diff --git a/README.md b/README.md new file mode 100644 index 000000000..36252a56d --- /dev/null +++ b/README.md @@ -0,0 +1,43 @@ +## How to build my own image? ## + +**Preparation** + +- x86 machine running any OS, 4G ram, SSD, quad core (recommended), +- [virtual box](https://www.virtualbox.org/wiki/Downloads) or similar virtualization software, **(highly recommended)** +- host system is **highly recommended** to be [Ubuntu 14.04](http://archive.ubuntu.com/ubuntu/dists/trusty-updates/main/installer-amd64/current/images/netboot/mini.iso) (**some but not all** sources can also compile on Ubuntu 15.04, Mint 17.2 and Debian Jessie), +- installed basic system, OpenSSH and Samba (optional), +- root access. + +**Execution** + + apt-get -y install git + git clone https://github.com/igorpecovnik/lib --depth 1 + cp lib/compile.sh . + chmod +x compile.sh + ./compile.sh + +This will download all necessary sources, execute compilation and build an bootable image. Most of things will be cached so next run will be extremly faster! + +## How to build my own kernel? ## + +**Prerequisition are the same as building an image!** + +Edit *compile.sh* prior to running and alter switch: + + KERNEL_ONLY="yes" + +In directory (output/debs) you will find deb packed kernel, together with headers, firmware and u-boot. + +If you are doing changes to kernel source, disable GIT lock with: + + FORCE_CHECKOUT="no" + +If you want to invoke menu configuration: + + KERNEL_CONFIGURE="yes" + +More info: + +- [Documentation](http://www.armbian.com/using-armbian-tools/) +- [Support forums](http://forum.armbian.com/ "Armbian support forum") +- [Project at Github](https://github.com/igorpecovnik/lib) \ No newline at end of file diff --git a/bin/NumixHolo.zip b/bin/NumixHolo.zip new file mode 100644 index 000000000..410775f71 Binary files /dev/null and b/bin/NumixHolo.zip differ diff --git a/bin/armbian.bmp b/bin/armbian.bmp new file mode 100644 index 000000000..df9118520 Binary files /dev/null and b/bin/armbian.bmp differ diff --git a/bin/armbian.key b/bin/armbian.key new file mode 100644 index 000000000..c5b7a796b --- /dev/null +++ b/bin/armbian.key @@ -0,0 +1,52 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQINBFUG8p4BEADGlseGFmdjjfmoXtHpZxqgYHGweCnGZ05LiGgEVgbv5SrTsJsy +O8H8RyBPxgbpKEY+JCV1IlYQPaE3Til1+kqmR4XNKbufjEuqAV4VJW3267tYRuJ3 +08E70q7kpQSsEAWLVY+xV/l5stAupp4/wF5BPdAjW7gLuicPnqoKK0jcfrjuvd45 +WFhpjL1Sdd0PnILehz0to6R2H9MsW+VYYPFztdjBM/78UD8grMcCm/7Mz8ENRKCn +TKrgj4bpWA0kPEHNBfaoQQUk5fCJYNMLvLMIGZcWeGOPo+yFnl4C6qTEgs0g7/0E +56ycaQDJ+gBCH9YNa8j3eH/t1vMN0ERXiOQf6WXgRihOD1fcnZFmczQFT3GGhv3y ++/cUpsUlmhhJ6tetiuXNuTfrl3M+99qUq5/8iiq292MCmn5s0BEOiyfQ2l2uZmjy +DUO+4lL9o3MX0W5Xp1puE2p42b+w458aDKuuFvBzVMiU51Js6DZnahxu2s+NDztD +gut7p+P60UBCbltXEB0ZIyWTAkKCwIlapZ9yDiHqXiNluTdBiFWGyU3xlb4fuQzw +lwvmS3yz4Ak5GCdDpiLmJoHOKV6q85VaI4T3gixx4JwEfdincOGfepSWFmbEsDuV +x5vbDV5Dwb3oAg80zp3W/uNyX7G41uIGDNzZL82p2XtgGzkjhEbKAnNavwARAQAB +tD1JZ29yIFBlY292bmlrIChManVibGphbmEsIFNsb3ZlbmlhKSA8aWdvci5wZWNv +dm5pa0BnbWFpbC5jb20+iQI4BBMBAgAiBQJVBvKeAhsDBgsJCAcDAgYVCAIJCgsE +FgIDAQIeAQIXgAAKCRCT1oifnw541T6WD/0X+LD9Gm1NVgZhrH35oQ3zstENrTjD +6LF+kT+zhe6QR9bAdOmeb7Je423y/UY3nSaJlS/OWsJs89tXUyE2jbxtLApN6OMT +ZsIxjgyg3fjbHV/lw/xGp+cqHjX+Ay5QZudJVxGJN7WJaRGxymjop7EX4CHiidGZ +PZoDT23WArLia7E8MLB/oK3wW6k9Qlc2SrhldzpuSmOwHQX9pxmy9dgfZa2a9w1c +EvktDnrizPmfxwYaC38FKRqz1I8CnPMESVJ+6mLEYxWJvJANuVvrhqOtjkY6yI0u +SOFHsmgci+3X2c7WWhloKub/Pf7TtM6tl6RCHfKvnsrTZPvxP1/CgzQiAITWppBl +olnSRHXp3notCF1rVbgInwVuCZCuWPJvHC6R3t9/UgESao0tEwr4mw7jNwtszWou +4rYzjEAME/O/kBBWPbDURm/4R8l0XSnG0zhePKv5iCzeQbIzUeAD1Dcvk7falgnl +9FX9/LZCY1kEwFMf2DG03lwG7c4ICSVAz0pNEPZdqpyCl82VKkDne8PA0Rb/uPIO +QY3aDu8bgcPQuokmRRL4rwdnRCVr0AFDZhVQnUjcdy8AvEPeye2fNdLhte+KUWiy +FNWp2vW2LbJ9GxPstaFihXZBcCEpGWsNHebDd1KmNGyPKcqzaIfzHPLP8+ee2deK +A95PVzV3iTL+ObkCDQRVBvKeARAAvGaKCHDGl0eC7fFok5sPq1WattpqQ9QL0BgZ +95VQLn+7/1nXmKsDfCwCvnBGqLXzPQyvWhCbCTN9oYkqokBX2Ch1zOIABynw+UCM ++KyZcmciYZIF21OstWMM0nQ06jno5Hq1vSHlgTkaaYWZYoqXocMCS9llvI2NVG34 +bcak1hAh9EkfmThVttDeGZP+osqt2mefpCAVITP1eQWU3RUBpOKNpthpLxMhy+l7 +m8tmkLH3FuqwZvVjY241w1o4AWVpJD/JdOuAfHtf7/UDPchSZLe9Ea8Y+bnkiZxg +SROtFrRzbVwP1Id4RKT44BwKMrXu8GiZAPvQq5CvINqZDMqiqq4+jFJPMVortuxX +skRh1dVYOioH1muzeHf560/BLW+mBuEd+xE0gd6SXRgPiflROylpJCb9Qxi8Ofq6 +FEHBfJ8mHz49d60qyXZNdNlxLhA3dfOvaahFBgXwNSwjak0zf6RpufAkh8Si5jc3 +Qh7lpuwsBelyNu7tBbL2y8WnUez/+aeX9sBSqs78mfpDdLAGnIlT9YcjkHl5W385 +jjhBAhpAgiLIsdSRKcc2CI34Vf775cLLIYrcBrjVMLYBwEiZHOPO90Lnizgx1l5t +1wG2Aa5OarTTUPIgMiTUtKPQ8BmcjGMZiavdJwqGUziDD+hMKcxPUMjyYiu+ngkH +1ROuCxMAEQEAAYkCHwQYAQIACQUCVQbyngIbDAAKCRCT1oifnw541Wm7D/sG0ouM +71c5mT+egff+QxfExy+JB4/vL1pLSHbMR8AtAJLN+Yh6EzeGmW2tga0Bk9AxEekQ +raXrMFhZSpT98qJnnDpdozfeIAyTwziw9K9opB0dU/+M3sVidkJ5mv4LW6CJaaY3 +rsom0TIjaxBvXqSeadJF4WGUHzg3ew+8ah0ZG8SDZu19ketN2cnTMAtgO+53Epjq +pk3uMF5hNaEHt9wVj2tq/anLEsl4T5U/ekQndxcTEsV2KIVSoye35ye4aam1gWhW +9JIFtShhEtXD/5Ovtj706YLTP84U8yHStzM6LLGpqM8bb1QsBUWRUhIKidltmO9K +jX6rJZuhwkcVJJYRdbetEXbiSIyeNZy7bBe4En+fVcN0ekBD36LhMcVL8F1Mntr1 +L5xf0cFEpFpEodQUvcayNgpI2y7EIPjKmKhVwW5dx36Q0CsCnwcC+Kg6BNzliI9I +s+oA2AVIanFPvjvSwfG9pH+2/u+KB4HT2Ux1FBbBi5GAwo+cu1d4XAc5bZHdPnAV +tnIN9dKRusZ8IGHWEd8Pw0kRepuNhSmSNALQkS6B+ppQZtmoGsBCqJeMPxQxj+yI +/bL3dmA2UXxnGJ3vs2ybFyHG3aoovKJfWVytxOJfG7qj1ACrOYOXekWlcw5lEiYF +cckukNqqFv/CXh+BZFlQT4DDvJlY0/KQFFKogQ== +=I/P8 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/bin/armbian01.jpg b/bin/armbian01.jpg new file mode 100644 index 000000000..aa2ac6655 Binary files /dev/null and b/bin/armbian01.jpg differ diff --git a/bin/armbian02.jpg b/bin/armbian02.jpg new file mode 100644 index 000000000..07e750428 Binary files /dev/null and b/bin/armbian02.jpg differ diff --git a/bin/hostapd23.tgz b/bin/hostapd23.tgz deleted file mode 100644 index d63ef90c5..000000000 Binary files a/bin/hostapd23.tgz and /dev/null differ diff --git a/bin/hostapd24.tgz b/bin/hostapd24.tgz deleted file mode 100644 index 79aab4477..000000000 Binary files a/bin/hostapd24.tgz and /dev/null differ diff --git a/bin/hostapd25-rt.tgz b/bin/hostapd25-rt.tgz new file mode 100644 index 000000000..9b6c81813 Binary files /dev/null and b/bin/hostapd25-rt.tgz differ diff --git a/bin/hostapd25.tgz b/bin/hostapd25.tgz new file mode 100644 index 000000000..cda9cec1a Binary files /dev/null and b/bin/hostapd25.tgz differ diff --git a/bin/jessie-desktop.tgz b/bin/jessie-desktop.tgz new file mode 100644 index 000000000..611fa95a7 Binary files /dev/null and b/bin/jessie-desktop.tgz differ diff --git a/bin/linux-firmware.zip b/bin/linux-firmware.zip index 6b2b288e0..3efcebadf 100644 Binary files a/bin/linux-firmware.zip and b/bin/linux-firmware.zip differ diff --git a/bin/m4startup.fw b/bin/m4startup.fw new file mode 100644 index 000000000..04881bbf5 Binary files /dev/null and b/bin/m4startup.fw differ diff --git a/bin/m4startup.fw.fast b/bin/m4startup.fw.fast new file mode 100644 index 000000000..101f1c90a Binary files /dev/null and b/bin/m4startup.fw.fast differ diff --git a/bin/m4startup.fw.origin b/bin/m4startup.fw.origin new file mode 100644 index 000000000..04881bbf5 Binary files /dev/null and b/bin/m4startup.fw.origin differ diff --git a/bin/nand1-allwinner.tgz b/bin/nand1-allwinner.tgz deleted file mode 100644 index 8f111bbba..000000000 Binary files a/bin/nand1-allwinner.tgz and /dev/null differ diff --git a/bin/nand1-cubietruck-debian-boot.tgz b/bin/nand1-cubietruck-debian-boot.tgz deleted file mode 100644 index bbdb571cb..000000000 Binary files a/bin/nand1-cubietruck-debian-boot.tgz and /dev/null differ diff --git a/bin/s500-bootloader.bin b/bin/s500-bootloader.bin new file mode 100644 index 000000000..edb532606 Binary files /dev/null and b/bin/s500-bootloader.bin differ diff --git a/bin/sunxitools.tgz b/bin/sunxitools.tgz new file mode 100644 index 000000000..699ec38e9 Binary files /dev/null and b/bin/sunxitools.tgz differ diff --git a/bin/swconfig.tgz b/bin/swconfig.tgz new file mode 100644 index 000000000..39454af6a Binary files /dev/null and b/bin/swconfig.tgz differ diff --git a/bin/trusty-desktop.tgz b/bin/trusty-desktop.tgz new file mode 100644 index 000000000..bbee8dd8b Binary files /dev/null and b/bin/trusty-desktop.tgz differ diff --git a/bin/vibrancy-colors_2.4-trusty-Noobslab.com_all.deb b/bin/vibrancy-colors_2.4-trusty-Noobslab.com_all.deb new file mode 100644 index 000000000..b55d9d662 Binary files /dev/null and b/bin/vibrancy-colors_2.4-trusty-Noobslab.com_all.deb differ diff --git a/bin/wheezy-desktop.tgz b/bin/wheezy-desktop.tgz new file mode 100644 index 000000000..d69e9517d Binary files /dev/null and b/bin/wheezy-desktop.tgz differ diff --git a/boards.config b/boards.config deleted file mode 100644 index 4278298dd..000000000 --- a/boards.config +++ /dev/null @@ -1,410 +0,0 @@ -#!/bin/bash -# -# Board definitions -# - -case $BOARD in - - -cubieboard4) -#-------------------------------------------------------------------------------------------------------------------------------- -# Cubieboards 3.4.x -#-------------------------------------------------------------------------------------------------------------------------------- -BOOTLOADER="https://github.com/patrickhwood/u-boot" -BOOTSOURCE="u-boot-patwood" -BOOTCONFIG="cubietruck" -CPUMIN="480000" -CPUMAX="1010000" -LINUXKERNEL="https://github.com/cubieboard/CC-A80-kernel-source" -LINUXSOURCE="linux-sunxi-a80" -LOCALVERSION="-sun9i" -FIRMWARE="" -DTBS="" -DOCS="" -DOCSDIR="" -MISC1="" -MISC1_DIR="" -MISC2="" -MISC2_DIR="" -MISC3="" -MISC3_DIR="" -MISC4="" -MISC4_DIR="" -;; -#-------------------------------------------------------------------------------------------------------------------------------- - - -cubieboard2 | cubietruck) -#-------------------------------------------------------------------------------------------------------------------------------- -# Cubieboards 3.4.x -#-------------------------------------------------------------------------------------------------------------------------------- -BOOTLOADER="https://github.com/patrickhwood/u-boot" -BOOTSOURCE="u-boot-patwood" -BOOTCONFIG="cubietruck" -CPUMIN="480000" -CPUMAX="1010000" -LINUXKERNEL="https://github.com/dan-and/linux-sunxi" -LINUXSOURCE="linux-sunxi" -LOCALVERSION="-sunxi" -FIRMWARE="bin/ap6210.zip" -DTBS="" -DOCS="https://github.com/igorpecovnik/Cubietruck-Debian.wiki.git" -DOCSDIR="docs-banana" -MISC1="https://github.com/linux-sunxi/sunxi-tools.git" -MISC1_DIR="sunxi-tools" -MISC2="https://github.com/matzrh/sunxi-lirc" -MISC2_DIR="sunxi-lirc" -MISC3="https://github.com/dz0ny/rt8192cu" -MISC3_DIR="rt8192cu" -MISC4="https://github.com/notro/fbtft" -MISC4_DIR="$LINUXSOURCE/drivers/video/fbtft" -;; -#-------------------------------------------------------------------------------------------------------------------------------- - - -cubieboard-next) -#-------------------------------------------------------------------------------------------------------------------------------- -# Cubieboard mainline kernel / experimental -#-------------------------------------------------------------------------------------------------------------------------------- -BOOTLOADER="https://github.com/RobertCNelson/u-boot" -BOOTSOURCE="u-boot" -BOOTCONFIG="Cubieboard_defconfig" -CPUMIN="480000" -CPUMAX="1010000" -LINUXKERNEL="https://github.com/linux-sunxi/linux-sunxi -b sunxi-next" -LINUXSOURCE="linux-sunxi-next" -LOCALVERSION="-sunxi" -DTBS="sun4i-a10-cubieboard.dtb" -DOCS="https://github.com/igorpecovnik/Cubietruck-Debian.wiki.git" -DOCSDIR="docs-banana" -MISC1="https://github.com/linux-sunxi/sunxi-tools.git" -MISC1_DIR="sunxi-tools" -MISC2="" -MISC2_DIR="" -MISC3="" -MISC3_DIR="" -MISC4="https://github.com/notro/fbtft" -MISC4_DIR="$LINUXSOURCE/drivers/video/fbtft" -;; - - -cubieboard2-next) -#-------------------------------------------------------------------------------------------------------------------------------- -# Cubieboard mainline kernel / experimental -#-------------------------------------------------------------------------------------------------------------------------------- -BOOTLOADER="https://github.com/RobertCNelson/u-boot" -BOOTSOURCE="u-boot" -BOOTCONFIG="Cubieboard2_defconfig" -CPUMIN="480000" -CPUMAX="1010000" -LINUXKERNEL="https://github.com/linux-sunxi/linux-sunxi -b sunxi-next" -LINUXSOURCE="linux-sunxi-next" -LOCALVERSION="-sunxi" -DTBS="sun7i-a20-cubieboard2.dtb" -DOCS="https://github.com/igorpecovnik/Cubietruck-Debian.wiki.git" -DOCSDIR="docs-banana" -MISC1="https://github.com/linux-sunxi/sunxi-tools.git" -MISC1_DIR="sunxi-tools" -MISC2="" -MISC2_DIR="" -MISC3="" -MISC3_DIR="" -MISC4="https://github.com/notro/fbtft" -MISC4_DIR="$LINUXSOURCE/drivers/video/fbtft" -;; - - -cubietruck-next) -#-------------------------------------------------------------------------------------------------------------------------------- -# Cubieboard mainline kernel / experimental -#-------------------------------------------------------------------------------------------------------------------------------- -BOOTLOADER="https://github.com/RobertCNelson/u-boot" -BOOTSOURCE="u-boot" -BOOTCONFIG="Cubietruck_defconfig" -CPUMIN="480000" -CPUMAX="1010000" -LINUXKERNEL="https://github.com/linux-sunxi/linux-sunxi -b sunxi-next" -LINUXSOURCE="linux-sunxi-next" -LOCALVERSION="-sunxi" -DTBS="sun7i-a20-cubietruck.dtb" -DOCS="https://github.com/igorpecovnik/Cubietruck-Debian.wiki.git" -DOCSDIR="docs-banana" -MISC1="https://github.com/linux-sunxi/sunxi-tools.git" -MISC1_DIR="sunxi-tools" -MISC2="" -MISC2_DIR="" -MISC3="" -MISC3_DIR="" -MISC4="https://github.com/notro/fbtft" -MISC4_DIR="$LINUXSOURCE/drivers/video/fbtft" -;; - - -lime-next) -#-------------------------------------------------------------------------------------------------------------------------------- -# Olimex Lime mainline kernel / experimental -#-------------------------------------------------------------------------------------------------------------------------------- -BOOTLOADER="https://github.com/RobertCNelson/u-boot" -BOOTSOURCE="u-boot" -BOOTCONFIG="A20-OLinuXino-Lime_defconfig" -CPUMIN="480000" -CPUMAX="1010000" -LINUXKERNEL="https://github.com/linux-sunxi/linux-sunxi -b sunxi-next" -LINUXSOURCE="linux-sunxi-next" -LOCALVERSION="-sunxi" -DTBS="sun7i-a20-olinuxino-lime.dtb" -DOCS="https://github.com/igorpecovnik/Cubietruck-Debian.wiki.git" -DOCSDIR="docs-banana" -MISC1="https://github.com/linux-sunxi/sunxi-tools.git" -MISC1_DIR="sunxi-tools" -MISC2="" -MISC2_DIR="" -MISC3="https://github.com/pvaret/rtl8192cu-fixes" -MISC3_DIR="rtl8192cu-fixes" -MISC4="https://github.com/notro/fbtft" -MISC4_DIR="$LINUXSOURCE/drivers/video/fbtft" -;; - - -micro-next) -#-------------------------------------------------------------------------------------------------------------------------------- -# Olimex Lime mainline kernel / experimental -#-------------------------------------------------------------------------------------------------------------------------------- -BOOTLOADER="https://github.com/RobertCNelson/u-boot" -BOOTSOURCE="u-boot" -BOOTCONFIG="A20-OLinuXino_MICRO_config" -CPUMIN="480000" -CPUMAX="1010000" -LINUXKERNEL="https://github.com/linux-sunxi/linux-sunxi -b sunxi-next" -LINUXSOURCE="linux-sunxi-next" -LOCALVERSION="-sunxi" -DTBS="sun7i-a20-olinuxino-micro.dtb" -DOCS="https://github.com/igorpecovnik/Cubietruck-Debian.wiki.git" -DOCSDIR="docs-banana" -MISC1="https://github.com/linux-sunxi/sunxi-tools.git" -MISC1_DIR="sunxi-tools" -MISC2="" -MISC2_DIR="" -MISC3="https://github.com/pvaret/rtl8192cu-fixes" -MISC3_DIR="rtl8192cu-fixes" -MISC4="https://github.com/notro/fbtft" -MISC4_DIR="$LINUXSOURCE/drivers/video/fbtft" -;; - - -lime2-next) -#-------------------------------------------------------------------------------------------------------------------------------- -# Olimex Lime mainline kernel / experimental -#-------------------------------------------------------------------------------------------------------------------------------- -BOOTLOADER="https://github.com/RobertCNelson/u-boot" -BOOTSOURCE="u-boot" -BOOTCONFIG="A20-OLinuXino-Lime2_defconfig" -CPUMIN="480000" -CPUMAX="1010000" -LINUXKERNEL="https://github.com/linux-sunxi/linux-sunxi -b sunxi-next" -LINUXSOURCE="linux-sunxi-next" -LOCALVERSION="-sunxi" -DTBS="sun7i-a20-olinuxino-lime2.dtb" -DOCS="https://github.com/igorpecovnik/Cubietruck-Debian.wiki.git" -DOCSDIR="docs-banana" -MISC1="https://github.com/linux-sunxi/sunxi-tools.git" -MISC1_DIR="sunxi-tools" -MISC2="" -MISC2_DIR="" -MISC3="" -MISC3_DIR="" -MISC4="https://github.com/notro/fbtft" -MISC4_DIR="$LINUXSOURCE/drivers/video/fbtft" -;; - - -pcduino3-next) -#-------------------------------------------------------------------------------------------------------------------------------- -# pcduino3 mainline kernel / experimental -#-------------------------------------------------------------------------------------------------------------------------------- -BOOTLOADER="https://github.com/RobertCNelson/u-boot" -BOOTSOURCE="u-boot" -BOOTCONFIG="Linksprite_pcDuino3_defconfig" -CPUMIN="480000" -CPUMAX="1010000" -LINUXKERNEL="https://github.com/linux-sunxi/linux-sunxi -b sunxi-next" -LINUXSOURCE="linux-sunxi-next" -LOCALVERSION="-sunxi" -DTBS="sun7i-a20-pcduino3.dtb" -DOCS="https://github.com/igorpecovnik/Cubietruck-Debian.wiki.git" -DOCSDIR="docs-banana" -MISC1="https://github.com/linux-sunxi/sunxi-tools.git" -MISC1_DIR="sunxi-tools" -MISC2="" -MISC2_DIR="" -MISC3="" -MISC3_DIR="" -MISC4="https://github.com/notro/fbtft" -MISC4_DIR="$LINUXSOURCE/drivers/video/fbtft" -;; - - -bananapi-next) -#-------------------------------------------------------------------------------------------------------------------------------- -# bananapi mainline kernel / experimental -#-------------------------------------------------------------------------------------------------------------------------------- -BOOTLOADER="https://github.com/RobertCNelson/u-boot" -BOOTSOURCE="u-boot" -BOOTCONFIG="BananaPi_defconfig" -CPUMIN="480000" -CPUMAX="1010000" -LINUXKERNEL="https://github.com/linux-sunxi/linux-sunxi -b sunxi-next" -LINUXSOURCE="linux-sunxi-next" -LOCALVERSION="-sunxi" -DTBS="sun7i-a20-bananapi.dtb" -DOCS="https://github.com/igorpecovnik/Cubietruck-Debian.wiki.git" -DOCSDIR="docs-banana" -MISC1="https://github.com/linux-sunxi/sunxi-tools.git" -MISC1_DIR="sunxi-tools" -MISC2="" -MISC2_DIR="" -MISC3="" -MISC3_DIR="" -MISC4="https://github.com/notro/fbtft" -MISC4_DIR="$LINUXSOURCE/drivers/video/fbtft" -;; - - -bananapi) -#-------------------------------------------------------------------------------------------------------------------------------- -# Bananapi cubieboard based 3.4.x -#-------------------------------------------------------------------------------------------------------------------------------- -BOOTLOADER="https://github.com/LeMaker/u-boot-bananapi" -BOOTSOURCE="u-boot-banana" -BOOTCONFIG="BananaPi_config" -CPUMIN="480000" -CPUMAX="1010000" -LINUXKERNEL="https://github.com/dan-and/linux-sunxi" -LINUXSOURCE="linux-sunxi" -LOCALVERSION="-sunxi" -FIRMWARE="bin/ap6210.zip" -DTBS="" -DOCS="" -DOCSDIR="" -MISC1="https://github.com/linux-sunxi/sunxi-tools.git" -MISC1_DIR="sunxi-tools" -MISC2="" -MISC2_DIR="" -MISC3="https://github.com/dz0ny/rt8192cu" -MISC3_DIR="rt8192cu" -MISC4="https://github.com/notro/fbtft" -MISC4_DIR="$LINUXSOURCE/drivers/video/fbtft" -;; - - -cubox-i) -#-------------------------------------------------------------------------------------------------------------------------------- -# cubox-i & hummingboard 3.14.xx -#-------------------------------------------------------------------------------------------------------------------------------- -BOOTLOADER="https://github.com/SolidRun/u-boot-imx6" -BOOTSOURCE="u-boot-cubox" -BOOTCONFIG="mx6_cubox-i_config" -CPUMIN="792000" -CPUMAX="996000" -LINUXKERNEL="https://github.com/linux4kix/linux-linaro-stable-mx6" -LINUXSOURCE="linux-cubox-next" -LOCALVERSION="-cubox" -DTBS="imx6q-cubox-i.dtb imx6dl-cubox-i.dtb imx6dl-hummingboard.dtb imx6q-hummingboard.dtb" -DOCS="https://github.com/igorpecovnik/Cubietruck-Debian.wiki.git" -DOCSDIR="docs-cubox" -MISC1="" -MISC1_DIR="" -MISC2="" -MISC2_DIR="" -MISC3="https://github.com/dz0ny/rt8192cu" -MISC3_DIR="rt8192cu" -MISC4="https://github.com/notro/fbtft" -MISC4_DIR="$LINUXSOURCE/drivers/video/fbtft" -;; - - -lime) -#-------------------------------------------------------------------------------------------------------------------------------- -# Olimex Lime 512Mb 3.4.x -#-------------------------------------------------------------------------------------------------------------------------------- -BOOTLOADER="https://github.com/linux-sunxi/u-boot-sunxi" -BOOTSOURCE="u-boot-sunxi" -BOOTCONFIG="A20-OLinuXino-Lime_config" -CPUMIN="480000" -CPUMAX="1010000" -LINUXKERNEL="https://github.com/dan-and/linux-sunxi" -LINUXSOURCE="linux-sunxi" -LOCALVERSION="-sunxi" -FIRMWARE="bin/ap6210.zip" -DTBS="" -DOCS="https://github.com/igorpecovnik/Cubietruck-Debian.wiki.git" -DOCSDIR="docs-banana" -MISC1="https://github.com/linux-sunxi/sunxi-tools.git" -MISC1_DIR="sunxi-tools" -MISC2="https://github.com/matzrh/sunxi-lirc" -MISC2_DIR="sunxi-lirc" -MISC3="https://github.com/dz0ny/rt8192cu" -MISC3_DIR="rt8192cu" -MISC4="https://github.com/notro/fbtft" -MISC4_DIR="$LINUXSOURCE/drivers/video/fbtft" -;; - - -micro) -#-------------------------------------------------------------------------------------------------------------------------------- -# Olimex Micro 3.4.x -#-------------------------------------------------------------------------------------------------------------------------------- -BOOTLOADER="https://github.com/linux-sunxi/u-boot-sunxi" -BOOTSOURCE="u-boot-sunxi" -BOOTCONFIG="A20-OLinuXino-Micro_config" -CPUMIN="480000" -CPUMAX="1010000" -LINUXKERNEL="https://github.com/dan-and/linux-sunxi" -LINUXSOURCE="linux-sunxi" -LOCALVERSION="-sunxi" -FIRMWARE="bin/ap6210.zip" -DTBS="" -DOCS="https://github.com/igorpecovnik/Cubietruck-Debian.wiki.git" -DOCSDIR="docs-banana" -MISC1="https://github.com/linux-sunxi/sunxi-tools.git" -MISC1_DIR="sunxi-tools" -MISC2="https://github.com/matzrh/sunxi-lirc" -MISC2_DIR="sunxi-lirc" -MISC3="https://github.com/dz0ny/rt8192cu" -MISC3_DIR="rt8192cu" -MISC4="https://github.com/notro/fbtft" -MISC4_DIR="$LINUXSOURCE/drivers/video/fbtft" -;; - - -lime2) -#-------------------------------------------------------------------------------------------------------------------------------- -# Olimex Lime2 1024Mb 3.4.x -#-------------------------------------------------------------------------------------------------------------------------------- -BOOTLOADER="https://github.com/linux-sunxi/u-boot-sunxi" -BOOTSOURCE="u-boot-sunxi" -BOOTCONFIG="A20-OLinuXino_Lime2_config" -CPUMIN="480000" -CPUMAX="1010000" -LINUXKERNEL="https://github.com/dan-and/linux-sunxi" -LINUXSOURCE="linux-sunxi" -LOCALVERSION="-sunxi" -FIRMWARE="bin/ap6210.zip" -DTBS="" -DOCS="https://github.com/igorpecovnik/Cubietruck-Debian.wiki.git" -DOCSDIR="docs-banana" -MISC1="https://github.com/linux-sunxi/sunxi-tools.git" -MISC1_DIR="sunxi-tools" -MISC2="https://github.com/matzrh/sunxi-lirc" -MISC2_DIR="sunxi-lirc" -MISC3="https://github.com/dz0ny/rt8192cu" -MISC3_DIR="rt8192cu" -MISC4="https://github.com/notro/fbtft" -MISC4_DIR="$LINUXSOURCE/drivers/video/fbtft" -;; - - -*) echo "Board configuration not found" -exit -;; -esac diff --git a/boards.sh b/boards.sh new file mode 100644 index 000000000..14ed7b75c --- /dev/null +++ b/boards.sh @@ -0,0 +1,275 @@ +#!/bin/bash +# +# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com +# +# This file is licensed under the terms of the GNU General Public +# License version 2. This program is licensed "as is" without any +# warranty of any kind, whether express or implied. +# +# This file is a part of tool chain https://github.com/igorpecovnik/lib +# +# +# Board speciefic +# +# + +install_board_specific (){ +#--------------------------------------------------------------------------------------------------------------------------------- +# Install board common and specific applications +#--------------------------------------------------------------------------------------------------------------------------------- + + # Allwinner's + if [[ $LINUXFAMILY == sun* ]] ; then + + # default lirc configuration + sed -i '1i sed -i \x27s/DEVICE="\\/dev\\/input.*/DEVICE="\\/dev\\/input\\/\x27$str\x27"/g\x27 /etc/lirc/hardware.conf' \ + $DEST/cache/sdcard/etc/lirc/hardware.conf + sed -i '1i str=$(cat /proc/bus/input/devices | grep "H: Handlers=sysrq rfkill kbd event" | awk \x27{print $(NF)}\x27)' \ + $DEST/cache/sdcard/etc/lirc/hardware.conf + sed -i '1i # Cubietruck automatic lirc device detection by Igor Pecovnik' $DEST/cache/sdcard/etc/lirc/hardware.conf + sed -e 's/DEVICE=""/DEVICE="\/dev\/input\/event1"/g' -i $DEST/cache/sdcard/etc/lirc/hardware.conf + sed -e 's/DRIVER="UNCONFIGURED"/DRIVER="devinput"/g' -i $DEST/cache/sdcard/etc/lirc/hardware.conf + cp $SRC/lib/config/lirc.conf.cubietruck $DEST/cache/sdcard/etc/lirc/lircd.conf + + fi + + + # Lemaker Guitar + if [[ $BOARD == "guitar" ]] ; then + + if [ -f $DEST/cache/sdcard/etc/inittab ]; then sed -e "s/ttyS0/ttyS3/g" -i $DEST/cache/sdcard/etc/inittab; fi + if [ -f $DEST/cache/sdcard/etc/init/ttyS0.conf ]; then + mv $DEST/cache/sdcard/etc/init/ttyS0.conf $DEST/cache/sdcard/etc/init/ttyS3.conf; + sed -e "s/ttyS0/ttyS3/g" -i $DEST/cache/sdcard/etc/init/ttyS3.conf; + fi + if [ -f $DEST/cache/sdcard/etc/systemd/system/getty.target.wants/serial-getty@ttyS0.service ]; then + mv $DEST/cache/sdcard/etc/systemd/system/getty.target.wants/serial-getty@ttyS0.service \ + $DEST/cache/sdcard/etc/systemd/system/getty.target.wants/serial-getty@ttyS3.service + fi + chroot $DEST/cache/sdcard /bin/bash -c "apt-get -y -qq autoremove >/dev/null 2>&1" + echo "blacklist wlan_8723bs_vq0" > $DEST/cache/sdcard/etc/modprobe.d/blacklist-guitar.conf + echo "blacklist ctp_gslX680" >> $DEST/cache/sdcard/etc/modprobe.d/blacklist-guitar.conf + echo "blacklist ctp_gsl3680" >> $DEST/cache/sdcard/etc/modprobe.d/blacklist-guitar.conf + echo "blacklist gsensor_mir3da" >> $DEST/cache/sdcard/etc/modprobe.d/blacklist-guitar.conf + echo "blacklist gsensor_stk8313" >> $DEST/cache/sdcard/etc/modprobe.d/blacklist-guitar.conf + echo "blacklist gsensor_bma222" >> $DEST/cache/sdcard/etc/modprobe.d/blacklist-guitar.conf + echo "blacklist lightsensor_ltr301" >> $DEST/cache/sdcard/etc/modprobe.d/blacklist-guitar.conf + + fi + + + # Udoo + if [[ $BOARD == "udoo" ]] ; then + + if [ -f $DEST/cache/sdcard/etc/inittab ]; then sed -e "s/ttyS0/ttymxc1/g" -i $DEST/cache/sdcard/etc/inittab; fi + if [ -f $DEST/cache/sdcard/etc/init/ttyS0.conf ]; then + mv $DEST/cache/sdcard/etc/init/ttyS0.conf $DEST/cache/sdcard/etc/init/ttymxc1.conf; + sed -e "s/ttyS0/ttymxc1/g" -i $DEST/cache/sdcard/etc/init/ttymxc1.conf; + fi + if [ -f $DEST/cache/sdcard/etc/systemd/system/getty.target.wants/serial-getty@ttyS0.service ]; then + mv $DEST/cache/sdcard/etc/systemd/system/getty.target.wants/serial-getty@ttyS0.service \ + $DEST/cache/sdcard/etc/systemd/system/getty.target.wants/serial-getty@ttymxc1.service + fi + chroot $DEST/cache/sdcard /bin/bash -c "apt-get -y -qq remove lirc >/dev/null 2>&1" + chroot $DEST/cache/sdcard /bin/bash -c "apt-get -y -qq autoremove >/dev/null 2>&1" + sed 's/wlan0/wlan2/' -i $DEST/cache/sdcard/etc/network/interfaces.default + sed 's/wlan0/wlan2/' -i $DEST/cache/sdcard/etc/network/interfaces.bonding + sed 's/wlan0/wlan2/' -i $DEST/cache/sdcard/etc/network/interfaces.hostapd + # Udoo doesn't have interactive + sed -e 's/interactive/ondemand/g' -i $DEST/cache/sdcard/etc/init.d/cpufrequtils + + fi + + + # Udoo neo + if [[ $BOARD == "udoo-neo" ]] ; then + + if [ -f $DEST/cache/sdcard/etc/inittab ]; then sed -e "s/ttyS0/ttymxc0/g" -i $DEST/cache/sdcard/etc/inittab; fi + if [ -f $DEST/cache/sdcard/etc/init/ttyS0.conf ]; then + mv $DEST/cache/sdcard/etc/init/ttyS0.conf $DEST/cache/sdcard/etc/init/ttymxc0.conf + sed -e "s/ttyS0/ttymxc0/g" -i $DEST/cache/sdcard/etc/init/ttymxc0.conf + fi + if [ -f $DEST/cache/sdcard/etc/systemd/system/getty.target.wants/serial-getty@ttyS0.service ]; then + mv $DEST/cache/sdcard/etc/systemd/system/getty.target.wants/serial-getty@ttyS0.service \ + $DEST/cache/sdcard/etc/systemd/system/getty.target.wants/serial-getty@ttymxc0.service + fi + chroot $DEST/cache/sdcard /bin/bash -c "apt-get -y -qq remove lirc && apt-get -y -qq autoremove" + sed 's/wlan0/wlan2/' -i $DEST/cache/sdcard/etc/network/interfaces.default + sed 's/wlan0/wlan2/' -i $DEST/cache/sdcard/etc/network/interfaces.bonding + sed 's/wlan0/wlan2/' -i $DEST/cache/sdcard/etc/network/interfaces.hostapd + # SD card is elsewhere + sed 's/mmcblk0p1/mmcblk1p1/' -i $DEST/cache/sdcard/etc/fstab + # firmware for M4 + mkdir -p $DEST/cache/sdcard/boot/bin/ + cp $SRC/lib/bin/m4startup.fw* $DEST/cache/sdcard/boot/bin/ + + fi + + + # cubox / hummingboard + if [[ $BOARD == cubox-i* ]] ; then + + if [ -f $DEST/cache/sdcard/etc/inittab ]; then sed -e "s/ttyS0/ttymxc0/g" -i $DEST/cache/sdcard/etc/inittab; fi + if [ -f $DEST/cache/sdcard/etc/init/ttyS0.conf ]; then + mv $DEST/cache/sdcard/etc/init/ttyS0.conf $DEST/cache/sdcard/etc/init/ttymxc0.conf + sed -e "s/ttyS0/ttymxc0/g" -i $DEST/cache/sdcard/etc/init/ttymxc0.conf + fi + if [ -f $DEST/cache/sdcard/etc/systemd/system/getty.target.wants/serial-getty@ttyS0.service ]; then + mv $DEST/cache/sdcard/etc/systemd/system/getty.target.wants/serial-getty@ttyS0.service \ + $DEST/cache/sdcard/etc/systemd/system/getty.target.wants/serial-getty@ttymxc0.service + fi + + # default lirc configuration + sed -e 's/DEVICE=""/DEVICE="\/dev\/lirc0"/g' -i $DEST/cache/sdcard/etc/lirc/hardware.conf + sed -e 's/DRIVER="UNCONFIGURED"/DRIVER="default"/g' -i $DEST/cache/sdcard/etc/lirc/hardware.conf + cp $SRC/lib/config/lirc.conf.cubox-i $DEST/cache/sdcard/etc/lirc/lircd.conf + cp $SRC/lib/bin/brcm_patchram_plus_cubox $DEST/cache/sdcard/usr/local/bin/brcm_patchram_plus + chroot $DEST/cache/sdcard /bin/bash -c "chmod +x /usr/local/bin/brcm_patchram_plus" + cp $SRC/lib/scripts/brcm4330 $DEST/cache/sdcard/etc/default + cp $SRC/lib/scripts/brcm4330-patch $DEST/cache/sdcard/etc/init.d + chroot $DEST/cache/sdcard /bin/bash -c "chmod +x /etc/init.d/brcm4330-patch" + chroot $DEST/cache/sdcard /bin/bash -c "update-rc.d brcm4330-patch defaults>> /dev/null" + + fi + + # install custom root package + chroot $DEST/cache/sdcard /bin/bash -c "dpkg -i /tmp/$RELEASE/$CHOOSEN_ROOTFS.deb >/dev/null 2>&1" + + # enable first run script + chroot $DEST/cache/sdcard /bin/bash -c "update-rc.d firstrun defaults >/dev/null 2>&1" + + display_alert "Creating boot scripts" "$BOARD" "info" + + rm -rf $DEST/cache/sdcard/boot/dtb.old # remove .old on new image + + if [[ $BOARD == udoo* ]] ; then + cp $SRC/lib/config/boot-$BOARD.cmd $DEST/cache/sdcard/boot/boot.cmd + elif [[ $BOARD == cubox-i* ]]; then + cp $SRC/lib/config/boot-cubox.cmd $DEST/cache/sdcard/boot/boot.cmd + elif [[ $BOARD == guitar* ]]; then + cp $SRC/lib/config/boot-guitar.cmd $DEST/cache/sdcard/boot/boot.cmd + else + cp $SRC/lib/config/boot.cmd $DEST/cache/sdcard/boot/boot.cmd + # let's prepare for old kernel too + chroot $DEST/cache/sdcard /bin/bash -c \ + "ln -s /boot/bin/$BOARD.bin /boot/script.bin >/dev/null 2>&1 || cp /boot/bin/$BOARD.bin /boot/script.bin" + fi + + # if we have a special fat boot partition, alter rootfs= + if [ "$BOOTSIZE" -gt "0" ]; then + display_alert "Adjusting boot scripts" "$BOARD" "info" + sed -e 's/p1 /p2 /g' -i $DEST/cache/sdcard/boot/boot.cmd + echo "/dev/mmcblk0p1 /boot vfat defaults 0 0" >> $DEST/cache/sdcard/etc/fstab + fi + + # convert to uboot compatible script + mkimage -C none -A arm -T script -d $DEST/cache/sdcard/boot/boot.cmd $DEST/cache/sdcard/boot/boot.scr >> /dev/null +} + + +install_kernel (){ +#-------------------------------------------------------------------------------------------------------------------------------- +# Install kernel to prepared root file-system +#-------------------------------------------------------------------------------------------------------------------------------- + + display_alert "Install kernel" "$CHOOSEN_KERNEL" "info" + + # configure MIN / MAX speed for cpufrequtils + sed -e "s/MIN_SPEED=\"0\"/MIN_SPEED=\"$CPUMIN\"/g" -i $DEST/cache/sdcard/etc/init.d/cpufrequtils + sed -e "s/MAX_SPEED=\"0\"/MAX_SPEED=\"$CPUMAX\"/g" -i $DEST/cache/sdcard/etc/init.d/cpufrequtils + + # interactive currently available only on 3.4 + if [[ $BRANCH != *next* ]];then + sed -e 's/ondemand/interactive/g' -i $DEST/cache/sdcard/etc/init.d/cpufrequtils + fi + + # set hostname + echo $HOST > $DEST/cache/sdcard/etc/hostname + + # this is needed for ubuntu + rm $DEST/cache/sdcard/etc/resolv.conf + echo "nameserver 8.8.8.8" >> $DEST/cache/sdcard/etc/resolv.conf + + # set hostname in hosts file + echo "127.0.0.1 localhost $HOST" > $DEST/cache/sdcard/etc/hosts + echo "::1 localhost $HOST ip6-localhost ip6-loopback" >> $DEST/cache/sdcard/etc/hosts + echo "fe00::0 ip6-localnet" >> $DEST/cache/sdcard/etc/hosts + echo "ff00::0 ip6-mcastprefix" >> $DEST/cache/sdcard/etc/hosts + echo "ff02::1 ip6-allnodes" >> $DEST/cache/sdcard/etc/hosts + echo "ff02::2 ip6-allrouters" >> $DEST/cache/sdcard/etc/hosts + + # create modules file + IFS=" " + if [[ $BRANCH == *next* ]];then + for word in $MODULES_NEXT; do + echo $word >> $DEST/cache/sdcard/etc/modules; + done + else + for word in $MODULES; do + echo $word >> $DEST/cache/sdcard/etc/modules; + done + fi + + # copy and create symlink to default interfaces configuration + cp $SRC/lib/config/interfaces.* $DEST/cache/sdcard/etc/network/ + ln -sf interfaces.default $DEST/cache/sdcard/etc/network/interfaces + + # mount deb storage to tmp + mount --bind $DEST/debs/ $DEST/cache/sdcard/tmp + + # extract kernel version + VER=$(dpkg --info $DEST/debs/$CHOOSEN_KERNEL | grep Descr | awk '{print $(NF)}') + HEADERS_DIR="linux-headers-"$VER + VER="${VER/-$LINUXFAMILY/}" + + # we need package names for dtb, uboot and headers + UBOOT_TMP="${CHOOSEN_KERNEL/image/u-boot}" + DTB_TMP="${CHOOSEN_KERNEL/image/dtb}" + FW_TMP="${CHOOSEN_KERNEL/image/firmware-image}" + HEADERS_TMP="${CHOOSEN_KERNEL/image/headers}" + HEADERS_CACHE="${CHOOSEN_KERNEL/image/cache}" + + # install kernel + chroot $DEST/cache/sdcard /bin/bash -c "dpkg -i /tmp/$CHOOSEN_KERNEL >/dev/null 2>&1" + + # install uboot + display_alert "Install u-boot" "$UBOOT_TMP" "info" + chroot $DEST/cache/sdcard /bin/bash -c "dpkg -i /tmp/$UBOOT_TMP >/dev/null 2>&1" + + # install headers + display_alert "Install headers" "$HEADERS_TMP" "info" + chroot $DEST/cache/sdcard /bin/bash -c "dpkg -i /tmp/$HEADERS_TMP >/dev/null 2>&1" + + # install firmware + display_alert "Install firmware" "$FW_TMP" "info" + chroot $DEST/cache/sdcard /bin/bash -c "dpkg -i /tmp/$FW_TMP >/dev/null 2>&1" + + # install DTB + if [ -f $DEST/cache/sdcard/tmp/$DTB_TMP ]; then + display_alert "Install DTB" "$DTB_TMP" "info" + chroot $DEST/cache/sdcard /bin/bash -c "dpkg -i /tmp/$DTB_TMP >/dev/null 2>&1"; + fi + + # recompile headers scripts or use cache if exists + cd $DEST/cache/sdcard/usr/src/$HEADERS_DIR + + if [ ! -f $DEST/cache/building/$HEADERS_CACHE.tgz ]; then + chroot $DEST/cache/sdcard /bin/bash -c "cd /usr/src/$HEADERS_DIR && make headers_check; make headers_install ; make scripts" | dialog --progressbox "Compile kernel headers scripts ..." 20 70 + rm -rf $DEST/cache/building/repack + mkdir -p $DEST/cache/building -p $DEST/cache/building/repack/usr/src/$HEADERS_DIR -p $DEST/cache/building/repack/DEBIAN + dpkg-deb -x $DEST/debs/$HEADERS_TMP $DEST/cache/building/repack + dpkg-deb -e $DEST/debs/$HEADERS_TMP $DEST/cache/building/repack/DEBIAN + cp -R . $DEST/cache/building/repack/usr/src/$HEADERS_DIR + dpkg-deb -b $DEST/cache/building/repack $DEST/debs + rm -rf $DEST/cache/building/repack + tar czpf $DEST/cache/building/$HEADERS_CACHE".tgz" . + else + tar xzpf $DEST/cache/building/$HEADERS_CACHE".tgz" + fi + + # copy boot splash image + cp $SRC/lib/bin/armbian.bmp $DEST/cache/sdcard/boot/boot.bmp + + # add our linux firmwares to cache image + unzip -q $SRC/lib/bin/linux-firmware.zip -d $DEST/cache/sdcard/lib/firmware +} \ No newline at end of file diff --git a/build-all.sh b/build-all.sh new file mode 100644 index 000000000..3a1b93976 --- /dev/null +++ b/build-all.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# +# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com +# +# This file is licensed under the terms of the GNU General Public +# License version 2. This program is licensed "as is" without any +# warranty of any kind, whether express or implied. +# +# This file is a part of tool chain https://github.com/igorpecovnik/lib +# + +IFS=";" +START=0 +OLDFAMILY="" + +distro-list () +{ +declare -a MYARRAY1=('wheezy' 'Debian 7 Wheezy | oldstable' 'jessie' 'Debian 8 Jessie | stable' 'trusty' 'Ubuntu Trusty Tahr 14.04.x LTS'); +k1=0 +l1=1 +while [[ $k1 -lt ${#MYARRAY1[@]} ]] + do + BUILD_DESKTOP="no" + BOARD=$1 + RELEASE=${MYARRAY1[$k1]} + BRANCH=$2 + if [[ $2 == "default" && "$RELEASE" == "trusty" ]]; then + BUILD_DESKTOP="yes" + else + BUILD_DESKTOP="no" + fi + + source $SRC/lib/configuration.sh + if [[ $KERNEL_ONLY == "yes" ]]; then + if [[ "$OLDFAMILY" != *"$LINUXFAMILY$BRANCH"* ]]; then + echo "$BOARD $RELEASE $BRANCH $BUILD_DESKTOP $LINUXFAMILY" + source $SRC/lib/main.sh + OLDFAMILY=$OLDFAMILY"$LINUXFAMILY$BRANCH" + fi + else + echo "$BOARD $RELEASE $BRANCH $BUILD_DESKTOP $LINUXFAMILY" + source $SRC/lib/main.sh + fi # kernel only + + SOURCE_COMPILE="yes" + k1=$[$k1+2] + l1=$[$l1+2] + done +} + +IFS=";" +MYARRAY=($(cat $SRC/lib/configuration.sh | awk '/)#enabled/ || /#des/ || /#build/' | sed 's/)#enabled//g' | sed 's/#description //g' | sed 's/#build //g' | sed ':a;N;$!ba;s/\n/;/g')) + i1=$[0+$START] + j1=$[1+$START] + o1=$[2+$START] + while [[ $i1 -lt ${#MYARRAY[@]} ]] + do + + if [ "${MYARRAY[$o1]}" == "1" ]; then + distro-list "${MYARRAY[$i1]}" "default" + fi + if [ "${MYARRAY[$o1]}" == "2" ]; then + distro-list "${MYARRAY[$i1]}" "next" + fi + if [ "${MYARRAY[$o1]}" == "3" ]; then + distro-list "${MYARRAY[$i1]}" "default" + distro-list "${MYARRAY[$i1]}" "next" + fi + + i1=$[$i1+3];j1=$[$j1+3];o1=$[$o1+3] + done diff --git a/common.sh b/common.sh index 0c167ae95..681df05e6 100644 --- a/common.sh +++ b/common.sh @@ -1,714 +1,312 @@ #!/bin/bash # -# Created by Igor Pecovnik, www.igorpecovnik.com +# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com +# +# This file is licensed under the terms of the GNU General Public +# License version 2. This program is licensed "as is" without any +# warranty of any kind, whether express or implied. +# +# This file is a part of tool chain https://github.com/igorpecovnik/lib # -# Image build functions - - -download_host_packages (){ -#-------------------------------------------------------------------------------------------------------------------------------- -# Download packages for host - Ubuntu 14.04 recommended -#-------------------------------------------------------------------------------------------------------------------------------- -echo "Downloading necessary files." -# basic -apt-get -y install debconf-utils -debconf-apt-progress -- apt-get -y install pv bc lzop zip binfmt-support bison build-essential ccache debootstrap flex gawk gcc-arm-linux-gnueabi -debconf-apt-progress -- apt-get -y install gcc-arm-linux-gnueabihf lvm2 qemu-user-static u-boot-tools uuid-dev zlib1g-dev unzip libncurses5-dev -debconf-apt-progress -- apt-get -y install libusb-1.0-0-dev parted pkg-config expect -# for creating PDF documentation -# debconf-apt-progress -- apt-get -y install pandoc nbibtex texlive-latex-base texlive-latex-recommended texlive-latex-extra preview-latex-style -# debconf-apt-progress -- apt-get -y install dvipng texlive-fonts-recommended -echo "Done."; -} - - -fetch_from_github (){ -#-------------------------------------------------------------------------------------------------------------------------------- -# Download sources from Github -#-------------------------------------------------------------------------------------------------------------------------------- -echo "------ Downloading $2." -if [ -d "$DEST/$2" ]; then - cd $DEST/$2 - # some patching for TFT display source and Realtek RT8192CU drivers - if [[ $1 == "https://github.com/notro/fbtft" || $1 == "https://github.com/dz0ny/rt8192cu" ]]; then git checkout master; fi - git pull - cd $SRC -else - git clone $1 $DEST/$2 -fi -} - - -patching_sources(){ -#-------------------------------------------------------------------------------------------------------------------------------- -# Patching sources -#-------------------------------------------------------------------------------------------------------------------------------- -# kernel -cd $DEST/$LINUXSOURCE -# sunxi -if [[ $LINUXSOURCE == "linux-sunxi" ]] ; then - # if the source is already patched for banana, do reverse GMAC patch - if [ "$(cat arch/arm/kernel/setup.c | grep BANANAPI)" != "" ]; then - echo "Reversing Banana patch" - patch --batch -t -p1 < $SRC/lib/patch/bananagmac.patch - fi - # - if [ "$(patch --dry-run -t -p1 < $SRC/lib/patch/gpio.patch | grep previ)" == "" ]; then - patch --batch -f -p1 < $SRC/lib/patch/gpio.patch - fi - # - if [ "$(patch --dry-run -t -p1 < $SRC/lib/patch/spi.patch | grep previ)" == "" ]; then - patch --batch -f -p1 < $SRC/lib/patch/spi.patch - fi - # - if [[ $BOARD == "bananapi" ]] ; then - if [ "$(patch --dry-run -t -p1 < $SRC/lib/patch/bananagmac.patch | grep previ)" == "" ]; then - patch --batch -N -p1 < $SRC/lib/patch/bananagmac.patch - fi - fi - # compile sunxi tools - compile_sunxi_tools -fi -# cubox / hummingboard -if [[ $LINUXSOURCE == "linux-cubox-next" ]] ; then - if [ "$(patch --dry-run -t -p1 < $SRC/lib/patch/hb-i2c-spi.patch | grep previ)" == "" ]; then - patch -p1 < $SRC/lib/patch/hb-i2c-spi.patch - fi -fi -} compile_uboot (){ #-------------------------------------------------------------------------------------------------------------------------------- -# Compile uboot +# Compile uboot from sources #-------------------------------------------------------------------------------------------------------------------------------- -echo "------ Compiling universal boot loader" -if [ -d "$DEST/$BOOTSOURCE" ]; then -cd $DEST/$BOOTSOURCE -make -s CROSS_COMPILE=arm-linux-gnueabihf- clean -# there are two methods of compilation -if [[ $BOOTCONFIG == *config* ]] -then - make $CTHREADS $BOOTCONFIG CROSS_COMPILE=arm-linux-gnueabihf- - make $CTHREADS CROSS_COMPILE=arm-linux-gnueabihf- + +if [ -d "$SOURCES/$BOOTSOURCE" ]; then + grab_u-boot_version + display_alert "Compiling uboot. Please wait." "$UBOOTVER" "info" + echo `date +"%d.%m.%Y %H:%M:%S"` $SOURCES/$BOOTSOURCE/$BOOTCONFIG >> $DEST/debug/install.log + cd $SOURCES/$BOOTSOURCE + make -s ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- clean >/dev/null 2>&1 + # there are two methods of compilation + if [[ $BOOTCONFIG == *config* ]]; then + make $CTHREADS $BOOTCONFIG CROSS_COMPILE=arm-linux-gnueabihf- >/dev/null 2>&1 + [ -f .config ] && sed -i 's/CONFIG_LOCALVERSION=""/CONFIG_LOCALVERSION="-armbian"/g' .config + [ -f .config ] && sed -i 's/CONFIG_LOCALVERSION_AUTO=.*/# CONFIG_LOCALVERSION_AUTO is not set/g' .config + touch .scmversion + if [[ $BRANCH != "next" && $LINUXCONFIG == *sun* ]] ; then + ## patch mainline uboot configuration to boot with old kernels + if [ "$(cat $SOURCES/$BOOTSOURCE/.config | grep CONFIG_ARMV7_BOOT_SEC_DEFAULT=y)" == "" ]; then + echo "CONFIG_ARMV7_BOOT_SEC_DEFAULT=y" >> $SOURCES/$BOOTSOURCE/.config + echo "CONFIG_OLD_SUNXI_KERNEL_COMPAT=y" >> $SOURCES/$BOOTSOURCE/.config + fi + fi + make $CTHREADS CROSS_COMPILE="$CCACHE arm-linux-gnueabihf-" >> $DEST/debug/install.log 2>&1 else - make $CTHREADS $BOOTCONFIG CROSS_COMPILE=arm-linux-gnueabihf- + make $CTHREADS $BOOTCONFIG CROSS_COMPILE=arm-linux-gnueabihf- >> $DEST/debug/install.log 2>&1 +fi + + + + +# create .deb package +# +if [[ $BRANCH == "next" ]] ; then + UBOOT_BRACH="-next" + else + UBOOT_BRACH="" +fi +CHOOSEN_UBOOT="linux-u-boot"$UBOOT_BRACH"-"$BOARD"_"$REVISION"_armhf" +UBOOT_PCK="linux-u-boot-"$BOARD""$UBOOT_BRACH +mkdir -p $DEST/debs/$CHOOSEN_UBOOT/usr/lib/$CHOOSEN_UBOOT +mkdir -p $DEST/debs/$CHOOSEN_UBOOT/DEBIAN +# set up post install script +cat < $DEST/debs/$CHOOSEN_UBOOT/DEBIAN/postinst +#!/bin/bash +set -e +if [[ \$DEVICE == "" ]]; then DEVICE="/dev/mmcblk0"; fi + +if [[ \$DPKG_MAINTSCRIPT_PACKAGE == *cubox* ]] ; then + ( dd if=/usr/lib/$CHOOSEN_UBOOT/SPL of=\$DEVICE bs=512 seek=2 status=noxfer ) > /dev/null 2>&1 + ( dd if=/usr/lib/$CHOOSEN_UBOOT/u-boot.img of=\$DEVICE bs=1K seek=42 status=noxfer ) > /dev/null 2>&1 +elif [[ \$DPKG_MAINTSCRIPT_PACKAGE == *guitar* ]] ; then + ( dd if=/usr/lib/$CHOOSEN_UBOOT/bootloader.bin of=\$DEVICE bs=512 seek=4097 conv=fsync ) > /dev/null 2>&1 + ( dd if=/usr/lib/$CHOOSEN_UBOOT/u-boot-dtb.bin of=\$DEVICE bs=512 seek=6144 conv=fsync ) > /dev/null 2>&1 +elif [[ \$DPKG_MAINTSCRIPT_PACKAGE == *udoo* ]] ; then + ( dd if=/usr/lib/$CHOOSEN_UBOOT/u-boot.imx of=\$DEVICE bs=1024 seek=1 conv=fsync ) > /dev/null 2>&1 +else + ( dd if=/usr/lib/$CHOOSEN_UBOOT/u-boot-sunxi-with-spl.bin of=\$DEVICE bs=1024 seek=8 status=noxfer ) > /dev/null 2>&1 +fi +exit 0 +END + +chmod 755 $DEST/debs/$CHOOSEN_UBOOT/DEBIAN/postinst +# set up control file +cat < $DEST/debs/$CHOOSEN_UBOOT/DEBIAN/control +Package: linux-u-boot-$BOARD$UBOOT_BRACH +Version: $REVISION +Architecture: armhf +Maintainer: $MAINTAINER <$MAINTAINERMAIL> +Installed-Size: 1 +Section: kernel +Priority: optional +Description: Uboot loader $UBOOTVER +END +# + +if [[ $BOARD == cubox-i* ]] ; then + [ ! -f "SPL" ] || cp SPL u-boot.img $DEST/debs/$CHOOSEN_UBOOT/usr/lib/$CHOOSEN_UBOOT +elif [[ $BOARD == guitar* ]] ; then + [ ! -f "u-boot-dtb.bin" ] || cp u-boot-dtb.bin $DEST/debs/$CHOOSEN_UBOOT/usr/lib/$CHOOSEN_UBOOT + [ ! -f "$SRC/lib/bin/s500-bootloader.bin" ] || cp $SRC/lib/bin/s500-bootloader.bin $DEST/debs/$CHOOSEN_UBOOT/usr/lib/$CHOOSEN_UBOOT/bootloader.bin +elif [[ $BOARD == udoo* ]] ; then + [ ! -f "u-boot.imx" ] || cp u-boot.imx $DEST/debs/$CHOOSEN_UBOOT/usr/lib/$CHOOSEN_UBOOT +else + [ ! -f "u-boot-sunxi-with-spl.bin" ] || cp u-boot-sunxi-with-spl.bin $DEST/debs/$CHOOSEN_UBOOT/usr/lib/$CHOOSEN_UBOOT +fi + +cd $DEST/debs +display_alert "Target directory" "$DEST/debs/" "info" +display_alert "Building deb" "$CHOOSEN_UBOOT.deb" "info" +dpkg -b $CHOOSEN_UBOOT >/dev/null 2>&1 +rm -rf $CHOOSEN_UBOOT +CHOOSEN_UBOOT=$CHOOSEN_UBOOT".deb" +# + +FILESIZE=$(wc -c $DEST/debs/$CHOOSEN_UBOOT | cut -f 1 -d ' ') + +if [ $FILESIZE -lt 50000 ]; then + display_alert "Building failed, check configuration." "$CHOOSEN_UBOOT deleted" "err" + rm $DEST/debs/$CHOOSEN_UBOOT + exit fi else -echo "ERROR: Source file $1 does not exists. Check fetch_from_github configuration." -exit +display_alert "Source file $1 does not exists. Check fetch_from_github configuration." "" "err" fi } compile_sunxi_tools (){ #-------------------------------------------------------------------------------------------------------------------------------- -# Compile sunxi_tools +# Compile sunxi_tools for host #-------------------------------------------------------------------------------------------------------------------------------- -echo "------ Compiling sunxi tools" -cd $DEST/sunxi-tools -# for host -make -s clean && make -s fex2bin && make -s bin2fex +display_alert "Compiling sunxi tools" "@host & target" "info" +cd $SOURCES/$MISC1_DIR +make -s clean >/dev/null 2>&1 +make -s >/dev/null 2>&1 cp fex2bin bin2fex /usr/local/bin/ -# for destination -make -s clean && make $CTHREADS 'fex2bin' CC=arm-linux-gnueabihf-gcc -make $CTHREADS 'bin2fex' CC=arm-linux-gnueabihf-gcc && make $CTHREADS 'nand-part' CC=arm-linux-gnueabihf-gcc -} - - -add_fb_tft (){ -#-------------------------------------------------------------------------------------------------------------------------------- -# Adding FBTFT library / small TFT display support -#-------------------------------------------------------------------------------------------------------------------------------- -# there is a change for kernel less than 3.5 -IFS='.' read -a array <<< "$VER" -cd $DEST/$MISC4_DIR -if (( "${array[0]}" == "3" )) && (( "${array[1]}" < "5" )) -then - git checkout 06f0bba152c036455ae76d26e612ff0e70a83a82 -else - git checkout master -fi -cd $DEST/$LINUXSOURCE -if [[ $BOARD == "bananapi" || $BOARD == "cubietruck" || $BOARD == "cubieboard2" || $BOARD == "cubieboard" || $BOARD == "lime" || $BOARD == "lime2" ]]; then - if [ "$(patch --dry-run -t -p1 < $SRC/lib/patch/bananafbtft.patch | grep previ)" == "" ]; then - # DMA disable - patch --batch -N -p1 < $SRC/lib/patch/bananafbtft.patch - fi -fi -# common patch -if [ "$(patch --dry-run -t -p1 < $SRC/lib/patch/small_lcd_drivers.patch | grep previ)" == "" ]; then - patch -p1 < $SRC/lib/patch/small_lcd_drivers.patch -fi } compile_kernel (){ #-------------------------------------------------------------------------------------------------------------------------------- -# Compile kernel +# Compile kernel #-------------------------------------------------------------------------------------------------------------------------------- -echo "------ Compiling kernel" -if [ -d "$DEST/$LINUXSOURCE" ]; then +display_alert "Compiling kernel" "@host" "info" +sleep 2 -# add small TFT display support -if [ "$FBTFT" = "yes" ]; then -add_fb_tft -fi +if [ -d "$SOURCES/$LINUXSOURCE" ]; then -cd $DEST/$LINUXSOURCE +cd $SOURCES/$LINUXSOURCE # delete previous creations -make -s CROSS_COMPILE=arm-linux-gnueabihf- clean +if [ "$KERNEL_CLEAN" = "yes" ]; then make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- clean | dialog --backtitle "$backtitle" --progressbox "Cleaning kernel source ..." 20 70; fi -rm -rf output -mkdir -p output/boot +# adding custom firmware to kernel source +if [[ -n "$FIRMWARE" ]]; then unzip -o $SRC/lib/$FIRMWARE -d $SOURCES/$LINUXSOURCE/firmware; fi -# Adding custom firmware to kernel source -if [[ -n "$FIRMWARE" ]]; then unzip -o $SRC/lib/$FIRMWARE -d $DEST/$LINUXSOURCE/firmware; fi +# use proven config +if [ "$KERNEL_KEEP_CONFIG" != "yes" ]; then cp $SRC/lib/config/$LINUXCONFIG.config $SOURCES/$LINUXSOURCE/.config; fi -# compile from proven config -cp $SRC/lib/config/$LINUXSOURCE.config $DEST/$LINUXSOURCE/.config -if [ "$KERNEL_CONFIGURE" = "yes" ]; then make $CTHREADS ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig ; fi - -# there are more methods of compilation -if [[ $BOARD == "cubox-i" ]] -then - make $CTHREADS ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules $DTBS LOCALVERSION="$LOCALVERSION" - make $CTHREADS ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=output modules_install - make $CTHREADS ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_HDR_PATH=output/usr headers_install - cp Module.symvers output/usr/include - cp arch/arm/boot/zImage output/boot/ - cp arch/arm/boot/dts/*.dtb output/boot -elif [[ $BOARD == *next* ]] -then - make $CTHREADS ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- LOADADDR=0x40008000 uImage modules dtbs LOCALVERSION="$LOCALVERSION" - make $CTHREADS ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=output modules_install - make $CTHREADS ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_HDR_PATH=output/usr headers_install - mkdir output/boot/dtb - cp Module.symvers output/usr/include - cp arch/arm/boot/uImage output/boot/ - cp arch/arm/boot/dts/*.dtb output/boot/dtb - sed -e "s/WHICH/$DTBS/g" $SRC/lib/config/boot.cmd > /tmp/boot.cmd - mkimage -C none -A arm -T script -d /tmp/boot.cmd output/boot/boot.scr -else - make $CTHREADS ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- uImage modules LOCALVERSION="$LOCALVERSION" - make $CTHREADS ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=output modules_install - make $CTHREADS ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_HDR_PATH=output/usr headers_install - cp Module.symvers output/usr/include - cp arch/arm/boot/uImage output/boot/ +# hacks for banana +if [[ $BOARD == banana* || $BOARD == orangepi* || $BOARD == lamobo* ]] ; then +sed -i 's/CONFIG_GMAC_CLK_SYS=y/CONFIG_GMAC_CLK_SYS=y\nCONFIG_GMAC_FOR_BANANAPI=y/g' .config fi -# add linux firmwares to output image -unzip $SRC/lib/bin/linux-firmware.zip -d output/lib/firmware +# hack for deb builder. To pack what's missing in headers pack. +cp $SRC/lib/patch/misc/headers-debian-byteshift.patch /tmp -if [ "$FBTFT" = "yes" ]; then -# reverse fbtft patch -patch --batch -t -p1 < $SRC/lib/patch/bananafbtft.patch +if [ "$KERNEL_CONFIGURE" = "yes" ]; then make $CTHREADS ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig; fi + +export LOCALVERSION="-"$LINUXFAMILY + +# this way of compilation is much faster. We can use multi threading here but not later +make $CTHREADS ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- oldconfig + +make $CTHREADS ARCH=arm CROSS_COMPILE="$CCACHE arm-linux-gnueabihf-" zImage modules 2>&1 | dialog --backtitle "$backtitle" --progressbox "Compiling kernel $CCACHE ..." 20 80 + +if [ ${PIPESTATUS[0]} -ne 0 ] || [ ! -f arch/arm/boot/zImage ]; then + display_alert "Kernel was not built" "@host" "err" + exit 1 +fi +make $CTHREADS ARCH=arm CROSS_COMPILE="$CCACHE arm-linux-gnueabihf-" dtbs 2>&1 | dialog --backtitle "$backtitle" --progressbox "Compiling DTB $CCACHE ..." 20 80 +if [ ${PIPESTATUS[0]} -ne 0 ]; then + display_alert "DTBs was not build" "@host" "err" + exit 1 fi + +if [[ $BRANCH == "next" ]] ; then + KERNEL_BRACH="-next" + else + KERNEL_BRACH="" +fi + +# different packaging for 4.3+ // probably temporaly soution +KERNEL_PACKING="deb-pkg" +IFS='.' read -a array <<< "$VER" +if (( "${array[0]}" == "4" )) && (( "${array[1]}" >= "3" )); then +KERNEL_PACKING="bindeb-pkg" +fi + +# make $CTHREADS ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- +# produce deb packages: image, headers, firmware, libc +make -j1 $KERNEL_PACKING KDEB_PKGVERSION=$REVISION LOCALVERSION="-"$LINUXFAMILY KBUILD_DEBARCH=armhf ARCH=arm DEBFULLNAME="$MAINTAINER" \ +DEBEMAIL="$MAINTAINERMAIL" CROSS_COMPILE="$CCACHE arm-linux-gnueabihf-" 2>&1 | dialog --backtitle "$backtitle" --progressbox "Packing kernel $CCACHE ..." 20 80 + + +# we need a name +CHOOSEN_KERNEL=linux-image"$KERNEL_BRACH"-"$CONFIG_LOCALVERSION$LINUXFAMILY"_"$REVISION"_armhf.deb +cd .. +mv *.deb $DEST/debs/ || exit else -echo "ERROR: Source file $1 does not exists. Check fetch_from_github configuration." +display_alert "Source file $1 does not exists. Check fetch_from_github configuration." "" "err" exit fi sync } -packing_kernel (){ -#-------------------------------------------------------------------------------------------------------------------------------- -# Pack kernel -#-------------------------------------------------------------------------------------------------------------------------------- - -if [ -d "$DEST/$LINUXSOURCE"/output/lib/modules/"$VER$LOCALVERSION" ]; then -cd "$DEST/$LINUXSOURCE"/output/lib/modules/"$VER$LOCALVERSION" -# correct link -rm build source -ln -s /usr/include/ build -ln -s /usr/include/ source -fi -# -mkdir -p $DEST/output/kernel -cd $DEST/$LINUXSOURCE/output -tar -cPf $DEST"/output/kernel/"$BOARD"_kernel_"$VER"_mod_head_fw.tar" * -cd $DEST/output/kernel -md5sum "$BOARD"_kernel_"$VER"_mod_head_fw.tar > "$BOARD"_kernel_"$VER"_mod_head_fw.md5 -zip "$BOARD"_kernel_"$VER"_mod_head_fw.zip "$BOARD"_kernel_"$VER"_mod_head_fw.* -sync -CHOOSEN_KERNEL="$BOARD"_kernel_"$VER"_mod_head_fw.tar -} - - -create_debian_template (){ -#-------------------------------------------------------------------------------------------------------------------------------- -# Create Debian and Ubuntu image template if it does not exists -#-------------------------------------------------------------------------------------------------------------------------------- -if [ ! -f "$DEST/output/rootfs/$RELEASE.raw.gz" ]; then -echo "------ Debootstrap $RELEASE to image template" -cd $DEST/output - -# create needed directories and mount image to next free loop device -mkdir -p $DEST/output/rootfs $DEST/output/sdcard/ $DEST/output/kernel - -# create image file -dd if=/dev/zero of=$DEST/output/rootfs/$RELEASE.raw bs=1M count=$SDSIZE status=noxfer - -# find first avaliable free device -LOOP=$(losetup -f) - -# mount image as block device -losetup $LOOP $DEST/output/rootfs/$RELEASE.raw - -sync - -# create one partition starting at 2048 which is default -echo "------ Partitioning and mounting file-system." -parted -s $LOOP -- mklabel msdos -parted -s $LOOP -- mkpart primary ext4 2048s -1s -partprobe $LOOP -losetup -d $LOOP -sleep 2 - -# 2048 (start) x 512 (block size) = where to mount partition -losetup -o 1048576 $LOOP $DEST/output/rootfs/$RELEASE.raw - -# create filesystem -mkfs.ext4 $LOOP - -# tune filesystem -tune2fs -o journal_data_writeback $LOOP - -# label it -e2label $LOOP "$BOARD" - -# mount image to already prepared mount point -mount -t ext4 $LOOP $DEST/output/sdcard/ - -# debootstrap base system -debootstrap --include=openssh-server,debconf-utils --arch=armhf --foreign $RELEASE $DEST/output/sdcard/ -#debootstrap --include=openssh-server,debconf-utils --arch=armhf --foreign $RELEASE $DEST/output/sdcard/ http://ftp.si.debian.org/debian - -# we need emulator for second stage -cp /usr/bin/qemu-arm-static $DEST/output/sdcard/usr/bin/ - -# enable arm binary format so that the cross-architecture chroot environment will work -test -e /proc/sys/fs/binfmt_misc/qemu-arm || update-binfmts --enable qemu-arm - -# debootstrap second stage -chroot $DEST/output/sdcard /bin/bash -c "/debootstrap/debootstrap --second-stage" - -# mount proc, sys and dev -mount -t proc chproc $DEST/output/sdcard/proc -mount -t sysfs chsys $DEST/output/sdcard/sys -mount -t devtmpfs chdev $DEST/output/sdcard/dev || mount --bind /dev $DEST/output/sdcard/dev -mount -t devpts chpts $DEST/output/sdcard/dev/pts - -# root-fs modifications -rm -f $DEST/output/sdcard/etc/motd -touch $DEST/output/sdcard/etc/motd - -# choose proper apt list -cp $SRC/lib/config/sources.list.$RELEASE $DEST/output/sdcard/etc/apt/sources.list - -# update and upgrade -LC_ALL=C LANGUAGE=C LANG=C chroot $DEST/output/sdcard /bin/bash -c "apt-get -y update" - -# install aditional packages -PAKETKI="alsa-utils bash-completion bc bridge-utils bluez build-essential cmake cpufrequtils curl dosfstools evtest figlet fping git haveged hddtemp hdparm hostapd htop i2c-tools ifenslave-2.6 iperf ir-keytable iw less libbluetooth-dev libbluetooth3 libfuse2 libnl-dev libssl-dev lirc lsof makedev module-init-tools nano ntfs-3g ntp parted pciutils python-smbus rfkill rsync screen stress sudo sysfsutils toilet u-boot-tools unattended-upgrades unzip usbutils wireless-tools wpasupplicant" - -if [ "$RELEASE" != "wheezy" ]; then - PAKETKI="${PAKETKI//libnl-dev/libnl-3-dev}"; # change package - PAKETKI=$PAKETKI" busybox-syslogd"; # to gain performance - LC_ALL=C LANGUAGE=C LANG=C chroot $DEST/output/sdcard /bin/bash -c "apt-get -y remove rsyslog" - sed -e s,"TTYVTDisallocate=yes","TTYVTDisallocate=no",g -i $DEST/output/sdcard/etc/systemd/system/getty.target.wants/getty@tty1.service - # enable root login for latest ssh on jessie - sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' $DEST/output/sdcard/etc/ssh/sshd_config -else - # don't clear screen - sed -e 's/1:2345:respawn:\/sbin\/getty 38400 tty1/1:2345:respawn:\/sbin\/getty --noclear 38400 tty1/g' -i $DEST/output/sdcard/etc/inittab -fi - -# Ubuntu fixes -# that my startup scripts works well -if [ ! -f "$DEST/output/sdcard/sbin/insserv" ]; then -chroot $DEST/output/sdcard /bin/bash -c "ln -s /usr/lib/insserv/insserv /sbin/insserv" -fi -# that my custom motd works well -if [ -d "$DEST/output/sdcard/etc/update-motd.d" ]; then -chroot $DEST/output/sdcard /bin/bash -c "mv /etc/update-motd.d /etc/update-motd.d-backup" -fi -# - -# too much ? udev / cups avahi-daemon colord dbus-x11 consolekit - -# generate locales -LC_ALL=C LANGUAGE=C LANG=C chroot $DEST/output/sdcard /bin/bash -c "apt-get -y -qq install locales" -sed -i "s/^# $DEST_LANG/$DEST_LANG/" $DEST/output/sdcard/etc/locale.gen -LC_ALL=C LANGUAGE=C LANG=C chroot $DEST/output/sdcard /bin/bash -c "locale-gen $DEST_LANG" -LC_ALL=C LANGUAGE=C LANG=C chroot $DEST/output/sdcard /bin/bash -c "export LANG=$DEST_LANG LANGUAGE=$DEST_LANG DEBIAN_FRONTEND=noninteractive" -LC_ALL=C LANGUAGE=C LANG=C chroot $DEST/output/sdcard /bin/bash -c "update-locale LANG=$DEST_LANG LANGUAGE=$DEST_LANG LC_MESSAGES=POSIX" -chroot $DEST/output/sdcard /bin/bash -c "debconf-apt-progress -- apt-get -y install $PAKETKI" -#chroot $DEST/output/sdcard /bin/bash -c "apt-get install $PAKETKI" - -chroot $DEST/output/sdcard /bin/bash -c "debconf-apt-progress -- apt-get -y autoremove" -# set up 'apt -cat < $DEST/output/sdcard/etc/apt/apt.conf.d/71-no-recommends -APT::Install-Recommends "0"; -APT::Install-Suggests "0"; -END - -# scripts for autoresize at first boot -cp $SRC/lib/scripts/resize2fs $DEST/output/sdcard/etc/init.d -cp $SRC/lib/scripts/firstrun $DEST/output/sdcard/etc/init.d -chroot $DEST/output/sdcard /bin/bash -c "chmod +x /etc/init.d/firstrun" -chroot $DEST/output/sdcard /bin/bash -c "chmod +x /etc/init.d/resize2fs" -chroot $DEST/output/sdcard /bin/bash -c "insserv firstrun >> /dev/null" - -# install custom bashrc and hardware dependent motd -cat $SRC/lib/scripts/bashrc >> $DEST/output/sdcard/etc/bash.bashrc -cp $SRC/lib/scripts/armhwinfo $DEST/output/sdcard/etc/init.d/ -chroot $DEST/output/sdcard /bin/bash -c "insserv armhwinfo >> /dev/null" - -if [ -f "$DEST/output/sdcard/etc/init.d/motd" ]; then -sed -e s,"# Update motd","insserv armhwinfo >> /dev/null",g -i $DEST/output/sdcard/etc/init.d/motd -sed -e s,"uname -snrvm > /var/run/motd.dynamic","",g -i $DEST/output/sdcard/etc/init.d/motd -fi - -# install ramlog -if [ "$RELEASE" = "wheezy" ]; then - cp $SRC/lib/bin/ramlog_2.0.0_all.deb $DEST/output/sdcard/tmp - chroot $DEST/output/sdcard /bin/bash -c "dpkg -i /tmp/ramlog_2.0.0_all.deb" - rm $DEST/output/sdcard/tmp/ramlog_2.0.0_all.deb - sed -e 's/TMPFS_RAMFS_SIZE=/TMPFS_RAMFS_SIZE=512m/g' -i $DEST/output/sdcard/etc/default/ramlog - sed -e 's/# Required-Start: $remote_fs $time/# Required-Start: $remote_fs $time ramlog/g' -i $DEST/output/sdcard/etc/init.d/rsyslog - sed -e 's/# Required-Stop: umountnfs $time/# Required-Stop: umountnfs $time ramlog/g' -i $DEST/output/sdcard/etc/init.d/rsyslog -fi - -# replace hostapd from testing binary -cd $DEST/output/sdcard/usr/sbin/ -tar xfz $SRC/lib/bin/hostapd24.tgz -cp $SRC/lib/config/hostapd.conf $DEST/output/sdcard/etc/hostapd.conf - -# set console -chroot $DEST/output/sdcard /bin/bash -c "export TERM=linux" - -# change time zone data -echo $TZDATA > $DEST/output/sdcard/etc/timezone -chroot $DEST/output/sdcard /bin/bash -c "dpkg-reconfigure -f noninteractive tzdata" - -# set root password and force password change upon first login -chroot $DEST/output/sdcard /bin/bash -c "(echo $ROOTPWD;echo $ROOTPWD;) | passwd root" -chroot $DEST/output/sdcard /bin/bash -c "chage -d 0 root" - -# change default I/O scheduler, noop for flash media, deadline for SSD, cfq for mechanical drive -cat <> $DEST/output/sdcard/etc/sysfs.conf -block/mmcblk0/queue/scheduler = noop -#block/sda/queue/scheduler = cfq -EOT - -# add noatime to root FS -echo "/dev/mmcblk0p1 / ext4 defaults,noatime,nodiratime,data=writeback,commit=600,errors=remount-ro 0 0" >> $DEST/output/sdcard/etc/fstab - -# Configure The System For unattended upgrades -cp $SRC/lib/scripts/50unattended-upgrades $DEST/output/sdcard/etc/apt/apt.conf.d/50unattended-upgrades -cp $SRC/lib/scripts/02periodic $DEST/output/sdcard/etc/apt/apt.conf.d/02periodic -sed -e "s/CODENAME/$RELEASE/g" -i $DEST/output/sdcard/etc/apt/apt.conf.d/50unattended-upgrades -if [[ "$RELEASE" == "wheezy" || "$RELEASE" == "jessie" ]]; then - sed -e "s/ORIGIN/Debian/g" -i $DEST/output/sdcard/etc/apt/apt.conf.d/50unattended-upgrades -else - # Ubuntu stuff - sed -e "s/ORIGIN/Ubuntu/g" -i $DEST/output/sdcard/etc/apt/apt.conf.d/50unattended-upgrades - # Serial console - cp $SRC/lib/config/ttymxc0.conf $DEST/output/sdcard/etc/init -fi - -# flash media tunning -if [ -f "$DEST/output/sdcard/etc/default/tmpfs" ]; then -sed -e 's/#RAMTMP=no/RAMTMP=yes/g' -i $DEST/output/sdcard/etc/default/tmpfs -sed -e 's/#RUN_SIZE=10%/RUN_SIZE=128M/g' -i $DEST/output/sdcard/etc/default/tmpfs -sed -e 's/#LOCK_SIZE=/LOCK_SIZE=/g' -i $DEST/output/sdcard/etc/default/tmpfs -sed -e 's/#SHM_SIZE=/SHM_SIZE=128M/g' -i $DEST/output/sdcard/etc/default/tmpfs -sed -e 's/#TMP_SIZE=/TMP_SIZE=1G/g' -i $DEST/output/sdcard/etc/default/tmpfs -fi - -# clean deb cache -chroot $DEST/output/sdcard /bin/bash -c "apt-get -y clean" - -echo "------ Closing image" -chroot $DEST/output/sdcard /bin/bash -c "sync" -sync -sleep 3 -# unmount proc, sys and dev from chroot -umount -l $DEST/output/sdcard/dev/pts -umount -l $DEST/output/sdcard/dev -umount -l $DEST/output/sdcard/proc -umount -l $DEST/output/sdcard/sys - -# kill process inside -KILLPROC=$(ps -uax | pgrep ntpd | tail -1); if [ -n "$KILLPROC" ]; then kill -9 $KILLPROC; fi -KILLPROC=$(ps -uax | pgrep dbus-daemon | tail -1); if [ -n "$KILLPROC" ]; then kill -9 $KILLPROC; fi - -umount -l $DEST/output/sdcard/ -sleep 2 -losetup -d $LOOP -rm -rf $DEST/output/sdcard/ - -gzip $DEST/output/rootfs/$RELEASE.raw -fi - - -# -} - - -install_kernel (){ -#-------------------------------------------------------------------------------------------------------------------------------- -# Install kernel to prepared root filesystem -#-------------------------------------------------------------------------------------------------------------------------------- -if [ ! -f "$DEST/output/kernel/"$CHOOSEN_KERNEL ]; then - echo "Previously compiled kernel does not exits. Please choose compile=yes in configuration and run again!" - exit -fi -mkdir -p $DEST/output/sdcard/ -gzip -dc < $DEST/output/rootfs/$RELEASE.raw.gz > $DEST/output/debian_rootfs.raw -LOOP=$(losetup -f) -losetup -o 1048576 $LOOP $DEST/output/debian_rootfs.raw -mount -t ext4 $LOOP $DEST/output/sdcard/ - -# mount proc, sys and dev -mount -t proc chproc $DEST/output/sdcard/proc -mount -t sysfs chsys $DEST/output/sdcard/sys -mount -t devtmpfs chdev $DEST/output/sdcard/dev || mount --bind /dev $DEST/output/sdcard/dev -mount -t devpts chpts $DEST/output/sdcard/dev/pts - -# configure MIN / MAX Speed for cpufrequtils -sed -e "s/MIN_SPEED=\"0\"/MIN_SPEED=\"$CPUMIN\"/g" -i $DEST/output/sdcard/etc/init.d/cpufrequtils -sed -e "s/MAX_SPEED=\"0\"/MAX_SPEED=\"$CPUMAX\"/g" -i $DEST/output/sdcard/etc/init.d/cpufrequtils -sed -e 's/ondemand/interactive/g' -i $DEST/output/sdcard/etc/init.d/cpufrequtils - -# alter hostap configuration -sed -i "s/BOARD/$BOARD/" $DEST/output/sdcard/etc/hostapd.conf - -# set hostname -echo $HOST > $DEST/output/sdcard/etc/hostname - -# set hostname in hosts file -cat > $DEST/output/sdcard/etc/hosts < /tmp/boot.cmd - mkimage -C none -A arm -T script -d /tmp/boot.cmd $DEST/output/sdcard/boot/boot.scr -fi -} - - -install_board_specific (){ -#-------------------------------------------------------------------------------------------------------------------------------- -# Install board specific applications -#-------------------------------------------------------------------------------------------------------------------------------- -echo "------ Install board specific applications" -# -if [[ $LOCALVERSION == *sunxi ]] ; then - # enable serial console (Debian/sysvinit way) - echo T0:2345:respawn:/sbin/getty -L ttyS0 115200 vt100 >> $DEST/output/sdcard/etc/inittab - # alter rc.local - head -n -1 $DEST/output/sdcard/etc/rc.local > /tmp/out - echo 'echo 2 > /proc/irq/$(cat /proc/interrupts | grep eth0 | cut -f 1 -d ":" | tr -d " ")/smp_affinity' >> /tmp/out - #echo 'KILLPROC=$(ps uax | pgrep fbi | tail -1); if [ -n "$KILLPROC" ]; then kill $KILLPROC; fi ' >> /tmp/out - echo 'exit 0' >> /tmp/out - mv /tmp/out $DEST/output/sdcard/etc/rc.local - chroot $DEST/output/sdcard /bin/bash -c "chmod +x /etc/rc.local" - if [[ $BOARD != *next* ]] ; then - # sunxi tools - cp $DEST/sunxi-tools/fex2bin $DEST/sunxi-tools/bin2fex $DEST/sunxi-tools/nand-part $DEST/output/sdcard/usr/bin/ - # script to install to SATA - cp $SRC/lib/scripts/sata-install.sh $DEST/output/sdcard/root - fi -fi - -if [[ $BOARD == "bananapi" ]] ; then - fex2bin $SRC/lib/config/bananapi.fex $DEST/output/sdcard/boot/bananapi.bin - cp $SRC/lib/config/uEnv.bananapi $DEST/output/sdcard/boot/uEnv.txt - # script to turn off the LED blinking - cp $SRC/lib/scripts/disable_led_banana.sh $DEST/output/sdcard/etc/init.d/disable_led_banana.sh - chroot $DEST/output/sdcard /bin/bash -c "chmod +x /etc/init.d/disable_led_banana.sh" - chroot $DEST/output/sdcard /bin/bash -c "insserv disable_led_banana.sh" - # default lirc configuration - sed -e 's/DEVICE=""/DEVICE="\/dev\/input\/event1"/g' -i $DEST/output/sdcard/etc/lirc/hardware.conf - sed -e 's/DRIVER="UNCONFIGURED"/DRIVER="devinput"/g' -i $DEST/output/sdcard/etc/lirc/hardware.conf - cp $SRC/lib/config/lirc.conf.bananapi $DEST/output/sdcard/etc/lirc/lircd.conf -fi - -if [[ $BOARD == "micro" || $BOARD == "lime" || $BOARD == "lime2" ]] ; then - fex2bin $SRC/lib/config/olimex-$BOARD.fex $DEST/output/sdcard/boot/$BOARD.bin - cp $SRC/lib/config/uEnv.bananapi $DEST/output/sdcard/boot/uEnv.txt - sed -i "s/bananapi.bin/$BOARD.bin/" $DEST/output/sdcard/boot/uEnv.txt - # script to install to NAND - cp $SRC/lib/scripts/nand-install.sh $DEST/output/sdcard/root - cp $SRC/lib/bin/nand1-allwinner.tgz $DEST/output/sdcard/root -fi - -if [[ $BOARD == "cubietruck" || $BOARD == "cubieboard2" ]] ; then - fex2bin $SRC/lib/config/cubietruck.fex $DEST/output/sdcard/boot/cubietruck.bin - fex2bin $SRC/lib/config/cubieboard2.fex $DEST/output/sdcard/boot/cubieboard2.bin - cp $SRC/lib/config/uEnv.cubietruck $DEST/output/sdcard/boot/uEnv.ct - cp $SRC/lib/config/uEnv.cubieboard2 $DEST/output/sdcard/boot/uEnv.cb2 - # script to turn off the LED blinking - cp $SRC/lib/scripts/disable_led.sh $DEST/output/sdcard/etc/init.d/disable_led.sh - chroot $DEST/output/sdcard /bin/bash -c "chmod +x /etc/init.d/disable_led.sh" - chroot $DEST/output/sdcard /bin/bash -c "insserv disable_led.sh" - # bluetooth device enabler - cp $SRC/lib/bin/brcm_patchram_plus $DEST/output/sdcard/usr/local/bin/brcm_patchram_plus - chroot $DEST/output/sdcard /bin/bash -c "chmod +x /usr/local/bin/brcm_patchram_plus" - cp $SRC/lib/scripts/brcm40183 $DEST/output/sdcard/etc/default - cp $SRC/lib/scripts/brcm40183-patch $DEST/output/sdcard/etc/init.d - chroot $DEST/output/sdcard /bin/bash -c "chmod +x /etc/init.d/brcm40183-patch" - # disabled by default - # chroot $DEST/output/sdcard /bin/bash -c "insserv brcm40183-patch" - # default lirc configuration - sed -i '1i sed -i \x27s/DEVICE="\\/dev\\/input.*/DEVICE="\\/dev\\/input\\/\x27$str\x27"/g\x27 /etc/lirc/hardware.conf' $DEST/output/sdcard/etc/lirc/hardware.conf - sed -i '1i str=$(cat /proc/bus/input/devices | grep "H: Handlers=sysrq rfkill kbd event" | awk \x27{print $(NF)}\x27)' $DEST/output/sdcard/etc/lirc/hardware.conf - sed -i '1i # Cubietruck automatic lirc device detection by Igor Pecovnik' $DEST/output/sdcard/etc/lirc/hardware.conf - sed -e 's/DEVICE=""/DEVICE="\/dev\/input\/event1"/g' -i $DEST/output/sdcard/etc/lirc/hardware.conf - sed -e 's/DRIVER="UNCONFIGURED"/DRIVER="devinput"/g' -i $DEST/output/sdcard/etc/lirc/hardware.conf - cp $SRC/lib/config/lirc.conf.cubietruck $DEST/output/sdcard/etc/lirc/lircd.conf - # script to install to NAND - cp $SRC/lib/scripts/nand-install.sh $DEST/output/sdcard/root - cp $SRC/lib/bin/nand1-allwinner.tgz $DEST/output/sdcard/root -fi - -if [[ $BOARD == "cubox-i" ]] ; then - cp $SRC/lib/config/uEnv.cubox-i $DEST/output/sdcard/boot/uEnv.txt - chroot $DEST/output/sdcard /bin/bash -c "chmod 755 /boot/uEnv.txt" - # enable serial console (Debian/sysvinit way) - echo T0:2345:respawn:/sbin/getty -L ttymxc0 115200 vt100 >> $DEST/output/sdcard/etc/inittab - # default lirc configuration - sed -e 's/DEVICE=""/DEVICE="\/dev\/lirc0"/g' -i $DEST/output/sdcard/etc/lirc/hardware.conf - sed -e 's/DRIVER="UNCONFIGURED"/DRIVER="default"/g' -i $DEST/output/sdcard/etc/lirc/hardware.conf - cp $SRC/lib/config/lirc.conf.cubox-i $DEST/output/sdcard/etc/lirc/lircd.conf - cp $SRC/lib/bin/brcm_patchram_plus_cubox $DEST/output/sdcard/usr/local/bin/brcm_patchram_plus - chroot $DEST/output/sdcard /bin/bash -c "chmod +x /usr/local/bin/brcm_patchram_plus" - cp $SRC/lib/scripts/brcm4330 $DEST/output/sdcard/etc/default - cp $SRC/lib/scripts/brcm4330-patch $DEST/output/sdcard/etc/init.d - chroot $DEST/output/sdcard /bin/bash -c "chmod +x /etc/init.d/brcm4330-patch" - chroot $DEST/output/sdcard /bin/bash -c "insserv brcm4330-patch >> /dev/null" - # script to install to SATA - cp $SRC/lib/scripts/sata-install.sh $DEST/output/sdcard/root - # alter rc.local - head -n -1 $DEST/output/sdcard/etc/rc.local > /tmp/out - #echo 'KILLPROC=$(ps uax | pgrep fbi | tail -1); if [ -n "$KILLPROC" ]; then kill $KILLPROC; fi ' >> /tmp/out - echo 'exit 0' >> /tmp/out - mv /tmp/out $DEST/output/sdcard/etc/rc.local - chroot $DEST/output/sdcard /bin/bash -c "chmod +x /etc/rc.local" -fi -} - - -choosing_kernel (){ -#-------------------------------------------------------------------------------------------------------------------------------- -# Choose which kernel to use -#-------------------------------------------------------------------------------------------------------------------------------- -cd $DEST"/output/kernel/" -if [[ $BRANCH == "next" ]]; then -MYLIST=`for x in $(ls -1 *next*.tar); do echo $x " -"; done` -else -MYLIST=`for x in $(ls -1 *.tar | grep -v next); do echo $x " -"; done` -fi -WC=`echo $MYLIST | wc -l` -if [[ $WC -ne 0 ]]; then - whiptail --title "Choose kernel archive" --backtitle "Which kernel do you want to use?" --menu "" 12 60 4 $MYLIST 2>results -fi -CHOOSEN_KERNEL=$(> $DEST/debug/install.log # configure USB redirector -sed -e 's/%INSTALLDIR_TAG%/\/usr\/local/g' $DEST/usb-redirector-linux-arm-eabi/files/rc.usbsrvd > $DEST/usb-redirector-linux-arm-eabi/files/rc.usbsrvd1 -sed -e 's/%PIDFILE_TAG%/\/var\/run\/usbsrvd.pid/g' $DEST/usb-redirector-linux-arm-eabi/files/rc.usbsrvd1 > $DEST/usb-redirector-linux-arm-eabi/files/rc.usbsrvd -sed -e 's/%STUBNAME_TAG%/tusbd/g' $DEST/usb-redirector-linux-arm-eabi/files/rc.usbsrvd > $DEST/usb-redirector-linux-arm-eabi/files/rc.usbsrvd1 -sed -e 's/%DAEMONNAME_TAG%/usbsrvd/g' $DEST/usb-redirector-linux-arm-eabi/files/rc.usbsrvd1 > $DEST/usb-redirector-linux-arm-eabi/files/rc.usbsrvd -chmod +x $DEST/usb-redirector-linux-arm-eabi/files/rc.usbsrvd +sed -e 's/%INSTALLDIR_TAG%/\/usr\/local/g' $SOURCES/usb-redirector-linux-arm-eabi/files/rc.usbsrvd > $SOURCES/usb-redirector-linux-arm-eabi/files/rc.usbsrvd1 +sed -e 's/%PIDFILE_TAG%/\/var\/run\/usbsrvd.pid/g' $SOURCES/usb-redirector-linux-arm-eabi/files/rc.usbsrvd1 > $SOURCES/usb-redirector-linux-arm-eabi/files/rc.usbsrvd +sed -e 's/%STUBNAME_TAG%/tusbd/g' $SOURCES/usb-redirector-linux-arm-eabi/files/rc.usbsrvd > $SOURCES/usb-redirector-linux-arm-eabi/files/rc.usbsrvd1 +sed -e 's/%DAEMONNAME_TAG%/usbsrvd/g' $SOURCES/usb-redirector-linux-arm-eabi/files/rc.usbsrvd1 > $SOURCES/usb-redirector-linux-arm-eabi/files/rc.usbsrvd +chmod +x $SOURCES/usb-redirector-linux-arm-eabi/files/rc.usbsrvd # copy to root -cp $DEST/usb-redirector-linux-arm-eabi/files/usb* $DEST/output/sdcard/usr/local/bin/ -cp $DEST/usb-redirector-linux-arm-eabi/files/modules/src/tusbd/tusbd.ko $DEST/output/sdcard/usr/local/bin/ -cp $DEST/usb-redirector-linux-arm-eabi/files/rc.usbsrvd $DEST/output/sdcard/etc/init.d/ +cp $SOURCES/usb-redirector-linux-arm-eabi/files/usb* $DEST/cache/sdcard/usr/local/bin/ +cp $SOURCES/usb-redirector-linux-arm-eabi/files/modules/src/tusbd/tusbd.ko $DEST/cache/sdcard/usr/local/bin/ +cp $SOURCES/usb-redirector-linux-arm-eabi/files/rc.usbsrvd $DEST/cache/sdcard/etc/init.d/ # not started by default ----- update.rc rc.usbsrvd defaults -# chroot $DEST/output/sdcard /bin/bash -c "update-rc.d rc.usbsrvd defaults" +# chroot $DEST/cache/sdcard /bin/bash -c "update-rc.d rc.usbsrvd defaults" + -# temper binary for USB temp meter -cd $DEST/output/sdcard/usr/local/bin -tar xvfz $SRC/lib/bin/temper.tgz # some aditional stuff. Some driver as example if [[ -n "$MISC3_DIR" ]]; then + display_alert "Installing external applications" "RT8192 driver" "info" # https://github.com/pvaret/rtl8192cu-fixes - cd $DEST/$MISC3_DIR - git checkout 0ea77e747df7d7e47e02638a2ee82ad3d1563199 - make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- clean && make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KSRC=$DEST/$LINUXSOURCE/ - cp *.ko $DEST/output/sdcard/usr/local/bin - cp blacklist*.conf $DEST/output/sdcard/etc/modprobe.d/ + cd $SOURCES/$MISC3_DIR + #git checkout 0ea77e747df7d7e47e02638a2ee82ad3d1563199 + make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- clean >/dev/null 2>&1 + (make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KSRC=$SOURCES/$LINUXSOURCE/ >/dev/null 2>&1) + cp *.ko $DEST/cache/sdcard/usr/local/bin + #cp blacklist*.conf $DEST/cache/sdcard/etc/modprobe.d/ +fi + +# MISC4 = NOTRO DRIVERS / special handling +# MISC5 = sunxu display control +if [[ -n "$MISC5_DIR" && $BRANCH != "next" && $LINUXSOURCE == *sunxi* ]]; then + cd $SOURCES/$MISC5_DIR + cp $SOURCES/$LINUXSOURCE/include/video/sunxi_disp_ioctl.h . + make clean >/dev/null 2>&1 + (make ARCH=arm CC=arm-linux-gnueabihf-gcc KSRC=$SOURCES/$LINUXSOURCE/ >/dev/null 2>&1) + install -m 755 a10disp $DEST/cache/sdcard/usr/local/bin fi } -fingerprint_image (){ +shrinking_raw_image (){ #-------------------------------------------------------------------------------------------------------------------------------- -# Saving build summary to the image +# Shrink partition and image to real size with 10% space #-------------------------------------------------------------------------------------------------------------------------------- -echo "------ Saving build summary to the image" -echo $1 -echo "--------------------------------------------------------------------------------" > $1 -echo "" >> $1 -echo "" >> $1 -echo "" >> $1 -echo "Title: $VERSION (unofficial)" >> $1 -echo "Kernel: Linux $VER" >> $1 -now="$(date +'%d.%m.%Y')" >> $1 -printf "Build date: %s\n" "$now" >> $1 -echo "Author: Igor Pecovnik, www.igorpecovnik.com" >> $1 -echo "Sources: http://github.com/igorpecovnik" >> $1 -echo "" >> $1 -echo "" >> $1 -echo "" >> $1 -echo "--------------------------------------------------------------------------------" >> $1 -echo "" >> $1 -cat $SRC/lib/LICENSE >> $1 -echo "" >> $1 -echo "--------------------------------------------------------------------------------" >> $1 +RAWIMAGE=$1 +display_alert "Shrink image last partition to" "minimum" "info" +# partition prepare +LOOP=$(losetup -f) +losetup $LOOP $RAWIMAGE +PARTSTART=$(parted $LOOP unit s print -sm | tail -1 | cut -d: -f2 | sed 's/s//') +PARTEND=$(parted $LOOP unit s print -sm | head -3 | tail -1 | cut -d: -f3 | sed 's/s//') # end of first partition +PARTSTARTBLOCKS=$(($PARTSTART*512)) +sleep 1; losetup -d $LOOP +# convert from EXT4 to EXT2 +sleep 1; losetup -o $PARTSTARTBLOCKS $LOOP $RAWIMAGE +sleep 1; fsck -n $LOOP >/dev/null 2>&1 +sleep 1; tune2fs -O ^has_journal $LOOP >/dev/null 2>&1 +sleep 1; e2fsck -fy $LOOP >/dev/null 2>&1 +resize2fs $LOOP -M >/dev/null 2>&1 +BLOCKSIZE=$(LANGUAGE=english tune2fs -l $LOOP | grep "Block count" | awk '{ print $(NF)}') +RESERVEDBLOCKSIZE=$(LANGUAGE=english tune2fs -l $LOOP | grep "Reserved block count" | awk '{ print $(NF)}') +BLOCKSIZE=$(($PARTSTART+$BLOCKSIZE+$RESERVEDBLOCKSIZE)) +resize2fs $LOOP $BLOCKSIZE >/dev/null 2>&1 +tune2fs -O has_journal $LOOP >/dev/null 2>&1 +tune2fs -o journal_data_writeback $LOOP >/dev/null 2>&1 +losetup -d $LOOP + +# mount once again and create new partition +sleep 1; losetup $LOOP $RAWIMAGE +#PARTITIONS=$(($(fdisk -l $LOOP | grep $LOOP | wc -l)-1)) +PARTITIONS=$(parted -m $LOOP 'print' | tail -1 | awk -F':' '{ print $1 }') + +#((echo d; echo $PARTITIONS; echo n; echo p; echo ; echo ; echo "+"$NEWSIZE"K"; echo w;) | fdisk $LOOP)>/dev/null +parted $LOOP rm $PARTITIONS >/dev/null 2>&1 +NEWSIZE=$(($BLOCKSIZE*4700/1024)) # overhead hardcoded to number +STARTFROM=$(($PARTEND+1)) # if we have two partitions, start of second one is where first one ends +1 +[[ $PARTITIONS == 1 ]] && STARTFROM=$PARTSTART + +((echo n; echo p; echo ; echo $STARTFROM; echo "+"$NEWSIZE"K"; echo w;) | fdisk $LOOP)>/dev/null +sleep 1 +# truncate the image + +TRUNCATE=$(parted -m $LOOP 'unit s print' | tail -1 | awk -F':' '{ print $3 }' | sed 's/.$//') +TRUNCATE=$((($TRUNCATE+1)*512)) +truncate -s $TRUNCATE $RAWIMAGE >/dev/null 2>&1 +losetup -d $LOOP } @@ -716,66 +314,90 @@ closing_image (){ #-------------------------------------------------------------------------------------------------------------------------------- # Closing image and clean-up #-------------------------------------------------------------------------------------------------------------------------------- -echo "------ Closing image" -chroot $DEST/output/sdcard /bin/bash -c "sync" +display_alert "Possible after install." "$AFTERINSTALL" "info" +chroot $DEST/cache/sdcard /bin/bash -c "$AFTERINSTALL" +chroot $DEST/cache/sdcard /bin/bash -c "sync" sync sleep 3 # unmount proc, sys and dev from chroot -umount -l $DEST/output/sdcard/dev/pts -umount -l $DEST/output/sdcard/dev -umount -l $DEST/output/sdcard/proc -umount -l $DEST/output/sdcard/sys +umount -l $DEST/cache/sdcard/dev/pts +umount -l $DEST/cache/sdcard/dev +umount -l $DEST/cache/sdcard/proc +umount -l $DEST/cache/sdcard/sys +umount -l $DEST/cache/sdcard/tmp >/dev/null 2>&1 # let's create nice file name +VER="${VER/-$LINUXFAMILY/}" VERSION=$VERSION" "$VER VERSION="${VERSION// /_}" VERSION="${VERSION//$BRANCH/}" VERSION="${VERSION//__/_}" +if [ "$BUILD_DESKTOP" = "yes" ]; then +VERSION=$VERSION"_desktop" +fi + + # kill process inside KILLPROC=$(ps -uax | pgrep ntpd | tail -1); if [ -n "$KILLPROC" ]; then kill -9 $KILLPROC; fi KILLPROC=$(ps -uax | pgrep dbus-daemon | tail -1); if [ -n "$KILLPROC" ]; then kill -9 $KILLPROC; fi # same info outside the image -cp $DEST/output/sdcard/root/readme.txt $DEST/output/ +cp $DEST/cache/sdcard/etc/armbian.txt $DEST/cache/ sleep 2 -rm $DEST/output/sdcard/usr/bin/qemu-arm-static -umount -l $DEST/output/sdcard/ +rm $DEST/cache/sdcard/usr/bin/qemu-arm-static +sleep 2 +umount -l $DEST/cache/sdcard/boot > /dev/null 2>&1 || /bin/true +umount -l $DEST/cache/sdcard/ sleep 2 losetup -d $LOOP -rm -rf $DEST/output/sdcard/ +rm -rf $DEST/cache/sdcard/ # write bootloader LOOP=$(losetup -f) -losetup $LOOP $DEST/output/debian_rootfs.raw -if [[ $BOARD == "cubox-i" ]] ; then - dd if=$DEST/$BOOTSOURCE/SPL of=$LOOP bs=512 seek=2 status=noxfer - dd if=$DEST/$BOOTSOURCE/u-boot.img of=$LOOP bs=1K seek=42 status=noxfer -elif [[ $BOARD == "cubieboard4" ]] -then - $SRC/lib/bin/host/cubie-fex2bin $SRC/lib/config/cubieboard4.fex /tmp/sys_config.bin - $SRC/lib/bin/host/cubie-uboot-spl $SRC/lib/bin/cb4-u-boot-spl.bin /tmp/sys_config.bin /tmp/u-boot-spl_with_sys_config.bin - dd if=/tmp/u-boot-spl_with_sys_config.bin of=$LOOP bs=1024 seek=8 status=noxfer - $SRC/lib/bin/host/cubie-uboot $SRC/lib/bin/cb4-u-boot-sun9iw1p1.bin /tmp/sys_config.bin /tmp/u-boot-sun9iw1p1_with_sys_config.bin - dd if=/tmp/u-boot-sun9iw1p1_with_sys_config.bin of=$LOOP bs=1024 seek=19096 status=noxfer -else - dd if=$DEST/$BOOTSOURCE/u-boot-sunxi-with-spl.bin of=$LOOP bs=1024 seek=8 status=noxfer +display_alert "Writing boot loader" "$LOOP" "info" +losetup $LOOP $DEST/cache/tmprootfs.raw +dpkg -x $DEST"/debs/"$CHOOSEN_UBOOT /tmp/ +CHOOSEN_UBOOT="${CHOOSEN_UBOOT//.deb/}" + +if [[ $BOARD == *cubox* ]] ; then + ( dd if=/tmp/usr/lib/"$CHOOSEN_UBOOT"/SPL of=$LOOP bs=512 seek=2 status=noxfer >/dev/null 2>&1) + ( dd if=/tmp/usr/lib/"$CHOOSEN_UBOOT"/u-boot.img of=$LOOP bs=1K seek=42 status=noxfer >/dev/null 2>&1) +elif [[ $BOARD == *udoo* ]] ; then + ( dd if=/tmp/usr/lib/"$CHOOSEN_UBOOT"/u-boot.imx of=$LOOP bs=1024 seek=1 conv=fsync >/dev/null 2>&1) +elif [[ $BOARD == *guitar* ]] ; then + ( dd if=/tmp/usr/lib/"$CHOOSEN_UBOOT"/bootloader.bin of=$LOOP bs=512 seek=4097 conv=fsync > /dev/null 2>&1) + ( dd if=/tmp/usr/lib/"$CHOOSEN_UBOOT"/u-boot-dtb.bin of=$LOOP bs=512 seek=6144 conv=fsync > /dev/null 2>&1) +else + ( dd if=/tmp/usr/lib/"$CHOOSEN_UBOOT"/u-boot-sunxi-with-spl.bin of=$LOOP bs=1024 seek=8 status=noxfer >/dev/null 2>&1) fi +if [ $? -ne 0 ]; then + display_alert "U-boot failed to install" "@host" "err" + exit 1 +fi +rm -r /tmp/usr sync sleep 3 losetup -d $LOOP - -# create documentation -#pandoc $SRC/lib/README.md $DEST/documentation/Home.md --standalone -o $DEST/output/$VERSION.pdf -V geometry:"top=2.54cm, bottom=2.54cm, left=3.17cm, right=3.17cm" -V geometry:paperwidth=21cm -V geometry:paperheight=29.7cm sync sleep 2 -mv $DEST/output/debian_rootfs.raw $DEST/output/$VERSION.raw -cd $DEST/output/ -# creating MD5 sum +mv $DEST/cache/tmprootfs.raw $DEST/cache/$VERSION.raw sync -md5sum $VERSION.raw > $VERSION.md5 +sleep 2 +# let's shrint it +shrinking_raw_image "$DEST/cache/$VERSION.raw" "15" +sleep 2 +cd $DEST/cache/ cp $SRC/lib/bin/imagewriter.exe . -md5sum imagewriter.exe > imagewriter.md5 -zip $VERSION.zip $VERSION.* readme.txt imagewriter.* -rm $VERSION.raw $VERSION.md5 imagewriter.* readme.txt +# sign with PGP +if [[ $GPG_PASS != "" ]] ; then + echo $GPG_PASS | gpg --passphrase-fd 0 --armor --detach-sign --batch --yes $VERSION.raw + echo $GPG_PASS | gpg --passphrase-fd 0 --armor --detach-sign --batch --yes imagewriter.exe + echo $GPG_PASS | gpg --passphrase-fd 0 --armor --detach-sign --batch --yes armbian.txt +fi +display_alert "Create and sign" "$VERSION.zip" "info" +mkdir -p $DEST/images +zip -FSq $DEST/images/$VERSION.zip $VERSION.raw* armbian.txt imagewriter.* +#display_alert "Uploading to server" "$VERSION.zip" "info" +rm -f $VERSION.raw *.asc imagewriter.* armbian.txt } diff --git a/compile.sh b/compile.sh new file mode 100644 index 000000000..1bf9a8241 --- /dev/null +++ b/compile.sh @@ -0,0 +1,84 @@ +#!/bin/bash +# +# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com +# +# This file is licensed under the terms of the GNU General Public +# License version 2. This program is licensed "as is" without any +# warranty of any kind, whether express or implied. +# +# This file is a part of tool chain https://github.com/igorpecovnik/lib +# +#-------------------------------------------------------------------------------------------------------------------------------- + +# method +KERNEL_ONLY="no" # build only kernel +KERNEL_CONFIGURE="no" # want to change my default configuration +CLEAN_LEVEL="" # 0 = make clean + del debs, 1 = only make clean, 2 = nothing + # 3 = choosing kernel if present 4 = del all output +# user +AFTERINSTALL="" # last command before closing image, example: apt-get install joe +DEST_LANG="en_US.UTF-8" # sl_SI.UTF-8, en_US.UTF-8 +CONSOLE_CHAR="UTF-8" +ROOTPWD="1234" # Must be changed @first login +MAINTAINER="Igor Pecovnik" # deb signature +MAINTAINERMAIL="igor.pecovnik@****l.com" # deb signature +GPG_PASS="" # signing password + +# advanced +KERNEL_KEEP_CONFIG="no" # overwrite kernel config before compilation +USE_CCACHE="yes" # use ccache for kernel compilation +FBTFT="yes" # https://github.com/notro/fbtft +EXTERNAL="yes" # compile extra drivers` +FORCE_CHECKOUT="yes" # igre manual changes to source +BUILD_ALL="no" # cycle through selected boards and make images +#-------------------------------------------------------------------------------------------------------------------------------- + +# source is where we start the script +SRC=$(pwd) + +# destination +DEST=$(pwd)/output + +# sources download +SOURCES=$(pwd)/sources + +#-------------------------------------------------------------------------------------------------------------------------------- +# To preserve proper librarires updating +#-------------------------------------------------------------------------------------------------------------------------------- +if [ -f "main.sh" ] && [ -d "bin" ]; then + echo -e "[\e[0;31m error \x1B[0m] Copy this file one level up, alter and run again." + exit +fi + + +#-------------------------------------------------------------------------------------------------------------------------------- +# Show warning for those who updated the script +#-------------------------------------------------------------------------------------------------------------------------------- +if [ -d "$DEST/output" ]; then + echo -e "[\e[0;35m warn \x1B[0m] Structure has been changed. Remove all files and start in a clean directory. \ + CTRL-C to exit or any key to continue. Only sources will be doubled ..." + read +fi + + +#-------------------------------------------------------------------------------------------------------------------------------- +# Get updates of the main build libraries +#-------------------------------------------------------------------------------------------------------------------------------- +apt-get -qq -y install git +if [ -d "$SRC/lib" ]; then + cd $SRC/lib + git pull +else + # download SDK + git clone --depth 1 https://github.com/igorpecovnik/lib +fi + + +#-------------------------------------------------------------------------------------------------------------------------------- +# Do we need to build all images +#-------------------------------------------------------------------------------------------------------------------------------- +if [ "$BUILD_ALL" == "yes" ]; then + source $SRC/lib/build-all.sh +else + source $SRC/lib/main.sh +fi diff --git a/config/aptly.conf b/config/aptly.conf new file mode 100644 index 000000000..fc5d690f0 --- /dev/null +++ b/config/aptly.conf @@ -0,0 +1,17 @@ +{ + "rootDir": "../output/repository", + "downloadConcurrency": 4, + "downloadSpeedLimit": 0, + "architectures": [], + "dependencyFollowSuggests": false, + "dependencyFollowRecommends": false, + "dependencyFollowAllVariants": false, + "dependencyFollowSource": false, + "gpgDisableSign": false, + "gpgDisableVerify": false, + "downloadSourcePackages": false, + "ppaDistributorID": "ubuntu", + "ppaCodename": "", + "S3PublishEndpoints": {}, + "SwiftPublishEndpoints": {} +} \ No newline at end of file diff --git a/config/aw-som-a20.fex b/config/aw-som-a20.fex new file mode 100644 index 000000000..4198bc778 --- /dev/null +++ b/config/aw-som-a20.fex @@ -0,0 +1,995 @@ +[product] +version = "100" +machine = "Aw-Som A20" + +[platform] +eraseflag = 0 + +[target] +boot_clock = 1008 +dcdc2_vol = 1400 +dcdc3_vol = 1250 +ldo2_vol = 3000 +ldo3_vol = 2800 +ldo4_vol = 2800 +power_start = 1 +storage_type = -1 + +[clock] +pll3 = 297 +pll4 = 300 +pll6 = 600 +pll7 = 297 +pll8 = 336 + +[card_boot] +logical_start = 40960 +sprite_gpio0 = + +[card0_boot_para] +card_ctrl = 0 +card_high_speed = 1 +card_line = 4 +sdc_d1 = port:PF00<2><1> +sdc_d0 = port:PF01<2><1> +sdc_clk = port:PF02<2><1> +sdc_cmd = port:PF03<2><1> +sdc_d3 = port:PF04<2><1> +sdc_d2 = port:PF05<2><1> + +[card2_boot_para] +card_ctrl = 2 +card_high_speed = 1 +card_line = 4 +sdc_cmd = port:PC06<3><1> +sdc_clk = port:PC07<3><1> +sdc_d0 = port:PC08<3><1> +sdc_d1 = port:PC09<3><1> +sdc_d2 = port:PC10<3><1> +sdc_d3 = port:PC11<3><1> + +[twi_para] +twi_port = 0 +twi_scl = port:PB00<2> +twi_sda = port:PB01<2> + +[uart_para] +uart_debug_port = 0 +uart_debug_tx = port:PB22<2><1> +uart_debug_rx = port:PB23<2><1> + +[uart_force_debug] +uart_debug_port = 0 +uart_debug_tx = port:PF02<4><1> +uart_debug_rx = port:PF04<4><1> + +[jtag_para] +jtag_enable = 0 +jtag_ms = port:PB14<3> +jtag_ck = port:PB15<3> +jtag_do = port:PB16<3> +jtag_di = port:PB17<3> + +[pm_para] +standby_mode = 1 + +[dram_para] +dram_baseaddr = 0x40000000 +dram_clk = 408 +dram_type = 3 +dram_rank_num = -1 +dram_chip_density = -1 +dram_io_width = -1 +dram_bus_width = -1 +dram_cas = 6 +dram_zq = 0x7b +dram_odt_en = 0 +dram_size = -1 +dram_tpr0 = 0x30926692 +dram_tpr1 = 0x1090 +dram_tpr2 = 0x1a0c8 +dram_tpr3 = 0x0 +dram_tpr4 = 0x1 +dram_tpr5 = 0x0 +dram_emr1 = 0x4 +dram_emr2 = 0x0 +dram_emr3 = 0x0 + +[mali_para] +mali_used = 1 +mali_clkdiv = 1 + +[emac_para] +emac_used = 1 +emac_rxd3 = port:PA00<2> +emac_rxd2 = port:PA01<2> +emac_rxd1 = port:PA02<2> +emac_rxd0 = port:PA03<2> +emac_txd3 = port:PA04<2> +emac_txd2 = port:PA05<2> +emac_txd1 = port:PA06<2> +emac_txd0 = port:PA07<2> +emac_rxclk = port:PA08<2> +emac_rxerr = port:PA09<2> +emac_rxdV = port:PA10<2> +emac_mdc = port:PA11<2> +emac_mdio = port:PA12<2> +emac_txen = port:PA13<2> +emac_txclk = port:PA14<2> +emac_crs = port:PA15<2> +emac_col = port:PA16<2> + +[twi0_para] +twi0_used = 1 +twi0_scl = port:PB00<2> +twi0_sda = port:PB01<2> + +[twi1_para] +twi1_used = 0 +twi1_scl = port:PB18<2> +twi1_sda = port:PB19<2> + +[twi2_para] +twi2_used = 0 +twi2_scl = port:PB20<2> +twi2_sda = port:PB21<2> + +[uart_para0] +uart_used = 1 +uart_port = 0 +uart_type = 2 +uart_tx = port:PB22<2><1> +uart_rx = port:PB23<2><1> + +[uart_para1] +uart_used = 0 +uart_port = 1 +uart_type = 8 +uart_tx = port:PA10<4><1> +uart_rx = port:PA11<4><1> +uart_rts = port:PA12<4><1> +uart_cts = port:PA13<4><1> +uart_dtr = port:PA14<4><1> +uart_dsr = port:PA15<4><1> +uart_dcd = port:PA16<4><1> +uart_ring = port:PA17<4><1> + +[uart_para2] +uart_used = 1 +uart_port = 2 +uart_type = 2 +uart_tx = port:PI18<3><1> +uart_rx = port:PI19<3><1> + +[uart_para3] +uart_used = 0 +uart_port = 3 +uart_type = 2 +uart_tx = port:PG10<4><1> +uart_rx = port:PG11<4><1> + +[uart_para4] +uart_used = 0 +uart_port = 4 +uart_type = 2 +uart_tx = port:PI10<4><1> +uart_rx = port:PI11<4><1> + +[uart_para5] +uart_used = 1 +uart_port = 5 +uart_type = 2 +uart_tx = port:PI10<3><1> +uart_rx = port:PI11<3><1> + +[uart_para6] +uart_used = 1 +uart_port = 6 +uart_type = 2 +uart_tx = port:PI12<3><1> +uart_rx = port:PI13<3><1> + +[uart_para7] +uart_used = 0 +uart_port = 7 +uart_type = 2 +uart_tx = port:PA14<4><1> +uart_rx = port:PA15<4><1> + +[spi0_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PI10<2> +spi_cs1 = port:PI14<2> +spi_sclk = port:PI11<2> +spi_mosi = port:PI12<2> +spi_miso = port:PI13<2> + +[spi1_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA00<3> +spi_cs1 = port:PA04<3> +spi_sclk = port:PA01<3> +spi_mosi = port:PA02<3> +spi_miso = port:PA03<3> + +[spi2_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PC19<3> +spi_cs1 = port:PB13<2> +spi_sclk = port:PC20<3> +spi_mosi = port:PC21<3> +spi_miso = port:PC22<3> + +[spi3_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA05<3> +spi_cs1 = port:PA09<3> +spi_sclk = port:PA06<3> +spi_mosi = port:PA07<3> +spi_miso = port:PA08<3> + +[ctp_para] +ctp_used = 0 +ctp_name = "gt811" +ctp_twi_id = 2 +ctp_twi_addr = 0x40 +ctp_screen_max_x = 1024 +ctp_screen_max_y = 600 +ctp_revert_x_flag = 0 +ctp_revert_y_flag = 0 +ctp_exchange_x_y_flag = 1 +ctp_firm = 1 +ctp_int_port = port:PH21<6> +ctp_wakeup = port:PB13<1><1> + +[ctp_list_para] +ctp_det_used = 0 +ft5x_ts = 0 +gt82x = 0 +gslX680 = 0 +gt9xx_ts = 0 +gt811 = 0 + +[tkey_para] +tkey_used = 0 +tkey_twi_id = 2 +tkey_twi_addr = 0x62 +tkey_int = port:PI13<6> + +[motor_para] +motor_used = 0 +motor_shake = port:PB03<1><1> + +[gpio_para] +gpio_used = 1 +gpio_num = 6 +gpio_pin_1 = port:PB10<1><1> +gpio_pin_2 = port:PB11<1><1> +gpio_pin_3 = port:PH18<6> +gpio_pin_4 = port:PH19<6> +gpio_pin_5 = port:PH20<6> +gpio_pin_6 = port:PH21<6> + +[gpio_init] +gpio_pin_1 = port:PB10<1><1> +gpio_pin_2 = port:PB11<1><1> +gpio_pin_3 = port:PH18<6> +gpio_pin_4 = port:PH19<6> +gpio_pin_5 = port:PH20<6> +gpio_pin_6 = port:PH21<6> + +[nand_para] +nand_used = 1 +nand_we = port:PC00<2> +nand_ale = port:PC01<2> +nand_cle = port:PC02<2> +nand_ce1 = port:PC03<2> +nand_ce0 = port:PC04<2> +nand_nre = port:PC05<2> +nand_rb0 = port:PC06<2> +nand_rb1 = port:PC07<2> +nand_d0 = port:PC08<2> +nand_d1 = port:PC09<2> +nand_d2 = port:PC10<2> +nand_d3 = port:PC11<2> +nand_d4 = port:PC12<2> +nand_d5 = port:PC13<2> +nand_d6 = port:PC14<2> +nand_d7 = port:PC15<2> +nand_wp = port:PC16<2> +nand_ce2 = port:PC17<2> +nand_ce3 = port:PC18<2> +nand_ce4 = +nand_ce5 = +nand_ce6 = +nand_ce7 = +nand_spi = port:PC23<3> +nand_ndqs = port:PC24<2> +good_block_ratio = 0 + +[disp_init] +disp_init_enable = 0 +disp_mode = 0 +screen0_output_type = 3 +screen0_output_mode = 4 +screen1_output_type = 0 +screen1_output_mode = 4 +fb0_width = 1024 +fb0_height = 768 +fb0_framebuffer_num = 2 +fb0_format = 10 +fb0_pixel_sequence = 0 +fb0_scaler_mode_enable = 1 +fb1_width = 1024 +fb1_height = 768 +fb1_framebuffer_num = 2 +fb1_format = 10 +fb1_pixel_sequence = 0 +fb1_scaler_mode_enable = 0 +lcd0_backlight = 197 +lcd1_backlight = 197 +lcd0_bright = 50 +lcd0_contrast = 50 +lcd0_saturation = 57 +lcd0_hue = 50 +lcd1_bright = 50 +lcd1_contrast = 50 +lcd1_saturation = 57 +lcd1_hue = 50 + +[lcd0_para] +lcd_used = 0 +lcd_x = 1024 +lcd_y = 600 +lcd_dclk_freq = 51 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 0 +lcd_pwm_freq = 10000 +lcd_pwm_pol = 1 +lcd_max_bright = 240 +lcd_min_bright = 64 +lcd_if = 0 +lcd_hbp = 158 +lcd_ht = 1344 +lcd_vbp = 25 +lcd_vt = 1270 +lcd_vspw = 3 +lcd_hspw = 20 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 1 +lcd_io_cfg0 = 0 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 0 +lcd_bl_en = port:PH07<1><0><1> +lcd_power_used = 0 +lcd_power = port:PH08<1><0><1> +lcd_pwm_used = 0 +lcd_pwm = port:PB02<2><0> +lcdd0 = port:PD00<2><0> +lcdd1 = port:PD01<2><0> +lcdd2 = port:PD02<2><0> +lcdd3 = port:PD03<2><0> +lcdd4 = port:PD04<2><0> +lcdd5 = port:PD05<2><0> +lcdd6 = port:PD06<2><0> +lcdd7 = port:PD07<2><0> +lcdd8 = port:PD08<2><0> +lcdd9 = port:PD09<2><0> +lcdd10 = port:PD10<2><0> +lcdd11 = port:PD11<2><0> +lcdd12 = port:PD12<2><0> +lcdd13 = port:PD13<2><0> +lcdd14 = port:PD14<2><0> +lcdd15 = port:PD15<2><0> +lcdd16 = port:PD16<2><0> +lcdd17 = port:PD17<2><0> +lcdd18 = port:PD18<2><0> +lcdd19 = port:PD19<2><0> +lcdd20 = port:PD20<2><0> +lcdd21 = port:PD21<2><0> +lcdd22 = port:PD22<2><0> +lcdd23 = port:PD23<2><0> +lcdclk = port:PD24<2><0> +lcdde = port:PD25<2><0> +lcdhsync = port:PD26<2><0> +lcdvsync = port:PD27<2><0> + +[lcd1_para] +lcd_used = 0 +lcd_x = 0 +lcd_y = 0 +lcd_dclk_freq = 0 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 1 +lcd_pwm_freq = 0 +lcd_pwm_pol = 0 +lcd_max_bright = 240 +lcd_min_bright = 64 +lcd_if = 0 +lcd_hbp = 0 +lcd_ht = 0 +lcd_vbp = 0 +lcd_vt = 0 +lcd_vspw = 0 +lcd_hspw = 0 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 0 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 0 +lcd_bl_en = +lcd_power_used = 0 +lcd_power = +lcd_pwm_used = 1 +lcd_pwm = port:PI03<2><0> +lcd_gpio_0 = +lcd_gpio_1 = +lcd_gpio_2 = +lcd_gpio_3 = +lcdd0 = port:PH00<2><0> +lcdd1 = port:PH01<2><0> +lcdd2 = port:PH02<2><0> +lcdd3 = port:PH03<2><0> +lcdd4 = port:PH04<2><0> +lcdd5 = port:PH05<2><0> +lcdd6 = port:PH06<2><0> +lcdd7 = port:PH07<2><0> +lcdd8 = port:PH08<2><0> +lcdd9 = port:PH09<2><0> +lcdd10 = port:PH10<2><0> +lcdd11 = port:PH11<2><0> +lcdd12 = port:PH12<2><0> +lcdd13 = port:PH13<2><0> +lcdd14 = port:PH14<2><0> +lcdd15 = port:PH15<2><0> +lcdd16 = port:PH16<2><0> +lcdd17 = port:PH17<2><0> +lcdd18 = port:PH18<2><0> +lcdd19 = port:PH19<2><0> +lcdd20 = port:PH20<2><0> +lcdd21 = port:PH21<2><0> +lcdd22 = port:PH22<2><0> +lcdd23 = port:PH23<2><0> +lcdclk = port:PH24<2><0> +lcdde = port:PH25<2><0> +lcdhsync = port:PH26<2><0> +lcdvsync = port:PH27<2><0> + +[tv_out_dac_para] +dac_used = 0 +dac0_src = 4 +dac1_src = 5 +dac2_src = 6 +dac3_src = 0 + +[hdmi_para] +hdmi_used = 0 + +[camera_list_para] +camera_list_para_used = 0 +ov7670 = 0 +gc0308 = 1 +gt2005 = 1 +hi704 = 0 +sp0838 = 0 +mt9m112 = 0 +mt9m113 = 0 +ov2655 = 0 +hi253 = 0 +gc0307 = 0 +mt9d112 = 0 +ov5640 = 0 +gc2015 = 0 +ov2643 = 0 +gc0329 = 0 +gc0309 = 0 +tvp5150 = 0 +s5k4ec = 0 +ov5650_mv9335 = 0 +siv121d = 0 +gc2035 = 0 + +[csi0_para] +csi_used = 0 +csi_dev_qty = 2 +csi_stby_mode = 0 +csi_mname = "gc0308" +csi_twi_id = 1 +csi_twi_addr = 0x42 +csi_if = 0 +csi_vflip = 0 +csi_hflip = 0 +csi_iovdd = "axp20_pll" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = 2800 +csi_vol_dvdd = +csi_vol_avdd = +csi_flash_pol = 0 +csi_mname_b = "gt2005" +csi_twi_id_b = 1 +csi_twi_addr_b = 0x78 +csi_if_b = 0 +csi_vflip_b = 0 +csi_hflip_b = 0 +csi_iovdd_b = "axp20_pll" +csi_avdd_b = "" +csi_dvdd_b = "" +csi_vol_iovdd_b = 2800 +csi_vol_avdd_b = +csi_vol_dvdd_b = +csi_flash_pol_b = 0 +csi_pck = port:PE00<3> +csi_ck = port:PE01<3> +csi_hsync = port:PE02<3> +csi_vsync = port:PE03<3> +csi_d0 = port:PE04<3> +csi_d1 = port:PE05<3> +csi_d2 = port:PE06<3> +csi_d3 = port:PE07<3> +csi_d4 = port:PE08<3> +csi_d5 = port:PE09<3> +csi_d6 = port:PE10<3> +csi_d7 = port:PE11<3> +csi_reset = port:PH14<1><0> +csi_power_en = port:PH17<1><0> +csi_stby = port:PH19<1><0> +csi_flash = +csi_af_en = +csi_reset_b = port:PH14<1><0> +csi_power_en_b = port:PH17<1><0> +csi_stby_b = port:PH18<1><0> +csi_flash_b = +csi_af_en_b = + +[csi1_para] +csi_used = 0 +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "gc0308" +csi_if = 0 +csi_iovdd = "axp20_pll" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = 2800 +csi_vol_dvdd = +csi_vol_avdd = +csi_vflip = 0 +csi_hflip = 0 +csi_flash_pol = 0 +csi_facing = 1 +csi_twi_id = 1 +csi_twi_addr = 0x42 +csi_pck = port:PG00<3> +csi_ck = port:PG01<3> +csi_hsync = port:PG02<3> +csi_vsync = port:PG03<3> +csi_d0 = port:PG04<3> +csi_d1 = port:PG05<3> +csi_d2 = port:PG06<3> +csi_d3 = port:PG07<3> +csi_d4 = port:PG08<3> +csi_d5 = port:PG09<3> +csi_d6 = port:PG10<3> +csi_d7 = port:PG11<3> +csi_reset = port:PH13<1><0> +csi_power_en = port:PH16<1><0> +csi_stby = port:PH19<1><0> + +[tvout_para] +tvout_used = 0 +tvout_channel_num = 1 + +[tvin_para] +tvin_used = 0 +tvin_channel_num = 4 + +[pwm0_para] +pwm_used = 1 +pwm_period = 20 +pwm_duty_percent = 50 + +[pwm1_para] +pwm_used = 1 +pwm_period = 20 +pwm_duty_percent = 50 + +[sata_para] +sata_used = 0 +sata_power_en = port:PB08<1><0> + +[mmc0_para] +sdc_used = 1 +sdc_detmode = 1 +sdc_buswidth = 4 +sdc_clk = port:PF02<2><1><2> +sdc_cmd = port:PF03<2><1><2> +sdc_d0 = port:PF01<2><1><2> +sdc_d1 = port:PF00<2><1><2> +sdc_d2 = port:PF05<2><1><2> +sdc_d3 = port:PF04<2><1><2> +sdc_det = port:PB09<0><1> +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc1_para] +sdc_used = 0 +sdc_detmode = 4 +sdc_buswidth = 4 +sdc_clk = port:PG00<2><1><2> +sdc_cmd = port:PG01<2><1><2> +sdc_d0 = port:PG02<2><1><2> +sdc_d1 = port:PG03<2><1><2> +sdc_d2 = port:PG04<2><1><2> +sdc_d3 = port:PG05<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc2_para] +sdc_used = 0 +sdc_detmode = 3 +sdc_buswidth = 4 +sdc_cmd = port:PC06<3><1><2> +sdc_clk = port:PC07<3><1><2> +sdc_d0 = port:PC08<3><1><2> +sdc_d1 = port:PC09<3><1><2> +sdc_d2 = port:PC10<3><1><2> +sdc_d3 = port:PC11<3><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc3_para] +sdc_used = 1 +sdc_detmode = 3 +sdc_buswidth = 4 +sdc_cmd = port:PI04<2><1><2> +sdc_clk = port:PI05<2><1><2> +sdc_d0 = port:PI06<2><1><2> +sdc_d1 = port:PI07<2><1><2> +sdc_d2 = port:PI08<2><1><2> +sdc_d3 = port:PI09<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[ms_para] +ms_used = 0 +ms_bs = port:PH06<5> +ms_clk = port:PH07<5> +ms_d0 = port:PH08<5> +ms_d1 = port:PH09<5> +ms_d2 = port:PH10<5> +ms_d3 = port:PH11<5> +ms_det = + +[smc_para] +smc_used = 0 +smc_rst = port:PH13<5> +smc_vppen = port:PH14<5> +smc_vppp = port:PH15<5> +smc_det = port:PH16<5> +smc_vccen = port:PH17<5> +smc_sck = port:PH18<5> +smc_sda = port:PH19<5> + +[ps2_0_para] +ps2_used = 0 +ps2_scl = port:PI20<2><1> +ps2_sda = port:PI21<2><1> + +[ps2_1_para] +ps2_used = 0 +ps2_scl = port:PI14<3><1> +ps2_sda = port:PI15<3><1> + +[can_para] +can_used = 0 +can_tx = port:PA16<3> +can_rx = port:PA17<3> + +[keypad_para] +kp_used = 0 +kp_in_size = 8 +kp_out_size = 8 +kp_in0 = port:PH08<4><1> +kp_in1 = port:PH09<4><1> +kp_in2 = port:PH10<4><1> +kp_in3 = port:PH11<4><1> +kp_in4 = port:PH14<4><1> +kp_in5 = port:PH15<4><1> +kp_in6 = port:PH16<4><1> +kp_in7 = port:PH17<4><1> +kp_out0 = port:PH18<4><1> +kp_out1 = port:PH19<4><1> +kp_out2 = port:PH22<4><1> +kp_out3 = port:PH23<4><1> +kp_out4 = port:PH24<4><1> +kp_out5 = port:PH25<4><1> +kp_out6 = port:PH26<4><1> +kp_out7 = port:PH27<4><1> + +[usbc0] +usb_used = 1 +usb_port_type = 2 +usb_detect_type = 1 +usb_id_gpio = port:PC19<0><1> +usb_det_vbus_gpio = "axp_ctrl" +usb_det_vbus_gpio = port:PC20<0><0> +usb_drv_vbus_gpio = port:PC21<1><0><0> +usb_restrict_gpio = 0 +usb_host_init_state = 1 +usb_restric_flag = 0 +usb_restric_voltage = 3550000 +usb_restric_capacity = 5 + +[usbc1] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PB10<1><0><0> +usb_restrict_gpio = +usb_host_init_state = 1 +usb_restric_flag = 0 + +[usbc2] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PB11<1><0><0> +usb_restrict_gpio = +usb_host_init_state = 1 +usb_restric_flag = 0 + +[usb_feature] +vendor_id = 6353 +mass_storage_id = 1 +adb_id = 2 +manufacturer_name = "USB Developer" +product_name = "Android" +serial_number = "20080411" + +[msc_feature] +vendor_name = "USB 2.0" +product_name = "USB Flash Driver" +release = 100 +luns = 2 + +[gsensor_para] +gsensor_used = 0 +gsensor_twi_id = 1 +gsensor_int1 = +gsensor_int2 = + +[gsensor_list_para] +gsensor_det_used = 0 +bma250 = 1 +mma8452 = 1 +mma7660 = 1 +mma865x = 1 +afa750 = 1 +lis3de_acc = 1 +lis3dh_acc = 1 +kxtik = 1 +dmard10 = 0 +dmard06 = 1 +mxc622x = 1 +fxos8700 = 1 +lsm303d = 1 + +[gps_para] +gps_used = 0 +gps_spi_id = 2 +gps_spi_cs_num = 0 +gps_lradc = 1 +gps_clk = port:PI00<2> +gps_sign = port:PI01<2> +gps_mag = port:PI02<2> +gps_vcc_en = port:PC22<1><0> +gps_osc_en = port:PI14<1><0> +gps_rx_en = port:PI15<1><0> + +[wifi_para] +wifi_used = 1 +wifi_usbc_id = 2 +wifi_usbc_type = 1 +wifi_power = "" + +[usb_wifi_para] +usb_wifi_used = 1 +usb_wifi_usbc_num = 2 + +[3g_para] +3g_used = 0 +3g_usbc_num = 2 +3g_uart_num = 0 +3g_pwr = +3g_wakeup = +3g_int = + +[gy_para] +gy_used = 0 +gy_twi_id = 1 +gy_twi_addr = 0 +gy_int1 = port:PH18<6><1> +gy_int2 = port:PH19<6><1> + +[ls_para] +ls_used = 0 +ls_twi_id = 1 +ls_twi_addr = 0 +ls_int = port:PH20<6><1> + +[compass_para] +compass_used = 0 +compass_twi_id = 1 +compass_twi_addr = 0 +compass_int = port:PI13<6><1> + +[bt_para] +bt_used = 1 + +[i2s_para] +i2s_used = 0 +i2s_channel = 2 +i2s_mclk = port:PB05<2><1> +i2s_bclk = port:PB06<2><1> +i2s_lrclk = port:PB07<2><1> +i2s_dout0 = port:PB08<2><1> +i2s_dout1 = +i2s_dout2 = +i2s_dout3 = +i2s_din = port:PB12<2><1> + +[spdif_para] +spdif_used = 0 +spdif_mclk = +spdif_dout = port:PB13<4><1> +spdif_din = + +[audio_para] +audio_used = 1 +audio_pa_ctrl = port:PH15<1><1> + +[switch_para] +switch_used = 1 + +[leds_para] +leds_used = 1 +leds_num = 2 +leds_pin_1 = port:PE06<1><0> +leds_name_1 = "green:pe06:led1" +leds_default_1 = 1 +leds_trigger_1 = "cpu0" +leds_pin_2 = port:PE07<1><0> +leds_name_2 = "yellow:pe07:led2" +leds_default_2 = 1 +leds_trigger_2 = "heartbeat" + +[ir_para] +ir_used = 0 +ir0_rx = port:PB04<2> + +[pmu_para] +pmu_used = 1 +pmu_twi_addr = 52 +pmu_twi_id = 0 +pmu_irq_id = 32 +pmu_battery_rdc = 120 +pmu_battery_cap = 2200 +pmu_init_chgcur = 500 +pmu_earlysuspend_chgcur = 600 +pmu_suspend_chgcur = 1000 +pmu_resume_chgcur = 300 +pmu_shutdown_chgcur = 1000 +pmu_init_chgvol = 4200 +pmu_init_chgend_rate = 15 +pmu_init_chg_enabled = 1 +pmu_init_adc_freq = 100 +pmu_init_adc_freqc = 100 +pmu_init_chg_pretime = 50 +pmu_init_chg_csttime = 720 +pmu_bat_para1 = 0 +pmu_bat_para2 = 0 +pmu_bat_para3 = 0 +pmu_bat_para4 = 0 +pmu_bat_para5 = 5 +pmu_bat_para6 = 11 +pmu_bat_para7 = 13 +pmu_bat_para8 = 15 +pmu_bat_para9 = 19 +pmu_bat_para10 = 32 +pmu_bat_para11 = 50 +pmu_bat_para12 = 58 +pmu_bat_para13 = 71 +pmu_bat_para14 = 81 +pmu_bat_para15 = 89 +pmu_bat_para16 = 100 +pmu_usbvol_limit = 1 +pmu_usbcur_limit = 0 +pmu_usbvol = 4000 +pmu_usbcur = 0 +pmu_usbvol_pc = 4200 +pmu_usbcur_pc = 0 +pmu_pwroff_vol = 3300 +pmu_pwron_vol = 2900 +pmu_pekoff_time = 6000 +pmu_pekoff_en = 1 +pmu_peklong_time = 1500 +pmu_pekon_time = 1000 +pmu_pwrok_time = 64 +pmu_pwrnoe_time = 2000 +pmu_intotp_en = 1 +pmu_used2 = 0 +pmu_adpdet = port:PH02<0> +pmu_init_chgcur2 = 400 +pmu_earlysuspend_chgcur2 = 600 +pmu_suspend_chgcur2 = 1200 +pmu_resume_chgcur2 = 400 +pmu_shutdown_chgcur2 = 1200 +pmu_suspendpwroff_vol = 3500 +pmu_batdeten = 1 +pmu_backupen = 1 +pmu_backup_rtc_enabled = 1 +pmu_backup_chgvol = 3000 +pmu_backup_chgcur = 50 + +[recovery_key] +key_min = 4 +key_max = 40 + +[dvfs_table] +max_freq = 1008000000 +min_freq = 312000000 +normal_freq = 528000000 +LV_count = 7 +LV1_freq = 1008000000 +LV1_volt = 1450 +LV2_freq = 912000000 +LV2_volt = 1425 +LV3_freq = 864000000 +LV3_volt = 1350 +LV4_freq = 720000000 +LV4_volt = 1250 +LV5_freq = 528000000 +LV5_volt = 1150 +LV6_freq = 312000000 +LV6_volt = 1100 +LV7_freq = 144000000 +LV7_volt = 1050 + diff --git a/config/bananapi.fex b/config/bananapi.fex index 37023bfc1..8b11660e1 100644 --- a/config/bananapi.fex +++ b/config/bananapi.fex @@ -277,6 +277,7 @@ ctp_firm = 1 ctp_int_port = port:PH21<6> ctp_wakeup = port:PB13<1><1> + [ctp_list_para] ctp_det_used = 0 ft5x_ts = 0 @@ -895,19 +896,12 @@ gps_vcc_en = port:PC22<1><0> gps_osc_en = port:PI14<1><0> gps_rx_en = port:PI15<1><0> -[wifi_para] -wifi_used = 0 -wifi_sdc_id = 3 -wifi_usbc_id = 2 -wifi_usbc_type = 1 -wifi_mod_sel = 6 -wifi_power = "" -ap6xxx_wl_regon = port:PH09<1><0> -ap6xxx_wl_host_wake = port:PH10<0><0> -ap6xxx_bt_regon = port:PH18<1><0> -ap6xxx_bt_wake = port:PH24<1><0> -ap6xxx_bt_host_wake = port:PH25<0><0> -ap6xxx_lpo = port:PI12<4><1><1> +[sdio_wifi_pro_para] +sdio_wifi_pro_used = 1 +sdio_wifi_pro_sdc_id = 3 +sdio_wifi_pro_mod_sel = 7 +ap6xxx_wl_regon = port:PH22<1><0> +ap6xxx_wl_vdd_en = port:PH27<1><0> [usb_wifi_para] usb_wifi_used = 1 @@ -948,7 +942,7 @@ bt_gpio = port:PI21<1> bt_rst = port:PB05<1> [i2s_para] -i2s_used = 1 +i2s_used = 0 i2s_channel = 2 i2s_mclk = port:PB05<2><1> i2s_bclk = port:PB06<2><1> diff --git a/config/bananapilcd7.fex b/config/bananapilcd7.fex new file mode 100644 index 000000000..88f550772 --- /dev/null +++ b/config/bananapilcd7.fex @@ -0,0 +1,1066 @@ +[product] +version = "100" +machine = "bananapi" + +[platform] +eraseflag = 0 + +[target] +boot_clock = 912 +dcdc2_vol = 1450 +dcdc3_vol = 1300 +ldo2_vol = 3000 +ldo3_vol = 2800 +ldo4_vol = 2800 +storage_type = 0 + +[clock] +pll3 = 297 +pll4 = 300 +pll6 = 600 +pll7 = 297 +pll8 = 336 + +[card_boot] +logical_start = 40960 +sprite_gpio0 = + +[card0_boot_para] +card_ctrl = 0 +card_high_speed = 1 +card_line = 4 +sdc_d1 = port:PF00<2><1> +sdc_d0 = port:PF01<2><1> +sdc_clk = port:PF02<2><1> +sdc_cmd = port:PF03<2><1> +sdc_d3 = port:PF04<2><1> +sdc_d2 = port:PF05<2><1> + +[card2_boot_para] +card_ctrl = 2 +card_high_speed = 1 +card_line = 4 +sdc_cmd = port:PC06<3><1> +sdc_clk = port:PC07<3><1> +sdc_d0 = port:PC08<3><1> +sdc_d1 = port:PC09<3><1> +sdc_d2 = port:PC10<3><1> +sdc_d3 = port:PC11<3><1> + +[twi_para] +twi_port = 0 +twi_scl = port:PB00<2> +twi_sda = port:PB01<2> + +[uart_para] +uart_debug_port = 0 +uart_debug_tx = port:PB22<2><1> +uart_debug_rx = port:PB23<2><1> + +[uart_force_debug] +uart_debug_port = 0 +uart_debug_tx = port:PF02<4><1> +uart_debug_rx = port:PF04<4><1> + +[jtag_para] +jtag_enable = 0 +jtag_ms = port:PB14<3> +jtag_ck = port:PB15<3> +jtag_do = port:PB16<3> +jtag_di = port:PB17<3> + +[pm_para] +standby_mode = 0 + +[dram_para] +dram_baseaddr = 0x40000000 +dram_clk = 432 +dram_type = 3 +dram_rank_num = 1 +dram_chip_density = 4096 +dram_io_width = 16 +dram_bus_width = 32 +dram_cas = 9 +dram_zq = 0x7f +dram_odt_en = 0 +dram_size = 1024 +dram_tpr0 = 0x42d899b7 +dram_tpr1 = 0xa090 +dram_tpr2 = 0x22a00 +dram_tpr3 = 0x0 +dram_tpr4 = 0x1 +dram_tpr5 = 0x0 +dram_emr1 = 0x4 +dram_emr2 = 0x10 +dram_emr3 = 0x0 + +[mali_para] +mali_used = 1 +mali_clkdiv = 1 + +[gmac_para] +gmac_used = 1 +gmac_rxd3 = port:PA00<5><3> +gmac_rxd2 = port:PA01<5><3> +gmac_rxd1 = port:PA02<5><3> +gmac_rxd0 = port:PA03<5><3> +gmac_txd3 = port:PA04<5><3> +gmac_txd2 = port:PA05<5><3> +gmac_txd1 = port:PA06<5><3> +gmac_txd0 = port:PA07<5><3> +gmac_rxclk = port:PA08<5><3> +gmac_rxerr = port:PA09<0><3> +gmac_rxctl = port:PA10<5><3> +gmac_mdc = port:PA11<5><3> +gmac_mdio = port:PA12<5><3> +gmac_txctl = port:PA13<5><3> +gmac_txclk = port:PA14<0><3> +gmac_txck = port:PA15<5><3> +gmac_clkin = port:PA16<5><3> +gmac_txerr = port:PA17<0><3> + +[gmac_phy_power] +gmac_phy_power_en = port:PH23<1><0> + +[twi0_para] +twi0_used = 1 +twi0_scl = port:PB00<2> +twi0_sda = port:PB01<2> + +[twi1_para] +twi1_used = 1 +twi1_scl = port:PB18<2> +twi1_sda = port:PB19<2> + +[twi2_para] +twi2_used = 1 +twi2_scl = port:PB20<2> +twi2_sda = port:PB21<2> + +[twi3_para] +twi3_used = 1 +twi3_scl = port:PI00<3> +twi3_sda = port:PI01<3> + +[uart_para0] +uart_used = 1 +uart_port = 0 +uart_type = 2 +uart_tx = port:PB22<2><1> +uart_rx = port:PB23<2><1> + +[uart_para1] +uart_used = 0 +uart_port = 1 +uart_type = 8 +uart_tx = port:PA10<4><1> +uart_rx = port:PA11<4><1> +uart_rts = port:PA12<4><1> +uart_cts = port:PA13<4><1> +uart_dtr = port:PA14<4><1> +uart_dsr = port:PA15<4><1> +uart_dcd = port:PA16<4><1> +uart_ring = port:PA17<4><1> + +[uart_para2] +uart_used = 1 +uart_port = 2 +uart_type = 4 +uart_tx = port:PI18<3><1> +uart_rx = port:PI19<3><1> +uart_rts = port:PI16<3><1> +uart_cts = port:PI17<3><1> + +[uart_para3] +uart_used = 1 +uart_port = 3 +uart_type = 2 +uart_tx = port:PH00<4><1> +uart_rx = port:PH01<4><1> + +[uart_para4] +uart_used = 0 +uart_port = 4 +uart_type = 2 +uart_tx = port:PH04<4><1> +uart_rx = port:PH05<4><1> + +[uart_para5] +uart_used = 0 +uart_port = 5 +uart_type = 2 +uart_tx = port:PH06<4><1> +uart_rx = port:PH07<4><1> + +[uart_para6] +uart_used = 0 +uart_port = 6 +uart_type = 2 +uart_tx = port:PA12<4><1> +uart_rx = port:PA13<4><1> + +[uart_para7] +uart_used = 1 +uart_port = 7 +uart_type = 2 +uart_tx = port:PI20<3><1> +uart_rx = port:PI21<3><1> + +[spi0_para] +spi_used = 1 +spi_cs_bitmap = 3 +spi_cs0 = port:PI10<2> +spi_cs1 = port:PI14<2> +spi_sclk = port:PI11<2> +spi_mosi = port:PI12<2> +spi_miso = port:PI13<2> + +[spi1_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA00<3> +spi_cs1 = port:PA04<3> +spi_sclk = port:PA01<3> +spi_mosi = port:PA02<3> +spi_miso = port:PA03<3> + +[spi2_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PC19<3> +spi_cs1 = port:PB13<2> +spi_sclk = port:PC20<3> +spi_mosi = port:PC21<3> +spi_miso = port:PC22<3> + +[spi3_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA05<3> +spi_cs1 = port:PA09<3> +spi_sclk = port:PA06<3> +spi_mosi = port:PA07<3> +spi_miso = port:PA08<3> + +[spi_devices] +spi_dev_num = 2 + +[spi_board0] +modalias = "spidev" +max_speed_hz = 12000000 +bus_num = 0 +chip_select = 0 +mode = 3 +full_duplex = 0 +manual_cs = 0 + +[spi_board1] +modalias = "spidev" +max_speed_hz = 12000000 +bus_num = 0 +chip_select = 1 +mode = 3 +full_duplex = 0 +manual_cs = 0 + +[ctp_para] +ctp_used = 1 +ctp_name = "ft5x_ts" +ctp_twi_id = 3 +ctp_twi_addr = 0x38 +ctp_screen_max_x = 1024 +ctp_screen_max_y = 600 +ctp_revert_x_flag = 0 +ctp_revert_y_flag = 0 +ctp_exchange_x_y_flag = 0 +ctp_firm = 1 +ctp_int_port = port:PH09<6> +ctp_wakeup = port:PH07<1><1> + +ctp_io_port = port:PH09<0> + +[ctp_list_para] +ctp_det_used = 1 +ft5x_ts = 1 +gt82x = 0 +gslX680 = 0 +gt9xx_ts = 0 +gt811 = 0 + +[tkey_para] +tkey_used = 0 +tkey_twi_id = 2 +tkey_twi_addr = 0x62 +tkey_int = port:PI13<6> + +[motor_para] +motor_used = 0 +motor_shake = port:PB03<1><1> + +[gpio_para] +gpio_used = 1 +gpio_num = 88 +gpio_pin_1 = port:PB20<1> +gpio_pin_2 = port:PB21<1> +gpio_pin_3 = port:PB20<1> +gpio_pin_4 = port:PI03<1> +gpio_pin_5 = port:PB22<1> +gpio_pin_6 = port:PB23<1> +gpio_pin_7 = port:PI14<1> +gpio_pin_8 = port:PI10<1> +gpio_pin_9 = port:PI13<1> +gpio_pin_10 = port:PI12<1> +gpio_pin_11 = port:PI11<1> +gpio_pin_12 = port:PH05<1> +gpio_pin_13 = port:PH03<1> +gpio_pin_14 = port:PH00<1> +gpio_pin_15 = port:PH01<1> +gpio_pin_16 = port:PH01<1> +gpio_pin_17 = port:PI19<1> +gpio_pin_18 = port:PH02<1> +gpio_pin_19 = port:PH02<1> +gpio_pin_20 = port:PI20<1> +gpio_pin_21 = port:PI21<1> +gpio_pin_22 = port:PI17<1> +gpio_pin_23 = port:PH20<1> +gpio_pin_24 = port:PH21<1> +gpio_pin_25 = port:PI16<1> +gpio_pin_26 = port:PI16<1> +gpio_pin_27 = port:PI18<1> +gpio_pin_28 = port:PH05<1> +gpio_pin_29 = port:PI21<1> +gpio_pin_30 = port:PH03<1> +gpio_pin_31 = port:PI20<1> +gpio_pin_32 = port:PH17<1> +gpio_pin_33 = port:PB19<1> +gpio_pin_34 = port:PB18<1> +gpio_pin_35 = port:PH19<1> +gpio_pin_36 = port:PE00<1> +gpio_pin_37 = port:PH16<1> +gpio_pin_38 = port:PE01<1> +gpio_pin_39 = port:PH14<1> +gpio_pin_40 = port:PE03<1> +gpio_pin_41 = port:PE02<1> +gpio_pin_42 = port:PH18<1> +gpio_pin_43 = port:PH11<1> +gpio_pin_44 = port:PE04<1> +gpio_pin_45 = port:PE05<1> +gpio_pin_46 = port:PE06<1> +gpio_pin_47 = port:PE07<1> +gpio_pin_48 = port:PE08<1> +gpio_pin_49 = port:PE09<1> +gpio_pin_50 = port:PE10<1> +gpio_pin_51 = port:PE11<1> +gpio_pin_52 = port:PH13<1> +gpio_pin_53 = port:PI01<1> +gpio_pin_54 = port:PI00<1> +gpio_pin_55 = port:PH07<1> +gpio_pin_56 = port:PH08<1> +gpio_pin_57 = port:PB02<1> +gpio_pin_58 = port:PH09<1> +gpio_pin_59 = port:PD25<1> +gpio_pin_60 = port:PD27<1> +gpio_pin_61 = port:PD26<1> +gpio_pin_62 = port:PH06<1> +gpio_pin_63 = port:PD24<1> +gpio_pin_64 = port:PD23<1> +gpio_pin_65 = port:PD22<1> +gpio_pin_66 = port:PD21<1> +gpio_pin_67 = port:PD20<1> +gpio_pin_68 = port:PD19<1> +gpio_pin_69 = port:PD18<1> +gpio_pin_70 = port:PD17<1> +gpio_pin_71 = port:PD16<1> +gpio_pin_72 = port:PH12<1> +gpio_pin_73 = port:PD00<1> +gpio_pin_74 = port:PD01<1> +gpio_pin_75 = port:PD02<1> +gpio_pin_76 = port:PD03<1> +gpio_pin_77 = port:PD04<1> +gpio_pin_78 = port:PD05<1> +gpio_pin_79 = port:PD06<1> +gpio_pin_80 = port:PD07<1> +gpio_pin_81 = port:PD08<1> +gpio_pin_82 = port:PD09<1> +gpio_pin_83 = port:PD10<1> +gpio_pin_84 = port:PD11<1> +gpio_pin_85 = port:PD12<1> +gpio_pin_86 = port:PD13<1> +gpio_pin_87 = port:PD14<1> +gpio_pin_88 = port:PD15<1> + +[nand_para] +nand_used = 0 +nand_we = port:PC00<2> +nand_ale = port:PC01<2> +nand_cle = port:PC02<2> +nand_ce1 = port:PC03<2> +nand_ce0 = port:PC04<2> +nand_nre = port:PC05<2> +nand_rb0 = port:PC06<2> +nand_rb1 = port:PC07<2> +nand_d0 = port:PC08<2> +nand_d1 = port:PC09<2> +nand_d2 = port:PC10<2> +nand_d3 = port:PC11<2> +nand_d4 = port:PC12<2> +nand_d5 = port:PC13<2> +nand_d6 = port:PC14<2> +nand_d7 = port:PC15<2> +nand_wp = port:PC16<2> +nand_ce2 = port:PC17<2> +nand_ce3 = port:PC18<2> +nand_ce4 = +nand_ce5 = +nand_ce6 = +nand_ce7 = +nand_spi = port:PC23<3> +nand_ndqs = port:PC24<2> +good_block_ratio = 0 + +[disp_init] +disp_init_enable = 1 +disp_mode = 0 +screen0_output_type = 1 +screen0_output_mode = 4 +screen1_output_type = 2 +screen1_output_mode = 11 +fb0_framebuffer_num = 2 +fb0_format = 10 +fb0_pixel_sequence = 0 +fb0_scaler_mode_enable = 1 +fb1_framebuffer_num = 2 +fb1_format = 10 +fb1_pixel_sequence = 0 +fb1_scaler_mode_enable = 0 +lcd0_backlight = 197 +lcd1_backlight = 197 +lcd0_bright = 50 +lcd0_contrast = 50 +lcd0_saturation = 57 +lcd0_hue = 50 +lcd1_bright = 50 +lcd1_contrast = 50 +lcd1_saturation = 57 +lcd1_hue = 50 + +[lcd0_para] +lcd_used = 1 +lcd_x = 1024 +lcd_y = 600 +lcd_dclk_freq = 55 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 0 +lcd_pwm_freq = 22000 +lcd_pwm_pol = 0 +lcd_max_bright = 240 +lcd_min_bright = 64 +lcd_if = 3 +lcd_hbp = 150 +lcd_ht = 1344 +lcd_vbp = 20 +lcd_vt = 1270 +lcd_vspw = 10 +lcd_hspw = 50 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 268435456 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 1 +lcd_bl_en = port:PH08<1><0><1> +lcd_power_used = 1 +lcd_power = port:PH12<1><0><1> +lcd_pwm_used = 1 +lcd_pwm = port:PB02<2><0> +lcdd0 = port:PD00<3><0> +lcdd1 = port:PD01<3><0> +lcdd2 = port:PD02<3><0> +lcdd3 = port:PD03<3><0> +lcdd4 = port:PD04<3><0> +lcdd5 = port:PD05<3><0> +lcdd6 = port:PD06<3><0> +lcdd7 = port:PD07<3><0> +lcdd8 = port:PD08<3><0> +lcdd9 = port:PD09<3><0> +lcdd10 = port:PD10<2><0> +lcdd11 = port:PD11<2><0> +lcdd12 = port:PD12<2><0> +lcdd13 = port:PD13<2><0> +lcdd14 = port:PD14<2><0> +lcdd15 = port:PD15<2><0> +lcdd16 = port:PD16<2><0> +lcdd17 = port:PD17<2><0> +lcdd18 = port:PD18<2><0> +lcdd19 = port:PD19<2><0> +lcdd20 = port:PD20<2><0> +lcdd21 = port:PD21<2><0> +lcdd22 = port:PD22<2><0> +lcdd23 = port:PD23<2><0> +lcdclk = port:PD24<2><0> +lcdde = port:PD25<2><0><3> +lcdhsync = port:PD26<2><0><3> +lcdvsync = port:PD27<2><0><3> + +[lcd1_para] +lcd_used = 0 +lcd_x = 0 +lcd_y = 0 +lcd_dclk_freq = 0 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 1 +lcd_pwm_freq = 0 +lcd_pwm_pol = 0 +lcd_max_bright = 240 +lcd_min_bright = 64 +lcd_if = 0 +lcd_hbp = 0 +lcd_ht = 0 +lcd_vbp = 0 +lcd_vt = 0 +lcd_vspw = 0 +lcd_hspw = 0 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 0 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 0 +lcd_bl_en = +lcd_power_used = 0 +lcd_power = +lcd_pwm_used = 1 +lcd_pwm = port:PI03<2><0> +lcd_gpio_0 = +lcd_gpio_1 = +lcd_gpio_2 = +lcd_gpio_3 = +lcdd0 = port:PH00<2><0> +lcdd1 = port:PH01<2><0> +lcdd2 = port:PH02<2><0> +lcdd3 = port:PH03<2><0> +lcdd4 = port:PH04<2><0> +lcdd5 = port:PH05<2><0> +lcdd6 = port:PH06<2><0> +lcdd7 = port:PH07<2><0> +lcdd8 = port:PH08<2><0> +lcdd9 = port:PH09<2><0> +lcdd10 = port:PH10<2><0> +lcdd11 = port:PH11<2><0> +lcdd12 = port:PH12<2><0> +lcdd13 = port:PH13<2><0> +lcdd14 = port:PH14<2><0> +lcdd15 = port:PH15<2><0> +lcdd16 = port:PH16<2><0> +lcdd17 = port:PH17<2><0> +lcdd18 = port:PH18<2><0> +lcdd19 = port:PH19<2><0> +lcdd20 = port:PH20<2><0> +lcdd21 = port:PH21<2><0> +lcdd22 = port:PH22<2><0> +lcdd23 = port:PH23<2><0> +lcdclk = port:PH24<2><0> +lcdde = port:PH25<2><0> +lcdhsync = port:PH26<2><0> +lcdvsync = port:PH27<2><0> + +[tv_out_dac_para] +dac_used = 0 +dac0_src = 4 +dac1_src = 5 +dac2_src = 6 +dac3_src = 0 + +[hdmi_para] +hdmi_used = 1 + +[csi0_para] +csi_used = 1 +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "ov5640" +csi_twi_id = 1 +csi_twi_addr = 0x78 +csi_if = 0 +csi_vflip = 1 +csi_hflip = 0 +csi_iovdd = "axp20_pll" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = 2800 +csi_vol_dvdd = +csi_vol_avdd = +csi_flash_pol = 0 +csi_facing = 0 +csi_pck = port:PE00<3> +csi_ck = port:PE01<3> +csi_hsync = port:PE02<3> +csi_vsync = port:PE03<3> +csi_d0 = port:PE04<3> +csi_d1 = port:PE05<3> +csi_d2 = port:PE06<3> +csi_d3 = port:PE07<3> +csi_d4 = port:PE08<3> +csi_d5 = port:PE09<3> +csi_d6 = port:PE10<3> +csi_d7 = port:PE11<3> +csi_reset = port:PH14<1><0> +csi_power_en = port:PH16<1><0> +csi_stby = port:PH19<1><0> + +[csi1_para] +csi_used = 0 +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "gc0308" +csi_if = 0 +csi_iovdd = "axp20_pll" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = 2800 +csi_vol_dvdd = +csi_vol_avdd = +csi_vflip = 0 +csi_hflip = 0 +csi_flash_pol = 0 +csi_facing = 1 +csi_twi_id = 1 +csi_twi_addr = 0x42 +csi_pck = port:PG00<3> +csi_ck = port:PG01<3> +csi_hsync = port:PG02<3> +csi_vsync = port:PG03<3> +csi_d0 = port:PG04<3> +csi_d1 = port:PG05<3> +csi_d2 = port:PG06<3> +csi_d3 = port:PG07<3> +csi_d4 = port:PG08<3> +csi_d5 = port:PG09<3> +csi_d6 = port:PG10<3> +csi_d7 = port:PG11<3> +csi_reset = port:PH13<1><0> +csi_power_en = port:PH16<1><0> +csi_stby = port:PH18<1><0> + +[camera_list_para] +camera_list_para_used = 1 +ov7670 = 0 +gc0308 = 0 +gt2005 = 0 +hi704 = 0 +sp0838 = 0 +mt9m112 = 0 +mt9m113 = 0 +ov2655 = 0 +hi253 = 0 +gc0307 = 0 +mt9d112 = 0 +ov5640 = 1 +gc2015 = 0 +ov2643 = 0 +gc0329 = 0 +gc0309 = 0 +tvp5150 = 0 +s5k4ec = 0 +ov5650_mv9335 = 0 +siv121d = 0 +gc2035 = 0 + +[tvout_para] +tvout_used = 0 +tvout_channel_num = 1 + +[tvin_para] +tvin_used = 0 +tvin_channel_num = 4 + +[sata_para] +sata_used = 1 +sata_power_en = + +[mmc0_para] +sdc_used = 1 +sdc_detmode = 1 +sdc_buswidth = 4 +sdc_clk = port:PF02<2><1><2> +sdc_cmd = port:PF03<2><1><2> +sdc_d0 = port:PF01<2><1><2> +sdc_d1 = port:PF00<2><1><2> +sdc_d2 = port:PF05<2><1><2> +sdc_d3 = port:PF04<2><1><2> +sdc_det = port:PH10<0><1> +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc1_para] +sdc_used = 0 +sdc_detmode = 4 +sdc_buswidth = 4 +sdc_clk = port:PG00<2><1><2> +sdc_cmd = port:PG01<2><1><2> +sdc_d0 = port:PG02<2><1><2> +sdc_d1 = port:PG03<2><1><2> +sdc_d2 = port:PG04<2><1><2> +sdc_d3 = port:PG05<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc2_para] +sdc_used = 0 +sdc_detmode = 3 +sdc_buswidth = 4 +sdc_cmd = port:PC06<3><1><2> +sdc_clk = port:PC07<3><1><2> +sdc_d0 = port:PC08<3><1><2> +sdc_d1 = port:PC09<3><1><2> +sdc_d2 = port:PC10<3><1><2> +sdc_d3 = port:PC11<3><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc3_para] +sdc_used = 0 +sdc_detmode = 4 +sdc_buswidth = 4 +sdc_cmd = port:PI04<2><1><2> +sdc_clk = port:PI05<2><1><2> +sdc_d0 = port:PI06<2><1><2> +sdc_d1 = port:PI07<2><1><2> +sdc_d2 = port:PI08<2><1><2> +sdc_d3 = port:PI09<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 1 +sdc_regulator = "none" + +[ms_para] +ms_used = 0 +ms_bs = port:PH06<5> +ms_clk = port:PH07<5> +ms_d0 = port:PH08<5> +ms_d1 = port:PH09<5> +ms_d2 = port:PH10<5> +ms_d3 = port:PH11<5> +ms_det = + +[smc_para] +smc_used = 0 +smc_rst = port:PH13<5> +smc_vppen = port:PH14<5> +smc_vppp = port:PH15<5> +smc_det = port:PH16<5> +smc_vccen = port:PH17<5> +smc_sck = port:PH18<5> +smc_sda = port:PH19<5> + +[ps2_0_para] +ps2_used = 0 +ps2_scl = port:PI20<2><1> +ps2_sda = port:PI21<2><1> + +[ps2_1_para] +ps2_used = 0 +ps2_scl = port:PI14<3><1> +ps2_sda = port:PI15<3><1> + +[can_para] +can_used = 0 +can_tx = port:PA16<3> +can_rx = port:PA17<3> + +[keypad_para] +kp_used = 0 +kp_in_size = 8 +kp_out_size = 8 +kp_in0 = port:PH08<4><1> +kp_in1 = port:PH09<4><1> +kp_in2 = port:PH10<4><1> +kp_in3 = port:PH11<4><1> +kp_in4 = port:PH14<4><1> +kp_in5 = port:PH15<4><1> +kp_in6 = port:PH16<4><1> +kp_in7 = port:PH17<4><1> +kp_out0 = port:PH18<4><1> +kp_out1 = port:PH19<4><1> +kp_out2 = port:PH22<4><1> +kp_out3 = port:PH23<4><1> +kp_out4 = port:PH24<4><1> +kp_out5 = port:PH25<4><1> +kp_out6 = port:PH26<4><1> +kp_out7 = port:PH27<4><1> + +[usbc0] +usb_used = 1 +usb_port_type = 2 +usb_detect_type = 0 +usb_id_gpio = port:PH04<0><1> +usb_det_vbus_gpio = port:PH05<0><0> +usb_drv_vbus_gpio = port:PB09<1><0><0> +usb_restric_gpio = port:PH00<1><0><0> +usb_host_init_state = 0 +usb_restric_flag = 0 +usb_restric_voltage = 3550000 +usb_restric_capacity = 5 + +[usbc1] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PH06<1><0><0> +usb_restrict_gpio = +usb_host_init_state = 1 +usb_restric_flag = 0 + +[usbc2] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PH03<1><0><0> +usb_restrict_gpio = +usb_host_init_state = 1 +usb_restric_flag = 0 + +[usb_feature] +vendor_id = 6353 +mass_storage_id = 1 +adb_id = 2 +manufacturer_name = "USB Developer" +product_name = "Android" +serial_number = "20080411" + +[msc_feature] +vendor_name = "USB 2.0" +product_name = "USB Flash Driver" +release = 100 +luns = 3 + +[gsensor_para] +gsensor_used = 0 +gsensor_twi_id = 1 +gsensor_int1 = +gsensor_int2 = + +[gsensor_list_para] +gsensor_det_used = 0 +bma250 = 1 +mma8452 = 1 +mma7660 = 1 +mma865x = 1 +afa750 = 1 +lis3de_acc = 1 +lis3dh_acc = 1 +kxtik = 1 +dmard10 = 0 +dmard06 = 1 +mxc622x = 1 +fxos8700 = 1 +lsm303d = 1 + +[gps_para] +gps_used = 0 +gps_spi_id = 2 +gps_spi_cs_num = 0 +gps_lradc = 1 +gps_clk = port:PI00<2> +gps_sign = port:PI01<2> +gps_mag = port:PI02<2> +gps_vcc_en = port:PC22<1><0> +gps_osc_en = port:PI14<1><0> +gps_rx_en = port:PI15<1><0> + +[sdio_wifi_pro_para] +sdio_wifi_pro_used = 1 +sdio_wifi_pro_sdc_id = 3 +sdio_wifi_pro_mod_sel = 7 +ap6xxx_wl_regon = port:PH22<1><0> +ap6xxx_wl_vdd_en = port:PH27<1><0> + +[usb_wifi_para] +usb_wifi_used = 1 +usb_wifi_usbc_num = 2 + +[3g_para] +3g_used = 0 +3g_usbc_num = 2 +3g_uart_num = 0 +3g_pwr = +3g_wakeup = +3g_int = + +[gy_para] +gy_used = 0 +gy_twi_id = 1 +gy_twi_addr = 0 +gy_int1 = port:PH18<6><1> +gy_int2 = port:PH19<6><1> + +[ls_para] +ls_used = 0 +ls_twi_id = 1 +ls_twi_addr = 0 +ls_int = port:PH20<6><1> + +[compass_para] +compass_used = 0 +compass_twi_id = 1 +compass_twi_addr = 0 +compass_int = port:PI13<6><1> + +[bt_para] +bt_used = 0 +bt_uart_id = 2 +bt_wakeup = port:PI20<1> +bt_gpio = port:PI21<1> +bt_rst = port:PB05<1> + +[i2s_para] +i2s_used = 0 +i2s_channel = 2 +i2s_mclk = port:PB05<2><1> +i2s_bclk = port:PB06<2><1> +i2s_lrclk = port:PB07<2><1> +i2s_dout0 = port:PB08<2><1> +i2s_dout1 = +i2s_dout2 = +i2s_dout3 = +i2s_din = port:PB12<2><1> + +[spdif_para] +spdif_used = 0 +spdif_mclk = +spdif_dout = port:PB13<4><1> +spdif_din = + +[audio_para] +audio_used = 1 +capture_used = 1 +audio_pa_ctrl = port:PH15<1><1> + +[switch_para] +switch_used = 0 + +[leds_para] +leds_used = 1 +leds_num = 1 +leds_pin_1 = port:PH24<1><0> +leds_name_1 = "green:ph24:led1" +leds_default_1 = 1 +leds_trigger_1 = "mmc0" + +[ir_para] +ir_used = 1 +ir0_rx = port:PB04<2> + +[pmu_para] +pmu_used = 1 +pmu_twi_addr = 52 +pmu_twi_id = 0 +pmu_irq_id = 32 +pmu_battery_rdc = 100 +pmu_battery_cap = 3200 +pmu_init_chgcur = 300 +pmu_earlysuspend_chgcur = 600 +pmu_suspend_chgcur = 1000 +pmu_resume_chgcur = 300 +pmu_shutdown_chgcur = 1000 +pmu_init_chgvol = 4200 +pmu_init_chgend_rate = 15 +pmu_init_chg_enabled = 1 +pmu_init_adc_freq = 100 +pmu_init_adc_freqc = 100 +pmu_init_chg_pretime = 50 +pmu_init_chg_csttime = 720 +pmu_bat_para1 = 0 +pmu_bat_para2 = 0 +pmu_bat_para3 = 0 +pmu_bat_para4 = 0 +pmu_bat_para5 = 5 +pmu_bat_para6 = 8 +pmu_bat_para7 = 11 +pmu_bat_para8 = 22 +pmu_bat_para9 = 33 +pmu_bat_para10 = 43 +pmu_bat_para11 = 50 +pmu_bat_para12 = 59 +pmu_bat_para13 = 71 +pmu_bat_para14 = 83 +pmu_bat_para15 = 92 +pmu_bat_para16 = 100 +pmu_usbvol_limit = 1 +pmu_usbcur_limit = 0 +pmu_usbvol = 4000 +pmu_usbcur = 0 +pmu_usbvol_pc = 4400 +pmu_usbcur_pc = 500 +pmu_pwroff_vol = 3300 +pmu_pwron_vol = 2900 +pmu_pekoff_time = 4000 +pmu_pekoff_en = 1 +pmu_peklong_time = 1500 +pmu_pekon_time = 1000 +pmu_pwrok_time = 64 +pmu_pwrnoe_time = 2000 +pmu_intotp_en = 1 +pmu_backupen = 1 +pmu_used2 = 0 +pmu_adpdet = port:PH02<0> +pmu_init_chgcur2 = 400 +pmu_earlysuspend_chgcur2 = 600 +pmu_suspend_chgcur2 = 1200 +pmu_resume_chgcur2 = 400 +pmu_shutdown_chgcur2 = 1200 +pmu_suspendpwroff_vol = 3500 +pmu_batdeten = 1 + +[recovery_key] +key_min = 4 +key_max = 10 + +[dvfs_table] +max_freq = 912000000 +min_freq = 720000000 +LV_count = 7 +LV1_freq = 1008000000 +LV1_volt = 1450 +LV2_freq = 912000000 +LV2_volt = 1425 +LV3_freq = 864000000 +LV3_volt = 1350 +LV4_freq = 720000000 +LV4_volt = 1250 +LV5_freq = 528000000 +LV5_volt = 1150 +LV6_freq = 312000000 +LV6_volt = 1100 +LV7_freq = 144000000 +LV7_volt = 1050 + diff --git a/config/bananapipro.fex b/config/bananapipro.fex new file mode 100644 index 000000000..9955aa9c6 --- /dev/null +++ b/config/bananapipro.fex @@ -0,0 +1,1066 @@ +[product] +version = "100" +machine = "bananapro" + +[platform] +eraseflag = 0 + +[target] +boot_clock = 912 +dcdc2_vol = 1450 +dcdc3_vol = 1300 +ldo2_vol = 3000 +ldo3_vol = 2800 +ldo4_vol = 2800 +storage_type = 0 + +[clock] +pll3 = 297 +pll4 = 300 +pll6 = 600 +pll7 = 297 +pll8 = 336 + +[card_boot] +logical_start = 40960 +sprite_gpio0 = + +[card0_boot_para] +card_ctrl = 0 +card_high_speed = 1 +card_line = 4 +sdc_d1 = port:PF00<2><1> +sdc_d0 = port:PF01<2><1> +sdc_clk = port:PF02<2><1> +sdc_cmd = port:PF03<2><1> +sdc_d3 = port:PF04<2><1> +sdc_d2 = port:PF05<2><1> + +[card2_boot_para] +card_ctrl = 2 +card_high_speed = 1 +card_line = 4 +sdc_cmd = port:PC06<3><1> +sdc_clk = port:PC07<3><1> +sdc_d0 = port:PC08<3><1> +sdc_d1 = port:PC09<3><1> +sdc_d2 = port:PC10<3><1> +sdc_d3 = port:PC11<3><1> + +[twi_para] +twi_port = 0 +twi_scl = port:PB00<2> +twi_sda = port:PB01<2> + +[uart_para] +uart_debug_port = 0 +uart_debug_tx = port:PB22<2><1> +uart_debug_rx = port:PB23<2><1> + +[uart_force_debug] +uart_debug_port = 0 +uart_debug_tx = port:PF02<4><1> +uart_debug_rx = port:PF04<4><1> + +[jtag_para] +jtag_enable = 0 +jtag_ms = port:PB14<3> +jtag_ck = port:PB15<3> +jtag_do = port:PB16<3> +jtag_di = port:PB17<3> + +[pm_para] +standby_mode = 0 + +[dram_para] +dram_baseaddr = 0x40000000 +dram_clk = 432 +dram_type = 3 +dram_rank_num = 1 +dram_chip_density = 4096 +dram_io_width = 16 +dram_bus_width = 32 +dram_cas = 9 +dram_zq = 0x7f +dram_odt_en = 0 +dram_size = 1024 +dram_tpr0 = 0x42d899b7 +dram_tpr1 = 0xa090 +dram_tpr2 = 0x22a00 +dram_tpr3 = 0x0 +dram_tpr4 = 0x1 +dram_tpr5 = 0x0 +dram_emr1 = 0x4 +dram_emr2 = 0x10 +dram_emr3 = 0x0 + +[mali_para] +mali_used = 1 +mali_clkdiv = 1 + +[gmac_para] +gmac_used = 1 +gmac_rxd3 = port:PA00<5><3> +gmac_rxd2 = port:PA01<5><3> +gmac_rxd1 = port:PA02<5><3> +gmac_rxd0 = port:PA03<5><3> +gmac_txd3 = port:PA04<5><3> +gmac_txd2 = port:PA05<5><3> +gmac_txd1 = port:PA06<5><3> +gmac_txd0 = port:PA07<5><3> +gmac_rxclk = port:PA08<5><3> +gmac_rxerr = port:PA09<0><3> +gmac_rxctl = port:PA10<5><3> +gmac_mdc = port:PA11<5><3> +gmac_mdio = port:PA12<5><3> +gmac_txctl = port:PA13<5><3> +gmac_txclk = port:PA14<0><3> +gmac_txck = port:PA15<5><3> +gmac_clkin = port:PA16<5><3> +gmac_txerr = port:PA17<0><3> + +[gmac_phy_power] +gmac_phy_power_en = port:PH23<1><0> + +[twi0_para] +twi0_used = 1 +twi0_scl = port:PB00<2> +twi0_sda = port:PB01<2> + +[twi1_para] +twi1_used = 1 +twi1_scl = port:PB18<2> +twi1_sda = port:PB19<2> + +[twi2_para] +twi2_used = 1 +twi2_scl = port:PB20<2> +twi2_sda = port:PB21<2> + +[twi3_para] +twi3_used = 1 +twi3_scl = port:PI00<3> +twi3_sda = port:PI01<3> + +[uart_para0] +uart_used = 1 +uart_port = 0 +uart_type = 2 +uart_tx = port:PB22<2><1> +uart_rx = port:PB23<2><1> + +[uart_para1] +uart_used = 0 +uart_port = 1 +uart_type = 8 +uart_tx = port:PA10<4><1> +uart_rx = port:PA11<4><1> +uart_rts = port:PA12<4><1> +uart_cts = port:PA13<4><1> +uart_dtr = port:PA14<4><1> +uart_dsr = port:PA15<4><1> +uart_dcd = port:PA16<4><1> +uart_ring = port:PA17<4><1> + +[uart_para2] +uart_used = 1 +uart_port = 2 +uart_type = 4 +uart_tx = port:PI18<3><1> +uart_rx = port:PI19<3><1> +uart_rts = port:PI16<3><1> +uart_cts = port:PI17<3><1> + +[uart_para3] +uart_used = 0 +uart_port = 3 +uart_type = 2 +uart_tx = port:PH00<4><1> +uart_rx = port:PH01<4><1> + +[uart_para4] +uart_used = 1 +uart_port = 4 +uart_type = 2 +uart_tx = port:PH04<4><1> +uart_rx = port:PH05<4><1> + +[uart_para5] +uart_used = 0 +uart_port = 5 +uart_type = 2 +uart_tx = port:PH06<4><1> +uart_rx = port:PH07<4><1> + +[uart_para6] +uart_used = 0 +uart_port = 6 +uart_type = 2 +uart_tx = port:PA12<4><1> +uart_rx = port:PA13<4><1> + +[uart_para7] +uart_used = 1 +uart_port = 7 +uart_type = 2 +uart_tx = port:PI20<3><1> +uart_rx = port:PI21<3><1> + +[spi0_para] +spi_used = 1 +spi_cs_bitmap = 3 +spi_cs0 = port:PI10<2> +spi_cs1 = port:PI14<2> +spi_sclk = port:PI11<2> +spi_mosi = port:PI12<2> +spi_miso = port:PI13<2> + +[spi1_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA00<3> +spi_cs1 = port:PA04<3> +spi_sclk = port:PA01<3> +spi_mosi = port:PA02<3> +spi_miso = port:PA03<3> + +[spi2_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PC19<3> +spi_cs1 = port:PB13<2> +spi_sclk = port:PC20<3> +spi_mosi = port:PC21<3> +spi_miso = port:PC22<3> + +[spi3_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA05<3> +spi_cs1 = port:PA09<3> +spi_sclk = port:PA06<3> +spi_mosi = port:PA07<3> +spi_miso = port:PA08<3> + +[spi_devices] +spi_dev_num = 2 + +[spi_board0] +modalias = "spidev" +max_speed_hz = 12000000 +bus_num = 0 +chip_select = 0 +mode = 3 +full_duplex = 0 +manual_cs = 0 + +[spi_board1] +modalias = "spidev" +max_speed_hz = 12000000 +bus_num = 0 +chip_select = 1 +mode = 3 +full_duplex = 0 +manual_cs = 0 + +[ctp_para] +ctp_used = 0 +ctp_name = "ft5x_ts" +ctp_twi_id = 3 +ctp_twi_addr = 0x38 +ctp_screen_max_x = 1024 +ctp_screen_max_y = 600 +ctp_revert_x_flag = 0 +ctp_revert_y_flag = 0 +ctp_exchange_x_y_flag = 0 +ctp_firm = 1 +ctp_int_port = port:PH09<6> +ctp_wakeup = port:PH07<1><1> +ctp_io_port = port:PH09<0> + +[ctp_list_para] +ctp_det_used = 1 +ft5x_ts = 1 +gt82x = 0 +gslX680 = 0 +gt9xx_ts = 0 +gt811 = 0 + +[tkey_para] +tkey_used = 0 +tkey_twi_id = 2 +tkey_twi_addr = 0x62 +tkey_int = port:PI13<6> + +[motor_para] +motor_used = 0 +motor_shake = port:PB03<1><1> + +[gpio_para] +gpio_used = 1 +gpio_num = 86 +gpio_pin_1 = port:PI00<1> +gpio_pin_2 = port:PB21<1> +gpio_pin_3 = port:PB20<1> +gpio_pin_4 = port:PH02<1> +gpio_pin_5 = port:PB03<1> +gpio_pin_6 = port:PI21<1> +gpio_pin_7 = port:PI14<1> +gpio_pin_8 = port:PI10<1> +gpio_pin_9 = port:PI13<1> +gpio_pin_10 = port:PI12<1> +gpio_pin_11 = port:PI11<1> +gpio_pin_12 = port:PI20<1> +gpio_pin_13 = port:PB13<1> +gpio_pin_14 = port:PH04<1> +gpio_pin_15 = port:PH05<1> +gpio_pin_16 = port:PB06<1> +gpio_pin_17 = port:PI19<1> +gpio_pin_18 = port:PI03<1> +gpio_pin_19 = port:PB07<1> +gpio_pin_20 = port:PB12<1> +gpio_pin_21 = port:PB08<1> +gpio_pin_22 = port:PI17<1> +gpio_pin_23 = port:PH20<1> +gpio_pin_24 = port:PH21<1> +gpio_pin_25 = port:PI16<1> +gpio_pin_26 = port:PB05<1> +gpio_pin_27 = port:PI18<1> +gpio_pin_28 = port:PI01<1> +gpio_pin_29 = port:PH17<1> +gpio_pin_30 = port:PB19<1> +gpio_pin_31 = port:PB18<1> +gpio_pin_32 = port:PH19<1> +gpio_pin_33 = port:PE00<1> +gpio_pin_34 = port:PH16<1> +gpio_pin_35 = port:PE01<1> +gpio_pin_36 = port:PH14<1> +gpio_pin_37 = port:PE03<1> +gpio_pin_38 = port:PE02<1> +gpio_pin_39 = port:PH18<1> +gpio_pin_40 = port:PH11<1> +gpio_pin_41 = port:PE04<1> +gpio_pin_42 = port:PE05<1> +gpio_pin_43 = port:PE06<1> +gpio_pin_44 = port:PE07<1> +gpio_pin_45 = port:PE08<1> +gpio_pin_46 = port:PE09<1> +gpio_pin_47 = port:PE10<1> +gpio_pin_48 = port:PE11<1> +gpio_pin_49 = port:PH13<1> +gpio_pin_50 = port:PI01<1> +gpio_pin_51 = port:PI00<1> +gpio_pin_52 = port:PH07<1> +gpio_pin_53 = port:PH08<1> +gpio_pin_54 = port:PB02<1> +gpio_pin_55 = port:PH09<1> +gpio_pin_56 = port:PD25<1> +gpio_pin_57 = port:PD27<1> +gpio_pin_58 = port:PD26<1> +gpio_pin_59 = port:PH06<1> +gpio_pin_60 = port:PD24<1> +gpio_pin_61 = port:PD23<1> +gpio_pin_62 = port:PD22<1> +gpio_pin_63 = port:PD21<1> +gpio_pin_64 = port:PD20<1> +gpio_pin_65 = port:PD19<1> +gpio_pin_66 = port:PD18<1> +gpio_pin_67 = port:PD17<1> +gpio_pin_68 = port:PD16<1> +gpio_pin_69 = port:PH12<1> +gpio_pin_70 = port:PD00<1> +gpio_pin_71 = port:PD01<1> +gpio_pin_72 = port:PD02<1> +gpio_pin_73 = port:PD03<1> +gpio_pin_74 = port:PD04<1> +gpio_pin_75 = port:PD05<1> +gpio_pin_76 = port:PD06<1> +gpio_pin_77 = port:PD07<1> +gpio_pin_78 = port:PD08<1> +gpio_pin_79 = port:PD09<1> +gpio_pin_80 = port:PD10<1> +gpio_pin_81 = port:PD11<1> +gpio_pin_82 = port:PD12<1> +gpio_pin_83 = port:PD13<1> +gpio_pin_84 = port:PD14<1> +gpio_pin_85 = port:PD15<1> +gpio_pin_86 = port:PH15<0><0> + +[nand_para] +nand_used = 0 +nand_we = port:PC00<2> +nand_ale = port:PC01<2> +nand_cle = port:PC02<2> +nand_ce1 = port:PC03<2> +nand_ce0 = port:PC04<2> +nand_nre = port:PC05<2> +nand_rb0 = port:PC06<2> +nand_rb1 = port:PC07<2> +nand_d0 = port:PC08<2> +nand_d1 = port:PC09<2> +nand_d2 = port:PC10<2> +nand_d3 = port:PC11<2> +nand_d4 = port:PC12<2> +nand_d5 = port:PC13<2> +nand_d6 = port:PC14<2> +nand_d7 = port:PC15<2> +nand_wp = port:PC16<2> +nand_ce2 = port:PC17<2> +nand_ce3 = port:PC18<2> +nand_ce4 = +nand_ce5 = +nand_ce6 = +nand_ce7 = +nand_spi = port:PC23<3> +nand_ndqs = port:PC24<2> +good_block_ratio = 0 + +[disp_init] +disp_init_enable = 1 +disp_mode = 0 +screen0_output_type = 3 +screen0_output_mode = 5 +screen1_output_type = 2 +screen1_output_mode = 11 +fb0_framebuffer_num = 2 +fb0_format = 10 +fb0_pixel_sequence = 0 +fb0_scaler_mode_enable = 1 +fb1_framebuffer_num = 2 +fb1_format = 10 +fb1_pixel_sequence = 0 +fb1_scaler_mode_enable = 0 +lcd0_backlight = 197 +lcd1_backlight = 197 +lcd0_bright = 50 +lcd0_contrast = 50 +lcd0_saturation = 57 +lcd0_hue = 50 +lcd1_bright = 50 +lcd1_contrast = 50 +lcd1_saturation = 57 +lcd1_hue = 50 + +[lcd0_para] +lcd_used = 0 +lcd_x = 1024 +lcd_y = 600 +lcd_dclk_freq = 55 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 0 +lcd_pwm_freq = 22000 +lcd_pwm_pol = 0 +lcd_max_bright = 240 +lcd_min_bright = 64 +lcd_if = 3 +lcd_hbp = 150 +lcd_ht = 1344 +lcd_vbp = 20 +lcd_vt = 1270 +lcd_vspw = 10 +lcd_hspw = 50 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 268435456 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 1 +lcd_bl_en = port:PH07<1><0><1> +lcd_power_used = 1 +lcd_power = port:PH08<1><0><1> +lcd_pwm_used = 1 +lcd_pwm = port:PB02<2><0> +lcdd0 = port:PD00<3><0> +lcdd1 = port:PD01<3><0> +lcdd2 = port:PD02<3><0> +lcdd3 = port:PD03<3><0> +lcdd4 = port:PD04<3><0> +lcdd5 = port:PD05<3><0> +lcdd6 = port:PD06<3><0> +lcdd7 = port:PD07<3><0> +lcdd8 = port:PD08<3><0> +lcdd9 = port:PD09<3><0> +lcdd10 = port:PD10<2><0> +lcdd11 = port:PD11<2><0> +lcdd12 = port:PD12<2><0> +lcdd13 = port:PD13<2><0> +lcdd14 = port:PD14<2><0> +lcdd15 = port:PD15<2><0> +lcdd16 = port:PD16<2><0> +lcdd17 = port:PD17<2><0> +lcdd18 = port:PD18<2><0> +lcdd19 = port:PD19<2><0> +lcdd20 = port:PD20<2><0> +lcdd21 = port:PD21<2><0> +lcdd22 = port:PD22<2><0> +lcdd23 = port:PD23<2><0> +lcdclk = port:PD24<2><0> +lcdde = port:PD25<2><0><3> +lcdhsync = port:PD26<2><0><3> +lcdvsync = port:PD27<2><0><3> + +[lcd1_para] +lcd_used = 0 +lcd_x = 0 +lcd_y = 0 +lcd_dclk_freq = 0 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 1 +lcd_pwm_freq = 0 +lcd_pwm_pol = 0 +lcd_max_bright = 240 +lcd_min_bright = 64 +lcd_if = 0 +lcd_hbp = 0 +lcd_ht = 0 +lcd_vbp = 0 +lcd_vt = 0 +lcd_vspw = 0 +lcd_hspw = 0 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 0 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 0 +lcd_bl_en = +lcd_power_used = 0 +lcd_power = +lcd_pwm_used = 1 +lcd_pwm = port:PI03<2><0> +lcd_gpio_0 = +lcd_gpio_1 = +lcd_gpio_2 = +lcd_gpio_3 = +lcdd0 = port:PH00<2><0> +lcdd1 = port:PH01<2><0> +lcdd2 = port:PH02<2><0> +lcdd3 = port:PH03<2><0> +lcdd4 = port:PH04<2><0> +lcdd5 = port:PH05<2><0> +lcdd6 = port:PH06<2><0> +lcdd7 = port:PH07<2><0> +lcdd8 = port:PH08<2><0> +lcdd9 = port:PH09<2><0> +lcdd10 = port:PH10<2><0> +lcdd11 = port:PH11<2><0> +lcdd12 = port:PH12<2><0> +lcdd13 = port:PH13<2><0> +lcdd14 = port:PH14<2><0> +lcdd15 = port:PH15<2><0> +lcdd16 = port:PH16<2><0> +lcdd17 = port:PH17<2><0> +lcdd18 = port:PH18<2><0> +lcdd19 = port:PH19<2><0> +lcdd20 = port:PH20<2><0> +lcdd21 = port:PH21<2><0> +lcdd22 = port:PH22<2><0> +lcdd23 = port:PH23<2><0> +lcdclk = port:PH24<2><0> +lcdde = port:PH25<2><0> +lcdhsync = port:PH26<2><0> +lcdvsync = port:PH27<2><0> + +[tv_out_dac_para] +dac_used = 0 +dac0_src = 4 +dac1_src = 5 +dac2_src = 6 +dac3_src = 0 + +[hdmi_para] +hdmi_used = 1 + +[csi0_para] +csi_used = 1 +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "ov5640" +csi_twi_id = 1 +csi_twi_addr = 0x78 +csi_if = 0 +csi_vflip = 1 +csi_hflip = 0 +csi_iovdd = "axp20_pll" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = 2800 +csi_vol_dvdd = +csi_vol_avdd = +csi_flash_pol = 0 +csi_facing = 0 +csi_pck = port:PE00<3> +csi_ck = port:PE01<3> +csi_hsync = port:PE02<3> +csi_vsync = port:PE03<3> +csi_d0 = port:PE04<3> +csi_d1 = port:PE05<3> +csi_d2 = port:PE06<3> +csi_d3 = port:PE07<3> +csi_d4 = port:PE08<3> +csi_d5 = port:PE09<3> +csi_d6 = port:PE10<3> +csi_d7 = port:PE11<3> +csi_reset = port:PH14<1><0> +csi_power_en = port:PH16<1><0> +csi_stby = port:PH19<1><0> + +[csi1_para] +csi_used = 0 +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "gc0308" +csi_if = 0 +csi_iovdd = "axp20_pll" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = 2800 +csi_vol_dvdd = +csi_vol_avdd = +csi_vflip = 0 +csi_hflip = 0 +csi_flash_pol = 0 +csi_facing = 1 +csi_twi_id = 1 +csi_twi_addr = 0x42 +csi_pck = port:PG00<3> +csi_ck = port:PG01<3> +csi_hsync = port:PG02<3> +csi_vsync = port:PG03<3> +csi_d0 = port:PG04<3> +csi_d1 = port:PG05<3> +csi_d2 = port:PG06<3> +csi_d3 = port:PG07<3> +csi_d4 = port:PG08<3> +csi_d5 = port:PG09<3> +csi_d6 = port:PG10<3> +csi_d7 = port:PG11<3> +csi_reset = port:PH13<1><0> +csi_power_en = port:PH16<1><0> +csi_stby = port:PH18<1><0> + +[camera_list_para] +camera_list_para_used = 1 +ov7670 = 0 +gc0308 = 0 +gt2005 = 0 +hi704 = 0 +sp0838 = 0 +mt9m112 = 0 +mt9m113 = 0 +ov2655 = 0 +hi253 = 0 +gc0307 = 0 +mt9d112 = 0 +ov5640 = 1 +gc2015 = 0 +ov2643 = 0 +gc0329 = 0 +gc0309 = 0 +tvp5150 = 0 +s5k4ec = 0 +ov5650_mv9335 = 0 +siv121d = 0 +gc2035 = 0 + +[tvout_para] +tvout_used = 0 +tvout_channel_num = 1 + +[tvin_para] +tvin_used = 0 +tvin_channel_num = 4 + +[sata_para] +sata_used = 1 +sata_power_en = + +[mmc0_para] +sdc_used = 1 +sdc_detmode = 1 +sdc_buswidth = 4 +sdc_clk = port:PF02<2><1><2> +sdc_cmd = port:PF03<2><1><2> +sdc_d0 = port:PF01<2><1><2> +sdc_d1 = port:PF00<2><1><2> +sdc_d2 = port:PF05<2><1><2> +sdc_d3 = port:PF04<2><1><2> +sdc_det = port:PH10<0><1> +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc1_para] +sdc_used = 0 +sdc_detmode = 4 +sdc_buswidth = 4 +sdc_clk = port:PG00<2><1><2> +sdc_cmd = port:PG01<2><1><2> +sdc_d0 = port:PG02<2><1><2> +sdc_d1 = port:PG03<2><1><2> +sdc_d2 = port:PG04<2><1><2> +sdc_d3 = port:PG05<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc2_para] +sdc_used = 0 +sdc_detmode = 3 +sdc_buswidth = 4 +sdc_cmd = port:PC06<3><1><2> +sdc_clk = port:PC07<3><1><2> +sdc_d0 = port:PC08<3><1><2> +sdc_d1 = port:PC09<3><1><2> +sdc_d2 = port:PC10<3><1><2> +sdc_d3 = port:PC11<3><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc3_para] +sdc_used = 1 +sdc_detmode = 4 +sdc_buswidth = 4 +sdc_cmd = port:PI04<2><1><2> +sdc_clk = port:PI05<2><1><2> +sdc_d0 = port:PI06<2><1><2> +sdc_d1 = port:PI07<2><1><2> +sdc_d2 = port:PI08<2><1><2> +sdc_d3 = port:PI09<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 1 +sdc_regulator = "none" + +[ms_para] +ms_used = 0 +ms_bs = port:PH06<5> +ms_clk = port:PH07<5> +ms_d0 = port:PH08<5> +ms_d1 = port:PH09<5> +ms_d2 = port:PH10<5> +ms_d3 = port:PH11<5> +ms_det = + +[smc_para] +smc_used = 0 +smc_rst = port:PH13<5> +smc_vppen = port:PH14<5> +smc_vppp = port:PH15<5> +smc_det = port:PH16<5> +smc_vccen = port:PH17<5> +smc_sck = port:PH18<5> +smc_sda = port:PH19<5> + +[ps2_0_para] +ps2_used = 0 +ps2_scl = port:PI20<2><1> +ps2_sda = port:PI21<2><1> + +[ps2_1_para] +ps2_used = 0 +ps2_scl = port:PI14<3><1> +ps2_sda = port:PI15<3><1> + +[can_para] +can_used = 0 +can_tx = port:PA16<3> +can_rx = port:PA17<3> + +[keypad_para] +kp_used = 0 +kp_in_size = 8 +kp_out_size = 8 +kp_in0 = port:PH08<4><1> +kp_in1 = port:PH09<4><1> +kp_in2 = port:PH10<4><1> +kp_in3 = port:PH11<4><1> +kp_in4 = port:PH14<4><1> +kp_in5 = port:PH15<4><1> +kp_in6 = port:PH16<4><1> +kp_in7 = port:PH17<4><1> +kp_out0 = port:PH18<4><1> +kp_out1 = port:PH19<4><1> +kp_out2 = port:PH22<4><1> +kp_out3 = port:PH23<4><1> +kp_out4 = port:PH24<4><1> +kp_out5 = port:PH25<4><1> +kp_out6 = port:PH26<4><1> +kp_out7 = port:PH27<4><1> + +[usbc0] +usb_used = 1 +usb_port_type = 2 +usb_detect_type = 1 +usb_id_gpio = port:PH04<0><1> +usb_det_vbus_gpio = "axp_ctrl" +usb_drv_vbus_gpio = port:PB09<1><0><0> +usb_ac_enable_gpio = port:PH05<1><0><0> +usb_restrict_gpio = 0 +usb_host_init_state = 0 +usb_restric_flag = 0 +usb_restric_voltage = 3550000 +usb_restric_capacity = 5 + +[usbc1] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PH00<1><0><0> +usb_restrict_gpio = +usb_host_init_state = 1 +usb_restric_flag = 0 + +[usbc2] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PH01<1><0><0> +usb_restrict_gpio = +usb_host_init_state = 1 +usb_restric_flag = 0 + +[usb_feature] +vendor_id = 6353 +mass_storage_id = 1 +adb_id = 2 +manufacturer_name = "USB Developer" +product_name = "Android" +serial_number = "20080411" + +[msc_feature] +vendor_name = "USB 2.0" +product_name = "USB Flash Driver" +release = 100 +luns = 3 + +[gsensor_para] +gsensor_used = 0 +gsensor_twi_id = 1 +gsensor_int1 = +gsensor_int2 = + +[gsensor_list_para] +gsensor_det_used = 0 +bma250 = 1 +mma8452 = 1 +mma7660 = 1 +mma865x = 1 +afa750 = 1 +lis3de_acc = 1 +lis3dh_acc = 1 +kxtik = 1 +dmard10 = 0 +dmard06 = 1 +mxc622x = 1 +fxos8700 = 1 +lsm303d = 1 + +[gps_para] +gps_used = 0 +gps_spi_id = 2 +gps_spi_cs_num = 0 +gps_lradc = 1 +gps_clk = port:PI00<2> +gps_sign = port:PI01<2> +gps_mag = port:PI02<2> +gps_vcc_en = port:PC22<1><0> +gps_osc_en = port:PI14<1><0> +gps_rx_en = port:PI15<1><0> + +[sdio_wifi_pro_para] +sdio_wifi_pro_used = 1 +sdio_wifi_pro_sdc_id = 3 +sdio_wifi_pro_mod_sel = 7 +ap6xxx_wl_regon = port:PH22<1><0> +ap6xxx_wl_vdd_en = port:PH27<1><0> + +[usb_wifi_para] +usb_wifi_used = 1 +usb_wifi_usbc_num = 2 + +[3g_para] +3g_used = 0 +3g_usbc_num = 2 +3g_uart_num = 0 +3g_pwr = +3g_wakeup = +3g_int = + +[gy_para] +gy_used = 0 +gy_twi_id = 1 +gy_twi_addr = 0 +gy_int1 = port:PH18<6><1> +gy_int2 = port:PH19<6><1> + +[ls_para] +ls_used = 0 +ls_twi_id = 1 +ls_twi_addr = 0 +ls_int = port:PH20<6><1> + +[compass_para] +compass_used = 0 +compass_twi_id = 1 +compass_twi_addr = 0 +compass_int = port:PI13<6><1> + +[bt_para] +bt_used = 0 +bt_uart_id = 2 +bt_wakeup = port:PI20<1> +bt_gpio = port:PI21<1> +bt_rst = port:PB05<1> + +[i2s_para] +i2s_used = 0 +i2s_channel = 2 +i2s_mclk = port:PB05<2><1> +i2s_bclk = port:PB06<2><1> +i2s_lrclk = port:PB07<2><1> +i2s_dout0 = port:PB08<2><1> +i2s_dout1 = +i2s_dout2 = +i2s_dout3 = +i2s_din = port:PB12<2><1> + +[spdif_para] +spdif_used = 0 +spdif_mclk = +spdif_dout = port:PB13<4><1> +spdif_din = + +[audio_para] +audio_used = 1 +capture_used = 1 +audio_pa_ctrl = port:PH15<1><1> + +[switch_para] +switch_used = 0 + +[leds_para] +leds_used = 1 +leds_num = 2 +leds_pin_1 = port:PH24<1><0> +leds_pin_2 = port:PG02<1><0> +leds_name_1 = "green:ph24:led1" +leds_name_2 = "blue:pg02:led2" +leds_trigger_1 = "heartbeat" +leds_trigger_2 = "mmc0" + +[ir_para] +ir_used = 1 +ir0_rx = port:PB04<2> + +[pmu_para] +pmu_used = 1 +pmu_twi_addr = 52 +pmu_twi_id = 0 +pmu_irq_id = 32 +pmu_battery_rdc = 100 +pmu_battery_cap = 3200 +pmu_init_chgcur = 300 +pmu_earlysuspend_chgcur = 600 +pmu_suspend_chgcur = 1000 +pmu_resume_chgcur = 300 +pmu_shutdown_chgcur = 1000 +pmu_init_chgvol = 4200 +pmu_init_chgend_rate = 15 +pmu_init_chg_enabled = 1 +pmu_init_adc_freq = 100 +pmu_init_adc_freqc = 100 +pmu_init_chg_pretime = 50 +pmu_init_chg_csttime = 720 +pmu_bat_para1 = 0 +pmu_bat_para2 = 0 +pmu_bat_para3 = 0 +pmu_bat_para4 = 0 +pmu_bat_para5 = 5 +pmu_bat_para6 = 8 +pmu_bat_para7 = 11 +pmu_bat_para8 = 22 +pmu_bat_para9 = 33 +pmu_bat_para10 = 43 +pmu_bat_para11 = 50 +pmu_bat_para12 = 59 +pmu_bat_para13 = 71 +pmu_bat_para14 = 83 +pmu_bat_para15 = 92 +pmu_bat_para16 = 100 +pmu_usbvol_limit = 1 +pmu_usbcur_limit = 0 +pmu_usbvol = 4000 +pmu_usbcur = 0 +pmu_usbvol_pc = 4400 +pmu_usbcur_pc = 500 +pmu_pwroff_vol = 3300 +pmu_pwron_vol = 2900 +pmu_pekoff_time = 4000 +pmu_pekoff_en = 1 +pmu_peklong_time = 1500 +pmu_pekon_time = 1000 +pmu_pwrok_time = 64 +pmu_pwrnoe_time = 2000 +pmu_intotp_en = 1 +pmu_backupen = 1 +pmu_used2 = 0 +pmu_adpdet = port:PH02<0> +pmu_init_chgcur2 = 400 +pmu_earlysuspend_chgcur2 = 600 +pmu_suspend_chgcur2 = 1200 +pmu_resume_chgcur2 = 400 +pmu_shutdown_chgcur2 = 1200 +pmu_suspendpwroff_vol = 3500 +pmu_batdeten = 1 + +[recovery_key] +key_min = 4 +key_max = 10 + +[dvfs_table] +max_freq = 912000000 +min_freq = 720000000 +LV_count = 7 +LV1_freq = 1008000000 +LV1_volt = 1450 +LV2_freq = 912000000 +LV2_volt = 1425 +LV3_freq = 864000000 +LV3_volt = 1350 +LV4_freq = 720000000 +LV4_volt = 1250 +LV5_freq = 528000000 +LV5_volt = 1150 +LV6_freq = 312000000 +LV6_volt = 1100 +LV7_freq = 144000000 +LV7_volt = 1050 + diff --git a/config/bananapiprolcd7.fex b/config/bananapiprolcd7.fex new file mode 100644 index 000000000..154cce914 --- /dev/null +++ b/config/bananapiprolcd7.fex @@ -0,0 +1,1063 @@ +[product] +version = "100" +machine = "bananapipro" + +[platform] +eraseflag = 0 + +[target] +boot_clock = 912 +dcdc2_vol = 1450 +dcdc3_vol = 1300 +ldo2_vol = 3000 +ldo3_vol = 2800 +ldo4_vol = 2800 +storage_type = 0 + +[clock] +pll3 = 297 +pll4 = 300 +pll6 = 600 +pll7 = 297 +pll8 = 336 + +[card_boot] +logical_start = 40960 +sprite_gpio0 = + +[card0_boot_para] +card_ctrl = 0 +card_high_speed = 1 +card_line = 4 +sdc_d1 = port:PF00<2><1> +sdc_d0 = port:PF01<2><1> +sdc_clk = port:PF02<2><1> +sdc_cmd = port:PF03<2><1> +sdc_d3 = port:PF04<2><1> +sdc_d2 = port:PF05<2><1> + +[card2_boot_para] +card_ctrl = 2 +card_high_speed = 1 +card_line = 4 +sdc_cmd = port:PC06<3><1> +sdc_clk = port:PC07<3><1> +sdc_d0 = port:PC08<3><1> +sdc_d1 = port:PC09<3><1> +sdc_d2 = port:PC10<3><1> +sdc_d3 = port:PC11<3><1> + +[twi_para] +twi_port = 0 +twi_scl = port:PB00<2> +twi_sda = port:PB01<2> + +[uart_para] +uart_debug_port = 0 +uart_debug_tx = port:PB22<2><1> +uart_debug_rx = port:PB23<2><1> + +[uart_force_debug] +uart_debug_port = 0 +uart_debug_tx = port:PF02<4><1> +uart_debug_rx = port:PF04<4><1> + +[jtag_para] +jtag_enable = 0 +jtag_ms = port:PB14<3> +jtag_ck = port:PB15<3> +jtag_do = port:PB16<3> +jtag_di = port:PB17<3> + +[pm_para] +standby_mode = 0 + +[dram_para] +dram_baseaddr = 0x40000000 +dram_clk = 432 +dram_type = 3 +dram_rank_num = 1 +dram_chip_density = 4096 +dram_io_width = 16 +dram_bus_width = 32 +dram_cas = 9 +dram_zq = 0x7f +dram_odt_en = 0 +dram_size = 1024 +dram_tpr0 = 0x42d899b7 +dram_tpr1 = 0xa090 +dram_tpr2 = 0x22a00 +dram_tpr3 = 0x0 +dram_tpr4 = 0x1 +dram_tpr5 = 0x0 +dram_emr1 = 0x4 +dram_emr2 = 0x10 +dram_emr3 = 0x0 + +[mali_para] +mali_used = 1 +mali_clkdiv = 1 + +[gmac_para] +gmac_used = 1 +gmac_rxd3 = port:PA00<5><3> +gmac_rxd2 = port:PA01<5><3> +gmac_rxd1 = port:PA02<5><3> +gmac_rxd0 = port:PA03<5><3> +gmac_txd3 = port:PA04<5><3> +gmac_txd2 = port:PA05<5><3> +gmac_txd1 = port:PA06<5><3> +gmac_txd0 = port:PA07<5><3> +gmac_rxclk = port:PA08<5><3> +gmac_rxerr = port:PA09<0><3> +gmac_rxctl = port:PA10<5><3> +gmac_mdc = port:PA11<5><3> +gmac_mdio = port:PA12<5><3> +gmac_txctl = port:PA13<5><3> +gmac_txclk = port:PA14<0><3> +gmac_txck = port:PA15<5><3> +gmac_clkin = port:PA16<5><3> +gmac_txerr = port:PA17<0><3> + +[gmac_phy_power] +gmac_phy_power_en = port:PH23<1><0> + +[twi0_para] +twi0_used = 1 +twi0_scl = port:PB00<2> +twi0_sda = port:PB01<2> + +[twi1_para] +twi1_used = 1 +twi1_scl = port:PB18<2> +twi1_sda = port:PB19<2> + +[twi2_para] +twi2_used = 1 +twi2_scl = port:PB20<2> +twi2_sda = port:PB21<2> + +[twi3_para] +twi3_used = 1 +twi3_scl = port:PI00<3> +twi3_sda = port:PI01<3> + +[uart_para0] +uart_used = 1 +uart_port = 0 +uart_type = 2 +uart_tx = port:PB22<2><1> +uart_rx = port:PB23<2><1> + +[uart_para1] +uart_used = 0 +uart_port = 1 +uart_type = 8 +uart_tx = port:PA10<4><1> +uart_rx = port:PA11<4><1> +uart_rts = port:PA12<4><1> +uart_cts = port:PA13<4><1> +uart_dtr = port:PA14<4><1> +uart_dsr = port:PA15<4><1> +uart_dcd = port:PA16<4><1> +uart_ring = port:PA17<4><1> + +[uart_para2] +uart_used = 1 +uart_port = 2 +uart_type = 4 +uart_tx = port:PI18<3><1> +uart_rx = port:PI19<3><1> +uart_rts = port:PI16<3><1> +uart_cts = port:PI17<3><1> + +[uart_para3] +uart_used = 0 +uart_port = 3 +uart_type = 2 +uart_tx = port:PH00<4><1> +uart_rx = port:PH01<4><1> + +[uart_para4] +uart_used = 1 +uart_port = 4 +uart_type = 2 +uart_tx = port:PH04<4><1> +uart_rx = port:PH05<4><1> + +[uart_para5] +uart_used = 0 +uart_port = 5 +uart_type = 2 +uart_tx = port:PH06<4><1> +uart_rx = port:PH07<4><1> + +[uart_para6] +uart_used = 0 +uart_port = 6 +uart_type = 2 +uart_tx = port:PA12<4><1> +uart_rx = port:PA13<4><1> + +[uart_para7] +uart_used = 1 +uart_port = 7 +uart_type = 2 +uart_tx = port:PI20<3><1> +uart_rx = port:PI21<3><1> + +[spi0_para] +spi_used = 1 +spi_cs_bitmap = 3 +spi_cs0 = port:PI10<2> +spi_cs1 = port:PI14<2> +spi_sclk = port:PI11<2> +spi_mosi = port:PI12<2> +spi_miso = port:PI13<2> + +[spi1_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA00<3> +spi_cs1 = port:PA04<3> +spi_sclk = port:PA01<3> +spi_mosi = port:PA02<3> +spi_miso = port:PA03<3> + +[spi2_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PC19<3> +spi_cs1 = port:PB13<2> +spi_sclk = port:PC20<3> +spi_mosi = port:PC21<3> +spi_miso = port:PC22<3> + +[spi3_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA05<3> +spi_cs1 = port:PA09<3> +spi_sclk = port:PA06<3> +spi_mosi = port:PA07<3> +spi_miso = port:PA08<3> + +[spi_devices] +spi_dev_num = 2 + +[spi_board0] +modalias = "spidev" +max_speed_hz = 12000000 +bus_num = 0 +chip_select = 0 +mode = 3 +full_duplex = 0 +manual_cs = 0 + +[spi_board1] +modalias = "spidev" +max_speed_hz = 12000000 +bus_num = 0 +chip_select = 1 +mode = 3 +full_duplex = 0 +manual_cs = 0 + +[ctp_para] +ctp_used = 1 +ctp_name = "ft5x_ts" +ctp_twi_id = 3 +ctp_twi_addr = 0x38 +ctp_screen_max_x = 1024 +ctp_screen_max_y = 600 +ctp_revert_x_flag = 0 +ctp_revert_y_flag = 0 +ctp_exchange_x_y_flag = 0 +ctp_firm = 1 +ctp_int_port = port:PH09<6> +ctp_wakeup = port:PH07<1><1> +ctp_io_port = port:PH09<0> + +[ctp_list_para] +ctp_det_used = 1 +ft5x_ts = 1 +gt82x = 0 +gslX680 = 0 +gt9xx_ts = 0 +gt811 = 0 + +[tkey_para] +tkey_used = 0 +tkey_twi_id = 2 +tkey_twi_addr = 0x62 +tkey_int = port:PI13<6> + +[motor_para] +motor_used = 0 +motor_shake = port:PB03<1><1> + +[gpio_para] +gpio_used = 1 +gpio_num = 86 +gpio_pin_1 = port:PI00<1> +gpio_pin_2 = port:PB21<1> +gpio_pin_3 = port:PB20<1> +gpio_pin_4 = port:PH02<1> +gpio_pin_5 = port:PB03<1> +gpio_pin_6 = port:PI21<1> +gpio_pin_7 = port:PI14<1> +gpio_pin_8 = port:PI10<1> +gpio_pin_9 = port:PI13<1> +gpio_pin_10 = port:PI12<1> +gpio_pin_11 = port:PI11<1> +gpio_pin_12 = port:PI20<1> +gpio_pin_13 = port:PB13<1> +gpio_pin_14 = port:PH04<1> +gpio_pin_15 = port:PH05<1> +gpio_pin_16 = port:PB06<1> +gpio_pin_17 = port:PI19<1> +gpio_pin_18 = port:PI03<1> +gpio_pin_19 = port:PB07<1> +gpio_pin_20 = port:PB12<1> +gpio_pin_21 = port:PB08<1> +gpio_pin_22 = port:PI17<1> +gpio_pin_23 = port:PH20<1> +gpio_pin_24 = port:PH21<1> +gpio_pin_25 = port:PI16<1> +gpio_pin_26 = port:PB05<1> +gpio_pin_27 = port:PI18<1> +gpio_pin_28 = port:PI01<1> +gpio_pin_29 = port:PH17<1> +gpio_pin_30 = port:PB19<1> +gpio_pin_31 = port:PB18<1> +gpio_pin_32 = port:PH19<1> +gpio_pin_33 = port:PE00<1> +gpio_pin_34 = port:PH16<1> +gpio_pin_35 = port:PE01<1> +gpio_pin_36 = port:PH14<1> +gpio_pin_37 = port:PE03<1> +gpio_pin_38 = port:PE02<1> +gpio_pin_39 = port:PH18<1> +gpio_pin_40 = port:PH11<1> +gpio_pin_41 = port:PE04<1> +gpio_pin_42 = port:PE05<1> +gpio_pin_43 = port:PE06<1> +gpio_pin_44 = port:PE07<1> +gpio_pin_45 = port:PE08<1> +gpio_pin_46 = port:PE09<1> +gpio_pin_47 = port:PE10<1> +gpio_pin_48 = port:PE11<1> +gpio_pin_49 = port:PH13<1> +gpio_pin_50 = port:PI01<1> +gpio_pin_51 = port:PI00<1> +gpio_pin_52 = port:PH07<1> +gpio_pin_53 = port:PH08<1> +gpio_pin_54 = port:PB02<1> +gpio_pin_55 = port:PH09<1> +gpio_pin_56 = port:PD25<1> +gpio_pin_57 = port:PD27<1> +gpio_pin_58 = port:PD26<1> +gpio_pin_59 = port:PH06<1> +gpio_pin_60 = port:PD24<1> +gpio_pin_61 = port:PD23<1> +gpio_pin_62 = port:PD22<1> +gpio_pin_63 = port:PD21<1> +gpio_pin_64 = port:PD20<1> +gpio_pin_65 = port:PD19<1> +gpio_pin_66 = port:PD18<1> +gpio_pin_67 = port:PD17<1> +gpio_pin_68 = port:PD16<1> +gpio_pin_69 = port:PH12<1> +gpio_pin_70 = port:PD00<1> +gpio_pin_71 = port:PD01<1> +gpio_pin_72 = port:PD02<1> +gpio_pin_73 = port:PD03<1> +gpio_pin_74 = port:PD04<1> +gpio_pin_75 = port:PD05<1> +gpio_pin_76 = port:PD06<1> +gpio_pin_77 = port:PD07<1> +gpio_pin_78 = port:PD08<1> +gpio_pin_79 = port:PD09<1> +gpio_pin_80 = port:PD10<1> +gpio_pin_81 = port:PD11<1> +gpio_pin_82 = port:PD12<1> +gpio_pin_83 = port:PD13<1> +gpio_pin_84 = port:PD14<1> +gpio_pin_85 = port:PD15<1> +gpio_pin_86 = port:PH15<0><0> + +[nand_para] +nand_used = 0 +nand_we = port:PC00<2> +nand_ale = port:PC01<2> +nand_cle = port:PC02<2> +nand_ce1 = port:PC03<2> +nand_ce0 = port:PC04<2> +nand_nre = port:PC05<2> +nand_rb0 = port:PC06<2> +nand_rb1 = port:PC07<2> +nand_d0 = port:PC08<2> +nand_d1 = port:PC09<2> +nand_d2 = port:PC10<2> +nand_d3 = port:PC11<2> +nand_d4 = port:PC12<2> +nand_d5 = port:PC13<2> +nand_d6 = port:PC14<2> +nand_d7 = port:PC15<2> +nand_wp = port:PC16<2> +nand_ce2 = port:PC17<2> +nand_ce3 = port:PC18<2> +nand_ce4 = +nand_ce5 = +nand_ce6 = +nand_ce7 = +nand_spi = port:PC23<3> +nand_ndqs = port:PC24<2> +good_block_ratio = 0 + +[disp_init] +disp_init_enable = 1 +disp_mode = 0 +screen0_output_type = 1 +screen0_output_mode = 4 +screen1_output_type = 2 +screen1_output_mode = 11 +fb0_framebuffer_num = 2 +fb0_format = 10 +fb0_pixel_sequence = 0 +fb0_scaler_mode_enable = 1 +fb1_framebuffer_num = 2 +fb1_format = 10 +fb1_pixel_sequence = 0 +fb1_scaler_mode_enable = 0 +lcd0_backlight = 197 +lcd1_backlight = 197 +lcd0_bright = 50 +lcd0_contrast = 50 +lcd0_saturation = 57 +lcd0_hue = 50 +lcd1_bright = 50 +lcd1_contrast = 50 +lcd1_saturation = 57 +lcd1_hue = 50 + +[lcd0_para] +lcd_used = 1 +lcd_x = 1024 +lcd_y = 600 +lcd_dclk_freq = 55 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 0 +lcd_pwm_freq = 22000 +lcd_pwm_pol = 0 +lcd_max_bright = 240 +lcd_min_bright = 64 +lcd_if = 3 +lcd_hbp = 150 +lcd_ht = 1344 +lcd_vbp = 20 +lcd_vt = 1270 +lcd_vspw = 10 +lcd_hspw = 50 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 268435456 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 1 +lcd_bl_en = port:PH08<1><0><1> +lcd_power_used = 1 +lcd_power = port:PH12<1><0><1> +lcd_pwm_used = 1 +lcd_pwm = port:PB02<2><0> +lcdd0 = port:PD00<3><0> +lcdd1 = port:PD01<3><0> +lcdd2 = port:PD02<3><0> +lcdd3 = port:PD03<3><0> +lcdd4 = port:PD04<3><0> +lcdd5 = port:PD05<3><0> +lcdd6 = port:PD06<3><0> +lcdd7 = port:PD07<3><0> +lcdd8 = port:PD08<3><0> +lcdd9 = port:PD09<3><0> +lcdd10 = port:PD10<2><0> +lcdd11 = port:PD11<2><0> +lcdd12 = port:PD12<2><0> +lcdd13 = port:PD13<2><0> +lcdd14 = port:PD14<2><0> +lcdd15 = port:PD15<2><0> +lcdd16 = port:PD16<2><0> +lcdd17 = port:PD17<2><0> +lcdd18 = port:PD18<2><0> +lcdd19 = port:PD19<2><0> +lcdd20 = port:PD20<2><0> +lcdd21 = port:PD21<2><0> +lcdd22 = port:PD22<2><0> +lcdd23 = port:PD23<2><0> +lcdclk = port:PD24<2><0> +lcdde = port:PD25<2><0><3> +lcdhsync = port:PD26<2><0><3> +lcdvsync = port:PD27<2><0><3> + +[lcd1_para] +lcd_used = 0 +lcd_x = 0 +lcd_y = 0 +lcd_dclk_freq = 0 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 1 +lcd_pwm_freq = 0 +lcd_pwm_pol = 0 +lcd_max_bright = 240 +lcd_min_bright = 64 +lcd_if = 0 +lcd_hbp = 0 +lcd_ht = 0 +lcd_vbp = 0 +lcd_vt = 0 +lcd_vspw = 0 +lcd_hspw = 0 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 0 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 0 +lcd_bl_en = +lcd_power_used = 0 +lcd_power = +lcd_pwm_used = 1 +lcd_pwm = port:PI03<2><0> +lcd_gpio_0 = +lcd_gpio_1 = +lcd_gpio_2 = +lcd_gpio_3 = +lcdd0 = port:PH00<2><0> +lcdd1 = port:PH01<2><0> +lcdd2 = port:PH02<2><0> +lcdd3 = port:PH03<2><0> +lcdd4 = port:PH04<2><0> +lcdd5 = port:PH05<2><0> +lcdd6 = port:PH06<2><0> +lcdd7 = port:PH07<2><0> +lcdd8 = port:PH08<2><0> +lcdd9 = port:PH09<2><0> +lcdd10 = port:PH10<2><0> +lcdd11 = port:PH11<2><0> +lcdd12 = port:PH12<2><0> +lcdd13 = port:PH13<2><0> +lcdd14 = port:PH14<2><0> +lcdd15 = port:PH15<2><0> +lcdd16 = port:PH16<2><0> +lcdd17 = port:PH17<2><0> +lcdd18 = port:PH18<2><0> +lcdd19 = port:PH19<2><0> +lcdd20 = port:PH20<2><0> +lcdd21 = port:PH21<2><0> +lcdd22 = port:PH22<2><0> +lcdd23 = port:PH23<2><0> +lcdclk = port:PH24<2><0> +lcdde = port:PH25<2><0> +lcdhsync = port:PH26<2><0> +lcdvsync = port:PH27<2><0> + +[tv_out_dac_para] +dac_used = 0 +dac0_src = 4 +dac1_src = 5 +dac2_src = 6 +dac3_src = 0 + +[hdmi_para] +hdmi_used = 1 + +[csi0_para] +csi_used = 1 +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "ov5640" +csi_twi_id = 1 +csi_twi_addr = 0x78 +csi_if = 0 +csi_vflip = 1 +csi_hflip = 0 +csi_iovdd = "axp20_pll" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = 2800 +csi_vol_dvdd = +csi_vol_avdd = +csi_flash_pol = 0 +csi_facing = 0 +csi_pck = port:PE00<3> +csi_ck = port:PE01<3> +csi_hsync = port:PE02<3> +csi_vsync = port:PE03<3> +csi_d0 = port:PE04<3> +csi_d1 = port:PE05<3> +csi_d2 = port:PE06<3> +csi_d3 = port:PE07<3> +csi_d4 = port:PE08<3> +csi_d5 = port:PE09<3> +csi_d6 = port:PE10<3> +csi_d7 = port:PE11<3> +csi_reset = port:PH14<1><0> +csi_power_en = port:PH16<1><0> +csi_stby = port:PH19<1><0> + +[csi1_para] +csi_used = 0 +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "gc0308" +csi_if = 0 +csi_iovdd = "axp20_pll" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = 2800 +csi_vol_dvdd = +csi_vol_avdd = +csi_vflip = 0 +csi_hflip = 0 +csi_flash_pol = 0 +csi_facing = 1 +csi_twi_id = 1 +csi_twi_addr = 0x42 +csi_pck = port:PG00<3> +csi_ck = port:PG01<3> +csi_hsync = port:PG02<3> +csi_vsync = port:PG03<3> +csi_d0 = port:PG04<3> +csi_d1 = port:PG05<3> +csi_d2 = port:PG06<3> +csi_d3 = port:PG07<3> +csi_d4 = port:PG08<3> +csi_d5 = port:PG09<3> +csi_d6 = port:PG10<3> +csi_d7 = port:PG11<3> +csi_reset = port:PH13<1><0> +csi_power_en = port:PH16<1><0> +csi_stby = port:PH18<1><0> + +[camera_list_para] +camera_list_para_used = 1 +ov7670 = 0 +gc0308 = 0 +gt2005 = 0 +hi704 = 0 +sp0838 = 0 +mt9m112 = 0 +mt9m113 = 0 +ov2655 = 0 +hi253 = 0 +gc0307 = 0 +mt9d112 = 0 +ov5640 = 1 +gc2015 = 0 +ov2643 = 0 +gc0329 = 0 +gc0309 = 0 +tvp5150 = 0 +s5k4ec = 0 +ov5650_mv9335 = 0 +siv121d = 0 +gc2035 = 0 + +[tvout_para] +tvout_used = 0 +tvout_channel_num = 1 + +[tvin_para] +tvin_used = 0 +tvin_channel_num = 4 + +[sata_para] +sata_used = 1 +sata_power_en = + +[mmc0_para] +sdc_used = 1 +sdc_detmode = 1 +sdc_buswidth = 4 +sdc_clk = port:PF02<2><1><2> +sdc_cmd = port:PF03<2><1><2> +sdc_d0 = port:PF01<2><1><2> +sdc_d1 = port:PF00<2><1><2> +sdc_d2 = port:PF05<2><1><2> +sdc_d3 = port:PF04<2><1><2> +sdc_det = port:PH10<0><1> +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc1_para] +sdc_used = 0 +sdc_detmode = 4 +sdc_buswidth = 4 +sdc_clk = port:PG00<2><1><2> +sdc_cmd = port:PG01<2><1><2> +sdc_d0 = port:PG02<2><1><2> +sdc_d1 = port:PG03<2><1><2> +sdc_d2 = port:PG04<2><1><2> +sdc_d3 = port:PG05<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc2_para] +sdc_used = 0 +sdc_detmode = 3 +sdc_buswidth = 4 +sdc_cmd = port:PC06<3><1><2> +sdc_clk = port:PC07<3><1><2> +sdc_d0 = port:PC08<3><1><2> +sdc_d1 = port:PC09<3><1><2> +sdc_d2 = port:PC10<3><1><2> +sdc_d3 = port:PC11<3><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc3_para] +sdc_used = 1 +sdc_detmode = 4 +sdc_buswidth = 4 +sdc_cmd = port:PI04<2><1><2> +sdc_clk = port:PI05<2><1><2> +sdc_d0 = port:PI06<2><1><2> +sdc_d1 = port:PI07<2><1><2> +sdc_d2 = port:PI08<2><1><2> +sdc_d3 = port:PI09<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 1 +sdc_regulator = "none" + +[ms_para] +ms_used = 0 +ms_bs = port:PH06<5> +ms_clk = port:PH07<5> +ms_d0 = port:PH08<5> +ms_d1 = port:PH09<5> +ms_d2 = port:PH10<5> +ms_d3 = port:PH11<5> +ms_det = + +[smc_para] +smc_used = 0 +smc_rst = port:PH13<5> +smc_vppen = port:PH14<5> +smc_vppp = port:PH15<5> +smc_det = port:PH16<5> +smc_vccen = port:PH17<5> +smc_sck = port:PH18<5> +smc_sda = port:PH19<5> + +[ps2_0_para] +ps2_used = 0 +ps2_scl = port:PI20<2><1> +ps2_sda = port:PI21<2><1> + +[ps2_1_para] +ps2_used = 0 +ps2_scl = port:PI14<3><1> +ps2_sda = port:PI15<3><1> + +[can_para] +can_used = 0 +can_tx = port:PA16<3> +can_rx = port:PA17<3> + +[keypad_para] +kp_used = 0 +kp_in_size = 8 +kp_out_size = 8 +kp_in0 = port:PH08<4><1> +kp_in1 = port:PH09<4><1> +kp_in2 = port:PH10<4><1> +kp_in3 = port:PH11<4><1> +kp_in4 = port:PH14<4><1> +kp_in5 = port:PH15<4><1> +kp_in6 = port:PH16<4><1> +kp_in7 = port:PH17<4><1> +kp_out0 = port:PH18<4><1> +kp_out1 = port:PH19<4><1> +kp_out2 = port:PH22<4><1> +kp_out3 = port:PH23<4><1> +kp_out4 = port:PH24<4><1> +kp_out5 = port:PH25<4><1> +kp_out6 = port:PH26<4><1> +kp_out7 = port:PH27<4><1> + +[usbc0] +usb_used = 1 +usb_port_type = 2 +usb_detect_type = 0 +usb_id_gpio = port:PH04<0><1> +usb_det_vbus_gpio = port:PH05<0><0> +usb_drv_vbus_gpio = port:PB09<1><0><0> +usb_restric_gpio = port:PH00<1><0><0> +usb_host_init_state = 0 +usb_restric_flag = 0 +usb_restric_voltage = 3550000 +usb_restric_capacity = 5 + +[usbc1] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PH06<1><0><0> +usb_restrict_gpio = +usb_host_init_state = 1 +usb_restric_flag = 0 + +[usbc2] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PH03<1><0><0> +usb_restrict_gpio = +usb_host_init_state = 1 +usb_restric_flag = 0 + +[usb_feature] +vendor_id = 6353 +mass_storage_id = 1 +adb_id = 2 +manufacturer_name = "USB Developer" +product_name = "Android" +serial_number = "20080411" + +[msc_feature] +vendor_name = "USB 2.0" +product_name = "USB Flash Driver" +release = 100 +luns = 3 + +[gsensor_para] +gsensor_used = 0 +gsensor_twi_id = 1 +gsensor_int1 = +gsensor_int2 = + +[gsensor_list_para] +gsensor_det_used = 0 +bma250 = 1 +mma8452 = 1 +mma7660 = 1 +mma865x = 1 +afa750 = 1 +lis3de_acc = 1 +lis3dh_acc = 1 +kxtik = 1 +dmard10 = 0 +dmard06 = 1 +mxc622x = 1 +fxos8700 = 1 +lsm303d = 1 + +[gps_para] +gps_used = 0 +gps_spi_id = 2 +gps_spi_cs_num = 0 +gps_lradc = 1 +gps_clk = port:PI00<2> +gps_sign = port:PI01<2> +gps_mag = port:PI02<2> +gps_vcc_en = port:PC22<1><0> +gps_osc_en = port:PI14<1><0> +gps_rx_en = port:PI15<1><0> + +[sdio_wifi_pro_para] +sdio_wifi_pro_used = 1 +sdio_wifi_pro_sdc_id = 3 +sdio_wifi_pro_mod_sel = 7 +ap6xxx_wl_regon = port:PH22<1><0> +ap6xxx_wl_vdd_en = port:PH27<1><0> + +[usb_wifi_para] +usb_wifi_used = 1 +usb_wifi_usbc_num = 2 + +[3g_para] +3g_used = 0 +3g_usbc_num = 2 +3g_uart_num = 0 +3g_pwr = +3g_wakeup = +3g_int = + +[gy_para] +gy_used = 0 +gy_twi_id = 1 +gy_twi_addr = 0 +gy_int1 = port:PH18<6><1> +gy_int2 = port:PH19<6><1> + +[ls_para] +ls_used = 0 +ls_twi_id = 1 +ls_twi_addr = 0 +ls_int = port:PH20<6><1> + +[compass_para] +compass_used = 0 +compass_twi_id = 1 +compass_twi_addr = 0 +compass_int = port:PI13<6><1> + +[bt_para] +bt_used = 0 +bt_uart_id = 2 +bt_wakeup = port:PI20<1> +bt_gpio = port:PI21<1> +bt_rst = port:PB05<1> + +[i2s_para] +i2s_used = 0 +i2s_channel = 2 +i2s_mclk = port:PB05<2><1> +i2s_bclk = port:PB06<2><1> +i2s_lrclk = port:PB07<2><1> +i2s_dout0 = port:PB08<2><1> +i2s_dout1 = +i2s_dout2 = +i2s_dout3 = +i2s_din = port:PB12<2><1> + +[spdif_para] +spdif_used = 0 +spdif_mclk = +spdif_dout = port:PB13<4><1> +spdif_din = + +[audio_para] +audio_used = 1 +capture_used = 1 +audio_pa_ctrl = port:PH15<1><1> + +[switch_para] +switch_used = 0 + +[leds_para] +leds_used = 1 +leds_num = 1 +leds_pin_1 = port:PH24<1><0> +leds_name_1 = "green:ph24:led1" +leds_default_1 = 1 +leds_trigger_1 = "mmc0" + +[ir_para] +ir_used = 1 +ir0_rx = port:PB04<2> + +[pmu_para] +pmu_used = 1 +pmu_twi_addr = 52 +pmu_twi_id = 0 +pmu_irq_id = 32 +pmu_battery_rdc = 100 +pmu_battery_cap = 3200 +pmu_init_chgcur = 300 +pmu_earlysuspend_chgcur = 600 +pmu_suspend_chgcur = 1000 +pmu_resume_chgcur = 300 +pmu_shutdown_chgcur = 1000 +pmu_init_chgvol = 4200 +pmu_init_chgend_rate = 15 +pmu_init_chg_enabled = 1 +pmu_init_adc_freq = 100 +pmu_init_adc_freqc = 100 +pmu_init_chg_pretime = 50 +pmu_init_chg_csttime = 720 +pmu_bat_para1 = 0 +pmu_bat_para2 = 0 +pmu_bat_para3 = 0 +pmu_bat_para4 = 0 +pmu_bat_para5 = 5 +pmu_bat_para6 = 8 +pmu_bat_para7 = 11 +pmu_bat_para8 = 22 +pmu_bat_para9 = 33 +pmu_bat_para10 = 43 +pmu_bat_para11 = 50 +pmu_bat_para12 = 59 +pmu_bat_para13 = 71 +pmu_bat_para14 = 83 +pmu_bat_para15 = 92 +pmu_bat_para16 = 100 +pmu_usbvol_limit = 1 +pmu_usbcur_limit = 0 +pmu_usbvol = 4000 +pmu_usbcur = 0 +pmu_usbvol_pc = 4400 +pmu_usbcur_pc = 500 +pmu_pwroff_vol = 3300 +pmu_pwron_vol = 2900 +pmu_pekoff_time = 4000 +pmu_pekoff_en = 1 +pmu_peklong_time = 1500 +pmu_pekon_time = 1000 +pmu_pwrok_time = 64 +pmu_pwrnoe_time = 2000 +pmu_intotp_en = 1 +pmu_backupen = 1 +pmu_used2 = 0 +pmu_adpdet = port:PH02<0> +pmu_init_chgcur2 = 400 +pmu_earlysuspend_chgcur2 = 600 +pmu_suspend_chgcur2 = 1200 +pmu_resume_chgcur2 = 400 +pmu_shutdown_chgcur2 = 1200 +pmu_suspendpwroff_vol = 3500 +pmu_batdeten = 1 + +[recovery_key] +key_min = 4 +key_max = 10 + +[dvfs_table] +max_freq = 912000000 +min_freq = 720000000 +LV_count = 7 +LV1_freq = 1008000000 +LV1_volt = 1450 +LV2_freq = 912000000 +LV2_volt = 1425 +LV3_freq = 864000000 +LV3_volt = 1350 +LV4_freq = 720000000 +LV4_volt = 1250 +LV5_freq = 528000000 +LV5_volt = 1150 +LV6_freq = 312000000 +LV6_volt = 1100 +LV7_freq = 144000000 +LV7_volt = 1050 + diff --git a/config/boot-cubox.cmd b/config/boot-cubox.cmd new file mode 100644 index 000000000..f6d67f80a --- /dev/null +++ b/config/boot-cubox.cmd @@ -0,0 +1,4 @@ +setenv bootargs root=/dev/mmcblk0p1 rootfstype=ext4 rootwait console=tty1 video=mxcfb0:dev=hdmi,1920x1080M@60,if=RGB24,bpp=32 rd.dm=0 rd.luks=0 rd.lvm=0 raid=noautodetect pci=nomsi ahci_imx.hotplug=1 consoleblank=0 vt.global_cursor_default=0 quiet +ext2load mmc 0 0x18000000 /boot/dtb/${fdt_file} +ext2load mmc 0 0x12000000 /boot/zImage +bootz 0x12000000 - 0x18000000 diff --git a/config/boot-guitar.cmd b/config/boot-guitar.cmd new file mode 100644 index 000000000..8edae0496 --- /dev/null +++ b/config/boot-guitar.cmd @@ -0,0 +1,5 @@ +setenv bootargs "earlyprintk clk_ignore_unused selinux=0 scandelay root=/dev/mmcblk1p2 rw console=tty0 rootfstype=ext4 console=ttyS3 loglevel=4 rootwait" +setenv os_type linux +fatload mmc 0:1 0x04000000 dtb/lemaker_guitar_bbb.dtb +fatload mmc 0:1 0x7fc0 zImage +bootz 0x7fc0 - 0x04000000 \ No newline at end of file diff --git a/config/boot-next.cmd b/config/boot-next.cmd new file mode 100644 index 000000000..4d876a7f3 --- /dev/null +++ b/config/boot-next.cmd @@ -0,0 +1,5 @@ +setenv bootargs console=tty1 root=/dev/mmcblk0p1 rootwait panic=10 consoleblank=0 +ext4load mmc 0 0x49000000 /boot/dtb/${fdtfile} +ext4load mmc 0 0x46000000 /boot/zImage +env set fdt_high ffffffff +bootz 0x46000000 - 0x49000000 diff --git a/config/boot-udoo-neo.cmd b/config/boot-udoo-neo.cmd new file mode 100644 index 000000000..7de8b9ca4 --- /dev/null +++ b/config/boot-udoo-neo.cmd @@ -0,0 +1,9 @@ +setenv fdt_file imx6sx-udoo-neo-hdmi-m4.dtb +setenv bootargs root=/dev/mmcblk0p1 rootfstype=ext4 rootwait console=ttymxc0,115200 rd.dm=0 rd.luks=0 rd.lvm=0 rw uart_from_osc loglevel=1 +ext2load mmc ${mmcdev}:${mmcpart} 0x84000000 /boot/bin/m4startup.fw +ext2load mmc ${mmcdev}:${mmcpart} ${loadaddr} /boot${image} +ext2load mmc ${mmcdev}:${mmcpart} ${fdt_addr} /boot/dtb/${fdt_file} +bootaux 0x84000000 +bootz ${loadaddr} - ${fdt_addr} +# Recompile: mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr +# (c) www.armbian.com \ No newline at end of file diff --git a/config/boot-udoo-next.cmd b/config/boot-udoo-next.cmd new file mode 100644 index 000000000..209adbef2 --- /dev/null +++ b/config/boot-udoo-next.cmd @@ -0,0 +1,5 @@ +setenv bootargs root=/dev/mmcblk0p1 rootfstype=ext4 rootwait console=tty1 video=mxcfb0:dev=hdmi,1920x1080M@60,if=RGB24,bpp=32 ahci_imx.hotplug=1 quiet loglevel=1 +ext2load mmc 0 0x18000000 /boot/dtb/imx6q-udoo.dtb +ext2load mmc 0 0x12000000 /boot/zImage +bootz 0x12000000 - 0x18000000 +# mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr \ No newline at end of file diff --git a/config/boot-udoo.cmd b/config/boot-udoo.cmd new file mode 100644 index 000000000..25bfdc36a --- /dev/null +++ b/config/boot-udoo.cmd @@ -0,0 +1,7 @@ +setenv bootargs root=/dev/mmcblk0p1 rootfstype=ext4 rootwait console=tty1 video=mxcfb0:dev=hdmi,1920x1080M@60,if=RGB24,bpp=32 rd.dm=0 rd.luks=0 rd.lvm=0 raid=noautodetect pci=nomsi ahci_imx.hotplug=1 quiet +setenv fdt_file imx6q-udoo.dtb +ext2load mmc 0 ${fdt_addr} /boot/dtb/${fdt_file} || fatload mmc 0 ${fdt_addr} dtb/${fdt_file} +ext2load mmc 0 ${loadaddr} /boot/${image} || fatload mmc 0 ${loadaddr} ${image} +bootz ${loadaddr} - ${fdt_addr} +# mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr + diff --git a/config/boot.cmd b/config/boot.cmd index 227d7197a..03972a59e 100644 --- a/config/boot.cmd +++ b/config/boot.cmd @@ -1,5 +1,25 @@ -setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0p1 rootwait panic=10 -ext4load mmc 0 0x46000000 /boot/uImage -ext4load mmc 0 0x49000000 /boot/dtb/WHICH +# if you want to boot jessie with systemd: setenv bootargs init=/bin/systemd console=tty1 ... +# remember to disable ramlog prior switching to systemd +setenv bootargs "console=tty1 root=/dev/mmcblk0p1 rootwait rootfstype=ext4 sunxi_ve_mem_reserve=0 sunxi_g2d_mem_reserve=0 sunxi_no_mali_mem_reserve sunxi_fb_mem_reserve=16 hdmi.audio=EDID:0 disp.screen0_output_mode=1920x1080p60 panic=10 consoleblank=0 enforcing=0 loglevel=1" +#-------------------------------------------------------------------------------------------------------------------------------- +# Boot loader script to boot with different boot methods for old and new kernel +#-------------------------------------------------------------------------------------------------------------------------------- +if ext4load mmc 0 0x00000000 /boot/.next || fatload mmc 0 0x00000000 .next +then +# sunxi mainline kernel +#-------------------------------------------------------------------------------------------------------------------------------- +ext4load mmc 0 0x49000000 /boot/dtb/${fdtfile} || fatload mmc 0 0x49000000 /dtb/${fdtfile} +ext4load mmc 0 0x46000000 /boot/zImage || fatload mmc 0 0x46000000 zImage env set fdt_high ffffffff -bootm 0x46000000 - 0x49000000 +bootz 0x46000000 - 0x49000000 +#-------------------------------------------------------------------------------------------------------------------------------- +else +# sunxi android kernel +#-------------------------------------------------------------------------------------------------------------------------------- +ext4load mmc 0 0x43000000 /boot/script.bin || fatload mmc 0 0x43000000 script.bin +ext4load mmc 0 0x48000000 /boot/zImage || fatload mmc 0 0x48000000 zImage +bootz 0x48000000 +#-------------------------------------------------------------------------------------------------------------------------------- +fi +# Recompile with: +# mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr \ No newline at end of file diff --git a/config/cubieboard.fex b/config/cubieboard.fex new file mode 100644 index 000000000..f59716dd4 --- /dev/null +++ b/config/cubieboard.fex @@ -0,0 +1,941 @@ +[product] +version = "1.0" +machine = "A10-EVB-V1.2" + +[target] +boot_clock = 1008 +dcdc2_vol = 1400 +dcdc3_vol = 1250 +ldo2_vol = 3000 +ldo3_vol = 2800 +ldo4_vol = 2800 +pll4_freq = 960 +pll6_freq = 960 +power_start = 0 +storage_type = 0 + +[card_boot] +logical_start = 40960 +sprite_gpio0 = + +[card_boot0_para] +card_ctrl = 0 +card_high_speed = 1 +card_line = 4 +sdc_d1 = port:PF00<2><1> +sdc_d0 = port:PF01<2><1> +sdc_clk = port:PF02<2><1> +sdc_cmd = port:PF03<2><1> +sdc_d3 = port:PF04<2><1> +sdc_d2 = port:PF05<2><1> + +[card_boot2_para] +card_ctrl = 2 +card_high_speed = 1 +card_line = 4 +sdc_cmd = port:PC06<3><1> +sdc_clk = port:PC07<3><1> +sdc_d0 = port:PC08<3><1> +sdc_d1 = port:PC09<3><1> +sdc_d2 = port:PC10<3><1> +sdc_d3 = port:PC11<3><1> + +[twi_para] +twi_port = 0 +twi_scl = port:PB00<2> +twi_sda = port:PB01<2> + +[uart_para] +uart_debug_port = 0 +uart_debug_tx = port:PB22<2><1> +uart_debug_rx = port:PB23<2><1> + +[uart_force_debug] +uart_debug_port = 0 +uart_debug_tx = port:PF02<4> +uart_debug_rx = port:PF04<4> + +[jtag_para] +jtag_enable = 1 +jtag_ms = port:PB14<3> +jtag_ck = port:PB15<3> +jtag_do = port:PB16<3> +jtag_di = port:PB17<3> + +[dram_para] +dram_baseaddr = 0x40000000 +dram_clk = 480 +dram_type = 3 +dram_rank_num = 1 +dram_chip_density = 4096 +dram_io_width = 16 +dram_bus_width = 32 +dram_cas = 6 +dram_zq = 0x7b +dram_odt_en = 0 +dram_size = 1024 +dram_tpr0 = 0x30926692 +dram_tpr1 = 0x1090 +dram_tpr2 = 0x1a0c8 +dram_tpr3 = 0x0 +dram_tpr4 = 0x0 +dram_tpr5 = 0x0 +dram_emr1 = 0x0 +dram_emr2 = 0x0 +dram_emr3 = 0x0 + +[mali_para] +mali_used = 1 +mali_clkdiv = 3 + +[g2d_para] +g2d_used = 1 +g2d_size = 0x1000000 + +[emac_para] +emac_used = 1 +emac_rxd3 = port:PA00<2> +emac_rxd2 = port:PA01<2> +emac_rxd1 = port:PA02<2> +emac_rxd0 = port:PA03<2> +emac_txd3 = port:PA04<2> +emac_txd2 = port:PA05<2> +emac_txd1 = port:PA06<2> +emac_txd0 = port:PA07<2> +emac_rxclk = port:PA08<2> +emac_rxerr = port:PA09<2> +emac_rxdV = port:PA10<2> +emac_mdc = port:PA11<2> +emac_mdio = port:PA12<2> +emac_txen = port:PA13<2> +emac_txclk = port:PA14<2> +emac_crs = port:PA15<2> +emac_col = port:PA16<2> +emac_reset = port:PA17<1> + +[twi0_para] +twi0_used = 1 +twi0_scl = port:PB00<2> +twi0_sda = port:PB01<2> + +[twi1_para] +twi1_used = 1 +twi1_scl = port:PB18<2> +twi1_sda = port:PB19<2> + +[twi2_para] +twi2_used = 1 +twi2_scl = port:PB20<2> +twi2_sda = port:PB21<2> + +[uart_para0] +uart_used = 1 +uart_port = 0 +uart_type = 2 +uart_tx = port:PB22<2><1> +uart_rx = port:PB23<2><1> + +[uart_para1] +uart_used = 0 +uart_port = 1 +uart_type = 8 +uart_tx = port:PA10<4><1> +uart_rx = port:PA11<4><1> +uart_rts = port:PA12<4><1> +uart_cts = port:PA13<4><1> +uart_dtr = port:PA14<4><1> +uart_dsr = port:PA15<4><1> +uart_dcd = port:PA16<4><1> +uart_ring = port:PA17<4><1> + +[uart_para2] +uart_used = 1 +uart_port = 2 +uart_type = 4 +uart_tx = port:PI18<3><1> +uart_rx = port:PI19<3><1> +uart_rts = port:PI16<3><1> +uart_cts = port:PI17<3><1> + +[uart_para3] +uart_used = 0 +uart_port = 3 +uart_type = 4 +uart_tx = port:PH00<4><1> +uart_rx = port:PH01<4><1> +uart_rts = port:PH02<4><1> +uart_cts = port:PH03<4><1> + +[uart_para4] +uart_used = 0 +uart_port = 4 +uart_type = 2 +uart_tx = port:PH04<4><1> +uart_rx = port:PH05<4><1> + +[uart_para5] +uart_used = 0 +uart_port = 5 +uart_type = 2 +uart_tx = port:PH06<4><1> +uart_rx = port:PH07<4><1> + +[uart_para6] +uart_used = 0 +uart_port = 6 +uart_type = 2 +uart_tx = port:PA12<4><1> +uart_rx = port:PA13<4><1> + +[uart_para7] +uart_used = 0 +uart_port = 7 +uart_type = 2 +uart_tx = port:PA14<4><1> +uart_rx = port:PA15<4><1> + +[spi0_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PI10<3> +spi_sclk = port:PI11<3> +spi_mosi = port:PI12<3> +spi_miso = port:PI13<3> + +[spi1_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA00<4> +spi_sclk = port:PA01<4> +spi_mosi = port:PA02<4> +spi_miso = port:PA03<4> + +[spi2_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PB14<2> +spi_sclk = port:PB15<2> +spi_mosi = port:PB16<2> +spi_miso = port:PB17<2> +spi_cs0 = port:PC19<3> +spi_sclk = port:PC20<3> +spi_mosi = port:PC21<3> +spi_miso = port:PC22<3> + +[spi3_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA05<3> +spi_sclk = port:PI06<3> +spi_mosi = port:PI07<3> +spi_miso = port:PI08<3> +spi_cs1 = port:PA09<3> + +[spi_devices] +spi_dev_num = 0 + +[spi_board0] +modalias = "aaa" +max_speed_hz = 12000000 +bus_num = 1 +chip_select = 0 +mode = 3 +full_duplex = 0 +manual_cs = 0 + +[rtp_para] +rtp_used = 1 +rtp_screen_size = 5 +rtp_regidity_level = 5 +rtp_press_threshold_enable = 0 +rtp_press_threshold = 0x1f40 +rtp_sensitive_level = 0xf +rtp_exchange_x_y_flag = 0 + +[ctp_para] +ctp_used = 0 +ctp_name = "ft5x_ts" +ctp_twi_id = 2 +ctp_twi_addr = 0x70 +ctp_screen_max_x = 800 +ctp_screen_max_y = 480 +ctp_revert_x_flag = 0 +ctp_revert_y_flag = 0 +ctp_exchange_x_y_flag = 0 +ctp_int_port = port:PH21<6> +ctp_wakeup = port:PB13<1><1> +ctp_io_port = port:PH21<0> + +[tkey_para] +tkey_used = 0 +tkey_name = "hv_keypad" +tkey_twi_id = 2 +tkey_twi_addr = 0x62 +tkey_int = port:PI13<6> + +[motor_para] +motor_used = 0 +motor_shake = port:PB03<1><1> + +[nand_para] +nand_used = 1 +nand_we = port:PC00<2> +nand_ale = port:PC01<2> +nand_cle = port:PC02<2> +nand_ce1 = port:PC03<2> +nand_ce0 = port:PC04<2> +nand_nre = port:PC05<2> +nand_rb0 = port:PC06<2> +nand_rb1 = port:PC07<2> +nand_d0 = port:PC08<2> +nand_d1 = port:PC09<2> +nand_d2 = port:PC10<2> +nand_d3 = port:PC11<2> +nand_d4 = port:PC12<2> +nand_d5 = port:PC13<2> +nand_d6 = port:PC14<2> +nand_d7 = port:PC15<2> +nand_wp = port:PC16<2> +nand_ce2 = port:PC17<2> +nand_ce3 = port:PC18<2> +nand_ce4 = +nand_ce5 = +nand_ce6 = +nand_ce7 = +nand_spi = port:PC23<3> +nand_ndqs = port:PC24<2> + +[disp_init] +disp_init_enable = 1 +disp_mode = 0 +screen0_output_type = 3 +screen0_output_mode = 4 +screen1_output_type = 1 +screen1_output_mode = 4 +fb0_framebuffer_num = 2 +fb0_format = 10 +fb0_pixel_sequence = 0 +fb0_scaler_mode_enable = 0 +fb1_framebuffer_num = 2 +fb1_format = 10 +fb1_pixel_sequence = 0 +fb1_scaler_mode_enable = 0 +lcd0_bright = 197 +lcd1_bright = 197 +lcd0_screen_bright = 50 +lcd0_screen_contrast = 50 +lcd0_screen_saturation = 57 +lcd0_screen_hue = 50 +lcd1_screen_bright = 50 +lcd1_screen_contrast = 50 +lcd1_screen_saturation = 57 +lcd1_screen_hue = 50 + +[lcd0_para] +lcd_used = 1 +lcd_x = 800 +lcd_y = 480 +lcd_dclk_freq = 33 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 0 +lcd_pwm_freq = 10000 +lcd_pwm_pol = 0 +lcd_if = 0 +lcd_hbp = 46 +lcd_ht = 1055 +lcd_vbp = 23 +lcd_vt = 1050 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_hv_vspw = 0 +lcd_hv_hspw = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 268435456 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 1 +lcd_bl_en = port:PH07<1><0><1> +lcd_power_used = 1 +lcd_power = port:PH08<1><0><1> +lcd_pwm_used = 1 +lcd_pwm = port:PB02<2><0> +lcd_gpio_0 = +lcd_gpio_1 = +lcd_gpio_2 = +lcd_gpio_3 = +lcdd0 = port:PD00<2><0> +lcdd1 = port:PD01<2><0> +lcdd2 = port:PD02<2><0> +lcdd3 = port:PD03<2><0> +lcdd4 = port:PD04<2><0> +lcdd5 = port:PD05<2><0> +lcdd6 = port:PD06<2><0> +lcdd7 = port:PD07<2><0> +lcdd8 = port:PD08<2><0> +lcdd9 = port:PD09<2><0> +lcdd10 = port:PD10<2><0> +lcdd11 = port:PD11<2><0> +lcdd12 = port:PD12<2><0> +lcdd13 = port:PD13<2><0> +lcdd14 = port:PD14<2><0> +lcdd15 = port:PD15<2><0> +lcdd16 = port:PD16<2><0> +lcdd17 = port:PD17<2><0> +lcdd18 = port:PD18<2><0> +lcdd19 = port:PD19<2><0> +lcdd20 = port:PD20<2><0> +lcdd21 = port:PD21<2><0> +lcdd22 = port:PD22<2><0> +lcdd23 = port:PD23<2><0> +lcdclk = port:PD24<2><0> +lcdde = port:PD25<2><0> +lcdhsync = port:PD26<2><0> +lcdvsync = port:PD27<2><0> + +[lcd1_para] +lcd_used = 0 +lcd_x = 0 +lcd_y = 0 +lcd_dclk_freq = 0 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 1 +lcd_pwm_freq = 0 +lcd_pwm_pol = 0 +lcd_if = 0 +lcd_hbp = 0 +lcd_ht = 0 +lcd_vbp = 0 +lcd_vt = 0 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_hv_vspw = 0 +lcd_hv_hspw = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 0 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 0 +lcd_bl_en = +lcd_power_used = 0 +lcd_power = +lcd_pwm_used = 1 +lcd_pwm = port:PI03<2><0> +lcd_gpio_0 = +lcd_gpio_1 = +lcd_gpio_2 = +lcd_gpio_3 = +lcdd0 = port:PH00<2><0> +lcdd1 = port:PH01<2><0> +lcdd2 = port:PH02<2><0> +lcdd3 = port:PH03<2><0> +lcdd4 = port:PH04<2><0> +lcdd5 = port:PH05<2><0> +lcdd6 = port:PH06<2><0> +lcdd7 = port:PH07<2><0> +lcdd8 = port:PH08<2><0> +lcdd9 = port:PH09<2><0> +lcdd10 = port:PH10<2><0> +lcdd11 = port:PH11<2><0> +lcdd12 = port:PH12<2><0> +lcdd13 = port:PH13<2><0> +lcdd14 = port:PH14<2><0> +lcdd15 = port:PH15<2><0> +lcdd16 = port:PH16<2><0> +lcdd17 = port:PH17<2><0> +lcdd18 = port:PH18<2><0> +lcdd19 = port:PH19<2><0> +lcdd20 = port:PH20<2><0> +lcdd21 = port:PH21<2><0> +lcdd22 = port:PH22<2><0> +lcdd23 = port:PH23<2><0> +lcdclk = port:PH24<2><0> +lcdde = port:PH25<2><0> +lcdhsync = port:PH26<2><0> +lcdvsync = port:PH27<2><0> + +[tv_out_dac_para] +dac_used = 1 +dac0_src = 4 +dac1_src = 5 +dac2_src = 6 +dac3_src = 0 + +[csi0_para] +csi_used = 1 +csi_mode = 0 +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "gc0308" +csi_twi_id = 1 +csi_twi_addr = 0x42 +csi_if = 0 +csi_vflip = 0 +csi_hflip = 1 +csi_iovdd = "" +csi_avdd = "" +csi_dvdd = "" +csi_flash_pol = 1 +csi_mname_b = "" +csi_twi_id_b = 1 +csi_twi_addr_b = 0x78 +csi_if_b = 0 +csi_vflip_b = 1 +csi_hflip_b = 0 +csi_iovdd_b = "" +csi_avdd_b = "" +csi_dvdd_b = "" +csi_flash_pol_b = 1 +csi_pck = port:PE00<3> +csi_ck = port:PE01<3> +csi_hsync = port:PE02<3> +csi_vsync = port:PE03<3> +csi_d0 = port:PE04<3> +csi_d1 = port:PE05<3> +csi_d2 = port:PE06<3> +csi_d3 = port:PE07<3> +csi_d4 = port:PE08<3> +csi_d5 = port:PE09<3> +csi_d6 = port:PE10<3> +csi_d7 = port:PE11<3> +csi_d8 = +csi_d9 = +csi_d10 = +csi_d11 = +csi_d12 = +csi_d13 = +csi_d14 = +csi_d15 = +csi_reset = port:PH13<1><0> +csi_power_en = +csi_stby = port:PH16<1><0> +csi_flash = +csi_af_en = +csi_reset_b = +csi_power_en_b = +csi_stby_b = +csi_flash_b = +csi_af_en_b = + +[csi1_para] +csi_used = 0 +csi_mode = 0 +csi_dev_qty = 1 +csi_stby_mode = 1 +csi_mname = "" +csi_twi_id = 1 +csi_twi_addr = 0xba +csi_if = 0 +csi_vflip = 0 +csi_hflip = 0 +csi_iovdd = "" +csi_avdd = "" +csi_dvdd = "" +csi_flash_pol = 1 +csi_mname_b = "" +csi_twi_id_b = 1 +csi_twi_addr_b = 0x78 +csi_if_b = 0 +csi_vflip_b = 1 +csi_hflip_b = 0 +csi_iovdd_b = "" +csi_avdd_b = "" +csi_dvdd_b = "" +csi_flash_pol_b = 1 +csi_pck = port:PG00<3> +csi_ck = port:PG01<3> +csi_hsync = port:PG02<3> +csi_vsync = port:PG03<3> +csi_field = +csi_d0 = port:PG04<3> +csi_d1 = port:PG05<3> +csi_d2 = port:PG06<3> +csi_d3 = port:PG07<3> +csi_d4 = port:PG08<3> +csi_d5 = port:PG09<3> +csi_d6 = port:PG10<3> +csi_d7 = port:PG11<3> +csi_d8 = +csi_d9 = +csi_d10 = +csi_d11 = +csi_d12 = +csi_d13 = +csi_d14 = +csi_d15 = +csi_d16 = +csi_d17 = +csi_d18 = +csi_d19 = +csi_d20 = +csi_d21 = +csi_d22 = +csi_d23 = +csi_reset = port:PH14<1><0> +csi_power_en = +csi_stby = port:PH17<1><0> +csi_flash = +csi_af_en = +csi_reset_b = +csi_power_en_b = +csi_stby_b = +csi_flash_b = +csi_af_en_b = + +[tvout_para] +tvout_used = 1 +tvout_channel_num = 1 +tv_en = port:PI12<1><0> + +[tvin_para] +tvin_used = 0 +tvin_channel_num = 4 + +[sata_para] +sata_used = 1 +sata_power_en = port:PB08<1><0> + +[mmc0_para] +sdc_used = 1 +sdc_detmode = 1 +bus_width = 4 +sdc_d1 = port:PF00<2><1><2> +sdc_d0 = port:PF01<2><1><2> +sdc_clk = port:PF02<2><1><2> +sdc_cmd = port:PF03<2><1><2> +sdc_d3 = port:PF04<2><1><2> +sdc_d2 = port:PF05<2><1><2> +sdc_det = port:PH01<0><1> +sdc_use_wp = 0 +sdc_wp = + +[mmc1_para] +sdc_used = 1 +sdc_detmode = 1 +bus_width = 4 +sdc_cmd = port:PH22<5><1><2> +sdc_clk = port:PH23<5><1><2> +sdc_d0 = port:PH24<5><1><2> +sdc_d1 = port:PH25<5><1><2> +sdc_d2 = port:PH26<5><1><2> +sdc_d3 = port:PH27<5><1><2> +sdc_det = port:PH02<0><1> +sdc_use_wp = 0 +sdc_wp = + +[mmc2_para] +sdc_used = 0 + +[mmc3_para] +sdc_used = 1 +sdc_detmode = 4 +bus_width = 4 +sdc_cmd = port:PI04<2><1><2> +sdc_clk = port:PI05<2><1><2> +sdc_d0 = port:PI06<2><1><2> +sdc_d1 = port:PI07<2><1><2> +sdc_d2 = port:PI08<2><1><2> +sdc_d3 = port:PI09<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = + +[ms_para] +ms_used = 0 +ms_bs = port:PH06<5> +ms_clk = port:PH07<5> +ms_d0 = port:PH08<5> +ms_d1 = port:PH09<5> +ms_d2 = port:PH10<5> +ms_d3 = port:PH11<5> +ms_det = + +[smc_para] +smc_used = 0 +smc_rst = port:PH13<5> +smc_vppen = port:PH14<5> +smc_vppp = port:PH15<5> +smc_det = port:PH16<5> +smc_vccen = port:PH17<5> +smc_sck = port:PH18<5> +smc_sda = port:PH19<5> + +[ps2_0_para] +ps2_used = 0 +ps2_scl = port:PI20<2><1> +ps2_sda = port:PI21<2><1> + +[ps2_1_para] +ps2_used = 0 +ps2_scl = port:PI14<3><1> +ps2_sda = port:PI15<3><1> + +[can_para] +can_used = 0 +can_tx = port:PA16<3> +can_rx = port:PA17<3> + +[keypad_para] +kp_used = 0 +kp_in_size = 8 +kp_out_size = 8 +kp_in0 = port:PH08<4><1> +kp_in1 = port:PH09<4><1> +kp_in2 = port:PH10<4><1> +kp_in3 = port:PH11<4><1> +kp_in4 = port:PH14<4><1> +kp_in5 = port:PH15<4><1> +kp_in6 = port:PH16<4><1> +kp_in7 = port:PH17<4><1> +kp_out0 = port:PH18<4><1> +kp_out1 = port:PH19<4><1> +kp_out2 = port:PH22<4><1> +kp_out3 = port:PH23<4><1> +kp_out4 = port:PH24<4><1> +kp_out5 = port:PH25<4><1> +kp_out6 = port:PH26<4><1> +kp_out7 = port:PH27<4><1> + +[usbc0] +usb_used = 1 +usb_port_type = 2 +usb_detect_type = 0 +usb_id_gpio = port:PH04<0><1> +usb_det_vbus_gpio = port:PH05<0><0> +usb_drv_vbus_gpio = port:PB09<1><0><0> +usb_host_init_state = 0 + +[usbc1] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_id_gpio = +usb_det_vbus_gpio = +usb_drv_vbus_gpio = port:PH06<1><0><0> +usb_host_init_state = 1 + +[usbc2] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_id_gpio = +usb_det_vbus_gpio = +usb_drv_vbus_gpio = port:PH03<1><0><0> +usb_host_init_state = 1 + +[usb_feature] +vendor_id = 6353 +mass_storage_id = 1 +adb_id = 2 +manufacturer_name = "USB Developer" +product_name = "Android" +serial_number = "20080411" + +[msc_feature] +vendor_name = "USB 2.0" +product_name = "USB Flash Driver" +release = 100 +luns = 3 + +[gsensor_para] +gsensor_used = 0 +gsensor_name = "bma250" +gsensor_twi_id = 1 +gsensor_twi_addr = 0x18 +gsensor_int1 = port:PH00<6><1> +gsensor_int2 = port:PI10<6><1> + +[gps_para] +gps_used = 0 +gps_spi_id = 2 +gps_spi_cs_num = 0 +gps_lradc = 1 +gps_clk = port:PI00<2> +gps_sign = port:PI01<2> +gps_mag = port:PI02<2> +gps_vcc_en = port:PC22<1><0> +gps_osc_en = port:PI14<1><0> +gps_rx_en = port:PI15<1><0> + +[sdio_wifi_para] +sdio_wifi_used = 0 +sdio_wifi_sdc_id = 3 +sdio_wifi_mod_sel = 1 +swl_n20_shdn = port:PH09<1><0> +swl_n20_host_wakeup = port:PH10<1><1> +swl_n20_vdd_en = port:PH11<1><0> +swl_n20_vcc_en = port:PH12<1><0> + +[usb_wifi_para] +usb_wifi_used = 0 +usb_wifi_usbc_num = 2 + +[3g_para] +3g_used = 0 +3g_usbc_num = 2 +3g_uart_num = 0 +3g_pwr = +3g_wakeup = +3g_int = + +[gy_para] +gy_used = 0 +gy_twi_id = 1 +gy_twi_addr = 0 +gy_int1 = port:PH18<6><1> +gy_int2 = port:PH19<6><1> + +[ls_para] +ls_used = 0 +ls_twi_id = 1 +ls_twi_addr = 0 +ls_int = port:PH20<6><1> + +[compass_para] +compass_used = 0 +compass_twi_id = 1 +compass_twi_addr = 0 +compass_int = port:PI13<6><1> + +[bt_para] +bt_used = 0 +bt_uart_id = 2 +bt_mod_type = 1 + +[i2s_para] +i2s_used = 1 +i2s_channel = 2 +i2s_mclk = port:PB05<2><1> +i2s_bclk = port:PB06<2><1> +i2s_lrclk = port:PB07<2><1> +i2s_dout0 = port:PB08<2><1> +i2s_dout1 = +i2s_dout2 = +i2s_dout3 = +i2s_din = port:PB12<2><1> + +[spdif_para] +spdif_used = 0 +spdif_mclk = +spdif_dout = port:PB13<4><1> +spdif_din = + +[audio_para] +audio_used = 1 +capture_used = 1 +audio_lr_change = 0 +audio_pa_ctrl = port:PH15<1><0> + +[switch_para] +switch_used = 0 + +[ir_para] +ir_used = 1 +ir0_rx = port:PB04<2> + +[pmu_para] +pmu_used = 1 +pmu_twi_addr = 52 +pmu_twi_id = 0 +pmu_irq_id = 0 +pmu_battery_rdc = 100 +pmu_battery_cap = 3200 +pmu_init_chgcur = 300 +pmu_earlysuspend_chgcur = 600 +pmu_suspend_chgcur = 1000 +pmu_resume_chgcur = 300 +pmu_shutdown_chgcur = 1000 +pmu_init_chgvol = 4200 +pmu_init_chgend_rate = 15 +pmu_init_chg_enabled = 1 +pmu_init_adc_freq = 100 +pmu_init_adc_freqc = 100 +pmu_init_chg_pretime = 50 +pmu_init_chg_csttime = 720 +pmu_bat_para1 = 0 +pmu_bat_para2 = 0 +pmu_bat_para3 = 0 +pmu_bat_para4 = 0 +pmu_bat_para5 = 5 +pmu_bat_para6 = 8 +pmu_bat_para7 = 11 +pmu_bat_para8 = 22 +pmu_bat_para9 = 33 +pmu_bat_para10 = 43 +pmu_bat_para11 = 50 +pmu_bat_para12 = 59 +pmu_bat_para13 = 71 +pmu_bat_para14 = 83 +pmu_bat_para15 = 92 +pmu_bat_para16 = 100 +pmu_usbvol_limit = 1 +pmu_usbcur_limit = 0 +pmu_usbvol = 4000 +pmu_usbcur = 0 +pmu_usbvol_pc = 4000 +pmu_usbcur_pc = 0 +pmu_pwroff_vol = 3300 +pmu_pwron_vol = 2900 +pmu_pekoff_time = 6000 +pmu_pekoff_en = 1 +pmu_peklong_time = 1500 +pmu_pekon_time = 1000 +pmu_pwrok_time = 64 +pmu_pwrnoe_time = 2000 +pmu_intotp_en = 1 +pmu_used2 = 0 +pmu_adpdet = port:PH02<0> +pmu_init_chgcur2 = 400 +pmu_earlysuspend_chgcur2 = 600 +pmu_suspend_chgcur2 = 1200 +pmu_resume_chgcur2 = 400 +pmu_shutdown_chgcur2 = 1200 +pmu_suspendpwroff_vol = 3500 +pmu_batdeten = 1 + +[recovery_key] +key_min = 4 +key_max = 6 + +[dvfs_table] +max_freq = 1008000000 +min_freq = 60000000 +LV_count = 5 +LV1_freq = 1056000000 +LV1_volt = 1500 +LV2_freq = 1008000000 +LV2_volt = 1400 +LV3_freq = 912000000 +LV3_volt = 1350 +LV4_freq = 864000000 +LV4_volt = 1300 +LV5_freq = 624000000 +LV5_volt = 1250 + +[leds_para] +leds_used = 1 +leds_num = 2 +leds_pin_1 = port:PH20<1><0> +leds_name_1 = "green:ph20:led1" +leds_default_1 = 1 +leds_trigger_1 = "mmc0" +leds_pin_2 = port:PH21<1><0> +leds_name_2 = "blue:ph21:led2" +leds_trigger_2 = "none" diff --git a/config/cubieboard2.fex b/config/cubieboard2.fex index 2ffe99cad..30aab033b 100644 --- a/config/cubieboard2.fex +++ b/config/cubieboard2.fex @@ -1204,7 +1204,7 @@ leds_default_1 = 1 leds_pin_2 = port:PH21<1><0> leds_name_2 = "blue:ph21:led2" leds_default_2 = 0 -leds_trigger_2 = "heartbeat" +leds_trigger_2 = "none" ;------------------------------------------------------------------------------- ;ir --- infra remote configuration diff --git a/config/cubieboard2dual.fex b/config/cubieboard2dual.fex new file mode 100644 index 000000000..83e14c9dd --- /dev/null +++ b/config/cubieboard2dual.fex @@ -0,0 +1,1387 @@ +;A20 PAD application +;------------------------------------------------------------------------------- +; 说明: +; 1. 脚本中的字符串区分大小写,用户可以修改"="后面的数值,但是不要修改前面的字符串 +; 2. 新增主键和子键的名称必须控制在32个字符以内,不包括32个 +; 3. 所以的注释以“;”开始,单独占据一行 +; 4. 注释不可和配置项同行,例如:主键和子健后面不能添加任何形式的注释 +; +; gpio的描述形式:Port:端口+组内序号<功能分配><内部电阻状态><驱动能力><输出电平状态> +; 例如:port:PA0<0> +;------------------------------------------------------------------------------- + +[product] +version = "100" +machine = "cubieboard2" + +[platform] +eraseflag = 0 + +[target] +boot_clock = 912 +dcdc2_vol = 1450 +dcdc3_vol = 1300 +ldo2_vol = 3000 +ldo3_vol = 2800 +ldo4_vol = 2800 +storage_type = 0 + +[clock] +pll3 = 297 +pll4 = 300 +pll6 = 600 +pll7 = 297 +pll8 = 336 + +[card_boot] +logical_start = 40960 +sprite_gpio0 = + +[card0_boot_para] +card_ctrl = 0 +card_high_speed = 1 +card_line = 4 +sdc_d1 = port:PF0<2><1> +sdc_d0 = port:PF1<2><1> +sdc_clk = port:PF2<2><1> +sdc_cmd = port:PF3<2><1> +sdc_d3 = port:PF4<2><1> +sdc_d2 = port:PF5<2><1> + +[card2_boot_para] +card_ctrl = 2 +card_high_speed = 1 +card_line = 4 +sdc_cmd = port:PC6<3><1> +sdc_clk = port:PC7<3><1> +sdc_d0 = port:PC8<3><1> +sdc_d1 = port:PC9<3><1> +sdc_d2 = port:PC10<3><1> +sdc_d3 = port:PC11<3><1> + +[twi_para] +twi_port = 0 +twi_scl = port:PB0<2> +twi_sda = port:PB1<2> + +[uart_para] +uart_debug_port = 0 +uart_debug_tx = port:PB22<2><1> +uart_debug_rx = port:PB23<2><1> + +[uart_force_debug] +uart_debug_port = 0 +uart_debug_tx =port:PF2<4><1> +uart_debug_rx =port:PF4<4><1> + +[jtag_para] +jtag_enable = 0 +jtag_ms = port:PB14<3> +jtag_ck = port:PB15<3> +jtag_do = port:PB16<3> +jtag_di = port:PB17<3> + +;--------------------------------------------------------------------------------------------------------- +; if 1 == standby_mode, then support super standby; +; else, support normal standby. +;--------------------------------------------------------------------------------------------------------- +[pm_para] +standby_mode = 0 + +;------------------------------------------------------------------------------- +;sdram configuration +;------------------------------------------------------------------------------- +[dram_para] +dram_baseaddr = 0x40000000 +dram_clk = 480 +dram_type = 3 +dram_rank_num = 0xffffffff +dram_chip_density = 0xffffffff +dram_io_width = 0xffffffff +dram_bus_width = 0xffffffff +dram_cas = 9 +dram_zq = 0x7f +dram_odt_en = 0 +dram_size = 0xffffffff +dram_tpr0 = 0x42d899b7 +dram_tpr1 = 0xa090 +dram_tpr2 = 0x22a00 +dram_tpr3 = 0x0 +dram_tpr4 = 0x1 +dram_tpr5 = 0x0 +dram_emr1 = 0x4 +dram_emr2 = 0x10 +dram_emr3 = 0x0 + +;------------------------------------------------------------------------------- +;Mali configuration +;------------------------------------------------------------------------------- +[mali_para] +mali_used = 1 +mali_clkdiv = 1 + +;------------------------------------------------------------------------------- +;Ethernet MAC configuration +;------------------------------------------------------------------------------- +[emac_para] +emac_used = 1 +emac_rxd3 = port:PA00<2> +emac_rxd2 = port:PA01<2> +emac_rxd1 = port:PA02<2> +emac_rxd0 = port:PA03<2> +emac_txd3 = port:PA04<2> +emac_txd2 = port:PA05<2> +emac_txd1 = port:PA06<2> +emac_txd0 = port:PA07<2> +emac_rxclk = port:PA08<2> +emac_rxerr = port:PA09<2> +emac_rxdV = port:PA10<2> +emac_mdc = port:PA11<2> +emac_mdio = port:PA12<2> +emac_txen = port:PA13<2> +emac_txclk = port:PA14<2> +emac_crs = port:PA15<2> +emac_col = port:PA16<2> +emac_reset = port:PA17<1> + +;------------------------------------------------------------------------------- +;i2c configuration +;------------------------------------------------------------------------------- +[twi0_para] +twi0_used = 1 +twi0_scl = port:PB0<2> +twi0_sda = port:PB1<2> + +[twi1_para] +twi1_used = 0 +twi1_scl = port:PB18<2> +twi1_sda = port:PB19<2> + +[twi2_para] +twi2_used = 0 +twi2_scl = port:PB20<2> +twi2_sda = port:PB21<2> + +;------------------------------------------------------------------------------- +;uart configuration +;uart_type --- 2 (2 wire), 4 (4 wire), 8 (8 wire, full function) +;------------------------------------------------------------------------------- +[uart_para0] +uart_used = 1 +uart_port = 0 +uart_type = 2 +uart_tx = port:PB22<2><1> +uart_rx = port:PB23<2><1> + +[uart_para1] +uart_used = 0 +uart_port = 1 +uart_type = 8 +uart_tx = port:PA10<4><1> +uart_rx = port:PA11<4><1> +uart_rts = port:PA12<4><1> +uart_cts = port:PA13<4><1> +uart_dtr = port:PA14<4><1> +uart_dsr = port:PA15<4><1> +uart_dcd = port:PA16<4><1> +uart_ring = port:PA17<4><1> + +[uart_para2] +uart_used = 0 +uart_port = 2 +uart_type = 4 +uart_tx = port:PI18<3><1> +uart_rx = port:PI19<3><1> +uart_rts = port:PI16<3><1> +uart_cts = port:PI17<3><1> + +[uart_para3] +uart_used = 0 +uart_port = 3 +uart_type = 4 +uart_tx = port:PH00<4><1> +uart_rx = port:PH01<4><1> +uart_rts = port:PH02<4><1> +uart_cts = port:PH03<4><1> + +[uart_para4] +uart_used = 0 +uart_port = 4 +uart_type = 2 +uart_tx = port:PH04<4><1> +uart_rx = port:PH05<4><1> + +[uart_para5] +uart_used = 0 +uart_port = 5 +uart_type = 2 +uart_tx = port:PH06<4><1> +uart_rx = port:PH07<4><1> + +[uart_para6] +uart_used = 0 +uart_port = 6 +uart_type = 2 +uart_tx = port:PA12<4><1> +uart_rx = port:PA13<4><1> + +[uart_para7] +uart_used = 0 +uart_port = 7 +uart_type = 2 +uart_tx = port:PA14<4><1> +uart_rx = port:PA15<4><1> + +;------------------------------------------------------------------------------- +;spi configuration +;------------------------------------------------------------------------------- +[spi0_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PI10<2> +spi_cs1 = port:PI14<2> +spi_sclk = port:PI11<2> +spi_mosi = port:PI12<2> +spi_miso = port:PI13<2> + +[spi1_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA00<3> +spi_cs1 = port:PA04<3> +spi_sclk = port:PA01<3> +spi_mosi = port:PA02<3> +spi_miso = port:PA03<3> + +[spi2_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PC19<3> +spi_cs1 = port:PB13<2> +spi_sclk = port:PC20<3> +spi_mosi = port:PC21<3> +spi_miso = port:PC22<3> + +[spi3_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA05<3> +spi_cs1 = port:PA09<3> +spi_sclk = port:PA06<3> +spi_mosi = port:PA07<3> +spi_miso = port:PA08<3> + +;------------------------------------------------------------------------------- +;capacitor tp configuration +;external int function +;wakeup output function +;notice: +; tp_int_port & tp_io_port use the same port +;------------------------------------------------------------------------------- +[ctp_para] +ctp_used = 0 +ctp_name = "gt811" +ctp_twi_id = 2 +ctp_twi_addr = 0x40 +ctp_screen_max_x = 1024 +ctp_screen_max_y = 600 +ctp_revert_x_flag = 0 +ctp_revert_y_flag = 0 +ctp_exchange_x_y_flag = 1 +ctp_firm = 1 + +ctp_int_port = port:PH21<6> +ctp_wakeup = port:PB13<1><1> +;-------------------------------------------------------------------------------- +; CTP automatic detection configuration +;ctp_detect_used --- Whether startup automatic inspection function. 1:used,0:unused +;Module name postposition 1 said detection, 0 means no detection. +;-------------------------------------------------------------------------------- +[ctp_list_para] +ctp_det_used = 0 +ft5x_ts = 0 +gt82x = 0 +gslX680 = 0 +gt9xx_ts = 0 +gt811 = 0 +;------------------------------------------------------------------------------- +;touch key configuration +;------------------------------------------------------------------------------- +[tkey_para] +tkey_used = 0 +tkey_twi_id = 2 +tkey_twi_addr = 0x62 +tkey_int = port:PI13<6> + +;------------------------------------------------------------------------------- +;motor configuration +;------------------------------------------------------------------------------- +[motor_para] +motor_used = 0 +motor_shake = port:PB03<1><1> + +[gpio_para] +gpio_used = 1 +gpio_num = 2 +gpio_pin_1 = port:PH20<1><1> +gpio_pin_2 = port:PH21<1><1> + +;------------------------------------------------------------------------------- +;nand flash configuration +;------------------------------------------------------------------------------- +[nand_para] +nand_used = 0 +nand_we = port:PC00<2> +nand_ale = port:PC01<2> +nand_cle = port:PC02<2> +nand_ce1 = port:PC03<2> +nand_ce0 = port:PC04<2> +nand_nre = port:PC05<2> +nand_rb0 = port:PC06<2> +nand_rb1 = port:PC07<2> +nand_d0 = port:PC08<2> +nand_d1 = port:PC09<2> +nand_d2 = port:PC10<2> +nand_d3 = port:PC11<2> +nand_d4 = port:PC12<2> +nand_d5 = port:PC13<2> +nand_d6 = port:PC14<2> +nand_d7 = port:PC15<2> +nand_wp = port:PC16<2> +nand_ce2 = port:PC17<2> +nand_ce3 = port:PC18<2> +nand_ce4 = +nand_ce5 = +nand_ce6 = +nand_ce7 = +nand_spi = port:PC23<3> +nand_ndqs = port:PC24<2> +good_block_ratio = 0 + +;------------------------------------------------------------------------------- +;disp init configuration +; +;disp_mode (0:screen0 1:screen1 2:two_diff_screen_diff_contents +; 3:two_same_screen_diff_contets 4:two_diff_screen_same_contents) +;screenx_output_type (0:none; 1:lcd; 2:tv; 3:hdmi; 4:vga) +;screenx_output_mode (used for tv/hdmi output, 0:480i 1:576i 2:480p 3:576p 4:720p50 5:720p60 6:1080i50 7:1080i60 8:1080p24 9:1080p50 10:1080p60 11:pal 14:ntsc) +;screenx_output_mode (used for vga output, 0:1680*1050 1:1440*900 2:1360*768 3:1280*1024 4:1024*768 5:800*600 6:640*480 10:1920*1080 11:1280*720) +;fbx format (4:RGB655 5:RGB565 6:RGB556 7:ARGB1555 8:RGBA5551 9:RGB888 10:ARGB8888 12:ARGB4444) +;fbx pixel sequence (0:ARGB 1:BGRA 2:ABGR 3:RGBA) --- 0 for linux, 2 for android +;lcd0_bright (lcd0 init bright,the range:[0,256],default:197 +;lcd1_bright (lcd1 init bright,the range:[0,256],default:197 +;------------------------------------------------------------------------------- +[disp_init] +disp_init_enable = 1 +disp_mode = 0 + +screen0_output_type = 3 +screen0_output_mode = 4 + +screen1_output_type = 0 +screen1_output_mode = 4 + +fb0_width = 1024 +fb0_height = 768 +fb0_framebuffer_num = 2 +fb0_format = 10 +fb0_pixel_sequence = 0 +fb0_scaler_mode_enable = 1 + +fb1_width = 1024 +fb1_height = 768 +fb1_framebuffer_num = 2 +fb1_format = 10 +fb1_pixel_sequence = 0 +fb1_scaler_mode_enable = 0 + +lcd0_backlight = 197 +lcd1_backlight = 197 + +lcd0_bright = 50 +lcd0_contrast = 50 +lcd0_saturation = 57 +lcd0_hue = 50 + +lcd1_bright = 50 +lcd1_contrast = 50 +lcd1_saturation = 57 +lcd1_hue = 50 + +;------------------------------------------------------------------------------- +;lcd0 configuration + +;lcd_dclk_freq: in MHZ unit +;lcd_pwm_freq: in HZ unit +;lcd_if: 0:hv(sync+de); 1:8080; 2:ttl; 3:lvds +;lcd_hbp: hsync back porch +;lcd_ht: hsync total cycle +;lcd_vbp: vsync back porch +;lcd_vt: vysnc total cycle *2 +;lcd_hv_if: 0:hv parallel 1:hv serial +;lcd_hv_smode: 0:RGB888 1:CCIR656 +;lcd_hv_s888_if serial RGB format +;lcd_hv_syuv_if: serial YUV format +;lcd_hspw: hsync plus width +;lcd_vspw: vysnc plus width +;lcd_lvds_ch: 0:single channel; 1:dual channel +;lcd_lvds_mode: 0:NS mode; 1:JEIDA mode +;lcd_lvds_bitwidth: 0:24bit; 1:18bit +;lcd_lvds_io_cross: 0:normal; 1:pn cross +;lcd_cpu_if: 0:18bit; 1:16bit mode0; 2:16bit mode1; 3:16bit mode2; 4:16bit mode3; 5:9bit; 6:8bit 256K; 7:8bit 65K +;lcd_frm: 0:disable; 1:enable rgb666 dither; 2:enable rgb656 dither + +;lcd_gpio_0: SCL +;lcd_gpio_1 SDA +;------------------------------------------------------------------------------- +[lcd0_para] +lcd_used = 1 + +lcd_x = 1024 +lcd_y = 600 +lcd_dclk_freq = 51 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 0 +lcd_pwm_freq = 10000 +lcd_pwm_pol = 1 +lcd_max_bright = 240 +lcd_min_bright = 64 +lcd_if = 0 +lcd_hbp = 158 +lcd_ht = 1344 +lcd_vbp = 25 +lcd_vt = 1270 +lcd_vspw = 3 +lcd_hspw = 20 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 1 +lcd_io_cfg0 = 0x00000000 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x00000000 +lcd_gamma_tbl_1 = 0x00010101 +lcd_gamma_tbl_255 = 0x00ffffff + +lcd_bl_en_used = 0 +lcd_bl_en = port:PH07<1><0><1> + +lcd_power_used = 0 +lcd_power = port:PH08<1><0><1> + +lcd_pwm_used = 0 +lcd_pwm = port:PB02<2><0> + +lcdd0 = port:PD00<2><0> +lcdd1 = port:PD01<2><0> +lcdd2 = port:PD02<2><0> +lcdd3 = port:PD03<2><0> +lcdd4 = port:PD04<2><0> +lcdd5 = port:PD05<2><0> +lcdd6 = port:PD06<2><0> +lcdd7 = port:PD07<2><0> +lcdd8 = port:PD08<2><0> +lcdd9 = port:PD09<2><0> +lcdd10 = port:PD10<2><0> +lcdd11 = port:PD11<2><0> +lcdd12 = port:PD12<2><0> +lcdd13 = port:PD13<2><0> +lcdd14 = port:PD14<2><0> +lcdd15 = port:PD15<2><0> +lcdd16 = port:PD16<2><0> +lcdd17 = port:PD17<2><0> +lcdd18 = port:PD18<2><0> +lcdd19 = port:PD19<2><0> +lcdd20 = port:PD20<2><0> +lcdd21 = port:PD21<2><0> +lcdd22 = port:PD22<2><0> +lcdd23 = port:PD23<2><0> +lcdclk = port:PD24<2><0> +lcdde = port:PD25<2><0> +lcdhsync = port:PD26<2><0> +lcdvsync = port:PD27<2><0> + +;---------------------------------------------------------------------------------- +;lcd1 configuration + +;lcd_dclk_freq: in MHZ unit +;lcd_pwm_freq: in HZ unit +;lcd_if: 0:hv(sync+de); 1:8080; 2:ttl; 3:lvds +;lcd_hbp: hsync back porch +;lcd_ht: hsync total cycle +;lcd_vbp: vsync back porch +;lcd_vt: vysnc total cycle *2 +;lcd_hv_if: 0:hv parallel 1:hv serial +;lcd_hv_smode: 0:RGB888 1:CCIR656 +;lcd_hv_s888_if serial RGB format +;lcd_hv_syuv_if: serial YUV format +;lcd_hspw: hsync plus width +;lcd_vspw: vysnc plus width +;lcd_lvds_ch: 0:single channel; 1:dual channel +;lcd_lvds_mode: 0:NS mode; 1:JEIDA mode +;lcd_lvds_bitwidth: 0:24bit; 1:18bit +;lcd_lvds_io_cross: 0:normal; 1:pn cross +;lcd_cpu_if: 0:18bit; 1:16bit mode0; 2:16bit mode1; 3:16bit mode2; 4:16bit mode3; 5:9bit; 6:8bit 256K; 7:8bit 65K +;lcd_frm: 0:disable; 1:enable rgb666 dither; 2:enable rgb656 dither + +;lcd_gpio_0: SCL +;lcd_gpio_1 SDA +;---------------------------------------------------------------------------------- +[lcd1_para] +lcd_used = 0 + +lcd_x = 0 +lcd_y = 0 +lcd_dclk_freq = 0 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 1 +lcd_pwm_freq = 0 +lcd_pwm_pol = 0 +lcd_max_bright = 240 +lcd_min_bright = 64 +lcd_if = 0 +lcd_hbp = 0 +lcd_ht = 0 +lcd_vbp = 0 +lcd_vt = 0 +lcd_vspw = 0 +lcd_hspw = 0 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 0 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x00000000 +lcd_gamma_tbl_1 = 0x00010101 +lcd_gamma_tbl_255 = 0x00ffffff + +lcd_bl_en_used = 0 +lcd_bl_en = + +lcd_power_used = 0 +lcd_power = + +lcd_pwm_used = 1 +lcd_pwm = port:PI03<2><0> + +lcd_gpio_0 = +lcd_gpio_1 = +lcd_gpio_2 = +lcd_gpio_3 = + +lcdd0 = port:PH00<2><0> +lcdd1 = port:PH01<2><0> +lcdd2 = port:PH02<2><0> +lcdd3 = port:PH03<2><0> +lcdd4 = port:PH04<2><0> +lcdd5 = port:PH05<2><0> +lcdd6 = port:PH06<2><0> +lcdd7 = port:PH07<2><0> +lcdd8 = port:PH08<2><0> +lcdd9 = port:PH09<2><0> +lcdd10 = port:PH10<2><0> +lcdd11 = port:PH11<2><0> +lcdd12 = port:PH12<2><0> +lcdd13 = port:PH13<2><0> +lcdd14 = port:PH14<2><0> +lcdd15 = port:PH15<2><0> +lcdd16 = port:PH16<2><0> +lcdd17 = port:PH17<2><0> +lcdd18 = port:PH18<2><0> +lcdd19 = port:PH19<2><0> +lcdd20 = port:PH20<2><0> +lcdd21 = port:PH21<2><0> +lcdd22 = port:PH22<2><0> +lcdd23 = port:PH23<2><0> +lcdclk = port:PH24<2><0> +lcdde = port:PH25<2><0> +lcdhsync = port:PH26<2><0> +lcdvsync = port:PH27<2><0> + +;------------------------------------------------------------------------------- +;tv out dac configuration +;dacx_src: 0:composite; 1:luma; 2:chroma; 4:Y; 5:Pb; 6: Pr; 7:none +;------------------------------------------------------------------------------- +[tv_out_dac_para] +dac_used = 1 +dac0_src = 4 +dac1_src = 5 +dac2_src = 6 +dac3_src = 0 + +;---------------------------------------------------------------------------------- +;hdmi configuration +;---------------------------------------------------------------------------------- +[hdmi_para] +hdmi_used = 1 + + +[camera_list_para] +camera_list_para_used = 1 +ov7670 = 0 +gc0308 = 1 +gt2005 = 1 +hi704 = 0 +sp0838 = 0 +mt9m112 = 0 +mt9m113 = 0 +ov2655 = 0 +hi253 = 0 +gc0307 = 0 +mt9d112 = 0 +ov5640 = 0 +gc2015 = 0 +ov2643 = 0 +gc0329 = 0 +gc0309 = 0 +tvp5150 = 0 +s5k4ec = 0 +ov5650_mv9335 = 0 +siv121d = 0 +gc2035 = 0 + +;-------------------------------------------------------------------------------- +;csi gpio configuration +;csi_if: 0:hv_8bit 1:hv_16bit 2:hv_24bit 3:bt656 1ch 4:bt656 2ch 5:bt656 4ch +;csi_mode: 0:sample one csi to one buffer 1:sample two csi to one buffer +;csi_dev_qty: The quantity of devices linked to csi interface +;csi_vflip: flip in vertical direction 0:disable 1:enable +;csi_hflip: flip in horizontal direction 0:disable 1:enable +;csi_stby_mode: 0:not shut down power at standby 1:shut down power at standby +;csi_iovdd: camera module io power , pmu power supply +;csi_avdd: camera module analog power , pmu power supply +;csi_dvdd: camera module core power , pmu power supply +;pmu_ldo3: fill "axp20_pll" +;pmu_ldo4: fill "axp20_hdmi" +;fill "" when not using any pmu power supply +;csi_flash_pol: the active polority of the flash light IO 0:low active 1:high active +;-------------------------------------------------------------------------------- + +[csi0_para] +csi_used = 0 + +csi_dev_qty = 2 +csi_stby_mode = 0 +csi_mname = "gc0308" +csi_twi_id = 1 +csi_twi_addr = 0x42 +csi_if = 0 +csi_vflip = 0 +csi_hflip = 0 +csi_iovdd = "axp20_pll" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = 2800 +csi_vol_dvdd = +csi_vol_avdd = +csi_flash_pol = 0 + +csi_mname_b = "gt2005" +csi_twi_id_b = 1 +csi_twi_addr_b = 0x78 +csi_if_b = 0 +csi_vflip_b = 0 +csi_hflip_b = 0 +csi_iovdd_b = "axp20_pll" +csi_avdd_b = "" +csi_dvdd_b = "" +csi_vol_iovdd_b = 2800 +csi_vol_avdd_b = +csi_vol_dvdd_b = +csi_flash_pol_b = 0 + +csi_pck = port:PE00<3> +csi_ck = port:PE01<3> +csi_hsync = port:PE02<3> +csi_vsync = port:PE03<3> +csi_d0 = port:PE04<3> +csi_d1 = port:PE05<3> +csi_d2 = port:PE06<3> +csi_d3 = port:PE07<3> +csi_d4 = port:PE08<3> +csi_d5 = port:PE09<3> +csi_d6 = port:PE10<3> +csi_d7 = port:PE11<3> +csi_reset = port:PH14<1><0> +csi_power_en = port:PH17<1><0> +csi_stby = port:PH19<1><0> +csi_flash = +csi_af_en = +csi_reset_b = port:PH14<1><0> +csi_power_en_b = port:PH17<1><0> +csi_stby_b = port:PH18<1><0> +csi_flash_b = +csi_af_en_b = + +[csi1_para] +csi_used = 0 + +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "gc0308" +csi_if = 0 +csi_iovdd = "axp20_pll" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = 2800 +csi_vol_dvdd = +csi_vol_avdd = +csi_vflip = 0 +csi_hflip = 0 +csi_flash_pol = 0 +csi_facing = 1 + +csi_twi_id = 1 +csi_twi_addr = 0x42 +csi_pck = port:PG00<3> +csi_ck = port:PG01<3> +csi_hsync = port:PG02<3> +csi_vsync = port:PG03<3> +csi_d0 = port:PG04<3> +csi_d1 = port:PG05<3> +csi_d2 = port:PG06<3> +csi_d3 = port:PG07<3> +csi_d4 = port:PG08<3> +csi_d5 = port:PG09<3> +csi_d6 = port:PG10<3> +csi_d7 = port:PG11<3> +csi_reset = port:PH13<1><0> +csi_power_en = port:PH16<1><0> +csi_stby = port:PH19<1><0> + +;------------------------------------------------------------------------------- +;tv configuration +; +;------------------------------------------------------------------------------- +[tvout_para] +tvout_used = 1 +tvout_channel_num = 1 + +[tvin_para] +tvin_used = 0 +tvin_channel_num = 4 + +[pwm0_para] +pwm_used = 1 +pwm_period = 20 +pwm_duty_percent = 50 + +;------------------------------------------------------------------------------- +;sata configuration +; +;------------------------------------------------------------------------------- +[sata_para] +sata_used = 1 +sata_power_en = port:PB08<1><0> + + +;------------------------------------------------------------------------------- +; SDMMC PINS MAPPING +; ------------------------------------------------------------------------------ +; Config Guide +; sdc_used: 1-enable card, 0-disable card +; sdc_detmode: card detect mode +; 1-detect card by gpio polling +; 2-detect card by gpio irq(must use IO with irq function) +; 3-no detect, always in for boot card +; 4-manually insert and remove by /proc/driver/sunxi-mmc.x/insert +; sdc_buswidth: card bus width, 1-1bit, 4-4bit, 8-8bit +; sdc_use_wp: 1-with write protect IO, 0-no write protect IO +; sdc_isio: for sdio card +; sdc_regulator: power control. +; other: GPIO Mapping configuration +; ------------------------------------------------------------------------------ +; Note: +; 1 if detmode=2, sdc_det's config=6 +; else if detmode=1, sdc_det's config=0 +; else sdc_det IO is not necessary +; 2 if the customer wants to support UHS-I and HS200 features, he must provide +; an independent power supply for the card. This is only used in platforms +; that supports SD3.0 cards and eMMC4.4+ flashes +;------------------------------------------------------------------------------- +[mmc0_para] +sdc_used = 1 +sdc_detmode = 1 +sdc_buswidth = 4 +sdc_clk = port:PF02<2><1><2> +sdc_cmd = port:PF03<2><1><2> +sdc_d0 = port:PF01<2><1><2> +sdc_d1 = port:PF00<2><1><2> +sdc_d2 = port:PF05<2><1><2> +sdc_d3 = port:PF04<2><1><2> +sdc_det = port:PH1<0><1> +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc1_para] +sdc_used = 0 +sdc_detmode = 4 +sdc_buswidth = 4 +sdc_clk = port:PG00<2><1><2> +sdc_cmd = port:PG01<2><1><2> +sdc_d0 = port:PG02<2><1><2> +sdc_d1 = port:PG03<2><1><2> +sdc_d2 = port:PG04<2><1><2> +sdc_d3 = port:PG05<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc2_para] +sdc_used = 1 +sdc_detmode = 1 +sdc_buswidth = 4 +sdc_cmd = port:PC06<3><1><2> +sdc_clk = port:PC07<3><1><2> +sdc_d0 = port:PC08<3><1><2> +sdc_d1 = port:PC09<3><1><2> +sdc_d2 = port:PC10<3><1><2> +sdc_d3 = port:PC11<3><1><2> +sdc_det = port:PH0<0><1> +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc3_para] +sdc_used = 0 +sdc_detmode = 4 +sdc_buswidth = 4 +sdc_cmd = port:PI04<2><1><2> +sdc_clk = port:PI05<2><1><2> +sdc_d0 = port:PI06<2><1><2> +sdc_d1 = port:PI07<2><1><2> +sdc_d2 = port:PI08<2><1><2> +sdc_d3 = port:PI09<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 1 +sdc_regulator = "none" + +; ------------------------------------------------------------------------------ +; memory stick configuration +;------------------------------------------------------------------------------- +[ms_para] +ms_used = 0 +ms_bs = port:PH06<5> +ms_clk = port:PH07<5> +ms_d0 = port:PH08<5> +ms_d1 = port:PH09<5> +ms_d2 = port:PH10<5> +ms_d3 = port:PH11<5> +ms_det = + +; ------------------------------------------------------------------------------ +; sim card configuration +;------------------------------------------------------------------------------- +[smc_para] +smc_used = 0 +smc_rst = port:PH13<5> +smc_vppen = port:PH14<5> +smc_vppp = port:PH15<5> +smc_det = port:PH16<5> +smc_vccen = port:PH17<5> +smc_sck = port:PH18<5> +smc_sda = port:PH19<5> + +;------------------------------------------------------------------------------- +;ps2 configuration +;------------------------------------------------------------------------------- +[ps2_0_para] +ps2_used = 0 +ps2_scl = port:PI20<2><1> +ps2_sda = port:PI21<2><1> + +[ps2_1_para] +ps2_used = 0 +ps2_scl = port:PI14<3><1> +ps2_sda = port:PI15<3><1> + +;------------------------------------------------------------------------------- +;can bus configuration +;------------------------------------------------------------------------------- +[can_para] +can_used = 0 +can_tx = port:PA16<3> +can_rx = port:PA17<3> + +;------------------------------------------------------------------------------- +;key matrix +;------------------------------------------------------------------------------- +[keypad_para] +kp_used = 0 +kp_in_size = 8 +kp_out_size = 8 +kp_in0 = port:PH08<4><1> +kp_in1 = port:PH09<4><1> +kp_in2 = port:PH10<4><1> +kp_in3 = port:PH11<4><1> +kp_in4 = port:PH14<4><1> +kp_in5 = port:PH15<4><1> +kp_in6 = port:PH16<4><1> +kp_in7 = port:PH17<4><1> +kp_out0 = port:PH18<4><1> +kp_out1 = port:PH19<4><1> +kp_out2 = port:PH22<4><1> +kp_out3 = port:PH23<4><1> +kp_out4 = port:PH24<4><1> +kp_out5 = port:PH25<4><1> +kp_out6 = port:PH26<4><1> +kp_out7 = port:PH27<4><1> + + +;------------------------------------------------------------------------------- +;[usbc0]:控制器0的配置。 +;usb_used:USB使能标志。置1,表示系统中USB模块可用,置0,则表示系统USB禁用。 +;usb_port_type:USB端口的使用情况。 0:device only;1:host only;2:OTG +;usb_detect_type:USB端口的检查方式。0:不做检测;1:vbus/id检查;2:id/dpdm检查 +;usb_id_gpio:USB ID pin脚配置。具体请参考gpio配置说明。 +;usb_det_vbus_gpio:USB DET_VBUS pin脚配置。具体请参考gpio配置说明。 +;usb_drv_vbus_gpio:USB DRY_VBUS pin脚配置。具体请参考gpio配置说明。 +;usb_det_vbus_gpio: "axp_ctrl",表示axp 提供 +;usb_restrict_gpio usb限流控制pin +;usb_restric_flag: usb限流标置 +;------------------------------------------------------------------------------- +;------------------------------------------------------------------------------- +;--- USB0控制标志 +;------------------------------------------------------------------------------- +[usbc0] +usb_used = 1 +usb_port_type = 2 +usb_detect_type = 0 +usb_id_gpio = port:PH04<0><1> +usb_det_vbus_gpio = port:PH05<0><0> +usb_drv_vbus_gpio = port:PB09<1><0><0> +usb_restrict_gpio = port:PH00<1><0><0> +usb_host_init_state = 1 +usb_restric_flag = 0 +usb_restric_voltage = 3550000 +usb_restric_capacity= 5 + +;------------------------------------------------------------------------------- +;--- USB1控制标志 +;------------------------------------------------------------------------------ +[usbc1] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PH06<1><0><0> +usb_restrict_gpio = +usb_host_init_state = 1 +usb_restric_flag = 0 + +;------------------------------------------------------------------------------ +;--- USB2控制标志 +;------------------------------------------------------------------------------ +[usbc2] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PH03<1><0><0> +usb_restrict_gpio = + +usb_host_init_state = 1 +usb_restric_flag = 0 + +;-------------------------------- +;--- USB Device +;-------------------------------- +[usb_feature] +vendor_id = 0x18D1 +mass_storage_id = 0x0001 +adb_id = 0x0002 + +manufacturer_name = "USB Developer" +product_name = "Android" +serial_number = "20080411" + +[msc_feature] +vendor_name = "USB 2.0" +product_name = "USB Flash Driver" +release = 100 +luns = 3 + +;------------------------------------------------------------------------------- +; G sensor configuration +; gs_twi_id --- TWI ID for controlling Gsensor (0: TWI0, 1: TWI1, 2: TWI2) +;------------------------------------------------------------------------------- +[gsensor_para] +gsensor_used = 0 +gsensor_twi_id = 1 +gsensor_int1 = +gsensor_int2 = + +;-------------------------------------------------------------------------------- +; G sensor automatic detection configuration +;gsensor_detect_used --- Whether startup automatic inspection function. 1:used,0:unused +;Module name postposition 1 said detection, 0 means no detection. +;-------------------------------------------------------------------------------- +[gsensor_list_para] +gsensor_det_used = 1 +bma250 = 1 +mma8452 = 1 +mma7660 = 1 +mma865x = 1 +afa750 = 1 +lis3de_acc = 1 +lis3dh_acc = 1 +kxtik = 1 +dmard10 = 0 +dmard06 = 1 +mxc622x = 1 +fxos8700 = 1 +lsm303d = 1 + +;------------------------------------------------------------------------------- +; gps gpio configuration +; gps_spi_id --- the index of SPI controller. 0: SPI0, 1: SPI1, 2: SPI2, 15: no SPI used +; gps_spi_cs_num --- the chip select number of SPI controller. 0: SPI CS0, 1: SPI CS1 +; gps_lradc --- the lradc number for GPS used. 0 and 1 is valid, set 2 if not use lradc +;------------------------------------------------------------------------------- +[gps_para] +gps_used = 0 +gps_spi_id = 2 +gps_spi_cs_num = 0 +gps_lradc = 1 +gps_clk = port:PI00<2> +gps_sign = port:PI01<2> +gps_mag = port:PI02<2> +gps_vcc_en = port:PC22<1><0> +gps_osc_en = port:PI14<1><0> +gps_rx_en = port:PI15<1><0> + +;-------------------------------------------------------------------------------- +;wifi configuration +;wifi_sdc_id --- 0- SDC0, 1- SDC1, 2- SDC2, 3- SDC3 +;wifi_usbc_id --- 0- USB0, 1- USB1, 2- USB2 +;wifi_usbc_type -- 1- EHCI(speed 2.0), 2- OHCI(speed 1.0) +;wifi_mod_sel --- 0- none, 1- bcm40181, 2- bcm40183(wifi+bt), +; 3 - rtl8723as(wifi+bt), 4- rtl8189es(SM89E00), +; 5 - rtl8192cu, 6 - rtl8188eu, 7 - ap6210 +;-------------------------------------------------------------------------------- +[wifi_para] +wifi_used = 1 +wifi_sdc_id = 3 +wifi_usbc_id = 2 +wifi_usbc_type = 1 +wifi_mod_sel = 5 +wifi_power = "" + +[usb_wifi_para] +usb_wifi_used = 0 +usb_wifi_usbc_num = 2 + +; 1 - bcm40181 sdio wifi gpio config +;bcm40181_shdn = port:PH09<1><0> +;bcm40181_host_wake = port:PH10<0><0> + +; 2 - bcm40183 sdio wifi gpio config +;bcm40183_wl_regon = port:PH09<1><0> +;bcm40183_wl_host_wake = port:PH10<0><0> +;bcm40183_bt_rst = port:PB05<1><0> +;bcm40183_bt_regon = port:PB05<1><0> +;bcm40183_bt_wake = port:PI20<1><0> +;bcm40183_bt_host_wake = port:PI21<0><0> + +; 3 - rtl8723as sdio wifi + bt gpio config +rtk_rtl8723as_wl_dis = port:PH09<1><0> +rtk_rtl8723as_bt_dis = port:PB05<1><0> +rtk_rtl8723as_wl_host_wake = port:PH10<0><0> +rtk_rtl8723as_bt_host_wake = port:PI21<0><0> + +; 4 - rtl8189es sdio wifi gpio config +;rtl8189es_shdn = port:PH09<1><0> +;rtl8189es_wakeup = port:PH10<1><1> +; 5 - rtl8192cu usb wifi +; 6 - rtl8188eu usb wifi +; 7 - ap6210 sdio wifi + bt gpio config +ap6xxx_wl_regon = port:PH09<1><0> +ap6xxx_wl_host_wake = port:PH10<0><0> +ap6xxx_bt_regon = port:PB05<1><0> +ap6xxx_bt_wake = port:PI20<1><0> +ap6xxx_bt_host_wake = port:PI21<0><0> + +;------------------------------------------------------------------------------- +;3G configuration +;------------------------------------------------------------------------------- +[3g_para] +3g_used = 0 +3g_usbc_num = 2 +3g_uart_num = 0 +3g_pwr = +3g_wakeup = +3g_int = + +;------------------------------------------------------------------------------- +;gyroscope +;------------------------------------------------------------------------------- +[gy_para] +gy_used = 0 +gy_twi_id = 1 +gy_twi_addr = 0x00 +gy_int1 = port:PH18<6><1> +gy_int2 = port:PH19<6><1> + +;------------------------------------------------------------------------------- +;light sensor +;------------------------------------------------------------------------------- +[ls_para] +ls_used = 0 +ls_twi_id = 1 +ls_twi_addr = 0x00 +ls_int = port:PH20<6><1> + +;------------------------------------------------------------------------------- +;compass +;------------------------------------------------------------------------------- +[compass_para] +compass_used = 0 +compass_twi_id = 1 +compass_twi_addr = 0x00 +compass_int = port:PI13<6><1> + +;------------------------------------------------------------------------------- +;blue tooth +;bt_used ---- blue tooth used (0- no used, 1- used) +;bt_uard_id ---- uart index +;------------------------------------------------------------------------------- +[bt_para] +bt_used = 0 +bt_uart_id = 2 +bt_wakeup = port:PI20<1> +bt_gpio = port:PI21<1> +bt_rst = port:PB05<1> + +[i2s_para] +i2s_used = 0 +i2s_channel = 2 +i2s_mclk = port:PB5<2><1> +i2s_bclk = port:PB6<2><1> +i2s_lrclk = port:PB7<2><1> +i2s_dout0 = port:PB8<2><1> +i2s_dout1 = +i2s_dout2 = +i2s_dout3 = +i2s_din = port:PB12<2><1> + +[spdif_para] +spdif_used = 0 +spdif_mclk = +spdif_dout = port:PB13<4><1> +spdif_din = + +[audio_para] +audio_used = 1 +audio_pa_ctrl = port:PH15<1><1> + +[switch_para] +switch_used = 1 + +[leds_para] +leds_used = 1 +leds_num = 2 +leds_pin_1 = port:PH20<1><0> +leds_name_1 = "green:ph20:led1" +leds_default_1 = 1 +leds_pin_2 = port:PH21<1><0> +leds_name_2 = "blue:ph21:led2" +leds_default_2 = 0 +leds_trigger_2 = "heartbeat" + +;------------------------------------------------------------------------------- +;ir --- infra remote configuration +;------------------------------------------------------------------------------- +[ir_para] +ir_used = 1 +ir0_rx = port:PB04<2> + + +;------------------------------------------------------------------------------- +;pmu_twi_addr ---slave address +;pmu_twi_id ---i2c bus number (0 TWI0, 1 TWI2, 2 TWI3) +;pmu_irq_id ---irq number (0 irq0,1 irq1,……) +;pmu_battery_rdc ---battery initial resistance,mΩ,根据实际电池内阻填写 +;pmu_battery_cap ---battery capability,mAh,根据实际电池容量填写 +;pmu_init_chgcur ---set initial charging current limite,mA,300/400/500/600/700/800/900/1000/1100/1200/1300/1400/1500/1600/1700/1800 +;pmu_suspend_chgcur ---set suspend charging current limite,mA,300/400/500/600/700/800/900/1000/1100/1200/1300/1400/1500/1600/1700/1800 +;pmu_resume_chgcur ---set resume charging current limite,mA,300/400/500/600/700/800/900/1000/1100/1200/1300/1400/1500/1600/1700/1800 +;pmu_shutdown_chgcur ---set shutdown charging current limite,mA,300/400/500/600/700/800/900/1000/1100/1200/1300/1400/1500/1600/1700/1800 +;pmu_init_chgvol ---set initial charing target voltage,mV,4100/4150/4200/4360 +;pmu_init_chgend_rate ---set initial charing end current rate,10/15 +;pmu_init_chg_enabled ---set initial charing enabled,0:关闭,1:打开 +;pmu_init_adc_freq ---set initial adc frequency,Hz,25/50/100/200 +;pmu_init_adc_freqc ---set initial coulomb adc coufrequency,Hz,25/50/100/200 +;pmu_init_chg_pretime ---set initial pre-charging time,min,40/50/60/70 +;pmu_init_chg_csttime ---set initial constance-charging time,min,360/480/600/720 +;pmu_bat_para1 ---battery indication at 3.1328V +;pmu_bat_para2 ---battery indication at 3.2736V +;pmu_bat_para3 ---battery indication at 3.4144V +;pmu_bat_para4 ---battery indication at 3.5552V +;pmu_bat_para5 ---battery indication at 3.6256V +;pmu_bat_para6 ---battery indication at 3.6608V +;pmu_bat_para7 ---battery indication at 3.6960V +;pmu_bat_para8 ---battery indication at 3.7312V +;pmu_bat_para9 ---battery indication at 3.7664V +;pmu_bat_para10 ---battery indication at 3.8016V +;pmu_bat_para11 ---battery indication at 3.8368V +;pmu_bat_para12 ---battery indication at 3.8720V +;pmu_bat_para13 ---battery indication at 3.9424V +;pmu_bat_para14 ---battery indication at 4.0128V +;pmu_bat_para15 ---battery indication at 4.0832V +;pmu_bat_para16 ---battery indication at 4.1536V +;pmu_usbvol ---set usb-ac limited voltage level,mV,4000/4100/4200/4300/4400/4500/4600/4700,0 - not limite +;pmu_usbcur ---set usb-ac limited voltage level,mA,100/500/900, 0 - not limite +;pmu_usbvol_pc ---set usb-pc limited voltage level,mV,4000/4100/4200/4300/4400/4500/4600/4700,0 - not limite +;pmu_usbcur_pc ---set usb-pc limited voltage level,mA,100/500/900, 0 - not limite +;pmu_pwroff_vol ---set protect voltage when system start up,mV,2600/2700/2800/2900/3000/3100/3200/3300 +;pmu_pwron_vol ---set protect voltage after system start up,mV,2600/2700/2800/2900/3000/3100/3200/3300 +;pmu_pekoff_time ---set pek off time,ms, 4000/6000/8000/10000 +;pmu_pekoff_en ---set pek off enable, 0:关闭,1:打开 +;pmu_peklong_time ---set pek pek long irq time,ms,1000/1500/2000/2500 +;pmu_pekon_time ---set pek on time,ms,128/1000/2000/3000 +;pmu_pwrok_time ---set pmu pwrok delay time,ms,8/64 +;pmu_pwrnoe_time ---set pmu n_oe power down delay time,ms,128/1000/2000/3000 +;pmu_intotp_en ---set pmu power down when overtempertur enable,0:关闭,1:打开 +;pmu_suspendpwroff_vol ---set pmu shutdown voltage when cpu is suspend and battery voltage is low +;pmu_batdeten ---set pmu battery detect enabled,0:关闭,1:打开 +;------------------------------------------------------------------------------- +[pmu_para] +pmu_used = 1 +pmu_twi_addr = 0x34 +pmu_twi_id = 0 +pmu_irq_id = 32 +pmu_battery_rdc = 120 +pmu_battery_cap = 2100 +pmu_init_chgcur = 300 +pmu_earlysuspend_chgcur = 600 +pmu_suspend_chgcur = 1000 +pmu_resume_chgcur = 300 +pmu_shutdown_chgcur = 1000 +pmu_init_chgvol = 4200 +pmu_init_chgend_rate = 15 +pmu_init_chg_enabled = 1 +pmu_init_adc_freq = 100 +pmu_init_adc_freqc = 100 +pmu_init_chg_pretime = 50 +pmu_init_chg_csttime = 720 + +pmu_bat_para1 = 0 +pmu_bat_para2 = 0 +pmu_bat_para3 = 0 +pmu_bat_para4 = 0 +pmu_bat_para5 = 5 +pmu_bat_para6 = 11 +pmu_bat_para7 = 13 +pmu_bat_para8 = 15 +pmu_bat_para9 = 19 +pmu_bat_para10 = 32 +pmu_bat_para11 = 50 +pmu_bat_para12 = 58 +pmu_bat_para13 = 71 +pmu_bat_para14 = 81 +pmu_bat_para15 = 89 +pmu_bat_para16 = 100 + +pmu_usbvol_limit = 1 +pmu_usbcur_limit = 0 +pmu_usbvol = 4000 +pmu_usbcur = 0 + +pmu_usbvol_pc = 4200 +pmu_usbcur_pc = 0 + +pmu_pwroff_vol = 3300 +pmu_pwron_vol = 2900 + +pmu_pekoff_time = 6000 +pmu_pekoff_en = 1 +pmu_peklong_time = 1500 +pmu_pekon_time = 1000 +pmu_pwrok_time = 64 +pmu_pwrnoe_time = 2000 +pmu_intotp_en = 1 + +pmu_used2 = 0 +pmu_adpdet = port:PH02<0> +pmu_init_chgcur2 = 400 +pmu_earlysuspend_chgcur2 = 600 +pmu_suspend_chgcur2 = 1200 +pmu_resume_chgcur2 = 400 +pmu_shutdown_chgcur2 = 1200 + +pmu_suspendpwroff_vol = 3500 + +pmu_batdeten = 1 + +[recovery_key] +key_min = 4 +key_max = 40 + +;---------------------------------------------------------------------------------- +; dvfs voltage-frequency table configuration +; +; max_freq: cpu maximum frequency, based on Hz, can not be more than 1008MHz +; min_freq: cpu minimum frequency, based on Hz, can not be less than 60MHz +; +; LV_count: count of LV_freq/LV_volt, must be < 16 +; +; LV1: core vdd is 1.45v if cpu frequency is (912Mhz, 1008Mhz] +; LV2: core vdd is 1.40v if cpu frequency is (864Mhz, 912Mhz] +; LV3: core vdd is 1.30v if cpu frequency is (720Mhz, 864Mhz] +; LV4: core vdd is 1.20v if cpu frequency is (528Mhz, 720Mhz] +; LV5: core vdd is 1.10v if cpu frequency is (312Mhz, 528Mhz] +; LV6: core vdd is 1.00v if cpu frequency is (144Mhz, 312Mhz] +; LV7: core vdd is 0.90v if cpu frequency is (60Mhz, 144Mhz] +; +;---------------------------------------------------------------------------------- +[dvfs_table] +max_freq = 912000000 +min_freq = 720000000 +normal_freq = 720000000 + +LV_count = 7 + +LV1_freq = 1008000000 +LV1_volt = 1450 + +LV2_freq = 912000000 +LV2_volt = 1425 + +LV3_freq = 864000000 +LV3_volt = 1350 + +LV4_freq = 720000000 +LV4_volt = 1250 + +LV5_freq = 528000000 +LV5_volt = 1150 + +LV6_freq = 312000000 +LV6_volt = 1100 + +LV7_freq = 144000000 +LV7_volt = 1050 + +[boot_disp] +output_type = 3 +output_mode = 4 +auto_hpd = 1 + diff --git a/config/cubieboard4.fex b/config/cubieboard4.fex deleted file mode 100644 index d47f39a74..000000000 --- a/config/cubieboard4.fex +++ /dev/null @@ -1,1829 +0,0 @@ -;A80 PAD application -;--------------------------------------------------------------------------------------------------------- -; 说明: 脚本中的字符串区分大小写,用户可以修改"="后面的数值,但是不要修改前面的字符串 -; 描述gpio的形式:Port:端口+组内序号<功能分配><内部电阻状态><驱动能力><输出电平状态> -;--------------------------------------------------------------------------------------------------------- - -[product] -version = "100" -machine = "cubieboard4" - -[platform] -eraseflag = 0 -;---------------------------------------------------------------------------------- -; system configuration -; ? -;dcdc1_vol ---set dcdc1 voltage,mV,1600-3400,100mV/step -;dcdc2_vol ---set dcdc2 voltage,mV,600-1540,20mV/step -;dcdc3_vol ---set dcdc3 voltage,mV,600-1860,20mV/step -;dcdc4_vol ---set dcdc4 voltage,mV,600-1540,20mV/step -;dcdc5_vol ---set dcdc5 voltage,mV,1000-2550,50mV/step -;aldo2_vol ---set aldo2 voltage,mV,700-3300,100mV/step -;aldo3_vol ---set aldo3 voltage,mV,700-3300,100mV/step -;---------------------------------------------------------------------------------- -[target] -boot_clock = 1008 -storage_type = -1 -[charging_type] -charging_type = 1 -;--------------------------------------------------------------------------------- -; uboot key detect enable -; 当keyen_flag = 1 时,支持按键检测 -; 当keyen_flag = 0 时,不支持 -;--------------------------------------------------------------------------------- -[key_detect_en] -keyen_flag = 0 - -;---------------------------------------------------------------------------------- -; -; 各路电压输出语法说明: -; -; 电压名称 = 100XXXX : 表示把该路电压设置为XXXX指定的电压值,同时打开输出开关 -; 电压名称 = 000XXXX : 表示把该路电压设置为XXXX指定的电压值,同时关闭输出开关,当有需要时由内核驱动打开 -; 电压名称 = 0 : 表示关闭该路电压输出开关,不修改原有的值 -; -;---------------------------------------------------------------------------------- -[power_sply] -dcdc1_vol = 1003000 -dcdc2_vol = 900 -dcdc3_vol = 1000900 -dcdc4_vol = 1000900 -dcdc5_vol = 1001500 -dc5ldo_vol = 1000900 -dldo2_vol = 1003000 -eldo3_vol = 1001800 -aldo1_vol = 1003000 -aldo3_vol = 1003000 -gpio1_vol = 0002500 - -[slave_power_sply] -dcdca_vol = 1000900 -dcdcb_vol = 0 -dcdcc_vol = 0 -dcdcd_vol = 1000900 -dcdce_vol = 1002100 -aldo1_vol = 1003000 -bldo1_vol = 1001800 -bldo2_vol = 1001800 -cldo1_vol = 0003000 - -[gpio_bias] -pa_bias = "axp809:gpio1:2500" -pb_bias = "axp809:aldo2:1800" -pc_bias = "axp809:dcdc1:3000" -pd_bias = "axp806:bldo1:1800" -pe_bias = "axp809:eldo2:1800" -pf_bias = "axp809:dcdc1:3000" -pg_bias = "axp809:gpio0:3000" -ph_bias = "axp809:dcdc1:3000" -pl_bias = "axp809:dldo2:3000" -pm_bias = "axp809:eldo3:3000" - -[card_boot] -logical_start = 40960 -sprite_gpio0 = -next_work = 3 - - -;--------------------------------------------------------------------------------------------------------- -; if 1 == standby_mode, then support super standby; -; else, support normal standby. -;--------------------------------------------------------------------------------------------------------- -[pm_para] -standby_mode = 1 - -[card0_boot_para] -card_ctrl = 0 -card_high_speed = 1 -card_line = 4 -sdc_d1 = port:PF00<2><1> -sdc_d0 = port:PF01<2><1> -sdc_clk = port:PF02<2><1> -sdc_cmd = port:PF03<2><1> -sdc_d3 = port:PF04<2><1> -sdc_d2 = port:PF05<2><1> - -[card2_boot_para] -card_ctrl = 2 -card_high_speed = 1 -card_line = 4 -sdc_cmd = port:PC06<3><1> -sdc_clk = port:PC07<3><1> -sdc_d0 = port:PC08<3><1> -sdc_d1 = port:PC09<3><1> -sdc_d2 = port:PC10<3><1> -sdc_d3 = port:PC11<3><1> - -[boot_disp] -output_disp = 1 -output_type = 3 -output_mode = 4 -auto_hpd = 1 - -[twi_para] -twi_port = 0 -twi_scl = port:PH14<2> -twi_sda = port:PH15<2> - -[uart_para] -uart_debug_port = 0 -uart_debug_tx = port:PH12<2><1> -uart_debug_rx = port:PH13<2><1> - -[jtag_para] -jtag_enable = 1 -jtag_ms = port:PF00<3> -jtag_ck = port:PF05<3> -jtag_do = port:PF03<3> -jtag_di = port:PF01<3> - -[clock] -pll4 = 300 -pll6 = 600 -pll8 = 297 -pll9 = 297 -pll10 = 2376 - -;***************************************************************************** -;sdram configuration -; -;dram_para2 = 0x00001200 ;代表启用dram双通道 -; -;dram_para2 = 0x00001100 ;代表启用dram单通道 -; -;***************************************************************************** -[dram_para] -dram_clk = 672 -dram_type = 3 -dram_zq = 0x003F3FDD -dram_odt_en = 1 -dram_para1 = 0x10f41000 -dram_para2 = 0x00001200 -dram_mr0 = 0x1A50 -dram_mr1 = 0x40 -dram_mr2 = 0x10 -dram_mr3 = 0 -dram_tpr0 = 0x04E214EA -dram_tpr1 = 0x004214AD -dram_tpr2 = 0x10A75030 -dram_tpr3 = 0 -dram_tpr4 = 0 -dram_tpr5 = 0 -dram_tpr6 = 0 -dram_tpr7 = 0 -dram_tpr8 = 0 -dram_tpr9 = 0 -dram_tpr10 = 0 -dram_tpr11 = 0 -dram_tpr12 = 168 -dram_tpr13 = 0x23 -;---------------------------------------------------------------------------------- -;os life cycle para configuration -;---------------------------------------------------------------------------------- - -;------------------------------------------------------------------------------; -; 10/100/100Mbps Ethernet MAC Controller Configure ; -;------------------------------------------------------------------------------; -; 配置选项: ; -; gmac_used --- 1: gmac used, 0: not used ; -; gmac_powerx -- A[:B] A: axp channel, B: voltage value ; -;------------------------------------------------------------------------------; -; MII GMII RGMII MII GMII RGMII MII GMII RGMII ; -;PA00~03 * * * PA10 * * PA20 * * * ; -; PA04 * PA11~14 * * * PA21 * * ; -; PA05 * PA15 * PA22 * * ; -; PA06 * PA16 * PA23 * * ; -; PA07 * PA17 * PA24 * * ; -; PA08 * * PA18 * PA25 * * ; -; PA09 * * * PA19 * * * PA26~27 * * * ; -;------------------------------------------------------------------------------; -[gmac0] -gmac_used = 1 -gmac_rxd3 = port:PA00<2><3> -gmac_rxd2 = port:PA01<2><3> -gmac_rxd1 = port:PA02<2><3> -gmac_rxd0 = port:PA03<2><3> -gmac_rxclk = port:PA04<2><3> -gmac_rxdv = port:PA05<2><3> -;gmac_rxerr = port:PA06<2><3> -gmac_txd3 = port:PA07<2><3> -gmac_txd2 = port:PA08<2><3> -gmac_txd1 = port:PA09<2><3> -gmac_txd0 = port:PA10<2><3> -;gmac_crs = port:PA11<2><3> -gmac_txclk = port:PA12<2><3> -gmac_txen = port:PA13<2><3> -gmac_txerr = port:PA14<2><3> -gmac_col = port:PA15<2><3> -gmac_mdc = port:PA16<2><3> -gmac_mdio = port:PA17<2><3> -gmac_power1 = "axp15_cldo1:3000000" -gmac_power2 = "axp22_ldoio1" - -;--------------------------------------------------------------------------------------------------------- -; wakeup_src_para: -; sometimes, u would like to add more wakeup src in standby mode, these para will be -; help; -; u need to make sure the standby mode support the wakeup src. Also, some hw -; condition must be guaranteed. -; including: -; cpu_en: power on or off. -; 1: mean power on -; 0: mean power off -; cpu_freq: indicating lowest freq. unit is Mhz; -; dram selfresh_en: selfresh or not. -; 1: enable enter selfresh -; 0: disable enter selfresh -; dram_pll: if not enter selfresh, indicating lowest freq. unit is Mhz; -; wakeup_src: to make the scenario work, the wakeup src is needed. -;--------------------------------------------------------------------------------------------------------- -[wakeup_src_para] -cpu_en = 0 -cpu_freq = 48 -; (cpu:apb:ahb) -pll_ratio = 0x111 -dram_selfresh_en = 1 -dram_freq = 36 -wakeup_src0 = -wakeup_src_wl = port:PL03<4><0> -wakeup_src_bt = port:PL04<4><0> -bb_wake_ap = port:PM01<4><0> - -;---------------------------------------------------------------------------------- -;i2c configuration -;---------------------------------------------------------------------------------- -[twi0] -twi_used = 1 -twi_scl = port:PH0<2> -twi_sda = port:PH1<2> - -[twi1] -twi_used = 1 -twi_scl = port:PH2<2> -twi_sda = port:PH3<2> - -[twi2] -twi_used = 1 -twi_scl = port:PH4<2> -twi_sda = port:PH5<2> - -[twi3] -twi_used = 0 -twi_scl = port:PG10<2> -twi_sda = port:PG11<2> - -[twi4] -twi_used = 0 -twi_scl = port:PB15<4> -twi_sda = port:PB16<4> - -;---------------------------------------------------------------------------------- -;uart configuration -;uart_type --- 2 (2 wire), 4 (4 wire), 8 (8 wire, full function) -;---------------------------------------------------------------------------------- -[uart0] -uart_used = 1 -uart_port = 0 -uart_type = 2 -uart_tx = port:PH12<2><1> -uart_rx = port:PH13<2><1> - -[uart1] -uart_used = 0 -uart_port = 1 -uart_type = 8 -uart_tx = port:PA0<4><1> -uart_rx = port:PA1<4><1> -uart_rts = port:PA2<4><1> -uart_cts = port:PA3<4><1> -;uart_dtr = port:PA4<4><1> -;uart_dsr = port:PA5<4><1> -;uart_dcd = port:PA6<4><1> -;uart_ring = port:PA7<4><1> - -[uart2] -uart_used = 1 -uart_port = 2 -uart_type = 4 -uart_tx = port:PG06<2><1> -uart_rx = port:PG07<2><1> -uart_rts = port:PG08<2><1> -uart_cts = port:PG09<2><1> - -[uart3] -uart_used = 0 -uart_port = 3 -uart_type = 4 -uart_tx = port:PB05<3><1> -uart_rx = port:PB06<3><1> -uart_rts = port:PB04<3><1> -uart_cts = port:PB00<3><1> - -[uart4] -uart_used = 1 -uart_port = 4 -uart_type = 4 -uart_tx = port:PG12<2><1> -uart_rx = port:PG13<2><1> -uart_rts = port:PG14<2><1> -uart_cts = port:PG15<2><1> - -[uart5] -uart_used = 1 -uart_port = 5 -uart_type = 2 -uart_tx = port:PE04<4><1> -uart_rx = port:PE05<4><1> - - - -;---------------------------------------------------------------------------------- -;SPI controller configuration -;---------------------------------------------------------------------------------- -[spi0] -spi_used = 0 -spi_cs_bitmap = 1 -spi_cs0 = port:PC19<3><1> -spi_sclk = port:PC02<3> -spi_mosi = port:PC00<3> -spi_miso = port:PC01<3> - -[spi1] -spi_used = 0 -spi_cs_bitmap = 1 -spi_cs0 = -spi_sclk = -spi_mosi = -spi_miso = - -[spi2] -spi_used = 0 -spi_cs_bitmap = 1 -spi_cs0 = port:PE04<3><1> -spi_sclk = port:PE05<3> -spi_mosi = port:PE06<3> -spi_miso = port:PE07<3> - -[spi3] -spi_used = 0 -spi_cs_bitmap = 1 -spi_cs0 = port:PH17<2><1> -spi_cs1 = port:PH18<2><1> -spi_cs2 = port:PH12<3><1> -spi_cs3 = port:PH13<3> -spi_sclk = port:PH14<2> -spi_mosi = port:PH15<2> -spi_miso = port:PH16<2> - -;---------------------------------------------------------------------------------- -;SPI device configuration -;---------------------------------------------------------------------------------- -[spi_devices] -spi_dev_num = 1 - -[spi_board0] -modalias = "m25p32" -max_speed_hz = 33000000 -bus_num = 0 -chip_select = 0 -mode = 0 - -;---------------------------------------------------------------------------------- -;resistance tp configuration -;---------------------------------------------------------------------------------- -[rtp_para] -rtp_used = 0 -rtp_screen_size = 5 -rtp_regidity_level = 5 -rtp_press_threshold_enable = 0 -rtp_press_threshold = 0x1f40 -rtp_sensitive_level = 0xf -rtp_exchange_x_y_flag = 0 - -;---------------------------------------------------------------------------------- -;capacitor tp configuration -;external int function -;wakeup output function -;notice --- tp_int_port & tp_io_port use the same port -;---------------------------------------------------------------------------------- -[ctp_para] -ctp_used = 0 -ctp_twi_id = 1 -ctp_twi_addr = 0x5d -ctp_screen_max_x = 1280 -ctp_screen_max_y = 800 -ctp_revert_x_flag = 1 -ctp_revert_y_flag = 1 -ctp_exchange_x_y_flag = 1 - -ctp_int_port = -ctp_wakeup = - -;-------------------------------------------------------------------------------- -; CTP automatic detection configuration -;ctp_detect_used --- Whether startup automatic inspection function. 1:used,0:unused -;Module name postposition 1 said detection, 0 means no detection. -;-------------------------------------------------------------------------------- -[ctp_list_para] -ctp_det_used = 1 -ft5x_ts = 1 -gt82x = 1 -gslX680 = 1 -gt9xx_ts = 1 -gt811 = 1 -zet622x = 1 -aw5306_ts = 1 - -;---------------------------------------------------------------------------------- -;touch key configuration -;---------------------------------------------------------------------------------- -[tkey_para] -tkey_used = 0 -tkey_twi_id = -tkey_twi_addr = -tkey_int = - -;---------------------------------------------------------------------------------- -;motor configuration -;---------------------------------------------------------------------------------- -[motor_para] -motor_used = 0 -motor_shake = 0 -motor_ldo = axp22_ldoio0 -motor_ldo_voltage = 3300 - -;---------------------------------------------------------------------------------- -;thermal configuration -;---------------------------------------------------------------------------------- -[ths_para] -ths_used = 1 -ths_trend = 0 -ths_trip1_count = 5 -ths_trip1_0 = 60 -ths_trip1_1 = 75 -ths_trip1_2 = 85 -ths_trip1_3 = 95 -ths_trip1_4 = 105 -ths_trip1_5 = 0 -ths_trip1_6 = 0 -ths_trip1_7 = 0 -ths_trip1_0_min = 0 -ths_trip1_0_max = 1 -ths_trip1_1_min = 1 -ths_trip1_1_max = 2 -ths_trip1_2_min = 2 -ths_trip1_2_max = 5 -ths_trip1_3_min = 5 -ths_trip1_3_max = 9 -ths_trip1_4_min = 0 -ths_trip1_4_max = 0 -ths_trip1_5_min = 0 -ths_trip1_5_max = 0 -ths_trip1_6_min = 0 -ths_trip1_6_max = 0 -ths_trip2_count = 1 -ths_trip2_0 = 105 -;---------------------------------------------------------------------------------- -;cooler_table cooler_count <=32 -;---------------------------------------------------------------------------------- -[cooler_table] -cooler_count = 10 -cooler0 = "1200000 4 1800000 4" -cooler1 = "1200000 4 1608000 4" -cooler2 = "1200000 4 1440000 4" -cooler3 = "1200000 4 1200000 4" -cooler4 = "1200000 4 1200000 3" -cooler5 = "1200000 4 1440000 2" -cooler6 = "1200000 4 1200000 2" -cooler7 = "1200000 4 1200000 1" -cooler8 = "1200000 4 4294967295 0" -cooler9 = "600000 4 4294967295 0" -;---------------------------------------------------------------------------------- - -[nand0_para] -nand_support_2ch = 0 - -nand0_used = 0 -nand0_we = port:PC00<2> -nand0_ale = port:PC01<2> -nand0_cle = port:PC02<2> -nand0_ce1 = port:PC03<2> -nand0_ce0 = port:PC04<2> -nand0_nre = port:PC05<2> -nand0_rb0 = port:PC06<2> -nand0_rb1 = port:PC07<2> -nand0_d0 = port:PC08<2> -nand0_d1 = port:PC09<2> -nand0_d2 = port:PC10<2> -nand0_d3 = port:PC11<2> -nand0_d4 = port:PC12<2> -nand0_d5 = port:PC13<2> -nand0_d6 = port:PC14<2> -nand0_d7 = port:PC15<2> -nand0_ce2 = port:PC17<2> -nand0_ce3 = port:PC18<2> -nand0_ndqs = port:PC16<2> - -[nand1_para] -nand1_used = 0 -nand1_we = port:PC00<2> -nand1_ale = port:PC01<2> -nand1_cle = port:PC03<2> -nand1_ce1 = port:PC03<2> -nand1_ce0 = port:PC04<2> -nand1_nre = port:PC05<2> -nand1_rb0 = port:PC06<2> -nand1_rb1 = port:PC07<2> -nand1_d0 = port:PC08<2> -nand1_d1 = port:PC09<2> -nand1_d2 = port:PC10<2> -nand1_d3 = port:PC11<2> -nand1_d4 = port:PC12<2> -nand1_d5 = port:PC13<2> -nand1_d6 = port:PC14<2> -nand1_d7 = port:PC15<2> -nand1_ce2 = port:PC17<2> -nand1_ce3 = port:PC18<2> -nand1_ndqs = port:PC16<2> - -;---------------------------------------------------------------------------------- -;disp init configuration -; -;disp_mode (0:screen0) -;screenx_output_type (0:none; 1:lcd; 3:hdmi;) -;screenx_output_mode (used for hdmi output, 0:480i 1:576i 2:480p 3:576p 4:720p50) -; (5:720p60 6:1080i50 7:1080i60 8:1080p24 9:1080p50 10:1080p60) -;fbx format (0:ARGB 1:ABGR 2:RGBA 3:BGRA) -;fbx_width,fbx_height (framebuffer horizontal/vertical pixels, fix to output resolution while equal 0) -;lcdx_backlight (lcd init backlight,the range:[0,256],default:197 -;lcdx_yy (lcd init screen bright/contrast/saturation/hue, value:0~100, default:50/50/57/50) -;---------------------------------------------------------------------------------- -[disp_init] -disp_composer_mode = 1 - -disp_init_enable = 1 -disp_mode = 0 - -screen0_output_type = 1 -screen0_output_mode = 1 - -screen1_output_type = 3 -screen1_output_mode = 10 - -fb0_format = 0 -fb0_scaler_mode_enable = 0 -fb0_width = 0 -fb0_height = 0 - -fb1_format = 0 -fb1_scaler_mode_enable = 0 -fb1_width = 0 -fb1_height = 0 - -lcd0_backlight = 197 -lcd1_backlight = 197 - -lcd0_bright = 50 -lcd0_contrast = 50 -lcd0_saturation = 57 -lcd0_hue = 50 - -lcd1_bright = 50 -lcd1_contrast = 50 -lcd1_saturation = 57 -lcd1_hue = 50 - -;---------------------------------------------------------------------------------- -;lcd0 configuration - -;lcd_if: 0:hv(sync+de); 1:8080; 2:ttl; 3:lvds; 4:dsi; 5:edp -;lcd_x: lcd horizontal resolution -;lcd_y: lcd vertical resolution -;lcd_width: width of lcd in mm -;lcd_height: height of lcd in mm -;lcd_dclk_freq: in MHZ unit -;lcd_pwm_freq: in HZ unit -;lcd_pwm_pol: lcd backlight PWM polarity -;lcd_pwm_max_limit lcd backlight PWM max limit(<=255) -;lcd_hbp: hsync back porch -;lcd_ht: hsync total cycle -;lcd_vbp: vsync back porch -;lcd_vt: vysnc total cycle -;lcd_hspw: hsync plus width -;lcd_vspw: vysnc plus width -;lcd_lvds_if: 0:single link; 1:dual link -;lcd_lvds_colordepth: 0:8bit; 1:6bit -;lcd_lvds_mode: 0:NS mode; 1:JEIDA mode -;lcd_frm: 0:disable; 1:enable rgb666 dither; 2:enable rgb656 dither -;lcd_gamma_en lcd gamma correction enable -;lcd_bright_curve_en lcd bright curve correction enable -;lcd_cmap_en lcd color map function enable -;deu_mode 0:smoll lcd screen; 1:large lcd screen(larger than 10inch) -;lcdgamma4iep: Smart Backlight parameter, lcd gamma vale * 10; -; decrease it while lcd is not bright enough; increase while lcd is too bright -;smart_color 90:normal lcd screen 65:retina lcd screen(9.7inch) - -;vga_used if need vga,lcd_used must be 1,in that case,vga_used is 1 means output to vga -;---------------------------------------------------------------------------------- -[lcd0_para] -lcd_used = 1 -vga_used = 1 -lcd_driver_name = "default_lcd" -lcd_if = 0 -lcd_x = 1024 -lcd_y = 768 -lcd_width = 150 -lcd_height = 94 -lcd_dclk_freq = 65 -lcd_pwm_used = 0 -lcd_pwm_ch = 0 -lcd_pwm_freq = 50000 -lcd_pwm_pol = 0 -lcd_hbp = 296 -lcd_ht = 1344 -lcd_hspw = 136 -lcd_vbp = 35 -lcd_vt = 806 -lcd_vspw = 6 -lcd_lvds_if = 0 -lcd_lvds_colordepth = 0 -lcd_lvds_mode = 0 -lcd_frm = 0 -lcd_hv_clk_phase = 0 -lcd_hv_sync_polarity = 0 -lcd_gamma_en = 0 -lcd_bright_curve_en = 0 -lcd_cmap_en = 0 - -deu_mode = 0 -lcdgamma4iep = 22 -smart_color = 90 - -;lcd_bl_en = port:PA6<1><0><1> -lcd_power = port:power2<1><0><1> - -lcdd0 = port:PD00<2><0> -lcdd1 = port:PD01<2><0> -lcdd2 = port:PD02<2><0> -lcdd3 = port:PD03<2><0> -lcdd4 = port:PD04<2><0> -lcdd5 = port:PD05<2><0> -lcdd6 = port:PD06<2><0> -lcdd7 = port:PD07<2><0> -lcdd8 = port:PD08<2><0> -lcdd9 = port:PD09<2><0> -lcdd10 = port:PD10<2><0> -lcdd11 = port:PD11<2><0> -lcdd12 = port:PD12<2><0> -lcdd13 = port:PD13<2><0> -lcdd14 = port:PD14<2><0> -lcdd15 = port:PD15<2><0> -lcdd16 = port:PD16<2><0> -lcdd17 = port:PD17<2><0> -lcdd18 = port:PD18<2><0> -lcdd19 = port:PD19<2><0> -lcdd20 = port:PD20<2><0> -lcdd21 = port:PD21<2><0> -lcdd22 = port:PD22<2><0> -lcdd23 = port:PD23<2><0> -lcdclk = port:PD24<2><0> -lcdde = port:PD25<2><0> -lcdhsync = port:PD26<2><0><3> -lcdvsync = port:PD27<2><0><3> - -;---------------------------------------------------------------------------------- -;hdmi configuration -;---------------------------------------------------------------------------------- -[hdmi_para] -hdmi_used = 1 - -;---------------------------------------------------------------------------------- -;pwm config -;---------------------------------------------------------------------------------- -[pwm0_para] -pwm_used = 0 -pwm_positive = port:PH6<2><0> - -[pwm1_para] -pwm_used = 0 -pwm_positive = port:PH8<3><0> - -;-------------------------------------------------------------------------------- -;vip (video input port) configuration -;vip_used: 0:disable 1:enable -;vip_mode: 0:sample one interface to one buffer 1:sample two interface to one buffer -;vip_dev_qty: The quantity of devices linked to capture bus -; -;vip_define_sensor_list: If you want use sensor detect function, please set vip_define_sensor_list = 1, and -; verify that file /system/etc/hawkview/sensor_list_cfg.ini is properly configured! -; -;vip_dev(x)_pos: sensor position, "rear" or "front", if vip_define_sensor_list = 1,vip_dev(x)_pos must be configured! -; -;vip_dev(x)_isp_used 0:not use isp 1:use isp -;vip_dev(x)_fmt: 0:yuv 1:bayer raw rgb -;vip_dev(x)_stby_mode: 0:not shut down power at standby 1:shut down power at standby -;vip_dev(x)_vflip: flip in vertical direction 0:disable 1:enable -;vip_dev(x)_hflip: flip in horizontal direction 0:disable 1:enable -;vip_dev(x)_iovdd: camera module io power handle string, pmu power supply -;vip_dev(x)_iovdd_vol: camera module io power voltage, pmu power supply -;vip_dev(x)_avdd: camera module analog power handle string, pmu power supply -;vip_dev(x)_avdd_vol: camera module analog power voltage, pmu power supply -;vip_dev(x)_dvdd: camera module core power handle string, pmu power supply -;vip_dev(x)_dvdd_vol: camera module core power voltage, pmu power supply -;vip_dev(x)_afvdd: camera module vcm power handle string, pmu power supply -;vip_dev(x)_afvdd_vol: camera module vcm power voltage, pmu power supply -;x indicates the index of the devices which are linked to the same capture bus -;fill voltage in uV, e.g. iovdd = 2.8V, vip_devx_iovdd_vol = 2800000 -;fill handle string as below: -;axp22_eldo3 -;axp22_dldo4 -;axp22_eldo2 -;fill handle string "" when not using any pmu power supply - -;-------------------------------------------------------------------------------- -[csi0] - -vip_used = 0 -vip_mode = 0 -vip_dev_qty = 1 -vip_define_sensor_list = 0 - -vip_csi_mck = port:PB14<3> -vip_csi_sck = port:PB15<3> -vip_csi_sda = port:PB16<3> - -vip_dev0_mname = "ov16825" -vip_dev0_pos = "rear" -vip_dev0_lane = 1 -vip_dev0_twi_id = 0 -vip_dev0_twi_addr = 0x6c -vip_dev0_isp_used = 1 -vip_dev0_fmt = 1 -vip_dev0_stby_mode = 0 -vip_dev0_vflip = 0 -vip_dev0_hflip = 0 -vip_dev0_iovdd = "axp22_aldo2" -vip_dev0_iovdd_vol = 2800000 -vip_dev0_avdd = "axp15_aldo2" -vip_dev0_avdd_vol = 2800000 -vip_dev0_dvdd = "axp22_eldo1" -vip_dev0_dvdd_vol = 1500000 -vip_dev0_afvdd = "axp15_cldo2" -vip_dev0_afvdd_vol = 2800000 -vip_dev0_power_en = -vip_dev0_reset = port:PB5<1> -vip_dev0_pwdn = port:PB6<1> -vip_dev0_flash_en = -vip_dev0_flash_mode = -vip_dev0_af_pwdn = - -vip_dev0_act_used = 1 -vip_dev0_act_name = "dw9714_act" -vip_dev0_act_slave = 0x18 - - -vip_dev1_mname = "" -vip_dev1_pos = "front" -vip_dev1_lane = 1 -vip_dev1_twi_id = 0 -vip_dev1_twi_addr = -vip_dev1_isp_used = 0 -vip_dev1_fmt = 1 -vip_dev1_stby_mode = 0 -vip_dev1_vflip = 0 -vip_dev1_hflip = 0 -vip_dev1_iovdd = "axp22_eldo3" -vip_dev1_iovdd_vol = 2800000 -vip_dev1_avdd = "axp22_dldo4" -vip_dev1_avdd_vol = 2800000 -vip_dev1_dvdd = "axp22_eldo2" -vip_dev1_dvdd_vol = 1500000 -vip_dev1_afvdd = "" -vip_dev1_afvdd_vol = 2800000 -vip_dev1_power_en = -vip_dev1_reset = -vip_dev1_pwdn = -vip_dev1_flash_en = -vip_dev1_flash_mode = -vip_dev1_af_pwdn = - -[csi1] - -vip_used = 0 -;-------------------------------------------------------------------------------- -;tv configuration -; -;-------------------------------------------------------------------------------- -[tvout_para] -tvout_used = -tvout_channel_num = -tv_en = - -[tvin_para] -tvin_used = -tvin_channel_num = - -;-------------------------------------------------------------------------------- -; SDMMC PINS MAPPING | -; ------------------------------------------------------------------------------| -; Config Guide | -; sdc_used: 1-enable card, 0-disable card | -; sdc_detmode: card detect mode | -; 1-detect card by gpio polling | -; 2-detect card by gpio irq(must use IO with irq function) | -; 3-no detect, always in for boot card | -; 4-manually insert and remove by /proc/driver/sunxi-mmc.x/insert| -; sdc_buswidth: card bus width, 1-1bit, 4-4bit, 8-8bit | -; sdc_use_wp: 1-with write protect IO, 0-no write protect IO | -; sdc_isio: for sdio card | -; sdc_regulator: power control.if card supports UHS-I/DDR and HS200 timing for| -; SD3.0 or eMMC4.5, regulator must be configured. the value is | -; the ldo name of AXP221, eg: sdc_regulator = "axp22_eldo2" | -; other: GPIO Mapping configuration | -; ------------------------------------------------------------------------------| -; Note: | -; 1 if detmode=2, sdc_det's config=6 | -; else if detmode=1, sdc_det's config=0 | -; else sdc_det IO is not necessary | -; 2 if the customer wants to support UHS-I and HS200 features, he must provide| -; an independent power supply for the card. This is only used in platforms | -; that supports SD3.0 cards and eMMC4.4+ flashes | -;-------------------------------------------------------------------------------- -[mmc0_para] -sdc_used = 1 -sdc_detmode = 2 -sdc_buswidth = 4 -sdc_clk = port:PF02<2><1><2> -sdc_cmd = port:PF03<2><1><2> -sdc_d0 = port:PF01<2><1><2> -sdc_d1 = port:PF00<2><1><2> -sdc_d2 = port:PF05<2><1><2> -sdc_d3 = port:PF04<2><1><2> -sdc_det = port:PH18<6><1><2> -sdc_use_wp = 0 -sdc_wp = -sdc_isio = 0 -sdc_regulator = "none" - -[mmc1_para] -sdc_used = 1 -sdc_detmode = 4 -sdc_buswidth = 4 -sdc_clk = port:PG00<2><1><2> -sdc_cmd = port:PG01<2><1><2> -sdc_d0 = port:PG02<2><1><2> -sdc_d1 = port:PG03<2><1><2> -sdc_d2 = port:PG04<2><1><2> -sdc_d3 = port:PG05<2><1><2> -sdc_det = -sdc_use_wp = 0 -sdc_wp = -sdc_isio = 1 -sdc_regulator = "none" - -[mmc2_para] -sdc_used = 1 -sdc_detmode = 3 -sdc_buswidth = 8 -sdc_clk = port:PC07<3><1><2> -sdc_cmd = port:PC06<3><1><2> -sdc_d0 = port:PC08<3><1><2> -sdc_d1 = port:PC09<3><1><2> -sdc_d2 = port:PC10<3><1><2> -sdc_d3 = port:PC11<3><1><2> -sdc_d4 = port:PC12<3><1><2> -sdc_d5 = port:PC13<3><1><2> -sdc_d6 = port:PC14<3><1><2> -sdc_d7 = port:PC15<3><1><2> -emmc_rst = port:PC16<3><1><2> -sdc_det = -sdc_use_wp = 0 -sdc_wp = -sdc_isio = 0 -sdc_regulator = "none" - -[mmc3_para] -sdc_used = 0 -sdc_detmode = 4 -sdc_buswidth = 8 -sdc_clk = port:PC07<3><1><2> -sdc_cmd = port:PC06<3><1><2> -sdc_d0 = port:PC08<3><1><2> -sdc_d1 = port:PC09<3><1><2> -sdc_d2 = port:PC10<3><1><2> -sdc_d3 = port:PC11<3><1><2> -sdc_d4 = port:PC12<3><1><2> -sdc_d5 = port:PC13<3><1><2> -sdc_d6 = port:PC14<3><1><2> -sdc_d7 = port:PC15<3><1><2> -emmc_rst = port:PC16<3><1><2> -sdc_det = -sdc_use_wp = 0 -sdc_wp = -sdc_isio = 0 -sdc_regulator = "none" - -; ------------------------------------------------------------------------------| -; sim card configuration -;-------------------------------------------------------------------------------- -[smc_para] -smc_used = -smc_rst = -smc_vppen = -smc_vppp = -smc_det = -smc_vccen = -smc_sck = -smc_sda = - - -;-------------------------------- -;[usbc0]:控制器0的配置。 -;usb_used:USB使能标志。置1,表示系统中USB模块可用,置0,则表示系统USB禁用。 -;usb_port_type:USB端口的使用情况。 0:device only;1:host only;2:OTG -;usb_detect_type:USB端口的检查方式。0:不做检测;1:vbus/id检查;2:id/dpdm检查 -;usb_id_gpio:USB ID pin脚配置。具体请参考gpio配置说明。 -;usb_det_vbus_gpio:USB DET_VBUS pin脚配置。具体请参考gpio配置说明。 -;usb_drv_vbus_gpio:USB DRY_VBUS pin脚配置。具体请参考gpio配置说明。 -;usb_det_vbus_gpio: "axp_ctrl",表示axp 提供 -;usb_restrict_gpio usb限流控制pin -;usb_restric_flag: usb限流标置 -;-------------------------------- -;-------------------------------- -;--- USB0控制标志 -;-------------------------------- -[usbc0] -usb_used = 1 -usb_port_type = 2 -usb_detect_type = 1 -usb_id_gpio = port:PH16<0><1> -usb_det_vbus_gpio = "axp_ctrl" -usb_drv_vbus_gpio = port:power4<1><0><1> -usb_restrict_gpio = -usb_host_init_state = 1 -usb_restric_flag = -usb_restric_voltage = 3550000 -usb_restric_capacity= 5 -;-------------------------------- -;--- USB1控制标志 -;-------------------------------- -[usbc1] -usb_used = 1 -usb_port_type = 1 -usb_detect_type = 0 -usb_drv_vbus_gpio = port:PH14<1><0><0> -usb_restrict_gpio = -usb_host_init_state = 1 -usb_restric_flag = 0 - -;-------------------------------- -;--- USB2控制标志 -;-------------------------------- -[usbc2] -usb_used = 1 -usb_port_type = 1 -usb_detect_type = 0 -usb_drv_vbus_gpio = port:PH15<1><0><0> -usb_restrict_gpio = -usb_host_init_state = 1 -usb_restric_flag = 0 - -;-------------------------------- -;--- USB3控制标志 -;-------------------------------- -[usbc3] -usb_used = 1 -usb_port_type = 1 -usb_detect_type = 0 -usb_drv_vbus_gpio = -usb_restrict_gpio = -usb_host_init_state = 1 -usb_restric_flag = 0 -;-------------------------------- -;--- USB Device -;-------------------------------- -[usb_feature] -vendor_id = 0x18D1 -mass_storage_id = 0x0001 -adb_id = 0x0002 - -manufacturer_name = "USB Developer" -product_name = "Android" -serial_number = "20080411" - -[msc_feature] -vendor_name = "USB 2.0" -product_name = "USB Flash Driver" -release = 100 -luns = 3 - -[serial_feature] -serial_unique = 0 - -;-------------------------------------------------------------------------------- -; G sensor configuration -; gs_twi_id --- TWI ID for controlling Gsensor (0: TWI0, 1: TWI1, 2: TWI2) -;-------------------------------------------------------------------------------- -[gsensor_para] -gsensor_used = 0 -gsensor_twi_id = 1 -gsensor_twi_addr = 0x18 -gsensor_int1 = port:PH17<6><1> -gsensor_int2 = - -;-------------------------------------------------------------------------------- -; G sensor automatic detection configuration -;gsensor_detect_used --- Whether startup automatic inspection function. 1:used,0:unused -;Module name postposition 1 said detection, 0 means no detection. -;-------------------------------------------------------------------------------- -[gsensor_list_para] -gsensor_det_used = 1 -bma250 = 1 -mma8452 = 1 -mma7660 = 1 -mma865x = 1 -afa750 = 1 -lis3de_acc = 1 -lis3dh_acc = 1 -kxtik = 1 -dmard10 = 0 -dmard06 = 1 -mxc622x = 1 -fxos8700 = 1 -lsm303d = 1 - -;-------------------------------------------------------------------------------- -; gps gpio configuration -; gps_spi_id --- the index of SPI controller. 0: SPI0, 1: SPI1, 2: SPI2, 15: no SPI used -; gps_spi_cs_num --- the chip select number of SPI controller. 0: SPI CS0, 1: SPI CS1 -; gps_lradc --- the lradc number for GPS used. 0 and 1 is valid, set 2 if not use lradc -;-------------------------------------------------------------------------------- -[gps_para] - -;-------------------------------------------------------------------------------- -;wifi configuration -;wifi_sdc_id --- 0- SDC0, 1- SDC1, 2- SDC2, 3- SDC3 -;wifi_usbc_id --- 0- USB0, 1- USB1, 2- USB2, 3- USB3 -;wifi_mod_sel --- 0- none, 1- rtl8188eu, 2- rtl8723bs(wifi+bt), -; 3 - ap6181, 4- ap6210(wifi+bt), 5 - ap6330(wifi+bt) -;-------------------------------------------------------------------------------- -[wifi_para] -wifi_used = 1 -wifi_sdc_id = 1 -wifi_usbc_id = 1 -wifi_usbc_type = 1 -wifi_mod_sel = 5 -wifi_power = "axp22_dldo1" -wifi_power_ext1 = "axp15_cldo3" -wifi_power_ext2 = "axp22_ldoio0" -sdio_power = "" - -; 1 - rtl8188eu usb wifi gpio conifg -;rtl8188eu_power = port:PH27<1><0><0> - -; 2 - rtl8723bs sdio wifi + bt gpio config -rtl8723bs_chip_en = port:PL09<1><0> -rtl8723bs_wl_regon = port:PL02<1><0> -rtl8723bs_wl_host_wake = port:PL03<4><0> -rtl8723bs_bt_regon = port:PL05<1><0> -rtl8723bs_bt_wake = port:PL08<1><0> -rtl8723bs_bt_host_wake = port:PL04<4><0> -rtl8723bs_lpo_use_apclk = 0 - -; 3 - ap6181 sdio wifi gpio config -; 4 - ap6210 sdio wifi + bt gpio config -; 5 - ap6330 sdio wifi + bt gpio config -ap6xxx_wl_regon = port:PL02<1><0> -ap6xxx_wl_host_wake = port:PL03<0><0> -ap6xxx_bt_regon = port:PL05<1><0> -ap6xxx_bt_wake = port:PL08<1><0> -ap6xxx_bt_host_wake = port:PL04<0><0> -ap6xxx_lpo_use_apclk = 2 - -;-------------------------------------------------------------------------------- -;3G configuration -;-------------------------------------------------------------------------------- -[3g_para] -3g_used = 0 -3g_usbc_num = 3 -3g_uart_num = 4 -bb_name = "mu509" -bb_vbat = -bb_on = port:PM02<1><0> -bb_pwr_on = port:PM03<1><0> -bb_wake = port:PM04<1><0> -bb_rf_dis = port:PM15<1><0> -bb_rst = port:PM00<1><0> -bb_dldo = "axp22_sw0" -bb_dldo_min_uV = 5000000 -bb_dldo_max_uV = 5000000 -;-------------------------------------------------------------------------------- -;gyroscope -;-------------------------------------------------------------------------------- -[gy_para] -gy_used = 1 -gy_twi_id = 1 -gy_twi_addr = 0x6a -gy_int1 = port:PH15<6><1> -gy_int2 = - -;-------------------------------------------------------------------------------- -; Gyro automatic detection configuration -;gy_detect_used --- Whether startup automatic inspection function. 1:used,0:unused -;Module name postposition 1 said detection, 0 means no detection. -;-------------------------------------------------------------------------------- -[gy_list_para] -gy_det_used = 0 -l3gd20_gyr = 1 - -;-------------------------------------------------------------------------------- -;light sensor -;-------------------------------------------------------------------------------- -[ls_para] -ls_used = 0 -ls_twi_id = 1 -ls_twi_addr = 0x23 -ls_int = port:PH17<6><1> - -;-------------------------------------------------------------------------------- -; lsensor automatic detection configuration -;ls_detect_used --- Whether startup automatic inspection function. 1:used,0:unused -;Module name postposition 1 said detection, 0 means no detection. -;-------------------------------------------------------------------------------- -[ls_list_para] -ls_det_used = 0 -ltr_501als = 1 - -;-------------------------------------------------------------------------------- -;compass -;-------------------------------------------------------------------------------- -[compass_para] -compass_used = 0 -compass_twi_id = 1 -compass_twi_addr = 0x0d -compass_int = - -;-------------------------------------------------------------------------------- -;led -;-------------------------------------------------------------------------------- -[leds_para] -leds_used = 1 -leds_num = 2 -leds_pin_1 = port:PH06<1><0> -leds_name_1 = "red:ph06:led1" -leds_default_1 = 0 -leds_trigger_1 = "heartbeat" -leds_pin_2 = port:PH17<1><0> -leds_name_2 = "green:ph17:led2" -leds_default_2 = 0 -leds_trigger_2 = "cpu0" - -;-------------------------------------------------------------------------------- -;blue tooth -;bt_used ---- blue tooth used (0- no used, 1- used) -;bt_uard_id ---- uart index -;-------------------------------------------------------------------------------- -[bt_para] -bt_used = 1 -bt_uart_id = 2 -bt_wakeup = -bt_gpio = -bt_rst = - -;-------------------------------------------------------------------------------- -;daudio_master:1: SND_SOC_DAIFMT_CBM_CFM(codec clk & FRM master) use -; 2: SND_SOC_DAIFMT_CBS_CFM(codec clk slave & FRM master) not use -; 3: SND_SOC_DAIFMT_CBM_CFS(codec clk master & frame slave) not use -; 4: SND_SOC_DAIFMT_CBS_CFS(codec clk & FRM slave) use -;daudio_select:0 is pcm.1 is i2s -;audio_format: 1:SND_SOC_DAIFMT_I2S(standard i2s format). use -; 2:SND_SOC_DAIFMT_RIGHT_J(right justfied format). -; 3:SND_SOC_DAIFMT_LEFT_J(left justfied format) -; 4:SND_SOC_DAIFMT_DSP_A(pcm. MSB is available on 2nd BCLK rising edge after LRC rising edge). use -; 5:SND_SOC_DAIFMT_DSP_B(pcm. MSB is available on 1nd BCLK rising edge after LRC rising edge) -;signal_inversion:1:SND_SOC_DAIFMT_NB_NF(normal bit clock + frame) use -; 2:SND_SOC_DAIFMT_NB_IF(normal BCLK + inv FRM) -; 3:SND_SOC_DAIFMT_IB_NF(invert BCLK + nor FRM) use -; 4:SND_SOC_DAIFMT_IB_IF(invert BCLK + FRM) -;over_sample_rate: support 128fs/192fs/256fs/384fs/512fs/768fs -;sample_resolution :16bits/20bits/24bits -;word_select_size :16bits/20bits/24bits/32bits -;pcm_sync_period :16/32/64/128/256 -;msb_lsb_first :0: msb first; 1: lsb first -;sign_extend :0: zero pending; 1: sign extend -;slot_index :slot index: 0: the 1st slot - 3: the 4th slot -;slot_width :8 bit width / 16 bit width -;frame_width :0: long frame = 2 clock width; 1: short frame -;tx_data_mode :0: 16bit linear PCM; 1: 8bit linear PCM; 2: 8bit u-law; 3: 8bit a-law -;rx_data_mode :0: 16bit linear PCM; 1: 8bit linear PCM; 2: 8bit u-law; 3: 8bit a-law -;-------------------------------------------------------------------------------- -[s_i2s1] -daudio_used = 1 -daudio_master = 4 -daudio_select = 1 -audio_format = 1 -signal_inversion = 1 -mclk_fs = 512 -sample_resolution = 16 -slot_width_select = 16 -;pcm_sync_period = 256 -pcm_lrck_period = 32 -pcm_lrckr_period = 1 -msb_lsb_first = 0 -sign_extend = 0 -slot_index = 0 -frame_width = 0 -tx_data_mode = 0 -rx_data_mode = 0 -s_i2s1_lrckr = port:PM04<3><1> -s_i2s1_dout1 = port:PM05<3><1> -s_i2s1_dout2 = port:PM06<3><1> -s_i2s1_dout3 = port:PM07<3><1> -s_i2s1_mclk = port:PM10<3><1> -s_i2s1_bclk = port:PM11<3><1> -s_i2s1_lrclk = port:PM12<3><1> -s_i2s1_din = port:PM13<3><1> -s_i2s1_dout0 = port:PM14<3><1> - -[audio0] -audio_int_ctrl = port:PL9<6><0> -audio_pa_ctrl = port:PA16<1><0> -audio_hp_det = port:PM00<0><0> -aif3_voltage = "axp15_cldo3" -Digital_bb_cap_keytone_used = 0 -;speaker_val = 0x1b -headset_val = 0x3b -single_speaker_val = 0x19 -double_speaker_val = 0x1b -speaker_double_used = 1 - -[spdif0] -spdif_used = 0 -spdif_dout = port:PH18<3><1> -spdif_din = port:PH17<3><1> -spdif_voltage = "axp22_dcdc1" - - -;---------------------------------------------------------------------------------- -;ir rx --- infra remote configuration -;---------------------------------------------------------------------------------- -[s_cir0] -ir_used = 1 -ir_rx = port:PL06<3><1> -ir_power_key_code = 0x0 -ir_addr_code = 0x0 - -;---------------------------------------------------------------------------------- -;ir tx--- infra remote configuration -;---------------------------------------------------------------------------------- -[cir] -ir_used = 1 -ir_tx = port:PH07<2> - -;------------------------------------------------------------------------------------- -;pmu_used ---0:not used,1:used -;pmu_twi_addr ---slave address -;pmu_twi_id ---i2c bus number (0 TWI0, 1 TWI2, 2 TWI3) -;pmu_irq_id ---irq number (0 irq0,1 irq1,……) -;pmu_battery_rdc ---battery initial resistance -;pmu_battery_cap ---battery capability,mAh -;pmu_batdeten ---battery detect en;0:disable 1:enable -;pmu_runtime_chgcur ---set initial charging current limite,mA,300/450/600/750/900/1050/1200/1350/1500/1650/1800/1950/ -;pmu_earlysuspend_chgcur ---set earlysuspend charging current limite,mA,300/450/600/750/900/1050/1200/1350/1500/1650/1800/1950/ -;pmu_suspend_chgcur ---set suspend charging current limite,mA,300/450/600/750/900/1050/1200/1350/1500/1650/1800/1950/ -;pmu_shutdown_chgcur ---set shutdown charging current limite,mA,300/450/600/750/900/1050/1200/1350/1500/1650/1800/1950/ -;pmu_init_chgvol ---set initial charing target voltage,mV,4100/4220/4200/4240 -;pmu_init_chgend_rate ---set initial charing end current rate,10/15 -;pmu_init_chg_enabled ---set initial charing enabled,0:disable,1:enable -;pmu_init_adc_freq ---set initial adc frequency,Hz,100/200/400/800 -;pmu_init_adcts_freq ---set initial adc TS,Hz,100/200/400/800 -;pmu_init_chg_pretime ---set initial pre-charging time,min,40/50/60/70 -;pmu_init_chg_csttime ---set initial constance-charging time,min,360/480/600/720 -;pmu_batt_cap_correct ---correct the battery capacity or not when one charge cycle 0:not correct 1:correct -;pmu_bat_regu_en ---bat regulator is enable or not when charge done 0:disable 1:enable -;pmu_bat_para1 ---battery indication at 3.13V -;pmu_bat_para2 ---battery indication at 3.27V -;pmu_bat_para3 ---battery indication at 3.34V -;pmu_bat_para4 ---battery indication at 3.41V -;pmu_bat_para5 ---battery indication at 3.48V -;pmu_bat_para6 ---battery indication at 3.52V -;pmu_bat_para7 ---battery indication at 3.55V -;pmu_bat_para8 ---battery indication at 3.57V -;pmu_bat_para9 ---battery indication at 3.59V -;pmu_bat_para10 ---battery indication at 3.61V -;pmu_bat_para11 ---battery indication at 3.63V -;pmu_bat_para12 ---battery indication at 3.64V -;pmu_bat_para13 ---battery indication at 3.66V -;pmu_bat_para14 ---battery indication at 3.7V -;pmu_bat_para15 ---battery indication at 3.73V -;pmu_bat_para16 ---battery indication at 3.77V -;pmu_bat_para17 ---battery indication at 3.78V -;pmu_bat_para18 ---battery indication at 3.8V -;pmu_bat_para19 ---battery indication at 3.82V -;pmu_bat_para20 ---battery indication at 3.84V -;pmu_bat_para21 ---battery indication at 3.85V -;pmu_bat_para22 ---battery indication at 3.87V -;pmu_bat_para23 ---battery indication at 3.91V -;pmu_bat_para24 ---battery indication at 3.94V -;pmu_bat_para25 ---battery indication at 3.98V -;pmu_bat_para26 ---battery indication at 4.01V -;pmu_bat_para27 ---battery indication at 4.05V -;pmu_bat_para28 ---battery indication at 4.08V -;pmu_bat_para29 ---battery indication at 4.1V -;pmu_bat_para30 ---battery indication at 4.12V -;pmu_bat_para31 ---battery indication at 4.14V -;pmu_bat_para32 ---battery indication at 4.15V -;pmu_usbvol_limit ---set usb-ac limited voltage enable,1:enable,0:disable -;pmu_usbcur_limit ---set usb-ac limited current enable,1:enable,0:disable -;pmu_usbvol ---set usb-ac limited voltage level,mV,4000/4100/4200/4300/4400/4500/4600/4700,0 - not limite -;pmu_usbcur ---set usb-ac limited current level,mA,500/900, 0 - not limite -;pmu_usbvol_pc ---set usb-pc limited voltage level,mV,4000/4100/4200/4300/4400/4500/4600/4700,0 - not limite -;pmu_usbcur_pc ---set usb-pc limited current level,mA,500/900, 0 - not limite -;pmu_pwroff_vol ---set protect voltage when system start up,mV,2600/2700/2800/2900/3000/3100/3200/3300 -;pmu_pwron_vol ---set protect voltage after system start up,mV,2600/2700/2800/2900/3000/3100/3200/3300 -;pmu_pekoff_time ---set pek off time,ms, 4000/6000/8000/10000 -;pmu_pekoff_func ---set pek off func, 0:shutdown,1:restart -;pmu_pekoff_en ---set pek offlevel powerdown or not, 0:not powerdown,1:powerdown -;pmu_pekoff_delay_time ---set pek off delay time s, 0/10/20/30/40/50/60/70 -;pmu_peklong_time ---set pek pek long irq time,ms,1000/1500/2000/2500 -;pmu_pekon_time ---set pek on time,ms,128/1000/2000/3000 -;pmu_pwrok_time ---set pmu pwrok delay time,ms,8/16/32/64 -;pmu_pwrok_shutdown_en ---set pwrok 6s shutdown enable -;pmu_battery_warning_level1 ---low power warning high level,5%-20%,1%/step -;pmu_battery_warning_level2 ---low power warning low level,0%-15%,1%/step -;pmu_restvol_time ---battery indicaton reflash time,30/60/120/ -;pmu_ocv_cou_adjust_time ---ocv battery indication reflash time,60/120/30 -;pmu_chgled_func ---CHGKED pin control,0:controlled by pmu,1:controlled by Charger -;pmu_chgled_type ---CHGLED Type select when pmu_chgled_func=0,0:Type A,1:Type B -;pmu_vbusen_func ---N_VBUSEN function select,0:as an output,1:as an input -;pmu_reset ---when power key press longer than 16's,PMU reset or not.0:not reset 1:reset -;pmu_IRQ_wakeup ---press IRQ wakeup or not when sleep or power down.0:not wakeup 1:wakeup -;pmu_hot_shutdowm ---when PMU over temperature protect or not;0:disable 1:enable -;pmu_inshort ---ACIN and VBUS inshort or not by software;0:auto detect 1:inshort -;pmu_charge_ltf --- -;pmu_charge_htf --- -;pmu_discharge_ltf --- -;pmu_discharge_htf --- -;pmu_temp_para1 --- temp -25 voltage -;pmu_temp_para2 --- temp -15 voltage -;pmu_temp_para3 --- temp -10 voltage -;pmu_temp_para4 --- temp -5 voltage -;pmu_temp_para5 --- temp 0 voltage -;pmu_temp_para6 --- temp 5 voltage -;pmu_temp_para7 --- temp 10 voltage -;pmu_temp_para8 --- temp 20 voltage -;pmu_temp_para9 --- temp 30 voltage -;pmu_temp_para10 --- temp 40 voltage -;pmu_temp_para11 --- temp 45 voltage -;pmu_temp_para12 --- temp 50 voltage -;pmu_temp_para13 --- temp 55 voltage -;pmu_temp_para14 --- temp 60 voltage -;pmu_temp_para15 --- temp 70 voltage -;pmu_temp_para16 --- temp 80 voltage -;-------------------------------------------------------------------------------------------------------- -;-------------------------------------------------------------------------------------------------------- -;pmu1 is axp22 -;-------------------------------------------------------------------------------------------------------- -[pmu1_para] -pmu_used = 1 -pmu_twi_addr = 0x34 -pmu_twi_id = 0 -pmu_irq_id = 0 -pmu_battery_rdc = 100 -pmu_battery_cap = 0 -pmu_batdeten = 1 -pmu_runtime_chgcur = 900 -pmu_earlysuspend_chgcur = 900 -pmu_suspend_chgcur = 1500 -pmu_shutdown_chgcur = 1500 -pmu_init_chgvol = 4200 -pmu_init_chgend_rate = 15 -pmu_init_chg_enabled = 1 -pmu_init_adc_freq = 800 -pmu_init_adcts_freq = 800 -pmu_init_chg_pretime = 70 -pmu_init_chg_csttime = 720 -pmu_batt_cap_correct = 1 -pmu_bat_regu_en = 0 - -pmu_bat_para1 = 0 -pmu_bat_para2 = 0 -pmu_bat_para3 = 0 -pmu_bat_para4 = 0 -pmu_bat_para5 = 0 -pmu_bat_para6 = 0 -pmu_bat_para7 = 0 -pmu_bat_para8 = 0 -pmu_bat_para9 = 5 -pmu_bat_para10 = 8 -pmu_bat_para11 = 9 -pmu_bat_para12 = 10 -pmu_bat_para13 = 13 -pmu_bat_para14 = 16 -pmu_bat_para15 = 20 -pmu_bat_para16 = 33 -pmu_bat_para17 = 41 -pmu_bat_para18 = 46 -pmu_bat_para19 = 50 -pmu_bat_para20 = 53 -pmu_bat_para21 = 57 -pmu_bat_para22 = 61 -pmu_bat_para23 = 67 -pmu_bat_para24 = 73 -pmu_bat_para25 = 78 -pmu_bat_para26 = 84 -pmu_bat_para27 = 88 -pmu_bat_para28 = 92 -pmu_bat_para29 = 93 -pmu_bat_para30 = 94 -pmu_bat_para31 = 95 -pmu_bat_para32 = 100 - -pmu_usbvol_limit = 0 -pmu_usbcur_limit = 0 -pmu_usbvol = 4000 -pmu_usbcur = 0 -pmu_usbvol_pc = 4400 -pmu_usbcur_pc = 500 -pmu_pwroff_vol = 3300 -pmu_pwron_vol = 2600 -pmu_pekoff_time = 6000 -pmu_pekoff_func = 0 -pmu_pekoff_en = 1 -pmu_pekoff_delay_time = 0 -pmu_peklong_time = 1500 -pmu_pekon_time = 1000 -pmu_pwrok_time = 64 -pmu_pwrok_shutdown_en = 0 -pmu_battery_warning_level1 = 15 -pmu_battery_warning_level2 = 0 -pmu_restvol_adjust_time = 60 -pmu_ocv_cou_adjust_time = 60 -pmu_chgled_func = 0 -pmu_chgled_type = 0 -pmu_vbusen_func = 1 -pmu_reset = 0 -pmu_IRQ_wakeup = 0 -pmu_hot_shutdowm = 1 -pmu_inshort = 0 -power_start = 1 - -pmu_temp_enable = 0 -pmu_charge_ltf = 2261 -pmu_charge_htf = 388 -pmu_discharge_ltf = 3200 -pmu_discharge_htf = 237 -pmu_temp_para1 = 7466 -pmu_temp_para2 = 4480 -pmu_temp_para3 = 3518 -pmu_temp_para4 = 2786 -pmu_temp_para5 = 2223 -pmu_temp_para6 = 1788 -pmu_temp_para7 = 1448 -pmu_temp_para8 = 969 -pmu_temp_para9 = 664 -pmu_temp_para10 = 466 -pmu_temp_para11 = 393 -pmu_temp_para12 = 333 -pmu_temp_para13 = 283 -pmu_temp_para14 = 242 -pmu_temp_para15 = 179 -pmu_temp_para16 = 134 - -;-------------------------------------------------------------------------------------------------------- -;pmu2 is axp15 -;pmu_used ---0:not used,1:used -;pmu_twi_addr ---slave address -;pmu_twi_id ---i2c bus number (0 TWI0, 1 TWI2, 2 TWI3) -;pmu_irq_id ---irq number (0 irq0,1 irq1) -;pmu_hot_shutdowm ---when PMU over temperature protect or not;0:disable 1:enable -;-------------------------------------------------------------------------------------------------------- -[pmu2_para] -pmu_used = 1 -pmu_twi_addr = 0x34 -pmu_twi_id = 1 -pmu_irq_id = 0 -pmu_hot_shutdowm = 1 -;---------------------------------------------------------------------------------- -; dvfs voltage-frequency table configuration -; -; there are two clusters, cluster0 and cluster1, they have diffrent configuration -; on frequency and voltage. -; -; max_freq: cpu maximum frequency, based on Hz -; min_freq: cpu minimum frequency, based on Hz -; -; LV_count: count of LV_freq/LV_volt, must be < 16 -; -; L_LV1: core vdd is 1.02v if cpu frequency is (1128Mhz, 1200Mhz] -; L_LV2: core vdd is 0.96v if cpu frequency is (1008Mhz, 1128Mhz] -; L_LV3: core vdd is 0.90v if cpu frequency is ( 864Mhz, 1008Mhz] -; L_LV4: core vdd is 0.84v if cpu frequency is ( 0Mhz, 864Mhz] -; L_LV5: core vdd is 0.84v if cpu frequency is ( 0Mhz, 864Mhz] -; L_LV6: core vdd is 0.84v if cpu frequency is ( 0Mhz, 864Mhz] -; L_LV7: core vdd is 0.84v if cpu frequency is ( 0Mhz, 864Mhz] -; L_LV8: core vdd is 0.84v if cpu frequency is ( 0Mhz, 864Mhz] -; -; B_LV1: core vdd is 1.08v if cpu frequency is (1608Mhz, 1800Mhz] -; B_LV2: core vdd is 1.00v if cpu frequency is (1536Mhz, 1608Mhz] -; B_LV3: core vdd is 0.96v if cpu frequency is (1440Mhz, 1536Mhz] -; B_LV4: core vdd is 0.90v if cpu frequency is (1296Mhz, 1440Mhz] -; B_LV5: core vdd is 0.84v if cpu frequency is ( 0Mhz, 1296Mhz] -; B_LV6: core vdd is 0.84v if cpu frequency is ( 0Mhz, 1296Mhz] -; B_LV7: core vdd is 0.84v if cpu frequency is ( 0Mhz, 1296Mhz] -; B_LV8: core vdd is 0.84v if cpu frequency is ( 0Mhz, 1296Mhz] -; -;---------------------------------------------------------------------------------- -[dvfs_table] -vf_table_count = 3 - -[vf_table0] -;little -L_max_freq = 1200000000 -L_min_freq = 480000000 - -L_LV_count = 8 - -L_LV1_freq = 1200000000 -L_LV1_volt = 1020 - -L_LV2_freq = 1104000000 -L_LV2_volt = 960 - -L_LV3_freq = 1008000000 -L_LV3_volt = 900 - -L_LV4_freq = 816000000 -L_LV4_volt = 840 - -L_LV5_freq = 0 -L_LV5_volt = 840 - -L_LV6_freq = 0 -L_LV6_volt = 840 - -L_LV7_freq = 0 -L_LV7_volt = 840 - -L_LV8_freq = 0 -L_LV8_volt = 840 - -;big -B_max_freq = 1800000000 -B_min_freq = 600000000 - -B_LV_count = 8 - -B_LV1_freq = 1800000000 -B_LV1_volt = 1100 - -B_LV2_freq = 1608000000 -B_LV2_volt = 1020 - -B_LV3_freq = 1416000000 -B_LV3_volt = 960 - -B_LV4_freq = 1200000000 -B_LV4_volt = 900 - -B_LV5_freq = 1008000000 -B_LV5_volt = 840 - -B_LV6_freq = 0 -B_LV6_volt = 840 - -B_LV7_freq = 0 -B_LV7_volt = 840 - -B_LV8_freq = 0 -B_LV8_volt = 840 - -[vf_table1] -;little -L_max_freq = 1200000000 -L_min_freq = 480000000 - -L_LV_count = 8 - -L_LV1_freq = 1200000000 -L_LV1_volt = 1060 - -L_LV2_freq = 1008000000 -L_LV2_volt = 960 - -L_LV3_freq = 912000000 -L_LV3_volt = 900 - -L_LV4_freq = 720000000 -L_LV4_volt = 840 - -L_LV5_freq = 0 -L_LV5_volt = 840 - -L_LV6_freq = 0 -L_LV6_volt = 840 - -L_LV7_freq = 0 -L_LV7_volt = 840 - -L_LV8_freq = 0 -L_LV8_volt = 840 - -;big -B_max_freq = 1608000000 -B_min_freq = 600000000 - -B_LV_count = 8 - -B_LV1_freq = 1800000000 -B_LV1_volt = 1160 - -B_LV2_freq = 1608000000 -B_LV2_volt = 1100 - -B_LV3_freq = 1416000000 -B_LV3_volt = 1020 - -B_LV4_freq = 1320000000 -B_LV4_volt = 960 - -B_LV5_freq = 1200000000 -B_LV5_volt = 900 - -B_LV6_freq = 1008000000 -B_LV6_volt = 840 - -B_LV7_freq = 0 -B_LV7_volt = 840 - -B_LV8_freq = 0 -B_LV8_volt = 840 - -[vf_table2] -;little -L_max_freq = 1200000000 -L_min_freq = 480000000 - -L_LV_count = 8 - -L_LV1_freq = 1200000000 -L_LV1_volt = 1020 - -L_LV2_freq = 1104000000 -L_LV2_volt = 960 - -L_LV3_freq = 1008000000 -L_LV3_volt = 900 - -L_LV4_freq = 816000000 -L_LV4_volt = 840 - -L_LV5_freq = 0 -L_LV5_volt = 840 - -L_LV6_freq = 0 -L_LV6_volt = 840 - -L_LV7_freq = 0 -L_LV7_volt = 840 - -L_LV8_freq = 0 -L_LV8_volt = 840 - -;big -B_max_freq = 1800000000 -B_min_freq = 600000000 - -B_LV_count = 8 - -B_LV1_freq = 1800000000 -B_LV1_volt = 1100 - -B_LV2_freq = 1608000000 -B_LV2_volt = 1020 - -B_LV3_freq = 1416000000 -B_LV3_volt = 960 - -B_LV4_freq = 1200000000 -B_LV4_volt = 900 - -B_LV5_freq = 1008000000 -B_LV5_volt = 840 - -B_LV6_freq = 0 -B_LV6_volt = 840 - -B_LV7_freq = 0 -B_LV7_volt = 840 - -B_LV8_freq = 0 -B_LV8_volt = 840 - -;---------------------------------------------------------------------------------- -;virtual device -;virtual device for pinctrl testing -;device have pin PA1 PA2 -;---------------------------------------------------------------------------------- -[Vdevice] -Vdevice_used = 1 -Vdevice_0 = -Vdevice_1 = - -;---------------------------------------------------------------------------------- -;s_uart0 config parameters -;s_uart_used --s_uart0 whether used for arisc debugging -; -;---------------------------------------------------------------------------------- -[s_uart0] -s_uart_used = 1 -s_uart_tx = port:PL00<3> -s_uart_rx = port:PL01<3> - -;---------------------------------------------------------------------------------- -;s_rsb0 config parameters -;s_rsb_used --s_rsb0 whether used for arisc -; -;---------------------------------------------------------------------------------- -[s_rsb0] -s_rsb_used = 1 -s_rsb_sck = port:PN00<3><1><2> -s_rsb_sda = port:PN01<3><1><2> - -;---------------------------------------------------------------------------------- -;s_jtag0 config parameters -;s_jtag0_used --s_jtag0 whether used for arisc -; -;---------------------------------------------------------------------------------- -[s_jtag0] -s_jtag_used = 1 -s_jtag_tms = port:PL02<3><1><2> -s_jtag_tck = port:PL03<3><1><2> -s_jtag_tdo = port:PL04<3><1><2> -s_jtag_tdi = port:PL05<3><1><2> - -;---------------------------------------------------------------------------------- -;s_powchk cpus power check -;s_powchk_used --power check whether used for arisc in super standby -; bit31:enable power updat, bit1:wakeup when power state exception -; bit0:wakeup when power consumption exception -;s_power_reg the expected regs stand for power on/off state -;s_system_power the limit maxmum power consumption when super standby (unit: mw) -; -;---------------------------------------------------------------------------------- -[s_powchk] -s_powchk_used = 0x80000000 -s_power_reg = 0x02309621 -s_system_power = 50 - -;---------------------------------------------------------------------------------- -; dram dvfs voltage-frequency table configuration -; -; LV_count: count of LV_freq/LV_volt -; -; LV1: core vdd is 0.90v if dram frequency is (360Mhz, 672Mhz] -; LV2: core vdd is 0.84v if dram frequency is ( 0Mhz, 168Mhz] -; LV3: core vdd is 0.84v if dram frequency is ( 0Mhz, 168Mhz] -; -;---------------------------------------------------------------------------------- -[dram_dvfs_table] -LV_count = 3 - -LV1_freq = 672000000 -LV1_volt = 900 - -LV2_freq = 168000000 -LV2_volt = 840 - -LV3_freq = 0 -LV3_volt = 840 - -;---------------------------------------------------------------------------------- -; dram scene frequency table configuration -; -; LV_count: count of LV_scene/LV_freq -; -; LV0: dram frequency default is 672MHz in normal -; LV1: dram frequency default is 480MHz in home, supported for 480MHz/672MHz -; LV2: dram frequency default is 240MHz in video play, supported for 240MHz/336MHz/480MHz/672MHz -; LV3: dram frequency default is 168MHz in bgmusic play -; LV4: dram frequency default is 480MHz in 4K video play, supported for 480MHz/672MHz -; -;---------------------------------------------------------------------------------- -[dram_scene_table] -LV_count = 5 - -LV0_scene = 0 -LV0_freq = 672000000 - -LV1_scene = 1 -LV1_freq = 480000000 - -LV2_scene = 2 -LV2_freq = 240000000 - -LV3_scene = 3 -LV3_freq = 168000000 - -LV4_scene = 4 -LV4_freq = 480000000 diff --git a/config/cubietruck.fex b/config/cubietruck.fex index a82336ace..954283c1e 100644 --- a/config/cubietruck.fex +++ b/config/cubietruck.fex @@ -322,10 +322,11 @@ motor_shake = port:PB03<1><1> [gpio_para] gpio_used = 1 -gpio_num = 2 +gpio_num = 4 gpio_pin_1 = port:PH20<1><1> gpio_pin_2 = port:PH10<0><0> - +gpio_pin_68 = port:PH18<0><0> +gpio_pin_69 = port:PH24<0><0> [leds_para] leds_used = 1 @@ -333,15 +334,15 @@ leds_num = 4 leds_pin_1 = port:PH21<1><0> leds_name_1 = "blue:ph21:led1" leds_default_1 = 0 -leds_trigger_1 = "heartbeat" +leds_trigger_1 = "none" leds_pin_2 = port:PH20<1><0> leds_name_2 = "orange:ph20:led2" leds_default_2 = 0 -leds_trigger_2 = "cpu0" +leds_trigger_2 = "none" leds_pin_3 = port:PH11<1><0> leds_name_3 = "white:ph11:led3" leds_default_3 = 0 -leds_trigger_3 = "cpu1" +leds_trigger_3 = "none" leds_pin_4 = port:PH07<1><0> leds_name_4 = "green:ph07:led4" leds_default_4 = 1 @@ -397,7 +398,7 @@ good_block_ratio = 0 disp_init_enable = 1 disp_mode = 0 -screen0_output_type = 4 +screen0_output_type = 3 screen0_output_mode = 4 screen1_output_type = 0 diff --git a/config/hostapd.conf b/config/hostapd.conf index 8805561ab..8187d7a03 100644 --- a/config/hostapd.conf +++ b/config/hostapd.conf @@ -1,12 +1,13 @@ -ssid=BOARD +ssid=SSID interface=wlan0 hw_mode=g -channel=1 +channel=5 driver=nl80211 bridge=br0 logger_syslog=0 logger_syslog_level=0 wmm_enabled=1 +ieee80211n=1 wpa=2 preamble=1 wpa_psk=66eb31d2b48d19ba216f2e50c6831ee11be98e2fa3a8075e30b866f4a5ccda27 @@ -16,7 +17,7 @@ wpa_pairwise=TKIP rsn_pairwise=CCMP auth_algs=1 macaddr_acl=0 -#noscan=1 -#ht_capab=[HT40-][SHORT-GI-40][SHORT-GI-40][DSSS_CCK-40][TX-STBC][RX-STBC1] +noscan=1 +#ht_capab=[HT40-][SHORT-GI-40][SHORT-GI-40][DSSS_CCK-40] #country_code=SI #ieee80211d=1 \ No newline at end of file diff --git a/config/hostapd.realtek.conf b/config/hostapd.realtek.conf new file mode 100644 index 000000000..7fb3ccea9 --- /dev/null +++ b/config/hostapd.realtek.conf @@ -0,0 +1,19 @@ +ssid=SSID +interface=wlan0 +ctrl_interface=/var/run/hostapd +channel=5 +noscan=1 +wpa=2 +wpa_passphrase=12345678 +bridge=br0 +wmm_enabled=0 +driver=rtl871xdrv +beacon_int=100 +hw_mode=g +ieee80211n=1 +wme_enabled=1 +ht_capab=[SHORT-GI-40][HT40+][HT40-][DSSS_CCK-40] +wpa_key_mgmt=WPA-PSK +wpa_pairwise=CCMP +max_num_sta=8 +wpa_group_rekey=86400 diff --git a/config/interfaces.default b/config/interfaces.default index 90f970e00..5d0b4530c 100644 --- a/config/interfaces.default +++ b/config/interfaces.default @@ -12,7 +12,6 @@ auto eth0 # # Wireless adapter #1 #auto wlan0 -# allow-hotplug wlan0 # iface wlan0 inet dhcp # wpa-ssid SSID # wpa-psk xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx diff --git a/config/interfaces.hostapd b/config/interfaces.hostapd index 7ffaae48e..6e357430b 100644 --- a/config/interfaces.hostapd +++ b/config/interfaces.hostapd @@ -1,10 +1,10 @@ auto lo br0 iface lo inet loopback -allow-hotplug eth0 +auto eth0 iface eth0 inet manual -allow-hotplug wlan0 +auto wlan0 iface wlan0 inet manual iface br0 inet dhcp diff --git a/config/interfaces.r1 b/config/interfaces.r1 new file mode 100644 index 000000000..06530a44a --- /dev/null +++ b/config/interfaces.r1 @@ -0,0 +1,21 @@ +auto lo +iface lo inet loopback + +auto eth0.101 +iface eth0.101 inet manual + pre-up swconfig dev eth0 set reset 1 + pre-up swconfig dev eth0 set enable_vlan 1 + pre-up swconfig dev eth0 vlan 101 set ports '3 8t' + pre-up swconfig dev eth0 set apply 1 + +auto eth0.102 +iface eth0.102 inet manual + pre-up swconfig dev eth0 vlan 102 set ports '0 1 2 4 8t' + pre-up swconfig dev eth0 set apply 1 + +auto wlan0 +iface wlan0 inet manual + +auto br0 +iface br0 inet dhcp +bridge_ports eth0.101 wlan0 diff --git a/config/interfaces.r1router b/config/interfaces.r1router new file mode 100644 index 000000000..a16dece2d --- /dev/null +++ b/config/interfaces.r1router @@ -0,0 +1,28 @@ +auto lo +iface lo inet loopback + +auto eth0.101 +iface eth0.101 inet manual + pre-up swconfig dev eth0 set reset 1 + pre-up swconfig dev eth0 set enable_vlan 1 + pre-up swconfig dev eth0 vlan 101 set ports '3 8t' + pre-up swconfig dev eth0 set apply 1 + +auto eth0.102 +iface eth0.102 inet manual + pre-up swconfig dev eth0 vlan 102 set ports '0 1 2 4 8t' + pre-up swconfig dev eth0 set apply 1 + +allow-hotplug wlan0 +iface wlan0 inet manual + +# WAN +auto eth0.101 +iface eth0.101 inet dhcp + +# LAN +auto br0 +iface br0 inet static +bridge_ports eth0.102 wlan0 + address 192.168.2.254 + netmask 255.255.255.0 diff --git a/config/interfaces.r1switch b/config/interfaces.r1switch new file mode 100644 index 000000000..fd5be5c28 --- /dev/null +++ b/config/interfaces.r1switch @@ -0,0 +1,16 @@ +auto lo +iface lo inet loopback + +auto eth0.101 +iface eth0.101 inet manual + pre-up swconfig dev eth0 set reset 1 + pre-up swconfig dev eth0 set enable_vlan 1 + pre-up swconfig dev eth0 vlan 101 set ports '0 1 2 3 4 8t' + pre-up swconfig dev eth0 set apply 1 + +auto wlan0 +iface wlan0 inet manual + +auto br0 +iface br0 inet dhcp +bridge_ports eth0.101 wlan0 diff --git a/config/lamobo-r1.fex b/config/lamobo-r1.fex new file mode 100644 index 000000000..1a8238085 --- /dev/null +++ b/config/lamobo-r1.fex @@ -0,0 +1,1074 @@ +[product] +version = "100" +machine = "bananapi" + +[platform] +eraseflag = 0 + +[target] +boot_clock = 912 +dcdc2_vol = 1450 +dcdc3_vol = 1300 +ldo2_vol = 3000 +ldo3_vol = 2800 +ldo4_vol = 2800 +storage_type = 0 + +[clock] +pll3 = 297 +pll4 = 300 +pll6 = 600 +pll7 = 297 +pll8 = 336 + +[card_boot] +logical_start = 40960 +sprite_gpio0 = + +[card0_boot_para] +card_ctrl = 0 +card_high_speed = 1 +card_line = 4 +sdc_d1 = port:PF00<2><1> +sdc_d0 = port:PF01<2><1> +sdc_clk = port:PF02<2><1> +sdc_cmd = port:PF03<2><1> +sdc_d3 = port:PF04<2><1> +sdc_d2 = port:PF05<2><1> + +[card2_boot_para] +card_ctrl = 2 +card_high_speed = 1 +card_line = 4 +sdc_cmd = port:PC06<3><1> +sdc_clk = port:PC07<3><1> +sdc_d0 = port:PC08<3><1> +sdc_d1 = port:PC09<3><1> +sdc_d2 = port:PC10<3><1> +sdc_d3 = port:PC11<3><1> + +[twi_para] +twi_port = 0 +twi_scl = port:PB00<2> +twi_sda = port:PB01<2> + +[uart_para] +uart_debug_port = 0 +uart_debug_tx = port:PB22<2><1> +uart_debug_rx = port:PB23<2><1> + +[uart_force_debug] +uart_debug_port = 0 +uart_debug_tx = port:PF02<4><1> +uart_debug_rx = port:PF04<4><1> + +[jtag_para] +jtag_enable = 0 +jtag_ms = port:PB14<3> +jtag_ck = port:PB15<3> +jtag_do = port:PB16<3> +jtag_di = port:PB17<3> + +[pm_para] +standby_mode = 0 + +[dram_para] +dram_baseaddr = 0x40000000 +dram_clk = 432 +dram_type = 3 +dram_rank_num = 1 +dram_chip_density = 4096 +dram_io_width = 16 +dram_bus_width = 32 +dram_cas = 9 +dram_zq = 0x7f +dram_odt_en = 0 +dram_size = 1024 +dram_tpr0 = 0x42d899b7 +dram_tpr1 = 0xa090 +dram_tpr2 = 0x22a00 +dram_tpr3 = 0x0 +dram_tpr4 = 0x1 +dram_tpr5 = 0x0 +dram_emr1 = 0x4 +dram_emr2 = 0x10 +dram_emr3 = 0x0 + +[mali_para] +mali_used = 1 +mali_clkdiv = 1 + +[gmac_para] +gmac_used = 1 +gmac_rxd3 = port:PA00<5><3> +gmac_rxd2 = port:PA01<5><3> +gmac_rxd1 = port:PA02<5><3> +gmac_rxd0 = port:PA03<5><3> +gmac_txd3 = port:PA04<5><3> +gmac_txd2 = port:PA05<5><3> +gmac_txd1 = port:PA06<5><3> +gmac_txd0 = port:PA07<5><3> +gmac_rxclk = port:PA08<5><3> +gmac_rxerr = port:PA09<0><3> +gmac_rxctl = port:PA10<5><3> +gmac_mdc = port:PA11<5><3> +gmac_mdio = port:PA12<5><3> +gmac_txctl = port:PA13<5><3> +gmac_txclk = port:PA14<0><3> +gmac_txck = port:PA15<5><3> +gmac_clkin = port:PA16<5><3> +gmac_txerr = port:PA17<0><3> + +[gmac_phy_power] +gmac_phy_power_en = port:PH23<1><0> + +[twi0_para] +twi0_used = 1 +twi0_scl = port:PB00<2> +twi0_sda = port:PB01<2> + +[twi1_para] +twi1_used = 1 +twi1_scl = port:PB18<2> +twi1_sda = port:PB19<2> + +[twi2_para] +twi2_used = 1 +twi2_scl = port:PB20<2> +twi2_sda = port:PB21<2> + +[twi3_para] +twi3_used = 1 +twi3_scl = port:PI00<3> +twi3_sda = port:PI01<3> + +[uart_para0] +uart_used = 1 +uart_port = 0 +uart_type = 2 +uart_tx = port:PB22<2><1> +uart_rx = port:PB23<2><1> + +[uart_para1] +uart_used = 0 +uart_port = 1 +uart_type = 8 +uart_tx = port:PA10<4><1> +uart_rx = port:PA11<4><1> +uart_rts = port:PA12<4><1> +uart_cts = port:PA13<4><1> +uart_dtr = port:PA14<4><1> +uart_dsr = port:PA15<4><1> +uart_dcd = port:PA16<4><1> +uart_ring = port:PA17<4><1> + +[uart_para2] +uart_used = 1 +uart_port = 2 +uart_type = 4 +uart_tx = port:PI18<3><1> +uart_rx = port:PI19<3><1> +uart_rts = port:PI16<3><1> +uart_cts = port:PI17<3><1> + +[uart_para3] +uart_used = 1 +uart_port = 3 +uart_type = 2 +uart_tx = port:PH00<4><1> +uart_rx = port:PH01<4><1> + +[uart_para4] +uart_used = 0 +uart_port = 4 +uart_type = 2 +uart_tx = port:PH04<4><1> +uart_rx = port:PH05<4><1> + +[uart_para5] +uart_used = 0 +uart_port = 5 +uart_type = 2 +uart_tx = port:PH06<4><1> +uart_rx = port:PH07<4><1> + +[uart_para6] +uart_used = 0 +uart_port = 6 +uart_type = 2 +uart_tx = port:PA12<4><1> +uart_rx = port:PA13<4><1> + +[uart_para7] +uart_used = 1 +uart_port = 7 +uart_type = 2 +uart_tx = port:PI20<3><1> +uart_rx = port:PI21<3><1> + +[spi0_para] +spi_used = 1 +spi_cs_bitmap = 3 +spi_cs0 = port:PI10<2> +spi_cs1 = port:PI14<2> +spi_sclk = port:PI11<2> +spi_mosi = port:PI12<2> +spi_miso = port:PI13<2> + +[spi1_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA00<3> +spi_cs1 = port:PA04<3> +spi_sclk = port:PA01<3> +spi_mosi = port:PA02<3> +spi_miso = port:PA03<3> + +[spi2_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PC19<3> +spi_cs1 = port:PB13<2> +spi_sclk = port:PC20<3> +spi_mosi = port:PC21<3> +spi_miso = port:PC22<3> + +[spi3_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA05<3> +spi_cs1 = port:PA09<3> +spi_sclk = port:PA06<3> +spi_mosi = port:PA07<3> +spi_miso = port:PA08<3> + +[spi_devices] +spi_dev_num = 2 + +[spi_board0] +modalias = "spidev" +max_speed_hz = 12000000 +bus_num = 0 +chip_select = 0 +mode = 3 +full_duplex = 0 +manual_cs = 0 + +[spi_board1] +modalias = "spidev" +max_speed_hz = 12000000 +bus_num = 0 +chip_select = 1 +mode = 3 +full_duplex = 0 +manual_cs = 0 + +[ctp_para] +ctp_used = 0 +ctp_name = "ft5x_ts" +ctp_twi_id = 3 +ctp_twi_addr = 0x38 +ctp_screen_max_x = 1024 +ctp_screen_max_y = 600 +ctp_revert_x_flag = 0 +ctp_revert_y_flag = 0 +ctp_exchange_x_y_flag = 0 +ctp_firm = 1 +ctp_int_port = port:PH09<6> +ctp_wakeup = port:PH07<1><1> +ctp_io_port = port:PH09<0> + + +[ctp_list_para] +ctp_det_used = 1 +ft5x_ts = 1 +gt82x = 0 +gslX680 = 0 +gt9xx_ts = 0 +gt811 = 0 + +[tkey_para] +tkey_used = 0 +tkey_twi_id = 2 +tkey_twi_addr = 0x62 +tkey_int = port:PI13<6> + +[motor_para] +motor_used = 0 +motor_shake = port:PB03<1><1> + +[gpio_para] +gpio_used = 1 +gpio_num = 88 +gpio_pin_1 = port:PB20<1> +gpio_pin_2 = port:PB21<1> +gpio_pin_3 = port:PB20<1> +gpio_pin_4 = port:PI03<1> +gpio_pin_5 = port:PB22<1> +gpio_pin_6 = port:PB23<1> +gpio_pin_7 = port:PI14<1> +gpio_pin_8 = port:PI10<1> +gpio_pin_9 = port:PI13<1> +gpio_pin_10 = port:PI12<1> +gpio_pin_11 = port:PI11<1> +gpio_pin_12 = port:PH05<1> +gpio_pin_13 = port:PH03<1> +gpio_pin_14 = port:PH00<1> +gpio_pin_15 = port:PH01<1> +gpio_pin_16 = port:PH01<1> +gpio_pin_17 = port:PI19<1> +gpio_pin_18 = port:PH02<1> +gpio_pin_19 = port:PH02<1> +gpio_pin_20 = port:PI20<1> +gpio_pin_21 = port:PI21<1> +gpio_pin_22 = port:PI17<1> +gpio_pin_23 = port:PH20<1> +gpio_pin_24 = port:PH21<1> +gpio_pin_25 = port:PI16<1> +gpio_pin_26 = port:PI16<1> +gpio_pin_27 = port:PI18<1> +gpio_pin_28 = port:PH05<1> +gpio_pin_29 = port:PI21<1> +gpio_pin_30 = port:PH03<1> +gpio_pin_31 = port:PI20<1> +gpio_pin_32 = port:PH17<1> +gpio_pin_33 = port:PB19<1> +gpio_pin_34 = port:PB18<1> +gpio_pin_35 = port:PH19<1> +gpio_pin_36 = port:PE00<1> +gpio_pin_37 = port:PH16<1> +gpio_pin_38 = port:PE01<1> +gpio_pin_39 = port:PH14<1> +gpio_pin_40 = port:PE03<1> +gpio_pin_41 = port:PE02<1> +gpio_pin_42 = port:PH18<1> +gpio_pin_43 = port:PH11<1> +gpio_pin_44 = port:PE04<1> +gpio_pin_45 = port:PE05<1> +gpio_pin_46 = port:PE06<1> +gpio_pin_47 = port:PE07<1> +gpio_pin_48 = port:PE08<1> +gpio_pin_49 = port:PE09<1> +gpio_pin_50 = port:PE10<1> +gpio_pin_51 = port:PE11<1> +gpio_pin_52 = port:PH13<1> +gpio_pin_53 = port:PI01<1> +gpio_pin_54 = port:PI00<1> +gpio_pin_55 = port:PH07<1> +gpio_pin_56 = port:PH08<1> +gpio_pin_57 = port:PB02<1> +gpio_pin_58 = port:PH09<1> +gpio_pin_59 = port:PD25<1> +gpio_pin_60 = port:PD27<1> +gpio_pin_61 = port:PD26<1> +gpio_pin_62 = port:PH06<1> +gpio_pin_63 = port:PD24<1> +gpio_pin_64 = port:PD23<1> +gpio_pin_65 = port:PD22<1> +gpio_pin_66 = port:PD21<1> +gpio_pin_67 = port:PD20<1> +gpio_pin_68 = port:PD19<1> +gpio_pin_69 = port:PD18<1> +gpio_pin_70 = port:PD17<1> +gpio_pin_71 = port:PD16<1> +gpio_pin_72 = port:PH12<1> +gpio_pin_73 = port:PD00<1> +gpio_pin_74 = port:PD01<1> +gpio_pin_75 = port:PD02<1> +gpio_pin_76 = port:PD03<1> +gpio_pin_77 = port:PD04<1> +gpio_pin_78 = port:PD05<1> +gpio_pin_79 = port:PD06<1> +gpio_pin_80 = port:PD07<1> +gpio_pin_81 = port:PD08<1> +gpio_pin_82 = port:PD09<1> +gpio_pin_83 = port:PD10<1> +gpio_pin_84 = port:PD11<1> +gpio_pin_85 = port:PD12<1> +gpio_pin_86 = port:PD13<1> +gpio_pin_87 = port:PD14<1> +gpio_pin_88 = port:PD15<1> + +[nand_para] +nand_used = 0 +nand_we = port:PC00<2> +nand_ale = port:PC01<2> +nand_cle = port:PC02<2> +nand_ce1 = port:PC03<2> +nand_ce0 = port:PC04<2> +nand_nre = port:PC05<2> +nand_rb0 = port:PC06<2> +nand_rb1 = port:PC07<2> +nand_d0 = port:PC08<2> +nand_d1 = port:PC09<2> +nand_d2 = port:PC10<2> +nand_d3 = port:PC11<2> +nand_d4 = port:PC12<2> +nand_d5 = port:PC13<2> +nand_d6 = port:PC14<2> +nand_d7 = port:PC15<2> +nand_wp = port:PC16<2> +nand_ce2 = port:PC17<2> +nand_ce3 = port:PC18<2> +nand_ce4 = +nand_ce5 = +nand_ce6 = +nand_ce7 = +nand_spi = port:PC23<3> +nand_ndqs = port:PC24<2> +good_block_ratio = 0 + +[disp_init] +disp_init_enable = 1 +disp_mode = 0 +screen0_output_type = 3 +screen0_output_mode = 4 +screen1_output_type = 2 +screen1_output_mode = 11 +fb0_framebuffer_num = 2 +fb0_format = 10 +fb0_pixel_sequence = 0 +fb0_scaler_mode_enable = 1 +fb1_framebuffer_num = 2 +fb1_format = 10 +fb1_pixel_sequence = 0 +fb1_scaler_mode_enable = 0 +lcd0_backlight = 197 +lcd1_backlight = 197 +lcd0_bright = 50 +lcd0_contrast = 50 +lcd0_saturation = 57 +lcd0_hue = 50 +lcd1_bright = 50 +lcd1_contrast = 50 +lcd1_saturation = 57 +lcd1_hue = 50 + +[lcd0_para] +lcd_used = 0 +lcd_x = 1024 +lcd_y = 600 +lcd_dclk_freq = 55 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 0 +lcd_pwm_freq = 22000 +lcd_pwm_pol = 0 +lcd_max_bright = 240 +lcd_min_bright = 64 +lcd_if = 3 +lcd_hbp = 150 +lcd_ht = 1344 +lcd_vbp = 20 +lcd_vt = 1270 +lcd_vspw = 10 +lcd_hspw = 50 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 268435456 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 1 +lcd_bl_en = port:PH07<1><0><1> +lcd_power_used = 1 +lcd_power = port:PH08<1><0><1> +lcd_pwm_used = 1 +lcd_pwm = port:PB02<2><0> +lcdd0 = port:PD00<3><0> +lcdd1 = port:PD01<3><0> +lcdd2 = port:PD02<3><0> +lcdd3 = port:PD03<3><0> +lcdd4 = port:PD04<3><0> +lcdd5 = port:PD05<3><0> +lcdd6 = port:PD06<3><0> +lcdd7 = port:PD07<3><0> +lcdd8 = port:PD08<3><0> +lcdd9 = port:PD09<3><0> +lcdd10 = port:PD10<2><0> +lcdd11 = port:PD11<2><0> +lcdd12 = port:PD12<2><0> +lcdd13 = port:PD13<2><0> +lcdd14 = port:PD14<2><0> +lcdd15 = port:PD15<2><0> +lcdd16 = port:PD16<2><0> +lcdd17 = port:PD17<2><0> +lcdd18 = port:PD18<2><0> +lcdd19 = port:PD19<2><0> +lcdd20 = port:PD20<2><0> +lcdd21 = port:PD21<2><0> +lcdd22 = port:PD22<2><0> +lcdd23 = port:PD23<2><0> +lcdclk = port:PD24<2><0> +lcdde = port:PD25<2><0><3> +lcdhsync = port:PD26<2><0><3> +lcdvsync = port:PD27<2><0><3> + +[lcd1_para] +lcd_used = 0 +lcd_x = 0 +lcd_y = 0 +lcd_dclk_freq = 0 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 1 +lcd_pwm_freq = 0 +lcd_pwm_pol = 0 +lcd_max_bright = 240 +lcd_min_bright = 64 +lcd_if = 0 +lcd_hbp = 0 +lcd_ht = 0 +lcd_vbp = 0 +lcd_vt = 0 +lcd_vspw = 0 +lcd_hspw = 0 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 0 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 0 +lcd_bl_en = +lcd_power_used = 0 +lcd_power = +lcd_pwm_used = 1 +lcd_pwm = port:PI03<2><0> +lcd_gpio_0 = +lcd_gpio_1 = +lcd_gpio_2 = +lcd_gpio_3 = +lcdd0 = port:PH00<2><0> +lcdd1 = port:PH01<2><0> +lcdd2 = port:PH02<2><0> +lcdd3 = port:PH03<2><0> +lcdd4 = port:PH04<2><0> +lcdd5 = port:PH05<2><0> +lcdd6 = port:PH06<2><0> +lcdd7 = port:PH07<2><0> +lcdd8 = port:PH08<2><0> +lcdd9 = port:PH09<2><0> +lcdd10 = port:PH10<2><0> +lcdd11 = port:PH11<2><0> +lcdd12 = port:PH12<2><0> +lcdd13 = port:PH13<2><0> +lcdd14 = port:PH14<2><0> +lcdd15 = port:PH15<2><0> +lcdd16 = port:PH16<2><0> +lcdd17 = port:PH17<2><0> +lcdd18 = port:PH18<2><0> +lcdd19 = port:PH19<2><0> +lcdd20 = port:PH20<2><0> +lcdd21 = port:PH21<2><0> +lcdd22 = port:PH22<2><0> +lcdd23 = port:PH23<2><0> +lcdclk = port:PH24<2><0> +lcdde = port:PH25<2><0> +lcdhsync = port:PH26<2><0> +lcdvsync = port:PH27<2><0> + +[tv_out_dac_para] +dac_used = 0 +dac0_src = 4 +dac1_src = 5 +dac2_src = 6 +dac3_src = 0 + +[hdmi_para] +hdmi_used = 1 + +[csi0_para] +csi_used = 1 +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "ov5640" +csi_twi_id = 1 +csi_twi_addr = 0x78 +csi_if = 0 +csi_vflip = 1 +csi_hflip = 0 +csi_iovdd = "axp20_pll" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = 2800 +csi_vol_dvdd = +csi_vol_avdd = +csi_flash_pol = 0 +csi_facing = 0 +csi_pck = port:PE00<3> +csi_ck = port:PE01<3> +csi_hsync = port:PE02<3> +csi_vsync = port:PE03<3> +csi_d0 = port:PE04<3> +csi_d1 = port:PE05<3> +csi_d2 = port:PE06<3> +csi_d3 = port:PE07<3> +csi_d4 = port:PE08<3> +csi_d5 = port:PE09<3> +csi_d6 = port:PE10<3> +csi_d7 = port:PE11<3> +csi_reset = port:PH14<1><0> +csi_power_en = port:PH16<1><0> +csi_stby = port:PH19<1><0> + +[csi1_para] +csi_used = 0 +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "gc0308" +csi_if = 0 +csi_iovdd = "axp20_pll" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = 2800 +csi_vol_dvdd = +csi_vol_avdd = +csi_vflip = 0 +csi_hflip = 0 +csi_flash_pol = 0 +csi_facing = 1 +csi_twi_id = 1 +csi_twi_addr = 0x42 +csi_pck = port:PG00<3> +csi_ck = port:PG01<3> +csi_hsync = port:PG02<3> +csi_vsync = port:PG03<3> +csi_d0 = port:PG04<3> +csi_d1 = port:PG05<3> +csi_d2 = port:PG06<3> +csi_d3 = port:PG07<3> +csi_d4 = port:PG08<3> +csi_d5 = port:PG09<3> +csi_d6 = port:PG10<3> +csi_d7 = port:PG11<3> +csi_reset = port:PH13<1><0> +csi_power_en = port:PH16<1><0> +csi_stby = port:PH18<1><0> + +[camera_list_para] +camera_list_para_used = 1 +ov7670 = 0 +gc0308 = 0 +gt2005 = 0 +hi704 = 0 +sp0838 = 0 +mt9m112 = 0 +mt9m113 = 0 +ov2655 = 0 +hi253 = 0 +gc0307 = 0 +mt9d112 = 0 +ov5640 = 1 +gc2015 = 0 +ov2643 = 0 +gc0329 = 0 +gc0309 = 0 +tvp5150 = 0 +s5k4ec = 0 +ov5650_mv9335 = 0 +siv121d = 0 +gc2035 = 0 + +[tvout_para] +tvout_used = 0 +tvout_channel_num = 1 + +[tvin_para] +tvin_used = 0 +tvin_channel_num = 4 + +[sata_para] +sata_used = 1 +sata_power_en = port:PB03<1><0> + +[mmc0_para] +sdc_used = 1 +sdc_detmode = 1 +sdc_buswidth = 4 +sdc_clk = port:PF02<2><1><2> +sdc_cmd = port:PF03<2><1><2> +sdc_d0 = port:PF01<2><1><2> +sdc_d1 = port:PF00<2><1><2> +sdc_d2 = port:PF05<2><1><2> +sdc_d3 = port:PF04<2><1><2> +sdc_det = port:PH10<0><1> +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc1_para] +sdc_used = 0 +sdc_detmode = 4 +sdc_buswidth = 4 +sdc_clk = port:PG00<2><1><2> +sdc_cmd = port:PG01<2><1><2> +sdc_d0 = port:PG02<2><1><2> +sdc_d1 = port:PG03<2><1><2> +sdc_d2 = port:PG04<2><1><2> +sdc_d3 = port:PG05<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc2_para] +sdc_used = 0 +sdc_detmode = 3 +sdc_buswidth = 4 +sdc_cmd = port:PC06<3><1><2> +sdc_clk = port:PC07<3><1><2> +sdc_d0 = port:PC08<3><1><2> +sdc_d1 = port:PC09<3><1><2> +sdc_d2 = port:PC10<3><1><2> +sdc_d3 = port:PC11<3><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc3_para] +sdc_used = 0 +sdc_detmode = 4 +sdc_buswidth = 4 +sdc_cmd = port:PI04<2><1><2> +sdc_clk = port:PI05<2><1><2> +sdc_d0 = port:PI06<2><1><2> +sdc_d1 = port:PI07<2><1><2> +sdc_d2 = port:PI08<2><1><2> +sdc_d3 = port:PI09<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 1 +sdc_regulator = "none" + +[ms_para] +ms_used = 0 +ms_bs = port:PH06<5> +ms_clk = port:PH07<5> +ms_d0 = port:PH08<5> +ms_d1 = port:PH09<5> +ms_d2 = port:PH10<5> +ms_d3 = port:PH11<5> +ms_det = + +[smc_para] +smc_used = 0 +smc_rst = port:PH13<5> +smc_vppen = port:PH14<5> +smc_vppp = port:PH15<5> +smc_det = port:PH16<5> +smc_vccen = port:PH17<5> +smc_sck = port:PH18<5> +smc_sda = port:PH19<5> + +[ps2_0_para] +ps2_used = 0 +ps2_scl = port:PI20<2><1> +ps2_sda = port:PI21<2><1> + +[ps2_1_para] +ps2_used = 0 +ps2_scl = port:PI14<3><1> +ps2_sda = port:PI15<3><1> + +[can_para] +can_used = 0 +can_tx = port:PA16<3> +can_rx = port:PA17<3> + +[keypad_para] +kp_used = 0 +kp_in_size = 8 +kp_out_size = 8 +kp_in0 = port:PH08<4><1> +kp_in1 = port:PH09<4><1> +kp_in2 = port:PH10<4><1> +kp_in3 = port:PH11<4><1> +kp_in4 = port:PH14<4><1> +kp_in5 = port:PH15<4><1> +kp_in6 = port:PH16<4><1> +kp_in7 = port:PH17<4><1> +kp_out0 = port:PH18<4><1> +kp_out1 = port:PH19<4><1> +kp_out2 = port:PH22<4><1> +kp_out3 = port:PH23<4><1> +kp_out4 = port:PH24<4><1> +kp_out5 = port:PH25<4><1> +kp_out6 = port:PH26<4><1> +kp_out7 = port:PH27<4><1> + +[usbc0] +usb_used = 0 +usb_port_type = 2 +usb_detect_type = 1 +usb_id_gpio = port:PH04<0><1> +usb_det_vbus_gpio = "axp_ctrl" +usb_drv_vbus_gpio = port:PB09<1><0><0> +usb_ac_enable_gpio = port:PH05<1><0><0> +usb_restrict_gpio = 0 +usb_host_init_state = 0 +usb_restric_flag = 0 +usb_restric_voltage = 3550000 +usb_restric_capacity = 5 + +[usbc1] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PH06<1><0><0> +usb_restrict_gpio = +usb_host_init_state = 1 +usb_restric_flag = 0 + +[usbc2] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PH03<1><0><0> +usb_restrict_gpio = +usb_host_init_state = 1 +usb_restric_flag = 0 + +[usb_feature] +vendor_id = 6353 +mass_storage_id = 1 +adb_id = 2 +manufacturer_name = "USB Developer" +product_name = "Android" +serial_number = "20080411" + +[msc_feature] +vendor_name = "USB 2.0" +product_name = "USB Flash Driver" +release = 100 +luns = 3 + +[gsensor_para] +gsensor_used = 0 +gsensor_twi_id = 1 +gsensor_int1 = +gsensor_int2 = + +[gsensor_list_para] +gsensor_det_used = 0 +bma250 = 1 +mma8452 = 1 +mma7660 = 1 +mma865x = 1 +afa750 = 1 +lis3de_acc = 1 +lis3dh_acc = 1 +kxtik = 1 +dmard10 = 0 +dmard06 = 1 +mxc622x = 1 +fxos8700 = 1 +lsm303d = 1 + +[gps_para] +gps_used = 0 +gps_spi_id = 2 +gps_spi_cs_num = 0 +gps_lradc = 1 +gps_clk = port:PI00<2> +gps_sign = port:PI01<2> +gps_mag = port:PI02<2> +gps_vcc_en = port:PC22<1><0> +gps_osc_en = port:PI14<1><0> +gps_rx_en = port:PI15<1><0> + +[wifi_para] +wifi_used = 0 +wifi_sdc_id = 3 +wifi_usbc_id = 2 +wifi_usbc_type = 1 +wifi_mod_sel = 6 +wifi_power = "" +ap6xxx_wl_regon = port:PH09<1><0> +ap6xxx_wl_host_wake = port:PH10<0><0> +ap6xxx_bt_regon = port:PH18<1><0> +ap6xxx_bt_wake = port:PH24<1><0> +ap6xxx_bt_host_wake = port:PH25<0><0> +ap6xxx_lpo = port:PI12<4><1><1> + +[usb_wifi_para] +usb_wifi_used = 1 +usb_wifi_usbc_num = 2 + +[3g_para] +3g_used = 0 +3g_usbc_num = 2 +3g_uart_num = 0 +3g_pwr = +3g_wakeup = +3g_int = + +[gy_para] +gy_used = 0 +gy_twi_id = 1 +gy_twi_addr = 0 +gy_int1 = port:PH18<6><1> +gy_int2 = port:PH19<6><1> + +[ls_para] +ls_used = 0 +ls_twi_id = 1 +ls_twi_addr = 0 +ls_int = port:PH20<6><1> + +[compass_para] +compass_used = 0 +compass_twi_id = 1 +compass_twi_addr = 0 +compass_int = port:PI13<6><1> + +[bt_para] +bt_used = 0 +bt_uart_id = 2 +bt_wakeup = port:PI20<1> +bt_gpio = port:PI21<1> +bt_rst = port:PB05<1> + +[i2s_para] +i2s_used = 0 +i2s_channel = 2 +i2s_mclk = port:PB05<2><1> +i2s_bclk = port:PB06<2><1> +i2s_lrclk = port:PB07<2><1> +i2s_dout0 = port:PB08<2><1> +i2s_dout1 = +i2s_dout2 = +i2s_dout3 = +i2s_din = port:PB12<2><1> + +[spdif_para] +spdif_used = 0 +spdif_mclk = +spdif_dout = port:PB13<4><1> +spdif_din = + +[audio_para] +audio_used = 1 +capture_used = 1 +audio_pa_ctrl = port:PH15<1><1> + +[switch_para] +switch_used = 0 + +[leds_para] +leds_used = 1 +leds_num = 1 +leds_pin_1 = port:PH24<1><0> +leds_name_1 = "green:ph24:led1" +leds_default_1 = 1 +leds_trigger_1 = "mmc0" + +[ir_para] +ir_used = 1 +ir0_rx = port:PB04<2> + +[pmu_para] +pmu_used = 1 +pmu_twi_addr = 52 +pmu_twi_id = 0 +pmu_irq_id = 32 +pmu_battery_rdc = 100 +pmu_battery_cap = 3200 +pmu_init_chgcur = 300 +pmu_earlysuspend_chgcur = 600 +pmu_suspend_chgcur = 1000 +pmu_resume_chgcur = 300 +pmu_shutdown_chgcur = 1000 +pmu_init_chgvol = 4200 +pmu_init_chgend_rate = 15 +pmu_init_chg_enabled = 1 +pmu_init_adc_freq = 100 +pmu_init_adc_freqc = 100 +pmu_init_chg_pretime = 50 +pmu_init_chg_csttime = 720 +pmu_bat_para1 = 0 +pmu_bat_para2 = 0 +pmu_bat_para3 = 0 +pmu_bat_para4 = 0 +pmu_bat_para5 = 5 +pmu_bat_para6 = 8 +pmu_bat_para7 = 11 +pmu_bat_para8 = 22 +pmu_bat_para9 = 33 +pmu_bat_para10 = 43 +pmu_bat_para11 = 50 +pmu_bat_para12 = 59 +pmu_bat_para13 = 71 +pmu_bat_para14 = 83 +pmu_bat_para15 = 92 +pmu_bat_para16 = 100 +pmu_usbvol_limit = 1 +pmu_usbcur_limit = 0 +pmu_usbvol = 4000 +pmu_usbcur = 0 +pmu_usbvol_pc = 4400 +pmu_usbcur_pc = 500 +pmu_pwroff_vol = 3300 +pmu_pwron_vol = 2900 +pmu_pekoff_time = 4000 +pmu_pekoff_en = 1 +pmu_peklong_time = 1500 +pmu_pekon_time = 1000 +pmu_pwrok_time = 64 +pmu_pwrnoe_time = 2000 +pmu_intotp_en = 1 +pmu_backupen = 1 +pmu_used2 = 0 +pmu_adpdet = port:PH02<0> +pmu_init_chgcur2 = 400 +pmu_earlysuspend_chgcur2 = 600 +pmu_suspend_chgcur2 = 1200 +pmu_resume_chgcur2 = 400 +pmu_shutdown_chgcur2 = 1200 +pmu_suspendpwroff_vol = 3500 +pmu_batdeten = 1 + +[recovery_key] +key_min = 4 +key_max = 10 + +[dvfs_table] +max_freq = 912000000 +min_freq = 720000000 +LV_count = 7 +LV1_freq = 1008000000 +LV1_volt = 1450 +LV2_freq = 912000000 +LV2_volt = 1425 +LV3_freq = 864000000 +LV3_volt = 1350 +LV4_freq = 720000000 +LV4_volt = 1250 +LV5_freq = 528000000 +LV5_volt = 1150 +LV6_freq = 312000000 +LV6_volt = 1100 +LV7_freq = 144000000 +LV7_volt = 1050 + diff --git a/config/lime-a10.fex b/config/lime-a10.fex new file mode 100644 index 000000000..7f0c1b8b9 --- /dev/null +++ b/config/lime-a10.fex @@ -0,0 +1,937 @@ +[product] +version = "1.0" +machine = "A10-EVB-V1.2" + +[target] +boot_clock = 1008 +dcdc2_vol = 1400 +dcdc3_vol = 1250 +ldo2_vol = 3000 +ldo3_vol = 2800 +ldo4_vol = 2800 +pll4_freq = 960 +pll6_freq = 960 +power_start = 0 +storage_type = 0 + +[card_boot] +logical_start = 40960 +sprite_gpio0 = + +[card_boot0_para] +card_ctrl = 0 +card_high_speed = 1 +card_line = 4 +sdc_d1 = port:PF00<2><1> +sdc_d0 = port:PF01<2><1> +sdc_clk = port:PF02<2><1> +sdc_cmd = port:PF03<2><1> +sdc_d3 = port:PF04<2><1> +sdc_d2 = port:PF05<2><1> + +[card_boot2_para] +card_ctrl = 2 +card_high_speed = 1 +card_line = 4 +sdc_cmd = port:PC06<3><1> +sdc_clk = port:PC07<3><1> +sdc_d0 = port:PC08<3><1> +sdc_d1 = port:PC09<3><1> +sdc_d2 = port:PC10<3><1> +sdc_d3 = port:PC11<3><1> + +[twi_para] +twi_port = 0 +twi_scl = port:PB00<2> +twi_sda = port:PB01<2> + +[uart_para] +uart_debug_port = 0 +uart_debug_tx = port:PB22<2><1> +uart_debug_rx = port:PB23<2><1> + +[uart_force_debug] +uart_debug_port = 0 +uart_debug_tx = port:PF02<4> +uart_debug_rx = port:PF04<4> + +[jtag_para] +jtag_enable = 0 +jtag_ms = port:PB14<3> +jtag_ck = port:PB15<3> +jtag_do = port:PB16<3> +jtag_di = port:PB17<3> + +[dram_para] +dram_baseaddr = 0x40000000 +dram_clk = 480 +dram_type = 3 +dram_rank_num = 1 +dram_chip_density = 4096 +dram_io_width = 16 +dram_bus_width = 16 +dram_cas = 6 +dram_zq = 0x7b +dram_odt_en = 0 +dram_size = 512 +dram_tpr0 = 0x30926692 +dram_tpr1 = 0x1090 +dram_tpr2 = 0x1a0c8 +dram_tpr3 = 0x0 +dram_tpr4 = 0x0 +dram_tpr5 = 0x0 +dram_emr1 = 0x4 +dram_emr2 = 0x0 +dram_emr3 = 0x0 + +[mali_para] +mali_used = 1 +mali_clkdiv = 3 + +[g2d_para] +g2d_used = 1 +g2d_size = 0x1000000 + +[emac_para] +emac_used = 1 +emac_rxd3 = port:PA00<2> +emac_rxd2 = port:PA01<2> +emac_rxd1 = port:PA02<2> +emac_rxd0 = port:PA03<2> +emac_txd3 = port:PA04<2> +emac_txd2 = port:PA05<2> +emac_txd1 = port:PA06<2> +emac_txd0 = port:PA07<2> +emac_rxclk = port:PA08<2> +emac_rxerr = port:PA09<2> +emac_rxdV = port:PA10<2> +emac_mdc = port:PA11<2> +emac_mdio = port:PA12<2> +emac_txen = port:PA13<2> +emac_txclk = port:PA14<2> +emac_crs = port:PA15<2> +emac_col = port:PA16<2> +emac_reset = port:PA17<1> + +[twi0_para] +twi0_used = 1 +twi0_scl = port:PB00<2> +twi0_sda = port:PB01<2> + +[twi1_para] +twi1_used = 0 +twi1_scl = port:PB18<2> +twi1_sda = port:PB19<2> + +[twi2_para] +twi2_used = 0 +twi2_scl = port:PB20<2> +twi2_sda = port:PB21<2> + +[uart_para0] +uart_used = 1 +uart_port = 0 +uart_type = 2 +uart_tx = port:PB22<2><1> +uart_rx = port:PB23<2><1> + +[uart_para1] +uart_used = 0 +uart_port = 1 +uart_type = 8 +uart_tx = port:PA10<4><1> +uart_rx = port:PA11<4><1> +uart_rts = port:PA12<4><1> +uart_cts = port:PA13<4><1> +uart_dtr = port:PA14<4><1> +uart_dsr = port:PA15<4><1> +uart_dcd = port:PA16<4><1> +uart_ring = port:PA17<4><1> + +[uart_para2] +uart_used = 0 +uart_port = 2 +uart_type = 4 +uart_tx = port:PI18<3><1> +uart_rx = port:PI19<3><1> +uart_rts = port:PI16<3><1> +uart_cts = port:PI17<3><1> + +[uart_para3] +uart_used = 0 +uart_port = 3 +uart_type = 4 +uart_tx = port:PH00<4><1> +uart_rx = port:PH01<4><1> +uart_rts = port:PH02<4><1> +uart_cts = port:PH03<4><1> + +[uart_para4] +uart_used = 0 +uart_port = 4 +uart_type = 2 +uart_tx = port:PH04<4><1> +uart_rx = port:PH05<4><1> + +[uart_para5] +uart_used = 0 +uart_port = 5 +uart_type = 2 +uart_tx = port:PH06<4><1> +uart_rx = port:PH07<4><1> + +[uart_para6] +uart_used = 0 +uart_port = 6 +uart_type = 2 +uart_tx = port:PA12<4><1> +uart_rx = port:PA13<4><1> + +[uart_para7] +uart_used = 0 +uart_port = 7 +uart_type = 2 +uart_tx = port:PA14<4><1> +uart_rx = port:PA15<4><1> + +[spi0_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PI10<3> +spi_sclk = port:PI11<3> +spi_mosi = port:PI12<3> +spi_miso = port:PI13<3> + +[spi1_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA00<4> +spi_sclk = port:PA01<4> +spi_mosi = port:PA02<4> +spi_miso = port:PA03<4> + +[spi2_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PB14<2> +spi_sclk = port:PB15<2> +spi_mosi = port:PB16<2> +spi_miso = port:PB17<2> +spi_cs0 = port:PC19<3> +spi_sclk = port:PC20<3> +spi_mosi = port:PC21<3> +spi_miso = port:PC22<3> + +[spi3_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA05<3> +spi_sclk = port:PI06<3> +spi_mosi = port:PI07<3> +spi_miso = port:PI08<3> +spi_cs1 = port:PA09<3> + +[spi_devices] +spi_dev_num = 0 + +[spi_board0] +modalias = "aaa" +max_speed_hz = 12000000 +bus_num = 1 +chip_select = 0 +mode = 3 +full_duplex = 0 +manual_cs = 0 + +[rtp_para] +rtp_used = 0 +rtp_screen_size = 5 +rtp_regidity_level = 5 +rtp_press_threshold_enable = 0 +rtp_press_threshold = 0x1f40 +rtp_sensitive_level = 0xf +rtp_exchange_x_y_flag = 0 + +[ctp_para] +ctp_used = 0 +ctp_name = "ft5x_ts" +ctp_twi_id = 2 +ctp_twi_addr = 0x70 +ctp_screen_max_x = 800 +ctp_screen_max_y = 480 +ctp_revert_x_flag = 0 +ctp_revert_y_flag = 0 +ctp_exchange_x_y_flag = 0 +ctp_int_port = port:PH21<6> +ctp_wakeup = port:PB13<1><1> +ctp_io_port = port:PH21<0> + +[tkey_para] +tkey_used = 0 +tkey_name = "hv_keypad" +tkey_twi_id = 2 +tkey_twi_addr = 0x62 +tkey_int = port:PI13<6> + +[motor_para] +motor_used = 0 +motor_shake = port:PB03<1><1> + +[nand_para] +nand_used = 0 +nand_we = port:PC00<2> +nand_ale = port:PC01<2> +nand_cle = port:PC02<2> +nand_ce1 = port:PC03<2> +nand_ce0 = port:PC04<2> +nand_nre = port:PC05<2> +nand_rb0 = port:PC06<2> +nand_rb1 = port:PC07<2> +nand_d0 = port:PC08<2> +nand_d1 = port:PC09<2> +nand_d2 = port:PC10<2> +nand_d3 = port:PC11<2> +nand_d4 = port:PC12<2> +nand_d5 = port:PC13<2> +nand_d6 = port:PC14<2> +nand_d7 = port:PC15<2> +nand_wp = port:PC16<2> +nand_ce2 = port:PC17<2> +nand_ce3 = port:PC18<2> +nand_ce4 = +nand_ce5 = +nand_ce6 = +nand_ce7 = +nand_spi = port:PC23<3> +nand_ndqs = port:PC24<2> + +[disp_init] +disp_init_enable = 1 +disp_mode = 0 +screen0_output_type = 3 +screen0_output_mode = 4 +screen1_output_type = 1 +screen1_output_mode = 4 +fb0_framebuffer_num = 2 +fb0_format = 10 +fb0_pixel_sequence = 0 +fb0_scaler_mode_enable = 0 +fb1_framebuffer_num = 2 +fb1_format = 10 +fb1_pixel_sequence = 0 +fb1_scaler_mode_enable = 0 +lcd0_bright = 197 +lcd1_bright = 197 +lcd0_screen_bright = 50 +lcd0_screen_contrast = 50 +lcd0_screen_saturation = 57 +lcd0_screen_hue = 50 +lcd1_screen_bright = 50 +lcd1_screen_contrast = 50 +lcd1_screen_saturation = 57 +lcd1_screen_hue = 50 + +[lcd0_para] +lcd_used = 1 +lcd_x = 800 +lcd_y = 480 +lcd_dclk_freq = 33 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 0 +lcd_pwm_freq = 10000 +lcd_pwm_pol = 0 +lcd_if = 0 +lcd_hbp = 46 +lcd_ht = 1055 +lcd_vbp = 23 +lcd_vt = 1050 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_hv_vspw = 0 +lcd_hv_hspw = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 268435456 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 1 +lcd_bl_en = port:PH07<1><0><1> +lcd_power_used = 1 +lcd_power = port:PH08<1><0><1> +lcd_pwm_used = 1 +lcd_pwm = port:PB02<2><0> +lcd_gpio_0 = +lcd_gpio_1 = +lcd_gpio_2 = +lcd_gpio_3 = +lcdd0 = port:PD00<2><0> +lcdd1 = port:PD01<2><0> +lcdd2 = port:PD02<2><0> +lcdd3 = port:PD03<2><0> +lcdd4 = port:PD04<2><0> +lcdd5 = port:PD05<2><0> +lcdd6 = port:PD06<2><0> +lcdd7 = port:PD07<2><0> +lcdd8 = port:PD08<2><0> +lcdd9 = port:PD09<2><0> +lcdd10 = port:PD10<2><0> +lcdd11 = port:PD11<2><0> +lcdd12 = port:PD12<2><0> +lcdd13 = port:PD13<2><0> +lcdd14 = port:PD14<2><0> +lcdd15 = port:PD15<2><0> +lcdd16 = port:PD16<2><0> +lcdd17 = port:PD17<2><0> +lcdd18 = port:PD18<2><0> +lcdd19 = port:PD19<2><0> +lcdd20 = port:PD20<2><0> +lcdd21 = port:PD21<2><0> +lcdd22 = port:PD22<2><0> +lcdd23 = port:PD23<2><0> +lcdclk = port:PD24<2><0> +lcdde = port:PD25<2><0> +lcdhsync = port:PD26<2><0> +lcdvsync = port:PD27<2><0> + +[lcd1_para] +lcd_used = 0 +lcd_x = 0 +lcd_y = 0 +lcd_dclk_freq = 0 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 1 +lcd_pwm_freq = 0 +lcd_pwm_pol = 0 +lcd_if = 0 +lcd_hbp = 0 +lcd_ht = 0 +lcd_vbp = 0 +lcd_vt = 0 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_hv_vspw = 0 +lcd_hv_hspw = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 0 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 0 +lcd_bl_en = +lcd_power_used = 0 +lcd_power = +lcd_pwm_used = 1 +lcd_pwm = port:PI03<2><0> +lcd_gpio_0 = +lcd_gpio_1 = +lcd_gpio_2 = +lcd_gpio_3 = +lcdd0 = port:PH00<2><0> +lcdd1 = port:PH01<2><0> +lcdd2 = port:PH02<2><0> +lcdd3 = port:PH03<2><0> +lcdd4 = port:PH04<2><0> +lcdd5 = port:PH05<2><0> +lcdd6 = port:PH06<2><0> +lcdd7 = port:PH07<2><0> +lcdd8 = port:PH08<2><0> +lcdd9 = port:PH09<2><0> +lcdd10 = port:PH10<2><0> +lcdd11 = port:PH11<2><0> +lcdd12 = port:PH12<2><0> +lcdd13 = port:PH13<2><0> +lcdd14 = port:PH14<2><0> +lcdd15 = port:PH15<2><0> +lcdd16 = port:PH16<2><0> +lcdd17 = port:PH17<2><0> +lcdd18 = port:PH18<2><0> +lcdd19 = port:PH19<2><0> +lcdd20 = port:PH20<2><0> +lcdd21 = port:PH21<2><0> +lcdd22 = port:PH22<2><0> +lcdd23 = port:PH23<2><0> +lcdclk = port:PH24<2><0> +lcdde = port:PH25<2><0> +lcdhsync = port:PH26<2><0> +lcdvsync = port:PH27<2><0> + +[tv_out_dac_para] +dac_used = 0 +dac0_src = 4 +dac1_src = 5 +dac2_src = 6 +dac3_src = 0 + +[csi0_para] +csi_used = 0 +csi_mode = 0 +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "gc0308" +csi_twi_id = 1 +csi_twi_addr = 0x42 +csi_if = 0 +csi_vflip = 0 +csi_hflip = 1 +csi_iovdd = "" +csi_avdd = "" +csi_dvdd = "" +csi_flash_pol = 1 +csi_mname_b = "" +csi_twi_id_b = 1 +csi_twi_addr_b = 0x78 +csi_if_b = 0 +csi_vflip_b = 1 +csi_hflip_b = 0 +csi_iovdd_b = "" +csi_avdd_b = "" +csi_dvdd_b = "" +csi_flash_pol_b = 1 +csi_pck = port:PE00<3> +csi_ck = port:PE01<3> +csi_hsync = port:PE02<3> +csi_vsync = port:PE03<3> +csi_d0 = port:PE04<3> +csi_d1 = port:PE05<3> +csi_d2 = port:PE06<3> +csi_d3 = port:PE07<3> +csi_d4 = port:PE08<3> +csi_d5 = port:PE09<3> +csi_d6 = port:PE10<3> +csi_d7 = port:PE11<3> +csi_d8 = +csi_d9 = +csi_d10 = +csi_d11 = +csi_d12 = +csi_d13 = +csi_d14 = +csi_d15 = +csi_reset = port:PH13<1><0> +csi_power_en = +csi_stby = port:PH16<1><0> +csi_flash = +csi_af_en = +csi_reset_b = +csi_power_en_b = +csi_stby_b = +csi_flash_b = +csi_af_en_b = + +[csi1_para] +csi_used = 0 +csi_mode = 0 +csi_dev_qty = 1 +csi_stby_mode = 1 +csi_mname = "" +csi_twi_id = 1 +csi_twi_addr = 0xba +csi_if = 0 +csi_vflip = 0 +csi_hflip = 0 +csi_iovdd = "" +csi_avdd = "" +csi_dvdd = "" +csi_flash_pol = 1 +csi_mname_b = "" +csi_twi_id_b = 1 +csi_twi_addr_b = 0x78 +csi_if_b = 0 +csi_vflip_b = 1 +csi_hflip_b = 0 +csi_iovdd_b = "" +csi_avdd_b = "" +csi_dvdd_b = "" +csi_flash_pol_b = 1 +csi_pck = port:PG00<3> +csi_ck = port:PG01<3> +csi_hsync = port:PG02<3> +csi_vsync = port:PG03<3> +csi_field = +csi_d0 = port:PG04<3> +csi_d1 = port:PG05<3> +csi_d2 = port:PG06<3> +csi_d3 = port:PG07<3> +csi_d4 = port:PG08<3> +csi_d5 = port:PG09<3> +csi_d6 = port:PG10<3> +csi_d7 = port:PG11<3> +csi_d8 = +csi_d9 = +csi_d10 = +csi_d11 = +csi_d12 = +csi_d13 = +csi_d14 = +csi_d15 = +csi_d16 = +csi_d17 = +csi_d18 = +csi_d19 = +csi_d20 = +csi_d21 = +csi_d22 = +csi_d23 = +csi_reset = port:PH14<1><0> +csi_power_en = +csi_stby = port:PH17<1><0> +csi_flash = +csi_af_en = +csi_reset_b = +csi_power_en_b = +csi_stby_b = +csi_flash_b = +csi_af_en_b = + +[tvout_para] +tvout_used = 0 +tvout_channel_num = 1 +tv_en = port:PI12<1><0> + +[tvin_para] +tvin_used = 0 +tvin_channel_num = 4 + +[sata_para] +sata_used = 1 +sata_power_en = port:PC03<1><0> + +[mmc0_para] +sdc_used = 1 +sdc_detmode = 1 +bus_width = 4 +sdc_d1 = port:PF00<2><1><2> +sdc_d0 = port:PF01<2><1><2> +sdc_clk = port:PF02<2><1><2> +sdc_cmd = port:PF03<2><1><2> +sdc_d3 = port:PF04<2><1><2> +sdc_d2 = port:PF05<2><1><2> +sdc_det = port:PH01<0><1> +sdc_use_wp = 0 +sdc_wp = + +[mmc1_para] +sdc_used = 0 +sdc_detmode = 1 +bus_width = 4 +sdc_cmd = port:PH22<5><1><2> +sdc_clk = port:PH23<5><1><2> +sdc_d0 = port:PH24<5><1><2> +sdc_d1 = port:PH25<5><1><2> +sdc_d2 = port:PH26<5><1><2> +sdc_d3 = port:PH27<5><1><2> +sdc_det = port:PH02<0><1> +sdc_use_wp = 0 +sdc_wp = + +[mmc2_para] +sdc_used = 0 + +[mmc3_para] +sdc_used = 0 +sdc_detmode = 4 +bus_width = 4 +sdc_cmd = port:PI04<2><1><2> +sdc_clk = port:PI05<2><1><2> +sdc_d0 = port:PI06<2><1><2> +sdc_d1 = port:PI07<2><1><2> +sdc_d2 = port:PI08<2><1><2> +sdc_d3 = port:PI09<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = + +[ms_para] +ms_used = 0 +ms_bs = port:PH06<5> +ms_clk = port:PH07<5> +ms_d0 = port:PH08<5> +ms_d1 = port:PH09<5> +ms_d2 = port:PH10<5> +ms_d3 = port:PH11<5> +ms_det = + +[smc_para] +smc_used = 0 +smc_rst = port:PH13<5> +smc_vppen = port:PH14<5> +smc_vppp = port:PH15<5> +smc_det = port:PH16<5> +smc_vccen = port:PH17<5> +smc_sck = port:PH18<5> +smc_sda = port:PH19<5> + +[ps2_0_para] +ps2_used = 0 +ps2_scl = port:PI20<2><1> +ps2_sda = port:PI21<2><1> + +[ps2_1_para] +ps2_used = 0 +ps2_scl = port:PI14<3><1> +ps2_sda = port:PI15<3><1> + +[can_para] +can_used = 0 +can_tx = port:PA16<3> +can_rx = port:PA17<3> + +[keypad_para] +kp_used = 0 +kp_in_size = 8 +kp_out_size = 8 +kp_in0 = port:PH08<4><1> +kp_in1 = port:PH09<4><1> +kp_in2 = port:PH10<4><1> +kp_in3 = port:PH11<4><1> +kp_in4 = port:PH14<4><1> +kp_in5 = port:PH15<4><1> +kp_in6 = port:PH16<4><1> +kp_in7 = port:PH17<4><1> +kp_out0 = port:PH18<4><1> +kp_out1 = port:PH19<4><1> +kp_out2 = port:PH22<4><1> +kp_out3 = port:PH23<4><1> +kp_out4 = port:PH24<4><1> +kp_out5 = port:PH25<4><1> +kp_out6 = port:PH26<4><1> +kp_out7 = port:PH27<4><1> + +[usbc0] +usb_used = 1 +usb_port_type = 2 +usb_detect_type = 1 +usb_id_gpio = port:PH04<0><1> +usb_det_vbus_gpio = port:PH05<0><0> +usb_drv_vbus_gpio = port:PB09<1><0><0> +usb_host_init_state = 0 + +[usbc1] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_id_gpio = +usb_det_vbus_gpio = +usb_drv_vbus_gpio = port:PH06<1><0><0> +usb_host_init_state = 1 + +[usbc2] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_id_gpio = +usb_det_vbus_gpio = +usb_drv_vbus_gpio = port:PH03<1><0><0> +usb_host_init_state = 1 + +[usb_feature] +vendor_id = 6353 +mass_storage_id = 1 +adb_id = 2 +manufacturer_name = "USB Developer" +product_name = "Android" +serial_number = "20080411" + +[msc_feature] +vendor_name = "USB 2.0" +product_name = "USB Flash Driver" +release = 100 +luns = 3 + +[gsensor_para] +gsensor_used = 0 +gsensor_name = "bma250" +gsensor_twi_id = 1 +gsensor_twi_addr = 0x18 +gsensor_int1 = port:PH00<6><1> +gsensor_int2 = port:PI10<6><1> + +[gps_para] +gps_used = 0 +gps_spi_id = 2 +gps_spi_cs_num = 0 +gps_lradc = 1 +gps_clk = port:PI00<2> +gps_sign = port:PI01<2> +gps_mag = port:PI02<2> +gps_vcc_en = port:PC22<1><0> +gps_osc_en = port:PI14<1><0> +gps_rx_en = port:PI15<1><0> + +[sdio_wifi_para] +sdio_wifi_used = 0 +sdio_wifi_sdc_id = 3 +sdio_wifi_mod_sel = 1 +swl_n20_shdn = port:PH09<1><0> +swl_n20_host_wakeup = port:PH10<1><1> +swl_n20_vdd_en = port:PH11<1><0> +swl_n20_vcc_en = port:PH12<1><0> + +[usb_wifi_para] +usb_wifi_used = 0 +usb_wifi_usbc_num = 2 + +[3g_para] +3g_used = 0 +3g_usbc_num = 2 +3g_uart_num = 0 +3g_pwr = +3g_wakeup = +3g_int = + +[gy_para] +gy_used = 0 +gy_twi_id = 1 +gy_twi_addr = 0 +gy_int1 = port:PH18<6><1> +gy_int2 = port:PH19<6><1> + +[ls_para] +ls_used = 0 +ls_twi_id = 1 +ls_twi_addr = 0 +ls_int = port:PH20<6><1> + +[compass_para] +compass_used = 0 +compass_twi_id = 1 +compass_twi_addr = 0 +compass_int = port:PI13<6><1> + +[bt_para] +bt_used = 0 +bt_uart_id = 2 +bt_mod_type = 1 + +[i2s_para] +i2s_used = 1 +i2s_channel = 2 +i2s_mclk = port:PB05<2><1> +i2s_bclk = port:PB06<2><1> +i2s_lrclk = port:PB07<2><1> +i2s_dout0 = port:PB08<2><1> +i2s_dout1 = +i2s_dout2 = +i2s_dout3 = +i2s_din = port:PB12<2><1> + +[spdif_para] +spdif_used = 0 +spdif_mclk = +spdif_dout = port:PB13<4><1> +spdif_din = + +[audio_para] +audio_used = 0 +capture_used = 0 +audio_lr_change = 0 +audio_pa_ctrl = port:PH15<1><0> + +[switch_para] +switch_used = 0 + +[ir_para] +ir_used = 0 +ir0_rx = port:PB04<2> + +[pmu_para] +pmu_used = 1 +pmu_twi_addr = 52 +pmu_twi_id = 0 +pmu_irq_id = 0 +pmu_battery_rdc = 100 +pmu_battery_cap = 3200 +pmu_init_chgcur = 300 +pmu_earlysuspend_chgcur = 600 +pmu_suspend_chgcur = 1000 +pmu_resume_chgcur = 300 +pmu_shutdown_chgcur = 1000 +pmu_init_chgvol = 4200 +pmu_init_chgend_rate = 15 +pmu_init_chg_enabled = 1 +pmu_init_adc_freq = 100 +pmu_init_adc_freqc = 100 +pmu_init_chg_pretime = 50 +pmu_init_chg_csttime = 720 +pmu_bat_para1 = 0 +pmu_bat_para2 = 0 +pmu_bat_para3 = 0 +pmu_bat_para4 = 0 +pmu_bat_para5 = 5 +pmu_bat_para6 = 8 +pmu_bat_para7 = 11 +pmu_bat_para8 = 22 +pmu_bat_para9 = 33 +pmu_bat_para10 = 43 +pmu_bat_para11 = 50 +pmu_bat_para12 = 59 +pmu_bat_para13 = 71 +pmu_bat_para14 = 83 +pmu_bat_para15 = 92 +pmu_bat_para16 = 100 +pmu_usbvol_limit = 1 +pmu_usbcur_limit = 0 +pmu_usbvol = 4000 +pmu_usbcur = 0 +pmu_usbvol_pc = 4000 +pmu_usbcur_pc = 0 +pmu_pwroff_vol = 3300 +pmu_pwron_vol = 2900 +pmu_pekoff_time = 6000 +pmu_pekoff_en = 1 +pmu_peklong_time = 1500 +pmu_pekon_time = 1000 +pmu_pwrok_time = 64 +pmu_pwrnoe_time = 2000 +pmu_intotp_en = 1 +pmu_used2 = 0 +pmu_adpdet = port:PH02<0> +pmu_init_chgcur2 = 400 +pmu_earlysuspend_chgcur2 = 600 +pmu_suspend_chgcur2 = 1200 +pmu_resume_chgcur2 = 400 +pmu_shutdown_chgcur2 = 1200 +pmu_suspendpwroff_vol = 3500 +pmu_batdeten = 1 + +[recovery_key] +key_min = 4 +key_max = 6 + +[dvfs_table] +max_freq = 1008000000 +min_freq = 60000000 +LV_count = 5 +LV1_freq = 1056000000 +LV1_volt = 1500 +LV2_freq = 1008000000 +LV2_volt = 1400 +LV3_freq = 912000000 +LV3_volt = 1350 +LV4_freq = 864000000 +LV4_volt = 1300 +LV5_freq = 624000000 +LV5_volt = 1250 + +[leds_para] +leds_used = 1 +leds_num = 1 +leds_pin_1 = port:PH2<1><0> +leds_name_1 = "green:ph2:led1" +leds_default_1 = 1 diff --git a/config/olimex-lime.fex b/config/lime.fex similarity index 99% rename from config/olimex-lime.fex rename to config/lime.fex index bcb2f593c..f315f2aff 100644 --- a/config/olimex-lime.fex +++ b/config/lime.fex @@ -303,7 +303,7 @@ leds_num = 1 leds_pin_1 = port:PH02<1><0> leds_name_1 = "green:ph02:led1" leds_default_1 = 0 -leds_trigger_1 = "heartbeat" +leds_trigger_1 = "mmc0" [nand_para] nand_used = 1 diff --git a/config/olimex-lime2.fex b/config/lime2.fex similarity index 99% rename from config/olimex-lime2.fex rename to config/lime2.fex index 9f7de5b0d..938c0056a 100644 --- a/config/olimex-lime2.fex +++ b/config/lime2.fex @@ -312,7 +312,7 @@ leds_num = 1 leds_pin_1 = port:PH02<1><0> leds_name_1 = "green:ph02:led1" leds_default_1 = 0 -leds_trigger_1 = "heartbeat" +leds_trigger_1 = "mmc0" [nand_para] nand_used = 1 diff --git a/config/linux-cubox-next.config b/config/linux-cubox-next.config index fb5ea1056..90322be21 100644 --- a/config/linux-cubox-next.config +++ b/config/linux-cubox-next.config @@ -1,23 +1,25 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 3.14.14 Kernel Configuration +# Linux/arm 4.1.0-rc5 Kernel Configuration # CONFIG_ARM=y +CONFIG_ARM_HAS_SG_CHAIN=y CONFIG_MIGHT_HAVE_PCI=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y CONFIG_HAVE_PROC_CPU=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y CONFIG_TRACE_IRQFLAGS_SUPPORT=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_ZONE_DMA=y CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_FIQ=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_ARM_PATCH_PHYS_VIRT=y CONFIG_GENERIC_BUG=y +CONFIG_PGTABLE_LEVELS=2 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_IRQ_WORK=y CONFIG_BUILDTIME_EXTABLE_SORT=y @@ -44,27 +46,28 @@ CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y CONFIG_FHANDLE=y -CONFIG_AUDIT=y -CONFIG_AUDITSYSCALL=y -CONFIG_AUDIT_WATCH=y -CONFIG_AUDIT_TREE=y +CONFIG_USELIB=y +# CONFIG_AUDIT is not set +CONFIG_HAVE_ARCH_AUDITSYSCALL=y # # IRQ subsystem # CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y CONFIG_HARDIRQS_SW_RESEND=y CONFIG_GENERIC_IRQ_CHIP=y CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_HANDLE_DOMAIN_IRQ=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set CONFIG_IRQ_FORCED_THREADING=y CONFIG_SPARSE_IRQ=y -CONFIG_KTIME_SCALAR=y CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_ARCH_HAS_TICK_BROADCAST=y CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y @@ -85,18 +88,15 @@ CONFIG_HIGH_RES_TIMERS=y CONFIG_TICK_CPU_ACCOUNTING=y # CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set # CONFIG_IRQ_TIME_ACCOUNTING is not set -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_TASKSTATS=y -CONFIG_TASK_DELAY_ACCT=y -CONFIG_TASK_XACCT=y -CONFIG_TASK_IO_ACCOUNTING=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set # # RCU Subsystem # CONFIG_TREE_RCU=y -# CONFIG_PREEMPT_RCU is not set +CONFIG_SRCU=y +# CONFIG_TASKS_RCU is not set CONFIG_RCU_STALL_COMMON=y # CONFIG_RCU_USER_QS is not set CONFIG_RCU_FANOUT=32 @@ -104,55 +104,48 @@ CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_RCU_FANOUT_EXACT is not set # CONFIG_RCU_FAST_NO_HZ is not set # CONFIG_TREE_RCU_TRACE is not set +CONFIG_RCU_KTHREAD_PRIO=0 # CONFIG_RCU_NOCB_CPU is not set +# CONFIG_RCU_EXPEDITE_BOOT is not set +CONFIG_BUILD_BIN2C=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=18 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 CONFIG_GENERIC_SCHED_CLOCK=y CONFIG_CGROUPS=y # CONFIG_CGROUP_DEBUG is not set -CONFIG_CGROUP_FREEZER=y -CONFIG_CGROUP_DEVICE=y -CONFIG_CPUSETS=y -CONFIG_PROC_PID_CPUSET=y -CONFIG_CGROUP_CPUACCT=y -CONFIG_RESOURCE_COUNTERS=y -CONFIG_MEMCG=y -CONFIG_MEMCG_SWAP=y -CONFIG_MEMCG_SWAP_ENABLED=y -CONFIG_MEMCG_KMEM=y -CONFIG_CGROUP_PERF=y -CONFIG_CGROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_CFS_BANDWIDTH=y -CONFIG_RT_GROUP_SCHED=y -CONFIG_BLK_CGROUP=y -# CONFIG_DEBUG_BLK_CGROUP is not set +# CONFIG_CGROUP_FREEZER is not set +# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CPUSETS is not set +# CONFIG_CGROUP_CPUACCT is not set +# CONFIG_MEMCG is not set +# CONFIG_CGROUP_PERF is not set +# CONFIG_CGROUP_SCHED is not set +# CONFIG_BLK_CGROUP is not set # CONFIG_CHECKPOINT_RESTORE is not set -CONFIG_NAMESPACES=y -CONFIG_UTS_NS=y -CONFIG_IPC_NS=y -CONFIG_USER_NS=y -CONFIG_PID_NS=y -CONFIG_NET_NS=y -CONFIG_SCHED_AUTOGROUP=y -CONFIG_MM_OWNER=y +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set # CONFIG_SYSFS_DEPRECATED is not set CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y -# CONFIG_RD_BZIP2 is not set -# CONFIG_RD_LZMA is not set -# CONFIG_RD_XZ is not set -# CONFIG_RD_LZO is not set -# CONFIG_RD_LZ4 is not set +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_ANON_INODES=y CONFIG_HAVE_UID16=y +CONFIG_BPF=y CONFIG_EXPERT=y CONFIG_UID16=y +CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set +CONFIG_SYSFS_SYSCALL=y # CONFIG_SYSCTL_SYSCALL is not set CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y @@ -165,8 +158,10 @@ CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y +# CONFIG_BPF_SYSCALL is not set CONFIG_SHMEM=y CONFIG_AIO=y +CONFIG_ADVISE_SYSCALLS=y CONFIG_PCI_QUIRKS=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y @@ -185,17 +180,17 @@ CONFIG_SLUB=y # CONFIG_SLOB is not set CONFIG_SLUB_CPU_PARTIAL=y # CONFIG_SYSTEM_TRUSTED_KEYRING is not set -CONFIG_PROFILING=y -CONFIG_OPROFILE=m +# CONFIG_PROFILING is not set CONFIG_HAVE_OPROFILE=y -CONFIG_KPROBES=y +# CONFIG_KPROBES is not set # CONFIG_JUMP_LABEL is not set +# CONFIG_UPROBES is not set # CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_ARCH_USE_BUILTIN_BSWAP=y -CONFIG_KRETPROBES=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_OPTPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_DMA_CONTIGUOUS=y @@ -210,7 +205,6 @@ CONFIG_HAVE_PERF_USER_STACK_DUMP=y CONFIG_HAVE_ARCH_JUMP_LABEL=y CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y CONFIG_HAVE_ARCH_SECCOMP_FILTER=y -CONFIG_SECCOMP_FILTER=y CONFIG_HAVE_CC_STACKPROTECTOR=y # CONFIG_CC_STACKPROTECTOR is not set CONFIG_CC_STACKPROTECTOR_NONE=y @@ -219,8 +213,8 @@ CONFIG_CC_STACKPROTECTOR_NONE=y CONFIG_HAVE_CONTEXT_TRACKING=y CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y -CONFIG_HAVE_MOD_ARCH_SPECIFIC=y CONFIG_MODULES_USE_ELF_REL=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y CONFIG_CLONE_BACKWARDS=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_OLD_SIGACTION=y @@ -228,6 +222,8 @@ CONFIG_OLD_SIGACTION=y # # GCOV-based kernel profiling # +# CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_RT_MUTEXES=y CONFIG_BASE_SMALL=0 @@ -238,39 +234,21 @@ CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_COMPRESS is not set CONFIG_STOP_MACHINE=y CONFIG_BLOCK=y CONFIG_LBDAF=y -CONFIG_BLK_DEV_BSG=y -CONFIG_BLK_DEV_BSGLIB=y -CONFIG_BLK_DEV_INTEGRITY=y -CONFIG_BLK_DEV_THROTTLING=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set # CONFIG_BLK_CMDLINE_PARSER is not set # # Partition Types # -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -CONFIG_AIX_PARTITION=y -CONFIG_OSF_PARTITION=y -CONFIG_AMIGA_PARTITION=y -# CONFIG_ATARI_PARTITION is not set -CONFIG_MAC_PARTITION=y +# CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y -CONFIG_LDM_PARTITION=y -# CONFIG_LDM_DEBUG is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -CONFIG_SUN_PARTITION=y -CONFIG_KARMA_PARTITION=y CONFIG_EFI_PARTITION=y -# CONFIG_SYSV68_PARTITION is not set -# CONFIG_CMDLINE_PARTITION is not set # # IO Schedulers @@ -278,22 +256,14 @@ CONFIG_EFI_PARTITION=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y -CONFIG_CFQ_GROUP_IOSCHED=y -CONFIG_IOSCHED_BFQ=y -CONFIG_CGROUP_BFQIO=y # CONFIG_DEFAULT_DEADLINE is not set -# CONFIG_DEFAULT_CFQ is not set -CONFIG_DEFAULT_BFQ=y +CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="bfq" -CONFIG_PADATA=y -CONFIG_INLINE_SPIN_UNLOCK_IRQ=y -CONFIG_INLINE_READ_UNLOCK=y -CONFIG_INLINE_READ_UNLOCK_IRQ=y -CONFIG_INLINE_WRITE_UNLOCK=y -CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_UNINLINE_SPIN_UNLOCK=y CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y -CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y CONFIG_FREEZER=y # @@ -301,10 +271,8 @@ CONFIG_FREEZER=y # CONFIG_MMU=y CONFIG_ARCH_MULTIPLATFORM=y -# CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_AT91 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_GEMINI is not set # CONFIG_ARCH_EBSA110 is not set @@ -316,7 +284,6 @@ CONFIG_ARCH_MULTIPLATFORM=y # CONFIG_ARCH_IOP33X is not set # CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_DOVE is not set -# CONFIG_ARCH_KIRKWOOD is not set # CONFIG_ARCH_MV78XX0 is not set # CONFIG_ARCH_ORION5X is not set # CONFIG_ARCH_MMP is not set @@ -324,16 +291,11 @@ CONFIG_ARCH_MULTIPLATFORM=y # CONFIG_ARCH_W90X900 is not set # CONFIG_ARCH_LPC32XX is not set # CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_MSM_NODT is not set # CONFIG_ARCH_SHMOBILE_LEGACY is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C24XX is not set # CONFIG_ARCH_S3C64XX is not set -# CONFIG_ARCH_S5P64X0 is not set -# CONFIG_ARCH_S5PC100 is not set -# CONFIG_ARCH_S5PV210 is not set -# CONFIG_ARCH_EXYNOS is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP1 is not set @@ -344,76 +306,146 @@ CONFIG_ARCH_MULTIPLATFORM=y # # CPU Core family selection # -# CONFIG_ARCH_MULTI_V6 is not set +CONFIG_ARCH_MULTI_V6=y CONFIG_ARCH_MULTI_V7=y CONFIG_ARCH_MULTI_V6_V7=y # CONFIG_ARCH_MULTI_CPU_AUTO is not set +# CONFIG_ARCH_VIRT is not set # CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_AT91 is not set # CONFIG_ARCH_BCM is not set # CONFIG_ARCH_BERLIN is not set -CONFIG_GPIO_PCA953X=y -# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_DIGICOLOR is not set # CONFIG_ARCH_HIGHBANK is not set -# CONFIG_ARCH_HI3xxx is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_KEYSTONE is not set -# CONFIG_ARCH_MSM_DT is not set +# CONFIG_ARCH_MESON is not set CONFIG_ARCH_MXC=y - -# -# Freescale i.MX support -# +CONFIG_MXC_TZIC=y +CONFIG_MXC_AVIC=y CONFIG_MXC_DEBUG_BOARD=y +CONFIG_HAVE_EPIT=y +# CONFIG_MXC_USE_EPIT is not set +CONFIG_ARCH_HAS_RNGA=y CONFIG_HAVE_IMX_ANATOP=y CONFIG_HAVE_IMX_GPC=y CONFIG_HAVE_IMX_MMDC=y CONFIG_HAVE_IMX_SRC=y +CONFIG_ARCH_MXC_IOMUX_V3=y +CONFIG_SOC_IMX31=y +CONFIG_SOC_IMX35=y # -# i.MX51 machines: +# MX31 platforms: # -# CONFIG_MACH_IMX51_DT is not set -# CONFIG_MACH_MX51_BABBAGE is not set -# CONFIG_MACH_EUKREA_CPUIMX51SD is not set +CONFIG_MACH_MX31ADS=y +CONFIG_MACH_MX31LILLY=y +CONFIG_MACH_MX31LITE=y +CONFIG_MACH_PCM037=y +CONFIG_MACH_PCM037_EET=y +CONFIG_MACH_MX31_3DS=y +# CONFIG_MACH_MX31_3DS_MXC_NAND_USE_BBT is not set +CONFIG_MACH_MX31MOBOARD=y +CONFIG_MACH_QONG=y +CONFIG_MACH_ARMADILLO5X0=y +CONFIG_MACH_KZM_ARM11_01=y +CONFIG_MACH_BUG=y +CONFIG_MACH_IMX31_DT=y + +# +# MX35 platforms: +# +CONFIG_MACH_IMX35_DT=y +CONFIG_MACH_PCM043=y +CONFIG_MACH_MX35_3DS=y +# CONFIG_MACH_EUKREA_CPUIMX35SD is not set +CONFIG_MACH_VPR200=y # # Device tree only # -# CONFIG_SOC_IMX50 is not set -# CONFIG_SOC_IMX53 is not set +CONFIG_SOC_IMX5=y +CONFIG_SOC_IMX50=y +CONFIG_SOC_IMX51=y +CONFIG_SOC_IMX53=y +CONFIG_SOC_IMX6=y CONFIG_SOC_IMX6Q=y CONFIG_SOC_IMX6SL=y -# CONFIG_SOC_VF610 is not set +CONFIG_SOC_IMX6SX=y +CONFIG_SOC_VF610=y +CONFIG_VF_USE_ARM_GLOBAL_TIMER=y +# CONFIG_VF_USE_PIT_TIMER is not set +# CONFIG_SOC_LS1021A is not set +CONFIG_IMX_HAVE_PLATFORM_FEC=y +CONFIG_IMX_HAVE_PLATFORM_FLEXCAN=y +CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC=y +CONFIG_IMX_HAVE_PLATFORM_GPIO_KEYS=y +CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT=y +CONFIG_IMX_HAVE_PLATFORM_IMX_FB=y +CONFIG_IMX_HAVE_PLATFORM_IMX_I2C=y +CONFIG_IMX_HAVE_PLATFORM_IMX_KEYPAD=y +CONFIG_IMX_HAVE_PLATFORM_IMX_SSI=y +CONFIG_IMX_HAVE_PLATFORM_IMX_UART=y +CONFIG_IMX_HAVE_PLATFORM_IPU_CORE=y +CONFIG_IMX_HAVE_PLATFORM_MXC_EHCI=y +CONFIG_IMX_HAVE_PLATFORM_MXC_MMC=y +CONFIG_IMX_HAVE_PLATFORM_MXC_NAND=y +CONFIG_IMX_HAVE_PLATFORM_MXC_RNGA=y +CONFIG_IMX_HAVE_PLATFORM_MXC_RTC=y +CONFIG_IMX_HAVE_PLATFORM_MXC_W1=y +CONFIG_IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX=y +CONFIG_IMX_HAVE_PLATFORM_SPI_IMX=y +# CONFIG_ARCH_MEDIATEK is not set + +# +# TI OMAP/AM/DM/DRA Family +# +# CONFIG_ARCH_OMAP2 is not set # CONFIG_ARCH_OMAP3 is not set # CONFIG_ARCH_OMAP4 is not set # CONFIG_SOC_OMAP5 is not set # CONFIG_SOC_AM33XX is not set # CONFIG_SOC_AM43XX is not set # CONFIG_SOC_DRA7XX is not set +# CONFIG_ARCH_PICOXCELL is not set +# CONFIG_ARCH_QCOM is not set # CONFIG_ARCH_ROCKCHIP is not set # CONFIG_ARCH_SOCFPGA is not set # CONFIG_PLAT_SPEAR is not set # CONFIG_ARCH_STI is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set # CONFIG_ARCH_SHMOBILE_MULTI is not set # CONFIG_ARCH_SUNXI is not set # CONFIG_ARCH_SIRF is not set # CONFIG_ARCH_TEGRA is not set # CONFIG_ARCH_U8500 is not set # CONFIG_ARCH_VEXPRESS is not set -# CONFIG_ARCH_VIRT is not set +# CONFIG_ARCH_WM8750 is not set # CONFIG_ARCH_WM8850 is not set # CONFIG_ARCH_ZYNQ is not set # # Processor Type # +CONFIG_CPU_V6=y +CONFIG_CPU_V6K=y CONFIG_CPU_V7=y +CONFIG_CPU_32v6=y CONFIG_CPU_32v6K=y CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV6=y CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V6=y CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V6=y CONFIG_CPU_CACHE_V7=y CONFIG_CPU_CACHE_VIPT=y CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V6=y CONFIG_CPU_TLB_V7=y CONFIG_CPU_HAS_ASID=y CONFIG_CPU_CP15=y @@ -422,91 +454,76 @@ CONFIG_CPU_CP15_MMU=y # # Processor Features # -# CONFIG_ARM_LPAE is not set # CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set CONFIG_ARM_THUMB=y # CONFIG_ARM_THUMBEE is not set CONFIG_ARM_VIRT_EXT=y -# CONFIG_SWP_EMULATE is not set +CONFIG_SWP_EMULATE=y # CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_BPREDICT_DISABLE is not set CONFIG_KUSER_HELPERS=y +# CONFIG_VDSO is not set +CONFIG_DMA_CACHE_RWFO=y CONFIG_OUTER_CACHE=y CONFIG_OUTER_CACHE_SYNC=y CONFIG_MIGHT_HAVE_CACHE_L2X0=y CONFIG_CACHE_L2X0=y -CONFIG_CACHE_PL310=y -CONFIG_PL310_ERRATA_588369=y -CONFIG_PL310_ERRATA_727915=y +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_PL310_ERRATA_727915 is not set # CONFIG_PL310_ERRATA_753970 is not set CONFIG_PL310_ERRATA_769419=y CONFIG_ARM_L1_CACHE_SHIFT_6=y CONFIG_ARM_L1_CACHE_SHIFT=6 CONFIG_ARM_DMA_MEM_BUFFERABLE=y -CONFIG_ARM_NR_BANKS=8 +# CONFIG_ARM_KERNMEM_PERMS is not set CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_326103 is not set +# CONFIG_ARM_ERRATA_411920 is not set # CONFIG_ARM_ERRATA_430973 is not set -# CONFIG_ARM_ERRATA_643719 is not set +CONFIG_ARM_ERRATA_643719=y # CONFIG_ARM_ERRATA_720789 is not set CONFIG_ARM_ERRATA_754322=y # CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_364296 is not set CONFIG_ARM_ERRATA_764369=y CONFIG_ARM_ERRATA_775420=y # CONFIG_ARM_ERRATA_798181 is not set # CONFIG_ARM_ERRATA_773022 is not set -CONFIG_ARM_ERRATA_794072=y -CONFIG_ARM_ERRATA_761320=y # # Bus support # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y CONFIG_PCI_SYSCALL=y # CONFIG_PCI_MSI is not set # CONFIG_PCI_DEBUG is not set # CONFIG_PCI_REALLOC_ENABLE_AUTO is not set -CONFIG_PCI_STUB=y -CONFIG_PCI_ATS=y -CONFIG_PCI_IOV=y -CONFIG_PCI_PRI=y -CONFIG_PCI_PASID=y +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_PRI is not set +# CONFIG_PCI_PASID is not set # # PCI host controller drivers # CONFIG_PCIE_DW=y CONFIG_PCI_IMX6=y -# CONFIG_EP_MODE_IN_EP_RC_SYS is not set -# CONFIG_RC_MODE_IN_EP_RC_SYS is not set +# CONFIG_PCI_HOST_GENERIC is not set +# CONFIG_PCI_LAYERSCAPE is not set +# CONFIG_PCIE_IPROC is not set CONFIG_PCIEPORTBUS=y CONFIG_PCIEAER=y -CONFIG_PCIE_ECRC=y -CONFIG_PCIEAER_INJECT=m +# CONFIG_PCIE_ECRC is not set +# CONFIG_PCIEAER_INJECT is not set CONFIG_PCIEASPM=y # CONFIG_PCIEASPM_DEBUG is not set CONFIG_PCIEASPM_DEFAULT=y # CONFIG_PCIEASPM_POWERSAVE is not set # CONFIG_PCIEASPM_PERFORMANCE is not set CONFIG_PCIE_PME=y -CONFIG_PCCARD=y -CONFIG_PCMCIA=y -CONFIG_PCMCIA_LOAD_CIS=y -CONFIG_CARDBUS=y - -# -# PC-card bridges -# -CONFIG_YENTA=m -CONFIG_YENTA_O2=y -CONFIG_YENTA_RICOH=y -CONFIG_YENTA_TI=y -CONFIG_YENTA_ENE_TUNE=y -CONFIG_YENTA_TOSHIBA=y -CONFIG_PD6729=m -CONFIG_I82092=m -CONFIG_PCCARD_NONSTATIC=y +# CONFIG_PCCARD is not set # # Kernel Features @@ -523,9 +540,9 @@ CONFIG_HAVE_ARM_TWD=y # CONFIG_MCPM is not set # CONFIG_BIG_LITTLE is not set CONFIG_VMSPLIT_3G=y -CONFIG_VMSPLIT_2G=y +# CONFIG_VMSPLIT_2G is not set # CONFIG_VMSPLIT_1G is not set -CONFIG_PAGE_OFFSET=0x80000000 +CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_NR_CPUS=4 CONFIG_HOTPLUG_CPU=y # CONFIG_ARM_PSCI is not set @@ -534,15 +551,14 @@ CONFIG_ARCH_NR_GPIO=0 CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set CONFIG_HZ_FIXED=0 -# CONFIG_HZ_100 is not set +CONFIG_HZ_100=y # CONFIG_HZ_200 is not set # CONFIG_HZ_250 is not set # CONFIG_HZ_300 is not set # CONFIG_HZ_500 is not set -CONFIG_HZ_1000=y -CONFIG_HZ=1000 +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 CONFIG_SCHED_HRTICK=y -# CONFIG_THUMB2_KERNEL is not set CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set @@ -560,31 +576,28 @@ CONFIG_MEMORY_ISOLATION=y # CONFIG_HAVE_BOOTMEM_INFO_NODE is not set CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_BALLOON_COMPACTION=y CONFIG_COMPACTION=y CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set -CONFIG_ZONE_DMA_FLAG=1 +CONFIG_ZONE_DMA_FLAG=0 CONFIG_BOUNCE=y -CONFIG_KSM=y +# CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 -CONFIG_CROSS_MEMORY_ATTACH=y -CONFIG_CLEANCACHE=y -CONFIG_FRONTSWAP=y +# CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set CONFIG_CMA=y # CONFIG_CMA_DEBUG is not set +# CONFIG_CMA_DEBUGFS is not set CONFIG_CMA_AREAS=7 -CONFIG_ZBUD=y -CONFIG_ZSWAP=y -CONFIG_ZSMALLOC=y -# CONFIG_PGTABLE_MAPPING is not set -CONFIG_FORCE_MAX_ZONEORDER=14 +# CONFIG_ZPOOL is not set +# CONFIG_ZBUD is not set +# CONFIG_ZSMALLOC is not set +CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_ALIGNMENT_TRAP=y # CONFIG_UACCESS_WITH_MEMCPY is not set -CONFIG_SECCOMP=y +# CONFIG_SECCOMP is not set CONFIG_SWIOTLB=y CONFIG_IOMMU_HELPER=y -# CONFIG_XEN is not set # # Boot options @@ -599,8 +612,7 @@ CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" CONFIG_CMDLINE_FROM_BOOTLOADER=y # CONFIG_CMDLINE_EXTEND is not set # CONFIG_CMDLINE_FORCE is not set -CONFIG_KEXEC=y -CONFIG_ATAGS_PROC=y +# CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set CONFIG_AUTO_ZRELADDR=y @@ -613,38 +625,31 @@ CONFIG_AUTO_ZRELADDR=y # CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_GOV_COMMON=y -CONFIG_CPU_FREQ_STAT=m -CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set CONFIG_CPU_FREQ_GOV_PERFORMANCE=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_INTERACTIVE=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set # -# ARM CPU frequency scaling drivers +# CPU frequency scaling drivers # -CONFIG_ARM_IMX6_CPUFREQ=y +# CONFIG_CPUFREQ_DT is not set +CONFIG_ARM_IMX6Q_CPUFREQ=y # CONFIG_ARM_KIRKWOOD_CPUFREQ is not set +# CONFIG_QORIQ_CPUFREQ is not set # # CPU Idle # -CONFIG_CPU_IDLE=y -# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set -CONFIG_CPU_IDLE_GOV_LADDER=y -CONFIG_CPU_IDLE_GOV_MENU=y - -# -# ARM CPU Idle Drivers -# +# CONFIG_CPU_IDLE is not set # CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set # @@ -657,13 +662,12 @@ CONFIG_CPU_IDLE_GOV_MENU=y CONFIG_VFP=y CONFIG_VFPv3=y CONFIG_NEON=y -CONFIG_KERNEL_MODE_NEON=y +# CONFIG_KERNEL_MODE_NEON is not set # # Userspace binary formats # CONFIG_BINFMT_ELF=y -CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y CONFIG_BINFMT_SCRIPT=y # CONFIG_HAVE_AOUT is not set @@ -675,581 +679,164 @@ CONFIG_COREDUMP=y # CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y +# CONFIG_HIBERNATION is not set CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y # CONFIG_PM_AUTOSLEEP is not set # CONFIG_PM_WAKELOCKS is not set -CONFIG_PM_RUNTIME=y CONFIG_PM=y CONFIG_PM_DEBUG=y # CONFIG_PM_ADVANCED_DEBUG is not set CONFIG_PM_TEST_SUSPEND=y CONFIG_PM_SLEEP_DEBUG=y -# CONFIG_DPM_WATCHDOG is not set # CONFIG_APM_EMULATION is not set -CONFIG_ARCH_HAS_OPP=y CONFIG_PM_OPP=y CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y # CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +CONFIG_PM_GENERIC_DOMAINS_OF=y CONFIG_CPU_PM=y CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ARM_CPU_SUSPEND=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_NET=y # # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_DIAG=m +# CONFIG_PACKET_DIAG is not set CONFIG_UNIX=y -CONFIG_UNIX_DIAG=m +# CONFIG_UNIX_DIAG is not set CONFIG_XFRM=y -CONFIG_XFRM_ALGO=y -CONFIG_XFRM_USER=y -CONFIG_XFRM_SUB_POLICY=y -CONFIG_XFRM_MIGRATE=y -CONFIG_XFRM_STATISTICS=y -CONFIG_XFRM_IPCOMP=m -CONFIG_NET_KEY=m -CONFIG_NET_KEY_MIGRATE=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_FIB_TRIE_STATS=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_ROUTE_CLASSID=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y # CONFIG_IP_PNP_BOOTP is not set # CONFIG_IP_PNP_RARP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE_DEMUX=m -CONFIG_NET_IP_TUNNEL=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -CONFIG_IP_MROUTE=y -CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -CONFIG_IP_PIMSM_V1=y -CONFIG_IP_PIMSM_V2=y -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m -CONFIG_INET_XFRM_TUNNEL=m -CONFIG_INET_TUNNEL=m +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=y +# CONFIG_SYN_COOKIES is not set +# CONFIG_NET_UDP_TUNNEL is not set +# CONFIG_NET_FOU is not set +# CONFIG_NET_FOU_IP_TUNNELS is not set +# CONFIG_GENEVE is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y # CONFIG_INET_XFRM_MODE_TRANSPORT is not set # CONFIG_INET_XFRM_MODE_TUNNEL is not set # CONFIG_INET_XFRM_MODE_BEET is not set -CONFIG_INET_LRO=m -CONFIG_INET_DIAG=m -CONFIG_INET_TCP_DIAG=m -CONFIG_INET_UDP_DIAG=m -CONFIG_TCP_CONG_ADVANCED=y -CONFIG_TCP_CONG_BIC=m +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y -CONFIG_TCP_CONG_WESTWOOD=m -CONFIG_TCP_CONG_HTCP=m -CONFIG_TCP_CONG_HSTCP=m -CONFIG_TCP_CONG_HYBLA=m -CONFIG_TCP_CONG_VEGAS=m -CONFIG_TCP_CONG_SCALABLE=m -CONFIG_TCP_CONG_LP=m -CONFIG_TCP_CONG_VENO=m -CONFIG_TCP_CONG_YEAH=m -CONFIG_TCP_CONG_ILLINOIS=m -CONFIG_DEFAULT_CUBIC=y -# CONFIG_DEFAULT_RENO is not set CONFIG_DEFAULT_TCP_CONG="cubic" -CONFIG_TCP_MD5SIG=y +# CONFIG_TCP_MD5SIG is not set CONFIG_IPV6=y -CONFIG_IPV6_ROUTER_PREF=y -CONFIG_IPV6_ROUTE_INFO=y -CONFIG_IPV6_OPTIMISTIC_DAD=y -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_MIP6=y -CONFIG_INET6_XFRM_TUNNEL=m -CONFIG_INET6_TUNNEL=m -CONFIG_INET6_XFRM_MODE_TRANSPORT=m -CONFIG_INET6_XFRM_MODE_TUNNEL=m -CONFIG_INET6_XFRM_MODE_BEET=m -CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m -CONFIG_IPV6_VTI=m -CONFIG_IPV6_SIT=m -CONFIG_IPV6_SIT_6RD=y +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set CONFIG_IPV6_NDISC_NODETYPE=y -CONFIG_IPV6_TUNNEL=m +# CONFIG_IPV6_TUNNEL is not set # CONFIG_IPV6_GRE is not set -CONFIG_IPV6_MULTIPLE_TABLES=y -CONFIG_IPV6_SUBTREES=y -CONFIG_IPV6_MROUTE=y -CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -CONFIG_IPV6_PIMSM_V2=y -CONFIG_NETLABEL=y -CONFIG_NETWORK_SECMARK=y -CONFIG_NETWORK_PHY_TIMESTAMPING=y +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NET_PTP_CLASSIFY=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set CONFIG_NETFILTER_ADVANCED=y -CONFIG_BRIDGE_NETFILTER=y # # Core Netfilter Configuration # -CONFIG_NETFILTER_NETLINK=m -CONFIG_NETFILTER_NETLINK_ACCT=m -CONFIG_NETFILTER_NETLINK_QUEUE=m -CONFIG_NETFILTER_NETLINK_LOG=m -CONFIG_NF_CONNTRACK=m -CONFIG_NF_CONNTRACK_MARK=y -CONFIG_NF_CONNTRACK_SECMARK=y -CONFIG_NF_CONNTRACK_ZONES=y -CONFIG_NF_CONNTRACK_PROCFS=y -CONFIG_NF_CONNTRACK_EVENTS=y -# CONFIG_NF_CONNTRACK_TIMEOUT is not set -CONFIG_NF_CONNTRACK_TIMESTAMP=y -CONFIG_NF_CONNTRACK_LABELS=y -CONFIG_NF_CT_PROTO_DCCP=m -CONFIG_NF_CT_PROTO_GRE=m -CONFIG_NF_CT_PROTO_SCTP=m -CONFIG_NF_CT_PROTO_UDPLITE=m -CONFIG_NF_CONNTRACK_AMANDA=m -CONFIG_NF_CONNTRACK_FTP=m -CONFIG_NF_CONNTRACK_H323=m -CONFIG_NF_CONNTRACK_IRC=m -CONFIG_NF_CONNTRACK_BROADCAST=m -CONFIG_NF_CONNTRACK_NETBIOS_NS=m -CONFIG_NF_CONNTRACK_SNMP=m -CONFIG_NF_CONNTRACK_PPTP=m -CONFIG_NF_CONNTRACK_SANE=m -CONFIG_NF_CONNTRACK_SIP=m -CONFIG_NF_CONNTRACK_TFTP=m -CONFIG_NF_CT_NETLINK=m -# CONFIG_NF_CT_NETLINK_TIMEOUT is not set -CONFIG_NF_CT_NETLINK_HELPER=m -CONFIG_NETFILTER_NETLINK_QUEUE_CT=y -CONFIG_NF_NAT=m -CONFIG_NF_NAT_NEEDED=y -CONFIG_NF_NAT_PROTO_DCCP=m -CONFIG_NF_NAT_PROTO_UDPLITE=m -CONFIG_NF_NAT_PROTO_SCTP=m -CONFIG_NF_NAT_AMANDA=m -CONFIG_NF_NAT_FTP=m -CONFIG_NF_NAT_IRC=m -CONFIG_NF_NAT_SIP=m -CONFIG_NF_NAT_TFTP=m -CONFIG_NETFILTER_SYNPROXY=m -CONFIG_NF_TABLES=m -CONFIG_NF_TABLES_INET=m -CONFIG_NFT_EXTHDR=m -CONFIG_NFT_META=m -CONFIG_NFT_CT=m -CONFIG_NFT_RBTREE=m -CONFIG_NFT_HASH=m -CONFIG_NFT_COUNTER=m -CONFIG_NFT_LOG=m -CONFIG_NFT_LIMIT=m -CONFIG_NFT_NAT=m -CONFIG_NFT_QUEUE=m -CONFIG_NFT_REJECT=m -CONFIG_NFT_REJECT_INET=m -CONFIG_NFT_COMPAT=m -CONFIG_NETFILTER_XTABLES=y - -# -# Xtables combined modules -# -CONFIG_NETFILTER_XT_MARK=m -CONFIG_NETFILTER_XT_CONNMARK=m -CONFIG_NETFILTER_XT_SET=m - -# -# Xtables targets -# -CONFIG_NETFILTER_XT_TARGET_AUDIT=m -CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -CONFIG_NETFILTER_XT_TARGET_CONNMARK=m -CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m -CONFIG_NETFILTER_XT_TARGET_CT=m -CONFIG_NETFILTER_XT_TARGET_DSCP=m -CONFIG_NETFILTER_XT_TARGET_HL=m -CONFIG_NETFILTER_XT_TARGET_HMARK=m -CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -CONFIG_NETFILTER_XT_TARGET_LED=m -CONFIG_NETFILTER_XT_TARGET_LOG=m -CONFIG_NETFILTER_XT_TARGET_MARK=m -CONFIG_NETFILTER_XT_TARGET_NETMAP=m -CONFIG_NETFILTER_XT_TARGET_NFLOG=m -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -CONFIG_NETFILTER_XT_TARGET_RATEEST=m -CONFIG_NETFILTER_XT_TARGET_REDIRECT=m -CONFIG_NETFILTER_XT_TARGET_TEE=m -CONFIG_NETFILTER_XT_TARGET_TPROXY=m -CONFIG_NETFILTER_XT_TARGET_TRACE=m -CONFIG_NETFILTER_XT_TARGET_SECMARK=m -CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m - -# -# Xtables matches -# -CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -CONFIG_NETFILTER_XT_MATCH_BPF=m -CONFIG_NETFILTER_XT_MATCH_CGROUP=m -CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -CONFIG_NETFILTER_XT_MATCH_COMMENT=m -CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m -CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -CONFIG_NETFILTER_XT_MATCH_CPU=m -CONFIG_NETFILTER_XT_MATCH_DCCP=m -CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m -CONFIG_NETFILTER_XT_MATCH_DSCP=m -CONFIG_NETFILTER_XT_MATCH_ECN=m -CONFIG_NETFILTER_XT_MATCH_ESP=m -CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -CONFIG_NETFILTER_XT_MATCH_HELPER=m -CONFIG_NETFILTER_XT_MATCH_HL=m -CONFIG_NETFILTER_XT_MATCH_IPCOMP=m -CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -CONFIG_NETFILTER_XT_MATCH_IPVS=m -CONFIG_NETFILTER_XT_MATCH_L2TP=m -CONFIG_NETFILTER_XT_MATCH_LENGTH=m -CONFIG_NETFILTER_XT_MATCH_LIMIT=m -CONFIG_NETFILTER_XT_MATCH_MAC=m -CONFIG_NETFILTER_XT_MATCH_MARK=m -CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -CONFIG_NETFILTER_XT_MATCH_NFACCT=m -CONFIG_NETFILTER_XT_MATCH_OSF=m -CONFIG_NETFILTER_XT_MATCH_OWNER=m -CONFIG_NETFILTER_XT_MATCH_POLICY=m -CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -CONFIG_NETFILTER_XT_MATCH_QUOTA=m -CONFIG_NETFILTER_XT_MATCH_RATEEST=m -CONFIG_NETFILTER_XT_MATCH_REALM=m -CONFIG_NETFILTER_XT_MATCH_RECENT=m -CONFIG_NETFILTER_XT_MATCH_SCTP=m -CONFIG_NETFILTER_XT_MATCH_SOCKET=m -CONFIG_NETFILTER_XT_MATCH_STATE=m -CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -CONFIG_NETFILTER_XT_MATCH_STRING=m -CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -CONFIG_NETFILTER_XT_MATCH_TIME=m -CONFIG_NETFILTER_XT_MATCH_U32=m -CONFIG_IP_SET=m -CONFIG_IP_SET_MAX=256 -CONFIG_IP_SET_BITMAP_IP=m -CONFIG_IP_SET_BITMAP_IPMAC=m -CONFIG_IP_SET_BITMAP_PORT=m -CONFIG_IP_SET_HASH_IP=m -CONFIG_IP_SET_HASH_IPPORT=m -CONFIG_IP_SET_HASH_IPPORTIP=m -CONFIG_IP_SET_HASH_IPPORTNET=m -CONFIG_IP_SET_HASH_NETPORTNET=m -CONFIG_IP_SET_HASH_NET=m -CONFIG_IP_SET_HASH_NETNET=m -CONFIG_IP_SET_HASH_NETPORT=m -CONFIG_IP_SET_HASH_NETIFACE=m -CONFIG_IP_SET_LIST_SET=m -CONFIG_IP_VS=m -CONFIG_IP_VS_IPV6=y -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=12 - -# -# IPVS transport protocol load balancing support -# -CONFIG_IP_VS_PROTO_TCP=y -CONFIG_IP_VS_PROTO_UDP=y -CONFIG_IP_VS_PROTO_AH_ESP=y -CONFIG_IP_VS_PROTO_ESP=y -CONFIG_IP_VS_PROTO_AH=y -CONFIG_IP_VS_PROTO_SCTP=y - -# -# IPVS scheduler -# -CONFIG_IP_VS_RR=m -CONFIG_IP_VS_WRR=m -CONFIG_IP_VS_LC=m -CONFIG_IP_VS_WLC=m -CONFIG_IP_VS_LBLC=m -CONFIG_IP_VS_LBLCR=m -CONFIG_IP_VS_DH=m -CONFIG_IP_VS_SH=m -CONFIG_IP_VS_SED=m -CONFIG_IP_VS_NQ=m - -# -# IPVS SH scheduler -# -CONFIG_IP_VS_SH_TAB_BITS=8 - -# -# IPVS application helper -# -CONFIG_IP_VS_FTP=m -CONFIG_IP_VS_NFCT=y -CONFIG_IP_VS_PE_SIP=m +# CONFIG_NETFILTER_NETLINK_ACCT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NF_TABLES is not set +# CONFIG_NETFILTER_XTABLES is not set +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set # # IP: Netfilter Configuration # -CONFIG_NF_DEFRAG_IPV4=m -CONFIG_NF_CONNTRACK_IPV4=m -# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set -CONFIG_NF_TABLES_IPV4=m -CONFIG_NFT_CHAIN_ROUTE_IPV4=m -CONFIG_NFT_CHAIN_NAT_IPV4=m -CONFIG_NFT_REJECT_IPV4=m -CONFIG_NF_TABLES_ARP=m -CONFIG_IP_NF_IPTABLES=y -CONFIG_IP_NF_MATCH_AH=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_RPFILTER=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_FILTER=y -CONFIG_IP_NF_TARGET_REJECT=y -CONFIG_IP_NF_TARGET_SYNPROXY=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_NF_NAT_IPV4=m -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_NF_NAT_SNMP_BASIC=m -CONFIG_NF_NAT_PROTO_GRE=m -CONFIG_NF_NAT_PPTP=m -CONFIG_NF_NAT_H323=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_CLUSTERIP=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_TTL=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_SECURITY=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m +# CONFIG_NF_DEFRAG_IPV4 is not set +# CONFIG_NF_LOG_ARP is not set +# CONFIG_NF_LOG_IPV4 is not set +# CONFIG_NF_REJECT_IPV4 is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set # # IPv6: Netfilter Configuration # -CONFIG_NF_DEFRAG_IPV6=m -CONFIG_NF_CONNTRACK_IPV6=m -CONFIG_NF_TABLES_IPV6=m -CONFIG_NFT_CHAIN_ROUTE_IPV6=m -CONFIG_NFT_CHAIN_NAT_IPV6=m -CONFIG_NFT_REJECT_IPV6=m -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_AH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_MH=m -CONFIG_IP6_NF_MATCH_RPFILTER=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_TARGET_HL=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_REJECT=m -CONFIG_IP6_NF_TARGET_SYNPROXY=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_RAW=m -CONFIG_IP6_NF_SECURITY=m -CONFIG_NF_NAT_IPV6=m -CONFIG_IP6_NF_TARGET_MASQUERADE=m -# CONFIG_IP6_NF_TARGET_NPT is not set -CONFIG_NF_TABLES_BRIDGE=m -CONFIG_BRIDGE_NF_EBTABLES=m -CONFIG_BRIDGE_EBT_BROUTE=m -CONFIG_BRIDGE_EBT_T_FILTER=m -CONFIG_BRIDGE_EBT_T_NAT=m -CONFIG_BRIDGE_EBT_802_3=m -CONFIG_BRIDGE_EBT_AMONG=m -CONFIG_BRIDGE_EBT_ARP=m -CONFIG_BRIDGE_EBT_IP=m -CONFIG_BRIDGE_EBT_IP6=m -CONFIG_BRIDGE_EBT_LIMIT=m -CONFIG_BRIDGE_EBT_MARK=m -CONFIG_BRIDGE_EBT_PKTTYPE=m -CONFIG_BRIDGE_EBT_STP=m -CONFIG_BRIDGE_EBT_VLAN=m -CONFIG_BRIDGE_EBT_ARPREPLY=m -CONFIG_BRIDGE_EBT_DNAT=m -CONFIG_BRIDGE_EBT_MARK_T=m -CONFIG_BRIDGE_EBT_REDIRECT=m -CONFIG_BRIDGE_EBT_SNAT=m -CONFIG_BRIDGE_EBT_LOG=m -CONFIG_BRIDGE_EBT_ULOG=m -CONFIG_BRIDGE_EBT_NFLOG=m -CONFIG_IP_DCCP=m -CONFIG_INET_DCCP_DIAG=m - -# -# DCCP CCIDs Configuration -# -# CONFIG_IP_DCCP_CCID2_DEBUG is not set -CONFIG_IP_DCCP_CCID3=y -# CONFIG_IP_DCCP_CCID3_DEBUG is not set -CONFIG_IP_DCCP_TFRC_LIB=y - -# -# DCCP Kernel Hacking -# -# CONFIG_IP_DCCP_DEBUG is not set -# CONFIG_NET_DCCPPROBE is not set -CONFIG_IP_SCTP=m -CONFIG_NET_SCTPPROBE=m -# CONFIG_SCTP_DBG_OBJCNT is not set -# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5 is not set -CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1=y -# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set -CONFIG_SCTP_COOKIE_HMAC_MD5=y -CONFIG_SCTP_COOKIE_HMAC_SHA1=y -CONFIG_RDS=m -CONFIG_RDS_RDMA=m -CONFIG_RDS_TCP=m -# CONFIG_RDS_DEBUG is not set -CONFIG_TIPC=m -CONFIG_TIPC_PORTS=8192 -# CONFIG_TIPC_MEDIA_IB is not set -CONFIG_ATM=m -CONFIG_ATM_CLIP=m -# CONFIG_ATM_CLIP_NO_ICMP is not set -CONFIG_ATM_LANE=m -# CONFIG_ATM_MPOA is not set -CONFIG_ATM_BR2684=m -# CONFIG_ATM_BR2684_IPFILTER is not set -CONFIG_L2TP=m -CONFIG_L2TP_V3=y -CONFIG_L2TP_IP=m -CONFIG_L2TP_ETH=m -CONFIG_STP=y -CONFIG_GARP=y -CONFIG_MRP=y -CONFIG_BRIDGE=y -CONFIG_BRIDGE_IGMP_SNOOPING=y -CONFIG_BRIDGE_VLAN_FILTERING=y +# CONFIG_NF_DEFRAG_IPV6 is not set +# CONFIG_NF_REJECT_IPV6 is not set +# CONFIG_NF_LOG_IPV6 is not set +# CONFIG_IP6_NF_IPTABLES is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +# CONFIG_BRIDGE is not set CONFIG_HAVE_NET_DSA=y -CONFIG_NET_DSA=m -CONFIG_NET_DSA_TAG_DSA=y -CONFIG_NET_DSA_TAG_EDSA=y -CONFIG_NET_DSA_TAG_TRAILER=y -CONFIG_VLAN_8021Q=y -CONFIG_VLAN_8021Q_GVRP=y -CONFIG_VLAN_8021Q_MVRP=y +# CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set -CONFIG_LLC=y # CONFIG_LLC2 is not set -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m -CONFIG_DEV_APPLETALK=m -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y +# CONFIG_IPX is not set +# CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_PHONET is not set -CONFIG_IEEE802154=m -CONFIG_IEEE802154_6LOWPAN=m -CONFIG_6LOWPAN_IPHC=m -CONFIG_MAC802154=m -CONFIG_NET_SCHED=y - -# -# Queueing/Scheduling -# -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_HFSC=m -CONFIG_NET_SCH_ATM=m -CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_MULTIQ=m -CONFIG_NET_SCH_RED=m -CONFIG_NET_SCH_SFB=m -CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_TEQL=m -CONFIG_NET_SCH_TBF=m -CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DSMARK=m -CONFIG_NET_SCH_NETEM=m -CONFIG_NET_SCH_DRR=m -CONFIG_NET_SCH_MQPRIO=m -CONFIG_NET_SCH_CHOKE=m -CONFIG_NET_SCH_QFQ=m -CONFIG_NET_SCH_CODEL=m -CONFIG_NET_SCH_FQ_CODEL=m -CONFIG_NET_SCH_FQ=m -CONFIG_NET_SCH_HHF=m -CONFIG_NET_SCH_PIE=m -CONFIG_NET_SCH_INGRESS=m -CONFIG_NET_SCH_PLUG=m - -# -# Classification -# -CONFIG_NET_CLS=y -CONFIG_NET_CLS_BASIC=m -CONFIG_NET_CLS_TCINDEX=m -CONFIG_NET_CLS_ROUTE4=m -CONFIG_NET_CLS_FW=m -CONFIG_NET_CLS_U32=m -CONFIG_CLS_U32_PERF=y -CONFIG_CLS_U32_MARK=y -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_FLOW=m -CONFIG_NET_CLS_CGROUP=y -CONFIG_NET_CLS_BPF=m -CONFIG_NET_EMATCH=y -CONFIG_NET_EMATCH_STACK=32 -CONFIG_NET_EMATCH_CMP=m -CONFIG_NET_EMATCH_NBYTE=m -CONFIG_NET_EMATCH_U32=m -CONFIG_NET_EMATCH_META=m -CONFIG_NET_EMATCH_TEXT=m -CONFIG_NET_EMATCH_IPSET=m -CONFIG_NET_CLS_ACT=y -CONFIG_NET_ACT_POLICE=m -CONFIG_NET_ACT_GACT=m -CONFIG_GACT_PROB=y -CONFIG_NET_ACT_MIRRED=m -CONFIG_NET_ACT_IPT=m -CONFIG_NET_ACT_NAT=m -CONFIG_NET_ACT_PEDIT=m -CONFIG_NET_ACT_SIMP=m -CONFIG_NET_ACT_SKBEDIT=m -CONFIG_NET_ACT_CSUM=m -CONFIG_NET_CLS_IND=y -CONFIG_NET_SCH_FIFO=y -CONFIG_DCB=y +# CONFIG_6LOWPAN is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set CONFIG_DNS_RESOLVER=y -CONFIG_BATMAN_ADV=m -CONFIG_BATMAN_ADV_BLA=y -CONFIG_BATMAN_ADV_DAT=y -CONFIG_BATMAN_ADV_NC=y -# CONFIG_BATMAN_ADV_DEBUG is not set -CONFIG_OPENVSWITCH=m -CONFIG_OPENVSWITCH_GRE=y -CONFIG_OPENVSWITCH_VXLAN=y -CONFIG_VSOCKETS=m -CONFIG_NETLINK_MMAP=y -CONFIG_NETLINK_DIAG=m -CONFIG_NET_MPLS_GSO=m +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_MPLS is not set # CONFIG_HSR is not set +# CONFIG_NET_SWITCHDEV is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y -CONFIG_CGROUP_NET_PRIO=m -CONFIG_CGROUP_NET_CLASSID=y +# CONFIG_CGROUP_NET_PRIO is not set +# CONFIG_CGROUP_NET_CLASSID is not set CONFIG_NET_RX_BUSY_POLL=y CONFIG_BQL=y # CONFIG_BPF_JIT is not set @@ -1258,174 +845,115 @@ CONFIG_NET_FLOW_LIMIT=y # # Network testing # -CONFIG_NET_PKTGEN=m -# CONFIG_NET_TCPPROBE is not set -CONFIG_HAMRADIO=y +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +CONFIG_CAN=y +CONFIG_CAN_RAW=y +CONFIG_CAN_BCM=y +CONFIG_CAN_GW=y # -# Packet Radio protocols +# CAN Device Drivers # -CONFIG_AX25=m -CONFIG_AX25_DAMA_SLAVE=y -CONFIG_NETROM=m -CONFIG_ROSE=m +# CONFIG_CAN_VCAN is not set +# CONFIG_CAN_SLCAN is not set +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +# CONFIG_CAN_LEDS is not set +# CONFIG_CAN_TI_HECC is not set +CONFIG_CAN_FLEXCAN=y +# CONFIG_CAN_GRCAN is not set +# CONFIG_CAN_RCAR is not set +# CONFIG_CAN_SJA1000 is not set +# CONFIG_CAN_C_CAN is not set +# CONFIG_CAN_M_CAN is not set +# CONFIG_CAN_CC770 is not set # -# AX.25 network device drivers +# CAN SPI interfaces # -CONFIG_MKISS=m -CONFIG_6PACK=m -CONFIG_BPQETHER=m -CONFIG_BAYCOM_SER_FDX=m -CONFIG_BAYCOM_SER_HDX=m -CONFIG_BAYCOM_PAR=m -CONFIG_BAYCOM_EPP=m -CONFIG_YAM=m -# CONFIG_CAN is not set -CONFIG_IRDA=m +# CONFIG_CAN_MCP251X is not set # -# IrDA protocols +# CAN USB interfaces # -CONFIG_IRLAN=m -CONFIG_IRNET=m -CONFIG_IRCOMM=m -# CONFIG_IRDA_ULTRA is not set - -# -# IrDA options -# -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -# CONFIG_IRDA_DEBUG is not set - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -CONFIG_IRTTY_SIR=m - -# -# Dongle support -# -CONFIG_DONGLE=y -CONFIG_ESI_DONGLE=m -CONFIG_ACTISYS_DONGLE=m -CONFIG_TEKRAM_DONGLE=m -CONFIG_TOIM3232_DONGLE=m -CONFIG_LITELINK_DONGLE=m -CONFIG_MA600_DONGLE=m -CONFIG_GIRBIL_DONGLE=m -CONFIG_MCP2120_DONGLE=m -CONFIG_OLD_BELKIN_DONGLE=m -CONFIG_ACT200L_DONGLE=m -CONFIG_KINGSUN_DONGLE=m -CONFIG_KSDAZZLE_DONGLE=m -CONFIG_KS959_DONGLE=m - -# -# FIR device drivers -# -CONFIG_USB_IRDA=m -CONFIG_SIGMATEL_FIR=m -CONFIG_VLSI_FIR=m -CONFIG_MCS_FIR=m -CONFIG_BT=m +# CONFIG_CAN_EMS_USB is not set +# CONFIG_CAN_ESD_USB2 is not set +# CONFIG_CAN_GS_USB is not set +# CONFIG_CAN_KVASER_USB is not set +# CONFIG_CAN_PEAK_USB is not set +# CONFIG_CAN_8DEV_USB is not set +# CONFIG_CAN_SOFTING is not set +# CONFIG_CAN_DEBUG_DEVICES is not set +# CONFIG_IRDA is not set +CONFIG_BT=y +CONFIG_BT_BREDR=y CONFIG_BT_RFCOMM=m CONFIG_BT_RFCOMM_TTY=y -CONFIG_BT_BNEP=m +CONFIG_BT_BNEP=y CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y -CONFIG_BT_CMTP=m -CONFIG_BT_HIDP=m +CONFIG_BT_HIDP=y +CONFIG_BT_LE=y +# CONFIG_BT_SELFTEST is not set +CONFIG_BT_DEBUGFS=y # # Bluetooth device drivers # +CONFIG_BT_INTEL=m +CONFIG_BT_BCM=m CONFIG_BT_HCIBTUSB=m -CONFIG_BT_HCIBTSDIO=m -CONFIG_BT_HCIUART=m -CONFIG_BT_HCIUART_H4=y -CONFIG_BT_HCIUART_BCSP=y -CONFIG_BT_HCIUART_ATH3K=y -CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIBTUSB_BCM=y +# CONFIG_BT_HCIBTSDIO is not set +CONFIG_BT_HCIUART=y +# CONFIG_BT_HCIUART_H4 is not set +# CONFIG_BT_HCIUART_BCSP is not set +# CONFIG_BT_HCIUART_ATH3K is not set +# CONFIG_BT_HCIUART_LL is not set CONFIG_BT_HCIUART_3WIRE=y -CONFIG_BT_HCIBCM203X=m -CONFIG_BT_HCIBPA10X=m -CONFIG_BT_HCIBFUSB=m -CONFIG_BT_HCIDTL1=m -CONFIG_BT_HCIBT3C=m -CONFIG_BT_HCIBLUECARD=m -CONFIG_BT_HCIBTUART=m -CONFIG_BT_HCIVHCI=m -CONFIG_BT_MRVL=m -CONFIG_BT_MRVL_SDIO=m -CONFIG_BT_ATH3K=m +# CONFIG_BT_HCIUART_INTEL is not set +# CONFIG_BT_HCIUART_BCM is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_MRVL is not set +# CONFIG_BT_ATH3K is not set # CONFIG_AF_RXRPC is not set -CONFIG_FIB_RULES=y CONFIG_WIRELESS=y -CONFIG_WIRELESS_EXT=y -CONFIG_WEXT_CORE=y -CONFIG_WEXT_PROC=y -CONFIG_WEXT_SPY=y -CONFIG_WEXT_PRIV=y -CONFIG_CFG80211=m +CONFIG_CFG80211=y # CONFIG_NL80211_TESTMODE is not set # CONFIG_CFG80211_DEVELOPER_WARNINGS is not set # CONFIG_CFG80211_REG_DEBUG is not set # CONFIG_CFG80211_CERTIFICATION_ONUS is not set CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set # CONFIG_CFG80211_INTERNAL_REGDB is not set -CONFIG_CFG80211_WEXT=y -CONFIG_LIB80211=m -# CONFIG_LIB80211_DEBUG is not set -CONFIG_MAC80211=m +# CONFIG_CFG80211_WEXT is not set +# CONFIG_LIB80211 is not set +CONFIG_MAC80211=y CONFIG_MAC80211_HAS_RC=y -# CONFIG_MAC80211_RC_PID is not set CONFIG_MAC80211_RC_MINSTREL=y CONFIG_MAC80211_RC_MINSTREL_HT=y +# CONFIG_MAC80211_RC_MINSTREL_VHT is not set CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" -CONFIG_MAC80211_MESH=y +# CONFIG_MAC80211_MESH is not set CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set # CONFIG_MAC80211_MESSAGE_TRACING is not set # CONFIG_MAC80211_DEBUG_MENU is not set # CONFIG_WIMAX is not set -CONFIG_RFKILL=m +CONFIG_RFKILL=y CONFIG_RFKILL_LEDS=y CONFIG_RFKILL_INPUT=y # CONFIG_RFKILL_REGULATOR is not set -CONFIG_RFKILL_GPIO=m -CONFIG_NET_9P=m -CONFIG_NET_9P_VIRTIO=m -CONFIG_NET_9P_RDMA=m -# CONFIG_NET_9P_DEBUG is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_NET_9P is not set # CONFIG_CAIF is not set -CONFIG_CEPH_LIB=m -# CONFIG_CEPH_LIB_PRETTYDEBUG is not set -# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set -CONFIG_NFC=m -CONFIG_NFC_DIGITAL=m -CONFIG_NFC_NCI=m -# CONFIG_NFC_NCI_SPI is not set -CONFIG_NFC_HCI=m -CONFIG_NFC_SHDLC=y - -# -# Near Field Communication (NFC) devices -# -CONFIG_NFC_PN533=m -CONFIG_NFC_SIM=m -CONFIG_NFC_PORT100=m -CONFIG_NFC_PN544=m -CONFIG_NFC_PN544_I2C=m -CONFIG_NFC_MICROREAD=m -CONFIG_NFC_MICROREAD_I2C=m -CONFIG_NFC_MRVL=m -CONFIG_NFC_MRVL_USB=m +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set CONFIG_HAVE_BPF_JIT=y # @@ -1435,6 +963,7 @@ CONFIG_HAVE_BPF_JIT=y # # Generic Driver Options # +CONFIG_UEVENT_HELPER=y CONFIG_UEVENT_HELPER_PATH="" CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y @@ -1442,14 +971,13 @@ CONFIG_DEVTMPFS_MOUNT=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y CONFIG_FIRMWARE_IN_KERNEL=y -CONFIG_EXTRA_FIRMWARE="imx/sdma/sdma-imx6q.bin" -CONFIG_EXTRA_FIRMWARE_DIR="firmware" -# CONFIG_FW_LOADER_USER_HELPER is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_ALLOW_DEV_COREDUMP=y # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_GENERIC_CPU_DEVICES is not set -# CONFIG_HAVE_CPU_AUTOPROBE is not set CONFIG_SOC_BUS=y CONFIG_REGMAP=y CONFIG_REGMAP_I2C=y @@ -1457,12 +985,13 @@ CONFIG_REGMAP_SPI=y CONFIG_REGMAP_MMIO=y CONFIG_REGMAP_IRQ=y CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_FENCE_TRACE is not set CONFIG_DMA_CMA=y # # Default contiguous memory area size: # -CONFIG_CMA_SIZE_MBYTES=256 +CONFIG_CMA_SIZE_MBYTES=16 CONFIG_CMA_SIZE_SEL_MBYTES=y # CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set # CONFIG_CMA_SIZE_SEL_MIN is not set @@ -1472,99 +1001,194 @@ CONFIG_CMA_ALIGNMENT=8 # # Bus devices # -# CONFIG_IMX_WEIM is not set -# CONFIG_ARM_CCI is not set +CONFIG_ARM_CCI=y +CONFIG_ARM_CCI400_COMMON=y +CONFIG_ARM_CCI400_PMU=y +# CONFIG_ARM_CCN is not set +# CONFIG_BRCMSTB_GISB_ARB is not set +CONFIG_IMX_WEIM=y +# CONFIG_VEXPRESS_CONFIG is not set CONFIG_CONNECTOR=y CONFIG_PROC_EVENTS=y -# CONFIG_MTD is not set +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set +# CONFIG_MTD_PARTITIONED_MASTER is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +CONFIG_MTD_DATAFLASH=y +# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set +# CONFIG_MTD_DATAFLASH_OTP is not set +CONFIG_MTD_M25P80=y +CONFIG_MTD_SST25L=y +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_DENALI is not set +# CONFIG_MTD_NAND_GPIO is not set +# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_RICOH is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_DOCG4 is not set +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_GPMI_NAND=y +# CONFIG_MTD_NAND_PLATFORM is not set +CONFIG_MTD_NAND_MXC=y +# CONFIG_MTD_NAND_HISI504 is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR & LPDDR2 PCM memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_LPDDR2_NVM is not set +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +CONFIG_SPI_FSL_QUADSPI=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_LIMIT=20 +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +# CONFIG_MTD_UBI_BLOCK is not set CONFIG_DTC=y CONFIG_OF=y # # Device Tree and Open Firmware support # -CONFIG_PROC_DEVICETREE=y -# CONFIG_OF_SELFTEST is not set +# CONFIG_OF_UNITTEST is not set CONFIG_OF_FLATTREE=y CONFIG_OF_EARLY_FLATTREE=y CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y CONFIG_OF_IRQ=y CONFIG_OF_NET=y CONFIG_OF_MDIO=y CONFIG_OF_PCI=y CONFIG_OF_PCI_IRQ=y -CONFIG_PARPORT=m +CONFIG_OF_MTD=y +CONFIG_OF_RESERVED_MEM=y +# CONFIG_OF_OVERLAY is not set CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_SERIAL=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_AX88796 is not set -CONFIG_PARPORT_1284=y -CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT is not set CONFIG_BLK_DEV=y -CONFIG_BLK_DEV_NULL_BLK=m -# CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_NULL_BLK is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set -CONFIG_ZRAM=m -# CONFIG_ZRAM_DEBUG is not set -CONFIG_BLK_CPQ_CISS_DA=m -CONFIG_CISS_SCSI_TAPE=y -CONFIG_BLK_DEV_DAC960=m -CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_LOOP_MIN_COUNT=0 +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 # CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_DRBD=m -# CONFIG_DRBD_FAULT_INJECTION is not set -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_NVME=m -CONFIG_BLK_DEV_OSD=m -CONFIG_BLK_DEV_SX8=m +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_NVME is not set +# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=65536 -# CONFIG_BLK_DEV_XIP is not set -CONFIG_CDROM_PKTCDVD=m -CONFIG_CDROM_PKTCDVD_BUFFERS=8 -# CONFIG_CDROM_PKTCDVD_WCACHE is not set -CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_PMEM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set # CONFIG_MG_DISK is not set -CONFIG_VIRTIO_BLK=m -CONFIG_BLK_DEV_RBD=m +# CONFIG_BLK_DEV_RBD is not set # CONFIG_BLK_DEV_RSXX is not set # # Misc devices # -CONFIG_SENSORS_LIS3LV02D=m +# CONFIG_SENSORS_LIS3LV02D is not set # CONFIG_AD525X_DPOT is not set -# CONFIG_ATMEL_PWM is not set # CONFIG_DUMMY_IRQ is not set # CONFIG_PHANTOM is not set # CONFIG_SGI_IOC4 is not set -CONFIG_TIFM_CORE=m -CONFIG_TIFM_7XX1=m +# CONFIG_TIFM_CORE is not set # CONFIG_ICS932S401 is not set -# CONFIG_ATMEL_SSC is not set -CONFIG_ENCLOSURE_SERVICES=m +# CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_HP_ILO is not set -CONFIG_APDS9802ALS=m -CONFIG_ISL29003=m -CONFIG_ISL29020=m -CONFIG_SENSORS_TSL2550=m +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set # CONFIG_SENSORS_BH1780 is not set -CONFIG_SENSORS_BH1770=m -CONFIG_SENSORS_APDS990X=m +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set # CONFIG_TI_DAC7512 is not set # CONFIG_BMP085_I2C is not set # CONFIG_BMP085_SPI is not set -# CONFIG_PCH_PHUB is not set # CONFIG_USB_SWITCH_FSA9480 is not set # CONFIG_LATTICE_ECP3_CONFIG is not set CONFIG_SRAM=y @@ -1573,27 +1197,29 @@ CONFIG_SRAM=y # # EEPROM support # -CONFIG_EEPROM_AT24=m -# CONFIG_EEPROM_AT25 is not set -CONFIG_EEPROM_LEGACY=m -CONFIG_EEPROM_MAX6875=m -CONFIG_EEPROM_93CX6=m +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set # CONFIG_EEPROM_93XX46 is not set -CONFIG_CB710_CORE=m -# CONFIG_CB710_DEBUG is not set -CONFIG_CB710_DEBUG_ASSUMPTIONS=y +# CONFIG_CB710_CORE is not set # # Texas Instruments shared transport line discipline # # CONFIG_TI_ST is not set -CONFIG_SENSORS_LIS3_SPI=m -CONFIG_SENSORS_LIS3_I2C=m +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set # # Altera FPGA firmware download module # -CONFIG_ALTERA_STAPL=m +# CONFIG_ALTERA_STAPL is not set + +# +# Intel MIC Bus Driver +# # # Intel MIC Host Driver @@ -1602,6 +1228,8 @@ CONFIG_ALTERA_STAPL=m # # Intel MIC Card Driver # +# CONFIG_ECHO is not set +# CONFIG_CXL_BASE is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1609,25 +1237,22 @@ CONFIG_HAVE_IDE=y # SCSI device support # CONFIG_SCSI_MOD=y -CONFIG_RAID_ATTRS=m +# CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m -CONFIG_SCSI_NETLINK=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set # CONFIG_SCSI_PROC_FS is not set # # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_CHR_DEV_SG=y -CONFIG_CHR_DEV_SCH=m -CONFIG_SCSI_ENCLOSURE=m -CONFIG_SCSI_MULTI_LUN=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SCAN_ASYNC=y @@ -1635,27 +1260,15 @@ CONFIG_SCSI_SCAN_ASYNC=y # # SCSI Transports # -CONFIG_SCSI_SPI_ATTRS=m -CONFIG_SCSI_FC_ATTRS=m -CONFIG_SCSI_FC_TGT_ATTRS=y -CONFIG_SCSI_ISCSI_ATTRS=m -CONFIG_SCSI_SAS_ATTRS=m -CONFIG_SCSI_SAS_LIBSAS=m -CONFIG_SCSI_SAS_ATA=y -CONFIG_SCSI_SAS_HOST_SMP=y -CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set # CONFIG_SCSI_LOWLEVEL is not set -# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set -CONFIG_SCSI_DH=y -CONFIG_SCSI_DH_RDAC=m -CONFIG_SCSI_DH_HP_SW=m -CONFIG_SCSI_DH_EMC=m -CONFIG_SCSI_DH_ALUA=m -CONFIG_SCSI_OSD_INITIATOR=m -CONFIG_SCSI_OSD_ULD=m -CONFIG_SCSI_OSD_DPRINT_SENSE=1 -# CONFIG_SCSI_OSD_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set CONFIG_ATA=y # CONFIG_ATA_NONSTANDARD is not set CONFIG_ATA_VERBOSE_ERROR=y @@ -1664,205 +1277,116 @@ CONFIG_SATA_PMP=y # # Controllers with non-SFF native interface # -CONFIG_SATA_AHCI=y +# CONFIG_SATA_AHCI is not set CONFIG_SATA_AHCI_PLATFORM=y CONFIG_AHCI_IMX=y -CONFIG_SATA_INIC162X=m -CONFIG_SATA_ACARD_AHCI=m -CONFIG_SATA_SIL24=m +# CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_ACARD_AHCI is not set +# CONFIG_SATA_SIL24 is not set CONFIG_ATA_SFF=y # # SFF controllers with custom DMA interface # -CONFIG_PDC_ADMA=m -CONFIG_SATA_QSTOR=m -CONFIG_SATA_SX4=m +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_SX4 is not set CONFIG_ATA_BMDMA=y # # SATA SFF controllers with BMDMA # -CONFIG_ATA_PIIX=y -# CONFIG_SATA_HIGHBANK is not set -CONFIG_SATA_MV=m -CONFIG_SATA_NV=m -CONFIG_SATA_PROMISE=m -CONFIG_SATA_RCAR=m -CONFIG_SATA_SIL=m -CONFIG_SATA_SIS=m -CONFIG_SATA_SVW=m -CONFIG_SATA_ULI=m -CONFIG_SATA_VIA=m -CONFIG_SATA_VITESSE=m +# CONFIG_ATA_PIIX is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_SVW is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set # # PATA SFF controllers with BMDMA # -CONFIG_PATA_ALI=m -CONFIG_PATA_AMD=m -CONFIG_PATA_ARASAN_CF=m -CONFIG_PATA_ARTOP=m -CONFIG_PATA_ATIIXP=m -CONFIG_PATA_ATP867X=m -CONFIG_PATA_CMD64X=m -CONFIG_PATA_CS5520=m -CONFIG_PATA_CS5530=m -CONFIG_PATA_CS5536=m -CONFIG_PATA_CYPRESS=m -CONFIG_PATA_EFAR=m -CONFIG_PATA_HPT366=m -CONFIG_PATA_HPT37X=m -CONFIG_PATA_HPT3X2N=m -CONFIG_PATA_HPT3X3=m -# CONFIG_PATA_HPT3X3_DMA is not set -# CONFIG_PATA_IMX is not set -CONFIG_PATA_IT8213=m -CONFIG_PATA_IT821X=m -CONFIG_PATA_JMICRON=m -CONFIG_PATA_MARVELL=m -CONFIG_PATA_NETCELL=m -CONFIG_PATA_NINJA32=m -CONFIG_PATA_NS87415=m -CONFIG_PATA_OLDPIIX=m -CONFIG_PATA_OPTIDMA=m -CONFIG_PATA_PDC2027X=m -CONFIG_PATA_PDC_OLD=m +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_ATP867X is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +CONFIG_PATA_IMX=y +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_PDC_OLD is not set # CONFIG_PATA_RADISYS is not set -CONFIG_PATA_RDC=m -# CONFIG_PATA_SC1200 is not set -CONFIG_PATA_SCH=m -CONFIG_PATA_SERVERWORKS=m -CONFIG_PATA_SIL680=m -CONFIG_PATA_SIS=m -CONFIG_PATA_TOSHIBA=m -CONFIG_PATA_TRIFLEX=m -CONFIG_PATA_VIA=m -CONFIG_PATA_WINBOND=m +# CONFIG_PATA_RDC is not set +# CONFIG_PATA_SCH is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_TOSHIBA is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set # # PIO-only SFF controllers # -CONFIG_PATA_CMD640_PCI=m -CONFIG_PATA_MPIIX=m -CONFIG_PATA_NS87410=m -CONFIG_PATA_OPTI=m -CONFIG_PATA_PCMCIA=m +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set # CONFIG_PATA_PLATFORM is not set # CONFIG_PATA_RZ1000 is not set # # Generic fallback / legacy drivers # -CONFIG_ATA_GENERIC=m +# CONFIG_ATA_GENERIC is not set # CONFIG_PATA_LEGACY is not set -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_AUTODETECT=y -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID10=m -CONFIG_MD_RAID456=m -CONFIG_MD_MULTIPATH=m -CONFIG_MD_FAULTY=m -CONFIG_BCACHE=m -# CONFIG_BCACHE_DEBUG is not set -# CONFIG_BCACHE_CLOSURES_DEBUG is not set -CONFIG_BLK_DEV_DM_BUILTIN=y -CONFIG_BLK_DEV_DM=y -CONFIG_DM_DEBUG=y -CONFIG_DM_BUFIO=y -CONFIG_DM_BIO_PRISON=m -CONFIG_DM_PERSISTENT_DATA=m -# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set -CONFIG_DM_CRYPT=m -CONFIG_DM_SNAPSHOT=y -CONFIG_DM_THIN_PROVISIONING=m -CONFIG_DM_CACHE=m -CONFIG_DM_CACHE_MQ=m -CONFIG_DM_CACHE_CLEANER=m -CONFIG_DM_MIRROR=y -CONFIG_DM_LOG_USERSPACE=m -CONFIG_DM_RAID=m -CONFIG_DM_ZERO=y -CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_QL=m -CONFIG_DM_MULTIPATH_ST=m -CONFIG_DM_DELAY=m -CONFIG_DM_UEVENT=y -CONFIG_DM_FLAKEY=m -CONFIG_DM_VERITY=m -CONFIG_DM_SWITCH=m -CONFIG_TARGET_CORE=m -CONFIG_TCM_IBLOCK=m -CONFIG_TCM_FILEIO=m -CONFIG_TCM_PSCSI=m -CONFIG_LOOPBACK_TARGET=m -CONFIG_ISCSI_TARGET=m -CONFIG_SBP_TARGET=m -CONFIG_FUSION=y -CONFIG_FUSION_SPI=m -CONFIG_FUSION_FC=m -CONFIG_FUSION_SAS=m -CONFIG_FUSION_MAX_SGE=40 -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_FUSION_LOGGING=y +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set # # IEEE 1394 (FireWire) support # -CONFIG_FIREWIRE=m -CONFIG_FIREWIRE_OHCI=m -CONFIG_FIREWIRE_SBP2=m -CONFIG_FIREWIRE_NET=m -CONFIG_FIREWIRE_NOSY=m -# CONFIG_I2O is not set +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set CONFIG_NETDEVICES=y -CONFIG_MII=m +CONFIG_MII=y CONFIG_NET_CORE=y CONFIG_BONDING=m -CONFIG_DUMMY=m -CONFIG_EQUALIZER=m -CONFIG_NET_FC=y -CONFIG_IFB=m -CONFIG_NET_TEAM=m -CONFIG_NET_TEAM_MODE_BROADCAST=m -CONFIG_NET_TEAM_MODE_ROUNDROBIN=m -CONFIG_NET_TEAM_MODE_RANDOM=m -CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m -CONFIG_NET_TEAM_MODE_LOADBALANCE=m -CONFIG_MACVLAN=m -CONFIG_MACVTAP=m -CONFIG_VXLAN=m -CONFIG_NETCONSOLE=m -CONFIG_NETCONSOLE_DYNAMIC=y -CONFIG_NETPOLL=y -CONFIG_NETPOLL_TRAP=y -CONFIG_NET_POLL_CONTROLLER=y -CONFIG_TUN=m -CONFIG_VETH=m -CONFIG_VIRTIO_NET=m -CONFIG_NLMON=m -CONFIG_SUNGEM_PHY=m +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_NET_FC is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_IPVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_NLMON is not set # CONFIG_ARCNET is not set -CONFIG_ATM_DRIVERS=y -# CONFIG_ATM_DUMMY is not set -CONFIG_ATM_TCP=m -# CONFIG_ATM_LANAI is not set -CONFIG_ATM_ENI=m -# CONFIG_ATM_ENI_DEBUG is not set -# CONFIG_ATM_ENI_TUNE_BURST is not set -CONFIG_ATM_NICSTAR=m -# CONFIG_ATM_NICSTAR_USE_SUNI is not set -# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set -# CONFIG_ATM_IDT77252 is not set -# CONFIG_ATM_IA is not set -# CONFIG_ATM_FORE200E is not set -CONFIG_ATM_HE=m -# CONFIG_ATM_HE_USE_SUNI is not set -CONFIG_ATM_SOLOS=m # # CAIF transport drivers @@ -1871,241 +1395,173 @@ CONFIG_ATM_SOLOS=m # # Distributed Switch Architecture drivers # -CONFIG_NET_DSA_MV88E6XXX=m -CONFIG_NET_DSA_MV88E6060=m -CONFIG_NET_DSA_MV88E6XXX_NEED_PPU=y -CONFIG_NET_DSA_MV88E6131=m -CONFIG_NET_DSA_MV88E6123_61_65=m +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set CONFIG_ETHERNET=y -CONFIG_MDIO=m CONFIG_NET_VENDOR_3COM=y -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_3C589=m -CONFIG_VORTEX=m -CONFIG_TYPHOON=m +# CONFIG_VORTEX is not set +# CONFIG_TYPHOON is not set CONFIG_NET_VENDOR_ADAPTEC=y -CONFIG_ADAPTEC_STARFIRE=m +# CONFIG_ADAPTEC_STARFIRE is not set +CONFIG_NET_VENDOR_AGERE=y +# CONFIG_ET131X is not set CONFIG_NET_VENDOR_ALTEON=y -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set +# CONFIG_ACENIC is not set +# CONFIG_ALTERA_TSE is not set CONFIG_NET_VENDOR_AMD=y -CONFIG_AMD8111_ETH=m -CONFIG_PCNET32=m -CONFIG_PCMCIA_NMCLAN=m +# CONFIG_AMD8111_ETH is not set +# CONFIG_PCNET32 is not set CONFIG_NET_VENDOR_ARC=y -CONFIG_ARC_EMAC=m +# CONFIG_ARC_EMAC is not set +# CONFIG_EMAC_ROCKCHIP is not set CONFIG_NET_VENDOR_ATHEROS=y -CONFIG_ATL2=m -CONFIG_ATL1=m -CONFIG_ATL1E=m -CONFIG_ATL1C=m -CONFIG_ALX=m +# CONFIG_ATL2 is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_ALX is not set CONFIG_NET_CADENCE=y -CONFIG_ARM_AT91_ETHER=m -CONFIG_MACB=m +# CONFIG_MACB is not set # CONFIG_NET_VENDOR_BROADCOM is not set CONFIG_NET_VENDOR_BROCADE=y -CONFIG_BNA=m -CONFIG_NET_CALXEDA_XGMAC=m +# CONFIG_BNA is not set CONFIG_NET_VENDOR_CHELSIO=y -CONFIG_CHELSIO_T1=m -CONFIG_CHELSIO_T1_1G=y -CONFIG_CHELSIO_T3=m -CONFIG_CHELSIO_T4=m -CONFIG_CHELSIO_T4VF=m -# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +CONFIG_NET_VENDOR_CIRRUS=y +CONFIG_CS89x0=y +CONFIG_CS89x0_PLATFORM=y CONFIG_NET_VENDOR_CISCO=y -CONFIG_ENIC=m +# CONFIG_ENIC is not set # CONFIG_DM9000 is not set -CONFIG_DNET=m +# CONFIG_DNET is not set CONFIG_NET_VENDOR_DEC=y -CONFIG_NET_TULIP=y -CONFIG_DE2104X=m -CONFIG_DE2104X_DSL=0 -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -CONFIG_TULIP_MMIO=y -# CONFIG_TULIP_NAPI is not set -CONFIG_WINBOND_840=m -CONFIG_DM9102=m -CONFIG_ULI526X=m -CONFIG_PCMCIA_XIRCOM=m +# CONFIG_NET_TULIP is not set CONFIG_NET_VENDOR_DLINK=y -CONFIG_DL2K=m -CONFIG_SUNDANCE=m -# CONFIG_SUNDANCE_MMIO is not set +# CONFIG_DL2K is not set +# CONFIG_SUNDANCE is not set CONFIG_NET_VENDOR_EMULEX=y -CONFIG_BE2NET=m +# CONFIG_BE2NET is not set CONFIG_NET_VENDOR_EXAR=y -CONFIG_S2IO=m -CONFIG_VXGE=m -# CONFIG_VXGE_DEBUG_TRACE_ALL is not set +# CONFIG_S2IO is not set +# CONFIG_VXGE is not set # CONFIG_NET_VENDOR_FARADAY is not set CONFIG_NET_VENDOR_FREESCALE=y CONFIG_FEC=y -# CONFIG_NET_VENDOR_FUJITSU is not set -# CONFIG_NET_VENDOR_HP is not set -CONFIG_NET_VENDOR_INTEL=y -CONFIG_E100=m -CONFIG_E1000=m -CONFIG_E1000E=m -CONFIG_IGB=m -CONFIG_IGB_HWMON=y -CONFIG_IGBVF=m -CONFIG_IXGB=m -CONFIG_IXGBE=m -CONFIG_IXGBE_HWMON=y -CONFIG_IXGBE_DCB=y -CONFIG_I40E=m -# CONFIG_I40E_VXLAN is not set -# CONFIG_I40E_DCB is not set -# CONFIG_NET_VENDOR_I825XX is not set +# CONFIG_FSL_PQ_MDIO is not set +# CONFIG_FSL_XGMAC_MDIO is not set +CONFIG_NET_VENDOR_HISILICON=y +# CONFIG_HIX5HD2_GMAC is not set +# CONFIG_HIP04_ETH is not set +CONFIG_NET_VENDOR_HP=y +# CONFIG_HP100 is not set +# CONFIG_NET_VENDOR_INTEL is not set # CONFIG_IP1000 is not set -CONFIG_JME=m -CONFIG_NET_VENDOR_MARVELL=y -CONFIG_MVMDIO=m -CONFIG_SKGE=m -CONFIG_SKGE_GENESIS=y -CONFIG_SKY2=m +# CONFIG_JME is not set +# CONFIG_NET_VENDOR_MARVELL is not set CONFIG_NET_VENDOR_MELLANOX=y # CONFIG_MLX4_EN is not set -CONFIG_MLX4_CORE=m -CONFIG_MLX4_DEBUG=y -CONFIG_MLX5_CORE=m -CONFIG_NET_VENDOR_MICREL=y -# CONFIG_KS8842 is not set -# CONFIG_KS8851 is not set -# CONFIG_KS8851_MLL is not set -CONFIG_KSZ884X_PCI=m -CONFIG_NET_VENDOR_MICROCHIP=y -# CONFIG_ENC28J60 is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_MLX5_CORE is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set CONFIG_NET_VENDOR_MYRI=y -CONFIG_MYRI10GE=m -CONFIG_FEALNX=m -CONFIG_NET_VENDOR_NATSEMI=y -CONFIG_NATSEMI=m -CONFIG_NS83820=m -CONFIG_NET_VENDOR_8390=y -CONFIG_PCMCIA_AXNET=m -# CONFIG_AX88796 is not set -CONFIG_NE2K_PCI=m -CONFIG_PCMCIA_PCNET=m +# CONFIG_MYRI10GE is not set +# CONFIG_FEALNX is not set +# CONFIG_NET_VENDOR_NATSEMI is not set CONFIG_NET_VENDOR_NVIDIA=y -CONFIG_FORCEDETH=m +# CONFIG_FORCEDETH is not set CONFIG_NET_VENDOR_OKI=y # CONFIG_ETHOC is not set CONFIG_NET_PACKET_ENGINE=y -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set CONFIG_NET_VENDOR_QLOGIC=y -CONFIG_QLA3XXX=m -CONFIG_QLCNIC=m -CONFIG_QLCNIC_SRIOV=y -CONFIG_QLCNIC_DCB=y -CONFIG_QLGE=m -CONFIG_NETXEN_NIC=m +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_QLGE is not set +# CONFIG_NETXEN_NIC is not set +CONFIG_NET_VENDOR_QUALCOMM=y +# CONFIG_QCA7000 is not set CONFIG_NET_VENDOR_REALTEK=y -CONFIG_8139CP=m -CONFIG_8139TOO=m -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -CONFIG_8139TOO_8129=y -# CONFIG_8139_OLD_RX_RESET is not set -CONFIG_R8169=m -# CONFIG_SH_ETH is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_R8169 is not set CONFIG_NET_VENDOR_RDC=y -CONFIG_R6040=m -CONFIG_NET_VENDOR_SEEQ=y +# CONFIG_R6040 is not set +CONFIG_NET_VENDOR_ROCKER=y +CONFIG_NET_VENDOR_SAMSUNG=y +# CONFIG_SXGBE_ETH is not set +# CONFIG_NET_VENDOR_SEEQ is not set CONFIG_NET_VENDOR_SILAN=y -CONFIG_SC92031=m +# CONFIG_SC92031 is not set CONFIG_NET_VENDOR_SIS=y -CONFIG_SIS900=m -CONFIG_SIS190=m +# CONFIG_SIS900 is not set +# CONFIG_SIS190 is not set # CONFIG_SFC is not set CONFIG_NET_VENDOR_SMSC=y -# CONFIG_SMC91X is not set -CONFIG_PCMCIA_SMC91C92=m -CONFIG_EPIC100=m -# CONFIG_SMC911X is not set -# CONFIG_SMSC911X is not set -CONFIG_SMSC9420=m -CONFIG_NET_VENDOR_STMICRO=y -# CONFIG_STMMAC_ETH is not set +CONFIG_SMC91X=y +# CONFIG_EPIC100 is not set +CONFIG_SMC911X=y +CONFIG_SMSC911X=y +# CONFIG_SMSC911X_ARCH_HOOKS is not set +# CONFIG_SMSC9420 is not set +# CONFIG_NET_VENDOR_STMICRO is not set CONFIG_NET_VENDOR_SUN=y -CONFIG_HAPPYMEAL=m -CONFIG_SUNGEM=m -CONFIG_CASSINI=m -CONFIG_NIU=m +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NIU is not set CONFIG_NET_VENDOR_TEHUTI=y -CONFIG_TEHUTI=m +# CONFIG_TEHUTI is not set CONFIG_NET_VENDOR_TI=y -CONFIG_TLAN=m +# CONFIG_TI_CPSW_ALE is not set +# CONFIG_TLAN is not set CONFIG_NET_VENDOR_VIA=y -CONFIG_VIA_RHINE=m -CONFIG_VIA_RHINE_MMIO=y +# CONFIG_VIA_RHINE is not set # CONFIG_VIA_VELOCITY is not set CONFIG_NET_VENDOR_WIZNET=y -CONFIG_WIZNET_W5100=m -CONFIG_WIZNET_W5300=m -# CONFIG_WIZNET_BUS_DIRECT is not set -# CONFIG_WIZNET_BUS_INDIRECT is not set -CONFIG_WIZNET_BUS_ANY=y -CONFIG_NET_VENDOR_XIRCOM=y -CONFIG_PCMCIA_XIRC2PS=m +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set CONFIG_PHYLIB=y +# CONFIG_SWCONFIG is not set # # MII PHY device drivers # CONFIG_AT803X_PHY=y -CONFIG_AMD_PHY=m -CONFIG_MARVELL_PHY=m -CONFIG_DAVICOM_PHY=m -CONFIG_QSEMI_PHY=m -CONFIG_LXT_PHY=m -CONFIG_CICADA_PHY=m -CONFIG_VITESSE_PHY=m -CONFIG_SMSC_PHY=m -CONFIG_BROADCOM_PHY=m -CONFIG_BCM87XX_PHY=m -CONFIG_ICPLUS_PHY=m -CONFIG_REALTEK_PHY=m -CONFIG_NATIONAL_PHY=m -CONFIG_STE10XP=m -CONFIG_LSI_ET1011C_PHY=m -CONFIG_MICREL_PHY=m -CONFIG_FIXED_PHY=y -CONFIG_MDIO_BITBANG=m -# CONFIG_MDIO_GPIO is not set +# CONFIG_AMD_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set # CONFIG_MDIO_BUS_MUX_GPIO is not set # CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_BCM_UNIMAC is not set # CONFIG_MICREL_KS8995MA is not set -# CONFIG_PLIP is not set -CONFIG_PPP=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPPOATM=m -CONFIG_PPPOE=m -CONFIG_PPTP=m -CONFIG_PPPOL2TP=m -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_SLIP=m -CONFIG_SLHC=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -# CONFIG_SLIP_MODE_SLIP6 is not set - -# -# USB Network Adapters -# -CONFIG_USB_CATC=m -CONFIG_USB_KAWETH=m +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_USB_NET_DRIVERS=y +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set CONFIG_USB_PEGASUS=m CONFIG_USB_RTL8150=m CONFIG_USB_RTL8152=m @@ -2115,348 +1571,121 @@ CONFIG_USB_NET_AX88179_178A=m CONFIG_USB_NET_CDCETHER=m CONFIG_USB_NET_CDC_EEM=m CONFIG_USB_NET_CDC_NCM=m -CONFIG_USB_NET_HUAWEI_CDC_NCM=m -CONFIG_USB_NET_CDC_MBIM=m -CONFIG_USB_NET_DM9601=m -CONFIG_USB_NET_SR9700=m +# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set +# CONFIG_USB_NET_CDC_MBIM is not set +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SR9700 is not set # CONFIG_USB_NET_SR9800 is not set -CONFIG_USB_NET_SMSC75XX=m -CONFIG_USB_NET_SMSC95XX=m -CONFIG_USB_NET_GL620A=m +# CONFIG_USB_NET_SMSC75XX is not set +# CONFIG_USB_NET_SMSC95XX is not set +# CONFIG_USB_NET_GL620A is not set CONFIG_USB_NET_NET1080=m -CONFIG_USB_NET_PLUSB=m -CONFIG_USB_NET_MCS7830=m -CONFIG_USB_NET_RNDIS_HOST=m +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +# CONFIG_USB_NET_RNDIS_HOST is not set CONFIG_USB_NET_CDC_SUBSET=m -CONFIG_USB_ALI_M5632=y -CONFIG_USB_AN2720=y +# CONFIG_USB_ALI_M5632 is not set +# CONFIG_USB_AN2720 is not set CONFIG_USB_BELKIN=y CONFIG_USB_ARMLINUX=y -CONFIG_USB_EPSON2888=y -CONFIG_USB_KC2190=y +# CONFIG_USB_EPSON2888 is not set +# CONFIG_USB_KC2190 is not set CONFIG_USB_NET_ZAURUS=m -CONFIG_USB_NET_CX82310_ETH=m -CONFIG_USB_NET_KALMIA=m -CONFIG_USB_NET_QMI_WWAN=m -CONFIG_USB_HSO=m -CONFIG_USB_NET_INT51X1=m -CONFIG_USB_IPHETH=m -CONFIG_USB_SIERRA_NET=m -CONFIG_USB_VL600=m +# CONFIG_USB_NET_CX82310_ETH is not set +# CONFIG_USB_NET_KALMIA is not set +# CONFIG_USB_NET_QMI_WWAN is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_USB_SIERRA_NET is not set +# CONFIG_USB_VL600 is not set CONFIG_WLAN=y -# CONFIG_PCMCIA_RAYCS is not set # CONFIG_LIBERTAS_THINFIRM is not set # CONFIG_ATMEL is not set -CONFIG_AT76C50X_USB=m -# CONFIG_AIRO_CS is not set -# CONFIG_PCMCIA_WL3501 is not set +# CONFIG_AT76C50X_USB is not set # CONFIG_PRISM54 is not set # CONFIG_USB_ZD1201 is not set -CONFIG_USB_NET_RNDIS_WLAN=m -CONFIG_RTL8180=m -CONFIG_RTL8187=m -CONFIG_RTL8187_LEDS=y +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8180 is not set +# CONFIG_RTL8187 is not set # CONFIG_ADM8211 is not set -CONFIG_MAC80211_HWSIM=m -CONFIG_MWL8K=m +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_MWL8K is not set CONFIG_ATH_COMMON=m CONFIG_ATH_CARDS=m # CONFIG_ATH_DEBUG is not set -CONFIG_ATH5K=m -CONFIG_ATH5K_DEBUG=y -CONFIG_ATH5K_PCI=y +# CONFIG_ATH5K is not set +# CONFIG_ATH5K_PCI is not set CONFIG_ATH9K_HW=m CONFIG_ATH9K_COMMON=m CONFIG_ATH9K_BTCOEX_SUPPORT=y CONFIG_ATH9K=m CONFIG_ATH9K_PCI=y -CONFIG_ATH9K_AHB=y +# CONFIG_ATH9K_AHB is not set +# CONFIG_ATH9K_DEBUGFS is not set +# CONFIG_ATH9K_DYNACK is not set # CONFIG_ATH9K_WOW is not set -# CONFIG_ATH9K_LEGACY_RATE_CONTROL is not set CONFIG_ATH9K_RFKILL=y -CONFIG_ATH9K_HTC=m -CONFIG_CARL9170=m -CONFIG_CARL9170_LEDS=y -CONFIG_CARL9170_WPC=y -# CONFIG_CARL9170_HWRNG is not set -CONFIG_ATH6KL=m -CONFIG_ATH6KL_SDIO=m -CONFIG_ATH6KL_USB=m -CONFIG_ATH6KL_DEBUG=y -CONFIG_AR5523=m -CONFIG_WIL6210=m -CONFIG_WIL6210_ISR_COR=y -CONFIG_ATH10K=m -CONFIG_ATH10K_PCI=m -# CONFIG_ATH10K_DEBUG is not set -CONFIG_ATH10K_DEBUGFS=y -CONFIG_WCN36XX=m -# CONFIG_WCN36XX_DEBUGFS is not set -CONFIG_B43=m -CONFIG_B43_BCMA=y -CONFIG_B43_SSB=y -CONFIG_B43_PCI_AUTOSELECT=y -CONFIG_B43_PCICORE_AUTOSELECT=y -CONFIG_B43_PCMCIA=y -CONFIG_B43_SDIO=y -CONFIG_B43_BCMA_PIO=y -CONFIG_B43_PIO=y -CONFIG_B43_PHY_N=y -CONFIG_B43_PHY_LP=y -CONFIG_B43_PHY_HT=y -CONFIG_B43_LEDS=y -CONFIG_B43_HWRNG=y -# CONFIG_B43_DEBUG is not set -CONFIG_B43LEGACY=m -CONFIG_B43LEGACY_PCI_AUTOSELECT=y -CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y -CONFIG_B43LEGACY_LEDS=y -CONFIG_B43LEGACY_HWRNG=y -# CONFIG_B43LEGACY_DEBUG is not set -CONFIG_B43LEGACY_DMA=y -CONFIG_B43LEGACY_PIO=y -CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y -# CONFIG_B43LEGACY_DMA_MODE is not set -# CONFIG_B43LEGACY_PIO_MODE is not set +# CONFIG_ATH9K_CHANNEL_CONTEXT is not set +CONFIG_ATH9K_PCOEM=y +# CONFIG_ATH9K_HTC is not set +# CONFIG_CARL9170 is not set +# CONFIG_ATH6KL is not set +# CONFIG_AR5523 is not set +# CONFIG_WIL6210 is not set +# CONFIG_ATH10K is not set +# CONFIG_WCN36XX is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set CONFIG_BRCMUTIL=m # CONFIG_BRCMSMAC is not set CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_PROTO_BCDC=y CONFIG_BRCMFMAC_SDIO=y # CONFIG_BRCMFMAC_USB is not set +# CONFIG_BRCMFMAC_PCIE is not set # CONFIG_BRCM_TRACING is not set # CONFIG_BRCMDBG is not set # CONFIG_HOSTAP is not set # CONFIG_IPW2100 is not set # CONFIG_IPW2200 is not set -CONFIG_IWLWIFI=m -CONFIG_IWLDVM=m -CONFIG_IWLMVM=m -CONFIG_IWLWIFI_OPMODE_MODULAR=y - -# -# Debugging Options -# -CONFIG_IWLWIFI_DEBUG=y -# CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE is not set -CONFIG_IWLEGACY=m -CONFIG_IWL4965=m -CONFIG_IWL3945=m - -# -# iwl3945 / iwl4965 Debugging Options -# -CONFIG_IWLEGACY_DEBUG=y -CONFIG_LIBERTAS=m -CONFIG_LIBERTAS_USB=m -CONFIG_LIBERTAS_CS=m -CONFIG_LIBERTAS_SDIO=m -# CONFIG_LIBERTAS_SPI is not set -# CONFIG_LIBERTAS_DEBUG is not set -CONFIG_LIBERTAS_MESH=y -CONFIG_HERMES=m -# CONFIG_HERMES_PRISM is not set -CONFIG_HERMES_CACHE_FW_ON_INIT=y -CONFIG_PLX_HERMES=m -# CONFIG_TMD_HERMES is not set -CONFIG_NORTEL_HERMES=m -CONFIG_PCMCIA_HERMES=m -# CONFIG_PCMCIA_SPECTRUM is not set -CONFIG_ORINOCO_USB=m -CONFIG_P54_COMMON=m -CONFIG_P54_USB=m -CONFIG_P54_PCI=m -# CONFIG_P54_SPI is not set -CONFIG_P54_LEDS=y -CONFIG_RT2X00=m -CONFIG_RT2400PCI=m -CONFIG_RT2500PCI=m -CONFIG_RT61PCI=m -CONFIG_RT2800PCI=m -CONFIG_RT2800PCI_RT33XX=y -CONFIG_RT2800PCI_RT35XX=y -CONFIG_RT2800PCI_RT53XX=y -CONFIG_RT2800PCI_RT3290=y -CONFIG_RT2500USB=m -CONFIG_RT73USB=m -CONFIG_RT2800USB=m -CONFIG_RT2800USB_RT33XX=y -CONFIG_RT2800USB_RT35XX=y -CONFIG_RT2800USB_RT3573=y -CONFIG_RT2800USB_RT53XX=y -CONFIG_RT2800USB_RT55XX=y -CONFIG_RT2800USB_UNKNOWN=y -CONFIG_RT2800_LIB=m -CONFIG_RT2800_LIB_MMIO=m -CONFIG_RT2X00_LIB_MMIO=m -CONFIG_RT2X00_LIB_PCI=m -CONFIG_RT2X00_LIB_USB=m -CONFIG_RT2X00_LIB=m -CONFIG_RT2X00_LIB_FIRMWARE=y -CONFIG_RT2X00_LIB_CRYPTO=y -CONFIG_RT2X00_LIB_LEDS=y -# CONFIG_RT2X00_DEBUG is not set -CONFIG_RTL_CARDS=m -CONFIG_RTL8192CE=m -CONFIG_RTL8192SE=m -CONFIG_RTL8192DE=m -CONFIG_RTL8723AE=m -CONFIG_RTL8188EE=m -CONFIG_RTL8192CU=m -CONFIG_RTLWIFI=m -CONFIG_RTLWIFI_PCI=m -CONFIG_RTLWIFI_USB=m -CONFIG_RTLWIFI_DEBUG=y -CONFIG_RTL8192C_COMMON=m +# CONFIG_IWLWIFI is not set +# CONFIG_IWL4965 is not set +# CONFIG_IWL3945 is not set +# CONFIG_LIBERTAS is not set +# CONFIG_HERMES is not set +# CONFIG_P54_COMMON is not set +# CONFIG_RT2X00 is not set +CONFIG_RTL_CARDS=y +# CONFIG_RTL8192CE is not set +# CONFIG_RTL8192SE is not set +# CONFIG_RTL8192DE is not set +# CONFIG_RTL8723AE is not set +# CONFIG_RTL8723BE is not set +# CONFIG_RTL8188EE is not set +# CONFIG_RTL8192EE is not set +# CONFIG_RTL8821AE is not set +# CONFIG_RTL8192CU is not set # CONFIG_WL_TI is not set -CONFIG_ZD1211RW=m -# CONFIG_ZD1211RW_DEBUG is not set -CONFIG_MWIFIEX=m -CONFIG_MWIFIEX_SDIO=m -CONFIG_MWIFIEX_PCIE=m -CONFIG_MWIFIEX_USB=m -CONFIG_CW1200=m -CONFIG_CW1200_WLAN_SDIO=m -CONFIG_CW1200_WLAN_SPI=m +# CONFIG_ZD1211RW is not set +# CONFIG_MWIFIEX is not set +# CONFIG_CW1200 is not set +# CONFIG_RSI_91X is not set # # Enable WiMAX (Networking options) to see the WiMAX drivers # # CONFIG_WAN is not set -CONFIG_IEEE802154_DRIVERS=m -CONFIG_IEEE802154_FAKEHARD=m -CONFIG_IEEE802154_FAKELB=m -# CONFIG_IEEE802154_AT86RF230 is not set -# CONFIG_IEEE802154_MRF24J40 is not set # CONFIG_VMXNET3 is not set -CONFIG_ISDN=y -CONFIG_ISDN_I4L=m -CONFIG_ISDN_PPP=y -CONFIG_ISDN_PPP_VJ=y -CONFIG_ISDN_MPP=y -CONFIG_IPPP_FILTER=y -# CONFIG_ISDN_PPP_BSDCOMP is not set -CONFIG_ISDN_AUDIO=y -CONFIG_ISDN_TTY_FAX=y - -# -# ISDN feature submodules -# -CONFIG_ISDN_DIVERSION=m - -# -# ISDN4Linux hardware drivers -# - -# -# Passive cards -# -CONFIG_ISDN_DRV_HISAX=m - -# -# D-channel protocol features -# -CONFIG_HISAX_EURO=y -CONFIG_DE_AOC=y -CONFIG_HISAX_NO_SENDCOMPLETE=y -CONFIG_HISAX_NO_LLC=y -CONFIG_HISAX_NO_KEYPAD=y -CONFIG_HISAX_1TR6=y -CONFIG_HISAX_NI1=y -CONFIG_HISAX_MAX_CARDS=8 - -# -# HiSax supported cards -# -CONFIG_HISAX_16_3=y -CONFIG_HISAX_TELESPCI=y -CONFIG_HISAX_S0BOX=y -CONFIG_HISAX_FRITZPCI=y -CONFIG_HISAX_AVM_A1_PCMCIA=y -CONFIG_HISAX_ELSA=y -CONFIG_HISAX_DIEHLDIVA=y -CONFIG_HISAX_SEDLBAUER=y -CONFIG_HISAX_NICCY=y -CONFIG_HISAX_BKM_A4T=y -CONFIG_HISAX_SCT_QUADRO=y -CONFIG_HISAX_GAZEL=y -CONFIG_HISAX_HFC_PCI=y -CONFIG_HISAX_W6692=y -CONFIG_HISAX_HFC_SX=y -# CONFIG_HISAX_DEBUG is not set - -# -# HiSax PCMCIA card service modules -# -CONFIG_HISAX_SEDLBAUER_CS=m -CONFIG_HISAX_ELSA_CS=m -CONFIG_HISAX_AVM_A1_CS=m -CONFIG_HISAX_TELES_CS=m - -# -# HiSax sub driver modules -# -CONFIG_HISAX_ST5481=m -# CONFIG_HISAX_HFCUSB is not set -CONFIG_HISAX_HFC4S8S=m -CONFIG_HISAX_FRITZ_PCIPNP=m - -# -# Active cards -# -CONFIG_ISDN_CAPI=m -CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y -# CONFIG_CAPI_TRACE is not set -CONFIG_ISDN_CAPI_CAPI20=m -CONFIG_ISDN_CAPI_MIDDLEWARE=y -CONFIG_ISDN_CAPI_CAPIDRV=m - -# -# CAPI hardware drivers -# -CONFIG_CAPI_AVM=y -CONFIG_ISDN_DRV_AVMB1_B1PCI=m -CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y -CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m -CONFIG_ISDN_DRV_AVMB1_AVM_CS=m -CONFIG_ISDN_DRV_AVMB1_T1PCI=m -CONFIG_ISDN_DRV_AVMB1_C4=m -# CONFIG_CAPI_EICON is not set -CONFIG_ISDN_DRV_GIGASET=m -CONFIG_GIGASET_CAPI=y -# CONFIG_GIGASET_I4L is not set -# CONFIG_GIGASET_DUMMYLL is not set -CONFIG_GIGASET_BASE=m -CONFIG_GIGASET_M105=m -CONFIG_GIGASET_M101=m -# CONFIG_GIGASET_DEBUG is not set -CONFIG_HYSDN=m -CONFIG_HYSDN_CAPI=y -CONFIG_MISDN=m -CONFIG_MISDN_DSP=m -CONFIG_MISDN_L1OIP=m - -# -# mISDN hardware drivers -# -CONFIG_MISDN_HFCPCI=m -CONFIG_MISDN_HFCMULTI=m -CONFIG_MISDN_HFCUSB=m -CONFIG_MISDN_AVMFRITZ=m -CONFIG_MISDN_SPEEDFAX=m -CONFIG_MISDN_INFINEON=m -CONFIG_MISDN_W6692=m -CONFIG_MISDN_NETJET=m -CONFIG_MISDN_IPAC=m -CONFIG_MISDN_ISAR=m -CONFIG_ISDN_HDLC=m +# CONFIG_ISDN is not set # # Input device support # CONFIG_INPUT=y -CONFIG_INPUT_FF_MEMLESS=m -CONFIG_INPUT_POLLDEV=m -CONFIG_INPUT_SPARSEKMAP=m +# CONFIG_INPUT_FF_MEMLESS is not set +CONFIG_INPUT_POLLDEV=y +# CONFIG_INPUT_SPARSEKMAP is not set CONFIG_INPUT_MATRIXKMAP=y # @@ -2466,9 +1695,9 @@ CONFIG_INPUT_MOUSEDEV=y # CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_JOYDEV is not set CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_EVBUG is not set +CONFIG_INPUT_EVBUG=m # # Input Device Drivers @@ -2476,11 +1705,12 @@ CONFIG_INPUT_EVDEV=y CONFIG_INPUT_KEYBOARD=y # CONFIG_KEYBOARD_ADP5588 is not set # CONFIG_KEYBOARD_ADP5589 is not set -# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_QT1070 is not set # CONFIG_KEYBOARD_QT2160 is not set # CONFIG_KEYBOARD_LKKBD is not set CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_GPIO_POLLED is not set # CONFIG_KEYBOARD_TCA6416 is not set # CONFIG_KEYBOARD_TCA8418 is not set # CONFIG_KEYBOARD_MATRIX is not set @@ -2495,161 +1725,125 @@ CONFIG_KEYBOARD_IMX=y # CONFIG_KEYBOARD_SAMSUNG is not set # CONFIG_KEYBOARD_STOWAWAY is not set # CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_STMPE is not set +# CONFIG_KEYBOARD_OMAP4 is not set # CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_BCM is not set CONFIG_INPUT_MOUSE=y -# CONFIG_MOUSE_PS2 is not set -CONFIG_MOUSE_SERIAL=m -CONFIG_MOUSE_APPLETOUCH=m -CONFIG_MOUSE_BCM5974=m -CONFIG_MOUSE_CYAPA=m -CONFIG_MOUSE_VSXXXAA=m +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_CYPRESS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +CONFIG_MOUSE_PS2_ELANTECH=y +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_FOCALTECH=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MOUSE_VSXXXAA is not set # CONFIG_MOUSE_GPIO is not set -CONFIG_MOUSE_SYNAPTICS_I2C=m -CONFIG_MOUSE_SYNAPTICS_USB=m -CONFIG_INPUT_JOYSTICK=y -CONFIG_JOYSTICK_ANALOG=m -CONFIG_JOYSTICK_A3D=m -CONFIG_JOYSTICK_ADI=m -CONFIG_JOYSTICK_COBRA=m -CONFIG_JOYSTICK_GF2K=m -CONFIG_JOYSTICK_GRIP=m -CONFIG_JOYSTICK_GRIP_MP=m -CONFIG_JOYSTICK_GUILLEMOT=m -CONFIG_JOYSTICK_INTERACT=m -CONFIG_JOYSTICK_SIDEWINDER=m -CONFIG_JOYSTICK_TMDC=m -CONFIG_JOYSTICK_IFORCE=m -CONFIG_JOYSTICK_IFORCE_USB=y -CONFIG_JOYSTICK_IFORCE_232=y -CONFIG_JOYSTICK_WARRIOR=m -CONFIG_JOYSTICK_MAGELLAN=m -CONFIG_JOYSTICK_SPACEORB=m -CONFIG_JOYSTICK_SPACEBALL=m -CONFIG_JOYSTICK_STINGER=m -CONFIG_JOYSTICK_TWIDJOY=m -CONFIG_JOYSTICK_ZHENHUA=m -CONFIG_JOYSTICK_DB9=m -CONFIG_JOYSTICK_GAMECON=m -CONFIG_JOYSTICK_TURBOGRAFX=m -# CONFIG_JOYSTICK_AS5011 is not set -CONFIG_JOYSTICK_JOYDUMP=m -CONFIG_JOYSTICK_XPAD=m -CONFIG_JOYSTICK_XPAD_FF=y -CONFIG_JOYSTICK_XPAD_LEDS=y -CONFIG_JOYSTICK_WALKERA0701=m -CONFIG_INPUT_TABLET=y -CONFIG_TABLET_USB_ACECAD=m -CONFIG_TABLET_USB_AIPTEK=m -CONFIG_TABLET_USB_GTCO=m -CONFIG_TABLET_USB_HANWANG=m -CONFIG_TABLET_USB_KBTAB=m -CONFIG_TABLET_USB_WACOM=m +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_OF_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_ADS7846 is not set # CONFIG_TOUCHSCREEN_AD7877 is not set # CONFIG_TOUCHSCREEN_AD7879 is not set -CONFIG_TOUCHSCREEN_ATMEL_MXT=m -CONFIG_TOUCHSCREEN_AUO_PIXCIR=m +# CONFIG_TOUCHSCREEN_AR1021_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set # CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_CHIPONE_ICN8318 is not set # CONFIG_TOUCHSCREEN_CY8CTMG110 is not set # CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set # CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set # CONFIG_TOUCHSCREEN_DA9052 is not set -CONFIG_TOUCHSCREEN_DYNAPRO=m +# CONFIG_TOUCHSCREEN_DYNAPRO is not set # CONFIG_TOUCHSCREEN_HAMPSHIRE is not set -CONFIG_TOUCHSCREEN_EETI=m -CONFIG_TOUCHSCREEN_EGALAX=m -CONFIG_TOUCHSCREEN_FUJITSU=m -CONFIG_TOUCHSCREEN_ILI210X=m -CONFIG_TOUCHSCREEN_GUNZE=m -CONFIG_TOUCHSCREEN_ELO=m -CONFIG_TOUCHSCREEN_WACOM_W8001=m -CONFIG_TOUCHSCREEN_WACOM_I2C=m +# CONFIG_TOUCHSCREEN_EETI is not set +CONFIG_TOUCHSCREEN_EGALAX=y +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GOODIX is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set # CONFIG_TOUCHSCREEN_MAX11801 is not set -CONFIG_TOUCHSCREEN_MCS5000=m -CONFIG_TOUCHSCREEN_MMS114=m -CONFIG_TOUCHSCREEN_MTOUCH=m -CONFIG_TOUCHSCREEN_INEXIO=m -CONFIG_TOUCHSCREEN_MK712=m -CONFIG_TOUCHSCREEN_PENMOUNT=m -CONFIG_TOUCHSCREEN_EDT_FT5X06=m -CONFIG_TOUCHSCREEN_TOUCHRIGHT=m -CONFIG_TOUCHSCREEN_TOUCHWIN=m -CONFIG_TOUCHSCREEN_PIXCIR=m +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set # CONFIG_TOUCHSCREEN_WM97XX is not set -CONFIG_TOUCHSCREEN_USB_COMPOSITE=m -# CONFIG_TOUCHSCREEN_MC13783 is not set -CONFIG_TOUCHSCREEN_USB_EGALAX=y -CONFIG_TOUCHSCREEN_USB_PANJIT=y -CONFIG_TOUCHSCREEN_USB_3M=y -CONFIG_TOUCHSCREEN_USB_ITM=y -CONFIG_TOUCHSCREEN_USB_ETURBO=y -CONFIG_TOUCHSCREEN_USB_GUNZE=y -CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y -CONFIG_TOUCHSCREEN_USB_IRTOUCH=y -CONFIG_TOUCHSCREEN_USB_IDEALTEK=y -CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y -CONFIG_TOUCHSCREEN_USB_GOTOP=y -CONFIG_TOUCHSCREEN_USB_JASTEC=y -CONFIG_TOUCHSCREEN_USB_ELO=y -CONFIG_TOUCHSCREEN_USB_E2I=y -CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y -CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y -CONFIG_TOUCHSCREEN_USB_NEXIO=y -CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y -CONFIG_TOUCHSCREEN_TOUCHIT213=m -CONFIG_TOUCHSCREEN_TSC_SERIO=m +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +CONFIG_TOUCHSCREEN_MC13783=y +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set # CONFIG_TOUCHSCREEN_TSC2005 is not set -CONFIG_TOUCHSCREEN_TSC2007=m -CONFIG_TOUCHSCREEN_W90X900=m -CONFIG_TOUCHSCREEN_ST1232=m +CONFIG_TOUCHSCREEN_TSC2007=y +# CONFIG_TOUCHSCREEN_ST1232 is not set +CONFIG_TOUCHSCREEN_STMPE=y # CONFIG_TOUCHSCREEN_SUR40 is not set +# CONFIG_TOUCHSCREEN_SX8654 is not set # CONFIG_TOUCHSCREEN_TPS6507X is not set -CONFIG_TOUCHSCREEN_ZFORCE=m +# CONFIG_TOUCHSCREEN_ZFORCE is not set CONFIG_INPUT_MISC=y # CONFIG_INPUT_AD714X is not set # CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_E3X0_BUTTON is not set # CONFIG_INPUT_MC13783_PWRBUTTON is not set -CONFIG_INPUT_MMA8450=m -CONFIG_INPUT_MPU3050=m -CONFIG_INPUT_GP2A=m +CONFIG_INPUT_MMA8450=y +# CONFIG_INPUT_MPU3050 is not set +# CONFIG_INPUT_GP2A is not set # CONFIG_INPUT_GPIO_BEEPER is not set # CONFIG_INPUT_GPIO_TILT_POLLED is not set -CONFIG_INPUT_ATI_REMOTE2=m -CONFIG_INPUT_KEYSPAN_REMOTE=m -CONFIG_INPUT_KXTJ9=m -# CONFIG_INPUT_KXTJ9_POLLED_MODE is not set -CONFIG_INPUT_POWERMATE=m -CONFIG_INPUT_YEALINK=m -CONFIG_INPUT_CM109=m -CONFIG_INPUT_UINPUT=m +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_REGULATOR_HAPTIC is not set +# CONFIG_INPUT_UINPUT is not set # CONFIG_INPUT_PCF8574 is not set -CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set # CONFIG_INPUT_DA9052_ONKEY is not set # CONFIG_INPUT_ADXL34X is not set # CONFIG_INPUT_IMS_PCU is not set -CONFIG_INPUT_CMA3000=m -CONFIG_INPUT_CMA3000_I2C=m +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set # # Hardware I/O ports # CONFIG_SERIO=y CONFIG_SERIO_SERPORT=m -# CONFIG_SERIO_PARKBD is not set # CONFIG_SERIO_PCIPS2 is not set -# CONFIG_SERIO_LIBPS2 is not set -CONFIG_SERIO_RAW=m -CONFIG_SERIO_ALTERA_PS2=m +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set # CONFIG_SERIO_PS2MULT is not set -CONFIG_SERIO_ARC_PS2=m +# CONFIG_SERIO_ARC_PS2 is not set # CONFIG_SERIO_APBPS2 is not set -# CONFIG_SERIO_OLPC_APSP is not set -CONFIG_GAMEPORT=m -CONFIG_GAMEPORT_NS558=m -CONFIG_GAMEPORT_L4=m -CONFIG_GAMEPORT_EMU10K1=m -CONFIG_GAMEPORT_FM801=m +# CONFIG_GAMEPORT is not set # # Character devices @@ -2662,108 +1856,60 @@ CONFIG_VT_CONSOLE_SLEEP=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y CONFIG_UNIX98_PTYS=y -CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_NONSTANDARD=y -CONFIG_ROCKETPORT=m -CONFIG_CYCLADES=m -# CONFIG_CYZ_INTR is not set -# CONFIG_MOXA_INTELLIO is not set -# CONFIG_MOXA_SMARTIO is not set -CONFIG_SYNCLINKMP=m -CONFIG_SYNCLINK_GT=m -CONFIG_NOZOMI=m -# CONFIG_ISI is not set -CONFIG_N_HDLC=m -CONFIG_N_GSM=m +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set # CONFIG_TRACE_SINK is not set +CONFIG_DEVMEM=y # CONFIG_DEVKMEM is not set # # Serial drivers # -CONFIG_SERIAL_8250=y -# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_DMA=y -CONFIG_SERIAL_8250_PCI=y -CONFIG_SERIAL_8250_CS=m -CONFIG_SERIAL_8250_NR_UARTS=32 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -CONFIG_SERIAL_8250_EXTENDED=y -CONFIG_SERIAL_8250_MANY_PORTS=y -CONFIG_SERIAL_8250_SHARE_IRQ=y -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -CONFIG_SERIAL_8250_RSA=y -# CONFIG_SERIAL_8250_DW is not set -# CONFIG_SERIAL_8250_EM is not set +# CONFIG_SERIAL_8250 is not set # # Non-8250 serial port support # +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set # CONFIG_SERIAL_MAX3100 is not set # CONFIG_SERIAL_MAX310X is not set -# CONFIG_SERIAL_MFD_HSU is not set CONFIG_SERIAL_IMX=y CONFIG_SERIAL_IMX_CONSOLE=y -# CONFIG_SERIAL_SH_SCI is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_SERIAL_JSM=m -# CONFIG_SERIAL_OF_PLATFORM is not set +# CONFIG_SERIAL_JSM is not set # CONFIG_SERIAL_SCCNXP is not set -# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_BCM63XX is not set # CONFIG_SERIAL_ALTERA_JTAGUART is not set # CONFIG_SERIAL_ALTERA_UART is not set # CONFIG_SERIAL_IFX6X60 is not set -# CONFIG_SERIAL_PCH_UART is not set # CONFIG_SERIAL_XILINX_PS_UART is not set -CONFIG_SERIAL_ARC=m -CONFIG_SERIAL_ARC_NR_PORTS=1 +# CONFIG_SERIAL_ARC is not set # CONFIG_SERIAL_RP2 is not set CONFIG_SERIAL_FSL_LPUART=y CONFIG_SERIAL_FSL_LPUART_CONSOLE=y +# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set # CONFIG_SERIAL_ST_ASC is not set # CONFIG_TTY_PRINTK is not set -CONFIG_FSL_OTP=y -CONFIG_PRINTER=m -CONFIG_LP_CONSOLE=y -CONFIG_PPDEV=m -CONFIG_HVC_DRIVER=y # CONFIG_HVC_DCC is not set -CONFIG_VIRTIO_CONSOLE=m -CONFIG_IPMI_HANDLER=m -# CONFIG_IPMI_PANIC_EVENT is not set -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_SI=m -CONFIG_IPMI_WATCHDOG=m -CONFIG_IPMI_POWEROFF=m +# CONFIG_IPMI_HANDLER is not set CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_TIMERIOMEM=m -# CONFIG_HW_RANDOM_ATMEL is not set -CONFIG_HW_RANDOM_VIRTIO=m -# CONFIG_HW_RANDOM_EXYNOS is not set -CONFIG_HW_RANDOM_TPM=m -# CONFIG_NVRAM is not set -CONFIG_R3964=m +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +CONFIG_HW_RANDOM_MXC_RNGA=y +# CONFIG_R3964 is not set # CONFIG_APPLICOM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +# CONFIG_XILLYBUS is not set # -# PCMCIA character devices +# I2C support # -# CONFIG_SYNCLINK_CS is not set -CONFIG_CARDMAN_4000=m -CONFIG_CARDMAN_4040=m -CONFIG_IPWIRELESS=m -CONFIG_RAW_DRIVER=y -CONFIG_MAX_RAW_DEVS=8192 -CONFIG_TCG_TPM=m -# CONFIG_TCG_TIS_I2C_ATMEL is not set -# CONFIG_TCG_TIS_I2C_INFINEON is not set -# CONFIG_TCG_TIS_I2C_NUVOTON is not set -CONFIG_TCG_ATMEL=m -# CONFIG_TCG_ST33_I2C is not set -CONFIG_DEVPORT=y CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y # CONFIG_I2C_COMPAT is not set @@ -2779,7 +1925,7 @@ CONFIG_I2C_MUX=y # CONFIG_I2C_MUX_PCA954x is not set # CONFIG_I2C_MUX_PINCTRL is not set # CONFIG_I2C_HELPER_AUTO is not set -CONFIG_I2C_SMBUS=m +# CONFIG_I2C_SMBUS is not set # # I2C Algorithms @@ -2803,7 +1949,7 @@ CONFIG_I2C_ALGOPCA=m # CONFIG_I2C_I801 is not set # CONFIG_I2C_ISCH is not set # CONFIG_I2C_PIIX4 is not set -CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set @@ -2816,30 +1962,29 @@ CONFIG_I2C_NFORCE2=m # CONFIG_I2C_CBUS_GPIO is not set # CONFIG_I2C_DESIGNWARE_PLATFORM is not set # CONFIG_I2C_DESIGNWARE_PCI is not set -# CONFIG_I2C_EG20T is not set # CONFIG_I2C_GPIO is not set CONFIG_I2C_IMX=y # CONFIG_I2C_OCORES is not set -CONFIG_I2C_PCA_PLATFORM=m +# CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_PXA_PCI is not set -CONFIG_I2C_SIMTEC=m +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_SIMTEC is not set # CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers # -CONFIG_I2C_DIOLAN_U2C=m -CONFIG_I2C_PARPORT=m -CONFIG_I2C_PARPORT_LIGHT=m +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_ROBOTFUZZ_OSIF is not set # CONFIG_I2C_TAOS_EVM is not set -CONFIG_I2C_TINY_USB=m -CONFIG_I2C_VIPERBOARD=m +# CONFIG_I2C_TINY_USB is not set # # Other I2C/SMBus bus drivers # -CONFIG_I2C_STUB=m +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_SLAVE is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -2852,16 +1997,16 @@ CONFIG_SPI_MASTER=y # # CONFIG_SPI_ALTERA is not set CONFIG_SPI_BITBANG=y -# CONFIG_SPI_BUTTERFLY is not set +# CONFIG_SPI_CADENCE is not set # CONFIG_SPI_GPIO is not set CONFIG_SPI_IMX=y -# CONFIG_SPI_LM70_LLP is not set # CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_FSL_DSPI is not set # CONFIG_SPI_OC_TINY is not set # CONFIG_SPI_PXA2XX is not set # CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_ROCKCHIP is not set # CONFIG_SPI_SC18IS602 is not set -# CONFIG_SPI_TOPCLIFF_PCH is not set # CONFIG_SPI_XCOMM is not set # CONFIG_SPI_XILINX is not set # CONFIG_SPI_DESIGNWARE is not set @@ -2869,8 +2014,9 @@ CONFIG_SPI_IMX=y # # SPI Protocol Masters # -CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_SPIDEV is not set # CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPMI is not set # CONFIG_HSI is not set # @@ -2883,9 +2029,8 @@ CONFIG_PPS=y # PPS clients support # # CONFIG_PPS_CLIENT_KTIMER is not set -CONFIG_PPS_CLIENT_LDISC=m -CONFIG_PPS_CLIENT_PARPORT=m -CONFIG_PPS_CLIENT_GPIO=m +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set # # PPS generators support @@ -2895,7 +2040,10 @@ CONFIG_PPS_CLIENT_GPIO=m # PTP clock support # CONFIG_PTP_1588_CLOCK=y -CONFIG_DP83640_PHY=m + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# CONFIG_PINCTRL=y # @@ -2904,114 +2052,87 @@ CONFIG_PINCTRL=y CONFIG_PINMUX=y CONFIG_PINCONF=y # CONFIG_DEBUG_PINCTRL is not set -# CONFIG_PINCTRL_CAPRI is not set +# CONFIG_PINCTRL_AMD is not set +# CONFIG_PINCTRL_SINGLE is not set CONFIG_PINCTRL_IMX=y +CONFIG_PINCTRL_IMX35=y +CONFIG_PINCTRL_IMX50=y +CONFIG_PINCTRL_IMX51=y +CONFIG_PINCTRL_IMX53=y CONFIG_PINCTRL_IMX6Q=y CONFIG_PINCTRL_IMX6SL=y -# CONFIG_PINCTRL_MSM8X74 is not set -# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PINCTRL_IMX6SX=y +CONFIG_PINCTRL_VF610=y CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y CONFIG_GPIO_DEVRES=y CONFIG_OF_GPIO=y +CONFIG_GPIOLIB_IRQCHIP=y # CONFIG_DEBUG_GPIO is not set CONFIG_GPIO_SYSFS=y CONFIG_GPIO_GENERIC=y -# CONFIG_GPIO_DA9052 is not set -CONFIG_GPIO_MAX730X=m # -# Memory mapped GPIO drivers: +# Memory mapped GPIO drivers # -# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_DWAPB is not set # CONFIG_GPIO_EM is not set -CONFIG_GPIO_MXC=y -# CONFIG_GPIO_RCAR is not set -# CONFIG_GPIO_SCH311X is not set -# CONFIG_GPIO_TS5500 is not set -# CONFIG_GPIO_VX855 is not set +# CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_GRGPIO is not set +CONFIG_GPIO_MXC=y +# CONFIG_GPIO_SCH311X is not set +# CONFIG_GPIO_SYSCON is not set +CONFIG_GPIO_VF610=y +# CONFIG_GPIO_VX855 is not set +# CONFIG_GPIO_ZEVIO is not set # -# I2C GPIO expanders: +# I2C GPIO expanders # -CONFIG_GPIO_MAX7300=m -CONFIG_GPIO_MAX732X=m +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +CONFIG_GPIO_MC9S08DZ60=y +CONFIG_GPIO_PCA953X=y # CONFIG_GPIO_PCA953X_IRQ is not set -CONFIG_GPIO_PCF857X=m -CONFIG_GPIO_SX150X=y -CONFIG_GPIO_ADP5588=m -CONFIG_GPIO_ADNP=m +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set # -# PCI GPIO expanders: +# MFD GPIO expanders +# +# CONFIG_GPIO_DA9052 is not set +CONFIG_GPIO_STMPE=y + +# +# PCI GPIO expanders # # CONFIG_GPIO_AMD8111 is not set +# CONFIG_GPIO_BT8XX is not set # CONFIG_GPIO_ML_IOH is not set # CONFIG_GPIO_RDC321X is not set # -# SPI GPIO expanders: +# SPI GPIO expanders # -CONFIG_GPIO_MAX7301=m -CONFIG_GPIO_MCP23S08=m -CONFIG_GPIO_MC33880=m -CONFIG_GPIO_74X164=m +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set # -# AC97 GPIO expanders: +# USB GPIO expanders # - -# -# LPC GPIO expanders: -# - -# -# MODULbus GPIO expanders: -# -# CONFIG_GPIO_BCM_KONA is not set - -# -# USB GPIO expanders: -# -CONFIG_GPIO_VIPERBOARD=m -CONFIG_W1=m -CONFIG_W1_CON=y - -# -# 1-wire Bus Masters -# -# CONFIG_W1_MASTER_MATROX is not set -CONFIG_W1_MASTER_DS2490=m -CONFIG_W1_MASTER_DS2482=m -# CONFIG_W1_MASTER_MXC is not set -CONFIG_W1_MASTER_DS1WM=m -CONFIG_W1_MASTER_GPIO=m - -# -# 1-wire Slaves -# -CONFIG_W1_SLAVE_THERM=m -CONFIG_W1_SLAVE_SMEM=m -CONFIG_W1_SLAVE_DS2408=m -# CONFIG_W1_SLAVE_DS2408_READBACK is not set -CONFIG_W1_SLAVE_DS2413=m -CONFIG_W1_SLAVE_DS2423=m -CONFIG_W1_SLAVE_DS2431=m -CONFIG_W1_SLAVE_DS2433=m -CONFIG_W1_SLAVE_DS2433_CRC=y -CONFIG_W1_SLAVE_DS2760=m -CONFIG_W1_SLAVE_DS2780=m -CONFIG_W1_SLAVE_DS2781=m -CONFIG_W1_SLAVE_DS28E04=m -CONFIG_W1_SLAVE_BQ27000=m +# CONFIG_W1 is not set CONFIG_POWER_SUPPLY=y # CONFIG_POWER_SUPPLY_DEBUG is not set # CONFIG_PDA_POWER is not set -# CONFIG_GENERIC_ADC_BATTERY is not set # CONFIG_TEST_POWER is not set -# CONFIG_BATTERY_DS2760 is not set # CONFIG_BATTERY_DS2780 is not set # CONFIG_BATTERY_DS2781 is not set # CONFIG_BATTERY_DS2782 is not set @@ -3028,155 +2149,159 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_BQ24190 is not set # CONFIG_CHARGER_BQ24735 is not set -CONFIG_CHARGER_SMB347=m -# CONFIG_IMX6_USB_CHARGER is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_BATTERY_GAUGE_LTC2941 is not set CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_BRCMSTB is not set # CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +CONFIG_POWER_RESET_IMX=y +# CONFIG_POWER_RESET_LTC2952 is not set # CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_RESET_VERSATILE is not set +CONFIG_POWER_RESET_SYSCON=y +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set # CONFIG_POWER_AVS is not set CONFIG_HWMON=y -CONFIG_HWMON_VID=m +# CONFIG_HWMON_VID is not set # CONFIG_HWMON_DEBUG_CHIP is not set # # Native drivers # # CONFIG_SENSORS_AD7314 is not set -CONFIG_SENSORS_AD7414=m -CONFIG_SENSORS_AD7418=m -# CONFIG_SENSORS_ADCXX is not set -CONFIG_SENSORS_ADM1021=m -CONFIG_SENSORS_ADM1025=m -CONFIG_SENSORS_ADM1026=m -CONFIG_SENSORS_ADM1029=m -CONFIG_SENSORS_ADM1031=m -CONFIG_SENSORS_ADM9240=m -CONFIG_SENSORS_ADT7X10=m -CONFIG_SENSORS_ADT7310=m -CONFIG_SENSORS_ADT7410=m -CONFIG_SENSORS_ADT7411=m -CONFIG_SENSORS_ADT7462=m -CONFIG_SENSORS_ADT7470=m -CONFIG_SENSORS_ADT7475=m -CONFIG_SENSORS_ASC7621=m -CONFIG_SENSORS_ATXP1=m -CONFIG_SENSORS_DS620=m -CONFIG_SENSORS_DS1621=m +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_DA9052_ADC is not set # CONFIG_SENSORS_I5K_AMB is not set -CONFIG_SENSORS_F71805F=m -CONFIG_SENSORS_F71882FG=m -CONFIG_SENSORS_F75375S=m -CONFIG_SENSORS_G760A=m -CONFIG_SENSORS_G762=m -CONFIG_SENSORS_GL518SM=m -CONFIG_SENSORS_GL520SM=m -# CONFIG_SENSORS_GPIO_FAN is not set -# CONFIG_SENSORS_HIH6130 is not set -# CONFIG_SENSORS_HTU21 is not set -CONFIG_SENSORS_IBMAEM=m -CONFIG_SENSORS_IBMPEX=m -# CONFIG_SENSORS_IIO_HWMON is not set -CONFIG_SENSORS_IT87=m -# CONFIG_SENSORS_JC42 is not set -CONFIG_SENSORS_LINEAGE=m -CONFIG_SENSORS_LM63=m -# CONFIG_SENSORS_LM70 is not set -CONFIG_SENSORS_LM73=m -CONFIG_SENSORS_LM75=m -CONFIG_SENSORS_LM77=m -CONFIG_SENSORS_LM78=m -CONFIG_SENSORS_LM80=m -CONFIG_SENSORS_LM83=m -CONFIG_SENSORS_LM85=m -CONFIG_SENSORS_LM87=m -CONFIG_SENSORS_LM90=m -CONFIG_SENSORS_LM92=m -CONFIG_SENSORS_LM93=m -CONFIG_SENSORS_LTC4151=m -CONFIG_SENSORS_LTC4215=m -CONFIG_SENSORS_LTC4245=m -CONFIG_SENSORS_LTC4261=m -CONFIG_SENSORS_LM95234=m -CONFIG_SENSORS_LM95241=m -CONFIG_SENSORS_LM95245=m -# CONFIG_SENSORS_MAX1111 is not set -CONFIG_SENSORS_MAX16065=m -CONFIG_SENSORS_MAX1619=m -CONFIG_SENSORS_MAX1668=m -CONFIG_SENSORS_MAX197=m -CONFIG_SENSORS_MAX6639=m -CONFIG_SENSORS_MAX6642=m -CONFIG_SENSORS_MAX6650=m -CONFIG_SENSORS_MAX6697=m -CONFIG_SENSORS_MCP3021=m -CONFIG_SENSORS_NCT6775=m -CONFIG_SENSORS_NTC_THERMISTOR=m -CONFIG_SENSORS_PC87360=m -CONFIG_SENSORS_PC87427=m -CONFIG_SENSORS_PCF8591=m -CONFIG_PMBUS=m -CONFIG_SENSORS_PMBUS=m -CONFIG_SENSORS_ADM1275=m -CONFIG_SENSORS_LM25066=m -CONFIG_SENSORS_LTC2978=m -CONFIG_SENSORS_MAX16064=m -CONFIG_SENSORS_MAX34440=m -CONFIG_SENSORS_MAX8688=m -CONFIG_SENSORS_UCD9000=m -CONFIG_SENSORS_UCD9200=m -CONFIG_SENSORS_ZL6100=m -CONFIG_SENSORS_SHT15=m -CONFIG_SENSORS_SHT21=m -CONFIG_SENSORS_SIS5595=m -# CONFIG_SENSORS_SMM665 is not set -CONFIG_SENSORS_DME1737=m -CONFIG_SENSORS_EMC1403=m -# CONFIG_SENSORS_EMC2103 is not set -CONFIG_SENSORS_EMC6W201=m -CONFIG_SENSORS_SMSC47M1=m -CONFIG_SENSORS_SMSC47M192=m -CONFIG_SENSORS_SMSC47B397=m -CONFIG_SENSORS_SCH56XX_COMMON=m -CONFIG_SENSORS_SCH5627=m -CONFIG_SENSORS_SCH5636=m -CONFIG_SENSORS_ADS1015=m -CONFIG_SENSORS_ADS7828=m -# CONFIG_SENSORS_ADS7871 is not set -CONFIG_SENSORS_AMC6821=m -CONFIG_SENSORS_INA209=m -CONFIG_SENSORS_INA2XX=m -CONFIG_SENSORS_THMC50=m -CONFIG_SENSORS_TMP102=m -CONFIG_SENSORS_TMP401=m -CONFIG_SENSORS_TMP421=m -CONFIG_SENSORS_VIA686A=m -CONFIG_SENSORS_VT1211=m -CONFIG_SENSORS_VT8231=m -CONFIG_SENSORS_W83781D=m -CONFIG_SENSORS_W83791D=m -CONFIG_SENSORS_W83792D=m -CONFIG_SENSORS_W83793=m -CONFIG_SENSORS_W83795=m -# CONFIG_SENSORS_W83795_FANCTRL is not set -CONFIG_SENSORS_W83L785TS=m -CONFIG_SENSORS_W83L786NG=m -CONFIG_SENSORS_W83627HF=m -CONFIG_SENSORS_W83627EHF=m +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set # CONFIG_SENSORS_MC13783_ADC is not set -# CONFIG_SENSORS_MAG3110 is not set -# CONFIG_MXC_MMA8451 is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +CONFIG_SENSORS_GPIO_FAN=y +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_HTU21 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_PWM_FAN is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set CONFIG_THERMAL=y CONFIG_THERMAL_HWMON=y -# CONFIG_THERMAL_OF is not set +CONFIG_THERMAL_OF=y CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y # CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set # CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set -CONFIG_THERMAL_GOV_FAIR_SHARE=y +# CONFIG_THERMAL_GOV_FAIR_SHARE is not set CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_BANG_BANG is not set # CONFIG_THERMAL_GOV_USER_SPACE is not set +CONFIG_CPU_THERMAL=y +# CONFIG_CLOCK_THERMAL is not set # CONFIG_THERMAL_EMULATION is not set -CONFIG_DEVICE_THERMAL=y +CONFIG_IMX_THERMAL=y # # Texas Instruments thermal drivers @@ -3188,59 +2313,40 @@ CONFIG_WATCHDOG_CORE=y # # Watchdog Device Drivers # -CONFIG_SOFT_WATCHDOG=m +# CONFIG_SOFT_WATCHDOG is not set # CONFIG_DA9052_WATCHDOG is not set # CONFIG_GPIO_WATCHDOG is not set +# CONFIG_XILINX_WATCHDOG is not set +# CONFIG_CADENCE_WATCHDOG is not set # CONFIG_DW_WATCHDOG is not set # CONFIG_MAX63XX_WATCHDOG is not set CONFIG_IMX2_WDT=y -CONFIG_ALIM7101_WDT=m -CONFIG_I6300ESB_WDT=m +# CONFIG_ALIM7101_WDT is not set +# CONFIG_I6300ESB_WDT is not set # CONFIG_MEN_A21_WDT is not set # # PCI-based Watchdog Cards # -CONFIG_PCIPCWATCHDOG=m -CONFIG_WDTPCI=m +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set # # USB-based Watchdog Cards # -CONFIG_USBPCWATCHDOG=m +# CONFIG_USBPCWATCHDOG is not set CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB=m -CONFIG_SSB_SPROM=y -CONFIG_SSB_BLOCKIO=y -CONFIG_SSB_PCIHOST_POSSIBLE=y -CONFIG_SSB_PCIHOST=y -CONFIG_SSB_B43_PCI_BRIDGE=y -CONFIG_SSB_PCMCIAHOST_POSSIBLE=y -CONFIG_SSB_PCMCIAHOST=y -CONFIG_SSB_SDIOHOST_POSSIBLE=y -CONFIG_SSB_SDIOHOST=y -# CONFIG_SSB_SILENT is not set -# CONFIG_SSB_DEBUG is not set -CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y -CONFIG_SSB_DRIVER_PCICORE=y -CONFIG_SSB_DRIVER_GPIO=y +# CONFIG_SSB is not set CONFIG_BCMA_POSSIBLE=y # # Broadcom specific AMBA # -CONFIG_BCMA=m -CONFIG_BCMA_BLOCKIO=y -CONFIG_BCMA_HOST_PCI_POSSIBLE=y -CONFIG_BCMA_HOST_PCI=y -# CONFIG_BCMA_HOST_SOC is not set -CONFIG_BCMA_DRIVER_GMAC_CMN=y -CONFIG_BCMA_DRIVER_GPIO=y -# CONFIG_BCMA_DEBUG is not set +# CONFIG_BCMA is not set # # Multifunction device drivers @@ -3250,6 +2356,9 @@ CONFIG_MFD_CORE=y # CONFIG_MFD_AS3722 is not set # CONFIG_PMIC_ADP5520 is not set # CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_ATMEL_HLCDC is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_AXP20X is not set # CONFIG_MFD_CROS_EC is not set # CONFIG_MFD_ASIC3 is not set # CONFIG_PMIC_DA903X is not set @@ -3258,15 +2367,18 @@ CONFIG_PMIC_DA9052=y CONFIG_MFD_DA9052_I2C=y # CONFIG_MFD_DA9055 is not set # CONFIG_MFD_DA9063 is not set -CONFIG_MFD_MXC_HDMI=y +# CONFIG_MFD_DA9150 is not set +# CONFIG_MFD_DLN2 is not set CONFIG_MFD_MC13XXX=y CONFIG_MFD_MC13XXX_SPI=y CONFIG_MFD_MC13XXX_I2C=y +# CONFIG_MFD_HI6421_PMIC is not set # CONFIG_HTC_EGPIO is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_HTC_I2CPLD is not set # CONFIG_LPC_ICH is not set # CONFIG_LPC_SCH is not set +# CONFIG_INTEL_SOC_PMIC is not set # CONFIG_MFD_JANZ_CMODIO is not set # CONFIG_MFD_KEMPLD is not set # CONFIG_MFD_88PM800 is not set @@ -3275,25 +2387,39 @@ CONFIG_MFD_MC13XXX_I2C=y # CONFIG_MFD_MAX14577 is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_MENF21BMC is not set # CONFIG_EZX_PCAP is not set -CONFIG_MFD_VIPERBOARD=m +# CONFIG_MFD_VIPERBOARD is not set # CONFIG_MFD_RETU is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_UCB1400_CORE is not set +# CONFIG_MFD_PM8921_CORE is not set # CONFIG_MFD_RDC321X is not set -CONFIG_MFD_RTSX_PCI=m +# CONFIG_MFD_RTSX_PCI is not set +# CONFIG_MFD_RT5033 is not set +# CONFIG_MFD_RTSX_USB is not set # CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK808 is not set +# CONFIG_MFD_RN5T618 is not set # CONFIG_MFD_SEC_CORE is not set -CONFIG_MFD_SI476X_CORE=y -CONFIG_MFD_SM501=m -CONFIG_MFD_SM501_GPIO=y +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set # CONFIG_MFD_SMSC is not set # CONFIG_ABX500_CORE is not set -# CONFIG_MFD_STMPE is not set +CONFIG_MFD_STMPE=y + +# +# STMicroelectronics STMPE Interface Drivers +# +CONFIG_STMPE_I2C=y +# CONFIG_STMPE_SPI is not set CONFIG_MFD_SYSCON=y # CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_LP3943 is not set @@ -3304,6 +2430,7 @@ CONFIG_MFD_SYSCON=y # CONFIG_TPS6507X is not set # CONFIG_MFD_TPS65090 is not set # CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_TPS65910 is not set # CONFIG_MFD_TPS65912 is not set @@ -3314,13 +2441,12 @@ CONFIG_MFD_SYSCON=y # CONFIG_TWL6040_CORE is not set # CONFIG_MFD_WL1273_CORE is not set # CONFIG_MFD_LM3533 is not set -# CONFIG_MFD_TIMBERDALE is not set # CONFIG_MFD_TC3589X is not set # CONFIG_MFD_TMIO is not set # CONFIG_MFD_T7L66XB is not set # CONFIG_MFD_TC6387XB is not set # CONFIG_MFD_TC6393XB is not set -CONFIG_MFD_VX855=m +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_ARIZONA_SPI is not set # CONFIG_MFD_WM8400 is not set @@ -3328,7 +2454,6 @@ CONFIG_MFD_VX855=m # CONFIG_MFD_WM831X_SPI is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_VEXPRESS_CONFIG is not set CONFIG_REGULATOR=y # CONFIG_REGULATOR_DEBUG is not set CONFIG_REGULATOR_FIXED_VOLTAGE=y @@ -3337,23 +2462,28 @@ CONFIG_REGULATOR_FIXED_VOLTAGE=y # CONFIG_REGULATOR_ACT8865 is not set # CONFIG_REGULATOR_AD5398 is not set CONFIG_REGULATOR_ANATOP=y -# CONFIG_REGULATOR_DA9052 is not set +CONFIG_REGULATOR_DA9052=y # CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set # CONFIG_REGULATOR_FAN53555 is not set -# CONFIG_REGULATOR_GPIO is not set +CONFIG_REGULATOR_GPIO=y +# CONFIG_REGULATOR_ISL9305 is not set # CONFIG_REGULATOR_ISL6271A is not set # CONFIG_REGULATOR_LP3971 is not set # CONFIG_REGULATOR_LP3972 is not set # CONFIG_REGULATOR_LP872X is not set # CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_LTC3589 is not set # CONFIG_REGULATOR_MAX1586 is not set # CONFIG_REGULATOR_MAX8649 is not set # CONFIG_REGULATOR_MAX8660 is not set # CONFIG_REGULATOR_MAX8952 is not set # CONFIG_REGULATOR_MAX8973 is not set -# CONFIG_REGULATOR_MC13783 is not set -# CONFIG_REGULATOR_MC13892 is not set +CONFIG_REGULATOR_MC13XXX_CORE=y +CONFIG_REGULATOR_MC13783=y +CONFIG_REGULATOR_MC13892=y CONFIG_REGULATOR_PFUZE100=y +# CONFIG_REGULATOR_PWM is not set # CONFIG_REGULATOR_TPS51632 is not set # CONFIG_REGULATOR_TPS62360 is not set # CONFIG_REGULATOR_TPS65023 is not set @@ -3365,58 +2495,52 @@ CONFIG_MEDIA_SUPPORT=y # Multimedia core support # CONFIG_MEDIA_CAMERA_SUPPORT=y -CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set # CONFIG_MEDIA_RADIO_SUPPORT is not set +# CONFIG_MEDIA_SDR_SUPPORT is not set CONFIG_MEDIA_RC_SUPPORT=y -CONFIG_MEDIA_CONTROLLER=y +# CONFIG_MEDIA_CONTROLLER is not set CONFIG_VIDEO_DEV=y -CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_VIDEO_V4L2=y # CONFIG_VIDEO_ADV_DEBUG is not set # CONFIG_VIDEO_FIXED_MINOR_RANGES is not set -CONFIG_VIDEO_TUNER=m +CONFIG_V4L2_MEM2MEM_DEV=y CONFIG_VIDEOBUF_GEN=y -CONFIG_VIDEOBUF_DMA_SG=m -CONFIG_VIDEOBUF_VMALLOC=m -CONFIG_VIDEOBUF_DMA_CONTIG=y -CONFIG_VIDEOBUF_DVB=m CONFIG_VIDEOBUF2_CORE=y -CONFIG_VIDEOBUF2_MEMOPS=m -CONFIG_VIDEOBUF2_DMA_CONTIG=m -CONFIG_VIDEOBUF2_VMALLOC=m -CONFIG_DVB_CORE=y -CONFIG_DVB_NET=y -CONFIG_TTPCI_EEPROM=m -CONFIG_DVB_MAX_ADAPTERS=8 -CONFIG_DVB_DYNAMIC_MINORS=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_DMA_CONTIG=y +CONFIG_VIDEOBUF2_VMALLOC=y +# CONFIG_TTPCI_EEPROM is not set # # Media drivers # CONFIG_RC_CORE=y -CONFIG_RC_MAP=m +CONFIG_RC_MAP=y CONFIG_RC_DECODERS=y -CONFIG_LIRC=m -CONFIG_IR_LIRC_CODEC=m -CONFIG_IR_NEC_DECODER=m -CONFIG_IR_RC5_DECODER=m -CONFIG_IR_RC6_DECODER=m -CONFIG_IR_JVC_DECODER=m -CONFIG_IR_SONY_DECODER=m -CONFIG_IR_RC5_SZ_DECODER=m -CONFIG_IR_SANYO_DECODER=m -CONFIG_IR_MCE_KBD_DECODER=m +# CONFIG_LIRC is not set +CONFIG_IR_NEC_DECODER=y +CONFIG_IR_RC5_DECODER=y +CONFIG_IR_RC6_DECODER=y +CONFIG_IR_JVC_DECODER=y +CONFIG_IR_SONY_DECODER=y +CONFIG_IR_SANYO_DECODER=y +CONFIG_IR_SHARP_DECODER=y +CONFIG_IR_MCE_KBD_DECODER=y +CONFIG_IR_XMP_DECODER=y CONFIG_RC_DEVICES=y -CONFIG_RC_ATI_REMOTE=m -CONFIG_IR_IMON=m -CONFIG_IR_MCEUSB=m -CONFIG_IR_REDRAT3=m -CONFIG_IR_STREAMZAP=m -CONFIG_IR_IGUANA=m -CONFIG_IR_TTUSBIR=m -CONFIG_RC_LOOPBACK=m -CONFIG_IR_GPIO_CIR=m +# CONFIG_RC_ATI_REMOTE is not set +# CONFIG_IR_HIX5HD2 is not set +# CONFIG_IR_IMON is not set +# CONFIG_IR_MCEUSB is not set +# CONFIG_IR_REDRAT3 is not set +# CONFIG_IR_STREAMZAP is not set +# CONFIG_IR_IGORPLUGUSB is not set +# CONFIG_IR_IGUANA is not set +# CONFIG_IR_TTUSBIR is not set +# CONFIG_RC_LOOPBACK is not set +CONFIG_IR_GPIO_CIR=y CONFIG_MEDIA_USB_SUPPORT=y # @@ -3425,298 +2549,112 @@ CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=m CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y CONFIG_USB_GSPCA=m -CONFIG_USB_M5602=m -CONFIG_USB_STV06XX=m -CONFIG_USB_GL860=m -CONFIG_USB_GSPCA_BENQ=m -CONFIG_USB_GSPCA_CONEX=m -CONFIG_USB_GSPCA_CPIA1=m -CONFIG_USB_GSPCA_ETOMS=m -CONFIG_USB_GSPCA_FINEPIX=m -CONFIG_USB_GSPCA_JEILINJ=m -CONFIG_USB_GSPCA_JL2005BCD=m -CONFIG_USB_GSPCA_KINECT=m -CONFIG_USB_GSPCA_KONICA=m -CONFIG_USB_GSPCA_MARS=m -CONFIG_USB_GSPCA_MR97310A=m -CONFIG_USB_GSPCA_NW80X=m -CONFIG_USB_GSPCA_OV519=m -CONFIG_USB_GSPCA_OV534=m -CONFIG_USB_GSPCA_OV534_9=m -CONFIG_USB_GSPCA_PAC207=m -CONFIG_USB_GSPCA_PAC7302=m -CONFIG_USB_GSPCA_PAC7311=m -CONFIG_USB_GSPCA_SE401=m -CONFIG_USB_GSPCA_SN9C2028=m -CONFIG_USB_GSPCA_SN9C20X=m -CONFIG_USB_GSPCA_SONIXB=m -CONFIG_USB_GSPCA_SONIXJ=m -CONFIG_USB_GSPCA_SPCA500=m -CONFIG_USB_GSPCA_SPCA501=m -CONFIG_USB_GSPCA_SPCA505=m -CONFIG_USB_GSPCA_SPCA506=m -CONFIG_USB_GSPCA_SPCA508=m -CONFIG_USB_GSPCA_SPCA561=m -CONFIG_USB_GSPCA_SPCA1528=m -CONFIG_USB_GSPCA_SQ905=m -CONFIG_USB_GSPCA_SQ905C=m -CONFIG_USB_GSPCA_SQ930X=m -CONFIG_USB_GSPCA_STK014=m -CONFIG_USB_GSPCA_STK1135=m -CONFIG_USB_GSPCA_STV0680=m -CONFIG_USB_GSPCA_SUNPLUS=m -CONFIG_USB_GSPCA_T613=m -CONFIG_USB_GSPCA_TOPRO=m -CONFIG_USB_GSPCA_TV8532=m -CONFIG_USB_GSPCA_VC032X=m -CONFIG_USB_GSPCA_VICAM=m -CONFIG_USB_GSPCA_XIRLINK_CIT=m -CONFIG_USB_GSPCA_ZC3XX=m -CONFIG_USB_PWC=m -# CONFIG_USB_PWC_DEBUG is not set -CONFIG_USB_PWC_INPUT_EVDEV=y -CONFIG_VIDEO_CPIA2=m -CONFIG_USB_ZR364XX=m -CONFIG_USB_STKWEBCAM=m -CONFIG_USB_S2255=m -CONFIG_VIDEO_USBTV=m - -# -# Analog TV USB devices -# -CONFIG_VIDEO_PVRUSB2=m -CONFIG_VIDEO_PVRUSB2_SYSFS=y -CONFIG_VIDEO_PVRUSB2_DVB=y -# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set -CONFIG_VIDEO_HDPVR=m -CONFIG_VIDEO_TLG2300=m -CONFIG_VIDEO_USBVISION=m -CONFIG_VIDEO_STK1160_COMMON=m -CONFIG_VIDEO_STK1160_AC97=y -CONFIG_VIDEO_STK1160=m - -# -# Analog/digital TV USB devices -# -CONFIG_VIDEO_AU0828=m -CONFIG_VIDEO_AU0828_V4L2=y -CONFIG_VIDEO_CX231XX=m -CONFIG_VIDEO_CX231XX_RC=y -CONFIG_VIDEO_CX231XX_ALSA=m -CONFIG_VIDEO_CX231XX_DVB=m -CONFIG_VIDEO_TM6000=m -CONFIG_VIDEO_TM6000_ALSA=m -CONFIG_VIDEO_TM6000_DVB=m - -# -# Digital TV USB devices -# -CONFIG_DVB_USB=m -# CONFIG_DVB_USB_DEBUG is not set -CONFIG_DVB_USB_A800=m -CONFIG_DVB_USB_DIBUSB_MB=m -# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set -CONFIG_DVB_USB_DIBUSB_MC=m -CONFIG_DVB_USB_DIB0700=m -CONFIG_DVB_USB_UMT_010=m -CONFIG_DVB_USB_CXUSB=m -CONFIG_DVB_USB_M920X=m -CONFIG_DVB_USB_DIGITV=m -CONFIG_DVB_USB_VP7045=m -CONFIG_DVB_USB_VP702X=m -CONFIG_DVB_USB_GP8PSK=m -CONFIG_DVB_USB_NOVA_T_USB2=m -CONFIG_DVB_USB_TTUSB2=m -CONFIG_DVB_USB_DTT200U=m -CONFIG_DVB_USB_OPERA1=m -CONFIG_DVB_USB_AF9005=m -CONFIG_DVB_USB_AF9005_REMOTE=m -CONFIG_DVB_USB_PCTV452E=m -CONFIG_DVB_USB_DW2102=m -CONFIG_DVB_USB_CINERGY_T2=m -CONFIG_DVB_USB_DTV5100=m -CONFIG_DVB_USB_FRIIO=m -CONFIG_DVB_USB_AZ6027=m -CONFIG_DVB_USB_TECHNISAT_USB2=m -CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_AF9015=m -CONFIG_DVB_USB_AF9035=m -CONFIG_DVB_USB_ANYSEE=m -CONFIG_DVB_USB_AU6610=m -CONFIG_DVB_USB_AZ6007=m -CONFIG_DVB_USB_CE6230=m -CONFIG_DVB_USB_EC168=m -CONFIG_DVB_USB_GL861=m -CONFIG_DVB_USB_IT913X=m -CONFIG_DVB_USB_LME2510=m -CONFIG_DVB_USB_MXL111SF=m -CONFIG_DVB_USB_RTL28XXU=m -CONFIG_DVB_TTUSB_BUDGET=m -CONFIG_DVB_TTUSB_DEC=m -CONFIG_SMS_USB_DRV=m -CONFIG_DVB_B2C2_FLEXCOP_USB=m -# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set +# CONFIG_USB_M5602 is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_DTCS033 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_JL2005BCD is not set +# CONFIG_USB_GSPCA_KINECT is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SE401 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SPCA1528 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STK1135 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TOPRO is not set +# CONFIG_USB_GSPCA_TOUPTEK is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_USB_PWC is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +# CONFIG_VIDEO_USBTV is not set # # Webcam, TV (analog/digital) USB devices # -CONFIG_VIDEO_EM28XX=m -CONFIG_VIDEO_EM28XX_V4L2=m -CONFIG_VIDEO_EM28XX_ALSA=m -CONFIG_VIDEO_EM28XX_DVB=m -CONFIG_VIDEO_EM28XX_RC=m -CONFIG_MEDIA_PCI_SUPPORT=y - -# -# Media capture support -# - -# -# Media capture/analog TV support -# -CONFIG_VIDEO_IVTV=m -# CONFIG_VIDEO_IVTV_ALSA is not set -CONFIG_VIDEO_FB_IVTV=m -CONFIG_VIDEO_HEXIUM_GEMINI=m -CONFIG_VIDEO_HEXIUM_ORION=m -CONFIG_VIDEO_MXB=m - -# -# Media capture/analog/hybrid TV support -# -CONFIG_VIDEO_CX18=m -CONFIG_VIDEO_CX18_ALSA=m -CONFIG_VIDEO_CX23885=m -CONFIG_MEDIA_ALTERA_CI=m -# CONFIG_VIDEO_CX25821 is not set -CONFIG_VIDEO_CX88=m -CONFIG_VIDEO_CX88_ALSA=m -CONFIG_VIDEO_CX88_BLACKBIRD=m -CONFIG_VIDEO_CX88_DVB=m -CONFIG_VIDEO_CX88_ENABLE_VP3054=y -CONFIG_VIDEO_CX88_VP3054=m -CONFIG_VIDEO_CX88_MPEG=m -CONFIG_VIDEO_BT848=m -CONFIG_DVB_BT8XX=m -CONFIG_VIDEO_SAA7134=m -CONFIG_VIDEO_SAA7134_ALSA=m -CONFIG_VIDEO_SAA7134_RC=y -CONFIG_VIDEO_SAA7134_DVB=m -CONFIG_VIDEO_SAA7164=m - -# -# Media digital TV PCI Adapters -# -CONFIG_DVB_AV7110=m -CONFIG_DVB_AV7110_OSD=y -CONFIG_DVB_BUDGET_CORE=m -CONFIG_DVB_BUDGET=m -CONFIG_DVB_BUDGET_CI=m -CONFIG_DVB_BUDGET_AV=m -CONFIG_DVB_BUDGET_PATCH=m -CONFIG_DVB_B2C2_FLEXCOP_PCI=m -# CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG is not set -CONFIG_DVB_PLUTO2=m -CONFIG_DVB_DM1105=m -CONFIG_DVB_PT1=m -CONFIG_MANTIS_CORE=m -CONFIG_DVB_MANTIS=m -CONFIG_DVB_HOPPER=m -CONFIG_DVB_NGENE=m -CONFIG_DVB_DDBRIDGE=m +# CONFIG_VIDEO_EM28XX is not set +# CONFIG_MEDIA_PCI_SUPPORT is not set CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_VIDEO_CAFE_CCIC=m -# CONFIG_VIDEO_TIMBERDALE is not set -CONFIG_VIDEO_MXC_OUTPUT=y -CONFIG_VIDEO_MXC_IPU_OUTPUT=y +# CONFIG_VIDEO_CAFE_CCIC is not set CONFIG_SOC_CAMERA=y # CONFIG_SOC_CAMERA_PLATFORM is not set -# CONFIG_VIDEO_MX3 is not set -# CONFIG_VIDEO_RCAR_VIN is not set -# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set -# CONFIG_VIDEO_SH_MOBILE_CEU is not set +CONFIG_VIDEO_MX3=y CONFIG_V4L_MEM2MEM_DRIVERS=y -# CONFIG_VIDEO_CODA is not set +CONFIG_VIDEO_CODA=y # CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set # CONFIG_VIDEO_SH_VEU is not set -# CONFIG_VIDEO_RENESAS_VSP1 is not set # CONFIG_V4L_TEST_DRIVERS is not set # # Supported MMC/SDIO adapters # -CONFIG_SMS_SDIO_DRV=m -# CONFIG_MEDIA_PARPORT_SUPPORT is not set - -# -# Supported FireWire (IEEE 1394) Adapters -# -CONFIG_DVB_FIREDTV=m -CONFIG_DVB_FIREDTV_INPUT=y -CONFIG_MEDIA_COMMON_OPTIONS=y - -# -# common driver options -# -CONFIG_VIDEO_CX2341X=m -CONFIG_VIDEO_BTCX=m -CONFIG_VIDEO_TVEEPROM=m -CONFIG_CYPRESS_FIRMWARE=m -CONFIG_DVB_B2C2_FLEXCOP=m -CONFIG_VIDEO_SAA7146=m -CONFIG_VIDEO_SAA7146_VV=m -CONFIG_SMS_SIANO_MDTV=m -CONFIG_SMS_SIANO_RC=y +# CONFIG_CYPRESS_FIRMWARE is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y -CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=y # # Audio decoders, processors and mixers # -CONFIG_VIDEO_TVAUDIO=m -CONFIG_VIDEO_TDA7432=m -CONFIG_VIDEO_TDA9840=m -CONFIG_VIDEO_TEA6415C=m -CONFIG_VIDEO_TEA6420=m -CONFIG_VIDEO_MSP3400=m -CONFIG_VIDEO_CS5345=m -CONFIG_VIDEO_CS53L32A=m -CONFIG_VIDEO_WM8775=m -CONFIG_VIDEO_WM8739=m -CONFIG_VIDEO_VP27SMPX=m # # RDS decoders # -CONFIG_VIDEO_SAA6588=m # # Video decoders # -CONFIG_VIDEO_SAA711X=m -CONFIG_VIDEO_TVP5150=m # # Video and audio decoders # -CONFIG_VIDEO_SAA717X=m -CONFIG_VIDEO_CX25840=m # # Video encoders # -CONFIG_VIDEO_SAA7127=m # # Camera sensor devices # -CONFIG_VIDEO_OV7670=m -CONFIG_VIDEO_MT9V011=m # # Flash devices @@ -3725,18 +2663,14 @@ CONFIG_VIDEO_MT9V011=m # # Video improvement chips # -CONFIG_VIDEO_UPD64031A=m -CONFIG_VIDEO_UPD64083=m # # Audio/Video compression chips # -CONFIG_VIDEO_SAA6752HS=m # # Miscellaneous helper chips # -CONFIG_VIDEO_M52790=m # # Sensors used on soc_camera driver @@ -3759,161 +2693,6 @@ CONFIG_SOC_CAMERA_OV2640=y # CONFIG_SOC_CAMERA_OV9740 is not set # CONFIG_SOC_CAMERA_RJ54N1 is not set # CONFIG_SOC_CAMERA_TW9910 is not set -CONFIG_MEDIA_TUNER=y -CONFIG_MEDIA_TUNER_SIMPLE=y -CONFIG_MEDIA_TUNER_TDA8290=y -CONFIG_MEDIA_TUNER_TDA827X=y -CONFIG_MEDIA_TUNER_TDA18271=y -CONFIG_MEDIA_TUNER_TDA9887=y -CONFIG_MEDIA_TUNER_MT20XX=y -CONFIG_MEDIA_TUNER_MT2060=m -CONFIG_MEDIA_TUNER_MT2063=m -CONFIG_MEDIA_TUNER_MT2266=m -CONFIG_MEDIA_TUNER_MT2131=m -CONFIG_MEDIA_TUNER_QT1010=m -CONFIG_MEDIA_TUNER_XC2028=y -CONFIG_MEDIA_TUNER_XC5000=y -CONFIG_MEDIA_TUNER_XC4000=y -CONFIG_MEDIA_TUNER_MXL5005S=m -CONFIG_MEDIA_TUNER_MXL5007T=m -CONFIG_MEDIA_TUNER_MC44S803=y -CONFIG_MEDIA_TUNER_MAX2165=m -CONFIG_MEDIA_TUNER_TDA18218=m -CONFIG_MEDIA_TUNER_FC0011=m -CONFIG_MEDIA_TUNER_FC0012=m -CONFIG_MEDIA_TUNER_FC0013=m -CONFIG_MEDIA_TUNER_TDA18212=m -CONFIG_MEDIA_TUNER_E4000=m -CONFIG_MEDIA_TUNER_FC2580=m -CONFIG_MEDIA_TUNER_M88TS2022=m -CONFIG_MEDIA_TUNER_TUA9001=m -CONFIG_MEDIA_TUNER_IT913X=m -CONFIG_MEDIA_TUNER_R820T=m - -# -# Multistandard (satellite) frontends -# -CONFIG_DVB_STB0899=m -CONFIG_DVB_STB6100=m -CONFIG_DVB_STV090x=m -CONFIG_DVB_STV6110x=m -CONFIG_DVB_M88DS3103=m - -# -# Multistandard (cable + terrestrial) frontends -# -CONFIG_DVB_DRXK=m -CONFIG_DVB_TDA18271C2DD=m - -# -# DVB-S (satellite) frontends -# -CONFIG_DVB_CX24110=m -CONFIG_DVB_CX24123=m -CONFIG_DVB_MT312=m -CONFIG_DVB_ZL10036=m -CONFIG_DVB_ZL10039=m -CONFIG_DVB_S5H1420=m -CONFIG_DVB_STV0288=m -CONFIG_DVB_STB6000=m -CONFIG_DVB_STV0299=m -CONFIG_DVB_STV6110=m -CONFIG_DVB_STV0900=m -CONFIG_DVB_TDA8083=m -CONFIG_DVB_TDA10086=m -CONFIG_DVB_TDA8261=m -CONFIG_DVB_VES1X93=m -CONFIG_DVB_TUNER_ITD1000=m -CONFIG_DVB_TUNER_CX24113=m -CONFIG_DVB_TDA826X=m -CONFIG_DVB_TUA6100=m -CONFIG_DVB_CX24116=m -CONFIG_DVB_CX24117=m -CONFIG_DVB_SI21XX=m -CONFIG_DVB_TS2020=m -CONFIG_DVB_DS3000=m -CONFIG_DVB_MB86A16=m -CONFIG_DVB_TDA10071=m - -# -# DVB-T (terrestrial) frontends -# -CONFIG_DVB_SP8870=m -CONFIG_DVB_SP887X=m -CONFIG_DVB_CX22700=m -CONFIG_DVB_CX22702=m -CONFIG_DVB_DRXD=m -CONFIG_DVB_L64781=m -CONFIG_DVB_TDA1004X=m -CONFIG_DVB_NXT6000=m -CONFIG_DVB_MT352=m -CONFIG_DVB_ZL10353=m -CONFIG_DVB_DIB3000MB=m -CONFIG_DVB_DIB3000MC=m -CONFIG_DVB_DIB7000M=m -CONFIG_DVB_DIB7000P=m -CONFIG_DVB_TDA10048=m -CONFIG_DVB_AF9013=m -CONFIG_DVB_EC100=m -CONFIG_DVB_STV0367=m -CONFIG_DVB_CXD2820R=m -CONFIG_DVB_RTL2830=m -CONFIG_DVB_RTL2832=m - -# -# DVB-C (cable) frontends -# -CONFIG_DVB_VES1820=m -CONFIG_DVB_TDA10021=m -CONFIG_DVB_TDA10023=m -CONFIG_DVB_STV0297=m - -# -# ATSC (North American/Korean Terrestrial/Cable DTV) frontends -# -CONFIG_DVB_NXT200X=m -CONFIG_DVB_OR51211=m -CONFIG_DVB_OR51132=m -CONFIG_DVB_BCM3510=m -CONFIG_DVB_LGDT330X=m -CONFIG_DVB_LGDT3305=m -CONFIG_DVB_LG2160=m -CONFIG_DVB_S5H1409=m -CONFIG_DVB_AU8522=m -CONFIG_DVB_AU8522_DTV=m -CONFIG_DVB_AU8522_V4L=m -CONFIG_DVB_S5H1411=m - -# -# ISDB-T (terrestrial) frontends -# -CONFIG_DVB_S921=m -CONFIG_DVB_DIB8000=m -CONFIG_DVB_MB86A20S=m - -# -# Digital terrestrial only tuners/PLL -# -CONFIG_DVB_PLL=m -CONFIG_DVB_TUNER_DIB0070=m -CONFIG_DVB_TUNER_DIB0090=m - -# -# SEC control devices for DVB-S -# -CONFIG_DVB_LNBP21=m -CONFIG_DVB_LNBP22=m -CONFIG_DVB_ISL6405=m -CONFIG_DVB_ISL6421=m -CONFIG_DVB_ISL6423=m -CONFIG_DVB_A8293=m -CONFIG_DVB_LGS8GXX=m -CONFIG_DVB_ATBM8830=m -CONFIG_DVB_TDA665x=m -CONFIG_DVB_IX2505V=m -CONFIG_DVB_IT913X_FE=m -CONFIG_DVB_M88RS2000=m -CONFIG_DVB_AF9033=m # # Tools to develop new frontends @@ -3923,35 +2702,32 @@ CONFIG_DVB_AF9033=m # # Graphics support # -CONFIG_FB_TFT=m -CONFIG_FB_TFT_BD663474=m -CONFIG_FB_TFT_HX8340BN=m -CONFIG_FB_TFT_HX8347D=m -CONFIG_FB_TFT_HX8353D=m -CONFIG_FB_TFT_ILI9320=m -CONFIG_FB_TFT_ILI9325=m -CONFIG_FB_TFT_ILI9340=m -CONFIG_FB_TFT_ILI9341=m -CONFIG_FB_TFT_ILI9481=m -CONFIG_FB_TFT_ILI9486=m -CONFIG_FB_TFT_PCD8544=m -CONFIG_FB_TFT_RA8875=m -CONFIG_FB_TFT_S6D02A1=m -CONFIG_FB_TFT_S6D1121=m -CONFIG_FB_TFT_SSD1289=m -CONFIG_FB_TFT_SSD1306=m -CONFIG_FB_TFT_SSD1331=m -CONFIG_FB_TFT_SSD1351=m -CONFIG_FB_TFT_ST7735R=m -CONFIG_FB_TFT_TINYLCD=m -CONFIG_FB_TFT_TLS8204=m -CONFIG_FB_TFT_UPD161704=m -CONFIG_FB_TFT_WATTEROTT=m -CONFIG_FB_FLEX=m -CONFIG_FB_TFT_FBTFT_DEVICE=m CONFIG_VGA_ARB=y CONFIG_VGA_ARB_MAX_GPUS=16 +CONFIG_IMX_IPUV3_CORE=y + +# +# Direct Rendering Manager +# CONFIG_DRM=y +CONFIG_DRM_KMS_HELPER=y +CONFIG_DRM_KMS_FB_HELPER=y +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +CONFIG_DRM_GEM_CMA_HELPER=y +CONFIG_DRM_KMS_CMA_HELPER=y + +# +# I2C encoder or helper chips +# +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_SIL164 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +CONFIG_DRM_DW_HDMI=y +# CONFIG_DRM_DW_HDMI_AHB_AUDIO is not set +# CONFIG_DRM_DW_HDMI_CEC is not set +# CONFIG_DRM_PTN3460 is not set +# CONFIG_DRM_PS8622 is not set # CONFIG_DRM_TDFX is not set # CONFIG_DRM_R128 is not set # CONFIG_DRM_RADEON is not set @@ -3959,7 +2735,7 @@ CONFIG_DRM=y # CONFIG_DRM_MGA is not set # CONFIG_DRM_VIA is not set # CONFIG_DRM_SAVAGE is not set -CONFIG_DRM_VIVANTE=y +# CONFIG_DRM_VGEM is not set # CONFIG_DRM_EXYNOS is not set # CONFIG_DRM_VMWGFX is not set # CONFIG_DRM_UDL is not set @@ -3967,31 +2743,46 @@ CONFIG_DRM_VIVANTE=y # CONFIG_DRM_MGAG200 is not set # CONFIG_DRM_CIRRUS_QEMU is not set # CONFIG_DRM_ARMADA is not set -# CONFIG_DRM_RCAR_DU is not set -# CONFIG_DRM_SHMOBILE is not set # CONFIG_DRM_TILCDC is not set # CONFIG_DRM_QXL is not set # CONFIG_DRM_BOCHS is not set -# CONFIG_VGASTATE is not set -CONFIG_VIDEO_OUTPUT_CONTROL=m -CONFIG_HDMI=y +CONFIG_DRM_PANEL=y + +# +# Display Panels +# +CONFIG_DRM_PANEL_SIMPLE=y +# CONFIG_DRM_PANEL_LD9040 is not set +# CONFIG_DRM_PANEL_S6E8AA0 is not set +# CONFIG_DRM_STI is not set +CONFIG_DRM_IMX=y +CONFIG_DRM_IMX_FB_HELPER=y +CONFIG_DRM_IMX_PARALLEL_DISPLAY=y +CONFIG_DRM_IMX_TVE=y +CONFIG_DRM_IMX_LDB=y +CONFIG_DRM_IMX_IPUV3=y +CONFIG_DRM_IMX_HDMI=y + +# +# Frame buffer Devices +# CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y # CONFIG_FB_DDC is not set # CONFIG_FB_BOOT_VESA_SUPPORT is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -CONFIG_FB_SYS_FILLRECT=m -CONFIG_FB_SYS_COPYAREA=m -CONFIG_FB_SYS_IMAGEBLIT=m +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y # CONFIG_FB_FOREIGN_ENDIAN is not set -CONFIG_FB_SYS_FOPS=m -CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SYS_FOPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set -CONFIG_FB_BACKLIGHT=y +# CONFIG_FB_BACKLIGHT is not set CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_TILEBLITTING is not set @@ -4000,7 +2791,6 @@ CONFIG_FB_MODE_HELPERS=y # # CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set -# CONFIG_FB_ARMHDLCD is not set # CONFIG_FB_IMX is not set # CONFIG_FB_CYBER2000 is not set # CONFIG_FB_ASILIANT is not set @@ -4027,52 +2817,47 @@ CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_ARK is not set # CONFIG_FB_PM3 is not set # CONFIG_FB_CARMINE is not set -# CONFIG_FB_TMIO is not set -# CONFIG_FB_SM501 is not set # CONFIG_FB_SMSCUFX is not set -CONFIG_FB_UDL=m -# CONFIG_FB_GOLDFISH is not set +# CONFIG_FB_UDL is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set # CONFIG_FB_MB862XX is not set -# CONFIG_FB_MX3 is not set +CONFIG_FB_MX3=y # CONFIG_FB_BROADSHEET is not set # CONFIG_FB_AUO_K190X is not set +CONFIG_FB_MXS=y # CONFIG_FB_SIMPLE is not set -# CONFIG_EXYNOS_VIDEO is not set +# CONFIG_FB_SSD1307 is not set CONFIG_BACKLIGHT_LCD_SUPPORT=y -CONFIG_LCD_CLASS_DEVICE=m -# CONFIG_LCD_L4F00242T03 is not set +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_LCD_L4F00242T03=y # CONFIG_LCD_LMS283GF05 is not set # CONFIG_LCD_LTV350QV is not set # CONFIG_LCD_ILI922X is not set # CONFIG_LCD_ILI9320 is not set # CONFIG_LCD_TDO24M is not set # CONFIG_LCD_VGG2432A4 is not set -CONFIG_LCD_PLATFORM=m +CONFIG_LCD_PLATFORM=y # CONFIG_LCD_S6E63M0 is not set # CONFIG_LCD_LD9040 is not set # CONFIG_LCD_AMS369FG06 is not set # CONFIG_LCD_LMS501KF03 is not set # CONFIG_LCD_HX8357 is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y -# CONFIG_BACKLIGHT_GENERIC is not set -# CONFIG_BACKLIGHT_PWM is not set +CONFIG_BACKLIGHT_GENERIC=y +CONFIG_BACKLIGHT_PWM=y # CONFIG_BACKLIGHT_DA9052 is not set # CONFIG_BACKLIGHT_ADP8860 is not set # CONFIG_BACKLIGHT_ADP8870 is not set # CONFIG_BACKLIGHT_LM3630A is not set # CONFIG_BACKLIGHT_LM3639 is not set # CONFIG_BACKLIGHT_LP855X is not set -# CONFIG_BACKLIGHT_GPIO is not set +CONFIG_BACKLIGHT_GPIO=y # CONFIG_BACKLIGHT_LV5207LP is not set # CONFIG_BACKLIGHT_BD6107 is not set -CONFIG_FB_MXC=y -CONFIG_FB_MXC_SYNC_PANEL=y -CONFIG_FB_MXC_LDB=y -# CONFIG_FB_MXC_MIPI_DSI is not set -CONFIG_FB_MXC_HDMI=y -CONFIG_FB_MXC_EDID=y +# CONFIG_VGASTATE is not set +CONFIG_VIDEOMODE_HELPERS=y +CONFIG_HDMI=y # # Console display driver support @@ -4081,189 +2866,224 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -CONFIG_LOGO_LINUX_CLUT224=y -# CONFIG_FB_SSD1307 is not set +# CONFIG_LOGO is not set CONFIG_SOUND=y -CONFIG_SOUND_OSS_CORE=y -CONFIG_SOUND_OSS_CORE_PRECLAIM=y +# CONFIG_SOUND_OSS_CORE is not set CONFIG_SND=y CONFIG_SND_TIMER=y CONFIG_SND_PCM=y CONFIG_SND_DMAENGINE_PCM=y -CONFIG_SND_HWDEP=y +CONFIG_SND_HWDEP=m CONFIG_SND_RAWMIDI=m CONFIG_SND_COMPRESS_OFFLOAD=y CONFIG_SND_JACK=y -CONFIG_SND_SEQUENCER=y -CONFIG_SND_SEQ_DUMMY=m -CONFIG_SND_OSSEMUL=y -CONFIG_SND_MIXER_OSS=y -CONFIG_SND_PCM_OSS=y -CONFIG_SND_PCM_OSS_PLUGINS=y -CONFIG_SND_SEQUENCER_OSS=y -CONFIG_SND_HRTIMER=y -CONFIG_SND_SEQ_HRTIMER_DEFAULT=y -CONFIG_SND_DYNAMIC_MINORS=y -CONFIG_SND_MAX_CARDS=32 -# CONFIG_SND_SUPPORT_OLD_API is not set +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set -CONFIG_SND_VMASTER=y -CONFIG_SND_KCTL_JACK=y -CONFIG_SND_RAWMIDI_SEQ=m -CONFIG_SND_OPL3_LIB_SEQ=m +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set # CONFIG_SND_OPL4_LIB_SEQ is not set # CONFIG_SND_SBAWE_SEQ is not set -CONFIG_SND_EMU10K1_SEQ=m -CONFIG_SND_MPU401_UART=m -CONFIG_SND_OPL3_LIB=m -CONFIG_SND_VX_LIB=m -CONFIG_SND_AC97_CODEC=y +# CONFIG_SND_EMU10K1_SEQ is not set CONFIG_SND_DRIVERS=y -CONFIG_SND_DUMMY=m -CONFIG_SND_ALOOP=m -CONFIG_SND_VIRMIDI=m -CONFIG_SND_MTPAV=m -CONFIG_SND_MTS64=m -CONFIG_SND_SERIAL_U16550=m -CONFIG_SND_MPU401=m -CONFIG_SND_PORTMAN2X4=m -CONFIG_SND_AC97_POWER_SAVE=y -CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set CONFIG_SND_PCI=y -CONFIG_SND_AD1889=m -CONFIG_SND_ALS300=m -CONFIG_SND_ALI5451=m -CONFIG_SND_ATIIXP=m -CONFIG_SND_ATIIXP_MODEM=m -CONFIG_SND_AU8810=m -CONFIG_SND_AU8820=m -CONFIG_SND_AU8830=m +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set # CONFIG_SND_AW2 is not set -CONFIG_SND_AZT3328=m -CONFIG_SND_BT87X=m -# CONFIG_SND_BT87X_OVERCLOCK is not set -CONFIG_SND_CA0106=m -CONFIG_SND_CMIPCI=m -CONFIG_SND_OXYGEN_LIB=m -CONFIG_SND_OXYGEN=m -CONFIG_SND_CS4281=m -CONFIG_SND_CS46XX=m -CONFIG_SND_CS46XX_NEW_DSP=y -CONFIG_SND_CS5535AUDIO=m -CONFIG_SND_CTXFI=m -CONFIG_SND_DARLA20=m -CONFIG_SND_GINA20=m -CONFIG_SND_LAYLA20=m -CONFIG_SND_DARLA24=m -CONFIG_SND_GINA24=m -CONFIG_SND_LAYLA24=m -CONFIG_SND_MONA=m -CONFIG_SND_MIA=m -CONFIG_SND_ECHO3G=m -CONFIG_SND_INDIGO=m -CONFIG_SND_INDIGOIO=m -CONFIG_SND_INDIGODJ=m -CONFIG_SND_INDIGOIOX=m -CONFIG_SND_INDIGODJX=m -CONFIG_SND_EMU10K1=m -CONFIG_SND_EMU10K1X=m -CONFIG_SND_ENS1370=m -CONFIG_SND_ENS1371=m -CONFIG_SND_ES1938=m -CONFIG_SND_ES1968=m -CONFIG_SND_ES1968_INPUT=y -CONFIG_SND_FM801=m -CONFIG_SND_HDA_INTEL=y -CONFIG_SND_HDA_DSP_LOADER=y -CONFIG_SND_HDA_PREALLOC_SIZE=4096 -CONFIG_SND_HDA_HWDEP=y -CONFIG_SND_HDA_RECONFIG=y -CONFIG_SND_HDA_INPUT_BEEP=y -CONFIG_SND_HDA_INPUT_BEEP_MODE=0 -CONFIG_SND_HDA_INPUT_JACK=y -CONFIG_SND_HDA_PATCH_LOADER=y -CONFIG_SND_HDA_CODEC_REALTEK=y -CONFIG_SND_HDA_CODEC_ANALOG=y -CONFIG_SND_HDA_CODEC_SIGMATEL=y -CONFIG_SND_HDA_CODEC_VIA=y -CONFIG_SND_HDA_CODEC_HDMI=y -CONFIG_SND_HDA_CODEC_CIRRUS=y -CONFIG_SND_HDA_CODEC_CONEXANT=y -CONFIG_SND_HDA_CODEC_CA0110=y -CONFIG_SND_HDA_CODEC_CA0132=y -CONFIG_SND_HDA_CODEC_CA0132_DSP=y -CONFIG_SND_HDA_CODEC_CMEDIA=y -CONFIG_SND_HDA_CODEC_SI3054=y -CONFIG_SND_HDA_GENERIC=y -CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 -CONFIG_SND_HDSP=m -CONFIG_SND_HDSPM=m -CONFIG_SND_ICE1712=m -CONFIG_SND_ICE1724=m -CONFIG_SND_INTEL8X0=y -CONFIG_SND_INTEL8X0M=m -CONFIG_SND_KORG1212=m -CONFIG_SND_LOLA=m -CONFIG_SND_LX6464ES=m -CONFIG_SND_MAESTRO3=m -CONFIG_SND_MAESTRO3_INPUT=y -CONFIG_SND_MIXART=m -CONFIG_SND_NM256=m -CONFIG_SND_PCXHR=m -CONFIG_SND_RIPTIDE=m -CONFIG_SND_RME32=m -CONFIG_SND_RME96=m -CONFIG_SND_RME9652=m -CONFIG_SND_SONICVIBES=m -CONFIG_SND_TRIDENT=m -CONFIG_SND_VIA82XX=m -CONFIG_SND_VIA82XX_MODEM=m -CONFIG_SND_VIRTUOSO=m -CONFIG_SND_VX222=m -CONFIG_SND_YMFPCI=m +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_OXYGEN is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CTXFI is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set +# CONFIG_SND_INDIGOIOX is not set +# CONFIG_SND_INDIGODJX is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_LOLA is not set +# CONFIG_SND_LX6464ES is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_SE6X is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_YMFPCI is not set + +# +# HD-Audio +# +# CONFIG_SND_HDA_INTEL is not set CONFIG_SND_ARM=y CONFIG_SND_SPI=y CONFIG_SND_USB=y CONFIG_SND_USB_AUDIO=m -CONFIG_SND_USB_UA101=m -CONFIG_SND_USB_CAIAQ=m -CONFIG_SND_USB_CAIAQ_INPUT=y -CONFIG_SND_USB_6FIRE=m -CONFIG_SND_USB_HIFACE=m -CONFIG_SND_FIREWIRE=y -CONFIG_SND_FIREWIRE_LIB=m -CONFIG_SND_DICE=m -CONFIG_SND_FIREWIRE_SPEAKERS=m -CONFIG_SND_ISIGHT=m -CONFIG_SND_SCS1X=m -# CONFIG_SND_PCMCIA is not set +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_BCD2000 is not set +# CONFIG_SND_USB_POD is not set +# CONFIG_SND_USB_PODHD is not set +# CONFIG_SND_USB_TONEPORT is not set +# CONFIG_SND_USB_VARIAX is not set CONFIG_SND_SOC=y +CONFIG_SND_SOC_AC97_BUS=y CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y # CONFIG_SND_ATMEL_SOC is not set # CONFIG_SND_DESIGNWARE_I2S is not set + +# +# SoC Audio for Freescale CPUs +# + +# +# Common SoC Audio options for Freescale CPUs: +# +# CONFIG_SND_SOC_FSL_ASRC is not set +CONFIG_SND_SOC_FSL_SAI=y CONFIG_SND_SOC_FSL_SSI=y CONFIG_SND_SOC_FSL_SPDIF=y -CONFIG_SND_SOC_FSL_ASRC=y -CONFIG_SND_SOC_FSL_HDMI=y -CONFIG_SND_IMX_SOC=y +# CONFIG_SND_SOC_FSL_ESAI is not set +CONFIG_SND_SOC_FSL_UTILS=y CONFIG_SND_SOC_IMX_PCM_DMA=y -CONFIG_SND_SOC_IMX_HDMI_DMA=y CONFIG_SND_SOC_IMX_AUDMUX=y -# CONFIG_SND_SOC_IMX_CS42888 is not set -# CONFIG_SND_SOC_IMX_WM8962 is not set +CONFIG_SND_IMX_SOC=y +CONFIG_SND_SOC_IMX_SSI=y +CONFIG_SND_SOC_IMX_PCM_FIQ=y + +# +# SoC Audio support for Freescale i.MX boards: +# +CONFIG_SND_SOC_PHYCORE_AC97=y +CONFIG_SND_SOC_EUKREA_TLV320=y +CONFIG_SND_SOC_IMX_WM8962=y +# CONFIG_SND_SOC_IMX_ES8328 is not set CONFIG_SND_SOC_IMX_SGTL5000=y CONFIG_SND_SOC_IMX_SPDIF=y -CONFIG_SND_SOC_IMX_HDMI=y -# CONFIG_SND_SOC_IMX_MC13783 is not set +CONFIG_SND_SOC_IMX_MC13783=y +# CONFIG_SND_SOC_FSL_ASOC_CARD is not set +# CONFIG_SND_SOC_QCOM is not set +# CONFIG_SND_SOC_XTFPGA_I2S is not set CONFIG_SND_SOC_I2C_AND_SPI=y -CONFIG_SND_SOC_HDMI_CODEC=y + +# +# CODEC drivers +# +# CONFIG_SND_SOC_ADAU1701 is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_AK4554 is not set +# CONFIG_SND_SOC_AK4642 is not set +# CONFIG_SND_SOC_AK5386 is not set +# CONFIG_SND_SOC_ALC5623 is not set +# CONFIG_SND_SOC_CS35L32 is not set +# CONFIG_SND_SOC_CS42L51_I2C is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_CS42L73 is not set +# CONFIG_SND_SOC_CS4265 is not set +# CONFIG_SND_SOC_CS4270 is not set +# CONFIG_SND_SOC_CS4271_I2C is not set +# CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_CS42XX8_I2C is not set +# CONFIG_SND_SOC_HDMI_CODEC is not set +# CONFIG_SND_SOC_ES8328 is not set +# CONFIG_SND_SOC_PCM1681 is not set +# CONFIG_SND_SOC_PCM1792A is not set +# CONFIG_SND_SOC_PCM512x_I2C is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_RT5631 is not set +# CONFIG_SND_SOC_RT5677_SPI is not set CONFIG_SND_SOC_SGTL5000=y -# CONFIG_SND_SIMPLE_CARD is not set +# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set +# CONFIG_SND_SOC_SPDIF is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM2602_I2C is not set +# CONFIG_SND_SOC_SSM4567 is not set +# CONFIG_SND_SOC_STA32X is not set +# CONFIG_SND_SOC_STA350 is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS5086 is not set +# CONFIG_SND_SOC_TFA9879 is not set +CONFIG_SND_SOC_TLV320AIC23=y +CONFIG_SND_SOC_TLV320AIC23_I2C=y +# CONFIG_SND_SOC_TLV320AIC23_SPI is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +CONFIG_SND_SOC_TLV320AIC3X=y +# CONFIG_SND_SOC_TS3A227E is not set +# CONFIG_SND_SOC_WM8510 is not set +# CONFIG_SND_SOC_WM8523 is not set +# CONFIG_SND_SOC_WM8580 is not set +# CONFIG_SND_SOC_WM8711 is not set +# CONFIG_SND_SOC_WM8728 is not set +# CONFIG_SND_SOC_WM8731 is not set +# CONFIG_SND_SOC_WM8737 is not set +# CONFIG_SND_SOC_WM8741 is not set +# CONFIG_SND_SOC_WM8750 is not set +# CONFIG_SND_SOC_WM8753 is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8776 is not set +# CONFIG_SND_SOC_WM8804_I2C is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_WM8903 is not set +CONFIG_SND_SOC_WM8962=y +# CONFIG_SND_SOC_WM8978 is not set +CONFIG_SND_SOC_WM9712=y +CONFIG_SND_SOC_MC13783=y +# CONFIG_SND_SOC_TPA6130A2 is not set +CONFIG_SND_SIMPLE_CARD=y # CONFIG_SOUND_PRIME is not set CONFIG_AC97_BUS=y @@ -4271,104 +3091,94 @@ CONFIG_AC97_BUS=y # HID support # CONFIG_HID=y -CONFIG_HID_BATTERY_STRENGTH=y -CONFIG_HIDRAW=y -CONFIG_UHID=m +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HIDRAW is not set +# CONFIG_UHID is not set CONFIG_HID_GENERIC=y # # Special HID drivers # # CONFIG_HID_A4TECH is not set -CONFIG_HID_ACRUX=m -CONFIG_HID_ACRUX_FF=y +# CONFIG_HID_ACRUX is not set # CONFIG_HID_APPLE is not set -CONFIG_HID_APPLEIR=m -CONFIG_HID_AUREAL=m +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set # CONFIG_HID_BELKIN is not set -CONFIG_HID_CHERRY=y +# CONFIG_HID_BETOP_FF is not set +# CONFIG_HID_CHERRY is not set # CONFIG_HID_CHICONY is not set -CONFIG_HID_PRODIKEYS=m +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CP2112 is not set # CONFIG_HID_CYPRESS is not set -CONFIG_HID_DRAGONRISE=m -CONFIG_DRAGONRISE_FF=y -CONFIG_HID_EMS_FF=m -CONFIG_HID_ELECOM=m -CONFIG_HID_ELO=m +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set # CONFIG_HID_EZKEY is not set -CONFIG_HID_HOLTEK=m -CONFIG_HOLTEK_FF=y -CONFIG_HID_HUION=m -CONFIG_HID_KEYTOUCH=m -CONFIG_HID_KYE=m -CONFIG_HID_UCLOGIC=m -CONFIG_HID_WALTOP=m -CONFIG_HID_GYRATION=m -CONFIG_HID_ICADE=m -CONFIG_HID_TWINHAN=m +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_GT683R is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_TWINHAN is not set # CONFIG_HID_KENSINGTON is not set -CONFIG_HID_LCPOWER=m -CONFIG_HID_LENOVO_TPKBD=m +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO is not set # CONFIG_HID_LOGITECH is not set -CONFIG_HID_MAGICMOUSE=y +# CONFIG_HID_MAGICMOUSE is not set # CONFIG_HID_MICROSOFT is not set # CONFIG_HID_MONTEREY is not set -CONFIG_HID_MULTITOUCH=m -CONFIG_HID_NTRIG=y -CONFIG_HID_ORTEK=m -CONFIG_HID_PANTHERLORD=m -CONFIG_PANTHERLORD_FF=y -CONFIG_HID_PETALYNX=m -CONFIG_HID_PICOLCD=m -# CONFIG_HID_PICOLCD_FB is not set -# CONFIG_HID_PICOLCD_BACKLIGHT is not set -# CONFIG_HID_PICOLCD_LCD is not set -# CONFIG_HID_PICOLCD_LEDS is not set -# CONFIG_HID_PICOLCD_CIR is not set -CONFIG_HID_PRIMAX=m -CONFIG_HID_ROCCAT=m -CONFIG_HID_SAITEK=m -CONFIG_HID_SAMSUNG=m -CONFIG_HID_SONY=m -CONFIG_SONY_FF=y -CONFIG_HID_SPEEDLINK=m -CONFIG_HID_STEELSERIES=m -CONFIG_HID_SUNPLUS=m -CONFIG_HID_GREENASIA=m -CONFIG_GREENASIA_FF=y -CONFIG_HID_SMARTJOYPLUS=m -CONFIG_SMARTJOYPLUS_FF=y -CONFIG_HID_TIVO=m -CONFIG_HID_TOPSEED=m -CONFIG_HID_THINGM=m -CONFIG_HID_THRUSTMASTER=m -CONFIG_THRUSTMASTER_FF=y -CONFIG_HID_WACOM=m -CONFIG_HID_WIIMOTE=m -CONFIG_HID_XINMO=m -CONFIG_HID_ZEROPLUS=m -CONFIG_ZEROPLUS_FF=y -CONFIG_HID_ZYDACRON=m -CONFIG_HID_SENSOR_HUB=m +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THINGM is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_WIIMOTE is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set # # USB HID support # CONFIG_USB_HID=y -CONFIG_HID_PID=y -CONFIG_USB_HIDDEV=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set # # I2C HID support # -CONFIG_I2C_HID=m +# CONFIG_I2C_HID is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_SUPPORT=y CONFIG_USB_COMMON=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB=y -# CONFIG_USB_DEBUG is not set -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set # # Miscellaneous USB options @@ -4378,53 +3188,43 @@ CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -CONFIG_USB_MON=y -CONFIG_USB_WUSB=m -CONFIG_USB_WUSB_CBAF=m -# CONFIG_USB_WUSB_CBAF_DEBUG is not set +# CONFIG_USB_OTG_FSM is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF is not set # # USB Host Controller Drivers # # CONFIG_USB_C67X00_HCD is not set -CONFIG_USB_XHCI_HCD=y +# CONFIG_USB_XHCI_HCD is not set CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y -# CONFIG_USB_EHCI_MXC is not set -# CONFIG_USB_EHCI_HCD_SYNOPSYS is not set +CONFIG_USB_EHCI_MXC=y # CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set -# CONFIG_USB_ISP1760_HCD is not set -CONFIG_USB_ISP1362_HCD=m -CONFIG_USB_FUSBH200_HCD=m +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FUSBH200_HCD is not set # CONFIG_USB_FOTG210_HCD is not set -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_OHCI_HCD_PCI=y +# CONFIG_USB_MAX3421_HCD is not set +CONFIG_USB_OHCI_HCD=m +CONFIG_USB_OHCI_HCD_PCI=m # CONFIG_USB_OHCI_HCD_PLATFORM is not set -CONFIG_USB_UHCI_HCD=y -CONFIG_USB_U132_HCD=m -CONFIG_USB_SL811_HCD=m -CONFIG_USB_SL811_HCD_ISO=y -# CONFIG_USB_SL811_CS is not set +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set -CONFIG_USB_WHCI_HCD=m -CONFIG_USB_HWA_HCD=m # CONFIG_USB_IMX21_HCD is not set -# CONFIG_USB_HCD_BCMA is not set -# CONFIG_USB_HCD_SSB is not set # CONFIG_USB_HCD_TEST_MODE is not set -# CONFIG_USB_RENESAS_USBHS is not set # # USB Device Class drivers # -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m -CONFIG_USB_WDM=m -CONFIG_USB_TMC=m +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set # # NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may @@ -4435,157 +3235,137 @@ CONFIG_USB_TMC=m # CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_REALTEK=m -CONFIG_REALTEK_AUTOPM=y -CONFIG_USB_STORAGE_DATAFAB=m -CONFIG_USB_STORAGE_FREECOM=m -CONFIG_USB_STORAGE_ISD200=m -CONFIG_USB_STORAGE_USBAT=y -CONFIG_USB_STORAGE_SDDR09=m -CONFIG_USB_STORAGE_SDDR55=m -CONFIG_USB_STORAGE_JUMPSHOT=m -CONFIG_USB_STORAGE_ALAUDA=m -CONFIG_USB_STORAGE_ONETOUCH=m -CONFIG_USB_STORAGE_KARMA=m -CONFIG_USB_STORAGE_CYPRESS_ATACB=m -CONFIG_USB_STORAGE_ENE_UB6250=m +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set # # USB Imaging devices # -CONFIG_USB_MDC800=m -CONFIG_USB_MICROTEK=m +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set # CONFIG_USB_MUSB_HDRC is not set # CONFIG_USB_DWC3 is not set # CONFIG_USB_DWC2 is not set CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_OF=y +CONFIG_USB_CHIPIDEA_PCI=y CONFIG_USB_CHIPIDEA_UDC=y CONFIG_USB_CHIPIDEA_HOST=y # CONFIG_USB_CHIPIDEA_DEBUG is not set +# CONFIG_USB_ISP1760 is not set # # USB port drivers # -CONFIG_USB_USS720=m -CONFIG_USB_SERIAL=y -CONFIG_USB_SERIAL_CONSOLE=y +CONFIG_USB_SERIAL=m CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_SIMPLE=m -CONFIG_USB_SERIAL_AIRCABLE=m -CONFIG_USB_SERIAL_ARK3116=m -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_CH341=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_CP210X=m -CONFIG_USB_SERIAL_CYPRESS_M8=m -CONFIG_USB_SERIAL_EMPEG=m +# CONFIG_USB_SERIAL_SIMPLE is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set CONFIG_USB_SERIAL_FTDI_SIO=m -CONFIG_USB_SERIAL_VISOR=m -CONFIG_USB_SERIAL_IPAQ=m -CONFIG_USB_SERIAL_IR=m -CONFIG_USB_SERIAL_EDGEPORT=m -CONFIG_USB_SERIAL_EDGEPORT_TI=m +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set # CONFIG_USB_SERIAL_F81232 is not set -CONFIG_USB_SERIAL_GARMIN=m -CONFIG_USB_SERIAL_IPW=m -CONFIG_USB_SERIAL_IUU=m -CONFIG_USB_SERIAL_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_MCT_U232=m +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set # CONFIG_USB_SERIAL_METRO is not set -CONFIG_USB_SERIAL_MOS7720=m -CONFIG_USB_SERIAL_MOS7715_PARPORT=y -CONFIG_USB_SERIAL_MOS7840=m +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set # CONFIG_USB_SERIAL_MXUPORT is not set -CONFIG_USB_SERIAL_NAVMAN=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_OTI6858=m -CONFIG_USB_SERIAL_QCAUX=m -CONFIG_USB_SERIAL_QUALCOMM=m -CONFIG_USB_SERIAL_SPCP8X5=m -CONFIG_USB_SERIAL_SAFE=m -CONFIG_USB_SERIAL_SAFE_PADDED=y -CONFIG_USB_SERIAL_SIERRAWIRELESS=m -CONFIG_USB_SERIAL_SYMBOL=m -CONFIG_USB_SERIAL_TI=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set CONFIG_USB_SERIAL_WWAN=m CONFIG_USB_SERIAL_OPTION=m -CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_SERIAL_OPTICON=m -CONFIG_USB_SERIAL_XSENS_MT=m +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_WISHBONE is not set -# CONFIG_USB_SERIAL_ZTE is not set -CONFIG_USB_SERIAL_SSU100=m -CONFIG_USB_SERIAL_QT2=m -CONFIG_USB_SERIAL_DEBUG=m +# CONFIG_USB_SERIAL_SSU100 is not set +# CONFIG_USB_SERIAL_QT2 is not set +# CONFIG_USB_SERIAL_DEBUG is not set # # USB Miscellaneous drivers # -CONFIG_USB_EMI62=m -CONFIG_USB_EMI26=m -CONFIG_USB_ADUTUX=m -CONFIG_USB_SEVSEG=m +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set # CONFIG_USB_RIO500 is not set -CONFIG_USB_LEGOTOWER=m -CONFIG_USB_LCD=m -CONFIG_USB_LED=m +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set -CONFIG_USB_IDMOUSE=m -CONFIG_USB_FTDI_ELAN=m -CONFIG_USB_APPLEDISPLAY=m -CONFIG_USB_SISUSBVGA=m -CONFIG_USB_SISUSBVGA_CON=y -CONFIG_USB_LD=m -CONFIG_USB_TRANCEVIBRATOR=m -CONFIG_USB_IOWARRIOR=m +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set -# CONFIG_USB_EHSET_TEST_FIXTURE is not set -CONFIG_USB_ISIGHTFW=m -CONFIG_USB_YUREX=m -CONFIG_USB_EZUSB_FX2=m -CONFIG_USB_HSIC_USB3503=m -CONFIG_USB_ATM=m -CONFIG_USB_SPEEDTOUCH=m -CONFIG_USB_CXACRU=m -CONFIG_USB_UEAGLEATM=m -CONFIG_USB_XUSBATM=m +CONFIG_USB_EHSET_TEST_FIXTURE=m +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_CHAOSKEY is not set # # USB Physical Layer drivers # CONFIG_USB_PHY=y -# CONFIG_USB_OTG_FSM is not set CONFIG_NOP_USB_XCEIV=y # CONFIG_AM335X_PHY_USB is not set -# CONFIG_SAMSUNG_USB2PHY is not set -# CONFIG_SAMSUNG_USB3PHY is not set # CONFIG_USB_GPIO_VBUS is not set # CONFIG_USB_ISP1301 is not set CONFIG_USB_MXS_PHY=y -CONFIG_USB_RCAR_PHY=m # CONFIG_USB_ULPI is not set CONFIG_USB_GADGET=y # CONFIG_USB_GADGET_DEBUG is not set # CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set CONFIG_USB_GADGET_VBUS_DRAW=2 CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 @@ -4598,15 +3378,16 @@ CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 # CONFIG_USB_GR_UDC is not set # CONFIG_USB_R8A66597 is not set # CONFIG_USB_PXA27X is not set -# CONFIG_USB_S3C_HSOTG is not set # CONFIG_USB_MV_UDC is not set # CONFIG_USB_MV_U3D is not set # CONFIG_USB_M66592 is not set +# CONFIG_USB_BDC_UDC is not set # CONFIG_USB_AMD5536UDC is not set # CONFIG_USB_NET2272 is not set # CONFIG_USB_NET2280 is not set # CONFIG_USB_GOKU is not set # CONFIG_USB_EG20T is not set +# CONFIG_USB_GADGET_XILINX is not set # CONFIG_USB_DUMMY_HCD is not set CONFIG_USB_LIBCOMPOSITE=m CONFIG_USB_F_ACM=m @@ -4615,22 +3396,40 @@ CONFIG_USB_U_SERIAL=m CONFIG_USB_U_ETHER=m CONFIG_USB_F_SERIAL=m CONFIG_USB_F_OBEX=m +CONFIG_USB_F_NCM=m CONFIG_USB_F_ECM=m +CONFIG_USB_F_EEM=m CONFIG_USB_F_SUBSET=m CONFIG_USB_F_RNDIS=m CONFIG_USB_F_MASS_STORAGE=m -# CONFIG_USB_CONFIGFS is not set +CONFIG_USB_F_FS=m +CONFIG_USB_CONFIGFS=m +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_ACM=y +CONFIG_USB_CONFIGFS_OBEX=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_ECM=y +CONFIG_USB_CONFIGFS_ECM_SUBSET=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_EEM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_LB_SS=y +CONFIG_USB_CONFIGFS_F_FS=y +# CONFIG_USB_CONFIGFS_F_UAC1 is not set +# CONFIG_USB_CONFIGFS_F_UAC2 is not set +# CONFIG_USB_CONFIGFS_F_MIDI is not set +# CONFIG_USB_CONFIGFS_F_HID is not set +# CONFIG_USB_CONFIGFS_F_UVC is not set +# CONFIG_USB_CONFIGFS_F_PRINTER is not set CONFIG_USB_ZERO=m # CONFIG_USB_AUDIO is not set CONFIG_USB_ETH=m CONFIG_USB_ETH_RNDIS=y # CONFIG_USB_ETH_EEM is not set -# CONFIG_USB_G_NCM is not set -# CONFIG_USB_GADGETFS is not set +CONFIG_USB_G_NCM=m +CONFIG_USB_GADGETFS=m # CONFIG_USB_FUNCTIONFS is not set CONFIG_USB_MASS_STORAGE=m -# CONFIG_FSL_UTP is not set -# CONFIG_USB_GADGET_TARGET is not set CONFIG_USB_G_SERIAL=m # CONFIG_USB_MIDI_GADGET is not set # CONFIG_USB_G_PRINTER is not set @@ -4640,13 +3439,10 @@ CONFIG_USB_G_SERIAL=m # CONFIG_USB_G_HID is not set # CONFIG_USB_G_DBGP is not set # CONFIG_USB_G_WEBCAM is not set -CONFIG_UWB=m -CONFIG_UWB_HWA=m -CONFIG_UWB_WHCI=m -CONFIG_UWB_I1480U=m +# CONFIG_USB_LED_TRIG is not set +# CONFIG_UWB is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set -CONFIG_MMC_UNSAFE_RESUME=y # CONFIG_MMC_CLKGATE is not set # @@ -4655,7 +3451,7 @@ CONFIG_MMC_UNSAFE_RESUME=y CONFIG_MMC_BLOCK=y CONFIG_MMC_BLOCK_MINORS=8 CONFIG_MMC_BLOCK_BOUNCE=y -CONFIG_SDIO_UART=m +# CONFIG_SDIO_UART is not set # CONFIG_MMC_TEST is not set # @@ -4663,158 +3459,82 @@ CONFIG_SDIO_UART=m # CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_IO_ACCESSORS=y -CONFIG_MMC_SDHCI_PCI=m -CONFIG_MMC_RICOH_MMC=y +# CONFIG_MMC_SDHCI_PCI is not set CONFIG_MMC_SDHCI_PLTFM=y # CONFIG_MMC_SDHCI_OF_ARASAN is not set CONFIG_MMC_SDHCI_ESDHC_IMX=y -# CONFIG_MMC_SDHCI_PXAV3 is not set -# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_SDHCI_F_SDH30 is not set # CONFIG_MMC_MXC is not set -CONFIG_MMC_TIFM_SD=m -CONFIG_MMC_SDRICOH_CS=m -CONFIG_MMC_CB710=m -CONFIG_MMC_VIA_SDMMC=m +# CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_VIA_SDMMC is not set # CONFIG_MMC_DW is not set -CONFIG_MMC_VUB300=m -CONFIG_MMC_USHC=m -CONFIG_MMC_REALTEK_PCI=m -CONFIG_MEMSTICK=m -# CONFIG_MEMSTICK_DEBUG is not set - -# -# MemoryStick drivers -# -# CONFIG_MEMSTICK_UNSAFE_RESUME is not set -CONFIG_MSPRO_BLOCK=m -# CONFIG_MS_BLOCK is not set - -# -# MemoryStick Host Controller Drivers -# -CONFIG_MEMSTICK_TIFM_MS=m -CONFIG_MEMSTICK_JMICRON_38X=m -CONFIG_MEMSTICK_R592=m -CONFIG_MEMSTICK_REALTEK_PCI=m - -# -# MXC support drivers -# -CONFIG_MXC_IPU=y - -# -# MXC Vivante GPU support -# -CONFIG_MXC_GPU_VIV=y -CONFIG_MXC_IPU_V3=y - -# -# MXC Asynchronous Sample Rate Converter support -# -CONFIG_MXC_ASRC=y - -# -# MXC VPU(Video Processing Unit) support -# -CONFIG_MXC_VPU=y -# CONFIG_MXC_VPU_DEBUG is not set -# CONFIG_MX6_VPU_352M is not set - -# -# MXC HDMI CEC (Consumer Electronics Control) support -# -CONFIG_MXC_HDMI_CEC=y - -# -# MXC MIPI Support -# -CONFIG_MXC_MIPI_CSI2=y - -# -# MXC Media Local Bus Driver -# -CONFIG_MXC_MLB=y -CONFIG_MXC_MLB150=m +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MMC_TOSHIBA_PCI is not set +# CONFIG_MEMSTICK is not set +CONFIG_LEDS_GPIO_REGISTER=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set # # LED drivers # -CONFIG_LEDS_LM3530=m +# CONFIG_LEDS_LM3530 is not set # CONFIG_LEDS_LM3642 is not set # CONFIG_LEDS_PCA9532 is not set CONFIG_LEDS_GPIO=y -CONFIG_LEDS_LP3944=m -CONFIG_LEDS_LP55XX_COMMON=m -CONFIG_LEDS_LP5521=m -CONFIG_LEDS_LP5523=m -CONFIG_LEDS_LP5562=m +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_LP8860 is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA963X is not set -# CONFIG_LEDS_PCA9685 is not set # CONFIG_LEDS_DA9052 is not set # CONFIG_LEDS_DAC124S085 is not set -CONFIG_LEDS_PWM=y -CONFIG_LEDS_REGULATOR=m +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_REGULATOR is not set # CONFIG_LEDS_BD2802 is not set -CONFIG_LEDS_LT3593=m +# CONFIG_LEDS_LT3593 is not set # CONFIG_LEDS_MC13783 is not set # CONFIG_LEDS_TCA6507 is not set # CONFIG_LEDS_LM355x is not set -# CONFIG_LEDS_OT200 is not set -CONFIG_LEDS_BLINKM=m + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_SYSCON is not set +# CONFIG_LEDS_PM8941_WLED is not set # # LED Triggers # CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=m -CONFIG_LEDS_TRIGGER_ONESHOT=m -CONFIG_LEDS_TRIGGER_HEARTBEAT=m -CONFIG_LEDS_TRIGGER_BACKLIGHT=m +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y # CONFIG_LEDS_TRIGGER_CPU is not set CONFIG_LEDS_TRIGGER_GPIO=y -CONFIG_LEDS_TRIGGER_DEFAULT_ON=m +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set # # iptables trigger is under Netfilter config (LED target) # -CONFIG_LEDS_TRIGGER_TRANSIENT=m -CONFIG_LEDS_TRIGGER_CAMERA=m -CONFIG_ACCESSIBILITY=y -CONFIG_A11Y_BRAILLE_CONSOLE=y -CONFIG_INFINIBAND=m -CONFIG_INFINIBAND_USER_MAD=m -CONFIG_INFINIBAND_USER_ACCESS=m -CONFIG_INFINIBAND_USER_MEM=y -CONFIG_INFINIBAND_ADDR_TRANS=y -CONFIG_INFINIBAND_MTHCA=m -# CONFIG_INFINIBAND_MTHCA_DEBUG is not set -CONFIG_INFINIBAND_AMSO1100=m -# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set -CONFIG_INFINIBAND_CXGB3=m -# CONFIG_INFINIBAND_CXGB3_DEBUG is not set -CONFIG_INFINIBAND_CXGB4=m -CONFIG_MLX4_INFINIBAND=m -CONFIG_MLX5_INFINIBAND=m -CONFIG_INFINIBAND_NES=m -# CONFIG_INFINIBAND_NES_DEBUG is not set -# CONFIG_INFINIBAND_OCRDMA is not set -CONFIG_INFINIBAND_IPOIB=m -CONFIG_INFINIBAND_IPOIB_CM=y -CONFIG_INFINIBAND_IPOIB_DEBUG=y -CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y -CONFIG_INFINIBAND_SRP=m -CONFIG_INFINIBAND_SRPT=m -CONFIG_INFINIBAND_ISER=m -CONFIG_INFINIBAND_ISERT=m +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y CONFIG_RTC_HCTOSYS=y -# CONFIG_RTC_SYSTOHC is not set +CONFIG_RTC_SYSTOHC=y CONFIG_RTC_HCTOSYS_DEVICE="rtc0" # CONFIG_RTC_DEBUG is not set @@ -4824,36 +3544,38 @@ CONFIG_RTC_HCTOSYS_DEVICE="rtc0" CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y CONFIG_RTC_INTF_DEV=y -# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +CONFIG_RTC_INTF_DEV_UIE_EMUL=y # CONFIG_RTC_DRV_TEST is not set # # I2C RTC drivers # -CONFIG_RTC_DRV_DS1307=m -CONFIG_RTC_DRV_DS1374=m -CONFIG_RTC_DRV_DS1672=m -CONFIG_RTC_DRV_DS3232=m +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABX80X is not set +CONFIG_RTC_DRV_DS1307=y +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set # CONFIG_RTC_DRV_HYM8563 is not set -CONFIG_RTC_DRV_MAX6900=m -CONFIG_RTC_DRV_RS5C372=m -CONFIG_RTC_DRV_ISL1208=m -CONFIG_RTC_DRV_ISL12022=m +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +CONFIG_RTC_DRV_ISL1208=y +# CONFIG_RTC_DRV_ISL12022 is not set # CONFIG_RTC_DRV_ISL12057 is not set -CONFIG_RTC_DRV_X1205=m -CONFIG_RTC_DRV_PCF2127=m -CONFIG_RTC_DRV_PCF8523=y -CONFIG_RTC_DRV_PCF8563=m -CONFIG_RTC_DRV_PCF8583=m -CONFIG_RTC_DRV_M41T80=m -CONFIG_RTC_DRV_M41T80_WDT=y -CONFIG_RTC_DRV_BQ32K=m +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +CONFIG_RTC_DRV_PCF8563=y +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set # CONFIG_RTC_DRV_S35390A is not set -CONFIG_RTC_DRV_FM3130=m -CONFIG_RTC_DRV_RX8581=m -CONFIG_RTC_DRV_RX8025=m -CONFIG_RTC_DRV_EM3027=m -CONFIG_RTC_DRV_RV3029C2=m +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set # # SPI RTC drivers @@ -4861,6 +3583,8 @@ CONFIG_RTC_DRV_RV3029C2=m # CONFIG_RTC_DRV_M41T93 is not set # CONFIG_RTC_DRV_M41T94 is not set # CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set # CONFIG_RTC_DRV_DS1390 is not set # CONFIG_RTC_DRV_MAX6902 is not set # CONFIG_RTC_DRV_R9701 is not set @@ -4868,34 +3592,36 @@ CONFIG_RTC_DRV_RV3029C2=m # CONFIG_RTC_DRV_DS3234 is not set # CONFIG_RTC_DRV_PCF2123 is not set # CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_MCP795 is not set # # Platform RTC drivers # -CONFIG_RTC_DRV_CMOS=y -CONFIG_RTC_DRV_DS1286=m -CONFIG_RTC_DRV_DS1511=m -CONFIG_RTC_DRV_DS1553=m -CONFIG_RTC_DRV_DS1742=m +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set # CONFIG_RTC_DRV_DA9052 is not set -CONFIG_RTC_DRV_STK17TA8=m +# CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_M48T86 is not set -CONFIG_RTC_DRV_M48T35=m -CONFIG_RTC_DRV_M48T59=m -CONFIG_RTC_DRV_MSM6242=m -CONFIG_RTC_DRV_BQ4802=m -CONFIG_RTC_DRV_RP5C01=m -CONFIG_RTC_DRV_V3020=m -CONFIG_RTC_DRV_DS2404=m +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set # # on-CPU RTC drivers # # CONFIG_RTC_DRV_IMXDI is not set -# CONFIG_RTC_DRV_MC13XXX is not set +CONFIG_RTC_DRV_MC13XXX=y CONFIG_RTC_DRV_MXC=y CONFIG_RTC_DRV_SNVS=y -# CONFIG_RTC_DRV_MOXART is not set +# CONFIG_RTC_DRV_XGENE is not set # # HID Sensor RTC drivers @@ -4907,226 +3633,79 @@ CONFIG_DMADEVICES=y # # DMA Devices # -CONFIG_DW_DMAC_CORE=m -CONFIG_DW_DMAC=m -CONFIG_DW_DMAC_PCI=m +# CONFIG_DW_DMAC is not set +# CONFIG_DW_DMAC_PCI is not set +# CONFIG_HSU_DMA_PCI is not set CONFIG_MX3_IPU=y CONFIG_MX3_IPU_IRQS=4 -CONFIG_MXC_PXP_V2=y -CONFIG_MXC_PXP_CLIENT_DEVICE=y -# CONFIG_TIMB_DMA is not set CONFIG_IMX_SDMA=y # CONFIG_IMX_DMA is not set CONFIG_MXS_DMA=y +CONFIG_FSL_EDMA=y +# CONFIG_NBPFAXI_DMA is not set CONFIG_DMA_ENGINE=y +CONFIG_DMA_VIRTUAL_CHANNELS=y CONFIG_DMA_OF=y # # DMA Clients # -CONFIG_ASYNC_TX_DMA=y +# CONFIG_ASYNC_TX_DMA is not set # CONFIG_DMATEST is not set -CONFIG_AUXDISPLAY=y -CONFIG_KS0108=m -CONFIG_KS0108_PORT=0x378 -CONFIG_KS0108_DELAY=2 -CONFIG_UIO=m -CONFIG_UIO_CIF=m -# CONFIG_UIO_PDRV_GENIRQ is not set -# CONFIG_UIO_DMEM_GENIRQ is not set -CONFIG_UIO_AEC=m -CONFIG_UIO_SERCOS3=m -CONFIG_UIO_PCI_GENERIC=m -# CONFIG_UIO_NETX is not set -# CONFIG_UIO_MF624 is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_VFIO is not set # CONFIG_VIRT_DRIVERS is not set -CONFIG_VIRTIO=m # # Virtio drivers # -CONFIG_VIRTIO_PCI=m -CONFIG_VIRTIO_BALLOON=m -CONFIG_VIRTIO_MMIO=m -# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set +# CONFIG_VIRTIO_PCI is not set +# CONFIG_VIRTIO_MMIO is not set # # Microsoft Hyper-V guest support # CONFIG_STAGING=y -# CONFIG_ET131X is not set -# CONFIG_USBIP_CORE is not set -# CONFIG_W35UND is not set # CONFIG_PRISM2_USB is not set -# CONFIG_ECHO is not set # CONFIG_COMEDI is not set -# CONFIG_PANEL is not set -# CONFIG_R8187SE is not set # CONFIG_RTL8192U is not set -CONFIG_RTLLIB=m -CONFIG_RTLLIB_CRYPTO_CCMP=m -CONFIG_RTLLIB_CRYPTO_TKIP=m -CONFIG_RTLLIB_CRYPTO_WEP=m -CONFIG_RTL8192E=m -CONFIG_R8712U=m +# CONFIG_RTLLIB is not set +# CONFIG_R8712U is not set # CONFIG_R8188EU is not set -# CONFIG_R8821AE is not set -# CONFIG_RTS5139 is not set +# CONFIG_R8723AU is not set # CONFIG_RTS5208 is not set -# CONFIG_TRANZPORT is not set -# CONFIG_IDE_PHISON is not set -# CONFIG_LINE6_USB is not set -# CONFIG_USB_SERIAL_QUATECH2 is not set # CONFIG_VT6655 is not set # CONFIG_VT6656 is not set -# CONFIG_DX_SEP is not set - -# -# IIO staging drivers -# - -# -# Accelerometers -# -# CONFIG_ADIS16201 is not set -# CONFIG_ADIS16203 is not set -# CONFIG_ADIS16204 is not set -# CONFIG_ADIS16209 is not set -# CONFIG_ADIS16220 is not set -# CONFIG_ADIS16240 is not set -# CONFIG_LIS3L02DQ is not set -# CONFIG_SCA3000 is not set - -# -# Analog to digital converters -# -# CONFIG_AD7291 is not set -# CONFIG_AD7606 is not set -# CONFIG_AD799X is not set -# CONFIG_AD7780 is not set -# CONFIG_AD7816 is not set -# CONFIG_AD7192 is not set -# CONFIG_AD7280 is not set - -# -# Analog digital bi-direction converters -# -# CONFIG_ADT7316 is not set - -# -# Capacitance to digital converters -# -# CONFIG_AD7150 is not set -# CONFIG_AD7152 is not set -# CONFIG_AD7746 is not set - -# -# Direct Digital Synthesis -# -# CONFIG_AD5930 is not set -# CONFIG_AD9832 is not set -# CONFIG_AD9834 is not set -# CONFIG_AD9850 is not set -# CONFIG_AD9852 is not set -# CONFIG_AD9910 is not set -# CONFIG_AD9951 is not set - -# -# Digital gyroscope sensors -# -# CONFIG_ADIS16060 is not set - -# -# Network Analyzer, Impedance Converters -# -# CONFIG_AD5933 is not set - -# -# Light sensors -# -# CONFIG_SENSORS_ISL29018 is not set -# CONFIG_SENSORS_ISL29028 is not set -# CONFIG_TSL2583 is not set -# CONFIG_TSL2x7x is not set - -# -# Magnetometer sensors -# -# CONFIG_SENSORS_HMC5843 is not set - -# -# Active energy metering IC -# -# CONFIG_ADE7753 is not set -# CONFIG_ADE7754 is not set -# CONFIG_ADE7758 is not set -# CONFIG_ADE7759 is not set -# CONFIG_ADE7854 is not set - -# -# Resolver to digital converters -# -# CONFIG_AD2S90 is not set -# CONFIG_AD2S1200 is not set -# CONFIG_AD2S1210 is not set - -# -# Triggers - standalone -# -# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set -# CONFIG_IIO_SIMPLE_DUMMY is not set -# CONFIG_WLAGS49_H2 is not set -# CONFIG_WLAGS49_H25 is not set # CONFIG_FB_SM7XX is not set -CONFIG_CRYSTALHD=m +# CONFIG_FB_SM750 is not set # CONFIG_FB_XGI is not set -# CONFIG_USB_ENESTORAGE is not set -# CONFIG_BCM_WIMAX is not set # CONFIG_FT1000 is not set # # Speakup console speech # # CONFIG_SPEAKUP is not set -# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set -CONFIG_STAGING_MEDIA=y -# CONFIG_DVB_AS102 is not set -# CONFIG_DVB_CXD2099 is not set -# CONFIG_VIDEO_DT3155 is not set -# CONFIG_VIDEO_GO7007 is not set -# CONFIG_USB_MSI3101 is not set -# CONFIG_VIDEO_TCM825X is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_SOLO6X10 is not set -CONFIG_LIRC_STAGING=y -CONFIG_LIRC_BT829=m -CONFIG_LIRC_IGORPLUGUSB=m -CONFIG_LIRC_IMON=m -CONFIG_LIRC_PARALLEL=m -CONFIG_LIRC_GPIO=m -CONFIG_LIRC_SASEM=m -CONFIG_LIRC_SERIAL=m -CONFIG_LIRC_SERIAL_TRANSMITTER=y -CONFIG_LIRC_SIR=m -CONFIG_LIRC_ZILOG=m +# CONFIG_STAGING_MEDIA is not set # # Android # -# CONFIG_ANDROID is not set # CONFIG_USB_WPAN_HCD is not set # CONFIG_WIMAX_GDM72XX is not set # CONFIG_LTE_GDM724X is not set -# CONFIG_NET_VENDOR_SILICOM is not set -# CONFIG_CED1401 is not set -# CONFIG_DRM_IMX is not set -# CONFIG_DGRP is not set -# CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_MTD_SPINAND_MT29F is not set # CONFIG_LUSTRE_FS is not set -# CONFIG_XILLYBUS is not set # CONFIG_DGNC is not set # CONFIG_DGAP is not set +# CONFIG_GS_FPGABOOT is not set +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set +# CONFIG_FB_TFT is not set +# CONFIG_I2O is not set +CONFIG_DRM_ETNAVIV=y +# CONFIG_DRM_ETNAVIV_REGISTER_LOGGING is not set +# CONFIG_CHROME_PLATFORMS is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_COMMON_CLK=y @@ -5136,15 +3715,37 @@ CONFIG_COMMON_CLK=y # # CONFIG_COMMON_CLK_SI5351 is not set # CONFIG_COMMON_CLK_SI570 is not set -# CONFIG_COMMON_CLK_QCOM is not set +# CONFIG_CLK_QORIQ is not set +# CONFIG_COMMON_CLK_PWM is not set +# CONFIG_COMMON_CLK_PXA is not set +# CONFIG_COMMON_CLK_CDCE706 is not set # # Hardware Spinlock drivers # + +# +# Clock Source drivers +# CONFIG_CLKSRC_OF=y CONFIG_CLKSRC_MMIO=y +CONFIG_ARM_GLOBAL_TIMER=y +CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y +# CONFIG_ATMEL_PIT is not set +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_SH_TIMER_MTU2 is not set +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_EM_TIMER_STI is not set # CONFIG_MAILBOX is not set -# CONFIG_IOMMU_SUPPORT is not set +CONFIG_IOMMU_API=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +CONFIG_OF_IOMMU=y +# CONFIG_ARM_SMMU is not set # # Remoteproc drivers @@ -5154,166 +3755,19 @@ CONFIG_CLKSRC_MMIO=y # # Rpmsg drivers # + +# +# SOC (System On Chip) specific Drivers +# +# CONFIG_SOC_TI is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set -CONFIG_IIO=m -CONFIG_IIO_BUFFER=y -CONFIG_IIO_BUFFER_CB=y -CONFIG_IIO_KFIFO_BUF=m -CONFIG_IIO_TRIGGERED_BUFFER=m -CONFIG_IIO_TRIGGER=y -CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 - -# -# Accelerometers -# -# CONFIG_BMA180 is not set -CONFIG_HID_SENSOR_ACCEL_3D=m -CONFIG_IIO_ST_ACCEL_3AXIS=m -CONFIG_IIO_ST_ACCEL_I2C_3AXIS=m -CONFIG_IIO_ST_ACCEL_SPI_3AXIS=m -# CONFIG_KXSD9 is not set - -# -# Analog to digital converters -# -# CONFIG_AD7266 is not set -# CONFIG_AD7298 is not set -# CONFIG_AD7476 is not set -# CONFIG_AD7791 is not set -# CONFIG_AD7793 is not set -# CONFIG_AD7887 is not set -# CONFIG_AD7923 is not set -# CONFIG_EXYNOS_ADC is not set -# CONFIG_MAX1363 is not set -# CONFIG_MCP320X is not set -# CONFIG_MCP3422 is not set -# CONFIG_NAU7802 is not set -# CONFIG_TI_ADC081C is not set -# CONFIG_VIPERBOARD_ADC is not set - -# -# Amplifiers -# -# CONFIG_AD8366 is not set - -# -# Hid Sensor IIO Common -# -CONFIG_HID_SENSOR_IIO_COMMON=m -CONFIG_HID_SENSOR_IIO_TRIGGER=m -CONFIG_IIO_ST_SENSORS_I2C=m -CONFIG_IIO_ST_SENSORS_SPI=m -CONFIG_IIO_ST_SENSORS_CORE=m - -# -# Digital to analog converters -# -# CONFIG_AD5064 is not set -# CONFIG_AD5360 is not set -# CONFIG_AD5380 is not set -# CONFIG_AD5421 is not set -# CONFIG_AD5446 is not set -# CONFIG_AD5449 is not set -# CONFIG_AD5504 is not set -# CONFIG_AD5624R_SPI is not set -# CONFIG_AD5686 is not set -# CONFIG_AD5755 is not set -# CONFIG_AD5764 is not set -# CONFIG_AD5791 is not set -# CONFIG_AD7303 is not set -# CONFIG_MAX517 is not set -# CONFIG_MCP4725 is not set - -# -# Frequency Synthesizers DDS/PLL -# - -# -# Clock Generator/Distribution -# -# CONFIG_AD9523 is not set - -# -# Phase-Locked Loop (PLL) frequency synthesizers -# -# CONFIG_ADF4350 is not set - -# -# Digital gyroscope sensors -# -# CONFIG_ADIS16080 is not set -# CONFIG_ADIS16130 is not set -# CONFIG_ADIS16136 is not set -# CONFIG_ADIS16260 is not set -# CONFIG_ADXRS450 is not set -CONFIG_HID_SENSOR_GYRO_3D=m -CONFIG_IIO_ST_GYRO_3AXIS=m -CONFIG_IIO_ST_GYRO_I2C_3AXIS=m -CONFIG_IIO_ST_GYRO_SPI_3AXIS=m -# CONFIG_ITG3200 is not set - -# -# Humidity sensors -# -# CONFIG_DHT11 is not set - -# -# Inertial measurement units -# -# CONFIG_ADIS16400 is not set -# CONFIG_ADIS16480 is not set -# CONFIG_INV_MPU6050_IIO is not set - -# -# Light sensors -# -# CONFIG_ADJD_S311 is not set -# CONFIG_APDS9300 is not set -# CONFIG_CM32181 is not set -# CONFIG_CM36651 is not set -# CONFIG_GP2AP020A00F is not set -CONFIG_HID_SENSOR_ALS=m -# CONFIG_TCS3472 is not set -# CONFIG_SENSORS_TSL2563 is not set -# CONFIG_TSL4531 is not set -# CONFIG_VCNL4000 is not set - -# -# Magnetometer sensors -# -# CONFIG_AK8975 is not set -# CONFIG_MAG3110 is not set -CONFIG_HID_SENSOR_MAGNETOMETER_3D=m -CONFIG_IIO_ST_MAGN_3AXIS=m -CONFIG_IIO_ST_MAGN_I2C_3AXIS=m -CONFIG_IIO_ST_MAGN_SPI_3AXIS=m - -# -# Inclinometer sensors -# -CONFIG_HID_SENSOR_INCLINOMETER_3D=m - -# -# Triggers - standalone -# -CONFIG_IIO_INTERRUPT_TRIGGER=m -# CONFIG_IIO_SYSFS_TRIGGER is not set - -# -# Pressure sensors -# -# CONFIG_MPL3115 is not set -# CONFIG_IIO_ST_PRESS is not set - -# -# Temperature sensors -# -# CONFIG_TMP006 is not set +# CONFIG_IIO is not set # CONFIG_VME_BUS is not set CONFIG_PWM=y CONFIG_PWM_SYSFS=y +# CONFIG_PWM_FSL_FTM is not set CONFIG_PWM_IMX=y # CONFIG_PWM_PCA9685 is not set CONFIG_IRQCHIP=y @@ -5321,98 +3775,96 @@ CONFIG_ARM_GIC=y # CONFIG_IPACK_BUS is not set CONFIG_ARCH_HAS_RESET_CONTROLLER=y CONFIG_RESET_CONTROLLER=y -CONFIG_RESET_GPIO=y -CONFIG_FMC=m -CONFIG_FMC_FAKEDEV=m -CONFIG_FMC_TRIVIAL=m -CONFIG_FMC_WRITE_EEPROM=m -CONFIG_FMC_CHARDEV=m +# CONFIG_FMC is not set # # PHY Subsystem # -CONFIG_GENERIC_PHY=y -# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set -# CONFIG_PHY_EXYNOS_DP_VIDEO is not set +# CONFIG_GENERIC_PHY is not set # CONFIG_BCM_KONA_USB2_PHY is not set # CONFIG_POWERCAP is not set +# CONFIG_MCB is not set + +# +# Consumer Electronics Control devices +# +CONFIG_RAS=y +# CONFIG_THUNDERBOLT is not set + +# +# Android +# +# CONFIG_ANDROID is not set + +# +# Firmware Drivers +# +# CONFIG_FIRMWARE_MEMMAP is not set # # File systems # CONFIG_DCACHE_WORD_ACCESS=y -# CONFIG_EXT2_FS is not set -# CONFIG_EXT3_FS is not set +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_DEFAULTS_TO_ORDERED=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y CONFIG_EXT4_FS=y -CONFIG_EXT4_USE_FOR_EXT23=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_ENCRYPTION is not set # CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set CONFIG_JBD2=y # CONFIG_JBD2_DEBUG is not set CONFIG_FS_MBCACHE=y -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -CONFIG_REISERFS_PROC_INFO=y -CONFIG_REISERFS_FS_XATTR=y -CONFIG_REISERFS_FS_POSIX_ACL=y -CONFIG_REISERFS_FS_SECURITY=y -CONFIG_JFS_FS=m -CONFIG_JFS_POSIX_ACL=y -CONFIG_JFS_SECURITY=y -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -CONFIG_XFS_FS=m -CONFIG_XFS_QUOTA=y -CONFIG_XFS_POSIX_ACL=y -# CONFIG_XFS_RT is not set -# CONFIG_XFS_WARN is not set -# CONFIG_XFS_DEBUG is not set -CONFIG_GFS2_FS=m -CONFIG_GFS2_FS_LOCKING_DLM=y -CONFIG_OCFS2_FS=m -CONFIG_OCFS2_FS_O2CB=m -CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m -# CONFIG_OCFS2_DEBUG_MASKLOG is not set -# CONFIG_OCFS2_DEBUG_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set CONFIG_BTRFS_FS=m CONFIG_BTRFS_FS_POSIX_ACL=y # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set # CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set # CONFIG_BTRFS_DEBUG is not set # CONFIG_BTRFS_ASSERT is not set -CONFIG_NILFS2_FS=m +# CONFIG_NILFS2_FS is not set +CONFIG_F2FS_FS=m +CONFIG_F2FS_STAT_FS=y +CONFIG_F2FS_FS_XATTR=y +CONFIG_F2FS_FS_POSIX_ACL=y +CONFIG_F2FS_FS_SECURITY=y +# CONFIG_F2FS_CHECK_FS is not set CONFIG_FS_POSIX_ACL=y CONFIG_EXPORTFS=y CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y CONFIG_INOTIFY_USER=y -CONFIG_FANOTIFY=y -CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y +# CONFIG_FANOTIFY is not set CONFIG_QUOTA=y CONFIG_QUOTA_NETLINK_INTERFACE=y # CONFIG_PRINT_QUOTA_WARNING is not set # CONFIG_QUOTA_DEBUG is not set -CONFIG_QUOTA_TREE=y # CONFIG_QFMT_V1 is not set -CONFIG_QFMT_V2=y +# CONFIG_QFMT_V2 is not set CONFIG_QUOTACTL=y CONFIG_AUTOFS4_FS=y CONFIG_FUSE_FS=y -CONFIG_CUSE=m +# CONFIG_CUSE is not set +# CONFIG_OVERLAY_FS is not set # # Caches # -CONFIG_FSCACHE=m -CONFIG_FSCACHE_STATS=y -# CONFIG_FSCACHE_HISTOGRAM is not set -# CONFIG_FSCACHE_DEBUG is not set -CONFIG_FSCACHE_OBJECT_LIST=y -CONFIG_CACHEFILES=m -# CONFIG_CACHEFILES_DEBUG is not set -# CONFIG_CACHEFILES_HISTOGRAM is not set +# CONFIG_FSCACHE is not set # # CD-ROM/DVD Filesystems @@ -5430,7 +3882,7 @@ CONFIG_FAT_FS=y CONFIG_MSDOS_FS=m CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_FS is not set # @@ -5439,179 +3891,127 @@ CONFIG_FAT_DEFAULT_IOCHARSET="ascii" CONFIG_PROC_FS=y CONFIG_PROC_SYSCTL=y CONFIG_PROC_PAGE_MONITOR=y +CONFIG_KERNFS=y CONFIG_SYSFS=y CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y -CONFIG_TMPFS_XATTR=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set # CONFIG_HUGETLB_PAGE is not set -CONFIG_CONFIGFS_FS=y +CONFIG_CONFIGFS_FS=m CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set -CONFIG_AFFS_FS=m -CONFIG_ECRYPT_FS=m -# CONFIG_ECRYPT_FS_MESSAGING is not set -CONFIG_HFS_FS=m -CONFIG_HFSPLUS_FS=m -# CONFIG_HFSPLUS_FS_POSIX_ACL is not set -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_UBIFS_FS=y +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y # CONFIG_LOGFS is not set -CONFIG_CRAMFS=m -CONFIG_SQUASHFS=m -CONFIG_SQUASHFS_FILE_CACHE=y -# CONFIG_SQUASHFS_FILE_DIRECT is not set -CONFIG_SQUASHFS_DECOMP_SINGLE=y -# CONFIG_SQUASHFS_DECOMP_MULTI is not set -# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set -CONFIG_SQUASHFS_XATTR=y -CONFIG_SQUASHFS_ZLIB=y -CONFIG_SQUASHFS_LZO=y -CONFIG_SQUASHFS_XZ=y -# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set -# CONFIG_SQUASHFS_EMBEDDED is not set -CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set -CONFIG_MINIX_FS=m +# CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set # CONFIG_QNX6FS_FS is not set -CONFIG_ROMFS_FS=m -CONFIG_ROMFS_BACKED_BY_BLOCK=y -CONFIG_ROMFS_ON_BLOCK=y -CONFIG_PSTORE=y -# CONFIG_PSTORE_CONSOLE is not set -CONFIG_PSTORE_RAM=m -CONFIG_SYSV_FS=m -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set -# CONFIG_UFS_DEBUG is not set -# CONFIG_EXOFS_FS is not set -# CONFIG_F2FS_FS is not set -CONFIG_ORE=m +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y -# CONFIG_NFS_V2 is not set +CONFIG_NFS_V2=y CONFIG_NFS_V3=y CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y -CONFIG_NFS_SWAP=y -CONFIG_NFS_V4_1=y -CONFIG_NFS_V4_2=y -CONFIG_PNFS_FILE_LAYOUT=y -CONFIG_PNFS_BLOCK=y -CONFIG_PNFS_OBJLAYOUT=m -CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" -# CONFIG_NFS_V4_1_MIGRATION is not set -CONFIG_NFS_V4_SECURITY_LABEL=y +# CONFIG_NFS_SWAP is not set +# CONFIG_NFS_V4_1 is not set CONFIG_ROOT_NFS=y # CONFIG_NFS_USE_LEGACY_DNS is not set CONFIG_NFS_USE_KERNEL_DNS=y -CONFIG_NFS_DEBUG=y -CONFIG_NFSD=m -CONFIG_NFSD_V2_ACL=y -CONFIG_NFSD_V3=y -CONFIG_NFSD_V3_ACL=y -CONFIG_NFSD_V4=y -CONFIG_NFSD_V4_SECURITY_LABEL=y -# CONFIG_NFSD_FAULT_INJECTION is not set +# CONFIG_NFSD is not set +CONFIG_GRACE_PERIOD=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_NFS_ACL_SUPPORT=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y -CONFIG_SUNRPC_BACKCHANNEL=y -CONFIG_SUNRPC_XPRT_RDMA=m -CONFIG_SUNRPC_SWAP=y -CONFIG_RPCSEC_GSS_KRB5=m -CONFIG_SUNRPC_DEBUG=y -CONFIG_CEPH_FS=m -CONFIG_CEPH_FSCACHE=y -CONFIG_CEPH_FS_POSIX_ACL=y -CONFIG_CIFS=m -CONFIG_CIFS_STATS=y -# CONFIG_CIFS_STATS2 is not set -CONFIG_CIFS_WEAK_PW_HASH=y -CONFIG_CIFS_UPCALL=y -CONFIG_CIFS_XATTR=y -CONFIG_CIFS_POSIX=y -CONFIG_CIFS_ACL=y -CONFIG_CIFS_DEBUG=y -# CONFIG_CIFS_DEBUG2 is not set -CONFIG_CIFS_DFS_UPCALL=y -CONFIG_CIFS_SMB2=y -CONFIG_CIFS_FSCACHE=y -CONFIG_NCP_FS=m -CONFIG_NCPFS_PACKET_SIGNING=y -CONFIG_NCPFS_IOCTL_LOCKING=y -CONFIG_NCPFS_STRONG=y -CONFIG_NCPFS_NFS_NS=y -CONFIG_NCPFS_OS2_NS=y -CONFIG_NCPFS_SMALLDOS=y -CONFIG_NCPFS_NLS=y -CONFIG_NCPFS_EXTRAS=y -CONFIG_CODA_FS=m +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set -CONFIG_9P_FS=m -CONFIG_9P_FSCACHE=y -CONFIG_9P_FS_POSIX_ACL=y -CONFIG_9P_FS_SECURITY=y CONFIG_NLS=y CONFIG_NLS_DEFAULT="cp437" CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_MAC_ROMAN=m -CONFIG_NLS_MAC_CELTIC=m -CONFIG_NLS_MAC_CENTEURO=m -CONFIG_NLS_MAC_CROATIAN=m -CONFIG_NLS_MAC_CYRILLIC=m -CONFIG_NLS_MAC_GAELIC=m -CONFIG_NLS_MAC_GREEK=m -CONFIG_NLS_MAC_ICELAND=m -CONFIG_NLS_MAC_INUIT=m -CONFIG_NLS_MAC_ROMANIAN=m -CONFIG_NLS_MAC_TURKISH=m +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set CONFIG_NLS_UTF8=y -CONFIG_DLM=m -CONFIG_DLM_DEBUG=y +# CONFIG_DLM is not set # # Kernel hacking @@ -5621,30 +4021,34 @@ CONFIG_DLM_DEBUG=y # printk and dmesg options # CONFIG_PRINTK_TIME=y -CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 -CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_DYNAMIC_DEBUG is not set # # Compile-time checks and compiler options # # CONFIG_DEBUG_INFO is not set -# CONFIG_ENABLE_WARN_DEPRECATED is not set +CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 -CONFIG_STRIP_ASM_SYMS=y +# CONFIG_STRIP_ASM_SYMS is not set # CONFIG_READABLE_ASM is not set -CONFIG_UNUSED_SYMBOLS=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set CONFIG_DEBUG_FS=y -CONFIG_HEADERS_CHECK=y +# CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_FRAME_POINTER=y # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set CONFIG_MAGIC_SYSRQ=y -CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x0 +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 CONFIG_DEBUG_KERNEL=y # # Memory Debugging # +# CONFIG_PAGE_EXTENSION is not set # CONFIG_DEBUG_PAGEALLOC is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_SLUB_STATS is not set @@ -5660,37 +4064,38 @@ CONFIG_HAVE_DEBUG_KMEMLEAK=y # # Debug Lockups and Hangs # -CONFIG_LOCKUP_DETECTOR=y -# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set -CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 -CONFIG_DETECT_HUNG_TASK=y -CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 -# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set # CONFIG_PANIC_ON_OOPS is not set CONFIG_PANIC_ON_OOPS_VALUE=0 CONFIG_PANIC_TIMEOUT=0 # CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set -CONFIG_TIMER_STATS=y +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_TIMER_STATS is not set # # Lock Debugging (spinlocks, mutexes, etc...) # # CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_MUTEXES is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y # CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=y +CONFIG_LOCKDEP=y # CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_LOCKDEP is not set # CONFIG_DEBUG_ATOMIC_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +CONFIG_TRACE_IRQFLAGS=y +CONFIG_STACKTRACE=y # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_BUGVERBOSE is not set -# CONFIG_DEBUG_WRITECOUNT is not set # CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set # CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_NOTIFIERS is not set # CONFIG_DEBUG_CREDENTIALS is not set @@ -5698,10 +4103,13 @@ CONFIG_TIMER_STATS=y # # RCU Debugging # +CONFIG_PROVE_RCU=y +# CONFIG_PROVE_RCU_REPEATEDLY is not set # CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_TORTURE_TEST is not set # CONFIG_RCU_TORTURE_TEST is not set -CONFIG_RCU_CPU_STALL_TIMEOUT=60 -# CONFIG_RCU_CPU_STALL_INFO is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +CONFIG_RCU_CPU_STALL_INFO=y # CONFIG_RCU_TRACE is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_NOTIFIER_ERROR_INJECTION is not set @@ -5712,75 +4120,61 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_HAVE_C_RECORDMCOUNT=y -CONFIG_TRACE_CLOCK=y -CONFIG_RING_BUFFER=y -CONFIG_RING_BUFFER_ALLOW_SWAP=y CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set # # Runtime Testing # +# CONFIG_LKDTM is not set # CONFIG_TEST_LIST_SORT is not set -# CONFIG_KPROBES_SANITY_TEST is not set # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_RBTREE_TEST is not set # CONFIG_INTERVAL_TREE_TEST is not set # CONFIG_PERCPU_TEST is not set -CONFIG_ATOMIC64_SELFTEST=y -CONFIG_ASYNC_RAID6_TEST=m +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_HEXDUMP is not set # CONFIG_TEST_STRING_HELPERS is not set -CONFIG_TEST_KSTRTOX=y -CONFIG_BUILD_DOCSRC=y +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_RHASHTABLE is not set # CONFIG_DMA_API_DEBUG is not set -# CONFIG_TEST_MODULE is not set +# CONFIG_TEST_LKM is not set # CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_MEMTEST is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set # CONFIG_ARM_PTDUMP is not set # CONFIG_STRICT_DEVMEM is not set -CONFIG_ARM_UNWIND=y +# CONFIG_ARM_UNWIND is not set # CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_LL is not set CONFIG_DEBUG_IMX_UART_PORT=1 +CONFIG_DEBUG_VF_UART_PORT=1 CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" -# CONFIG_DEBUG_UART_PL01X is not set # CONFIG_DEBUG_UART_8250 is not set +# CONFIG_DEBUG_UART_BCM63XX is not set CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" -# CONFIG_ARM_KPROBES_TEST is not set # CONFIG_PID_IN_CONTEXTIDR is not set -CONFIG_DEBUG_SET_MODULE_RONX=y +# CONFIG_DEBUG_SET_MODULE_RONX is not set +# CONFIG_CORESIGHT is not set # # Security options # CONFIG_KEYS=y -CONFIG_PERSISTENT_KEYRINGS=y -CONFIG_BIG_KEYS=y -CONFIG_TRUSTED_KEYS=m -CONFIG_ENCRYPTED_KEYS=m -CONFIG_KEYS_DEBUG_PROC_KEYS=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_ENCRYPTED_KEYS is not set # CONFIG_SECURITY_DMESG_RESTRICT is not set -CONFIG_SECURITY=y +# CONFIG_SECURITY is not set CONFIG_SECURITYFS=y -CONFIG_SECURITY_NETWORK=y -CONFIG_SECURITY_NETWORK_XFRM=y -# CONFIG_SECURITY_PATH is not set -# CONFIG_SECURITY_SELINUX is not set -# CONFIG_SECURITY_SMACK is not set -# CONFIG_SECURITY_TOMOYO is not set -# CONFIG_SECURITY_APPARMOR is not set -# CONFIG_SECURITY_YAMA is not set -# CONFIG_IMA is not set CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" CONFIG_XOR_BLOCKS=m -CONFIG_ASYNC_CORE=m -CONFIG_ASYNC_MEMCPY=m -CONFIG_ASYNC_XOR=m -CONFIG_ASYNC_PQ=m -CONFIG_ASYNC_RAID6_RECOV=m CONFIG_CRYPTO=y # @@ -5796,20 +4190,19 @@ CONFIG_CRYPTO_HASH=y CONFIG_CRYPTO_HASH2=y CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_PCOMP=m CONFIG_CRYPTO_PCOMP2=y CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_USER=y -# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set +# CONFIG_CRYPTO_USER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y CONFIG_CRYPTO_GF128MUL=y CONFIG_CRYPTO_NULL=y -CONFIG_CRYPTO_PCRYPT=m +# CONFIG_CRYPTO_PCRYPT is not set CONFIG_CRYPTO_WORKQUEUE=y -CONFIG_CRYPTO_CRYPTD=y -CONFIG_CRYPTO_AUTHENC=m -CONFIG_CRYPTO_TEST=m -CONFIG_CRYPTO_ABLK_HELPER=y +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_MCRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set # # Authenticated Encryption with Associated Data @@ -5821,88 +4214,82 @@ CONFIG_CRYPTO_SEQIV=y # # Block modes # -CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CBC is not set CONFIG_CRYPTO_CTR=y -CONFIG_CRYPTO_CTS=y +# CONFIG_CRYPTO_CTS is not set CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_LRW=y -CONFIG_CRYPTO_PCBC=m -CONFIG_CRYPTO_XTS=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set # # Hash modes # -CONFIG_CRYPTO_CMAC=m -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_XCBC=m -CONFIG_CRYPTO_VMAC=m +CONFIG_CRYPTO_CMAC=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set # # Digest # CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_CRC32=m +# CONFIG_CRYPTO_CRC32 is not set CONFIG_CRYPTO_CRCT10DIF=y CONFIG_CRYPTO_GHASH=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_MICHAEL_MIC=y -CONFIG_CRYPTO_RMD128=y -CONFIG_CRYPTO_RMD160=y -CONFIG_CRYPTO_RMD256=y -CONFIG_CRYPTO_RMD320=y -CONFIG_CRYPTO_SHA1=y -# CONFIG_CRYPTO_SHA1_ARM is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_TGR192=y -CONFIG_CRYPTO_WP512=y +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set # # Ciphers # CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_AES_ARM=y -CONFIG_CRYPTO_AES_ARM_BS=y -CONFIG_CRYPTO_ANUBIS=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_BLOWFISH=y -CONFIG_CRYPTO_BLOWFISH_COMMON=y -CONFIG_CRYPTO_CAMELLIA=y -CONFIG_CRYPTO_CAST_COMMON=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_FCRYPT=m -CONFIG_CRYPTO_KHAZAD=m -CONFIG_CRYPTO_SALSA20=m -CONFIG_CRYPTO_SEED=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_TWOFISH_COMMON=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set # # Compression # -CONFIG_CRYPTO_DEFLATE=m -CONFIG_CRYPTO_ZLIB=m +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_ZLIB is not set CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_LZ4=m -CONFIG_CRYPTO_LZ4HC=m +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set # # Random Number Generation # # CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRYPTO_USER_API=y -CONFIG_CRYPTO_USER_API_HASH=y -CONFIG_CRYPTO_USER_API_SKCIPHER=y -CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_DEV_HIFN_795X=m -CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y -# CONFIG_CRYPTO_DEV_SAHARA is not set +# CONFIG_CRYPTO_DRBG_MENU is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +# CONFIG_CRYPTO_HW is not set # CONFIG_ASYMMETRIC_KEY_TYPE is not set +# CONFIG_ARM_CRYPTO is not set # CONFIG_BINARY_PRINTF is not set # @@ -5910,6 +4297,7 @@ CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y # CONFIG_RAID6_PQ=m CONFIG_BITREVERSE=y +# CONFIG_HAVE_ARCH_BITREVERSE is not set CONFIG_RATIONAL=y CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y @@ -5930,47 +4318,45 @@ CONFIG_CRC32_SLICEBY8=y # CONFIG_CRC32_BIT is not set CONFIG_CRC7=m CONFIG_LIBCRC32C=m -CONFIG_CRC8=m -CONFIG_AUDIT_GENERIC=y +# CONFIG_CRC8 is not set +# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set # CONFIG_RANDOM32_SELFTEST is not set CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y CONFIG_LZO_COMPRESS=y CONFIG_LZO_DECOMPRESS=y -CONFIG_LZ4_COMPRESS=m -CONFIG_LZ4HC_COMPRESS=m -CONFIG_LZ4_DECOMPRESS=m +CONFIG_LZ4_DECOMPRESS=y CONFIG_XZ_DEC=y CONFIG_XZ_DEC_X86=y CONFIG_XZ_DEC_POWERPC=y -# CONFIG_XZ_DEC_IA64 is not set +CONFIG_XZ_DEC_IA64=y CONFIG_XZ_DEC_ARM=y -# CONFIG_XZ_DEC_ARMTHUMB is not set -# CONFIG_XZ_DEC_SPARC is not set +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_SPARC=y CONFIG_XZ_DEC_BCJ=y # CONFIG_XZ_DEC_TEST is not set CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y CONFIG_GENERIC_ALLOCATOR=y -CONFIG_REED_SOLOMON=m -CONFIG_REED_SOLOMON_ENC8=y -CONFIG_REED_SOLOMON_DEC8=y -CONFIG_TEXTSEARCH=y -CONFIG_TEXTSEARCH_KMP=m -CONFIG_TEXTSEARCH_BM=m -CONFIG_TEXTSEARCH_FSM=m CONFIG_ASSOCIATIVE_ARRAY=y CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y CONFIG_HAS_DMA=y -CONFIG_CHECK_SIGNATURE=y CONFIG_CPU_RMAP=y CONFIG_DQL=y +CONFIG_GLOB=y +# CONFIG_GLOB_SELFTEST is not set CONFIG_NLATTR=y +CONFIG_GENERIC_ATOMIC64=y CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y -CONFIG_LRU_CACHE=m CONFIG_AVERAGE=y -CONFIG_CORDIC=m +# CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_LIBFDT=y CONFIG_OID_REGISTRY=y CONFIG_FONT_SUPPORT=y CONFIG_FONTS=y @@ -5981,7 +4367,9 @@ CONFIG_FONT_8x16=y # CONFIG_FONT_PEARL_8x8 is not set # CONFIG_FONT_ACORN_8x8 is not set # CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_6x10 is not set # CONFIG_FONT_SUN8x16 is not set # CONFIG_FONT_SUN12x22 is not set # CONFIG_FONT_10x18 is not set +CONFIG_ARCH_HAS_SG_CHAIN=y # CONFIG_VIRTUALIZATION is not set diff --git a/config/linux-cubox.config b/config/linux-cubox.config new file mode 100644 index 000000000..f3232e2ea --- /dev/null +++ b/config/linux-cubox.config @@ -0,0 +1,6003 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.14.53 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_MIGHT_HAVE_PCI=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_GENERIC_BUG=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_HAVE_KERNEL_LZ4=y +# CONFIG_KERNEL_GZIP is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_XZ is not set +CONFIG_KERNEL_LZO=y +# CONFIG_KERNEL_LZ4 is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_FHANDLE=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +CONFIG_AUDIT_WATCH=y +CONFIG_AUDIT_TREE=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +CONFIG_KTIME_SCALAR=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +# CONFIG_IRQ_TIME_ACCOUNTING is not set +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_PREEMPT_RCU is not set +CONFIG_RCU_STALL_COMMON=y +# CONFIG_RCU_USER_QS is not set +CONFIG_RCU_FANOUT=32 +CONFIG_RCU_FANOUT_LEAF=16 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_RCU_FAST_NO_HZ is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_NOCB_CPU is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_MEMCG_SWAP_ENABLED=y +CONFIG_MEMCG_KMEM=y +CONFIG_CGROUP_PERF=y +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_CGROUP=y +# CONFIG_DEBUG_BLK_CGROUP is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +CONFIG_USER_NS=y +CONFIG_PID_NS=y +CONFIG_NET_NS=y +CONFIG_SCHED_AUTOGROUP=y +CONFIG_MM_OWNER=y +# CONFIG_SYSFS_DEPRECATED is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_EXPERT=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_PCI_QUIRKS=y +# CONFIG_EMBEDDED is not set +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_SYSTEM_TRUSTED_KEYRING is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_HAVE_OPROFILE=y +CONFIG_KPROBES=y +# CONFIG_JUMP_LABEL is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_KRETPROBES=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP_FILTER=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR is not set +CONFIG_CC_STACKPROTECTOR_NONE=y +# CONFIG_CC_STACKPROTECTOR_REGULAR is not set +# CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_MODULE_SIG is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +CONFIG_BLK_DEV_BSG=y +CONFIG_BLK_DEV_BSGLIB=y +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_BLK_DEV_THROTTLING=y +# CONFIG_BLK_CMDLINE_PARSER is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_AIX_PARTITION=y +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_LDM_PARTITION=y +# CONFIG_LDM_DEBUG is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_CMDLINE_PARTITION is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_CFQ_GROUP_IOSCHED=y +CONFIG_IOSCHED_BFQ=y +CONFIG_CGROUP_BFQIO=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_BFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="bfq" +CONFIG_PADATA=y +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +CONFIG_INLINE_READ_UNLOCK=y +CONFIG_INLINE_READ_UNLOCK_IRQ=y +CONFIG_INLINE_WRITE_UNLOCK=y +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +CONFIG_ARCH_MULTIPLATFORM=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM_NODT is not set +# CONFIG_ARCH_SHMOBILE_LEGACY is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C24XX is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP1 is not set + +# +# Multiple platform selection +# + +# +# CPU Core family selection +# +# CONFIG_ARCH_MULTI_V6 is not set +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_MULTI_V6_V7=y +# CONFIG_ARCH_MULTI_CPU_AUTO is not set +# CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_BCM is not set +# CONFIG_ARCH_BERLIN is not set +CONFIG_GPIO_PCA953X=y +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_HI3xxx is not set +# CONFIG_ARCH_KEYSTONE is not set +# CONFIG_ARCH_MSM_DT is not set +CONFIG_ARCH_MXC=y + +# +# Freescale i.MX support +# +CONFIG_MXC_DEBUG_BOARD=y +CONFIG_HAVE_IMX_ANATOP=y +CONFIG_HAVE_IMX_GPC=y +CONFIG_HAVE_IMX_MMDC=y +CONFIG_HAVE_IMX_SRC=y + +# +# i.MX51 machines: +# +# CONFIG_MACH_IMX51_DT is not set +# CONFIG_MACH_MX51_BABBAGE is not set +# CONFIG_MACH_EUKREA_CPUIMX51SD is not set + +# +# Device tree only +# +# CONFIG_SOC_IMX50 is not set +# CONFIG_SOC_IMX53 is not set +CONFIG_SOC_IMX6Q=y +CONFIG_SOC_IMX6SL=y +# CONFIG_SOC_VF610 is not set +# CONFIG_ARCH_OMAP3 is not set +# CONFIG_ARCH_OMAP4 is not set +# CONFIG_SOC_OMAP5 is not set +# CONFIG_SOC_AM33XX is not set +# CONFIG_SOC_AM43XX is not set +# CONFIG_SOC_DRA7XX is not set +# CONFIG_ARCH_ROCKCHIP is not set +# CONFIG_ARCH_SOCFPGA is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_STI is not set +# CONFIG_ARCH_SHMOBILE_MULTI is not set +# CONFIG_ARCH_SUNXI is not set +# CONFIG_ARCH_SIRF is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_VIRT is not set +# CONFIG_ARCH_WM8850 is not set +# CONFIG_ARCH_ZYNQ is not set + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_LPAE is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_ARM_VIRT_EXT=y +# CONFIG_SWP_EMULATE is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_KUSER_HELPERS=y +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y +CONFIG_PL310_ERRATA_588369=y +CONFIG_PL310_ERRATA_727915=y +# CONFIG_PL310_ERRATA_753970 is not set +CONFIG_PL310_ERRATA_769419=y +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_ARM_NR_BANKS=8 +CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_643719 is not set +# CONFIG_ARM_ERRATA_720789 is not set +CONFIG_ARM_ERRATA_754322=y +# CONFIG_ARM_ERRATA_754327 is not set +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_ERRATA_775420=y +# CONFIG_ARM_ERRATA_798181 is not set +# CONFIG_ARM_ERRATA_773022 is not set +CONFIG_ARM_ERRATA_794072=y +CONFIG_ARM_ERRATA_761320=y + +# +# Bus support +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_SYSCALL=y +# CONFIG_PCI_MSI is not set +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set +CONFIG_PCI_STUB=y +CONFIG_PCI_ATS=y +CONFIG_PCI_IOV=y +CONFIG_PCI_PRI=y +CONFIG_PCI_PASID=y + +# +# PCI host controller drivers +# +CONFIG_PCIE_DW=y +CONFIG_PCI_IMX6=y +# CONFIG_EP_MODE_IN_EP_RC_SYS is not set +# CONFIG_RC_MODE_IN_EP_RC_SYS is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIEAER=y +CONFIG_PCIE_ECRC=y +CONFIG_PCIEAER_INJECT=m +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEBUG is not set +CONFIG_PCIEASPM_DEFAULT=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_PERFORMANCE is not set +CONFIG_PCIE_PME=y +CONFIG_PCCARD=y +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=m +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_PCCARD_NONSTATIC=y + +# +# Kernel Features +# +CONFIG_HAVE_SMP=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_ARM_CPU_TOPOLOGY=y +# CONFIG_SCHED_MC is not set +# CONFIG_SCHED_SMT is not set +CONFIG_HAVE_ARM_SCU=y +# CONFIG_HAVE_ARM_ARCH_TIMER is not set +CONFIG_HAVE_ARM_TWD=y +# CONFIG_MCPM is not set +# CONFIG_BIG_LITTLE is not set +# CONFIG_VMSPLIT_3G is not set +CONFIG_VMSPLIT_2G=y +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0x80000000 +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +# CONFIG_ARM_PSCI is not set +CONFIG_ARCH_NR_GPIO=0 +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_HZ_FIXED=0 +# CONFIG_HZ_100 is not set +# CONFIG_HZ_200 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +# CONFIG_HZ_500 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 +CONFIG_SCHED_HRTICK=y +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HW_PERF_EVENTS=y +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +CONFIG_MEMORY_ISOLATION=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_BALLOON_COMPACTION=y +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_KSM=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_CLEANCACHE=y +CONFIG_FRONTSWAP=y +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set +CONFIG_CMA_AREAS=7 +CONFIG_ZBUD=y +CONFIG_ZSWAP=y +CONFIG_ZSMALLOC=y +# CONFIG_PGTABLE_MAPPING is not set +CONFIG_FORCE_MAX_ZONEORDER=14 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +CONFIG_SECCOMP=y +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +# CONFIG_XEN is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ATAGS=y +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +# CONFIG_ARM_APPENDED_DTB is not set +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_EXTEND is not set +# CONFIG_CMDLINE_FORCE is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y +# CONFIG_CRASH_DUMP is not set +CONFIG_AUTO_ZRELADDR=y + +# +# CPU Power Management +# + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y + +# +# ARM CPU frequency scaling drivers +# +CONFIG_ARM_IMX6_CPUFREQ=y +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y + +# +# ARM CPU Idle Drivers +# +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y +CONFIG_KERNEL_MODE_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=m +CONFIG_COREDUMP=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM=y +CONFIG_PM_DEBUG=y +# CONFIG_PM_ADVANCED_DEBUG is not set +CONFIG_PM_TEST_SUSPEND=y +CONFIG_PM_SLEEP_DEBUG=y +# CONFIG_DPM_WATCHDOG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_HAS_OPP=y +CONFIG_PM_OPP=y +CONFIG_PM_CLK=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_CPU_PM=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_DIAG=m +CONFIG_UNIX=y +CONFIG_UNIX_DIAG=m +CONFIG_XFRM=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_XFRM_STATISTICS=y +CONFIG_XFRM_IPCOMP=m +CONFIG_NET_KEY=m +CONFIG_NET_KEY_MIGRATE=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_FIB_TRIE_STATS=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_ROUTE_CLASSID=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IP_TUNNEL=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +CONFIG_INET_LRO=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_INET_UDP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_IPV6_VTI=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +# CONFIG_IPV6_GRE is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETLABEL=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NETWORK_PHY_TIMESTAMPING=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_ACCT=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_LABELS=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_BROADCAST=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +# CONFIG_NF_CT_NETLINK_TIMEOUT is not set +CONFIG_NF_CT_NETLINK_HELPER=m +CONFIG_NETFILTER_NETLINK_QUEUE_CT=y +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PROTO_DCCP=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_SIP=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NETFILTER_SYNPROXY=m +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=m +CONFIG_NFT_EXTHDR=m +CONFIG_NFT_META=m +CONFIG_NFT_CT=m +CONFIG_NFT_RBTREE=m +CONFIG_NFT_HASH=m +CONFIG_NFT_COUNTER=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +CONFIG_NFT_NAT=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_REJECT_INET=m +CONFIG_NFT_COMPAT=m +CONFIG_NETFILTER_XTABLES=y + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_CONNMARK=m +CONFIG_NETFILTER_XT_SET=m + +# +# Xtables targets +# +CONFIG_NETFILTER_XT_TARGET_AUDIT=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ECN=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_L2TP=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_MAX=256 +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_NETPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETNET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS SH scheduler +# +CONFIG_IP_VS_SH_TAB_BITS=8 + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_NFCT=y +CONFIG_IP_VS_PE_SIP=m + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_CONNTRACK_IPV4=m +# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set +CONFIG_NF_TABLES_IPV4=m +CONFIG_NFT_CHAIN_ROUTE_IPV4=m +CONFIG_NFT_CHAIN_NAT_IPV4=m +CONFIG_NFT_REJECT_IPV4=m +CONFIG_NF_TABLES_ARP=m +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_TARGET_SYNPROXY=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_NF_NAT_IPV4=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_SECURITY=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_NF_TABLES_IPV6=m +CONFIG_NFT_CHAIN_ROUTE_IPV6=m +CONFIG_NFT_CHAIN_NAT_IPV6=m +CONFIG_NFT_REJECT_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_SYNPROXY=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_SECURITY=m +CONFIG_NF_NAT_IPV6=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +# CONFIG_IP6_NF_TARGET_NPT is not set +CONFIG_NF_TABLES_BRIDGE=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m + +# +# DCCP CCIDs Configuration +# +# CONFIG_IP_DCCP_CCID2_DEBUG is not set +CONFIG_IP_DCCP_CCID3=y +# CONFIG_IP_DCCP_CCID3_DEBUG is not set +CONFIG_IP_DCCP_TFRC_LIB=y + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set +# CONFIG_NET_DCCPPROBE is not set +CONFIG_IP_SCTP=m +CONFIG_NET_SCTPPROBE=m +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5 is not set +CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1=y +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set +CONFIG_SCTP_COOKIE_HMAC_MD5=y +CONFIG_SCTP_COOKIE_HMAC_SHA1=y +CONFIG_RDS=m +CONFIG_RDS_RDMA=m +CONFIG_RDS_TCP=m +# CONFIG_RDS_DEBUG is not set +CONFIG_TIPC=m +CONFIG_TIPC_PORTS=8192 +# CONFIG_TIPC_MEDIA_IB is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_L2TP=m +# CONFIG_L2TP_DEBUGFS is not set +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_STP=y +CONFIG_GARP=y +CONFIG_MRP=y +CONFIG_BRIDGE=y +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_HAVE_NET_DSA=y +CONFIG_NET_DSA=m +CONFIG_NET_DSA_TAG_DSA=y +CONFIG_NET_DSA_TAG_EDSA=y +CONFIG_NET_DSA_TAG_TRAILER=y +CONFIG_VLAN_8021Q=y +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLAN_8021Q_MVRP=y +# CONFIG_DECNET is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +CONFIG_IEEE802154=m +CONFIG_IEEE802154_6LOWPAN=m +CONFIG_6LOWPAN_IPHC=m +CONFIG_MAC802154=m +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_CHOKE=m +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=m +CONFIG_NET_SCH_FQ=m +CONFIG_NET_SCH_HHF=m +CONFIG_NET_SCH_PIE=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_SCH_PLUG=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_CGROUP=y +CONFIG_NET_CLS_BPF=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_IPSET=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_ACT_CSUM=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_SCH_FIFO=y +CONFIG_DCB=y +CONFIG_DNS_RESOLVER=y +CONFIG_BATMAN_ADV=m +CONFIG_BATMAN_ADV_BLA=y +CONFIG_BATMAN_ADV_DAT=y +CONFIG_BATMAN_ADV_NC=y +# CONFIG_BATMAN_ADV_DEBUG is not set +CONFIG_OPENVSWITCH=m +CONFIG_OPENVSWITCH_GRE=y +CONFIG_OPENVSWITCH_VXLAN=y +CONFIG_VSOCKETS=m +CONFIG_NETLINK_MMAP=y +CONFIG_NETLINK_DIAG=m +CONFIG_NET_MPLS_GSO=m +# CONFIG_HSR is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +CONFIG_CGROUP_NET_PRIO=m +CONFIG_CGROUP_NET_CLASSID=y +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_JIT is not set +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +CONFIG_HAMRADIO=y + +# +# Packet Radio protocols +# +CONFIG_AX25=m +CONFIG_AX25_DAMA_SLAVE=y +CONFIG_NETROM=m +CONFIG_ROSE=m + +# +# AX.25 network device drivers +# +CONFIG_MKISS=m +CONFIG_6PACK=m +CONFIG_BPQETHER=m +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +CONFIG_BAYCOM_PAR=m +CONFIG_BAYCOM_EPP=m +CONFIG_YAM=m +# CONFIG_CAN is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m +CONFIG_KINGSUN_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +CONFIG_KS959_DONGLE=m + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTSDIO=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIUART_3WIRE=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +# CONFIG_BT_HCIVHCI is not set +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_BT_ATH3K=m +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=m +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_WEXT=y +CONFIG_LIB80211=m +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_HAS_RC=y +# CONFIG_MAC80211_RC_PID is not set +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_MESSAGE_TRACING is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set +CONFIG_RFKILL=m +CONFIG_RFKILL_LEDS=y +CONFIG_RFKILL_INPUT=y +# CONFIG_RFKILL_REGULATOR is not set +CONFIG_RFKILL_GPIO=m +CONFIG_NET_9P=m +CONFIG_NET_9P_VIRTIO=m +CONFIG_NET_9P_RDMA=m +# CONFIG_NET_9P_DEBUG is not set +# CONFIG_CAIF is not set +CONFIG_CEPH_LIB=m +# CONFIG_CEPH_LIB_PRETTYDEBUG is not set +# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set +CONFIG_NFC=m +CONFIG_NFC_DIGITAL=m +CONFIG_NFC_NCI=m +# CONFIG_NFC_NCI_SPI is not set +CONFIG_NFC_HCI=m +CONFIG_NFC_SHDLC=y + +# +# Near Field Communication (NFC) devices +# +CONFIG_NFC_PN533=m +CONFIG_NFC_SIM=m +CONFIG_NFC_PORT100=m +CONFIG_NFC_PN544=m +CONFIG_NFC_PN544_I2C=m +CONFIG_NFC_MICROREAD=m +CONFIG_NFC_MICROREAD_I2C=m +CONFIG_NFC_MRVL=m +CONFIG_NFC_MRVL_USB=m +CONFIG_HAVE_BPF_JIT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="imx/sdma/sdma-imx6q.bin" +CONFIG_EXTRA_FIRMWARE_DIR="firmware" +# CONFIG_FW_LOADER_USER_HELPER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +# CONFIG_HAVE_CPU_AUTOPROBE is not set +CONFIG_SOC_BUS=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_IRQ=y +CONFIG_DMA_SHARED_BUFFER=y +CONFIG_DMA_CMA=y + +# +# Default contiguous memory area size: +# +CONFIG_CMA_SIZE_MBYTES=256 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 + +# +# Bus devices +# +# CONFIG_IMX_WEIM is not set +# CONFIG_ARM_CCI is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +# CONFIG_MTD is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y +CONFIG_PARPORT_NOT_PC=y +CONFIG_BLK_DEV=y +CONFIG_BLK_DEV_NULL_BLK=m +# CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +CONFIG_ZRAM=m +# CONFIG_ZRAM_DEBUG is not set +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=0 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_DRBD=m +# CONFIG_DRBD_FAULT_INJECTION is not set +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_NVME=m +CONFIG_BLK_DEV_OSD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +# CONFIG_BLK_DEV_XIP is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m +# CONFIG_MG_DISK is not set +CONFIG_VIRTIO_BLK=m +CONFIG_BLK_DEV_RBD=m +# CONFIG_BLK_DEV_RSXX is not set + +# +# Misc devices +# +CONFIG_SENSORS_LIS3LV02D=m +# CONFIG_AD525X_DPOT is not set +# CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +CONFIG_TIFM_CORE=m +CONFIG_TIFM_7XX1=m +# CONFIG_ICS932S401 is not set +# CONFIG_ATMEL_SSC is not set +CONFIG_ENCLOSURE_SERVICES=m +# CONFIG_HP_ILO is not set +CONFIG_APDS9802ALS=m +CONFIG_ISL29003=m +CONFIG_ISL29020=m +CONFIG_SENSORS_TSL2550=m +# CONFIG_SENSORS_BH1780 is not set +CONFIG_SENSORS_BH1770=m +CONFIG_SENSORS_APDS990X=m +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_PCH_PHUB is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +CONFIG_SRAM=y +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=m +# CONFIG_EEPROM_AT25 is not set +CONFIG_EEPROM_LEGACY=m +CONFIG_EEPROM_MAX6875=m +CONFIG_EEPROM_93CX6=m +# CONFIG_EEPROM_93XX46 is not set +CONFIG_CB710_CORE=m +# CONFIG_CB710_DEBUG is not set +CONFIG_CB710_DEBUG_ASSUMPTIONS=y + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +CONFIG_SENSORS_LIS3_SPI=m +CONFIG_SENSORS_LIS3_I2C=m + +# +# Altera FPGA firmware download module +# +CONFIG_ALTERA_STAPL=m + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +CONFIG_SCSI_TGT=m +CONFIG_SCSI_NETLINK=y +# CONFIG_SCSI_PROC_FS is not set + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=m +CONFIG_SCSI_ENCLOSURE=m +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y + +# +# SCSI Transports +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_FC_TGT_ATTRS=y +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m +CONFIG_SCSI_SAS_LIBSAS=m +CONFIG_SCSI_SAS_ATA=y +CONFIG_SCSI_SAS_HOST_SMP=y +CONFIG_SCSI_SRP_ATTRS=m +CONFIG_SCSI_SRP_TGT_ATTRS=y +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +CONFIG_SCSI_DH=y +CONFIG_SCSI_DH_RDAC=m +CONFIG_SCSI_DH_HP_SW=m +CONFIG_SCSI_DH_EMC=m +CONFIG_SCSI_DH_ALUA=m +CONFIG_SCSI_OSD_INITIATOR=m +CONFIG_SCSI_OSD_ULD=m +CONFIG_SCSI_OSD_DPRINT_SENSE=1 +# CONFIG_SCSI_OSD_DEBUG is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +CONFIG_SATA_AHCI=y +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_AHCI_IMX=y +CONFIG_SATA_INIC162X=m +CONFIG_SATA_ACARD_AHCI=m +CONFIG_SATA_SIL24=m +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +CONFIG_PDC_ADMA=m +CONFIG_SATA_QSTOR=m +CONFIG_SATA_SX4=m +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# +CONFIG_ATA_PIIX=y +# CONFIG_SATA_HIGHBANK is not set +CONFIG_SATA_MV=m +CONFIG_SATA_NV=m +CONFIG_SATA_PROMISE=m +CONFIG_SATA_RCAR=m +CONFIG_SATA_SIL=m +CONFIG_SATA_SIS=m +CONFIG_SATA_SVW=m +CONFIG_SATA_ULI=m +CONFIG_SATA_VIA=m +CONFIG_SATA_VITESSE=m + +# +# PATA SFF controllers with BMDMA +# +CONFIG_PATA_ALI=m +CONFIG_PATA_AMD=m +CONFIG_PATA_ARASAN_CF=m +CONFIG_PATA_ARTOP=m +CONFIG_PATA_ATIIXP=m +CONFIG_PATA_ATP867X=m +CONFIG_PATA_CMD64X=m +CONFIG_PATA_CS5520=m +CONFIG_PATA_CS5530=m +CONFIG_PATA_CS5536=m +CONFIG_PATA_CYPRESS=m +CONFIG_PATA_EFAR=m +CONFIG_PATA_HPT366=m +CONFIG_PATA_HPT37X=m +CONFIG_PATA_HPT3X2N=m +CONFIG_PATA_HPT3X3=m +# CONFIG_PATA_HPT3X3_DMA is not set +# CONFIG_PATA_IMX is not set +CONFIG_PATA_IT8213=m +CONFIG_PATA_IT821X=m +CONFIG_PATA_JMICRON=m +CONFIG_PATA_MARVELL=m +CONFIG_PATA_NETCELL=m +CONFIG_PATA_NINJA32=m +CONFIG_PATA_NS87415=m +CONFIG_PATA_OLDPIIX=m +CONFIG_PATA_OPTIDMA=m +CONFIG_PATA_PDC2027X=m +CONFIG_PATA_PDC_OLD=m +# CONFIG_PATA_RADISYS is not set +CONFIG_PATA_RDC=m +# CONFIG_PATA_SC1200 is not set +CONFIG_PATA_SCH=m +CONFIG_PATA_SERVERWORKS=m +CONFIG_PATA_SIL680=m +CONFIG_PATA_SIS=m +CONFIG_PATA_TOSHIBA=m +CONFIG_PATA_TRIFLEX=m +CONFIG_PATA_VIA=m +CONFIG_PATA_WINBOND=m + +# +# PIO-only SFF controllers +# +CONFIG_PATA_CMD640_PCI=m +CONFIG_PATA_MPIIX=m +CONFIG_PATA_NS87410=m +CONFIG_PATA_OPTI=m +CONFIG_PATA_PCMCIA=m +# CONFIG_PATA_PLATFORM is not set +# CONFIG_PATA_RZ1000 is not set + +# +# Generic fallback / legacy drivers +# +CONFIG_ATA_GENERIC=m +# CONFIG_PATA_LEGACY is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_AUTODETECT=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BCACHE=m +# CONFIG_BCACHE_DEBUG is not set +# CONFIG_BCACHE_CLOSURES_DEBUG is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_DEBUG=y +CONFIG_DM_BUFIO=y +CONFIG_DM_BIO_PRISON=m +CONFIG_DM_PERSISTENT_DATA=m +# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=y +CONFIG_DM_THIN_PROVISIONING=m +CONFIG_DM_CACHE=m +CONFIG_DM_CACHE_MQ=m +CONFIG_DM_CACHE_CLEANER=m +CONFIG_DM_MIRROR=y +CONFIG_DM_LOG_USERSPACE=m +CONFIG_DM_RAID=m +CONFIG_DM_ZERO=y +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_QL=m +CONFIG_DM_MULTIPATH_ST=m +CONFIG_DM_DELAY=m +CONFIG_DM_UEVENT=y +CONFIG_DM_FLAKEY=m +CONFIG_DM_VERITY=m +CONFIG_DM_SWITCH=m +CONFIG_TARGET_CORE=m +CONFIG_TCM_IBLOCK=m +CONFIG_TCM_FILEIO=m +CONFIG_TCM_PSCSI=m +CONFIG_LOOPBACK_TARGET=m +CONFIG_ISCSI_TARGET=m +CONFIG_SBP_TARGET=m +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m +CONFIG_FUSION_LOGGING=y + +# +# IEEE 1394 (FireWire) support +# +CONFIG_FIREWIRE=m +CONFIG_FIREWIRE_OHCI=m +CONFIG_FIREWIRE_SBP2=m +CONFIG_FIREWIRE_NET=m +CONFIG_FIREWIRE_NOSY=m +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +CONFIG_MII=m +CONFIG_NET_CORE=y +CONFIG_BONDING=m +CONFIG_DUMMY=m +CONFIG_EQUALIZER=m +CONFIG_NET_FC=y +CONFIG_IFB=m +CONFIG_NET_TEAM=m +CONFIG_NET_TEAM_MODE_BROADCAST=m +CONFIG_NET_TEAM_MODE_ROUNDROBIN=m +CONFIG_NET_TEAM_MODE_RANDOM=m +CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m +CONFIG_NET_TEAM_MODE_LOADBALANCE=m +CONFIG_MACVLAN=m +CONFIG_MACVTAP=m +CONFIG_VXLAN=m +CONFIG_NETCONSOLE=m +CONFIG_NETCONSOLE_DYNAMIC=y +CONFIG_NETPOLL=y +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y +CONFIG_TUN=m +CONFIG_VETH=m +CONFIG_VIRTIO_NET=m +CONFIG_NLMON=m +CONFIG_SUNGEM_PHY=m +# CONFIG_ARCNET is not set +CONFIG_ATM_DRIVERS=y +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +# CONFIG_ATM_LANAI is not set +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +# CONFIG_ATM_IDT77252 is not set +# CONFIG_ATM_IA is not set +# CONFIG_ATM_FORE200E is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_ATM_SOLOS=m + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +CONFIG_NET_DSA_MV88E6XXX=m +CONFIG_NET_DSA_MV88E6060=m +CONFIG_NET_DSA_MV88E6XXX_NEED_PPU=y +CONFIG_NET_DSA_MV88E6131=m +CONFIG_NET_DSA_MV88E6123_61_65=m +CONFIG_ETHERNET=y +CONFIG_MDIO=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_3C589=m +CONFIG_VORTEX=m +CONFIG_TYPHOON=m +CONFIG_NET_VENDOR_ADAPTEC=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_NET_VENDOR_ALTEON=y +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_NET_VENDOR_AMD=y +CONFIG_AMD8111_ETH=m +CONFIG_PCNET32=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_NET_VENDOR_ARC=y +CONFIG_ARC_EMAC=m +CONFIG_NET_VENDOR_ATHEROS=y +CONFIG_ATL2=m +CONFIG_ATL1=m +CONFIG_ATL1E=m +CONFIG_ATL1C=m +CONFIG_ALX=m +CONFIG_NET_CADENCE=y +CONFIG_ARM_AT91_ETHER=m +CONFIG_MACB=m +# CONFIG_NET_VENDOR_BROADCOM is not set +CONFIG_NET_VENDOR_BROCADE=y +CONFIG_BNA=m +CONFIG_NET_CALXEDA_XGMAC=m +CONFIG_NET_VENDOR_CHELSIO=y +CONFIG_CHELSIO_T1=m +CONFIG_CHELSIO_T1_1G=y +CONFIG_CHELSIO_T3=m +CONFIG_CHELSIO_T4=m +CONFIG_CHELSIO_T4VF=m +# CONFIG_NET_VENDOR_CIRRUS is not set +CONFIG_NET_VENDOR_CISCO=y +CONFIG_ENIC=m +# CONFIG_DM9000 is not set +CONFIG_DNET=m +CONFIG_NET_VENDOR_DEC=y +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_DE2104X_DSL=0 +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +CONFIG_NET_VENDOR_DLINK=y +CONFIG_DL2K=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_NET_VENDOR_EMULEX=y +CONFIG_BE2NET=m +CONFIG_NET_VENDOR_EXAR=y +CONFIG_S2IO=m +CONFIG_VXGE=m +# CONFIG_VXGE_DEBUG_TRACE_ALL is not set +# CONFIG_NET_VENDOR_FARADAY is not set +CONFIG_NET_VENDOR_FREESCALE=y +CONFIG_FEC=y +# CONFIG_NET_VENDOR_FUJITSU is not set +# CONFIG_NET_VENDOR_HP is not set +CONFIG_NET_VENDOR_INTEL=y +CONFIG_E100=m +CONFIG_E1000=m +CONFIG_E1000E=m +CONFIG_IGB=m +CONFIG_IGB_HWMON=y +CONFIG_IGBVF=m +CONFIG_IXGB=m +CONFIG_IXGBE=m +CONFIG_IXGBE_HWMON=y +CONFIG_IXGBE_DCB=y +CONFIG_I40E=m +# CONFIG_I40E_VXLAN is not set +# CONFIG_I40E_DCB is not set +# CONFIG_NET_VENDOR_I825XX is not set +# CONFIG_IP1000 is not set +CONFIG_JME=m +CONFIG_NET_VENDOR_MARVELL=y +CONFIG_MVMDIO=m +CONFIG_SKGE=m +# CONFIG_SKGE_DEBUG is not set +CONFIG_SKGE_GENESIS=y +CONFIG_SKY2=m +# CONFIG_SKY2_DEBUG is not set +CONFIG_NET_VENDOR_MELLANOX=y +# CONFIG_MLX4_EN is not set +CONFIG_MLX4_CORE=m +CONFIG_MLX4_DEBUG=y +CONFIG_MLX5_CORE=m +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +CONFIG_KSZ884X_PCI=m +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +CONFIG_NET_VENDOR_MYRI=y +CONFIG_MYRI10GE=m +CONFIG_FEALNX=m +CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NATSEMI=m +CONFIG_NS83820=m +CONFIG_NET_VENDOR_8390=y +CONFIG_PCMCIA_AXNET=m +# CONFIG_AX88796 is not set +CONFIG_NE2K_PCI=m +CONFIG_PCMCIA_PCNET=m +CONFIG_NET_VENDOR_NVIDIA=y +CONFIG_FORCEDETH=m +CONFIG_NET_VENDOR_OKI=y +# CONFIG_ETHOC is not set +CONFIG_NET_PACKET_ENGINE=y +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_NET_VENDOR_QLOGIC=y +CONFIG_QLA3XXX=m +CONFIG_QLCNIC=m +CONFIG_QLCNIC_SRIOV=y +CONFIG_QLCNIC_DCB=y +CONFIG_QLGE=m +CONFIG_NETXEN_NIC=m +CONFIG_NET_VENDOR_REALTEK=y +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_R8169=m +# CONFIG_SH_ETH is not set +CONFIG_NET_VENDOR_RDC=y +CONFIG_R6040=m +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SILAN=y +CONFIG_SC92031=m +CONFIG_NET_VENDOR_SIS=y +CONFIG_SIS900=m +CONFIG_SIS190=m +# CONFIG_SFC is not set +CONFIG_NET_VENDOR_SMSC=y +# CONFIG_SMC91X is not set +CONFIG_PCMCIA_SMC91C92=m +CONFIG_EPIC100=m +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +CONFIG_SMSC9420=m +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_SUN=y +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NIU=m +CONFIG_NET_VENDOR_TEHUTI=y +CONFIG_TEHUTI=m +CONFIG_NET_VENDOR_TI=y +CONFIG_TLAN=m +CONFIG_NET_VENDOR_VIA=y +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +# CONFIG_VIA_VELOCITY is not set +CONFIG_NET_VENDOR_WIZNET=y +CONFIG_WIZNET_W5100=m +CONFIG_WIZNET_W5300=m +# CONFIG_WIZNET_BUS_DIRECT is not set +# CONFIG_WIZNET_BUS_INDIRECT is not set +CONFIG_WIZNET_BUS_ANY=y +CONFIG_NET_VENDOR_XIRCOM=y +CONFIG_PCMCIA_XIRC2PS=m +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_AT803X_PHY=y +CONFIG_AMD_PHY=m +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_BROADCOM_PHY=m +CONFIG_BCM87XX_PHY=m +CONFIG_ICPLUS_PHY=m +CONFIG_REALTEK_PHY=m +CONFIG_NATIONAL_PHY=m +CONFIG_STE10XP=m +CONFIG_LSI_ET1011C_PHY=m +CONFIG_MICREL_PHY=m +CONFIG_FIXED_PHY=y +CONFIG_MDIO_BITBANG=m +# CONFIG_MDIO_GPIO is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PLIP is not set +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOATM=m +CONFIG_PPPOE=m +CONFIG_PPTP=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_SLIP=m +CONFIG_SLHC=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_AX88179_178A=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_CDC_NCM=m +CONFIG_USB_NET_HUAWEI_CDC_NCM=m +CONFIG_USB_NET_CDC_MBIM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SR9700=m +# CONFIG_USB_NET_SR9800 is not set +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_HSO=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_WLAN=y +# CONFIG_PCMCIA_RAYCS is not set +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_ATMEL is not set +CONFIG_AT76C50X_USB=m +# CONFIG_AIRO_CS is not set +# CONFIG_PCMCIA_WL3501 is not set +# CONFIG_PRISM54 is not set +# CONFIG_USB_ZD1201 is not set +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8180=m +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y +# CONFIG_ADM8211 is not set +CONFIG_MAC80211_HWSIM=m +CONFIG_MWL8K=m +CONFIG_ATH_COMMON=m +CONFIG_ATH_CARDS=m +# CONFIG_ATH_DEBUG is not set +CONFIG_ATH5K=m +CONFIG_ATH5K_DEBUG=y +CONFIG_ATH5K_PCI=y +CONFIG_ATH9K_HW=m +CONFIG_ATH9K_COMMON=m +CONFIG_ATH9K_BTCOEX_SUPPORT=y +CONFIG_ATH9K=m +CONFIG_ATH9K_PCI=y +CONFIG_ATH9K_AHB=y +# CONFIG_ATH9K_DEBUGFS is not set +# CONFIG_ATH9K_WOW is not set +# CONFIG_ATH9K_LEGACY_RATE_CONTROL is not set +CONFIG_ATH9K_RFKILL=y +CONFIG_ATH9K_HTC=m +# CONFIG_ATH9K_HTC_DEBUGFS is not set +CONFIG_CARL9170=m +CONFIG_CARL9170_LEDS=y +CONFIG_CARL9170_WPC=y +# CONFIG_CARL9170_HWRNG is not set +CONFIG_ATH6KL=m +CONFIG_ATH6KL_SDIO=m +CONFIG_ATH6KL_USB=m +CONFIG_ATH6KL_DEBUG=y +CONFIG_AR5523=m +CONFIG_WIL6210=m +CONFIG_WIL6210_ISR_COR=y +CONFIG_ATH10K=m +CONFIG_ATH10K_PCI=m +# CONFIG_ATH10K_DEBUG is not set +CONFIG_ATH10K_DEBUGFS=y +CONFIG_WCN36XX=m +# CONFIG_WCN36XX_DEBUGFS is not set +CONFIG_B43=m +CONFIG_B43_BCMA=y +CONFIG_B43_SSB=y +CONFIG_B43_PCI_AUTOSELECT=y +CONFIG_B43_PCICORE_AUTOSELECT=y +CONFIG_B43_PCMCIA=y +CONFIG_B43_SDIO=y +CONFIG_B43_BCMA_PIO=y +CONFIG_B43_PIO=y +CONFIG_B43_PHY_N=y +CONFIG_B43_PHY_LP=y +CONFIG_B43_PHY_HT=y +CONFIG_B43_LEDS=y +CONFIG_B43_HWRNG=y +# CONFIG_B43_DEBUG is not set +CONFIG_B43LEGACY=m +CONFIG_B43LEGACY_PCI_AUTOSELECT=y +CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y +CONFIG_B43LEGACY_LEDS=y +CONFIG_B43LEGACY_HWRNG=y +# CONFIG_B43LEGACY_DEBUG is not set +CONFIG_B43LEGACY_DMA=y +CONFIG_B43LEGACY_PIO=y +CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y +# CONFIG_B43LEGACY_DMA_MODE is not set +# CONFIG_B43LEGACY_PIO_MODE is not set +CONFIG_BRCMUTIL=m +# CONFIG_BRCMSMAC is not set +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_SDIO=y +# CONFIG_BRCMFMAC_USB is not set +# CONFIG_BRCM_TRACING is not set +# CONFIG_BRCMDBG is not set +# CONFIG_HOSTAP is not set +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +CONFIG_IWLWIFI=m +CONFIG_IWLDVM=m +CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y + +# +# Debugging Options +# +CONFIG_IWLWIFI_DEBUG=y +# CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE is not set +CONFIG_IWLEGACY=m +CONFIG_IWL4965=m +CONFIG_IWL3945=m + +# +# iwl3945 / iwl4965 Debugging Options +# +CONFIG_IWLEGACY_DEBUG=y +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_CS=m +CONFIG_LIBERTAS_SDIO=m +# CONFIG_LIBERTAS_SPI is not set +# CONFIG_LIBERTAS_DEBUG is not set +CONFIG_LIBERTAS_MESH=y +CONFIG_HERMES=m +# CONFIG_HERMES_PRISM is not set +CONFIG_HERMES_CACHE_FW_ON_INIT=y +CONFIG_PLX_HERMES=m +# CONFIG_TMD_HERMES is not set +CONFIG_NORTEL_HERMES=m +CONFIG_PCMCIA_HERMES=m +# CONFIG_PCMCIA_SPECTRUM is not set +CONFIG_ORINOCO_USB=m +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +CONFIG_P54_PCI=m +# CONFIG_P54_SPI is not set +CONFIG_P54_LEDS=y +CONFIG_RT2X00=m +CONFIG_RT2400PCI=m +CONFIG_RT2500PCI=m +CONFIG_RT61PCI=m +CONFIG_RT2800PCI=m +CONFIG_RT2800PCI_RT33XX=y +CONFIG_RT2800PCI_RT35XX=y +CONFIG_RT2800PCI_RT53XX=y +CONFIG_RT2800PCI_RT3290=y +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT33XX=y +CONFIG_RT2800USB_RT35XX=y +CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RT2800_LIB=m +CONFIG_RT2800_LIB_MMIO=m +CONFIG_RT2X00_LIB_MMIO=m +CONFIG_RT2X00_LIB_PCI=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_DEBUG is not set +CONFIG_RTL_CARDS=m +CONFIG_RTL8192CE=m +CONFIG_RTL8192SE=m +CONFIG_RTL8192DE=m +CONFIG_RTL8723AE=m +CONFIG_RTL8188EE=m +CONFIG_RTL8192CU=m +CONFIG_RTLWIFI=m +CONFIG_RTLWIFI_PCI=m +CONFIG_RTLWIFI_USB=m +CONFIG_RTLWIFI_DEBUG=y +CONFIG_RTL8192C_COMMON=m +# CONFIG_WL_TI is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_MWIFIEX_PCIE=m +CONFIG_MWIFIEX_USB=m +CONFIG_CW1200=m +CONFIG_CW1200_WLAN_SDIO=m +CONFIG_CW1200_WLAN_SPI=m + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +CONFIG_IEEE802154_DRIVERS=m +CONFIG_IEEE802154_FAKEHARD=m +CONFIG_IEEE802154_FAKELB=m +# CONFIG_IEEE802154_AT86RF230 is not set +# CONFIG_IEEE802154_MRF24J40 is not set +# CONFIG_VMXNET3 is not set +CONFIG_ISDN=y +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m + +# +# Active cards +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +# CONFIG_CAPI_TRACE is not set +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# +CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m +# CONFIG_CAPI_EICON is not set +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_CAPI=y +# CONFIG_GIGASET_I4L is not set +# CONFIG_GIGASET_DUMMYLL is not set +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +CONFIG_GIGASET_M101=m +# CONFIG_GIGASET_DEBUG is not set +CONFIG_HYSDN=m +CONFIG_HYSDN_CAPI=y +CONFIG_MISDN=m +CONFIG_MISDN_DSP=m +CONFIG_MISDN_L1OIP=m + +# +# mISDN hardware drivers +# +CONFIG_MISDN_HFCPCI=m +CONFIG_MISDN_HFCMULTI=m +CONFIG_MISDN_HFCUSB=m +CONFIG_MISDN_AVMFRITZ=m +CONFIG_MISDN_SPEEDFAX=m +CONFIG_MISDN_INFINEON=m +CONFIG_MISDN_W6692=m +CONFIG_MISDN_NETJET=m +CONFIG_MISDN_IPAC=m +CONFIG_MISDN_ISAR=m +CONFIG_ISDN_HDLC=m + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_FF_MEMLESS=m +CONFIG_INPUT_POLLDEV=m +CONFIG_INPUT_SPARSEKMAP=m +CONFIG_INPUT_MATRIXKMAP=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +CONFIG_KEYBOARD_IMX=y +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_APPLETOUCH=m +CONFIG_MOUSE_BCM5974=m +CONFIG_MOUSE_CYAPA=m +CONFIG_MOUSE_VSXXXAA=m +# CONFIG_MOUSE_GPIO is not set +CONFIG_MOUSE_SYNAPTICS_I2C=m +CONFIG_MOUSE_SYNAPTICS_USB=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_ZHENHUA=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +# CONFIG_JOYSTICK_AS5011 is not set +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_WALKERA0701=m +CONFIG_INPUT_TABLET=y +CONFIG_TABLET_USB_ACECAD=m +CONFIG_TABLET_USB_AIPTEK=m +CONFIG_TABLET_USB_GTCO=m +CONFIG_TABLET_USB_HANWANG=m +CONFIG_TABLET_USB_KBTAB=m +CONFIG_TABLET_USB_WACOM=m +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +CONFIG_TOUCHSCREEN_ATMEL_MXT=m +CONFIG_TOUCHSCREEN_AUO_PIXCIR=m +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_DA9052 is not set +CONFIG_TOUCHSCREEN_DYNAPRO=m +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +CONFIG_TOUCHSCREEN_EETI=m +CONFIG_TOUCHSCREEN_EGALAX=m +CONFIG_TOUCHSCREEN_FUJITSU=m +CONFIG_TOUCHSCREEN_ILI210X=m +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_WACOM_W8001=m +CONFIG_TOUCHSCREEN_WACOM_I2C=m +# CONFIG_TOUCHSCREEN_MAX11801 is not set +CONFIG_TOUCHSCREEN_MCS5000=m +CONFIG_TOUCHSCREEN_MMS114=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_INEXIO=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_TOUCHSCREEN_PENMOUNT=m +CONFIG_TOUCHSCREEN_EDT_FT5X06=m +CONFIG_TOUCHSCREEN_TOUCHRIGHT=m +CONFIG_TOUCHSCREEN_TOUCHWIN=m +CONFIG_TOUCHSCREEN_PIXCIR=m +# CONFIG_TOUCHSCREEN_WM97XX is not set +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +# CONFIG_TOUCHSCREEN_MC13783 is not set +CONFIG_TOUCHSCREEN_USB_EGALAX=y +CONFIG_TOUCHSCREEN_USB_PANJIT=y +CONFIG_TOUCHSCREEN_USB_3M=y +CONFIG_TOUCHSCREEN_USB_ITM=y +CONFIG_TOUCHSCREEN_USB_ETURBO=y +CONFIG_TOUCHSCREEN_USB_GUNZE=y +CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y +CONFIG_TOUCHSCREEN_USB_IRTOUCH=y +CONFIG_TOUCHSCREEN_USB_IDEALTEK=y +CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y +CONFIG_TOUCHSCREEN_USB_GOTOP=y +CONFIG_TOUCHSCREEN_USB_JASTEC=y +CONFIG_TOUCHSCREEN_USB_ELO=y +CONFIG_TOUCHSCREEN_USB_E2I=y +CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y +CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y +CONFIG_TOUCHSCREEN_USB_NEXIO=y +CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y +CONFIG_TOUCHSCREEN_TOUCHIT213=m +CONFIG_TOUCHSCREEN_TSC_SERIO=m +# CONFIG_TOUCHSCREEN_TSC2005 is not set +CONFIG_TOUCHSCREEN_TSC2007=m +CONFIG_TOUCHSCREEN_W90X900=m +CONFIG_TOUCHSCREEN_ST1232=m +# CONFIG_TOUCHSCREEN_SUR40 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +CONFIG_TOUCHSCREEN_ZFORCE=m +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_MC13783_PWRBUTTON is not set +CONFIG_INPUT_MMA8450=m +CONFIG_INPUT_MPU3050=m +CONFIG_INPUT_GP2A=m +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_KXTJ9=m +# CONFIG_INPUT_KXTJ9_POLLED_MODE is not set +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_YEALINK=m +CONFIG_INPUT_CM109=m +CONFIG_INPUT_UINPUT=m +# CONFIG_INPUT_PCF8574 is not set +CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +# CONFIG_INPUT_DA9052_ONKEY is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set +CONFIG_INPUT_CMA3000=m +CONFIG_INPUT_CMA3000_I2C=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=m +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_LIBPS2 is not set +CONFIG_SERIO_RAW=m +CONFIG_SERIO_ALTERA_PS2=m +# CONFIG_SERIO_PS2MULT is not set +CONFIG_SERIO_ARC_PS2=m +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_SERIO_OLPC_APSP is not set +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_NONSTANDARD=y +CONFIG_ROCKETPORT=m +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_NOZOMI=m +# CONFIG_ISI is not set +CONFIG_N_HDLC=m +CONFIG_N_GSM=m +# CONFIG_TRACE_SINK is not set +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_DMA=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +CONFIG_SERIAL_8250_RSA=y +# CONFIG_SERIAL_8250_DW is not set +# CONFIG_SERIAL_8250_EM is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +# CONFIG_SERIAL_MFD_HSU is not set +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +# CONFIG_SERIAL_SH_SCI is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_JSM=m +# CONFIG_SERIAL_OF_PLATFORM is not set +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_PCH_UART is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +CONFIG_SERIAL_ARC=m +CONFIG_SERIAL_ARC_NR_PORTS=1 +# CONFIG_SERIAL_RP2 is not set +CONFIG_SERIAL_FSL_LPUART=y +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y +# CONFIG_SERIAL_ST_ASC is not set +# CONFIG_TTY_PRINTK is not set +CONFIG_FSL_OTP=y +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_HVC_DRIVER=y +# CONFIG_HVC_DCC is not set +CONFIG_VIRTIO_CONSOLE=m +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_TIMERIOMEM=m +# CONFIG_HW_RANDOM_ATMEL is not set +CONFIG_HW_RANDOM_VIRTIO=m +# CONFIG_HW_RANDOM_EXYNOS is not set +CONFIG_HW_RANDOM_TPM=m +# CONFIG_NVRAM is not set +CONFIG_R3964=m +# CONFIG_APPLICOM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_IPWIRELESS=m +CONFIG_RAW_DRIVER=y +CONFIG_MAX_RAW_DEVS=8192 +CONFIG_TCG_TPM=m +# CONFIG_TCG_TIS_I2C_ATMEL is not set +# CONFIG_TCG_TIS_I2C_INFINEON is not set +# CONFIG_TCG_TIS_I2C_NUVOTON is not set +CONFIG_TCG_ATMEL=m +# CONFIG_TCG_ST33_I2C is not set +CONFIG_DEVPORT=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +# CONFIG_I2C_COMPAT is not set +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_SMBUS=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set +# CONFIG_I2C_EG20T is not set +# CONFIG_I2C_GPIO is not set +CONFIG_I2C_IMX=y +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PCA_PLATFORM=m +# CONFIG_I2C_PXA_PCI is not set +CONFIG_I2C_SIMTEC=m +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +CONFIG_I2C_DIOLAN_U2C=m +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +CONFIG_I2C_TINY_USB=m +CONFIG_I2C_VIPERBOARD=m + +# +# Other I2C/SMBus bus drivers +# +CONFIG_I2C_STUB=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_BUTTERFLY is not set +# CONFIG_SPI_GPIO is not set +CONFIG_SPI_IMX=y +# CONFIG_SPI_LM70_LLP is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_TOPCLIFF_PCH is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_HSI is not set + +# +# PPS support +# +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +CONFIG_PPS_CLIENT_LDISC=m +CONFIG_PPS_CLIENT_PARPORT=m +CONFIG_PPS_CLIENT_GPIO=m + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y +CONFIG_DP83640_PHY=m +CONFIG_PINCTRL=y + +# +# Pin controllers +# +CONFIG_PINMUX=y +CONFIG_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_CAPRI is not set +CONFIG_PINCTRL_IMX=y +CONFIG_PINCTRL_IMX6Q=y +CONFIG_PINCTRL_IMX6SL=y +# CONFIG_PINCTRL_MSM8X74 is not set +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_GENERIC=y +# CONFIG_GPIO_DA9052 is not set +CONFIG_GPIO_MAX730X=m + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_EM is not set +CONFIG_GPIO_MXC=y +# CONFIG_GPIO_RCAR is not set +# CONFIG_GPIO_SCH311X is not set +# CONFIG_GPIO_TS5500 is not set +# CONFIG_GPIO_VX855 is not set +# CONFIG_GPIO_GRGPIO is not set + +# +# I2C GPIO expanders: +# +CONFIG_GPIO_MAX7300=m +CONFIG_GPIO_MAX732X=m +# CONFIG_GPIO_PCA953X_IRQ is not set +CONFIG_GPIO_PCF857X=m +CONFIG_GPIO_SX150X=y +CONFIG_GPIO_ADP5588=m +CONFIG_GPIO_ADNP=m + +# +# PCI GPIO expanders: +# +# CONFIG_GPIO_AMD8111 is not set +# CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_RDC321X is not set + +# +# SPI GPIO expanders: +# +CONFIG_GPIO_MAX7301=m +CONFIG_GPIO_MCP23S08=m +CONFIG_GPIO_MC33880=m +CONFIG_GPIO_74X164=m + +# +# AC97 GPIO expanders: +# + +# +# LPC GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_GPIO_BCM_KONA is not set + +# +# USB GPIO expanders: +# +CONFIG_GPIO_VIPERBOARD=m +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +# CONFIG_W1_MASTER_MATROX is not set +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m +# CONFIG_W1_MASTER_MXC is not set +CONFIG_W1_MASTER_DS1WM=m +CONFIG_W1_MASTER_GPIO=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2408=m +# CONFIG_W1_SLAVE_DS2408_READBACK is not set +CONFIG_W1_SLAVE_DS2413=m +CONFIG_W1_SLAVE_DS2423=m +CONFIG_W1_SLAVE_DS2431=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y +CONFIG_W1_SLAVE_DS2760=m +CONFIG_W1_SLAVE_DS2780=m +CONFIG_W1_SLAVE_DS2781=m +CONFIG_W1_SLAVE_DS28E04=m +CONFIG_W1_SLAVE_BQ27000=m +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_GENERIC_ADC_BATTERY is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2760 is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_DA9052 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24735 is not set +CONFIG_CHARGER_SMB347=m +# CONFIG_IMX6_USB_CHARGER is not set +CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_AVS is not set +CONFIG_HWMON=y +CONFIG_HWMON_VID=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +CONFIG_SENSORS_AD7414=m +CONFIG_SENSORS_AD7418=m +# CONFIG_SENSORS_ADCXX is not set +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1029=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ADT7X10=m +CONFIG_SENSORS_ADT7310=m +CONFIG_SENSORS_ADT7410=m +CONFIG_SENSORS_ADT7411=m +CONFIG_SENSORS_ADT7462=m +CONFIG_SENSORS_ADT7470=m +CONFIG_SENSORS_ADT7475=m +CONFIG_SENSORS_ASC7621=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS620=m +CONFIG_SENSORS_DS1621=m +# CONFIG_SENSORS_DA9052_ADC is not set +# CONFIG_SENSORS_I5K_AMB is not set +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_F71882FG=m +CONFIG_SENSORS_F75375S=m +CONFIG_SENSORS_G760A=m +CONFIG_SENSORS_G762=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_HTU21 is not set +CONFIG_SENSORS_IBMAEM=m +CONFIG_SENSORS_IBMPEX=m +# CONFIG_SENSORS_IIO_HWMON is not set +CONFIG_SENSORS_IT87=m +# CONFIG_SENSORS_JC42 is not set +CONFIG_SENSORS_LINEAGE=m +CONFIG_SENSORS_LM63=m +# CONFIG_SENSORS_LM70 is not set +CONFIG_SENSORS_LM73=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_LM93=m +CONFIG_SENSORS_LTC4151=m +CONFIG_SENSORS_LTC4215=m +CONFIG_SENSORS_LTC4245=m +CONFIG_SENSORS_LTC4261=m +CONFIG_SENSORS_LM95234=m +CONFIG_SENSORS_LM95241=m +CONFIG_SENSORS_LM95245=m +# CONFIG_SENSORS_MAX1111 is not set +CONFIG_SENSORS_MAX16065=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_MAX1668=m +CONFIG_SENSORS_MAX197=m +CONFIG_SENSORS_MAX6639=m +CONFIG_SENSORS_MAX6642=m +CONFIG_SENSORS_MAX6650=m +CONFIG_SENSORS_MAX6697=m +CONFIG_SENSORS_MCP3021=m +CONFIG_SENSORS_NCT6775=m +CONFIG_SENSORS_NTC_THERMISTOR=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_PC87427=m +CONFIG_SENSORS_PCF8591=m +CONFIG_PMBUS=m +CONFIG_SENSORS_PMBUS=m +CONFIG_SENSORS_ADM1275=m +CONFIG_SENSORS_LM25066=m +CONFIG_SENSORS_LTC2978=m +CONFIG_SENSORS_MAX16064=m +CONFIG_SENSORS_MAX34440=m +CONFIG_SENSORS_MAX8688=m +CONFIG_SENSORS_UCD9000=m +CONFIG_SENSORS_UCD9200=m +CONFIG_SENSORS_ZL6100=m +CONFIG_SENSORS_SHT15=m +CONFIG_SENSORS_SHT21=m +CONFIG_SENSORS_SIS5595=m +# CONFIG_SENSORS_SMM665 is not set +CONFIG_SENSORS_DME1737=m +CONFIG_SENSORS_EMC1403=m +# CONFIG_SENSORS_EMC2103 is not set +CONFIG_SENSORS_EMC6W201=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_SCH56XX_COMMON=m +CONFIG_SENSORS_SCH5627=m +CONFIG_SENSORS_SCH5636=m +CONFIG_SENSORS_ADS1015=m +CONFIG_SENSORS_ADS7828=m +# CONFIG_SENSORS_ADS7871 is not set +CONFIG_SENSORS_AMC6821=m +CONFIG_SENSORS_INA209=m +CONFIG_SENSORS_INA2XX=m +CONFIG_SENSORS_THMC50=m +CONFIG_SENSORS_TMP102=m +CONFIG_SENSORS_TMP401=m +CONFIG_SENSORS_TMP421=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT1211=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83793=m +CONFIG_SENSORS_W83795=m +# CONFIG_SENSORS_W83795_FANCTRL is not set +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83L786NG=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +# CONFIG_SENSORS_MC13783_ADC is not set +# CONFIG_SENSORS_MAG3110 is not set +# CONFIG_MXC_MMA8451 is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +# CONFIG_THERMAL_OF is not set +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +CONFIG_THERMAL_GOV_FAIR_SHARE=y +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_USER_SPACE is not set +# CONFIG_THERMAL_EMULATION is not set +CONFIG_DEVICE_THERMAL=y + +# +# Texas Instruments thermal drivers +# +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +# CONFIG_DA9052_WATCHDOG is not set +# CONFIG_GPIO_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set +CONFIG_IMX2_WDT=y +CONFIG_ALIM7101_WDT=m +CONFIG_I6300ESB_WDT=m +# CONFIG_MEN_A21_WDT is not set + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB=m +CONFIG_SSB_SPROM=y +CONFIG_SSB_BLOCKIO=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +CONFIG_SSB_PCIHOST=y +CONFIG_SSB_B43_PCI_BRIDGE=y +CONFIG_SSB_PCMCIAHOST_POSSIBLE=y +CONFIG_SSB_PCMCIAHOST=y +CONFIG_SSB_SDIOHOST_POSSIBLE=y +CONFIG_SSB_SDIOHOST=y +# CONFIG_SSB_SILENT is not set +# CONFIG_SSB_DEBUG is not set +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_DRIVER_PCICORE=y +CONFIG_SSB_DRIVER_GPIO=y +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +CONFIG_BCMA=m +CONFIG_BCMA_BLOCKIO=y +CONFIG_BCMA_HOST_PCI_POSSIBLE=y +CONFIG_BCMA_HOST_PCI=y +# CONFIG_BCMA_HOST_SOC is not set +CONFIG_BCMA_DRIVER_GMAC_CMN=y +CONFIG_BCMA_DRIVER_GPIO=y +# CONFIG_BCMA_DEBUG is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_PMIC_DA903X is not set +CONFIG_PMIC_DA9052=y +# CONFIG_MFD_DA9052_SPI is not set +CONFIG_MFD_DA9052_I2C=y +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9063 is not set +CONFIG_MFD_MXC_HDMI=y +CONFIG_MFD_MC13XXX=y +CONFIG_MFD_MC13XXX_SPI=y +CONFIG_MFD_MC13XXX_I2C=y +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_EZX_PCAP is not set +CONFIG_MFD_VIPERBOARD=m +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_UCB1400_CORE is not set +# CONFIG_MFD_RDC321X is not set +CONFIG_MFD_RTSX_PCI=m +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_SEC_CORE is not set +CONFIG_MFD_SI476X_CORE=y +CONFIG_MFD_SM501=m +CONFIG_MFD_SM501_GPIO=y +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TIMBERDALE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +CONFIG_MFD_VX855=m +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_VEXPRESS_CONFIG is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +CONFIG_REGULATOR_ANATOP=y +# CONFIG_REGULATOR_DA9052 is not set +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_REGULATOR_GPIO is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_MC13783 is not set +# CONFIG_REGULATOR_MC13892 is not set +CONFIG_REGULATOR_PFUZE100=y +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +# CONFIG_MEDIA_RADIO_SUPPORT is not set +CONFIG_MEDIA_RC_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_VIDEO_V4L2=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEOBUF_GEN=y +CONFIG_VIDEOBUF_DMA_SG=m +CONFIG_VIDEOBUF_VMALLOC=m +CONFIG_VIDEOBUF_DMA_CONTIG=y +CONFIG_VIDEOBUF_DVB=m +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_MEMOPS=m +CONFIG_VIDEOBUF2_DMA_CONTIG=m +CONFIG_VIDEOBUF2_VMALLOC=m +CONFIG_DVB_CORE=y +CONFIG_DVB_NET=y +CONFIG_TTPCI_EEPROM=m +CONFIG_DVB_MAX_ADAPTERS=8 +CONFIG_DVB_DYNAMIC_MINORS=y + +# +# Media drivers +# +CONFIG_RC_CORE=y +CONFIG_RC_MAP=m +CONFIG_RC_DECODERS=y +CONFIG_LIRC=m +CONFIG_IR_LIRC_CODEC=m +CONFIG_IR_NEC_DECODER=m +CONFIG_IR_RC5_DECODER=m +CONFIG_IR_RC6_DECODER=m +CONFIG_IR_JVC_DECODER=m +CONFIG_IR_SONY_DECODER=m +CONFIG_IR_RC5_SZ_DECODER=m +CONFIG_IR_SANYO_DECODER=m +CONFIG_IR_MCE_KBD_DECODER=m +CONFIG_RC_DEVICES=y +CONFIG_RC_ATI_REMOTE=m +CONFIG_IR_IMON=m +CONFIG_IR_MCEUSB=m +CONFIG_IR_REDRAT3=m +CONFIG_IR_STREAMZAP=m +CONFIG_IR_IGUANA=m +CONFIG_IR_TTUSBIR=m +CONFIG_RC_LOOPBACK=m +CONFIG_IR_GPIO_CIR=m +CONFIG_MEDIA_USB_SUPPORT=y + +# +# Webcam devices +# +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=m +CONFIG_USB_M5602=m +CONFIG_USB_STV06XX=m +CONFIG_USB_GL860=m +CONFIG_USB_GSPCA_BENQ=m +CONFIG_USB_GSPCA_CONEX=m +CONFIG_USB_GSPCA_CPIA1=m +CONFIG_USB_GSPCA_ETOMS=m +CONFIG_USB_GSPCA_FINEPIX=m +CONFIG_USB_GSPCA_JEILINJ=m +CONFIG_USB_GSPCA_JL2005BCD=m +CONFIG_USB_GSPCA_KINECT=m +CONFIG_USB_GSPCA_KONICA=m +CONFIG_USB_GSPCA_MARS=m +CONFIG_USB_GSPCA_MR97310A=m +CONFIG_USB_GSPCA_NW80X=m +CONFIG_USB_GSPCA_OV519=m +CONFIG_USB_GSPCA_OV534=m +CONFIG_USB_GSPCA_OV534_9=m +CONFIG_USB_GSPCA_PAC207=m +CONFIG_USB_GSPCA_PAC7302=m +CONFIG_USB_GSPCA_PAC7311=m +CONFIG_USB_GSPCA_SE401=m +CONFIG_USB_GSPCA_SN9C2028=m +CONFIG_USB_GSPCA_SN9C20X=m +CONFIG_USB_GSPCA_SONIXB=m +CONFIG_USB_GSPCA_SONIXJ=m +CONFIG_USB_GSPCA_SPCA500=m +CONFIG_USB_GSPCA_SPCA501=m +CONFIG_USB_GSPCA_SPCA505=m +CONFIG_USB_GSPCA_SPCA506=m +CONFIG_USB_GSPCA_SPCA508=m +CONFIG_USB_GSPCA_SPCA561=m +CONFIG_USB_GSPCA_SPCA1528=m +CONFIG_USB_GSPCA_SQ905=m +CONFIG_USB_GSPCA_SQ905C=m +CONFIG_USB_GSPCA_SQ930X=m +CONFIG_USB_GSPCA_STK014=m +CONFIG_USB_GSPCA_STK1135=m +CONFIG_USB_GSPCA_STV0680=m +CONFIG_USB_GSPCA_SUNPLUS=m +CONFIG_USB_GSPCA_T613=m +CONFIG_USB_GSPCA_TOPRO=m +CONFIG_USB_GSPCA_TV8532=m +CONFIG_USB_GSPCA_VC032X=m +CONFIG_USB_GSPCA_VICAM=m +CONFIG_USB_GSPCA_XIRLINK_CIT=m +CONFIG_USB_GSPCA_ZC3XX=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set +CONFIG_USB_PWC_INPUT_EVDEV=y +CONFIG_VIDEO_CPIA2=m +CONFIG_USB_ZR364XX=m +CONFIG_USB_STKWEBCAM=m +CONFIG_USB_S2255=m +CONFIG_VIDEO_USBTV=m + +# +# Analog TV USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_PVRUSB2_DVB=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_TLG2300=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_STK1160_COMMON=m +CONFIG_VIDEO_STK1160_AC97=y +CONFIG_VIDEO_STK1160=m + +# +# Analog/digital TV USB devices +# +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_AU0828_V4L2=y +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_RC=y +CONFIG_VIDEO_CX231XX_ALSA=m +CONFIG_VIDEO_CX231XX_DVB=m +CONFIG_VIDEO_TM6000=m +CONFIG_VIDEO_TM6000_ALSA=m +CONFIG_VIDEO_TM6000_DVB=m + +# +# Digital TV USB devices +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_PCTV452E=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_CINERGY_T2=m +CONFIG_DVB_USB_DTV5100=m +CONFIG_DVB_USB_FRIIO=m +CONFIG_DVB_USB_AZ6027=m +CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_USB_V2=m +CONFIG_DVB_USB_AF9015=m +CONFIG_DVB_USB_AF9035=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_AZ6007=m +CONFIG_DVB_USB_CE6230=m +CONFIG_DVB_USB_EC168=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_IT913X=m +CONFIG_DVB_USB_LME2510=m +CONFIG_DVB_USB_MXL111SF=m +CONFIG_DVB_USB_RTL28XXU=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_SMS_USB_DRV=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set + +# +# Webcam, TV (analog/digital) USB devices +# +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_EM28XX_V4L2=m +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_VIDEO_EM28XX_RC=m +CONFIG_MEDIA_PCI_SUPPORT=y + +# +# Media capture support +# + +# +# Media capture/analog TV support +# +CONFIG_VIDEO_IVTV=m +# CONFIG_VIDEO_IVTV_ALSA is not set +CONFIG_VIDEO_FB_IVTV=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_MXB=m + +# +# Media capture/analog/hybrid TV support +# +CONFIG_VIDEO_CX18=m +CONFIG_VIDEO_CX18_ALSA=m +CONFIG_VIDEO_CX23885=m +CONFIG_MEDIA_ALTERA_CI=m +# CONFIG_VIDEO_CX25821 is not set +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_ENABLE_VP3054=y +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88_MPEG=m +CONFIG_VIDEO_BT848=m +CONFIG_DVB_BT8XX=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_RC=y +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7164=m + +# +# Media digital TV PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET_CORE=m +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +# CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG is not set +CONFIG_DVB_PLUTO2=m +CONFIG_DVB_DM1105=m +CONFIG_DVB_PT1=m +CONFIG_MANTIS_CORE=m +CONFIG_DVB_MANTIS=m +CONFIG_DVB_HOPPER=m +CONFIG_DVB_NGENE=m +CONFIG_DVB_DDBRIDGE=m +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_VIDEO_CAFE_CCIC=m +# CONFIG_VIDEO_TIMBERDALE is not set +CONFIG_VIDEO_MXC_OUTPUT=y +CONFIG_VIDEO_MXC_IPU_OUTPUT=y +CONFIG_SOC_CAMERA=y +# CONFIG_SOC_CAMERA_PLATFORM is not set +# CONFIG_VIDEO_MX3 is not set +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set +# CONFIG_VIDEO_SH_MOBILE_CEU is not set +CONFIG_V4L_MEM2MEM_DRIVERS=y +# CONFIG_VIDEO_CODA is not set +# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set +# CONFIG_VIDEO_SH_VEU is not set +# CONFIG_VIDEO_RENESAS_VSP1 is not set +# CONFIG_V4L_TEST_DRIVERS is not set + +# +# Supported MMC/SDIO adapters +# +CONFIG_SMS_SDIO_DRV=m +# CONFIG_MEDIA_PARPORT_SUPPORT is not set + +# +# Supported FireWire (IEEE 1394) Adapters +# +CONFIG_DVB_FIREDTV=m +CONFIG_DVB_FIREDTV_INPUT=y +CONFIG_MEDIA_COMMON_OPTIONS=y + +# +# common driver options +# +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_SMS_SIANO_MDTV=m +CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set + +# +# Media ancillary drivers (tuners, sensors, i2c, frontends) +# +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y +CONFIG_VIDEO_IR_I2C=y + +# +# Audio decoders, processors and mixers +# +CONFIG_VIDEO_TVAUDIO=m +CONFIG_VIDEO_TDA7432=m +CONFIG_VIDEO_TDA9840=m +CONFIG_VIDEO_TEA6415C=m +CONFIG_VIDEO_TEA6420=m +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS5345=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_VP27SMPX=m + +# +# RDS decoders +# +CONFIG_VIDEO_SAA6588=m + +# +# Video decoders +# +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_TVP5150=m + +# +# Video and audio decoders +# +CONFIG_VIDEO_SAA717X=m +CONFIG_VIDEO_CX25840=m + +# +# Video encoders +# +CONFIG_VIDEO_SAA7127=m + +# +# Camera sensor devices +# +CONFIG_VIDEO_OV7670=m +CONFIG_VIDEO_MT9V011=m + +# +# Flash devices +# + +# +# Video improvement chips +# +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# Audio/Video compression chips +# +CONFIG_VIDEO_SAA6752HS=m + +# +# Miscellaneous helper chips +# +CONFIG_VIDEO_M52790=m + +# +# Sensors used on soc_camera driver +# + +# +# soc_camera sensor drivers +# +# CONFIG_SOC_CAMERA_IMX074 is not set +# CONFIG_SOC_CAMERA_MT9M001 is not set +# CONFIG_SOC_CAMERA_MT9M111 is not set +# CONFIG_SOC_CAMERA_MT9T031 is not set +# CONFIG_SOC_CAMERA_MT9T112 is not set +# CONFIG_SOC_CAMERA_MT9V022 is not set +CONFIG_SOC_CAMERA_OV2640=y +# CONFIG_SOC_CAMERA_OV5642 is not set +# CONFIG_SOC_CAMERA_OV6650 is not set +# CONFIG_SOC_CAMERA_OV772X is not set +# CONFIG_SOC_CAMERA_OV9640 is not set +# CONFIG_SOC_CAMERA_OV9740 is not set +# CONFIG_SOC_CAMERA_RJ54N1 is not set +# CONFIG_SOC_CAMERA_TW9910 is not set +CONFIG_MEDIA_TUNER=y +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA827X=y +CONFIG_MEDIA_TUNER_TDA18271=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT2063=m +CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_MT2131=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_XC4000=y +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_MEDIA_TUNER_MXL5007T=m +CONFIG_MEDIA_TUNER_MC44S803=y +CONFIG_MEDIA_TUNER_MAX2165=m +CONFIG_MEDIA_TUNER_TDA18218=m +CONFIG_MEDIA_TUNER_FC0011=m +CONFIG_MEDIA_TUNER_FC0012=m +CONFIG_MEDIA_TUNER_FC0013=m +CONFIG_MEDIA_TUNER_TDA18212=m +CONFIG_MEDIA_TUNER_E4000=m +CONFIG_MEDIA_TUNER_FC2580=m +CONFIG_MEDIA_TUNER_M88TS2022=m +CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m + +# +# Multistandard (satellite) frontends +# +CONFIG_DVB_STB0899=m +CONFIG_DVB_STB6100=m +CONFIG_DVB_STV090x=m +CONFIG_DVB_STV6110x=m +CONFIG_DVB_M88DS3103=m + +# +# Multistandard (cable + terrestrial) frontends +# +CONFIG_DVB_DRXK=m +CONFIG_DVB_TDA18271C2DD=m + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_MT312=m +CONFIG_DVB_ZL10036=m +CONFIG_DVB_ZL10039=m +CONFIG_DVB_S5H1420=m +CONFIG_DVB_STV0288=m +CONFIG_DVB_STB6000=m +CONFIG_DVB_STV0299=m +CONFIG_DVB_STV6110=m +CONFIG_DVB_STV0900=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_TDA10086=m +CONFIG_DVB_TDA8261=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_TUNER_ITD1000=m +CONFIG_DVB_TUNER_CX24113=m +CONFIG_DVB_TDA826X=m +CONFIG_DVB_TUA6100=m +CONFIG_DVB_CX24116=m +CONFIG_DVB_CX24117=m +CONFIG_DVB_SI21XX=m +CONFIG_DVB_TS2020=m +CONFIG_DVB_DS3000=m +CONFIG_DVB_MB86A16=m +CONFIG_DVB_TDA10071=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_DRXD=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_DIB7000M=m +CONFIG_DVB_DIB7000P=m +CONFIG_DVB_TDA10048=m +CONFIG_DVB_AF9013=m +CONFIG_DVB_EC100=m +CONFIG_DVB_STV0367=m +CONFIG_DVB_CXD2820R=m +CONFIG_DVB_RTL2830=m +CONFIG_DVB_RTL2832=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_TDA10023=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m +CONFIG_DVB_LGDT3305=m +CONFIG_DVB_LG2160=m +CONFIG_DVB_S5H1409=m +CONFIG_DVB_AU8522=m +CONFIG_DVB_AU8522_DTV=m +CONFIG_DVB_AU8522_V4L=m +CONFIG_DVB_S5H1411=m + +# +# ISDB-T (terrestrial) frontends +# +CONFIG_DVB_S921=m +CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m + +# +# Digital terrestrial only tuners/PLL +# +CONFIG_DVB_PLL=m +CONFIG_DVB_TUNER_DIB0070=m +CONFIG_DVB_TUNER_DIB0090=m + +# +# SEC control devices for DVB-S +# +CONFIG_DVB_LNBP21=m +CONFIG_DVB_LNBP22=m +CONFIG_DVB_ISL6405=m +CONFIG_DVB_ISL6421=m +CONFIG_DVB_ISL6423=m +CONFIG_DVB_A8293=m +CONFIG_DVB_LGS8GXX=m +CONFIG_DVB_ATBM8830=m +CONFIG_DVB_TDA665x=m +CONFIG_DVB_IX2505V=m +CONFIG_DVB_IT913X_FE=m +CONFIG_DVB_M88RS2000=m +CONFIG_DVB_AF9033=m + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set + +# +# Graphics support +# +CONFIG_FB_TFT=y +CONFIG_FB_TFT_AGM1264K_FL=m +CONFIG_FB_TFT_BD663474=m +CONFIG_FB_TFT_HX8340BN=m +CONFIG_FB_TFT_HX8347D=m +CONFIG_FB_TFT_HX8353D=m +CONFIG_FB_TFT_ILI9320=m +CONFIG_FB_TFT_ILI9325=m +CONFIG_FB_TFT_ILI9340=m +CONFIG_FB_TFT_ILI9341=m +CONFIG_FB_TFT_ILI9481=m +CONFIG_FB_TFT_ILI9486=m +CONFIG_FB_TFT_PCD8544=m +CONFIG_FB_TFT_RA8875=m +CONFIG_FB_TFT_S6D02A1=m +CONFIG_FB_TFT_S6D1121=m +CONFIG_FB_TFT_SSD1289=m +CONFIG_FB_TFT_SSD1306=m +CONFIG_FB_TFT_SSD1331=m +CONFIG_FB_TFT_SSD1351=m +CONFIG_FB_TFT_ST7735R=m +CONFIG_FB_TFT_TINYLCD=m +CONFIG_FB_TFT_TLS8204=m +CONFIG_FB_TFT_UC1701=m +CONFIG_FB_TFT_UPD161704=m +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +CONFIG_DRM=y +# CONFIG_DRM_TDFX is not set +# CONFIG_DRM_R128 is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_DRM_MGA is not set +# CONFIG_DRM_VIA is not set +# CONFIG_DRM_SAVAGE is not set +CONFIG_DRM_VIVANTE=y +# CONFIG_DRM_EXYNOS is not set +# CONFIG_DRM_VMWGFX is not set +# CONFIG_DRM_UDL is not set +# CONFIG_DRM_AST is not set +# CONFIG_DRM_MGAG200 is not set +# CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_ARMADA is not set +# CONFIG_DRM_RCAR_DU is not set +# CONFIG_DRM_SHMOBILE is not set +# CONFIG_DRM_TILCDC is not set +# CONFIG_DRM_QXL is not set +# CONFIG_DRM_BOCHS is not set +# CONFIG_VGASTATE is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m +CONFIG_HDMI=y +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=y +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +CONFIG_FB_BACKLIGHT=y +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_ARMHDLCD is not set +# CONFIG_FB_IMX is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_I740 is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set +# CONFIG_FB_TMIO is not set +# CONFIG_FB_SM501 is not set +# CONFIG_FB_SMSCUFX is not set +CONFIG_FB_UDL=m +# CONFIG_FB_GOLDFISH is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_MX3 is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_EXYNOS_VIDEO is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=m +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI922X is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +CONFIG_LCD_PLATFORM=m +# CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_LCD_AMS369FG06 is not set +# CONFIG_LCD_LMS501KF03 is not set +# CONFIG_LCD_HX8357 is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_GENERIC is not set +# CONFIG_BACKLIGHT_PWM is not set +# CONFIG_BACKLIGHT_DA9052 is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set +CONFIG_FB_MXC=y +CONFIG_FB_MXC_SYNC_PANEL=y +CONFIG_FB_MXC_LDB=y +# CONFIG_FB_MXC_MIPI_DSI is not set +CONFIG_FB_MXC_HDMI=y +CONFIG_FB_MXC_EDID=y + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_FB_SSD1307 is not set +CONFIG_SOUND=y +CONFIG_SOUND_OSS_CORE=y +CONFIG_SOUND_OSS_CORE_PRECLAIM=y +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_DMAENGINE_PCM=y +CONFIG_SND_HWDEP=y +CONFIG_SND_RAWMIDI=m +CONFIG_SND_COMPRESS_OFFLOAD=y +CONFIG_SND_JACK=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_MAX_CARDS=32 +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_VMASTER=y +CONFIG_SND_KCTL_JACK=y +CONFIG_SND_RAWMIDI_SEQ=m +CONFIG_SND_OPL3_LIB_SEQ=m +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +CONFIG_SND_EMU10K1_SEQ=m +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=y +CONFIG_SND_DRIVERS=y +CONFIG_SND_DUMMY=m +CONFIG_SND_ALOOP=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +CONFIG_SND_MTS64=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m +CONFIG_SND_PORTMAN2X4=m +CONFIG_SND_AC97_POWER_SAVE=y +CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 +CONFIG_SND_PCI=y +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +# CONFIG_SND_AW2 is not set +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_OXYGEN_LIB=m +CONFIG_SND_OXYGEN=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CS5535AUDIO=m +CONFIG_SND_CTXFI=m +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_INDIGOIOX=m +CONFIG_SND_INDIGODJX=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_ES1968_INPUT=y +CONFIG_SND_FM801=m +CONFIG_SND_HDA_INTEL=y +CONFIG_SND_HDA_DSP_LOADER=y +CONFIG_SND_HDA_PREALLOC_SIZE=4096 +CONFIG_SND_HDA_HWDEP=y +CONFIG_SND_HDA_RECONFIG=y +CONFIG_SND_HDA_INPUT_BEEP=y +CONFIG_SND_HDA_INPUT_BEEP_MODE=0 +CONFIG_SND_HDA_INPUT_JACK=y +CONFIG_SND_HDA_PATCH_LOADER=y +CONFIG_SND_HDA_CODEC_REALTEK=y +CONFIG_SND_HDA_CODEC_ANALOG=y +CONFIG_SND_HDA_CODEC_SIGMATEL=y +CONFIG_SND_HDA_CODEC_VIA=y +CONFIG_SND_HDA_CODEC_HDMI=y +CONFIG_SND_HDA_CODEC_CIRRUS=y +CONFIG_SND_HDA_CODEC_CONEXANT=y +CONFIG_SND_HDA_CODEC_CA0110=y +CONFIG_SND_HDA_CODEC_CA0132=y +CONFIG_SND_HDA_CODEC_CA0132_DSP=y +CONFIG_SND_HDA_CODEC_CMEDIA=y +CONFIG_SND_HDA_CODEC_SI3054=y +CONFIG_SND_HDA_GENERIC=y +CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=y +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_LOLA=m +CONFIG_SND_LX6464ES=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MAESTRO3_INPUT=y +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VIRTUOSO=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_6FIRE=m +CONFIG_SND_USB_HIFACE=m +CONFIG_SND_FIREWIRE=y +CONFIG_SND_FIREWIRE_LIB=m +CONFIG_SND_DICE=m +CONFIG_SND_FIREWIRE_SPEAKERS=m +CONFIG_SND_ISIGHT=m +CONFIG_SND_SCS1X=m +# CONFIG_SND_PCMCIA is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_DESIGNWARE_I2S is not set +CONFIG_SND_SOC_FSL_SSI=y +CONFIG_SND_SOC_FSL_SPDIF=y +CONFIG_SND_SOC_FSL_ASRC=y +CONFIG_SND_SOC_FSL_HDMI=y +CONFIG_SND_IMX_SOC=y +CONFIG_SND_SOC_IMX_PCM_DMA=y +CONFIG_SND_SOC_IMX_HDMI_DMA=y +CONFIG_SND_SOC_IMX_AUDMUX=y +# CONFIG_SND_SOC_IMX_CS42888 is not set +# CONFIG_SND_SOC_IMX_WM8962 is not set +CONFIG_SND_SOC_IMX_SGTL5000=y +CONFIG_SND_SOC_IMX_SPDIF=y +CONFIG_SND_SOC_IMX_HDMI=y +# CONFIG_SND_SOC_IMX_MC13783 is not set +CONFIG_SND_SOC_I2C_AND_SPI=y +CONFIG_SND_SOC_HDMI_CODEC=y +CONFIG_SND_SOC_SGTL5000=y +# CONFIG_SND_SIMPLE_CARD is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_AC97_BUS=y + +# +# HID support +# +CONFIG_HID=y +CONFIG_HID_BATTERY_STRENGTH=y +CONFIG_HIDRAW=y +CONFIG_UHID=m +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +CONFIG_HID_ACRUX=m +CONFIG_HID_ACRUX_FF=y +CONFIG_HID_APPLE=m +CONFIG_HID_APPLEIR=m +CONFIG_HID_AUREAL=m +# CONFIG_HID_BELKIN is not set +CONFIG_HID_CHERRY=y +# CONFIG_HID_CHICONY is not set +CONFIG_HID_PRODIKEYS=m +# CONFIG_HID_CYPRESS is not set +CONFIG_HID_DRAGONRISE=m +CONFIG_DRAGONRISE_FF=y +CONFIG_HID_EMS_FF=m +CONFIG_HID_ELECOM=m +CONFIG_HID_ELO=m +# CONFIG_HID_EZKEY is not set +CONFIG_HID_HOLTEK=m +CONFIG_HOLTEK_FF=y +CONFIG_HID_HUION=m +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_KYE=m +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WALTOP=m +CONFIG_HID_GYRATION=m +CONFIG_HID_ICADE=m +CONFIG_HID_TWINHAN=m +# CONFIG_HID_KENSINGTON is not set +CONFIG_HID_LCPOWER=m +CONFIG_HID_LENOVO_TPKBD=m +# CONFIG_HID_LOGITECH is not set +CONFIG_HID_MAGICMOUSE=y +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NTRIG=y +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_PANTHERLORD_FF=y +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +# CONFIG_HID_PICOLCD_FB is not set +# CONFIG_HID_PICOLCD_BACKLIGHT is not set +# CONFIG_HID_PICOLCD_LCD is not set +# CONFIG_HID_PICOLCD_LEDS is not set +# CONFIG_HID_PICOLCD_CIR is not set +CONFIG_HID_PRIMAX=m +CONFIG_HID_ROCCAT=m +CONFIG_HID_SAITEK=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_SONY_FF=y +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_STEELSERIES=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_GREENASIA=m +CONFIG_GREENASIA_FF=y +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_HID_TIVO=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_THINGM=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_THRUSTMASTER_FF=y +CONFIG_HID_WACOM=m +CONFIG_HID_WIIMOTE=m +CONFIG_HID_XINMO=m +CONFIG_HID_ZEROPLUS=m +CONFIG_ZEROPLUS_FF=y +CONFIG_HID_ZYDACRON=m +CONFIG_HID_SENSOR_HUB=m + +# +# USB HID support +# +CONFIG_USB_HID=y +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y + +# +# I2C HID support +# +CONFIG_I2C_HID=m +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=y +CONFIG_USB_WUSB=m +CONFIG_USB_WUSB_CBAF=m +# CONFIG_USB_WUSB_CBAF_DEBUG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_MXC is not set +# CONFIG_USB_EHCI_HCD_SYNOPSYS is not set +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +CONFIG_USB_ISP1362_HCD=m +CONFIG_USB_FUSBH200_HCD=m +# CONFIG_USB_FOTG210_HCD is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PCI=y +# CONFIG_USB_OHCI_HCD_PLATFORM is not set +CONFIG_USB_UHCI_HCD=y +CONFIG_USB_U132_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_HCD_ISO=y +# CONFIG_USB_SL811_CS is not set +# CONFIG_USB_R8A66597_HCD is not set +CONFIG_USB_WHCI_HCD=m +CONFIG_USB_HWA_HCD=m +# CONFIG_USB_IMX21_HCD is not set +# CONFIG_USB_HCD_BCMA is not set +# CONFIG_USB_HCD_SSB is not set +# CONFIG_USB_HCD_TEST_MODE is not set +# CONFIG_USB_RENESAS_USBHS is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_WDM=m +CONFIG_USB_TMC=m + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_REALTEK=m +CONFIG_REALTEK_AUTOPM=y +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +CONFIG_USB_STORAGE_ENE_UB6250=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_DWC2 is not set +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +# CONFIG_USB_CHIPIDEA_DEBUG is not set + +# +# USB port drivers +# +CONFIG_USB_USS720=m +CONFIG_USB_SERIAL=y +CONFIG_USB_SERIAL_CONSOLE=y +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_SIMPLE=m +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +# CONFIG_USB_SERIAL_F81232 is not set +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +# CONFIG_USB_SERIAL_METRO is not set +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7715_PARPORT=y +CONFIG_USB_SERIAL_MOS7840=m +# CONFIG_USB_SERIAL_MXUPORT is not set +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_WWAN=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_XSENS_MT=m +# CONFIG_USB_SERIAL_WISHBONE is not set +# CONFIG_USB_SERIAL_ZTE is not set +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m +CONFIG_USB_SERIAL_DEBUG=m + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_SEVSEG=m +# CONFIG_USB_RIO500 is not set +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_IDMOUSE=m +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +# CONFIG_USB_TEST is not set +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_YUREX=m +CONFIG_USB_EZUSB_FX2=m +CONFIG_USB_HSIC_USB3503=m +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +# CONFIG_USB_OTG_FSM is not set +CONFIG_NOP_USB_XCEIV=y +# CONFIG_AM335X_PHY_USB is not set +# CONFIG_SAMSUNG_USB2PHY is not set +# CONFIG_SAMSUNG_USB3PHY is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +CONFIG_USB_MXS_PHY=y +CONFIG_USB_RCAR_PHY=m +# CONFIG_USB_ULPI is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FSL_USB2 is not set +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_S3C_HSOTG is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_AMD5536UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET2280 is not set +# CONFIG_USB_GOKU is not set +# CONFIG_USB_EG20T is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=m +CONFIG_USB_F_ACM=m +CONFIG_USB_F_SS_LB=m +CONFIG_USB_U_SERIAL=m +CONFIG_USB_U_ETHER=m +CONFIG_USB_F_SERIAL=m +CONFIG_USB_F_OBEX=m +CONFIG_USB_F_ECM=m +CONFIG_USB_F_SUBSET=m +CONFIG_USB_F_RNDIS=m +CONFIG_USB_F_MASS_STORAGE=m +# CONFIG_USB_CONFIGFS is not set +CONFIG_USB_ZERO=m +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_ETH_EEM is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +CONFIG_USB_MASS_STORAGE=m +# CONFIG_FSL_UTP is not set +# CONFIG_USB_GADGET_TARGET is not set +CONFIG_USB_G_SERIAL=m +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set +CONFIG_UWB=m +CONFIG_UWB_HWA=m +CONFIG_UWB_WHCI=m +CONFIG_UWB_I1480U=m +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_UNSAFE_RESUME=y +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_SDIO_UART=m +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +CONFIG_MMC_SDHCI_PCI=m +CONFIG_MMC_RICOH_MMC=y +CONFIG_MMC_SDHCI_PLTFM=y +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +CONFIG_MMC_SDHCI_ESDHC_IMX=y +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_MXC is not set +CONFIG_MMC_TIFM_SD=m +CONFIG_MMC_SDRICOH_CS=m +CONFIG_MMC_CB710=m +CONFIG_MMC_VIA_SDMMC=m +# CONFIG_MMC_DW is not set +CONFIG_MMC_VUB300=m +CONFIG_MMC_USHC=m +CONFIG_MMC_REALTEK_PCI=m +CONFIG_MEMSTICK=m +# CONFIG_MEMSTICK_DEBUG is not set + +# +# MemoryStick drivers +# +# CONFIG_MEMSTICK_UNSAFE_RESUME is not set +CONFIG_MSPRO_BLOCK=m +# CONFIG_MS_BLOCK is not set + +# +# MemoryStick Host Controller Drivers +# +CONFIG_MEMSTICK_TIFM_MS=m +CONFIG_MEMSTICK_JMICRON_38X=m +CONFIG_MEMSTICK_R592=m +CONFIG_MEMSTICK_REALTEK_PCI=m + +# +# MXC support drivers +# +CONFIG_MXC_IPU=y + +# +# MXC Vivante GPU support +# +CONFIG_MXC_GPU_VIV=y +CONFIG_MXC_IPU_V3=y + +# +# MXC Asynchronous Sample Rate Converter support +# +CONFIG_MXC_ASRC=y + +# +# MXC VPU(Video Processing Unit) support +# +CONFIG_MXC_VPU=y +# CONFIG_MXC_VPU_DEBUG is not set +# CONFIG_MX6_VPU_352M is not set + +# +# MXC HDMI CEC (Consumer Electronics Control) support +# +CONFIG_MXC_HDMI_CEC=y + +# +# MXC MIPI Support +# +CONFIG_MXC_MIPI_CSI2=y + +# +# MXC Media Local Bus Driver +# +CONFIG_MXC_MLB=y +CONFIG_MXC_MLB150=m +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +CONFIG_LEDS_LM3530=m +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_LP3944=m +CONFIG_LEDS_LP55XX_COMMON=m +CONFIG_LEDS_LP5521=m +CONFIG_LEDS_LP5523=m +CONFIG_LEDS_LP5562=m +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_PCA9685 is not set +# CONFIG_LEDS_DA9052 is not set +# CONFIG_LEDS_DAC124S085 is not set +CONFIG_LEDS_PWM=y +CONFIG_LEDS_REGULATOR=m +# CONFIG_LEDS_BD2802 is not set +CONFIG_LEDS_LT3593=m +# CONFIG_LEDS_MC13783 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_OT200 is not set +CONFIG_LEDS_BLINKM=m + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_ONESHOT=m +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LEDS_TRIGGER_BACKLIGHT=m +# CONFIG_LEDS_TRIGGER_CPU is not set +CONFIG_LEDS_TRIGGER_GPIO=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m + +# +# iptables trigger is under Netfilter config (LED target) +# +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_CAMERA=m +CONFIG_ACCESSIBILITY=y +CONFIG_A11Y_BRAILLE_CONSOLE=y +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_USER_MEM=y +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +# CONFIG_INFINIBAND_MTHCA_DEBUG is not set +CONFIG_INFINIBAND_AMSO1100=m +# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set +CONFIG_INFINIBAND_CXGB3=m +# CONFIG_INFINIBAND_CXGB3_DEBUG is not set +CONFIG_INFINIBAND_CXGB4=m +CONFIG_MLX4_INFINIBAND=m +CONFIG_MLX5_INFINIBAND=m +CONFIG_INFINIBAND_NES=m +# CONFIG_INFINIBAND_NES_DEBUG is not set +# CONFIG_INFINIBAND_OCRDMA is not set +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_CM=y +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_SRPT=m +CONFIG_INFINIBAND_ISER=m +CONFIG_INFINIBAND_ISERT=m +# CONFIG_EDAC is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +# CONFIG_RTC_SYSTOHC is not set +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1374=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS3232=m +# CONFIG_RTC_DRV_HYM8563 is not set +CONFIG_RTC_DRV_MAX6900=m +CONFIG_RTC_DRV_RS5C372=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_ISL12022=m +# CONFIG_RTC_DRV_ISL12057 is not set +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_PCF2127=m +CONFIG_RTC_DRV_PCF8523=y +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_M41T80=m +CONFIG_RTC_DRV_M41T80_WDT=y +CONFIG_RTC_DRV_BQ32K=m +# CONFIG_RTC_DRV_S35390A is not set +CONFIG_RTC_DRV_FM3130=m +CONFIG_RTC_DRV_RX8581=m +CONFIG_RTC_DRV_RX8025=m +CONFIG_RTC_DRV_EM3027=m +CONFIG_RTC_DRV_RV3029C2=m + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_RX4581 is not set + +# +# Platform RTC drivers +# +CONFIG_RTC_DRV_CMOS=y +CONFIG_RTC_DRV_DS1286=m +CONFIG_RTC_DRV_DS1511=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_DS1742=m +# CONFIG_RTC_DRV_DA9052 is not set +CONFIG_RTC_DRV_STK17TA8=m +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_M48T35=m +CONFIG_RTC_DRV_M48T59=m +CONFIG_RTC_DRV_MSM6242=m +CONFIG_RTC_DRV_BQ4802=m +CONFIG_RTC_DRV_RP5C01=m +CONFIG_RTC_DRV_V3020=m +CONFIG_RTC_DRV_DS2404=m + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_IMXDI is not set +# CONFIG_RTC_DRV_MC13XXX is not set +CONFIG_RTC_DRV_MXC=y +CONFIG_RTC_DRV_SNVS=y +# CONFIG_RTC_DRV_MOXART is not set + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_DW_DMAC_CORE=m +CONFIG_DW_DMAC=m +CONFIG_DW_DMAC_PCI=m +CONFIG_MX3_IPU=y +CONFIG_MX3_IPU_IRQS=4 +CONFIG_MXC_PXP_V2=y +CONFIG_MXC_PXP_CLIENT_DEVICE=y +# CONFIG_TIMB_DMA is not set +CONFIG_IMX_SDMA=y +# CONFIG_IMX_DMA is not set +CONFIG_MXS_DMA=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y + +# +# DMA Clients +# +CONFIG_ASYNC_TX_DMA=y +# CONFIG_DMATEST is not set +CONFIG_AUXDISPLAY=y +CONFIG_KS0108=m +CONFIG_KS0108_PORT=0x378 +CONFIG_KS0108_DELAY=2 +CONFIG_UIO=m +CONFIG_UIO_CIF=m +# CONFIG_UIO_PDRV_GENIRQ is not set +# CONFIG_UIO_DMEM_GENIRQ is not set +CONFIG_UIO_AEC=m +CONFIG_UIO_SERCOS3=m +CONFIG_UIO_PCI_GENERIC=m +# CONFIG_UIO_NETX is not set +# CONFIG_UIO_MF624 is not set +# CONFIG_VIRT_DRIVERS is not set +CONFIG_VIRTIO=m + +# +# Virtio drivers +# +CONFIG_VIRTIO_PCI=m +CONFIG_VIRTIO_BALLOON=m +CONFIG_VIRTIO_MMIO=m +# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_ET131X is not set +# CONFIG_USBIP_CORE is not set +# CONFIG_W35UND is not set +# CONFIG_PRISM2_USB is not set +# CONFIG_ECHO is not set +# CONFIG_COMEDI is not set +# CONFIG_PANEL is not set +# CONFIG_R8187SE is not set +# CONFIG_RTL8192U is not set +CONFIG_RTLLIB=m +CONFIG_RTLLIB_CRYPTO_CCMP=m +CONFIG_RTLLIB_CRYPTO_TKIP=m +CONFIG_RTLLIB_CRYPTO_WEP=m +CONFIG_RTL8192E=m +CONFIG_R8712U=m +# CONFIG_R8188EU is not set +# CONFIG_R8821AE is not set +# CONFIG_RTS5139 is not set +# CONFIG_RTS5208 is not set +# CONFIG_TRANZPORT is not set +# CONFIG_IDE_PHISON is not set +# CONFIG_LINE6_USB is not set +# CONFIG_USB_SERIAL_QUATECH2 is not set +# CONFIG_VT6655 is not set +# CONFIG_VT6656 is not set +# CONFIG_DX_SEP is not set + +# +# IIO staging drivers +# + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_LIS3L02DQ is not set +# CONFIG_SCA3000 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7291 is not set +# CONFIG_AD7606 is not set +# CONFIG_AD799X is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7280 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Direct Digital Synthesis +# +# CONFIG_AD5930 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_AD9850 is not set +# CONFIG_AD9852 is not set +# CONFIG_AD9910 is not set +# CONFIG_AD9951 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set + +# +# Light sensors +# +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_ISL29028 is not set +# CONFIG_TSL2583 is not set +# CONFIG_TSL2x7x is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_HMC5843 is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set +# CONFIG_IIO_SIMPLE_DUMMY is not set +# CONFIG_WLAGS49_H2 is not set +# CONFIG_WLAGS49_H25 is not set +# CONFIG_FB_SM7XX is not set +CONFIG_CRYSTALHD=m +# CONFIG_FB_XGI is not set +# CONFIG_USB_ENESTORAGE is not set +# CONFIG_BCM_WIMAX is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +CONFIG_STAGING_MEDIA=y +# CONFIG_DVB_AS102 is not set +# CONFIG_DVB_CXD2099 is not set +# CONFIG_VIDEO_DT3155 is not set +# CONFIG_VIDEO_GO7007 is not set +# CONFIG_USB_MSI3101 is not set +# CONFIG_VIDEO_TCM825X is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_SOLO6X10 is not set +CONFIG_LIRC_STAGING=y +CONFIG_LIRC_BT829=m +CONFIG_LIRC_IGORPLUGUSB=m +CONFIG_LIRC_IMON=m +CONFIG_LIRC_PARALLEL=m +CONFIG_LIRC_GPIO=m +CONFIG_LIRC_SASEM=m +CONFIG_LIRC_SERIAL=m +CONFIG_LIRC_SERIAL_TRANSMITTER=y +CONFIG_LIRC_SIR=m +CONFIG_LIRC_ZILOG=m + +# +# Android +# +# CONFIG_ANDROID is not set +# CONFIG_USB_WPAN_HCD is not set +# CONFIG_WIMAX_GDM72XX is not set +# CONFIG_LTE_GDM724X is not set +# CONFIG_NET_VENDOR_SILICOM is not set +# CONFIG_CED1401 is not set +# CONFIG_DRM_IMX is not set +# CONFIG_DGRP is not set +# CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_LUSTRE_FS is not set +# CONFIG_XILLYBUS is not set +# CONFIG_DGNC is not set +# CONFIG_DGAP is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_QCOM is not set + +# +# Hardware Spinlock drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_MMIO=y +# CONFIG_MAILBOX is not set +# CONFIG_IOMMU_SUPPORT is not set + +# +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +CONFIG_IIO=m +CONFIG_IIO_BUFFER=y +CONFIG_IIO_BUFFER_CB=y +CONFIG_IIO_KFIFO_BUF=m +CONFIG_IIO_TRIGGERED_BUFFER=m +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 + +# +# Accelerometers +# +# CONFIG_BMA180 is not set +CONFIG_HID_SENSOR_ACCEL_3D=m +CONFIG_IIO_ST_ACCEL_3AXIS=m +CONFIG_IIO_ST_ACCEL_I2C_3AXIS=m +CONFIG_IIO_ST_ACCEL_SPI_3AXIS=m +# CONFIG_KXSD9 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7266 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_EXYNOS_ADC is not set +# CONFIG_MAX1363 is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3422 is not set +# CONFIG_NAU7802 is not set +# CONFIG_TI_ADC081C is not set +# CONFIG_VIPERBOARD_ADC is not set + +# +# Amplifiers +# +# CONFIG_AD8366 is not set + +# +# Hid Sensor IIO Common +# +CONFIG_HID_SENSOR_IIO_COMMON=m +CONFIG_HID_SENSOR_IIO_TRIGGER=m +CONFIG_IIO_ST_SENSORS_I2C=m +CONFIG_IIO_ST_SENSORS_SPI=m +CONFIG_IIO_ST_SENSORS_CORE=m + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5686 is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD7303 is not set +# CONFIG_MAX517 is not set +# CONFIG_MCP4725 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +# CONFIG_AD9523 is not set + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +# CONFIG_ADF4350 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set +CONFIG_HID_SENSOR_GYRO_3D=m +CONFIG_IIO_ST_GYRO_3AXIS=m +CONFIG_IIO_ST_GYRO_I2C_3AXIS=m +CONFIG_IIO_ST_GYRO_SPI_3AXIS=m +# CONFIG_ITG3200 is not set + +# +# Humidity sensors +# +# CONFIG_DHT11 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_INV_MPU6050_IIO is not set + +# +# Light sensors +# +# CONFIG_ADJD_S311 is not set +# CONFIG_APDS9300 is not set +# CONFIG_CM32181 is not set +# CONFIG_CM36651 is not set +# CONFIG_GP2AP020A00F is not set +CONFIG_HID_SENSOR_ALS=m +# CONFIG_TCS3472 is not set +# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_TSL4531 is not set +# CONFIG_VCNL4000 is not set + +# +# Magnetometer sensors +# +# CONFIG_AK8975 is not set +# CONFIG_MAG3110 is not set +CONFIG_HID_SENSOR_MAGNETOMETER_3D=m +CONFIG_IIO_ST_MAGN_3AXIS=m +CONFIG_IIO_ST_MAGN_I2C_3AXIS=m +CONFIG_IIO_ST_MAGN_SPI_3AXIS=m + +# +# Inclinometer sensors +# +CONFIG_HID_SENSOR_INCLINOMETER_3D=m + +# +# Triggers - standalone +# +CONFIG_IIO_INTERRUPT_TRIGGER=m +# CONFIG_IIO_SYSFS_TRIGGER is not set + +# +# Pressure sensors +# +# CONFIG_MPL3115 is not set +# CONFIG_IIO_ST_PRESS is not set + +# +# Temperature sensors +# +# CONFIG_TMP006 is not set +# CONFIG_VME_BUS is not set +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +CONFIG_PWM_IMX=y +# CONFIG_PWM_PCA9685 is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +# CONFIG_IPACK_BUS is not set +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RESET_GPIO=y +CONFIG_FMC=m +CONFIG_FMC_FAKEDEV=m +CONFIG_FMC_TRIVIAL=m +CONFIG_FMC_WRITE_EEPROM=m +CONFIG_FMC_CHARDEV=m + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set +# CONFIG_PHY_EXYNOS_DP_VIDEO is not set +# CONFIG_BCM_KONA_USB2_PHY is not set +# CONFIG_POWERCAP is not set + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT23=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set +# CONFIG_XFS_DEBUG is not set +CONFIG_GFS2_FS=m +CONFIG_GFS2_FS_LOCKING_DLM=y +CONFIG_OCFS2_FS=m +CONFIG_OCFS2_FS_O2CB=m +CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +CONFIG_OCFS2_FS_STATS=y +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +# CONFIG_OCFS2_DEBUG_FS is not set +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set +# CONFIG_BTRFS_ASSERT is not set +CONFIG_NILFS2_FS=m +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_FANOTIFY=y +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set +# CONFIG_QUOTA_DEBUG is not set +CONFIG_QUOTA_TREE=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=y +CONFIG_CUSE=m + +# +# Caches +# +CONFIG_FSCACHE=m +CONFIG_FSCACHE_STATS=y +# CONFIG_FSCACHE_HISTOGRAM is not set +# CONFIG_FSCACHE_DEBUG is not set +CONFIG_FSCACHE_OBJECT_LIST=y +CONFIG_CACHEFILES=m +# CONFIG_CACHEFILES_DEBUG is not set +# CONFIG_CACHEFILES_HISTOGRAM is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=y +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_ECRYPT_FS=m +# CONFIG_ECRYPT_FS_MESSAGING is not set +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +# CONFIG_HFSPLUS_FS_POSIX_ACL is not set +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +CONFIG_SQUASHFS_FILE_CACHE=y +# CONFIG_SQUASHFS_FILE_DIRECT is not set +CONFIG_SQUASHFS_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_DECOMP_MULTI is not set +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +CONFIG_MINIX_FS=m +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +CONFIG_ROMFS_FS=m +CONFIG_ROMFS_BACKED_BY_BLOCK=y +CONFIG_ROMFS_ON_BLOCK=y +CONFIG_PSTORE=y +# CONFIG_PSTORE_CONSOLE is not set +CONFIG_PSTORE_RAM=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set +# CONFIG_EXOFS_FS is not set +# CONFIG_F2FS_FS is not set +CONFIG_ORE=m +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +# CONFIG_NFS_V2 is not set +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_SWAP=y +CONFIG_NFS_V4_1=y +CONFIG_NFS_V4_2=y +CONFIG_PNFS_FILE_LAYOUT=y +CONFIG_PNFS_BLOCK=y +CONFIG_PNFS_OBJLAYOUT=m +CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" +# CONFIG_NFS_V4_1_MIGRATION is not set +CONFIG_NFS_V4_SECURITY_LABEL=y +CONFIG_ROOT_NFS=y +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +CONFIG_NFS_DEBUG=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_V4_SECURITY_LABEL=y +# CONFIG_NFSD_FAULT_INJECTION is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_SUNRPC_BACKCHANNEL=y +CONFIG_SUNRPC_XPRT_RDMA=m +CONFIG_SUNRPC_SWAP=y +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_SUNRPC_DEBUG=y +CONFIG_CEPH_FS=m +CONFIG_CEPH_FSCACHE=y +CONFIG_CEPH_FS_POSIX_ACL=y +CONFIG_CIFS=m +CONFIG_CIFS_STATS=y +# CONFIG_CIFS_STATS2 is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_CIFS_ACL=y +CONFIG_CIFS_DEBUG=y +# CONFIG_CIFS_DEBUG2 is not set +CONFIG_CIFS_DFS_UPCALL=y +CONFIG_CIFS_SMB2=y +CONFIG_CIFS_FSCACHE=y +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m +CONFIG_9P_FSCACHE=y +CONFIG_9P_FS_POSIX_ACL=y +CONFIG_9P_FS_SECURITY=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_MAC_ROMAN=m +CONFIG_NLS_MAC_CELTIC=m +CONFIG_NLS_MAC_CENTEURO=m +CONFIG_NLS_MAC_CROATIAN=m +CONFIG_NLS_MAC_CYRILLIC=m +CONFIG_NLS_MAC_GAELIC=m +CONFIG_NLS_MAC_GREEK=m +CONFIG_NLS_MAC_ICELAND=m +CONFIG_NLS_MAC_INUIT=m +CONFIG_NLS_MAC_ROMANIAN=m +CONFIG_NLS_MAC_TURKISH=m +CONFIG_NLS_UTF8=y +CONFIG_DLM=m +CONFIG_DLM_DEBUG=y + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_BOOT_PRINTK_DELAY=y +# CONFIG_DYNAMIC_DEBUG is not set + +# +# Compile-time checks and compiler options +# +# CONFIG_DEBUG_INFO is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_STRIP_ASM_SYMS=y +# CONFIG_READABLE_ASM is not set +CONFIG_UNUSED_SYMBOLS=y +CONFIG_DEBUG_FS=y +CONFIG_HEADERS_CHECK=y +# CONFIG_DEBUG_SECTION_MISMATCH is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x0 +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +CONFIG_LOCKUP_DETECTOR=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +CONFIG_TIMER_STATS=y + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set + +# +# RCU Debugging +# +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_CPU_STALL_INFO is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACE_CLOCK=y +CONFIG_RING_BUFFER=y +CONFIG_RING_BUFFER_ALLOW_SWAP=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set + +# +# Runtime Testing +# +# CONFIG_LKDTM is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_KPROBES_SANITY_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +CONFIG_ATOMIC64_SELFTEST=y +CONFIG_ASYNC_RAID6_TEST=m +# CONFIG_TEST_STRING_HELPERS is not set +CONFIG_TEST_KSTRTOX=y +CONFIG_BUILD_DOCSRC=y +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_TEST_MODULE is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARM_PTDUMP is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_LL is not set +CONFIG_DEBUG_IMX_UART_PORT=1 +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +# CONFIG_DEBUG_UART_PL01X is not set +# CONFIG_DEBUG_UART_8250 is not set +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +# CONFIG_ARM_KPROBES_TEST is not set +# CONFIG_PID_IN_CONTEXTIDR is not set +CONFIG_DEBUG_SET_MODULE_RONX=y + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_PERSISTENT_KEYRINGS=y +CONFIG_BIG_KEYS=y +CONFIG_TRUSTED_KEYS=m +CONFIG_ENCRYPTED_KEYS=m +CONFIG_KEYS_DEBUG_PROC_KEYS=y +# CONFIG_SECURITY_DMESG_RESTRICT is not set +CONFIG_SECURITY=y +CONFIG_SECURITYFS=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_NETWORK_XFRM=y +# CONFIG_SECURITY_PATH is not set +# CONFIG_SECURITY_SELINUX is not set +# CONFIG_SECURITY_SMACK is not set +# CONFIG_SECURITY_TOMOYO is not set +# CONFIG_SECURITY_APPARMOR is not set +# CONFIG_SECURITY_YAMA is not set +# CONFIG_IMA is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_XOR_BLOCKS=m +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_ASYNC_PQ=m +CONFIG_ASYNC_RAID6_RECOV=m +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=m +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_USER=y +# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_PCRYPT=m +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_TEST=m +CONFIG_CRYPTO_ABLK_HELPER=y + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_SEQIV=y + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_CTS=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_LRW=y +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_XTS=y + +# +# Hash modes +# +CONFIG_CRYPTO_CMAC=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_VMAC=m + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRC32=m +CONFIG_CRYPTO_CRCT10DIF=y +CONFIG_CRYPTO_GHASH=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=y +CONFIG_CRYPTO_RMD128=y +CONFIG_CRYPTO_RMD160=y +CONFIG_CRYPTO_RMD256=y +CONFIG_CRYPTO_RMD320=y +CONFIG_CRYPTO_SHA1=y +# CONFIG_CRYPTO_SHA1_ARM is not set +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_TGR192=y +CONFIG_CRYPTO_WP512=y + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_AES_ARM_BS=y +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_BLOWFISH_COMMON=y +CONFIG_CRYPTO_CAMELLIA=y +CONFIG_CRYPTO_CAST_COMMON=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SALSA20=m +CONFIG_CRYPTO_SEED=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_ZLIB=m +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_LZ4=m +CONFIG_CRYPTO_LZ4HC=m + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_USER_API=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_DEV_HIFN_795X=m +CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y +# CONFIG_CRYPTO_DEV_SAHARA is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_RAID6_PQ=m +CONFIG_BITREVERSE=y +CONFIG_RATIONAL=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_STMP_DEVICE=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_CRC_CCITT=m +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=m +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +CONFIG_CRC7=m +CONFIG_LIBCRC32C=m +CONFIG_CRC8=m +CONFIG_AUDIT_GENERIC=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_COMPRESS=m +CONFIG_LZ4HC_COMPRESS=m +CONFIG_LZ4_DECOMPRESS=m +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +# CONFIG_XZ_DEC_IA64 is not set +CONFIG_XZ_DEC_ARM=y +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_SPARC is not set +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CHECK_SIGNATURE=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_LRU_CACHE=m +CONFIG_AVERAGE=y +CONFIG_CORDIC=m +# CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y +CONFIG_FONT_SUPPORT=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +# CONFIG_VIRTUALIZATION is not set diff --git a/config/linux-sunxi-a80.config b/config/linux-guitar.config similarity index 64% rename from config/linux-sunxi-a80.config rename to config/linux-guitar.config index 6b19695a6..f77b0cdda 100644 --- a/config/linux-sunxi-a80.config +++ b/config/linux-guitar.config @@ -1,41 +1,30 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 3.4.39 Kernel Configuration +# Linux/arm 3.10.37 Kernel Configuration # CONFIG_ARM=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARM_HAS_SG_CHAIN=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_GENERIC_GPIO=y -# CONFIG_ARCH_USES_GETTIMEOFFSET is not set -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_KTIME_SCALAR=y CONFIG_HAVE_PROC_CPU=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y CONFIG_TRACE_IRQFLAGS_SUPPORT=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_GENERIC_LOCKBREAK=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_ARCH_HAS_CPUFREQ=y -CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_NEED_DMA_MAP_STATE=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_ARM_PATCH_PHYS_VIRT=y -CONFIG_NEED_MACH_IO_H=y -CONFIG_NEED_MACH_MEMORY_H=y CONFIG_GENERIC_BUG=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -CONFIG_HAVE_IRQ_WORK=y CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y # # General setup # -CONFIG_EXPERIMENTAL=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" CONFIG_LOCALVERSION="" @@ -48,19 +37,12 @@ CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_LZMA is not set # CONFIG_KERNEL_XZ is not set # CONFIG_KERNEL_LZO is not set -CONFIG_DEFAULT_HOSTNAME="SUNXI_MACHINE" +CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -# CONFIG_FHANDLE is not set -CONFIG_TASKSTATS=y -CONFIG_TASK_DELAY_ACCT=y -CONFIG_TASK_XACCT=y -CONFIG_TASK_IO_ACCOUNTING=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_FHANDLE=y CONFIG_AUDIT=y CONFIG_AUDITSYSCALL=y CONFIG_AUDIT_WATCH=y @@ -72,64 +54,93 @@ CONFIG_HAVE_GENERIC_HARDIRQS=y # IRQ subsystem # CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_HARDIRQS_SW_RESEND=y CONFIG_IRQ_DOMAIN=y # CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_KTIME_SCALAR=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_IRQ_TIME_ACCOUNTING is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set # # RCU Subsystem # CONFIG_TREE_PREEMPT_RCU=y CONFIG_PREEMPT_RCU=y +CONFIG_RCU_STALL_COMMON=y +# CONFIG_RCU_USER_QS is not set CONFIG_RCU_FANOUT=32 +CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_RCU_FANOUT_EXACT is not set # CONFIG_RCU_FAST_NO_HZ is not set # CONFIG_TREE_RCU_TRACE is not set # CONFIG_RCU_BOOST is not set +# CONFIG_RCU_NOCB_CPU is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=16 +CONFIG_LOG_BUF_SHIFT=17 CONFIG_CGROUPS=y CONFIG_CGROUP_DEBUG=y CONFIG_CGROUP_FREEZER=y -CONFIG_CGROUP_DEVICE=y -CONFIG_CPUSETS=y -CONFIG_PROC_PID_CPUSET=y +# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CPUSETS is not set CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y -CONFIG_CGROUP_MEM_RES_CTLR=y -CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y -# CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED is not set -CONFIG_CGROUP_MEM_RES_CTLR_KMEM=y -CONFIG_CGROUP_PERF=y +CONFIG_MEMCG=y +# CONFIG_MEMCG_SWAP is not set +# CONFIG_MEMCG_KMEM is not set +# CONFIG_CGROUP_PERF is not set CONFIG_CGROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y # CONFIG_CFS_BANDWIDTH is not set CONFIG_RT_GROUP_SCHED=y -CONFIG_BLK_CGROUP=y -# CONFIG_DEBUG_BLK_CGROUP is not set +# CONFIG_BLK_CGROUP is not set # CONFIG_CHECKPOINT_RESTORE is not set CONFIG_NAMESPACES=y CONFIG_UTS_NS=y CONFIG_IPC_NS=y -CONFIG_USER_NS=y +# CONFIG_USER_NS is not set CONFIG_PID_NS=y CONFIG_NET_NS=y +CONFIG_UIDGID_CONVERTED=y +# CONFIG_UIDGID_STRICT_TYPE_CHECKS is not set # CONFIG_SCHED_AUTOGROUP is not set CONFIG_MM_OWNER=y # CONFIG_SYSFS_DEPRECATED is not set CONFIG_RELAY=y # CONFIG_BLK_DEV_INITRD is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_HOTPLUG=y CONFIG_PANIC_TIMEOUT=0 CONFIG_EXPERT=y CONFIG_UID16=y -CONFIG_SYSCTL_SYSCALL=y +# CONFIG_SYSCTL_SYSCALL is not set CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y @@ -149,27 +160,42 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -# CONFIG_PERF_COUNTERS is not set -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_DEBUG_PERF_USE_VMALLOC=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y CONFIG_COMPAT_BRK=y -CONFIG_SLAB=y -# CONFIG_SLUB is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y # CONFIG_SLOB is not set -CONFIG_PROFILING=y +# CONFIG_PROFILING is not set CONFIG_TRACEPOINTS=y -# CONFIG_OPROFILE is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set -CONFIG_JUMP_LABEL=y +# CONFIG_JUMP_LABEL is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y CONFIG_HAVE_HW_BREAKPOINT=y CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP_FILTER=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OLD_SIGACTION=y # # GCOV-based kernel profiling @@ -182,38 +208,23 @@ CONFIG_BASE_SMALL=0 CONFIG_MODULES=y CONFIG_MODULE_FORCE_LOAD=y CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MODVERSIONS=y -CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_MODULE_SIG is not set CONFIG_STOP_MACHINE=y CONFIG_BLOCK=y CONFIG_LBDAF=y -# CONFIG_BLK_DEV_BSG is not set +CONFIG_BLK_DEV_BSG=y # CONFIG_BLK_DEV_BSGLIB is not set # CONFIG_BLK_DEV_INTEGRITY is not set -# CONFIG_BLK_DEV_THROTTLING is not set # # Partition Types # -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set +# CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_KARMA_PARTITION is not set CONFIG_EFI_PARTITION=y -# CONFIG_SYSV68_PARTITION is not set # # IO Schedulers @@ -221,82 +232,40 @@ CONFIG_EFI_PARTITION=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y -# CONFIG_CFQ_GROUP_IOSCHED is not set # CONFIG_DEFAULT_DEADLINE is not set CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" -# CONFIG_INLINE_SPIN_TRYLOCK is not set -# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK is not set -# CONFIG_INLINE_SPIN_LOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK_IRQ is not set -# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set CONFIG_UNINLINE_SPIN_UNLOCK=y -# CONFIG_INLINE_SPIN_UNLOCK_BH is not set -# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set -# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_READ_TRYLOCK is not set -# CONFIG_INLINE_READ_LOCK is not set -# CONFIG_INLINE_READ_LOCK_BH is not set -# CONFIG_INLINE_READ_LOCK_IRQ is not set -# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set -# CONFIG_INLINE_READ_UNLOCK is not set -# CONFIG_INLINE_READ_UNLOCK_BH is not set -# CONFIG_INLINE_READ_UNLOCK_IRQ is not set -# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_WRITE_TRYLOCK is not set -# CONFIG_INLINE_WRITE_LOCK is not set -# CONFIG_INLINE_WRITE_LOCK_BH is not set -# CONFIG_INLINE_WRITE_LOCK_IRQ is not set -# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set -# CONFIG_INLINE_WRITE_UNLOCK is not set -# CONFIG_INLINE_WRITE_UNLOCK_BH is not set -# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set -# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set -# CONFIG_MUTEX_SPIN_ON_OWNER is not set CONFIG_FREEZER=y # # System Type # CONFIG_MMU=y +# CONFIG_ARCH_MULTIPLATFORM is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_VEXPRESS is not set -CONFIG_ARCH_SUNXI=y # CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_BCMRING is not set -# CONFIG_ARCH_HIGHBANK is not set # CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CNS3XXX is not set # CONFIG_ARCH_GEMINI is not set -# CONFIG_ARCH_PRIMA2 is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_MXC is not set -# CONFIG_ARCH_MXS is not set # CONFIG_ARCH_NETX is not set -# CONFIG_ARCH_H720X is not set # CONFIG_ARCH_IOP13XX is not set # CONFIG_ARCH_IOP32X is not set # CONFIG_ARCH_IOP33X is not set -# CONFIG_ARCH_IXP23XX is not set -# CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_DOVE is not set # CONFIG_ARCH_KIRKWOOD is not set -# CONFIG_ARCH_LPC32XX is not set # CONFIG_ARCH_MV78XX0 is not set # CONFIG_ARCH_ORION5X is not set # CONFIG_ARCH_MMP is not set # CONFIG_ARCH_KS8695 is not set # CONFIG_ARCH_W90X900 is not set -# CONFIG_ARCH_TEGRA is not set -# CONFIG_ARCH_PICOXCELL is not set -# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_LPC32XX is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_MSM is not set # CONFIG_ARCH_SHMOBILE is not set @@ -310,43 +279,36 @@ CONFIG_ARCH_SUNXI=y # CONFIG_ARCH_EXYNOS is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_U300 is not set -# CONFIG_ARCH_U8500 is not set -# CONFIG_ARCH_NOMADIK is not set # CONFIG_ARCH_DAVINCI is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_PLAT_SPEAR is not set -# CONFIG_ARCH_VT8500 is not set -# CONFIG_ARCH_ZYNQ is not set +# CONFIG_ARCH_OMAP1 is not set +CONFIG_ARCH_OWL=y # CONFIG_GPIO_PCA953X is not set # CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_PLAT_SPEAR is not set # -# System MMU -# -CONFIG_SUNXI_CONSISTENT_DMA_SIZE=12 -# CONFIG_ARCH_SUN8I is not set -CONFIG_ARCH_SUN9I=y -CONFIG_ARCH_SUN9IW1=y -CONFIG_SUN9I_CCI=y -CONFIG_DRAMFREQ_RESERVE_MEM=y -CONFIG_SW_POWERNOW=y -CONFIG_ARCH_SUN9IW1P1=y -# CONFIG_FPGA_V4_PLATFORM is not set -# CONFIG_FPGA_V7_PLATFORM is not set -CONFIG_EVB_PLATFORM=y -# CONFIG_SUN9IW1_PERF5_BOARD is not set - -# -# Power management -# - -# -# Common Features Selection -# - -# -# Boot Options +# Owl configurations # +CONFIG_MACH_OWL=y +# CONFIG_OWL_DEBUG_IRQ_STACK is not set +CONFIG_SERIAL_OWL=y +CONFIG_SERIAL_OWL_CONSOLE=y +# CONFIG_OWL_CONSOLE_KEEP_ON is not set +CONFIG_GPIO_OWL=y +CONFIG_GPU_RESERVED_SIZE=64 +CONFIG_ION_RESERVED_SIZE=96 +CONFIG_FB_RESERVED_SIZE=32 +CONFIG_I2C_OWL=y +CONFIG_I2C_OWL_BUS0=y +CONFIG_I2C_OWL_BUS1=y +# CONFIG_I2C_OWL_BUS2 is not set +# CONFIG_I2C_OWL_BUS3 is not set +CONFIG_PINCTRL_OWL=y +CONFIG_ACTIONS_SOC_CAMERA=y +# CONFIG_FB_ACTIONS is not set +# CONFIG_BACKLIGHT_ACTIONS is not set +CONFIG_CPUFREQ_ACTIONS=y +CONFIG_OWL_CLOSE_PATCH=y # # Processor Type @@ -371,120 +333,124 @@ CONFIG_CPU_CP15_MMU=y # CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set CONFIG_ARM_THUMB=y CONFIG_ARM_THUMBEE=y -CONFIG_SWP_EMULATE=y +CONFIG_ARM_VIRT_EXT=y +# CONFIG_SWP_EMULATE is not set # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_KUSER_HELPERS=y +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y CONFIG_MIGHT_HAVE_CACHE_L2X0=y -# CONFIG_CACHE_L2X0 is not set +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y CONFIG_ARM_L1_CACHE_SHIFT_6=y CONFIG_ARM_L1_CACHE_SHIFT=6 CONFIG_ARM_DMA_MEM_BUFFERABLE=y CONFIG_ARM_NR_BANKS=8 -CONFIG_CPU_HAS_PMU=y CONFIG_MULTI_IRQ_HANDLER=y -CONFIG_ARM_ERRATA_430973=y -CONFIG_ARM_ERRATA_458693=y -CONFIG_ARM_ERRATA_460075=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set # CONFIG_ARM_ERRATA_742230 is not set # CONFIG_ARM_ERRATA_742231 is not set -CONFIG_ARM_ERRATA_720789=y -CONFIG_ARM_ERRATA_743622=y -CONFIG_ARM_ERRATA_751472=y +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_ARM_ERRATA_643719 is not set +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_PL310_ERRATA_753970 is not set CONFIG_ARM_ERRATA_754322=y # CONFIG_ARM_ERRATA_754327 is not set -# CONFIG_ARM_ERRATA_764369 is not set -CONFIG_ARM_ERRATA_775420=y -CONFIG_ARM_GIC=y +CONFIG_ARM_ERRATA_764369=y +# CONFIG_PL310_ERRATA_769419 is not set +# CONFIG_ARM_ERRATA_775420 is not set +# CONFIG_ARM_ERRATA_798181 is not set # CONFIG_FIQ_DEBUGGER is not set # # Bus support # # CONFIG_PCI_SYSCALL is not set -# CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCCARD is not set # # Kernel Features # -CONFIG_TICK_ONESHOT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_HAVE_SMP=y CONFIG_SMP=y CONFIG_SMP_ON_UP=y CONFIG_ARM_CPU_TOPOLOGY=y CONFIG_SCHED_MC=y # CONFIG_SCHED_SMT is not set -CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE=y -CONFIG_SCHED_HMP=y -# CONFIG_SCHED_HMP_PRIO_FILTER is not set -CONFIG_HMP_FAST_CPU_MASK="4-7" -CONFIG_HMP_SLOW_CPU_MASK="0-3" -CONFIG_HMP_VARIABLE_SCALE=y -CONFIG_HMP_FREQUENCY_INVARIANT_SCALE=y -CONFIG_SCHED_HMP_LITTLE_PACKING=y +# CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE is not set CONFIG_HAVE_ARM_SCU=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_MCPM=y -CONFIG_BIG_LITTLE=y -# CONFIG_BL_SWITCHER is not set +# CONFIG_HAVE_ARM_ARCH_TIMER is not set +CONFIG_HAVE_ARM_TWD=y +# CONFIG_MCPM is not set +# CONFIG_BIG_LITTLE is not set CONFIG_VMSPLIT_3G=y # CONFIG_VMSPLIT_2G is not set # CONFIG_VMSPLIT_1G is not set CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_NR_CPUS=8 +CONFIG_NR_CPUS=4 CONFIG_HOTPLUG_CPU=y -CONFIG_ARCH_NR_GPIO=2048 +# CONFIG_ARM_PSCI is not set +CONFIG_LOCAL_TIMERS=y +CONFIG_ARCH_NR_GPIO=0 # CONFIG_PREEMPT_NONE is not set # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_PREEMPT_COUNT=y CONFIG_HZ=100 +CONFIG_SCHED_HRTICK=y # CONFIG_THUMB2_KERNEL is not set CONFIG_AEABI=y -CONFIG_OABI_COMPAT=y +# CONFIG_OABI_COMPAT is not set # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set CONFIG_HAVE_ARCH_PFN_VALID=y CONFIG_HIGHMEM=y -CONFIG_HIGHPTE=y +# CONFIG_HIGHPTE is not set CONFIG_HW_PERF_EVENTS=y -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_HAVE_MEMBLOCK=y +CONFIG_MEMORY_ISOLATION=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_SPLIT_PTLOCK_CPUS=999999 -# CONFIG_COMPACTION is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_BOUNCE=y +# CONFIG_BOUNCE is not set CONFIG_VIRT_TO_BUS=y -# CONFIG_KSM is not set -CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 +CONFIG_KSM=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_CROSS_MEMORY_ATTACH=y # CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_ALIGNMENT_TRAP=y # CONFIG_UACCESS_WITH_MEMCPY is not set -# CONFIG_SECCOMP is not set +CONFIG_SECCOMP=y # CONFIG_CC_STACKPROTECTOR is not set -# CONFIG_DEPRECATED_PARAM_STRUCT is not set -CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART=y +# CONFIG_XEN is not set +# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set # # Boot options # -# CONFIG_USE_OF is not set +CONFIG_USE_OF=y +CONFIG_ATAGS=y +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +# CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE is not set CONFIG_ZBOOT_ROM_TEXT=0 CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_CMDLINE="earlyprintk=ttyS0,115200 loglevel=8 initcall_debug=1 console=ttyS0,115200 init=/init" -CONFIG_CMDLINE_FROM_BOOTLOADER=y -# CONFIG_CMDLINE_EXTEND is not set -# CONFIG_CMDLINE_FORCE is not set +# CONFIG_ARM_APPENDED_DTB is not set +CONFIG_CMDLINE="" # CONFIG_XIP_KERNEL is not set # CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set @@ -501,37 +467,34 @@ CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_FREQ_GOV_COMMON=y CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_STAT_DETAILS=y -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_FANTASYS is not set CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_INTERACTIVE=y -CONFIG_CPU_FREQ_GOV_AUTO_HOTPLUG=y -CONFIG_CPU_GOV_AUTO_HOTPLUG_WITHOUT_POLICY=y -CONFIG_CPU_FREQ_GOV_AUTO_HOTPLUG_ROOMAGE=y -# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -CONFIG_CPU_FREQ_INPUT_EVNT_NOTIFY=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +# CONFIG_GENERIC_CPUFREQ_CPU0 is not set # # ARM CPU frequency scaling drivers # -CONFIG_ARM_SUNXI_IKS_CPUFREQ=y # CONFIG_ARM_EXYNOS4210_CPUFREQ is not set # CONFIG_ARM_EXYNOS4X12_CPUFREQ is not set # CONFIG_ARM_EXYNOS5250_CPUFREQ is not set - -# -# CPU Idle -# -# CONFIG_CPU_IDLE is not set +# CONFIG_ARM_EXYNOS5440_CPUFREQ is not set +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set +CONFIG_ARM_OWL_CPUFREQ=y +CONFIG_CPU_IDLE=y +# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y # CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set # @@ -541,8 +504,6 @@ CONFIG_ARM_SUNXI_IKS_CPUFREQ=y # # At least one emulation must be selected # -# CONFIG_FPE_NWFPE is not set -# CONFIG_FPE_FASTFPE is not set CONFIG_VFP=y CONFIG_VFPv3=y CONFIG_NEON=y @@ -552,10 +513,11 @@ CONFIG_NEON=y # CONFIG_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y -CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y -CONFIG_HAVE_AOUT=y -CONFIG_BINFMT_AOUT=y -CONFIG_BINFMT_MISC=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_COREDUMP=y # # Power management options @@ -563,29 +525,30 @@ CONFIG_BINFMT_MISC=y CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y CONFIG_HAS_WAKELOCK=y -CONFIG_HAS_EARLYSUSPEND=y CONFIG_WAKELOCK=y -CONFIG_WAKELOCK_STAT=y -CONFIG_USER_WAKELOCK=y -CONFIG_SCENELOCK=y -CONFIG_USER_SCENELOCK=y +CONFIG_HAS_EARLYSUSPEND=y CONFIG_EARLYSUSPEND=y -CONFIG_EARLYSUSPEND_DELAY=y -# CONFIG_NO_USER_SPACE_SCREEN_ACCESS_CONTROL is not set -# CONFIG_CONSOLE_EARLYSUSPEND is not set CONFIG_FB_EARLYSUSPEND=y +CONFIG_HIBERNATE_CALLBACKS=y +CONFIG_HIBERNATION=y +CONFIG_PM_STD_PARTITION="" CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y -# CONFIG_PM_AUTOSLEEP is not set -# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set CONFIG_PM_RUNTIME=y CONFIG_PM=y CONFIG_PM_DEBUG=y -CONFIG_PM_ADVANCED_DEBUG=y +# CONFIG_PM_ADVANCED_DEBUG is not set # CONFIG_PM_TEST_SUSPEND is not set -CONFIG_CAN_PM_TRACE=y -CONFIG_APM_EMULATION=y +CONFIG_PM_SLEEP_DEBUG=y +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_HAS_OPP=y +CONFIG_PM_OPP=y CONFIG_PM_CLK=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set CONFIG_CPU_PM=y CONFIG_SUSPEND_TIME=y CONFIG_ARCH_SUSPEND_POSSIBLE=y @@ -596,73 +559,53 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set CONFIG_UNIX=y -CONFIG_UNIX_DIAG=y +# CONFIG_UNIX_DIAG is not set CONFIG_XFRM=y +CONFIG_XFRM_ALGO=y CONFIG_XFRM_USER=y -CONFIG_XFRM_SUB_POLICY=y +# CONFIG_XFRM_SUB_POLICY is not set CONFIG_XFRM_MIGRATE=y -CONFIG_XFRM_STATISTICS=y +# CONFIG_XFRM_STATISTICS is not set CONFIG_XFRM_IPCOMP=y CONFIG_NET_KEY=y CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_FIB_TRIE_STATS=y +# CONFIG_IP_FIB_TRIE_STATS is not set CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_VERBOSE is not set CONFIG_IP_ROUTE_CLASSID=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y CONFIG_IP_PNP_RARP=y -CONFIG_NET_IPIP=y -CONFIG_NET_IPGRE_DEMUX=y -CONFIG_NET_IPGRE=y -CONFIG_NET_IPGRE_BROADCAST=y -CONFIG_IP_MROUTE=y -CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -CONFIG_IP_PIMSM_V1=y -CONFIG_IP_PIMSM_V2=y -CONFIG_ARPD=y -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -CONFIG_INET_XFRM_TUNNEL=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=y +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_NET_IPVTI is not set +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m CONFIG_INET_TUNNEL=y -CONFIG_INET_XFRM_MODE_TRANSPORT=y -CONFIG_INET_XFRM_MODE_TUNNEL=y -CONFIG_INET_XFRM_MODE_BEET=y -CONFIG_INET_LRO=y +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +# CONFIG_INET_LRO is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y -CONFIG_INET_UDP_DIAG=y -CONFIG_TCP_CONG_ADVANCED=y -CONFIG_TCP_CONG_BIC=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y -CONFIG_TCP_CONG_WESTWOOD=y -CONFIG_TCP_CONG_HTCP=y -CONFIG_TCP_CONG_HSTCP=y -CONFIG_TCP_CONG_HYBLA=y -CONFIG_TCP_CONG_VEGAS=y -CONFIG_TCP_CONG_SCALABLE=y -CONFIG_TCP_CONG_LP=y -CONFIG_TCP_CONG_VENO=y -CONFIG_TCP_CONG_YEAH=y -CONFIG_TCP_CONG_ILLINOIS=y -# CONFIG_DEFAULT_BIC is not set -CONFIG_DEFAULT_CUBIC=y -# CONFIG_DEFAULT_HTCP is not set -# CONFIG_DEFAULT_HYBLA is not set -# CONFIG_DEFAULT_VEGAS is not set -# CONFIG_DEFAULT_VENO is not set -# CONFIG_DEFAULT_WESTWOOD is not set -# CONFIG_DEFAULT_RENO is not set CONFIG_DEFAULT_TCP_CONG="cubic" -CONFIG_TCP_MD5SIG=y +# CONFIG_TCP_MD5SIG is not set CONFIG_IPV6=y CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y @@ -679,22 +622,22 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=y CONFIG_INET6_XFRM_MODE_BEET=y # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set CONFIG_IPV6_SIT=y -CONFIG_IPV6_SIT_6RD=y +# CONFIG_IPV6_SIT_6RD is not set CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=y +# CONFIG_IPV6_GRE is not set CONFIG_IPV6_MULTIPLE_TABLES=y -CONFIG_IPV6_SUBTREES=y -CONFIG_IPV6_MROUTE=y -CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -CONFIG_IPV6_PIMSM_V2=y -CONFIG_NETLABEL=y +# CONFIG_IPV6_SUBTREES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETLABEL is not set # CONFIG_ANDROID_PARANOID_NETWORK is not set CONFIG_NET_ACTIVITY_STATS=y CONFIG_NETWORK_SECMARK=y -CONFIG_NETWORK_PHY_TIMESTAMPING=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set CONFIG_NETFILTER=y -CONFIG_NETFILTER_DEBUG=y +# CONFIG_NETFILTER_DEBUG is not set CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y # # Core Netfilter Configuration @@ -705,12 +648,13 @@ CONFIG_NETFILTER_NETLINK_QUEUE=y CONFIG_NETFILTER_NETLINK_LOG=y CONFIG_NF_CONNTRACK=y CONFIG_NF_CONNTRACK_MARK=y -CONFIG_NF_CONNTRACK_SECMARK=y +# CONFIG_NF_CONNTRACK_SECMARK is not set # CONFIG_NF_CONNTRACK_ZONES is not set CONFIG_NF_CONNTRACK_PROCFS=y CONFIG_NF_CONNTRACK_EVENTS=y -CONFIG_NF_CONNTRACK_TIMEOUT=y -CONFIG_NF_CONNTRACK_TIMESTAMP=y +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set +CONFIG_NF_CONNTRACK_LABELS=y CONFIG_NF_CT_PROTO_DCCP=y CONFIG_NF_CT_PROTO_GRE=y CONFIG_NF_CT_PROTO_SCTP=y @@ -721,13 +665,24 @@ CONFIG_NF_CONNTRACK_H323=y CONFIG_NF_CONNTRACK_IRC=y CONFIG_NF_CONNTRACK_BROADCAST=y CONFIG_NF_CONNTRACK_NETBIOS_NS=y -CONFIG_NF_CONNTRACK_SNMP=y +# CONFIG_NF_CONNTRACK_SNMP is not set CONFIG_NF_CONNTRACK_PPTP=y CONFIG_NF_CONNTRACK_SANE=y -CONFIG_NF_CONNTRACK_SIP=y +# CONFIG_NF_CONNTRACK_SIP is not set CONFIG_NF_CONNTRACK_TFTP=y CONFIG_NF_CT_NETLINK=y # CONFIG_NF_CT_NETLINK_TIMEOUT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE_CT is not set +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PROTO_DCCP=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +# CONFIG_NF_NAT_SIP is not set +CONFIG_NF_NAT_TFTP=m CONFIG_NETFILTER_TPROXY=y CONFIG_NETFILTER_XTABLES=y @@ -736,139 +691,90 @@ CONFIG_NETFILTER_XTABLES=y # CONFIG_NETFILTER_XT_MARK=y CONFIG_NETFILTER_XT_CONNMARK=y -# CONFIG_NETFILTER_XT_SET is not set # # Xtables targets # -CONFIG_NETFILTER_XT_TARGET_AUDIT=y +# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set # CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y CONFIG_NETFILTER_XT_TARGET_CONNMARK=y -CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y -CONFIG_NETFILTER_XT_TARGET_CT=y -CONFIG_NETFILTER_XT_TARGET_DSCP=y +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m CONFIG_NETFILTER_XT_TARGET_HL=y +CONFIG_NETFILTER_XT_TARGET_HMARK=m CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y -CONFIG_NETFILTER_XT_TARGET_LED=y -CONFIG_NETFILTER_XT_TARGET_LOG=y +# CONFIG_NETFILTER_XT_TARGET_LED is not set +CONFIG_NETFILTER_XT_TARGET_LOG=m CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NETMAP=m CONFIG_NETFILTER_XT_TARGET_NFLOG=y CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y -CONFIG_NETFILTER_XT_TARGET_NOTRACK=y -CONFIG_NETFILTER_XT_TARGET_RATEEST=y -CONFIG_NETFILTER_XT_TARGET_TEE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=y CONFIG_NETFILTER_XT_TARGET_TRACE=y -CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=m CONFIG_NETFILTER_XT_TARGET_TCPMSS=y -CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=y +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m # # Xtables matches # -CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y -CONFIG_NETFILTER_XT_MATCH_CLUSTER=y -CONFIG_NETFILTER_XT_MATCH_COMMENT=y -# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y CONFIG_NETFILTER_XT_MATCH_CONNMARK=y CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y -CONFIG_NETFILTER_XT_MATCH_CPU=y -CONFIG_NETFILTER_XT_MATCH_DCCP=y -CONFIG_NETFILTER_XT_MATCH_DEVGROUP=y -CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m CONFIG_NETFILTER_XT_MATCH_ECN=y -CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_ESP=m CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y CONFIG_NETFILTER_XT_MATCH_HELPER=y CONFIG_NETFILTER_XT_MATCH_HL=y CONFIG_NETFILTER_XT_MATCH_IPRANGE=y -# CONFIG_NETFILTER_XT_MATCH_IPVS is not set CONFIG_NETFILTER_XT_MATCH_LENGTH=y CONFIG_NETFILTER_XT_MATCH_LIMIT=y CONFIG_NETFILTER_XT_MATCH_MAC=y CONFIG_NETFILTER_XT_MATCH_MARK=y -CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y -CONFIG_NETFILTER_XT_MATCH_NFACCT=y -CONFIG_NETFILTER_XT_MATCH_OSF=y -CONFIG_NETFILTER_XT_MATCH_OWNER=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y CONFIG_NETFILTER_XT_MATCH_QUOTA=y CONFIG_NETFILTER_XT_MATCH_QUOTA2=y -CONFIG_NETFILTER_XT_MATCH_RATEEST=y -CONFIG_NETFILTER_XT_MATCH_REALM=y -CONFIG_NETFILTER_XT_MATCH_RECENT=y -CONFIG_NETFILTER_XT_MATCH_SCTP=y +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m CONFIG_NETFILTER_XT_MATCH_SOCKET=y CONFIG_NETFILTER_XT_MATCH_STATE=y CONFIG_NETFILTER_XT_MATCH_STATISTIC=y CONFIG_NETFILTER_XT_MATCH_STRING=y -CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m CONFIG_NETFILTER_XT_MATCH_TIME=y CONFIG_NETFILTER_XT_MATCH_U32=y -CONFIG_IP_SET=y -CONFIG_IP_SET_MAX=256 -# CONFIG_IP_SET_BITMAP_IP is not set -# CONFIG_IP_SET_BITMAP_IPMAC is not set -# CONFIG_IP_SET_BITMAP_PORT is not set -# CONFIG_IP_SET_HASH_IP is not set -# CONFIG_IP_SET_HASH_IPPORT is not set -# CONFIG_IP_SET_HASH_IPPORTIP is not set -# CONFIG_IP_SET_HASH_IPPORTNET is not set -# CONFIG_IP_SET_HASH_NET is not set -# CONFIG_IP_SET_HASH_NETPORT is not set -# CONFIG_IP_SET_HASH_NETIFACE is not set -# CONFIG_IP_SET_LIST_SET is not set -CONFIG_IP_VS=y -CONFIG_IP_VS_IPV6=y -CONFIG_IP_VS_DEBUG=y -CONFIG_IP_VS_TAB_BITS=12 - -# -# IPVS transport protocol load balancing support -# -CONFIG_IP_VS_PROTO_TCP=y -CONFIG_IP_VS_PROTO_UDP=y -CONFIG_IP_VS_PROTO_AH_ESP=y -CONFIG_IP_VS_PROTO_ESP=y -CONFIG_IP_VS_PROTO_AH=y -CONFIG_IP_VS_PROTO_SCTP=y - -# -# IPVS scheduler -# -CONFIG_IP_VS_RR=y -CONFIG_IP_VS_WRR=y -CONFIG_IP_VS_LC=y -CONFIG_IP_VS_WLC=y -CONFIG_IP_VS_LBLC=y -CONFIG_IP_VS_LBLCR=y -CONFIG_IP_VS_DH=y -CONFIG_IP_VS_SH=y -CONFIG_IP_VS_SED=y -CONFIG_IP_VS_NQ=y - -# -# IPVS SH scheduler -# -CONFIG_IP_VS_SH_TAB_BITS=8 - -# -# IPVS application helper -# -CONFIG_IP_VS_FTP=y -CONFIG_IP_VS_NFCT=y -CONFIG_IP_VS_PE_SIP=y +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set # # IP: Netfilter Configuration # CONFIG_NF_DEFRAG_IPV4=y -CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_NF_CONNTRACK_IPV4=m CONFIG_NF_CONNTRACK_PROC_COMPAT=y -# CONFIG_IP_NF_QUEUE is not set CONFIG_IP_NF_IPTABLES=y CONFIG_IP_NF_MATCH_AH=y CONFIG_IP_NF_MATCH_ECN=y @@ -878,96 +784,91 @@ CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_REJECT=y CONFIG_IP_NF_TARGET_REJECT_SKERR=y CONFIG_IP_NF_TARGET_ULOG=y -CONFIG_NF_NAT=y -CONFIG_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=y -CONFIG_IP_NF_TARGET_NETMAP=y -CONFIG_IP_NF_TARGET_REDIRECT=y -CONFIG_NF_NAT_SNMP_BASIC=y -CONFIG_NF_NAT_PROTO_DCCP=y -CONFIG_NF_NAT_PROTO_GRE=y -CONFIG_NF_NAT_PROTO_UDPLITE=y -CONFIG_NF_NAT_PROTO_SCTP=y -CONFIG_NF_NAT_FTP=y -CONFIG_NF_NAT_IRC=y -CONFIG_NF_NAT_TFTP=y -CONFIG_NF_NAT_AMANDA=y -CONFIG_NF_NAT_PPTP=y -CONFIG_NF_NAT_H323=y -CONFIG_NF_NAT_SIP=y +CONFIG_NF_NAT_IPV4=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m CONFIG_IP_NF_MANGLE=y -CONFIG_IP_NF_TARGET_CLUSTERIP=y +CONFIG_IP_NF_TARGET_CLUSTERIP=m CONFIG_IP_NF_TARGET_ECN=y CONFIG_IP_NF_TARGET_TTL=y CONFIG_IP_NF_RAW=y CONFIG_IP_NF_SECURITY=y -CONFIG_IP_NF_ARPTABLES=y -CONFIG_IP_NF_ARPFILTER=y -CONFIG_IP_NF_ARP_MANGLE=y +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m # # IPv6: Netfilter Configuration # CONFIG_NF_DEFRAG_IPV6=y CONFIG_NF_CONNTRACK_IPV6=y -CONFIG_IP6_NF_QUEUE=y CONFIG_IP6_NF_IPTABLES=y -CONFIG_IP6_NF_MATCH_AH=y -CONFIG_IP6_NF_MATCH_EUI64=y -CONFIG_IP6_NF_MATCH_FRAG=y -CONFIG_IP6_NF_MATCH_OPTS=y -CONFIG_IP6_NF_MATCH_HL=y -CONFIG_IP6_NF_MATCH_IPV6HEADER=y -CONFIG_IP6_NF_MATCH_MH=y -CONFIG_IP6_NF_MATCH_RPFILTER=y -CONFIG_IP6_NF_MATCH_RT=y -CONFIG_IP6_NF_TARGET_HL=y +# CONFIG_IP6_NF_MATCH_AH is not set +# CONFIG_IP6_NF_MATCH_EUI64 is not set +# CONFIG_IP6_NF_MATCH_FRAG is not set +# CONFIG_IP6_NF_MATCH_OPTS is not set +# CONFIG_IP6_NF_MATCH_HL is not set +# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set +# CONFIG_IP6_NF_MATCH_MH is not set +# CONFIG_IP6_NF_MATCH_RPFILTER is not set +# CONFIG_IP6_NF_MATCH_RT is not set +# CONFIG_IP6_NF_TARGET_HL is not set CONFIG_IP6_NF_FILTER=y CONFIG_IP6_NF_TARGET_REJECT=y CONFIG_IP6_NF_TARGET_REJECT_SKERR=y CONFIG_IP6_NF_MANGLE=y CONFIG_IP6_NF_RAW=y -CONFIG_IP6_NF_SECURITY=y -CONFIG_IP_DCCP=y -CONFIG_INET_DCCP_DIAG=y - -# -# DCCP CCIDs Configuration (EXPERIMENTAL) -# -# CONFIG_IP_DCCP_CCID2_DEBUG is not set -CONFIG_IP_DCCP_CCID3=y -# CONFIG_IP_DCCP_CCID3_DEBUG is not set -CONFIG_IP_DCCP_TFRC_LIB=y - -# -# DCCP Kernel Hacking -# -# CONFIG_IP_DCCP_DEBUG is not set -CONFIG_IP_SCTP=y -# CONFIG_SCTP_DBG_MSG is not set -# CONFIG_SCTP_DBG_OBJCNT is not set -# CONFIG_SCTP_HMAC_NONE is not set -# CONFIG_SCTP_HMAC_SHA1 is not set -CONFIG_SCTP_HMAC_MD5=y -CONFIG_RDS=y -CONFIG_RDS_TCP=y -# CONFIG_RDS_DEBUG is not set +# CONFIG_IP6_NF_SECURITY is not set +# CONFIG_NF_NAT_IPV6 is not set +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set # CONFIG_TIPC is not set # CONFIG_ATM is not set CONFIG_L2TP=y # CONFIG_L2TP_DEBUGFS is not set # CONFIG_L2TP_V3 is not set -# CONFIG_BRIDGE is not set -# CONFIG_NET_DSA is not set -# CONFIG_VLAN_8021Q is not set +CONFIG_STP=y +CONFIG_BRIDGE=y +CONFIG_BRIDGE_IGMP_SNOOPING=y +# CONFIG_BRIDGE_VLAN_FILTERING is not set +CONFIG_HAVE_NET_DSA=y +CONFIG_VLAN_8021Q=y +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_VLAN_8021Q_MVRP is not set # CONFIG_DECNET is not set +CONFIG_LLC=y # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set # CONFIG_PHONET is not set # CONFIG_IEEE802154 is not set CONFIG_NET_SCHED=y @@ -992,6 +893,8 @@ CONFIG_NET_SCH_HTB=y # CONFIG_NET_SCH_MQPRIO is not set # CONFIG_NET_SCH_CHOKE is not set # CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_CODEL is not set +# CONFIG_NET_SCH_FQ_CODEL is not set # CONFIG_NET_SCH_INGRESS is not set # CONFIG_NET_SCH_PLUG is not set @@ -1032,12 +935,14 @@ CONFIG_NET_SCH_FIFO=y # CONFIG_DCB is not set # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y # CONFIG_NETPRIO_CGROUP is not set CONFIG_BQL=y -CONFIG_HAVE_BPF_JIT=y # CONFIG_BPF_JIT is not set # @@ -1050,10 +955,8 @@ CONFIG_HAVE_BPF_JIT=y # CONFIG_IRDA is not set CONFIG_BT=y CONFIG_BT_RFCOMM=y -CONFIG_BT_RFCOMM_TTY=y -CONFIG_BT_BNEP=y -CONFIG_BT_BNEP_MC_FILTER=y -CONFIG_BT_BNEP_PROTO_FILTER=y +# CONFIG_BT_RFCOMM_TTY is not set +# CONFIG_BT_BNEP is not set CONFIG_BT_HIDP=y # @@ -1065,32 +968,49 @@ CONFIG_BT_HCIUART=y CONFIG_BT_HCIUART_H4=y # CONFIG_BT_HCIUART_BCSP is not set # CONFIG_BT_HCIUART_ATH3K is not set -CONFIG_BT_HCIUART_RTKH5=y # CONFIG_BT_HCIUART_LL is not set +# CONFIG_BT_HCIUART_3WIRE is not set +CONFIG_BT_HCIUART_RTKH5=y # CONFIG_BT_HCIBCM203X is not set # CONFIG_BT_HCIBPA10X is not set # CONFIG_BT_HCIBFUSB is not set # CONFIG_BT_HCIVHCI is not set -CONFIG_BCM_BT_LPM=m -CONFIG_RTL_BT_LPM=m # CONFIG_BT_MRVL is not set # CONFIG_AF_RXRPC is not set CONFIG_FIB_RULES=y CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y CONFIG_WEXT_CORE=y CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y CONFIG_CFG80211=y -# CONFIG_NL80211_TESTMODE is not set +CONFIG_NL80211_TESTMODE=y # CONFIG_CFG80211_DEVELOPER_WARNINGS is not set # CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set CONFIG_CFG80211_DEFAULT_PS=y # CONFIG_CFG80211_DEBUGFS is not set # CONFIG_CFG80211_INTERNAL_REGDB is not set CONFIG_CFG80211_WEXT=y -CONFIG_WIRELESS_EXT_SYSFS=y -# CONFIG_LIB80211 is not set -CONFIG_CFG80211_ALLOW_RECONNECT=y -# CONFIG_MAC80211 is not set +CONFIG_LIB80211=y +CONFIG_LIB80211_CRYPT_WEP=y +CONFIG_LIB80211_CRYPT_CCMP=y +CONFIG_LIB80211_CRYPT_TKIP=y +# CONFIG_LIB80211_DEBUG is not set +# CONFIG_CFG80211_ALLOW_RECONNECT is not set +CONFIG_MAC80211=y +CONFIG_MAC80211_HAS_RC=y +# CONFIG_MAC80211_RC_PID is not set +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_MESSAGE_TRACING is not set +# CONFIG_MAC80211_DEBUG_MENU is not set # CONFIG_WIMAX is not set CONFIG_RFKILL=y CONFIG_RFKILL_PM=y @@ -1102,23 +1022,24 @@ CONFIG_RFKILL_LEDS=y # CONFIG_CAIF is not set # CONFIG_CEPH_LIB is not set # CONFIG_NFC is not set +CONFIG_HAVE_BPF_JIT=y # # Device Drivers # -CONFIG_SUNXI_ARISC=y # # Generic Driver Options # -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_UEVENT_HELPER_PATH="" CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y -# CONFIG_STANDALONE is not set +CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y CONFIG_FIRMWARE_IN_KERNEL=y CONFIG_EXTRA_FIRMWARE="" +CONFIG_FW_LOADER_USER_HELPER=y # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set @@ -1126,33 +1047,55 @@ CONFIG_EXTRA_FIRMWARE="" CONFIG_REGMAP=y CONFIG_REGMAP_I2C=y CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_IRQ=y CONFIG_DMA_SHARED_BUFFER=y -CONFIG_SYNC=y -CONFIG_SW_SYNC=y -CONFIG_SW_SYNC_USER=y +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set + +# +# Default contiguous memory area size: +# +CONFIG_CMA_SIZE_MBYTES=48 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=2 +CONFIG_CMA_AREAS=1 # # Bus devices # -CONFIG_SUNXI_GTBUS=y -# CONFIG_SUNXI_MBUS is not set +# CONFIG_ARM_CCI is not set # CONFIG_CONNECTOR is not set # CONFIG_MTD is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_DEVICE=y +CONFIG_OF_I2C=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y # CONFIG_PARPORT is not set CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 -CONFIG_BLK_DEV_CRYPTOLOOP=y - -# -# DRBD disabled because PROC_FS, INET or CONNECTOR not selected -# +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_SIZE=8192 # CONFIG_BLK_DEV_XIP is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -1162,11 +1105,12 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # # Misc devices # -CONFIG_SUNXI_VIBRATOR=m # CONFIG_SENSORS_LIS3LV02D is not set # CONFIG_AD525X_DPOT is not set # CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_ICS932S401 is not set +# CONFIG_ATMEL_SSC is not set # CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_APDS9802ALS is not set # CONFIG_ISL29003 is not set @@ -1176,13 +1120,14 @@ CONFIG_SUNXI_VIBRATOR=m # CONFIG_SENSORS_BH1770 is not set # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set -# CONFIG_SENSORS_AK8975 is not set # CONFIG_DS1682 is not set # CONFIG_TI_DAC7512 is not set -CONFIG_UID_STAT=y -# CONFIG_BMP085 is not set +# CONFIG_UID_STAT is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set # CONFIG_USB_SWITCH_FSA9480 is not set -# CONFIG_WL127X_RFKILL is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -1192,9 +1137,8 @@ CONFIG_UID_STAT=y # CONFIG_EEPROM_AT25 is not set # CONFIG_EEPROM_LEGACY is not set # CONFIG_EEPROM_MAX6875 is not set -# CONFIG_EEPROM_93CX6 is not set +CONFIG_EEPROM_93CX6=m # CONFIG_EEPROM_93XX46 is not set -# CONFIG_IWMC3200TOP is not set # # Texas Instruments shared transport line discipline @@ -1207,7 +1151,11 @@ CONFIG_UID_STAT=y # Altera FPGA firmware download module # # CONFIG_ALTERA_STAPL is not set -# CONFIG_SW_3G_MODULE is not set + +# +# ACTIONS MISC INFO ACCESS DRIVER +# +CONFIG_MISC_INFO=y # # SCSI device support @@ -1227,13 +1175,12 @@ CONFIG_BLK_DEV_SD=y # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set # CONFIG_BLK_DEV_SR is not set -# CONFIG_CHR_DEV_SG is not set +CONFIG_CHR_DEV_SG=y # CONFIG_CHR_DEV_SCH is not set # CONFIG_SCSI_MULTI_LUN is not set # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set # CONFIG_SCSI_SCAN_ASYNC is not set -CONFIG_SCSI_WAIT_SCAN=m # # SCSI Transports @@ -1247,6 +1194,7 @@ CONFIG_SCSI_WAIT_SCAN=m CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set # CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_UFSHCD is not set # CONFIG_LIBFC is not set # CONFIG_LIBFCOE is not set # CONFIG_SCSI_DEBUG is not set @@ -1255,31 +1203,34 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_ATA is not set CONFIG_MD=y # CONFIG_BLK_DEV_MD is not set +# CONFIG_BCACHE is not set +CONFIG_BLK_DEV_DM_BUILTIN=y CONFIG_BLK_DEV_DM=y # CONFIG_DM_DEBUG is not set +CONFIG_DM_BUFIO=y CONFIG_DM_CRYPT=y # CONFIG_DM_SNAPSHOT is not set # CONFIG_DM_THIN_PROVISIONING is not set +# CONFIG_DM_CACHE is not set # CONFIG_DM_MIRROR is not set # CONFIG_DM_RAID is not set # CONFIG_DM_ZERO is not set # CONFIG_DM_MULTIPATH is not set # CONFIG_DM_DELAY is not set -# CONFIG_DM_UEVENT is not set +CONFIG_DM_UEVENT=y # CONFIG_DM_FLAKEY is not set -# CONFIG_DM_VERITY is not set +CONFIG_DM_VERITY=y # CONFIG_TARGET_CORE is not set CONFIG_NETDEVICES=y CONFIG_NET_CORE=y -CONFIG_BONDING=y -CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set # CONFIG_EQUALIZER is not set CONFIG_MII=y # CONFIG_IFB is not set -CONFIG_NET_TEAM=y -CONFIG_NET_TEAM_MODE_ROUNDROBIN=y -CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=y +# CONFIG_NET_TEAM is not set # CONFIG_MACVLAN is not set +# CONFIG_VXLAN is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -1289,33 +1240,64 @@ CONFIG_TUN=y # # CAIF transport drivers # + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set CONFIG_ETHERNET=y -# CONFIG_NET_VENDOR_BROADCOM is not set +CONFIG_NET_CADENCE=y +# CONFIG_ARM_AT91_ETHER is not set +# CONFIG_MACB is not set +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set # CONFIG_NET_CALXEDA_XGMAC is not set -# CONFIG_NET_VENDOR_CHELSIO is not set -# CONFIG_NET_VENDOR_CIRRUS is not set +CONFIG_NET_VENDOR_CIRRUS=y +# CONFIG_CS89x0 is not set # CONFIG_DM9000 is not set +CONFIG_NET_VENDOR_ACTS=m +CONFIG_POLL_PHY_STATE=y +# CONFIG_PHY_REALTEK_RTL8201 is not set +CONFIG_PHY_CORECHIP_SR8201G=y +# CONFIG_NET_VENDOR_SG8201G is not set # CONFIG_DNET is not set -# CONFIG_NET_VENDOR_FARADAY is not set -# CONFIG_NET_VENDOR_INTEL is not set -# CONFIG_NET_VENDOR_MARVELL is not set -# CONFIG_NET_VENDOR_MICREL is not set -# CONFIG_NET_VENDOR_MICROCHIP is not set -# CONFIG_NET_VENDOR_NATSEMI is not set +CONFIG_NET_VENDOR_FARADAY=y +# CONFIG_FTMAC100 is not set +# CONFIG_FTGMAC100 is not set +CONFIG_NET_VENDOR_INTEL=y +CONFIG_NET_VENDOR_I825XX=y +CONFIG_NET_VENDOR_MARVELL=y +# CONFIG_MVMDIO is not set +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NET_VENDOR_8390=y +# CONFIG_AX88796 is not set # CONFIG_ETHOC is not set -# CONFIG_NET_VENDOR_SEEQ is not set -# CONFIG_NET_VENDOR_SMSC is not set -# CONFIG_NET_VENDOR_STMICRO is not set -CONFIG_NET_VENDOR_SUNXI=y -CONFIG_SUNXI_GETH=m -CONFIG_GETH_SCRIPT_SYS=y -CONFIG_GETH_CLK_SYS=y -CONFIG_GETH_PHY_POWER=y +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SMSC=y +# CONFIG_SMC91X is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set CONFIG_PHYLIB=y # # MII PHY device drivers # +# CONFIG_AT803X_PHY is not set # CONFIG_AMD_PHY is not set # CONFIG_MARVELL_PHY is not set # CONFIG_DAVICOM_PHY is not set @@ -1325,6 +1307,7 @@ CONFIG_PHYLIB=y # CONFIG_VITESSE_PHY is not set # CONFIG_SMSC_PHY is not set # CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM87XX_PHY is not set # CONFIG_ICPLUS_PHY is not set # CONFIG_REALTEK_PHY is not set # CONFIG_NATIONAL_PHY is not set @@ -1333,22 +1316,23 @@ CONFIG_PHYLIB=y # CONFIG_MICREL_PHY is not set # CONFIG_FIXED_PHY is not set # CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set # CONFIG_MICREL_KS8995MA is not set -CONFIG_PPP=y -CONFIG_PPP_BSDCOMP=y -CONFIG_PPP_DEFLATE=y +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=y +CONFIG_PPP_MPPE=m CONFIG_PPP_MULTILINK=y -CONFIG_PPPOE=y -CONFIG_PPTP=y -CONFIG_PPPOL2TP=y -CONFIG_PPPOLAC=y -CONFIG_PPPOPNS=y -CONFIG_PPP_ASYNC=y -CONFIG_PPP_SYNC_TTY=y +CONFIG_PPPOE=m +CONFIG_PPPOL2TP=m +CONFIG_PPPOLAC=m +CONFIG_PPPOPNS=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m # CONFIG_SLIP is not set -CONFIG_SLHC=y +CONFIG_SLHC=m # # USB Network Adapters @@ -1356,22 +1340,33 @@ CONFIG_SLHC=y # CONFIG_USB_CATC is not set # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set -CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8150=y +CONFIG_USB_RTL8152=y CONFIG_USB_USBNET=m -CONFIG_USB_NET_AX8817X=m -CONFIG_USB_NET_QF9700=m +# CONFIG_USB_NET_ASIX is not set +# CONFIG_USB_NET_SR9700 is not set +# CONFIG_USB_NET_SR9800 is not set +# CONFIG_USB_NET_AX8817X is not set +# CONFIG_USB_NET_AX88179_178A is not set CONFIG_USB_NET_CDCETHER=m -# CONFIG_USB_NET_CDC_EEM is not set -# CONFIG_USB_NET_CDC_NCM is not set +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_CDC_NCM=m +CONFIG_USB_NET_CDC_MBIM=m # CONFIG_USB_NET_DM9601 is not set # CONFIG_USB_NET_SMSC75XX is not set # CONFIG_USB_NET_SMSC95XX is not set # CONFIG_USB_NET_GL620A is not set # CONFIG_USB_NET_NET1080 is not set # CONFIG_USB_NET_PLUSB is not set -CONFIG_USB_NET_MCS7830=m +# CONFIG_USB_NET_MCS7830 is not set # CONFIG_USB_NET_RNDIS_HOST is not set -# CONFIG_USB_NET_CDC_SUBSET is not set +CONFIG_USB_NET_CDC_SUBSET=m +# CONFIG_USB_ALI_M5632 is not set +# CONFIG_USB_AN2720 is not set +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +# CONFIG_USB_EPSON2888 is not set +# CONFIG_USB_KC2190 is not set # CONFIG_USB_NET_ZAURUS is not set # CONFIG_USB_NET_CX82310_ETH is not set # CONFIG_USB_NET_KALMIA is not set @@ -1382,24 +1377,76 @@ CONFIG_USB_NET_MCS7830=m # CONFIG_USB_SIERRA_NET is not set # CONFIG_USB_VL600 is not set CONFIG_WLAN=y +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_AT76C50X_USB is not set # CONFIG_USB_ZD1201 is not set # CONFIG_USB_NET_RNDIS_WLAN is not set +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y +# CONFIG_MAC80211_HWSIM is not set # CONFIG_WIFI_CONTROL_FUNC is not set -# CONFIG_ATH_COMMON is not set -CONFIG_BCMDHD=m -CONFIG_BCMDHD_FW_PATH=y -CONFIG_BCMDHD_NVRAM_PATH=y -CONFIG_BCMDHD_CONFIG_PATH=y -CONFIG_BCMDHD_OOB=y -# CONFIG_BCMDHD_SDIO_IRQ is not set -# CONFIG_BRCMFMAC is not set -# CONFIG_HOSTAP is not set -# CONFIG_IWM is not set -# CONFIG_LIBERTAS is not set -# CONFIG_MWIFIEX is not set -CONFIG_RTL8188EU=m -# CONFIG_RTL8189ES is not set +CONFIG_BROADCOM_WIFI_BT=m CONFIG_RTL8723BS=m +# CONFIG_RTL8723BS_VQ0 is not set +CONFIG_RTL8723BU=m +CONFIG_RTL8188ETV=m +CONFIG_ATH_COMMON=m +CONFIG_ATH_CARDS=m +# CONFIG_ATH_DEBUG is not set +CONFIG_ATH9K_HW=m +CONFIG_ATH9K_COMMON=m +CONFIG_ATH9K_BTCOEX_SUPPORT=y +CONFIG_ATH9K=m +CONFIG_ATH9K_AHB=y +# CONFIG_ATH9K_DEBUGFS is not set +CONFIG_ATH9K_LEGACY_RATE_CONTROL=y +CONFIG_ATH9K_HTC=m +# CONFIG_ATH9K_HTC_DEBUGFS is not set +CONFIG_CARL9170=m +CONFIG_CARL9170_LEDS=y +CONFIG_CARL9170_WPC=y +# CONFIG_CARL9170_HWRNG is not set +# CONFIG_ATH6KL is not set +CONFIG_AR5523=m +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_BRCMFMAC is not set +CONFIG_HOSTAP=y +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +# CONFIG_LIBERTAS is not set +# CONFIG_P54_COMMON is not set +CONFIG_RT2X00=y +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT33XX=y +CONFIG_RT2800USB_RT35XX=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +# CONFIG_RT2800USB_UNKNOWN is not set +CONFIG_RT2800_LIB=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_DEBUG is not set +CONFIG_RTLWIFI=y +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8192CU=m +CONFIG_RTL8192C_COMMON=m +CONFIG_WL_TI=y +CONFIG_WL1251=m +# CONFIG_WL1251_SPI is not set +# CONFIG_WL1251_SDIO is not set +CONFIG_WL12XX=m +CONFIG_WL18XX=m +CONFIG_WLCORE=m +# CONFIG_WLCORE_SPI is not set +# CONFIG_WLCORE_SDIO is not set +# CONFIG_ZD1211RW is not set +# CONFIG_MWIFIEX is not set # # Enable WiMAX (Networking options) to see the WiMAX drivers @@ -1414,6 +1461,7 @@ CONFIG_INPUT=y CONFIG_INPUT_FF_MEMLESS=y CONFIG_INPUT_POLLDEV=y # CONFIG_INPUT_SPARSEKMAP is not set +# CONFIG_INPUT_MATRIXKMAP is not set # # Userland interfaces @@ -1422,12 +1470,10 @@ CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=y +# CONFIG_INPUT_JOYDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set -# CONFIG_INPUT_APMPOWER is not set # CONFIG_INPUT_KEYRESET is not set -CONFIG_INPUT_SW_DEVICE=m # # Input Device Drivers @@ -1444,6 +1490,7 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_TCA8418 is not set # CONFIG_KEYBOARD_MATRIX is not set # CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set # CONFIG_KEYBOARD_MAX7359 is not set # CONFIG_KEYBOARD_MCS is not set # CONFIG_KEYBOARD_MPR121 is not set @@ -1452,27 +1499,11 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_SAMSUNG is not set # CONFIG_KEYBOARD_STOWAWAY is not set # CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_ATC260X_ADCKEY is not set +CONFIG_KEYBOARD_ATC260X_ONOFF=y +CONFIG_KEYBOARD_ATC260X_IRKEY=m # CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_SUNXI is not set -CONFIG_IR_RX_SUNXI=m -CONFIG_IR_TX_SUNXI=m -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=y -CONFIG_MOUSE_PS2_ALPS=y -CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_TRACKPOINT=y -# CONFIG_MOUSE_PS2_ELANTECH is not set -# CONFIG_MOUSE_PS2_SENTELIC is not set -# CONFIG_MOUSE_PS2_TOUCHKIT is not set -CONFIG_MOUSE_SERIAL=y -# CONFIG_MOUSE_APPLETOUCH is not set -# CONFIG_MOUSE_BCM5974 is not set -# CONFIG_MOUSE_VSXXXAA is not set -# CONFIG_MOUSE_GPIO is not set -# CONFIG_MOUSE_SYNAPTICS_I2C is not set -# CONFIG_MOUSE_SYNAPTICS_USB is not set +# CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_JOYSTICK=y # CONFIG_JOYSTICK_ANALOG is not set # CONFIG_JOYSTICK_A3D is not set @@ -1496,9 +1527,15 @@ CONFIG_INPUT_JOYSTICK=y # CONFIG_JOYSTICK_AS5011 is not set # CONFIG_JOYSTICK_JOYDUMP is not set CONFIG_JOYSTICK_XPAD=y -# CONFIG_JOYSTICK_XPAD_FF is not set -# CONFIG_JOYSTICK_XPAD_LEDS is not set -# CONFIG_INPUT_TABLET is not set +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_INPUT_TABLET=y +CONFIG_TABLET_USB_ACECAD=y +CONFIG_TABLET_USB_AIPTEK=y +CONFIG_TABLET_USB_GTCO=y +CONFIG_TABLET_USB_HANWANG=y +CONFIG_TABLET_USB_KBTAB=y +CONFIG_TABLET_USB_WACOM=y CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_ADS7846 is not set # CONFIG_TOUCHSCREEN_AD7877 is not set @@ -1517,13 +1554,15 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_GUNZE is not set # CONFIG_TOUCHSCREEN_ELO is not set # CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set # CONFIG_TOUCHSCREEN_MAX11801 is not set # CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set # CONFIG_TOUCHSCREEN_MTOUCH is not set # CONFIG_TOUCHSCREEN_INEXIO is not set # CONFIG_TOUCHSCREEN_MK712 is not set # CONFIG_TOUCHSCREEN_PENMOUNT is not set -# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set # CONFIG_TOUCHSCREEN_TOUCHWIN is not set # CONFIG_TOUCHSCREEN_PIXCIR is not set @@ -1535,26 +1574,13 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_W90X900 is not set # CONFIG_TOUCHSCREEN_ST1232 is not set # CONFIG_TOUCHSCREEN_TPS6507X is not set -# CONFIG_TOUCHSCREEN_GT82X is not set -# CONFIG_TOUCHSCREEN_SUN6I_TS is not set -# CONFIG_TOUCHSCREEN_FT5X_TS is not set -# CONFIG_TOUCHSCREEN_GT9XX_TS is not set -# CONFIG_TOUCHSCREEN_GT9XXF_TS is not set -# CONFIG_TOUCHSCREEN_GSLX680 is not set -# CONFIG_TOUCHSCREEN_GSLX680NEW is not set -# CONFIG_TOUCHSCREEN_GT9XXNEW_TS is not set -# CONFIG_TOUCHSCREEN_AW5X06_TS is not set -# CONFIG_TOUCHSCREEN_GT818_TS is not set -# CONFIG_TOUCHSCREEN_TU_TS is not set -# CONFIG_TOUCHSCREEN_ICN83XX_TS is not set +CONFIG_TOUCHSCREEN_GSLX680=m +# CONFIG_TOUCHSCREEN_GSL1680F is not set +CONFIG_TOUCHSCREEN_GSL3680=m +CONFIG_TOUCHSCREEN_FT5X06=m +# CONFIG_TOUCHSCREEN_GT9XX is not set +CONFIG_TOUCHSCREEN_DETECT=m CONFIG_INPUT_MISC=y -CONFIG_E_COMPASS_L3M303D=m -CONFIG_E_COMPASS_FXOS8700=m -CONFIG_E_COMPASS_AKM8963=m -CONFIG_GYR_L3GD20=m -CONFIG_GYR_BMG160=m -CONFIG_INPUT_LTR501ALS=m -CONFIG_INPUT_JSA1127=m # CONFIG_INPUT_AD714X is not set # CONFIG_INPUT_BMA150 is not set # CONFIG_INPUT_MMA8450 is not set @@ -1571,24 +1597,42 @@ CONFIG_INPUT_JSA1127=m CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_GPIO is not set # CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PWM_BEEPER is not set # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set +CONFIG_INPUT_GSENSOR=y +CONFIG_GSENSOR_DETECT=m +CONFIG_GSENSOR_BMA222=m +# CONFIG_GSENSOR_STK8312 is not set +CONFIG_GSENSOR_STK8313=m +CONFIG_GSENSOR_MC3236=m +# CONFIG_GSENSOR_MC3230 is not set +CONFIG_GSENSOR_MC3232=m +# CONFIG_GSENSOR_MMA7660 is not set +CONFIG_GSENSOR_KIONIX=m +CONFIG_GSENSOR_MIR3DA=m +CONFIG_INPUT_LIGHT_GSENSOR=y +CONFIG_LIGHT_GSENSOR_LTR301=m # # Hardware I/O ports # CONFIG_SERIO=y -# CONFIG_SERIO_SERPORT is not set +CONFIG_SERIO_SERPORT=y CONFIG_SERIO_LIBPS2=y # CONFIG_SERIO_RAW is not set # CONFIG_SERIO_ALTERA_PS2 is not set # CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set # CONFIG_GAMEPORT is not set # # Character devices # +CONFIG_TTY=y CONFIG_VT=y CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y @@ -1602,7 +1646,7 @@ CONFIG_UNIX98_PTYS=y # CONFIG_N_GSM is not set # CONFIG_TRACE_SINK is not set CONFIG_DEVMEM=y -CONFIG_DEVKMEM=y +# CONFIG_DEVKMEM is not set # # Serial drivers @@ -1613,37 +1657,34 @@ CONFIG_DEVKMEM=y # Non-8250 serial port support # # CONFIG_SERIAL_MAX3100 is not set -# CONFIG_SERIAL_MAX3107 is not set +# CONFIG_SERIAL_MAX310X is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_SCCNXP is not set # CONFIG_SERIAL_TIMBERDALE is not set # CONFIG_SERIAL_ALTERA_JTAGUART is not set # CONFIG_SERIAL_ALTERA_UART is not set # CONFIG_SERIAL_IFX6X60 is not set # CONFIG_SERIAL_XILINX_PS_UART is not set -CONFIG_SERIAL_SUNXI=y -CONFIG_SERIAL_SUNXI_CONSOLE=y +# CONFIG_SERIAL_ARC is not set # CONFIG_TTY_PRINTK is not set # CONFIG_HVC_DCC is not set # CONFIG_IPMI_HANDLER is not set -# CONFIG_HW_RANDOM is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_HW_RANDOM_ATMEL is not set +# CONFIG_HW_RANDOM_EXYNOS is not set # CONFIG_R3964 is not set # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set # CONFIG_DCC_TTY is not set -# CONFIG_RAMOOPS is not set -CONFIG_SUNXI_G2D=y -CONFIG_SUNXI_ARISC_TEST=m -CONFIG_SUNXI_MODULE=y -CONFIG_SUNXI_TIMER_TEST=m -CONFIG_SUNXI_DMA_TEST=m CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_COMPAT=y -# CONFIG_I2C_CHARDEV is not set +CONFIG_I2C_CHARDEV=y # CONFIG_I2C_MUX is not set CONFIG_I2C_HELPER_AUTO=y -CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_ALGOBIT=m # # I2C Hardware Bus support @@ -1652,13 +1693,13 @@ CONFIG_I2C_ALGOBIT=y # # I2C system bus drivers (mostly embedded / system-on-chip) # +# CONFIG_I2C_CBUS_GPIO is not set # CONFIG_I2C_DESIGNWARE_PLATFORM is not set # CONFIG_I2C_GPIO is not set # CONFIG_I2C_OCORES is not set # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_PXA_PCI is not set # CONFIG_I2C_SIMTEC is not set -CONFIG_I2C_SUNXI=y # CONFIG_I2C_XILINX is not set # @@ -1686,17 +1727,25 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_ALTERA is not set # CONFIG_SPI_BITBANG is not set # CONFIG_SPI_GPIO is not set +# CONFIG_SPI_FSL_SPI is not set # CONFIG_SPI_OC_TINY is not set # CONFIG_SPI_PXA2XX_PCI is not set -CONFIG_SPI_SUNXI=y +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_XCOMM is not set # CONFIG_SPI_XILINX is not set # CONFIG_SPI_DESIGNWARE is not set # # SPI Protocol Masters # -# CONFIG_SPI_SPIDEV is not set +CONFIG_SPI_SPIDEV=y # CONFIG_SPI_TLE62X0 is not set +CONFIG_SPI_OWL=y + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # @@ -1711,10 +1760,12 @@ CONFIG_SPI_SUNXI=y # # PTP clock support # +# CONFIG_PTP_1588_CLOCK is not set # -# Enable Device Drivers -> PPS to see the PTP clock options. +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. # +# CONFIG_PTP_1588_CLOCK_PCH is not set CONFIG_PINCTRL=y # @@ -1722,23 +1773,26 @@ CONFIG_PINCTRL=y # CONFIG_PINMUX=y CONFIG_PINCONF=y -CONFIG_GENERIC_PINCONF=y # CONFIG_DEBUG_PINCTRL is not set -CONFIG_PINCTRL_SUNXI=y -# CONFIG_PINCTRL_SUNXI_DEBUG is not set -CONFIG_SUNXI_PINCTRL_TEST=m -CONFIG_PINCTRL_AXP=y +# CONFIG_PINCTRL_SINGLE is not set +# CONFIG_PINCTRL_EXYNOS is not set +# CONFIG_PINCTRL_EXYNOS5440 is not set CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIO_DEVRES=y CONFIG_GPIOLIB=y +CONFIG_OF_GPIO=y # CONFIG_DEBUG_GPIO is not set CONFIG_GPIO_SYSFS=y -CONFIG_GPIO_GENERIC=y # # Memory mapped GPIO drivers: # -CONFIG_GPIO_GENERIC_PLATFORM=y +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_EM is not set +# CONFIG_GPIO_RCAR is not set +# CONFIG_GPIO_TS5500 is not set +# CONFIG_GPIO_GRGPIO is not set # # I2C GPIO expanders: @@ -1748,6 +1802,8 @@ CONFIG_GPIO_GENERIC_PLATFORM=y # CONFIG_GPIO_PCF857X is not set # CONFIG_GPIO_SX150X is not set # CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set +CONFIG_GPIO_ATC260X=y # # PCI GPIO expanders: @@ -1768,35 +1824,36 @@ CONFIG_GPIO_GENERIC_PLATFORM=y # # MODULbus GPIO expanders: # + +# +# USB GPIO expanders: +# # CONFIG_W1 is not set CONFIG_POWER_SUPPLY=y -CONFIG_AW_AXP=y -# CONFIG_AW_AXP81X is not set -CONFIG_AW_AXP22=y -CONFIG_AXP809=y -# CONFIG_AW_AXP19 is not set -CONFIG_AW_AXP15=y -CONFIG_AXP_CHARGEINIT=y -CONFIG_AXP_CHGCHANGE=y -# CONFIG_AXP_TWI_USED is not set # CONFIG_POWER_SUPPLY_DEBUG is not set # CONFIG_PDA_POWER is not set -# CONFIG_APM_POWER is not set +# CONFIG_GENERIC_ADC_BATTERY is not set # CONFIG_TEST_POWER is not set # CONFIG_BATTERY_DS2780 is not set # CONFIG_BATTERY_DS2781 is not set # CONFIG_BATTERY_DS2782 is not set # CONFIG_BATTERY_SBS is not set # CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_BQ27441 is not set # CONFIG_BATTERY_MAX17040 is not set # CONFIG_BATTERY_MAX17042 is not set -CONFIG_BATTERY_ANDROID=y -# CONFIG_CHARGER_ISP1704 is not set # CONFIG_CHARGER_MAX8903 is not set # CONFIG_CHARGER_LP8727 is not set # CONFIG_CHARGER_GPIO is not set # CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_SMB347 is not set +# CONFIG_BATTERY_GOLDFISH is not set +CONFIG_CHARGER_DRV_ATC206X=y +# CONFIG_ATC260X_CAP_GAUGE is not set +# CONFIG_POWER_RESET is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_AVS is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_HWMON_DEBUG_CHIP is not set @@ -1804,14 +1861,6 @@ CONFIG_HWMON=y # # Native drivers # -CONFIG_SENSORS_KIONIX=m -CONFIG_SENSORS_MMA7660=m -CONFIG_SENSORS_MMA865x=m -CONFIG_SENSORS_MMA8452=m -CONFIG_SENSORS_AFA750=m -CONFIG_SENSORS_BMA250=m -CONFIG_SENSORS_LIS3DH_ACC=m -CONFIG_SENSORS_LIS3DE_ACC=m # CONFIG_SENSORS_AD7314 is not set # CONFIG_SENSORS_AD7414 is not set # CONFIG_SENSORS_AD7418 is not set @@ -1822,6 +1871,8 @@ CONFIG_SENSORS_LIS3DE_ACC=m # CONFIG_SENSORS_ADM1029 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set # CONFIG_SENSORS_ADT7411 is not set # CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set @@ -1837,6 +1888,8 @@ CONFIG_SENSORS_LIS3DE_ACC=m # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_IIO_HWMON is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_JC42 is not set # CONFIG_SENSORS_LINEAGE is not set @@ -1857,16 +1910,20 @@ CONFIG_SENSORS_LIS3DE_ACC=m # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set # CONFIG_SENSORS_MAX1111 is not set # CONFIG_SENSORS_MAX16065 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set # CONFIG_SENSORS_MAX6639 is not set # CONFIG_SENSORS_MAX6642 is not set # CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -1883,12 +1940,12 @@ CONFIG_SENSORS_LIS3DE_ACC=m # CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_SCH56XX_COMMON is not set -# CONFIG_SENSORS_SCH5627 is not set -# CONFIG_SENSORS_SCH5636 is not set # CONFIG_SENSORS_ADS1015 is not set # CONFIG_SENSORS_ADS7828 is not set # CONFIG_SENSORS_ADS7871 is not set # CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set # CONFIG_SENSORS_THMC50 is not set # CONFIG_SENSORS_TMP102 is not set # CONFIG_SENSORS_TMP401 is not set @@ -1903,25 +1960,19 @@ CONFIG_SENSORS_LIS3DE_ACC=m # CONFIG_SENSORS_W83L786NG is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set - -# -# INA219 drivers -# -# CONFIG_SENSORS_INA219 is not set +CONFIG_SENSORS_ATC260X=y CONFIG_THERMAL=y CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y # CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set # CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set -# CONFIG_FAIR_SHARE is not set -CONFIG_STEP_WISE=y -# CONFIG_USER_SPACE is not set -CONFIG_SUNXI_THERMAL_DYNAMIC=y -# CONFIG_CPU_THERMAL is not set -CONFIG_CPU_BUDGET_THERMAL=y -CONFIG_SUNXI_THERMAL=y -CONFIG_SUNXI_BUDGET_COOLING=y -CONFIG_SUNXI_BUDGET_COOLING_VFTBL=y +CONFIG_THERMAL_GOV_FAIR_SHARE=y +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_CPU_THERMAL=y +CONFIG_THERMAL_EMULATION=y +CONFIG_OWL_THERMAL=y # CONFIG_WATCHDOG is not set CONFIG_SSB_POSSIBLE=y @@ -1939,50 +1990,75 @@ CONFIG_BCMA_POSSIBLE=y # # Multifunction device drivers # -# CONFIG_MFD_CORE is not set -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_SM501 is not set +CONFIG_MFD_CORE=y +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_MFD_ASIC3 is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set # CONFIG_HTC_EGPIO is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_HTC_I2CPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set # CONFIG_TPS6105X is not set # CONFIG_TPS65010 is not set # CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set # CONFIG_MFD_TPS65217 is not set # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set # CONFIG_MFD_TPS65912_I2C is not set # CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set # CONFIG_TWL4030_CORE is not set # CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set # CONFIG_MFD_TC3589X is not set # CONFIG_MFD_TMIO is not set # CONFIG_MFD_T7L66XB is not set # CONFIG_MFD_TC6387XB is not set # CONFIG_MFD_TC6393XB is not set -# CONFIG_PMIC_DA903X is not set -# CONFIG_MFD_DA9052_SPI is not set -# CONFIG_MFD_DA9052_I2C is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_MAX8925 is not set -# CONFIG_MFD_MAX8997 is not set -# CONFIG_MFD_MAX8998 is not set -# CONFIG_MFD_S5M_CORE is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM831X_SPI is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_EZX_PCAP is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_AAT2870_CORE is not set -# CONFIG_MFD_RC5T583 is not set +CONFIG_MFD_ATC260X=y +# CONFIG_VEXPRESS_CONFIG is not set +CONFIG_ATC260X_PWM=y CONFIG_REGULATOR=y # CONFIG_REGULATOR_DEBUG is not set # CONFIG_REGULATOR_DUMMY is not set @@ -1991,146 +2067,55 @@ CONFIG_REGULATOR=y # CONFIG_REGULATOR_USERSPACE_CONSUMER is not set # CONFIG_REGULATOR_GPIO is not set # CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_FAN53555 is not set # CONFIG_REGULATOR_ISL6271A is not set # CONFIG_REGULATOR_MAX1586 is not set # CONFIG_REGULATOR_MAX8649 is not set # CONFIG_REGULATOR_MAX8660 is not set # CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set # CONFIG_REGULATOR_LP3971 is not set # CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_TPS51632 is not set # CONFIG_REGULATOR_TPS62360 is not set # CONFIG_REGULATOR_TPS65023 is not set # CONFIG_REGULATOR_TPS6507X is not set # CONFIG_REGULATOR_TPS6524X is not set -CONFIG_PWM=y -CONFIG_PWM_SUNXI=y +CONFIG_REGULATOR_ATC260X=y CONFIG_MEDIA_SUPPORT=y # # Multimedia core support # +CONFIG_MEDIA_CAMERA_SUPPORT=y +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set +# CONFIG_MEDIA_RADIO_SUPPORT is not set +# CONFIG_MEDIA_RC_SUPPORT is not set # CONFIG_MEDIA_CONTROLLER is not set CONFIG_VIDEO_DEV=y -CONFIG_VIDEO_V4L2_COMMON=y -# CONFIG_DVB_CORE is not set -CONFIG_VIDEO_MEDIA=y - -# -# Multimedia drivers -# -# CONFIG_RC_CORE is not set -# CONFIG_MEDIA_ATTACH is not set -CONFIG_MEDIA_TUNER=y -# CONFIG_MEDIA_TUNER_CUSTOMISE is not set -CONFIG_MEDIA_TUNER_SIMPLE=y -CONFIG_MEDIA_TUNER_TDA8290=y -CONFIG_MEDIA_TUNER_TDA827X=y -CONFIG_MEDIA_TUNER_TDA18271=y -CONFIG_MEDIA_TUNER_TDA9887=y -CONFIG_MEDIA_TUNER_TEA5761=y -CONFIG_MEDIA_TUNER_TEA5767=y -CONFIG_MEDIA_TUNER_MT20XX=y -CONFIG_MEDIA_TUNER_XC2028=y -CONFIG_MEDIA_TUNER_XC5000=y -CONFIG_MEDIA_TUNER_XC4000=y -CONFIG_MEDIA_TUNER_MC44S803=y CONFIG_VIDEO_V4L2=y -CONFIG_VIDEOBUF_GEN=m -CONFIG_VIDEOBUF_DMA_CONTIG=m -CONFIG_VIDEO_CAPTURE_DRIVERS=y # CONFIG_VIDEO_ADV_DEBUG is not set # CONFIG_VIDEO_FIXED_MINOR_RANGES is not set -# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set +CONFIG_VIDEOBUF_GEN=y +CONFIG_VIDEOBUF_DMA_CONTIG=y +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_DMA_CONTIG=y +CONFIG_VIDEOBUF2_VMALLOC=m +# CONFIG_VIDEO_V4L2_INT_DEVICE is not set +# CONFIG_TTPCI_EEPROM is not set # -# Encoders, decoders, sensors and other helper chips +# Media drivers # +CONFIG_MEDIA_USB_SUPPORT=y # -# Audio decoders, processors and mixers +# Webcam devices # -# CONFIG_VIDEO_TVAUDIO is not set -# CONFIG_VIDEO_TDA7432 is not set -# CONFIG_VIDEO_TDA9840 is not set -# CONFIG_VIDEO_TEA6415C is not set -# CONFIG_VIDEO_TEA6420 is not set -# CONFIG_VIDEO_MSP3400 is not set -# CONFIG_VIDEO_CS5345 is not set -# CONFIG_VIDEO_CS53L32A is not set -# CONFIG_VIDEO_TLV320AIC23B is not set -# CONFIG_VIDEO_WM8775 is not set -# CONFIG_VIDEO_WM8739 is not set -# CONFIG_VIDEO_VP27SMPX is not set - -# -# RDS decoders -# -# CONFIG_VIDEO_SAA6588 is not set - -# -# Video decoders -# -# CONFIG_VIDEO_ADV7180 is not set -# CONFIG_VIDEO_ADV7183 is not set -# CONFIG_VIDEO_BT819 is not set -# CONFIG_VIDEO_BT856 is not set -# CONFIG_VIDEO_BT866 is not set -# CONFIG_VIDEO_KS0127 is not set -# CONFIG_VIDEO_SAA7110 is not set -# CONFIG_VIDEO_SAA711X is not set -# CONFIG_VIDEO_SAA7191 is not set -# CONFIG_VIDEO_TVP514X is not set -# CONFIG_VIDEO_TVP5150 is not set -# CONFIG_VIDEO_TVP7002 is not set -# CONFIG_VIDEO_VPX3220 is not set - -# -# Video and audio decoders -# -# CONFIG_VIDEO_SAA717X is not set -# CONFIG_VIDEO_CX25840 is not set - -# -# MPEG video encoders -# -# CONFIG_VIDEO_CX2341X is not set - -# -# Video encoders -# -# CONFIG_VIDEO_SAA7127 is not set -# CONFIG_VIDEO_SAA7185 is not set -# CONFIG_VIDEO_ADV7170 is not set -# CONFIG_VIDEO_ADV7175 is not set -# CONFIG_VIDEO_ADV7343 is not set -# CONFIG_VIDEO_AK881X is not set - -# -# Camera sensor devices -# -# CONFIG_VIDEO_OV7670 is not set -# CONFIG_VIDEO_VS6624 is not set -# CONFIG_VIDEO_MT9V011 is not set -# CONFIG_VIDEO_TCM825X is not set -# CONFIG_VIDEO_SR030PC30 is not set - -# -# Flash devices -# - -# -# Video improvement chips -# -# CONFIG_VIDEO_UPD64031A is not set -# CONFIG_VIDEO_UPD64083 is not set - -# -# Miscelaneous helper chips -# -# CONFIG_VIDEO_THS7303 is not set -# CONFIG_VIDEO_M52790 is not set -# CONFIG_VIDEO_VIVI is not set -CONFIG_V4L_USB_DRIVERS=y CONFIG_USB_VIDEO_CLASS=m CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y CONFIG_USB_GSPCA=m @@ -2180,37 +2165,160 @@ CONFIG_USB_GSPCA=m # CONFIG_USB_GSPCA_VICAM is not set # CONFIG_USB_GSPCA_XIRLINK_CIT is not set # CONFIG_USB_GSPCA_ZC3XX is not set -# CONFIG_VIDEO_PVRUSB2 is not set -# CONFIG_VIDEO_HDPVR is not set -# CONFIG_VIDEO_EM28XX is not set -# CONFIG_VIDEO_USBVISION is not set -# CONFIG_USB_ET61X251 is not set -# CONFIG_USB_SN9C102 is not set # CONFIG_USB_PWC is not set # CONFIG_VIDEO_CPIA2 is not set # CONFIG_USB_ZR364XX is not set # CONFIG_USB_STKWEBCAM is not set # CONFIG_USB_S2255 is not set +# CONFIG_USB_SN9C102 is not set + +# +# Webcam, TV (analog/digital) USB devices +# +# CONFIG_VIDEO_EM28XX is not set CONFIG_V4L_PLATFORM_DRIVERS=y # CONFIG_VIDEO_TIMBERDALE is not set -# CONFIG_SOC_CAMERA is not set -CONFIG_VIDEO_SUNXI_VFE=m -CONFIG_CSI_VFE=m +CONFIG_SOC_CAMERA=y +# CONFIG_SOC_CAMERA_PLATFORM is not set +# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set +# CONFIG_VIDEO_SH_MOBILE_CEU is not set # CONFIG_V4L_MEM2MEM_DRIVERS is not set -CONFIG_SUNXI_FD=m -# CONFIG_RADIO_ADAPTERS is not set -CONFIG_VIDEO_ENCODER_DECODER_SUNXI=y +# CONFIG_V4L_TEST_DRIVERS is not set + +# +# Supported MMC/SDIO adapters +# +# CONFIG_CYPRESS_FIRMWARE is not set + +# +# Media ancillary drivers (tuners, sensors, i2c, frontends) +# +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y + +# +# Audio decoders, processors and mixers +# + +# +# RDS decoders +# + +# +# Video decoders +# + +# +# Video and audio decoders +# + +# +# Video encoders +# + +# +# Camera sensor devices +# + +# +# Flash devices +# + +# +# Video improvement chips +# + +# +# Miscelaneous helper chips +# + +# +# Sensors used on soc_camera driver +# + +# +# soc_camera sensor drivers +# +# CONFIG_SOC_CAMERA_IMX074 is not set +# CONFIG_SOC_CAMERA_MT9M001 is not set +# CONFIG_SOC_CAMERA_MT9M111 is not set +# CONFIG_SOC_CAMERA_MT9T031 is not set +# CONFIG_SOC_CAMERA_MT9T112 is not set +# CONFIG_SOC_CAMERA_MT9V022 is not set +# CONFIG_SOC_CAMERA_OV2640 is not set +# CONFIG_SOC_CAMERA_OV5642 is not set +# CONFIG_SOC_CAMERA_OV6650 is not set +# CONFIG_SOC_CAMERA_OV772X is not set +# CONFIG_SOC_CAMERA_OV9640 is not set +# CONFIG_SOC_CAMERA_OV9740 is not set +# CONFIG_SOC_CAMERA_RJ54N1 is not set +# CONFIG_SOC_CAMERA_TW9910 is not set +CONFIG_ACTIONS_CAMERA=y + +# +# Sensors used on Actions driver +# +CONFIG_GC2035=m +CONFIG_GC0308=m +CONFIG_GC2155=m +CONFIG_GC0312=m +CONFIG_GC2145=m +CONFIG_GC0328=m +CONFIG_GC0329=m +CONFIG_SP0A19=m +CONFIG_HI257=m +CONFIG_HI708=m +CONFIG_OV5640=m +CONFIG_SP2519=m +CONFIG_OV2686=m +CONFIG_SOC5140=m +CONFIG_SP0718=m +CONFIG_SIV121DU=m +CONFIG_FLASHLIGHT=m +CONFIG_OWL7059_CAMERA=m +CONFIG_SENSOR_DETECT=m + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set # # Graphics support # -CONFIG_DRM=y +CONFIG_FB_TFT=m +CONFIG_FB_TFT_BD663474=m +CONFIG_FB_TFT_HX8340BN=m +CONFIG_FB_TFT_HX8347D=m +CONFIG_FB_TFT_HX8353D=m +CONFIG_FB_TFT_ILI9320=m +CONFIG_FB_TFT_ILI9325=m +CONFIG_FB_TFT_ILI9340=m +CONFIG_FB_TFT_ILI9341=m +CONFIG_FB_TFT_ILI9486=m +CONFIG_FB_TFT_PCD8544=m +CONFIG_FB_TFT_RA8875=m +CONFIG_FB_TFT_S6D02A1=m +CONFIG_FB_TFT_S6D1121=m +CONFIG_FB_TFT_SSD1289=m +CONFIG_FB_TFT_SSD1306=m +CONFIG_FB_TFT_SSD1331=m +CONFIG_FB_TFT_SSD1351=m +CONFIG_FB_TFT_ST7735R=m +CONFIG_FB_TFT_TINYLCD=m +CONFIG_FB_TFT_TLS8204=m +CONFIG_FB_TFT_UPD161704=m +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m +CONFIG_DRM=m # CONFIG_DRM_UDL is not set -CONFIG_ION=y -CONFIG_ION_SUNXI=y -CONFIG_ION_SUNXI_CARVEOUT_SIZE=384 +# CONFIG_DRM_TILCDC is not set +CONFIG_IMG_PVR_GPU=y +CONFIG_IMG_SGX_5xx=m +# CONFIG_IMG_ROGUE_T6xxx is not set # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_HDMI=y CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set # CONFIG_FB_DDC is not set @@ -2219,37 +2327,61 @@ CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -# CONFIG_FB_SYS_FILLRECT is not set -# CONFIG_FB_SYS_COPYAREA is not set -# CONFIG_FB_SYS_IMAGEBLIT is not set +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_IMAGEBLIT=m # CONFIG_FB_FOREIGN_ENDIAN is not set -# CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set +CONFIG_FB_SYS_FOPS=m +CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set -CONFIG_FB_MODE_HELPERS=y -CONFIG_FB_TILEBLITTING=y +CONFIG_FB_BACKLIGHT=y +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set # # Frame buffer hardware drivers # - -# -# Video support for sunxi -# -CONFIG_FB_SUNXI=y -CONFIG_FB_CONSOLE_SUNXI=y -CONFIG_LCD_SUNXI=y -CONFIG_HDMI_SUNXI=y +# CONFIG_FB_ARMHDLCD is not set # CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_TMIO is not set # CONFIG_FB_SMSCUFX is not set # CONFIG_FB_UDL is not set +# CONFIG_FB_GOLDFISH is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set # CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set # CONFIG_EXYNOS_VIDEO is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +CONFIG_VIDEO_OWL=y +CONFIG_VIDEO_ACTIONS_VCE=y +CONFIG_VIDEO_ACTIONS_VDE=y +CONFIG_VIDEO_OWL_PWM_BACKLIGHT=y +CONFIG_VIDEO_OWL_DSS=y +CONFIG_VIDEO_OWL_DE_ATM7059=y +# CONFIG_VIDEO_OWL_DE_ATM9009 is not set +CONFIG_VIDEO_OWL_MMU_SUPPORT=y +CONFIG_VIDEO_OWL_MMU_ION_SUPPORT=y +CONFIG_VIDEO_OWL_LCDC=y +CONFIG_VIDEO_OWL_DSI=y +CONFIG_VIDEO_OWL_NO_DVI=y +CONFIG_VIDEO_OWL_HDMI=y +CONFIG_FB_COLOR_MODE_XRGB32=y +CONFIG_FB_MAP_TO_DE=y +CONFIG_FB_DEFAULT_MIRROR_TO_HDMI=y +CONFIG_VIDEO_OWL_FB=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_GENERIC is not set +# CONFIG_BACKLIGHT_PWM is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3630 is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_ADF is not set # # Console display driver support @@ -2258,27 +2390,22 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y -CONFIG_FONTS=y +# CONFIG_FONTS is not set CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y -CONFIG_FONT_6x11=y -CONFIG_FONT_7x14=y -CONFIG_FONT_PEARL_8x8=y -CONFIG_FONT_ACORN_8x8=y -CONFIG_FONT_MINI_4x6=y -CONFIG_FONT_SUN8x16=y -CONFIG_FONT_SUN12x22=y -CONFIG_FONT_10x18=y CONFIG_LOGO=y CONFIG_LOGO_LINUX_MONO=y CONFIG_LOGO_LINUX_VGA16=y CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_LOGO_ACTIONS_CLUT224 is not set +# CONFIG_FB_SSD1307 is not set CONFIG_SOUND=y # CONFIG_SOUND_OSS_CORE is not set CONFIG_SND=y CONFIG_SND_TIMER=y CONFIG_SND_PCM=y CONFIG_SND_RAWMIDI=y +CONFIG_SND_COMPRESS_OFFLOAD=y CONFIG_SND_JACK=y # CONFIG_SND_SEQUENCER is not set # CONFIG_SND_MIXER_OSS is not set @@ -2308,27 +2435,27 @@ CONFIG_SND_USB=y # CONFIG_SND_USB_CAIAQ is not set # CONFIG_SND_USB_6FIRE is not set CONFIG_SND_SOC=y -CONFIG_SND_SOC_DMAENGINE_PCM=y -CONFIG_SND_SUNXI_SOC_DAUDIO_INTERFACE=y -CONFIG_SND_SUNXI_SOC_HDMIAUDIO=y -# CONFIG_SND_SUNXI_SOC_SPDIF is not set -# CONFIG_SND_SUNXI_SOC_VIRTUAL_AUDIO_INTERFACE is not set +CONFIG_SND_SOC_OWL=y +CONFIG_SND_SOC_ATC2603A=y +CONFIG_SND_SOC_ATC2603C=y +CONFIG_SND_SOC_HDMI_OWL=y +CONFIG_SND_SOC_DAI_OWL=y +CONFIG_SND_SOC_ALL_PMU_OWL=y +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_DESIGNWARE_I2S is not set CONFIG_SND_SOC_I2C_AND_SPI=y -CONFIG_SND_SOC_AC100_CODEC=y +# CONFIG_SND_SOC_ALL_CODECS is not set +# CONFIG_SND_SIMPLE_CARD is not set # CONFIG_SOUND_PRIME is not set -CONFIG_HID_SUPPORT=y + +# +# HID support +# CONFIG_HID=y # CONFIG_HID_BATTERY_STRENGTH is not set CONFIG_HIDRAW=y CONFIG_UHID=y - -# -# USB Input Devices -# -CONFIG_USB_HID=y -CONFIG_HID_REMOTE_WAKEUP=y -CONFIG_HID_PID=y -CONFIG_USB_HIDDEV=y +CONFIG_HID_GENERIC=y # # Special HID drivers @@ -2337,6 +2464,8 @@ CONFIG_HID_A4TECH=y CONFIG_HID_ACRUX=y CONFIG_HID_ACRUX_FF=y CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y CONFIG_HID_CHICONY=y @@ -2348,15 +2477,17 @@ CONFIG_HID_EMS_FF=y CONFIG_HID_ELECOM=y CONFIG_HID_EZKEY=y CONFIG_HID_HOLTEK=y -CONFIG_HOLTEK_FF=y +# CONFIG_HOLTEK_FF is not set CONFIG_HID_KEYTOUCH=y CONFIG_HID_KYE=y CONFIG_HID_UCLOGIC=y CONFIG_HID_WALTOP=y CONFIG_HID_GYRATION=y +# CONFIG_HID_ICADE is not set CONFIG_HID_TWINHAN=y CONFIG_HID_KENSINGTON=y CONFIG_HID_LCPOWER=y +# CONFIG_HID_LENOVO_TPKBD is not set CONFIG_HID_LOGITECH=y CONFIG_HID_LOGITECH_DJ=y CONFIG_LOGITECH_FF=y @@ -2374,13 +2505,16 @@ CONFIG_PANTHERLORD_FF=y CONFIG_HID_PETALYNX=y CONFIG_HID_PICOLCD=y # CONFIG_HID_PICOLCD_FB is not set +# CONFIG_HID_PICOLCD_BACKLIGHT is not set # CONFIG_HID_PICOLCD_LEDS is not set CONFIG_HID_PRIMAX=y +# CONFIG_HID_PS3REMOTE is not set CONFIG_HID_ROCCAT=y CONFIG_HID_SAITEK=y CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y CONFIG_HID_SPEEDLINK=y +# CONFIG_HID_STEELSERIES is not set CONFIG_HID_SUNPLUS=y CONFIG_HID_GREENASIA=y CONFIG_GREENASIA_FF=y @@ -2388,38 +2522,49 @@ CONFIG_HID_SMARTJOYPLUS=y CONFIG_SMARTJOYPLUS_FF=y CONFIG_HID_TIVO=y CONFIG_HID_TOPSEED=y +# CONFIG_HID_THINGM is not set CONFIG_HID_THRUSTMASTER=y -CONFIG_THRUSTMASTER_FF=y +# CONFIG_THRUSTMASTER_FF is not set CONFIG_HID_WACOM=y -CONFIG_HID_WACOM_POWER_SUPPLY=y CONFIG_HID_WIIMOTE=y CONFIG_HID_WIIMOTE_EXT=y CONFIG_HID_ZEROPLUS=y -CONFIG_ZEROPLUS_FF=y +# CONFIG_ZEROPLUS_FF is not set CONFIG_HID_ZYDACRON=y -CONFIG_USB_ARCH_HAS_OHCI=y -CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_HID_SENSOR_HUB is not set + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +CONFIG_USB_HIDDEV=y + +# +# I2C HID support +# +# CONFIG_I2C_HID is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set CONFIG_USB_ARCH_HAS_XHCI=y CONFIG_USB_SUPPORT=y CONFIG_USB_COMMON=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB=y -# CONFIG_USB_DEBUG is not set -# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +CONFIG_USB_DEBUG=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y # # Miscellaneous USB options # -# CONFIG_USB_DEVICEFS is not set -CONFIG_USB_DEVICE_CLASS=y +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_SUSPEND is not set +CONFIG_USB_OTG=y # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set -CONFIG_USB_SUNXI=y -# CONFIG_USB_SUNXI_DEBUG is not set -# CONFIG_USB_MON is not set +CONFIG_USB_MON=y +CONFIG_USB_ACTIONS_MON=y +CONFIG_USB_PLATFORM_LINUX=y # CONFIG_USB_WUSB_CBAF is not set # @@ -2429,41 +2574,22 @@ CONFIG_USB_SUNXI=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_PLATFORM=y # CONFIG_USB_XHCI_HCD_DEBUGGING is not set -CONFIG_USB_EHCI_HCD=y -# CONFIG_USB_EHCI_ROOT_HUB_TT is not set -CONFIG_USB_EHCI_TT_NEWSCHED=y # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_ISP1362_HCD is not set -CONFIG_USB_OHCI_HCD=y -# CONFIG_USB_OHCI_HCD_PLATFORM is not set -# CONFIG_USB_EHCI_HCD_PLATFORM is not set -# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set -CONFIG_USB_SUNXI_HCD=y -# CONFIG_USB_SUNXI_HCD0 is not set -CONFIG_USB_SUNXI_HCI=y -CONFIG_USB_SUNXI_EHCI0=y -CONFIG_USB_SUNXI_EHCI1=y -CONFIG_USB_SUNXI_OHCI0=y -# CONFIG_USB_SUNXI_OHCI1 is not set -CONFIG_USB_SUNXI_EHCI2=y -CONFIG_USB_SUNXI_OHCI2=y -# CONFIG_USB_SUNXI_HSIC is not set -# CONFIG_SW_USB_3G is not set +CONFIG_USB_AOTG_HCD=y # CONFIG_USB_MUSB_HDRC is not set # CONFIG_USB_RENESAS_USBHS is not set # # USB Device Class drivers # -# CONFIG_USB_ACM is not set +CONFIG_USB_ACM=y # CONFIG_USB_PRINTER is not set -# CONFIG_USB_WDM is not set +CONFIG_USB_WDM=m # CONFIG_USB_TMC is not set # @@ -2475,85 +2601,93 @@ CONFIG_USB_SUNXI_OHCI2=y # CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_REALTEK=y -CONFIG_REALTEK_AUTOPM=y -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_USBAT=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_STORAGE_ALAUDA=y -CONFIG_USB_STORAGE_ONETOUCH=y -CONFIG_USB_STORAGE_KARMA=y -CONFIG_USB_STORAGE_CYPRESS_ATACB=y -CONFIG_USB_STORAGE_ENE_UB6250=y -# CONFIG_USB_LIBUSUAL is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set # # USB Imaging devices # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_HOST is not set +# CONFIG_USB_DWC3_GADGET is not set +CONFIG_USB_DWC3_DUAL_ROLE=y +# CONFIG_USB_DWC3_DEBUG is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers # CONFIG_USB_SERIAL=y -# CONFIG_USB_SERIAL_CONSOLE is not set -# CONFIG_USB_EZUSB is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_AIRCABLE is not set -# CONFIG_USB_SERIAL_ARK3116 is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_CH341 is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_CP210X is not set -# CONFIG_USB_SERIAL_CYPRESS_M8 is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_FUNSOFT is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_IPAQ is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_EDGEPORT_TI is not set -# CONFIG_USB_SERIAL_F81232 is not set -# CONFIG_USB_SERIAL_GARMIN is not set -# CONFIG_USB_SERIAL_IPW is not set -# CONFIG_USB_SERIAL_IUU is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +CONFIG_USB_SERIAL_CONSOLE=y +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F81232=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m # CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KLSI is not set -# CONFIG_USB_SERIAL_KOBIL_SCT is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_METRO is not set -# CONFIG_USB_SERIAL_MOS7720 is not set -# CONFIG_USB_SERIAL_MOS7840 is not set -# CONFIG_USB_SERIAL_MOTOROLA is not set -# CONFIG_USB_SERIAL_NAVMAN is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_OTI6858 is not set -# CONFIG_USB_SERIAL_QCAUX is not set -# CONFIG_USB_SERIAL_QUALCOMM is not set -# CONFIG_USB_SERIAL_SPCP8X5 is not set -# CONFIG_USB_SERIAL_HP4X is not set -# CONFIG_USB_SERIAL_SAFE is not set -# CONFIG_USB_SERIAL_SIEMENS_MPI is not set -# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set -# CONFIG_USB_SERIAL_SYMBOL is not set -# CONFIG_USB_SERIAL_TI is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_XIRCOM is not set +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MOTOROLA=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIEMENS_MPI=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m CONFIG_USB_SERIAL_WWAN=y CONFIG_USB_SERIAL_OPTION=y -# CONFIG_USB_SERIAL_OMNINET is not set -# CONFIG_USB_SERIAL_OPTICON is not set -# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set -# CONFIG_USB_SERIAL_ZIO is not set -# CONFIG_USB_SERIAL_SSU100 is not set +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m +CONFIG_USB_SERIAL_XSENS_MT=m +CONFIG_USB_SERIAL_ZIO=m +CONFIG_USB_SERIAL_WISHBONE=m +CONFIG_USB_SERIAL_ZTE=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m # CONFIG_USB_SERIAL_DEBUG is not set # @@ -2572,76 +2706,69 @@ CONFIG_USB_SERIAL_OPTION=y # CONFIG_USB_IDMOUSE is not set # CONFIG_USB_FTDI_ELAN is not set # CONFIG_USB_APPLEDISPLAY is not set -# CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TRANCEVIBRATOR is not set # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_YUREX is not set +CONFIG_USB_EZUSB_FX2=m +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_PHY is not set +# CONFIG_USB_OTG_WAKELOCK is not set CONFIG_USB_GADGET=y # CONFIG_USB_GADGET_DEBUG is not set # CONFIG_USB_GADGET_DEBUG_FILES is not set # CONFIG_USB_GADGET_DEBUG_FS is not set CONFIG_USB_GADGET_VBUS_DRAW=2 CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# # CONFIG_USB_FUSB300 is not set # CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set # CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MV_U3D is not set # CONFIG_USB_M66592 is not set # CONFIG_USB_NET2272 is not set # CONFIG_USB_DUMMY_HCD is not set -# CONFIG_USB_SUNXI_UDC0 is not set CONFIG_USB_GADGET_DUALSPEED=y -CONFIG_USB_GADGET_SUPERSPEED=y +CONFIG_USB_LIBCOMPOSITE=y # CONFIG_USB_ZERO is not set # CONFIG_USB_AUDIO is not set # CONFIG_USB_ETH is not set # CONFIG_USB_G_NCM is not set # CONFIG_USB_GADGETFS is not set # CONFIG_USB_FUNCTIONFS is not set -# CONFIG_USB_FILE_STORAGE is not set # CONFIG_USB_MASS_STORAGE is not set # CONFIG_USB_G_SERIAL is not set # CONFIG_USB_MIDI_GADGET is not set # CONFIG_USB_G_PRINTER is not set -CONFIG_USB_G_ANDROID=y +# CONFIG_USB_G_ANDROID is not set # CONFIG_USB_CDC_COMPOSITE is not set # CONFIG_USB_G_ACM_MS is not set # CONFIG_USB_G_MULTI is not set # CONFIG_USB_G_HID is not set # CONFIG_USB_G_DBGP is not set # CONFIG_USB_G_WEBCAM is not set - -# -# OTG and related infrastructure -# -CONFIG_USB_OTG_UTILS=y -CONFIG_USB_OTG_WAKELOCK=y -# CONFIG_USB_GPIO_VBUS is not set -# CONFIG_USB_ULPI is not set -# CONFIG_NOP_USB_XCEIV is not set -CONFIG_USB_SUNXI_USB=y -CONFIG_USB_SUNXI_USB_MANAGER=y -# CONFIG_USB_SUNXI_USB0_NULL is not set -# CONFIG_USB_SUNXI_USB0_DEVICE_ONLY is not set -# CONFIG_USB_SUNXI_USB0_HOST_ONLY is not set -CONFIG_USB_SUNXI_USB0_OTG=y -CONFIG_USB_SUNXI_USB_DEBUG=y -# CONFIG_USB_SUNXI_HOST is not set +CONFIG_USB_ACTIONS_ADFUSERVER=y CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set CONFIG_MMC_UNSAFE_RESUME=y # CONFIG_MMC_CLKGATE is not set # CONFIG_MMC_EMBEDDED_SDIO is not set -CONFIG_MMC_PARANOID_SD_INIT=y +# CONFIG_MMC_PARANOID_SD_INIT is not set # # MMC/SD/SDIO Card Drivers # CONFIG_MMC_BLOCK=y +# CONFIG_TSD_MMC_BLOCK is not set +# CONFIG_CARD_TO_CARD_MMC_BLOCK is not set CONFIG_MMC_BLOCK_MINORS=16 -# CONFIG_MMC_BLOCK_BOUNCE is not set +CONFIG_MMC_BLOCK_BOUNCE=y # CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set # CONFIG_SDIO_UART is not set # CONFIG_MMC_TEST is not set @@ -2652,10 +2779,8 @@ CONFIG_MMC_BLOCK_MINORS=16 # CONFIG_MMC_SDHCI is not set # CONFIG_MMC_SDHCI_PXAV3 is not set # CONFIG_MMC_SDHCI_PXAV2 is not set +CONFIG_MMC_OWL=y # CONFIG_MMC_DW is not set -CONFIG_MMC_SUNXI=y -CONFIG_MMC_DEBUG_SUNXI=y -CONFIG_MMC_PRE_DBGLVL_SUNXI=0 # CONFIG_MMC_VUB300 is not set # CONFIG_MMC_USHC is not set # CONFIG_MEMSTICK is not set @@ -2666,42 +2791,51 @@ CONFIG_LEDS_CLASS=y # LED drivers # # CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set # CONFIG_LEDS_PCA9532 is not set -# CONFIG_LEDS_GPIO is not set +CONFIG_LEDS_GPIO=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set # CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_PWM is not set # CONFIG_LEDS_REGULATOR is not set # CONFIG_LEDS_BD2802 is not set # CONFIG_LEDS_LT3593 is not set # CONFIG_LEDS_RENESAS_TPU is not set # CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set -CONFIG_LEDS_SUNXI=y -CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_BLINKM is not set # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_LEDS_TRIGGER_BACKLIGHT=y -CONFIG_LEDS_TRIGGER_GPIO=y -CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -CONFIG_LEDS_TRIGGER_SLEEP=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set CONFIG_LEDS_TRIGGER_CPU=y +# CONFIG_LEDS_TRIGGER_GPIO is not set +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y # # iptables trigger is under Netfilter config (LED target) # -# CONFIG_SWITCH is not set +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +CONFIG_SWITCH=y +CONFIG_SWITCH_GPIO=y # CONFIG_ACCESSIBILITY is not set +# CONFIG_EDAC is not set CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_SYSTOHC=y CONFIG_RTC_HCTOSYS_DEVICE="rtc0" # CONFIG_RTC_DEBUG is not set @@ -2726,6 +2860,7 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_ISL1208 is not set # CONFIG_RTC_DRV_ISL12022 is not set # CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8523 is not set # CONFIG_RTC_DRV_PCF8563 is not set # CONFIG_RTC_DRV_PCF8583 is not set # CONFIG_RTC_DRV_M41T80 is not set @@ -2749,6 +2884,7 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_RS5C348 is not set # CONFIG_RTC_DRV_DS3234 is not set # CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_RX4581 is not set # # Platform RTC drivers @@ -2766,37 +2902,42 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_BQ4802 is not set # CONFIG_RTC_DRV_RP5C01 is not set # CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_DS2404 is not set +CONFIG_RTC_DRV_ATC206X=y # # on-CPU RTC drivers # -CONFIG_RTC_DRV_SUNXI=y +# CONFIG_RTC_DRV_SNVS is not set + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set CONFIG_DMADEVICES=y # CONFIG_DMADEVICES_DEBUG is not set # # DMA Devices # +CONFIG_OWL_DMAC=y # CONFIG_DW_DMAC is not set # CONFIG_TIMB_DMA is not set CONFIG_DMA_ENGINE=y -CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DMA_OF=y # # DMA Clients # -# CONFIG_NET_DMA is not set # CONFIG_ASYNC_TX_DMA is not set -CONFIG_SUNXI_DMA=y -CONFIG_SUNXI_RDMA=y # CONFIG_DMATEST is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers # -# CONFIG_VIRTIO_BALLOON is not set # CONFIG_VIRTIO_MMIO is not set # @@ -2804,8 +2945,10 @@ CONFIG_SUNXI_RDMA=y # CONFIG_STAGING=y # CONFIG_USBIP_CORE is not set +# CONFIG_W35UND is not set # CONFIG_PRISM2_USB is not set # CONFIG_ECHO is not set +# CONFIG_COMEDI is not set # CONFIG_ASUS_OLED is not set # CONFIG_RTLLIB is not set # CONFIG_R8712U is not set @@ -2813,15 +2956,11 @@ CONFIG_STAGING=y # CONFIG_TRANZPORT is not set # CONFIG_LINE6_USB is not set # CONFIG_USB_SERIAL_QUATECH2 is not set -# CONFIG_USB_SERIAL_QUATECH_USB2 is not set # CONFIG_VT6656 is not set -CONFIG_IIO=y -CONFIG_IIO_ST_HWMON=y -CONFIG_IIO_BUFFER=y -CONFIG_IIO_SW_RING=y -CONFIG_IIO_KFIFO_BUF=y -CONFIG_IIO_TRIGGER=y -CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 + +# +# IIO staging drivers +# # # Accelerometers @@ -2832,7 +2971,6 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # CONFIG_ADIS16209 is not set # CONFIG_ADIS16220 is not set # CONFIG_ADIS16240 is not set -# CONFIG_KXSD9 is not set # CONFIG_LIS3L02DQ is not set # CONFIG_SCA3000 is not set @@ -2840,19 +2978,12 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # Analog to digital converters # # CONFIG_AD7291 is not set -# CONFIG_AD7298 is not set # CONFIG_AD7606 is not set # CONFIG_AD799X is not set -# CONFIG_AD7476 is not set -# CONFIG_AD7887 is not set # CONFIG_AD7780 is not set -# CONFIG_AD7793 is not set # CONFIG_AD7816 is not set # CONFIG_AD7192 is not set -# CONFIG_ADT7310 is not set -# CONFIG_ADT7410 is not set # CONFIG_AD7280 is not set -# CONFIG_MAX1363 is not set # # Analog digital bi-direction converters @@ -2866,21 +2997,6 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # CONFIG_AD7152 is not set # CONFIG_AD7746 is not set -# -# Digital to analog converters -# -# CONFIG_AD5064 is not set -# CONFIG_AD5360 is not set -# CONFIG_AD5380 is not set -# CONFIG_AD5421 is not set -# CONFIG_AD5624R_SPI is not set -# CONFIG_AD5446 is not set -# CONFIG_AD5504 is not set -# CONFIG_AD5764 is not set -# CONFIG_AD5791 is not set -# CONFIG_AD5686 is not set -# CONFIG_MAX517 is not set - # # Direct Digital Synthesis # @@ -2896,27 +3012,21 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # Digital gyroscope sensors # # CONFIG_ADIS16060 is not set -# CONFIG_ADIS16080 is not set # CONFIG_ADIS16130 is not set # CONFIG_ADIS16260 is not set -# CONFIG_ADXRS450 is not set # # Network Analyzer, Impedance Converters # # CONFIG_AD5933 is not set -# -# Inertial measurement units -# -# CONFIG_ADIS16400 is not set - # # Light sensors # # CONFIG_SENSORS_ISL29018 is not set -# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_SENSORS_ISL29028 is not set # CONFIG_TSL2583 is not set +# CONFIG_TSL2x7x is not set # # Magnetometer sensors @@ -2945,16 +3055,10 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set # CONFIG_IIO_GPIO_TRIGGER is not set # CONFIG_IIO_SYSFS_TRIGGER is not set -CONFIG_INV_SENSORS=y -CONFIG_INV_MPU5400_IIO=m -# CONFIG_INV_SENSORS_MPU65XX is not set -CONFIG_INV_SENSORS_MPU5400=y -CONFIG_INV_SENSORS_DMP=y -CONFIG_INV_SENSORS_DMP_K520S=y -# CONFIG_INV_SENSORS_DBG is not set -# CONFIG_INV_SENSORS_DTS_SUPPORT is not set # CONFIG_IIO_SIMPLE_DUMMY is not set -# CONFIG_FB_SM7XX is not set +CONFIG_ZSMALLOC=y +CONFIG_ZRAM=y +# CONFIG_ZRAM_DEBUG is not set # CONFIG_USB_ENESTORAGE is not set # CONFIG_BCM_WIMAX is not set # CONFIG_FT1000 is not set @@ -2971,20 +3075,29 @@ CONFIG_INV_SENSORS_DMP_K520S=y # Android # CONFIG_ANDROID=y -# CONFIG_ANDROID_BINDER_IPC is not set -# CONFIG_ASHMEM is not set -# CONFIG_ANDROID_LOGGER is not set -# CONFIG_ANDROID_RAM_CONSOLE is not set -# CONFIG_PERSISTENT_TRACER is not set +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDER_IPC_32BIT=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOGGER=y CONFIG_ANDROID_TIMED_OUTPUT=y -# CONFIG_ANDROID_TIMED_GPIO is not set -# CONFIG_ANDROID_LOW_MEMORY_KILLER is not set -CONFIG_ANDROID_SWITCH=y -# CONFIG_SWITCH_HEADSET is not set -# CONFIG_ANDROID_SWITCH_GPIO is not set -# CONFIG_ANDROID_INTF_ALARM_DEV is not set -# CONFIG_PHONE is not set +CONFIG_ANDROID_TIMED_GPIO=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y +# CONFIG_ANDROID_SWITCH is not set +CONFIG_ANDROID_INTF_ALARM_DEV=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +CONFIG_SW_SYNC_USER=y +CONFIG_ION=y +# CONFIG_ION_TEST is not set +# CONFIG_ION_DUMMY is not set +CONFIG_ION_OWL=y # CONFIG_USB_WPAN_HCD is not set +# CONFIG_WIMAX_GDM72XX is not set +# CONFIG_CSR_WIFI is not set +# CONFIG_CED1401 is not set +# CONFIG_DGRP is not set +# CONFIG_USB_DWC2 is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_COMMON_CLK=y @@ -2992,71 +3105,148 @@ CONFIG_COMMON_CLK=y # # Common Clock Framework # -# CONFIG_COMMON_CLK_DISABLE_UNUSED is not set -# CONFIG_COMMON_CLK_ENABLE_SYNCBOOT is not set -CONFIG_COMMON_CLK_DEBUG=y - -# -# SUNXI Clock Configuration -# -CONFIG_SUNXI_CLK_DEFAULT_INIT=y -CONFIG_SUNXI_CLK_AHB_FROM_PLL6=y -CONFIG_SUNXI_AC100_CLK=y +# CONFIG_COMMON_CLK_DEBUG is not set +# CONFIG_COMMON_CLK_SI5351 is not set # # Hardware Spinlock drivers # -CONFIG_CLKSRC_MMIO=y -CONFIG_SUNXI_TIMER=y -# CONFIG_IOMMU_SUPPORT is not set +CONFIG_CLKSRC_OF=y +# CONFIG_MAILBOX is not set +CONFIG_IOMMU_SUPPORT=y +CONFIG_OF_IOMMU=y # -# Remoteproc drivers (EXPERIMENTAL) +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +# CONFIG_IIO_BUFFER_CB is not set +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 + +# +# Accelerometers +# +# CONFIG_KXSD9 is not set +# CONFIG_IIO_ST_ACCEL_3AXIS is not set + +# +# Analog to digital converters +# +# CONFIG_AD7266 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7923 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7887 is not set +# CONFIG_EXYNOS_ADC is not set +# CONFIG_MAX1363 is not set +# CONFIG_TI_ADC081C is not set + +# +# Amplifiers +# +# CONFIG_AD8366 is not set + +# +# Hid Sensor IIO Common # # -# Rpmsg drivers (EXPERIMENTAL) +# Digital to analog converters # -# CONFIG_VIRT_DRIVERS is not set -CONFIG_PM_DEVFREQ=y +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD5686 is not set +# CONFIG_MAX517 is not set +# CONFIG_MCP4725 is not set # -# DEVFREQ Governors +# Frequency Synthesizers DDS/PLL # -# CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND is not set -# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set -# CONFIG_DEVFREQ_GOV_POWERSAVE is not set -# CONFIG_DEVFREQ_GOV_USERSPACE is not set -CONFIG_DEVFREQ_GOV_DSM=y # -# DEVFREQ Drivers +# Clock Generator/Distribution # -CONFIG_DEVFREQ_DRAM_FREQ=y -CONFIG_DEVFREQ_DRAM_FREQ_BUSFREQ=y -CONFIG_DEVFREQ_DRAM_FREQ_VDDSYS=y -CONFIG_DEVFREQ_DRAM_FREQ_IN_VSYNC=y -# CONFIG_GATOR_PERF is not set +# CONFIG_AD9523 is not set + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +# CONFIG_ADF4350 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADXRS450 is not set +# CONFIG_IIO_ST_GYRO_3AXIS is not set +# CONFIG_ITG3200 is not set +CONFIG_IIO_INV_MPU6515=m + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_INV_MPU6050_IIO is not set + +# +# Light sensors +# +# CONFIG_ADJD_S311 is not set +# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_VCNL4000 is not set + +# +# Magnetometer sensors +# +# CONFIG_AK8975 is not set +# CONFIG_IIO_ST_MAGN_3AXIS is not set +CONFIG_PWM=y +CONFIG_PWM_OWL=y +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +# CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # File systems # +CONFIG_DCACHE_WORD_ACCESS=y CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -CONFIG_EXT2_FS_XIP=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y CONFIG_EXT3_DEFAULTS_TO_ORDERED=y CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_SECURITY is not set CONFIG_EXT4_FS=y -CONFIG_EXT4_FS_XATTR=y # CONFIG_EXT4_FS_POSIX_ACL is not set CONFIG_EXT4_FS_SECURITY=y # CONFIG_EXT4_DEBUG is not set -CONFIG_FS_XIP=y CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_JBD2=y @@ -3064,12 +3254,9 @@ CONFIG_JBD2=y CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set -CONFIG_XFS_FS=y -# CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_POSIX_ACL is not set -# CONFIG_XFS_RT is not set -# CONFIG_XFS_DEBUG is not set +# CONFIG_XFS_FS is not set # CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set # CONFIG_NILFS2_FS is not set CONFIG_FS_POSIX_ACL=y @@ -3078,35 +3265,24 @@ CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y CONFIG_INOTIFY_USER=y -CONFIG_FANOTIFY=y -# CONFIG_FANOTIFY_ACCESS_PERMISSIONS is not set +# CONFIG_FANOTIFY is not set # CONFIG_QUOTA is not set # CONFIG_QUOTACTL is not set CONFIG_AUTOFS4_FS=y CONFIG_FUSE_FS=y -CONFIG_CUSE=y +# CONFIG_CUSE is not set CONFIG_GENERIC_ACL=y # # Caches # -CONFIG_FSCACHE=y -CONFIG_FSCACHE_STATS=y -# CONFIG_FSCACHE_HISTOGRAM is not set -# CONFIG_FSCACHE_DEBUG is not set -# CONFIG_FSCACHE_OBJECT_LIST is not set -CONFIG_CACHEFILES=y -# CONFIG_CACHEFILES_DEBUG is not set -# CONFIG_CACHEFILES_HISTOGRAM is not set +# CONFIG_FSCACHE is not set # # CD-ROM/DVD Filesystems # -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_UDF_FS=y -CONFIG_UDF_NLS=y +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set # # DOS/FAT/NT Filesystems @@ -3115,7 +3291,7 @@ CONFIG_FAT_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_NTFS_FS=y # CONFIG_NTFS_DEBUG is not set CONFIG_NTFS_RW=y @@ -3131,7 +3307,7 @@ CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_TMPFS_XATTR=y # CONFIG_HUGETLB_PAGE is not set -# CONFIG_CONFIGFS_FS is not set +CONFIG_CONFIGFS_FS=y CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set @@ -3141,7 +3317,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_LOGFS is not set -CONFIG_CRAMFS=y +# CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set @@ -3150,17 +3326,23 @@ CONFIG_CRAMFS=y # CONFIG_QNX4FS_FS is not set # CONFIG_QNX6FS_FS is not set # CONFIG_ROMFS_FS is not set -# CONFIG_PSTORE is not set +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_RAM=y # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set +# CONFIG_F2FS_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set +CONFIG_NFS_V2=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set +# CONFIG_NFS_SWAP is not set # CONFIG_ROOT_NFS is not set -# CONFIG_NFS_FSCACHE is not set # CONFIG_NFSD is not set CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y # CONFIG_SUNRPC_DEBUG is not set @@ -3169,8 +3351,9 @@ CONFIG_CIFS=y # CONFIG_CIFS_STATS is not set # CONFIG_CIFS_WEAK_PW_HASH is not set # CONFIG_CIFS_XATTR is not set +CONFIG_CIFS_DEBUG=y # CONFIG_CIFS_DEBUG2 is not set -# CONFIG_CIFS_FSCACHE is not set +# CONFIG_CIFS_SMB2 is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set @@ -3192,14 +3375,14 @@ CONFIG_NLS_CODEPAGE_437=y # CONFIG_NLS_CODEPAGE_866 is not set # CONFIG_NLS_CODEPAGE_869 is not set CONFIG_NLS_CODEPAGE_936=y -CONFIG_NLS_CODEPAGE_950=y +# CONFIG_NLS_CODEPAGE_950 is not set # CONFIG_NLS_CODEPAGE_932 is not set # CONFIG_NLS_CODEPAGE_949 is not set # CONFIG_NLS_CODEPAGE_874 is not set # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set -CONFIG_NLS_ASCII=y +# CONFIG_NLS_ASCII is not set CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set @@ -3213,18 +3396,32 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_ISO8859_15 is not set # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set +# CONFIG_DEBUG_READDUMP is not set # # Kernel hacking # CONFIG_PRINTK_TIME=y CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y # CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set @@ -3232,41 +3429,39 @@ CONFIG_DEBUG_FS=y CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set # CONFIG_LOCKUP_DETECTOR is not set -# CONFIG_HARDLOCKUP_DETECTOR_NMI is not set -# CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU is not set -# CONFIG_HARDLOCKUP_DETECTOR is not set -# CONFIG_DETECT_HUNG_TASK is not set -# CONFIG_SCHED_DEBUG is not set -# CONFIG_SCHEDSTATS is not set -# CONFIG_TIMER_STATS is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y # CONFIG_DEBUG_OBJECTS is not set -CONFIG_DEBUG_SLAB=y -# CONFIG_DEBUG_SLAB_LEAK is not set -# CONFIG_DEBUG_KMEMLEAK is not set -# CONFIG_DEBUG_PREEMPT is not set -CONFIG_DEBUG_RT_MUTEXES=y -CONFIG_DEBUG_PI_LIST=y +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=800 +# CONFIG_DEBUG_KMEMLEAK_TEST is not set +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set -CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_SPINLOCK is not set CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_LOCK_ALLOC=y -CONFIG_PROVE_LOCKING=y -CONFIG_PROVE_RCU=y -CONFIG_PROVE_RCU_REPEATEDLY=y -# CONFIG_SPARSE_RCU_POINTER is not set -CONFIG_LOCKDEP=y -CONFIG_LOCK_STAT=y -CONFIG_DEBUG_LOCKDEP=y -CONFIG_TRACE_IRQFLAGS=y -CONFIG_DEBUG_ATOMIC_SLEEP=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set CONFIG_STACKTRACE=y -CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_HIGHMEM is not set CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_INFO_REDUCED=y +# CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_WRITECOUNT is not set # CONFIG_DEBUG_MEMORY_INIT is not set @@ -3275,8 +3470,13 @@ CONFIG_DEBUG_INFO_REDUCED=y # CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_NOTIFIERS is not set # CONFIG_DEBUG_CREDENTIALS is not set -CONFIG_FRAME_POINTER=y # CONFIG_BOOT_PRINTK_DELAY is not set + +# +# RCU Debugging +# +# CONFIG_PROVE_RCU_DELAY is not set +# CONFIG_SPARSE_RCU_POINTER is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_RCU_CPU_STALL_TIMEOUT=60 CONFIG_RCU_CPU_STALL_VERBOSE=y @@ -3287,58 +3487,60 @@ CONFIG_RCU_CPU_STALL_VERBOSE=y # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set # CONFIG_DEBUG_PER_CPU_MAPS is not set # CONFIG_LKDTM is not set -# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set -# CONFIG_DEBUG_PAGEALLOC is not set CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_HAVE_C_RECORDMCOUNT=y -CONFIG_TRACER_MAX_TRACE=y +CONFIG_TRACE_CLOCK=y CONFIG_RING_BUFFER=y CONFIG_EVENT_TRACING=y -# CONFIG_EVENT_POWER_TRACING_DEPRECATED is not set CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_TRACING=y CONFIG_GENERIC_TRACER=y CONFIG_TRACING_SUPPORT=y CONFIG_FTRACE=y -CONFIG_FUNCTION_TRACER=y -CONFIG_FUNCTION_GRAPH_TRACER=y +# CONFIG_FUNCTION_TRACER is not set # CONFIG_IRQSOFF_TRACER is not set # CONFIG_PREEMPT_TRACER is not set -CONFIG_SCHED_TRACER=y +# CONFIG_SCHED_TRACER is not set +# CONFIG_FTRACE_SYSCALLS is not set +# CONFIG_TRACER_SNAPSHOT is not set CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set -CONFIG_STACK_TRACER=y +# CONFIG_STACK_TRACER is not set CONFIG_BLK_DEV_IO_TRACE=y -CONFIG_DYNAMIC_FTRACE=y -CONFIG_FUNCTION_PROFILER=y -CONFIG_FTRACE_MCOUNT_RECORD=y +# CONFIG_PROBE_EVENTS is not set # CONFIG_FTRACE_STARTUP_TEST is not set # CONFIG_RING_BUFFER_BENCHMARK is not set -# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_RING_BUFFER_STARTUP_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +CONFIG_DYNAMIC_DEBUG=y # CONFIG_DMA_API_DEBUG is not set # CONFIG_ATOMIC64_SELFTEST is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set # CONFIG_STRICT_DEVMEM is not set CONFIG_ARM_UNWIND=y -CONFIG_OLD_MCOUNT=y -CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_RODATA is not set CONFIG_DEBUG_LL=y -CONFIG_DEBUG_SUNXI_UART0=y -# CONFIG_DEBUG_SUNXI_UART1 is not set -# CONFIG_DEBUG_LL_UART_NONE is not set +CONFIG_DEBUG_LL_UART_NONE=y # CONFIG_DEBUG_ICEDCC is not set # CONFIG_DEBUG_SEMIHOSTING is not set +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +CONFIG_UNCOMPRESS_INCLUDE="mach/uncompress.h" CONFIG_EARLY_PRINTK=y +# CONFIG_PID_IN_CONTEXTIDR is not set # # Security options @@ -3352,7 +3554,8 @@ CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_PATH=y CONFIG_LSM_MMAP_MIN_ADDR=32768 CONFIG_SECURITY_SELINUX=y -# CONFIG_SECURITY_SELINUX_BOOTPARAM is not set +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 # CONFIG_SECURITY_SELINUX_DISABLE is not set CONFIG_SECURITY_SELINUX_DEVELOP=y CONFIG_SECURITY_SELINUX_AVC_STATS=y @@ -3360,10 +3563,12 @@ CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 # CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set # CONFIG_SECURITY_SMACK is not set # CONFIG_SECURITY_TOMOYO is not set -# CONFIG_SECURITY_APPARMOR is not set +CONFIG_SECURITY_APPARMOR=y +CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1 # CONFIG_SECURITY_YAMA is not set # CONFIG_IMA is not set CONFIG_DEFAULT_SECURITY_SELINUX=y +# CONFIG_DEFAULT_SECURITY_APPARMOR is not set # CONFIG_DEFAULT_SECURITY_DAC is not set CONFIG_DEFAULT_SECURITY="selinux" CONFIG_CRYPTO=y @@ -3379,8 +3584,8 @@ CONFIG_CRYPTO_BLKCIPHER=y CONFIG_CRYPTO_BLKCIPHER2=y CONFIG_CRYPTO_HASH=y CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_PCOMP=y CONFIG_CRYPTO_PCOMP2=y CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_MANAGER2=y @@ -3415,6 +3620,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -3423,15 +3629,17 @@ CONFIG_CRYPTO_HMAC=y # Digest # CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set # CONFIG_CRYPTO_GHASH is not set CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_MD5=y -# CONFIG_CRYPTO_MICHAEL_MIC is not set +CONFIG_CRYPTO_MICHAEL_MIC=y # CONFIG_CRYPTO_RMD128 is not set # CONFIG_CRYPTO_RMD160 is not set # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +# CONFIG_CRYPTO_SHA1_ARM is not set CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3441,6 +3649,7 @@ CONFIG_CRYPTO_SHA256=y # Ciphers # CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_AES_ARM is not set # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set @@ -3461,37 +3670,37 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y # Compression # CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_ZLIB=y -CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set # # Random Number Generation # -# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_ANSI_CPRNG=y # CONFIG_CRYPTO_USER_API_HASH is not set # CONFIG_CRYPTO_USER_API_SKCIPHER is not set -# CONFIG_CRYPTO_USER_API_RNG is not set CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_SUNXI=m CONFIG_BINARY_PRINTF=y # # Library routines # CONFIG_BITREVERSE=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GENERIC_PCI_IOMAP=y CONFIG_GENERIC_IO=y CONFIG_CRC_CCITT=y CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set -CONFIG_CRC_ITU_T=y +CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC32_SELFTEST is not set CONFIG_CRC32_SLICEBY8=y # CONFIG_CRC32_SLICEBY4 is not set # CONFIG_CRC32_SARWATE is not set # CONFIG_CRC32_BIT is not set -# CONFIG_CRC7 is not set +CONFIG_CRC7=m CONFIG_LIBCRC32C=y # CONFIG_CRC8 is not set CONFIG_AUDIT_GENERIC=y @@ -3509,6 +3718,9 @@ CONFIG_XZ_DEC_SPARC=y CONFIG_XZ_DEC_BCJ=y # CONFIG_XZ_DEC_TEST is not set CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y CONFIG_TEXTSEARCH=y CONFIG_TEXTSEARCH_KMP=y CONFIG_TEXTSEARCH_BM=y @@ -3519,14 +3731,8 @@ CONFIG_HAS_DMA=y CONFIG_CPU_RMAP=y CONFIG_DQL=y CONFIG_NLATTR=y -# CONFIG_AVERAGE is not set +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_AVERAGE=y # CONFIG_CORDIC is not set - -# -# Modules -# - -# -# Mali -# -# CONFIG_MALI_LINUX_ENV is not set +# CONFIG_DDR is not set +# CONFIG_VIRTUALIZATION is not set diff --git a/config/linux-sun4i.config b/config/linux-sun4i.config new file mode 100644 index 000000000..6b40f0e5d --- /dev/null +++ b/config/linux-sun4i.config @@ -0,0 +1,4001 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.4.110 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_KTIME_SCALAR=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_NEED_MACH_IO_H=y +CONFIG_GENERIC_BUG=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_HAVE_IRQ_WORK=y +CONFIG_IRQ_WORK=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_XZ is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_FHANDLE=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_AUDIT=y +# CONFIG_AUDITSYSCALL is not set +# CONFIG_AUDIT_LOGINUID_IMMUTABLE is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_SHOW=y + +# +# RCU Subsystem +# +CONFIG_TINY_PREEMPT_RCU=y +CONFIG_PREEMPT_RCU=y +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_BOOST is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=19 +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_MEM_RES_CTLR=y +CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y +CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED=y +CONFIG_CGROUP_MEM_RES_CTLR_KMEM=y +CONFIG_CGROUP_PERF=y +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_CGROUP=y +# CONFIG_DEBUG_BLK_CGROUP is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +CONFIG_USER_NS=y +CONFIG_PID_NS=y +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_MM_OWNER=y +# CONFIG_SYSFS_DEPRECATED is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_EXPERT is not set +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +# CONFIG_EMBEDDED is not set +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +CONFIG_PERF_COUNTERS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_JUMP_LABEL=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +CONFIG_BLK_DEV_BSG=y +CONFIG_BLK_DEV_BSGLIB=y +CONFIG_BLK_DEV_INTEGRITY=y +# CONFIG_BLK_DEV_THROTTLING is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +# CONFIG_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_SUNXI_NAND_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_CFQ_GROUP_IOSCHED=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_UNINLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +# CONFIG_INLINE_READ_UNLOCK is not set +# CONFIG_INLINE_READ_UNLOCK_BH is not set +# CONFIG_INLINE_READ_UNLOCK_IRQ is not set +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +# CONFIG_INLINE_WRITE_UNLOCK is not set +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_PRIMA2 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_PICOXCELL is not set +CONFIG_ARCH_SUN4I=y +# CONFIG_ARCH_SUN5I is not set +# CONFIG_ARCH_SUN7I is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C24XX is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set +# CONFIG_ARCH_ZYNQ is not set +# CONFIG_GPIO_PCA953X is not set +CONFIG_KEYBOARD_GPIO_POLLED=m + +# +# System MMU +# + +# +# Allwinner's sunxi options +# +CONFIG_SW_DEBUG_UART=0 +CONFIG_SUNXI_MULTIPLATFORM=y +CONFIG_SUNXI_SCALING_MIN=60 +CONFIG_PLAT_SUNXI=y + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_LPAE is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_CACHE_L2X0 is not set +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_ARM_NR_BANKS=8 +CONFIG_CPU_HAS_PMU=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_775420 is not set +# CONFIG_FIQ_DEBUGGER is not set + +# +# Bus support +# +CONFIG_ARM_AMBA=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_ARCH_NR_GPIO=0 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_HZ=100 +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HW_PERF_EVENTS=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_KSM=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_NEED_PER_CPU_KM=y +# CONFIG_CLEANCACHE is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set + +# +# Boot options +# +# CONFIG_USE_OF is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/mmc0p1 rw init=/init loglevel=8" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_EXTEND is not set +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_XIP_KERNEL is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_FANTASY is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_GOV_FANTASY is not set +CONFIG_CPU_FREQ_USR_EVNT_NOTIFY=y +CONFIG_CPU_FREQ_DVFS=y + +# +# ARM CPU frequency scaling drivers +# +# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set +# CONFIG_ARM_EXYNOS4X12_CPUFREQ is not set +# CONFIG_ARM_EXYNOS5250_CPUFREQ is not set +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_HAS_WAKELOCK=y +CONFIG_WAKELOCK=y +CONFIG_PM_SLEEP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM=y +CONFIG_PM_DEBUG=y +CONFIG_PM_ADVANCED_DEBUG=y +# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_CAN_PM_TRACE=y +# CONFIG_APM_EMULATION is not set +CONFIG_PM_CLK=y +CONFIG_CPU_PM=y +# CONFIG_SUSPEND_TIME is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=y +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_FIB_TRIE_STATS=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_ROUTE_CLASSID=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=y +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_ARPD=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_INET_UDP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_WESTWOOD=y +CONFIG_TCP_CONG_HTCP=y +CONFIG_TCP_CONG_HSTCP=y +CONFIG_TCP_CONG_HYBLA=y +CONFIG_TCP_CONG_VEGAS=y +CONFIG_TCP_CONG_SCALABLE=y +CONFIG_TCP_CONG_LP=y +CONFIG_TCP_CONG_VENO=y +CONFIG_TCP_CONG_YEAH=y +CONFIG_TCP_CONG_ILLINOIS=y +# CONFIG_DEFAULT_BIC is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_HTCP is not set +# CONFIG_DEFAULT_HYBLA is not set +# CONFIG_DEFAULT_VEGAS is not set +# CONFIG_DEFAULT_VENO is not set +# CONFIG_DEFAULT_WESTWOOD is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6=y +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +# CONFIG_ANDROID_PARANOID_NETWORK is not set +CONFIG_NET_ACTIVITY_STATS=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NETWORK_PHY_TIMESTAMPING=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_ACCT=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_BROADCAST=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_NETLINK_TIMEOUT=m +CONFIG_NETFILTER_TPROXY=m +CONFIG_NETFILTER_XTABLES=m + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_CONNMARK=m +CONFIG_NETFILTER_XT_SET=m + +# +# Xtables targets +# +CONFIG_NETFILTER_XT_TARGET_AUDIT=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ECN=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_QUOTA2=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_MAX=256 +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS SH scheduler +# +CONFIG_IP_VS_SH_TAB_BITS=8 + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_NFCT=y +CONFIG_IP_VS_PE_SIP=m + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_REJECT_SKERR=y +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PROTO_DCCP=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m +CONFIG_NF_NAT_SIP=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_REJECT_SKERR=y +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_L2TP=m +# CONFIG_L2TP_DEBUGFS is not set +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_STP=m +CONFIG_GARP=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_IGMP_SNOOPING=y +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +# CONFIG_DECNET is not set +CONFIG_LLC=m +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=y +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_CHOKE=m +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_PLUG=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_CLS_CGROUP is not set +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +CONFIG_BATMAN_ADV=m +# CONFIG_BATMAN_ADV_DEBUG is not set +CONFIG_OPENVSWITCH=m +CONFIG_NETPRIO_CGROUP=m +CONFIG_BQL=y +CONFIG_HAVE_BPF_JIT=y +# CONFIG_BPF_JIT is not set + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y + +# +# IrDA options +# +# CONFIG_IRDA_CACHE_LAST_LSAP is not set +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +# CONFIG_DONGLE is not set +CONFIG_KINGSUN_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +CONFIG_KS959_DONGLE=m + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTSDIO=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +# CONFIG_BT_HCIVHCI is not set +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_BT_ATH3K=m +CONFIG_BT_WILINK=m +CONFIG_AF_RXRPC=m +# CONFIG_AF_RXRPC_DEBUG is not set +CONFIG_RXKAD=m +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=y +# CONFIG_NL80211_TESTMODE is not set +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_WEXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_LIB80211=m +CONFIG_LIB80211_CRYPT_WEP=m +CONFIG_LIB80211_CRYPT_CCMP=m +CONFIG_LIB80211_CRYPT_TKIP=m +# CONFIG_LIB80211_DEBUG is not set +CONFIG_CFG80211_ALLOW_RECONNECT=y +CONFIG_MAC80211=m +CONFIG_MAC80211_HAS_RC=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_WIMAX=m +CONFIG_WIMAX_DEBUG_LEVEL=8 +CONFIG_RFKILL=y +CONFIG_RFKILL_PM=y +CONFIG_RFKILL_LEDS=y +CONFIG_RFKILL_INPUT=y +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RFKILL_GPIO is not set +CONFIG_SUNXI_RFKILL=y +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_SYNC is not set +# CONFIG_CMA is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +# CONFIG_MTD is not set +CONFIG_PARPORT=m +# CONFIG_PARPORT_PC is not set +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y +CONFIG_PARPORT_NOT_PC=y +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +CONFIG_BLK_DEV_CRYPTOLOOP=y +CONFIG_BLK_DEV_DRBD=m +# CONFIG_DRBD_FAULT_INJECTION is not set +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_OSD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +# CONFIG_BLK_DEV_XIP is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set +CONFIG_SUNXI_NAND=y +# CONFIG_SUNXI_NAND_COMPAT_DEV is not set +# CONFIG_SUNXI_NAND_TEST is not set + +# +# Misc devices +# +CONFIG_SENSORS_LIS3LV02D=m +# CONFIG_AD525X_DPOT is not set +# CONFIG_SUN4I_VIBRATOR is not set +CONFIG_SUNXI_DBGREG=m +# CONFIG_ATMEL_PWM is not set +CONFIG_SUNXI_PWM=y +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_SENSORS_AK8975 is not set +# CONFIG_DS1682 is not set +CONFIG_TI_DAC7512=m +# CONFIG_UID_STAT is not set +CONFIG_BMP085=m +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_WL127X_RFKILL is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=m +CONFIG_EEPROM_AT25=m +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +CONFIG_EEPROM_93CX6=m +CONFIG_EEPROM_93XX46=m +CONFIG_IWMC3200TOP=m +# CONFIG_IWMC3200TOP_DEBUG is not set +# CONFIG_IWMC3200TOP_DEBUGFS is not set + +# +# Texas Instruments shared transport line discipline +# +CONFIG_TI_ST=m +CONFIG_SENSORS_LIS3_SPI=m +CONFIG_SENSORS_LIS3_I2C=m + +# +# Altera FPGA firmware download module +# +CONFIG_ALTERA_STAPL=m + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +CONFIG_SCSI_NETLINK=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +CONFIG_ISCSI_TCP=m +# CONFIG_ISCSI_BOOT_SYSFS is not set +CONFIG_LIBFC=m +CONFIG_LIBFCOE=m +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +CONFIG_SCSI_OSD_INITIATOR=m +CONFIG_SCSI_OSD_ULD=m +CONFIG_SCSI_OSD_DPRINT_SENSE=1 +# CONFIG_SCSI_OSD_DEBUG is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +# CONFIG_SATA_AHCI_PLATFORM is not set +CONFIG_SW_SATA_AHCI_PLATFORM=y +# CONFIG_ATA_SFF is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +CONFIG_MD_RAID1=m +# CONFIG_MD_RAID10 is not set +CONFIG_MD_RAID456=m +# CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_DEBUG=y +CONFIG_DM_BUFIO=m +CONFIG_DM_PERSISTENT_DATA=m +CONFIG_DM_CRYPT=y +CONFIG_DM_SNAPSHOT=y +CONFIG_DM_THIN_PROVISIONING=m +# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set +# CONFIG_DM_DEBUG_SPACE_MAPS is not set +CONFIG_DM_MIRROR=y +CONFIG_DM_RAID=m +CONFIG_DM_LOG_USERSPACE=m +CONFIG_DM_ZERO=y +CONFIG_DM_MULTIPATH=y +CONFIG_DM_MULTIPATH_QL=y +CONFIG_DM_MULTIPATH_ST=y +CONFIG_DM_DELAY=m +CONFIG_DM_UEVENT=y +# CONFIG_DM_FLAKEY is not set +CONFIG_DM_VERITY=m +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +CONFIG_BONDING=y +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +CONFIG_MII=y +# CONFIG_NET_TEAM is not set +CONFIG_MACVLAN=y +CONFIG_MACVTAP=y +CONFIG_NETCONSOLE=y +CONFIG_NETCONSOLE_DYNAMIC=y +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y +CONFIG_TUN=m +CONFIG_VETH=y + +# +# CAIF transport drivers +# +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +CONFIG_NET_VENDOR_CHELSIO=y +CONFIG_NET_VENDOR_CIRRUS=y +# CONFIG_CS89x0 is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_DLINK=y +# CONFIG_DE600 is not set +# CONFIG_DE620 is not set +CONFIG_NET_VENDOR_FARADAY=y +# CONFIG_FTMAC100 is not set +# CONFIG_FTGMAC100 is not set +CONFIG_NET_VENDOR_INTEL=y +CONFIG_NET_VENDOR_I825XX=y +CONFIG_NET_VENDOR_MARVELL=y +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NET_VENDOR_8390=y +# CONFIG_AX88796 is not set +# CONFIG_ETHOC is not set +CONFIG_NET_VENDOR_SEEQ=y +# CONFIG_SEEQ8005 is not set +CONFIG_NET_VENDOR_SMSC=y +# CONFIG_SMC91X is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_SUNXI_EMAC=y +CONFIG_PHYLIB=y +# CONFIG_SWCONFIG is not set + +# +# MII PHY device drivers +# +# CONFIG_AMD_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +CONFIG_FIXED_PHY=y +CONFIG_MDIO_BITBANG=y +# CONFIG_MDIO_GPIO is not set +CONFIG_MICREL_KS8995MA=m +CONFIG_PLIP=m +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +# CONFIG_PPP_MULTILINK is not set +CONFIG_PPPOE=y +CONFIG_PPTP=m +CONFIG_PPPOL2TP=m +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +CONFIG_SLIP=m +CONFIG_SLHC=y +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_QF9700=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_CDC_NCM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +# CONFIG_USB_NET_GL620A is not set +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_PLUSB is not set +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_HSO=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_WLAN=y +CONFIG_LIBERTAS_THINFIRM=m +# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AT76C50X_USB=m +CONFIG_USB_ZD1201=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_WIFI_CONTROL_FUNC is not set +CONFIG_ATH_COMMON=m +# CONFIG_ATH_DEBUG is not set +CONFIG_ATH9K_HW=m +CONFIG_ATH9K_COMMON=m +CONFIG_ATH9K_BTCOEX_SUPPORT=y +CONFIG_ATH9K=m +CONFIG_ATH9K_AHB=y +# CONFIG_ATH9K_DEBUGFS is not set +# CONFIG_ATH9K_LEGACY_RATE_CONTROL is not set +CONFIG_ATH9K_HTC=m +# CONFIG_ATH9K_HTC_DEBUGFS is not set +CONFIG_CARL9170=m +CONFIG_CARL9170_LEDS=y +CONFIG_CARL9170_WPC=y +CONFIG_ATH6KL=m +CONFIG_ATH6KL_SDIO=m +CONFIG_ATH6KL_USB=m +# CONFIG_ATH6KL_DEBUG is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_BCMDHD is not set +# CONFIG_AP6210 is not set +CONFIG_BRCMUTIL=m +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_SDIO=y +CONFIG_BRCMFMAC_USB=y +# CONFIG_BRCMDBG is not set +# CONFIG_BCM4330 is not set +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set +CONFIG_IWM=m +# CONFIG_IWM_DEBUG is not set +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_LIBERTAS_SPI=m +# CONFIG_LIBERTAS_DEBUG is not set +# CONFIG_LIBERTAS_MESH is not set +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +CONFIG_P54_SPI=m +CONFIG_P54_SPI_DEFAULT_EEPROM=y +CONFIG_P54_LEDS=y +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT33XX=y +CONFIG_RT2800USB_RT35XX=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RT2800_LIB=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_DEBUG is not set +# CONFIG_RTL8192CU is not set +CONFIG_WL1251=m +CONFIG_WL1251_SPI=m +CONFIG_WL1251_SDIO=m +CONFIG_WL12XX_MENU=m +CONFIG_WL12XX=m +CONFIG_WL12XX_SPI=m +CONFIG_WL12XX_SDIO=m +CONFIG_WL12XX_PLATFORM_DATA=y +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_RTL8192CU_SW=m +CONFIG_RTL8188EU=m +CONFIG_RTL8189ES=m +CONFIG_RTL8723AS=m +CONFIG_RTXX7X_SW=m + +# +# WiMAX Wireless Broadband devices +# +CONFIG_WIMAX_I2400M=m +CONFIG_WIMAX_I2400M_USB=m +CONFIG_WIMAX_I2400M_SDIO=m +CONFIG_WIMAX_IWMC3200_SDIO=y +CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8 +# CONFIG_WAN is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_FF_MEMLESS=y +CONFIG_INPUT_POLLDEV=y +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +CONFIG_INPUT_KEYRESET=y + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ADP5588=m +CONFIG_KEYBOARD_ADP5589=m +CONFIG_KEYBOARD_ATKBD=y +CONFIG_KEYBOARD_QT1070=m +CONFIG_KEYBOARD_QT2160=m +CONFIG_KEYBOARD_LKKBD=m +CONFIG_KEYBOARD_GPIO=m +CONFIG_KEYBOARD_TCA6416=m +CONFIG_KEYBOARD_TCA8418=m +CONFIG_KEYBOARD_MATRIX=m +CONFIG_KEYBOARD_LM8323=m +CONFIG_KEYBOARD_MAX7359=m +CONFIG_KEYBOARD_MCS=m +CONFIG_KEYBOARD_MPR121=m +CONFIG_KEYBOARD_NEWTON=m +CONFIG_KEYBOARD_OPENCORES=m +CONFIG_KEYBOARD_SAMSUNG=m +CONFIG_KEYBOARD_STOWAWAY=m +CONFIG_KEYBOARD_SUNKBD=m +CONFIG_KEYBOARD_OMAP4=m +CONFIG_KEYBOARD_XTKBD=m +CONFIG_KEYBOARD_SUN4IKEYPAD=m +CONFIG_KEYBOARD_SUN4I_KEYBOARD=m +# CONFIG_KEYBOARD_SUN4I_KEYBOARD_FEX is not set +CONFIG_KEYBOARD_HV2605_KEYBOARD=y +CONFIG_IR_SUNXI=m +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +CONFIG_MOUSE_SYNAPTICS_USB=m +CONFIG_INPUT_JOYSTICK=y +# CONFIG_JOYSTICK_ANALOG is not set +# CONFIG_JOYSTICK_A3D is not set +# CONFIG_JOYSTICK_ADI is not set +# CONFIG_JOYSTICK_COBRA is not set +# CONFIG_JOYSTICK_GF2K is not set +# CONFIG_JOYSTICK_GRIP is not set +# CONFIG_JOYSTICK_GRIP_MP is not set +# CONFIG_JOYSTICK_GUILLEMOT is not set +# CONFIG_JOYSTICK_INTERACT is not set +# CONFIG_JOYSTICK_SIDEWINDER is not set +# CONFIG_JOYSTICK_TMDC is not set +# CONFIG_JOYSTICK_IFORCE is not set +# CONFIG_JOYSTICK_WARRIOR is not set +# CONFIG_JOYSTICK_MAGELLAN is not set +# CONFIG_JOYSTICK_SPACEORB is not set +# CONFIG_JOYSTICK_SPACEBALL is not set +# CONFIG_JOYSTICK_STINGER is not set +# CONFIG_JOYSTICK_TWIDJOY is not set +# CONFIG_JOYSTICK_ZHENHUA is not set +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +# CONFIG_JOYSTICK_AS5011 is not set +# CONFIG_JOYSTICK_JOYDUMP is not set +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_WALKERA0701=m +CONFIG_INPUT_TABLET=y +CONFIG_TABLET_USB_ACECAD=m +CONFIG_TABLET_USB_AIPTEK=m +CONFIG_TABLET_USB_GTCO=m +CONFIG_TABLET_USB_HANWANG=m +CONFIG_TABLET_USB_KBTAB=m +CONFIG_TABLET_USB_WACOM=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_AD7877=m +CONFIG_TOUCHSCREEN_AD7879=m +CONFIG_TOUCHSCREEN_AD7879_I2C=m +CONFIG_TOUCHSCREEN_AD7879_SPI=m +CONFIG_TOUCHSCREEN_ATMEL_MXT=m +CONFIG_TOUCHSCREEN_AUO_PIXCIR=m +CONFIG_TOUCHSCREEN_BU21013=m +CONFIG_TOUCHSCREEN_CY8CTMG110=m +CONFIG_TOUCHSCREEN_CYTTSP_CORE=m +CONFIG_TOUCHSCREEN_CYTTSP_I2C=m +CONFIG_TOUCHSCREEN_CYTTSP_SPI=m +CONFIG_TOUCHSCREEN_DYNAPRO=m +CONFIG_TOUCHSCREEN_HAMPSHIRE=m +CONFIG_TOUCHSCREEN_EETI=m +# CONFIG_TOUCHSCREEN_EGALAX is not set +CONFIG_TOUCHSCREEN_FUJITSU=m +CONFIG_TOUCHSCREEN_ILI210X=m +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_WACOM_W8001=m +CONFIG_TOUCHSCREEN_MAX11801=m +CONFIG_TOUCHSCREEN_MCS5000=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_INEXIO=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_TOUCHSCREEN_PENMOUNT=m +CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI=m +CONFIG_TOUCHSCREEN_TOUCHRIGHT=m +CONFIG_TOUCHSCREEN_TOUCHWIN=m +CONFIG_TOUCHSCREEN_PIXCIR=m +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_TOUCHSCREEN_USB_EGALAX=y +CONFIG_TOUCHSCREEN_USB_PANJIT=y +CONFIG_TOUCHSCREEN_USB_3M=y +CONFIG_TOUCHSCREEN_USB_ITM=y +CONFIG_TOUCHSCREEN_USB_ETURBO=y +CONFIG_TOUCHSCREEN_USB_GUNZE=y +CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y +CONFIG_TOUCHSCREEN_USB_IRTOUCH=y +CONFIG_TOUCHSCREEN_USB_IDEALTEK=y +CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y +CONFIG_TOUCHSCREEN_USB_GOTOP=y +CONFIG_TOUCHSCREEN_USB_JASTEC=y +CONFIG_TOUCHSCREEN_USB_ELO=y +CONFIG_TOUCHSCREEN_USB_E2I=y +CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y +CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y +CONFIG_TOUCHSCREEN_USB_NEXIO=y +CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y +CONFIG_TOUCHSCREEN_TOUCHIT213=m +CONFIG_TOUCHSCREEN_TSC_SERIO=m +CONFIG_TOUCHSCREEN_TSC2005=m +CONFIG_TOUCHSCREEN_TSC2007=m +CONFIG_TOUCHSCREEN_W90X900=m +CONFIG_TOUCHSCREEN_ST1232=m +CONFIG_TOUCHSCREEN_TPS6507X=m +CONFIG_TOUCHSCREEN_GT801=m +CONFIG_TOUCHSCREEN_GT801_2PLUS1_TS=m +CONFIG_TOUCHSCREEN_GT811=m +CONFIG_TOUCHSCREEN_GT818=m +CONFIG_TOUCHSCREEN_SUN4I_TS=m +CONFIG_TOUCHSCREEN_FT5X_TS=m +CONFIG_TOUCHSCREEN_ZT8031=m +# CONFIG_TOUCHSCREEN_COASIA is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AD714X=m +CONFIG_INPUT_AD714X_I2C=m +CONFIG_INPUT_AD714X_SPI=m +CONFIG_INPUT_BMA150=m +CONFIG_INPUT_MMA8450=m +CONFIG_INPUT_MPU3050=m +CONFIG_INPUT_GP2A=m +CONFIG_INPUT_GPIO_TILT_POLLED=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_KEYCHORD=m +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_KXTJ9=m +CONFIG_INPUT_KXTJ9_POLLED_MODE=y +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_YEALINK=m +CONFIG_INPUT_CM109=m +CONFIG_INPUT_UINPUT=m +CONFIG_INPUT_GPIO=m +CONFIG_INPUT_PCF8574=m +CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +CONFIG_INPUT_ADXL34X=m +CONFIG_INPUT_ADXL34X_I2C=m +CONFIG_INPUT_ADXL34X_SPI=m +CONFIG_INPUT_CMA3000=m +CONFIG_INPUT_CMA3000_I2C=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_AMBAKMI is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_GAMEPORT is not set +CONFIG_GSENSOR=y +CONFIG_SENSORS_BMA250=m +CONFIG_MEMSIC_ECOMPASS=m +CONFIG_SENSORS_MXC622X=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVMEM=y +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_SUNXI=y +CONFIG_SERIAL_8250_NR_UARTS=8 +CONFIG_SERIAL_8250_RUNTIME_UARTS=8 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +CONFIG_PRINTER=m +# CONFIG_LP_CONSOLE is not set +CONFIG_PPDEV=m +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_DCC_TTY is not set +# CONFIG_RAMOOPS is not set +CONFIG_SUNXI_G2D=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=m + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +CONFIG_I2C_SUNXI=y +# CONFIG_SUNXI_IIC_PRINT_TRANSFER_INFO is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_BUTTERFLY is not set +CONFIG_SPI_GPIO=y +# CONFIG_SPI_LM70_LLP is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX_PCI is not set +CONFIG_SPI_SUNXI=m +CONFIG_SPI_SUNXI_NDMA=y +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=m +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_HSI is not set + +# +# PPS support +# +CONFIG_PPS=m +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_PARPORT is not set +# CONFIG_PPS_CLIENT_GPIO is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=m +# CONFIG_DP83640_PHY is not set +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_PL061 is not set +CONFIG_GPIO_SUNXI=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +CONFIG_W1=m +CONFIG_W1_CON=y +CONFIG_W1_SUNXI=m + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m +CONFIG_W1_MASTER_DS1WM=m +CONFIG_W1_MASTER_GPIO=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2408=m +CONFIG_W1_SLAVE_DS2423=m +CONFIG_W1_SLAVE_DS2431=m +CONFIG_W1_SLAVE_DS2433=m +# CONFIG_W1_SLAVE_DS2433_CRC is not set +CONFIG_W1_SLAVE_DS2760=m +CONFIG_W1_SLAVE_DS2780=m +CONFIG_W1_SLAVE_DS2781=m +CONFIG_W1_SLAVE_BQ27000=m +CONFIG_POWER_SUPPLY=y +CONFIG_AW_AXP=y +# CONFIG_AW_AXP18 is not set +# CONFIG_AW_AXP19 is not set +CONFIG_AW_AXP20=y +CONFIG_AXP_CHARGEINIT=y +CONFIG_AXP_CHGCHANGE=y +CONFIG_AXP_HWMON=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +CONFIG_AXP152=y +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2760 is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_SMB347 is not set +CONFIG_HWMON=y +CONFIG_HWMON_VID=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +CONFIG_SENSORS_MMA7660=m +CONFIG_SENSORS_A20_TP_HWMON=m +CONFIG_SENSORS_AD7314=m +CONFIG_SENSORS_AD7414=m +CONFIG_SENSORS_AD7418=m +CONFIG_SENSORS_ADCXX=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1029=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ADT7411=m +CONFIG_SENSORS_ADT7462=m +CONFIG_SENSORS_ADT7470=m +CONFIG_SENSORS_ADT7475=m +CONFIG_SENSORS_ASC7621=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS620=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_F71882FG=m +CONFIG_SENSORS_F75375S=m +CONFIG_SENSORS_G760A=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_GPIO_FAN=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_JC42=m +CONFIG_SENSORS_LINEAGE=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM70=m +CONFIG_SENSORS_LM73=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_LM93=m +CONFIG_SENSORS_LTC4151=m +CONFIG_SENSORS_LTC4215=m +CONFIG_SENSORS_LTC4245=m +CONFIG_SENSORS_LTC4261=m +CONFIG_SENSORS_LM95241=m +CONFIG_SENSORS_LM95245=m +CONFIG_SENSORS_MAX1111=m +CONFIG_SENSORS_MAX16065=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_MAX1668=y +CONFIG_SENSORS_MAX6639=m +CONFIG_SENSORS_MAX6642=m +CONFIG_SENSORS_MAX6650=m +CONFIG_SENSORS_MCP3021=m +CONFIG_SENSORS_NTC_THERMISTOR=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_PC87427=m +CONFIG_SENSORS_PCF8591=m +CONFIG_PMBUS=m +CONFIG_SENSORS_PMBUS=m +CONFIG_SENSORS_ADM1275=m +CONFIG_SENSORS_LM25066=m +CONFIG_SENSORS_LTC2978=m +CONFIG_SENSORS_MAX16064=m +CONFIG_SENSORS_MAX34440=m +CONFIG_SENSORS_MAX8688=m +CONFIG_SENSORS_UCD9000=m +CONFIG_SENSORS_UCD9200=m +CONFIG_SENSORS_ZL6100=m +CONFIG_SENSORS_SHT15=m +CONFIG_SENSORS_SHT21=m +CONFIG_SENSORS_SMM665=m +CONFIG_SENSORS_DME1737=m +CONFIG_SENSORS_EMC1403=m +CONFIG_SENSORS_EMC2103=m +CONFIG_SENSORS_EMC6W201=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_SCH56XX_COMMON=m +CONFIG_SENSORS_SCH5627=m +CONFIG_SENSORS_SCH5636=m +CONFIG_SENSORS_ADS1015=m +CONFIG_SENSORS_ADS7828=m +CONFIG_SENSORS_ADS7871=m +CONFIG_SENSORS_AMC6821=m +CONFIG_SENSORS_THMC50=m +CONFIG_SENSORS_TMP102=m +CONFIG_SENSORS_TMP401=m +CONFIG_SENSORS_TMP421=m +CONFIG_SENSORS_VT1211=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83793=m +# CONFIG_SENSORS_W83795 is not set +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83L786NG=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_CORE is not set +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set +CONFIG_SUNXI_WDT=m + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB=m +CONFIG_SSB_SDIOHOST_POSSIBLE=y +CONFIG_SSB_SDIOHOST=y +# CONFIG_SSB_DEBUG is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=m +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_S5M_CORE is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +CONFIG_MFD_WL1273_CORE=m +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_RC5T583 is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_DUMMY is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_GPIO is not set +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_COMMON=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_DVB_CORE=m +CONFIG_DVB_NET=y +CONFIG_VIDEO_MEDIA=m + +# +# Multimedia drivers +# +CONFIG_RC_CORE=m +CONFIG_LIRC=m +CONFIG_RC_MAP=m +CONFIG_IR_NEC_DECODER=m +CONFIG_IR_RC5_DECODER=m +CONFIG_IR_RC6_DECODER=m +CONFIG_IR_JVC_DECODER=m +CONFIG_IR_SONY_DECODER=m +CONFIG_IR_RC5_SZ_DECODER=m +CONFIG_IR_SANYO_DECODER=m +CONFIG_IR_MCE_KBD_DECODER=m +CONFIG_IR_LIRC_CODEC=m +CONFIG_RC_ATI_REMOTE=m +CONFIG_IR_IMON=m +CONFIG_IR_MCEUSB=m +CONFIG_IR_REDRAT3=m +CONFIG_IR_STREAMZAP=m +# CONFIG_RC_LOOPBACK is not set +# CONFIG_IR_GPIO_CIR is not set +CONFIG_MEDIA_ATTACH=y +CONFIG_MEDIA_TUNER=m +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_MEDIA_TUNER_SIMPLE=m +CONFIG_MEDIA_TUNER_TDA8290=m +CONFIG_MEDIA_TUNER_TDA827X=m +CONFIG_MEDIA_TUNER_TDA18271=m +CONFIG_MEDIA_TUNER_TDA9887=m +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +CONFIG_MEDIA_TUNER_MT20XX=m +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT2063=m +CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_XC2028=m +CONFIG_MEDIA_TUNER_XC5000=m +CONFIG_MEDIA_TUNER_XC4000=m +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_MEDIA_TUNER_MXL5007T=m +CONFIG_MEDIA_TUNER_MC44S803=m +CONFIG_MEDIA_TUNER_MAX2165=m +CONFIG_MEDIA_TUNER_TDA18218=m +CONFIG_MEDIA_TUNER_TDA18212=m +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEOBUF_GEN=m +CONFIG_VIDEOBUF_VMALLOC=m +CONFIG_VIDEOBUF_DMA_CONTIG=m +CONFIG_VIDEOBUF_DVB=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEOBUF2_CORE=m +CONFIG_VIDEOBUF2_MEMOPS=m +CONFIG_VIDEOBUF2_VMALLOC=m +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_VIDEO_HELPER_CHIPS_AUTO=y +CONFIG_VIDEO_IR_I2C=m + +# +# Audio decoders, processors and mixers +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_WM8775=m + +# +# RDS decoders +# + +# +# Video decoders +# +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_TVP5150=m + +# +# Video and audio decoders +# +CONFIG_VIDEO_CX25840=m + +# +# MPEG video encoders +# +CONFIG_VIDEO_CX2341X=m + +# +# Video encoders +# + +# +# Camera sensor devices +# +CONFIG_VIDEO_MT9V011=m + +# +# Flash devices +# + +# +# Video improvement chips +# + +# +# Miscelaneous helper chips +# +# CONFIG_VIDEO_VIVI is not set +CONFIG_V4L_USB_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=m +CONFIG_USB_M5602=m +CONFIG_USB_STV06XX=m +CONFIG_USB_GL860=m +CONFIG_USB_GSPCA_BENQ=m +CONFIG_USB_GSPCA_CONEX=m +CONFIG_USB_GSPCA_CPIA1=m +CONFIG_USB_GSPCA_ETOMS=m +CONFIG_USB_GSPCA_FINEPIX=m +CONFIG_USB_GSPCA_JEILINJ=m +CONFIG_USB_GSPCA_JL2005BCD=m +CONFIG_USB_GSPCA_KINECT=m +CONFIG_USB_GSPCA_KONICA=m +CONFIG_USB_GSPCA_MARS=m +CONFIG_USB_GSPCA_MR97310A=m +CONFIG_USB_GSPCA_NW80X=m +CONFIG_USB_GSPCA_OV519=m +CONFIG_USB_GSPCA_OV534=m +CONFIG_USB_GSPCA_OV534_9=m +CONFIG_USB_GSPCA_PAC207=m +CONFIG_USB_GSPCA_PAC7302=m +CONFIG_USB_GSPCA_PAC7311=m +CONFIG_USB_GSPCA_SE401=m +CONFIG_USB_GSPCA_SN9C2028=m +CONFIG_USB_GSPCA_SN9C20X=m +CONFIG_USB_GSPCA_SONIXB=m +CONFIG_USB_GSPCA_SONIXJ=m +CONFIG_USB_GSPCA_SPCA500=m +CONFIG_USB_GSPCA_SPCA501=m +CONFIG_USB_GSPCA_SPCA505=m +CONFIG_USB_GSPCA_SPCA506=m +CONFIG_USB_GSPCA_SPCA508=m +CONFIG_USB_GSPCA_SPCA561=m +CONFIG_USB_GSPCA_SPCA1528=m +CONFIG_USB_GSPCA_SQ905=m +CONFIG_USB_GSPCA_SQ905C=m +CONFIG_USB_GSPCA_SQ930X=m +CONFIG_USB_GSPCA_STK014=m +CONFIG_USB_GSPCA_STV0680=m +CONFIG_USB_GSPCA_SUNPLUS=m +CONFIG_USB_GSPCA_T613=m +CONFIG_USB_GSPCA_TOPRO=m +CONFIG_USB_GSPCA_TV8532=m +CONFIG_USB_GSPCA_VC032X=m +CONFIG_USB_GSPCA_VICAM=m +CONFIG_USB_GSPCA_XIRLINK_CIT=m +CONFIG_USB_GSPCA_ZC3XX=m +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_PVRUSB2_DVB=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_VIDEO_EM28XX_RC=y +CONFIG_VIDEO_TLG2300=m +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_RC=y +CONFIG_VIDEO_CX231XX_ALSA=m +CONFIG_VIDEO_CX231XX_DVB=m +CONFIG_VIDEO_TM6000=m +CONFIG_VIDEO_TM6000_ALSA=m +CONFIG_VIDEO_TM6000_DVB=m +CONFIG_VIDEO_USBVISION=m +CONFIG_USB_ET61X251=m +CONFIG_USB_SN9C102=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set +CONFIG_USB_PWC_INPUT_EVDEV=y +# CONFIG_VIDEO_CPIA2 is not set +CONFIG_USB_ZR364XX=m +CONFIG_USB_STKWEBCAM=m +CONFIG_USB_S2255=m +# CONFIG_V4L_ISA_PARPORT_DRIVERS is not set +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_SOC_CAMERA=m +CONFIG_SOC_CAMERA_IMX074=m +CONFIG_SOC_CAMERA_MT9M001=m +CONFIG_SOC_CAMERA_MT9M111=m +CONFIG_SOC_CAMERA_MT9T031=m +CONFIG_SOC_CAMERA_MT9T112=m +CONFIG_SOC_CAMERA_MT9V022=m +CONFIG_SOC_CAMERA_RJ54N1=m +CONFIG_SOC_CAMERA_TW9910=m +CONFIG_SOC_CAMERA_PLATFORM=m +CONFIG_SOC_CAMERA_OV2640=m +CONFIG_SOC_CAMERA_OV5642=m +CONFIG_SOC_CAMERA_OV6650=m +CONFIG_SOC_CAMERA_OV772X=m +CONFIG_SOC_CAMERA_OV9640=m +CONFIG_SOC_CAMERA_OV9740=m +# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set +# CONFIG_VIDEO_SH_MOBILE_CEU is not set +CONFIG_V4L_MEM2MEM_DRIVERS=y +# CONFIG_VIDEO_MEM2MEM_TESTDEV is not set +CONFIG_VIDEO_SUNXI_CEDAR=y +CONFIG_VIDEO_DECODER_SUNXI=y +CONFIG_VIDEO_AVS_COUNTER=y +CONFIG_VIDEO_CSI_SUN4I=y +CONFIG_CSI_DEV_SEL=m +CONFIG_CSI0_SUN4I=m +CONFIG_CSI1_SUN4I=m +CONFIG_CSI_OV7670=m +CONFIG_CSI_GT2005=m +CONFIG_CSI_GC0308=m +CONFIG_CSI_HI704=m +CONFIG_CSI_SP0838=m +CONFIG_CSI_MT9M112=m +CONFIG_CSI_MT9M113=m +CONFIG_CSI_OV2655=m +CONFIG_CSI_HI253=m +CONFIG_CSI_MT9D112=m +CONFIG_CSI_GC0307=m +CONFIG_CSI_OV5640=m +CONFIG_RADIO_ADAPTERS=y +CONFIG_RADIO_SI470X=y +CONFIG_USB_SI470X=m +CONFIG_I2C_SI470X=m +CONFIG_USB_MR800=m +CONFIG_USB_DSBR=m +CONFIG_I2C_SI4713=m +CONFIG_RADIO_SI4713=m +CONFIG_USB_KEENE=m +CONFIG_RADIO_TEA5764=m +CONFIG_RADIO_SAA7706H=m +CONFIG_RADIO_TEF6862=m +CONFIG_RADIO_WL1273=m + +# +# Texas Instruments WL128x FM driver (ST based) +# +# CONFIG_RADIO_WL128X is not set +CONFIG_AUDIO_ENGINE=y +CONFIG_ACE_CONFIG=y +CONFIG_PA_CONTROL=y +CONFIG_PA_CONFIG=y +CONFIG_DVB_MAX_ADAPTERS=8 +CONFIG_DVB_DYNAMIC_MINORS=y +CONFIG_DVB_CAPTURE_DRIVERS=y +CONFIG_TTPCI_EEPROM=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_PCTV452E=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_CINERGY_T2=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_DTV5100=m +CONFIG_DVB_USB_AF9015=m +CONFIG_DVB_USB_CE6230=m +CONFIG_DVB_USB_FRIIO=m +CONFIG_DVB_USB_EC168=m +CONFIG_DVB_USB_AZ6007=m +CONFIG_DVB_USB_AZ6027=m +CONFIG_DVB_USB_LME2510=m +CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_USB_IT913X=m +CONFIG_DVB_USB_MXL111SF=m +CONFIG_DVB_USB_RTL28XXU=m +CONFIG_SMS_SIANO_MDTV=m + +# +# Siano module components +# +CONFIG_SMS_USB_DRV=m +CONFIG_SMS_SDIO_DRV=m + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported DVB Frontends +# +# CONFIG_DVB_FE_CUSTOMISE is not set + +# +# Multistandard (satellite) frontends +# +CONFIG_DVB_STB0899=m +CONFIG_DVB_STB6100=m +CONFIG_DVB_STV090x=m +CONFIG_DVB_STV6110x=m + +# +# Multistandard (cable + terrestrial) frontends +# +CONFIG_DVB_DRXK=m +CONFIG_DVB_TDA18271C2DD=m + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_CX24123=m +CONFIG_DVB_MT312=m +CONFIG_DVB_ZL10039=m +CONFIG_DVB_S5H1420=m +CONFIG_DVB_STV0288=m +CONFIG_DVB_STB6000=m +CONFIG_DVB_STV0299=m +CONFIG_DVB_STV6110=m +CONFIG_DVB_STV0900=m +CONFIG_DVB_TDA10086=m +CONFIG_DVB_TUNER_ITD1000=m +CONFIG_DVB_TUNER_CX24113=m +CONFIG_DVB_TDA826X=m +CONFIG_DVB_CX24116=m +CONFIG_DVB_SI21XX=m +CONFIG_DVB_DS3000=m +CONFIG_DVB_TDA10071=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_CX22702=m +CONFIG_DVB_DRXD=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_DIB7000M=m +CONFIG_DVB_DIB7000P=m +CONFIG_DVB_TDA10048=m +CONFIG_DVB_AF9013=m +CONFIG_DVB_EC100=m +CONFIG_DVB_CXD2820R=m +CONFIG_DVB_RTL2830=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_TDA10023=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m +CONFIG_DVB_LGDT3305=m +CONFIG_DVB_S5H1409=m +CONFIG_DVB_S5H1411=m + +# +# ISDB-T (terrestrial) frontends +# +CONFIG_DVB_S921=m +CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m + +# +# Digital terrestrial only tuners/PLL +# +CONFIG_DVB_PLL=m +CONFIG_DVB_TUNER_DIB0070=m +CONFIG_DVB_TUNER_DIB0090=m + +# +# SEC control devices for DVB-S +# +CONFIG_DVB_LNBP21=m +CONFIG_DVB_LNBP22=m +CONFIG_DVB_ISL6421=m +CONFIG_DVB_ISL6423=m +CONFIG_DVB_A8293=m +CONFIG_DVB_LGS8GXX=m +CONFIG_DVB_ATBM8830=m +CONFIG_DVB_IX2505V=m +CONFIG_DVB_IT913X_FE=m +CONFIG_DVB_M88RS2000=m + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set + +# +# Graphics support +# +CONFIG_FB_TFT=m +CONFIG_FB_TFT_BD663474=m +CONFIG_FB_TFT_HX8340BN=m +CONFIG_FB_TFT_HX8347D=m +CONFIG_FB_TFT_HX8353D=m +CONFIG_FB_TFT_ILI9320=m +CONFIG_FB_TFT_ILI9325=m +CONFIG_FB_TFT_ILI9340=m +CONFIG_FB_TFT_ILI9341=m +CONFIG_FB_TFT_ILI9486=m +CONFIG_FB_TFT_PCD8544=m +CONFIG_FB_TFT_RA8875=m +CONFIG_FB_TFT_S6D02A1=m +CONFIG_FB_TFT_S6D1121=m +CONFIG_FB_TFT_SSD1289=m +CONFIG_FB_TFT_SSD1306=m +CONFIG_FB_TFT_SSD1331=m +CONFIG_FB_TFT_SSD1351=m +CONFIG_FB_TFT_ST7735R=m +CONFIG_FB_TFT_TINYLCD=m +CONFIG_FB_TFT_TLS8204=m +CONFIG_FB_TFT_UPD161704=m +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m +CONFIG_DRM=m +CONFIG_DRM_USB=m +CONFIG_DRM_KMS_HELPER=m +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set + +# +# I2C encoder or helper chips +# +CONFIG_DRM_I2C_CH7006=m +CONFIG_DRM_I2C_SIL164=m +CONFIG_DRM_MALI=m +CONFIG_DRM_UDL=m +# CONFIG_ION is not set +CONFIG_MALI=m +CONFIG_MALI400=m +CONFIG_MALI400_DEBUG=y +# CONFIG_MALI400_GPU_UTILIZATION is not set +CONFIG_UMP=m +CONFIG_UMP_DEBUG=y +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_IMAGEBLIT=m +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=m +# CONFIG_FB_WMT_GE_ROPS is not set +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +CONFIG_FB_BACKLIGHT=y +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +CONFIG_FB_SUNXI=y +CONFIG_FB_SUNXI_RESERVED_MEM=y +CONFIG_FB_SUNXI_UMP=y +CONFIG_FB_SUNXI_LCD=y +CONFIG_FB_SUNXI_HDMI=y +CONFIG_HDMI_CEC=m +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_TMIO is not set +CONFIG_FB_SMSCUFX=m +CONFIG_FB_UDL=m +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_EXYNOS_VIDEO is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=m +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_PLATFORM is not set +# CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_LCD_AMS369FG06 is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=m +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LP855X is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_LOGO is not set +CONFIG_SOUND=y +CONFIG_SOUND_OSS_CORE=y +CONFIG_SOUND_OSS_CORE_PRECLAIM=y +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_JACK=y +CONFIG_SND_SEQUENCER=m +# CONFIG_SND_SEQ_DUMMY is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_SEQUENCER_OSS is not set +CONFIG_SND_HRTIMER=y +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_VMASTER=y +CONFIG_SND_RAWMIDI_SEQ=m +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_DRIVERS=y +CONFIG_SND_DUMMY=m +CONFIG_SND_ALOOP=m +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_MTS64 is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +# CONFIG_SND_PORTMAN2X4 is not set +# CONFIG_SND_ARM is not set +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_6FIRE=m +CONFIG_SND_SOC=y +CONFIG_SOUND_SUNXI=y +CONFIG_SND_SUNXI_SOC_CODEC=y +CONFIG_SND_SUNXI_SOC_HDMIAUDIO=y +# CONFIG_SND_SUNXI_SOC_SPDIF is not set +# CONFIG_SND_SUNXI_SOC_I2S_INTERFACE is not set +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +CONFIG_HIDRAW=y +# CONFIG_UHID is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=y +CONFIG_HID_ACRUX=m +CONFIG_HID_ACRUX_FF=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_PRODIKEYS=m +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=m +CONFIG_DRAGONRISE_FF=y +CONFIG_HID_EMS_FF=m +CONFIG_HID_ELECOM=m +CONFIG_HID_EZKEY=y +CONFIG_HID_HOLTEK=m +CONFIG_HOLTEK_FF=y +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_KYE=y +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WALTOP=m +CONFIG_HID_GYRATION=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LCPOWER=m +CONFIG_HID_LOGITECH=y +CONFIG_HID_LOGITECH_DJ=m +CONFIG_LOGITECH_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_LOGIG940_FF=y +CONFIG_LOGIWHEELS_FF=y +# CONFIG_HID_MAGICMOUSE is not set +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NTRIG=m +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_PANTHERLORD_FF=y +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +CONFIG_HID_PICOLCD_FB=y +CONFIG_HID_PICOLCD_BACKLIGHT=y +CONFIG_HID_PICOLCD_LCD=y +CONFIG_HID_PICOLCD_LEDS=y +CONFIG_HID_PRIMAX=m +CONFIG_HID_ROCCAT=m +CONFIG_HID_SAITEK=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_GREENASIA=m +CONFIG_GREENASIA_FF=y +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_HID_TIVO=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_THRUSTMASTER_FF=y +CONFIG_HID_WACOM=m +# CONFIG_HID_WACOM_POWER_SUPPLY is not set +CONFIG_HID_WIIMOTE=m +CONFIG_HID_WIIMOTE_EXT=y +CONFIG_HID_ZEROPLUS=m +CONFIG_ZEROPLUS_FF=y +CONFIG_HID_ZYDACRON=m +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB_ARCH_HAS_XHCI is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_DWC3 is not set +CONFIG_USB_MON=y +CONFIG_USB_WUSB_CBAF=m +CONFIG_USB_WUSB_CBAF_DEBUG=y + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_HCD_PLATFORM is not set +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_U132_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +CONFIG_USB_SUNXI_EHCI=y +CONFIG_USB_SUNXI_OHCI=y +CONFIG_USB_SUNXI_COMMON=y +CONFIG_USB_SW_SUNXI_HCD0=y +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_RENESAS_USBHS is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_WDM=m +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_REALTEK=y +CONFIG_REALTEK_AUTOPM=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_STORAGE_ENE_UB6250=y +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +CONFIG_USB_USS720=m +CONFIG_USB_SERIAL=m +CONFIG_USB_EZUSB=y +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F81232=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7715_PARPORT=y +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MOTOROLA=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_HP4X=m +# CONFIG_USB_SERIAL_SAFE is not set +CONFIG_USB_SERIAL_SIEMENS_MPI=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_WWAN=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m +# CONFIG_USB_SERIAL_ZIO is not set +CONFIG_USB_SERIAL_SSU100=m +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_IDMOUSE=m +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +# CONFIG_USB_TEST is not set +CONFIG_USB_ISIGHTFW=m +# CONFIG_USB_YUREX is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_NET2272 is not set +CONFIG_USB_SW_SUNXI_UDC0_SELECT=m +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_SW_SUNXI_UDC0=y +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +CONFIG_USB_AUDIO=m +# CONFIG_GADGET_UAC1 is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_ETH_EEM=y +CONFIG_USB_G_NCM=m +CONFIG_USB_GADGETFS=m +CONFIG_USB_FUNCTIONFS=m +CONFIG_USB_FUNCTIONFS_ETH=y +CONFIG_USB_FUNCTIONFS_RNDIS=y +CONFIG_USB_FUNCTIONFS_GENERIC=y +# CONFIG_USB_FILE_STORAGE is not set +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_G_SERIAL=m +CONFIG_USB_MIDI_GADGET=m +CONFIG_USB_G_PRINTER=m +CONFIG_USB_CDC_COMPOSITE=m +CONFIG_USB_G_ACM_MS=m +CONFIG_USB_G_MULTI=m +CONFIG_USB_G_MULTI_RNDIS=y +CONFIG_USB_G_MULTI_CDC=y +CONFIG_USB_G_HID=m +CONFIG_USB_G_DBGP=m +# CONFIG_USB_G_DBGP_PRINTK is not set +CONFIG_USB_G_DBGP_SERIAL=y +CONFIG_USB_G_WEBCAM=m + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +CONFIG_USB_OTG_WAKELOCK=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ULPI is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_USB_SW_SUNXI_USB=y +CONFIG_USB_SW_SUNXI_USB_MANAGER=y +# CONFIG_USB_SW_SUNXI_USB0_HOST_ONLY is not set +CONFIG_USB_SW_SUNXI_USB0_OTG=y +# CONFIG_USB_SW_SUNXI_USB0_DEVICE_ONLY is not set +# CONFIG_USB_SW_SUNXI_USB0_NULL is not set +CONFIG_USB_SW_SUNXI_USB_DEBUG=y +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_UNSAFE_RESUME=y +# CONFIG_MMC_CLKGATE is not set +# CONFIG_MMC_EMBEDDED_SDIO is not set +CONFIG_MMC_PARANOID_SD_INIT=y + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +# CONFIG_MMC_BLOCK_BOUNCE is not set +# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set +CONFIG_SDIO_UART=m +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_DW is not set +CONFIG_MMC_SUNXI_NEW=y +# CONFIG_MMC_DEBUG_SUNXI is not set +CONFIG_MMC_PRE_DBGLVL_SUNXI=0 +# CONFIG_MMC_VUB300 is not set +CONFIG_MMC_USHC=m + +# +# MMC/SD/SDIO Card Power Management Drivers +# +CONFIG_MMC_SUNXI_POWER_CONTROL=m + +# +# SUNXI MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +CONFIG_LEDS_SUNXI=y +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA9633 is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_RENESAS_TPU is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_OT200 is not set +CONFIG_LEDS_TRIGGERS=y + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_GPIO=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_SWITCH is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_DS1307=y +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +CONFIG_RTC_DRV_SUN4I=y +# CONFIG_DMADEVICES is not set +CONFIG_AUXDISPLAY=y +# CONFIG_UIO is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_BALLOON is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +CONFIG_USBIP_CORE=m +CONFIG_USBIP_VHCI_HCD=m +CONFIG_USBIP_HOST=m +# CONFIG_USBIP_DEBUG is not set +CONFIG_W35UND=m +CONFIG_PRISM2_USB=m +CONFIG_ECHO=m +# CONFIG_ASUS_OLED is not set +CONFIG_PANEL=m +CONFIG_PANEL_PARPORT=0 +CONFIG_PANEL_PROFILE=5 +# CONFIG_PANEL_CHANGE_MESSAGE is not set +CONFIG_RTLLIB=m +CONFIG_RTLLIB_CRYPTO_CCMP=m +CONFIG_RTLLIB_CRYPTO_TKIP=m +CONFIG_RTLLIB_CRYPTO_WEP=m +CONFIG_R8712U=m +CONFIG_RTS5139=m +# CONFIG_RTS5139_DEBUG is not set +# CONFIG_TRANZPORT is not set +CONFIG_LINE6_USB=m +# CONFIG_LINE6_USB_DEBUG is not set +# CONFIG_LINE6_USB_DUMP_CTRL is not set +# CONFIG_LINE6_USB_DUMP_MIDI is not set +# CONFIG_LINE6_USB_DUMP_PCM is not set +# CONFIG_LINE6_USB_RAW is not set +# CONFIG_LINE6_USB_IMPULSE_RESPONSE is not set +CONFIG_USB_SERIAL_QUATECH2=m +CONFIG_USB_SERIAL_QUATECH_USB2=m +# CONFIG_VT6656 is not set +CONFIG_IIO=m +# CONFIG_IIO_ST_HWMON is not set +# CONFIG_IIO_BUFFER is not set +# CONFIG_IIO_TRIGGER is not set + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_KXSD9 is not set +# CONFIG_LIS3L02DQ is not set + +# +# Analog to digital converters +# +# CONFIG_AD7291 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7606 is not set +# CONFIG_AD799X is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_ADT7310 is not set +# CONFIG_ADT7410 is not set +# CONFIG_AD7280 is not set +# CONFIG_MAX1363 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD5686 is not set +# CONFIG_MAX517 is not set + +# +# Direct Digital Synthesis +# +# CONFIG_AD5930 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_AD9850 is not set +# CONFIG_AD9852 is not set +# CONFIG_AD9910 is not set +# CONFIG_AD9951 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set + +# +# Light sensors +# +# CONFIG_SENSORS_ISL29018 is not set +CONFIG_SENSORS_TSL2563=m +# CONFIG_TSL2583 is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_HMC5843 is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_SIMPLE_DUMMY is not set +CONFIG_FB_SM7XX=m +CONFIG_USB_ENESTORAGE=m +CONFIG_BCM_WIMAX=m +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +CONFIG_SPEAKUP=m +# CONFIG_SPEAKUP_SYNTH_ACNTSA is not set +# CONFIG_SPEAKUP_SYNTH_ACNTPC is not set +# CONFIG_SPEAKUP_SYNTH_APOLLO is not set +# CONFIG_SPEAKUP_SYNTH_AUDPTR is not set +# CONFIG_SPEAKUP_SYNTH_BNS is not set +# CONFIG_SPEAKUP_SYNTH_DECTLK is not set +# CONFIG_SPEAKUP_SYNTH_DECEXT is not set +# CONFIG_SPEAKUP_SYNTH_DECPC is not set +# CONFIG_SPEAKUP_SYNTH_DTLK is not set +# CONFIG_SPEAKUP_SYNTH_KEYPC is not set +# CONFIG_SPEAKUP_SYNTH_LTLK is not set +CONFIG_SPEAKUP_SYNTH_SOFT=m +# CONFIG_SPEAKUP_SYNTH_SPKOUT is not set +# CONFIG_SPEAKUP_SYNTH_TXPRT is not set +# CONFIG_SPEAKUP_SYNTH_DUMMY is not set +CONFIG_TOUCHSCREEN_CLEARPAD_TM1217=m +CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=m +CONFIG_STAGING_MEDIA=y +CONFIG_DVB_AS102=m +CONFIG_EASYCAP=m +# CONFIG_EASYCAP_DEBUG is not set +CONFIG_LIRC_STAGING=y +CONFIG_LIRC_IGORPLUGUSB=m +CONFIG_LIRC_IMON=m +# CONFIG_LIRC_PARALLEL is not set +CONFIG_LIRC_SASEM=m +# CONFIG_LIRC_SERIAL is not set +# CONFIG_LIRC_SIR is not set +CONFIG_LIRC_TTUSBIR=m +CONFIG_LIRC_ZILOG=m + +# +# Android +# +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOGGER=y +CONFIG_ANDROID_PERSISTENT_RAM=y +CONFIG_ANDROID_RAM_CONSOLE=y +# CONFIG_PERSISTENT_TRACER is not set +CONFIG_ANDROID_TIMED_OUTPUT=y +# CONFIG_ANDROID_TIMED_GPIO is not set +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y +# CONFIG_ANDROID_SWITCH is not set +# CONFIG_ANDROID_INTF_ALARM_DEV is not set +# CONFIG_PHONE is not set +CONFIG_USB_WPAN_HCD=m + +# +# Hardware Spinlock drivers +# +CONFIG_IOMMU_SUPPORT=y + +# +# Remoteproc drivers (EXPERIMENTAL) +# + +# +# Rpmsg drivers (EXPERIMENTAL) +# +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_DEFAULTS_TO_ORDERED=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_XATTR=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=y +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=y +# CONFIG_JFS_POSIX_ACL is not set +# CONFIG_JFS_SECURITY is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_XFS_FS=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +# CONFIG_XFS_DEBUG is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_BTRFS_FS=y +# CONFIG_BTRFS_FS_POSIX_ACL is not set +# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set +# CONFIG_QUOTA_DEBUG is not set +CONFIG_QUOTA_TREE=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=y +CONFIG_OVERLAYFS_FS=m +CONFIG_CUSE=y +CONFIG_GENERIC_ACL=y + +# +# Caches +# +CONFIG_FSCACHE=y +CONFIG_FSCACHE_STATS=y +# CONFIG_FSCACHE_HISTOGRAM is not set +# CONFIG_FSCACHE_DEBUG is not set +# CONFIG_FSCACHE_OBJECT_LIST is not set +CONFIG_CACHEFILES=y +# CONFIG_CACHEFILES_DEBUG is not set +# CONFIG_CACHEFILES_HISTOGRAM is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=y +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +CONFIG_NTFS_FS=y +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=y +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +CONFIG_ECRYPT_FS=y +# CONFIG_HFS_FS is not set +CONFIG_HFSPLUS_FS=y +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y +CONFIG_SQUASHFS_EMBEDDED=y +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_EXOFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFS_FSCACHE is not set +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +# CONFIG_NFSD_FAULT_INJECTION is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set +CONFIG_CIFS=y +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +CONFIG_CIFS_DFS_UPCALL=y +# CONFIG_CIFS_FSCACHE is not set +CONFIG_CIFS_ACL=y +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +CONFIG_NLS_CODEPAGE_936=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_CODEPAGE_932=y +CONFIG_NLS_CODEPAGE_949=y +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_PRINTK_TIME=y +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=7 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +CONFIG_MAGIC_SYSRQ=y +CONFIG_STRIP_ASM_SYMS=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_SHIRQ=y +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR_NMI is not set +# CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DEBUG_LIST=y +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_BOOT_PRINTK_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y +# CONFIG_LKDTM is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +CONFIG_DYNAMIC_DEBUG=y +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_ASYNC_RAID6_TEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX is not set +CONFIG_STRICT_DEVMEM=y +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_RODATA is not set +CONFIG_DEBUG_LL=y +CONFIG_DEBUG_LL_UART_NONE=y +# CONFIG_DEBUG_ICEDCC is not set +# CONFIG_DEBUG_SEMIHOSTING is not set +CONFIG_EARLY_PRINTK=y +# CONFIG_OC_ETM is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_XOR_BLOCKS=m +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_ASYNC_PQ=m +CONFIG_ASYNC_RAID6_RECOV=m +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_USER=m +# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set +CONFIG_CRYPTO_GF128MUL=y +# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_GCM=m +CONFIG_CRYPTO_SEQIV=y + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=m +CONFIG_CRYPTO_CTS=m +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_XTS=m + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_VMAC=m + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_GHASH=m +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_BLOWFISH_COMMON=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SALSA20=m +CONFIG_CRYPTO_SEED=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_ZLIB=y +CONFIG_CRYPTO_LZO=y + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_USER_API=m +CONFIG_CRYPTO_USER_API_HASH=m +CONFIG_CRYPTO_USER_API_SKCIPHER=m +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_RAID6_PQ=m +CONFIG_BITREVERSE=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +CONFIG_CRC7=m +CONFIG_LIBCRC32C=y +# CONFIG_CRC8 is not set +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_IA64=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_LRU_CACHE=m +CONFIG_AVERAGE=y +# CONFIG_CORDIC is not set diff --git a/config/linux-sun7i.config b/config/linux-sun7i.config new file mode 100644 index 000000000..712e2ebd0 --- /dev/null +++ b/config/linux-sun7i.config @@ -0,0 +1,4054 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.4.110 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_KTIME_SCALAR=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_LOCKBREAK=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_NEED_MACH_IO_H=y +CONFIG_NEED_MACH_MEMORY_H=y +CONFIG_GENERIC_BUG=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_HAVE_IRQ_WORK=y +CONFIG_IRQ_WORK=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_XZ is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_FHANDLE=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_AUDIT=y +# CONFIG_AUDITSYSCALL is not set +# CONFIG_AUDIT_LOGINUID_IMMUTABLE is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_DEBUG=y + +# +# RCU Subsystem +# +CONFIG_TREE_PREEMPT_RCU=y +CONFIG_PREEMPT_RCU=y +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +CONFIG_RCU_FAST_NO_HZ=y +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_BOOST is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=19 +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_MEM_RES_CTLR=y +CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y +CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED=y +CONFIG_CGROUP_MEM_RES_CTLR_KMEM=y +CONFIG_CGROUP_PERF=y +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_CGROUP=y +# CONFIG_DEBUG_BLK_CGROUP is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +CONFIG_USER_NS=y +CONFIG_PID_NS=y +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_MM_OWNER=y +# CONFIG_SYSFS_DEPRECATED is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_EXPERT is not set +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +# CONFIG_EMBEDDED is not set +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +CONFIG_PERF_COUNTERS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_JUMP_LABEL=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +CONFIG_BLK_DEV_BSG=y +CONFIG_BLK_DEV_BSGLIB=y +CONFIG_BLK_DEV_INTEGRITY=y +# CONFIG_BLK_DEV_THROTTLING is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +# CONFIG_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_SUNXI_NAND_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_CFQ_GROUP_IOSCHED=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_UNINLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +# CONFIG_INLINE_READ_UNLOCK is not set +# CONFIG_INLINE_READ_UNLOCK_BH is not set +# CONFIG_INLINE_READ_UNLOCK_IRQ is not set +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +# CONFIG_INLINE_WRITE_UNLOCK is not set +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_PRIMA2 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_PICOXCELL is not set +# CONFIG_ARCH_SUN4I is not set +# CONFIG_ARCH_SUN5I is not set +CONFIG_ARCH_SUN7I=y +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C24XX is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set +# CONFIG_ARCH_ZYNQ is not set +# CONFIG_GPIO_PCA953X is not set +CONFIG_KEYBOARD_GPIO_POLLED=m + +# +# System MMU +# + +# +# Allwinner's sunxi options +# +CONFIG_SW_DEBUG_UART=0 +CONFIG_SUNXI_MULTIPLATFORM=y +CONFIG_SUNXI_SCALING_MIN=60 +CONFIG_PLAT_SUNXI=y + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_LPAE is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +# CONFIG_CACHE_L2X0 is not set +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_ARCH_HAS_BARRIERS=y +CONFIG_ARM_NR_BANKS=8 +CONFIG_CPU_HAS_PMU=y +CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_742230 is not set +# CONFIG_ARM_ERRATA_742231 is not set +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764369 is not set +# CONFIG_ARM_ERRATA_775420 is not set +CONFIG_ARM_GIC=y +# CONFIG_FIQ_DEBUGGER is not set + +# +# Bus support +# +CONFIG_ARM_AMBA=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_HAVE_SMP=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_ARM_CPU_TOPOLOGY=y +CONFIG_SCHED_MC=y +CONFIG_SCHED_SMT=y +CONFIG_HAVE_ARM_SCU=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_HAVE_ARM_TWD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_NR_CPUS=2 +CONFIG_HOTPLUG_CPU=y +CONFIG_LOCAL_TIMERS=y +CONFIG_ARCH_NR_GPIO=0 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_HZ=100 +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HW_PERF_EVENTS=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_KSM=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_CLEANCACHE is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set + +# +# Boot options +# +# CONFIG_USE_OF is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/mmc0p1 rw init=/init loglevel=8" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_EXTEND is not set +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_XIP_KERNEL is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_FANTASY is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_GOV_FANTASY is not set +CONFIG_CPU_FREQ_USR_EVNT_NOTIFY=y +CONFIG_CPU_FREQ_DVFS=y + +# +# ARM CPU frequency scaling drivers +# +# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set +# CONFIG_ARM_EXYNOS4X12_CPUFREQ is not set +# CONFIG_ARM_EXYNOS5250_CPUFREQ is not set +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_HAS_WAKELOCK=y +CONFIG_WAKELOCK=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM=y +CONFIG_PM_DEBUG=y +CONFIG_PM_ADVANCED_DEBUG=y +# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_CAN_PM_TRACE=y +# CONFIG_APM_EMULATION is not set +CONFIG_PM_CLK=y +CONFIG_CPU_PM=y +# CONFIG_SUSPEND_TIME is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=y +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_FIB_TRIE_STATS=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_ROUTE_CLASSID=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=y +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_ARPD=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_INET_UDP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_WESTWOOD=y +CONFIG_TCP_CONG_HTCP=y +CONFIG_TCP_CONG_HSTCP=y +CONFIG_TCP_CONG_HYBLA=y +CONFIG_TCP_CONG_VEGAS=y +CONFIG_TCP_CONG_SCALABLE=y +CONFIG_TCP_CONG_LP=y +CONFIG_TCP_CONG_VENO=y +CONFIG_TCP_CONG_YEAH=y +CONFIG_TCP_CONG_ILLINOIS=y +# CONFIG_DEFAULT_BIC is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_HTCP is not set +# CONFIG_DEFAULT_HYBLA is not set +# CONFIG_DEFAULT_VEGAS is not set +# CONFIG_DEFAULT_VENO is not set +# CONFIG_DEFAULT_WESTWOOD is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6=y +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +# CONFIG_ANDROID_PARANOID_NETWORK is not set +CONFIG_NET_ACTIVITY_STATS=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NETWORK_PHY_TIMESTAMPING=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_ACCT=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_BROADCAST=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_NETLINK_TIMEOUT=m +CONFIG_NETFILTER_TPROXY=m +CONFIG_NETFILTER_XTABLES=m + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_CONNMARK=m +CONFIG_NETFILTER_XT_SET=m + +# +# Xtables targets +# +CONFIG_NETFILTER_XT_TARGET_AUDIT=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ECN=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_QUOTA2=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_MAX=256 +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS SH scheduler +# +CONFIG_IP_VS_SH_TAB_BITS=8 + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_NFCT=y +CONFIG_IP_VS_PE_SIP=m + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_REJECT_SKERR=y +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PROTO_DCCP=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m +CONFIG_NF_NAT_SIP=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_REJECT_SKERR=y +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_L2TP=m +# CONFIG_L2TP_DEBUGFS is not set +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_STP=m +CONFIG_GARP=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_IGMP_SNOOPING=y +# CONFIG_NET_DSA is not set +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +# CONFIG_DECNET is not set +CONFIG_LLC=m +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=y +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_CHOKE=m +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_PLUG=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_CLS_CGROUP is not set +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +CONFIG_BATMAN_ADV=m +# CONFIG_BATMAN_ADV_DEBUG is not set +CONFIG_OPENVSWITCH=m +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +CONFIG_NETPRIO_CGROUP=m +CONFIG_BQL=y +CONFIG_HAVE_BPF_JIT=y +# CONFIG_BPF_JIT is not set + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y + +# +# IrDA options +# +# CONFIG_IRDA_CACHE_LAST_LSAP is not set +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +# CONFIG_DONGLE is not set +CONFIG_KINGSUN_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +CONFIG_KS959_DONGLE=m + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTSDIO=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +# CONFIG_BT_HCIVHCI is not set +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_BT_ATH3K=m +CONFIG_BT_WILINK=m +CONFIG_AF_RXRPC=m +# CONFIG_AF_RXRPC_DEBUG is not set +CONFIG_RXKAD=m +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=y +# CONFIG_NL80211_TESTMODE is not set +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_WEXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_LIB80211=m +CONFIG_LIB80211_CRYPT_WEP=m +CONFIG_LIB80211_CRYPT_CCMP=m +CONFIG_LIB80211_CRYPT_TKIP=m +# CONFIG_LIB80211_DEBUG is not set +CONFIG_CFG80211_ALLOW_RECONNECT=y +CONFIG_MAC80211=m +CONFIG_MAC80211_HAS_RC=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_WIMAX=m +CONFIG_WIMAX_DEBUG_LEVEL=8 +CONFIG_RFKILL=y +CONFIG_RFKILL_PM=y +CONFIG_RFKILL_LEDS=y +CONFIG_RFKILL_INPUT=y +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RFKILL_GPIO is not set +CONFIG_SUNXI_RFKILL=y +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_SYNC is not set +# CONFIG_CMA is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +# CONFIG_MTD is not set +CONFIG_PARPORT=m +# CONFIG_PARPORT_PC is not set +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y +CONFIG_PARPORT_NOT_PC=y +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +CONFIG_BLK_DEV_CRYPTOLOOP=y +CONFIG_BLK_DEV_DRBD=m +# CONFIG_DRBD_FAULT_INJECTION is not set +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_OSD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +# CONFIG_BLK_DEV_XIP is not set +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set +CONFIG_SUNXI_NAND=y +# CONFIG_SUNXI_NAND_COMPAT_DEV is not set +# CONFIG_SUNXI_NAND_TEST is not set + +# +# Misc devices +# +CONFIG_SENSORS_LIS3LV02D=m +# CONFIG_AD525X_DPOT is not set +# CONFIG_SUN4I_VIBRATOR is not set +CONFIG_SUNXI_DBGREG=m +# CONFIG_ATMEL_PWM is not set +CONFIG_SUNXI_PWM=y +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_SENSORS_AK8975 is not set +# CONFIG_DS1682 is not set +CONFIG_TI_DAC7512=m +# CONFIG_UID_STAT is not set +CONFIG_BMP085=m +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_WL127X_RFKILL is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=m +CONFIG_EEPROM_AT25=m +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +CONFIG_EEPROM_93CX6=m +CONFIG_EEPROM_93XX46=m +CONFIG_IWMC3200TOP=m +# CONFIG_IWMC3200TOP_DEBUG is not set +# CONFIG_IWMC3200TOP_DEBUGFS is not set + +# +# Texas Instruments shared transport line discipline +# +CONFIG_TI_ST=m +CONFIG_SENSORS_LIS3_SPI=m +CONFIG_SENSORS_LIS3_I2C=m + +# +# Altera FPGA firmware download module +# +CONFIG_ALTERA_STAPL=m + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +CONFIG_SCSI_NETLINK=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +CONFIG_ISCSI_TCP=m +# CONFIG_ISCSI_BOOT_SYSFS is not set +CONFIG_LIBFC=m +CONFIG_LIBFCOE=m +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +CONFIG_SCSI_OSD_INITIATOR=m +CONFIG_SCSI_OSD_ULD=m +CONFIG_SCSI_OSD_DPRINT_SENSE=1 +# CONFIG_SCSI_OSD_DEBUG is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +# CONFIG_SATA_AHCI_PLATFORM is not set +CONFIG_SW_SATA_AHCI_PLATFORM=y +# CONFIG_ATA_SFF is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +CONFIG_MD_RAID1=m +# CONFIG_MD_RAID10 is not set +CONFIG_MD_RAID456=m +# CONFIG_MULTICORE_RAID456 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_DEBUG=y +CONFIG_DM_BUFIO=m +CONFIG_DM_PERSISTENT_DATA=m +CONFIG_DM_CRYPT=y +CONFIG_DM_SNAPSHOT=y +CONFIG_DM_THIN_PROVISIONING=m +# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set +# CONFIG_DM_DEBUG_SPACE_MAPS is not set +CONFIG_DM_MIRROR=y +CONFIG_DM_RAID=m +CONFIG_DM_LOG_USERSPACE=m +CONFIG_DM_ZERO=y +CONFIG_DM_MULTIPATH=y +CONFIG_DM_MULTIPATH_QL=y +CONFIG_DM_MULTIPATH_ST=y +CONFIG_DM_DELAY=m +CONFIG_DM_UEVENT=y +# CONFIG_DM_FLAKEY is not set +CONFIG_DM_VERITY=m +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +CONFIG_BONDING=y +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +CONFIG_MII=y +# CONFIG_NET_TEAM is not set +CONFIG_MACVLAN=y +CONFIG_MACVTAP=y +CONFIG_NETCONSOLE=y +CONFIG_NETCONSOLE_DYNAMIC=y +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y +CONFIG_TUN=m +CONFIG_VETH=y + +# +# CAIF transport drivers +# +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +CONFIG_NET_VENDOR_CHELSIO=y +CONFIG_NET_VENDOR_CIRRUS=y +# CONFIG_CS89x0 is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_DLINK=y +# CONFIG_DE600 is not set +# CONFIG_DE620 is not set +CONFIG_NET_VENDOR_FARADAY=y +# CONFIG_FTMAC100 is not set +# CONFIG_FTGMAC100 is not set +CONFIG_NET_VENDOR_INTEL=y +CONFIG_NET_VENDOR_I825XX=y +CONFIG_NET_VENDOR_MARVELL=y +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NET_VENDOR_8390=y +# CONFIG_AX88796 is not set +# CONFIG_ETHOC is not set +CONFIG_NET_VENDOR_SEEQ=y +# CONFIG_SEEQ8005 is not set +CONFIG_NET_VENDOR_SMSC=y +# CONFIG_SMC91X is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_SUNXI_EMAC=y +CONFIG_SUNXI_GMAC=y +CONFIG_GMAC_SCRIPT_SYS=y +CONFIG_GMAC_CLK_SYS=y +CONFIG_GMAC_RING=y +# CONFIG_GMAC_CHAINED is not set +CONFIG_PHYLIB=y +CONFIG_SWCONFIG=y + +# +# MII PHY device drivers +# +# CONFIG_AMD_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +CONFIG_FIXED_PHY=y +CONFIG_MDIO_BITBANG=y +# CONFIG_MDIO_GPIO is not set +CONFIG_B53=y +CONFIG_B53_SPI_DRIVER=y +CONFIG_B53_PHY_DRIVER=y +CONFIG_B53_SRAB_DRIVER=y +CONFIG_B53_PHY_FIXUP=y +CONFIG_MICREL_KS8995MA=m +CONFIG_PLIP=m +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +# CONFIG_PPP_MULTILINK is not set +CONFIG_PPPOE=y +CONFIG_PPTP=m +CONFIG_PPPOL2TP=m +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +CONFIG_SLIP=m +CONFIG_SLHC=y +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_QF9700=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_CDC_NCM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +# CONFIG_USB_NET_GL620A is not set +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_PLUSB is not set +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_HSO=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_WLAN=y +CONFIG_LIBERTAS_THINFIRM=m +# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AT76C50X_USB=m +CONFIG_USB_ZD1201=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_WIFI_CONTROL_FUNC is not set +CONFIG_ATH_COMMON=m +# CONFIG_ATH_DEBUG is not set +CONFIG_ATH9K_HW=m +CONFIG_ATH9K_COMMON=m +CONFIG_ATH9K_BTCOEX_SUPPORT=y +CONFIG_ATH9K=m +CONFIG_ATH9K_AHB=y +# CONFIG_ATH9K_DEBUGFS is not set +# CONFIG_ATH9K_LEGACY_RATE_CONTROL is not set +CONFIG_ATH9K_HTC=m +# CONFIG_ATH9K_HTC_DEBUGFS is not set +CONFIG_CARL9170=m +CONFIG_CARL9170_LEDS=y +CONFIG_CARL9170_WPC=y +CONFIG_ATH6KL=m +CONFIG_ATH6KL_SDIO=m +CONFIG_ATH6KL_USB=m +# CONFIG_ATH6KL_DEBUG is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_BCMDHD is not set +CONFIG_AP6210=m +CONFIG_AP6210_FW_PATH="/lib/firmware/ap6210/fw_bcmxxxx.bin" +CONFIG_AP6210_NVRAM_PATH="/lib/firmware/ap6210/nvram_apxxxx.txt" +CONFIG_AP6210_OOB=y +# CONFIG_AP6210_SDIO_IRQ is not set +CONFIG_BRCMUTIL=m +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_SDIO=y +CONFIG_BRCMFMAC_USB=y +# CONFIG_BRCMDBG is not set +# CONFIG_BCM4330 is not set +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set +CONFIG_IWM=m +# CONFIG_IWM_DEBUG is not set +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_LIBERTAS_SPI=m +# CONFIG_LIBERTAS_DEBUG is not set +# CONFIG_LIBERTAS_MESH is not set +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +CONFIG_P54_SPI=m +CONFIG_P54_SPI_DEFAULT_EEPROM=y +CONFIG_P54_LEDS=y +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT33XX=y +CONFIG_RT2800USB_RT35XX=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RT2800_LIB=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_DEBUG is not set +# CONFIG_RTL8192CU is not set +CONFIG_WL1251=m +CONFIG_WL1251_SPI=m +CONFIG_WL1251_SDIO=m +CONFIG_WL12XX_MENU=m +CONFIG_WL12XX=m +CONFIG_WL12XX_SPI=m +CONFIG_WL12XX_SDIO=m +CONFIG_WL12XX_PLATFORM_DATA=y +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_RTL8192CU_SW=m +CONFIG_RTL8188EU=m +CONFIG_RTL8189ES=m +CONFIG_RTL8723AS=m +CONFIG_RTXX7X_SW=m + +# +# WiMAX Wireless Broadband devices +# +CONFIG_WIMAX_I2400M=m +CONFIG_WIMAX_I2400M_USB=m +CONFIG_WIMAX_I2400M_SDIO=m +CONFIG_WIMAX_IWMC3200_SDIO=y +CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8 +# CONFIG_WAN is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_FF_MEMLESS=y +CONFIG_INPUT_POLLDEV=y +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +CONFIG_INPUT_KEYRESET=y + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ADP5588=m +CONFIG_KEYBOARD_ADP5589=m +CONFIG_KEYBOARD_ATKBD=y +CONFIG_KEYBOARD_QT1070=m +CONFIG_KEYBOARD_QT2160=m +CONFIG_KEYBOARD_LKKBD=m +CONFIG_KEYBOARD_GPIO=m +CONFIG_KEYBOARD_TCA6416=m +CONFIG_KEYBOARD_TCA8418=m +CONFIG_KEYBOARD_MATRIX=m +CONFIG_KEYBOARD_LM8323=m +CONFIG_KEYBOARD_MAX7359=m +CONFIG_KEYBOARD_MCS=m +CONFIG_KEYBOARD_MPR121=m +CONFIG_KEYBOARD_NEWTON=m +CONFIG_KEYBOARD_OPENCORES=m +CONFIG_KEYBOARD_SAMSUNG=m +CONFIG_KEYBOARD_STOWAWAY=m +CONFIG_KEYBOARD_SUNKBD=m +CONFIG_KEYBOARD_OMAP4=m +CONFIG_KEYBOARD_XTKBD=m +CONFIG_KEYBOARD_SUN4IKEYPAD=m +CONFIG_KEYBOARD_SUN4I_KEYBOARD=m +# CONFIG_KEYBOARD_SUN4I_KEYBOARD_FEX is not set +CONFIG_KEYBOARD_HV2605_KEYBOARD=y +CONFIG_IR_SUNXI=m +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +CONFIG_MOUSE_SYNAPTICS_USB=m +CONFIG_INPUT_JOYSTICK=y +# CONFIG_JOYSTICK_ANALOG is not set +# CONFIG_JOYSTICK_A3D is not set +# CONFIG_JOYSTICK_ADI is not set +# CONFIG_JOYSTICK_COBRA is not set +# CONFIG_JOYSTICK_GF2K is not set +# CONFIG_JOYSTICK_GRIP is not set +# CONFIG_JOYSTICK_GRIP_MP is not set +# CONFIG_JOYSTICK_GUILLEMOT is not set +# CONFIG_JOYSTICK_INTERACT is not set +# CONFIG_JOYSTICK_SIDEWINDER is not set +# CONFIG_JOYSTICK_TMDC is not set +# CONFIG_JOYSTICK_IFORCE is not set +# CONFIG_JOYSTICK_WARRIOR is not set +# CONFIG_JOYSTICK_MAGELLAN is not set +# CONFIG_JOYSTICK_SPACEORB is not set +# CONFIG_JOYSTICK_SPACEBALL is not set +# CONFIG_JOYSTICK_STINGER is not set +# CONFIG_JOYSTICK_TWIDJOY is not set +# CONFIG_JOYSTICK_ZHENHUA is not set +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +# CONFIG_JOYSTICK_AS5011 is not set +# CONFIG_JOYSTICK_JOYDUMP is not set +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_WALKERA0701=m +CONFIG_INPUT_TABLET=y +CONFIG_TABLET_USB_ACECAD=m +CONFIG_TABLET_USB_AIPTEK=m +CONFIG_TABLET_USB_GTCO=m +CONFIG_TABLET_USB_HANWANG=m +CONFIG_TABLET_USB_KBTAB=m +CONFIG_TABLET_USB_WACOM=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_AD7877=m +CONFIG_TOUCHSCREEN_AD7879=m +CONFIG_TOUCHSCREEN_AD7879_I2C=m +CONFIG_TOUCHSCREEN_AD7879_SPI=m +CONFIG_TOUCHSCREEN_ATMEL_MXT=m +CONFIG_TOUCHSCREEN_AUO_PIXCIR=m +CONFIG_TOUCHSCREEN_BU21013=m +CONFIG_TOUCHSCREEN_CY8CTMG110=m +CONFIG_TOUCHSCREEN_CYTTSP_CORE=m +CONFIG_TOUCHSCREEN_CYTTSP_I2C=m +CONFIG_TOUCHSCREEN_CYTTSP_SPI=m +CONFIG_TOUCHSCREEN_DYNAPRO=m +CONFIG_TOUCHSCREEN_HAMPSHIRE=m +CONFIG_TOUCHSCREEN_EETI=m +# CONFIG_TOUCHSCREEN_EGALAX is not set +CONFIG_TOUCHSCREEN_FUJITSU=m +CONFIG_TOUCHSCREEN_ILI210X=m +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_WACOM_W8001=m +CONFIG_TOUCHSCREEN_MAX11801=m +CONFIG_TOUCHSCREEN_MCS5000=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_INEXIO=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_TOUCHSCREEN_PENMOUNT=m +CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI=m +CONFIG_TOUCHSCREEN_TOUCHRIGHT=m +CONFIG_TOUCHSCREEN_TOUCHWIN=m +CONFIG_TOUCHSCREEN_PIXCIR=m +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_TOUCHSCREEN_USB_EGALAX=y +CONFIG_TOUCHSCREEN_USB_PANJIT=y +CONFIG_TOUCHSCREEN_USB_3M=y +CONFIG_TOUCHSCREEN_USB_ITM=y +CONFIG_TOUCHSCREEN_USB_ETURBO=y +CONFIG_TOUCHSCREEN_USB_GUNZE=y +CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y +CONFIG_TOUCHSCREEN_USB_IRTOUCH=y +CONFIG_TOUCHSCREEN_USB_IDEALTEK=y +CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y +CONFIG_TOUCHSCREEN_USB_GOTOP=y +CONFIG_TOUCHSCREEN_USB_JASTEC=y +CONFIG_TOUCHSCREEN_USB_ELO=y +CONFIG_TOUCHSCREEN_USB_E2I=y +CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y +CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y +CONFIG_TOUCHSCREEN_USB_NEXIO=y +CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y +CONFIG_TOUCHSCREEN_TOUCHIT213=m +CONFIG_TOUCHSCREEN_TSC_SERIO=m +CONFIG_TOUCHSCREEN_TSC2005=m +CONFIG_TOUCHSCREEN_TSC2007=m +CONFIG_TOUCHSCREEN_W90X900=m +CONFIG_TOUCHSCREEN_ST1232=m +CONFIG_TOUCHSCREEN_TPS6507X=m +CONFIG_TOUCHSCREEN_GT801=m +# CONFIG_TOUCHSCREEN_GT801_2PLUS1_TS is not set +CONFIG_TOUCHSCREEN_GT811=m +CONFIG_TOUCHSCREEN_GT818=m +CONFIG_TOUCHSCREEN_SUN4I_TS=m +CONFIG_TOUCHSCREEN_FT5X_TS=m +CONFIG_TOUCHSCREEN_ZT8031=m +# CONFIG_TOUCHSCREEN_COASIA is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AD714X=m +CONFIG_INPUT_AD714X_I2C=m +CONFIG_INPUT_AD714X_SPI=m +CONFIG_INPUT_BMA150=m +CONFIG_INPUT_MMA8450=m +CONFIG_INPUT_MPU3050=m +CONFIG_INPUT_GP2A=m +CONFIG_INPUT_GPIO_TILT_POLLED=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_KEYCHORD=m +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_KXTJ9=m +CONFIG_INPUT_KXTJ9_POLLED_MODE=y +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_YEALINK=m +CONFIG_INPUT_CM109=m +CONFIG_INPUT_UINPUT=m +CONFIG_INPUT_GPIO=m +CONFIG_INPUT_PCF8574=m +CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +CONFIG_INPUT_ADXL34X=m +CONFIG_INPUT_ADXL34X_I2C=m +CONFIG_INPUT_ADXL34X_SPI=m +CONFIG_INPUT_CMA3000=m +CONFIG_INPUT_CMA3000_I2C=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_AMBAKMI is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_GAMEPORT is not set +CONFIG_GSENSOR=y +CONFIG_SENSORS_BMA250=m +CONFIG_MEMSIC_ECOMPASS=m +CONFIG_SENSORS_MXC622X=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVMEM=y +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_SUNXI=y +CONFIG_SERIAL_8250_NR_UARTS=8 +CONFIG_SERIAL_8250_RUNTIME_UARTS=8 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +CONFIG_PRINTER=m +# CONFIG_LP_CONSOLE is not set +CONFIG_PPDEV=m +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_DCC_TTY is not set +# CONFIG_RAMOOPS is not set +CONFIG_SUNXI_G2D=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=m + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +CONFIG_I2C_SUNXI=y +# CONFIG_SUNXI_IIC_PRINT_TRANSFER_INFO is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_BUTTERFLY is not set +CONFIG_SPI_GPIO=y +# CONFIG_SPI_LM70_LLP is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX_PCI is not set +CONFIG_SPI_SUN7I=y +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=m +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_HSI is not set + +# +# PPS support +# +CONFIG_PPS=m +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_PARPORT is not set +# CONFIG_PPS_CLIENT_GPIO is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=m +# CONFIG_DP83640_PHY is not set +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_PL061 is not set +CONFIG_GPIO_SUNXI=y + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +CONFIG_W1=m +CONFIG_W1_CON=y +CONFIG_W1_SUNXI=m + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m +CONFIG_W1_MASTER_DS1WM=m +CONFIG_W1_MASTER_GPIO=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2408=m +CONFIG_W1_SLAVE_DS2423=m +CONFIG_W1_SLAVE_DS2431=m +CONFIG_W1_SLAVE_DS2433=m +# CONFIG_W1_SLAVE_DS2433_CRC is not set +CONFIG_W1_SLAVE_DS2760=m +CONFIG_W1_SLAVE_DS2780=m +CONFIG_W1_SLAVE_DS2781=m +CONFIG_W1_SLAVE_BQ27000=m +CONFIG_POWER_SUPPLY=y +CONFIG_AW_AXP=y +# CONFIG_AW_AXP18 is not set +# CONFIG_AW_AXP19 is not set +CONFIG_AW_AXP20=y +CONFIG_AXP_CHARGEINIT=y +CONFIG_AXP_CHGCHANGE=y +CONFIG_AXP_HWMON=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +CONFIG_AXP152=y +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2760 is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_SMB347 is not set +CONFIG_HWMON=y +CONFIG_HWMON_VID=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +CONFIG_SENSORS_MMA7660=m +CONFIG_SENSORS_A20_TP_HWMON=m +CONFIG_SENSORS_AD7314=m +CONFIG_SENSORS_AD7414=m +CONFIG_SENSORS_AD7418=m +CONFIG_SENSORS_ADCXX=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1029=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ADT7411=m +CONFIG_SENSORS_ADT7462=m +CONFIG_SENSORS_ADT7470=m +CONFIG_SENSORS_ADT7475=m +CONFIG_SENSORS_ASC7621=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS620=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_F71882FG=m +CONFIG_SENSORS_F75375S=m +CONFIG_SENSORS_G760A=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_GPIO_FAN=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_JC42=m +CONFIG_SENSORS_LINEAGE=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM70=m +CONFIG_SENSORS_LM73=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_LM93=m +CONFIG_SENSORS_LTC4151=m +CONFIG_SENSORS_LTC4215=m +CONFIG_SENSORS_LTC4245=m +CONFIG_SENSORS_LTC4261=m +CONFIG_SENSORS_LM95241=m +CONFIG_SENSORS_LM95245=m +CONFIG_SENSORS_MAX1111=m +CONFIG_SENSORS_MAX16065=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_MAX1668=y +CONFIG_SENSORS_MAX6639=m +CONFIG_SENSORS_MAX6642=m +CONFIG_SENSORS_MAX6650=m +CONFIG_SENSORS_MCP3021=m +CONFIG_SENSORS_NTC_THERMISTOR=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_PC87427=m +CONFIG_SENSORS_PCF8591=m +CONFIG_PMBUS=m +CONFIG_SENSORS_PMBUS=m +CONFIG_SENSORS_ADM1275=m +CONFIG_SENSORS_LM25066=m +CONFIG_SENSORS_LTC2978=m +CONFIG_SENSORS_MAX16064=m +CONFIG_SENSORS_MAX34440=m +CONFIG_SENSORS_MAX8688=m +CONFIG_SENSORS_UCD9000=m +CONFIG_SENSORS_UCD9200=m +CONFIG_SENSORS_ZL6100=m +CONFIG_SENSORS_SHT15=m +CONFIG_SENSORS_SHT21=m +CONFIG_SENSORS_SMM665=m +CONFIG_SENSORS_DME1737=m +CONFIG_SENSORS_EMC1403=m +CONFIG_SENSORS_EMC2103=m +CONFIG_SENSORS_EMC6W201=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_SCH56XX_COMMON=m +CONFIG_SENSORS_SCH5627=m +CONFIG_SENSORS_SCH5636=m +CONFIG_SENSORS_ADS1015=m +CONFIG_SENSORS_ADS7828=m +CONFIG_SENSORS_ADS7871=m +CONFIG_SENSORS_AMC6821=m +CONFIG_SENSORS_THMC50=m +CONFIG_SENSORS_TMP102=m +CONFIG_SENSORS_TMP401=m +CONFIG_SENSORS_TMP421=m +CONFIG_SENSORS_VT1211=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83793=m +# CONFIG_SENSORS_W83795 is not set +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83L786NG=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_CORE is not set +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_MPCORE_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB=m +CONFIG_SSB_SDIOHOST_POSSIBLE=y +CONFIG_SSB_SDIOHOST=y +# CONFIG_SSB_DEBUG is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=m +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_S5M_CORE is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +CONFIG_MFD_WL1273_CORE=m +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_RC5T583 is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_DUMMY is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_GPIO is not set +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_COMMON=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_DVB_CORE=m +CONFIG_DVB_NET=y +CONFIG_VIDEO_MEDIA=m + +# +# Multimedia drivers +# +CONFIG_RC_CORE=m +CONFIG_LIRC=m +CONFIG_RC_MAP=m +CONFIG_IR_NEC_DECODER=m +CONFIG_IR_RC5_DECODER=m +CONFIG_IR_RC6_DECODER=m +CONFIG_IR_JVC_DECODER=m +CONFIG_IR_SONY_DECODER=m +CONFIG_IR_RC5_SZ_DECODER=m +CONFIG_IR_SANYO_DECODER=m +CONFIG_IR_MCE_KBD_DECODER=m +CONFIG_IR_LIRC_CODEC=m +CONFIG_RC_ATI_REMOTE=m +CONFIG_IR_IMON=m +CONFIG_IR_MCEUSB=m +CONFIG_IR_REDRAT3=m +CONFIG_IR_STREAMZAP=m +# CONFIG_RC_LOOPBACK is not set +# CONFIG_IR_GPIO_CIR is not set +CONFIG_MEDIA_ATTACH=y +CONFIG_MEDIA_TUNER=m +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_MEDIA_TUNER_SIMPLE=m +CONFIG_MEDIA_TUNER_TDA8290=m +CONFIG_MEDIA_TUNER_TDA827X=m +CONFIG_MEDIA_TUNER_TDA18271=m +CONFIG_MEDIA_TUNER_TDA9887=m +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +CONFIG_MEDIA_TUNER_MT20XX=m +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT2063=m +CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_XC2028=m +CONFIG_MEDIA_TUNER_XC5000=m +CONFIG_MEDIA_TUNER_XC4000=m +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_MEDIA_TUNER_MXL5007T=m +CONFIG_MEDIA_TUNER_MC44S803=m +CONFIG_MEDIA_TUNER_MAX2165=m +CONFIG_MEDIA_TUNER_TDA18218=m +CONFIG_MEDIA_TUNER_TDA18212=m +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEOBUF_GEN=m +CONFIG_VIDEOBUF_VMALLOC=m +CONFIG_VIDEOBUF_DMA_CONTIG=m +CONFIG_VIDEOBUF_DVB=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEOBUF2_CORE=m +CONFIG_VIDEOBUF2_MEMOPS=m +CONFIG_VIDEOBUF2_VMALLOC=m +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_VIDEO_HELPER_CHIPS_AUTO=y +CONFIG_VIDEO_IR_I2C=m + +# +# Audio decoders, processors and mixers +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_WM8775=m + +# +# RDS decoders +# + +# +# Video decoders +# +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_TVP5150=m + +# +# Video and audio decoders +# +CONFIG_VIDEO_CX25840=m + +# +# MPEG video encoders +# +CONFIG_VIDEO_CX2341X=m + +# +# Video encoders +# + +# +# Camera sensor devices +# +CONFIG_VIDEO_MT9V011=m + +# +# Flash devices +# + +# +# Video improvement chips +# + +# +# Miscelaneous helper chips +# +# CONFIG_VIDEO_VIVI is not set +CONFIG_V4L_USB_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=m +CONFIG_USB_M5602=m +CONFIG_USB_STV06XX=m +CONFIG_USB_GL860=m +CONFIG_USB_GSPCA_BENQ=m +CONFIG_USB_GSPCA_CONEX=m +CONFIG_USB_GSPCA_CPIA1=m +CONFIG_USB_GSPCA_ETOMS=m +CONFIG_USB_GSPCA_FINEPIX=m +CONFIG_USB_GSPCA_JEILINJ=m +CONFIG_USB_GSPCA_JL2005BCD=m +CONFIG_USB_GSPCA_KINECT=m +CONFIG_USB_GSPCA_KONICA=m +CONFIG_USB_GSPCA_MARS=m +CONFIG_USB_GSPCA_MR97310A=m +CONFIG_USB_GSPCA_NW80X=m +CONFIG_USB_GSPCA_OV519=m +CONFIG_USB_GSPCA_OV534=m +CONFIG_USB_GSPCA_OV534_9=m +CONFIG_USB_GSPCA_PAC207=m +CONFIG_USB_GSPCA_PAC7302=m +CONFIG_USB_GSPCA_PAC7311=m +CONFIG_USB_GSPCA_SE401=m +CONFIG_USB_GSPCA_SN9C2028=m +CONFIG_USB_GSPCA_SN9C20X=m +CONFIG_USB_GSPCA_SONIXB=m +CONFIG_USB_GSPCA_SONIXJ=m +CONFIG_USB_GSPCA_SPCA500=m +CONFIG_USB_GSPCA_SPCA501=m +CONFIG_USB_GSPCA_SPCA505=m +CONFIG_USB_GSPCA_SPCA506=m +CONFIG_USB_GSPCA_SPCA508=m +CONFIG_USB_GSPCA_SPCA561=m +CONFIG_USB_GSPCA_SPCA1528=m +CONFIG_USB_GSPCA_SQ905=m +CONFIG_USB_GSPCA_SQ905C=m +CONFIG_USB_GSPCA_SQ930X=m +CONFIG_USB_GSPCA_STK014=m +CONFIG_USB_GSPCA_STV0680=m +CONFIG_USB_GSPCA_SUNPLUS=m +CONFIG_USB_GSPCA_T613=m +CONFIG_USB_GSPCA_TOPRO=m +CONFIG_USB_GSPCA_TV8532=m +CONFIG_USB_GSPCA_VC032X=m +CONFIG_USB_GSPCA_VICAM=m +CONFIG_USB_GSPCA_XIRLINK_CIT=m +CONFIG_USB_GSPCA_ZC3XX=m +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_PVRUSB2_DVB=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_VIDEO_EM28XX_RC=y +CONFIG_VIDEO_TLG2300=m +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_RC=y +CONFIG_VIDEO_CX231XX_ALSA=m +CONFIG_VIDEO_CX231XX_DVB=m +CONFIG_VIDEO_TM6000=m +CONFIG_VIDEO_TM6000_ALSA=m +CONFIG_VIDEO_TM6000_DVB=m +CONFIG_VIDEO_USBVISION=m +CONFIG_USB_ET61X251=m +CONFIG_USB_SN9C102=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set +CONFIG_USB_PWC_INPUT_EVDEV=y +# CONFIG_VIDEO_CPIA2 is not set +CONFIG_USB_ZR364XX=m +CONFIG_USB_STKWEBCAM=m +CONFIG_USB_S2255=m +# CONFIG_V4L_ISA_PARPORT_DRIVERS is not set +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_SOC_CAMERA=m +CONFIG_SOC_CAMERA_IMX074=m +CONFIG_SOC_CAMERA_MT9M001=m +CONFIG_SOC_CAMERA_MT9M111=m +CONFIG_SOC_CAMERA_MT9T031=m +CONFIG_SOC_CAMERA_MT9T112=m +CONFIG_SOC_CAMERA_MT9V022=m +CONFIG_SOC_CAMERA_RJ54N1=m +CONFIG_SOC_CAMERA_TW9910=m +CONFIG_SOC_CAMERA_PLATFORM=m +CONFIG_SOC_CAMERA_OV2640=m +CONFIG_SOC_CAMERA_OV5642=m +CONFIG_SOC_CAMERA_OV6650=m +CONFIG_SOC_CAMERA_OV772X=m +CONFIG_SOC_CAMERA_OV9640=m +CONFIG_SOC_CAMERA_OV9740=m +# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set +# CONFIG_VIDEO_SH_MOBILE_CEU is not set +CONFIG_V4L_MEM2MEM_DRIVERS=y +# CONFIG_VIDEO_MEM2MEM_TESTDEV is not set +CONFIG_VIDEO_SUNXI_CEDAR=y +CONFIG_VIDEO_DECODER_SUNXI=y +CONFIG_VIDEO_AVS_COUNTER=y +CONFIG_VIDEO_CSI_SUN4I=y +CONFIG_CSI_DEV_SEL=m +CONFIG_CSI0_SUN4I=m +CONFIG_CSI1_SUN4I=m +CONFIG_CSI_OV7670=m +CONFIG_CSI_GT2005=m +CONFIG_CSI_GC0308=m +CONFIG_CSI_HI704=m +CONFIG_CSI_SP0838=m +CONFIG_CSI_MT9M112=m +CONFIG_CSI_MT9M113=m +CONFIG_CSI_OV2655=m +CONFIG_CSI_HI253=m +CONFIG_CSI_MT9D112=m +CONFIG_CSI_GC0307=m +CONFIG_CSI_OV5640=m +CONFIG_RADIO_ADAPTERS=y +CONFIG_RADIO_SI470X=y +CONFIG_USB_SI470X=m +CONFIG_I2C_SI470X=m +CONFIG_USB_MR800=m +CONFIG_USB_DSBR=m +CONFIG_I2C_SI4713=m +CONFIG_RADIO_SI4713=m +CONFIG_USB_KEENE=m +CONFIG_RADIO_TEA5764=m +CONFIG_RADIO_SAA7706H=m +CONFIG_RADIO_TEF6862=m +CONFIG_RADIO_WL1273=m + +# +# Texas Instruments WL128x FM driver (ST based) +# +# CONFIG_RADIO_WL128X is not set +CONFIG_AUDIO_ENGINE=y +CONFIG_ACE_CONFIG=y +CONFIG_PA_CONTROL=y +CONFIG_PA_CONFIG=y +CONFIG_DVB_MAX_ADAPTERS=8 +CONFIG_DVB_DYNAMIC_MINORS=y +CONFIG_DVB_CAPTURE_DRIVERS=y +CONFIG_TTPCI_EEPROM=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_PCTV452E=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_CINERGY_T2=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_DTV5100=m +CONFIG_DVB_USB_AF9015=m +CONFIG_DVB_USB_CE6230=m +CONFIG_DVB_USB_FRIIO=m +CONFIG_DVB_USB_EC168=m +CONFIG_DVB_USB_AZ6007=m +CONFIG_DVB_USB_AZ6027=m +CONFIG_DVB_USB_LME2510=m +CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_USB_IT913X=m +CONFIG_DVB_USB_MXL111SF=m +CONFIG_DVB_USB_RTL28XXU=m +CONFIG_SMS_SIANO_MDTV=m + +# +# Siano module components +# +CONFIG_SMS_USB_DRV=m +CONFIG_SMS_SDIO_DRV=m + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported DVB Frontends +# +# CONFIG_DVB_FE_CUSTOMISE is not set + +# +# Multistandard (satellite) frontends +# +CONFIG_DVB_STB0899=m +CONFIG_DVB_STB6100=m +CONFIG_DVB_STV090x=m +CONFIG_DVB_STV6110x=m + +# +# Multistandard (cable + terrestrial) frontends +# +CONFIG_DVB_DRXK=m +CONFIG_DVB_TDA18271C2DD=m + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_CX24123=m +CONFIG_DVB_MT312=m +CONFIG_DVB_ZL10039=m +CONFIG_DVB_S5H1420=m +CONFIG_DVB_STV0288=m +CONFIG_DVB_STB6000=m +CONFIG_DVB_STV0299=m +CONFIG_DVB_STV6110=m +CONFIG_DVB_STV0900=m +CONFIG_DVB_TDA10086=m +CONFIG_DVB_TUNER_ITD1000=m +CONFIG_DVB_TUNER_CX24113=m +CONFIG_DVB_TDA826X=m +CONFIG_DVB_CX24116=m +CONFIG_DVB_SI21XX=m +CONFIG_DVB_DS3000=m +CONFIG_DVB_TDA10071=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_CX22702=m +CONFIG_DVB_DRXD=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_DIB7000M=m +CONFIG_DVB_DIB7000P=m +CONFIG_DVB_TDA10048=m +CONFIG_DVB_AF9013=m +CONFIG_DVB_EC100=m +CONFIG_DVB_CXD2820R=m +CONFIG_DVB_RTL2830=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_TDA10023=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m +CONFIG_DVB_LGDT3305=m +CONFIG_DVB_S5H1409=m +CONFIG_DVB_S5H1411=m + +# +# ISDB-T (terrestrial) frontends +# +CONFIG_DVB_S921=m +CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m + +# +# Digital terrestrial only tuners/PLL +# +CONFIG_DVB_PLL=m +CONFIG_DVB_TUNER_DIB0070=m +CONFIG_DVB_TUNER_DIB0090=m + +# +# SEC control devices for DVB-S +# +CONFIG_DVB_LNBP21=m +CONFIG_DVB_LNBP22=m +CONFIG_DVB_ISL6421=m +CONFIG_DVB_ISL6423=m +CONFIG_DVB_A8293=m +CONFIG_DVB_LGS8GXX=m +CONFIG_DVB_ATBM8830=m +CONFIG_DVB_IX2505V=m +CONFIG_DVB_IT913X_FE=m +CONFIG_DVB_M88RS2000=m + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set + +# +# Graphics support +# +CONFIG_FB_TFT=m +CONFIG_FB_TFT_BD663474=m +CONFIG_FB_TFT_HX8340BN=m +CONFIG_FB_TFT_HX8347D=m +CONFIG_FB_TFT_HX8353D=m +CONFIG_FB_TFT_ILI9320=m +CONFIG_FB_TFT_ILI9325=m +CONFIG_FB_TFT_ILI9340=m +CONFIG_FB_TFT_ILI9341=m +CONFIG_FB_TFT_ILI9486=m +CONFIG_FB_TFT_PCD8544=m +CONFIG_FB_TFT_RA8875=m +CONFIG_FB_TFT_S6D02A1=m +CONFIG_FB_TFT_S6D1121=m +CONFIG_FB_TFT_SSD1289=m +CONFIG_FB_TFT_SSD1306=m +CONFIG_FB_TFT_SSD1331=m +CONFIG_FB_TFT_SSD1351=m +CONFIG_FB_TFT_ST7735R=m +CONFIG_FB_TFT_TINYLCD=m +CONFIG_FB_TFT_TLS8204=m +CONFIG_FB_TFT_UPD161704=m +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m +CONFIG_DRM=m +CONFIG_DRM_USB=m +CONFIG_DRM_KMS_HELPER=m +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set + +# +# I2C encoder or helper chips +# +CONFIG_DRM_I2C_CH7006=m +CONFIG_DRM_I2C_SIL164=m +CONFIG_DRM_MALI=m +CONFIG_DRM_UDL=m +# CONFIG_ION is not set +CONFIG_MALI=m +CONFIG_MALI400=m +CONFIG_MALI400_DEBUG=y +# CONFIG_MALI400_GPU_UTILIZATION is not set +CONFIG_UMP=m +CONFIG_UMP_DEBUG=y +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_IMAGEBLIT=m +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=m +# CONFIG_FB_WMT_GE_ROPS is not set +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +CONFIG_FB_BACKLIGHT=y +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +CONFIG_FB_SUNXI=y +CONFIG_FB_SUNXI_RESERVED_MEM=y +CONFIG_FB_SUNXI_UMP=y +CONFIG_FB_SUNXI_LCD=y +CONFIG_FB_SUNXI_HDMI=y +CONFIG_HDMI_CEC=m +# CONFIG_FB_ARMCLCD is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_TMIO is not set +CONFIG_FB_SMSCUFX=m +CONFIG_FB_UDL=m +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_EXYNOS_VIDEO is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=m +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_PLATFORM is not set +# CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_LCD_AMS369FG06 is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=m +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LP855X is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_LOGO is not set +CONFIG_SOUND=y +CONFIG_SOUND_OSS_CORE=y +CONFIG_SOUND_OSS_CORE_PRECLAIM=y +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_JACK=y +CONFIG_SND_SEQUENCER=m +# CONFIG_SND_SEQ_DUMMY is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_SEQUENCER_OSS is not set +CONFIG_SND_HRTIMER=y +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_VMASTER=y +CONFIG_SND_RAWMIDI_SEQ=m +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_DRIVERS=y +CONFIG_SND_DUMMY=m +CONFIG_SND_ALOOP=m +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_MTS64 is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +# CONFIG_SND_PORTMAN2X4 is not set +# CONFIG_SND_ARM is not set +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_6FIRE=m +CONFIG_SND_SOC=y +CONFIG_SOUND_SUNXI=y +CONFIG_SND_SUNXI_SOC_CODEC=y +CONFIG_SND_SUNXI_SOC_HDMIAUDIO=y +CONFIG_SND_SUNXI_SOC_SPDIF=y +CONFIG_SND_SUNXI_SOC_I2S_INTERFACE=y +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +CONFIG_HIDRAW=y +# CONFIG_UHID is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=y +CONFIG_HID_ACRUX=m +CONFIG_HID_ACRUX_FF=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_PRODIKEYS=m +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=m +CONFIG_DRAGONRISE_FF=y +CONFIG_HID_EMS_FF=m +CONFIG_HID_ELECOM=m +CONFIG_HID_EZKEY=y +CONFIG_HID_HOLTEK=m +CONFIG_HOLTEK_FF=y +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_KYE=y +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WALTOP=m +CONFIG_HID_GYRATION=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LCPOWER=m +CONFIG_HID_LOGITECH=y +CONFIG_HID_LOGITECH_DJ=m +CONFIG_LOGITECH_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_LOGIG940_FF=y +CONFIG_LOGIWHEELS_FF=y +# CONFIG_HID_MAGICMOUSE is not set +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NTRIG=m +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_PANTHERLORD_FF=y +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +CONFIG_HID_PICOLCD_FB=y +CONFIG_HID_PICOLCD_BACKLIGHT=y +CONFIG_HID_PICOLCD_LCD=y +CONFIG_HID_PICOLCD_LEDS=y +CONFIG_HID_PRIMAX=m +CONFIG_HID_ROCCAT=m +CONFIG_HID_SAITEK=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_GREENASIA=m +CONFIG_GREENASIA_FF=y +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_HID_TIVO=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_THRUSTMASTER_FF=y +CONFIG_HID_WACOM=m +# CONFIG_HID_WACOM_POWER_SUPPLY is not set +CONFIG_HID_WIIMOTE=m +CONFIG_HID_WIIMOTE_EXT=y +CONFIG_HID_ZEROPLUS=m +CONFIG_ZEROPLUS_FF=y +CONFIG_HID_ZYDACRON=m +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB_ARCH_HAS_XHCI is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_DWC3 is not set +CONFIG_USB_MON=y +CONFIG_USB_WUSB_CBAF=m +CONFIG_USB_WUSB_CBAF_DEBUG=y + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_HCD_PLATFORM is not set +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_U132_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +CONFIG_USB_SUNXI_EHCI=y +CONFIG_USB_SUNXI_OHCI=y +CONFIG_USB_SUNXI_COMMON=y +CONFIG_USB_SW_SUNXI_HCD0=y +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_RENESAS_USBHS is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_WDM=m +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_REALTEK=y +CONFIG_REALTEK_AUTOPM=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_STORAGE_ENE_UB6250=y +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +CONFIG_USB_USS720=m +CONFIG_USB_SERIAL=m +CONFIG_USB_EZUSB=y +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F81232=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7715_PARPORT=y +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MOTOROLA=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_HP4X=m +# CONFIG_USB_SERIAL_SAFE is not set +CONFIG_USB_SERIAL_SIEMENS_MPI=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_WWAN=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m +# CONFIG_USB_SERIAL_ZIO is not set +CONFIG_USB_SERIAL_SSU100=m +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_IDMOUSE=m +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +# CONFIG_USB_TEST is not set +CONFIG_USB_ISIGHTFW=m +# CONFIG_USB_YUREX is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_NET2272 is not set +CONFIG_USB_SW_SUNXI_UDC0_SELECT=m +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_SW_SUNXI_UDC0=y +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +CONFIG_USB_AUDIO=m +# CONFIG_GADGET_UAC1 is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_ETH_EEM=y +CONFIG_USB_G_NCM=m +CONFIG_USB_GADGETFS=m +CONFIG_USB_FUNCTIONFS=m +CONFIG_USB_FUNCTIONFS_ETH=y +CONFIG_USB_FUNCTIONFS_RNDIS=y +CONFIG_USB_FUNCTIONFS_GENERIC=y +# CONFIG_USB_FILE_STORAGE is not set +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_G_SERIAL=m +CONFIG_USB_MIDI_GADGET=m +CONFIG_USB_G_PRINTER=m +CONFIG_USB_CDC_COMPOSITE=m +CONFIG_USB_G_ACM_MS=m +CONFIG_USB_G_MULTI=m +CONFIG_USB_G_MULTI_RNDIS=y +CONFIG_USB_G_MULTI_CDC=y +CONFIG_USB_G_HID=m +CONFIG_USB_G_DBGP=m +# CONFIG_USB_G_DBGP_PRINTK is not set +CONFIG_USB_G_DBGP_SERIAL=y +CONFIG_USB_G_WEBCAM=m + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +CONFIG_USB_OTG_WAKELOCK=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ULPI is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_USB_SW_SUNXI_USB=y +CONFIG_USB_SW_SUNXI_USB_MANAGER=y +# CONFIG_USB_SW_SUNXI_USB0_HOST_ONLY is not set +CONFIG_USB_SW_SUNXI_USB0_OTG=y +# CONFIG_USB_SW_SUNXI_USB0_DEVICE_ONLY is not set +# CONFIG_USB_SW_SUNXI_USB0_NULL is not set +CONFIG_USB_SW_SUNXI_USB_DEBUG=y +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_UNSAFE_RESUME=y +# CONFIG_MMC_CLKGATE is not set +# CONFIG_MMC_EMBEDDED_SDIO is not set +CONFIG_MMC_PARANOID_SD_INIT=y + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +# CONFIG_MMC_BLOCK_BOUNCE is not set +# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set +CONFIG_SDIO_UART=m +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_ARMMMCI is not set +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_DW is not set +CONFIG_MMC_SUNXI_NEW=y +# CONFIG_MMC_DEBUG_SUNXI is not set +CONFIG_MMC_PRE_DBGLVL_SUNXI=0 +# CONFIG_MMC_VUB300 is not set +CONFIG_MMC_USHC=m + +# +# MMC/SD/SDIO Card Power Management Drivers +# +CONFIG_MMC_SUNXI_POWER_CONTROL=y + +# +# SUNXI MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +CONFIG_LEDS_SUNXI=y +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA9633 is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_RENESAS_TPU is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_OT200 is not set +CONFIG_LEDS_TRIGGERS=y + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_GPIO=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_SWITCH is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_DS1307=y +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +CONFIG_RTC_DRV_SUN4I=y +# CONFIG_DMADEVICES is not set +CONFIG_AUXDISPLAY=y +# CONFIG_UIO is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_BALLOON is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +CONFIG_USBIP_CORE=m +CONFIG_USBIP_VHCI_HCD=m +CONFIG_USBIP_HOST=m +# CONFIG_USBIP_DEBUG is not set +CONFIG_W35UND=m +CONFIG_PRISM2_USB=m +CONFIG_ECHO=m +# CONFIG_ASUS_OLED is not set +CONFIG_PANEL=m +CONFIG_PANEL_PARPORT=0 +CONFIG_PANEL_PROFILE=5 +# CONFIG_PANEL_CHANGE_MESSAGE is not set +CONFIG_RTLLIB=m +CONFIG_RTLLIB_CRYPTO_CCMP=m +CONFIG_RTLLIB_CRYPTO_TKIP=m +CONFIG_RTLLIB_CRYPTO_WEP=m +CONFIG_R8712U=m +CONFIG_RTS5139=m +# CONFIG_RTS5139_DEBUG is not set +# CONFIG_TRANZPORT is not set +CONFIG_LINE6_USB=m +# CONFIG_LINE6_USB_DEBUG is not set +# CONFIG_LINE6_USB_DUMP_CTRL is not set +# CONFIG_LINE6_USB_DUMP_MIDI is not set +# CONFIG_LINE6_USB_DUMP_PCM is not set +# CONFIG_LINE6_USB_RAW is not set +# CONFIG_LINE6_USB_IMPULSE_RESPONSE is not set +CONFIG_USB_SERIAL_QUATECH2=m +CONFIG_USB_SERIAL_QUATECH_USB2=m +# CONFIG_VT6656 is not set +CONFIG_IIO=m +# CONFIG_IIO_ST_HWMON is not set +# CONFIG_IIO_BUFFER is not set +# CONFIG_IIO_TRIGGER is not set + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_KXSD9 is not set +# CONFIG_LIS3L02DQ is not set + +# +# Analog to digital converters +# +# CONFIG_AD7291 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7606 is not set +# CONFIG_AD799X is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_ADT7310 is not set +# CONFIG_ADT7410 is not set +# CONFIG_AD7280 is not set +# CONFIG_MAX1363 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD5686 is not set +# CONFIG_MAX517 is not set + +# +# Direct Digital Synthesis +# +# CONFIG_AD5930 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_AD9850 is not set +# CONFIG_AD9852 is not set +# CONFIG_AD9910 is not set +# CONFIG_AD9951 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set + +# +# Light sensors +# +# CONFIG_SENSORS_ISL29018 is not set +CONFIG_SENSORS_TSL2563=m +# CONFIG_TSL2583 is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_HMC5843 is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_SIMPLE_DUMMY is not set +CONFIG_FB_SM7XX=m +CONFIG_USB_ENESTORAGE=m +CONFIG_BCM_WIMAX=m +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +CONFIG_SPEAKUP=m +# CONFIG_SPEAKUP_SYNTH_ACNTSA is not set +# CONFIG_SPEAKUP_SYNTH_ACNTPC is not set +# CONFIG_SPEAKUP_SYNTH_APOLLO is not set +# CONFIG_SPEAKUP_SYNTH_AUDPTR is not set +# CONFIG_SPEAKUP_SYNTH_BNS is not set +# CONFIG_SPEAKUP_SYNTH_DECTLK is not set +# CONFIG_SPEAKUP_SYNTH_DECEXT is not set +# CONFIG_SPEAKUP_SYNTH_DECPC is not set +# CONFIG_SPEAKUP_SYNTH_DTLK is not set +# CONFIG_SPEAKUP_SYNTH_KEYPC is not set +# CONFIG_SPEAKUP_SYNTH_LTLK is not set +CONFIG_SPEAKUP_SYNTH_SOFT=m +# CONFIG_SPEAKUP_SYNTH_SPKOUT is not set +# CONFIG_SPEAKUP_SYNTH_TXPRT is not set +# CONFIG_SPEAKUP_SYNTH_DUMMY is not set +CONFIG_TOUCHSCREEN_CLEARPAD_TM1217=m +CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=m +CONFIG_STAGING_MEDIA=y +CONFIG_DVB_AS102=m +CONFIG_EASYCAP=m +# CONFIG_EASYCAP_DEBUG is not set +CONFIG_LIRC_STAGING=y +CONFIG_LIRC_IGORPLUGUSB=m +CONFIG_LIRC_IMON=m +# CONFIG_LIRC_PARALLEL is not set +CONFIG_LIRC_SASEM=m +# CONFIG_LIRC_SERIAL is not set +# CONFIG_LIRC_SIR is not set +CONFIG_LIRC_TTUSBIR=m +CONFIG_LIRC_ZILOG=m + +# +# Android +# +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_LOGGER=y +CONFIG_ANDROID_PERSISTENT_RAM=y +CONFIG_ANDROID_RAM_CONSOLE=y +# CONFIG_PERSISTENT_TRACER is not set +CONFIG_ANDROID_TIMED_OUTPUT=y +# CONFIG_ANDROID_TIMED_GPIO is not set +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y +# CONFIG_ANDROID_SWITCH is not set +# CONFIG_ANDROID_INTF_ALARM_DEV is not set +# CONFIG_PHONE is not set +CONFIG_USB_WPAN_HCD=m +CONFIG_CLKDEV_LOOKUP=y + +# +# Hardware Spinlock drivers +# +CONFIG_IOMMU_SUPPORT=y + +# +# Remoteproc drivers (EXPERIMENTAL) +# + +# +# Rpmsg drivers (EXPERIMENTAL) +# +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_DEFAULTS_TO_ORDERED=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_XATTR=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=y +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=y +# CONFIG_JFS_POSIX_ACL is not set +# CONFIG_JFS_SECURITY is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_XFS_FS=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +# CONFIG_XFS_DEBUG is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_BTRFS_FS=y +# CONFIG_BTRFS_FS_POSIX_ACL is not set +# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set +# CONFIG_QUOTA_DEBUG is not set +CONFIG_QUOTA_TREE=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=y +CONFIG_OVERLAYFS_FS=m +CONFIG_CUSE=y +CONFIG_GENERIC_ACL=y + +# +# Caches +# +CONFIG_FSCACHE=y +CONFIG_FSCACHE_STATS=y +# CONFIG_FSCACHE_HISTOGRAM is not set +# CONFIG_FSCACHE_DEBUG is not set +# CONFIG_FSCACHE_OBJECT_LIST is not set +CONFIG_CACHEFILES=y +# CONFIG_CACHEFILES_DEBUG is not set +# CONFIG_CACHEFILES_HISTOGRAM is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=y +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +CONFIG_NTFS_FS=y +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=y +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +CONFIG_ECRYPT_FS=y +# CONFIG_HFS_FS is not set +CONFIG_HFSPLUS_FS=y +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y +CONFIG_SQUASHFS_EMBEDDED=y +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_EXOFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFS_FSCACHE is not set +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +# CONFIG_NFSD_FAULT_INJECTION is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set +CONFIG_CIFS=y +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +CONFIG_CIFS_DFS_UPCALL=y +# CONFIG_CIFS_FSCACHE is not set +CONFIG_CIFS_ACL=y +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +CONFIG_NLS_CODEPAGE_936=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_CODEPAGE_932=y +CONFIG_NLS_CODEPAGE_949=y +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_PRINTK_TIME=y +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=7 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +CONFIG_MAGIC_SYSRQ=y +CONFIG_STRIP_ASM_SYMS=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_SHIRQ=y +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR_NMI is not set +# CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DEBUG_LIST=y +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_BOOT_PRINTK_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_RCU_CPU_STALL_VERBOSE=y +CONFIG_RCU_CPU_STALL_INFO=y +# CONFIG_RCU_TRACE is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_LKDTM is not set +# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +CONFIG_DYNAMIC_DEBUG=y +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_ASYNC_RAID6_TEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX is not set +CONFIG_STRICT_DEVMEM=y +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_RODATA is not set +CONFIG_DEBUG_LL=y +CONFIG_DEBUG_LL_UART_NONE=y +# CONFIG_DEBUG_ICEDCC is not set +# CONFIG_DEBUG_SEMIHOSTING is not set +CONFIG_EARLY_PRINTK=y +# CONFIG_OC_ETM is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_XOR_BLOCKS=m +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_ASYNC_PQ=m +CONFIG_ASYNC_RAID6_RECOV=m +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_USER=m +# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set +CONFIG_CRYPTO_GF128MUL=y +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_GCM=m +CONFIG_CRYPTO_SEQIV=y + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=m +CONFIG_CRYPTO_CTS=m +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_XTS=m + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_VMAC=m + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_GHASH=m +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_BLOWFISH_COMMON=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SALSA20=m +CONFIG_CRYPTO_SEED=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_ZLIB=y +CONFIG_CRYPTO_LZO=y + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_USER_API=m +CONFIG_CRYPTO_USER_API_HASH=m +CONFIG_CRYPTO_USER_API_SKCIPHER=m +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_RAID6_PQ=m +CONFIG_BITREVERSE=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +CONFIG_CRC7=m +CONFIG_LIBCRC32C=y +# CONFIG_CRC8 is not set +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_IA64=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_LRU_CACHE=m +CONFIG_AVERAGE=y +# CONFIG_CORDIC is not set diff --git a/config/linux-sunxi-dev.config b/config/linux-sunxi-dev.config new file mode 100644 index 000000000..c8e3fccf5 --- /dev/null +++ b/config/linux-sunxi-dev.config @@ -0,0 +1,4850 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 4.4.0-rc1 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_MIGHT_HAVE_PCI=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_GENERIC_BUG=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_HAVE_KERNEL_LZ4=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_XZ is not set +# CONFIG_KERNEL_LZO is not set +# CONFIG_KERNEL_LZ4 is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_FHANDLE=y +CONFIG_USELIB=y +# CONFIG_AUDIT is not set +CONFIG_HAVE_ARCH_AUDITSYSCALL=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_HANDLE_DOMAIN_IRQ=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +# CONFIG_IRQ_TIME_ACCOUNTING is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_RCU_EXPERT is not set +CONFIG_SRCU=y +# CONFIG_TASKS_RCU is not set +CONFIG_RCU_STALL_COMMON=y +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_EXPEDITE_BOOT is not set +CONFIG_BUILD_BIN2C=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_FREEZER=y +# CONFIG_CGROUP_PIDS is not set +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_PAGE_COUNTER=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_MEMCG_SWAP_ENABLED=y +CONFIG_MEMCG_KMEM=y +CONFIG_CGROUP_PERF=y +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_CGROUP=y +# CONFIG_DEBUG_BLK_CGROUP is not set +CONFIG_CGROUP_WRITEBACK=y +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +CONFIG_USER_NS=y +CONFIG_PID_NS=y +CONFIG_NET_NS=y +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_BPF=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set +CONFIG_SYSFS_SYSCALL=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +# CONFIG_BPF_SYSCALL is not set +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_ADVISE_SYSCALLS=y +# CONFIG_USERFAULTFD is not set +CONFIG_MEMBARRIER=y +# CONFIG_EMBEDDED is not set +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_SYSTEM_DATA_VERIFICATION is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_JUMP_LABEL is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_OPTPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR is not set +CONFIG_CC_STACKPROTECTOR_NONE=y +# CONFIG_CC_STACKPROTECTOR_REGULAR is not set +# CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_COMPRESS is not set +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +CONFIG_BLK_DEV_BSG=y +CONFIG_BLK_DEV_BSGLIB=y +# CONFIG_BLK_DEV_INTEGRITY is not set +CONFIG_BLK_DEV_THROTTLING=y +# CONFIG_BLK_CMDLINE_PARSER is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_CFQ_GROUP_IOSCHED=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +CONFIG_INLINE_READ_UNLOCK=y +CONFIG_INLINE_READ_UNLOCK_IRQ=y +CONFIG_INLINE_WRITE_UNLOCK=y +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +CONFIG_ARCH_MULTIPLATFORM=y +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C24XX is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP1 is not set + +# +# Multiple platform selection +# + +# +# CPU Core family selection +# +# CONFIG_ARCH_MULTI_V6 is not set +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_MULTI_V6_V7=y +# CONFIG_ARCH_MULTI_CPU_AUTO is not set +# CONFIG_ARCH_VIRT is not set +# CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCM is not set +# CONFIG_ARCH_BERLIN is not set +# CONFIG_ARCH_DIGICOLOR is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_KEYSTONE is not set +# CONFIG_ARCH_MESON is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MEDIATEK is not set + +# +# TI OMAP/AM/DM/DRA Family +# +# CONFIG_ARCH_OMAP3 is not set +# CONFIG_ARCH_OMAP4 is not set +# CONFIG_SOC_OMAP5 is not set +# CONFIG_SOC_AM33XX is not set +# CONFIG_SOC_AM43XX is not set +# CONFIG_SOC_DRA7XX is not set +# CONFIG_ARCH_QCOM is not set +# CONFIG_ARCH_ROCKCHIP is not set +# CONFIG_ARCH_SOCFPGA is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_STI is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SHMOBILE_MULTI is not set +CONFIG_ARCH_SUNXI=y +CONFIG_MACH_SUN4I=y +CONFIG_MACH_SUN5I=y +CONFIG_MACH_SUN6I=y +CONFIG_MACH_SUN7I=y +CONFIG_MACH_SUN8I=y +CONFIG_MACH_SUN9I=y +# CONFIG_ARCH_SIRF is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_UNIPHIER is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_WM8850 is not set +# CONFIG_ARCH_ZX is not set +# CONFIG_ARCH_ZYNQ is not set + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_LPAE is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_ARM_VIRT_EXT=y +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_KUSER_HELPERS=y +CONFIG_VDSO=y +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_CACHE_L2X0=y +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_PL310_ERRATA_753970 is not set +# CONFIG_PL310_ERRATA_769419 is not set +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_ARM_HEAVY_MB=y +# CONFIG_ARM_KERNMEM_PERMS is not set +CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_430973 is not set +CONFIG_ARM_ERRATA_643719=y +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764369 is not set +# CONFIG_ARM_ERRATA_775420 is not set +# CONFIG_ARM_ERRATA_798181 is not set +# CONFIG_ARM_ERRATA_773022 is not set + +# +# Bus support +# +# CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS_GENERIC is not set +# CONFIG_PCI_SYSCALL is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_HAVE_SMP=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_ARM_CPU_TOPOLOGY=y +CONFIG_SCHED_MC=y +CONFIG_SCHED_SMT=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +# CONFIG_MCPM is not set +# CONFIG_BIG_LITTLE is not set +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_3G_OPT is not set +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARM_PSCI=y +CONFIG_ARCH_NR_GPIO=416 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ_FIXED=0 +CONFIG_HZ_100=y +# CONFIG_HZ_200 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +# CONFIG_HZ_500 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 +CONFIG_SCHED_HRTICK=y +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HIGHMEM=y +CONFIG_HIGHPTE=y +CONFIG_CPU_SW_DOMAIN_PAN=y +CONFIG_HW_PERF_EVENTS=y +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +# CONFIG_ARM_MODULE_PLTS is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +CONFIG_MEMORY_ISOLATION=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_BOUNCE=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_CLEANCACHE=y +CONFIG_FRONTSWAP=y +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set +# CONFIG_CMA_DEBUGFS is not set +CONFIG_CMA_AREAS=7 +CONFIG_ZSWAP=y +CONFIG_ZPOOL=y +# CONFIG_ZBUD is not set +CONFIG_ZSMALLOC=y +# CONFIG_PGTABLE_MAPPING is not set +# CONFIG_ZSMALLOC_STAT is not set +# CONFIG_IDLE_PAGE_TRACKING is not set +CONFIG_FRAME_VECTOR=y +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +# CONFIG_XEN is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ATAGS=y +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_ARM_APPENDED_DTB=y +CONFIG_ARM_ATAG_DTB_COMPAT=y +CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set +CONFIG_CMDLINE="" +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +CONFIG_AUTO_ZRELADDR=y + +# +# CPU Power Management +# + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y + +# +# CPU frequency scaling drivers +# +CONFIG_CPUFREQ_DT=y +CONFIG_ARM_BIG_LITTLE_CPUFREQ=m +CONFIG_ARM_DT_BL_CPUFREQ=m +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set +CONFIG_QORIQ_CPUFREQ=m + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_DT_IDLE_STATES=y + +# +# ARM CPU Idle Drivers +# +CONFIG_ARM_CPUIDLE=y +# CONFIG_ARM_HIGHBANK_CPUIDLE is not set +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y +# CONFIG_KERNEL_MODE_NEON is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_COREDUMP=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_SUSPEND_SKIP_SYNC is not set +# CONFIG_HIBERNATION is not set +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM_EMULATION is not set +CONFIG_PM_OPP=y +CONFIG_PM_CLK=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_CPU_PM=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_NET=y +CONFIG_NET_INGRESS=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_DIAG=m +CONFIG_UNIX=y +CONFIG_UNIX_DIAG=m +CONFIG_XFRM=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_USER=y +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=y +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_FIB_TRIE_STATS=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_ROUTE_CLASSID=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=y +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IP_TUNNEL=y +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +# CONFIG_NET_IPVTI is not set +CONFIG_NET_UDP_TUNNEL=m +# CONFIG_NET_FOU is not set +# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_INET_UDP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_WESTWOOD=y +CONFIG_TCP_CONG_HTCP=y +CONFIG_TCP_CONG_HSTCP=y +CONFIG_TCP_CONG_HYBLA=y +CONFIG_TCP_CONG_VEGAS=y +CONFIG_TCP_CONG_SCALABLE=y +CONFIG_TCP_CONG_LP=y +CONFIG_TCP_CONG_VENO=y +CONFIG_TCP_CONG_YEAH=y +CONFIG_TCP_CONG_ILLINOIS=y +# CONFIG_TCP_CONG_DCTCP is not set +# CONFIG_TCP_CONG_CDG is not set +# CONFIG_DEFAULT_BIC is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_HTCP is not set +# CONFIG_DEFAULT_HYBLA is not set +# CONFIG_DEFAULT_VEGAS is not set +# CONFIG_DEFAULT_VENO is not set +# CONFIG_DEFAULT_WESTWOOD is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_IPV6_ILA=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=m +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +# CONFIG_IPV6_GRE is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NET_PTP_CLASSIFY=y +CONFIG_NETWORK_PHY_TIMESTAMPING=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=m + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_ACCT=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_LOG_COMMON=m +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_LABELS=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_BROADCAST=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_NETLINK_TIMEOUT=m +# CONFIG_NETFILTER_NETLINK_GLUE_CT is not set +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PROTO_DCCP=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_SIP=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_REDIRECT=m +CONFIG_NETFILTER_SYNPROXY=m +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=m +CONFIG_NF_TABLES_NETDEV=m +CONFIG_NFT_EXTHDR=m +CONFIG_NFT_META=m +CONFIG_NFT_CT=m +CONFIG_NFT_RBTREE=m +CONFIG_NFT_HASH=m +CONFIG_NFT_COUNTER=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +CONFIG_NFT_MASQ=m +CONFIG_NFT_REDIR=m +CONFIG_NFT_NAT=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_REJECT_INET=m +CONFIG_NFT_COMPAT=m +CONFIG_NETFILTER_XTABLES=m + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_CONNMARK=m +CONFIG_NETFILTER_XT_SET=m + +# +# Xtables targets +# +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_NAT=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ECN=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_L2TP=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_MAX=256 +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPMARK=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_MAC=m +CONFIG_IP_SET_HASH_NETPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETNET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +# CONFIG_IP_VS_FO is not set +CONFIG_IP_VS_OVF=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS SH scheduler +# +CONFIG_IP_VS_SH_TAB_BITS=8 + +# +# IPVS application helper +# +# CONFIG_IP_VS_FTP is not set +CONFIG_IP_VS_NFCT=y +CONFIG_IP_VS_PE_SIP=m + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_CONNTRACK_IPV4=m +# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set +CONFIG_NF_TABLES_IPV4=m +CONFIG_NFT_CHAIN_ROUTE_IPV4=m +CONFIG_NFT_REJECT_IPV4=m +CONFIG_NFT_DUP_IPV4=m +CONFIG_NF_TABLES_ARP=m +CONFIG_NF_DUP_IPV4=m +CONFIG_NF_LOG_ARP=m +CONFIG_NF_LOG_IPV4=m +CONFIG_NF_REJECT_IPV4=m +CONFIG_NF_NAT_IPV4=m +CONFIG_NFT_CHAIN_NAT_IPV4=m +CONFIG_NF_NAT_MASQUERADE_IPV4=m +CONFIG_NFT_MASQ_IPV4=m +CONFIG_NFT_REDIR_IPV4=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_SYNPROXY=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_NF_TABLES_IPV6=m +CONFIG_NFT_CHAIN_ROUTE_IPV6=m +CONFIG_NFT_REJECT_IPV6=m +CONFIG_NFT_DUP_IPV6=m +CONFIG_NF_DUP_IPV6=m +CONFIG_NF_REJECT_IPV6=m +CONFIG_NF_LOG_IPV6=m +CONFIG_NF_NAT_IPV6=m +CONFIG_NFT_CHAIN_NAT_IPV6=m +CONFIG_NF_NAT_MASQUERADE_IPV6=m +CONFIG_NFT_MASQ_IPV6=m +CONFIG_NFT_REDIR_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_SYNPROXY=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_IP6_NF_TARGET_NPT=m +CONFIG_NF_TABLES_BRIDGE=m +CONFIG_NFT_BRIDGE_META=m +CONFIG_NFT_BRIDGE_REJECT=m +CONFIG_NF_LOG_BRIDGE=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m + +# +# DCCP CCIDs Configuration +# +# CONFIG_IP_DCCP_CCID2_DEBUG is not set +CONFIG_IP_DCCP_CCID3=y +# CONFIG_IP_DCCP_CCID3_DEBUG is not set +CONFIG_IP_DCCP_TFRC_LIB=y + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_OBJCNT is not set +CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set +CONFIG_SCTP_COOKIE_HMAC_MD5=y +# CONFIG_SCTP_COOKIE_HMAC_SHA1 is not set +CONFIG_RDS=m +CONFIG_RDS_TCP=m +# CONFIG_RDS_DEBUG is not set +CONFIG_TIPC=m +CONFIG_TIPC_MEDIA_UDP=y +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +CONFIG_ATM_CLIP_NO_ICMP=y +# CONFIG_ATM_LANE is not set +CONFIG_ATM_BR2684=m +CONFIG_ATM_BR2684_IPFILTER=y +CONFIG_L2TP=m +# CONFIG_L2TP_DEBUGFS is not set +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_STP=y +CONFIG_GARP=y +CONFIG_MRP=y +CONFIG_BRIDGE=y +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_HAVE_NET_DSA=y +CONFIG_NET_DSA=m +CONFIG_NET_DSA_HWMON=y +CONFIG_VLAN_8021Q=y +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLAN_8021Q_MVRP=y +# CONFIG_DECNET is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_NHC=m +CONFIG_6LOWPAN_NHC_DEST=m +CONFIG_6LOWPAN_NHC_FRAGMENT=m +CONFIG_6LOWPAN_NHC_HOP=m +CONFIG_6LOWPAN_NHC_IPV6=m +CONFIG_6LOWPAN_NHC_MOBILITY=m +CONFIG_6LOWPAN_NHC_ROUTING=m +CONFIG_6LOWPAN_NHC_UDP=m +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_HFSC=m +# CONFIG_NET_SCH_ATM is not set +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +# CONFIG_NET_SCH_DRR is not set +CONFIG_NET_SCH_MQPRIO=m +# CONFIG_NET_SCH_CHOKE is not set +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=y +# CONFIG_NET_SCH_FQ is not set +# CONFIG_NET_SCH_HHF is not set +# CONFIG_NET_SCH_PIE is not set +CONFIG_NET_SCH_INGRESS=m +# CONFIG_NET_SCH_PLUG is not set + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=y +CONFIG_NET_CLS_ROUTE4=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +CONFIG_NET_CLS_FLOW=m +# CONFIG_NET_CLS_CGROUP is not set +# CONFIG_NET_CLS_BPF is not set +# CONFIG_NET_CLS_FLOWER is not set +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_CANID=m +# CONFIG_NET_EMATCH_IPSET is not set +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +# CONFIG_NET_ACT_GACT is not set +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +# CONFIG_NET_ACT_SIMP is not set +CONFIG_NET_ACT_SKBEDIT=m +# CONFIG_NET_ACT_CSUM is not set +CONFIG_NET_ACT_VLAN=m +CONFIG_NET_ACT_BPF=m +CONFIG_NET_ACT_CONNMARK=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_SCH_FIFO=y +CONFIG_DCB=y +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +CONFIG_OPENVSWITCH=m +CONFIG_OPENVSWITCH_GRE=m +# CONFIG_VSOCKETS is not set +CONFIG_NETLINK_MMAP=y +CONFIG_NETLINK_DIAG=m +CONFIG_MPLS=y +CONFIG_NET_MPLS_GSO=m +# CONFIG_MPLS_ROUTING is not set +CONFIG_HSR=m +CONFIG_NET_SWITCHDEV=y +# CONFIG_NET_L3_MASTER_DEV is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +# CONFIG_CGROUP_NET_PRIO is not set +CONFIG_CGROUP_NET_CLASSID=y +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_JIT is not set +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +CONFIG_CAN=y +CONFIG_CAN_RAW=m +CONFIG_CAN_BCM=m +CONFIG_CAN_GW=m + +# +# CAN Device Drivers +# +CONFIG_CAN_VCAN=m +CONFIG_CAN_SLCAN=m +CONFIG_CAN_DEV=m +CONFIG_CAN_CALC_BITTIMING=y +# CONFIG_CAN_LEDS is not set +CONFIG_CAN_TI_HECC=m +CONFIG_CAN_FLEXCAN=m +CONFIG_CAN_GRCAN=m +CONFIG_CAN_RCAR=m +CONFIG_CAN_SUN4I=m +CONFIG_CAN_SJA1000=m +CONFIG_CAN_SJA1000_ISA=m +CONFIG_CAN_SJA1000_PLATFORM=m +CONFIG_CAN_C_CAN=m +CONFIG_CAN_C_CAN_PLATFORM=m +CONFIG_CAN_M_CAN=m +CONFIG_CAN_CC770=m +CONFIG_CAN_CC770_ISA=m +CONFIG_CAN_CC770_PLATFORM=m + +# +# CAN SPI interfaces +# +CONFIG_CAN_MCP251X=m + +# +# CAN USB interfaces +# +CONFIG_CAN_EMS_USB=m +CONFIG_CAN_ESD_USB2=m +CONFIG_CAN_GS_USB=m +CONFIG_CAN_KVASER_USB=m +CONFIG_CAN_PEAK_USB=m +CONFIG_CAN_8DEV_USB=m +CONFIG_CAN_SOFTING=m +# CONFIG_CAN_DEBUG_DEVICES is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +# CONFIG_IRNET is not set +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y + +# +# IrDA options +# +# CONFIG_IRDA_CACHE_LAST_LSAP is not set +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +# CONFIG_DONGLE is not set +CONFIG_KINGSUN_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +CONFIG_KS959_DONGLE=m + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_BREDR=y +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m +CONFIG_BT_HS=y +CONFIG_BT_LE=y +# CONFIG_BT_6LOWPAN is not set +# CONFIG_BT_SELFTEST is not set +CONFIG_BT_DEBUGFS=y + +# +# Bluetooth device drivers +# +CONFIG_BT_INTEL=m +CONFIG_BT_BCM=m +CONFIG_BT_RTL=m +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTUSB_BCM=y +CONFIG_BT_HCIBTUSB_RTL=y +CONFIG_BT_HCIBTSDIO=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_LL=y +# CONFIG_BT_HCIUART_3WIRE is not set +# CONFIG_BT_HCIUART_INTEL is not set +# CONFIG_BT_HCIUART_BCM is not set +# CONFIG_BT_HCIUART_QCA is not set +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +# CONFIG_BT_HCIVHCI is not set +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_BT_ATH3K=m +CONFIG_AF_RXRPC=m +# CONFIG_AF_RXRPC_DEBUG is not set +CONFIG_RXKAD=m +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=y +# CONFIG_NL80211_TESTMODE is not set +CONFIG_CFG80211_DEVELOPER_WARNINGS=y +# CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_CRDA_SUPPORT=y +CONFIG_CFG80211_WEXT=y +# CONFIG_LIB80211 is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_HAS_RC=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +# CONFIG_MAC80211_RC_MINSTREL_VHT is not set +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_MESSAGE_TRACING is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +CONFIG_WIMAX=m +CONFIG_WIMAX_DEBUG_LEVEL=8 +CONFIG_RFKILL=y +CONFIG_RFKILL_LEDS=y +# CONFIG_RFKILL_INPUT is not set +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +CONFIG_LWTUNNEL=y +CONFIG_HAVE_BPF_JIT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +CONFIG_WANT_DEV_COREDUMP=y +CONFIG_ALLOW_DEV_COREDUMP=y +CONFIG_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_IRQ=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_FENCE_TRACE is not set +# CONFIG_DMA_CMA is not set + +# +# Bus devices +# +CONFIG_ARM_CCI=y +CONFIG_ARM_CCI_PMU=y +CONFIG_ARM_CCI400_COMMON=y +CONFIG_ARM_CCI400_PMU=y +CONFIG_ARM_CCI500_PMU=y +# CONFIG_ARM_CCN is not set +# CONFIG_BRCMSTB_GISB_ARB is not set +CONFIG_SUNXI_RSB=y +# CONFIG_VEXPRESS_CONFIG is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +CONFIG_DTC=y +CONFIG_OF=y +# CONFIG_OF_UNITTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_RESERVED_MEM=y +# CONFIG_OF_OVERLAY is not set +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_PARPORT=y +# CONFIG_PARPORT_PC is not set +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +# CONFIG_PARPORT_1284 is not set +CONFIG_PARPORT_NOT_PC=y +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +CONFIG_ZRAM=m +CONFIG_ZRAM_LZ4_COMPRESS=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +CONFIG_BLK_DEV_CRYPTOLOOP=y +# CONFIG_BLK_DEV_DRBD is not set +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set + +# +# Misc devices +# +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +CONFIG_SENSORS_TSL2550=m +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +CONFIG_BMP085=y +CONFIG_BMP085_I2C=m +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_SRAM is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +CONFIG_EEPROM_93CX6=m +# CONFIG_EEPROM_93XX46 is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# Intel MIC Bus Driver +# + +# +# SCIF Bus Driver +# + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# + +# +# SCIF Driver +# + +# +# Intel MIC Coprocessor State Management (COSM) Drivers +# +# CONFIG_ECHO is not set +# CONFIG_CXL_BASE is not set +# CONFIG_CXL_KERNEL_API is not set +# CONFIG_CXL_EEH is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +CONFIG_SCSI_ISCSI_ATTRS=y +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_UFSHCD is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +CONFIG_SCSI_OSD_INITIATOR=m +# CONFIG_SCSI_OSD_ULD is not set +CONFIG_SCSI_OSD_DPRINT_SENSE=1 +# CONFIG_SCSI_OSD_DEBUG is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +CONFIG_SATA_AHCI_PLATFORM=y +# CONFIG_AHCI_CEVA is not set +CONFIG_AHCI_SUNXI=y +# CONFIG_AHCI_QORIQ is not set +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# + +# +# PATA SFF controllers with BMDMA +# + +# +# PIO-only SFF controllers +# +# CONFIG_PATA_PLATFORM is not set + +# +# Generic fallback / legacy drivers +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BCACHE=m +# CONFIG_BCACHE_DEBUG is not set +# CONFIG_BCACHE_CLOSURES_DEBUG is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=m +# CONFIG_DM_MQ_DEFAULT is not set +CONFIG_DM_DEBUG=y +CONFIG_DM_BUFIO=m +CONFIG_DM_BIO_PRISON=m +CONFIG_DM_PERSISTENT_DATA=m +# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_THIN_PROVISIONING=m +CONFIG_DM_CACHE=m +CONFIG_DM_CACHE_MQ=m +CONFIG_DM_CACHE_SMQ=m +CONFIG_DM_CACHE_CLEANER=m +# CONFIG_DM_ERA is not set +# CONFIG_DM_MIRROR is not set +CONFIG_DM_RAID=m +# CONFIG_DM_ZERO is not set +CONFIG_DM_MULTIPATH=m +# CONFIG_DM_MULTIPATH_QL is not set +# CONFIG_DM_MULTIPATH_ST is not set +# CONFIG_DM_DELAY is not set +CONFIG_DM_UEVENT=y +CONFIG_DM_FLAKEY=m +CONFIG_DM_VERITY=m +CONFIG_DM_SWITCH=m +CONFIG_DM_LOG_WRITES=m +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +CONFIG_MII=y +CONFIG_NET_CORE=y +CONFIG_BONDING=y +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_IFB is not set +# CONFIG_NET_TEAM is not set +CONFIG_MACVLAN=y +CONFIG_MACVTAP=m +CONFIG_IPVLAN=m +# CONFIG_VXLAN is not set +# CONFIG_GENEVE is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +CONFIG_TUN=y +# CONFIG_TUN_VNET_CROSS_LE is not set +CONFIG_VETH=y +# CONFIG_NLMON is not set +CONFIG_ATM_DRIVERS=y +# CONFIG_ATM_DUMMY is not set +# CONFIG_ATM_TCP is not set + +# +# CAIF transport drivers +# +# CONFIG_VHOST_NET is not set +# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set +# CONFIG_NET_DSA_MV88E6171 is not set +# CONFIG_NET_DSA_MV88E6352 is not set +# CONFIG_NET_DSA_BCM_SF2 is not set +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_ALLWINNER=y +CONFIG_SUN4I_EMAC=y +# CONFIG_ALTERA_TSE is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_CADENCE is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_EZCHIP=y +# CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set +# CONFIG_NET_VENDOR_FARADAY is not set +CONFIG_NET_VENDOR_HISILICON=y +# CONFIG_HIX5HD2_GMAC is not set +CONFIG_HIP04_ETH=m +CONFIG_HNS_MDIO=m +# CONFIG_HNS is not set +# CONFIG_HNS_DSAF is not set +# CONFIG_HNS_ENET is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_ETHOC is not set +CONFIG_NET_VENDOR_QUALCOMM=y +# CONFIG_QCA7000 is not set +CONFIG_NET_VENDOR_RENESAS=y +CONFIG_NET_VENDOR_ROCKER=y +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +CONFIG_NET_VENDOR_STMICRO=y +CONFIG_STMMAC_ETH=y +CONFIG_STMMAC_PLATFORM=y +CONFIG_DWMAC_GENERIC=y +# CONFIG_DWMAC_IPQ806X is not set +# CONFIG_DWMAC_LPC18XX is not set +# CONFIG_DWMAC_MESON is not set +# CONFIG_DWMAC_ROCKCHIP is not set +# CONFIG_DWMAC_SOCFPGA is not set +# CONFIG_DWMAC_STI is not set +CONFIG_DWMAC_SUNXI=m +CONFIG_NET_VENDOR_SYNOPSYS=y +CONFIG_SYNOPSYS_DWC_ETH_QOS=m +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_PHYLIB=y +CONFIG_SWCONFIG=y +# CONFIG_SWCONFIG_LEDS is not set + +# +# MII PHY device drivers +# +CONFIG_AQUANTIA_PHY=m +CONFIG_AT803X_PHY=m +CONFIG_AMD_PHY=m +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_TERANETICS_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_BCM_NET_PHYLIB=m +CONFIG_BROADCOM_PHY=m +# CONFIG_BCM7XXX_PHY is not set +CONFIG_BCM87XX_PHY=m +CONFIG_ICPLUS_PHY=m +CONFIG_REALTEK_PHY=m +CONFIG_NATIONAL_PHY=m +CONFIG_STE10XP=m +CONFIG_LSI_ET1011C_PHY=m +CONFIG_MICREL_PHY=m +CONFIG_DP83848_PHY=m +# CONFIG_DP83867_PHY is not set +CONFIG_MICROCHIP_PHY=m +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_MDIO_SUN4I=y +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_BCM_UNIMAC is not set +CONFIG_B53=y +CONFIG_B53_SPI_DRIVER=y +CONFIG_B53_PHY_DRIVER=y +# CONFIG_B53_MMAP_DRIVER is not set +CONFIG_B53_SRAB_DRIVER=y +CONFIG_B53_PHY_FIXUP=y +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PLIP is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPPOATM is not set +CONFIG_PPPOE=y +CONFIG_PPTP=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +CONFIG_SLIP=m +CONFIG_SLHC=y +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y +CONFIG_USB_NET_DRIVERS=y +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_LAN78XX=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_AX88179_178A=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_CDC_NCM=m +CONFIG_USB_NET_HUAWEI_CDC_NCM=m +CONFIG_USB_NET_CDC_MBIM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SR9700=m +CONFIG_USB_NET_SR9800=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_HSO=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_USB_NET_CH9200=m +CONFIG_WLAN=y +CONFIG_LIBERTAS_THINFIRM=m +# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AT76C50X_USB=m +# CONFIG_USB_ZD1201 is not set +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y +CONFIG_MAC80211_HWSIM=m +CONFIG_ATH_COMMON=m +CONFIG_ATH_CARDS=m +# CONFIG_ATH_DEBUG is not set +CONFIG_ATH9K_HW=m +CONFIG_ATH9K_COMMON=m +CONFIG_ATH9K_BTCOEX_SUPPORT=y +CONFIG_ATH9K=m +# CONFIG_ATH9K_AHB is not set +# CONFIG_ATH9K_DEBUGFS is not set +# CONFIG_ATH9K_DYNACK is not set +# CONFIG_ATH9K_WOW is not set +CONFIG_ATH9K_RFKILL=y +# CONFIG_ATH9K_CHANNEL_CONTEXT is not set +CONFIG_ATH9K_PCOEM=y +CONFIG_ATH9K_HTC=m +# CONFIG_ATH9K_HTC_DEBUGFS is not set +CONFIG_CARL9170=m +CONFIG_CARL9170_LEDS=y +CONFIG_CARL9170_WPC=y +# CONFIG_CARL9170_HWRNG is not set +CONFIG_ATH6KL=m +CONFIG_ATH6KL_SDIO=m +CONFIG_ATH6KL_USB=m +# CONFIG_ATH6KL_DEBUG is not set +CONFIG_AR5523=m +CONFIG_ATH10K=m +# CONFIG_ATH10K_DEBUG is not set +# CONFIG_ATH10K_DEBUGFS is not set +# CONFIG_WCN36XX is not set +CONFIG_B43=m +CONFIG_B43_BCMA=y +CONFIG_B43_SSB=y +CONFIG_B43_BUSES_BCMA_AND_SSB=y +# CONFIG_B43_BUSES_BCMA is not set +# CONFIG_B43_BUSES_SSB is not set +# CONFIG_B43_SDIO is not set +CONFIG_B43_BCMA_PIO=y +CONFIG_B43_PIO=y +CONFIG_B43_PHY_G=y +CONFIG_B43_PHY_N=y +CONFIG_B43_PHY_LP=y +CONFIG_B43_PHY_HT=y +CONFIG_B43_LEDS=y +CONFIG_B43_HWRNG=y +# CONFIG_B43_DEBUG is not set +# CONFIG_B43LEGACY is not set +CONFIG_BRCMUTIL=m +# CONFIG_BRCMSMAC is not set +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_PROTO_BCDC=y +CONFIG_BRCMFMAC_SDIO=y +# CONFIG_BRCMFMAC_USB is not set +# CONFIG_BRCM_TRACING is not set +# CONFIG_BRCMDBG is not set +# CONFIG_HOSTAP is not set +# CONFIG_LIBERTAS is not set +# CONFIG_P54_COMMON is not set +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +# CONFIG_RT73USB is not set +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT33XX=y +CONFIG_RT2800USB_RT35XX=y +CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RT2800_LIB=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +CONFIG_RT2X00_DEBUG=y +CONFIG_WL_MEDIATEK=y +CONFIG_MT7601U=m +CONFIG_RTL_CARDS=m +CONFIG_RTL8192CU=m +CONFIG_RTLWIFI=m +CONFIG_RTLWIFI_USB=m +CONFIG_RTLWIFI_DEBUG=y +CONFIG_RTL8192C_COMMON=m +# CONFIG_RTL8XXXU is not set +# CONFIG_WL_TI is not set +# CONFIG_ZD1211RW is not set +# CONFIG_MWIFIEX is not set +# CONFIG_CW1200 is not set +# CONFIG_RSI_91X is not set + +# +# WiMAX Wireless Broadband devices +# +# CONFIG_WIMAX_I2400M_USB is not set +# CONFIG_WAN is not set +# CONFIG_ISDN is not set +# CONFIG_NVM is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_LEDS=m +CONFIG_INPUT_FF_MEMLESS=m +CONFIG_INPUT_POLLDEV=m +# CONFIG_INPUT_SPARSEKMAP is not set +CONFIG_INPUT_MATRIXKMAP=m + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=m +CONFIG_INPUT_EVBUG=m + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +CONFIG_KEYBOARD_SUN4I_LRADC=m +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CAP11XX is not set +CONFIG_KEYBOARD_BCM=m +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_CYPRESS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_FOCALTECH=y +CONFIG_MOUSE_SERIAL=m +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_AR1021_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +CONFIG_TOUCHSCREEN_CHIPONE_ICN8318=m +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_FT6236 is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +CONFIG_TOUCHSCREEN_GOODIX=m +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +CONFIG_TOUCHSCREEN_IMX6UL_TSC=m +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_UCB1400 is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set +# CONFIG_TOUCHSCREEN_WM97XX is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_TSC2004 is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +CONFIG_TOUCHSCREEN_SUN4I=m +# CONFIG_TOUCHSCREEN_SUR40 is not set +CONFIG_TOUCHSCREEN_SX8654=m +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_MPU3050 is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_REGULATOR_HAPTIC is not set +CONFIG_INPUT_AXP20X_PEK=y +# CONFIG_INPUT_UINPUT is not set +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_DA9063_ONKEY is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2665_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PARKBD is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +CONFIG_SERIO_SUN4I_PS2=m +# CONFIG_USERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVMEM=y +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=8 +CONFIG_SERIAL_8250_RUNTIME_UARTS=8 +# CONFIG_SERIAL_8250_EXTENDED is not set +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_DW=y +# CONFIG_SERIAL_8250_EM is not set +# CONFIG_SERIAL_8250_RT288X is not set +# CONFIG_SERIAL_8250_INGENIC is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +CONFIG_SERIAL_UARTLITE=m +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_BCM63XX is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_FSL_LPUART is not set +CONFIG_SERIAL_CONEXANT_DIGICOLOR=m +# CONFIG_SERIAL_ST_ASC is not set +CONFIG_SERIAL_STM32=m +# CONFIG_TTY_PRINTK is not set +# CONFIG_PRINTER is not set +# CONFIG_PPDEV is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=m +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_XILLYBUS is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +CONFIG_I2C_ARB_GPIO_CHALLENGE=m +CONFIG_I2C_MUX_GPIO=m +CONFIG_I2C_MUX_PCA9541=m +CONFIG_I2C_MUX_PCA954x=m +CONFIG_I2C_MUX_PINCTRL=m +CONFIG_I2C_MUX_REG=m +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=m + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +CONFIG_I2C_EMEV2=m +# CONFIG_I2C_GPIO is not set +CONFIG_I2C_MV64XXX=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_SUN6I_P2WI is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +CONFIG_I2C_STUB=m +CONFIG_I2C_SLAVE=y +CONFIG_I2C_SLAVE_EEPROM=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_BUTTERFLY is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_LM70_LLP is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_ROCKCHIP is not set +# CONFIG_SPI_SC18IS602 is not set +CONFIG_SPI_SUN4I=y +CONFIG_SPI_SUN6I=y +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPMI is not set +# CONFIG_HSI is not set + +# +# PPS support +# +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_PARPORT is not set +# CONFIG_PPS_CLIENT_GPIO is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y +# CONFIG_DP83640_PHY is not set +CONFIG_PINCTRL=y + +# +# Pin controllers +# +CONFIG_PINMUX=y +CONFIG_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_AMD is not set +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PINCTRL_SUNXI_COMMON=y +CONFIG_PINCTRL_SUN4I_A10=y +CONFIG_PINCTRL_SUN5I_A10S=y +CONFIG_PINCTRL_SUN5I_A13=y +CONFIG_PINCTRL_SUN6I_A31=y +CONFIG_PINCTRL_SUN6I_A31S=y +CONFIG_PINCTRL_SUN6I_A31_R=y +CONFIG_PINCTRL_SUN7I_A20=y +CONFIG_PINCTRL_SUN8I_A23=y +CONFIG_PINCTRL_SUN8I_A33=y +CONFIG_PINCTRL_SUN8I_A83T=y +CONFIG_PINCTRL_SUN8I_A23_R=y +CONFIG_PINCTRL_SUN9I_A80=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers +# +# CONFIG_GPIO_74XX_MMIO is not set +CONFIG_GPIO_ALTERA=m +# CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_EM is not set +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_GRGPIO is not set +CONFIG_GPIO_SYSCON=m +# CONFIG_GPIO_XILINX is not set +# CONFIG_GPIO_ZEVIO is not set +# CONFIG_GPIO_ZX is not set + +# +# I2C GPIO expanders +# +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set + +# +# MFD GPIO expanders +# +# CONFIG_GPIO_UCB1400 is not set + +# +# SPI GPIO expanders +# +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MC33880 is not set + +# +# SPI or I2C GPIO expanders +# +# CONFIG_GPIO_MCP23S08 is not set + +# +# USB GPIO expanders +# +CONFIG_W1=m + +# +# 1-wire Bus Masters +# +# CONFIG_W1_MASTER_DS2490 is not set +# CONFIG_W1_MASTER_DS2482 is not set +# CONFIG_W1_MASTER_DS1WM is not set +# CONFIG_W1_MASTER_GPIO is not set + +# +# 1-wire Slaves +# +# CONFIG_W1_SLAVE_THERM is not set +# CONFIG_W1_SLAVE_SMEM is not set +# CONFIG_W1_SLAVE_DS2408 is not set +# CONFIG_W1_SLAVE_DS2413 is not set +# CONFIG_W1_SLAVE_DS2406 is not set +# CONFIG_W1_SLAVE_DS2423 is not set +# CONFIG_W1_SLAVE_DS2431 is not set +# CONFIG_W1_SLAVE_DS2433 is not set +# CONFIG_W1_SLAVE_DS2760 is not set +# CONFIG_W1_SLAVE_DS2780 is not set +# CONFIG_W1_SLAVE_DS2781 is not set +# CONFIG_W1_SLAVE_DS28E04 is not set +# CONFIG_W1_SLAVE_BQ27000 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_DA9150 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24257 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_SMB347 is not set +CONFIG_BATTERY_GAUGE_LTC2941=m +CONFIG_BATTERY_RT5033=m +# CONFIG_CHARGER_RT9455 is not set +CONFIG_AXP20X_POWER=y +CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_BRCMSTB is not set +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_RESTART is not set +CONFIG_POWER_RESET_VERSATILE=y +# CONFIG_POWER_RESET_SYSCON is not set +CONFIG_POWER_RESET_SYSCON_POWEROFF=y +# CONFIG_POWER_AVS is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MAX31790 is not set +# CONFIG_SENSORS_HTU21 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NCT7802 is not set +CONFIG_SENSORS_NCT7904=m +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_TC74 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +# CONFIG_THERMAL_WRITABLE_TRIPS is not set +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_GOV_FAIR_SHARE is not set +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_BANG_BANG is not set +# CONFIG_THERMAL_GOV_USER_SPACE is not set +# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set +# CONFIG_CPU_THERMAL is not set +# CONFIG_CLOCK_THERMAL is not set +# CONFIG_THERMAL_EMULATION is not set +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_DA9062_WATCHDOG=m +# CONFIG_GPIO_WATCHDOG is not set +# CONFIG_XILINX_WATCHDOG is not set +# CONFIG_CADENCE_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +CONFIG_SUNXI_WATCHDOG=y +# CONFIG_MAX63XX_WATCHDOG is not set +# CONFIG_BCM7038_WDT is not set +# CONFIG_MEN_A21_WDT is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB=m +CONFIG_SSB_BLOCKIO=y +CONFIG_SSB_SDIOHOST_POSSIBLE=y +# CONFIG_SSB_SDIOHOST is not set +# CONFIG_SSB_HOST_SOC is not set +# CONFIG_SSB_SILENT is not set +# CONFIG_SSB_DEBUG is not set +# CONFIG_SSB_DRIVER_GPIO is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +CONFIG_BCMA=m +CONFIG_BCMA_BLOCKIO=y +# CONFIG_BCMA_HOST_SOC is not set +# CONFIG_BCMA_DRIVER_GMAC_CMN is not set +# CONFIG_BCMA_DRIVER_GPIO is not set +# CONFIG_BCMA_DEBUG is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_ATMEL_FLEXCOM is not set +# CONFIG_MFD_ATMEL_HLCDC is not set +# CONFIG_MFD_BCM590XX is not set +CONFIG_MFD_AXP20X=y +# CONFIG_MFD_CROS_EC is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +CONFIG_MFD_DA9062=m +# CONFIG_MFD_DA9063 is not set +CONFIG_MFD_DA9150=m +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_INTEL_SOC_PMIC is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +CONFIG_MFD_MT6397=m +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +CONFIG_UCB1400_CORE=m +# CONFIG_MFD_PM8921_CORE is not set +CONFIG_MFD_RT5033=m +# CONFIG_MFD_RTSX_USB is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK808 is not set +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +CONFIG_MFD_SKY81452=m +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +CONFIG_MFD_SUN6I_PRCM=y +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +CONFIG_MFD_WL1273_CORE=m +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_VIRTUAL_CONSUMER=y +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +CONFIG_REGULATOR_ANATOP=m +CONFIG_REGULATOR_AXP20X=y +CONFIG_REGULATOR_DA9062=m +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set +# CONFIG_REGULATOR_FAN53555 is not set +CONFIG_REGULATOR_GPIO=y +# CONFIG_REGULATOR_ISL9305 is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +CONFIG_REGULATOR_MT6311=m +CONFIG_REGULATOR_MT6397=m +# CONFIG_REGULATOR_PFUZE100 is not set +CONFIG_REGULATOR_RT5033=m +CONFIG_REGULATOR_SKY81452=m +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_SDR_SUPPORT=y +CONFIG_MEDIA_RC_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_FIXED_MINOR_RANGES=y +CONFIG_VIDEO_TUNER=m +CONFIG_V4L2_MEM2MEM_DEV=m +CONFIG_V4L2_FLASH_LED_CLASS=m +CONFIG_VIDEOBUF_GEN=m +CONFIG_VIDEOBUF_VMALLOC=m +CONFIG_VIDEOBUF_DVB=m +CONFIG_VIDEOBUF2_CORE=m +CONFIG_VIDEOBUF2_MEMOPS=m +CONFIG_VIDEOBUF2_VMALLOC=m +CONFIG_DVB_CORE=y +CONFIG_DVB_NET=y +CONFIG_TTPCI_EEPROM=m +CONFIG_DVB_MAX_ADAPTERS=8 +CONFIG_DVB_DYNAMIC_MINORS=y + +# +# Media drivers +# +CONFIG_RC_CORE=y +CONFIG_RC_MAP=y +CONFIG_RC_DECODERS=y +CONFIG_LIRC=m +CONFIG_IR_LIRC_CODEC=m +CONFIG_IR_NEC_DECODER=y +CONFIG_IR_RC5_DECODER=y +CONFIG_IR_RC6_DECODER=y +CONFIG_IR_JVC_DECODER=y +CONFIG_IR_SONY_DECODER=y +CONFIG_IR_SANYO_DECODER=y +CONFIG_IR_SHARP_DECODER=y +CONFIG_IR_MCE_KBD_DECODER=y +CONFIG_IR_XMP_DECODER=y +CONFIG_RC_DEVICES=y +# CONFIG_RC_ATI_REMOTE is not set +# CONFIG_IR_HIX5HD2 is not set +# CONFIG_IR_IMON is not set +# CONFIG_IR_MCEUSB is not set +# CONFIG_IR_REDRAT3 is not set +# CONFIG_IR_STREAMZAP is not set +# CONFIG_IR_IGORPLUGUSB is not set +# CONFIG_IR_IGUANA is not set +# CONFIG_IR_TTUSBIR is not set +# CONFIG_RC_LOOPBACK is not set +# CONFIG_IR_GPIO_CIR is not set +CONFIG_IR_SUNXI=m +CONFIG_MEDIA_USB_SUPPORT=y + +# +# Webcam devices +# +# CONFIG_USB_VIDEO_CLASS is not set +CONFIG_USB_GSPCA=m +# CONFIG_USB_M5602 is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_DTCS033 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_JL2005BCD is not set +# CONFIG_USB_GSPCA_KINECT is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SE401 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SPCA1528 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STK1135 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TOPRO is not set +# CONFIG_USB_GSPCA_TOUPTEK is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_USB_PWC is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +# CONFIG_VIDEO_USBTV is not set + +# +# Analog TV USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_PVRUSB2_DVB=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_STK1160_COMMON=m +# CONFIG_VIDEO_STK1160_AC97 is not set +CONFIG_VIDEO_STK1160=m +# CONFIG_VIDEO_GO7007 is not set + +# +# Analog/digital TV USB devices +# +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_AU0828_V4L2=y +# CONFIG_VIDEO_AU0828_RC is not set +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_RC=y +CONFIG_VIDEO_CX231XX_ALSA=m +CONFIG_VIDEO_CX231XX_DVB=m +CONFIG_VIDEO_TM6000=m +CONFIG_VIDEO_TM6000_ALSA=m +CONFIG_VIDEO_TM6000_DVB=m + +# +# Digital TV USB devices +# +CONFIG_DVB_USB=m +CONFIG_DVB_USB_DEBUG=y +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_PCTV452E=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_CINERGY_T2=m +CONFIG_DVB_USB_DTV5100=m +CONFIG_DVB_USB_FRIIO=m +CONFIG_DVB_USB_AZ6027=m +CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_USB_V2=y +CONFIG_DVB_USB_AF9015=m +CONFIG_DVB_USB_AF9035=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_AZ6007=m +CONFIG_DVB_USB_CE6230=m +CONFIG_DVB_USB_EC168=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_LME2510=m +CONFIG_DVB_USB_MXL111SF=m +CONFIG_DVB_USB_RTL28XXU=m +CONFIG_DVB_USB_DVBSKY=m +CONFIG_SMS_USB_DRV=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG=y +CONFIG_DVB_AS102=m + +# +# Webcam, TV (analog/digital) USB devices +# +# CONFIG_VIDEO_EM28XX is not set + +# +# Software defined radio USB devices +# +CONFIG_USB_AIRSPY=m +CONFIG_USB_HACKRF=m +CONFIG_USB_MSI2500=m +CONFIG_V4L_PLATFORM_DRIVERS=y +# CONFIG_SOC_CAMERA is not set +# CONFIG_VIDEO_XILINX is not set +CONFIG_V4L_MEM2MEM_DRIVERS=y +# CONFIG_VIDEO_SH_VEU is not set +CONFIG_V4L_TEST_DRIVERS=y +CONFIG_VIDEO_VIVID=m +CONFIG_VIDEO_VIVID_MAX_DEVS=64 +CONFIG_VIDEO_VIM2M=m +CONFIG_DVB_PLATFORM_DRIVERS=y +CONFIG_DVB_C8SECTPFE=m + +# +# Supported MMC/SDIO adapters +# +CONFIG_SMS_SDIO_DRV=m +CONFIG_RADIO_ADAPTERS=y +CONFIG_RADIO_TEA575X=m +CONFIG_RADIO_SI470X=y +CONFIG_USB_SI470X=m +CONFIG_I2C_SI470X=m +CONFIG_RADIO_SI4713=m +CONFIG_USB_SI4713=m +CONFIG_PLATFORM_SI4713=m +CONFIG_I2C_SI4713=m +CONFIG_USB_MR800=m +CONFIG_USB_DSBR=m +CONFIG_RADIO_SHARK=m +CONFIG_RADIO_SHARK2=m +CONFIG_USB_KEENE=m +CONFIG_USB_RAREMONO=m +CONFIG_USB_MA901=m +CONFIG_RADIO_TEA5764=m +CONFIG_RADIO_SAA7706H=m +CONFIG_RADIO_TEF6862=m +CONFIG_RADIO_WL1273=m + +# +# Texas Instruments WL128x FM driver (ST based) +# +CONFIG_MEDIA_COMMON_OPTIONS=y + +# +# common driver options +# +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_DEBUG=y +CONFIG_SMS_SIANO_MDTV=m +CONFIG_SMS_SIANO_RC=y +CONFIG_SMS_SIANO_DEBUGFS=y + +# +# Media ancillary drivers (tuners, sensors, i2c, frontends) +# +# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set +CONFIG_MEDIA_ATTACH=y +CONFIG_VIDEO_IR_I2C=y + +# +# Encoders, decoders, sensors and other helper chips +# + +# +# Audio decoders, processors and mixers +# +CONFIG_VIDEO_TVAUDIO=m +CONFIG_VIDEO_TDA7432=m +CONFIG_VIDEO_TDA9840=m +CONFIG_VIDEO_TEA6415C=m +CONFIG_VIDEO_TEA6420=m +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS5345=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_UDA1342=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_VP27SMPX=m +CONFIG_VIDEO_SONY_BTF_MPX=m + +# +# RDS decoders +# +CONFIG_VIDEO_SAA6588=m + +# +# Video decoders +# +CONFIG_VIDEO_ADV7180=m +CONFIG_VIDEO_ADV7183=m +CONFIG_VIDEO_ADV7604=m +CONFIG_VIDEO_ADV7842=m +CONFIG_VIDEO_BT819=m +CONFIG_VIDEO_BT856=m +CONFIG_VIDEO_BT866=m +CONFIG_VIDEO_KS0127=m +CONFIG_VIDEO_ML86V7667=m +CONFIG_VIDEO_SAA7110=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_TC358743=m +CONFIG_VIDEO_TVP514X=m +CONFIG_VIDEO_TVP5150=m +CONFIG_VIDEO_TVP7002=m +CONFIG_VIDEO_TW2804=m +CONFIG_VIDEO_TW9903=m +CONFIG_VIDEO_TW9906=m +CONFIG_VIDEO_VPX3220=m + +# +# Video and audio decoders +# +CONFIG_VIDEO_SAA717X=m +CONFIG_VIDEO_CX25840=m + +# +# Video encoders +# +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_SAA7185=m +CONFIG_VIDEO_ADV7170=m +CONFIG_VIDEO_ADV7175=m +CONFIG_VIDEO_ADV7343=m +CONFIG_VIDEO_ADV7393=m +CONFIG_VIDEO_ADV7511=m +CONFIG_VIDEO_AD9389B=m +CONFIG_VIDEO_AK881X=m +CONFIG_VIDEO_THS8200=m + +# +# Camera sensor devices +# +# CONFIG_VIDEO_OV2659 is not set +# CONFIG_VIDEO_OV7640 is not set +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_OV9650 is not set +# CONFIG_VIDEO_VS6624 is not set +# CONFIG_VIDEO_MT9M032 is not set +# CONFIG_VIDEO_MT9P031 is not set +# CONFIG_VIDEO_MT9T001 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_MT9V032 is not set +# CONFIG_VIDEO_SR030PC30 is not set +# CONFIG_VIDEO_NOON010PC30 is not set +# CONFIG_VIDEO_M5MOLS is not set +# CONFIG_VIDEO_S5K6AA is not set +# CONFIG_VIDEO_S5K6A3 is not set +# CONFIG_VIDEO_S5K4ECGX is not set +# CONFIG_VIDEO_S5K5BAF is not set +# CONFIG_VIDEO_SMIAPP is not set +# CONFIG_VIDEO_S5C73M3 is not set + +# +# Flash devices +# +CONFIG_VIDEO_ADP1653=m +CONFIG_VIDEO_AS3645A=m +CONFIG_VIDEO_LM3560=m +CONFIG_VIDEO_LM3646=m + +# +# Video improvement chips +# +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# Audio/Video compression chips +# +CONFIG_VIDEO_SAA6752HS=m + +# +# Miscellaneous helper chips +# +CONFIG_VIDEO_THS7303=m +CONFIG_VIDEO_M52790=m + +# +# Sensors used on soc_camera driver +# +CONFIG_MEDIA_TUNER=y + +# +# Customize TV tuners +# +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA827X=y +CONFIG_MEDIA_TUNER_TDA18271=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +CONFIG_MEDIA_TUNER_MSI001=m +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT2063=m +CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_MT2131=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_XC4000=y +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_MEDIA_TUNER_MXL5007T=m +CONFIG_MEDIA_TUNER_MC44S803=y +CONFIG_MEDIA_TUNER_MAX2165=m +CONFIG_MEDIA_TUNER_TDA18218=m +CONFIG_MEDIA_TUNER_FC0011=m +CONFIG_MEDIA_TUNER_FC0012=m +CONFIG_MEDIA_TUNER_FC0013=m +CONFIG_MEDIA_TUNER_TDA18212=m +CONFIG_MEDIA_TUNER_E4000=m +CONFIG_MEDIA_TUNER_FC2580=m +CONFIG_MEDIA_TUNER_M88RS6000T=m +CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_SI2157=y +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m +CONFIG_MEDIA_TUNER_MXL301RF=m +CONFIG_MEDIA_TUNER_QM1D1C0042=m + +# +# Customise DVB Frontends +# + +# +# Multistandard (satellite) frontends +# +CONFIG_DVB_STB0899=m +CONFIG_DVB_STB6100=m +CONFIG_DVB_STV090x=m +CONFIG_DVB_STV6110x=m +CONFIG_DVB_M88DS3103=y + +# +# Multistandard (cable + terrestrial) frontends +# +CONFIG_DVB_DRXK=m +CONFIG_DVB_TDA18271C2DD=m +CONFIG_DVB_SI2165=m + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_MT312=m +CONFIG_DVB_ZL10036=m +CONFIG_DVB_ZL10039=m +CONFIG_DVB_S5H1420=m +CONFIG_DVB_STV0288=m +CONFIG_DVB_STB6000=m +CONFIG_DVB_STV0299=m +CONFIG_DVB_STV6110=m +CONFIG_DVB_STV0900=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_TDA10086=m +CONFIG_DVB_TDA8261=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_TUNER_ITD1000=m +CONFIG_DVB_TUNER_CX24113=m +CONFIG_DVB_TDA826X=m +CONFIG_DVB_TUA6100=m +CONFIG_DVB_CX24116=m +CONFIG_DVB_CX24117=m +CONFIG_DVB_CX24120=m +CONFIG_DVB_SI21XX=m +CONFIG_DVB_TS2020=y +CONFIG_DVB_DS3000=m +CONFIG_DVB_MB86A16=m +CONFIG_DVB_TDA10071=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_S5H1432=m +CONFIG_DVB_DRXD=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_DIB7000M=m +CONFIG_DVB_DIB7000P=m +CONFIG_DVB_DIB9000=m +CONFIG_DVB_TDA10048=m +CONFIG_DVB_AF9013=m +CONFIG_DVB_EC100=m +CONFIG_DVB_HD29L2=m +CONFIG_DVB_STV0367=m +CONFIG_DVB_CXD2820R=m +CONFIG_DVB_CXD2841ER=m +CONFIG_DVB_RTL2830=m +CONFIG_DVB_RTL2832=m +CONFIG_DVB_RTL2832_SDR=m +CONFIG_DVB_SI2168=y +CONFIG_DVB_AS102_FE=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_TDA10023=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m +CONFIG_DVB_LGDT3305=m +CONFIG_DVB_LGDT3306A=m +CONFIG_DVB_LG2160=m +CONFIG_DVB_S5H1409=m +CONFIG_DVB_AU8522=m +CONFIG_DVB_AU8522_DTV=m +CONFIG_DVB_AU8522_V4L=m +CONFIG_DVB_S5H1411=m + +# +# ISDB-T (terrestrial) frontends +# +CONFIG_DVB_S921=m +CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m + +# +# ISDB-S (satellite) & ISDB-T (terrestrial) frontends +# +CONFIG_DVB_TC90522=m + +# +# Digital terrestrial only tuners/PLL +# +CONFIG_DVB_PLL=m +CONFIG_DVB_TUNER_DIB0070=m +CONFIG_DVB_TUNER_DIB0090=m + +# +# SEC control devices for DVB-S +# +CONFIG_DVB_DRX39XYJ=m +CONFIG_DVB_LNBH25=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_LNBP22=m +CONFIG_DVB_ISL6405=m +CONFIG_DVB_ISL6421=m +CONFIG_DVB_ISL6423=m +CONFIG_DVB_A8293=m +CONFIG_DVB_SP2=y +CONFIG_DVB_LGS8GL5=m +CONFIG_DVB_LGS8GXX=m +CONFIG_DVB_ATBM8830=m +CONFIG_DVB_TDA665x=m +CONFIG_DVB_IX2505V=m +CONFIG_DVB_M88RS2000=m +CONFIG_DVB_AF9033=m +CONFIG_DVB_HORUS3A=m +CONFIG_DVB_ASCOT2E=m + +# +# Tools to develop new frontends +# +CONFIG_DVB_DUMMY_FE=m + +# +# Graphics support +# +# CONFIG_IMX_IPUV3_CORE is not set +# CONFIG_DRM is not set + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_IMAGEBLIT=m +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=m +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +CONFIG_FB_BACKLIGHT=y +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_IBM_GXT4500 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +CONFIG_FB_SIMPLE=y +# CONFIG_FB_SSD1307 is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=m +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI922X is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_PLATFORM is not set +# CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_LCD_AMS369FG06 is not set +# CONFIG_LCD_LMS501KF03 is not set +# CONFIG_LCD_HX8357 is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y +CONFIG_BACKLIGHT_PM8941_WLED=m +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3639 is not set +CONFIG_BACKLIGHT_SKY81452=m +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set +# CONFIG_VGASTATE is not set +CONFIG_HDMI=y + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_LOGO is not set +CONFIG_SOUND=m +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +CONFIG_SND_PCM_TIMER=y +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_PROC_FS=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_VMASTER=y +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_MTS64 is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +# CONFIG_SND_PORTMAN2X4 is not set +# CONFIG_SND_AC97_POWER_SAVE is not set + +# +# HD-Audio +# +CONFIG_SND_HDA_PREALLOC_SIZE=64 +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_BCD2000 is not set +CONFIG_SND_USB_LINE6=m +CONFIG_SND_USB_POD=m +CONFIG_SND_USB_PODHD=m +CONFIG_SND_USB_TONEPORT=m +CONFIG_SND_USB_VARIAX=m +# CONFIG_SND_SOC is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_AC97_BUS=m + +# +# HID support +# +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HIDRAW is not set +# CONFIG_UHID is not set +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=m +CONFIG_HID_ACRUX=m +CONFIG_HID_ACRUX_FF=y +CONFIG_HID_APPLE=m +CONFIG_HID_APPLEIR=m +CONFIG_HID_AUREAL=m +CONFIG_HID_BELKIN=m +CONFIG_HID_BETOP_FF=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +# CONFIG_HID_CORSAIR is not set +CONFIG_HID_PRODIKEYS=m +CONFIG_HID_CP2112=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_DRAGONRISE_FF=y +CONFIG_HID_EMS_FF=m +CONFIG_HID_ELECOM=m +CONFIG_HID_ELO=m +CONFIG_HID_EZKEY=m +CONFIG_HID_GEMBIRD=m +# CONFIG_HID_GFRM is not set +CONFIG_HID_HOLTEK=m +CONFIG_HOLTEK_FF=y +CONFIG_HID_GT683R=m +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_KYE=m +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WALTOP=m +CONFIG_HID_GYRATION=m +CONFIG_HID_ICADE=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LCPOWER=m +CONFIG_HID_LENOVO=m +CONFIG_HID_LOGITECH=m +CONFIG_HID_LOGITECH_HIDPP=m +CONFIG_LOGITECH_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_LOGIG940_FF=y +CONFIG_LOGIWHEELS_FF=y +CONFIG_HID_MAGICMOUSE=m +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NTRIG=m +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_PANTHERLORD_FF=y +CONFIG_HID_PENMOUNT=m +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +CONFIG_HID_PICOLCD_FB=y +CONFIG_HID_PICOLCD_BACKLIGHT=y +CONFIG_HID_PICOLCD_LCD=y +CONFIG_HID_PICOLCD_LEDS=y +# CONFIG_HID_PICOLCD_CIR is not set +CONFIG_HID_PLANTRONICS=y +CONFIG_HID_PRIMAX=m +CONFIG_HID_ROCCAT=m +CONFIG_HID_SAITEK=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_SONY_FF=y +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_STEELSERIES=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_RMI=m +CONFIG_HID_GREENASIA=m +CONFIG_GREENASIA_FF=y +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_HID_TIVO=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_THINGM=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_THRUSTMASTER_FF=y +CONFIG_HID_WACOM=m +CONFIG_HID_WIIMOTE=m +CONFIG_HID_XINMO=m +CONFIG_HID_ZEROPLUS=m +CONFIG_ZEROPLUS_FF=y +CONFIG_HID_ZYDACRON=m +CONFIG_HID_SENSOR_HUB=m +CONFIG_HID_SENSOR_CUSTOM_SENSOR=m + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# I2C HID support +# +# CONFIG_I2C_HID is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_FSM is not set +CONFIG_USB_ULPI_BUS=m +CONFIG_USB_MON=m +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_XHCI_HCD is not set +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +# CONFIG_USB_U132_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HCD_BCMA is not set +# CONFIG_USB_HCD_SSB is not set +# CONFIG_USB_HCD_TEST_MODE is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +# CONFIG_USB_PRINTER is not set +CONFIG_USB_WDM=m +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +CONFIG_USB_UAS=m + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set +CONFIG_USB_MUSB_HDRC=y +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_DWC2 is not set +# CONFIG_USB_CHIPIDEA is not set +CONFIG_USB_ISP1760=m +CONFIG_USB_ISP1760_HCD=y +CONFIG_USB_ISP1760_HOST_ROLE=y + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_SIMPLE=m +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F81232=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7715_PARPORT=y +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MXUPORT=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_SAFE=m +# CONFIG_USB_SERIAL_SAFE_PADDED is not set +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_WWAN=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_XSENS_MT=m +CONFIG_USB_SERIAL_WISHBONE=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m +CONFIG_USB_SERIAL_DEBUG=m + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +CONFIG_USB_FTDI_ELAN=y +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +CONFIG_USB_EZUSB_FX2=m +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set +CONFIG_USB_CHAOSKEY=m +# CONFIG_USB_ATM is not set + +# +# USB Physical Layer drivers +# +# CONFIG_USB_PHY is not set +CONFIG_NOP_USB_XCEIV=y +# CONFIG_AM335X_PHY_USB is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +# CONFIG_USB_ULPI is not set +# CONFIG_USB_GADGET is not set +# CONFIG_USB_LED_TRIG is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_USDHI6ROL0 is not set +CONFIG_MMC_SUNXI=y +CONFIG_MMC_MTK=m +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_CLASS_FLASH=m + +# +# LED drivers +# +# CONFIG_LEDS_AAT1290 is not set +# CONFIG_LEDS_BCM6328 is not set +# CONFIG_LEDS_BCM6358 is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TLC591XX is not set +# CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_KTD2692 is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +CONFIG_LEDS_SYSCON=y + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_ONESHOT is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_GPIO=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +# CONFIG_EDAC is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_SYSTOHC_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +# CONFIG_RTC_INTF_SYSFS is not set +# CONFIG_RTC_INTF_PROC is not set +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_ABB5ZES3=m +CONFIG_RTC_DRV_ABX80X=m +CONFIG_RTC_DRV_DS1307=m +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12057 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set +# CONFIG_RTC_DRV_RV8803 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_MCP795 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +CONFIG_RTC_DRV_DS1685_FAMILY=m +CONFIG_RTC_DRV_DS1685=y +# CONFIG_RTC_DRV_DS1689 is not set +# CONFIG_RTC_DRV_DS17285 is not set +# CONFIG_RTC_DRV_DS17485 is not set +# CONFIG_RTC_DRV_DS17885 is not set +# CONFIG_RTC_DS1685_PROC_REGS is not set +# CONFIG_RTC_DS1685_SYSFS_REGS is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +CONFIG_RTC_DRV_DA9063=m +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set +CONFIG_RTC_DRV_ZYNQMP=m + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_SUN6I=y +CONFIG_RTC_DRV_SUNXI=y +# CONFIG_RTC_DRV_SNVS is not set +# CONFIG_RTC_DRV_MT6397 is not set + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_VIRT_DRIVERS is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_PRISM2_USB is not set +# CONFIG_COMEDI is not set +# CONFIG_PANEL is not set +# CONFIG_RTLLIB is not set +CONFIG_R8712U=m +CONFIG_R8188EU=m +CONFIG_88EU_AP_MODE=y +# CONFIG_R8723AU is not set +# CONFIG_VT6656 is not set + +# +# Speakup console speech +# +# CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +CONFIG_STAGING_MEDIA=y +CONFIG_I2C_BCM2048=m +CONFIG_DVB_MN88472=m +CONFIG_DVB_MN88473=m +# CONFIG_LIRC_STAGING is not set + +# +# Android +# +# CONFIG_STAGING_BOARD is not set +# CONFIG_WIMAX_GDM72XX is not set +# CONFIG_LTE_GDM724X is not set +# CONFIG_LUSTRE_FS is not set +# CONFIG_DGAP is not set +# CONFIG_GS_FPGABOOT is not set +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set +CONFIG_FB_TFT=m +CONFIG_FB_TFT_AGM1264K_FL=m +CONFIG_FB_TFT_BD663474=m +CONFIG_FB_TFT_HX8340BN=m +CONFIG_FB_TFT_HX8347D=m +CONFIG_FB_TFT_HX8353D=m +CONFIG_FB_TFT_HX8357D=m +CONFIG_FB_TFT_ILI9163=m +CONFIG_FB_TFT_ILI9320=m +CONFIG_FB_TFT_ILI9325=m +CONFIG_FB_TFT_ILI9340=m +CONFIG_FB_TFT_ILI9341=m +CONFIG_FB_TFT_ILI9481=m +CONFIG_FB_TFT_ILI9486=m +CONFIG_FB_TFT_PCD8544=m +CONFIG_FB_TFT_RA8875=m +CONFIG_FB_TFT_S6D02A1=m +CONFIG_FB_TFT_S6D1121=m +CONFIG_FB_TFT_SSD1289=m +CONFIG_FB_TFT_SSD1306=m +CONFIG_FB_TFT_SSD1331=m +CONFIG_FB_TFT_SSD1351=m +CONFIG_FB_TFT_ST7735R=m +CONFIG_FB_TFT_ST7789V=m +CONFIG_FB_TFT_TINYLCD=m +CONFIG_FB_TFT_TLS8204=m +CONFIG_FB_TFT_UC1611=m +CONFIG_FB_TFT_UC1701=m +CONFIG_FB_TFT_UPD161704=m +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m +# CONFIG_WILC1000_DRIVER is not set +CONFIG_MOST=m +CONFIG_MOSTCORE=m +CONFIG_AIM_CDEV=m +CONFIG_AIM_NETWORK=m +CONFIG_AIM_SOUND=m +CONFIG_AIM_V4L2=m +CONFIG_HDM_DIM2=m +CONFIG_HDM_I2C=m +CONFIG_HDM_USB=m +# CONFIG_CHROME_PLATFORMS is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI514 is not set +# CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_CDCE925 is not set +CONFIG_CLK_QORIQ=y +# CONFIG_COMMON_CLK_PXA is not set +# CONFIG_COMMON_CLK_CDCE706 is not set + +# +# Hardware Spinlock drivers +# + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_PROBE=y +CONFIG_CLKSRC_MMIO=y +CONFIG_SUN4I_TIMER=y +CONFIG_SUN5I_HSTIMER=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_TIMER_SP804 is not set +# CONFIG_ATMEL_PIT is not set +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_SH_TIMER_MTU2 is not set +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_EM_TIMER_STI is not set +# CONFIG_MAILBOX is not set +# CONFIG_IOMMU_SUPPORT is not set + +# +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# + +# +# SOC (System On Chip) specific Drivers +# +# CONFIG_SOC_BRCMSTB is not set +CONFIG_SUNXI_SRAM=y +# CONFIG_SOC_TI is not set +# CONFIG_PM_DEVFREQ is not set +CONFIG_EXTCON=m + +# +# Extcon Device Drivers +# +CONFIG_EXTCON_GPIO=m +CONFIG_EXTCON_RT8973A=m +CONFIG_EXTCON_SM5502=m +CONFIG_EXTCON_USB_GPIO=m +# CONFIG_MEMORY is not set +# CONFIG_IIO is not set +# CONFIG_PWM is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +# CONFIG_IPACK_BUS is not set +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +CONFIG_RESET_CONTROLLER=y +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set +# CONFIG_BCM_KONA_USB2_PHY is not set +CONFIG_PHY_SUN4I_USB=m +CONFIG_PHY_SUN9I_USB=y +# CONFIG_PHY_TUSB1210 is not set +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set + +# +# Performance monitor support +# +CONFIG_ARM_PMU=y +# CONFIG_RAS is not set + +# +# Android +# +# CONFIG_ANDROID is not set +# CONFIG_NVMEM is not set +# CONFIG_STM is not set +# CONFIG_STM_DUMMY is not set +# CONFIG_STM_SOURCE_CONSOLE is not set +# CONFIG_INTEL_TH is not set + +# +# FPGA Configuration Support +# +# CONFIG_FPGA is not set + +# +# Firmware Drivers +# +CONFIG_ARM_PSCI_FW=y +# CONFIG_FIRMWARE_MEMMAP is not set + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT2=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_ENCRYPTION=y +CONFIG_EXT4_FS_ENCRYPTION=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=y +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +# CONFIG_REISERFS_FS_XATTR is not set +CONFIG_JFS_FS=y +CONFIG_JFS_POSIX_ACL=y +# CONFIG_JFS_SECURITY is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_XFS_FS=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +# CONFIG_XFS_WARN is not set +# CONFIG_XFS_DEBUG is not set +# CONFIG_GFS2_FS is not set +CONFIG_BTRFS_FS=y +CONFIG_BTRFS_FS_POSIX_ACL=y +# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set +# CONFIG_BTRFS_ASSERT is not set +# CONFIG_NILFS2_FS is not set +CONFIG_F2FS_FS=y +CONFIG_F2FS_STAT_FS=y +CONFIG_F2FS_FS_XATTR=y +CONFIG_F2FS_FS_POSIX_ACL=y +# CONFIG_F2FS_FS_SECURITY is not set +# CONFIG_F2FS_CHECK_FS is not set +# CONFIG_F2FS_FS_ENCRYPTION is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_FANOTIFY=y +# CONFIG_QUOTA is not set +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_QUOTACTL=y +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=y +CONFIG_CUSE=m +CONFIG_OVERLAY_FS=m + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +# CONFIG_ZISOFS is not set +CONFIG_UDF_FS=y +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_PROC_CHILDREN is not set +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +CONFIG_HFS_FS=y +CONFIG_HFSPLUS_FS=y +CONFIG_HFSPLUS_FS_POSIX_ACL=y +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_FILE_CACHE=y +# CONFIG_SQUASHFS_FILE_DIRECT is not set +# CONFIG_SQUASHFS_DECOMP_SINGLE is not set +CONFIG_SQUASHFS_DECOMP_MULTI=y +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_ZLIB=y +# CONFIG_SQUASHFS_LZ4 is not set +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y +CONFIG_SQUASHFS_EMBEDDED=y +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V2=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_SWAP=y +# CONFIG_NFS_V4_1 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +# CONFIG_NFSD_PNFS is not set +# CONFIG_NFSD_FAULT_INJECTION is not set +CONFIG_GRACE_PERIOD=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_SUNRPC_SWAP=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set +CONFIG_CIFS=y +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +# CONFIG_CIFS_UPCALL is not set +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_CIFS_ACL=y +CONFIG_CIFS_DEBUG=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_DFS_UPCALL is not set +# CONFIG_CIFS_SMB2 is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +CONFIG_NLS_UTF8=y + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_DYNAMIC_DEBUG is not set + +# +# Compile-time checks and compiler options +# +# CONFIG_DEBUG_INFO is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +CONFIG_SCHED_DEBUG=y +CONFIG_SCHED_INFO=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_TIMER_STATS is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +# CONFIG_STACKTRACE is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set + +# +# RCU Debugging +# +# CONFIG_PROVE_RCU is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +# CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set + +# +# Runtime Testing +# +# CONFIG_LKDTM is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_ASYNC_RAID6_TEST is not set +CONFIG_TEST_HEXDUMP=m +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_MEMTEST is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARM_PTDUMP is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_SUN9I_UART0 is not set +CONFIG_DEBUG_SUNXI_UART0=y +# CONFIG_DEBUG_SUNXI_UART1 is not set +# CONFIG_DEBUG_SUNXI_R_UART is not set +# CONFIG_DEBUG_ICEDCC is not set +# CONFIG_DEBUG_SEMIHOSTING is not set +# CONFIG_DEBUG_LL_UART_8250 is not set +# CONFIG_DEBUG_LL_UART_PL01X is not set +CONFIG_DEBUG_LL_INCLUDE="debug/8250.S" +CONFIG_DEBUG_UART_8250=y +# CONFIG_DEBUG_UART_BCM63XX is not set +CONFIG_DEBUG_UART_PHYS=0x01c28000 +CONFIG_DEBUG_UART_VIRT=0xf1c28000 +CONFIG_DEBUG_UART_8250_SHIFT=2 +# CONFIG_DEBUG_UART_8250_WORD is not set +# CONFIG_DEBUG_UART_8250_FLOW_CONTROL is not set +CONFIG_DEBUG_UNCOMPRESS=y +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +# CONFIG_EARLY_PRINTK is not set +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set +# CONFIG_CORESIGHT is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +CONFIG_ENCRYPTED_KEYS=y +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_XOR_BLOCKS=y +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_ASYNC_PQ=m +CONFIG_ASYNC_RAID6_RECOV=m +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_AKCIPHER2=y +# CONFIG_CRYPTO_RSA is not set +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_USER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_NULL2=y +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_MCRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_GCM=m +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_ECHAINIV=m + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_CTS=y +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_XTS=y +# CONFIG_CRYPTO_KEYWRAP is not set + +# +# Hash modes +# +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +# CONFIG_CRYPTO_CRCT10DIF is not set +CONFIG_CRYPTO_GHASH=m +# CONFIG_CRYPTO_POLY1305 is not set +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_FCRYPT=m +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_842 is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_DRBG_HMAC=y +# CONFIG_CRYPTO_DRBG_HASH is not set +# CONFIG_CRYPTO_DRBG_CTR is not set +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_USER_API=m +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_USER_API_RNG=m +# CONFIG_CRYPTO_USER_API_AEAD is not set +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_DEV_SUN4I_SS=m +# CONFIG_ASYMMETRIC_KEY_TYPE is not set + +# +# Certificates for signature checking +# +# CONFIG_SYSTEM_TRUSTED_KEYRING is not set +CONFIG_ARM_CRYPTO=y +# CONFIG_CRYPTO_SHA1_ARM is not set +CONFIG_CRYPTO_SHA256_ARM=m +# CONFIG_CRYPTO_SHA512_ARM is not set +# CONFIG_CRYPTO_AES_ARM is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_RAID6_PQ=y +CONFIG_BITREVERSE=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_RATIONAL=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=y +# CONFIG_CRC8 is not set +# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_COMPRESS=m +CONFIG_LZ4_DECOMPRESS=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_IA64=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_GLOB=y +# CONFIG_GLOB_SELFTEST is not set +CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set +CONFIG_LIBFDT=y +CONFIG_OID_REGISTRY=y +CONFIG_FONT_SUPPORT=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_SG_SPLIT is not set +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_VIRTUALIZATION=y diff --git a/config/linux-sunxi-next.config b/config/linux-sunxi-next.config index f25cefa33..e62477541 100644 --- a/config/linux-sunxi-next.config +++ b/config/linux-sunxi-next.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 3.18.0-rc3 Kernel Configuration +# Linux/arm 4.2.6 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -18,6 +18,7 @@ CONFIG_ARCH_SUPPORTS_UPROBES=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_ARM_PATCH_PHYS_VIRT=y CONFIG_GENERIC_BUG=y +CONFIG_PGTABLE_LEVELS=2 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_IRQ_WORK=y CONFIG_BUILDTIME_EXTABLE_SORT=y @@ -44,7 +45,8 @@ CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y -# CONFIG_POSIX_MQUEUE is not set +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y CONFIG_CROSS_MEMORY_ATTACH=y CONFIG_FHANDLE=y CONFIG_USELIB=y @@ -56,15 +58,17 @@ CONFIG_HAVE_ARCH_AUDITSYSCALL=y # CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y CONFIG_HARDIRQS_SW_RESEND=y CONFIG_GENERIC_IRQ_CHIP=y CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y CONFIG_HANDLE_DOMAIN_IRQ=y # CONFIG_IRQ_DOMAIN_DEBUG is not set CONFIG_IRQ_FORCED_THREADING=y CONFIG_SPARSE_IRQ=y +CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_ARCH_HAS_TICK_BROADCAST=y CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y @@ -86,23 +90,23 @@ CONFIG_TICK_CPU_ACCOUNTING=y # CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set # CONFIG_IRQ_TIME_ACCOUNTING is not set # CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_TASKSTATS is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y # # RCU Subsystem # CONFIG_TREE_RCU=y -# CONFIG_PREEMPT_RCU is not set +# CONFIG_RCU_EXPERT is not set +CONFIG_SRCU=y # CONFIG_TASKS_RCU is not set CONFIG_RCU_STALL_COMMON=y -# CONFIG_RCU_USER_QS is not set -CONFIG_RCU_FANOUT=32 -CONFIG_RCU_FANOUT_LEAF=16 -# CONFIG_RCU_FANOUT_EXACT is not set -# CONFIG_RCU_FAST_NO_HZ is not set # CONFIG_TREE_RCU_TRACE is not set # CONFIG_RCU_NOCB_CPU is not set -# CONFIG_BUILD_BIN2C is not set +# CONFIG_RCU_EXPEDITE_BOOT is not set +CONFIG_BUILD_BIN2C=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=17 @@ -110,24 +114,34 @@ CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 CONFIG_GENERIC_SCHED_CLOCK=y CONFIG_CGROUPS=y # CONFIG_CGROUP_DEBUG is not set -# CONFIG_CGROUP_FREEZER is not set -# CONFIG_CGROUP_DEVICE is not set -# CONFIG_CPUSETS is not set -# CONFIG_CGROUP_CPUACCT is not set -# CONFIG_RESOURCE_COUNTERS is not set -# CONFIG_CGROUP_PERF is not set -# CONFIG_CGROUP_SCHED is not set -# CONFIG_BLK_CGROUP is not set +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_PAGE_COUNTER=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_MEMCG_SWAP_ENABLED=y +CONFIG_MEMCG_KMEM=y +CONFIG_CGROUP_PERF=y +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_CGROUP=y +# CONFIG_DEBUG_BLK_CGROUP is not set +CONFIG_CGROUP_WRITEBACK=y # CONFIG_CHECKPOINT_RESTORE is not set CONFIG_NAMESPACES=y CONFIG_UTS_NS=y CONFIG_IPC_NS=y -# CONFIG_USER_NS is not set +CONFIG_USER_NS=y CONFIG_PID_NS=y CONFIG_NET_NS=y # CONFIG_SCHED_AUTOGROUP is not set # CONFIG_SYSFS_DEPRECATED is not set -# CONFIG_RELAY is not set +CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y @@ -141,8 +155,9 @@ CONFIG_SYSCTL=y CONFIG_ANON_INODES=y CONFIG_HAVE_UID16=y CONFIG_BPF=y -# CONFIG_EXPERT is not set +CONFIG_EXPERT=y CONFIG_UID16=y +CONFIG_MULTIUSER=y # CONFIG_SGETMASK_SYSCALL is not set CONFIG_SYSFS_SYSCALL=y # CONFIG_SYSCTL_SYSCALL is not set @@ -175,6 +190,7 @@ CONFIG_SLUB_DEBUG=y CONFIG_COMPAT_BRK=y # CONFIG_SLAB is not set CONFIG_SLUB=y +# CONFIG_SLOB is not set CONFIG_SLUB_CPU_PARTIAL=y # CONFIG_SYSTEM_TRUSTED_KEYRING is not set # CONFIG_PROFILING is not set @@ -187,6 +203,7 @@ CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_ARCH_USE_BUILTIN_BSWAP=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_OPTPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_DMA_CONTIGUOUS=y @@ -211,6 +228,7 @@ CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y CONFIG_HAVE_MOD_ARCH_SPECIFIC=y CONFIG_MODULES_USE_ELF_REL=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y CONFIG_CLONE_BACKWARDS=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_OLD_SIGACTION=y @@ -219,23 +237,27 @@ CONFIG_OLD_SIGACTION=y # GCOV-based kernel profiling # # CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y CONFIG_BASE_SMALL=0 CONFIG_MODULES=y # CONFIG_MODULE_FORCE_LOAD is not set -# CONFIG_MODULE_UNLOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set # CONFIG_MODULE_SIG is not set # CONFIG_MODULE_COMPRESS is not set +CONFIG_MODULES_TREE_LOOKUP=y CONFIG_STOP_MACHINE=y CONFIG_BLOCK=y CONFIG_LBDAF=y CONFIG_BLK_DEV_BSG=y -# CONFIG_BLK_DEV_BSGLIB is not set +CONFIG_BLK_DEV_BSGLIB=y # CONFIG_BLK_DEV_INTEGRITY is not set +CONFIG_BLK_DEV_THROTTLING=y # CONFIG_BLK_CMDLINE_PARSER is not set # @@ -251,6 +273,7 @@ CONFIG_EFI_PARTITION=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_DEADLINE=y CONFIG_IOSCHED_CFQ=y +CONFIG_CFQ_GROUP_IOSCHED=y # CONFIG_DEFAULT_DEADLINE is not set CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set @@ -263,6 +286,7 @@ CONFIG_INLINE_WRITE_UNLOCK_IRQ=y CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y CONFIG_MUTEX_SPIN_ON_OWNER=y CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y CONFIG_FREEZER=y # @@ -270,10 +294,8 @@ CONFIG_FREEZER=y # CONFIG_MMU=y CONFIG_ARCH_MULTIPLATFORM=y -# CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_AT91 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_GEMINI is not set # CONFIG_ARCH_EBSA110 is not set @@ -292,7 +314,6 @@ CONFIG_ARCH_MULTIPLATFORM=y # CONFIG_ARCH_W90X900 is not set # CONFIG_ARCH_LPC32XX is not set # CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_MSM is not set # CONFIG_ARCH_SHMOBILE_LEGACY is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set @@ -314,8 +335,11 @@ CONFIG_ARCH_MULTI_V6_V7=y # CONFIG_ARCH_MULTI_CPU_AUTO is not set # CONFIG_ARCH_VIRT is not set # CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_AT91 is not set # CONFIG_ARCH_BCM is not set # CONFIG_ARCH_BERLIN is not set +# CONFIG_ARCH_DIGICOLOR is not set # CONFIG_ARCH_HIGHBANK is not set # CONFIG_ARCH_HISI is not set # CONFIG_ARCH_KEYSTONE is not set @@ -349,9 +373,11 @@ CONFIG_MACH_SUN8I=y CONFIG_MACH_SUN9I=y # CONFIG_ARCH_SIRF is not set # CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_UNIPHIER is not set # CONFIG_ARCH_U8500 is not set # CONFIG_ARCH_VEXPRESS is not set # CONFIG_ARCH_WM8850 is not set +# CONFIG_ARCH_ZX is not set # CONFIG_ARCH_ZYNQ is not set # @@ -380,14 +406,13 @@ CONFIG_ARM_THUMB=y CONFIG_ARM_VIRT_EXT=y CONFIG_SWP_EMULATE=y # CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_BPREDICT_DISABLE is not set CONFIG_KUSER_HELPERS=y +CONFIG_VDSO=y CONFIG_OUTER_CACHE=y CONFIG_OUTER_CACHE_SYNC=y CONFIG_MIGHT_HAVE_CACHE_L2X0=y CONFIG_CACHE_L2X0=y -CONFIG_CACHE_PL310=y # CONFIG_PL310_ERRATA_588369 is not set # CONFIG_PL310_ERRATA_727915 is not set # CONFIG_PL310_ERRATA_753970 is not set @@ -395,9 +420,10 @@ CONFIG_CACHE_PL310=y CONFIG_ARM_L1_CACHE_SHIFT_6=y CONFIG_ARM_L1_CACHE_SHIFT=6 CONFIG_ARM_DMA_MEM_BUFFERABLE=y +# CONFIG_ARM_KERNMEM_PERMS is not set CONFIG_MULTI_IRQ_HANDLER=y # CONFIG_ARM_ERRATA_430973 is not set -# CONFIG_ARM_ERRATA_643719 is not set +CONFIG_ARM_ERRATA_643719=y # CONFIG_ARM_ERRATA_720789 is not set # CONFIG_ARM_ERRATA_754322 is not set # CONFIG_ARM_ERRATA_754327 is not set @@ -410,6 +436,7 @@ CONFIG_MULTI_IRQ_HANDLER=y # Bus support # # CONFIG_PCI is not set +# CONFIG_PCI_DOMAINS_GENERIC is not set # CONFIG_PCI_SYSCALL is not set # CONFIG_PCCARD is not set @@ -420,8 +447,8 @@ CONFIG_HAVE_SMP=y CONFIG_SMP=y CONFIG_SMP_ON_UP=y CONFIG_ARM_CPU_TOPOLOGY=y -# CONFIG_SCHED_MC is not set -# CONFIG_SCHED_SMT is not set +CONFIG_SCHED_MC=y +CONFIG_SCHED_SMT=y CONFIG_HAVE_ARM_ARCH_TIMER=y # CONFIG_MCPM is not set # CONFIG_BIG_LITTLE is not set @@ -455,10 +482,12 @@ CONFIG_HIGHMEM=y CONFIG_HIGHPTE=y CONFIG_HW_PERF_EVENTS=y CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +# CONFIG_ARM_MODULE_PLTS is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_HAVE_MEMBLOCK=y CONFIG_NO_BOOTMEM=y +CONFIG_MEMORY_ISOLATION=y # CONFIG_HAVE_BOOTMEM_INFO_NODE is not set CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 @@ -469,12 +498,18 @@ CONFIG_ZONE_DMA_FLAG=0 CONFIG_BOUNCE=y # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 -# CONFIG_CLEANCACHE is not set -# CONFIG_FRONTSWAP is not set -# CONFIG_CMA is not set -# CONFIG_ZPOOL is not set +CONFIG_CLEANCACHE=y +CONFIG_FRONTSWAP=y +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set +# CONFIG_CMA_DEBUGFS is not set +CONFIG_CMA_AREAS=7 +CONFIG_ZSWAP=y +CONFIG_ZPOOL=y # CONFIG_ZBUD is not set -# CONFIG_ZSMALLOC is not set +CONFIG_ZSMALLOC=y +# CONFIG_PGTABLE_MAPPING is not set +# CONFIG_ZSMALLOC_STAT is not set CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_ALIGNMENT_TRAP=y # CONFIG_UACCESS_WITH_MEMCPY is not set @@ -512,20 +547,24 @@ CONFIG_CPU_FREQ_GOV_COMMON=y CONFIG_CPU_FREQ_STAT=y # CONFIG_CPU_FREQ_STAT_DETAILS is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_ONDEMAND=y -# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -# CONFIG_CPUFREQ_DT is not set +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y # -# ARM CPU frequency scaling drivers +# CPU frequency scaling drivers # +CONFIG_CPUFREQ_DT=y +CONFIG_ARM_BIG_LITTLE_CPUFREQ=m +CONFIG_ARM_DT_BL_CPUFREQ=m # CONFIG_ARM_KIRKWOOD_CPUFREQ is not set +CONFIG_QORIQ_CPUFREQ=m # # CPU Idle @@ -533,10 +572,12 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE_GOV_LADDER=y CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_DT_IDLE_STATES=y # # ARM CPU Idle Drivers # +CONFIG_ARM_CPUIDLE=y # CONFIG_ARM_HIGHBANK_CPUIDLE is not set # CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set @@ -556,7 +597,6 @@ CONFIG_NEON=y # Userspace binary formats # CONFIG_BINFMT_ELF=y -CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y CONFIG_BINFMT_SCRIPT=y # CONFIG_HAVE_AOUT is not set @@ -573,10 +613,10 @@ CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y # CONFIG_PM_AUTOSLEEP is not set # CONFIG_PM_WAKELOCKS is not set -CONFIG_PM_RUNTIME=y CONFIG_PM=y # CONFIG_PM_DEBUG is not set # CONFIG_APM_EMULATION is not set +CONFIG_PM_OPP=y CONFIG_PM_CLK=y # CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set CONFIG_CPU_PM=y @@ -584,14 +624,15 @@ CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ARM_CPU_SUSPEND=y CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_NET=y +CONFIG_NET_INGRESS=y # # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_DIAG is not set +CONFIG_PACKET_DIAG=m CONFIG_UNIX=y -# CONFIG_UNIX_DIAG is not set +CONFIG_UNIX_DIAG=m CONFIG_XFRM=y CONFIG_XFRM_ALGO=y CONFIG_XFRM_USER=y @@ -626,7 +667,8 @@ CONFIG_SYN_COOKIES=y # CONFIG_NET_IPVTI is not set CONFIG_NET_UDP_TUNNEL=m # CONFIG_NET_FOU is not set -# CONFIG_GENEVE is not set +# CONFIG_NET_FOU_IP_TUNNELS is not set +# CONFIG_GENEVE_CORE is not set CONFIG_INET_AH=y CONFIG_INET_ESP=y CONFIG_INET_IPCOMP=y @@ -653,6 +695,7 @@ CONFIG_TCP_CONG_VENO=y CONFIG_TCP_CONG_YEAH=y CONFIG_TCP_CONG_ILLINOIS=y # CONFIG_TCP_CONG_DCTCP is not set +# CONFIG_TCP_CONG_CDG is not set # CONFIG_DEFAULT_BIC is not set CONFIG_DEFAULT_CUBIC=y # CONFIG_DEFAULT_HTCP is not set @@ -699,11 +742,13 @@ CONFIG_BRIDGE_NETFILTER=m # # Core Netfilter Configuration # +CONFIG_NETFILTER_INGRESS=y CONFIG_NETFILTER_NETLINK=m CONFIG_NETFILTER_NETLINK_ACCT=m CONFIG_NETFILTER_NETLINK_QUEUE=m CONFIG_NETFILTER_NETLINK_LOG=m CONFIG_NF_CONNTRACK=m +CONFIG_NF_LOG_COMMON=m CONFIG_NF_CONNTRACK_MARK=y CONFIG_NF_CONNTRACK_SECMARK=y CONFIG_NF_CONNTRACK_ZONES=y @@ -711,6 +756,7 @@ CONFIG_NF_CONNTRACK_PROCFS=y CONFIG_NF_CONNTRACK_EVENTS=y CONFIG_NF_CONNTRACK_TIMEOUT=y CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_LABELS=y CONFIG_NF_CT_PROTO_DCCP=m CONFIG_NF_CT_PROTO_GRE=m CONFIG_NF_CT_PROTO_SCTP=m @@ -728,8 +774,38 @@ CONFIG_NF_CONNTRACK_SIP=m CONFIG_NF_CONNTRACK_TFTP=m CONFIG_NF_CT_NETLINK=m CONFIG_NF_CT_NETLINK_TIMEOUT=m -# CONFIG_NETFILTER_NETLINK_QUEUE_CT is not set -# CONFIG_NF_TABLES is not set +CONFIG_NF_CT_NETLINK_HELPER=m +CONFIG_NETFILTER_NETLINK_QUEUE_CT=y +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PROTO_DCCP=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_SIP=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_REDIRECT=m +CONFIG_NETFILTER_SYNPROXY=m +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=m +CONFIG_NF_TABLES_NETDEV=m +CONFIG_NFT_EXTHDR=m +CONFIG_NFT_META=m +CONFIG_NFT_CT=m +CONFIG_NFT_RBTREE=m +CONFIG_NFT_HASH=m +CONFIG_NFT_COUNTER=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +CONFIG_NFT_MASQ=m +CONFIG_NFT_REDIR=m +CONFIG_NFT_NAT=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_REJECT_INET=m +CONFIG_NFT_COMPAT=m CONFIG_NETFILTER_XTABLES=m # @@ -749,15 +825,18 @@ CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m CONFIG_NETFILTER_XT_TARGET_CT=m CONFIG_NETFILTER_XT_TARGET_DSCP=m CONFIG_NETFILTER_XT_TARGET_HL=m -# CONFIG_NETFILTER_XT_TARGET_HMARK is not set +CONFIG_NETFILTER_XT_TARGET_HMARK=m CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m CONFIG_NETFILTER_XT_TARGET_LED=m -# CONFIG_NETFILTER_XT_TARGET_LOG is not set +CONFIG_NETFILTER_XT_TARGET_LOG=m CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_NAT=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m CONFIG_NETFILTER_XT_TARGET_NFLOG=m CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m CONFIG_NETFILTER_XT_TARGET_NOTRACK=m CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m @@ -769,12 +848,12 @@ CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m # Xtables matches # CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -# CONFIG_NETFILTER_XT_MATCH_BPF is not set -# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m CONFIG_NETFILTER_XT_MATCH_CLUSTER=m CONFIG_NETFILTER_XT_MATCH_COMMENT=m CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m CONFIG_NETFILTER_XT_MATCH_CONNMARK=m CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m @@ -787,7 +866,7 @@ CONFIG_NETFILTER_XT_MATCH_ESP=m CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m CONFIG_NETFILTER_XT_MATCH_HELPER=m CONFIG_NETFILTER_XT_MATCH_HL=m -# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m CONFIG_NETFILTER_XT_MATCH_IPRANGE=m CONFIG_NETFILTER_XT_MATCH_IPVS=m CONFIG_NETFILTER_XT_MATCH_L2TP=m @@ -820,14 +899,14 @@ CONFIG_IP_SET_BITMAP_IP=m CONFIG_IP_SET_BITMAP_IPMAC=m CONFIG_IP_SET_BITMAP_PORT=m CONFIG_IP_SET_HASH_IP=m -# CONFIG_IP_SET_HASH_IPMARK is not set +CONFIG_IP_SET_HASH_IPMARK=m CONFIG_IP_SET_HASH_IPPORT=m CONFIG_IP_SET_HASH_IPPORTIP=m CONFIG_IP_SET_HASH_IPPORTNET=m -# CONFIG_IP_SET_HASH_MAC is not set -# CONFIG_IP_SET_HASH_NETPORTNET is not set +CONFIG_IP_SET_HASH_MAC=m +CONFIG_IP_SET_HASH_NETPORTNET=m CONFIG_IP_SET_HASH_NET=m -# CONFIG_IP_SET_HASH_NETNET is not set +CONFIG_IP_SET_HASH_NETNET=m CONFIG_IP_SET_HASH_NETPORT=m CONFIG_IP_SET_HASH_NETIFACE=m CONFIG_IP_SET_LIST_SET=m @@ -869,6 +948,7 @@ CONFIG_IP_VS_SH_TAB_BITS=8 # # IPVS application helper # +# CONFIG_IP_VS_FTP is not set CONFIG_IP_VS_NFCT=y CONFIG_IP_VS_PE_SIP=m @@ -877,11 +957,23 @@ CONFIG_IP_VS_PE_SIP=m # CONFIG_NF_DEFRAG_IPV4=m CONFIG_NF_CONNTRACK_IPV4=m -CONFIG_NF_CONNTRACK_PROC_COMPAT=y -# CONFIG_NF_LOG_ARP is not set -# CONFIG_NF_LOG_IPV4 is not set +# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set +CONFIG_NF_TABLES_IPV4=m +CONFIG_NFT_CHAIN_ROUTE_IPV4=m +CONFIG_NFT_REJECT_IPV4=m +CONFIG_NF_TABLES_ARP=m +CONFIG_NF_LOG_ARP=m +CONFIG_NF_LOG_IPV4=m CONFIG_NF_REJECT_IPV4=m -# CONFIG_NF_NAT_IPV4 is not set +CONFIG_NF_NAT_IPV4=m +CONFIG_NFT_CHAIN_NAT_IPV4=m +CONFIG_NF_NAT_MASQUERADE_IPV4=m +CONFIG_NFT_MASQ_IPV4=m +CONFIG_NFT_REDIR_IPV4=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_MATCH_AH=m CONFIG_IP_NF_MATCH_ECN=m @@ -889,8 +981,11 @@ CONFIG_IP_NF_MATCH_RPFILTER=m CONFIG_IP_NF_MATCH_TTL=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m -# CONFIG_IP_NF_TARGET_SYNPROXY is not set -# CONFIG_IP_NF_NAT is not set +CONFIG_IP_NF_TARGET_SYNPROXY=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_TARGET_CLUSTERIP=m CONFIG_IP_NF_TARGET_ECN=m @@ -905,9 +1000,16 @@ CONFIG_IP_NF_ARP_MANGLE=m # CONFIG_NF_DEFRAG_IPV6=m CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_NF_TABLES_IPV6=m +CONFIG_NFT_CHAIN_ROUTE_IPV6=m +CONFIG_NFT_REJECT_IPV6=m CONFIG_NF_REJECT_IPV6=m -# CONFIG_NF_LOG_IPV6 is not set -# CONFIG_NF_NAT_IPV6 is not set +CONFIG_NF_LOG_IPV6=m +CONFIG_NF_NAT_IPV6=m +CONFIG_NFT_CHAIN_NAT_IPV6=m +CONFIG_NF_NAT_MASQUERADE_IPV6=m +CONFIG_NFT_MASQ_IPV6=m +CONFIG_NFT_REDIR_IPV6=m CONFIG_IP6_NF_IPTABLES=m CONFIG_IP6_NF_MATCH_AH=m CONFIG_IP6_NF_MATCH_EUI64=m @@ -921,10 +1023,16 @@ CONFIG_IP6_NF_MATCH_RT=m CONFIG_IP6_NF_TARGET_HL=m CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_REJECT=m -# CONFIG_IP6_NF_TARGET_SYNPROXY is not set +CONFIG_IP6_NF_TARGET_SYNPROXY=m CONFIG_IP6_NF_MANGLE=m CONFIG_IP6_NF_RAW=m -# CONFIG_IP6_NF_NAT is not set +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_IP6_NF_TARGET_NPT=m +CONFIG_NF_TABLES_BRIDGE=m +CONFIG_NFT_BRIDGE_META=m +CONFIG_NFT_BRIDGE_REJECT=m +CONFIG_NF_LOG_BRIDGE=m CONFIG_BRIDGE_NF_EBTABLES=m CONFIG_BRIDGE_EBT_BROUTE=m CONFIG_BRIDGE_EBT_T_FILTER=m @@ -946,56 +1054,167 @@ CONFIG_BRIDGE_EBT_REDIRECT=m CONFIG_BRIDGE_EBT_SNAT=m CONFIG_BRIDGE_EBT_LOG=m CONFIG_BRIDGE_EBT_NFLOG=m -# CONFIG_IP_DCCP is not set -# CONFIG_IP_SCTP is not set -# CONFIG_RDS is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m + +# +# DCCP CCIDs Configuration +# +# CONFIG_IP_DCCP_CCID2_DEBUG is not set +CONFIG_IP_DCCP_CCID3=y +# CONFIG_IP_DCCP_CCID3_DEBUG is not set +CONFIG_IP_DCCP_TFRC_LIB=y + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_OBJCNT is not set +CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set +CONFIG_SCTP_COOKIE_HMAC_MD5=y +# CONFIG_SCTP_COOKIE_HMAC_SHA1 is not set +CONFIG_RDS=m +CONFIG_RDS_TCP=m +# CONFIG_RDS_DEBUG is not set +CONFIG_TIPC=m +CONFIG_TIPC_MEDIA_UDP=y +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +CONFIG_ATM_CLIP_NO_ICMP=y +# CONFIG_ATM_LANE is not set +CONFIG_ATM_BR2684=m +CONFIG_ATM_BR2684_IPFILTER=y CONFIG_L2TP=m # CONFIG_L2TP_DEBUGFS is not set CONFIG_L2TP_V3=y CONFIG_L2TP_IP=m CONFIG_L2TP_ETH=m -CONFIG_STP=m -CONFIG_GARP=m -CONFIG_BRIDGE=m +CONFIG_STP=y +CONFIG_GARP=y +CONFIG_MRP=y +CONFIG_BRIDGE=y CONFIG_BRIDGE_IGMP_SNOOPING=y -# CONFIG_BRIDGE_VLAN_FILTERING is not set +CONFIG_BRIDGE_VLAN_FILTERING=y CONFIG_HAVE_NET_DSA=y -CONFIG_VLAN_8021Q=m +CONFIG_NET_DSA=m +CONFIG_NET_DSA_HWMON=y +CONFIG_VLAN_8021Q=y CONFIG_VLAN_8021Q_GVRP=y -# CONFIG_VLAN_8021Q_MVRP is not set +CONFIG_VLAN_8021Q_MVRP=y # CONFIG_DECNET is not set -CONFIG_LLC=m +CONFIG_LLC=y # CONFIG_LLC2 is not set # CONFIG_IPX is not set -# CONFIG_ATALK is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_PHONET is not set -# CONFIG_6LOWPAN is not set +CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_NHC=m +CONFIG_6LOWPAN_NHC_DEST=m +CONFIG_6LOWPAN_NHC_FRAGMENT=m +CONFIG_6LOWPAN_NHC_HOP=m +CONFIG_6LOWPAN_NHC_IPV6=m +CONFIG_6LOWPAN_NHC_MOBILITY=m +CONFIG_6LOWPAN_NHC_ROUTING=m +CONFIG_6LOWPAN_NHC_UDP=m # CONFIG_IEEE802154 is not set -# CONFIG_NET_SCHED is not set -# CONFIG_DCB is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_HFSC=m +# CONFIG_NET_SCH_ATM is not set +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +# CONFIG_NET_SCH_DRR is not set +CONFIG_NET_SCH_MQPRIO=m +# CONFIG_NET_SCH_CHOKE is not set +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=y +# CONFIG_NET_SCH_FQ is not set +# CONFIG_NET_SCH_HHF is not set +# CONFIG_NET_SCH_PIE is not set +CONFIG_NET_SCH_INGRESS=m +# CONFIG_NET_SCH_PLUG is not set + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=y +CONFIG_NET_CLS_ROUTE4=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +CONFIG_NET_CLS_FLOW=m +# CONFIG_NET_CLS_CGROUP is not set +# CONFIG_NET_CLS_BPF is not set +# CONFIG_NET_CLS_FLOWER is not set +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_CANID=m +# CONFIG_NET_EMATCH_IPSET is not set +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +# CONFIG_NET_ACT_GACT is not set +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +# CONFIG_NET_ACT_SIMP is not set +CONFIG_NET_ACT_SKBEDIT=m +# CONFIG_NET_ACT_CSUM is not set +CONFIG_NET_ACT_VLAN=m +CONFIG_NET_ACT_BPF=m +CONFIG_NET_ACT_CONNMARK=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_SCH_FIFO=y +CONFIG_DCB=y CONFIG_DNS_RESOLVER=y -CONFIG_BATMAN_ADV=m -CONFIG_BATMAN_ADV_BLA=y -# CONFIG_BATMAN_ADV_DAT is not set -# CONFIG_BATMAN_ADV_NC is not set -# CONFIG_BATMAN_ADV_MCAST is not set -# CONFIG_BATMAN_ADV_DEBUG is not set +# CONFIG_BATMAN_ADV is not set CONFIG_OPENVSWITCH=m -CONFIG_OPENVSWITCH_GRE=y +CONFIG_OPENVSWITCH_GRE=m # CONFIG_VSOCKETS is not set -# CONFIG_NETLINK_MMAP is not set -# CONFIG_NETLINK_DIAG is not set -# CONFIG_NET_MPLS_GSO is not set -# CONFIG_HSR is not set +CONFIG_NETLINK_MMAP=y +CONFIG_NETLINK_DIAG=m +CONFIG_MPLS=y +CONFIG_NET_MPLS_GSO=m +# CONFIG_MPLS_ROUTING is not set +CONFIG_HSR=m +CONFIG_NET_SWITCHDEV=y CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y # CONFIG_CGROUP_NET_PRIO is not set -# CONFIG_CGROUP_NET_CLASSID is not set +CONFIG_CGROUP_NET_CLASSID=y CONFIG_NET_RX_BUSY_POLL=y CONFIG_BQL=y # CONFIG_BPF_JIT is not set @@ -1006,13 +1225,57 @@ CONFIG_NET_FLOW_LIMIT=y # CONFIG_NET_PKTGEN=m # CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set +CONFIG_CAN=y +CONFIG_CAN_RAW=m +CONFIG_CAN_BCM=m +CONFIG_CAN_GW=m + +# +# CAN Device Drivers +# +CONFIG_CAN_VCAN=m +CONFIG_CAN_SLCAN=m +CONFIG_CAN_DEV=m +CONFIG_CAN_CALC_BITTIMING=y +# CONFIG_CAN_LEDS is not set +CONFIG_CAN_TI_HECC=m +CONFIG_CAN_FLEXCAN=m +CONFIG_CAN_GRCAN=m +CONFIG_CAN_RCAR=m +CONFIG_CAN_SUN4I=m +CONFIG_CAN_SJA1000=m +CONFIG_CAN_SJA1000_ISA=m +CONFIG_CAN_SJA1000_PLATFORM=m +CONFIG_CAN_C_CAN=m +CONFIG_CAN_C_CAN_PLATFORM=m +CONFIG_CAN_M_CAN=m +CONFIG_CAN_CC770=m +CONFIG_CAN_CC770_ISA=m +CONFIG_CAN_CC770_PLATFORM=m + +# +# CAN SPI interfaces +# +CONFIG_CAN_MCP251X=m + +# +# CAN USB interfaces +# +CONFIG_CAN_EMS_USB=m +CONFIG_CAN_ESD_USB2=m +CONFIG_CAN_GS_USB=m +CONFIG_CAN_KVASER_USB=m +CONFIG_CAN_PEAK_USB=m +CONFIG_CAN_8DEV_USB=m +CONFIG_CAN_SOFTING=m +# CONFIG_CAN_DEBUG_DEVICES is not set CONFIG_IRDA=m # # IrDA protocols # CONFIG_IRLAN=m +# CONFIG_IRNET is not set CONFIG_IRCOMM=m CONFIG_IRDA_ULTRA=y @@ -1047,17 +1310,27 @@ CONFIG_USB_IRDA=m CONFIG_SIGMATEL_FIR=m CONFIG_MCS_FIR=m CONFIG_BT=m +CONFIG_BT_BREDR=y CONFIG_BT_RFCOMM=m CONFIG_BT_RFCOMM_TTY=y CONFIG_BT_BNEP=m CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=m +CONFIG_BT_LE=y +# CONFIG_BT_6LOWPAN is not set +# CONFIG_BT_SELFTEST is not set +CONFIG_BT_DEBUGFS=y # # Bluetooth device drivers # +CONFIG_BT_INTEL=m +CONFIG_BT_BCM=m +CONFIG_BT_RTL=m CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTUSB_BCM=y +CONFIG_BT_HCIBTUSB_RTL=y CONFIG_BT_HCIBTSDIO=m CONFIG_BT_HCIUART=m CONFIG_BT_HCIUART_H4=y @@ -1065,6 +1338,8 @@ CONFIG_BT_HCIUART_BCSP=y CONFIG_BT_HCIUART_ATH3K=y CONFIG_BT_HCIUART_LL=y # CONFIG_BT_HCIUART_3WIRE is not set +# CONFIG_BT_HCIUART_INTEL is not set +# CONFIG_BT_HCIUART_BCM is not set CONFIG_BT_HCIBCM203X=m CONFIG_BT_HCIBPA10X=m CONFIG_BT_HCIBFUSB=m @@ -1077,12 +1352,15 @@ CONFIG_AF_RXRPC=m CONFIG_RXKAD=m CONFIG_FIB_RULES=y CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y CONFIG_WEXT_CORE=y CONFIG_WEXT_PROC=y +CONFIG_WEXT_PRIV=y CONFIG_CFG80211=y # CONFIG_NL80211_TESTMODE is not set CONFIG_CFG80211_DEVELOPER_WARNINGS=y # CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set CONFIG_CFG80211_DEFAULT_PS=y # CONFIG_CFG80211_DEBUGFS is not set # CONFIG_CFG80211_INTERNAL_REGDB is not set @@ -1092,6 +1370,7 @@ CONFIG_MAC80211=m CONFIG_MAC80211_HAS_RC=y CONFIG_MAC80211_RC_MINSTREL=y CONFIG_MAC80211_RC_MINSTREL_HT=y +# CONFIG_MAC80211_RC_MINSTREL_VHT is not set CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" CONFIG_MAC80211_MESH=y @@ -1099,11 +1378,12 @@ CONFIG_MAC80211_LEDS=y # CONFIG_MAC80211_DEBUGFS is not set # CONFIG_MAC80211_MESSAGE_TRACING is not set # CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 CONFIG_WIMAX=m CONFIG_WIMAX_DEBUG_LEVEL=8 CONFIG_RFKILL=y CONFIG_RFKILL_LEDS=y -CONFIG_RFKILL_INPUT=y +# CONFIG_RFKILL_INPUT is not set # CONFIG_RFKILL_REGULATOR is not set # CONFIG_RFKILL_GPIO is not set # CONFIG_NET_9P is not set @@ -1128,47 +1408,147 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y CONFIG_FIRMWARE_IN_KERNEL=y CONFIG_EXTRA_FIRMWARE="" -# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +CONFIG_WANT_DEV_COREDUMP=y +CONFIG_ALLOW_DEV_COREDUMP=y +CONFIG_DEV_COREDUMP=y # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_GENERIC_CPU_DEVICES is not set CONFIG_REGMAP=y CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=m +CONFIG_REGMAP_MMIO=y CONFIG_REGMAP_IRQ=y -# CONFIG_DMA_SHARED_BUFFER is not set +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_FENCE_TRACE is not set +CONFIG_DMA_CMA=y + +# +# Default contiguous memory area size: +# +CONFIG_CMA_SIZE_MBYTES=16 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 # # Bus devices # -# CONFIG_BRCMSTB_GISB_ARB is not set -# CONFIG_ARM_CCI is not set +CONFIG_ARM_CCI=y +CONFIG_ARM_CCI_PMU=y +CONFIG_ARM_CCI400_COMMON=y +CONFIG_ARM_CCI400_PMU=y +CONFIG_ARM_CCI500_PMU=y # CONFIG_ARM_CCN is not set +# CONFIG_BRCMSTB_GISB_ARB is not set # CONFIG_VEXPRESS_CONFIG is not set # CONFIG_CONNECTOR is not set -# CONFIG_MTD is not set -CONFIG_DTC=y -CONFIG_OF=y +CONFIG_MTD=m +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_OF_PARTS=m +# CONFIG_MTD_AR7_PARTS is not set # -# Device Tree and Open Firmware support +# User Modules And Translation Layers # -# CONFIG_OF_SELFTEST is not set +# CONFIG_MTD_BLOCK is not set +# CONFIG_MTD_BLOCK_RO is not set +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set +# CONFIG_MTD_PARTITIONED_MASTER is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR & LPDDR2 PCM memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_LPDDR2_NVM is not set +# CONFIG_MTD_SPI_NOR is not set +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y +# CONFIG_OF_UNITTEST is not set CONFIG_OF_FLATTREE=y CONFIG_OF_EARLY_FLATTREE=y CONFIG_OF_ADDRESS=y CONFIG_OF_IRQ=y CONFIG_OF_NET=y CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y CONFIG_OF_RESERVED_MEM=y +# CONFIG_OF_OVERLAY is not set CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -# CONFIG_PARPORT is not set +CONFIG_PARPORT=y +# CONFIG_PARPORT_PC is not set +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +# CONFIG_PARPORT_1284 is not set +CONFIG_PARPORT_NOT_PC=y CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_NULL_BLK is not set +CONFIG_ZRAM=m +CONFIG_ZRAM_LZ4_COMPRESS=y # CONFIG_BLK_DEV_COW_COMMON is not set -# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +CONFIG_BLK_DEV_CRYPTOLOOP=y # CONFIG_BLK_DEV_DRBD is not set -# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_NBD=m # CONFIG_BLK_DEV_RAM is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -1186,14 +1566,15 @@ CONFIG_BLK_DEV=y # CONFIG_APDS9802ALS is not set # CONFIG_ISL29003 is not set # CONFIG_ISL29020 is not set -# CONFIG_SENSORS_TSL2550 is not set +CONFIG_SENSORS_TSL2550=m # CONFIG_SENSORS_BH1780 is not set # CONFIG_SENSORS_BH1770 is not set # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set # CONFIG_TI_DAC7512 is not set -# CONFIG_BMP085_I2C is not set +CONFIG_BMP085=y +CONFIG_BMP085_I2C=m # CONFIG_BMP085_SPI is not set # CONFIG_USB_SWITCH_FSA9480 is not set # CONFIG_LATTICE_ECP3_CONFIG is not set @@ -1207,9 +1588,9 @@ CONFIG_BLK_DEV=y # CONFIG_EEPROM_AT25 is not set # CONFIG_EEPROM_LEGACY is not set # CONFIG_EEPROM_MAX6875 is not set -# CONFIG_EEPROM_93CX6 is not set +CONFIG_EEPROM_93CX6=m # CONFIG_EEPROM_93XX46 is not set -CONFIG_EEPROM_SUNXI_SID=y +# CONFIG_EEPROM_SUNXI_SID is not set # # Texas Instruments shared transport line discipline @@ -1227,6 +1608,10 @@ CONFIG_EEPROM_SUNXI_SID=y # Intel MIC Bus Driver # +# +# SCIF Bus Driver +# + # # Intel MIC Host Driver # @@ -1234,14 +1619,19 @@ CONFIG_EEPROM_SUNXI_SID=y # # Intel MIC Card Driver # + +# +# SCIF Driver +# # CONFIG_ECHO is not set # CONFIG_CXL_BASE is not set +# CONFIG_CXL_KERNEL_API is not set # # SCSI device support # CONFIG_SCSI_MOD=y -# CONFIG_RAID_ATTRS is not set +CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y # CONFIG_SCSI_NETLINK is not set @@ -1254,9 +1644,10 @@ CONFIG_SCSI_PROC_FS=y CONFIG_BLK_DEV_SD=y # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set -# CONFIG_BLK_DEV_SR is not set -# CONFIG_CHR_DEV_SG is not set -# CONFIG_CHR_DEV_SCH is not set +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set # CONFIG_SCSI_SCAN_ASYNC is not set @@ -1266,7 +1657,7 @@ CONFIG_BLK_DEV_SD=y # # CONFIG_SCSI_SPI_ATTRS is not set # CONFIG_SCSI_FC_ATTRS is not set -# CONFIG_SCSI_ISCSI_ATTRS is not set +CONFIG_SCSI_ISCSI_ATTRS=y # CONFIG_SCSI_SAS_ATTRS is not set # CONFIG_SCSI_SAS_LIBSAS is not set # CONFIG_SCSI_SRP_ATTRS is not set @@ -1276,7 +1667,10 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_UFSHCD is not set # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_DH is not set -# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_SCSI_OSD_INITIATOR=m +# CONFIG_SCSI_OSD_ULD is not set +CONFIG_SCSI_OSD_DPRINT_SENSE=1 +# CONFIG_SCSI_OSD_DEBUG is not set CONFIG_ATA=y # CONFIG_ATA_NONSTANDARD is not set CONFIG_ATA_VERBOSE_ERROR=y @@ -1285,7 +1679,8 @@ CONFIG_SATA_PMP=y # # Controllers with non-SFF native interface # -# CONFIG_SATA_AHCI_PLATFORM is not set +CONFIG_SATA_AHCI_PLATFORM=y +# CONFIG_AHCI_CEVA is not set CONFIG_AHCI_SUNXI=y CONFIG_ATA_SFF=y @@ -1305,11 +1700,51 @@ CONFIG_ATA_BMDMA=y # # PIO-only SFF controllers # +# CONFIG_PATA_PLATFORM is not set # # Generic fallback / legacy drivers # -# CONFIG_MD is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BCACHE=m +# CONFIG_BCACHE_DEBUG is not set +# CONFIG_BCACHE_CLOSURES_DEBUG is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=m +# CONFIG_DM_MQ_DEFAULT is not set +CONFIG_DM_DEBUG=y +CONFIG_DM_BUFIO=m +CONFIG_DM_BIO_PRISON=m +CONFIG_DM_PERSISTENT_DATA=m +# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_THIN_PROVISIONING=m +CONFIG_DM_CACHE=m +CONFIG_DM_CACHE_MQ=m +CONFIG_DM_CACHE_SMQ=m +CONFIG_DM_CACHE_CLEANER=m +# CONFIG_DM_ERA is not set +# CONFIG_DM_MIRROR is not set +CONFIG_DM_RAID=m +# CONFIG_DM_ZERO is not set +CONFIG_DM_MULTIPATH=m +# CONFIG_DM_MULTIPATH_QL is not set +# CONFIG_DM_MULTIPATH_ST is not set +# CONFIG_DM_DELAY is not set +CONFIG_DM_UEVENT=y +CONFIG_DM_FLAKEY=m +CONFIG_DM_VERITY=m +CONFIG_DM_SWITCH=m +CONFIG_DM_LOG_WRITES=m # CONFIG_TARGET_CORE is not set CONFIG_NETDEVICES=y CONFIG_MII=y @@ -1317,15 +1752,22 @@ CONFIG_NET_CORE=y CONFIG_BONDING=y # CONFIG_DUMMY is not set # CONFIG_EQUALIZER is not set +# CONFIG_IFB is not set # CONFIG_NET_TEAM is not set -# CONFIG_MACVLAN is not set +CONFIG_MACVLAN=y +CONFIG_MACVTAP=m +CONFIG_IPVLAN=m # CONFIG_VXLAN is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_TUN is not set -# CONFIG_VETH is not set +CONFIG_TUN=y +# CONFIG_TUN_VNET_CROSS_LE is not set +CONFIG_VETH=y # CONFIG_NLMON is not set +CONFIG_ATM_DRIVERS=y +# CONFIG_ATM_DUMMY is not set +# CONFIG_ATM_TCP is not set # # CAIF transport drivers @@ -1340,21 +1782,24 @@ CONFIG_BONDING=y # CONFIG_NET_DSA_MV88E6131 is not set # CONFIG_NET_DSA_MV88E6123_61_65 is not set # CONFIG_NET_DSA_MV88E6171 is not set +# CONFIG_NET_DSA_MV88E6352 is not set # CONFIG_NET_DSA_BCM_SF2 is not set CONFIG_ETHERNET=y CONFIG_NET_VENDOR_ALLWINNER=y CONFIG_SUN4I_EMAC=y # CONFIG_ALTERA_TSE is not set -# CONFIG_NET_XGENE is not set # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set # CONFIG_NET_VENDOR_CIRRUS is not set # CONFIG_DM9000 is not set # CONFIG_DNET is not set +CONFIG_NET_VENDOR_EZCHIP=y +# CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set # CONFIG_NET_VENDOR_FARADAY is not set CONFIG_NET_VENDOR_HISILICON=y # CONFIG_HIX5HD2_GMAC is not set +CONFIG_HIP04_ETH=m # CONFIG_NET_VENDOR_INTEL is not set # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MICREL is not set @@ -1363,64 +1808,218 @@ CONFIG_NET_VENDOR_HISILICON=y # CONFIG_ETHOC is not set CONFIG_NET_VENDOR_QUALCOMM=y # CONFIG_QCA7000 is not set +CONFIG_NET_VENDOR_RENESAS=y +CONFIG_NET_VENDOR_ROCKER=y # CONFIG_NET_VENDOR_SAMSUNG is not set # CONFIG_NET_VENDOR_SEEQ is not set # CONFIG_NET_VENDOR_SMSC is not set CONFIG_NET_VENDOR_STMICRO=y CONFIG_STMMAC_ETH=y CONFIG_STMMAC_PLATFORM=y -CONFIG_DWMAC_SUNXI=y -# CONFIG_STMMAC_DEBUG_FS is not set -# CONFIG_STMMAC_DA is not set +CONFIG_DWMAC_GENERIC=y +# CONFIG_DWMAC_IPQ806X is not set +# CONFIG_DWMAC_LPC18XX is not set +# CONFIG_DWMAC_MESON is not set +# CONFIG_DWMAC_ROCKCHIP is not set +# CONFIG_DWMAC_SOCFPGA is not set +# CONFIG_DWMAC_STI is not set +CONFIG_DWMAC_SUNXI=m # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_PHYLIB=y +CONFIG_SWCONFIG=y +# CONFIG_SWCONFIG_LEDS is not set # # MII PHY device drivers # -# CONFIG_AT803X_PHY is not set -# CONFIG_AMD_PHY is not set -# CONFIG_AMD_XGBE_PHY is not set -# CONFIG_MARVELL_PHY is not set -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -# CONFIG_LXT_PHY is not set -# CONFIG_CICADA_PHY is not set -# CONFIG_VITESSE_PHY is not set -# CONFIG_SMSC_PHY is not set -# CONFIG_BROADCOM_PHY is not set +CONFIG_AT803X_PHY=m +CONFIG_AMD_PHY=m +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_BROADCOM_PHY=m # CONFIG_BCM7XXX_PHY is not set -# CONFIG_BCM87XX_PHY is not set -# CONFIG_ICPLUS_PHY is not set -# CONFIG_REALTEK_PHY is not set -# CONFIG_NATIONAL_PHY is not set -# CONFIG_STE10XP is not set -# CONFIG_LSI_ET1011C_PHY is not set -# CONFIG_MICREL_PHY is not set +CONFIG_BCM87XX_PHY=m +CONFIG_ICPLUS_PHY=m +CONFIG_REALTEK_PHY=m +CONFIG_NATIONAL_PHY=m +CONFIG_STE10XP=m +CONFIG_LSI_ET1011C_PHY=m +CONFIG_MICREL_PHY=m +# CONFIG_DP83867_PHY is not set # CONFIG_FIXED_PHY is not set # CONFIG_MDIO_BITBANG is not set CONFIG_MDIO_SUN4I=y # CONFIG_MDIO_BUS_MUX_GPIO is not set # CONFIG_MDIO_BUS_MUX_MMIOREG is not set # CONFIG_MDIO_BCM_UNIMAC is not set +CONFIG_B53=y +CONFIG_B53_SPI_DRIVER=y +CONFIG_B53_PHY_DRIVER=y +# CONFIG_B53_MMAP_DRIVER is not set +CONFIG_B53_SRAB_DRIVER=y +CONFIG_B53_PHY_FIXUP=y # CONFIG_MICREL_KS8995MA is not set -# CONFIG_PPP is not set +# CONFIG_PLIP is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPPOATM is not set +CONFIG_PPPOE=y +CONFIG_PPTP=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y CONFIG_SLIP=m -CONFIG_SLHC=m +CONFIG_SLHC=y CONFIG_SLIP_COMPRESSED=y CONFIG_SLIP_SMART=y CONFIG_SLIP_MODE_SLIP6=y CONFIG_USB_NET_DRIVERS=y -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_RTL8152 is not set -# CONFIG_USB_USBNET is not set -# CONFIG_USB_HSO is not set -# CONFIG_USB_IPHETH is not set -# CONFIG_WLAN is not set +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_AX88179_178A=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_CDC_NCM=m +CONFIG_USB_NET_HUAWEI_CDC_NCM=m +CONFIG_USB_NET_CDC_MBIM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SR9700=m +CONFIG_USB_NET_SR9800=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_HSO=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_WLAN=y +CONFIG_LIBERTAS_THINFIRM=m +# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AT76C50X_USB=m +# CONFIG_USB_ZD1201 is not set +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y +CONFIG_MAC80211_HWSIM=m +CONFIG_ATH_COMMON=m +CONFIG_ATH_CARDS=m +# CONFIG_ATH_DEBUG is not set +CONFIG_ATH9K_HW=m +CONFIG_ATH9K_COMMON=m +CONFIG_ATH9K_BTCOEX_SUPPORT=y +CONFIG_ATH9K=m +# CONFIG_ATH9K_AHB is not set +# CONFIG_ATH9K_DEBUGFS is not set +# CONFIG_ATH9K_DYNACK is not set +# CONFIG_ATH9K_WOW is not set +CONFIG_ATH9K_RFKILL=y +# CONFIG_ATH9K_CHANNEL_CONTEXT is not set +CONFIG_ATH9K_PCOEM=y +CONFIG_ATH9K_HTC=m +# CONFIG_ATH9K_HTC_DEBUGFS is not set +CONFIG_CARL9170=m +CONFIG_CARL9170_LEDS=y +CONFIG_CARL9170_WPC=y +# CONFIG_CARL9170_HWRNG is not set +CONFIG_ATH6KL=m +CONFIG_ATH6KL_SDIO=m +CONFIG_ATH6KL_USB=m +# CONFIG_ATH6KL_DEBUG is not set +CONFIG_AR5523=m +CONFIG_ATH10K=m +# CONFIG_ATH10K_DEBUG is not set +# CONFIG_ATH10K_DEBUGFS is not set +# CONFIG_WCN36XX is not set +CONFIG_B43=m +CONFIG_B43_BCMA=y +CONFIG_B43_SSB=y +CONFIG_B43_BUSES_BCMA_AND_SSB=y +# CONFIG_B43_BUSES_BCMA is not set +# CONFIG_B43_BUSES_SSB is not set +# CONFIG_B43_SDIO is not set +CONFIG_B43_BCMA_PIO=y +CONFIG_B43_PIO=y +CONFIG_B43_PHY_G=y +CONFIG_B43_PHY_N=y +CONFIG_B43_PHY_LP=y +CONFIG_B43_PHY_HT=y +CONFIG_B43_LEDS=y +CONFIG_B43_HWRNG=y +# CONFIG_B43_DEBUG is not set +# CONFIG_B43LEGACY is not set +CONFIG_BRCMUTIL=m +# CONFIG_BRCMSMAC is not set +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_PROTO_BCDC=y +CONFIG_BRCMFMAC_SDIO=y +# CONFIG_BRCMFMAC_USB is not set +# CONFIG_BRCM_TRACING is not set +# CONFIG_BRCMDBG is not set +# CONFIG_HOSTAP is not set +# CONFIG_LIBERTAS is not set +# CONFIG_P54_COMMON is not set +CONFIG_RT2X00=m +CONFIG_RT2500USB=m +# CONFIG_RT73USB is not set +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT33XX=y +CONFIG_RT2800USB_RT35XX=y +CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RT2800_LIB=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +CONFIG_RT2X00_DEBUG=y +CONFIG_WL_MEDIATEK=y +CONFIG_MT7601U=m +CONFIG_RTL_CARDS=m +CONFIG_RTL8192CU=m +CONFIG_RTLWIFI=m +CONFIG_RTLWIFI_USB=m +CONFIG_RTLWIFI_DEBUG=y +CONFIG_RTL8192C_COMMON=m +# CONFIG_WL_TI is not set +# CONFIG_ZD1211RW is not set +# CONFIG_MWIFIEX is not set +# CONFIG_CW1200 is not set +# CONFIG_RSI_91X is not set # # WiMAX Wireless Broadband devices @@ -1433,40 +2032,162 @@ CONFIG_USB_NET_DRIVERS=y # Input device support # CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set -# CONFIG_INPUT_POLLDEV is not set +CONFIG_INPUT_LEDS=m +CONFIG_INPUT_FF_MEMLESS=m +CONFIG_INPUT_POLLDEV=m # CONFIG_INPUT_SPARSEKMAP is not set -# CONFIG_INPUT_MATRIXKMAP is not set +CONFIG_INPUT_MATRIXKMAP=m # # Userland interfaces # # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set +CONFIG_INPUT_EVDEV=m +CONFIG_INPUT_EVBUG=m # # Input Device Drivers # -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +CONFIG_KEYBOARD_SUN4I_LRADC=m +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CAP11XX is not set +CONFIG_KEYBOARD_BCM=m +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_CYPRESS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_FOCALTECH=y +CONFIG_MOUSE_SERIAL=m +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_OF_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_AR1021_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +CONFIG_TOUCHSCREEN_CHIPONE_ICN8318=m +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +CONFIG_TOUCHSCREEN_GOODIX=m +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_UCB1400 is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set +# CONFIG_TOUCHSCREEN_WM97XX is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +CONFIG_TOUCHSCREEN_SUN4I=m +# CONFIG_TOUCHSCREEN_SUR40 is not set +CONFIG_TOUCHSCREEN_SX8654=m +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_MPU3050 is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_REGULATOR_HAPTIC is not set +CONFIG_INPUT_AXP20X_PEK=y +# CONFIG_INPUT_UINPUT is not set +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2665_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set # # Hardware I/O ports # CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_LIBPS2 is not set +# CONFIG_SERIO_PARKBD is not set +CONFIG_SERIO_LIBPS2=y # CONFIG_SERIO_RAW is not set # CONFIG_SERIO_ALTERA_PS2 is not set # CONFIG_SERIO_PS2MULT is not set # CONFIG_SERIO_ARC_PS2 is not set # CONFIG_SERIO_APBPS2 is not set +CONFIG_SERIO_SUN4I_PS2=m # CONFIG_GAMEPORT is not set # @@ -1478,14 +2199,15 @@ CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_VT_CONSOLE_SLEEP=y CONFIG_HW_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_VT_HW_CONSOLE_BINDING=y CONFIG_UNIX98_PTYS=y -# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_N_GSM is not set # CONFIG_TRACE_SINK is not set +CONFIG_DEVMEM=y CONFIG_DEVKMEM=y # @@ -1500,6 +2222,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=8 # CONFIG_SERIAL_8250_EXTENDED is not set CONFIG_SERIAL_8250_DW=y # CONFIG_SERIAL_8250_EM is not set +# CONFIG_SERIAL_8250_INGENIC is not set # # Non-8250 serial port support @@ -1512,16 +2235,24 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_SERIAL_SCCNXP is not set # CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_BCM63XX is not set # CONFIG_SERIAL_ALTERA_JTAGUART is not set # CONFIG_SERIAL_ALTERA_UART is not set # CONFIG_SERIAL_IFX6X60 is not set # CONFIG_SERIAL_XILINX_PS_UART is not set # CONFIG_SERIAL_ARC is not set # CONFIG_SERIAL_FSL_LPUART is not set +CONFIG_SERIAL_CONEXANT_DIGICOLOR=m # CONFIG_SERIAL_ST_ASC is not set +CONFIG_SERIAL_STM32=m +# CONFIG_TTY_PRINTK is not set +CONFIG_PRINTER=m +# CONFIG_LP_CONSOLE is not set +# CONFIG_PPDEV is not set # CONFIG_HVC_DCC is not set # CONFIG_IPMI_HANDLER is not set -# CONFIG_HW_RANDOM is not set +CONFIG_HW_RANDOM=m +# CONFIG_HW_RANDOM_TIMERIOMEM is not set # CONFIG_R3964 is not set # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set @@ -1534,8 +2265,18 @@ CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_COMPAT=y CONFIG_I2C_CHARDEV=y -# CONFIG_I2C_MUX is not set +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +CONFIG_I2C_ARB_GPIO_CHALLENGE=m +CONFIG_I2C_MUX_GPIO=m +CONFIG_I2C_MUX_PCA9541=m +CONFIG_I2C_MUX_PCA954x=m +CONFIG_I2C_MUX_PINCTRL=m CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=m # # I2C Hardware Bus support @@ -1560,6 +2301,7 @@ CONFIG_I2C_MV64XXX=y # External I2C/SMBus adapter drivers # # CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_ROBOTFUZZ_OSIF is not set # CONFIG_I2C_TAOS_EVM is not set @@ -1568,7 +2310,9 @@ CONFIG_I2C_MV64XXX=y # # Other I2C/SMBus bus drivers # -# CONFIG_I2C_STUB is not set +CONFIG_I2C_STUB=m +CONFIG_I2C_SLAVE=y +CONFIG_I2C_SLAVE_EEPROM=m # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -1581,8 +2325,10 @@ CONFIG_SPI_MASTER=y # # CONFIG_SPI_ALTERA is not set # CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_BUTTERFLY is not set # CONFIG_SPI_CADENCE is not set # CONFIG_SPI_GPIO is not set +# CONFIG_SPI_LM70_LLP is not set # CONFIG_SPI_FSL_SPI is not set # CONFIG_SPI_OC_TINY is not set # CONFIG_SPI_PXA2XX_PCI is not set @@ -1592,12 +2338,13 @@ CONFIG_SPI_SUN4I=y CONFIG_SPI_SUN6I=y # CONFIG_SPI_XCOMM is not set # CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set # CONFIG_SPI_DESIGNWARE is not set # # SPI Protocol Masters # -CONFIG_SPI_SPIDEV=m +CONFIG_SPI_SPIDEV=y # CONFIG_SPI_TLE62X0 is not set # CONFIG_SPMI is not set # CONFIG_HSI is not set @@ -1613,6 +2360,7 @@ CONFIG_PPS=y # # CONFIG_PPS_CLIENT_KTIMER is not set # CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_PARPORT is not set # CONFIG_PPS_CLIENT_GPIO is not set # @@ -1633,15 +2381,18 @@ CONFIG_PINMUX=y CONFIG_PINCONF=y CONFIG_GENERIC_PINCONF=y # CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_AMD is not set # CONFIG_PINCTRL_SINGLE is not set CONFIG_PINCTRL_SUNXI_COMMON=y CONFIG_PINCTRL_SUN4I_A10=y CONFIG_PINCTRL_SUN5I_A10S=y CONFIG_PINCTRL_SUN5I_A13=y CONFIG_PINCTRL_SUN6I_A31=y +CONFIG_PINCTRL_SUN6I_A31S=y CONFIG_PINCTRL_SUN6I_A31_R=y CONFIG_PINCTRL_SUN7I_A20=y CONFIG_PINCTRL_SUN8I_A23=y +CONFIG_PINCTRL_SUN8I_A33=y CONFIG_PINCTRL_SUN8I_A23_R=y CONFIG_PINCTRL_SUN9I_A80=y CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y @@ -1650,58 +2401,77 @@ CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y CONFIG_GPIO_DEVRES=y CONFIG_OF_GPIO=y +CONFIG_GPIOLIB_IRQCHIP=y # CONFIG_DEBUG_GPIO is not set CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_GENERIC=m # -# Memory mapped GPIO drivers: +# Memory mapped GPIO drivers # -# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_74XX_MMIO is not set +CONFIG_GPIO_ALTERA=m # CONFIG_GPIO_DWAPB is not set # CONFIG_GPIO_EM is not set -# CONFIG_GPIO_ZEVIO is not set -# CONFIG_GPIO_SCH311X is not set +# CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_SCH311X is not set +CONFIG_GPIO_SYSCON=m +# CONFIG_GPIO_ZEVIO is not set # -# I2C GPIO expanders: +# I2C GPIO expanders # +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set # CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set # CONFIG_GPIO_SX150X is not set -# CONFIG_GPIO_ADP5588 is not set -# CONFIG_GPIO_ADNP is not set # -# PCI GPIO expanders: +# MFD GPIO expanders # +# CONFIG_GPIO_UCB1400 is not set # -# SPI GPIO expanders: +# SPI GPIO expanders # +# CONFIG_GPIO_74X164 is not set # CONFIG_GPIO_MAX7301 is not set # CONFIG_GPIO_MCP23S08 is not set # CONFIG_GPIO_MC33880 is not set -# CONFIG_GPIO_74X164 is not set # -# AC97 GPIO expanders: +# USB GPIO expanders # +CONFIG_W1=m # -# LPC GPIO expanders: +# 1-wire Bus Masters # +# CONFIG_W1_MASTER_DS2490 is not set +# CONFIG_W1_MASTER_DS2482 is not set +# CONFIG_W1_MASTER_DS1WM is not set +# CONFIG_W1_MASTER_GPIO is not set # -# MODULbus GPIO expanders: +# 1-wire Slaves # - -# -# USB GPIO expanders: -# -# CONFIG_W1 is not set +# CONFIG_W1_SLAVE_THERM is not set +# CONFIG_W1_SLAVE_SMEM is not set +# CONFIG_W1_SLAVE_DS2408 is not set +# CONFIG_W1_SLAVE_DS2413 is not set +# CONFIG_W1_SLAVE_DS2406 is not set +# CONFIG_W1_SLAVE_DS2423 is not set +# CONFIG_W1_SLAVE_DS2431 is not set +# CONFIG_W1_SLAVE_DS2433 is not set +# CONFIG_W1_SLAVE_DS2760 is not set +# CONFIG_W1_SLAVE_DS2780 is not set +# CONFIG_W1_SLAVE_DS2781 is not set +# CONFIG_W1_SLAVE_DS28E04 is not set +# CONFIG_W1_SLAVE_BQ27000 is not set CONFIG_POWER_SUPPLY=y # CONFIG_POWER_SUPPLY_DEBUG is not set # CONFIG_PDA_POWER is not set @@ -1719,19 +2489,175 @@ CONFIG_POWER_SUPPLY=y # CONFIG_CHARGER_MANAGER is not set # CONFIG_CHARGER_BQ2415X is not set # CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24257 is not set # CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_BQ25890 is not set # CONFIG_CHARGER_SMB347 is not set +CONFIG_BATTERY_GAUGE_LTC2941=m +CONFIG_BATTERY_RT5033=m +# CONFIG_CHARGER_RT9455 is not set CONFIG_POWER_RESET=y # CONFIG_POWER_RESET_BRCMSTB is not set # CONFIG_POWER_RESET_GPIO is not set # CONFIG_POWER_RESET_GPIO_RESTART is not set # CONFIG_POWER_RESET_LTC2952 is not set # CONFIG_POWER_RESET_RESTART is not set -CONFIG_POWER_RESET_SUN6I=y +CONFIG_POWER_RESET_VERSATILE=y # CONFIG_POWER_RESET_SYSCON is not set +CONFIG_POWER_RESET_SYSCON_POWEROFF=y # CONFIG_POWER_AVS is not set -# CONFIG_HWMON is not set -# CONFIG_THERMAL is not set +CONFIG_HWMON=y +CONFIG_HWMON_VID=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +CONFIG_SENSORS_AD7314=m +CONFIG_SENSORS_AD7414=m +CONFIG_SENSORS_AD7418=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1029=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ADT7X10=m +CONFIG_SENSORS_ADT7310=m +CONFIG_SENSORS_ADT7410=m +CONFIG_SENSORS_ADT7411=m +CONFIG_SENSORS_ADT7462=m +CONFIG_SENSORS_ADT7470=m +CONFIG_SENSORS_ADT7475=m +CONFIG_SENSORS_ASC7621=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS620=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_F71882FG=m +CONFIG_SENSORS_F75375S=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_G760A=m +CONFIG_SENSORS_G762=m +CONFIG_SENSORS_GPIO_FAN=m +CONFIG_SENSORS_HIH6130=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_JC42=m +CONFIG_SENSORS_POWR1220=m +CONFIG_SENSORS_LINEAGE=m +CONFIG_SENSORS_LTC2945=m +CONFIG_SENSORS_LTC4151=m +CONFIG_SENSORS_LTC4215=m +CONFIG_SENSORS_LTC4222=m +CONFIG_SENSORS_LTC4245=m +CONFIG_SENSORS_LTC4260=m +CONFIG_SENSORS_LTC4261=m +CONFIG_SENSORS_MAX1111=m +CONFIG_SENSORS_MAX16065=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_MAX1668=m +CONFIG_SENSORS_MAX197=m +CONFIG_SENSORS_MAX6639=m +CONFIG_SENSORS_MAX6642=m +CONFIG_SENSORS_MAX6650=m +CONFIG_SENSORS_MAX6697=m +CONFIG_SENSORS_HTU21=m +CONFIG_SENSORS_MCP3021=m +CONFIG_SENSORS_ADCXX=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM70=m +CONFIG_SENSORS_LM73=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_LM93=m +CONFIG_SENSORS_LM95234=m +CONFIG_SENSORS_LM95241=m +CONFIG_SENSORS_LM95245=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_PC87427=m +CONFIG_SENSORS_NTC_THERMISTOR=m +CONFIG_SENSORS_NCT6683=m +CONFIG_SENSORS_NCT6775=m +CONFIG_SENSORS_NCT7802=m +CONFIG_SENSORS_NCT7904=m +CONFIG_SENSORS_PCF8591=m +CONFIG_PMBUS=m +CONFIG_SENSORS_PMBUS=m +# CONFIG_SENSORS_ADM1275 is not set +# CONFIG_SENSORS_LM25066 is not set +# CONFIG_SENSORS_LTC2978 is not set +# CONFIG_SENSORS_MAX16064 is not set +# CONFIG_SENSORS_MAX34440 is not set +# CONFIG_SENSORS_MAX8688 is not set +# CONFIG_SENSORS_TPS40422 is not set +# CONFIG_SENSORS_UCD9000 is not set +# CONFIG_SENSORS_UCD9200 is not set +# CONFIG_SENSORS_ZL6100 is not set +CONFIG_SENSORS_SHT15=m +CONFIG_SENSORS_SHT21=m +CONFIG_SENSORS_SHTC1=m +CONFIG_SENSORS_DME1737=m +CONFIG_SENSORS_EMC1403=m +CONFIG_SENSORS_EMC2103=m +CONFIG_SENSORS_EMC6W201=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_SCH56XX_COMMON=m +CONFIG_SENSORS_SCH5627=m +CONFIG_SENSORS_SCH5636=m +CONFIG_SENSORS_SMM665=m +CONFIG_SENSORS_ADC128D818=m +CONFIG_SENSORS_ADS1015=m +CONFIG_SENSORS_ADS7828=m +CONFIG_SENSORS_ADS7871=m +CONFIG_SENSORS_AMC6821=m +CONFIG_SENSORS_INA209=m +CONFIG_SENSORS_INA2XX=m +CONFIG_SENSORS_TC74=m +CONFIG_SENSORS_THMC50=m +CONFIG_SENSORS_TMP102=m +CONFIG_SENSORS_TMP103=m +CONFIG_SENSORS_TMP401=m +CONFIG_SENSORS_TMP421=m +CONFIG_SENSORS_VT1211=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83793=m +# CONFIG_SENSORS_W83795 is not set +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83L786NG=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +# CONFIG_THERMAL_WRITABLE_TRIPS is not set +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_GOV_FAIR_SHARE is not set +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_BANG_BANG is not set +# CONFIG_THERMAL_GOV_USER_SPACE is not set +# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set +# CONFIG_CPU_THERMAL is not set +# CONFIG_CLOCK_THERMAL is not set +# CONFIG_THERMAL_EMULATION is not set + +# +# Texas Instruments thermal drivers +# CONFIG_WATCHDOG=y CONFIG_WATCHDOG_CORE=y # CONFIG_WATCHDOG_NOWAYOUT is not set @@ -1757,13 +2683,24 @@ CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -# CONFIG_SSB is not set +CONFIG_SSB=m +CONFIG_SSB_BLOCKIO=y +CONFIG_SSB_SDIOHOST_POSSIBLE=y +# CONFIG_SSB_SDIOHOST is not set +# CONFIG_SSB_SILENT is not set +# CONFIG_SSB_DEBUG is not set +# CONFIG_SSB_DRIVER_GPIO is not set CONFIG_BCMA_POSSIBLE=y # # Broadcom specific AMBA # -# CONFIG_BCMA is not set +CONFIG_BCMA=m +CONFIG_BCMA_BLOCKIO=y +# CONFIG_BCMA_HOST_SOC is not set +# CONFIG_BCMA_DRIVER_GMAC_CMN is not set +# CONFIG_BCMA_DRIVER_GPIO is not set +# CONFIG_BCMA_DEBUG is not set # # Multifunction device drivers @@ -1773,6 +2710,7 @@ CONFIG_MFD_CORE=y # CONFIG_MFD_AS3722 is not set # CONFIG_PMIC_ADP5520 is not set # CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_ATMEL_HLCDC is not set # CONFIG_MFD_BCM590XX is not set CONFIG_MFD_AXP20X=y # CONFIG_MFD_CROS_EC is not set @@ -1782,6 +2720,8 @@ CONFIG_MFD_AXP20X=y # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set # CONFIG_MFD_DA9063 is not set +CONFIG_MFD_DA9150=m +# CONFIG_MFD_DLN2 is not set # CONFIG_MFD_MC13XXX_SPI is not set # CONFIG_MFD_MC13XXX_I2C is not set # CONFIG_MFD_HI6421_PMIC is not set @@ -1796,16 +2736,20 @@ CONFIG_MFD_AXP20X=y # CONFIG_MFD_MAX14577 is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +CONFIG_MFD_MT6397=m # CONFIG_MFD_MENF21BMC is not set # CONFIG_EZX_PCAP is not set # CONFIG_MFD_VIPERBOARD is not set # CONFIG_MFD_RETU is not set # CONFIG_MFD_PCF50633 is not set +CONFIG_UCB1400_CORE=m # CONFIG_MFD_PM8921_CORE is not set +CONFIG_MFD_RT5033=m # CONFIG_MFD_RTSX_USB is not set # CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_RK808 is not set @@ -1813,11 +2757,12 @@ CONFIG_MFD_AXP20X=y # CONFIG_MFD_SEC_CORE is not set # CONFIG_MFD_SI476X_CORE is not set # CONFIG_MFD_SM501 is not set +CONFIG_MFD_SKY81452=m # CONFIG_MFD_SMSC is not set # CONFIG_ABX500_CORE is not set # CONFIG_MFD_STMPE is not set CONFIG_MFD_SUN6I_PRCM=y -# CONFIG_MFD_SYSCON is not set +CONFIG_MFD_SYSCON=y # CONFIG_MFD_TI_AM335X_TSCADC is not set # CONFIG_MFD_LP3943 is not set # CONFIG_MFD_LP8788 is not set @@ -1836,7 +2781,7 @@ CONFIG_MFD_SUN6I_PRCM=y # CONFIG_MFD_TPS80031 is not set # CONFIG_TWL4030_CORE is not set # CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_WL1273_CORE is not set +CONFIG_MFD_WL1273_CORE=m # CONFIG_MFD_LM3533 is not set # CONFIG_MFD_TC3589X is not set # CONFIG_MFD_TMIO is not set @@ -1857,7 +2802,8 @@ CONFIG_REGULATOR_VIRTUAL_CONSUMER=y # CONFIG_REGULATOR_USERSPACE_CONSUMER is not set # CONFIG_REGULATOR_ACT8865 is not set # CONFIG_REGULATOR_AD5398 is not set -# CONFIG_REGULATOR_AXP20X is not set +CONFIG_REGULATOR_ANATOP=m +CONFIG_REGULATOR_AXP20X=y # CONFIG_REGULATOR_DA9210 is not set # CONFIG_REGULATOR_DA9211 is not set # CONFIG_REGULATOR_FAN53555 is not set @@ -1874,45 +2820,619 @@ CONFIG_REGULATOR_GPIO=y # CONFIG_REGULATOR_MAX8660 is not set # CONFIG_REGULATOR_MAX8952 is not set # CONFIG_REGULATOR_MAX8973 is not set +CONFIG_REGULATOR_MT6397=m # CONFIG_REGULATOR_PFUZE100 is not set +CONFIG_REGULATOR_RT5033=m +CONFIG_REGULATOR_SKY81452=m # CONFIG_REGULATOR_TPS51632 is not set # CONFIG_REGULATOR_TPS62360 is not set # CONFIG_REGULATOR_TPS65023 is not set # CONFIG_REGULATOR_TPS6507X is not set # CONFIG_REGULATOR_TPS6524X is not set -# CONFIG_MEDIA_SUPPORT is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_SDR_SUPPORT=y +CONFIG_MEDIA_RC_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_FIXED_MINOR_RANGES=y +CONFIG_VIDEO_TUNER=m +CONFIG_V4L2_MEM2MEM_DEV=m +CONFIG_V4L2_FLASH_LED_CLASS=m +CONFIG_VIDEOBUF_GEN=m +CONFIG_VIDEOBUF_VMALLOC=m +CONFIG_VIDEOBUF_DVB=m +CONFIG_VIDEOBUF2_CORE=m +CONFIG_VIDEOBUF2_MEMOPS=m +CONFIG_VIDEOBUF2_VMALLOC=m +CONFIG_DVB_CORE=y +CONFIG_DVB_NET=y +CONFIG_TTPCI_EEPROM=m +CONFIG_DVB_MAX_ADAPTERS=8 +CONFIG_DVB_DYNAMIC_MINORS=y + +# +# Media drivers +# +CONFIG_RC_CORE=y +CONFIG_RC_MAP=y +CONFIG_RC_DECODERS=y +CONFIG_LIRC=m +CONFIG_IR_LIRC_CODEC=m +CONFIG_IR_NEC_DECODER=y +CONFIG_IR_RC5_DECODER=y +CONFIG_IR_RC6_DECODER=y +CONFIG_IR_JVC_DECODER=y +CONFIG_IR_SONY_DECODER=y +CONFIG_IR_SANYO_DECODER=y +CONFIG_IR_SHARP_DECODER=y +CONFIG_IR_MCE_KBD_DECODER=y +CONFIG_IR_XMP_DECODER=y +CONFIG_RC_DEVICES=y +# CONFIG_RC_ATI_REMOTE is not set +# CONFIG_IR_HIX5HD2 is not set +# CONFIG_IR_IMON is not set +# CONFIG_IR_MCEUSB is not set +# CONFIG_IR_REDRAT3 is not set +# CONFIG_IR_STREAMZAP is not set +# CONFIG_IR_IGORPLUGUSB is not set +# CONFIG_IR_IGUANA is not set +# CONFIG_IR_TTUSBIR is not set +# CONFIG_RC_LOOPBACK is not set +# CONFIG_IR_GPIO_CIR is not set +CONFIG_IR_SUNXI=m +CONFIG_MEDIA_USB_SUPPORT=y + +# +# Webcam devices +# +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=m +# CONFIG_USB_M5602 is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_DTCS033 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_JL2005BCD is not set +# CONFIG_USB_GSPCA_KINECT is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SE401 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SPCA1528 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STK1135 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TOPRO is not set +# CONFIG_USB_GSPCA_TOUPTEK is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_USB_PWC is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +# CONFIG_VIDEO_USBTV is not set + +# +# Analog TV USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_PVRUSB2_DVB=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_STK1160_COMMON=m +# CONFIG_VIDEO_STK1160_AC97 is not set +CONFIG_VIDEO_STK1160=m +# CONFIG_VIDEO_GO7007 is not set + +# +# Analog/digital TV USB devices +# +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_AU0828_V4L2=y +# CONFIG_VIDEO_AU0828_RC is not set +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_RC=y +CONFIG_VIDEO_CX231XX_ALSA=m +CONFIG_VIDEO_CX231XX_DVB=m +CONFIG_VIDEO_TM6000=m +CONFIG_VIDEO_TM6000_ALSA=m +CONFIG_VIDEO_TM6000_DVB=m + +# +# Digital TV USB devices +# +CONFIG_DVB_USB=m +CONFIG_DVB_USB_DEBUG=y +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_PCTV452E=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_CINERGY_T2=m +CONFIG_DVB_USB_DTV5100=m +CONFIG_DVB_USB_FRIIO=m +CONFIG_DVB_USB_AZ6027=m +CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_USB_V2=y +CONFIG_DVB_USB_AF9015=m +CONFIG_DVB_USB_AF9035=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_AZ6007=m +CONFIG_DVB_USB_CE6230=m +CONFIG_DVB_USB_EC168=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_LME2510=m +CONFIG_DVB_USB_MXL111SF=m +CONFIG_DVB_USB_RTL28XXU=m +CONFIG_DVB_USB_DVBSKY=m +CONFIG_SMS_USB_DRV=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG=y +CONFIG_DVB_AS102=m + +# +# Webcam, TV (analog/digital) USB devices +# +# CONFIG_VIDEO_EM28XX is not set + +# +# Software defined radio USB devices +# +CONFIG_USB_AIRSPY=m +CONFIG_USB_HACKRF=m +CONFIG_USB_MSI2500=m +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_SOC_CAMERA=m +# CONFIG_SOC_CAMERA_PLATFORM is not set +# CONFIG_VIDEO_XILINX is not set +CONFIG_V4L_MEM2MEM_DRIVERS=y +# CONFIG_VIDEO_SH_VEU is not set +CONFIG_V4L_TEST_DRIVERS=y +CONFIG_VIDEO_VIVID=m +CONFIG_VIDEO_VIM2M=m + +# +# Supported MMC/SDIO adapters +# +CONFIG_SMS_SDIO_DRV=m +CONFIG_RADIO_ADAPTERS=y +CONFIG_RADIO_TEA575X=m +CONFIG_RADIO_SI470X=y +CONFIG_USB_SI470X=m +CONFIG_I2C_SI470X=m +CONFIG_RADIO_SI4713=m +CONFIG_USB_SI4713=m +CONFIG_PLATFORM_SI4713=m +CONFIG_I2C_SI4713=m +CONFIG_USB_MR800=m +CONFIG_USB_DSBR=m +CONFIG_RADIO_SHARK=m +CONFIG_RADIO_SHARK2=m +CONFIG_USB_KEENE=m +CONFIG_USB_RAREMONO=m +CONFIG_USB_MA901=m +CONFIG_RADIO_TEA5764=m +CONFIG_RADIO_SAA7706H=m +CONFIG_RADIO_TEF6862=m +CONFIG_RADIO_WL1273=m + +# +# Texas Instruments WL128x FM driver (ST based) +# +CONFIG_MEDIA_COMMON_OPTIONS=y + +# +# common driver options +# +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_DEBUG=y +CONFIG_SMS_SIANO_MDTV=m +CONFIG_SMS_SIANO_RC=y +CONFIG_SMS_SIANO_DEBUGFS=y + +# +# Media ancillary drivers (tuners, sensors, i2c, frontends) +# +# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set +CONFIG_MEDIA_ATTACH=y +CONFIG_VIDEO_IR_I2C=y + +# +# Encoders, decoders, sensors and other helper chips +# + +# +# Audio decoders, processors and mixers +# +CONFIG_VIDEO_TVAUDIO=m +CONFIG_VIDEO_TDA7432=m +CONFIG_VIDEO_TDA9840=m +CONFIG_VIDEO_TEA6415C=m +CONFIG_VIDEO_TEA6420=m +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS5345=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_UDA1342=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_VP27SMPX=m +CONFIG_VIDEO_SONY_BTF_MPX=m + +# +# RDS decoders +# +CONFIG_VIDEO_SAA6588=m + +# +# Video decoders +# +CONFIG_VIDEO_ADV7180=m +CONFIG_VIDEO_ADV7183=m +CONFIG_VIDEO_ADV7604=m +CONFIG_VIDEO_ADV7842=m +CONFIG_VIDEO_BT819=m +CONFIG_VIDEO_BT856=m +CONFIG_VIDEO_BT866=m +CONFIG_VIDEO_KS0127=m +CONFIG_VIDEO_ML86V7667=m +CONFIG_VIDEO_SAA7110=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_TVP514X=m +CONFIG_VIDEO_TVP5150=m +CONFIG_VIDEO_TVP7002=m +CONFIG_VIDEO_TW2804=m +CONFIG_VIDEO_TW9903=m +CONFIG_VIDEO_TW9906=m +CONFIG_VIDEO_VPX3220=m + +# +# Video and audio decoders +# +CONFIG_VIDEO_SAA717X=m +CONFIG_VIDEO_CX25840=m + +# +# Video encoders +# +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_SAA7185=m +CONFIG_VIDEO_ADV7170=m +CONFIG_VIDEO_ADV7175=m +CONFIG_VIDEO_ADV7343=m +CONFIG_VIDEO_ADV7393=m +CONFIG_VIDEO_ADV7511=m +CONFIG_VIDEO_AD9389B=m +CONFIG_VIDEO_AK881X=m +CONFIG_VIDEO_THS8200=m + +# +# Camera sensor devices +# +# CONFIG_VIDEO_OV2659 is not set +# CONFIG_VIDEO_OV7640 is not set +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_OV9650 is not set +# CONFIG_VIDEO_VS6624 is not set +# CONFIG_VIDEO_MT9M032 is not set +# CONFIG_VIDEO_MT9P031 is not set +# CONFIG_VIDEO_MT9T001 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_MT9V032 is not set +# CONFIG_VIDEO_SR030PC30 is not set +# CONFIG_VIDEO_NOON010PC30 is not set +# CONFIG_VIDEO_M5MOLS is not set +# CONFIG_VIDEO_S5K6AA is not set +# CONFIG_VIDEO_S5K6A3 is not set +# CONFIG_VIDEO_S5K4ECGX is not set +# CONFIG_VIDEO_S5K5BAF is not set +# CONFIG_VIDEO_SMIAPP is not set +# CONFIG_VIDEO_S5C73M3 is not set + +# +# Flash devices +# +CONFIG_VIDEO_ADP1653=m +CONFIG_VIDEO_AS3645A=m +CONFIG_VIDEO_LM3560=m +CONFIG_VIDEO_LM3646=m + +# +# Video improvement chips +# +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# Audio/Video compression chips +# +CONFIG_VIDEO_SAA6752HS=m + +# +# Miscellaneous helper chips +# +CONFIG_VIDEO_THS7303=m +CONFIG_VIDEO_M52790=m + +# +# Sensors used on soc_camera driver +# + +# +# soc_camera sensor drivers +# +# CONFIG_SOC_CAMERA_IMX074 is not set +# CONFIG_SOC_CAMERA_MT9M001 is not set +# CONFIG_SOC_CAMERA_MT9M111 is not set +# CONFIG_SOC_CAMERA_MT9T031 is not set +# CONFIG_SOC_CAMERA_MT9T112 is not set +# CONFIG_SOC_CAMERA_MT9V022 is not set +# CONFIG_SOC_CAMERA_OV2640 is not set +# CONFIG_SOC_CAMERA_OV5642 is not set +# CONFIG_SOC_CAMERA_OV6650 is not set +# CONFIG_SOC_CAMERA_OV772X is not set +# CONFIG_SOC_CAMERA_OV9640 is not set +# CONFIG_SOC_CAMERA_OV9740 is not set +# CONFIG_SOC_CAMERA_RJ54N1 is not set +# CONFIG_SOC_CAMERA_TW9910 is not set +CONFIG_MEDIA_TUNER=y + +# +# Customize TV tuners +# +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA827X=y +CONFIG_MEDIA_TUNER_TDA18271=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +CONFIG_MEDIA_TUNER_MSI001=m +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT2063=m +CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_MT2131=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_XC4000=y +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_MEDIA_TUNER_MXL5007T=m +CONFIG_MEDIA_TUNER_MC44S803=y +CONFIG_MEDIA_TUNER_MAX2165=m +CONFIG_MEDIA_TUNER_TDA18218=m +CONFIG_MEDIA_TUNER_FC0011=m +CONFIG_MEDIA_TUNER_FC0012=m +CONFIG_MEDIA_TUNER_FC0013=m +CONFIG_MEDIA_TUNER_TDA18212=m +CONFIG_MEDIA_TUNER_E4000=m +CONFIG_MEDIA_TUNER_FC2580=m +CONFIG_MEDIA_TUNER_M88RS6000T=m +CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_SI2157=y +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m +CONFIG_MEDIA_TUNER_MXL301RF=m +CONFIG_MEDIA_TUNER_QM1D1C0042=m + +# +# Customise DVB Frontends +# + +# +# Multistandard (satellite) frontends +# +CONFIG_DVB_STB0899=m +CONFIG_DVB_STB6100=m +CONFIG_DVB_STV090x=m +CONFIG_DVB_STV6110x=m +CONFIG_DVB_M88DS3103=y + +# +# Multistandard (cable + terrestrial) frontends +# +CONFIG_DVB_DRXK=m +CONFIG_DVB_TDA18271C2DD=m +CONFIG_DVB_SI2165=m + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_MT312=m +CONFIG_DVB_ZL10036=m +CONFIG_DVB_ZL10039=m +CONFIG_DVB_S5H1420=m +CONFIG_DVB_STV0288=m +CONFIG_DVB_STB6000=m +CONFIG_DVB_STV0299=m +CONFIG_DVB_STV6110=m +CONFIG_DVB_STV0900=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_TDA10086=m +CONFIG_DVB_TDA8261=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_TUNER_ITD1000=m +CONFIG_DVB_TUNER_CX24113=m +CONFIG_DVB_TDA826X=m +CONFIG_DVB_TUA6100=m +CONFIG_DVB_CX24116=m +CONFIG_DVB_CX24117=m +CONFIG_DVB_CX24120=m +CONFIG_DVB_SI21XX=m +CONFIG_DVB_TS2020=y +CONFIG_DVB_DS3000=m +CONFIG_DVB_MB86A16=m +CONFIG_DVB_TDA10071=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_S5H1432=m +CONFIG_DVB_DRXD=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_DIB7000M=m +CONFIG_DVB_DIB7000P=m +CONFIG_DVB_DIB9000=m +CONFIG_DVB_TDA10048=m +CONFIG_DVB_AF9013=m +CONFIG_DVB_EC100=m +CONFIG_DVB_HD29L2=m +CONFIG_DVB_STV0367=m +CONFIG_DVB_CXD2820R=m +CONFIG_DVB_RTL2830=m +CONFIG_DVB_RTL2832=m +CONFIG_DVB_RTL2832_SDR=m +CONFIG_DVB_SI2168=y +CONFIG_DVB_AS102_FE=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_TDA10023=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m +CONFIG_DVB_LGDT3305=m +CONFIG_DVB_LGDT3306A=m +CONFIG_DVB_LG2160=m +CONFIG_DVB_S5H1409=m +CONFIG_DVB_AU8522=m +CONFIG_DVB_AU8522_DTV=m +CONFIG_DVB_AU8522_V4L=m +CONFIG_DVB_S5H1411=m + +# +# ISDB-T (terrestrial) frontends +# +CONFIG_DVB_S921=m +CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m + +# +# ISDB-S (satellite) & ISDB-T (terrestrial) frontends +# +CONFIG_DVB_TC90522=m + +# +# Digital terrestrial only tuners/PLL +# +CONFIG_DVB_PLL=m +CONFIG_DVB_TUNER_DIB0070=m +CONFIG_DVB_TUNER_DIB0090=m + +# +# SEC control devices for DVB-S +# +CONFIG_DVB_DRX39XYJ=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_LNBP22=m +CONFIG_DVB_ISL6405=m +CONFIG_DVB_ISL6421=m +CONFIG_DVB_ISL6423=m +CONFIG_DVB_A8293=m +CONFIG_DVB_SP2=y +CONFIG_DVB_LGS8GL5=m +CONFIG_DVB_LGS8GXX=m +CONFIG_DVB_ATBM8830=m +CONFIG_DVB_TDA665x=m +CONFIG_DVB_IX2505V=m +CONFIG_DVB_M88RS2000=m +CONFIG_DVB_AF9033=m + +# +# Tools to develop new frontends +# +CONFIG_DVB_DUMMY_FE=m # # Graphics support # -CONFIG_FB_TFT=m -# CONFIG_FB_TFT_AGM1264K_FL is not set -CONFIG_FB_TFT_BD663474=m -CONFIG_FB_TFT_HX8340BN=m -CONFIG_FB_TFT_HX8347D=m -CONFIG_FB_TFT_HX8353D=m -CONFIG_FB_TFT_ILI9320=m -CONFIG_FB_TFT_ILI9325=m -CONFIG_FB_TFT_ILI9340=m -CONFIG_FB_TFT_ILI9341=m -CONFIG_FB_TFT_ILI9481=m -CONFIG_FB_TFT_ILI9486=m -CONFIG_FB_TFT_PCD8544=m -CONFIG_FB_TFT_RA8875=m -CONFIG_FB_TFT_S6D02A1=m -CONFIG_FB_TFT_S6D1121=m -CONFIG_FB_TFT_SSD1289=m -CONFIG_FB_TFT_SSD1306=m -CONFIG_FB_TFT_SSD1331=m -CONFIG_FB_TFT_SSD1351=m -CONFIG_FB_TFT_ST7735R=m -CONFIG_FB_TFT_TINYLCD=m -CONFIG_FB_TFT_TLS8204=m -CONFIG_FB_TFT_UC1701=m -CONFIG_FB_TFT_UPD161704=m -CONFIG_FB_TFT_WATTEROTT=m -CONFIG_FB_FLEX=m -CONFIG_FB_TFT_FBTFT_DEVICE=m # CONFIG_IMX_IPUV3_CORE is not set # @@ -1977,18 +3497,149 @@ CONFIG_BACKLIGHT_GENERIC=y # CONFIG_BACKLIGHT_ADP8860 is not set # CONFIG_BACKLIGHT_ADP8870 is not set # CONFIG_BACKLIGHT_LM3639 is not set +CONFIG_BACKLIGHT_SKY81452=m # CONFIG_BACKLIGHT_GPIO is not set # CONFIG_BACKLIGHT_LV5207LP is not set # CONFIG_BACKLIGHT_BD6107 is not set # CONFIG_VGASTATE is not set +CONFIG_HDMI=y # # Console display driver support # CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y # CONFIG_LOGO is not set -# CONFIG_SOUND is not set +CONFIG_SOUND=m +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_COMPRESS_OFFLOAD=m +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_SUPPORT_OLD_API is not set +# CONFIG_SND_PROC_FS is not set +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_VMASTER=y +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_MTS64 is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +# CONFIG_SND_PORTMAN2X4 is not set +# CONFIG_SND_AC97_POWER_SAVE is not set + +# +# HD-Audio +# +CONFIG_SND_HDA_PREALLOC_SIZE=64 +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +# CONFIG_SND_USB is not set +CONFIG_SND_SOC=m +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_DESIGNWARE_I2S is not set + +# +# SoC Audio for Freescale CPUs +# + +# +# Common SoC Audio options for Freescale CPUs: +# +# CONFIG_SND_SOC_FSL_ASRC is not set +# CONFIG_SND_SOC_FSL_SAI is not set +# CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_FSL_SPDIF is not set +# CONFIG_SND_SOC_FSL_ESAI is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set +# CONFIG_SND_SOC_QCOM is not set +# CONFIG_SND_SOC_XTFPGA_I2S is not set +CONFIG_SND_SOC_I2C_AND_SPI=m + +# +# CODEC drivers +# +# CONFIG_SND_SOC_AC97_CODEC is not set +# CONFIG_SND_SOC_ADAU1701 is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_AK4554 is not set +# CONFIG_SND_SOC_AK4642 is not set +# CONFIG_SND_SOC_AK5386 is not set +# CONFIG_SND_SOC_ALC5623 is not set +# CONFIG_SND_SOC_CS35L32 is not set +# CONFIG_SND_SOC_CS42L51_I2C is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_CS42L73 is not set +# CONFIG_SND_SOC_CS4265 is not set +# CONFIG_SND_SOC_CS4270 is not set +# CONFIG_SND_SOC_CS4271_I2C is not set +# CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_CS42XX8_I2C is not set +# CONFIG_SND_SOC_HDMI_CODEC is not set +# CONFIG_SND_SOC_ES8328 is not set +# CONFIG_SND_SOC_PCM1681 is not set +# CONFIG_SND_SOC_PCM1792A is not set +# CONFIG_SND_SOC_PCM512x_I2C is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_RT5631 is not set +# CONFIG_SND_SOC_RT5677_SPI is not set +# CONFIG_SND_SOC_SGTL5000 is not set +# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set +# CONFIG_SND_SOC_SPDIF is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM2602_I2C is not set +# CONFIG_SND_SOC_SSM4567 is not set +# CONFIG_SND_SOC_STA32X is not set +# CONFIG_SND_SOC_STA350 is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS5086 is not set +# CONFIG_SND_SOC_TAS571X is not set +# CONFIG_SND_SOC_TFA9879 is not set +# CONFIG_SND_SOC_TLV320AIC23_I2C is not set +# CONFIG_SND_SOC_TLV320AIC23_SPI is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC3X is not set +# CONFIG_SND_SOC_TS3A227E is not set +# CONFIG_SND_SOC_WM8510 is not set +# CONFIG_SND_SOC_WM8523 is not set +# CONFIG_SND_SOC_WM8580 is not set +# CONFIG_SND_SOC_WM8711 is not set +# CONFIG_SND_SOC_WM8728 is not set +# CONFIG_SND_SOC_WM8731 is not set +# CONFIG_SND_SOC_WM8737 is not set +# CONFIG_SND_SOC_WM8741 is not set +# CONFIG_SND_SOC_WM8750 is not set +# CONFIG_SND_SOC_WM8753 is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8776 is not set +# CONFIG_SND_SOC_WM8804_I2C is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_WM8903 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_TPA6130A2 is not set +CONFIG_SND_SIMPLE_CARD=m +# CONFIG_SOUND_PRIME is not set +CONFIG_AC97_BUS=m # # HID support @@ -2002,70 +3653,88 @@ CONFIG_HID_GENERIC=y # # Special HID drivers # -CONFIG_HID_A4TECH=y -# CONFIG_HID_ACRUX is not set -CONFIG_HID_APPLE=y -# CONFIG_HID_APPLEIR is not set -# CONFIG_HID_AUREAL is not set -CONFIG_HID_BELKIN=y -CONFIG_HID_CHERRY=y -CONFIG_HID_CHICONY=y -# CONFIG_HID_CP2112 is not set -CONFIG_HID_CYPRESS=y -# CONFIG_HID_DRAGONRISE is not set -# CONFIG_HID_EMS_FF is not set -# CONFIG_HID_ELECOM is not set -# CONFIG_HID_ELO is not set -CONFIG_HID_EZKEY=y -# CONFIG_HID_HOLTEK is not set -# CONFIG_HID_GT683R is not set -# CONFIG_HID_HUION is not set -# CONFIG_HID_KEYTOUCH is not set -# CONFIG_HID_KYE is not set -# CONFIG_HID_UCLOGIC is not set -# CONFIG_HID_WALTOP is not set -# CONFIG_HID_GYRATION is not set -# CONFIG_HID_ICADE is not set -# CONFIG_HID_TWINHAN is not set -CONFIG_HID_KENSINGTON=y -# CONFIG_HID_LCPOWER is not set -# CONFIG_HID_LENOVO is not set -CONFIG_HID_LOGITECH=y -# CONFIG_LOGITECH_FF is not set -# CONFIG_LOGIRUMBLEPAD2_FF is not set -# CONFIG_LOGIG940_FF is not set -# CONFIG_LOGIWHEELS_FF is not set -# CONFIG_HID_MAGICMOUSE is not set -CONFIG_HID_MICROSOFT=y -CONFIG_HID_MONTEREY=y -# CONFIG_HID_MULTITOUCH is not set -# CONFIG_HID_NTRIG is not set -# CONFIG_HID_ORTEK is not set -# CONFIG_HID_PANTHERLORD is not set -# CONFIG_HID_PENMOUNT is not set -# CONFIG_HID_PETALYNX is not set -# CONFIG_HID_PICOLCD is not set -# CONFIG_HID_PRIMAX is not set -# CONFIG_HID_ROCCAT is not set -# CONFIG_HID_SAITEK is not set -# CONFIG_HID_SAMSUNG is not set -# CONFIG_HID_SONY is not set -# CONFIG_HID_SPEEDLINK is not set -# CONFIG_HID_STEELSERIES is not set -# CONFIG_HID_SUNPLUS is not set -# CONFIG_HID_RMI is not set -# CONFIG_HID_GREENASIA is not set -# CONFIG_HID_SMARTJOYPLUS is not set -# CONFIG_HID_TIVO is not set -# CONFIG_HID_TOPSEED is not set -# CONFIG_HID_THINGM is not set -# CONFIG_HID_THRUSTMASTER is not set -# CONFIG_HID_WACOM is not set -# CONFIG_HID_WIIMOTE is not set -# CONFIG_HID_XINMO is not set -# CONFIG_HID_ZEROPLUS is not set -# CONFIG_HID_ZYDACRON is not set -# CONFIG_HID_SENSOR_HUB is not set +CONFIG_HID_A4TECH=m +CONFIG_HID_ACRUX=m +CONFIG_HID_ACRUX_FF=y +CONFIG_HID_APPLE=m +CONFIG_HID_APPLEIR=m +CONFIG_HID_AUREAL=m +CONFIG_HID_BELKIN=m +CONFIG_HID_BETOP_FF=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_PRODIKEYS=m +CONFIG_HID_CP2112=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_DRAGONRISE_FF=y +CONFIG_HID_EMS_FF=m +CONFIG_HID_ELECOM=m +CONFIG_HID_ELO=m +CONFIG_HID_EZKEY=m +CONFIG_HID_HOLTEK=m +CONFIG_HOLTEK_FF=y +CONFIG_HID_GT683R=m +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_KYE=m +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WALTOP=m +CONFIG_HID_GYRATION=m +CONFIG_HID_ICADE=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LCPOWER=m +CONFIG_HID_LENOVO=m +CONFIG_HID_LOGITECH=m +CONFIG_HID_LOGITECH_HIDPP=m +CONFIG_LOGITECH_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_LOGIG940_FF=y +CONFIG_LOGIWHEELS_FF=y +CONFIG_HID_MAGICMOUSE=m +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NTRIG=m +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_PANTHERLORD_FF=y +CONFIG_HID_PENMOUNT=m +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +CONFIG_HID_PICOLCD_FB=y +CONFIG_HID_PICOLCD_BACKLIGHT=y +CONFIG_HID_PICOLCD_LCD=y +CONFIG_HID_PICOLCD_LEDS=y +# CONFIG_HID_PICOLCD_CIR is not set +CONFIG_HID_PLANTRONICS=y +CONFIG_HID_PRIMAX=m +CONFIG_HID_ROCCAT=m +CONFIG_HID_SAITEK=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_SONY_FF=y +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_STEELSERIES=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_RMI=m +CONFIG_HID_GREENASIA=m +CONFIG_GREENASIA_FF=y +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_HID_TIVO=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_THINGM=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_THRUSTMASTER_FF=y +CONFIG_HID_WACOM=m +CONFIG_HID_WIIMOTE=m +CONFIG_HID_XINMO=m +CONFIG_HID_ZEROPLUS=m +CONFIG_ZEROPLUS_FF=y +CONFIG_HID_ZYDACRON=m +CONFIG_HID_SENSOR_HUB=m +CONFIG_HID_SENSOR_CUSTOM_SENSOR=m # # USB HID support @@ -2083,17 +3752,19 @@ CONFIG_USB_SUPPORT=y CONFIG_USB_COMMON=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB=y -# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y # # Miscellaneous USB options # CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_OTG is not set +CONFIG_USB_OTG=y # CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set # CONFIG_USB_OTG_FSM is not set -# CONFIG_USB_MON is not set +CONFIG_USB_ULPI_BUS=m +CONFIG_USB_MON=m # CONFIG_USB_WUSB_CBAF is not set # @@ -2107,23 +3778,25 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_HCD_PLATFORM=y # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set -# CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_ISP1362_HCD is not set # CONFIG_USB_FUSBH200_HCD is not set # CONFIG_USB_FOTG210_HCD is not set # CONFIG_USB_MAX3421_HCD is not set CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_HCD_PLATFORM=y +# CONFIG_USB_U132_HCD is not set # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HCD_BCMA is not set +# CONFIG_USB_HCD_SSB is not set # CONFIG_USB_HCD_TEST_MODE is not set # # USB Device Class drivers # -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_WDM is not set +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_WDM=m # CONFIG_USB_TMC is not set # @@ -2133,7 +3806,7 @@ CONFIG_USB_OHCI_HCD_PLATFORM=y # # also be needed; see USB_STORAGE Help for more info # -CONFIG_USB_STORAGE=m +CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set # CONFIG_USB_STORAGE_REALTEK is not set # CONFIG_USB_STORAGE_DATAFAB is not set @@ -2148,7 +3821,7 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_KARMA is not set # CONFIG_USB_STORAGE_CYPRESS_ATACB is not set # CONFIG_USB_STORAGE_ENE_UB6250 is not set -# CONFIG_USB_UAS is not set +CONFIG_USB_UAS=m # # USB Imaging devices @@ -2160,11 +3833,80 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_DWC3 is not set # CONFIG_USB_DWC2 is not set # CONFIG_USB_CHIPIDEA is not set +CONFIG_USB_ISP1760=m +CONFIG_USB_ISP1760_HCD=y +CONFIG_USB_ISP1760_HOST_ROLE=y # # USB port drivers # -# CONFIG_USB_SERIAL is not set +# CONFIG_USB_USS720 is not set +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_SIMPLE=m +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F81232=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7715_PARPORT=y +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MXUPORT=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_SAFE=m +# CONFIG_USB_SERIAL_SAFE_PADDED is not set +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_WWAN=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_XSENS_MT=m +CONFIG_USB_SERIAL_WISHBONE=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m +CONFIG_USB_SERIAL_DEBUG=m # # USB Miscellaneous drivers @@ -2180,7 +3922,7 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_FTDI_ELAN is not set +CONFIG_USB_FTDI_ELAN=y # CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set @@ -2190,9 +3932,11 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_EHSET_TEST_FIXTURE is not set # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_YUREX is not set -# CONFIG_USB_EZUSB_FX2 is not set +CONFIG_USB_EZUSB_FX2=m # CONFIG_USB_HSIC_USB3503 is not set # CONFIG_USB_LINK_LAYER_TEST is not set +CONFIG_USB_CHAOSKEY=m +# CONFIG_USB_ATM is not set # # USB Physical Layer drivers @@ -2228,13 +3972,18 @@ CONFIG_MMC_BLOCK_BOUNCE=y # CONFIG_MMC_USHC is not set # CONFIG_MMC_USDHI6ROL0 is not set CONFIG_MMC_SUNXI=y +CONFIG_MMC_MTK=m # CONFIG_MEMSTICK is not set CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y +CONFIG_LEDS_CLASS_FLASH=m # # LED drivers # +# CONFIG_LEDS_AAT1290 is not set +# CONFIG_LEDS_BCM6328 is not set +# CONFIG_LEDS_BCM6358 is not set # CONFIG_LEDS_LM3530 is not set # CONFIG_LEDS_LM3642 is not set # CONFIG_LEDS_PCA9532 is not set @@ -2244,6 +3993,7 @@ CONFIG_LEDS_GPIO=y # CONFIG_LEDS_LP5523 is not set # CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_LP8860 is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA963X is not set # CONFIG_LEDS_DAC124S085 is not set @@ -2251,12 +4001,16 @@ CONFIG_LEDS_GPIO=y # CONFIG_LEDS_BD2802 is not set # CONFIG_LEDS_LT3593 is not set # CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TLC591XX is not set # CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_KTD2692 is not set # # LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) # # CONFIG_LEDS_BLINKM is not set +CONFIG_LEDS_SYSCON=y +# CONFIG_LEDS_PM8941_WLED is not set # # LED Triggers @@ -2266,8 +4020,8 @@ CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_ONESHOT is not set CONFIG_LEDS_TRIGGER_HEARTBEAT=y # CONFIG_LEDS_TRIGGER_BACKLIGHT is not set -# CONFIG_LEDS_TRIGGER_CPU is not set -# CONFIG_LEDS_TRIGGER_GPIO is not set +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_GPIO=m CONFIG_LEDS_TRIGGER_DEFAULT_ON=y # @@ -2276,12 +4030,15 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y # CONFIG_LEDS_TRIGGER_TRANSIENT is not set # CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y # CONFIG_EDAC is not set CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y CONFIG_RTC_HCTOSYS=y -CONFIG_RTC_SYSTOHC=y CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_SYSTOHC_DEVICE="rtc0" # CONFIG_RTC_DEBUG is not set # @@ -2296,7 +4053,9 @@ CONFIG_RTC_INTF_DEV=y # # I2C RTC drivers # -# CONFIG_RTC_DRV_DS1307 is not set +CONFIG_RTC_DRV_ABB5ZES3=m +CONFIG_RTC_DRV_ABX80X=m +CONFIG_RTC_DRV_DS1307=m # CONFIG_RTC_DRV_DS1374 is not set # CONFIG_RTC_DRV_DS1672 is not set # CONFIG_RTC_DRV_DS3232 is not set @@ -2345,6 +4104,14 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_DS1286 is not set # CONFIG_RTC_DRV_DS1511 is not set # CONFIG_RTC_DRV_DS1553 is not set +CONFIG_RTC_DRV_DS1685_FAMILY=m +CONFIG_RTC_DRV_DS1685=y +# CONFIG_RTC_DRV_DS1689 is not set +# CONFIG_RTC_DRV_DS17285 is not set +# CONFIG_RTC_DRV_DS17485 is not set +# CONFIG_RTC_DRV_DS17885 is not set +# CONFIG_RTC_DS1685_PROC_REGS is not set +# CONFIG_RTC_DS1685_SYSFS_REGS is not set # CONFIG_RTC_DRV_DS1742 is not set # CONFIG_RTC_DRV_DS2404 is not set # CONFIG_RTC_DRV_STK17TA8 is not set @@ -2362,7 +4129,7 @@ CONFIG_RTC_INTF_DEV=y CONFIG_RTC_DRV_SUN6I=y CONFIG_RTC_DRV_SUNXI=y # CONFIG_RTC_DRV_SNVS is not set -# CONFIG_RTC_DRV_XGENE is not set +# CONFIG_RTC_DRV_MT6397 is not set # # HID Sensor RTC drivers @@ -2381,12 +4148,71 @@ CONFIG_RTC_DRV_SUNXI=y # # Microsoft Hyper-V guest support # -# CONFIG_STAGING is not set +CONFIG_STAGING=y +# CONFIG_PRISM2_USB is not set +# CONFIG_COMEDI is not set +# CONFIG_PANEL is not set +# CONFIG_RTLLIB is not set +CONFIG_R8712U=m +CONFIG_R8188EU=m +CONFIG_88EU_AP_MODE=y +# CONFIG_R8723AU is not set +# CONFIG_VT6656 is not set +# CONFIG_FT1000 is not set # -# SOC (System On Chip) specific Drivers +# Speakup console speech # -# CONFIG_SOC_TI is not set +# CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +CONFIG_STAGING_MEDIA=y +CONFIG_I2C_BCM2048=m +CONFIG_DVB_MN88472=m +CONFIG_DVB_MN88473=m +# CONFIG_LIRC_STAGING is not set + +# +# Android +# +# CONFIG_STAGING_BOARD is not set +# CONFIG_USB_WPAN_HCD is not set +# CONFIG_WIMAX_GDM72XX is not set +# CONFIG_LTE_GDM724X is not set +# CONFIG_LUSTRE_FS is not set +# CONFIG_DGAP is not set +# CONFIG_GS_FPGABOOT is not set +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set +CONFIG_FB_TFT=m +CONFIG_FB_TFT_AGM1264K_FL=m +CONFIG_FB_TFT_BD663474=m +CONFIG_FB_TFT_HX8340BN=m +CONFIG_FB_TFT_HX8347D=m +CONFIG_FB_TFT_HX8353D=m +CONFIG_FB_TFT_HX8357D=m +CONFIG_FB_TFT_ILI9163=m +CONFIG_FB_TFT_ILI9320=m +CONFIG_FB_TFT_ILI9325=m +CONFIG_FB_TFT_ILI9340=m +CONFIG_FB_TFT_ILI9341=m +CONFIG_FB_TFT_ILI9481=m +CONFIG_FB_TFT_ILI9486=m +CONFIG_FB_TFT_PCD8544=m +CONFIG_FB_TFT_RA8875=m +CONFIG_FB_TFT_S6D02A1=m +CONFIG_FB_TFT_S6D1121=m +CONFIG_FB_TFT_SSD1289=m +CONFIG_FB_TFT_SSD1306=m +CONFIG_FB_TFT_SSD1331=m +CONFIG_FB_TFT_SSD1351=m +CONFIG_FB_TFT_ST7735R=m +CONFIG_FB_TFT_TINYLCD=m +CONFIG_FB_TFT_TLS8204=m +CONFIG_FB_TFT_UC1701=m +CONFIG_FB_TFT_UPD161704=m +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m +# CONFIG_CHROME_PLATFORMS is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_COMMON_CLK=y @@ -2396,8 +4222,10 @@ CONFIG_COMMON_CLK=y # # CONFIG_COMMON_CLK_SI5351 is not set # CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_CDCE925 is not set +CONFIG_CLK_QORIQ=y # CONFIG_COMMON_CLK_PXA is not set -# CONFIG_COMMON_CLK_QCOM is not set +# CONFIG_COMMON_CLK_CDCE706 is not set # # Hardware Spinlock drivers @@ -2412,12 +4240,12 @@ CONFIG_SUN4I_TIMER=y CONFIG_SUN5I_HSTIMER=y CONFIG_ARM_ARCH_TIMER=y CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_TIMER_SP804 is not set # CONFIG_ATMEL_PIT is not set # CONFIG_SH_TIMER_CMT is not set # CONFIG_SH_TIMER_MTU2 is not set # CONFIG_SH_TIMER_TMU is not set # CONFIG_EM_TIMER_STI is not set -# CONFIG_CLKSRC_VERSATILE is not set # CONFIG_MAILBOX is not set # CONFIG_IOMMU_SUPPORT is not set @@ -2433,8 +4261,18 @@ CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y # # SOC (System On Chip) specific Drivers # +CONFIG_SUNXI_SRAM=y +CONFIG_SOC_TI=y # CONFIG_PM_DEVFREQ is not set -# CONFIG_EXTCON is not set +CONFIG_EXTCON=m + +# +# Extcon Device Drivers +# +CONFIG_EXTCON_GPIO=m +CONFIG_EXTCON_RT8973A=m +CONFIG_EXTCON_SM5502=m +CONFIG_EXTCON_USB_GPIO=m # CONFIG_MEMORY is not set # CONFIG_IIO is not set # CONFIG_PWM is not set @@ -2449,11 +4287,25 @@ CONFIG_RESET_CONTROLLER=y # PHY Subsystem # CONFIG_GENERIC_PHY=y +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set # CONFIG_BCM_KONA_USB2_PHY is not set -CONFIG_PHY_SUN4I_USB=y +CONFIG_PHY_SUN4I_USB=m +CONFIG_PHY_SUN9I_USB=y +# CONFIG_PHY_TUSB1210 is not set # CONFIG_POWERCAP is not set # CONFIG_MCB is not set +# +# Android +# +# CONFIG_ANDROID is not set + +# +# Firmware Drivers +# +# CONFIG_FIRMWARE_MEMMAP is not set + # # File systems # @@ -2462,15 +4314,29 @@ CONFIG_DCACHE_WORD_ACCESS=y # CONFIG_EXT3_FS is not set CONFIG_EXT4_FS=y CONFIG_EXT4_USE_FOR_EXT23=y -# CONFIG_EXT4_FS_POSIX_ACL is not set -# CONFIG_EXT4_FS_SECURITY is not set +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_ENCRYPTION=y +CONFIG_EXT4_FS_ENCRYPTION=y # CONFIG_EXT4_DEBUG is not set CONFIG_JBD2=y # CONFIG_JBD2_DEBUG is not set CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set +CONFIG_REISERFS_FS=y +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +# CONFIG_REISERFS_FS_XATTR is not set +CONFIG_JFS_FS=y +CONFIG_JFS_POSIX_ACL=y +# CONFIG_JFS_SECURITY is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_XFS_FS=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +# CONFIG_XFS_WARN is not set +# CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y CONFIG_BTRFS_FS_POSIX_ACL=y @@ -2479,17 +4345,27 @@ CONFIG_BTRFS_FS_POSIX_ACL=y # CONFIG_BTRFS_DEBUG is not set # CONFIG_BTRFS_ASSERT is not set # CONFIG_NILFS2_FS is not set +CONFIG_F2FS_FS=y +CONFIG_F2FS_STAT_FS=y +CONFIG_F2FS_FS_XATTR=y +CONFIG_F2FS_FS_POSIX_ACL=y +# CONFIG_F2FS_FS_SECURITY is not set +# CONFIG_F2FS_CHECK_FS is not set +# CONFIG_F2FS_FS_ENCRYPTION is not set CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y CONFIG_INOTIFY_USER=y CONFIG_FANOTIFY=y # CONFIG_QUOTA is not set -# CONFIG_QUOTACTL is not set +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_QUOTACTL=y CONFIG_AUTOFS4_FS=y CONFIG_FUSE_FS=y -# CONFIG_OVERLAYFS_FS is not set +CONFIG_CUSE=m +CONFIG_OVERLAY_FS=m # # Caches @@ -2499,18 +4375,23 @@ CONFIG_FUSE_FS=y # # CD-ROM/DVD Filesystems # -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +# CONFIG_ZISOFS is not set +CONFIG_UDF_FS=y +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems # CONFIG_FAT_FS=y -# CONFIG_MSDOS_FS is not set +CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_CODEPAGE=437 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y # # Pseudo filesystems @@ -2518,22 +4399,25 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_PROC_SYSCTL=y CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_PROC_CHILDREN is not set CONFIG_KERNFS=y CONFIG_SYSFS=y CONFIG_TMPFS=y -# CONFIG_TMPFS_POSIX_ACL is not set -# CONFIG_TMPFS_XATTR is not set +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y # CONFIG_HUGETLB_PAGE is not set # CONFIG_CONFIGFS_FS is not set CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_ECRYPT_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set +CONFIG_HFS_FS=y +CONFIG_HFSPLUS_FS=y +CONFIG_HFSPLUS_FS_POSIX_ACL=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set # CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set CONFIG_SQUASHFS=y @@ -2544,6 +4428,7 @@ CONFIG_SQUASHFS_DECOMP_MULTI=y # CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set CONFIG_SQUASHFS_XATTR=y CONFIG_SQUASHFS_ZLIB=y +# CONFIG_SQUASHFS_LZ4 is not set CONFIG_SQUASHFS_LZO=y CONFIG_SQUASHFS_XZ=y CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y @@ -2559,19 +4444,24 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_PSTORE is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set -# CONFIG_F2FS_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y CONFIG_NFS_V3=y CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y -# CONFIG_NFS_SWAP is not set +CONFIG_NFS_SWAP=y # CONFIG_NFS_V4_1 is not set CONFIG_ROOT_NFS=y # CONFIG_NFS_USE_LEGACY_DNS is not set CONFIG_NFS_USE_KERNEL_DNS=y -# CONFIG_NFSD is not set +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +# CONFIG_NFSD_PNFS is not set +# CONFIG_NFSD_FAULT_INJECTION is not set CONFIG_GRACE_PERIOD=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y @@ -2579,9 +4469,21 @@ CONFIG_NFS_ACL_SUPPORT=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y +CONFIG_SUNRPC_SWAP=y +CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_SUNRPC_DEBUG is not set # CONFIG_CEPH_FS is not set -# CONFIG_CIFS is not set +CONFIG_CIFS=y +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +# CONFIG_CIFS_UPCALL is not set +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_CIFS_ACL=y +CONFIG_CIFS_DEBUG=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_DFS_UPCALL is not set +# CONFIG_CIFS_SMB2 is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set @@ -2635,7 +4537,7 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_MAC_INUIT is not set # CONFIG_NLS_MAC_ROMANIAN is not set # CONFIG_NLS_MAC_TURKISH is not set -# CONFIG_NLS_UTF8 is not set +CONFIG_NLS_UTF8=y # # Kernel hacking @@ -2659,6 +4561,7 @@ CONFIG_FRAME_WARN=1024 # CONFIG_STRIP_ASM_SYMS is not set # CONFIG_READABLE_ASM is not set # CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_SECTION_MISMATCH is not set @@ -2669,6 +4572,7 @@ CONFIG_DEBUG_KERNEL=y # # Memory Debugging # +# CONFIG_PAGE_EXTENSION is not set # CONFIG_DEBUG_PAGEALLOC is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_SLUB_DEBUG_ON is not set @@ -2677,7 +4581,7 @@ CONFIG_HAVE_DEBUG_KMEMLEAK=y # CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_VM is not set -CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_PER_CPU_MAPS is not set # CONFIG_DEBUG_HIGHMEM is not set # CONFIG_DEBUG_SHIRQ is not set @@ -2691,8 +4595,10 @@ CONFIG_DEBUG_MEMORY_INIT=y CONFIG_PANIC_ON_OOPS_VALUE=0 CONFIG_PANIC_TIMEOUT=0 CONFIG_SCHED_DEBUG=y +CONFIG_SCHED_INFO=y # CONFIG_SCHEDSTATS is not set # CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set # CONFIG_TIMER_STATS is not set # @@ -2720,12 +4626,14 @@ CONFIG_DEBUG_BUGVERBOSE=y # # RCU Debugging # +# CONFIG_PROVE_RCU is not set # CONFIG_SPARSE_RCU_POINTER is not set # CONFIG_TORTURE_TEST is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_RCU_CPU_STALL_TIMEOUT=21 -# CONFIG_RCU_CPU_STALL_INFO is not set +CONFIG_RCU_CPU_STALL_INFO=y # CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set @@ -2748,6 +4656,8 @@ CONFIG_TRACING_SUPPORT=y # CONFIG_INTERVAL_TREE_TEST is not set # CONFIG_PERCPU_TEST is not set # CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_ASYNC_RAID6_TEST is not set +CONFIG_TEST_HEXDUMP=m # CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set # CONFIG_TEST_RHASHTABLE is not set @@ -2757,6 +4667,7 @@ CONFIG_TRACING_SUPPORT=y # CONFIG_TEST_BPF is not set # CONFIG_TEST_FIRMWARE is not set # CONFIG_TEST_UDELAY is not set +# CONFIG_MEMTEST is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set @@ -2774,7 +4685,6 @@ CONFIG_DEBUG_SUNXI_UART0=y # CONFIG_DEBUG_LL_UART_8250 is not set # CONFIG_DEBUG_LL_UART_PL01X is not set CONFIG_DEBUG_LL_INCLUDE="debug/8250.S" -# CONFIG_DEBUG_UART_PL01X is not set CONFIG_DEBUG_UART_8250=y # CONFIG_DEBUG_UART_BCM63XX is not set CONFIG_DEBUG_UART_PHYS=0x01c28000 @@ -2787,6 +4697,7 @@ CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" # CONFIG_EARLY_PRINTK is not set # CONFIG_PID_IN_CONTEXTIDR is not set # CONFIG_DEBUG_SET_MODULE_RONX is not set +# CONFIG_CORESIGHT is not set # # Security options @@ -2794,14 +4705,18 @@ CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" CONFIG_KEYS=y # CONFIG_PERSISTENT_KEYRINGS is not set # CONFIG_BIG_KEYS is not set -# CONFIG_ENCRYPTED_KEYS is not set -# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +CONFIG_ENCRYPTED_KEYS=y # CONFIG_SECURITY_DMESG_RESTRICT is not set # CONFIG_SECURITY is not set # CONFIG_SECURITYFS is not set CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" CONFIG_XOR_BLOCKS=y +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_ASYNC_PQ=m +CONFIG_ASYNC_RAID6_RECOV=m CONFIG_CRYPTO=y # @@ -2817,13 +4732,16 @@ CONFIG_CRYPTO_HASH=y CONFIG_CRYPTO_HASH2=y CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_AKCIPHER2=y +# CONFIG_CRYPTO_RSA is not set CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_MANAGER2=y # CONFIG_CRYPTO_USER is not set CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y -# CONFIG_CRYPTO_GF128MUL is not set -# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y # CONFIG_CRYPTO_PCRYPT is not set CONFIG_CRYPTO_WORKQUEUE=y # CONFIG_CRYPTO_CRYPTD is not set @@ -2835,24 +4753,26 @@ CONFIG_CRYPTO_AUTHENC=y # Authenticated Encryption with Associated Data # CONFIG_CRYPTO_CCM=m -# CONFIG_CRYPTO_GCM is not set -CONFIG_CRYPTO_SEQIV=m +CONFIG_CRYPTO_GCM=m +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_ECHAINIV=m # # Block modes # CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_CTR=m -# CONFIG_CRYPTO_CTS is not set -CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_CTS=y +CONFIG_CRYPTO_ECB=y # CONFIG_CRYPTO_LRW is not set CONFIG_CRYPTO_PCBC=m -# CONFIG_CRYPTO_XTS is not set +CONFIG_CRYPTO_XTS=y # # Hash modes # -# CONFIG_CRYPTO_CMAC is not set +CONFIG_CRYPTO_CMAC=y CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -2863,8 +4783,9 @@ CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_CRC32C=y # CONFIG_CRYPTO_CRC32 is not set # CONFIG_CRYPTO_CRCT10DIF is not set -# CONFIG_CRYPTO_GHASH is not set -# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_GHASH=m +# CONFIG_CRYPTO_POLY1305 is not set +CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_MICHAEL_MIC is not set # CONFIG_CRYPTO_RMD128 is not set @@ -2872,8 +4793,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y -# CONFIG_CRYPTO_SHA1_ARM is not set -CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set # CONFIG_CRYPTO_WP512 is not set @@ -2882,9 +4802,8 @@ CONFIG_CRYPTO_SHA256=m # Ciphers # CONFIG_CRYPTO_AES=y -# CONFIG_CRYPTO_AES_ARM is not set # CONFIG_CRYPTO_ANUBIS is not set -CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAST5 is not set @@ -2893,6 +4812,7 @@ CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_FCRYPT=m # CONFIG_CRYPTO_KHAZAD is not set # CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_CHACHA20 is not set # CONFIG_CRYPTO_SEED is not set # CONFIG_CRYPTO_SERPENT is not set # CONFIG_CRYPTO_TEA is not set @@ -2903,7 +4823,8 @@ CONFIG_CRYPTO_FCRYPT=m # CONFIG_CRYPTO_DEFLATE=y # CONFIG_CRYPTO_ZLIB is not set -# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_842 is not set # CONFIG_CRYPTO_LZ4 is not set # CONFIG_CRYPTO_LZ4HC is not set @@ -2911,11 +4832,24 @@ CONFIG_CRYPTO_DEFLATE=y # Random Number Generation # CONFIG_CRYPTO_ANSI_CPRNG=y -# CONFIG_CRYPTO_DRBG_MENU is not set +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_DRBG_HMAC=y +# CONFIG_CRYPTO_DRBG_HASH is not set +# CONFIG_CRYPTO_DRBG_CTR is not set +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_USER_API=m # CONFIG_CRYPTO_USER_API_HASH is not set # CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_USER_API_RNG=m +# CONFIG_CRYPTO_USER_API_AEAD is not set CONFIG_CRYPTO_HW=y # CONFIG_ASYMMETRIC_KEY_TYPE is not set +CONFIG_ARM_CRYPTO=y +# CONFIG_CRYPTO_SHA1_ARM is not set +CONFIG_CRYPTO_SHA256_ARM=m +# CONFIG_CRYPTO_SHA512_ARM is not set +# CONFIG_CRYPTO_AES_ARM is not set # CONFIG_BINARY_PRINTF is not set # @@ -2923,16 +4857,18 @@ CONFIG_CRYPTO_HW=y # CONFIG_RAID6_PQ=y CONFIG_BITREVERSE=y +CONFIG_HAVE_ARCH_BITREVERSE=y CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GENERIC_NET_UTILS=y CONFIG_GENERIC_PCI_IOMAP=y CONFIG_GENERIC_IO=y +CONFIG_PERCPU_RWSEM=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y -CONFIG_CRC_CCITT=m +CONFIG_CRC_CCITT=y CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set -# CONFIG_CRC_ITU_T is not set +CONFIG_CRC_ITU_T=y CONFIG_CRC32=y # CONFIG_CRC32_SELFTEST is not set CONFIG_CRC32_SLICEBY8=y @@ -2940,7 +4876,7 @@ CONFIG_CRC32_SLICEBY8=y # CONFIG_CRC32_SARWATE is not set # CONFIG_CRC32_BIT is not set # CONFIG_CRC7 is not set -CONFIG_LIBCRC32C=m +CONFIG_LIBCRC32C=y # CONFIG_CRC8 is not set # CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set # CONFIG_RANDOM32_SELFTEST is not set @@ -2948,6 +4884,7 @@ CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y CONFIG_LZO_COMPRESS=y CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_COMPRESS=m CONFIG_LZ4_DECOMPRESS=y CONFIG_XZ_DEC=y CONFIG_XZ_DEC_X86=y @@ -2984,5 +4921,9 @@ CONFIG_AVERAGE=y # CONFIG_DDR is not set CONFIG_LIBFDT=y CONFIG_OID_REGISTRY=y +CONFIG_FONT_SUPPORT=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y CONFIG_ARCH_HAS_SG_CHAIN=y -# CONFIG_VIRTUALIZATION is not set +CONFIG_VIRTUALIZATION=y diff --git a/config/linux-sunxi.config b/config/linux-sunxi.config index be7e6b9cf..e8c7dba82 100644 --- a/config/linux-sunxi.config +++ b/config/linux-sunxi.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 3.4.105 Kernel Configuration +# Linux/arm 3.4.110 Kernel Configuration # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -161,7 +161,6 @@ CONFIG_SLUB_DEBUG=y # CONFIG_SLAB is not set CONFIG_SLUB=y # CONFIG_PROFILING is not set -CONFIG_TRACEPOINTS=y CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set CONFIG_JUMP_LABEL=y @@ -945,7 +944,49 @@ CONFIG_LLC=m # CONFIG_WAN_ROUTER is not set # CONFIG_PHONET is not set # CONFIG_IEEE802154 is not set -# CONFIG_NET_SCHED is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=y +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_CHOKE=m +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_PLUG=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_CLS_CGROUP is not set +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_SCH_FIFO=y # CONFIG_DCB is not set CONFIG_DNS_RESOLVER=y CONFIG_BATMAN_ADV=m @@ -963,7 +1004,6 @@ CONFIG_HAVE_BPF_JIT=y # Network testing # CONFIG_NET_PKTGEN=m -# CONFIG_NET_DROP_MONITOR is not set # CONFIG_HAMRADIO is not set # CONFIG_CAN is not set CONFIG_IRDA=m @@ -1162,7 +1202,7 @@ CONFIG_SUNXI_PWM=y # CONFIG_DS1682 is not set CONFIG_TI_DAC7512=m # CONFIG_UID_STAT is not set -# CONFIG_BMP085 is not set +CONFIG_BMP085=m # CONFIG_USB_SWITCH_FSA9480 is not set # CONFIG_WL127X_RFKILL is not set # CONFIG_C2PORT is not set @@ -1242,7 +1282,7 @@ CONFIG_SCSI_OSD_DPRINT_SENSE=1 CONFIG_ATA=y # CONFIG_ATA_NONSTANDARD is not set CONFIG_ATA_VERBOSE_ERROR=y -# CONFIG_SATA_PMP is not set +CONFIG_SATA_PMP=y # # Controllers with non-SFF native interface @@ -1341,9 +1381,11 @@ CONFIG_SUNXI_EMAC=y CONFIG_SUNXI_GMAC=y CONFIG_GMAC_SCRIPT_SYS=y CONFIG_GMAC_CLK_SYS=y +CONFIG_GMAC_FOR_BANANAPI=y CONFIG_GMAC_RING=y # CONFIG_GMAC_CHAINED is not set CONFIG_PHYLIB=y +CONFIG_SWCONFIG=y # # MII PHY device drivers @@ -1363,8 +1405,14 @@ CONFIG_PHYLIB=y # CONFIG_STE10XP is not set # CONFIG_LSI_ET1011C_PHY is not set # CONFIG_MICREL_PHY is not set -# CONFIG_FIXED_PHY is not set -# CONFIG_MDIO_BITBANG is not set +CONFIG_FIXED_PHY=y +CONFIG_MDIO_BITBANG=y +# CONFIG_MDIO_GPIO is not set +CONFIG_B53=y +CONFIG_B53_SPI_DRIVER=y +CONFIG_B53_PHY_DRIVER=y +CONFIG_B53_SRAB_DRIVER=y +CONFIG_B53_PHY_FIXUP=y CONFIG_MICREL_KS8995MA=m CONFIG_PLIP=m CONFIG_PPP=y @@ -1395,6 +1443,7 @@ CONFIG_USB_PEGASUS=m CONFIG_USB_RTL8150=m CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_AX88179_178A=m CONFIG_USB_NET_QF9700=m CONFIG_USB_NET_CDCETHER=m CONFIG_USB_NET_CDC_EEM=m @@ -1459,6 +1508,11 @@ CONFIG_BCMDHD_FW_PATH="/lib/firmware/ap6210/fw_bcmxxxx.bin" CONFIG_BCMDHD_NVRAM_PATH="/lib/firmware/ap6210/nvram_apxxxx.txt" CONFIG_BCMDHD_OOB=y # CONFIG_BCMDHD_SDIO_IRQ is not set +CONFIG_AP6210=m +CONFIG_AP6210_FW_PATH="/lib/firmware/ap6210/fw_bcmxxxx.bin" +CONFIG_AP6210_NVRAM_PATH="/lib/firmware/ap6210/nvram_apxxxx.txt" +CONFIG_AP6210_OOB=y +# CONFIG_AP6210_SDIO_IRQ is not set CONFIG_BRCMUTIL=m CONFIG_BRCMFMAC=m CONFIG_BRCMFMAC_SDIO=y @@ -1784,6 +1838,7 @@ CONFIG_PPDEV=m # CONFIG_DCC_TTY is not set # CONFIG_RAMOOPS is not set CONFIG_SUNXI_G2D=y +# CONFIG_SUNXI_PHYS_MEM_ALLOCATOR is not set CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_COMPAT=y @@ -1975,6 +2030,7 @@ CONFIG_HWMON=y # Native drivers # # CONFIG_SENSORS_MMA7660 is not set +CONFIG_SENSORS_A20_TP_HWMON=m # CONFIG_SENSORS_AD7314 is not set # CONFIG_SENSORS_AD7414 is not set # CONFIG_SENSORS_AD7418 is not set @@ -2006,7 +2062,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_LM63 is not set # CONFIG_SENSORS_LM70 is not set # CONFIG_SENSORS_LM73 is not set -# CONFIG_SENSORS_LM75 is not set +CONFIG_SENSORS_LM75=m # CONFIG_SENSORS_LM77 is not set # CONFIG_SENSORS_LM78 is not set # CONFIG_SENSORS_LM80 is not set @@ -2642,15 +2698,8 @@ CONFIG_DRM_UDL=m # CONFIG_ION is not set CONFIG_MALI=m CONFIG_MALI400=m -# CONFIG_MALI450 is not set CONFIG_MALI400_DEBUG=y -CONFIG_MALI400_PROFILING=y -# CONFIG_MALI400_INTERNAL_PROFILING is not set -# CONFIG_MALI400_UMP is not set -# CONFIG_MALI400_POWER_PERFORMANCE_POLICY is not set -CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH=y -# CONFIG_MALI_SHARED_INTERRUPTS is not set -# CONFIG_MALI_PMU_PARALLEL_POWER_UP is not set +# CONFIG_MALI400_GPU_UTILIZATION is not set CONFIG_UMP=m CONFIG_UMP_DEBUG=y # CONFIG_VGASTATE is not set @@ -2724,31 +2773,38 @@ CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y # CONFIG_LOGO is not set CONFIG_SOUND=y -# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SOUND_OSS_CORE=y +CONFIG_SOUND_OSS_CORE_PRECLAIM=y CONFIG_SND=y CONFIG_SND_TIMER=y CONFIG_SND_PCM=y CONFIG_SND_HWDEP=m CONFIG_SND_RAWMIDI=m CONFIG_SND_JACK=y -# CONFIG_SND_SEQUENCER is not set -# CONFIG_SND_MIXER_OSS is not set -# CONFIG_SND_PCM_OSS is not set +CONFIG_SND_SEQUENCER=m +# CONFIG_SND_SEQ_DUMMY is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_SEQUENCER_OSS is not set CONFIG_SND_HRTIMER=y +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y CONFIG_SND_DYNAMIC_MINORS=y CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set CONFIG_SND_VMASTER=y -# CONFIG_SND_RAWMIDI_SEQ is not set +CONFIG_SND_RAWMIDI_SEQ=m # CONFIG_SND_OPL3_LIB_SEQ is not set # CONFIG_SND_OPL4_LIB_SEQ is not set # CONFIG_SND_SBAWE_SEQ is not set # CONFIG_SND_EMU10K1_SEQ is not set CONFIG_SND_DRIVERS=y -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_ALOOP is not set +CONFIG_SND_DUMMY=m +CONFIG_SND_ALOOP=m +# CONFIG_SND_VIRMIDI is not set # CONFIG_SND_MTPAV is not set # CONFIG_SND_MTS64 is not set # CONFIG_SND_SERIAL_U16550 is not set @@ -3184,7 +3240,7 @@ CONFIG_RTC_INTF_DEV=y # # I2C RTC drivers # -# CONFIG_RTC_DRV_DS1307 is not set +CONFIG_RTC_DRV_DS1307=y # CONFIG_RTC_DRV_DS1374 is not set # CONFIG_RTC_DRV_DS1672 is not set # CONFIG_RTC_DRV_DS3232 is not set @@ -3380,7 +3436,7 @@ CONFIG_IIO=m # Light sensors # # CONFIG_SENSORS_ISL29018 is not set -# CONFIG_SENSORS_TSL2563 is not set +CONFIG_SENSORS_TSL2563=m # CONFIG_TSL2583 is not set # @@ -3408,6 +3464,9 @@ CONFIG_IIO=m # Triggers - standalone # # CONFIG_IIO_SIMPLE_DUMMY is not set +CONFIG_ZRAM=m +# CONFIG_ZRAM_DEBUG is not set +CONFIG_ZSMALLOC=m CONFIG_FB_SM7XX=m CONFIG_USB_ENESTORAGE=m CONFIG_BCM_WIMAX=m @@ -3514,7 +3573,11 @@ CONFIG_REISERFS_PROC_INFO=y CONFIG_REISERFS_FS_XATTR=y CONFIG_REISERFS_FS_POSIX_ACL=y CONFIG_REISERFS_FS_SECURITY=y -# CONFIG_JFS_FS is not set +CONFIG_JFS_FS=y +# CONFIG_JFS_POSIX_ACL is not set +# CONFIG_JFS_SECURITY is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set CONFIG_XFS_FS=y CONFIG_XFS_QUOTA=y CONFIG_XFS_POSIX_ACL=y @@ -3543,6 +3606,7 @@ CONFIG_QFMT_V2=y CONFIG_QUOTACTL=y CONFIG_AUTOFS4_FS=y CONFIG_FUSE_FS=y +CONFIG_OVERLAYFS_FS=m CONFIG_CUSE=y CONFIG_GENERIC_ACL=y @@ -3748,8 +3812,7 @@ CONFIG_STACKTRACE=y # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_HIGHMEM is not set CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_INFO=y -# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_WRITECOUNT is not set CONFIG_DEBUG_MEMORY_INIT=y @@ -3779,6 +3842,16 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_C_RECORDMCOUNT=y CONFIG_TRACING_SUPPORT=y CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set CONFIG_DYNAMIC_DEBUG=y # CONFIG_DMA_API_DEBUG is not set # CONFIG_ATOMIC64_SELFTEST is not set diff --git a/config/linux-udoo-neo.config b/config/linux-udoo-neo.config new file mode 100644 index 000000000..e9d880a81 --- /dev/null +++ b/config/linux-udoo-neo.config @@ -0,0 +1,4331 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.14.54 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_MIGHT_HAVE_PCI=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_FIQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_GENERIC_BUG=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_HAVE_KERNEL_LZ4=y +# CONFIG_KERNEL_GZIP is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_XZ is not set +CONFIG_KERNEL_LZO=y +# CONFIG_KERNEL_LZ4 is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_FHANDLE is not set +# CONFIG_AUDIT is not set + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +CONFIG_KTIME_SCALAR=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +# CONFIG_IRQ_TIME_ACCOUNTING is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set + +# +# RCU Subsystem +# +CONFIG_TREE_PREEMPT_RCU=y +CONFIG_PREEMPT_RCU=y +CONFIG_RCU_STALL_COMMON=y +# CONFIG_RCU_USER_QS is not set +CONFIG_RCU_FANOUT=32 +CONFIG_RCU_FANOUT_LEAF=16 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_RCU_FAST_NO_HZ is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_BOOST is not set +# CONFIG_RCU_NOCB_CPU is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +# CONFIG_CPUSETS is not set +# CONFIG_CGROUP_CPUACCT is not set +# CONFIG_RESOURCE_COUNTERS is not set +# CONFIG_CGROUP_PERF is not set +# CONFIG_CGROUP_SCHED is not set +# CONFIG_BLK_CGROUP is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_EXPERT=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +# CONFIG_EMBEDDED is not set +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_SYSTEM_TRUSTED_KEYRING is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_JUMP_LABEL is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR is not set +CONFIG_CC_STACKPROTECTOR_NONE=y +# CONFIG_CC_STACKPROTECTOR_REGULAR is not set +# CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_MODULE_SIG is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_CMDLINE_PARSER is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +CONFIG_ARCH_MULTIPLATFORM=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM_NODT is not set +# CONFIG_ARCH_SHMOBILE_LEGACY is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C24XX is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP1 is not set + +# +# Multiple platform selection +# + +# +# CPU Core family selection +# +# CONFIG_ARCH_MULTI_V6 is not set +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_MULTI_V6_V7=y +# CONFIG_ARCH_MULTI_CPU_AUTO is not set +# CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_BCM is not set +# CONFIG_ARCH_BERLIN is not set +CONFIG_GPIO_PCA953X=y +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_HI3xxx is not set +# CONFIG_ARCH_KEYSTONE is not set +# CONFIG_ARCH_MSM_DT is not set +CONFIG_ARCH_MXC=y + +# +# Freescale i.MX support +# +CONFIG_MXC_TZIC=y +# CONFIG_MXC_DEBUG_BOARD is not set +CONFIG_HAVE_IMX_RNG=y +CONFIG_HAVE_IMX_ANATOP=y +CONFIG_HAVE_IMX_GPC=y +CONFIG_HAVE_IMX_MMDC=y +CONFIG_HAVE_IMX_SRC=y +CONFIG_HAVE_IMX_MCC=y +CONFIG_HAVE_IMX_AMP=y +CONFIG_ARCH_MXC_IOMUX_V3=y +CONFIG_SOC_IMX5=y +CONFIG_SOC_IMX51=y + +# +# i.MX51 machines: +# +CONFIG_MACH_IMX51_DT=y +# CONFIG_MACH_MX51_BABBAGE is not set +# CONFIG_MACH_EUKREA_CPUIMX51SD is not set + +# +# Device tree only +# +# CONFIG_SOC_IMX50 is not set +# CONFIG_SOC_IMX53 is not set +CONFIG_SOC_IMX6=y +CONFIG_SOC_IMX6Q=y +CONFIG_SOC_IMX6SL=y +CONFIG_SOC_IMX6SX=y +# CONFIG_SOC_VF610 is not set +CONFIG_IMX_HAVE_PLATFORM_FEC=y +CONFIG_IMX_HAVE_PLATFORM_GPIO_KEYS=y +# CONFIG_ARCH_OMAP3 is not set +# CONFIG_ARCH_OMAP4 is not set +# CONFIG_SOC_OMAP5 is not set +# CONFIG_SOC_AM33XX is not set +# CONFIG_SOC_AM43XX is not set +# CONFIG_SOC_DRA7XX is not set +# CONFIG_ARCH_ROCKCHIP is not set +# CONFIG_ARCH_SOCFPGA is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_STI is not set +# CONFIG_ARCH_SHMOBILE_MULTI is not set +# CONFIG_ARCH_SUNXI is not set +# CONFIG_ARCH_SIRF is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_VIRT is not set +# CONFIG_ARCH_WM8850 is not set +# CONFIG_ARCH_ZYNQ is not set + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_LPAE is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_ARM_VIRT_EXT=y +# CONFIG_SWP_EMULATE is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_KUSER_HELPERS=y +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_ARM_NR_BANKS=8 +CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_ARM_ERRATA_643719 is not set +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_PL310_ERRATA_753970 is not set +CONFIG_ARM_ERRATA_754322=y +# CONFIG_ARM_ERRATA_754327 is not set +CONFIG_ARM_ERRATA_764369=y +CONFIG_PL310_ERRATA_769419=y +CONFIG_ARM_ERRATA_775420=y +# CONFIG_ARM_ERRATA_798181 is not set +# CONFIG_ARM_ERRATA_773022 is not set + +# +# Bus support +# +# CONFIG_PCI is not set +# CONFIG_PCI_SYSCALL is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_HAVE_SMP=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_ARM_CPU_TOPOLOGY=y +# CONFIG_SCHED_MC is not set +# CONFIG_SCHED_SMT is not set +CONFIG_HAVE_ARM_SCU=y +# CONFIG_HAVE_ARM_ARCH_TIMER is not set +CONFIG_HAVE_ARM_TWD=y +# CONFIG_MCPM is not set +# CONFIG_BIG_LITTLE is not set +# CONFIG_VMSPLIT_3G is not set +CONFIG_VMSPLIT_2G=y +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0x80000000 +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +# CONFIG_ARM_PSCI is not set +CONFIG_ARCH_NR_GPIO=0 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_HZ_FIXED=0 +CONFIG_HZ_100=y +# CONFIG_HZ_200 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +# CONFIG_HZ_500 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 +CONFIG_SCHED_HRTICK=y +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HW_PERF_EVENTS=y +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +CONFIG_MEMORY_ISOLATION=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_CROSS_MEMORY_ATTACH=y +# CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set +# CONFIG_ZBUD is not set +# CONFIG_ZSMALLOC is not set +CONFIG_FORCE_MAX_ZONEORDER=14 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +# CONFIG_XEN is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ATAGS=y +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +# CONFIG_ARM_APPENDED_DTB is not set +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_EXTEND is not set +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +CONFIG_AUTO_ZRELADDR=y + +# +# CPU Power Management +# + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +# CONFIG_GENERIC_CPUFREQ_CPU0 is not set + +# +# ARM CPU frequency scaling drivers +# +CONFIG_ARM_IMX6Q_CPUFREQ=y +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y + +# +# ARM CPU Idle Drivers +# +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y +CONFIG_KERNEL_MODE_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=m +CONFIG_COREDUMP=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM=y +CONFIG_PM_DEBUG=y +# CONFIG_PM_ADVANCED_DEBUG is not set +CONFIG_PM_TEST_SUSPEND=y +CONFIG_PM_SLEEP_DEBUG=y +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_HAS_OPP=y +CONFIG_PM_OPP=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +CONFIG_PM_GENERIC_DOMAINS_RUNTIME=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_CPU_PM=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +# CONFIG_IP_MULTIPLE_TABLES is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=y +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_GRE is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETLABEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK_ACCT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +CONFIG_NF_CONNTRACK=y +# CONFIG_NF_CONNTRACK_MARK is not set +CONFIG_NF_CONNTRACK_PROCFS=y +# CONFIG_NF_CONNTRACK_EVENTS is not set +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set +# CONFIG_NF_CT_PROTO_DCCP is not set +# CONFIG_NF_CT_PROTO_SCTP is not set +# CONFIG_NF_CT_PROTO_UDPLITE is not set +# CONFIG_NF_CONNTRACK_AMANDA is not set +# CONFIG_NF_CONNTRACK_FTP is not set +# CONFIG_NF_CONNTRACK_H323 is not set +# CONFIG_NF_CONNTRACK_IRC is not set +# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set +# CONFIG_NF_CONNTRACK_SNMP is not set +# CONFIG_NF_CONNTRACK_PPTP is not set +# CONFIG_NF_CONNTRACK_SANE is not set +# CONFIG_NF_CONNTRACK_SIP is not set +# CONFIG_NF_CONNTRACK_TFTP is not set +# CONFIG_NF_CT_NETLINK is not set +# CONFIG_NF_CT_NETLINK_TIMEOUT is not set +# CONFIG_NF_TABLES is not set +CONFIG_NETFILTER_XTABLES=y + +# +# Xtables combined modules +# +# CONFIG_NETFILTER_XT_MARK is not set +# CONFIG_NETFILTER_XT_CONNMARK is not set + +# +# Xtables targets +# +# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set +# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set +# CONFIG_NETFILTER_XT_TARGET_HMARK is not set +# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set +# CONFIG_NETFILTER_XT_TARGET_LED is not set +# CONFIG_NETFILTER_XT_TARGET_LOG is not set +# CONFIG_NETFILTER_XT_TARGET_MARK is not set +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_TEE is not set +# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set + +# +# Xtables matches +# +# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_BPF is not set +# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set +# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set +# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set +# CONFIG_NETFILTER_XT_MATCH_CPU is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +# CONFIG_NETFILTER_XT_MATCH_ECN is not set +# CONFIG_NETFILTER_XT_MATCH_ESP is not set +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_HELPER is not set +# CONFIG_NETFILTER_XT_MATCH_HL is not set +# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set +# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_MAC is not set +# CONFIG_NETFILTER_XT_MATCH_MARK is not set +# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set +# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +# CONFIG_NETFILTER_XT_MATCH_POLICY is not set +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set +# CONFIG_NETFILTER_XT_MATCH_STATE is not set +# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +CONFIG_IP_NF_IPTABLES=y +# CONFIG_IP_NF_MATCH_AH is not set +# CONFIG_IP_NF_MATCH_ECN is not set +# CONFIG_IP_NF_MATCH_TTL is not set +CONFIG_IP_NF_FILTER=y +# CONFIG_IP_NF_TARGET_REJECT is not set +# CONFIG_IP_NF_TARGET_SYNPROXY is not set +# CONFIG_IP_NF_TARGET_ULOG is not set +# CONFIG_NF_NAT_IPV4 is not set +# CONFIG_IP_NF_MANGLE is not set +# CONFIG_IP_NF_RAW is not set +# CONFIG_IP_NF_SECURITY is not set +# CONFIG_IP_NF_ARPTABLES is not set + +# +# IPv6: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV6 is not set +# CONFIG_NF_CONNTRACK_IPV6 is not set +# CONFIG_IP6_NF_IPTABLES is not set +# CONFIG_BRIDGE_NF_EBTABLES is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +CONFIG_STP=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_HAVE_NET_DSA=y +CONFIG_VLAN_8021Q=m +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_VLAN_8021Q_MVRP is not set +# CONFIG_DECNET is not set +CONFIG_LLC=m +CONFIG_LLC2=m +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +CONFIG_6LOWPAN_IPHC=m +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +CONFIG_BATMAN_ADV=m +CONFIG_BATMAN_ADV_BLA=y +# CONFIG_BATMAN_ADV_DAT is not set +# CONFIG_BATMAN_ADV_NC is not set +# CONFIG_BATMAN_ADV_DEBUG is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_NET_MPLS_GSO is not set +# CONFIG_HSR is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +# CONFIG_CGROUP_NET_PRIO is not set +# CONFIG_CGROUP_NET_CLASSID is not set +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_JIT is not set +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +CONFIG_CAN=m +CONFIG_CAN_RAW=m +CONFIG_CAN_BCM=m +CONFIG_CAN_GW=m + +# +# CAN Device Drivers +# +# CONFIG_CAN_VCAN is not set +# CONFIG_CAN_SLCAN is not set +CONFIG_CAN_DEV=m +CONFIG_CAN_CALC_BITTIMING=y +# CONFIG_CAN_LEDS is not set +# CONFIG_CAN_AT91 is not set +# CONFIG_CAN_TI_HECC is not set +# CONFIG_CAN_MCP251X is not set +CONFIG_CAN_FLEXCAN=m +# CONFIG_CAN_GRCAN is not set +CONFIG_CAN_M_CAN=m +# CONFIG_CAN_SJA1000 is not set +# CONFIG_CAN_C_CAN is not set +# CONFIG_CAN_CC770 is not set + +# +# CAN USB interfaces +# +# CONFIG_CAN_EMS_USB is not set +# CONFIG_CAN_ESD_USB2 is not set +# CONFIG_CAN_KVASER_USB is not set +# CONFIG_CAN_PEAK_USB is not set +# CONFIG_CAN_8DEV_USB is not set +# CONFIG_CAN_SOFTING is not set +# CONFIG_CAN_DEBUG_DEVICES is not set +# CONFIG_IRDA is not set +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTSDIO=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_ATH3K=y +# CONFIG_BT_HCIUART_LL is not set +# CONFIG_BT_HCIUART_3WIRE is not set +CONFIG_BT_HCIBCM203X=m +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_MRVL is not set +CONFIG_BT_ATH3K=m +CONFIG_BT_WILINK=m +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +CONFIG_CFG80211=m +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +# CONFIG_CFG80211_WEXT is not set +# CONFIG_LIB80211 is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_HAS_RC=y +# CONFIG_MAC80211_RC_PID is not set +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +# CONFIG_MAC80211_MESH is not set +# CONFIG_MAC80211_LEDS is not set +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_MESSAGE_TRACING is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set +CONFIG_RFKILL=m +CONFIG_RFKILL_LEDS=y +CONFIG_RFKILL_INPUT=y +CONFIG_RFKILL_REGULATOR=m +CONFIG_RFKILL_GPIO=m +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +CONFIG_HAVE_BPF_JIT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FW_LOADER_USER_HELPER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_SOC_BUS=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_IRQ=y +CONFIG_DMA_SHARED_BUFFER=y +CONFIG_DMA_CMA=y + +# +# Default contiguous memory area size: +# +CONFIG_CMA_SIZE_MBYTES=320 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 +CONFIG_CMA_AREAS=7 + +# +# Bus devices +# +CONFIG_IMX_WEIM=y +# CONFIG_ARM_CCI is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_DATAFLASH=y +# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set +# CONFIG_MTD_DATAFLASH_OTP is not set +CONFIG_MTD_M25P80=y +CONFIG_MTD_SST25L=y +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_DENALI is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_DOCG4 is not set +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_GPMI_NAND=m +# CONFIG_MTD_NAND_PLATFORM is not set +CONFIG_MTD_NAND_MXC=y +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +CONFIG_MTD_SPI_NOR=y +CONFIG_SPI_FSL_QUADSPI=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_LIMIT=20 +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +CONFIG_PROC_DEVICETREE=y +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set + +# +# Misc devices +# +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ATMEL_SSC is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +CONFIG_SRAM=y +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set + +# +# Texas Instruments shared transport line discipline +# +CONFIG_TI_ST=m +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_PROC_FS is not set + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_AHCI_IMX=y +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# +# CONFIG_SATA_MV is not set + +# +# PATA SFF controllers with BMDMA +# +CONFIG_PATA_IMX=y + +# +# PIO-only SFF controllers +# +# CONFIG_PATA_PLATFORM is not set + +# +# Generic fallback / legacy drivers +# +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +CONFIG_MII=y +CONFIG_NET_CORE=y +CONFIG_BONDING=m +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_NLMON is not set + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_ARC=y +# CONFIG_ARC_EMAC is not set +CONFIG_NET_CADENCE=y +# CONFIG_ARM_AT91_ETHER is not set +# CONFIG_MACB is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +CONFIG_NET_VENDOR_CIRRUS=y +CONFIG_CS89x0=y +CONFIG_CS89x0_PLATFORM=y +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +# CONFIG_NET_VENDOR_FARADAY is not set +CONFIG_NET_VENDOR_FREESCALE=y +CONFIG_FEC=y +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_ETHOC is not set +# CONFIG_SH_ETH is not set +# CONFIG_NET_VENDOR_SEEQ is not set +CONFIG_NET_VENDOR_SMSC=y +CONFIG_SMC91X=y +CONFIG_SMC911X=y +CONFIG_SMSC911X=y +# CONFIG_SMSC911X_ARCH_HOOKS is not set +# CONFIG_NET_VENDOR_STMICRO is not set +CONFIG_NET_VENDOR_VIA=y +# CONFIG_VIA_VELOCITY is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_AT803X_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_AX88179_178A=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_CDC_NCM=m +# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set +# CONFIG_USB_NET_CDC_MBIM is not set +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SR9700 is not set +# CONFIG_USB_NET_SR9800 is not set +# CONFIG_USB_NET_SMSC75XX is not set +# CONFIG_USB_NET_SMSC95XX is not set +# CONFIG_USB_NET_GL620A is not set +CONFIG_USB_NET_NET1080=m +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +CONFIG_USB_NET_CDC_SUBSET=m +# CONFIG_USB_ALI_M5632 is not set +# CONFIG_USB_AN2720 is not set +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +# CONFIG_USB_EPSON2888 is not set +# CONFIG_USB_KC2190 is not set +CONFIG_USB_NET_ZAURUS=m +# CONFIG_USB_NET_CX82310_ETH is not set +# CONFIG_USB_NET_KALMIA is not set +# CONFIG_USB_NET_QMI_WWAN is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_USB_SIERRA_NET is not set +# CONFIG_USB_VL600 is not set +CONFIG_WLAN=y +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_AT76C50X_USB is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8187 is not set +# CONFIG_MAC80211_HWSIM is not set +CONFIG_ATH_CARDS=m +# CONFIG_ATH_DEBUG is not set +# CONFIG_ATH9K is not set +# CONFIG_ATH9K_HTC is not set +# CONFIG_CARL9170 is not set +CONFIG_ATH6KL=m +CONFIG_ATH6KL_SDIO=m +# CONFIG_ATH6KL_USB is not set +# CONFIG_ATH6KL_DEBUG is not set +# CONFIG_AR5523 is not set +# CONFIG_ATH10K is not set +# CONFIG_WCN36XX is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +CONFIG_BRCMUTIL=m +# CONFIG_BRCMSMAC is not set +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_SDIO=y +# CONFIG_BRCMFMAC_USB is not set +# CONFIG_BRCM_TRACING is not set +# CONFIG_BRCMDBG is not set +# CONFIG_HOSTAP is not set +# CONFIG_LIBERTAS is not set +# CONFIG_P54_COMMON is not set +# CONFIG_RT2X00 is not set +CONFIG_RTL_CARDS=m +# CONFIG_RTL8192CU is not set +# CONFIG_WL_TI is not set +# CONFIG_ZD1211RW is not set +# CONFIG_MWIFIEX is not set +# CONFIG_CW1200 is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_FF_MEMLESS=m +CONFIG_INPUT_POLLDEV=y +# CONFIG_INPUT_SPARSEKMAP is not set +CONFIG_INPUT_MATRIXKMAP=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_EVBUG=m + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +CONFIG_KEYBOARD_SNVS_PWRKEY=y +CONFIG_KEYBOARD_IMX=y +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_STMPE is not set +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_CYPRESS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +CONFIG_MOUSE_PS2_ELANTECH=y +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +CONFIG_TOUCHSCREEN_DA9052=m +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +CONFIG_TOUCHSCREEN_EGALAX=m +CONFIG_TOUCHSCREEN_ELAN=m +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +CONFIG_TOUCHSCREEN_MAX11801=m +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_TOUCHSCREEN_MC13783=m +CONFIG_TOUCHSCREEN_USB_EGALAX=y +CONFIG_TOUCHSCREEN_USB_PANJIT=y +CONFIG_TOUCHSCREEN_USB_3M=y +CONFIG_TOUCHSCREEN_USB_ITM=y +CONFIG_TOUCHSCREEN_USB_ETURBO=y +CONFIG_TOUCHSCREEN_USB_GUNZE=y +CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y +CONFIG_TOUCHSCREEN_USB_IRTOUCH=y +CONFIG_TOUCHSCREEN_USB_IDEALTEK=y +CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y +CONFIG_TOUCHSCREEN_USB_GOTOP=y +CONFIG_TOUCHSCREEN_USB_JASTEC=y +CONFIG_TOUCHSCREEN_USB_ELO=y +CONFIG_TOUCHSCREEN_USB_E2I=y +CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y +CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y +CONFIG_TOUCHSCREEN_USB_NEXIO=y +CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +CONFIG_TOUCHSCREEN_TSC2007=m +# CONFIG_TOUCHSCREEN_W90X900 is not set +CONFIG_TOUCHSCREEN_ST1232=y +CONFIG_TOUCHSCREEN_STMPE=m +# CONFIG_TOUCHSCREEN_SUR40 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_MC13783_PWRBUTTON is not set +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_MPU3050 is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +CONFIG_INPUT_UINPUT=y +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +CONFIG_INPUT_DA9052_ONKEY=m +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_ISL29023 is not set +CONFIG_INPUT_FXAS2100X=m +CONFIG_INPUT_FXOS8700=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=m +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_SERIO_OLPC_APSP is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +# CONFIG_SERIAL_SH_SCI is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +CONFIG_SERIAL_FSL_LPUART=y +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y +# CONFIG_SERIAL_ST_ASC is not set +# CONFIG_TTY_PRINTK is not set +CONFIG_FSL_OTP=y +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_HW_RANDOM_ATMEL is not set +# CONFIG_HW_RANDOM_IMX_RNG is not set +# CONFIG_HW_RANDOM_EXYNOS is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_IMX_SEMA4=y +CONFIG_IMX_MCC_TEST=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +# CONFIG_I2C_COMPAT is not set +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +# CONFIG_I2C_HELPER_AUTO is not set +# CONFIG_I2C_SMBUS is not set + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_GPIO is not set +CONFIG_I2C_IMX=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_GPIO is not set +CONFIG_SPI_IMX=y +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_HSI is not set + +# +# PPS support +# +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_PINCTRL=y + +# +# Pin controllers +# +CONFIG_PINMUX=y +CONFIG_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_CAPRI is not set +CONFIG_PINCTRL_IMX=y +CONFIG_PINCTRL_IMX51=y +CONFIG_PINCTRL_IMX6Q=y +CONFIG_PINCTRL_IMX6SL=y +CONFIG_PINCTRL_IMX6SX=y +# CONFIG_PINCTRL_MSM8X74 is not set +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_GENERIC=y +# CONFIG_GPIO_DA9052 is not set + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_EM is not set +CONFIG_GPIO_MXC=y +# CONFIG_GPIO_RCAR is not set +# CONFIG_GPIO_SCH311X is not set +# CONFIG_GPIO_TS5500 is not set +# CONFIG_GPIO_GRGPIO is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X_IRQ is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_STMPE is not set +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# LPC GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_GPIO_BCM_KONA is not set + +# +# USB GPIO expanders: +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +# CONFIG_W1_MASTER_DS2490 is not set +# CONFIG_W1_MASTER_DS2482 is not set +# CONFIG_W1_MASTER_MXC is not set +# CONFIG_W1_MASTER_DS1WM is not set +# CONFIG_W1_MASTER_GPIO is not set + +# +# 1-wire Slaves +# +# CONFIG_W1_SLAVE_THERM is not set +# CONFIG_W1_SLAVE_SMEM is not set +# CONFIG_W1_SLAVE_DS2408 is not set +# CONFIG_W1_SLAVE_DS2413 is not set +# CONFIG_W1_SLAVE_DS2423 is not set +# CONFIG_W1_SLAVE_DS2431 is not set +# CONFIG_W1_SLAVE_DS2433 is not set +# CONFIG_W1_SLAVE_DS2760 is not set +# CONFIG_W1_SLAVE_DS2780 is not set +# CONFIG_W1_SLAVE_DS2781 is not set +# CONFIG_W1_SLAVE_DS28E04 is not set +# CONFIG_W1_SLAVE_BQ27000 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_GENERIC_ADC_BATTERY is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_DA9052 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +CONFIG_SABRESD_MAX8903=m +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_IMX6_USB_CHARGER is not set +# CONFIG_POWER_RESET is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_AVS is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_DA9052_ADC is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_HTU21 is not set +# CONFIG_SENSORS_IIO_HWMON is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +CONFIG_SENSORS_LM75=m +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +CONFIG_SENSORS_MAX17135=y +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_MC13783_ADC is not set +CONFIG_SENSORS_MAG3110=y +CONFIG_MXC_MMA8451=y +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_GOV_FAIR_SHARE is not set +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_USER_SPACE is not set +CONFIG_CPU_THERMAL=y +# CONFIG_THERMAL_EMULATION is not set +CONFIG_IMX_THERMAL=y +CONFIG_DEVICE_THERMAL=y + +# +# Texas Instruments thermal drivers +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_CORE is not set +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_DA9052_WATCHDOG is not set +# CONFIG_GPIO_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set +CONFIG_IMX2_WDT=y +# CONFIG_MEN_A21_WDT is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_PMIC_DA903X is not set +CONFIG_PMIC_DA9052=y +# CONFIG_MFD_DA9052_SPI is not set +CONFIG_MFD_DA9052_I2C=y +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9063 is not set +CONFIG_MFD_MXC_HDMI=y +# CONFIG_MFD_MXC_HDMI_ANDROID is not set +CONFIG_MFD_MC13XXX=y +CONFIG_MFD_MC13XXX_SPI=y +CONFIG_MFD_MC13XXX_I2C=y +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +CONFIG_MFD_MAX17135=y +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_SEC_CORE is not set +CONFIG_MFD_SI476X_CORE=y +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +CONFIG_MFD_STMPE=y + +# +# STMicroelectronics STMPE Interface Drivers +# +CONFIG_STMPE_I2C=y +# CONFIG_STMPE_SPI is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_VEXPRESS_CONFIG is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +CONFIG_REGULATOR_ANATOP=y +CONFIG_REGULATOR_DA9052=y +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_REGULATOR_GPIO is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_MAX1586 is not set +CONFIG_REGULATOR_MAX17135=y +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +CONFIG_REGULATOR_MC13XXX_CORE=y +CONFIG_REGULATOR_MC13783=y +CONFIG_REGULATOR_MC13892=y +CONFIG_REGULATOR_PFUZE100=y +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_RC_SUPPORT=y +# CONFIG_MEDIA_CONTROLLER is not set +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_V4L2_MEM2MEM_DEV=y +CONFIG_VIDEOBUF_GEN=y +CONFIG_VIDEOBUF_DMA_CONTIG=y +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_DMA_CONTIG=y +CONFIG_VIDEOBUF2_VMALLOC=m +# CONFIG_TTPCI_EEPROM is not set + +# +# Media drivers +# +CONFIG_RC_CORE=y +CONFIG_RC_MAP=y +CONFIG_RC_DECODERS=y +# CONFIG_LIRC is not set +CONFIG_IR_NEC_DECODER=y +CONFIG_IR_RC5_DECODER=y +CONFIG_IR_RC6_DECODER=y +CONFIG_IR_JVC_DECODER=y +CONFIG_IR_SONY_DECODER=y +CONFIG_IR_RC5_SZ_DECODER=y +CONFIG_IR_SANYO_DECODER=y +CONFIG_IR_MCE_KBD_DECODER=y +CONFIG_RC_DEVICES=y +# CONFIG_RC_ATI_REMOTE is not set +# CONFIG_IR_IMON is not set +# CONFIG_IR_MCEUSB is not set +# CONFIG_IR_REDRAT3 is not set +# CONFIG_IR_STREAMZAP is not set +# CONFIG_IR_IGUANA is not set +# CONFIG_IR_TTUSBIR is not set +# CONFIG_RC_LOOPBACK is not set +CONFIG_IR_GPIO_CIR=y +CONFIG_MEDIA_USB_SUPPORT=y + +# +# Webcam devices +# +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=m +# CONFIG_USB_M5602 is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_JL2005BCD is not set +# CONFIG_USB_GSPCA_KINECT is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SE401 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SPCA1528 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STK1135 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TOPRO is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_USB_PWC is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +# CONFIG_VIDEO_USBTV is not set + +# +# Webcam, TV (analog/digital) USB devices +# +# CONFIG_VIDEO_EM28XX is not set +CONFIG_V4L_PLATFORM_DRIVERS=y +# CONFIG_VIDEO_TIMBERDALE is not set +CONFIG_VIDEO_MXC_OUTPUT=y +CONFIG_VIDEO_MXC_CAPTURE=m +CONFIG_VIDEO_V4L2_MXC_INT_DEVICE=m + +# +# MXC Camera/V4L2 PRP Features support +# +CONFIG_VIDEO_MXC_IPU_CAMERA=y +# CONFIG_MXC_CAMERA_OV5640 is not set +# CONFIG_MXC_CAMERA_OV5642 is not set +# CONFIG_MXC_CAMERA_OV5640_MIPI is not set +# CONFIG_MXC_TVIN_ADV7180 is not set +CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m +CONFIG_MXC_IPU_PRP_ENC=m +CONFIG_MXC_IPU_CSI_ENC=m +CONFIG_VIDEO_MXC_IPU_OUTPUT=y +CONFIG_VIDEO_MXC_PXP_V4L2=y +CONFIG_VIDEO_MXC_CSI_CAMERA=m +CONFIG_MXC_VADC=m +CONFIG_SOC_CAMERA=y +# CONFIG_SOC_CAMERA_PLATFORM is not set +CONFIG_VIDEO_MX3=y +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set +# CONFIG_VIDEO_SH_MOBILE_CEU is not set +CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_CODA=y +# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set +# CONFIG_VIDEO_SH_VEU is not set +# CONFIG_V4L_TEST_DRIVERS is not set + +# +# Supported MMC/SDIO adapters +# +CONFIG_RADIO_ADAPTERS=y +# CONFIG_RADIO_SI470X is not set +# CONFIG_RADIO_SI4713 is not set +CONFIG_RADIO_SI476X=y +# CONFIG_USB_MR800 is not set +# CONFIG_USB_DSBR is not set +# CONFIG_RADIO_SHARK is not set +# CONFIG_RADIO_SHARK2 is not set +# CONFIG_USB_KEENE is not set +# CONFIG_USB_RAREMONO is not set +# CONFIG_USB_MA901 is not set +# CONFIG_RADIO_TEA5764 is not set +# CONFIG_RADIO_SAA7706H is not set +# CONFIG_RADIO_TEF6862 is not set +# CONFIG_RADIO_WL1273 is not set + +# +# Texas Instruments WL128x FM driver (ST based) +# +CONFIG_RADIO_WL128X=m +# CONFIG_CYPRESS_FIRMWARE is not set + +# +# Media ancillary drivers (tuners, sensors, i2c, frontends) +# +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y +CONFIG_VIDEO_IR_I2C=y + +# +# Audio decoders, processors and mixers +# + +# +# RDS decoders +# + +# +# Video decoders +# + +# +# Video and audio decoders +# + +# +# Video encoders +# + +# +# Camera sensor devices +# + +# +# Flash devices +# + +# +# Video improvement chips +# + +# +# Audio/Video compression chips +# + +# +# Miscellaneous helper chips +# + +# +# Sensors used on soc_camera driver +# + +# +# soc_camera sensor drivers +# +# CONFIG_SOC_CAMERA_IMX074 is not set +# CONFIG_SOC_CAMERA_MT9M001 is not set +# CONFIG_SOC_CAMERA_MT9M111 is not set +# CONFIG_SOC_CAMERA_MT9T031 is not set +# CONFIG_SOC_CAMERA_MT9T112 is not set +# CONFIG_SOC_CAMERA_MT9V022 is not set +CONFIG_SOC_CAMERA_OV2640=y +# CONFIG_SOC_CAMERA_OV5642 is not set +# CONFIG_SOC_CAMERA_OV6650 is not set +# CONFIG_SOC_CAMERA_OV772X is not set +# CONFIG_SOC_CAMERA_OV9640 is not set +# CONFIG_SOC_CAMERA_OV9740 is not set +# CONFIG_SOC_CAMERA_RJ54N1 is not set +# CONFIG_SOC_CAMERA_TW9910 is not set +CONFIG_MEDIA_TUNER=y +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA827X=y +CONFIG_MEDIA_TUNER_TDA18271=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_XC4000=y +CONFIG_MEDIA_TUNER_MC44S803=y + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set + +# +# Graphics support +# +CONFIG_FB_TFT=m +CONFIG_FB_TFT_AGM1264K_FL=m +CONFIG_FB_TFT_BD663474=m +CONFIG_FB_TFT_HX8340BN=m +CONFIG_FB_TFT_HX8347D=m +CONFIG_FB_TFT_HX8353D=m +CONFIG_FB_TFT_ILI9320=m +CONFIG_FB_TFT_ILI9325=m +CONFIG_FB_TFT_ILI9340=m +CONFIG_FB_TFT_ILI9341=m +CONFIG_FB_TFT_ILI9481=m +CONFIG_FB_TFT_ILI9486=m +CONFIG_FB_TFT_PCD8544=m +CONFIG_FB_TFT_RA8875=m +CONFIG_FB_TFT_S6D02A1=m +CONFIG_FB_TFT_S6D1121=m +CONFIG_FB_TFT_SSD1289=m +CONFIG_FB_TFT_SSD1306=m +CONFIG_FB_TFT_SSD1331=m +CONFIG_FB_TFT_SSD1351=m +CONFIG_FB_TFT_ST7735R=m +CONFIG_FB_TFT_TINYLCD=m +CONFIG_FB_TFT_TLS8204=m +CONFIG_FB_TFT_UC1701=m +CONFIG_FB_TFT_UPD161704=m +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m +CONFIG_DRM=y +CONFIG_DRM_VIVANTE=y +# CONFIG_DRM_EXYNOS is not set +# CONFIG_DRM_UDL is not set +# CONFIG_DRM_ARMADA is not set +# CONFIG_DRM_RCAR_DU is not set +# CONFIG_DRM_SHMOBILE is not set +# CONFIG_DRM_TILCDC is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_VIDEOMODE_HELPERS=y +CONFIG_HDMI=y +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_IMAGEBLIT=m +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=m +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +CONFIG_FB_BACKLIGHT=y +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_IMX is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_TMIO is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_GOLDFISH is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +CONFIG_FB_MX3=y +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +CONFIG_FB_MXS=y +# CONFIG_FB_SIMPLE is not set +# CONFIG_EXYNOS_VIDEO is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_LCD_L4F00242T03=y +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI922X is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +CONFIG_LCD_PLATFORM=y +# CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_LCD_AMS369FG06 is not set +# CONFIG_LCD_LMS501KF03 is not set +# CONFIG_LCD_HX8357 is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y +CONFIG_BACKLIGHT_PWM=y +# CONFIG_BACKLIGHT_DA9052 is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set +CONFIG_FB_MXC=y +CONFIG_FB_MXC_SYNC_PANEL=y +CONFIG_FB_MXC_LDB=y +CONFIG_FB_MXC_MIPI_DSI=y +CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL=y +CONFIG_FB_MXC_HDMI=y +CONFIG_FB_MXC_EDID=y +CONFIG_FB_MXC_EINK_PANEL=y +# CONFIG_FB_MXC_EINK_AUTO_UPDATE_MODE is not set +CONFIG_FB_MXS_SII902X=y +CONFIG_FB_MXC_DCIC=m +CONFIG_HANNSTAR_CABC=y +CONFIG_FB_MXS_TDA19988=y + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_FB_SSD1307 is not set +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_DMAENGINE_PCM=y +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_COMPRESS_OFFLOAD=y +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +CONFIG_SND_KCTL_JACK=y +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_HIFACE is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_DESIGNWARE_I2S is not set + +# +# SoC Audio for Freescale CPUs +# + +# +# Common SoC Audio options for Freescale CPUs: +# +CONFIG_SND_SOC_FSL_ASRC=y +CONFIG_SND_SOC_FSL_SAI=y +CONFIG_SND_SOC_FSL_SSI=y +CONFIG_SND_SOC_FSL_SPDIF=y +CONFIG_SND_SOC_FSL_ESAI=y +CONFIG_SND_SOC_FSL_UTILS=y +CONFIG_SND_SOC_FSL_HDMI=y +CONFIG_SND_SOC_IMX_PCM_DMA=y +CONFIG_SND_SOC_IMX_AUDMUX=y +CONFIG_SND_IMX_SOC=y +CONFIG_SND_SOC_IMX_SSI=y +CONFIG_SND_SOC_IMX_PCM_FIQ=y +CONFIG_SND_SOC_IMX_HDMI_DMA=y + +# +# SoC Audio support for Freescale i.MX boards: +# +CONFIG_SND_SOC_IMX_CS42888=y +CONFIG_SND_SOC_IMX_WM8962=y +# CONFIG_SND_SOC_IMX_WM8962_ANDROID is not set +CONFIG_SND_SOC_IMX_SGTL5000=y +CONFIG_SND_SOC_IMX_MQS=y +CONFIG_SND_SOC_IMX_SPDIF=y +CONFIG_SND_SOC_IMX_MC13783=y +CONFIG_SND_SOC_IMX_HDMI=y +CONFIG_SND_SOC_IMX_SI476X=y +CONFIG_SND_SOC_IMX_TDA19988=y +CONFIG_SND_SOC_I2C_AND_SPI=y +CONFIG_SND_SOC_CS42XX8=y +CONFIG_SND_SOC_CS42XX8_I2C=y +CONFIG_SND_SOC_FSL_MQS=y +CONFIG_SND_SOC_HDMI_CODEC=y +CONFIG_SND_SOC_SGTL5000=y +CONFIG_SND_SOC_SI476X=y +CONFIG_SND_SOC_WM8962=y +CONFIG_SND_SOC_MC13783=y +CONFIG_SND_SOC_TDA19988_CODEC=y +# CONFIG_SND_SIMPLE_CARD is not set +# CONFIG_SOUND_PRIME is not set + +# +# HID support +# +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HIDRAW is not set +# CONFIG_UHID is not set +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_HUION is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO_TPKBD is not set +CONFIG_HID_LOGITECH=m +CONFIG_LOGITECH_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_LOGIG940_FF=y +CONFIG_LOGIWHEELS_FF=y +# CONFIG_HID_MAGICMOUSE is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +CONFIG_HID_SONY=m +CONFIG_SONY_FF=y +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THINGM is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +CONFIG_HID_WIIMOTE=m +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# I2C HID support +# +# CONFIG_I2C_HID is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_FSM is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_XHCI_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_MXC=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FUSBH200_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_IMX21_HCD is not set +# CONFIG_USB_HCD_TEST_MODE is not set +# CONFIG_USB_RENESAS_USBHS is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_DWC2 is not set +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +# CONFIG_USB_CHIPIDEA_DEBUG is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_SIMPLE is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +CONFIG_USB_SERIAL_FTDI_SIO=m +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_F81232 is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_METRO is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MXUPORT is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +CONFIG_USB_SERIAL_WWAN=m +CONFIG_USB_SERIAL_OPTION=m +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_XSENS_MT is not set +# CONFIG_USB_SERIAL_WISHBONE is not set +# CONFIG_USB_SERIAL_ZTE is not set +# CONFIG_USB_SERIAL_SSU100 is not set +# CONFIG_USB_SERIAL_QT2 is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +CONFIG_USB_EHSET_TEST_FIXTURE=m +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HSIC_USB3503 is not set + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +CONFIG_NOP_USB_XCEIV=y +# CONFIG_AM335X_PHY_USB is not set +# CONFIG_SAMSUNG_USB2PHY is not set +# CONFIG_SAMSUNG_USB3PHY is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +CONFIG_USB_MXS_PHY=y +# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_ULPI is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FSL_USB2 is not set +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_S3C_HSOTG is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=m +CONFIG_USB_F_ACM=m +CONFIG_USB_F_SS_LB=m +CONFIG_USB_U_SERIAL=m +CONFIG_USB_U_ETHER=m +CONFIG_USB_F_SERIAL=m +CONFIG_USB_F_OBEX=m +CONFIG_USB_F_NCM=m +CONFIG_USB_F_ECM=m +CONFIG_USB_F_EEM=m +CONFIG_USB_F_SUBSET=m +CONFIG_USB_F_RNDIS=m +CONFIG_USB_F_MASS_STORAGE=m +CONFIG_USB_F_FS=m +CONFIG_USB_CONFIGFS=m +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_ACM=y +CONFIG_USB_CONFIGFS_OBEX=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_ECM=y +CONFIG_USB_CONFIGFS_ECM_SUBSET=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_EEM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_LB_SS=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_ZERO=m +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_ETH_EEM is not set +CONFIG_USB_G_NCM=m +CONFIG_USB_GADGETFS=m +# CONFIG_USB_FUNCTIONFS is not set +CONFIG_USB_MASS_STORAGE=m +CONFIG_FSL_UTP=y +CONFIG_USB_G_SERIAL=m +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +CONFIG_USB_CDC_COMPOSITE=m +CONFIG_USB_G_ACM_MS=m +CONFIG_USB_G_MULTI=m +CONFIG_USB_G_MULTI_RNDIS=y +# CONFIG_USB_G_MULTI_CDC is not set +CONFIG_USB_G_HID=m +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_UNSAFE_RESUME=y +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +CONFIG_MMC_SDHCI_PLTFM=y +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +CONFIG_MMC_SDHCI_ESDHC_IMX=y +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_MXC is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set + +# +# MXC support drivers +# +CONFIG_MXC_IPU=y + +# +# MXC Vivante GPU support +# +CONFIG_MXC_GPU_VIV=y +CONFIG_MXC_IPU_V3=y + +# +# MXC VPU(Video Processing Unit) support +# +CONFIG_MXC_VPU=y +# CONFIG_MXC_VPU_DEBUG is not set +# CONFIG_MX6_VPU_352M is not set + +# +# MXC HDMI CEC (Consumer Electronics Control) support +# +# CONFIG_MXC_HDMI_CEC is not set + +# +# MXC MIPI Support +# +CONFIG_MXC_MIPI_CSI2=y + +# +# MXC Media Local Bus Driver +# +CONFIG_MXC_MLB=y +CONFIG_MXC_MLB150=m +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_PCA9685 is not set +# CONFIG_LEDS_DA9052 is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_MC13783 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_OT200 is not set +# CONFIG_LEDS_BLINKM is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +# CONFIG_LEDS_TRIGGER_CPU is not set +CONFIG_LEDS_TRIGGER_GPIO=y +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_EDAC is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12057 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_RX4581 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DA9052 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_DS2404 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_IMXDI is not set +CONFIG_RTC_DRV_MC13XXX=y +CONFIG_RTC_DRV_MXC=y +CONFIG_RTC_DRV_SNVS=y +# CONFIG_RTC_DRV_MOXART is not set + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +# CONFIG_DW_DMAC_CORE is not set +# CONFIG_DW_DMAC is not set +CONFIG_MX3_IPU=y +CONFIG_MX3_IPU_IRQS=4 +CONFIG_MXC_PXP_V2=y +CONFIG_MXC_PXP_CLIENT_DEVICE=y +# CONFIG_TIMB_DMA is not set +CONFIG_IMX_SDMA=y +# CONFIG_IMX_DMA is not set +CONFIG_MXS_DMA=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_VIRT_DRIVERS is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_USBIP_CORE is not set +# CONFIG_W35UND is not set +# CONFIG_PRISM2_USB is not set +# CONFIG_ECHO is not set +# CONFIG_COMEDI is not set +# CONFIG_RTLLIB is not set +# CONFIG_R8712U is not set +# CONFIG_R8188EU is not set +# CONFIG_RTS5139 is not set +# CONFIG_TRANZPORT is not set +# CONFIG_LINE6_USB is not set +# CONFIG_USB_SERIAL_QUATECH2 is not set +# CONFIG_VT6656 is not set + +# +# IIO staging drivers +# + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_LIS3L02DQ is not set + +# +# Analog to digital converters +# +# CONFIG_AD7291 is not set +# CONFIG_AD7606 is not set +# CONFIG_AD799X is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7280 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Direct Digital Synthesis +# +# CONFIG_AD5930 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_AD9850 is not set +# CONFIG_AD9852 is not set +# CONFIG_AD9910 is not set +# CONFIG_AD9951 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set + +# +# Light sensors +# +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_ISL29028 is not set +# CONFIG_TSL2583 is not set +# CONFIG_TSL2x7x is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_HMC5843 is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_SIMPLE_DUMMY is not set +# CONFIG_USB_ENESTORAGE is not set +# CONFIG_BCM_WIMAX is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +CONFIG_STAGING_MEDIA=y +# CONFIG_I2C_BCM2048 is not set +# CONFIG_VIDEO_GO7007 is not set +# CONFIG_USB_MSI3101 is not set +# CONFIG_VIDEO_TCM825X is not set +# CONFIG_USB_SN9C102 is not set + +# +# Android +# +# CONFIG_ANDROID is not set +# CONFIG_USB_WPAN_HCD is not set +# CONFIG_WIMAX_GDM72XX is not set +# CONFIG_LTE_GDM724X is not set +# CONFIG_CED1401 is not set +# CONFIG_DRM_IMX is not set +# CONFIG_DGRP is not set +# CONFIG_MTD_SPINAND_MT29F is not set +# CONFIG_LUSTRE_FS is not set +# CONFIG_XILLYBUS is not set +# CONFIG_DGAP is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_QCOM is not set + +# +# Hardware Spinlock drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_MMIO=y +# CONFIG_MAILBOX is not set +# CONFIG_IOMMU_SUPPORT is not set + +# +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +CONFIG_IIO=y +# CONFIG_IIO_BUFFER is not set +# CONFIG_IIO_TRIGGER is not set + +# +# Accelerometers +# +# CONFIG_BMA180 is not set +# CONFIG_IIO_ST_ACCEL_3AXIS is not set +# CONFIG_KXSD9 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7266 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_EXYNOS_ADC is not set +# CONFIG_MAX1363 is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3422 is not set +# CONFIG_NAU7802 is not set +# CONFIG_TI_ADC081C is not set +CONFIG_VF610_ADC=y + +# +# Amplifiers +# +# CONFIG_AD8366 is not set + +# +# Hid Sensor IIO Common +# + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5686 is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD7303 is not set +# CONFIG_MAX517 is not set +# CONFIG_MCP4725 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +# CONFIG_AD9523 is not set + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +# CONFIG_ADF4350 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set +# CONFIG_IIO_ST_GYRO_3AXIS is not set +# CONFIG_ITG3200 is not set + +# +# Humidity sensors +# +# CONFIG_DHT11 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_INV_MPU6050_IIO is not set + +# +# Light sensors +# +# CONFIG_ADJD_S311 is not set +# CONFIG_APDS9300 is not set +# CONFIG_CM32181 is not set +# CONFIG_CM36651 is not set +# CONFIG_GP2AP020A00F is not set +# CONFIG_TCS3472 is not set +# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_TSL4531 is not set +# CONFIG_VCNL4000 is not set + +# +# Magnetometer sensors +# +# CONFIG_AK8975 is not set +# CONFIG_MAG3110 is not set +# CONFIG_IIO_ST_MAGN_3AXIS is not set + +# +# Inclinometer sensors +# + +# +# Pressure sensors +# +# CONFIG_MPL3115 is not set +# CONFIG_IIO_ST_PRESS is not set + +# +# Temperature sensors +# +# CONFIG_TMP006 is not set +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +CONFIG_PWM_IMX=y +# CONFIG_PWM_PCA9685 is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +# CONFIG_IPACK_BUS is not set +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RESET_GPIO=y +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +# CONFIG_GENERIC_PHY is not set +# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set +# CONFIG_PHY_EXYNOS_DP_VIDEO is not set +# CONFIG_POWERCAP is not set + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_DEFAULTS_TO_ORDERED=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=m +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set +# CONFIG_QUOTA_DEBUG is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set +CONFIG_QUOTACTL=y +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=m +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_UBIFS_FS=y +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_F2FS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V2=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +# CONFIG_NFS_SWAP is not set +# CONFIG_NFS_V4_1 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +CONFIG_NFSD_V4=y +# CONFIG_NFSD_V4_SECURITY_LABEL is not set +# CONFIG_NFSD_FAULT_INJECTION is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +# CONFIG_CIFS_UPCALL is not set +# CONFIG_CIFS_XATTR is not set +CONFIG_CIFS_DEBUG=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_DFS_UPCALL is not set +# CONFIG_CIFS_SMB2 is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +CONFIG_NLS_ISO8859_15=m +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +# CONFIG_BOOT_PRINTK_DELAY is not set +CONFIG_DYNAMIC_DEBUG=y + +# +# Compile-time checks and compiler options +# +# CONFIG_DEBUG_INFO is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +CONFIG_DEBUG_PREEMPT=y + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set + +# +# RCU Debugging +# +# CONFIG_PROVE_RCU_DELAY is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +CONFIG_RCU_CPU_STALL_VERBOSE=y +# CONFIG_RCU_CPU_STALL_INFO is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set + +# +# Runtime Testing +# +# CONFIG_LKDTM is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_TEST_MODULE is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARM_PTDUMP is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_LL is not set +CONFIG_DEBUG_IMX_UART_PORT=1 +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +# CONFIG_DEBUG_UART_PL01X is not set +# CONFIG_DEBUG_UART_8250 is not set +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +CONFIG_SECURITY=y +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_NETWORK is not set +# CONFIG_SECURITY_PATH is not set +# CONFIG_SECURITY_SMACK is not set +# CONFIG_SECURITY_TOMOYO is not set +# CONFIG_SECURITY_APPARMOR is not set +# CONFIG_SECURITY_YAMA is not set +# CONFIG_IMA is not set +# CONFIG_EVM is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_USER=y +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_AUTHENC=y +CONFIG_CRYPTO_TEST=m +CONFIG_CRYPTO_ABLK_HELPER=m + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_SEQIV=y + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_CTS=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_LRW=y +# CONFIG_CRYPTO_PCBC is not set +CONFIG_CRYPTO_XTS=y + +# +# Hash modes +# +CONFIG_CRYPTO_CMAC=m +CONFIG_CRYPTO_HMAC=m +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +CONFIG_CRYPTO_CRCT10DIF=y +CONFIG_CRYPTO_GHASH=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=y +CONFIG_CRYPTO_RMD128=y +CONFIG_CRYPTO_RMD160=y +CONFIG_CRYPTO_RMD256=y +CONFIG_CRYPTO_RMD320=y +CONFIG_CRYPTO_SHA1=y +# CONFIG_CRYPTO_SHA1_ARM is not set +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_TGR192=y +CONFIG_CRYPTO_WP512=y + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=m +CONFIG_CRYPTO_AES_ARM_BS=m +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_BLOWFISH_COMMON=y +CONFIG_CRYPTO_CAMELLIA=y +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_DEV_FSL_CAAM=y +CONFIG_CRYPTO_DEV_FSL_CAAM_JR=y +CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE=9 +# CONFIG_CRYPTO_DEV_FSL_CAAM_INTC is not set +CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=y +CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API=y +CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API=y +# CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST is not set +CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y +CONFIG_CRYPTO_DEV_FSL_CAAM_SM_SLOTSIZE=7 +CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=y +CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y +# CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG is not set +# CONFIG_CRYPTO_DEV_SAHARA is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_RATIONAL=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_STMP_DEVICE=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_CRC_CCITT=m +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=m +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +CONFIG_CRC7=m +CONFIG_LIBCRC32C=m +# CONFIG_CRC8 is not set +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_AVERAGE=y +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y +CONFIG_FONT_SUPPORT=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +# CONFIG_VIRTUALIZATION is not set +CONFIG_BACKPORT_INTEGRATE=y +CONFIG_BACKPORT_DIR="backports/" +CONFIG_BACKPORT_VERSION="v4.1.1-1-0-g8286954" +CONFIG_BACKPORT_KERNEL_VERSION="v4.1.7-0-g0c5c1f1" +CONFIG_BACKPORT_KERNEL_NAME="Linux" +CONFIG_BACKPORT_LINUX=y +CONFIG_BACKPORT_KERNEL_3_15=y +CONFIG_BACKPORT_KERNEL_3_16=y +CONFIG_BACKPORT_KERNEL_3_17=y +CONFIG_BACKPORT_KERNEL_3_18=y +CONFIG_BACKPORT_KERNEL_3_19=y +CONFIG_BACKPORT_KERNEL_3_20=y +CONFIG_BACKPORT_KERNEL_3_21=y +CONFIG_BACKPORT_KERNEL_3_22=y +CONFIG_BACKPORT_KERNEL_3_23=y +CONFIG_BACKPORT_KERNEL_3_24=y +CONFIG_BACKPORT_KERNEL_3_25=y +CONFIG_BACKPORT_KERNEL_3_26=y +CONFIG_BACKPORT_KERNEL_3_27=y +CONFIG_BACKPORT_KERNEL_3_28=y +CONFIG_BACKPORT_KERNEL_3_29=y +CONFIG_BACKPORT_KERNEL_3_30=y +CONFIG_BACKPORT_KERNEL_3_31=y +CONFIG_BACKPORT_KERNEL_3_32=y +CONFIG_BACKPORT_KERNEL_3_33=y +CONFIG_BACKPORT_KERNEL_3_34=y +CONFIG_BACKPORT_KERNEL_3_35=y +CONFIG_BACKPORT_KERNEL_3_36=y +CONFIG_BACKPORT_KERNEL_3_37=y +CONFIG_BACKPORT_KERNEL_3_38=y +CONFIG_BACKPORT_KERNEL_3_39=y +CONFIG_BACKPORT_KERNEL_3_40=y +CONFIG_BACKPORT_KERNEL_3_41=y +CONFIG_BACKPORT_KERNEL_3_42=y +CONFIG_BACKPORT_KERNEL_3_43=y +CONFIG_BACKPORT_KERNEL_3_44=y +CONFIG_BACKPORT_KERNEL_3_45=y +CONFIG_BACKPORT_KERNEL_3_46=y +CONFIG_BACKPORT_KERNEL_3_47=y +CONFIG_BACKPORT_KERNEL_3_48=y +CONFIG_BACKPORT_KERNEL_3_49=y +CONFIG_BACKPORT_KERNEL_3_50=y +CONFIG_BACKPORT_KERNEL_3_51=y +CONFIG_BACKPORT_KERNEL_3_52=y +CONFIG_BACKPORT_KERNEL_3_53=y +CONFIG_BACKPORT_KERNEL_3_54=y +CONFIG_BACKPORT_KERNEL_3_55=y +CONFIG_BACKPORT_KERNEL_3_56=y +CONFIG_BACKPORT_KERNEL_3_57=y +CONFIG_BACKPORT_KERNEL_3_58=y +CONFIG_BACKPORT_KERNEL_3_59=y +CONFIG_BACKPORT_KERNEL_3_60=y +CONFIG_BACKPORT_KERNEL_3_61=y +CONFIG_BACKPORT_KERNEL_3_62=y +CONFIG_BACKPORT_KERNEL_3_63=y +CONFIG_BACKPORT_KERNEL_3_64=y +CONFIG_BACKPORT_KERNEL_3_65=y +CONFIG_BACKPORT_KERNEL_3_66=y +CONFIG_BACKPORT_KERNEL_3_67=y +CONFIG_BACKPORT_KERNEL_3_68=y +CONFIG_BACKPORT_KERNEL_3_69=y +CONFIG_BACKPORT_KERNEL_3_70=y +CONFIG_BACKPORT_KERNEL_3_71=y +CONFIG_BACKPORT_KERNEL_3_72=y +CONFIG_BACKPORT_KERNEL_3_73=y +CONFIG_BACKPORT_KERNEL_3_74=y +CONFIG_BACKPORT_KERNEL_3_75=y +CONFIG_BACKPORT_KERNEL_3_76=y +CONFIG_BACKPORT_KERNEL_3_77=y +CONFIG_BACKPORT_KERNEL_3_78=y +CONFIG_BACKPORT_KERNEL_3_79=y +CONFIG_BACKPORT_KERNEL_3_80=y +CONFIG_BACKPORT_KERNEL_3_81=y +CONFIG_BACKPORT_KERNEL_3_82=y +CONFIG_BACKPORT_KERNEL_3_83=y +CONFIG_BACKPORT_KERNEL_3_84=y +CONFIG_BACKPORT_KERNEL_3_85=y +CONFIG_BACKPORT_KERNEL_3_86=y +CONFIG_BACKPORT_KERNEL_3_87=y +CONFIG_BACKPORT_KERNEL_3_88=y +CONFIG_BACKPORT_KERNEL_3_89=y +CONFIG_BACKPORT_KERNEL_3_90=y +CONFIG_BACKPORT_KERNEL_3_91=y +CONFIG_BACKPORT_KERNEL_3_92=y +CONFIG_BACKPORT_KERNEL_3_93=y +CONFIG_BACKPORT_KERNEL_3_94=y +CONFIG_BACKPORT_KERNEL_3_95=y +CONFIG_BACKPORT_KERNEL_3_96=y +CONFIG_BACKPORT_KERNEL_3_97=y +CONFIG_BACKPORT_KERNEL_3_98=y +# CONFIG_BACKPORT_BPAUTO_USERSEL_BUILD_ALL is not set +# CONFIG_BACKPORT_BPAUTO_BUILD_CRYPTO_CCM is not set +CONFIG_BACKPORT_CFG80211=m +# CONFIG_BACKPORT_NL80211_TESTMODE is not set +CONFIG_BACKPORT_CFG80211_DEVELOPER_WARNINGS=y +CONFIG_BACKPORT_CFG80211_REG_DEBUG=y +# CONFIG_BACKPORT_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_BACKPORT_CFG80211_DEFAULT_PS=y +# CONFIG_BACKPORT_CFG80211_DEBUGFS is not set +# CONFIG_BACKPORT_CFG80211_INTERNAL_REGDB is not set +# CONFIG_BACKPORT_LIB80211 is not set +CONFIG_BACKPORT_MAC80211=m +CONFIG_BACKPORT_MAC80211_HAS_RC=y +CONFIG_BACKPORT_MAC80211_RC_MINSTREL=y +CONFIG_BACKPORT_MAC80211_RC_MINSTREL_HT=y +# CONFIG_BACKPORT_MAC80211_RC_MINSTREL_VHT is not set +CONFIG_BACKPORT_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_BACKPORT_MAC80211_RC_DEFAULT="minstrel_ht" +CONFIG_BACKPORT_MAC80211_MESH=y +# CONFIG_BACKPORT_MAC80211_LEDS is not set +# CONFIG_BACKPORT_MAC80211_DEBUGFS is not set +CONFIG_BACKPORT_MAC80211_MESSAGE_TRACING=y +CONFIG_BACKPORT_MAC80211_DEBUG_MENU=y +# CONFIG_BACKPORT_MAC80211_NOINLINE is not set +CONFIG_BACKPORT_MAC80211_VERBOSE_DEBUG=y +# CONFIG_BACKPORT_MAC80211_MLME_DEBUG is not set +CONFIG_BACKPORT_MAC80211_STA_DEBUG=y +# CONFIG_BACKPORT_MAC80211_HT_DEBUG is not set +# CONFIG_BACKPORT_MAC80211_OCB_DEBUG is not set +# CONFIG_BACKPORT_MAC80211_IBSS_DEBUG is not set +# CONFIG_BACKPORT_MAC80211_PS_DEBUG is not set +# CONFIG_BACKPORT_MAC80211_MPL_DEBUG is not set +# CONFIG_BACKPORT_MAC80211_MPATH_DEBUG is not set +# CONFIG_BACKPORT_MAC80211_MHWMP_DEBUG is not set +# CONFIG_BACKPORT_MAC80211_MESH_SYNC_DEBUG is not set +# CONFIG_BACKPORT_MAC80211_MESH_CSA_DEBUG is not set +# CONFIG_BACKPORT_MAC80211_MESH_PS_DEBUG is not set +# CONFIG_BACKPORT_MAC80211_TDLS_DEBUG is not set +CONFIG_BACKPORT_BT=m +CONFIG_BACKPORT_BT_BREDR=y +CONFIG_BACKPORT_BT_RFCOMM=m +CONFIG_BACKPORT_BT_RFCOMM_TTY=y +CONFIG_BACKPORT_BT_BNEP=m +CONFIG_BACKPORT_BT_BNEP_MC_FILTER=y +CONFIG_BACKPORT_BT_BNEP_PROTO_FILTER=y +CONFIG_BACKPORT_BT_HIDP=m +CONFIG_BACKPORT_BT_LE=y +# CONFIG_BACKPORT_BT_SELFTEST is not set +CONFIG_BACKPORT_BT_DEBUGFS=y + +# +# Bluetooth device drivers +# +CONFIG_BACKPORT_BT_INTEL=m +CONFIG_BACKPORT_BT_BCM=m +CONFIG_BACKPORT_BT_HCIBTUSB=m +CONFIG_BACKPORT_BT_HCIBTUSB_BCM=y +# CONFIG_BACKPORT_BT_HCIBTSDIO is not set +# CONFIG_BACKPORT_BT_HCIUART is not set +# CONFIG_BACKPORT_BT_HCIBCM203X is not set +# CONFIG_BACKPORT_BT_HCIBPA10X is not set +# CONFIG_BACKPORT_BT_HCIBFUSB is not set +# CONFIG_BACKPORT_BT_HCIVHCI is not set +# CONFIG_BACKPORT_BT_MRVL is not set +# CONFIG_BACKPORT_BT_ATH3K is not set +CONFIG_BACKPORT_BT_WILINK=m +CONFIG_BACKPORT_WLAN=y +# CONFIG_BACKPORT_LIBERTAS_THINFIRM is not set +# CONFIG_BACKPORT_AT76C50X_USB is not set +# CONFIG_BACKPORT_USB_NET_RNDIS_WLAN is not set +# CONFIG_BACKPORT_MAC80211_HWSIM is not set +# CONFIG_BACKPORT_ATH_CARDS is not set +# CONFIG_BACKPORT_BRCMFMAC is not set +# CONFIG_BACKPORT_P54_COMMON is not set +# CONFIG_BACKPORT_RT2X00 is not set +# CONFIG_BACKPORT_RTL_CARDS is not set +CONFIG_BACKPORT_WL_TI=y +# CONFIG_BACKPORT_WL1251 is not set +# CONFIG_BACKPORT_WL12XX is not set +CONFIG_BACKPORT_WL18XX=m +CONFIG_BACKPORT_WLCORE=m +# CONFIG_BACKPORT_WLCORE_SPI is not set +CONFIG_BACKPORT_WLCORE_SDIO=m +# CONFIG_BACKPORT_ZD1211RW is not set +# CONFIG_BACKPORT_MWIFIEX is not set +# CONFIG_BACKPORT_RSI_91X is not set + +# +# Host-side USB support is needed for USB Network Adapter support +# +# CONFIG_BACKPORT_USB_NET_DRIVERS is not set +# CONFIG_BACKPORT_NFC is not set +# CONFIG_BACKPORT_6LOWPAN is not set +# CONFIG_BACKPORT_IEEE802154 is not set + +# +# USB Device Class drivers +# +# CONFIG_BACKPORT_USB_WDM is not set \ No newline at end of file diff --git a/config/linux-udoo-next.config b/config/linux-udoo-next.config new file mode 100644 index 000000000..eff8b53f6 --- /dev/null +++ b/config/linux-udoo-next.config @@ -0,0 +1,4782 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 4.2.6 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_MIGHT_HAVE_PCI=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_GENERIC_BUG=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_HAVE_KERNEL_LZ4=y +# CONFIG_KERNEL_GZIP is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_XZ is not set +CONFIG_KERNEL_LZO=y +# CONFIG_KERNEL_LZ4 is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_FHANDLE=y +CONFIG_USELIB=y +# CONFIG_AUDIT is not set +CONFIG_HAVE_ARCH_AUDITSYSCALL=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +# CONFIG_IRQ_TIME_ACCOUNTING is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_RCU_EXPERT is not set +CONFIG_SRCU=y +# CONFIG_TASKS_RCU is not set +CONFIG_RCU_STALL_COMMON=y +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_NOCB_CPU is not set +# CONFIG_RCU_EXPEDITE_BOOT is not set +# CONFIG_BUILD_BIN2C is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=15 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CGROUP_FREEZER is not set +# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CPUSETS is not set +# CONFIG_CGROUP_CPUACCT is not set +# CONFIG_MEMCG is not set +# CONFIG_CGROUP_PERF is not set +# CONFIG_CGROUP_SCHED is not set +# CONFIG_BLK_CGROUP is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_BPF=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_MULTIUSER=y +CONFIG_SGETMASK_SYSCALL=y +CONFIG_SYSFS_SYSCALL=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +# CONFIG_BPF_SYSCALL is not set +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_ADVISE_SYSCALLS=y +CONFIG_PCI_QUIRKS=y +# CONFIG_EMBEDDED is not set +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_SLUB_CPU_PARTIAL=y +CONFIG_SYSTEM_TRUSTED_KEYRING=y +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_JUMP_LABEL is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_OPTPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR is not set +CONFIG_CC_STACKPROTECTOR_NONE=y +# CONFIG_CC_STACKPROTECTOR_REGULAR is not set +# CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_COMPRESS is not set +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_CMDLINE_PARSER is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_PADATA=y +CONFIG_ASN1=m +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +CONFIG_INLINE_READ_UNLOCK=y +CONFIG_INLINE_READ_UNLOCK_IRQ=y +CONFIG_INLINE_WRITE_UNLOCK=y +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +CONFIG_ARCH_MULTIPLATFORM=y +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_SHMOBILE_LEGACY is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C24XX is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP1 is not set + +# +# Multiple platform selection +# + +# +# CPU Core family selection +# +# CONFIG_ARCH_MULTI_V6 is not set +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_MULTI_V6_V7=y +# CONFIG_ARCH_MULTI_CPU_AUTO is not set +# CONFIG_ARCH_VIRT is not set +# CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCM is not set +# CONFIG_ARCH_BERLIN is not set +# CONFIG_ARCH_DIGICOLOR is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_KEYSTONE is not set +# CONFIG_ARCH_MESON is not set +CONFIG_ARCH_MXC=y +CONFIG_HAVE_IMX_ANATOP=y +CONFIG_HAVE_IMX_GPC=y +CONFIG_HAVE_IMX_MMDC=y +CONFIG_HAVE_IMX_SRC=y + +# +# Device tree only +# + +# +# Cortex-A platforms +# +# CONFIG_SOC_IMX50 is not set +# CONFIG_SOC_IMX51 is not set +# CONFIG_SOC_IMX53 is not set +CONFIG_SOC_IMX6=y +CONFIG_SOC_IMX6Q=y +CONFIG_SOC_IMX6SL=y +# CONFIG_SOC_IMX6SX is not set +# CONFIG_SOC_IMX7D is not set +CONFIG_SOC_LS1021A=y + +# +# Cortex-A/Cortex-M asymmetric multiprocessing platforms +# +# CONFIG_SOC_VF610 is not set +# CONFIG_ARCH_MEDIATEK is not set + +# +# TI OMAP/AM/DM/DRA Family +# +# CONFIG_ARCH_OMAP3 is not set +# CONFIG_ARCH_OMAP4 is not set +# CONFIG_SOC_OMAP5 is not set +# CONFIG_SOC_AM33XX is not set +# CONFIG_SOC_AM43XX is not set +# CONFIG_SOC_DRA7XX is not set +# CONFIG_ARCH_QCOM is not set +# CONFIG_ARCH_ROCKCHIP is not set +# CONFIG_ARCH_SOCFPGA is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_STI is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SHMOBILE_MULTI is not set +# CONFIG_ARCH_SUNXI is not set +# CONFIG_ARCH_SIRF is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_UNIPHIER is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_WM8850 is not set +# CONFIG_ARCH_ZX is not set +# CONFIG_ARCH_ZYNQ is not set + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_LPAE is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_ARM_VIRT_EXT=y +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_KUSER_HELPERS=y +CONFIG_VDSO=y +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_CACHE_L2X0=y +CONFIG_PL310_ERRATA_588369=y +CONFIG_PL310_ERRATA_727915=y +# CONFIG_PL310_ERRATA_753970 is not set +CONFIG_PL310_ERRATA_769419=y +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +# CONFIG_ARM_KERNMEM_PERMS is not set +CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_430973 is not set +CONFIG_ARM_ERRATA_643719=y +CONFIG_ARM_ERRATA_720789=y +CONFIG_ARM_ERRATA_754322=y +CONFIG_ARM_ERRATA_754327=y +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_ERRATA_775420=y +# CONFIG_ARM_ERRATA_798181 is not set +# CONFIG_ARM_ERRATA_773022 is not set + +# +# Bus support +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_SYSCALL=y +# CONFIG_PCI_MSI is not set +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_PRI is not set +# CONFIG_PCI_PASID is not set + +# +# PCI host controller drivers +# +CONFIG_PCIE_DW=y +CONFIG_PCI_IMX6=y +CONFIG_PCI_HOST_GENERIC=y +# CONFIG_PCI_LAYERSCAPE is not set +# CONFIG_PCIE_IPROC is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIEAER=y +# CONFIG_PCIE_ECRC is not set +# CONFIG_PCIEAER_INJECT is not set +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEBUG is not set +CONFIG_PCIEASPM_DEFAULT=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_PERFORMANCE is not set +CONFIG_PCIE_PME=y +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_HAVE_SMP=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_ARM_CPU_TOPOLOGY=y +# CONFIG_SCHED_MC is not set +# CONFIG_SCHED_SMT is not set +CONFIG_HAVE_ARM_SCU=y +CONFIG_HAVE_ARM_ARCH_TIMER=y +CONFIG_HAVE_ARM_TWD=y +# CONFIG_MCPM is not set +# CONFIG_BIG_LITTLE is not set +# CONFIG_VMSPLIT_3G is not set +CONFIG_VMSPLIT_2G=y +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0x80000000 +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARM_PSCI=y +CONFIG_ARCH_NR_GPIO=0 +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_HZ_FIXED=0 +CONFIG_HZ_100=y +# CONFIG_HZ_200 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +# CONFIG_HZ_500 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 +CONFIG_SCHED_HRTICK=y +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HW_PERF_EVENTS=y +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +# CONFIG_ARM_MODULE_PLTS is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +CONFIG_MEMORY_ISOLATION=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_MEMORY_BALLOON=y +CONFIG_BALLOON_COMPACTION=y +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_BOUNCE=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_CLEANCACHE=y +CONFIG_FRONTSWAP=y +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set +CONFIG_CMA_AREAS=7 +CONFIG_ZSWAP=y +CONFIG_ZPOOL=y +CONFIG_ZBUD=y +CONFIG_ZSMALLOC=y +# CONFIG_PGTABLE_MAPPING is not set +# CONFIG_ZSMALLOC_STAT is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +# CONFIG_XEN is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ATAGS=y +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +# CONFIG_ARM_APPENDED_DTB is not set +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_EXTEND is not set +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +CONFIG_AUTO_ZRELADDR=y + +# +# CPU Power Management +# + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y + +# +# CPU frequency scaling drivers +# +# CONFIG_CPUFREQ_DT is not set +CONFIG_ARM_BIG_LITTLE_CPUFREQ=m +# CONFIG_ARM_DT_BL_CPUFREQ is not set +CONFIG_ARM_IMX6Q_CPUFREQ=y +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set +# CONFIG_QORIQ_CPUFREQ is not set + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y + +# +# ARM CPU Idle Drivers +# +# CONFIG_ARM_CPUIDLE is not set +# CONFIG_ARM_HIGHBANK_CPUIDLE is not set +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y +CONFIG_KERNEL_MODE_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=m +CONFIG_COREDUMP=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_HIBERNATION is not set +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM=y +CONFIG_PM_DEBUG=y +# CONFIG_PM_ADVANCED_DEBUG is not set +CONFIG_PM_TEST_SUSPEND=y +CONFIG_PM_SLEEP_DEBUG=y +# CONFIG_APM_EMULATION is not set +CONFIG_PM_OPP=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_CPU_PM=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_NET=y +CONFIG_NET_INGRESS=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_ROUTE_CLASSID=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=y +# CONFIG_SYN_COOKIES is not set +# CONFIG_NET_IPVTI is not set +CONFIG_NET_UDP_TUNNEL=m +# CONFIG_NET_FOU is not set +# CONFIG_NET_FOU_IP_TUNNELS is not set +# CONFIG_GENEVE_CORE is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +# CONFIG_IPV6_GRE is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NET_PTP_CLASSIFY=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_ACCT=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NF_CONNTRACK=y +CONFIG_NF_LOG_COMMON=m +CONFIG_NF_CONNTRACK_MARK=y +# CONFIG_NF_CONNTRACK_ZONES is not set +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_LABELS=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_BROADCAST=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_NETLINK_TIMEOUT=m +CONFIG_NF_CT_NETLINK_HELPER=m +CONFIG_NETFILTER_NETLINK_QUEUE_CT=y +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PROTO_DCCP=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_SIP=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_REDIRECT=m +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=m +# CONFIG_NF_TABLES_NETDEV is not set +CONFIG_NFT_EXTHDR=m +CONFIG_NFT_META=m +CONFIG_NFT_CT=m +CONFIG_NFT_RBTREE=m +CONFIG_NFT_HASH=m +CONFIG_NFT_COUNTER=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +# CONFIG_NFT_MASQ is not set +CONFIG_NFT_REDIR=m +CONFIG_NFT_NAT=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_REJECT_INET=m +CONFIG_NFT_COMPAT=m +CONFIG_NETFILTER_XTABLES=y + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_CONNMARK=m +CONFIG_NETFILTER_XT_SET=m + +# +# Xtables targets +# +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_NAT=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ECN=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +# CONFIG_NETFILTER_XT_MATCH_HELPER is not set +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_L2TP=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_MAX=256 +# CONFIG_IP_SET_BITMAP_IP is not set +# CONFIG_IP_SET_BITMAP_IPMAC is not set +# CONFIG_IP_SET_BITMAP_PORT is not set +# CONFIG_IP_SET_HASH_IP is not set +CONFIG_IP_SET_HASH_IPMARK=m +# CONFIG_IP_SET_HASH_IPPORT is not set +# CONFIG_IP_SET_HASH_IPPORTIP is not set +# CONFIG_IP_SET_HASH_IPPORTNET is not set +# CONFIG_IP_SET_HASH_MAC is not set +# CONFIG_IP_SET_HASH_NETPORTNET is not set +# CONFIG_IP_SET_HASH_NET is not set +# CONFIG_IP_SET_HASH_NETNET is not set +# CONFIG_IP_SET_HASH_NETPORT is not set +# CONFIG_IP_SET_HASH_NETIFACE is not set +# CONFIG_IP_SET_LIST_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +# CONFIG_NF_CONNTRACK_IPV4 is not set +CONFIG_NF_TABLES_IPV4=m +# CONFIG_NFT_CHAIN_ROUTE_IPV4 is not set +CONFIG_NFT_REJECT_IPV4=m +# CONFIG_NF_TABLES_ARP is not set +CONFIG_NF_LOG_ARP=m +CONFIG_NF_LOG_IPV4=m +CONFIG_NF_REJECT_IPV4=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +# CONFIG_IP_NF_MATCH_RPFILTER is not set +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +# CONFIG_IP_NF_TARGET_SYNPROXY is not set +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=m +# CONFIG_NF_CONNTRACK_IPV6 is not set +CONFIG_NF_TABLES_IPV6=m +# CONFIG_NFT_CHAIN_ROUTE_IPV6 is not set +CONFIG_NFT_REJECT_IPV6=m +CONFIG_NF_REJECT_IPV6=m +CONFIG_NF_LOG_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +# CONFIG_IP6_NF_MATCH_AH is not set +# CONFIG_IP6_NF_MATCH_EUI64 is not set +# CONFIG_IP6_NF_MATCH_FRAG is not set +# CONFIG_IP6_NF_MATCH_OPTS is not set +# CONFIG_IP6_NF_MATCH_HL is not set +# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set +# CONFIG_IP6_NF_MATCH_MH is not set +# CONFIG_IP6_NF_MATCH_RT is not set +# CONFIG_IP6_NF_FILTER is not set +# CONFIG_IP6_NF_TARGET_SYNPROXY is not set +# CONFIG_IP6_NF_MANGLE is not set +# CONFIG_IP6_NF_RAW is not set +CONFIG_NF_TABLES_BRIDGE=m +CONFIG_NFT_BRIDGE_META=m +CONFIG_NFT_BRIDGE_REJECT=m +CONFIG_NF_LOG_BRIDGE=m +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +CONFIG_STP=y +CONFIG_BRIDGE=y +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_HAVE_NET_DSA=y +CONFIG_VLAN_8021Q=y +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_VLAN_8021Q_MVRP is not set +# CONFIG_DECNET is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +# CONFIG_6LOWPAN is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +# CONFIG_NET_SCH_CBQ is not set +# CONFIG_NET_SCH_HTB is not set +# CONFIG_NET_SCH_HFSC is not set +# CONFIG_NET_SCH_PRIO is not set +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_CODEL is not set +# CONFIG_NET_SCH_FQ_CODEL is not set +# CONFIG_NET_SCH_FQ is not set +# CONFIG_NET_SCH_HHF is not set +# CONFIG_NET_SCH_PIE is not set +# CONFIG_NET_SCH_PLUG is not set + +# +# Classification +# +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_FW is not set +# CONFIG_NET_CLS_U32 is not set +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_FLOW is not set +CONFIG_NET_CLS_CGROUP=m +CONFIG_NET_CLS_BPF=m +# CONFIG_NET_CLS_FLOWER is not set +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +# CONFIG_NET_EMATCH_CMP is not set +# CONFIG_NET_EMATCH_NBYTE is not set +# CONFIG_NET_EMATCH_U32 is not set +# CONFIG_NET_EMATCH_META is not set +# CONFIG_NET_EMATCH_TEXT is not set +# CONFIG_NET_EMATCH_IPSET is not set +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +CONFIG_OPENVSWITCH=m +CONFIG_OPENVSWITCH_VXLAN=m +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set +CONFIG_MPLS=y +CONFIG_NET_MPLS_GSO=m +# CONFIG_MPLS_ROUTING is not set +# CONFIG_HSR is not set +# CONFIG_NET_SWITCHDEV is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +# CONFIG_CGROUP_NET_PRIO is not set +CONFIG_CGROUP_NET_CLASSID=y +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_JIT is not set +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +CONFIG_BT=y +CONFIG_BT_BREDR=y +CONFIG_BT_RFCOMM=y +# CONFIG_BT_RFCOMM_TTY is not set +# CONFIG_BT_BNEP is not set +CONFIG_BT_HIDP=y +CONFIG_BT_LE=y +# CONFIG_BT_SELFTEST is not set + +# +# Bluetooth device drivers +# +CONFIG_BT_INTEL=y +CONFIG_BT_BCM=y +CONFIG_BT_RTL=y +CONFIG_BT_HCIBTUSB=y +CONFIG_BT_HCIBTUSB_BCM=y +CONFIG_BT_HCIBTUSB_RTL=y +# CONFIG_BT_HCIBTSDIO is not set +CONFIG_BT_HCIUART=y +# CONFIG_BT_HCIUART_H4 is not set +# CONFIG_BT_HCIUART_BCSP is not set +# CONFIG_BT_HCIUART_ATH3K is not set +# CONFIG_BT_HCIUART_LL is not set +# CONFIG_BT_HCIUART_3WIRE is not set +# CONFIG_BT_HCIUART_INTEL is not set +# CONFIG_BT_HCIUART_BCM is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_MRVL is not set +# CONFIG_BT_ATH3K is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=y +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_WEXT=y +CONFIG_CFG80211_WEXT_EXPORT=y +CONFIG_LIB80211=m +CONFIG_LIB80211_CRYPT_WEP=m +CONFIG_LIB80211_CRYPT_CCMP=m +CONFIG_LIB80211_CRYPT_TKIP=m +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=y +CONFIG_MAC80211_HAS_RC=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MAC80211_RC_MINSTREL_VHT=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +CONFIG_MAC80211_MESH=y +# CONFIG_MAC80211_LEDS is not set +# CONFIG_MAC80211_MESSAGE_TRACING is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +CONFIG_CEPH_LIB=y +# CONFIG_CEPH_LIB_PRETTYDEBUG is not set +# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set +# CONFIG_NFC is not set +CONFIG_HAVE_BPF_JIT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_SOC_BUS=y +CONFIG_REGMAP=y +CONFIG_REGMAP_AC97=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_IRQ=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_FENCE_TRACE is not set +CONFIG_DMA_CMA=y + +# +# Default contiguous memory area size: +# +CONFIG_CMA_SIZE_MBYTES=256 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 + +# +# Bus devices +# +CONFIG_ARM_CCI=y +CONFIG_ARM_CCI_PMU=y +# CONFIG_ARM_CCI400_PMU is not set +CONFIG_ARM_CCI500_PMU=y +CONFIG_ARM_CCN=y +# CONFIG_BRCMSTB_GISB_ARB is not set +CONFIG_IMX_WEIM=y +# CONFIG_VEXPRESS_CONFIG is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +# CONFIG_MTD is not set +CONFIG_DTC=y +CONFIG_OF=y +# CONFIG_OF_UNITTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_OF_RESERVED_MEM=y +# CONFIG_OF_OVERLAY is not set +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_ZRAM is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_NVME is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_VIRTIO_BLK is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_BLK_DEV_RSXX is not set + +# +# Misc devices +# +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +CONFIG_SRAM=y +CONFIG_UDOO_ARD=m +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_CB710_CORE is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# Intel MIC Bus Driver +# + +# +# SCIF Bus Driver +# + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# + +# +# SCIF Driver +# +# CONFIG_ECHO is not set +# CONFIG_CXL_BASE is not set +# CONFIG_CXL_KERNEL_API is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_MVUMI is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_SCSI_ESAS2R is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_MPT3SAS is not set +# CONFIG_SCSI_UFSHCD is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_SNIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_WD719X is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_PMCRAID is not set +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_VIRTIO is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +# CONFIG_SATA_AHCI is not set +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_AHCI_IMX=y +# CONFIG_AHCI_CEVA is not set +# CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_ACARD_AHCI is not set +# CONFIG_SATA_SIL24 is not set +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_SX4 is not set +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# +# CONFIG_ATA_PIIX is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_SVW is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set + +# +# PATA SFF controllers with BMDMA +# +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_ATP867X is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IMX is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RDC is not set +# CONFIG_PATA_SCH is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_TOSHIBA is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set + +# +# PIO-only SFF controllers +# +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_PLATFORM is not set +# CONFIG_PATA_RZ1000 is not set + +# +# Generic fallback / legacy drivers +# +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_LEGACY is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +# CONFIG_MD_LINEAR is not set +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_MULTIPATH=m +# CONFIG_MD_FAULTY is not set +CONFIG_BCACHE=m +# CONFIG_BCACHE_DEBUG is not set +# CONFIG_BCACHE_CLOSURES_DEBUG is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=y +# CONFIG_DM_MQ_DEFAULT is not set +# CONFIG_DM_DEBUG is not set +CONFIG_DM_BUFIO=m +CONFIG_DM_BIO_PRISON=m +CONFIG_DM_PERSISTENT_DATA=m +# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set +CONFIG_DM_CRYPT=y +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_THIN_PROVISIONING=m +CONFIG_DM_CACHE=m +CONFIG_DM_CACHE_MQ=m +CONFIG_DM_CACHE_SMQ=m +CONFIG_DM_CACHE_CLEANER=m +# CONFIG_DM_ERA is not set +CONFIG_DM_MIRROR=m +CONFIG_DM_LOG_USERSPACE=m +CONFIG_DM_RAID=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_QL=m +CONFIG_DM_MULTIPATH_ST=m +CONFIG_DM_DELAY=m +CONFIG_DM_UEVENT=y +# CONFIG_DM_FLAKEY is not set +# CONFIG_DM_VERITY is not set +# CONFIG_DM_SWITCH is not set +# CONFIG_DM_LOG_WRITES is not set +# CONFIG_TARGET_CORE is not set +CONFIG_FUSION=y +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_SAS is not set +CONFIG_FUSION_MAX_SGE=128 +# CONFIG_FUSION_LOGGING is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +CONFIG_BONDING=y +# CONFIG_DUMMY is not set +CONFIG_EQUALIZER=m +# CONFIG_NET_FC is not set +CONFIG_NET_TEAM=m +CONFIG_NET_TEAM_MODE_BROADCAST=m +CONFIG_NET_TEAM_MODE_ROUNDROBIN=m +CONFIG_NET_TEAM_MODE_RANDOM=m +CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m +CONFIG_NET_TEAM_MODE_LOADBALANCE=m +CONFIG_MACVLAN=y +CONFIG_MACVTAP=y +CONFIG_IPVLAN=m +CONFIG_VXLAN=m +CONFIG_NETCONSOLE=m +# CONFIG_NETCONSOLE_DYNAMIC is not set +CONFIG_NETPOLL=y +CONFIG_NET_POLL_CONTROLLER=y +CONFIG_TUN=y +# CONFIG_TUN_VNET_CROSS_LE is not set +# CONFIG_VETH is not set +# CONFIG_VIRTIO_NET is not set +# CONFIG_NLMON is not set +# CONFIG_ARCNET is not set + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_3COM=y +# CONFIG_VORTEX is not set +# CONFIG_TYPHOON is not set +CONFIG_NET_VENDOR_ADAPTEC=y +# CONFIG_ADAPTEC_STARFIRE is not set +CONFIG_NET_VENDOR_AGERE=y +# CONFIG_ET131X is not set +CONFIG_NET_VENDOR_ALTEON=y +# CONFIG_ACENIC is not set +# CONFIG_ALTERA_TSE is not set +CONFIG_NET_VENDOR_AMD=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_PCNET32 is not set +CONFIG_NET_VENDOR_ARC=y +# CONFIG_ARC_EMAC is not set +# CONFIG_EMAC_ROCKCHIP is not set +CONFIG_NET_VENDOR_ATHEROS=y +# CONFIG_ATL2 is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_ALX is not set +CONFIG_NET_CADENCE=y +# CONFIG_MACB is not set +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_BCMGENET is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2X is not set +# CONFIG_SYSTEMPORT is not set +CONFIG_NET_VENDOR_BROCADE=y +# CONFIG_BNA is not set +CONFIG_NET_VENDOR_CAVIUM=y +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +CONFIG_NET_VENDOR_CIRRUS=y +# CONFIG_CS89x0 is not set +CONFIG_NET_VENDOR_CISCO=y +# CONFIG_ENIC is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_DEC=y +# CONFIG_NET_TULIP is not set +CONFIG_NET_VENDOR_DLINK=y +# CONFIG_DL2K is not set +# CONFIG_SUNDANCE is not set +CONFIG_NET_VENDOR_EMULEX=y +# CONFIG_BE2NET is not set +CONFIG_NET_VENDOR_EZCHIP=y +# CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set +CONFIG_NET_VENDOR_EXAR=y +# CONFIG_S2IO is not set +# CONFIG_VXGE is not set +CONFIG_NET_VENDOR_FARADAY=y +# CONFIG_FTMAC100 is not set +# CONFIG_FTGMAC100 is not set +CONFIG_NET_VENDOR_FREESCALE=y +CONFIG_FEC=y +# CONFIG_FSL_PQ_MDIO is not set +# CONFIG_FSL_XGMAC_MDIO is not set +# CONFIG_GIANFAR is not set +CONFIG_NET_VENDOR_HISILICON=y +# CONFIG_HIX5HD2_GMAC is not set +CONFIG_HIP04_ETH=m +CONFIG_NET_VENDOR_HP=y +# CONFIG_HP100 is not set +CONFIG_NET_VENDOR_INTEL=y +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +# CONFIG_I40E is not set +CONFIG_NET_VENDOR_I825XX=y +# CONFIG_IP1000 is not set +# CONFIG_JME is not set +CONFIG_NET_VENDOR_MARVELL=y +# CONFIG_MVMDIO is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +CONFIG_NET_VENDOR_MELLANOX=y +# CONFIG_MLX4_EN is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_MLX5_CORE is not set +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_KSZ884X_PCI is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +CONFIG_NET_VENDOR_MYRI=y +# CONFIG_MYRI10GE is not set +# CONFIG_FEALNX is not set +CONFIG_NET_VENDOR_NATSEMI=y +# CONFIG_NATSEMI is not set +# CONFIG_NS83820 is not set +CONFIG_NET_VENDOR_8390=y +# CONFIG_AX88796 is not set +# CONFIG_NE2K_PCI is not set +CONFIG_NET_VENDOR_NVIDIA=y +# CONFIG_FORCEDETH is not set +CONFIG_NET_VENDOR_OKI=y +# CONFIG_ETHOC is not set +CONFIG_NET_PACKET_ENGINE=y +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +CONFIG_NET_VENDOR_QLOGIC=y +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_QLGE is not set +# CONFIG_NETXEN_NIC is not set +CONFIG_NET_VENDOR_QUALCOMM=y +# CONFIG_QCA7000 is not set +CONFIG_NET_VENDOR_REALTEK=y +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_R8169 is not set +CONFIG_NET_VENDOR_RENESAS=y +CONFIG_NET_VENDOR_RDC=y +# CONFIG_R6040 is not set +CONFIG_NET_VENDOR_ROCKER=y +CONFIG_NET_VENDOR_SAMSUNG=y +# CONFIG_SXGBE_ETH is not set +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SILAN=y +# CONFIG_SC92031 is not set +CONFIG_NET_VENDOR_SIS=y +# CONFIG_SIS900 is not set +# CONFIG_SIS190 is not set +# CONFIG_SFC is not set +CONFIG_NET_VENDOR_SMSC=y +# CONFIG_SMC91X is not set +# CONFIG_EPIC100 is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_SMSC9420 is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_SUN=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NIU is not set +CONFIG_NET_VENDOR_TEHUTI=y +# CONFIG_TEHUTI is not set +CONFIG_NET_VENDOR_TI=y +# CONFIG_TI_CPSW_ALE is not set +# CONFIG_TLAN is not set +CONFIG_NET_VENDOR_VIA=y +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_AT803X_PHY=y +# CONFIG_AMD_PHY is not set +CONFIG_MARVELL_PHY=m +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_DP83867_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_USB_NET_DRIVERS=y +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_RTL8152 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set +CONFIG_WLAN=y +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_ATMEL is not set +# CONFIG_AT76C50X_USB is not set +# CONFIG_PRISM54 is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8180 is not set +# CONFIG_RTL8187 is not set +# CONFIG_ADM8211 is not set +CONFIG_MAC80211_HWSIM=y +# CONFIG_MWL8K is not set +# CONFIG_ATH_CARDS is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +CONFIG_BRCMUTIL=m +# CONFIG_BRCMSMAC is not set +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_PROTO_BCDC=y +CONFIG_BRCMFMAC_SDIO=y +# CONFIG_BRCMFMAC_USB is not set +# CONFIG_BRCMFMAC_PCIE is not set +# CONFIG_BRCM_TRACING is not set +# CONFIG_BRCMDBG is not set +# CONFIG_HOSTAP is not set +# CONFIG_IPW2100 is not set +CONFIG_IPW2200=m +# CONFIG_IPW2200_MONITOR is not set +# CONFIG_IPW2200_QOS is not set +# CONFIG_IPW2200_DEBUG is not set +CONFIG_LIBIPW=m +# CONFIG_LIBIPW_DEBUG is not set +# CONFIG_IWLWIFI is not set +# CONFIG_IWL4965 is not set +# CONFIG_IWL3945 is not set +# CONFIG_LIBERTAS is not set +# CONFIG_HERMES is not set +# CONFIG_P54_COMMON is not set +CONFIG_RT2X00=y +# CONFIG_RT2400PCI is not set +# CONFIG_RT2500PCI is not set +# CONFIG_RT61PCI is not set +# CONFIG_RT2800PCI is not set +# CONFIG_RT2500USB is not set +# CONFIG_RT73USB is not set +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT33XX=y +CONFIG_RT2800USB_RT35XX=y +# CONFIG_RT2800USB_RT3573 is not set +CONFIG_RT2800USB_RT53XX=y +# CONFIG_RT2800USB_RT55XX is not set +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RT2800_LIB=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_DEBUG is not set +# CONFIG_WL_MEDIATEK is not set +CONFIG_RTL_CARDS=y +# CONFIG_RTL8192CE is not set +# CONFIG_RTL8192SE is not set +# CONFIG_RTL8192DE is not set +# CONFIG_RTL8723AE is not set +# CONFIG_RTL8723BE is not set +# CONFIG_RTL8188EE is not set +# CONFIG_RTL8192EE is not set +# CONFIG_RTL8821AE is not set +# CONFIG_RTL8192CU is not set +# CONFIG_WL_TI is not set +# CONFIG_ZD1211RW is not set +# CONFIG_MWIFIEX is not set +# CONFIG_CW1200 is not set +# CONFIG_RSI_91X is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_VMXNET3 is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_LEDS=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set +CONFIG_INPUT_MATRIXKMAP=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +CONFIG_KEYBOARD_IMX=y +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_BCM is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_CYPRESS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_FOCALTECH=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_MC13783_PWRBUTTON is not set +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_MPU3050 is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_REGULATOR_HAPTIC is not set +# CONFIG_INPUT_UINPUT is not set +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_DA9052_ONKEY is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2665_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=m +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVMEM=y +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SC16IS7XX is not set +CONFIG_SERIAL_BCM63XX=m +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_RP2 is not set +CONFIG_SERIAL_FSL_LPUART=y +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y +CONFIG_SERIAL_CONEXANT_DIGICOLOR=m +# CONFIG_SERIAL_ST_ASC is not set +# CONFIG_SERIAL_STM32 is not set +# CONFIG_TTY_PRINTK is not set +CONFIG_HVC_DRIVER=y +CONFIG_HVC_DCC=y +# CONFIG_VIRTIO_CONSOLE is not set +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +# CONFIG_IPMI_DEVICE_INTERFACE is not set +# CONFIG_IPMI_SI is not set +# CONFIG_IPMI_SSIF is not set +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +CONFIG_HW_RANDOM_VIRTIO=m +CONFIG_HW_RANDOM_TPM=m +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_RAW_DRIVER is not set +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS_I2C_ATMEL=m +# CONFIG_TCG_TIS_I2C_INFINEON is not set +# CONFIG_TCG_TIS_I2C_NUVOTON is not set +CONFIG_TCG_ATMEL=m +# CONFIG_TCG_TIS_ST33ZP24 is not set +CONFIG_DEVPORT=y +# CONFIG_XILLYBUS is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set +# CONFIG_I2C_GPIO is not set +CONFIG_I2C_IMX=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +CONFIG_I2C_SLAVE=y +# CONFIG_I2C_SLAVE_EEPROM is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_GPIO is not set +CONFIG_SPI_IMX=y +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_FSL_DSPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_ROCKCHIP is not set +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPMI is not set +# CONFIG_HSI is not set + +# +# PPS support +# +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_PINCTRL=y + +# +# Pin controllers +# +CONFIG_PINMUX=y +CONFIG_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_AMD is not set +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PINCTRL_IMX=y +CONFIG_PINCTRL_IMX6Q=y +CONFIG_PINCTRL_IMX6SL=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_GENERIC=y + +# +# Memory mapped GPIO drivers +# +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_EM is not set +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_GRGPIO is not set +CONFIG_GPIO_MXC=y +# CONFIG_GPIO_SCH311X is not set +# CONFIG_GPIO_SYSCON is not set +# CONFIG_GPIO_VX855 is not set +# CONFIG_GPIO_ZEVIO is not set + +# +# I2C GPIO expanders +# +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +CONFIG_GPIO_PCA953X=y +# CONFIG_GPIO_PCA953X_IRQ is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set + +# +# MFD GPIO expanders +# +# CONFIG_GPIO_DA9052 is not set + +# +# PCI GPIO expanders +# +# CONFIG_GPIO_AMD8111 is not set +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_RDC321X is not set + +# +# SPI GPIO expanders +# +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set + +# +# USB GPIO expanders +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_DA9052 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24257 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_SMB347 is not set +CONFIG_BATTERY_GAUGE_LTC2941=m +CONFIG_BATTERY_RT5033=m +# CONFIG_CHARGER_RT9455 is not set +CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_BRCMSTB is not set +CONFIG_POWER_RESET_GPIO=y +# CONFIG_POWER_RESET_GPIO_RESTART is not set +CONFIG_POWER_RESET_IMX=y +# CONFIG_POWER_RESET_LTC2952 is not set +CONFIG_POWER_RESET_RESTART=y +# CONFIG_POWER_RESET_VERSATILE is not set +CONFIG_POWER_RESET_UDOO=y +# CONFIG_POWER_RESET_SYSCON is not set +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set +# CONFIG_POWER_AVS is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_DA9052_ADC is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_MC13783_ADC is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_IBMAEM is not set +# CONFIG_SENSORS_IBMPEX is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX17135 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_HTU21 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +CONFIG_SENSORS_LM75=m +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +CONFIG_SENSORS_PWM_FAN=m +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_TC74 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +# CONFIG_THERMAL_WRITABLE_TRIPS is not set +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_GOV_FAIR_SHARE is not set +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_BANG_BANG is not set +# CONFIG_THERMAL_GOV_USER_SPACE is not set +# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set +CONFIG_CPU_THERMAL=y +CONFIG_CLOCK_THERMAL=y +# CONFIG_THERMAL_EMULATION is not set +CONFIG_IMX_THERMAL=y + +# +# Texas Instruments thermal drivers +# +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_DA9052_WATCHDOG is not set +# CONFIG_GPIO_WATCHDOG is not set +# CONFIG_XILINX_WATCHDOG is not set +# CONFIG_CADENCE_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set +CONFIG_IMX2_WDT=y +# CONFIG_ALIM7101_WDT is not set +# CONFIG_I6300ESB_WDT is not set +# CONFIG_MEN_A21_WDT is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +CONFIG_MFD_ATMEL_HLCDC=m +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_AXP20X is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_PMIC_DA903X is not set +CONFIG_PMIC_DA9052=y +# CONFIG_MFD_DA9052_SPI is not set +CONFIG_MFD_DA9052_I2C=y +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_DA9150 is not set +CONFIG_MFD_MXC_HDMI=y +# CONFIG_MFD_DLN2 is not set +CONFIG_MFD_MC13XXX=y +CONFIG_MFD_MC13XXX_SPI=y +CONFIG_MFD_MC13XXX_I2C=y +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_INTEL_SOC_PMIC is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX17135 is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_UCB1400_CORE is not set +# CONFIG_MFD_PM8921_CORE is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_RTSX_PCI is not set +CONFIG_MFD_RT5033=m +# CONFIG_MFD_RTSX_USB is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK808 is not set +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_SEC_CORE is not set +CONFIG_MFD_SI476X_CORE=y +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +CONFIG_REGULATOR_ANATOP=y +# CONFIG_REGULATOR_DA9052 is not set +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_REGULATOR_GPIO is not set +# CONFIG_REGULATOR_ISL9305 is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_MC13783 is not set +# CONFIG_REGULATOR_MC13892 is not set +CONFIG_REGULATOR_PFUZE100=y +# CONFIG_REGULATOR_PWM is not set +CONFIG_REGULATOR_RT5033=m +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_SDR_SUPPORT=y +CONFIG_MEDIA_RC_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_VIDEO_V4L2=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_VMALLOC=y +CONFIG_DVB_CORE=y +CONFIG_DVB_NET=y +# CONFIG_TTPCI_EEPROM is not set +CONFIG_DVB_MAX_ADAPTERS=8 +CONFIG_DVB_DYNAMIC_MINORS=y + +# +# Media drivers +# +CONFIG_RC_CORE=y +CONFIG_RC_MAP=y +CONFIG_RC_DECODERS=y +# CONFIG_LIRC is not set +CONFIG_IR_NEC_DECODER=y +CONFIG_IR_RC5_DECODER=y +CONFIG_IR_RC6_DECODER=y +CONFIG_IR_JVC_DECODER=y +CONFIG_IR_SONY_DECODER=y +CONFIG_IR_SANYO_DECODER=y +CONFIG_IR_SHARP_DECODER=y +CONFIG_IR_MCE_KBD_DECODER=y +CONFIG_IR_XMP_DECODER=y +CONFIG_RC_DEVICES=y +# CONFIG_RC_ATI_REMOTE is not set +# CONFIG_IR_HIX5HD2 is not set +# CONFIG_IR_IMON is not set +# CONFIG_IR_MCEUSB is not set +# CONFIG_IR_REDRAT3 is not set +# CONFIG_IR_STREAMZAP is not set +CONFIG_IR_IGORPLUGUSB=m +# CONFIG_IR_IGUANA is not set +# CONFIG_IR_TTUSBIR is not set +# CONFIG_RC_LOOPBACK is not set +# CONFIG_IR_GPIO_CIR is not set +CONFIG_MEDIA_USB_SUPPORT=y + +# +# Webcam devices +# +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=m +# CONFIG_USB_M5602 is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_DTCS033 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_JL2005BCD is not set +# CONFIG_USB_GSPCA_KINECT is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SE401 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +CONFIG_USB_GSPCA_SPCA500=m +CONFIG_USB_GSPCA_SPCA501=m +CONFIG_USB_GSPCA_SPCA505=m +CONFIG_USB_GSPCA_SPCA506=m +CONFIG_USB_GSPCA_SPCA508=m +CONFIG_USB_GSPCA_SPCA561=m +CONFIG_USB_GSPCA_SPCA1528=m +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STK1135 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TOPRO is not set +CONFIG_USB_GSPCA_TOUPTEK=m +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_USB_PWC is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +CONFIG_VIDEO_USBTV=y + +# +# Analog TV USB devices +# +# CONFIG_VIDEO_PVRUSB2 is not set +# CONFIG_VIDEO_HDPVR is not set +# CONFIG_VIDEO_USBVISION is not set +# CONFIG_VIDEO_STK1160_COMMON is not set +# CONFIG_VIDEO_GO7007 is not set + +# +# Analog/digital TV USB devices +# +# CONFIG_VIDEO_AU0828 is not set +# CONFIG_VIDEO_CX231XX is not set +# CONFIG_VIDEO_TM6000 is not set + +# +# Digital TV USB devices +# +# CONFIG_DVB_USB is not set +CONFIG_DVB_USB_V2=m +# CONFIG_DVB_USB_AF9015 is not set +# CONFIG_DVB_USB_AF9035 is not set +# CONFIG_DVB_USB_ANYSEE is not set +# CONFIG_DVB_USB_AU6610 is not set +# CONFIG_DVB_USB_AZ6007 is not set +# CONFIG_DVB_USB_CE6230 is not set +# CONFIG_DVB_USB_EC168 is not set +# CONFIG_DVB_USB_GL861 is not set +# CONFIG_DVB_USB_LME2510 is not set +# CONFIG_DVB_USB_MXL111SF is not set +CONFIG_DVB_USB_RTL28XXU=m +# CONFIG_DVB_USB_DVBSKY is not set +# CONFIG_DVB_TTUSB_BUDGET is not set +# CONFIG_DVB_TTUSB_DEC is not set +# CONFIG_SMS_USB_DRV is not set +# CONFIG_DVB_B2C2_FLEXCOP_USB is not set +# CONFIG_DVB_AS102 is not set + +# +# Webcam, TV (analog/digital) USB devices +# +# CONFIG_VIDEO_EM28XX is not set + +# +# Software defined radio USB devices +# +# CONFIG_USB_AIRSPY is not set +# CONFIG_USB_HACKRF is not set +# CONFIG_USB_MSI2500 is not set +# CONFIG_MEDIA_PCI_SUPPORT is not set +# CONFIG_V4L_PLATFORM_DRIVERS is not set +CONFIG_V4L_MEM2MEM_DRIVERS=y +# CONFIG_VIDEO_CODA is not set +# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set +# CONFIG_VIDEO_SH_VEU is not set +# CONFIG_V4L_TEST_DRIVERS is not set + +# +# Supported MMC/SDIO adapters +# +# CONFIG_SMS_SDIO_DRV is not set +CONFIG_RADIO_ADAPTERS=y +# CONFIG_RADIO_SI470X is not set +# CONFIG_RADIO_SI4713 is not set +# CONFIG_RADIO_SI476X is not set +# CONFIG_USB_MR800 is not set +# CONFIG_USB_DSBR is not set +# CONFIG_RADIO_MAXIRADIO is not set +# CONFIG_RADIO_SHARK is not set +# CONFIG_RADIO_SHARK2 is not set +# CONFIG_USB_KEENE is not set +# CONFIG_USB_RAREMONO is not set +# CONFIG_USB_MA901 is not set +# CONFIG_RADIO_TEA5764 is not set +# CONFIG_RADIO_SAA7706H is not set +# CONFIG_RADIO_TEF6862 is not set +# CONFIG_RADIO_WL1273 is not set + +# +# Texas Instruments WL128x FM driver (ST based) +# +# CONFIG_CYPRESS_FIRMWARE is not set + +# +# Media ancillary drivers (tuners, sensors, i2c, frontends) +# +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y +CONFIG_VIDEO_IR_I2C=y + +# +# Audio decoders, processors and mixers +# + +# +# RDS decoders +# + +# +# Video decoders +# + +# +# Video and audio decoders +# + +# +# Video encoders +# + +# +# Camera sensor devices +# + +# +# Flash devices +# + +# +# Video improvement chips +# + +# +# Audio/Video compression chips +# + +# +# Miscellaneous helper chips +# + +# +# Sensors used on soc_camera driver +# +CONFIG_MEDIA_TUNER=y +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA827X=y +CONFIG_MEDIA_TUNER_TDA18271=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_XC4000=y +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_MEDIA_TUNER_MC44S803=y +CONFIG_MEDIA_TUNER_FC0012=m +CONFIG_MEDIA_TUNER_FC0013=m +CONFIG_MEDIA_TUNER_E4000=m +CONFIG_MEDIA_TUNER_FC2580=m +CONFIG_MEDIA_TUNER_R820T=m + +# +# Multistandard (satellite) frontends +# + +# +# Multistandard (cable + terrestrial) frontends +# + +# +# DVB-S (satellite) frontends +# + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_RTL2830=m +CONFIG_DVB_RTL2832=m +CONFIG_DVB_RTL2832_SDR=m +# CONFIG_DVB_AS102_FE is not set + +# +# DVB-C (cable) frontends +# + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# + +# +# ISDB-T (terrestrial) frontends +# + +# +# ISDB-S (satellite) & ISDB-T (terrestrial) frontends +# + +# +# Digital terrestrial only tuners/PLL +# + +# +# SEC control devices for DVB-S +# + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set + +# +# Graphics support +# +CONFIG_FB_MXS=m +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +# CONFIG_IMX_IPUV3_CORE is not set +CONFIG_FB_MXC=y +CONFIG_FB_MXC_SYNC_PANEL=y +CONFIG_FB_MXC_LDB=y +# CONFIG_FB_MXC_MIPI_DSI is not set +CONFIG_FB_MXC_HDMI=y +CONFIG_FB_MXC_EDID=y +# CONFIG_FB_MXC_EINK_PANEL is not set +CONFIG_FB_MXS_SII902X=m +# CONFIG_FB_MXC_DCIC is not set +# CONFIG_HANNSTAR_CABC is not set + +# +# Direct Rendering Manager +# +CONFIG_DRM=y +CONFIG_DRM_KMS_HELPER=m +CONFIG_DRM_KMS_FB_HELPER=y +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +CONFIG_DRM_GEM_CMA_HELPER=y +CONFIG_DRM_KMS_CMA_HELPER=y + +# +# I2C encoder or helper chips +# +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_SIL164 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_PTN3460 is not set +# CONFIG_DRM_PS8622 is not set +# CONFIG_DRM_TDFX is not set +# CONFIG_DRM_R128 is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_DRM_AMDGPU is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_DRM_MGA is not set +# CONFIG_DRM_VIA is not set +# CONFIG_DRM_SAVAGE is not set +# CONFIG_DRM_VGEM is not set +CONFIG_DRM_VIVANTE=y +# CONFIG_DRM_EXYNOS is not set +# CONFIG_DRM_VMWGFX is not set +# CONFIG_DRM_UDL is not set +# CONFIG_DRM_AST is not set +# CONFIG_DRM_MGAG200 is not set +# CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_ARMADA is not set +CONFIG_DRM_ATMEL_HLCDC=m +# CONFIG_DRM_TILCDC is not set +# CONFIG_DRM_QXL is not set +# CONFIG_DRM_BOCHS is not set +# CONFIG_DRM_VIRTIO_GPU is not set +CONFIG_DRM_PANEL=y + +# +# Display Panels +# +CONFIG_DRM_PANEL_SIMPLE=m +# CONFIG_DRM_PANEL_LD9040 is not set +# CONFIG_DRM_PANEL_S6E8AA0 is not set +# CONFIG_DRM_STI is not set + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_IMX is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_I740 is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +CONFIG_FB_MX3=y +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SSD1307 is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=m +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI922X is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_PLATFORM is not set +# CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_LCD_AMS369FG06 is not set +# CONFIG_LCD_LMS501KF03 is not set +# CONFIG_LCD_HX8357 is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y +# CONFIG_BACKLIGHT_PWM is not set +# CONFIG_BACKLIGHT_DA9052 is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set +# CONFIG_VGASTATE is not set +CONFIG_VIDEOMODE_HELPERS=y +CONFIG_HDMI=y + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_DMAENGINE_PCM=y +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_COMPRESS_OFFLOAD=y +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_PROC_FS=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_MPU401_UART=m +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_PCI=y +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_AW2 is not set +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMIPCI is not set +CONFIG_SND_OXYGEN_LIB=m +# CONFIG_SND_OXYGEN is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CTXFI is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set +# CONFIG_SND_INDIGOIOX is not set +# CONFIG_SND_INDIGODJX is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_LOLA is not set +# CONFIG_SND_LX6464ES is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +CONFIG_SND_SE6X=m +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_YMFPCI is not set + +# +# HD-Audio +# +# CONFIG_SND_HDA_INTEL is not set +CONFIG_SND_HDA_PREALLOC_SIZE=64 +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_BCD2000 is not set +# CONFIG_SND_USB_POD is not set +# CONFIG_SND_USB_PODHD is not set +# CONFIG_SND_USB_TONEPORT is not set +# CONFIG_SND_USB_VARIAX is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_AC97_BUS=y +CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_DESIGNWARE_I2S is not set + +# +# SoC Audio for Freescale CPUs +# + +# +# Common SoC Audio options for Freescale CPUs: +# +CONFIG_SND_SOC_FSL_ASRC=y +CONFIG_SND_SOC_FSL_SAI=y +CONFIG_SND_SOC_FSL_SSI=y +CONFIG_SND_SOC_FSL_SPDIF=y +CONFIG_SND_SOC_FSL_ESAI=y +CONFIG_SND_SOC_FSL_HDMI=y +CONFIG_SND_SOC_IMX_PCM_DMA=y +CONFIG_SND_SOC_IMX_HDMI_DMA=y +CONFIG_SND_SOC_IMX_AUDMUX=y +CONFIG_SND_IMX_SOC=y + +# +# SoC Audio support for Freescale i.MX boards: +# +# CONFIG_SND_SOC_EUKREA_TLV320 is not set +# CONFIG_SND_SOC_IMX_WM8962 is not set +# CONFIG_SND_SOC_IMX_ES8328 is not set +CONFIG_SND_SOC_IMX_SGTL5000=y +CONFIG_SND_SOC_IMX_AC97_VT1613=y +CONFIG_SND_SOC_IMX_SPDIF=y +CONFIG_SND_SOC_IMX_HDMI=y +# CONFIG_SND_SOC_IMX_MC13783 is not set +# CONFIG_SND_SOC_FSL_ASOC_CARD is not set +# CONFIG_SND_SOC_QCOM is not set +CONFIG_SND_SOC_XTFPGA_I2S=m +CONFIG_SND_SOC_I2C_AND_SPI=y + +# +# CODEC drivers +# +# CONFIG_SND_SOC_AC97_CODEC is not set +# CONFIG_SND_SOC_ADAU1701 is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_AK4554 is not set +# CONFIG_SND_SOC_AK4642 is not set +# CONFIG_SND_SOC_AK5386 is not set +# CONFIG_SND_SOC_ALC5623 is not set +# CONFIG_SND_SOC_CS35L32 is not set +CONFIG_SND_SOC_CS42L51=m +CONFIG_SND_SOC_CS42L51_I2C=m +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_CS42L73 is not set +# CONFIG_SND_SOC_CS4265 is not set +# CONFIG_SND_SOC_CS4270 is not set +CONFIG_SND_SOC_CS4271=m +CONFIG_SND_SOC_CS4271_I2C=m +CONFIG_SND_SOC_CS4271_SPI=m +# CONFIG_SND_SOC_CS42XX8_I2C is not set +CONFIG_SND_SOC_HDMI_CODEC=y +# CONFIG_SND_SOC_ES8328 is not set +# CONFIG_SND_SOC_PCM1681 is not set +# CONFIG_SND_SOC_PCM1792A is not set +# CONFIG_SND_SOC_PCM512x_I2C is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +CONFIG_SND_SOC_RT5631=m +# CONFIG_SND_SOC_RT5677_SPI is not set +CONFIG_SND_SOC_SGTL5000=y +# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set +CONFIG_SND_SOC_SPDIF=y +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM2602_I2C is not set +# CONFIG_SND_SOC_SSM4567 is not set +CONFIG_SND_SOC_STA32X=m +# CONFIG_SND_SOC_STA350 is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS5086 is not set +# CONFIG_SND_SOC_TAS571X is not set +CONFIG_SND_SOC_TFA9879=m +CONFIG_SND_SOC_TLV320AIC23=m +CONFIG_SND_SOC_TLV320AIC23_I2C=m +CONFIG_SND_SOC_TLV320AIC23_SPI=m +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC3X is not set +CONFIG_SND_SOC_TS3A227E=m +CONFIG_SND_SOC_VT1613=y +# CONFIG_SND_SOC_WM8510 is not set +# CONFIG_SND_SOC_WM8523 is not set +# CONFIG_SND_SOC_WM8580 is not set +# CONFIG_SND_SOC_WM8711 is not set +# CONFIG_SND_SOC_WM8728 is not set +# CONFIG_SND_SOC_WM8731 is not set +# CONFIG_SND_SOC_WM8737 is not set +# CONFIG_SND_SOC_WM8741 is not set +# CONFIG_SND_SOC_WM8750 is not set +# CONFIG_SND_SOC_WM8753 is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8776 is not set +# CONFIG_SND_SOC_WM8804_I2C is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_WM8903 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_TPA6130A2 is not set +# CONFIG_SND_SIMPLE_CARD is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_AC97_BUS=y + +# +# HID support +# +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HIDRAW is not set +# CONFIG_UHID is not set +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_BETOP_FF is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_PRODIKEYS is not set +CONFIG_HID_CP2112=m +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_GT683R is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MAGICMOUSE is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +CONFIG_HID_PLANTRONICS=m +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THINGM is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_WIIMOTE is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# I2C HID support +# +# CONFIG_I2C_HID is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_OTG=y +CONFIG_USB_OTG_WHITELIST=y +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_OTG_FSM=y +# CONFIG_USB_ULPI_BUS is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_XHCI_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_PCI=y +CONFIG_USB_EHCI_MXC=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FUSBH200_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_UHCI_HCD is not set +CONFIG_USB_U132_HCD=m +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_IMX21_HCD is not set +# CONFIG_USB_HCD_TEST_MODE is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +CONFIG_USB_UAS=m + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_DWC2 is not set +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_OF=y +CONFIG_USB_CHIPIDEA_PCI=y +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +# CONFIG_USB_CHIPIDEA_DEBUG is not set +CONFIG_USB_ISP1760=m +CONFIG_USB_ISP1760_HCD=y +CONFIG_USB_ISP1761_UDC=y +# CONFIG_USB_ISP1760_HOST_ROLE is not set +# CONFIG_USB_ISP1760_GADGET_ROLE is not set +CONFIG_USB_ISP1760_DUAL_ROLE=y + +# +# USB port drivers +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_SIMPLE=m +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F81232=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MXUPORT=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_SAFE=m +# CONFIG_USB_SERIAL_SAFE_PADDED is not set +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_WWAN=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_XSENS_MT=m +CONFIG_USB_SERIAL_WISHBONE=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m +CONFIG_USB_SERIAL_DEBUG=m + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +CONFIG_USB_FTDI_ELAN=m +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +CONFIG_USB_EZUSB_FX2=m +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_CHAOSKEY is not set + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +CONFIG_NOP_USB_XCEIV=y +# CONFIG_AM335X_PHY_USB is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +CONFIG_USB_MXS_PHY=y +# CONFIG_USB_ULPI is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FSL_USB2 is not set +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +CONFIG_USB_BDC_UDC=m + +# +# Platform Support +# +CONFIG_USB_BDC_PCI=m +# CONFIG_USB_AMD5536UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET2280 is not set +# CONFIG_USB_GOKU is not set +# CONFIG_USB_EG20T is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=m +CONFIG_USB_F_ACM=m +CONFIG_USB_F_SS_LB=m +CONFIG_USB_U_SERIAL=m +CONFIG_USB_U_ETHER=m +CONFIG_USB_F_SERIAL=m +CONFIG_USB_F_OBEX=m +CONFIG_USB_F_ECM=m +CONFIG_USB_F_SUBSET=m +CONFIG_USB_F_RNDIS=m +CONFIG_USB_F_MASS_STORAGE=m +# CONFIG_USB_CONFIGFS is not set +CONFIG_USB_ZERO=m +# CONFIG_USB_ZERO_HNPTEST is not set +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_ETH_EEM is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_G_SERIAL=m +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set +# CONFIG_USB_LED_TRIG is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +CONFIG_MMC_SDHCI_ESDHC_IMX=y +# CONFIG_MMC_SDHCI_F_SDH30 is not set +# CONFIG_MMC_MXC is not set +# CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_VIA_SDMMC is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_USDHI6ROL0 is not set +CONFIG_MMC_TOSHIBA_PCI=m +# CONFIG_MMC_MTK is not set +# CONFIG_MEMSTICK is not set + +# +# MXC support drivers +# +CONFIG_MXC_IPU=y + +# +# MXC Vivante GPU support +# +CONFIG_MXC_GPU_VIV=y +CONFIG_MXC_IPU_V3=y + +# +# MXC VPU(Video Processing Unit) support +# +CONFIG_MXC_VPU=y +# CONFIG_MXC_VPU_DEBUG is not set +CONFIG_MX6_VPU_352M=y + +# +# MXC HDMI CEC (Consumer Electronics Control) support +# +CONFIG_MXC_HDMI_CEC=y + +# +# MXC MIPI Support +# +CONFIG_MXC_MIPI_CSI2=y + +# +# MXC Media Local Bus Driver +# +CONFIG_MXC_MLB=y +CONFIG_MXC_MLB150=m +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set + +# +# LED drivers +# +# CONFIG_LEDS_BCM6328 is not set +# CONFIG_LEDS_BCM6358 is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +CONFIG_LEDS_LP8860=m +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_DA9052 is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_MC13783 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TLC591XX is not set +# CONFIG_LEDS_LM355x is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_SYSCON is not set +# CONFIG_LEDS_PM8941_WLED is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +# CONFIG_LEDS_TRIGGER_TIMER is not set +# CONFIG_LEDS_TRIGGER_ONESHOT is not set +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_CPU is not set +CONFIG_LEDS_TRIGGER_GPIO=y +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +# CONFIG_EDAC is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_SYSTOHC_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_ABB5ZES3=m +# CONFIG_RTC_DRV_ABX80X is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12057 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +CONFIG_RTC_DRV_PCF8523=y +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_MCP795 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +CONFIG_RTC_DRV_DS1685_FAMILY=m +CONFIG_RTC_DRV_DS1685=y +# CONFIG_RTC_DRV_DS1689 is not set +# CONFIG_RTC_DRV_DS17285 is not set +# CONFIG_RTC_DRV_DS17485 is not set +# CONFIG_RTC_DRV_DS17885 is not set +# CONFIG_RTC_DS1685_PROC_REGS is not set +# CONFIG_RTC_DS1685_SYSFS_REGS is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_DA9052 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_IMXDI=y +# CONFIG_RTC_DRV_MC13XXX is not set +CONFIG_RTC_DRV_MXC=y +CONFIG_RTC_DRV_SNVS=y + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +# CONFIG_DW_DMAC is not set +# CONFIG_DW_DMAC_PCI is not set +# CONFIG_HSU_DMA_PCI is not set +CONFIG_MX3_IPU=y +CONFIG_MX3_IPU_IRQS=4 +CONFIG_MXC_PXP_V2=y +# CONFIG_MXC_PXP_V3 is not set +CONFIG_MXC_PXP_CLIENT_DEVICE=y +CONFIG_IMX_SDMA=y +# CONFIG_IMX_DMA is not set +CONFIG_MXS_DMA=y +CONFIG_FSL_EDMA=y +# CONFIG_NBPFAXI_DMA is not set +CONFIG_DMA_ENGINE=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DMA_OF=y + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +CONFIG_VIRT_DRIVERS=y +CONFIG_VIRTIO=m + +# +# Virtio drivers +# +CONFIG_VIRTIO_PCI=m +CONFIG_VIRTIO_PCI_LEGACY=y +CONFIG_VIRTIO_BALLOON=m +# CONFIG_VIRTIO_INPUT is not set +CONFIG_VIRTIO_MMIO=m +CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y + +# +# Microsoft Hyper-V guest support +# +# CONFIG_STAGING is not set +# CONFIG_CHROME_PLATFORMS is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_CDCE925 is not set +# CONFIG_CLK_QORIQ is not set +# CONFIG_COMMON_CLK_PWM is not set +# CONFIG_COMMON_CLK_PXA is not set +# CONFIG_COMMON_CLK_CDCE706 is not set + +# +# Hardware Spinlock drivers +# + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_MMIO=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_TIMER_SP804 is not set +# CONFIG_ATMEL_PIT is not set +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_SH_TIMER_MTU2 is not set +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_EM_TIMER_STI is not set +CONFIG_CLKSRC_IMX_GPT=y +# CONFIG_MAILBOX is not set +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +# CONFIG_ARM_SMMU is not set + +# +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# + +# +# SOC (System On Chip) specific Drivers +# +# CONFIG_SUNXI_SRAM is not set +# CONFIG_SOC_TI is not set +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +# CONFIG_IIO is not set +# CONFIG_NTB is not set +# CONFIG_VME_BUS is not set +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +# CONFIG_PWM_ATMEL_HLCDC_PWM is not set +# CONFIG_PWM_FSL_FTM is not set +CONFIG_PWM_IMX=y +# CONFIG_PWM_PCA9685 is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +# CONFIG_IPACK_BUS is not set +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +CONFIG_RESET_CONTROLLER=y +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +# CONFIG_GENERIC_PHY is not set +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set +# CONFIG_BCM_KONA_USB2_PHY is not set +CONFIG_POWERCAP=y +# CONFIG_MCB is not set +CONFIG_RAS=y +# CONFIG_THUNDERBOLT is not set + +# +# Android +# +# CONFIG_ANDROID is not set + +# +# Firmware Drivers +# +# CONFIG_FIRMWARE_MEMMAP is not set + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_EXT2_FS=m +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_DEFAULTS_TO_ORDERED=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=m +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_REISERFS_FS_XATTR=y +# CONFIG_REISERFS_FS_POSIX_ACL is not set +# CONFIG_REISERFS_FS_SECURITY is not set +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +# CONFIG_XFS_FS is not set +CONFIG_GFS2_FS=m +CONFIG_OCFS2_FS=m +CONFIG_OCFS2_FS_O2CB=m +CONFIG_OCFS2_DEBUG_MASKLOG=y +CONFIG_OCFS2_DEBUG_FS=y +CONFIG_BTRFS_FS=y +CONFIG_BTRFS_FS_POSIX_ACL=y +# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +CONFIG_BTRFS_FS_RUN_SANITY_TESTS=y +# CONFIG_BTRFS_DEBUG is not set +CONFIG_BTRFS_ASSERT=y +CONFIG_NILFS2_FS=m +# CONFIG_F2FS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_PRINT_QUOTA_WARNING=y +# CONFIG_QUOTA_DEBUG is not set +CONFIG_QUOTA_TREE=m +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set +CONFIG_QUOTACTL=y +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=y +CONFIG_CUSE=y +# CONFIG_OVERLAY_FS is not set + +# +# Caches +# +CONFIG_FSCACHE=y +# CONFIG_FSCACHE_STATS is not set +# CONFIG_FSCACHE_HISTOGRAM is not set +# CONFIG_FSCACHE_DEBUG is not set +# CONFIG_FSCACHE_OBJECT_LIST is not set +CONFIG_CACHEFILES=y +# CONFIG_CACHEFILES_DEBUG is not set +# CONFIG_CACHEFILES_HISTOGRAM is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-2" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_PROC_CHILDREN is not set +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=m +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V2=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +# CONFIG_NFS_SWAP is not set +CONFIG_NFS_V4_1=y +CONFIG_NFS_V4_2=y +CONFIG_PNFS_FILE_LAYOUT=y +CONFIG_PNFS_BLOCK=y +CONFIG_PNFS_FLEXFILE_LAYOUT=m +CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="home" +CONFIG_NFS_V4_1_MIGRATION=y +CONFIG_ROOT_NFS=y +CONFIG_NFS_FSCACHE=y +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +# CONFIG_NFSD_PNFS is not set +CONFIG_GRACE_PERIOD=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_SUNRPC_BACKCHANNEL=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_SUNRPC_DEBUG is not set +CONFIG_CEPH_FS=y +# CONFIG_CEPH_FSCACHE is not set +# CONFIG_CEPH_FS_POSIX_ACL is not set +CONFIG_CIFS=m +CONFIG_CIFS_STATS=y +# CONFIG_CIFS_STATS2 is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_CIFS_ACL=y +CONFIG_CIFS_DEBUG=y +# CONFIG_CIFS_DEBUG2 is not set +CONFIG_CIFS_DFS_UPCALL=y +CONFIG_CIFS_SMB2=y +# CONFIG_CIFS_SMB311 is not set +CONFIG_CIFS_FSCACHE=y +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +CONFIG_NLS_CODEPAGE_1250=y +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_2=y +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +CONFIG_NLS_ISO8859_15=m +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set + +# +# Compile-time checks and compiler options +# +# CONFIG_DEBUG_INFO is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHED_INFO is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_TIMER_STATS is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +# CONFIG_STACKTRACE is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set + +# +# RCU Debugging +# +# CONFIG_PROVE_RCU is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +# CONFIG_RCU_CPU_STALL_INFO is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +# CONFIG_FTRACE_SYSCALLS is not set +# CONFIG_TRACER_SNAPSHOT is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_UPROBE_EVENT is not set +# CONFIG_PROBE_EVENTS is not set +# CONFIG_TRACEPOINT_BENCHMARK is not set + +# +# Runtime Testing +# +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_ASYNC_RAID6_TEST is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_MEMTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARM_PTDUMP is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_LL is not set +CONFIG_DEBUG_IMX_UART_PORT=1 +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +# CONFIG_DEBUG_UART_8250 is not set +# CONFIG_DEBUG_UART_BCM63XX is not set +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set +# CONFIG_CORESIGHT is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_TRUSTED_KEYS is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +CONFIG_SECURITYFS=y +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_XOR_BLOCKS=y +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_ASYNC_PQ=m +CONFIG_ASYNC_RAID6_RECOV=m +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_PCOMP=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_AKCIPHER2=y +# CONFIG_CRYPTO_RSA is not set +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_USER=y +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_PCRYPT=y +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=y +# CONFIG_CRYPTO_MCRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +CONFIG_CRYPTO_TEST=m + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_ECHAINIV=m + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_CTS=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_LRW=y +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_XTS=y + +# +# Hash modes +# +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_VMAC=m + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRCT10DIF=y +CONFIG_CRYPTO_GHASH=y +# CONFIG_CRYPTO_POLY1305 is not set +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=y +CONFIG_CRYPTO_RMD128=y +CONFIG_CRYPTO_RMD160=y +CONFIG_CRYPTO_RMD256=y +CONFIG_CRYPTO_RMD320=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_TGR192=y +CONFIG_CRYPTO_WP512=y + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_BLOWFISH_COMMON=y +CONFIG_CRYPTO_CAMELLIA=y +CONFIG_CRYPTO_CAST_COMMON=y +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SALSA20=m +# CONFIG_CRYPTO_CHACHA20 is not set +CONFIG_CRYPTO_SEED=y +CONFIG_CRYPTO_SERPENT=y +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_ZLIB=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_842 is not set +CONFIG_CRYPTO_LZ4=y +CONFIG_CRYPTO_LZ4HC=y + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_DRBG_HMAC=y +# CONFIG_CRYPTO_DRBG_HASH is not set +# CONFIG_CRYPTO_DRBG_CTR is not set +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_USER_API=m +CONFIG_CRYPTO_USER_API_HASH=m +CONFIG_CRYPTO_USER_API_SKCIPHER=m +CONFIG_CRYPTO_USER_API_RNG=m +# CONFIG_CRYPTO_USER_API_AEAD is not set +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set +CONFIG_CRYPTO_DEV_FSL_CAAM=y +CONFIG_CRYPTO_DEV_FSL_CAAM_JR=y +CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE=9 +CONFIG_CRYPTO_DEV_FSL_CAAM_INTC=y +CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_COUNT_THLD=255 +CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD=2048 +CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=y +CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API=y +CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API=y +CONFIG_CRYPTO_DEV_FSL_CAAM_IMX=y +CONFIG_CRYPTO_DEV_FSL_CAAM_LE=y +# CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG is not set +# CONFIG_CRYPTO_DEV_SAHARA is not set +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m +CONFIG_PUBLIC_KEY_ALGO_RSA=m +CONFIG_X509_CERTIFICATE_PARSER=m +CONFIG_PKCS7_MESSAGE_PARSER=m +CONFIG_PKCS7_TEST_KEY=m +# CONFIG_ARM_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_RAID6_PQ=y +CONFIG_BITREVERSE=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_RATIONAL=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_STMP_DEVICE=y +CONFIG_PERCPU_RWSEM=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_CRC_CCITT=m +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=m +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +CONFIG_CRC7=m +CONFIG_LIBCRC32C=y +CONFIG_CRC8=m +# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_COMPRESS=y +CONFIG_LZ4HC_COMPRESS=y +CONFIG_LZ4_DECOMPRESS=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_IA64=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_GLOB=y +# CONFIG_GLOB_SELFTEST is not set +CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_AVERAGE=y +CONFIG_CLZ_TAB=y +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set +CONFIG_MPILIB=m +CONFIG_LIBFDT=y +CONFIG_OID_REGISTRY=y +CONFIG_FONT_SUPPORT=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_6x10 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_VIRTUALIZATION=y diff --git a/config/linux-udoo.config b/config/linux-udoo.config new file mode 100644 index 000000000..dc246b627 --- /dev/null +++ b/config/linux-udoo.config @@ -0,0 +1,3882 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.14.57 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_MIGHT_HAVE_PCI=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_GENERIC_BUG=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_HAVE_KERNEL_LZ4=y +# CONFIG_KERNEL_GZIP is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_XZ is not set +CONFIG_KERNEL_LZO=y +# CONFIG_KERNEL_LZ4 is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_FHANDLE is not set +# CONFIG_AUDIT is not set + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +CONFIG_KTIME_SCALAR=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +# CONFIG_IRQ_TIME_ACCOUNTING is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set + +# +# RCU Subsystem +# +CONFIG_TREE_PREEMPT_RCU=y +CONFIG_PREEMPT_RCU=y +CONFIG_RCU_STALL_COMMON=y +# CONFIG_RCU_USER_QS is not set +CONFIG_RCU_FANOUT=32 +CONFIG_RCU_FANOUT_LEAF=16 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_RCU_FAST_NO_HZ is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_BOOST is not set +# CONFIG_RCU_NOCB_CPU is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CGROUP_FREEZER is not set +# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CPUSETS is not set +# CONFIG_CGROUP_CPUACCT is not set +# CONFIG_RESOURCE_COUNTERS is not set +# CONFIG_CGROUP_PERF is not set +# CONFIG_CGROUP_SCHED is not set +# CONFIG_BLK_CGROUP is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +CONFIG_RELAY=y +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_EXPERT=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +# CONFIG_EMBEDDED is not set +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_SYSTEM_TRUSTED_KEYRING is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_JUMP_LABEL is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR is not set +CONFIG_CC_STACKPROTECTOR_NONE=y +# CONFIG_CC_STACKPROTECTOR_REGULAR is not set +# CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_MODULE_SIG is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_CMDLINE_PARSER is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +CONFIG_ARCH_MULTIPLATFORM=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM_NODT is not set +# CONFIG_ARCH_SHMOBILE_LEGACY is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C24XX is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP1 is not set + +# +# Multiple platform selection +# + +# +# CPU Core family selection +# +# CONFIG_ARCH_MULTI_V6 is not set +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_MULTI_V6_V7=y +# CONFIG_ARCH_MULTI_CPU_AUTO is not set +# CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_BCM is not set +# CONFIG_ARCH_BERLIN is not set +CONFIG_GPIO_PCA953X=y +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_HI3xxx is not set +# CONFIG_ARCH_KEYSTONE is not set +# CONFIG_ARCH_MSM_DT is not set +CONFIG_ARCH_MXC=y + +# +# Freescale i.MX support +# +# CONFIG_MXC_DEBUG_BOARD is not set +CONFIG_HAVE_IMX_RNG=y +CONFIG_HAVE_IMX_ANATOP=y +CONFIG_HAVE_IMX_GPC=y +CONFIG_HAVE_IMX_MMDC=y +CONFIG_HAVE_IMX_SRC=y +CONFIG_HAVE_IMX_MCC=y +CONFIG_HAVE_IMX_AMP=y + +# +# i.MX51 machines: +# +# CONFIG_MACH_IMX51_DT is not set +# CONFIG_MACH_MX51_BABBAGE is not set +# CONFIG_MACH_EUKREA_CPUIMX51SD is not set + +# +# Device tree only +# +# CONFIG_SOC_IMX50 is not set +# CONFIG_SOC_IMX53 is not set +CONFIG_SOC_IMX6=y +CONFIG_SOC_IMX6Q=y +CONFIG_SOC_IMX6SL=y +CONFIG_SOC_IMX6SX=y +# CONFIG_SOC_VF610 is not set + +# +# UDOO Boards +# +CONFIG_UDOO_QDL_HALT=y +# CONFIG_ARCH_OMAP3 is not set +# CONFIG_ARCH_OMAP4 is not set +# CONFIG_SOC_OMAP5 is not set +# CONFIG_SOC_AM33XX is not set +# CONFIG_SOC_AM43XX is not set +# CONFIG_SOC_DRA7XX is not set +# CONFIG_ARCH_ROCKCHIP is not set +# CONFIG_ARCH_SOCFPGA is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_STI is not set +# CONFIG_ARCH_SHMOBILE_MULTI is not set +# CONFIG_ARCH_SUNXI is not set +# CONFIG_ARCH_SIRF is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_VIRT is not set +# CONFIG_ARCH_WM8850 is not set +# CONFIG_ARCH_ZYNQ is not set + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_LPAE is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_ARM_VIRT_EXT=y +# CONFIG_SWP_EMULATE is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_KUSER_HELPERS=y +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_CACHE_L2X0=y +CONFIG_CACHE_PL310=y +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +CONFIG_ARM_NR_BANKS=8 +CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_PL310_ERRATA_588369 is not set +# CONFIG_ARM_ERRATA_643719 is not set +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_PL310_ERRATA_727915 is not set +# CONFIG_PL310_ERRATA_753970 is not set +CONFIG_ARM_ERRATA_754322=y +# CONFIG_ARM_ERRATA_754327 is not set +CONFIG_ARM_ERRATA_764369=y +CONFIG_PL310_ERRATA_769419=y +CONFIG_ARM_ERRATA_775420=y +# CONFIG_ARM_ERRATA_798181 is not set +# CONFIG_ARM_ERRATA_773022 is not set + +# +# Bus support +# +# CONFIG_PCI is not set +# CONFIG_PCI_SYSCALL is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_HAVE_SMP=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_ARM_CPU_TOPOLOGY=y +# CONFIG_SCHED_MC is not set +# CONFIG_SCHED_SMT is not set +CONFIG_HAVE_ARM_SCU=y +# CONFIG_HAVE_ARM_ARCH_TIMER is not set +CONFIG_HAVE_ARM_TWD=y +# CONFIG_MCPM is not set +# CONFIG_BIG_LITTLE is not set +# CONFIG_VMSPLIT_3G is not set +CONFIG_VMSPLIT_2G=y +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0x80000000 +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +# CONFIG_ARM_PSCI is not set +CONFIG_ARCH_NR_GPIO=0 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_HZ_FIXED=0 +CONFIG_HZ_100=y +# CONFIG_HZ_200 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +# CONFIG_HZ_500 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 +CONFIG_SCHED_HRTICK=y +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HW_PERF_EVENTS=y +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +CONFIG_MEMORY_ISOLATION=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_CROSS_MEMORY_ATTACH=y +# CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set +# CONFIG_ZBUD is not set +# CONFIG_ZSMALLOC is not set +CONFIG_FORCE_MAX_ZONEORDER=14 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +# CONFIG_XEN is not set + +# +# Boot options +# +CONFIG_USE_OF=y +CONFIG_ATAGS=y +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +# CONFIG_ARM_APPENDED_DTB is not set +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" +CONFIG_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_CMDLINE_EXTEND is not set +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +CONFIG_AUTO_ZRELADDR=y + +# +# CPU Power Management +# + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +# CONFIG_GENERIC_CPUFREQ_CPU0 is not set + +# +# ARM CPU frequency scaling drivers +# +CONFIG_ARM_IMX6Q_CPUFREQ=y +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y + +# +# ARM CPU Idle Drivers +# +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_NEON=y +CONFIG_KERNEL_MODE_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=m +CONFIG_COREDUMP=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM=y +CONFIG_PM_DEBUG=y +# CONFIG_PM_ADVANCED_DEBUG is not set +CONFIG_PM_TEST_SUSPEND=y +CONFIG_PM_SLEEP_DEBUG=y +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_HAS_OPP=y +CONFIG_PM_OPP=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +CONFIG_PM_GENERIC_DOMAINS_RUNTIME=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_CPU_PM=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +# CONFIG_IP_MULTIPLE_TABLES is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=m +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=m +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_VTI is not set +CONFIG_IPV6_SIT=m +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_GRE is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK_ACCT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NF_TABLES is not set +# CONFIG_NETFILTER_XTABLES is not set +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV4 is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set + +# +# IPv6: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV6 is not set +# CONFIG_IP6_NF_IPTABLES is not set +# CONFIG_BRIDGE_NF_EBTABLES is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +CONFIG_STP=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_HAVE_NET_DSA=y +CONFIG_VLAN_8021Q=m +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_VLAN_8021Q_MVRP is not set +# CONFIG_DECNET is not set +CONFIG_LLC=m +CONFIG_LLC2=m +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +CONFIG_6LOWPAN_IPHC=m +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=m +CONFIG_BATMAN_ADV=m +CONFIG_BATMAN_ADV_BLA=y +# CONFIG_BATMAN_ADV_DAT is not set +# CONFIG_BATMAN_ADV_NC is not set +# CONFIG_BATMAN_ADV_DEBUG is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_NET_MPLS_GSO is not set +# CONFIG_HSR is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +# CONFIG_CGROUP_NET_PRIO is not set +# CONFIG_CGROUP_NET_CLASSID is not set +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_JIT is not set +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +CONFIG_CAN=m +CONFIG_CAN_RAW=m +CONFIG_CAN_BCM=m +CONFIG_CAN_GW=m + +# +# CAN Device Drivers +# +# CONFIG_CAN_VCAN is not set +# CONFIG_CAN_SLCAN is not set +CONFIG_CAN_DEV=m +CONFIG_CAN_CALC_BITTIMING=y +# CONFIG_CAN_LEDS is not set +# CONFIG_CAN_AT91 is not set +# CONFIG_CAN_TI_HECC is not set +# CONFIG_CAN_MCP251X is not set +CONFIG_CAN_FLEXCAN=m +# CONFIG_CAN_GRCAN is not set +CONFIG_CAN_M_CAN=m +# CONFIG_CAN_SJA1000 is not set +# CONFIG_CAN_C_CAN is not set +# CONFIG_CAN_CC770 is not set + +# +# CAN USB interfaces +# +# CONFIG_CAN_EMS_USB is not set +# CONFIG_CAN_ESD_USB2 is not set +# CONFIG_CAN_KVASER_USB is not set +# CONFIG_CAN_PEAK_USB is not set +# CONFIG_CAN_8DEV_USB is not set +# CONFIG_CAN_SOFTING is not set +# CONFIG_CAN_DEBUG_DEVICES is not set +# CONFIG_IRDA is not set +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIBTUSB=m +# CONFIG_BT_HCIBTSDIO is not set +CONFIG_BT_HCIUART=m +# CONFIG_BT_HCIUART_H4 is not set +# CONFIG_BT_HCIUART_BCSP is not set +# CONFIG_BT_HCIUART_ATH3K is not set +# CONFIG_BT_HCIUART_LL is not set +# CONFIG_BT_HCIUART_3WIRE is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_MRVL is not set +# CONFIG_BT_ATH3K is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_CFG80211=y +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_WEXT=y +# CONFIG_LIB80211 is not set +CONFIG_MAC80211=y +CONFIG_MAC80211_HAS_RC=y +# CONFIG_MAC80211_RC_PID is not set +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +CONFIG_MAC80211_MESH=y +# CONFIG_MAC80211_LEDS is not set +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_MESSAGE_TRACING is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +CONFIG_CEPH_LIB=y +# CONFIG_CEPH_LIB_PRETTYDEBUG is not set +# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set +# CONFIG_NFC is not set +CONFIG_HAVE_BPF_JIT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FW_LOADER_USER_HELPER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_SOC_BUS=y +CONFIG_REGMAP=y +CONFIG_REGMAP_AC97=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_IRQ=y +CONFIG_DMA_SHARED_BUFFER=y +CONFIG_DMA_CMA=y + +# +# Default contiguous memory area size: +# +CONFIG_CMA_SIZE_MBYTES=320 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 +CONFIG_CMA_AREAS=7 + +# +# Bus devices +# +CONFIG_IMX_WEIM=y +# CONFIG_ARM_CCI is not set +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_DATAFLASH=y +# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set +# CONFIG_MTD_DATAFLASH_OTP is not set +CONFIG_MTD_M25P80=y +CONFIG_MTD_SST25L=y +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_DENALI is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_DOCG4 is not set +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_GPMI_NAND=y +# CONFIG_MTD_NAND_PLATFORM is not set +CONFIG_MTD_NAND_MXC=y +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set +CONFIG_MTD_SPI_NOR=y +CONFIG_SPI_FSL_QUADSPI=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_LIMIT=20 +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +# CONFIG_PROC_DEVICETREE is not set +# CONFIG_OF_SELFTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=m +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set + +# +# Misc devices +# +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +# CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ATMEL_SSC is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +CONFIG_SRAM=y +CONFIG_UDOO_ARD=y +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# + +# +# SCSI device support +# +CONFIG_SCSI_MOD=m +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_PROC_FS is not set + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_ATA=m +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +CONFIG_SATA_AHCI_PLATFORM=m +CONFIG_AHCI_IMX=m +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# +# CONFIG_SATA_MV is not set + +# +# PATA SFF controllers with BMDMA +# +CONFIG_PATA_IMX=m + +# +# PIO-only SFF controllers +# +# CONFIG_PATA_PLATFORM is not set + +# +# Generic fallback / legacy drivers +# +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +CONFIG_NETDEVICES=y +CONFIG_MII=m +CONFIG_NET_CORE=y +CONFIG_BONDING=m +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_NLMON is not set + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set +CONFIG_ETHERNET=y +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_CADENCE is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +# CONFIG_NET_VENDOR_FARADAY is not set +CONFIG_NET_VENDOR_FREESCALE=y +CONFIG_FEC=y +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_ETHOC is not set +# CONFIG_SH_ETH is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_AT803X_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_AX88179_178A=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_CDC_NCM=m +# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set +# CONFIG_USB_NET_CDC_MBIM is not set +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SR9700 is not set +# CONFIG_USB_NET_SR9800 is not set +# CONFIG_USB_NET_SMSC75XX is not set +# CONFIG_USB_NET_SMSC95XX is not set +# CONFIG_USB_NET_GL620A is not set +CONFIG_USB_NET_NET1080=m +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +CONFIG_USB_NET_CDC_SUBSET=m +# CONFIG_USB_ALI_M5632 is not set +# CONFIG_USB_AN2720 is not set +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +# CONFIG_USB_EPSON2888 is not set +# CONFIG_USB_KC2190 is not set +CONFIG_USB_NET_ZAURUS=m +# CONFIG_USB_NET_CX82310_ETH is not set +# CONFIG_USB_NET_KALMIA is not set +# CONFIG_USB_NET_QMI_WWAN is not set +# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_USB_SIERRA_NET is not set +# CONFIG_USB_VL600 is not set +CONFIG_WLAN=y +# CONFIG_LIBERTAS_THINFIRM is not set +# CONFIG_AT76C50X_USB is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8187 is not set +# CONFIG_MAC80211_HWSIM is not set +CONFIG_ATH_CARDS=m +# CONFIG_ATH_DEBUG is not set +# CONFIG_ATH9K is not set +# CONFIG_ATH9K_HTC is not set +# CONFIG_CARL9170 is not set +CONFIG_ATH6KL=m +CONFIG_ATH6KL_SDIO=m +# CONFIG_ATH6KL_USB is not set +# CONFIG_ATH6KL_DEBUG is not set +# CONFIG_AR5523 is not set +# CONFIG_ATH10K is not set +# CONFIG_WCN36XX is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +CONFIG_BRCMUTIL=m +# CONFIG_BRCMSMAC is not set +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_SDIO=y +# CONFIG_BRCMFMAC_USB is not set +# CONFIG_BRCM_TRACING is not set +# CONFIG_BRCMDBG is not set +# CONFIG_HOSTAP is not set +# CONFIG_LIBERTAS is not set +# CONFIG_P54_COMMON is not set +CONFIG_RT2X00=m +# CONFIG_RT2500USB is not set +# CONFIG_RT73USB is not set +CONFIG_RT2800USB=m +# CONFIG_RT2800USB_RT33XX is not set +# CONFIG_RT2800USB_RT35XX is not set +# CONFIG_RT2800USB_RT3573 is not set +CONFIG_RT2800USB_RT53XX=y +# CONFIG_RT2800USB_RT55XX is not set +# CONFIG_RT2800USB_UNKNOWN is not set +CONFIG_RT2800_LIB=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_DEBUG is not set +CONFIG_RTL_CARDS=m +# CONFIG_RTL8192CU is not set +# CONFIG_WL_TI is not set +# CONFIG_ZD1211RW is not set +# CONFIG_MWIFIEX is not set +# CONFIG_CW1200 is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set +CONFIG_INPUT_MATRIXKMAP=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_EVBUG=m + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +CONFIG_KEYBOARD_SNVS_PWRKEY=y +CONFIG_KEYBOARD_IMX=y +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_STMPE is not set +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_CYPRESS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +CONFIG_MOUSE_PS2_ELANTECH=y +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_DA9052 is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +CONFIG_TOUCHSCREEN_EGALAX=y +CONFIG_TOUCHSCREEN_ELAN=y +# CONFIG_TOUCHSCREEN_FUJITSU is not set +CONFIG_TOUCHSCREEN_GOODIX=m +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +CONFIG_TOUCHSCREEN_MAX11801=y +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_WM97XX is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +CONFIG_TOUCHSCREEN_MC13783=y +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +CONFIG_TOUCHSCREEN_TSC2007=y +# CONFIG_TOUCHSCREEN_W90X900 is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +CONFIG_TOUCHSCREEN_STMPE=y +# CONFIG_TOUCHSCREEN_SUR40 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=m +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_SERIO_OLPC_APSP is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +# CONFIG_SERIAL_SH_SCI is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +CONFIG_SERIAL_FSL_LPUART=y +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y +# CONFIG_SERIAL_ST_ASC is not set +# CONFIG_TTY_PRINTK is not set +CONFIG_FSL_OTP=y +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=m +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_HW_RANDOM_ATMEL is not set +# CONFIG_HW_RANDOM_IMX_RNG is not set +# CONFIG_HW_RANDOM_EXYNOS is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_IMX_SEMA4=y +CONFIG_IMX_MCC_TEST=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +# CONFIG_I2C_COMPAT is not set +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +# CONFIG_I2C_HELPER_AUTO is not set +# CONFIG_I2C_SMBUS is not set + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_GPIO is not set +CONFIG_I2C_IMX=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +CONFIG_SPI_BITBANG=y +# CONFIG_SPI_GPIO is not set +CONFIG_SPI_IMX=y +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_HSI is not set + +# +# PPS support +# +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_PINCTRL=y + +# +# Pin controllers +# +CONFIG_PINMUX=y +CONFIG_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_CAPRI is not set +CONFIG_PINCTRL_IMX=y +CONFIG_PINCTRL_IMX6Q=y +CONFIG_PINCTRL_IMX6SL=y +CONFIG_PINCTRL_IMX6SX=y +# CONFIG_PINCTRL_MSM8X74 is not set +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_GENERIC=y +# CONFIG_GPIO_DA9052 is not set + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_EM is not set +CONFIG_GPIO_MXC=y +# CONFIG_GPIO_RCAR is not set +# CONFIG_GPIO_SCH311X is not set +# CONFIG_GPIO_TS5500 is not set +# CONFIG_GPIO_GRGPIO is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X_IRQ is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set +# CONFIG_GPIO_STMPE is not set +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# LPC GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +# CONFIG_GPIO_BCM_KONA is not set + +# +# USB GPIO expanders: +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_GENERIC_ADC_BATTERY is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_DA9052 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +CONFIG_SABRESD_MAX8903=y +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_IMX6_USB_CHARGER is not set +# CONFIG_POWER_RESET is not set +# CONFIG_POWER_RESET_RESTART is not set +# CONFIG_POWER_AVS is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_DA9052_ADC is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_HTU21 is not set +# CONFIG_SENSORS_IIO_HWMON is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +CONFIG_SENSORS_LM75=m +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +CONFIG_SENSORS_MAX17135=y +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_MC13783_ADC is not set +# CONFIG_SENSORS_MAG3110 is not set +# CONFIG_MXC_MMA8451 is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_GOV_FAIR_SHARE is not set +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_USER_SPACE is not set +CONFIG_CPU_THERMAL=y +# CONFIG_THERMAL_EMULATION is not set +CONFIG_IMX_THERMAL=y +CONFIG_DEVICE_THERMAL=y + +# +# Texas Instruments thermal drivers +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_CORE is not set +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_DA9052_WATCHDOG is not set +# CONFIG_GPIO_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set +CONFIG_IMX2_WDT=y +# CONFIG_MEN_A21_WDT is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_PMIC_DA903X is not set +CONFIG_PMIC_DA9052=y +# CONFIG_MFD_DA9052_SPI is not set +CONFIG_MFD_DA9052_I2C=y +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9063 is not set +CONFIG_MFD_MXC_HDMI=y +# CONFIG_MFD_MXC_HDMI_ANDROID is not set +CONFIG_MFD_MC13XXX=y +CONFIG_MFD_MC13XXX_SPI=y +CONFIG_MFD_MC13XXX_I2C=y +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +CONFIG_MFD_MAX17135=y +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_UCB1400_CORE is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_SEC_CORE is not set +CONFIG_MFD_SI476X_CORE=y +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +CONFIG_MFD_STMPE=y + +# +# STMicroelectronics STMPE Interface Drivers +# +CONFIG_STMPE_I2C=y +# CONFIG_STMPE_SPI is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_TDA1997X is not set +# CONFIG_VEXPRESS_CONFIG is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +CONFIG_REGULATOR_ANATOP=y +CONFIG_REGULATOR_DA9052=y +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_REGULATOR_GPIO is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8755 is not set +CONFIG_REGULATOR_LTC3676=m +# CONFIG_REGULATOR_MAX1586 is not set +CONFIG_REGULATOR_MAX17135=y +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +CONFIG_REGULATOR_MC13XXX_CORE=y +CONFIG_REGULATOR_MC13783=y +CONFIG_REGULATOR_MC13892=y +CONFIG_REGULATOR_PFUZE100=y +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set +# CONFIG_MEDIA_RADIO_SUPPORT is not set +CONFIG_MEDIA_RC_SUPPORT=y +# CONFIG_MEDIA_CONTROLLER is not set +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_V4L2_MEM2MEM_DEV=y +CONFIG_VIDEOBUF_GEN=y +CONFIG_VIDEOBUF_DMA_CONTIG=y +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_DMA_CONTIG=y +CONFIG_VIDEOBUF2_VMALLOC=m +# CONFIG_TTPCI_EEPROM is not set + +# +# Media drivers +# +CONFIG_RC_CORE=y +CONFIG_RC_MAP=y +CONFIG_RC_DECODERS=y +# CONFIG_LIRC is not set +CONFIG_IR_NEC_DECODER=y +CONFIG_IR_RC5_DECODER=y +CONFIG_IR_RC6_DECODER=y +CONFIG_IR_JVC_DECODER=y +CONFIG_IR_SONY_DECODER=y +CONFIG_IR_RC5_SZ_DECODER=y +CONFIG_IR_SANYO_DECODER=y +CONFIG_IR_MCE_KBD_DECODER=y +CONFIG_RC_DEVICES=y +# CONFIG_RC_ATI_REMOTE is not set +# CONFIG_IR_IMON is not set +# CONFIG_IR_MCEUSB is not set +# CONFIG_IR_REDRAT3 is not set +# CONFIG_IR_STREAMZAP is not set +# CONFIG_IR_IGUANA is not set +# CONFIG_IR_TTUSBIR is not set +# CONFIG_RC_LOOPBACK is not set +CONFIG_IR_GPIO_CIR=y +CONFIG_MEDIA_USB_SUPPORT=y + +# +# Webcam devices +# +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=m +# CONFIG_USB_M5602 is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_JL2005BCD is not set +# CONFIG_USB_GSPCA_KINECT is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SE401 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SPCA1528 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STK1135 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TOPRO is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_USB_PWC is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +# CONFIG_VIDEO_USBTV is not set + +# +# Webcam, TV (analog/digital) USB devices +# +# CONFIG_VIDEO_EM28XX is not set +CONFIG_V4L_PLATFORM_DRIVERS=y +# CONFIG_VIDEO_TIMBERDALE is not set +CONFIG_VIDEO_MXC_OUTPUT=y +CONFIG_VIDEO_MXC_CAPTURE=m +CONFIG_VIDEO_V4L2_MXC_INT_DEVICE=m + +# +# MXC Camera/V4L2 PRP Features support +# +CONFIG_VIDEO_MXC_IPU_CAMERA=y +# CONFIG_MXC_TVIN_TDA1997X is not set +CONFIG_MXC_CAMERA_OV5640=m +CONFIG_MXC_CAMERA_OV5642=m +CONFIG_MXC_CAMERA_OV5640_MIPI=m +CONFIG_MXC_TVIN_ADV7180=m +CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m +CONFIG_MXC_IPU_PRP_ENC=m +CONFIG_MXC_IPU_CSI_ENC=m +CONFIG_VIDEO_MXC_IPU_OUTPUT=y +CONFIG_VIDEO_MXC_PXP_V4L2=y +CONFIG_VIDEO_MXC_CSI_CAMERA=m +CONFIG_MXC_VADC=m +CONFIG_SOC_CAMERA=y +# CONFIG_SOC_CAMERA_PLATFORM is not set +CONFIG_VIDEO_MX3=y +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set +# CONFIG_VIDEO_SH_MOBILE_CEU is not set +CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_CODA=y +# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set +# CONFIG_VIDEO_SH_VEU is not set +# CONFIG_V4L_TEST_DRIVERS is not set + +# +# Supported MMC/SDIO adapters +# +# CONFIG_CYPRESS_FIRMWARE is not set + +# +# Media ancillary drivers (tuners, sensors, i2c, frontends) +# +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_VIDEO_IR_I2C=y + +# +# Audio decoders, processors and mixers +# + +# +# RDS decoders +# + +# +# Video decoders +# + +# +# Video and audio decoders +# + +# +# Video encoders +# + +# +# Camera sensor devices +# + +# +# Flash devices +# + +# +# Video improvement chips +# + +# +# Audio/Video compression chips +# + +# +# Miscellaneous helper chips +# + +# +# Sensors used on soc_camera driver +# + +# +# soc_camera sensor drivers +# +# CONFIG_SOC_CAMERA_IMX074 is not set +# CONFIG_SOC_CAMERA_MT9M001 is not set +# CONFIG_SOC_CAMERA_MT9M111 is not set +# CONFIG_SOC_CAMERA_MT9T031 is not set +# CONFIG_SOC_CAMERA_MT9T112 is not set +# CONFIG_SOC_CAMERA_MT9V022 is not set +CONFIG_SOC_CAMERA_OV2640=y +# CONFIG_SOC_CAMERA_OV5642 is not set +# CONFIG_SOC_CAMERA_OV6650 is not set +# CONFIG_SOC_CAMERA_OV772X is not set +# CONFIG_SOC_CAMERA_OV9640 is not set +# CONFIG_SOC_CAMERA_OV9740 is not set +# CONFIG_SOC_CAMERA_RJ54N1 is not set +# CONFIG_SOC_CAMERA_TW9910 is not set + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set + +# +# Graphics support +# +CONFIG_FB_TFT=m +CONFIG_FB_TFT_AGM1264K_FL=m +CONFIG_FB_TFT_BD663474=m +CONFIG_FB_TFT_HX8340BN=m +CONFIG_FB_TFT_HX8347D=m +CONFIG_FB_TFT_HX8353D=m +CONFIG_FB_TFT_ILI9320=m +CONFIG_FB_TFT_ILI9325=m +CONFIG_FB_TFT_ILI9340=m +CONFIG_FB_TFT_ILI9341=m +CONFIG_FB_TFT_ILI9481=m +CONFIG_FB_TFT_ILI9486=m +CONFIG_FB_TFT_PCD8544=m +CONFIG_FB_TFT_RA8875=m +CONFIG_FB_TFT_S6D02A1=m +CONFIG_FB_TFT_S6D1121=m +CONFIG_FB_TFT_SSD1289=m +CONFIG_FB_TFT_SSD1306=m +CONFIG_FB_TFT_SSD1331=m +CONFIG_FB_TFT_SSD1351=m +CONFIG_FB_TFT_ST7735R=m +CONFIG_FB_TFT_TINYLCD=m +CONFIG_FB_TFT_TLS8204=m +CONFIG_FB_TFT_UC1701=m +CONFIG_FB_TFT_UPD161704=m +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m +CONFIG_DRM=y +CONFIG_DRM_VIVANTE=y +# CONFIG_DRM_EXYNOS is not set +# CONFIG_DRM_UDL is not set +# CONFIG_DRM_ARMADA is not set +# CONFIG_DRM_RCAR_DU is not set +# CONFIG_DRM_SHMOBILE is not set +# CONFIG_DRM_TILCDC is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_VIDEOMODE_HELPERS=y +CONFIG_HDMI=y +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_IMAGEBLIT=m +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=m +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +CONFIG_FB_BACKLIGHT=y +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_IMX is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_TMIO is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_GOLDFISH is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +CONFIG_FB_MX3=y +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +CONFIG_FB_MXS=y +# CONFIG_FB_SIMPLE is not set +# CONFIG_EXYNOS_VIDEO is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_LCD_L4F00242T03=y +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI922X is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +CONFIG_LCD_PLATFORM=y +# CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_LCD_AMS369FG06 is not set +# CONFIG_LCD_LMS501KF03 is not set +# CONFIG_LCD_HX8357 is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y +CONFIG_BACKLIGHT_PWM=y +# CONFIG_BACKLIGHT_DA9052 is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set +CONFIG_FB_MXC=y +CONFIG_FB_MXC_SYNC_PANEL=y +# CONFIG_FB_MXC_TVOUT_ADV739X is not set +CONFIG_FB_MXC_LDB=y +CONFIG_FB_MXC_MIPI_DSI=y +CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL=y +CONFIG_FB_MXC_HDMI=y +CONFIG_FB_MXC_EDID=y +CONFIG_FB_MXC_EINK_PANEL=y +# CONFIG_FB_MXC_EINK_AUTO_UPDATE_MODE is not set +CONFIG_FB_MXS_SII902X=y +CONFIG_FB_MXC_DCIC=m +CONFIG_HANNSTAR_CABC=y +# CONFIG_FB_MXS_TDA19988 is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_FB_SSD1307 is not set +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_DMAENGINE_PCM=y +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_COMPRESS_OFFLOAD=y +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_HIFACE is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_AC97_BUS=y +CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_DESIGNWARE_I2S is not set + +# +# SoC Audio for Freescale CPUs +# + +# +# Common SoC Audio options for Freescale CPUs: +# +# CONFIG_SND_SOC_FSL_ASRC is not set +CONFIG_SND_SOC_FSL_SAI=y +CONFIG_SND_SOC_FSL_SSI=y +CONFIG_SND_SOC_FSL_SPDIF=y +# CONFIG_SND_SOC_FSL_ESAI is not set +CONFIG_SND_SOC_FSL_UTILS=y +CONFIG_SND_SOC_FSL_HDMI=y +CONFIG_SND_SOC_IMX_PCM_DMA=y +CONFIG_SND_SOC_IMX_AUDMUX=y +CONFIG_SND_IMX_SOC=y +CONFIG_SND_SOC_IMX_HDMI_DMA=y + +# +# SoC Audio support for Freescale i.MX boards: +# +# CONFIG_SND_SOC_IMX_CS42888 is not set +# CONFIG_SND_SOC_IMX_WM8962 is not set +# CONFIG_SND_SOC_IMX_SGTL5000 is not set +CONFIG_SND_SOC_IMX_AC97_VT1613=y +CONFIG_SND_SOC_IMX_MQS=y +CONFIG_SND_SOC_IMX_SPDIF=y +# CONFIG_SND_SOC_IMX_MC13783 is not set +CONFIG_SND_SOC_IMX_HDMI=y +# CONFIG_SND_SOC_IMX_SI476X is not set +# CONFIG_SND_SOC_IMX_TDA19988 is not set +# CONFIG_SND_SOC_IMX_TDA1997X is not set +CONFIG_SND_SOC_I2C_AND_SPI=y +CONFIG_SND_SOC_CS42XX8=m +CONFIG_SND_SOC_CS42XX8_I2C=m +CONFIG_SND_SOC_FSL_MQS=y +CONFIG_SND_SOC_HDMI_CODEC=y +CONFIG_SND_SOC_VT1613=y +# CONFIG_SND_SIMPLE_CARD is not set +# CONFIG_SOUND_PRIME is not set +CONFIG_AC97_BUS=y + +# +# HID support +# +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HIDRAW is not set +# CONFIG_UHID is not set +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_HUION is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO_TPKBD is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MAGICMOUSE is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THINGM is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_WIIMOTE is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set + +# +# USB HID support +# +CONFIG_USB_HID=m +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set + +# +# I2C HID support +# +# CONFIG_I2C_HID is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=m +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=m +CONFIG_USB_DEBUG=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_FSM is not set +CONFIG_USB_MON=m +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_XHCI_HCD is not set +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_MXC=m +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FUSBH200_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_IMX21_HCD is not set +# CONFIG_USB_HCD_TEST_MODE is not set +# CONFIG_USB_RENESAS_USBHS is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_DWC2 is not set +CONFIG_USB_CHIPIDEA=m +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +# CONFIG_USB_CHIPIDEA_DEBUG is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_SIMPLE is not set +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +CONFIG_USB_SERIAL_FTDI_SIO=m +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_F81232 is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_METRO is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MXUPORT is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +# CONFIG_USB_SERIAL_PL2303 is not set +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +CONFIG_USB_SERIAL_WWAN=m +CONFIG_USB_SERIAL_OPTION=m +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_XSENS_MT is not set +# CONFIG_USB_SERIAL_WISHBONE is not set +# CONFIG_USB_SERIAL_ZTE is not set +# CONFIG_USB_SERIAL_SSU100 is not set +# CONFIG_USB_SERIAL_QT2 is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +CONFIG_USB_EHSET_TEST_FIXTURE=m +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HSIC_USB3503 is not set + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +CONFIG_NOP_USB_XCEIV=y +# CONFIG_AM335X_PHY_USB is not set +# CONFIG_SAMSUNG_USB2PHY is not set +# CONFIG_SAMSUNG_USB3PHY is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +CONFIG_USB_MXS_PHY=y +# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_ULPI is not set +CONFIG_USB_GADGET=m +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FSL_USB2 is not set +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_S3C_HSOTG is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=m +CONFIG_USB_F_ACM=m +CONFIG_USB_F_SS_LB=m +CONFIG_USB_U_SERIAL=m +CONFIG_USB_U_ETHER=m +CONFIG_USB_F_SERIAL=m +CONFIG_USB_F_OBEX=m +CONFIG_USB_F_NCM=m +CONFIG_USB_F_ECM=m +CONFIG_USB_F_EEM=m +CONFIG_USB_F_SUBSET=m +CONFIG_USB_F_RNDIS=m +CONFIG_USB_F_MASS_STORAGE=m +CONFIG_USB_F_FS=m +CONFIG_USB_CONFIGFS=m +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_ACM=y +CONFIG_USB_CONFIGFS_OBEX=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_ECM=y +CONFIG_USB_CONFIGFS_ECM_SUBSET=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_EEM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_LB_SS=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_ZERO=m +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_ETH_EEM is not set +CONFIG_USB_G_NCM=m +CONFIG_USB_GADGETFS=m +# CONFIG_USB_FUNCTIONFS is not set +CONFIG_USB_MASS_STORAGE=m +# CONFIG_FSL_UTP is not set +CONFIG_USB_G_SERIAL=m +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_UNSAFE_RESUME=y +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +CONFIG_MMC_SDHCI_PLTFM=y +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +CONFIG_MMC_SDHCI_ESDHC_IMX=y +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_MXC is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set + +# +# MXC support drivers +# +CONFIG_MXC_IPU=y + +# +# MXC Vivante GPU support +# +CONFIG_MXC_GPU_VIV=y +CONFIG_MXC_IPU_V3=y + +# +# MXC VPU(Video Processing Unit) support +# +CONFIG_MXC_VPU=y +# CONFIG_MXC_VPU_DEBUG is not set +# CONFIG_MX6_VPU_352M is not set + +# +# MXC HDMI CEC (Consumer Electronics Control) support +# +# CONFIG_MXC_HDMI_CEC is not set + +# +# MXC MIPI Support +# +CONFIG_MXC_MIPI_CSI2=y + +# +# MXC Media Local Bus Driver +# +CONFIG_MXC_MLB=y +CONFIG_MXC_MLB150=m +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_PCA9685 is not set +# CONFIG_LEDS_DA9052 is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_MC13783 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_OT200 is not set +# CONFIG_LEDS_BLINKM is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +# CONFIG_LEDS_TRIGGER_CPU is not set +CONFIG_LEDS_TRIGGER_GPIO=y +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_EDAC is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12057 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_RX4581 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DA9052 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_DS2404 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_IMXDI is not set +CONFIG_RTC_DRV_MC13XXX=y +CONFIG_RTC_DRV_MXC=y +CONFIG_RTC_DRV_SNVS=y +# CONFIG_RTC_DRV_MOXART is not set + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +# CONFIG_DW_DMAC_CORE is not set +# CONFIG_DW_DMAC is not set +CONFIG_MX3_IPU=y +CONFIG_MX3_IPU_IRQS=4 +CONFIG_MXC_PXP_V2=y +CONFIG_MXC_PXP_CLIENT_DEVICE=y +# CONFIG_TIMB_DMA is not set +CONFIG_IMX_SDMA=y +# CONFIG_IMX_DMA is not set +CONFIG_MXS_DMA=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_VIRT_DRIVERS is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_USBIP_CORE is not set +# CONFIG_W35UND is not set +# CONFIG_PRISM2_USB is not set +# CONFIG_ECHO is not set +# CONFIG_COMEDI is not set +# CONFIG_RTLLIB is not set +# CONFIG_R8712U is not set +# CONFIG_R8188EU is not set +# CONFIG_RTS5139 is not set +# CONFIG_TRANZPORT is not set +# CONFIG_LINE6_USB is not set +# CONFIG_USB_SERIAL_QUATECH2 is not set +# CONFIG_VT6656 is not set + +# +# IIO staging drivers +# + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16204 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16220 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_LIS3L02DQ is not set + +# +# Analog to digital converters +# +# CONFIG_AD7291 is not set +# CONFIG_AD7606 is not set +# CONFIG_AD799X is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7280 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Direct Digital Synthesis +# +# CONFIG_AD5930 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_AD9850 is not set +# CONFIG_AD9852 is not set +# CONFIG_AD9910 is not set +# CONFIG_AD9951 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16060 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set + +# +# Light sensors +# +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_ISL29028 is not set +# CONFIG_TSL2583 is not set +# CONFIG_TSL2x7x is not set + +# +# Magnetometer sensors +# +# CONFIG_SENSORS_HMC5843 is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7753 is not set +# CONFIG_ADE7754 is not set +# CONFIG_ADE7758 is not set +# CONFIG_ADE7759 is not set +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set + +# +# Triggers - standalone +# +# CONFIG_IIO_SIMPLE_DUMMY is not set +# CONFIG_USB_ENESTORAGE is not set +# CONFIG_BCM_WIMAX is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +CONFIG_STAGING_MEDIA=y +# CONFIG_VIDEO_GO7007 is not set +# CONFIG_USB_MSI3101 is not set +# CONFIG_VIDEO_TCM825X is not set +# CONFIG_USB_SN9C102 is not set + +# +# Android +# +# CONFIG_ANDROID is not set +# CONFIG_USB_WPAN_HCD is not set +# CONFIG_WIMAX_GDM72XX is not set +# CONFIG_LTE_GDM724X is not set +# CONFIG_CED1401 is not set +# CONFIG_DRM_IMX is not set +# CONFIG_DGRP is not set +# CONFIG_MTD_SPINAND_MT29F is not set +# CONFIG_LUSTRE_FS is not set +# CONFIG_XILLYBUS is not set +# CONFIG_DGAP is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_QCOM is not set + +# +# Hardware Spinlock drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_MMIO=y +# CONFIG_MAILBOX is not set +# CONFIG_IOMMU_SUPPORT is not set + +# +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +CONFIG_IIO=y +# CONFIG_IIO_BUFFER is not set +# CONFIG_IIO_TRIGGER is not set + +# +# Accelerometers +# +# CONFIG_BMA180 is not set +# CONFIG_IIO_ST_ACCEL_3AXIS is not set +# CONFIG_KXSD9 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7266 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_EXYNOS_ADC is not set +# CONFIG_MAX1363 is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3422 is not set +# CONFIG_NAU7802 is not set +# CONFIG_TI_ADC081C is not set +CONFIG_VF610_ADC=y + +# +# Amplifiers +# +# CONFIG_AD8366 is not set + +# +# Hid Sensor IIO Common +# + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5686 is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD7303 is not set +# CONFIG_MAX517 is not set +# CONFIG_MCP4725 is not set + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +# CONFIG_AD9523 is not set + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +# CONFIG_ADF4350 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set +# CONFIG_IIO_ST_GYRO_3AXIS is not set +# CONFIG_ITG3200 is not set + +# +# Humidity sensors +# +# CONFIG_DHT11 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_INV_MPU6050_IIO is not set + +# +# Light sensors +# +# CONFIG_ADJD_S311 is not set +# CONFIG_APDS9300 is not set +# CONFIG_CM32181 is not set +# CONFIG_CM36651 is not set +# CONFIG_GP2AP020A00F is not set +# CONFIG_TCS3472 is not set +# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_TSL4531 is not set +# CONFIG_VCNL4000 is not set + +# +# Magnetometer sensors +# +# CONFIG_AK8975 is not set +# CONFIG_MAG3110 is not set +# CONFIG_IIO_ST_MAGN_3AXIS is not set + +# +# Inclinometer sensors +# + +# +# Pressure sensors +# +# CONFIG_MPL3115 is not set +# CONFIG_IIO_ST_PRESS is not set + +# +# Temperature sensors +# +# CONFIG_TMP006 is not set +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +CONFIG_PWM_IMX=y +# CONFIG_PWM_PCA9685 is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +# CONFIG_IPACK_BUS is not set +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RESET_GPIO=y +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +# CONFIG_GENERIC_PHY is not set +# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set +# CONFIG_PHY_EXYNOS_DP_VIDEO is not set +# CONFIG_POWERCAP is not set + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT23=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set +# CONFIG_QUOTA_DEBUG is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set +CONFIG_QUOTACTL=y +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=m +# CONFIG_CUSE is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=m +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_UBIFS_FS=m +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_F2FS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=m +CONFIG_NFS_V2=m +CONFIG_NFS_V3=m +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=m +# CONFIG_NFS_SWAP is not set +# CONFIG_NFS_V4_1 is not set +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +CONFIG_NLS_ISO8859_15=m +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=7 +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_DYNAMIC_DEBUG is not set + +# +# Compile-time checks and compiler options +# +# CONFIG_DEBUG_INFO is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +CONFIG_DEBUG_PREEMPT=y + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set + +# +# RCU Debugging +# +# CONFIG_PROVE_RCU_DELAY is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +CONFIG_RCU_CPU_STALL_VERBOSE=y +# CONFIG_RCU_CPU_STALL_INFO is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set + +# +# Runtime Testing +# +# CONFIG_LKDTM is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_TEST_MODULE is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARM_PTDUMP is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_LL is not set +CONFIG_DEBUG_IMX_UART_PORT=1 +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +# CONFIG_DEBUG_UART_PL01X is not set +# CONFIG_DEBUG_UART_8250 is not set +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_USER=y +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +CONFIG_CRYPTO_TEST=m + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_SEQIV=y + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_CTS=y +CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_LRW=y +# CONFIG_CRYPTO_PCBC is not set +CONFIG_CRYPTO_XTS=y + +# +# Hash modes +# +# CONFIG_CRYPTO_CMAC is not set +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +CONFIG_CRYPTO_CRCT10DIF=y +CONFIG_CRYPTO_GHASH=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=y +CONFIG_CRYPTO_RMD128=y +CONFIG_CRYPTO_RMD160=y +CONFIG_CRYPTO_RMD256=y +CONFIG_CRYPTO_RMD320=y +CONFIG_CRYPTO_SHA1=y +# CONFIG_CRYPTO_SHA1_ARM is not set +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_TGR192=y +CONFIG_CRYPTO_WP512=y + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_AES_ARM is not set +# CONFIG_CRYPTO_AES_ARM_BS is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_BLOWFISH_COMMON=y +CONFIG_CRYPTO_CAMELLIA=y +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=m +# CONFIG_CRYPTO_ZLIB is not set +CONFIG_CRYPTO_LZO=m +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_FSL_CAAM is not set +# CONFIG_CRYPTO_DEV_FSL_CAAM_SM is not set +# CONFIG_CRYPTO_DEV_SAHARA is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_RATIONAL=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_STMP_DEVICE=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_CRC_CCITT=m +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=m +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +CONFIG_CRC7=m +CONFIG_LIBCRC32C=y +# CONFIG_CRC8 is not set +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=m +CONFIG_ZLIB_DEFLATE=m +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_AVERAGE=y +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set +CONFIG_OID_REGISTRY=m +CONFIG_FONT_SUPPORT=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_VIRTUALIZATION is not set +CONFIG_BACKPORT_INTEGRATE=y +CONFIG_BACKPORT_DIR="backports/" +CONFIG_BACKPORT_VERSION="v4.1.1-1-0-g8286954" +CONFIG_BACKPORT_KERNEL_VERSION="v4.1.7-0-g0c5c1f1" +CONFIG_BACKPORT_KERNEL_NAME="Linux" +# CONFIG_BACKPORT_LINUX is not set diff --git a/config/olimex-micro.fex b/config/micro.fex similarity index 73% rename from config/olimex-micro.fex rename to config/micro.fex index 8052e31d3..8d8441d07 100644 --- a/config/olimex-micro.fex +++ b/config/micro.fex @@ -60,8 +60,8 @@ uart_debug_rx = port:PB23<2><1> [uart_force_debug] uart_debug_port = 0 -uart_debug_tx = port:PF02<4><1> -uart_debug_rx = port:PF04<4><1> +uart_debug_tx = port:PB22<2><1> +uart_debug_rx = port:PB23<2><1> [jtag_para] jtag_enable = 0 @@ -71,7 +71,7 @@ jtag_do = port:PB16<3> jtag_di = port:PB17<3> [pm_para] -standby_mode = 1 +standby_mode = 0 [dram_para] dram_baseaddr = 0x40000000 @@ -135,6 +135,16 @@ twi2_used = 1 twi2_scl = port:PB20<2> twi2_sda = port:PB21<2> +[twi3_para] +twi3_used = 0 +twi3_scl = port:PI00<3> +twi3_sda = port:PI01<3> + +[twi4_para] +twi4_used = 0 +twi4_scl = port:PI02<3> +twi4_sda = port:PI03<3> + [uart_para0] uart_used = 1 uart_port = 0 @@ -177,8 +187,8 @@ uart_cts = port:PH03<4><1> uart_used = 0 uart_port = 4 uart_type = 2 -uart_tx = port:PH04<4><1> -uart_rx = port:PH05<4><1> +uart_tx = port:PG10<4><1> +uart_rx = port:PG11<4><1> [uart_para5] uart_used = 0 @@ -191,15 +201,15 @@ uart_rx = port:PH07<4><1> uart_used = 1 uart_port = 6 uart_type = 2 -uart_tx = port:PI12<4><1> -uart_rx = port:PI13<4><1> +uart_tx = port:PI12<3><1> +uart_rx = port:PI13<3><1> [uart_para7] uart_used = 1 uart_port = 7 uart_type = 2 -uart_tx = port:PI20<4><1> -uart_rx = port:PI21<4><1> +uart_tx = port:PI20<3><1> +uart_rx = port:PI21<3><1> [spi0_para] spi_used = 0 @@ -235,6 +245,28 @@ spi_sclk = port:PA06<3> spi_mosi = port:PA07<3> spi_miso = port:PA08<3> +[spi_devices] +spi_dev_num = 2 + +[spi_board0] +modalias = "spidev" +max_speed_hz = 1000000 +bus_num = 2 +chip_select = 0 +mode = 3 +full_duplex = 0 +manual_cs = 0 + +[spi_board1] +modalias = "spidev" +max_speed_hz = 1000000 +bus_num = 1 +chip_select = 0 +mode = 3 +full_duplex = 0 +manual_cs = 0 + + [rtp_para] rtp_used = 1 rtp_screen_size = 5 @@ -266,6 +298,14 @@ tkey_int = port:PI13<6> motor_used = 0 motor_shake = port:PB03<1><1> +[leds_para] +leds_used = 1 +leds_num = 1 +leds_pin_1 = port:PH02<1><0> +leds_name_1 = "green:ph02:led1" +leds_default_1 = 0 +leds_trigger_1 = "heartbeat" + [nand_para] nand_used = 1 nand_we = port:PC00<2> @@ -818,6 +858,8 @@ spdif_din = [audio_para] audio_used = 1 capture_used = 1 +playback_used = 1 +audio_lr_change = 0 [switch_para] switch_used = 1 @@ -891,7 +933,7 @@ key_min = 4 key_max = 6 [dvfs_table] -max_freq = 912000000 +max_freq = 1008000000 min_freq = 408000000 LV_count = 7 LV1_freq = 1008000000 @@ -908,171 +950,139 @@ LV6_freq = 312000000 LV6_volt = 1000 LV7_freq = 144000000 LV7_volt = 1000 - [gpio_para] gpio_used = 1 -gpio_num = 76 -gpio_pin_1 = port:PE00<0> -gpio_pin_2 = port:PE01<0> -gpio_pin_3 = port:PE02<0> -gpio_pin_4 = port:PE03<0> -gpio_pin_5 = port:PE04<0> -gpio_pin_6 = port:PE05<0> -gpio_pin_7 = port:PE06<0> -gpio_pin_8 = port:PE07<0> -gpio_pin_9 = port:PE08<0> -gpio_pin_10 = port:PE09<0> -gpio_pin_11 = port:PE10<0> -gpio_pin_12 = port:PE11<0> -gpio_pin_13 = port:PI14<0> -gpio_pin_14 = port:PI15<0> -gpio_pin_15 = port:PI00<0> -gpio_pin_16 = port:PI01<0> -gpio_pin_17 = port:PI02<0> -gpio_pin_18 = port:PI03<0> -gpio_pin_19 = port:PI10<0> -gpio_pin_20 = port:PI11<0> -gpio_pin_21 = port:PC03<0> -gpio_pin_22 = port:PC07<0> -gpio_pin_23 = port:PC16<0> -gpio_pin_24 = port:PC17<0> -gpio_pin_25 = port:PC18<0> -gpio_pin_26 = port:PC23<0> -gpio_pin_27 = port:PC24<0> -gpio_pin_28 = port:PB03<0> -gpio_pin_29 = port:PB04<0> -gpio_pin_30 = port:PB05<0> -gpio_pin_31 = port:PB06<0> -gpio_pin_32 = port:PB07<0> -gpio_pin_33 = port:PB08<0> -gpio_pin_34 = port:PB10<0> -gpio_pin_35 = port:PB11<0> -gpio_pin_36 = port:PB12<0> -gpio_pin_37 = port:PB13<0> -gpio_pin_38 = port:PB14<0> -gpio_pin_39 = port:PB15<0> -gpio_pin_40 = port:PB16<0> -gpio_pin_41 = port:PB17<0> -gpio_pin_42 = port:PH24<0> -gpio_pin_43 = port:PH25<0> -gpio_pin_44 = port:PH26<0> -gpio_pin_45 = port:PH27<0> -gpio_pin_46 = port:PH00<0> -gpio_pin_47 = port:PH02<0> -gpio_pin_48 = port:PH07<0> -gpio_pin_49 = port:PH09<0> -gpio_pin_50 = port:PH10<0> -gpio_pin_51 = port:PH11<0> -gpio_pin_52 = port:PH12<0> -gpio_pin_53 = port:PH13<0> -gpio_pin_54 = port:PH14<0> -gpio_pin_55 = port:PH15<0> -gpio_pin_56 = port:PH16<0> -gpio_pin_57 = port:PH17<0> -gpio_pin_58 = port:PH18<0> -gpio_pin_59 = port:PH19<0> -gpio_pin_60 = port:PH20<0> -gpio_pin_61 = port:PH21<0> -gpio_pin_62 = port:PH22<0> -gpio_pin_63 = port:PH23<0> -gpio_pin_64 = port:PG00<0> -gpio_pin_65 = port:PG01<0> -gpio_pin_66 = port:PG02<0> -gpio_pin_67 = port:PG03<0> -gpio_pin_68 = port:PG04<0> -gpio_pin_69 = port:PG05<0> -gpio_pin_70 = port:PG06<0> -gpio_pin_71 = port:PG07<0> -gpio_pin_72 = port:PG08<0> -gpio_pin_73 = port:PG09<0> -gpio_pin_74 = port:PG10<0> -gpio_pin_75 = port:PG11<0> -gpio_pin_76 = port:PH08<1><1> +gpio_num = 61 +gpio_pin_1 = port:PG00<0> +gpio_pin_2 = port:PG01<0> +gpio_pin_3 = port:PG02<0> +gpio_pin_4 = port:PG03<0> +gpio_pin_5 = port:PG04<0> +gpio_pin_6 = port:PG05<0> +gpio_pin_7 = port:PG06<0> +gpio_pin_8 = port:PG07<0> +gpio_pin_9 = port:PG08<0> +gpio_pin_10 = port:PG09<0> +gpio_pin_11 = port:PC07<0> +gpio_pin_12 = port:PC17<0> +gpio_pin_13 = port:PC18<0> +gpio_pin_14 = port:PC23<0> +gpio_pin_15 = port:PC24<0> +gpio_pin_16 = port:PH00<0> +gpio_pin_17 = port:PH02<0> +gpio_pin_18 = port:PH09<0> +gpio_pin_19 = port:PH10<0> +gpio_pin_20 = port:PH11<0> +gpio_pin_21 = port:PH14<0> +gpio_pin_22 = port:PH15<0> +gpio_pin_23 = port:PH16<0> +gpio_pin_24 = port:PH17<0> +gpio_pin_25 = port:PH18<0> +gpio_pin_26 = port:PH19<0> +gpio_pin_27 = port:PH20<0> +gpio_pin_28 = port:PH21<0> +gpio_pin_29 = port:PH22<0> +gpio_pin_30 = port:PH23<0> +gpio_pin_31 = port:PH24<0> +gpio_pin_32 = port:PH25<0> +gpio_pin_33 = port:PH26<0> +gpio_pin_34 = port:PH27<0> +gpio_pin_35 = port:PB03<0> +gpio_pin_36 = port:PB04<0> +gpio_pin_37 = port:PB05<0> +gpio_pin_38 = port:PB06<0> +gpio_pin_39 = port:PB07<0> +gpio_pin_40 = port:PB10<0> +gpio_pin_41 = port:PB11<0> +gpio_pin_42 = port:PB12<0> +gpio_pin_43 = port:PB13<0> +gpio_pin_44 = port:PB14<0> +gpio_pin_45 = port:PB15<0> +gpio_pin_46 = port:PB16<0> +gpio_pin_47 = port:PB17<0> +gpio_pin_48 = port:PI00<0> +gpio_pin_49 = port:PI01<0> +gpio_pin_50 = port:PI02<0> +gpio_pin_51 = port:PI03<0> +gpio_pin_52 = port:PI04<0> +gpio_pin_53 = port:PI05<0> +gpio_pin_54 = port:PI06<0> +gpio_pin_55 = port:PI07<0> +gpio_pin_56 = port:PI08<0> +gpio_pin_57 = port:PI09<0> +gpio_pin_58 = port:PI10<0> +gpio_pin_59 = port:PI11<0> +gpio_pin_60 = port:PI14<0> +gpio_pin_61 = port:PI15<0> [gpio_init] -pin_1 = port:PE00<0> -pin_2 = port:PE01<0> -pin_3 = port:PE02<0> -pin_4 = port:PE03<0> -pin_5 = port:PE04<0> -pin_6 = port:PE05<0> -pin_7 = port:PE06<0> -pin_8 = port:PE07<0> -pin_9 = port:PE08<0> -pin_10 = port:PE09<0> -pin_11 = port:PE10<0> -pin_12 = port:PE11<0> -pin_13 = port:PI14<0> -pin_14 = port:PI15<0> -pin_15 = port:PI00<0> -pin_16 = port:PI01<0> -pin_17 = port:PI02<0> -pin_18 = port:PI03<0> -pin_19 = port:PI10<0> -pin_20 = port:PI11<0> -pin_21 = port:PC03<0> -pin_22 = port:PC07<0> -pin_23 = port:PC16<0> -pin_24 = port:PC17<0> -pin_25 = port:PC18<0> -pin_26 = port:PC23<0> -pin_27 = port:PC24<0> -pin_28 = port:PB03<0> -pin_29 = port:PB04<0> -pin_30 = port:PB05<0> -pin_31 = port:PB06<0> -pin_32 = port:PB07<0> -pin_33 = port:PB08<0> -pin_34 = port:PB10<0> -pin_35 = port:PB11<0> -pin_36 = port:PB12<0> -pin_37 = port:PB13<0> -pin_38 = port:PB14<0> -pin_39 = port:PB15<0> -pin_40 = port:PB16<0> -pin_41 = port:PB17<0> -pin_42 = port:PH24<0> -pin_43 = port:PH25<0> -pin_44 = port:PH26<0> -pin_45 = port:PH27<0> -pin_46 = port:PH00<0> -pin_47 = port:PH02<0> -pin_48 = port:PH07<0> -pin_49 = port:PH09<0> -pin_50 = port:PH10<0> -pin_51 = port:PH11<0> -pin_52 = port:PH12<0> -pin_53 = port:PH13<0> -pin_54 = port:PH14<0> -pin_55 = port:PH15<0> -pin_56 = port:PH16<0> -pin_57 = port:PH17<0> -pin_58 = port:PH18<0> -pin_59 = port:PH19<0> -pin_60 = port:PH20<0> -pin_61 = port:PH21<0> -pin_62 = port:PH22<0> -pin_63 = port:PH23<0> -pin_64 = port:PG00<0> -pin_65 = port:PG01<0> -pin_66 = port:PG02<0> -pin_67 = port:PG03<0> -pin_68 = port:PG04<0> -pin_69 = port:PG05<0> -pin_70 = port:PG06<0> -pin_71 = port:PG07<0> -pin_72 = port:PG08<0> -pin_73 = port:PG09<0> -pin_74 = port:PG10<0> -pin_75 = port:PG11<0> -pin_76 = port:PH08<1><1> +pin_1 = port:PG00<0> +pin_2 = port:PG01<0> +pin_3 = port:PG02<0> +pin_4 = port:PG03<0> +pin_5 = port:PG04<0> +pin_6 = port:PG05<0> +pin_7 = port:PG06<0> +pin_8 = port:PG07<0> +pin_9 = port:PG08<0> +pin_10 = port:PG09<0> +pin_11 = port:PC07<0> +pin_12 = port:PC17<0> +pin_13 = port:PC18<0> +pin_14 = port:PC23<0> +pin_15 = port:PC24<0> +pin_16 = port:PH00<0> +pin_17 = port:PH02<0> +pin_18 = port:PH09<0> +pin_19 = port:PH10<0> +pin_20 = port:PH11<0> +pin_21 = port:PH14<0> +pin_22 = port:PH15<0> +pin_23 = port:PH16<0> +pin_24 = port:PH17<0> +pin_25 = port:PH18<0> +pin_26 = port:PH19<0> +pin_27 = port:PH20<0> +pin_28 = port:PH21<0> +pin_29 = port:PH22<0> +pin_30 = port:PH23<0> +pin_31 = port:PH24<0> +pin_32 = port:PH25<0> +pin_33 = port:PH26<0> +pin_34 = port:PH27<0> +pin_35 = port:PB03<0> +pin_36 = port:PB04<0> +pin_37 = port:PB05<0> +pin_38 = port:PB06<0> +pin_39 = port:PB07<0> +pin_40 = port:PB10<0> +pin_41 = port:PB11<0> +pin_42 = port:PB12<0> +pin_43 = port:PB13<0> +pin_44 = port:PB14<0> +pin_45 = port:PB15<0> +pin_46 = port:PB16<0> +pin_47 = port:PB17<0> +pin_48 = port:PI00<0> +pin_49 = port:PI01<0> +pin_50 = port:PI02<0> +pin_51 = port:PI03<0> +pin_52 = port:PI04<0> +pin_53 = port:PI05<0> +pin_54 = port:PI06<0> +pin_55 = port:PI07<0> +pin_56 = port:PI08<0> +pin_57 = port:PI09<0> +pin_58 = port:PI10<0> +pin_59 = port:PI11<0> +pin_60 = port:PI14<0> +pin_61 = port:PI15<0> + +[softpwm_para] +softpwm_used = 1 +pwm_pin = port:PD23<0> +dcr_pin = port:PD24<0> -[leds_para] -leds_used = 1 -leds_num = 1 -leds_pin_1 = port:PH02<1><0> -leds_name_1 = "green:ph02:led1" -leds_default_1 = 1 [tabletkeys_para] tabletkeys_used = 1 diff --git a/config/modules.bananapi b/config/modules.bananapi deleted file mode 100644 index 716560efa..000000000 --- a/config/modules.bananapi +++ /dev/null @@ -1,7 +0,0 @@ -hci_uart -gpio_sunxi -rfcomm -hidp -sunxi-ir -bonding -spi_sun7i \ No newline at end of file diff --git a/config/modules.bananapi-next b/config/modules.bananapi-next deleted file mode 100644 index e69de29bb..000000000 diff --git a/config/modules.cubietruck b/config/modules.cubietruck deleted file mode 100644 index a76dbc9de..000000000 --- a/config/modules.cubietruck +++ /dev/null @@ -1,21 +0,0 @@ -hci_uart -gpio_sunxi -bt_gpio -wifi_gpio -rfcomm -hidp -sunxi-ir -sunxi_ss -bonding -spi_sun7i -bcmdhd -# if you want access point mode, load wifi module this way: bcmdhd op_mode=2 -# in Jessie load module without option and add: nano /etc/modprobe.d/bcmdhd.conf and put in: options bcmdhd op_mode=2 -# and edit /etc/init.d/hostapd change DAEMON_CONF=/etc/hostapd.conf ; edit your wifi net settings in hostapd.conf ; reboot -# -# w1_sunxi -# -# Advanced LIRC driver: https://github.com/matzrh/sunxi-lirc -# -# lirc_gpio -# sunxi_lirc diff --git a/config/modules.cubietruck-next b/config/modules.cubietruck-next deleted file mode 100644 index ce48da23a..000000000 --- a/config/modules.cubietruck-next +++ /dev/null @@ -1 +0,0 @@ -brcmfmac \ No newline at end of file diff --git a/config/modules.cubox-i b/config/modules.cubox-i deleted file mode 100644 index 29a76c4d8..000000000 --- a/config/modules.cubox-i +++ /dev/null @@ -1 +0,0 @@ -bonding diff --git a/config/modules.lime b/config/modules.lime deleted file mode 100644 index e039ae37d..000000000 --- a/config/modules.lime +++ /dev/null @@ -1,7 +0,0 @@ -hci_uart -gpio_sunxi -rfcomm -hidp -sunxi_ss -bonding -spi_sun7i diff --git a/config/modules.lime2 b/config/modules.lime2 deleted file mode 100644 index e039ae37d..000000000 --- a/config/modules.lime2 +++ /dev/null @@ -1,7 +0,0 @@ -hci_uart -gpio_sunxi -rfcomm -hidp -sunxi_ss -bonding -spi_sun7i diff --git a/config/orangepi.fex b/config/orangepi.fex new file mode 100644 index 000000000..7888dd4f3 --- /dev/null +++ b/config/orangepi.fex @@ -0,0 +1,1072 @@ +[product] +version = "100" +machine = "bananapi" + +[platform] +eraseflag = 0 + +[target] +boot_clock = 912 +dcdc2_vol = 1450 +dcdc3_vol = 1300 +ldo2_vol = 3000 +ldo3_vol = 2800 +ldo4_vol = 2800 +storage_type = 0 + +[clock] +pll3 = 297 +pll4 = 300 +pll6 = 600 +pll7 = 297 +pll8 = 336 + +[card_boot] +logical_start = 40960 +sprite_gpio0 = + +[card0_boot_para] +card_ctrl = 0 +card_high_speed = 1 +card_line = 4 +sdc_d1 = port:PF00<2><1> +sdc_d0 = port:PF01<2><1> +sdc_clk = port:PF02<2><1> +sdc_cmd = port:PF03<2><1> +sdc_d3 = port:PF04<2><1> +sdc_d2 = port:PF05<2><1> + +[card2_boot_para] +card_ctrl = 2 +card_high_speed = 1 +card_line = 4 +sdc_cmd = port:PC06<3><1> +sdc_clk = port:PC07<3><1> +sdc_d0 = port:PC08<3><1> +sdc_d1 = port:PC09<3><1> +sdc_d2 = port:PC10<3><1> +sdc_d3 = port:PC11<3><1> + +[twi_para] +twi_port = 0 +twi_scl = port:PB00<2> +twi_sda = port:PB01<2> + +[uart_para] +uart_debug_port = 0 +uart_debug_tx = port:PB22<2><1> +uart_debug_rx = port:PB23<2><1> + +[uart_force_debug] +uart_debug_port = 0 +uart_debug_tx = port:PF02<4><1> +uart_debug_rx = port:PF04<4><1> + +[jtag_para] +jtag_enable = 0 +jtag_ms = port:PB14<3> +jtag_ck = port:PB15<3> +jtag_do = port:PB16<3> +jtag_di = port:PB17<3> + +[pm_para] +standby_mode = 0 + +[dram_para] +dram_baseaddr = 0x40000000 +dram_clk = 432 +dram_type = 3 +dram_rank_num = 1 +dram_chip_density = 4096 +dram_io_width = 16 +dram_bus_width = 32 +dram_cas = 9 +dram_zq = 0x7f +dram_odt_en = 0 +dram_size = 1024 +dram_tpr0 = 0x42d899b7 +dram_tpr1 = 0xa090 +dram_tpr2 = 0x22a00 +dram_tpr3 = 0x0 +dram_tpr4 = 0x1 +dram_tpr5 = 0x0 +dram_emr1 = 0x4 +dram_emr2 = 0x10 +dram_emr3 = 0x0 + +[mali_para] +mali_used = 1 +mali_clkdiv = 1 + +[gmac_para] +gmac_used = 1 +gmac_rxd3 = port:PA00<5><3> +gmac_rxd2 = port:PA01<5><3> +gmac_rxd1 = port:PA02<5><3> +gmac_rxd0 = port:PA03<5><3> +gmac_txd3 = port:PA04<5><3> +gmac_txd2 = port:PA05<5><3> +gmac_txd1 = port:PA06<5><3> +gmac_txd0 = port:PA07<5><3> +gmac_rxclk = port:PA08<5><3> +gmac_rxerr = port:PA09<0><3> +gmac_rxctl = port:PA10<5><3> +gmac_mdc = port:PA11<5><3> +gmac_mdio = port:PA12<5><3> +gmac_txctl = port:PA13<5><3> +gmac_txclk = port:PA14<0><3> +gmac_txck = port:PA15<5><3> +gmac_clkin = port:PA16<5><3> +gmac_txerr = port:PA17<0><3> + +[gmac_phy_power] +gmac_phy_power_en = port:PH23<1><0> + +[twi0_para] +twi0_used = 1 +twi0_scl = port:PB00<2> +twi0_sda = port:PB01<2> + +[twi1_para] +twi1_used = 1 +twi1_scl = port:PB18<2> +twi1_sda = port:PB19<2> + +[twi2_para] +twi2_used = 1 +twi2_scl = port:PB20<2> +twi2_sda = port:PB21<2> + +[twi3_para] +twi3_used = 1 +twi3_scl = port:PI00<3> +twi3_sda = port:PI01<3> + +[uart_para0] +uart_used = 1 +uart_port = 0 +uart_type = 2 +uart_tx = port:PB22<2><1> +uart_rx = port:PB23<2><1> + +[uart_para1] +uart_used = 0 +uart_port = 1 +uart_type = 8 +uart_tx = port:PA10<4><1> +uart_rx = port:PA11<4><1> +uart_rts = port:PA12<4><1> +uart_cts = port:PA13<4><1> +uart_dtr = port:PA14<4><1> +uart_dsr = port:PA15<4><1> +uart_dcd = port:PA16<4><1> +uart_ring = port:PA17<4><1> + +[uart_para2] +uart_used = 1 +uart_port = 2 +uart_type = 4 +uart_tx = port:PI18<3><1> +uart_rx = port:PI19<3><1> +uart_rts = port:PI16<3><1> +uart_cts = port:PI17<3><1> + +[uart_para3] +uart_used = 1 +uart_port = 3 +uart_type = 2 +uart_tx = port:PH00<4><1> +uart_rx = port:PH01<4><1> + +[uart_para4] +uart_used = 0 +uart_port = 4 +uart_type = 2 +uart_tx = port:PH04<4><1> +uart_rx = port:PH05<4><1> + +[uart_para5] +uart_used = 0 +uart_port = 5 +uart_type = 2 +uart_tx = port:PH06<4><1> +uart_rx = port:PH07<4><1> + +[uart_para6] +uart_used = 0 +uart_port = 6 +uart_type = 2 +uart_tx = port:PA12<4><1> +uart_rx = port:PA13<4><1> + +[uart_para7] +uart_used = 1 +uart_port = 7 +uart_type = 2 +uart_tx = port:PI20<3><1> +uart_rx = port:PI21<3><1> + +[spi0_para] +spi_used = 1 +spi_cs_bitmap = 3 +spi_cs0 = port:PI10<2> +spi_cs1 = port:PI14<2> +spi_sclk = port:PI11<2> +spi_mosi = port:PI12<2> +spi_miso = port:PI13<2> + +[spi1_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA00<3> +spi_cs1 = port:PA04<3> +spi_sclk = port:PA01<3> +spi_mosi = port:PA02<3> +spi_miso = port:PA03<3> + +[spi2_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PC19<3> +spi_cs1 = port:PB13<2> +spi_sclk = port:PC20<3> +spi_mosi = port:PC21<3> +spi_miso = port:PC22<3> + +[spi3_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA05<3> +spi_cs1 = port:PA09<3> +spi_sclk = port:PA06<3> +spi_mosi = port:PA07<3> +spi_miso = port:PA08<3> + +[spi_devices] +spi_dev_num = 2 + +[spi_board0] +modalias = "spidev" +max_speed_hz = 12000000 +bus_num = 0 +chip_select = 0 +mode = 3 +full_duplex = 0 +manual_cs = 0 + +[spi_board1] +modalias = "spidev" +max_speed_hz = 12000000 +bus_num = 0 +chip_select = 1 +mode = 3 +full_duplex = 0 +manual_cs = 0 + +[ctp_para] +ctp_used = 0 +ctp_name = "gt811" +ctp_twi_id = 2 +ctp_twi_addr = 0x40 +ctp_screen_max_x = 1024 +ctp_screen_max_y = 600 +ctp_revert_x_flag = 0 +ctp_revert_y_flag = 0 +ctp_exchange_x_y_flag = 1 +ctp_firm = 1 +ctp_int_port = port:PH21<6> +ctp_wakeup = port:PB13<1><1> + +[ctp_list_para] +ctp_det_used = 0 +ft5x_ts = 0 +gt82x = 0 +gslX680 = 0 +gt9xx_ts = 0 +gt811 = 0 + +[tkey_para] +tkey_used = 0 +tkey_twi_id = 2 +tkey_twi_addr = 0x62 +tkey_int = port:PI13<6> + +[motor_para] +motor_used = 0 +motor_shake = port:PB03<1><1> + +[gpio_para] +gpio_used = 1 +gpio_num = 88 +gpio_pin_1 = port:PB20<1> +gpio_pin_2 = port:PB21<1> +gpio_pin_3 = port:PB20<1> +gpio_pin_4 = port:PI03<1> +gpio_pin_5 = port:PB22<1> +gpio_pin_6 = port:PB23<1> +gpio_pin_7 = port:PI14<1> +gpio_pin_8 = port:PI10<1> +gpio_pin_9 = port:PI13<1> +gpio_pin_10 = port:PI12<1> +gpio_pin_11 = port:PI11<1> +gpio_pin_12 = port:PH05<1> +gpio_pin_13 = port:PH03<1> +gpio_pin_14 = port:PH00<1> +gpio_pin_15 = port:PH01<1> +gpio_pin_16 = port:PH01<1> +gpio_pin_17 = port:PI19<1> +gpio_pin_18 = port:PH02<1> +gpio_pin_19 = port:PH02<1> +gpio_pin_20 = port:PI20<1> +gpio_pin_21 = port:PI21<1> +gpio_pin_22 = port:PI17<1> +gpio_pin_23 = port:PH20<1> +gpio_pin_24 = port:PH21<1> +gpio_pin_25 = port:PI16<1> +gpio_pin_26 = port:PI16<1> +gpio_pin_27 = port:PI18<1> +gpio_pin_28 = port:PH05<1> +gpio_pin_29 = port:PI21<1> +gpio_pin_30 = port:PH03<1> +gpio_pin_31 = port:PI20<1> +gpio_pin_32 = port:PH17<1> +gpio_pin_33 = port:PB19<1> +gpio_pin_34 = port:PB18<1> +gpio_pin_35 = port:PH19<1> +gpio_pin_36 = port:PE00<1> +gpio_pin_37 = port:PH16<1> +gpio_pin_38 = port:PE01<1> +gpio_pin_39 = port:PH14<1> +gpio_pin_40 = port:PE03<1> +gpio_pin_41 = port:PE02<1> +gpio_pin_42 = port:PH18<1> +gpio_pin_43 = port:PH11<1> +gpio_pin_44 = port:PE04<1> +gpio_pin_45 = port:PE05<1> +gpio_pin_46 = port:PE06<1> +gpio_pin_47 = port:PE07<1> +gpio_pin_48 = port:PE08<1> +gpio_pin_49 = port:PE09<1> +gpio_pin_50 = port:PE10<1> +gpio_pin_51 = port:PE11<1> +gpio_pin_52 = port:PH13<1> +gpio_pin_53 = port:PI01<1> +gpio_pin_54 = port:PI00<1> +gpio_pin_55 = port:PH07<1> +gpio_pin_56 = port:PH08<1> +gpio_pin_57 = port:PB02<1> +gpio_pin_58 = port:PH09<1> +gpio_pin_59 = port:PD25<1> +gpio_pin_60 = port:PD27<1> +gpio_pin_61 = port:PD26<1> +gpio_pin_62 = port:PH06<1> +gpio_pin_63 = port:PD24<1> +gpio_pin_64 = port:PD23<1> +gpio_pin_65 = port:PD22<1> +gpio_pin_66 = port:PD21<1> +gpio_pin_67 = port:PD20<1> +gpio_pin_68 = port:PD19<1> +gpio_pin_69 = port:PD18<1> +gpio_pin_70 = port:PD17<1> +gpio_pin_71 = port:PD16<1> +gpio_pin_72 = port:PH12<1> +gpio_pin_73 = port:PD00<1> +gpio_pin_74 = port:PD01<1> +gpio_pin_75 = port:PD02<1> +gpio_pin_76 = port:PD03<1> +gpio_pin_77 = port:PD04<1> +gpio_pin_78 = port:PD05<1> +gpio_pin_79 = port:PD06<1> +gpio_pin_80 = port:PD07<1> +gpio_pin_81 = port:PD08<1> +gpio_pin_82 = port:PD09<1> +gpio_pin_83 = port:PD10<1> +gpio_pin_84 = port:PD11<1> +gpio_pin_85 = port:PD12<1> +gpio_pin_86 = port:PD13<1> +gpio_pin_87 = port:PD14<1> +gpio_pin_88 = port:PD15<1> + +[nand_para] +nand_used = 0 +nand_we = port:PC00<2> +nand_ale = port:PC01<2> +nand_cle = port:PC02<2> +nand_ce1 = port:PC03<2> +nand_ce0 = port:PC04<2> +nand_nre = port:PC05<2> +nand_rb0 = port:PC06<2> +nand_rb1 = port:PC07<2> +nand_d0 = port:PC08<2> +nand_d1 = port:PC09<2> +nand_d2 = port:PC10<2> +nand_d3 = port:PC11<2> +nand_d4 = port:PC12<2> +nand_d5 = port:PC13<2> +nand_d6 = port:PC14<2> +nand_d7 = port:PC15<2> +nand_wp = port:PC16<2> +nand_ce2 = port:PC17<2> +nand_ce3 = port:PC18<2> +nand_ce4 = +nand_ce5 = +nand_ce6 = +nand_ce7 = +nand_spi = port:PC23<3> +nand_ndqs = port:PC24<2> +good_block_ratio = 0 + +[disp_init] +disp_init_enable = 1 +disp_mode = 4 +screen0_output_type = 4 +screen0_output_mode = 4 +screen1_output_type = 3 +screen1_output_mode = 5 +fb0_framebuffer_num = 2 +fb0_format = 10 +fb0_pixel_sequence = 0 +fb0_scaler_mode_enable = 1 +fb1_framebuffer_num = 2 +fb1_format = 10 +fb1_pixel_sequence = 0 +fb1_scaler_mode_enable = 0 +lcd0_backlight = 197 +lcd1_backlight = 197 +lcd0_bright = 50 +lcd0_contrast = 50 +lcd0_saturation = 57 +lcd0_hue = 50 +lcd1_bright = 50 +lcd1_contrast = 50 +lcd1_saturation = 57 +lcd1_hue = 50 + +[lcd0_para] +lcd_used = 0 +lcd_x = 800 +lcd_y = 480 +lcd_dclk_freq = 33 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 0 +lcd_pwm_freq = 10000 +lcd_pwm_pol = 0 +lcd_max_bright = 240 +lcd_min_bright = 64 +lcd_if = 0 +lcd_hbp = 46 +lcd_ht = 1055 +lcd_vbp = 23 +lcd_vt = 1050 +lcd_vspw = 0 +lcd_hspw = 0 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 268435456 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 1 +lcd_bl_en = port:PH07<1><0><1> +lcd_power_used = 1 +lcd_power = port:PH08<1><0><1> +lcd_pwm_used = 1 +lcd_pwm = port:PB02<2><0> +lcdd0 = port:PD00<2><0> +lcdd1 = port:PD01<2><0> +lcdd2 = port:PD02<2><0> +lcdd3 = port:PD03<2><0> +lcdd4 = port:PD04<2><0> +lcdd5 = port:PD05<2><0> +lcdd6 = port:PD06<2><0> +lcdd7 = port:PD07<2><0> +lcdd8 = port:PD08<2><0> +lcdd9 = port:PD09<2><0> +lcdd10 = port:PD10<2><0> +lcdd11 = port:PD11<2><0> +lcdd12 = port:PD12<2><0> +lcdd13 = port:PD13<2><0> +lcdd14 = port:PD14<2><0> +lcdd15 = port:PD15<2><0> +lcdd16 = port:PD16<2><0> +lcdd17 = port:PD17<2><0> +lcdd18 = port:PD18<2><0> +lcdd19 = port:PD19<2><0> +lcdd20 = port:PD20<2><0> +lcdd21 = port:PD21<2><0> +lcdd22 = port:PD22<2><0> +lcdd23 = port:PD23<2><0> +lcdclk = port:PD24<2><0> +lcdde = port:PD25<2><0> +lcdhsync = port:PD26<2><0> +lcdvsync = port:PD27<2><0> + +[lcd1_para] +lcd_used = 0 +lcd_x = 0 +lcd_y = 0 +lcd_dclk_freq = 0 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 1 +lcd_pwm_freq = 0 +lcd_pwm_pol = 0 +lcd_max_bright = 240 +lcd_min_bright = 64 +lcd_if = 0 +lcd_hbp = 0 +lcd_ht = 0 +lcd_vbp = 0 +lcd_vt = 0 +lcd_vspw = 0 +lcd_hspw = 0 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 0 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x0 +lcd_gamma_tbl_1 = 0x10101 +lcd_gamma_tbl_255 = 0xffffff +lcd_bl_en_used = 0 +lcd_bl_en = +lcd_power_used = 0 +lcd_power = +lcd_pwm_used = 1 +lcd_pwm = port:PI03<2><0> +lcd_gpio_0 = +lcd_gpio_1 = +lcd_gpio_2 = +lcd_gpio_3 = +lcdd0 = port:PH00<2><0> +lcdd1 = port:PH01<2><0> +lcdd2 = port:PH02<2><0> +lcdd3 = port:PH03<2><0> +lcdd4 = port:PH04<2><0> +lcdd5 = port:PH05<2><0> +lcdd6 = port:PH06<2><0> +lcdd7 = port:PH07<2><0> +lcdd8 = port:PH08<2><0> +lcdd9 = port:PH09<2><0> +lcdd10 = port:PH10<2><0> +lcdd11 = port:PH11<2><0> +lcdd12 = port:PH12<2><0> +lcdd13 = port:PH13<2><0> +lcdd14 = port:PH14<2><0> +lcdd15 = port:PH15<2><0> +lcdd16 = port:PH16<2><0> +lcdd17 = port:PH17<2><0> +lcdd18 = port:PH18<2><0> +lcdd19 = port:PH19<2><0> +lcdd20 = port:PH20<2><0> +lcdd21 = port:PH21<2><0> +lcdd22 = port:PH22<2><0> +lcdd23 = port:PH23<2><0> +lcdclk = port:PH24<2><0> +lcdde = port:PH25<2><0> +lcdhsync = port:PH26<2><0> +lcdvsync = port:PH27<2><0> + +[tv_out_dac_para] +dac_used = 0 +dac0_src = 4 +dac1_src = 5 +dac2_src = 6 +dac3_src = 0 + +[hdmi_para] +hdmi_used = 1 + +[csi0_para] +csi_used = 1 +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "ov5640" +csi_twi_id = 1 +csi_twi_addr = 0x78 +csi_if = 0 +csi_vflip = 1 +csi_hflip = 0 +csi_iovdd = "axp20_pll" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = 2800 +csi_vol_dvdd = +csi_vol_avdd = +csi_flash_pol = 0 +csi_facing = 0 +csi_pck = port:PE00<3> +csi_ck = port:PE01<3> +csi_hsync = port:PE02<3> +csi_vsync = port:PE03<3> +csi_d0 = port:PE04<3> +csi_d1 = port:PE05<3> +csi_d2 = port:PE06<3> +csi_d3 = port:PE07<3> +csi_d4 = port:PE08<3> +csi_d5 = port:PE09<3> +csi_d6 = port:PE10<3> +csi_d7 = port:PE11<3> +csi_reset = port:PH14<1><0> +csi_power_en = port:PH16<1><0> +csi_stby = port:PH19<1><0> + +[csi1_para] +csi_used = 0 +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "gc0308" +csi_if = 0 +csi_iovdd = "axp20_pll" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = 2800 +csi_vol_dvdd = +csi_vol_avdd = +csi_vflip = 0 +csi_hflip = 0 +csi_flash_pol = 0 +csi_facing = 1 +csi_twi_id = 1 +csi_twi_addr = 0x42 +csi_pck = port:PG00<3> +csi_ck = port:PG01<3> +csi_hsync = port:PG02<3> +csi_vsync = port:PG03<3> +csi_d0 = port:PG04<3> +csi_d1 = port:PG05<3> +csi_d2 = port:PG06<3> +csi_d3 = port:PG07<3> +csi_d4 = port:PG08<3> +csi_d5 = port:PG09<3> +csi_d6 = port:PG10<3> +csi_d7 = port:PG11<3> +csi_reset = port:PH13<1><0> +csi_power_en = port:PH16<1><0> +csi_stby = port:PH18<1><0> + +[camera_list_para] +camera_list_para_used = 1 +ov7670 = 0 +gc0308 = 0 +gt2005 = 0 +hi704 = 0 +sp0838 = 0 +mt9m112 = 0 +mt9m113 = 0 +ov2655 = 0 +hi253 = 0 +gc0307 = 0 +mt9d112 = 0 +ov5640 = 1 +gc2015 = 0 +ov2643 = 0 +gc0329 = 0 +gc0309 = 0 +tvp5150 = 0 +s5k4ec = 0 +ov5650_mv9335 = 0 +siv121d = 0 +gc2035 = 0 + +[tvout_para] +tvout_used = 0 +tvout_channel_num = 1 + +[tvin_para] +tvin_used = 0 +tvin_channel_num = 4 + +[sata_para] +sata_used = 1 +sata_power_en = + +[mmc0_para] +sdc_used = 1 +sdc_detmode = 1 +sdc_buswidth = 4 +sdc_clk = port:PF02<2><1><2> +sdc_cmd = port:PF03<2><1><2> +sdc_d0 = port:PF01<2><1><2> +sdc_d1 = port:PF00<2><1><2> +sdc_d2 = port:PF05<2><1><2> +sdc_d3 = port:PF04<2><1><2> +sdc_det = port:PH10<0><1> +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc1_para] +sdc_used = 0 +sdc_detmode = 4 +sdc_buswidth = 4 +sdc_clk = port:PG00<2><1><2> +sdc_cmd = port:PG01<2><1><2> +sdc_d0 = port:PG02<2><1><2> +sdc_d1 = port:PG03<2><1><2> +sdc_d2 = port:PG04<2><1><2> +sdc_d3 = port:PG05<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc2_para] +sdc_used = 0 +sdc_detmode = 3 +sdc_buswidth = 4 +sdc_cmd = port:PC06<3><1><2> +sdc_clk = port:PC07<3><1><2> +sdc_d0 = port:PC08<3><1><2> +sdc_d1 = port:PC09<3><1><2> +sdc_d2 = port:PC10<3><1><2> +sdc_d3 = port:PC11<3><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc3_para] +sdc_used = 0 +sdc_detmode = 4 +sdc_buswidth = 4 +sdc_cmd = port:PI04<2><1><2> +sdc_clk = port:PI05<2><1><2> +sdc_d0 = port:PI06<2><1><2> +sdc_d1 = port:PI07<2><1><2> +sdc_d2 = port:PI08<2><1><2> +sdc_d3 = port:PI09<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 1 +sdc_regulator = "none" + +[ms_para] +ms_used = 0 +ms_bs = port:PH06<5> +ms_clk = port:PH07<5> +ms_d0 = port:PH08<5> +ms_d1 = port:PH09<5> +ms_d2 = port:PH10<5> +ms_d3 = port:PH11<5> +ms_det = + +[smc_para] +smc_used = 0 +smc_rst = port:PH13<5> +smc_vppen = port:PH14<5> +smc_vppp = port:PH15<5> +smc_det = port:PH16<5> +smc_vccen = port:PH17<5> +smc_sck = port:PH18<5> +smc_sda = port:PH19<5> + +[ps2_0_para] +ps2_used = 0 +ps2_scl = port:PI20<2><1> +ps2_sda = port:PI21<2><1> + +[ps2_1_para] +ps2_used = 0 +ps2_scl = port:PI14<3><1> +ps2_sda = port:PI15<3><1> + +[can_para] +can_used = 0 +can_tx = port:PA16<3> +can_rx = port:PA17<3> + +[keypad_para] +kp_used = 0 +kp_in_size = 8 +kp_out_size = 8 +kp_in0 = port:PH08<4><1> +kp_in1 = port:PH09<4><1> +kp_in2 = port:PH10<4><1> +kp_in3 = port:PH11<4><1> +kp_in4 = port:PH14<4><1> +kp_in5 = port:PH15<4><1> +kp_in6 = port:PH16<4><1> +kp_in7 = port:PH17<4><1> +kp_out0 = port:PH18<4><1> +kp_out1 = port:PH19<4><1> +kp_out2 = port:PH22<4><1> +kp_out3 = port:PH23<4><1> +kp_out4 = port:PH24<4><1> +kp_out5 = port:PH25<4><1> +kp_out6 = port:PH26<4><1> +kp_out7 = port:PH27<4><1> + +[usbc0] +usb_used = 1 +usb_port_type = 2 +usb_detect_type = 1 +usb_id_gpio = port:PH04<0><1> +usb_det_vbus_gpio = "axp_ctrl" +usb_drv_vbus_gpio = port:PB09<1><0><0> +usb_ac_enable_gpio = port:PH05<1><0><0> +usb_restrict_gpio = 0 +usb_host_init_state = 0 +usb_restric_flag = 0 +usb_restric_voltage = 3550000 +usb_restric_capacity = 5 + +[usbc1] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PH26<1><0><0> +usb_restrict_gpio = +usb_host_init_state = 1 +usb_restric_flag = 0 + +[usbc2] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PH22<1><0><0> +usb_restrict_gpio = +usb_host_init_state = 1 +usb_restric_flag = 0 + +[usb_feature] +vendor_id = 6353 +mass_storage_id = 1 +adb_id = 2 +manufacturer_name = "USB Developer" +product_name = "Android" +serial_number = "20080411" + +[msc_feature] +vendor_name = "USB 2.0" +product_name = "USB Flash Driver" +release = 100 +luns = 3 + +[gsensor_para] +gsensor_used = 0 +gsensor_twi_id = 1 +gsensor_int1 = +gsensor_int2 = + +[gsensor_list_para] +gsensor_det_used = 0 +bma250 = 1 +mma8452 = 1 +mma7660 = 1 +mma865x = 1 +afa750 = 1 +lis3de_acc = 1 +lis3dh_acc = 1 +kxtik = 1 +dmard10 = 0 +dmard06 = 1 +mxc622x = 1 +fxos8700 = 1 +lsm303d = 1 + +[gps_para] +gps_used = 0 +gps_spi_id = 2 +gps_spi_cs_num = 0 +gps_lradc = 1 +gps_clk = port:PI00<2> +gps_sign = port:PI01<2> +gps_mag = port:PI02<2> +gps_vcc_en = port:PC22<1><0> +gps_osc_en = port:PI14<1><0> +gps_rx_en = port:PI15<1><0> + +[wifi_para] +wifi_used = 1 +wifi_sdc_id = 3 +wifi_usbc_id = 2 +wifi_usbc_type = 1 +wifi_mod_sel = 6 +wifi_power = "" +ap6xxx_wl_regon = port:PH09<1><0> +ap6xxx_wl_host_wake = port:PH10<0><0> +ap6xxx_bt_regon = port:PH18<1><0> +ap6xxx_bt_wake = port:PH24<1><0> +ap6xxx_bt_host_wake = port:PH25<0><0> +ap6xxx_lpo = port:PI12<4><1><1> + +[usb_wifi_para] +usb_wifi_used = 1 +usb_wifi_usbc_num = 2 + +[3g_para] +3g_used = 0 +3g_usbc_num = 2 +3g_uart_num = 0 +3g_pwr = +3g_wakeup = +3g_int = + +[gy_para] +gy_used = 0 +gy_twi_id = 1 +gy_twi_addr = 0 +gy_int1 = port:PH18<6><1> +gy_int2 = port:PH19<6><1> + +[ls_para] +ls_used = 0 +ls_twi_id = 1 +ls_twi_addr = 0 +ls_int = port:PH20<6><1> + +[compass_para] +compass_used = 0 +compass_twi_id = 1 +compass_twi_addr = 0 +compass_int = port:PI13<6><1> + +[bt_para] +bt_used = 0 +bt_uart_id = 2 +bt_wakeup = port:PI20<1> +bt_gpio = port:PI21<1> +bt_rst = port:PB05<1> + +[i2s_para] +i2s_used = 0 +i2s_channel = 2 +i2s_mclk = port:PB05<2><1> +i2s_bclk = port:PB06<2><1> +i2s_lrclk = port:PB07<2><1> +i2s_dout0 = port:PB08<2><1> +i2s_dout1 = +i2s_dout2 = +i2s_dout3 = +i2s_din = port:PB12<2><1> + +[spdif_para] +spdif_used = 0 +spdif_mclk = +spdif_dout = port:PB13<4><1> +spdif_din = + +[audio_para] +audio_used = 1 +capture_used = 1 +audio_pa_ctrl = port:PH15<1><1> + +[switch_para] +switch_used = 0 + +[leds_para] +leds_used = 1 +leds_num = 1 +leds_pin_1 = port:PH24<1><0> +leds_name_1 = "green:ph24:led1" +leds_default_1 = 1 +leds_trigger_1 = "mmc0" + +[ir_para] +ir_used = 1 +ir0_rx = port:PB04<2> + +[pmu_para] +pmu_used = 1 +pmu_twi_addr = 52 +pmu_twi_id = 0 +pmu_irq_id = 32 +pmu_battery_rdc = 100 +pmu_battery_cap = 3200 +pmu_init_chgcur = 300 +pmu_earlysuspend_chgcur = 600 +pmu_suspend_chgcur = 1000 +pmu_resume_chgcur = 300 +pmu_shutdown_chgcur = 1000 +pmu_init_chgvol = 4200 +pmu_init_chgend_rate = 15 +pmu_init_chg_enabled = 1 +pmu_init_adc_freq = 100 +pmu_init_adc_freqc = 100 +pmu_init_chg_pretime = 50 +pmu_init_chg_csttime = 720 +pmu_bat_para1 = 0 +pmu_bat_para2 = 0 +pmu_bat_para3 = 0 +pmu_bat_para4 = 0 +pmu_bat_para5 = 5 +pmu_bat_para6 = 8 +pmu_bat_para7 = 11 +pmu_bat_para8 = 22 +pmu_bat_para9 = 33 +pmu_bat_para10 = 43 +pmu_bat_para11 = 50 +pmu_bat_para12 = 59 +pmu_bat_para13 = 71 +pmu_bat_para14 = 83 +pmu_bat_para15 = 92 +pmu_bat_para16 = 100 +pmu_usbvol_limit = 1 +pmu_usbcur_limit = 0 +pmu_usbvol = 4000 +pmu_usbcur = 0 +pmu_usbvol_pc = 4400 +pmu_usbcur_pc = 500 +pmu_pwroff_vol = 3300 +pmu_pwron_vol = 2900 +pmu_pekoff_time = 4000 +pmu_pekoff_en = 1 +pmu_peklong_time = 1500 +pmu_pekon_time = 1000 +pmu_pwrok_time = 64 +pmu_pwrnoe_time = 2000 +pmu_intotp_en = 1 +pmu_backupen = 1 +pmu_used2 = 0 +pmu_adpdet = port:PH02<0> +pmu_init_chgcur2 = 400 +pmu_earlysuspend_chgcur2 = 600 +pmu_suspend_chgcur2 = 1200 +pmu_resume_chgcur2 = 400 +pmu_shutdown_chgcur2 = 1200 +pmu_suspendpwroff_vol = 3500 +pmu_batdeten = 1 + +[recovery_key] +key_min = 4 +key_max = 10 + +[dvfs_table] +max_freq = 912000000 +min_freq = 720000000 +LV_count = 7 +LV1_freq = 1008000000 +LV1_volt = 1450 +LV2_freq = 912000000 +LV2_volt = 1425 +LV3_freq = 864000000 +LV3_volt = 1350 +LV4_freq = 720000000 +LV4_volt = 1250 +LV5_freq = 528000000 +LV5_volt = 1150 +LV6_freq = 312000000 +LV6_volt = 1100 +LV7_freq = 144000000 +LV7_volt = 1050 + diff --git a/config/pcduino3nano.fex b/config/pcduino3nano.fex new file mode 100644 index 000000000..13fc474ac --- /dev/null +++ b/config/pcduino3nano.fex @@ -0,0 +1,1067 @@ +[product] +version = "100" +machine = "pcduino3-nano-v10" + +[platform] +eraseflag = 1 + +[target] +boot_clock = 912 +dcdc2_vol = 1450 +dcdc3_vol = 1300 +ldo2_vol = 3000 +ldo3_vol = 2800 +ldo4_vol = 2800 +power_start = 0 +storage_type = 0 + +[clock] +pll3 = 297 +pll4 = 300 +pll6 = 600 +pll7 = 297 +pll8 = 336 + +[card_boot] +logical_start = 40960 +sprite_gpio0 = port:PH15<1><0> +sprite_work_delay = 1000 +sprite_err_delay = 100 + +[card0_boot_para] +card_ctrl = 0 +card_high_speed = 1 +card_line = 4 +sdc_d1 = port:PF00<2><1> +sdc_d0 = port:PF01<2><1> +sdc_clk = port:PF02<2><1> +sdc_cmd = port:PF03<2><1> +sdc_d3 = port:PF04<2><1> +sdc_d2 = port:PF05<2><1> + +[card2_boot_para] +card_ctrl = 2 +card_high_speed = 1 +card_line = 4 +sdc_cmd = port:PC06<3><1> +sdc_clk = port:PC07<3><1> +sdc_d0 = port:PC08<3><1> +sdc_d1 = port:PC09<3><1> +sdc_d2 = port:PC10<3><1> +sdc_d3 = port:PC11<3><1> + +[twi_para] +twi_port = 0 +twi_scl = port:PB00<2> +twi_sda = port:PB01<2> + +[uart_para] +uart_debug_port = 0 +uart_debug_tx = port:PB22<2><1> +uart_debug_rx = port:PB23<2><1> + +[uart_force_debug] +uart_debug_port = 0 +uart_debug_tx = port:PF02<4><1> +uart_debug_rx = port:PF04<4><1> + +[jtag_para] +jtag_enable = 0 +jtag_ms = port:PB14<3> +jtag_ck = port:PB15<3> +jtag_do = port:PB16<3> +jtag_di = port:PB17<3> + +[pm_para] +standby_mode = 0 + +[dram_para] +dram_baseaddr = 0x40000000 +dram_clk = 408 +dram_type = 3 +dram_rank_num = 0xffffffff +dram_chip_density = 0xffffffff +dram_io_width = 0xffffffff +dram_bus_width = 0xffffffff +dram_cas = 9 +dram_zq = 0x7a +dram_odt_en = 0 +dram_size = 0xffffffff +dram_tpr0 = 0x42d899b7 +dram_tpr1 = 0xa090 +dram_tpr2 = 0x22a00 +dram_tpr3 = 0x0 +dram_tpr4 = 0x0 +dram_tpr5 = 0x0 +dram_emr1 = 0x4 +dram_emr2 = 0x10 +dram_emr3 = 0x0 + +[mali_para] +mali_used = 1 +mali_clkdiv = 1 + +[gmac_para] +gmac_used = 1 +gmac_rxd3 = port:PA00<5><3> +gmac_rxd2 = port:PA01<5><3> +gmac_rxd1 = port:PA02<5><3> +gmac_rxd0 = port:PA03<5><3> +gmac_txd3 = port:PA04<5><3> +gmac_txd2 = port:PA05<5><3> +gmac_txd1 = port:PA06<5><3> +gmac_txd0 = port:PA07<5><3> +gmac_rxclk = port:PA08<5><3> +gmac_rxerr = port:PA09<0><3> +gmac_rxctl = port:PA10<5><3> +gmac_mdc = port:PA11<5><3> +gmac_mdio = port:PA12<5><3> +gmac_txctl = port:PA13<5><3> +gmac_txclk = port:PA14<0><3> +gmac_txck = port:PA15<5><3> +gmac_clkin = port:PA16<5><3> +gmac_txerr = port:PA17<0><3> + +[twi0_para] +twi0_used = 1 +twi0_scl = port:PB00<2> +twi0_sda = port:PB01<2> + +[twi1_para] +twi1_used = 1 +twi1_scl = port:PB18<2> +twi1_sda = port:PB19<2> + +[twi2_para] +twi2_used = 1 +twi2_scl = port:PB20<2> +twi2_sda = port:PB21<2> + +[uart_para0] +uart_used = 1 +uart_port = 0 +uart_type = 2 +uart_tx = port:PB22<2><1> +uart_rx = port:PB23<2><1> + +[uart_para1] +uart_used = 0 +uart_port = 1 +uart_type = 8 +uart_tx = port:PA10<4><1> +uart_rx = port:PA11<4><1> +uart_rts = port:PA12<4><1> +uart_cts = port:PA13<4><1> +uart_dtr = port:PA14<4><1> +uart_dsr = port:PA15<4><1> +uart_dcd = port:PA16<4><1> +uart_ring = port:PA17<4><1> + +[uart_para2] +uart_used = 1 +uart_port = 2 +uart_type = 4 +uart_tx = port:PI18<0><2> +uart_rx = port:PI19<1><2> +uart_rts = port:PI16<3><1> +uart_cts = port:PI17<3><1> + +[uart_para3] +uart_used = 0 +uart_port = 3 +uart_type = 4 +uart_tx = port:PH00<4><1> +uart_rx = port:PH01<4><1> +uart_rts = port:PH02<4><1> +uart_cts = port:PH03<4><1> + +[uart_para4] +uart_used = 0 +uart_port = 4 +uart_type = 2 +uart_tx = port:PH04<4><1> +uart_rx = port:PH05<4><1> + +[uart_para5] +uart_used = 0 +uart_port = 5 +uart_type = 2 +uart_tx = port:PH06<4><1> +uart_rx = port:PH07<4><1> + +[uart_para6] +uart_used = 0 +uart_port = 6 +uart_type = 2 +uart_tx = port:PA12<3><1> +uart_rx = port:PA13<3><1> + +[uart_para7] +uart_used = 0 +uart_port = 7 +uart_type = 2 +uart_tx = port:PA14<3><1> +uart_rx = port:PA15<3><1> + +[spi0_para] +spi_used = 1 +spi_cs_bitmap = 1 +spi_cs0 = port:PI10<0><2> +spi_cs1 = port:PI14<2> +spi_sclk = port:PI11<0><2> +spi_mosi = port:PI12<0><2> +spi_miso = port:PI13<0><2> + +[spi1_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA00<3> +spi_cs1 = port:PA04<3> +spi_sclk = port:PA01<3> +spi_mosi = port:PA02<3> +spi_miso = port:PA03<3> + +[spi2_para] +spi_used = 1 +spi_cs_bitmap = 1 +spi_cs0 = port:PC19<0><2> +spi_cs1 = port:PB13<2> +spi_sclk = port:PC20<0><2> +spi_mosi = port:PC21<0><2> +spi_miso = port:PC22<0><2> + +[spi3_para] +spi_used = 0 +spi_cs_bitmap = 1 +spi_cs0 = port:PA05<3> +spi_cs1 = port:PA09<3> +spi_sclk = port:PA06<3> +spi_mosi = port:PA07<3> +spi_miso = port:PA08<3> + +[spi_devices] +spi_dev_num = 2 + +[spi_board0] +modalias = "spidev" +max_speed_hz = 12000000 +bus_num = 0 +chip_select = 0 +mode = 3 +full_duplex = 0 +manual_cs = 0 + +[spi_board1] +modalias = "spidev" +max_speed_hz = 12000000 +bus_num = 2 +chip_select = 0 +mode = 0 +full_duplex = 0 +manual_cs = 0 + +[rtp_para] +rtp_used = 1 +rtp_screen_size = 5 +rtp_regidity_level = 5 +rtp_press_threshold_enable = 0 +rtp_press_threshold = 0x1f40 +rtp_sensitive_level = 0xf +rtp_exchange_x_y_flag = 0 + +[ctp_para] +ctp_used = 1 +ctp_twi_id = 2 +ctp_twi_name = "gslX680" +ctp_screen_max_x = 1024 +ctp_screen_max_y = 600 +ctp_revert_x_flag = 0 +ctp_revert_y_flag = 0 +ctp_exchange_x_y_flag = 0 +ctp_int_port = port:PH10<6> +ctp_wakeup = + +[tkey_para] +tkey_used = 0 +tkey_twi_id = 2 +tkey_twi_addr = 0x62 +tkey_int = port:PI13<6> + +[motor_para] +motor_used = 0 +motor_shake = port:PB03<1><1> + +[nand_para] +nand_used = 1 +nand_we = port:PC00<2> +nand_ale = port:PC01<2> +nand_cle = port:PC02<2> +nand_ce1 = port:PC03<2> +nand_ce0 = port:PC04<2> +nand_nre = port:PC05<2> +nand_rb0 = port:PC06<2> +nand_rb1 = port:PC07<2> +nand_d0 = port:PC08<2> +nand_d1 = port:PC09<2> +nand_d2 = port:PC10<2> +nand_d3 = port:PC11<2> +nand_d4 = port:PC12<2> +nand_d5 = port:PC13<2> +nand_d6 = port:PC14<2> +nand_d7 = port:PC15<2> +nand_wp = port:PC16<2> +nand_ce2 = port:PC17<2> +nand_ce3 = port:PC18<2> +nand_ce4 = +nand_ce5 = +nand_ce6 = +nand_ce7 = +nand_spi = port:PC23<3> +nand_ndqs = port:PC24<2> +good_block_ratio = 0 + +[boot_disp] +output_type = 3 +output_mode = 5 + +[disp_init] +disp_init_enable = 1 +disp_mode = 0 +screen0_output_type = 3 +screen0_output_mode = 5 +screen1_output_type = 0 +screen1_output_mode = 4 +fb0_framebuffer_num = 2 +fb0_format = 10 +fb0_pixel_sequence = 0 +fb0_scaler_mode_enable = 1 +fb0_width = 0 +fb0_height = 0 +fb1_framebuffer_num = 2 +fb1_format = 10 +fb1_pixel_sequence = 0 +fb1_scaler_mode_enable = 0 +fb1_width = 0 +fb1_height = 0 +lcd0_backlight = 197 +lcd1_backlight = 197 +lcd0_bright = 50 +lcd0_contrast = 50 +lcd0_saturation = 57 +lcd0_hue = 50 +lcd1_bright = 50 +lcd1_contrast = 50 +lcd1_saturation = 57 +lcd1_hue = 50 + +[lcd0_para] +lcd_used = 0 +lcd_x = 1024 +lcd_y = 600 +lcd_width = 0 +lcd_height = 0 +lcd_dclk_freq = 51 +lcd_pwm_not_used = 1 +lcd_pwm_ch = 0 +lcd_pwm_freq = 10000 +lcd_pwm_pol = 0 +lcd_if = 3 +lcd_hbp = 310 +lcd_ht = 1340 +lcd_vbp = 30 +lcd_vt = 1268 +lcd_vspw = 0 +lcd_hspw = 0 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 0x10000000 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x00000000 +lcd_gamma_tbl_1 = 0x00010101 +lcd_gamma_tbl_255 = 0x00ffffff +lcd_bl_en_used = 0 +lcd_bl_en = port:PH07<1><0><1> +lcd_power_used = 0 +lcd_power = port:PH08<1><0><1> +lcd_pwm_used = 0 +lcd_pwm = port:PB02<2><0> +lcdd0 = port:PD00<3> +lcdd1 = port:PD01<3> +lcdd2 = port:PD02<3> +lcdd3 = port:PD03<3> +lcdd4 = port:PD04<3> +lcdd5 = port:PD05<3> +lcdd6 = port:PD06<3> +lcdd7 = port:PD07<3> +lcdd8 = port:PD08<3> +lcdd9 = port:PD09<3> + +[lcd1_para] +lcd_used = 0 +lcd_x = 1024 +lcd_y = 600 +lcd_width = 0 +lcd_height = 0 +lcd_dclk_freq = 51 +lcd_pwm_not_used = 0 +lcd_pwm_ch = 0 +lcd_pwm_freq = 10000 +lcd_pwm_pol = 0 +lcd_if = 3 +lcd_hbp = 310 +lcd_ht = 1340 +lcd_vbp = 30 +lcd_vt = 1268 +lcd_vspw = 0 +lcd_hspw = 0 +lcd_hv_if = 0 +lcd_hv_smode = 0 +lcd_hv_s888_if = 0 +lcd_hv_syuv_if = 0 +lcd_lvds_ch = 0 +lcd_lvds_mode = 0 +lcd_lvds_bitwidth = 0 +lcd_lvds_io_cross = 0 +lcd_cpu_if = 0 +lcd_frm = 0 +lcd_io_cfg0 = 0 +lcd_gamma_correction_en = 0 +lcd_gamma_tbl_0 = 0x00000000 +lcd_gamma_tbl_1 = 0x00010101 +lcd_gamma_tbl_255 = 0x00ffffff +lcd_bl_en_used = 1 +lcd_bl_en = port:PH07<1><1> +lcd_power_used = 1 +lcd_power = port:PH08<1><1> +lcd_pwm_used = 1 +lcd_pwm = port:PH06<1><0> +lcd_gpio_0 = +lcd_gpio_1 = +lcd_gpio_2 = +lcd_gpio_3 = +lcdd10 = port:PD10<3> +lcdd11 = port:PD11<3> +lcdd12 = port:PD12<3> +lcdd13 = port:PD13<3> +lcdd14 = port:PD14<3> +lcdd15 = port:PD15<3> +lcdd16 = port:PD16<3> +lcdd17 = port:PD17<3> +lcdd18 = port:PD18<3> +lcdd19 = port:PD19<3> + +[tv_out_dac_para] +dac_used = 1 +dac0_src = 4 +dac1_src = 5 +dac2_src = 6 +dac3_src = 0 + +[hdmi_para] +hdmi_used = 1 +hdcp_enable = 0 + +[i2s2_para] +i2s_channel = 2 +i2s_master = 4 +i2s_select = 1 +audio_format = 1 +signal_inversion = 1 +over_sample_rate = 256 +sample_resolution = 16 +word_select_size = 32 +pcm_sync_period = 256 +msb_lsb_first = 0 +sign_extend = 0 +slot_index = 0 +slot_width = 16 +frame_width = 1 +tx_data_mode = 0 +rx_data_mode = 0 + +[camera_list_para] +camera_list_para_used = 1 +ov7670 = 0 +gc0308 = 1 +gt2005 = 0 +hi704 = 0 +sp0838 = 0 +mt9m112 = 0 +mt9m113 = 0 +ov2655 = 0 +hi253 = 0 +gc0307 = 0 +mt9d112 = 0 +ov5640 = 1 +gc2015 = 0 +ov2643 = 0 +gc0329 = 0 +gc0309 = 0 +tvp5150 = 0 +s5k4ec = 0 +ov5650_mv9335 = 0 +siv121d = 0 + +[csi0_para] +csi_used = 1 +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "gc2035" +csi_if = 0 +csi_iovdd = "" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = +csi_vol_dvdd = +csi_vol_avdd = +csi_vflip = 0 +csi_hflip = 0 +csi_flash_pol = 0 +csi_facing = 0 +csi_twi_id = 1 +csi_twi_addr = 0x78 +csi_pck = port:PE00<3> +csi_ck = port:PE01<3> +csi_hsync = port:PE02<3> +csi_vsync = port:PE03<3> +csi_d0 = port:PE04<3> +csi_d1 = port:PE05<3> +csi_d2 = port:PE06<3> +csi_d3 = port:PE07<3> +csi_d4 = port:PE08<3> +csi_d5 = port:PE09<3> +csi_d6 = port:PE10<3> +csi_d7 = port:PE11<3> +csi_reset = port:PH27<1><1> +csi_power_en = port:PH26<1><0> +csi_stby = + +[csi1_para] +csi_used = 0 +csi_dev_qty = 1 +csi_stby_mode = 0 +csi_mname = "gc0308" +csi_if = 0 +csi_iovdd = "" +csi_avdd = "" +csi_dvdd = "" +csi_vol_iovdd = +csi_vol_dvdd = +csi_vol_avdd = +csi_vflip = 0 +csi_hflip = 0 +csi_flash_pol = 0 +csi_facing = 1 +csi_twi_id = 1 +csi_twi_addr = 0x42 +csi_pck = port:PG00<3> +csi_ck = port:PG01<3> +csi_hsync = port:PG02<3> +csi_vsync = port:PG03<3> +csi_d0 = port:PG04<3> +csi_d1 = port:PG05<3> +csi_d2 = port:PG06<3> +csi_d3 = port:PG07<3> +csi_d4 = port:PG08<3> +csi_d5 = port:PG09<3> +csi_d6 = port:PG10<3> +csi_d7 = port:PG11<3> +csi_reset = port:PH14<1><0> +csi_power_en = +csi_stby = port:PH17<1><0> + +[tvout_para] +tvout_used = 1 +tvout_channel_num = 1 + +[tvin_para] +tvin_used = 0 +tvin_channel_num = 4 + +[sata_para] +sata_used = 1 +sata_power_en = port:PH02<1><1> + +[mmc0_para] +sdc_used = 1 +sdc_detmode = 1 +sdc_buswidth = 4 +sdc_clk = port:PF02<2><1><2> +sdc_cmd = port:PF03<2><1><2> +sdc_d0 = port:PF01<2><1><2> +sdc_d1 = port:PF00<2><1><2> +sdc_d2 = port:PF05<2><1><2> +sdc_d3 = port:PF04<2><1><2> +sdc_det = port:PH01<0><1> +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc1_para] +sdc_used = 0 +sdc_detmode = 4 +sdc_buswidth = 4 +sdc_clk = port:PG00<2><1><2> +sdc_cmd = port:PG01<2><1><2> +sdc_d0 = port:PG02<2><1><2> +sdc_d1 = port:PG03<2><1><2> +sdc_d2 = port:PG04<2><1><2> +sdc_d3 = port:PG05<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc2_para] +sdc_used = 0 +sdc_detmode = 3 +sdc_buswidth = 4 +sdc_cmd = port:PC06<3><1><2> +sdc_clk = port:PC07<3><1><2> +sdc_d0 = port:PC08<3><1><2> +sdc_d1 = port:PC09<3><1><2> +sdc_d2 = port:PC10<3><1><2> +sdc_d3 = port:PC11<3><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 0 +sdc_regulator = "none" + +[mmc3_para] +sdc_used = 0 +sdc_detmode = 4 +sdc_buswidth = 4 +sdc_cmd = port:PI04<2><1><2> +sdc_clk = port:PI05<2><1><2> +sdc_d0 = port:PI06<2><1><2> +sdc_d1 = port:PI07<2><1><2> +sdc_d2 = port:PI08<2><1><2> +sdc_d3 = port:PI09<2><1><2> +sdc_det = +sdc_use_wp = 0 +sdc_wp = +sdc_isio = 1 +sdc_regulator = "none" + +[ms_para] +ms_used = 0 +ms_bs = port:PH06<5> +ms_clk = port:PH07<5> +ms_d0 = port:PH08<5> +ms_d1 = port:PH09<5> +ms_d2 = port:PH10<5> +ms_d3 = port:PH11<5> +ms_det = + +[smc_para] +smc_used = 0 +smc_rst = port:PH13<5> +smc_vppen = port:PH14<5> +smc_vppp = port:PH15<5> +smc_det = port:PH16<5> +smc_vccen = port:PH17<5> +smc_sck = port:PH18<5> +smc_sda = port:PH19<5> + +[ps2_0_para] +ps2_used = 0 +ps2_scl = port:PI20<2><1> +ps2_sda = port:PI21<2><1> + +[ps2_1_para] +ps2_used = 0 +ps2_scl = port:PI14<3><1> +ps2_sda = port:PI15<3><1> + +[can_para] +can_used = 0 +can_tx = port:PA16<3> +can_rx = port:PA17<3> + +[keypad_para] +kp_used = 0 +kp_in_size = 8 +kp_out_size = 8 +kp_in0 = port:PH08<4><1> +kp_in1 = port:PH09<4><1> +kp_in2 = port:PH10<4><1> +kp_in3 = port:PH11<4><1> +kp_in4 = port:PH14<4><1> +kp_in5 = port:PH15<4><1> +kp_in6 = port:PH16<4><1> +kp_in7 = port:PH17<4><1> +kp_out0 = port:PH18<4><1> +kp_out1 = port:PH19<4><1> +kp_out2 = port:PH22<4><1> +kp_out3 = port:PH23<4><1> +kp_out4 = port:PH24<4><1> +kp_out5 = port:PH25<4><1> +kp_out6 = port:PH26<4><1> +kp_out7 = port:PH27<4><1> + +[usbc0] +usb_used = 1 +usb_port_type = 0 +usb_detect_type = 0 +usb_id_gpio = port:PH04<0><1> +usb_det_vbus_gpio = "axp_ctrl" +usb_drv_vbus_gpio = port:PB09<1><0><0> +usb_host_init_state = 0 +usb_restric_flag = 0 +usb_restric_voltage = 3550000 +usb_restric_capacity = 5 + +[usbc1] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PH11<1><0><0> +usb_restrict_gpio = +usb_host_init_state = 1 +usb_restric_flag = 0 + +[usbc2] +usb_used = 1 +usb_port_type = 1 +usb_detect_type = 0 +usb_drv_vbus_gpio = port:PH03<1><0><0> +usb_restrict_gpio = +usb_host_init_state = 1 +usb_restric_flag = 0 + +[usb_feature] +vendor_id = 0x18D1 +mass_storage_id = 0x0001 +adb_id = 0x0002 +manufacturer_name = "USB Developer" +product_name = "Android" +serial_number = "20080411" + +[msc_feature] +vendor_name = "USB 2.0" +product_name = "USB Flash Driver" +release = 100 +luns = 1 + +[gsensor_para] +gsensor_used = 0 +gsensor_twi_id = 1 +gsensor_int1 = +gsensor_int2 = + +[gps_para] +gps_used = 0 +gps_spi_id = 2 +gps_spi_cs_num = 0 +gps_lradc = 1 +gps_clk = port:PI00<2> +gps_sign = port:PI01<2> +gps_mag = port:PI02<2> +gps_vcc_en = port:PC22<1><0> +gps_osc_en = port:PI14<1><0> +gps_rx_en = port:PI15<1><0> + +[wifi_para] +wifi_used = 0 +wifi_sdc_id = 3 +wifi_usbc_id = 2 +wifi_usbc_type = 1 +wifi_mod_sel = 7 +wifi_power = "" +rtk_rtl8723as_wl_dis = port:PH09<1><0> +rtk_rtl8723as_bt_dis = port:PB05<1><0> +rtk_rtl8723as_wl_host_wake = port:PH10<0><0> +rtk_rtl8723as_bt_host_wake = port:PI21<0><0> +ap6xxx_wl_regon = port:PH09<1><0> +ap6xxx_wl_host_wake = port:PH10<0><0> +ap6xxx_bt_regon = port:PB05<1><0> +ap6xxx_bt_wake = port:PI20<1><0> +ap6xxx_bt_host_wake = port:PI21<0><0> + +[usb_wifi_para] +usb_wifi_used = 1 +usb_wifi_usbc_num = 2 + +[3g_para] +3g_used = 0 +3g_usbc_num = 2 +3g_uart_num = 0 +3g_pwr = +3g_wakeup = +3g_int = + +[gy_para] +gy_used = 0 +gy_twi_id = 1 +gy_twi_addr = 0 +gy_int1 = port:PH18<6><1> +gy_int2 = port:PH19<6><1> + +[ls_para] +ls_used = 0 +ls_twi_id = 1 +ls_twi_addr = 0 +ls_int = port:PH20<6><1> + +[compass_para] +compass_used = 0 +compass_twi_id = 1 +compass_twi_addr = 0 +compass_int = port:PI13<6><1> + +[bt_para] +bt_used = 0 +bt_uart_id = 2 +bt_wakeup = port:PI20<1> +bt_gpio = port:PI21<1> +bt_rst = port:PB05<1> + +[i2s_para] +i2s_used = 0 +i2s_channel = 2 +i2s_master = 4 +i2s_select = 1 +audio_format = 1 +signal_inversion = 1 +over_sample_rate = 256 +sample_resolution = 16 +word_select_size = 32 +pcm_sync_period = 256 +msb_lsb_first = 0 +sign_extend = 0 +slot_index = 0 +slot_width = 16 +frame_width = 1 +tx_data_mode = 0 +rx_data_mode = 0 +i2s_mclk = port:PB05<2><1> +i2s_bclk = port:PB06<2><1> +i2s_lrclk = port:PB07<2><1> +i2s_dout0 = port:PB08<2><1> +i2s_dout1 = +i2s_dout2 = +i2s_dout3 = +i2s_din = port:PB12<2><1> + +[pcm_para] +pcm_used = 0 +pcm_channel = 2 +pcm_master = 4 +pcm_select = 1 +audio_format = 4 +signal_inversion = 1 +over_sample_rate = 256 +sample_resolution = 16 +word_select_size = 32 +pcm_sync_period = 256 +msb_lsb_first = 0 +sign_extend = 0 +slot_index = 0 +slot_width = 16 +frame_width = 1 +tx_data_mode = 0 +rx_data_mode = 0 +pcm_mclk = port:PA09<6><1> +pcm_bclk = port:PA14<6><1> +pcm_lrclk = port:PA15<6><1> +pcm_dout0 = port:PA16<6><1> +pcm_dout1 = +pcm_dout2 = +pcm_dout3 = +pcm_din = port:PA17<6><1> + +[spdif_para] +spdif_used = 0 +spdif_mclk = +spdif_dout = port:PB13<4><1> +spdif_din = + +[audio_para] +audio_used = 1 +audio_pa_ctrl = port:PH15<1><0> +capture_used = 1 + +[switch_para] +switch_used = 0 + +[ir_para] +ir_used = 1 +ir0_rx = port:PB04<2> + +[pmu_para] +pmu_used = 1 +pmu_twi_addr = 52 +pmu_twi_id = 0 +pmu_irq_id = 32 +pmu_battery_rdc = 100 +pmu_battery_cap = 3200 +pmu_init_chgcur = 300 +pmu_earlysuspend_chgcur = 600 +pmu_suspend_chgcur = 1000 +pmu_resume_chgcur = 300 +pmu_shutdown_chgcur = 1000 +pmu_init_chgvol = 4200 +pmu_init_chgend_rate = 15 +pmu_init_chg_enabled = 1 +pmu_init_adc_freq = 100 +pmu_init_adc_freqc = 100 +pmu_init_chg_pretime = 50 +pmu_init_chg_csttime = 720 +pmu_bat_para1 = 0 +pmu_bat_para2 = 0 +pmu_bat_para3 = 0 +pmu_bat_para4 = 0 +pmu_bat_para5 = 5 +pmu_bat_para6 = 8 +pmu_bat_para7 = 11 +pmu_bat_para8 = 22 +pmu_bat_para9 = 33 +pmu_bat_para10 = 43 +pmu_bat_para11 = 50 +pmu_bat_para12 = 59 +pmu_bat_para13 = 71 +pmu_bat_para14 = 83 +pmu_bat_para15 = 92 +pmu_bat_para16 = 100 +pmu_usbvol_limit = 1 +pmu_usbcur_limit = 0 +pmu_usbvol = 4000 +pmu_usbcur = 0 +pmu_usbvol_pc = 4400 +pmu_usbcur_pc = 500 +pmu_pwroff_vol = 3300 +pmu_pwron_vol = 2900 +pmu_pekoff_time = 6000 +pmu_pekoff_en = 1 +pmu_peklong_time = 1500 +pmu_pekon_time = 1000 +pmu_pwrok_time = 64 +pmu_pwrnoe_time = 2000 +pmu_intotp_en = 1 +pmu_used2 = 0 +pmu_adpdet = port:PH02<0> +pmu_init_chgcur2 = 400 +pmu_earlysuspend_chgcur2 = 600 +pmu_suspend_chgcur2 = 1200 +pmu_resume_chgcur2 = 400 +pmu_shutdown_chgcur2 = 1200 +pmu_suspendpwroff_vol = 3500 +pmu_batdeten = 0 + +[recovery_key] +key_min = 4 +key_max = 6 + +[dvfs_table] +max_freq = 912000000 +min_freq = 720000000 +LV_count = 7 +LV1_freq = 1008000000 +LV1_volt = 1450 +LV2_freq = 912000000 +LV2_volt = 1425 +LV3_freq = 864000000 +LV3_volt = 1350 +LV4_freq = 720000000 +LV4_volt = 1250 +LV5_freq = 528000000 +LV5_volt = 1150 +LV6_freq = 312000000 +LV6_volt = 1100 +LV7_freq = 144000000 +LV7_volt = 1050 + +[gpio_para] +gpio_used = 1 +gpio_num = 51 +gpio_pin_0 = port:PI19<1><2> +gpio_pin_1 = port:PI18<0><2> +gpio_pin_2 = port:PH07<0><2> +gpio_pin_3 = port:PH06<0><2> +gpio_pin_4 = port:PH08<0><2> +gpio_pin_5 = port:PB02<0><2> +gpio_pin_6 = port:PI03<0><2> +gpio_pin_7 = port:PH09<0><2> +gpio_pin_8 = port:PH10<0><2> +gpio_pin_9 = port:PH05<0><2> +gpio_pin_10 = port:PI10<0><2> +gpio_pin_11 = port:PI12<0><2> +gpio_pin_12 = port:PI13<0><2> +gpio_pin_13 = port:PI11<0><2> +gpio_pin_14 = port:PH11<0><2> +gpio_pin_15 = port:PH12<0><2> +gpio_pin_16 = port:PH13<0><2> +gpio_pin_17 = port:PH14<0><2> +gpio_pin_18 = port:PH15<1><0> +gpio_pin_19 = port:PH16<1><0> +gpio_pin_20 = port:PC19<0><2> +gpio_pin_21 = port:PC21<0><2> +gpio_pin_22 = port:PC22<0><2> +gpio_pin_23 = port:PC20<0><2> +gpio_pin_24 = port:PD10<3> +gpio_pin_25 = port:PD11<3> +gpio_pin_26 = port:PD12<3> +gpio_pin_27 = port:PD13<3> +gpio_pin_28 = port:PD14<3> +gpio_pin_29 = port:PD15<3> +gpio_pin_30 = port:PD16<3> +gpio_pin_31 = port:PD17<3> +gpio_pin_32 = port:PD18<3> +gpio_pin_33 = port:PD19<3> +gpio_pin_34 = port:PE04<3> +gpio_pin_35 = port:PE05<3> +gpio_pin_36 = port:PE06<3> +gpio_pin_37 = port:PE07<3> +gpio_pin_38 = port:PE08<3> +gpio_pin_39 = port:PE09<3> +gpio_pin_40 = port:PE10<3> +gpio_pin_41 = port:PE11<3> +gpio_pin_42 = port:PB19<2> +gpio_pin_43 = port:PB18<2> +gpio_pin_44 = port:PE02<3> +gpio_pin_45 = port:PE03<3> +gpio_pin_46 = port:PE00<3> +gpio_pin_47 = port:PE01<3> +gpio_pin_48 = port:PH26<1><0> +gpio_pin_49 = port:PH27<1><1> +gpio_pin_50 = port:PD02<1><1> +gpio_pin_51 = port:PI19<0><1> + +[sb_pwm0] +pwm_gpio = port:PH06<1> + +[sb_pwm1] +pwm_gpio = port:PB02<2> + +[sb_pwm2] +pwm_gpio = port:PI03<2> + +[sb_pwm3] +pwm_gpio = port:PH05<1> + +[sb_pwm4] +pwm_gpio = port:PI10<1> + +[sb_pwm5] +pwm_gpio = port:PI12<1> + +[sb_keypad_para] +sb_key_used = 1 +key_num = 3 +key_pin_0 = port:PH17<6><1><3> +key_code_0 = 1 +key_pin_1 = port:PH18<6><1><3> +key_code_1 = 57 +key_pin_2 = port:PH19<6><1><3> +key_code_2 = 28 diff --git a/config/sources.list.jessie b/config/sources.list.jessie index 7c80b8409..078af0bc4 100644 --- a/config/sources.list.jessie +++ b/config/sources.list.jessie @@ -1,8 +1,9 @@ -deb http://ftp.de.debian.org/debian testing main contrib non-free -deb-src http://ftp.de.debian.org/debian testing main contrib non-free +deb http://httpredir.debian.org/debian jessie main contrib non-free +deb-src http://httpredir.debian.org/debian jessie main contrib non-free -deb http://ftp.debian.org/debian/ jessie-updates main contrib non-free -deb-src http://ftp.debian.org/debian/ jessie-updates main contrib non-free +deb http://httpredir.debian.org/debian/ jessie-updates main contrib non-free +deb-src http://httpredir.debian.org/debian/ jessie-updates main contrib non-free +# security packages come always from main repository deb http://security.debian.org/ jessie/updates main contrib non-free -deb-src http://security.debian.org/ jessie/updates main contrib non-free +deb-src http://security.debian.org/ jessie/updates main contrib non-free \ No newline at end of file diff --git a/config/sources.list.trusty b/config/sources.list.trusty index 774c995c4..48618a2f1 100644 --- a/config/sources.list.trusty +++ b/config/sources.list.trusty @@ -1,3 +1,4 @@ -deb http://ports.ubuntu.com/ubuntu-ports/ trusty main universe multiverse -deb http://ports.ubuntu.com/ubuntu-ports/ trusty-updates main universe multiverse -deb http://ports.ubuntu.com/ubuntu-ports/ trusty-proposed main universe multiverse \ No newline at end of file +deb http://ports.ubuntu.com/ trusty main restricted universe multiverse +deb http://ports.ubuntu.com/ trusty-security main restricted universe multiverse +deb http://ports.ubuntu.com/ trusty-updates main restricted universe multiverse +deb http://ports.ubuntu.com/ trusty-backports main restricted universe multiverse diff --git a/config/sources.list.wheezy b/config/sources.list.wheezy index b5ad5034c..fb9c5494a 100644 --- a/config/sources.list.wheezy +++ b/config/sources.list.wheezy @@ -1,9 +1,12 @@ -deb http://ftp.de.debian.org/debian stable main contrib non-free -deb-src http://ftp.de.debian.org/debian stable main contrib non-free +deb http://httpredir.debian.org/debian wheezy main contrib non-free +deb-src http://httpredir.debian.org/debian wheezy main contrib non-free -deb http://ftp.debian.org/debian/ wheezy-updates main contrib non-free -deb-src http://ftp.debian.org/debian/ wheezy-updates main contrib non-free +deb http://httpredir.debian.org/debian/ wheezy-updates main contrib non-free +deb-src http://httpredir.debian.org/debian/ wheezy-updates main contrib non-free +deb http://httpredir.debian.org/debian wheezy-backports main contrib non-free +deb-src http://httpredir.debian.org/debian wheezy-backports main contrib non-free + +# security packages come always from main repository deb http://security.debian.org/ wheezy/updates main contrib non-free -deb-src http://security.debian.org/ wheezy/updates main contrib non-free - +deb-src http://security.debian.org/ wheezy/updates main contrib non-free \ No newline at end of file diff --git a/config/ttyS0.conf b/config/ttyS0.conf new file mode 100644 index 000000000..8128da39f --- /dev/null +++ b/config/ttyS0.conf @@ -0,0 +1,5 @@ +start on stopped rc RUNLEVEL=[2345] +stop on runlevel [!2345] + +respawn +exec /sbin/getty --noclear 115200 ttyS0 \ No newline at end of file diff --git a/config/uEnv.bananapi b/config/uEnv.bananapi deleted file mode 100644 index f13c41946..000000000 --- a/config/uEnv.bananapi +++ /dev/null @@ -1,5 +0,0 @@ -console=tty1 -root=/dev/mmcblk0p1 rootwait -extraargs=rootfstype=ext4 sunxi_ve_mem_reserve=0 sunxi_g2d_mem_reserve=0 sunxi_no_mali_mem_reserve sunxi_fb_mem_reserve=16 hdmi.audio=EDID:0 disp.screen0_output_mode=EDID:1280x720p60 panic=10 consoleblank=0 -script=bananapi.bin -kernel=uImage diff --git a/config/uEnv.cubieboard2 b/config/uEnv.cubieboard2 deleted file mode 100644 index 055d75c06..000000000 --- a/config/uEnv.cubieboard2 +++ /dev/null @@ -1,5 +0,0 @@ -console=tty1 -root=/dev/mmcblk0p1 rootwait -extraargs=rootfstype=ext4 sunxi_ve_mem_reserve=0 sunxi_g2d_mem_reserve=0 sunxi_no_mali_mem_reserve sunxi_fb_mem_reserve=16 hdmi.audio=EDID:0 disp.screen0_output_mode=EDID:1280x720p60 panic=10 consoleblank=0 -script=cubieboard2.bin -kernel=uImage diff --git a/config/uEnv.cubietruck b/config/uEnv.cubietruck deleted file mode 100644 index 513ff1512..000000000 --- a/config/uEnv.cubietruck +++ /dev/null @@ -1,5 +0,0 @@ -console=tty1 -root=/dev/mmcblk0p1 rootwait -extraargs=rootfstype=ext4 sunxi_ve_mem_reserve=0 sunxi_g2d_mem_reserve=0 sunxi_no_mali_mem_reserve sunxi_fb_mem_reserve=16 hdmi.audio=EDID:0 disp.screen0_output_mode=EDID:1280x720p60 panic=10 consoleblank=0 -script=cubietruck.bin -kernel=uImage diff --git a/config/uEnv.cubox-i b/config/uEnv.cubox-i deleted file mode 100644 index 284e4b572..000000000 --- a/config/uEnv.cubox-i +++ /dev/null @@ -1 +0,0 @@ -mmcargs=setenv bootargs root=/dev/mmcblk0p1 rootfstype=ext4 rootwait console=ttymxc0,115200 cma=32M video=mxcfb0:dev=hdmi,1920x1080M@60,if=RGB24,bpp=32 rd.dm=0 rd.luks=0 rd.lvm=0 raid=noautodetect pci=nomsi ahci_imx.hotplug=1 quiet diff --git a/configuration.sh b/configuration.sh new file mode 100644 index 000000000..97d17d607 --- /dev/null +++ b/configuration.sh @@ -0,0 +1,455 @@ +#!/bin/bash +# +# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com +# +# This file is licensed under the terms of the GNU General Public +# License version 2. This program is licensed "as is" without any +# warranty of any kind, whether express or implied. +# +# This file is a part of tool chain https://github.com/igorpecovnik/lib +# +# +# Board configurations +# +# + + +# vaid options for automatic building +# +# build 0 = don't build +# build 1 = old kernel +# build 2 = next kernel +# build 3 = both kernels + + +#--------------------------------------------------------------------------------------------------------------------------------- +# common options +#--------------------------------------------------------------------------------------------------------------------------------- + + +REVISION="4.71" # all boards have same revision +SDSIZE="4000" # SD image size in MB +TZDATA=`cat /etc/timezone` # Timezone for target is taken from host or defined here. +USEALLCORES="yes" # Use all CPU cores for compiling +SYSTEMD="no" # Enable or disable systemd on Jessie. +OFFSET="1" # Bootloader space in MB (1 x 2048 = default) +BOOTSIZE="0" # Mb size of boot partition +UBOOTTAG="v2015.10" # U-boot TAG +BOOTLOADER="git://git.denx.de/u-boot.git" # mainline u-boot sources +BOOTSOURCE="u-boot" # mainline u-boot local directory +BOOTDEFAULT="master" # default branch that git checkout works properly +LINUXDEFAULT="HEAD" # default branch that git checkout works properly +MISC1="https://github.com/linux-sunxi/sunxi-tools.git" # Allwinner fex compiler / decompiler +MISC1_DIR="sunxi-tools" # local directory +MISC2="" # Reserved +MISC2_DIR="" # local directory +MISC3="https://github.com/dz0ny/rt8192cu --depth 1" # Realtek drivers +MISC3_DIR="rt8192cu" # local directory +MISC4="https://github.com/notro/fbtft" # Small TFT display driver +MISC4_DIR="fbtft-drivers" # local directory +MISC5="https://github.com/hglm/a10disp/ --depth 1" # Display changer for Allwinner +MISC5_DIR="sunxi-display-changer" # local directory + + +#--------------------------------------------------------------------------------------------------------------------------------- +# If KERNELTAG is not defined, let's compile latest stable. Vanilla kernel only +#--------------------------------------------------------------------------------------------------------------------------------- +[[ -z "$KERNELTAG" ]] && KERNELTAG="v"`wget -qO- https://www.kernel.org/finger_banner | grep "The latest st" | awk '{print $NF}'` + + +#--------------------------------------------------------------------------------------------------------------------------------- +# common for legacy allwinner kernel-source +#--------------------------------------------------------------------------------------------------------------------------------- +# dan and me +LINUXKERNEL="https://github.com/dan-and/linux-sunxi --depth 1" +LINUXSOURCE="linux-sunxi" +LINUXFAMILY="sunxi" +LINUXCONFIG="linux-sunxi" + + +# linux-sunxi +LINUXKERNEL="https://github.com/linux-sunxi/linux-sunxi -b sunxi-3.4 --depth 1" +LINUXSOURCE="linux-sunxi-dev" +LINUXFAMILY="sun7i" +LINUXCONFIG="linux-sun7i" + +CPUMIN="480000" +CPUMAX="1010000" + + +#--------------------------------------------------------------------------------------------------------------------------------- +# choose configuration +#--------------------------------------------------------------------------------------------------------------------------------- +case $BOARD in + + +cubieboard4)#disabled +#--------------------------------------------------------------------------------------------------------------------------------- +# Cubieboards 3.4.x +#--------------------------------------------------------------------------------------------------------------------------------- +OFFSET="20" +BOOTSIZE="16" +BOOTCONFIG="Bananapi_defconfig" # we don't use it. binnary +CPUMIN="1200000" +CPUMAX="1800000" +LINUXFAMILY="sun9i" +LINUXKERNEL="https://github.com/cubieboard/CC-A80-kernel-source" +LINUXSOURCE="linux-sun9i" +LINUXCONFIG="linux-sun9i" +;; + + +aw-som-a20)#enabled +#description A20 dual core SoM +#build 0 +#--------------------------------------------------------------------------------------------------------------------------------- +# https://aw-som.com/ +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTCONFIG="Awsom_defconfig" +MODULES="hci_uart gpio_sunxi rfcomm hidp bonding spi_sun7i" +MODULES_NEXT="bonding" +;; + + +cubieboard)#enabled +#description A10 single core 1Gb SoC +#build 3 +#--------------------------------------------------------------------------------------------------------------------------------- +# Cubieboard +#--------------------------------------------------------------------------------------------------------------------------------- +LINUXFAMILY="sun4i" +LINUXCONFIG="linux-sun4i" +BOOTCONFIG="Cubieboard_config" +MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sunxi" +MODULES_NEXT="bonding" +;; + + +cubieboard2)#enabled +#description A20 dual core 1Gb SoC +#build 3 +#--------------------------------------------------------------------------------------------------------------------------------- +# Cubieboard +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTCONFIG="Cubieboard2_config" +MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i" +MODULES_NEXT="bonding" +;; + + +cubietruck)#enabled +#description A20 dual core 2Gb SoC Wifi +#build 3 +#--------------------------------------------------------------------------------------------------------------------------------- +# Cubieboard +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTCONFIG="Cubietruck_config" +MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i ap6210" +MODULES_NEXT="brcmfmac rfcomm hidp bonding" +;; + + +lime-a10)#enabled +#description A10 single core 512Mb SoC +#build 3 +#--------------------------------------------------------------------------------------------------------------------------------- +# Olimex Lime +#--------------------------------------------------------------------------------------------------------------------------------- +LINUXKERNEL="https://github.com/linux-sunxi/linux-sunxi" +LINUXSOURCE="linux-sunxi-dev" +LINUXFAMILY="sun4i" +LINUXCONFIG="linux-sun4i" +BOOTCONFIG="A10-OLinuXino-Lime_defconfig" +MODULES="hci_uart gpio_sunxi rfcomm hidp bonding spi_sun7i 8021q a20_tp" +MODULES_NEXT="bonding" +;; + + +lime)#enabled +#description A20 dual core 512Mb SoC +#build 3 +#--------------------------------------------------------------------------------------------------------------------------------- +# Olimex Lime +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTCONFIG="A20-OLinuXino-Lime_defconfig" +MODULES="hci_uart gpio_sunxi rfcomm hidp bonding spi_sun7i 8021q a20_tp" +MODULES_NEXT="bonding" +;; + + +lime2)#enabled +#description A20 dual core 1Gb SoC +#build 3 +#--------------------------------------------------------------------------------------------------------------------------------- +# Olimex Lime 2 +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTCONFIG="A20-OLinuXino-Lime2_defconfig" +MODULES="hci_uart gpio_sunxi rfcomm hidp bonding spi_sun7i 8021q a20_tp" +MODULES_NEXT="bonding" +;; + + +micro)#enabled +#description A20 dual core 1Gb SoC +#build 3 +#--------------------------------------------------------------------------------------------------------------------------------- +# Olimex Lime mainline kernel / experimental +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTCONFIG="A20-OLinuXino_MICRO_config" +MODULES="hci_uart gpio_sunxi rfcomm hidp bonding spi_sun7i 8021q a20_tp" +MODULES_NEXT="bonding" +;; + + +pcduino3nano)#enabled +#description A20 dual core 1Gb SoC +#build 3 +#--------------------------------------------------------------------------------------------------------------------------------- +# pcduino3nano +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTCONFIG="Linksprite_pcDuino3_Nano_defconfig" +MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i" +MODULES_NEXT="bonding" +;; + + +bananapim2)#enabled +#description A31 quad core 1Gb SoC Wifi +#build 2 +#--------------------------------------------------------------------------------------------------------------------------------- +# Bananapi M2 +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTLOADER="https://github.com/BPI-SINOVOIP/BPI-Mainline-uboot" +BOOTCONFIG="Bananapi_M2_defconfig" +BOOTSOURCE="u-boot-bpi-m2" +BOOTDEFAULT="master" +UBOOTTAG="" +MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i 8021q a20_tp" +MODULES_NEXT="brcmfmac bonding" +;; + + +bananapi)#enabled +#description A20 dual core 1Gb SoC +#build 3 +#--------------------------------------------------------------------------------------------------------------------------------- +# Bananapi +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTCONFIG="Bananapi_defconfig" +MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i 8021q a20_tp" +MODULES_NEXT="brcmfmac bonding" +;; + + +bananapipro)#enabled +#description A20 dual core 1Gb SoC Wifi +#build 0 +#--------------------------------------------------------------------------------------------------------------------------------- +# Bananapi +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTCONFIG="Bananapro_defconfig" +MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i 8021q a20_tp ap6210" +MODULES_NEXT="brcmfmac bonding" +;; + + +lamobo-r1)#enabled +#description A20 dual core 1Gb SoC Switch +#build 3 +#--------------------------------------------------------------------------------------------------------------------------------- +# Bananapi +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTCONFIG="Lamobo_R1_defconfig" +MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i 8021q" +MODULES_NEXT="brcmfmac bonding" +;; + + +orangepi)#enabled +#description A20 dual core 1Gb SoC Wifi USB hub +#build 3 +#--------------------------------------------------------------------------------------------------------------------------------- +# Bananapi +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTCONFIG="Orangepi_defconfig" +MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i 8021q a20_tp" +MODULES_NEXT="bonding" +;; + + +orangepimini)#enabled +#description A20 dual core 1Gb SoC Wifi +#build 0 +#--------------------------------------------------------------------------------------------------------------------------------- +# Bananapi +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTCONFIG="Orangepi_mini_defconfig" +MODULES="hci_uart gpio_sunxi rfcomm hidp sunxi-ir bonding spi_sun7i 8021q a20_tp" +MODULES_NEXT="bonding" +;; + + +orangepiplus)#enabled +#description H3 quad core 1Gb SoC Wifi USB hub +#build 2wip +#--------------------------------------------------------------------------------------------------------------------------------- +# Orange pi plus H3 +#--------------------------------------------------------------------------------------------------------------------------------- +KERNELTAG="v4.4-rc2" +BOOTCONFIG="orangepi_plus_defconfig" +LINUXFAMILY="sun8i" +CPUMIN="1200000" +CPUMAX="1200000" +UBOOTTAG="" +LINUXCONFIG="linux-sunxi-dev" +;; + + +cubox-i)#enabled +#description Freescale iMx dual/quad core Wifi +#build 1 +#--------------------------------------------------------------------------------------------------------------------------------- +# cubox-i & hummingboard 3.14.xx +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTLOADER="https://github.com/SolidRun/u-boot-imx6 --depth 1" +BOOTDEFAULT="HEAD" +UBOOTTAG="" +BOOTSOURCE="u-boot-cubox" +BOOTCONFIG="mx6_cubox-i_config" +CPUMIN="396000" +CPUMAX="996000" +MODULES="bonding" +MODULES_NEXT="bonding" +LINUXKERNEL="https://github.com/linux4kix/linux-linaro-stable-mx6 --depth 1" +LINUXFAMILY="cubox" +LINUXCONFIG="linux-cubox" +LINUXSOURCE="linux-cubox" +if [[ $BRANCH == *next* ]];then + LINUXKERNEL="git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git" + LINUXSOURCE="linux-mainline" + LINUXCONFIG="linux-cubox-next" +fi +;; + + +udoo)#enabled +#description Freescale iMx dual/quad core Wifi +#build 3 +#--------------------------------------------------------------------------------------------------------------------------------- +# Udoo quad +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTCONFIG="udoo_quad_config" +BOOTLOADER="https://github.com/UDOOboard/uboot-imx" +BOOTSOURCE="u-boot-neo" +UBOOTTAG="" +BOOTDEFAULT="master" +CPUMIN="392000" +CPUMAX="996000" +MODULES="bonding" +MODULES_NEXT="" +KERNELTAG="" +LINUXKERNEL="https://github.com/UDOOboard/linux_kernel --depth 1" +LINUXCONFIG="linux-udoo" +LINUXSOURCE="linux-udoo" +LINUXDEFAULT="3.14-1.0.x-udoo" +LINUXFAMILY="udoo" +;; + + +udoo-neo)#enabled +#description Freescale iMx singe core Wifi +#build 0 +#--------------------------------------------------------------------------------------------------------------------------------- +# Udoo Neo +#--------------------------------------------------------------------------------------------------------------------------------- +#BOOTSIZE="32" +BOOTCONFIG="udoo_neo_config" +BOOTLOADER="https://github.com/UDOOboard/uboot-imx" +BOOTSOURCE="u-boot-neo" +UBOOTTAG="" +CPUMIN="198000" +CPUMAX="996000" +MODULES="bonding" +MODULES_NEXT="" +LINUXKERNEL="--depth 1 https://github.com/UDOOboard/linux_kernel -b imx_3.14.28_1.0.0_ga_neo_dev" +LINUXCONFIG="linux-udoo-neo" +LINUXSOURCE="linux-neo" +LINUXFAMILY="neo" +;; + + +guitar)#enabled +#description S500 Lemaker Guitar Action quad core +#build 1wip +#--------------------------------------------------------------------------------------------------------------------------------- +# Lemaker Guitar +#--------------------------------------------------------------------------------------------------------------------------------- +OFFSET="16" +BOOTSIZE="16" +BOOTCONFIG="s500_defconfig" +BOOTLOADER="https://github.com/LeMaker/u-boot-actions" +BOOTSOURCE="u-boot-guitar" +UBOOTTAG="" +CPUMIN="198000" +CPUMAX="996000" +MODULES="ethernet wlan_8723bs bonding" +MODULES_NEXT="" +LINUXKERNEL="https://github.com/LeMaker/linux-actions --depth 1" +LINUXCONFIG="linux-guitar" +LINUXSOURCE="linux-guitar" +LINUXFAMILY="s500" +;; + + +rpi)#disabled +#--------------------------------------------------------------------------------------------------------------------------------- +# RPi +#--------------------------------------------------------------------------------------------------------------------------------- +BOOTSIZE="32" +BOOTLOADER="https://github.com/UDOOboard/uboot-imx" +BOOTSOURCE="u-boot-neo" +BOOTCONFIG="udoo_neo_config" +CPUMIN="198000" +CPUMAX="996000" +MODULES="bonding" +MODULES_NEXT="" +LINUXKERNEL="https://github.com/raspberrypi/linux" +LINUXCONFIG="linux-rpi.config" +LINUXSOURCE="linux-rpi" +LINUXFAMILY="rpi" +;; + + + +*) echo "Board configuration not found" +exit +;; +esac + + +#--------------------------------------------------------------------------------------------------------------------------------- +# Vanilla Linux, second option, ... +#--------------------------------------------------------------------------------------------------------------------------------- +if [[ $BRANCH == *next* ]];then + # All next compilations are using mainline u-boot & kernel + LINUXKERNEL="git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git --depth 1" + LINUXSOURCE="linux-mainline" + LINUXCONFIG="linux-sunxi-next" + LINUXDEFAULT="master" + LINUXFAMILY="sunxi" + FIRMWARE="" + #LINUXSOURCE="linux-mainline-dac" + #LINUXKERNEL="https://github.com/ssvb/linux-sunxi -b 20151014-4.3.0-rc5-pcduino2-otg-test --depth 1" + #LINUXCONFIG="linux-sunxi-dac" + #KERNELTAG="" + + + if [[ $BOARD == "udoo" ]];then + LINUXKERNEL="https://github.com/patrykk/linux-udoo --depth 1" + LINUXSOURCE="linux-udoo-next" + LINUXCONFIG="linux-udoo-next" + LINUXDEFAULT="HEAD" + KERNELTAG="" + LINUXFAMILY="udoo" + fi +fi \ No newline at end of file diff --git a/deboostrap.sh b/deboostrap.sh new file mode 100644 index 000000000..30301030b --- /dev/null +++ b/deboostrap.sh @@ -0,0 +1,203 @@ +#!/bin/bash +# +# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com +# +# This file is licensed under the terms of the GNU General Public +# License version 2. This program is licensed "as is" without any +# warranty of any kind, whether express or implied. +# +# This file is a part of tool chain https://github.com/igorpecovnik/lib +# +# +# Create system template +# +# + +custom_debootstrap (){ +#--------------------------------------------------------------------------------------------------------------------------------- +# Create clean and fresh Debian and Ubuntu image template if it does not exists +#--------------------------------------------------------------------------------------------------------------------------------- + +# is boot partition to big? +if [ "$SDSIZE" -le "$(($OFFSET+$BOOTSIZE))" ]; then + display_alert "Image size too small." "$BOOTSIZE > $SDSIZE" "err" + exit +fi + +# create needed directories and mount image to next free loop device +rm -rf $DEST/cache/sdcard/ +mkdir -p $DEST/cache/rootfs $DEST/cache/sdcard + +cd $DEST/cache + +# We need to re-calculate from human to machine +BOOTSTART=$(($OFFSET*2048)) +ROOTSTART=$(($BOOTSTART+($BOOTSIZE*2048))) +BOOTEND=$(($ROOTSTART-1)) + +# Create image file +while read line;do + [[ "$line" =~ "records out" ]] && + echo "$(( ${line%+*}*100/$SDSIZE +1 ))" | dialog --backtitle "$backtitle" --title "Creating blank image ($SDSIZE Mb), please wait ..." --gauge "" 5 70 +done< <( dd if=/dev/zero of=$DEST/cache/tmprootfs.raw bs=1M count=$SDSIZE 2>&1 & + pid=$! + sleep 1 + while kill -USR1 $pid 2>/dev/null;do + sleep 1 + done ) + +# Find first available free device +LOOP=$(losetup -f) + +if [[ "$LOOP" != "/dev/loop0" && "$LOOP" != "/dev/loop1" ]]; then +display_alert "You run out of loop devices" "pleese reboot" "error" +exit +fi + +# Mount image as block device +losetup $LOOP $DEST/cache/tmprootfs.raw +sync + +# Create partitions and file-system +parted -s $LOOP -- mklabel msdos +if [ "$BOOTSIZE" -eq "0" ]; then + parted -s $LOOP -- mkpart primary ext4 $ROOTSTART"s" -1s + partprobe $LOOP + mkfs.ext4 -q $LOOP"p1" + mount $LOOP"p1" $DEST/cache/sdcard/ +else + parted -s $LOOP -- mkpart primary fat16 $BOOTSTART"s" $BOOTEND"s" + parted -s $LOOP -- mkpart primary ext4 $ROOTSTART"s" -1s + partprobe $LOOP + mkfs.vfat -n "$IMAGEVOLUME" $LOOP"p1" >/dev/null 2>&1 + mkfs.ext4 -q $LOOP"p2" + mount $LOOP"p2" $DEST/cache/sdcard/ + mkdir -p $DEST/cache/sdcard/boot + mount $LOOP"p1" $DEST/cache/sdcard/boot +fi + +# Uncompress from cache +if [ -f "$DEST/cache/rootfs/$RELEASE.tgz" ]; then + filemtime=`stat -c %Y $DEST/cache/rootfs/$RELEASE.tgz` + currtime=`date +%s` + diff=$(( (currtime - filemtime) / 86400 )) + display_alert "Extracting $RELEASE from cache" "$diff days old" "info" + tar xpfz "$DEST/cache/rootfs/$RELEASE.tgz" -C $DEST/cache/sdcard/ + if [ "$diff" -gt "3" ]; then + chroot $DEST/cache/sdcard /bin/bash -c "apt-get update" | dialog --backtitle "$backtitle" --title "Force package update ..." --progressbox 20 70 + fi +fi + +# If we don't have a filesystem cached, let's make em +if [ ! -f "$DEST/cache/rootfs/$RELEASE.tgz" ]; then + +# debootstrap base system +if [[ $RELEASE == "jessie" && $SYSTEMD == "no" ]]; then sysvinit=",sysvinit-core"; fi +debootstrap --include=openssh-server,debconf-utils$sysvinit --arch=armhf --foreign $RELEASE $DEST/cache/sdcard/ | dialog --backtitle "$backtitle" --title "Debootstrap $DISTRIBUTION $RELEASE base system to image template ..." --progressbox 20 70 + +# remove systemd default load. It's installed and can be used with kernel parameter +if [[ $RELEASE == "jessie" && $SYSTEMD == "no" ]]; then +sed -i -e 's/systemd-sysv //g' $DEST/cache/sdcard/debootstrap/required +fi + +# we need emulator for second stage +cp /usr/bin/qemu-arm-static $DEST/cache/sdcard/usr/bin/ + +# and keys +d=$DEST/cache/sdcard/usr/share/keyrings/ +test -d "$d" || mkdir -p "$d" && cp /usr/share/keyrings/debian-archive-keyring.gpg "$d" + +# enable arm binary format so that the cross-architecture chroot environment will work +test -e /proc/sys/fs/binfmt_misc/qemu-arm || update-binfmts --enable qemu-arm + +# debootstrap second stage +chroot $DEST/cache/sdcard /bin/bash -c "/debootstrap/debootstrap --second-stage" | dialog --backtitle "$backtitle" --title "Installing $DISTRIBUTION $RELEASE base system to image template ..." --progressbox 20 70 + +# mount proc, sys and dev +mount -t proc chproc $DEST/cache/sdcard/proc +mount -t sysfs chsys $DEST/cache/sdcard/sys +mount -t devtmpfs chdev $DEST/cache/sdcard/dev || mount --bind /dev $DEST/cache/sdcard/dev +mount -t devpts chpts $DEST/cache/sdcard/dev/pts + +# choose proper apt list +cp $SRC/lib/config/sources.list.$RELEASE $DEST/cache/sdcard/etc/apt/sources.list + +# add armbian key +echo "deb http://apt.armbian.com $RELEASE main" > $DEST/cache/sdcard/etc/apt/sources.list.d/armbian.list +cp $SRC/lib/bin/armbian.key $DEST/cache/sdcard +chroot $DEST/cache/sdcard /bin/bash -c "cat armbian.key | apt-key add -" +rm $DEST/cache/sdcard/armbian.key + +# update and upgrade +LC_ALL=C LANGUAGE=C LANG=C chroot $DEST/cache/sdcard /bin/bash -c "apt-get -y update" | dialog --progressbox "Updating package databases ..." 20 70 + +# install aditional packages +PAKETKI="alsa-utils automake btrfs-tools bash-completion bc bridge-utils bluez build-essential cmake cpufrequtils curl \ +device-tree-compiler dosfstools evtest figlet fbset fping git haveged hddtemp hdparm hostapd htop i2c-tools ifenslave-2.6 \ +iperf ir-keytable iotop iozone3 iw less libbluetooth-dev libbluetooth3 libtool libwrap0-dev libfuse2 libssl-dev lirc lsof makedev \ +module-init-tools mtp-tools nano ntfs-3g ntp parted pkg-config pciutils pv python-smbus rfkill rsync screen stress sudo subversion \ +sysfsutils toilet u-boot-tools unattended-upgrades unzip usbutils vlan wireless-tools weather-util weather-util-data wget \ +wpasupplicant iptables dvb-apps libdigest-sha-perl libproc-processtable-perl w-scan apt-transport-https sysbench libusb-dev dialog" + +# generate locales and install packets +display_alert "Install locales" "$DEST_LANG" "info" +LC_ALL=C LANGUAGE=C LANG=C chroot $DEST/cache/sdcard /bin/bash -c "apt-get -y -qq install locales" +if [ -f $DEST/cache/sdcard/etc/locale.gen ]; then sed -i "s/^# $DEST_LANG/$DEST_LANG/" $DEST/cache/sdcard/etc/locale.gen; fi +LC_ALL=C LANGUAGE=C LANG=C chroot $DEST/cache/sdcard /bin/bash -c "locale-gen $DEST_LANG" +LC_ALL=C LANGUAGE=C LANG=C chroot $DEST/cache/sdcard /bin/bash -c "export CHARMAP=$CONSOLE_CHAR FONTFACE=8x16 LANG=$DEST_LANG LANGUAGE=$DEST_LANG DEBIAN_FRONTEND=noninteractive" +LC_ALL=C LANGUAGE=C LANG=C chroot $DEST/cache/sdcard /bin/bash -c "update-locale LANG=$DEST_LANG LANGUAGE=$DEST_LANG LC_MESSAGES=POSIX" + + +install_packet "$PAKETKI" "Installing Armbian on the top of $DISTRIBUTION $RELEASE base system ..." + +install_packet "console-setup console-data kbd console-common unicode-data" "Installing console packages" + + +# configure the system for unattended upgrades +cp $SRC/lib/scripts/50unattended-upgrades $DEST/cache/sdcard/etc/apt/apt.conf.d/50unattended-upgrades +cp $SRC/lib/scripts/02periodic $DEST/cache/sdcard/etc/apt/apt.conf.d/02periodic + +# copy hostapd configurations +install -m 755 $SRC/lib/config/hostapd.conf $DEST/cache/sdcard/etc/hostapd.conf +install -m 755 $SRC/lib/config/hostapd.realtek.conf $DEST/cache/sdcard/etc/hostapd.conf-rt + +# set up 'apt +cat < $DEST/cache/sdcard/etc/apt/apt.conf.d/71-no-recommends +APT::Install-Recommends "0"; +APT::Install-Suggests "0"; +END + +# console fix due to Debian bug +sed -e 's/CHARMAP=".*"/CHARMAP="'$CONSOLE_CHAR'"/g' -i $DEST/cache/sdcard/etc/default/console-setup + +# root-fs modifications +rm -f $DEST/cache/sdcard/etc/motd +touch $DEST/cache/sdcard/etc/motd + +chroot $DEST/cache/sdcard /bin/bash -c "apt-get clean" +chroot $DEST/cache/sdcard /bin/bash -c "sync" +chroot $DEST/cache/sdcard /bin/bash -c "unset DEBIAN_FRONTEND" +sync +sleep 3 +# unmount proc, sys and dev from chroot +umount -l $DEST/cache/sdcard/dev/pts +umount -l $DEST/cache/sdcard/dev +umount -l $DEST/cache/sdcard/proc +umount -l $DEST/cache/sdcard/sys + +# kill process inside +KILLPROC=$(ps -uax | pgrep ntpd | tail -1); if [ -n "$KILLPROC" ]; then kill -9 $KILLPROC; fi +KILLPROC=$(ps -uax | pgrep dbus-daemon | tail -1); if [ -n "$KILLPROC" ]; then kill -9 $KILLPROC; fi + +display_alert "Closing deboostrap process and preparing cache." "" "info" + +tar czpf $DEST/cache/rootfs/$RELEASE.tgz --directory=$DEST/cache/sdcard/ \ +--exclude=dev/* --exclude=proc/* --exclude=run/* --exclude=tmp/* --exclude=mnt/* . +fi +# +# mount proc, sys and dev +mount -t proc chproc $DEST/cache/sdcard/proc +mount -t sysfs chsys $DEST/cache/sdcard/sys +mount -t devtmpfs chdev $DEST/cache/sdcard/dev || mount --bind /dev $DEST/cache/sdcard/dev +mount -t devpts chpts $DEST/cache/sdcard/dev/pts +} \ No newline at end of file diff --git a/desktop.sh b/desktop.sh new file mode 100644 index 000000000..0e1841d2f --- /dev/null +++ b/desktop.sh @@ -0,0 +1,140 @@ +#!/bin/bash +# +# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com +# +# This file is licensed under the terms of the GNU General Public +# License version 2. This program is licensed "as is" without any +# warranty of any kind, whether express or implied. +# +# This file is a part of tool chain https://github.com/igorpecovnik/lib +# + + +install_desktop (){ +#-------------------------------------------------------------------------------------------------------------------------------- +# Install desktop with HW acceleration +#-------------------------------------------------------------------------------------------------------------------------------- +display_alert "Installing desktop" "XFCE" "info" + +umount $DEST/cache/sdcard/tmp >/dev/null 2>&1 +mount --bind $SRC/lib/bin/ $DEST/cache/sdcard/tmp + +# Declare office packages if any +OFFICE_PACKETS="libreoffice-writer libreoffice-java-common" + +# Debian Wheezy +#-------------------------------------------------------------------------------------------------------------------------------- +if [[ $RELEASE == "wheezy" ]]; then +BASIC_PACKETS="xserver-xorg xserver-xorg-core xfonts-base xinit nodm x11-xserver-utils xfce4 mozo pluma wicd thunar-volman \ +galculator iceweasel libgnome2-perl gcj-jre-headless gtk2-engines gtk2-engines-murrine gtk2-engines-pixbuf libgtk2.0-bin \ +xfce4-screenshooter icedove radiotray mirage xterm lxtask" +# copy wallpapers and default desktop settings +d=$DEST/cache/sdcard/usr/share/xfce4/backdrops/ +test -d "$d" || mkdir -p "$d" && cp $SRC/lib/bin/armbian*.jpg "$d" +#cp $SRC/lib/config/wheezy-desktop.tgz /tmp/kernel # start configuration +chroot $DEST/cache/sdcard /bin/bash -c "tar xfz /tmp/wheezy-desktop.tgz -C /root/" +fi + +# Debian Jessie +#-------------------------------------------------------------------------------------------------------------------------------- +if [[ $RELEASE == "jessie" ]]; then +BASIC_PACKETS="xserver-xorg xserver-xorg-core xfonts-base xinit nodm x11-xserver-utils xfce4 mozo pluma wicd thunar-volman \ +galculator iceweasel libgnome2-perl gcj-jre-headless gtk2-engines gtk2-engines-murrine gtk2-engines-pixbuf libgtk2.0-bin \ +$OFFICE_PACKETS xfce4-screenshooter icedove radiotray mirage xterm lxtask" +# copy wallpapers +d=$DEST/cache/sdcard/usr/share/backgrounds/xfce/ +test -d "$d" || mkdir -p "$d" && cp $SRC/lib/bin/armbian*.jpg "$d" +#cp $SRC/lib/config/jessie-desktop.tgz /tmp/kernel # start configuration +chroot $DEST/cache/sdcard /bin/bash -c "tar xfz /tmp/jessie-desktop.tgz -C /root/" +fi + +# Ubuntu trusty +#-------------------------------------------------------------------------------------------------------------------------------- +if [[ $RELEASE == "trusty" ]]; then +BASIC_PACKETS="xserver-xorg xserver-xorg-core xfonts-base xinit nodm x11-xserver-utils xfce4 wicd thunar-volman galculator \ +libgnome2-perl gcj-jre-headless gtk2-engines gtk2-engines-murrine gtk2-engines-pixbuf libgtk2.0-bin \ +$OFFICE_PACKETS xfce4-screenshooter thunderbird firefox radiotray mirage gnome-icon-theme-full \ +tango-icon-theme xterm lxtask gvfs-backends" +# copy wallpapers and default desktop settings +d=$DEST/cache/sdcard/usr/share/backgrounds/xfce/ +test -d "$d" || mkdir -p "$d" && cp $SRC/lib/bin/armbian*.jpg "$d" +#cp $SRC/lib/config/trusty-desktop.tgz /tmp/kernel # start configuration +chroot $DEST/cache/sdcard /bin/bash -c "tar xfz /tmp/trusty-desktop.tgz -C /root/" +fi + +install_packet "$BASIC_PACKETS" "Installing desktop" + +# Install custom icons and theme +#cp $SRC/lib/bin/vibrancy-colors_2.4-trusty-Noobslab.com_all.deb /tmp/kernel +#cp $SRC/lib/bin/NumixHolo.zip /tmp/kernel +chroot $DEST/cache/sdcard /bin/bash -c "dpkg -i /tmp/vibrancy-colors_2.4-trusty-Noobslab.com_all.deb >/dev/null 2>&1" +chroot $DEST/cache/sdcard /bin/bash -c "unzip -qq /tmp/NumixHolo.zip -d /usr/share/themes" +# cleanup +chroot $DEST/cache/sdcard /bin/bash -c "apt-get -y autoremove >/dev/null 2>&1" +chroot $DEST/cache/sdcard /bin/bash -c "apt-get clean >/dev/null 2>&1" + +umount $DEST/cache/sdcard/tmp >/dev/null 2>&1 + +# fix for udoo +if [[ $BOARD != "udoo" ]]; then + echo "[Settings]" > $DEST/cache/sdcard/etc/wicd/manager-settings.conf + echo "wireless_interface = wlan0" >> $DEST/cache/sdcard/etc/wicd/manager-settings.conf +fi + +# Enable desktop moode autostart without password +sed "s/NODM_ENABLED=\(.*\)/NODM_ENABLED=true/g" -i $DEST/cache/sdcard/etc/default/nodm + +# Compile Turbo Frame buffer for sunxi +if [[ $LINUXCONFIG == *sun* && $BRANCH != "next" ]]; then + install_packet "xorg-dev xutils-dev x11proto-dri2-dev xutils-dev libdrm-dev libvdpau-dev" "Installing support libraries" + # quemu bug walkaround + git clone https://github.com/ssvb/xf86-video-fbturbo.git $DEST/cache/sdcard/tmp/xf86-video-fbturbo + chroot $DEST/cache/sdcard /bin/bash -c "cd /tmp/xf86-video-fbturbo && autoreconf -vi" + chroot $DEST/cache/sdcard /bin/bash -c "cd /tmp/xf86-video-fbturbo && ./configure --prefix=/usr" + chroot $DEST/cache/sdcard /bin/bash -c "cd /tmp/xf86-video-fbturbo && make && make install && cp xorg.conf /etc/X11/xorg.conf" + + # compile video acceleration + # A + git clone https://github.com/linux-sunxi/libvdpau-sunxi.git $DEST/cache/sdcard/tmp/libvdpau-sunxi + # temporaly fix + chroot $DEST/cache/sdcard /bin/bash -c "git checkout 906c36ed45ceb53fecd5fc72e821c11849eeb1a3" + chroot $DEST/cache/sdcard /bin/bash -c "cd /tmp/libvdpau-sunxi && make" + d=$DEST/cache/sdcard/usr/lib/vdpau + test -d "$d" || mkdir -p "$d" && cp $DEST/cache/sdcard/tmp/libvdpau-sunxi/libvdpau_sunxi.so.1 "$d" + ln -s $d/libvdpau_sunxi.so $d/libvdpau_sunxi.so.1 + + # B + # git clone https://github.com/Snaipe/libcsptr.git $DEST/cache/sdcard/usr/local/src/libcsptr + # chroot $DEST/cache/sdcard /bin/bash -c "cd /usr/local/src/libcsptr && mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=/usr/local .. && make && make install" + # chroot $DEST/cache/sdcard /bin/bash -c "cd /usr/local/src/libcsptr && make" + # chroot $DEST/cache/sdcard /bin/bash -c "cd /usr/local/src/libcsptr && make install" + # display_alert "GIT clone" "libvdpau-sunxi" "info" + # echo -e "[\e[0;34m git cloning \x1B[0m] libvdpau-sunxi ..." + # git clone -b staging https://github.com/rellla/libvdpau-sunxi.git $DEST/cache/sdcard/usr/local/src/libvdpau-sunxi + # chroot $DEST/cache/sdcard /bin/bash -c "cd /usr/local/src/libvdpau-sunxi && make clean && make $CTHREADS ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- && make install" + + # That we can just play + echo "export VDPAU_DRIVER=sunxi" >> $DEST/cache/sdcard/etc/profile + # enable memory reservations + sed "s/sunxi_ve_mem_reserve=0 sunxi_g2d_mem_reserve=0 sunxi_no_mali_mem_reserve sunxi_fb_mem_reserve=16 //g" -i $DEST/cache/sdcard/boot/boot.cmd + mkimage -C none -A arm -T script -d $DEST/cache/sdcard/boot/boot.cmd $DEST/cache/sdcard/boot/boot.scr >> /dev/null + # clean deb cache + chroot $DEST/cache/sdcard /bin/bash -c "apt-get -y clean >/dev/null 2>&1" +fi + +if [[ $LINUXCONFIG == *sunxi* ]]; then +# disable DPMS for sunxi because screen doesn't resume +cat >> $DEST/cache/sdcard/etc/X11/xorg.conf <> $DEST/cache/sdcard/etc/inittab + + # don't clear screen on boot console + sed -e 's/getty 38400 tty1/getty --noclear 38400 tty1/g' -i $DEST/cache/sdcard/etc/inittab + + # disable some getties + sed -e 's/5:23:respawn/#5:23:respawn/g' -i $DEST/cache/sdcard/etc/inittab + sed -e 's/6:23:respawn/#6:23:respawn/g' -i $DEST/cache/sdcard/etc/inittab + + # auto upgrading + sed -e "s/ORIGIN/Debian/g" -i $DEST/cache/sdcard/etc/apt/apt.conf.d/50unattended-upgrades + sed -e "s/n=CODENAME/a=old-stable/g" -i $DEST/cache/sdcard/etc/apt/apt.conf.d/50unattended-upgrades + + # install ramlog + cp $SRC/lib/bin/ramlog_2.0.0_all.deb $DEST/cache/sdcard/tmp + chroot $DEST/cache/sdcard /bin/bash -c "dpkg -i /tmp/ramlog_2.0.0_all.deb >/dev/null 2>&1" + # enabled back at first run. To remove errors + chroot $DEST/cache/sdcard /bin/bash -c "service ramlog disable >/dev/null 2>&1" + rm $DEST/cache/sdcard/tmp/ramlog_2.0.0_all.deb + sed -e 's/TMPFS_RAMFS_SIZE=/TMPFS_RAMFS_SIZE=512m/g' -i $DEST/cache/sdcard/etc/default/ramlog + sed -e 's/$remote_fs $time/$remote_fs $time ramlog/g' -i $DEST/cache/sdcard/etc/init.d/rsyslog + sed -e 's/umountnfs $time/umountnfs $time ramlog/g' -i $DEST/cache/sdcard/etc/init.d/rsyslog + ;; + +# Debian Jessie +jessie) + + # specifics packets add and remove + install_packet "thin-provisioning-tools libnl-3-dev libnl-genl-3-dev libpam-systemd \ + software-properties-common python-software-properties libnss-myhostname" "Installing Jessie packages" "" "quiet" + + LC_ALL=C LANGUAGE=C LANG=C chroot $DEST/cache/sdcard /bin/bash -c "apt-get autoremove >/dev/null 2>&1" + + # enable root login for latest ssh on jessie + sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' $DEST/cache/sdcard/etc/ssh/sshd_config + + # auto upgrading + sed -e "s/ORIGIN/Debian/g" -i $DEST/cache/sdcard/etc/apt/apt.conf.d/50unattended-upgrades + sed -e "s/CODENAME/$RELEASE/g" -i $DEST/cache/sdcard/etc/apt/apt.conf.d/50unattended-upgrades + + # mount 256Mb tmpfs to /tmp + echo "tmpfs /tmp tmpfs nodev,nosuid,size=256M 0 0" >> $DEST/cache/sdcard/etc/fstab + + # fix selinux error + chroot $DEST/cache/sdcard /bin/bash -c "mkdir /selinux" + + # configuration for systemd + + # add serial console + local systemdpath="$DEST/cache/sdcard/lib/systemd/system" + cp $SRC/lib/config/ttyS0.conf $DEST/cache/sdcard/etc/init/ttyS0.conf + cp $systemdpath/serial-getty@.service $systemdpath/getty.target.wants/serial-getty@ttyS0.service + sed -e s/"--keep-baud 115200,38400,9600"/"-L 115200"/g -i $systemdpath/getty.target.wants/serial-getty@ttyS0.service + + # don't clear screen tty1 + sed -e s,"TTYVTDisallocate=yes","TTYVTDisallocate=no",g -i $DEST/cache/sdcard/lib/systemd/system/getty@.service + + # configuration for sysvinit + + # add serial console + echo T0:2345:respawn:/sbin/getty -L ttyS0 115200 vt100 >> $DEST/cache/sdcard/etc/inittab + + # don't clear screen on boot console + sed -e 's/getty 38400 tty1/getty --noclear 38400 tty1/g' -i $DEST/cache/sdcard/etc/inittab + + # disable some getties + sed -e 's/5:23:respawn/#5:23:respawn/g' -i $DEST/cache/sdcard/etc/inittab + sed -e 's/6:23:respawn/#6:23:respawn/g' -i $DEST/cache/sdcard/etc/inittab + + # install ramlog if we don't have systemd + if [[ $SYSTEMD == "no" ]]; then + cp $SRC/lib/bin/ramlog_2.0.0_all.deb $DEST/cache/sdcard/tmp + chroot $DEST/cache/sdcard /bin/bash -c "dpkg -i /tmp/ramlog_2.0.0_all.deb >/dev/null 2>&1" + # enabled back at first run. To remove errors + chroot $DEST/cache/sdcard /bin/bash -c "service ramlog disable >/dev/null 2>&1" + rm $DEST/cache/sdcard/tmp/ramlog_2.0.0_all.deb + sed -e 's/TMPFS_RAMFS_SIZE=/TMPFS_RAMFS_SIZE=512m/g' -i $DEST/cache/sdcard/etc/default/ramlog + # supress warning + sed -e 's/update-rc.d $prog.*/update-rc.d $prog defaults/g' -i $DEST/cache/sdcard/etc/init.d/ramlog + sed -e 's/$remote_fs $time/$remote_fs $time ramlog/g' -i $DEST/cache/sdcard/etc/init.d/rsyslog + sed -e 's/umountnfs $time/umountnfs $time ramlog/g' -i $DEST/cache/sdcard/etc/init.d/rsyslog + fi + ;; + +# Ubuntu Trusty +trusty) + + # specifics packets add and remove + install_packet "libnl-3-dev libnl-genl-3-dev software-properties-common \ + python-software-properties" "Installing Trusty packages" "" "quiet" + + LC_ALL=C LANGUAGE=C LANG=C chroot $DEST/cache/sdcard /bin/bash -c "apt-get autoremove >/dev/null 2>&1" + + # add serial console + cp $SRC/lib/config/ttyS0.conf $DEST/cache/sdcard/etc/init/ttyS0.conf + + # don't clear screen tty1 + sed -e s,"exec /sbin/getty","exec /sbin/getty --noclear",g -i $DEST/cache/sdcard/etc/init/tty1.conf + + # disable some getties + chroot $DEST/cache/sdcard /bin/bash -c "rm /etc/init/tty5.conf" + chroot $DEST/cache/sdcard /bin/bash -c "rm /etc/init/tty6.conf" + + # enable root login for latest ssh on trusty + sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' $DEST/cache/sdcard/etc/ssh/sshd_config + + # fix selinux error + chroot $DEST/cache/sdcard /bin/bash -c "mkdir /selinux" + + # that my custom motd works well + if [ -d "$DEST/cache/sdcard/etc/update-motd.d" ]; then + chroot $DEST/cache/sdcard /bin/bash -c "mv /etc/update-motd.d /etc/update-motd.d-backup" + fi + + # auto upgrading + sed -e "s/ORIGIN/Ubuntu/g" -i $DEST/cache/sdcard/etc/apt/apt.conf.d/50unattended-upgrades + sed -e "s/CODENAME/$RELEASE/g" -i $DEST/cache/sdcard/etc/apt/apt.conf.d/50unattended-upgrades + + # remove what's anyway not working + rm $DEST/cache/sdcard/etc/init/ureadahead* + rm $DEST/cache/sdcard/etc/init/plymouth* + ;; + +*) echo "Release hasn't been choosen" +exit +;; +esac + +# Common + +# change time zone data +echo $TZDATA > $DEST/cache/sdcard/etc/timezone +chroot $DEST/cache/sdcard /bin/bash -c "dpkg-reconfigure -f noninteractive tzdata >/dev/null 2>&1" + +# set root password +chroot $DEST/cache/sdcard /bin/bash -c "(echo $ROOTPWD;echo $ROOTPWD;) | passwd root >/dev/null 2>&1" + +# create proper fstab +if [ "$BOOTSIZE" -eq "0" ]; then + local device="/dev/mmcblk0p1 / ext4 defaults,noatime,nodiratime,data=writeback,commit=600,errors=remount-ro" +else + local device="/dev/mmcblk0p2 / ext4 defaults,noatime,nodiratime,data=writeback,commit=600,errors=remount-ro" +fi +echo "$device 0 0" >> $DEST/cache/sdcard/etc/fstab + +# flash media tunning +if [ -f "$DEST/cache/sdcard/etc/default/tmpfs" ]; then + sed -e 's/#RAMTMP=no/RAMTMP=yes/g' -i $DEST/cache/sdcard/etc/default/tmpfs + sed -e 's/#RUN_SIZE=10%/RUN_SIZE=128M/g' -i $DEST/cache/sdcard/etc/default/tmpfs + sed -e 's/#LOCK_SIZE=/LOCK_SIZE=/g' -i $DEST/cache/sdcard/etc/default/tmpfs + sed -e 's/#SHM_SIZE=/SHM_SIZE=128M/g' -i $DEST/cache/sdcard/etc/default/tmpfs + sed -e 's/#TMP_SIZE=/TMP_SIZE=1G/g' -i $DEST/cache/sdcard/etc/default/tmpfs +fi + +# add custom bashrc loading +cat <> $DEST/cache/sdcard/etc/bash.bashrc +if [ -f /etc/bash.bashrc.custom ]; then + . /etc/bash.bashrc.custom +fi +END + +# remove hostapd because it's replaced with ours +chroot $DEST/cache/sdcard /bin/bash -c "apt-get -y -qq remove hostapd >/dev/null 2>&1" +} \ No newline at end of file diff --git a/documentation/geek-faq.md b/documentation/geek-faq.md new file mode 100644 index 000000000..5c65ddb7f --- /dev/null +++ b/documentation/geek-faq.md @@ -0,0 +1,173 @@ +# How to build Armbian? # + +You will need to setup development environment within [Ubuntu 14.04 LTS x64 server image](http://releases.ubuntu.com/14.04/) and cca. 20G of free space. + +Login as root and run: + + apt-get -y -qq install git + git clone --depth 1 https://github.com/igorpecovnik/lib + cp lib/compile.sh . + nano compile.sh # alter if necessary + +Make it executable. + + chmod +x compile.sh + +Run the script + + ./compile.sh + +# What is behind the build process? + + +Build process summary: + +- creates development environment on the top of X86/AMD64 Ubuntu 14.04 LTS, +- download proven sources, applies patches and use tested configurations, +- cross-compile universal boot loader (u-boot), kernel and other tools and drivers, +- pack kernel, uboot, dtb and root customizations into debs, +- debootstrap minimalistic Debian Wheezy, Jessie and Ubuntu Trusty into SD card image, +- install additional packets, apply customizations and shrink image to it's actual size. + +Switches clarification: + +- **KERNEL_ONLY** - if we want to compile kernel, u-boot, headers and dtbs package only. +- **KERNEL_CONFIGURE** will bring up kernel configurator otherwise kernel will be compiled with script presets located in lib/config/linux-*.config +- **KERNEL\_KEEP\_CONFIG** overwrite kernel config before compilation +- **CLEAN_LEVEL** defines what should be cached. This is useful when we are rebuilind images or builind more than one image. + - 0 = executes make clean and delete previously created deb files [default] + - 1 = executes make clean + - 2 = does nothing + - 3 = provide kernel selection if any present + - 4 = delete all output files (rootfs cache, debs) +- **USE_CCACHE** use a C compiler cache to speed up the build process +- **BUILD_DESKTOP** builds a desktop on the top of the system with hw acceleration for some boards. +- **AFTERINSTALL** is a variable with command executed in a process of building just before closing image to insert some of your custom applications or fixes. +- **FBTFT** is a [driver for small displays](https://github.com/notro/fbtft). Only applicable for old kernels (3.4-3.14) +- **EXTERNAL** compiles custom drivers +- **FORCE** ignore manual changes to source +- **BUILD_ALL** cycle through selected boards and make images + +Image compiling example with partial cache: + +[su_youtube_advanced url="https:\/\/youtu.be\/zeShf12MNLg" controls="yes" showinfo="no" loop="yes" rel="no" modestbranding="yes"] + +## Creating compile environment ## + +At first run we are downloading all necessary dependencies. + +## Using board configuration ## + +We need to get some predefined variables about selected board. Which kernel & uboot source to use, modules to load, which is the build number, do we need to have a single partition or dual with boot on fat, which extra drivers to compile out of the kernel tree, ... + +**Board configuration example:** + + REVISION="1.1" # Version number is altered by board maintainer + BOOTSIZE="16" # FAT boot partition in MB, 0 for none + BOOTLOADER="https://github.com/UDOOboard/uboot-imx" # Uboot source location + BOOTSOURCE="u-boot-neo" # Local folder where to download it + BOOTCONFIG="udoo_neo_config" # Which compile config to use + CPUMIN="198000" # CPU minimum frequency + CPUMAX="996000" # CPU minimum frequency + MODULES="bonding" # old kernel modules + MODULES_NEXT="" # new kernel modules + LINUXKERNEL="https://github.com/UDOOboard/linux_kernel" # kernel source location + LINUXCONFIG="linux-udoo-neo" # kernel configuration + LINUXSOURCE="linux-neo" # Local folder where to download it + LINUXFAMILY="udoo" # boards share kernel + +This **isn't ment to be user configurable** but you can alter variables if you know what you are doing. + +## Downloading sources ## + +When we know where are the sources and where they need to be the download / update process starts. This might take from several minutes to several hours. + +## Patching ## + +In patching process we are appling patches to sources. The process is defined in: + + lib/patching.sh + +## User patching ## + +You can add your own patches outside build script. Place your patches inside appropriate directory, for kernel or u-boot. There are no limitations except all patches must have ending **.patch** + + userpatches/kernel + userpatches/u-boot + +## Compiling or choosing from cache ## + + +- compile from scratch with additional source cleaning and menu config. +- select cached / already made kernel + +## Debootstrap ## + +Debootstrap creates fresh Debian / Ubuntu root filesystem templates or use cached under: + + output/cache/rootfs/$DISTRIBUTION.tgz + +To recreate those files you need to remove them manually. + +## Kernel install ## + +When root filesystem is ready we need to instal kernel image with modules, board definitions, firmwares. Along with this we set the CPU frequency min/max, hostname, modules, network interfaces templates. Here is also the place to install headers and fix + native compile them on the way. + +## Distribution fixes ## + +Each distributin has it's own way of doing things: + +- serial console +- different packets +- configuration locations + +## Board fixes ## + +Each board has their own tricks: **different device names, firmware loaders, configuration (de)compilers, hardware configurators** + +## Desktop installation ## + +You can build a desktop withing the image. Consider this feature as experimental. Hardware acceleration on Allwinner boards is working within kernel 3.4.x only. + +## External applications ## + +This place is reserved for custom applications. There is one example of application - USB redirector. + +## Closing image ## + +There is an option to add some extra commands just before closing an image which is also automaticaly shrink to it's actual size with some small reserve. + +## Directory structure ## + +It will be something like this: + + compile.sh compile execution script + lib/bin/ blobs, firmwares, static compiled, bootsplash + lib/config/ kernel, board, u-boot, hostapd, package list + lib/documentation/ user and developers manual + lib/patch/ collection of kernel and u-boot patches + lib/scripts/ firstrun, arm hardware info, firmware loaders + lib/LICENSE licence description + lib/README.md quick manual + lib/boards.sh board specfic installation, kernel install, desktop install + lib/common.sh creates environment, compiles, shrink image + lib/configuration.sh boards presets - kernel source, config, modules, ... + lib/deboostrap.sh basic system template creation + lib/distributions.sh system specific installation and fixes + lib/main.sh user input and script calls + lib/patching.sh board and system dependend kernel & u-boot patch calls + lib/repo-update.sh creates and updates your local repository + lib/repo-show-sh show packets in your local repository + lib/upgrade.sh script to upgrade older images + sources/ source code for kernel, uboot and other utilities + output/repository repository + output/cache cache for root filesystem and headers compilation + output/debs deb packeges + output/images zip packed RAW image + userpatches/kernel put your kernel patches here + userpatches/u-boot put your u-boot patches here + + +## Additional info ## + +- [Allwinner SBC community](https://linux-sunxi.org/) \ No newline at end of file diff --git a/documentation/logbook.md b/documentation/logbook.md new file mode 100644 index 000000000..f0b656ea2 --- /dev/null +++ b/documentation/logbook.md @@ -0,0 +1,332 @@ +# Release history + +**v4.5 / 14.10.2015** + +- vanilla kernel upgraded to 4.2.3 for Allwinner based boards +- legacy kernel for Allwinner compiled from new sources (linux-sunxi) +- udoo vanilla upgraded to 4.2.3 +- cubox / hummingboard upgraded to 3.14.54 +- changed kernel naming: A10 = linux-image-sun4i, A20 = linux-image-sun7i +- new boards: Banana M2, Orange+(A31S), Cubieboard 1, Cubieboard 2 Dual SD, Lime A10 +- fixed Udoo legacy wireless problems +- fixed Jessie boot problems by disabling systemd. It’s possible to re-enable within boot scripts +- added ramlog to Jessie because we don’t have systemd anymore +- changed wireless driver for Cubietruck and Banana PRO (now it’s ap6210) +- added ZRAM to vanilla kernel +- fixed dvbsky modules + +and a bunch of small fixes. + +**v4.4 / 1.10.2015** + +Images: + +- vanilla kernel upgrade to 4.2.2 (Allwinner, Udoo Quad), +- legacy kernel upgraded to 3.4.109 (Allwinner), +- added I2C support and bunch of multimedia modules (DVB) (vanilla Allwinner), +- Udoo quad images with fixed legacy kernel 3.14.28, +- Cubox and Hummingboard kernel upgrade to 3.14.53, +- brcmfmac driver fixes for vanilla kernel (Banana PRO / Cubietruck) +- performance tweak: choosing a closest Debian mirror (Debian images) +- added Astrometa DVB firmware and dvb-tools +- added Nikkov SPDIF / I2S recent patch (legacy Allwinner) +- added patch for rtl8192cu: Add missing case in rtl92cu_get_hw_reg (Lamobo R1) +- bigger NAND boot partition on install +- install script bug fixes + +Script: + +- force apt-get update on older rootfs cache, +- image harden manipulation security, +- packages NAND/FAT/same version install faling fixed, +- image shrinking function rework, +- better packages installation install checking, +- added Debian keys to suppress warnings in debootstrap process, +- added fancy progress bars, +- added whiptail downloading prior to usage (bugfix). + +**v4.3 / 17.9.2015** + +- kernel 4.2 for Allwinner based boards +- kernel 4.2 for Udoo Quad +- walk-around if ethernet is not detected on some boards due to RTC not set(?) +- update is done (semi) automatic if you are using Armbian 4.2. You only need to issue command: apt-get update && apt-get upgrade. If you are coming from older system, check Documentation +- U-boot on R1 is now updated to latest stable version (2015.07) +- Fixed AW SOM. Working with latest u-boot but you need to build image by yourself. +- Enabled whole USB net and HID section in kernel for Allwinner boards v4.2 +- Fixed upgrade script – only some minor bugs remains. +- Fixes to build script that it’s working under Ubuntu 15.04 +- Adding Bananapi Wireless driver (ap6210) back to legacy kernel +- Udoo official kernel (3.14.28) not updated due too many troubles. + +**v4.2 / 1.9.2015** + +Images: + +- Upgraded NAND / SATA installer. Possible to install to SATA/NAND boot in one step. +- Easy kernel switching between old 3.4 and 4.x +- Automatic kernel updating (to disable comment armbian repo /etc/apt/sources.list) +- Allwinner boards share one 4.x kernel and two 3.4 +- All boards share the same revision number +- One minimal Ubuntu Desktop per board (Wicd, Firefox, Word) +- u-boot v2015.07 for most boards +- Aufs file system support +- kernel 4.1.6 and 3.4.108 +- Added Orangepi Mini, Cubieboard 1 (4.x only), Udoo with official kernel +- Repository for Wheezy, Jessie and Trusty +- enabled USB audio in kernel 4.x +- kernel headers fixed. No need to rebuild when you update the kernel. +- fixed boot scripts that can load from FAT partition too +- removed Cubox binnary repository because of troubles +- Docker support (kernel 4.x). Already here for a while / forget to mention. +- nodm change default login + +Build script: + +- changed structure: sources now in folder sources, output is what we produce, deb in one folder +- expanded desktop part +- possible to build all images at once, create package repository +- SD card initial size is 4Gb, variable transfered into configuration.sh +- Avaliable board list is now created from file configuration.sh +- Fixed image shrinking problem +- Patching part rework +- Using first FAT boot partition now fixes boot scripts +- Uboot TAG moved to configuration.sh and differs for some boards +- new variables for source branches. Only too remove errors when checking out + +**v4.1 / 5.8.2015** + +- Added desktop image +- U-Boot 2015.07 with many new features +- Added auto system update via repository apt.armbian.com +- Root password change is initialized at first boot. +- 3.4.108 kernel fixes, 4.1.4 Allwinner Security System + +**v4.0 / 12.7.2015** + +- Fixed stability issues, temperature display in 4.x +- Kernel upgrades to 3.4.108 and 4.1.2 + +**v3.9 / 11.6.2015** + +- Bugfix release +- Kernel 4.0.5 traffic control support +- SATA / USB install fixed on kernel 4.x +- Added 256Mb emergency swap area, created automatically @first boot + +**v3.8 / 21.5.2015** + +- Bugfix release: Cubietruck images successfully booted on Cubietruck. I waited for automatic reboot than tested remote login. +- Kernel 4.0.4 added support for power on/off button +- Both: Jessie fixed, Ethernet init fixed (uboot) +- armbian.com introduction + +**v3.7 / 14.5.2015** + +- Kernel 4.0.3 some new functionality +- Kernel 3.4.107 added sunxi display manager to change FB on demand +- Both: Ubuntu and jessie install errors fixed, removed busybox-syslogd and changed to default logger due to problems in Jessie and Ubuntu, apt-get upgrade fixed, documentations update, Uboot fixed to 2015.4 – no more from dev branch +- Build script rework - image size shrink to actual size, possible to have fat boot partition on SD card, several script bug fixes + +**v3.6 / 29.4.2015** + +- Kernel 3.19.6 +- Kernel 3.4.107 with better BT loading solution + +**v3.5 / 18.4.2015** + +- Kernel 3.19.4: fixed AP mode, fixed USB, added 8192CU module +- Common: apt-get upgrade ready but not enabled yet, serial console fixed, fixed hostapd under jessie, easy kernel switching, latest patched hostapd for best performance – normal and for realtek adaptors, auto IO scheduler script +- Build script: everything packed as DEB + +**v3.4 / 28.3.2015** + +- Kernel 3.19.3: docker support, apple hid, pmp, nfsd, sata peformance fix +- Kernel 3.4.106: pmp, a20_tp - soc temp sensor +- Common: console setup fixed, headers bugfix, nand install fix +- Build script: kernel build only, custom packets install, hardware accelerated desktop build as option + +**v3.3 / 28.2.2015** + +- Kernel 3.19.0: many new functionality and fixes. +- Bugfixes: CT wireless works in all kernels + +**v3.2 / 24.1.2015** + +- Possible to compile external modules on both kernels +- Kernel 3.19.0 RC5 +- Bugfixes: install script, headers, bashrc, spi + +**v3.1 / 16.1.2015** + +- Kernel 3.19.0 RC4 +- Added Cubieboard 1 images +- Dualboot for CB2 and CT dropped due to u-boot change. Now separate images. +- New user friendly SATA + USB installer, also on mainline + +**v3.0 / 29.12.2014** + +- Kernel 3.18.1 for mainline image +- Added Ubuntu Trusty (14.04 LTS) image +- Bugfixes: auto packages update + +**v2.9 / 3.12.2014** + +- Kernel 3.4.105 with new MALI driver and other fixes +- Added: Jessie image +- Major build script rewrite - much faster image building +- Fixed: failed MIN/MAX settings + +**v2.8 / 17.10.2014** + +- Added: ondemand governor, fhandle, squashfs and btrfs +- Removed: bootsplash, lvm, version numbering in issue +- Fixed: custom scripts, Jessie upgrade +- Disabled: BT firmware loading, enable back with: insserv brcm40183-patch +- Added working driver for RT 8188C, 8192C + +**v2.7 / 1.10.2014** + +- Kernel 3.4.104 +- Automatic Debian system updates +- VGA output is now default but if HDMI is attached at first boot than it switch to HDMI for good. After first restart! +- Fixed NAND install script. /boot is mounted by default. Kernel upgrade is now the same as on SD systems. + Cubieboard2 - disabled Cubietruck dedicated scripts (BT firmware, LED disable) +- Added network bonding and configuration for "notebook" mode (/etc/network/interfaces.bonding) +- IR receiver is preconfigured with default driver and LG remote (/etc/lirc/lircd.conf), advanced driver is present but disabled +- Added SPI and LVM functionality +- Added Debian logo boot splash image +- Added build essentials package + +**v2.6 / 22.8.2014** + +- Kernel 3.4.103 and 3.17.0-RC1 +- Added GPIO patch (only for 3.4.103) + +**v2.5 / 2.8.2014** + +- Kernel 3.4.101 and 3.16.0-RC4 +- major build script rewrite + +**v2.4 / 11.7.2014** + +- Kernel 3.4.98 +- default root password (1234) expires at first login +- build script rewrite, now 100% non-interactive process, time zone as config option +- bug fixes: removed non-existing links in /lib/modules + +**v2.3 / 2.7.2014** + +- Kernel 3.4.96 +- cpuinfo serial number added +- bug fixes: stability issues - downclocked to factory defaults, root SSH login enabled in Jessie, dedicated core for eth0 fix +- disp_vsync kernel patch + +**v2.2 / 26.6.2014** + +- Kernel 3.4.94 +- Added Jessie distro image +- Updated hostapd, bashrc, build script +- bug fixes: disabled upgrade and best mirror search @firstboot, bluetooth enabler fix +- MD5 hash image protection + +**v2.1 / 13.6.2014** + +- Kernel 3.4.93 +- Onboard Bluetooth finally works +- Small performance fix +- Allwinner Security System cryptographic accelerator + +**v2.0 / 2.6.2014** + +- Kernel 3.4.91 with many fixes +- Cubieboard 2 stability issues fix +- eth0 interrupts are using dedicated core +- Global bashrc /etc/bash.bashrc +- Verbose output and package upgrade @ first run + +**v1.9 / 27.4.2014** + +- Kernel headers included +- Clustering support +- Advanced IR driver with RAW RX and TX +- Bluetooth ready (working only with supported USB devices) +- Bugfixes: VLAN, login script, build script +- New packages: lirc, bluetooth + +**v1.8 / 27.3.2014** + +- Kernel 3.4.79 +- Alsa I2S patch + basic ALSA utils +- Performance tweaks: CPU O.C. to 1.2Ghz, IO scheduler NOOP for SD, CFQ for sda, journal data writeback enabled +- Avaliable memory = 2000MB +- Minimized console output at boot +- MAC address from chip ID, manual optional +- Latest (Access point) hostapd, 2.1 final release +- Login script shows current CPU temp, hard drive temp & actual free memory +- Fastest Debian mirror auto selection @first boot +- New packages: alsa-utils netselect-apt sysfsutils hddtemp bc + +**v1.7 / 26.2.2014** + +- Flash media performance tweaks, reduced writings, tmp & logging to RAM with ramlog app – sync logs on shutdown +- SATA install script +- Dynamic MOTD: Cubieboard / Cubietruck +- Disabled Debian logo at startup +- New packages: figlet toilet screen hdparm libfuse2 ntfs-3g bash-completion + +**v1.6 / 9.2.2014** + +- Added support for Cubieboard 2 +- Build script creates separate images for VGA and HDMI +- NAND install script added support for Cubieboard 2 + +**v1.52 / 7.2.2014** + +- Various kernel tweaks, more modules enabled +- Root filesystem can be moved to USB drive +- Bugfixes: NAND install script + +**v1.5 / 22.1.2014** + +- Hotspot Wifi Access Point / Hostapd 2.1 +- Bugfixes: MAC creation script, SSH keys creation, removed double packages, … +- Graphics desktop environment upgrade ready + +**v1.4 / 12.1.2014** + +- Patwood’s kernel 3.4.75+ with many features +- Optimized CPU frequency scaling 480-1010Mhz with interactive governor +- NAND install script included +- Cubietruck MOTD +- USB redirector – for sharing USB over TCP/IP + +**v1.3 / 3.1.2014** + +- CPU frequency scaling 30-1000Mhz +- Patch for gpio + +**v1.23 / 1.1.2014** + +- added HDMI version +- added sunxi-tools +- build.sh transfered to Github repository +- disabled LED blinking + +**v1.2 / 26.12.2013** + +- changed kernel and hardware config repository +- kernel 3.4.61+ +- wi-fi working +- updated manual how-to + +**v1.0 / 24.12.2013** + +- total memory available is 2G (disabled memory for GPU by default) +- gigabit ethernet is fully operational +- sata driver enabled +- root filesystem autoresize +- MAC address fixed at first boot +- Kernel 3.4.75 +- root password=1234 +- Bugs: wifi and BT not working \ No newline at end of file diff --git a/documentation/user-faq.md b/documentation/user-faq.md new file mode 100644 index 000000000..f964491c4 --- /dev/null +++ b/documentation/user-faq.md @@ -0,0 +1,333 @@ +# What to download? + +Each board is fully supported with three basic system options: Debian Wheezy, Jessie and Ubuntu Trusty desktop build per board. + +# Which kernel to use? + +All stable kernels are production ready, but you should use them for different purpuses: + + * for headless server or light desktop operations use vanilla kernel (linux-image-next-[kernelfamily](http://forum.armbian.com/index.php/topic/211-kernel-update-procedure-has-been-changed/)) + * for using video acceleration, audio, IR, NAND, ... you should stick to legacy (linux-image-[kernelfamily](http://forum.armbian.com/index.php/topic/211-kernel-update-procedure-has-been-changed/)) + +# How to prepare SD card? + +Unzipped .raw images can be written with supplied imagewriter.exe on Windows XP/2003/Win7, with [Win32Diskimager](http://sourceforge.net/projects/win32diskimager/) on Windows 8.x or with DD command in Linux/Mac: + + dd bs=1M if=filename.raw of=/dev/sdx + # /dev/sdx is your sd card device + +Image writting takes around 3 minutes on a slow, class 6 SD card. + +# How to boot? + +Insert SD card into a slot and power the board. First boot takes around 3 minutes than it reboots and you will need to wait another one minute to login. This delay is because system updates package list and creates 128Mb emergency SWAP on the SD card. + +Normal boot (with DHCP) takes up to 35 seconds with a class 6 SD CARD and cheapest board. + +# How to login? + +Login as **root** on console or via SSH and use password **1234**. You will be prompted to change this password at first login. This is the only pre-installed user. + +Desktop images starts into desktop without asking for password. To change this add some display manager: + + apt-get install lightdm + +... or edit the contents of file: + + /etc/default/nodm + +and change the autologin user. + +# How to update kernel? + +For Armbian 4.2 and newer. + + apt-get update + apt-get upgrade + reboot + +For all other cases. Note that this procedure upgrades only kernel with hardware definitions (bin, dtb, firmware and headers. Operating system and modifications remain as is. + + wget -q -O - http://upgrade.armbian.com | bash + +You will be prompted to select and confirm some actions. It's possible to upgrade **from any other distribution**. + +[su_youtube_advanced url="https:\/\/youtu.be\/iPAlPW3sv3I" controls="yes" showinfo="no" loop="yes" rel="no" modestbranding="yes"] + +# How to troubleshoot? + +If you broke the system you can try to get in this way. You have to get to u-boot command prompt, using either a serial adapter or monitor and usb keyboard. + +After switching power on or rebooting, when u-boot loads up, press some key on the keyboard (or send some key presses via terminal) to abort default boot sequence and get to the command prompt: + + U-Boot SPL 2015.07-dirty (Oct 01 2015 - 15:05:21) + ... + Hit any key to stop autoboot: 0 + sunxi# + +Enter these commands, replacing root device path if necessary. Select setenv line with ttyS0 for serial, tty1 for keyboard+monitor: + + setenv bootargs init=/bin/bash root=/dev/mmcblk0p1 rootwait console=ttyS0,115200 + # or + setenv bootargs init=/bin/bash root=/dev/mmcblk0p1 rootwait console=tty1 + + ext4load mmc 0 0x49000000 /boot/dtb/${fdtfile} + ext4load mmc 0 0x46000000 /boot/zImage + env set fdt_high ffffffff + bootz 0x46000000 - 0x49000000 + +System should eventually boot to bash shell: + + root@(none):/# + +Now you can try to fix your broken system. + + +- [Fix a Jessie systemd problem due to upgrade from 3.4 to 4.x](https://github.com/igorpecovnik/lib/issues/111) + +# How to unbrick the system? + +When something goes terribly wrong and you are not able to boot the system, this is the way to proceed. You need some linux machine, where you can mount the failed SD card. With this procedure you will reinstall the u-boot, kernel and hardware settings. In most cases this should be enought to unbrick the board. It's recommended to issue a filesystem check before mounting: + + fsck /dev/sdX -f + +Than mount the SD card and download those files (This example is only for Banana R1): + + http://apt.armbian.com/pool/main/l/linux-trusty-root-next-lamobo-r1/linux-trusty-root-next-lamobo-r1_4.5_armhf.deb + http://apt.armbian.com/pool/main/l/linux-upstream/linux-image-next-sunxi_4.5_armhf.deb + http://apt.armbian.com/pool/main/l/linux-upstream/linux-firmware-image-next-sunxi_4.5_armhf.deb + http://apt.armbian.com/pool/main/l/linux-upstream/linux-dtb-next-sunxi_4.5_armhf.deb + +This is just an example for: **Ubuntu Trusty, Lamobo R1, Vanilla kernel** (next). Alter packages naming according to [this](http://forum.armbian.com/index.php/topic/211-kernel-update-procedure-has-been-changed/). + +Mount SD card and extract all those deb files to it's mount point. + + dpkg -x DEB_FILE /mnt + +Go to /mnt/boot and link (or copy) **vmlinuz-4.x.x-sunxi** kernel file to **zImage**. + +Unmount SD card, move it to the board and power on. + +# How to add users? + +To create a normal user do this: + + adduser MyNewUsername + +Put user to sudo group: + + usermod -aG sudo MyNewUsername + +# How to customize keyboard, time zone? + +keyboard: + + dpkg-reconfigure keyboard-configuration + +system language: + + dpkg-reconfigure locales + +time zone: + + dpkg-reconfigure tzdata + +screen resolution: + + nano /boot/boot.cmd + + # example: + # change example from + # disp.screen0_output_mode=1920x1080p60 + # to + # disp.screen0_output_mode=1280x720p60 + + mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr + +screen resolution interactive - only Allwinner boards with A10 and A20 with legacy kernel: + + # Example to set console framebuffer resolution to 1280 x 720 + a10disp changehdmimodeforce 4 + +Other modes: + + 0 480i + 1 576i + 2 480p + 3 576p + 4 720p 50Hz + 5 720p 60Hz + 6 1080i 50 Hz + 7 1080i 60 Hz + 8 1080p 24 Hz + 9 1080p 50 Hz + 10 1080p 60 Hz + +# How to alter CPU frequency? + +Some boards allow to adjust CPU speed. + + nano /etc/init.d/cpufrequtils + +Alter **min_speed** or **max_speed** variable. + + service cpufrequtils restart + +# How to upgrade into simple desktop environment? + + apt-get -y install xorg lightdm xfce4 tango-icon-theme gnome-icon-theme + reboot + + +Check [this site](http://namhuy.net/1085/install-gui-on-debian-7-wheezy.html) for others. + +# How to upgrade Debian from Wheezy to Jessie? + + dpkg -r ramlog + cp /etc/apt/sources.list{,.bak} + sed -i -e 's/ \(old-stable\|wheezy\)/ jessie/ig' /etc/apt/sources.list + apt-get update + apt-get --download-only dist-upgrade + apt-get dist-upgrade + + +# How to upgrade from Ubuntu Trusty to next LTS? + +... when available. + + apt-get install update-manager-core + do-release-upgrade -d + # further to vivid + apt-get dist-upgrade + +# How to toggle boot output? +Edit and change [boot parameters](http://redsymbol.net/linux-kernel-boot-parameters/) in /boot/boot.cmd: + + - console=ttyS0,115200 + + console=tty1 + +and convert it to boot.scr with this command: + + mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr + +Reboot. + +Serial console on imx6 boards are ttymxc0 (Hummingboard, Cubox-i) or ttymxc1 (Udoo). + +# How to install to NAND, SATA & USB? + +[su_youtube_advanced url="https:\/\/youtu.be\/6So8MA-qru8" controls="yes" showinfo="no" loop="yes" rel="no" modestbranding="yes"] + +Required condition: + +NAND: + + * kernel 3.4.x and NAND storage + * pre-installed system on NAND (stock Android or other Linux) + +SATA/USB: + + * any kernel + * pre-partitioned SATA or USB storage + +Start the install script: + + nand-sata-install + +and follow the guide. You can create up to three scenarios: + + * boot from SD, system on SATA / USB + * boot from NAND, system on NAND + * boot from NAND, system on SATA / USB + +# How to change network configuration? + +There are five predefined configurations, you can find them in those files: + + /etc/network/interfaces.default + /etc/network/interfaces.hostapd + /etc/network/interfaces.bonding + /etc/network/interfaces.r1 + /etc/network/interfaces.r1switch + +By default **/etc/network/interfaces** is symlinked to **/etc/network/interfaces.default** + +1. DEFAULT: your network adapters are connected classical way. +2. HOSTAPD: your network adapters are bridged together and bridge is connected to the network. This allows you to have your AP connected directly to your router. +3. BONDING: your network adapters are bonded in fail safe / "notebook" way. +4. Router configuration for Lamobo R1 / Banana R1. +5. Switch configuration for Lamobo R1 / Banana R1. + +You can switch configuration with re-linking. + + cd /etc/network + ln -sf interfaces.x interfaces +(x = default,hostapd,bonding,r1) + +Than check / alter your interfaces: + + nano /etc/network/interfaces + +# How to set fixed IP? + +By default your main network adapter's IP is assigned by your router DHCP server. + + iface eth0 inet dhcp + +change to - for example: + + iface eth0 inet static + address 192.168.1.100 + netmask 255.255.255.0 + gateway 192.168.1.1 + +# How to set wireless access point? + +There are two different hostap daemons. One is **default** and the other one is for some **Realtek** wifi cards. Both have their own basic configurations and both are patched to gain maximum performances. + +Sources: [https://github.com/igorpecovnik/hostapd](https://github.com/igorpecovnik/hostapd "https://github.com/igorpecovnik/hostapd") + +Default binary and configuration location: + + /usr/sbin/hostapd + /etc/hostapd.conf + +Realtek binary and configuration location: + + /usr/sbin/hostapd-rt + /etc/hostapd.conf-rt + +Since its hard to define when to use which you always try both combinations in case of troubles. To start AP automatically: + +1. Edit /etc/init.d/hostapd and add/alter location of your conf file **DAEMON_CONF=/etc/hostapd.conf** and binary **DAEMON_SBIN=/usr/sbin/hostapd** +2. Link **/etc/network/interfaces.hostapd** to **/etc/network/interfaces** +3. Reboot +4. Predefined network name: "BOARD NAME" password: 12345678 +5. To change parameters, edit /etc/hostapd.conf BTW: You can get WPAPSK the long blob from wpa_passphrase YOURNAME YOURPASS + +# How to connect IR remote? + +Required conditions: + +- IR hardware +- loaded driver + +Get your [remote configuration](http://lirc.sourceforge.net/remotes/) (lircd.conf) or [learn](http://kodi.wiki/view/HOW-TO:Setup_Lirc#Learning_Commands). You are going to need the list of all possible commands which you can map to your IR remote keys: + + irrecord --list-namespace + +To start with learning process you need to delete old config: + + rm /etc/lircd.conf + +Than start the process with: + + irrecord --driver=default --device=/dev/lirc0 /etc/lircd.conf + +And finally start your service when done with learning: + + service lirc start + +Test your remote: + + irw /dev/lircd diff --git a/general.sh b/general.sh new file mode 100644 index 000000000..eb56b6e4c --- /dev/null +++ b/general.sh @@ -0,0 +1,281 @@ +#!/bin/bash +# +# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com +# +# This file is licensed under the terms of the GNU General Public +# License version 2. This program is licensed "as is" without any +# warranty of any kind, whether express or implied. +# +# This file is a part of tool chain https://github.com/igorpecovnik/lib +# + + +cleaning() +#-------------------------------------------------------------------------------------------------------------------------------- +# Let's clean stuff +#-------------------------------------------------------------------------------------------------------------------------------- +{ +case $1 in +1) # Clean u-boot and kernel sources + [ -d "$SOURCES/$BOOTSOURCE" ] && display_alert "Cleaning" "$SOURCES/$BOOTSOURCE" "info" && cd $SOURCES/$BOOTSOURCE && make -s ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- clean + [ -d "$SOURCES/$LINUXSOURCE" ] && display_alert "Cleaning" "$SOURCES/$LINUXSOURCE" "info" && cd $SOURCES/$LINUXSOURCE && make -s ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- clean + [ -f $DEST/cache/building/$HEADERS_CACHE.tgz ] && display_alert "Cleaning" "$HEADERS_CACHE.tgz" "info" && rm -f $DEST/cache/building/$HEADERS_CACHE.tgz + +;; +2) display_alert "No cleaning" "sources" "info" +;; +3) # Choosing kernel if debs are present + if [[ $BRANCH == "next" ]]; then + MYARRAY=($(ls -1 $DEST/debs/linux-image* | awk '/next/' | sed ':a;N;$!ba;s/\n/;/g')) + else + MYARRAY=($(ls -1 $DEST/debs/linux-image* | awk '!/next/' | sed ':a;N;$!ba;s/\n/;/g')) + fi + if [[ ${#MYARRAY[@]} != "0" && $KERNEL_ONLY != "yes" ]]; then choosing_kernel; fi +;; +4) # Delete all in output except repository + display_alert "Removing deb packages" "$DEST/debs/" "info" + rm -rf $DEST/debs + display_alert "Removing root filesystem cache" "$DEST/cache" "info" + rm -rf $DEST/cache + display_alert "Removing SD card images" "$DEST/images" "info" + rm -rf $DEST/images +;; +*) # Clean u-boot and kernel sources and remove debs + [ -d "$SOURCES/$BOOTSOURCE" ] && + display_alert "Cleaning" "$SOURCES/$BOOTSOURCE" "info" && cd $SOURCES/$BOOTSOURCE && make -s ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- clean + [ -f "$DEST/debs/$CHOOSEN_UBOOT" ] && + display_alert "Removing" "$DEST/debs/$CHOOSEN_UBOOT" "info" && rm $DEST/debs/$CHOOSEN_UBOOT + [ -d "$SOURCES/$LINUXSOURCE" ] && + display_alert "Cleaning" "$SOURCES/$LINUXSOURCE" "info" && cd $SOURCES/$LINUXSOURCE && make -s ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- clean + [ -f "$DEST/debs/$CHOOSEN_KERNEL" ] && + display_alert "Removing" "$DEST/debs/$CHOOSEN_KERNEL" "info" && rm $DEST/debs/$CHOOSEN_KERNEL + [ -f $DEST/cache/building/$HEADERS_CACHE.tgz ] && display_alert "Cleaning" "$HEADERS_CACHE.tgz" "info" && rm -f $DEST/cache/building/$HEADERS_CACHE.tgz +;; +esac +} + + +fetch_from_github (){ +#-------------------------------------------------------------------------------------------------------------------------------- +# Download or updates sources from Github +#-------------------------------------------------------------------------------------------------------------------------------- +if [ -d "$SOURCES/$2" ]; then + cd $SOURCES/$2 + if [[ "$3" != "" ]]; then + PULL=$(git checkout $FORCE -q $3) + fi + display_alert "... updating" "$2" "info" + PULL=$(git pull) + cd $SRC +else + display_alert "... downloading" "$2" "info" + git clone $1 $SOURCES/$2 +fi +if [ $? -ne 0 ]; then display_alert "Github download failed" "$1" "err"; exit 1; fi +} + + +display_alert() +#-------------------------------------------------------------------------------------------------------------------------------- +# Let's have unique way of displaying alerts +#-------------------------------------------------------------------------------------------------------------------------------- +{ +if [[ $2 != "" ]]; then TMPARA="[\e[0;33m $2 \x1B[0m]"; else unset TMPARA; fi +if [ $3 == "err" ]; then + echo -e "[\e[0;31m error \x1B[0m] $1 $TMPARA" +elif [ $3 == "wrn" ]; then + echo -e "[\e[0;35m warn \x1B[0m] $1 $TMPARA" +else + echo -e "[\e[0;32m o.k. \x1B[0m] $1 $TMPARA" +fi +} + + +check_error () +# check last command and display warning only +{ +if [ $? -ne 0 ]; then + # display warning if patching fails + display_alert "... failed. More info: debug/install.log" "$1" "wrn"; +fi +} + + +install_packet () +{ +#-------------------------------------------------------------------------------------------------------------------------------- +# Install packets inside chroot +#-------------------------------------------------------------------------------------------------------------------------------- +i=0 +j=1 +declare -a PACKETS=($1) +skupaj=${#PACKETS[@]} +while [[ $i -lt $skupaj ]]; do +procent=$(echo "scale=2;($j/$skupaj)*100"|bc) +procent=${procent%.*} + x=${PACKETS[$i]} + if [[ $3 == "host" ]]; then + DEBIAN_FRONTEND=noninteractive apt-get -qq -y install $x >> $DEST/debug/install.log 2>&1 + else + chroot $DEST/cache/sdcard /bin/bash -c "DEBIAN_FRONTEND=noninteractive apt-get -qq -y install $x" >> $DEST/debug/install.log 2>&1 + fi + + if [ $? -ne 0 ]; then display_alert "Installation of package failed" "$INSTALL" "err"; exit 1; fi + + if [[ $4 != "quiet" ]]; then + printf '%.0f\n' $procent | dialog --backtitle "$backtitle" --title "$2" --gauge "\n\n$x" 9 70 + fi + i=$[$i+1] + j=$[$j+1] +done +} + +grab_kernel_version (){ +#-------------------------------------------------------------------------------------------------------------------------------- +# extract linux kernel version from Makefile +#-------------------------------------------------------------------------------------------------------------------------------- +VER=$(cat $SOURCES/$LINUXSOURCE/Makefile | grep VERSION | head -1 | awk '{print $(NF)}') +VER=$VER.$(cat $SOURCES/$LINUXSOURCE/Makefile | grep PATCHLEVEL | head -1 | awk '{print $(NF)}') +VER=$VER.$(cat $SOURCES/$LINUXSOURCE/Makefile | grep SUBLEVEL | head -1 | awk '{print $(NF)}') +EXTRAVERSION=$(cat $SOURCES/$LINUXSOURCE/Makefile | grep EXTRAVERSION | head -1 | awk '{print $(NF)}' | cut -d '-' -f 2) +if [ "$EXTRAVERSION" != "=" ]; then VER=$VER$EXTRAVERSION; fi +} + + +grab_u-boot_version (){ +#-------------------------------------------------------------------------------------------------------------------------------- +# extract uboot version from Makefile +#-------------------------------------------------------------------------------------------------------------------------------- +UBOOTVER=$(cat $SOURCES/$BOOTSOURCE/Makefile | grep VERSION | head -1 | awk '{print $(NF)}') +UBOOTVER=$UBOOTVER.$(cat $SOURCES/$BOOTSOURCE/Makefile | grep PATCHLEVEL | head -1 | awk '{print $(NF)}') +UBOOTSUB=$(cat $SOURCES/$BOOTSOURCE/Makefile | grep SUBLEVEL | head -1 | awk '{print $(NF)}' | cut -d '=' -f 2) +[ "$UBOOTSUB" != "" ] && UBOOTVER=$UBOOTVER.$UBOOTSUB +EXTRAVERSION=$(cat $SOURCES/$BOOTSOURCE/Makefile | grep EXTRAVERSION | head -1 | awk '{print $(NF)}' | cut -d '-' -f 2) +if [ "$EXTRAVERSION" != "=" ]; then UBOOTVER=$UBOOTVER$EXTRAVERSION; fi +} + + +choosing_kernel (){ +#-------------------------------------------------------------------------------------------------------------------------------- +# Choose which kernel to use +#-------------------------------------------------------------------------------------------------------------------------------- +IFS=";" +cd $DEST"/debs/" +if [[ $BRANCH == "next" ]]; then +MYARRAY=($(ls -1 linux-image* | awk '/next/' | sed ':a;N;$!ba;s/\n/;/g')) +else +MYARRAY=($(ls -1 linux-image* | awk '!/next/' | sed ':a;N;$!ba;s/\n/;/g')) +fi +# if there are no precompiled kernels proceed with compilation +if [[ ${#MYARRAY[@]} == "0" ]]; then +SOURCE_COMPILE="yes" +fi + +MYPARAMS=( --title "Choose a kernel" --backtitle $backtitle --menu "\n Prebuild packages:" 25 60 16 ) +i=0 +while [[ $i -lt ${#MYARRAY[@]} ]] + do + MYPARAMS+=( "${MYARRAY[$i]}" " -" ) + i=$[$i+1] + done +whiptail "${MYPARAMS[@]}" 2>results +CHOOSEN_KERNEL=$( $1 +echo "" >> $1 +echo "" >> $1 +echo "" >> $1 +echo "Title: $VERSION (unofficial)" >> $1 +echo "Kernel: Linux $VER" >> $1 +now="$(date +'%d.%m.%Y')" >> $1 +printf "Build date: %s\n" "$now" >> $1 +echo "Author: Igor Pecovnik, www.igorpecovnik.com" >> $1 +echo "Sources: http://github.com/igorpecovnik" >> $1 +echo "" >> $1 +echo "Support: http://www.armbian.com" >> $1 +echo "" >> $1 +echo "" >> $1 +echo "--------------------------------------------------------------------------------" >> $1 +echo "" >> $1 +cat $SRC/lib/LICENSE >> $1 +echo "" >> $1 +echo "--------------------------------------------------------------------------------" >> $1 +} + + +umount_image (){ +FBTFTMOUNT=$(mount | grep fbtft | awk '{ print $3 }') +umount $FBTFTMOUNT >/dev/null 2>&1 +umount $SOURCES/$LINUXSOURCE/drivers/video/fbtft >/dev/null 2>&1 +umount -l $DEST/cache/sdcard/dev/pts >/dev/null 2>&1 +umount -l $DEST/cache/sdcard/dev >/dev/null 2>&1 +umount -l $DEST/cache/sdcard/proc >/dev/null 2>&1 +umount -l $DEST/cache/sdcard/sys >/dev/null 2>&1 +umount -l $DEST/cache/sdcard/tmp >/dev/null 2>&1 +umount -l $DEST/cache/sdcard >/dev/null 2>&1 +IFS=" " +x=$(losetup -a |awk '{ print $1 }' | rev | cut -c 2- | rev | tac); +for x in $x; do + losetup -d $x +done +} + + +addtorepo () +{ +# add all deb files to repository +# parameter "remove" dumps all and creates new +# function: cycle trough distributions +DISTROS=("wheezy" "jessie" "trusty") +IFS=" " +j=0 +while [[ $j -lt ${#DISTROS[@]} ]] + do + # add each packet to distribution + DIS=${DISTROS[$j]} + + # let's drop from publish if exits + if [ "$(aptly publish list -config=config/aptly.conf -raw | awk '{print $(NF)}' | grep $DIS)" != "" ]; then + aptly publish drop -config=config/aptly.conf $DIS > /dev/null 2>&1 + fi + #aptly db cleanup -config=config/aptly.conf + + if [ "$1" == "remove" ]; then + # remove repository + aptly repo drop -config=config/aptly.conf $DIS > /dev/null 2>&1 + aptly db cleanup -config=config/aptly.conf > /dev/null 2>&1 + fi + + # create repository if not exist + OUT=$(aptly repo list -config=config/aptly.conf -raw | awk '{print $(NF)}' | grep $DIS) + if [[ "$OUT" != "$DIS" ]]; then + display_alert "Creating section" "$DIS" "info" + aptly repo create -config=config/aptly.conf -distribution=$DIS -component=main -comment="Armbian stable" $DIS > /dev/null 2>&1 + fi + + # add all packages + aptly repo add -force-replace=true -config=config/aptly.conf $DIS $POT/*.deb + + # add all distribution packages + if [ -d "$POT/$DIS" ]; then + aptly repo add -force-replace=true -config=config/aptly.conf $DIS $POT/$DIS/*.deb + fi + + aptly publish -passphrase=$GPG_PASS -force-overwrite=true -config=config/aptly.conf -component="main" --distribution=$DIS repo $DIS > /dev/null 2>&1 + + #aptly repo show -config=config/aptly.conf $DIS + + j=$[$j+1] +done +} \ No newline at end of file diff --git a/main.sh b/main.sh index bbe360756..05591fffc 100644 --- a/main.sh +++ b/main.sh @@ -1,101 +1,296 @@ #!/bin/bash - -#-------------------------------------------------------------------------------------------------------------------------------- -# let's start with fresh screen -clear - -#-------------------------------------------------------------------------------------------------------------------------------- -# optimize build time with 100% CPU usage -CPUS=$(grep -c 'processor' /proc/cpuinfo) -if [ "$USEALLCORES" = "yes" ]; then -CTHREADS="-j$(($CPUS + $CPUS/2))"; -else -CTHREADS="-j${CPUS}"; -fi - -#-------------------------------------------------------------------------------------------------------------------------------- -# to display build time at the end -start=`date +%s` - -#-------------------------------------------------------------------------------------------------------------------------------- -# display what we are doing -echo "Building $VERSION." - -#-------------------------------------------------------------------------------------------------------------------------------- -# Download packages for host # -download_host_packages - -#-------------------------------------------------------------------------------------------------------------------------------- -# fetch_from_github [repository, sub directory] +# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com +# +# This file is licensed under the terms of the GNU General Public +# License version 2. This program is licensed "as is" without any +# warranty of any kind, whether express or implied. +# +# This file is a part of tool chain https://github.com/igorpecovnik/lib +# +# +# Main program # -mkdir -p $DEST/output -fetch_from_github "$BOOTLOADER" "$BOOTSOURCE" -fetch_from_github "$LINUXKERNEL" "$LINUXSOURCE" -if [[ -n "$DOCS" ]]; then fetch_from_github "$DOCS" "$DOCSDIR"; fi -if [[ -n "$MISC1" ]]; then fetch_from_github "$MISC1" "$MISC1_DIR"; fi -if [[ -n "$MISC2" ]]; then fetch_from_github "$MISC2" "$MISC2_DIR"; fi -if [[ -n "$MISC3" ]]; then fetch_from_github "$MISC3" "$MISC3_DIR"; fi -if [[ -n "$MISC4" ]]; then fetch_from_github "$MISC4" "$MISC4_DIR"; fi - -#-------------------------------------------------------------------------------------------------------------------------------- -# grab linux kernel version from Makefile # -VER=$(cat $DEST/$LINUXSOURCE/Makefile | grep VERSION | head -1 | awk '{print $(NF)}') -VER=$VER.$(cat $DEST/$LINUXSOURCE/Makefile | grep PATCHLEVEL | head -1 | awk '{print $(NF)}') -VER=$VER.$(cat $DEST/$LINUXSOURCE/Makefile | grep SUBLEVEL | head -1 | awk '{print $(NF)}') -EXTRAVERSION=$(cat $DEST/$LINUXSOURCE/Makefile | grep EXTRAVERSION | head -1 | awk '{print $(NF)}') -if [ "$EXTRAVERSION" != "=" ]; then VER=$VER$EXTRAVERSION; fi -# always compile boot loader -compile_uboot -if [ "$SOURCE_COMPILE" = "yes" ]; then -#-------------------------------------------------------------------------------------------------------------------------------- - # Patching sources + # currently there is no option to create an image without root + # you can compile a kernel but you can complete the whole process + # if you find a way, please submit code corrections. Thanks. + if [ "$UID" -ne 0 ] + then echo "Please run as root"; exit + fi + + # We'll use this tittle on all menus + backtitle="Armbian building script, http://www.armbian.com | Author: Igor Pecovnik" + mkdir -p $DEST/debug $SRC/userpatches/kernel $SRC/userpatches/u-boot + echo "Place your patches here. They'll be automaticly included during patching process!" > $SRC/userpatches/readme.txt + + # Install some basic support if not here yet + if [ $(dpkg-query -W -f='${Status}' whiptail 2>/dev/null | grep -c "ok installed") -eq 0 ]; then + apt-get install -qq -y whiptail bc >/dev/null 2>&1 + fi + + if [ $(dpkg-query -W -f='${Status}' bc 2>/dev/null | grep -c "ok installed") -eq 0 ]; then + apt-get install -qq -y bc >/dev/null 2>&1 + fi + + if [ $(dpkg-query -W -f='${Status}' dialog 2>/dev/null | grep -c "ok installed") -eq 0 ]; then + apt-get install -qq -y dialog >/dev/null 2>&1 + fi + + # if language not set, set to english + [ "$LANGUAGE" == "" ] && export LANGUAGE="en_US:en" + + # default console if not set + [ "$CONSOLE_CHAR" == "" ] && export CONSOLE_CHAR="UTF-8" + + # Add aptly repository for repo handling + if [ ! -f "/etc/apt/sources.list.d/aptly.list" ]; then + echo "deb http://repo.aptly.info/ squeeze main" > /etc/apt/sources.list.d/aptly.list + apt-key adv --keyserver keys.gnupg.net --recv-keys E083A3782A194991 + apt-get update + fi + + + # Choose destination - creating board list from file configuration.sh + if [ "$BOARD" == "" ]; then + IFS=";" + MYARRAY=($(cat $SRC/lib/configuration.sh | awk '/\)#enabled/ || /#des/' | sed 's/)#enabled//g' \ + | sed 's/#description //g' | sed ':a;N;$!ba;s/\n/;/g')) + MYPARAMS=( --title "Choose a board" --backtitle $backtitle --menu "\n Supported:" 34 67 24 ) + i=0; j=1 + while [[ $i -lt ${#MYARRAY[@]} ]]; do + MYPARAMS+=( "${MYARRAY[$i]}" " ${MYARRAY[$j]}" ) + i=$[$i+2]; j=$[$j+2] + done + whiptail "${MYPARAMS[@]}" 2>results + BOARD=$(results + RELEASE=$(results + BUILD_DESKTOP=$(results + BRANCH=$( $DEST/debug/install.log + + + # let's start with fresh screen + clear + display_alert "Dependencies check" "@host" "info" + + # optimize build time with 100% CPU usage + CPUS=$(grep -c 'processor' /proc/cpuinfo) + if [ "$USEALLCORES" = "yes" ]; then + CTHREADS="-j$(($CPUS + $CPUS/2))"; + else + CTHREADS="-j${CPUS}"; + fi + + # Use C compiler cache + if [ "$USE_CCACHE" = "yes" ]; then + CCACHE="ccache"; + else + CCACHE=""; + fi + + # display what we do + if [ "$KERNEL_ONLY" == "yes" ]; then + display_alert "Compiling kernel" "$BOARD" "info" + else + display_alert "Building" "$VERSION" "info" + fi + + # download packages for host + PAK="aptly device-tree-compiler pv bc lzop zip binfmt-support bison build-essential ccache debootstrap flex ntpdate " + PAK=$PAK"gawk gcc-arm-linux-gnueabihf lvm2 qemu-user-static u-boot-tools uuid-dev zlib1g-dev unzip libusb-1.0-0-dev " + PAK=$PAK"parted pkg-config expect gcc-arm-linux-gnueabi libncurses5-dev whiptail debian-keyring debian-archive-keyring" + + if [ "$(LANGUAGE=english apt-get -s install $PAK | grep "0 newly installed")" == "" ]; then + install_packet "$PAK" "Checking and installing host dependencies" "host" + fi + + # sync clock + if [ "$SYNC_CLOCK" != "no" ]; then + display_alert "Synching clock" "host" "info" + ntpdate -s time.ijs.si + fi + start=`date +%s` + + # fetch_from_github [repository, sub directory] + mkdir -p $DEST -p $SOURCES + + if [ "$FORCE_CHECKOUT" = "yes" ]; then FORCE="-f"; else FORCE=""; fi + display_alert "source downloading" "@host" "info" + + fetch_from_github "$BOOTLOADER" "$BOOTSOURCE" "$BOOTDEFAULT" + fetch_from_github "$LINUXKERNEL" "$LINUXSOURCE" "$LINUXDEFAULT" + if [[ -n "$MISC1" ]]; then fetch_from_github "$MISC1" "$MISC1_DIR"; fi + if [[ -n "$MISC2" ]]; then fetch_from_github "$MISC2" "$MISC2_DIR"; fi + if [[ -n "$MISC3" ]]; then fetch_from_github "$MISC3" "$MISC3_DIR"; fi + if [[ -n "$MISC4" ]]; then fetch_from_github "$MISC4" "$MISC4_DIR" "master"; fi + if [[ -n "$MISC5" ]]; then fetch_from_github "$MISC5" "$MISC5_DIR"; fi + + # compile sunxi tools + if [[ $LINUXFAMILY == *sun* ]]; then + compile_sunxi_tools + fi + + # define some packages + if [[ $BRANCH == "next" ]] ; then KERNEL_BRACH="-next"; UBOOT_BRACH="-next"; else KERNEL_BRACH=""; UBOOT_BRACH=""; fi + CHOOSEN_UBOOT=linux-u-boot"$UBOOT_BRACH"-"$BOARD"_"$REVISION"_armhf.deb + CHOOSEN_KERNEL=linux-image"$KERNEL_BRACH"-"$CONFIG_LOCALVERSION$LINUXFAMILY"_"$REVISION"_armhf.deb + CHOOSEN_ROOTFS=linux-"$RELEASE"-root"$ROOT_BRACH"-"$BOARD"_"$REVISION"_armhf + HEADERS_CACHE="${CHOOSEN_KERNEL/image/cache}" + + # cleaning level 0,1,2,3 + cleaning "$CLEAN_LEVEL" + + # patching sources patching_sources - # compile kernel and create archives - compile_kernel - - # create tar file - packing_kernel - -else - - # choose kernel from ready made - choosing_kernel - -#-------------------------------------------------------------------------------------------------------------------------------- -fi + # Compile source if packed not exits + [ ! -f "$DEST/debs/$CHOOSEN_UBOOT" ] && compile_uboot + [ ! -f "$DEST/debs/$CHOOSEN_KERNEL" ] && compile_kernel -#-------------------------------------------------------------------------------------------------------------------------------- -# create or use prepared root file-system -create_debian_template + if [ "$KERNEL_ONLY" == "yes" ]; then + [[ -n "$RELEASE" ]] && create_board_package + display_alert "Kernel building done" "@host" "info" + display_alert "Target directory" "$DEST/debs/" "info" + display_alert "File name" "$CHOOSEN_KERNEL" "info" + else + + # create or use prepared root file-system + custom_debootstrap -#-------------------------------------------------------------------------------------------------------------------------------- -# add kernel to the image -install_kernel + # add kernel to the image + install_kernel -#-------------------------------------------------------------------------------------------------------------------------------- -# install board specific applications -install_board_specific + # install board specific applications + install_distribution_specific + create_board_package + install_board_specific -#-------------------------------------------------------------------------------------------------------------------------------- -# install external applications -if [ "$EXTERNAL" = "yes" ]; then -install_external_applications -fi + # install desktop + if [ "$BUILD_DESKTOP" = "yes" ]; then + install_desktop + fi -#-------------------------------------------------------------------------------------------------------------------------------- -# add some summary to the image -fingerprint_image "$DEST/output/sdcard/root/readme.txt" + # install external applications + if [ "$EXTERNAL" = "yes" ]; then + install_external_applications + fi -#-------------------------------------------------------------------------------------------------------------------------------- -# closing image -closing_image + # closing image + closing_image + fi -end=`date +%s` -runtime=$(((end-start)/60)) -echo "Runtime $runtime min." + end=`date +%s` + runtime=$(((end-start)/60)) + umount $SOURCES/$LINUXSOURCE/drivers/video/fbtft >/dev/null 2>&1 + display_alert "Runtime" "$runtime min" "info" \ No newline at end of file diff --git a/makeboarddeb.sh b/makeboarddeb.sh new file mode 100644 index 000000000..af3d9a27c --- /dev/null +++ b/makeboarddeb.sh @@ -0,0 +1,130 @@ +#!/bin/bash +# +# Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com +# +# This file is licensed under the terms of the GNU General Public +# License version 2. This program is licensed "as is" without any +# warranty of any kind, whether express or implied. +# +# This file is a part of tool chain https://github.com/igorpecovnik/lib +# +# +# Create board support packages +# +# + +create_board_package (){ +#--------------------------------------------------------------------------------------------------------------------------------- +# create .deb package for the rest +#--------------------------------------------------------------------------------------------------------------------------------- + + display_alert "Creating board support package." "$BOARD" "info" + + if [[ $BRANCH == "next" ]]; then + ROOT_BRACH="-next"; + else + ROOT_BRACH=""; + fi + + # construct a package name + CHOOSEN_ROOTFS=linux-"$RELEASE"-root"$ROOT_BRACH"-"$BOARD"_"$REVISION"_armhf + + local destination=$DEST/debs/$RELEASE/$CHOOSEN_ROOTFS + local controlfile=$destination/DEBIAN/control + + mkdir -p $destination/DEBIAN + + echo "Package: linux-$RELEASE-root$ROOT_BRACH-$BOARD" > $controlfile + echo "Version: $REVISION" >> $controlfile + echo "Architecture: armhf" >> $controlfile + echo "Maintainer: $MAINTAINER <$MAINTAINERMAIL>" >> $controlfile + echo "Installed-Size: 1" >> $controlfile + echo "Section: kernel" >> $controlfile + echo "Priority: optional" >> $controlfile + echo "Description: Root file system tweaks for $BOARD" >> $controlfile + + # set up post install script + echo "#!/bin/bash" > $destination/DEBIAN/postinst + chmod 755 $destination/DEBIAN/postinst + + # scripts for autoresize at first boot + mkdir -p $destination/etc/init.d + mkdir -p $destination/etc/default + + install -m 755 $SRC/lib/scripts/resize2fs $destination/etc/init.d + install -m 755 $SRC/lib/scripts/firstrun $destination/etc/init.d + + # install custom bashrc and hardware dependent motd + + install $SRC/lib/scripts/bashrc $destination/etc/bash.bashrc.custom + install -m 755 $SRC/lib/scripts/armhwinfo $destination/etc/init.d + echo "set -e" >> $destination/DEBIAN/postinst + echo "update-rc.d armhwinfo defaults >/dev/null 2>&1" >> $destination/DEBIAN/postinst + echo "update-rc.d -f motd remove >/dev/null 2>&1" >> $destination/DEBIAN/postinst + echo "[[ -f /root/.nand1-allwinner.tgz ]] && rm /root/.nand1-allwinner.tgz" >> $destination/DEBIAN/postinst + echo "[[ -f /root/nand-sata-install ]] && rm /root/nand-sata-install" >> $destination/DEBIAN/postinst + echo "exit 0" >> $destination/DEBIAN/postinst + + # temper binary for USB temp meter + mkdir -p $destination/usr/local/bin + tar xfz $SRC/lib/bin/temper.tgz -C $destination/usr/local/bin + + # replace hostapd from latest self compiled & patched + mkdir -p $destination/usr/sbin/ + tar xfz $SRC/lib/bin/hostapd25-rt.tgz -C $destination/usr/sbin/ + tar xfz $SRC/lib/bin/hostapd25.tgz -C $destination/usr/sbin/ + + # module evbug is loaded automagically at boot time but we don't want that + mkdir -p $destination/etc/modprobe.d/ + echo "blacklist evbug" > $destination/etc/modprobe.d/ev-debug-blacklist.conf + + # script to install to SATA + cp -R $SRC/lib/scripts/nand-sata-install/usr $destination/ + chmod +x $destination/usr/lib/nand-sata-install/nand-sata-install.sh + ln -s ../lib/nand-sata-install/nand-sata-install.sh $destination/usr/sbin/nand-sata-install + + # first login and reboot note when updated + mkdir -p $destination/root $destination/tmp $destination/etc/profile.d + install -m 755 $SRC/lib/scripts/check_first_login_reboot.sh $destination/etc/profile.d + install -m 755 $SRC/lib/scripts/check_first_login.sh $destination/etc/profile.d + touch $destination/root/.not_logged_in_yet + touch $destination/tmp/.reboot_required + + if [[ $LINUXCONFIG == *sun* ]] ; then + + # add sunxi tools + tar xfz $SRC/lib/bin/sunxitools.tgz -C $destination/usr/local/bin + if [ "$BRANCH" != "next" ]; then + # add soc temperature app + arm-linux-gnueabihf-gcc $SRC/lib/scripts/sunxi-temp/sunxi_tp_temp.c -o $destination/usr/local/bin/sunxi_tp_temp + fi + + # lamobo R1 router switch config + tar xfz $SRC/lib/bin/swconfig.tgz -C $destination/usr/local/bin + + # convert and add fex files + unset IFS + mkdir -p $destination/boot/bin + for i in $(ls -w1 $SRC/lib/config/*.fex | xargs -n1 basename); do + fex2bin $SRC/lib/config/${i%*.fex}.fex $destination/boot/bin/${i%*.fex}.bin; + done + + # bluetooth device enabler - for cubietruck + install -m 755 $SRC/lib/bin/brcm_patchram_plus $destination/usr/local/bin + install $SRC/lib/scripts/brcm40183 $destination/etc/default + install -m 755 $SRC/lib/scripts/brcm40183-patch $destination/etc/init.d + + fi + + # add some summary to the image + fingerprint_image "$destination/etc/armbian.txt" + + # create board DEB file + cd $DEST/debs/$RELEASE/ + display_alert "Building deb package." "$CHOOSEN_ROOTFS"".deb" "info" + dpkg -b $CHOOSEN_ROOTFS >/dev/null 2>&1 + + # clean up + rm -rf $CHOOSEN_ROOTFS + rm -f ../.reboot_required +} \ No newline at end of file diff --git a/patch/devices/sun4i-a10.h b/patch/devices/sun4i-a10.h new file mode 100644 index 000000000..f7553c143 --- /dev/null +++ b/patch/devices/sun4i-a10.h @@ -0,0 +1,62 @@ +/* + * Copyright 2014 Maxime Ripard + * + * Maxime Ripard + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __DT_BINDINGS_PINCTRL_SUN4I_A10_H_ +#define __DT_BINDINGS_PINCTRL_SUN4I_A10_H_ + +#define SUN4I_PINCTRL_10_MA 0 +#define SUN4I_PINCTRL_20_MA 1 +#define SUN4I_PINCTRL_30_MA 2 +#define SUN4I_PINCTRL_40_MA 3 + +#define SUN4I_PINCTRL_NO_PULL 0 +#define SUN4I_PINCTRL_PULL_UP 1 +#define SUN4I_PINCTRL_PULL_DOWN 2 + +#endif /* __DT_BINDINGS_PINCTRL_SUN4I_A10_H_ */ diff --git a/patch/devices/sun6i-a31s-bananapi-m2.dts b/patch/devices/sun6i-a31s-bananapi-m2.dts new file mode 100644 index 000000000..6bbed73e5 --- /dev/null +++ b/patch/devices/sun6i-a31s-bananapi-m2.dts @@ -0,0 +1,244 @@ +/* + * Copyright 2015 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun6i-a31.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include + +/ { + model = "Banana Pi BPI-M2"; + compatible = "sinovoip,bpi-m2", "allwinner,sun6i-a31"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_bananapi>; + green { + label = "bananapi:green:usr"; + gpios = <&pio 6 10 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + blue { + label = "bananapi:blue:usr"; + gpios = <&pio 6 11 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + }; + red { + label = "bananapi:red:usr"; + gpios = <&pio 6 5 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "default-on"; + }; + }; + + g40_leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&g40_pins_bananapi>; + pm2 { + label = "bananapi:pm2:usr"; + gpios = <&r_pio 1 2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + reg_vmmc2: vmmc2 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&vmmc2_pin_bananapi>; + regulator-name = "vmmc2"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + enable-active-high; + gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */ +// gpio = <&r_pio 1 0 GPIO_ACTIVE_HIGH>; /* PM0 */ + }; +}; + +&ohci0 { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_rgmii_a>; + phy = <&phy1>; + phy-mode = "rgmii"; + snps,reset-gpio = <&pio 0 21 GPIO_ACTIVE_HIGH>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 30000>; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + /* pull-ups and devices require AXP221 DLDO3 */ + status = "failed"; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_a>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_bananapi>; + vmmc-supply = <®_vcc3v0>; + bus-width = <4>; + cd-gpios = <&pio 0 4 GPIO_ACTIVE_HIGH>; /* PA4 */ + cd-inverted; + status = "okay"; +}; + +&mmc2 { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins_a>; + vmmc-supply = <®_vmmc2>; + bus-width = <4>; + non-removable; + enable-sdio-wakeup; + status = "okay"; + +/* + brcmf: bcrmf@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; + interrupt-parent = <&pio>; + interrupts = <5 0>; + interrupt-names = "host-wake"; + status = "okay"; + }; +*/ +}; + +&mmc0_pins_a { + /* external pull-ups missing for some pins */ + allwinner,pull = ; +}; + +&mmc2_pins_a { + /* external pull-ups missing for some pins */ + allwinner,pull = ; +}; + +&pio { + led_pins_bananapi: led_pins@0 { + allwinner,pins = "PG10", "PG5", "PG11"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc0_cd_pin_bananapi: mmc0_cd_pin@0 { + allwinner,pins = "PA4"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc2_pins_a: mmc2@0 { + allwinner,pins = "PC6","PC7","PC8","PC9","PC10","PC11"; + allwinner,function = "mmc2"; + allwinner,drive = ; + allwinner,pull = ; + }; + + +}; + +&r_pio { + g40_pins_bananapi: g40_pins@0 { + allwinner,pins = "PM2"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + vmmc2_pin_bananapi: vmmc2_pin@0 { + allwinner,pins = "PL8"; +// allwinner,pins = "PM0"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + status = "okay"; +}; diff --git a/patch/devices/sun7i-a20-bananapi-m1-plus.dts b/patch/devices/sun7i-a20-bananapi-m1-plus.dts new file mode 100644 index 000000000..e62e4afa5 --- /dev/null +++ b/patch/devices/sun7i-a20-bananapi-m1-plus.dts @@ -0,0 +1,294 @@ +/* + * Copyright 2015 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun7i-a20.dtsi" +#include "sunxi-common-regulators.dtsi" +#include +#include + +/ { + model = "Banana Pi BPI-M1-Plus"; + compatible = "sinovoip,bpi-m1-plus", "allwinner,sun7i-a20"; + + aliases { + serial0 = &uart0; + serial1 = &uart2; + serial2 = &uart3; + serial3 = &uart7; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_bananapi>; + + red { + label = "bananapi:red:usr"; + gpios = <&pio 7 25 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "default-on"; + }; + + green { + label = "bananapi:green:usr"; + gpios = <&pio 7 24 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + + }; + }; + + reg_gmac_3v3: gmac-3v3 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac_power_pin_bananapi>; + regulator-name = "gmac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + enable-active-high; + gpio = <&pio 7 23 GPIO_ACTIVE_HIGH>; + }; + + reg_vmmc3: vmmc3 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&vmmc3_pin_bananapi>; + regulator-name = "vmmc3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + enable-active-high; + gpio = <&pio 7 22 GPIO_ACTIVE_HIGH>; + }; +}; + +&ahci { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_rgmii_a>; + phy = <&phy1>; + phy-mode = "rgmii"; + phy-supply = <®_gmac_3v3>; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + + interrupt-controller; + #interrupt-cells = <1>; + }; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; + +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_rx_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_bananapi>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */ + cd-inverted; + status = "okay"; +}; + +&mmc3 { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc3_pins_a>; + vmmc-supply = <®_vmmc3>; + bus-width = <4>; + non-removable; + enable-sdio-wakeup; + status = "okay"; + +/* + brcmf: bcrmf@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; + interrupt-parent = <&pio>; + interrupts = <15 8>; + interrupt-names = "host-wake"; + }; +*/ +}; + +&pio { + gmac_power_pin_bananapi: gmac_power_pin@0 { + allwinner,pins = "PH23"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + led_pins_bananapi: led_pins@0 { + allwinner,pins = "PH24", "PG2"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc0_cd_pin_bananapi: mmc0_cd_pin@0 { + allwinner,pins = "PH10"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb1_vbus_pin_bananapi: usb1_vbus_pin@0 { + allwinner,pins = "PH0"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb2_vbus_pin_bananapi: usb2_vbus_pin@0 { + allwinner,pins = "PH1"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + vmmc3_pin_bananapi: vmmc3_pin@0 { + allwinner,pins = "PH22"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_usb1_vbus { + pinctrl-0 = <&usb1_vbus_pin_bananapi>; + gpio = <&pio 7 0 GPIO_ACTIVE_HIGH>; /* PH0 */ + status = "okay"; +}; + +®_usb2_vbus { + pinctrl-0 = <&usb2_vbus_pin_bananapi>; + gpio = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins_a>, + <&spi0_cs0_pins_a>, + <&spi0_cs1_pins_a>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins_a>; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins_b>; + status = "okay"; +}; + +&uart7 { + pinctrl-names = "default"; + pinctrl-0 = <&uart7_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; diff --git a/patch/devices/sun7i-a20-bananapi-r1.dts b/patch/devices/sun7i-a20-bananapi-r1.dts new file mode 100644 index 000000000..a287819c3 --- /dev/null +++ b/patch/devices/sun7i-a20-bananapi-r1.dts @@ -0,0 +1,229 @@ +/* + * Copyright 2015 Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun7i-a20.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include +#include + +/ { + model = "Banana Pi BPI-R1"; + compatible = "sinovoip,bpi-r1", "allwinner,sun7i-a20"; + + aliases { + serial0 = &uart0; + serial1 = &uart2; + serial2 = &uart3; + serial3 = &uart7; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_bananapi>; + + green { + label = "bananapi:green:usr"; + gpios = <&pio 7 24 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + reg_gmac_3v3: gmac-3v3 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac_power_pin_bananapi>; + regulator-name = "gmac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + enable-active-high; + gpio = <&pio 7 23 GPIO_ACTIVE_HIGH>; + }; +}; + +&ahci { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_rgmii_a>; + phy = <&phy1>; + phy-mode = "rgmii"; + phy-supply = <®_gmac_3v3>; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + + interrupt-controller; + #interrupt-cells = <1>; + }; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; +}; + +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_rx_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_bananapi>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */ + cd-inverted; + status = "okay"; +}; + +&pio { + mmc0_cd_pin_bananapi: mmc0_cd_pin@0 { + allwinner,pins = "PH10"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + gmac_power_pin_bananapi: gmac_power_pin@0 { + allwinner,pins = "PH23"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + led_pins_bananapi: led_pins@0 { + allwinner,pins = "PH24"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_usb1_vbus { + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins_a>, + <&spi0_cs0_pins_a>, + <&spi0_cs1_pins_a>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins_a>; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins_b>; + status = "okay"; +}; + +&uart7 { + pinctrl-names = "default"; + pinctrl-0 = <&uart7_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; diff --git a/patch/devices/sun7i-a20-lamobo-r1.dts b/patch/devices/sun7i-a20-lamobo-r1.dts new file mode 100644 index 000000000..69b11dc6f --- /dev/null +++ b/patch/devices/sun7i-a20-lamobo-r1.dts @@ -0,0 +1,238 @@ +/* + * Copyright 2014 Hans de Goede + * + * Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun7i-a20.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include +#include + +/ { + model = "Lamobo R1"; + compatible = "lamobo,lamobo-r1", "allwinner,sun7i-a20"; + + aliases { + serial0 = &uart0; + serial1 = &uart3; + serial2 = &uart7; + }; + + soc@01c00000 { + spi0: spi@01c05000 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins_a>; + status = "okay"; + }; + + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_bananapi>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 10 0>; /* PH10 */ + cd-inverted; + status = "okay"; + }; + + usbphy: phy@01c13400 { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; + }; + + ehci0: usb@01c14000 { + status = "okay"; + }; + + ohci0: usb@01c14400 { + status = "okay"; + }; + + ahci: sata@01c18000 { + status = "okay"; + }; + + ehci1: usb@01c1c000 { + status = "okay"; + }; + + ohci1: usb@01c1c400 { + status = "okay"; + }; + + pinctrl@01c20800 { + mmc0_cd_pin_bananapi: mmc0_cd_pin@0 { + allwinner,pins = "PH10"; + allwinner,function = "gpio_in"; + allwinner,drive = <0>; + allwinner,pull = <1>; + }; + + gmac_power_pin_bananapi: gmac_power_pin@0 { + allwinner,pins = "PH23"; + allwinner,function = "gpio_out"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; + + led_pins_bananapi: led_pins@0 { + allwinner,pins = "PH24"; + allwinner,function = "gpio_out"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; + + ahci_pwr_pin_a: ahci_pwr_pin@0 { + allwinner,pins = "PB3"; + allwinner,function = "gpio_out"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; + + }; + + uart0: serial@01c28000 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; + }; + + uart3: serial@01c28c00 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins_b>; + status = "okay"; + }; + + uart7: serial@01c29c00 { + pinctrl-names = "default"; + pinctrl-0 = <&uart7_pins_a>; + status = "okay"; + }; + + i2c0: i2c@01c2ac00 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 8>; + + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + i2c2: i2c@01c2b400 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; + }; + + gmac: ethernet@01c50000 { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_rgmii_a>; + phy = <&phy1>; + phy-mode = "rgmii"; + phy-supply = <®_gmac_3v3>; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_bananapi>; + + green { + label = "bananapi:green:usr"; + gpios = <&pio 7 24 0>; + }; + }; + + reg_usb1_vbus: usb1-vbus { + status = "okay"; + }; + + reg_usb2_vbus: usb2-vbus { + status = "okay"; + }; + + reg_gmac_3v3: gmac-3v3 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac_power_pin_bananapi>; + regulator-name = "gmac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + enable-active-high; + gpio = <&pio 7 23 0>; + }; + + reg_ahci_5v: ahci-5v { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&ahci_pwr_pin_a>; + regulator-name = "ahci-5v"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&pio 1 3 0>; + status = "okay"; + }; +}; diff --git a/patch/devices/sun7i-a20-orangepi-mini.dts b/patch/devices/sun7i-a20-orangepi-mini.dts new file mode 100644 index 000000000..ea07bc84f --- /dev/null +++ b/patch/devices/sun7i-a20-orangepi-mini.dts @@ -0,0 +1,244 @@ +/* + * Copyright 2015 Hans de Goede + * + * Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun7i-a20.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include +#include + +/ { + model = "Orange Pi Mini"; + compatible = "xunlong,orangepi-mini", "allwinner,sun7i-a20"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_orangepi>; + + green { + label = "orangepi:green:usr"; + gpios = <&pio 7 24 GPIO_ACTIVE_HIGH>; /* PH24 */ + }; + + blue { + label = "orangepi:blue:usr"; + gpios = <&pio 7 25 GPIO_ACTIVE_HIGH>; /* PH25 */ + }; + }; + + reg_gmac_3v3: gmac-3v3 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac_power_pin_orangepi>; + regulator-name = "gmac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + enable-active-high; + gpio = <&pio 7 23 GPIO_ACTIVE_HIGH>; /* PH23 */ + }; +}; + +&ahci { + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_rgmii_a>; + phy = <&phy1>; + phy-mode = "rgmii"; + phy-supply = <®_gmac_3v3>; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +#include "axp209.dtsi" + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_orangepi>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */ + cd-inverted; + status = "okay"; +}; + +&mmc3 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc3_pins_a>, <&mmc3_cd_pin_orangepi>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */ + cd-inverted; + status = "okay"; +}; + +&pio { + mmc0_cd_pin_orangepi: mmc0_cd_pin@0 { + allwinner,pins = "PH10"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc3_cd_pin_orangepi: mmc3_cd_pin@0 { + allwinner,pins = "PH11"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb2_vbus_pin_bananapro: usb2_vbus_pin@0 { + allwinner,pins = "PH22"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + gmac_power_pin_orangepi: gmac_power_pin@0 { + allwinner,pins = "PH23"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + led_pins_orangepi: led_pins@0 { + allwinner,pins = "PH24", "PH25"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb1_vbus_pin_bananapro: usb1_vbus_pin@0 { + allwinner,pins = "PH26"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_dcdc2 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1500000>; + regulator-name = "vdd-cpu"; +}; + +®_dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1400000>; + regulator-name = "vdd-int-pll"; +}; + +®_ldo1 { + regulator-name = "vdd-rtc"; +}; + +®_ldo2 { + regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-name = "avcc"; +}; + +®_usb1_vbus { + pinctrl-0 = <&usb1_vbus_pin_bananapro>; + gpio = <&pio 7 26 GPIO_ACTIVE_HIGH>; /* PH26 */ + status = "okay"; +}; + +®_usb2_vbus { + pinctrl-0 = <&usb2_vbus_pin_bananapro>; + gpio = <&pio 7 22 GPIO_ACTIVE_HIGH>; /* PH22 */ + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; diff --git a/patch/devices/sun7i-a20-orangepi.dts b/patch/devices/sun7i-a20-orangepi.dts new file mode 100644 index 000000000..c40568a25 --- /dev/null +++ b/patch/devices/sun7i-a20-orangepi.dts @@ -0,0 +1,225 @@ +/* + * Copyright 2014 Hans de Goede + * + * Hans de Goede + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun7i-a20.dtsi" +#include "sunxi-common-regulators.dtsi" + +#include +#include +#include + +/ { + model = "Orange PI"; + compatible = "lemaker,bananapi", "allwinner,sun7i-a20"; + + aliases { + serial0 = &uart0; + serial1 = &uart3; + serial2 = &uart7; + }; + + soc@01c00000 { + spi0: spi@01c05000 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins_a>; + status = "okay"; + }; + + mmc0: mmc@01c0f000 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_bananapi>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 10 0>; /* PH10 */ + cd-inverted; + status = "okay"; + }; + + usbphy: phy@01c13400 { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; + }; + + ehci0: usb@01c14000 { + status = "okay"; + }; + + ohci0: usb@01c14400 { + status = "okay"; + }; + + ahci: sata@01c18000 { + status = "okay"; + }; + + ehci1: usb@01c1c000 { + status = "okay"; + }; + + ohci1: usb@01c1c400 { + status = "okay"; + }; + + pinctrl@01c20800 { + mmc0_cd_pin_bananapi: mmc0_cd_pin@0 { + allwinner,pins = "PH10"; + allwinner,function = "gpio_in"; + allwinner,drive = <0>; + allwinner,pull = <1>; + }; + + gmac_power_pin_bananapi: gmac_power_pin@0 { + allwinner,pins = "PH23"; + allwinner,function = "gpio_out"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; + + led_pins_bananapi: led_pins@0 { + allwinner,pins = "PH24"; + allwinner,function = "gpio_out"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; + + }; + + ir0: ir@01c21800 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; + }; + + uart0: serial@01c28000 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; + }; + + uart3: serial@01c28c00 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins_b>; + status = "okay"; + }; + + uart7: serial@01c29c00 { + pinctrl-names = "default"; + pinctrl-0 = <&uart7_pins_a>; + status = "okay"; + }; + + i2c0: i2c@01c2ac00 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 8>; + + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + + i2c2: i2c@01c2b400 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + status = "okay"; + }; + + gmac: ethernet@01c50000 { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_rgmii_a>; + phy = <&phy1>; + phy-mode = "rgmii"; + phy-supply = <®_gmac_3v3>; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_bananapi>; + + green { + label = "bananapi:green:usr"; + gpios = <&pio 7 24 0>; + }; + }; + + reg_usb1_vbus: usb1-vbus { + status = "okay"; + }; + + reg_usb2_vbus: usb2-vbus { + status = "okay"; + }; + + reg_gmac_3v3: gmac-3v3 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&gmac_power_pin_bananapi>; + regulator-name = "gmac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + enable-active-high; + gpio = <&pio 7 22 23 0>; + }; +}; diff --git a/patch/devices/sun7i-a20-pcduino3-nano.dts b/patch/devices/sun7i-a20-pcduino3-nano.dts new file mode 100644 index 000000000..fe2aadbed --- /dev/null +++ b/patch/devices/sun7i-a20-pcduino3-nano.dts @@ -0,0 +1,191 @@ +/* + * Copyright 2015 Adam Sampson + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "sun7i-a20.dtsi" +#include "sunxi-common-regulators.dtsi" +#include +#include + +/ { + model = "LinkSprite pcDuino3 Nano"; + compatible = "linksprite,pcduino3-nano", "allwinner,sun7i-a20"; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins_pcduino3_nano>; + + /* Marked "LED3" on the PCB. */ + usr1 { + label = "pcduino3-nano:green:usr1"; + gpios = <&pio 7 16 GPIO_ACTIVE_LOW>; /* PH16 */ + }; + + /* Marked "LED4" on the PCB. */ + usr2 { + label = "pcduino3-nano:green:usr2"; + gpios = <&pio 7 15 GPIO_ACTIVE_LOW>; /* PH15 */ + }; + }; +}; + +&ahci { + target-supply = <®_ahci_5v>; + status = "okay"; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&gmac_pins_rgmii_a>; + phy = <&phy1>; + phy-mode = "rgmii"; + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_a>; + status = "okay"; + + axp209: pmic@34 { + compatible = "x-powers,axp209"; + reg = <0x34>; + interrupt-parent = <&nmi_intc>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + + interrupt-controller; + #interrupt-cells = <1>; + }; +}; + +&ir0 { + pinctrl-names = "default"; + pinctrl-0 = <&ir0_pins_a>; + status = "okay"; +}; + +&mmc0 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; + vmmc-supply = <®_vcc3v3>; + bus-width = <4>; + cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ + cd-inverted; + status = "okay"; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&pio { + ahci_pwr_pin_pcduino3_nano: ahci_pwr_pin@0 { + allwinner,pins = "PH2"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + led_pins_pcduino3_nano: led_pins@0 { + allwinner,pins = "PH16", "PH15"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; + + usb1_vbus_pin_pcduino3_nano: usb1_vbus_pin@0 { + allwinner,pins = "PH11"; + allwinner,function = "gpio_out"; + allwinner,drive = ; + allwinner,pull = ; + }; +}; + +®_ahci_5v { + pinctrl-0 = <&ahci_pwr_pin_pcduino3_nano>; + gpio = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */ + status = "okay"; +}; + +®_usb1_vbus { + pinctrl-0 = <&usb1_vbus_pin_pcduino3_nano>; + gpio = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */ + status = "okay"; +}; + +®_usb2_vbus { + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins_a>; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + status = "okay"; +}; diff --git a/patch/kernel/0001-ARM-sun5i-dt-Add-Security-System-to-A10s-SoC-DTS.patch b/patch/kernel/0001-ARM-sun5i-dt-Add-Security-System-to-A10s-SoC-DTS.patch new file mode 100644 index 000000000..d26722294 --- /dev/null +++ b/patch/kernel/0001-ARM-sun5i-dt-Add-Security-System-to-A10s-SoC-DTS.patch @@ -0,0 +1,38 @@ +From 15eb60db598930b0a653d056c13bffb614ab2db7 Mon Sep 17 00:00:00 2001 +From: LABBE Corentin +Date: Wed, 22 Apr 2015 14:33:29 +0200 +Subject: [PATCH 1/8] ARM: sun5i: dt: Add Security System to A10s SoC DTS + +The Security System is a hardware cryptographic accelerator that support +AES/MD5/SHA1/DES/3DES/PRNG algorithms. +It could be found on many Allwinner SoC. + +This patch enable the Security System on Allwinner A10s SoC Device-tree. + +Signed-off-by: LABBE Corentin +--- + arch/arm/boot/dts/sun5i-a10s.dtsi | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi +index 2fd8988..dbe8704 100644 +--- a/arch/arm/boot/dts/sun5i-a10s.dtsi ++++ b/arch/arm/boot/dts/sun5i-a10s.dtsi +@@ -448,6 +448,14 @@ + status = "disabled"; + }; + ++ crypto: crypto-engine@01c15000 { ++ compatible = "allwinner,sun4i-a10-crypto"; ++ reg = <0x01c15000 0x1000>; ++ interrupts = <86>; ++ clocks = <&ahb_gates 5>, <&ss_clk>; ++ clock-names = "ahb", "mod"; ++ }; ++ + spi2: spi@01c17000 { + compatible = "allwinner,sun4i-a10-spi"; + reg = <0x01c17000 0x1000>; +-- +2.3.6 + diff --git a/patch/kernel/0001-I2S-module-rework.patch b/patch/kernel/0001-I2S-module-rework.patch new file mode 100644 index 000000000..4109b1ea0 --- /dev/null +++ b/patch/kernel/0001-I2S-module-rework.patch @@ -0,0 +1,1143 @@ +From 9aec2b8e002ec3fd7664ec0c6b9ec608067bdde8 Mon Sep 17 00:00:00 2001 +From: nikkov +Date: Wed, 19 Mar 2014 17:17:53 +0700 +Subject: [PATCH] I2S module rework + +--- + sound/soc/Kconfig | 2 +- + sound/soc/sunxi/i2s/Kconfig | 2 +- + sound/soc/sunxi/i2s/sndi2s.c | 68 ++++++++-- + sound/soc/sunxi/i2s/sndi2s.h | 3 + + sound/soc/sunxi/i2s/sunxi-i2s.c | 279 ++++++++++++++++++++++++++++-------- + sound/soc/sunxi/i2s/sunxi-i2s.h | 9 +- + sound/soc/sunxi/i2s/sunxi-i2sdma.c | 36 +++++- + sound/soc/sunxi/i2s/sunxi-i2sdma.h | 4 +- + sound/soc/sunxi/i2s/sunxi-sndi2s.c | 135 ++++++++++++++++-- + sound/soc/sunxi/i2s/sunxi-sndi2s.h | 3 +- + 10 files changed, 446 insertions(+), 95 deletions(-) + +diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig +index adafead..2334cab 100644 +--- a/sound/soc/Kconfig ++++ b/sound/soc/Kconfig +@@ -60,7 +60,7 @@ source "sound/soc/sunxi/Kconfig" + source "sound/soc/sunxi/hdmiaudio/Kconfig" + source "sound/soc/sunxi/spdif/Kconfig" + # i2s needs various adjustments for sun7i +-if ARCH_SUN4I || ARCH_SUN5I ++if ARCH_SUN4I || ARCH_SUN5I || ARCH_SUN7I + source "sound/soc/sunxi/i2s/Kconfig" + endif + endif +diff --git a/sound/soc/sunxi/i2s/Kconfig b/sound/soc/sunxi/i2s/Kconfig +index a6dff42..f244faa 100644 +--- a/sound/soc/sunxi/i2s/Kconfig ++++ b/sound/soc/sunxi/i2s/Kconfig +@@ -1,5 +1,5 @@ + config SND_SUNXI_SOC_I2S_INTERFACE +- tristate "SoC i2s interface for the AllWinner sun4i and sun5i chips" ++ tristate "SoC i2s interface for the AllWinner sun4i, sun5i and sun7i chips" + default m + help + Say Y or M if you want to add support for codecs attached to +diff --git a/sound/soc/sunxi/i2s/sndi2s.c b/sound/soc/sunxi/i2s/sndi2s.c +index 68bad02..f07129e 100644 +--- a/sound/soc/sunxi/i2s/sndi2s.c ++++ b/sound/soc/sunxi/i2s/sndi2s.c +@@ -35,11 +35,23 @@ struct sndi2s_priv { + }; + + static int i2s_used = 0; +-#define sndi2s_RATES (SNDRV_PCM_RATE_8000_192000|SNDRV_PCM_RATE_KNOT) ++static int sunxi_i2s_slave = 0; ++ ++#define sndi2s_RATES_MASTER (SNDRV_PCM_RATE_8000_192000|SNDRV_PCM_RATE_KNOT) ++#define sndi2s_RATES_SLAVE (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ ++ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\ ++ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) ++ ++#if defined CONFIG_ARCH_SUN7I ++#define sndi2s_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) ++#else + #define sndi2s_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \ +- SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE) ++ SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_LE) ++#endif + ++/* cleaning code + hdmi_audio_t hdmi_parameter; ++*/ + + static int sndi2s_mute(struct snd_soc_dai *dai, int mute) + { +@@ -62,8 +74,26 @@ static int sndi2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) + { ++/* ++ switch (params_format(params)) ++ { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ printk("[IIS-0] sndi2s_hw_params: format 16 bit\n"); ++ break; ++ case SNDRV_PCM_FORMAT_S20_3LE: ++ printk("[IIS-0] sndi2s_hw_params: format 20 bit in 3 bytes\n"); ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ printk("[IIS-0] sndi2s_hw_params: format 24 bit in 4 bytes\n"); ++ break; ++ default: ++ printk("[IIS-0] sndi2s_hw_params: Unsupported format (%d)\n", (int)params_format(params)); ++ //return -EINVAL; ++ } ++*/ ++/* cleaning code + hdmi_parameter.sample_rate = params_rate(params); +- ++*/ + return 0; + } + +@@ -75,15 +105,18 @@ static int sndi2s_set_dai_sysclk(struct snd_soc_dai *codec_dai, + + static int sndi2s_set_dai_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div) + { +- ++/* cleaning code + hdmi_parameter.fs_between = div; +- ++*/ + return 0; + } + + static int sndi2s_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) + { ++/* ++ printk("[IIS-0] sndi2s_set_dai_fmt: format (%u)\n", fmt); ++*/ + return 0; + } + +@@ -104,7 +137,7 @@ struct snd_soc_dai_driver sndi2s_dai = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, +- .rates = sndi2s_RATES, ++ .rates = sndi2s_RATES_MASTER, + .formats = sndi2s_FORMATS, + }, + /* pcm operations */ +@@ -129,10 +162,8 @@ static int sndi2s_soc_probe(struct snd_soc_codec *codec) + /* power down chip */ + static int sndi2s_soc_remove(struct snd_soc_codec *codec) + { +- struct sndhdmi_priv *sndi2s = snd_soc_codec_get_drvdata(codec); +- ++ struct sndi2s_priv *sndi2s = snd_soc_codec_get_drvdata(codec); + kfree(sndi2s); +- + return 0; + } + +@@ -143,6 +174,12 @@ static struct snd_soc_codec_driver soc_codec_dev_sndi2s = { + + static int __devinit sndi2s_codec_probe(struct platform_device *pdev) + { ++ if(sunxi_i2s_slave) { ++ sndi2s_dai.playback.rates = sndi2s_RATES_SLAVE; ++ printk("[I2S-0] sndi2s_codec_probe I2S used in slave mode\n"); ++ } ++ else ++ printk("[I2S-0] sndi2s_codec_probe I2S used in master mode\n"); + return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_sndi2s, &sndi2s_dai, 1); + } + +@@ -169,7 +206,7 @@ static struct platform_driver sndi2s_codec_driver = { + static int __init sndi2s_codec_init(void) + { + int err = 0; +- int ret = 0; ++ int ret = 0, i2s_slave = 0; + + ret = script_parser_fetch("i2s_para","i2s_used", &i2s_used, sizeof(int)); + if (ret) { +@@ -177,6 +214,16 @@ static int __init sndi2s_codec_init(void) + } + + if (i2s_used) { ++ ret = script_parser_fetch("i2s_para","i2s_slave", &i2s_slave, sizeof(int)); ++ if(ret == 0 && i2s_slave == 1) { ++ sunxi_i2s_slave = 1; ++ printk("[I2S-0] sndi2s_codec_init I2S used in slave mode\n"); ++ } ++ else { ++ sunxi_i2s_slave = 0; ++ printk("[I2S-0] sndi2s_codec_init I2S used in master mode\n"); ++ } ++ + if((err = platform_device_register(&sndi2s_codec_device)) < 0) + return err; + +@@ -204,3 +251,4 @@ MODULE_DESCRIPTION("SNDI2S ALSA soc codec driver"); + MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin "); + MODULE_LICENSE("GPL"); + MODULE_ALIAS("platform:sunxi-i2s-codec"); ++ +diff --git a/sound/soc/sunxi/i2s/sndi2s.h b/sound/soc/sunxi/i2s/sndi2s.h +index e5b95c8..57e2aa5 100644 +--- a/sound/soc/sunxi/i2s/sndi2s.h ++++ b/sound/soc/sunxi/i2s/sndi2s.h +@@ -16,6 +16,8 @@ + #ifndef SNDI2S_H_ + #define SNDI2S_H_ + ++#if 0 ++cleaning code + typedef struct hdmi_audio + { + __u8 hw_intf; /* 0:iis 1:spdif 2:pcm */ +@@ -54,5 +56,6 @@ typedef enum tag_HDMI_CMD + HDMI_CMD_AUDIO_ENABLE, + HDMI_CMD_GET_HPD_STATUS, + }__hdmi_cmd_t; ++#endif + + #endif +diff --git a/sound/soc/sunxi/i2s/sunxi-i2s.c b/sound/soc/sunxi/i2s/sunxi-i2s.c +index b4dd3ad..9f19991 100644 +--- a/sound/soc/sunxi/i2s/sunxi-i2s.c ++++ b/sound/soc/sunxi/i2s/sunxi-i2s.c +@@ -58,13 +58,15 @@ static struct sunxi_dma_params sunxi_i2s_pcm_stereo_in = { + }; + + +- struct sunxi_i2s_info sunxi_iis; ++/* most of fields of this structure is never initialized and useless !!!*/ ++struct sunxi_i2s_info sunxi_iis; + static u32 i2s_handle = 0; +- static struct clk *i2s_apbclk, *i2s_pll2clk, *i2s_pllx8, *i2s_moduleclk; ++static struct clk *i2s_apbclk, *i2s_pll2clk, *i2s_pllx8, *i2s_moduleclk; + + void sunxi_snd_txctrl_i2s(struct snd_pcm_substream *substream, int on) + { + u32 reg_val; ++ /*printk("[I2S-0] sunxi_snd_txctrl_i2s\n");*/ + + reg_val = readl(sunxi_iis.regs + SUNXI_TXCHSEL); + reg_val &= ~0x7; +@@ -73,7 +75,7 @@ void sunxi_snd_txctrl_i2s(struct snd_pcm_substream *substream, int on) + + reg_val = readl(sunxi_iis.regs + SUNXI_TXCHMAP); + reg_val = 0; +- if (sunxi_is_sun4i()) { ++ if (sunxi_is_sun4i() || sunxi_is_sun7i()) { + if(substream->runtime->channels == 1) { + reg_val = 0x76543200; + } else { +@@ -89,7 +91,7 @@ void sunxi_snd_txctrl_i2s(struct snd_pcm_substream *substream, int on) + writel(reg_val, sunxi_iis.regs + SUNXI_TXCHMAP); + + reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); +- if (sunxi_is_sun4i()) { ++ if (sunxi_is_sun4i() || sunxi_is_sun7i()) { + reg_val &= ~SUNXI_IISCTL_SDO3EN; + reg_val &= ~SUNXI_IISCTL_SDO2EN; + reg_val &= ~SUNXI_IISCTL_SDO1EN; +@@ -146,6 +148,8 @@ void sunxi_snd_txctrl_i2s(struct snd_pcm_substream *substream, int on) + + //Global Enable Digital Audio Interface + reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); ++ if(sunxi_iis.slave) ++ reg_val |= SUNXI_IISCTL_MS; // 1: Slave! + reg_val |= SUNXI_IISCTL_GEN; + writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); + +@@ -170,7 +174,7 @@ void sunxi_snd_txctrl_i2s(struct snd_pcm_substream *substream, int on) + void sunxi_snd_rxctrl_i2s(int on) + { + u32 reg_val; +- ++ /*printk("[I2S-0] sunxi_snd_rxctrl_i2s\n");*/ + //flush RX FIFO + reg_val = readl(sunxi_iis.regs + SUNXI_IISFCTL); + reg_val |= SUNXI_IISFCTL_FRX; +@@ -192,6 +196,8 @@ void sunxi_snd_rxctrl_i2s(int on) + + //Global Enable Digital Audio Interface + reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); ++ if(sunxi_iis.slave) ++ reg_val |= SUNXI_IISCTL_MS; // 1: Slave! + reg_val |= SUNXI_IISCTL_GEN; + writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); + +@@ -201,7 +207,7 @@ void sunxi_snd_rxctrl_i2s(int on) + reg_val &= ~SUNXI_IISCTL_RXEN; + writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); + +- /* DISBALE dma DRQ mode */ ++ /* DISABLE dma DRQ mode */ + reg_val = readl(sunxi_iis.regs + SUNXI_IISINT); + reg_val &= ~SUNXI_IISINT_RXDRQEN; + writel(reg_val, sunxi_iis.regs + SUNXI_IISINT); +@@ -213,11 +219,13 @@ void sunxi_snd_rxctrl_i2s(int on) + } + } + ++//not used ++/* + static inline int sunxi_snd_is_clkmaster(void) + { + return ((readl(sunxi_iis.regs + SUNXI_IISCTL) & SUNXI_IISCTL_MS) ? 0 : 1); + } +- ++*/ + static int sunxi_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) + { + u32 reg_val; +@@ -225,7 +233,7 @@ static int sunxi_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) + + //SDO ON + reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); +- if (sunxi_is_sun4i()) { ++ if (sunxi_is_sun4i() || sunxi_is_sun7i()) { + reg_val |= (SUNXI_IISCTL_SDO0EN | SUNXI_IISCTL_SDO1EN | + SUNXI_IISCTL_SDO2EN | SUNXI_IISCTL_SDO3EN); + } else { +@@ -235,16 +243,31 @@ static int sunxi_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) + + /* master or slave selection */ + reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); ++ if(sunxi_iis.slave) ++ { ++ reg_val |= SUNXI_IISCTL_MS; // 1: Slave! ++ /*printk("[IIS-0] sunxi_i2s_set_fmt: set slave mode for I2S interface\n");*/ ++ } ++ else ++ { ++ reg_val &= ~SUNXI_IISCTL_MS; // 0: Master! ++ /*printk("[IIS-0] sunxi_i2s_set_fmt: set master mode for I2S interface\n");*/ ++ } ++/* + switch(fmt & SND_SOC_DAIFMT_MASTER_MASK){ +- case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */ +- reg_val |= SUNXI_IISCTL_MS; ++ case SND_SOC_DAIFMT_CBS_CFS: // codec clk & frm slave ++ reg_val |= SUNXI_IISCTL_MS; // 1: Slave! ++ printk("[IIS-0] sunxi_i2s_set_fmt: set slave mode for I2S interface\n"); + break; +- case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */ +- reg_val &= ~SUNXI_IISCTL_MS; ++ case SND_SOC_DAIFMT_CBM_CFM: // codec clk & frm master ++ reg_val &= ~SUNXI_IISCTL_MS; // 0: Master! ++ printk("[IIS-0] sunxi_i2s_set_fmt: set master mode for I2S interface\n"); + break; + default: ++ printk("[IIS-0] sunxi_i2s_set_fmt: not master or slave mode\n"); + return -EINVAL; + } ++*/ + writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); + + /* pcm or i2s mode selection */ +@@ -255,24 +278,30 @@ static int sunxi_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) + case SND_SOC_DAIFMT_I2S: /* I2S mode */ + reg_val &= ~SUNXI_IISCTL_PCM; + reg_val1 |= SUNXI_IISFAT0_FMT_I2S; ++ /*printk("[IIS-0] sunxi_i2s_set_fmt: set I2S mode\n");*/ + break; + case SND_SOC_DAIFMT_RIGHT_J: /* Right Justified mode */ + reg_val &= ~SUNXI_IISCTL_PCM; + reg_val1 |= SUNXI_IISFAT0_FMT_RGT; ++ /*printk("[IIS-0] sunxi_i2s_set_fmt: set Right Justified mode\n");*/ + break; + case SND_SOC_DAIFMT_LEFT_J: /* Left Justified mode */ + reg_val &= ~SUNXI_IISCTL_PCM; + reg_val1 |= SUNXI_IISFAT0_FMT_LFT; ++ /*printk("[IIS-0] sunxi_i2s_set_fmt: set Left Justified mode\n");*/ + break; + case SND_SOC_DAIFMT_DSP_A: /* L data msb after FRM LRC */ + reg_val |= SUNXI_IISCTL_PCM; + reg_val1 &= ~SUNXI_IISFAT0_LRCP; ++ /*printk("[IIS-0] sunxi_i2s_set_fmt: set L data msb after FRM LRC mode\n");*/ + break; + case SND_SOC_DAIFMT_DSP_B: /* L data msb during FRM LRC */ + reg_val |= SUNXI_IISCTL_PCM; + reg_val1 |= SUNXI_IISFAT0_LRCP; ++ /*printk("[IIS-0] sunxi_i2s_set_fmt: set L data msb during FRM LRC mode\n");*/ + break; + default: ++ printk("[IIS-0] sunxi_i2s_set_fmt: unknown mode\n"); + return -EINVAL; + } + writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); +@@ -284,25 +313,30 @@ static int sunxi_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) + case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */ + reg_val1 &= ~SUNXI_IISFAT0_LRCP; + reg_val1 &= ~SUNXI_IISFAT0_BCP; ++ /*printk("[IIS-0] sunxi_i2s_set_fmt: normal bit clock + frame\n");*/ + break; + case SND_SOC_DAIFMT_NB_IF: /* normal bclk + inv frm */ + reg_val1 |= SUNXI_IISFAT0_LRCP; + reg_val1 &= ~SUNXI_IISFAT0_BCP; ++ /*printk("[IIS-0] sunxi_i2s_set_fmt: normal bclk + inv frm\n");*/ + break; + case SND_SOC_DAIFMT_IB_NF: /* invert bclk + nor frm */ + reg_val1 &= ~SUNXI_IISFAT0_LRCP; + reg_val1 |= SUNXI_IISFAT0_BCP; ++ /*printk("[IIS-0] sunxi_i2s_set_fmt: invert bclk + nor frm\n");*/ + break; + case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */ + reg_val1 |= SUNXI_IISFAT0_LRCP; + reg_val1 |= SUNXI_IISFAT0_BCP; ++ /*printk("[IIS-0] sunxi_i2s_set_fmt: invert bclk + frm\n");*/ + break; + } + writel(reg_val1, sunxi_iis.regs + SUNXI_IISFAT0); + +- /* word select size */ ++ /* clear word select size */ + reg_val = readl(sunxi_iis.regs + SUNXI_IISFAT0); + reg_val &= ~SUNXI_IISFAT0_WSS_32BCLK; ++ /*printk("[IIS-0] sunxi_i2s_set_fmt: word size = %d\n", sunxi_iis.ws_size);*/ + if(sunxi_iis.ws_size == 16) + reg_val |= SUNXI_IISFAT0_WSS_16BCLK; + else if(sunxi_iis.ws_size == 20) +@@ -318,9 +352,15 @@ static int sunxi_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) + reg_val |= sunxi_iis.pcm_rxtype<<2; + + if(!sunxi_iis.pcm_sync_type) ++ { + reg_val |= SUNXI_IISFAT1_SSYNC; //short sync ++ /*printk("[IIS-0] sunxi_i2s_set_fmt: set pcm_sync_type = short sync\n");*/ ++ } + if(sunxi_iis.pcm_sw == 16) ++ { + reg_val |= SUNXI_IISFAT1_SW; ++ /*printk("[IIS-0] sunxi_i2s_set_fmt: pcm_sw == 16\n");*/ ++ } + + reg_val |=((sunxi_iis.pcm_start_slot - 1)&0x3)<<6; //start slot index + +@@ -349,6 +389,7 @@ static int sunxi_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) + { ++ u32 reg_val; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct sunxi_dma_params *dma_data; + +@@ -358,6 +399,31 @@ static int sunxi_i2s_hw_params(struct snd_pcm_substream *substream, + else + dma_data = &sunxi_i2s_pcm_stereo_in; + ++ /* set format info */ ++ reg_val = readl(sunxi_iis.regs + SUNXI_IISFAT0); ++ /* clear sample resolution select size */ ++ reg_val &= ~SUNXI_IISFAT0_SR_RVD; ++ ++ switch (params_format(params)) ++ { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ reg_val |= SUNXI_IISFAT0_SR_16BIT; ++ /*printk("[IIS-0] sunxi_i2s_hw_params: format 16 bit\n");*/ ++ break; ++ case SNDRV_PCM_FORMAT_S20_3LE: ++ reg_val |= SUNXI_IISFAT0_SR_20BIT; ++ /*printk("[IIS-0] sunxi_i2s_hw_params: format 20 bit\n");*/ ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ reg_val |= SUNXI_IISFAT0_SR_24BIT; ++ /*printk("[IIS-0] sunxi_i2s_hw_params: format 24 bit\n");*/ ++ break; ++ default: ++ printk("[IIS-0] sunxi_i2s_hw_params: Unsupported format (%d)\n", (int)params_format(params)); ++ //return -EINVAL; ++ } ++ writel(reg_val, sunxi_iis.regs + SUNXI_IISFAT0); ++ + snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); + return 0; + } +@@ -403,9 +469,17 @@ static int sunxi_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, + unsigned int freq, int dir) + { + if (!freq) { +- clk_set_rate(i2s_pll2clk, 24576000); ++ /*printk("[IIS-0] sunxi_i2s_set_sysclk: set sysclk=24576000\n");*/ ++ if(sunxi_iis.slave) ++ gpio_write_one_pin_value(i2s_handle, 0, "i2s_clk_sel"); ++ else ++ clk_set_rate(i2s_pll2clk, 24576000); + } else { +- clk_set_rate(i2s_pll2clk, 22579200); ++ /*printk("[IIS-0] sunxi_i2s_set_sysclk: set sysclk=22579200\n");*/ ++ if(sunxi_iis.slave) ++ gpio_write_one_pin_value(i2s_handle, 1, "i2s_clk_sel"); ++ else ++ clk_set_rate(i2s_pll2clk, 22579200); + } + + return 0; +@@ -414,6 +488,27 @@ static int sunxi_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, + static int sunxi_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div) + { + u32 reg; ++ /*printk("[IIS-0] sunxi_i2s_set_clkdiv: PLL clock div_id=(%s), div=(%d)\n", ++ div_id == SUNXI_DIV_MCLK ? "SUNXI_DIV_MCLK" : ++ (div_id == SUNXI_DIV_BCLK ? "SUNXI_DIV_BCLK" : "SUNXI_DIV_EXTCLK"), div);*/ ++ ++ ++ if(sunxi_iis.slave) { ++ if(div_id != SUNXI_DIV_EXTCLK) { ++ pr_err("[I2S-0] try to set external clock divider failed\n"); ++ return -EINVAL; ++ } ++ /*printk("[IIS-0] sunxi_i2s_set_clkdiv: external clock, div=(%d)\n", div);*/ ++ } ++ else { ++ if(div_id != SUNXI_DIV_MCLK && div_id != SUNXI_DIV_BCLK) { ++ pr_err("[I2S-0] try to set PLL clock divider failed\n"); ++ return -EINVAL; ++ } ++ /*printk("[IIS-0] sunxi_i2s_set_clkdiv: PLL clock div_id=(%s), div=(%d)\n", ++ div_id == SUNXI_DIV_MCLK ? "SUNXI_DIV_MCLK" : "SUNXI_DIV_BCLK", div);*/ ++ } ++ + switch (div_id) { + case SUNXI_DIV_MCLK: + if(div <= 8) +@@ -447,18 +542,39 @@ static int sunxi_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div + reg = (readl(sunxi_iis.regs + SUNXI_IISCLKD) & ~SUNXI_IISCLKD_BCLK_MASK) | (div <params == NULL) { + prtd->params = dma; + ret = sunxi_dma_request(prtd->params, 0); +@@ -196,10 +214,22 @@ static int sunxi_pcm_prepare(struct snd_pcm_substream *substream) + #else + dma_config_t codec_dma_conf; + memset(&codec_dma_conf, 0, sizeof(codec_dma_conf)); +- codec_dma_conf.xfer_type.src_data_width = DATA_WIDTH_16BIT; ++ ++ /*printk("[IIS-0] sunxi_pcm_prepare: DMA data width=(%d)\n", dma_width);*/ ++ if(dma_width > 16) ++ { ++ codec_dma_conf.xfer_type.src_data_width = DATA_WIDTH_32BIT; ++ codec_dma_conf.xfer_type.dst_data_width = DATA_WIDTH_32BIT; ++ } ++ else ++ { ++ codec_dma_conf.xfer_type.src_data_width = DATA_WIDTH_16BIT; ++ codec_dma_conf.xfer_type.dst_data_width = DATA_WIDTH_16BIT; ++ } + codec_dma_conf.xfer_type.src_bst_len = DATA_BRST_1; +- codec_dma_conf.xfer_type.dst_data_width = DATA_WIDTH_16BIT; ++// codec_dma_conf.xfer_type.src_bst_len = DATA_BRST_4; /*like SPDIF module?*/ + codec_dma_conf.xfer_type.dst_bst_len = DATA_BRST_1; ++// codec_dma_conf.xfer_type.src_bst_len = DATA_BRST_4; /*like SPDIF module?*/ + codec_dma_conf.address_type.src_addr_mode = NDMA_ADDR_INCREMENT; + codec_dma_conf.address_type.dst_addr_mode = NDMA_ADDR_NOCHANGE; + codec_dma_conf.src_drq_type = N_SRC_SDRAM; +diff --git a/sound/soc/sunxi/i2s/sunxi-i2sdma.h b/sound/soc/sunxi/i2s/sunxi-i2sdma.h +index 50418a58..8f0b029 100644 +--- a/sound/soc/sunxi/i2s/sunxi-i2sdma.h ++++ b/sound/soc/sunxi/i2s/sunxi-i2sdma.h +@@ -29,7 +29,7 @@ enum sunxi_dma_buffresult { + }; + + /* platform data */ +-extern struct snd_soc_platform sunxi_soc_platform_i2s; +-extern struct sunxi_i2s_info sunxi_iis; ++//extern struct snd_soc_platform sunxi_soc_platform_i2s; ++//extern struct sunxi_i2s_info sunxi_iis; + + #endif //SUNXI_PCM_H_ +diff --git a/sound/soc/sunxi/i2s/sunxi-sndi2s.c b/sound/soc/sunxi/i2s/sunxi-sndi2s.c +index 7c1a3d4..682c553 100644 +--- a/sound/soc/sunxi/i2s/sunxi-sndi2s.c ++++ b/sound/soc/sunxi/i2s/sunxi-sndi2s.c +@@ -29,9 +29,14 @@ + + #include "sndi2s.h" + ++/* cleaning code + static struct clk *xtal; + static int clk_users; + static DEFINE_MUTEX(clk_lock); ++*/ ++ ++/* slave mode flag*/ ++static int sunxi_i2s_slave = 0; + + #ifdef ENFORCE_RATES + static struct snd_pcm_hw_constraint_list hw_constraints_rates = { +@@ -62,6 +67,7 @@ static int sunxi_sndi2s_startup(struct snd_pcm_substream *substream) + + static void sunxi_sndi2s_shutdown(struct snd_pcm_substream *substream) + { ++/* cleaning code + mutex_lock(&clk_lock); + clk_users -= 1; + if (clk_users == 0) { +@@ -70,6 +76,7 @@ static void sunxi_sndi2s_shutdown(struct snd_pcm_substream *substream) + + } + mutex_unlock(&clk_lock); ++*/ + } + + typedef struct __MCLK_SET_INF +@@ -91,6 +98,14 @@ typedef struct __BCLK_SET_INF + + } __bclk_set_inf; + ++typedef struct __EXTCLK_SET_INF ++{ ++ __u32 samp_rate; // sample rate ++ __u16 clk_div; // masterclock division ++ __u16 mpll; // select mpll, 0 - 24.576 Mhz, 1 - 22.5792 Mhz ++ ++} __extclk_set_inf; ++ + + static __bclk_set_inf BCLK_INF[] = + { +@@ -164,7 +179,45 @@ static __mclk_set_inf MCLK_INF[] = + {0xffffffff, 0, 0, 0}, + }; + +-static s32 get_clock_divder(u32 sample_rate, u32 sample_width, u32 * mclk_div, u32* mpll, u32* bclk_div, u32* mult_fs) ++static __extclk_set_inf EXTCLK_INF[] = ++{ ++ //44.1k bitrate ++ { 44100, 512, 1}, ++ //48k bitrate ++ { 48000, 512, 0}, ++ //88.2k bitrate ++ { 88200, 256, 1}, ++ //96k bitrate ++ { 96000, 256, 0}, ++ //176.4k bitrate ++ { 176400, 128, 1}, ++ //192k bitrate ++ { 192000, 128, 0}, ++ ++ //end flag 0xffffffff ++ {0xffffffff, 0, 0} ++}; ++ ++ ++static s32 get_clock_divder_slave(u32 sample_rate, u32 sample_width, u32* bclk_div, u32* mpll, u32* mult_fs) ++{ ++ u32 i, ret = -EINVAL; ++ ++ for(i=0; i< 100; i++) { ++ if(EXTCLK_INF[i].samp_rate == sample_rate) { ++ //set mpll and bclk division ++ *mpll = EXTCLK_INF[i].mpll; ++ *bclk_div = EXTCLK_INF[i].clk_div; ++ ret = 0; ++ break; ++ } ++ else if(EXTCLK_INF[i].samp_rate == 0xffffffff) ++ break; ++ } ++ return ret; ++} ++ ++static s32 get_clock_divder_master(u32 sample_rate, u32 sample_width, u32 * mclk_div, u32* mpll, u32* bclk_div, u32* mult_fs) + { + u32 i, j, ret = -EINVAL; + +@@ -200,35 +253,77 @@ static int sunxi_sndi2s_hw_params(struct snd_pcm_substream *substream, + int ret = 0; + unsigned long rate = params_rate(params); + u32 mclk_div=0, mpll=0, bclk_div=0, mult_fs=0; ++/* ++ printk("[IIS-0] sunxi_sndi2s_hw_params: codec_dai=(%s), cpu_dai=(%s)\n", codec_dai->name, cpu_dai->name); ++ printk("[IIS-0] sunxi_sndi2s_hw_params: channel num=(%d)\n", params_channels(params)); ++ printk("[IIS-0] sunxi_sndi2s_hw_params: sample rate=(%lu)\n", rate); ++ ++ switch (params_format(params)) ++ { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ printk("[IIS-0] sunxi_sndi2s_hw_params: format 16 bit\n"); ++ break; ++ case SNDRV_PCM_FORMAT_S20_3LE: ++ printk("[IIS-0] sunxi_sndi2s_hw_params: format 20 bit in 3 bytes\n"); ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ printk("[IIS-0] sunxi_sndi2s_hw_params: format 24 bit in 4 bytes\n"); ++ break; ++ default: ++ printk("[IIS-0] sunxi_sndi2s_hw_params: Unsupported format (%d)\n", (int)params_format(params)); ++ //return -EINVAL; ++ } ++*/ ++ if(!sunxi_i2s_slave) { ++ get_clock_divder_master(rate, 32, &mclk_div, &mpll, &bclk_div, &mult_fs); ++ printk("[IIS-0] get_clock_divder_master: rate=(%lu), mclk_div=(%d), mpll=(%d), bclk_div=(%d), mult_fs=(%d)\n", ++ rate, mclk_div, mpll, bclk_div, mult_fs); ++ } else { ++ get_clock_divder_slave(rate, 32, &bclk_div, &mpll, &mult_fs); ++ printk("[IIS-0] get_clock_divder_slave: rate=(%lu), bclk_div=(%d), mpll=(%d), mult_fs=(%d)\n", ++ rate, bclk_div, mpll, mult_fs); ++ } + +- get_clock_divder(rate, 32, &mclk_div, &mpll, &bclk_div, &mult_fs); +- ++ //call sunxi_iis_set_fmt + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | +- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); ++ SND_SOC_DAIFMT_NB_NF/* | SND_SOC_DAIFMT_CBM_CFM*/); + if (ret < 0) + return ret; + ++ //call sunxi_iis_set_fmt + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | +- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); ++ SND_SOC_DAIFMT_NB_NF/* | SND_SOC_DAIFMT_CBM_CFM*/); + if (ret < 0) + return ret; + ++ //call sunxi_iis_set_sysclk + ret = snd_soc_dai_set_sysclk(cpu_dai, 0 , mpll, 0); + if (ret < 0) + return ret; + ++ //call sndi2s_set_dai_sysclk + ret = snd_soc_dai_set_sysclk(codec_dai, 0 , mpll, 0); + if (ret < 0) + return ret; + +- ret = snd_soc_dai_set_clkdiv(cpu_dai, SUNXI_DIV_MCLK, mclk_div); +- if (ret < 0) +- return ret; ++ if(!sunxi_i2s_slave) { ++ //call sunxi_iis_set_clkdiv ++ ret = snd_soc_dai_set_clkdiv(cpu_dai, SUNXI_DIV_MCLK, mclk_div); ++ if (ret < 0) ++ return ret; + +- ret = snd_soc_dai_set_clkdiv(cpu_dai, SUNXI_DIV_BCLK, bclk_div); +- if (ret < 0) +- return ret; ++ //call sunxi_iis_set_clkdiv ++ ret = snd_soc_dai_set_clkdiv(cpu_dai, SUNXI_DIV_BCLK, bclk_div); ++ if (ret < 0) ++ return ret; ++ } else { ++ //call sunxi_iis_set_clkdiv ++ ret = snd_soc_dai_set_clkdiv(cpu_dai, SUNXI_DIV_EXTCLK, bclk_div); ++ if (ret < 0) ++ return ret; ++ } + ++ //call sndi2s_set_dai_clkdiv + ret = snd_soc_dai_set_clkdiv(codec_dai, 0, mult_fs); + if (ret < 0) + return ret; +@@ -243,7 +338,7 @@ static struct snd_soc_ops sunxi_sndi2s_ops = { + }; + + static struct snd_soc_dai_link sunxi_sndi2s_dai_link = { +- .name = "I2S", ++ .name = "I2S", + .stream_name = "SUNXI-I2S", + .cpu_dai_name = "sunxi-i2s.0", + .codec_dai_name = "sndi2s", +@@ -286,12 +381,26 @@ static struct platform_driver sunxi_sndi2s_driver = { + + static int __init sunxi_sndi2s_init(void) + { +- int ret, i2s_used = 0; ++ int ret, i2s_used = 0, i2s_slave = 0; ++ ++ printk("[IIS]Entered %s\n", __func__); + + ret = script_parser_fetch("i2s_para", "i2s_used", &i2s_used, 1); + if (ret != 0 || !i2s_used) + return -ENODEV; + ++ script_parser_fetch("i2s_para","i2s_slave", &i2s_slave, sizeof(int)); ++ if (i2s_slave) ++ { ++ sunxi_i2s_slave = 1; ++ printk("[I2S-0] sunxi_sndi2s_init I2S used in slave mode\n"); ++ } ++ else ++ { ++ sunxi_i2s_slave = 0; ++ printk("[I2S-0] sunxi_sndi2s_init I2S used in master mode\n"); ++ } ++ + ret = platform_device_register(&sunxi_sndi2s_device); + if (ret < 0) + return ret; +diff --git a/sound/soc/sunxi/i2s/sunxi-sndi2s.h b/sound/soc/sunxi/i2s/sunxi-sndi2s.h +index 47f0961..89cc71a 100644 +--- a/sound/soc/sunxi/i2s/sunxi-sndi2s.h ++++ b/sound/soc/sunxi/i2s/sunxi-sndi2s.h +@@ -14,7 +14,7 @@ + */ + #ifndef SUNXI_SNDI2S_H_ + #define SUNXI_SNDI2S_H_ +- ++/* cleaning code + struct sunxi_sndi2s_platform_data { + int iis_bclk; + int iis_ws; +@@ -22,4 +22,5 @@ struct sunxi_sndi2s_platform_data { + void (*power)(int); + int model; + } ++*/ + #endif +-- +1.7.7.1.msysgit.0 + diff --git a/patch/kernel/0002-ARM-sun6i-dt-Add-Security-System-to-A31-SoC-DTS.patch b/patch/kernel/0002-ARM-sun6i-dt-Add-Security-System-to-A31-SoC-DTS.patch new file mode 100644 index 000000000..f2e0ba809 --- /dev/null +++ b/patch/kernel/0002-ARM-sun6i-dt-Add-Security-System-to-A31-SoC-DTS.patch @@ -0,0 +1,53 @@ +From 4c4c51f19c975948b3a43d10606e075ca2254f74 Mon Sep 17 00:00:00 2001 +From: LABBE Corentin +Date: Fri, 17 Apr 2015 13:25:34 +0200 +Subject: [PATCH 2/8] ARM: sun6i: dt: Add Security System to A31 SoC DTS + +The Security System is a hardware cryptographic accelerator that support +AES/MD5/SHA1/DES/3DES/PRNG algorithms. +It could be found on many Allwinner SoC. + +This patch enable the Security System on the Allwinner A31 SoC Device-tree. + +Signed-off-by: LABBE Corentin +--- + arch/arm/boot/dts/sun6i-a31.dtsi | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi +index fa2f403..6b300f4 100644 +--- a/arch/arm/boot/dts/sun6i-a31.dtsi ++++ b/arch/arm/boot/dts/sun6i-a31.dtsi +@@ -296,6 +296,14 @@ + "mmc3_sample"; + }; + ++ ss_clk: clk@01c2009c { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-mod0-clk"; ++ reg = <0x01c2009c 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; ++ clock-output-names = "ss"; ++ }; ++ + spi0_clk: clk@01c200a0 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod0-clk"; +@@ -455,6 +463,14 @@ + status = "disabled"; + }; + ++ crypto: crypto-engine@01c15000 { ++ compatible = "allwinner,sun4i-a10-crypto"; ++ reg = <0x01c15000 0x1000>; ++ interrupts = ; ++ clocks = <&ahb_gates 5>, <&ss_clk>; ++ clock-names = "ahb", "mod"; ++ }; ++ + usbphy: phy@01c19400 { + compatible = "allwinner,sun6i-a31-usb-phy"; + reg = <0x01c19400 0x10>, +-- +2.3.6 + diff --git a/patch/kernel/0003-ARM-sun4i-dt-Add-Security-System-to-A10-SoC-DTS.patch b/patch/kernel/0003-ARM-sun4i-dt-Add-Security-System-to-A10-SoC-DTS.patch new file mode 100644 index 000000000..e489e5265 --- /dev/null +++ b/patch/kernel/0003-ARM-sun4i-dt-Add-Security-System-to-A10-SoC-DTS.patch @@ -0,0 +1,38 @@ +From d2a3003bba47ebab67252992f533f1f957666f2a Mon Sep 17 00:00:00 2001 +From: LABBE Corentin +Date: Wed, 22 Apr 2015 14:16:08 +0200 +Subject: [PATCH 3/8] ARM: sun4i: dt: Add Security System to A10 SoC DTS + +The Security System is a hardware cryptographic accelerator that support +AES/MD5/SHA1/DES/3DES/PRNG algorithms. +It could be found on many Allwinner SoC. + +This patch enable the Security System on the Allwinner A10 SoC Device-tree. + +Signed-off-by: LABBE Corentin +--- + arch/arm/boot/dts/sun4i-a10.dtsi | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index eebb785..bd7cdeb 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -564,6 +564,14 @@ + status = "disabled"; + }; + ++ crypto: crypto-engine@01c15000 { ++ compatible = "allwinner,sun4i-a10-crypto"; ++ reg = <0x01c15000 0x1000>; ++ interrupts = <86>; ++ clocks = <&ahb_gates 5>, <&ss_clk>; ++ clock-names = "ahb", "mod"; ++ }; ++ + spi2: spi@01c17000 { + compatible = "allwinner,sun4i-a10-spi"; + reg = <0x01c17000 0x1000>; +-- +2.3.6 + diff --git a/patch/kernel/0004-ARM-sun7i-dt-Add-Security-System-to-A20-SoC-DTS.patch b/patch/kernel/0004-ARM-sun7i-dt-Add-Security-System-to-A20-SoC-DTS.patch new file mode 100644 index 000000000..a5cd3476f --- /dev/null +++ b/patch/kernel/0004-ARM-sun7i-dt-Add-Security-System-to-A20-SoC-DTS.patch @@ -0,0 +1,38 @@ +From bc67b1914525bd0ea236255bc05598e2acf3ef59 Mon Sep 17 00:00:00 2001 +From: LABBE Corentin +Date: Sat, 4 Oct 2014 14:18:07 +0200 +Subject: [PATCH 4/8] ARM: sun7i: dt: Add Security System to A20 SoC DTS + +The Security System is a hardware cryptographic accelerator that support +AES/MD5/SHA1/DES/3DES/PRNG algorithms. +It could be found on many Allwinner SoC. + +This patch enable the Security System on the Allwinner A20 SoC Device-tree. + +Signed-off-by: LABBE Corentin +--- + arch/arm/boot/dts/sun7i-a20.dtsi | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index fdd1817..e840d76 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -679,6 +679,14 @@ + status = "disabled"; + }; + ++ crypto: crypto-engine@01c15000 { ++ compatible = "allwinner,sun4i-a10-crypto"; ++ reg = <0x01c15000 0x1000>; ++ interrupts = ; ++ clocks = <&ahb_gates 5>, <&ss_clk>; ++ clock-names = "ahb", "mod"; ++ }; ++ + spi2: spi@01c17000 { + compatible = "allwinner,sun4i-a10-spi"; + reg = <0x01c17000 0x1000>; +-- +2.3.6 + diff --git a/patch/kernel/0005-ARM-sun4i-dt-Add-DT-bindings-documentation-for-SUN4I.patch b/patch/kernel/0005-ARM-sun4i-dt-Add-DT-bindings-documentation-for-SUN4I.patch new file mode 100644 index 000000000..003a25503 --- /dev/null +++ b/patch/kernel/0005-ARM-sun4i-dt-Add-DT-bindings-documentation-for-SUN4I.patch @@ -0,0 +1,43 @@ +From bda35d07f7fc2f755b1b8c44cd762391be60b44f Mon Sep 17 00:00:00 2001 +From: LABBE Corentin +Date: Sat, 4 Oct 2014 14:19:41 +0200 +Subject: [PATCH 5/8] ARM: sun4i: dt: Add DT bindings documentation for SUN4I + Security System + +This patch adds documentation for Device-Tree bindings for the Security System +cryptographic accelerator driver. + +Signed-off-by: LABBE Corentin +--- + Documentation/devicetree/bindings/crypto/sun4i-ss.txt | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + create mode 100644 Documentation/devicetree/bindings/crypto/sun4i-ss.txt + +diff --git a/Documentation/devicetree/bindings/crypto/sun4i-ss.txt b/Documentation/devicetree/bindings/crypto/sun4i-ss.txt +new file mode 100644 +index 0000000..1e02d17 +--- /dev/null ++++ b/Documentation/devicetree/bindings/crypto/sun4i-ss.txt +@@ -0,0 +1,19 @@ ++* Allwinner Security System found on A20 SoC ++ ++Required properties: ++- compatible : Should be "allwinner,sun4i-a10-crypto". ++- reg: Should contain the Security System register location and length. ++- interrupts: Should contain the IRQ line for the Security System. ++- clocks : List of clock specifiers, corresponding to ahb and ss. ++- clock-names : Name of the functional clock, should be ++ * "ahb" : AHB gating clock ++ * "mod" : SS controller clock ++ ++Example: ++ crypto: crypto-engine@01c15000 { ++ compatible = "allwinner,sun4i-a10-crypto"; ++ reg = <0x01c15000 0x1000>; ++ interrupts = ; ++ clocks = <&ahb_gates 5>, <&ss_clk>; ++ clock-names = "ahb", "mod"; ++ }; +-- +2.3.6 + diff --git a/patch/kernel/0006-crypto-Add-Allwinner-Security-System-crypto-accelera.patch b/patch/kernel/0006-crypto-Add-Allwinner-Security-System-crypto-accelera.patch new file mode 100644 index 000000000..9f86a5e2f --- /dev/null +++ b/patch/kernel/0006-crypto-Add-Allwinner-Security-System-crypto-accelera.patch @@ -0,0 +1,1717 @@ +From 39ab54af71d9bbabf9b4538e84fbcca9cf552dc7 Mon Sep 17 00:00:00 2001 +From: LABBE Corentin +Date: Sat, 4 Oct 2014 14:21:17 +0200 +Subject: [PATCH 6/8] crypto: Add Allwinner Security System crypto accelerator + +Add support for the Security System included in Allwinner SoC A20. +The Security System is a hardware cryptographic accelerator that support: +- MD5 and SHA1 hash algorithms +- AES block cipher in CBC/ECB mode with 128/196/256bits keys. +- DES and 3DES block cipher in CBC/ECB mode + +Signed-off-by: LABBE Corentin +--- + drivers/crypto/Kconfig | 17 + + drivers/crypto/Makefile | 1 + + drivers/crypto/sunxi-ss/Makefile | 2 + + drivers/crypto/sunxi-ss/sun4i-ss-cipher.c | 529 ++++++++++++++++++++++++++++++ + drivers/crypto/sunxi-ss/sun4i-ss-core.c | 395 ++++++++++++++++++++++ + drivers/crypto/sunxi-ss/sun4i-ss-hash.c | 501 ++++++++++++++++++++++++++++ + drivers/crypto/sunxi-ss/sun4i-ss.h | 195 +++++++++++ + 7 files changed, 1640 insertions(+) + create mode 100644 drivers/crypto/sunxi-ss/Makefile + create mode 100644 drivers/crypto/sunxi-ss/sun4i-ss-cipher.c + create mode 100644 drivers/crypto/sunxi-ss/sun4i-ss-core.c + create mode 100644 drivers/crypto/sunxi-ss/sun4i-ss-hash.c + create mode 100644 drivers/crypto/sunxi-ss/sun4i-ss.h + +diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig +index 033c0c8..2a5598e 100644 +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -459,4 +459,21 @@ config CRYPTO_DEV_IMGTEC_HASH + hardware hash accelerator. Supporting MD5/SHA1/SHA224/SHA256 + hashing algorithms. + ++config CRYPTO_DEV_SUN4I_SS ++ tristate "Support for Allwinner Security System cryptographic accelerator" ++ depends on ARCH_SUNXI ++ select CRYPTO_MD5 ++ select CRYPTO_SHA1 ++ select CRYPTO_AES ++ select CRYPTO_DES ++ select CRYPTO_BLKCIPHER ++ help ++ Some Allwinner SoC have a crypto accelerator named ++ Security System. Select this if you want to use it. ++ The Security System handle AES/DES/3DES ciphers in CBC mode ++ and SHA1 and MD5 hash algorithms. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called sun4i-ss. ++ + endif # CRYPTO_HW +diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile +index fb84be7..e843292 100644 +--- a/drivers/crypto/Makefile ++++ b/drivers/crypto/Makefile +@@ -27,3 +27,4 @@ obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/ + obj-$(CONFIG_CRYPTO_DEV_QAT) += qat/ + obj-$(CONFIG_CRYPTO_DEV_QCE) += qce/ + obj-$(CONFIG_CRYPTO_DEV_VMX) += vmx/ ++obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sunxi-ss/ +diff --git a/drivers/crypto/sunxi-ss/Makefile b/drivers/crypto/sunxi-ss/Makefile +new file mode 100644 +index 0000000..8f4c7a2 +--- /dev/null ++++ b/drivers/crypto/sunxi-ss/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sun4i-ss.o ++sun4i-ss-y += sun4i-ss-core.o sun4i-ss-hash.o sun4i-ss-cipher.o +diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +new file mode 100644 +index 0000000..01634aa +--- /dev/null ++++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +@@ -0,0 +1,529 @@ ++/* ++ * sun4i-ss-cipher.c - hardware cryptographic accelerator for Allwinner A20 SoC ++ * ++ * Copyright (C) 2013-2015 Corentin LABBE ++ * ++ * This file add support for AES cipher with 128,192,256 bits ++ * keysize in CBC and ECB mode. ++ * Add support also for DES and 3DES in CBC and ECB mode. ++ * ++ * You could find the datasheet in Documentation/arm/sunxi/README ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#include "sun4i-ss.h" ++ ++static int sun4i_ss_opti_poll(struct ablkcipher_request *areq) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq); ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_ss_ctx *ss = op->ss; ++ unsigned int ivsize = crypto_ablkcipher_ivsize(tfm); ++ struct sun4i_cipher_req_ctx *ctx = ablkcipher_request_ctx(areq); ++ u32 mode = ctx->mode; ++ /* when activating SS, the default FIFO space is 32 */ ++ u32 rx_cnt = 32; ++ u32 tx_cnt = 0; ++ u32 spaces; ++ u32 v; ++ int i, err = 0; ++ unsigned int ileft = areq->nbytes; ++ unsigned int oleft = areq->nbytes; ++ unsigned int todo; ++ struct sg_mapping_iter mi, mo; ++ unsigned int oi, oo; /* offset for in and out */ ++ ++ if (areq->nbytes == 0) ++ return 0; ++ ++ if (areq->info == NULL) { ++ dev_err(ss->dev, "ERROR: Empty IV\n"); ++ return -EINVAL; ++ } ++ ++ if (areq->src == NULL || areq->dst == NULL) { ++ dev_err(ss->dev, "ERROR: Some SGs are NULL\n"); ++ return -EINVAL; ++ } ++ ++ spin_lock_bh(&ss->slock); ++ ++ for (i = 0; i < op->keylen; i += 4) ++ writel(*(op->key + i / 4), ss->base + SS_KEY0 + i); ++ ++ if (areq->info != NULL) { ++ for (i = 0; i < 4 && i < ivsize / 4; i++) { ++ v = *(u32 *)(areq->info + i * 4); ++ writel(v, ss->base + SS_IV0 + i * 4); ++ } ++ } ++ writel(mode, ss->base + SS_CTL); ++ ++ sg_miter_start(&mi, areq->src, sg_nents(areq->src), ++ SG_MITER_FROM_SG | SG_MITER_ATOMIC); ++ sg_miter_start(&mo, areq->dst, sg_nents(areq->dst), ++ SG_MITER_TO_SG | SG_MITER_ATOMIC); ++ sg_miter_next(&mi); ++ sg_miter_next(&mo); ++ if (mi.addr == NULL || mo.addr == NULL) { ++ dev_err(ss->dev, "ERROR: sg_miter return null\n"); ++ err = -EINVAL; ++ goto release_ss; ++ } ++ ++ ileft = areq->nbytes / 4; ++ oleft = areq->nbytes / 4; ++ oi = 0; ++ oo = 0; ++ do { ++ todo = min3(rx_cnt, ileft, (mi.length - oi) / 4); ++ if (todo > 0) { ++ ileft -= todo; ++ writesl(ss->base + SS_RXFIFO, mi.addr + oi, todo); ++ oi += todo * 4; ++ } ++ if (oi == mi.length) { ++ sg_miter_next(&mi); ++ oi = 0; ++ } ++ ++ spaces = readl(ss->base + SS_FCSR); ++ rx_cnt = SS_RXFIFO_SPACES(spaces); ++ tx_cnt = SS_TXFIFO_SPACES(spaces); ++ ++ todo = min3(tx_cnt, oleft, (mo.length - oo) / 4); ++ if (todo > 0) { ++ oleft -= todo; ++ readsl(ss->base + SS_TXFIFO, mo.addr + oo, todo); ++ oo += todo * 4; ++ } ++ if (oo == mo.length) { ++ sg_miter_next(&mo); ++ oo = 0; ++ } ++ } while (mo.length > 0); ++ ++release_ss: ++ sg_miter_stop(&mi); ++ sg_miter_stop(&mo); ++ writel(0, ss->base + SS_CTL); ++ spin_unlock_bh(&ss->slock); ++ return err; ++} ++ ++/* Generic function that support SG with size not multiple of 4 */ ++static int sun4i_ss_cipher_poll(struct ablkcipher_request *areq) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq); ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_ss_ctx *ss = op->ss; ++ int no_chunk = 1; ++ struct scatterlist *in_sg = areq->src; ++ struct scatterlist *out_sg = areq->dst; ++ unsigned int ivsize = crypto_ablkcipher_ivsize(tfm); ++ struct sun4i_cipher_req_ctx *ctx = ablkcipher_request_ctx(areq); ++ u32 mode = ctx->mode; ++ /* when activating SS, the default FIFO space is 32 */ ++ u32 rx_cnt = 32; ++ u32 tx_cnt = 0; ++ u32 v; ++ u32 spaces; ++ int i, err = 0; ++ unsigned int ileft = areq->nbytes; ++ unsigned int oleft = areq->nbytes; ++ unsigned int todo; ++ struct sg_mapping_iter mi, mo; ++ unsigned int oi, oo; /* offset for in and out */ ++ char buf[4 * 32];/* buffer for linearize SG src */ ++ char bufo[4 * 32];/* buffer for linearize SG dst */ ++ unsigned int ob = 0; /* offset in buf */ ++ unsigned int obo = 0; /* offset in bufo*/ ++ unsigned int obl = 0; /* length of data in bufo */ ++ ++ if (areq->nbytes == 0) ++ return 0; ++ ++ if (areq->info == NULL) { ++ dev_err(ss->dev, "ERROR: Empty IV\n"); ++ return -EINVAL; ++ } ++ ++ if (areq->src == NULL || areq->dst == NULL) { ++ dev_err(ss->dev, "ERROR: Some SGs are NULL\n"); ++ return -EINVAL; ++ } ++ ++ /* ++ * if we have only SGs with size multiple of 4, ++ * we can use the SS optimized function ++ */ ++ while (in_sg != NULL && no_chunk == 1) { ++ if ((in_sg->length % 4) != 0) ++ no_chunk = 0; ++ in_sg = sg_next(in_sg); ++ } ++ while (out_sg != NULL && no_chunk == 1) { ++ if ((out_sg->length % 4) != 0) ++ no_chunk = 0; ++ out_sg = sg_next(out_sg); ++ } ++ ++ if (no_chunk == 1) ++ return sun4i_ss_opti_poll(areq); ++ ++ spin_lock_bh(&ss->slock); ++ ++ for (i = 0; i < op->keylen; i += 4) ++ writel(*(op->key + i / 4), ss->base + SS_KEY0 + i); ++ ++ if (areq->info != NULL) { ++ for (i = 0; i < 4 && i < ivsize / 4; i++) { ++ v = *(u32 *)(areq->info + i * 4); ++ writel(v, ss->base + SS_IV0 + i * 4); ++ } ++ } ++ writel(mode, ss->base + SS_CTL); ++ ++ sg_miter_start(&mi, areq->src, sg_nents(areq->src), ++ SG_MITER_FROM_SG | SG_MITER_ATOMIC); ++ sg_miter_start(&mo, areq->dst, sg_nents(areq->dst), ++ SG_MITER_TO_SG | SG_MITER_ATOMIC); ++ sg_miter_next(&mi); ++ sg_miter_next(&mo); ++ if (mi.addr == NULL || mo.addr == NULL) { ++ dev_err(ss->dev, "ERROR: sg_miter return null\n"); ++ err = -EINVAL; ++ goto release_ss; ++ } ++ ileft = areq->nbytes; ++ oleft = areq->nbytes; ++ oi = 0; ++ oo = 0; ++ ++ while (oleft > 0) { ++ if (ileft > 0) { ++ /* ++ * todo is the number of consecutive 4byte word that we ++ * can read from current SG ++ */ ++ todo = min3(rx_cnt, ileft / 4, (mi.length - oi) / 4); ++ if (todo > 0 && ob == 0) { ++ writesl(ss->base + SS_RXFIFO, mi.addr + oi, ++ todo); ++ ileft -= todo * 4; ++ oi += todo * 4; ++ } else { ++ /* ++ * not enought consecutive bytes, so we need to ++ * linearize in buf. todo is in bytes ++ * After that copy, if we have a multiple of 4 ++ * we need to be able to write all buf in one ++ * pass, so it is why we min() with rx_cnt ++ */ ++ todo = min3(rx_cnt * 4 - ob, ileft, ++ mi.length - oi); ++ memcpy(buf + ob, mi.addr + oi, todo); ++ ileft -= todo; ++ oi += todo; ++ ob += todo; ++ if (ob % 4 == 0) { ++ writesl(ss->base + SS_RXFIFO, buf, ++ ob / 4); ++ ob = 0; ++ } ++ } ++ if (oi == mi.length) { ++ sg_miter_next(&mi); ++ oi = 0; ++ } ++ } ++ ++ spaces = readl(ss->base + SS_FCSR); ++ rx_cnt = SS_RXFIFO_SPACES(spaces); ++ tx_cnt = SS_TXFIFO_SPACES(spaces); ++ dev_dbg(ss->dev, "%x %u/%u %u/%u cnt=%u %u/%u %u/%u cnt=%u %u %u\n", ++ mode, ++ oi, mi.length, ileft, areq->nbytes, rx_cnt, ++ oo, mo.length, oleft, areq->nbytes, tx_cnt, ++ todo, ob); ++ ++ if (tx_cnt == 0) ++ continue; ++ /* todo in 4bytes word */ ++ todo = min3(tx_cnt, oleft / 4, (mo.length - oo) / 4); ++ if (todo > 0) { ++ readsl(ss->base + SS_TXFIFO, mo.addr + oo, todo); ++ oleft -= todo * 4; ++ oo += todo * 4; ++ if (oo == mo.length) { ++ sg_miter_next(&mo); ++ oo = 0; ++ } ++ } else { ++ /* ++ * read obl bytes in bufo, we read at maximum for ++ * empying the device ++ */ ++ readsl(ss->base + SS_TXFIFO, bufo, tx_cnt); ++ obl = tx_cnt * 4; ++ obo = 0; ++ do { ++ /* ++ * how many bytes we can copy ? ++ * no more than remaining SG size ++ * no more than remaining buffer ++ * no need to test against oleft ++ */ ++ todo = min(mo.length - oo, obl - obo); ++ memcpy(mo.addr + oo, bufo + obo, todo); ++ oleft -= todo; ++ obo += todo; ++ oo += todo; ++ if (oo == mo.length) { ++ sg_miter_next(&mo); ++ oo = 0; ++ } ++ } while (obo < obl); ++ /* bufo must be fully used here */ ++ } ++ } ++ ++release_ss: ++ sg_miter_stop(&mi); ++ sg_miter_stop(&mo); ++ writel(0, ss->base + SS_CTL); ++ spin_unlock_bh(&ss->slock); ++ ++ return err; ++} ++ ++/* CBC AES */ ++int sun4i_ss_cbc_aes_encrypt(struct ablkcipher_request *areq) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq); ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq); ++ ++ rctx->mode = SS_OP_AES | SS_CBC | SS_ENABLED | SS_ENCRYPTION | ++ op->keymode; ++ return sun4i_ss_cipher_poll(areq); ++} ++ ++int sun4i_ss_cbc_aes_decrypt(struct ablkcipher_request *areq) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq); ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq); ++ ++ rctx->mode = SS_OP_AES | SS_CBC | SS_ENABLED | SS_DECRYPTION | ++ op->keymode; ++ return sun4i_ss_cipher_poll(areq); ++} ++ ++/* ECB AES */ ++int sun4i_ss_ecb_aes_encrypt(struct ablkcipher_request *areq) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq); ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq); ++ ++ rctx->mode = SS_OP_AES | SS_ECB | SS_ENABLED | SS_ENCRYPTION | ++ op->keymode; ++ return sun4i_ss_cipher_poll(areq); ++} ++ ++int sun4i_ss_ecb_aes_decrypt(struct ablkcipher_request *areq) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq); ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq); ++ ++ rctx->mode = SS_OP_AES | SS_ECB | SS_ENABLED | SS_DECRYPTION | ++ op->keymode; ++ return sun4i_ss_cipher_poll(areq); ++} ++ ++/* CBC DES */ ++int sun4i_ss_cbc_des_encrypt(struct ablkcipher_request *areq) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq); ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq); ++ ++ rctx->mode = SS_OP_DES | SS_CBC | SS_ENABLED | SS_ENCRYPTION | ++ op->keymode; ++ return sun4i_ss_cipher_poll(areq); ++} ++ ++int sun4i_ss_cbc_des_decrypt(struct ablkcipher_request *areq) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq); ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq); ++ ++ rctx->mode = SS_OP_DES | SS_CBC | SS_ENABLED | SS_DECRYPTION | ++ op->keymode; ++ return sun4i_ss_cipher_poll(areq); ++} ++ ++/* ECB DES */ ++int sun4i_ss_ecb_des_encrypt(struct ablkcipher_request *areq) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq); ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq); ++ ++ rctx->mode = SS_OP_DES | SS_ECB | SS_ENABLED | SS_ENCRYPTION | ++ op->keymode; ++ return sun4i_ss_cipher_poll(areq); ++} ++ ++int sun4i_ss_ecb_des_decrypt(struct ablkcipher_request *areq) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq); ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq); ++ ++ rctx->mode = SS_OP_DES | SS_ECB | SS_ENABLED | SS_DECRYPTION | ++ op->keymode; ++ return sun4i_ss_cipher_poll(areq); ++} ++ ++/* CBC 3DES */ ++int sun4i_ss_cbc_des3_encrypt(struct ablkcipher_request *areq) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq); ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq); ++ ++ rctx->mode = SS_OP_3DES | SS_CBC | SS_ENABLED | SS_ENCRYPTION | ++ op->keymode; ++ return sun4i_ss_cipher_poll(areq); ++} ++ ++int sun4i_ss_cbc_des3_decrypt(struct ablkcipher_request *areq) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq); ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq); ++ ++ rctx->mode = SS_OP_3DES | SS_CBC | SS_ENABLED | SS_DECRYPTION | ++ op->keymode; ++ return sun4i_ss_cipher_poll(areq); ++} ++ ++/* ECB 3DES */ ++int sun4i_ss_ecb_des3_encrypt(struct ablkcipher_request *areq) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq); ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq); ++ ++ rctx->mode = SS_OP_3DES | SS_ECB | SS_ENABLED | SS_ENCRYPTION | ++ op->keymode; ++ return sun4i_ss_cipher_poll(areq); ++} ++ ++int sun4i_ss_ecb_des3_decrypt(struct ablkcipher_request *areq) ++{ ++ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(areq); ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_cipher_req_ctx *rctx = ablkcipher_request_ctx(areq); ++ ++ rctx->mode = SS_OP_3DES | SS_ECB | SS_ENABLED | SS_DECRYPTION | ++ op->keymode; ++ return sun4i_ss_cipher_poll(areq); ++} ++ ++int sun4i_ss_cipher_init(struct crypto_tfm *tfm) ++{ ++ struct sun4i_tfm_ctx *op = crypto_tfm_ctx(tfm); ++ struct crypto_alg *alg = tfm->__crt_alg; ++ struct sun4i_ss_alg_template *algt; ++ ++ memset(op, 0, sizeof(struct sun4i_tfm_ctx)); ++ ++ algt = container_of(alg, struct sun4i_ss_alg_template, alg.crypto); ++ op->ss = algt->ss; ++ ++ tfm->crt_ablkcipher.reqsize = sizeof(struct sun4i_cipher_req_ctx); ++ ++ return 0; ++} ++ ++/* check and set the AES key, prepare the mode to be used */ ++int sun4i_ss_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, ++ unsigned int keylen) ++{ ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_ss_ctx *ss = op->ss; ++ ++ switch (keylen) { ++ case 128 / 8: ++ op->keymode = SS_AES_128BITS; ++ break; ++ case 192 / 8: ++ op->keymode = SS_AES_192BITS; ++ break; ++ case 256 / 8: ++ op->keymode = SS_AES_256BITS; ++ break; ++ default: ++ dev_err(ss->dev, "ERROR: Invalid keylen %u\n", keylen); ++ crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); ++ return -EINVAL; ++ } ++ op->keylen = keylen; ++ memcpy(op->key, key, keylen); ++ return 0; ++} ++ ++/* check and set the DES key, prepare the mode to be used */ ++int sun4i_ss_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, ++ unsigned int keylen) ++{ ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_ss_ctx *ss = op->ss; ++ u32 flags; ++ u32 tmp[DES_EXPKEY_WORDS]; ++ int ret; ++ ++ if (unlikely(keylen != DES_KEY_SIZE)) { ++ dev_err(ss->dev, "Invalid keylen %u\n", keylen); ++ crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); ++ return -EINVAL; ++ } ++ ++ flags = crypto_ablkcipher_get_flags(tfm); ++ ++ ret = des_ekey(tmp, key); ++ if (unlikely(ret == 0) && (flags & CRYPTO_TFM_REQ_WEAK_KEY)) { ++ crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_WEAK_KEY); ++ dev_dbg(ss->dev, "Weak key %u\n", keylen); ++ return -EINVAL; ++ } ++ ++ op->keylen = keylen; ++ memcpy(op->key, key, keylen); ++ return 0; ++} ++ ++/* check and set the 3DES key, prepare the mode to be used */ ++int sun4i_ss_des3_setkey(struct crypto_ablkcipher *tfm, const u8 *key, ++ unsigned int keylen) ++{ ++ struct sun4i_tfm_ctx *op = crypto_ablkcipher_ctx(tfm); ++ struct sun4i_ss_ctx *ss = op->ss; ++ ++ if (unlikely(keylen != 3 * DES_KEY_SIZE)) { ++ dev_err(ss->dev, "Invalid keylen %u\n", keylen); ++ crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); ++ return -EINVAL; ++ } ++ op->keylen = keylen; ++ memcpy(op->key, key, keylen); ++ return 0; ++} +diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-core.c b/drivers/crypto/sunxi-ss/sun4i-ss-core.c +new file mode 100644 +index 0000000..fcb4c01 +--- /dev/null ++++ b/drivers/crypto/sunxi-ss/sun4i-ss-core.c +@@ -0,0 +1,395 @@ ++/* ++ * sun4i-ss-core.c - hardware cryptographic accelerator for Allwinner A20 SoC ++ * ++ * Copyright (C) 2013-2015 Corentin LABBE ++ * ++ * Core file which registers crypto algorithms supported by the SS. ++ * ++ * You could find a link for the datasheet in Documentation/arm/sunxi/README ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "sun4i-ss.h" ++ ++static struct sun4i_ss_alg_template driver_algs[] = { ++{ .type = CRYPTO_ALG_TYPE_AHASH, ++ .alg.hash = { ++ .init = sun4i_hash_init, ++ .update = sun4i_hash_update, ++ .final = sun4i_hash_final, ++ .finup = sun4i_hash_finup, ++ .digest = sun4i_hash_digest, ++ .export = sun4i_hash_export_md5, ++ .import = sun4i_hash_import_md5, ++ .halg = { ++ .digestsize = MD5_DIGEST_SIZE, ++ .base = { ++ .cra_name = "md5", ++ .cra_driver_name = "md5-sun4i-ss", ++ .cra_priority = 300, ++ .cra_alignmask = 3, ++ .cra_flags = CRYPTO_ALG_TYPE_AHASH, ++ .cra_blocksize = MD5_HMAC_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct sun4i_req_ctx), ++ .cra_module = THIS_MODULE, ++ .cra_type = &crypto_ahash_type, ++ .cra_init = sun4i_hash_crainit ++ } ++ } ++ } ++}, ++{ .type = CRYPTO_ALG_TYPE_AHASH, ++ .alg.hash = { ++ .init = sun4i_hash_init, ++ .update = sun4i_hash_update, ++ .final = sun4i_hash_final, ++ .finup = sun4i_hash_finup, ++ .digest = sun4i_hash_digest, ++ .export = sun4i_hash_export_sha1, ++ .import = sun4i_hash_import_sha1, ++ .halg = { ++ .digestsize = SHA1_DIGEST_SIZE, ++ .base = { ++ .cra_name = "sha1", ++ .cra_driver_name = "sha1-sun4i-ss", ++ .cra_priority = 300, ++ .cra_alignmask = 3, ++ .cra_flags = CRYPTO_ALG_TYPE_AHASH, ++ .cra_blocksize = SHA1_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct sun4i_req_ctx), ++ .cra_module = THIS_MODULE, ++ .cra_type = &crypto_ahash_type, ++ .cra_init = sun4i_hash_crainit ++ } ++ } ++ } ++}, ++{ .type = CRYPTO_ALG_TYPE_ABLKCIPHER, ++ .alg.crypto = { ++ .cra_name = "cbc(aes)", ++ .cra_driver_name = "cbc-aes-sun4i-ss", ++ .cra_priority = 300, ++ .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER, ++ .cra_ctxsize = sizeof(struct sun4i_tfm_ctx), ++ .cra_module = THIS_MODULE, ++ .cra_alignmask = 3, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_init = sun4i_ss_cipher_init, ++ .cra_ablkcipher = { ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .setkey = sun4i_ss_aes_setkey, ++ .encrypt = sun4i_ss_cbc_aes_encrypt, ++ .decrypt = sun4i_ss_cbc_aes_decrypt, ++ } ++ } ++}, ++{ .type = CRYPTO_ALG_TYPE_ABLKCIPHER, ++ .alg.crypto = { ++ .cra_name = "ecb(aes)", ++ .cra_driver_name = "ecb-aes-sun4i-ss", ++ .cra_priority = 300, ++ .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER, ++ .cra_ctxsize = sizeof(struct sun4i_tfm_ctx), ++ .cra_module = THIS_MODULE, ++ .cra_alignmask = 3, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_init = sun4i_ss_cipher_init, ++ .cra_ablkcipher = { ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .setkey = sun4i_ss_aes_setkey, ++ .encrypt = sun4i_ss_ecb_aes_encrypt, ++ .decrypt = sun4i_ss_ecb_aes_decrypt, ++ } ++ } ++}, ++{ .type = CRYPTO_ALG_TYPE_ABLKCIPHER, ++ .alg.crypto = { ++ .cra_name = "cbc(des)", ++ .cra_driver_name = "cbc-des-sun4i-ss", ++ .cra_priority = 300, ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER, ++ .cra_ctxsize = sizeof(struct sun4i_req_ctx), ++ .cra_module = THIS_MODULE, ++ .cra_alignmask = 3, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_init = sun4i_ss_cipher_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = DES_KEY_SIZE, ++ .max_keysize = DES_KEY_SIZE, ++ .ivsize = DES_BLOCK_SIZE, ++ .setkey = sun4i_ss_des_setkey, ++ .encrypt = sun4i_ss_cbc_des_encrypt, ++ .decrypt = sun4i_ss_cbc_des_decrypt, ++ } ++ } ++}, ++{ .type = CRYPTO_ALG_TYPE_ABLKCIPHER, ++ .alg.crypto = { ++ .cra_name = "ecb(des)", ++ .cra_driver_name = "ecb-des-sun4i-ss", ++ .cra_priority = 300, ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER, ++ .cra_ctxsize = sizeof(struct sun4i_req_ctx), ++ .cra_module = THIS_MODULE, ++ .cra_alignmask = 3, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_init = sun4i_ss_cipher_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = DES_KEY_SIZE, ++ .max_keysize = DES_KEY_SIZE, ++ .setkey = sun4i_ss_des_setkey, ++ .encrypt = sun4i_ss_ecb_des_encrypt, ++ .decrypt = sun4i_ss_ecb_des_decrypt, ++ } ++ } ++}, ++{ .type = CRYPTO_ALG_TYPE_ABLKCIPHER, ++ .alg.crypto = { ++ .cra_name = "cbc(des3_ede)", ++ .cra_driver_name = "cbc-des3-sun4i-ss", ++ .cra_priority = 300, ++ .cra_blocksize = DES3_EDE_BLOCK_SIZE, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER, ++ .cra_ctxsize = sizeof(struct sun4i_req_ctx), ++ .cra_module = THIS_MODULE, ++ .cra_alignmask = 3, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_init = sun4i_ss_cipher_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = DES3_EDE_KEY_SIZE, ++ .max_keysize = DES3_EDE_KEY_SIZE, ++ .ivsize = DES3_EDE_BLOCK_SIZE, ++ .setkey = sun4i_ss_des3_setkey, ++ .encrypt = sun4i_ss_cbc_des3_encrypt, ++ .decrypt = sun4i_ss_cbc_des3_decrypt, ++ } ++ } ++}, ++{ .type = CRYPTO_ALG_TYPE_ABLKCIPHER, ++ .alg.crypto = { ++ .cra_name = "ecb(des3_ede)", ++ .cra_driver_name = "ecb-des3-sun4i-ss", ++ .cra_priority = 300, ++ .cra_blocksize = DES3_EDE_BLOCK_SIZE, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER, ++ .cra_ctxsize = sizeof(struct sun4i_req_ctx), ++ .cra_module = THIS_MODULE, ++ .cra_alignmask = 3, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_init = sun4i_ss_cipher_init, ++ .cra_u.ablkcipher = { ++ .min_keysize = DES3_EDE_KEY_SIZE, ++ .max_keysize = DES3_EDE_KEY_SIZE, ++ .ivsize = DES3_EDE_BLOCK_SIZE, ++ .setkey = sun4i_ss_des3_setkey, ++ .encrypt = sun4i_ss_ecb_des3_encrypt, ++ .decrypt = sun4i_ss_ecb_des3_decrypt, ++ } ++ } ++}, ++}; ++ ++static int sun4i_ss_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ u32 v; ++ int err, i; ++ unsigned long cr; ++ const unsigned long cr_ahb = 24 * 1000 * 1000; ++ const unsigned long cr_mod = 150 * 1000 * 1000; ++ struct sun4i_ss_ctx *ss; ++ ++ if (!pdev->dev.of_node) ++ return -ENODEV; ++ ++ ss = devm_kzalloc(&pdev->dev, sizeof(*ss), GFP_KERNEL); ++ if (ss == NULL) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ss->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(ss->base)) { ++ dev_err(&pdev->dev, "Cannot request MMIO\n"); ++ return PTR_ERR(ss->base); ++ } ++ ++ ss->ssclk = devm_clk_get(&pdev->dev, "mod"); ++ if (IS_ERR(ss->ssclk)) { ++ err = PTR_ERR(ss->ssclk); ++ dev_err(&pdev->dev, "Cannot get SS clock err=%d\n", err); ++ return err; ++ } ++ dev_dbg(&pdev->dev, "clock ss acquired\n"); ++ ++ ss->busclk = devm_clk_get(&pdev->dev, "ahb"); ++ if (IS_ERR(ss->busclk)) { ++ err = PTR_ERR(ss->busclk); ++ dev_err(&pdev->dev, "Cannot get AHB SS clock err=%d\n", err); ++ return err; ++ } ++ dev_dbg(&pdev->dev, "clock ahb_ss acquired\n"); ++ ++ /* Enable both clocks */ ++ err = clk_prepare_enable(ss->busclk); ++ if (err != 0) { ++ dev_err(&pdev->dev, "Cannot prepare_enable busclk\n"); ++ return err; ++ } ++ err = clk_prepare_enable(ss->ssclk); ++ if (err != 0) { ++ dev_err(&pdev->dev, "Cannot prepare_enable ssclk\n"); ++ goto error_ssclk; ++ } ++ ++ /* ++ * Check that clock have the correct rates gived in the datasheet ++ * Try to set the clock to the maximum allowed ++ */ ++ err = clk_set_rate(ss->ssclk, cr_mod); ++ if (err != 0) { ++ dev_err(&pdev->dev, "Cannot set clock rate to ssclk\n"); ++ goto error_clk; ++ } ++ ++ /* ++ * The only impact on clocks below requirement are bad performance, ++ * so do not print "errors" ++ * warn on Overclocked clocks ++ */ ++ cr = clk_get_rate(ss->busclk); ++ if (cr >= cr_ahb) ++ dev_dbg(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n", ++ cr, cr / 1000000, cr_ahb); ++ else ++ dev_warn(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n", ++ cr, cr / 1000000, cr_ahb); ++ ++ cr = clk_get_rate(ss->ssclk); ++ if (cr <= cr_mod) ++ if (cr < cr_mod) ++ dev_warn(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n", ++ cr, cr / 1000000, cr_mod); ++ else ++ dev_dbg(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n", ++ cr, cr / 1000000, cr_mod); ++ else ++ dev_warn(&pdev->dev, "Clock ss is at %lu (%lu MHz) (must be <= %lu)\n", ++ cr, cr / 1000000, cr_mod); ++ ++ /* ++ * Datasheet named it "Die Bonding ID" ++ * I expect to be a sort of Security System Revision number. ++ * Since the A80 seems to have an other version of SS ++ * this info could be useful ++ */ ++ writel(SS_ENABLED, ss->base + SS_CTL); ++ v = readl(ss->base + SS_CTL); ++ v >>= 16; ++ v &= 0x07; ++ dev_info(&pdev->dev, "Die ID %d\n", v); ++ writel(0, ss->base + SS_CTL); ++ ++ ss->dev = &pdev->dev; ++ ++ spin_lock_init(&ss->slock); ++ ++ for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { ++ driver_algs[i].ss = ss; ++ switch (driver_algs[i].type) { ++ case CRYPTO_ALG_TYPE_ABLKCIPHER: ++ err = crypto_register_alg(&driver_algs[i].alg.crypto); ++ if (err != 0) ++ goto error_alg; ++ break; ++ case CRYPTO_ALG_TYPE_AHASH: ++ err = crypto_register_ahash(&driver_algs[i].alg.hash); ++ if (err != 0) ++ goto error_alg; ++ break; ++ } ++ } ++ platform_set_drvdata(pdev, ss); ++ return 0; ++error_alg: ++ i--; ++ for (; i >= 0; i--) { ++ switch (driver_algs[i].type) { ++ case CRYPTO_ALG_TYPE_ABLKCIPHER: ++ crypto_unregister_alg(&driver_algs[i].alg.crypto); ++ break; ++ case CRYPTO_ALG_TYPE_AHASH: ++ crypto_unregister_ahash(&driver_algs[i].alg.hash); ++ break; ++ } ++ } ++error_clk: ++ clk_disable_unprepare(ss->ssclk); ++error_ssclk: ++ clk_disable_unprepare(ss->busclk); ++ return err; ++} ++ ++static int sun4i_ss_remove(struct platform_device *pdev) ++{ ++ int i; ++ struct sun4i_ss_ctx *ss = platform_get_drvdata(pdev); ++ ++ for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { ++ switch (driver_algs[i].type) { ++ case CRYPTO_ALG_TYPE_ABLKCIPHER: ++ crypto_unregister_alg(&driver_algs[i].alg.crypto); ++ break; ++ case CRYPTO_ALG_TYPE_AHASH: ++ crypto_unregister_ahash(&driver_algs[i].alg.hash); ++ break; ++ } ++ } ++ ++ writel(0, ss->base + SS_CTL); ++ clk_disable_unprepare(ss->busclk); ++ clk_disable_unprepare(ss->ssclk); ++ return 0; ++} ++ ++static const struct of_device_id a20ss_crypto_of_match_table[] = { ++ { .compatible = "allwinner,sun4i-a10-crypto" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, a20ss_crypto_of_match_table); ++ ++static struct platform_driver sun4i_ss_driver = { ++ .probe = sun4i_ss_probe, ++ .remove = sun4i_ss_remove, ++ .driver = { ++ .name = "sun4i-ss", ++ .of_match_table = a20ss_crypto_of_match_table, ++ }, ++}; ++ ++module_platform_driver(sun4i_ss_driver); ++ ++MODULE_DESCRIPTION("Allwinner Security System cryptographic accelerator"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Corentin LABBE "); +diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-hash.c b/drivers/crypto/sunxi-ss/sun4i-ss-hash.c +new file mode 100644 +index 0000000..fcd2157 +--- /dev/null ++++ b/drivers/crypto/sunxi-ss/sun4i-ss-hash.c +@@ -0,0 +1,501 @@ ++/* ++ * sun4i-ss-hash.c - hardware cryptographic accelerator for Allwinner A20 SoC ++ * ++ * Copyright (C) 2013-2015 Corentin LABBE ++ * ++ * This file add support for MD5 and SHA1. ++ * ++ * You could find the datasheet in Documentation/arm/sunxi/README ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#include "sun4i-ss.h" ++#include ++ ++/* This is a totaly arbitrary value */ ++#define SS_TIMEOUT 100 ++ ++int sun4i_hash_crainit(struct crypto_tfm *tfm) ++{ ++ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), ++ sizeof(struct sun4i_req_ctx)); ++ return 0; ++} ++ ++/* sun4i_hash_init: initialize request context */ ++int sun4i_hash_init(struct ahash_request *areq) ++{ ++ const char *hash_type; ++ struct sun4i_req_ctx *op = ahash_request_ctx(areq); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); ++ struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); ++ struct sun4i_ss_alg_template *algt; ++ struct sun4i_ss_ctx *ss; ++ ++ memset(op, 0, sizeof(struct sun4i_req_ctx)); ++ ++ algt = container_of(alg, struct sun4i_ss_alg_template, alg.hash); ++ ss = algt->ss; ++ op->ss = algt->ss; ++ ++ hash_type = crypto_tfm_alg_name(areq->base.tfm); ++ ++ if (strcmp(hash_type, "sha1") == 0) ++ op->mode = SS_OP_SHA1; ++ else if (strcmp(hash_type, "md5") == 0) ++ op->mode = SS_OP_MD5; ++ else ++ return -EINVAL; ++ ++ return 0; ++} ++ ++int sun4i_hash_export_md5(struct ahash_request *areq, void *out) ++{ ++ struct sun4i_req_ctx *op = ahash_request_ctx(areq); ++ struct md5_state *octx = out; ++ int i; ++ ++ octx->byte_count = op->byte_count + op->len; ++ ++ memcpy(octx->block, op->buf, op->len); ++ ++ if (op->byte_count > 0) { ++ for (i = 0; i < 4; i++) ++ octx->hash[i] = op->hash[i]; ++ } else { ++ octx->hash[0] = SHA1_H0; ++ octx->hash[1] = SHA1_H1; ++ octx->hash[2] = SHA1_H2; ++ octx->hash[3] = SHA1_H3; ++ } ++ ++ return 0; ++} ++ ++int sun4i_hash_import_md5(struct ahash_request *areq, const void *in) ++{ ++ struct sun4i_req_ctx *op = ahash_request_ctx(areq); ++ const struct md5_state *ictx = in; ++ int i; ++ ++ op->byte_count = ictx->byte_count & ~0x3F; ++ op->len = ictx->byte_count & 0x3F; ++ ++ memcpy(op->buf, ictx->block, op->len); ++ ++ for (i = 0; i < 4; i++) ++ op->hash[i] = ictx->hash[i]; ++ ++ return 0; ++} ++ ++int sun4i_hash_export_sha1(struct ahash_request *areq, void *out) ++{ ++ struct sun4i_req_ctx *op = ahash_request_ctx(areq); ++ struct sha1_state *octx = out; ++ int i; ++ ++ octx->count = op->byte_count + op->len; ++ ++ memcpy(octx->buffer, op->buf, op->len); ++ ++ if (op->byte_count > 0) { ++ for (i = 0; i < 5; i++) ++ octx->state[i] = op->hash[i]; ++ } else { ++ octx->state[0] = SHA1_H0; ++ octx->state[1] = SHA1_H1; ++ octx->state[2] = SHA1_H2; ++ octx->state[3] = SHA1_H3; ++ octx->state[4] = SHA1_H4; ++ } ++ ++ return 0; ++} ++ ++int sun4i_hash_import_sha1(struct ahash_request *areq, const void *in) ++{ ++ struct sun4i_req_ctx *op = ahash_request_ctx(areq); ++ const struct sha1_state *ictx = in; ++ int i; ++ ++ op->byte_count = ictx->count & ~0x3F; ++ op->len = ictx->count & 0x3F; ++ ++ memcpy(op->buf, ictx->buffer, op->len); ++ ++ for (i = 0; i < 5; i++) ++ op->hash[i] = ictx->state[i]; ++ ++ return 0; ++} ++ ++/* ++ * sun4i_hash_update: update hash engine ++ * ++ * Could be used for both SHA1 and MD5 ++ * Write data by step of 32bits and put then in the SS. ++ * ++ * Since we cannot leave partial data and hash state in the engine, ++ * we need to get the hash state at the end of this function. ++ * We can get the hash state every 64 bytes ++ * ++ * So the first work is to get the number of bytes to write to SS modulo 64 ++ * The extra bytes will go to a temporary buffer op->buf storing op->len bytes ++ * ++ * So at the begin of update() ++ * if op->len + areq->nbytes < 64 ++ * => all data will be writen to wait buffer (op->buf) and end=0 ++ * if not, write all data from op->buf to the device and position end to ++ * complete to 64bytes ++ * ++ * example 1: ++ * update1 60o => op->len=60 ++ * update2 60o => need one more word to have 64 bytes ++ * end=4 ++ * so write all data from op->buf and one word of SGs ++ * write remaining data in op->buf ++ * final state op->len=56 ++ */ ++int sun4i_hash_update(struct ahash_request *areq) ++{ ++ u32 v, ivmode = 0; ++ unsigned int i = 0; ++ /* ++ * i is the total bytes read from SGs, to be compared to areq->nbytes ++ * i is important because we cannot rely on SG length since the sum of ++ * SG->length could be greater than areq->nbytes ++ */ ++ ++ struct sun4i_req_ctx *op = ahash_request_ctx(areq); ++ struct sun4i_ss_ctx *ss = op->ss; ++ unsigned int in_i = 0; /* advancement in the current SG */ ++ unsigned int end; ++ /* ++ * end is the position when we need to stop writing to the device, ++ * to be compared to i ++ */ ++ int in_r, err = 0; ++ unsigned int todo; ++ u32 spaces, rx_cnt = 32; ++ size_t copied = 0; ++ struct sg_mapping_iter mi; ++ ++ dev_dbg(ss->dev, "%s %s bc=%llu len=%u mode=%x wl=%u h0=%0x", ++ __func__, crypto_tfm_alg_name(areq->base.tfm), ++ op->byte_count, areq->nbytes, op->mode, ++ op->len, op->hash[0]); ++ ++ if (areq->nbytes == 0) ++ return 0; ++ ++ /* protect againt overflow */ ++ if (areq->nbytes > UINT_MAX - op->len) { ++ dev_err(ss->dev, "Cannot process too large request\n"); ++ return -EINVAL; ++ } ++ ++ if (op->len + areq->nbytes < 64) { ++ /* linearize data to op->buf */ ++ copied = sg_pcopy_to_buffer(areq->src, sg_nents(areq->src), ++ op->buf + op->len, areq->nbytes, 0); ++ op->len += copied; ++ return 0; ++ } ++ ++ end = ((areq->nbytes + op->len) / 64) * 64 - op->len; ++ ++ if (end > areq->nbytes || areq->nbytes - end > 63) { ++ dev_err(ss->dev, "ERROR: Bound error %u %u\n", ++ end, areq->nbytes); ++ return -EINVAL; ++ } ++ ++ spin_lock_bh(&ss->slock); ++ ++ /* ++ * if some data have been processed before, ++ * we need to restore the partial hash state ++ */ ++ if (op->byte_count > 0) { ++ ivmode = SS_IV_ARBITRARY; ++ for (i = 0; i < 5; i++) ++ writel(op->hash[i], ss->base + SS_IV0 + i * 4); ++ } ++ /* Enable the device */ ++ writel(op->mode | SS_ENABLED | ivmode, ss->base + SS_CTL); ++ ++ rx_cnt = 32; ++ i = 0; ++ sg_miter_start(&mi, areq->src, sg_nents(areq->src), ++ SG_MITER_FROM_SG | SG_MITER_ATOMIC); ++ sg_miter_next(&mi); ++ in_i = 0; ++ ++ do { ++ /* ++ * we need to linearize in two case: ++ * - the buffer is already used ++ * - the SG does not have enought byte remaining ( < 4) ++ */ ++ if (op->len > 0 || (mi.length - in_i) < 4) { ++ /* ++ * if we have entered here we have two reason to stop ++ * - the buffer is full ++ * - reach the end ++ */ ++ while (op->len < 64 && i < end) { ++ /* how many bytes we can read from current SG */ ++ in_r = min3(mi.length - in_i, end - i, ++ 64 - op->len); ++ memcpy(op->buf + op->len, mi.addr + in_i, in_r); ++ op->len += in_r; ++ i += in_r; ++ in_i += in_r; ++ if (in_i == mi.length) { ++ sg_miter_next(&mi); ++ in_i = 0; ++ } ++ } ++ if (op->len > 3 && (op->len % 4) == 0) { ++ /* write buf to the device */ ++ writesl(ss->base + SS_RXFIFO, op->buf, ++ op->len / 4); ++ op->byte_count += op->len; ++ op->len = 0; ++ } ++ } ++ if (mi.length - in_i > 3 && i < end) { ++ /* how many bytes we can read from current SG */ ++ in_r = min3(mi.length - in_i, areq->nbytes - i, ++ ((mi.length - in_i) / 4) * 4); ++ /* how many bytes we can write in the device*/ ++ todo = min3((u32)(end - i) / 4, rx_cnt, (u32)in_r / 4); ++ writesl(ss->base + SS_RXFIFO, mi.addr + in_i, todo); ++ op->byte_count += todo * 4; ++ i += todo * 4; ++ in_i += todo * 4; ++ rx_cnt -= todo; ++ if (rx_cnt == 0) { ++ spaces = readl(ss->base + SS_FCSR); ++ rx_cnt = SS_RXFIFO_SPACES(spaces); ++ } ++ if (in_i == mi.length) { ++ sg_miter_next(&mi); ++ in_i = 0; ++ } ++ } ++ } while (i < end); ++ /* final linear */ ++ if ((areq->nbytes - i) < 64) { ++ while (i < areq->nbytes && in_i < mi.length && op->len < 64) { ++ /* how many bytes we can read from current SG */ ++ in_r = min3(mi.length - in_i, areq->nbytes - i, ++ 64 - op->len); ++ memcpy(op->buf + op->len, mi.addr + in_i, in_r); ++ op->len += in_r; ++ i += in_r; ++ in_i += in_r; ++ if (in_i == mi.length) { ++ sg_miter_next(&mi); ++ in_i = 0; ++ } ++ } ++ } ++ ++ sg_miter_stop(&mi); ++ ++ writel(op->mode | SS_ENABLED | SS_DATA_END, ss->base + SS_CTL); ++ i = 0; ++ do { ++ v = readl(ss->base + SS_CTL); ++ i++; ++ } while (i < SS_TIMEOUT && (v & SS_DATA_END) > 0); ++ if (i >= SS_TIMEOUT) { ++ dev_err(ss->dev, "ERROR: hash end timeout %d>%d ctl=%x len=%u\n", ++ i, SS_TIMEOUT, v, areq->nbytes); ++ err = -EIO; ++ goto release_ss; ++ } ++ ++ /* get the partial hash only if something was written */ ++ if (op->mode == SS_OP_SHA1) { ++ for (i = 0; i < 5; i++) ++ op->hash[i] = readl(ss->base + SS_MD0 + i * 4); ++ } else { ++ for (i = 0; i < 4; i++) ++ op->hash[i] = readl(ss->base + SS_MD0 + i * 4); ++ } ++ ++release_ss: ++ writel(0, ss->base + SS_CTL); ++ spin_unlock_bh(&ss->slock); ++ return err; ++} ++ ++/* ++ * sun4i_hash_final: finalize hashing operation ++ * ++ * If we have some remaining bytes, we write them. ++ * Then ask the SS for finalizing the hashing operation ++ * ++ * I do not check RX FIFO size in this function since the size is 32 ++ * after each enabling and this function neither write more than 32 words. ++ */ ++int sun4i_hash_final(struct ahash_request *areq) ++{ ++ u32 v, ivmode = 0; ++ unsigned int i; ++ unsigned int j = 0; ++ int zeros, err = 0; ++ unsigned int index, padlen; ++ __be64 bits; ++ struct sun4i_req_ctx *op = ahash_request_ctx(areq); ++ struct sun4i_ss_ctx *ss = op->ss; ++ u32 bf[32]; ++ u32 wb = 0; ++ unsigned int nwait, nbw = 0; ++ ++ dev_dbg(ss->dev, "%s: byte=%llu len=%u mode=%x wl=%u h=%x", ++ __func__, op->byte_count, areq->nbytes, op->mode, ++ op->len, op->hash[0]); ++ ++ spin_lock_bh(&ss->slock); ++ ++ /* ++ * if we have already writed something, ++ * restore the partial hash state ++ */ ++ if (op->byte_count > 0) { ++ ivmode = SS_IV_ARBITRARY; ++ for (i = 0; i < 5; i++) ++ writel(op->hash[i], ss->base + SS_IV0 + i * 4); ++ } ++ writel(op->mode | SS_ENABLED | ivmode, ss->base + SS_CTL); ++ ++ /* write the remaining words of the wait buffer */ ++ if (op->len > 0) { ++ nwait = op->len / 4; ++ if (nwait > 0) { ++ writesl(ss->base + SS_RXFIFO, op->buf, nwait); ++ op->byte_count += 4 * nwait; ++ } ++ nbw = op->len - 4 * nwait; ++ wb = *(u32 *)(op->buf + nwait * 4); ++ wb &= (0xFFFFFFFF >> (4 - nbw) * 8); ++ } ++ ++ /* write the remaining bytes of the nbw buffer */ ++ if (nbw > 0) { ++ wb |= ((1 << 7) << (nbw * 8)); ++ bf[j++] = wb; ++ } else { ++ bf[j++] = 1 << 7; ++ } ++ ++ /* ++ * number of space to pad to obtain 64o minus 8(size) minus 4 (final 1) ++ * I take the operations from other md5/sha1 implementations ++ */ ++ ++ /* we have already send 4 more byte of which nbw data */ ++ if (op->mode == SS_OP_MD5) { ++ index = (op->byte_count + 4) & 0x3f; ++ op->byte_count += nbw; ++ if (index > 56) ++ zeros = (120 - index) / 4; ++ else ++ zeros = (56 - index) / 4; ++ } else { ++ op->byte_count += nbw; ++ index = op->byte_count & 0x3f; ++ padlen = (index < 56) ? (56 - index) : ((64 + 56) - index); ++ zeros = (padlen - 1) / 4; ++ } ++ ++ /*for (i = 0; i < zeros; i++) ++ bf[j++] = 0;*/ ++ memset(bf + j, 0, 4 * zeros); ++ j += zeros; ++ ++ /* write the length of data */ ++ if (op->mode == SS_OP_SHA1) { ++ bits = cpu_to_be64(op->byte_count << 3); ++ bf[j++] = bits & 0xffffffff; ++ bf[j++] = (bits >> 32) & 0xffffffff; ++ } else { ++ bf[j++] = (op->byte_count << 3) & 0xffffffff; ++ bf[j++] = (op->byte_count >> 29) & 0xffffffff; ++ } ++ writesl(ss->base + SS_RXFIFO, bf, j); ++ ++ /* Tell the SS to stop the hashing */ ++ writel(op->mode | SS_ENABLED | SS_DATA_END, ss->base + SS_CTL); ++ ++ /* ++ * Wait for SS to finish the hash. ++ * The timeout could happend only in case of bad overcloking ++ * or driver bug. ++ */ ++ i = 0; ++ do { ++ v = readl(ss->base + SS_CTL); ++ i++; ++ } while (i < SS_TIMEOUT && (v & SS_DATA_END) > 0); ++ if (i >= SS_TIMEOUT) { ++ dev_err(ss->dev, "ERROR: hash end timeout %d>%d ctl=%x len=%u\n", ++ i, SS_TIMEOUT, v, areq->nbytes); ++ err = -EIO; ++ goto release_ss; ++ } ++ ++ /* Get the hash from the device */ ++ if (op->mode == SS_OP_SHA1) { ++ for (i = 0; i < 5; i++) { ++ v = cpu_to_be32(readl(ss->base + SS_MD0 + i * 4)); ++ memcpy(areq->result + i * 4, &v, 4); ++ } ++ } else { ++ for (i = 0; i < 4; i++) { ++ v = readl(ss->base + SS_MD0 + i * 4); ++ memcpy(areq->result + i * 4, &v, 4); ++ } ++ } ++ ++release_ss: ++ writel(0, ss->base + SS_CTL); ++ spin_unlock_bh(&ss->slock); ++ return err; ++} ++ ++/* sun4i_hash_finup: finalize hashing operation after an update */ ++int sun4i_hash_finup(struct ahash_request *areq) ++{ ++ int err; ++ ++ err = sun4i_hash_update(areq); ++ if (err != 0) ++ return err; ++ ++ return sun4i_hash_final(areq); ++} ++ ++/* combo of init/update/final functions */ ++int sun4i_hash_digest(struct ahash_request *areq) ++{ ++ int err; ++ ++ err = sun4i_hash_init(areq); ++ if (err != 0) ++ return err; ++ ++ err = sun4i_hash_update(areq); ++ if (err != 0) ++ return err; ++ ++ return sun4i_hash_final(areq); ++} +diff --git a/drivers/crypto/sunxi-ss/sun4i-ss.h b/drivers/crypto/sunxi-ss/sun4i-ss.h +new file mode 100644 +index 0000000..6bb0ba8 +--- /dev/null ++++ b/drivers/crypto/sunxi-ss/sun4i-ss.h +@@ -0,0 +1,195 @@ ++/* ++ * sun4i-ss.h - hardware cryptographic accelerator for Allwinner A20 SoC ++ * ++ * Copyright (C) 2013-2015 Corentin LABBE ++ * ++ * Support AES cipher with 128,192,256 bits keysize. ++ * Support MD5 and SHA1 hash algorithms. ++ * Support DES and 3DES ++ * ++ * You could find the datasheet in Documentation/arm/sunxi/README ++ * ++ * Licensed under the GPL-2. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SS_CTL 0x00 ++#define SS_KEY0 0x04 ++#define SS_KEY1 0x08 ++#define SS_KEY2 0x0C ++#define SS_KEY3 0x10 ++#define SS_KEY4 0x14 ++#define SS_KEY5 0x18 ++#define SS_KEY6 0x1C ++#define SS_KEY7 0x20 ++ ++#define SS_IV0 0x24 ++#define SS_IV1 0x28 ++#define SS_IV2 0x2C ++#define SS_IV3 0x30 ++ ++#define SS_FCSR 0x44 ++ ++#define SS_MD0 0x4C ++#define SS_MD1 0x50 ++#define SS_MD2 0x54 ++#define SS_MD3 0x58 ++#define SS_MD4 0x5C ++ ++#define SS_RXFIFO 0x200 ++#define SS_TXFIFO 0x204 ++ ++/* SS_CTL configuration values */ ++ ++/* PRNG generator mode - bit 15 */ ++#define SS_PRNG_ONESHOT (0 << 15) ++#define SS_PRNG_CONTINUE (1 << 15) ++ ++/* IV mode for hash */ ++#define SS_IV_ARBITRARY (1 << 14) ++ ++/* SS operation mode - bits 12-13 */ ++#define SS_ECB (0 << 12) ++#define SS_CBC (1 << 12) ++#define SS_CTS (3 << 12) ++ ++/* Counter width for CNT mode - bits 10-11 */ ++#define SS_CNT_16BITS (0 << 10) ++#define SS_CNT_32BITS (1 << 10) ++#define SS_CNT_64BITS (2 << 10) ++ ++/* Key size for AES - bits 8-9 */ ++#define SS_AES_128BITS (0 << 8) ++#define SS_AES_192BITS (1 << 8) ++#define SS_AES_256BITS (2 << 8) ++ ++/* Operation direction - bit 7 */ ++#define SS_ENCRYPTION (0 << 7) ++#define SS_DECRYPTION (1 << 7) ++ ++/* SS Method - bits 4-6 */ ++#define SS_OP_AES (0 << 4) ++#define SS_OP_DES (1 << 4) ++#define SS_OP_3DES (2 << 4) ++#define SS_OP_SHA1 (3 << 4) ++#define SS_OP_MD5 (4 << 4) ++#define SS_OP_PRNG (5 << 4) ++ ++/* Data end bit - bit 2 */ ++#define SS_DATA_END (1 << 2) ++ ++/* PRNG start bit - bit 1 */ ++#define SS_PRNG_START (1 << 1) ++ ++/* SS Enable bit - bit 0 */ ++#define SS_DISABLED (0 << 0) ++#define SS_ENABLED (1 << 0) ++ ++/* SS_FCSR configuration values */ ++/* RX FIFO status - bit 30 */ ++#define SS_RXFIFO_FREE (1 << 30) ++ ++/* RX FIFO empty spaces - bits 24-29 */ ++#define SS_RXFIFO_SPACES(val) (((val) >> 24) & 0x3f) ++ ++/* TX FIFO status - bit 22 */ ++#define SS_TXFIFO_AVAILABLE (1 << 22) ++ ++/* TX FIFO available spaces - bits 16-21 */ ++#define SS_TXFIFO_SPACES(val) (((val) >> 16) & 0x3f) ++ ++#define SS_RXFIFO_EMP_INT_PENDING (1 << 10) ++#define SS_TXFIFO_AVA_INT_PENDING (1 << 8) ++#define SS_RXFIFO_EMP_INT_ENABLE (1 << 2) ++#define SS_TXFIFO_AVA_INT_ENABLE (1 << 0) ++ ++ ++struct sun4i_ss_ctx { ++ void __iomem *base; ++ int irq; ++ struct clk *busclk; ++ struct clk *ssclk; ++ struct device *dev; ++ struct resource *res; ++ spinlock_t slock; /* control the use of the device */ ++}; ++ ++struct sun4i_ss_alg_template { ++ u32 type; ++ union { ++ struct crypto_alg crypto; ++ struct ahash_alg hash; ++ } alg; ++ struct sun4i_ss_ctx *ss; ++}; ++ ++struct sun4i_tfm_ctx { ++ u32 key[AES_MAX_KEY_SIZE / 4];/* divided by sizeof(u32) */ ++ u32 keylen; ++ u32 keymode; ++ struct sun4i_ss_ctx *ss; ++}; ++ ++struct sun4i_cipher_req_ctx { ++ u32 mode; ++}; ++ ++struct sun4i_req_ctx { ++ u32 mode; ++ u64 byte_count; /* number of bytes "uploaded" to the device */ ++ u32 hash[5]; /* for storing SS_IVx register */ ++ char buf[64]; ++ unsigned int len; ++ struct sun4i_ss_ctx *ss; ++}; ++ ++int sun4i_hash_crainit(struct crypto_tfm *tfm); ++int sun4i_hash_init(struct ahash_request *areq); ++int sun4i_hash_update(struct ahash_request *areq); ++int sun4i_hash_final(struct ahash_request *areq); ++int sun4i_hash_finup(struct ahash_request *areq); ++int sun4i_hash_digest(struct ahash_request *areq); ++int sun4i_hash_export_md5(struct ahash_request *areq, void *out); ++int sun4i_hash_import_md5(struct ahash_request *areq, const void *in); ++int sun4i_hash_export_sha1(struct ahash_request *areq, void *out); ++int sun4i_hash_import_sha1(struct ahash_request *areq, const void *in); ++ ++int sun4i_ss_cbc_aes_encrypt(struct ablkcipher_request *areq); ++int sun4i_ss_cbc_aes_decrypt(struct ablkcipher_request *areq); ++int sun4i_ss_ecb_aes_encrypt(struct ablkcipher_request *areq); ++int sun4i_ss_ecb_aes_decrypt(struct ablkcipher_request *areq); ++ ++int sun4i_ss_cbc_des_encrypt(struct ablkcipher_request *areq); ++int sun4i_ss_cbc_des_decrypt(struct ablkcipher_request *areq); ++int sun4i_ss_ecb_des_encrypt(struct ablkcipher_request *areq); ++int sun4i_ss_ecb_des_decrypt(struct ablkcipher_request *areq); ++ ++int sun4i_ss_cbc_des3_encrypt(struct ablkcipher_request *areq); ++int sun4i_ss_cbc_des3_decrypt(struct ablkcipher_request *areq); ++int sun4i_ss_ecb_des3_encrypt(struct ablkcipher_request *areq); ++int sun4i_ss_ecb_des3_decrypt(struct ablkcipher_request *areq); ++ ++int sun4i_ss_cipher_init(struct crypto_tfm *tfm); ++int sun4i_ss_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, ++ unsigned int keylen); ++int sun4i_ss_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, ++ unsigned int keylen); ++int sun4i_ss_des3_setkey(struct crypto_ablkcipher *tfm, const u8 *key, ++ unsigned int keylen); +-- +2.3.6 + diff --git a/patch/kernel/0007-MAINTAINERS-Add-myself-as-maintainer-of-Allwinner-Se.patch b/patch/kernel/0007-MAINTAINERS-Add-myself-as-maintainer-of-Allwinner-Se.patch new file mode 100644 index 000000000..4c3dfec70 --- /dev/null +++ b/patch/kernel/0007-MAINTAINERS-Add-myself-as-maintainer-of-Allwinner-Se.patch @@ -0,0 +1,31 @@ +From 086a380119420becff42d04f01e71b84332221c6 Mon Sep 17 00:00:00 2001 +From: LABBE Corentin +Date: Sun, 19 Oct 2014 14:50:22 +0200 +Subject: [PATCH 7/8] MAINTAINERS: Add myself as maintainer of Allwinner + Security System + +Signed-off-by: LABBE Corentin +--- + MAINTAINERS | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 474bcb6..754b569 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -555,6 +555,12 @@ S: Maintained + F: Documentation/i2c/busses/i2c-ali1563 + F: drivers/i2c/busses/i2c-ali1563.c + ++ALLWINNER SECURITY SYSTEM ++M: Corentin Labbe ++L: linux-crypto@vger.kernel.org ++S: Maintained ++F: drivers/crypto/sunxi-ss/ ++ + ALPHA PORT + M: Richard Henderson + M: Ivan Kokshaysky +-- +2.3.6 + diff --git a/patch/kernel/0008-crypto-sun4i-ss-support-the-Security-System-PRNG.patch b/patch/kernel/0008-crypto-sun4i-ss-support-the-Security-System-PRNG.patch new file mode 100644 index 000000000..3d11a3666 --- /dev/null +++ b/patch/kernel/0008-crypto-sun4i-ss-support-the-Security-System-PRNG.patch @@ -0,0 +1,183 @@ +From faf8cb104cdae9dd88303fd2788128f8460bd4ca Mon Sep 17 00:00:00 2001 +From: LABBE Corentin +Date: Fri, 27 Mar 2015 10:05:19 +0100 +Subject: [PATCH 8/8] crypto: sun4i-ss: support the Security System PRNG + +The Security System have a PRNG. +This patch add support for it as an hwrng. + +Signed-off-by: LABBE Corentin +--- + drivers/crypto/Kconfig | 1 + + drivers/crypto/sunxi-ss/Makefile | 2 +- + drivers/crypto/sunxi-ss/sun4i-ss-core.c | 5 +++ + drivers/crypto/sunxi-ss/sun4i-ss-hwrng.c | 77 ++++++++++++++++++++++++++++++++ + drivers/crypto/sunxi-ss/sun4i-ss.h | 7 +++ + 5 files changed, 91 insertions(+), 1 deletion(-) + create mode 100644 drivers/crypto/sunxi-ss/sun4i-ss-hwrng.c + +diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig +index 2a5598e..979bc2a 100644 +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -467,6 +467,7 @@ config CRYPTO_DEV_SUN4I_SS + select CRYPTO_AES + select CRYPTO_DES + select CRYPTO_BLKCIPHER ++ select HW_RANDOM + help + Some Allwinner SoC have a crypto accelerator named + Security System. Select this if you want to use it. +diff --git a/drivers/crypto/sunxi-ss/Makefile b/drivers/crypto/sunxi-ss/Makefile +index 8f4c7a2..e846fe8 100644 +--- a/drivers/crypto/sunxi-ss/Makefile ++++ b/drivers/crypto/sunxi-ss/Makefile +@@ -1,2 +1,2 @@ + obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sun4i-ss.o +-sun4i-ss-y += sun4i-ss-core.o sun4i-ss-hash.o sun4i-ss-cipher.o ++sun4i-ss-y += sun4i-ss-core.o sun4i-ss-hash.o sun4i-ss-cipher.o sun4i-ss-hwrng.o +diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-core.c b/drivers/crypto/sunxi-ss/sun4i-ss-core.c +index fcb4c01..f3a410a 100644 +--- a/drivers/crypto/sunxi-ss/sun4i-ss-core.c ++++ b/drivers/crypto/sunxi-ss/sun4i-ss-core.c +@@ -331,6 +331,9 @@ static int sun4i_ss_probe(struct platform_device *pdev) + } + } + platform_set_drvdata(pdev, ss); ++ ++ sun4i_ss_hwrng_register(&ss->hwrng); ++ + return 0; + error_alg: + i--; +@@ -356,6 +359,8 @@ static int sun4i_ss_remove(struct platform_device *pdev) + int i; + struct sun4i_ss_ctx *ss = platform_get_drvdata(pdev); + ++ sun4i_ss_hwrng_remove(&ss->hwrng); ++ + for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { + switch (driver_algs[i].type) { + case CRYPTO_ALG_TYPE_ABLKCIPHER: +diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-hwrng.c b/drivers/crypto/sunxi-ss/sun4i-ss-hwrng.c +new file mode 100644 +index 0000000..0af67a8a1 +--- /dev/null ++++ b/drivers/crypto/sunxi-ss/sun4i-ss-hwrng.c +@@ -0,0 +1,77 @@ ++#include "sun4i-ss.h" ++ ++static int sun4i_ss_hwrng_init(struct hwrng *hwrng) ++{ ++ struct sun4i_ss_ctx *ss; ++ ++ ss = container_of(hwrng, struct sun4i_ss_ctx, hwrng); ++ get_random_bytes(ss->seed, SS_SEED_LEN); ++ ++ return 0; ++} ++ ++static int sun4i_ss_hwrng_read(struct hwrng *hwrng, void *buf, ++ size_t max, bool wait) ++{ ++ int i; ++ u32 v; ++ u32 *data = buf; ++ u32 mode = SS_OP_PRNG | SS_PRNG_ONESHOT | SS_ENABLED; ++ size_t len; ++ struct sun4i_ss_ctx *ss; ++ ++ ss = container_of(hwrng, struct sun4i_ss_ctx, hwrng); ++ len = min_t(size_t, SS_DATA_LEN, max); ++ ++ spin_lock_bh(&ss->slock); ++ ++ writel(mode, ss->base + SS_CTL); ++ for (i = 0; i < SS_SEED_LEN / 4; i++) ++ writel(ss->seed[i], ss->base + SS_KEY0 + i * 4); ++ writel(mode | SS_PRNG_START, ss->base + SS_CTL); ++ ++#define SS_HWRNG_TIMEOUT 30 ++ /* if we are in SS_PRNG_ONESHOT mode, wait for completion */ ++ if ((mode & SS_PRNG_CONTINUE) == 0) { ++ i = 0; ++ do { ++ v = readl(ss->base + SS_CTL); ++ i++; ++ } while (v != mode && i < SS_HWRNG_TIMEOUT); ++ if (v != mode) { ++ dev_err(ss->dev, ++ "ERROR: hwrng end timeout %d>%d ctl=%x\n", ++ i, SS_HWRNG_TIMEOUT, v); ++ len = -EFAULT; ++ goto release_ss; ++ } ++ } ++ ++ for (i = 0; i < len; i += 4) { ++ v = readl(ss->base + SS_MD0 + i); ++ *(data + i / 4) = v; ++ } ++ for (i = 0; i < SS_SEED_LEN / 4; i++) { ++ v = readl(ss->base + SS_KEY0 + i * 4); ++ ss->seed[i] = v; ++ } ++release_ss: ++ writel(0, ss->base + SS_CTL); ++ spin_unlock_bh(&ss->slock); ++ return len; ++} ++ ++int sun4i_ss_hwrng_register(struct hwrng *hwrng) ++{ ++ hwrng->name = "sunxi Security System"; ++ hwrng->init = sun4i_ss_hwrng_init; ++ hwrng->read = sun4i_ss_hwrng_read; ++ ++ /*sun4i_ss_hwrng_init(hwrng);*/ ++ return hwrng_register(hwrng); ++} ++ ++void sun4i_ss_hwrng_remove(struct hwrng *hwrng) ++{ ++ hwrng_unregister(hwrng); ++} +diff --git a/drivers/crypto/sunxi-ss/sun4i-ss.h b/drivers/crypto/sunxi-ss/sun4i-ss.h +index 6bb0ba8..2185a05 100644 +--- a/drivers/crypto/sunxi-ss/sun4i-ss.h ++++ b/drivers/crypto/sunxi-ss/sun4i-ss.h +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -120,6 +121,8 @@ + #define SS_RXFIFO_EMP_INT_ENABLE (1 << 2) + #define SS_TXFIFO_AVA_INT_ENABLE (1 << 0) + ++#define SS_SEED_LEN (160/8) ++#define SS_DATA_LEN (160 / 8) + + struct sun4i_ss_ctx { + void __iomem *base; +@@ -129,6 +132,8 @@ struct sun4i_ss_ctx { + struct device *dev; + struct resource *res; + spinlock_t slock; /* control the use of the device */ ++ struct hwrng hwrng; ++ u32 seed[SS_SEED_LEN / 4]; + }; + + struct sun4i_ss_alg_template { +@@ -193,3 +198,5 @@ int sun4i_ss_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int keylen); + int sun4i_ss_des3_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int keylen); ++int sun4i_ss_hwrng_register(struct hwrng *hwrng); ++void sun4i_ss_hwrng_remove(struct hwrng *hwrng); +-- +2.3.6 + diff --git a/patch/kernel/0009-a31_breaks.patch b/patch/kernel/0009-a31_breaks.patch new file mode 100644 index 000000000..9798ea7f5 --- /dev/null +++ b/patch/kernel/0009-a31_breaks.patch @@ -0,0 +1,21 @@ +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -541,12 +541,12 @@ + sun5i-a13-hsg-h702.dtb \ + sun5i-a13-olinuxino.dtb \ + sun5i-a13-olinuxino-micro.dtb +-dtb-$(CONFIG_MACH_SUN6I) += \ +- sun6i-a31-app4-evb1.dtb \ +- sun6i-a31-colombus.dtb \ +- sun6i-a31-hummingbird.dtb \ +- sun6i-a31-m9.dtb \ +- sun6i-a31s-cs908.dtb ++#dtb-$(CONFIG_MACH_SUN6I) += \ ++# sun6i-a31-app4-evb1.dtb \ ++# sun6i-a31-colombus.dtb \ ++# sun6i-a31-hummingbird.dtb \ ++# sun6i-a31-m9.dtb \ ++# sun6i-a31s-cs908.dtb + dtb-$(CONFIG_MACH_SUN7I) += \ + sun7i-a20-bananapi.dtb \ + sun7i-a20-pcduino3-nano.dtb \ diff --git a/patch/kernel/allwinner-audio-4.x.patch b/patch/kernel/allwinner-audio-4.x.patch new file mode 100644 index 000000000..d48738f94 --- /dev/null +++ b/patch/kernel/allwinner-audio-4.x.patch @@ -0,0 +1,1929 @@ + ARM: bcm2835: Add the DDC I2C controller to the device tree. + ARM: bcm2835: Switch to using the new clock driver support. + ARM: dts: sun6i: Add dts file for MSI Primo81 tablet + ARM: dts: sun6i: Add simplefb node labels to reference at board level + ARM: dts: sun4i: Enable audio codec on Marsboard A10. + ARM: dts: sun4i: Add dts file for the pov protab2-ips9 tablet + ARM: sun4i: Enable cubieboard audio codec + ARM: sun5i: chip: Enable the audio codec + ARM: sun4i: Enable audio-codec on Mele A1000 + ARM: sun7i: Enable cubieboard2 audio codec + ARM: sun7i: dt: enable audio codec on Cubietruck + ARM: sun7i: Add sunxi codec device node + ARM: sun5i: Add the Audio codec DT node + ARM: sun4i: Add sunxi codec device node + ARM: sun7i: Add audio codec clock + ARM: sun5i: Add audio codec clock + ARM: sun4i: Add audio codec clock + ARM: sun7i: Add audio PLL + ARM: sun5i: Add audio PLL + ARM: sun4i: Add audio PLL + ... +Diffstat +-rw-r--r-- Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt 45 +-rw-r--r-- arch/arm/boot/dts/Makefile 9 +-rw-r--r-- arch/arm/boot/dts/bcm2835-rpi-a-plus.dts 30 +-rw-r--r-- arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts 23 +-rw-r--r-- arch/arm/boot/dts/bcm2835-rpi-b.dts 8 +-rw-r--r-- arch/arm/boot/dts/bcm2835-rpi.dtsi 4 +-rw-r--r-- arch/arm/boot/dts/bcm2835.dtsi 64 +-rw-r--r-- arch/arm/boot/dts/sun4i-a10-a1000.dts 4 +-rw-r--r-- arch/arm/boot/dts/sun4i-a10-cubieboard.dts 4 +-rw-r--r-- arch/arm/boot/dts/sun4i-a10-marsboard.dts 4 +-rw-r--r-- arch/arm/boot/dts/sun4i-a10-pov-protab2-ips9.dts 199 +-rw-r--r-- arch/arm/boot/dts/sun4i-a10.dtsi 31 +-rw-r--r-- arch/arm/boot/dts/sun5i-r8-chip.dts 4 +-rw-r--r-- arch/arm/boot/dts/sun5i.dtsi 31 +-rw-r--r-- arch/arm/boot/dts/sun6i-a31.dtsi 4 +-rw-r--r-- arch/arm/boot/dts/sun6i-a31s-primo81.dts 255 +-rw-r--r-- arch/arm/boot/dts/sun6i-a31s-sina31s-core.dtsi 140 +-rw-r--r-- arch/arm/boot/dts/sun6i-a31s-sina31s.dts 153 +-rw-r--r-- arch/arm/boot/dts/sun7i-a20-cubieboard2.dts 4 +-rw-r--r-- arch/arm/boot/dts/sun7i-a20-cubietruck.dts 4 +-rw-r--r-- arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts 19 +-rw-r--r-- arch/arm/boot/dts/sun7i-a20.dtsi 31 +-rw-r--r-- drivers/clk/Makefile 2 +-rw-r--r-- drivers/clk/bcm/Makefile 1 +-rw-r--r-- drivers/clk/bcm/clk-bcm2835.c 1575 +-rw-r--r-- drivers/clk/clk-bcm2835.c 55 +-rw-r--r-- drivers/clk/clk-multiplier.c 181 +-rw-r--r-- drivers/clk/sunxi/Makefile 3 +-rw-r--r-- drivers/clk/sunxi/clk-a10-codec.c 44 +-rw-r--r-- drivers/clk/sunxi/clk-a10-mod1.c 81 +-rw-r--r-- drivers/clk/sunxi/clk-a10-pll2.c 216 +-rw-r--r-- drivers/clk/sunxi/clk-simple-gates.c 2 +-rw-r--r-- include/dt-bindings/clock/bcm2835.h 47 +-rw-r--r-- include/dt-bindings/clock/sun4i-a10-pll2.h 53 +-rw-r--r-- include/linux/clk-provider.h 42 +diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts +index 2630d78..97570cb 100644 +--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts ++++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts +@@ -93,6 +93,10 @@ + status = "okay"; + }; + ++&codec { ++ status = "okay"; ++}; ++ + &ehci0 { + status = "okay"; + }; +diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +index 046a84d..710e2ef 100644 +--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts ++++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +@@ -83,6 +83,10 @@ + status = "okay"; + }; + ++&codec { ++ status = "okay"; ++}; ++ + &cpu0 { + cpu-supply = <®_dcdc2>; + }; +diff --git a/arch/arm/boot/dts/sun4i-a10-marsboard.dts b/arch/arm/boot/dts/sun4i-a10-marsboard.dts +index 9a012db..8e50723 100644 +--- a/arch/arm/boot/dts/sun4i-a10-marsboard.dts ++++ b/arch/arm/boot/dts/sun4i-a10-marsboard.dts +@@ -91,6 +91,10 @@ + status = "okay"; + }; + ++&codec { ++ status = "okay"; ++}; ++ + &ehci0 { + status = "okay"; + }; +diff --git a/arch/arm/boot/dts/sun4i-a10-pov-protab2-ips9.dts b/arch/arm/boot/dts/sun4i-a10-pov-protab2-ips9.dts +new file mode 100644 +index 0000000..82e69c3 +--- /dev/null ++++ b/arch/arm/boot/dts/sun4i-a10-pov-protab2-ips9.dts +@@ -0,0 +1,199 @@ ++/* ++ * Copyright 2015 Hans de Goede ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This file is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++#include "sun4i-a10.dtsi" ++#include "sunxi-common-regulators.dtsi" ++#include ++#include ++#include ++#include ++ ++/ { ++ model = "Point of View Protab2-IPS9"; ++ compatible = "pov,protab2-ips9", "allwinner,sun4i-a10"; ++ ++ aliases { ++ serial0 = &uart0; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <®_dcdc2>; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins_a>; ++ status = "okay"; ++ ++ axp209: pmic@34 { ++ reg = <0x34>; ++ interrupts = <0>; ++ }; ++}; ++ ++#include "axp209.dtsi" ++ ++&i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins_a>; ++ /* pull-ups and devices require AXP209 LDO3 */ ++ status = "failed"; ++}; ++ ++&i2c2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c2_pins_a>; ++ status = "okay"; ++}; ++ ++&lradc { ++ vref-supply = <®_ldo2>; ++ status = "okay"; ++ ++ button@400 { ++ label = "Volume Up"; ++ linux,code = ; ++ channel = <0>; ++ voltage = <400000>; ++ }; ++ ++ button@800 { ++ label = "Volume Down"; ++ linux,code = ; ++ channel = <0>; ++ voltage = <800000>; ++ }; ++}; ++ ++&mmc0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>; ++ vmmc-supply = <®_vcc3v3>; ++ bus-width = <4>; ++ cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */ ++ cd-inverted; ++ status = "okay"; ++}; ++ ++&otg_sram { ++ status = "okay"; ++}; ++ ++&pio { ++ usb0_id_detect_pin: usb0_id_detect_pin@0 { ++ allwinner,pins = "PH4"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++ ++ usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 { ++ allwinner,pins = "PH5"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++}; ++ ++®_dcdc2 { ++ regulator-always-on; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1400000>; ++ regulator-name = "vdd-cpu"; ++}; ++ ++®_dcdc3 { ++ regulator-always-on; ++ regulator-min-microvolt = <1250000>; ++ regulator-max-microvolt = <1250000>; ++ regulator-name = "vdd-int-dll"; ++}; ++ ++®_ldo1 { ++ regulator-name = "vdd-rtc"; ++}; ++ ++®_ldo2 { ++ regulator-always-on; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-name = "avcc"; ++}; ++ ++®_usb0_vbus { ++ status = "okay"; ++}; ++ ++®_usb1_vbus { ++ status = "okay"; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins_a>; ++ status = "okay"; ++}; ++ ++&usb_otg { ++ dr_mode = "otg"; ++ status = "okay"; ++}; ++ ++&usbphy { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>; ++ usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ ++ usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */ ++ usb0_vbus-supply = <®_usb0_vbus>; ++ usb1_vbus-supply = <®_usb1_vbus>; ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index 1f3c51a..aa90f31 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -45,6 +45,7 @@ + + #include + ++#include + #include + #include + +@@ -195,6 +196,15 @@ + clock-output-names = "pll1"; + }; + ++ pll2: clk@01c20008 { ++ #clock-cells = <1>; ++ compatible = "allwinner,sun4i-a10-pll2-clk"; ++ reg = <0x01c20008 0x8>; ++ clocks = <&osc24M>; ++ clock-output-names = "pll2-1x", "pll2-2x", ++ "pll2-4x", "pll2-8x"; ++ }; ++ + pll4: clk@01c20018 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-pll1-clk"; +@@ -481,6 +491,14 @@ + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "spi3"; + }; ++ ++ codec_clk: clk@01c20140 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-codec-clk"; ++ reg = <0x01c20140 0x4>; ++ clocks = <&pll2 SUN4I_A10_PLL2_1X>; ++ clock-output-names = "codec"; ++ }; + }; + + soc@01c00000 { +@@ -1004,6 +1022,19 @@ + status = "disabled"; + }; + ++ codec: codec@01c22c00 { ++ #sound-dai-cells = <0>; ++ compatible = "allwinner,sun4i-a10-codec"; ++ reg = <0x01c22c00 0x40>; ++ interrupts = <30>; ++ clocks = <&apb0_gates 0>, <&codec_clk>; ++ clock-names = "apb", "codec"; ++ dmas = <&dma SUN4I_DMA_NORMAL 19>, ++ <&dma SUN4I_DMA_NORMAL 19>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; ++ + sid: eeprom@01c23800 { + compatible = "allwinner,sun4i-a10-sid"; + reg = <0x01c23800 0x10>; +diff --git a/arch/arm/boot/dts/sun5i.dtsi b/arch/arm/boot/dts/sun5i.dtsi +index 9ffee9b..59a9426 100644 +--- a/arch/arm/boot/dts/sun5i.dtsi ++++ b/arch/arm/boot/dts/sun5i.dtsi +@@ -44,6 +44,7 @@ + + #include "skeleton.dtsi" + ++#include + #include + #include + +@@ -102,6 +103,15 @@ + clock-output-names = "pll1"; + }; + ++ pll2: clk@01c20008 { ++ #clock-cells = <1>; ++ compatible = "allwinner,sun5i-a13-pll2-clk"; ++ reg = <0x01c20008 0x8>; ++ clocks = <&osc24M>; ++ clock-output-names = "pll2-1x", "pll2-2x", ++ "pll2-4x", "pll2-8x"; ++ }; ++ + pll4: clk@01c20018 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-pll1-clk"; +@@ -285,6 +295,14 @@ + clock-output-names = "usb_ohci0", "usb_phy"; + }; + ++ codec_clk: clk@01c20140 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-codec-clk"; ++ reg = <0x01c20140 0x4>; ++ clocks = <&pll2 SUN4I_A10_PLL2_1X>; ++ clock-output-names = "codec"; ++ }; ++ + mbus_clk: clk@01c2015c { + #clock-cells = <0>; + compatible = "allwinner,sun5i-a13-mbus-clk"; +@@ -571,6 +589,19 @@ + status = "disabled"; + }; + ++ codec: codec@01c22c00 { ++ #sound-dai-cells = <0>; ++ compatible = "allwinner,sun4i-a10-codec"; ++ reg = <0x01c22c00 0x40>; ++ interrupts = <30>; ++ clocks = <&apb0_gates 0>, <&codec_clk>; ++ clock-names = "apb", "codec"; ++ dmas = <&dma SUN4I_DMA_NORMAL 19>, ++ <&dma SUN4I_DMA_NORMAL 19>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; ++ + sid: eeprom@01c23800 { + compatible = "allwinner,sun4i-a10-sid"; + reg = <0x01c23800 0x10>; +diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi +index 83c1879..b6ad785 100644 +--- a/arch/arm/boot/dts/sun6i-a31.dtsi ++++ b/arch/arm/boot/dts/sun6i-a31.dtsi +@@ -61,7 +61,7 @@ + #size-cells = <1>; + ranges; + +- framebuffer@0 { ++ simplefb_hdmi: framebuffer@0 { + compatible = "allwinner,simple-framebuffer", + "simple-framebuffer"; + allwinner,pipeline = "de_be0-lcd0-hdmi"; +@@ -69,7 +69,7 @@ + status = "disabled"; + }; + +- framebuffer@1 { ++ simplefb_lcd: framebuffer@1 { + compatible = "allwinner,simple-framebuffer", + "simple-framebuffer"; + allwinner,pipeline = "de_be0-lcd0"; +diff --git a/arch/arm/boot/dts/sun6i-a31s-primo81.dts b/arch/arm/boot/dts/sun6i-a31s-primo81.dts +new file mode 100644 +index 0000000..2d4250b +--- /dev/null ++++ b/arch/arm/boot/dts/sun6i-a31s-primo81.dts +@@ -0,0 +1,255 @@ ++/* ++ * Copyright 2014 Siarhei Siamashka ++ * Copyright 2015 Karsten Merker ++ * Copyright 2015 Chen-Yu Tsai ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This file is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++#include "sun6i-a31s.dtsi" ++#include "sunxi-common-regulators.dtsi" ++ ++#include ++#include ++#include ++ ++/ { ++ model = "MSI Primo81 tablet"; ++ compatible = "msi,primo81", "allwinner,sun6i-a31s"; ++}; ++ ++&cpu0 { ++ cpu-supply = <®_dcdc3>; ++}; ++ ++&ehci0 { ++ /* rtl8188etv wifi is connected here */ ++ status = "okay"; ++}; ++ ++&i2c0 { ++ /* pull-ups and device VDDIO use AXP221 DLDO3 */ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins_a>; ++ status = "failed"; ++}; ++ ++&i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins_a>; ++ status = "okay"; ++ ++ ctp@5d { ++ pinctrl-names = "default"; ++ pinctrl-0 = <>911_int_primo81>; ++ compatible = "goodix,gt911"; ++ reg = <0x5d>; ++ interrupt-parent = <&pio>; ++ interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>; /* PA3 */ ++ }; ++}; ++ ++&i2c2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c2_pins_a>; ++ status = "okay"; ++ ++ accelerometer@1c { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mma8452_int_primo81>; ++ compatible = "fsl,mma8452"; ++ reg = <0x1c>; ++ interrupt-parent = <&pio>; ++ interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>; /* PA9 */ ++ #io-channel-cells = <1>; ++ }; ++}; ++ ++&lradc { ++ vref-supply = <®_aldo3>; ++ status = "okay"; ++ ++ button@158 { ++ label = "Volume Up"; ++ linux,code = ; ++ channel = <0>; ++ voltage = <158730>; ++ }; ++ ++ button@349 { ++ label = "Volume Down"; ++ linux,code = ; ++ channel = <0>; ++ voltage = <349206>; ++ }; ++}; ++ ++&mmc0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_primo81>; ++ vmmc-supply = <®_dcdc1>; ++ bus-width = <4>; ++ cd-gpios = <&pio 0 8 GPIO_ACTIVE_HIGH>; /* PA8 */ ++ cd-inverted; ++ status = "okay"; ++}; ++ ++&pio { ++ gt911_int_primo81: gt911_int_pin@0 { ++ allwinner,pins = "PA3"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++ ++ mma8452_int_primo81: mma8452_int_pin@0 { ++ allwinner,pins = "PA9"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++ ++ mmc0_cd_pin_primo81: mmc0_cd_pin@0 { ++ allwinner,pins = "PA8"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++}; ++ ++&p2wi { ++ status = "okay"; ++ ++ axp22x: pmic@68 { ++ compatible = "x-powers,axp221"; ++ reg = <0x68>; ++ interrupt-parent = <&nmi_intc>; ++ interrupts = <0 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ ++#include "axp22x.dtsi" ++ ++®_aldo3 { ++ regulator-always-on; ++ regulator-min-microvolt = <2700000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "avcc"; ++}; ++ ++®_dc1sw { ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-name = "vcc-lcd"; ++}; ++ ++®_dc5ldo { ++ regulator-min-microvolt = <700000>; ++ regulator-max-microvolt = <1320000>; ++ regulator-name = "vdd-cpus"; /* This is an educated guess */ ++}; ++ ++®_dcdc1 { ++ regulator-always-on; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-name = "vcc-3v0"; ++}; ++ ++®_dcdc2 { ++ regulator-min-microvolt = <700000>; ++ regulator-max-microvolt = <1320000>; ++ regulator-name = "vdd-gpu"; ++}; ++ ++®_dcdc3 { ++ regulator-always-on; ++ regulator-min-microvolt = <700000>; ++ regulator-max-microvolt = <1320000>; ++ regulator-name = "vdd-cpu"; ++}; ++ ++®_dcdc4 { ++ regulator-always-on; ++ regulator-min-microvolt = <700000>; ++ regulator-max-microvolt = <1320000>; ++ regulator-name = "vdd-sys-dll"; ++}; ++ ++®_dcdc5 { ++ regulator-always-on; ++ regulator-min-microvolt = <1500000>; ++ regulator-max-microvolt = <1500000>; ++ regulator-name = "vcc-dram"; ++}; ++ ++®_dldo1 { ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc-wifi"; ++}; ++ ++®_dldo3 { ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ regulator-name = "vddio-csi"; ++}; ++ ++®_eldo3 { ++ regulator-min-microvolt = <1080000>; ++ regulator-max-microvolt = <1320000>; ++ regulator-name = "vdd-mipi-bridge"; ++}; ++ ++&simplefb_lcd { ++ vcc-lcd-supply = <®_dc1sw>; ++ vdd-mipi-bridge-supply = <®_eldo3>; ++}; ++ ++&usb_otg { ++ /* otg support requires support for AXP221 usb-power-supply and GPIO */ ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&usbphy { ++ usb1_vbus-supply = <®_dldo1>; ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/sun6i-a31s-sina31s-core.dtsi b/arch/arm/boot/dts/sun6i-a31s-sina31s-core.dtsi +new file mode 100644 +index 0000000..ea69fb8 +--- /dev/null ++++ b/arch/arm/boot/dts/sun6i-a31s-sina31s-core.dtsi +@@ -0,0 +1,140 @@ ++/* ++ * Copyright 2015 Chen-Yu Tsai ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This file is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++#include "sun6i-a31s.dtsi" ++#include "sunxi-common-regulators.dtsi" ++ ++#include ++#include ++ ++/ { ++ model = "Sinlinx SinA31s Core Board"; ++ compatible = "sinlinx,sina31s", "allwinner,sun6i-a31s"; ++ ++ aliases { ++ serial0 = &uart0; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <®_dcdc3>; ++}; ++ ++/* eMMC on core board */ ++&mmc2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc2_8bit_emmc_pins>; ++ vmmc-supply = <®_dcdc1>; ++ bus-width = <8>; ++ non-removable; ++ status = "okay"; ++}; ++ ++/* AXP221s PMIC on core board */ ++&p2wi { ++ status = "okay"; ++ ++ axp22x: pmic@68 { ++ compatible = "x-powers,axp221"; ++ reg = <0x68>; ++ interrupt-parent = <&nmi_intc>; ++ interrupts = <0 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ ++#include "axp22x.dtsi" ++ ++®_aldo3 { ++ regulator-always-on; ++ regulator-min-microvolt = <2700000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "avcc"; ++}; ++ ++®_dc5ldo { ++ regulator-min-microvolt = <700000>; ++ regulator-max-microvolt = <1320000>; ++ regulator-name = "vdd-cpus"; ++}; ++ ++®_dcdc1 { ++ regulator-always-on; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ regulator-name = "vcc-3v0"; ++}; ++ ++®_dcdc2 { ++ regulator-min-microvolt = <700000>; ++ regulator-max-microvolt = <1320000>; ++ regulator-name = "vdd-gpu"; ++}; ++ ++®_dcdc3 { ++ regulator-always-on; ++ regulator-min-microvolt = <700000>; ++ regulator-max-microvolt = <1320000>; ++ regulator-name = "vdd-cpu"; ++}; ++ ++®_dcdc4 { ++ regulator-always-on; ++ regulator-min-microvolt = <700000>; ++ regulator-max-microvolt = <1320000>; ++ regulator-name = "vdd-sys-dll"; ++}; ++ ++®_dcdc5 { ++ regulator-always-on; ++ regulator-min-microvolt = <1500000>; ++ regulator-max-microvolt = <1500000>; ++ regulator-name = "vcc-dram"; ++}; ++ ++/* UART0 pads available on core board */ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins_a>; ++ status = "okay"; ++}; ++ +diff --git a/arch/arm/boot/dts/sun6i-a31s-sina31s.dts b/arch/arm/boot/dts/sun6i-a31s-sina31s.dts +new file mode 100644 +index 0000000..6ead2f5 +--- /dev/null ++++ b/arch/arm/boot/dts/sun6i-a31s-sina31s.dts +@@ -0,0 +1,153 @@ ++/* ++ * Copyright 2015 Chen-Yu Tsai ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This file is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/* The SinA31s development board has the SinA31s core board soldered on */ ++#include "sun6i-a31s-sina31s-core.dtsi" ++ ++#include ++ ++/ { ++ model = "Sinlinx SinA31s Development Board"; ++ compatible = "sinlinx,sina31s-sdk", "allwinner,sun6i-a31s"; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&led_pin_sina31s>; ++ ++ status { ++ label = "sina31s:status:usr"; ++ gpios = <&pio 7 13 GPIO_ACTIVE_HIGH>; /* PH13 */ ++ }; ++ }; ++}; ++ ++&ehci0 { ++ /* USB 2.0 4 port hub IC */ ++ status = "okay"; ++}; ++ ++&ehci1 { ++ status = "okay"; ++}; ++ ++&gmac { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&gmac_pins_mii_a>; ++ phy = <&phy1>; ++ phy-mode = "mii"; ++ phy-supply = <®_dldo1>; ++ status = "okay"; ++ ++ phy1: ethernet-phy@1 { ++ reg = <1>; ++ }; ++}; ++ ++&ir { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ir_pins_a>; ++ status = "okay"; ++}; ++ ++&lradc { ++ vref-supply = <®_aldo3>; ++ status = "okay"; ++ ++ button@158 { ++ label = "Volume Up"; ++ linux,code = ; ++ channel = <0>; ++ voltage = <158730>; ++ }; ++ ++ button@349 { ++ label = "Volume Down"; ++ linux,code = ; ++ channel = <0>; ++ voltage = <349206>; ++ }; ++}; ++ ++&mmc0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_sina31s>; ++ vmmc-supply = <®_dcdc1>; ++ bus-width = <4>; ++ cd-gpios = <&pio 0 4 GPIO_ACTIVE_HIGH>; /* PA4 */ ++ cd-inverted; ++ status = "okay"; ++}; ++ ++&ohci1 { ++ status = "okay"; ++}; ++ ++&pio { ++ led_pin_sina31s: led_pin@0 { ++ allwinner,pins = "PH13"; ++ allwinner,function = "gpio_out"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++ ++ mmc0_cd_pin_sina31s: mmc0_cd_pin@0 { ++ allwinner,pins = "PA4"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++}; ++ ++®_dldo1 { ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc-gmac-phy"; ++}; ++ ++&usbphy { ++ status = "okay"; ++}; +diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +index 9ff459b..1fa832d 100644 +--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts ++++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +@@ -84,6 +84,10 @@ + status = "okay"; + }; + ++&codec { ++ status = "okay"; ++}; ++ + &cpu0 { + cpu-supply = <®_dcdc2>; + }; +diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +index e6b0192..8da939a 100644 +--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts ++++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts +@@ -101,6 +101,10 @@ + status = "okay"; + }; + ++&codec { ++ status = "okay"; ++}; ++ + &cpu0 { + cpu-supply = <®_dcdc2>; + }; +diff --git a/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts b/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts +index beac431..1757a6a 100644 +--- a/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts ++++ b/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts +@@ -142,6 +142,10 @@ + status = "okay"; + }; + ++&otg_sram { ++ status = "okay"; ++}; ++ + &pio { + ahci_pwr_pin_pcduino3_nano: ahci_pwr_pin@0 { + allwinner,pins = "PH2"; +@@ -157,6 +161,13 @@ + allwinner,pull = ; + }; + ++ usb0_id_detect_pin: usb0_id_detect_pin@0 { ++ allwinner,pins = "PH4"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++ + usb1_vbus_pin_pcduino3_nano: usb1_vbus_pin@0 { + allwinner,pins = "PD2"; + allwinner,function = "gpio_out"; +@@ -211,7 +222,15 @@ + status = "okay"; + }; + ++&usb_otg { ++ dr_mode = "otg"; ++ status = "okay"; ++}; ++ + &usbphy { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb0_id_detect_pin>; ++ usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */ + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb1_vbus>; + status = "okay"; +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index 3a68852..e02eb72 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -47,6 +47,7 @@ + #include + #include + ++#include + #include + #include + +@@ -199,6 +200,15 @@ + clock-output-names = "pll1"; + }; + ++ pll2: clk@01c20008 { ++ #clock-cells = <1>; ++ compatible = "allwinner,sun4i-a10-pll2-clk"; ++ reg = <0x01c20008 0x8>; ++ clocks = <&osc24M>; ++ clock-output-names = "pll2-1x", "pll2-2x", ++ "pll2-4x", "pll2-8x"; ++ }; ++ + pll4: clk@01c20018 { + #clock-cells = <0>; + compatible = "allwinner,sun7i-a20-pll4-clk"; +@@ -491,6 +501,14 @@ + clock-output-names = "spi3"; + }; + ++ codec_clk: clk@01c20140 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-codec-clk"; ++ reg = <0x01c20140 0x4>; ++ clocks = <&pll2 SUN4I_A10_PLL2_1X>; ++ clock-output-names = "codec"; ++ }; ++ + mbus_clk: clk@01c2015c { + #clock-cells = <0>; + compatible = "allwinner,sun5i-a13-mbus-clk"; +@@ -1198,6 +1216,19 @@ + status = "disabled"; + }; + ++ codec: codec@01c22c00 { ++ #sound-dai-cells = <0>; ++ compatible = "allwinner,sun7i-a20-codec"; ++ reg = <0x01c22c00 0x40>; ++ interrupts = ; ++ clocks = <&apb0_gates 0>, <&codec_clk>; ++ clock-names = "apb", "codec"; ++ dmas = <&dma SUN4I_DMA_NORMAL 19>, ++ <&dma SUN4I_DMA_NORMAL 19>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; ++ + sid: eeprom@01c23800 { + compatible = "allwinner,sun7i-a20-sid"; + reg = <0x01c23800 0x200>; +diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile +index a381431..1ec1ce1 100644 +--- a/drivers/clk/Makefile ++++ b/drivers/clk/Makefile +@@ -6,6 +6,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-divider.o + obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o + obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o + obj-$(CONFIG_COMMON_CLK) += clk-gate.o ++obj-$(CONFIG_COMMON_CLK) += clk-multiplier.o + obj-$(CONFIG_COMMON_CLK) += clk-mux.o + obj-$(CONFIG_COMMON_CLK) += clk-composite.o + obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o +@@ -19,7 +20,6 @@ endif + obj-$(CONFIG_MACH_ASM9260) += clk-asm9260.o + obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o + obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o +-obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o + obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o + obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o + obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o +diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile +index 8a7a477..ee2349b 100644 +--- a/drivers/clk/bcm/Makefile ++++ b/drivers/clk/bcm/Makefile +@@ -3,4 +3,5 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o + obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o + obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o + obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o ++obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o + obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o +diff --git a/drivers/clk/clk-multiplier.c b/drivers/clk/clk-multiplier.c +new file mode 100644 +index 0000000..43ec269 +--- /dev/null ++++ b/drivers/clk/clk-multiplier.c +@@ -0,0 +1,181 @@ ++/* ++ * Copyright (C) 2015 Maxime Ripard ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define to_clk_multiplier(_hw) container_of(_hw, struct clk_multiplier, hw) ++ ++static unsigned long __get_mult(struct clk_multiplier *mult, ++ unsigned long rate, ++ unsigned long parent_rate) ++{ ++ if (mult->flags & CLK_MULTIPLIER_ROUND_CLOSEST) ++ return DIV_ROUND_CLOSEST(rate, parent_rate); ++ ++ return rate / parent_rate; ++} ++ ++static unsigned long clk_multiplier_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct clk_multiplier *mult = to_clk_multiplier(hw); ++ unsigned long val; ++ ++ val = clk_readl(mult->reg) >> mult->shift; ++ val &= GENMASK(mult->width - 1, 0); ++ ++ if (!val && mult->flags & CLK_MULTIPLIER_ZERO_BYPASS) ++ val = 1; ++ ++ return parent_rate * val; ++} ++ ++static bool __is_best_rate(unsigned long rate, unsigned long new, ++ unsigned long best, unsigned long flags) ++{ ++ if (flags & CLK_MULTIPLIER_ROUND_CLOSEST) ++ return abs(rate - new) < abs(rate - best); ++ ++ return new >= rate && new < best; ++} ++ ++static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate, ++ unsigned long *best_parent_rate, ++ u8 width, unsigned long flags) ++{ ++ unsigned long orig_parent_rate = *best_parent_rate; ++ unsigned long parent_rate, current_rate, best_rate = ~0; ++ unsigned int i, bestmult = 0; ++ ++ if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) ++ return rate / *best_parent_rate; ++ ++ for (i = 1; i < ((1 << width) - 1); i++) { ++ if (rate == orig_parent_rate * i) { ++ /* ++ * This is the best case for us if we have a ++ * perfect match without changing the parent ++ * rate. ++ */ ++ *best_parent_rate = orig_parent_rate; ++ return i; ++ } ++ ++ parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), ++ rate / i); ++ current_rate = parent_rate * i; ++ ++ if (__is_best_rate(rate, current_rate, best_rate, flags)) { ++ bestmult = i; ++ best_rate = current_rate; ++ *best_parent_rate = parent_rate; ++ } ++ } ++ ++ return bestmult; ++} ++ ++static long clk_multiplier_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ struct clk_multiplier *mult = to_clk_multiplier(hw); ++ unsigned long factor = __bestmult(hw, rate, parent_rate, ++ mult->width, mult->flags); ++ ++ return *parent_rate * factor; ++} ++ ++static int clk_multiplier_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct clk_multiplier *mult = to_clk_multiplier(hw); ++ unsigned long factor = __get_mult(mult, rate, parent_rate); ++ unsigned long flags = 0; ++ unsigned long val; ++ ++ if (mult->lock) ++ spin_lock_irqsave(mult->lock, flags); ++ else ++ __acquire(mult->lock); ++ ++ val = clk_readl(mult->reg); ++ val &= ~GENMASK(mult->width + mult->shift - 1, mult->shift); ++ val |= factor << mult->shift; ++ clk_writel(val, mult->reg); ++ ++ if (mult->lock) ++ spin_unlock_irqrestore(mult->lock, flags); ++ else ++ __release(mult->lock); ++ ++ return 0; ++} ++ ++const struct clk_ops clk_multiplier_ops = { ++ .recalc_rate = clk_multiplier_recalc_rate, ++ .round_rate = clk_multiplier_round_rate, ++ .set_rate = clk_multiplier_set_rate, ++}; ++EXPORT_SYMBOL_GPL(clk_multiplier_ops); ++ ++struct clk *clk_register_multiplier(struct device *dev, const char *name, ++ const char *parent_name, ++ unsigned long flags, ++ void __iomem *reg, u8 shift, u8 width, ++ u8 clk_mult_flags, spinlock_t *lock) ++{ ++ struct clk_init_data init; ++ struct clk_multiplier *mult; ++ struct clk *clk; ++ ++ mult = kmalloc(sizeof(*mult), GFP_KERNEL); ++ if (!mult) ++ return ERR_PTR(-ENOMEM); ++ ++ init.name = name; ++ init.ops = &clk_multiplier_ops; ++ init.flags = flags | CLK_IS_BASIC; ++ init.parent_names = &parent_name; ++ init.num_parents = 1; ++ ++ mult->reg = reg; ++ mult->shift = shift; ++ mult->width = width; ++ mult->flags = clk_mult_flags; ++ mult->lock = lock; ++ mult->hw.init = &init; ++ ++ clk = clk_register(dev, &mult->hw); ++ if (IS_ERR(clk)) ++ kfree(mult); ++ ++ return clk; ++} ++EXPORT_SYMBOL_GPL(clk_register_multiplier); ++ ++void clk_unregister_multiplier(struct clk *clk) ++{ ++ struct clk_multiplier *mult; ++ struct clk_hw *hw; ++ ++ hw = __clk_get_hw(clk); ++ if (!hw) ++ return; ++ ++ mult = to_clk_multiplier(hw); ++ ++ clk_unregister(clk); ++ kfree(mult); ++} ++EXPORT_SYMBOL_GPL(clk_unregister_multiplier); +diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile +index f5a35b8..cb4c299 100644 +--- a/drivers/clk/sunxi/Makefile ++++ b/drivers/clk/sunxi/Makefile +@@ -3,7 +3,10 @@ + # + + obj-y += clk-sunxi.o clk-factors.o ++obj-y += clk-a10-codec.o + obj-y += clk-a10-hosc.o ++obj-y += clk-a10-mod1.o ++obj-y += clk-a10-pll2.o + obj-y += clk-a20-gmac.o + obj-y += clk-mod0.o + obj-y += clk-simple-gates.o +diff --git a/drivers/clk/sunxi/clk-a10-codec.c b/drivers/clk/sunxi/clk-a10-codec.c +new file mode 100644 +index 0000000..ac321d6 +--- /dev/null ++++ b/drivers/clk/sunxi/clk-a10-codec.c +@@ -0,0 +1,44 @@ ++/* ++ * Copyright 2013 Emilio López ++ * ++ * Emilio López ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++ ++#define SUN4I_CODEC_GATE 31 ++ ++static void __init sun4i_codec_clk_setup(struct device_node *node) ++{ ++ struct clk *clk; ++ const char *clk_name = node->name, *parent_name; ++ void __iomem *reg; ++ ++ reg = of_io_request_and_map(node, 0, of_node_full_name(node)); ++ if (IS_ERR(reg)) ++ return; ++ ++ of_property_read_string(node, "clock-output-names", &clk_name); ++ parent_name = of_clk_get_parent_name(node, 0); ++ ++ clk = clk_register_gate(NULL, clk_name, parent_name, ++ CLK_SET_RATE_PARENT, reg, ++ SUN4I_CODEC_GATE, 0, NULL); ++ ++ if (!IS_ERR(clk)) ++ of_clk_add_provider(node, of_clk_src_simple_get, clk); ++} ++CLK_OF_DECLARE(sun4i_codec, "allwinner,sun4i-a10-codec-clk", ++ sun4i_codec_clk_setup); +diff --git a/drivers/clk/sunxi/clk-a10-mod1.c b/drivers/clk/sunxi/clk-a10-mod1.c +new file mode 100644 +index 0000000..e9d870d +--- /dev/null ++++ b/drivers/clk/sunxi/clk-a10-mod1.c +@@ -0,0 +1,81 @@ ++/* ++ * Copyright 2013 Emilio López ++ * ++ * Emilio López ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++static DEFINE_SPINLOCK(mod1_lock); ++ ++#define SUN4I_MOD1_ENABLE 31 ++#define SUN4I_MOD1_MUX 16 ++#define SUN4I_MOD1_MUX_WIDTH 2 ++#define SUN4I_MOD1_MAX_PARENTS 4 ++ ++static void __init sun4i_mod1_clk_setup(struct device_node *node) ++{ ++ struct clk *clk; ++ struct clk_mux *mux; ++ struct clk_gate *gate; ++ const char *parents[4]; ++ const char *clk_name = node->name; ++ void __iomem *reg; ++ int i; ++ ++ reg = of_io_request_and_map(node, 0, of_node_full_name(node)); ++ if (IS_ERR(reg)) ++ return; ++ ++ mux = kzalloc(sizeof(*mux), GFP_KERNEL); ++ if (!mux) ++ goto err_unmap; ++ ++ gate = kzalloc(sizeof(*gate), GFP_KERNEL); ++ if (!gate) ++ goto err_free_mux; ++ ++ of_property_read_string(node, "clock-output-names", &clk_name); ++ i = of_clk_parent_fill(node, parents, SUN4I_MOD1_MAX_PARENTS); ++ ++ gate->reg = reg; ++ gate->bit_idx = SUN4I_MOD1_ENABLE; ++ gate->lock = &mod1_lock; ++ mux->reg = reg; ++ mux->shift = SUN4I_MOD1_MUX; ++ mux->mask = BIT(SUN4I_MOD1_MUX_WIDTH) - 1; ++ mux->lock = &mod1_lock; ++ ++ clk = clk_register_composite(NULL, clk_name, parents, i, ++ &mux->hw, &clk_mux_ops, ++ NULL, NULL, ++ &gate->hw, &clk_gate_ops, 0); ++ if (IS_ERR(clk)) ++ goto err_free_gate; ++ ++ of_clk_add_provider(node, of_clk_src_simple_get, clk); ++ ++ return; ++ ++err_free_gate: ++ kfree(gate); ++err_free_mux: ++ kfree(mux); ++err_unmap: ++ iounmap(reg); ++} ++CLK_OF_DECLARE(sun4i_mod1, "allwinner,sun4i-a10-mod1-clk", ++ sun4i_mod1_clk_setup); +diff --git a/drivers/clk/sunxi/clk-a10-pll2.c b/drivers/clk/sunxi/clk-a10-pll2.c +new file mode 100644 +index 0000000..5484c31 +--- /dev/null ++++ b/drivers/clk/sunxi/clk-a10-pll2.c +@@ -0,0 +1,216 @@ ++/* ++ * Copyright 2013 Emilio López ++ * Emilio López ++ * ++ * Copyright 2015 Maxime Ripard ++ * Maxime Ripard ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define SUN4I_PLL2_ENABLE 31 ++ ++#define SUN4I_PLL2_PRE_DIV_SHIFT 0 ++#define SUN4I_PLL2_PRE_DIV_WIDTH 5 ++#define SUN4I_PLL2_PRE_DIV_MASK GENMASK(SUN4I_PLL2_PRE_DIV_WIDTH - 1, 0) ++ ++#define SUN4I_PLL2_N_SHIFT 8 ++#define SUN4I_PLL2_N_WIDTH 7 ++#define SUN4I_PLL2_N_MASK GENMASK(SUN4I_PLL2_N_WIDTH - 1, 0) ++ ++#define SUN4I_PLL2_POST_DIV_SHIFT 26 ++#define SUN4I_PLL2_POST_DIV_WIDTH 4 ++#define SUN4I_PLL2_POST_DIV_MASK GENMASK(SUN4I_PLL2_POST_DIV_WIDTH - 1, 0) ++ ++#define SUN4I_PLL2_POST_DIV_VALUE 4 ++ ++#define SUN4I_PLL2_OUTPUTS 4 ++ ++struct sun4i_pll2_data { ++ u32 post_div_offset; ++ u32 pre_div_flags; ++}; ++ ++static DEFINE_SPINLOCK(sun4i_a10_pll2_lock); ++ ++static void __init sun4i_pll2_setup(struct device_node *node, ++ struct sun4i_pll2_data *data) ++{ ++ const char *clk_name = node->name, *parent; ++ struct clk **clks, *base_clk, *prediv_clk; ++ struct clk_onecell_data *clk_data; ++ struct clk_multiplier *mult; ++ struct clk_gate *gate; ++ void __iomem *reg; ++ u32 val; ++ ++ reg = of_io_request_and_map(node, 0, of_node_full_name(node)); ++ if (IS_ERR(reg)) ++ return; ++ ++ clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); ++ if (!clk_data) ++ goto err_unmap; ++ ++ clks = kcalloc(SUN4I_PLL2_OUTPUTS, sizeof(struct clk *), GFP_KERNEL); ++ if (!clks) ++ goto err_free_data; ++ ++ parent = of_clk_get_parent_name(node, 0); ++ prediv_clk = clk_register_divider(NULL, "pll2-prediv", ++ parent, 0, reg, ++ SUN4I_PLL2_PRE_DIV_SHIFT, ++ SUN4I_PLL2_PRE_DIV_WIDTH, ++ data->pre_div_flags, ++ &sun4i_a10_pll2_lock); ++ if (!prediv_clk) { ++ pr_err("Couldn't register the prediv clock\n"); ++ goto err_free_array; ++ } ++ ++ /* Setup the gate part of the PLL2 */ ++ gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); ++ if (!gate) ++ goto err_unregister_prediv; ++ ++ gate->reg = reg; ++ gate->bit_idx = SUN4I_PLL2_ENABLE; ++ gate->lock = &sun4i_a10_pll2_lock; ++ ++ /* Setup the multiplier part of the PLL2 */ ++ mult = kzalloc(sizeof(struct clk_multiplier), GFP_KERNEL); ++ if (!mult) ++ goto err_free_gate; ++ ++ mult->reg = reg; ++ mult->shift = SUN4I_PLL2_N_SHIFT; ++ mult->width = 7; ++ mult->flags = CLK_MULTIPLIER_ZERO_BYPASS | ++ CLK_MULTIPLIER_ROUND_CLOSEST; ++ mult->lock = &sun4i_a10_pll2_lock; ++ ++ parent = __clk_get_name(prediv_clk); ++ base_clk = clk_register_composite(NULL, "pll2-base", ++ &parent, 1, ++ NULL, NULL, ++ &mult->hw, &clk_multiplier_ops, ++ &gate->hw, &clk_gate_ops, ++ CLK_SET_RATE_PARENT); ++ if (!base_clk) { ++ pr_err("Couldn't register the base multiplier clock\n"); ++ goto err_free_multiplier; ++ } ++ ++ parent = __clk_get_name(base_clk); ++ ++ /* ++ * PLL2-1x ++ * ++ * This is supposed to have a post divider, but we won't need ++ * to use it, we just need to initialise it to 4, and use a ++ * fixed divider. ++ */ ++ val = readl(reg); ++ val &= ~(SUN4I_PLL2_POST_DIV_MASK << SUN4I_PLL2_POST_DIV_SHIFT); ++ val |= (SUN4I_PLL2_POST_DIV_VALUE - data->post_div_offset) << SUN4I_PLL2_POST_DIV_SHIFT; ++ writel(val, reg); ++ ++ of_property_read_string_index(node, "clock-output-names", ++ SUN4I_A10_PLL2_1X, &clk_name); ++ clks[SUN4I_A10_PLL2_1X] = clk_register_fixed_factor(NULL, clk_name, ++ parent, ++ CLK_SET_RATE_PARENT, ++ 1, ++ SUN4I_PLL2_POST_DIV_VALUE); ++ WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_1X])); ++ ++ /* ++ * PLL2-2x ++ * ++ * This clock doesn't use the post divider, and really is just ++ * a fixed divider from the PLL2 base clock. ++ */ ++ of_property_read_string_index(node, "clock-output-names", ++ SUN4I_A10_PLL2_2X, &clk_name); ++ clks[SUN4I_A10_PLL2_2X] = clk_register_fixed_factor(NULL, clk_name, ++ parent, ++ CLK_SET_RATE_PARENT, ++ 1, 2); ++ WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_2X])); ++ ++ /* PLL2-4x */ ++ of_property_read_string_index(node, "clock-output-names", ++ SUN4I_A10_PLL2_4X, &clk_name); ++ clks[SUN4I_A10_PLL2_4X] = clk_register_fixed_factor(NULL, clk_name, ++ parent, ++ CLK_SET_RATE_PARENT, ++ 1, 1); ++ WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_4X])); ++ ++ /* PLL2-8x */ ++ of_property_read_string_index(node, "clock-output-names", ++ SUN4I_A10_PLL2_8X, &clk_name); ++ clks[SUN4I_A10_PLL2_8X] = clk_register_fixed_factor(NULL, clk_name, ++ parent, ++ CLK_SET_RATE_PARENT, ++ 2, 1); ++ WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_8X])); ++ ++ clk_data->clks = clks; ++ clk_data->clk_num = SUN4I_PLL2_OUTPUTS; ++ of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ ++ return; ++ ++err_free_multiplier: ++ kfree(mult); ++err_free_gate: ++ kfree(gate); ++err_unregister_prediv: ++ clk_unregister_divider(prediv_clk); ++err_free_array: ++ kfree(clks); ++err_free_data: ++ kfree(clk_data); ++err_unmap: ++ iounmap(reg); ++} ++ ++static struct sun4i_pll2_data sun4i_a10_pll2_data = { ++ .pre_div_flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, ++}; ++ ++static void __init sun4i_a10_pll2_setup(struct device_node *node) ++{ ++ sun4i_pll2_setup(node, &sun4i_a10_pll2_data); ++} ++ ++CLK_OF_DECLARE(sun4i_a10_pll2, "allwinner,sun4i-a10-pll2-clk", ++ sun4i_a10_pll2_setup); ++ ++static struct sun4i_pll2_data sun5i_a13_pll2_data = { ++ .post_div_offset = 1, ++}; ++ ++static void __init sun5i_a13_pll2_setup(struct device_node *node) ++{ ++ sun4i_pll2_setup(node, &sun5i_a13_pll2_data); ++} ++ ++CLK_OF_DECLARE(sun5i_a13_pll2, "allwinner,sun5i-a13-pll2-clk", ++ sun5i_a13_pll2_setup); +diff --git a/drivers/clk/sunxi/clk-simple-gates.c b/drivers/clk/sunxi/clk-simple-gates.c +index 6ce9118..0214c65 100644 +--- a/drivers/clk/sunxi/clk-simple-gates.c ++++ b/drivers/clk/sunxi/clk-simple-gates.c +@@ -128,6 +128,8 @@ CLK_OF_DECLARE(sun8i_a23_apb1, "allwinner,sun8i-a23-apb1-gates-clk", + sunxi_simple_gates_init); + CLK_OF_DECLARE(sun8i_a23_apb2, "allwinner,sun8i-a23-apb2-gates-clk", + sunxi_simple_gates_init); ++CLK_OF_DECLARE(sun8i_a33_ahb1, "allwinner,sun8i-a33-ahb1-gates-clk", ++ sunxi_simple_gates_init); + CLK_OF_DECLARE(sun9i_a80_ahb0, "allwinner,sun9i-a80-ahb0-gates-clk", + sunxi_simple_gates_init); + CLK_OF_DECLARE(sun9i_a80_ahb1, "allwinner,sun9i-a80-ahb1-gates-clk", +diff --git a/include/dt-bindings/clock/bcm2835.h b/include/dt-bindings/clock/bcm2835.h +new file mode 100644 +index 0000000..d323efa +--- /dev/null ++++ b/include/dt-bindings/clock/bcm2835.h +@@ -0,0 +1,47 @@ ++/* ++ * Copyright (C) 2015 Broadcom Corporation ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#define BCM2835_PLLA 0 ++#define BCM2835_PLLB 1 ++#define BCM2835_PLLC 2 ++#define BCM2835_PLLD 3 ++#define BCM2835_PLLH 4 ++ ++#define BCM2835_PLLA_CORE 5 ++#define BCM2835_PLLA_PER 6 ++#define BCM2835_PLLB_ARM 7 ++#define BCM2835_PLLC_CORE0 8 ++#define BCM2835_PLLC_CORE1 9 ++#define BCM2835_PLLC_CORE2 10 ++#define BCM2835_PLLC_PER 11 ++#define BCM2835_PLLD_CORE 12 ++#define BCM2835_PLLD_PER 13 ++#define BCM2835_PLLH_RCAL 14 ++#define BCM2835_PLLH_AUX 15 ++#define BCM2835_PLLH_PIX 16 ++ ++#define BCM2835_CLOCK_TIMER 17 ++#define BCM2835_CLOCK_OTP 18 ++#define BCM2835_CLOCK_UART 19 ++#define BCM2835_CLOCK_VPU 20 ++#define BCM2835_CLOCK_V3D 21 ++#define BCM2835_CLOCK_ISP 22 ++#define BCM2835_CLOCK_H264 23 ++#define BCM2835_CLOCK_VEC 24 ++#define BCM2835_CLOCK_HSM 25 ++#define BCM2835_CLOCK_SDRAM 26 ++#define BCM2835_CLOCK_TSENS 27 ++#define BCM2835_CLOCK_EMMC 28 ++#define BCM2835_CLOCK_PERI_IMAGE 29 ++ ++#define BCM2835_CLOCK_COUNT 30 +diff --git a/include/dt-bindings/clock/sun4i-a10-pll2.h b/include/dt-bindings/clock/sun4i-a10-pll2.h +new file mode 100644 +index 0000000..071c811 +--- /dev/null ++++ b/include/dt-bindings/clock/sun4i-a10-pll2.h +@@ -0,0 +1,53 @@ ++/* ++ * Copyright 2015 Maxime Ripard ++ * ++ * Maxime Ripard ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This file is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#ifndef __DT_BINDINGS_CLOCK_SUN4I_A10_PLL2_H_ ++#define __DT_BINDINGS_CLOCK_SUN4I_A10_PLL2_H_ ++ ++#define SUN4I_A10_PLL2_1X 0 ++#define SUN4I_A10_PLL2_2X 1 ++#define SUN4I_A10_PLL2_4X 2 ++#define SUN4I_A10_PLL2_8X 3 ++ ++#endif /* __DT_BINDINGS_CLOCK_SUN4I_A10_PLL2_H_ */ +diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h +index 3ecc07d..6a7dfe3 100644 +--- a/include/linux/clk-provider.h ++++ b/include/linux/clk-provider.h +@@ -518,6 +518,48 @@ struct clk *clk_register_fractional_divider(struct device *dev, + void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, + u8 clk_divider_flags, spinlock_t *lock); + ++/** ++ * struct clk_multiplier - adjustable multiplier clock ++ * ++ * @hw: handle between common and hardware-specific interfaces ++ * @reg: register containing the multiplier ++ * @shift: shift to the multiplier bit field ++ * @width: width of the multiplier bit field ++ * @lock: register lock ++ * ++ * Clock with an adjustable multiplier affecting its output frequency. ++ * Implements .recalc_rate, .set_rate and .round_rate ++ * ++ * Flags: ++ * CLK_MULTIPLIER_ZERO_BYPASS - By default, the multiplier is the value read ++ * from the register, with 0 being a valid value effectively ++ * zeroing the output clock rate. If CLK_MULTIPLIER_ZERO_BYPASS is ++ * set, then a null multiplier will be considered as a bypass, ++ * leaving the parent rate unmodified. ++ * CLK_MULTIPLIER_ROUND_CLOSEST - Makes the best calculated divider to be ++ * rounded to the closest integer instead of the down one. ++ */ ++struct clk_multiplier { ++ struct clk_hw hw; ++ void __iomem *reg; ++ u8 shift; ++ u8 width; ++ u8 flags; ++ spinlock_t *lock; ++}; ++ ++#define CLK_MULTIPLIER_ZERO_BYPASS BIT(0) ++#define CLK_MULTIPLIER_ROUND_CLOSEST BIT(1) ++ ++extern const struct clk_ops clk_multiplier_ops; ++ ++struct clk *clk_register_multiplier(struct device *dev, const char *name, ++ const char *parent_name, ++ unsigned long flags, ++ void __iomem *reg, u8 shift, u8 width, ++ u8 clk_mult_flags, spinlock_t *lock); ++void clk_unregister_multiplier(struct clk *clk); ++ + /*** + * struct clk_composite - aggregate clock of mux, divider and gate clocks + * +generated by cgit v0.11.2 at 2015-11-04 11:28:59 (GMT) diff --git a/patch/kernel/aufs3-base.patch b/patch/kernel/aufs3-base.patch new file mode 100644 index 000000000..d639d79bd --- /dev/null +++ b/patch/kernel/aufs3-base.patch @@ -0,0 +1,70 @@ +aufs3.4 base patch + +diff --git a/fs/namei.c b/fs/namei.c +index c427919..7ff959b 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -1831,7 +1831,7 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, + * needs parent already locked. Doesn't follow mounts. + * SMP-safe. + */ +-static struct dentry *lookup_hash(struct nameidata *nd) ++struct dentry *lookup_hash(struct nameidata *nd) + { + return __lookup_hash(&nd->last, nd->path.dentry, nd); + } +diff --git a/fs/splice.c b/fs/splice.c +index f847684..f871233 100644 +--- a/fs/splice.c ++++ b/fs/splice.c +@@ -1084,8 +1084,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); + /* + * Attempt to initiate a splice from pipe to file. + */ +-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, +- loff_t *ppos, size_t len, unsigned int flags) ++long do_splice_from(struct pipe_inode_info *pipe, struct file *out, ++ loff_t *ppos, size_t len, unsigned int flags) + { + ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, + loff_t *, size_t, unsigned int); +@@ -1112,9 +1112,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, + /* + * Attempt to initiate a splice from a file to a pipe. + */ +-static long do_splice_to(struct file *in, loff_t *ppos, +- struct pipe_inode_info *pipe, size_t len, +- unsigned int flags) ++long do_splice_to(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags) + { + ssize_t (*splice_read)(struct file *, loff_t *, + struct pipe_inode_info *, size_t, unsigned int); +diff --git a/include/linux/namei.h b/include/linux/namei.h +index ffc0213..ef35a31 100644 +--- a/include/linux/namei.h ++++ b/include/linux/namei.h +@@ -85,6 +85,7 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *, + extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, + int (*open)(struct inode *, struct file *)); + ++extern struct dentry *lookup_hash(struct nameidata *nd); + extern struct dentry *lookup_one_len(const char *, struct dentry *, int); + + extern int follow_down_one(struct path *); +diff --git a/include/linux/splice.h b/include/linux/splice.h +index 26e5b61..3ffef2f 100644 +--- a/include/linux/splice.h ++++ b/include/linux/splice.h +@@ -91,4 +91,10 @@ extern void splice_shrink_spd(struct pipe_inode_info *, + extern void spd_release_page(struct splice_pipe_desc *, unsigned int); + + extern const struct pipe_buf_operations page_cache_pipe_buf_ops; ++ ++extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out, ++ loff_t *ppos, size_t len, unsigned int flags); ++extern long do_splice_to(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags); + #endif diff --git a/patch/kernel/aufs3-kbuild.patch b/patch/kernel/aufs3-kbuild.patch new file mode 100644 index 000000000..345704994 --- /dev/null +++ b/patch/kernel/aufs3-kbuild.patch @@ -0,0 +1,38 @@ +aufs3.4 kbuild patch + +diff --git a/fs/Kconfig b/fs/Kconfig +index f95ae3a..6d8a9a5 100644 +--- a/fs/Kconfig ++++ b/fs/Kconfig +@@ -220,6 +220,7 @@ source "fs/pstore/Kconfig" + source "fs/sysv/Kconfig" + source "fs/ufs/Kconfig" + source "fs/exofs/Kconfig" ++source "fs/aufs/Kconfig" + + endif # MISC_FILESYSTEMS + +diff --git a/fs/Makefile b/fs/Makefile +index 2fb9779..abefac5 100644 +--- a/fs/Makefile ++++ b/fs/Makefile +@@ -125,6 +125,6 @@ + obj-y += exofs/ # Multiple modules + obj-$(CONFIG_CEPH_FS) += ceph/ + obj-$(CONFIG_PSTORE) += pstore/ +- ++obj-$(CONFIG_AUFS_FS) += aufs/ + # Patched by YAFFS + obj-$(CONFIG_YAFFS_FS) += yaffs2/ +diff --git a/include/linux/Kbuild b/include/linux/Kbuild +index 3c9b616..8704efa 100644 +--- a/include/linux/Kbuild ++++ b/include/linux/Kbuild +@@ -66,6 +66,7 @@ header-y += atmppp.h + header-y += atmsap.h + header-y += atmsvc.h + header-y += audit.h ++header-y += aufs_type.h + header-y += auto_fs.h + header-y += auto_fs4.h + header-y += auxvec.h diff --git a/patch/kernel/aufs3-mmap.patch b/patch/kernel/aufs3-mmap.patch new file mode 100644 index 000000000..30b23067d --- /dev/null +++ b/patch/kernel/aufs3-mmap.patch @@ -0,0 +1,349 @@ +aufs3.4 mmap patch + +diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c +index b1822dd..d8518aa 100644 +--- a/fs/proc/nommu.c ++++ b/fs/proc/nommu.c +@@ -45,7 +45,9 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region) + file = region->vm_file; + + if (file) { +- struct inode *inode = region->vm_file->f_path.dentry->d_inode; ++ struct inode *inode; ++ file = vmr_pr_or_file(region); ++ inode = file->f_path.dentry->d_inode; + dev = inode->i_sb->s_dev; + ino = inode->i_ino; + } +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index 1030a71..748aa74 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -225,7 +225,9 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) + const char *name = NULL; + + if (file) { +- struct inode *inode = vma->vm_file->f_path.dentry->d_inode; ++ struct inode *inode; ++ file = vma_pr_or_file(vma); ++ inode = file->f_path.dentry->d_inode; + dev = inode->i_sb->s_dev; + ino = inode->i_ino; + pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT; +@@ -1158,6 +1160,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) + seq_printf(m, "%08lx %s", vma->vm_start, buffer); + + if (file) { ++ file = vma_pr_or_file(vma); + seq_printf(m, " file="); + seq_path(m, &file->f_path, "\n\t= "); + } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { +diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c +index 74fe164..ff3ef72 100644 +--- a/fs/proc/task_nommu.c ++++ b/fs/proc/task_nommu.c +@@ -149,7 +149,9 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma, + file = vma->vm_file; + + if (file) { +- struct inode *inode = vma->vm_file->f_path.dentry->d_inode; ++ struct inode *inode; ++ file = vma_pr_or_file(file); ++ inode = file->f_path.dentry->d_inode; + dev = inode->i_sb->s_dev; + ino = inode->i_ino; + pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT; +diff --git a/include/linux/mm.h b/include/linux/mm.h +index 74aa71b..f4aabab9 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -18,6 +18,9 @@ + #include + #include + #include ++#include ++#include ++#include + + struct mempolicy; + struct anon_vma; +@@ -984,6 +987,87 @@ static inline int fixup_user_fault(struct task_struct *tsk, + } + #endif + ++/* ++ * Mainly for aufs which mmap(2) diffrent file and wants to print different path ++ * in /proc/PID/maps. ++ */ ++/* #define AUFS_DEBUG_MMAP */ ++static inline void aufs_trace(struct file *f, struct file *pr, ++ const char func[], int line, const char func2[]) ++{ ++#ifdef AUFS_DEBUG_MMAP ++ if (pr) ++ pr_info("%s:%d: %s, %p\n", func, line, func2, ++ f ? (char *)f->f_dentry->d_name.name : "(null)"); ++#endif ++} ++ ++static inline struct file *vmr_do_pr_or_file(struct vm_region *region, ++ const char func[], int line) ++{ ++ struct file *f = region->vm_file, *pr = region->vm_prfile; ++ aufs_trace(f, pr, func, line, __func__); ++ return (f && pr) ? pr : f; ++} ++ ++static inline void vmr_do_fput(struct vm_region *region, ++ const char func[], int line) ++{ ++ struct file *f = region->vm_file, *pr = region->vm_prfile; ++ aufs_trace(f, pr, func, line, __func__); ++ fput(f); ++ if (f && pr) ++ fput(pr); ++} ++ ++static inline void vma_do_file_update_time(struct vm_area_struct *vma, ++ const char func[], int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ aufs_trace(f, pr, func, line, __func__); ++ file_update_time(f); ++ if (f && pr) ++ file_update_time(pr); ++} ++ ++static inline struct file *vma_do_pr_or_file(struct vm_area_struct *vma, ++ const char func[], int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ aufs_trace(f, pr, func, line, __func__); ++ return (f && pr) ? pr : f; ++} ++ ++static inline void vma_do_get_file(struct vm_area_struct *vma, ++ const char func[], int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ aufs_trace(f, pr, func, line, __func__); ++ get_file(f); ++ if (f && pr) ++ get_file(pr); ++} ++ ++static inline void vma_do_fput(struct vm_area_struct *vma, ++ const char func[], int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ aufs_trace(f, pr, func, line, __func__); ++ fput(f); ++ if (f && pr) ++ fput(pr); ++} ++ ++#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \ ++ __LINE__) ++#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__) ++#define vma_file_update_time(vma) vma_do_file_update_time(vma, __func__, \ ++ __LINE__) ++#define vma_pr_or_file(vma) vma_do_pr_or_file(vma, __func__, \ ++ __LINE__) ++#define vma_get_file(vma) vma_do_get_file(vma, __func__, __LINE__) ++#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__) ++ + extern int make_pages_present(unsigned long addr, unsigned long end); + extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); + extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, +diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h +index 3cc3062..9742239 100644 +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -185,6 +185,7 @@ struct vm_region { + unsigned long vm_top; /* region allocated to here */ + unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */ + struct file *vm_file; /* the backing file or NULL */ ++ struct file *vm_prfile; /* the virtual backing file or NULL */ + + int vm_usage; /* region usage count (access under nommu_region_sem) */ + bool vm_icache_flushed : 1; /* true if the icache has been flushed for +@@ -244,6 +245,7 @@ struct vm_area_struct { + unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE + units, *not* PAGE_CACHE_SIZE */ + struct file * vm_file; /* File we map to (can be NULL). */ ++ struct file *vm_prfile; /* shadow of vm_file */ + void * vm_private_data; /* was vm_pte (shared mem) */ + + #ifndef CONFIG_MMU +diff --git a/kernel/fork.c b/kernel/fork.c +index 687a15d..fe47fd0 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -381,7 +381,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) + struct inode *inode = file->f_path.dentry->d_inode; + struct address_space *mapping = file->f_mapping; + +- get_file(file); ++ vma_get_file(tmp); + if (tmp->vm_flags & VM_DENYWRITE) + atomic_dec(&inode->i_writecount); + mutex_lock(&mapping->i_mmap_mutex); +diff --git a/mm/fremap.c b/mm/fremap.c +index 9ed4fd4..00ee66b 100644 +--- a/mm/fremap.c ++++ b/mm/fremap.c +@@ -198,10 +198,10 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, + struct file *file = vma->vm_file; + + flags &= MAP_NONBLOCK; +- get_file(file); ++ vma_get_file(vma); + addr = mmap_region(file, start, size, + flags, vma->vm_flags, pgoff); +- fput(file); ++ vma_fput(vma); + if (IS_ERR_VALUE(addr)) { + err = addr; + } else { +diff --git a/mm/memory.c b/mm/memory.c +index 6105f47..9bdc45d 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -2652,7 +2652,7 @@ reuse: + + /* file_update_time outside page_lock */ + if (vma->vm_file) +- file_update_time(vma->vm_file); ++ vma_file_update_time(vma); + + return ret; + } +@@ -3337,7 +3337,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, + + /* file_update_time outside page_lock */ + if (vma->vm_file) +- file_update_time(vma->vm_file); ++ vma_file_update_time(vma); + } else { + unlock_page(vmf.page); + if (anon) +diff --git a/mm/mmap.c b/mm/mmap.c +index 848ef52..423d68f 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -231,7 +231,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) + if (vma->vm_ops && vma->vm_ops->close) + vma->vm_ops->close(vma); + if (vma->vm_file) { +- fput(vma->vm_file); ++ vma_fput(vma); + if (vma->vm_flags & VM_EXECUTABLE) + removed_exe_file_vma(vma->vm_mm); + } +@@ -619,7 +619,7 @@ again: remove_next = 1 + (end > next->vm_end); + + if (remove_next) { + if (file) { +- fput(file); ++ vma_fput(vma); + if (next->vm_flags & VM_EXECUTABLE) + removed_exe_file_vma(mm); + } +@@ -1376,8 +1376,8 @@ out: + unmap_and_free_vma: + if (correct_wcount) + atomic_inc(&inode->i_writecount); ++ vma_fput(vma); + vma->vm_file = NULL; +- fput(file); + + /* Undo any partial mapping done by a device driver. */ + unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); +@@ -1998,7 +1998,7 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, + goto out_free_mpol; + + if (new->vm_file) { +- get_file(new->vm_file); ++ vma_get_file(new); + if (vma->vm_flags & VM_EXECUTABLE) + added_exe_file_vma(mm); + } +@@ -2022,7 +2022,7 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, + if (new->vm_file) { + if (vma->vm_flags & VM_EXECUTABLE) + removed_exe_file_vma(mm); +- fput(new->vm_file); ++ vma_fput(new); + } + unlink_anon_vmas(new); + out_free_mpol: +@@ -2420,7 +2420,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, + new_vma->vm_end = addr + len; + new_vma->vm_pgoff = pgoff; + if (new_vma->vm_file) { +- get_file(new_vma->vm_file); ++ vma_get_file(new_vma); + if (vma->vm_flags & VM_EXECUTABLE) + added_exe_file_vma(mm); + } +diff --git a/mm/msync.c b/mm/msync.c +index 632df45..02d770e 100644 +--- a/mm/msync.c ++++ b/mm/msync.c +@@ -80,10 +80,10 @@ SYSCALL_DEFINE3(msync, unsigned long, start, size_t, len, int, flags) + start = vma->vm_end; + if ((flags & MS_SYNC) && file && + (vma->vm_flags & VM_SHARED)) { +- get_file(file); ++ vma_get_file(vma); + up_read(&mm->mmap_sem); + error = vfs_fsync(file, 0); +- fput(file); ++ vma_fput(vma); + if (error || start >= end) + goto out; + down_read(&mm->mmap_sem); +diff --git a/mm/nommu.c b/mm/nommu.c +index bb8f4f0..2bc7252 100644 +--- a/mm/nommu.c ++++ b/mm/nommu.c +@@ -632,7 +632,7 @@ static void __put_nommu_region(struct vm_region *region) + up_write(&nommu_region_sem); + + if (region->vm_file) +- fput(region->vm_file); ++ vmr_fput(region); + + /* IO memory and memory shared directly out of the pagecache + * from ramfs/tmpfs mustn't be released here */ +@@ -790,7 +790,7 @@ static void delete_vma(struct mm_struct *mm, struct vm_area_struct *vma) + if (vma->vm_ops && vma->vm_ops->close) + vma->vm_ops->close(vma); + if (vma->vm_file) { +- fput(vma->vm_file); ++ vma_fput(vma); + if (vma->vm_flags & VM_EXECUTABLE) + removed_exe_file_vma(mm); + } +@@ -1363,7 +1363,7 @@ static unsigned long do_mmap_pgoff(struct file *file, + goto error_just_free; + } + } +- fput(region->vm_file); ++ vmr_fput(region); + kmem_cache_free(vm_region_jar, region); + region = pregion; + result = start; +@@ -1439,10 +1439,10 @@ error_just_free: + up_write(&nommu_region_sem); + error: + if (region->vm_file) +- fput(region->vm_file); ++ vmr_fput(region); + kmem_cache_free(vm_region_jar, region); + if (vma->vm_file) +- fput(vma->vm_file); ++ vma_fput(vma); + if (vma->vm_flags & VM_EXECUTABLE) + removed_exe_file_vma(vma->vm_mm); + kmem_cache_free(vm_area_cachep, vma); diff --git a/patch/kernel/aufs3-standalone.patch b/patch/kernel/aufs3-standalone.patch new file mode 100644 index 000000000..67cd853bd --- /dev/null +++ b/patch/kernel/aufs3-standalone.patch @@ -0,0 +1,257 @@ +aufs3.4 standalone patch + +diff --git a/fs/file_table.c b/fs/file_table.c +index 70f2a0f..146a3d7 100644 +--- a/fs/file_table.c ++++ b/fs/file_table.c +@@ -442,6 +442,8 @@ void file_sb_list_del(struct file *file) + } + } + ++EXPORT_SYMBOL(file_sb_list_del); ++ + #ifdef CONFIG_SMP + + /* +diff --git a/fs/inode.c b/fs/inode.c +index 9f4f5fe..bb0f3ba 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -56,6 +56,7 @@ static struct hlist_head *inode_hashtable __read_mostly; + static __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_hash_lock); + + __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_sb_list_lock); ++EXPORT_SYMBOL(inode_sb_list_lock); + + /* + * Empty aops. Can be used for the cases where the user does not +diff --git a/fs/namei.c b/fs/namei.c +index 7ff959b..b170167 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -1835,6 +1835,7 @@ struct dentry *lookup_hash(struct nameidata *nd) + { + return __lookup_hash(&nd->last, nd->path.dentry, nd); + } ++EXPORT_SYMBOL(lookup_hash); + + /** + * lookup_one_len - filesystem helper to lookup single pathname component +diff --git a/fs/namespace.c b/fs/namespace.c +index e608199..38fcc2e 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1339,6 +1339,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, + } + return 0; + } ++EXPORT_SYMBOL(iterate_mounts); + + static void cleanup_group_ids(struct mount *mnt, struct mount *end) + { +diff --git a/fs/notify/group.c b/fs/notify/group.c +index 63fc294..6f4adca 100644 +--- a/fs/notify/group.c ++++ b/fs/notify/group.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + #include + #include "fsnotify.h" +@@ -70,6 +71,7 @@ void fsnotify_put_group(struct fsnotify_group *group) + if (atomic_dec_and_test(&group->refcnt)) + fsnotify_destroy_group(group); + } ++EXPORT_SYMBOL(fsnotify_put_group); + + /* + * Create a new fsnotify_group and hold a reference for the group returned. +@@ -102,3 +104,4 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops) + + return group; + } ++EXPORT_SYMBOL(fsnotify_alloc_group); +diff --git a/fs/notify/mark.c b/fs/notify/mark.c +index f104d56..54f36db 100644 +--- a/fs/notify/mark.c ++++ b/fs/notify/mark.c +@@ -112,6 +112,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark) + if (atomic_dec_and_test(&mark->refcnt)) + mark->free_mark(mark); + } ++EXPORT_SYMBOL(fsnotify_put_mark); + + /* + * Any time a mark is getting freed we end up here. +@@ -191,6 +192,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark) + if (unlikely(atomic_dec_and_test(&group->num_marks))) + fsnotify_final_destroy_group(group); + } ++EXPORT_SYMBOL(fsnotify_destroy_mark); + + void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask) + { +@@ -278,6 +280,7 @@ err: + + return ret; + } ++EXPORT_SYMBOL(fsnotify_add_mark); + + /* + * clear any marks in a group in which mark->flags & flags is true +@@ -333,6 +336,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark, + atomic_set(&mark->refcnt, 1); + mark->free_mark = free_mark; + } ++EXPORT_SYMBOL(fsnotify_init_mark); + + static int fsnotify_mark_destroy(void *ignored) + { +diff --git a/fs/open.c b/fs/open.c +index 5720854..ec59242 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -60,6 +60,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, + mutex_unlock(&dentry->d_inode->i_mutex); + return ret; + } ++EXPORT_SYMBOL(do_truncate); + + static long do_sys_truncate(const char __user *pathname, loff_t length) + { +diff --git a/fs/splice.c b/fs/splice.c +index f871233..70f5481 100644 +--- a/fs/splice.c ++++ b/fs/splice.c +@@ -1108,6 +1108,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out, + + return splice_write(pipe, out, ppos, len, flags); + } ++EXPORT_SYMBOL(do_splice_from); + + /* + * Attempt to initiate a splice from a file to a pipe. +@@ -1134,6 +1135,7 @@ long do_splice_to(struct file *in, loff_t *ppos, + + return splice_read(in, ppos, pipe, len, flags); + } ++EXPORT_SYMBOL(do_splice_to); + + /** + * splice_direct_to_actor - splices data directly between two non-pipes +diff --git a/security/commoncap.c b/security/commoncap.c +index 71a166a..5d63aac 100644 +--- a/security/commoncap.c ++++ b/security/commoncap.c +@@ -972,3 +972,4 @@ int cap_file_mmap(struct file *file, unsigned long reqprot, + } + return ret; + } ++EXPORT_SYMBOL(cap_file_mmap); +diff --git a/security/device_cgroup.c b/security/device_cgroup.c +index c43a332..0c37289 100644 +--- a/security/device_cgroup.c ++++ b/security/device_cgroup.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -499,6 +500,7 @@ found: + + return -EPERM; + } ++EXPORT_SYMBOL(__devcgroup_inode_permission); + + int devcgroup_inode_mknod(int mode, dev_t dev) + { +diff --git a/security/security.c b/security/security.c +index bf619ff..60b996a 100644 +--- a/security/security.c ++++ b/security/security.c +@@ -380,6 +380,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry) + return 0; + return security_ops->path_rmdir(dir, dentry); + } ++EXPORT_SYMBOL(security_path_rmdir); + + int security_path_unlink(struct path *dir, struct dentry *dentry) + { +@@ -396,6 +397,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry, + return 0; + return security_ops->path_symlink(dir, dentry, old_name); + } ++EXPORT_SYMBOL(security_path_symlink); + + int security_path_link(struct dentry *old_dentry, struct path *new_dir, + struct dentry *new_dentry) +@@ -404,6 +406,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir, + return 0; + return security_ops->path_link(old_dentry, new_dir, new_dentry); + } ++EXPORT_SYMBOL(security_path_link); + + int security_path_rename(struct path *old_dir, struct dentry *old_dentry, + struct path *new_dir, struct dentry *new_dentry) +@@ -422,6 +425,7 @@ int security_path_truncate(struct path *path) + return 0; + return security_ops->path_truncate(path); + } ++EXPORT_SYMBOL(security_path_truncate); + + int security_path_chmod(struct path *path, umode_t mode) + { +@@ -429,6 +433,7 @@ int security_path_chmod(struct path *path, umode_t mode) + return 0; + return security_ops->path_chmod(path, mode); + } ++EXPORT_SYMBOL(security_path_chmod); + + int security_path_chown(struct path *path, uid_t uid, gid_t gid) + { +@@ -436,6 +441,7 @@ int security_path_chown(struct path *path, uid_t uid, gid_t gid) + return 0; + return security_ops->path_chown(path, uid, gid); + } ++EXPORT_SYMBOL(security_path_chown); + + int security_path_chroot(struct path *path) + { +@@ -512,6 +518,7 @@ int security_inode_readlink(struct dentry *dentry) + return 0; + return security_ops->inode_readlink(dentry); + } ++EXPORT_SYMBOL(security_inode_readlink); + + int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd) + { +@@ -526,6 +533,7 @@ int security_inode_permission(struct inode *inode, int mask) + return 0; + return security_ops->inode_permission(inode, mask); + } ++EXPORT_SYMBOL(security_inode_permission); + + int security_inode_setattr(struct dentry *dentry, struct iattr *attr) + { +@@ -641,6 +649,7 @@ int security_file_permission(struct file *file, int mask) + + return fsnotify_perm(file, mask); + } ++EXPORT_SYMBOL(security_file_permission); + + int security_file_alloc(struct file *file) + { +@@ -668,6 +677,7 @@ int security_file_mmap(struct file *file, unsigned long reqprot, + return ret; + return ima_file_mmap(file, prot); + } ++EXPORT_SYMBOL(security_file_mmap); + + int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, + unsigned long prot) diff --git a/patch/bananagmac.patch b/patch/kernel/banana-default/banana_ethernet_driver.patch similarity index 100% rename from patch/bananagmac.patch rename to patch/kernel/banana-default/banana_ethernet_driver.patch diff --git a/patch/kernel/banana-default/debian_packaging-fix.patch b/patch/kernel/banana-default/debian_packaging-fix.patch new file mode 100644 index 000000000..e528e0f2b --- /dev/null +++ b/patch/kernel/banana-default/debian_packaging-fix.patch @@ -0,0 +1,65 @@ +--- a/scripts/package/builddeb ++++ b/scripts/package/builddeb +@@ -81,10 +81,10 @@ fwdir="$objtree/debian/fwtmp" + kernel_headers_dir="$objtree/debian/hdrtmp" + libc_headers_dir="$objtree/debian/headertmp" + dbg_dir="$objtree/debian/dbgtmp" +-packagename=linux-image-$version +-fwpackagename=linux-firmware-image-$version +-kernel_headers_packagename=linux-headers-$version +-libc_headers_packagename=linux-libc-dev ++packagename=linux-image"$LOCALVERSION" ++fwpackagename=linux-firmware-image"$LOCALVERSION" ++kernel_headers_packagename=linux-headers"$LOCALVERSION" ++libc_headers_packagename=linux-libc-dev"$LOCALVERSION" + dbg_packagename=$packagename-dbg + + if [ "$ARCH" = "um" ] ; then +@@ -177,7 +177,7 @@ fi + + if [ "$ARCH" != "um" ]; then + $MAKE headers_check KBUILD_SRC= +- $MAKE headers_install KBUILD_SRC= INSTALL_HDR_PATH="$libc_headers_dir/usr" ++ #$MAKE headers_install KBUILD_SRC= INSTALL_HDR_PATH="$libc_headers_dir/usr" + fi + + # Install the maintainer scripts +@@ -213,10 +213,25 @@ done + ## + ## Create sym link to kernel image + ## +-kernel_tmp_version="${installed_image_path////\\/}" +-sed -e "s/exit 0/ln -sf \/$kernel_tmp_version \/boot\/zImage/g" -i $tmpdir/DEBIAN/postinst +-echo "rm -f /boot/.next" >> $tmpdir/DEBIAN/postinst +-echo "exit 0" >> $tmpdir/DEBIAN/postinst ++sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/postinst ++cat >> $tmpdir/DEBIAN/postinst < /dev/null 2>&1 ++rm -f /$installed_image_path /boot/zImage ++else ++ln -sf /$installed_image_path /boot/zImage > /dev/null 2>&1 || mv /$installed_image_path /boot/zImage ++fi ++rm -f /boot/.next ++exit 0 ++EOT ++## ++## FAT install workaround ++## ++sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/preinst ++cat >> $tmpdir/DEBIAN/preinst <> $tmpdir/DEBIAN/preinst + + # Try to determine maintainer and email values + if [ -n "$DEBEMAIL" ]; then +@@ -359,7 +374,7 @@ EOF + + if [ "$ARCH" != "um" ]; then + create_package "$kernel_headers_packagename" "$kernel_headers_dir" +- create_package "$libc_headers_packagename" "$libc_headers_dir" ++ #create_package "$libc_headers_packagename" "$libc_headers_dir" + fi + + create_package "$packagename" "$tmpdir" diff --git a/patch/kernel/banana-default/i2s_spdif_driver.patch b/patch/kernel/banana-default/i2s_spdif_driver.patch new file mode 100644 index 000000000..6f94dad88 --- /dev/null +++ b/patch/kernel/banana-default/i2s_spdif_driver.patch @@ -0,0 +1,2955 @@ +--- a/include/sound/pcm.h ++++ b/include/sound/pcm.h +@@ -124,6 +124,10 @@ struct snd_pcm_ops { + #define SNDRV_PCM_RATE_96000 (1<<10) /* 96000Hz */ + #define SNDRV_PCM_RATE_176400 (1<<11) /* 176400Hz */ + #define SNDRV_PCM_RATE_192000 (1<<12) /* 192000Hz */ ++#define SNDRV_PCM_RATE_352800 (1<<13) /* 352800Hz */ ++#define SNDRV_PCM_RATE_384000 (1<<14) /* 384000Hz */ ++#define SNDRV_PCM_RATE_705600 (1<<15) /* 705600Hz */ ++#define SNDRV_PCM_RATE_768000 (1<<16) /* 768000Hz */ + + #define SNDRV_PCM_RATE_CONTINUOUS (1<<30) /* continuous range */ + #define SNDRV_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */ +@@ -136,6 +140,10 @@ struct snd_pcm_ops { + SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000) + #define SNDRV_PCM_RATE_8000_192000 (SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\ + SNDRV_PCM_RATE_192000) ++#define SNDRV_PCM_RATE_8000_384000 (SNDRV_PCM_RATE_8000_192000|SNDRV_PCM_RATE_352800|\ ++ SNDRV_PCM_RATE_384000) ++#define SNDRV_PCM_RATE_8000_768000 (SNDRV_PCM_RATE_8000_384000|SNDRV_PCM_RATE_705600|\ ++ SNDRV_PCM_RATE_768000) + #define _SNDRV_PCM_FMTBIT(fmt) (1ULL << (__force int)SNDRV_PCM_FORMAT_##fmt) + #define SNDRV_PCM_FMTBIT_S8 _SNDRV_PCM_FMTBIT(S8) + #define SNDRV_PCM_FMTBIT_U8 _SNDRV_PCM_FMTBIT(U8) + +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -1382,8 +1382,6 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state) + if (! snd_pcm_playback_empty(substream)) { + snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING); + snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING); +- } else { +- runtime->status->state = SNDRV_PCM_STATE_SETUP; + } + break; + case SNDRV_PCM_STATE_RUNNING: +@@ -1765,12 +1763,13 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, + return snd_interval_refine(hw_param_interval(params, rule->var), &t); + } + +-#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12 ++#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_768000 != 1 << 16 + #error "Change this table" + #endif + + static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, +- 48000, 64000, 88200, 96000, 176400, 192000 }; ++ 48000, 64000, 88200, 96000, 176400, 192000, ++ 352800, 384000, 705600, 768000 }; + + const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { + .count = ARRAY_SIZE(rates), + +--- a/sound/soc/sunxi/i2s/sndi2s.c ++++ b/sound/soc/sunxi/i2s/sndi2s.c +@@ -40,7 +40,8 @@ static int sunxi_i2s_slave = 0; + #define sndi2s_RATES_MASTER (SNDRV_PCM_RATE_8000_192000|SNDRV_PCM_RATE_KNOT) + #define sndi2s_RATES_SLAVE (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\ +- SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) ++ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000|\ ++ SNDRV_PCM_RATE_352800 | SNDRV_PCM_RATE_384000) + + #if defined CONFIG_ARCH_SUN7I + #define sndi2s_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) +@@ -49,10 +50,6 @@ static int sunxi_i2s_slave = 0; + SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_LE) + #endif + +-/* cleaning code +-hdmi_audio_t hdmi_parameter; +-*/ +- + static int sndi2s_mute(struct snd_soc_dai *dai, int mute) + { + return 0; +@@ -74,26 +71,6 @@ static int sndi2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) + { +-/* +- switch (params_format(params)) +- { +- case SNDRV_PCM_FORMAT_S16_LE: +- printk("[IIS-0] sndi2s_hw_params: format 16 bit\n"); +- break; +- case SNDRV_PCM_FORMAT_S20_3LE: +- printk("[IIS-0] sndi2s_hw_params: format 20 bit in 3 bytes\n"); +- break; +- case SNDRV_PCM_FORMAT_S24_LE: +- printk("[IIS-0] sndi2s_hw_params: format 24 bit in 4 bytes\n"); +- break; +- default: +- printk("[IIS-0] sndi2s_hw_params: Unsupported format (%d)\n", (int)params_format(params)); +- //return -EINVAL; +- } +-*/ +-/* cleaning code +- hdmi_parameter.sample_rate = params_rate(params); +-*/ + return 0; + } + +@@ -105,18 +82,12 @@ static int sndi2s_set_dai_sysclk(struct snd_soc_dai *codec_dai, + + static int sndi2s_set_dai_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div) + { +-/* cleaning code +- hdmi_parameter.fs_between = div; +-*/ + return 0; + } + + static int sndi2s_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) + { +-/* +- printk("[IIS-0] sndi2s_set_dai_fmt: format (%u)\n", fmt); +-*/ + return 0; + } + +@@ -140,6 +111,13 @@ struct snd_soc_dai_driver sndi2s_dai = { + .rates = sndi2s_RATES_MASTER, + .formats = sndi2s_FORMATS, + }, ++ .capture = { ++ .stream_name = "Capture", ++ .channels_min = 1, ++ .channels_max = 2, ++ .rates = sndi2s_RATES_MASTER, ++ .formats = sndi2s_FORMATS, ++ }, + /* pcm operations */ + .ops = &sndi2s_dai_ops, + .symmetric_rates = 1, +@@ -176,6 +154,7 @@ static int __devinit sndi2s_codec_probe(struct platform_device *pdev) + { + if(sunxi_i2s_slave) { + sndi2s_dai.playback.rates = sndi2s_RATES_SLAVE; ++ sndi2s_dai.capture.rates = sndi2s_RATES_SLAVE; + printk("[I2S-0] sndi2s_codec_probe I2S used in slave mode\n"); + } + else +@@ -210,7 +189,7 @@ static int __init sndi2s_codec_init(void) + + ret = script_parser_fetch("i2s_para","i2s_used", &i2s_used, sizeof(int)); + if (ret) { +- printk("[I2S]sndi2s_init fetch i2s using configuration failed\n"); ++ printk("[I2S-0] sndi2s_init fetch i2s using configuration failed\n"); + } + + if (i2s_used) { +@@ -230,7 +209,7 @@ static int __init sndi2s_codec_init(void) + if ((err = platform_driver_register(&sndi2s_codec_driver)) < 0) + return err; + } else { +- printk("[I2S]sndi2s cannot find any using configuration for controllers, return directly!\n"); ++ printk("[I2S-0] sndi2s cannot find any using configuration for controllers, return directly!\n"); + return 0; + } + +--- a/sound/soc/sunxi/i2s/sunxi-i2s.c ++++ b/sound/soc/sunxi/i2s/sunxi-i2s.c +@@ -38,7 +38,7 @@ + #include "sunxi-i2sdma.h" + #include "sunxi-i2s.h" + +-static int regsave[8]; ++static int regsave[10]; + static int i2s_used = 0; + + static struct sunxi_dma_params sunxi_i2s_pcm_stereo_out = { +@@ -66,7 +66,8 @@ static struct clk *i2s_apbclk, *i2s_pll2clk, *i2s_pllx8, *i2s_moduleclk; + void sunxi_snd_txctrl_i2s(struct snd_pcm_substream *substream, int on) + { + u32 reg_val; +- /*printk("[I2S-0] sunxi_snd_txctrl_i2s\n");*/ ++ int res; ++ printk("[I2S-0] sunxi_snd_txctrl_i2s is on=(%d)\n", on); + + reg_val = readl(sunxi_iis.regs + SUNXI_TXCHSEL); + reg_val &= ~0x7; +@@ -146,14 +147,13 @@ void sunxi_snd_txctrl_i2s(struct snd_pcm_substream *substream, int on) + reg_val |= SUNXI_IISINT_TXDRQEN; + writel(reg_val, sunxi_iis.regs + SUNXI_IISINT); + +- //Global Enable Digital Audio Interface +- reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); +- if(sunxi_iis.slave) +- reg_val |= SUNXI_IISCTL_MS; // 1: Slave! +- reg_val |= SUNXI_IISCTL_GEN; +- writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); ++ //Disable mute ++ res = gpio_write_one_pin_value(i2s_handle, 0, "i2s_mute"); + + } else { ++ //Enable mute ++ res = gpio_write_one_pin_value(i2s_handle, 1, "i2s_mute"); ++ + /* IIS TX DISABLE */ + reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); + reg_val &= ~SUNXI_IISCTL_TXEN; +@@ -163,18 +163,27 @@ void sunxi_snd_txctrl_i2s(struct snd_pcm_substream *substream, int on) + reg_val = readl(sunxi_iis.regs + SUNXI_IISINT); + reg_val &= ~SUNXI_IISINT_TXDRQEN; + writel(reg_val, sunxi_iis.regs + SUNXI_IISINT); +- +- //Global disable Digital Audio Interface +- reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); +- reg_val &= ~SUNXI_IISCTL_GEN; +- writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); + } + } + +-void sunxi_snd_rxctrl_i2s(int on) ++void sunxi_snd_rxctrl_i2s(struct snd_pcm_substream *substream, int on) + { + u32 reg_val; +- /*printk("[I2S-0] sunxi_snd_rxctrl_i2s\n");*/ ++ printk("[I2S-0] sunxi_snd_rxctrl_i2s is on=(%d)\n", on); ++ reg_val = readl(sunxi_iis.regs + SUNXI_RXCHSEL); ++ reg_val &= ~0x7; ++ reg_val |= SUNXI_RXCHSEL_CHNUM(substream->runtime->channels); ++ writel(reg_val, sunxi_iis.regs + SUNXI_RXCHSEL); ++ ++ reg_val = readl(sunxi_iis.regs + SUNXI_RXCHMAP); ++ reg_val = 0; ++ if(substream->runtime->channels == 1) { ++ reg_val = 0x00003200; ++ } else { ++ reg_val = 0x00003210; ++ } ++ writel(reg_val, sunxi_iis.regs + SUNXI_RXCHMAP); ++ + //flush RX FIFO + reg_val = readl(sunxi_iis.regs + SUNXI_IISFCTL); + reg_val |= SUNXI_IISFCTL_FRX; +@@ -194,13 +203,6 @@ void sunxi_snd_rxctrl_i2s(int on) + reg_val |= SUNXI_IISINT_RXDRQEN; + writel(reg_val, sunxi_iis.regs + SUNXI_IISINT); + +- //Global Enable Digital Audio Interface +- reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); +- if(sunxi_iis.slave) +- reg_val |= SUNXI_IISCTL_MS; // 1: Slave! +- reg_val |= SUNXI_IISCTL_GEN; +- writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); +- + } else { + /* IIS RX DISABLE */ + reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); +@@ -211,26 +213,16 @@ void sunxi_snd_rxctrl_i2s(int on) + reg_val = readl(sunxi_iis.regs + SUNXI_IISINT); + reg_val &= ~SUNXI_IISINT_RXDRQEN; + writel(reg_val, sunxi_iis.regs + SUNXI_IISINT); +- +- //Global disable Digital Audio Interface +- reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); +- reg_val &= ~SUNXI_IISCTL_GEN; +- writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); + } + } + +-//not used +-/* +-static inline int sunxi_snd_is_clkmaster(void) +-{ +- return ((readl(sunxi_iis.regs + SUNXI_IISCTL) & SUNXI_IISCTL_MS) ? 0 : 1); +-} +-*/ + static int sunxi_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) + { + u32 reg_val; + u32 reg_val1; + ++ printk("[IIS-0] sunxi_i2s_set_fmt\n"); ++ + //SDO ON + reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); + if (sunxi_is_sun4i() || sunxi_is_sun7i()) { +@@ -239,37 +231,24 @@ static int sunxi_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) + } else { + reg_val |= SUNXI_IISCTL_SDO0EN; + } +- writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); ++ ++ //writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); + + /* master or slave selection */ +- reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); ++ //reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); + if(sunxi_iis.slave) + { + reg_val |= SUNXI_IISCTL_MS; // 1: Slave! +- /*printk("[IIS-0] sunxi_i2s_set_fmt: set slave mode for I2S interface\n");*/ ++ printk("[IIS-0] sunxi_i2s_set_fmt: set slave mode for I2S interface\n"); + } + else + { + reg_val &= ~SUNXI_IISCTL_MS; // 0: Master! +- /*printk("[IIS-0] sunxi_i2s_set_fmt: set master mode for I2S interface\n");*/ +- } +-/* +- switch(fmt & SND_SOC_DAIFMT_MASTER_MASK){ +- case SND_SOC_DAIFMT_CBS_CFS: // codec clk & frm slave +- reg_val |= SUNXI_IISCTL_MS; // 1: Slave! +- printk("[IIS-0] sunxi_i2s_set_fmt: set slave mode for I2S interface\n"); +- break; +- case SND_SOC_DAIFMT_CBM_CFM: // codec clk & frm master +- reg_val &= ~SUNXI_IISCTL_MS; // 0: Master! +- printk("[IIS-0] sunxi_i2s_set_fmt: set master mode for I2S interface\n"); +- break; +- default: +- printk("[IIS-0] sunxi_i2s_set_fmt: not master or slave mode\n"); +- return -EINVAL; ++ printk("[IIS-0] sunxi_i2s_set_fmt: set master mode for I2S interface\n"); + } +-*/ + writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); + ++ sunxi_iis.lrc_pol = 0; + /* pcm or i2s mode selection */ + reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); + reg_val1 = readl(sunxi_iis.regs + SUNXI_IISFAT0); +@@ -278,27 +257,33 @@ static int sunxi_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) + case SND_SOC_DAIFMT_I2S: /* I2S mode */ + reg_val &= ~SUNXI_IISCTL_PCM; + reg_val1 |= SUNXI_IISFAT0_FMT_I2S; +- /*printk("[IIS-0] sunxi_i2s_set_fmt: set I2S mode\n");*/ ++ sunxi_iis.samp_format = 0; ++ printk("[IIS-0] sunxi_i2s_set_fmt: set I2S mode\n"); + break; + case SND_SOC_DAIFMT_RIGHT_J: /* Right Justified mode */ + reg_val &= ~SUNXI_IISCTL_PCM; + reg_val1 |= SUNXI_IISFAT0_FMT_RGT; +- /*printk("[IIS-0] sunxi_i2s_set_fmt: set Right Justified mode\n");*/ ++ sunxi_iis.samp_format = 2; ++ printk("[IIS-0] sunxi_i2s_set_fmt: set Right Justified mode\n"); + break; + case SND_SOC_DAIFMT_LEFT_J: /* Left Justified mode */ + reg_val &= ~SUNXI_IISCTL_PCM; + reg_val1 |= SUNXI_IISFAT0_FMT_LFT; ++ sunxi_iis.samp_format = 1; + /*printk("[IIS-0] sunxi_i2s_set_fmt: set Left Justified mode\n");*/ + break; + case SND_SOC_DAIFMT_DSP_A: /* L data msb after FRM LRC */ + reg_val |= SUNXI_IISCTL_PCM; + reg_val1 &= ~SUNXI_IISFAT0_LRCP; +- /*printk("[IIS-0] sunxi_i2s_set_fmt: set L data msb after FRM LRC mode\n");*/ ++ sunxi_iis.samp_format = 3; ++ printk("[IIS-0] sunxi_i2s_set_fmt: set L data msb after FRM LRC mode\n"); + break; + case SND_SOC_DAIFMT_DSP_B: /* L data msb during FRM LRC */ + reg_val |= SUNXI_IISCTL_PCM; + reg_val1 |= SUNXI_IISFAT0_LRCP; +- /*printk("[IIS-0] sunxi_i2s_set_fmt: set L data msb during FRM LRC mode\n");*/ ++ sunxi_iis.samp_format = 3; ++ sunxi_iis.lrc_pol = 1; ++ printk("[IIS-0] sunxi_i2s_set_fmt: set L data msb during FRM LRC mode\n"); + break; + default: + printk("[IIS-0] sunxi_i2s_set_fmt: unknown mode\n"); +@@ -313,22 +298,30 @@ static int sunxi_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) + case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */ + reg_val1 &= ~SUNXI_IISFAT0_LRCP; + reg_val1 &= ~SUNXI_IISFAT0_BCP; +- /*printk("[IIS-0] sunxi_i2s_set_fmt: normal bit clock + frame\n");*/ ++ sunxi_iis.lrc_pol = 0; ++ sunxi_iis.bclk_pol = 0; ++ printk("[IIS-0] sunxi_i2s_set_fmt: normal bit clock + frame\n"); + break; + case SND_SOC_DAIFMT_NB_IF: /* normal bclk + inv frm */ + reg_val1 |= SUNXI_IISFAT0_LRCP; + reg_val1 &= ~SUNXI_IISFAT0_BCP; +- /*printk("[IIS-0] sunxi_i2s_set_fmt: normal bclk + inv frm\n");*/ ++ sunxi_iis.lrc_pol = 1; ++ sunxi_iis.bclk_pol = 0; ++ printk("[IIS-0] sunxi_i2s_set_fmt: normal bclk + inv frm\n"); + break; + case SND_SOC_DAIFMT_IB_NF: /* invert bclk + nor frm */ + reg_val1 &= ~SUNXI_IISFAT0_LRCP; + reg_val1 |= SUNXI_IISFAT0_BCP; +- /*printk("[IIS-0] sunxi_i2s_set_fmt: invert bclk + nor frm\n");*/ ++ sunxi_iis.lrc_pol = 0; ++ sunxi_iis.bclk_pol = 1; ++ printk("[IIS-0] sunxi_i2s_set_fmt: invert bclk + nor frm\n"); + break; + case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */ + reg_val1 |= SUNXI_IISFAT0_LRCP; + reg_val1 |= SUNXI_IISFAT0_BCP; +- /*printk("[IIS-0] sunxi_i2s_set_fmt: invert bclk + frm\n");*/ ++ sunxi_iis.lrc_pol = 1; ++ sunxi_iis.bclk_pol = 1; ++ printk("[IIS-0] sunxi_i2s_set_fmt: invert bclk + frm\n"); + break; + } + writel(reg_val1, sunxi_iis.regs + SUNXI_IISFAT0); +@@ -336,7 +329,10 @@ static int sunxi_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) + /* clear word select size */ + reg_val = readl(sunxi_iis.regs + SUNXI_IISFAT0); + reg_val &= ~SUNXI_IISFAT0_WSS_32BCLK; +- /*printk("[IIS-0] sunxi_i2s_set_fmt: word size = %d\n", sunxi_iis.ws_size);*/ ++ /* word size hardcoded to 32 (ref. sunxi-sndi2s.c func. sunxi_sndi2s_hw_params()) */ ++ sunxi_iis.ws_size = 32; ++ printk("[IIS-0] sunxi_i2s_set_fmt: word size = %d\n", sunxi_iis.ws_size); ++ /* + if(sunxi_iis.ws_size == 16) + reg_val |= SUNXI_IISFAT0_WSS_16BCLK; + else if(sunxi_iis.ws_size == 20) +@@ -344,22 +340,25 @@ static int sunxi_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) + else if(sunxi_iis.ws_size == 24) + reg_val |= SUNXI_IISFAT0_WSS_24BCLK; + else +- reg_val |= SUNXI_IISFAT0_WSS_32BCLK; ++ */ ++ reg_val |= SUNXI_IISFAT0_WSS_32BCLK; ++ + writel(reg_val, sunxi_iis.regs + SUNXI_IISFAT0); + + /* PCM REGISTER setup */ +- reg_val = sunxi_iis.pcm_txtype&0x3; +- reg_val |= sunxi_iis.pcm_rxtype<<2; ++ reg_val = 0; ++ //reg_val = sunxi_iis.pcm_txtype&0x3; ++ //reg_val |= sunxi_iis.pcm_rxtype<<2; + + if(!sunxi_iis.pcm_sync_type) + { + reg_val |= SUNXI_IISFAT1_SSYNC; //short sync +- /*printk("[IIS-0] sunxi_i2s_set_fmt: set pcm_sync_type = short sync\n");*/ ++ printk("[IIS-0] sunxi_i2s_set_fmt: set pcm_sync_type = short sync\n"); + } + if(sunxi_iis.pcm_sw == 16) + { + reg_val |= SUNXI_IISFAT1_SW; +- /*printk("[IIS-0] sunxi_i2s_set_fmt: pcm_sw == 16\n");*/ ++ printk("[IIS-0] sunxi_i2s_set_fmt: pcm_sw == 16\n"); + } + + reg_val |=((sunxi_iis.pcm_start_slot - 1)&0x3)<<6; //start slot index +@@ -367,31 +366,31 @@ static int sunxi_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) + reg_val |= sunxi_iis.pcm_lsb_first<<9; //MSB or LSB first + + if(sunxi_iis.pcm_sync_period == 256) +- reg_val |= 0x4<<12; ++ reg_val |= SUNXI_IISFAT1_SYNCLEN_256BCLK; + else if (sunxi_iis.pcm_sync_period == 128) +- reg_val |= 0x3<<12; ++ reg_val |= SUNXI_IISFAT1_SYNCLEN_128BCLK; + else if (sunxi_iis.pcm_sync_period == 64) +- reg_val |= 0x2<<12; ++ reg_val |= SUNXI_IISFAT1_SYNCLEN_64BCLK; + else if (sunxi_iis.pcm_sync_period == 32) +- reg_val |= 0x1<<12; ++ reg_val |= SUNXI_IISFAT1_SYNCLEN_32BCLK; + writel(reg_val, sunxi_iis.regs + SUNXI_IISFAT1); + + /* set FIFO control register */ +- reg_val = 0 & 0x3; +- reg_val |= (1 & 0x1)<<2; +- reg_val |= SUNXI_IISFCTL_RXTL(0xf); //RX FIFO trigger level +- reg_val |= SUNXI_IISFCTL_TXTL(0x40); //TX FIFO empty trigger level ++ reg_val = 0; ++ reg_val |= SUNXI_IISFCTL_RXTL(0xf); //RX FIFO trigger level ++ reg_val |= SUNXI_IISFCTL_TXTL(0x40); //TX FIFO empty trigger level + writel(reg_val, sunxi_iis.regs + SUNXI_IISFCTL); + return 0; + } + + static int sunxi_i2s_hw_params(struct snd_pcm_substream *substream, +- struct snd_pcm_hw_params *params, +- struct snd_soc_dai *dai) ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai) + { + u32 reg_val; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct sunxi_dma_params *dma_data; ++ printk("[IIS-0] sunxi_i2s_hw_params: %s\n", substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "recording"); + + /* play or record */ + if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +@@ -408,23 +407,39 @@ static int sunxi_i2s_hw_params(struct snd_pcm_substream *substream, + { + case SNDRV_PCM_FORMAT_S16_LE: + reg_val |= SUNXI_IISFAT0_SR_16BIT; +- /*printk("[IIS-0] sunxi_i2s_hw_params: format 16 bit\n");*/ ++ sunxi_iis.samp_res = 16; + break; + case SNDRV_PCM_FORMAT_S20_3LE: + reg_val |= SUNXI_IISFAT0_SR_20BIT; +- /*printk("[IIS-0] sunxi_i2s_hw_params: format 20 bit\n");*/ ++ sunxi_iis.samp_res = 20; + break; + case SNDRV_PCM_FORMAT_S24_LE: + reg_val |= SUNXI_IISFAT0_SR_24BIT; +- /*printk("[IIS-0] sunxi_i2s_hw_params: format 24 bit\n");*/ ++ sunxi_iis.samp_res = 24; + break; + default: +- printk("[IIS-0] sunxi_i2s_hw_params: Unsupported format (%d)\n", (int)params_format(params)); +- //return -EINVAL; ++ pr_err("[IIS-0] sunxi_i2s_hw_params: Unsupported format (%d)\n", (int)params_format(params)); ++ return -EINVAL; + } + writel(reg_val, sunxi_iis.regs + SUNXI_IISFAT0); + ++ /* set FIFO control register */ ++ reg_val = readl(sunxi_iis.regs + SUNXI_IISFCTL); ++ reg_val |= SUNXI_IISFCTL_TXIM_MOD1; //1: Valid data at the LSB of TXFIFO register ++ //CHECK EXPANDING FORMAT!!! ++ if(sunxi_iis.samp_res == 24) { ++ reg_val &= ~SUNXI_IISFCTL_RXOM_MOD3; //00: Expanding 0 at LSB of DA_RXFIFO register ++ } ++ else { ++ reg_val |= SUNXI_IISFCTL_RXOM_MOD1; //00: Expanding 0 at LSB of DA_RXFIFO register ++ } ++ writel(reg_val, sunxi_iis.regs + SUNXI_IISFCTL); ++ + snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); ++ sunxi_iis.samp_fs = params_rate(params); ++ sunxi_iis.channel_num = params_channels(params); ++ printk("[IIS-0] sunxi_i2s_hw_params: channel num %d, format %d bit, sample rate %d\n", ++ sunxi_iis.channel_num, sunxi_iis.samp_res, sunxi_iis.samp_fs); + return 0; + } + +@@ -441,7 +456,7 @@ static int sunxi_i2s_trigger(struct snd_pcm_substream *substream, + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { +- sunxi_snd_rxctrl_i2s(1); ++ sunxi_snd_rxctrl_i2s(substream, 1); + } else { + sunxi_snd_txctrl_i2s(substream, 1); + } +@@ -451,7 +466,7 @@ static int sunxi_i2s_trigger(struct snd_pcm_substream *substream, + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { +- sunxi_snd_rxctrl_i2s(0); ++ sunxi_snd_rxctrl_i2s(substream, 0); + } else { + sunxi_snd_txctrl_i2s(substream, 0); + } +@@ -556,6 +571,10 @@ static int sunxi_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div + gpio_write_one_pin_value(i2s_handle, 0, "i2s_clk_div1"); + gpio_write_one_pin_value(i2s_handle, 0, "i2s_clk_div0"); + } ++ else if(div == 64) { ++ gpio_write_one_pin_value(i2s_handle, 1, "i2s_clk_div1"); ++ gpio_write_one_pin_value(i2s_handle, 0, "i2s_clk_div0"); ++ } + else { + pr_err("[I2S-0] try to set unsupported external clock divider div=(%d)\n", div); + return -EINVAL; +@@ -599,6 +618,8 @@ static void iisregsave(void) + regsave[5] = readl(sunxi_iis.regs + SUNXI_IISCLKD); + regsave[6] = readl(sunxi_iis.regs + SUNXI_TXCHSEL); + regsave[7] = readl(sunxi_iis.regs + SUNXI_TXCHMAP); ++ regsave[8] = readl(sunxi_iis.regs + SUNXI_RXCHSEL); ++ regsave[9] = readl(sunxi_iis.regs + SUNXI_RXCHMAP); + } + + static void iisregrestore(void) +@@ -611,12 +632,14 @@ static void iisregrestore(void) + writel(regsave[5], sunxi_iis.regs + SUNXI_IISCLKD); + writel(regsave[6], sunxi_iis.regs + SUNXI_TXCHSEL); + writel(regsave[7], sunxi_iis.regs + SUNXI_TXCHMAP); ++ writel(regsave[8], sunxi_iis.regs + SUNXI_RXCHSEL); ++ writel(regsave[9], sunxi_iis.regs + SUNXI_RXCHMAP); + } + + static int sunxi_i2s_suspend(struct snd_soc_dai *cpu_dai) + { + u32 reg_val; +- printk("[IIS]Entered %s\n", __func__); ++ printk("[I2S-0] Entered %s\n", __func__); + + //Global Disable Digital Audio Interface + reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); +@@ -632,15 +655,15 @@ static int sunxi_i2s_suspend(struct snd_soc_dai *cpu_dai) + clk_disable(i2s_apbclk); + + //printk("[IIS]PLL2 0x01c20008 = %#x\n", *(volatile int*)0xF1C20008); +- printk("[IIS]SPECIAL CLK 0x01c20068 = %#x, line= %d\n", *(volatile int*)0xF1C20068, __LINE__); +- printk("[IIS]SPECIAL CLK 0x01c200B8 = %#x, line = %d\n", *(volatile int*)0xF1C200B8, __LINE__); ++ printk("[I2S-0] SPECIAL CLK 0x01c20068 = %#x, line= %d\n", *(volatile int*)0xF1C20068, __LINE__); ++ printk("[I2S-0] SPECIAL CLK 0x01c200B8 = %#x, line = %d\n", *(volatile int*)0xF1C200B8, __LINE__); + + return 0; + } + static int sunxi_i2s_resume(struct snd_soc_dai *cpu_dai) + { + u32 reg_val; +- printk("[IIS]Entered %s\n", __func__); ++ printk("[I2S-0] Entered %s\n", __func__); + + //enable the module clock + clk_enable(i2s_apbclk); +@@ -657,12 +680,14 @@ static int sunxi_i2s_resume(struct snd_soc_dai *cpu_dai) + reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); + if(sunxi_iis.slave) + reg_val |= SUNXI_IISCTL_MS; // 1: Slave! ++ else ++ reg_val &= ~SUNXI_IISCTL_MS; // 0: Master! + reg_val |= SUNXI_IISCTL_GEN; + writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); + + //printk("[IIS]PLL2 0x01c20008 = %#x\n", *(volatile int*)0xF1C20008); +- printk("[IIS]SPECIAL CLK 0x01c20068 = %#x, line= %d\n", *(volatile int*)0xF1C20068, __LINE__); +- printk("[IIS]SPECIAL CLK 0x01c200B8 = %#x, line = %d\n", *(volatile int*)0xF1C200B8, __LINE__); ++ printk("[I2S-0] SPECIAL CLK 0x01c20068 = %#x, line= %d\n", *(volatile int*)0xF1C20068, __LINE__); ++ printk("[I2S-0] SPECIAL CLK 0x01c200B8 = %#x, line = %d\n", *(volatile int*)0xF1C200B8, __LINE__); + + return 0; + } +@@ -670,7 +695,8 @@ static int sunxi_i2s_resume(struct snd_soc_dai *cpu_dai) + #define SUNXI_I2S_RATES_MASTER (SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT) + #define SUNXI_I2S_RATES_SLAVE (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\ +- SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) ++ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 |\ ++ SNDRV_PCM_RATE_352800 | SNDRV_PCM_RATE_384000) + static struct snd_soc_dai_ops sunxi_iis_dai_ops = { + .trigger = sunxi_i2s_trigger, + .hw_params = sunxi_i2s_hw_params, +@@ -704,7 +730,7 @@ static int __devinit sunxi_i2s_dev_probe(struct platform_device *pdev) + { + int reg_val = 0; + int ret; +- printk("[IIS]Entered %s\n", __func__); ++ printk("[I2S-0] Entered %s\n", __func__); + + sunxi_iis.regs = ioremap(SUNXI_IISBASE, 0x100); + if (sunxi_iis.regs == NULL) +@@ -720,7 +746,7 @@ static int __devinit sunxi_i2s_dev_probe(struct platform_device *pdev) + ); + + if(-1 == clk_enable(i2s_apbclk)){ +- printk("i2s_apbclk failed! line = %d\n", __LINE__); ++ pr_err("[I2S-0] i2s_apbclk failed! line = %d\n", __LINE__); + goto out; + } + +@@ -739,25 +765,30 @@ static int __devinit sunxi_i2s_dev_probe(struct platform_device *pdev) + ); + + if(clk_set_parent(i2s_moduleclk, i2s_pll2clk)){ +- printk("try to set parent of i2s_moduleclk to i2s_pll2ck failed! line = %d\n",__LINE__); ++ pr_err("[I2S-0] try to set parent of i2s_moduleclk to i2s_pll2ck failed! line = %d\n",__LINE__); + goto out1; + } + + if(clk_set_rate(i2s_moduleclk, 24576000/8)){ +- printk("set i2s_moduleclk clock freq to 24576000 failed! line = %d\n", __LINE__); ++ pr_err("[I2S-0] set i2s_moduleclk clock freq to 24576000 failed! line = %d\n", __LINE__); + goto out1; + } + + if(-1 == clk_enable(i2s_moduleclk)){ +- printk("open i2s_moduleclk failed! line = %d\n", __LINE__); ++ pr_err("[I2S-0] open i2s_moduleclk failed! line = %d\n", __LINE__); + goto out1; + } + } else +- sunxi_iis_dai.playback.rates = SUNXI_I2S_RATES_SLAVE; ++ { ++ sunxi_iis_dai.playback.rates = SUNXI_I2S_RATES_SLAVE; ++ sunxi_iis_dai.capture.rates = SUNXI_I2S_RATES_SLAVE; ++ } + + reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); + if(sunxi_iis.slave) + reg_val |= SUNXI_IISCTL_MS; // 1: Slave! ++ else ++ reg_val &= ~SUNXI_IISCTL_MS; // 0: Master! + reg_val |= SUNXI_IISCTL_GEN; + writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); + +@@ -780,9 +811,15 @@ static int __devinit sunxi_i2s_dev_probe(struct platform_device *pdev) + + static int __devexit sunxi_i2s_dev_remove(struct platform_device *pdev) + { +- printk("[IIS]Entered %s\n", __func__); ++ int reg_val = 0; ++ printk("[I2S-0] Entered %s\n", __func__); + + if(i2s_used) { ++ //Global disable Digital Audio Interface ++ reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); ++ reg_val &= ~SUNXI_IISCTL_GEN; ++ writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); ++ + i2s_used = 0; + if(!sunxi_iis.slave) { + //release the module clock +@@ -824,11 +861,11 @@ static int __init sunxi_i2s_init(void) + int err = 0, i2s_slave = 0; + int ret; + +- printk("[IIS]Entered %s\n", __func__); ++ printk("[I2S-0] Entered %s\n", __func__); + + ret = script_parser_fetch("i2s_para","i2s_used", &i2s_used, sizeof(int)); + if (ret) { +- printk("[I2S]sunxi_i2s_init fetch i2s using configuration failed\n"); ++ printk("[I2S-0] sunxi_i2s_init fetch i2s using configuration failed\n"); + } + + if (i2s_used) { +@@ -849,7 +886,7 @@ static int __init sunxi_i2s_init(void) + if ((err = platform_driver_register(&sunxi_i2s_driver)) < 0) + return err; + } else { +- printk("[I2S]sunxi-i2s cannot find any using configuration for controllers, return directly!\n"); ++ printk("[I2S-0] sunxi-i2s cannot find any using configuration for controllers, return directly!\n"); + return 0; + } + return 0; +@@ -858,7 +895,7 @@ module_init(sunxi_i2s_init); + + static void __exit sunxi_i2s_exit(void) + { +- printk("[IIS]Entered %s\n", __func__); ++ printk("[I2S-0] Entered %s\n", __func__); + platform_driver_unregister(&sunxi_i2s_driver); + } + module_exit(sunxi_i2s_exit); +--- a/sound/soc/sunxi/i2s/sunxi-i2s.h ++++ b/sound/soc/sunxi/i2s/sunxi-i2s.h +@@ -20,71 +20,71 @@ + /* REGISTER definition */ + + /* IIS REGISTER */ +-#define SUNXI_IISBASE (0x01C22400) ++#define SUNXI_IISBASE (0x01C22400) + +-#define SUNXI_IISCTL (0x00) ++#define SUNXI_IISCTL (0x00) + #define SUNXI_IISCTL_SDO3EN (1<<11) + #define SUNXI_IISCTL_SDO2EN (1<<10) + #define SUNXI_IISCTL_SDO1EN (1<<9) + #define SUNXI_IISCTL_SDO0EN (1<<8) +- #define SUNXI_IISCTL_ASS (1<<6) ++ #define SUNXI_IISCTL_ASS (1<<6) + #define SUNXI_IISCTL_MS (1<<5) +- #define SUNXI_IISCTL_PCM (1<<4) +- #define SUNXI_IISCTL_LOOP (1<<3) +- #define SUNXI_IISCTL_TXEN (1<<2) +- #define SUNXI_IISCTL_RXEN (1<<1) +- #define SUNXI_IISCTL_GEN (1<<0) +- +-#define SUNXI_IISFAT0 (0x04) +- #define SUNXI_IISFAT0_LRCP (1<<7) +- #define SUNXI_IISFAT0_BCP (1<<6) +- #define SUNXI_IISFAT0_SR_RVD (3<<4) +- #define SUNXI_IISFAT0_SR_16BIT (0<<4) +- #define SUNXI_IISFAT0_SR_20BIT (1<<4) +- #define SUNXI_IISFAT0_SR_24BIT (2<<4) +- #define SUNXI_IISFAT0_WSS_16BCLK (0<<2) +- #define SUNXI_IISFAT0_WSS_20BCLK (1<<2) +- #define SUNXI_IISFAT0_WSS_24BCLK (2<<2) +- #define SUNXI_IISFAT0_WSS_32BCLK (3<<2) +- #define SUNXI_IISFAT0_FMT_I2S (0<<0) +- #define SUNXI_IISFAT0_FMT_LFT (1<<0) +- #define SUNXI_IISFAT0_FMT_RGT (2<<0) +- #define SUNXI_IISFAT0_FMT_RVD (3<<0) +- +-#define SUNXI_IISFAT1 (0x08) +- #define SUNXI_IISFAT1_SYNCLEN_16BCLK (0<<12) +- #define SUNXI_IISFAT1_SYNCLEN_32BCLK (1<<12) +- #define SUNXI_IISFAT1_SYNCLEN_64BCLK (2<<12) +- #define SUNXI_IISFAT1_SYNCLEN_128BCLK (3<<12) +- #define SUNXI_IISFAT1_SYNCLEN_256BCLK (4<<12) +- #define SUNXI_IISFAT1_SYNCOUTEN (1<<11) +- #define SUNXI_IISFAT1_OUTMUTE (1<<10) +- #define SUNXI_IISFAT1_MLS (1<<9) +- #define SUNXI_IISFAT1_SEXT (1<<8) +- #define SUNXI_IISFAT1_SI_1ST (0<<6) +- #define SUNXI_IISFAT1_SI_2ND (1<<6) +- #define SUNXI_IISFAT1_SI_3RD (2<<6) +- #define SUNXI_IISFAT1_SI_4TH (3<<6) +- #define SUNXI_IISFAT1_SW (1<<5) +- #define SUNXI_IISFAT1_SSYNC (1<<4) +- #define SUNXI_IISFAT1_RXPDM_16PCM (0<<2) +- #define SUNXI_IISFAT1_RXPDM_8PCM (1<<2) +- #define SUNXI_IISFAT1_RXPDM_8ULAW (2<<2) +- #define SUNXI_IISFAT1_RXPDM_8ALAW (3<<2) +- #define SUNXI_IISFAT1_TXPDM_16PCM (0<<0) +- #define SUNXI_IISFAT1_TXPDM_8PCM (1<<0) +- #define SUNXI_IISFAT1_TXPDM_8ULAW (2<<0) +- #define SUNXI_IISFAT1_TXPDM_8ALAW (3<<0) +- +-#define SUNXI_IISTXFIFO (0x0C) +- +-#define SUNXI_IISRXFIFO (0x10) +- +-#define SUNXI_IISFCTL (0x14) +- #define SUNXI_IISFCTL_FIFOSRC (1<<31) +- #define SUNXI_IISFCTL_FTX (1<<25) +- #define SUNXI_IISFCTL_FRX (1<<24) +- #define SUNXI_IISFCTL_TXTL(v) ((v)<<12) ++ #define SUNXI_IISCTL_PCM (1<<4) ++ #define SUNXI_IISCTL_LOOP (1<<3) ++ #define SUNXI_IISCTL_TXEN (1<<2) ++ #define SUNXI_IISCTL_RXEN (1<<1) ++ #define SUNXI_IISCTL_GEN (1<<0) ++ ++#define SUNXI_IISFAT0 (0x04) ++ #define SUNXI_IISFAT0_LRCP (1<<7) ++ #define SUNXI_IISFAT0_BCP (1<<6) ++ #define SUNXI_IISFAT0_SR_RVD (3<<4) ++ #define SUNXI_IISFAT0_SR_16BIT (0<<4) ++ #define SUNXI_IISFAT0_SR_20BIT (1<<4) ++ #define SUNXI_IISFAT0_SR_24BIT (2<<4) ++ #define SUNXI_IISFAT0_WSS_16BCLK (0<<2) ++ #define SUNXI_IISFAT0_WSS_20BCLK (1<<2) ++ #define SUNXI_IISFAT0_WSS_24BCLK (2<<2) ++ #define SUNXI_IISFAT0_WSS_32BCLK (3<<2) ++ #define SUNXI_IISFAT0_FMT_I2S (0<<0) ++ #define SUNXI_IISFAT0_FMT_LFT (1<<0) ++ #define SUNXI_IISFAT0_FMT_RGT (2<<0) ++ #define SUNXI_IISFAT0_FMT_RVD (3<<0) ++ ++#define SUNXI_IISFAT1 (0x08) ++ #define SUNXI_IISFAT1_SYNCLEN_16BCLK (0<<12) ++ #define SUNXI_IISFAT1_SYNCLEN_32BCLK (1<<12) ++ #define SUNXI_IISFAT1_SYNCLEN_64BCLK (2<<12) ++ #define SUNXI_IISFAT1_SYNCLEN_128BCLK (3<<12) ++ #define SUNXI_IISFAT1_SYNCLEN_256BCLK (4<<12) ++ #define SUNXI_IISFAT1_SYNCOUTEN (1<<11) ++ #define SUNXI_IISFAT1_OUTMUTE (1<<10) ++ #define SUNXI_IISFAT1_MLS (1<<9) ++ #define SUNXI_IISFAT1_SEXT (1<<8) ++ #define SUNXI_IISFAT1_SI_1ST (0<<6) ++ #define SUNXI_IISFAT1_SI_2ND (1<<6) ++ #define SUNXI_IISFAT1_SI_3RD (2<<6) ++ #define SUNXI_IISFAT1_SI_4TH (3<<6) ++ #define SUNXI_IISFAT1_SW (1<<5) ++ #define SUNXI_IISFAT1_SSYNC (1<<4) ++ #define SUNXI_IISFAT1_RXPDM_16PCM (0<<2) ++ #define SUNXI_IISFAT1_RXPDM_8PCM (1<<2) ++ #define SUNXI_IISFAT1_RXPDM_8ULAW (2<<2) ++ #define SUNXI_IISFAT1_RXPDM_8ALAW (3<<2) ++ #define SUNXI_IISFAT1_TXPDM_16PCM (0<<0) ++ #define SUNXI_IISFAT1_TXPDM_8PCM (1<<0) ++ #define SUNXI_IISFAT1_TXPDM_8ULAW (2<<0) ++ #define SUNXI_IISFAT1_TXPDM_8ALAW (3<<0) ++ ++#define SUNXI_IISTXFIFO (0x0C) ++ ++#define SUNXI_IISRXFIFO (0x10) ++ ++#define SUNXI_IISFCTL (0x14) ++ #define SUNXI_IISFCTL_FIFOSRC (1<<31) ++ #define SUNXI_IISFCTL_FTX (1<<25) ++ #define SUNXI_IISFCTL_FRX (1<<24) ++ #define SUNXI_IISFCTL_TXTL(v) ((v)<<12) + #define SUNXI_IISFCTL_RXTL(v) ((v)<<4) + #define SUNXI_IISFCTL_TXIM_MOD0 (0<<2) + #define SUNXI_IISFCTL_TXIM_MOD1 (1<<2) +@@ -93,168 +93,94 @@ + #define SUNXI_IISFCTL_RXOM_MOD2 (2<<0) + #define SUNXI_IISFCTL_RXOM_MOD3 (3<<0) + +-#define SUNXI_IISFSTA (0x18) +- #define SUNXI_IISFSTA_TXE (1<<28) ++#define SUNXI_IISFSTA (0x18) ++ #define SUNXI_IISFSTA_TXE (1<<28) + #define SUNXI_IISFSTA_TXECNT(v) ((v)<<16) +- #define SUNXI_IISFSTA_RXA (1<<8) ++ #define SUNXI_IISFSTA_RXA (1<<8) + #define SUNXI_IISFSTA_RXACNT(v) ((v)<<0) + +-#define SUNXI_IISINT (0x1C) +- #define SUNXI_IISINT_TXDRQEN (1<<7) +- #define SUNXI_IISINT_TXUIEN (1<<6) +- #define SUNXI_IISINT_TXOIEN (1<<5) +- #define SUNXI_IISINT_TXEIEN (1<<4) +- #define SUNXI_IISINT_RXDRQEN (1<<2) +- #define SUNXI_IISINT_RXOIEN (1<<1) +- #define SUNXI_IISINT_RXAIEN (1<<0) +- +-#define SUNXI_IISISTA (0x20) +- #define SUNXI_IISISTA_TXUISTA (1<<6) +- #define SUNXI_IISISTA_TXOISTA (1<<5) +- #define SUNXI_IISISTA_TXEISTA (1<<4) +- #define SUNXI_IISISTA_RXOISTA (1<<1) +- #define SUNXI_IISISTA_RXAISTA (1<<0) +- +-#define SUNXI_IISCLKD (0x24) +- #define SUNXI_IISCLKD_MCLKOEN (1<<7) ++#define SUNXI_IISINT (0x1C) ++ #define SUNXI_IISINT_TXDRQEN (1<<7) ++ #define SUNXI_IISINT_TXUIEN (1<<6) ++ #define SUNXI_IISINT_TXOIEN (1<<5) ++ #define SUNXI_IISINT_TXEIEN (1<<4) ++ #define SUNXI_IISINT_RXDRQEN (1<<3) ++ #define SUNXI_IISINT_RXUIEN (1<<2) ++ #define SUNXI_IISINT_RXOIEN (1<<1) ++ #define SUNXI_IISINT_RXAIEN (1<<0) ++ ++#define SUNXI_IISISTA (0x20) ++ #define SUNXI_IISISTA_TXUISTA (1<<6) ++ #define SUNXI_IISISTA_TXOISTA (1<<5) ++ #define SUNXI_IISISTA_TXEISTA (1<<4) ++ #define SUNXI_IISISTA_RXUISTA (1<<2) ++ #define SUNXI_IISISTA_RXOISTA (1<<1) ++ #define SUNXI_IISISTA_RXAISTA (1<<0) ++ ++#define SUNXI_IISCLKD (0x24) ++ #define SUNXI_IISCLKD_MCLKOEN (1<<7) + #define SUNXI_IISCLKD_BCLKDIV_2 (0<<4) + #define SUNXI_IISCLKD_BCLKDIV_4 (1<<4) + #define SUNXI_IISCLKD_BCLKDIV_6 (2<<4) + #define SUNXI_IISCLKD_BCLKDIV_8 (3<<4) +- #define SUNXI_IISCLKD_BCLKDIV_12 (4<<4) +- #define SUNXI_IISCLKD_BCLKDIV_16 (5<<4) +- #define SUNXI_IISCLKD_BCLKDIV_32 (6<<4) +- #define SUNXI_IISCLKD_BCLKDIV_64 (7<<4) ++ #define SUNXI_IISCLKD_BCLKDIV_12 (4<<4) ++ #define SUNXI_IISCLKD_BCLKDIV_16 (5<<4) ++ #define SUNXI_IISCLKD_BCLKDIV_32 (6<<4) ++ #define SUNXI_IISCLKD_BCLKDIV_64 (7<<4) + #define SUNXI_IISCLKD_MCLKDIV_1 (0<<0) + #define SUNXI_IISCLKD_MCLKDIV_2 (1<<0) + #define SUNXI_IISCLKD_MCLKDIV_4 (2<<0) + #define SUNXI_IISCLKD_MCLKDIV_6 (3<<0) + #define SUNXI_IISCLKD_MCLKDIV_8 (4<<0) +- #define SUNXI_IISCLKD_MCLKDIV_12 (5<<0) +- #define SUNXI_IISCLKD_MCLKDIV_16 (6<<0) +- #define SUNXI_IISCLKD_MCLKDIV_24 (7<<0) +- #define SUNXI_IISCLKD_MCLKDIV_32 (8<<0) +- #define SUNXI_IISCLKD_MCLKDIV_48 (9<<0) +- #define SUNXI_IISCLKD_MCLKDIV_64 (10<<0) +- +-#define SUNXI_IISTXCNT (0x28) +- +-#define SUNXI_IISRXCNT (0x2C) +- +-#define SUNXI_TXCHSEL (0x30) +- #define SUNXI_TXCHSEL_CHNUM(v) (((v)-1)<<0) +- +-#define SUNXI_TXCHMAP (0x34) +- #define SUNXI_TXCHMAP_CH7(v) (((v)-1)<<28) +- #define SUNXI_TXCHMAP_CH6(v) (((v)-1)<<24) +- #define SUNXI_TXCHMAP_CH5(v) (((v)-1)<<20) +- #define SUNXI_TXCHMAP_CH4(v) (((v)-1)<<16) +- #define SUNXI_TXCHMAP_CH3(v) (((v)-1)<<12) +- #define SUNXI_TXCHMAP_CH2(v) (((v)-1)<<8) +- #define SUNXI_TXCHMAP_CH1(v) (((v)-1)<<4) +- #define SUNXI_TXCHMAP_CH0(v) (((v)-1)<<0) +- +-#define SUNXI_RXCHSEL (0x38) +- #define SUNXI_RXCHSEL_CHNUM(v) (((v)-1)<<0) +- +-#define SUNXI_RXCHMAP (0x3C) +- #define SUNXI_RXCHMAP_CH3(v) (((v)-1)<<12) +- #define SUNXI_RXCHMAP_CH2(v) (((v)-1)<<8) +- #define SUNXI_RXCHMAP_CH1(v) (((v)-1)<<4) +- #define SUNXI_RXCHMAP_CH0(v) (((v)-1)<<0) +- +- +-/* DMA REGISTER */ +-#define SUNXI_DMABASE (0x01C02000) +- +-#define SUNXI_DMAIRQEN (0x0) +- #define SUNXI_DMAIRQEN_NDMA_FULLEN(v) (1<<((v)*2+1)) +- #define SUNXI_DMAIRQEN_NDMA_HALFEN(v) (1<<((v)*2)) +- +-#define SUNXI_DMAIRQPENDING (0x4) +- #define SUNXI_DMAIRQPENGDING_NDMA_FULLPEND(v) (1<<((v)*2+1)) +- #define SUNXI_DMAIRQPENGDING_NDMA_HALFPEND(v) (1<<((v)*2)) +- +-#define SUNXI_NDMACFG(v) ((v)*0x20+0x100) +- #define SUNXI_NDMACFG_DMALOAD (1<<31) +- #define SUNXI_NDMACFG_BUSY (1<<30) +- #define SUNXI_NDMACFG_CONTINUOUS (1<<29) +- #define SUNXI_NDMACFG_WAIT(v) (((v)-1)<<26) //wait clock = 2^n example: 8 clocks = 2^3 +- #define SUNXI_NDMACFG_DSTDATAWIDTH_8BIT (0<<24) +- #define SUNXI_NDMACFG_DSTDATAWIDTH_16BIT (1<<24) +- #define SUNXI_NDMACFG_DSTDATAWIDTH_32BIT (2<<24) +- #define SUNXI_NDMACFG_DSTDATAWIDTH_RVD (3<<24) +- #define SUNXI_NDMACFG_DSTBURST4 (1<<23) +- #define SUNXI_NDMACFG_DSTADDRTYPE_INC (0<<21) +- #define SUNXI_NDMACFG_DSTADDRTYPE_CON (1<<21) +- #define SUNXI_NDMACFG_DSTTYPE_IRTX (0x0<<16) +- #define SUNXI_NDMACFG_DSTTYPE_SPDIFTX (0x1<<16) +- #define SUNXI_NDMACFG_DSTTYPE_IISTX (0x2<<16) +- #define SUNXI_NDMACFG_DSTTYPE_AC97TX (0x3<<16) +- #define SUNXI_NDMACFG_DSTTYPE_SPI0TX (0x4<<16) +- #define SUNXI_NDMACFG_DSTTYPE_SPI1TX (0x5<<16) +- #define SUNXI_NDMACFG_DSTTYPE_SPI2TX (0x6<<16) +- #define SUNXI_NDMACFG_DSTTYPE_UART0TX (0x8<<16) +- #define SUNXI_NDMACFG_DSTTYPE_UART1TX (0x9<<16) +- #define SUNXI_NDMACFG_DSTTYPE_UART2TX (0xA<<16) +- #define SUNXI_NDMACFG_DSTTYPE_UART3TX (0xB<<16) +- #define SUNXI_NDMACFG_DSTTYPE_AUDIODA (0xC<<16) +- #define SUNXI_NDMACFG_DSTTYPE_NFC (0xF<<16) +- #define SUNXI_NDMACFG_DSTTYPE_SRAM (0x10<<16) +- #define SUNXI_NDMACFG_DSTTYPE_DRAM (0x11<<16) +- #define SUNXI_NDMACFG_DSTTYPE_UART4TX (0x12<<16) +- #define SUNXI_NDMACFG_DSTTYPE_UART5TX (0x13<<16) +- #define SUNXI_NDMACFG_DSTTYPE_UART6TX (0x14<<16) +- #define SUNXI_NDMACFG_DSTTYPE_UART7TX (0x15<<16) +- #define SUNXI_NDMACFG_SRCDATAWIDTH_8BIT (0<<8) +- #define SUNXI_NDMACFG_SRCDATAWIDTH_16BIT (1<<8) +- #define SUNXI_NDMACFG_SRCDATAWIDTH_32BIT (2<<8) +- #define SUNXI_NDMACFG_SRCDATAWIDTH_RVD (3<<8) +- #define SUNXI_NDMACFG_SRCBURST4 (1<<7) +- #define SUNXI_NDMACFG_SRCADDRTYPE_INC (0<<5) +- #define SUNXI_NDMACFG_SRCADDRTYPE_CON (1<<5) +- #define SUNXI_NDMACFG_SRCTYPE_IRRX (0x0<<0) +- #define SUNXI_NDMACFG_SRCTYPE_SPDIFRX (0x1<<0) +- #define SUNXI_NDMACFG_SRCTYPE_IISRX (0x2<<0) +- #define SUNXI_NDMACFG_SRCTYPE_AC97RX (0x3<<0) +- #define SUNXI_NDMACFG_SRCTYPE_SPI0RX (0x4<<0) +- #define SUNXI_NDMACFG_SRCTYPE_SPI1RX (0x5<<0) +- #define SUNXI_NDMACFG_SRCTYPE_SPI2RX (0x6<<0) +- #define SUNXI_NDMACFG_SRCTYPE_UART0RX (0x8<<0) +- #define SUNXI_NDMACFG_SRCTYPE_UART1RX (0x9<<0) +- #define SUNXI_NDMACFG_SRCTYPE_UART2RX (0xA<<0) +- #define SUNXI_NDMACFG_SRCTYPE_UART3RX (0xB<<0) +- #define SUNXI_NDMACFG_SRCTYPE_AUDIOAD (0xC<<0) +- #define SUNXI_NDMACFG_SRCTYPE_TPAD (0xD<<0) +- #define SUNXI_NDMACFG_SRCTYPE_NFC (0xF<<0) +- #define SUNXI_NDMACFG_SRCTYPE_SRAM (0x10<<0) +- #define SUNXI_NDMACFG_SRCTYPE_DRAM (0x11<<0) +- #define SUNXI_NDMACFG_SRCTYPE_UART4RX (0x12<<0) +- #define SUNXI_NDMACFG_SRCTYPE_UART5RX (0x13<<0) +- #define SUNXI_NDMACFG_SRCTYPE_UART6RX (0x14<<0) +- #define SUNXI_NDMACFG_SRCTYPE_UART7RX (0x15<<0) +- +-#define SUNXI_NDMASRCADDR(v) ((v)*0x20 + 0x100 + 4) +- +-#define SUNXI_NDMADSTADDR(v) ((v)*0x20 + 0x100 + 8) +- +-#define SUNXI_NDMACNT(v) ((v)*0x20 + 0x100 + 0xC) ++ #define SUNXI_IISCLKD_MCLKDIV_12 (5<<0) ++ #define SUNXI_IISCLKD_MCLKDIV_16 (6<<0) ++ #define SUNXI_IISCLKD_MCLKDIV_24 (7<<0) ++ #define SUNXI_IISCLKD_MCLKDIV_32 (8<<0) ++ #define SUNXI_IISCLKD_MCLKDIV_48 (9<<0) ++ #define SUNXI_IISCLKD_MCLKDIV_64 (10<<0) ++ ++#define SUNXI_IISTXCNT (0x28) ++ ++#define SUNXI_IISRXCNT (0x2C) ++ ++#define SUNXI_TXCHSEL (0x30) ++ #define SUNXI_TXCHSEL_CHNUM(v) (((v)-1)<<0) ++ ++#define SUNXI_TXCHMAP (0x34) ++ #define SUNXI_TXCHMAP_CH7(v) (((v)-1)<<28) ++ #define SUNXI_TXCHMAP_CH6(v) (((v)-1)<<24) ++ #define SUNXI_TXCHMAP_CH5(v) (((v)-1)<<20) ++ #define SUNXI_TXCHMAP_CH4(v) (((v)-1)<<16) ++ #define SUNXI_TXCHMAP_CH3(v) (((v)-1)<<12) ++ #define SUNXI_TXCHMAP_CH2(v) (((v)-1)<<8) ++ #define SUNXI_TXCHMAP_CH1(v) (((v)-1)<<4) ++ #define SUNXI_TXCHMAP_CH0(v) (((v)-1)<<0) ++ ++#define SUNXI_RXCHSEL (0x38) ++ #define SUNXI_RXCHSEL_CHNUM(v) (((v)-1)<<0) ++ ++#define SUNXI_RXCHMAP (0x3C) ++ #define SUNXI_RXCHMAP_CH3(v) (((v)-1)<<12) ++ #define SUNXI_RXCHMAP_CH2(v) (((v)-1)<<8) ++ #define SUNXI_RXCHMAP_CH1(v) (((v)-1)<<4) ++ #define SUNXI_RXCHMAP_CH0(v) (((v)-1)<<0) ++ + + + /* CCM REGISTER */ +-#define SUNXI_CCMBASE (0x01C20000) ++#define SUNXI_CCMBASE (0x01C20000) + +-#define SUNXI_CCM_AUDIO_HOSC_PLL_REG (0x08) ++#define SUNXI_CCM_AUDIO_HOSC_PLL_REG (0x08) + #define SUNXI_CCM_AUDIO_HOSC_PLL_REG_AUDIOEN (1<<31) + #define SUNXI_CCM_AUDIO_HOSC_PLL_REG_FRE225792MHZ (0<<27) + #define SUNXI_CCM_AUDIO_HOSC_PLL_REG_FRE24576MHZ (1<<27) + +-#define SUNXI_CCM_APB_GATE_REG (0x68) +- #define SUNXI_CCM_APB_GATE_REG_IISGATE (1<<3) ++#define SUNXI_CCM_APB_GATE_REG (0x68) ++ #define SUNXI_CCM_APB_GATE_REG_IISGATE (1<<3) + +-#define SUNXI_CCM_AUDIO_CLK_REG (0xb8) ++#define SUNXI_CCM_AUDIO_CLK_REG (0xb8) + #define SUNXI_CCM_AUDIO_CLK_REG_IISSPECIALGATE (1<<31) +- #define SUNXI_CCM_AUDIO_CLK_REG_DIV(v) ((v)<<16) ++ #define SUNXI_CCM_AUDIO_CLK_REG_DIV(v) ((v)<<16) + /*------------------------------------------------------------*/ + + /*------------------------------------------------------------*/ +@@ -270,34 +196,32 @@ + #define SUNXI_IISCLKD_MCLKEN_OFFS 7 + + unsigned int sunxi_i2s_get_clockrate(void); +-//extern struct sunxi_i2s_info sunxi_iis; +-//extern struct snd_soc_dai sunxi_iis_dai; + + extern void sunxi_snd_txctrl_i2s(struct snd_pcm_substream *substream, int on); +-extern void sunxi_snd_rxctrl_i2s(int on); ++extern void sunxi_snd_rxctrl_i2s(struct snd_pcm_substream *substream, int on); + + struct sunxi_i2s_info { +- void __iomem *regs; /* IIS BASE */ +- void __iomem *ccmregs; //CCM BASE +- void __iomem *ioregs; //IO BASE ++ void __iomem *regs; //IIS BASE ++ void __iomem *ccmregs; //CCM BASE ++ void __iomem *ioregs; //IO BASE + +- u32 slave; //0: master, 1: slave +- u32 mono; //0: stereo, 1: mono +- u32 samp_fs; //audio sample rate (unit in kHz) ++ u32 slave; //0: master, 1: slave ++ u32 channel_num; // ++ u32 samp_fs; //audio sample rate (unit in kHz) + u32 samp_res; //16 bits, 20 bits , 24 bits, 32 bits) + u32 samp_format; //audio sample format (0: standard I2S, 1: left-justified, 2: right-justified, 3: pcm) +- u32 ws_size; //16 BCLK, 20 BCLK, 24 BCLK, 32 BCLK) ++ u32 ws_size; //16 BCLK, 20 BCLK, 24 BCLK, 32 BCLK) + u32 mclk_rate; //mclk frequency divide by fs (128fs, 192fs, 256fs, 384fs, 512fs, 768fs) +- u32 lrc_pol; //LRC clock polarity (0: normal ,1: inverted) ++ u32 lrc_pol; //LRC clock polarity (0: normal ,1: inverted) + u32 bclk_pol; //BCLK polarity (0: normal, 1: inverted) +- u32 pcm_txtype; //PCM transmitter type (0: 16-bits linear mode, 1: 8-bits linear mode, 2: u-law, 3: A-law) +- u32 pcm_rxtype; //PCM receiver type (0: 16-bits linear mode, 1: 8-bits linear mode, 2: u-law, 3: A-law) +- u32 pcm_sw; //PCM slot width (8: 8 bits, 16: 16 bits) +- u32 pcm_sync_period;//PCM sync period (16/32/64/128/256) +- u32 pcm_sync_type; //PCM sync symbol size (0: short sync, 1: long sync) +- u32 pcm_start_slot;//PCM start slot index (1--4) +- u32 pcm_lsb_first; //0: MSB first, 1: LSB first +- u32 pcm_ch_num; //PCM channel number (1: one channel, 2: two channel) ++ u32 pcm_txtype; //PCM transmitter type (0: 16-bits linear mode, 1: 8-bits linear mode, 2: u-law, 3: A-law) ++ u32 pcm_rxtype; //PCM receiver type (0: 16-bits linear mode, 1: 8-bits linear mode, 2: u-law, 3: A-law) ++ u32 pcm_sw; //PCM slot width (8: 8 bits, 16: 16 bits) ++ u32 pcm_sync_period; //PCM sync period (16/32/64/128/256) ++ u32 pcm_sync_type; //PCM sync symbol size (0: short sync, 1: long sync) ++ u32 pcm_start_slot; //PCM start slot index (1--4) ++ u32 pcm_lsb_first; //0: MSB first, 1: LSB first ++ u32 pcm_ch_num; //PCM channel number (1: one channel, 2: two channel) + + }; + +--- a/sound/soc/sunxi/i2s/sunxi-i2sdma.c ++++ b/sound/soc/sunxi/i2s/sunxi-i2sdma.c +@@ -32,21 +32,32 @@ + #include "sunxi-i2s.h" + #include "sunxi-i2sdma.h" + +-static volatile unsigned int dmasrc = 0; +-static volatile unsigned int dmadst = 0; +- +-//DMA data width +-static unsigned int dma_width = 16; +- ++static const struct snd_pcm_hardware sunxi_pcm_out_hardware = { ++ .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | ++ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | ++ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, ++ .rates = SNDRV_PCM_RATE_8000_384000 | SNDRV_PCM_RATE_KNOT, ++ .rate_min = 8000, ++ .rate_max = 384000, ++ .channels_min = 1, ++ .channels_max = 2, ++ .buffer_bytes_max = 128*1024, /* value must be (2^n)Kbyte size */ ++ .period_bytes_min = 1024*4,//1024*4, ++ .period_bytes_max = 1024*32,//1024*32, ++ .periods_min = 4,//4, ++ .periods_max = 8,//8, ++ .fifo_size = 128, ++}; + +-static const struct snd_pcm_hardware sunxi_pcm_hardware = { ++static const struct snd_pcm_hardware sunxi_pcm_in_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, +- .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT, ++ .rates = SNDRV_PCM_RATE_8000_384000 | SNDRV_PCM_RATE_KNOT, + .rate_min = 8000, +- .rate_max = 192000, ++ .rate_max = 384000, + .channels_min = 1, + .channels_max = 2, + .buffer_bytes_max = 128*1024, /* value must be (2^n)Kbyte size */ +@@ -54,7 +65,7 @@ static const struct snd_pcm_hardware sunxi_pcm_hardware = { + .period_bytes_max = 1024*32,//1024*32, + .periods_min = 4,//4, + .periods_max = 8,//8, +- .fifo_size = 128,//32, ++ .fifo_size = 64, + }; + + struct sunxi_runtime_data { +@@ -67,32 +78,32 @@ struct sunxi_runtime_data { + dma_addr_t dma_pos; + dma_addr_t dma_end; + struct sunxi_dma_params *params; ++ /*DMA data width*/ ++ unsigned int dma_width; + }; + + static void sunxi_pcm_enqueue(struct snd_pcm_substream *substream) + { ++ int ret = 0; + struct sunxi_runtime_data *prtd = substream->runtime->private_data; + dma_addr_t pos = prtd->dma_pos; +- unsigned int limit; +- int ret; +- + unsigned long len = prtd->dma_period; +- limit = prtd->dma_limit; +- while(prtd->dma_loaded < limit) { +- if((pos + len) > prtd->dma_end) { ++ unsigned int limit = prtd->dma_limit; ++ int read = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; ++ ++ while(prtd->dma_loaded < limit){ ++ if((pos + len) > prtd->dma_end){ + len = prtd->dma_end - pos; + } +- +- ret = sunxi_dma_enqueue(prtd->params, pos, len, 0); +- if(ret == 0) { ++ ret = sunxi_dma_enqueue(prtd->params, pos, len, read); ++ if(ret == 0){ + prtd->dma_loaded++; + pos += prtd->dma_period; + if(pos >= prtd->dma_end) + pos = prtd->dma_start; +- }else { ++ }else{ + break; + } +- + } + prtd->dma_pos = pos; + } +@@ -129,31 +140,32 @@ static int sunxi_pcm_hw_params(struct snd_pcm_substream *substream, + if (!dma) + return 0; + ++ prtd->dma_width = 16; + /* set DMA width for using in sunxi_pcm_prepare*/ + switch(params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: +- dma_width = 16; ++ prtd->dma_width = 16; + break; + case SNDRV_PCM_FORMAT_S20_3LE: +- dma_width = 32; ++ prtd->dma_width = 32; + break; + case SNDRV_PCM_FORMAT_S24_LE: +- dma_width = 32; ++ prtd->dma_width = 32; + break; + } +- /*printk("[IIS-0] sunxi_pcm_hw_params: dma width %d bit\n", dma_width);*/ +- + if (prtd->params == NULL) { + prtd->params = dma; + ret = sunxi_dma_request(prtd->params, 0); + if (ret < 0) { +- return ret; ++ printk("[IIS-0] sunxi_dma_request failed! ret == %d\n", ret); ++ return ret; + } + } + + if (sunxi_dma_set_callback(prtd->params, sunxi_audio_buffdone, + substream) != 0) { + sunxi_dma_release(prtd->params); ++ printk("[IIS-0] sunxi_dma_set_callback failed! ret == %d\n", ret); + prtd->params = NULL; + return -EINVAL; + } +@@ -169,6 +181,7 @@ static int sunxi_pcm_hw_params(struct snd_pcm_substream *substream, + prtd->dma_start = runtime->dma_addr; + prtd->dma_pos = prtd->dma_start; + prtd->dma_end = prtd->dma_start + totbytes; ++ + spin_unlock_irq(&prtd->lock); + return 0; + } +@@ -215,8 +228,8 @@ static int sunxi_pcm_prepare(struct snd_pcm_substream *substream) + dma_config_t codec_dma_conf; + memset(&codec_dma_conf, 0, sizeof(codec_dma_conf)); + +- /*printk("[IIS-0] sunxi_pcm_prepare: DMA data width=(%d)\n", dma_width);*/ +- if(dma_width > 16) ++ printk("[IIS-0] sunxi_pcm_prepare: playback DMA data width=(%d)\n", prtd->dma_width); ++ if(prtd->dma_width > 16) + { + codec_dma_conf.xfer_type.src_data_width = DATA_WIDTH_32BIT; + codec_dma_conf.xfer_type.dst_data_width = DATA_WIDTH_32BIT; +@@ -226,16 +239,42 @@ static int sunxi_pcm_prepare(struct snd_pcm_substream *substream) + codec_dma_conf.xfer_type.src_data_width = DATA_WIDTH_16BIT; + codec_dma_conf.xfer_type.dst_data_width = DATA_WIDTH_16BIT; + } +- codec_dma_conf.xfer_type.src_bst_len = DATA_BRST_1; +-// codec_dma_conf.xfer_type.src_bst_len = DATA_BRST_4; /*like SPDIF module?*/ +- codec_dma_conf.xfer_type.dst_bst_len = DATA_BRST_1; +-// codec_dma_conf.xfer_type.src_bst_len = DATA_BRST_4; /*like SPDIF module?*/ ++ codec_dma_conf.xfer_type.src_bst_len = DATA_BRST_4; ++ codec_dma_conf.xfer_type.dst_bst_len = DATA_BRST_4; + codec_dma_conf.address_type.src_addr_mode = NDMA_ADDR_INCREMENT; + codec_dma_conf.address_type.dst_addr_mode = NDMA_ADDR_NOCHANGE; + codec_dma_conf.src_drq_type = N_SRC_SDRAM; + codec_dma_conf.dst_drq_type = N_DST_IIS0_TX; + codec_dma_conf.bconti_mode = false; +- codec_dma_conf.irq_spt = CHAN_IRQ_FD; ++ codec_dma_conf.irq_spt = CHAN_IRQ_FD; //buf full done irq ++#endif ++ ret = sunxi_dma_config(prtd->params, &codec_dma_conf, 0); ++ } ++ else { ++#if defined CONFIG_ARCH_SUN4I || defined CONFIG_ARCH_SUN5I ++#else ++ dma_config_t codec_dma_conf; ++ memset(&codec_dma_conf, 0, sizeof(codec_dma_conf)); ++ ++ printk("[IIS-0] sunxi_pcm_prepare: capture DMA data width=(%d)\n", prtd->dma_width); ++ if(prtd->dma_width > 16) ++ { ++ codec_dma_conf.xfer_type.src_data_width = DATA_WIDTH_32BIT; ++ codec_dma_conf.xfer_type.dst_data_width = DATA_WIDTH_32BIT; ++ } ++ else ++ { ++ codec_dma_conf.xfer_type.src_data_width = DATA_WIDTH_16BIT; ++ codec_dma_conf.xfer_type.dst_data_width = DATA_WIDTH_16BIT; ++ } ++ codec_dma_conf.xfer_type.src_bst_len = DATA_BRST_4; ++ codec_dma_conf.xfer_type.dst_bst_len = DATA_BRST_4; ++ codec_dma_conf.address_type.src_addr_mode = NDMA_ADDR_NOCHANGE; ++ codec_dma_conf.address_type.dst_addr_mode = NDMA_ADDR_INCREMENT; ++ codec_dma_conf.src_drq_type = N_SRC_IIS0_RX; ++ codec_dma_conf.dst_drq_type = N_DST_SDRAM; ++ codec_dma_conf.bconti_mode = false; ++ codec_dma_conf.irq_spt = CHAN_IRQ_FD; //buf full done irq + #endif + ret = sunxi_dma_config(prtd->params, &codec_dma_conf, 0); + } +@@ -261,15 +300,16 @@ static int sunxi_pcm_trigger(struct snd_pcm_substream *substream, int cmd) + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: +- printk("[IIS] dma trigger start\n"); +- printk("[IIS] 0x01c22400+0x24 = %#x, line= %d\n", readl(0xf1c22400+0x24), __LINE__); ++ printk("[IIS-0] dma trigger start\n"); ++ prtd->state |= ST_RUNNING; + sunxi_dma_start(prtd->params); + break; + + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: +- printk("[IIS] dma trigger stop\n"); ++ printk("[IIS-0] dma trigger stop\n"); ++ prtd->state &= ~ST_RUNNING; + sunxi_dma_stop(prtd->params); + break; + +@@ -288,31 +328,42 @@ static snd_pcm_uframes_t sunxi_pcm_pointer(struct snd_pcm_substream *substream) + struct sunxi_runtime_data *prtd = runtime->private_data; + unsigned long res = 0; + snd_pcm_uframes_t offset = 0; ++ unsigned int dmasrc = 0; ++ unsigned int dmadst = 0; + + spin_lock(&prtd->lock); + sunxi_dma_getcurposition(prtd->params, +- (dma_addr_t*)&dmasrc, (dma_addr_t*)&dmadst); ++ (dma_addr_t*)&dmasrc, (dma_addr_t*)&dmadst); + +- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) +- res = dmadst - prtd->dma_start; +- else +- { +- offset = bytes_to_frames(runtime, dmasrc + prtd->dma_period - runtime->dma_addr); ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ res = dmasrc + prtd->dma_period - prtd->dma_start; + } ++ else { ++ res = dmadst + prtd->dma_period - prtd->dma_start; ++ //res = dmadst - prtd->dma_start; ++ } ++ offset = bytes_to_frames(runtime, res); + spin_unlock(&prtd->lock); + + if(offset >= runtime->buffer_size) + offset = 0; +- return offset; ++ ++ return offset; + } + ++ + static int sunxi_pcm_open(struct snd_pcm_substream *substream) + { + struct snd_pcm_runtime *runtime = substream->runtime; + struct sunxi_runtime_data *prtd; + + snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); +- snd_soc_set_runtime_hwparams(substream, &sunxi_pcm_hardware); ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ snd_soc_set_runtime_hwparams(substream, &sunxi_pcm_out_hardware); ++ } ++ else { ++ snd_soc_set_runtime_hwparams(substream, &sunxi_pcm_in_hardware); ++ } + + prtd = kzalloc(sizeof(struct sunxi_runtime_data), GFP_KERNEL); + if (prtd == NULL) +@@ -361,13 +412,19 @@ static int sunxi_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) + { + struct snd_pcm_substream *substream = pcm->streams[stream].substream; + struct snd_dma_buffer *buf = &substream->dma_buffer; +- size_t size = sunxi_pcm_hardware.buffer_bytes_max; +- ++ size_t size = 0; ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ size = sunxi_pcm_out_hardware.buffer_bytes_max; ++ } ++ else { ++ size = sunxi_pcm_in_hardware.buffer_bytes_max; ++ } + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = pcm->card->dev; + buf->private_data = NULL; + buf->area = dma_alloc_writecombine(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); ++ + if (!buf->area) + return -ENOMEM; + buf->bytes = size; +--- a/sound/soc/sunxi/i2s/sunxi-sndi2s.c ++++ b/sound/soc/sunxi/i2s/sunxi-sndi2s.c +@@ -29,12 +29,6 @@ + + #include "sndi2s.h" + +-/* cleaning code +-static struct clk *xtal; +-static int clk_users; +-static DEFINE_MUTEX(clk_lock); +-*/ +- + /* slave mode flag*/ + static int sunxi_i2s_slave = 0; + +@@ -50,7 +44,7 @@ static int sunxi_sndi2s_startup(struct snd_pcm_substream *substream) + { + int ret = 0; + #ifdef ENFORCE_RATES +- struct snd_pcm_runtime *runtime = substream->runtime;; ++ struct snd_pcm_runtime *runtime = substream->runtime; + #endif + + if (!ret) { +@@ -67,16 +61,6 @@ static int sunxi_sndi2s_startup(struct snd_pcm_substream *substream) + + static void sunxi_sndi2s_shutdown(struct snd_pcm_substream *substream) + { +-/* cleaning code +- mutex_lock(&clk_lock); +- clk_users -= 1; +- if (clk_users == 0) { +- clk_put(xtal); +- xtal = NULL; +- +- } +- mutex_unlock(&clk_lock); +-*/ + } + + typedef struct __MCLK_SET_INF +@@ -194,6 +178,11 @@ static __extclk_set_inf EXTCLK_INF[] = + //192k bitrate + { 192000, 128, 0}, + ++ //352.8k bitrate ++ { 352800, 64, 1}, ++ //384 bitrate ++ { 384000, 64, 0}, ++ + //end flag 0xffffffff + {0xffffffff, 0, 0} + }; +@@ -253,33 +242,13 @@ static int sunxi_sndi2s_hw_params(struct snd_pcm_substream *substream, + int ret = 0; + unsigned long rate = params_rate(params); + u32 mclk_div=0, mpll=0, bclk_div=0, mult_fs=0; +-/* +- printk("[IIS-0] sunxi_sndi2s_hw_params: codec_dai=(%s), cpu_dai=(%s)\n", codec_dai->name, cpu_dai->name); +- printk("[IIS-0] sunxi_sndi2s_hw_params: channel num=(%d)\n", params_channels(params)); +- printk("[IIS-0] sunxi_sndi2s_hw_params: sample rate=(%lu)\n", rate); + +- switch (params_format(params)) +- { +- case SNDRV_PCM_FORMAT_S16_LE: +- printk("[IIS-0] sunxi_sndi2s_hw_params: format 16 bit\n"); +- break; +- case SNDRV_PCM_FORMAT_S20_3LE: +- printk("[IIS-0] sunxi_sndi2s_hw_params: format 20 bit in 3 bytes\n"); +- break; +- case SNDRV_PCM_FORMAT_S24_LE: +- printk("[IIS-0] sunxi_sndi2s_hw_params: format 24 bit in 4 bytes\n"); +- break; +- default: +- printk("[IIS-0] sunxi_sndi2s_hw_params: Unsupported format (%d)\n", (int)params_format(params)); +- //return -EINVAL; +- } +-*/ + if(!sunxi_i2s_slave) { +- get_clock_divder_master(rate, 32, &mclk_div, &mpll, &bclk_div, &mult_fs); ++ get_clock_divder_master(rate, /*fixed sample width*/32, &mclk_div, &mpll, &bclk_div, &mult_fs); + printk("[IIS-0] get_clock_divder_master: rate=(%lu), mclk_div=(%d), mpll=(%d), bclk_div=(%d), mult_fs=(%d)\n", + rate, mclk_div, mpll, bclk_div, mult_fs); + } else { +- get_clock_divder_slave(rate, 32, &bclk_div, &mpll, &mult_fs); ++ get_clock_divder_slave(rate, /*fixed sample width*/32, &bclk_div, &mpll, &mult_fs); + printk("[IIS-0] get_clock_divder_slave: rate=(%lu), bclk_div=(%d), mpll=(%d), mult_fs=(%d)\n", + rate, bclk_div, mpll, mult_fs); + } +@@ -383,7 +352,7 @@ static int __init sunxi_sndi2s_init(void) + { + int ret, i2s_used = 0, i2s_slave = 0; + +- printk("[IIS]Entered %s\n", __func__); ++ printk("[I2S-0] Entered %s\n", __func__); + + ret = script_parser_fetch("i2s_para", "i2s_used", &i2s_used, 1); + if (ret != 0 || !i2s_used) +--- a/sound/soc/sunxi/spdif/sndspdif.c ++++ b/sound/soc/sunxi/spdif/sndspdif.c +@@ -26,7 +26,7 @@ + #include "sndspdif.h" + + #define SNDSPDIF_RATES (SNDRV_PCM_RATE_8000_192000|SNDRV_PCM_RATE_KNOT) +-#define SNDSPDIF_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) ++#define SNDSPDIF_FORMATS (SNDRV_PCM_FMTBIT_S16_LE|SNDRV_PCM_FMTBIT_S20_3LE| SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + + struct sndspdif_priv { + int sysclk; +@@ -94,9 +94,18 @@ struct snd_soc_dai_driver sndspdif_dai = { + .rates = SNDSPDIF_RATES, + .formats = SNDSPDIF_FORMATS, + }, ++ .capture = { ++ .stream_name = "Capture", ++ .channels_min = 1, ++ .channels_max = 2, ++ .rates = SNDSPDIF_RATES, ++ .formats = SNDSPDIF_FORMATS, ++ }, + /* pcm operations */ + .ops = &sndspdif_dai_ops, ++ //clear start? + .symmetric_rates = 1, ++ //clear end? + }; + EXPORT_SYMBOL(sndspdif_dai); + +@@ -106,7 +115,7 @@ static int sndspdif_soc_probe(struct snd_soc_codec *codec) + + sndspdif = kzalloc(sizeof(struct sndspdif_priv), GFP_KERNEL); + if(sndspdif == NULL){ +- printk("%s,%d\n",__func__,__LINE__); ++ pr_err("[SPDIF] try to alloc sndspdif failed %s,%d\n", __func__,__LINE__); + return -ENOMEM; + } + snd_soc_codec_set_drvdata(codec, sndspdif); +@@ -161,22 +170,27 @@ static int __init sndspdif_codec_init(void) + int ret, spdif_used = 0; + + ret = script_parser_fetch("spdif_para", "spdif_used", &spdif_used, 1); +- if (ret != 0 || !spdif_used) ++ if (ret != 0 || !spdif_used) { ++ printk("[SPDIF] [spdif_para] isn't defined or spdif_used=0\n"); + return -ENODEV; ++ } + + spd_gpio_hdle = gpio_request_ex("spdif_para", "spdif_dout"); + if (0 == spd_gpio_hdle) { +- pr_err("try to request spdif_para gpio failed\n"); ++ pr_err("[SPDIF] try to request spdif_para gpio failed %s,%d\n", __func__,__LINE__); + return -1; + } + + ret = platform_device_register(&sndspdif_codec_device); +- if (ret < 0) ++ if (ret < 0) { ++ pr_err("[SPDIF] try to SPDIF platform_device_register failed (ret=(%d)) failed %s,%d\n", ret, __func__,__LINE__); + return ret; ++ } + + ret = platform_driver_register(&sndspdif_codec_driver); + if (ret < 0) { + platform_device_unregister(&sndspdif_codec_device); ++ pr_err("[SPDIF] try to SPDIF platform_driver_register failed (ret=(%d)) failed %s,%d\n", ret, __func__,__LINE__); + return ret; + } + + +--- a/sound/soc/sunxi/spdif/sunxi_sndspdif.c ++++ b/sound/soc/sunxi/spdif/sunxi_sndspdif.c +@@ -45,7 +45,7 @@ static int sunxi_sndspdif_startup(struct snd_pcm_substream *substream) + { + int ret = 0; + #ifdef ENFORCE_RATES +- struct snd_pcm_runtime *runtime = substream->runtime;; ++ struct snd_pcm_runtime *runtime = substream->runtime; + #endif + if (!ret) { + #ifdef ENFORCE_RATES +@@ -71,7 +71,7 @@ static void sunxi_sndspdif_shutdown(struct snd_pcm_substream *substream) + typedef struct __MCLK_SET_INF + { + __u32 samp_rate; // sample rate +- __u16 mult_fs; // multiply of smaple rate ++ __u16 mult_fs; // multiply of smaple rate + + __u8 clk_div; // mpll division + __u8 mpll; // select mpll, 0 - 24.576 Mhz, 1 - 22.5792 Mhz +@@ -83,7 +83,7 @@ typedef struct __BCLK_SET_INF + { + __u8 bitpersamp; // bits per sample + __u8 clk_div; // clock division +- __u16 mult_fs; // multiplay of sample rate ++ __u16 mult_fs; // multiply of sample rate + + } __bclk_set_inf; + +@@ -218,13 +218,13 @@ static struct snd_soc_ops sunxi_sndspdif_ops = { + }; + + static struct snd_soc_dai_link sunxi_sndspdif_dai_link = { +- .name = "SPDIF", ++ .name = "SPDIF", + .stream_name = "SUNXI-SPDIF", + .cpu_dai_name = "sunxi-spdif.0", + .codec_dai_name = "sndspdif", + .platform_name = "sunxi-spdif-pcm-audio.0", + .codec_name = "sunxi-spdif-codec.0", +- .ops = &sunxi_sndspdif_ops, ++ .ops = &sunxi_sndspdif_ops, + }; + + static struct snd_soc_card snd_soc_sunxi_sndspdif = { +@@ -236,6 +236,12 @@ static struct snd_soc_card snd_soc_sunxi_sndspdif = { + + static int __devinit sunxi_sndspdif_probe(struct platform_device *pdev) + { ++ int ret, spdif_used = 0; ++ ++ ret = script_parser_fetch("spdif_para", "spdif_used", &spdif_used, 1); ++ if (ret != 0 || !spdif_used) ++ return -ENODEV; ++ + snd_soc_sunxi_sndspdif.dev = &pdev->dev; + return snd_soc_register_card(&snd_soc_sunxi_sndspdif); + } + +--- a/sound/soc/sunxi/spdif/sunxi_spdif.c ++++ b/sound/soc/sunxi/spdif/sunxi_spdif.c +@@ -37,7 +37,7 @@ + #include "sunxi_spdma.h" + #include "sunxi_spdif.h" + +-static int regsave[6]; ++static int regsave[9]; + + static struct sunxi_dma_params sunxi_spdif_stereo_out = { + .client.name = "SPDIF out", +@@ -48,9 +48,9 @@ static struct sunxi_dma_params sunxi_spdif_stereo_out = { + }; + + static struct sunxi_dma_params sunxi_spdif_stereo_in = { +- .client.name = "SPDIF out", ++ .client.name = "SPDIF in", + #if defined CONFIG_ARCH_SUN4I || defined CONFIG_ARCH_SUN5I +- .channel = DMACH_NSPDIF, ++ .channel = DMACH_NSPDIF, //??? + #endif + .dma_addr = SUNXI_SPDIFBASE + SUNXI_SPDIF_RXFIFO, + }; +@@ -63,34 +63,33 @@ void sunxi_snd_txctrl(struct snd_pcm_substream *substream, int on) + { + u32 reg_val; + ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); + if (substream->runtime->channels == 1) { +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); + reg_val |= SUNXI_SPDIF_TXCFG_SINGLEMOD; +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); + } ++ else { ++ reg_val &= ~SUNXI_SPDIF_TXCFG_SINGLEMOD; ++ } ++ reg_val |= SUNXI_SPDIF_TXCFG_ASS; //Sending the last audio (may be 0?) ++ reg_val |= SUNXI_SPDIF_TXCFG_CHSTMODE; //Channel status A&B generated form TX_CHSTA ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); + +- //soft reset SPDIF +- writel(0x1, sunxi_spdif.regs + SUNXI_SPDIF_CTL); +- +- //MCLK OUTPUT enable +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_CTL); +- reg_val |= SUNXI_SPDIF_CTL_MCLKOUTEN; +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_CTL); +- +- //flush TX FIFO ++ /*flush TX FIFO and set FIFO empty trigger level*/ + reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL); +- reg_val |= SUNXI_SPDIF_FCTL_FTX; ++ reg_val |= SUNXI_SPDIF_FCTL_TXTL(0x10); //TX FIFO empty Trigger Level ++ reg_val |= SUNXI_SPDIF_FCTL_FTX; //flush TX FIFO + writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_FCTL); + +- //clear interrupt status ++ /*clear interrupt status*/ + reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_ISTA); ++ reg_val |= SUNXI_SPDIF_ISTA_TXCLR; + writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_ISTA); + +- //clear TX counter ++ /*clear TX counter*/ + writel(0, sunxi_spdif.regs + SUNXI_SPDIF_TXCNT); + + if (on) { +- //SPDIF TX ENBALE ++ //SPDIF TX ENABLE + reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); + reg_val |= SUNXI_SPDIF_TXCFG_TXEN; + writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); +@@ -99,13 +98,8 @@ void sunxi_snd_txctrl(struct snd_pcm_substream *substream, int on) + reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_INT); + reg_val |= SUNXI_SPDIF_INT_TXDRQEN; + writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_INT); +- +- //global enable +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_CTL); +- reg_val |= SUNXI_SPDIF_CTL_GEN; +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_CTL); + } else { +- //SPDIF TX DISABALE ++ //SPDIF TX DISABLE + reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); + reg_val &= ~SUNXI_SPDIF_TXCFG_TXEN; + writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); +@@ -114,16 +108,48 @@ void sunxi_snd_txctrl(struct snd_pcm_substream *substream, int on) + reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_INT); + reg_val &= ~SUNXI_SPDIF_INT_TXDRQEN; + writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_INT); +- +- //global disable +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_CTL); +- reg_val &= ~SUNXI_SPDIF_CTL_GEN; +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_CTL); + } + } + +-void sunxi_snd_rxctrl(int on) ++void sunxi_snd_rxctrl(struct snd_pcm_substream *substream, int on) + { ++ u32 reg_val; ++ ++ /*flush RX FIFO and set FIFO empty trigger level*/ ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL); ++ reg_val |= SUNXI_SPDIF_FCTL_RXTL(0x0F); //RX FIFO Trigger Level ++ reg_val |= SUNXI_SPDIF_FCTL_FRX; //flush RX FIFO ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_FCTL); ++ ++ /*clear interrupt status*/ ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_ISTA); ++ reg_val |= SUNXI_SPDIF_ISTA_RXCLR; ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_ISTA); ++ ++ /*clear RX counter*/ ++ writel(0, sunxi_spdif.regs + SUNXI_SPDIF_RXCNT); ++ ++ if (on) { ++ /*SPDIF RX ENABLE*/ ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_RXCFG); ++ reg_val |= SUNXI_SPDIF_RXCFG_RXEN; ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_RXCFG); ++ ++ /*DRQ ENABLE*/ ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_INT); ++ reg_val |= SUNXI_SPDIF_INT_RXDRQEN; ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_INT); ++ } else { ++ /*SPDIF TX DISABLE*/ ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_RXCFG); ++ reg_val &= ~SUNXI_SPDIF_RXCFG_RXEN; ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_RXCFG); ++ ++ /*DRQ DISABLE*/ ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_INT); ++ reg_val &= ~SUNXI_SPDIF_INT_RXDRQEN; ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_INT); ++ } + } + + static inline int sunxi_snd_is_clkmaster(void) +@@ -135,63 +161,122 @@ static int sunxi_spdif_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) + { + u32 reg_val; + +- reg_val = 0; +- reg_val &= ~SUNXI_SPDIF_TXCFG_SINGLEMOD; +- reg_val |= SUNXI_SPDIF_TXCFG_ASS; +- reg_val &= ~SUNXI_SPDIF_TXCFG_NONAUDIO; +- reg_val |= SUNXI_SPDIF_TXCFG_FMT16BIT; +- reg_val |= SUNXI_SPDIF_TXCFG_CHSTMODE; +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); +- +- reg_val = 0; +- reg_val &= ~SUNXI_SPDIF_FCTL_FIFOSRC; +- reg_val |= SUNXI_SPDIF_FCTL_TXTL(16); +- reg_val |= SUNXI_SPDIF_FCTL_RXTL(15); +- reg_val |= SUNXI_SPDIF_FCTL_TXIM(1); +- reg_val |= SUNXI_SPDIF_FCTL_RXOM(3); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_FCTL); +- + if (!fmt) {//PCM +- reg_val = 0; ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); ++ reg_val &= ~SUNXI_SPDIF_TXCFG_NONAUDIO; ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); ++ ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); + reg_val |= (SUNXI_SPDIF_TXCHSTA0_CHNUM(2)); ++ reg_val &= ~SUNXI_SPDIF_TXCHSTA0_AUDIO; + writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); + +- reg_val = 0; +- reg_val |= (SUNXI_SPDIF_TXCHSTA1_SAMWORDLEN(1)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_RXCHSTA0); ++ reg_val |= (SUNXI_SPDIF_RXCHSTA0_CHNUM(2)); ++ reg_val &= ~SUNXI_SPDIF_RXCHSTA0_AUDIO; ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_RXCHSTA0); + } else { //non PCM + reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); + reg_val |= SUNXI_SPDIF_TXCFG_NONAUDIO; + writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); + +- reg_val = 0; ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); + reg_val |= (SUNXI_SPDIF_TXCHSTA0_CHNUM(2)); + reg_val |= SUNXI_SPDIF_TXCHSTA0_AUDIO; + writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); + +- reg_val = 0; +- reg_val |= (SUNXI_SPDIF_TXCHSTA1_SAMWORDLEN(1)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_RXCHSTA0); ++ reg_val |= (SUNXI_SPDIF_RXCHSTA0_CHNUM(2)); ++ reg_val |= SUNXI_SPDIF_RXCHSTA0_AUDIO; ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_RXCHSTA0); + } + + return 0; + } + + static int sunxi_spdif_hw_params(struct snd_pcm_substream *substream, +- struct snd_pcm_hw_params *params, +- struct snd_soc_dai *dai) ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai) + { + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct sunxi_dma_params *dma_data; ++ u32 reg_val, reg_val1; ++ int format; ++ switch (params_format(params)) ++ { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ format = 16; ++ break; ++ case SNDRV_PCM_FORMAT_S20_3LE: ++ format = 20; ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ format = 24; ++ break; ++ case SNDRV_PCM_FORMAT_S32_LE: ++ format = 24; ++ break; ++ default: ++ return -EINVAL; ++ } + +- /* play or record */ +- if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ /* playback or capture */ ++ if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + dma_data = &sunxi_spdif_stereo_out; +- else ++ ++ reg_val1 = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); ++ reg_val &= ~SUNXI_SPDIF_TXCFG_FMTRVD; ++ reg_val1 &= ~SUNXI_SPDIF_TXCHSTA1_MAXWORDLEN; ++ reg_val1 &= ~(SUNXI_SPDIF_TXCHSTA1_SAMWORDLEN(7)); ++ if(format == 16) { ++ reg_val |= SUNXI_SPDIF_TXCFG_FMT16BIT; ++ reg_val1 |= (SUNXI_SPDIF_TXCHSTA1_SAMWORDLEN(1)); ++ } ++ else if(format == 20) { ++ reg_val |= SUNXI_SPDIF_TXCFG_FMT20BIT; ++ reg_val1 |= SUNXI_SPDIF_TXCHSTA1_MAXWORDLEN; ++ reg_val1 |= (SUNXI_SPDIF_TXCHSTA1_SAMWORDLEN(1)); ++ } ++ else { ++ reg_val |= SUNXI_SPDIF_TXCFG_FMT24BIT; ++ reg_val1 |= SUNXI_SPDIF_TXCHSTA1_MAXWORDLEN; ++ reg_val1 |= (SUNXI_SPDIF_TXCHSTA1_SAMWORDLEN(5)); ++ } ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); ++ writel(reg_val1, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ ++ /* Set TX FIFO Input Mode */ ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL); ++ reg_val &= ~SUNXI_SPDIF_FCTL_TXIM1; //0. Valid data at the MSB of OWA_TXFIFO register ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_FCTL); ++ } ++ else { + dma_data = &sunxi_spdif_stereo_in; ++ /* Set TX FIFO Input Mode */ ++ reg_val1 = readl(sunxi_spdif.regs + SUNXI_SPDIF_RXCHSTA1); ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL); ++ reg_val &= ~SUNXI_SPDIF_FCTL_RXOM3; ++ reg_val1 &= ~SUNXI_SPDIF_RXCHSTA1_MAXWORDLEN; ++ reg_val1 &= ~(SUNXI_SPDIF_RXCHSTA1_SAMWORDLEN(7)); ++ ++ if(format == 16) { ++ reg_val |= SUNXI_SPDIF_FCTL_RXOM3; ++ reg_val1 |= (SUNXI_SPDIF_RXCHSTA1_SAMWORDLEN(1)); ++ } ++ else if(format == 20) { ++ reg_val1 |= SUNXI_SPDIF_RXCHSTA1_MAXWORDLEN; ++ reg_val1 |= (SUNXI_SPDIF_RXCHSTA1_SAMWORDLEN(1)); ++ } ++ else { ++ reg_val1 |= SUNXI_SPDIF_RXCHSTA1_MAXWORDLEN; ++ reg_val1 |= (SUNXI_SPDIF_RXCHSTA1_SAMWORDLEN(5)); ++ } + ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_FCTL); ++ writel(reg_val1, sunxi_spdif.regs + SUNXI_SPDIF_RXCHSTA1); ++ } + snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data); +- + return 0; + } + +@@ -208,7 +293,7 @@ static int sunxi_spdif_trigger(struct snd_pcm_substream *substream, + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { +- sunxi_snd_rxctrl(1); ++ sunxi_snd_rxctrl(substream, 1); + } else { + sunxi_snd_txctrl(substream, 1); + } +@@ -218,9 +303,9 @@ static int sunxi_spdif_trigger(struct snd_pcm_substream *substream, + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { +- sunxi_snd_rxctrl(0); ++ sunxi_snd_rxctrl(substream, 0); + } else { +- sunxi_snd_txctrl(substream, 0); ++ sunxi_snd_txctrl(substream, 0); + } + break; + default: +@@ -246,23 +331,31 @@ static int sunxi_spdif_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, + + static int sunxi_spdif_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div) + { +- u32 reg_val = 0; +- +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- reg_val &= ~(SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0xf)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); +- reg_val &= ~(SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0xf)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ u32 reg_val_txchsta0 = 0; ++ u32 reg_val_txchsta1 = 0; ++ u32 reg_val_rxchsta0 = 0; ++ u32 reg_val_rxchsta1 = 0; ++ u32 reg_val_txcfg = 0; + + switch(div_id) { + case SUNXI_DIV_MCLK: + { +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); +- reg_val &= ~SUNXI_SPDIF_TXCFG_TXRATIO(0x1F); +- reg_val |= SUNXI_SPDIF_TXCFG_TXRATIO(div-1); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); ++ reg_val_txchsta0 = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); ++ reg_val_txchsta0 &= ~(SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0xf)); ++ ++ reg_val_txchsta1 = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ reg_val_txchsta1 &= ~(SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0xf)); ++ ++ reg_val_rxchsta0 = readl(sunxi_spdif.regs + SUNXI_SPDIF_RXCHSTA0); ++ reg_val_rxchsta0 &= ~(SUNXI_SPDIF_RXCHSTA0_SAMFREQ(0xf)); ++ ++ reg_val_rxchsta1 = readl(sunxi_spdif.regs + SUNXI_SPDIF_RXCHSTA1); ++ reg_val_rxchsta1 &= ~(SUNXI_SPDIF_RXCHSTA1_ORISAMFREQ(0xf)); ++ ++ reg_val_txcfg = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); ++ reg_val_txcfg &= ~SUNXI_SPDIF_TXCFG_TXRATIO(0x1F); ++ reg_val_txcfg |= SUNXI_SPDIF_TXCFG_TXRATIO(div-1); ++ writel(reg_val_txcfg, sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); + + if(clk_get_rate(spdif_pll2clk) == 24576000) + { +@@ -270,67 +363,49 @@ static int sunxi_spdif_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int d + { + //24KHZ + case 8: +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- reg_val |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0x6)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); +- reg_val |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0x9)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ reg_val_txchsta0 |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0x6)); ++ reg_val_txchsta1 |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0x9)); ++ reg_val_rxchsta0 |= (SUNXI_SPDIF_RXCHSTA0_SAMFREQ(0x6)); ++ reg_val_rxchsta1 |= (SUNXI_SPDIF_RXCHSTA1_ORISAMFREQ(0x9)); + break; + + //32KHZ + case 6: +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- reg_val |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0x3)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); +- reg_val |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0xC)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ reg_val_txchsta0 |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0x3)); ++ reg_val_txchsta1 |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0xC)); ++ reg_val_rxchsta0 |= (SUNXI_SPDIF_RXCHSTA0_SAMFREQ(0x3)); ++ reg_val_rxchsta1 |= (SUNXI_SPDIF_RXCHSTA1_ORISAMFREQ(0xC)); + break; + + //48KHZ + case 4: +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- reg_val |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0x2)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); +- reg_val |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0xD)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ reg_val_txchsta0 |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0x2)); ++ reg_val_txchsta1 |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0xD)); ++ reg_val_rxchsta0 |= (SUNXI_SPDIF_RXCHSTA0_SAMFREQ(0x2)); ++ reg_val_rxchsta1 |= (SUNXI_SPDIF_RXCHSTA1_ORISAMFREQ(0xD)); + break; + + //96KHZ + case 2: +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- reg_val |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0xA)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); +- reg_val |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0x5)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ reg_val_txchsta0 |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0xA)); ++ reg_val_txchsta1 |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0x5)); ++ reg_val_rxchsta0 |= (SUNXI_SPDIF_RXCHSTA0_SAMFREQ(0xA)); ++ reg_val_rxchsta1 |= (SUNXI_SPDIF_RXCHSTA1_ORISAMFREQ(0x5)); + break; + + //192KHZ + case 1: +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- reg_val |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0xE)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); +- reg_val |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0x1)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ reg_val_txchsta0 |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0xE)); ++ reg_val_txchsta1 |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0x1)); ++ reg_val_rxchsta0 |= (SUNXI_SPDIF_RXCHSTA0_SAMFREQ(0xE)); ++ reg_val_rxchsta1 |= (SUNXI_SPDIF_RXCHSTA1_ORISAMFREQ(0x1)); + break; + + default: +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- reg_val |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(1)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); +- reg_val |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ reg_val_txchsta0 |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(1)); ++ reg_val_txchsta1 |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0)); ++ reg_val_rxchsta0 |= (SUNXI_SPDIF_RXCHSTA0_SAMFREQ(1)); ++ reg_val_rxchsta1 |= (SUNXI_SPDIF_RXCHSTA1_ORISAMFREQ(0)); + break; + } + }else{ //22.5792MHz +@@ -338,59 +413,50 @@ static int sunxi_spdif_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int d + { + //22.05khz + case 8: +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- reg_val |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0x4)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); +- reg_val |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0xb)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ reg_val_txchsta0 |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0x4)); ++ reg_val_txchsta1 |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0xb)); ++ reg_val_rxchsta0 |= (SUNXI_SPDIF_RXCHSTA0_SAMFREQ(0x4)); ++ reg_val_rxchsta1 |= (SUNXI_SPDIF_RXCHSTA1_ORISAMFREQ(0xb)); + break; + + //44.1KHZ + case 4: +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- reg_val |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0x0)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); +- reg_val |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0xF)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ reg_val_txchsta0 |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0x0)); ++ reg_val_txchsta1 |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0xF)); ++ reg_val_rxchsta0 |= (SUNXI_SPDIF_RXCHSTA0_SAMFREQ(0x0)); ++ reg_val_rxchsta1 |= (SUNXI_SPDIF_RXCHSTA1_ORISAMFREQ(0xF)); + break; + + //88.2khz + case 2: +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- reg_val |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0x8)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); +- reg_val |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0x7)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ reg_val_txchsta0 |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0x8)); ++ reg_val_txchsta1 |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0x7)); ++ reg_val_rxchsta0 |= (SUNXI_SPDIF_RXCHSTA0_SAMFREQ(0x8)); ++ reg_val_rxchsta1 |= (SUNXI_SPDIF_RXCHSTA1_ORISAMFREQ(0x7)); + break; + + //176.4KHZ + case 1: +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- reg_val |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0xC)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); +- reg_val |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0x3)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ reg_val_txchsta0 |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(0xC)); ++ reg_val_txchsta1 |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0x3)); ++ reg_val_rxchsta0 |= (SUNXI_SPDIF_RXCHSTA0_SAMFREQ(0xC)); ++ reg_val_rxchsta1 |= (SUNXI_SPDIF_RXCHSTA1_ORISAMFREQ(0x3)); + break; + + default: +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- reg_val |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(1)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); +- +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); +- reg_val |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0)); +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ reg_val_txchsta0 |= (SUNXI_SPDIF_TXCHSTA0_SAMFREQ(1)); ++ reg_val_txchsta1 |= (SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(0)); ++ reg_val_rxchsta0 |= (SUNXI_SPDIF_RXCHSTA0_SAMFREQ(1)); ++ reg_val_rxchsta1 |= (SUNXI_SPDIF_RXCHSTA1_ORISAMFREQ(0)); ++ + break; + } + } ++ writel(reg_val_txchsta0, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); ++ writel(reg_val_txchsta1, sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ ++ writel(reg_val_rxchsta0, sunxi_spdif.regs + SUNXI_SPDIF_RXCHSTA0); ++ writel(reg_val_rxchsta1, sunxi_spdif.regs + SUNXI_SPDIF_RXCHSTA1); + } + break; + case SUNXI_DIV_BCLK: +@@ -399,7 +465,6 @@ static int sunxi_spdif_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int d + default: + return -EINVAL; + } +- + return 0; + } + +@@ -422,10 +487,13 @@ static void spdifregsave(void) + { + regsave[0] = readl(sunxi_spdif.regs + SUNXI_SPDIF_CTL); + regsave[1] = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCFG); +- regsave[2] = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL) | (0x3<<16); ++ regsave[2] = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL) | (0x3<<16); //clear TX, RX fifo + regsave[3] = readl(sunxi_spdif.regs + SUNXI_SPDIF_INT); + regsave[4] = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); + regsave[5] = readl(sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ regsave[6] = readl(sunxi_spdif.regs + SUNXI_SPDIF_RXCFG); ++ regsave[7] = readl(sunxi_spdif.regs + SUNXI_SPDIF_RXCHSTA0); ++ regsave[8] = readl(sunxi_spdif.regs + SUNXI_SPDIF_RXCHSTA1); + } + + static void spdifregrestore(void) +@@ -436,14 +504,18 @@ static void spdifregrestore(void) + writel(regsave[3], sunxi_spdif.regs + SUNXI_SPDIF_INT); + writel(regsave[4], sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA0); + writel(regsave[5], sunxi_spdif.regs + SUNXI_SPDIF_TXCHSTA1); ++ writel(regsave[6], sunxi_spdif.regs + SUNXI_SPDIF_RXCFG); ++ writel(regsave[7], sunxi_spdif.regs + SUNXI_SPDIF_RXCHSTA0); ++ writel(regsave[8], sunxi_spdif.regs + SUNXI_SPDIF_RXCHSTA1); + } + + //#ifdef CONFIG_PM + static int sunxi_spdif_suspend(struct snd_soc_dai *cpu_dai) + { + u32 reg_val; +- printk("[SPDIF]Enter %s\n", __func__); ++ printk("[SPDIF] Enter %s\n", __func__); + ++ //global disable + reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_CTL); + reg_val &= ~SUNXI_SPDIF_CTL_GEN; + writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_CTL); +@@ -453,7 +525,9 @@ static int sunxi_spdif_suspend(struct snd_soc_dai *cpu_dai) + //disable the module clock + clk_disable(spdif_moduleclk); + ++ //clear start? + clk_disable(spdif_apbclk); ++ //clear end? + + printk("[SPDIF]SPECIAL CLK 0x01c20068 = %#x, line= %d\n", *(volatile int*)0xF1C20068, __LINE__); + printk("[SPDIF]SPECIAL CLK 0x01c200C0 = %#x, line= %d\n", *(volatile int*)0xF1C200C0, __LINE__); +@@ -464,9 +538,9 @@ static int sunxi_spdif_suspend(struct snd_soc_dai *cpu_dai) + static int sunxi_spdif_resume(struct snd_soc_dai *cpu_dai) + { + u32 reg_val; +- printk("[SPDIF]Enter %s\n", __func__); ++ printk("[SPDIF] Enter %s\n", __func__); + +- //disable the module clock ++ //enable the module clock + clk_enable(spdif_apbclk); + + //enable the module clock +@@ -474,11 +548,18 @@ static int sunxi_spdif_resume(struct snd_soc_dai *cpu_dai) + + spdifregrestore(); + ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL); ++ reg_val &= ~SUNXI_SPDIF_FCTL_FIFOSRC; //set TX FIFO source select as APB bus ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_FCTL); ++ + reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_CTL); ++ //soft reset SPDIF ++ reg_val |= SUNXI_SPDIF_CTL_RESET; ++ //global enable + reg_val |= SUNXI_SPDIF_CTL_GEN; + writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_CTL); + +- //printk("[SPDIF]PLL2 0x01c20008 = %#x\n", *(volatile int*)0xF1C20008); ++ printk("[SPDIF]PLL2 0x01c20008 = %#x\n", *(volatile int*)0xF1C20008); + printk("[SPDIF]SPECIAL CLK 0x01c20068 = %#x, line= %d\n", *(volatile int*)0xF1C20068, __LINE__); + printk("[SPDIF]SPECIAL CLK 0x01c200C0 = %#x, line = %d\n", *(volatile int*)0xF1C200C0, __LINE__); + +@@ -487,11 +568,11 @@ static int sunxi_spdif_resume(struct snd_soc_dai *cpu_dai) + + #define SUNXI_SPDIF_RATES (SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT) + static struct snd_soc_dai_ops sunxi_spdif_dai_ops = { +- .trigger = sunxi_spdif_trigger, ++ .trigger = sunxi_spdif_trigger, + .hw_params = sunxi_spdif_hw_params, +- .set_fmt = sunxi_spdif_set_fmt, +- .set_clkdiv = sunxi_spdif_set_clkdiv, +- .set_sysclk = sunxi_spdif_set_sysclk, ++ .set_fmt = sunxi_spdif_set_fmt, ++ .set_clkdiv = sunxi_spdif_set_clkdiv, ++ .set_sysclk = sunxi_spdif_set_sysclk, + }; + static struct snd_soc_dai_driver sunxi_spdif_dai = { + .probe = sunxi_spdif_dai_probe, +@@ -502,14 +583,14 @@ static struct snd_soc_dai_driver sunxi_spdif_dai = { + .channels_min = 1, + .channels_max = 2, + .rates = SUNXI_SPDIF_RATES, +- .formats = SNDRV_PCM_FMTBIT_S16_LE,}, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE|SNDRV_PCM_FMTBIT_S20_3LE| SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,}, + .capture = { + .channels_min = 1, + .channels_max = 2, + .rates = SUNXI_SPDIF_RATES, +- .formats = SNDRV_PCM_FMTBIT_S16_LE,}, +- .symmetric_rates = 1, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE|SNDRV_PCM_FMTBIT_S20_3LE| SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,}, + .ops = &sunxi_spdif_dai_ops, ++ .symmetric_rates = 1, + }; + + static int __devinit sunxi_spdif_dev_probe(struct platform_device *pdev) +@@ -521,46 +602,58 @@ static int __devinit sunxi_spdif_dev_probe(struct platform_device *pdev) + if(sunxi_spdif.regs == NULL) + return -ENXIO; + +- //spdif apbclk +- spdif_apbclk = clk_get(NULL, "apb_spdif"); +- if(-1 == clk_enable(spdif_apbclk)){ +- printk("spdif_apbclk failed! line = %d\n", __LINE__); +- } ++ //spdif apbclk ++ spdif_apbclk = clk_get(NULL, "apb_spdif"); ++ if(-1 == clk_enable(spdif_apbclk)){ ++ printk("spdif_apbclk failed! line = %d\n", __LINE__); ++ } + +- spdif_pllx8 = clk_get(NULL, "audio_pllx8"); ++ spdif_pllx8 = clk_get(NULL, "audio_pllx8"); + +- //spdif pll2clk +- spdif_pll2clk = clk_get(NULL, "audio_pll"); ++ //spdif pll2clk ++ spdif_pll2clk = clk_get(NULL, "audio_pll"); + +- //spdif module clk +- spdif_moduleclk = clk_get(NULL, "spdif"); ++ //spdif module clk ++ spdif_moduleclk = clk_get(NULL, "spdif"); + +- if(clk_set_parent(spdif_moduleclk, spdif_pll2clk)){ +- printk("try to set parent of spdif_moduleclk to spdif_pll2ck failed! line = %d\n",__LINE__); +- } ++ if(clk_set_parent(spdif_moduleclk, spdif_pll2clk)){ ++ printk("try to set parent of spdif_moduleclk to spdif_pll2ck failed! line = %d\n",__LINE__); ++ } + +- if(clk_set_rate(spdif_moduleclk, 24576000/8)){ +- printk("set spdif_moduleclk clock freq to 24576000 failed! line = %d\n", __LINE__); +- } ++ if(clk_set_rate(spdif_moduleclk, 24576000/8)){ ++ printk("set spdif_moduleclk clock freq to 24576000 failed! line = %d\n", __LINE__); ++ } + +- if(-1 == clk_enable(spdif_moduleclk)){ +- printk("open spdif_moduleclk failed! line = %d\n", __LINE__); +- } ++ if(-1 == clk_enable(spdif_moduleclk)){ ++ printk("open spdif_moduleclk failed! line = %d\n", __LINE__); ++ } + +- //global enbale +- reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_CTL); +- reg_val |= SUNXI_SPDIF_CTL_GEN; +- writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_CTL); ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_FCTL); ++ reg_val &= ~SUNXI_SPDIF_FCTL_FIFOSRC; //set TX FIFO source select as APB bus ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_FCTL); ++ ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_CTL); ++ //soft reset SPDIF ++ reg_val |= SUNXI_SPDIF_CTL_RESET; ++ //global enable ++ reg_val |= SUNXI_SPDIF_CTL_GEN; ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_CTL); + +- ret = snd_soc_register_dai(&pdev->dev, &sunxi_spdif_dai); ++ ret = snd_soc_register_dai(&pdev->dev, &sunxi_spdif_dai); + +- iounmap(sunxi_spdif.ioregs); ++ iounmap(sunxi_spdif.ioregs); + + return 0; + } + + static int __devexit sunxi_spdif_dev_remove(struct platform_device *pdev) + { ++ int reg_val = 0; ++ //global disable ++ reg_val = readl(sunxi_spdif.regs + SUNXI_SPDIF_CTL); ++ reg_val &= ~SUNXI_SPDIF_CTL_GEN; ++ writel(reg_val, sunxi_spdif.regs + SUNXI_SPDIF_CTL); ++ + /* release the module clock */ + clk_disable(spdif_moduleclk); + + +--- a/sound/soc/sunxi/spdif/sunxi_spdif.h ++++ b/sound/soc/sunxi/spdif/sunxi_spdif.h +@@ -17,127 +17,134 @@ + #define SUNXI_SPDIF_H_ + + /*------------------SPDIF register definition--------------------*/ +-#define SUNXI_SPDIFBASE 0x01C21000 ++#define SUNXI_SPDIFBASE 0x01C21000 + +-#define SUNXI_SPDIF_CTL (0x00) ++#define SUNXI_SPDIF_CTL (0x00) + #define SUNXI_SPDIF_CTL_MCLKDIV(v) ((v)<<4) //v even +- #define SUNXI_SPDIF_CTL_MCLKOUTEN (1<<2) +- #define SUNXI_SPDIF_CTL_GEN (1<<1) +- #define SUNXI_SPDIF_CTL_RESET (1<<0) ++ #define SUNXI_SPDIF_CTL_MCLKOUTEN (1<<2) ++ #define SUNXI_SPDIF_CTL_GEN (1<<1) ++ #define SUNXI_SPDIF_CTL_RESET (1<<0) + +-#define SUNXI_SPDIF_TXCFG (0x04) ++#define SUNXI_SPDIF_TXCFG (0x04) + #define SUNXI_SPDIF_TXCFG_SINGLEMOD (1<<31) +- #define SUNXI_SPDIF_TXCFG_ASS (1<<17) ++ #define SUNXI_SPDIF_TXCFG_ASS (1<<17) + #define SUNXI_SPDIF_TXCFG_NONAUDIO (1<<16) +- #define SUNXI_SPDIF_TXCFG_TXRATIO(v) ((v)<<4) +- #define SUNXI_SPDIF_TXCFG_FMTRVD (3<<2) ++ #define SUNXI_SPDIF_TXCFG_TXRATIO(v) ((v)<<4) ++ #define SUNXI_SPDIF_TXCFG_FMTRVD (3<<2) + #define SUNXI_SPDIF_TXCFG_FMT16BIT (0<<2) + #define SUNXI_SPDIF_TXCFG_FMT20BIT (1<<2) + #define SUNXI_SPDIF_TXCFG_FMT24BIT (2<<2) + #define SUNXI_SPDIF_TXCFG_CHSTMODE (1<<1) +- #define SUNXI_SPDIF_TXCFG_TXEN (1<<0) ++ #define SUNXI_SPDIF_TXCFG_TXEN (1<<0) + + #define SUNXI_SPDIF_RXCFG (0x08) + #define SUNXI_SPDIF_RXCFG_LOCKFLAG (1<<4) +- #define SUNXI_SPDIF_RXCFG_CHSTSRC (1<<3) +- #define SUNXI_SPDIF_RXCFG_CHSTCP (1<<1) +- #define SUNXI_SPDIF_RXCFG_RXEN (1<<0) +- +-#define SUNXI_SPDIF_TXFIFO (0x0C) +- +-#define SUNXI_SPDIF_RXFIFO (0x10) +- +-#define SUNXI_SPDIF_FCTL (0x14) +- #define SUNXI_SPDIF_FCTL_FIFOSRC (1<<31) +- #define SUNXI_SPDIF_FCTL_FTX (1<<17) +- #define SUNXI_SPDIF_FCTL_FRX (1<<16) +- #define SUNXI_SPDIF_FCTL_TXTL(v) ((v)<<8) +- #define SUNXI_SPDIF_FCTL_RXTL(v) (((v))<<3) +- #define SUNXI_SPDIF_FCTL_TXIM(v) ((v)<<2) +- #define SUNXI_SPDIF_FCTL_RXOM(v) ((v)<<0) +- +-#define SUNXI_SPDIF_FSTA (0x18) +- #define SUNXI_SPDIF_FSTA_TXE (1<<14) ++ #define SUNXI_SPDIF_RXCFG_CHSTSRC (1<<3) ++ #define SUNXI_SPDIF_RXCFG_CHSTCP (1<<1) ++ #define SUNXI_SPDIF_RXCFG_RXEN (1<<0) ++ ++#define SUNXI_SPDIF_TXFIFO (0x0C) ++ ++#define SUNXI_SPDIF_RXFIFO (0x10) ++ ++#define SUNXI_SPDIF_FCTL (0x14) ++ #define SUNXI_SPDIF_FCTL_FIFOSRC (1<<31) ++ #define SUNXI_SPDIF_FCTL_FTX (1<<17) ++ #define SUNXI_SPDIF_FCTL_FRX (1<<16) ++ #define SUNXI_SPDIF_FCTL_TXTL(v) ((v)<<8) ++ #define SUNXI_SPDIF_FCTL_RXTL(v) ((v)<<3) ++ #define SUNXI_SPDIF_FCTL_TXIM0 (0<<2) ++ #define SUNXI_SPDIF_FCTL_TXIM1 (1<<2) ++ #define SUNXI_SPDIF_FCTL_RXOM0 (0<<0) ++ #define SUNXI_SPDIF_FCTL_RXOM1 (1<<0) ++ #define SUNXI_SPDIF_FCTL_RXOM2 (2<<0) ++ #define SUNXI_SPDIF_FCTL_RXOM3 (3<<0) ++ ++#define SUNXI_SPDIF_FSTA (0x18) ++ #define SUNXI_SPDIF_FSTA_TXE (1<<14) + #define SUNXI_SPDIF_FSTA_TXECNTSHT (8) +- #define SUNXI_SPDIF_FSTA_RXA (1<<6) ++ #define SUNXI_SPDIF_FSTA_RXA (1<<6) + #define SUNXI_SPDIF_FSTA_RXACNTSHT (0) + +-#define SUNXI_SPDIF_INT (0x1C) +- #define SUNXI_SPDIF_INT_RXLOCKEN (1<<18) ++#define SUNXI_SPDIF_INT (0x1C) ++ #define SUNXI_SPDIF_INT_RXLOCKEN (1<<18) + #define SUNXI_SPDIF_INT_RXUNLOCKEN (1<<17) + #define SUNXI_SPDIF_INT_RXPARERREN (1<<16) +- #define SUNXI_SPDIF_INT_TXDRQEN (1<<7) +- #define SUNXI_SPDIF_INT_TXUIEN (1<<6) +- #define SUNXI_SPDIF_INT_TXOIEN (1<<5) +- #define SUNXI_SPDIF_INT_TXEIEN (1<<4) +- #define SUNXI_SPDIF_INT_RXDRQEN (1<<2) +- #define SUNXI_SPDIF_INT_RXOIEN (1<<1) +- #define SUNXI_SPDIF_INT_RXAIEN (1<<0) +- +-#define SUNXI_SPDIF_ISTA (0x20) ++ #define SUNXI_SPDIF_INT_TXDRQEN (1<<7) ++ #define SUNXI_SPDIF_INT_TXUIEN (1<<6) ++ #define SUNXI_SPDIF_INT_TXOIEN (1<<5) ++ #define SUNXI_SPDIF_INT_TXEIEN (1<<4) ++ #define SUNXI_SPDIF_INT_RXDRQEN (1<<2) ++ #define SUNXI_SPDIF_INT_RXOIEN (1<<1) ++ #define SUNXI_SPDIF_INT_RXAIEN (1<<0) ++ ++#define SUNXI_SPDIF_ISTA (0x20) + #define SUNXI_SPDIF_ISTA_RXLOCKSTA (1<<18) +- #define SUNXI_SPDIF_ISTA_RXUNLOCKSTA (1<<17) +- #define SUNXI_SPDIF_ISTA_RXPARERRSTA (1<<16) +- #define SUNXI_SPDIF_ISTA_TXUSTA (1<<6) +- #define SUNXI_SPDIF_ISTA_TXOSTA (1<<5) +- #define SUNXI_SPDIF_ISTA_TXESTA (1<<4) +- #define SUNXI_SPDIF_ISTA_RXOSTA (1<<1) +- #define SUNXI_SPDIF_ISTA_RXASTA (1<<0) +- +-#define SUNXI_SPDIF_TXCNT (0x24) +- +-#define SUNXI_SPDIF_RXCNT (0x28) +- +-#define SUNXI_SPDIF_TXCHSTA0 (0x2C) +- #define SUNXI_SPDIF_TXCHSTA0_CLK(v) ((v)<<28) +- #define SUNXI_SPDIF_TXCHSTA0_SAMFREQ(v) ((v)<<24) +- #define SUNXI_SPDIF_TXCHSTA0_CHNUM(v) ((v)<<20) +- #define SUNXI_SPDIF_TXCHSTA0_SRCNUM(v) ((v)<<16) +- #define SUNXI_SPDIF_TXCHSTA0_CATACOD(v) ((v)<<8) +- #define SUNXI_SPDIF_TXCHSTA0_MODE(v) ((v)<<6) +- #define SUNXI_SPDIF_TXCHSTA0_EMPHASIS(v) ((v)<<3) +- #define SUNXI_SPDIF_TXCHSTA0_CP (1<<2) +- #define SUNXI_SPDIF_TXCHSTA0_AUDIO (1<<1) +- #define SUNXI_SPDIF_TXCHSTA0_PRO (1<<0) +- +-#define SUNXI_SPDIF_TXCHSTA1 (0x30) +- #define SUNXI_SPDIF_TXCHSTA1_CGMSA(v) ((v)<<8) ++ #define SUNXI_SPDIF_ISTA_RXUNLOCKSTA (1<<17) ++ #define SUNXI_SPDIF_ISTA_RXPARERRSTA (1<<16) ++ #define SUNXI_SPDIF_ISTA_TXUSTA (1<<6) ++ #define SUNXI_SPDIF_ISTA_TXOSTA (1<<5) ++ #define SUNXI_SPDIF_ISTA_TXESTA (1<<4) ++ #define SUNXI_SPDIF_ISTA_RXOSTA (1<<1) ++ #define SUNXI_SPDIF_ISTA_RXASTA (1<<0) ++ #define SUNXI_SPDIF_ISTA_RXCLR (SUNXI_SPDIF_ISTA_RXLOCKSTA | SUNXI_SPDIF_ISTA_RXUNLOCKSTA | SUNXI_SPDIF_ISTA_RXPARERRSTA | SUNXI_SPDIF_ISTA_RXOSTA | SUNXI_SPDIF_ISTA_RXASTA) ++ #define SUNXI_SPDIF_ISTA_TXCLR (SUNXI_SPDIF_ISTA_TXUSTA | SUNXI_SPDIF_ISTA_TXOSTA | SUNXI_SPDIF_ISTA_TXESTA) ++ ++ ++#define SUNXI_SPDIF_TXCNT (0x24) ++ ++#define SUNXI_SPDIF_RXCNT (0x28) ++ ++#define SUNXI_SPDIF_TXCHSTA0 (0x2C) ++ #define SUNXI_SPDIF_TXCHSTA0_CLK(v) ((v)<<28) ++ #define SUNXI_SPDIF_TXCHSTA0_SAMFREQ(v) ((v)<<24) ++ #define SUNXI_SPDIF_TXCHSTA0_CHNUM(v) ((v)<<20) ++ #define SUNXI_SPDIF_TXCHSTA0_SRCNUM(v) ((v)<<16) ++ #define SUNXI_SPDIF_TXCHSTA0_CATACOD(v) ((v)<<8) ++ #define SUNXI_SPDIF_TXCHSTA0_MODE(v) ((v)<<6) ++ #define SUNXI_SPDIF_TXCHSTA0_EMPHASIS(v) ((v)<<3) ++ #define SUNXI_SPDIF_TXCHSTA0_CP (1<<2) ++ #define SUNXI_SPDIF_TXCHSTA0_AUDIO (1<<1) ++ #define SUNXI_SPDIF_TXCHSTA0_PRO (1<<0) ++ ++#define SUNXI_SPDIF_TXCHSTA1 (0x30) ++ #define SUNXI_SPDIF_TXCHSTA1_CGMSA(v) ((v)<<8) + #define SUNXI_SPDIF_TXCHSTA1_ORISAMFREQ(v) ((v)<<4) + #define SUNXI_SPDIF_TXCHSTA1_SAMWORDLEN(v) ((v)<<1) +- #define SUNXI_SPDIF_TXCHSTA1_MAXWORDLEN (1<<0) +- +-#define SUNXI_SPDIF_RXCHSTA0 (0x34) +- #define SUNXI_SPDIF_RXCHSTA0_CLK(v) ((v)<<28) +- #define SUNXI_SPDIF_RXCHSTA0_SAMFREQ(v) ((v)<<24) +- #define SUNXI_SPDIF_RXCHSTA0_CHNUM(v) ((v)<<20) +- #define SUNXI_SPDIF_RXCHSTA0_SRCNUM(v) ((v)<<16) +- #define SUNXI_SPDIF_RXCHSTA0_CATACOD(v) ((v)<<8) +- #define SUNXI_SPDIF_RXCHSTA0_MODE(v) ((v)<<6) +- #define SUNXI_SPDIF_RXCHSTA0_EMPHASIS(v) ((v)<<3) +- #define SUNXI_SPDIF_RXCHSTA0_CP (1<<2) +- #define SUNXI_SPDIF_RXCHSTA0_AUDIO (1<<1) +- #define SUNXI_SPDIF_RXCHSTA0_PRO (1<<0) +- +-#define SUNXI_SPDIF_RXCHSTA1 (0x38) +- #define SUNXI_SPDIF_RXCHSTA1_CGMSA(v) ((v)<<8) ++ #define SUNXI_SPDIF_TXCHSTA1_MAXWORDLEN (1<<0) ++ ++#define SUNXI_SPDIF_RXCHSTA0 (0x34) ++ #define SUNXI_SPDIF_RXCHSTA0_CLK(v) ((v)<<28) ++ #define SUNXI_SPDIF_RXCHSTA0_SAMFREQ(v) ((v)<<24) ++ #define SUNXI_SPDIF_RXCHSTA0_CHNUM(v) ((v)<<20) ++ #define SUNXI_SPDIF_RXCHSTA0_SRCNUM(v) ((v)<<16) ++ #define SUNXI_SPDIF_RXCHSTA0_CATACOD(v) ((v)<<8) ++ #define SUNXI_SPDIF_RXCHSTA0_MODE(v) ((v)<<6) ++ #define SUNXI_SPDIF_RXCHSTA0_EMPHASIS(v) ((v)<<3) ++ #define SUNXI_SPDIF_RXCHSTA0_CP (1<<2) ++ #define SUNXI_SPDIF_RXCHSTA0_AUDIO (1<<1) ++ #define SUNXI_SPDIF_RXCHSTA0_PRO (1<<0) ++ ++#define SUNXI_SPDIF_RXCHSTA1 (0x38) ++ #define SUNXI_SPDIF_RXCHSTA1_CGMSA(v) ((v)<<8) + #define SUNXI_SPDIF_RXCHSTA1_ORISAMFREQ(v) ((v)<<4) + #define SUNXI_SPDIF_RXCHSTA1_SAMWORDLEN(v) ((v)<<1) +- #define SUNXI_SPDIF_RXCHSTA1_MAXWORDLEN (1<<0) ++ #define SUNXI_SPDIF_RXCHSTA1_MAXWORDLEN (1<<0) + + /*--------------------------------CCM register definition---------------------*/ +-#define SUNXI_CCMBASE (0x01C20000) ++#define SUNXI_CCMBASE (0x01C20000) + +-#define SUNXI_CCMBASE_AUDIOHOSCPLL (0x08) +- #define SUNXI_CCMBASE_AUDIOHOSCPLL_EN (1<<31) +- #define SUNXI_CCMBASE_AUDIOHOSCPLL_24576M (1<<27) +- #define SUNXI_CCMBASE_AUDIOHOSCPLL_225792M (0<<27) ++#define SUNXI_CCMBASE_AUDIOHOSCPLL (0x08) ++ #define SUNXI_CCMBASE_AUDIOHOSCPLL_EN (1<<31) ++ #define SUNXI_CCMBASE_AUDIOHOSCPLL_24576M (1<<27) ++ #define SUNXI_CCMBASE_AUDIOHOSCPLL_225792M (0<<27) + +-#define SUNXI_CCMBASE_APBGATE (0x68) +- #define SUNXI_CCMBASE_APBGATE_SPDIFGATE (1<<1) ++#define SUNXI_CCMBASE_APBGATE (0x68) ++ #define SUNXI_CCMBASE_APBGATE_SPDIFGATE (1<<1) + +-#define SUNXI_CCMBASE_AUDIOCLK (0xC0) ++#define SUNXI_CCMBASE_AUDIOCLK (0xC0) + #define SUNXI_CCMBASE_AUDIOCLK_SPDIFSPEGATE (1<<31) +- #define SUNXI_CCMBASE_AUDIOCLK_DIV(v) ((v)<<16) ++ #define SUNXI_CCMBASE_AUDIOCLK_DIV(v) ((v)<<16) + + /* Clock dividers */ + #define SUNXI_DIV_MCLK 0 +@@ -156,6 +163,6 @@ extern struct sunxi_spdif_info sunxi_spdif; + unsigned int sunxi_spdif_get_clockrate(void); + + extern void sunxi_snd_txctrl(struct snd_pcm_substream *substream, int on); +-extern void sunxi_snd_rxctrl(int on); ++extern void sunxi_snd_rxctrl(struct snd_pcm_substream *substream, int on); + + #endif + +--- a/sound/soc/sunxi/spdif/sunxi_spdma.c ++++ b/sound/soc/sunxi/spdif/sunxi_spdma.c +@@ -34,25 +34,40 @@ + #include "sunxi_spdif.h" + #include "sunxi_spdma.h" + +-static volatile unsigned int dmasrc = 0; +-static volatile unsigned int dmadst = 0; ++static const struct snd_pcm_hardware sunxi_pcm_out_hardware = { ++ .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | ++ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | ++ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE |SNDRV_PCM_FMTBIT_S20_3LE| SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, ++ .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT, ++ .rate_min = 8000, ++ .rate_max = 192000, ++ .channels_min = 1, ++ .channels_max = 2, ++ .buffer_bytes_max = 128*1024, /* value must be (2^n)Kbyte size */ ++ .period_bytes_min = 1024,//1024*4, ++ .period_bytes_max = 1024*32,//1024*128, ++ .periods_min = 4, ++ .periods_max = 8, ++ .fifo_size = 32, ++}; + +-static const struct snd_pcm_hardware sunxi_pcm_hardware = { ++static const struct snd_pcm_hardware sunxi_pcm_in_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, +- .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE |SNDRV_PCM_FMTBIT_S20_3LE| SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, + .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT, + .rate_min = 8000, + .rate_max = 192000, + .channels_min = 1, + .channels_max = 2, +- .buffer_bytes_max = 128*1024, //1024*1024 /* value must be (2^n)Kbyte size */ +- .period_bytes_min = 1024*4,//1024*4, ++ .buffer_bytes_max = 128*1024, /* value must be (2^n)Kbyte size */ ++ .period_bytes_min = 1024,//1024*4, + .period_bytes_max = 1024*32,//1024*128, +- .periods_min = 4,//8, +- .periods_max = 8,//8, +- .fifo_size = 32,//32, ++ .periods_min = 4, ++ .periods_max = 8, ++ .fifo_size = 32, + }; + + struct sunxi_runtime_data { +@@ -65,6 +80,8 @@ struct sunxi_runtime_data { + dma_addr_t dma_pos; + dma_addr_t dma_end; + struct sunxi_dma_params *params; ++ /*DMA data width*/ ++ unsigned int dma_width; + }; + + static void sunxi_pcm_enqueue(struct snd_pcm_substream *substream) +@@ -73,8 +90,8 @@ static void sunxi_pcm_enqueue(struct snd_pcm_substream *substream) + dma_addr_t pos = prtd->dma_pos; + unsigned int limit; + int ret; +- + unsigned long len = prtd->dma_period; ++ int read = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 0 : 1; + + limit = prtd->dma_limit; + while(prtd->dma_loaded < limit){ +@@ -82,7 +99,7 @@ static void sunxi_pcm_enqueue(struct snd_pcm_substream *substream) + len = prtd->dma_end - pos; + } + +- ret = sunxi_dma_enqueue(prtd->params, pos, len, 0); ++ ret = sunxi_dma_enqueue(prtd->params, pos, len, read); + if (ret == 0) { + prtd->dma_loaded++; + pos += prtd->dma_period; +@@ -120,17 +137,24 @@ static int sunxi_pcm_hw_params(struct snd_pcm_substream *substream, + struct sunxi_runtime_data *prtd = runtime->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + unsigned long totbytes = params_buffer_bytes(params); +- struct sunxi_dma_params *dma = +- snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); ++ struct sunxi_dma_params *dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + int ret = 0; + if (!dma) + return 0; + ++ if (SNDRV_PCM_FORMAT_S16_LE == params_format(params)) { ++ prtd->dma_width = 16; ++ } ++ else { ++ prtd->dma_width = 32; ++ } ++ + if (prtd->params == NULL) { + prtd->params = dma; + ret = sunxi_dma_request(prtd->params, 0); + if (ret < 0) { +- return ret; ++ pr_err("[SPDIF] sunxi_dma_request failed! (ret=(%d)) failed %s,%d\n", ret, __func__,__LINE__); ++ return ret; + } + } + +@@ -138,6 +162,7 @@ static int sunxi_pcm_hw_params(struct snd_pcm_substream *substream, + substream) != 0) { + sunxi_dma_release(prtd->params); + prtd->params = NULL; ++ pr_err("[SPDIF] sunxi_dma_set_callback failed! (ret=(%d)) failed %s,%d\n", ret, __func__,__LINE__); + return -EINVAL; + } + +@@ -153,6 +178,7 @@ static int sunxi_pcm_hw_params(struct snd_pcm_substream *substream, + prtd->dma_pos = prtd->dma_start; + prtd->dma_end = prtd->dma_start + totbytes; + spin_unlock_irq(&prtd->lock); ++ + return 0; + } + +@@ -197,16 +223,22 @@ static int sunxi_pcm_prepare(struct snd_pcm_substream *substream) + #else + dma_config_t spdif_dma_conf; + memset(&spdif_dma_conf, 0, sizeof(spdif_dma_conf)); +- spdif_dma_conf.xfer_type.src_data_width = DATA_WIDTH_16BIT; ++ if(prtd->dma_width > 16) { ++ spdif_dma_conf.xfer_type.src_data_width = DATA_WIDTH_32BIT; ++ spdif_dma_conf.xfer_type.dst_data_width = DATA_WIDTH_32BIT; ++ } ++ else { ++ spdif_dma_conf.xfer_type.src_data_width = DATA_WIDTH_16BIT; ++ spdif_dma_conf.xfer_type.dst_data_width = DATA_WIDTH_16BIT; ++ } + spdif_dma_conf.xfer_type.src_bst_len = DATA_BRST_4; +- spdif_dma_conf.xfer_type.dst_data_width = DATA_WIDTH_16BIT; + spdif_dma_conf.xfer_type.dst_bst_len = DATA_BRST_4; + spdif_dma_conf.address_type.src_addr_mode = NDMA_ADDR_INCREMENT; + spdif_dma_conf.address_type.dst_addr_mode = NDMA_ADDR_NOCHANGE; + spdif_dma_conf.bconti_mode = false; + spdif_dma_conf.irq_spt = CHAN_IRQ_FD; + spdif_dma_conf.src_drq_type = N_SRC_SDRAM; +- spdif_dma_conf.dst_drq_type = N_DST_SPDIF_TX;//DRQDST_SPDIFTX; ++ spdif_dma_conf.dst_drq_type = N_DST_SPDIF_TX; + #endif + ret = sunxi_dma_config(prtd->params, &spdif_dma_conf, 0); + } else { +@@ -221,10 +253,27 @@ static int sunxi_pcm_prepare(struct snd_pcm_substream *substream) + spdif_dma_conf.hf_irq = SW_DMA_IRQ_FULL|SW_DMA_IRQ_HALF; + spdif_dma_conf.from = prtd->params->dma_addr; + spdif_dma_conf.to = prtd->dma_start; +- ret = sunxi_dma_config(prtd->params, &spdif_dma_conf, 0); + #else +- return -EINVAL; ++ dma_config_t spdif_dma_conf; ++ memset(&spdif_dma_conf, 0, sizeof(spdif_dma_conf)); ++ if(prtd->dma_width > 16) { ++ spdif_dma_conf.xfer_type.src_data_width = DATA_WIDTH_32BIT; ++ spdif_dma_conf.xfer_type.dst_data_width = DATA_WIDTH_32BIT; ++ } ++ else { ++ spdif_dma_conf.xfer_type.src_data_width = DATA_WIDTH_16BIT; ++ spdif_dma_conf.xfer_type.dst_data_width = DATA_WIDTH_16BIT; ++ } ++ spdif_dma_conf.xfer_type.src_bst_len = DATA_BRST_4; ++ spdif_dma_conf.xfer_type.dst_bst_len = DATA_BRST_4; ++ spdif_dma_conf.address_type.src_addr_mode = NDMA_ADDR_NOCHANGE; ++ spdif_dma_conf.address_type.dst_addr_mode = NDMA_ADDR_INCREMENT; ++ spdif_dma_conf.bconti_mode = false; ++ spdif_dma_conf.irq_spt = CHAN_IRQ_FD; ++ spdif_dma_conf.src_drq_type = N_SRC_SPDIF_RX; ++ spdif_dma_conf.dst_drq_type = N_DST_SDRAM; + #endif ++ ret = sunxi_dma_config(prtd->params, &spdif_dma_conf, 0); + } + /* flush the DMA channel */ + prtd->dma_loaded = 0; +@@ -248,12 +297,14 @@ static int sunxi_pcm_trigger(struct snd_pcm_substream *substream, int cmd) + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + sunxi_dma_start(prtd->params); ++ prtd->state |= ST_RUNNING; + break; + + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + sunxi_dma_stop(prtd->params); ++ prtd->state &= ~ST_RUNNING; + break; + + default: +@@ -271,21 +322,26 @@ static snd_pcm_uframes_t sunxi_pcm_pointer(struct snd_pcm_substream *substream) + struct sunxi_runtime_data *prtd = runtime->private_data; + unsigned long res = 0; + snd_pcm_uframes_t offset = 0; ++ dma_addr_t dmasrc = 0; ++ dma_addr_t dmadst = 0; ++ + + spin_lock(&prtd->lock); + sunxi_dma_getcurposition(prtd->params, + (dma_addr_t*)&dmasrc, (dma_addr_t*)&dmadst); + +- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE){ +- res = dmadst - prtd->dma_start; ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){ ++ res = dmasrc + prtd->dma_period - prtd->dma_start; + } else { +- offset = bytes_to_frames(runtime, dmasrc + prtd->dma_period - runtime->dma_addr); ++ res = dmadst + prtd->dma_period - prtd->dma_start; + } ++ offset = bytes_to_frames(runtime, res); + spin_unlock(&prtd->lock); + + if(offset >= runtime->buffer_size) + offset = 0; +- return offset; ++ ++ return offset; + } + + static int sunxi_pcm_open(struct snd_pcm_substream *substream) +@@ -294,11 +350,17 @@ static int sunxi_pcm_open(struct snd_pcm_substream *substream) + struct sunxi_runtime_data *prtd; + + snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); +- snd_soc_set_runtime_hwparams(substream, &sunxi_pcm_hardware); ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ snd_soc_set_runtime_hwparams(substream, &sunxi_pcm_out_hardware); ++ } else { ++ snd_soc_set_runtime_hwparams(substream, &sunxi_pcm_in_hardware); ++ } + + prtd = kzalloc(sizeof(struct sunxi_runtime_data), GFP_KERNEL); +- if (prtd == NULL) ++ if (prtd == NULL) { ++ pr_err("[SPDIF] try to alloc sunxi_runtime_data failed %s,%d\n", __func__,__LINE__); + return -ENOMEM; ++ } + + spin_lock_init(&prtd->lock); + +@@ -311,7 +373,6 @@ static int sunxi_pcm_close(struct snd_pcm_substream *substream) + struct snd_pcm_runtime *runtime = substream->runtime; + struct sunxi_runtime_data *prtd = runtime->private_data; + kfree(prtd); +- + return 0; + } + +@@ -342,8 +403,13 @@ static int sunxi_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) + { + struct snd_pcm_substream *substream = pcm->streams[stream].substream; + struct snd_dma_buffer *buf = &substream->dma_buffer; +- size_t size = sunxi_pcm_hardware.buffer_bytes_max; ++ size_t size = 0; + ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ size = sunxi_pcm_out_hardware.buffer_bytes_max; ++ } else { ++ size = sunxi_pcm_in_hardware.buffer_bytes_max; ++ } + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = pcm->card->dev; + buf->private_data = NULL; +@@ -384,6 +450,7 @@ static int sunxi_pcm_new(struct snd_soc_pcm_runtime *rtd) + struct snd_pcm *pcm = rtd->pcm; + int ret = 0; + ++ + if (!card->dev->dma_mask) + card->dev->dma_mask = &sunxi_pcm_mask; + if (!card->dev->coherent_dma_mask) +@@ -443,16 +510,19 @@ static int __init sunxi_soc_platform_spdif_init(void) + int ret, spdif_used = 0; + + ret = script_parser_fetch("spdif_para", "spdif_used", &spdif_used, 1); +- if (ret != 0 || !spdif_used) ++ if (ret != 0 || !spdif_used) + return -ENODEV; + + ret = platform_device_register(&sunxi_spdif_pcm_device); +- if (ret < 0) ++ if (ret < 0) { ++ pr_err("[SPDIF] try to SPDIF platform_device_register failed (ret=(%d)) failed %s,%d\n", ret, __func__,__LINE__); + return ret; ++ } + + ret = platform_driver_register(&sunxi_spdif_pcm_driver); + if (ret < 0) { + platform_device_unregister(&sunxi_spdif_pcm_device); ++ pr_err("[SPDIF] try to SPDIF platform_driver_register failed (ret=(%d)) failed %s,%d\n", ret, __func__,__LINE__); + return ret; + } + return 0; diff --git a/patch/kernel/banana-default/rt8192cu_driver_missing_case_fix.patch b/patch/kernel/banana-default/rt8192cu_driver_missing_case_fix.patch new file mode 100644 index 000000000..64aea3b9c --- /dev/null +++ b/patch/kernel/banana-default/rt8192cu_driver_missing_case_fix.patch @@ -0,0 +1,20 @@ +diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +index 25db369..34ce064 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +@@ -1946,6 +1946,14 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) + rtl_write_word(rtlpriv, REG_RXFLTMAP2, *(u16 *)val); + mac->rx_data_filter = *(u16 *)val; + break; ++ case HW_VAR_KEEP_ALIVE:{ ++ u8 array[2]; ++ array[0] = 0xff; ++ array[1] = *((u8 *)val); ++ rtl92c_fill_h2c_cmd(hw, H2C_92C_KEEP_ALIVE_CTRL, 2, ++ array); ++ break; ++ } + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + diff --git a/patch/spi.patch b/patch/kernel/banana-default/sun7i_SPI_driver.patch similarity index 100% rename from patch/spi.patch rename to patch/kernel/banana-default/sun7i_SPI_driver.patch diff --git a/patch/kernel/banana-default/wireless_driver_bananapro.patch b/patch/kernel/banana-default/wireless_driver_bananapro.patch new file mode 100644 index 000000000..171846a82 --- /dev/null +++ b/patch/kernel/banana-default/wireless_driver_bananapro.patch @@ -0,0 +1,85159 @@ +From b16914711456ca75d066d6de8c246d545fd4d6a5 Mon Sep 17 00:00:00 2001 +From: Igor Pecovnik +Date: Mon, 16 Feb 2015 19:10:06 +0100 +Subject: [PATCH] BananaPRO + +--- + drivers/net/wireless/Kconfig | 1 + + drivers/net/wireless/Makefile | 1 + + drivers/net/wireless/ap6210/Kconfig | 45 + + drivers/net/wireless/ap6210/Makefile | 65 + + drivers/net/wireless/ap6210/aiutils.c | 873 ++ + drivers/net/wireless/ap6210/ap6210.h | 22 + + drivers/net/wireless/ap6210/ap6210_gpio.h | 9 + + drivers/net/wireless/ap6210/ap6210_gpio_bt.c | 164 + + drivers/net/wireless/ap6210/ap6210_gpio_wifi.c | 463 + + drivers/net/wireless/ap6210/bcmevent.c | 152 + + drivers/net/wireless/ap6210/bcmsdh.c | 778 ++ + drivers/net/wireless/ap6210/bcmsdh_linux.c | 796 ++ + drivers/net/wireless/ap6210/bcmsdh_sdmmc.c | 1532 +++ + drivers/net/wireless/ap6210/bcmsdh_sdmmc_linux.c | 427 + + drivers/net/wireless/ap6210/bcmutils.c | 2095 ++++ + drivers/net/wireless/ap6210/bcmwifi_channels.c | 1179 +++ + drivers/net/wireless/ap6210/dhd.h | 888 ++ + drivers/net/wireless/ap6210/dhd_bta.c | 338 + + drivers/net/wireless/ap6210/dhd_bta.h | 39 + + drivers/net/wireless/ap6210/dhd_bus.h | 111 + + drivers/net/wireless/ap6210/dhd_cdc.c | 3191 ++++++ + drivers/net/wireless/ap6210/dhd_cfg80211.c | 680 ++ + drivers/net/wireless/ap6210/dhd_cfg80211.h | 44 + + drivers/net/wireless/ap6210/dhd_common.c | 2255 +++++ + drivers/net/wireless/ap6210/dhd_custom_gpio.c | 313 + + drivers/net/wireless/ap6210/dhd_dbg.h | 79 + + drivers/net/wireless/ap6210/dhd_gpio.c | 47 + + drivers/net/wireless/ap6210/dhd_ip.c | 111 + + drivers/net/wireless/ap6210/dhd_ip.h | 42 + + drivers/net/wireless/ap6210/dhd_linux.c | 6152 +++++++++++ + drivers/net/wireless/ap6210/dhd_linux_sched.c | 39 + + drivers/net/wireless/ap6210/dhd_pno.c | 1838 ++++ + drivers/net/wireless/ap6210/dhd_pno.h | 249 + + drivers/net/wireless/ap6210/dhd_proto.h | 113 + + drivers/net/wireless/ap6210/dhd_sdio.c | 7856 ++++++++++++++ + drivers/net/wireless/ap6210/dhd_wlfc.c | 2441 +++++ + drivers/net/wireless/ap6210/dhd_wlfc.h | 288 + + drivers/net/wireless/ap6210/dngl_stats.h | 43 + + drivers/net/wireless/ap6210/dngl_wlhdr.h | 40 + + drivers/net/wireless/ap6210/hndpmu.c | 208 + + drivers/net/wireless/ap6210/include/Makefile | 54 + + drivers/net/wireless/ap6210/include/aidmp.h | 375 + + drivers/net/wireless/ap6210/include/bcm_cfg.h | 29 + + .../net/wireless/ap6210/include/bcm_mpool_pub.h | 361 + + drivers/net/wireless/ap6210/include/bcmcdc.h | 132 + + drivers/net/wireless/ap6210/include/bcmdefs.h | 270 + + drivers/net/wireless/ap6210/include/bcmdevs.h | 503 + + drivers/net/wireless/ap6210/include/bcmendian.h | 299 + + drivers/net/wireless/ap6210/include/bcmpcispi.h | 181 + + drivers/net/wireless/ap6210/include/bcmperf.h | 36 + + drivers/net/wireless/ap6210/include/bcmsdbus.h | 152 + + drivers/net/wireless/ap6210/include/bcmsdh.h | 247 + + drivers/net/wireless/ap6210/include/bcmsdh_sdmmc.h | 109 + + drivers/net/wireless/ap6210/include/bcmsdpcm.h | 281 + + drivers/net/wireless/ap6210/include/bcmsdspi.h | 119 + + drivers/net/wireless/ap6210/include/bcmsdstd.h | 248 + + drivers/net/wireless/ap6210/include/bcmspi.h | 40 + + drivers/net/wireless/ap6210/include/bcmutils.h | 808 ++ + .../net/wireless/ap6210/include/bcmwifi_channels.h | 490 + + .../net/wireless/ap6210/include/bcmwifi_rates.h | 318 + + drivers/net/wireless/ap6210/include/dhdioctl.h | 136 + + drivers/net/wireless/ap6210/include/epivers.h | 56 + + drivers/net/wireless/ap6210/include/hndpmu.h | 36 + + .../net/wireless/ap6210/include/hndrte_armtrap.h | 88 + + drivers/net/wireless/ap6210/include/hndrte_cons.h | 67 + + drivers/net/wireless/ap6210/include/hndsoc.h | 235 + + drivers/net/wireless/ap6210/include/linux_osl.h | 430 + + drivers/net/wireless/ap6210/include/linuxver.h | 652 ++ + drivers/net/wireless/ap6210/include/miniopt.h | 77 + + drivers/net/wireless/ap6210/include/msgtrace.h | 74 + + drivers/net/wireless/ap6210/include/osl.h | 90 + + .../wireless/ap6210/include/packed_section_end.h | 59 + + .../wireless/ap6210/include/packed_section_start.h | 63 + + drivers/net/wireless/ap6210/include/pcicfg.h | 100 + + drivers/net/wireless/ap6210/include/proto/802.11.h | 2355 +++++ + .../net/wireless/ap6210/include/proto/802.11_bta.h | 45 + + .../net/wireless/ap6210/include/proto/802.11e.h | 131 + + drivers/net/wireless/ap6210/include/proto/802.1d.h | 50 + + drivers/net/wireless/ap6210/include/proto/bcmeth.h | 112 + + .../net/wireless/ap6210/include/proto/bcmevent.h | 368 + + drivers/net/wireless/ap6210/include/proto/bcmip.h | 210 + + .../net/wireless/ap6210/include/proto/bt_amp_hci.h | 441 + + drivers/net/wireless/ap6210/include/proto/eapol.h | 193 + + .../net/wireless/ap6210/include/proto/ethernet.h | 190 + + drivers/net/wireless/ap6210/include/proto/p2p.h | 579 ++ + drivers/net/wireless/ap6210/include/proto/sdspi.h | 75 + + drivers/net/wireless/ap6210/include/proto/vlan.h | 69 + + drivers/net/wireless/ap6210/include/proto/wpa.h | 206 + + drivers/net/wireless/ap6210/include/sbchipc.h | 2405 +++++ + drivers/net/wireless/ap6210/include/sbconfig.h | 282 + + drivers/net/wireless/ap6210/include/sbhnddma.h | 384 + + drivers/net/wireless/ap6210/include/sbpcmcia.h | 113 + + drivers/net/wireless/ap6210/include/sbsdio.h | 188 + + drivers/net/wireless/ap6210/include/sbsdpcmdev.h | 295 + + drivers/net/wireless/ap6210/include/sbsocram.h | 199 + + drivers/net/wireless/ap6210/include/sdio.h | 617 ++ + drivers/net/wireless/ap6210/include/sdioh.h | 445 + + drivers/net/wireless/ap6210/include/sdiovar.h | 58 + + drivers/net/wireless/ap6210/include/siutils.h | 347 + + drivers/net/wireless/ap6210/include/trxhdr.h | 53 + + drivers/net/wireless/ap6210/include/typedefs.h | 343 + + drivers/net/wireless/ap6210/include/wlfc_proto.h | 217 + + drivers/net/wireless/ap6210/include/wlioctl.h | 5079 ++++++++++ + drivers/net/wireless/ap6210/linux_osl.c | 1138 +++ + drivers/net/wireless/ap6210/sbutils.c | 1003 ++ + drivers/net/wireless/ap6210/siutils.c | 2472 +++++ + drivers/net/wireless/ap6210/siutils_priv.h | 236 + + drivers/net/wireless/ap6210/uamp_api.h | 176 + + drivers/net/wireless/ap6210/wl_android.c | 1448 +++ + drivers/net/wireless/ap6210/wl_android.h | 124 + + drivers/net/wireless/ap6210/wl_cfg80211.c | 10129 +++++++++++++++++++ + drivers/net/wireless/ap6210/wl_cfg80211.h | 791 ++ + drivers/net/wireless/ap6210/wl_cfgp2p.c | 2393 +++++ + drivers/net/wireless/ap6210/wl_cfgp2p.h | 311 + + drivers/net/wireless/ap6210/wl_iw.c | 3622 +++++++ + drivers/net/wireless/ap6210/wl_iw.h | 161 + + drivers/net/wireless/ap6210/wl_linux_mon.c | 422 + + drivers/net/wireless/ap6210/wldev_common.c | 374 + + drivers/net/wireless/ap6210/wldev_common.h | 111 + + 119 files changed, 84182 insertions(+) + mode change 100644 => 100755 drivers/net/wireless/Kconfig + mode change 100644 => 100755 drivers/net/wireless/Makefile + create mode 100755 drivers/net/wireless/ap6210/Kconfig + create mode 100755 drivers/net/wireless/ap6210/Makefile + create mode 100755 drivers/net/wireless/ap6210/aiutils.c + create mode 100755 drivers/net/wireless/ap6210/ap6210.h + create mode 100755 drivers/net/wireless/ap6210/ap6210_gpio.h + create mode 100755 drivers/net/wireless/ap6210/ap6210_gpio_bt.c + create mode 100755 drivers/net/wireless/ap6210/ap6210_gpio_wifi.c + create mode 100755 drivers/net/wireless/ap6210/bcmevent.c + create mode 100755 drivers/net/wireless/ap6210/bcmsdh.c + create mode 100755 drivers/net/wireless/ap6210/bcmsdh_linux.c + create mode 100755 drivers/net/wireless/ap6210/bcmsdh_sdmmc.c + create mode 100755 drivers/net/wireless/ap6210/bcmsdh_sdmmc_linux.c + create mode 100755 drivers/net/wireless/ap6210/bcmutils.c + create mode 100755 drivers/net/wireless/ap6210/bcmwifi_channels.c + create mode 100755 drivers/net/wireless/ap6210/dhd.h + create mode 100755 drivers/net/wireless/ap6210/dhd_bta.c + create mode 100755 drivers/net/wireless/ap6210/dhd_bta.h + create mode 100755 drivers/net/wireless/ap6210/dhd_bus.h + create mode 100755 drivers/net/wireless/ap6210/dhd_cdc.c + create mode 100755 drivers/net/wireless/ap6210/dhd_cfg80211.c + create mode 100755 drivers/net/wireless/ap6210/dhd_cfg80211.h + create mode 100755 drivers/net/wireless/ap6210/dhd_common.c + create mode 100755 drivers/net/wireless/ap6210/dhd_custom_gpio.c + create mode 100755 drivers/net/wireless/ap6210/dhd_dbg.h + create mode 100755 drivers/net/wireless/ap6210/dhd_gpio.c + create mode 100755 drivers/net/wireless/ap6210/dhd_ip.c + create mode 100755 drivers/net/wireless/ap6210/dhd_ip.h + create mode 100755 drivers/net/wireless/ap6210/dhd_linux.c + create mode 100755 drivers/net/wireless/ap6210/dhd_linux_sched.c + create mode 100755 drivers/net/wireless/ap6210/dhd_pno.c + create mode 100755 drivers/net/wireless/ap6210/dhd_pno.h + create mode 100755 drivers/net/wireless/ap6210/dhd_proto.h + create mode 100755 drivers/net/wireless/ap6210/dhd_sdio.c + create mode 100755 drivers/net/wireless/ap6210/dhd_wlfc.c + create mode 100755 drivers/net/wireless/ap6210/dhd_wlfc.h + create mode 100755 drivers/net/wireless/ap6210/dngl_stats.h + create mode 100755 drivers/net/wireless/ap6210/dngl_wlhdr.h + create mode 100755 drivers/net/wireless/ap6210/hndpmu.c + create mode 100755 drivers/net/wireless/ap6210/include/Makefile + create mode 100755 drivers/net/wireless/ap6210/include/aidmp.h + create mode 100755 drivers/net/wireless/ap6210/include/bcm_cfg.h + create mode 100755 drivers/net/wireless/ap6210/include/bcm_mpool_pub.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmcdc.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmdefs.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmdevs.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmendian.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmpcispi.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmperf.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmsdbus.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmsdh.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmsdh_sdmmc.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmsdpcm.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmsdspi.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmsdstd.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmspi.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmutils.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmwifi_channels.h + create mode 100755 drivers/net/wireless/ap6210/include/bcmwifi_rates.h + create mode 100755 drivers/net/wireless/ap6210/include/dhdioctl.h + create mode 100755 drivers/net/wireless/ap6210/include/epivers.h + create mode 100755 drivers/net/wireless/ap6210/include/hndpmu.h + create mode 100755 drivers/net/wireless/ap6210/include/hndrte_armtrap.h + create mode 100755 drivers/net/wireless/ap6210/include/hndrte_cons.h + create mode 100755 drivers/net/wireless/ap6210/include/hndsoc.h + create mode 100755 drivers/net/wireless/ap6210/include/linux_osl.h + create mode 100755 drivers/net/wireless/ap6210/include/linuxver.h + create mode 100755 drivers/net/wireless/ap6210/include/miniopt.h + create mode 100755 drivers/net/wireless/ap6210/include/msgtrace.h + create mode 100755 drivers/net/wireless/ap6210/include/osl.h + create mode 100755 drivers/net/wireless/ap6210/include/packed_section_end.h + create mode 100755 drivers/net/wireless/ap6210/include/packed_section_start.h + create mode 100755 drivers/net/wireless/ap6210/include/pcicfg.h + create mode 100755 drivers/net/wireless/ap6210/include/proto/802.11.h + create mode 100755 drivers/net/wireless/ap6210/include/proto/802.11_bta.h + create mode 100755 drivers/net/wireless/ap6210/include/proto/802.11e.h + create mode 100755 drivers/net/wireless/ap6210/include/proto/802.1d.h + create mode 100755 drivers/net/wireless/ap6210/include/proto/bcmeth.h + create mode 100755 drivers/net/wireless/ap6210/include/proto/bcmevent.h + create mode 100755 drivers/net/wireless/ap6210/include/proto/bcmip.h + create mode 100755 drivers/net/wireless/ap6210/include/proto/bt_amp_hci.h + create mode 100755 drivers/net/wireless/ap6210/include/proto/eapol.h + create mode 100755 drivers/net/wireless/ap6210/include/proto/ethernet.h + create mode 100755 drivers/net/wireless/ap6210/include/proto/p2p.h + create mode 100755 drivers/net/wireless/ap6210/include/proto/sdspi.h + create mode 100755 drivers/net/wireless/ap6210/include/proto/vlan.h + create mode 100755 drivers/net/wireless/ap6210/include/proto/wpa.h + create mode 100755 drivers/net/wireless/ap6210/include/sbchipc.h + create mode 100755 drivers/net/wireless/ap6210/include/sbconfig.h + create mode 100755 drivers/net/wireless/ap6210/include/sbhnddma.h + create mode 100755 drivers/net/wireless/ap6210/include/sbpcmcia.h + create mode 100755 drivers/net/wireless/ap6210/include/sbsdio.h + create mode 100755 drivers/net/wireless/ap6210/include/sbsdpcmdev.h + create mode 100755 drivers/net/wireless/ap6210/include/sbsocram.h + create mode 100755 drivers/net/wireless/ap6210/include/sdio.h + create mode 100755 drivers/net/wireless/ap6210/include/sdioh.h + create mode 100755 drivers/net/wireless/ap6210/include/sdiovar.h + create mode 100755 drivers/net/wireless/ap6210/include/siutils.h + create mode 100755 drivers/net/wireless/ap6210/include/trxhdr.h + create mode 100755 drivers/net/wireless/ap6210/include/typedefs.h + create mode 100755 drivers/net/wireless/ap6210/include/wlfc_proto.h + create mode 100755 drivers/net/wireless/ap6210/include/wlioctl.h + create mode 100755 drivers/net/wireless/ap6210/linux_osl.c + create mode 100755 drivers/net/wireless/ap6210/sbutils.c + create mode 100755 drivers/net/wireless/ap6210/siutils.c + create mode 100755 drivers/net/wireless/ap6210/siutils_priv.h + create mode 100755 drivers/net/wireless/ap6210/uamp_api.h + create mode 100755 drivers/net/wireless/ap6210/wl_android.c + create mode 100755 drivers/net/wireless/ap6210/wl_android.h + create mode 100755 drivers/net/wireless/ap6210/wl_cfg80211.c + create mode 100755 drivers/net/wireless/ap6210/wl_cfg80211.h + create mode 100755 drivers/net/wireless/ap6210/wl_cfgp2p.c + create mode 100755 drivers/net/wireless/ap6210/wl_cfgp2p.h + create mode 100755 drivers/net/wireless/ap6210/wl_iw.c + create mode 100755 drivers/net/wireless/ap6210/wl_iw.h + create mode 100755 drivers/net/wireless/ap6210/wl_linux_mon.c + create mode 100755 drivers/net/wireless/ap6210/wldev_common.c + create mode 100755 drivers/net/wireless/ap6210/wldev_common.h + +diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig +old mode 100644 +new mode 100755 +index a17fd93..6afeab3 +--- a/drivers/net/wireless/Kconfig ++++ b/drivers/net/wireless/Kconfig +@@ -278,6 +278,7 @@ source "drivers/net/wireless/ath/Kconfig" + source "drivers/net/wireless/b43/Kconfig" + source "drivers/net/wireless/b43legacy/Kconfig" + source "drivers/net/wireless/bcmdhd/Kconfig" ++source "drivers/net/wireless/ap6210/Kconfig" + source "drivers/net/wireless/brcm80211/Kconfig" + source "drivers/net/wireless/bcm4330/Kconfig" + source "drivers/net/wireless/hostap/Kconfig" +diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile +old mode 100644 +new mode 100755 +index 0db00ba..a970c43 +--- a/drivers/net/wireless/Makefile ++++ b/drivers/net/wireless/Makefile +@@ -65,6 +65,7 @@ obj-$(CONFIG_IWM) += iwmc3200wifi/ + obj-$(CONFIG_MWIFIEX) += mwifiex/ + + obj-$(CONFIG_BCMDHD) += bcmdhd/ ++obj-$(CONFIG_AP6210) += ap6210/ + + obj-$(CONFIG_BRCMFMAC) += brcm80211/ + obj-$(CONFIG_BRCMSMAC) += brcm80211/ +diff --git a/drivers/net/wireless/ap6210/Kconfig b/drivers/net/wireless/ap6210/Kconfig +new file mode 100755 +index 0000000..9756ac7 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/Kconfig +@@ -0,0 +1,45 @@ ++config AP6210 ++ tristate "AMPAK AP6210 wireless/bluetooth module support" ++ depends on MMC ++ default n ++ ---help--- ++ This module adds support for the wireless and bluetooth ++ module of the CubieTruck. ++ ++config AP6210_FW_PATH ++ depends on AP6210 ++ string "Firmware path" ++ default "/system/vendor/modules/fw_bcmxxxx.bin" ++ ---help--- ++ Path to the firmware file. ++ ++config AP6210_NVRAM_PATH ++ depends on AP6210 ++ string "NVRAM path" ++ default "/system/vendor/modules/nvram_apxxxx.txt" ++ ---help--- ++ Path to the calibration file. ++ ++config AP6210_WEXT ++ bool "Enable WEXT support" ++ depends on AP6210 && CFG80211 = n ++ select WIRELESS_EXT ++ select WEXT_PRIV ++ help ++ Enables WEXT support ++ ++choice ++ depends on AP6210 ++ prompt "Interrupt type" ++config AP6210_OOB ++ depends on AP6210 ++ bool "Out-of-Band Interrupt" ++ ---help--- ++ Interrupt through WL_HOST_WAKE. ++config AP6210_SDIO_IRQ ++ depends on AP6210 ++ bool "In-Band Interrupt" ++ default y ++ ---help--- ++ Interrupt through SDIO DAT[1] ++endchoice +diff --git a/drivers/net/wireless/ap6210/Makefile b/drivers/net/wireless/ap6210/Makefile +new file mode 100755 +index 0000000..59ef7c8 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/Makefile +@@ -0,0 +1,65 @@ ++# ap6210 ++DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ ++ -DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DBCMFILEIMAGE \ ++ -DDHDTHREAD -DDHD_DEBUG -DSDTEST -DBDC -DTOE \ ++ -DDHD_BCMEVENTS -DSHOW_EVENTS -DPROP_TXSTATUS -DBCMDBG \ ++ -DMMC_SDIO_ABORT -DBCMSDIO -DBCMLXSDMMC -DBCMPLATFORM_BUS -DWLP2P \ ++ -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \ ++ -DKEEP_ALIVE -DPKT_FILTER_SUPPORT \ ++ -DEMBEDDED_PLATFORM -DENABLE_INSMOD_NO_FW_LOAD -DPNO_SUPPORT \ ++ -DDHD_USE_IDLECOUNT -DSET_RANDOM_MAC_SOFTAP -DVSDB \ ++ -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST -DSDIO_CRC_ERROR_FIX \ ++ -DESCAN_RESULT_PATCH -DHT40_GO -DPASS_ARP_PACKET -DSUPPORT_PM2_ONLY \ ++ -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT -DAMPDU_HOSTREORDER \ ++ -DDISABLE_FW_ROAM_SUSPEND -DDISABLE_BUILTIN_ROAM \ ++ -DCUSTOM_SDIO_F2_BLKSIZE=128 -DWL_SDO -DWL_SUPPORT_BACKPORTED_KPATCHES\ ++ -Idrivers/net/wireless/ap6210 -Idrivers/net/wireless/ap6210/include ++ ++DHDOFILES = aiutils.o bcmsdh_sdmmc_linux.o dhd_linux.o siutils.o bcmutils.o \ ++ dhd_linux_sched.o dhd_sdio.o bcmwifi_channels.o bcmevent.o hndpmu.o \ ++ bcmsdh.o dhd_cdc.o bcmsdh_linux.o dhd_common.o linux_osl.o \ ++ bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o wldev_common.o wl_android.o \ ++ ap6210_gpio_wifi.o ap6210_gpio_bt.o ++ ++obj-$(CONFIG_AP6210) += ap6210.o ++ap6210-objs += $(DHDOFILES) ++ ++DHDOFILES += dhd_gpio.o ++DHDCFLAGS += -DCUSTOMER_HW ++#DHDCFLAGS += -DBCMWAPI_WPI -DBCMWAPI_WAI ++ ++ifeq ($(CONFIG_AP6210_OOB),y) ++DHDCFLAGS += -DOOB_INTR_ONLY -DHW_OOB -DCUSTOMER_OOB ++else ++DHDCFLAGS += -DSDIO_ISR_THREAD ++endif ++ ++ifeq ($(CONFIG_AP6210_AG),y) ++ DHDCFLAGS += -DBAND_AG ++endif ++ ++ifneq ($(CONFIG_WIRELESS_EXT),) ++ap6210-objs += wl_iw.o ++DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT -DUSE_IW ++endif ++ifneq ($(CONFIG_CFG80211),) ++ap6210-objs += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o dhd_cfg80211.o ++DHDCFLAGS += -DWL_CFG80211 -DWL_CFG80211_STA_EVENT ++DHDCFLAGS += -DCUSTOM_ROAM_TRIGGER_SETTING=-65 ++DHDCFLAGS += -DCUSTOM_ROAM_DELTA_SETTING=15 ++DHDCFLAGS += -DCUSTOM_KEEP_ALIVE_SETTING=28000 ++DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=7 ++#DHDCFLAGS += -fno-aggressive-loop-optimizations ++endif ++ifneq ($(CONFIG_DHD_USE_SCHED_SCAN),) ++DHDCFLAGS += -DWL_SCHED_SCAN ++endif ++EXTRA_CFLAGS = $(DHDCFLAGS) ++ifeq ($(CONFIG_AP6210),m) ++EXTRA_LDFLAGS += --strip-debug ++endif ++ ++# GPIO Power Management Modules ++ ++#obj-$(CONFIG_AP6210) += ap6210_gpio_wifi.o ++#obj-$(CONFIG_AP6210) += ap6210_gpio_bt.o +diff --git a/drivers/net/wireless/ap6210/aiutils.c b/drivers/net/wireless/ap6210/aiutils.c +new file mode 100755 +index 0000000..bc116d7 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/aiutils.c +@@ -0,0 +1,873 @@ ++/* ++ * Misc utility routines for accessing chip-specific features ++ * of the SiliconBackplane-based Broadcom chips. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: aiutils.c 347614 2012-07-27 10:24:51Z $ ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "siutils_priv.h" ++ ++#include ++ ++#define BCM47162_DMP() (0) ++#define BCM5357_DMP() (0) ++#define remap_coreid(sih, coreid) (coreid) ++#define remap_corerev(sih, corerev) (corerev) ++ ++/* EROM parsing */ ++ ++static uint32 ++get_erom_ent(si_t *sih, uint32 **eromptr, uint32 mask, uint32 match) ++{ ++ uint32 ent; ++ uint inv = 0, nom = 0; ++ ++ while (TRUE) { ++ ent = R_REG(si_osh(sih), *eromptr); ++ (*eromptr)++; ++ ++ if (mask == 0) ++ break; ++ ++ if ((ent & ER_VALID) == 0) { ++ inv++; ++ continue; ++ } ++ ++ if (ent == (ER_END | ER_VALID)) ++ break; ++ ++ if ((ent & mask) == match) ++ break; ++ ++ nom++; ++ } ++ ++ AP6210_DEBUG("%s: Returning ent 0x%08x\n", __FUNCTION__, ent); ++ if (inv + nom) { ++ AP6210_DEBUG(" after %d invalid and %d non-matching entries\n", inv, nom); ++ } ++ return ent; ++} ++ ++static uint32 ++get_asd(si_t *sih, uint32 **eromptr, uint sp, uint ad, uint st, uint32 *addrl, uint32 *addrh, ++ uint32 *sizel, uint32 *sizeh) ++{ ++ uint32 asd, sz, szd; ++ ++ asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID); ++ if (((asd & ER_TAG1) != ER_ADD) || ++ (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) || ++ ((asd & AD_ST_MASK) != st)) { ++ /* This is not what we want, "push" it back */ ++ (*eromptr)--; ++ return 0; ++ } ++ *addrl = asd & AD_ADDR_MASK; ++ if (asd & AD_AG32) ++ *addrh = get_erom_ent(sih, eromptr, 0, 0); ++ else ++ *addrh = 0; ++ *sizeh = 0; ++ sz = asd & AD_SZ_MASK; ++ if (sz == AD_SZ_SZD) { ++ szd = get_erom_ent(sih, eromptr, 0, 0); ++ *sizel = szd & SD_SZ_MASK; ++ if (szd & SD_SG32) ++ *sizeh = get_erom_ent(sih, eromptr, 0, 0); ++ } else ++ *sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT); ++ ++ AP6210_DEBUG(" SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n", ++ sp, ad, st, *sizeh, *sizel, *addrh, *addrl); ++ ++ return asd; ++} ++ ++static void ++ai_hwfixup(si_info_t *sii) ++{ ++} ++ ++ ++/* parse the enumeration rom to identify all cores */ ++void ++ai_scan(si_t *sih, void *regs, uint devid) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ chipcregs_t *cc = (chipcregs_t *)regs; ++ uint32 erombase, *eromptr, *eromlim; ++ ++ erombase = R_REG(sii->osh, &cc->eromptr); ++ ++ switch (BUSTYPE(sih->bustype)) { ++ case SI_BUS: ++ eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE); ++ break; ++ ++ case PCI_BUS: ++ /* Set wrappers address */ ++ sii->curwrap = (void *)((uintptr)regs + SI_CORE_SIZE); ++ ++ /* Now point the window at the erom */ ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, erombase); ++ eromptr = regs; ++ break; ++ ++ case SPI_BUS: ++ case SDIO_BUS: ++ eromptr = (uint32 *)(uintptr)erombase; ++ break; ++ ++ case PCMCIA_BUS: ++ default: ++ AP6210_ERR("Don't know how to do AXI enumertion on bus %d\n", sih->bustype); ++ ASSERT(0); ++ return; ++ } ++ eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32)); ++ ++ AP6210_DEBUG("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%p, eromlim = 0x%p\n", ++ regs, erombase, eromptr, eromlim); ++ while (eromptr < eromlim) { ++ uint32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp; ++ uint32 mpd, asd, addrl, addrh, sizel, sizeh; ++ uint i, j, idx; ++ bool br; ++ ++ br = FALSE; ++ ++ /* Grok a component */ ++ cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI); ++ if (cia == (ER_END | ER_VALID)) { ++ AP6210_DEBUG("Found END of erom after %d cores\n", sii->numcores); ++ ai_hwfixup(sii); ++ return; ++ } ++ ++ cib = get_erom_ent(sih, &eromptr, 0, 0); ++ ++ if ((cib & ER_TAG) != ER_CI) { ++ AP6210_ERR("CIA not followed by CIB\n"); ++ goto error; ++ } ++ ++ cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT; ++ mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT; ++ crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT; ++ nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT; ++ nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT; ++ nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; ++ nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; ++ ++#ifdef BCMDBG_SI ++ AP6210_DEBUG("Found component 0x%04x/0x%04x rev %d at erom addr 0x%p, with nmw = %d, " ++ "nsw = %d, nmp = %d & nsp = %d\n", ++ mfg, cid, crev, eromptr - 1, nmw, nsw, nmp, nsp); ++#else ++ BCM_REFERENCE(crev); ++#endif ++ ++ if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0)) ++ continue; ++ if ((nmw + nsw == 0)) { ++ /* A component which is not a core */ ++ if (cid == OOB_ROUTER_CORE_ID) { ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, ++ &addrl, &addrh, &sizel, &sizeh); ++ if (asd != 0) { ++ sii->oob_router = addrl; ++ } ++ } ++ if (cid != GMAC_COMMON_4706_CORE_ID) ++ continue; ++ } ++ ++ idx = sii->numcores; ++ ++ sii->cia[idx] = cia; ++ sii->cib[idx] = cib; ++ sii->coreid[idx] = remap_coreid(sih, cid); ++ ++ for (i = 0; i < nmp; i++) { ++ mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); ++ if ((mpd & ER_TAG) != ER_MP) { ++ AP6210_ERR("Not enough MP entries for component 0x%x\n", cid); ++ goto error; ++ } ++ AP6210_DEBUG(" Master port %d, mp: %d id: %d\n", i, ++ (mpd & MPD_MP_MASK) >> MPD_MP_SHIFT, ++ (mpd & MPD_MUI_MASK) >> MPD_MUI_SHIFT); ++ } ++ ++ /* First Slave Address Descriptor should be port 0: ++ * the main register space for the core ++ */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh); ++ if (asd == 0) { ++ do { ++ /* Try again to see if it is a bridge */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd != 0) ++ br = TRUE; ++ else { ++ if (br == TRUE) { ++ break; ++ } ++ else if ((addrh != 0) || (sizeh != 0) || ++ (sizel != SI_CORE_SIZE)) { ++ AP6210_ERR("addrh = 0x%x\t sizeh = 0x%x\t size1 =" ++ "0x%x\n", addrh, sizeh, sizel); ++ AP6210_ERR("First Slave ASD for" ++ "core 0x%04x malformed " ++ "(0x%08x)\n", cid, asd); ++ goto error; ++ } ++ } ++ } while (1); ++ } ++ sii->coresba[idx] = addrl; ++ sii->coresba_size[idx] = sizel; ++ /* Get any more ASDs in port 0 */ ++ j = 1; ++ do { ++ asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) { ++ sii->coresba2[idx] = addrl; ++ sii->coresba2_size[idx] = sizel; ++ } ++ j++; ++ } while (asd != 0); ++ ++ /* Go through the ASDs for other slave ports */ ++ for (i = 1; i < nsp; i++) { ++ j = 0; ++ do { ++ asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ ++ if (asd == 0) ++ break; ++ j++; ++ } while (1); ++ if (j == 0) { ++ AP6210_ERR(" SP %d has no address descriptors\n", i); ++ goto error; ++ } ++ } ++ ++ /* Now get master wrappers */ ++ for (i = 0; i < nmw; i++) { ++ asd = get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd == 0) { ++ AP6210_ERR("Missing descriptor for MW %d\n", i); ++ goto error; ++ } ++ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { ++ AP6210_ERR("Master wrapper %d is not 4KB\n", i); ++ goto error; ++ } ++ if (i == 0) ++ sii->wrapba[idx] = addrl; ++ } ++ ++ /* And finally slave wrappers */ ++ for (i = 0; i < nsw; i++) { ++ uint fwp = (nsp == 1) ? 0 : 1; ++ asd = get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd == 0) { ++ AP6210_ERR("Missing descriptor for SW %d\n", i); ++ goto error; ++ } ++ if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { ++ AP6210_ERR("Slave wrapper %d is not 4KB\n", i); ++ goto error; ++ } ++ if ((nmw == 0) && (i == 0)) ++ sii->wrapba[idx] = addrl; ++ } ++ ++ ++ /* Don't record bridges */ ++ if (br) ++ continue; ++ ++ /* Done with core */ ++ sii->numcores++; ++ } ++ ++ AP6210_ERR("Reached end of erom without finding END"); ++ ++error: ++ sii->numcores = 0; ++ return; ++} ++ ++/* This function changes the logical "focus" to the indicated core. ++ * Return the current core's virtual address. ++ */ ++void * ++ai_setcoreidx(si_t *sih, uint coreidx) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ uint32 addr, wrap; ++ void *regs; ++ ++ if (coreidx >= MIN(sii->numcores, SI_MAXCORES)) ++ return (NULL); ++ ++ addr = sii->coresba[coreidx]; ++ wrap = sii->wrapba[coreidx]; ++ ++ /* ++ * If the user has provided an interrupt mask enabled function, ++ * then assert interrupts are disabled before switching the core. ++ */ ++ ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg)); ++ ++ switch (BUSTYPE(sih->bustype)) { ++ case SI_BUS: ++ /* map new one */ ++ if (!sii->regs[coreidx]) { ++ sii->regs[coreidx] = REG_MAP(addr, SI_CORE_SIZE); ++ ASSERT(GOODREGS(sii->regs[coreidx])); ++ } ++ sii->curmap = regs = sii->regs[coreidx]; ++ if (!sii->wrappers[coreidx]) { ++ sii->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE); ++ ASSERT(GOODREGS(sii->wrappers[coreidx])); ++ } ++ sii->curwrap = sii->wrappers[coreidx]; ++ break; ++ ++ ++ case SPI_BUS: ++ case SDIO_BUS: ++ sii->curmap = regs = (void *)((uintptr)addr); ++ sii->curwrap = (void *)((uintptr)wrap); ++ break; ++ ++ case PCMCIA_BUS: ++ default: ++ ASSERT(0); ++ regs = NULL; ++ break; ++ } ++ ++ sii->curmap = regs; ++ sii->curidx = coreidx; ++ ++ return regs; ++} ++ ++void ++ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ chipcregs_t *cc = NULL; ++ uint32 erombase, *eromptr, *eromlim; ++ uint i, j, cidx; ++ uint32 cia, cib, nmp, nsp; ++ uint32 asd, addrl, addrh, sizel, sizeh; ++ ++ for (i = 0; i < sii->numcores; i++) { ++ if (sii->coreid[i] == CC_CORE_ID) { ++ cc = (chipcregs_t *)sii->regs[i]; ++ break; ++ } ++ } ++ if (cc == NULL) ++ goto error; ++ ++ erombase = R_REG(sii->osh, &cc->eromptr); ++ eromptr = (uint32 *)REG_MAP(erombase, SI_CORE_SIZE); ++ eromlim = eromptr + (ER_REMAPCONTROL / sizeof(uint32)); ++ ++ cidx = sii->curidx; ++ cia = sii->cia[cidx]; ++ cib = sii->cib[cidx]; ++ ++ nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; ++ nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; ++ ++ /* scan for cores */ ++ while (eromptr < eromlim) { ++ if ((get_erom_ent(sih, &eromptr, ER_TAG, ER_CI) == cia) && ++ (get_erom_ent(sih, &eromptr, 0, 0) == cib)) { ++ break; ++ } ++ } ++ ++ /* skip master ports */ ++ for (i = 0; i < nmp; i++) ++ get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); ++ ++ /* Skip ASDs in port 0 */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh); ++ if (asd == 0) { ++ /* Try again to see if it is a bridge */ ++ asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh, ++ &sizel, &sizeh); ++ } ++ ++ j = 1; ++ do { ++ asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ j++; ++ } while (asd != 0); ++ ++ /* Go through the ASDs for other slave ports */ ++ for (i = 1; i < nsp; i++) { ++ j = 0; ++ do { ++ asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh, ++ &sizel, &sizeh); ++ if (asd == 0) ++ break; ++ ++ if (!asidx--) { ++ *addr = addrl; ++ *size = sizel; ++ return; ++ } ++ j++; ++ } while (1); ++ ++ if (j == 0) { ++ AP6210_ERR(" SP %d has no address descriptors\n", i); ++ break; ++ } ++ } ++ ++error: ++ *size = 0; ++ return; ++} ++ ++/* Return the number of address spaces in current core */ ++int ++ai_numaddrspaces(si_t *sih) ++{ ++ return 2; ++} ++ ++/* Return the address of the nth address space in the current core */ ++uint32 ++ai_addrspace(si_t *sih, uint asidx) ++{ ++ si_info_t *sii; ++ uint cidx; ++ ++ sii = SI_INFO(sih); ++ cidx = sii->curidx; ++ ++ if (asidx == 0) ++ return sii->coresba[cidx]; ++ else if (asidx == 1) ++ return sii->coresba2[cidx]; ++ else { ++ AP6210_ERR("%s: Need to parse the erom again to find addr space %d\n", ++ __FUNCTION__, asidx); ++ return 0; ++ } ++} ++ ++/* Return the size of the nth address space in the current core */ ++uint32 ++ai_addrspacesize(si_t *sih, uint asidx) ++{ ++ si_info_t *sii; ++ uint cidx; ++ ++ sii = SI_INFO(sih); ++ cidx = sii->curidx; ++ ++ if (asidx == 0) ++ return sii->coresba_size[cidx]; ++ else if (asidx == 1) ++ return sii->coresba2_size[cidx]; ++ else { ++ AP6210_ERR("%s: Need to parse the erom again to find addr space %d\n", ++ __FUNCTION__, asidx); ++ return 0; ++ } ++} ++ ++uint ++ai_flag(si_t *sih) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ ++ sii = SI_INFO(sih); ++ if (BCM47162_DMP()) { ++ AP6210_ERR("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__); ++ return sii->curidx; ++ } ++ if (BCM5357_DMP()) { ++ AP6210_ERR("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__); ++ return sii->curidx; ++ } ++ ai = sii->curwrap; ++ ++ return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f); ++} ++ ++void ++ai_setint(si_t *sih, int siflag) ++{ ++} ++ ++uint ++ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ uint32 *map = (uint32 *) sii->curwrap; ++ ++ if (mask || val) { ++ uint32 w = R_REG(sii->osh, map+(offset/4)); ++ w &= ~mask; ++ w |= val; ++ W_REG(sii->osh, map+(offset/4), val); ++ } ++ ++ return (R_REG(sii->osh, map+(offset/4))); ++} ++ ++uint ++ai_corevendor(si_t *sih) ++{ ++ si_info_t *sii; ++ uint32 cia; ++ ++ sii = SI_INFO(sih); ++ cia = sii->cia[sii->curidx]; ++ return ((cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT); ++} ++ ++uint ++ai_corerev(si_t *sih) ++{ ++ si_info_t *sii; ++ uint32 cib; ++ ++ sii = SI_INFO(sih); ++ cib = sii->cib[sii->curidx]; ++ return remap_corerev(sih, (cib & CIB_REV_MASK) >> CIB_REV_SHIFT); ++} ++ ++bool ++ai_iscoreup(si_t *sih) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ ++ sii = SI_INFO(sih); ++ ai = sii->curwrap; ++ ++ return (((R_REG(sii->osh, &ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == SICF_CLOCK_EN) && ++ ((R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) == 0)); ++} ++ ++/* ++ * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation, ++ * switch back to the original core, and return the new value. ++ * ++ * When using the silicon backplane, no fiddling with interrupts or core switches is needed. ++ * ++ * Also, when using pci/pcie, we can optimize away the core switching for pci registers ++ * and (on newer pci cores) chipcommon registers. ++ */ ++uint ++ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) ++{ ++ uint origidx = 0; ++ uint32 *r = NULL; ++ uint w; ++ uint intr_val = 0; ++ bool fast = FALSE; ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ ASSERT(GOODIDX(coreidx)); ++ ASSERT(regoff < SI_CORE_SIZE); ++ ASSERT((val & ~mask) == 0); ++ ++ if (coreidx >= SI_MAXCORES) ++ return 0; ++ ++ if (BUSTYPE(sih->bustype) == SI_BUS) { ++ /* If internal bus, we can always get at everything */ ++ fast = TRUE; ++ /* map if does not exist */ ++ if (!sii->regs[coreidx]) { ++ sii->regs[coreidx] = REG_MAP(sii->coresba[coreidx], ++ SI_CORE_SIZE); ++ ASSERT(GOODREGS(sii->regs[coreidx])); ++ } ++ r = (uint32 *)((uchar *)sii->regs[coreidx] + regoff); ++ } else if (BUSTYPE(sih->bustype) == PCI_BUS) { ++ /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ ++ ++ if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) { ++ /* Chipc registers are mapped at 12KB */ ++ ++ fast = TRUE; ++ r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff); ++ } else if (sii->pub.buscoreidx == coreidx) { ++ /* pci registers are at either in the last 2KB of an 8KB window ++ * or, in pcie and pci rev 13 at 8KB ++ */ ++ fast = TRUE; ++ if (SI_FAST(sii)) ++ r = (uint32 *)((char *)sii->curmap + ++ PCI_16KB0_PCIREGS_OFFSET + regoff); ++ else ++ r = (uint32 *)((char *)sii->curmap + ++ ((regoff >= SBCONFIGOFF) ? ++ PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + ++ regoff); ++ } ++ } ++ ++ if (!fast) { ++ INTR_OFF(sii, intr_val); ++ ++ /* save current core index */ ++ origidx = si_coreidx(&sii->pub); ++ ++ /* switch core */ ++ r = (uint32*) ((uchar*) ai_setcoreidx(&sii->pub, coreidx) + regoff); ++ } ++ ASSERT(r != NULL); ++ ++ /* mask and set */ ++ if (mask || val) { ++ w = (R_REG(sii->osh, r) & ~mask) | val; ++ W_REG(sii->osh, r, w); ++ } ++ ++ /* readback */ ++ w = R_REG(sii->osh, r); ++ ++ if (!fast) { ++ /* restore core index */ ++ if (origidx != coreidx) ++ ai_setcoreidx(&sii->pub, origidx); ++ ++ INTR_RESTORE(sii, intr_val); ++ } ++ ++ return (w); ++} ++ ++void ++ai_core_disable(si_t *sih, uint32 bits) ++{ ++ si_info_t *sii; ++ volatile uint32 dummy; ++ uint32 status; ++ aidmp_t *ai; ++ ++ sii = SI_INFO(sih); ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ /* if core is already in reset, just return */ ++ if (R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) ++ return; ++ ++ /* ensure there are no pending backplane operations */ ++ SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 300); ++ ++ /* if pending backplane ops still, try waiting longer */ ++ if (status != 0) { ++ /* 300usecs was sufficient to allow backplane ops to clear for big hammer */ ++ /* during driver load we may need more time */ ++ SPINWAIT(((status = R_REG(sii->osh, &ai->resetstatus)) != 0), 10000); ++ /* if still pending ops, continue on and try disable anyway */ ++ /* this is in big hammer path, so don't call wl_reinit in this case... */ ++ } ++ ++ W_REG(sii->osh, &ai->ioctrl, bits); ++ dummy = R_REG(sii->osh, &ai->ioctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(10); ++ ++ W_REG(sii->osh, &ai->resetctrl, AIRC_RESET); ++ dummy = R_REG(sii->osh, &ai->resetctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++} ++ ++/* reset and re-enable a core ++ * inputs: ++ * bits - core specific bits that are set during and after reset sequence ++ * resetbits - core specific bits that are set only during reset sequence ++ */ ++void ++ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ volatile uint32 dummy; ++ ++ sii = SI_INFO(sih); ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ /* ++ * Must do the disable sequence first to work for arbitrary current core state. ++ */ ++ ai_core_disable(sih, (bits | resetbits)); ++ ++ /* ++ * Now do the initialization sequence. ++ */ ++ W_REG(sii->osh, &ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN)); ++ dummy = R_REG(sii->osh, &ai->ioctrl); ++ BCM_REFERENCE(dummy); ++ ++ W_REG(sii->osh, &ai->resetctrl, 0); ++ dummy = R_REG(sii->osh, &ai->resetctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++ ++ W_REG(sii->osh, &ai->ioctrl, (bits | SICF_CLOCK_EN)); ++ dummy = R_REG(sii->osh, &ai->ioctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++} ++ ++void ++ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ uint32 w; ++ ++ sii = SI_INFO(sih); ++ ++ if (BCM47162_DMP()) { ++ AP6210_ERR("%s: Accessing MIPS DMP register (ioctrl) on 47162a0", ++ __FUNCTION__); ++ return; ++ } ++ if (BCM5357_DMP()) { ++ AP6210_ERR("%s: Accessing USB20H DMP register (ioctrl) on 5357\n", ++ __FUNCTION__); ++ return; ++ } ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ ASSERT((val & ~mask) == 0); ++ ++ if (mask || val) { ++ w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val); ++ W_REG(sii->osh, &ai->ioctrl, w); ++ } ++} ++ ++uint32 ++ai_core_cflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ uint32 w; ++ ++ sii = SI_INFO(sih); ++ if (BCM47162_DMP()) { ++ AP6210_ERR("%s: Accessing MIPS DMP register (ioctrl) on 47162a0", ++ __FUNCTION__); ++ return 0; ++ } ++ if (BCM5357_DMP()) { ++ AP6210_ERR("%s: Accessing USB20H DMP register (ioctrl) on 5357\n", ++ __FUNCTION__); ++ return 0; ++ } ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ ASSERT((val & ~mask) == 0); ++ ++ if (mask || val) { ++ w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val); ++ W_REG(sii->osh, &ai->ioctrl, w); ++ } ++ ++ return R_REG(sii->osh, &ai->ioctrl); ++} ++ ++uint32 ++ai_core_sflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ si_info_t *sii; ++ aidmp_t *ai; ++ uint32 w; ++ ++ sii = SI_INFO(sih); ++ if (BCM47162_DMP()) { ++ AP6210_ERR("%s: Accessing MIPS DMP register (iostatus) on 47162a0", ++ __FUNCTION__); ++ return 0; ++ } ++ if (BCM5357_DMP()) { ++ AP6210_ERR("%s: Accessing USB20H DMP register (iostatus) on 5357\n", ++ __FUNCTION__); ++ return 0; ++ } ++ ++ ASSERT(GOODREGS(sii->curwrap)); ++ ai = sii->curwrap; ++ ++ ASSERT((val & ~mask) == 0); ++ ASSERT((mask & ~SISF_CORE_BITS) == 0); ++ ++ if (mask || val) { ++ w = ((R_REG(sii->osh, &ai->iostatus) & ~mask) | val); ++ W_REG(sii->osh, &ai->iostatus, w); ++ } ++ ++ return R_REG(sii->osh, &ai->iostatus); ++} +diff --git a/drivers/net/wireless/ap6210/ap6210.h b/drivers/net/wireless/ap6210/ap6210.h +new file mode 100755 +index 0000000..90e7d8d +--- /dev/null ++++ b/drivers/net/wireless/ap6210/ap6210.h +@@ -0,0 +1,22 @@ ++#ifndef __AP6210_H__ ++#define __AP6210_H__ ++ ++#define AP6210_EMERG(...) pr_emerg("[ap6210] "__VA_ARGS__) ++#define AP6210_ALERT(...) pr_alert("[ap6210] "__VA_ARGS__) ++#define AP6210_CRIT(...) pr_crit("[ap6210] "__VA_ARGS__) ++#define AP6210_ERR(...) pr_err("[ap6210] "__VA_ARGS__) ++#define AP6210_WARN(...) pr_warn("[ap6210] "__VA_ARGS__) ++#define AP6210_NOTICE(...) pr_notice("[ap6210] "__VA_ARGS__) ++#define AP6210_INFO(...) pr_info("[ap6210] "__VA_ARGS__) ++#define AP6210_DEBUG(...) pr_debug("[ap6210] "__VA_ARGS__) ++#define AP6210_DUMP(...) pr_debug(__VA_ARGS__) ++#define AP6210_CONT(...) pr_cont(__VA_ARGS__) ++ ++extern int __init sw_rfkill_init(void); ++extern void __exit sw_rfkill_exit(void); ++ ++extern int __init ap6210_gpio_wifi_init(void); ++extern void __exit ap6210_gpio_wifi_exit(void); ++ ++ ++#endif /* __AP6210_H__ */ +diff --git a/drivers/net/wireless/ap6210/ap6210_gpio.h b/drivers/net/wireless/ap6210/ap6210_gpio.h +new file mode 100755 +index 0000000..96a3166 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/ap6210_gpio.h +@@ -0,0 +1,9 @@ ++#ifndef __AP6210_GPIO_H__ ++#define __AP6210_GPIO_H__ ++ ++extern int ap6210_gpio_wifi_get_mod_type(void); ++extern int ap6210_gpio_wifi_gpio_ctrl(char* name, int level); ++extern void ap6210_gpio_wifi_power(int on); ++extern char *ap6210_gpio_wifi_get_name(int module_sel); ++ ++#endif /* __AP6210_GPIO_H__ */ +diff --git a/drivers/net/wireless/ap6210/ap6210_gpio_bt.c b/drivers/net/wireless/ap6210/ap6210_gpio_bt.c +new file mode 100755 +index 0000000..4686615 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/ap6210_gpio_bt.c +@@ -0,0 +1,164 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if (defined CONFIG_MMC) ++#include "ap6210_gpio.h" ++#else ++static __inline int ap6210_gpio_wifi_get_mod_type(void) ++{ ++ AP6210_DEBUG("%s : not implemented!\n", __FUNCTION__ ); ++ return 0; ++} ++static __inline int ap6210_gpio_wifi_gpio_ctrl(char* name, int level) ++{ ++ AP6210_DEBUG("%s : not implemented!\n", __FUNCTION__ ); ++ return -1; ++} ++#endif ++ ++#include ++ ++static const char bt_name[] = "bcm40183"; ++static struct rfkill *sw_rfkill; ++static int bt_used; ++ ++static int rfkill_set_power(void *data, bool blocked) ++{ ++ unsigned int mod_sel = ap6210_gpio_wifi_get_mod_type(); ++ ++ AP6210_DEBUG("rfkill set power %s\n", ( blocked ? "blocked" : "unblocked" )); ++ ++ switch (mod_sel) ++ { ++ case 2: /* bcm40183 */ ++ if (!blocked) { ++ ap6210_gpio_wifi_gpio_ctrl("bcm40183_bt_regon", 1); ++ ap6210_gpio_wifi_gpio_ctrl("bcm40183_bt_rst", 1); ++ } else { ++ ap6210_gpio_wifi_gpio_ctrl("bcm40183_bt_rst", 0); ++ ap6210_gpio_wifi_gpio_ctrl("bcm40183_bt_regon", 0); ++ } ++ AP6210_ERR("Using %s configuration.\n", ap6210_gpio_wifi_get_name(mod_sel) ); ++ break; ++ case 3: /* realtek rtl8723as */ ++ if (!blocked) { ++ ap6210_gpio_wifi_gpio_ctrl("rtk_rtl8723as_bt_dis", 1); ++ } else { ++ ap6210_gpio_wifi_gpio_ctrl("rtk_rtl8723as_bt_dis", 0); ++ } ++ AP6210_ERR("Using %s configuration.\n", ap6210_gpio_wifi_get_name(mod_sel) ); ++ break; ++ case 7: /* ap6210 */ ++ case 8: /* ap6330 */ ++ if (!blocked) { ++ ap6210_gpio_wifi_gpio_ctrl("ap6xxx_bt_regon", 1); ++ } else { ++ ap6210_gpio_wifi_gpio_ctrl("ap6xxx_bt_regon", 0); ++ } ++ AP6210_ERR("Using %s configuration.\n", ap6210_gpio_wifi_get_name(mod_sel) ); ++ break; ++ case 10: /* realtek rtl8723au */ ++ if (!blocked) { ++ ap6210_gpio_wifi_gpio_ctrl("rtl8723au_bt", 1); ++ } else { ++ ap6210_gpio_wifi_gpio_ctrl("rtl8723au_bt", 0); ++ } ++ AP6210_ERR("Using %s configuration.\n", ap6210_gpio_wifi_get_name(mod_sel) ); ++ break; ++ default: ++ AP6210_ERR("no bluetooth module matched.\n" ); ++ } ++ ++ msleep(10); ++ return 0; ++} ++ ++static struct rfkill_ops sw_rfkill_ops = { ++ .set_block = rfkill_set_power, ++}; ++ ++static int sw_rfkill_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ sw_rfkill = rfkill_alloc(bt_name, &pdev->dev, ++ RFKILL_TYPE_BLUETOOTH, &sw_rfkill_ops, NULL); ++ if (unlikely(!sw_rfkill)) { ++ AP6210_DEBUG("Unable to alocate rfkill structure.\n" ); ++ return -ENOMEM; ++ } ++ ++ ret = rfkill_register(sw_rfkill); ++ if (unlikely(ret)) { ++ AP6210_DEBUG("Unable to register rfkill structure.\n" ); ++ rfkill_destroy(sw_rfkill); ++ } ++ AP6210_DEBUG("rfkill structure registered successfully.\n" ); ++ return ret; ++} ++ ++static int sw_rfkill_remove(struct platform_device *pdev) ++{ ++ if (likely(sw_rfkill)) { ++ rfkill_unregister(sw_rfkill); ++ rfkill_destroy(sw_rfkill); ++ AP6210_DEBUG("rfkill structure removed successfully.\n" ); ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver sw_rfkill_driver = { ++ .probe = sw_rfkill_probe, ++ .remove = sw_rfkill_remove, ++ .driver = { ++ .name = "sunxi-rfkill", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static struct platform_device sw_rfkill_dev = { ++ .name = "sunxi-rfkill", ++}; ++ ++int __init sw_rfkill_init(void) ++{ ++ if (SCRIPT_PARSER_OK != script_parser_fetch("bt_para", "bt_used", &bt_used, 1)) { ++ AP6210_DEBUG("parse bt_used failed in script.fex.\n" ); ++ return -1; ++ } ++ ++ if (!bt_used) { ++ AP6210_ERR("bluetooth is disable in script.fex.\n" ); ++ return 0; ++ } ++ ++ platform_device_register(&sw_rfkill_dev); ++ AP6210_ERR("platform device registered successfully.\n" ); ++ return platform_driver_register(&sw_rfkill_driver); ++} ++ ++void __exit sw_rfkill_exit(void) ++{ ++ if (!bt_used) { ++ AP6210_ERR("exit no bt used in configuration\n" ); ++ return ; ++ } ++ ++ platform_device_unregister(&sw_rfkill_dev); ++ platform_driver_unregister(&sw_rfkill_driver); ++} ++ ++/* ++module_init(sw_rfkill_init); ++module_exit(sw_rfkill_exit); ++ ++MODULE_DESCRIPTION("sunxi-rfkill driver"); ++MODULE_AUTHOR("Aaron.magic"); ++MODULE_LICENSE("GPL"); ++*/ ++ +diff --git a/drivers/net/wireless/ap6210/ap6210_gpio_wifi.c b/drivers/net/wireless/ap6210/ap6210_gpio_wifi.c +new file mode 100755 +index 0000000..916749d +--- /dev/null ++++ b/drivers/net/wireless/ap6210/ap6210_gpio_wifi.c +@@ -0,0 +1,463 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static char *wifi_para = "sdio_wifi_pro_para"; /*modify by lemaker team for ap6210*/ ++ ++struct ap6210_gpio_wifi_ops { ++ char* mod_name; ++ int wifi_used; ++ int sdio_id; ++ int usb_id; ++ int module_sel; ++ int (*gpio_ctrl)(char* name, int level); ++ void (*standby)(int in); ++ void (*power)(int mode, int *updown); ++ ++#ifdef CONFIG_PROC_FS ++ struct proc_dir_entry *proc_root; ++ struct proc_dir_entry *proc_power; ++#endif /* CONFIG_PROC_FS */ ++}; ++ ++static unsigned int ap6210_wl_regon = 0; ++static unsigned int ap6210_bt_regon = 0; ++static unsigned int ap6210_wl_vdd_en = 0; /*add by lemaker team for ap6210*/ ++ ++struct ap6210_gpio_wifi_ops ap6210_wifi_select_pm_ops; ++ ++char *ap6210_gpio_wifi_get_name(int module_sel) { ++ char* mod_name[] = { " ", ++ "bcm40181", /* 1 - BCM40181(BCM4330)*/ ++ "bcm40183", /* 2 - BCM40183(BCM4330)*/ ++ "rtl8723as", /* 3 - RTL8723AS(RF-SM02B) */ ++ "rtl8189es", /* 4 - RTL8189ES(SM89E00) */ ++ "rtl8192cu", /* 5 - RTL8192CU*/ ++ "rtl8188eu", /* 6 - RTL8188EU*/ ++ "ap6210", /* 7 - AP6210*/ ++ "ap6330", /* 8 - AP6330*/ ++ "ap6181", /* 9 - AP6181*/ ++ "rtl8723au", /* 10 - RTL8723AU */ ++ }; ++ ++ return(mod_name[module_sel]); ++} ++ ++EXPORT_SYMBOL(ap6210_gpio_wifi_get_name); ++ ++static int ap6210_gpio_ctrl(char* name, int level) ++{ ++ int i = 0; ++ int ret = 0; ++ int gpio = 0; ++ char * gpio_name[3] = {"ap6210_wl_regon", "ap6210_bt_regon", "ap6210_wl_vdd_en"}; /*modify by lemaker team for ap6210*/ ++ ++ for (i = 0; i < 3; i++) { ++ if (strcmp(name, gpio_name[i]) == 0) { ++ switch (i) ++ { ++ case 0: /*ap6210_wl_regon*/ ++ gpio = ap6210_wl_regon; ++ break; ++ case 1: /*ap6210_bt_regon*/ ++ gpio = ap6210_bt_regon; ++ break; ++ case 2: /*add by lemaker team for ap6210*/ ++ gpio = ap6210_wl_vdd_en; ++ break; ++ default: ++ AP6210_ERR("no matched gpio.\n" ); ++ } ++ break; ++ } ++ } ++ ++ ret = gpio_write_one_pin_value(gpio, level, name); ++ ++ if (ret) /*add by lemaker team for ap6210*/ ++ { ++ AP6210_INFO("Failed to set the gpio %s to %d\n", name, level); ++ return -1; ++ }else{ ++ AP6210_INFO("Succeed to set the gpio %s to %d\n", name, level); ++ } ++ ++ return 0; ++} ++ ++static int ap6210_gpio_read(char* name) ++{ ++ int i = 0; ++ int gpio = 0; ++ int val = 0; ++ char * gpio_name[3] = {"ap6210_wl_regon", "ap6210_bt_regon", "ap6210_wl_vdd_en"}; /*modify by lemaker team for ap6210*/ ++ ++ for (i = 0; i < 3; i++) { ++ if (strcmp(name, gpio_name[i]) == 0) { ++ switch (i) ++ { ++ case 0: /*ap6210_wl_regon*/ ++ gpio = ap6210_wl_regon; ++ break; ++ case 1: /*ap6210_bt_regon*/ ++ gpio = ap6210_bt_regon; ++ break; ++ case 2: /*add by lemaker team for ap6210*/ ++ gpio = ap6210_wl_vdd_en; ++ break; ++ default: ++ AP6210_ERR("no matched gpio.\n" ); ++ } ++ break; ++ } ++ } ++ ++ val = gpio_read_one_pin_value(gpio, name); ++ ++ return val; ++} ++ ++ ++void ap6210_power(int mode, int *updown) ++{ ++ if (mode) { ++ if (*updown) { ++ ap6210_gpio_ctrl("ap6210_wl_regon", 1); ++ mdelay(100); ++ } else { ++ ap6210_gpio_ctrl("ap6210_wl_regon", 0); ++ mdelay(100); ++ } ++ AP6210_DEBUG("sdio wifi power state: %s\n", *updown ? "on" : "off"); ++ } else { ++ *updown = ap6210_gpio_read("ap6210_wl_regon"); ++ } ++ ++ return; ++} ++/* remove by lemaker team for ap6210 ++static void ap6210_cfg_gpio_32k_clkout(int gpio_index) ++{ ++ int ret; ++ struct clk *clk_32k, *parent; ++ ++ parent = clk_get(NULL, CLK_SYS_LOSC); ++ clk_32k = clk_get(NULL, CLK_MOD_OUTA); ++ ret = clk_set_parent(clk_32k, parent); ++ ++ if(ret){ ++ AP6210_ERR("32k clk_set_parent fail.\n" ); ++ return; ++ } ++ ++ ret = clk_set_rate(clk_32k, 32768); ++ if(ret){ ++ AP6210_ERR("32k clk_set_rate fail.\n" ); ++ return; ++ } ++ ++ clk_enable(clk_32k); ++} ++*/ ++void ap6210_gpio_init(void) ++{ ++ struct ap6210_gpio_wifi_ops *ops = &ap6210_wifi_select_pm_ops; ++ /*int ap6210_lpo = 0;*/ ++ ++/* CT expected ap6210_lpo as a GPIO */ ++/* remove by lemaker team for ap6210 ++ ap6210_lpo = gpio_request_ex(wifi_para, "ap6xxx_lpo"); ++ if (!ap6210_lpo) { ++ AP6210_ERR("request lpo gpio failed.\n" ); ++ return; ++ } ++ ++ if(ap6210_lpo) { ++ AP6210_DEBUG("config 32k clock.\n" ); ++ ap6210_cfg_gpio_32k_clkout(ap6210_lpo); ++ } ++*/ ++ ap6210_wl_regon = gpio_request_ex(wifi_para, "ap6xxx_wl_regon"); ++ if (!ap6210_wl_regon) { ++ AP6210_ERR("request wl_regon gpio failed.\n" ); ++ return; ++ } ++ /* The comment must remove when we use the Bluetooth ++ ap6210_bt_regon = gpio_request_ex(wifi_para, "ap6xxx_bt_regon"); ++ if (!ap6210_bt_regon) { ++ AP6210_ERR("request ap6210_bt_regon gpio failed.\n" ); ++ return; ++ } ++ */ ++ ++ /*add by lemaker team for ap6210*/ ++ ap6210_wl_vdd_en = gpio_request_ex(wifi_para, "ap6xxx_wl_vdd_en"); ++ if (!ap6210_wl_vdd_en) { ++ AP6210_ERR("request wl_vdd_en gpio failed.\n" ); ++ return; ++ } ++ ops->gpio_ctrl = ap6210_gpio_ctrl; ++ ops->power = ap6210_power; ++ ++ ap6210_gpio_ctrl("ap6210_wl_vdd_en", 0); /*enable the vdd*/ ++ ++} ++ ++int ap6210_gpio_wifi_get_mod_type(void) ++{ ++ struct ap6210_gpio_wifi_ops *ops = &ap6210_wifi_select_pm_ops; ++ if (ops->wifi_used) ++ return ops->module_sel; ++ else { ++ AP6210_ERR("No wifi type selected, please check your config.\n" ); ++ return 0; ++ } ++} ++EXPORT_SYMBOL(ap6210_gpio_wifi_get_mod_type); ++ ++int ap6210_gpio_wifi_gpio_ctrl(char* name, int level) ++{ ++ struct ap6210_gpio_wifi_ops *ops = &ap6210_wifi_select_pm_ops; ++ if (ops->wifi_used && ops->gpio_ctrl) ++ return ops->gpio_ctrl(name, level); ++ else { ++ AP6210_ERR("No wifi type selected, please check your config.\n" ); ++ return -1; ++ } ++} ++EXPORT_SYMBOL(ap6210_gpio_wifi_gpio_ctrl); ++ ++void ap6210_gpio_wifi_power(int on) ++{ ++ struct ap6210_gpio_wifi_ops *ops = &ap6210_wifi_select_pm_ops; ++ int power = on; ++ ++ if (ops->wifi_used && ops->power) ++ return ops->power(1, &power); ++ else { ++ AP6210_ERR("No wifi type selected, please check your config.\n" ); ++ return; ++ } ++} ++EXPORT_SYMBOL(ap6210_gpio_wifi_power); ++ ++#ifdef CONFIG_PROC_FS ++static int ap6210_gpio_wifi_power_stat(char *page, char **start, off_t off, int count, int *eof, void *data) ++{ ++ struct ap6210_gpio_wifi_ops *ops = (struct ap6210_gpio_wifi_ops *)data; ++ char *p = page; ++ int power = 0; ++ ++ if (ops->power) ++ ops->power(0, &power); ++ ++ p += sprintf(p, "%s : power state %s\n", ops->mod_name, power ? "on" : "off"); ++ return p - page; ++} ++ ++static int ap6210_gpio_wifi_power_ctrl(struct file *file, const char __user *buffer, unsigned long count, void *data) ++{ ++ struct ap6210_gpio_wifi_ops *ops = (struct ap6210_gpio_wifi_ops *)data; ++ int power = simple_strtoul(buffer, NULL, 10); ++ ++ power = power ? 1 : 0; ++ if (ops->power) ++ ops->power(1, &power); ++ else ++ AP6210_ERR("No power control for %s\n", ops->mod_name); ++ return sizeof(power); ++} ++ ++static inline void awwifi_procfs_attach(void) ++{ ++ char proc_rootname[] = "driver/ap6210_gpio_wifi"; ++ char proc_powername[] = "power"; ++ ++ struct ap6210_gpio_wifi_ops *ops = &ap6210_wifi_select_pm_ops; ++ ++ ops->proc_root = proc_mkdir(proc_rootname, NULL); ++ if (IS_ERR(ops->proc_root)) ++ { ++ AP6210_ERR("failed to create procfs \"%s\".\n", proc_rootname ); ++ } ++ ++ ops->proc_power = create_proc_entry(proc_powername, 0644, ops->proc_root); ++ if (IS_ERR(ops->proc_power)) ++ { ++ AP6210_ERR("failed to create procfs \"%s\".\n", proc_powername); ++ } ++ ops->proc_power->data = ops; ++ ops->proc_power->read_proc = ap6210_gpio_wifi_power_stat; ++ ops->proc_power->write_proc = ap6210_gpio_wifi_power_ctrl; ++} ++ ++static inline void awwifi_procfs_remove(void) ++{ ++ struct ap6210_gpio_wifi_ops *ops = &ap6210_wifi_select_pm_ops; ++ char proc_rootname[] = "driver/ap6210_gpio_wifi"; ++ ++ remove_proc_entry("power", ops->proc_root); ++ remove_proc_entry(proc_rootname, NULL); ++} ++#else ++static inline void awwifi_procfs_attach(void) {} ++static inline void awwifi_procfs_remove(void) {} ++#endif ++ ++ ++ ++static int ap6210_gpio_wifi_get_res(void) ++{ ++ struct ap6210_gpio_wifi_ops *ops = &ap6210_wifi_select_pm_ops; ++ ++ /*add by lemaker team for AP6210*/ ++ if (SCRIPT_PARSER_OK != script_parser_fetch(wifi_para, "sdio_wifi_pro_used", &ops->wifi_used, 1)) { ++ AP6210_ERR("parse sdio_wifi_pro_used failed in script.fex.\n" ); ++ return -1; ++ } ++ if (!ops->wifi_used) { ++ AP6210_ERR("wifi pm disable in script.fex.\n" ); ++ return -1; ++ } ++ ++ /*add by lemaker team for AP6210*/ ++ if (SCRIPT_PARSER_OK != script_parser_fetch(wifi_para, "sdio_wifi_pro_sdc_id", &ops->sdio_id, 1)) { ++ AP6210_ERR("parse sdio_wifi_pro_sdc_id in script.fex failed.\n" ); ++ return -1; ++ } ++/* remove by lemaker team for AP6210 ++ if (SCRIPT_PARSER_OK != script_parser_fetch(wifi_para, "wifi_usbc_id", &ops->usb_id, 1)) { ++ AP6210_ERR("parse wifi_sdc_id in script.fex failed.\n" ); ++ return -1; ++ } ++*/ ++ /*add by lemaker team for AP6210*/ ++ if (SCRIPT_PARSER_OK != script_parser_fetch(wifi_para, "sdio_wifi_pro_mod_sel", &ops->module_sel, 1)) { ++ AP6210_ERR("parse sdio_wifi_pro_mod_sel in script.fex failed.\n" ); ++ return -1; ++ } ++ ++ ops->mod_name = ap6210_gpio_wifi_get_name(ops->module_sel); ++ ++ AP6210_ERR("select wifi %s\n", ops->mod_name); ++ ++ return 0; ++} ++ ++static int __devinit ap6210_gpio_wifi_probe(struct platform_device *pdev) ++{ ++ struct ap6210_gpio_wifi_ops *ops = &ap6210_wifi_select_pm_ops; ++ ++ switch (ops->module_sel) { ++ case 1: /* BCM40181 */ ++ case 2: /* BCM40183 */ ++ case 3: /* RTL8723AS */ ++ case 4: /* RTL8189ES */ ++ case 5: /* RTL8192CU */ ++ case 6: /* RTL8188EU */ ++ AP6210_ERR("Unsupported device.\n"); ++ break; ++ case 7: /* AP6210 */ ++ case 8: /* AP6330 */ ++ case 9: /* AP6181 */ ++ AP6210_ERR("Initializing %s.\n", ops->mod_name); ++ ap6210_gpio_init(); ++ break; ++ case 10: /* RTL8723AU */ ++ AP6210_ERR("Unsupported device.\n"); ++ break; ++ default: ++ AP6210_ERR("Unsupported device.\n"); ++ } ++ ++ awwifi_procfs_attach(); ++ AP6210_DEBUG("wifi gpio attached.\n" ); ++ return 0; ++} ++ ++static int __devexit ap6210_gpio_wifi_remove(struct platform_device *pdev) ++{ ++ awwifi_procfs_remove(); ++ AP6210_DEBUG("wifi gpio released.\n" ); ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int ap6210_gpio_wifi_suspend(struct device *dev) ++{ ++ struct ap6210_gpio_wifi_ops *ops = &ap6210_wifi_select_pm_ops; ++ ++ if (ops->standby) ++ ops->standby(1); ++ return 0; ++} ++ ++static int ap6210_gpio_wifi_resume(struct device *dev) ++{ ++ struct ap6210_gpio_wifi_ops *ops = &ap6210_wifi_select_pm_ops; ++ ++ if (ops->standby) ++ ops->standby(0); ++ return 0; ++} ++ ++static struct dev_pm_ops wifi_dev_pm_ops = { ++ .suspend = ap6210_gpio_wifi_suspend, ++ .resume = ap6210_gpio_wifi_resume, ++}; ++#endif ++ ++static struct platform_device ap6210_gpio_wifi_dev = { ++ .name = "ap6210_gpio_wifi", ++}; ++ ++static struct platform_driver ap6210_gpio_wifi_driver = { ++ .driver.name = "ap6210_gpio_wifi", ++ .driver.owner = THIS_MODULE, ++#ifdef CONFIG_PM ++ .driver.pm = &wifi_dev_pm_ops, ++#endif ++ .probe = ap6210_gpio_wifi_probe, ++ .remove = __devexit_p(ap6210_gpio_wifi_remove), ++}; ++ ++int __init ap6210_gpio_wifi_init(void) ++{ ++ struct ap6210_gpio_wifi_ops *ops = &ap6210_wifi_select_pm_ops; ++ ++ memset(ops, 0, sizeof(struct ap6210_gpio_wifi_ops)); ++ ap6210_gpio_wifi_get_res(); ++ if (!ops->wifi_used) ++ return 0; ++ ++ platform_device_register(&ap6210_gpio_wifi_dev); ++ return platform_driver_register(&ap6210_gpio_wifi_driver); ++} ++ ++void __exit ap6210_gpio_wifi_exit(void) ++{ ++ struct ap6210_gpio_wifi_ops *ops = &ap6210_wifi_select_pm_ops; ++ if (!ops->wifi_used) ++ return; ++ ++ platform_driver_unregister(&ap6210_gpio_wifi_driver); ++ memset(ops, 0, sizeof(struct ap6210_gpio_wifi_ops)); ++} ++ ++/* ++module_init(ap6210_gpio_wifi_init); ++module_exit(ap6210_gpio_wifi_exit); ++ ++MODULE_LICENSE("GPL"); ++*/ +diff --git a/drivers/net/wireless/ap6210/bcmevent.c b/drivers/net/wireless/ap6210/bcmevent.c +new file mode 100755 +index 0000000..16e2fca +--- /dev/null ++++ b/drivers/net/wireless/ap6210/bcmevent.c +@@ -0,0 +1,152 @@ ++/* ++ * bcmevent read-only data shared by kernel or app layers ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * $Id: bcmevent.c 370587 2012-11-22 09:32:38Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if WLC_E_LAST != 107 ++#error "You need to add an entry to bcmevent_names[] for the new event" ++#endif ++ ++const bcmevent_name_t bcmevent_names[] = { ++ { WLC_E_SET_SSID, "SET_SSID" }, ++ { WLC_E_JOIN, "JOIN" }, ++ { WLC_E_START, "START" }, ++ { WLC_E_AUTH, "AUTH" }, ++ { WLC_E_AUTH_IND, "AUTH_IND" }, ++ { WLC_E_DEAUTH, "DEAUTH" }, ++ { WLC_E_DEAUTH_IND, "DEAUTH_IND" }, ++ { WLC_E_ASSOC, "ASSOC" }, ++ { WLC_E_ASSOC_IND, "ASSOC_IND" }, ++ { WLC_E_REASSOC, "REASSOC" }, ++ { WLC_E_REASSOC_IND, "REASSOC_IND" }, ++ { WLC_E_DISASSOC, "DISASSOC" }, ++ { WLC_E_DISASSOC_IND, "DISASSOC_IND" }, ++ { WLC_E_QUIET_START, "START_QUIET" }, ++ { WLC_E_QUIET_END, "END_QUIET" }, ++ { WLC_E_BEACON_RX, "BEACON_RX" }, ++ { WLC_E_LINK, "LINK" }, ++ { WLC_E_MIC_ERROR, "MIC_ERROR" }, ++ { WLC_E_NDIS_LINK, "NDIS_LINK" }, ++ { WLC_E_ROAM, "ROAM" }, ++ { WLC_E_TXFAIL, "TXFAIL" }, ++ { WLC_E_PMKID_CACHE, "PMKID_CACHE" }, ++ { WLC_E_RETROGRADE_TSF, "RETROGRADE_TSF" }, ++ { WLC_E_PRUNE, "PRUNE" }, ++ { WLC_E_AUTOAUTH, "AUTOAUTH" }, ++ { WLC_E_EAPOL_MSG, "EAPOL_MSG" }, ++ { WLC_E_SCAN_COMPLETE, "SCAN_COMPLETE" }, ++ { WLC_E_ADDTS_IND, "ADDTS_IND" }, ++ { WLC_E_DELTS_IND, "DELTS_IND" }, ++ { WLC_E_BCNSENT_IND, "BCNSENT_IND" }, ++ { WLC_E_BCNRX_MSG, "BCNRX_MSG" }, ++ { WLC_E_BCNLOST_MSG, "BCNLOST_IND" }, ++ { WLC_E_ROAM_PREP, "ROAM_PREP" }, ++ { WLC_E_PFN_NET_FOUND, "PFNFOUND_IND" }, ++ { WLC_E_PFN_NET_LOST, "PFNLOST_IND" }, ++#if defined(IBSS_PEER_DISCOVERY_EVENT) ++ { WLC_E_IBSS_ASSOC, "IBSS_ASSOC" }, ++#endif /* defined(IBSS_PEER_DISCOVERY_EVENT) */ ++ { WLC_E_RADIO, "RADIO" }, ++ { WLC_E_PSM_WATCHDOG, "PSM_WATCHDOG" }, ++ { WLC_E_PROBREQ_MSG, "PROBE_REQ_MSG" }, ++ { WLC_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND" }, ++ { WLC_E_PSK_SUP, "PSK_SUP" }, ++ { WLC_E_COUNTRY_CODE_CHANGED, "CNTRYCODE_IND" }, ++ { WLC_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME" }, ++ { WLC_E_ICV_ERROR, "ICV_ERROR" }, ++ { WLC_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR" }, ++ { WLC_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR" }, ++ { WLC_E_TRACE, "TRACE" }, ++#ifdef WLBTAMP ++ { WLC_E_BTA_HCI_EVENT, "BTA_HCI_EVENT" }, ++#endif ++ { WLC_E_IF, "IF" }, ++#ifdef WLP2P ++ { WLC_E_P2P_DISC_LISTEN_COMPLETE, "WLC_E_P2P_DISC_LISTEN_COMPLETE" }, ++#endif ++ { WLC_E_RSSI, "RSSI" }, ++ { WLC_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE" }, ++ { WLC_E_EXTLOG_MSG, "EXTERNAL LOG MESSAGE" }, ++#ifdef WIFI_ACT_FRAME ++ { WLC_E_ACTION_FRAME, "ACTION_FRAME" }, ++ { WLC_E_ACTION_FRAME_RX, "ACTION_FRAME_RX" }, ++ { WLC_E_ACTION_FRAME_COMPLETE, "ACTION_FRAME_COMPLETE" }, ++#endif ++#ifdef BCMWAPI_WAI ++ { WLC_E_WAI_STA_EVENT, "WAI_STA_EVENT" }, ++ { WLC_E_WAI_MSG, "WAI_MSG" }, ++#endif /* BCMWAPI_WAI */ ++#if 0 && (NDISVER >= 0x0620) ++ { WLC_E_PRE_ASSOC_IND, "ASSOC_RECV" }, ++ { WLC_E_PRE_REASSOC_IND, "REASSOC_RECV" }, ++ { WLC_E_CHANNEL_ADOPTED, "CHANNEL_ADOPTED" }, ++ { WLC_E_AP_STARTED, "AP_STARTED" }, ++ { WLC_E_DFS_AP_STOP, "DFS_AP_STOP" }, ++ { WLC_E_DFS_AP_RESUME, "DFS_AP_RESUME" }, ++ { WLC_E_ASSOC_IND_NDIS, "ASSOC_IND_NDIS"}, ++ { WLC_E_REASSOC_IND_NDIS, "REASSOC_IND_NDIS"}, ++ { WLC_E_ACTION_FRAME_RX_NDIS, "WLC_E_ACTION_FRAME_RX_NDIS" }, ++ { WLC_E_AUTH_REQ, "WLC_E_AUTH_REQ" }, ++#endif ++ { WLC_E_ESCAN_RESULT, "WLC_E_ESCAN_RESULT" }, ++ { WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, "WLC_E_AF_OFF_CHAN_COMPLETE" }, ++#ifdef WLP2P ++ { WLC_E_PROBRESP_MSG, "PROBE_RESP_MSG" }, ++ { WLC_E_P2P_PROBREQ_MSG, "P2P PROBE_REQ_MSG" }, ++#endif ++#ifdef PROP_TXSTATUS ++ { WLC_E_FIFO_CREDIT_MAP, "FIFO_CREDIT_MAP" }, ++#endif ++ { WLC_E_WAKE_EVENT, "WAKE_EVENT" }, ++ { WLC_E_DCS_REQUEST, "DCS_REQUEST" }, ++ { WLC_E_RM_COMPLETE, "RM_COMPLETE" }, ++#ifdef WLMEDIA_HTSF ++ { WLC_E_HTSFSYNC, "HTSF_SYNC_EVENT" }, ++#endif ++ { WLC_E_OVERLAY_REQ, "OVERLAY_REQ_EVENT" }, ++ { WLC_E_CSA_COMPLETE_IND, "WLC_E_CSA_COMPLETE_IND"}, ++ { WLC_E_EXCESS_PM_WAKE_EVENT, "EXCESS_PM_WAKE_EVENT" }, ++ { WLC_E_PFN_SCAN_NONE, "PFN_SCAN_NONE" }, ++ { WLC_E_PFN_SCAN_ALLGONE, "PFN_SCAN_ALLGONE" }, ++#ifdef SOFTAP ++ { WLC_E_GTK_PLUMBED, "GTK_PLUMBED" }, ++#endif ++ { WLC_E_ASSOC_REQ_IE, "ASSOC_REQ_IE" }, ++ { WLC_E_ASSOC_RESP_IE, "ASSOC_RESP_IE" }, ++ { WLC_E_ACTION_FRAME_RX_NDIS, "WLC_E_ACTION_FRAME_RX_NDIS" }, ++#ifdef WLTDLS ++ { WLC_E_TDLS_PEER_EVENT, "TDLS_PEER_EVENT" }, ++#endif /* WLTDLS */ ++ { WLC_E_SERVICE_FOUND, "SERVICE_FOUND" }, ++ { WLC_E_P2PO_ADD_DEVICE, "P2PO_DEV_FOUND" }, ++ { WLC_E_P2PO_DEL_DEVICE, "P2PO_DEV_LOST" }, ++}; ++ ++const int bcmevent_names_size = ARRAYSIZE(bcmevent_names); +diff --git a/drivers/net/wireless/ap6210/bcmsdh.c b/drivers/net/wireless/ap6210/bcmsdh.c +new file mode 100755 +index 0000000..ca59ff8 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/bcmsdh.c +@@ -0,0 +1,778 @@ ++/* ++ * BCMSDH interface glue ++ * implement bcmsdh API for SDIOH driver ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmsdh.c 373330 2012-12-07 04:46:17Z $ ++ */ ++ ++/** ++ * @file bcmsdh.c ++ */ ++ ++/* ****************** BCMSDH Interface Functions *************************** */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include /* BRCM API for SDIO clients (such as wl, dhd) */ ++#include /* common SDIO/controller interface */ ++#include /* SDIO device core hardware definitions. */ ++ ++#include /* SDIO Device and Protocol Specs */ ++ ++#include ++ ++#define SDIOH_API_ACCESS_RETRY_LIMIT 2 ++const uint bcmsdh_msglevel = BCMSDH_ERROR_VAL; ++ ++/** ++ * BCMSDH API context ++ */ ++struct bcmsdh_info ++{ ++ bool init_success; /* underlying driver successfully attached */ ++ void *sdioh; /* handler for sdioh */ ++ uint32 vendevid; /* Target Vendor and Device ID on SD bus */ ++ osl_t *osh; ++ bool regfail; /* Save status of last reg_read/reg_write call */ ++ uint32 sbwad; /* Save backplane window address */ ++}; ++/* local copy of bcm sd handler */ ++bcmsdh_info_t * l_bcmsdh = NULL; ++ ++#if defined(OOB_INTR_ONLY) && defined(HW_OOB) ++extern int ++sdioh_enable_hw_oob_intr(void *sdioh, bool enable); ++ ++void ++bcmsdh_enable_hw_oob_intr(bcmsdh_info_t *sdh, bool enable) ++{ ++ sdioh_enable_hw_oob_intr(sdh->sdioh, enable); ++} ++#endif ++ ++#if defined(HW_OOB) ++#include ++void ++bcmsdh_config_hw_oob_intr(bcmsdh_info_t *sdh, uint chip) ++{ ++ uint32 gpiocontrol, addr; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ if (CHIPID(chip) == BCM43362_CHIP_ID) { ++ addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, gpiocontrol); ++ gpiocontrol = bcmsdh_reg_read(sdh, addr, 4); ++ gpiocontrol |= 0x2; ++ bcmsdh_reg_write(sdh, addr, 4, gpiocontrol); ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10005, 0xf, NULL); ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10006, 0x0, NULL); ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10007, 0x2, NULL); ++ } ++} ++#endif ++ ++/* Attach BCMSDH layer to SDIO Host Controller Driver ++ * ++ * @param osh OSL Handle. ++ * @param cfghdl Configuration Handle. ++ * @param regsva Virtual address of controller registers. ++ * @param irq Interrupt number of SDIO controller. ++ * ++ * @return bcmsdh_info_t Handle to BCMSDH context. ++ */ ++bcmsdh_info_t * ++bcmsdh_attach(osl_t *osh, void *cfghdl, void **regsva, uint irq) ++{ ++ bcmsdh_info_t *bcmsdh; ++ ++ if ((bcmsdh = (bcmsdh_info_t *)MALLOC(osh, sizeof(bcmsdh_info_t))) == NULL) { ++ BCMSDH_ERROR(("bcmsdh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh))); ++ return NULL; ++ } ++ bzero((char *)bcmsdh, sizeof(bcmsdh_info_t)); ++ ++ /* save the handler locally */ ++ l_bcmsdh = bcmsdh; ++ ++ if (!(bcmsdh->sdioh = sdioh_attach(osh, cfghdl, irq))) { ++ bcmsdh_detach(osh, bcmsdh); ++ return NULL; ++ } ++ ++ bcmsdh->osh = osh; ++ bcmsdh->init_success = TRUE; ++ ++ *regsva = (uint32 *)SI_ENUM_BASE; ++ ++ /* Report the BAR, to fix if needed */ ++ bcmsdh->sbwad = SI_ENUM_BASE; ++ return bcmsdh; ++} ++ ++int ++bcmsdh_detach(osl_t *osh, void *sdh) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ ++ if (bcmsdh != NULL) { ++ if (bcmsdh->sdioh) { ++ sdioh_detach(osh, bcmsdh->sdioh); ++ bcmsdh->sdioh = NULL; ++ } ++ MFREE(osh, bcmsdh, sizeof(bcmsdh_info_t)); ++ } ++ ++ l_bcmsdh = NULL; ++ return 0; ++} ++ ++int ++bcmsdh_iovar_op(void *sdh, const char *name, ++ void *params, int plen, void *arg, int len, bool set) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ return sdioh_iovar_op(bcmsdh->sdioh, name, params, plen, arg, len, set); ++} ++ ++bool ++bcmsdh_intr_query(void *sdh) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ SDIOH_API_RC status; ++ bool on; ++ ++ ASSERT(bcmsdh); ++ status = sdioh_interrupt_query(bcmsdh->sdioh, &on); ++ if (SDIOH_API_SUCCESS(status)) ++ return FALSE; ++ else ++ return on; ++} ++ ++int ++bcmsdh_intr_enable(void *sdh) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ SDIOH_API_RC status; ++ ASSERT(bcmsdh); ++ ++ status = sdioh_interrupt_set(bcmsdh->sdioh, TRUE); ++ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); ++} ++ ++int ++bcmsdh_intr_disable(void *sdh) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ SDIOH_API_RC status; ++ ASSERT(bcmsdh); ++ ++ status = sdioh_interrupt_set(bcmsdh->sdioh, FALSE); ++ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); ++} ++ ++int ++bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ SDIOH_API_RC status; ++ ASSERT(bcmsdh); ++ ++ status = sdioh_interrupt_register(bcmsdh->sdioh, fn, argh); ++ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); ++} ++ ++int ++bcmsdh_intr_dereg(void *sdh) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ SDIOH_API_RC status; ++ ASSERT(bcmsdh); ++ ++ status = sdioh_interrupt_deregister(bcmsdh->sdioh); ++ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); ++} ++ ++#if defined(DHD_DEBUG) ++bool ++bcmsdh_intr_pending(void *sdh) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ ++ ASSERT(sdh); ++ return sdioh_interrupt_pending(bcmsdh->sdioh); ++} ++#endif ++ ++ ++int ++bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh) ++{ ++ ASSERT(sdh); ++ ++ /* don't support yet */ ++ return BCME_UNSUPPORTED; ++} ++ ++/** ++ * Read from SDIO Configuration Space ++ * @param sdh SDIO Host context. ++ * @param func_num Function number to read from. ++ * @param addr Address to read from. ++ * @param err Error return. ++ * @return value read from SDIO configuration space. ++ */ ++uint8 ++bcmsdh_cfg_read(void *sdh, uint fnc_num, uint32 addr, int *err) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ SDIOH_API_RC status; ++#ifdef SDIOH_API_ACCESS_RETRY_LIMIT ++ int32 retry = 0; ++#endif ++ uint8 data = 0; ++ ++ if (!bcmsdh) ++ bcmsdh = l_bcmsdh; ++ ++ ASSERT(bcmsdh->init_success); ++ ++#ifdef SDIOH_API_ACCESS_RETRY_LIMIT ++ do { ++ if (retry) /* wait for 1 ms till bus get settled down */ ++ OSL_DELAY(1000); ++#endif ++ status = sdioh_cfg_read(bcmsdh->sdioh, fnc_num, addr, (uint8 *)&data); ++#ifdef SDIOH_API_ACCESS_RETRY_LIMIT ++ } while (!SDIOH_API_SUCCESS(status) && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); ++#endif ++ if (err) ++ *err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR); ++ ++ BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint8data = 0x%x\n", __FUNCTION__, ++ fnc_num, addr, data)); ++ ++ return data; ++} ++ ++void ++bcmsdh_cfg_write(void *sdh, uint fnc_num, uint32 addr, uint8 data, int *err) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ SDIOH_API_RC status; ++#ifdef SDIOH_API_ACCESS_RETRY_LIMIT ++ int32 retry = 0; ++#endif ++ ++ if (!bcmsdh) ++ bcmsdh = l_bcmsdh; ++ ++ ASSERT(bcmsdh->init_success); ++ ++#ifdef SDIOH_API_ACCESS_RETRY_LIMIT ++ do { ++ if (retry) /* wait for 1 ms till bus get settled down */ ++ OSL_DELAY(1000); ++#endif ++ status = sdioh_cfg_write(bcmsdh->sdioh, fnc_num, addr, (uint8 *)&data); ++#ifdef SDIOH_API_ACCESS_RETRY_LIMIT ++ } while (!SDIOH_API_SUCCESS(status) && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); ++#endif ++ if (err) ++ *err = SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR; ++ ++ BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint8data = 0x%x\n", __FUNCTION__, ++ fnc_num, addr, data)); ++} ++ ++uint32 ++bcmsdh_cfg_read_word(void *sdh, uint fnc_num, uint32 addr, int *err) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ SDIOH_API_RC status; ++ uint32 data = 0; ++ ++ if (!bcmsdh) ++ bcmsdh = l_bcmsdh; ++ ++ ASSERT(bcmsdh->init_success); ++ ++ status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_READ, fnc_num, ++ addr, &data, 4); ++ ++ if (err) ++ *err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR); ++ ++ BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint32data = 0x%x\n", __FUNCTION__, ++ fnc_num, addr, data)); ++ ++ return data; ++} ++ ++void ++bcmsdh_cfg_write_word(void *sdh, uint fnc_num, uint32 addr, uint32 data, int *err) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ SDIOH_API_RC status; ++ ++ if (!bcmsdh) ++ bcmsdh = l_bcmsdh; ++ ++ ASSERT(bcmsdh->init_success); ++ ++ status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_WRITE, fnc_num, ++ addr, &data, 4); ++ ++ if (err) ++ *err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR); ++ ++ BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint32data = 0x%x\n", __FUNCTION__, fnc_num, ++ addr, data)); ++} ++ ++ ++int ++bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ SDIOH_API_RC status; ++ ++ uint8 *tmp_buf, *tmp_ptr; ++ uint8 *ptr; ++ bool ascii = func & ~0xf; ++ func &= 0x7; ++ ++ if (!bcmsdh) ++ bcmsdh = l_bcmsdh; ++ ++ ASSERT(bcmsdh->init_success); ++ ASSERT(cis); ++ ASSERT(length <= SBSDIO_CIS_SIZE_LIMIT); ++ ++ status = sdioh_cis_read(bcmsdh->sdioh, func, cis, length); ++ ++ if (ascii) { ++ /* Move binary bits to tmp and format them into the provided buffer. */ ++ if ((tmp_buf = (uint8 *)MALLOC(bcmsdh->osh, length)) == NULL) { ++ BCMSDH_ERROR(("%s: out of memory\n", __FUNCTION__)); ++ return BCME_NOMEM; ++ } ++ bcopy(cis, tmp_buf, length); ++ for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4); tmp_ptr++) { ++ ptr += snprintf((char*)ptr, (cis + length - ptr - 4), ++ "%.2x ", *tmp_ptr & 0xff); ++ if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0) ++ ptr += snprintf((char *)ptr, (cis + length - ptr -4), "\n"); ++ } ++ MFREE(bcmsdh->osh, tmp_buf, length); ++ } ++ ++ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); ++} ++ ++ ++int ++bcmsdhsdio_set_sbaddr_window(void *sdh, uint32 address, bool force_set) ++{ ++ int err = 0; ++ uint bar0 = address & ~SBSDIO_SB_OFT_ADDR_MASK; ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ ++ if (bar0 != bcmsdh->sbwad || force_set) { ++ bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, ++ (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err); ++ if (!err) ++ bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID, ++ (address >> 16) & SBSDIO_SBADDRMID_MASK, &err); ++ if (!err) ++ bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH, ++ (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err); ++ ++ if (!err) ++ bcmsdh->sbwad = bar0; ++ else ++ /* invalidate cached window var */ ++ bcmsdh->sbwad = 0; ++ ++ } ++ ++ return err; ++} ++ ++uint32 ++bcmsdh_reg_read(void *sdh, uint32 addr, uint size) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ SDIOH_API_RC status; ++ uint32 word = 0; ++ ++ BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, ", __FUNCTION__, addr)); ++ ++ if (!bcmsdh) ++ bcmsdh = l_bcmsdh; ++ ++ ASSERT(bcmsdh->init_success); ++ ++ if (bcmsdhsdio_set_sbaddr_window(bcmsdh, addr, FALSE)) ++ return 0xFFFFFFFF; ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ if (size == 4) ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ ++ status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, ++ SDIOH_READ, SDIO_FUNC_1, addr, &word, size); ++ ++ bcmsdh->regfail = !(SDIOH_API_SUCCESS(status)); ++ ++ BCMSDH_INFO(("uint32data = 0x%x\n", word)); ++ ++ /* if ok, return appropriately masked word */ ++ if (SDIOH_API_SUCCESS(status)) { ++ switch (size) { ++ case sizeof(uint8): ++ return (word & 0xff); ++ case sizeof(uint16): ++ return (word & 0xffff); ++ case sizeof(uint32): ++ return word; ++ default: ++ bcmsdh->regfail = TRUE; ++ ++ } ++ } ++ ++ /* otherwise, bad sdio access or invalid size */ ++ BCMSDH_ERROR(("%s: error reading addr 0x%04x size %d\n", __FUNCTION__, addr, size)); ++ return 0xFFFFFFFF; ++} ++ ++uint32 ++bcmsdh_reg_write(void *sdh, uint32 addr, uint size, uint32 data) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ SDIOH_API_RC status; ++ int err = 0; ++ ++ BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n", ++ __FUNCTION__, addr, size*8, data)); ++ ++ if (!bcmsdh) ++ bcmsdh = l_bcmsdh; ++ ++ ASSERT(bcmsdh->init_success); ++ ++ if ((err = bcmsdhsdio_set_sbaddr_window(bcmsdh, addr, FALSE))) ++ return err; ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ if (size == 4) ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_WRITE, SDIO_FUNC_1, ++ addr, &data, size); ++ bcmsdh->regfail = !(SDIOH_API_SUCCESS(status)); ++ ++ if (SDIOH_API_SUCCESS(status)) ++ return 0; ++ ++ BCMSDH_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n", ++ __FUNCTION__, data, addr, size)); ++ return 0xFFFFFFFF; ++} ++ ++bool ++bcmsdh_regfail(void *sdh) ++{ ++ return ((bcmsdh_info_t *)sdh)->regfail; ++} ++ ++int ++bcmsdh_recv_buf(void *sdh, uint32 addr, uint fn, uint flags, ++ uint8 *buf, uint nbytes, void *pkt, ++ bcmsdh_cmplt_fn_t complete_fn, void *handle) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ SDIOH_API_RC status; ++ uint incr_fix; ++ uint width; ++ int err = 0; ++ ++ ASSERT(bcmsdh); ++ ASSERT(bcmsdh->init_success); ++ ++ BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n", ++ __FUNCTION__, fn, addr, nbytes)); ++ ++ /* Async not implemented yet */ ++ ASSERT(!(flags & SDIO_REQ_ASYNC)); ++ if (flags & SDIO_REQ_ASYNC) ++ return BCME_UNSUPPORTED; ++ ++ if ((err = bcmsdhsdio_set_sbaddr_window(bcmsdh, addr, FALSE))) ++ return err; ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ ++ incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; ++ width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; ++ if (width == 4) ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ ++ status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix, ++ SDIOH_READ, fn, addr, width, nbytes, buf, pkt); ++ ++ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR); ++} ++ ++int ++bcmsdh_send_buf(void *sdh, uint32 addr, uint fn, uint flags, ++ uint8 *buf, uint nbytes, void *pkt, ++ bcmsdh_cmplt_fn_t complete_fn, void *handle) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ SDIOH_API_RC status; ++ uint incr_fix; ++ uint width; ++ int err = 0; ++ ++ ASSERT(bcmsdh); ++ ASSERT(bcmsdh->init_success); ++ ++ BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n", ++ __FUNCTION__, fn, addr, nbytes)); ++ ++ /* Async not implemented yet */ ++ ASSERT(!(flags & SDIO_REQ_ASYNC)); ++ if (flags & SDIO_REQ_ASYNC) ++ return BCME_UNSUPPORTED; ++ ++ if ((err = bcmsdhsdio_set_sbaddr_window(bcmsdh, addr, FALSE))) ++ return err; ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ ++ incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; ++ width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; ++ if (width == 4) ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ ++ status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix, ++ SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt); ++ ++ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); ++} ++ ++int ++bcmsdh_rwdata(void *sdh, uint rw, uint32 addr, uint8 *buf, uint nbytes) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ SDIOH_API_RC status; ++ ++ ASSERT(bcmsdh); ++ ASSERT(bcmsdh->init_success); ++ ASSERT((addr & SBSDIO_SBWINDOW_MASK) == 0); ++ ++ addr &= SBSDIO_SB_OFT_ADDR_MASK; ++ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; ++ ++ status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, SDIOH_DATA_INC, ++ (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1, ++ addr, 4, nbytes, buf, NULL); ++ ++ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); ++} ++ ++int ++bcmsdh_abort(void *sdh, uint fn) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ ++ return sdioh_abort(bcmsdh->sdioh, fn); ++} ++ ++int ++bcmsdh_start(void *sdh, int stage) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ ++ return sdioh_start(bcmsdh->sdioh, stage); ++} ++ ++int ++bcmsdh_stop(void *sdh) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ ++ return sdioh_stop(bcmsdh->sdioh); ++} ++ ++int ++bcmsdh_waitlockfree(void *sdh) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ if (!bcmsdh) ++ bcmsdh = l_bcmsdh; ++ ++ return sdioh_waitlockfree(bcmsdh->sdioh); ++} ++ ++ ++int ++bcmsdh_query_device(void *sdh) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ bcmsdh->vendevid = (VENDOR_BROADCOM << 16) | 0; ++ return (bcmsdh->vendevid); ++} ++ ++uint ++bcmsdh_query_iofnum(void *sdh) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ ++ if (!bcmsdh) ++ bcmsdh = l_bcmsdh; ++ ++ return (sdioh_query_iofnum(bcmsdh->sdioh)); ++} ++ ++int ++bcmsdh_reset(bcmsdh_info_t *sdh) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ ++ return sdioh_sdio_reset(bcmsdh->sdioh); ++} ++ ++void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh) ++{ ++ ASSERT(sdh); ++ return sdh->sdioh; ++} ++ ++/* Function to pass device-status bits to DHD. */ ++uint32 ++bcmsdh_get_dstatus(void *sdh) ++{ ++ return 0; ++} ++uint32 ++bcmsdh_cur_sbwad(void *sdh) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ ++ if (!bcmsdh) ++ bcmsdh = l_bcmsdh; ++ ++ return (bcmsdh->sbwad); ++} ++ ++void ++bcmsdh_chipinfo(void *sdh, uint32 chip, uint32 chiprev) ++{ ++ return; ++} ++ ++ ++int ++bcmsdh_sleep(void *sdh, bool enab) ++{ ++#ifdef SDIOH_SLEEP_ENABLED ++ bcmsdh_info_t *p = (bcmsdh_info_t *)sdh; ++ sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh); ++ ++ return sdioh_sleep(sd, enab); ++#else ++ return BCME_UNSUPPORTED; ++#endif ++} ++ ++int ++bcmsdh_gpio_init(void *sdh) ++{ ++ bcmsdh_info_t *p = (bcmsdh_info_t *)sdh; ++ sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh); ++ ++ return sdioh_gpio_init(sd); ++} ++ ++bool ++bcmsdh_gpioin(void *sdh, uint32 gpio) ++{ ++ bcmsdh_info_t *p = (bcmsdh_info_t *)sdh; ++ sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh); ++ ++ return sdioh_gpioin(sd, gpio); ++} ++ ++int ++bcmsdh_gpioouten(void *sdh, uint32 gpio) ++{ ++ bcmsdh_info_t *p = (bcmsdh_info_t *)sdh; ++ sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh); ++ ++ return sdioh_gpioouten(sd, gpio); ++} ++ ++int ++bcmsdh_gpioout(void *sdh, uint32 gpio, bool enab) ++{ ++ bcmsdh_info_t *p = (bcmsdh_info_t *)sdh; ++ sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh); ++ ++ return sdioh_gpioout(sd, gpio, enab); ++} ++ ++#ifdef BCMSDIOH_TXGLOM ++void ++bcmsdh_glom_post(void *sdh, uint8 *frame, uint len) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ sdioh_glom_post(bcmsdh->sdioh, frame, len); ++} ++ ++void ++bcmsdh_glom_clear(void *sdh) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ sdioh_glom_clear(bcmsdh->sdioh); ++} ++ ++uint ++bcmsdh_set_mode(void *sdh, uint mode) ++{ ++ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; ++ return (sdioh_set_mode(bcmsdh->sdioh, mode)); ++} ++ ++bool ++bcmsdh_glom_enabled(void) ++{ ++ return (sdioh_glom_enabled()); ++} ++#endif /* BCMSDIOH_TXGLOM */ +diff --git a/drivers/net/wireless/ap6210/bcmsdh_linux.c b/drivers/net/wireless/ap6210/bcmsdh_linux.c +new file mode 100755 +index 0000000..71bb3d9 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/bcmsdh_linux.c +@@ -0,0 +1,796 @@ ++/* ++ * SDIO access interface for drivers - linux specific (pci only) ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmsdh_linux.c 373359 2012-12-07 06:36:37Z $ ++ */ ++ ++/** ++ * @file bcmsdh_linux.c ++ */ ++ ++#define __UNDEF_NO_VERSION__ ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(OOB_INTR_ONLY) ++#include ++extern void dhdsdio_isr(void * args); ++#include ++#include ++#include ++#include ++#include ++#endif ++ ++#include ++ ++/** ++ * SDIO Host Controller info ++ */ ++typedef struct bcmsdh_hc bcmsdh_hc_t; ++ ++struct bcmsdh_hc { ++ bcmsdh_hc_t *next; ++#ifdef BCMPLATFORM_BUS ++ struct device *dev; /* platform device handle */ ++#else ++ struct pci_dev *dev; /* pci device handle */ ++#endif /* BCMPLATFORM_BUS */ ++ osl_t *osh; ++ void *regs; /* SDIO Host Controller address */ ++ bcmsdh_info_t *sdh; /* SDIO Host Controller handle */ ++ void *ch; ++ unsigned int oob_irq; ++ unsigned long oob_flags; /* OOB Host specifiction as edge and etc */ ++ bool oob_irq_registered; ++ bool oob_irq_enable_flag; ++#if defined(OOB_INTR_ONLY) ++ spinlock_t irq_lock; ++#endif ++}; ++static bcmsdh_hc_t *sdhcinfo = NULL; ++ ++/* driver info, initialized when bcmsdh_register is called */ ++static bcmsdh_driver_t drvinfo = {NULL, NULL}; ++ ++/** ++ * Checks to see if vendor and device IDs match a supported SDIO Host Controller. ++ */ ++bool ++bcmsdh_chipmatch(uint16 vendor, uint16 device) ++{ ++ /* Add other vendors and devices as required */ ++ ++#ifdef BCMSDIOH_STD ++ /* Check for Arasan host controller */ ++ if (vendor == VENDOR_SI_IMAGE) { ++ return (TRUE); ++ } ++ /* Check for BRCM 27XX Standard host controller */ ++ if (device == BCM27XX_SDIOH_ID && vendor == VENDOR_BROADCOM) { ++ return (TRUE); ++ } ++ /* Check for BRCM Standard host controller */ ++ if (device == SDIOH_FPGA_ID && vendor == VENDOR_BROADCOM) { ++ return (TRUE); ++ } ++ /* Check for TI PCIxx21 Standard host controller */ ++ if (device == PCIXX21_SDIOH_ID && vendor == VENDOR_TI) { ++ return (TRUE); ++ } ++ if (device == PCIXX21_SDIOH0_ID && vendor == VENDOR_TI) { ++ return (TRUE); ++ } ++ /* Ricoh R5C822 Standard SDIO Host */ ++ if (device == R5C822_SDIOH_ID && vendor == VENDOR_RICOH) { ++ return (TRUE); ++ } ++ /* JMicron Standard SDIO Host */ ++ if (device == JMICRON_SDIOH_ID && vendor == VENDOR_JMICRON) { ++ return (TRUE); ++ } ++ ++#endif /* BCMSDIOH_STD */ ++#ifdef BCMSDIOH_SPI ++ /* This is the PciSpiHost. */ ++ if (device == SPIH_FPGA_ID && vendor == VENDOR_BROADCOM) { ++ AP6210_ERR("Found PCI SPI Host Controller\n"); ++ return (TRUE); ++ } ++ ++#endif /* BCMSDIOH_SPI */ ++ ++ return (FALSE); ++} ++ ++#if defined(BCMPLATFORM_BUS) ++#if defined(BCMLXSDMMC) ++/* forward declarations */ ++int bcmsdh_probe(struct device *dev); ++int bcmsdh_remove(struct device *dev); ++ ++EXPORT_SYMBOL(bcmsdh_probe); ++EXPORT_SYMBOL(bcmsdh_remove); ++ ++#else ++/* forward declarations */ ++static int __devinit bcmsdh_probe(struct device *dev); ++static int __devexit bcmsdh_remove(struct device *dev); ++#endif ++ ++#if !defined(BCMLXSDMMC) ++static ++#endif ++int bcmsdh_probe(struct device *dev) ++{ ++ osl_t *osh = NULL; ++ bcmsdh_hc_t *sdhc = NULL; ++ ulong regs = 0; ++ bcmsdh_info_t *sdh = NULL; ++#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS) ++ struct platform_device *pdev; ++ struct resource *r; ++#endif ++ int irq = 0; ++ uint32 vendevid; ++ unsigned long irq_flags = 0; ++ ++#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS) ++ pdev = to_platform_device(dev); ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ irq = platform_get_irq(pdev, 0); ++ if (!r || irq == NO_IRQ) ++ return -ENXIO; ++#endif ++ ++#if defined(OOB_INTR_ONLY) ++#ifdef HW_OOB ++ irq_flags = ++ IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE; ++#else ++ irq_flags = IRQF_TRIGGER_FALLING; ++#endif /* HW_OOB */ ++ ++ /* Get customer specific OOB IRQ parametres: IRQ number as IRQ type */ ++ irq = dhd_customer_oob_irq_map(&irq_flags); ++#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) ++ /* Do not disable this IRQ during suspend */ ++ irq_flags |= IRQF_NO_SUSPEND; ++#endif /* defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) */ ++ if (irq < 0) { ++ AP6210_ERR("%s: Host irq is not defined\n", __FUNCTION__); ++ return 1; ++ } ++#endif ++ /* allocate SDIO Host Controller state info */ ++ if (!(osh = osl_attach(dev, PCI_BUS, FALSE))) { ++ AP6210_ERR("%s: osl_attach failed\n", __FUNCTION__); ++ goto err; ++ } ++ if (!(sdhc = MALLOC(osh, sizeof(bcmsdh_hc_t)))) { ++ AP6210_ERR("%s: out of memory, allocated %d bytes\n", ++ __FUNCTION__, ++ MALLOCED(osh)); ++ goto err; ++ } ++ bzero(sdhc, sizeof(bcmsdh_hc_t)); ++ sdhc->osh = osh; ++ ++ sdhc->dev = (void *)dev; ++ ++#if defined(BCMLXSDMMC) ++ if (!(sdh = bcmsdh_attach(osh, (void *)0, ++ (void **)®s, irq))) { ++ AP6210_ERR("%s: bcmsdh_attach failed\n", __FUNCTION__); ++ goto err; ++ } ++#else ++ if (!(sdh = bcmsdh_attach(osh, (void *)r->start, ++ (void **)®s, irq))) { ++ AP6210_ERR("%s: bcmsdh_attach failed\n", __FUNCTION__); ++ goto err; ++ } ++#endif ++ sdhc->sdh = sdh; ++ sdhc->oob_irq = irq; ++ sdhc->oob_flags = irq_flags; ++ sdhc->oob_irq_registered = FALSE; /* to make sure.. */ ++ sdhc->oob_irq_enable_flag = FALSE; ++#if defined(OOB_INTR_ONLY) ++ spin_lock_init(&sdhc->irq_lock); ++#endif ++ ++ /* chain SDIO Host Controller info together */ ++ sdhc->next = sdhcinfo; ++ sdhcinfo = sdhc; ++ ++ /* Read the vendor/device ID from the CIS */ ++ vendevid = bcmsdh_query_device(sdh); ++ /* try to attach to the target device */ ++ if (!(sdhc->ch = drvinfo.attach((vendevid >> 16), ++ (vendevid & 0xFFFF), 0, 0, 0, 0, ++ (void *)regs, NULL, sdh))) { ++ AP6210_ERR("%s: device attach failed\n", __FUNCTION__); ++ goto err; ++ } ++ ++ return 0; ++ ++ /* error handling */ ++err: ++ if (sdhc) { ++ if (sdhc->sdh) ++ bcmsdh_detach(sdhc->osh, sdhc->sdh); ++ MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); ++ } ++ if (osh) ++ osl_detach(osh); ++ return -ENODEV; ++} ++ ++#if !defined(BCMLXSDMMC) ++static ++#endif ++int bcmsdh_remove(struct device *dev) ++{ ++ bcmsdh_hc_t *sdhc, *prev; ++ osl_t *osh; ++ ++ sdhc = sdhcinfo; ++ drvinfo.detach(sdhc->ch); ++ bcmsdh_detach(sdhc->osh, sdhc->sdh); ++ ++ /* find the SDIO Host Controller state for this pdev and take it out from the list */ ++ for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) { ++ if (sdhc->dev == (void *)dev) { ++ if (prev) ++ prev->next = sdhc->next; ++ else ++ sdhcinfo = NULL; ++ break; ++ } ++ prev = sdhc; ++ } ++ if (!sdhc) { ++ AP6210_ERR("%s: failed\n", __FUNCTION__); ++ return 0; ++ } ++ ++ /* release SDIO Host Controller info */ ++ osh = sdhc->osh; ++ MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); ++ osl_detach(osh); ++ ++#if !defined(BCMLXSDMMC) || defined(OOB_INTR_ONLY) ++ dev_set_drvdata(dev, NULL); ++#endif ++ ++ return 0; ++} ++ ++#else /* BCMPLATFORM_BUS */ ++ ++#if !defined(BCMLXSDMMC) ++/* forward declarations for PCI probe and remove functions. */ ++static int __devinit bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent); ++static void __devexit bcmsdh_pci_remove(struct pci_dev *pdev); ++ ++/** ++ * pci id table ++ */ ++static struct pci_device_id bcmsdh_pci_devid[] __devinitdata = { ++ { vendor: PCI_ANY_ID, ++ device: PCI_ANY_ID, ++ subvendor: PCI_ANY_ID, ++ subdevice: PCI_ANY_ID, ++ class: 0, ++ class_mask: 0, ++ driver_data: 0, ++ }, ++ { 0, } ++}; ++MODULE_DEVICE_TABLE(pci, bcmsdh_pci_devid); ++ ++/** ++ * SDIO Host Controller pci driver info ++ */ ++static struct pci_driver bcmsdh_pci_driver = { ++ node: {}, ++ name: "bcmsdh", ++ id_table: bcmsdh_pci_devid, ++ probe: bcmsdh_pci_probe, ++ remove: bcmsdh_pci_remove, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++ save_state: NULL, ++#endif ++ suspend: NULL, ++ resume: NULL, ++ }; ++ ++ ++extern uint sd_pci_slot; /* Force detection to a particular PCI */ ++ /* slot only . Allows for having multiple */ ++ /* WL devices at once in a PC */ ++ /* Only one instance of dhd will be */ ++ /* usable at a time */ ++ /* Upper word is bus number, */ ++ /* lower word is slot number */ ++ /* Default value of 0xffffffff turns this */ ++ /* off */ ++module_param(sd_pci_slot, uint, 0); ++ ++ ++/** ++ * Detect supported SDIO Host Controller and attach if found. ++ * ++ * Determine if the device described by pdev is a supported SDIO Host ++ * Controller. If so, attach to it and attach to the target device. ++ */ ++static int __devinit ++bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ++{ ++ osl_t *osh = NULL; ++ bcmsdh_hc_t *sdhc = NULL; ++ ulong regs; ++ bcmsdh_info_t *sdh = NULL; ++ int rc; ++ ++ if (sd_pci_slot != 0xFFFFffff) { ++ if (pdev->bus->number != (sd_pci_slot>>16) || ++ PCI_SLOT(pdev->devfn) != (sd_pci_slot&0xffff)) { ++ AP6210_DEBUG("%s: %s: bus %X, slot %X, vend %X, dev %X\n", ++ __FUNCTION__, ++ bcmsdh_chipmatch(pdev->vendor, pdev->device) ++ ?"Found compatible SDIOHC" ++ :"Probing unknown device", ++ pdev->bus->number, PCI_SLOT(pdev->devfn), pdev->vendor, ++ pdev->device); ++ return -ENODEV; ++ } ++ AP6210_DEBUG("%s: %s: bus %X, slot %X, vendor %X, device %X (good PCI location)\n", ++ __FUNCTION__, ++ bcmsdh_chipmatch(pdev->vendor, pdev->device) ++ ?"Using compatible SDIOHC" ++ :"WARNING, forced use of unkown device", ++ pdev->bus->number, PCI_SLOT(pdev->devfn), pdev->vendor, pdev->device); ++ } ++ ++ if ((pdev->vendor == VENDOR_TI) && ((pdev->device == PCIXX21_FLASHMEDIA_ID) || ++ (pdev->device == PCIXX21_FLASHMEDIA0_ID))) { ++ uint32 config_reg; ++ ++ AP6210_ERR("%s: Disabling TI FlashMedia Controller.\n", __FUNCTION__); ++ if (!(osh = osl_attach(pdev, PCI_BUS, FALSE))) { ++ AP6210_ERR("%s: osl_attach failed\n", __FUNCTION__); ++ goto err; ++ } ++ ++ config_reg = OSL_PCI_READ_CONFIG(osh, 0x4c, 4); ++ ++ /* ++ * Set MMC_SD_DIS bit in FlashMedia Controller. ++ * Disbling the SD/MMC Controller in the FlashMedia Controller ++ * allows the Standard SD Host Controller to take over control ++ * of the SD Slot. ++ */ ++ config_reg |= 0x02; ++ OSL_PCI_WRITE_CONFIG(osh, 0x4c, 4, config_reg); ++ osl_detach(osh); ++ } ++ /* match this pci device with what we support */ ++ /* we can't solely rely on this to believe it is our SDIO Host Controller! */ ++ if (!bcmsdh_chipmatch(pdev->vendor, pdev->device)) { ++ return -ENODEV; ++ } ++ ++ /* this is a pci device we might support */ ++ AP6210_ERR("%s: Found possible SDIO Host Controller: bus %d slot %d func %d irq %d\n", ++ __FUNCTION__, ++ pdev->bus->number, PCI_SLOT(pdev->devfn), ++ PCI_FUNC(pdev->devfn), pdev->irq); ++ ++ /* use bcmsdh_query_device() to get the vendor ID of the target device so ++ * it will eventually appear in the Broadcom string on the console ++ */ ++ ++ /* allocate SDIO Host Controller state info */ ++ if (!(osh = osl_attach(pdev, PCI_BUS, FALSE))) { ++ AP6210_ERR("%s: osl_attach failed\n", __FUNCTION__); ++ goto err; ++ } ++ if (!(sdhc = MALLOC(osh, sizeof(bcmsdh_hc_t)))) { ++ AP6210_ERR("%s: out of memory, allocated %d bytes\n", ++ __FUNCTION__, ++ MALLOCED(osh)); ++ goto err; ++ } ++ bzero(sdhc, sizeof(bcmsdh_hc_t)); ++ sdhc->osh = osh; ++ ++ sdhc->dev = pdev; ++ ++ /* map to address where host can access */ ++ pci_set_master(pdev); ++ rc = pci_enable_device(pdev); ++ if (rc) { ++ AP6210_ERR("%s: Cannot enable PCI device\n", __FUNCTION__); ++ goto err; ++ } ++ if (!(sdh = bcmsdh_attach(osh, (void *)(uintptr)pci_resource_start(pdev, 0), ++ (void **)®s, pdev->irq))) { ++ AP6210_ERR("%s: bcmsdh_attach failed\n", __FUNCTION__); ++ goto err; ++ } ++ ++ sdhc->sdh = sdh; ++ ++ /* try to attach to the target device */ ++ if (!(sdhc->ch = drvinfo.attach(VENDOR_BROADCOM, /* pdev->vendor, */ ++ bcmsdh_query_device(sdh) & 0xFFFF, 0, 0, 0, 0, ++ (void *)regs, NULL, sdh))) { ++ AP6210_ERR("%s: device attach failed\n", __FUNCTION__); ++ goto err; ++ } ++ ++ /* chain SDIO Host Controller info together */ ++ sdhc->next = sdhcinfo; ++ sdhcinfo = sdhc; ++ ++ return 0; ++ ++ /* error handling */ ++err: ++ if (sdhc) { ++ if (sdhc->sdh) ++ bcmsdh_detach(sdhc->osh, sdhc->sdh); ++ MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); ++ } ++ if (osh) ++ osl_detach(osh); ++ return -ENODEV; ++} ++ ++ ++/** ++ * Detach from target devices and SDIO Host Controller ++ */ ++static void __devexit ++bcmsdh_pci_remove(struct pci_dev *pdev) ++{ ++ bcmsdh_hc_t *sdhc, *prev; ++ osl_t *osh; ++ ++ /* find the SDIO Host Controller state for this pdev and take it out from the list */ ++ for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) { ++ if (sdhc->dev == pdev) { ++ if (prev) ++ prev->next = sdhc->next; ++ else ++ sdhcinfo = NULL; ++ break; ++ } ++ prev = sdhc; ++ } ++ if (!sdhc) ++ return; ++ ++ drvinfo.detach(sdhc->ch); ++ ++ bcmsdh_detach(sdhc->osh, sdhc->sdh); ++ ++ /* release SDIO Host Controller info */ ++ osh = sdhc->osh; ++ MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); ++ osl_detach(osh); ++} ++#endif /* BCMLXSDMMC */ ++#endif /* BCMPLATFORM_BUS */ ++ ++extern int sdio_function_init(void); ++ ++extern int sdio_func_reg_notify(void* semaphore); ++extern void sdio_func_unreg_notify(void); ++ ++#if defined(BCMLXSDMMC) ++int bcmsdh_reg_sdio_notify(void* semaphore) ++{ ++ return sdio_func_reg_notify(semaphore); ++} ++ ++void bcmsdh_unreg_sdio_notify(void) ++{ ++ sdio_func_unreg_notify(); ++} ++#endif /* defined(BCMLXSDMMC) */ ++ ++int ++bcmsdh_register(bcmsdh_driver_t *driver) ++{ ++ int error = 0; ++ ++ drvinfo = *driver; ++ ++#if defined(BCMPLATFORM_BUS) ++ AP6210_ERR("Linux Kernel SDIO/MMC Driver\n"); ++ error = sdio_function_init(); ++ return error; ++#endif /* defined(BCMPLATFORM_BUS) */ ++ ++#if !defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC) ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++ if (!(error = pci_module_init(&bcmsdh_pci_driver))) ++ return 0; ++#else ++ if (!(error = pci_register_driver(&bcmsdh_pci_driver))) ++ return 0; ++#endif ++ ++ AP6210_ERR("%s: pci_module_init failed 0x%x\n", __FUNCTION__, error); ++#endif /* BCMPLATFORM_BUS */ ++ ++ return error; ++} ++ ++extern void sdio_function_cleanup(void); ++ ++void ++bcmsdh_unregister(void) ++{ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++ if (bcmsdh_pci_driver.node.next) ++#endif ++ ++#if defined(BCMLXSDMMC) ++ sdio_function_cleanup(); ++#endif /* BCMLXSDMMC */ ++ ++#if !defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC) ++ pci_unregister_driver(&bcmsdh_pci_driver); ++#endif /* BCMPLATFORM_BUS */ ++} ++ ++int bcmsdh_set_drvdata(void * dhdp) ++{ ++ AP6210_DEBUG("%s Enter \n", __FUNCTION__); ++ ++ dev_set_drvdata(sdhcinfo->dev, dhdp); ++ ++ return 0; ++} ++ ++#if defined(OOB_INTR_ONLY) ++#define CONFIG_ARCH_SUN6I_AP6210 1 ++ ++void bcmsdh_oob_intr_set(bool enable) ++{ ++ static bool curstate = 1; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&sdhcinfo->irq_lock, flags); ++ if (curstate != enable) { ++ if(enable) { ++ enable_irq(sdhcinfo->oob_irq); ++ } ++ else { ++ disable_irq_nosync(sdhcinfo->oob_irq); ++ } ++ curstate = enable; ++ } ++ ++ spin_unlock_irqrestore(&sdhcinfo->irq_lock, flags); ++} ++ ++static irqreturn_t wlan_oob_irq(int irq, void *dev_id) ++{ ++ dhd_pub_t *dhdp; ++ ++ dhdp = (dhd_pub_t *)dev_get_drvdata(sdhcinfo->dev); ++ ++ bcmsdh_oob_intr_set(0); ++ ++ if (dhdp == NULL) { ++ AP6210_ERR("Out of band GPIO interrupt fired way too early\n"); ++ return IRQ_HANDLED; ++ } ++ ++ dhdsdio_isr((void *)dhdp->bus); ++ ++ return IRQ_HANDLED; ++} ++ ++extern int wl_host_wake_irqno; ++irqreturn_t bcmdhd_gpio_irq_handler(int irq, void *dev) ++{ ++ wlan_oob_irq(0, NULL); ++ return IRQ_HANDLED; ++} ++ ++int bcmsdh_register_oob_intr(void * dhdp) ++{ ++ int error = 0; ++ int ret; ++ AP6210_DEBUG("%s Enter \n", __FUNCTION__); ++ ++ /* IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE; */ ++ dev_set_drvdata(sdhcinfo->dev, dhdp); ++ ++ if (!sdhcinfo->oob_irq_registered) { ++ AP6210_DEBUG("%s IRQ=%d Type=%X \n", __FUNCTION__, ++ (int)sdhcinfo->oob_irq, (int)sdhcinfo->oob_flags); ++ ++ ret = request_irq(wl_host_wake_irqno, bcmdhd_gpio_irq_handler, IRQF_DISABLED| IRQF_SHARED| IRQF_TRIGGER_HIGH, "bcmdhd_gpio_irq", (void *)&wl_host_wake_irqno); ++ if (ret) { ++ AP6210_ERR("request irq%d failed\n", wl_host_wake_irqno); ++ return -1; ++ } ++ ++#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) || defined(CONFIG_ARCH_SUN6I_AP6210) ++ if (device_may_wakeup(sdhcinfo->dev)) { ++#endif ++ error = enable_irq_wake(sdhcinfo->oob_irq); ++#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) || defined(CONFIG_ARCH_SUN6I_AP6210) ++ } ++#endif ++ if (error) ++ AP6210_ERR("%s enable_irq_wake error=%d \n", __FUNCTION__, error); ++ sdhcinfo->oob_irq_registered = TRUE; ++ sdhcinfo->oob_irq_enable_flag = TRUE; ++ } ++ ++ return 0; ++} ++ ++void bcmsdh_set_irq(int flag) ++{ ++ if (sdhcinfo->oob_irq_registered && sdhcinfo->oob_irq_enable_flag != flag) { ++ AP6210_ERR("%s Flag = %d\n", __FUNCTION__, flag); ++ sdhcinfo->oob_irq_enable_flag = flag; ++ if (flag) { ++ enable_irq(sdhcinfo->oob_irq); ++ ++#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) || defined(CONFIG_ARCH_SUN6I_AP6210) ++ if (device_may_wakeup(sdhcinfo->dev)) ++#endif ++ enable_irq_wake(sdhcinfo->oob_irq); ++ } else { ++#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) || defined(CONFIG_ARCH_SUN6I_AP6210) ++ if (device_may_wakeup(sdhcinfo->dev)) ++#endif ++ disable_irq_wake(sdhcinfo->oob_irq); ++ ++ ++ disable_irq(sdhcinfo->oob_irq); ++ } ++ } ++} ++ ++void bcmsdh_unregister_oob_intr(void) ++{ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (sdhcinfo->oob_irq_registered == TRUE) { ++ ++ if(0 != wl_host_wake_irqno) { ++ AP6210_DEBUG("free_irq %d\n", wl_host_wake_irqno); ++ free_irq(wl_host_wake_irqno, &wl_host_wake_irqno); ++ } ++ ++ sdhcinfo->oob_irq_registered = FALSE; ++ } ++} ++#endif ++ ++#if defined(BCMLXSDMMC) ++void *bcmsdh_get_drvdata(void) ++{ ++ if (!sdhcinfo) ++ return NULL; ++ return dev_get_drvdata(sdhcinfo->dev); ++} ++#endif ++ ++/* Module parameters specific to each host-controller driver */ ++ ++extern uint sd_msglevel; /* Debug message level */ ++module_param(sd_msglevel, uint, 0); ++ ++extern uint sd_power; /* 0 = SD Power OFF, 1 = SD Power ON. */ ++module_param(sd_power, uint, 0); ++ ++extern uint sd_clock; /* SD Clock Control, 0 = SD Clock OFF, 1 = SD Clock ON */ ++module_param(sd_clock, uint, 0); ++ ++extern uint sd_divisor; /* Divisor (-1 means external clock) */ ++module_param(sd_divisor, uint, 0); ++ ++extern uint sd_sdmode; /* Default is SD4, 0=SPI, 1=SD1, 2=SD4 */ ++module_param(sd_sdmode, uint, 0); ++ ++extern uint sd_hiok; /* Ok to use hi-speed mode */ ++module_param(sd_hiok, uint, 0); ++ ++extern uint sd_f2_blocksize; ++module_param(sd_f2_blocksize, int, 0); ++ ++#ifdef BCMSDIOH_STD ++extern int sd_uhsimode; ++module_param(sd_uhsimode, int, 0); ++#endif ++ ++#ifdef BCMSDIOH_TXGLOM ++extern uint sd_txglom; ++module_param(sd_txglom, uint, 0); ++#endif ++ ++#ifdef BCMSDH_MODULE ++EXPORT_SYMBOL(bcmsdh_attach); ++EXPORT_SYMBOL(bcmsdh_detach); ++EXPORT_SYMBOL(bcmsdh_intr_query); ++EXPORT_SYMBOL(bcmsdh_intr_enable); ++EXPORT_SYMBOL(bcmsdh_intr_disable); ++EXPORT_SYMBOL(bcmsdh_intr_reg); ++EXPORT_SYMBOL(bcmsdh_intr_dereg); ++ ++#if defined(DHD_DEBUG) ++EXPORT_SYMBOL(bcmsdh_intr_pending); ++#endif ++ ++EXPORT_SYMBOL(bcmsdh_devremove_reg); ++EXPORT_SYMBOL(bcmsdh_cfg_read); ++EXPORT_SYMBOL(bcmsdh_cfg_write); ++EXPORT_SYMBOL(bcmsdh_cis_read); ++EXPORT_SYMBOL(bcmsdh_reg_read); ++EXPORT_SYMBOL(bcmsdh_reg_write); ++EXPORT_SYMBOL(bcmsdh_regfail); ++EXPORT_SYMBOL(bcmsdh_send_buf); ++EXPORT_SYMBOL(bcmsdh_recv_buf); ++ ++EXPORT_SYMBOL(bcmsdh_rwdata); ++EXPORT_SYMBOL(bcmsdh_abort); ++EXPORT_SYMBOL(bcmsdh_query_device); ++EXPORT_SYMBOL(bcmsdh_query_iofnum); ++EXPORT_SYMBOL(bcmsdh_iovar_op); ++EXPORT_SYMBOL(bcmsdh_register); ++EXPORT_SYMBOL(bcmsdh_unregister); ++EXPORT_SYMBOL(bcmsdh_chipmatch); ++EXPORT_SYMBOL(bcmsdh_reset); ++EXPORT_SYMBOL(bcmsdh_waitlockfree); ++ ++EXPORT_SYMBOL(bcmsdh_get_dstatus); ++EXPORT_SYMBOL(bcmsdh_cfg_read_word); ++EXPORT_SYMBOL(bcmsdh_cfg_write_word); ++EXPORT_SYMBOL(bcmsdh_cur_sbwad); ++EXPORT_SYMBOL(bcmsdh_chipinfo); ++ ++#endif /* BCMSDH_MODULE */ +diff --git a/drivers/net/wireless/ap6210/bcmsdh_sdmmc.c b/drivers/net/wireless/ap6210/bcmsdh_sdmmc.c +new file mode 100755 +index 0000000..5f0d300 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/bcmsdh_sdmmc.c +@@ -0,0 +1,1532 @@ ++/* ++ * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmsdh_sdmmc.c 362913 2012-10-15 11:26:11Z $ ++ */ ++#include ++ ++#include ++#include ++#include ++#include ++#include /* SDIO Device and Protocol Specs */ ++#include /* Standard SDIO Host Controller Specification */ ++#include /* bcmsdh to/from specific controller APIs */ ++#include /* ioctl/iovars */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) ++#include ++extern volatile bool dhd_mmc_suspend; ++#endif ++#include "bcmsdh_sdmmc.h" ++ ++#include ++ ++#ifndef BCMSDH_MODULE ++extern int sdio_function_init(void); ++extern void sdio_function_cleanup(void); ++#endif /* BCMSDH_MODULE */ ++ ++#if !defined(OOB_INTR_ONLY) ++static void IRQHandler(struct sdio_func *func); ++static void IRQHandlerF2(struct sdio_func *func); ++#endif /* !defined(OOB_INTR_ONLY) */ ++static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr); ++extern int sdio_reset_comm(struct mmc_card *card); ++extern int sw_mci_check_r1_ready(struct mmc_host* mmc, unsigned ms); ++ ++extern PBCMSDH_SDMMC_INSTANCE gInstance; ++ ++#define DEFAULT_SDIO_F2_BLKSIZE 512 ++#ifndef CUSTOM_SDIO_F2_BLKSIZE ++#define CUSTOM_SDIO_F2_BLKSIZE DEFAULT_SDIO_F2_BLKSIZE ++#endif ++ ++uint sd_sdmode = SDIOH_MODE_SD4; /* Use SD4 mode by default */ ++uint sd_f2_blocksize = CUSTOM_SDIO_F2_BLKSIZE; ++uint sd_divisor = 2; /* Default 48MHz/2 = 24MHz */ ++ ++uint sd_power = 1; /* Default to SD Slot powered ON */ ++uint sd_clock = 1; /* Default to SD Clock turned ON */ ++uint sd_hiok = FALSE; /* Don't use hi-speed mode by default */ ++uint sd_msglevel = 0x01; ++uint sd_use_dma = TRUE; ++DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait); ++DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait); ++DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait); ++DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait); ++ ++#define DMA_ALIGN_MASK 0x03 ++#define MMC_SDIO_ABORT_RETRY_LIMIT 5 ++ ++int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data); ++ ++static int ++sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd) ++{ ++ int err_ret; ++ uint32 fbraddr; ++ uint8 func; ++ ++ AP6210_DEBUG("%s\n", __FUNCTION__);; ++ ++ /* Get the Card's common CIS address */ ++ sd->com_cis_ptr = sdioh_sdmmc_get_cisaddr(sd, SDIOD_CCCR_CISPTR_0); ++ sd->func_cis_ptr[0] = sd->com_cis_ptr; ++ AP6210_DEBUG("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr); ++ ++ /* Get the Card's function CIS (for each function) */ ++ for (fbraddr = SDIOD_FBR_STARTADDR, func = 1; ++ func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { ++ sd->func_cis_ptr[func] = sdioh_sdmmc_get_cisaddr(sd, SDIOD_FBR_CISPTR_0 + fbraddr); ++ AP6210_DEBUG("%s: Function %d CIS Ptr = 0x%x\n", ++ __FUNCTION__, func, sd->func_cis_ptr[func]); ++ } ++ ++ sd->func_cis_ptr[0] = sd->com_cis_ptr; ++ AP6210_DEBUG("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr); ++ ++ /* Enable Function 1 */ ++ sdio_claim_host(gInstance->func[1]); ++ err_ret = sdio_enable_func(gInstance->func[1]); ++ sdio_release_host(gInstance->func[1]); ++ if (err_ret) { ++ AP6210_ERR("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x", err_ret); ++ } ++ ++ return FALSE; ++} ++ ++/* ++ * Public entry points & extern's ++ */ ++extern sdioh_info_t * ++sdioh_attach(osl_t *osh, void *bar0, uint irq) ++{ ++ sdioh_info_t *sd; ++ int err_ret; ++ ++ AP6210_DEBUG("%s\n", __FUNCTION__); ++ ++ if (gInstance == NULL) { ++ AP6210_ERR("%s: SDIO Device not present\n", __FUNCTION__); ++ return NULL; ++ } ++ ++ if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) { ++ AP6210_ERR("sdioh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh)); ++ return NULL; ++ } ++ bzero((char *)sd, sizeof(sdioh_info_t)); ++ sd->osh = osh; ++ if (sdioh_sdmmc_osinit(sd) != 0) { ++ AP6210_ERR("%s:sdioh_sdmmc_osinit() failed\n", __FUNCTION__); ++ MFREE(sd->osh, sd, sizeof(sdioh_info_t)); ++ return NULL; ++ } ++ ++ sd->num_funcs = 2; ++ sd->sd_blockmode = TRUE; ++ sd->use_client_ints = TRUE; ++ sd->client_block_size[0] = 64; ++ sd->use_rxchain = FALSE; ++ ++ gInstance->sd = sd; ++ ++ /* Claim host controller */ ++ if (gInstance->func[1]) { ++ sdio_claim_host(gInstance->func[1]); ++ ++ sd->client_block_size[1] = 64; ++ err_ret = sdio_set_block_size(gInstance->func[1], 64); ++ if (err_ret) { ++ AP6210_ERR("bcmsdh_sdmmc: Failed to set F1 blocksize\n"); ++ } ++ ++ /* Release host controller F1 */ ++ sdio_release_host(gInstance->func[1]); ++ } else { ++ AP6210_ERR("%s:gInstance->func[1] is null\n", __FUNCTION__); ++ MFREE(sd->osh, sd, sizeof(sdioh_info_t)); ++ return NULL; ++ } ++ ++ if (gInstance->func[2]) { ++ /* Claim host controller F2 */ ++ sdio_claim_host(gInstance->func[2]); ++ ++ sd->client_block_size[2] = sd_f2_blocksize; ++ err_ret = sdio_set_block_size(gInstance->func[2], sd_f2_blocksize); ++ if (err_ret) { ++ AP6210_ERR("bcmsdh_sdmmc: Failed to set F2 blocksize to %d\n", ++ sd_f2_blocksize); ++ } ++ ++ /* Release host controller F2 */ ++ sdio_release_host(gInstance->func[2]); ++ } else { ++ AP6210_ERR("%s:gInstance->func[2] is null\n", __FUNCTION__); ++ MFREE(sd->osh, sd, sizeof(sdioh_info_t)); ++ return NULL; ++ } ++ ++ sdioh_sdmmc_card_enablefuncs(sd); ++ ++ AP6210_DEBUG("%s: Done\n", __FUNCTION__); ++ return sd; ++} ++ ++ ++extern SDIOH_API_RC ++sdioh_detach(osl_t *osh, sdioh_info_t *sd) ++{ ++ AP6210_DEBUG("%s\n", __FUNCTION__); ++ ++ if (sd) { ++ ++ /* Disable Function 2 */ ++ sdio_claim_host(gInstance->func[2]); ++ sdio_disable_func(gInstance->func[2]); ++ sdio_release_host(gInstance->func[2]); ++ ++ /* Disable Function 1 */ ++ if (gInstance->func[1]) { ++ sdio_claim_host(gInstance->func[1]); ++ sdio_disable_func(gInstance->func[1]); ++ sdio_release_host(gInstance->func[1]); ++ } ++ ++ gInstance->func[1] = NULL; ++ gInstance->func[2] = NULL; ++ ++ /* deregister irq */ ++ sdioh_sdmmc_osfree(sd); ++ ++ MFREE(sd->osh, sd, sizeof(sdioh_info_t)); ++ } ++ return SDIOH_API_RC_SUCCESS; ++} ++ ++#if defined(OOB_INTR_ONLY) && defined(HW_OOB) ++ ++extern SDIOH_API_RC ++sdioh_enable_func_intr(void) ++{ ++ uint8 reg; ++ int err; ++ ++ if (gInstance->func[0]) { ++ sdio_claim_host(gInstance->func[0]); ++ ++ reg = sdio_readb(gInstance->func[0], SDIOD_CCCR_INTEN, &err); ++ if (err) { ++ AP6210_ERR("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err); ++ sdio_release_host(gInstance->func[0]); ++ return SDIOH_API_RC_FAIL; ++ } ++ ++ /* Enable F1 and F2 interrupts, set master enable */ ++ reg |= (INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN | INTR_CTL_MASTER_EN); ++ ++ sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &err); ++ sdio_release_host(gInstance->func[0]); ++ ++ if (err) { ++ AP6210_ERR("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err); ++ return SDIOH_API_RC_FAIL; ++ } ++ } ++ ++ return SDIOH_API_RC_SUCCESS; ++} ++ ++extern SDIOH_API_RC ++sdioh_disable_func_intr(void) ++{ ++ uint8 reg; ++ int err; ++ ++ if (gInstance->func[0]) { ++ sdio_claim_host(gInstance->func[0]); ++ reg = sdio_readb(gInstance->func[0], SDIOD_CCCR_INTEN, &err); ++ if (err) { ++ AP6210_ERR("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err); ++ sdio_release_host(gInstance->func[0]); ++ return SDIOH_API_RC_FAIL; ++ } ++ ++ reg &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN); ++ /* Disable master interrupt with the last function interrupt */ ++ if (!(reg & 0xFE)) ++ reg = 0; ++ sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &err); ++ ++ sdio_release_host(gInstance->func[0]); ++ if (err) { ++ AP6210_ERR("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err); ++ return SDIOH_API_RC_FAIL; ++ } ++ } ++ return SDIOH_API_RC_SUCCESS; ++} ++#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */ ++ ++/* Configure callback to client when we recieve client interrupt */ ++extern SDIOH_API_RC ++sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh) ++{ ++ AP6210_DEBUG("%s: Entering\n", __FUNCTION__); ++ if (fn == NULL) { ++ AP6210_ERR("%s: interrupt handler is NULL, not registering\n", __FUNCTION__); ++ return SDIOH_API_RC_FAIL; ++ } ++#if !defined(OOB_INTR_ONLY) ++ sd->intr_handler = fn; ++ sd->intr_handler_arg = argh; ++ sd->intr_handler_valid = TRUE; ++ ++ /* register and unmask irq */ ++ if (gInstance->func[2]) { ++ sdio_claim_host(gInstance->func[2]); ++ sdio_claim_irq(gInstance->func[2], IRQHandlerF2); ++ sdio_release_host(gInstance->func[2]); ++ } ++ ++ if (gInstance->func[1]) { ++ sdio_claim_host(gInstance->func[1]); ++ sdio_claim_irq(gInstance->func[1], IRQHandler); ++ sdio_release_host(gInstance->func[1]); ++ } ++#elif defined(HW_OOB) ++ sdioh_enable_func_intr(); ++#endif /* !defined(OOB_INTR_ONLY) */ ++ ++ return SDIOH_API_RC_SUCCESS; ++} ++ ++extern SDIOH_API_RC ++sdioh_interrupt_deregister(sdioh_info_t *sd) ++{ ++ AP6210_DEBUG("%s: Entering\n", __FUNCTION__); ++ ++#if !defined(OOB_INTR_ONLY) ++ if (gInstance->func[1]) { ++ /* register and unmask irq */ ++ sdio_claim_host(gInstance->func[1]); ++ sdio_release_irq(gInstance->func[1]); ++ sdio_release_host(gInstance->func[1]); ++ } ++ ++ if (gInstance->func[2]) { ++ /* Claim host controller F2 */ ++ sdio_claim_host(gInstance->func[2]); ++ sdio_release_irq(gInstance->func[2]); ++ /* Release host controller F2 */ ++ sdio_release_host(gInstance->func[2]); ++ } ++ ++ sd->intr_handler_valid = FALSE; ++ sd->intr_handler = NULL; ++ sd->intr_handler_arg = NULL; ++#elif defined(HW_OOB) ++ sdioh_disable_func_intr(); ++#endif /* !defined(OOB_INTR_ONLY) */ ++ return SDIOH_API_RC_SUCCESS; ++} ++ ++extern SDIOH_API_RC ++sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff) ++{ ++ AP6210_DEBUG("%s: Entering\n", __FUNCTION__); ++ *onoff = sd->client_intr_enabled; ++ return SDIOH_API_RC_SUCCESS; ++} ++ ++#if defined(DHD_DEBUG) ++extern bool ++sdioh_interrupt_pending(sdioh_info_t *sd) ++{ ++ return (0); ++} ++#endif ++ ++uint ++sdioh_query_iofnum(sdioh_info_t *sd) ++{ ++ return sd->num_funcs; ++} ++ ++/* IOVar table */ ++enum { ++ IOV_MSGLEVEL = 1, ++ IOV_BLOCKMODE, ++ IOV_BLOCKSIZE, ++ IOV_DMA, ++ IOV_USEINTS, ++ IOV_NUMINTS, ++ IOV_NUMLOCALINTS, ++ IOV_HOSTREG, ++ IOV_DEVREG, ++ IOV_DIVISOR, ++ IOV_SDMODE, ++ IOV_HISPEED, ++ IOV_HCIREGS, ++ IOV_POWER, ++ IOV_CLOCK, ++ IOV_RXCHAIN ++}; ++ ++const bcm_iovar_t sdioh_iovars[] = { ++ {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 }, ++ {"sd_blockmode", IOV_BLOCKMODE, 0, IOVT_BOOL, 0 }, ++ {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0 }, /* ((fn << 16) | size) */ ++ {"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0 }, ++ {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0 }, ++ {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0 }, ++ {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0 }, ++ {"sd_hostreg", IOV_HOSTREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, ++ {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, ++ {"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0 }, ++ {"sd_power", IOV_POWER, 0, IOVT_UINT32, 0 }, ++ {"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0 }, ++ {"sd_mode", IOV_SDMODE, 0, IOVT_UINT32, 100}, ++ {"sd_highspeed", IOV_HISPEED, 0, IOVT_UINT32, 0 }, ++ {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0 }, ++ {NULL, 0, 0, 0, 0 } ++}; ++ ++int ++sdioh_iovar_op(sdioh_info_t *si, const char *name, ++ void *params, int plen, void *arg, int len, bool set) ++{ ++ const bcm_iovar_t *vi = NULL; ++ int bcmerror = 0; ++ int val_size; ++ int32 int_val = 0; ++ bool bool_val; ++ uint32 actionid; ++ ++ ASSERT(name); ++ ASSERT(len >= 0); ++ ++ /* Get must have return space; Set does not take qualifiers */ ++ ASSERT(set || (arg && len)); ++ ASSERT(!set || (!params && !plen)); ++ ++ AP6210_DEBUG("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name); ++ ++ if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) { ++ bcmerror = BCME_UNSUPPORTED; ++ goto exit; ++ } ++ ++ if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0) ++ goto exit; ++ ++ /* Set up params so get and set can share the convenience variables */ ++ if (params == NULL) { ++ params = arg; ++ plen = len; ++ } ++ ++ if (vi->type == IOVT_VOID) ++ val_size = 0; ++ else if (vi->type == IOVT_BUFFER) ++ val_size = len; ++ else ++ val_size = sizeof(int); ++ ++ if (plen >= (int)sizeof(int_val)) ++ bcopy(params, &int_val, sizeof(int_val)); ++ ++ bool_val = (int_val != 0) ? TRUE : FALSE; ++ BCM_REFERENCE(bool_val); ++ ++ actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); ++ switch (actionid) { ++ case IOV_GVAL(IOV_MSGLEVEL): ++ int_val = (int32)sd_msglevel; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_MSGLEVEL): ++ sd_msglevel = int_val; ++ break; ++ ++ case IOV_GVAL(IOV_BLOCKMODE): ++ int_val = (int32)si->sd_blockmode; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_BLOCKMODE): ++ si->sd_blockmode = (bool)int_val; ++ /* Haven't figured out how to make non-block mode with DMA */ ++ break; ++ ++ case IOV_GVAL(IOV_BLOCKSIZE): ++ if ((uint32)int_val > si->num_funcs) { ++ bcmerror = BCME_BADARG; ++ break; ++ } ++ int_val = (int32)si->client_block_size[int_val]; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_BLOCKSIZE): ++ { ++ uint func = ((uint32)int_val >> 16); ++ uint blksize = (uint16)int_val; ++ uint maxsize; ++ ++ if (func > si->num_funcs) { ++ bcmerror = BCME_BADARG; ++ break; ++ } ++ ++ switch (func) { ++ case 0: maxsize = 32; break; ++ case 1: maxsize = BLOCK_SIZE_4318; break; ++ case 2: maxsize = BLOCK_SIZE_4328; break; ++ default: maxsize = 0; ++ } ++ if (blksize > maxsize) { ++ bcmerror = BCME_BADARG; ++ break; ++ } ++ if (!blksize) { ++ blksize = maxsize; ++ } ++ ++ /* Now set it */ ++ si->client_block_size[func] = blksize; ++ ++ break; ++ } ++ ++ case IOV_GVAL(IOV_RXCHAIN): ++ int_val = (int32)si->use_rxchain; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_GVAL(IOV_DMA): ++ int_val = (int32)si->sd_use_dma; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_DMA): ++ si->sd_use_dma = (bool)int_val; ++ break; ++ ++ case IOV_GVAL(IOV_USEINTS): ++ int_val = (int32)si->use_client_ints; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_USEINTS): ++ si->use_client_ints = (bool)int_val; ++ if (si->use_client_ints) ++ si->intmask |= CLIENT_INTR; ++ else ++ si->intmask &= ~CLIENT_INTR; ++ ++ break; ++ ++ case IOV_GVAL(IOV_DIVISOR): ++ int_val = (uint32)sd_divisor; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_DIVISOR): ++ sd_divisor = int_val; ++ break; ++ ++ case IOV_GVAL(IOV_POWER): ++ int_val = (uint32)sd_power; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_POWER): ++ sd_power = int_val; ++ break; ++ ++ case IOV_GVAL(IOV_CLOCK): ++ int_val = (uint32)sd_clock; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_CLOCK): ++ sd_clock = int_val; ++ break; ++ ++ case IOV_GVAL(IOV_SDMODE): ++ int_val = (uint32)sd_sdmode; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_SDMODE): ++ sd_sdmode = int_val; ++ break; ++ ++ case IOV_GVAL(IOV_HISPEED): ++ int_val = (uint32)sd_hiok; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_HISPEED): ++ sd_hiok = int_val; ++ break; ++ ++ case IOV_GVAL(IOV_NUMINTS): ++ int_val = (int32)si->intrcount; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_GVAL(IOV_NUMLOCALINTS): ++ int_val = (int32)0; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_GVAL(IOV_HOSTREG): ++ { ++ sdreg_t *sd_ptr = (sdreg_t *)params; ++ ++ if (sd_ptr->offset < SD_SysAddr || sd_ptr->offset > SD_MaxCurCap) { ++ AP6210_ERR("%s: bad offset 0x%x\n", __FUNCTION__, sd_ptr->offset); ++ bcmerror = BCME_BADARG; ++ break; ++ } ++ ++ AP6210_DEBUG("%s: rreg%d at offset %d\n", __FUNCTION__, ++ (sd_ptr->offset & 1) ? 8 : ((sd_ptr->offset & 2) ? 16 : 32), ++ sd_ptr->offset); ++ if (sd_ptr->offset & 1) ++ int_val = 8; /* sdioh_sdmmc_rreg8(si, sd_ptr->offset); */ ++ else if (sd_ptr->offset & 2) ++ int_val = 16; /* sdioh_sdmmc_rreg16(si, sd_ptr->offset); */ ++ else ++ int_val = 32; /* sdioh_sdmmc_rreg(si, sd_ptr->offset); */ ++ ++ bcopy(&int_val, arg, sizeof(int_val)); ++ break; ++ } ++ ++ case IOV_SVAL(IOV_HOSTREG): ++ { ++ sdreg_t *sd_ptr = (sdreg_t *)params; ++ ++ if (sd_ptr->offset < SD_SysAddr || sd_ptr->offset > SD_MaxCurCap) { ++ AP6210_ERR("%s: bad offset 0x%x\n", __FUNCTION__, sd_ptr->offset); ++ bcmerror = BCME_BADARG; ++ break; ++ } ++ ++ AP6210_DEBUG("%s: wreg%d value 0x%08x at offset %d\n", __FUNCTION__, sd_ptr->value, ++ (sd_ptr->offset & 1) ? 8 : ((sd_ptr->offset & 2) ? 16 : 32), ++ sd_ptr->offset); ++ break; ++ } ++ ++ case IOV_GVAL(IOV_DEVREG): ++ { ++ sdreg_t *sd_ptr = (sdreg_t *)params; ++ uint8 data = 0; ++ ++ if (sdioh_cfg_read(si, sd_ptr->func, sd_ptr->offset, &data)) { ++ bcmerror = BCME_SDIO_ERROR; ++ break; ++ } ++ ++ int_val = (int)data; ++ bcopy(&int_val, arg, sizeof(int_val)); ++ break; ++ } ++ ++ case IOV_SVAL(IOV_DEVREG): ++ { ++ sdreg_t *sd_ptr = (sdreg_t *)params; ++ uint8 data = (uint8)sd_ptr->value; ++ ++ if (sdioh_cfg_write(si, sd_ptr->func, sd_ptr->offset, &data)) { ++ bcmerror = BCME_SDIO_ERROR; ++ break; ++ } ++ break; ++ } ++ ++ default: ++ bcmerror = BCME_UNSUPPORTED; ++ break; ++ } ++exit: ++ ++ return bcmerror; ++} ++ ++#if defined(OOB_INTR_ONLY) && defined(HW_OOB) ++ ++SDIOH_API_RC ++sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable) ++{ ++ SDIOH_API_RC status; ++ uint8 data; ++ ++ if (enable) ++ data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE | SDIO_SEPINT_ACT_HI; ++ else ++ data = SDIO_SEPINT_ACT_HI; /* disable hw oob interrupt */ ++ ++ status = sdioh_request_byte(sd, SDIOH_WRITE, 0, SDIOD_CCCR_BRCM_SEPINT, &data); ++ return status; ++} ++#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */ ++ ++extern SDIOH_API_RC ++sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data) ++{ ++ SDIOH_API_RC status; ++ /* No lock needed since sdioh_request_byte does locking */ ++ status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data); ++ return status; ++} ++ ++extern SDIOH_API_RC ++sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data) ++{ ++ /* No lock needed since sdioh_request_byte does locking */ ++ SDIOH_API_RC status; ++ status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data); ++ return status; ++} ++ ++static int ++sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr) ++{ ++ /* read 24 bits and return valid 17 bit addr */ ++ int i; ++ uint32 scratch, regdata; ++ uint8 *ptr = (uint8 *)&scratch; ++ for (i = 0; i < 3; i++) { ++ if ((sdioh_sdmmc_card_regread (sd, 0, regaddr, 1, ®data)) != SUCCESS) ++ AP6210_ERR("%s: Can't read!\n", __FUNCTION__); ++ ++ *ptr++ = (uint8) regdata; ++ regaddr++; ++ } ++ ++ /* Only the lower 17-bits are valid */ ++ scratch = ltoh32(scratch); ++ scratch &= 0x0001FFFF; ++ return (scratch); ++} ++ ++extern SDIOH_API_RC ++sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length) ++{ ++ uint32 count; ++ int offset; ++ uint32 foo; ++ uint8 *cis = cisd; ++ ++ AP6210_DEBUG("%s: Func = %d\n", __FUNCTION__, func); ++ ++ if (!sd->func_cis_ptr[func]) { ++ bzero(cis, length); ++ AP6210_ERR("%s: no func_cis_ptr[%d]\n", __FUNCTION__, func); ++ return SDIOH_API_RC_FAIL; ++ } ++ ++ AP6210_ERR("%s: func_cis_ptr[%d]=0x%04x\n", __FUNCTION__, func, sd->func_cis_ptr[func]); ++ ++ for (count = 0; count < length; count++) { ++ offset = sd->func_cis_ptr[func] + count; ++ if (sdioh_sdmmc_card_regread (sd, 0, offset, 1, &foo) < 0) { ++ AP6210_ERR("%s: regread failed: Can't read CIS\n", __FUNCTION__); ++ return SDIOH_API_RC_FAIL; ++ } ++ ++ *cis = (uint8)(foo & 0xff); ++ cis++; ++ } ++ ++ return SDIOH_API_RC_SUCCESS; ++} ++ ++extern SDIOH_API_RC ++sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte) ++{ ++ int err_ret; ++#if defined(MMC_SDIO_ABORT) ++ int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT; ++#endif ++ int ret = 0; ++ ++ AP6210_DEBUG("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr); ++ ++ DHD_PM_RESUME_WAIT(sdioh_request_byte_wait); ++ DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); ++ if(rw) { /* CMD52 Write */ ++ if (func == 0) { ++ /* Can only directly write to some F0 registers. Handle F2 enable ++ * as a special case. ++ */ ++ if (regaddr == SDIOD_CCCR_IOEN) { ++ if (gInstance->func[2]) { ++ sdio_claim_host(gInstance->func[2]); ++ if (*byte & SDIO_FUNC_ENABLE_2) { ++ /* Enable Function 2 */ ++ err_ret = sdio_enable_func(gInstance->func[2]); ++ if (err_ret) { ++ AP6210_ERR("bcmsdh_sdmmc: enable F2 failed:%d", ++ err_ret); ++ } ++ } else { ++ /* Disable Function 2 */ ++ err_ret = sdio_disable_func(gInstance->func[2]); ++ if (err_ret) { ++ AP6210_ERR("bcmsdh_sdmmc: Disab F2 failed:%d", ++ err_ret); ++ } ++ } ++ sdio_release_host(gInstance->func[2]); ++ } ++ } ++#if defined(MMC_SDIO_ABORT) ++ /* to allow abort command through F1 */ ++ else if (regaddr == SDIOD_CCCR_IOABORT) { ++ /* Because of SDIO3.0 host issue on Manta, ++ * sometimes the abort fails. ++ * Retrying again will fix this issue. ++ */ ++ while (sdio_abort_retry--) { ++ if (gInstance->func[func]) { ++ sdio_claim_host(gInstance->func[func]); ++ /* ++ * this sdio_f0_writeb() can be replaced with ++ * another api depending upon MMC driver change. ++ * As of this time, this is temporaray one ++ */ ++ sdio_writeb(gInstance->func[func], ++ *byte, regaddr, &err_ret); ++ sdio_release_host(gInstance->func[func]); ++ } ++ if (!err_ret) ++ break; ++ } ++ } ++#endif /* MMC_SDIO_ABORT */ ++ else if (regaddr < 0xF0) { ++ AP6210_ERR("bcmsdh_sdmmc: F0 Wr:0x%02x: write disallowed\n", regaddr); ++ } else { ++ /* Claim host controller, perform F0 write, and release */ ++ if (gInstance->func[func]) { ++ sdio_claim_host(gInstance->func[func]); ++ sdio_f0_writeb(gInstance->func[func], ++ *byte, regaddr, &err_ret); ++ sdio_release_host(gInstance->func[func]); ++ } ++ } ++ } else { ++ /* Claim host controller, perform Fn write, and release */ ++ if (gInstance->func[func]) { ++ sdio_claim_host(gInstance->func[func]); ++ sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret); ++ sdio_release_host(gInstance->func[func]); ++ } ++ } ++ } else { /* CMD52 Read */ ++ /* Claim host controller, perform Fn read, and release */ ++ if (gInstance->func[func]) { ++ sdio_claim_host(gInstance->func[func]); ++ if (func == 0) { ++ *byte = sdio_f0_readb(gInstance->func[func], regaddr, &err_ret); ++ } else { ++ *byte = sdio_readb(gInstance->func[func], regaddr, &err_ret); ++ } ++ sdio_release_host(gInstance->func[func]); ++ } ++ } ++ ++ //AW judge sdio read write timeout, 1s ++ ret = sw_mci_check_r1_ready(gInstance->func[func]->card->host, 1000); ++ if (ret != 0) ++ AP6210_DEBUG("%s data timeout.\n", __FUNCTION__); ++ ++ if (err_ret) { ++ AP6210_ERR("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", ++ rw ? "Write" : "Read", func, regaddr, *byte, err_ret); ++ } ++ ++ return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); ++} ++ ++extern SDIOH_API_RC ++sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr, ++ uint32 *word, uint nbytes) ++{ ++ int err_ret = SDIOH_API_RC_FAIL; ++#if defined(MMC_SDIO_ABORT) ++ int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT; ++#endif ++ int ret = 0; ++ ++ if (func == 0) { ++ AP6210_ERR("%s: Only CMD52 allowed to F0.\n", __FUNCTION__); ++ return SDIOH_API_RC_FAIL; ++ } ++ ++ AP6210_DEBUG("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", ++ __FUNCTION__, cmd_type, rw, func, addr, nbytes); ++ ++ DHD_PM_RESUME_WAIT(sdioh_request_word_wait); ++ DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); ++ /* Claim host controller */ ++ sdio_claim_host(gInstance->func[func]); ++ ++ if(rw) { /* CMD53 Write */ ++ if (nbytes == 4) { ++ sdio_writel(gInstance->func[func], *word, addr, &err_ret); ++ } else if (nbytes == 2) { ++ sdio_writew(gInstance->func[func], (*word & 0xFFFF), addr, &err_ret); ++ } else { ++ AP6210_ERR("%s: Invalid nbytes: %d\n", __FUNCTION__, nbytes); ++ } ++ } else { /* CMD52 Read */ ++ if (nbytes == 4) { ++ *word = sdio_readl(gInstance->func[func], addr, &err_ret); ++ } else if (nbytes == 2) { ++ *word = sdio_readw(gInstance->func[func], addr, &err_ret) & 0xFFFF; ++ } else { ++ AP6210_ERR("%s: Invalid nbytes: %d\n", __FUNCTION__, nbytes); ++ } ++ } ++ ++ //AW judge sdio read write timeout, 1s ++ ret = sw_mci_check_r1_ready(gInstance->func[func]->card->host, 1000); ++ if (ret != 0) ++ AP6210_DEBUG("%s data timeout.\n", __FUNCTION__); ++ ++ /* Release host controller */ ++ sdio_release_host(gInstance->func[func]); ++ ++ if (err_ret) { ++#if defined(MMC_SDIO_ABORT) ++ /* Any error on CMD53 transaction should abort that function using function 0. */ ++ while (sdio_abort_retry--) { ++ if (gInstance->func[0]) { ++ sdio_claim_host(gInstance->func[0]); ++ /* ++ * this sdio_f0_writeb() can be replaced with another api ++ * depending upon MMC driver change. ++ * As of this time, this is temporaray one ++ */ ++ sdio_writeb(gInstance->func[0], ++ func, SDIOD_CCCR_IOABORT, &err_ret); ++ sdio_release_host(gInstance->func[0]); ++ } ++ if (!err_ret) ++ break; ++ } ++ if (err_ret) ++#endif /* MMC_SDIO_ABORT */ ++ { ++ AP6210_ERR("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x\n", ++ rw ? "Write" : "Read", err_ret); ++ } ++ } ++ ++ return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); ++} ++ ++static SDIOH_API_RC ++sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, ++ uint addr, void *pkt) ++{ ++ bool fifo = (fix_inc == SDIOH_DATA_FIX); ++ uint32 SGCount = 0; ++ int err_ret = 0; ++ void *pnext, *pprev; ++ uint ttl_len, dma_len, lft_len, xfred_len, pkt_len; ++ uint blk_num; ++ int blk_size; ++ struct mmc_request mmc_req; ++ struct mmc_command mmc_cmd; ++ struct mmc_data mmc_dat; ++ int ret = 0; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ ASSERT(pkt); ++ DHD_PM_RESUME_WAIT(sdioh_request_packet_wait); ++ DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); ++ ++ ttl_len = xfred_len = 0; ++ /* at least 4 bytes alignment of skb buff is guaranteed */ ++ for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) ++ ttl_len += PKTLEN(sd->osh, pnext); ++ ++ blk_size = sd->client_block_size[func]; ++ if (!sd->use_rxchain || ttl_len <= blk_size) { ++ blk_num = 0; ++ dma_len = 0; ++ } else { ++ blk_num = ttl_len / blk_size; ++ dma_len = blk_num * blk_size; ++ } ++ lft_len = ttl_len - dma_len; ++ ++ AP6210_DEBUG("%s: %s %dB to func%d:%08x, %d blks with DMA, %dB leftover\n", ++ __FUNCTION__, write ? "W" : "R", ++ ttl_len, func, addr, blk_num, lft_len); ++ ++ if (0 != dma_len) { ++ memset(&mmc_req, 0, sizeof(struct mmc_request)); ++ memset(&mmc_cmd, 0, sizeof(struct mmc_command)); ++ memset(&mmc_dat, 0, sizeof(struct mmc_data)); ++ ++ /* Set up DMA descriptors */ ++ pprev = pkt; ++ for (pnext = pkt; ++ pnext && dma_len; ++ pnext = PKTNEXT(sd->osh, pnext)) { ++ pkt_len = PKTLEN(sd->osh, pnext); ++ ++ if (dma_len > pkt_len) ++ dma_len -= pkt_len; ++ else { ++ pkt_len = xfred_len = dma_len; ++ dma_len = 0; ++ pkt = pnext; ++ } ++ ++ sg_set_buf(&sd->sg_list[SGCount++], ++ (uint8*)PKTDATA(sd->osh, pnext), ++ pkt_len); ++ ++ if (SGCount >= SDIOH_SDMMC_MAX_SG_ENTRIES) { ++ AP6210_ERR("%s: sg list entries exceed limit\n", ++ __FUNCTION__); ++ return (SDIOH_API_RC_FAIL); ++ } ++ } ++ ++ mmc_dat.sg = sd->sg_list; ++ mmc_dat.sg_len = SGCount; ++ mmc_dat.blksz = blk_size; ++ mmc_dat.blocks = blk_num; ++ mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; ++ ++ mmc_cmd.opcode = 53; /* SD_IO_RW_EXTENDED */ ++ mmc_cmd.arg = write ? 1<<31 : 0; ++ mmc_cmd.arg |= (func & 0x7) << 28; ++ mmc_cmd.arg |= 1<<27; ++ mmc_cmd.arg |= fifo ? 0 : 1<<26; ++ mmc_cmd.arg |= (addr & 0x1FFFF) << 9; ++ mmc_cmd.arg |= blk_num & 0x1FF; ++ mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; ++ ++ mmc_req.cmd = &mmc_cmd; ++ mmc_req.data = &mmc_dat; ++ ++ sdio_claim_host(gInstance->func[func]); ++ mmc_set_data_timeout(&mmc_dat, gInstance->func[func]->card); ++ mmc_wait_for_req(gInstance->func[func]->card->host, &mmc_req); ++ sdio_release_host(gInstance->func[func]); ++ ++ err_ret = mmc_cmd.error? mmc_cmd.error : mmc_dat.error; ++ if (0 != err_ret) { ++ AP6210_ERR("%s:CMD53 %s failed with code %d\n", ++ __FUNCTION__, ++ write ? "write" : "read", ++ err_ret); ++ AP6210_ERR("%s:Disabling rxchain and fire it with PIO\n", ++ __FUNCTION__); ++ sd->use_rxchain = FALSE; ++ pkt = pprev; ++ lft_len = ttl_len; ++ } else if (!fifo) { ++ addr = addr + ttl_len - lft_len - dma_len; ++ } ++ } ++ ++ /* PIO mode */ ++ if (0 != lft_len) { ++ /* Claim host controller */ ++ sdio_claim_host(gInstance->func[func]); ++ for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) { ++ uint8 *buf = (uint8*)PKTDATA(sd->osh, pnext) + ++ xfred_len; ++ pkt_len = PKTLEN(sd->osh, pnext); ++ if (0 != xfred_len) { ++ pkt_len -= xfred_len; ++ xfred_len = 0; ++ } ++ ++ /* Align Patch ++ * read or small packet(ex:BDC header) skip 32 byte align ++ * otherwise, padding DHD_SDALIGN for performance ++ */ ++ if (write == 0 || pkt_len < 32) ++ pkt_len = (pkt_len + 3) & 0xFFFFFFFC; ++ else if (pkt_len % blk_size) ++ pkt_len += blk_size - (pkt_len % blk_size); ++ ++#ifdef CONFIG_MMC_MSM7X00A ++ if ((pkt_len % 64) == 32) { ++ AP6210_DEBUG("%s: Rounding up TX packet +=32\n", __FUNCTION__); ++ pkt_len += 32; ++ } ++#endif /* CONFIG_MMC_MSM7X00A */ ++ ++ if ((write) && (!fifo)) ++ err_ret = sdio_memcpy_toio( ++ gInstance->func[func], ++ addr, buf, pkt_len); ++ else if (write) ++ err_ret = sdio_memcpy_toio( ++ gInstance->func[func], ++ addr, buf, pkt_len); ++ else if (fifo) ++ err_ret = sdio_readsb( ++ gInstance->func[func], ++ buf, addr, pkt_len); ++ else ++ err_ret = sdio_memcpy_fromio( ++ gInstance->func[func], ++ buf, addr, pkt_len); ++ ++ //AW judge sdio read write timeout, 1s ++ ret = sw_mci_check_r1_ready(gInstance->func[func]->card->host, 1000); ++ if (ret != 0) ++ AP6210_DEBUG("%s data timeout.\n", __FUNCTION__); ++ ++ if (err_ret) ++ AP6210_ERR("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=%d\n", ++ __FUNCTION__, ++ (write) ? "TX" : "RX", ++ pnext, SGCount, addr, pkt_len, err_ret); ++ else ++ AP6210_DEBUG("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n", ++ __FUNCTION__, ++ (write) ? "TX" : "RX", ++ pnext, SGCount, addr, pkt_len); ++ ++ if (!fifo) ++ addr += pkt_len; ++ SGCount ++; ++ } ++ sdio_release_host(gInstance->func[func]); ++ } ++ ++ AP6210_DEBUG("%s: Exit\n", __FUNCTION__); ++ return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); ++} ++ ++ ++/* ++ * This function takes a buffer or packet, and fixes everything up so that in the ++ * end, a DMA-able packet is created. ++ * ++ * A buffer does not have an associated packet pointer, and may or may not be aligned. ++ * A packet may consist of a single packet, or a packet chain. If it is a packet chain, ++ * then all the packets in the chain must be properly aligned. If the packet data is not ++ * aligned, then there may only be one packet, and in this case, it is copied to a new ++ * aligned packet. ++ * ++ */ ++extern SDIOH_API_RC ++sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, uint func, ++ uint addr, uint reg_width, uint buflen_u, uint8 *buffer, void *pkt) ++{ ++ SDIOH_API_RC Status; ++ void *mypkt = NULL; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait); ++ DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); ++ /* Case 1: we don't have a packet. */ ++ if (pkt == NULL) { ++ AP6210_DEBUG("%s: Creating new %s Packet, len=%d\n", ++ __FUNCTION__, write ? "TX" : "RX", buflen_u); ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++ if (!(mypkt = PKTGET_STATIC(sd->osh, buflen_u, write ? TRUE : FALSE))) ++#else ++ if (!(mypkt = PKTGET(sd->osh, buflen_u, write ? TRUE : FALSE))) ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ { ++ AP6210_ERR("%s: PKTGET failed: len %d\n", ++ __FUNCTION__, buflen_u); ++ return SDIOH_API_RC_FAIL; ++ } ++ ++ /* For a write, copy the buffer data into the packet. */ ++ if (write) { ++ bcopy(buffer, PKTDATA(sd->osh, mypkt), buflen_u); ++ } ++ ++ Status = sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt); ++ ++ /* For a read, copy the packet data back to the buffer. */ ++ if (!write) { ++ bcopy(PKTDATA(sd->osh, mypkt), buffer, buflen_u); ++ } ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++ PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE); ++#else ++ PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE); ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ } else if (((uint32)(PKTDATA(sd->osh, pkt)) & DMA_ALIGN_MASK) != 0) { ++ /* Case 2: We have a packet, but it is unaligned. */ ++ ++ /* In this case, we cannot have a chain. */ ++ ASSERT(PKTNEXT(sd->osh, pkt) == NULL); ++ ++ AP6210_DEBUG("%s: Creating aligned %s Packet, len=%d\n", ++ __FUNCTION__, write ? "TX" : "RX", PKTLEN(sd->osh, pkt)); ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++ if (!(mypkt = PKTGET_STATIC(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) ++#else ++ if (!(mypkt = PKTGET(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ { ++ AP6210_ERR("%s: PKTGET failed: len %d\n", ++ __FUNCTION__, PKTLEN(sd->osh, pkt)); ++ return SDIOH_API_RC_FAIL; ++ } ++ ++ /* For a write, copy the buffer data into the packet. */ ++ if (write) { ++ bcopy(PKTDATA(sd->osh, pkt), ++ PKTDATA(sd->osh, mypkt), ++ PKTLEN(sd->osh, pkt)); ++ } ++ ++ Status = sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt); ++ ++ /* For a read, copy the packet data back to the buffer. */ ++ if (!write) { ++ bcopy(PKTDATA(sd->osh, mypkt), ++ PKTDATA(sd->osh, pkt), ++ PKTLEN(sd->osh, mypkt)); ++ } ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++ PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE); ++#else ++ PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE); ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ } else { /* case 3: We have a packet and it is aligned. */ ++ AP6210_DEBUG("%s: Aligned %s Packet, direct DMA\n", ++ __FUNCTION__, write ? "Tx" : "Rx"); ++ Status = sdioh_request_packet(sd, fix_inc, write, func, addr, pkt); ++ } ++ ++ return (Status); ++} ++ ++/* this function performs "abort" for both of host & device */ ++extern int ++sdioh_abort(sdioh_info_t *sd, uint func) ++{ ++#if defined(MMC_SDIO_ABORT) ++ char t_func = (char) func; ++#endif /* defined(MMC_SDIO_ABORT) */ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++#if defined(MMC_SDIO_ABORT) ++ /* issue abort cmd52 command through F1 */ ++ sdioh_request_byte(sd, SD_IO_OP_WRITE, SDIO_FUNC_0, SDIOD_CCCR_IOABORT, &t_func); ++#endif /* defined(MMC_SDIO_ABORT) */ ++ ++ AP6210_DEBUG("%s: Exit\n", __FUNCTION__); ++ return SDIOH_API_RC_SUCCESS; ++} ++ ++/* Reset and re-initialize the device */ ++int sdioh_sdio_reset(sdioh_info_t *si) ++{ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ AP6210_DEBUG("%s: Exit\n", __FUNCTION__); ++ return SDIOH_API_RC_SUCCESS; ++} ++ ++/* Disable device interrupt */ ++void ++sdioh_sdmmc_devintr_off(sdioh_info_t *sd) ++{ ++ AP6210_DEBUG("%s: %d\n", __FUNCTION__, sd->use_client_ints); ++ sd->intmask &= ~CLIENT_INTR; ++} ++ ++/* Enable device interrupt */ ++void ++sdioh_sdmmc_devintr_on(sdioh_info_t *sd) ++{ ++ AP6210_DEBUG("%s: %d\n", __FUNCTION__, sd->use_client_ints); ++ sd->intmask |= CLIENT_INTR; ++} ++ ++/* Read client card reg */ ++int ++sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data) ++{ ++ ++ if ((func == 0) || (regsize == 1)) { ++ uint8 temp = 0; ++ ++ sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp); ++ *data = temp; ++ *data &= 0xff; ++ AP6210_DEBUG("%s: byte read data=0x%02x\n", ++ __FUNCTION__, *data); ++ } else { ++ sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data, regsize); ++ if (regsize == 2) ++ *data &= 0xffff; ++ ++ AP6210_DEBUG("%s: word read data=0x%08x\n", ++ __FUNCTION__, *data); ++ } ++ ++ return SUCCESS; ++} ++ ++#if !defined(OOB_INTR_ONLY) ++/* bcmsdh_sdmmc interrupt handler */ ++static void IRQHandler(struct sdio_func *func) ++{ ++ sdioh_info_t *sd; ++ ++ AP6210_DEBUG("bcmsdh_sdmmc: ***IRQHandler\n"); ++ sd = gInstance->sd; ++ ++ ASSERT(sd != NULL); ++ sdio_release_host(gInstance->func[0]); ++ ++ if (sd->use_client_ints) { ++ sd->intrcount++; ++ ASSERT(sd->intr_handler); ++ ASSERT(sd->intr_handler_arg); ++ (sd->intr_handler)(sd->intr_handler_arg); ++ } else { ++ AP6210_ERR("bcmsdh_sdmmc: ***IRQHandler\n"); ++ ++ AP6210_ERR("%s: Not ready for intr: enabled %d, handler %p\n", ++ __FUNCTION__, sd->client_intr_enabled, sd->intr_handler); ++ } ++ ++ sdio_claim_host(gInstance->func[0]); ++} ++ ++/* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */ ++static void IRQHandlerF2(struct sdio_func *func) ++{ ++ sdioh_info_t *sd; ++ ++ AP6210_DEBUG("bcmsdh_sdmmc: ***IRQHandlerF2\n"); ++ ++ sd = gInstance->sd; ++ ++ ASSERT(sd != NULL); ++ BCM_REFERENCE(sd); ++} ++#endif /* !defined(OOB_INTR_ONLY) */ ++ ++#ifdef NOTUSED ++/* Write client card reg */ ++static int ++sdioh_sdmmc_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data) ++{ ++ ++ if ((func == 0) || (regsize == 1)) { ++ uint8 temp; ++ ++ temp = data & 0xff; ++ sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp); ++ AP6210_DEBUG("%s: byte write data=0x%02x\n", ++ __FUNCTION__, data); ++ } else { ++ if (regsize == 2) ++ data &= 0xffff; ++ ++ sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, &data, regsize); ++ ++ AP6210_DEBUG("%s: word write data=0x%08x\n", ++ __FUNCTION__, data); ++ } ++ ++ return SUCCESS; ++} ++#endif /* NOTUSED */ ++ ++int ++sdioh_start(sdioh_info_t *si, int stage) ++{ ++ int ret; ++ sdioh_info_t *sd = gInstance->sd; ++ ++ if (!sd) return (0); ++ ++ /* Need to do this stages as we can't enable the interrupt till ++ downloading of the firmware is complete, other wise polling ++ sdio access will come in way ++ */ ++ if (gInstance->func[0]) { ++ if (stage == 0) { ++ /* Since the power to the chip is killed, we will have ++ re enumerate the device again. Set the block size ++ and enable the fucntion 1 for in preparation for ++ downloading the code ++ */ ++ /* sdio_reset_comm() - has been fixed in latest kernel/msm.git for Linux ++ 2.6.27. The implementation prior to that is buggy, and needs broadcom's ++ patch for it ++ */ ++ if ((ret = sdio_reset_comm(gInstance->func[0]->card))) { ++ AP6210_ERR("%s Failed, error = %d\n", __FUNCTION__, ret); ++ return ret; ++ } ++ else { ++ sd->num_funcs = 2; ++ sd->sd_blockmode = TRUE; ++ sd->use_client_ints = TRUE; ++ sd->client_block_size[0] = 64; ++ ++ if (gInstance->func[1]) { ++ /* Claim host controller */ ++ sdio_claim_host(gInstance->func[1]); ++ ++ sd->client_block_size[1] = 64; ++ if (sdio_set_block_size(gInstance->func[1], 64)) { ++ AP6210_ERR("bcmsdh_sdmmc: Failed to set F1 blocksize\n"); ++ } ++ ++ /* Release host controller F1 */ ++ sdio_release_host(gInstance->func[1]); ++ } ++ ++ if (gInstance->func[2]) { ++ /* Claim host controller F2 */ ++ sdio_claim_host(gInstance->func[2]); ++ ++ sd->client_block_size[2] = sd_f2_blocksize; ++ if (sdio_set_block_size(gInstance->func[2], ++ sd_f2_blocksize)) { ++ AP6210_ERR("bcmsdh_sdmmc: Failed to set F2 " ++ "blocksize to %d\n", sd_f2_blocksize); ++ } ++ ++ /* Release host controller F2 */ ++ sdio_release_host(gInstance->func[2]); ++ } ++ ++ sdioh_sdmmc_card_enablefuncs(sd); ++ } ++ } else { ++#if !defined(OOB_INTR_ONLY) ++ sdio_claim_host(gInstance->func[0]); ++ if (gInstance->func[2]) ++ sdio_claim_irq(gInstance->func[2], IRQHandlerF2); ++ if (gInstance->func[1]) ++ sdio_claim_irq(gInstance->func[1], IRQHandler); ++ sdio_release_host(gInstance->func[0]); ++#else /* defined(OOB_INTR_ONLY) */ ++#if defined(HW_OOB) ++ sdioh_enable_func_intr(); ++#endif ++ bcmsdh_oob_intr_set(TRUE); ++#endif /* !defined(OOB_INTR_ONLY) */ ++ } ++ } ++ else ++ AP6210_ERR("%s Failed\n", __FUNCTION__); ++ ++ return (0); ++} ++ ++int ++sdioh_stop(sdioh_info_t *si) ++{ ++ /* MSM7201A Android sdio stack has bug with interrupt ++ So internaly within SDIO stack they are polling ++ which cause issue when device is turned off. So ++ unregister interrupt with SDIO stack to stop the ++ polling ++ */ ++ if (gInstance->func[0]) { ++#if !defined(OOB_INTR_ONLY) ++ sdio_claim_host(gInstance->func[0]); ++ if (gInstance->func[1]) ++ sdio_release_irq(gInstance->func[1]); ++ if (gInstance->func[2]) ++ sdio_release_irq(gInstance->func[2]); ++ sdio_release_host(gInstance->func[0]); ++#else /* defined(OOB_INTR_ONLY) */ ++#if defined(HW_OOB) ++ sdioh_disable_func_intr(); ++#endif ++ bcmsdh_oob_intr_set(FALSE); ++#endif /* !defined(OOB_INTR_ONLY) */ ++ } ++ else ++ AP6210_ERR("%s Failed\n", __FUNCTION__); ++ return (0); ++} ++ ++int ++sdioh_waitlockfree(sdioh_info_t *sd) ++{ ++ return (1); ++} ++ ++ ++SDIOH_API_RC ++sdioh_gpioouten(sdioh_info_t *sd, uint32 gpio) ++{ ++ return SDIOH_API_RC_FAIL; ++} ++ ++SDIOH_API_RC ++sdioh_gpioout(sdioh_info_t *sd, uint32 gpio, bool enab) ++{ ++ return SDIOH_API_RC_FAIL; ++} ++ ++bool ++sdioh_gpioin(sdioh_info_t *sd, uint32 gpio) ++{ ++ return FALSE; ++} ++ ++SDIOH_API_RC ++sdioh_gpio_init(sdioh_info_t *sd) ++{ ++ return SDIOH_API_RC_FAIL; ++} +diff --git a/drivers/net/wireless/ap6210/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/ap6210/bcmsdh_sdmmc_linux.c +new file mode 100755 +index 0000000..98b5818 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/bcmsdh_sdmmc_linux.c +@@ -0,0 +1,427 @@ ++/* ++ * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmsdh_sdmmc_linux.c 363783 2012-10-19 06:27:14Z $ ++ */ ++ ++#include ++#include ++#include /* SDIO Device and Protocol Specs */ ++#include /* bcmsdh to/from specific controller APIs */ ++#include /* to get msglevel bit values */ ++ ++#include /* request_irq() */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#if !defined(SDIO_VENDOR_ID_BROADCOM) ++#define SDIO_VENDOR_ID_BROADCOM 0x02d0 ++#endif /* !defined(SDIO_VENDOR_ID_BROADCOM) */ ++ ++#define SDIO_DEVICE_ID_BROADCOM_DEFAULT 0x0000 ++ ++#if !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) ++#define SDIO_DEVICE_ID_BROADCOM_4325_SDGWB 0x0492 /* BCM94325SDGWB */ ++#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) */ ++#if !defined(SDIO_DEVICE_ID_BROADCOM_4325) ++#define SDIO_DEVICE_ID_BROADCOM_4325 0x0493 ++#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */ ++#if !defined(SDIO_DEVICE_ID_BROADCOM_4329) ++#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 ++#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */ ++#if !defined(SDIO_DEVICE_ID_BROADCOM_4319) ++#define SDIO_DEVICE_ID_BROADCOM_4319 0x4319 ++#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4319) */ ++#if !defined(SDIO_DEVICE_ID_BROADCOM_4330) ++#define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 ++#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4330) */ ++#if !defined(SDIO_DEVICE_ID_BROADCOM_4334) ++#define SDIO_DEVICE_ID_BROADCOM_4334 0x4334 ++#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4334) */ ++#if !defined(SDIO_DEVICE_ID_BROADCOM_4324) ++#define SDIO_DEVICE_ID_BROADCOM_4324 0x4324 ++#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4324) */ ++#if !defined(SDIO_DEVICE_ID_BROADCOM_43239) ++#define SDIO_DEVICE_ID_BROADCOM_43239 43239 ++#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_43239) */ ++ ++ ++#include ++ ++#include ++ ++#ifdef WL_CFG80211 ++extern void wl_cfg80211_set_parent_dev(void *dev); ++#endif ++ ++extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd); ++extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd); ++extern int dhd_os_check_wakelock(void *dhdp); ++extern int dhd_os_check_if_up(void *dhdp); ++extern void *bcmsdh_get_drvdata(void); ++ ++int sdio_function_init(void); ++void sdio_function_cleanup(void); ++ ++#define DESCRIPTION "bcmsdh_sdmmc Driver" ++#define AUTHOR "Broadcom Corporation" ++ ++/* module param defaults */ ++static int clockoverride = 0; ++ ++module_param(clockoverride, int, 0644); ++MODULE_PARM_DESC(clockoverride, "SDIO card clock override"); ++ ++PBCMSDH_SDMMC_INSTANCE gInstance; ++ ++/* Maximum number of bcmsdh_sdmmc devices supported by driver */ ++#define BCMSDH_SDMMC_MAX_DEVICES 1 ++ ++extern int bcmsdh_probe(struct device *dev); ++extern int bcmsdh_remove(struct device *dev); ++extern volatile bool dhd_mmc_suspend; ++ ++static int bcmsdh_sdmmc_probe(struct sdio_func *func, ++ const struct sdio_device_id *id) ++{ ++ int ret = 0; ++ static struct sdio_func sdio_func_0; ++ ++ if (func) { ++ AP6210_DEBUG("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__); ++ AP6210_DEBUG("sdio_bcmsdh: func->class=%x\n", func->class); ++ AP6210_DEBUG("sdio_vendor: 0x%04x\n", func->vendor); ++ AP6210_DEBUG("sdio_device: 0x%04x\n", func->device); ++ AP6210_DEBUG("Function#: 0x%04x\n", func->num); ++ ++ if (func->num == 1) { ++ sdio_func_0.num = 0; ++ sdio_func_0.card = func->card; ++ gInstance->func[0] = &sdio_func_0; ++ if(func->device == 0x4) { /* 4318 */ ++ gInstance->func[2] = NULL; ++ AP6210_DEBUG("NIC found, calling bcmsdh_probe...\n"); ++ ret = bcmsdh_probe(&func->dev); ++ } ++ } ++ ++ gInstance->func[func->num] = func; ++ ++ if (func->num == 2) { ++ #ifdef WL_CFG80211 ++ wl_cfg80211_set_parent_dev(&func->dev); ++ #endif ++ AP6210_DEBUG("F2 found, calling bcmsdh_probe...\n"); ++ ret = bcmsdh_probe(&func->dev); ++ } ++ } else { ++ ret = -ENODEV; ++ } ++ ++ return ret; ++} ++ ++static void bcmsdh_sdmmc_remove(struct sdio_func *func) ++{ ++ if (func) { ++ AP6210_DEBUG("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__); ++ AP6210_DEBUG("sdio_bcmsdh: func->class=%x\n", func->class); ++ AP6210_DEBUG("sdio_vendor: 0x%04x\n", func->vendor); ++ AP6210_DEBUG("sdio_device: 0x%04x\n", func->device); ++ AP6210_DEBUG("Function#: 0x%04x\n", func->num); ++ ++ if (gInstance->func[2]) { ++ AP6210_DEBUG("F2 found, calling bcmsdh_remove...\n"); ++ bcmsdh_remove(&func->dev); ++ gInstance->func[2] = NULL; ++ } ++ if (func->num == 1) { ++ sdio_claim_host(func); ++ sdio_disable_func(func); ++ sdio_release_host(func); ++ gInstance->func[1] = NULL; ++ } ++ } ++} ++ ++/* devices we support, null terminated */ ++static const struct sdio_device_id bcmsdh_sdmmc_ids[] = { ++ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_DEFAULT) }, ++ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) }, ++ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325) }, ++ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329) }, ++ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319) }, ++ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330) }, ++ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334) }, ++ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4324) }, ++ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43239) }, ++ { SDIO_DEVICE_CLASS(SDIO_CLASS_NONE) }, ++ { /* end: all zeroes */ }, ++}; ++ ++MODULE_DEVICE_TABLE(sdio, bcmsdh_sdmmc_ids); ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) ++static int bcmsdh_sdmmc_suspend(struct device *pdev) ++{ ++ struct sdio_func *func = dev_to_sdio_func(pdev); ++ mmc_pm_flag_t sdio_flags; ++ int ret; ++ ++ if (func->num != 2) ++ return 0; ++ ++ AP6210_DEBUG("%s Enter\n", __FUNCTION__); ++ ++ if (dhd_os_check_wakelock(bcmsdh_get_drvdata())) ++ return -EBUSY; ++ ++ sdio_flags = sdio_get_host_pm_caps(func); ++ ++ if (!(sdio_flags & MMC_PM_KEEP_POWER)) { ++ AP6210_ERR("%s: can't keep power while host is suspended\n", __FUNCTION__); ++ return -EINVAL; ++ } ++ ++ /* keep power while host suspended */ ++ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); ++ if (ret) { ++ AP6210_ERR("%s: error while trying to keep power\n", __FUNCTION__); ++ return ret; ++ } ++ ++#if defined(OOB_INTR_ONLY) ++ bcmsdh_oob_intr_set(0); ++#endif /* defined(OOB_INTR_ONLY) */ ++ dhd_mmc_suspend = TRUE; ++ smp_mb(); ++ ++ return 0; ++} ++ ++static int bcmsdh_sdmmc_resume(struct device *pdev) ++{ ++#if defined(OOB_INTR_ONLY) ++ struct sdio_func *func = dev_to_sdio_func(pdev); ++#endif /* defined(OOB_INTR_ONLY) */ ++ AP6210_DEBUG("%s Enter\n", __FUNCTION__); ++ ++ dhd_mmc_suspend = FALSE; ++#if defined(OOB_INTR_ONLY) ++ if ((func->num == 2) && dhd_os_check_if_up(bcmsdh_get_drvdata())) ++ bcmsdh_oob_intr_set(1); ++#endif /* (OOB_INTR_ONLY) */ ++ smp_mb(); ++ return 0; ++} ++ ++static const struct dev_pm_ops bcmsdh_sdmmc_pm_ops = { ++ .suspend = bcmsdh_sdmmc_suspend, ++ .resume = bcmsdh_sdmmc_resume, ++}; ++#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */ ++ ++#if defined(BCMLXSDMMC) ++static struct semaphore *notify_semaphore = NULL; ++ ++static int dummy_probe(struct sdio_func *func, ++ const struct sdio_device_id *id) ++{ ++ if (notify_semaphore) ++ up(notify_semaphore); ++ return 0; ++} ++ ++static void dummy_remove(struct sdio_func *func) ++{ ++} ++ ++static struct sdio_driver dummy_sdmmc_driver = { ++ .probe = dummy_probe, ++ .remove = dummy_remove, ++ .name = "dummy_sdmmc", ++ .id_table = bcmsdh_sdmmc_ids, ++ }; ++ ++int sdio_func_reg_notify(void* semaphore) ++{ ++ notify_semaphore = semaphore; ++ return sdio_register_driver(&dummy_sdmmc_driver); ++} ++ ++void sdio_func_unreg_notify(void) ++{ ++ sdio_unregister_driver(&dummy_sdmmc_driver); ++} ++ ++#endif /* defined(BCMLXSDMMC) */ ++ ++static struct sdio_driver bcmsdh_sdmmc_driver = { ++ .probe = bcmsdh_sdmmc_probe, ++ .remove = bcmsdh_sdmmc_remove, ++ .name = "bcmsdh_sdmmc", ++ .id_table = bcmsdh_sdmmc_ids, ++#if !defined(CONFIG_ARCH_RHEA) || !defined(CONFIG_ARCH_CAPRI) ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) ++ .drv = { ++ .pm = &bcmsdh_sdmmc_pm_ops, ++ }, ++#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */ ++#endif /* !defined(CONFIG_ARCH_RHEA) || !defined(CONFIG_ARCH_CAPRI) */ ++ }; ++ ++struct sdos_info { ++ sdioh_info_t *sd; ++ spinlock_t lock; ++}; ++ ++ ++int ++sdioh_sdmmc_osinit(sdioh_info_t *sd) ++{ ++ struct sdos_info *sdos; ++ ++ if (!sd) ++ return BCME_BADARG; ++ ++ sdos = (struct sdos_info*)MALLOC(sd->osh, sizeof(struct sdos_info)); ++ sd->sdos_info = (void*)sdos; ++ if (sdos == NULL) ++ return BCME_NOMEM; ++ ++ sdos->sd = sd; ++ spin_lock_init(&sdos->lock); ++ return BCME_OK; ++} ++ ++void ++sdioh_sdmmc_osfree(sdioh_info_t *sd) ++{ ++ struct sdos_info *sdos; ++ ASSERT(sd && sd->sdos_info); ++ ++ sdos = (struct sdos_info *)sd->sdos_info; ++ MFREE(sd->osh, sdos, sizeof(struct sdos_info)); ++} ++ ++/* Interrupt enable/disable */ ++SDIOH_API_RC ++sdioh_interrupt_set(sdioh_info_t *sd, bool enable) ++{ ++ ulong flags; ++ struct sdos_info *sdos; ++ ++ if (!sd) ++ return BCME_BADARG; ++ ++ AP6210_DEBUG("%s: %s\n", __FUNCTION__, enable ? "Enabling" : "Disabling"); ++ ++ sdos = (struct sdos_info *)sd->sdos_info; ++ ASSERT(sdos); ++ ++#if !defined(OOB_INTR_ONLY) ++ if (enable && !(sd->intr_handler && sd->intr_handler_arg)) { ++ AP6210_ERR("%s: no handler registered, will not enable\n", __FUNCTION__); ++ return SDIOH_API_RC_FAIL; ++ } ++#endif /* !defined(OOB_INTR_ONLY) */ ++ ++ /* Ensure atomicity for enable/disable calls */ ++ spin_lock_irqsave(&sdos->lock, flags); ++ ++ sd->client_intr_enabled = enable; ++ if (enable) { ++ sdioh_sdmmc_devintr_on(sd); ++ } else { ++ sdioh_sdmmc_devintr_off(sd); ++ } ++ ++ spin_unlock_irqrestore(&sdos->lock, flags); ++ ++ return SDIOH_API_RC_SUCCESS; ++} ++ ++ ++#ifdef BCMSDH_MODULE ++static int __init ++bcmsdh_module_init(void) ++{ ++ int error = 0; ++ error = sdio_function_init(); ++ return error; ++} ++ ++static void __exit ++bcmsdh_module_cleanup(void) ++{ ++ sdio_function_cleanup(); ++} ++ ++module_init(bcmsdh_module_init); ++module_exit(bcmsdh_module_cleanup); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION(DESCRIPTION); ++MODULE_AUTHOR(AUTHOR); ++ ++#endif /* BCMSDH_MODULE */ ++/* ++ * module init ++*/ ++int sdio_function_init(void) ++{ ++ int error = 0; ++ AP6210_DEBUG("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__); ++ ++ gInstance = kzalloc(sizeof(BCMSDH_SDMMC_INSTANCE), GFP_KERNEL); ++ if (!gInstance) ++ return -ENOMEM; ++ ++ error = sdio_register_driver(&bcmsdh_sdmmc_driver); ++ if (error && gInstance) { ++ kfree(gInstance); ++ gInstance = 0; ++ } ++ ++ return error; ++} ++ ++/* ++ * module cleanup ++*/ ++extern int bcmsdh_remove(struct device *dev); ++void sdio_function_cleanup(void) ++{ ++ AP6210_DEBUG("%s Enter\n", __FUNCTION__); ++ ++ ++ sdio_unregister_driver(&bcmsdh_sdmmc_driver); ++ ++ if (gInstance) ++ kfree(gInstance); ++} +diff --git a/drivers/net/wireless/ap6210/bcmutils.c b/drivers/net/wireless/ap6210/bcmutils.c +new file mode 100755 +index 0000000..631125a +--- /dev/null ++++ b/drivers/net/wireless/ap6210/bcmutils.c +@@ -0,0 +1,2095 @@ ++/* ++ * Driver O/S-independent utility routines ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * $Id: bcmutils.c 312855 2012-02-04 02:01:18Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#ifdef BCMDRIVER ++ ++#include ++#include ++ ++#else /* !BCMDRIVER */ ++ ++#include ++#include ++#include ++ ++#if defined(BCMEXTSUP) ++#include ++#endif ++ ++ ++#endif /* !BCMDRIVER */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++void *_bcmutils_dummy_fn = NULL; ++ ++#include ++ ++ ++#ifdef BCMDRIVER ++ ++ ++ ++/* copy a pkt buffer chain into a buffer */ ++uint ++pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf) ++{ ++ uint n, ret = 0; ++ ++ if (len < 0) ++ len = 4096; /* "infinite" */ ++ ++ /* skip 'offset' bytes */ ++ for (; p && offset; p = PKTNEXT(osh, p)) { ++ if (offset < (uint)PKTLEN(osh, p)) ++ break; ++ offset -= PKTLEN(osh, p); ++ } ++ ++ if (!p) ++ return 0; ++ ++ /* copy the data */ ++ for (; p && len; p = PKTNEXT(osh, p)) { ++ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); ++ bcopy(PKTDATA(osh, p) + offset, buf, n); ++ buf += n; ++ len -= n; ++ ret += n; ++ offset = 0; ++ } ++ ++ return ret; ++} ++ ++/* copy a buffer into a pkt buffer chain */ ++uint ++pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf) ++{ ++ uint n, ret = 0; ++ ++ /* skip 'offset' bytes */ ++ for (; p && offset; p = PKTNEXT(osh, p)) { ++ if (offset < (uint)PKTLEN(osh, p)) ++ break; ++ offset -= PKTLEN(osh, p); ++ } ++ ++ if (!p) ++ return 0; ++ ++ /* copy the data */ ++ for (; p && len; p = PKTNEXT(osh, p)) { ++ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); ++ bcopy(buf, PKTDATA(osh, p) + offset, n); ++ buf += n; ++ len -= n; ++ ret += n; ++ offset = 0; ++ } ++ ++ return ret; ++} ++ ++ ++ ++/* return total length of buffer chain */ ++uint BCMFASTPATH ++pkttotlen(osl_t *osh, void *p) ++{ ++ uint total; ++ int len; ++ ++ total = 0; ++ for (; p; p = PKTNEXT(osh, p)) { ++ len = PKTLEN(osh, p); ++ total += len; ++ } ++ ++ return (total); ++} ++ ++/* return the last buffer of chained pkt */ ++void * ++pktlast(osl_t *osh, void *p) ++{ ++ for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p)) ++ ; ++ ++ return (p); ++} ++ ++/* count segments of a chained packet */ ++uint BCMFASTPATH ++pktsegcnt(osl_t *osh, void *p) ++{ ++ uint cnt; ++ ++ for (cnt = 0; p; p = PKTNEXT(osh, p)) ++ cnt++; ++ ++ return cnt; ++} ++ ++ ++/* count segments of a chained packet */ ++uint BCMFASTPATH ++pktsegcnt_war(osl_t *osh, void *p) ++{ ++ uint cnt; ++ uint8 *pktdata; ++ uint len, remain, align64; ++ ++ for (cnt = 0; p; p = PKTNEXT(osh, p)) { ++ cnt++; ++ len = PKTLEN(osh, p); ++ if (len > 128) { ++ pktdata = (uint8 *)PKTDATA(osh, p); /* starting address of data */ ++ /* Check for page boundary straddle (2048B) */ ++ if (((uintptr)pktdata & ~0x7ff) != ((uintptr)(pktdata+len) & ~0x7ff)) ++ cnt++; ++ ++ align64 = (uint)((uintptr)pktdata & 0x3f); /* aligned to 64B */ ++ align64 = (64 - align64) & 0x3f; ++ len -= align64; /* bytes from aligned 64B to end */ ++ /* if aligned to 128B, check for MOD 128 between 1 to 4B */ ++ remain = len % 128; ++ if (remain > 0 && remain <= 4) ++ cnt++; /* add extra seg */ ++ } ++ } ++ ++ return cnt; ++} ++ ++uint8 * BCMFASTPATH ++pktoffset(osl_t *osh, void *p, uint offset) ++{ ++ uint total = pkttotlen(osh, p); ++ uint pkt_off = 0, len = 0; ++ uint8 *pdata = (uint8 *) PKTDATA(osh, p); ++ ++ if (offset > total) ++ return NULL; ++ ++ for (; p; p = PKTNEXT(osh, p)) { ++ pdata = (uint8 *) PKTDATA(osh, p); ++ pkt_off = offset - len; ++ len += PKTLEN(osh, p); ++ if (len > offset) ++ break; ++ } ++ return (uint8*) (pdata+pkt_off); ++} ++ ++/* ++ * osl multiple-precedence packet queue ++ * hi_prec is always >= the number of the highest non-empty precedence ++ */ ++void * BCMFASTPATH ++pktq_penq(struct pktq *pq, int prec, void *p) ++{ ++ struct pktq_prec *q; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ ++ ++ ASSERT(!pktq_full(pq)); ++ ASSERT(!pktq_pfull(pq, prec)); ++ ++ q = &pq->q[prec]; ++ ++ if (q->head) ++ PKTSETLINK(q->tail, p); ++ else ++ q->head = p; ++ ++ q->tail = p; ++ q->len++; ++ ++ pq->len++; ++ ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (uint8)prec; ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_penq_head(struct pktq *pq, int prec, void *p) ++{ ++ struct pktq_prec *q; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ ++ ++ ASSERT(!pktq_full(pq)); ++ ASSERT(!pktq_pfull(pq, prec)); ++ ++ q = &pq->q[prec]; ++ ++ if (q->head == NULL) ++ q->tail = p; ++ ++ PKTSETLINK(p, q->head); ++ q->head = p; ++ q->len++; ++ ++ pq->len++; ++ ++ if (pq->hi_prec < prec) ++ pq->hi_prec = (uint8)prec; ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_pdeq(struct pktq *pq, int prec) ++{ ++ struct pktq_prec *q; ++ void *p; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ pq->len--; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p) ++{ ++ struct pktq_prec *q; ++ void *p; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ q = &pq->q[prec]; ++ ++ if (prev_p == NULL) ++ return NULL; ++ ++ if ((p = PKTLINK(prev_p)) == NULL) ++ return NULL; ++ ++ q->len--; ++ ++ pq->len--; ++ ++ PKTSETLINK(prev_p, PKTLINK(p)); ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_pdeq_tail(struct pktq *pq, int prec) ++{ ++ struct pktq_prec *q; ++ void *p, *prev; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ for (prev = NULL; p != q->tail; p = PKTLINK(p)) ++ prev = p; ++ ++ if (prev) ++ PKTSETLINK(prev, NULL); ++ else ++ q->head = NULL; ++ ++ q->tail = prev; ++ q->len--; ++ ++ pq->len--; ++ ++ return p; ++} ++ ++void ++pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ifpkt_cb_t fn, int arg) ++{ ++ struct pktq_prec *q; ++ void *p, *prev = NULL; ++ ++ q = &pq->q[prec]; ++ p = q->head; ++ while (p) { ++ if (fn == NULL || (*fn)(p, arg)) { ++ bool head = (p == q->head); ++ if (head) ++ q->head = PKTLINK(p); ++ else ++ PKTSETLINK(prev, PKTLINK(p)); ++ PKTSETLINK(p, NULL); ++ PKTFREE(osh, p, dir); ++ q->len--; ++ pq->len--; ++ p = (head ? q->head : PKTLINK(prev)); ++ } else { ++ prev = p; ++ p = PKTLINK(p); ++ } ++ } ++ ++ if (q->head == NULL) { ++ ASSERT(q->len == 0); ++ q->tail = NULL; ++ } ++} ++ ++bool BCMFASTPATH ++pktq_pdel(struct pktq *pq, void *pktbuf, int prec) ++{ ++ struct pktq_prec *q; ++ void *p; ++ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ if (!pktbuf) ++ return FALSE; ++ ++ q = &pq->q[prec]; ++ ++ if (q->head == pktbuf) { ++ if ((q->head = PKTLINK(pktbuf)) == NULL) ++ q->tail = NULL; ++ } else { ++ for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p)) ++ ; ++ if (p == NULL) ++ return FALSE; ++ ++ PKTSETLINK(p, PKTLINK(pktbuf)); ++ if (q->tail == pktbuf) ++ q->tail = p; ++ } ++ ++ q->len--; ++ pq->len--; ++ PKTSETLINK(pktbuf, NULL); ++ return TRUE; ++} ++ ++void ++pktq_init(struct pktq *pq, int num_prec, int max_len) ++{ ++ int prec; ++ ++ ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC); ++ ++ /* pq is variable size; only zero out what's requested */ ++ bzero(pq, OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec)); ++ ++ pq->num_prec = (uint16)num_prec; ++ ++ pq->max = (uint16)max_len; ++ ++ for (prec = 0; prec < num_prec; prec++) ++ pq->q[prec].max = pq->max; ++} ++ ++void ++pktq_set_max_plen(struct pktq *pq, int prec, int max_len) ++{ ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ if (prec < pq->num_prec) ++ pq->q[prec].max = (uint16)max_len; ++} ++ ++void * BCMFASTPATH ++pktq_deq(struct pktq *pq, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p; ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ pq->len--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * BCMFASTPATH ++pktq_deq_tail(struct pktq *pq, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p, *prev; ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ for (prec = 0; prec < pq->hi_prec; prec++) ++ if (pq->q[prec].head) ++ break; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ for (prev = NULL; p != q->tail; p = PKTLINK(p)) ++ prev = p; ++ ++ if (prev) ++ PKTSETLINK(prev, NULL); ++ else ++ q->head = NULL; ++ ++ q->tail = prev; ++ q->len--; ++ ++ pq->len--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++void * ++pktq_peek(struct pktq *pq, int *prec_out) ++{ ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return (pq->q[prec].head); ++} ++ ++void * ++pktq_peek_tail(struct pktq *pq, int *prec_out) ++{ ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ for (prec = 0; prec < pq->hi_prec; prec++) ++ if (pq->q[prec].head) ++ break; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return (pq->q[prec].tail); ++} ++ ++void ++pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg) ++{ ++ int prec; ++ ++ /* Optimize flush, if pktq len = 0, just return. ++ * pktq len of 0 means pktq's prec q's are all empty. ++ */ ++ if (pq->len == 0) { ++ return; ++ } ++ ++ for (prec = 0; prec < pq->num_prec; prec++) ++ pktq_pflush(osh, pq, prec, dir, fn, arg); ++ if (fn == NULL) ++ ASSERT(pq->len == 0); ++} ++ ++/* Return sum of lengths of a specific set of precedences */ ++int ++pktq_mlen(struct pktq *pq, uint prec_bmp) ++{ ++ int prec, len; ++ ++ len = 0; ++ ++ for (prec = 0; prec <= pq->hi_prec; prec++) ++ if (prec_bmp & (1 << prec)) ++ len += pq->q[prec].len; ++ ++ return len; ++} ++ ++/* Priority peek from a specific set of precedences */ ++void * BCMFASTPATH ++pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p; ++ int prec; ++ ++ if (pq->len == 0) ++ { ++ return NULL; ++ } ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) ++ if (prec-- == 0) ++ return NULL; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return p; ++} ++/* Priority dequeue from a specific set of precedences */ ++void * BCMFASTPATH ++pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out) ++{ ++ struct pktq_prec *q; ++ void *p; ++ int prec; ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) ++ pq->hi_prec--; ++ ++ while ((pq->q[prec].head == NULL) || ((prec_bmp & (1 << prec)) == 0)) ++ if (prec-- == 0) ++ return NULL; ++ ++ q = &pq->q[prec]; ++ ++ if ((p = q->head) == NULL) ++ return NULL; ++ ++ if ((q->head = PKTLINK(p)) == NULL) ++ q->tail = NULL; ++ ++ q->len--; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ pq->len--; ++ ++ PKTSETLINK(p, NULL); ++ ++ return p; ++} ++ ++#endif /* BCMDRIVER */ ++ ++const unsigned char bcm_ctype[] = { ++ ++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */ ++ _BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C, ++ _BCM_C, /* 8-15 */ ++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */ ++ _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */ ++ _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */ ++ _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */ ++ _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */ ++ _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */ ++ _BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, ++ _BCM_U|_BCM_X, _BCM_U, /* 64-71 */ ++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */ ++ _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */ ++ _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */ ++ _BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, ++ _BCM_L|_BCM_X, _BCM_L, /* 96-103 */ ++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */ ++ _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */ ++ _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */ ++ _BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, ++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */ ++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, ++ _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */ ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */ ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U, ++ _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */ ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */ ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L, ++ _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */ ++}; ++ ++ulong ++bcm_strtoul(const char *cp, char **endp, uint base) ++{ ++ ulong result, last_result = 0, value; ++ bool minus; ++ ++ minus = FALSE; ++ ++ while (bcm_isspace(*cp)) ++ cp++; ++ ++ if (cp[0] == '+') ++ cp++; ++ else if (cp[0] == '-') { ++ minus = TRUE; ++ cp++; ++ } ++ ++ if (base == 0) { ++ if (cp[0] == '0') { ++ if ((cp[1] == 'x') || (cp[1] == 'X')) { ++ base = 16; ++ cp = &cp[2]; ++ } else { ++ base = 8; ++ cp = &cp[1]; ++ } ++ } else ++ base = 10; ++ } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) { ++ cp = &cp[2]; ++ } ++ ++ result = 0; ++ ++ while (bcm_isxdigit(*cp) && ++ (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) { ++ result = result*base + value; ++ /* Detected overflow */ ++ if (result < last_result && !minus) ++ return (ulong)-1; ++ last_result = result; ++ cp++; ++ } ++ ++ if (minus) ++ result = (ulong)(-(long)result); ++ ++ if (endp) ++ *endp = DISCARD_QUAL(cp, char); ++ ++ return (result); ++} ++ ++int ++bcm_atoi(const char *s) ++{ ++ return (int)bcm_strtoul(s, NULL, 10); ++} ++ ++/* return pointer to location of substring 'needle' in 'haystack' */ ++char * ++bcmstrstr(const char *haystack, const char *needle) ++{ ++ int len, nlen; ++ int i; ++ ++ if ((haystack == NULL) || (needle == NULL)) ++ return DISCARD_QUAL(haystack, char); ++ ++ nlen = strlen(needle); ++ len = strlen(haystack) - nlen + 1; ++ ++ for (i = 0; i < len; i++) ++ if (memcmp(needle, &haystack[i], nlen) == 0) ++ return DISCARD_QUAL(&haystack[i], char); ++ return (NULL); ++} ++ ++char * ++bcmstrcat(char *dest, const char *src) ++{ ++ char *p; ++ ++ p = dest + strlen(dest); ++ ++ while ((*p++ = *src++) != '\0') ++ ; ++ ++ return (dest); ++} ++ ++char * ++bcmstrncat(char *dest, const char *src, uint size) ++{ ++ char *endp; ++ char *p; ++ ++ p = dest + strlen(dest); ++ endp = p + size; ++ ++ while (p != endp && (*p++ = *src++) != '\0') ++ ; ++ ++ return (dest); ++} ++ ++ ++/**************************************************************************** ++* Function: bcmstrtok ++* ++* Purpose: ++* Tokenizes a string. This function is conceptually similiar to ANSI C strtok(), ++* but allows strToken() to be used by different strings or callers at the same ++* time. Each call modifies '*string' by substituting a NULL character for the ++* first delimiter that is encountered, and updates 'string' to point to the char ++* after the delimiter. Leading delimiters are skipped. ++* ++* Parameters: ++* string (mod) Ptr to string ptr, updated by token. ++* delimiters (in) Set of delimiter characters. ++* tokdelim (out) Character that delimits the returned token. (May ++* be set to NULL if token delimiter is not required). ++* ++* Returns: Pointer to the next token found. NULL when no more tokens are found. ++***************************************************************************** ++*/ ++char * ++bcmstrtok(char **string, const char *delimiters, char *tokdelim) ++{ ++ unsigned char *str; ++ unsigned long map[8]; ++ int count; ++ char *nextoken; ++ ++ if (tokdelim != NULL) { ++ /* Prime the token delimiter */ ++ *tokdelim = '\0'; ++ } ++ ++ /* Clear control map */ ++ for (count = 0; count < 8; count++) { ++ map[count] = 0; ++ } ++ ++ /* Set bits in delimiter table */ ++ do { ++ map[*delimiters >> 5] |= (1 << (*delimiters & 31)); ++ } ++ while (*delimiters++); ++ ++ str = (unsigned char*)*string; ++ ++ /* Find beginning of token (skip over leading delimiters). Note that ++ * there is no token iff this loop sets str to point to the terminal ++ * null (*str == '\0') ++ */ ++ while (((map[*str >> 5] & (1 << (*str & 31))) && *str) || (*str == ' ')) { ++ str++; ++ } ++ ++ nextoken = (char*)str; ++ ++ /* Find the end of the token. If it is not the end of the string, ++ * put a null there. ++ */ ++ for (; *str; str++) { ++ if (map[*str >> 5] & (1 << (*str & 31))) { ++ if (tokdelim != NULL) { ++ *tokdelim = *str; ++ } ++ ++ *str++ = '\0'; ++ break; ++ } ++ } ++ ++ *string = (char*)str; ++ ++ /* Determine if a token has been found. */ ++ if (nextoken == (char *) str) { ++ return NULL; ++ } ++ else { ++ return nextoken; ++ } ++} ++ ++ ++#define xToLower(C) \ ++ ((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C) ++ ++ ++/**************************************************************************** ++* Function: bcmstricmp ++* ++* Purpose: Compare to strings case insensitively. ++* ++* Parameters: s1 (in) First string to compare. ++* s2 (in) Second string to compare. ++* ++* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if ++* t1 > t2, when ignoring case sensitivity. ++***************************************************************************** ++*/ ++int ++bcmstricmp(const char *s1, const char *s2) ++{ ++ char dc, sc; ++ ++ while (*s2 && *s1) { ++ dc = xToLower(*s1); ++ sc = xToLower(*s2); ++ if (dc < sc) return -1; ++ if (dc > sc) return 1; ++ s1++; ++ s2++; ++ } ++ ++ if (*s1 && !*s2) return 1; ++ if (!*s1 && *s2) return -1; ++ return 0; ++} ++ ++ ++/**************************************************************************** ++* Function: bcmstrnicmp ++* ++* Purpose: Compare to strings case insensitively, upto a max of 'cnt' ++* characters. ++* ++* Parameters: s1 (in) First string to compare. ++* s2 (in) Second string to compare. ++* cnt (in) Max characters to compare. ++* ++* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if ++* t1 > t2, when ignoring case sensitivity. ++***************************************************************************** ++*/ ++int ++bcmstrnicmp(const char* s1, const char* s2, int cnt) ++{ ++ char dc, sc; ++ ++ while (*s2 && *s1 && cnt) { ++ dc = xToLower(*s1); ++ sc = xToLower(*s2); ++ if (dc < sc) return -1; ++ if (dc > sc) return 1; ++ s1++; ++ s2++; ++ cnt--; ++ } ++ ++ if (!cnt) return 0; ++ if (*s1 && !*s2) return 1; ++ if (!*s1 && *s2) return -1; ++ return 0; ++} ++ ++/* parse a xx:xx:xx:xx:xx:xx format ethernet address */ ++int ++bcm_ether_atoe(const char *p, struct ether_addr *ea) ++{ ++ int i = 0; ++ char *ep; ++ ++ for (;;) { ++ ea->octet[i++] = (char) bcm_strtoul(p, &ep, 16); ++ p = ep; ++ if (!*p++ || i == 6) ++ break; ++ } ++ ++ return (i == 6); ++} ++ ++ ++#if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER) ++/* registry routine buffer preparation utility functions: ++ * parameter order is like strncpy, but returns count ++ * of bytes copied. Minimum bytes copied is null char(1)/wchar(2) ++ */ ++ulong ++wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen) ++{ ++ ulong copyct = 1; ++ ushort i; ++ ++ if (abuflen == 0) ++ return 0; ++ ++ /* wbuflen is in bytes */ ++ wbuflen /= sizeof(ushort); ++ ++ for (i = 0; i < wbuflen; ++i) { ++ if (--abuflen == 0) ++ break; ++ *abuf++ = (char) *wbuf++; ++ ++copyct; ++ } ++ *abuf = '\0'; ++ ++ return copyct; ++} ++#endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */ ++ ++char * ++bcm_ether_ntoa(const struct ether_addr *ea, char *buf) ++{ ++ static const char hex[] = ++ { ++ '0', '1', '2', '3', '4', '5', '6', '7', ++ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' ++ }; ++ const uint8 *octet = ea->octet; ++ char *p = buf; ++ int i; ++ ++ for (i = 0; i < 6; i++, octet++) { ++ *p++ = hex[(*octet >> 4) & 0xf]; ++ *p++ = hex[*octet & 0xf]; ++ *p++ = ':'; ++ } ++ ++ *(p-1) = '\0'; ++ ++ return (buf); ++} ++ ++char * ++bcm_ip_ntoa(struct ipv4_addr *ia, char *buf) ++{ ++ snprintf(buf, 16, "%d.%d.%d.%d", ++ ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]); ++ return (buf); ++} ++ ++#ifdef BCMDRIVER ++ ++void ++bcm_mdelay(uint ms) ++{ ++ uint i; ++ ++ for (i = 0; i < ms; i++) { ++ OSL_DELAY(1000); ++ } ++} ++ ++ ++ ++ ++ ++#if defined(DHD_DEBUG) ++/* pretty hex print a pkt buffer chain */ ++void ++prpkt(const char *msg, osl_t *osh, void *p0) ++{ ++ void *p; ++ ++ if (msg && (msg[0] != '\0')) ++ AP6210_DEBUG("%s:\n", msg); ++ ++ for (p = p0; p; p = PKTNEXT(osh, p)) ++ prhex(NULL, PKTDATA(osh, p), PKTLEN(osh, p)); ++} ++#endif ++ ++/* Takes an Ethernet frame and sets out-of-bound PKTPRIO. ++ * Also updates the inplace vlan tag if requested. ++ * For debugging, it returns an indication of what it did. ++ */ ++uint BCMFASTPATH ++pktsetprio(void *pkt, bool update_vtag) ++{ ++ struct ether_header *eh; ++ struct ethervlan_header *evh; ++ uint8 *pktdata; ++ int priority = 0; ++ int rc = 0; ++ ++ pktdata = (uint8 *)PKTDATA(NULL, pkt); ++ ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16))); ++ ++ eh = (struct ether_header *) pktdata; ++ ++ if (ntoh16(eh->ether_type) == ETHER_TYPE_8021Q) { ++ uint16 vlan_tag; ++ int vlan_prio, dscp_prio = 0; ++ ++ evh = (struct ethervlan_header *)eh; ++ ++ vlan_tag = ntoh16(evh->vlan_tag); ++ vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; ++ ++ if (ntoh16(evh->ether_type) == ETHER_TYPE_IP) { ++ uint8 *ip_body = pktdata + sizeof(struct ethervlan_header); ++ uint8 tos_tc = IP_TOS46(ip_body); ++ dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); ++ } ++ ++ /* DSCP priority gets precedence over 802.1P (vlan tag) */ ++ if (dscp_prio != 0) { ++ priority = dscp_prio; ++ rc |= PKTPRIO_VDSCP; ++ } else { ++ priority = vlan_prio; ++ rc |= PKTPRIO_VLAN; ++ } ++ /* ++ * If the DSCP priority is not the same as the VLAN priority, ++ * then overwrite the priority field in the vlan tag, with the ++ * DSCP priority value. This is required for Linux APs because ++ * the VLAN driver on Linux, overwrites the skb->priority field ++ * with the priority value in the vlan tag ++ */ ++ if (update_vtag && (priority != vlan_prio)) { ++ vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT); ++ vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT; ++ evh->vlan_tag = hton16(vlan_tag); ++ rc |= PKTPRIO_UPD; ++ } ++ } else if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) { ++ uint8 *ip_body = pktdata + sizeof(struct ether_header); ++ uint8 tos_tc = IP_TOS46(ip_body); ++ priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); ++ rc |= PKTPRIO_DSCP; ++ } ++ ++ ASSERT(priority >= 0 && priority <= MAXPRIO); ++ PKTSETPRIO(pkt, priority); ++ return (rc | priority); ++} ++ ++ ++static char bcm_undeferrstr[32]; ++static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE; ++ ++/* Convert the error codes into related error strings */ ++const char * ++bcmerrorstr(int bcmerror) ++{ ++ /* check if someone added a bcmerror code but forgot to add errorstring */ ++ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1)); ++ ++ if (bcmerror > 0 || bcmerror < BCME_LAST) { ++ snprintf(bcm_undeferrstr, sizeof(bcm_undeferrstr), "Undefined error %d", bcmerror); ++ return bcm_undeferrstr; ++ } ++ ++ ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN); ++ ++ return bcmerrorstrtable[-bcmerror]; ++} ++ ++ ++ ++/* iovar table lookup */ ++const bcm_iovar_t* ++bcm_iovar_lookup(const bcm_iovar_t *table, const char *name) ++{ ++ const bcm_iovar_t *vi; ++ const char *lookup_name; ++ ++ /* skip any ':' delimited option prefixes */ ++ lookup_name = strrchr(name, ':'); ++ if (lookup_name != NULL) ++ lookup_name++; ++ else ++ lookup_name = name; ++ ++ ASSERT(table != NULL); ++ ++ for (vi = table; vi->name; vi++) { ++ if (!strcmp(vi->name, lookup_name)) ++ return vi; ++ } ++ /* ran to end of table */ ++ ++ return NULL; /* var name not found */ ++} ++ ++int ++bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set) ++{ ++ int bcmerror = 0; ++ ++ /* length check on io buf */ ++ switch (vi->type) { ++ case IOVT_BOOL: ++ case IOVT_INT8: ++ case IOVT_INT16: ++ case IOVT_INT32: ++ case IOVT_UINT8: ++ case IOVT_UINT16: ++ case IOVT_UINT32: ++ /* all integers are int32 sized args at the ioctl interface */ ++ if (len < (int)sizeof(int)) { ++ bcmerror = BCME_BUFTOOSHORT; ++ } ++ break; ++ ++ case IOVT_BUFFER: ++ /* buffer must meet minimum length requirement */ ++ if (len < vi->minlen) { ++ bcmerror = BCME_BUFTOOSHORT; ++ } ++ break; ++ ++ case IOVT_VOID: ++ if (!set) { ++ /* Cannot return nil... */ ++ bcmerror = BCME_UNSUPPORTED; ++ } else if (len) { ++ /* Set is an action w/o parameters */ ++ bcmerror = BCME_BUFTOOLONG; ++ } ++ break; ++ ++ default: ++ /* unknown type for length check in iovar info */ ++ ASSERT(0); ++ bcmerror = BCME_UNSUPPORTED; ++ } ++ ++ return bcmerror; ++} ++ ++#endif /* BCMDRIVER */ ++ ++ ++/******************************************************************************* ++ * crc8 ++ * ++ * Computes a crc8 over the input data using the polynomial: ++ * ++ * x^8 + x^7 +x^6 + x^4 + x^2 + 1 ++ * ++ * The caller provides the initial value (either CRC8_INIT_VALUE ++ * or the previous returned value) to allow for processing of ++ * discontiguous blocks of data. When generating the CRC the ++ * caller is responsible for complementing the final return value ++ * and inserting it into the byte stream. When checking, a final ++ * return value of CRC8_GOOD_VALUE indicates a valid CRC. ++ * ++ * Reference: Dallas Semiconductor Application Note 27 ++ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", ++ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., ++ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt ++ * ++ * **************************************************************************** ++ */ ++ ++static const uint8 crc8_table[256] = { ++ 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, ++ 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, ++ 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, ++ 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, ++ 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, ++ 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, ++ 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, ++ 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, ++ 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, ++ 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, ++ 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, ++ 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, ++ 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, ++ 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, ++ 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, ++ 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, ++ 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, ++ 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, ++ 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, ++ 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, ++ 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, ++ 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, ++ 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, ++ 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, ++ 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, ++ 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, ++ 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, ++ 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, ++ 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, ++ 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, ++ 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, ++ 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F ++}; ++ ++#define CRC_INNER_LOOP(n, c, x) \ ++ (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] ++ ++uint8 ++hndcrc8( ++ uint8 *pdata, /* pointer to array of data to process */ ++ uint nbytes, /* number of input data bytes to process */ ++ uint8 crc /* either CRC8_INIT_VALUE or previous return value */ ++) ++{ ++ /* hard code the crc loop instead of using CRC_INNER_LOOP macro ++ * to avoid the undefined and unnecessary (uint8 >> 8) operation. ++ */ ++ while (nbytes-- > 0) ++ crc = crc8_table[(crc ^ *pdata++) & 0xff]; ++ ++ return crc; ++} ++ ++/******************************************************************************* ++ * crc16 ++ * ++ * Computes a crc16 over the input data using the polynomial: ++ * ++ * x^16 + x^12 +x^5 + 1 ++ * ++ * The caller provides the initial value (either CRC16_INIT_VALUE ++ * or the previous returned value) to allow for processing of ++ * discontiguous blocks of data. When generating the CRC the ++ * caller is responsible for complementing the final return value ++ * and inserting it into the byte stream. When checking, a final ++ * return value of CRC16_GOOD_VALUE indicates a valid CRC. ++ * ++ * Reference: Dallas Semiconductor Application Note 27 ++ * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", ++ * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., ++ * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt ++ * ++ * **************************************************************************** ++ */ ++ ++static const uint16 crc16_table[256] = { ++ 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, ++ 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, ++ 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, ++ 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, ++ 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, ++ 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, ++ 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, ++ 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, ++ 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, ++ 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, ++ 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, ++ 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, ++ 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, ++ 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, ++ 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, ++ 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, ++ 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, ++ 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, ++ 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, ++ 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, ++ 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, ++ 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, ++ 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, ++ 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, ++ 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, ++ 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, ++ 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, ++ 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, ++ 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, ++ 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, ++ 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, ++ 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 ++}; ++ ++uint16 ++hndcrc16( ++ uint8 *pdata, /* pointer to array of data to process */ ++ uint nbytes, /* number of input data bytes to process */ ++ uint16 crc /* either CRC16_INIT_VALUE or previous return value */ ++) ++{ ++ while (nbytes-- > 0) ++ CRC_INNER_LOOP(16, crc, *pdata++); ++ return crc; ++} ++ ++static const uint32 crc32_table[256] = { ++ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, ++ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, ++ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, ++ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, ++ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, ++ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, ++ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, ++ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, ++ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, ++ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, ++ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, ++ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, ++ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, ++ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, ++ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, ++ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, ++ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, ++ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, ++ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, ++ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, ++ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, ++ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, ++ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, ++ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, ++ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, ++ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, ++ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, ++ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, ++ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, ++ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, ++ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, ++ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, ++ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, ++ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, ++ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, ++ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, ++ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, ++ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, ++ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, ++ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, ++ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, ++ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, ++ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, ++ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, ++ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, ++ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, ++ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, ++ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, ++ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, ++ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, ++ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, ++ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, ++ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, ++ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, ++ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, ++ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, ++ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, ++ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, ++ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, ++ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, ++ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, ++ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, ++ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, ++ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D ++}; ++ ++/* ++ * crc input is CRC32_INIT_VALUE for a fresh start, or previous return value if ++ * accumulating over multiple pieces. ++ */ ++uint32 ++hndcrc32(uint8 *pdata, uint nbytes, uint32 crc) ++{ ++ uint8 *pend; ++ pend = pdata + nbytes; ++ while (pdata < pend) ++ CRC_INNER_LOOP(32, crc, *pdata++); ++ ++ return crc; ++} ++ ++#ifdef notdef ++#define CLEN 1499 /* CRC Length */ ++#define CBUFSIZ (CLEN+4) ++#define CNBUFS 5 /* # of bufs */ ++ ++void ++testcrc32(void) ++{ ++ uint j, k, l; ++ uint8 *buf; ++ uint len[CNBUFS]; ++ uint32 crcr; ++ uint32 crc32tv[CNBUFS] = ++ {0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110}; ++ ++ ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL); ++ ++ /* step through all possible alignments */ ++ for (l = 0; l <= 4; l++) { ++ for (j = 0; j < CNBUFS; j++) { ++ len[j] = CLEN; ++ for (k = 0; k < len[j]; k++) ++ *(buf + j*CBUFSIZ + (k+l)) = (j+k) & 0xff; ++ } ++ ++ for (j = 0; j < CNBUFS; j++) { ++ crcr = crc32(buf + j*CBUFSIZ + l, len[j], CRC32_INIT_VALUE); ++ ASSERT(crcr == crc32tv[j]); ++ } ++ } ++ ++ MFREE(buf, CBUFSIZ*CNBUFS); ++ return; ++} ++#endif /* notdef */ ++ ++/* ++ * Advance from the current 1-byte tag/1-byte length/variable-length value ++ * triple, to the next, returning a pointer to the next. ++ * If the current or next TLV is invalid (does not fit in given buffer length), ++ * NULL is returned. ++ * *buflen is not modified if the TLV elt parameter is invalid, or is decremented ++ * by the TLV parameter's length if it is valid. ++ */ ++bcm_tlv_t * ++bcm_next_tlv(bcm_tlv_t *elt, int *buflen) ++{ ++ int len; ++ ++ /* validate current elt */ ++ if (!bcm_valid_tlv(elt, *buflen)) ++ return NULL; ++ ++ /* advance to next elt */ ++ len = elt->len; ++ elt = (bcm_tlv_t*)(elt->data + len); ++ *buflen -= (TLV_HDR_LEN + len); ++ ++ /* validate next elt */ ++ if (!bcm_valid_tlv(elt, *buflen)) ++ return NULL; ++ ++ return elt; ++} ++ ++/* ++ * Traverse a string of 1-byte tag/1-byte length/variable-length value ++ * triples, returning a pointer to the substring whose first element ++ * matches tag ++ */ ++bcm_tlv_t * ++bcm_parse_tlvs(void *buf, int buflen, uint key) ++{ ++ bcm_tlv_t *elt; ++ int totlen; ++ ++ elt = (bcm_tlv_t*)buf; ++ totlen = buflen; ++ ++ /* find tagged parameter */ ++ while (totlen >= TLV_HDR_LEN) { ++ int len = elt->len; ++ ++ /* validate remaining totlen */ ++ if ((elt->id == key) && ++ (totlen >= (len + TLV_HDR_LEN))) ++ return (elt); ++ ++ elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); ++ totlen -= (len + TLV_HDR_LEN); ++ } ++ ++ return NULL; ++} ++ ++/* ++ * Traverse a string of 1-byte tag/1-byte length/variable-length value ++ * triples, returning a pointer to the substring whose first element ++ * matches tag. Stop parsing when we see an element whose ID is greater ++ * than the target key. ++ */ ++bcm_tlv_t * ++bcm_parse_ordered_tlvs(void *buf, int buflen, uint key) ++{ ++ bcm_tlv_t *elt; ++ int totlen; ++ ++ elt = (bcm_tlv_t*)buf; ++ totlen = buflen; ++ ++ /* find tagged parameter */ ++ while (totlen >= TLV_HDR_LEN) { ++ uint id = elt->id; ++ int len = elt->len; ++ ++ /* Punt if we start seeing IDs > than target key */ ++ if (id > key) ++ return (NULL); ++ ++ /* validate remaining totlen */ ++ if ((id == key) && ++ (totlen >= (len + TLV_HDR_LEN))) ++ return (elt); ++ ++ elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); ++ totlen -= (len + TLV_HDR_LEN); ++ } ++ return NULL; ++} ++ ++#if defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \ ++ defined(DHD_DEBUG) ++int ++bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len) ++{ ++ int i; ++ char* p = buf; ++ char hexstr[16]; ++ int slen = 0, nlen = 0; ++ uint32 bit; ++ const char* name; ++ ++ if (len < 2 || !buf) ++ return 0; ++ ++ buf[0] = '\0'; ++ ++ for (i = 0; flags != 0; i++) { ++ bit = bd[i].bit; ++ name = bd[i].name; ++ if (bit == 0 && flags != 0) { ++ /* print any unnamed bits */ ++ snprintf(hexstr, 16, "0x%X", flags); ++ name = hexstr; ++ flags = 0; /* exit loop */ ++ } else if ((flags & bit) == 0) ++ continue; ++ flags &= ~bit; ++ nlen = strlen(name); ++ slen += nlen; ++ /* count btwn flag space */ ++ if (flags != 0) ++ slen += 1; ++ /* need NULL char as well */ ++ if (len <= slen) ++ break; ++ /* copy NULL char but don't count it */ ++ strncpy(p, name, nlen + 1); ++ p += nlen; ++ /* copy btwn flag space and NULL char */ ++ if (flags != 0) ++ p += snprintf(p, 2, " "); ++ } ++ ++ /* indicate the str was too short */ ++ if (flags != 0) { ++ if (len < 2) ++ p -= 2 - len; /* overwrite last char */ ++ p += snprintf(p, 2, ">"); ++ } ++ ++ return (int)(p - buf); ++} ++ ++/* print bytes formatted as hex to a string. return the resulting string length */ ++int ++bcm_format_hex(char *str, const void *bytes, int len) ++{ ++ int i; ++ char *p = str; ++ const uint8 *src = (const uint8*)bytes; ++ ++ for (i = 0; i < len; i++) { ++ p += snprintf(p, 3, "%02X", *src); ++ src++; ++ } ++ return (int)(p - str); ++} ++#endif ++ ++/* pretty hex print a contiguous buffer */ ++void ++prhex(const char *msg, uchar *buf, uint nbytes) ++{ ++ char line[128], *p; ++ int len = sizeof(line); ++ int nchar; ++ uint i; ++ ++ if (msg && (msg[0] != '\0')) ++ AP6210_DEBUG("%s:\n", msg); ++ ++ p = line; ++ for (i = 0; i < nbytes; i++) { ++ if (i % 16 == 0) { ++ nchar = snprintf(p, len, " %04d: ", i); /* line prefix */ ++ p += nchar; ++ len -= nchar; ++ } ++ if (len > 0) { ++ nchar = snprintf(p, len, "%02x ", buf[i]); ++ p += nchar; ++ len -= nchar; ++ } ++ ++ if (i % 16 == 15) { ++ AP6210_DEBUG("%s\n", line); /* flush line */ ++ p = line; ++ len = sizeof(line); ++ } ++ } ++ ++ /* flush last partial line */ ++ if (p != line) ++ AP6210_DUMP("%s\n", line); ++} ++ ++static const char *crypto_algo_names[] = { ++ "NONE", ++ "WEP1", ++ "TKIP", ++ "WEP128", ++ "AES_CCM", ++ "AES_OCB_MSDU", ++ "AES_OCB_MPDU", ++ "NALG" ++ "UNDEF", ++ "UNDEF", ++ "UNDEF", ++#ifdef BCMWAPI_WPI ++ "WAPI", ++#endif /* BCMWAPI_WPI */ ++ "UNDEF" ++}; ++ ++const char * ++bcm_crypto_algo_name(uint algo) ++{ ++ return (algo < ARRAYSIZE(crypto_algo_names)) ? crypto_algo_names[algo] : "ERR"; ++} ++ ++ ++char * ++bcm_chipname(uint chipid, char *buf, uint len) ++{ ++ const char *fmt; ++ ++ fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x"; ++ snprintf(buf, len, fmt, chipid); ++ return buf; ++} ++ ++/* Produce a human-readable string for boardrev */ ++char * ++bcm_brev_str(uint32 brev, char *buf) ++{ ++ if (brev < 0x100) ++ snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf); ++ else ++ snprintf(buf, 8, "%c%03x", ((brev & 0xf000) == 0x1000) ? 'P' : 'A', brev & 0xfff); ++ ++ return (buf); ++} ++ ++#define BUFSIZE_TODUMP_ATONCE 512 /* Buffer size */ ++ ++/* dump large strings to console */ ++void ++printbig(char *buf) ++{ ++ uint len, max_len; ++ char c; ++ ++ len = strlen(buf); ++ ++ max_len = BUFSIZE_TODUMP_ATONCE; ++ ++ while (len > max_len) { ++ c = buf[max_len]; ++ buf[max_len] = '\0'; ++ AP6210_DUMP("%s", buf); ++ buf[max_len] = c; ++ ++ buf += max_len; ++ len -= max_len; ++ } ++ /* print the remaining string */ ++ AP6210_DUMP("%s\n", buf); ++ return; ++} ++ ++/* routine to dump fields in a fileddesc structure */ ++uint ++bcmdumpfields(bcmutl_rdreg_rtn read_rtn, void *arg0, uint arg1, struct fielddesc *fielddesc_array, ++ char *buf, uint32 bufsize) ++{ ++ uint filled_len; ++ int len; ++ struct fielddesc *cur_ptr; ++ ++ filled_len = 0; ++ cur_ptr = fielddesc_array; ++ ++ while (bufsize > 1) { ++ if (cur_ptr->nameandfmt == NULL) ++ break; ++ len = snprintf(buf, bufsize, cur_ptr->nameandfmt, ++ read_rtn(arg0, arg1, cur_ptr->offset)); ++ /* check for snprintf overflow or error */ ++ if (len < 0 || (uint32)len >= bufsize) ++ len = bufsize - 1; ++ buf += len; ++ bufsize -= len; ++ filled_len += len; ++ cur_ptr++; ++ } ++ return filled_len; ++} ++ ++uint ++bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) ++{ ++ uint len; ++ ++ len = strlen(name) + 1; ++ ++ if ((len + datalen) > buflen) ++ return 0; ++ ++ strncpy(buf, name, buflen); ++ ++ /* append data onto the end of the name string */ ++ memcpy(&buf[len], data, datalen); ++ len += datalen; ++ ++ return len; ++} ++ ++/* Quarter dBm units to mW ++ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 ++ * Table is offset so the last entry is largest mW value that fits in ++ * a uint16. ++ */ ++ ++#define QDBM_OFFSET 153 /* Offset for first entry */ ++#define QDBM_TABLE_LEN 40 /* Table size */ ++ ++/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. ++ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 ++ */ ++#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ ++ ++/* Largest mW value that will round down to the last table entry, ++ * QDBM_OFFSET + QDBM_TABLE_LEN-1. ++ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. ++ */ ++#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ ++ ++static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { ++/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ ++/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, ++/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, ++/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, ++/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, ++/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 ++}; ++ ++uint16 ++bcm_qdbm_to_mw(uint8 qdbm) ++{ ++ uint factor = 1; ++ int idx = qdbm - QDBM_OFFSET; ++ ++ if (idx >= QDBM_TABLE_LEN) { ++ /* clamp to max uint16 mW value */ ++ return 0xFFFF; ++ } ++ ++ /* scale the qdBm index up to the range of the table 0-40 ++ * where an offset of 40 qdBm equals a factor of 10 mW. ++ */ ++ while (idx < 0) { ++ idx += 40; ++ factor *= 10; ++ } ++ ++ /* return the mW value scaled down to the correct factor of 10, ++ * adding in factor/2 to get proper rounding. ++ */ ++ return ((nqdBm_to_mW_map[idx] + factor/2) / factor); ++} ++ ++uint8 ++bcm_mw_to_qdbm(uint16 mw) ++{ ++ uint8 qdbm; ++ int offset; ++ uint mw_uint = mw; ++ uint boundary; ++ ++ /* handle boundary case */ ++ if (mw_uint <= 1) ++ return 0; ++ ++ offset = QDBM_OFFSET; ++ ++ /* move mw into the range of the table */ ++ while (mw_uint < QDBM_TABLE_LOW_BOUND) { ++ mw_uint *= 10; ++ offset -= 40; ++ } ++ ++ for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) { ++ boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] - ++ nqdBm_to_mW_map[qdbm])/2; ++ if (mw_uint < boundary) break; ++ } ++ ++ qdbm += (uint8)offset; ++ ++ return (qdbm); ++} ++ ++ ++uint ++bcm_bitcount(uint8 *bitmap, uint length) ++{ ++ uint bitcount = 0, i; ++ uint8 tmp; ++ for (i = 0; i < length; i++) { ++ tmp = bitmap[i]; ++ while (tmp) { ++ bitcount++; ++ tmp &= (tmp - 1); ++ } ++ } ++ return bitcount; ++} ++ ++#ifdef BCMDRIVER ++ ++/* Initialization of bcmstrbuf structure */ ++void ++bcm_binit(struct bcmstrbuf *b, char *buf, uint size) ++{ ++ b->origsize = b->size = size; ++ b->origbuf = b->buf = buf; ++} ++ ++/* Buffer sprintf wrapper to guard against buffer overflow */ ++int ++bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...) ++{ ++ va_list ap; ++ int r; ++ ++ va_start(ap, fmt); ++ ++ r = vsnprintf(b->buf, b->size, fmt, ap); ++ ++ /* Non Ansi C99 compliant returns -1, ++ * Ansi compliant return r >= b->size, ++ * bcmstdlib returns 0, handle all ++ */ ++ /* r == 0 is also the case when strlen(fmt) is zero. ++ * typically the case when "" is passed as argument. ++ */ ++ if ((r == -1) || (r >= (int)b->size)) { ++ b->size = 0; ++ } else { ++ b->size -= r; ++ b->buf += r; ++ } ++ ++ va_end(ap); ++ ++ return r; ++} ++ ++void ++bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len) ++{ ++ int i; ++ ++ if (msg != NULL && msg[0] != '\0') ++ bcm_bprintf(b, "%s", msg); ++ for (i = 0; i < len; i ++) ++ bcm_bprintf(b, "%02X", buf[i]); ++ if (newline) ++ bcm_bprintf(b, "\n"); ++} ++ ++void ++bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount) ++{ ++ int i; ++ ++ for (i = 0; i < num_bytes; i++) { ++ num[i] += amount; ++ if (num[i] >= amount) ++ break; ++ amount = 1; ++ } ++} ++ ++int ++bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes) ++{ ++ int i; ++ ++ for (i = nbytes - 1; i >= 0; i--) { ++ if (arg1[i] != arg2[i]) ++ return (arg1[i] - arg2[i]); ++ } ++ return 0; ++} ++ ++void ++bcm_print_bytes(const char *name, const uchar *data, int len) ++{ ++ int i; ++ int per_line = 0; ++ ++ AP6210_DEBUG("%s: %d \n", name ? name : "", len); ++ for (i = 0; i < len; i++) { ++ AP6210_DUMP("%02x ", *data++); ++ per_line++; ++ if (per_line == 16) { ++ per_line = 0; ++ AP6210_DUMP("\n"); ++ } ++ } ++ AP6210_DUMP("\n"); ++} ++#if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \ ++ defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) ++#define SSID_FMT_BUF_LEN ((4 * DOT11_MAX_SSID_LEN) + 1) ++ ++int ++bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len) ++{ ++ uint i, c; ++ char *p = buf; ++ char *endp = buf + SSID_FMT_BUF_LEN; ++ ++ if (ssid_len > DOT11_MAX_SSID_LEN) ssid_len = DOT11_MAX_SSID_LEN; ++ ++ for (i = 0; i < ssid_len; i++) { ++ c = (uint)ssid[i]; ++ if (c == '\\') { ++ *p++ = '\\'; ++ *p++ = '\\'; ++ } else if (bcm_isprint((uchar)c)) { ++ *p++ = (char)c; ++ } else { ++ p += snprintf(p, (endp - p), "\\x%02X", c); ++ } ++ } ++ *p = '\0'; ++ ASSERT(p < endp); ++ ++ return (int)(p - buf); ++} ++#endif ++ ++#endif /* BCMDRIVER */ ++ ++/* ++ * ProcessVars:Takes a buffer of "=\n" lines read from a file and ending in a NUL. ++ * also accepts nvram files which are already in the format of =\0\=\0 ++ * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs. ++ * Shortens buffer as needed and pads with NULs. End of buffer is marked by two NULs. ++*/ ++ ++unsigned int ++process_nvram_vars(char *varbuf, unsigned int len) ++{ ++ char *dp; ++ bool findNewline; ++ int column; ++ unsigned int buf_len, n; ++ unsigned int pad = 0; ++ ++ dp = varbuf; ++ ++ findNewline = FALSE; ++ column = 0; ++ ++ for (n = 0; n < len; n++) { ++ if (varbuf[n] == '\r') ++ continue; ++ if (findNewline && varbuf[n] != '\n') ++ continue; ++ findNewline = FALSE; ++ if (varbuf[n] == '#') { ++ findNewline = TRUE; ++ continue; ++ } ++ if (varbuf[n] == '\n') { ++ if (column == 0) ++ continue; ++ *dp++ = 0; ++ column = 0; ++ continue; ++ } ++ *dp++ = varbuf[n]; ++ column++; ++ } ++ buf_len = (unsigned int)(dp - varbuf); ++ if (buf_len % 4) { ++ pad = 4 - buf_len % 4; ++ if (pad && (buf_len + pad <= len)) { ++ buf_len += pad; ++ } ++ } ++ ++ while (dp < varbuf + n) ++ *dp++ = 0; ++ ++ return buf_len; ++} +diff --git a/drivers/net/wireless/ap6210/bcmwifi_channels.c b/drivers/net/wireless/ap6210/bcmwifi_channels.c +new file mode 100755 +index 0000000..6b5b0a3 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/bcmwifi_channels.c +@@ -0,0 +1,1179 @@ ++/* ++ * Misc utility routines used by kernel or app-level. ++ * Contents are wifi-specific, used by any kernel or app-level ++ * software that might want wifi things as it grows. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * $Id: bcmwifi_channels.c 309193 2012-01-19 00:03:57Z $ ++ */ ++ ++#include ++#include ++ ++#ifdef BCMDRIVER ++#include ++#include ++#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) ++#define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) ++#else ++#include ++#include ++#include ++#ifndef ASSERT ++#define ASSERT(exp) ++#endif ++#endif /* BCMDRIVER */ ++ ++#ifdef _bcmwifi_c_ ++/* temporary for transitional compatibility */ ++#include ++#else ++#include ++#endif ++ ++#if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL)) ++#include /* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */ ++#endif ++ ++#ifndef D11AC_IOTYPES ++ ++/* Definitions for legacy Chanspec type */ ++ ++/* Chanspec ASCII representation: ++ * ++ * digit [AB] [N] [UL] ++ * ++ * : channel number of the 10MHz or 20MHz channel, ++ * or control sideband channel of 40MHz channel. ++ * : A for 5GHz, B for 2.4GHz ++ * : N for 10MHz, nothing for 20MHz or 40MHz ++ * (ctl-sideband spec implies 40MHz) ++ * : U for upper, L for lower ++ * ++ * may be omitted on input, and will be assumed to be ++ * 2.4GHz if channel number <= 14. ++ * ++ * Examples: ++ * 8 -> 2.4GHz channel 8, 20MHz ++ * 8b -> 2.4GHz channel 8, 20MHz ++ * 8l -> 2.4GHz channel 8, 40MHz, lower ctl sideband ++ * 8a -> 5GHz channel 8 (low 5 GHz band), 20MHz ++ * 36 -> 5GHz channel 36, 20MHz ++ * 36l -> 5GHz channel 36, 40MHz, lower ctl sideband ++ * 40u -> 5GHz channel 40, 40MHz, upper ctl sideband ++ * 180n -> channel 180, 10MHz ++ */ ++ ++ ++/* given a chanspec and a string buffer, format the chanspec as a ++ * string, and return the original pointer a. ++ * Min buffer length must be CHANSPEC_STR_LEN. ++ * On error return NULL ++ */ ++char * ++wf_chspec_ntoa(chanspec_t chspec, char *buf) ++{ ++ const char *band, *bw, *sb; ++ uint channel; ++ ++ band = ""; ++ bw = ""; ++ sb = ""; ++ channel = CHSPEC_CHANNEL(chspec); ++ /* check for non-default band spec */ ++ if ((CHSPEC_IS2G(chspec) && channel > CH_MAX_2G_CHANNEL) || ++ (CHSPEC_IS5G(chspec) && channel <= CH_MAX_2G_CHANNEL)) ++ band = (CHSPEC_IS2G(chspec)) ? "b" : "a"; ++ if (CHSPEC_IS40(chspec)) { ++ if (CHSPEC_SB_UPPER(chspec)) { ++ sb = "u"; ++ channel += CH_10MHZ_APART; ++ } else { ++ sb = "l"; ++ channel -= CH_10MHZ_APART; ++ } ++ } else if (CHSPEC_IS10(chspec)) { ++ bw = "n"; ++ } ++ ++ /* Outputs a max of 6 chars including '\0' */ ++ snprintf(buf, 6, "%d%s%s%s", channel, band, bw, sb); ++ return (buf); ++} ++ ++/* given a chanspec string, convert to a chanspec. ++ * On error return 0 ++ */ ++chanspec_t ++wf_chspec_aton(const char *a) ++{ ++ char *endp = NULL; ++ uint channel, band, bw, ctl_sb; ++ char c; ++ ++ channel = strtoul(a, &endp, 10); ++ ++ /* check for no digits parsed */ ++ if (endp == a) ++ return 0; ++ ++ if (channel > MAXCHANNEL) ++ return 0; ++ ++ band = ((channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); ++ bw = WL_CHANSPEC_BW_20; ++ ctl_sb = WL_CHANSPEC_CTL_SB_NONE; ++ ++ a = endp; ++ ++ c = tolower(a[0]); ++ if (c == '\0') ++ goto done; ++ ++ /* parse the optional ['A' | 'B'] band spec */ ++ if (c == 'a' || c == 'b') { ++ band = (c == 'a') ? WL_CHANSPEC_BAND_5G : WL_CHANSPEC_BAND_2G; ++ a++; ++ c = tolower(a[0]); ++ if (c == '\0') ++ goto done; ++ } ++ ++ /* parse bandwidth 'N' (10MHz) or 40MHz ctl sideband ['L' | 'U'] */ ++ if (c == 'n') { ++ bw = WL_CHANSPEC_BW_10; ++ } else if (c == 'l') { ++ bw = WL_CHANSPEC_BW_40; ++ ctl_sb = WL_CHANSPEC_CTL_SB_LOWER; ++ /* adjust channel to center of 40MHz band */ ++ if (channel <= (MAXCHANNEL - CH_20MHZ_APART)) ++ channel += CH_10MHZ_APART; ++ else ++ return 0; ++ } else if (c == 'u') { ++ bw = WL_CHANSPEC_BW_40; ++ ctl_sb = WL_CHANSPEC_CTL_SB_UPPER; ++ /* adjust channel to center of 40MHz band */ ++ if (channel > CH_20MHZ_APART) ++ channel -= CH_10MHZ_APART; ++ else ++ return 0; ++ } else { ++ return 0; ++ } ++ ++done: ++ return (channel | band | bw | ctl_sb); ++} ++ ++/* ++ * Verify the chanspec is using a legal set of parameters, i.e. that the ++ * chanspec specified a band, bw, ctl_sb and channel and that the ++ * combination could be legal given any set of circumstances. ++ * RETURNS: TRUE is the chanspec is malformed, false if it looks good. ++ */ ++bool ++wf_chspec_malformed(chanspec_t chanspec) ++{ ++ /* must be 2G or 5G band */ ++ if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec)) ++ return TRUE; ++ /* must be 20 or 40 bandwidth */ ++ if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec)) ++ return TRUE; ++ ++ /* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */ ++ if (CHSPEC_IS20(chanspec)) { ++ if (!CHSPEC_SB_NONE(chanspec)) ++ return TRUE; ++ } else { ++ if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++/* ++ * This function returns the channel number that control traffic is being sent on, for legacy ++ * channels this is just the channel number, for 40MHZ channels it is the upper or lower 20MHZ ++ * sideband depending on the chanspec selected ++ */ ++uint8 ++wf_chspec_ctlchan(chanspec_t chspec) ++{ ++ uint8 ctl_chan; ++ ++ /* Is there a sideband ? */ ++ if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) { ++ return CHSPEC_CHANNEL(chspec); ++ } else { ++ /* we only support 40MHZ with sidebands */ ++ ASSERT(CHSPEC_BW(chspec) == WL_CHANSPEC_BW_40); ++ /* chanspec channel holds the centre frequency, use that and the ++ * side band information to reconstruct the control channel number ++ */ ++ if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) { ++ /* control chan is the upper 20 MHZ SB of the 40MHZ channel */ ++ ctl_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec)); ++ } else { ++ ASSERT(CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_LOWER); ++ /* control chan is the lower 20 MHZ SB of the 40MHZ channel */ ++ ctl_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec)); ++ } ++ } ++ ++ return ctl_chan; ++} ++ ++chanspec_t ++wf_chspec_ctlchspec(chanspec_t chspec) ++{ ++ chanspec_t ctl_chspec = 0; ++ uint8 channel; ++ ++ ASSERT(!wf_chspec_malformed(chspec)); ++ ++ /* Is there a sideband ? */ ++ if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) { ++ return chspec; ++ } else { ++ if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) { ++ channel = UPPER_20_SB(CHSPEC_CHANNEL(chspec)); ++ } else { ++ channel = LOWER_20_SB(CHSPEC_CHANNEL(chspec)); ++ } ++ ctl_chspec = channel | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE; ++ ctl_chspec |= CHSPEC_BAND(chspec); ++ } ++ return ctl_chspec; ++} ++ ++#else /* D11AC_IOTYPES */ ++ ++/* Definitions for D11AC capable Chanspec type */ ++ ++/* Chanspec ASCII representation with 802.11ac capability: ++ * [ 'g'] ['/' []['/'<1st80channel>'-'<2nd80channel>]] ++ * ++ * : ++ * (optional) 2, 3, 4, 5 for 2.4GHz, 3GHz, 4GHz, and 5GHz respectively. ++ * Default value is 2g if channel <= 14, otherwise 5g. ++ * : ++ * channel number of the 5MHz, 10MHz, 20MHz channel, ++ * or primary channel of 40MHz, 80MHz, 160MHz, or 80+80MHz channel. ++ * : ++ * (optional) 5, 10, 20, 40, 80, 160, or 80+80. Default value is 20. ++ * : ++ * (only for 2.4GHz band 40MHz) U for upper sideband primary, L for lower. ++ * ++ * For 2.4GHz band 40MHz channels, the same primary channel may be the ++ * upper sideband for one 40MHz channel, and the lower sideband for an ++ * overlapping 40MHz channel. The U/L disambiguates which 40MHz channel ++ * is being specified. ++ * ++ * For 40MHz in the 5GHz band and all channel bandwidths greater than ++ * 40MHz, the U/L specificaion is not allowed since the channels are ++ * non-overlapping and the primary sub-band is derived from its ++ * position in the wide bandwidth channel. ++ * ++ * <1st80Channel>: ++ * <2nd80Channel>: ++ * Required for 80+80, otherwise not allowed. ++ * Specifies the center channel of the first and second 80MHz band. ++ * ++ * In its simplest form, it is a 20MHz channel number, with the implied band ++ * of 2.4GHz if channel number <= 14, and 5GHz otherwise. ++ * ++ * To allow for backward compatibility with scripts, the old form for ++ * 40MHz channels is also allowed: ++ * ++ * : ++ * primary channel of 40MHz, channel <= 14 is 2GHz, otherwise 5GHz ++ * : ++ * "U" for upper, "L" for lower (or lower case "u" "l") ++ * ++ * 5 GHz Examples: ++ * Chanspec BW Center Ch Channel Range Primary Ch ++ * 5g8 20MHz 8 - - ++ * 52 20MHz 52 - - ++ * 52/40 40MHz 54 52-56 52 ++ * 56/40 40MHz 54 52-56 56 ++ * 52/80 80MHz 58 52-64 52 ++ * 56/80 80MHz 58 52-64 56 ++ * 60/80 80MHz 58 52-64 60 ++ * 64/80 80MHz 58 52-64 64 ++ * 52/160 160MHz 50 36-64 52 ++ * 36/160 160MGz 50 36-64 36 ++ * 36/80+80/42-106 80+80MHz 42,106 36-48,100-112 36 ++ * ++ * 2 GHz Examples: ++ * Chanspec BW Center Ch Channel Range Primary Ch ++ * 2g8 20MHz 8 - - ++ * 8 20MHz 8 - - ++ * 6 20MHz 6 - - ++ * 6/40l 40MHz 8 6-10 6 ++ * 6l 40MHz 8 6-10 6 ++ * 6/40u 40MHz 4 2-6 6 ++ * 6u 40MHz 4 2-6 6 ++ */ ++ ++/* bandwidth ASCII string */ ++static const char *wf_chspec_bw_str[] = ++{ ++ "5", ++ "10", ++ "20", ++ "40", ++ "80", ++ "160", ++ "80+80", ++ "na" ++}; ++ ++static const uint8 wf_chspec_bw_mhz[] = ++{5, 10, 20, 40, 80, 160, 160}; ++ ++#define WF_NUM_BW \ ++ (sizeof(wf_chspec_bw_mhz)/sizeof(uint8)) ++ ++/* 40MHz channels in 5GHz band */ ++static const uint8 wf_5g_40m_chans[] = ++{38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159}; ++#define WF_NUM_5G_40M_CHANS \ ++ (sizeof(wf_5g_40m_chans)/sizeof(uint8)) ++ ++/* 80MHz channels in 5GHz band */ ++static const uint8 wf_5g_80m_chans[] = ++{42, 58, 106, 122, 138, 155}; ++#define WF_NUM_5G_80M_CHANS \ ++ (sizeof(wf_5g_80m_chans)/sizeof(uint8)) ++ ++/* 160MHz channels in 5GHz band */ ++static const uint8 wf_5g_160m_chans[] = ++{50, 114}; ++#define WF_NUM_5G_160M_CHANS \ ++ (sizeof(wf_5g_160m_chans)/sizeof(uint8)) ++ ++ ++/* convert bandwidth from chanspec to MHz */ ++static uint ++bw_chspec_to_mhz(chanspec_t chspec) ++{ ++ uint bw; ++ ++ bw = (chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT; ++ return (bw >= WF_NUM_BW ? 0 : wf_chspec_bw_mhz[bw]); ++} ++ ++/* bw in MHz, return the channel count from the center channel to the ++ * the channel at the edge of the band ++ */ ++static uint8 ++center_chan_to_edge(uint bw) ++{ ++ /* edge channels separated by BW - 10MHz on each side ++ * delta from cf to edge is half of that, ++ * MHz to channel num conversion is 5MHz/channel ++ */ ++ return (uint8)(((bw - 20) / 2) / 5); ++} ++ ++/* return channel number of the low edge of the band ++ * given the center channel and BW ++ */ ++static uint8 ++channel_low_edge(uint center_ch, uint bw) ++{ ++ return (uint8)(center_ch - center_chan_to_edge(bw)); ++} ++ ++/* return side band number given center channel and control channel ++ * return -1 on error ++ */ ++static int ++channel_to_sb(uint center_ch, uint ctl_ch, uint bw) ++{ ++ uint lowest = channel_low_edge(center_ch, bw); ++ uint sb; ++ ++ if ((ctl_ch - lowest) % 4) { ++ /* bad ctl channel, not mult 4 */ ++ return -1; ++ } ++ ++ sb = ((ctl_ch - lowest) / 4); ++ ++ /* sb must be a index to a 20MHz channel in range */ ++ if (sb >= (bw / 20)) { ++ /* ctl_ch must have been too high for the center_ch */ ++ return -1; ++ } ++ ++ return sb; ++} ++ ++/* return control channel given center channel and side band */ ++static uint8 ++channel_to_ctl_chan(uint center_ch, uint bw, uint sb) ++{ ++ return (uint8)(channel_low_edge(center_ch, bw) + sb * 4); ++} ++ ++/* return index of 80MHz channel from channel number ++ * return -1 on error ++ */ ++static int ++channel_80mhz_to_id(uint ch) ++{ ++ uint i; ++ for (i = 0; i < WF_NUM_5G_80M_CHANS; i ++) { ++ if (ch == wf_5g_80m_chans[i]) ++ return i; ++ } ++ ++ return -1; ++} ++ ++/* given a chanspec and a string buffer, format the chanspec as a ++ * string, and return the original pointer a. ++ * Min buffer length must be CHANSPEC_STR_LEN. ++ * On error return NULL ++ */ ++char * ++wf_chspec_ntoa(chanspec_t chspec, char *buf) ++{ ++ const char *band; ++ uint ctl_chan; ++ ++ if (wf_chspec_malformed(chspec)) ++ return NULL; ++ ++ band = ""; ++ ++ /* check for non-default band spec */ ++ if ((CHSPEC_IS2G(chspec) && CHSPEC_CHANNEL(chspec) > CH_MAX_2G_CHANNEL) || ++ (CHSPEC_IS5G(chspec) && CHSPEC_CHANNEL(chspec) <= CH_MAX_2G_CHANNEL)) ++ band = (CHSPEC_IS2G(chspec)) ? "2g" : "5g"; ++ ++ /* ctl channel */ ++ ctl_chan = wf_chspec_ctlchan(chspec); ++ ++ /* bandwidth and ctl sideband */ ++ if (CHSPEC_IS20(chspec)) { ++ snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, ctl_chan); ++ } else if (!CHSPEC_IS8080(chspec)) { ++ const char *bw; ++ const char *sb = ""; ++ ++ bw = wf_chspec_bw_str[(chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT]; ++ ++#ifdef CHANSPEC_NEW_40MHZ_FORMAT ++ /* ctl sideband string if needed for 2g 40MHz */ ++ if (CHSPEC_IS40(chspec) && CHSPEC_IS2G(chspec)) { ++ sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l"; ++ } ++ ++ snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, ctl_chan, bw, sb); ++#else ++ /* ctl sideband string instead of BW for 40MHz */ ++ if (CHSPEC_IS40(chspec)) { ++ sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l"; ++ snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, ctl_chan, sb); ++ } else { ++ snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, ctl_chan, bw); ++ } ++#endif /* CHANSPEC_NEW_40MHZ_FORMAT */ ++ ++ } else { ++ /* 80+80 */ ++ uint chan1 = (chspec & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT; ++ uint chan2 = (chspec & WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT; ++ ++ /* convert to channel number */ ++ chan1 = (chan1 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan1] : 0; ++ chan2 = (chan2 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan2] : 0; ++ ++ /* Outputs a max of CHANSPEC_STR_LEN chars including '\0' */ ++ snprintf(buf, CHANSPEC_STR_LEN, "%d/80+80/%d-%d", ctl_chan, chan1, chan2); ++ } ++ ++ return (buf); ++} ++ ++static int ++read_uint(const char **p, unsigned int *num) ++{ ++ unsigned long val; ++ char *endp = NULL; ++ ++ val = strtoul(*p, &endp, 10); ++ /* if endp is the initial pointer value, then a number was not read */ ++ if (endp == *p) ++ return 0; ++ ++ /* advance the buffer pointer to the end of the integer string */ ++ *p = endp; ++ /* return the parsed integer */ ++ *num = (unsigned int)val; ++ ++ return 1; ++} ++ ++/* given a chanspec string, convert to a chanspec. ++ * On error return 0 ++ */ ++chanspec_t ++wf_chspec_aton(const char *a) ++{ ++ chanspec_t chspec; ++ uint chspec_ch, chspec_band, bw, chspec_bw, chspec_sb; ++ uint num, ctl_ch; ++ uint ch1, ch2; ++ char c, sb_ul = '\0'; ++ int i; ++ ++ bw = 20; ++ chspec_sb = 0; ++ chspec_ch = ch1 = ch2 = 0; ++ ++ /* parse channel num or band */ ++ if (!read_uint(&a, &num)) ++ return 0; ++ ++ /* if we are looking at a 'g', then the first number was a band */ ++ c = tolower(a[0]); ++ if (c == 'g') { ++ a ++; /* consume the char */ ++ ++ /* band must be "2" or "5" */ ++ if (num == 2) ++ chspec_band = WL_CHANSPEC_BAND_2G; ++ else if (num == 5) ++ chspec_band = WL_CHANSPEC_BAND_5G; ++ else ++ return 0; ++ ++ /* read the channel number */ ++ if (!read_uint(&a, &ctl_ch)) ++ return 0; ++ ++ c = tolower(a[0]); ++ } ++ else { ++ /* first number is channel, use default for band */ ++ ctl_ch = num; ++ chspec_band = ((ctl_ch <= CH_MAX_2G_CHANNEL) ? ++ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); ++ } ++ ++ if (c == '\0') { ++ /* default BW of 20MHz */ ++ chspec_bw = WL_CHANSPEC_BW_20; ++ goto done_read; ++ } ++ ++ a ++; /* consume the 'u','l', or '/' */ ++ ++ /* check 'u'/'l' */ ++ if (c == 'u' || c == 'l') { ++ sb_ul = c; ++ chspec_bw = WL_CHANSPEC_BW_40; ++ goto done_read; ++ } ++ ++ /* next letter must be '/' */ ++ if (c != '/') ++ return 0; ++ ++ /* read bandwidth */ ++ if (!read_uint(&a, &bw)) ++ return 0; ++ ++ /* convert to chspec value */ ++ if (bw == 20) { ++ chspec_bw = WL_CHANSPEC_BW_20; ++ } else if (bw == 40) { ++ chspec_bw = WL_CHANSPEC_BW_40; ++ } else if (bw == 80) { ++ chspec_bw = WL_CHANSPEC_BW_80; ++ } else if (bw == 160) { ++ chspec_bw = WL_CHANSPEC_BW_160; ++ } else { ++ return 0; ++ } ++ ++ /* So far we have g/ ++ * Can now be followed by u/l if bw = 40, ++ * or '+80' if bw = 80, to make '80+80' bw. ++ */ ++ ++ c = tolower(a[0]); ++ ++ /* if we have a 2g/40 channel, we should have a l/u spec now */ ++ if (chspec_band == WL_CHANSPEC_BAND_2G && bw == 40) { ++ if (c == 'u' || c == 'l') { ++ a ++; /* consume the u/l char */ ++ sb_ul = c; ++ goto done_read; ++ } ++ } ++ ++ /* check for 80+80 */ ++ if (c == '+') { ++ /* 80+80 */ ++ static const char *plus80 = "80/"; ++ ++ /* must be looking at '+80/' ++ * check and consume this string. ++ */ ++ chspec_bw = WL_CHANSPEC_BW_8080; ++ ++ a ++; /* consume the char '+' */ ++ ++ /* consume the '80/' string */ ++ for (i = 0; i < 3; i++) { ++ if (*a++ != *plus80++) { ++ return 0; ++ } ++ } ++ ++ /* read primary 80MHz channel */ ++ if (!read_uint(&a, &ch1)) ++ return 0; ++ ++ /* must followed by '-' */ ++ if (a[0] != '-') ++ return 0; ++ a ++; /* consume the char */ ++ ++ /* read secondary 80MHz channel */ ++ if (!read_uint(&a, &ch2)) ++ return 0; ++ } ++ ++done_read: ++ /* skip trailing white space */ ++ while (a[0] == ' ') { ++ a ++; ++ } ++ ++ /* must be end of string */ ++ if (a[0] != '\0') ++ return 0; ++ ++ /* Now have all the chanspec string parts read; ++ * chspec_band, ctl_ch, chspec_bw, sb_ul, ch1, ch2. ++ * chspec_band and chspec_bw are chanspec values. ++ * Need to convert ctl_ch, sb_ul, and ch1,ch2 into ++ * a center channel (or two) and sideband. ++ */ ++ ++ /* if a sb u/l string was given, just use that, ++ * guaranteed to be bw = 40 by sting parse. ++ */ ++ if (sb_ul != '\0') { ++ if (sb_ul == 'l') { ++ chspec_ch = UPPER_20_SB(ctl_ch); ++ chspec_sb = WL_CHANSPEC_CTL_SB_LLL; ++ } else if (sb_ul == 'u') { ++ chspec_ch = LOWER_20_SB(ctl_ch); ++ chspec_sb = WL_CHANSPEC_CTL_SB_LLU; ++ } ++ } ++ /* if the bw is 20, center and sideband are trivial */ ++ else if (chspec_bw == WL_CHANSPEC_BW_20) { ++ chspec_ch = ctl_ch; ++ chspec_sb = 0; ++ } ++ /* if the bw is 40/80/160, not 80+80, a single method ++ * can be used to to find the center and sideband ++ */ ++ else if (chspec_bw != WL_CHANSPEC_BW_8080) { ++ /* figure out ctl sideband based on ctl channel and bandwidth */ ++ const uint8 *center_ch = NULL; ++ int num_ch = 0; ++ int sb = -1; ++ ++ if (chspec_bw == WL_CHANSPEC_BW_40) { ++ center_ch = wf_5g_40m_chans; ++ num_ch = WF_NUM_5G_40M_CHANS; ++ } else if (chspec_bw == WL_CHANSPEC_BW_80) { ++ center_ch = wf_5g_80m_chans; ++ num_ch = WF_NUM_5G_80M_CHANS; ++ } else if (chspec_bw == WL_CHANSPEC_BW_160) { ++ center_ch = wf_5g_160m_chans; ++ num_ch = WF_NUM_5G_160M_CHANS; ++ } else { ++ return 0; ++ } ++ ++ for (i = 0; i < num_ch; i ++) { ++ sb = channel_to_sb(center_ch[i], ctl_ch, bw); ++ if (sb >= 0) { ++ chspec_ch = center_ch[i]; ++ chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT; ++ break; ++ } ++ } ++ ++ /* check for no matching sb/center */ ++ if (sb < 0) { ++ return 0; ++ } ++ } ++ /* Otherwise, bw is 80+80. Figure out channel pair and sb */ ++ else { ++ int ch1_id = 0, ch2_id = 0; ++ int sb; ++ ++ ch1_id = channel_80mhz_to_id(ch1); ++ ch2_id = channel_80mhz_to_id(ch2); ++ ++ /* validate channels */ ++ if (ch1 >= ch2 || ch1_id < 0 || ch2_id < 0) ++ return 0; ++ ++ /* combined channel in chspec */ ++ chspec_ch = (((uint16)ch1_id << WL_CHANSPEC_CHAN1_SHIFT) | ++ ((uint16)ch2_id << WL_CHANSPEC_CHAN2_SHIFT)); ++ ++ /* figure out ctl sideband */ ++ ++ /* does the primary channel fit with the 1st 80MHz channel ? */ ++ sb = channel_to_sb(ch1, ctl_ch, bw); ++ if (sb < 0) { ++ /* no, so does the primary channel fit with the 2nd 80MHz channel ? */ ++ sb = channel_to_sb(ch2, ctl_ch, bw); ++ if (sb < 0) { ++ /* no match for ctl_ch to either 80MHz center channel */ ++ return 0; ++ } ++ /* sb index is 0-3 for the low 80MHz channel, and 4-7 for ++ * the high 80MHz channel. Add 4 to to shift to high set. ++ */ ++ sb += 4; ++ } ++ ++ chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT; ++ } ++ ++ chspec = (chspec_ch | chspec_band | chspec_bw | chspec_sb); ++ ++ if (wf_chspec_malformed(chspec)) ++ return 0; ++ ++ return chspec; ++} ++ ++/* ++ * Verify the chanspec is using a legal set of parameters, i.e. that the ++ * chanspec specified a band, bw, ctl_sb and channel and that the ++ * combination could be legal given any set of circumstances. ++ * RETURNS: TRUE is the chanspec is malformed, false if it looks good. ++ */ ++bool ++wf_chspec_malformed(chanspec_t chanspec) ++{ ++ uint chspec_bw = CHSPEC_BW(chanspec); ++ uint chspec_ch = CHSPEC_CHANNEL(chanspec); ++ ++ /* must be 2G or 5G band */ ++ if (CHSPEC_IS2G(chanspec)) { ++ /* must be valid bandwidth */ ++ if (chspec_bw != WL_CHANSPEC_BW_20 && ++ chspec_bw != WL_CHANSPEC_BW_40) { ++ return TRUE; ++ } ++ } else if (CHSPEC_IS5G(chanspec)) { ++ if (chspec_bw == WL_CHANSPEC_BW_8080) { ++ uint ch1_id, ch2_id; ++ ++ /* channel number in 80+80 must be in range */ ++ ch1_id = CHSPEC_CHAN1(chanspec); ++ ch2_id = CHSPEC_CHAN2(chanspec); ++ if (ch1_id >= WF_NUM_5G_80M_CHANS || ch2_id >= WF_NUM_5G_80M_CHANS) ++ return TRUE; ++ ++ /* ch2 must be above ch1 for the chanspec */ ++ if (ch2_id <= ch1_id) ++ return TRUE; ++ } else if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40 || ++ chspec_bw == WL_CHANSPEC_BW_80 || chspec_bw == WL_CHANSPEC_BW_160) { ++ ++ if (chspec_ch > MAXCHANNEL) { ++ return TRUE; ++ } ++ } else { ++ /* invalid bandwidth */ ++ return TRUE; ++ } ++ } else { ++ /* must be 2G or 5G band */ ++ return TRUE; ++ } ++ ++ /* side band needs to be consistent with bandwidth */ ++ if (chspec_bw == WL_CHANSPEC_BW_20) { ++ if (CHSPEC_CTL_SB(chanspec) != WL_CHANSPEC_CTL_SB_LLL) ++ return TRUE; ++ } else if (chspec_bw == WL_CHANSPEC_BW_40) { ++ if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LLU) ++ return TRUE; ++ } else if (chspec_bw == WL_CHANSPEC_BW_80) { ++ if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LUU) ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++/* ++ * Verify the chanspec specifies a valid channel according to 802.11. ++ * RETURNS: TRUE if the chanspec is a valid 802.11 channel ++ */ ++bool ++wf_chspec_valid(chanspec_t chanspec) ++{ ++ uint chspec_bw = CHSPEC_BW(chanspec); ++ uint chspec_ch = CHSPEC_CHANNEL(chanspec); ++ ++ if (wf_chspec_malformed(chanspec)) ++ return FALSE; ++ ++ if (CHSPEC_IS2G(chanspec)) { ++ /* must be valid bandwidth and channel range */ ++ if (chspec_bw == WL_CHANSPEC_BW_20) { ++ if (chspec_ch >= 1 && chspec_ch <= 14) ++ return TRUE; ++ } else if (chspec_bw == WL_CHANSPEC_BW_40) { ++ if (chspec_ch >= 3 && chspec_ch <= 11) ++ return TRUE; ++ } ++ } else if (CHSPEC_IS5G(chanspec)) { ++ if (chspec_bw == WL_CHANSPEC_BW_8080) { ++ uint16 ch1, ch2; ++ ++ ch1 = wf_5g_80m_chans[CHSPEC_CHAN1(chanspec)]; ++ ch2 = wf_5g_80m_chans[CHSPEC_CHAN2(chanspec)]; ++ ++ /* the two channels must be separated by more than 80MHz by VHT req, ++ * and ch2 above ch1 for the chanspec ++ */ ++ if (ch2 > ch1 + CH_80MHZ_APART) ++ return TRUE; ++ } else { ++ const uint8 *center_ch; ++ uint num_ch, i; ++ ++ if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40) { ++ center_ch = wf_5g_40m_chans; ++ num_ch = WF_NUM_5G_40M_CHANS; ++ } else if (chspec_bw == WL_CHANSPEC_BW_80) { ++ center_ch = wf_5g_80m_chans; ++ num_ch = WF_NUM_5G_80M_CHANS; ++ } else if (chspec_bw == WL_CHANSPEC_BW_160) { ++ center_ch = wf_5g_160m_chans; ++ num_ch = WF_NUM_5G_160M_CHANS; ++ } else { ++ /* invalid bandwidth */ ++ return FALSE; ++ } ++ ++ /* check for a valid center channel */ ++ if (chspec_bw == WL_CHANSPEC_BW_20) { ++ /* We don't have an array of legal 20MHz 5G channels, but they are ++ * each side of the legal 40MHz channels. Check the chanspec ++ * channel against either side of the 40MHz channels. ++ */ ++ for (i = 0; i < num_ch; i ++) { ++ if (chspec_ch == (uint)LOWER_20_SB(center_ch[i]) || ++ chspec_ch == (uint)UPPER_20_SB(center_ch[i])) ++ break; /* match found */ ++ } ++ ++ if (i == num_ch) { ++ /* check for legacy JP channels on failure */ ++ if (chspec_ch == 34 || chspec_ch == 38 || ++ chspec_ch == 42 || chspec_ch == 46) ++ i = 0; ++ } ++ } else { ++ /* check the chanspec channel to each legal channel */ ++ for (i = 0; i < num_ch; i ++) { ++ if (chspec_ch == center_ch[i]) ++ break; /* match found */ ++ } ++ } ++ ++ if (i < num_ch) { ++ /* match found */ ++ return TRUE; ++ } ++ } ++ } ++ ++ return FALSE; ++} ++ ++/* ++ * This function returns the channel number that control traffic is being sent on, for 20MHz ++ * channels this is just the channel number, for 40MHZ, 80MHz, 160MHz channels it is the 20MHZ ++ * sideband depending on the chanspec selected ++ */ ++uint8 ++wf_chspec_ctlchan(chanspec_t chspec) ++{ ++ uint center_chan; ++ uint bw_mhz; ++ uint sb; ++ ++ ASSERT(!wf_chspec_malformed(chspec)); ++ ++ /* Is there a sideband ? */ ++ if (CHSPEC_IS20(chspec)) { ++ return CHSPEC_CHANNEL(chspec); ++ } else { ++ sb = CHSPEC_CTL_SB(chspec) >> WL_CHANSPEC_CTL_SB_SHIFT; ++ ++ if (CHSPEC_IS8080(chspec)) { ++ bw_mhz = 80; ++ ++ if (sb < 4) { ++ center_chan = CHSPEC_CHAN1(chspec); ++ } ++ else { ++ center_chan = CHSPEC_CHAN2(chspec); ++ sb -= 4; ++ } ++ ++ /* convert from channel index to channel number */ ++ center_chan = wf_5g_80m_chans[center_chan]; ++ } ++ else { ++ bw_mhz = bw_chspec_to_mhz(chspec); ++ center_chan = CHSPEC_CHANNEL(chspec) >> WL_CHANSPEC_CHAN_SHIFT; ++ } ++ ++ return (channel_to_ctl_chan(center_chan, bw_mhz, sb)); ++ } ++} ++ ++/* ++ * This function returns the chanspec of the control channel of a given chanspec ++ */ ++chanspec_t ++wf_chspec_ctlchspec(chanspec_t chspec) ++{ ++ chanspec_t ctl_chspec = chspec; ++ uint8 ctl_chan; ++ ++ ASSERT(!wf_chspec_malformed(chspec)); ++ ++ /* Is there a sideband ? */ ++ if (!CHSPEC_IS20(chspec)) { ++ ctl_chan = wf_chspec_ctlchan(chspec); ++ ctl_chspec = ctl_chan | WL_CHANSPEC_BW_20; ++ ctl_chspec |= CHSPEC_BAND(chspec); ++ } ++ return ctl_chspec; ++} ++ ++/* return chanspec given control channel and bandwidth ++ * return 0 on error ++ */ ++uint16 ++wf_channel2chspec(uint ctl_ch, uint bw) ++{ ++ uint16 chspec; ++ const uint8 *center_ch = NULL; ++ int num_ch = 0; ++ int sb = -1; ++ int i = 0; ++ ++ chspec = ((ctl_ch <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); ++ ++ chspec |= bw; ++ ++ if (bw == WL_CHANSPEC_BW_40) { ++ center_ch = wf_5g_40m_chans; ++ num_ch = WF_NUM_5G_40M_CHANS; ++ bw = 40; ++ } else if (bw == WL_CHANSPEC_BW_80) { ++ center_ch = wf_5g_80m_chans; ++ num_ch = WF_NUM_5G_80M_CHANS; ++ bw = 80; ++ } else if (bw == WL_CHANSPEC_BW_160) { ++ center_ch = wf_5g_160m_chans; ++ num_ch = WF_NUM_5G_160M_CHANS; ++ bw = 160; ++ } else if (bw == WL_CHANSPEC_BW_20) { ++ chspec |= ctl_ch; ++ return chspec; ++ } else { ++ return 0; ++ } ++ ++ for (i = 0; i < num_ch; i ++) { ++ sb = channel_to_sb(center_ch[i], ctl_ch, bw); ++ if (sb >= 0) { ++ chspec |= center_ch[i]; ++ chspec |= (sb << WL_CHANSPEC_CTL_SB_SHIFT); ++ break; ++ } ++ } ++ ++ /* check for no matching sb/center */ ++ if (sb < 0) { ++ return 0; ++ } ++ ++ return chspec; ++} ++#endif /* D11AC_IOTYPES */ ++ ++/* ++ * This function returns the chanspec for the primary 40MHz of an 80MHz channel. ++ * The control sideband specifies the same 20MHz channel that the 80MHz channel is using ++ * as the primary 20MHz channel. ++ */ ++extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec) ++{ ++ chanspec_t chspec40 = chspec; ++ uint center_chan; ++ uint sb; ++ ++ ASSERT(!wf_chspec_malformed(chspec)); ++ ++ if (CHSPEC_IS80(chspec)) { ++ center_chan = CHSPEC_CHANNEL(chspec); ++ sb = CHSPEC_CTL_SB(chspec); ++ ++ if (sb == WL_CHANSPEC_CTL_SB_UL) { ++ /* Primary 40MHz is on upper side */ ++ sb = WL_CHANSPEC_CTL_SB_L; ++ center_chan += CH_20MHZ_APART; ++ } else if (sb == WL_CHANSPEC_CTL_SB_UU) { ++ /* Primary 40MHz is on upper side */ ++ sb = WL_CHANSPEC_CTL_SB_U; ++ center_chan += CH_20MHZ_APART; ++ } else { ++ /* Primary 40MHz is on lower side */ ++ /* sideband bits are the same for LL/LU and L/U */ ++ center_chan -= CH_20MHZ_APART; ++ } ++ ++ /* Create primary 40MHz chanspec */ ++ chspec40 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_40 | ++ sb | center_chan); ++ } ++ ++ return chspec40; ++} ++ ++/* ++ * Return the channel number for a given frequency and base frequency. ++ * The returned channel number is relative to the given base frequency. ++ * If the given base frequency is zero, a base frequency of 5 GHz is assumed for ++ * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz. ++ * ++ * Frequency is specified in MHz. ++ * The base frequency is specified as (start_factor * 500 kHz). ++ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for ++ * 2.4 GHz and 5 GHz bands. ++ * ++ * The returned channel will be in the range [1, 14] in the 2.4 GHz band ++ * and [0, 200] otherwise. ++ * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the ++ * frequency is not a 2.4 GHz channel, or if the frequency is not and even ++ * multiple of 5 MHz from the base frequency to the base plus 1 GHz. ++ * ++ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 ++ */ ++int ++wf_mhz2channel(uint freq, uint start_factor) ++{ ++ int ch = -1; ++ uint base; ++ int offset; ++ ++ /* take the default channel start frequency */ ++ if (start_factor == 0) { ++ if (freq >= 2400 && freq <= 2500) ++ start_factor = WF_CHAN_FACTOR_2_4_G; ++ else if (freq >= 5000 && freq <= 6000) ++ start_factor = WF_CHAN_FACTOR_5_G; ++ } ++ ++ if (freq == 2484 && start_factor == WF_CHAN_FACTOR_2_4_G) ++ return 14; ++ ++ base = start_factor / 2; ++ ++ /* check that the frequency is in 1GHz range of the base */ ++ if ((freq < base) || (freq > base + 1000)) ++ return -1; ++ ++ offset = freq - base; ++ ch = offset / 5; ++ ++ /* check that frequency is a 5MHz multiple from the base */ ++ if (offset != (ch * 5)) ++ return -1; ++ ++ /* restricted channel range check for 2.4G */ ++ if (start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 13)) ++ return -1; ++ ++ return ch; ++} ++ ++/* ++ * Return the center frequency in MHz of the given channel and base frequency. ++ * The channel number is interpreted relative to the given base frequency. ++ * ++ * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise. ++ * The base frequency is specified as (start_factor * 500 kHz). ++ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_4_G, and WF_CHAN_FACTOR_5_G ++ * are defined for 2.4 GHz, 4 GHz, and 5 GHz bands. ++ * The channel range of [1, 14] is only checked for a start_factor of ++ * WF_CHAN_FACTOR_2_4_G (4814 = 2407 * 2). ++ * Odd start_factors produce channels on .5 MHz boundaries, in which case ++ * the answer is rounded down to an integral MHz. ++ * -1 is returned for an out of range channel. ++ * ++ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 ++ */ ++int ++wf_channel2mhz(uint ch, uint start_factor) ++{ ++ int freq; ++ ++ if ((start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 14)) || ++ (ch > 200)) ++ freq = -1; ++ else if ((start_factor == WF_CHAN_FACTOR_2_4_G) && (ch == 14)) ++ freq = 2484; ++ else ++ freq = ch * 5 + start_factor / 2; ++ ++ return freq; ++} +diff --git a/drivers/net/wireless/ap6210/dhd.h b/drivers/net/wireless/ap6210/dhd.h +new file mode 100755 +index 0000000..006a41c +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd.h +@@ -0,0 +1,888 @@ ++/* ++ * Header file describing the internal (inter-module) DHD interfaces. ++ * ++ * Provides type definitions and function prototypes used to link the ++ * DHD OS, bus, and protocol modules. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhd.h 373887 2012-12-10 21:58:02Z $ ++ */ ++ ++/**************** ++ * Common types * ++ */ ++ ++#ifndef _dhd_h_ ++#define _dhd_h_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) ++#include ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ ++/* The kernel threading is sdio-specific */ ++struct task_struct; ++struct sched_param; ++int setScheduler(struct task_struct *p, int policy, struct sched_param *param); ++ ++#define ALL_INTERFACES 0xff ++ ++#include ++#include ++ ++ ++/* Forward decls */ ++struct dhd_bus; ++struct dhd_prot; ++struct dhd_info; ++ ++/* The level of bus communication with the dongle */ ++enum dhd_bus_state { ++ DHD_BUS_DOWN, /* Not ready for frame transfers */ ++ DHD_BUS_LOAD, /* Download access only (CPU reset) */ ++ DHD_BUS_DATA /* Ready for frame transfers */ ++}; ++ ++enum dhd_op_flags { ++/* Firmware requested operation mode */ ++ DHD_FLAG_STA_MODE = BIT(0), /* STA only */ ++ DHD_FLAG_HOSTAP_MODE = BIT(1), /* SOFTAP only */ ++ DHD_FLAG_P2P_MODE = BIT(2), /* P2P Only */ ++ /* STA + P2P */ ++ DHD_FLAG_CONCURR_SINGLE_CHAN_MODE = (DHD_FLAG_STA_MODE | DHD_FLAG_P2P_MODE), ++ DHD_FLAG_CONCURR_MULTI_CHAN_MODE = BIT(4), /* STA + P2P */ ++ /* Current P2P mode for P2P connection */ ++ DHD_FLAG_P2P_GC_MODE = BIT(5), ++ DHD_FLAG_P2P_GO_MODE = BIT(6), ++ DHD_FLAG_MBSS_MODE = BIT(7) /* MBSS in future */ ++}; ++ ++#define MANUFACTRING_FW "WLTEST" ++ ++/* max sequential rxcntl timeouts to set HANG event */ ++#ifndef MAX_CNTL_TIMEOUT ++#define MAX_CNTL_TIMEOUT 2 ++#endif ++ ++#define DHD_SCAN_ASSOC_ACTIVE_TIME 40 /* ms: Embedded default Active setting from DHD */ ++#define DHD_SCAN_UNASSOC_ACTIVE_TIME 80 /* ms: Embedded def. Unassoc Active setting from DHD */ ++#define DHD_SCAN_PASSIVE_TIME 130 /* ms: Embedded default Passive setting from DHD */ ++ ++#ifndef POWERUP_MAX_RETRY ++#define POWERUP_MAX_RETRY 3 /* how many times we retry to power up the chip */ ++#endif ++#ifndef POWERUP_WAIT_MS ++#define POWERUP_WAIT_MS 2000 /* ms: time out in waiting wifi to come up */ ++#endif ++ ++enum dhd_bus_wake_state { ++ WAKE_LOCK_OFF, ++ WAKE_LOCK_PRIV, ++ WAKE_LOCK_DPC, ++ WAKE_LOCK_IOCTL, ++ WAKE_LOCK_DOWNLOAD, ++ WAKE_LOCK_TMOUT, ++ WAKE_LOCK_WATCHDOG, ++ WAKE_LOCK_LINK_DOWN_TMOUT, ++ WAKE_LOCK_PNO_FIND_TMOUT, ++ WAKE_LOCK_SOFTAP_SET, ++ WAKE_LOCK_SOFTAP_STOP, ++ WAKE_LOCK_SOFTAP_START, ++ WAKE_LOCK_SOFTAP_THREAD, ++ WAKE_LOCK_MAX ++}; ++ ++enum dhd_prealloc_index { ++ DHD_PREALLOC_PROT = 0, ++ DHD_PREALLOC_RXBUF, ++ DHD_PREALLOC_DATABUF, ++#if defined(STATIC_WL_PRIV_STRUCT) ++ DHD_PREALLOC_OSL_BUF, ++ DHD_PREALLOC_WIPHY_ESCAN0 = 5, ++#else ++ DHD_PREALLOC_OSL_BUF ++#endif /* STATIC_WL_PRIV_STRUCT */ ++}; ++ ++typedef enum { ++ DHD_IF_NONE = 0, ++ DHD_IF_ADD, ++ DHD_IF_DEL, ++ DHD_IF_CHANGE, ++ DHD_IF_DELETING ++} dhd_if_state_t; ++ ++ ++#if defined(CONFIG_DHD_USE_STATIC_BUF) ++ ++uint8* dhd_os_prealloc(void *osh, int section, uint size); ++void dhd_os_prefree(void *osh, void *addr, uint size); ++#define DHD_OS_PREALLOC(osh, section, size) dhd_os_prealloc(osh, section, size) ++#define DHD_OS_PREFREE(osh, addr, size) dhd_os_prefree(osh, addr, size) ++ ++#else ++ ++#define DHD_OS_PREALLOC(osh, section, size) MALLOC(osh, size) ++#define DHD_OS_PREFREE(osh, addr, size) MFREE(osh, addr, size) ++ ++#endif /* defined(CONFIG_DHD_USE_STATIC_BUF) */ ++ ++/* Packet alignment for most efficient SDIO (can change based on platform) */ ++#ifndef DHD_SDALIGN ++#define DHD_SDALIGN 32 ++#endif ++ ++/* host reordering packts logic */ ++/* followed the structure to hold the reorder buffers (void **p) */ ++typedef struct reorder_info { ++ void **p; ++ uint8 flow_id; ++ uint8 cur_idx; ++ uint8 exp_idx; ++ uint8 max_idx; ++ uint8 pend_pkts; ++} reorder_info_t; ++ ++/* Common structure for module and instance linkage */ ++typedef struct dhd_pub { ++ /* Linkage ponters */ ++ osl_t *osh; /* OSL handle */ ++ struct dhd_bus *bus; /* Bus module handle */ ++ struct dhd_prot *prot; /* Protocol module handle */ ++ struct dhd_info *info; /* Info module handle */ ++ ++ /* Internal dhd items */ ++ bool up; /* Driver up/down (to OS) */ ++ bool txoff; /* Transmit flow-controlled */ ++ bool dongle_reset; /* TRUE = DEVRESET put dongle into reset */ ++ enum dhd_bus_state busstate; ++ uint hdrlen; /* Total DHD header length (proto + bus) */ ++ uint maxctl; /* Max size rxctl request from proto to bus */ ++ uint rxsz; /* Rx buffer size bus module should use */ ++ uint8 wme_dp; /* wme discard priority */ ++ ++ /* Dongle media info */ ++ bool iswl; /* Dongle-resident driver is wl */ ++ ulong drv_version; /* Version of dongle-resident driver */ ++ struct ether_addr mac; /* MAC address obtained from dongle */ ++ dngl_stats_t dstats; /* Stats for dongle-based data */ ++ ++ /* Additional stats for the bus level */ ++ ulong tx_packets; /* Data packets sent to dongle */ ++ ulong tx_multicast; /* Multicast data packets sent to dongle */ ++ ulong tx_errors; /* Errors in sending data to dongle */ ++ ulong tx_ctlpkts; /* Control packets sent to dongle */ ++ ulong tx_ctlerrs; /* Errors sending control frames to dongle */ ++ ulong rx_packets; /* Packets sent up the network interface */ ++ ulong rx_multicast; /* Multicast packets sent up the network interface */ ++ ulong rx_errors; /* Errors processing rx data packets */ ++ ulong rx_ctlpkts; /* Control frames processed from dongle */ ++ ulong rx_ctlerrs; /* Errors in processing rx control frames */ ++ ulong rx_dropped; /* Packets dropped locally (no memory) */ ++ ulong rx_flushed; /* Packets flushed due to unscheduled sendup thread */ ++ ulong wd_dpc_sched; /* Number of times dhd dpc scheduled by watchdog timer */ ++ ++ ulong rx_readahead_cnt; /* Number of packets where header read-ahead was used. */ ++ ulong tx_realloc; /* Number of tx packets we had to realloc for headroom */ ++ ulong fc_packets; /* Number of flow control pkts recvd */ ++ ++ /* Last error return */ ++ int bcmerror; ++ uint tickcnt; ++ ++ /* Last error from dongle */ ++ int dongle_error; ++ ++ uint8 country_code[WLC_CNTRY_BUF_SZ]; ++ ++ /* Suspend disable flag and "in suspend" flag */ ++ int suspend_disable_flag; /* "1" to disable all extra powersaving during suspend */ ++ int in_suspend; /* flag set to 1 when early suspend called */ ++#ifdef PNO_SUPPORT ++ int pno_enable; /* pno status : "1" is pno enable */ ++ int pno_suspend; /* pno suspend status : "1" is pno suspended */ ++#endif /* PNO_SUPPORT */ ++ /* DTIM skip value, default 0(or 1) means wake each DTIM ++ * 3 means skip 2 DTIMs and wake up 3rd DTIM(9th beacon when AP DTIM is 3) ++ */ ++ int suspend_bcn_li_dtim; /* bcn_li_dtim value in suspend mode */ ++#ifdef PKT_FILTER_SUPPORT ++ int early_suspended; /* Early suspend status */ ++ int dhcp_in_progress; /* DHCP period */ ++#endif ++ ++ /* Pkt filter defination */ ++ char * pktfilter[100]; ++ int pktfilter_count; ++ ++ wl_country_t dhd_cspec; /* Current Locale info */ ++ char eventmask[WL_EVENTING_MASK_LEN]; ++ int op_mode; /* STA, HostAPD, WFD, SoftAP */ ++ ++/* Set this to 1 to use a seperate interface (p2p0) for p2p operations. ++ * For ICS MR1 releases it should be disable to be compatable with ICS MR1 Framework ++ * see target dhd-cdc-sdmmc-panda-cfg80211-icsmr1-gpl-debug in Makefile ++ */ ++/* #define WL_ENABLE_P2P_IF 1 */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ struct mutex wl_start_stop_lock; /* lock/unlock for Android start/stop */ ++ struct mutex wl_softap_lock; /* lock/unlock for any SoftAP/STA settings */ ++#endif ++ ++#ifdef WLBTAMP ++ uint16 maxdatablks; ++#endif /* WLBTAMP */ ++#ifdef PROP_TXSTATUS ++ int wlfc_enabled; ++ void* wlfc_state; ++#endif ++ bool dongle_isolation; ++ bool dongle_trap_occured; /* flag for sending HANG event to upper layer */ ++ int hang_was_sent; ++ int rxcnt_timeout; /* counter rxcnt timeout to send HANG */ ++ int txcnt_timeout; /* counter txcnt timeout to send HANG */ ++#ifdef WLMEDIA_HTSF ++ uint8 htsfdlystat_sz; /* Size of delay stats, max 255B */ ++#endif ++ struct reorder_info *reorder_bufs[WLHOST_REORDERDATA_MAXFLOWS]; ++#if defined(ARP_OFFLOAD_SUPPORT) ++ uint32 arp_version; ++#endif ++} dhd_pub_t; ++ ++ ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) ++ ++ #define DHD_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); ++ #define _DHD_PM_RESUME_WAIT(a, b) do {\ ++ int retry = 0; \ ++ SMP_RD_BARRIER_DEPENDS(); \ ++ while (dhd_mmc_suspend && retry++ != b) { \ ++ SMP_RD_BARRIER_DEPENDS(); \ ++ wait_event_interruptible_timeout(a, !dhd_mmc_suspend, 1); \ ++ } \ ++ } while (0) ++ #define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 200) ++ #define DHD_PM_RESUME_WAIT_FOREVER(a) _DHD_PM_RESUME_WAIT(a, ~0) ++ #define DHD_PM_RESUME_RETURN_ERROR(a) do { if (dhd_mmc_suspend) return a; } while (0) ++ #define DHD_PM_RESUME_RETURN do { if (dhd_mmc_suspend) return; } while (0) ++ ++ #define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); ++ #define SPINWAIT_SLEEP(a, exp, us) do { \ ++ uint countdown = (us) + 9999; \ ++ while ((exp) && (countdown >= 10000)) { \ ++ wait_event_interruptible_timeout(a, FALSE, 1); \ ++ countdown -= 10000; \ ++ } \ ++ } while (0) ++ ++ #else ++ ++ #define DHD_PM_RESUME_WAIT_INIT(a) ++ #define DHD_PM_RESUME_WAIT(a) ++ #define DHD_PM_RESUME_WAIT_FOREVER(a) ++ #define DHD_PM_RESUME_RETURN_ERROR(a) ++ #define DHD_PM_RESUME_RETURN ++ ++ #define DHD_SPINWAIT_SLEEP_INIT(a) ++ #define SPINWAIT_SLEEP(a, exp, us) do { \ ++ uint countdown = (us) + 9; \ ++ while ((exp) && (countdown >= 10)) { \ ++ OSL_DELAY(10); \ ++ countdown -= 10; \ ++ } \ ++ } while (0) ++ ++ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ ++#ifndef DHDTHREAD ++#undef SPINWAIT_SLEEP ++#define SPINWAIT_SLEEP(a, exp, us) SPINWAIT(exp, us) ++#endif /* DHDTHREAD */ ++#define DHD_IF_VIF 0x01 /* Virtual IF (Hidden from user) */ ++ ++unsigned long dhd_os_spin_lock(dhd_pub_t *pub); ++void dhd_os_spin_unlock(dhd_pub_t *pub, unsigned long flags); ++ ++/* Wakelock Functions */ ++extern int dhd_os_wake_lock(dhd_pub_t *pub); ++extern int dhd_os_wake_unlock(dhd_pub_t *pub); ++extern int dhd_os_wake_lock_timeout(dhd_pub_t *pub); ++extern int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val); ++extern int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val); ++extern int dhd_os_wd_wake_lock(dhd_pub_t *pub); ++extern int dhd_os_wd_wake_unlock(dhd_pub_t *pub); ++ ++inline static void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t * dhdp) ++{ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ mutex_init(&dhdp->wl_softap_lock); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++} ++ ++inline static void MUTEX_LOCK_SOFTAP_SET(dhd_pub_t * dhdp) ++{ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ mutex_lock(&dhdp->wl_softap_lock); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++} ++ ++inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp) ++{ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ mutex_unlock(&dhdp->wl_softap_lock); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++} ++ ++#define DHD_OS_WAKE_LOCK(pub) dhd_os_wake_lock(pub) ++#define DHD_OS_WAKE_UNLOCK(pub) dhd_os_wake_unlock(pub) ++#define DHD_OS_WD_WAKE_LOCK(pub) dhd_os_wd_wake_lock(pub) ++#define DHD_OS_WD_WAKE_UNLOCK(pub) dhd_os_wd_wake_unlock(pub) ++#define DHD_OS_WAKE_LOCK_TIMEOUT(pub) dhd_os_wake_lock_timeout(pub) ++#define DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(pub, val) \ ++ dhd_os_wake_lock_rx_timeout_enable(pub, val) ++#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(pub, val) \ ++ dhd_os_wake_lock_ctrl_timeout_enable(pub, val) ++#define DHD_PACKET_TIMEOUT_MS 1000 ++#define DHD_EVENT_TIMEOUT_MS 1500 ++ ++/* interface operations (register, remove) should be atomic, use this lock to prevent race ++ * condition among wifi on/off and interface operation functions ++ */ ++void dhd_net_if_lock(struct net_device *dev); ++void dhd_net_if_unlock(struct net_device *dev); ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++extern struct mutex _dhd_sdio_mutex_lock_; ++#endif ++ ++typedef struct dhd_if_event { ++ uint8 ifidx; ++ uint8 action; ++ uint8 flags; ++ uint8 bssidx; ++ uint8 is_AP; ++} dhd_if_event_t; ++ ++typedef enum dhd_attach_states ++{ ++ DHD_ATTACH_STATE_INIT = 0x0, ++ DHD_ATTACH_STATE_NET_ALLOC = 0x1, ++ DHD_ATTACH_STATE_DHD_ALLOC = 0x2, ++ DHD_ATTACH_STATE_ADD_IF = 0x4, ++ DHD_ATTACH_STATE_PROT_ATTACH = 0x8, ++ DHD_ATTACH_STATE_WL_ATTACH = 0x10, ++ DHD_ATTACH_STATE_THREADS_CREATED = 0x20, ++ DHD_ATTACH_STATE_WAKELOCKS_INIT = 0x40, ++ DHD_ATTACH_STATE_CFG80211 = 0x80, ++ DHD_ATTACH_STATE_EARLYSUSPEND_DONE = 0x100, ++ DHD_ATTACH_STATE_DONE = 0x200 ++} dhd_attach_states_t; ++ ++/* Value -1 means we are unsuccessful in creating the kthread. */ ++#define DHD_PID_KT_INVALID -1 ++/* Value -2 means we are unsuccessful in both creating the kthread and tasklet */ ++#define DHD_PID_KT_TL_INVALID -2 ++ ++/* ++ * Exported from dhd OS modules (dhd_linux/dhd_ndis) ++ */ ++ ++/* To allow osl_attach/detach calls from os-independent modules */ ++osl_t *dhd_osl_attach(void *pdev, uint bustype); ++void dhd_osl_detach(osl_t *osh); ++ ++/* Indication from bus module regarding presence/insertion of dongle. ++ * Return dhd_pub_t pointer, used as handle to OS module in later calls. ++ * Returned structure should have bus and prot pointers filled in. ++ * bus_hdrlen specifies required headroom for bus module header. ++ */ ++extern dhd_pub_t *dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen); ++#if defined(WLP2P) && defined(WL_CFG80211) ++/* To allow attach/detach calls corresponding to p2p0 interface */ ++extern int dhd_attach_p2p(dhd_pub_t *); ++extern int dhd_detach_p2p(dhd_pub_t *); ++#endif /* WLP2P && WL_CFG80211 */ ++extern int dhd_net_attach(dhd_pub_t *dhdp, int idx); ++ ++/* Indication from bus module regarding removal/absence of dongle */ ++extern void dhd_detach(dhd_pub_t *dhdp); ++extern void dhd_free(dhd_pub_t *dhdp); ++ ++/* Indication from bus module to change flow-control state */ ++extern void dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool on); ++ ++extern bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec); ++ ++/* Receive frame for delivery to OS. Callee disposes of rxp. */ ++extern void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *rxp, int numpkt, uint8 chan); ++ ++/* Return pointer to interface name */ ++extern char *dhd_ifname(dhd_pub_t *dhdp, int idx); ++ ++/* Request scheduling of the bus dpc */ ++extern void dhd_sched_dpc(dhd_pub_t *dhdp); ++ ++/* Notify tx completion */ ++extern void dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success); ++ ++/* OS independent layer functions */ ++extern int dhd_os_proto_block(dhd_pub_t * pub); ++extern int dhd_os_proto_unblock(dhd_pub_t * pub); ++extern int dhd_os_ioctl_resp_wait(dhd_pub_t * pub, uint * condition, bool * pending); ++extern int dhd_os_ioctl_resp_wake(dhd_pub_t * pub); ++extern unsigned int dhd_os_get_ioctl_resp_timeout(void); ++extern void dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec); ++extern void * dhd_os_open_image(char * filename); ++extern int dhd_os_get_image_block(char * buf, int len, void * image); ++extern void dhd_os_close_image(void * image); ++extern void dhd_os_wd_timer(void *bus, uint wdtick); ++extern void dhd_os_sdlock(dhd_pub_t * pub); ++extern void dhd_os_sdunlock(dhd_pub_t * pub); ++extern void dhd_os_sdlock_txq(dhd_pub_t * pub); ++extern void dhd_os_sdunlock_txq(dhd_pub_t * pub); ++extern void dhd_os_sdlock_rxq(dhd_pub_t * pub); ++extern void dhd_os_sdunlock_rxq(dhd_pub_t * pub); ++extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t * pub); ++extern void dhd_customer_gpio_wlan_ctrl(int onoff); ++extern int dhd_custom_get_mac_address(unsigned char *buf); ++extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub); ++extern void dhd_os_sdlock_eventq(dhd_pub_t * pub); ++extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub); ++extern bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret); ++extern int dhd_os_send_hang_message(dhd_pub_t *dhdp); ++extern void dhd_set_version_info(dhd_pub_t *pub, char *fw); ++ ++#ifdef PNO_SUPPORT ++extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled); ++extern int dhd_pno_clean(dhd_pub_t *dhd); ++extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ++ ushort scan_fr, int pno_repeat, int pno_freq_expo_max); ++extern int dhd_pno_get_status(dhd_pub_t *dhd); ++extern int dhd_dev_pno_reset(struct net_device *dev); ++extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, ++ int nssid, ushort scan_fr, int pno_repeat, int pno_freq_expo_max); ++extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled); ++extern int dhd_dev_get_pno_status(struct net_device *dev); ++#endif /* PNO_SUPPORT */ ++ ++#ifdef PKT_FILTER_SUPPORT ++#define DHD_UNICAST_FILTER_NUM 0 ++#define DHD_BROADCAST_FILTER_NUM 1 ++#define DHD_MULTICAST4_FILTER_NUM 2 ++#define DHD_MULTICAST6_FILTER_NUM 3 ++#define DHD_MDNS_FILTER_NUM 4 ++extern int dhd_os_enable_packet_filter(dhd_pub_t *dhdp, int val); ++extern void dhd_enable_packet_filter(int value, dhd_pub_t *dhd); ++extern int net_os_enable_packet_filter(struct net_device *dev, int val); ++extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num); ++#endif /* PKT_FILTER_SUPPORT */ ++ ++extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd); ++extern bool dhd_support_sta_mode(dhd_pub_t *dhd); ++ ++#ifdef DHD_DEBUG ++extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size); ++#endif /* DHD_DEBUG */ ++#if defined(OOB_INTR_ONLY) ++extern int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr); ++#endif ++extern void dhd_os_sdtxlock(dhd_pub_t * pub); ++extern void dhd_os_sdtxunlock(dhd_pub_t * pub); ++ ++typedef struct { ++ uint32 limit; /* Expiration time (usec) */ ++ uint32 increment; /* Current expiration increment (usec) */ ++ uint32 elapsed; /* Current elapsed time (usec) */ ++ uint32 tick; /* O/S tick time (usec) */ ++} dhd_timeout_t; ++ ++extern void dhd_timeout_start(dhd_timeout_t *tmo, uint usec); ++extern int dhd_timeout_expired(dhd_timeout_t *tmo); ++ ++extern int dhd_ifname2idx(struct dhd_info *dhd, char *name); ++extern int dhd_net2idx(struct dhd_info *dhd, struct net_device *net); ++extern struct net_device * dhd_idx2net(void *pub, int ifidx); ++extern int net_os_send_hang_message(struct net_device *dev); ++extern int wl_host_event(dhd_pub_t *dhd_pub, int *idx, void *pktdata, ++ wl_event_msg_t *, void **data_ptr); ++extern void wl_event_to_host_order(wl_event_msg_t * evt); ++ ++extern int dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int len); ++extern int dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uint8 set, ++ int ifindex); ++ ++extern void dhd_common_init(osl_t *osh); ++ ++extern int dhd_do_driver_init(struct net_device *net); ++extern int dhd_add_if(struct dhd_info *dhd, int ifidx, void *handle, ++ char *name, uint8 *mac_addr, uint32 flags, uint8 bssidx); ++extern void dhd_del_if(struct dhd_info *dhd, int ifidx); ++ ++extern void dhd_vif_add(struct dhd_info *dhd, int ifidx, char * name); ++extern void dhd_vif_del(struct dhd_info *dhd, int ifidx); ++ ++extern void dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx); ++extern void dhd_vif_sendup(struct dhd_info *dhd, int ifidx, uchar *cp, int len); ++ ++ ++/* Send packet to dongle via data channel */ ++extern int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pkt); ++ ++/* send up locally generated event */ ++extern void dhd_sendup_event_common(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data); ++/* Send event to host */ ++extern void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data); ++extern int dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag); ++extern uint dhd_bus_status(dhd_pub_t *dhdp); ++extern int dhd_bus_start(dhd_pub_t *dhdp); ++extern int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size); ++extern void dhd_print_buf(void *pbuf, int len, int bytes_per_line); ++extern bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval); ++extern uint dhd_bus_chip_id(dhd_pub_t *dhdp); ++extern uint dhd_bus_chiprev_id(dhd_pub_t *dhdp); ++extern uint dhd_bus_chippkg_id(dhd_pub_t *dhdp); ++ ++#if defined(KEEP_ALIVE) ++extern int dhd_keep_alive_onoff(dhd_pub_t *dhd); ++#endif /* KEEP_ALIVE */ ++ ++extern bool dhd_is_concurrent_mode(dhd_pub_t *dhd); ++ ++typedef enum cust_gpio_modes { ++ WLAN_RESET_ON, ++ WLAN_RESET_OFF, ++ WLAN_POWER_ON, ++ WLAN_POWER_OFF ++} cust_gpio_modes_t; ++ ++extern int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag); ++extern int wl_iw_send_priv_event(struct net_device *dev, char *flag); ++/* ++ * Insmod parameters for debug/test ++ */ ++ ++/* Watchdog timer interval */ ++extern uint dhd_watchdog_ms; ++ ++#if defined(DHD_DEBUG) ++/* Console output poll interval */ ++extern uint dhd_console_ms; ++#endif /* defined(DHD_DEBUG) */ ++//extern uint android_msg_level; ++#ifdef CONFIG_WIRELESS_EXT ++extern uint iw_msg_level; ++#endif ++#ifdef WL_CFG80211 ++extern uint wl_dbg_level; ++#endif ++extern uint dhd_slpauto; ++ ++/* Use interrupts */ ++extern uint dhd_intr; ++ ++/* Use polling */ ++extern uint dhd_poll; ++ ++/* ARP offload agent mode */ ++extern uint dhd_arp_mode; ++ ++/* ARP offload enable */ ++extern uint dhd_arp_enable; ++ ++/* Pkt filte enable control */ ++extern uint dhd_pkt_filter_enable; ++ ++/* Pkt filter init setup */ ++extern uint dhd_pkt_filter_init; ++ ++/* Pkt filter mode control */ ++extern uint dhd_master_mode; ++ ++/* Roaming mode control */ ++extern uint dhd_roam_disable; ++ ++/* Roaming mode control */ ++extern uint dhd_radio_up; ++ ++/* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */ ++extern int dhd_idletime; ++#ifdef DHD_USE_IDLECOUNT ++#define DHD_IDLETIME_TICKS 5 ++#else ++#define DHD_IDLETIME_TICKS 1 ++#endif /* DHD_USE_IDLECOUNT */ ++ ++/* SDIO Drive Strength */ ++extern uint dhd_sdiod_drive_strength; ++ ++/* Override to force tx queueing all the time */ ++extern uint dhd_force_tx_queueing; ++/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */ ++#define DEFAULT_KEEP_ALIVE_VALUE 55000 /* msec */ ++#ifndef CUSTOM_KEEP_ALIVE_SETTING ++#define CUSTOM_KEEP_ALIVE_SETTING DEFAULT_KEEP_ALIVE_VALUE ++#endif /* DEFAULT_KEEP_ALIVE_VALUE */ ++ ++#define NULL_PKT_STR "null_pkt" ++ ++/* hooks for custom glom setting option via Makefile */ ++#define DEFAULT_GLOM_VALUE -1 ++#ifndef CUSTOM_GLOM_SETTING ++#define CUSTOM_GLOM_SETTING DEFAULT_GLOM_VALUE ++#endif ++ ++/* hooks for custom Roaming Trigger setting via Makefile */ ++#define DEFAULT_ROAM_TRIGGER_VALUE -75 /* dBm default roam trigger all band */ ++#define DEFAULT_ROAM_TRIGGER_SETTING -1 ++#ifndef CUSTOM_ROAM_TRIGGER_SETTING ++#define CUSTOM_ROAM_TRIGGER_SETTING DEFAULT_ROAM_TRIGGER_VALUE ++#endif ++ ++/* hooks for custom Roaming Romaing setting via Makefile */ ++#define DEFAULT_ROAM_DELTA_VALUE 10 /* dBm default roam delta all band */ ++#define DEFAULT_ROAM_DELTA_SETTING -1 ++#ifndef CUSTOM_ROAM_DELTA_SETTING ++#define CUSTOM_ROAM_DELTA_SETTING DEFAULT_ROAM_DELTA_VALUE ++#endif ++ ++/* hooks for custom PNO Event wake lock to guarantee enough time ++ for the Platform to detect Event before system suspended ++*/ ++#define DEFAULT_PNO_EVENT_LOCK_xTIME 2 /* multiplay of DHD_PACKET_TIMEOUT_MS */ ++#ifndef CUSTOM_PNO_EVENT_LOCK_xTIME ++#define CUSTOM_PNO_EVENT_LOCK_xTIME DEFAULT_PNO_EVENT_LOCK_xTIME ++#endif ++ ++/* hooks for custom dhd_dpc_prio setting option via Makefile */ ++#define DEFAULT_DHP_DPC_PRIO 1 ++#ifndef CUSTOM_DPC_PRIO_SETTING ++#define CUSTOM_DPC_PRIO_SETTING DEFAULT_DHP_DPC_PRIO ++#endif ++ ++#define DEFAULT_SUSPEND_BCN_LI_DTIM 3 ++#ifndef CUSTOM_SUSPEND_BCN_LI_DTIM ++#define CUSTOM_SUSPEND_BCN_LI_DTIM DEFAULT_SUSPEND_BCN_LI_DTIM ++#endif ++ ++#ifdef SDTEST ++/* Echo packet generator (SDIO), pkts/s */ ++extern uint dhd_pktgen; ++ ++/* Echo packet len (0 => sawtooth, max 1800) */ ++extern uint dhd_pktgen_len; ++#define MAX_PKTGEN_LEN 1800 ++#endif ++ ++ ++/* optionally set by a module_param_string() */ ++#define MOD_PARAM_PATHLEN 2048 ++extern char fw_path[MOD_PARAM_PATHLEN]; ++extern char nv_path[MOD_PARAM_PATHLEN]; ++ ++#define MOD_PARAM_INFOLEN 512 ++ ++#ifdef SOFTAP ++extern char fw_path2[MOD_PARAM_PATHLEN]; ++#endif ++ ++#define FW_PATH_AUTO_SELECT 1 ++extern char firmware_path[MOD_PARAM_PATHLEN]; ++extern void dhd_bus_select_firmware_name_by_chip(struct dhd_bus *bus, char *dst, char *src); ++#define COPY_FW_PATH_BY_CHIP(bus, dst, src) dhd_bus_select_firmware_name_by_chip(bus, dst, src); ++ ++/* Flag to indicate if we should download firmware on driver load */ ++extern uint dhd_download_fw_on_driverload; ++ ++ ++/* For supporting multiple interfaces */ ++#define DHD_MAX_IFS 16 ++#define DHD_DEL_IF -0xe ++#define DHD_BAD_IF -0xf ++#define WL_AUTO_ROAM_TRIGGER -75 ++ ++#ifdef PROP_TXSTATUS ++/* Please be mindful that total pkttag space is 32 octets only */ ++typedef struct dhd_pkttag { ++ /* ++ b[11 ] - 1 = this packet was sent in response to one time packet request, ++ do not increment credit on status for this one. [WLFC_CTL_TYPE_MAC_REQUEST_PACKET]. ++ b[10 ] - 1 = signal-only-packet to firmware [i.e. nothing to piggyback on] ++ b[9 ] - 1 = packet is host->firmware (transmit direction) ++ - 0 = packet received from firmware (firmware->host) ++ b[8 ] - 1 = packet was sent due to credit_request (pspoll), ++ packet does not count against FIFO credit. ++ - 0 = normal transaction, packet counts against FIFO credit ++ b[7 ] - 1 = AP, 0 = STA ++ b[6:4] - AC FIFO number ++ b[3:0] - interface index ++ */ ++ uint16 if_flags; ++ /* destination MAC address for this packet so that not every ++ module needs to open the packet to find this ++ */ ++ uint8 dstn_ether[ETHER_ADDR_LEN]; ++ /* ++ This 32-bit goes from host to device for every packet. ++ */ ++ uint32 htod_tag; ++ /* bus specific stuff */ ++ union { ++ struct { ++ void* stuff; ++ uint32 thing1; ++ uint32 thing2; ++ } sd; ++ struct { ++ void* bus; ++ void* urb; ++ } usb; ++ } bus_specific; ++} dhd_pkttag_t; ++ ++#define DHD_PKTTAG_SET_H2DTAG(tag, h2dvalue) ((dhd_pkttag_t*)(tag))->htod_tag = (h2dvalue) ++#define DHD_PKTTAG_H2DTAG(tag) (((dhd_pkttag_t*)(tag))->htod_tag) ++ ++#define DHD_PKTTAG_IFMASK 0xf ++#define DHD_PKTTAG_IFTYPE_MASK 0x1 ++#define DHD_PKTTAG_IFTYPE_SHIFT 7 ++#define DHD_PKTTAG_FIFO_MASK 0x7 ++#define DHD_PKTTAG_FIFO_SHIFT 4 ++ ++#define DHD_PKTTAG_SIGNALONLY_MASK 0x1 ++#define DHD_PKTTAG_SIGNALONLY_SHIFT 10 ++ ++#define DHD_PKTTAG_ONETIMEPKTRQST_MASK 0x1 ++#define DHD_PKTTAG_ONETIMEPKTRQST_SHIFT 11 ++ ++#define DHD_PKTTAG_PKTDIR_MASK 0x1 ++#define DHD_PKTTAG_PKTDIR_SHIFT 9 ++ ++#define DHD_PKTTAG_CREDITCHECK_MASK 0x1 ++#define DHD_PKTTAG_CREDITCHECK_SHIFT 8 ++ ++#define DHD_PKTTAG_INVALID_FIFOID 0x7 ++ ++#define DHD_PKTTAG_SETFIFO(tag, fifo) ((dhd_pkttag_t*)(tag))->if_flags = \ ++ (((dhd_pkttag_t*)(tag))->if_flags & ~(DHD_PKTTAG_FIFO_MASK << DHD_PKTTAG_FIFO_SHIFT)) | \ ++ (((fifo) & DHD_PKTTAG_FIFO_MASK) << DHD_PKTTAG_FIFO_SHIFT) ++#define DHD_PKTTAG_FIFO(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ ++ DHD_PKTTAG_FIFO_SHIFT) & DHD_PKTTAG_FIFO_MASK) ++ ++#define DHD_PKTTAG_SETIF(tag, if) ((dhd_pkttag_t*)(tag))->if_flags = \ ++ (((dhd_pkttag_t*)(tag))->if_flags & ~DHD_PKTTAG_IFMASK) | ((if) & DHD_PKTTAG_IFMASK) ++#define DHD_PKTTAG_IF(tag) (((dhd_pkttag_t*)(tag))->if_flags & DHD_PKTTAG_IFMASK) ++ ++#define DHD_PKTTAG_SETIFTYPE(tag, isAP) ((dhd_pkttag_t*)(tag))->if_flags = \ ++ (((dhd_pkttag_t*)(tag))->if_flags & \ ++ ~(DHD_PKTTAG_IFTYPE_MASK << DHD_PKTTAG_IFTYPE_SHIFT)) | \ ++ (((isAP) & DHD_PKTTAG_IFTYPE_MASK) << DHD_PKTTAG_IFTYPE_SHIFT) ++#define DHD_PKTTAG_IFTYPE(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ ++ DHD_PKTTAG_IFTYPE_SHIFT) & DHD_PKTTAG_IFTYPE_MASK) ++ ++#define DHD_PKTTAG_SETCREDITCHECK(tag, check) ((dhd_pkttag_t*)(tag))->if_flags = \ ++ (((dhd_pkttag_t*)(tag))->if_flags & \ ++ ~(DHD_PKTTAG_CREDITCHECK_MASK << DHD_PKTTAG_CREDITCHECK_SHIFT)) | \ ++ (((check) & DHD_PKTTAG_CREDITCHECK_MASK) << DHD_PKTTAG_CREDITCHECK_SHIFT) ++#define DHD_PKTTAG_CREDITCHECK(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ ++ DHD_PKTTAG_CREDITCHECK_SHIFT) & DHD_PKTTAG_CREDITCHECK_MASK) ++ ++#define DHD_PKTTAG_SETPKTDIR(tag, dir) ((dhd_pkttag_t*)(tag))->if_flags = \ ++ (((dhd_pkttag_t*)(tag))->if_flags & \ ++ ~(DHD_PKTTAG_PKTDIR_MASK << DHD_PKTTAG_PKTDIR_SHIFT)) | \ ++ (((dir) & DHD_PKTTAG_PKTDIR_MASK) << DHD_PKTTAG_PKTDIR_SHIFT) ++#define DHD_PKTTAG_PKTDIR(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ ++ DHD_PKTTAG_PKTDIR_SHIFT) & DHD_PKTTAG_PKTDIR_MASK) ++ ++#define DHD_PKTTAG_SETSIGNALONLY(tag, signalonly) ((dhd_pkttag_t*)(tag))->if_flags = \ ++ (((dhd_pkttag_t*)(tag))->if_flags & \ ++ ~(DHD_PKTTAG_SIGNALONLY_MASK << DHD_PKTTAG_SIGNALONLY_SHIFT)) | \ ++ (((signalonly) & DHD_PKTTAG_SIGNALONLY_MASK) << DHD_PKTTAG_SIGNALONLY_SHIFT) ++#define DHD_PKTTAG_SIGNALONLY(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ ++ DHD_PKTTAG_SIGNALONLY_SHIFT) & DHD_PKTTAG_SIGNALONLY_MASK) ++ ++#define DHD_PKTTAG_SETONETIMEPKTRQST(tag) ((dhd_pkttag_t*)(tag))->if_flags = \ ++ (((dhd_pkttag_t*)(tag))->if_flags & \ ++ ~(DHD_PKTTAG_ONETIMEPKTRQST_MASK << DHD_PKTTAG_ONETIMEPKTRQST_SHIFT)) | \ ++ (1 << DHD_PKTTAG_ONETIMEPKTRQST_SHIFT) ++#define DHD_PKTTAG_ONETIMEPKTRQST(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ ++ DHD_PKTTAG_ONETIMEPKTRQST_SHIFT) & DHD_PKTTAG_ONETIMEPKTRQST_MASK) ++ ++#define DHD_PKTTAG_SETDSTN(tag, dstn_MAC_ea) memcpy(((dhd_pkttag_t*)((tag)))->dstn_ether, \ ++ (dstn_MAC_ea), ETHER_ADDR_LEN) ++#define DHD_PKTTAG_DSTN(tag) ((dhd_pkttag_t*)(tag))->dstn_ether ++ ++typedef int (*f_commitpkt_t)(void* ctx, void* p, bool wlfc_locked); ++ ++#ifdef PROP_TXSTATUS_DEBUG ++#define DHD_WLFC_CTRINC_MAC_CLOSE(entry) do { (entry)->closed_ct++; } while (0) ++#define DHD_WLFC_CTRINC_MAC_OPEN(entry) do { (entry)->opened_ct++; } while (0) ++#else ++#define DHD_WLFC_CTRINC_MAC_CLOSE(entry) do {} while (0) ++#define DHD_WLFC_CTRINC_MAC_OPEN(entry) do {} while (0) ++#endif ++ ++#endif /* PROP_TXSTATUS */ ++ ++extern void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar); ++extern void dhd_wait_event_wakeup(dhd_pub_t*dhd); ++ ++#define IFLOCK_INIT(lock) *lock = 0 ++#define IFLOCK(lock) while (InterlockedCompareExchange((lock), 1, 0)) \ ++ NdisStallExecution(1); ++#define IFUNLOCK(lock) InterlockedExchange((lock), 0) ++#define IFLOCK_FREE(lock) ++ ++#ifdef PNO_SUPPORT ++extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled); ++extern int dhd_pnoenable(dhd_pub_t *dhd, int pfn_enabled); ++extern int dhd_pno_clean(dhd_pub_t *dhd); ++extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ++ ushort scan_fr, int pno_repeat, int pno_freq_expo_max); ++extern int dhd_pno_get_status(dhd_pub_t *dhd); ++extern int dhd_pno_set_add(dhd_pub_t *dhd, wl_pfn_t *netinfo, int nssid, ushort scan_fr, ++ ushort slowscan_fr, uint8 pno_repeat, uint8 pno_freq_expo_max, int16 flags); ++extern int dhd_pno_cfg(dhd_pub_t *dhd, wl_pfn_cfg_t *pcfg); ++extern int dhd_pno_suspend(dhd_pub_t *dhd, int pfn_suspend); ++#endif /* PNO_SUPPORT */ ++#ifdef ARP_OFFLOAD_SUPPORT ++#define MAX_IPV4_ENTRIES 8 ++void dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode); ++void dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable); ++ ++/* dhd_commn arp offload wrapers */ ++void dhd_aoe_hostip_clr(dhd_pub_t *dhd, int idx); ++void dhd_aoe_arp_clr(dhd_pub_t *dhd, int idx); ++int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen, int idx); ++void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr, int idx); ++#endif /* ARP_OFFLOAD_SUPPORT */ ++ ++#endif /* _dhd_h_ */ +diff --git a/drivers/net/wireless/ap6210/dhd_bta.c b/drivers/net/wireless/ap6210/dhd_bta.c +new file mode 100755 +index 0000000..3752bbd +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_bta.c +@@ -0,0 +1,338 @@ ++/* ++ * BT-AMP support routines ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhd_bta.c 303834 2011-12-20 06:17:39Z $ ++ */ ++#ifndef WLBTAMP ++#error "WLBTAMP is not defined" ++#endif /* WLBTAMP */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++ ++#ifdef SEND_HCI_CMD_VIA_IOCTL ++#define BTA_HCI_CMD_MAX_LEN HCI_CMD_PREAMBLE_SIZE + HCI_CMD_DATA_SIZE ++ ++/* Send HCI cmd via wl iovar HCI_cmd to the dongle. */ ++int ++dhd_bta_docmd(dhd_pub_t *pub, void *cmd_buf, uint cmd_len) ++{ ++ amp_hci_cmd_t *cmd = (amp_hci_cmd_t *)cmd_buf; ++ uint8 buf[BTA_HCI_CMD_MAX_LEN + 16]; ++ uint len = sizeof(buf); ++ wl_ioctl_t ioc; ++ ++ if (cmd_len < HCI_CMD_PREAMBLE_SIZE) ++ return BCME_BADLEN; ++ ++ if ((uint)cmd->plen + HCI_CMD_PREAMBLE_SIZE > cmd_len) ++ return BCME_BADLEN; ++ ++ len = bcm_mkiovar("HCI_cmd", ++ (char *)cmd, (uint)cmd->plen + HCI_CMD_PREAMBLE_SIZE, (char *)buf, len); ++ ++ ++ memset(&ioc, 0, sizeof(ioc)); ++ ++ ioc.cmd = WLC_SET_VAR; ++ ioc.buf = buf; ++ ioc.len = len; ++ ioc.set = TRUE; ++ ++ return dhd_wl_ioctl(pub, &ioc, ioc.buf, ioc.len); ++} ++#else /* !SEND_HCI_CMD_VIA_IOCTL */ ++ ++static void ++dhd_bta_flush_hcidata(dhd_pub_t *pub, uint16 llh) ++{ ++ int prec; ++ struct pktq *q; ++ uint count = 0; ++ ++ q = dhd_bus_txq(pub->bus); ++ if (q == NULL) ++ return; ++ ++ DHD_BTA(("dhd: flushing HCI ACL data for logical link %u...\n", llh)); ++ ++ dhd_os_sdlock_txq(pub); ++ ++ /* Walk through the txq and toss all HCI ACL data packets */ ++ PKTQ_PREC_ITER(q, prec) { ++ void *head_pkt = NULL; ++ ++ while (pktq_ppeek(q, prec) != head_pkt) { ++ void *pkt = pktq_pdeq(q, prec); ++ int ifidx; ++ ++ PKTPULL(pub->osh, pkt, dhd_bus_hdrlen(pub->bus)); ++ dhd_prot_hdrpull(pub, &ifidx, pkt, NULL, NULL); ++ ++ if (PKTLEN(pub->osh, pkt) >= RFC1042_HDR_LEN) { ++ struct ether_header *eh = ++ (struct ether_header *)PKTDATA(pub->osh, pkt); ++ ++ if (ntoh16(eh->ether_type) < ETHER_TYPE_MIN) { ++ struct dot11_llc_snap_header *lsh = ++ (struct dot11_llc_snap_header *)&eh[1]; ++ ++ if (bcmp(lsh, BT_SIG_SNAP_MPROT, ++ DOT11_LLC_SNAP_HDR_LEN - 2) == 0 && ++ ntoh16(lsh->type) == BTA_PROT_L2CAP) { ++ amp_hci_ACL_data_t *ACL_data = ++ (amp_hci_ACL_data_t *)&lsh[1]; ++ uint16 handle = ltoh16(ACL_data->handle); ++ ++ if (HCI_ACL_DATA_HANDLE(handle) == llh) { ++ PKTFREE(pub->osh, pkt, TRUE); ++ count ++; ++ continue; ++ } ++ } ++ } ++ } ++ ++ dhd_prot_hdrpush(pub, ifidx, pkt); ++ PKTPUSH(pub->osh, pkt, dhd_bus_hdrlen(pub->bus)); ++ ++ if (head_pkt == NULL) ++ head_pkt = pkt; ++ pktq_penq(q, prec, pkt); ++ } ++ } ++ ++ dhd_os_sdunlock_txq(pub); ++ ++ DHD_BTA(("dhd: flushed %u packet(s) for logical link %u...\n", count, llh)); ++} ++ ++/* Handle HCI cmd locally. ++ * Return 0: continue to send the cmd across SDIO ++ * < 0: stop, fail ++ * > 0: stop, succuess ++ */ ++static int ++_dhd_bta_docmd(dhd_pub_t *pub, amp_hci_cmd_t *cmd) ++{ ++ int status = 0; ++ ++ switch (ltoh16_ua((uint8 *)&cmd->opcode)) { ++ case HCI_Enhanced_Flush: { ++ eflush_cmd_parms_t *cmdparms = (eflush_cmd_parms_t *)cmd->parms; ++ dhd_bta_flush_hcidata(pub, ltoh16_ua(cmdparms->llh)); ++ break; ++ } ++ default: ++ break; ++ } ++ ++ return status; ++} ++ ++/* Send HCI cmd encapsulated in BT-SIG frame via data channel to the dongle. */ ++int ++dhd_bta_docmd(dhd_pub_t *pub, void *cmd_buf, uint cmd_len) ++{ ++ amp_hci_cmd_t *cmd = (amp_hci_cmd_t *)cmd_buf; ++ struct ether_header *eh; ++ struct dot11_llc_snap_header *lsh; ++ osl_t *osh = pub->osh; ++ uint len; ++ void *p; ++ int status; ++ ++ if (cmd_len < HCI_CMD_PREAMBLE_SIZE) { ++ AP6210_ERR("dhd_bta_docmd: short command, cmd_len %u\n", cmd_len); ++ return BCME_BADLEN; ++ } ++ ++ if ((len = (uint)cmd->plen + HCI_CMD_PREAMBLE_SIZE) > cmd_len) { ++ AP6210_ERR("dhd_bta_docmd: malformed command, len %u cmd_len %u\n", ++ len, cmd_len); ++ /* return BCME_BADLEN; */ ++ } ++ ++ p = PKTGET(osh, pub->hdrlen + RFC1042_HDR_LEN + len, TRUE); ++ if (p == NULL) { ++ AP6210_ERR("dhd_bta_docmd: out of memory\n"); ++ return BCME_NOMEM; ++ } ++ ++ ++ /* intercept and handle the HCI cmd locally */ ++ if ((status = _dhd_bta_docmd(pub, cmd)) > 0) ++ return 0; ++ else if (status < 0) ++ return status; ++ ++ /* copy in HCI cmd */ ++ PKTPULL(osh, p, pub->hdrlen + RFC1042_HDR_LEN); ++ bcopy(cmd, PKTDATA(osh, p), len); ++ ++ /* copy in partial Ethernet header with BT-SIG LLC/SNAP header */ ++ PKTPUSH(osh, p, RFC1042_HDR_LEN); ++ eh = (struct ether_header *)PKTDATA(osh, p); ++ bzero(eh->ether_dhost, ETHER_ADDR_LEN); ++ ETHER_SET_LOCALADDR(eh->ether_dhost); ++ bcopy(&pub->mac, eh->ether_shost, ETHER_ADDR_LEN); ++ eh->ether_type = hton16(len + DOT11_LLC_SNAP_HDR_LEN); ++ lsh = (struct dot11_llc_snap_header *)&eh[1]; ++ bcopy(BT_SIG_SNAP_MPROT, lsh, DOT11_LLC_SNAP_HDR_LEN - 2); ++ lsh->type = 0; ++ ++ return dhd_sendpkt(pub, 0, p); ++} ++#endif /* !SEND_HCI_CMD_VIA_IOCTL */ ++ ++/* Send HCI ACL data to dongle via data channel */ ++int ++dhd_bta_tx_hcidata(dhd_pub_t *pub, void *data_buf, uint data_len) ++{ ++ amp_hci_ACL_data_t *data = (amp_hci_ACL_data_t *)data_buf; ++ struct ether_header *eh; ++ struct dot11_llc_snap_header *lsh; ++ osl_t *osh = pub->osh; ++ uint len; ++ void *p; ++ ++ if (data_len < HCI_ACL_DATA_PREAMBLE_SIZE) { ++ AP6210_ERR("dhd_bta_tx_hcidata: short data_buf, data_len %u\n", data_len); ++ return BCME_BADLEN; ++ } ++ ++ if ((len = (uint)ltoh16(data->dlen) + HCI_ACL_DATA_PREAMBLE_SIZE) > data_len) { ++ AP6210_ERR("dhd_bta_tx_hcidata: malformed hci data, len %u data_len %u\n", ++ len, data_len); ++ /* return BCME_BADLEN; */ ++ } ++ ++ p = PKTGET(osh, pub->hdrlen + RFC1042_HDR_LEN + len, TRUE); ++ if (p == NULL) { ++ AP6210_ERR("dhd_bta_tx_hcidata: out of memory\n"); ++ return BCME_NOMEM; ++ } ++ ++ ++ /* copy in HCI ACL data header and HCI ACL data */ ++ PKTPULL(osh, p, pub->hdrlen + RFC1042_HDR_LEN); ++ bcopy(data, PKTDATA(osh, p), len); ++ ++ /* copy in partial Ethernet header with BT-SIG LLC/SNAP header */ ++ PKTPUSH(osh, p, RFC1042_HDR_LEN); ++ eh = (struct ether_header *)PKTDATA(osh, p); ++ bzero(eh->ether_dhost, ETHER_ADDR_LEN); ++ bcopy(&pub->mac, eh->ether_shost, ETHER_ADDR_LEN); ++ eh->ether_type = hton16(len + DOT11_LLC_SNAP_HDR_LEN); ++ lsh = (struct dot11_llc_snap_header *)&eh[1]; ++ bcopy(BT_SIG_SNAP_MPROT, lsh, DOT11_LLC_SNAP_HDR_LEN - 2); ++ lsh->type = HTON16(BTA_PROT_L2CAP); ++ ++ return dhd_sendpkt(pub, 0, p); ++} ++ ++/* txcomplete callback */ ++void ++dhd_bta_tx_hcidata_complete(dhd_pub_t *dhdp, void *txp, bool success) ++{ ++ uint8 *pktdata = (uint8 *)PKTDATA(dhdp->osh, txp); ++ amp_hci_ACL_data_t *ACL_data = (amp_hci_ACL_data_t *)(pktdata + RFC1042_HDR_LEN); ++ uint16 handle = ltoh16(ACL_data->handle); ++ uint16 llh = HCI_ACL_DATA_HANDLE(handle); ++ ++ wl_event_msg_t event; ++ uint8 data[HCI_EVT_PREAMBLE_SIZE + sizeof(num_completed_data_blocks_evt_parms_t)]; ++ amp_hci_event_t *evt; ++ num_completed_data_blocks_evt_parms_t *parms; ++ ++ uint16 len = HCI_EVT_PREAMBLE_SIZE + sizeof(num_completed_data_blocks_evt_parms_t); ++ ++ /* update the event struct */ ++ memset(&event, 0, sizeof(event)); ++ event.version = hton16(BCM_EVENT_MSG_VERSION); ++ event.event_type = hton32(WLC_E_BTA_HCI_EVENT); ++ event.status = 0; ++ event.reason = 0; ++ event.auth_type = 0; ++ event.datalen = hton32(len); ++ event.flags = 0; ++ ++ /* generate Number of Completed Blocks event */ ++ evt = (amp_hci_event_t *)data; ++ evt->ecode = HCI_Number_of_Completed_Data_Blocks; ++ evt->plen = sizeof(num_completed_data_blocks_evt_parms_t); ++ ++ parms = (num_completed_data_blocks_evt_parms_t *)evt->parms; ++ htol16_ua_store(dhdp->maxdatablks, (uint8 *)&parms->num_blocks); ++ parms->num_handles = 1; ++ htol16_ua_store(llh, (uint8 *)&parms->completed[0].handle); ++ parms->completed[0].pkts = 1; ++ parms->completed[0].blocks = 1; ++ ++ dhd_sendup_event_common(dhdp, &event, data); ++} ++ ++/* event callback */ ++void ++dhd_bta_doevt(dhd_pub_t *dhdp, void *data_buf, uint data_len) ++{ ++ amp_hci_event_t *evt = (amp_hci_event_t *)data_buf; ++ ++ switch (evt->ecode) { ++ case HCI_Command_Complete: { ++ cmd_complete_parms_t *parms = (cmd_complete_parms_t *)evt->parms; ++ switch (ltoh16_ua((uint8 *)&parms->opcode)) { ++ case HCI_Read_Data_Block_Size: { ++ read_data_block_size_evt_parms_t *parms2 = ++ (read_data_block_size_evt_parms_t *)parms->parms; ++ dhdp->maxdatablks = ltoh16_ua((uint8 *)&parms2->data_block_num); ++ break; ++ } ++ } ++ break; ++ } ++ ++ case HCI_Flush_Occurred: { ++ flush_occurred_evt_parms_t *evt_parms = (flush_occurred_evt_parms_t *)evt->parms; ++ dhd_bta_flush_hcidata(dhdp, ltoh16_ua((uint8 *)&evt_parms->handle)); ++ break; ++ } ++ default: ++ break; ++ } ++} +diff --git a/drivers/net/wireless/ap6210/dhd_bta.h b/drivers/net/wireless/ap6210/dhd_bta.h +new file mode 100755 +index 0000000..0337f15 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_bta.h +@@ -0,0 +1,39 @@ ++/* ++ * BT-AMP support routines ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhd_bta.h 291086 2011-10-21 01:17:24Z $ ++ */ ++#ifndef __dhd_bta_h__ ++#define __dhd_bta_h__ ++ ++struct dhd_pub; ++ ++extern int dhd_bta_docmd(struct dhd_pub *pub, void *cmd_buf, uint cmd_len); ++ ++extern void dhd_bta_doevt(struct dhd_pub *pub, void *data_buf, uint data_len); ++ ++extern int dhd_bta_tx_hcidata(struct dhd_pub *pub, void *data_buf, uint data_len); ++extern void dhd_bta_tx_hcidata_complete(struct dhd_pub *dhdp, void *txp, bool success); ++ ++ ++#endif /* __dhd_bta_h__ */ +diff --git a/drivers/net/wireless/ap6210/dhd_bus.h b/drivers/net/wireless/ap6210/dhd_bus.h +new file mode 100755 +index 0000000..131907d +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_bus.h +@@ -0,0 +1,111 @@ ++/* ++ * Header file describing the internal (inter-module) DHD interfaces. ++ * ++ * Provides type definitions and function prototypes used to link the ++ * DHD OS, bus, and protocol modules. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhd_bus.h 347614 2012-07-27 10:24:51Z $ ++ */ ++ ++#ifndef _dhd_bus_h_ ++#define _dhd_bus_h_ ++ ++/* ++ * Exported from dhd bus module (dhd_usb, dhd_sdio) ++ */ ++ ++/* Indicate (dis)interest in finding dongles. */ ++extern int dhd_bus_register(void); ++extern void dhd_bus_unregister(void); ++ ++/* Download firmware image and nvram image */ ++extern bool dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh, ++ char *fw_path, char *nv_path); ++ ++/* Stop bus module: clear pending frames, disable data flow */ ++extern void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex); ++ ++/* Initialize bus module: prepare for communication w/dongle */ ++extern int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex); ++ ++/* Get the Bus Idle Time */ ++extern void dhd_bus_getidletime(dhd_pub_t *dhdp, int *idletime); ++ ++/* Set the Bus Idle Time */ ++extern void dhd_bus_setidletime(dhd_pub_t *dhdp, int idle_time); ++ ++/* Send a data frame to the dongle. Callee disposes of txp. */ ++extern int dhd_bus_txdata(struct dhd_bus *bus, void *txp, bool wlfc_locked); ++ ++/* Send/receive a control message to/from the dongle. ++ * Expects caller to enforce a single outstanding transaction. ++ */ ++extern int dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen); ++extern int dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen); ++ ++/* Watchdog timer function */ ++extern bool dhd_bus_watchdog(dhd_pub_t *dhd); ++extern void dhd_disable_intr(dhd_pub_t *dhd); ++ ++#if defined(DHD_DEBUG) ++/* Device console input function */ ++extern int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen); ++#endif /* defined(DHD_DEBUG) */ ++ ++/* Deferred processing for the bus, return TRUE requests reschedule */ ++extern bool dhd_bus_dpc(struct dhd_bus *bus); ++extern void dhd_bus_isr(bool * InterruptRecognized, bool * QueueMiniportHandleInterrupt, void *arg); ++ ++ ++/* Check for and handle local prot-specific iovar commands */ ++extern int dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name, ++ void *params, int plen, void *arg, int len, bool set); ++ ++/* Add bus dump output to a buffer */ ++extern void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf); ++ ++/* Clear any bus counters */ ++extern void dhd_bus_clearcounts(dhd_pub_t *dhdp); ++ ++/* return the dongle chipid */ ++extern uint dhd_bus_chip(struct dhd_bus *bus); ++ ++/* Set user-specified nvram parameters. */ ++extern void dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_params); ++ ++extern void *dhd_bus_pub(struct dhd_bus *bus); ++extern void *dhd_bus_txq(struct dhd_bus *bus); ++extern uint dhd_bus_hdrlen(struct dhd_bus *bus); ++ ++ ++#define DHD_SET_BUS_STATE_DOWN(_bus) do { \ ++ (_bus)->dhd->busstate = DHD_BUS_DOWN; \ ++} while (0) ++ ++/* Register a dummy SDIO client driver in order to be notified of new SDIO device */ ++extern int dhd_bus_reg_sdio_notify(void* semaphore); ++extern void dhd_bus_unreg_sdio_notify(void); ++ ++extern void dhd_txglom_enable(dhd_pub_t *dhdp, bool enable); ++ ++#endif /* _dhd_bus_h_ */ +diff --git a/drivers/net/wireless/ap6210/dhd_cdc.c b/drivers/net/wireless/ap6210/dhd_cdc.c +new file mode 100755 +index 0000000..3a7f55b +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_cdc.c +@@ -0,0 +1,3191 @@ ++/* ++ * DHD Protocol Module for CDC and BDC. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhd_cdc.c 368762 2012-11-14 21:59:17Z $ ++ * ++ * BDC is like CDC, except it includes a header for data packets to convey ++ * packet priority over the bus, and flags (e.g. to indicate checksum status ++ * for dongle offload.) ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++ ++#ifdef PROP_TXSTATUS ++#include ++#include ++#endif ++ ++#include ++ ++#define RETRIES 2 /* # of retries to retrieve matching ioctl response */ ++#define BUS_HEADER_LEN (24+DHD_SDALIGN) /* Must be at least SDPCM_RESERVE ++ * defined in dhd_sdio.c (amount of header tha might be added) ++ * plus any space that might be needed for alignment padding. ++ */ ++#define ROUND_UP_MARGIN 2048 /* Biggest SDIO block size possible for ++ * round off at the end of buffer ++ */ ++ ++#define BUS_RETRIES 1 /* # of retries before aborting a bus tx operation */ ++ ++#ifdef PROP_TXSTATUS ++typedef struct dhd_wlfc_commit_info { ++ uint8 needs_hdr; ++ uint8 ac_fifo_credit_spent; ++ ewlfc_packet_state_t pkt_type; ++ wlfc_mac_descriptor_t* mac_entry; ++ void* p; ++} dhd_wlfc_commit_info_t; ++#endif /* PROP_TXSTATUS */ ++ ++ ++typedef struct dhd_prot { ++ uint16 reqid; ++ uint8 pending; ++ uint32 lastcmd; ++ uint8 bus_header[BUS_HEADER_LEN]; ++ cdc_ioctl_t msg; ++ unsigned char buf[WLC_IOCTL_MAXLEN + ROUND_UP_MARGIN]; ++} dhd_prot_t; ++ ++ ++static int ++dhdcdc_msg(dhd_pub_t *dhd) ++{ ++ int err = 0; ++ dhd_prot_t *prot = dhd->prot; ++ int len = ltoh32(prot->msg.len) + sizeof(cdc_ioctl_t); ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ DHD_OS_WAKE_LOCK(dhd); ++ ++ /* NOTE : cdc->msg.len holds the desired length of the buffer to be ++ * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area ++ * is actually sent to the dongle ++ */ ++ if (len > CDC_MAX_MSG_SIZE) ++ len = CDC_MAX_MSG_SIZE; ++ ++ /* Send request */ ++ err = dhd_bus_txctl(dhd->bus, (uchar*)&prot->msg, len); ++ ++ DHD_OS_WAKE_UNLOCK(dhd); ++ return err; ++} ++ ++static int ++dhdcdc_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len) ++{ ++ int ret; ++ int cdc_len = len + sizeof(cdc_ioctl_t); ++ dhd_prot_t *prot = dhd->prot; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ do { ++ ret = dhd_bus_rxctl(dhd->bus, (uchar*)&prot->msg, cdc_len); ++ if (ret < 0) ++ break; ++ } while (CDC_IOC_ID(ltoh32(prot->msg.flags)) != id); ++ ++ return ret; ++} ++ ++static int ++dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action) ++{ ++ dhd_prot_t *prot = dhd->prot; ++ cdc_ioctl_t *msg = &prot->msg; ++ void *info; ++ int ret = 0, retries = 0; ++ uint32 id, flags = 0; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ AP6210_DEBUG("%s: cmd %d len %d\n", __FUNCTION__, cmd, len); ++ ++ ++ /* Respond "bcmerror" and "bcmerrorstr" with local cache */ ++ if (cmd == WLC_GET_VAR && buf) ++ { ++ if (!strcmp((char *)buf, "bcmerrorstr")) ++ { ++ strncpy((char *)buf, bcmerrorstr(dhd->dongle_error), BCME_STRLEN); ++ goto done; ++ } ++ else if (!strcmp((char *)buf, "bcmerror")) ++ { ++ *(int *)buf = dhd->dongle_error; ++ goto done; ++ } ++ } ++ ++ memset(msg, 0, sizeof(cdc_ioctl_t)); ++ ++ msg->cmd = htol32(cmd); ++ msg->len = htol32(len); ++ msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT); ++ CDC_SET_IF_IDX(msg, ifidx); ++ /* add additional action bits */ ++ action &= WL_IOCTL_ACTION_MASK; ++ msg->flags |= (action << CDCF_IOC_ACTION_SHIFT); ++ msg->flags = htol32(msg->flags); ++ ++ if (buf) ++ memcpy(prot->buf, buf, len); ++ ++ if ((ret = dhdcdc_msg(dhd)) < 0) { ++ if (!dhd->hang_was_sent) ++ AP6210_ERR("dhdcdc_query_ioctl: dhdcdc_msg failed w/status %d\n", ret); ++ goto done; ++ } ++ ++retry: ++ /* wait for interrupt and get first fragment */ ++ if ((ret = dhdcdc_cmplt(dhd, prot->reqid, len)) < 0) ++ goto done; ++ ++ flags = ltoh32(msg->flags); ++ id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT; ++ ++ if ((id < prot->reqid) && (++retries < RETRIES)) ++ goto retry; ++ if (id != prot->reqid) { ++ AP6210_ERR("%s: %s: unexpected request id %d (expected %d)\n", ++ dhd_ifname(dhd, ifidx), __FUNCTION__, id, prot->reqid); ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ /* Check info buffer */ ++ info = (void*)&msg[1]; ++ ++ /* Copy info buffer */ ++ if (buf) ++ { ++ if (ret < (int)len) ++ len = ret; ++ memcpy(buf, info, len); ++ } ++ ++ /* Check the ERROR flag */ ++ if (flags & CDCF_IOC_ERROR) ++ { ++ ret = ltoh32(msg->status); ++ /* Cache error from dongle */ ++ dhd->dongle_error = ret; ++ } ++ ++done: ++ return ret; ++} ++ ++static int ++dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action) ++{ ++ dhd_prot_t *prot = dhd->prot; ++ cdc_ioctl_t *msg = &prot->msg; ++ int ret = 0; ++ uint32 flags, id; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ AP6210_DEBUG("%s: cmd %d len %d\n", __FUNCTION__, cmd, len); ++ ++ if (dhd->busstate == DHD_BUS_DOWN) { ++ AP6210_ERR("%s : bus is down. we have nothing to do\n", __FUNCTION__); ++ return -EIO; ++ } ++ ++ /* don't talk to the dongle if fw is about to be reloaded */ ++ if (dhd->hang_was_sent) { ++ AP6210_ERR("%s: HANG was sent up earlier. Not talking to the chip\n", ++ __FUNCTION__); ++ return -EIO; ++ } ++ ++ memset(msg, 0, sizeof(cdc_ioctl_t)); ++ ++ msg->cmd = htol32(cmd); ++ msg->len = htol32(len); ++ msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT); ++ CDC_SET_IF_IDX(msg, ifidx); ++ /* add additional action bits */ ++ action &= WL_IOCTL_ACTION_MASK; ++ msg->flags |= (action << CDCF_IOC_ACTION_SHIFT) | CDCF_IOC_SET; ++ msg->flags = htol32(msg->flags); ++ ++ if (buf) ++ memcpy(prot->buf, buf, len); ++ ++ if ((ret = dhdcdc_msg(dhd)) < 0) { ++ AP6210_ERR("%s: dhdcdc_msg failed w/status %d\n", __FUNCTION__, ret); ++ goto done; ++ } ++ ++ if ((ret = dhdcdc_cmplt(dhd, prot->reqid, len)) < 0) ++ goto done; ++ ++ flags = ltoh32(msg->flags); ++ id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT; ++ ++ if (id != prot->reqid) { ++ AP6210_ERR("%s: %s: unexpected request id %d (expected %d)\n", ++ dhd_ifname(dhd, ifidx), __FUNCTION__, id, prot->reqid); ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ /* Check the ERROR flag */ ++ if (flags & CDCF_IOC_ERROR) ++ { ++ ret = ltoh32(msg->status); ++ /* Cache error from dongle */ ++ dhd->dongle_error = ret; ++ } ++ ++done: ++ return ret; ++} ++ ++ ++int ++dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len) ++{ ++ dhd_prot_t *prot = dhd->prot; ++ int ret = -1; ++ uint8 action; ++#if defined(NDIS630) ++ bool acquired = FALSE; ++#endif ++ ++ if ((dhd->busstate == DHD_BUS_DOWN) || dhd->hang_was_sent) { ++ AP6210_ERR("%s : bus is down. we have nothing to do\n", __FUNCTION__); ++ goto done; ++ } ++#if defined(NDIS630) ++ if (dhd_os_proto_block(dhd)) ++ { ++ acquired = TRUE; ++ } ++ else ++ { ++ /* attempt to acquire protocol mutex timed out. */ ++ ret = -1; ++ return ret; ++ } ++#endif /* NDIS630 */ ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ ASSERT(len <= WLC_IOCTL_MAXLEN); ++ ++ if (len > WLC_IOCTL_MAXLEN) ++ goto done; ++ ++ if (prot->pending == TRUE) { ++ AP6210_ERR("CDC packet is pending!!!! cmd=0x%x (%lu) lastcmd=0x%x (%lu)\n", ++ ioc->cmd, (unsigned long)ioc->cmd, prot->lastcmd, ++ (unsigned long)prot->lastcmd); ++ if ((ioc->cmd == WLC_SET_VAR) || (ioc->cmd == WLC_GET_VAR)) { ++ AP6210_DEBUG("iovar cmd=%s\n", (char*)buf); ++ } ++ goto done; ++ } ++ ++ prot->pending = TRUE; ++ prot->lastcmd = ioc->cmd; ++ action = ioc->set; ++ if (action & WL_IOCTL_ACTION_SET) ++ ret = dhdcdc_set_ioctl(dhd, ifidx, ioc->cmd, buf, len, action); ++ else { ++ ret = dhdcdc_query_ioctl(dhd, ifidx, ioc->cmd, buf, len, action); ++ if (ret > 0) ++ ioc->used = ret - sizeof(cdc_ioctl_t); ++ } ++ ++ /* Too many programs assume ioctl() returns 0 on success */ ++ if (ret >= 0) ++ ret = 0; ++ else { ++ cdc_ioctl_t *msg = &prot->msg; ++ ioc->needed = ltoh32(msg->len); /* len == needed when set/query fails from dongle */ ++ } ++ ++ /* Intercept the wme_dp ioctl here */ ++ if ((!ret) && (ioc->cmd == WLC_SET_VAR) && (!strcmp(buf, "wme_dp"))) { ++ int slen, val = 0; ++ ++ slen = strlen("wme_dp") + 1; ++ if (len >= (int)(slen + sizeof(int))) ++ bcopy(((char *)buf + slen), &val, sizeof(int)); ++ dhd->wme_dp = (uint8) ltoh32(val); ++ } ++ ++ prot->pending = FALSE; ++ ++done: ++#if defined(NDIS630) ++ if (acquired) ++ dhd_os_proto_unblock(dhd); ++#endif ++ return ret; ++} ++ ++int ++dhd_prot_iovar_op(dhd_pub_t *dhdp, const char *name, ++ void *params, int plen, void *arg, int len, bool set) ++{ ++ return BCME_UNSUPPORTED; ++} ++ ++#ifdef PROP_TXSTATUS ++void ++dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) ++{ ++ int i; ++ uint8* ea; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhdp->wlfc_state; ++ wlfc_hanger_t* h; ++ wlfc_mac_descriptor_t* mac_table; ++ wlfc_mac_descriptor_t* interfaces; ++ char* iftypes[] = {"STA", "AP", "WDS", "p2pGO", "p2pCL"}; ++ ++ if (wlfc == NULL) { ++ bcm_bprintf(strbuf, "wlfc not initialized yet\n"); ++ return; ++ } ++ h = (wlfc_hanger_t*)wlfc->hanger; ++ if (h == NULL) { ++ bcm_bprintf(strbuf, "wlfc-hanger not initialized yet\n"); ++ } ++ ++ mac_table = wlfc->destination_entries.nodes; ++ interfaces = wlfc->destination_entries.interfaces; ++ bcm_bprintf(strbuf, "---- wlfc stats ----\n"); ++ if (h) { ++ bcm_bprintf(strbuf, "wlfc hanger (pushed,popped,f_push," ++ "f_pop,f_slot, pending) = (%d,%d,%d,%d,%d,%d)\n", ++ h->pushed, ++ h->popped, ++ h->failed_to_push, ++ h->failed_to_pop, ++ h->failed_slotfind, ++ (h->pushed - h->popped)); ++ } ++ ++ bcm_bprintf(strbuf, "wlfc fail(tlv,credit_rqst,mac_update,psmode_update), " ++ "(dq_full,sendq_full, rollback_fail) = (%d,%d,%d,%d), (%d,%d,%d)\n", ++ wlfc->stats.tlv_parse_failed, ++ wlfc->stats.credit_request_failed, ++ wlfc->stats.mac_update_failed, ++ wlfc->stats.psmode_update_failed, ++ wlfc->stats.delayq_full_error, ++ wlfc->stats.sendq_full_error, ++ wlfc->stats.rollback_failed); ++ ++ bcm_bprintf(strbuf, "SENDQ (len,credit,sent) " ++ "(AC0[%d,%d,%d],AC1[%d,%d,%d],AC2[%d,%d,%d],AC3[%d,%d,%d],BC_MC[%d,%d,%d])\n", ++ wlfc->SENDQ.q[0].len, wlfc->FIFO_credit[0], wlfc->stats.sendq_pkts[0], ++ wlfc->SENDQ.q[1].len, wlfc->FIFO_credit[1], wlfc->stats.sendq_pkts[1], ++ wlfc->SENDQ.q[2].len, wlfc->FIFO_credit[2], wlfc->stats.sendq_pkts[2], ++ wlfc->SENDQ.q[3].len, wlfc->FIFO_credit[3], wlfc->stats.sendq_pkts[3], ++ wlfc->SENDQ.q[4].len, wlfc->FIFO_credit[4], wlfc->stats.sendq_pkts[4]); ++ ++#ifdef PROP_TXSTATUS_DEBUG ++ bcm_bprintf(strbuf, "SENDQ dropped: AC[0-3]:(%d,%d,%d,%d), (bcmc,atim):(%d,%d)\n", ++ wlfc->stats.dropped_qfull[0], wlfc->stats.dropped_qfull[1], ++ wlfc->stats.dropped_qfull[2], wlfc->stats.dropped_qfull[3], ++ wlfc->stats.dropped_qfull[4], wlfc->stats.dropped_qfull[5]); ++#endif ++ ++ bcm_bprintf(strbuf, "\n"); ++ for (i = 0; i < WLFC_MAX_IFNUM; i++) { ++ if (interfaces[i].occupied) { ++ char* iftype_desc; ++ ++ if (interfaces[i].iftype > WLC_E_IF_ROLE_P2P_CLIENT) ++ iftype_desc = "hostif_flow_state[i] == OFF) ++ ? " OFF":" ON")); ++ ++ bcm_bprintf(strbuf, "INTERFACE[%d].DELAYQ(len,state,credit)" ++ "= (%d,%s,%d)\n", ++ i, ++ interfaces[i].psq.len, ++ ((interfaces[i].state == ++ WLFC_STATE_OPEN) ? " OPEN":"CLOSE"), ++ interfaces[i].requested_credit); ++ ++ bcm_bprintf(strbuf, "INTERFACE[%d].DELAYQ" ++ "(sup,ac0),(sup,ac1),(sup,ac2),(sup,ac3) = " ++ "(%d,%d),(%d,%d),(%d,%d),(%d,%d)\n", ++ i, ++ interfaces[i].psq.q[0].len, ++ interfaces[i].psq.q[1].len, ++ interfaces[i].psq.q[2].len, ++ interfaces[i].psq.q[3].len, ++ interfaces[i].psq.q[4].len, ++ interfaces[i].psq.q[5].len, ++ interfaces[i].psq.q[6].len, ++ interfaces[i].psq.q[7].len); ++ } ++ } ++ ++ bcm_bprintf(strbuf, "\n"); ++ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { ++ if (mac_table[i].occupied) { ++ ea = mac_table[i].ea; ++ bcm_bprintf(strbuf, "MAC_table[%d].ea = " ++ "[%02x:%02x:%02x:%02x:%02x:%02x], if:%d \n", i, ++ ea[0], ea[1], ea[2], ea[3], ea[4], ea[5], ++ mac_table[i].interface_id); ++ ++ bcm_bprintf(strbuf, "MAC_table[%d].DELAYQ(len,state,credit)" ++ "= (%d,%s,%d)\n", ++ i, ++ mac_table[i].psq.len, ++ ((mac_table[i].state == ++ WLFC_STATE_OPEN) ? " OPEN":"CLOSE"), ++ mac_table[i].requested_credit); ++#ifdef PROP_TXSTATUS_DEBUG ++ bcm_bprintf(strbuf, "MAC_table[%d]: (opened, closed) = (%d, %d)\n", ++ i, mac_table[i].opened_ct, mac_table[i].closed_ct); ++#endif ++ bcm_bprintf(strbuf, "MAC_table[%d].DELAYQ" ++ "(sup,ac0),(sup,ac1),(sup,ac2),(sup,ac3) = " ++ "(%d,%d),(%d,%d),(%d,%d),(%d,%d)\n", ++ i, ++ mac_table[i].psq.q[0].len, ++ mac_table[i].psq.q[1].len, ++ mac_table[i].psq.q[2].len, ++ mac_table[i].psq.q[3].len, ++ mac_table[i].psq.q[4].len, ++ mac_table[i].psq.q[5].len, ++ mac_table[i].psq.q[6].len, ++ mac_table[i].psq.q[7].len); ++ } ++ } ++ ++#ifdef PROP_TXSTATUS_DEBUG ++ { ++ int avg; ++ int moving_avg = 0; ++ int moving_samples; ++ ++ if (wlfc->stats.latency_sample_count) { ++ moving_samples = sizeof(wlfc->stats.deltas)/sizeof(uint32); ++ ++ for (i = 0; i < moving_samples; i++) ++ moving_avg += wlfc->stats.deltas[i]; ++ moving_avg /= moving_samples; ++ ++ avg = (100 * wlfc->stats.total_status_latency) / ++ wlfc->stats.latency_sample_count; ++ bcm_bprintf(strbuf, "txstatus latency (average, last, moving[%d]) = " ++ "(%d.%d, %03d, %03d)\n", ++ moving_samples, avg/100, (avg - (avg/100)*100), ++ wlfc->stats.latency_most_recent, ++ moving_avg); ++ } ++ } ++ ++ bcm_bprintf(strbuf, "wlfc- fifo[0-5] credit stats: sent = (%d,%d,%d,%d,%d,%d), " ++ "back = (%d,%d,%d,%d,%d,%d)\n", ++ wlfc->stats.fifo_credits_sent[0], ++ wlfc->stats.fifo_credits_sent[1], ++ wlfc->stats.fifo_credits_sent[2], ++ wlfc->stats.fifo_credits_sent[3], ++ wlfc->stats.fifo_credits_sent[4], ++ wlfc->stats.fifo_credits_sent[5], ++ ++ wlfc->stats.fifo_credits_back[0], ++ wlfc->stats.fifo_credits_back[1], ++ wlfc->stats.fifo_credits_back[2], ++ wlfc->stats.fifo_credits_back[3], ++ wlfc->stats.fifo_credits_back[4], ++ wlfc->stats.fifo_credits_back[5]); ++ { ++ uint32 fifo_cr_sent = 0; ++ uint32 fifo_cr_acked = 0; ++ uint32 request_cr_sent = 0; ++ uint32 request_cr_ack = 0; ++ uint32 bc_mc_cr_ack = 0; ++ ++ for (i = 0; i < sizeof(wlfc->stats.fifo_credits_sent)/sizeof(uint32); i++) { ++ fifo_cr_sent += wlfc->stats.fifo_credits_sent[i]; ++ } ++ ++ for (i = 0; i < sizeof(wlfc->stats.fifo_credits_back)/sizeof(uint32); i++) { ++ fifo_cr_acked += wlfc->stats.fifo_credits_back[i]; ++ } ++ ++ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { ++ if (wlfc->destination_entries.nodes[i].occupied) { ++ request_cr_sent += ++ wlfc->destination_entries.nodes[i].dstncredit_sent_packets; ++ } ++ } ++ for (i = 0; i < WLFC_MAX_IFNUM; i++) { ++ if (wlfc->destination_entries.interfaces[i].occupied) { ++ request_cr_sent += ++ wlfc->destination_entries.interfaces[i].dstncredit_sent_packets; ++ } ++ } ++ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { ++ if (wlfc->destination_entries.nodes[i].occupied) { ++ request_cr_ack += ++ wlfc->destination_entries.nodes[i].dstncredit_acks; ++ } ++ } ++ for (i = 0; i < WLFC_MAX_IFNUM; i++) { ++ if (wlfc->destination_entries.interfaces[i].occupied) { ++ request_cr_ack += ++ wlfc->destination_entries.interfaces[i].dstncredit_acks; ++ } ++ } ++ bcm_bprintf(strbuf, "wlfc- (sent, status) => pq(%d,%d), vq(%d,%d)," ++ "other:%d, bc_mc:%d, signal-only, (sent,freed): (%d,%d)", ++ fifo_cr_sent, fifo_cr_acked, ++ request_cr_sent, request_cr_ack, ++ wlfc->destination_entries.other.dstncredit_acks, ++ bc_mc_cr_ack, ++ wlfc->stats.signal_only_pkts_sent, wlfc->stats.signal_only_pkts_freed); ++ } ++#endif /* PROP_TXSTATUS_DEBUG */ ++ bcm_bprintf(strbuf, "\n"); ++ bcm_bprintf(strbuf, "wlfc- pkt((in,2bus,txstats,hdrpull),(dropped,hdr_only,wlc_tossed)" ++ "(freed,free_err,rollback)) = " ++ "((%d,%d,%d,%d),(%d,%d,%d),(%d,%d,%d))\n", ++ wlfc->stats.pktin, ++ wlfc->stats.pkt2bus, ++ wlfc->stats.txstatus_in, ++ wlfc->stats.dhd_hdrpulls, ++ ++ wlfc->stats.pktdropped, ++ wlfc->stats.wlfc_header_only_pkt, ++ wlfc->stats.wlc_tossed_pkts, ++ ++ wlfc->stats.pkt_freed, ++ wlfc->stats.pkt_free_err, wlfc->stats.rollback); ++ ++ bcm_bprintf(strbuf, "wlfc- suppress((d11,wlc,err),enq(d11,wl,hq,mac?),retx(d11,wlc,hq)) = " ++ "((%d,%d,%d),(%d,%d,%d,%d),(%d,%d,%d))\n", ++ ++ wlfc->stats.d11_suppress, ++ wlfc->stats.wl_suppress, ++ wlfc->stats.bad_suppress, ++ ++ wlfc->stats.psq_d11sup_enq, ++ wlfc->stats.psq_wlsup_enq, ++ wlfc->stats.psq_hostq_enq, ++ wlfc->stats.mac_handle_notfound, ++ ++ wlfc->stats.psq_d11sup_retx, ++ wlfc->stats.psq_wlsup_retx, ++ wlfc->stats.psq_hostq_retx); ++ return; ++} ++ ++/* Create a place to store all packet pointers submitted to the firmware until ++ a status comes back, suppress or otherwise. ++ ++ hang-er: noun, a contrivance on which things are hung, as a hook. ++*/ ++static void* ++dhd_wlfc_hanger_create(osl_t *osh, int max_items) ++{ ++ int i; ++ wlfc_hanger_t* hanger; ++ ++ /* allow only up to a specific size for now */ ++ ASSERT(max_items == WLFC_HANGER_MAXITEMS); ++ ++ if ((hanger = (wlfc_hanger_t*)MALLOC(osh, WLFC_HANGER_SIZE(max_items))) == NULL) ++ return NULL; ++ ++ memset(hanger, 0, WLFC_HANGER_SIZE(max_items)); ++ hanger->max_items = max_items; ++ ++ for (i = 0; i < hanger->max_items; i++) { ++ hanger->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; ++ } ++ return hanger; ++} ++ ++static int ++dhd_wlfc_hanger_delete(osl_t *osh, void* hanger) ++{ ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; ++ ++ if (h) { ++ MFREE(osh, h, WLFC_HANGER_SIZE(h->max_items)); ++ return BCME_OK; ++ } ++ return BCME_BADARG; ++} ++ ++static uint16 ++dhd_wlfc_hanger_get_free_slot(void* hanger) ++{ ++ uint32 i; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; ++ ++ if (h) { ++ for (i = (h->slot_pos + 1); i != h->slot_pos;) { ++ if (h->items[i].state == WLFC_HANGER_ITEM_STATE_FREE) { ++ h->slot_pos = i; ++ return (uint16)i; ++ } ++ (i == h->max_items)? i = 0 : i++; ++ } ++ h->failed_slotfind++; ++ } ++ return WLFC_HANGER_MAXITEMS; ++} ++ ++static int ++dhd_wlfc_hanger_get_genbit(void* hanger, void* pkt, uint32 slot_id, int* gen) ++{ ++ int rc = BCME_OK; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; ++ ++ *gen = 0xff; ++ ++ /* this packet was not pushed at the time it went to the firmware */ ++ if (slot_id == WLFC_HANGER_MAXITEMS) ++ return BCME_NOTFOUND; ++ ++ if (h) { ++ if ((h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE) || ++ (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED)) { ++ *gen = h->items[slot_id].gen; ++ } ++ else { ++ rc = BCME_NOTFOUND; ++ } ++ } ++ else ++ rc = BCME_BADARG; ++ return rc; ++} ++ ++static int ++dhd_wlfc_hanger_pushpkt(void* hanger, void* pkt, uint32 slot_id) ++{ ++ int rc = BCME_OK; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; ++ ++ if (h && (slot_id < WLFC_HANGER_MAXITEMS)) { ++ if (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_FREE) { ++ h->items[slot_id].state = WLFC_HANGER_ITEM_STATE_INUSE; ++ h->items[slot_id].pkt = pkt; ++ h->items[slot_id].identifier = slot_id; ++ h->pushed++; ++ } ++ else { ++ h->failed_to_push++; ++ rc = BCME_NOTFOUND; ++ } ++ } ++ else ++ rc = BCME_BADARG; ++ return rc; ++} ++ ++static int ++dhd_wlfc_hanger_poppkt(void* hanger, uint32 slot_id, void** pktout, int remove_from_hanger) ++{ ++ int rc = BCME_OK; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; ++ ++ /* this packet was not pushed at the time it went to the firmware */ ++ if (slot_id == WLFC_HANGER_MAXITEMS) ++ return BCME_NOTFOUND; ++ ++ if (h) { ++ if (h->items[slot_id].state != WLFC_HANGER_ITEM_STATE_FREE) { ++ *pktout = h->items[slot_id].pkt; ++ if (remove_from_hanger) { ++ h->items[slot_id].state = ++ WLFC_HANGER_ITEM_STATE_FREE; ++ h->items[slot_id].pkt = NULL; ++ h->items[slot_id].identifier = 0; ++ h->items[slot_id].gen = 0xff; ++ h->popped++; ++ } ++ } ++ else { ++ h->failed_to_pop++; ++ rc = BCME_NOTFOUND; ++ } ++ } ++ else ++ rc = BCME_BADARG; ++ return rc; ++} ++ ++static int ++dhd_wlfc_hanger_mark_suppressed(void* hanger, uint32 slot_id, uint8 gen) ++{ ++ int rc = BCME_OK; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; ++ ++ /* this packet was not pushed at the time it went to the firmware */ ++ if (slot_id == WLFC_HANGER_MAXITEMS) ++ return BCME_NOTFOUND; ++ if (h) { ++ h->items[slot_id].gen = gen; ++ if (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE) { ++ h->items[slot_id].state = WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED; ++ } ++ else ++ rc = BCME_BADARG; ++ } ++ else ++ rc = BCME_BADARG; ++ ++ return rc; ++} ++ ++static int ++_dhd_wlfc_pushheader(athost_wl_status_info_t* ctx, void* p, bool tim_signal, ++ uint8 tim_bmp, uint8 mac_handle, uint32 htodtag) ++{ ++ uint32 wl_pktinfo = 0; ++ uint8* wlh; ++ uint8 dataOffset; ++ uint8 fillers; ++ uint8 tim_signal_len = 0; ++ ++ struct bdc_header *h; ++ ++ if (tim_signal) { ++ tim_signal_len = 1 + 1 + WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP; ++ } ++ ++ /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */ ++ dataOffset = WLFC_CTL_VALUE_LEN_PKTTAG + 2 + tim_signal_len; ++ fillers = ROUNDUP(dataOffset, 4) - dataOffset; ++ dataOffset += fillers; ++ ++ PKTPUSH(ctx->osh, p, dataOffset); ++ wlh = (uint8*) PKTDATA(ctx->osh, p); ++ ++ wl_pktinfo = htol32(htodtag); ++ ++ wlh[0] = WLFC_CTL_TYPE_PKTTAG; ++ wlh[1] = WLFC_CTL_VALUE_LEN_PKTTAG; ++ memcpy(&wlh[2], &wl_pktinfo, sizeof(uint32)); ++ ++ if (tim_signal_len) { ++ wlh[dataOffset - fillers - tim_signal_len ] = ++ WLFC_CTL_TYPE_PENDING_TRAFFIC_BMP; ++ wlh[dataOffset - fillers - tim_signal_len + 1] = ++ WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP; ++ wlh[dataOffset - fillers - tim_signal_len + 2] = mac_handle; ++ wlh[dataOffset - fillers - tim_signal_len + 3] = tim_bmp; ++ } ++ if (fillers) ++ memset(&wlh[dataOffset - fillers], WLFC_CTL_TYPE_FILLER, fillers); ++ ++ PKTPUSH(ctx->osh, p, BDC_HEADER_LEN); ++ h = (struct bdc_header *)PKTDATA(ctx->osh, p); ++ h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); ++ if (PKTSUMNEEDED(p)) ++ h->flags |= BDC_FLAG_SUM_NEEDED; ++ ++ ++ h->priority = (PKTPRIO(p) & BDC_PRIORITY_MASK); ++ h->flags2 = 0; ++ h->dataOffset = dataOffset >> 2; ++ BDC_SET_IF_IDX(h, DHD_PKTTAG_IF(PKTTAG(p))); ++ return BCME_OK; ++} ++ ++static int ++_dhd_wlfc_pullheader(athost_wl_status_info_t* ctx, void* pktbuf) ++{ ++ struct bdc_header *h; ++ ++ if (PKTLEN(ctx->osh, pktbuf) < BDC_HEADER_LEN) { ++ AP6210_DEBUG("%s: rx data too short (%d < %d)\n", __FUNCTION__, ++ PKTLEN(ctx->osh, pktbuf), BDC_HEADER_LEN); ++ return BCME_ERROR; ++ } ++ h = (struct bdc_header *)PKTDATA(ctx->osh, pktbuf); ++ ++ /* pull BDC header */ ++ PKTPULL(ctx->osh, pktbuf, BDC_HEADER_LEN); ++ ++ if (PKTLEN(ctx->osh, pktbuf) < (h->dataOffset << 2)) { ++ AP6210_DEBUG("%s: rx data too short (%d < %d)\n", __FUNCTION__, ++ PKTLEN(ctx->osh, pktbuf), (h->dataOffset << 2)); ++ return BCME_ERROR; ++ } ++ /* pull wl-header */ ++ PKTPULL(ctx->osh, pktbuf, (h->dataOffset << 2)); ++ return BCME_OK; ++} ++ ++static wlfc_mac_descriptor_t* ++_dhd_wlfc_find_table_entry(athost_wl_status_info_t* ctx, void* p) ++{ ++ int i; ++ wlfc_mac_descriptor_t* table = ctx->destination_entries.nodes; ++ uint8 ifid = DHD_PKTTAG_IF(PKTTAG(p)); ++ uint8* dstn = DHD_PKTTAG_DSTN(PKTTAG(p)); ++ ++ if (((ctx->destination_entries.interfaces[ifid].iftype == WLC_E_IF_ROLE_STA) || ++ ETHER_ISMULTI(dstn) || ++ (ctx->destination_entries.interfaces[ifid].iftype == WLC_E_IF_ROLE_P2P_CLIENT)) && ++ (ctx->destination_entries.interfaces[ifid].occupied)) { ++ return &ctx->destination_entries.interfaces[ifid]; ++ } ++ ++ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { ++ if (table[i].occupied) { ++ if (table[i].interface_id == ifid) { ++ if (!memcmp(table[i].ea, dstn, ETHER_ADDR_LEN)) ++ return &table[i]; ++ } ++ } ++ } ++ return &ctx->destination_entries.other; ++} ++ ++static int ++_dhd_wlfc_rollback_packet_toq(athost_wl_status_info_t* ctx, ++ void* p, ewlfc_packet_state_t pkt_type, uint32 hslot) ++{ ++ /* ++ put the packet back to the head of queue ++ ++ - a packet from send-q will need to go back to send-q and not delay-q ++ since that will change the order of packets. ++ - suppressed packet goes back to suppress sub-queue ++ - pull out the header, if new or delayed packet ++ ++ Note: hslot is used only when header removal is done. ++ */ ++ wlfc_mac_descriptor_t* entry; ++ void* pktout; ++ int rc = BCME_OK; ++ int prec; ++ ++ entry = _dhd_wlfc_find_table_entry(ctx, p); ++ prec = DHD_PKTTAG_FIFO(PKTTAG(p)); ++ if (entry != NULL) { ++ if (pkt_type == eWLFC_PKTTYPE_SUPPRESSED) { ++ /* wl-header is saved for suppressed packets */ ++ if (WLFC_PKTQ_PENQ_HEAD(&entry->psq, ((prec << 1) + 1), p) == NULL) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ rc = BCME_ERROR; ++ } ++ } ++ else { ++ /* remove header first */ ++ rc = _dhd_wlfc_pullheader(ctx, p); ++ if (rc != BCME_OK) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ /* free the hanger slot */ ++ dhd_wlfc_hanger_poppkt(ctx->hanger, hslot, &pktout, 1); ++ PKTFREE(ctx->osh, p, TRUE); ++ rc = BCME_ERROR; ++ return rc; ++ } ++ ++ if (pkt_type == eWLFC_PKTTYPE_DELAYED) { ++ /* delay-q packets are going to delay-q */ ++ if (WLFC_PKTQ_PENQ_HEAD(&entry->psq, (prec << 1), p) == NULL) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ rc = BCME_ERROR; ++ } ++ } ++ else { ++ /* these are going to SENDQ */ ++ if (WLFC_PKTQ_PENQ_HEAD(&ctx->SENDQ, prec, p) == NULL) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ rc = BCME_ERROR; ++ } ++ } ++ /* free the hanger slot */ ++ dhd_wlfc_hanger_poppkt(ctx->hanger, hslot, &pktout, 1); ++ ++ /* decrement sequence count */ ++ WLFC_DECR_SEQCOUNT(entry, prec); ++ } ++ /* ++ if this packet did not count against FIFO credit, it must have ++ taken a requested_credit from the firmware (for pspoll etc.) ++ */ ++ if (!DHD_PKTTAG_CREDITCHECK(PKTTAG(p))) { ++ entry->requested_credit++; ++ } ++ } ++ else { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ rc = BCME_ERROR; ++ } ++ if (rc != BCME_OK) ++ ctx->stats.rollback_failed++; ++ else ++ ctx->stats.rollback++; ++ ++ return rc; ++} ++ ++static void ++_dhd_wlfc_flow_control_check(athost_wl_status_info_t* ctx, struct pktq* pq, uint8 if_id) ++{ ++ if ((pq->len <= WLFC_FLOWCONTROL_LOWATER) && (ctx->hostif_flow_state[if_id] == ON)) { ++ /* start traffic */ ++ ctx->hostif_flow_state[if_id] = OFF; ++ /* ++ AP6210_DEBUG("qlen:%02d, if:%02d, ->OFF, start traffic %s()\n", ++ pq->len, if_id, __FUNCTION__); ++ */ ++ AP6210_DEBUG("F"); ++ dhd_txflowcontrol(ctx->dhdp, if_id, OFF); ++ ctx->toggle_host_if = 0; ++ } ++ if ((pq->len >= WLFC_FLOWCONTROL_HIWATER) && (ctx->hostif_flow_state[if_id] == OFF)) { ++ /* stop traffic */ ++ ctx->hostif_flow_state[if_id] = ON; ++ /* ++ AP6210_DEBUG("qlen:%02d, if:%02d, ->ON, stop traffic %s()\n", ++ pq->len, if_id, __FUNCTION__); ++ */ ++ AP6210_DEBUG("N"); ++ dhd_txflowcontrol(ctx->dhdp, if_id, ON); ++ ctx->host_ifidx = if_id; ++ ctx->toggle_host_if = 1; ++ } ++ return; ++} ++ ++static int ++_dhd_wlfc_send_signalonly_packet(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry, ++ uint8 ta_bmp) ++{ ++ int rc = BCME_OK; ++ void* p = NULL; ++ int dummylen = ((dhd_pub_t *)ctx->dhdp)->hdrlen+ 12; ++ ++ /* allocate a dummy packet */ ++ p = PKTGET(ctx->osh, dummylen, TRUE); ++ if (p) { ++ PKTPULL(ctx->osh, p, dummylen); ++ DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), 0); ++ _dhd_wlfc_pushheader(ctx, p, TRUE, ta_bmp, entry->mac_handle, 0); ++ DHD_PKTTAG_SETSIGNALONLY(PKTTAG(p), 1); ++#ifdef PROP_TXSTATUS_DEBUG ++ ctx->stats.signal_only_pkts_sent++; ++#endif ++ rc = dhd_bus_txdata(((dhd_pub_t *)ctx->dhdp)->bus, p, FALSE); ++ if (rc != BCME_OK) { ++ PKTFREE(ctx->osh, p, TRUE); ++ } ++ } ++ else { ++ AP6210_ERR("%s: couldn't allocate new %d-byte packet\n", ++ __FUNCTION__, dummylen); ++ rc = BCME_NOMEM; ++ } ++ return rc; ++} ++ ++/* Return TRUE if traffic availability changed */ ++static bool ++_dhd_wlfc_traffic_pending_check(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry, ++ int prec) ++{ ++ bool rc = FALSE; ++ ++ if (entry->state == WLFC_STATE_CLOSE) { ++ if ((pktq_plen(&entry->psq, (prec << 1)) == 0) && ++ (pktq_plen(&entry->psq, ((prec << 1) + 1)) == 0)) { ++ ++ if (entry->traffic_pending_bmp & NBITVAL(prec)) { ++ rc = TRUE; ++ entry->traffic_pending_bmp = ++ entry->traffic_pending_bmp & ~ NBITVAL(prec); ++ } ++ } ++ else { ++ if (!(entry->traffic_pending_bmp & NBITVAL(prec))) { ++ rc = TRUE; ++ entry->traffic_pending_bmp = ++ entry->traffic_pending_bmp | NBITVAL(prec); ++ } ++ } ++ } ++ if (rc) { ++ /* request a TIM update to firmware at the next piggyback opportunity */ ++ if (entry->traffic_lastreported_bmp != entry->traffic_pending_bmp) { ++ entry->send_tim_signal = 1; ++ _dhd_wlfc_send_signalonly_packet(ctx, entry, entry->traffic_pending_bmp); ++ entry->traffic_lastreported_bmp = entry->traffic_pending_bmp; ++ entry->send_tim_signal = 0; ++ } ++ else { ++ rc = FALSE; ++ } ++ } ++ return rc; ++} ++ ++static int ++_dhd_wlfc_enque_suppressed(athost_wl_status_info_t* ctx, int prec, void* p) ++{ ++ wlfc_mac_descriptor_t* entry; ++ ++ entry = _dhd_wlfc_find_table_entry(ctx, p); ++ if (entry == NULL) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ return BCME_NOTFOUND; ++ } ++ /* ++ - suppressed packets go to sub_queue[2*prec + 1] AND ++ - delayed packets go to sub_queue[2*prec + 0] to ensure ++ order of delivery. ++ */ ++ if (WLFC_PKTQ_PENQ(&entry->psq, ((prec << 1) + 1), p) == NULL) { ++ ctx->stats.delayq_full_error++; ++ /* AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); */ ++ AP6210_DEBUG("s"); ++ return BCME_ERROR; ++ } ++ /* A packet has been pushed, update traffic availability bitmap, if applicable */ ++ _dhd_wlfc_traffic_pending_check(ctx, entry, prec); ++ _dhd_wlfc_flow_control_check(ctx, &entry->psq, DHD_PKTTAG_IF(PKTTAG(p))); ++ return BCME_OK; ++} ++ ++static int ++_dhd_wlfc_pretx_pktprocess(athost_wl_status_info_t* ctx, ++ wlfc_mac_descriptor_t* entry, void* p, int header_needed, uint32* slot) ++{ ++ int rc = BCME_OK; ++ int hslot = WLFC_HANGER_MAXITEMS; ++ bool send_tim_update = FALSE; ++ uint32 htod = 0; ++ uint8 free_ctr; ++ ++ *slot = hslot; ++ ++ if (entry == NULL) { ++ entry = _dhd_wlfc_find_table_entry(ctx, p); ++ } ++ ++ if (entry == NULL) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ return BCME_ERROR; ++ } ++ if (entry->send_tim_signal) { ++ send_tim_update = TRUE; ++ entry->send_tim_signal = 0; ++ entry->traffic_lastreported_bmp = entry->traffic_pending_bmp; ++ } ++ if (header_needed) { ++ hslot = dhd_wlfc_hanger_get_free_slot(ctx->hanger); ++ free_ctr = WLFC_SEQCOUNT(entry, DHD_PKTTAG_FIFO(PKTTAG(p))); ++ DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), htod); ++ WLFC_PKTFLAG_SET_GENERATION(htod, entry->generation); ++ entry->transit_count++; ++ } ++ else { ++ hslot = WLFC_PKTID_HSLOT_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); ++ free_ctr = WLFC_PKTID_FREERUNCTR_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); ++ } ++ WLFC_PKTID_HSLOT_SET(htod, hslot); ++ WLFC_PKTID_FREERUNCTR_SET(htod, free_ctr); ++ DHD_PKTTAG_SETPKTDIR(PKTTAG(p), 1); ++ WL_TXSTATUS_SET_FLAGS(htod, WLFC_PKTFLAG_PKTFROMHOST); ++ WL_TXSTATUS_SET_FIFO(htod, DHD_PKTTAG_FIFO(PKTTAG(p))); ++ ++ if (!DHD_PKTTAG_CREDITCHECK(PKTTAG(p))) { ++ /* ++ Indicate that this packet is being sent in response to an ++ explicit request from the firmware side. ++ */ ++ WLFC_PKTFLAG_SET_PKTREQUESTED(htod); ++ } ++ else { ++ WLFC_PKTFLAG_CLR_PKTREQUESTED(htod); ++ } ++ if (header_needed) { ++ rc = _dhd_wlfc_pushheader(ctx, p, send_tim_update, ++ entry->traffic_lastreported_bmp, entry->mac_handle, htod); ++ if (rc == BCME_OK) { ++ DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), htod); ++ /* ++ a new header was created for this packet. ++ push to hanger slot and scrub q. Since bus ++ send succeeded, increment seq number as well. ++ */ ++ rc = dhd_wlfc_hanger_pushpkt(ctx->hanger, p, hslot); ++ if (rc == BCME_OK) { ++ /* increment free running sequence count */ ++ WLFC_INCR_SEQCOUNT(entry, DHD_PKTTAG_FIFO(PKTTAG(p))); ++#ifdef PROP_TXSTATUS_DEBUG ++ ((wlfc_hanger_t*)(ctx->hanger))->items[hslot].push_time = ++ OSL_SYSUPTIME(); ++#endif ++ } ++ else { ++ AP6210_DEBUG("%s() hanger_pushpkt() failed, rc: %d\n", ++ __FUNCTION__, rc); ++ } ++ } ++ } ++ else { ++ int gen; ++ ++ /* remove old header */ ++ rc = _dhd_wlfc_pullheader(ctx, p); ++ if (rc == BCME_OK) { ++ hslot = WLFC_PKTID_HSLOT_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); ++ dhd_wlfc_hanger_get_genbit(ctx->hanger, p, hslot, &gen); ++ ++ WLFC_PKTFLAG_SET_GENERATION(htod, gen); ++ free_ctr = WLFC_PKTID_FREERUNCTR_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); ++ /* push new header */ ++ _dhd_wlfc_pushheader(ctx, p, send_tim_update, ++ entry->traffic_lastreported_bmp, entry->mac_handle, htod); ++ } ++ } ++ *slot = hslot; ++ return rc; ++} ++ ++static int ++_dhd_wlfc_is_destination_closed(athost_wl_status_info_t* ctx, ++ wlfc_mac_descriptor_t* entry, int prec) ++{ ++ if (ctx->destination_entries.interfaces[entry->interface_id].iftype == ++ WLC_E_IF_ROLE_P2P_GO) { ++ /* - destination interface is of type p2p GO. ++ For a p2pGO interface, if the destination is OPEN but the interface is ++ CLOSEd, do not send traffic. But if the dstn is CLOSEd while there is ++ destination-specific-credit left send packets. This is because the ++ firmware storing the destination-specific-requested packet in queue. ++ */ ++ if ((entry->state == WLFC_STATE_CLOSE) && (entry->requested_credit == 0) && ++ (entry->requested_packet == 0)) ++ return 1; ++ } ++ /* AP, p2p_go -> unicast desc entry, STA/p2p_cl -> interface desc. entry */ ++ if (((entry->state == WLFC_STATE_CLOSE) && (entry->requested_credit == 0) && ++ (entry->requested_packet == 0)) || ++ (!(entry->ac_bitmap & (1 << prec)))) ++ return 1; ++ ++ return 0; ++} ++ ++static void* ++_dhd_wlfc_deque_delayedq(athost_wl_status_info_t* ctx, ++ int prec, uint8* ac_credit_spent, uint8* needs_hdr, wlfc_mac_descriptor_t** entry_out) ++{ ++ wlfc_mac_descriptor_t* entry; ++ wlfc_mac_descriptor_t* table; ++ uint8 token_pos; ++ int total_entries; ++ void* p = NULL; ++ int pout; ++ int i; ++ ++ *entry_out = NULL; ++ token_pos = ctx->token_pos[prec]; ++ /* most cases a packet will count against FIFO credit */ ++ *ac_credit_spent = 1; ++ *needs_hdr = 1; ++ ++ /* search all entries, include nodes as well as interfaces */ ++ table = (wlfc_mac_descriptor_t*)&ctx->destination_entries; ++ total_entries = sizeof(ctx->destination_entries)/sizeof(wlfc_mac_descriptor_t); ++ ++ for (i = 0; i < total_entries; i++) { ++ entry = &table[(token_pos + i) % total_entries]; ++ if (entry->occupied) { ++ if (!_dhd_wlfc_is_destination_closed(ctx, entry, prec)) { ++ p = pktq_mdeq(&entry->psq, ++ /* higher precedence will be picked up first, ++ * i.e. suppressed packets before delayed ones ++ */ ++ NBITVAL((prec << 1) + 1), &pout); ++ *needs_hdr = 0; ++ ++ if (p == NULL) { ++ if (entry->suppressed == TRUE) { ++ if ((entry->suppr_transit_count <= ++ entry->suppress_count)) { ++ entry->suppressed = FALSE; ++ } else { ++ return NULL; ++ } ++ } ++ /* De-Q from delay Q */ ++ p = pktq_mdeq(&entry->psq, ++ NBITVAL((prec << 1)), ++ &pout); ++ *needs_hdr = 1; ++ } ++ ++ if (p != NULL) { ++ /* did the packet come from suppress sub-queue? */ ++ if (entry->requested_credit > 0) { ++ entry->requested_credit--; ++#ifdef PROP_TXSTATUS_DEBUG ++ entry->dstncredit_sent_packets++; ++#endif ++ /* ++ if the packet was pulled out while destination is in ++ closed state but had a non-zero packets requested, ++ then this should not count against the FIFO credit. ++ That is due to the fact that the firmware will ++ most likely hold onto this packet until a suitable ++ time later to push it to the appropriate AC FIFO. ++ */ ++ if (entry->state == WLFC_STATE_CLOSE) ++ *ac_credit_spent = 0; ++ } ++ else if (entry->requested_packet > 0) { ++ entry->requested_packet--; ++ DHD_PKTTAG_SETONETIMEPKTRQST(PKTTAG(p)); ++ if (entry->state == WLFC_STATE_CLOSE) ++ *ac_credit_spent = 0; ++ } ++ /* move token to ensure fair round-robin */ ++ ctx->token_pos[prec] = ++ (token_pos + i + 1) % total_entries; ++ *entry_out = entry; ++ _dhd_wlfc_flow_control_check(ctx, &entry->psq, ++ DHD_PKTTAG_IF(PKTTAG(p))); ++ /* ++ A packet has been picked up, update traffic ++ availability bitmap, if applicable ++ */ ++ _dhd_wlfc_traffic_pending_check(ctx, entry, prec); ++ return p; ++ } ++ } ++ } ++ } ++ return NULL; ++} ++ ++static void* ++_dhd_wlfc_deque_sendq(athost_wl_status_info_t* ctx, int prec) ++{ ++ wlfc_mac_descriptor_t* entry; ++ void* p; ++ ++ ++ p = pktq_pdeq(&ctx->SENDQ, prec); ++ if (p != NULL) { ++ if (ETHER_ISMULTI(DHD_PKTTAG_DSTN(PKTTAG(p)))) ++ /* bc/mc packets do not have a delay queue */ ++ return p; ++ ++ entry = _dhd_wlfc_find_table_entry(ctx, p); ++ ++ if (entry == NULL) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ return p; ++ } ++ ++ while ((p != NULL)) { ++ /* ++ - suppressed packets go to sub_queue[2*prec + 1] AND ++ - delayed packets go to sub_queue[2*prec + 0] to ensure ++ order of delivery. ++ */ ++ if (WLFC_PKTQ_PENQ(&entry->psq, (prec << 1), p) == NULL) { ++ AP6210_DEBUG("D"); ++ /* dhd_txcomplete(ctx->dhdp, p, FALSE); */ ++ PKTFREE(ctx->osh, p, TRUE); ++ ctx->stats.delayq_full_error++; ++ } ++ /* ++ A packet has been pushed, update traffic availability bitmap, ++ if applicable ++ */ ++ _dhd_wlfc_traffic_pending_check(ctx, entry, prec); ++ ++ p = pktq_pdeq(&ctx->SENDQ, prec); ++ if (p == NULL) ++ break; ++ ++ entry = _dhd_wlfc_find_table_entry(ctx, p); ++ ++ if ((entry == NULL) || (ETHER_ISMULTI(DHD_PKTTAG_DSTN(PKTTAG(p))))) { ++ return p; ++ } ++ } ++ } ++ return p; ++} ++ ++static int ++_dhd_wlfc_mac_entry_update(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry, ++ ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea) ++{ ++ int rc = BCME_OK; ++ ++ if (action == eWLFC_MAC_ENTRY_ACTION_ADD) { ++ entry->occupied = 1; ++ entry->state = WLFC_STATE_OPEN; ++ entry->requested_credit = 0; ++ entry->interface_id = ifid; ++ entry->iftype = iftype; ++ entry->ac_bitmap = 0xff; /* update this when handling APSD */ ++ /* for an interface entry we may not care about the MAC address */ ++ if (ea != NULL) ++ memcpy(&entry->ea[0], ea, ETHER_ADDR_LEN); ++ pktq_init(&entry->psq, WLFC_PSQ_PREC_COUNT, WLFC_PSQ_LEN); ++ } ++ else if (action == eWLFC_MAC_ENTRY_ACTION_UPDATE) { ++ entry->occupied = 1; ++ entry->state = WLFC_STATE_OPEN; ++ entry->requested_credit = 0; ++ entry->interface_id = ifid; ++ entry->iftype = iftype; ++ entry->ac_bitmap = 0xff; /* update this when handling APSD */ ++ /* for an interface entry we may not care about the MAC address */ ++ if (ea != NULL) ++ memcpy(&entry->ea[0], ea, ETHER_ADDR_LEN); ++ } ++ else if (action == eWLFC_MAC_ENTRY_ACTION_DEL) { ++ entry->occupied = 0; ++ entry->state = WLFC_STATE_CLOSE; ++ entry->requested_credit = 0; ++ /* enable after packets are queued-deqeued properly. ++ pktq_flush(dhd->osh, &entry->psq, FALSE, NULL, 0); ++ */ ++ } ++ return rc; ++} ++ ++int ++_dhd_wlfc_borrow_credit(athost_wl_status_info_t* ctx, uint8 available_credit_map, int borrower_ac) ++{ ++ int lender_ac; ++ int rc = BCME_ERROR; ++ ++ if (ctx == NULL || available_credit_map == 0) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ return BCME_BADARG; ++ } ++ ++ /* Borrow from lowest priority available AC (including BC/MC credits) */ ++ for (lender_ac = 0; lender_ac <= AC_COUNT; lender_ac++) { ++ if ((available_credit_map && (1 << lender_ac)) && ++ (ctx->FIFO_credit[lender_ac] > 0)) { ++ ctx->credits_borrowed[borrower_ac][lender_ac]++; ++ ctx->FIFO_credit[lender_ac]--; ++ rc = BCME_OK; ++ break; ++ } ++ } ++ ++ return rc; ++} ++ ++int ++dhd_wlfc_interface_entry_update(void* state, ++ ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea) ++{ ++ athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; ++ wlfc_mac_descriptor_t* entry; ++ ++ if (ifid >= WLFC_MAX_IFNUM) ++ return BCME_BADARG; ++ ++ entry = &ctx->destination_entries.interfaces[ifid]; ++ return _dhd_wlfc_mac_entry_update(ctx, entry, action, ifid, iftype, ea); ++} ++ ++int ++dhd_wlfc_FIFOcreditmap_update(void* state, uint8* credits) ++{ ++ athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; ++ ++ /* update the AC FIFO credit map */ ++ ctx->FIFO_credit[0] = credits[0]; ++ ctx->FIFO_credit[1] = credits[1]; ++ ctx->FIFO_credit[2] = credits[2]; ++ ctx->FIFO_credit[3] = credits[3]; ++ /* credit for bc/mc packets */ ++ ctx->FIFO_credit[4] = credits[4]; ++ /* credit for ATIM FIFO is not used yet. */ ++ ctx->FIFO_credit[5] = 0; ++ return BCME_OK; ++} ++ ++int ++dhd_wlfc_enque_sendq(void* state, int prec, void* p) ++{ ++ athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; ++ ++ if ((state == NULL) || ++ /* prec = AC_COUNT is used for bc/mc queue */ ++ (prec > AC_COUNT) || ++ (p == NULL)) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ return BCME_BADARG; ++ } ++ if (FALSE == dhd_prec_enq(ctx->dhdp, &ctx->SENDQ, p, prec)) { ++ ctx->stats.sendq_full_error++; ++ /* ++ AP6210_DEBUG("Error: %s():%d, qlen:%d\n", ++ __FUNCTION__, __LINE__, ctx->SENDQ.len); ++ */ ++ WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, prec); ++ AP6210_DEBUG("Q"); ++ PKTFREE(ctx->osh, p, TRUE); ++ return BCME_ERROR; ++ } ++ ctx->stats.pktin++; ++ /* _dhd_wlfc_flow_control_check(ctx, &ctx->SENDQ, DHD_PKTTAG_IF(PKTTAG(p))); */ ++ return BCME_OK; ++} ++ ++int ++_dhd_wlfc_handle_packet_commit(athost_wl_status_info_t* ctx, int ac, ++ dhd_wlfc_commit_info_t *commit_info, f_commitpkt_t fcommit, void* commit_ctx) ++{ ++ uint32 hslot; ++ int rc; ++ ++ /* ++ if ac_fifo_credit_spent = 0 ++ ++ This packet will not count against the FIFO credit. ++ To ensure the txstatus corresponding to this packet ++ does not provide an implied credit (default behavior) ++ mark the packet accordingly. ++ ++ if ac_fifo_credit_spent = 1 ++ ++ This is a normal packet and it counts against the FIFO ++ credit count. ++ */ ++ DHD_PKTTAG_SETCREDITCHECK(PKTTAG(commit_info->p), commit_info->ac_fifo_credit_spent); ++ rc = _dhd_wlfc_pretx_pktprocess(ctx, commit_info->mac_entry, commit_info->p, ++ commit_info->needs_hdr, &hslot); ++ ++ if (rc == BCME_OK) ++ rc = fcommit(commit_ctx, commit_info->p, TRUE); ++ else ++ ctx->stats.generic_error++; ++ ++ if (rc == BCME_OK) { ++ ctx->stats.pkt2bus++; ++ if (commit_info->ac_fifo_credit_spent) { ++ ctx->stats.sendq_pkts[ac]++; ++ WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac); ++ } ++ } else if (rc == BCME_NORESOURCE) ++ rc = BCME_ERROR; ++ else { ++ /* ++ bus commit has failed, rollback. ++ - remove wl-header for a delayed packet ++ - save wl-header header for suppressed packets ++ */ ++ rc = _dhd_wlfc_rollback_packet_toq(ctx, commit_info->p, ++ (commit_info->pkt_type), hslot); ++ if (rc != BCME_OK) ++ ctx->stats.rollback_failed++; ++ ++ rc = BCME_ERROR; ++ } ++ ++ return rc; ++} ++ ++int ++dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx) ++{ ++ int ac; ++ int credit; ++ int rc; ++ dhd_wlfc_commit_info_t commit_info; ++ athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; ++ int credit_count = 0; ++ int bus_retry_count = 0; ++ uint8 ac_available = 0; /* Bitmask for 4 ACs + BC/MC */ ++ ++ if ((state == NULL) || ++ (fcommit == NULL)) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ return BCME_BADARG; ++ } ++ ++ memset(&commit_info, 0, sizeof(commit_info)); ++ ++ /* ++ Commit packets for regular AC traffic. Higher priority first. ++ First, use up FIFO credits available to each AC. Based on distribution ++ and credits left, borrow from other ACs as applicable ++ ++ -NOTE: ++ If the bus between the host and firmware is overwhelmed by the ++ traffic from host, it is possible that higher priority traffic ++ starves the lower priority queue. If that occurs often, we may ++ have to employ weighted round-robin or ucode scheme to avoid ++ low priority packet starvation. ++ */ ++ ++ for (ac = AC_COUNT; ac >= 0; ac--) { ++ ++ int initial_credit_count = ctx->FIFO_credit[ac]; ++ ++ /* packets from SENDQ are fresh and they'd need header and have no MAC entry */ ++ commit_info.needs_hdr = 1; ++ commit_info.mac_entry = NULL; ++ commit_info.pkt_type = eWLFC_PKTTYPE_NEW; ++ ++ do { ++ commit_info.p = _dhd_wlfc_deque_sendq(ctx, ac); ++ if (commit_info.p == NULL) ++ break; ++ else if (ETHER_ISMULTI(DHD_PKTTAG_DSTN(PKTTAG(commit_info.p)))) { ++ ASSERT(ac == AC_COUNT); ++ ++ if (ctx->FIFO_credit[ac]) { ++ rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info, ++ fcommit, commit_ctx); ++ ++ /* Bus commits may fail (e.g. flow control); abort after retries */ ++ if (rc == BCME_OK) { ++ if (commit_info.ac_fifo_credit_spent) { ++ (void) _dhd_wlfc_borrow_credit(ctx, ++ ac_available, ac); ++ credit_count--; ++ } ++ } else { ++ bus_retry_count++; ++ if (bus_retry_count >= BUS_RETRIES) { ++ AP6210_ERR(" %s: bus error\n", ++ __FUNCTION__); ++ return rc; ++ } ++ } ++ } ++ } ++ ++ } while (commit_info.p); ++ ++ for (credit = 0; credit < ctx->FIFO_credit[ac];) { ++ commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac, ++ &(commit_info.ac_fifo_credit_spent), ++ &(commit_info.needs_hdr), ++ &(commit_info.mac_entry)); ++ ++ if (commit_info.p == NULL) ++ break; ++ ++ commit_info.pkt_type = (commit_info.needs_hdr) ? eWLFC_PKTTYPE_DELAYED : ++ eWLFC_PKTTYPE_SUPPRESSED; ++ ++ rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info, ++ fcommit, commit_ctx); ++ ++ /* Bus commits may fail (e.g. flow control); abort after retries */ ++ if (rc == BCME_OK) { ++ if (commit_info.ac_fifo_credit_spent) { ++ credit++; ++ } ++ } ++ else { ++ bus_retry_count++; ++ if (bus_retry_count >= BUS_RETRIES) { ++ AP6210_ERR("dhd_wlfc_commit_packets(): bus error\n"); ++ ctx->FIFO_credit[ac] -= credit; ++ return rc; ++ } ++ } ++ } ++ ++ ctx->FIFO_credit[ac] -= credit; ++ ++ ++ /* If no credits were used, the queue is idle and can be re-used ++ Note that resv credits cannot be borrowed ++ */ ++ if (initial_credit_count == ctx->FIFO_credit[ac]) { ++ ac_available |= (1 << ac); ++ credit_count += ctx->FIFO_credit[ac]; ++ } ++ } ++ ++ /* We borrow only for AC_BE and only if no other traffic seen for DEFER_PERIOD ++ ++ Note that (ac_available & WLFC_AC_BE_TRAFFIC_ONLY) is done to: ++ a) ignore BC/MC for deferring borrow ++ b) ignore AC_BE being available along with other ACs ++ (this should happen only for pure BC/MC traffic) ++ ++ i.e. AC_VI, AC_VO, AC_BK all MUST be available (i.e. no traffic) and ++ we do not care if AC_BE and BC/MC are available or not ++ */ ++ if ((ac_available & WLFC_AC_BE_TRAFFIC_ONLY) == WLFC_AC_BE_TRAFFIC_ONLY) { ++ ++ if (ctx->allow_credit_borrow) { ++ ac = 1; /* Set ac to AC_BE and borrow credits */ ++ } ++ else { ++ int delta; ++ int curr_t = OSL_SYSUPTIME(); ++ ++ if (curr_t > ctx->borrow_defer_timestamp) ++ delta = curr_t - ctx->borrow_defer_timestamp; ++ else ++ delta = 0xffffffff + curr_t - ctx->borrow_defer_timestamp; ++ ++ if (delta >= WLFC_BORROW_DEFER_PERIOD_MS) { ++ /* Reset borrow but defer to next iteration (defensive borrowing) */ ++ ctx->allow_credit_borrow = TRUE; ++ ctx->borrow_defer_timestamp = 0; ++ } ++ return BCME_OK; ++ } ++ } ++ else { ++ /* If we have multiple AC traffic, turn off borrowing, mark time and bail out */ ++ ctx->allow_credit_borrow = FALSE; ++ ctx->borrow_defer_timestamp = OSL_SYSUPTIME(); ++ return BCME_OK; ++ } ++ ++ /* At this point, borrow all credits only for "ac" (which should be set above to AC_BE) ++ Generically use "ac" only in case we extend to all ACs in future ++ */ ++ for (; (credit_count > 0);) { ++ ++ commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac, ++ &(commit_info.ac_fifo_credit_spent), ++ &(commit_info.needs_hdr), ++ &(commit_info.mac_entry)); ++ if (commit_info.p == NULL) ++ break; ++ ++ commit_info.pkt_type = (commit_info.needs_hdr) ? eWLFC_PKTTYPE_DELAYED : ++ eWLFC_PKTTYPE_SUPPRESSED; ++ ++ rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info, ++ fcommit, commit_ctx); ++ ++ /* Bus commits may fail (e.g. flow control); abort after retries */ ++ if (rc == BCME_OK) { ++ if (commit_info.ac_fifo_credit_spent) { ++ (void) _dhd_wlfc_borrow_credit(ctx, ac_available, ac); ++ credit_count--; ++ } ++ } ++ else { ++ bus_retry_count++; ++ if (bus_retry_count >= BUS_RETRIES) { ++ AP6210_ERR("dhd_wlfc_commit_packets(): bus error\n"); ++ return rc; ++ } ++ } ++ } ++ ++ return BCME_OK; ++} ++ ++static uint8 ++dhd_wlfc_find_mac_desc_id_from_mac(dhd_pub_t *dhdp, uint8* ea) ++{ ++ wlfc_mac_descriptor_t* table = ++ ((athost_wl_status_info_t*)dhdp->wlfc_state)->destination_entries.nodes; ++ uint8 table_index; ++ ++ if (ea != NULL) { ++ for (table_index = 0; table_index < WLFC_MAC_DESC_TABLE_SIZE; table_index++) { ++ if ((memcmp(ea, &table[table_index].ea[0], ETHER_ADDR_LEN) == 0) && ++ table[table_index].occupied) ++ return table_index; ++ } ++ } ++ return WLFC_MAC_DESC_ID_INVALID; ++} ++ ++void ++dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success, bool wake_locked) ++{ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ void* p; ++ int fifo_id; ++ ++ if (!wake_locked) ++ dhd_os_wlfc_block(dhd); ++ ++ if (DHD_PKTTAG_SIGNALONLY(PKTTAG(txp))) { ++#ifdef PROP_TXSTATUS_DEBUG ++ wlfc->stats.signal_only_pkts_freed++; ++#endif ++ if (success) ++ /* is this a signal-only packet? */ ++ PKTFREE(wlfc->osh, txp, TRUE); ++ if (!wake_locked) ++ dhd_os_wlfc_unblock(dhd); ++ return; ++ } ++ if (!success) { ++ AP6210_DEBUG("At: %s():%d, bus_complete() failure for %p, htod_tag:0x%08x\n", ++ __FUNCTION__, __LINE__, txp, DHD_PKTTAG_H2DTAG(PKTTAG(txp))); ++ dhd_wlfc_hanger_poppkt(wlfc->hanger, WLFC_PKTID_HSLOT_GET(DHD_PKTTAG_H2DTAG ++ (PKTTAG(txp))), &p, 1); ++ ++ /* indicate failure and free the packet */ ++ dhd_txcomplete(dhd, txp, FALSE); ++ ++ /* return the credit, if necessary */ ++ if (DHD_PKTTAG_CREDITCHECK(PKTTAG(txp))) { ++ int lender, credit_returned = 0; /* Note that borrower is fifo_id */ ++ ++ fifo_id = DHD_PKTTAG_FIFO(PKTTAG(txp)); ++ ++ /* Return credits to highest priority lender first */ ++ for (lender = AC_COUNT; lender >= 0; lender--) { ++ if (wlfc->credits_borrowed[fifo_id][lender] > 0) { ++ wlfc->FIFO_credit[lender]++; ++ wlfc->credits_borrowed[fifo_id][lender]--; ++ credit_returned = 1; ++ break; ++ } ++ } ++ ++ if (!credit_returned) { ++ wlfc->FIFO_credit[fifo_id]++; ++ } ++ } ++ ++ PKTFREE(wlfc->osh, txp, TRUE); ++ } ++ if (!wake_locked) ++ dhd_os_wlfc_unblock(dhd); ++ return; ++} ++ ++static int ++dhd_wlfc_compressed_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info, uint8 len) ++{ ++ uint8 status_flag; ++ uint32 status; ++ int ret; ++ int remove_from_hanger = 1; ++ void* pktbuf; ++ uint8 fifo_id; ++ uint8 count = 0; ++ uint32 status_g; ++ uint32 hslot, hcnt; ++ wlfc_mac_descriptor_t* entry = NULL; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ ++ memcpy(&status, pkt_info, sizeof(uint32)); ++ status_flag = WL_TXSTATUS_GET_FLAGS(status); ++ status_g = status & 0xff000000; ++ hslot = (status & 0x00ffff00) >> 8; ++ hcnt = status & 0xff; ++ len = pkt_info[4]; ++ ++ wlfc->stats.txstatus_in++; ++ ++ if (status_flag == WLFC_CTL_PKTFLAG_DISCARD) { ++ wlfc->stats.pkt_freed++; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) { ++ wlfc->stats.d11_suppress++; ++ remove_from_hanger = 0; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS) { ++ wlfc->stats.wl_suppress++; ++ remove_from_hanger = 0; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_TOSSED_BYWLC) { ++ wlfc->stats.wlc_tossed_pkts++; ++ } ++ while (count < len) { ++ status = (status_g << 24) | (hslot << 8) | (hcnt); ++ count++; ++ hslot++; ++ hcnt++; ++ ++ ret = dhd_wlfc_hanger_poppkt(wlfc->hanger, ++ WLFC_PKTID_HSLOT_GET(status), &pktbuf, remove_from_hanger); ++ if (ret != BCME_OK) { ++ /* do something */ ++ continue; ++ } ++ ++ entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); ++ ++ if (!remove_from_hanger) { ++ /* this packet was suppressed */ ++ if (!entry->suppressed || entry->generation != WLFC_PKTID_GEN(status)) { ++ entry->suppressed = TRUE; ++ entry->suppress_count = pktq_mlen(&entry->psq, ++ NBITVAL((WL_TXSTATUS_GET_FIFO(status) << 1) + 1)); ++ entry->suppr_transit_count = entry->transit_count; ++ } ++ entry->generation = WLFC_PKTID_GEN(status); ++ } ++ ++#ifdef PROP_TXSTATUS_DEBUG ++ { ++ uint32 new_t = OSL_SYSUPTIME(); ++ uint32 old_t; ++ uint32 delta; ++ old_t = ((wlfc_hanger_t*)(wlfc->hanger))->items[ ++ WLFC_PKTID_HSLOT_GET(status)].push_time; ++ ++ ++ wlfc->stats.latency_sample_count++; ++ if (new_t > old_t) ++ delta = new_t - old_t; ++ else ++ delta = 0xffffffff + new_t - old_t; ++ wlfc->stats.total_status_latency += delta; ++ wlfc->stats.latency_most_recent = delta; ++ ++ wlfc->stats.deltas[wlfc->stats.idx_delta++] = delta; ++ if (wlfc->stats.idx_delta == sizeof(wlfc->stats.deltas)/sizeof(uint32)) ++ wlfc->stats.idx_delta = 0; ++ } ++#endif /* PROP_TXSTATUS_DEBUG */ ++ ++ fifo_id = DHD_PKTTAG_FIFO(PKTTAG(pktbuf)); ++ ++ /* pick up the implicit credit from this packet */ ++ if (DHD_PKTTAG_CREDITCHECK(PKTTAG(pktbuf))) { ++ if (wlfc->proptxstatus_mode == WLFC_FCMODE_IMPLIED_CREDIT) { ++ ++ int lender, credit_returned = 0; /* Note that borrower is fifo_id */ ++ ++ /* Return credits to highest priority lender first */ ++ for (lender = AC_COUNT; lender >= 0; lender--) { ++ if (wlfc->credits_borrowed[fifo_id][lender] > 0) { ++ wlfc->FIFO_credit[lender]++; ++ wlfc->credits_borrowed[fifo_id][lender]--; ++ credit_returned = 1; ++ break; ++ } ++ } ++ ++ if (!credit_returned) { ++ wlfc->FIFO_credit[fifo_id]++; ++ } ++ } ++ } ++ else { ++ /* ++ if this packet did not count against FIFO credit, it must have ++ taken a requested_credit from the destination entry (for pspoll etc.) ++ */ ++ if (!entry) { ++ ++ entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); ++ } ++ if (!DHD_PKTTAG_ONETIMEPKTRQST(PKTTAG(pktbuf))) ++ entry->requested_credit++; ++#ifdef PROP_TXSTATUS_DEBUG ++ entry->dstncredit_acks++; ++#endif ++ } ++ if ((status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) || ++ (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS)) { ++ ++ ret = _dhd_wlfc_enque_suppressed(wlfc, fifo_id, pktbuf); ++ if (ret != BCME_OK) { ++ /* delay q is full, drop this packet */ ++ dhd_wlfc_hanger_poppkt(wlfc->hanger, WLFC_PKTID_HSLOT_GET(status), ++ &pktbuf, 1); ++ ++ /* indicate failure and free the packet */ ++ dhd_txcomplete(dhd, pktbuf, FALSE); ++ entry->transit_count--; ++ /* packet is transmitted Successfully by dongle ++ * after first suppress. ++ */ ++ if (entry->suppressed) { ++ entry->suppr_transit_count--; ++ } ++ PKTFREE(wlfc->osh, pktbuf, TRUE); ++ } else { ++ /* Mark suppressed to avoid a double free during wlfc cleanup */ ++ ++ dhd_wlfc_hanger_mark_suppressed(wlfc->hanger, ++ WLFC_PKTID_HSLOT_GET(status), WLFC_PKTID_GEN(status)); ++ entry->suppress_count++; ++ } ++ } ++ else { ++ dhd_txcomplete(dhd, pktbuf, TRUE); ++ entry->transit_count--; ++ ++ /* This packet is transmitted Successfully by dongle ++ * even after first suppress. ++ */ ++ if (entry->suppressed) { ++ entry->suppr_transit_count--; ++ } ++ /* free the packet */ ++ PKTFREE(wlfc->osh, pktbuf, TRUE); ++ } ++ } ++ return BCME_OK; ++} ++ ++/* Handle discard or suppress indication */ ++static int ++dhd_wlfc_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info) ++{ ++ uint8 status_flag; ++ uint32 status; ++ int ret; ++ int remove_from_hanger = 1; ++ void* pktbuf; ++ uint8 fifo_id; ++ wlfc_mac_descriptor_t* entry = NULL; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ ++ memcpy(&status, pkt_info, sizeof(uint32)); ++ status_flag = WL_TXSTATUS_GET_FLAGS(status); ++ wlfc->stats.txstatus_in++; ++ ++ if (status_flag == WLFC_CTL_PKTFLAG_DISCARD) { ++ wlfc->stats.pkt_freed++; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) { ++ wlfc->stats.d11_suppress++; ++ remove_from_hanger = 0; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS) { ++ wlfc->stats.wl_suppress++; ++ remove_from_hanger = 0; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_TOSSED_BYWLC) { ++ wlfc->stats.wlc_tossed_pkts++; ++ } ++ ++ ret = dhd_wlfc_hanger_poppkt(wlfc->hanger, ++ WLFC_PKTID_HSLOT_GET(status), &pktbuf, remove_from_hanger); ++ if (ret != BCME_OK) { ++ /* do something */ ++ return ret; ++ } ++ ++ entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); ++ ++ if (!remove_from_hanger) { ++ /* this packet was suppressed */ ++ if (!entry->suppressed || entry->generation != WLFC_PKTID_GEN(status)) { ++ entry->suppressed = TRUE; ++ entry->suppress_count = pktq_mlen(&entry->psq, ++ NBITVAL((WL_TXSTATUS_GET_FIFO(status) << 1) + 1)); ++ entry->suppr_transit_count = entry->transit_count; ++ } ++ entry->generation = WLFC_PKTID_GEN(status); ++ } ++ ++#ifdef PROP_TXSTATUS_DEBUG ++ { ++ uint32 new_t = OSL_SYSUPTIME(); ++ uint32 old_t; ++ uint32 delta; ++ old_t = ((wlfc_hanger_t*)(wlfc->hanger))->items[ ++ WLFC_PKTID_HSLOT_GET(status)].push_time; ++ ++ ++ wlfc->stats.latency_sample_count++; ++ if (new_t > old_t) ++ delta = new_t - old_t; ++ else ++ delta = 0xffffffff + new_t - old_t; ++ wlfc->stats.total_status_latency += delta; ++ wlfc->stats.latency_most_recent = delta; ++ ++ wlfc->stats.deltas[wlfc->stats.idx_delta++] = delta; ++ if (wlfc->stats.idx_delta == sizeof(wlfc->stats.deltas)/sizeof(uint32)) ++ wlfc->stats.idx_delta = 0; ++ } ++#endif /* PROP_TXSTATUS_DEBUG */ ++ ++ fifo_id = DHD_PKTTAG_FIFO(PKTTAG(pktbuf)); ++ ++ /* pick up the implicit credit from this packet */ ++ if (DHD_PKTTAG_CREDITCHECK(PKTTAG(pktbuf))) { ++ if (wlfc->proptxstatus_mode == WLFC_FCMODE_IMPLIED_CREDIT) { ++ ++ int lender, credit_returned = 0; /* Note that borrower is fifo_id */ ++ ++ /* Return credits to highest priority lender first */ ++ for (lender = AC_COUNT; lender >= 0; lender--) { ++ if (wlfc->credits_borrowed[fifo_id][lender] > 0) { ++ wlfc->FIFO_credit[lender]++; ++ wlfc->credits_borrowed[fifo_id][lender]--; ++ credit_returned = 1; ++ break; ++ } ++ } ++ ++ if (!credit_returned) { ++ wlfc->FIFO_credit[fifo_id]++; ++ } ++ } ++ } ++ else { ++ /* ++ if this packet did not count against FIFO credit, it must have ++ taken a requested_credit from the destination entry (for pspoll etc.) ++ */ ++ if (!entry) { ++ ++ entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); ++ } ++ if (!DHD_PKTTAG_ONETIMEPKTRQST(PKTTAG(pktbuf))) ++ entry->requested_credit++; ++#ifdef PROP_TXSTATUS_DEBUG ++ entry->dstncredit_acks++; ++#endif ++ } ++ if ((status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) || ++ (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS)) { ++ ++ ret = _dhd_wlfc_enque_suppressed(wlfc, fifo_id, pktbuf); ++ if (ret != BCME_OK) { ++ /* delay q is full, drop this packet */ ++ dhd_wlfc_hanger_poppkt(wlfc->hanger, WLFC_PKTID_HSLOT_GET(status), ++ &pktbuf, 1); ++ ++ /* indicate failure and free the packet */ ++ dhd_txcomplete(dhd, pktbuf, FALSE); ++ entry->transit_count--; ++ /* This packet is transmitted Successfully by ++ * dongle even after first suppress. ++ */ ++ if (entry->suppressed) { ++ entry->suppr_transit_count--; ++ } ++ PKTFREE(wlfc->osh, pktbuf, TRUE); ++ } else { ++ /* Mark suppressed to avoid a double free during wlfc cleanup */ ++ dhd_wlfc_hanger_mark_suppressed(wlfc->hanger, ++ WLFC_PKTID_HSLOT_GET(status), WLFC_PKTID_GEN(status)); ++ entry->suppress_count++; ++ } ++ } ++ else { ++ dhd_txcomplete(dhd, pktbuf, TRUE); ++ entry->transit_count--; ++ ++ /* This packet is transmitted Successfully by dongle even after first suppress. */ ++ if (entry->suppressed) { ++ entry->suppr_transit_count--; ++ } ++ /* free the packet */ ++ PKTFREE(wlfc->osh, pktbuf, TRUE); ++ } ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_fifocreditback_indicate(dhd_pub_t *dhd, uint8* credits) ++{ ++ int i; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ for (i = 0; i < WLFC_CTL_VALUE_LEN_FIFO_CREDITBACK; i++) { ++#ifdef PROP_TXSTATUS_DEBUG ++ wlfc->stats.fifo_credits_back[i] += credits[i]; ++#endif ++ /* update FIFO credits */ ++ if (wlfc->proptxstatus_mode == WLFC_FCMODE_EXPLICIT_CREDIT) ++ { ++ int lender; /* Note that borrower is i */ ++ ++ /* Return credits to highest priority lender first */ ++ for (lender = AC_COUNT; (lender >= 0) && (credits[i] > 0); lender--) { ++ if (wlfc->credits_borrowed[i][lender] > 0) { ++ if (credits[i] >= wlfc->credits_borrowed[i][lender]) { ++ credits[i] -= wlfc->credits_borrowed[i][lender]; ++ wlfc->FIFO_credit[lender] += ++ wlfc->credits_borrowed[i][lender]; ++ wlfc->credits_borrowed[i][lender] = 0; ++ } ++ else { ++ wlfc->credits_borrowed[i][lender] -= credits[i]; ++ wlfc->FIFO_credit[lender] += credits[i]; ++ credits[i] = 0; ++ } ++ } ++ } ++ ++ /* If we have more credits left over, these must belong to the AC */ ++ if (credits[i] > 0) { ++ wlfc->FIFO_credit[i] += credits[i]; ++ } ++ } ++ } ++ ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_dbg_senum_check(dhd_pub_t *dhd, uint8 *value) ++{ ++ uint32 timestamp; ++ ++ (void)dhd; ++ ++ bcopy(&value[2], ×tamp, sizeof(uint32)); ++ AP6210_DEBUG("RXPKT: SEQ: %d, timestamp %d\n", value[1], timestamp); ++ return BCME_OK; ++} ++ ++ ++static int ++dhd_wlfc_rssi_indicate(dhd_pub_t *dhd, uint8* rssi) ++{ ++ (void)dhd; ++ (void)rssi; ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_mac_table_update(dhd_pub_t *dhd, uint8* value, uint8 type) ++{ ++ int rc; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ uint8 existing_index; ++ uint8 table_index; ++ uint8 ifid; ++ uint8* ea; ++ ++ AP6210_DEBUG("%s(), mac [%02x:%02x:%02x:%02x:%02x:%02x],%s,idx:%d,id:0x%02x\n", ++ __FUNCTION__, value[2], value[3], value[4], value[5], value[6], value[7], ++ ((type == WLFC_CTL_TYPE_MACDESC_ADD) ? "ADD":"DEL"), ++ WLFC_MAC_DESC_GET_LOOKUP_INDEX(value[0]), value[0]); ++ ++ table = wlfc->destination_entries.nodes; ++ table_index = WLFC_MAC_DESC_GET_LOOKUP_INDEX(value[0]); ++ ifid = value[1]; ++ ea = &value[2]; ++ ++ if (type == WLFC_CTL_TYPE_MACDESC_ADD) { ++ existing_index = dhd_wlfc_find_mac_desc_id_from_mac(dhd, &value[2]); ++ if (existing_index == WLFC_MAC_DESC_ID_INVALID) { ++ /* this MAC entry does not exist, create one */ ++ if (!table[table_index].occupied) { ++ table[table_index].mac_handle = value[0]; ++ rc = _dhd_wlfc_mac_entry_update(wlfc, &table[table_index], ++ eWLFC_MAC_ENTRY_ACTION_ADD, ifid, ++ wlfc->destination_entries.interfaces[ifid].iftype, ++ ea); ++ } ++ else { ++ /* the space should have been empty, but it's not */ ++ wlfc->stats.mac_update_failed++; ++ } ++ } ++ else { ++ /* ++ there is an existing entry, move it to new index ++ if necessary. ++ */ ++ if (existing_index != table_index) { ++ /* if we already have an entry, free the old one */ ++ table[existing_index].occupied = 0; ++ table[existing_index].state = WLFC_STATE_CLOSE; ++ table[existing_index].requested_credit = 0; ++ table[existing_index].interface_id = 0; ++ /* enable after packets are queued-deqeued properly. ++ pktq_flush(dhd->osh, &table[existing_index].psq, FALSE, NULL, 0); ++ */ ++ } ++ } ++ } ++ if (type == WLFC_CTL_TYPE_MACDESC_DEL) { ++ if (table[table_index].occupied) { ++ rc = _dhd_wlfc_mac_entry_update(wlfc, &table[table_index], ++ eWLFC_MAC_ENTRY_ACTION_DEL, ifid, ++ wlfc->destination_entries.interfaces[ifid].iftype, ++ ea); ++ } ++ else { ++ /* the space should have been occupied, but it's not */ ++ wlfc->stats.mac_update_failed++; ++ } ++ } ++ BCM_REFERENCE(rc); ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_psmode_update(dhd_pub_t *dhd, uint8* value, uint8 type) ++{ ++ /* Handle PS on/off indication */ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ wlfc_mac_descriptor_t* desc; ++ uint8 mac_handle = value[0]; ++ int i; ++ ++ table = wlfc->destination_entries.nodes; ++ desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)]; ++ if (desc->occupied) { ++ /* a fresh PS mode should wipe old ps credits? */ ++ desc->requested_credit = 0; ++ if (type == WLFC_CTL_TYPE_MAC_OPEN) { ++ desc->state = WLFC_STATE_OPEN; ++ DHD_WLFC_CTRINC_MAC_OPEN(desc); ++ } ++ else { ++ desc->state = WLFC_STATE_CLOSE; ++ DHD_WLFC_CTRINC_MAC_CLOSE(desc); ++ /* ++ Indicate to firmware if there is any traffic pending. ++ */ ++ for (i = AC_BE; i < AC_COUNT; i++) { ++ _dhd_wlfc_traffic_pending_check(wlfc, desc, i); ++ } ++ } ++ } ++ else { ++ wlfc->stats.psmode_update_failed++; ++ } ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_interface_update(dhd_pub_t *dhd, uint8* value, uint8 type) ++{ ++ /* Handle PS on/off indication */ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ uint8 if_id = value[0]; ++ ++ if (if_id < WLFC_MAX_IFNUM) { ++ table = wlfc->destination_entries.interfaces; ++ if (table[if_id].occupied) { ++ if (type == WLFC_CTL_TYPE_INTERFACE_OPEN) { ++ table[if_id].state = WLFC_STATE_OPEN; ++ /* AP6210_DEBUG("INTERFACE[%d] OPEN\n", if_id); */ ++ } ++ else { ++ table[if_id].state = WLFC_STATE_CLOSE; ++ /* AP6210_DEBUG("INTERFACE[%d] CLOSE\n", if_id); */ ++ } ++ return BCME_OK; ++ } ++ } ++ wlfc->stats.interface_update_failed++; ++ ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_credit_request(dhd_pub_t *dhd, uint8* value) ++{ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ wlfc_mac_descriptor_t* desc; ++ uint8 mac_handle; ++ uint8 credit; ++ ++ table = wlfc->destination_entries.nodes; ++ mac_handle = value[1]; ++ credit = value[0]; ++ ++ desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)]; ++ if (desc->occupied) { ++ desc->requested_credit = credit; ++ ++ desc->ac_bitmap = value[2]; ++ } ++ else { ++ wlfc->stats.credit_request_failed++; ++ } ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_packet_request(dhd_pub_t *dhd, uint8* value) ++{ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ wlfc_mac_descriptor_t* desc; ++ uint8 mac_handle; ++ uint8 packet_count; ++ ++ table = wlfc->destination_entries.nodes; ++ mac_handle = value[1]; ++ packet_count = value[0]; ++ ++ desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)]; ++ if (desc->occupied) { ++ desc->requested_packet = packet_count; ++ ++ desc->ac_bitmap = value[2]; ++ } ++ else { ++ wlfc->stats.packet_request_failed++; ++ } ++ return BCME_OK; ++} ++ ++static void ++dhd_wlfc_reorderinfo_indicate(uint8 *val, uint8 len, uchar *info_buf, uint *info_len) ++{ ++ if (info_len) { ++ if (info_buf) { ++ bcopy(val, info_buf, len); ++ *info_len = len; ++ } ++ else ++ *info_len = 0; ++ } ++} ++ ++static int ++dhd_wlfc_parse_header_info(dhd_pub_t *dhd, void* pktbuf, int tlv_hdr_len, uchar *reorder_info_buf, ++ uint *reorder_info_len) ++{ ++ uint8 type, len; ++ uint8* value; ++ uint8* tmpbuf; ++ uint16 remainder = tlv_hdr_len; ++ uint16 processed = 0; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ tmpbuf = (uint8*)PKTDATA(dhd->osh, pktbuf); ++ if (remainder) { ++ while ((processed < (WLFC_MAX_PENDING_DATALEN * 2)) && (remainder > 0)) { ++ type = tmpbuf[processed]; ++ if (type == WLFC_CTL_TYPE_FILLER) { ++ remainder -= 1; ++ processed += 1; ++ continue; ++ } ++ ++ len = tmpbuf[processed + 1]; ++ value = &tmpbuf[processed + 2]; ++ ++ if (remainder < (2 + len)) ++ break; ++ ++ remainder -= 2 + len; ++ processed += 2 + len; ++ if (type == WLFC_CTL_TYPE_TXSTATUS) ++ dhd_wlfc_txstatus_update(dhd, value); ++ if (type == WLFC_CTL_TYPE_COMP_TXSTATUS) ++ dhd_wlfc_compressed_txstatus_update(dhd, value, len); ++ ++ else if (type == WLFC_CTL_TYPE_HOST_REORDER_RXPKTS) ++ dhd_wlfc_reorderinfo_indicate(value, len, reorder_info_buf, ++ reorder_info_len); ++ else if (type == WLFC_CTL_TYPE_FIFO_CREDITBACK) ++ dhd_wlfc_fifocreditback_indicate(dhd, value); ++ ++ else if (type == WLFC_CTL_TYPE_RSSI) ++ dhd_wlfc_rssi_indicate(dhd, value); ++ ++ else if (type == WLFC_CTL_TYPE_MAC_REQUEST_CREDIT) ++ dhd_wlfc_credit_request(dhd, value); ++ ++ else if (type == WLFC_CTL_TYPE_MAC_REQUEST_PACKET) ++ dhd_wlfc_packet_request(dhd, value); ++ ++ else if ((type == WLFC_CTL_TYPE_MAC_OPEN) || ++ (type == WLFC_CTL_TYPE_MAC_CLOSE)) ++ dhd_wlfc_psmode_update(dhd, value, type); ++ ++ else if ((type == WLFC_CTL_TYPE_MACDESC_ADD) || ++ (type == WLFC_CTL_TYPE_MACDESC_DEL)) ++ dhd_wlfc_mac_table_update(dhd, value, type); ++ ++ else if (type == WLFC_CTL_TYPE_TRANS_ID) ++ dhd_wlfc_dbg_senum_check(dhd, value); ++ ++ else if ((type == WLFC_CTL_TYPE_INTERFACE_OPEN) || ++ (type == WLFC_CTL_TYPE_INTERFACE_CLOSE)) { ++ dhd_wlfc_interface_update(dhd, value, type); ++ } ++ } ++ if (remainder != 0) { ++ /* trouble..., something is not right */ ++ wlfc->stats.tlv_parse_failed++; ++ } ++ } ++ return BCME_OK; ++} ++ ++int ++dhd_wlfc_init(dhd_pub_t *dhd) ++{ ++ char iovbuf[12]; /* Room for "tlv" + '\0' + parameter */ ++ /* enable all signals & indicate host proptxstatus logic is active */ ++ uint32 tlv = dhd->wlfc_enabled? ++ WLFC_FLAGS_RSSI_SIGNALS | ++ WLFC_FLAGS_XONXOFF_SIGNALS | ++ WLFC_FLAGS_CREDIT_STATUS_SIGNALS | ++ WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE | ++ WLFC_FLAGS_HOST_RXRERODER_ACTIVE : 0; ++ /* WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE | WLFC_FLAGS_HOST_RXRERODER_ACTIVE : 0; */ ++ ++ ++ /* ++ try to enable/disable signaling by sending "tlv" iovar. if that fails, ++ fallback to no flow control? Print a message for now. ++ */ ++ ++ /* enable proptxtstatus signaling by default */ ++ bcm_mkiovar("tlv", (char *)&tlv, 4, iovbuf, sizeof(iovbuf)); ++ if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) < 0) { ++ AP6210_ERR("dhd_wlfc_init(): failed to enable/disable bdcv2 tlv signaling\n"); ++ } ++ else { ++ /* ++ Leaving the message for now, it should be removed after a while; once ++ the tlv situation is stable. ++ */ ++ AP6210_DEBUG("dhd_wlfc_init(): successfully %s bdcv2 tlv signaling, %d\n", ++ dhd->wlfc_enabled?"enabled":"disabled", tlv); ++ } ++ return BCME_OK; ++} ++ ++int ++dhd_wlfc_enable(dhd_pub_t *dhd) ++{ ++ int i; ++ athost_wl_status_info_t* wlfc; ++ ++ AP6210_DEBUG("Enter %s\n", __FUNCTION__); ++ ++ if (!dhd->wlfc_enabled || dhd->wlfc_state) ++ return BCME_OK; ++ ++ /* allocate space to track txstatus propagated from firmware */ ++ dhd->wlfc_state = MALLOC(dhd->osh, sizeof(athost_wl_status_info_t)); ++ if (dhd->wlfc_state == NULL) ++ return BCME_NOMEM; ++ ++ /* initialize state space */ ++ wlfc = (athost_wl_status_info_t*)dhd->wlfc_state; ++ memset(wlfc, 0, sizeof(athost_wl_status_info_t)); ++ ++ /* remember osh & dhdp */ ++ wlfc->osh = dhd->osh; ++ wlfc->dhdp = dhd; ++ ++ wlfc->hanger = ++ dhd_wlfc_hanger_create(dhd->osh, WLFC_HANGER_MAXITEMS); ++ if (wlfc->hanger == NULL) { ++ MFREE(dhd->osh, dhd->wlfc_state, sizeof(athost_wl_status_info_t)); ++ dhd->wlfc_state = NULL; ++ return BCME_NOMEM; ++ } ++ ++ /* initialize all interfaces to accept traffic */ ++ for (i = 0; i < WLFC_MAX_IFNUM; i++) { ++ wlfc->hostif_flow_state[i] = OFF; ++ } ++ ++ /* ++ create the SENDQ containing ++ sub-queues for all AC precedences + 1 for bc/mc traffic ++ */ ++ pktq_init(&wlfc->SENDQ, (AC_COUNT + 1), WLFC_SENDQ_LEN); ++ ++ wlfc->destination_entries.other.state = WLFC_STATE_OPEN; ++ /* bc/mc FIFO is always open [credit aside], i.e. b[5] */ ++ wlfc->destination_entries.other.ac_bitmap = 0x1f; ++ wlfc->destination_entries.other.interface_id = 0; ++ ++ wlfc->proptxstatus_mode = WLFC_FCMODE_EXPLICIT_CREDIT; ++ ++ wlfc->allow_credit_borrow = TRUE; ++ wlfc->borrow_defer_timestamp = 0; ++ ++ return BCME_OK; ++} ++ ++/* release all packet resources */ ++void ++dhd_wlfc_cleanup(dhd_pub_t *dhd) ++{ ++ int i; ++ int total_entries; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ wlfc_hanger_t* h; ++ int prec; ++ void *pkt = NULL; ++ struct pktq *txq = NULL; ++ ++ AP6210_DEBUG("Enter %s\n", __FUNCTION__); ++ if (dhd->wlfc_state == NULL) ++ return; ++ /* flush bus->txq */ ++ txq = dhd_bus_txq(dhd->bus); ++ ++ /* any in the hanger? */ ++ h = (wlfc_hanger_t*)wlfc->hanger; ++ total_entries = sizeof(wlfc->destination_entries)/sizeof(wlfc_mac_descriptor_t); ++ /* search all entries, include nodes as well as interfaces */ ++ table = (wlfc_mac_descriptor_t*)&wlfc->destination_entries; ++ ++ for (i = 0; i < total_entries; i++) { ++ if (table[i].occupied) { ++ if (table[i].psq.len) { ++ AP6210_DEBUG("%s(): DELAYQ[%d].len = %d\n", ++ __FUNCTION__, i, table[i].psq.len); ++ /* release packets held in DELAYQ */ ++ pktq_flush(wlfc->osh, &table[i].psq, TRUE, NULL, 0); ++ } ++ table[i].occupied = 0; ++ } ++ } ++ /* release packets held in SENDQ */ ++ if (wlfc->SENDQ.len) ++ pktq_flush(wlfc->osh, &wlfc->SENDQ, TRUE, NULL, 0); ++ for (prec = 0; prec < txq->num_prec; prec++) { ++ pkt = pktq_pdeq(txq, prec); ++ while (pkt) { ++ for (i = 0; i < h->max_items; i++) { ++ if (pkt == h->items[i].pkt) { ++ if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { ++ PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); ++ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; ++ h->items[i].pkt = NULL; ++ h->items[i].identifier = 0; ++ } else if (h->items[i].state == ++ WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { ++ /* These are already freed from the psq */ ++ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; ++ } ++ break; ++ } ++ } ++ pkt = pktq_pdeq(txq, prec); ++ } ++ } ++ /* flush remained pkt in hanger queue, not in bus->txq */ ++ for (i = 0; i < h->max_items; i++) { ++ if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { ++ PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); ++ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; ++ } else if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { ++ /* These are freed from the psq so no need to free again */ ++ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; ++ } ++ } ++ ++ return; ++} ++ ++void ++dhd_wlfc_deinit(dhd_pub_t *dhd) ++{ ++ /* cleanup all psq related resources */ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ ++ AP6210_DEBUG("Enter %s\n", __FUNCTION__); ++ ++ dhd_os_wlfc_block(dhd); ++ if (dhd->wlfc_state == NULL) { ++ dhd_os_wlfc_unblock(dhd); ++ return; ++ } ++ ++#ifdef PROP_TXSTATUS_DEBUG ++ { ++ int i; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)wlfc->hanger; ++ for (i = 0; i < h->max_items; i++) { ++ if (h->items[i].state != WLFC_HANGER_ITEM_STATE_FREE) { ++ AP6210_DEBUG("%s() pkt[%d] = 0x%p, FIFO_credit_used:%d\n", ++ __FUNCTION__, i, h->items[i].pkt, ++ DHD_PKTTAG_CREDITCHECK(PKTTAG(h->items[i].pkt))); ++ } ++ } ++ } ++#endif ++ /* delete hanger */ ++ dhd_wlfc_hanger_delete(dhd->osh, wlfc->hanger); ++ ++ /* free top structure */ ++ MFREE(dhd->osh, dhd->wlfc_state, sizeof(athost_wl_status_info_t)); ++ dhd->wlfc_state = NULL; ++ dhd_os_wlfc_unblock(dhd); ++ ++ return; ++} ++#endif /* PROP_TXSTATUS */ ++ ++void ++dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) ++{ ++ bcm_bprintf(strbuf, "Protocol CDC: reqid %d\n", dhdp->prot->reqid); ++#ifdef PROP_TXSTATUS ++ dhd_os_wlfc_block(dhdp); ++ if (dhdp->wlfc_state) ++ dhd_wlfc_dump(dhdp, strbuf); ++ dhd_os_wlfc_unblock(dhdp); ++#endif ++} ++ ++void ++dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *pktbuf) ++{ ++#ifdef BDC ++ struct bdc_header *h; ++#endif /* BDC */ ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++#ifdef BDC ++ /* Push BDC header used to convey priority for buses that don't */ ++ ++ PKTPUSH(dhd->osh, pktbuf, BDC_HEADER_LEN); ++ ++ h = (struct bdc_header *)PKTDATA(dhd->osh, pktbuf); ++ ++ h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); ++ if (PKTSUMNEEDED(pktbuf)) ++ h->flags |= BDC_FLAG_SUM_NEEDED; ++ ++ ++ h->priority = (PKTPRIO(pktbuf) & BDC_PRIORITY_MASK); ++ h->flags2 = 0; ++ h->dataOffset = 0; ++#endif /* BDC */ ++ BDC_SET_IF_IDX(h, ifidx); ++} ++ ++int ++dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf, uchar *reorder_buf_info, ++ uint *reorder_info_len) ++{ ++#ifdef BDC ++ struct bdc_header *h; ++#endif ++ uint8 data_offset = 0; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++#ifdef BDC ++ if (reorder_info_len) ++ *reorder_info_len = 0; ++ /* Pop BDC header used to convey priority for buses that don't */ ++ ++ if (PKTLEN(dhd->osh, pktbuf) < BDC_HEADER_LEN) { ++ AP6210_ERR("%s: rx data too short (%d < %d)\n", __FUNCTION__, ++ PKTLEN(dhd->osh, pktbuf), BDC_HEADER_LEN); ++ return BCME_ERROR; ++ } ++ ++ h = (struct bdc_header *)PKTDATA(dhd->osh, pktbuf); ++ ++#if defined(NDIS630) ++ h->dataOffset = 0; ++#endif ++ ++ if (!ifidx) { ++ /* for tx packet, skip the analysis */ ++ data_offset = h->dataOffset; ++ PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN); ++ goto exit; ++ } ++ ++ if ((*ifidx = BDC_GET_IF_IDX(h)) >= DHD_MAX_IFS) { ++ AP6210_ERR("%s: rx data ifnum out of range (%d)\n", ++ __FUNCTION__, *ifidx); ++ return BCME_ERROR; ++ } ++ ++ if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != BDC_PROTO_VER) { ++ AP6210_ERR("%s: non-BDC packet received, flags = 0x%x\n", ++ dhd_ifname(dhd, *ifidx), h->flags); ++ if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) == BDC_PROTO_VER_1) ++ h->dataOffset = 0; ++ else ++ return BCME_ERROR; ++ } ++ ++ if (h->flags & BDC_FLAG_SUM_GOOD) { ++ AP6210_DEBUG("%s: BDC packet received with good rx-csum, flags 0x%x\n", ++ dhd_ifname(dhd, *ifidx), h->flags); ++ PKTSETSUMGOOD(pktbuf, TRUE); ++ } ++ ++ PKTSETPRIO(pktbuf, (h->priority & BDC_PRIORITY_MASK)); ++ data_offset = h->dataOffset; ++ PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN); ++#endif /* BDC */ ++ ++#if !defined(NDIS630) ++ if (PKTLEN(dhd->osh, pktbuf) < (uint32) (data_offset << 2)) { ++ AP6210_ERR("%s: rx data too short (%d < %d)\n", __FUNCTION__, ++ PKTLEN(dhd->osh, pktbuf), (data_offset * 4)); ++ return BCME_ERROR; ++ } ++#endif ++#ifdef PROP_TXSTATUS ++ if (dhd->wlfc_state && ++ ((athost_wl_status_info_t*)dhd->wlfc_state)->proptxstatus_mode ++ != WLFC_FCMODE_NONE && ++ (!DHD_PKTTAG_PKTDIR(PKTTAG(pktbuf)))) { ++ /* ++ - parse txstatus only for packets that came from the firmware ++ */ ++ dhd_os_wlfc_block(dhd); ++ dhd_wlfc_parse_header_info(dhd, pktbuf, (data_offset << 2), ++ reorder_buf_info, reorder_info_len); ++ ((athost_wl_status_info_t*)dhd->wlfc_state)->stats.dhd_hdrpulls++; ++ dhd_os_wlfc_unblock(dhd); ++ } ++#endif /* PROP_TXSTATUS */ ++ ++exit: ++#if !defined(NDIS630) ++ PKTPULL(dhd->osh, pktbuf, (data_offset << 2)); ++#endif ++ return 0; ++} ++ ++#if defined(PROP_TXSTATUS) ++void ++dhd_wlfc_trigger_pktcommit(dhd_pub_t *dhd) ++{ ++ if (dhd->wlfc_state && ++ (((athost_wl_status_info_t*)dhd->wlfc_state)->proptxstatus_mode ++ != WLFC_FCMODE_NONE)) { ++ dhd_os_wlfc_block(dhd); ++ dhd_wlfc_commit_packets(dhd->wlfc_state, (f_commitpkt_t)dhd_bus_txdata, ++ (void *)dhd->bus); ++ dhd_os_wlfc_unblock(dhd); ++ } ++} ++#endif ++ ++int ++dhd_prot_attach(dhd_pub_t *dhd) ++{ ++ dhd_prot_t *cdc; ++ ++ if (!(cdc = (dhd_prot_t *)DHD_OS_PREALLOC(dhd->osh, DHD_PREALLOC_PROT, ++ sizeof(dhd_prot_t)))) { ++ AP6210_ERR("%s: kmalloc failed\n", __FUNCTION__); ++ goto fail; ++ } ++ memset(cdc, 0, sizeof(dhd_prot_t)); ++ ++ /* ensure that the msg buf directly follows the cdc msg struct */ ++ if ((uintptr)(&cdc->msg + 1) != (uintptr)cdc->buf) { ++ AP6210_ERR("dhd_prot_t is not correctly defined\n"); ++ goto fail; ++ } ++ ++ dhd->prot = cdc; ++#ifdef BDC ++ dhd->hdrlen += BDC_HEADER_LEN; ++#endif ++ dhd->maxctl = WLC_IOCTL_MAXLEN + sizeof(cdc_ioctl_t) + ROUND_UP_MARGIN; ++ return 0; ++ ++fail: ++#ifndef CONFIG_DHD_USE_STATIC_BUF ++ if (cdc != NULL) ++ MFREE(dhd->osh, cdc, sizeof(dhd_prot_t)); ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ return BCME_NOMEM; ++} ++ ++/* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */ ++void ++dhd_prot_detach(dhd_pub_t *dhd) ++{ ++#ifdef PROP_TXSTATUS ++ dhd_wlfc_deinit(dhd); ++#endif ++#ifndef CONFIG_DHD_USE_STATIC_BUF ++ MFREE(dhd->osh, dhd->prot, sizeof(dhd_prot_t)); ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ dhd->prot = NULL; ++} ++ ++void ++dhd_prot_dstats(dhd_pub_t *dhd) ++{ ++ /* No stats from dongle added yet, copy bus stats */ ++ dhd->dstats.tx_packets = dhd->tx_packets; ++ dhd->dstats.tx_errors = dhd->tx_errors; ++ dhd->dstats.rx_packets = dhd->rx_packets; ++ dhd->dstats.rx_errors = dhd->rx_errors; ++ dhd->dstats.rx_dropped = dhd->rx_dropped; ++ dhd->dstats.multicast = dhd->rx_multicast; ++ return; ++} ++ ++int ++dhd_prot_init(dhd_pub_t *dhd) ++{ ++ int ret = 0; ++ wlc_rev_info_t revinfo; ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ ++ /* Get the device rev info */ ++ memset(&revinfo, 0, sizeof(revinfo)); ++ ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_REVINFO, &revinfo, sizeof(revinfo), FALSE, 0); ++ if (ret < 0) ++ goto done; ++ ++ ++#if defined(WL_CFG80211) ++ if (dhd_download_fw_on_driverload) ++#endif /* defined(WL_CFG80211) */ ++ ret = dhd_preinit_ioctls(dhd); ++ ++#ifdef PROP_TXSTATUS ++ ret = dhd_wlfc_init(dhd); ++#endif ++ ++ /* Always assumes wl for now */ ++ dhd->iswl = TRUE; ++ ++done: ++ return ret; ++} ++ ++void ++dhd_prot_stop(dhd_pub_t *dhd) ++{ ++ /* Nothing to do for CDC */ ++} ++ ++ ++static void ++dhd_get_hostreorder_pkts(void *osh, struct reorder_info *ptr, void **pkt, ++ uint32 *pkt_count, void **pplast, uint8 start, uint8 end) ++{ ++ uint i; ++ void *plast = NULL, *p; ++ uint32 pkt_cnt = 0; ++ ++ if (ptr->pend_pkts == 0) { ++ AP6210_DEBUG("%s: no packets in reorder queue \n", __FUNCTION__); ++ *pplast = NULL; ++ *pkt_count = 0; ++ *pkt = NULL; ++ return; ++ } ++ if (start == end) ++ i = ptr->max_idx + 1; ++ else { ++ if (start > end) ++ i = ((ptr->max_idx + 1) - start) + end; ++ else ++ i = end - start; ++ } ++ while (i) { ++ p = (void *)(ptr->p[start]); ++ ptr->p[start] = NULL; ++ ++ if (p != NULL) { ++ if (plast == NULL) ++ *pkt = p; ++ else ++ PKTSETNEXT(osh, plast, p); ++ ++ plast = p; ++ pkt_cnt++; ++ } ++ i--; ++ if (start++ == ptr->max_idx) ++ start = 0; ++ } ++ *pplast = plast; ++ *pkt_count = (uint32)pkt_cnt; ++} ++ ++int ++dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reorder_info_len, ++ void **pkt, uint32 *pkt_count) ++{ ++ uint8 flow_id, max_idx, cur_idx, exp_idx; ++ struct reorder_info *ptr; ++ uint8 flags; ++ void *cur_pkt, *plast = NULL; ++ uint32 cnt = 0; ++ ++ if (pkt == NULL) { ++ if (pkt_count != NULL) ++ *pkt_count = 0; ++ return 0; ++ } ++ ++ flow_id = reorder_info_buf[WLHOST_REORDERDATA_FLOWID_OFFSET]; ++ flags = reorder_info_buf[WLHOST_REORDERDATA_FLAGS_OFFSET]; ++ ++ AP6210_DEBUG("flow_id %d, flags 0x%02x, idx(%d, %d, %d)\n", flow_id, flags, ++ reorder_info_buf[WLHOST_REORDERDATA_CURIDX_OFFSET], ++ reorder_info_buf[WLHOST_REORDERDATA_EXPIDX_OFFSET], ++ reorder_info_buf[WLHOST_REORDERDATA_MAXIDX_OFFSET]); ++ ++ /* validate flags and flow id */ ++ if (flags == 0xFF) { ++ AP6210_ERR("%s: invalid flags...so ignore this packet\n", __FUNCTION__); ++ *pkt_count = 1; ++ return 0; ++ } ++ ++ cur_pkt = *pkt; ++ *pkt = NULL; ++ ++ ptr = dhd->reorder_bufs[flow_id]; ++ if (flags & WLHOST_REORDERDATA_DEL_FLOW) { ++ uint32 buf_size = sizeof(struct reorder_info); ++ ++ AP6210_DEBUG("%s: Flags indicating to delete a flow id %d\n", ++ __FUNCTION__, flow_id); ++ ++ if (ptr == NULL) { ++ AP6210_ERR("%s: received flags to cleanup, but no flow (%d) yet\n", ++ __FUNCTION__, flow_id); ++ *pkt_count = 1; ++ *pkt = cur_pkt; ++ return 0; ++ } ++ ++ dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast, ++ ptr->exp_idx, ptr->exp_idx); ++ /* set it to the last packet */ ++ if (plast) { ++ PKTSETNEXT(dhd->osh, plast, cur_pkt); ++ cnt++; ++ } ++ else { ++ if (cnt != 0) { ++ AP6210_ERR("%s: del flow: something fishy, pending packets %d\n", ++ __FUNCTION__, cnt); ++ } ++ *pkt = cur_pkt; ++ cnt = 1; ++ } ++ buf_size += ((ptr->max_idx + 1) * sizeof(void *)); ++ MFREE(dhd->osh, ptr, buf_size); ++ dhd->reorder_bufs[flow_id] = NULL; ++ *pkt_count = cnt; ++ return 0; ++ } ++ /* all the other cases depend on the existance of the reorder struct for that flow id */ ++ if (ptr == NULL) { ++ uint32 buf_size_alloc = sizeof(reorder_info_t); ++ max_idx = reorder_info_buf[WLHOST_REORDERDATA_MAXIDX_OFFSET]; ++ ++ buf_size_alloc += ((max_idx + 1) * sizeof(void*)); ++ /* allocate space to hold the buffers, index etc */ ++ ++ AP6210_DEBUG("%s: alloc buffer of size %d size, reorder info id %d, maxidx %d\n", ++ __FUNCTION__, buf_size_alloc, flow_id, max_idx); ++ ptr = (struct reorder_info *)MALLOC(dhd->osh, buf_size_alloc); ++ if (ptr == NULL) { ++ AP6210_ERR("%s: Malloc failed to alloc buffer\n", __FUNCTION__); ++ *pkt_count = 1; ++ return 0; ++ } ++ bzero(ptr, buf_size_alloc); ++ dhd->reorder_bufs[flow_id] = ptr; ++ ptr->p = (void *)(ptr+1); ++ ptr->max_idx = max_idx; ++ } ++ if (flags & WLHOST_REORDERDATA_NEW_HOLE) { ++ AP6210_DEBUG("%s: new hole, so cleanup pending buffers\n", __FUNCTION__); ++ if (ptr->pend_pkts) { ++ dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast, ++ ptr->exp_idx, ptr->exp_idx); ++ ptr->pend_pkts = 0; ++ } ++ ptr->cur_idx = reorder_info_buf[WLHOST_REORDERDATA_CURIDX_OFFSET]; ++ ptr->exp_idx = reorder_info_buf[WLHOST_REORDERDATA_EXPIDX_OFFSET]; ++ ptr->max_idx = reorder_info_buf[WLHOST_REORDERDATA_MAXIDX_OFFSET]; ++ ptr->p[ptr->cur_idx] = cur_pkt; ++ ptr->pend_pkts++; ++ *pkt_count = cnt; ++ } ++ else if (flags & WLHOST_REORDERDATA_CURIDX_VALID) { ++ cur_idx = reorder_info_buf[WLHOST_REORDERDATA_CURIDX_OFFSET]; ++ exp_idx = reorder_info_buf[WLHOST_REORDERDATA_EXPIDX_OFFSET]; ++ ++ ++ if ((exp_idx == ptr->exp_idx) && (cur_idx != ptr->exp_idx)) { ++ /* still in the current hole */ ++ /* enqueue the current on the buffer chain */ ++ if (ptr->p[cur_idx] != NULL) { ++ AP6210_DEBUG("%s: HOLE: ERROR buffer pending..free it\n", ++ __FUNCTION__); ++ PKTFREE(dhd->osh, ptr->p[cur_idx], TRUE); ++ ptr->p[cur_idx] = NULL; ++ } ++ ptr->p[cur_idx] = cur_pkt; ++ ptr->pend_pkts++; ++ ptr->cur_idx = cur_idx; ++ AP6210_DEBUG("%s: fill up a hole..pending packets is %d\n", ++ __FUNCTION__, ptr->pend_pkts); ++ *pkt_count = 0; ++ *pkt = NULL; ++ } ++ else if (ptr->exp_idx == cur_idx) { ++ /* got the right one ..flush from cur to exp and update exp */ ++ AP6210_DEBUG("%s: got the right one now, cur_idx is %d\n", ++ __FUNCTION__, cur_idx); ++ if (ptr->p[cur_idx] != NULL) { ++ AP6210_DEBUG("%s: Error buffer pending..free it\n", ++ __FUNCTION__); ++ PKTFREE(dhd->osh, ptr->p[cur_idx], TRUE); ++ ptr->p[cur_idx] = NULL; ++ } ++ ptr->p[cur_idx] = cur_pkt; ++ ptr->pend_pkts++; ++ ++ ptr->cur_idx = cur_idx; ++ ptr->exp_idx = exp_idx; ++ ++ dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast, ++ cur_idx, exp_idx); ++ ptr->pend_pkts -= (uint8)cnt; ++ *pkt_count = cnt; ++ AP6210_DEBUG("%s: freeing up buffers %d, still pending %d\n", ++ __FUNCTION__, cnt, ptr->pend_pkts); ++ } ++ else { ++ uint8 end_idx; ++ bool flush_current = FALSE; ++ /* both cur and exp are moved now .. */ ++ AP6210_DEBUG("%s:, flow %d, both moved, cur %d(%d), exp %d(%d)\n", ++ __FUNCTION__, flow_id, ptr->cur_idx, cur_idx, ++ ptr->exp_idx, exp_idx); ++ if (flags & WLHOST_REORDERDATA_FLUSH_ALL) ++ end_idx = ptr->exp_idx; ++ else ++ end_idx = exp_idx; ++ ++ /* flush pkts first */ ++ dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast, ++ ptr->exp_idx, end_idx); ++ ++ if (cur_idx == ptr->max_idx) { ++ if (exp_idx == 0) ++ flush_current = TRUE; ++ } else { ++ if (exp_idx == cur_idx + 1) ++ flush_current = TRUE; ++ } ++ if (flush_current) { ++ if (plast) ++ PKTSETNEXT(dhd->osh, plast, cur_pkt); ++ else ++ *pkt = cur_pkt; ++ cnt++; ++ } ++ else { ++ ptr->p[cur_idx] = cur_pkt; ++ ptr->pend_pkts++; ++ } ++ ptr->exp_idx = exp_idx; ++ ptr->cur_idx = cur_idx; ++ *pkt_count = cnt; ++ } ++ } ++ else { ++ uint8 end_idx; ++ /* no real packet but update to exp_seq...that means explicit window move */ ++ exp_idx = reorder_info_buf[WLHOST_REORDERDATA_EXPIDX_OFFSET]; ++ ++ AP6210_DEBUG("%s: move the window, cur_idx is %d, exp is %d, new exp is %d\n", ++ __FUNCTION__, ptr->cur_idx, ptr->exp_idx, exp_idx); ++ if (flags & WLHOST_REORDERDATA_FLUSH_ALL) ++ end_idx = ptr->exp_idx; ++ else ++ end_idx = exp_idx; ++ ++ dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast, ptr->exp_idx, end_idx); ++ ptr->pend_pkts -= (uint8)cnt; ++ if (plast) ++ PKTSETNEXT(dhd->osh, plast, cur_pkt); ++ else ++ *pkt = cur_pkt; ++ cnt++; ++ *pkt_count = cnt; ++ /* set the new expected idx */ ++ ptr->exp_idx = exp_idx; ++ } ++ return 0; ++} +diff --git a/drivers/net/wireless/ap6210/dhd_cfg80211.c b/drivers/net/wireless/ap6210/dhd_cfg80211.c +new file mode 100755 +index 0000000..8cb440e +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_cfg80211.c +@@ -0,0 +1,680 @@ ++/* ++ * Linux cfg80211 driver - Dongle Host Driver (DHD) related ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: wl_cfg80211.c,v 1.1.4.1.2.14 2011/02/09 01:40:07 Exp $ ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#ifdef PKT_FILTER_SUPPORT ++#include ++#include ++#endif ++ ++extern struct wl_priv *wlcfg_drv_priv; ++ ++#ifdef PKT_FILTER_SUPPORT ++extern uint dhd_pkt_filter_enable; ++extern uint dhd_master_mode; ++extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode); ++#endif ++ ++static int dhd_dongle_up = FALSE; ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++static s32 wl_dongle_up(struct net_device *ndev, u32 up); ++ ++/** ++ * Function implementations ++ */ ++ ++s32 dhd_cfg80211_init(struct wl_priv *wl) ++{ ++ dhd_dongle_up = FALSE; ++ return 0; ++} ++ ++s32 dhd_cfg80211_deinit(struct wl_priv *wl) ++{ ++ dhd_dongle_up = FALSE; ++ return 0; ++} ++ ++s32 dhd_cfg80211_down(struct wl_priv *wl) ++{ ++ dhd_dongle_up = FALSE; ++ return 0; ++} ++ ++s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val) ++{ ++ dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); ++ dhd->op_mode |= val; ++ AP6210_ERR("Set : op_mode=0x%04x\n", dhd->op_mode); ++#ifdef ARP_OFFLOAD_SUPPORT ++ if (dhd->arp_version == 1) { ++ /* IF P2P is enabled, disable arpoe */ ++ dhd_arp_offload_set(dhd, 0); ++ dhd_arp_offload_enable(dhd, false); ++ } ++#endif /* ARP_OFFLOAD_SUPPORT */ ++ ++ return 0; ++} ++ ++s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl) ++{ ++ dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); ++ dhd->op_mode &= ~(DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE); ++ AP6210_ERR("Clean : op_mode=0x%04x\n", dhd->op_mode); ++ ++#ifdef ARP_OFFLOAD_SUPPORT ++ if (dhd->arp_version == 1) { ++ /* IF P2P is disabled, enable arpoe back for STA mode. */ ++ dhd_arp_offload_set(dhd, dhd_arp_mode); ++ dhd_arp_offload_enable(dhd, true); ++ } ++#endif /* ARP_OFFLOAD_SUPPORT */ ++ ++ return 0; ++} ++ ++static s32 wl_dongle_up(struct net_device *ndev, u32 up) ++{ ++ s32 err = 0; ++ ++ err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), true); ++ if (unlikely(err)) { ++ AP6210_ERR("WLC_UP error (%d)\n", err); ++ } ++ return err; ++} ++s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock) ++{ ++#ifndef DHD_SDALIGN ++#define DHD_SDALIGN 32 ++#endif ++ struct net_device *ndev; ++ s32 err = 0; ++ ++ AP6210_DEBUG("In\n"); ++ if (dhd_dongle_up) { ++ AP6210_ERR("Dongle is already up\n"); ++ return err; ++ } ++ ++ ndev = wl_to_prmry_ndev(wl); ++ ++ if (need_lock) ++ rtnl_lock(); ++ ++ err = wl_dongle_up(ndev, 0); ++ if (unlikely(err)) { ++ AP6210_ERR("wl_dongle_up failed\n"); ++ goto default_conf_out; ++ } ++ dhd_dongle_up = true; ++ ++default_conf_out: ++ if (need_lock) ++ rtnl_unlock(); ++ return err; ++ ++} ++ ++ ++/* TODO: clean up the BT-Coex code, it still have some legacy ioctl/iovar functions */ ++#define COEX_DHCP ++ ++#if defined(COEX_DHCP) ++ ++/* use New SCO/eSCO smart YG suppression */ ++#define BT_DHCP_eSCO_FIX ++/* this flag boost wifi pkt priority to max, caution: -not fair to sco */ ++#define BT_DHCP_USE_FLAGS ++/* T1 start SCO/ESCo priority suppression */ ++#define BT_DHCP_OPPR_WIN_TIME 2500 ++/* T2 turn off SCO/SCO supperesion is (timeout) */ ++#define BT_DHCP_FLAG_FORCE_TIME 5500 ++ ++enum wl_cfg80211_btcoex_status { ++ BT_DHCP_IDLE, ++ BT_DHCP_START, ++ BT_DHCP_OPPR_WIN, ++ BT_DHCP_FLAG_FORCE_TIMEOUT ++}; ++ ++/* ++ * get named driver variable to uint register value and return error indication ++ * calling example: dev_wlc_intvar_get_reg(dev, "btc_params",66, ®_value) ++ */ ++static int ++dev_wlc_intvar_get_reg(struct net_device *dev, char *name, ++ uint reg, int *retval) ++{ ++ union { ++ char buf[WLC_IOCTL_SMLEN]; ++ int val; ++ } var; ++ int error; ++ ++ bcm_mkiovar(name, (char *)(®), sizeof(reg), ++ (char *)(&var), sizeof(var.buf)); ++ error = wldev_ioctl(dev, WLC_GET_VAR, (char *)(&var), sizeof(var.buf), false); ++ ++ *retval = dtoh32(var.val); ++ return (error); ++} ++ ++static int ++dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) ++ char ioctlbuf_local[1024]; ++#else ++ static char ioctlbuf_local[1024]; ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */ ++ ++ bcm_mkiovar(name, buf, len, ioctlbuf_local, sizeof(ioctlbuf_local)); ++ ++ return (wldev_ioctl(dev, WLC_SET_VAR, ioctlbuf_local, sizeof(ioctlbuf_local), true)); ++} ++/* ++get named driver variable to uint register value and return error indication ++calling example: dev_wlc_intvar_set_reg(dev, "btc_params",66, value) ++*/ ++static int ++dev_wlc_intvar_set_reg(struct net_device *dev, char *name, char *addr, char * val) ++{ ++ char reg_addr[8]; ++ ++ memset(reg_addr, 0, sizeof(reg_addr)); ++ memcpy((char *)®_addr[0], (char *)addr, 4); ++ memcpy((char *)®_addr[4], (char *)val, 4); ++ ++ return (dev_wlc_bufvar_set(dev, name, (char *)®_addr[0], sizeof(reg_addr))); ++} ++ ++static bool btcoex_is_sco_active(struct net_device *dev) ++{ ++ int ioc_res = 0; ++ bool res = FALSE; ++ int sco_id_cnt = 0; ++ int param27; ++ int i; ++ ++ for (i = 0; i < 12; i++) { ++ ++ ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, ¶m27); ++ ++ AP6210_DEBUG("%s, sample[%d], btc params: 27:%x\n", ++ __FUNCTION__, i, param27); ++ ++ if (ioc_res < 0) { ++ AP6210_ERR("%s ioc read btc params error\n", __FUNCTION__); ++ break; ++ } ++ ++ if ((param27 & 0x6) == 2) { /* count both sco & esco */ ++ sco_id_cnt++; ++ } ++ ++ if (sco_id_cnt > 2) { ++ AP6210_DEBUG("%s, sco/esco detected, pkt id_cnt:%d samples:%d\n", ++ __FUNCTION__, sco_id_cnt, i); ++ res = TRUE; ++ break; ++ } ++ ++ msleep(5); ++ } ++ ++ return res; ++} ++ ++#if defined(BT_DHCP_eSCO_FIX) ++/* Enhanced BT COEX settings for eSCO compatibility during DHCP window */ ++static int set_btc_esco_params(struct net_device *dev, bool trump_sco) ++{ ++ static bool saved_status = FALSE; ++ ++ char buf_reg50va_dhcp_on[8] = ++ { 50, 00, 00, 00, 0x22, 0x80, 0x00, 0x00 }; ++ char buf_reg51va_dhcp_on[8] = ++ { 51, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 }; ++ char buf_reg64va_dhcp_on[8] = ++ { 64, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 }; ++ char buf_reg65va_dhcp_on[8] = ++ { 65, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 }; ++ char buf_reg71va_dhcp_on[8] = ++ { 71, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 }; ++ uint32 regaddr; ++ static uint32 saved_reg50; ++ static uint32 saved_reg51; ++ static uint32 saved_reg64; ++ static uint32 saved_reg65; ++ static uint32 saved_reg71; ++ ++ if (trump_sco) { ++ /* this should reduce eSCO agressive retransmit ++ * w/o breaking it ++ */ ++ ++ /* 1st save current */ ++ AP6210_DEBUG("Do new SCO/eSCO coex algo {save &" ++ "override}\n"); ++ if ((!dev_wlc_intvar_get_reg(dev, "btc_params", 50, &saved_reg50)) && ++ (!dev_wlc_intvar_get_reg(dev, "btc_params", 51, &saved_reg51)) && ++ (!dev_wlc_intvar_get_reg(dev, "btc_params", 64, &saved_reg64)) && ++ (!dev_wlc_intvar_get_reg(dev, "btc_params", 65, &saved_reg65)) && ++ (!dev_wlc_intvar_get_reg(dev, "btc_params", 71, &saved_reg71))) { ++ saved_status = TRUE; ++ AP6210_DEBUG("%s saved bt_params[50,51,64,65,71]:" ++ "0x%x 0x%x 0x%x 0x%x 0x%x\n", ++ __FUNCTION__, saved_reg50, saved_reg51, ++ saved_reg64, saved_reg65, saved_reg71); ++ } else { ++ AP6210_ERR(":%s: save btc_params failed\n", ++ __FUNCTION__); ++ saved_status = FALSE; ++ return -1; ++ } ++ ++ AP6210_DEBUG("override with [50,51,64,65,71]:" ++ "0x%x 0x%x 0x%x 0x%x 0x%x\n", ++ *(u32 *)(buf_reg50va_dhcp_on+4), ++ *(u32 *)(buf_reg51va_dhcp_on+4), ++ *(u32 *)(buf_reg64va_dhcp_on+4), ++ *(u32 *)(buf_reg65va_dhcp_on+4), ++ *(u32 *)(buf_reg71va_dhcp_on+4)); ++ ++ dev_wlc_bufvar_set(dev, "btc_params", ++ (char *)&buf_reg50va_dhcp_on[0], 8); ++ dev_wlc_bufvar_set(dev, "btc_params", ++ (char *)&buf_reg51va_dhcp_on[0], 8); ++ dev_wlc_bufvar_set(dev, "btc_params", ++ (char *)&buf_reg64va_dhcp_on[0], 8); ++ dev_wlc_bufvar_set(dev, "btc_params", ++ (char *)&buf_reg65va_dhcp_on[0], 8); ++ dev_wlc_bufvar_set(dev, "btc_params", ++ (char *)&buf_reg71va_dhcp_on[0], 8); ++ ++ saved_status = TRUE; ++ } else if (saved_status) { ++ /* restore previously saved bt params */ ++ AP6210_DEBUG("Do new SCO/eSCO coex algo {save &" ++ "override}\n"); ++ ++ regaddr = 50; ++ dev_wlc_intvar_set_reg(dev, "btc_params", ++ (char *)®addr, (char *)&saved_reg50); ++ regaddr = 51; ++ dev_wlc_intvar_set_reg(dev, "btc_params", ++ (char *)®addr, (char *)&saved_reg51); ++ regaddr = 64; ++ dev_wlc_intvar_set_reg(dev, "btc_params", ++ (char *)®addr, (char *)&saved_reg64); ++ regaddr = 65; ++ dev_wlc_intvar_set_reg(dev, "btc_params", ++ (char *)®addr, (char *)&saved_reg65); ++ regaddr = 71; ++ dev_wlc_intvar_set_reg(dev, "btc_params", ++ (char *)®addr, (char *)&saved_reg71); ++ ++ AP6210_DEBUG("restore bt_params[50,51,64,65,71]:" ++ "0x%x 0x%x 0x%x 0x%x 0x%x\n", ++ saved_reg50, saved_reg51, saved_reg64, ++ saved_reg65, saved_reg71); ++ ++ saved_status = FALSE; ++ } else { ++ AP6210_ERR(":%s att to restore not saved BTCOEX params\n", ++ __FUNCTION__); ++ return -1; ++ } ++ return 0; ++} ++#endif /* BT_DHCP_eSCO_FIX */ ++ ++static void ++wl_cfg80211_bt_setflag(struct net_device *dev, bool set) ++{ ++#if defined(BT_DHCP_USE_FLAGS) ++ char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 }; ++ char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00}; ++#endif ++ ++ ++#if defined(BT_DHCP_eSCO_FIX) ++ /* set = 1, save & turn on 0 - off & restore prev settings */ ++ set_btc_esco_params(dev, set); ++#endif ++ ++#if defined(BT_DHCP_USE_FLAGS) ++ AP6210_DEBUG("WI-FI priority boost via bt flags, set:%d\n", set); ++ if (set == TRUE) ++ /* Forcing bt_flag7 */ ++ dev_wlc_bufvar_set(dev, "btc_flags", ++ (char *)&buf_flag7_dhcp_on[0], ++ sizeof(buf_flag7_dhcp_on)); ++ else ++ /* Restoring default bt flag7 */ ++ dev_wlc_bufvar_set(dev, "btc_flags", ++ (char *)&buf_flag7_default[0], ++ sizeof(buf_flag7_default)); ++#endif ++} ++ ++static void wl_cfg80211_bt_timerfunc(ulong data) ++{ ++ struct btcoex_info *bt_local = (struct btcoex_info *)data; ++ AP6210_DEBUG("%s\n", __FUNCTION__); ++ bt_local->timer_on = 0; ++ schedule_work(&bt_local->work); ++} ++ ++static void wl_cfg80211_bt_handler(struct work_struct *work) ++{ ++ struct btcoex_info *btcx_inf; ++ ++ btcx_inf = container_of(work, struct btcoex_info, work); ++ ++ if (btcx_inf->timer_on) { ++ btcx_inf->timer_on = 0; ++ del_timer_sync(&btcx_inf->timer); ++ } ++ ++ switch (btcx_inf->bt_state) { ++ case BT_DHCP_START: ++ /* DHCP started ++ * provide OPPORTUNITY window to get DHCP address ++ */ ++ AP6210_DEBUG("%s bt_dhcp stm: started \n", ++ __FUNCTION__); ++ btcx_inf->bt_state = BT_DHCP_OPPR_WIN; ++ mod_timer(&btcx_inf->timer, ++ jiffies + msecs_to_jiffies(BT_DHCP_OPPR_WIN_TIME)); ++ btcx_inf->timer_on = 1; ++ break; ++ ++ case BT_DHCP_OPPR_WIN: ++ if (btcx_inf->dhcp_done) { ++ AP6210_DEBUG("%s DHCP Done before T1 expiration\n", ++ __FUNCTION__); ++ goto btc_coex_idle; ++ } ++ ++ /* DHCP is not over yet, start lowering BT priority ++ * enforce btc_params + flags if necessary ++ */ ++ AP6210_DEBUG("%s DHCP T1:%d expired\n", __FUNCTION__, ++ BT_DHCP_OPPR_WIN_TIME); ++ if (btcx_inf->dev) ++ wl_cfg80211_bt_setflag(btcx_inf->dev, TRUE); ++ btcx_inf->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT; ++ mod_timer(&btcx_inf->timer, ++ jiffies + msecs_to_jiffies(BT_DHCP_FLAG_FORCE_TIME)); ++ btcx_inf->timer_on = 1; ++ break; ++ ++ case BT_DHCP_FLAG_FORCE_TIMEOUT: ++ if (btcx_inf->dhcp_done) { ++ AP6210_DEBUG("%s DHCP Done before T2 expiration\n", ++ __FUNCTION__); ++ } else { ++ /* Noo dhcp during T1+T2, restore BT priority */ ++ AP6210_DEBUG("%s DHCP wait interval T2:%d" ++ "msec expired\n", __FUNCTION__, ++ BT_DHCP_FLAG_FORCE_TIME); ++ } ++ ++ /* Restoring default bt priority */ ++ if (btcx_inf->dev) ++ wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE); ++btc_coex_idle: ++ btcx_inf->bt_state = BT_DHCP_IDLE; ++ btcx_inf->timer_on = 0; ++ break; ++ ++ default: ++ AP6210_ERR("%s error g_status=%d !!!\n", __FUNCTION__, ++ btcx_inf->bt_state); ++ if (btcx_inf->dev) ++ wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE); ++ btcx_inf->bt_state = BT_DHCP_IDLE; ++ btcx_inf->timer_on = 0; ++ break; ++ } ++ ++ net_os_wake_unlock(btcx_inf->dev); ++} ++ ++int wl_cfg80211_btcoex_init(struct wl_priv *wl) ++{ ++ struct btcoex_info *btco_inf = NULL; ++ ++ btco_inf = kmalloc(sizeof(struct btcoex_info), GFP_KERNEL); ++ if (!btco_inf) ++ return -ENOMEM; ++ ++ btco_inf->bt_state = BT_DHCP_IDLE; ++ btco_inf->ts_dhcp_start = 0; ++ btco_inf->ts_dhcp_ok = 0; ++ /* Set up timer for BT */ ++ btco_inf->timer_ms = 10; ++ init_timer(&btco_inf->timer); ++ btco_inf->timer.data = (ulong)btco_inf; ++ btco_inf->timer.function = wl_cfg80211_bt_timerfunc; ++ ++ btco_inf->dev = wl->wdev->netdev; ++ ++ INIT_WORK(&btco_inf->work, wl_cfg80211_bt_handler); ++ ++ wl->btcoex_info = btco_inf; ++ return 0; ++} ++ ++void wl_cfg80211_btcoex_deinit(struct wl_priv *wl) ++{ ++ if (!wl->btcoex_info) ++ return; ++ ++ if (wl->btcoex_info->timer_on) { ++ wl->btcoex_info->timer_on = 0; ++ del_timer_sync(&wl->btcoex_info->timer); ++ } ++ ++ cancel_work_sync(&wl->btcoex_info->work); ++ ++ kfree(wl->btcoex_info); ++ wl->btcoex_info = NULL; ++} ++#endif ++ ++int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) ++{ ++ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ char powermode_val = 0; ++ char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 }; ++ char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 }; ++ char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 }; ++ ++ uint32 regaddr; ++ static uint32 saved_reg66; ++ static uint32 saved_reg41; ++ static uint32 saved_reg68; ++ static bool saved_status = FALSE; ++ ++#ifdef COEX_DHCP ++ char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00}; ++ struct btcoex_info *btco_inf = wl->btcoex_info; ++#endif /* COEX_DHCP */ ++ ++#ifdef PKT_FILTER_SUPPORT ++ dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); ++#endif ++ ++ /* Figure out powermode 1 or o command */ ++ strncpy((char *)&powermode_val, command + strlen("BTCOEXMODE") +1, 1); ++ ++ if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) { ++ AP6210_DEBUG("%s: DHCP session starts\n", __FUNCTION__); ++ ++#if defined(DHCP_SCAN_SUPPRESS) ++ /* Suppress scan during the DHCP */ ++ wl_cfg80211_scan_suppress(dev, 1); ++#endif /* OEM_ANDROID */ ++ ++#ifdef PKT_FILTER_SUPPORT ++ dhd->dhcp_in_progress = 1; ++ ++ if (dhd->early_suspended) { ++ AP6210_DEBUG("DHCP in progressing , disable packet filter!!!\n"); ++ dhd_enable_packet_filter(0, dhd); ++ } ++#endif ++ ++ /* Retrieve and saved orig regs value */ ++ if ((saved_status == FALSE) && ++ (!dev_wlc_intvar_get_reg(dev, "btc_params", 66, &saved_reg66)) && ++ (!dev_wlc_intvar_get_reg(dev, "btc_params", 41, &saved_reg41)) && ++ (!dev_wlc_intvar_get_reg(dev, "btc_params", 68, &saved_reg68))) { ++ saved_status = TRUE; ++ AP6210_DEBUG("Saved 0x%x 0x%x 0x%x\n", ++ saved_reg66, saved_reg41, saved_reg68); ++ ++ /* Disable PM mode during dhpc session */ ++ ++ /* Disable PM mode during dhpc session */ ++#ifdef COEX_DHCP ++ /* Start BT timer only for SCO connection */ ++ if (btcoex_is_sco_active(dev)) { ++ /* btc_params 66 */ ++ dev_wlc_bufvar_set(dev, "btc_params", ++ (char *)&buf_reg66va_dhcp_on[0], ++ sizeof(buf_reg66va_dhcp_on)); ++ /* btc_params 41 0x33 */ ++ dev_wlc_bufvar_set(dev, "btc_params", ++ (char *)&buf_reg41va_dhcp_on[0], ++ sizeof(buf_reg41va_dhcp_on)); ++ /* btc_params 68 0x190 */ ++ dev_wlc_bufvar_set(dev, "btc_params", ++ (char *)&buf_reg68va_dhcp_on[0], ++ sizeof(buf_reg68va_dhcp_on)); ++ saved_status = TRUE; ++ ++ btco_inf->bt_state = BT_DHCP_START; ++ btco_inf->timer_on = 1; ++ mod_timer(&btco_inf->timer, btco_inf->timer.expires); ++ AP6210_DEBUG("%s enable BT DHCP Timer\n", ++ __FUNCTION__); ++ } ++#endif /* COEX_DHCP */ ++ } ++ else if (saved_status == TRUE) { ++ AP6210_ERR("%s was called w/o DHCP OFF. Continue\n", __FUNCTION__); ++ } ++ } ++ else if (strnicmp((char *)&powermode_val, "2", strlen("2")) == 0) { ++ ++ ++#ifdef PKT_FILTER_SUPPORT ++ dhd->dhcp_in_progress = 0; ++ AP6210_DEBUG("%s: DHCP is complete \n", __FUNCTION__); ++ ++#if defined(DHCP_SCAN_SUPPRESS) ++ /* Since DHCP is complete, enable the scan back */ ++ wl_cfg80211_scan_suppress(dev, 0); ++#endif /* OEM_ANDROID */ ++ ++ /* Enable packet filtering */ ++ if (dhd->early_suspended) { ++ AP6210_DEBUG("DHCP is complete , enable packet filter!!!\n"); ++ dhd_enable_packet_filter(1, dhd); ++ } ++#endif /* PKT_FILTER_SUPPORT */ ++ ++ /* Restoring PM mode */ ++ ++#ifdef COEX_DHCP ++ /* Stop any bt timer because DHCP session is done */ ++ AP6210_DEBUG("%s disable BT DHCP Timer\n", __FUNCTION__); ++ if (btco_inf->timer_on) { ++ btco_inf->timer_on = 0; ++ del_timer_sync(&btco_inf->timer); ++ ++ if (btco_inf->bt_state != BT_DHCP_IDLE) { ++ /* need to restore original btc flags & extra btc params */ ++ AP6210_DEBUG("%s bt->bt_state:%d\n", ++ __FUNCTION__, btco_inf->bt_state); ++ /* wake up btcoex thread to restore btlags+params */ ++ schedule_work(&btco_inf->work); ++ } ++ } ++ ++ /* Restoring btc_flag paramter anyway */ ++ if (saved_status == TRUE) ++ dev_wlc_bufvar_set(dev, "btc_flags", ++ (char *)&buf_flag7_default[0], sizeof(buf_flag7_default)); ++#endif /* COEX_DHCP */ ++ ++ /* Restore original values */ ++ if (saved_status == TRUE) { ++ regaddr = 66; ++ dev_wlc_intvar_set_reg(dev, "btc_params", ++ (char *)®addr, (char *)&saved_reg66); ++ regaddr = 41; ++ dev_wlc_intvar_set_reg(dev, "btc_params", ++ (char *)®addr, (char *)&saved_reg41); ++ regaddr = 68; ++ dev_wlc_intvar_set_reg(dev, "btc_params", ++ (char *)®addr, (char *)&saved_reg68); ++ ++ AP6210_DEBUG("restore regs {66,41,68} <- 0x%x 0x%x 0x%x\n", ++ saved_reg66, saved_reg41, saved_reg68); ++ } ++ saved_status = FALSE; ++ ++ } ++ else { ++ AP6210_ERR("%s Unkwown yet power setting, ignored\n", ++ __FUNCTION__); ++ } ++ ++ snprintf(command, 3, "OK"); ++ ++ return (strlen("OK")); ++} +diff --git a/drivers/net/wireless/ap6210/dhd_cfg80211.h b/drivers/net/wireless/ap6210/dhd_cfg80211.h +new file mode 100755 +index 0000000..922d6ed +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_cfg80211.h +@@ -0,0 +1,44 @@ ++/* ++ * Linux cfg80211 driver - Dongle Host Driver (DHD) related ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: wl_cfg80211.c,v 1.1.4.1.2.14 2011/02/09 01:40:07 Exp $ ++ */ ++ ++ ++#ifndef __DHD_CFG80211__ ++#define __DHD_CFG80211__ ++ ++#include ++#include ++ ++s32 dhd_cfg80211_init(struct wl_priv *wl); ++s32 dhd_cfg80211_deinit(struct wl_priv *wl); ++s32 dhd_cfg80211_down(struct wl_priv *wl); ++s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val); ++s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl); ++s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock); ++ ++int wl_cfg80211_btcoex_init(struct wl_priv *wl); ++void wl_cfg80211_btcoex_deinit(struct wl_priv *wl); ++ ++#endif /* __DHD_CFG80211__ */ +diff --git a/drivers/net/wireless/ap6210/dhd_common.c b/drivers/net/wireless/ap6210/dhd_common.c +new file mode 100755 +index 0000000..96c021f +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_common.c +@@ -0,0 +1,2255 @@ ++/* ++ * Broadcom Dongle Host Driver (DHD), common DHD core. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhd_common.c 373873 2012-12-10 20:45:58Z $ ++ */ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#ifdef WL_CFG80211 ++#include ++#endif ++#ifdef WLBTAMP ++#include ++#include ++#endif ++#ifdef SET_RANDOM_MAC_SOFTAP ++#include ++#include ++#endif ++ ++#define htod32(i) i ++#define htod16(i) i ++#define dtoh32(i) i ++#define dtoh16(i) i ++#define htodchanspec(i) i ++#define dtohchanspec(i) i ++ ++#ifdef PROP_TXSTATUS ++#include ++#include ++#endif ++ ++#include ++#include ++ ++#ifdef WLMEDIA_HTSF ++extern void htsf_update(struct dhd_info *dhd, void *data); ++#endif ++int dhd_msg_level = DHD_ERROR_VAL; ++ ++ ++#include ++ ++char fw_path[MOD_PARAM_PATHLEN]; ++char nv_path[MOD_PARAM_PATHLEN]; ++ ++#ifdef SOFTAP ++char fw_path2[MOD_PARAM_PATHLEN]; ++extern bool softap_enabled; ++#endif ++ ++/* Last connection success/failure status */ ++uint32 dhd_conn_event; ++uint32 dhd_conn_status; ++uint32 dhd_conn_reason; ++ ++extern int dhd_iscan_request(void * dhdp, uint16 action); ++extern void dhd_ind_scan_confirm(void *h, bool status); ++extern int dhd_iscan_in_progress(void *h); ++void dhd_iscan_lock(void); ++void dhd_iscan_unlock(void); ++extern int dhd_change_mtu(dhd_pub_t *dhd, int new_mtu, int ifidx); ++#if !defined(AP) && defined(WLP2P) ++extern int dhd_get_concurrent_capabilites(dhd_pub_t *dhd); ++#endif ++bool ap_cfg_running = FALSE; ++bool ap_fw_loaded = FALSE; ++ ++ ++#ifdef DHD_DEBUG ++const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR "\nCompiled on " ++ __DATE__ " at " __TIME__; ++#else ++const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR; ++#endif ++ ++void dhd_set_timer(void *bus, uint wdtick); ++ ++/* IOVar table */ ++enum { ++ IOV_VERSION = 1, ++ IOV_WLMSGLEVEL, ++ IOV_MSGLEVEL, ++ IOV_BCMERRORSTR, ++ IOV_BCMERROR, ++ IOV_WDTICK, ++ IOV_DUMP, ++ IOV_CLEARCOUNTS, ++ IOV_LOGDUMP, ++ IOV_LOGCAL, ++ IOV_LOGSTAMP, ++ IOV_GPIOOB, ++ IOV_IOCTLTIMEOUT, ++#ifdef WLBTAMP ++ IOV_HCI_CMD, /* HCI command */ ++ IOV_HCI_ACL_DATA, /* HCI data packet */ ++#endif ++#if defined(DHD_DEBUG) ++ IOV_CONS, ++ IOV_DCONSOLE_POLL, ++#endif /* defined(DHD_DEBUG) */ ++#ifdef PROP_TXSTATUS ++ IOV_PROPTXSTATUS_ENABLE, ++ IOV_PROPTXSTATUS_MODE, ++#endif ++ IOV_BUS_TYPE, ++#ifdef WLMEDIA_HTSF ++ IOV_WLPKTDLYSTAT_SZ, ++#endif ++ IOV_CHANGEMTU, ++ IOV_HOSTREORDER_FLOWS, ++ IOV_LAST ++}; ++ ++const bcm_iovar_t dhd_iovars[] = { ++ {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(dhd_version) }, ++ {"wlmsglevel", IOV_WLMSGLEVEL, 0, IOVT_UINT32, 0 }, ++#ifdef DHD_DEBUG ++ {"msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 }, ++#endif /* DHD_DEBUG */ ++ {"bcmerrorstr", IOV_BCMERRORSTR, 0, IOVT_BUFFER, BCME_STRLEN }, ++ {"bcmerror", IOV_BCMERROR, 0, IOVT_INT8, 0 }, ++ {"wdtick", IOV_WDTICK, 0, IOVT_UINT32, 0 }, ++ {"dump", IOV_DUMP, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN }, ++#ifdef DHD_DEBUG ++ {"cons", IOV_CONS, 0, IOVT_BUFFER, 0 }, ++ {"dconpoll", IOV_DCONSOLE_POLL, 0, IOVT_UINT32, 0 }, ++#endif ++ {"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID, 0 }, ++ {"gpioob", IOV_GPIOOB, 0, IOVT_UINT32, 0 }, ++ {"ioctl_timeout", IOV_IOCTLTIMEOUT, 0, IOVT_UINT32, 0 }, ++#ifdef WLBTAMP ++ {"HCI_cmd", IOV_HCI_CMD, 0, IOVT_BUFFER, 0}, ++ {"HCI_ACL_data", IOV_HCI_ACL_DATA, 0, IOVT_BUFFER, 0}, ++#endif ++#ifdef PROP_TXSTATUS ++ {"proptx", IOV_PROPTXSTATUS_ENABLE, 0, IOVT_UINT32, 0 }, ++ /* ++ set the proptxtstatus operation mode: ++ 0 - Do not do any proptxtstatus flow control ++ 1 - Use implied credit from a packet status ++ 2 - Use explicit credit ++ */ ++ {"ptxmode", IOV_PROPTXSTATUS_MODE, 0, IOVT_UINT32, 0 }, ++#endif ++ {"bustype", IOV_BUS_TYPE, 0, IOVT_UINT32, 0}, ++#ifdef WLMEDIA_HTSF ++ {"pktdlystatsz", IOV_WLPKTDLYSTAT_SZ, 0, IOVT_UINT8, 0 }, ++#endif ++ {"changemtu", IOV_CHANGEMTU, 0, IOVT_UINT32, 0 }, ++ {"host_reorder_flows", IOV_HOSTREORDER_FLOWS, 0, IOVT_BUFFER, ++ (WLHOST_REORDERDATA_MAXFLOWS + 1) }, ++ {NULL, 0, 0, 0, 0 } ++}; ++ ++void ++dhd_common_init(osl_t *osh) ++{ ++ int select_type = 0; ++ //aw checkout which wifi had select ++ select_type = ap6210_gpio_wifi_get_mod_type(); ++ ++#ifdef CONFIG_AP6210_FW_PATH ++ //select bcm40181/ap6181/ap6210 ++ if (select_type == 1 || select_type == 7 || select_type == 9) { ++ bcm_strncpy_s(fw_path, sizeof(fw_path), "/lib/firmware/ap6210/fw_bcm40181a2.bin", MOD_PARAM_PATHLEN-1); ++ } ++ //select bcm40183 ++ if (select_type == 2) { ++ bcm_strncpy_s(fw_path, sizeof(fw_path), "/lib/firmware/ap6210/fw_bcm40183b2.bin", MOD_PARAM_PATHLEN-1); ++ } ++ //select ap6330 ++ if (select_type == 8) { ++ bcm_strncpy_s(fw_path, sizeof(fw_path), "/lib/firmware/ap6210/fw_bcm40183b2_ag.bin", MOD_PARAM_PATHLEN-1); ++ } ++ ++#else /* CONFIG_AP6210_FW_PATH */ ++ fw_path[0] = '\0'; ++#endif /* CONFIG_AP6210_FW_PATH */ ++#ifdef CONFIG_AP6210_NVRAM_PATH ++ //select bcm40181 ++ if (select_type == 1) { ++ bcm_strncpy_s(nv_path, sizeof(nv_path), "/lib/firmware/ap6210/nvram_bcm40181.txt", MOD_PARAM_PATHLEN-1); ++ } ++ //select bcm40183 ++ if (select_type == 2) { ++ bcm_strncpy_s(nv_path, sizeof(nv_path), "/lib/firmware/ap6210/nvram_bcm40183.txt", MOD_PARAM_PATHLEN-1); ++ } ++ //select ap6210 ++ if (select_type == 7) { ++ bcm_strncpy_s(nv_path, sizeof(nv_path), "/lib/firmware/ap6210/nvram_ap6210.txt", MOD_PARAM_PATHLEN-1); ++ } ++ ++ //select ap6330 ++ if (select_type == 8) { ++ bcm_strncpy_s(nv_path, sizeof(nv_path), "/lib/firmware/ap6210/nvram_ap6330.txt", MOD_PARAM_PATHLEN-1); ++ } ++ //select ap6181 ++ if (select_type == 9) { ++ bcm_strncpy_s(nv_path, sizeof(nv_path), "/lib/firmware/ap6210/nvram_ap6181.txt", MOD_PARAM_PATHLEN-1); ++ } ++#else /* CONFIG_AP6210_NVRAM_PATH */ ++ nv_path[0] = '\0'; ++#endif /* CONFIG_AP6210_NVRAM_PATH */ ++#ifdef SOFTAP ++ fw_path2[0] = '\0'; ++#endif ++} ++ ++static int ++dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen) ++{ ++ char eabuf[ETHER_ADDR_STR_LEN]; ++ ++ struct bcmstrbuf b; ++ struct bcmstrbuf *strbuf = &b; ++ ++ bcm_binit(strbuf, buf, buflen); ++ ++ /* Base DHD info */ ++ bcm_bprintf(strbuf, "%s\n", dhd_version); ++ bcm_bprintf(strbuf, "\n"); ++ bcm_bprintf(strbuf, "pub.up %d pub.txoff %d pub.busstate %d\n", ++ dhdp->up, dhdp->txoff, dhdp->busstate); ++ bcm_bprintf(strbuf, "pub.hdrlen %d pub.maxctl %d pub.rxsz %d\n", ++ dhdp->hdrlen, dhdp->maxctl, dhdp->rxsz); ++ bcm_bprintf(strbuf, "pub.iswl %d pub.drv_version %ld pub.mac %s\n", ++ dhdp->iswl, dhdp->drv_version, bcm_ether_ntoa(&dhdp->mac, eabuf)); ++ bcm_bprintf(strbuf, "pub.bcmerror %d tickcnt %d\n", dhdp->bcmerror, dhdp->tickcnt); ++ ++ bcm_bprintf(strbuf, "dongle stats:\n"); ++ bcm_bprintf(strbuf, "tx_packets %ld tx_bytes %ld tx_errors %ld tx_dropped %ld\n", ++ dhdp->dstats.tx_packets, dhdp->dstats.tx_bytes, ++ dhdp->dstats.tx_errors, dhdp->dstats.tx_dropped); ++ bcm_bprintf(strbuf, "rx_packets %ld rx_bytes %ld rx_errors %ld rx_dropped %ld\n", ++ dhdp->dstats.rx_packets, dhdp->dstats.rx_bytes, ++ dhdp->dstats.rx_errors, dhdp->dstats.rx_dropped); ++ bcm_bprintf(strbuf, "multicast %ld\n", dhdp->dstats.multicast); ++ ++ bcm_bprintf(strbuf, "bus stats:\n"); ++ bcm_bprintf(strbuf, "tx_packets %ld tx_multicast %ld tx_errors %ld\n", ++ dhdp->tx_packets, dhdp->tx_multicast, dhdp->tx_errors); ++ bcm_bprintf(strbuf, "tx_ctlpkts %ld tx_ctlerrs %ld\n", ++ dhdp->tx_ctlpkts, dhdp->tx_ctlerrs); ++ bcm_bprintf(strbuf, "rx_packets %ld rx_multicast %ld rx_errors %ld \n", ++ dhdp->rx_packets, dhdp->rx_multicast, dhdp->rx_errors); ++ bcm_bprintf(strbuf, "rx_ctlpkts %ld rx_ctlerrs %ld rx_dropped %ld\n", ++ dhdp->rx_ctlpkts, dhdp->rx_ctlerrs, dhdp->rx_dropped); ++ bcm_bprintf(strbuf, "rx_readahead_cnt %ld tx_realloc %ld\n", ++ dhdp->rx_readahead_cnt, dhdp->tx_realloc); ++ bcm_bprintf(strbuf, "\n"); ++ ++ /* Add any prot info */ ++ dhd_prot_dump(dhdp, strbuf); ++ bcm_bprintf(strbuf, "\n"); ++ ++ /* Add any bus info */ ++ dhd_bus_dump(dhdp, strbuf); ++ ++ return (!strbuf->size ? BCME_BUFTOOSHORT : 0); ++} ++ ++int ++dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uint8 set, int ifindex) ++{ ++ wl_ioctl_t ioc; ++ ++ ioc.cmd = cmd; ++ ioc.buf = arg; ++ ioc.len = len; ++ ioc.set = set; ++ ++ return dhd_wl_ioctl(dhd_pub, ifindex, &ioc, arg, len); ++} ++ ++ ++int ++dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int len) ++{ ++ int ret; ++ ++ dhd_os_proto_block(dhd_pub); ++ ++ ret = dhd_prot_ioctl(dhd_pub, ifindex, ioc, buf, len); ++ if ((ret) && (dhd_pub->up)) ++ /* Send hang event only if dhd_open() was success */ ++ dhd_os_check_hang(dhd_pub, ifindex, ret); ++ ++ dhd_os_proto_unblock(dhd_pub); ++ ++ return ret; ++} ++ ++static int ++dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const char *name, ++ void *params, int plen, void *arg, int len, int val_size) ++{ ++ int bcmerror = 0; ++ int32 int_val = 0; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ AP6210_DEBUG("%s: actionid = %d; name %s\n", __FUNCTION__, actionid, name); ++ ++ if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0) ++ goto exit; ++ ++ if (plen >= (int)sizeof(int_val)) ++ bcopy(params, &int_val, sizeof(int_val)); ++ ++ switch (actionid) { ++ case IOV_GVAL(IOV_VERSION): ++ /* Need to have checked buffer length */ ++ bcm_strncpy_s((char*)arg, len, dhd_version, len); ++ break; ++ ++ case IOV_GVAL(IOV_WLMSGLEVEL): ++ //AP6210_DEBUG("android_msg_level=0x%x\n", android_msg_level); ++#if defined(CONFIG_WIRELESS_EXT) ++ int_val = (int32)iw_msg_level; ++ bcopy(&int_val, arg, val_size); ++ AP6210_DEBUG("iw_msg_level=0x%x\n", iw_msg_level); ++#endif ++#ifdef WL_CFG80211 ++ int_val = (int32)wl_dbg_level; ++ bcopy(&int_val, arg, val_size); ++ AP6210_DEBUG("cfg_msg_level=0x%x\n", wl_dbg_level); ++#endif ++ break; ++ ++ case IOV_SVAL(IOV_WLMSGLEVEL): ++#if defined(CONFIG_WIRELESS_EXT) ++ if (int_val & DHD_IW_VAL) { ++ iw_msg_level = (uint)(int_val & 0xFFFF); ++ AP6210_DEBUG("iw_msg_level=0x%x\n", iw_msg_level); ++ } else ++#endif ++#ifdef WL_CFG80211 ++ if (int_val & DHD_CFG_VAL) { ++ wl_cfg80211_enable_trace((u32)(int_val & 0xFFFF)); ++ } else ++#endif ++ { ++ //android_msg_level = (uint)int_val; ++ //AP6210_DEBUG("android_msg_level=0x%x\n", android_msg_level); ++ } ++ break; ++ ++ case IOV_GVAL(IOV_MSGLEVEL): ++ int_val = (int32)dhd_msg_level; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_MSGLEVEL): ++ dhd_msg_level = int_val; ++ break; ++ ++ case IOV_GVAL(IOV_BCMERRORSTR): ++ bcm_strncpy_s((char *)arg, len, bcmerrorstr(dhd_pub->bcmerror), BCME_STRLEN); ++ ((char *)arg)[BCME_STRLEN - 1] = 0x00; ++ break; ++ ++ case IOV_GVAL(IOV_BCMERROR): ++ int_val = (int32)dhd_pub->bcmerror; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_GVAL(IOV_WDTICK): ++ int_val = (int32)dhd_watchdog_ms; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_WDTICK): ++ if (!dhd_pub->up) { ++ bcmerror = BCME_NOTUP; ++ break; ++ } ++ dhd_os_wd_timer(dhd_pub, (uint)int_val); ++ break; ++ ++ case IOV_GVAL(IOV_DUMP): ++ bcmerror = dhd_dump(dhd_pub, arg, len); ++ break; ++ ++#ifdef DHD_DEBUG ++ case IOV_GVAL(IOV_DCONSOLE_POLL): ++ int_val = (int32)dhd_console_ms; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_DCONSOLE_POLL): ++ dhd_console_ms = (uint)int_val; ++ break; ++ ++ case IOV_SVAL(IOV_CONS): ++ if (len > 0) ++ bcmerror = dhd_bus_console_in(dhd_pub, arg, len - 1); ++ break; ++#endif /* DHD_DEBUG */ ++ ++ case IOV_SVAL(IOV_CLEARCOUNTS): ++ dhd_pub->tx_packets = dhd_pub->rx_packets = 0; ++ dhd_pub->tx_errors = dhd_pub->rx_errors = 0; ++ dhd_pub->tx_ctlpkts = dhd_pub->rx_ctlpkts = 0; ++ dhd_pub->tx_ctlerrs = dhd_pub->rx_ctlerrs = 0; ++ dhd_pub->rx_dropped = 0; ++ dhd_pub->rx_readahead_cnt = 0; ++ dhd_pub->tx_realloc = 0; ++ dhd_pub->wd_dpc_sched = 0; ++ memset(&dhd_pub->dstats, 0, sizeof(dhd_pub->dstats)); ++ dhd_bus_clearcounts(dhd_pub); ++#ifdef PROP_TXSTATUS ++ /* clear proptxstatus related counters */ ++ if (dhd_pub->wlfc_state) { ++ athost_wl_status_info_t *wlfc = ++ (athost_wl_status_info_t*)dhd_pub->wlfc_state; ++ wlfc_hanger_t* hanger; ++ ++ memset(&wlfc->stats, 0, sizeof(athost_wl_stat_counters_t)); ++ ++ hanger = (wlfc_hanger_t*)wlfc->hanger; ++ hanger->pushed = 0; ++ hanger->popped = 0; ++ hanger->failed_slotfind = 0; ++ hanger->failed_to_pop = 0; ++ hanger->failed_to_push = 0; ++ } ++#endif /* PROP_TXSTATUS */ ++ break; ++ ++ ++ case IOV_GVAL(IOV_IOCTLTIMEOUT): { ++ int_val = (int32)dhd_os_get_ioctl_resp_timeout(); ++ bcopy(&int_val, arg, sizeof(int_val)); ++ break; ++ } ++ ++ case IOV_SVAL(IOV_IOCTLTIMEOUT): { ++ if (int_val <= 0) ++ bcmerror = BCME_BADARG; ++ else ++ dhd_os_set_ioctl_resp_timeout((unsigned int)int_val); ++ break; ++ } ++ ++#ifdef WLBTAMP ++ case IOV_SVAL(IOV_HCI_CMD): { ++ amp_hci_cmd_t *cmd = (amp_hci_cmd_t *)arg; ++ ++ /* sanity check: command preamble present */ ++ if (len < HCI_CMD_PREAMBLE_SIZE) ++ return BCME_BUFTOOSHORT; ++ ++ /* sanity check: command parameters are present */ ++ if (len < (int)(HCI_CMD_PREAMBLE_SIZE + cmd->plen)) ++ return BCME_BUFTOOSHORT; ++ ++ dhd_bta_docmd(dhd_pub, cmd, len); ++ break; ++ } ++ ++ case IOV_SVAL(IOV_HCI_ACL_DATA): { ++ amp_hci_ACL_data_t *ACL_data = (amp_hci_ACL_data_t *)arg; ++ ++ /* sanity check: HCI header present */ ++ if (len < HCI_ACL_DATA_PREAMBLE_SIZE) ++ return BCME_BUFTOOSHORT; ++ ++ /* sanity check: ACL data is present */ ++ if (len < (int)(HCI_ACL_DATA_PREAMBLE_SIZE + ACL_data->dlen)) ++ return BCME_BUFTOOSHORT; ++ ++ dhd_bta_tx_hcidata(dhd_pub, ACL_data, len); ++ break; ++ } ++#endif /* WLBTAMP */ ++ ++#ifdef PROP_TXSTATUS ++ case IOV_GVAL(IOV_PROPTXSTATUS_ENABLE): ++ int_val = dhd_pub->wlfc_enabled? 1 : 0; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_PROPTXSTATUS_ENABLE): ++ dhd_pub->wlfc_enabled = int_val? 1 : 0; ++ break; ++ ++ case IOV_GVAL(IOV_PROPTXSTATUS_MODE): { ++ athost_wl_status_info_t *wlfc = ++ (athost_wl_status_info_t*)dhd_pub->wlfc_state; ++ int_val = dhd_pub->wlfc_state ? (int32)wlfc->proptxstatus_mode : 0; ++ bcopy(&int_val, arg, val_size); ++ break; ++ } ++ ++ case IOV_SVAL(IOV_PROPTXSTATUS_MODE): ++ if (dhd_pub->wlfc_state) { ++ athost_wl_status_info_t *wlfc = ++ (athost_wl_status_info_t*)dhd_pub->wlfc_state; ++ wlfc->proptxstatus_mode = int_val & 0xff; ++ } ++ break; ++#endif /* PROP_TXSTATUS */ ++ ++ case IOV_GVAL(IOV_BUS_TYPE): ++ /* The dhd application queries the driver to check if its usb or sdio. */ ++#ifdef AP6210USB ++ int_val = BUS_TYPE_USB; ++#endif ++ int_val = BUS_TYPE_SDIO; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ ++#ifdef WLMEDIA_HTSF ++ case IOV_GVAL(IOV_WLPKTDLYSTAT_SZ): ++ int_val = dhd_pub->htsfdlystat_sz; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_WLPKTDLYSTAT_SZ): ++ dhd_pub->htsfdlystat_sz = int_val & 0xff; ++ AP6210_DEBUG("Setting tsfdlystat_sz:%d\n", dhd_pub->htsfdlystat_sz); ++ break; ++#endif ++ case IOV_SVAL(IOV_CHANGEMTU): ++ int_val &= 0xffff; ++ bcmerror = dhd_change_mtu(dhd_pub, int_val, 0); ++ break; ++ ++ case IOV_GVAL(IOV_HOSTREORDER_FLOWS): ++ { ++ uint i = 0; ++ uint8 *ptr = (uint8 *)arg; ++ uint8 count = 0; ++ ++ ptr++; ++ for (i = 0; i < WLHOST_REORDERDATA_MAXFLOWS; i++) { ++ if (dhd_pub->reorder_bufs[i] != NULL) { ++ *ptr = dhd_pub->reorder_bufs[i]->flow_id; ++ ptr++; ++ count++; ++ } ++ } ++ ptr = (uint8 *)arg; ++ *ptr = count; ++ break; ++ } ++ ++ default: ++ bcmerror = BCME_UNSUPPORTED; ++ break; ++ } ++ ++exit: ++ AP6210_DEBUG("%s: actionid %d, bcmerror %d\n", __FUNCTION__, actionid, bcmerror); ++ return bcmerror; ++} ++ ++/* Store the status of a connection attempt for later retrieval by an iovar */ ++void ++dhd_store_conn_status(uint32 event, uint32 status, uint32 reason) ++{ ++ /* Do not overwrite a WLC_E_PRUNE with a WLC_E_SET_SSID ++ * because an encryption/rsn mismatch results in both events, and ++ * the important information is in the WLC_E_PRUNE. ++ */ ++ if (!(event == WLC_E_SET_SSID && status == WLC_E_STATUS_FAIL && ++ dhd_conn_event == WLC_E_PRUNE)) { ++ dhd_conn_event = event; ++ dhd_conn_status = status; ++ dhd_conn_reason = reason; ++ } ++} ++ ++bool ++dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec) ++{ ++ void *p; ++ int eprec = -1; /* precedence to evict from */ ++ bool discard_oldest; ++ ++ /* Fast case, precedence queue is not full and we are also not ++ * exceeding total queue length ++ */ ++ if (!pktq_pfull(q, prec) && !pktq_full(q)) { ++ pktq_penq(q, prec, pkt); ++ return TRUE; ++ } ++ ++ /* Determine precedence from which to evict packet, if any */ ++ if (pktq_pfull(q, prec)) ++ eprec = prec; ++ else if (pktq_full(q)) { ++ pktq_peek_tail(q, &eprec); ++ if (eprec > prec || eprec < 0) ++ return FALSE; ++ } ++ ++ /* Evict if needed */ ++ if (eprec >= 0) { ++ /* Detect queueing to unconfigured precedence */ ++ ASSERT(!pktq_pempty(q, eprec)); ++ discard_oldest = AC_BITMAP_TST(dhdp->wme_dp, eprec); ++ if (eprec == prec && !discard_oldest) ++ return FALSE; /* refuse newer (incoming) packet */ ++ /* Evict packet according to discard policy */ ++ p = discard_oldest ? pktq_pdeq(q, eprec) : pktq_pdeq_tail(q, eprec); ++ ASSERT(p); ++ ++ PKTFREE(dhdp->osh, p, TRUE); ++ } ++ ++ /* Enqueue */ ++ pktq_penq(q, prec, pkt); ++ ++ return TRUE; ++} ++ ++static int ++dhd_iovar_op(dhd_pub_t *dhd_pub, const char *name, ++ void *params, int plen, void *arg, int len, bool set) ++{ ++ int bcmerror = 0; ++ int val_size; ++ const bcm_iovar_t *vi = NULL; ++ uint32 actionid; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ ASSERT(name); ++ ASSERT(len >= 0); ++ ++ /* Get MUST have return space */ ++ ASSERT(set || (arg && len)); ++ ++ /* Set does NOT take qualifiers */ ++ ASSERT(!set || (!params && !plen)); ++ ++ if ((vi = bcm_iovar_lookup(dhd_iovars, name)) == NULL) { ++ bcmerror = BCME_UNSUPPORTED; ++ goto exit; ++ } ++ ++ AP6210_DEBUG("%s: %s %s, len %d plen %d\n", __FUNCTION__, ++ name, (set ? "set" : "get"), len, plen); ++ ++ /* set up 'params' pointer in case this is a set command so that ++ * the convenience int and bool code can be common to set and get ++ */ ++ if (params == NULL) { ++ params = arg; ++ plen = len; ++ } ++ ++ if (vi->type == IOVT_VOID) ++ val_size = 0; ++ else if (vi->type == IOVT_BUFFER) ++ val_size = len; ++ else ++ /* all other types are integer sized */ ++ val_size = sizeof(int); ++ ++ actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); ++ ++ bcmerror = dhd_doiovar(dhd_pub, vi, actionid, name, params, plen, arg, len, val_size); ++ ++exit: ++ return bcmerror; ++} ++ ++int ++dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void * buf, uint buflen) ++{ ++ int bcmerror = 0; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (!buf) { ++ return BCME_BADARG; ++ } ++ ++ switch (ioc->cmd) { ++ case DHD_GET_MAGIC: ++ if (buflen < sizeof(int)) ++ bcmerror = BCME_BUFTOOSHORT; ++ else ++ *(int*)buf = DHD_IOCTL_MAGIC; ++ break; ++ ++ case DHD_GET_VERSION: ++ if (buflen < sizeof(int)) ++ bcmerror = -BCME_BUFTOOSHORT; ++ else ++ *(int*)buf = DHD_IOCTL_VERSION; ++ break; ++ ++ case DHD_GET_VAR: ++ case DHD_SET_VAR: { ++ char *arg; ++ uint arglen; ++ ++ /* scan past the name to any arguments */ ++ for (arg = buf, arglen = buflen; *arg && arglen; arg++, arglen--) ++ ; ++ ++ if (*arg) { ++ bcmerror = BCME_BUFTOOSHORT; ++ break; ++ } ++ ++ /* account for the NUL terminator */ ++ arg++, arglen--; ++ ++ /* call with the appropriate arguments */ ++ if (ioc->cmd == DHD_GET_VAR) ++ bcmerror = dhd_iovar_op(dhd_pub, buf, arg, arglen, ++ buf, buflen, IOV_GET); ++ else ++ bcmerror = dhd_iovar_op(dhd_pub, buf, NULL, 0, arg, arglen, IOV_SET); ++ if (bcmerror != BCME_UNSUPPORTED) ++ break; ++ ++ /* not in generic table, try protocol module */ ++ if (ioc->cmd == DHD_GET_VAR) ++ bcmerror = dhd_prot_iovar_op(dhd_pub, buf, arg, ++ arglen, buf, buflen, IOV_GET); ++ else ++ bcmerror = dhd_prot_iovar_op(dhd_pub, buf, ++ NULL, 0, arg, arglen, IOV_SET); ++ if (bcmerror != BCME_UNSUPPORTED) ++ break; ++ ++ /* if still not found, try bus module */ ++ if (ioc->cmd == DHD_GET_VAR) { ++ bcmerror = dhd_bus_iovar_op(dhd_pub, buf, ++ arg, arglen, buf, buflen, IOV_GET); ++ } else { ++ bcmerror = dhd_bus_iovar_op(dhd_pub, buf, ++ NULL, 0, arg, arglen, IOV_SET); ++ } ++ ++ break; ++ } ++ ++ default: ++ bcmerror = BCME_UNSUPPORTED; ++ } ++ ++ return bcmerror; ++} ++ ++#ifdef SHOW_EVENTS ++static void ++wl_show_host_event(wl_event_msg_t *event, void *event_data) ++{ ++ uint i, status, reason; ++ bool group = FALSE, flush_txq = FALSE, link = FALSE; ++ const char *auth_str; ++ const char *event_name; ++ uchar *buf; ++ char err_msg[256], eabuf[ETHER_ADDR_STR_LEN]; ++ uint event_type, flags, auth_type, datalen; ++ ++ event_type = ntoh32(event->event_type); ++ flags = ntoh16(event->flags); ++ status = ntoh32(event->status); ++ reason = ntoh32(event->reason); ++ BCM_REFERENCE(reason); ++ auth_type = ntoh32(event->auth_type); ++ datalen = ntoh32(event->datalen); ++ ++ /* debug dump of event messages */ ++ snprintf(eabuf, sizeof(eabuf), "%02x:%02x:%02x:%02x:%02x:%02x", ++ (uchar)event->addr.octet[0]&0xff, ++ (uchar)event->addr.octet[1]&0xff, ++ (uchar)event->addr.octet[2]&0xff, ++ (uchar)event->addr.octet[3]&0xff, ++ (uchar)event->addr.octet[4]&0xff, ++ (uchar)event->addr.octet[5]&0xff); ++ ++ event_name = "UNKNOWN"; ++ for (i = 0; i < (uint)bcmevent_names_size; i++) ++ if (bcmevent_names[i].event == event_type) ++ event_name = bcmevent_names[i].name; ++ ++ if (flags & WLC_EVENT_MSG_LINK) ++ link = TRUE; ++ if (flags & WLC_EVENT_MSG_GROUP) ++ group = TRUE; ++ if (flags & WLC_EVENT_MSG_FLUSHTXQ) ++ flush_txq = TRUE; ++ ++ switch (event_type) { ++ case WLC_E_START: ++ case WLC_E_DEAUTH: ++ case WLC_E_DISASSOC: ++ AP6210_DEBUG("MACEVENT: %s, MAC %s\n", event_name, eabuf); ++ break; ++ ++ case WLC_E_ASSOC_IND: ++ case WLC_E_REASSOC_IND: ++ ++ AP6210_DEBUG("MACEVENT: %s, MAC %s\n", event_name, eabuf); ++ break; ++ ++ case WLC_E_ASSOC: ++ case WLC_E_REASSOC: ++ if (status == WLC_E_STATUS_SUCCESS) { ++ AP6210_DEBUG("MACEVENT: %s, MAC %s, SUCCESS\n", event_name, eabuf); ++ } else if (status == WLC_E_STATUS_TIMEOUT) { ++ AP6210_DEBUG("MACEVENT: %s, MAC %s, TIMEOUT\n", event_name, eabuf); ++ } else if (status == WLC_E_STATUS_FAIL) { ++ AP6210_DEBUG("MACEVENT: %s, MAC %s, FAILURE, reason %d\n", ++ event_name, eabuf, (int)reason); ++ } else { ++ AP6210_DEBUG("MACEVENT: %s, MAC %s, unexpected status %d\n", ++ event_name, eabuf, (int)status); ++ } ++ break; ++ ++ case WLC_E_DEAUTH_IND: ++ case WLC_E_DISASSOC_IND: ++ AP6210_DEBUG("MACEVENT: %s, MAC %s, reason %d\n", event_name, eabuf, (int)reason); ++ break; ++ ++ case WLC_E_AUTH: ++ case WLC_E_AUTH_IND: ++ if (auth_type == DOT11_OPEN_SYSTEM) ++ auth_str = "Open System"; ++ else if (auth_type == DOT11_SHARED_KEY) ++ auth_str = "Shared Key"; ++ else { ++ snprintf(err_msg, sizeof(err_msg), "AUTH unknown: %d", (int)auth_type); ++ auth_str = err_msg; ++ } ++ if (event_type == WLC_E_AUTH_IND) { ++ AP6210_DEBUG("MACEVENT: %s, MAC %s, %s\n", event_name, eabuf, auth_str); ++ } else if (status == WLC_E_STATUS_SUCCESS) { ++ AP6210_DEBUG("MACEVENT: %s, MAC %s, %s, SUCCESS\n", ++ event_name, eabuf, auth_str); ++ } else if (status == WLC_E_STATUS_TIMEOUT) { ++ AP6210_DEBUG("MACEVENT: %s, MAC %s, %s, TIMEOUT\n", ++ event_name, eabuf, auth_str); ++ } else if (status == WLC_E_STATUS_FAIL) { ++ AP6210_DEBUG("MACEVENT: %s, MAC %s, %s, FAILURE, reason %d\n", ++ event_name, eabuf, auth_str, (int)reason); ++ } ++ BCM_REFERENCE(auth_str); ++ ++ break; ++ ++ case WLC_E_JOIN: ++ case WLC_E_ROAM: ++ case WLC_E_SET_SSID: ++ if (status == WLC_E_STATUS_SUCCESS) { ++ AP6210_DEBUG("MACEVENT: %s, MAC %s\n", event_name, eabuf); ++ } else if (status == WLC_E_STATUS_FAIL) { ++ AP6210_DEBUG("MACEVENT: %s, failed\n", event_name); ++ } else if (status == WLC_E_STATUS_NO_NETWORKS) { ++ AP6210_DEBUG("MACEVENT: %s, no networks found\n", event_name); ++ } else { ++ AP6210_DEBUG("MACEVENT: %s, unexpected status %d\n", ++ event_name, (int)status); ++ } ++ break; ++ ++ case WLC_E_BEACON_RX: ++ if (status == WLC_E_STATUS_SUCCESS) { ++ AP6210_DEBUG("MACEVENT: %s, SUCCESS\n", event_name); ++ } else if (status == WLC_E_STATUS_FAIL) { ++ AP6210_DEBUG("MACEVENT: %s, FAIL\n", event_name); ++ } else { ++ AP6210_DEBUG("MACEVENT: %s, status %d\n", event_name, status); ++ } ++ break; ++ ++ case WLC_E_LINK: ++ AP6210_DEBUG("MACEVENT: %s %s\n", event_name, link?"UP":"DOWN"); ++ BCM_REFERENCE(link); ++ break; ++ ++ case WLC_E_MIC_ERROR: ++ AP6210_DEBUG("MACEVENT: %s, MAC %s, Group %d, Flush %d\n", ++ event_name, eabuf, group, flush_txq); ++ BCM_REFERENCE(group); ++ BCM_REFERENCE(flush_txq); ++ break; ++ ++ case WLC_E_ICV_ERROR: ++ case WLC_E_UNICAST_DECODE_ERROR: ++ case WLC_E_MULTICAST_DECODE_ERROR: ++ AP6210_DEBUG("MACEVENT: %s, MAC %s\n", ++ event_name, eabuf); ++ break; ++ ++ case WLC_E_TXFAIL: ++ AP6210_DEBUG("MACEVENT: %s, RA %s\n", event_name, eabuf); ++ break; ++ ++ case WLC_E_SCAN_COMPLETE: ++ case WLC_E_ASSOC_REQ_IE: ++ case WLC_E_ASSOC_RESP_IE: ++ case WLC_E_PMKID_CACHE: ++ AP6210_DEBUG("MACEVENT: %s\n", event_name); ++ break; ++ ++ case WLC_E_PFN_NET_FOUND: ++ case WLC_E_PFN_NET_LOST: ++ case WLC_E_PFN_SCAN_COMPLETE: ++ case WLC_E_PFN_SCAN_NONE: ++ case WLC_E_PFN_SCAN_ALLGONE: ++ AP6210_DEBUG("PNOEVENT: %s\n", event_name); ++ break; ++ ++ case WLC_E_PSK_SUP: ++ case WLC_E_PRUNE: ++ AP6210_DEBUG("MACEVENT: %s, status %d, reason %d\n", ++ event_name, (int)status, (int)reason); ++ break; ++ ++#ifdef WIFI_ACT_FRAME ++ case WLC_E_ACTION_FRAME: ++ AP6210_DEBUG("MACEVENT: %s Bssid %s\n", event_name, eabuf); ++ break; ++#endif /* WIFI_ACT_FRAME */ ++ ++ case WLC_E_TRACE: { ++ static uint32 seqnum_prev = 0; ++ msgtrace_hdr_t hdr; ++ uint32 nblost; ++ char *s, *p; ++ ++ buf = (uchar *) event_data; ++ memcpy(&hdr, buf, MSGTRACE_HDRLEN); ++ ++ if (hdr.version != MSGTRACE_VERSION) { ++ AP6210_DEBUG("MACEVENT: %s [unsupported version --> " ++ "dhd version:%d dongle version:%d]\n", ++ event_name, MSGTRACE_VERSION, hdr.version); ++ /* Reset datalen to avoid display below */ ++ datalen = 0; ++ break; ++ } ++ ++ /* There are 2 bytes available at the end of data */ ++ buf[MSGTRACE_HDRLEN + ntoh16(hdr.len)] = '\0'; ++ ++ if (ntoh32(hdr.discarded_bytes) || ntoh32(hdr.discarded_printf)) { ++ AP6210_DEBUG("WLC_E_TRACE: [Discarded traces in dongle -->" ++ "discarded_bytes %d discarded_printf %d]\n", ++ ntoh32(hdr.discarded_bytes), ntoh32(hdr.discarded_printf)); ++ } ++ ++ nblost = ntoh32(hdr.seqnum) - seqnum_prev - 1; ++ if (nblost > 0) { ++ AP6210_DEBUG("WLC_E_TRACE: [Event lost --> seqnum %d nblost %d\n", ++ ntoh32(hdr.seqnum), nblost); ++ } ++ seqnum_prev = ntoh32(hdr.seqnum); ++ ++ /* Display the trace buffer. Advance from \n to \n to avoid display big ++ * printf (issue with Linux printk ) ++ */ ++ p = (char *)&buf[MSGTRACE_HDRLEN]; ++ while ((s = strstr(p, "\n")) != NULL) { ++ *s = '\0'; ++ AP6210_DEBUG("%s\n", p); ++ p = s+1; ++ } ++ AP6210_DEBUG("%s\n", p); ++ ++ /* Reset datalen to avoid display below */ ++ datalen = 0; ++ break; ++ } ++ ++ ++ case WLC_E_RSSI: ++ AP6210_DEBUG("MACEVENT: %s %d\n", event_name, ntoh32(*((int *)event_data))); ++ break; ++ ++ case WLC_E_SERVICE_FOUND: ++ case WLC_E_P2PO_ADD_DEVICE: ++ case WLC_E_P2PO_DEL_DEVICE: ++ AP6210_DEBUG("MACEVENT: %s, MAC: %s\n", event_name, eabuf); ++ break; ++ ++ default: ++ AP6210_DEBUG("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n", ++ event_name, event_type, eabuf, (int)status, (int)reason, ++ (int)auth_type); ++ break; ++ } ++ ++ /* show any appended data */ ++ if (datalen) { ++ buf = (uchar *) event_data; ++ AP6210_DEBUG(" data (%d) : ", datalen); ++ for (i = 0; i < datalen; i++) ++ AP6210_DUMP(" 0x%02x ", *buf++); ++ AP6210_DUMP("\n"); ++ } ++} ++#endif /* SHOW_EVENTS */ ++ ++int ++wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, ++ wl_event_msg_t *event, void **data_ptr) ++{ ++ /* check whether packet is a BRCM event pkt */ ++ bcm_event_t *pvt_data = (bcm_event_t *)pktdata; ++ uint8 *event_data; ++ uint32 type, status, datalen; ++ uint16 flags; ++ int evlen; ++ ++ if (bcmp(BRCM_OUI, &pvt_data->bcm_hdr.oui[0], DOT11_OUI_LEN)) { ++ AP6210_ERR("%s: mismatched OUI, bailing\n", __FUNCTION__); ++ return (BCME_ERROR); ++ } ++ ++ /* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */ ++ if (ntoh16_ua((void *)&pvt_data->bcm_hdr.usr_subtype) != BCMILCP_BCM_SUBTYPE_EVENT) { ++ AP6210_ERR("%s: mismatched subtype, bailing\n", __FUNCTION__); ++ return (BCME_ERROR); ++ } ++ ++ *data_ptr = &pvt_data[1]; ++ event_data = *data_ptr; ++ ++ /* memcpy since BRCM event pkt may be unaligned. */ ++ memcpy(event, &pvt_data->event, sizeof(wl_event_msg_t)); ++ ++ type = ntoh32_ua((void *)&event->event_type); ++ flags = ntoh16_ua((void *)&event->flags); ++ status = ntoh32_ua((void *)&event->status); ++ datalen = ntoh32_ua((void *)&event->datalen); ++ evlen = datalen + sizeof(bcm_event_t); ++ ++ switch (type) { ++#ifdef PROP_TXSTATUS ++ case WLC_E_FIFO_CREDIT_MAP: ++ dhd_wlfc_event(dhd_pub->info); ++ dhd_wlfc_FIFOcreditmap_event(dhd_pub->info, event_data); ++ AP6210_DEBUG("WLC_E_FIFO_CREDIT_MAP:(AC0,AC1,AC2,AC3),(BC_MC),(OTHER): " ++ "(%d,%d,%d,%d),(%d),(%d)\n", event_data[0], event_data[1], ++ event_data[2], ++ event_data[3], event_data[4], event_data[5]); ++ break; ++#endif ++ ++ case WLC_E_IF: ++ { ++ dhd_if_event_t *ifevent = (dhd_if_event_t *)event_data; ++#ifdef PROP_TXSTATUS ++ { ++ uint8* ea = pvt_data->eth.ether_dhost; ++ AP6210_DEBUG("WLC_E_IF: idx:%d, action:%s, iftype:%s, " ++ "[%02x:%02x:%02x:%02x:%02x:%02x]\n", ++ ifevent->ifidx, ++ ((ifevent->action == WLC_E_IF_ADD) ? "ADD":"DEL"), ++ ((ifevent->is_AP == 0) ? "STA":"AP "), ++ ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]); ++ (void)ea; ++ if (ifevent->action == WLC_E_IF_CHANGE) ++ dhd_wlfc_interface_event(dhd_pub->info, ++ eWLFC_MAC_ENTRY_ACTION_UPDATE, ++ ifevent->ifidx, ifevent->is_AP, ea); ++ else ++ dhd_wlfc_interface_event(dhd_pub->info, ++ ((ifevent->action == WLC_E_IF_ADD) ? ++ eWLFC_MAC_ENTRY_ACTION_ADD : eWLFC_MAC_ENTRY_ACTION_DEL), ++ ifevent->ifidx, ifevent->is_AP, ea); ++ ++ ++ /* dhd already has created an interface by default, for 0 */ ++ if (ifevent->ifidx == 0) ++ break; ++ } ++#endif /* PROP_TXSTATUS */ ++ ++#ifdef WL_CFG80211 ++ if (wl_cfg80211_is_progress_ifchange()) { ++ AP6210_ERR("%s: ifidx %d for %s action %d\n", ++ __FUNCTION__, ifevent->ifidx, ++ event->ifname, ifevent->action); ++ if (ifevent->action == WLC_E_IF_ADD || ++ ifevent->action == WLC_E_IF_CHANGE) ++ wl_cfg80211_notify_ifchange(); ++ return (BCME_OK); ++ } ++#endif /* WL_CFG80211 */ ++ if (ifevent->ifidx > 0 && ifevent->ifidx < DHD_MAX_IFS) { ++ if (ifevent->action == WLC_E_IF_ADD) { ++ if (dhd_add_if(dhd_pub->info, ifevent->ifidx, ++ NULL, event->ifname, ++ event->addr.octet, ++ ifevent->flags, ifevent->bssidx)) { ++ AP6210_ERR("%s: dhd_add_if failed!!" ++ " ifidx: %d for %s\n", ++ __FUNCTION__, ++ ifevent->ifidx, ++ event->ifname); ++ return (BCME_ERROR); ++ } ++ } ++ else if (ifevent->action == WLC_E_IF_DEL) ++ dhd_del_if(dhd_pub->info, ifevent->ifidx); ++ } else { ++#ifndef PROP_TXSTATUS ++ AP6210_ERR("%s: Invalid ifidx %d for %s\n", ++ __FUNCTION__, ifevent->ifidx, event->ifname); ++#endif /* !PROP_TXSTATUS */ ++ } ++ } ++ /* send up the if event: btamp user needs it */ ++ *ifidx = dhd_ifname2idx(dhd_pub->info, event->ifname); ++ /* push up to external supp/auth */ ++ dhd_event(dhd_pub->info, (char *)pvt_data, evlen, *ifidx); ++ break; ++ ++ ++#ifdef WLMEDIA_HTSF ++ case WLC_E_HTSFSYNC: ++ htsf_update(dhd_pub->info, event_data); ++ break; ++#endif /* WLMEDIA_HTSF */ ++#if defined(NDIS630) ++ case WLC_E_NDIS_LINK: ++ break; ++#else /* defined(NDIS630) && defined(BCMDONGLEHOST) */ ++ case WLC_E_NDIS_LINK: { ++ uint32 temp = hton32(WLC_E_LINK); ++ ++ memcpy((void *)(&pvt_data->event.event_type), &temp, ++ sizeof(pvt_data->event.event_type)); ++ } ++#endif ++ /* These are what external supplicant/authenticator wants */ ++ /* fall through */ ++ case WLC_E_LINK: ++ case WLC_E_DEAUTH: ++ case WLC_E_DEAUTH_IND: ++ case WLC_E_DISASSOC: ++ case WLC_E_DISASSOC_IND: ++ AP6210_DEBUG("%s: Link event %d, flags %x, status %x\n", ++ __FUNCTION__, type, flags, status); ++ /* fall through */ ++ default: ++ *ifidx = dhd_ifname2idx(dhd_pub->info, event->ifname); ++ /* push up to external supp/auth */ ++ dhd_event(dhd_pub->info, (char *)pvt_data, evlen, *ifidx); ++ AP6210_DEBUG("%s: MAC event %d, flags %x, status %x\n", ++ __FUNCTION__, type, flags, status); ++ BCM_REFERENCE(flags); ++ BCM_REFERENCE(status); ++ ++ /* put it back to WLC_E_NDIS_LINK */ ++ if (type == WLC_E_NDIS_LINK) { ++ uint32 temp; ++ ++ temp = ntoh32_ua((void *)&event->event_type); ++ AP6210_DEBUG("Converted to WLC_E_LINK type %d\n", temp); ++ ++ temp = ntoh32(WLC_E_NDIS_LINK); ++ memcpy((void *)(&pvt_data->event.event_type), &temp, ++ sizeof(pvt_data->event.event_type)); ++ } ++ break; ++ } ++ ++#ifdef SHOW_EVENTS ++ wl_show_host_event(event, (void *)event_data); ++#endif /* SHOW_EVENTS */ ++ ++ return (BCME_OK); ++} ++ ++void ++wl_event_to_host_order(wl_event_msg_t * evt) ++{ ++ /* Event struct members passed from dongle to host are stored in network ++ * byte order. Convert all members to host-order. ++ */ ++ evt->event_type = ntoh32(evt->event_type); ++ evt->flags = ntoh16(evt->flags); ++ evt->status = ntoh32(evt->status); ++ evt->reason = ntoh32(evt->reason); ++ evt->auth_type = ntoh32(evt->auth_type); ++ evt->datalen = ntoh32(evt->datalen); ++ evt->version = ntoh16(evt->version); ++} ++ ++void ++dhd_print_buf(void *pbuf, int len, int bytes_per_line) ++{ ++#ifdef DHD_DEBUG ++ int i, j = 0; ++ unsigned char *buf = pbuf; ++ ++ if (bytes_per_line == 0) { ++ bytes_per_line = len; ++ } ++ ++ for (i = 0; i < len; i++) { ++ AP6210_DUMP("%2.2x", *buf++); ++ j++; ++ if (j == bytes_per_line) { ++ AP6210_DUMP("\n"); ++ j = 0; ++ } else { ++ AP6210_DUMP(":"); ++ } ++ } ++ AP6210_DUMP("\n"); ++#endif /* DHD_DEBUG */ ++} ++ ++#ifndef strtoul ++#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) ++#endif ++ ++#ifdef PKT_FILTER_SUPPORT ++/* Convert user's input in hex pattern to byte-size mask */ ++static int ++wl_pattern_atoh(char *src, char *dst) ++{ ++ int i; ++ if (strncmp(src, "0x", 2) != 0 && ++ strncmp(src, "0X", 2) != 0) { ++ AP6210_ERR("Mask invalid format. Needs to start with 0x\n"); ++ return -1; ++ } ++ src = src + 2; /* Skip past 0x */ ++ if (strlen(src) % 2 != 0) { ++ AP6210_ERR("Mask invalid format. Needs to be of even length\n"); ++ return -1; ++ } ++ for (i = 0; *src != '\0'; i++) { ++ char num[3]; ++ bcm_strncpy_s(num, sizeof(num), src, 2); ++ num[2] = '\0'; ++ dst[i] = (uint8)strtoul(num, NULL, 16); ++ src += 2; ++ } ++ return i; ++} ++ ++void ++dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode) ++{ ++ char *argv[8]; ++ int i = 0; ++ const char *str; ++ int buf_len; ++ int str_len; ++ char *arg_save = 0, *arg_org = 0; ++ int rc; ++ char buf[128]; ++ wl_pkt_filter_enable_t enable_parm; ++ wl_pkt_filter_enable_t * pkt_filterp; ++ ++ if (!arg) ++ return; ++ ++ if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) { ++ AP6210_ERR("%s: kmalloc failed\n", __FUNCTION__); ++ goto fail; ++ } ++ arg_org = arg_save; ++ memcpy(arg_save, arg, strlen(arg) + 1); ++ ++ argv[i] = bcmstrtok(&arg_save, " ", 0); ++ ++ i = 0; ++ if (argv[i] == NULL) { ++ AP6210_ERR("No args provided\n"); ++ goto fail; ++ } ++ ++ str = "pkt_filter_enable"; ++ str_len = strlen(str); ++ bcm_strncpy_s(buf, sizeof(buf), str, str_len); ++ buf[str_len] = '\0'; ++ buf_len = str_len + 1; ++ ++ pkt_filterp = (wl_pkt_filter_enable_t *)(buf + str_len + 1); ++ ++ /* Parse packet filter id. */ ++ enable_parm.id = htod32(strtoul(argv[i], NULL, 0)); ++ ++ /* Parse enable/disable value. */ ++ enable_parm.enable = htod32(enable); ++ ++ buf_len += sizeof(enable_parm); ++ memcpy((char *)pkt_filterp, ++ &enable_parm, ++ sizeof(enable_parm)); ++ ++ /* Enable/disable the specified filter. */ ++ rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0); ++ rc = rc >= 0 ? 0 : rc; ++ if (rc) ++ AP6210_DEBUG("%s: failed to add pktfilter %s, retcode = %d\n", ++ __FUNCTION__, arg, rc); ++ else ++ AP6210_DEBUG("%s: successfully added pktfilter %s\n", ++ __FUNCTION__, arg); ++ ++ /* Contorl the master mode */ ++ bcm_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf, sizeof(buf)); ++ rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); ++ rc = rc >= 0 ? 0 : rc; ++ if (rc) ++ AP6210_DEBUG("%s: failed to add pktfilter %s, retcode = %d\n", ++ __FUNCTION__, arg, rc); ++ ++fail: ++ if (arg_org) ++ MFREE(dhd->osh, arg_org, strlen(arg) + 1); ++} ++ ++void ++dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) ++{ ++ const char *str; ++ wl_pkt_filter_t pkt_filter; ++ wl_pkt_filter_t *pkt_filterp; ++ int buf_len; ++ int str_len; ++ int rc; ++ uint32 mask_size; ++ uint32 pattern_size; ++ char *argv[8], * buf = 0; ++ int i = 0; ++ char *arg_save = 0, *arg_org = 0; ++#define BUF_SIZE 2048 ++ ++ if (!arg) ++ return; ++ ++ if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) { ++ AP6210_ERR("%s: kmalloc failed\n", __FUNCTION__); ++ goto fail; ++ } ++ ++ arg_org = arg_save; ++ ++ if (!(buf = MALLOC(dhd->osh, BUF_SIZE))) { ++ AP6210_ERR("%s: kmalloc failed\n", __FUNCTION__); ++ goto fail; ++ } ++ ++ memcpy(arg_save, arg, strlen(arg) + 1); ++ ++ if (strlen(arg) > BUF_SIZE) { ++ AP6210_ERR("Not enough buffer %d < %d\n", (int)strlen(arg), (int)sizeof(buf)); ++ goto fail; ++ } ++ ++ argv[i] = bcmstrtok(&arg_save, " ", 0); ++ while (argv[i++]) ++ argv[i] = bcmstrtok(&arg_save, " ", 0); ++ ++ i = 0; ++ if (argv[i] == NULL) { ++ AP6210_ERR("No args provided\n"); ++ goto fail; ++ } ++ ++ str = "pkt_filter_add"; ++ str_len = strlen(str); ++ bcm_strncpy_s(buf, BUF_SIZE, str, str_len); ++ buf[ str_len ] = '\0'; ++ buf_len = str_len + 1; ++ ++ pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1); ++ ++ /* Parse packet filter id. */ ++ pkt_filter.id = htod32(strtoul(argv[i], NULL, 0)); ++ ++ if (argv[++i] == NULL) { ++ AP6210_ERR("Polarity not provided\n"); ++ goto fail; ++ } ++ ++ /* Parse filter polarity. */ ++ pkt_filter.negate_match = htod32(strtoul(argv[i], NULL, 0)); ++ ++ if (argv[++i] == NULL) { ++ AP6210_ERR("Filter type not provided\n"); ++ goto fail; ++ } ++ ++ /* Parse filter type. */ ++ pkt_filter.type = htod32(strtoul(argv[i], NULL, 0)); ++ ++ if (argv[++i] == NULL) { ++ AP6210_ERR("Offset not provided\n"); ++ goto fail; ++ } ++ ++ /* Parse pattern filter offset. */ ++ pkt_filter.u.pattern.offset = htod32(strtoul(argv[i], NULL, 0)); ++ ++ if (argv[++i] == NULL) { ++ AP6210_ERR("Bitmask not provided\n"); ++ goto fail; ++ } ++ ++ /* Parse pattern filter mask. */ ++ mask_size = ++ htod32(wl_pattern_atoh(argv[i], (char *) pkt_filterp->u.pattern.mask_and_pattern)); ++ ++ if (argv[++i] == NULL) { ++ AP6210_ERR("Pattern not provided\n"); ++ goto fail; ++ } ++ ++ /* Parse pattern filter pattern. */ ++ pattern_size = ++ htod32(wl_pattern_atoh(argv[i], ++ (char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size])); ++ ++ if (mask_size != pattern_size) { ++ AP6210_ERR("Mask and pattern not the same size\n"); ++ goto fail; ++ } ++ ++ pkt_filter.u.pattern.size_bytes = mask_size; ++ buf_len += WL_PKT_FILTER_FIXED_LEN; ++ buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); ++ ++ /* Keep-alive attributes are set in local variable (keep_alive_pkt), and ++ ** then memcpy'ed into buffer (keep_alive_pktp) since there is no ++ ** guarantee that the buffer is properly aligned. ++ */ ++ memcpy((char *)pkt_filterp, ++ &pkt_filter, ++ WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN); ++ ++ rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0); ++ rc = rc >= 0 ? 0 : rc; ++ ++ if (rc) ++ AP6210_DEBUG("%s: failed to add pktfilter %s, retcode = %d\n", ++ __FUNCTION__, arg, rc); ++ else ++ AP6210_DEBUG("%s: successfully added pktfilter %s\n", ++ __FUNCTION__, arg); ++ ++fail: ++ if (arg_org) ++ MFREE(dhd->osh, arg_org, strlen(arg) + 1); ++ ++ if (buf) ++ MFREE(dhd->osh, buf, BUF_SIZE); ++} ++#endif /* PKT_FILTER_SUPPORT */ ++ ++/* ========================== */ ++/* ==== ARP OFFLOAD SUPPORT = */ ++/* ========================== */ ++#ifdef ARP_OFFLOAD_SUPPORT ++void ++dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode) ++{ ++ char iovbuf[32]; ++ int retcode; ++ ++ bcm_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf)); ++ retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++ retcode = retcode >= 0 ? 0 : retcode; ++ if (retcode) ++ AP6210_DEBUG("%s: failed to set ARP offload mode to 0x%x, retcode = %d\n", ++ __FUNCTION__, arp_mode, retcode); ++ else ++ AP6210_DEBUG("%s: successfully set ARP offload mode to 0x%x\n", ++ __FUNCTION__, arp_mode); ++} ++ ++void ++dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable) ++{ ++ char iovbuf[32]; ++ int retcode; ++ ++ bcm_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf)); ++ retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++ retcode = retcode >= 0 ? 0 : retcode; ++ if (retcode) ++ AP6210_DEBUG("%s: failed to enabe ARP offload to %d, retcode = %d\n", ++ __FUNCTION__, arp_enable, retcode); ++ else ++ AP6210_DEBUG("%s: successfully enabed ARP offload to %d\n", ++ __FUNCTION__, arp_enable); ++ if (arp_enable) { ++ uint32 version; ++ bcm_mkiovar("arp_version", 0, 0, iovbuf, sizeof(iovbuf)); ++ retcode = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0); ++ if (retcode) { ++ AP6210_DEBUG("%s: fail to get version (maybe version 1:retcode = %d\n", ++ __FUNCTION__, retcode); ++ dhd->arp_version = 1; ++ } ++ else { ++ memcpy(&version, iovbuf, sizeof(version)); ++ AP6210_DEBUG("%s: ARP Version= %x\n", __FUNCTION__, version); ++ dhd->arp_version = version; ++ } ++ } ++} ++ ++void ++dhd_aoe_arp_clr(dhd_pub_t *dhd, int idx) ++{ ++ int ret = 0; ++ int iov_len = 0; ++ char iovbuf[128]; ++ ++ if (dhd == NULL) return; ++ if (dhd->arp_version == 1) ++ idx = 0; ++ ++ iov_len = bcm_mkiovar("arp_table_clear", 0, 0, iovbuf, sizeof(iovbuf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx) < 0)) ++ AP6210_ERR("%s failed code %d\n", __FUNCTION__, ret); ++} ++ ++void ++dhd_aoe_hostip_clr(dhd_pub_t *dhd, int idx) ++{ ++ int ret = 0; ++ int iov_len = 0; ++ char iovbuf[128]; ++ ++ if (dhd == NULL) return; ++ if (dhd->arp_version == 1) ++ idx = 0; ++ ++ iov_len = bcm_mkiovar("arp_hostip_clear", 0, 0, iovbuf, sizeof(iovbuf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx)) < 0) ++ AP6210_ERR("%s failed code %d\n", __FUNCTION__, ret); ++} ++ ++void ++dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr, int idx) ++{ ++ int iov_len = 0; ++ char iovbuf[32]; ++ int retcode; ++ ++ ++ if (dhd == NULL) return; ++ if (dhd->arp_version == 1) ++ idx = 0; ++ iov_len = bcm_mkiovar("arp_hostip", (char *)&ipaddr, ++ sizeof(ipaddr), iovbuf, sizeof(iovbuf)); ++ retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx); ++ ++ if (retcode) ++ AP6210_DEBUG("%s: ARP ip addr add failed, retcode = %d\n", ++ __FUNCTION__, retcode); ++ else ++ AP6210_DEBUG("%s: sARP H ipaddr entry added \n", ++ __FUNCTION__); ++} ++ ++int ++dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen, int idx) ++{ ++ int retcode, i; ++ int iov_len; ++ uint32 *ptr32 = buf; ++ bool clr_bottom = FALSE; ++ ++ if (!buf) ++ return -1; ++ if (dhd == NULL) return -1; ++ if (dhd->arp_version == 1) ++ idx = 0; ++ ++ iov_len = bcm_mkiovar("arp_hostip", 0, 0, buf, buflen); ++ BCM_REFERENCE(iov_len); ++ retcode = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, buflen, FALSE, idx); ++ ++ if (retcode) { ++ AP6210_DEBUG("%s: ioctl WLC_GET_VAR error %d\n", ++ __FUNCTION__, retcode); ++ ++ return -1; ++ } ++ ++ /* clean up the buf, ascii reminder */ ++ for (i = 0; i < MAX_IPV4_ENTRIES; i++) { ++ if (!clr_bottom) { ++ if (*ptr32 == 0) ++ clr_bottom = TRUE; ++ } else { ++ *ptr32 = 0; ++ } ++ ptr32++; ++ } ++ ++ return 0; ++} ++#endif /* ARP_OFFLOAD_SUPPORT */ ++ ++/* send up locally generated event */ ++void ++dhd_sendup_event_common(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data) ++{ ++ switch (ntoh32(event->event_type)) { ++#ifdef WLBTAMP ++ case WLC_E_BTA_HCI_EVENT: ++ break; ++#endif /* WLBTAMP */ ++ default: ++ break; ++ } ++ ++ /* Call per-port handler. */ ++ dhd_sendup_event(dhdp, event, data); ++} ++ ++ ++/* ++ * returns = TRUE if associated, FALSE if not associated ++ */ ++bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval) ++{ ++ char bssid[6], zbuf[6]; ++ int ret = -1; ++ ++ bzero(bssid, 6); ++ bzero(zbuf, 6); ++ ++ ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, (char *)&bssid, ETHER_ADDR_LEN, FALSE, 0); ++ AP6210_DEBUG(" %s WLC_GET_BSSID ioctl res = %d\n", __FUNCTION__, ret); ++ ++ if (ret == BCME_NOTASSOCIATED) { ++ AP6210_DEBUG("%s: not associated! res:%d\n", __FUNCTION__, ret); ++ } ++ ++ if (retval) ++ *retval = ret; ++ ++ if (ret < 0) ++ return FALSE; ++ ++ if ((memcmp(bssid, zbuf, ETHER_ADDR_LEN) != 0)) { ++ /* STA is assocoated BSSID is non zero */ ++ ++ if (bss_buf) { ++ /* return bss if caller provided buf */ ++ memcpy(bss_buf, bssid, ETHER_ADDR_LEN); ++ } ++ return TRUE; ++ } else { ++ AP6210_DEBUG("%s: WLC_GET_BSSID ioctl returned zero bssid\n", __FUNCTION__); ++ return FALSE; ++ } ++} ++ ++ ++/* Function to estimate possible DTIM_SKIP value */ ++int ++dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd) ++{ ++ int bcn_li_dtim; ++ int ret = -1; ++ int dtim_assoc = 0; ++ ++ bcn_li_dtim = dhd->suspend_bcn_li_dtim; ++ ++ /* Check if associated */ ++ if (dhd_is_associated(dhd, NULL, NULL) == FALSE) { ++ AP6210_DEBUG("%s NOT assoc ret %d\n", __FUNCTION__, ret); ++ goto exit; ++ } ++ ++ /* if assoc grab ap's dtim value */ ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_DTIMPRD, ++ &dtim_assoc, sizeof(dtim_assoc), FALSE, 0)) < 0) { ++ AP6210_ERR("%s failed code %d\n", __FUNCTION__, ret); ++ goto exit; ++ } ++ ++ AP6210_ERR("%s bcn_li_dtim=%d DTIM=%d Listen=%d\n", ++ __FUNCTION__, bcn_li_dtim, dtim_assoc, LISTEN_INTERVAL); ++ ++ /* if not assocated just eixt */ ++ if (dtim_assoc == 0) { ++ goto exit; ++ } ++ ++ /* check if sta listen interval fits into AP dtim */ ++ if (dtim_assoc > LISTEN_INTERVAL) { ++ /* AP DTIM to big for our Listen Interval : no dtim skiping */ ++ bcn_li_dtim = 1; ++ AP6210_ERR("%s DTIM=%d > Listen=%d : too big ...\n", ++ __FUNCTION__, dtim_assoc, LISTEN_INTERVAL); ++ goto exit; ++ } ++ ++ if ((bcn_li_dtim * dtim_assoc) > LISTEN_INTERVAL) { ++ /* Round up dtim_skip to fit into STAs Listen Interval */ ++ bcn_li_dtim = (int)(LISTEN_INTERVAL / dtim_assoc); ++ AP6210_DEBUG("%s agjust dtim_skip as %d\n", __FUNCTION__, bcn_li_dtim); ++ } ++ ++exit: ++ return bcn_li_dtim; ++} ++ ++/* Check if the mode supports STA MODE */ ++bool dhd_support_sta_mode(dhd_pub_t *dhd) ++{ ++ ++#ifdef WL_CFG80211 ++ if (!(dhd->op_mode & DHD_FLAG_STA_MODE)) ++ return FALSE; ++ else ++#endif /* WL_CFG80211 */ ++ return TRUE; ++} ++ ++#if defined(PNO_SUPPORT) ++int ++dhd_pno_clean(dhd_pub_t *dhd) ++{ ++ char iovbuf[128]; ++ int pfn_enabled = 0; ++ int iov_len = 0; ++ int ret; ++ ++ /* Disable pfn */ ++ iov_len = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) >= 0) { ++ /* clear pfn */ ++ iov_len = bcm_mkiovar("pfnclear", 0, 0, iovbuf, sizeof(iovbuf)); ++ if (iov_len) { ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, ++ iov_len, TRUE, 0)) < 0) { ++ AP6210_ERR("%s failed code %d\n", __FUNCTION__, ret); ++ } ++ } ++ else { ++ ret = -1; ++ AP6210_ERR("%s failed code %d\n", __FUNCTION__, iov_len); ++ } ++ } ++ else ++ AP6210_ERR("%s failed code %d\n", __FUNCTION__, ret); ++ ++ return ret; ++} ++ ++int ++dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled) ++{ ++ char iovbuf[128]; ++ int ret = -1; ++ ++ if ((!dhd) && ((pfn_enabled != 0) || (pfn_enabled != 1))) { ++ AP6210_ERR("%s error exit\n", __FUNCTION__); ++ return ret; ++ } ++ ++#ifndef WL_SCHED_SCAN ++ if (!dhd_support_sta_mode(dhd)) ++ return (ret); ++ ++ memset(iovbuf, 0, sizeof(iovbuf)); ++ ++ if ((pfn_enabled) && (dhd_is_associated(dhd, NULL, NULL) == TRUE)) { ++ AP6210_ERR("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__); ++ return ret; ++ } ++#endif /* !WL_SCHED_SCAN */ ++ ++ /* Enable/disable PNO */ ++ if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) { ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, ++ iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { ++ AP6210_ERR("%s failed for error=%d\n", __FUNCTION__, ret); ++ return ret; ++ } ++ else { ++ dhd->pno_enable = pfn_enabled; ++ AP6210_DEBUG("%s set pno as %s\n", ++ __FUNCTION__, dhd->pno_enable ? "Enable" : "Disable"); ++ } ++ } ++ else AP6210_ERR("%s failed err=%d\n", __FUNCTION__, ret); ++ ++ return ret; ++} ++ ++/* Function to execute combined scan */ ++int ++dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, ++ int pno_repeat, int pno_freq_expo_max) ++{ ++ int err = -1; ++ char iovbuf[128]; ++ int k, i; ++ wl_pfn_param_t pfn_param; ++ wl_pfn_t pfn_element; ++ uint len = 0; ++ ++ AP6210_DEBUG("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, scan_fr); ++ ++ if ((!dhd) || (!ssids_local)) { ++ AP6210_ERR("%s error exit(%s %s)\n", __FUNCTION__, ++ (!dhd)?"dhd is null":"", (!ssids_local)?"ssid is null":""); ++ err = -1; ++ return err; ++ } ++#ifndef WL_SCHED_SCAN ++ if (!dhd_support_sta_mode(dhd)) ++ return err; ++#endif /* !WL_SCHED_SCAN */ ++ ++ /* Check for broadcast ssid */ ++ for (k = 0; k < nssid; k++) { ++ if (!ssids_local[k].SSID_len) { ++ AP6210_ERR("%d: Broadcast SSID is ilegal for PNO setting\n", k); ++ return err; ++ } ++ } ++/* #define PNO_DUMP 1 */ ++#ifdef PNO_DUMP ++ { ++ int j; ++ for (j = 0; j < nssid; j++) { ++ AP6210_ERR("%d: scan for %s size =%d\n", j, ++ ssids_local[j].SSID, ssids_local[j].SSID_len); ++ } ++ } ++#endif /* PNO_DUMP */ ++ ++ /* clean up everything */ ++ if ((err = dhd_pno_clean(dhd)) < 0) { ++ AP6210_ERR("%s failed error=%d\n", __FUNCTION__, err); ++ return err; ++ } ++ memset(iovbuf, 0, sizeof(iovbuf)); ++ memset(&pfn_param, 0, sizeof(pfn_param)); ++ memset(&pfn_element, 0, sizeof(pfn_element)); ++ ++ /* set pfn parameters */ ++ pfn_param.version = htod32(PFN_VERSION); ++ pfn_param.flags = htod16((PFN_LIST_ORDER << SORT_CRITERIA_BIT)); ++ ++ /* check and set extra pno params */ ++ if ((pno_repeat != 0) || (pno_freq_expo_max != 0)) { ++ pfn_param.flags |= htod16(ENABLE << ENABLE_ADAPTSCAN_BIT); ++ pfn_param.repeat = (uchar) (pno_repeat); ++ pfn_param.exp = (uchar) (pno_freq_expo_max); ++ } ++ /* set up pno scan fr */ ++ if (scan_fr != 0) ++ pfn_param.scan_freq = htod32(scan_fr); ++ ++ if (pfn_param.scan_freq > PNO_SCAN_MAX_FW_SEC) { ++ AP6210_ERR("%s pno freq above %d sec\n", __FUNCTION__, PNO_SCAN_MAX_FW_SEC); ++ return err; ++ } ++ if (pfn_param.scan_freq < PNO_SCAN_MIN_FW_SEC) { ++ AP6210_ERR("%s pno freq less %d sec\n", __FUNCTION__, PNO_SCAN_MIN_FW_SEC); ++ return err; ++ } ++ ++ len = bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf, sizeof(iovbuf)); ++ if ((err = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE, 0)) < 0) { ++ AP6210_ERR("%s pfn_set failed for error=%d\n", ++ __FUNCTION__, err); ++ return err; ++ } ++ ++ /* set all pfn ssid */ ++ for (i = 0; i < nssid; i++) { ++ ++ pfn_element.infra = htod32(DOT11_BSSTYPE_INFRASTRUCTURE); ++ pfn_element.auth = (DOT11_OPEN_SYSTEM); ++ pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY); ++ pfn_element.wsec = htod32(0); ++ pfn_element.infra = htod32(1); ++ pfn_element.flags = htod32(ENABLE << WL_PFN_HIDDEN_BIT); ++ memcpy((char *)pfn_element.ssid.SSID, ssids_local[i].SSID, ssids_local[i].SSID_len); ++ pfn_element.ssid.SSID_len = ssids_local[i].SSID_len; ++ ++ if ((len = ++ bcm_mkiovar("pfn_add", (char *)&pfn_element, ++ sizeof(pfn_element), iovbuf, sizeof(iovbuf))) > 0) { ++ if ((err = ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE, 0)) < 0) { ++ AP6210_ERR("%s failed for i=%d error=%d\n", ++ __FUNCTION__, i, err); ++ return err; ++ } ++ else ++ AP6210_DEBUG("%s set OK with PNO time=%d repeat=%d max_adjust=%d\n", ++ __FUNCTION__, pfn_param.scan_freq, ++ pfn_param.repeat, pfn_param.exp); ++ } ++ else AP6210_ERR("%s failed err=%d\n", __FUNCTION__, err); ++ } ++ ++ /* Enable PNO */ ++ /* dhd_pno_enable(dhd, 1); */ ++ return err; ++} ++ ++int ++dhd_pno_get_status(dhd_pub_t *dhd) ++{ ++ int ret = -1; ++ ++ if (!dhd) ++ return ret; ++ else ++ return (dhd->pno_enable); ++} ++ ++#endif /* OEM_ANDROID && PNO_SUPPORT */ ++ ++#if defined(KEEP_ALIVE) ++int dhd_keep_alive_onoff(dhd_pub_t *dhd) ++{ ++ char buf[256]; ++ const char *str; ++ wl_mkeep_alive_pkt_t mkeep_alive_pkt; ++ wl_mkeep_alive_pkt_t *mkeep_alive_pktp; ++ int buf_len; ++ int str_len; ++ int res = -1; ++ ++ if (!dhd_support_sta_mode(dhd)) ++ return res; ++ ++ AP6210_DEBUG("%s execution\n", __FUNCTION__); ++ ++ str = "mkeep_alive"; ++ str_len = strlen(str); ++ strncpy(buf, str, str_len); ++ buf[ str_len ] = '\0'; ++ mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) (buf + str_len + 1); ++ mkeep_alive_pkt.period_msec = CUSTOM_KEEP_ALIVE_SETTING; ++ buf_len = str_len + 1; ++ mkeep_alive_pkt.version = htod16(WL_MKEEP_ALIVE_VERSION); ++ mkeep_alive_pkt.length = htod16(WL_MKEEP_ALIVE_FIXED_LEN); ++ /* Setup keep alive zero for null packet generation */ ++ mkeep_alive_pkt.keep_alive_id = 0; ++ mkeep_alive_pkt.len_bytes = 0; ++ buf_len += WL_MKEEP_ALIVE_FIXED_LEN; ++ bzero(mkeep_alive_pkt.data, sizeof(mkeep_alive_pkt.data)); ++ /* Keep-alive attributes are set in local variable (mkeep_alive_pkt), and ++ * then memcpy'ed into buffer (mkeep_alive_pktp) since there is no ++ * guarantee that the buffer is properly aligned. ++ */ ++ memcpy((char *)mkeep_alive_pktp, &mkeep_alive_pkt, WL_MKEEP_ALIVE_FIXED_LEN); ++ ++ res = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0); ++ ++ return res; ++} ++#endif /* defined(KEEP_ALIVE) */ ++/* Android ComboSCAN support */ ++ ++/* ++ * data parsing from ComboScan tlv list ++*/ ++int ++wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token, ++ int input_size, int *bytes_left) ++{ ++ char* str; ++ uint16 short_temp; ++ uint32 int_temp; ++ ++ if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) { ++ AP6210_ERR("%s error paramters\n", __FUNCTION__); ++ return -1; ++ } ++ str = *list_str; ++ ++ /* Clean all dest bytes */ ++ memset(dst, 0, dst_size); ++ while (*bytes_left > 0) { ++ ++ if (str[0] != token) { ++ AP6210_DEBUG("%s NOT Type=%d get=%d left_parse=%d \n", ++ __FUNCTION__, token, str[0], *bytes_left); ++ return -1; ++ } ++ ++ *bytes_left -= 1; ++ str += 1; ++ ++ if (input_size == 1) { ++ memcpy(dst, str, input_size); ++ } ++ else if (input_size == 2) { ++ memcpy(dst, (char *)htod16(memcpy(&short_temp, str, input_size)), ++ input_size); ++ } ++ else if (input_size == 4) { ++ memcpy(dst, (char *)htod32(memcpy(&int_temp, str, input_size)), ++ input_size); ++ } ++ ++ *bytes_left -= input_size; ++ str += input_size; ++ *list_str = str; ++ return 1; ++ } ++ return 1; ++} ++ ++/* ++ * channel list parsing from cscan tlv list ++*/ ++int ++wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list, ++ int channel_num, int *bytes_left) ++{ ++ char* str; ++ int idx = 0; ++ ++ if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) { ++ AP6210_ERR("%s error paramters\n", __FUNCTION__); ++ return -1; ++ } ++ str = *list_str; ++ ++ while (*bytes_left > 0) { ++ ++ if (str[0] != CSCAN_TLV_TYPE_CHANNEL_IE) { ++ *list_str = str; ++ AP6210_DEBUG("End channel=%d left_parse=%d %d\n", idx, *bytes_left, str[0]); ++ return idx; ++ } ++ /* Get proper CSCAN_TLV_TYPE_CHANNEL_IE */ ++ *bytes_left -= 1; ++ str += 1; ++ ++ if (str[0] == 0) { ++ /* All channels */ ++ channel_list[idx] = 0x0; ++ } ++ else { ++ channel_list[idx] = (uint16)str[0]; ++ AP6210_DEBUG("%s channel=%d \n", __FUNCTION__, channel_list[idx]); ++ } ++ *bytes_left -= 1; ++ str += 1; ++ ++ if (idx++ > 255) { ++ AP6210_ERR("%s Too many channels \n", __FUNCTION__); ++ return -1; ++ } ++ } ++ ++ *list_str = str; ++ return idx; ++} ++ ++/* ++ * SSIDs list parsing from cscan tlv list ++ */ ++int ++wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes_left) ++{ ++ char* str; ++ int idx = 0; ++ ++ if ((list_str == NULL) || (*list_str == NULL) || (*bytes_left < 0)) { ++ AP6210_ERR("%s error paramters\n", __FUNCTION__); ++ return -1; ++ } ++ str = *list_str; ++ while (*bytes_left > 0) { ++ ++ if (str[0] != CSCAN_TLV_TYPE_SSID_IE) { ++ *list_str = str; ++ AP6210_DEBUG("nssid=%d left_parse=%d %d\n", idx, *bytes_left, str[0]); ++ return idx; ++ } ++ ++ /* Get proper CSCAN_TLV_TYPE_SSID_IE */ ++ *bytes_left -= 1; ++ str += 1; ++ ++ if (str[0] == 0) { ++ /* Broadcast SSID */ ++ ssid[idx].SSID_len = 0; ++ memset((char*)ssid[idx].SSID, 0x0, DOT11_MAX_SSID_LEN); ++ *bytes_left -= 1; ++ str += 1; ++ ++ AP6210_DEBUG("BROADCAST SCAN left=%d\n", *bytes_left); ++ } ++ else if (str[0] <= DOT11_MAX_SSID_LEN) { ++ /* Get proper SSID size */ ++ ssid[idx].SSID_len = str[0]; ++ *bytes_left -= 1; ++ str += 1; ++ ++ /* Get SSID */ ++ if (ssid[idx].SSID_len > *bytes_left) { ++ AP6210_ERR("%s out of memory range len=%d but left=%d\n", ++ __FUNCTION__, ssid[idx].SSID_len, *bytes_left); ++ return -1; ++ } ++ ++ memcpy((char*)ssid[idx].SSID, str, ssid[idx].SSID_len); ++ ++ *bytes_left -= ssid[idx].SSID_len; ++ str += ssid[idx].SSID_len; ++ ++ AP6210_DEBUG("%s :size=%d left=%d\n", ++ (char*)ssid[idx].SSID, ssid[idx].SSID_len, *bytes_left); ++ } ++ else { ++ AP6210_ERR("### SSID size more that %d\n", str[0]); ++ return -1; ++ } ++ ++ if (idx++ > max) { ++ AP6210_ERR("%s number of SSIDs more that %d\n", __FUNCTION__, idx); ++ return -1; ++ } ++ } ++ ++ *list_str = str; ++ return idx; ++} ++ ++/* Parse a comma-separated list from list_str into ssid array, starting ++ * at index idx. Max specifies size of the ssid array. Parses ssids ++ * and returns updated idx; if idx >= max not all fit, the excess have ++ * not been copied. Returns -1 on empty string, or on ssid too long. ++ */ ++int ++wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max) ++{ ++ char* str, *ptr; ++ ++ if ((list_str == NULL) || (*list_str == NULL)) ++ return -1; ++ ++ for (str = *list_str; str != NULL; str = ptr) { ++ ++ /* check for next TAG */ ++ if (!strncmp(str, GET_CHANNEL, strlen(GET_CHANNEL))) { ++ *list_str = str + strlen(GET_CHANNEL); ++ return idx; ++ } ++ ++ if ((ptr = strchr(str, ',')) != NULL) { ++ *ptr++ = '\0'; ++ } ++ ++ if (strlen(str) > DOT11_MAX_SSID_LEN) { ++ AP6210_ERR("ssid <%s> exceeds %d\n", str, DOT11_MAX_SSID_LEN); ++ return -1; ++ } ++ ++ if (strlen(str) == 0) ++ ssid[idx].SSID_len = 0; ++ ++ if (idx < max) { ++ bzero(ssid[idx].SSID, sizeof(ssid[idx].SSID)); ++ strncpy((char*)ssid[idx].SSID, str, sizeof(ssid[idx].SSID) - 1); ++ ssid[idx].SSID_len = strlen(str); ++ } ++ idx++; ++ } ++ return idx; ++} ++ ++/* ++ * Parse channel list from iwpriv CSCAN ++ */ ++int ++wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num) ++{ ++ int num; ++ int val; ++ char* str; ++ char* endptr = NULL; ++ ++ if ((list_str == NULL)||(*list_str == NULL)) ++ return -1; ++ ++ str = *list_str; ++ num = 0; ++ while (strncmp(str, GET_NPROBE, strlen(GET_NPROBE))) { ++ val = (int)strtoul(str, &endptr, 0); ++ if (endptr == str) { ++ AP6210_ERR("could not parse channel number starting at" ++ " substring \"%s\" in list:\n%s\n", ++ str, *list_str); ++ return -1; ++ } ++ str = endptr + strspn(endptr, " ,"); ++ ++ if (num == channel_num) { ++ AP6210_ERR("too many channels (more than %d) in channel list:\n%s\n", ++ channel_num, *list_str); ++ return -1; ++ } ++ ++ channel_list[num++] = (uint16)val; ++ } ++ *list_str = str; ++ return num; ++} +diff --git a/drivers/net/wireless/ap6210/dhd_custom_gpio.c b/drivers/net/wireless/ap6210/dhd_custom_gpio.c +new file mode 100755 +index 0000000..afdb9b3 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_custom_gpio.c +@@ -0,0 +1,313 @@ ++/* ++* Customer code to add GPIO control during WLAN start/stop ++* Copyright (C) 1999-2012, Broadcom Corporation ++* ++* Unless you and Broadcom execute a separate written software license ++* agreement governing use of this software, this software is licensed to you ++* under the terms of the GNU General Public License version 2 (the "GPL"), ++* available at http://www.broadcom.com/licenses/GPLv2.php, with the ++* following added to such license: ++* ++* As a special exception, the copyright holders of this software give you ++* permission to link this software with independent modules, and to copy and ++* distribute the resulting executable under terms of your choice, provided that ++* you also meet, for each linked independent module, the terms and conditions of ++* the license of that module. An independent module is a module which is not ++* derived from this software. The special exception does not apply to any ++* modifications of the software. ++* ++* Notwithstanding the above, under no circumstances may you combine this ++* software in any way with any other Broadcom software provided under a license ++* other than the GPL, without Broadcom's express prior written consent. ++* ++* $Id: dhd_custom_gpio.c 353167 2012-08-24 22:11:30Z $ ++*/ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++extern void sunximmc_rescan_card(unsigned id, unsigned insert); ++ ++#ifdef CUSTOMER_HW ++#include ++#if defined(CUSTOMER_OOB) ++extern int bcm_wlan_get_oob_irq(void); ++#endif ++extern void bcm_wlan_power_off(int); ++extern void bcm_wlan_power_on(int); ++#endif /* CUSTOMER_HW */ ++#if defined(CUSTOMER_HW2) ++#ifdef CONFIG_WIFI_CONTROL_FUNC ++int wifi_set_power(int on, unsigned long msec); ++int wifi_get_irq_number(unsigned long *irq_flags_ptr); ++int wifi_get_mac_addr(unsigned char *buf); ++void *wifi_get_country_code(char *ccode); ++#else ++int wifi_set_power(int on, unsigned long msec) { return -1; } ++int wifi_get_irq_number(unsigned long *irq_flags_ptr) { return -1; } ++int wifi_get_mac_addr(unsigned char *buf) { return -1; } ++void *wifi_get_country_code(char *ccode) { return NULL; } ++#endif /* CONFIG_WIFI_CONTROL_FUNC */ ++#endif ++ ++#if defined(OOB_INTR_ONLY) ++ ++#if defined(BCMLXSDMMC) ++extern int sdioh_mmc_irq(int irq); ++#endif /* (BCMLXSDMMC) */ ++ ++#ifdef CUSTOMER_HW3 ++#include ++#endif ++ ++/* Customer specific Host GPIO defintion */ ++static int dhd_oob_gpio_num = 2; ++ ++module_param(dhd_oob_gpio_num, int, 0644); ++MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD oob gpio number"); ++ ++/* This function will return: ++ * 1) return : Host gpio interrupt number per customer platform ++ * 2) irq_flags_ptr : Type of Host interrupt as Level or Edge ++ * ++ * NOTE : ++ * Customer should check his platform definitions ++ * and his Host Interrupt spec ++ * to figure out the proper setting for his platform. ++ * Broadcom provides just reference settings as example. ++ * ++ */ ++int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr) ++{ ++ int host_oob_irq = -1; ++ ++#if defined(CUSTOMER_HW2) ++ host_oob_irq = wifi_get_irq_number(irq_flags_ptr); ++ ++#elif defined(CUSTOMER_OOB) ++ host_oob_irq = bcm_wlan_get_oob_irq(); ++ AP6210_DEBUG("irq=%d, flags=0x%08lx\n", host_oob_irq, *irq_flags_ptr); ++#else ++#if defined(CUSTOM_OOB_GPIO_NUM) ++ if (dhd_oob_gpio_num < 0) { ++ dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM; ++ } ++#endif /* CUSTOMER_OOB_GPIO_NUM */ ++ ++ if (dhd_oob_gpio_num < 0) { ++ AP6210_ERR("%s: ERROR customer specific Host GPIO is NOT defined \n", ++ __FUNCTION__); ++ return (dhd_oob_gpio_num); ++ } ++ ++ AP6210_ERR("%s: customer specific Host GPIO number is (%d)\n", ++ __FUNCTION__, dhd_oob_gpio_num); ++ ++#if defined CUSTOMER_HW ++ AP6210_ERR("%s: should not be here!\n", __FUNCTION__); ++#elif defined CUSTOMER_HW3 ++ gpio_request(dhd_oob_gpio_num, "oob irq"); ++ host_oob_irq = gpio_to_irq(dhd_oob_gpio_num); ++ gpio_direction_input(dhd_oob_gpio_num); ++#endif /* CUSTOMER_HW */ ++#endif ++ ++ return (host_oob_irq); ++} ++#endif ++ ++/* Customer function to control hw specific wlan gpios */ ++void ++dhd_customer_gpio_wlan_ctrl(int onoff) ++{ ++ static int sdc_id = 3; ++ ++ switch (onoff) { ++ case WLAN_RESET_OFF: ++ AP6210_DEBUG("%s: call customer specific GPIO to insert WLAN RESET\n", ++ __FUNCTION__); ++#ifdef CUSTOMER_HW ++ ap6210_gpio_wifi_power(0); ++#endif /* CUSTOMER_HW */ ++#if defined(CUSTOMER_HW2) ++ wifi_set_power(0, 0); ++#endif ++ mdelay(100); ++ AP6210_ERR("WLAN placed in RESET\n"); ++ break; ++ ++ case WLAN_RESET_ON: ++ AP6210_DEBUG("%s: callc customer specific GPIO to remove WLAN RESET\n", ++ __FUNCTION__); ++#ifdef CUSTOMER_HW ++ ap6210_gpio_wifi_power(1); ++#endif /* CUSTOMER_HW */ ++#if defined(CUSTOMER_HW2) ++ wifi_set_power(1, 0); ++#endif ++ mdelay(100); ++ AP6210_ERR("WLAN going back to live\n"); ++ break; ++ ++ case WLAN_POWER_OFF: ++ AP6210_DEBUG("%s: call customer specific GPIO to turn off WL_REG_ON\n", ++ __FUNCTION__); ++#ifdef CUSTOMER_HW ++ ap6210_gpio_wifi_power(0); ++ sunximmc_rescan_card(sdc_id, 0); ++#endif /* CUSTOMER_HW */ ++ AP6210_ERR("WLAN placed in POWER OFF\n"); ++ break; ++ ++ case WLAN_POWER_ON: ++ AP6210_DEBUG("%s: call customer specific GPIO to turn on WL_REG_ON\n", ++ __FUNCTION__); ++#ifdef CUSTOMER_HW ++ ap6210_gpio_wifi_power(1); ++ sunximmc_rescan_card(sdc_id, 1); ++ /* Lets customer power to get stable */ ++#endif /* CUSTOMER_HW */ ++ mdelay(100); ++ AP6210_ERR("WLAN placed in POWER ON\n"); ++ break; ++ } ++} ++ ++#ifdef GET_CUSTOM_MAC_ENABLE ++/* Function to get custom MAC address */ ++int ++dhd_custom_get_mac_address(unsigned char *buf) ++{ ++ int ret = 0; ++ ++ AP6210_DEBUG("%s Enter\n", __FUNCTION__); ++ if (!buf) ++ return -EINVAL; ++ ++ /* Customer access to MAC address stored outside of DHD driver */ ++#if defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) ++ ret = wifi_get_mac_addr(buf); ++#endif ++ ++#ifdef EXAMPLE_GET_MAC ++ /* EXAMPLE code */ ++ { ++ struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}}; ++ bcopy((char *)&ea_example, buf, sizeof(struct ether_addr)); ++ } ++#endif /* EXAMPLE_GET_MAC */ ++ ++ return ret; ++} ++#endif /* GET_CUSTOM_MAC_ENABLE */ ++ ++/* Customized Locale table : OPTIONAL feature */ ++const struct cntry_locales_custom translate_custom_table[] = { ++/* Table should be filled out based on custom platform regulatory requirement */ ++#ifdef EXAMPLE_TABLE ++ {"", "XY", 4}, /* Universal if Country code is unknown or empty */ ++ {"US", "US", 69}, /* input ISO "US" to : US regrev 69 */ ++ {"CA", "US", 69}, /* input ISO "CA" to : US regrev 69 */ ++ {"EU", "EU", 5}, /* European union countries to : EU regrev 05 */ ++ {"AT", "EU", 5}, ++ {"BE", "EU", 5}, ++ {"BG", "EU", 5}, ++ {"CY", "EU", 5}, ++ {"CZ", "EU", 5}, ++ {"DK", "EU", 5}, ++ {"EE", "EU", 5}, ++ {"FI", "EU", 5}, ++ {"FR", "EU", 5}, ++ {"DE", "EU", 5}, ++ {"GR", "EU", 5}, ++ {"HU", "EU", 5}, ++ {"IE", "EU", 5}, ++ {"IT", "EU", 5}, ++ {"LV", "EU", 5}, ++ {"LI", "EU", 5}, ++ {"LT", "EU", 5}, ++ {"LU", "EU", 5}, ++ {"MT", "EU", 5}, ++ {"NL", "EU", 5}, ++ {"PL", "EU", 5}, ++ {"PT", "EU", 5}, ++ {"RO", "EU", 5}, ++ {"SK", "EU", 5}, ++ {"SI", "EU", 5}, ++ {"ES", "EU", 5}, ++ {"SE", "EU", 5}, ++ {"GB", "EU", 5}, ++ {"KR", "XY", 3}, ++ {"AU", "XY", 3}, ++ {"CN", "XY", 3}, /* input ISO "CN" to : XY regrev 03 */ ++ {"TW", "XY", 3}, ++ {"AR", "XY", 3}, ++ {"MX", "XY", 3}, ++ {"IL", "IL", 0}, ++ {"CH", "CH", 0}, ++ {"TR", "TR", 0}, ++ {"NO", "NO", 0}, ++#endif /* EXMAPLE_TABLE */ ++}; ++ ++ ++/* Customized Locale convertor ++* input : ISO 3166-1 country abbreviation ++* output: customized cspec ++*/ ++void get_customized_country_code(char *country_iso_code, wl_country_t *cspec) ++{ ++#if defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) ++ ++ struct cntry_locales_custom *cloc_ptr; ++ ++ if (!cspec) ++ return; ++ ++ cloc_ptr = wifi_get_country_code(country_iso_code); ++ if (cloc_ptr) { ++ strlcpy(cspec->ccode, cloc_ptr->custom_locale, WLC_CNTRY_BUF_SZ); ++ cspec->rev = cloc_ptr->custom_locale_rev; ++ } ++ return; ++#else ++ int size, i; ++ ++ size = ARRAYSIZE(translate_custom_table); ++ ++ if (cspec == 0) ++ return; ++ ++ if (size == 0) ++ return; ++ ++ for (i = 0; i < size; i++) { ++ if (strcmp(country_iso_code, translate_custom_table[i].iso_abbrev) == 0) { ++ memcpy(cspec->ccode, ++ translate_custom_table[i].custom_locale, WLC_CNTRY_BUF_SZ); ++ cspec->rev = translate_custom_table[i].custom_locale_rev; ++ return; ++ } ++ } ++#ifdef EXAMPLE_TABLE ++ /* if no country code matched return first universal code from translate_custom_table */ ++ memcpy(cspec->ccode, translate_custom_table[0].custom_locale, WLC_CNTRY_BUF_SZ); ++ cspec->rev = translate_custom_table[0].custom_locale_rev; ++#endif /* EXMAPLE_TABLE */ ++ return; ++#endif /* defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) */ ++} +diff --git a/drivers/net/wireless/ap6210/dhd_dbg.h b/drivers/net/wireless/ap6210/dhd_dbg.h +new file mode 100755 +index 0000000..67cd2e5 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_dbg.h +@@ -0,0 +1,79 @@ ++/* ++ * Debug/trace/assert driver definitions for Dongle Host Driver. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhd_dbg.h 353490 2012-08-27 21:10:02Z $ ++ */ ++ ++#ifndef _dhd_dbg_ ++#define _dhd_dbg_ ++ ++#define USE_NET_RATELIMIT net_ratelimit() ++ ++#if defined(DHD_DEBUG) ++ ++#define DHD_ERROR_ON() (dhd_msg_level & DHD_ERROR_VAL) ++#define DHD_TRACE_ON() (dhd_msg_level & DHD_TRACE_VAL) ++#define DHD_INFO_ON() (dhd_msg_level & DHD_INFO_VAL) ++#define DHD_DATA_ON() (dhd_msg_level & DHD_DATA_VAL) ++#define DHD_CTL_ON() (dhd_msg_level & DHD_CTL_VAL) ++#define DHD_TIMER_ON() (dhd_msg_level & DHD_TIMER_VAL) ++#define DHD_HDRS_ON() (dhd_msg_level & DHD_HDRS_VAL) ++#define DHD_BYTES_ON() (dhd_msg_level & DHD_BYTES_VAL) ++#define DHD_INTR_ON() (dhd_msg_level & DHD_INTR_VAL) ++#define DHD_GLOM_ON() (dhd_msg_level & DHD_GLOM_VAL) ++#define DHD_EVENT_ON() (dhd_msg_level & DHD_EVENT_VAL) ++#define DHD_BTA_ON() (dhd_msg_level & DHD_BTA_VAL) ++#define DHD_ISCAN_ON() (dhd_msg_level & DHD_ISCAN_VAL) ++#define DHD_ARPOE_ON() (dhd_msg_level & DHD_ARPOE_VAL) ++#define DHD_REORDER_ON() (dhd_msg_level & DHD_REORDER_VAL) ++ ++#else /* defined(BCMDBG) || defined(DHD_DEBUG) */ ++ ++#define DHD_ERROR_ON() 0 ++#define DHD_TRACE_ON() 0 ++#define DHD_INFO_ON() 0 ++#define DHD_DATA_ON() 0 ++#define DHD_CTL_ON() 0 ++#define DHD_TIMER_ON() 0 ++#define DHD_HDRS_ON() 0 ++#define DHD_BYTES_ON() 0 ++#define DHD_INTR_ON() 0 ++#define DHD_GLOM_ON() 0 ++#define DHD_EVENT_ON() 0 ++#define DHD_BTA_ON() 0 ++#define DHD_ISCAN_ON() 0 ++#define DHD_ARPOE_ON() 0 ++#define DHD_REORDER_ON() 0 ++#endif ++ ++#define DHD_LOG(args) ++ ++#define DHD_BLOG(cp, size) ++ ++#define DHD_NONE(args) ++extern int dhd_msg_level; ++ ++/* Defines msg bits */ ++#include ++ ++#endif /* _dhd_dbg_ */ +diff --git a/drivers/net/wireless/ap6210/dhd_gpio.c b/drivers/net/wireless/ap6210/dhd_gpio.c +new file mode 100755 +index 0000000..dae0dd3 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_gpio.c +@@ -0,0 +1,47 @@ ++/* ++* Customer code to add GPIO control during WLAN start/stop ++* Copyright (C) 1999-2011, Broadcom Corporation ++* ++* Unless you and Broadcom execute a separate written software license ++* agreement governing use of this software, this software is licensed to you ++* under the terms of the GNU General Public License version 2 (the "GPL"), ++* available at http://www.broadcom.com/licenses/GPLv2.php, with the ++* following added to such license: ++* ++* As a special exception, the copyright holders of this software give you ++* permission to link this software with independent modules, and to copy and ++* distribute the resulting executable under terms of your choice, provided that ++* you also meet, for each linked independent module, the terms and conditions of ++* the license of that module. An independent module is a module which is not ++* derived from this software. The special exception does not apply to any ++* modifications of the software. ++* ++* Notwithstanding the above, under no circumstances may you combine this ++* software in any way with any other Broadcom software provided under a license ++* other than the GPL, without Broadcom's express prior written consent. ++* ++* $Id: dhd_custom_gpio.c,v 1.2.42.1 2010-10-19 00:41:09 Exp $ ++*/ ++ ++#include ++ ++#include ++#include ++ ++#ifdef CUSTOMER_HW ++ ++extern int __gpio_to_irq(unsigned gpio); ++extern int gpio_direction_input(unsigned gpio); ++extern int gpio_request(unsigned gpio, const char *label); ++extern void gpio_free(unsigned gpio); ++ ++#ifdef CUSTOMER_OOB ++extern int wl_host_wake_irqno; ++int bcm_wlan_get_oob_irq(void) ++{ ++ return wl_host_wake_irqno; ++} ++#endif ++ ++ ++#endif /* CUSTOMER_HW */ +diff --git a/drivers/net/wireless/ap6210/dhd_ip.c b/drivers/net/wireless/ap6210/dhd_ip.c +new file mode 100755 +index 0000000..05abc93 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_ip.c +@@ -0,0 +1,111 @@ ++/* ++ * IP Packet Parser Module. ++ * ++ * Copyright (C) 1999-2013, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id$ ++ */ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++/* special values */ ++/* 802.3 llc/snap header */ ++static const uint8 llc_snap_hdr[SNAP_HDR_LEN] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; ++ ++pkt_frag_t pkt_frag_info(osl_t *osh, void *p) ++{ ++ uint8 *frame; ++ int length; ++ uint8 *pt; /* Pointer to type field */ ++ uint16 ethertype; ++ struct ipv4_hdr *iph; /* IP frame pointer */ ++ int ipl; /* IP frame length */ ++ uint16 iph_frag; ++ ++ ASSERT(osh && p); ++ ++ frame = PKTDATA(osh, p); ++ length = PKTLEN(osh, p); ++ ++ /* Process Ethernet II or SNAP-encapsulated 802.3 frames */ ++ if (length < ETHER_HDR_LEN) { ++ AP6210_DEBUG("%s: short eth frame (%d)\n", __FUNCTION__, length); ++ return DHD_PKT_FRAG_NONE; ++ } else if (ntoh16(*(uint16 *)(frame + ETHER_TYPE_OFFSET)) >= ETHER_TYPE_MIN) { ++ /* Frame is Ethernet II */ ++ pt = frame + ETHER_TYPE_OFFSET; ++ } else if (length >= ETHER_HDR_LEN + SNAP_HDR_LEN + ETHER_TYPE_LEN && ++ !bcmp(llc_snap_hdr, frame + ETHER_HDR_LEN, SNAP_HDR_LEN)) { ++ pt = frame + ETHER_HDR_LEN + SNAP_HDR_LEN; ++ } else { ++ AP6210_DEBUG("%s: non-SNAP 802.3 frame\n", __FUNCTION__); ++ return DHD_PKT_FRAG_NONE; ++ } ++ ++ ethertype = ntoh16(*(uint16 *)pt); ++ ++ /* Skip VLAN tag, if any */ ++ if (ethertype == ETHER_TYPE_8021Q) { ++ pt += VLAN_TAG_LEN; ++ ++ if (pt + ETHER_TYPE_LEN > frame + length) { ++ AP6210_DEBUG("%s: short VLAN frame (%d)\n", __FUNCTION__, length); ++ return DHD_PKT_FRAG_NONE; ++ } ++ ++ ethertype = ntoh16(*(uint16 *)pt); ++ } ++ ++ if (ethertype != ETHER_TYPE_IP) { ++ AP6210_DEBUG("%s: non-IP frame (ethertype 0x%x, length %d)\n", ++ __FUNCTION__, ethertype, length); ++ return DHD_PKT_FRAG_NONE; ++ } ++ ++ iph = (struct ipv4_hdr *)(pt + ETHER_TYPE_LEN); ++ ipl = length - (pt + ETHER_TYPE_LEN - frame); ++ ++ /* We support IPv4 only */ ++ if ((ipl < IPV4_OPTIONS_OFFSET) || (IP_VER(iph) != IP_VER_4)) { ++ AP6210_DEBUG("%s: short frame (%d) or non-IPv4\n", __FUNCTION__, ipl); ++ return DHD_PKT_FRAG_NONE; ++ } ++ ++ iph_frag = ntoh16(iph->frag); ++ ++ if (iph_frag & IPV4_FRAG_DONT) { ++ return DHD_PKT_FRAG_NONE; ++ } else if ((iph_frag & IPV4_FRAG_MORE) == 0) { ++ return DHD_PKT_FRAG_LAST; ++ } else { ++ return (iph_frag & IPV4_FRAG_OFFSET_MASK)? DHD_PKT_FRAG_CONT : DHD_PKT_FRAG_FIRST; ++ } ++} +diff --git a/drivers/net/wireless/ap6210/dhd_ip.h b/drivers/net/wireless/ap6210/dhd_ip.h +new file mode 100755 +index 0000000..ceb3877 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_ip.h +@@ -0,0 +1,42 @@ ++/* ++ * Header file describing the common ip parser function. ++ * ++ * Provides type definitions and function prototypes used to parse ip packet. ++ * ++ * Copyright (C) 1999-2013, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id$ ++ */ ++ ++#ifndef _dhd_ip_h_ ++#define _dhd_ip_h_ ++ ++typedef enum pkt_frag ++{ ++ DHD_PKT_FRAG_NONE = 0, ++ DHD_PKT_FRAG_FIRST, ++ DHD_PKT_FRAG_CONT, ++ DHD_PKT_FRAG_LAST ++} pkt_frag_t; ++ ++extern pkt_frag_t pkt_frag_info(osl_t *osh, void *p); ++ ++#endif /* _dhd_ip_h_ */ +diff --git a/drivers/net/wireless/ap6210/dhd_linux.c b/drivers/net/wireless/ap6210/dhd_linux.c +new file mode 100755 +index 0000000..28fe811 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_linux.c +@@ -0,0 +1,6152 @@ ++/* ++ * Broadcom Dongle Host Driver (DHD), Linux-specific network interface ++ * Basically selected code segments from usb-cdc.c and usb-rndis.c ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhd_linux.c 374275 2012-12-12 11:44:18Z $ ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef CONFIG_HAS_WAKELOCK ++#include ++#endif ++#ifdef WL_CFG80211 ++#include ++#endif ++ ++#ifdef WLBTAMP ++#include ++#include ++#include ++#endif ++ ++#include ++#include ++ ++#ifdef WLMEDIA_HTSF ++#include ++#include ++ ++#define HTSF_MINLEN 200 /* min. packet length to timestamp */ ++#define HTSF_BUS_DELAY 150 /* assume a fix propagation in us */ ++#define TSMAX 1000 /* max no. of timing record kept */ ++#define NUMBIN 34 ++static uint32 tsidx = 0; ++static uint32 htsf_seqnum = 0; ++uint32 tsfsync; ++struct timeval tsync; ++static uint32 tsport = 5010; ++ ++typedef struct histo_ { ++ uint32 bin[NUMBIN]; ++} histo_t; ++ ++#if !ISPOWEROF2(DHD_SDALIGN) ++#error DHD_SDALIGN is not a power of 2! ++#endif ++ ++static histo_t vi_d1, vi_d2, vi_d3, vi_d4; ++#endif /* WLMEDIA_HTSF */ ++ ++#if defined(PKT_FILTER_SUPPORT) ++#endif /* PKT_FILTER_SUPPORT */ ++ ++#if defined(SOFTAP) ++extern bool ap_cfg_running; ++extern bool ap_fw_loaded; ++#endif ++ ++/* enable HOSTIP cache update from the host side when an eth0:N is up */ ++#define AOE_IP_ALIAS_SUPPORT 1 ++ ++#ifdef BCM_FD_AGGR ++#include ++#include ++#endif ++#ifdef PROP_TXSTATUS ++#include ++#include ++#endif ++ ++#include ++ ++#ifdef ARP_OFFLOAD_SUPPORT ++void aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add, int idx); ++static int dhd_device_event(struct notifier_block *this, ++ unsigned long event, ++ void *ptr); ++ ++static struct notifier_block dhd_notifier = { ++ .notifier_call = dhd_device_event ++}; ++#endif /* ARP_OFFLOAD_SUPPORT */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) ++#include ++volatile bool dhd_mmc_suspend = FALSE; ++DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ ++ ++#if defined(OOB_INTR_ONLY) ++extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable); ++#endif ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (1) ++static void dhd_hang_process(struct work_struct *work); ++#endif ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++MODULE_LICENSE("GPL v2"); ++#endif /* LinuxVer */ ++ ++#include ++ ++#ifdef BCM_FD_AGGR ++#define DBUS_RX_BUFFER_SIZE_DHD(net) (BCM_RPC_TP_DNGL_AGG_MAX_BYTE) ++#else ++#ifndef PROP_TXSTATUS ++#define DBUS_RX_BUFFER_SIZE_DHD(net) (net->mtu + net->hard_header_len + dhd->pub.hdrlen) ++#else ++#define DBUS_RX_BUFFER_SIZE_DHD(net) (net->mtu + net->hard_header_len + dhd->pub.hdrlen + 128) ++#endif ++#endif /* BCM_FD_AGGR */ ++ ++#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15) ++const char * ++print_tainted() ++{ ++ return ""; ++} ++#endif /* LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15) */ ++ ++/* Linux wireless extension support */ ++#if defined(CONFIG_WIRELESS_EXT) ++#include ++extern wl_iw_extra_params_t g_wl_iw_params; ++#endif /* defined(CONFIG_WIRELESS_EXT) */ ++ ++#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) ++#include ++#endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */ ++ ++extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd); ++ ++#ifdef PKT_FILTER_SUPPORT ++extern void dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg); ++extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode); ++#endif ++ ++#ifdef READ_MACADDR ++extern int dhd_read_macaddr(struct dhd_info *dhd, struct ether_addr *mac); ++#endif ++#ifdef RDWR_MACADDR ++extern int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp, struct ether_addr *mac); ++extern int dhd_write_rdwr_macaddr(struct ether_addr *mac); ++#endif ++#ifdef WRITE_MACADDR ++extern int dhd_write_macaddr(struct ether_addr *mac); ++#endif ++#ifdef GET_MAC_FROM_OTP ++extern int dhd_check_module_mac(dhd_pub_t *dhd, struct ether_addr *mac); ++#endif ++#ifdef MIMO_ANT_SETTING ++extern int dhd_sel_ant_from_file(dhd_pub_t *dhd); ++#endif ++ ++#ifdef GLOBALCONFIG_WLAN_COUNTRY_CODE ++int dhd_customer_set_country(dhd_pub_t *dhd); ++#endif ++ ++/* Interface control information */ ++typedef struct dhd_if { ++ struct dhd_info *info; /* back pointer to dhd_info */ ++ /* OS/stack specifics */ ++ struct net_device *net; ++ struct net_device_stats stats; ++ int idx; /* iface idx in dongle */ ++ dhd_if_state_t state; /* interface state */ ++ uint subunit; /* subunit */ ++ uint8 mac_addr[ETHER_ADDR_LEN]; /* assigned MAC address */ ++ bool attached; /* Delayed attachment when unset */ ++ bool txflowcontrol; /* Per interface flow control indicator */ ++ char name[IFNAMSIZ+1]; /* linux interface name */ ++ uint8 bssidx; /* bsscfg index for the interface */ ++ bool set_multicast; ++ bool event2cfg80211; /* To determine if pass event to cfg80211 */ ++} dhd_if_t; ++ ++#ifdef WLMEDIA_HTSF ++typedef struct { ++ uint32 low; ++ uint32 high; ++} tsf_t; ++ ++typedef struct { ++ uint32 last_cycle; ++ uint32 last_sec; ++ uint32 last_tsf; ++ uint32 coef; /* scaling factor */ ++ uint32 coefdec1; /* first decimal */ ++ uint32 coefdec2; /* second decimal */ ++} htsf_t; ++ ++typedef struct { ++ uint32 t1; ++ uint32 t2; ++ uint32 t3; ++ uint32 t4; ++} tstamp_t; ++ ++static tstamp_t ts[TSMAX]; ++static tstamp_t maxdelayts; ++static uint32 maxdelay = 0, tspktcnt = 0, maxdelaypktno = 0; ++ ++#endif /* WLMEDIA_HTSF */ ++ ++/* Local private structure (extension of pub) */ ++typedef struct dhd_info { ++#if defined(CONFIG_WIRELESS_EXT) ++ wl_iw_t iw; /* wireless extensions state (must be first) */ ++#endif /* defined(CONFIG_WIRELESS_EXT) */ ++ ++ dhd_pub_t pub; ++ ++ /* For supporting multiple interfaces */ ++ dhd_if_t *iflist[DHD_MAX_IFS]; ++ ++ struct semaphore proto_sem; ++#ifdef PROP_TXSTATUS ++ spinlock_t wlfc_spinlock; ++#endif /* PROP_TXSTATUS */ ++#ifdef WLMEDIA_HTSF ++ htsf_t htsf; ++#endif ++ wait_queue_head_t ioctl_resp_wait; ++ struct timer_list timer; ++ bool wd_timer_valid; ++ struct tasklet_struct tasklet; ++ spinlock_t sdlock; ++ spinlock_t txqlock; ++ spinlock_t dhd_lock; ++#ifdef DHDTHREAD ++ /* Thread based operation */ ++ bool threads_only; ++ struct semaphore sdsem; ++ ++ tsk_ctl_t thr_dpc_ctl; ++ tsk_ctl_t thr_wdt_ctl; ++#endif /* DHDTHREAD */ ++ bool dhd_tasklet_create; ++ tsk_ctl_t thr_sysioc_ctl; ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ struct work_struct work_hang; ++#endif ++ ++ /* Wakelocks */ ++#if defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ struct wake_lock *wl_wifi; /* Wifi wakelock */ ++ struct wake_lock *wl_rxwake; /* Wifi rx wakelock */ ++ struct wake_lock *wl_ctrlwake; /* Wifi ctrl wakelock */ ++ struct wake_lock *wl_wdwake; /* Wifi wd wakelock */ ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ /* net_device interface lock, prevent race conditions among net_dev interface ++ * calls and wifi_on or wifi_off ++ */ ++ struct mutex dhd_net_if_mutex; ++ struct mutex dhd_suspend_mutex; ++#endif ++ spinlock_t wakelock_spinlock; ++ int wakelock_counter; ++ int wakelock_wd_counter; ++ int wakelock_rx_timeout_enable; ++ int wakelock_ctrl_timeout_enable; ++ ++ /* Thread to issue ioctl for multicast */ ++ unsigned char set_macaddress; ++ struct ether_addr macvalue; ++ wait_queue_head_t ctrl_wait; ++ atomic_t pend_8021x_cnt; ++ dhd_attach_states_t dhd_state; ++ ++#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) ++ struct early_suspend early_suspend; ++#endif /* CONFIG_HAS_EARLYSUSPEND && defined(DHD_USE_EARLYSUSPEND) */ ++ ++#ifdef ARP_OFFLOAD_SUPPORT ++ u32 pend_ipaddr; ++#endif /* ARP_OFFLOAD_SUPPORT */ ++#ifdef BCM_FD_AGGR ++ void *rpc_th; ++ void *rpc_osh; ++ struct timer_list rpcth_timer; ++ bool rpcth_timer_active; ++ bool fdaggr; ++#endif ++} dhd_info_t; ++ ++/* Flag to indicate if we should download firmware on driver load */ ++uint dhd_download_fw_on_driverload = TRUE; ++ ++/* Definitions to provide path to the firmware and nvram ++ * example nvram_path[MOD_PARAM_PATHLEN]="/projects/wlan/nvram.txt" ++ */ ++char firmware_path[MOD_PARAM_PATHLEN]; ++char nvram_path[MOD_PARAM_PATHLEN]; ++ ++/* information string to keep firmware, chio, cheip version info visiable from log */ ++char info_string[MOD_PARAM_INFOLEN]; ++module_param_string(info_string, info_string, MOD_PARAM_INFOLEN, 0444); ++ ++int op_mode = 0; ++int disable_proptx = 0; ++module_param(op_mode, int, 0644); ++extern int wl_control_wl_start(struct net_device *dev); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++struct semaphore dhd_registration_sem; ++struct semaphore dhd_chipup_sem; ++int dhd_registration_check = FALSE; ++ ++#define DHD_REGISTRATION_TIMEOUT 12000 /* msec : allowed time to finished dhd registration */ ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++ ++/* Spawn a thread for system ioctls (set mac, set mcast) */ ++uint dhd_sysioc = TRUE; ++module_param(dhd_sysioc, uint, 0); ++ ++/* Error bits */ ++module_param(dhd_msg_level, int, 0); ++#if defined(CONFIG_WIRELESS_EXT) ++module_param(iw_msg_level, int, 0); ++#endif ++#ifdef WL_CFG80211 ++module_param(wl_dbg_level, int, 0); ++#endif ++//module_param(android_msg_level, int, 0); ++ ++/* Disable Prop tx */ ++module_param(disable_proptx, int, 0644); ++ ++/* load firmware and/or nvram values from the filesystem */ ++module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0660); ++module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0); ++ ++/* Watchdog interval */ ++uint dhd_watchdog_ms = 10; ++module_param(dhd_watchdog_ms, uint, 0); ++ ++#if defined(DHD_DEBUG) ++/* Console poll interval */ ++uint dhd_console_ms = 0; ++module_param(dhd_console_ms, uint, 0644); ++#endif /* defined(DHD_DEBUG) */ ++ ++uint dhd_slpauto = TRUE; ++module_param(dhd_slpauto, uint, 0); ++ ++/* ARP offload agent mode : Enable ARP Host Auto-Reply and ARP Peer Auto-Reply */ ++uint dhd_arp_mode = ARP_OL_AGENT | ARP_OL_PEER_AUTO_REPLY; ++module_param(dhd_arp_mode, uint, 0); ++ ++/* ARP offload enable */ ++uint dhd_arp_enable = TRUE; ++module_param(dhd_arp_enable, uint, 0); ++ ++#ifdef PKT_FILTER_SUPPORT ++/* Global Pkt filter enable control */ ++uint dhd_pkt_filter_enable = TRUE; ++module_param(dhd_pkt_filter_enable, uint, 0); ++#endif ++ ++/* Pkt filter init setup */ ++uint dhd_pkt_filter_init = 0; ++module_param(dhd_pkt_filter_init, uint, 0); ++ ++/* Pkt filter mode control */ ++#ifdef GAN_LITE_NAT_KEEPALIVE_FILTER ++uint dhd_master_mode = FALSE; ++#else ++uint dhd_master_mode = TRUE; ++#endif /* GAL_LITE_NAT_KEEPALIVE_FILTER */ ++module_param(dhd_master_mode, uint, 0); ++ ++#ifdef DHDTHREAD ++int dhd_watchdog_prio = 0; ++module_param(dhd_watchdog_prio, int, 0); ++ ++/* DPC thread priority */ ++int dhd_dpc_prio = CUSTOM_DPC_PRIO_SETTING; ++module_param(dhd_dpc_prio, int, 0); ++ ++/* DPC thread priority, -1 to use tasklet */ ++extern int dhd_dongle_memsize; ++module_param(dhd_dongle_memsize, int, 0); ++#endif /* DHDTHREAD */ ++/* Control fw roaming */ ++uint dhd_roam_disable = 0; ++ ++/* Control radio state */ ++uint dhd_radio_up = 1; ++ ++/* Network inteface name */ ++char iface_name[IFNAMSIZ] = {'\0'}; ++module_param_string(iface_name, iface_name, IFNAMSIZ, 0); ++ ++/* The following are specific to the SDIO dongle */ ++ ++/* IOCTL response timeout */ ++int dhd_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT; ++ ++/* Idle timeout for backplane clock */ ++int dhd_idletime = DHD_IDLETIME_TICKS; ++module_param(dhd_idletime, int, 0); ++ ++/* Use polling */ ++uint dhd_poll = FALSE; ++module_param(dhd_poll, uint, 0); ++ ++/* Use interrupts */ ++uint dhd_intr = TRUE; ++module_param(dhd_intr, uint, 0); ++ ++/* SDIO Drive Strength (in milliamps) */ ++uint dhd_sdiod_drive_strength = 6; ++module_param(dhd_sdiod_drive_strength, uint, 0); ++ ++/* Tx/Rx bounds */ ++extern uint dhd_txbound; ++extern uint dhd_rxbound; ++module_param(dhd_txbound, uint, 0); ++module_param(dhd_rxbound, uint, 0); ++ ++/* Deferred transmits */ ++extern uint dhd_deferred_tx; ++module_param(dhd_deferred_tx, uint, 0); ++ ++#ifdef BCMDBGFS ++extern void dhd_dbg_init(dhd_pub_t *dhdp); ++extern void dhd_dbg_remove(void); ++#endif /* BCMDBGFS */ ++ ++/* ++ * the the 2 vars init at init time ++ *benn@cubietech.com ++ */ ++#define WL_HOST_WAKE_DEF_GPIO 86 ++int wl_host_wake_irqno = -1; ++int wl_host_wake = -1; ++ ++ ++#ifdef SDTEST ++/* Echo packet generator (pkts/s) */ ++uint dhd_pktgen = 0; ++module_param(dhd_pktgen, uint, 0); ++ ++/* Echo packet len (0 => sawtooth, max 2040) */ ++uint dhd_pktgen_len = 0; ++module_param(dhd_pktgen_len, uint, 0); ++#endif /* SDTEST */ ++ ++/* Version string to report */ ++#ifdef DHD_DEBUG ++#ifndef SRCBASE ++#define SRCBASE "drivers/net/wireless/ap6210" ++#endif ++#define DHD_COMPILED "\nCompiled in " SRCBASE ++#else ++#define DHD_COMPILED ++#endif /* DHD_DEBUG */ ++ ++static char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR "."; ++#ifdef DHD_DEBUG ++static char dhd_version_info[] = "Compiled in " SRCBASE " on " __DATE__ " at " __TIME__ "."; ++#endif ++ ++static void dhd_net_if_lock_local(dhd_info_t *dhd); ++static void dhd_net_if_unlock_local(dhd_info_t *dhd); ++static void dhd_suspend_lock(dhd_pub_t *dhdp); ++static void dhd_suspend_unlock(dhd_pub_t *dhdp); ++ ++#ifdef WLMEDIA_HTSF ++void htsf_update(dhd_info_t *dhd, void *data); ++tsf_t prev_tsf, cur_tsf; ++ ++uint32 dhd_get_htsf(dhd_info_t *dhd, int ifidx); ++static int dhd_ioctl_htsf_get(dhd_info_t *dhd, int ifidx); ++static void dhd_dump_latency(void); ++static void dhd_htsf_addtxts(dhd_pub_t *dhdp, void *pktbuf); ++static void dhd_htsf_addrxts(dhd_pub_t *dhdp, void *pktbuf); ++static void dhd_dump_htsfhisto(histo_t *his, char *s); ++#endif /* WLMEDIA_HTSF */ ++ ++/* Monitor interface */ ++int dhd_monitor_init(void *dhd_pub); ++int dhd_monitor_uninit(void); ++ ++ ++#if defined(CONFIG_WIRELESS_EXT) ++struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev); ++#endif /* defined(CONFIG_WIRELESS_EXT) */ ++ ++static void dhd_dpc(ulong data); ++/* forward decl */ ++extern int dhd_wait_pend8021x(struct net_device *dev); ++ ++#ifdef TOE ++#ifndef BDC ++#error TOE requires BDC ++#endif /* !BDC */ ++static int dhd_toe_get(dhd_info_t *dhd, int idx, uint32 *toe_ol); ++static int dhd_toe_set(dhd_info_t *dhd, int idx, uint32 toe_ol); ++#endif /* TOE */ ++ ++static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, ++ wl_event_msg_t *event_ptr, void **data_ptr); ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) ++static int dhd_sleep_pm_callback(struct notifier_block *nfb, unsigned long action, void *ignored) ++{ ++ int ret = NOTIFY_DONE; ++ ++#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) || (LINUX_VERSION_CODE <= \ ++ KERNEL_VERSION(2, 6, 39)) ++ switch (action) { ++ case PM_HIBERNATION_PREPARE: ++ case PM_SUSPEND_PREPARE: ++ dhd_mmc_suspend = TRUE; ++ ret = NOTIFY_OK; ++ break; ++ case PM_POST_HIBERNATION: ++ case PM_POST_SUSPEND: ++ dhd_mmc_suspend = FALSE; ++ ret = NOTIFY_OK; ++ break; ++ } ++ smp_mb(); ++#endif ++ return ret; ++} ++ ++static struct notifier_block dhd_sleep_pm_notifier = { ++ .notifier_call = dhd_sleep_pm_callback, ++ .priority = 10 ++}; ++extern int register_pm_notifier(struct notifier_block *nb); ++extern int unregister_pm_notifier(struct notifier_block *nb); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ ++ ++void dhd_set_packet_filter(dhd_pub_t *dhd) ++{ ++#ifdef PKT_FILTER_SUPPORT ++ int i; ++ ++ AP6210_DEBUG("%s: enter\n", __FUNCTION__); ++ if (dhd_pkt_filter_enable) { ++ for (i = 0; i < dhd->pktfilter_count; i++) { ++ dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]); ++ } ++ } ++#endif /* PKT_FILTER_SUPPORT */ ++} ++ ++void dhd_enable_packet_filter(int value, dhd_pub_t *dhd) ++{ ++#ifdef PKT_FILTER_SUPPORT ++ int i; ++ ++ AP6210_DEBUG("%s: enter, value = %d\n", __FUNCTION__, value); ++ /* 1 - Enable packet filter, only allow unicast packet to send up */ ++ /* 0 - Disable packet filter */ ++ if (dhd_pkt_filter_enable && (!value || ++ (dhd_support_sta_mode(dhd) && !dhd->dhcp_in_progress))) { ++ for (i = 0; i < dhd->pktfilter_count; i++) { ++#ifdef PASS_ARP_PACKET ++ if (value && (i == dhd->pktfilter_count -1) && ++ !(dhd->op_mode & (DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE))) { ++ AP6210_DEBUG("Do not turn on ARP white list pkt filter:" ++ "val %d, cnt %d, op_mode 0x%x\n", ++ value, i, dhd->op_mode); ++ continue; ++ } ++#endif ++ dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i], ++ value, dhd_master_mode); ++ } ++ } ++#endif /* PKT_FILTER_SUPPORT */ ++} ++ ++static int dhd_set_suspend(int value, dhd_pub_t *dhd) ++{ ++#if !defined(SUPPORT_PM2_ONLY) ++ int power_mode = PM_MAX; ++#endif ++ /* wl_pkt_filter_enable_t enable_parm; */ ++ char iovbuf[32]; ++ int bcn_li_dtim = 0; /* Default bcn_li_dtim in resume mode is 0 */ ++#ifndef DISABLE_FW_ROAM_SUSPEND ++ uint roamvar = 1; ++#endif ++#ifdef ENABLE_BCN_LI_BCN_WAKEUP ++ int bcn_li_bcn; ++#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ ++#ifdef PASS_ALL_MCAST_PKTS ++ struct dhd_info *dhdinfo = dhd->info; ++ uint32 allmulti; ++ uint i; ++#endif /* PASS_ALL_MCAST_PKTS */ ++ ++ AP6210_DEBUG("%s: enter, value = %d in_suspend=%d\n", ++ __FUNCTION__, value, dhd->in_suspend); ++ ++ dhd_suspend_lock(dhd); ++ if (dhd && dhd->up) { ++ if (value && dhd->in_suspend) { ++#ifdef PKT_FILTER_SUPPORT ++ dhd->early_suspended = 1; ++#endif ++ /* Kernel suspended */ ++ AP6210_ERR("%s: force extra Suspend setting\n", __FUNCTION__); ++ ++#if !defined(SUPPORT_PM2_ONLY) ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, ++ sizeof(power_mode), TRUE, 0); ++#endif ++ /* Enable packet filter, only allow unicast packet to send up */ ++ dhd_enable_packet_filter(1, dhd); ++#ifdef PASS_ALL_MCAST_PKTS ++ allmulti = 0; ++ bcm_mkiovar("allmulti", (char *)&allmulti, ++ 4, iovbuf, sizeof(iovbuf)); ++ for (i = 0; i < DHD_MAX_IFS; i++) { ++ if (dhdinfo->iflist[i] && dhdinfo->iflist[i]->net) ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, ++ sizeof(iovbuf), TRUE, i); ++ } ++#endif /* PASS_ALL_MCAST_PKTS */ ++ ++ /* If DTIM skip is set up as default, force it to wake ++ * each third DTIM for better power savings. Note that ++ * one side effect is a chance to miss BC/MC packet. ++ */ ++ bcn_li_dtim = dhd_get_suspend_bcn_li_dtim(dhd); ++ bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim, ++ 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++ ++#ifndef DISABLE_FW_ROAM_SUSPEND ++ /* Disable firmware roaming during suspend */ ++ bcm_mkiovar("roam_off", (char *)&roamvar, 4, ++ iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++#endif ++#ifdef ENABLE_BCN_LI_BCN_WAKEUP ++ bcn_li_bcn = 0; ++ bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn, ++ 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ ++ ++ } else { ++#ifdef PKT_FILTER_SUPPORT ++ dhd->early_suspended = 0; ++#endif ++ /* Kernel resumed */ ++ AP6210_ERR("%s: Remove extra suspend setting\n", __FUNCTION__); ++ ++#if !defined(SUPPORT_PM2_ONLY) ++ power_mode = PM_FAST; ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, ++ sizeof(power_mode), TRUE, 0); ++#endif ++ /* disable pkt filter */ ++ dhd_enable_packet_filter(0, dhd); ++#ifdef PASS_ALL_MCAST_PKTS ++ allmulti = 1; ++ bcm_mkiovar("allmulti", (char *)&allmulti, ++ 4, iovbuf, sizeof(iovbuf)); ++ for (i = 0; i < DHD_MAX_IFS; i++) { ++ if (dhdinfo->iflist[i] && dhdinfo->iflist[i]->net) ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, ++ sizeof(iovbuf), TRUE, i); ++ } ++#endif /* PASS_ALL_MCAST_PKTS */ ++ ++ /* restore pre-suspend setting for dtim_skip */ ++ bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim, ++ 4, iovbuf, sizeof(iovbuf)); ++ ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++#ifndef DISABLE_FW_ROAM_SUSPEND ++ roamvar = dhd_roam_disable; ++ bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, ++ sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++#endif ++#ifdef ENABLE_BCN_LI_BCN_WAKEUP ++ bcn_li_bcn = 1; ++ bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn, ++ 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ ++ ++ } ++ } ++ ++ dhd_suspend_unlock(dhd); ++ return 0; ++} ++ ++static int dhd_suspend_resume_helper(struct dhd_info *dhd, int val, int force) ++{ ++ dhd_pub_t *dhdp = &dhd->pub; ++ int ret = 0; ++ ++ DHD_OS_WAKE_LOCK(dhdp); ++ /* Set flag when early suspend was called */ ++ dhdp->in_suspend = val; ++ if ((force || !dhdp->suspend_disable_flag) && ++ dhd_support_sta_mode(dhdp)) ++ { ++ ret = dhd_set_suspend(val, dhdp); ++ } ++ ++ DHD_OS_WAKE_UNLOCK(dhdp); ++ return ret; ++} ++ ++#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) ++static void dhd_early_suspend(struct early_suspend *h) ++{ ++ struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend); ++ AP6210_DEBUG("%s: enter\n", __FUNCTION__); ++ ++ if (dhd) ++ dhd_suspend_resume_helper(dhd, 1, 0); ++} ++ ++static void dhd_late_resume(struct early_suspend *h) ++{ ++ struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend); ++ AP6210_DEBUG("%s: enter\n", __FUNCTION__); ++ ++ if (dhd) ++ dhd_suspend_resume_helper(dhd, 0, 0); ++} ++#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ ++ ++/* ++ * Generalized timeout mechanism. Uses spin sleep with exponential back-off until ++ * the sleep time reaches one jiffy, then switches over to task delay. Usage: ++ * ++ * dhd_timeout_start(&tmo, usec); ++ * while (!dhd_timeout_expired(&tmo)) ++ * if (poll_something()) ++ * break; ++ * if (dhd_timeout_expired(&tmo)) ++ * fatal(); ++ */ ++ ++void ++dhd_timeout_start(dhd_timeout_t *tmo, uint usec) ++{ ++ tmo->limit = usec; ++ tmo->increment = 0; ++ tmo->elapsed = 0; ++ tmo->tick = jiffies_to_usecs(1); ++} ++ ++int ++dhd_timeout_expired(dhd_timeout_t *tmo) ++{ ++ /* Does nothing the first call */ ++ if (tmo->increment == 0) { ++ tmo->increment = 1; ++ return 0; ++ } ++ ++ if (tmo->elapsed >= tmo->limit) ++ return 1; ++ ++ /* Add the delay that's about to take place */ ++ tmo->elapsed += tmo->increment; ++ ++ if (tmo->increment < tmo->tick) { ++ OSL_DELAY(tmo->increment); ++ tmo->increment *= 2; ++ if (tmo->increment > tmo->tick) ++ tmo->increment = tmo->tick; ++ } else { ++ wait_queue_head_t delay_wait; ++ DECLARE_WAITQUEUE(wait, current); ++ init_waitqueue_head(&delay_wait); ++ add_wait_queue(&delay_wait, &wait); ++ set_current_state(TASK_INTERRUPTIBLE); ++ schedule_timeout(1); ++ remove_wait_queue(&delay_wait, &wait); ++ set_current_state(TASK_RUNNING); ++ } ++ ++ return 0; ++} ++ ++int ++dhd_net2idx(dhd_info_t *dhd, struct net_device *net) ++{ ++ int i = 0; ++ ++ ASSERT(dhd); ++ while (i < DHD_MAX_IFS) { ++ if (dhd->iflist[i] && (dhd->iflist[i]->net == net)) ++ return i; ++ i++; ++ } ++ ++ return DHD_BAD_IF; ++} ++ ++struct net_device * dhd_idx2net(void *pub, int ifidx) ++{ ++ struct dhd_pub *dhd_pub = (struct dhd_pub *)pub; ++ struct dhd_info *dhd_info; ++ ++ if (!dhd_pub || ifidx < 0 || ifidx >= DHD_MAX_IFS) ++ return NULL; ++ dhd_info = dhd_pub->info; ++ if (dhd_info && dhd_info->iflist[ifidx]) ++ return dhd_info->iflist[ifidx]->net; ++ return NULL; ++} ++ ++int ++dhd_ifname2idx(dhd_info_t *dhd, char *name) ++{ ++ int i = DHD_MAX_IFS; ++ ++ ASSERT(dhd); ++ ++ if (name == NULL || *name == '\0') ++ return 0; ++ ++ while (--i > 0) ++ if (dhd->iflist[i] && !strncmp(dhd->iflist[i]->name, name, IFNAMSIZ)) ++ break; ++ ++ AP6210_DEBUG("%s: return idx %d for \"%s\"\n", __FUNCTION__, i, name); ++ ++ return i; /* default - the primary interface */ ++} ++ ++char * ++dhd_ifname(dhd_pub_t *dhdp, int ifidx) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)dhdp->info; ++ ++ ASSERT(dhd); ++ ++ if (ifidx < 0 || ifidx >= DHD_MAX_IFS) { ++ AP6210_ERR("%s: ifidx %d out of range\n", __FUNCTION__, ifidx); ++ return ""; ++ } ++ ++ if (dhd->iflist[ifidx] == NULL) { ++ AP6210_ERR("%s: null i/f %d\n", __FUNCTION__, ifidx); ++ return ""; ++ } ++ ++ if (dhd->iflist[ifidx]->net) ++ return dhd->iflist[ifidx]->net->name; ++ ++ return ""; ++} ++ ++uint8 * ++dhd_bssidx2bssid(dhd_pub_t *dhdp, int idx) ++{ ++ int i; ++ dhd_info_t *dhd = (dhd_info_t *)dhdp; ++ ++ ASSERT(dhd); ++ for (i = 0; i < DHD_MAX_IFS; i++) ++ if (dhd->iflist[i] && dhd->iflist[i]->bssidx == idx) ++ return dhd->iflist[i]->mac_addr; ++ ++ return NULL; ++} ++ ++ ++static void ++_dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) ++{ ++ struct net_device *dev; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) ++ struct netdev_hw_addr *ha; ++#else ++ struct dev_mc_list *mclist; ++#endif ++ uint32 allmulti, cnt; ++ ++ wl_ioctl_t ioc; ++ char *buf, *bufp; ++ uint buflen; ++ int ret; ++ ++ ASSERT(dhd && dhd->iflist[ifidx]); ++ dev = dhd->iflist[ifidx]->net; ++ if (!dev) ++ return; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) ++ netif_addr_lock_bh(dev); ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) ++ cnt = netdev_mc_count(dev); ++#else ++ cnt = dev->mc_count; ++#endif /* LINUX_VERSION_CODE */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) ++ netif_addr_unlock_bh(dev); ++#endif ++ ++ /* Determine initial value of allmulti flag */ ++ allmulti = (dev->flags & IFF_ALLMULTI) ? TRUE : FALSE; ++#ifdef PASS_ALL_MCAST_PKTS ++#ifdef PKT_FILTER_SUPPORT ++ if (!dhd->pub.early_suspended) ++#endif /* PKT_FILTER_SUPPORT */ ++ allmulti = TRUE; ++#endif /* PASS_ALL_MCAST_PKTS */ ++ ++ /* Send down the multicast list first. */ ++ ++ ++ buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETHER_ADDR_LEN); ++ if (!(bufp = buf = MALLOC(dhd->pub.osh, buflen))) { ++ AP6210_ERR("%s: out of memory for mcast_list, cnt %d\n", ++ dhd_ifname(&dhd->pub, ifidx), cnt); ++ return; ++ } ++ ++ strncpy(bufp, "mcast_list", buflen - 1); ++ bufp[buflen - 1] = '\0'; ++ bufp += strlen("mcast_list") + 1; ++ ++ cnt = htol32(cnt); ++ memcpy(bufp, &cnt, sizeof(cnt)); ++ bufp += sizeof(cnt); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) ++ netif_addr_lock_bh(dev); ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) ++ netdev_for_each_mc_addr(ha, dev) { ++ if (!cnt) ++ break; ++ memcpy(bufp, ha->addr, ETHER_ADDR_LEN); ++ bufp += ETHER_ADDR_LEN; ++ cnt--; ++ } ++#else ++ for (mclist = dev->mc_list; (mclist && (cnt > 0)); ++ cnt--, mclist = mclist->next) { ++ memcpy(bufp, (void *)mclist->dmi_addr, ETHER_ADDR_LEN); ++ bufp += ETHER_ADDR_LEN; ++ } ++#endif /* LINUX_VERSION_CODE */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) ++ netif_addr_unlock_bh(dev); ++#endif ++ ++ memset(&ioc, 0, sizeof(ioc)); ++ ioc.cmd = WLC_SET_VAR; ++ ioc.buf = buf; ++ ioc.len = buflen; ++ ioc.set = TRUE; ++ ++ ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len); ++ if (ret < 0) { ++ AP6210_ERR("%s: set mcast_list failed, cnt %d\n", ++ dhd_ifname(&dhd->pub, ifidx), cnt); ++ allmulti = cnt ? TRUE : allmulti; ++ } ++ ++ MFREE(dhd->pub.osh, buf, buflen); ++ ++ /* Now send the allmulti setting. This is based on the setting in the ++ * net_device flags, but might be modified above to be turned on if we ++ * were trying to set some addresses and dongle rejected it... ++ */ ++ ++ buflen = sizeof("allmulti") + sizeof(allmulti); ++ if (!(buf = MALLOC(dhd->pub.osh, buflen))) { ++ AP6210_ERR("%s: out of memory for allmulti\n", dhd_ifname(&dhd->pub, ifidx)); ++ return; ++ } ++ allmulti = htol32(allmulti); ++ ++ if (!bcm_mkiovar("allmulti", (void*)&allmulti, sizeof(allmulti), buf, buflen)) { ++ AP6210_ERR("%s: mkiovar failed for allmulti, datalen %d buflen %u\n", ++ dhd_ifname(&dhd->pub, ifidx), (int)sizeof(allmulti), buflen); ++ MFREE(dhd->pub.osh, buf, buflen); ++ return; ++ } ++ ++ ++ memset(&ioc, 0, sizeof(ioc)); ++ ioc.cmd = WLC_SET_VAR; ++ ioc.buf = buf; ++ ioc.len = buflen; ++ ioc.set = TRUE; ++ ++ ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len); ++ if (ret < 0) { ++ AP6210_ERR("%s: set allmulti %d failed\n", ++ dhd_ifname(&dhd->pub, ifidx), ltoh32(allmulti)); ++ } ++ ++ MFREE(dhd->pub.osh, buf, buflen); ++ ++ /* Finally, pick up the PROMISC flag as well, like the NIC driver does */ ++ ++ allmulti = (dev->flags & IFF_PROMISC) ? TRUE : FALSE; ++ allmulti = htol32(allmulti); ++ ++ memset(&ioc, 0, sizeof(ioc)); ++ ioc.cmd = WLC_SET_PROMISC; ++ ioc.buf = &allmulti; ++ ioc.len = sizeof(allmulti); ++ ioc.set = TRUE; ++ ++ ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len); ++ if (ret < 0) { ++ AP6210_ERR("%s: set promisc %d failed\n", ++ dhd_ifname(&dhd->pub, ifidx), ltoh32(allmulti)); ++ } ++} ++ ++int ++_dhd_set_mac_address(dhd_info_t *dhd, int ifidx, struct ether_addr *addr) ++{ ++ char buf[32]; ++ wl_ioctl_t ioc; ++ int ret; ++ ++ if (!bcm_mkiovar("cur_etheraddr", (char*)addr, ETHER_ADDR_LEN, buf, 32)) { ++ AP6210_ERR("%s: mkiovar failed for cur_etheraddr\n", dhd_ifname(&dhd->pub, ifidx)); ++ return -1; ++ } ++ memset(&ioc, 0, sizeof(ioc)); ++ ioc.cmd = WLC_SET_VAR; ++ ioc.buf = buf; ++ ioc.len = 32; ++ ioc.set = TRUE; ++ ++ ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len); ++ if (ret < 0) { ++ AP6210_ERR("%s: set cur_etheraddr failed\n", dhd_ifname(&dhd->pub, ifidx)); ++ } else { ++ memcpy(dhd->iflist[ifidx]->net->dev_addr, addr, ETHER_ADDR_LEN); ++ memcpy(dhd->pub.mac.octet, addr, ETHER_ADDR_LEN); ++ } ++ ++ return ret; ++} ++ ++#ifdef SOFTAP ++extern struct net_device *ap_net_dev; ++extern tsk_ctl_t ap_eth_ctl; /* ap netdev heper thread ctl */ ++#endif ++ ++static void ++dhd_op_if(dhd_if_t *ifp) ++{ ++ dhd_info_t *dhd; ++ int ret = 0, err = 0; ++#ifdef SOFTAP ++ unsigned long flags; ++#endif ++ ++ if (!ifp || !ifp->info || !ifp->idx) ++ return; ++ ASSERT(ifp && ifp->info && ifp->idx); /* Virtual interfaces only */ ++ dhd = ifp->info; ++ ++ AP6210_DEBUG("%s: idx %d, state %d\n", __FUNCTION__, ifp->idx, ifp->state); ++ ++#ifdef WL_CFG80211 ++ if (wl_cfg80211_is_progress_ifchange()) ++ return; ++ ++#endif ++ switch (ifp->state) { ++ case DHD_IF_ADD: ++ /* ++ * Delete the existing interface before overwriting it ++ * in case we missed the WLC_E_IF_DEL event. ++ */ ++ if (ifp->net != NULL) { ++ AP6210_ERR("%s: ERROR: netdev:%s already exists, try free & unregister \n", ++ __FUNCTION__, ifp->net->name); ++ netif_stop_queue(ifp->net); ++ unregister_netdev(ifp->net); ++ free_netdev(ifp->net); ++ } ++ /* Allocate etherdev, including space for private structure */ ++ if (!(ifp->net = alloc_etherdev(sizeof(dhd)))) { ++ AP6210_ERR("%s: OOM - alloc_etherdev\n", __FUNCTION__); ++ ret = -ENOMEM; ++ } ++ if (ret == 0) { ++ strncpy(ifp->net->name, ifp->name, IFNAMSIZ); ++ ifp->net->name[IFNAMSIZ - 1] = '\0'; ++ memcpy(netdev_priv(ifp->net), &dhd, sizeof(dhd)); ++#ifdef WL_CFG80211 ++ if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) ++ if (!wl_cfg80211_notify_ifadd(ifp->net, ifp->idx, ifp->bssidx, ++ (void*)dhd_net_attach)) { ++ ifp->state = DHD_IF_NONE; ++ ifp->event2cfg80211 = TRUE; ++ return; ++ } ++#endif ++ if ((err = dhd_net_attach(&dhd->pub, ifp->idx)) != 0) { ++ AP6210_ERR("%s: dhd_net_attach failed, err %d\n", ++ __FUNCTION__, err); ++ ret = -EOPNOTSUPP; ++ } else { ++#if defined(SOFTAP) ++ if (ap_fw_loaded && !(dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)) { ++ /* semaphore that the soft AP CODE waits on */ ++ flags = dhd_os_spin_lock(&dhd->pub); ++ ++ /* save ptr to wl0.1 netdev for use in wl_iw.c */ ++ ap_net_dev = ifp->net; ++ /* signal to the SOFTAP 'sleeper' thread, wl0.1 is ready */ ++ up(&ap_eth_ctl.sema); ++ dhd_os_spin_unlock(&dhd->pub, flags); ++ } ++#endif ++ AP6210_DEBUG(" ==== pid:%x, net_device for if:%s created ===\n\n", ++ current->pid, ifp->net->name); ++ ifp->state = DHD_IF_NONE; ++ } ++ } ++ break; ++ case DHD_IF_DEL: ++ /* Make sure that we don't enter again here if .. */ ++ /* dhd_op_if is called again from some other context */ ++ ifp->state = DHD_IF_DELETING; ++ if (ifp->net != NULL) { ++ AP6210_DEBUG("%s: got 'DHD_IF_DEL' state\n", __FUNCTION__); ++ netif_stop_queue(ifp->net); ++#ifdef WL_CFG80211 ++ if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { ++ wl_cfg80211_ifdel_ops(ifp->net); ++ } ++#endif ++ unregister_netdev(ifp->net); ++ ret = DHD_DEL_IF; /* Make sure the free_netdev() is called */ ++#ifdef WL_CFG80211 ++ if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { ++ wl_cfg80211_notify_ifdel(); ++ } ++#endif ++ } ++ break; ++ case DHD_IF_DELETING: ++ break; ++ default: ++ AP6210_ERR("%s: bad op %d\n", __FUNCTION__, ifp->state); ++ ASSERT(!ifp->state); ++ break; ++ } ++ ++ if (ret < 0) { ++ ifp->set_multicast = FALSE; ++ if (ifp->net) { ++ free_netdev(ifp->net); ++ ifp->net = NULL; ++ } ++ dhd->iflist[ifp->idx] = NULL; ++#ifdef SOFTAP ++ flags = dhd_os_spin_lock(&dhd->pub); ++ if (ifp->net == ap_net_dev) ++ ap_net_dev = NULL; /* NULL SOFTAP global wl0.1 as well */ ++ dhd_os_spin_unlock(&dhd->pub, flags); ++#endif /* SOFTAP */ ++ MFREE(dhd->pub.osh, ifp, sizeof(*ifp)); ++ } ++} ++ ++static int ++_dhd_sysioc_thread(void *data) ++{ ++ tsk_ctl_t *tsk = (tsk_ctl_t *)data; ++ dhd_info_t *dhd = (dhd_info_t *)tsk->parent; ++ ++ ++ int i; ++#ifdef SOFTAP ++ bool in_ap = FALSE; ++ unsigned long flags; ++#endif ++#ifndef USE_KTHREAD_API ++ DAEMONIZE("dhd_sysioc"); ++ ++ complete(&tsk->completed); ++#endif ++ ++ while (down_interruptible(&tsk->sema) == 0) { ++ ++ SMP_RD_BARRIER_DEPENDS(); ++ if (tsk->terminated) { ++ break; ++ } ++ ++ dhd_net_if_lock_local(dhd); ++ DHD_OS_WAKE_LOCK(&dhd->pub); ++ ++ for (i = 0; i < DHD_MAX_IFS; i++) { ++ if (dhd->iflist[i]) { ++ AP6210_DEBUG("%s: interface %d\n", __FUNCTION__, i); ++#ifdef SOFTAP ++ flags = dhd_os_spin_lock(&dhd->pub); ++ in_ap = (ap_net_dev != NULL); ++ dhd_os_spin_unlock(&dhd->pub, flags); ++#endif /* SOFTAP */ ++ if (dhd->iflist[i] && dhd->iflist[i]->state) ++ dhd_op_if(dhd->iflist[i]); ++ ++ if (dhd->iflist[i] == NULL) { ++ AP6210_DEBUG("%s: interface %d just been removed,!\n", __FUNCTION__, i); ++ continue; ++ } ++#ifdef SOFTAP ++ if (in_ap && dhd->set_macaddress == i+1) { ++ AP6210_DEBUG("attempt to set MAC for %s in AP Mode," ++ "blocked. \n", dhd->iflist[i]->net->name); ++ dhd->set_macaddress = 0; ++ continue; ++ } ++ ++ if (in_ap && dhd->iflist[i]->set_multicast) { ++ AP6210_DEBUG("attempt to set MULTICAST list for %s" ++ "in AP Mode, blocked. \n", dhd->iflist[i]->net->name); ++ dhd->iflist[i]->set_multicast = FALSE; ++ continue; ++ } ++#endif /* SOFTAP */ ++ if (dhd->pub.up == 0) ++ continue; ++ if (dhd->iflist[i]->set_multicast) { ++ dhd->iflist[i]->set_multicast = FALSE; ++ _dhd_set_multicast_list(dhd, i); ++ } ++ if (dhd->set_macaddress == i+1) { ++ dhd->set_macaddress = 0; ++ if (_dhd_set_mac_address(dhd, i, &dhd->macvalue) == 0) { ++ AP6210_DEBUG( ++ "dhd_sysioc_thread: MACID is overwritten\n"); ++ } else { ++ AP6210_ERR( ++ "dhd_sysioc_thread: _dhd_set_mac_address() failed\n"); ++ } ++ } ++ } ++ } ++ ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ dhd_net_if_unlock_local(dhd); ++ } ++ AP6210_DEBUG("%s: stopped\n", __FUNCTION__); ++ complete_and_exit(&tsk->completed, 0); ++} ++ ++static int ++dhd_set_mac_address(struct net_device *dev, void *addr) ++{ ++ int ret = 0; ++ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ struct sockaddr *sa = (struct sockaddr *)addr; ++ int ifidx; ++ ++ ifidx = dhd_net2idx(dhd, dev); ++ if (ifidx == DHD_BAD_IF) ++ return -1; ++ ++ ASSERT(dhd->thr_sysioc_ctl.thr_pid >= 0); ++ memcpy(&dhd->macvalue, sa->sa_data, ETHER_ADDR_LEN); ++ dhd->set_macaddress = ifidx+1; ++ up(&dhd->thr_sysioc_ctl.sema); ++ ++ return ret; ++} ++ ++static void ++dhd_set_multicast_list(struct net_device *dev) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ int ifidx; ++ ++ ifidx = dhd_net2idx(dhd, dev); ++ if (ifidx == DHD_BAD_IF) ++ return; ++ ++ ASSERT(dhd->thr_sysioc_ctl.thr_pid >= 0); ++ dhd->iflist[ifidx]->set_multicast = TRUE; ++ up(&dhd->thr_sysioc_ctl.sema); ++} ++ ++#ifdef PROP_TXSTATUS ++int ++dhd_os_wlfc_block(dhd_pub_t *pub) ++{ ++ dhd_info_t *di = (dhd_info_t *)(pub->info); ++ ASSERT(di != NULL); ++ spin_lock_bh(&di->wlfc_spinlock); ++ return 1; ++} ++ ++int ++dhd_os_wlfc_unblock(dhd_pub_t *pub) ++{ ++ dhd_info_t *di = (dhd_info_t *)(pub->info); ++ ++ ASSERT(di != NULL); ++ spin_unlock_bh(&di->wlfc_spinlock); ++ return 1; ++} ++ ++const uint8 wme_fifo2ac[] = { 0, 1, 2, 3, 1, 1 }; ++uint8 prio2fifo[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; ++#define WME_PRIO2AC(prio) wme_fifo2ac[prio2fifo[(prio)]] ++ ++#endif /* PROP_TXSTATUS */ ++int ++dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) ++{ ++ int ret; ++ dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); ++ struct ether_header *eh = NULL; ++ ++ /* Reject if down */ ++ if (!dhdp->up || (dhdp->busstate == DHD_BUS_DOWN)) { ++ /* free the packet here since the caller won't */ ++ PKTFREE(dhdp->osh, pktbuf, TRUE); ++ return -ENODEV; ++ } ++ ++ /* Update multicast statistic */ ++ if (PKTLEN(dhdp->osh, pktbuf) >= ETHER_HDR_LEN) { ++ uint8 *pktdata = (uint8 *)PKTDATA(dhdp->osh, pktbuf); ++ eh = (struct ether_header *)pktdata; ++ ++ if (ETHER_ISMULTI(eh->ether_dhost)) ++ dhdp->tx_multicast++; ++ if (ntoh16(eh->ether_type) == ETHER_TYPE_802_1X) ++ atomic_inc(&dhd->pend_8021x_cnt); ++ } else { ++ PKTFREE(dhd->pub.osh, pktbuf, TRUE); ++ return BCME_ERROR; ++ } ++ ++ /* Look into the packet and update the packet priority */ ++#ifndef PKTPRIO_OVERRIDE ++ if (PKTPRIO(pktbuf) == 0) ++#endif ++ pktsetprio(pktbuf, FALSE); ++ ++#ifdef PROP_TXSTATUS ++ if (dhdp->wlfc_state) { ++ /* store the interface ID */ ++ DHD_PKTTAG_SETIF(PKTTAG(pktbuf), ifidx); ++ ++ /* store destination MAC in the tag as well */ ++ DHD_PKTTAG_SETDSTN(PKTTAG(pktbuf), eh->ether_dhost); ++ ++ /* decide which FIFO this packet belongs to */ ++ if (ETHER_ISMULTI(eh->ether_dhost)) ++ /* one additional queue index (highest AC + 1) is used for bc/mc queue */ ++ DHD_PKTTAG_SETFIFO(PKTTAG(pktbuf), AC_COUNT); ++ else ++ DHD_PKTTAG_SETFIFO(PKTTAG(pktbuf), WME_PRIO2AC(PKTPRIO(pktbuf))); ++ } else ++#endif /* PROP_TXSTATUS */ ++ /* If the protocol uses a data header, apply it */ ++ dhd_prot_hdrpush(dhdp, ifidx, pktbuf); ++ ++ /* Use bus module to send data frame */ ++#ifdef WLMEDIA_HTSF ++ dhd_htsf_addtxts(dhdp, pktbuf); ++#endif ++#ifdef PROP_TXSTATUS ++ dhd_os_wlfc_block(dhdp); ++ if (dhdp->wlfc_state && ((athost_wl_status_info_t*)dhdp->wlfc_state)->proptxstatus_mode ++ != WLFC_FCMODE_NONE) { ++ ret = dhd_wlfc_enque_sendq(dhdp->wlfc_state, DHD_PKTTAG_FIFO(PKTTAG(pktbuf)), ++ pktbuf); ++ dhd_wlfc_commit_packets(dhdp->wlfc_state, (f_commitpkt_t)dhd_bus_txdata, ++ dhdp->bus); ++ if (((athost_wl_status_info_t*)dhdp->wlfc_state)->toggle_host_if) { ++ ((athost_wl_status_info_t*)dhdp->wlfc_state)->toggle_host_if = 0; ++ } ++ dhd_os_wlfc_unblock(dhdp); ++ } ++ else { ++ dhd_os_wlfc_unblock(dhdp); ++ /* non-proptxstatus way */ ++ ret = dhd_bus_txdata(dhdp->bus, pktbuf, FALSE); ++ } ++#else ++ ret = dhd_bus_txdata(dhdp->bus, pktbuf, FALSE); ++#endif /* PROP_TXSTATUS */ ++ ++ return ret; ++} ++ ++int ++dhd_start_xmit(struct sk_buff *skb, struct net_device *net) ++{ ++ int ret; ++ void *pktbuf; ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); ++ int ifidx; ++#ifdef WLMEDIA_HTSF ++ uint8 htsfdlystat_sz = dhd->pub.htsfdlystat_sz; ++#else ++ uint8 htsfdlystat_sz = 0; ++#endif ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ DHD_OS_WAKE_LOCK(&dhd->pub); ++ ++ /* Reject if down */ ++ if (dhd->pub.busstate == DHD_BUS_DOWN || dhd->pub.hang_was_sent) { ++ AP6210_ERR("%s: xmit rejected pub.up=%d busstate=%d \n", ++ __FUNCTION__, dhd->pub.up, dhd->pub.busstate); ++ netif_stop_queue(net); ++ /* Send Event when bus down detected during data session */ ++ if (dhd->pub.up) { ++ AP6210_ERR("%s: Event HANG sent up\n", __FUNCTION__); ++ net_os_send_hang_message(net); ++ } ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)) ++ return -ENODEV; ++#else ++ return NETDEV_TX_BUSY; ++#endif ++ } ++ ++ ifidx = dhd_net2idx(dhd, net); ++ if (ifidx == DHD_BAD_IF) { ++ AP6210_ERR("%s: bad ifidx %d\n", __FUNCTION__, ifidx); ++ netif_stop_queue(net); ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)) ++ return -ENODEV; ++#else ++ return NETDEV_TX_BUSY; ++#endif ++ } ++ ++ /* Make sure there's enough room for any header */ ++ ++ if (skb_headroom(skb) < dhd->pub.hdrlen + htsfdlystat_sz) { ++ struct sk_buff *skb2; ++ ++ AP6210_DEBUG("%s: insufficient headroom\n", ++ dhd_ifname(&dhd->pub, ifidx)); ++ dhd->pub.tx_realloc++; ++ ++ skb2 = skb_realloc_headroom(skb, dhd->pub.hdrlen + htsfdlystat_sz); ++ ++ dev_kfree_skb(skb); ++ if ((skb = skb2) == NULL) { ++ AP6210_ERR("%s: skb_realloc_headroom failed\n", ++ dhd_ifname(&dhd->pub, ifidx)); ++ ret = -ENOMEM; ++ goto done; ++ } ++ } ++ ++ /* Convert to packet */ ++ if (!(pktbuf = PKTFRMNATIVE(dhd->pub.osh, skb))) { ++ AP6210_ERR("%s: PKTFRMNATIVE failed\n", ++ dhd_ifname(&dhd->pub, ifidx)); ++ dev_kfree_skb_any(skb); ++ ret = -ENOMEM; ++ goto done; ++ } ++#ifdef WLMEDIA_HTSF ++ if (htsfdlystat_sz && PKTLEN(dhd->pub.osh, pktbuf) >= ETHER_ADDR_LEN) { ++ uint8 *pktdata = (uint8 *)PKTDATA(dhd->pub.osh, pktbuf); ++ struct ether_header *eh = (struct ether_header *)pktdata; ++ ++ if (!ETHER_ISMULTI(eh->ether_dhost) && ++ (ntoh16(eh->ether_type) == ETHER_TYPE_IP)) { ++ eh->ether_type = hton16(ETHER_TYPE_BRCM_PKTDLYSTATS); ++ } ++ } ++#endif ++ ++ ret = dhd_sendpkt(&dhd->pub, ifidx, pktbuf); ++ ++ ++done: ++ if (ret) ++ dhd->pub.dstats.tx_dropped++; ++ else ++ dhd->pub.tx_packets++; ++ ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ ++ /* Return ok: we always eat the packet */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)) ++ return 0; ++#else ++ return NETDEV_TX_OK; ++#endif ++} ++ ++void ++dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool state) ++{ ++ struct net_device *net; ++ dhd_info_t *dhd = dhdp->info; ++ int i; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ ASSERT(dhd); ++ ++ if (ifidx == ALL_INTERFACES) { ++ /* Flow control on all active interfaces */ ++ dhdp->txoff = state; ++ for (i = 0; i < DHD_MAX_IFS; i++) { ++ if (dhd->iflist[i]) { ++ net = dhd->iflist[i]->net; ++ if (state == ON) ++ netif_stop_queue(net); ++ else ++ netif_wake_queue(net); ++ } ++ } ++ } ++ else { ++ if (dhd->iflist[ifidx]) { ++ net = dhd->iflist[ifidx]->net; ++ if (state == ON) ++ netif_stop_queue(net); ++ else ++ netif_wake_queue(net); ++ } ++ } ++} ++ ++#ifdef DHD_RX_DUMP ++typedef struct { ++ uint16 type; ++ const char *str; ++} PKTTYPE_INFO; ++ ++static const PKTTYPE_INFO packet_type_info[] = ++{ ++ { ETHER_TYPE_IP, "IP" }, ++ { ETHER_TYPE_ARP, "ARP" }, ++ { ETHER_TYPE_BRCM, "BRCM" }, ++ { ETHER_TYPE_802_1X, "802.1X" }, ++ { ETHER_TYPE_WAI, "WAPI" }, ++ { 0, ""} ++}; ++ ++static const char *_get_packet_type_str(uint16 type) ++{ ++ int i; ++ int n = sizeof(packet_type_info)/sizeof(packet_type_info[1]) - 1; ++ ++ for (i = 0; i < n; i++) { ++ if (packet_type_info[i].type == type) ++ return packet_type_info[i].str; ++ } ++ ++ return packet_type_info[n].str; ++} ++#endif /* DHD_RX_DUMP */ ++ ++void ++dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)dhdp->info; ++ struct sk_buff *skb; ++ uchar *eth; ++ uint len; ++ void *data, *pnext = NULL; ++ int i; ++ dhd_if_t *ifp; ++ wl_event_msg_t event; ++ int tout_rx = 0; ++ int tout_ctrl = 0; ++ ++#ifdef DHD_RX_DUMP ++#ifdef DHD_RX_FULL_DUMP ++ int k; ++#endif /* DHD_RX_FULL_DUMP */ ++ char *dump_data; ++ uint16 protocol; ++#endif /* DHD_RX_DUMP */ ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ for (i = 0; pktbuf && i < numpkt; i++, pktbuf = pnext) { ++#ifdef WLBTAMP ++ struct ether_header *eh; ++ struct dot11_llc_snap_header *lsh; ++#endif ++ ++ ifp = dhd->iflist[ifidx]; ++ if (ifp == NULL) { ++ AP6210_ERR("%s: ifp is NULL. drop packet\n", ++ __FUNCTION__); ++ PKTFREE(dhdp->osh, pktbuf, TRUE); ++ continue; ++ } ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++ /* Dropping packets before registering net device to avoid kernel panic */ ++#ifndef PROP_TXSTATUS_VSDB ++ if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED) { ++#else ++ if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED || !dhd->pub.up) { ++#endif /* PROP_TXSTATUS_VSDB */ ++ AP6210_ERR("%s: net device is NOT registered yet. drop packet\n", ++ __FUNCTION__); ++ PKTFREE(dhdp->osh, pktbuf, TRUE); ++ continue; ++ } ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ ++ ++ pnext = PKTNEXT(dhdp->osh, pktbuf); ++ PKTSETNEXT(wl->sh.osh, pktbuf, NULL); ++ ++#ifdef WLBTAMP ++ eh = (struct ether_header *)PKTDATA(wl->sh.osh, pktbuf); ++ lsh = (struct dot11_llc_snap_header *)&eh[1]; ++ ++ if ((ntoh16(eh->ether_type) < ETHER_TYPE_MIN) && ++ (PKTLEN(wl->sh.osh, pktbuf) >= RFC1042_HDR_LEN) && ++ bcmp(lsh, BT_SIG_SNAP_MPROT, DOT11_LLC_SNAP_HDR_LEN - 2) == 0 && ++ lsh->type == HTON16(BTA_PROT_L2CAP)) { ++ amp_hci_ACL_data_t *ACL_data = (amp_hci_ACL_data_t *) ++ ((uint8 *)eh + RFC1042_HDR_LEN); ++ ACL_data = NULL; ++ } ++#endif /* WLBTAMP */ ++ ++#ifdef PROP_TXSTATUS ++ if (dhdp->wlfc_state && PKTLEN(wl->sh.osh, pktbuf) == 0) { ++ /* WLFC may send header only packet when ++ there is an urgent message but no packet to ++ piggy-back on ++ */ ++ ((athost_wl_status_info_t*)dhdp->wlfc_state)->stats.wlfc_header_only_pkt++; ++ PKTFREE(dhdp->osh, pktbuf, TRUE); ++ continue; ++ } ++#endif ++ ++ skb = PKTTONATIVE(dhdp->osh, pktbuf); ++ ++ /* Get the protocol, maintain skb around eth_type_trans() ++ * The main reason for this hack is for the limitation of ++ * Linux 2.4 where 'eth_type_trans' uses the 'net->hard_header_len' ++ * to perform skb_pull inside vs ETH_HLEN. Since to avoid ++ * coping of the packet coming from the network stack to add ++ * BDC, Hardware header etc, during network interface registration ++ * we set the 'net->hard_header_len' to ETH_HLEN + extra space required ++ * for BDC, Hardware header etc. and not just the ETH_HLEN ++ */ ++ eth = skb->data; ++ len = skb->len; ++ ++#ifdef DHD_RX_DUMP ++ dump_data = skb->data; ++ protocol = (dump_data[12] << 8) | dump_data[13]; ++ AP6210_ERR("RX DUMP - %s\n", _get_packet_type_str(protocol)); ++ ++#ifdef DHD_RX_FULL_DUMP ++ if (protocol != ETHER_TYPE_BRCM) { ++ for (k = 0; k < skb->len; k++) { ++ AP6210_ERR("%02X ", dump_data[k])); ++ if ((k & 15) == 15) ++ AP6210_ERR("\n"); ++ } ++ AP6210_ERR("\n"); ++ } ++#endif /* DHD_RX_FULL_DUMP */ ++ ++ if (protocol != ETHER_TYPE_BRCM) { ++ if (dump_data[0] == 0xFF) { ++ AP6210_ERR("%s: BROADCAST\n", __FUNCTION__); ++ ++ if ((dump_data[12] == 8) && ++ (dump_data[13] == 6)) { ++ AP6210_ERR("%s: ARP %d\n", ++ __FUNCTION__, dump_data[0x15]); ++ } ++ } else if (dump_data[0] & 1) { ++ AP6210_ERR("%s: MULTICAST: " MACDBG "\n", ++ __FUNCTION__, MAC2STRDBG(dump_data)); ++ } ++ ++ if (protocol == ETHER_TYPE_802_1X) { ++ AP6210_ERR("ETHER_TYPE_802_1X: " ++ "ver %d, type %d, replay %d\n", ++ dump_data[14], dump_data[15], ++ dump_data[30]); ++ } ++ } ++ ++#endif /* DHD_RX_DUMP */ ++ ++ ifp = dhd->iflist[ifidx]; ++ if (ifp == NULL) ++ ifp = dhd->iflist[0]; ++ ++ ASSERT(ifp); ++ skb->dev = ifp->net; ++ skb->protocol = eth_type_trans(skb, skb->dev); ++ ++ if (skb->pkt_type == PACKET_MULTICAST) { ++ dhd->pub.rx_multicast++; ++ } ++ ++ skb->data = eth; ++ skb->len = len; ++ ++#ifdef WLMEDIA_HTSF ++ dhd_htsf_addrxts(dhdp, pktbuf); ++#endif ++ /* Strip header, count, deliver upward */ ++ skb_pull(skb, ETH_HLEN); ++ ++ /* Process special event packets and then discard them */ ++ if (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) { ++ dhd_wl_host_event(dhd, &ifidx, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) ++ skb->mac_header, ++#else ++ skb->mac.raw, ++#endif ++ &event, ++ &data); ++ ++ wl_event_to_host_order(&event); ++ if (!tout_ctrl) ++ tout_ctrl = DHD_PACKET_TIMEOUT_MS; ++#ifdef WLBTAMP ++ if (event.event_type == WLC_E_BTA_HCI_EVENT) { ++ dhd_bta_doevt(dhdp, data, event.datalen); ++ } ++#endif /* WLBTAMP */ ++ ++#if defined(PNO_SUPPORT) ++ if (event.event_type == WLC_E_PFN_NET_FOUND) { ++ /* enforce custom wake lock to garantee that Kernel not suspended */ ++ tout_ctrl = CUSTOM_PNO_EVENT_LOCK_xTIME * DHD_PACKET_TIMEOUT_MS; ++ } ++#endif /* PNO_SUPPORT */ ++ ++#ifdef DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT ++ PKTFREE(dhdp->osh, pktbuf, TRUE); ++ continue; ++#endif ++ } else { ++ tout_rx = DHD_PACKET_TIMEOUT_MS; ++ } ++ ++ ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]); ++ if (dhd->iflist[ifidx] && !dhd->iflist[ifidx]->state) ++ ifp = dhd->iflist[ifidx]; ++ ++ if (ifp->net) ++ ifp->net->last_rx = jiffies; ++ ++ dhdp->dstats.rx_bytes += skb->len; ++ dhdp->rx_packets++; /* Local count */ ++ ++ if (in_interrupt()) { ++ netif_rx(skb); ++ } else { ++ /* If the receive is not processed inside an ISR, ++ * the softirqd must be woken explicitly to service ++ * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled ++ * by netif_rx_ni(), but in earlier kernels, we need ++ * to do it manually. ++ */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++ netif_rx_ni(skb); ++#else ++ ulong flags; ++ netif_rx(skb); ++ local_irq_save(flags); ++ RAISE_RX_SOFTIRQ(); ++ local_irq_restore(flags); ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ ++ } ++ } ++ ++ DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(dhdp, tout_rx); ++ DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp, tout_ctrl); ++} ++ ++void ++dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx) ++{ ++ /* Linux version has nothing to do */ ++ return; ++} ++ ++void ++dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); ++ struct ether_header *eh; ++ uint16 type; ++#ifdef WLBTAMP ++ uint len; ++#endif ++ ++ dhd_prot_hdrpull(dhdp, NULL, txp, NULL, NULL); ++ ++ eh = (struct ether_header *)PKTDATA(dhdp->osh, txp); ++ type = ntoh16(eh->ether_type); ++ ++ if (type == ETHER_TYPE_802_1X) ++ atomic_dec(&dhd->pend_8021x_cnt); ++ ++#ifdef WLBTAMP ++ /* Crack open the packet and check to see if it is BT HCI ACL data packet. ++ * If yes generate packet completion event. ++ */ ++ len = PKTLEN(dhdp->osh, txp); ++ ++ /* Generate ACL data tx completion event locally to avoid SDIO bus transaction */ ++ if ((type < ETHER_TYPE_MIN) && (len >= RFC1042_HDR_LEN)) { ++ struct dot11_llc_snap_header *lsh = (struct dot11_llc_snap_header *)&eh[1]; ++ ++ if (bcmp(lsh, BT_SIG_SNAP_MPROT, DOT11_LLC_SNAP_HDR_LEN - 2) == 0 && ++ ntoh16(lsh->type) == BTA_PROT_L2CAP) { ++ ++ dhd_bta_tx_hcidata_complete(dhdp, txp, success); ++ } ++ } ++#endif /* WLBTAMP */ ++} ++ ++static struct net_device_stats * ++dhd_get_stats(struct net_device *net) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); ++ dhd_if_t *ifp; ++ int ifidx; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ ifidx = dhd_net2idx(dhd, net); ++ if (ifidx == DHD_BAD_IF) { ++ AP6210_ERR("%s: BAD_IF\n", __FUNCTION__); ++ return NULL; ++ } ++ ++ ifp = dhd->iflist[ifidx]; ++ ASSERT(dhd && ifp); ++ ++ if (dhd->pub.up) { ++ /* Use the protocol to get dongle stats */ ++ dhd_prot_dstats(&dhd->pub); ++ } ++ ++ /* Copy dongle stats to net device stats */ ++ ifp->stats.rx_packets = dhd->pub.dstats.rx_packets; ++ ifp->stats.tx_packets = dhd->pub.dstats.tx_packets; ++ ifp->stats.rx_bytes = dhd->pub.dstats.rx_bytes; ++ ifp->stats.tx_bytes = dhd->pub.dstats.tx_bytes; ++ ifp->stats.rx_errors = dhd->pub.dstats.rx_errors; ++ ifp->stats.tx_errors = dhd->pub.dstats.tx_errors; ++ ifp->stats.rx_dropped = dhd->pub.dstats.rx_dropped; ++ ifp->stats.tx_dropped = dhd->pub.dstats.tx_dropped; ++ ifp->stats.multicast = dhd->pub.dstats.multicast; ++ ++ return &ifp->stats; ++} ++ ++#ifdef DHDTHREAD ++static int ++dhd_watchdog_thread(void *data) ++{ ++ tsk_ctl_t *tsk = (tsk_ctl_t *)data; ++ dhd_info_t *dhd = (dhd_info_t *)tsk->parent; ++ /* This thread doesn't need any user-level access, ++ * so get rid of all our resources ++ */ ++ if (dhd_watchdog_prio > 0) { ++ struct sched_param param; ++ param.sched_priority = (dhd_watchdog_prio < MAX_RT_PRIO)? ++ dhd_watchdog_prio:(MAX_RT_PRIO-1); ++ setScheduler(current, SCHED_FIFO, ¶m); ++ } ++#ifndef USE_KTHREAD_API ++ DAEMONIZE("dhd_watchdog"); ++ ++ /* Run until signal received */ ++ complete(&tsk->completed); ++#endif ++ ++ while (1) ++ if (down_interruptible (&tsk->sema) == 0) { ++ unsigned long flags; ++ unsigned long jiffies_at_start = jiffies; ++ unsigned long time_lapse; ++ ++ SMP_RD_BARRIER_DEPENDS(); ++ if (tsk->terminated) { ++ break; ++ } ++ ++ dhd_os_sdlock(&dhd->pub); ++ if (dhd->pub.dongle_reset == FALSE) { ++ AP6210_DEBUG("%s:\n", __FUNCTION__); ++ ++ /* Call the bus module watchdog */ ++ dhd_bus_watchdog(&dhd->pub); ++ ++ flags = dhd_os_spin_lock(&dhd->pub); ++ /* Count the tick for reference */ ++ dhd->pub.tickcnt++; ++ time_lapse = jiffies - jiffies_at_start; ++ ++ /* Reschedule the watchdog */ ++ if (dhd->wd_timer_valid) ++ mod_timer(&dhd->timer, ++ jiffies + ++ msecs_to_jiffies(dhd_watchdog_ms) - ++ min(msecs_to_jiffies(dhd_watchdog_ms), time_lapse)); ++ dhd_os_spin_unlock(&dhd->pub, flags); ++ } ++ dhd_os_sdunlock(&dhd->pub); ++ } else { ++ break; ++ } ++ ++ complete_and_exit(&tsk->completed, 0); ++} ++#endif /* DHDTHREAD */ ++ ++static void dhd_watchdog(ulong data) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)data; ++ unsigned long flags; ++ ++ if (dhd->pub.dongle_reset) { ++ return; ++ } ++ ++#ifdef DHDTHREAD ++ if (dhd->thr_wdt_ctl.thr_pid >= 0) { ++ up(&dhd->thr_wdt_ctl.sema); ++ return; ++ } ++#endif /* DHDTHREAD */ ++ ++ dhd_os_sdlock(&dhd->pub); ++ /* Call the bus module watchdog */ ++ dhd_bus_watchdog(&dhd->pub); ++ ++ flags = dhd_os_spin_lock(&dhd->pub); ++ /* Count the tick for reference */ ++ dhd->pub.tickcnt++; ++ ++ /* Reschedule the watchdog */ ++ if (dhd->wd_timer_valid) ++ mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms)); ++ dhd_os_spin_unlock(&dhd->pub, flags); ++ dhd_os_sdunlock(&dhd->pub); ++} ++ ++#ifdef DHDTHREAD ++static int ++dhd_dpc_thread(void *data) ++{ ++ tsk_ctl_t *tsk = (tsk_ctl_t *)data; ++ dhd_info_t *dhd = (dhd_info_t *)tsk->parent; ++ ++ /* This thread doesn't need any user-level access, ++ * so get rid of all our resources ++ */ ++ if (dhd_dpc_prio > 0) ++ { ++ struct sched_param param; ++ param.sched_priority = (dhd_dpc_prio < MAX_RT_PRIO)?dhd_dpc_prio:(MAX_RT_PRIO-1); ++ setScheduler(current, SCHED_FIFO, ¶m); ++ } ++#ifndef USE_KTHREAD_API ++ DAEMONIZE("dhd_dpc"); ++ /* DHD_OS_WAKE_LOCK is called in dhd_sched_dpc[dhd_linux.c] down below */ ++ ++ /* signal: thread has started */ ++ complete(&tsk->completed); ++#endif ++ ++ /* Run until signal received */ ++ while (1) { ++ if (down_interruptible(&tsk->sema) == 0) { ++ ++ SMP_RD_BARRIER_DEPENDS(); ++ if (tsk->terminated) { ++ break; ++ } ++ ++ /* Call bus dpc unless it indicated down (then clean stop) */ ++ if (dhd->pub.busstate != DHD_BUS_DOWN) { ++ if (dhd_bus_dpc(dhd->pub.bus)) { ++ up(&tsk->sema); ++ } ++ else { ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ } ++ } else { ++ if (dhd->pub.up) ++ dhd_bus_stop(dhd->pub.bus, TRUE); ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ } ++ } ++ else ++ break; ++ } ++ ++ complete_and_exit(&tsk->completed, 0); ++} ++#endif /* DHDTHREAD */ ++ ++static void ++dhd_dpc(ulong data) ++{ ++ dhd_info_t *dhd; ++ ++ dhd = (dhd_info_t *)data; ++ ++ /* this (tasklet) can be scheduled in dhd_sched_dpc[dhd_linux.c] ++ * down below , wake lock is set, ++ * the tasklet is initialized in dhd_attach() ++ */ ++ /* Call bus dpc unless it indicated down (then clean stop) */ ++ if (dhd->pub.busstate != DHD_BUS_DOWN) { ++ if (dhd_bus_dpc(dhd->pub.bus)) ++ tasklet_schedule(&dhd->tasklet); ++ else ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ } else { ++ dhd_bus_stop(dhd->pub.bus, TRUE); ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ } ++} ++ ++void ++dhd_sched_dpc(dhd_pub_t *dhdp) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)dhdp->info; ++ ++ DHD_OS_WAKE_LOCK(dhdp); ++#ifdef DHDTHREAD ++ if (dhd->thr_dpc_ctl.thr_pid >= 0) { ++ up(&dhd->thr_dpc_ctl.sema); ++ return; ++ } ++#endif /* DHDTHREAD */ ++ ++ if (dhd->dhd_tasklet_create) ++ tasklet_schedule(&dhd->tasklet); ++} ++ ++#ifdef TOE ++/* Retrieve current toe component enables, which are kept as a bitmap in toe_ol iovar */ ++static int ++dhd_toe_get(dhd_info_t *dhd, int ifidx, uint32 *toe_ol) ++{ ++ wl_ioctl_t ioc; ++ char buf[32]; ++ int ret; ++ ++ memset(&ioc, 0, sizeof(ioc)); ++ ++ ioc.cmd = WLC_GET_VAR; ++ ioc.buf = buf; ++ ioc.len = (uint)sizeof(buf); ++ ioc.set = FALSE; ++ ++ strncpy(buf, "toe_ol", sizeof(buf) - 1); ++ buf[sizeof(buf) - 1] = '\0'; ++ if ((ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len)) < 0) { ++ /* Check for older dongle image that doesn't support toe_ol */ ++ if (ret == -EIO) { ++ AP6210_ERR("%s: toe not supported by device\n", ++ dhd_ifname(&dhd->pub, ifidx)); ++ return -EOPNOTSUPP; ++ } ++ ++ AP6210_DEBUG("%s: could not get toe_ol: ret=%d\n", dhd_ifname(&dhd->pub, ifidx), ret); ++ return ret; ++ } ++ ++ memcpy(toe_ol, buf, sizeof(uint32)); ++ return 0; ++} ++ ++/* Set current toe component enables in toe_ol iovar, and set toe global enable iovar */ ++static int ++dhd_toe_set(dhd_info_t *dhd, int ifidx, uint32 toe_ol) ++{ ++ wl_ioctl_t ioc; ++ char buf[32]; ++ int toe, ret; ++ ++ memset(&ioc, 0, sizeof(ioc)); ++ ++ ioc.cmd = WLC_SET_VAR; ++ ioc.buf = buf; ++ ioc.len = (uint)sizeof(buf); ++ ioc.set = TRUE; ++ ++ /* Set toe_ol as requested */ ++ ++ strncpy(buf, "toe_ol", sizeof(buf) - 1); ++ buf[sizeof(buf) - 1] = '\0'; ++ memcpy(&buf[sizeof("toe_ol")], &toe_ol, sizeof(uint32)); ++ ++ if ((ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len)) < 0) { ++ AP6210_ERR("%s: could not set toe_ol: ret=%d\n", ++ dhd_ifname(&dhd->pub, ifidx), ret); ++ return ret; ++ } ++ ++ /* Enable toe globally only if any components are enabled. */ ++ ++ toe = (toe_ol != 0); ++ ++ strcpy(buf, "toe"); ++ memcpy(&buf[sizeof("toe")], &toe, sizeof(uint32)); ++ ++ if ((ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len)) < 0) { ++ AP6210_ERR("%s: could not set toe: ret=%d\n", dhd_ifname(&dhd->pub, ifidx), ret); ++ return ret; ++ } ++ ++ return 0; ++} ++#endif /* TOE */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) ++static void ++dhd_ethtool_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); ++ ++ snprintf(info->driver, sizeof(info->driver), "wl"); ++ snprintf(info->version, sizeof(info->version), "%lu", dhd->pub.drv_version); ++} ++ ++struct ethtool_ops dhd_ethtool_ops = { ++ .get_drvinfo = dhd_ethtool_get_drvinfo ++}; ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ ++ ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) ++static int ++dhd_ethtool(dhd_info_t *dhd, void *uaddr) ++{ ++ struct ethtool_drvinfo info; ++ char drvname[sizeof(info.driver)]; ++ uint32 cmd; ++#ifdef TOE ++ struct ethtool_value edata; ++ uint32 toe_cmpnt, csum_dir; ++ int ret; ++#endif ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ /* all ethtool calls start with a cmd word */ ++ if (copy_from_user(&cmd, uaddr, sizeof (uint32))) ++ return -EFAULT; ++ ++ switch (cmd) { ++ case ETHTOOL_GDRVINFO: ++ /* Copy out any request driver name */ ++ if (copy_from_user(&info, uaddr, sizeof(info))) ++ return -EFAULT; ++ strncpy(drvname, info.driver, sizeof(info.driver)); ++ drvname[sizeof(info.driver)-1] = '\0'; ++ ++ /* clear struct for return */ ++ memset(&info, 0, sizeof(info)); ++ info.cmd = cmd; ++ ++ /* if dhd requested, identify ourselves */ ++ if (strcmp(drvname, "?dhd") == 0) { ++ snprintf(info.driver, sizeof(info.driver), "dhd"); ++ strncpy(info.version, EPI_VERSION_STR, sizeof(info.version) - 1); ++ info.version[sizeof(info.version) - 1] = '\0'; ++ } ++ ++ /* otherwise, require dongle to be up */ ++ else if (!dhd->pub.up) { ++ AP6210_ERR("%s: dongle is not up\n", __FUNCTION__); ++ return -ENODEV; ++ } ++ ++ /* finally, report dongle driver type */ ++ else if (dhd->pub.iswl) ++ snprintf(info.driver, sizeof(info.driver), "wl"); ++ else ++ snprintf(info.driver, sizeof(info.driver), "xx"); ++ ++ snprintf(info.version, sizeof(info.version), "%lu", dhd->pub.drv_version); ++ if (copy_to_user(uaddr, &info, sizeof(info))) ++ return -EFAULT; ++ AP6210_DEBUG("%s: given %*s, returning %s\n", __FUNCTION__, ++ (int)sizeof(drvname), drvname, info.driver); ++ break; ++ ++#ifdef TOE ++ /* Get toe offload components from dongle */ ++ case ETHTOOL_GRXCSUM: ++ case ETHTOOL_GTXCSUM: ++ if ((ret = dhd_toe_get(dhd, 0, &toe_cmpnt)) < 0) ++ return ret; ++ ++ csum_dir = (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; ++ ++ edata.cmd = cmd; ++ edata.data = (toe_cmpnt & csum_dir) ? 1 : 0; ++ ++ if (copy_to_user(uaddr, &edata, sizeof(edata))) ++ return -EFAULT; ++ break; ++ ++ /* Set toe offload components in dongle */ ++ case ETHTOOL_SRXCSUM: ++ case ETHTOOL_STXCSUM: ++ if (copy_from_user(&edata, uaddr, sizeof(edata))) ++ return -EFAULT; ++ ++ /* Read the current settings, update and write back */ ++ if ((ret = dhd_toe_get(dhd, 0, &toe_cmpnt)) < 0) ++ return ret; ++ ++ csum_dir = (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; ++ ++ if (edata.data != 0) ++ toe_cmpnt |= csum_dir; ++ else ++ toe_cmpnt &= ~csum_dir; ++ ++ if ((ret = dhd_toe_set(dhd, 0, toe_cmpnt)) < 0) ++ return ret; ++ ++ /* If setting TX checksum mode, tell Linux the new mode */ ++ if (cmd == ETHTOOL_STXCSUM) { ++ if (edata.data) ++ dhd->iflist[0]->net->features |= NETIF_F_IP_CSUM; ++ else ++ dhd->iflist[0]->net->features &= ~NETIF_F_IP_CSUM; ++ } ++ ++ break; ++#endif /* TOE */ ++ ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */ ++ ++static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error) ++{ ++ dhd_info_t * dhd; ++ ++ if (!dhdp) ++ return FALSE; ++ ++ dhd = (dhd_info_t *)dhdp->info; ++ if (dhd->thr_sysioc_ctl.thr_pid < 0) { ++ AP6210_ERR("%s : skipped due to negative pid - unloading?\n", __FUNCTION__); ++ return FALSE; ++ } ++ ++ if ((error == -ETIMEDOUT) || (error == -EREMOTEIO) || ++ ((dhdp->busstate == DHD_BUS_DOWN) && (!dhdp->dongle_reset))) { ++ AP6210_ERR("%s: Event HANG send up due to re=%d te=%d e=%d s=%d\n", __FUNCTION__, ++ dhdp->rxcnt_timeout, dhdp->txcnt_timeout, error, dhdp->busstate); ++ net_os_send_hang_message(net); ++ return TRUE; ++ } ++ return FALSE; ++} ++ ++static int ++dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); ++ dhd_ioctl_t ioc; ++ int bcmerror = 0; ++ int buflen = 0; ++ void *buf = NULL; ++ uint driver = 0; ++ int ifidx; ++ int ret; ++ ++ DHD_OS_WAKE_LOCK(&dhd->pub); ++ ++ /* send to dongle only if we are not waiting for reload already */ ++ if (dhd->pub.hang_was_sent) { ++ AP6210_ERR("%s: HANG was sent up earlier\n", __FUNCTION__); ++ DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT_MS); ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ return OSL_ERROR(BCME_DONGLE_DOWN); ++ } ++ ++ ifidx = dhd_net2idx(dhd, net); ++ AP6210_DEBUG("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd); ++ ++ if (ifidx == DHD_BAD_IF) { ++ AP6210_ERR("%s: BAD IF\n", __FUNCTION__); ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ return -1; ++ } ++ ++#if defined(CONFIG_WIRELESS_EXT) ++ /* linux wireless extensions */ ++ if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) { ++ /* may recurse, do NOT lock */ ++ ret = wl_iw_ioctl(net, ifr, cmd); ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ return ret; ++ } ++#endif /* defined(CONFIG_WIRELESS_EXT) */ ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) ++ if (cmd == SIOCETHTOOL) { ++ ret = dhd_ethtool(dhd, (void*)ifr->ifr_data); ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ return ret; ++ } ++#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */ ++ ++ if (cmd == SIOCDEVPRIVATE+1) { ++ ret = wl_android_priv_cmd(net, ifr, cmd); ++ dhd_check_hang(net, &dhd->pub, ret); ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ return ret; ++ } ++ ++ if (cmd != SIOCDEVPRIVATE) { ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ return -EOPNOTSUPP; ++ } ++ ++ memset(&ioc, 0, sizeof(ioc)); ++ ++ /* Copy the ioc control structure part of ioctl request */ ++ if (copy_from_user(&ioc, ifr->ifr_data, sizeof(wl_ioctl_t))) { ++ bcmerror = BCME_BADADDR; ++ goto done; ++ } ++ ++ /* Copy out any buffer passed */ ++ if (ioc.buf) { ++ if (ioc.len == 0) { ++ AP6210_DEBUG("%s: ioc.len=0, returns BCME_BADARG \n", __FUNCTION__); ++ bcmerror = BCME_BADARG; ++ goto done; ++ } ++ buflen = MIN(ioc.len, DHD_IOCTL_MAXLEN); ++ /* optimization for direct ioctl calls from kernel */ ++ /* ++ if (segment_eq(get_fs(), KERNEL_DS)) { ++ buf = ioc.buf; ++ } else { ++ */ ++ { ++ if (!(buf = (char*)MALLOC(dhd->pub.osh, buflen))) { ++ bcmerror = BCME_NOMEM; ++ goto done; ++ } ++ if (copy_from_user(buf, ioc.buf, buflen)) { ++ bcmerror = BCME_BADADDR; ++ goto done; ++ } ++ } ++ } ++ ++ /* To differentiate between wl and dhd read 4 more byes */ ++ if ((copy_from_user(&driver, (char *)ifr->ifr_data + sizeof(wl_ioctl_t), ++ sizeof(uint)) != 0)) { ++ bcmerror = BCME_BADADDR; ++ goto done; ++ } ++ ++ if (!capable(CAP_NET_ADMIN)) { ++ bcmerror = BCME_EPERM; ++ goto done; ++ } ++ ++ /* check for local dhd ioctl and handle it */ ++ if (driver == DHD_IOCTL_MAGIC) { ++ bcmerror = dhd_ioctl((void *)&dhd->pub, &ioc, buf, buflen); ++ if (bcmerror) ++ dhd->pub.bcmerror = bcmerror; ++ goto done; ++ } ++ ++ /* send to dongle (must be up, and wl). */ ++ if (dhd->pub.busstate != DHD_BUS_DATA) { ++ bcmerror = BCME_DONGLE_DOWN; ++ goto done; ++ } ++ ++ if (!dhd->pub.iswl) { ++ bcmerror = BCME_DONGLE_DOWN; ++ goto done; ++ } ++ ++ /* ++ * Flush the TX queue if required for proper message serialization: ++ * Intercept WLC_SET_KEY IOCTL - serialize M4 send and set key IOCTL to ++ * prevent M4 encryption and ++ * intercept WLC_DISASSOC IOCTL - serialize WPS-DONE and WLC_DISASSOC IOCTL to ++ * prevent disassoc frame being sent before WPS-DONE frame. ++ */ ++ if (ioc.cmd == WLC_SET_KEY || ++ (ioc.cmd == WLC_SET_VAR && ioc.buf != NULL && ++ strncmp("wsec_key", ioc.buf, 9) == 0) || ++ (ioc.cmd == WLC_SET_VAR && ioc.buf != NULL && ++ strncmp("bsscfg:wsec_key", ioc.buf, 15) == 0) || ++ ioc.cmd == WLC_DISASSOC) ++ dhd_wait_pend8021x(net); ++ ++#ifdef WLMEDIA_HTSF ++ if (ioc.buf) { ++ /* short cut wl ioctl calls here */ ++ if (strcmp("htsf", ioc.buf) == 0) { ++ dhd_ioctl_htsf_get(dhd, 0); ++ return BCME_OK; ++ } ++ ++ if (strcmp("htsflate", ioc.buf) == 0) { ++ if (ioc.set) { ++ memset(ts, 0, sizeof(tstamp_t)*TSMAX); ++ memset(&maxdelayts, 0, sizeof(tstamp_t)); ++ maxdelay = 0; ++ tspktcnt = 0; ++ maxdelaypktno = 0; ++ memset(&vi_d1.bin, 0, sizeof(uint32)*NUMBIN); ++ memset(&vi_d2.bin, 0, sizeof(uint32)*NUMBIN); ++ memset(&vi_d3.bin, 0, sizeof(uint32)*NUMBIN); ++ memset(&vi_d4.bin, 0, sizeof(uint32)*NUMBIN); ++ } else { ++ dhd_dump_latency(); ++ } ++ return BCME_OK; ++ } ++ if (strcmp("htsfclear", ioc.buf) == 0) { ++ memset(&vi_d1.bin, 0, sizeof(uint32)*NUMBIN); ++ memset(&vi_d2.bin, 0, sizeof(uint32)*NUMBIN); ++ memset(&vi_d3.bin, 0, sizeof(uint32)*NUMBIN); ++ memset(&vi_d4.bin, 0, sizeof(uint32)*NUMBIN); ++ htsf_seqnum = 0; ++ return BCME_OK; ++ } ++ if (strcmp("htsfhis", ioc.buf) == 0) { ++ dhd_dump_htsfhisto(&vi_d1, "H to D"); ++ dhd_dump_htsfhisto(&vi_d2, "D to D"); ++ dhd_dump_htsfhisto(&vi_d3, "D to H"); ++ dhd_dump_htsfhisto(&vi_d4, "H to H"); ++ return BCME_OK; ++ } ++ if (strcmp("tsport", ioc.buf) == 0) { ++ if (ioc.set) { ++ memcpy(&tsport, ioc.buf + 7, 4); ++ } else { ++ AP6210_ERR("current timestamp port: %d \n", tsport); ++ } ++ return BCME_OK; ++ } ++ } ++#endif /* WLMEDIA_HTSF */ ++ ++ if ((ioc.cmd == WLC_SET_VAR || ioc.cmd == WLC_GET_VAR) && ++ ioc.buf != NULL && strncmp("rpc_", ioc.buf, 4) == 0) { ++#ifdef BCM_FD_AGGR ++ bcmerror = dhd_fdaggr_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen); ++#else ++ bcmerror = BCME_UNSUPPORTED; ++#endif ++ goto done; ++ } ++ bcmerror = dhd_wl_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen); ++ ++done: ++ dhd_check_hang(net, &dhd->pub, bcmerror); ++ ++ if (!bcmerror && buf && ioc.buf) { ++ if (copy_to_user(ioc.buf, buf, buflen)) ++ bcmerror = -EFAULT; ++ } ++ ++ if (buf) ++ MFREE(dhd->pub.osh, buf, buflen); ++ ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ ++ return OSL_ERROR(bcmerror); ++} ++ ++#ifdef WL_CFG80211 ++static int ++dhd_cleanup_virt_ifaces(dhd_info_t *dhd) ++{ ++ int i = 1; /* Leave ifidx 0 [Primary Interface] */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ int rollback_lock = FALSE; ++#endif ++ ++ AP6210_DEBUG("%s: Enter \n", __func__); ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ /* release lock for unregister_netdev */ ++ if (rtnl_is_locked()) { ++ rtnl_unlock(); ++ rollback_lock = TRUE; ++ } ++#endif ++ ++ for (i = 1; i < DHD_MAX_IFS; i++) { ++ dhd_net_if_lock_local(dhd); ++ if (dhd->iflist[i]) { ++ AP6210_DEBUG("Deleting IF: %d \n", i); ++ if ((dhd->iflist[i]->state != DHD_IF_DEL) && ++ (dhd->iflist[i]->state != DHD_IF_DELETING)) { ++ dhd->iflist[i]->state = DHD_IF_DEL; ++ dhd->iflist[i]->idx = i; ++ dhd_op_if(dhd->iflist[i]); ++ } ++ } ++ dhd_net_if_unlock_local(dhd); ++ } ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ if (rollback_lock) ++ rtnl_lock(); ++#endif ++ ++ return 0; ++} ++#endif /* WL_CFG80211 */ ++ ++ ++static int ++dhd_stop(struct net_device *net) ++{ ++ int ifidx = 0; ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); ++ DHD_OS_WAKE_LOCK(&dhd->pub); ++ AP6210_DEBUG("%s: Enter %p\n", __FUNCTION__, net); ++ if (dhd->pub.up == 0) { ++ goto exit; ++ } ++ ifidx = dhd_net2idx(dhd, net); ++ BCM_REFERENCE(ifidx); ++ ++ /* Set state and stop OS transmissions */ ++ netif_stop_queue(net); ++ dhd->pub.up = 0; ++ ++#ifdef WL_CFG80211 ++ if (ifidx == 0) { ++ wl_cfg80211_down(NULL); ++ ++ /* ++ * For CFG80211: Clean up all the left over virtual interfaces ++ * when the primary Interface is brought down. [ifconfig wlan0 down] ++ */ ++ if ((dhd->dhd_state & DHD_ATTACH_STATE_ADD_IF) && ++ (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)) { ++ dhd_cleanup_virt_ifaces(dhd); ++ } ++ } ++#endif ++ ++#ifdef PROP_TXSTATUS ++ dhd_os_wlfc_block(&dhd->pub); ++ dhd_wlfc_cleanup(&dhd->pub); ++ dhd_os_wlfc_unblock(&dhd->pub); ++#endif ++ /* Stop the protocol module */ ++ dhd_prot_stop(&dhd->pub); ++ ++ OLD_MOD_DEC_USE_COUNT; ++exit: ++#if defined(WL_CFG80211) ++ if (ifidx == 0) { ++ if (!dhd_download_fw_on_driverload) ++ wl_android_wifi_off(net); ++ } ++#endif ++ dhd->pub.rxcnt_timeout = 0; ++ dhd->pub.txcnt_timeout = 0; ++ ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ return 0; ++} ++ ++static int ++dhd_open(struct net_device *net) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); ++#ifdef TOE ++ uint32 toe_ol; ++#endif ++ int ifidx; ++ int32 ret = 0; ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ if (mutex_is_locked(&_dhd_sdio_mutex_lock_) != 0) { ++ AP6210_ERR("%s : dhd_open: call dev open before insmod complete!\n", __FUNCTION__); ++ } ++ mutex_lock(&_dhd_sdio_mutex_lock_); ++#endif ++ ++ AP6210_DEBUG("%s, firmware path %s\n", __func__, firmware_path); ++ ++ DHD_OS_WAKE_LOCK(&dhd->pub); ++ /* Update FW path if it was changed */ ++ if (strlen(firmware_path) != 0) { ++ if (firmware_path[strlen(firmware_path)-1] == '\n') ++ firmware_path[strlen(firmware_path)-1] = '\0'; ++ COPY_FW_PATH_BY_CHIP( dhd->pub.bus, fw_path, firmware_path); ++ } ++ ++ ++ dhd->pub.dongle_trap_occured = 0; ++ dhd->pub.hang_was_sent = 0; ++#if !defined(WL_CFG80211) ++ /* ++ * Force start if ifconfig_up gets called before START command ++ * We keep WEXT's wl_control_wl_start to provide backward compatibility ++ * This should be removed in the future ++ */ ++ ret = wl_control_wl_start(net); ++ if (ret != 0) { ++ AP6210_ERR("%s: failed with code %d\n", __FUNCTION__, ret); ++ ret = -1; ++ goto exit; ++ } ++#endif ++ ++ ifidx = dhd_net2idx(dhd, net); ++ AP6210_DEBUG("%s: ifidx %d\n", __FUNCTION__, ifidx); ++ ++ if (ifidx < 0) { ++ AP6210_ERR("%s: Error: called with invalid IF\n", __FUNCTION__); ++ ret = -1; ++ goto exit; ++ } ++ ++ if (!dhd->iflist[ifidx] || dhd->iflist[ifidx]->state == DHD_IF_DEL) { ++ AP6210_ERR("%s: Error: called when IF already deleted\n", __FUNCTION__); ++ ret = -1; ++ goto exit; ++ } ++ ++ if (ifidx == 0) { ++ atomic_set(&dhd->pend_8021x_cnt, 0); ++#if defined(WL_CFG80211) ++ AP6210_ERR("%s\n", dhd_version); ++#if defined(DHD_DEBUG) ++ AP6210_ERR("%s\n", dhd_version_info); ++#endif ++ ++ if (!dhd_download_fw_on_driverload) { ++ ret = wl_android_wifi_on(net); ++ if (ret != 0) { ++ AP6210_ERR("%s: failed with code %d\n", __FUNCTION__, ret); ++ ret = -1; ++ goto exit; ++ } ++ } else { ++ } ++#endif ++ ++ if (dhd->pub.busstate != DHD_BUS_DATA) { ++ ++ /* try to bring up bus */ ++ if ((ret = dhd_bus_start(&dhd->pub)) != 0) { ++ AP6210_ERR("%s: failed with code %d\n", __FUNCTION__, ret); ++ ret = -1; ++ goto exit; ++ } ++ ++ } ++ ++ /* dhd_prot_init has been called in dhd_bus_start or wl_android_wifi_on */ ++ memcpy(net->dev_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN); ++ ++#ifdef TOE ++ /* Get current TOE mode from dongle */ ++ if (dhd_toe_get(dhd, ifidx, &toe_ol) >= 0 && (toe_ol & TOE_TX_CSUM_OL) != 0) ++ dhd->iflist[ifidx]->net->features |= NETIF_F_IP_CSUM; ++ else ++ dhd->iflist[ifidx]->net->features &= ~NETIF_F_IP_CSUM; ++#endif /* TOE */ ++ ++#if defined(WL_CFG80211) ++ if (unlikely(wl_cfg80211_up(NULL))) { ++ AP6210_ERR("%s: failed to bring up cfg80211\n", __FUNCTION__); ++ ret = -1; ++ goto exit; ++ } ++#endif /* WL_CFG80211 */ ++ } ++ ++ /* Allow transmit calls */ ++ netif_start_queue(net); ++ dhd->pub.up = 1; ++ ++#ifdef BCMDBGFS ++ dhd_dbg_init(&dhd->pub); ++#endif ++ ++ OLD_MOD_INC_USE_COUNT; ++exit: ++ if (ret) ++ dhd_stop(net); ++ ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ mutex_unlock(&_dhd_sdio_mutex_lock_); ++#endif ++ return ret; ++} ++ ++int dhd_do_driver_init(struct net_device *net) ++{ ++ dhd_info_t *dhd = NULL; ++ ++ if (!net) { ++ AP6210_ERR("Primary Interface not initialized \n"); ++ return -EINVAL; ++ } ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++#ifdef MULTIPLE_SUPPLICANT ++ if (mutex_is_locked(&_dhd_sdio_mutex_lock_) != 0) { ++ AP6210_ERR("%s : dhdsdio_probe is already running!\n", __FUNCTION__); ++ return 0; ++ } ++#endif /* MULTIPLE_SUPPLICANT */ ++#endif ++ ++ dhd = *(dhd_info_t **)netdev_priv(net); ++ ++ /* If driver is already initialized, do nothing ++ */ ++ if (dhd->pub.busstate == DHD_BUS_DATA) { ++ AP6210_DEBUG("Driver already Inititalized. Nothing to do"); ++ return 0; ++ } ++ ++ if (dhd_open(net) < 0) { ++ AP6210_ERR("Driver Init Failed \n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++osl_t * ++dhd_osl_attach(void *pdev, uint bustype) ++{ ++ return osl_attach(pdev, bustype, TRUE); ++} ++ ++void ++dhd_osl_detach(osl_t *osh) ++{ ++ if (MALLOCED(osh)) { ++ AP6210_ERR("%s: MEMORY LEAK %d bytes\n", __FUNCTION__, MALLOCED(osh)); ++ } ++ osl_detach(osh); ++#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ dhd_registration_check = FALSE; ++ up(&dhd_registration_sem); ++#if defined(BCMLXSDMMC) ++ up(&dhd_chipup_sem); ++#endif ++#endif ++} ++ ++int ++dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name, ++ uint8 *mac_addr, uint32 flags, uint8 bssidx) ++{ ++ dhd_if_t *ifp; ++ ++ AP6210_DEBUG("%s: idx %d, handle->%p\n", __FUNCTION__, ifidx, handle); ++ ++ ASSERT(dhd && (ifidx < DHD_MAX_IFS)); ++ ++ ifp = dhd->iflist[ifidx]; ++ if (ifp != NULL) { ++ if (ifp->net != NULL) { ++ netif_stop_queue(ifp->net); ++ unregister_netdev(ifp->net); ++ free_netdev(ifp->net); ++ } ++ } else ++ if ((ifp = MALLOC(dhd->pub.osh, sizeof(dhd_if_t))) == NULL) { ++ AP6210_ERR("%s: OOM - dhd_if_t\n", __FUNCTION__); ++ return -ENOMEM; ++ } ++ ++ memset(ifp, 0, sizeof(dhd_if_t)); ++ ifp->event2cfg80211 = FALSE; ++ ifp->info = dhd; ++ dhd->iflist[ifidx] = ifp; ++ strncpy(ifp->name, name, IFNAMSIZ); ++ ifp->name[IFNAMSIZ] = '\0'; ++ if (mac_addr != NULL) ++ memcpy(&ifp->mac_addr, mac_addr, ETHER_ADDR_LEN); ++ ++ if (handle == NULL) { ++ ifp->state = DHD_IF_ADD; ++ ifp->idx = ifidx; ++ ifp->bssidx = bssidx; ++ ASSERT(dhd->thr_sysioc_ctl.thr_pid >= 0); ++ up(&dhd->thr_sysioc_ctl.sema); ++ } else ++ ifp->net = (struct net_device *)handle; ++ ++ if (ifidx == 0) { ++ ifp->event2cfg80211 = TRUE; ++ } ++ ++ return 0; ++} ++ ++void ++dhd_del_if(dhd_info_t *dhd, int ifidx) ++{ ++ dhd_if_t *ifp; ++ ++ AP6210_DEBUG("%s: idx %d\n", __FUNCTION__, ifidx); ++ ++ ASSERT(dhd && ifidx && (ifidx < DHD_MAX_IFS)); ++ ifp = dhd->iflist[ifidx]; ++ if (!ifp) { ++ AP6210_ERR("%s: Null interface\n", __FUNCTION__); ++ return; ++ } ++ ++ ifp->state = DHD_IF_DEL; ++ ifp->idx = ifidx; ++ ASSERT(dhd->thr_sysioc_ctl.thr_pid >= 0); ++ up(&dhd->thr_sysioc_ctl.sema); ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) ++static struct net_device_ops dhd_ops_pri = { ++ .ndo_open = dhd_open, ++ .ndo_stop = dhd_stop, ++ .ndo_get_stats = dhd_get_stats, ++ .ndo_do_ioctl = dhd_ioctl_entry, ++ .ndo_start_xmit = dhd_start_xmit, ++ .ndo_set_mac_address = dhd_set_mac_address, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) ++ .ndo_set_rx_mode = dhd_set_multicast_list, ++#else ++ .ndo_set_multicast_list = dhd_set_multicast_list, ++#endif ++}; ++ ++static struct net_device_ops dhd_ops_virt = { ++ .ndo_get_stats = dhd_get_stats, ++ .ndo_do_ioctl = dhd_ioctl_entry, ++ .ndo_start_xmit = dhd_start_xmit, ++ .ndo_set_mac_address = dhd_set_mac_address, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) ++ .ndo_set_rx_mode = dhd_set_multicast_list, ++#else ++ .ndo_set_multicast_list = dhd_set_multicast_list, ++#endif ++}; ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) */ ++ ++dhd_pub_t * ++dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) ++{ ++ dhd_info_t *dhd = NULL; ++ struct net_device *net = NULL; ++ ++ dhd_attach_states_t dhd_state = DHD_ATTACH_STATE_INIT; ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ AP6210_DEBUG("%s, firmware path %s\n", __func__, firmware_path); ++ ++ /* updates firmware nvram path if it was provided as module parameters */ ++ if ((firmware_path != NULL) && (firmware_path[0] != '\0')) ++ COPY_FW_PATH_BY_CHIP(bus, fw_path, firmware_path); ++ if (strlen(nvram_path) != 0) { ++ strncpy(nv_path, nvram_path, sizeof(nv_path) -1); ++ nv_path[sizeof(nv_path) -1] = '\0'; ++ } ++ ++ /* Allocate etherdev, including space for private structure */ ++ if (!(net = alloc_etherdev(sizeof(dhd)))) { ++ AP6210_ERR("%s: OOM - alloc_etherdev\n", __FUNCTION__); ++ goto fail; ++ } ++ dhd_state |= DHD_ATTACH_STATE_NET_ALLOC; ++ ++ /* Allocate primary dhd_info */ ++ if (!(dhd = MALLOC(osh, sizeof(dhd_info_t)))) { ++ AP6210_ERR("%s: OOM - alloc dhd_info\n", __FUNCTION__); ++ goto fail; ++ } ++ memset(dhd, 0, sizeof(dhd_info_t)); ++ ++#ifdef DHDTHREAD ++ dhd->thr_dpc_ctl.thr_pid = DHD_PID_KT_TL_INVALID; ++ dhd->thr_wdt_ctl.thr_pid = DHD_PID_KT_INVALID; ++#endif /* DHDTHREAD */ ++ dhd->dhd_tasklet_create = FALSE; ++ dhd->thr_sysioc_ctl.thr_pid = DHD_PID_KT_INVALID; ++ dhd_state |= DHD_ATTACH_STATE_DHD_ALLOC; ++ ++ /* ++ * Save the dhd_info into the priv ++ */ ++ memcpy((void *)netdev_priv(net), &dhd, sizeof(dhd)); ++ dhd->pub.osh = osh; ++ ++ /* Link to info module */ ++ dhd->pub.info = dhd; ++ /* Link to bus module */ ++ dhd->pub.bus = bus; ++ dhd->pub.hdrlen = bus_hdrlen; ++ ++ /* Set network interface name if it was provided as module parameter */ ++ if (iface_name[0]) { ++ int len; ++ char ch; ++ strncpy(net->name, iface_name, IFNAMSIZ); ++ net->name[IFNAMSIZ - 1] = 0; ++ len = strlen(net->name); ++ ch = net->name[len - 1]; ++ if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2)) ++ strcat(net->name, "%d"); ++ } ++ ++ if (dhd_add_if(dhd, 0, (void *)net, net->name, NULL, 0, 0) == DHD_BAD_IF) ++ goto fail; ++ dhd_state |= DHD_ATTACH_STATE_ADD_IF; ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) ++ net->open = NULL; ++#else ++ net->netdev_ops = NULL; ++#endif ++ ++ sema_init(&dhd->proto_sem, 1); ++ ++#ifdef PROP_TXSTATUS ++ spin_lock_init(&dhd->wlfc_spinlock); ++#ifdef PROP_TXSTATUS_VSDB ++ dhd->pub.wlfc_enabled = FALSE; ++#else ++ dhd->pub.wlfc_enabled = TRUE; ++#endif /* PROP_TXSTATUS_VSDB */ ++#endif /* PROP_TXSTATUS */ ++ ++ /* Initialize other structure content */ ++ init_waitqueue_head(&dhd->ioctl_resp_wait); ++ init_waitqueue_head(&dhd->ctrl_wait); ++ ++ /* Initialize the spinlocks */ ++ spin_lock_init(&dhd->sdlock); ++ spin_lock_init(&dhd->txqlock); ++ spin_lock_init(&dhd->dhd_lock); ++ ++ /* Initialize Wakelock stuff */ ++ spin_lock_init(&dhd->wakelock_spinlock); ++ dhd->wakelock_counter = 0; ++ dhd->wakelock_wd_counter = 0; ++ dhd->wakelock_rx_timeout_enable = 0; ++ dhd->wakelock_ctrl_timeout_enable = 0; ++#ifdef CONFIG_HAS_WAKELOCK ++ dhd->wl_wifi = MALLOC(osh, sizeof(struct wake_lock)); ++ dhd->wl_rxwake = MALLOC(osh, sizeof(struct wake_lock)); ++ dhd->wl_ctrlwake = MALLOC(osh, sizeof(struct wake_lock)); ++ dhd->wl_wdwake = MALLOC(osh, sizeof(struct wake_lock)); ++ if (!dhd->wl_wifi || !dhd->wl_rxwake || !dhd->wl_ctrlwake || !dhd->wl_wdwake) { ++ AP6210_ERR("%s: mem alloc for wake lock failed\n", __FUNCTION__); ++ goto fail; ++ } ++ wake_lock_init(dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake"); ++ wake_lock_init(dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake"); ++ wake_lock_init(dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake"); ++ wake_lock_init(dhd->wl_wdwake, WAKE_LOCK_SUSPEND, "wlan_wd_wake"); ++#endif /* CONFIG_HAS_WAKELOCK */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ mutex_init(&dhd->dhd_net_if_mutex); ++ mutex_init(&dhd->dhd_suspend_mutex); ++#endif ++ dhd_state |= DHD_ATTACH_STATE_WAKELOCKS_INIT; ++ ++ /* Attach and link in the protocol */ ++ if (dhd_prot_attach(&dhd->pub) != 0) { ++ AP6210_ERR("dhd_prot_attach failed\n"); ++ goto fail; ++ } ++ dhd_state |= DHD_ATTACH_STATE_PROT_ATTACH; ++ ++#ifdef WL_CFG80211 ++ /* Attach and link in the cfg80211 */ ++ if (unlikely(wl_cfg80211_attach(net, &dhd->pub))) { ++ AP6210_ERR("wl_cfg80211_attach failed\n"); ++ goto fail; ++ } ++ ++ dhd_monitor_init(&dhd->pub); ++ dhd_state |= DHD_ATTACH_STATE_CFG80211; ++#endif ++#if defined(CONFIG_WIRELESS_EXT) ++ /* Attach and link in the iw */ ++ if (!(dhd_state & DHD_ATTACH_STATE_CFG80211)) { ++ if (wl_iw_attach(net, (void *)&dhd->pub) != 0) { ++ AP6210_ERR("wl_iw_attach failed\n"); ++ goto fail; ++ } ++ dhd_state |= DHD_ATTACH_STATE_WL_ATTACH; ++ } ++#endif /* defined(CONFIG_WIRELESS_EXT) */ ++ ++ ++ /* Set up the watchdog timer */ ++ init_timer(&dhd->timer); ++ dhd->timer.data = (ulong)dhd; ++ dhd->timer.function = dhd_watchdog; ++ ++#ifdef DHDTHREAD ++ /* Initialize thread based operation and lock */ ++ sema_init(&dhd->sdsem, 1); ++ if ((dhd_watchdog_prio >= 0) && (dhd_dpc_prio >= 0)) { ++ dhd->threads_only = TRUE; ++ } ++ else { ++ dhd->threads_only = FALSE; ++ } ++ ++ if (dhd_watchdog_prio >= 0) { ++ /* Initialize watchdog thread */ ++#ifdef USE_KTHREAD_API ++ PROC_START2(dhd_watchdog_thread, dhd, &dhd->thr_wdt_ctl, 0, "dhd_watchdog_thread"); ++#else ++ PROC_START(dhd_watchdog_thread, dhd, &dhd->thr_wdt_ctl, 0); ++#endif ++ } else { ++ dhd->thr_wdt_ctl.thr_pid = -1; ++ } ++ ++ /* Set up the bottom half handler */ ++ if (dhd_dpc_prio >= 0) { ++ /* Initialize DPC thread */ ++#ifdef USE_KTHREAD_API ++ PROC_START2(dhd_dpc_thread, dhd, &dhd->thr_dpc_ctl, 0, "dhd_dpc"); ++#else ++ PROC_START(dhd_dpc_thread, dhd, &dhd->thr_dpc_ctl, 0); ++#endif ++ } else { ++ /* use tasklet for dpc */ ++ tasklet_init(&dhd->tasklet, dhd_dpc, (ulong)dhd); ++ dhd->thr_dpc_ctl.thr_pid = -1; ++ } ++#else ++ /* Set up the bottom half handler */ ++ tasklet_init(&dhd->tasklet, dhd_dpc, (ulong)dhd); ++ dhd->dhd_tasklet_create = TRUE; ++#endif /* DHDTHREAD */ ++ ++ if (dhd_sysioc) { ++#ifdef USE_KTHREAD_API ++ PROC_START2(_dhd_sysioc_thread, dhd, &dhd->thr_sysioc_ctl, 0, "dhd_sysioc"); ++#else ++ PROC_START(_dhd_sysioc_thread, dhd, &dhd->thr_sysioc_ctl, 0); ++#endif ++ } else { ++ dhd->thr_sysioc_ctl.thr_pid = -1; ++ } ++ dhd_state |= DHD_ATTACH_STATE_THREADS_CREATED; ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (1) ++ INIT_WORK(&dhd->work_hang, dhd_hang_process); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++ /* ++ * Save the dhd_info into the priv ++ */ ++ memcpy(netdev_priv(net), &dhd, sizeof(dhd)); ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) ++ register_pm_notifier(&dhd_sleep_pm_notifier); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ ++ ++#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) ++ dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20; ++ dhd->early_suspend.suspend = dhd_early_suspend; ++ dhd->early_suspend.resume = dhd_late_resume; ++ register_early_suspend(&dhd->early_suspend); ++ dhd_state |= DHD_ATTACH_STATE_EARLYSUSPEND_DONE; ++#endif ++ ++#ifdef ARP_OFFLOAD_SUPPORT ++ dhd->pend_ipaddr = 0; ++ register_inetaddr_notifier(&dhd_notifier); ++#endif /* ARP_OFFLOAD_SUPPORT */ ++#ifdef IPV6 ++ register_inet6addr_notifier(&dhd_notifier_ipv6); ++#endif ++ ++#ifdef DHDTCPACK_SUPPRESS ++ dhd->pub.tcp_ack_info_cnt = 0; ++ bzero(dhd->pub.tcp_ack_info_tbl, sizeof(struct tcp_ack_info)*MAXTCPSTREAMS); ++#endif /* DHDTCPACK_SUPPRESS */ ++ ++ dhd_state |= DHD_ATTACH_STATE_DONE; ++ dhd->dhd_state = dhd_state; ++ return &dhd->pub; ++ ++fail: ++ if (dhd_state < DHD_ATTACH_STATE_DHD_ALLOC) { ++ if (net) free_netdev(net); ++ } else { ++ AP6210_DEBUG("%s: Calling dhd_detach dhd_state 0x%x &dhd->pub %p\n", ++ __FUNCTION__, dhd_state, &dhd->pub); ++ dhd->dhd_state = dhd_state; ++ dhd_detach(&dhd->pub); ++ dhd_free(&dhd->pub); ++ } ++ ++ return NULL; ++} ++ ++int ++dhd_bus_start(dhd_pub_t *dhdp) ++{ ++ int ret = -1; ++ dhd_info_t *dhd = (dhd_info_t*)dhdp->info; ++ unsigned long flags; ++ ++ ASSERT(dhd); ++ ++ AP6210_DEBUG("Enter %s:\n", __FUNCTION__); ++ ++#ifdef DHDTHREAD ++ if (dhd->threads_only) ++ dhd_os_sdlock(dhdp); ++#endif /* DHDTHREAD */ ++ ++ ++ /* try to download image and nvram to the dongle */ ++ if ((dhd->pub.busstate == DHD_BUS_DOWN) && ++ (fw_path != NULL) && (fw_path[0] != '\0') && ++ (nv_path != NULL) && (nv_path[0] != '\0')) { ++ /* wake lock moved to dhdsdio_download_firmware */ ++ if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh, ++ fw_path, nv_path))) { ++ AP6210_ERR("%s: dhdsdio_probe_download failed. firmware = %s nvram = %s\n", ++ __FUNCTION__, fw_path, nv_path); ++#ifdef DHDTHREAD ++ if (dhd->threads_only) ++ dhd_os_sdunlock(dhdp); ++#endif /* DHDTHREAD */ ++ return -1; ++ } ++ } ++ if (dhd->pub.busstate != DHD_BUS_LOAD) { ++#ifdef DHDTHREAD ++ if (dhd->threads_only) ++ dhd_os_sdunlock(dhdp); ++#endif /* DHDTHREAD */ ++ return -ENETDOWN; ++ } ++ ++ /* Start the watchdog timer */ ++ dhd->pub.tickcnt = 0; ++ dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms); ++ ++ /* Bring up the bus */ ++ if ((ret = dhd_bus_init(&dhd->pub, FALSE)) != 0) { ++ ++ AP6210_ERR("%s, dhd_bus_init failed %d\n", __FUNCTION__, ret); ++#ifdef DHDTHREAD ++ if (dhd->threads_only) ++ dhd_os_sdunlock(dhdp); ++#endif /* DHDTHREAD */ ++ return ret; ++ } ++ bcmsdh_set_drvdata(dhdp); ++#if defined(OOB_INTR_ONLY) ++ /* Host registration for OOB interrupt */ ++ if (bcmsdh_register_oob_intr(dhdp)) { ++ /* deactivate timer and wait for the handler to finish */ ++ ++ flags = dhd_os_spin_lock(&dhd->pub); ++ dhd->wd_timer_valid = FALSE; ++ dhd_os_spin_unlock(&dhd->pub, flags); ++ del_timer_sync(&dhd->timer); ++ AP6210_ERR("%s Host failed to register for OOB\n", __FUNCTION__); ++#ifdef DHDTHREAD ++ if (dhd->threads_only) ++ dhd_os_sdunlock(dhdp); ++#endif /* DHDTHREAD */ ++ DHD_OS_WD_WAKE_UNLOCK(&dhd->pub); ++ return -ENODEV; ++ } ++ ++ /* Enable oob at firmware */ ++ dhd_enable_oob_intr(dhd->pub.bus, TRUE); ++#endif ++ ++ /* If bus is not ready, can't come up */ ++ if (dhd->pub.busstate != DHD_BUS_DATA) { ++ flags = dhd_os_spin_lock(&dhd->pub); ++ dhd->wd_timer_valid = FALSE; ++ dhd_os_spin_unlock(&dhd->pub, flags); ++ del_timer_sync(&dhd->timer); ++ AP6210_ERR("%s failed bus is not ready\n", __FUNCTION__); ++#ifdef DHDTHREAD ++ if (dhd->threads_only) ++ dhd_os_sdunlock(dhdp); ++#endif /* DHDTHREAD */ ++ DHD_OS_WD_WAKE_UNLOCK(&dhd->pub); ++ return -ENODEV; ++ } ++ ++#ifdef DHDTHREAD ++ if (dhd->threads_only) ++ dhd_os_sdunlock(dhdp); ++#endif /* DHDTHREAD */ ++ ++#ifdef BCMSDIOH_TXGLOM ++ if ((dhd->pub.busstate == DHD_BUS_DATA) && bcmsdh_glom_enabled()) { ++ dhd_txglom_enable(dhdp, TRUE); ++ } ++#endif ++ ++#ifdef READ_MACADDR ++ dhd_read_macaddr(dhd); ++#endif ++ ++ /* Bus is ready, do any protocol initialization */ ++ if ((ret = dhd_prot_init(&dhd->pub)) < 0) ++ return ret; ++ ++#ifdef WRITE_MACADDR ++ dhd_write_macaddr(dhd->pub.mac.octet); ++#endif ++ ++#ifdef ARP_OFFLOAD_SUPPORT ++ if (dhd->pend_ipaddr) { ++#ifdef AOE_IP_ALIAS_SUPPORT ++ aoe_update_host_ipv4_table(&dhd->pub, dhd->pend_ipaddr, TRUE, 0); ++#endif /* AOE_IP_ALIAS_SUPPORT */ ++ dhd->pend_ipaddr = 0; ++ } ++#endif /* ARP_OFFLOAD_SUPPORT */ ++ ++ return 0; ++} ++ ++bool dhd_is_concurrent_mode(dhd_pub_t *dhd) ++{ ++ if (!dhd) ++ return FALSE; ++ ++ if (dhd->op_mode & DHD_FLAG_CONCURR_MULTI_CHAN_MODE) ++ return TRUE; ++ else if ((dhd->op_mode & DHD_FLAG_CONCURR_SINGLE_CHAN_MODE) == ++ DHD_FLAG_CONCURR_SINGLE_CHAN_MODE) ++ return TRUE; ++ else ++ return FALSE; ++} ++ ++#if !defined(AP) && defined(WLP2P) ++/* From Android JerryBean release, the concurrent mode is enabled by default and the firmware ++ * name would be fw_bcmdhd.bin. So we need to determine whether P2P is enabled in the STA ++ * firmware and accordingly enable concurrent mode (Apply P2P settings). SoftAP firmware ++ * would still be named as fw_bcmdhd_apsta. ++ */ ++uint32 ++dhd_get_concurrent_capabilites(dhd_pub_t *dhd) ++{ ++ int32 ret = 0; ++ char buf[WLC_IOCTL_SMLEN]; ++ bool mchan_supported = FALSE; ++ /* if dhd->op_mode is already set for HOSTAP, ++ * that means we only will use the mode as it is ++ */ ++ if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) ++ return 0; ++ memset(buf, 0, sizeof(buf)); ++ bcm_mkiovar("cap", 0, 0, buf, sizeof(buf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), ++ FALSE, 0)) < 0) { ++ AP6210_ERR("%s: Get Capability failed (error=%d)\n", ++ __FUNCTION__, ret); ++ return 0; ++ } ++ if (strstr(buf, "vsdb")) { ++ mchan_supported = TRUE; ++ } ++ if (strstr(buf, "p2p") == NULL) { ++ AP6210_DEBUG("Chip does not support p2p\n"); ++ return 0; ++ } ++ else { ++ /* Chip supports p2p but ensure that p2p is really implemented in firmware or not */ ++ memset(buf, 0, sizeof(buf)); ++ bcm_mkiovar("p2p", 0, 0, buf, sizeof(buf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), ++ FALSE, 0)) < 0) { ++ AP6210_ERR("%s: Get P2P failed (error=%d)\n", __FUNCTION__, ret); ++ return 0; ++ } ++ else { ++ if (buf[0] == 1) { ++ /* By default, chip supports single chan concurrency, ++ * now lets check for mchan ++ */ ++ ret = DHD_FLAG_CONCURR_SINGLE_CHAN_MODE; ++ if (mchan_supported) ++ ret |= DHD_FLAG_CONCURR_MULTI_CHAN_MODE; ++#if defined(WL_ENABLE_P2P_IF) ++ /* For customer_hw4, although ICS, ++ * we still support concurrent mode ++ */ ++ return ret; ++#else ++ return 0; ++#endif ++ } ++ } ++ } ++ return 0; ++} ++#endif ++int ++dhd_preinit_ioctls(dhd_pub_t *dhd) ++{ ++ int ret = 0; ++ char eventmask[WL_EVENTING_MASK_LEN]; ++ char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ ++ ++#if !defined(WL_CFG80211) ++ uint up = 0; ++#endif /* !defined(WL_CFG80211) */ ++ uint power_mode = PM_FAST; ++ uint32 dongle_align = DHD_SDALIGN; ++ uint32 glom = CUSTOM_GLOM_SETTING; ++#if defined(VSDB) || defined(ROAM_ENABLE) ++ uint bcn_timeout = 8; ++#else ++ uint bcn_timeout = 4; ++#endif ++#ifdef ENABLE_BCN_LI_BCN_WAKEUP ++ uint32 bcn_li_bcn = 1; ++#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ ++ uint retry_max = 3; ++#if defined(ARP_OFFLOAD_SUPPORT) ++ int arpoe = 1; ++#endif ++ int scan_assoc_time = DHD_SCAN_ASSOC_ACTIVE_TIME; ++ int scan_unassoc_time = DHD_SCAN_UNASSOC_ACTIVE_TIME; ++ int scan_passive_time = DHD_SCAN_PASSIVE_TIME; ++ char buf[WLC_IOCTL_SMLEN]; ++ char *ptr; ++ uint32 listen_interval = LISTEN_INTERVAL; /* Default Listen Interval in Beacons */ ++#ifdef ROAM_ENABLE ++ uint roamvar = 0; ++ int roam_trigger[2] = {CUSTOM_ROAM_TRIGGER_SETTING, WLC_BAND_ALL}; ++ int roam_scan_period[2] = {10, WLC_BAND_ALL}; ++ int roam_delta[2] = {CUSTOM_ROAM_DELTA_SETTING, WLC_BAND_ALL}; ++#ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC ++ int roam_fullscan_period = 60; ++#else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */ ++ int roam_fullscan_period = 120; ++#endif /* FULL_ROAMING_SCAN_PERIOD_60_SEC */ ++#else ++#ifdef DISABLE_BUILTIN_ROAM ++ uint roamvar = 1; ++#endif /* DISABLE_BUILTIN_ROAM */ ++#endif /* ROAM_ENABLE */ ++ ++#if defined(SOFTAP) ++ uint dtim = 1; ++#endif ++#if (defined(AP) && !defined(WLP2P)) || (!defined(AP) && defined(WL_CFG80211)) ++ uint32 mpc = 0; /* Turn MPC off for AP/APSTA mode */ ++ struct ether_addr p2p_ea; ++#endif ++ uint32 mimo_bw_cap = 1; /* Turn HT40 on in 2.4 GHz */ ++ ++#if defined(AP) || defined(WLP2P) ++ uint32 apsta = 1; /* Enable APSTA mode */ ++#endif /* defined(AP) || defined(WLP2P) */ ++#ifdef GET_CUSTOM_MAC_ENABLE ++ struct ether_addr ea_addr; ++#endif /* GET_CUSTOM_MAC_ENABLE */ ++#ifdef DISABLE_11N ++ uint32 nmode = 0; ++#else ++#ifdef AMPDU_HOSTREORDER ++ uint32 hostreorder = 1; ++#endif ++#endif /* DISABLE_11N */ ++ dhd->suspend_bcn_li_dtim = CUSTOM_SUSPEND_BCN_LI_DTIM; ++#ifdef PROP_TXSTATUS ++#ifdef PROP_TXSTATUS_VSDB ++ dhd->wlfc_enabled = FALSE; ++ /* enable WLFC only if the firmware is VSDB */ ++#else ++ dhd->wlfc_enabled = TRUE; ++#endif /* PROP_TXSTATUS_VSDB */ ++#endif /* PROP_TXSTATUS */ ++ AP6210_DEBUG("Enter %s\n", __FUNCTION__); ++ dhd->op_mode = 0; ++#ifdef GET_CUSTOM_MAC_ENABLE ++ ret = dhd_custom_get_mac_address(ea_addr.octet); ++ if (!ret) { ++ memset(buf, 0, sizeof(buf)); ++ bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf)); ++ ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); ++ if (ret < 0) { ++ AP6210_ERR("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret); ++ return BCME_NOTUP; ++ } ++ memcpy(dhd->mac.octet, ea_addr.octet, ETHER_ADDR_LEN); ++ } else { ++#endif /* GET_CUSTOM_MAC_ENABLE */ ++ /* Get the default device MAC address directly from firmware */ ++ memset(buf, 0, sizeof(buf)); ++ bcm_mkiovar("cur_etheraddr", 0, 0, buf, sizeof(buf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), ++ FALSE, 0)) < 0) { ++ AP6210_ERR("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret); ++ return BCME_NOTUP; ++ } ++ /* Update public MAC address after reading from Firmware */ ++ memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN); ++ ++#ifdef GET_CUSTOM_MAC_ENABLE ++ } ++#endif /* GET_CUSTOM_MAC_ENABLE */ ++ ++ AP6210_DEBUG("Firmware = %s\n", fw_path); ++ ++ if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || ++ (op_mode == DHD_FLAG_HOSTAP_MODE)) { ++#ifdef SET_RANDOM_MAC_SOFTAP ++ uint rand_mac; ++#endif ++ dhd->op_mode = DHD_FLAG_HOSTAP_MODE; ++#if defined(ARP_OFFLOAD_SUPPORT) ++ arpoe = 0; ++#endif ++#ifdef PKT_FILTER_SUPPORT ++ dhd_pkt_filter_enable = FALSE; ++#endif ++#ifdef SET_RANDOM_MAC_SOFTAP ++ srandom32((uint)jiffies); ++ rand_mac = random32(); ++ iovbuf[0] = 0x02; /* locally administered bit */ ++ iovbuf[1] = 0x1A; ++ iovbuf[2] = 0x11; ++ iovbuf[3] = (unsigned char)(rand_mac & 0x0F) | 0xF0; ++ iovbuf[4] = (unsigned char)(rand_mac >> 8); ++ iovbuf[5] = (unsigned char)(rand_mac >> 16); ++ ++ bcm_mkiovar("cur_etheraddr", (void *)iovbuf, ETHER_ADDR_LEN, buf, sizeof(buf)); ++ ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); ++ if (ret < 0) { ++ AP6210_ERR("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret); ++ } else ++ memcpy(dhd->mac.octet, iovbuf, ETHER_ADDR_LEN); ++#endif /* SET_RANDOM_MAC_SOFTAP */ ++#if !defined(AP) && defined(WL_CFG80211) ++ /* Turn off MPC in AP mode */ ++ bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, ++ sizeof(iovbuf), TRUE, 0)) < 0) { ++ AP6210_ERR("%s mpc for HostAPD failed %d\n", __FUNCTION__, ret); ++ } ++#endif ++ ++ } ++ else { ++ uint32 concurrent_mode = 0; ++ if ((!op_mode && strstr(fw_path, "_p2p") != NULL) || ++ (op_mode == DHD_FLAG_P2P_MODE)) { ++#if defined(ARP_OFFLOAD_SUPPORT) ++ arpoe = 0; ++#endif ++#ifdef PKT_FILTER_SUPPORT ++ dhd_pkt_filter_enable = FALSE; ++#endif ++ dhd->op_mode = DHD_FLAG_P2P_MODE; ++ } ++ else ++ dhd->op_mode = DHD_FLAG_STA_MODE; ++#if !defined(AP) && defined(WLP2P) ++ if ((concurrent_mode = dhd_get_concurrent_capabilites(dhd))) { ++#if defined(ARP_OFFLOAD_SUPPORT) ++ arpoe = 1; ++#endif ++ dhd->op_mode |= concurrent_mode; ++ } ++ ++ /* Check if we are enabling p2p */ ++ if (dhd->op_mode & DHD_FLAG_P2P_MODE) { ++ bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, ++ iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { ++ AP6210_ERR("%s APSTA for P2P failed ret= %d\n", __FUNCTION__, ret); ++ } ++ ++ memcpy(&p2p_ea, &dhd->mac, ETHER_ADDR_LEN); ++ ETHER_SET_LOCALADDR(&p2p_ea); ++ bcm_mkiovar("p2p_da_override", (char *)&p2p_ea, ++ ETHER_ADDR_LEN, iovbuf, sizeof(iovbuf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, ++ iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { ++ AP6210_ERR("%s p2p_da_override ret= %d\n", __FUNCTION__, ret); ++ } else { ++ AP6210_DEBUG("dhd_preinit_ioctls: p2p_da_override succeeded\n"); ++ } ++ } ++#else ++ (void)concurrent_mode; ++#endif ++ } ++ ++ AP6210_ERR("Firmware up: op_mode=0x%04x, " ++ "Broadcom Dongle Host Driver mac="MACDBG"\n", ++ dhd->op_mode, ++ MAC2STRDBG(dhd->mac.octet)); ++ /* Set Country code */ ++ if (dhd->dhd_cspec.ccode[0] != 0) { ++ bcm_mkiovar("country", (char *)&dhd->dhd_cspec, ++ sizeof(wl_country_t), iovbuf, sizeof(iovbuf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) ++ AP6210_ERR("%s: country code setting failed\n", __FUNCTION__); ++ } ++ ++ /* Set Listen Interval */ ++ bcm_mkiovar("assoc_listen", (char *)&listen_interval, 4, iovbuf, sizeof(iovbuf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) ++ AP6210_ERR("%s assoc_listen failed %d\n", __FUNCTION__, ret); ++ ++#if defined(ROAM_ENABLE) || defined(DISABLE_BUILTIN_ROAM) ++ /* Disable built-in roaming to allowed ext supplicant to take care of roaming */ ++ bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++#endif /* ROAM_ENABLE || DISABLE_BUILTIN_ROAM */ ++#ifdef ROAM_ENABLE ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_TRIGGER, roam_trigger, ++ sizeof(roam_trigger), TRUE, 0)) < 0) ++ AP6210_ERR("%s: roam trigger set failed %d\n", __FUNCTION__, ret); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_SCAN_PERIOD, roam_scan_period, ++ sizeof(roam_scan_period), TRUE, 0)) < 0) ++ AP6210_ERR("%s: roam scan period set failed %d\n", __FUNCTION__, ret); ++ if ((dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_DELTA, roam_delta, ++ sizeof(roam_delta), TRUE, 0)) < 0) ++ AP6210_ERR("%s: roam delta set failed %d\n", __FUNCTION__, ret); ++ bcm_mkiovar("fullroamperiod", (char *)&roam_fullscan_period, 4, iovbuf, sizeof(iovbuf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) ++ AP6210_ERR("%s: roam fullscan period set failed %d\n", __FUNCTION__, ret); ++#endif /* ROAM_ENABLE */ ++ ++ /* Set PowerSave mode */ ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0); ++ ++ /* Match Host and Dongle rx alignment */ ++ bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++ ++ if (glom != DEFAULT_GLOM_VALUE) { ++ AP6210_DEBUG("%s set glom=0x%X\n", __FUNCTION__, glom); ++ bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++ } ++ ++ /* Setup timeout if Beacons are lost and roam is off to report link down */ ++ bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++ /* Setup assoc_retry_max count to reconnect target AP in dongle */ ++ bcm_mkiovar("assoc_retry_max", (char *)&retry_max, 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++#if defined(AP) && !defined(WLP2P) ++ /* Turn off MPC in AP mode */ ++ bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++ bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++#endif /* defined(AP) && !defined(WLP2P) */ ++ ++ if (dhd_bus_chip_id(dhd) == BCM43341_CHIP_ID || dhd_bus_chip_id(dhd) == BCM4324_CHIP_ID) { ++ /* Turn on HT40 in 2.4 GHz */ ++ bcm_mkiovar("mimo_bw_cap", (char *)&mimo_bw_cap, 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++ } ++ ++#if defined(SOFTAP) ++ if (ap_fw_loaded == TRUE) { ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_DTIMPRD, (char *)&dtim, sizeof(dtim), TRUE, 0); ++ } ++#endif ++ ++#if defined(KEEP_ALIVE) ++ { ++ /* Set Keep Alive : be sure to use FW with -keepalive */ ++ int res; ++ ++#if defined(SOFTAP) ++ if (ap_fw_loaded == FALSE) ++#endif ++ if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) { ++ if ((res = dhd_keep_alive_onoff(dhd)) < 0) ++ AP6210_ERR("%s set keeplive failed %d\n", ++ __FUNCTION__, res); ++ } ++ } ++#endif /* defined(KEEP_ALIVE) */ ++ ++ /* Read event_msgs mask */ ++ bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) { ++ AP6210_ERR("%s read Event mask failed %d\n", __FUNCTION__, ret); ++ goto done; ++ } ++ bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN); ++ ++ /* Setup event_msgs */ ++ setbit(eventmask, WLC_E_SET_SSID); ++ setbit(eventmask, WLC_E_PRUNE); ++ setbit(eventmask, WLC_E_AUTH); ++ setbit(eventmask, WLC_E_ASSOC); ++ setbit(eventmask, WLC_E_REASSOC); ++ setbit(eventmask, WLC_E_REASSOC_IND); ++ setbit(eventmask, WLC_E_DEAUTH); ++ setbit(eventmask, WLC_E_DEAUTH_IND); ++ setbit(eventmask, WLC_E_DISASSOC_IND); ++ setbit(eventmask, WLC_E_DISASSOC); ++ setbit(eventmask, WLC_E_JOIN); ++ setbit(eventmask, WLC_E_ASSOC_IND); ++ setbit(eventmask, WLC_E_PSK_SUP); ++ setbit(eventmask, WLC_E_LINK); ++ setbit(eventmask, WLC_E_NDIS_LINK); ++ setbit(eventmask, WLC_E_MIC_ERROR); ++ setbit(eventmask, WLC_E_ASSOC_REQ_IE); ++ setbit(eventmask, WLC_E_ASSOC_RESP_IE); ++#ifndef WL_CFG80211 ++ setbit(eventmask, WLC_E_PMKID_CACHE); ++ setbit(eventmask, WLC_E_TXFAIL); ++#endif ++ setbit(eventmask, WLC_E_JOIN_START); ++ setbit(eventmask, WLC_E_SCAN_COMPLETE); ++#ifdef WLMEDIA_HTSF ++ setbit(eventmask, WLC_E_HTSFSYNC); ++#endif /* WLMEDIA_HTSF */ ++#ifdef PNO_SUPPORT ++ setbit(eventmask, WLC_E_PFN_NET_FOUND); ++#endif /* PNO_SUPPORT */ ++ /* enable dongle roaming event */ ++ setbit(eventmask, WLC_E_ROAM); ++#ifdef WL_CFG80211 ++ setbit(eventmask, WLC_E_ESCAN_RESULT); ++ if (dhd->op_mode & DHD_FLAG_P2P_MODE) { ++ setbit(eventmask, WLC_E_ACTION_FRAME_RX); ++ setbit(eventmask, WLC_E_P2P_DISC_LISTEN_COMPLETE); ++ } ++#endif /* WL_CFG80211 */ ++ ++ /* Write updated Event mask */ ++ bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { ++ AP6210_ERR("%s Set Event mask failed %d\n", __FUNCTION__, ret); ++ goto done; ++ } ++ ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_CHANNEL_TIME, (char *)&scan_assoc_time, ++ sizeof(scan_assoc_time), TRUE, 0); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time, ++ sizeof(scan_unassoc_time), TRUE, 0); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_PASSIVE_TIME, (char *)&scan_passive_time, ++ sizeof(scan_passive_time), TRUE, 0); ++ ++#ifdef ARP_OFFLOAD_SUPPORT ++ /* Set and enable ARP offload feature for STA only */ ++#if defined(SOFTAP) ++ if (arpoe && !ap_fw_loaded) { ++#else ++ if (arpoe) { ++#endif ++ dhd_arp_offload_enable(dhd, TRUE); ++ dhd_arp_offload_set(dhd, dhd_arp_mode); ++ } else { ++ dhd_arp_offload_enable(dhd, FALSE); ++ dhd_arp_offload_set(dhd, 0); ++ } ++ dhd_arp_enable = arpoe; ++#endif /* ARP_OFFLOAD_SUPPORT */ ++ ++#ifdef PKT_FILTER_SUPPORT ++ /* Setup default defintions for pktfilter , enable in suspend */ ++ dhd->pktfilter_count = 5; ++ /* Setup filter to allow only unicast */ ++ dhd->pktfilter[0] = "100 0 0 0 0x01 0x00"; ++ dhd->pktfilter[1] = NULL; ++ dhd->pktfilter[2] = NULL; ++ dhd->pktfilter[3] = NULL; ++ /* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */ ++ dhd->pktfilter[4] = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB"; ++ dhd_set_packet_filter(dhd); ++ ++#if defined(SOFTAP) ++ if (ap_fw_loaded) { ++ dhd_enable_packet_filter(0, dhd); ++ } ++#endif /* defined(SOFTAP) */ ++ ++#endif /* PKT_FILTER_SUPPORT */ ++#ifdef DISABLE_11N ++ bcm_mkiovar("nmode", (char *)&nmode, 4, iovbuf, sizeof(iovbuf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) ++ AP6210_ERR("%s wl nmode 0 failed %d\n", __FUNCTION__, ret); ++#else ++#ifdef AMPDU_HOSTREORDER ++ bcm_mkiovar("ampdu_hostreorder", (char *)&hostreorder, 4, buf, sizeof(buf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); ++#endif /* AMPDU_HOSTREORDER */ ++#endif /* DISABLE_11N */ ++ ++#if !defined(WL_CFG80211) ++ /* Force STA UP */ ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0)) < 0) { ++ AP6210_ERR("%s Setting WL UP failed %d\n", __FUNCTION__, ret); ++ goto done; ++ } ++#endif ++ ++#ifdef ENABLE_BCN_LI_BCN_WAKEUP ++ bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn, 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ ++ ++ /* query for 'ver' to get version info from firmware */ ++ memset(buf, 0, sizeof(buf)); ++ ptr = buf; ++ bcm_mkiovar("ver", (char *)&buf, 4, buf, sizeof(buf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), FALSE, 0)) < 0) ++ AP6210_ERR("%s failed %d\n", __FUNCTION__, ret); ++ else { ++ bcmstrtok(&ptr, "\n", 0); ++ /* Print fw version info */ ++ AP6210_ERR("Firmware version = %s\n", buf); ++ ++ dhd_set_version_info(dhd, buf); ++ ++ DHD_BLOG(buf, strlen(buf) + 1); ++ DHD_BLOG(dhd_version, strlen(dhd_version) + 1); ++ DHD_BLOG(dhd_version_info, strlen(dhd_version_info) +1); ++ ++ /* Check and adjust IOCTL response timeout for Manufactring firmware */ ++ if (strstr(buf, MANUFACTRING_FW) != NULL) { ++ dhd_os_set_ioctl_resp_timeout(20000); ++ AP6210_ERR("%s : adjust IOCTL response time for Manufactring Firmware\n", ++ __FUNCTION__); ++ } ++ } ++ ++done: ++ return ret; ++} ++ ++ ++int ++dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, int set) ++{ ++ char buf[strlen(name) + 1 + cmd_len]; ++ int len = sizeof(buf); ++ wl_ioctl_t ioc; ++ int ret; ++ ++ len = bcm_mkiovar(name, cmd_buf, cmd_len, buf, len); ++ ++ memset(&ioc, 0, sizeof(ioc)); ++ ++ ioc.cmd = set? WLC_SET_VAR : WLC_GET_VAR; ++ ioc.buf = buf; ++ ioc.len = len; ++ ioc.set = TRUE; ++ ++ ret = dhd_wl_ioctl(pub, ifidx, &ioc, ioc.buf, ioc.len); ++ if (!set && ret >= 0) ++ memcpy(cmd_buf, buf, cmd_len); ++ ++ return ret; ++} ++ ++int dhd_change_mtu(dhd_pub_t *dhdp, int new_mtu, int ifidx) ++{ ++ struct dhd_info *dhd = dhdp->info; ++ struct net_device *dev = NULL; ++ ++ ASSERT(dhd && dhd->iflist[ifidx]); ++ dev = dhd->iflist[ifidx]->net; ++ ASSERT(dev); ++ ++ if (netif_running(dev)) { ++ AP6210_ERR("%s: Must be down to change its MTU", dev->name); ++ return BCME_NOTDOWN; ++ } ++ ++#define DHD_MIN_MTU 1500 ++#define DHD_MAX_MTU 1752 ++ ++ if ((new_mtu < DHD_MIN_MTU) || (new_mtu > DHD_MAX_MTU)) { ++ AP6210_ERR("%s: MTU size %d is invalid.\n", __FUNCTION__, new_mtu); ++ return BCME_BADARG; ++ } ++ ++ dev->mtu = new_mtu; ++ return 0; ++} ++ ++#ifdef ARP_OFFLOAD_SUPPORT ++/* add or remove AOE host ip(s) (up to 8 IPs on the interface) */ ++void ++aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add, int idx) ++{ ++ u32 ipv4_buf[MAX_IPV4_ENTRIES]; /* temp save for AOE host_ip table */ ++ int i; ++ int ret; ++ ++ bzero(ipv4_buf, sizeof(ipv4_buf)); ++ ++ /* display what we've got */ ++ ret = dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf), idx); ++ AP6210_DEBUG("%s: hostip table read from Dongle:\n", __FUNCTION__); ++#ifdef AOE_DBG ++ dhd_print_buf(ipv4_buf, 32, 4); /* max 8 IPs 4b each */ ++#endif ++ /* now we saved hoste_ip table, clr it in the dongle AOE */ ++ dhd_aoe_hostip_clr(dhd_pub, idx); ++ ++ if (ret) { ++ AP6210_ERR("%s failed\n", __FUNCTION__); ++ return; ++ } ++ ++ for (i = 0; i < MAX_IPV4_ENTRIES; i++) { ++ if (add && (ipv4_buf[i] == 0)) { ++ ipv4_buf[i] = ipa; ++ add = FALSE; /* added ipa to local table */ ++ AP6210_DEBUG("%s: Saved new IP in temp arp_hostip[%d]\n", ++ __FUNCTION__, i); ++ } else if (ipv4_buf[i] == ipa) { ++ ipv4_buf[i] = 0; ++ AP6210_DEBUG("%s: removed IP:%x from temp table %d\n", ++ __FUNCTION__, ipa, i); ++ } ++ ++ if (ipv4_buf[i] != 0) { ++ /* add back host_ip entries from our local cache */ ++ dhd_arp_offload_add_ip(dhd_pub, ipv4_buf[i], idx); ++ AP6210_DEBUG("%s: added IP:%x to dongle arp_hostip[%d]\n\n", ++ __FUNCTION__, ipv4_buf[i], i); ++ } ++ } ++#ifdef AOE_DBG ++ /* see the resulting hostip table */ ++ dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf), idx); ++ AP6210_DEBUG("%s: read back arp_hostip table:\n", __FUNCTION__); ++ dhd_print_buf(ipv4_buf, 32, 4); /* max 8 IPs 4b each */ ++#endif ++} ++ ++/* ++ * Notification mechanism from kernel to our driver. This function is called by the Linux kernel ++ * whenever there is an event related to an IP address. ++ * ptr : kernel provided pointer to IP address that has changed ++ */ ++static int dhd_device_event(struct notifier_block *this, ++ unsigned long event, ++ void *ptr) ++{ ++ struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; ++ ++ dhd_info_t *dhd; ++ dhd_pub_t *dhd_pub; ++ int idx; ++ ++ if (!dhd_arp_enable) ++ return NOTIFY_DONE; ++ if (!ifa || !(ifa->ifa_dev->dev)) ++ return NOTIFY_DONE; ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) ++ /* Filter notifications meant for non Broadcom devices */ ++ if ((ifa->ifa_dev->dev->netdev_ops != &dhd_ops_pri) && ++ (ifa->ifa_dev->dev->netdev_ops != &dhd_ops_virt)) { ++#ifdef WLP2P ++ if (!wl_cfgp2p_is_ifops(ifa->ifa_dev->dev->netdev_ops)) ++#endif ++ return NOTIFY_DONE; ++ } ++#endif /* LINUX_VERSION_CODE */ ++ ++ dhd = *(dhd_info_t **)netdev_priv(ifa->ifa_dev->dev); ++ if (!dhd) ++ return NOTIFY_DONE; ++ ++ dhd_pub = &dhd->pub; ++ ++ if (dhd_pub->arp_version == 1) { ++ idx = 0; ++ } ++ else { ++ for (idx = 0; idx < DHD_MAX_IFS; idx++) { ++ if (dhd->iflist[idx] && dhd->iflist[idx]->net == ifa->ifa_dev->dev) ++ break; ++ } ++ if (idx < DHD_MAX_IFS) ++ AP6210_DEBUG("ifidx : %p %s %d\n", dhd->iflist[idx]->net, ++ dhd->iflist[idx]->name, dhd->iflist[idx]->idx); ++ else { ++ AP6210_ERR("Cannot find ifidx for(%s) set to 0\n", ifa->ifa_label); ++ idx = 0; ++ } ++ } ++ ++ switch (event) { ++ case NETDEV_UP: ++ AP6210_DEBUG("%s: [%s] Up IP: 0x%x\n", ++ __FUNCTION__, ifa->ifa_label, ifa->ifa_address); ++ ++ if (dhd->pub.busstate != DHD_BUS_DATA) { ++ AP6210_ERR("%s: bus not ready, exit\n", __FUNCTION__); ++ if (dhd->pend_ipaddr) { ++ AP6210_ERR("%s: overwrite pending ipaddr: 0x%x\n", ++ __FUNCTION__, dhd->pend_ipaddr); ++ } ++ dhd->pend_ipaddr = ifa->ifa_address; ++ break; ++ } ++ ++#ifdef AOE_IP_ALIAS_SUPPORT ++ AP6210_DEBUG("%s:add aliased IP to AOE hostip cache\n", ++ __FUNCTION__); ++ aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE, idx); ++#endif ++ break; ++ ++ case NETDEV_DOWN: ++ AP6210_DEBUG("%s: [%s] Down IP: 0x%x\n", ++ __FUNCTION__, ifa->ifa_label, ifa->ifa_address); ++ dhd->pend_ipaddr = 0; ++#ifdef AOE_IP_ALIAS_SUPPORT ++ AP6210_DEBUG("%s:interface is down, AOE clr all for this if\n", ++ __FUNCTION__); ++ aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, FALSE, idx); ++#else ++ dhd_aoe_hostip_clr(&dhd->pub, idx); ++ dhd_aoe_arp_clr(&dhd->pub, idx); ++#endif /* AOE_IP_ALIAS_SUPPORT */ ++ break; ++ ++ default: ++ AP6210_DEBUG("%s: do noting for [%s] Event: %lu\n", ++ __func__, ifa->ifa_label, event); ++ break; ++ } ++ return NOTIFY_DONE; ++} ++#endif /* ARP_OFFLOAD_SUPPORT */ ++ ++int ++dhd_net_attach(dhd_pub_t *dhdp, int ifidx) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)dhdp->info; ++ struct net_device *net = NULL; ++ int err = 0; ++ uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33 }; ++ ++ AP6210_DEBUG("%s: ifidx %d\n", __FUNCTION__, ifidx); ++ ++ ASSERT(dhd && dhd->iflist[ifidx]); ++ ++ net = dhd->iflist[ifidx]->net; ++ ASSERT(net); ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) ++ ASSERT(!net->open); ++ net->get_stats = dhd_get_stats; ++ net->do_ioctl = dhd_ioctl_entry; ++ net->hard_start_xmit = dhd_start_xmit; ++ net->set_mac_address = dhd_set_mac_address; ++ net->set_multicast_list = dhd_set_multicast_list; ++ net->open = net->stop = NULL; ++#else ++ ASSERT(!net->netdev_ops); ++ net->netdev_ops = &dhd_ops_virt; ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */ ++ ++ /* Ok, link into the network layer... */ ++ if (ifidx == 0) { ++ /* ++ * device functions for the primary interface only ++ */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) ++ net->open = dhd_open; ++ net->stop = dhd_stop; ++#else ++ net->netdev_ops = &dhd_ops_pri; ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */ ++ if (!ETHER_ISNULLADDR(dhd->pub.mac.octet)) ++ memcpy(temp_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN); ++ } else { ++ /* ++ * We have to use the primary MAC for virtual interfaces ++ */ ++ memcpy(temp_addr, dhd->iflist[ifidx]->mac_addr, ETHER_ADDR_LEN); ++ /* ++ * Android sets the locally administered bit to indicate that this is a ++ * portable hotspot. This will not work in simultaneous AP/STA mode, ++ * nor with P2P. Need to set the Donlge's MAC address, and then use that. ++ */ ++ if (!memcmp(temp_addr, dhd->iflist[0]->mac_addr, ++ ETHER_ADDR_LEN)) { ++ AP6210_ERR("%s interface [%s]: set locally administered bit in MAC\n", ++ __func__, net->name); ++ temp_addr[0] |= 0x02; ++ } ++ } ++ ++ net->hard_header_len = ETH_HLEN + dhd->pub.hdrlen; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) ++ net->ethtool_ops = &dhd_ethtool_ops; ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ ++ ++#if defined(CONFIG_WIRELESS_EXT) ++#if WIRELESS_EXT < 19 ++ net->get_wireless_stats = dhd_get_wireless_stats; ++#endif /* WIRELESS_EXT < 19 */ ++#if WIRELESS_EXT > 12 ++ net->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def; ++#endif /* WIRELESS_EXT > 12 */ ++#endif /* defined(CONFIG_WIRELESS_EXT) */ ++ ++ dhd->pub.rxsz = DBUS_RX_BUFFER_SIZE_DHD(net); ++ ++ memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN); ++ ++ if ((err = register_netdev(net)) != 0) { ++ AP6210_ERR("couldn't register the net device, err %d\n", err); ++ goto fail; ++ } ++ AP6210_ERR("Broadcom Dongle Host Driver: register interface [%s] MAC: "MACDBG"\n", ++ net->name, ++ MAC2STRDBG(net->dev_addr)); ++ ++#if defined(SOFTAP) && defined(CONFIG_WIRELESS_EXT) && !defined(WL_CFG80211) ++ wl_iw_iscan_set_scan_broadcast_prep(net, 1); ++#endif ++ ++#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ if (ifidx == 0) { ++ dhd_registration_check = TRUE; ++ up(&dhd_registration_sem); ++ } ++#endif ++ return 0; ++ ++fail: ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) ++ net->open = NULL; ++#else ++ net->netdev_ops = NULL; ++#endif ++ return err; ++} ++ ++void ++dhd_bus_detach(dhd_pub_t *dhdp) ++{ ++ dhd_info_t *dhd; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (dhdp) { ++ dhd = (dhd_info_t *)dhdp->info; ++ if (dhd) { ++ ++ /* ++ * In case of Android cfg80211 driver, the bus is down in dhd_stop, ++ * calling stop again will cuase SD read/write errors. ++ */ ++ if (dhd->pub.busstate != DHD_BUS_DOWN) { ++ /* Stop the protocol module */ ++ dhd_prot_stop(&dhd->pub); ++ ++ /* Stop the bus module */ ++ dhd_bus_stop(dhd->pub.bus, TRUE); ++ } ++ ++#if defined(OOB_INTR_ONLY) ++ bcmsdh_unregister_oob_intr(); ++#endif ++ } ++ } ++} ++ ++ ++void dhd_detach(dhd_pub_t *dhdp) ++{ ++ dhd_info_t *dhd; ++ unsigned long flags; ++ int timer_valid = FALSE; ++ ++ if (!dhdp) ++ return; ++ ++ dhd = (dhd_info_t *)dhdp->info; ++ if (!dhd) ++ return; ++ ++ AP6210_DEBUG("%s: Enter state 0x%x\n", __FUNCTION__, dhd->dhd_state); ++#ifdef ARP_OFFLOAD_SUPPORT ++ unregister_inetaddr_notifier(&dhd_notifier); ++#endif /* ARP_OFFLOAD_SUPPORT */ ++#ifdef IPV6 ++ unregister_inet6addr_notifier(&dhd_notifier_ipv6); ++#endif ++ ++ dhd->pub.up = 0; ++ if (!(dhd->dhd_state & DHD_ATTACH_STATE_DONE)) { ++ /* Give sufficient time for threads to start running in case ++ * dhd_attach() has failed ++ */ ++ osl_delay(1000*100); ++ } ++ ++ if (dhd->dhd_state & DHD_ATTACH_STATE_PROT_ATTACH) { ++ dhd_bus_detach(dhdp); ++ ++ if (dhdp->prot) ++ dhd_prot_detach(dhdp); ++ } ++ ++#ifdef ARP_OFFLOAD_SUPPORT ++ unregister_inetaddr_notifier(&dhd_notifier); ++#endif /* ARP_OFFLOAD_SUPPORT */ ++ ++#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) ++ if (dhd->dhd_state & DHD_ATTACH_STATE_EARLYSUSPEND_DONE) { ++ if (dhd->early_suspend.suspend) ++ unregister_early_suspend(&dhd->early_suspend); ++ } ++#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ cancel_work_sync(&dhd->work_hang); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++ ++#if defined(CONFIG_WIRELESS_EXT) ++ if (dhd->dhd_state & DHD_ATTACH_STATE_WL_ATTACH) { ++ /* Detatch and unlink in the iw */ ++ wl_iw_detach(); ++ } ++#endif /* defined(CONFIG_WIRELESS_EXT) */ ++ ++ if (dhd->thr_sysioc_ctl.thr_pid >= 0) { ++ PROC_STOP(&dhd->thr_sysioc_ctl); ++ } ++ ++ /* delete all interfaces, start with virtual */ ++ if (dhd->dhd_state & DHD_ATTACH_STATE_ADD_IF) { ++ int i = 1; ++ dhd_if_t *ifp; ++ ++ /* Cleanup virtual interfaces */ ++ for (i = 1; i < DHD_MAX_IFS; i++) { ++ dhd_net_if_lock_local(dhd); ++ if (dhd->iflist[i]) { ++ dhd->iflist[i]->state = DHD_IF_DEL; ++ dhd->iflist[i]->idx = i; ++ dhd_op_if(dhd->iflist[i]); ++ } ++ ++ dhd_net_if_unlock_local(dhd); ++ } ++ /* delete primary interface 0 */ ++ ifp = dhd->iflist[0]; ++ ASSERT(ifp); ++ ASSERT(ifp->net); ++ if (ifp && ifp->net) { ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) ++ if (ifp->net->open) ++#else ++ if (ifp->net->netdev_ops == &dhd_ops_pri) ++#endif ++ { ++ unregister_netdev(ifp->net); ++ free_netdev(ifp->net); ++ ifp->net = NULL; ++ MFREE(dhd->pub.osh, ifp, sizeof(*ifp)); ++ dhd->iflist[0] = NULL; ++ } ++ } ++ } ++ ++ /* Clear the watchdog timer */ ++ flags = dhd_os_spin_lock(&dhd->pub); ++ timer_valid = dhd->wd_timer_valid; ++ dhd->wd_timer_valid = FALSE; ++ dhd_os_spin_unlock(&dhd->pub, flags); ++ if (timer_valid) ++ del_timer_sync(&dhd->timer); ++ ++ if (dhd->dhd_state & DHD_ATTACH_STATE_THREADS_CREATED) { ++#ifdef DHDTHREAD ++ if (dhd->thr_wdt_ctl.thr_pid >= 0) { ++ PROC_STOP(&dhd->thr_wdt_ctl); ++ } ++ ++ if (dhd->thr_dpc_ctl.thr_pid >= 0) { ++ PROC_STOP(&dhd->thr_dpc_ctl); ++ } ++ else ++#endif /* DHDTHREAD */ ++ tasklet_kill(&dhd->tasklet); ++ } ++ ++#ifdef WL_CFG80211 ++ if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { ++ wl_cfg80211_detach(NULL); ++ dhd_monitor_uninit(); ++ } ++#endif ++ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) ++ unregister_pm_notifier(&dhd_sleep_pm_notifier); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ ++ /* && defined(CONFIG_PM_SLEEP) */ ++ ++ if (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT) { ++#ifdef CONFIG_HAS_WAKELOCK ++ dhd->wakelock_counter = 0; ++ dhd->wakelock_wd_counter = 0; ++ dhd->wakelock_rx_timeout_enable = 0; ++ dhd->wakelock_ctrl_timeout_enable = 0; ++ if (dhd->wl_wifi) { ++ wake_lock_destroy(dhd->wl_wifi); ++ MFREE(dhd->pub.osh, dhd->wl_wifi, sizeof(struct wake_lock)); ++ dhd->wl_wifi = NULL; ++ } ++ if (dhd->wl_rxwake) { ++ wake_lock_destroy(dhd->wl_rxwake); ++ MFREE(dhd->pub.osh, dhd->wl_rxwake, sizeof(struct wake_lock)); ++ dhd->wl_rxwake = NULL; ++ } ++ if (dhd->wl_ctrlwake) { ++ wake_lock_destroy(dhd->wl_ctrlwake); ++ MFREE(dhd->pub.osh, dhd->wl_ctrlwake, sizeof(struct wake_lock)); ++ dhd->wl_ctrlwake = NULL; ++ } ++ if (dhd->wl_wdwake) { ++ wake_lock_destroy(dhd->wl_wdwake); ++ MFREE(dhd->pub.osh, dhd->wl_wdwake, sizeof(struct wake_lock)); ++ dhd->wl_wdwake = NULL; ++ } ++#endif /* CONFIG_HAS_WAKELOCK */ ++ } ++} ++ ++ ++void ++dhd_free(dhd_pub_t *dhdp) ++{ ++ dhd_info_t *dhd; ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (dhdp) { ++ int i; ++ for (i = 0; i < ARRAYSIZE(dhdp->reorder_bufs); i++) { ++ if (dhdp->reorder_bufs[i]) { ++ reorder_info_t *ptr; ++ uint32 buf_size = sizeof(struct reorder_info); ++ ++ ptr = dhdp->reorder_bufs[i]; ++ ++ buf_size += ((ptr->max_idx + 1) * sizeof(void*)); ++ AP6210_DEBUG("free flow id buf %d, maxidx is %d, buf_size %d\n", ++ i, ptr->max_idx, buf_size); ++ ++ MFREE(dhdp->osh, dhdp->reorder_bufs[i], buf_size); ++ dhdp->reorder_bufs[i] = NULL; ++ } ++ } ++ dhd = (dhd_info_t *)dhdp->info; ++ if (dhd) ++ MFREE(dhd->pub.osh, dhd, sizeof(*dhd)); ++ } ++} ++ ++static void __exit ++dhd_module_cleanup(void) ++{ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ dhd_bus_unregister(); ++ ++#if defined(CONFIG_WIFI_CONTROL_FUNC) ++ wl_android_wifictrl_func_del(); ++#endif /* CONFIG_WIFI_CONTROL_FUNC */ ++ wl_android_exit(); ++ ++ /* Call customer gpio to turn off power with WL_REG_ON signal */ ++ dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF); ++ ++ if (wl_host_wake > 0) ++ gpio_free(wl_host_wake); ++ wl_host_wake = -1; ++ ++ /*sw_rfkill_exit(); The comment must remove when we use the Bluetooth*/ ++ ap6210_gpio_wifi_exit(); ++} ++ ++ ++static int __init ++dhd_module_init(void) ++{ ++ int error = 0; ++ ++#if 1 && defined(BCMLXSDMMC) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ int retry = POWERUP_MAX_RETRY; ++ int chip_up = 0; ++#endif ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ AP6210_INFO("--->The Drive has been modified for BananaPro by LeMaker team<---\n"); ++ ++ ap6210_gpio_wifi_init(); ++ /*sw_rfkill_init(); The comment must remove when we use the Bluetooth*/ ++ ++ if (gpio_request(WL_HOST_WAKE_DEF_GPIO, "wl_host_wake")) { ++ AP6210_ERR("[%s] get wl_host_wake gpio failed\n", __FUNCTION__); ++ wl_host_wake = -1; ++ return -1; ++ } ++ wl_host_wake = WL_HOST_WAKE_DEF_GPIO; ++ gpio_direction_input(wl_host_wake); ++ wl_host_wake_irqno = gpio_to_irq(wl_host_wake); ++ AP6210_DEBUG("got gpio%d, mapped to irqno%d\n", wl_host_wake, wl_host_wake_irqno); ++ ++ wl_android_init(); ++ ++#if defined(DHDTHREAD) ++ /* Sanity check on the module parameters */ ++ do { ++ /* Both watchdog and DPC as tasklets are ok */ ++ if ((dhd_watchdog_prio < 0) && (dhd_dpc_prio < 0)) ++ break; ++ ++ /* If both watchdog and DPC are threads, TX must be deferred */ ++ if ((dhd_watchdog_prio >= 0) && (dhd_dpc_prio >= 0) && dhd_deferred_tx) ++ break; ++ ++ AP6210_ERR("Invalid module parameters.\n"); ++ return -EINVAL; ++ } while (0); ++#endif ++ ++#if 1 && defined(BCMLXSDMMC) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ do { ++ sema_init(&dhd_chipup_sem, 0); ++ dhd_bus_reg_sdio_notify(&dhd_chipup_sem); ++ dhd_customer_gpio_wlan_ctrl(WLAN_POWER_ON); ++#if defined(CONFIG_WIFI_CONTROL_FUNC) ++ if (wl_android_wifictrl_func_add() < 0) { ++ dhd_bus_unreg_sdio_notify(); ++ goto fail_1; ++ } ++#endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */ ++ if (down_timeout(&dhd_chipup_sem, ++ msecs_to_jiffies(POWERUP_WAIT_MS)) == 0) { ++ dhd_bus_unreg_sdio_notify(); ++ chip_up = 1; ++ break; ++ } ++ AP6210_ERR("failed to power up wifi chip, retry again (%d left) **\n\n", ++ retry+1); ++ dhd_bus_unreg_sdio_notify(); ++#if defined(CONFIG_WIFI_CONTROL_FUNC) ++ wl_android_wifictrl_func_del(); ++#endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */ ++ dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF); ++ } while (retry-- > 0); ++ ++ if (!chip_up) { ++ AP6210_ERR("failed to power up wifi chip, max retry reached, exits **\n\n"); ++ return -ENODEV; ++ } ++#else ++ dhd_customer_gpio_wlan_ctrl(WLAN_POWER_ON); ++#if defined(CONFIG_WIFI_CONTROL_FUNC) ++ if (wl_android_wifictrl_func_add() < 0) ++ goto fail_1; ++#endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */ ++ ++#endif ++ ++#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ sema_init(&dhd_registration_sem, 0); ++#endif ++ ++ ++ error = dhd_bus_register(); ++ ++ if (!error) ++ AP6210_DEBUG("%s\n", dhd_version); ++ else { ++ AP6210_ERR("%s: sdio_register_driver failed\n", __FUNCTION__); ++ goto fail_1; ++ } ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ /* ++ * Wait till MMC sdio_register_driver callback called and made driver attach. ++ * It's needed to make sync up exit from dhd insmod and ++ * Kernel MMC sdio device callback registration ++ */ ++ if ((down_timeout(&dhd_registration_sem, ++ msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT)) != 0) || ++ (dhd_registration_check != TRUE)) { ++ error = -ENODEV; ++ AP6210_ERR("%s: sdio_register_driver timeout or error \n", __FUNCTION__); ++ goto fail_2; ++ } ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++#if defined(WL_CFG80211) ++ wl_android_post_init(); ++#endif /* defined(WL_CFG80211) */ ++ ++ return error; ++ ++#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++fail_2: ++ dhd_bus_unregister(); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++ ++fail_1: ++ ++#if defined(CONFIG_WIFI_CONTROL_FUNC) ++ wl_android_wifictrl_func_del(); ++#endif ++ ++ /* Call customer gpio to turn off power with WL_REG_ON signal */ ++ dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF); ++ ++ return error; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++late_initcall(dhd_module_init); ++#else ++module_init(dhd_module_init); ++#endif ++ ++module_exit(dhd_module_cleanup); ++ ++/* ++ * OS specific functions required to implement DHD driver in OS independent way ++ */ ++int ++dhd_os_proto_block(dhd_pub_t *pub) ++{ ++ dhd_info_t * dhd = (dhd_info_t *)(pub->info); ++ ++ if (dhd) { ++ down(&dhd->proto_sem); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int ++dhd_os_proto_unblock(dhd_pub_t *pub) ++{ ++ dhd_info_t * dhd = (dhd_info_t *)(pub->info); ++ ++ if (dhd) { ++ up(&dhd->proto_sem); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++unsigned int ++dhd_os_get_ioctl_resp_timeout(void) ++{ ++ return ((unsigned int)dhd_ioctl_timeout_msec); ++} ++ ++void ++dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec) ++{ ++ dhd_ioctl_timeout_msec = (int)timeout_msec; ++} ++ ++int ++dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool *pending) ++{ ++ dhd_info_t * dhd = (dhd_info_t *)(pub->info); ++ int timeout; ++ ++ /* Convert timeout in millsecond to jiffies */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ timeout = msecs_to_jiffies(dhd_ioctl_timeout_msec); ++#else ++ timeout = dhd_ioctl_timeout_msec * HZ / 1000; ++#endif ++ ++ timeout = wait_event_timeout(dhd->ioctl_resp_wait, (*condition), timeout); ++ return timeout; ++} ++ ++int ++dhd_os_ioctl_resp_wake(dhd_pub_t *pub) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)(pub->info); ++ ++ if (waitqueue_active(&dhd->ioctl_resp_wait)) { ++ wake_up(&dhd->ioctl_resp_wait); ++ } ++ ++ return 0; ++} ++ ++void ++dhd_os_wd_timer(void *bus, uint wdtick) ++{ ++ dhd_pub_t *pub = bus; ++ dhd_info_t *dhd = (dhd_info_t *)pub->info; ++ unsigned long flags; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (!dhd) ++ return; ++ if (wdtick) ++ DHD_OS_WD_WAKE_LOCK(pub); ++ ++ flags = dhd_os_spin_lock(pub); ++ ++ /* don't start the wd until fw is loaded */ ++ if (pub->busstate == DHD_BUS_DOWN) { ++ dhd_os_spin_unlock(pub, flags); ++ DHD_OS_WD_WAKE_UNLOCK(pub); ++ return; ++ } ++ ++ /* totally stop the timer */ ++ if (!wdtick && dhd->wd_timer_valid == TRUE) { ++ dhd->wd_timer_valid = FALSE; ++ dhd_os_spin_unlock(pub, flags); ++#ifdef DHDTHREAD ++ del_timer_sync(&dhd->timer); ++#else ++ del_timer(&dhd->timer); ++#endif /* DHDTHREAD */ ++ /* Unlock when timer deleted */ ++ DHD_OS_WD_WAKE_UNLOCK(pub); ++ return; ++ } ++ ++ if (wdtick) { ++ dhd_watchdog_ms = (uint)wdtick; ++ /* Re arm the timer, at last watchdog period */ ++ mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms)); ++ dhd->wd_timer_valid = TRUE; ++ } ++ dhd_os_spin_unlock(pub, flags); ++} ++ ++void * ++dhd_os_open_image(char *filename) ++{ ++ struct file *fp; ++ ++ fp = filp_open(filename, O_RDONLY, 0); ++ /* ++ * 2.6.11 (FC4) supports filp_open() but later revs don't? ++ * Alternative: ++ * fp = open_namei(AT_FDCWD, filename, O_RD, 0); ++ * ??? ++ */ ++ if (IS_ERR(fp)) ++ fp = NULL; ++ ++ return fp; ++} ++ ++int ++dhd_os_get_image_block(char *buf, int len, void *image) ++{ ++ struct file *fp = (struct file *)image; ++ int rdlen; ++ ++ if (!image) ++ return 0; ++ ++ rdlen = kernel_read(fp, fp->f_pos, buf, len); ++ if (rdlen > 0) ++ fp->f_pos += rdlen; ++ ++ return rdlen; ++} ++ ++void ++dhd_os_close_image(void *image) ++{ ++ if (image) ++ filp_close((struct file *)image, NULL); ++} ++ ++ ++void ++dhd_os_sdlock(dhd_pub_t *pub) ++{ ++ dhd_info_t *dhd; ++ ++ dhd = (dhd_info_t *)(pub->info); ++ ++#ifdef DHDTHREAD ++ if (dhd->threads_only) ++ down(&dhd->sdsem); ++ else ++#endif /* DHDTHREAD */ ++ spin_lock_bh(&dhd->sdlock); ++} ++ ++void ++dhd_os_sdunlock(dhd_pub_t *pub) ++{ ++ dhd_info_t *dhd; ++ ++ dhd = (dhd_info_t *)(pub->info); ++ ++#ifdef DHDTHREAD ++ if (dhd->threads_only) ++ up(&dhd->sdsem); ++ else ++#endif /* DHDTHREAD */ ++ spin_unlock_bh(&dhd->sdlock); ++} ++ ++void ++dhd_os_sdlock_txq(dhd_pub_t *pub) ++{ ++ dhd_info_t *dhd; ++ ++ dhd = (dhd_info_t *)(pub->info); ++ spin_lock_bh(&dhd->txqlock); ++} ++ ++void ++dhd_os_sdunlock_txq(dhd_pub_t *pub) ++{ ++ dhd_info_t *dhd; ++ ++ dhd = (dhd_info_t *)(pub->info); ++ spin_unlock_bh(&dhd->txqlock); ++} ++ ++void ++dhd_os_sdlock_rxq(dhd_pub_t *pub) ++{ ++} ++ ++void ++dhd_os_sdunlock_rxq(dhd_pub_t *pub) ++{ ++} ++ ++void ++dhd_os_sdtxlock(dhd_pub_t *pub) ++{ ++ dhd_os_sdlock(pub); ++} ++ ++void ++dhd_os_sdtxunlock(dhd_pub_t *pub) ++{ ++ dhd_os_sdunlock(pub); ++} ++ ++#if defined(CONFIG_DHD_USE_STATIC_BUF) ++uint8* dhd_os_prealloc(void *osh, int section, uint size) ++{ ++ return (uint8*)wl_android_prealloc(section, size); ++} ++ ++void dhd_os_prefree(void *osh, void *addr, uint size) ++{ ++} ++#endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */ ++ ++#if defined(CONFIG_WIRELESS_EXT) ++struct iw_statistics * ++dhd_get_wireless_stats(struct net_device *dev) ++{ ++ int res = 0; ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ ++ if (!dhd->pub.up) { ++ return NULL; ++ } ++ ++ res = wl_iw_get_wireless_stats(dev, &dhd->iw.wstats); ++ ++ if (res == 0) ++ return &dhd->iw.wstats; ++ else ++ return NULL; ++} ++#endif /* defined(CONFIG_WIRELESS_EXT) */ ++ ++static int ++dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, ++ wl_event_msg_t *event, void **data) ++{ ++ int bcmerror = 0; ++ ASSERT(dhd != NULL); ++ ++ bcmerror = wl_host_event(&dhd->pub, ifidx, pktdata, event, data); ++ if (bcmerror != BCME_OK) ++ return (bcmerror); ++ ++#if defined(CONFIG_WIRELESS_EXT) ++ if (event->bsscfgidx == 0) { ++ /* ++ * Wireless ext is on primary interface only ++ */ ++ ++ ASSERT(dhd->iflist[*ifidx] != NULL); ++ ASSERT(dhd->iflist[*ifidx]->net != NULL); ++ ++ if (dhd->iflist[*ifidx]->net) { ++ wl_iw_event(dhd->iflist[*ifidx]->net, event, *data); ++ } ++ } ++#endif /* defined(CONFIG_WIRELESS_EXT) */ ++ ++#ifdef WL_CFG80211 ++ if ((ntoh32(event->event_type) == WLC_E_IF) && ++ (((dhd_if_event_t *)*data)->action == WLC_E_IF_ADD)) ++ /* If ADD_IF has been called directly by wl utility then we ++ * should not report this. In case if ADD_IF was called from ++ * CFG stack, then too this event need not be reported back ++ */ ++ return (BCME_OK); ++ if ((wl_cfg80211_is_progress_ifchange() || ++ wl_cfg80211_is_progress_ifadd()) && (*ifidx != 0)) { ++ /* ++ * If IF_ADD/CHANGE operation is going on, ++ * discard any event received on the virtual I/F ++ */ ++ return (BCME_OK); ++ } ++ ++ ASSERT(dhd->iflist[*ifidx] != NULL); ++ ASSERT(dhd->iflist[*ifidx]->net != NULL); ++ if (dhd->iflist[*ifidx]->event2cfg80211 && dhd->iflist[*ifidx]->net) { ++ wl_cfg80211_event(dhd->iflist[*ifidx]->net, event, *data); ++ } ++#endif /* defined(WL_CFG80211) */ ++ ++ return (bcmerror); ++} ++ ++/* send up locally generated event */ ++void ++dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data) ++{ ++ switch (ntoh32(event->event_type)) { ++#ifdef WLBTAMP ++ /* Send up locally generated AMP HCI Events */ ++ case WLC_E_BTA_HCI_EVENT: { ++ struct sk_buff *p, *skb; ++ bcm_event_t *msg; ++ wl_event_msg_t *p_bcm_event; ++ char *ptr; ++ uint32 len; ++ uint32 pktlen; ++ dhd_if_t *ifp; ++ dhd_info_t *dhd; ++ uchar *eth; ++ int ifidx; ++ ++ len = ntoh32(event->datalen); ++ pktlen = sizeof(bcm_event_t) + len + 2; ++ dhd = dhdp->info; ++ ifidx = dhd_ifname2idx(dhd, event->ifname); ++ ++ if ((p = PKTGET(dhdp->osh, pktlen, FALSE))) { ++ ASSERT(ISALIGNED((uintptr)PKTDATA(dhdp->osh, p), sizeof(uint32))); ++ ++ msg = (bcm_event_t *) PKTDATA(dhdp->osh, p); ++ ++ bcopy(&dhdp->mac, &msg->eth.ether_dhost, ETHER_ADDR_LEN); ++ bcopy(&dhdp->mac, &msg->eth.ether_shost, ETHER_ADDR_LEN); ++ ETHER_TOGGLE_LOCALADDR(&msg->eth.ether_shost); ++ ++ msg->eth.ether_type = hton16(ETHER_TYPE_BRCM); ++ ++ /* BCM Vendor specific header... */ ++ msg->bcm_hdr.subtype = hton16(BCMILCP_SUBTYPE_VENDOR_LONG); ++ msg->bcm_hdr.version = BCMILCP_BCM_SUBTYPEHDR_VERSION; ++ bcopy(BRCM_OUI, &msg->bcm_hdr.oui[0], DOT11_OUI_LEN); ++ ++ /* vendor spec header length + pvt data length (private indication ++ * hdr + actual message itself) ++ */ ++ msg->bcm_hdr.length = hton16(BCMILCP_BCM_SUBTYPEHDR_MINLENGTH + ++ BCM_MSG_LEN + sizeof(wl_event_msg_t) + (uint16)len); ++ msg->bcm_hdr.usr_subtype = hton16(BCMILCP_BCM_SUBTYPE_EVENT); ++ ++ PKTSETLEN(dhdp->osh, p, (sizeof(bcm_event_t) + len + 2)); ++ ++ /* copy wl_event_msg_t into sk_buf */ ++ ++ /* pointer to wl_event_msg_t in sk_buf */ ++ p_bcm_event = &msg->event; ++ bcopy(event, p_bcm_event, sizeof(wl_event_msg_t)); ++ ++ /* copy hci event into sk_buf */ ++ bcopy(data, (p_bcm_event + 1), len); ++ ++ msg->bcm_hdr.length = hton16(sizeof(wl_event_msg_t) + ++ ntoh16(msg->bcm_hdr.length)); ++ PKTSETLEN(dhdp->osh, p, (sizeof(bcm_event_t) + len + 2)); ++ ++ ptr = (char *)(msg + 1); ++ /* Last 2 bytes of the message are 0x00 0x00 to signal that there ++ * are no ethertypes which are following this ++ */ ++ ptr[len+0] = 0x00; ++ ptr[len+1] = 0x00; ++ ++ skb = PKTTONATIVE(dhdp->osh, p); ++ eth = skb->data; ++ len = skb->len; ++ ++ ifp = dhd->iflist[ifidx]; ++ if (ifp == NULL) ++ ifp = dhd->iflist[0]; ++ ++ ASSERT(ifp); ++ skb->dev = ifp->net; ++ skb->protocol = eth_type_trans(skb, skb->dev); ++ ++ skb->data = eth; ++ skb->len = len; ++ ++ /* Strip header, count, deliver upward */ ++ skb_pull(skb, ETH_HLEN); ++ ++ /* Send the packet */ ++ if (in_interrupt()) { ++ netif_rx(skb); ++ } else { ++ netif_rx_ni(skb); ++ } ++ } ++ else { ++ /* Could not allocate a sk_buf */ ++ AP6210_ERR("%s: unable to alloc sk_buf", __FUNCTION__); ++ } ++ break; ++ } /* case WLC_E_BTA_HCI_EVENT */ ++#endif /* WLBTAMP */ ++ ++ default: ++ break; ++ } ++} ++ ++void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar) ++{ ++#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++ struct dhd_info *dhdinfo = dhd->info; ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ int timeout = msecs_to_jiffies(IOCTL_RESP_TIMEOUT); ++#else ++ int timeout = (IOCTL_RESP_TIMEOUT / 1000) * HZ; ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++ ++ dhd_os_sdunlock(dhd); ++ wait_event_timeout(dhdinfo->ctrl_wait, (*lockvar == FALSE), timeout); ++ dhd_os_sdlock(dhd); ++#endif ++ return; ++} ++ ++void dhd_wait_event_wakeup(dhd_pub_t *dhd) ++{ ++#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++ struct dhd_info *dhdinfo = dhd->info; ++ if (waitqueue_active(&dhdinfo->ctrl_wait)) ++ wake_up(&dhdinfo->ctrl_wait); ++#endif ++ return; ++} ++ ++int ++dhd_dev_reset(struct net_device *dev, uint8 flag) ++{ ++ int ret; ++ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ ++ if (flag == TRUE) { ++ /* Issue wl down command before resetting the chip */ ++ if (dhd_wl_ioctl_cmd(&dhd->pub, WLC_DOWN, NULL, 0, TRUE, 0) < 0) { ++ AP6210_DEBUG("%s: wl down failed\n", __FUNCTION__); ++ } ++ } ++ ++ ret = dhd_bus_devreset(&dhd->pub, flag); ++ if (ret) { ++ AP6210_ERR("%s: dhd_bus_devreset: %d\n", __FUNCTION__, ret); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++int net_os_set_suspend_disable(struct net_device *dev, int val) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ int ret = 0; ++ ++ if (dhd) { ++ ret = dhd->pub.suspend_disable_flag; ++ dhd->pub.suspend_disable_flag = val; ++ } ++ return ret; ++} ++ ++int net_os_set_suspend(struct net_device *dev, int val, int force) ++{ ++ int ret = 0; ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ ++ if (dhd) { ++#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) ++ ret = dhd_set_suspend(val, &dhd->pub); ++#else ++ ret = dhd_suspend_resume_helper(dhd, val, force); ++#endif ++#ifdef WL_CFG80211 ++ wl_cfg80211_update_power_mode(dev); ++#endif ++ } ++ return ret; ++} ++ ++int net_os_set_suspend_bcn_li_dtim(struct net_device *dev, int val) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ ++ if (dhd) ++ dhd->pub.suspend_bcn_li_dtim = val; ++ ++ return 0; ++} ++ ++#ifdef PKT_FILTER_SUPPORT ++int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num) ++{ ++#ifndef GAN_LITE_NAT_KEEPALIVE_FILTER ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ char *filterp = NULL; ++ int ret = 0; ++ ++ if (!dhd || (num == DHD_UNICAST_FILTER_NUM) || ++ (num == DHD_MDNS_FILTER_NUM)) ++ return ret; ++ if (num >= dhd->pub.pktfilter_count) ++ return -EINVAL; ++ if (add_remove) { ++ switch (num) { ++ case DHD_BROADCAST_FILTER_NUM: ++ filterp = "101 0 0 0 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF"; ++ break; ++ case DHD_MULTICAST4_FILTER_NUM: ++ filterp = "102 0 0 0 0xFFFFFF 0x01005E"; ++ break; ++ case DHD_MULTICAST6_FILTER_NUM: ++ filterp = "103 0 0 0 0xFFFF 0x3333"; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ dhd->pub.pktfilter[num] = filterp; ++ dhd_pktfilter_offload_set(&dhd->pub, dhd->pub.pktfilter[num]); ++ return ret; ++#else ++ return 0; ++#endif /* GAN_LITE_NAT_KEEPALIVE_FILTER */ ++} ++ ++int dhd_os_enable_packet_filter(dhd_pub_t *dhdp, int val) ++{ ++ int ret = 0; ++ ++ /* Packet filtering is set only if we still in early-suspend and ++ * we need either to turn it ON or turn it OFF ++ * We can always turn it OFF in case of early-suspend, but we turn it ++ * back ON only if suspend_disable_flag was not set ++ */ ++ if (dhdp && dhdp->up) { ++ if (dhdp->in_suspend) { ++ if (!val || (val && !dhdp->suspend_disable_flag)) ++ dhd_enable_packet_filter(val, dhdp); ++ } ++ } ++ return ret; ++} ++ ++/* function to enable/disable packet for Network device */ ++int net_os_enable_packet_filter(struct net_device *dev, int val) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ ++ return dhd_os_enable_packet_filter(&dhd->pub, val); ++} ++#endif /* PKT_FILTER_SUPPORT */ ++ ++int ++dhd_dev_init_ioctl(struct net_device *dev) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ return dhd_preinit_ioctls(&dhd->pub); ++} ++ ++#ifdef PNO_SUPPORT ++/* Linux wrapper to call common dhd_pno_clean */ ++int ++dhd_dev_pno_reset(struct net_device *dev) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ ++ return (dhd_pno_clean(&dhd->pub)); ++} ++ ++ ++/* Linux wrapper to call common dhd_pno_enable */ ++int ++dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ ++ return (dhd_pno_enable(&dhd->pub, pfn_enabled)); ++} ++ ++ ++/* Linux wrapper to call common dhd_pno_set */ ++int ++dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, ++ ushort scan_fr, int pno_repeat, int pno_freq_expo_max) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ ++ return (dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr, pno_repeat, pno_freq_expo_max)); ++} ++ ++/* Linux wrapper to get pno status */ ++int ++dhd_dev_get_pno_status(struct net_device *dev) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ ++ return (dhd_pno_get_status(&dhd->pub)); ++} ++ ++#endif /* PNO_SUPPORT */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (1) ++static void dhd_hang_process(struct work_struct *work) ++{ ++ dhd_info_t *dhd; ++ struct net_device *dev; ++ ++ dhd = (dhd_info_t *)container_of(work, dhd_info_t, work_hang); ++ dev = dhd->iflist[0]->net; ++ ++ if (dev) { ++ rtnl_lock(); ++ dev_close(dev); ++ rtnl_unlock(); ++#if defined(WL_WIRELESS_EXT) ++ wl_iw_send_priv_event(dev, "HANG"); ++#endif ++#if defined(WL_CFG80211) ++ wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); ++#endif ++ } ++} ++ ++int dhd_os_send_hang_message(dhd_pub_t *dhdp) ++{ ++ int ret = 0; ++ if (dhdp) { ++ if (!dhdp->hang_was_sent) { ++ dhdp->hang_was_sent = 1; ++ schedule_work(&dhdp->info->work_hang); ++ } ++ } ++ return ret; ++} ++ ++int net_os_send_hang_message(struct net_device *dev) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ int ret = 0; ++ ++ if (dhd) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ ret = dhd_os_send_hang_message(&dhd->pub); ++#else ++ ret = wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); ++#endif ++ return ret; ++} ++#endif /* (OEM_ANDROID) */ ++ ++void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ ++ if (dhd && dhd->pub.up) { ++ memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t)); ++#ifdef WL_CFG80211 ++ wl_update_wiphybands(NULL, true); ++#endif ++ } ++} ++ ++void dhd_bus_band_set(struct net_device *dev, uint band) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ if (dhd && dhd->pub.up) { ++#ifdef WL_CFG80211 ++ wl_update_wiphybands(NULL, true); ++#endif ++ } ++} ++ ++void dhd_net_if_lock(struct net_device *dev) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ dhd_net_if_lock_local(dhd); ++} ++ ++void dhd_net_if_unlock(struct net_device *dev) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ dhd_net_if_unlock_local(dhd); ++} ++ ++static void dhd_net_if_lock_local(dhd_info_t *dhd) ++{ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ if (dhd) ++ mutex_lock(&dhd->dhd_net_if_mutex); ++#endif ++} ++ ++static void dhd_net_if_unlock_local(dhd_info_t *dhd) ++{ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ if (dhd) ++ mutex_unlock(&dhd->dhd_net_if_mutex); ++#endif ++} ++ ++static void dhd_suspend_lock(dhd_pub_t *pub) ++{ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ dhd_info_t *dhd = (dhd_info_t *)(pub->info); ++ if (dhd) ++ mutex_lock(&dhd->dhd_suspend_mutex); ++#endif ++} ++ ++static void dhd_suspend_unlock(dhd_pub_t *pub) ++{ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ dhd_info_t *dhd = (dhd_info_t *)(pub->info); ++ if (dhd) ++ mutex_unlock(&dhd->dhd_suspend_mutex); ++#endif ++} ++ ++unsigned long dhd_os_spin_lock(dhd_pub_t *pub) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)(pub->info); ++ unsigned long flags = 0; ++ ++ if (dhd) ++ spin_lock_irqsave(&dhd->dhd_lock, flags); ++ ++ return flags; ++} ++ ++void dhd_os_spin_unlock(dhd_pub_t *pub, unsigned long flags) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)(pub->info); ++ ++ if (dhd) ++ spin_unlock_irqrestore(&dhd->dhd_lock, flags); ++} ++ ++static int ++dhd_get_pend_8021x_cnt(dhd_info_t *dhd) ++{ ++ return (atomic_read(&dhd->pend_8021x_cnt)); ++} ++ ++#define MAX_WAIT_FOR_8021X_TX 25 ++ ++int ++dhd_wait_pend8021x(struct net_device *dev) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ int timeout = msecs_to_jiffies(10); ++ int ntimes = MAX_WAIT_FOR_8021X_TX; ++ int pend = dhd_get_pend_8021x_cnt(dhd); ++ ++ while (ntimes && pend) { ++ if (pend) { ++ set_current_state(TASK_INTERRUPTIBLE); ++ schedule_timeout(timeout); ++ set_current_state(TASK_RUNNING); ++ ntimes--; ++ } ++ pend = dhd_get_pend_8021x_cnt(dhd); ++ } ++ if (ntimes == 0) ++ AP6210_ERR("%s: TIMEOUT\n", __FUNCTION__); ++ return pend; ++} ++ ++#ifdef DHD_DEBUG ++int ++write_to_file(dhd_pub_t *dhd, uint8 *buf, int size) ++{ ++ int ret = 0; ++ struct file *fp; ++ mm_segment_t old_fs; ++ loff_t pos = 0; ++ ++ /* change to KERNEL_DS address limit */ ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ ++ /* open file to write */ ++ fp = filp_open("/tmp/mem_dump", O_WRONLY|O_CREAT, 0640); ++ if (!fp) { ++ AP6210_ERR("%s: open file error\n", __FUNCTION__); ++ ret = -1; ++ goto exit; ++ } ++ ++ /* Write buf to file */ ++ fp->f_op->write(fp, buf, size, &pos); ++ ++exit: ++ /* free buf before return */ ++ MFREE(dhd->osh, buf, size); ++ /* close file before return */ ++ if (fp) ++ filp_close(fp, current->files); ++ /* restore previous address limit */ ++ set_fs(old_fs); ++ ++ return ret; ++} ++#endif /* DHD_DEBUG */ ++ ++int dhd_os_wake_lock_timeout(dhd_pub_t *pub) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)(pub->info); ++ unsigned long flags; ++ int ret = 0; ++ ++ if (dhd) { ++ spin_lock_irqsave(&dhd->wakelock_spinlock, flags); ++ ret = dhd->wakelock_rx_timeout_enable > dhd->wakelock_ctrl_timeout_enable ? ++ dhd->wakelock_rx_timeout_enable : dhd->wakelock_ctrl_timeout_enable; ++#ifdef CONFIG_HAS_WAKELOCK ++ if (dhd->wakelock_rx_timeout_enable) ++ wake_lock_timeout(dhd->wl_rxwake, ++ msecs_to_jiffies(dhd->wakelock_rx_timeout_enable)); ++ if (dhd->wakelock_ctrl_timeout_enable) ++ wake_lock_timeout(dhd->wl_ctrlwake, ++ msecs_to_jiffies(dhd->wakelock_ctrl_timeout_enable)); ++#endif ++ dhd->wakelock_rx_timeout_enable = 0; ++ dhd->wakelock_ctrl_timeout_enable = 0; ++ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); ++ } ++ return ret; ++} ++ ++int net_os_wake_lock_timeout(struct net_device *dev) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ int ret = 0; ++ ++ if (dhd) ++ ret = dhd_os_wake_lock_timeout(&dhd->pub); ++ return ret; ++} ++ ++int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)(pub->info); ++ unsigned long flags; ++ ++ if (dhd) { ++ spin_lock_irqsave(&dhd->wakelock_spinlock, flags); ++ if (val > dhd->wakelock_rx_timeout_enable) ++ dhd->wakelock_rx_timeout_enable = val; ++ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); ++ } ++ return 0; ++} ++ ++int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)(pub->info); ++ unsigned long flags; ++ ++ if (dhd) { ++ spin_lock_irqsave(&dhd->wakelock_spinlock, flags); ++ if (val > dhd->wakelock_ctrl_timeout_enable) ++ dhd->wakelock_ctrl_timeout_enable = val; ++ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); ++ } ++ return 0; ++} ++ ++int net_os_wake_lock_rx_timeout_enable(struct net_device *dev, int val) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ int ret = 0; ++ ++ if (dhd) ++ ret = dhd_os_wake_lock_rx_timeout_enable(&dhd->pub, val); ++ return ret; ++} ++ ++int net_os_wake_lock_ctrl_timeout_enable(struct net_device *dev, int val) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ int ret = 0; ++ ++ if (dhd) ++ ret = dhd_os_wake_lock_ctrl_timeout_enable(&dhd->pub, val); ++ return ret; ++} ++ ++int dhd_os_wake_lock(dhd_pub_t *pub) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)(pub->info); ++ unsigned long flags; ++ int ret = 0; ++ ++ if (dhd) { ++ spin_lock_irqsave(&dhd->wakelock_spinlock, flags); ++#ifdef CONFIG_HAS_WAKELOCK ++ if (!dhd->wakelock_counter) ++ wake_lock(dhd->wl_wifi); ++#endif ++ dhd->wakelock_counter++; ++ ret = dhd->wakelock_counter; ++ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); ++ } ++ return ret; ++} ++ ++int net_os_wake_lock(struct net_device *dev) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ int ret = 0; ++ ++ if (dhd) ++ ret = dhd_os_wake_lock(&dhd->pub); ++ return ret; ++} ++ ++int dhd_os_wake_unlock(dhd_pub_t *pub) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)(pub->info); ++ unsigned long flags; ++ int ret = 0; ++ ++ dhd_os_wake_lock_timeout(pub); ++ if (dhd) { ++ spin_lock_irqsave(&dhd->wakelock_spinlock, flags); ++ if (dhd->wakelock_counter) { ++ dhd->wakelock_counter--; ++#ifdef CONFIG_HAS_WAKELOCK ++ if (!dhd->wakelock_counter) ++ wake_unlock(dhd->wl_wifi); ++#endif ++ ret = dhd->wakelock_counter; ++ } ++ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); ++ } ++ return ret; ++} ++ ++int dhd_os_check_wakelock(void *dhdp) ++{ ++#ifdef CONFIG_HAS_WAKELOCK ++ dhd_pub_t *pub = (dhd_pub_t *)dhdp; ++ dhd_info_t *dhd; ++ ++ if (!pub) ++ return 0; ++ dhd = (dhd_info_t *)(pub->info); ++ ++ /* Indicate to the SD Host to avoid going to suspend if internal locks are up */ ++ if (dhd && (wake_lock_active(dhd->wl_wifi) || ++ (wake_lock_active(dhd->wl_wdwake)))) ++ return 1; ++#endif ++ return 0; ++} ++ ++int net_os_wake_unlock(struct net_device *dev) ++{ ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ int ret = 0; ++ ++ if (dhd) ++ ret = dhd_os_wake_unlock(&dhd->pub); ++ return ret; ++} ++ ++int dhd_os_wd_wake_lock(dhd_pub_t *pub) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)(pub->info); ++ unsigned long flags; ++ int ret = 0; ++ ++ if (dhd) { ++ spin_lock_irqsave(&dhd->wakelock_spinlock, flags); ++#ifdef CONFIG_HAS_WAKELOCK ++ /* if wakelock_wd_counter was never used : lock it at once */ ++ if (!dhd->wakelock_wd_counter) { ++ if (dhd->wl_wdwake) ++ wake_lock(dhd->wl_wdwake); ++ else { ++ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); ++ return 0; ++ } ++ } ++#endif ++ dhd->wakelock_wd_counter++; ++ ret = dhd->wakelock_wd_counter; ++ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); ++ } ++ return ret; ++} ++ ++int dhd_os_wd_wake_unlock(dhd_pub_t *pub) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)(pub->info); ++ unsigned long flags; ++ int ret = 0; ++ ++ if (dhd) { ++ spin_lock_irqsave(&dhd->wakelock_spinlock, flags); ++ if (dhd->wakelock_wd_counter) { ++ dhd->wakelock_wd_counter = 0; ++#ifdef CONFIG_HAS_WAKELOCK ++ wake_unlock(dhd->wl_wdwake); ++#endif ++ } ++ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); ++ } ++ return ret; ++} ++ ++int dhd_os_check_if_up(void *dhdp) ++{ ++ dhd_pub_t *pub = (dhd_pub_t *)dhdp; ++ ++ if (!pub) ++ return 0; ++ return pub->up; ++} ++ ++/* function to collect firmware, chip id and chip version info */ ++void dhd_set_version_info(dhd_pub_t *dhdp, char *fw) ++{ ++ int i; ++ ++ i = snprintf(info_string, sizeof(info_string), "Driver: %s\n Firmware: %s ", EPI_VERSION_STR, fw); ++ ++ if (!dhdp) ++ return; ++ ++ i = snprintf(&info_string[i], sizeof(info_string) - i, ++ "\n Chip: %x Rev %x Pkg %x", dhd_bus_chip_id(dhdp), ++ dhd_bus_chiprev_id(dhdp), dhd_bus_chippkg_id(dhdp)); ++ AP6210_ERR("Chip: %x Rev %x Pkg %x", dhd_bus_chip_id(dhdp), dhd_bus_chiprev_id(dhdp), dhd_bus_chippkg_id(dhdp)); ++} ++ ++int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd) ++{ ++ int ifidx; ++ int ret = 0; ++ dhd_info_t *dhd = NULL; ++ ++ if (!net || !netdev_priv(net)) { ++ AP6210_ERR("%s invalid parameter\n", __FUNCTION__); ++ return -EINVAL; ++ } ++ ++ dhd = *(dhd_info_t **)netdev_priv(net); ++ ifidx = dhd_net2idx(dhd, net); ++ if (ifidx == DHD_BAD_IF) { ++ AP6210_ERR("%s bad ifidx\n", __FUNCTION__); ++ return -ENODEV; ++ } ++ ++ DHD_OS_WAKE_LOCK(&dhd->pub); ++ ret = dhd_wl_ioctl(&dhd->pub, ifidx, ioc, ioc->buf, ioc->len); ++ dhd_check_hang(net, &dhd->pub, ret); ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ ++ return ret; ++} ++ ++bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret) ++{ ++ struct net_device *net; ++ ++ net = dhd_idx2net(dhdp, ifidx); ++ return dhd_check_hang(net, dhdp, ret); ++} ++ ++ ++#ifdef PROP_TXSTATUS ++extern int dhd_wlfc_interface_entry_update(void* state, ewlfc_mac_entry_action_t action, uint8 ifid, ++ uint8 iftype, uint8* ea); ++extern int dhd_wlfc_FIFOcreditmap_update(void* state, uint8* credits); ++ ++int dhd_wlfc_interface_event(struct dhd_info *dhd, ++ ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea) ++{ ++ int status; ++ ++ dhd_os_wlfc_block(&dhd->pub); ++ if (dhd->pub.wlfc_state == NULL) { ++ dhd_os_wlfc_unblock(&dhd->pub); ++ return BCME_OK; ++ } ++ ++ status = dhd_wlfc_interface_entry_update(dhd->pub.wlfc_state, action, ifid, iftype, ea); ++ dhd_os_wlfc_unblock(&dhd->pub); ++ return status; ++} ++ ++int dhd_wlfc_FIFOcreditmap_event(struct dhd_info *dhd, uint8* event_data) ++{ ++ int status; ++ ++ dhd_os_wlfc_block(&dhd->pub); ++ if (dhd->pub.wlfc_state == NULL) { ++ dhd_os_wlfc_unblock(&dhd->pub); ++ return BCME_OK; ++ } ++ ++ status = dhd_wlfc_FIFOcreditmap_update(dhd->pub.wlfc_state, event_data); ++ dhd_os_wlfc_unblock(&dhd->pub); ++ return status; ++} ++ ++int dhd_wlfc_event(struct dhd_info *dhd) ++{ ++ int status; ++ ++ dhd_os_wlfc_block(&dhd->pub); ++ status = dhd_wlfc_enable(&dhd->pub); ++ dhd_os_wlfc_unblock(&dhd->pub); ++ return status; ++} ++#endif /* PROP_TXSTATUS */ ++ ++#ifdef BCMDBGFS ++ ++#include ++ ++extern uint32 dhd_readregl(void *bp, uint32 addr); ++extern uint32 dhd_writeregl(void *bp, uint32 addr, uint32 data); ++ ++typedef struct dhd_dbgfs { ++ struct dentry *debugfs_dir; ++ struct dentry *debugfs_mem; ++ dhd_pub_t *dhdp; ++ uint32 size; ++} dhd_dbgfs_t; ++ ++dhd_dbgfs_t g_dbgfs; ++ ++static int ++dhd_dbg_state_open(struct inode *inode, struct file *file) ++{ ++ file->private_data = inode->i_private; ++ return 0; ++} ++ ++static ssize_t ++dhd_dbg_state_read(struct file *file, char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ ssize_t rval; ++ uint32 tmp; ++ loff_t pos = *ppos; ++ size_t ret; ++ ++ if (pos < 0) ++ return -EINVAL; ++ if (pos >= g_dbgfs.size || !count) ++ return 0; ++ if (count > g_dbgfs.size - pos) ++ count = g_dbgfs.size - pos; ++ ++ /* Basically enforce aligned 4 byte reads. It's up to the user to work out the details */ ++ tmp = dhd_readregl(g_dbgfs.dhdp->bus, file->f_pos & (~3)); ++ ++ ret = copy_to_user(ubuf, &tmp, 4); ++ if (ret == count) ++ return -EFAULT; ++ ++ count -= ret; ++ *ppos = pos + count; ++ rval = count; ++ ++ return rval; ++} ++ ++ ++static ssize_t ++dhd_debugfs_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) ++{ ++ loff_t pos = *ppos; ++ size_t ret; ++ uint32 buf; ++ ++ if (pos < 0) ++ return -EINVAL; ++ if (pos >= g_dbgfs.size || !count) ++ return 0; ++ if (count > g_dbgfs.size - pos) ++ count = g_dbgfs.size - pos; ++ ++ ret = copy_from_user(&buf, ubuf, sizeof(uint32)); ++ if (ret == count) ++ return -EFAULT; ++ ++ /* Basically enforce aligned 4 byte writes. It's up to the user to work out the details */ ++ dhd_writeregl(g_dbgfs.dhdp->bus, file->f_pos & (~3), buf); ++ ++ return count; ++} ++ ++ ++loff_t ++dhd_debugfs_lseek(struct file *file, loff_t off, int whence) ++{ ++ loff_t pos = -1; ++ ++ switch (whence) { ++ case 0: ++ pos = off; ++ break; ++ case 1: ++ pos = file->f_pos + off; ++ break; ++ case 2: ++ pos = g_dbgfs.size - off; ++ } ++ return (pos < 0 || pos > g_dbgfs.size) ? -EINVAL : (file->f_pos = pos); ++} ++ ++static const struct file_operations dhd_dbg_state_ops = { ++ .read = dhd_dbg_state_read, ++ .write = dhd_debugfs_write, ++ .open = dhd_dbg_state_open, ++ .llseek = dhd_debugfs_lseek ++}; ++ ++static void dhd_dbg_create(void) ++{ ++ if (g_dbgfs.debugfs_dir) { ++ g_dbgfs.debugfs_mem = debugfs_create_file("mem", 0644, g_dbgfs.debugfs_dir, ++ NULL, &dhd_dbg_state_ops); ++ } ++} ++ ++void dhd_dbg_init(dhd_pub_t *dhdp) ++{ ++ int err; ++ ++ g_dbgfs.dhdp = dhdp; ++ g_dbgfs.size = 0x20000000; /* Allow access to various cores regs */ ++ ++ g_dbgfs.debugfs_dir = debugfs_create_dir("dhd", 0); ++ if (IS_ERR(g_dbgfs.debugfs_dir)) { ++ err = PTR_ERR(g_dbgfs.debugfs_dir); ++ g_dbgfs.debugfs_dir = NULL; ++ return; ++ } ++ ++ dhd_dbg_create(); ++ ++ return; ++} ++ ++void dhd_dbg_remove(void) ++{ ++ debugfs_remove(g_dbgfs.debugfs_mem); ++ debugfs_remove(g_dbgfs.debugfs_dir); ++ ++ bzero((unsigned char *) &g_dbgfs, sizeof(g_dbgfs)); ++ ++} ++#endif /* ifdef BCMDBGFS */ ++ ++#ifdef WLMEDIA_HTSF ++ ++static ++void dhd_htsf_addtxts(dhd_pub_t *dhdp, void *pktbuf) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); ++ struct sk_buff *skb; ++ uint32 htsf = 0; ++ uint16 dport = 0, oldmagic = 0xACAC; ++ char *p1; ++ htsfts_t ts; ++ ++ /* timestamp packet */ ++ ++ p1 = (char*) PKTDATA(dhdp->osh, pktbuf); ++ ++ if (PKTLEN(dhdp->osh, pktbuf) > HTSF_MINLEN) { ++/* memcpy(&proto, p1+26, 4); */ ++ memcpy(&dport, p1+40, 2); ++/* proto = ((ntoh32(proto))>> 16) & 0xFF; */ ++ dport = ntoh16(dport); ++ } ++ ++ /* timestamp only if icmp or udb iperf with port 5555 */ ++/* if (proto == 17 && dport == tsport) { */ ++ if (dport >= tsport && dport <= tsport + 20) { ++ ++ skb = (struct sk_buff *) pktbuf; ++ ++ htsf = dhd_get_htsf(dhd, 0); ++ memset(skb->data + 44, 0, 2); /* clear checksum */ ++ memcpy(skb->data+82, &oldmagic, 2); ++ memcpy(skb->data+84, &htsf, 4); ++ ++ memset(&ts, 0, sizeof(htsfts_t)); ++ ts.magic = HTSFMAGIC; ++ ts.prio = PKTPRIO(pktbuf); ++ ts.seqnum = htsf_seqnum++; ++ ts.c10 = get_cycles(); ++ ts.t10 = htsf; ++ ts.endmagic = HTSFENDMAGIC; ++ ++ memcpy(skb->data + HTSF_HOSTOFFSET, &ts, sizeof(ts)); ++ } ++} ++ ++static void dhd_dump_htsfhisto(histo_t *his, char *s) ++{ ++ int pktcnt = 0, curval = 0, i; ++ for (i = 0; i < (NUMBIN-2); i++) { ++ curval += 500; ++ AP6210_DUMP("%d ", his->bin[i]); ++ pktcnt += his->bin[i]; ++ } ++ AP6210_DUMP(" max: %d TotPkt: %d neg: %d [%s]\n", his->bin[NUMBIN-2], pktcnt, ++ his->bin[NUMBIN-1], s); ++} ++ ++static ++void sorttobin(int value, histo_t *histo) ++{ ++ int i, binval = 0; ++ ++ if (value < 0) { ++ histo->bin[NUMBIN-1]++; ++ return; ++ } ++ if (value > histo->bin[NUMBIN-2]) /* store the max value */ ++ histo->bin[NUMBIN-2] = value; ++ ++ for (i = 0; i < (NUMBIN-2); i++) { ++ binval += 500; /* 500m s bins */ ++ if (value <= binval) { ++ histo->bin[i]++; ++ return; ++ } ++ } ++ histo->bin[NUMBIN-3]++; ++} ++ ++static ++void dhd_htsf_addrxts(dhd_pub_t *dhdp, void *pktbuf) ++{ ++ dhd_info_t *dhd = (dhd_info_t *)dhdp->info; ++ struct sk_buff *skb; ++ char *p1; ++ uint16 old_magic; ++ int d1, d2, d3, end2end; ++ htsfts_t *htsf_ts; ++ uint32 htsf; ++ ++ skb = PKTTONATIVE(dhdp->osh, pktbuf); ++ p1 = (char*)PKTDATA(dhdp->osh, pktbuf); ++ ++ if (PKTLEN(osh, pktbuf) > HTSF_MINLEN) { ++ memcpy(&old_magic, p1+78, 2); ++ htsf_ts = (htsfts_t*) (p1 + HTSF_HOSTOFFSET - 4); ++ } ++ else ++ return; ++ ++ if (htsf_ts->magic == HTSFMAGIC) { ++ htsf_ts->tE0 = dhd_get_htsf(dhd, 0); ++ htsf_ts->cE0 = get_cycles(); ++ } ++ ++ if (old_magic == 0xACAC) { ++ ++ tspktcnt++; ++ htsf = dhd_get_htsf(dhd, 0); ++ memcpy(skb->data+92, &htsf, sizeof(uint32)); ++ ++ memcpy(&ts[tsidx].t1, skb->data+80, 16); ++ ++ d1 = ts[tsidx].t2 - ts[tsidx].t1; ++ d2 = ts[tsidx].t3 - ts[tsidx].t2; ++ d3 = ts[tsidx].t4 - ts[tsidx].t3; ++ end2end = ts[tsidx].t4 - ts[tsidx].t1; ++ ++ sorttobin(d1, &vi_d1); ++ sorttobin(d2, &vi_d2); ++ sorttobin(d3, &vi_d3); ++ sorttobin(end2end, &vi_d4); ++ ++ if (end2end > 0 && end2end > maxdelay) { ++ maxdelay = end2end; ++ maxdelaypktno = tspktcnt; ++ memcpy(&maxdelayts, &ts[tsidx], 16); ++ } ++ if (++tsidx >= TSMAX) ++ tsidx = 0; ++ } ++} ++ ++uint32 dhd_get_htsf(dhd_info_t *dhd, int ifidx) ++{ ++ uint32 htsf = 0, cur_cycle, delta, delta_us; ++ uint32 factor, baseval, baseval2; ++ cycles_t t; ++ ++ t = get_cycles(); ++ cur_cycle = t; ++ ++ if (cur_cycle > dhd->htsf.last_cycle) ++ delta = cur_cycle - dhd->htsf.last_cycle; ++ else { ++ delta = cur_cycle + (0xFFFFFFFF - dhd->htsf.last_cycle); ++ } ++ ++ delta = delta >> 4; ++ ++ if (dhd->htsf.coef) { ++ /* times ten to get the first digit */ ++ factor = (dhd->htsf.coef*10 + dhd->htsf.coefdec1); ++ baseval = (delta*10)/factor; ++ baseval2 = (delta*10)/(factor+1); ++ delta_us = (baseval - (((baseval - baseval2) * dhd->htsf.coefdec2)) / 10); ++ htsf = (delta_us << 4) + dhd->htsf.last_tsf + HTSF_BUS_DELAY; ++ } ++ else { ++ AP6210_ERR("-------dhd->htsf.coef = 0 -------\n"); ++ } ++ ++ return htsf; ++} ++ ++static void dhd_dump_latency(void) ++{ ++ int i, max = 0; ++ int d1, d2, d3, d4, d5; ++ ++ AP6210_DEBUG("T1 T2 T3 T4 d1 d2 t4-t1 i \n"); ++ for (i = 0; i < TSMAX; i++) { ++ d1 = ts[i].t2 - ts[i].t1; ++ d2 = ts[i].t3 - ts[i].t2; ++ d3 = ts[i].t4 - ts[i].t3; ++ d4 = ts[i].t4 - ts[i].t1; ++ d5 = ts[max].t4-ts[max].t1; ++ if (d4 > d5 && d4 > 0) { ++ max = i; ++ } ++ AP6210_DUMP("%08X %08X %08X %08X \t%d %d %d %d i=%d\n", ++ ts[i].t1, ts[i].t2, ts[i].t3, ts[i].t4, ++ d1, d2, d3, d4, i); ++ } ++ ++ AP6210_DEBUG("current idx = %d \n", tsidx); ++ ++ AP6210_DEBUG("Highest latency %d pkt no.%d total=%d\n", maxdelay, maxdelaypktno, tspktcnt); ++ AP6210_DEBUG("%08X %08X %08X %08X \t%d %d %d %d\n", ++ maxdelayts.t1, maxdelayts.t2, maxdelayts.t3, maxdelayts.t4, ++ maxdelayts.t2 - maxdelayts.t1, ++ maxdelayts.t3 - maxdelayts.t2, ++ maxdelayts.t4 - maxdelayts.t3, ++ maxdelayts.t4 - maxdelayts.t1); ++} ++ ++ ++static int ++dhd_ioctl_htsf_get(dhd_info_t *dhd, int ifidx) ++{ ++ wl_ioctl_t ioc; ++ char buf[32]; ++ int ret; ++ uint32 s1, s2; ++ ++ struct tsf { ++ uint32 low; ++ uint32 high; ++ } tsf_buf; ++ ++ memset(&ioc, 0, sizeof(ioc)); ++ memset(&tsf_buf, 0, sizeof(tsf_buf)); ++ ++ ioc.cmd = WLC_GET_VAR; ++ ioc.buf = buf; ++ ioc.len = (uint)sizeof(buf); ++ ioc.set = FALSE; ++ ++ strncpy(buf, "tsf", sizeof(buf) - 1); ++ buf[sizeof(buf) - 1] = '\0'; ++ s1 = dhd_get_htsf(dhd, 0); ++ if ((ret = dhd_wl_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len)) < 0) { ++ if (ret == -EIO) { ++ AP6210_ERR("%s: tsf is not supported by device\n", ++ dhd_ifname(&dhd->pub, ifidx)); ++ return -EOPNOTSUPP; ++ } ++ return ret; ++ } ++ s2 = dhd_get_htsf(dhd, 0); ++ ++ memcpy(&tsf_buf, buf, sizeof(tsf_buf)); ++ AP6210_DEBUG("TSF_h=%04X lo=%08X Calc:htsf=%08X, coef=%d.%d%d delta=%d ", ++ tsf_buf.high, tsf_buf.low, s2, dhd->htsf.coef, dhd->htsf.coefdec1, ++ dhd->htsf.coefdec2, s2-tsf_buf.low); ++ AP6210_DEBUG("lasttsf=%08X lastcycle=%08X\n", dhd->htsf.last_tsf, dhd->htsf.last_cycle); ++ return 0; ++} ++ ++void htsf_update(dhd_info_t *dhd, void *data) ++{ ++ static ulong cur_cycle = 0, prev_cycle = 0; ++ uint32 htsf, tsf_delta = 0; ++ uint32 hfactor = 0, cyc_delta, dec1 = 0, dec2, dec3, tmp; ++ ulong b, a; ++ cycles_t t; ++ ++ /* cycles_t in inlcude/mips/timex.h */ ++ ++ t = get_cycles(); ++ ++ prev_cycle = cur_cycle; ++ cur_cycle = t; ++ ++ if (cur_cycle > prev_cycle) ++ cyc_delta = cur_cycle - prev_cycle; ++ else { ++ b = cur_cycle; ++ a = prev_cycle; ++ cyc_delta = cur_cycle + (0xFFFFFFFF - prev_cycle); ++ } ++ ++ if (data == NULL) ++ AP6210_DEBUG(" tsf update ata point er is null \n"); ++ ++ memcpy(&prev_tsf, &cur_tsf, sizeof(tsf_t)); ++ memcpy(&cur_tsf, data, sizeof(tsf_t)); ++ ++ if (cur_tsf.low == 0) { ++ AP6210_DEBUG(" ---- 0 TSF, do not update, return\n"); ++ return; ++ } ++ ++ if (cur_tsf.low > prev_tsf.low) ++ tsf_delta = (cur_tsf.low - prev_tsf.low); ++ else { ++ AP6210_DEBUG(" ---- tsf low is smaller cur_tsf= %08X, prev_tsf=%08X, \n", ++ cur_tsf.low, prev_tsf.low); ++ if (cur_tsf.high > prev_tsf.high) { ++ tsf_delta = cur_tsf.low + (0xFFFFFFFF - prev_tsf.low); ++ AP6210_DEBUG(" ---- Wrap around tsf coutner adjusted TSF=%08X\n", tsf_delta); ++ } ++ else ++ return; /* do not update */ ++ } ++ ++ if (tsf_delta) { ++ hfactor = cyc_delta / tsf_delta; ++ tmp = (cyc_delta - (hfactor * tsf_delta))*10; ++ dec1 = tmp/tsf_delta; ++ dec2 = ((tmp - dec1*tsf_delta)*10) / tsf_delta; ++ tmp = (tmp - (dec1*tsf_delta))*10; ++ dec3 = ((tmp - dec2*tsf_delta)*10) / tsf_delta; ++ ++ if (dec3 > 4) { ++ if (dec2 == 9) { ++ dec2 = 0; ++ if (dec1 == 9) { ++ dec1 = 0; ++ hfactor++; ++ } ++ else { ++ dec1++; ++ } ++ } ++ else ++ dec2++; ++ } ++ } ++ ++ if (hfactor) { ++ htsf = ((cyc_delta * 10) / (hfactor*10+dec1)) + prev_tsf.low; ++ dhd->htsf.coef = hfactor; ++ dhd->htsf.last_cycle = cur_cycle; ++ dhd->htsf.last_tsf = cur_tsf.low; ++ dhd->htsf.coefdec1 = dec1; ++ dhd->htsf.coefdec2 = dec2; ++ } ++ else { ++ htsf = prev_tsf.low; ++ } ++} ++ ++#endif /* WLMEDIA_HTSF */ +diff --git a/drivers/net/wireless/ap6210/dhd_linux_sched.c b/drivers/net/wireless/ap6210/dhd_linux_sched.c +new file mode 100755 +index 0000000..290caf7 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_linux_sched.c +@@ -0,0 +1,39 @@ ++/* ++ * Expose some of the kernel scheduler routines ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhd_linux_sched.c 291086 2011-10-21 01:17:24Z $ ++ */ ++#include ++#include ++#include ++#include ++#include ++ ++int setScheduler(struct task_struct *p, int policy, struct sched_param *param) ++{ ++ int rc = 0; ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++ rc = sched_setscheduler(p, policy, param); ++#endif /* LinuxVer */ ++ return rc; ++} +diff --git a/drivers/net/wireless/ap6210/dhd_pno.c b/drivers/net/wireless/ap6210/dhd_pno.c +new file mode 100755 +index 0000000..317a063 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_pno.c +@@ -0,0 +1,1838 @@ ++/* ++ * Broadcom Dongle Host Driver (DHD) ++ * Prefered Network Offload and Wi-Fi Location Service(WLS) code. ++ * ++ * Copyright (C) 1999-2013, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhd_pno.c 420056 2013-08-24 00:53:12Z $ ++ */ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#ifdef __BIG_ENDIAN ++#include ++#define htod32(i) (bcmswap32(i)) ++#define htod16(i) (bcmswap16(i)) ++#define dtoh32(i) (bcmswap32(i)) ++#define dtoh16(i) (bcmswap16(i)) ++#define htodchanspec(i) htod16(i) ++#define dtohchanspec(i) dtoh16(i) ++#else ++#define htod32(i) i ++#define htod16(i) i ++#define dtoh32(i) i ++#define dtoh16(i) i ++#define htodchanspec(i) i ++#define dtohchanspec(i) i ++#endif /* IL_BIGENDINA */ ++ ++#define NULL_CHECK(p, s, err) \ ++ do { \ ++ if (!(p)) { \ ++ printf("NULL POINTER (%s) : %s\n", __FUNCTION__, (s)); \ ++ err = BCME_ERROR; \ ++ return err; \ ++ } \ ++ } while (0) ++#define PNO_GET_PNOSTATE(dhd) ((dhd_pno_status_info_t *)dhd->pno_state) ++#define PNO_BESTNET_LEN 1024 ++#define PNO_ON 1 ++#define PNO_OFF 0 ++#define CHANNEL_2G_MAX 14 ++#define MAX_NODE_CNT 5 ++#define WLS_SUPPORTED(pno_state) (pno_state->wls_supported == TRUE) ++#define TIME_DIFF(timestamp1, timestamp2) (abs((uint32)(timestamp1/1000) \ ++ - (uint32)(timestamp2/1000))) ++ ++#define ENTRY_OVERHEAD strlen("bssid=\nssid=\nfreq=\nlevel=\nage=\ndist=\ndistSd=\n====") ++#define TIME_MIN_DIFF 5 ++static inline bool ++is_dfs(uint16 channel) ++{ ++ if (channel >= 52 && channel <= 64) /* class 2 */ ++ return TRUE; ++ else if (channel >= 100 && channel <= 140) /* class 4 */ ++ return TRUE; ++ else ++ return FALSE; ++} ++static int ++_dhd_pno_clean(dhd_pub_t *dhd) ++{ ++ int pfn = 0; ++ int err; ++ dhd_pno_status_info_t *_pno_state; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); ++ _pno_state = PNO_GET_PNOSTATE(dhd); ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ /* Disable PNO */ ++ err = dhd_iovar(dhd, 0, "pfn", (char *)&pfn, sizeof(pfn), 1); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to execute pfn(error : %d)\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ _pno_state->pno_status = DHD_PNO_DISABLED; ++ err = dhd_iovar(dhd, 0, "pfnclear", NULL, 0, 1); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to execute pfnclear(error : %d)\n", ++ __FUNCTION__, err); ++ } ++exit: ++ return err; ++} ++ ++static int ++_dhd_pno_suspend(dhd_pub_t *dhd) ++{ ++ int err; ++ int suspend = 1; ++ dhd_pno_status_info_t *_pno_state; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ err = dhd_iovar(dhd, 0, "pfn_suspend", (char *)&suspend, sizeof(suspend), 1); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to suspend pfn(error :%d)\n", __FUNCTION__, err); ++ goto exit; ++ ++ } ++ _pno_state->pno_status = DHD_PNO_SUSPEND; ++exit: ++ return err; ++} ++static int ++_dhd_pno_enable(dhd_pub_t *dhd, int enable) ++{ ++ int err = BCME_OK; ++ dhd_pno_status_info_t *_pno_state; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); ++ _pno_state = PNO_GET_PNOSTATE(dhd); ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ ++ if (enable & 0xfffe) { ++ AP6210_ERR("%s invalid value\n", __FUNCTION__); ++ err = BCME_BADARG; ++ goto exit; ++ } ++ if (!dhd_support_sta_mode(dhd)) { ++ AP6210_ERR("PNO is not allowed for non-STA mode"); ++ err = BCME_BADOPTION; ++ goto exit; ++ } ++ if (enable) { ++ if ((_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) && ++ dhd_is_associated(dhd, NULL, NULL)) { ++ AP6210_ERR("%s Legacy PNO mode cannot be enabled " ++ "in assoc mode , ignore it\n", __FUNCTION__); ++ err = BCME_BADOPTION; ++ goto exit; ++ } ++ } ++ /* Enable/Disable PNO */ ++ err = dhd_iovar(dhd, 0, "pfn", (char *)&enable, sizeof(enable), 1); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to execute pfn_set\n", __FUNCTION__); ++ goto exit; ++ } ++ _pno_state->pno_status = (enable)? ++ DHD_PNO_ENABLED : DHD_PNO_DISABLED; ++ if (!enable) ++ _pno_state->pno_mode = DHD_PNO_NONE_MODE; ++ ++ AP6210_DEBUG("%s set pno as %s\n", ++ __FUNCTION__, enable ? "Enable" : "Disable"); ++exit: ++ return err; ++} ++ ++static int ++_dhd_pno_set(dhd_pub_t *dhd, const dhd_pno_params_t *pno_params, dhd_pno_mode_t mode) ++{ ++ int err = BCME_OK; ++ wl_pfn_param_t pfn_param; ++ dhd_pno_params_t *_params; ++ dhd_pno_status_info_t *_pno_state; ++ bool combined_scan = FALSE; ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); ++ _pno_state = PNO_GET_PNOSTATE(dhd); ++ ++ memset(&pfn_param, 0, sizeof(pfn_param)); ++ ++ /* set pfn parameters */ ++ pfn_param.version = htod32(PFN_VERSION); ++ pfn_param.flags = ((PFN_LIST_ORDER << SORT_CRITERIA_BIT) | ++ (ENABLE << IMMEDIATE_SCAN_BIT) | (ENABLE << REPORT_SEPERATELY_BIT)); ++ if (mode == DHD_PNO_LEGACY_MODE) { ++ /* check and set extra pno params */ ++ if ((pno_params->params_legacy.pno_repeat != 0) || ++ (pno_params->params_legacy.pno_freq_expo_max != 0)) { ++ pfn_param.flags |= htod16(ENABLE << ENABLE_ADAPTSCAN_BIT); ++ pfn_param.repeat = (uchar) (pno_params->params_legacy.pno_repeat); ++ pfn_param.exp = (uchar) (pno_params->params_legacy.pno_freq_expo_max); ++ } ++ /* set up pno scan fr */ ++ if (pno_params->params_legacy.scan_fr != 0) ++ pfn_param.scan_freq = htod32(pno_params->params_legacy.scan_fr); ++ if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) { ++ AP6210_DEBUG("will enable combined scan with BATCHIG SCAN MODE\n"); ++ mode |= DHD_PNO_BATCH_MODE; ++ combined_scan = TRUE; ++ } else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) { ++ AP6210_DEBUG("will enable combined scan with HOTLIST SCAN MODE\n"); ++ mode |= DHD_PNO_HOTLIST_MODE; ++ combined_scan = TRUE; ++ } ++ } ++ if (mode & (DHD_PNO_BATCH_MODE | DHD_PNO_HOTLIST_MODE)) { ++ /* Scan frequency of 30 sec */ ++ pfn_param.scan_freq = htod32(30); ++ /* slow adapt scan is off by default */ ++ pfn_param.slow_freq = htod32(0); ++ /* RSSI margin of 30 dBm */ ++ pfn_param.rssi_margin = htod16(30); ++ /* Network timeout 60 sec */ ++ pfn_param.lost_network_timeout = htod32(60); ++ /* best n = 2 by default */ ++ pfn_param.bestn = DEFAULT_BESTN; ++ /* mscan m=0 by default, so not record best networks by default */ ++ pfn_param.mscan = DEFAULT_MSCAN; ++ /* default repeat = 10 */ ++ pfn_param.repeat = DEFAULT_REPEAT; ++ /* by default, maximum scan interval = 2^2 ++ * scan_freq when adaptive scan is turned on ++ */ ++ pfn_param.exp = DEFAULT_EXP; ++ if (mode == DHD_PNO_BATCH_MODE) { ++ /* In case of BATCH SCAN */ ++ if (pno_params->params_batch.bestn) ++ pfn_param.bestn = pno_params->params_batch.bestn; ++ if (pno_params->params_batch.scan_fr) ++ pfn_param.scan_freq = htod32(pno_params->params_batch.scan_fr); ++ if (pno_params->params_batch.mscan) ++ pfn_param.mscan = pno_params->params_batch.mscan; ++ /* enable broadcast scan */ ++ pfn_param.flags |= (ENABLE << ENABLE_BD_SCAN_BIT); ++ } else if (mode == DHD_PNO_HOTLIST_MODE) { ++ /* In case of HOTLIST SCAN */ ++ if (pno_params->params_hotlist.scan_fr) ++ pfn_param.scan_freq = htod32(pno_params->params_hotlist.scan_fr); ++ pfn_param.bestn = 0; ++ pfn_param.repeat = 0; ++ /* enable broadcast scan */ ++ pfn_param.flags |= (ENABLE << ENABLE_BD_SCAN_BIT); ++ } ++ if (combined_scan) { ++ /* Disable Adaptive Scan */ ++ pfn_param.flags &= ~(htod16(ENABLE << ENABLE_ADAPTSCAN_BIT)); ++ pfn_param.flags |= (ENABLE << ENABLE_BD_SCAN_BIT); ++ pfn_param.repeat = 0; ++ pfn_param.exp = 0; ++ if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) { ++ /* In case of Legacy PNO + BATCH SCAN */ ++ _params = &(_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]); ++ if (_params->params_batch.bestn) ++ pfn_param.bestn = _params->params_batch.bestn; ++ if (_params->params_batch.scan_fr) ++ pfn_param.scan_freq = htod32(_params->params_batch.scan_fr); ++ if (_params->params_batch.mscan) ++ pfn_param.mscan = _params->params_batch.mscan; ++ } else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) { ++ /* In case of Legacy PNO + HOTLIST SCAN */ ++ _params = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]); ++ if (_params->params_hotlist.scan_fr) ++ pfn_param.scan_freq = htod32(_params->params_hotlist.scan_fr); ++ pfn_param.bestn = 0; ++ pfn_param.repeat = 0; ++ } ++ } ++ } ++ if (pfn_param.scan_freq < htod32(PNO_SCAN_MIN_FW_SEC) || ++ pfn_param.scan_freq > htod32(PNO_SCAN_MAX_FW_SEC)) { ++ AP6210_ERR("%s pno freq(%d sec) is not valid \n", ++ __FUNCTION__, PNO_SCAN_MIN_FW_SEC); ++ err = BCME_BADARG; ++ goto exit; ++ } ++ if (mode == DHD_PNO_BATCH_MODE) { ++ int _tmp = pfn_param.bestn; ++ /* set bestn to calculate the max mscan which firmware supports */ ++ err = dhd_iovar(dhd, 0, "pfnmem", (char *)&_tmp, sizeof(_tmp), 1); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to set pfnmscan\n", __FUNCTION__); ++ goto exit; ++ } ++ /* get max mscan which the firmware supports */ ++ err = dhd_iovar(dhd, 0, "pfnmem", (char *)&_tmp, sizeof(_tmp), 0); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to get pfnmscan\n", __FUNCTION__); ++ goto exit; ++ } ++ AP6210_DEBUG(" returned mscan : %d, set bestn : %d\n", _tmp, pfn_param.bestn); ++ pfn_param.mscan = MIN(pfn_param.mscan, _tmp); ++ } ++ err = dhd_iovar(dhd, 0, "pfn_set", (char *)&pfn_param, sizeof(pfn_param), 1); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to execute pfn_set\n", __FUNCTION__); ++ goto exit; ++ } ++ /* need to return mscan if this is for batch scan instead of err */ ++ err = (mode == DHD_PNO_BATCH_MODE)? pfn_param.mscan : err; ++exit: ++ return err; ++} ++static int ++_dhd_pno_add_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssids_list, int nssid) ++{ ++ int err = BCME_OK; ++ int i = 0; ++ wl_pfn_t pfn_element; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ if (nssid) { ++ NULL_CHECK(ssids_list, "ssid list is NULL", err); ++ } ++ memset(&pfn_element, 0, sizeof(pfn_element)); ++ { ++ int j; ++ for (j = 0; j < nssid; j++) { ++ AP6210_DEBUG("%d: scan for %s size = %d\n", j, ++ ssids_list[j].SSID, ssids_list[j].SSID_len); ++ } ++ } ++ /* Check for broadcast ssid */ ++ for (i = 0; i < nssid; i++) { ++ if (!ssids_list[i].SSID_len) { ++ AP6210_ERR("%d: Broadcast SSID is ilegal for PNO setting\n", i); ++ err = BCME_ERROR; ++ goto exit; ++ } ++ } ++ /* set all pfn ssid */ ++ for (i = 0; i < nssid; i++) { ++ pfn_element.infra = htod32(DOT11_BSSTYPE_INFRASTRUCTURE); ++ pfn_element.auth = (DOT11_OPEN_SYSTEM); ++ pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY); ++ pfn_element.wsec = htod32(0); ++ pfn_element.infra = htod32(1); ++ pfn_element.flags = htod32(ENABLE << WL_PFN_HIDDEN_BIT); ++ memcpy((char *)pfn_element.ssid.SSID, ssids_list[i].SSID, ++ ssids_list[i].SSID_len); ++ pfn_element.ssid.SSID_len = ssids_list[i].SSID_len; ++ err = dhd_iovar(dhd, 0, "pfn_add", (char *)&pfn_element, ++ sizeof(pfn_element), 1); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to execute pfn_add\n", __FUNCTION__); ++ goto exit; ++ } ++ } ++exit: ++ return err; ++} ++/* qsort compare function */ ++static int ++_dhd_pno_cmpfunc(const void *a, const void *b) ++{ ++ return (*(uint16*)a - *(uint16*)b); ++} ++static int ++_dhd_pno_chan_merge(uint16 *d_chan_list, int *nchan, ++ uint16 *chan_list1, int nchan1, uint16 *chan_list2, int nchan2) ++{ ++ int err = BCME_OK; ++ int i = 0, j = 0, k = 0; ++ uint16 tmp; ++ NULL_CHECK(d_chan_list, "d_chan_list is NULL", err); ++ NULL_CHECK(nchan, "nchan is NULL", err); ++ NULL_CHECK(chan_list1, "chan_list1 is NULL", err); ++ NULL_CHECK(chan_list2, "chan_list2 is NULL", err); ++ /* chan_list1 and chan_list2 should be sorted at first */ ++ while (i < nchan1 && j < nchan2) { ++ tmp = chan_list1[i] < chan_list2[j]? ++ chan_list1[i++] : chan_list2[j++]; ++ for (; i < nchan1 && chan_list1[i] == tmp; i++); ++ for (; j < nchan2 && chan_list2[j] == tmp; j++); ++ d_chan_list[k++] = tmp; ++ } ++ ++ while (i < nchan1) { ++ tmp = chan_list1[i++]; ++ for (; i < nchan1 && chan_list1[i] == tmp; i++); ++ d_chan_list[k++] = tmp; ++ } ++ ++ while (j < nchan2) { ++ tmp = chan_list2[j++]; ++ for (; j < nchan2 && chan_list2[j] == tmp; j++); ++ d_chan_list[k++] = tmp; ++ ++ } ++ *nchan = k; ++ return err; ++} ++static int ++_dhd_pno_get_channels(dhd_pub_t *dhd, uint16 *d_chan_list, ++ int *nchan, uint8 band, bool skip_dfs) ++{ ++ int err = BCME_OK; ++ int i, j; ++ uint32 chan_buf[WL_NUMCHANNELS + 1]; ++ wl_uint32_list_t *list; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ if (*nchan) { ++ NULL_CHECK(d_chan_list, "d_chan_list is NULL", err); ++ } ++ list = (wl_uint32_list_t *) (void *)chan_buf; ++ list->count = htod32(WL_NUMCHANNELS); ++ err = dhd_wl_ioctl_cmd(dhd, WLC_GET_VALID_CHANNELS, chan_buf, sizeof(chan_buf), FALSE, 0); ++ if (err < 0) { ++ AP6210_ERR("failed to get channel list (err: %d)\n", err); ++ goto exit; ++ } ++ for (i = 0, j = 0; i < dtoh32(list->count) && i < *nchan; i++) { ++ if (band == WLC_BAND_2G) { ++ if (dtoh32(list->element[i]) > CHANNEL_2G_MAX) ++ continue; ++ } else if (band == WLC_BAND_5G) { ++ if (dtoh32(list->element[i]) <= CHANNEL_2G_MAX) ++ continue; ++ if (skip_dfs && is_dfs(dtoh32(list->element[i]))) ++ continue; ++ ++ } else { /* All channels */ ++ if (skip_dfs && is_dfs(dtoh32(list->element[i]))) ++ continue; ++ } ++ d_chan_list[j++] = dtoh32(list->element[i]); ++ } ++ *nchan = j; ++exit: ++ return err; ++} ++static int ++_dhd_pno_convert_format(dhd_pub_t *dhd, struct dhd_pno_batch_params *params_batch, ++ char *buf, int nbufsize) ++{ ++ int err = BCME_OK; ++ int bytes_written = 0, nreadsize = 0; ++ int t_delta = 0; ++ int nleftsize = nbufsize; ++ uint8 cnt = 0; ++ char *bp = buf; ++ char eabuf[ETHER_ADDR_STR_LEN]; ++#ifdef PNO_DEBUG ++ char *_base_bp; ++ char msg[150]; ++#endif ++ dhd_pno_bestnet_entry_t *iter, *next; ++ dhd_pno_scan_results_t *siter, *snext; ++ dhd_pno_best_header_t *phead, *pprev; ++ NULL_CHECK(params_batch, "params_batch is NULL", err); ++ if (nbufsize > 0) ++ NULL_CHECK(buf, "buf is NULL", err); ++ /* initialize the buffer */ ++ memset(buf, 0, nbufsize); ++ AP6210_DEBUG("%s enter \n", __FUNCTION__); ++ /* # of scans */ ++ if (!params_batch->get_batch.batch_started) { ++ bp += nreadsize = sprintf(bp, "scancount=%d\n", ++ params_batch->get_batch.expired_tot_scan_cnt); ++ nleftsize -= nreadsize; ++ params_batch->get_batch.batch_started = TRUE; ++ } ++ AP6210_DEBUG("%s scancount %d\n", __FUNCTION__, params_batch->get_batch.expired_tot_scan_cnt); ++ /* preestimate scan count until which scan result this report is going to end */ ++ list_for_each_entry_safe(siter, snext, ++ ¶ms_batch->get_batch.expired_scan_results_list, list) { ++ phead = siter->bestnetheader; ++ while (phead != NULL) { ++ /* if left_size is less than bestheader total size , stop this */ ++ if (nleftsize <= ++ (phead->tot_size + phead->tot_cnt * ENTRY_OVERHEAD)) ++ goto exit; ++ /* increase scan count */ ++ cnt++; ++ /* # best of each scan */ ++ AP6210_DEBUG("\n", cnt - 1, phead->tot_cnt); ++ /* attribute of the scan */ ++ if (phead->reason & PNO_STATUS_ABORT_MASK) { ++ bp += nreadsize = sprintf(bp, "trunc\n"); ++ nleftsize -= nreadsize; ++ } ++ list_for_each_entry_safe(iter, next, ++ &phead->entry_list, list) { ++ t_delta = jiffies_to_msecs(jiffies - iter->recorded_time); ++#ifdef PNO_DEBUG ++ _base_bp = bp; ++ memset(msg, 0, sizeof(msg)); ++#endif ++ /* BSSID info */ ++ bp += nreadsize = sprintf(bp, "bssid=%s\n", ++ bcm_ether_ntoa((const struct ether_addr *)&iter->BSSID, eabuf)); ++ nleftsize -= nreadsize; ++ /* SSID */ ++ bp += nreadsize = sprintf(bp, "ssid=%s\n", iter->SSID); ++ nleftsize -= nreadsize; ++ /* channel */ ++ bp += nreadsize = sprintf(bp, "freq=%d\n", ++ wf_channel2mhz(iter->channel, ++ iter->channel <= CH_MAX_2G_CHANNEL? ++ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G)); ++ nleftsize -= nreadsize; ++ /* RSSI */ ++ bp += nreadsize = sprintf(bp, "level=%d\n", iter->RSSI); ++ nleftsize -= nreadsize; ++ /* add the time consumed in Driver to the timestamp of firmware */ ++ iter->timestamp += t_delta; ++ bp += nreadsize = sprintf(bp, "age=%d\n", iter->timestamp); ++ nleftsize -= nreadsize; ++ /* RTT0 */ ++ bp += nreadsize = sprintf(bp, "dist=%d\n", ++ (iter->rtt0 == 0)? -1 : iter->rtt0); ++ nleftsize -= nreadsize; ++ /* RTT1 */ ++ bp += nreadsize = sprintf(bp, "distSd=%d\n", ++ (iter->rtt0 == 0)? -1 : iter->rtt1); ++ nleftsize -= nreadsize; ++ bp += nreadsize = sprintf(bp, "%s", AP_END_MARKER); ++ nleftsize -= nreadsize; ++ list_del(&iter->list); ++ MFREE(dhd->osh, iter, BESTNET_ENTRY_SIZE); ++#ifdef PNO_DEBUG ++ memcpy(msg, _base_bp, bp - _base_bp); ++ AP6210_DEBUG("Entry : \n%s", msg); ++#endif ++ } ++ bp += nreadsize = sprintf(bp, "%s", SCAN_END_MARKER); ++ AP6210_DEBUG("%s", SCAN_END_MARKER); ++ nleftsize -= nreadsize; ++ pprev = phead; ++ /* reset the header */ ++ siter->bestnetheader = phead = phead->next; ++ MFREE(dhd->osh, pprev, BEST_HEADER_SIZE); ++ ++ siter->cnt_header--; ++ } ++ if (phead == NULL) { ++ /* we store all entry in this scan , so it is ok to delete */ ++ list_del(&siter->list); ++ MFREE(dhd->osh, siter, SCAN_RESULTS_SIZE); ++ } ++ } ++exit: ++ if (cnt < params_batch->get_batch.expired_tot_scan_cnt) { ++ AP6210_ERR("Buffer size is small to save all batch entry," ++ " cnt : %d (remained_scan_cnt): %d\n", ++ cnt, params_batch->get_batch.expired_tot_scan_cnt - cnt); ++ } ++ params_batch->get_batch.expired_tot_scan_cnt -= cnt; ++ /* set FALSE only if the link list is empty after returning the data */ ++ if (list_empty(¶ms_batch->get_batch.expired_scan_results_list)) { ++ params_batch->get_batch.batch_started = FALSE; ++ bp += sprintf(bp, "%s", RESULTS_END_MARKER); ++ AP6210_DEBUG("%s", RESULTS_END_MARKER); ++ AP6210_DEBUG("%s : Getting the batching data is complete\n", __FUNCTION__); ++ } ++ /* return used memory in buffer */ ++ bytes_written = (int32)(bp - buf); ++ return bytes_written; ++} ++static int ++_dhd_pno_clear_all_batch_results(dhd_pub_t *dhd, struct list_head *head, bool only_last) ++{ ++ int err = BCME_OK; ++ int removed_scan_cnt = 0; ++ dhd_pno_scan_results_t *siter, *snext; ++ dhd_pno_best_header_t *phead, *pprev; ++ dhd_pno_bestnet_entry_t *iter, *next; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ NULL_CHECK(head, "head is NULL", err); ++ NULL_CHECK(head->next, "head->next is NULL", err); ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ list_for_each_entry_safe(siter, snext, ++ head, list) { ++ if (only_last) { ++ /* in case that we need to delete only last one */ ++ if (!list_is_last(&siter->list, head)) { ++ /* skip if the one is not last */ ++ continue; ++ } ++ } ++ /* delete all data belong if the one is last */ ++ phead = siter->bestnetheader; ++ while (phead != NULL) { ++ removed_scan_cnt++; ++ list_for_each_entry_safe(iter, next, ++ &phead->entry_list, list) { ++ list_del(&iter->list); ++ MFREE(dhd->osh, iter, BESTNET_ENTRY_SIZE); ++ } ++ pprev = phead; ++ phead = phead->next; ++ MFREE(dhd->osh, pprev, BEST_HEADER_SIZE); ++ } ++ if (phead == NULL) { ++ /* it is ok to delete top node */ ++ list_del(&siter->list); ++ MFREE(dhd->osh, siter, SCAN_RESULTS_SIZE); ++ } ++ } ++ return removed_scan_cnt; ++} ++ ++static int ++_dhd_pno_cfg(dhd_pub_t *dhd, uint16 *channel_list, int nchan) ++{ ++ int err = BCME_OK; ++ int i = 0; ++ wl_pfn_cfg_t pfncfg_param; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ if (nchan) { ++ NULL_CHECK(channel_list, "nchan is NULL", err); ++ } ++ AP6210_DEBUG("%s enter : nchan : %d\n", __FUNCTION__, nchan); ++ memset(&pfncfg_param, 0, sizeof(wl_pfn_cfg_t)); ++ /* Setup default values */ ++ pfncfg_param.reporttype = htod32(WL_PFN_REPORT_ALLNET); ++ pfncfg_param.channel_num = htod32(0); ++ ++ for (i = 0; i < nchan && nchan < WL_NUMCHANNELS; i++) ++ pfncfg_param.channel_list[i] = channel_list[i]; ++ ++ pfncfg_param.channel_num = htod32(nchan); ++ err = dhd_iovar(dhd, 0, "pfn_cfg", (char *)&pfncfg_param, sizeof(pfncfg_param), 1); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to execute pfn_cfg\n", __FUNCTION__); ++ goto exit; ++ } ++exit: ++ return err; ++} ++static int ++_dhd_pno_reinitialize_prof(dhd_pub_t *dhd, dhd_pno_params_t *params, dhd_pno_mode_t mode) ++{ ++ int err = BCME_OK; ++ dhd_pno_status_info_t *_pno_state; ++ NULL_CHECK(dhd, "dhd is NULL\n", err); ++ NULL_CHECK(dhd->pno_state, "pno_state is NULL\n", err); ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ _pno_state = PNO_GET_PNOSTATE(dhd); ++ mutex_lock(&_pno_state->pno_mutex); ++ switch (mode) { ++ case DHD_PNO_LEGACY_MODE: { ++ struct dhd_pno_ssid *iter, *next; ++ if (params->params_legacy.nssid > 0) { ++ list_for_each_entry_safe(iter, next, ++ ¶ms->params_legacy.ssid_list, list) { ++ list_del(&iter->list); ++ kfree(iter); ++ } ++ } ++ params->params_legacy.scan_fr = 0; ++ params->params_legacy.pno_freq_expo_max = 0; ++ params->params_legacy.pno_repeat = 0; ++ params->params_legacy.nchan = 0; ++ memset(params->params_legacy.chan_list, 0, ++ sizeof(params->params_legacy.chan_list)); ++ break; ++ } ++ case DHD_PNO_BATCH_MODE: { ++ params->params_batch.scan_fr = 0; ++ params->params_batch.mscan = 0; ++ params->params_batch.nchan = 0; ++ params->params_batch.rtt = 0; ++ params->params_batch.bestn = 0; ++ params->params_batch.nchan = 0; ++ params->params_batch.band = WLC_BAND_AUTO; ++ memset(params->params_batch.chan_list, 0, ++ sizeof(params->params_batch.chan_list)); ++ params->params_batch.get_batch.batch_started = FALSE; ++ params->params_batch.get_batch.buf = NULL; ++ params->params_batch.get_batch.bufsize = 0; ++ params->params_batch.get_batch.reason = 0; ++ _dhd_pno_clear_all_batch_results(dhd, ++ ¶ms->params_batch.get_batch.scan_results_list, FALSE); ++ _dhd_pno_clear_all_batch_results(dhd, ++ ¶ms->params_batch.get_batch.expired_scan_results_list, FALSE); ++ params->params_batch.get_batch.tot_scan_cnt = 0; ++ params->params_batch.get_batch.expired_tot_scan_cnt = 0; ++ params->params_batch.get_batch.top_node_cnt = 0; ++ INIT_LIST_HEAD(¶ms->params_batch.get_batch.scan_results_list); ++ INIT_LIST_HEAD(¶ms->params_batch.get_batch.expired_scan_results_list); ++ break; ++ } ++ case DHD_PNO_HOTLIST_MODE: { ++ struct dhd_pno_bssid *iter, *next; ++ if (params->params_hotlist.nbssid > 0) { ++ list_for_each_entry_safe(iter, next, ++ ¶ms->params_hotlist.bssid_list, list) { ++ list_del(&iter->list); ++ kfree(iter); ++ } ++ } ++ params->params_hotlist.scan_fr = 0; ++ params->params_hotlist.nbssid = 0; ++ params->params_hotlist.nchan = 0; ++ params->params_batch.band = WLC_BAND_AUTO; ++ memset(params->params_hotlist.chan_list, 0, ++ sizeof(params->params_hotlist.chan_list)); ++ break; ++ } ++ default: ++ AP6210_ERR("%s : unknown mode : %d\n", __FUNCTION__, mode); ++ break; ++ } ++ mutex_unlock(&_pno_state->pno_mutex); ++ return err; ++} ++static int ++_dhd_pno_add_bssid(dhd_pub_t *dhd, wl_pfn_bssid_t *p_pfn_bssid, int nbssid) ++{ ++ int err = BCME_OK; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ if (nbssid) { ++ NULL_CHECK(p_pfn_bssid, "bssid list is NULL", err); ++ } ++ err = dhd_iovar(dhd, 0, "pfn_add_bssid", (char *)&p_pfn_bssid, ++ sizeof(wl_pfn_bssid_t) * nbssid, 1); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to execute pfn_cfg\n", __FUNCTION__); ++ goto exit; ++ } ++exit: ++ return err; ++} ++int ++dhd_pno_stop_for_ssid(dhd_pub_t *dhd) ++{ ++ int err = BCME_OK; ++ uint32 mode = 0; ++ dhd_pno_status_info_t *_pno_state; ++ dhd_pno_params_t *_params; ++ wl_pfn_bssid_t *p_pfn_bssid; ++ NULL_CHECK(dhd, "dev is NULL", err); ++ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); ++ _pno_state = PNO_GET_PNOSTATE(dhd); ++ if (!(_pno_state->pno_mode & DHD_PNO_LEGACY_MODE)) { ++ AP6210_ERR("%s : LEGACY PNO MODE is not enabled\n", __FUNCTION__); ++ goto exit; ++ } ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE; ++ /* restart Batch mode if the batch mode is on */ ++ if (_pno_state->pno_mode & (DHD_PNO_BATCH_MODE | DHD_PNO_HOTLIST_MODE)) { ++ /* retrieve the batching data from firmware into host */ ++ dhd_pno_get_for_batch(dhd, NULL, 0, PNO_STATUS_DISABLE); ++ /* save current pno_mode before calling dhd_pno_clean */ ++ mode = _pno_state->pno_mode; ++ _dhd_pno_clean(dhd); ++ /* restore previous pno_mode */ ++ _pno_state->pno_mode = mode; ++ if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) { ++ _params = &(_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]); ++ /* restart BATCH SCAN */ ++ err = dhd_pno_set_for_batch(dhd, &_params->params_batch); ++ if (err < 0) { ++ _pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE; ++ AP6210_ERR("%s : failed to restart batch scan(err: %d)\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ } else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) { ++ /* restart HOTLIST SCAN */ ++ struct dhd_pno_bssid *iter, *next; ++ _params = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]); ++ p_pfn_bssid = kzalloc(sizeof(wl_pfn_bssid_t) * ++ _params->params_hotlist.nbssid, GFP_KERNEL); ++ if (p_pfn_bssid == NULL) { ++ AP6210_ERR("%s : failed to allocate wl_pfn_bssid_t array" ++ " (count: %d)", ++ __FUNCTION__, _params->params_hotlist.nbssid); ++ err = BCME_ERROR; ++ _pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE; ++ goto exit; ++ } ++ /* convert dhd_pno_bssid to wl_pfn_bssid */ ++ list_for_each_entry_safe(iter, next, ++ &_params->params_hotlist.bssid_list, list) { ++ memcpy(&p_pfn_bssid->macaddr, ++ &iter->macaddr, ETHER_ADDR_LEN); ++ p_pfn_bssid->flags = iter->flags; ++ p_pfn_bssid++; ++ } ++ err = dhd_pno_set_for_hotlist(dhd, p_pfn_bssid, &_params->params_hotlist); ++ if (err < 0) { ++ _pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE; ++ AP6210_ERR("%s : failed to restart hotlist scan(err: %d)\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ } ++ } else { ++ err = _dhd_pno_clean(dhd); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to call _dhd_pno_clean (err: %d)\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ } ++exit: ++ return err; ++} ++ ++int ++dhd_pno_enable(dhd_pub_t *dhd, int enable) ++{ ++ int err = BCME_OK; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ return (_dhd_pno_enable(dhd, enable)); ++} ++ ++int ++dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid, ++ uint16 scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan) ++{ ++ struct dhd_pno_ssid *_pno_ssid; ++ dhd_pno_params_t *_params; ++ dhd_pno_params_t *_params2; ++ dhd_pno_status_info_t *_pno_state; ++ uint16 _chan_list[WL_NUMCHANNELS]; ++ int32 tot_nchan = 0; ++ int err = BCME_OK; ++ int i; ++ int mode = 0; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); ++ _pno_state = PNO_GET_PNOSTATE(dhd); ++ ++ if (!dhd_support_sta_mode(dhd)) { ++ err = BCME_BADOPTION; ++ goto exit; ++ } ++ AP6210_DEBUG("%s enter : scan_fr :%d, pno_repeat :%d," ++ "pno_freq_expo_max: %d, nchan :%d\n", __FUNCTION__, ++ scan_fr, pno_repeat, pno_freq_expo_max, nchan); ++ ++ _params = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]); ++ if (!(_pno_state->pno_mode & DHD_PNO_LEGACY_MODE)) { ++ _pno_state->pno_mode |= DHD_PNO_LEGACY_MODE; ++ err = _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to reinitialize profile (err %d)\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ } ++ memset(_chan_list, 0, sizeof(_chan_list)); ++ tot_nchan = nchan; ++ if (tot_nchan > 0 && channel_list) { ++ for (i = 0; i < nchan; i++) ++ _params->params_legacy.chan_list[i] = _chan_list[i] = channel_list[i]; ++ } ++ if (_pno_state->pno_mode & (DHD_PNO_BATCH_MODE | DHD_PNO_HOTLIST_MODE)) { ++ AP6210_DEBUG("BATCH SCAN is on progress in firmware\n"); ++ /* retrieve the batching data from firmware into host */ ++ dhd_pno_get_for_batch(dhd, NULL, 0, PNO_STATUS_DISABLE); ++ /* store current pno_mode before disabling pno */ ++ mode = _pno_state->pno_mode; ++ err = _dhd_pno_enable(dhd, PNO_OFF); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to disable PNO\n", __FUNCTION__); ++ goto exit; ++ } ++ /* restore the previous mode */ ++ _pno_state->pno_mode = mode; ++ /* use superset of channel list between two mode */ ++ if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) { ++ _params2 = &(_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]); ++ if (_params2->params_batch.nchan > 0 && nchan > 0) { ++ err = _dhd_pno_chan_merge(_chan_list, &tot_nchan, ++ &_params2->params_batch.chan_list[0], ++ _params2->params_batch.nchan, ++ &channel_list[0], nchan); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to merge channel list" ++ " between legacy and batch\n", ++ __FUNCTION__); ++ goto exit; ++ } ++ } else { ++ AP6210_DEBUG("superset channel will use" ++ " all channels in firmware\n"); ++ } ++ } else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) { ++ _params2 = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]); ++ if (_params2->params_hotlist.nchan > 0 && nchan > 0) { ++ err = _dhd_pno_chan_merge(_chan_list, &tot_nchan, ++ &_params2->params_hotlist.chan_list[0], ++ _params2->params_hotlist.nchan, ++ &channel_list[0], nchan); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to merge channel list" ++ " between legacy and hotlist\n", ++ __FUNCTION__); ++ goto exit; ++ } ++ } ++ } ++ } ++ _params->params_legacy.scan_fr = scan_fr; ++ _params->params_legacy.pno_repeat = pno_repeat; ++ _params->params_legacy.pno_freq_expo_max = pno_freq_expo_max; ++ _params->params_legacy.nchan = nchan; ++ _params->params_legacy.nssid = nssid; ++ INIT_LIST_HEAD(&_params->params_legacy.ssid_list); ++ if ((err = _dhd_pno_set(dhd, _params, DHD_PNO_LEGACY_MODE)) < 0) { ++ AP6210_ERR("failed to set call pno_set (err %d) in firmware\n", err); ++ goto exit; ++ } ++ if ((err = _dhd_pno_add_ssid(dhd, ssid_list, nssid)) < 0) { ++ AP6210_ERR("failed to add ssid list (err %d) in firmware\n", err); ++ goto exit; ++ } ++ for (i = 0; i < nssid; i++) { ++ _pno_ssid = kzalloc(sizeof(struct dhd_pno_ssid), GFP_KERNEL); ++ if (_pno_ssid == NULL) { ++ AP6210_ERR("%s : failed to allocate struct dhd_pno_ssid\n", ++ __FUNCTION__); ++ goto exit; ++ } ++ _pno_ssid->SSID_len = ssid_list[i].SSID_len; ++ memcpy(_pno_ssid->SSID, ssid_list[i].SSID, _pno_ssid->SSID_len); ++ list_add_tail(&_pno_ssid->list, &_params->params_legacy.ssid_list); ++ ++ } ++ if (tot_nchan > 0) { ++ if ((err = _dhd_pno_cfg(dhd, _chan_list, tot_nchan)) < 0) { ++ AP6210_ERR("%s : failed to set call pno_cfg (err %d) in firmware\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ } ++ if (_pno_state->pno_status == DHD_PNO_DISABLED) { ++ if ((err = _dhd_pno_enable(dhd, PNO_ON)) < 0) ++ AP6210_ERR("%s : failed to enable PNO\n", __FUNCTION__); ++ } ++exit: ++ /* clear mode in case of error */ ++ if (err < 0) ++ _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE; ++ return err; ++} ++int ++dhd_pno_set_for_batch(dhd_pub_t *dhd, struct dhd_pno_batch_params *batch_params) ++{ ++ int err = BCME_OK; ++ uint16 _chan_list[WL_NUMCHANNELS]; ++ int rem_nchan = 0, tot_nchan = 0; ++ int mode = 0, mscan = 0; ++ int i = 0; ++ dhd_pno_params_t *_params; ++ dhd_pno_params_t *_params2; ++ dhd_pno_status_info_t *_pno_state; ++ wlc_ssid_t *p_ssid_list = NULL; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); ++ NULL_CHECK(batch_params, "batch_params is NULL", err); ++ _pno_state = PNO_GET_PNOSTATE(dhd); ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ if (!dhd_support_sta_mode(dhd)) { ++ err = BCME_BADOPTION; ++ goto exit; ++ } ++ if (!WLS_SUPPORTED(_pno_state)) { ++ AP6210_ERR("%s : wifi location service is not supported\n", __FUNCTION__); ++ err = BCME_UNSUPPORTED; ++ goto exit; ++ } ++ _params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]; ++ if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) { ++ _pno_state->pno_mode |= DHD_PNO_BATCH_MODE; ++ err = _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_BATCH_MODE); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to call _dhd_pno_reinitialize_prof\n", ++ __FUNCTION__); ++ goto exit; ++ } ++ } ++ _params->params_batch.scan_fr = batch_params->scan_fr; ++ _params->params_batch.bestn = batch_params->bestn; ++ _params->params_batch.mscan = (batch_params->mscan)? ++ batch_params->mscan : DEFAULT_BATCH_MSCAN; ++ _params->params_batch.nchan = batch_params->nchan; ++ memcpy(_params->params_batch.chan_list, batch_params->chan_list, ++ sizeof(_params->params_batch.chan_list)); ++ ++ memset(_chan_list, 0, sizeof(_chan_list)); ++ ++ rem_nchan = ARRAYSIZE(batch_params->chan_list) - batch_params->nchan; ++ if (batch_params->band == WLC_BAND_2G || batch_params->band == WLC_BAND_5G) { ++ /* get a valid channel list based on band B or A */ ++ err = _dhd_pno_get_channels(dhd, ++ &_params->params_batch.chan_list[batch_params->nchan], ++ &rem_nchan, batch_params->band, FALSE); ++ if (err < 0) { ++ AP6210_ERR("%s: failed to get valid channel list(band : %d)\n", ++ __FUNCTION__, batch_params->band); ++ goto exit; ++ } ++ /* now we need to update nchan because rem_chan has valid channel count */ ++ _params->params_batch.nchan += rem_nchan; ++ /* need to sort channel list */ ++ sort(_params->params_batch.chan_list, _params->params_batch.nchan, ++ sizeof(_params->params_batch.chan_list[0]), _dhd_pno_cmpfunc, NULL); ++ } ++#ifdef PNO_DEBUG ++{ ++ AP6210_DEBUG("Channel list : "); ++ for (i = 0; i < _params->params_batch.nchan; i++) { ++ AP6210_DEBUG("%d ", _params->params_batch.chan_list[i]); ++ } ++ AP6210_DEBUG("\n"); ++} ++#endif ++ if (_params->params_batch.nchan) { ++ /* copy the channel list into local array */ ++ memcpy(_chan_list, _params->params_batch.chan_list, sizeof(_chan_list)); ++ tot_nchan = _params->params_batch.nchan; ++ } ++ if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) { ++ struct dhd_pno_ssid *iter, *next; ++ AP6210_DEBUG("PNO SSID is on progress in firmware\n"); ++ /* store current pno_mode before disabling pno */ ++ mode = _pno_state->pno_mode; ++ err = _dhd_pno_enable(dhd, PNO_OFF); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to disable PNO\n", __FUNCTION__); ++ goto exit; ++ } ++ /* restore the previous mode */ ++ _pno_state->pno_mode = mode; ++ /* Use the superset for channelist between two mode */ ++ _params2 = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]); ++ if (_params2->params_legacy.nchan > 0 && _params->params_batch.nchan > 0) { ++ err = _dhd_pno_chan_merge(_chan_list, &tot_nchan, ++ &_params2->params_legacy.chan_list[0], ++ _params2->params_legacy.nchan, ++ &_params->params_batch.chan_list[0], _params->params_batch.nchan); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to merge channel list" ++ " between legacy and batch\n", ++ __FUNCTION__); ++ goto exit; ++ } ++ } else { ++ AP6210_DEBUG("superset channel will use all channels in firmware\n"); ++ } ++ p_ssid_list = kzalloc(sizeof(wlc_ssid_t) * ++ _params2->params_legacy.nssid, GFP_KERNEL); ++ if (p_ssid_list == NULL) { ++ AP6210_ERR("%s : failed to allocate wlc_ssid_t array (count: %d)", ++ __FUNCTION__, _params2->params_legacy.nssid); ++ err = BCME_ERROR; ++ _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE; ++ goto exit; ++ } ++ i = 0; ++ /* convert dhd_pno_ssid to dhd_pno_ssid */ ++ list_for_each_entry_safe(iter, next, &_params2->params_legacy.ssid_list, list) { ++ p_ssid_list[i].SSID_len = iter->SSID_len; ++ memcpy(p_ssid_list->SSID, iter->SSID, p_ssid_list[i].SSID_len); ++ i++; ++ } ++ if ((err = _dhd_pno_add_ssid(dhd, p_ssid_list, ++ _params2->params_legacy.nssid)) < 0) { ++ AP6210_ERR("failed to add ssid list (err %d) in firmware\n", err); ++ goto exit; ++ } ++ } ++ if ((err = _dhd_pno_set(dhd, _params, DHD_PNO_BATCH_MODE)) < 0) { ++ AP6210_ERR("%s : failed to set call pno_set (err %d) in firmware\n", ++ __FUNCTION__, err); ++ goto exit; ++ } else { ++ /* we need to return mscan */ ++ mscan = err; ++ } ++ if (tot_nchan > 0) { ++ if ((err = _dhd_pno_cfg(dhd, _chan_list, tot_nchan)) < 0) { ++ AP6210_ERR("%s : failed to set call pno_cfg (err %d) in firmware\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ } ++ if (_pno_state->pno_status == DHD_PNO_DISABLED) { ++ if ((err = _dhd_pno_enable(dhd, PNO_ON)) < 0) ++ AP6210_ERR("%s : failed to enable PNO\n", __FUNCTION__); ++ } ++exit: ++ /* clear mode in case of error */ ++ if (err < 0) ++ _pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE; ++ else { ++ /* return #max scan firmware can do */ ++ err = mscan; ++ } ++ if (p_ssid_list) ++ kfree(p_ssid_list); ++ return err; ++} ++ ++static int ++_dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason) ++{ ++ int err = BCME_OK; ++ int i, j; ++ uint32 timestamp = 0; ++ dhd_pno_params_t *_params = NULL; ++ dhd_pno_status_info_t *_pno_state = NULL; ++ wl_pfn_lscanresults_t *plbestnet = NULL; ++ wl_pfn_lnet_info_t *plnetinfo; ++ dhd_pno_bestnet_entry_t *pbestnet_entry; ++ dhd_pno_best_header_t *pbestnetheader = NULL; ++ dhd_pno_scan_results_t *pscan_results = NULL, *siter, *snext; ++ bool allocate_header = FALSE; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); ++ if (!dhd_support_sta_mode(dhd)) { ++ err = BCME_BADOPTION; ++ goto exit; ++ } ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ _pno_state = PNO_GET_PNOSTATE(dhd); ++ ++ if (!WLS_SUPPORTED(_pno_state)) { ++ AP6210_ERR("%s : wifi location service is not supported\n", __FUNCTION__); ++ err = BCME_UNSUPPORTED; ++ goto exit; ++ } ++ if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) { ++ AP6210_ERR("%s: Batching SCAN mode is not enabled\n", __FUNCTION__); ++ goto exit; ++ } ++ mutex_lock(&_pno_state->pno_mutex); ++ _params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]; ++ if (buf && bufsize) { ++ if (!list_empty(&_params->params_batch.get_batch.expired_scan_results_list)) { ++ /* need to check whether we have cashed data or not */ ++ AP6210_DEBUG("%s: have cashed batching data in Driver\n", ++ __FUNCTION__); ++ /* convert to results format */ ++ goto convert_format; ++ } else { ++ /* this is a first try to get batching results */ ++ if (!list_empty(&_params->params_batch.get_batch.scan_results_list)) { ++ /* move the scan_results_list to expired_scan_results_lists */ ++ list_for_each_entry_safe(siter, snext, ++ &_params->params_batch.get_batch.scan_results_list, list) { ++ list_move_tail(&siter->list, ++ &_params->params_batch.get_batch.expired_scan_results_list); ++ } ++ _params->params_batch.get_batch.top_node_cnt = 0; ++ _params->params_batch.get_batch.expired_tot_scan_cnt = ++ _params->params_batch.get_batch.tot_scan_cnt; ++ _params->params_batch.get_batch.tot_scan_cnt = 0; ++ goto convert_format; ++ } ++ } ++ } ++ /* create dhd_pno_scan_results_t whenever we got event WLC_E_PFN_BEST_BATCHING */ ++ pscan_results = (dhd_pno_scan_results_t *)MALLOC(dhd->osh, SCAN_RESULTS_SIZE); ++ if (pscan_results == NULL) { ++ err = BCME_NOMEM; ++ AP6210_ERR("failed to allocate dhd_pno_scan_results_t\n"); ++ goto exit; ++ } ++ pscan_results->bestnetheader = NULL; ++ pscan_results->cnt_header = 0; ++ /* add the element into list unless total node cnt is less than MAX_NODE_ CNT */ ++ if (_params->params_batch.get_batch.top_node_cnt < MAX_NODE_CNT) { ++ list_add(&pscan_results->list, &_params->params_batch.get_batch.scan_results_list); ++ _params->params_batch.get_batch.top_node_cnt++; ++ } else { ++ int _removed_scan_cnt; ++ /* remove oldest one and add new one */ ++ AP6210_DEBUG("%s : Remove oldest node and add new one\n", __FUNCTION__); ++ _removed_scan_cnt = _dhd_pno_clear_all_batch_results(dhd, ++ &_params->params_batch.get_batch.scan_results_list, TRUE); ++ _params->params_batch.get_batch.tot_scan_cnt -= _removed_scan_cnt; ++ list_add(&pscan_results->list, &_params->params_batch.get_batch.scan_results_list); ++ ++ } ++ plbestnet = (wl_pfn_lscanresults_t *)MALLOC(dhd->osh, PNO_BESTNET_LEN); ++ NULL_CHECK(plbestnet, "failed to allocate buffer for bestnet", err); ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ memset(plbestnet, 0, PNO_BESTNET_LEN); ++ while (plbestnet->status != PFN_COMPLETE) { ++ memset(plbestnet, 0, PNO_BESTNET_LEN); ++ err = dhd_iovar(dhd, 0, "pfnlbest", (char *)plbestnet, PNO_BESTNET_LEN, 0); ++ if (err < 0) { ++ if (err == BCME_EPERM) { ++ AP6210_ERR("we cannot get the batching data " ++ "during scanning in firmware, try again\n,"); ++ msleep(500); ++ continue; ++ } else { ++ AP6210_ERR("%s : failed to execute pfnlbest (err :%d)\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ } ++ AP6210_DEBUG("ver %d, status : %d, count %d\n", plbestnet->version, ++ plbestnet->status, plbestnet->count); ++ if (plbestnet->version != PFN_SCANRESULT_VERSION) { ++ err = BCME_VERSION; ++ AP6210_ERR("bestnet version(%d) is mismatch with Driver version(%d)\n", ++ plbestnet->version, PFN_SCANRESULT_VERSION); ++ goto exit; ++ } ++ plnetinfo = plbestnet->netinfo; ++ for (i = 0; i < plbestnet->count; i++) { ++ pbestnet_entry = (dhd_pno_bestnet_entry_t *) ++ MALLOC(dhd->osh, BESTNET_ENTRY_SIZE); ++ if (pbestnet_entry == NULL) { ++ err = BCME_NOMEM; ++ AP6210_ERR("failed to allocate dhd_pno_bestnet_entry\n"); ++ goto exit; ++ } ++ pbestnet_entry->recorded_time = jiffies; /* record the current time */ ++ /* create header for the first entry */ ++ allocate_header = (i == 0)? TRUE : FALSE; ++ /* check whether the new generation is started or not */ ++ if (timestamp && (TIME_DIFF(timestamp, plnetinfo->timestamp) ++ > TIME_MIN_DIFF)) ++ allocate_header = TRUE; ++ timestamp = plnetinfo->timestamp; ++ if (allocate_header) { ++ pbestnetheader = (dhd_pno_best_header_t *) ++ MALLOC(dhd->osh, BEST_HEADER_SIZE); ++ if (pbestnetheader == NULL) { ++ err = BCME_NOMEM; ++ if (pbestnet_entry) ++ MFREE(dhd->osh, pbestnet_entry, ++ BESTNET_ENTRY_SIZE); ++ AP6210_ERR("failed to allocate dhd_pno_bestnet_entry\n"); ++ goto exit; ++ } ++ /* increase total cnt of bestnet header */ ++ pscan_results->cnt_header++; ++ /* need to record the reason to call dhd_pno_get_for_bach */ ++ if (reason) ++ pbestnetheader->reason = (ENABLE << reason); ++ memset(pbestnetheader, 0, BEST_HEADER_SIZE); ++ /* initialize the head of linked list */ ++ INIT_LIST_HEAD(&(pbestnetheader->entry_list)); ++ /* link the pbestnet heaer into existed list */ ++ if (pscan_results->bestnetheader == NULL) ++ /* In case of header */ ++ pscan_results->bestnetheader = pbestnetheader; ++ else { ++ dhd_pno_best_header_t *head = pscan_results->bestnetheader; ++ pscan_results->bestnetheader = pbestnetheader; ++ pbestnetheader->next = head; ++ } ++ } ++ /* fills the best network info */ ++ pbestnet_entry->channel = plnetinfo->pfnsubnet.channel; ++ pbestnet_entry->RSSI = plnetinfo->RSSI; ++ if (plnetinfo->flags & PFN_PARTIAL_SCAN_MASK) { ++ /* if RSSI is positive value, we assume that ++ * this scan is aborted by other scan ++ */ ++ AP6210_DEBUG("This scan is aborted\n"); ++ pbestnetheader->reason = (ENABLE << PNO_STATUS_ABORT); ++ } ++ pbestnet_entry->rtt0 = plnetinfo->rtt0; ++ pbestnet_entry->rtt1 = plnetinfo->rtt1; ++ pbestnet_entry->timestamp = plnetinfo->timestamp; ++ pbestnet_entry->SSID_len = plnetinfo->pfnsubnet.SSID_len; ++ memcpy(pbestnet_entry->SSID, plnetinfo->pfnsubnet.SSID, ++ pbestnet_entry->SSID_len); ++ memcpy(&pbestnet_entry->BSSID, &plnetinfo->pfnsubnet.BSSID, ETHER_ADDR_LEN); ++ /* add the element into list */ ++ list_add_tail(&pbestnet_entry->list, &pbestnetheader->entry_list); ++ /* increase best entry count */ ++ pbestnetheader->tot_cnt++; ++ pbestnetheader->tot_size += BESTNET_ENTRY_SIZE; ++ AP6210_DEBUG("Header %d\n", pscan_results->cnt_header - 1); ++ AP6210_DEBUG("\tSSID : "); ++ for (j = 0; j < plnetinfo->pfnsubnet.SSID_len; j++) ++ AP6210_DEBUG("%c", plnetinfo->pfnsubnet.SSID[j]); ++ AP6210_DEBUG("\n"); ++ AP6210_DEBUG("\tBSSID: %02x:%02x:%02x:%02x:%02x:%02x\n", ++ plnetinfo->pfnsubnet.BSSID.octet[0], ++ plnetinfo->pfnsubnet.BSSID.octet[1], ++ plnetinfo->pfnsubnet.BSSID.octet[2], ++ plnetinfo->pfnsubnet.BSSID.octet[3], ++ plnetinfo->pfnsubnet.BSSID.octet[4], ++ plnetinfo->pfnsubnet.BSSID.octet[5]); ++ AP6210_DEBUG("\tchannel: %d, RSSI: %d, timestamp: %d ms\n", ++ plnetinfo->pfnsubnet.channel, ++ plnetinfo->RSSI, plnetinfo->timestamp); ++ AP6210_DEBUG("\tRTT0 : %d, RTT1: %d\n", plnetinfo->rtt0, plnetinfo->rtt1); ++ plnetinfo++; ++ } ++ } ++ /* increase total scan count using current scan count */ ++ _params->params_batch.get_batch.tot_scan_cnt += pscan_results->cnt_header; ++ ++ if (buf && bufsize) { ++ /* This is a first try to get batching results */ ++ if (!list_empty(&_params->params_batch.get_batch.scan_results_list)) { ++ /* move the scan_results_list to expired_scan_results_lists */ ++ list_for_each_entry_safe(siter, snext, ++ &_params->params_batch.get_batch.scan_results_list, list) { ++ list_move_tail(&siter->list, ++ &_params->params_batch.get_batch.expired_scan_results_list); ++ } ++ /* reset gloval values after moving to expired list */ ++ _params->params_batch.get_batch.top_node_cnt = 0; ++ _params->params_batch.get_batch.expired_tot_scan_cnt = ++ _params->params_batch.get_batch.tot_scan_cnt; ++ _params->params_batch.get_batch.tot_scan_cnt = 0; ++ } ++convert_format: ++ err = _dhd_pno_convert_format(dhd, &_params->params_batch, buf, bufsize); ++ if (err < 0) { ++ AP6210_ERR("failed to convert the data into upper layer format\n"); ++ goto exit; ++ } ++ } ++exit: ++ if (plbestnet) ++ MFREE(dhd->osh, plbestnet, PNO_BESTNET_LEN); ++ _params->params_batch.get_batch.buf = NULL; ++ _params->params_batch.get_batch.bufsize = 0; ++ mutex_unlock(&_pno_state->pno_mutex); ++ complete(&_pno_state->get_batch_done); ++ return err; ++} ++static void ++_dhd_pno_get_batch_handler(struct work_struct *work) ++{ ++ dhd_pno_status_info_t *_pno_state; ++ dhd_pub_t *dhd; ++ struct dhd_pno_batch_params *params_batch; ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ _pno_state = container_of(work, struct dhd_pno_status_info, work); ++ dhd = _pno_state->dhd; ++ if (dhd == NULL) { ++ AP6210_ERR("%s : dhd is NULL\n", __FUNCTION__); ++ return; ++ } ++ params_batch = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS].params_batch; ++ _dhd_pno_get_for_batch(dhd, params_batch->get_batch.buf, ++ params_batch->get_batch.bufsize, params_batch->get_batch.reason); ++ ++} ++ ++int ++dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason) ++{ ++ int err = BCME_OK; ++ dhd_pno_status_info_t *_pno_state; ++ struct dhd_pno_batch_params *params_batch; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); ++ if (!dhd_support_sta_mode(dhd)) { ++ err = BCME_BADOPTION; ++ goto exit; ++ } ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ _pno_state = PNO_GET_PNOSTATE(dhd); ++ ++ if (!WLS_SUPPORTED(_pno_state)) { ++ AP6210_ERR("%s : wifi location service is not supported\n", __FUNCTION__); ++ err = BCME_UNSUPPORTED; ++ goto exit; ++ } ++ params_batch = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS].params_batch; ++ if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) { ++ AP6210_ERR("%s: Batching SCAN mode is not enabled\n", __FUNCTION__); ++ goto exit; ++ } ++ params_batch->get_batch.buf = buf; ++ params_batch->get_batch.bufsize = bufsize; ++ params_batch->get_batch.reason = reason; ++ schedule_work(&_pno_state->work); ++ wait_for_completion(&_pno_state->get_batch_done); ++exit: ++ return err; ++} ++ ++int ++dhd_pno_stop_for_batch(dhd_pub_t *dhd) ++{ ++ int err = BCME_OK; ++ int mode = 0; ++ int i = 0; ++ dhd_pno_status_info_t *_pno_state; ++ dhd_pno_params_t *_params; ++ wl_pfn_bssid_t *p_pfn_bssid; ++ wlc_ssid_t *p_ssid_list = NULL; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); ++ _pno_state = PNO_GET_PNOSTATE(dhd); ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ if (!dhd_support_sta_mode(dhd)) { ++ err = BCME_BADOPTION; ++ goto exit; ++ } ++ if (!WLS_SUPPORTED(_pno_state)) { ++ AP6210_ERR("%s : wifi location service is not supported\n", ++ __FUNCTION__); ++ err = BCME_UNSUPPORTED; ++ goto exit; ++ } ++ if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) { ++ AP6210_ERR("%s : PNO BATCH MODE is not enabled\n", __FUNCTION__); ++ goto exit; ++ } ++ _pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE; ++ if (_pno_state->pno_mode & (DHD_PNO_LEGACY_MODE | DHD_PNO_HOTLIST_MODE)) { ++ mode = _pno_state->pno_mode; ++ _dhd_pno_clean(dhd); ++ _pno_state->pno_mode = mode; ++ /* restart Legacy PNO if the Legacy PNO is on */ ++ if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) { ++ struct dhd_pno_legacy_params *_params_legacy; ++ struct dhd_pno_ssid *iter, *next; ++ _params_legacy = ++ &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy); ++ p_ssid_list = kzalloc(sizeof(wlc_ssid_t) * ++ _params_legacy->nssid, GFP_KERNEL); ++ if (p_ssid_list == NULL) { ++ AP6210_ERR("%s : failed to allocate wlc_ssid_t array (count: %d)", ++ __FUNCTION__, _params_legacy->nssid); ++ err = BCME_ERROR; ++ _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE; ++ goto exit; ++ } ++ i = 0; ++ /* convert dhd_pno_ssid to dhd_pno_ssid */ ++ list_for_each_entry_safe(iter, next, &_params_legacy->ssid_list, list) { ++ p_ssid_list[i].SSID_len = iter->SSID_len; ++ memcpy(p_ssid_list[i].SSID, iter->SSID, p_ssid_list[i].SSID_len); ++ i++; ++ } ++ err = dhd_pno_set_for_ssid(dhd, p_ssid_list, _params_legacy->nssid, ++ _params_legacy->scan_fr, _params_legacy->pno_repeat, ++ _params_legacy->pno_freq_expo_max, _params_legacy->chan_list, ++ _params_legacy->nchan); ++ if (err < 0) { ++ _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE; ++ AP6210_ERR("%s : failed to restart legacy PNO scan(err: %d)\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ } else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) { ++ struct dhd_pno_bssid *iter, *next; ++ _params = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]); ++ p_pfn_bssid = kzalloc(sizeof(wl_pfn_bssid_t) * ++ _params->params_hotlist.nbssid, GFP_KERNEL); ++ if (p_pfn_bssid == NULL) { ++ AP6210_ERR("%s : failed to allocate wl_pfn_bssid_t array" ++ " (count: %d)", ++ __FUNCTION__, _params->params_hotlist.nbssid); ++ err = BCME_ERROR; ++ _pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE; ++ goto exit; ++ } ++ i = 0; ++ /* convert dhd_pno_bssid to wl_pfn_bssid */ ++ list_for_each_entry_safe(iter, next, ++ &_params->params_hotlist.bssid_list, list) { ++ memcpy(&p_pfn_bssid[i].macaddr, &iter->macaddr, ETHER_ADDR_LEN); ++ p_pfn_bssid[i].flags = iter->flags; ++ i++; ++ } ++ err = dhd_pno_set_for_hotlist(dhd, p_pfn_bssid, &_params->params_hotlist); ++ if (err < 0) { ++ _pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE; ++ AP6210_ERR("%s : failed to restart hotlist scan(err: %d)\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ } ++ } else { ++ err = _dhd_pno_clean(dhd); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to call _dhd_pno_clean (err: %d)\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ } ++exit: ++ _params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]; ++ _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_BATCH_MODE); ++ if (p_ssid_list) ++ kfree(p_ssid_list); ++ return err; ++} ++ ++int ++dhd_pno_set_for_hotlist(dhd_pub_t *dhd, wl_pfn_bssid_t *p_pfn_bssid, ++ struct dhd_pno_hotlist_params *hotlist_params) ++{ ++ int err = BCME_OK; ++ int i; ++ uint16 _chan_list[WL_NUMCHANNELS]; ++ int rem_nchan = 0; ++ int tot_nchan = 0; ++ int mode = 0; ++ dhd_pno_params_t *_params; ++ dhd_pno_params_t *_params2; ++ struct dhd_pno_bssid *_pno_bssid; ++ dhd_pno_status_info_t *_pno_state; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); ++ NULL_CHECK(hotlist_params, "hotlist_params is NULL", err); ++ NULL_CHECK(p_pfn_bssid, "p_pfn_bssid is NULL", err); ++ _pno_state = PNO_GET_PNOSTATE(dhd); ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ ++ if (!dhd_support_sta_mode(dhd)) { ++ err = BCME_BADOPTION; ++ goto exit; ++ } ++ if (!WLS_SUPPORTED(_pno_state)) { ++ AP6210_ERR("%s : wifi location service is not supported\n", __FUNCTION__); ++ err = BCME_UNSUPPORTED; ++ goto exit; ++ } ++ _params = &_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]; ++ if (!(_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE)) { ++ _pno_state->pno_mode |= DHD_PNO_HOTLIST_MODE; ++ err = _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_HOTLIST_MODE); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to call _dhd_pno_reinitialize_prof\n", ++ __FUNCTION__); ++ goto exit; ++ } ++ } ++ _params->params_batch.nchan = hotlist_params->nchan; ++ _params->params_batch.scan_fr = hotlist_params->scan_fr; ++ if (hotlist_params->nchan) ++ memcpy(_params->params_hotlist.chan_list, hotlist_params->chan_list, ++ sizeof(_params->params_hotlist.chan_list)); ++ memset(_chan_list, 0, sizeof(_chan_list)); ++ ++ rem_nchan = ARRAYSIZE(hotlist_params->chan_list) - hotlist_params->nchan; ++ if (hotlist_params->band == WLC_BAND_2G || hotlist_params->band == WLC_BAND_5G) { ++ /* get a valid channel list based on band B or A */ ++ err = _dhd_pno_get_channels(dhd, ++ &_params->params_hotlist.chan_list[hotlist_params->nchan], ++ &rem_nchan, hotlist_params->band, FALSE); ++ if (err < 0) { ++ AP6210_ERR("%s: failed to get valid channel list(band : %d)\n", ++ __FUNCTION__, hotlist_params->band); ++ goto exit; ++ } ++ /* now we need to update nchan because rem_chan has valid channel count */ ++ _params->params_hotlist.nchan += rem_nchan; ++ /* need to sort channel list */ ++ sort(_params->params_hotlist.chan_list, _params->params_hotlist.nchan, ++ sizeof(_params->params_hotlist.chan_list[0]), _dhd_pno_cmpfunc, NULL); ++ } ++#ifdef PNO_DEBUG ++{ ++ int i; ++ AP6210_DEBUG("Channel list : "); ++ for (i = 0; i < _params->params_batch.nchan; i++) { ++ AP6210_DEBUG("%d ", _params->params_batch.chan_list[i]); ++ } ++ AP6210_DEBUG("\n"); ++} ++#endif ++ if (_params->params_hotlist.nchan) { ++ /* copy the channel list into local array */ ++ memcpy(_chan_list, _params->params_hotlist.chan_list, ++ sizeof(_chan_list)); ++ tot_nchan = _params->params_hotlist.nchan; ++ } ++ if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) { ++ AP6210_DEBUG("PNO SSID is on progress in firmware\n"); ++ /* store current pno_mode before disabling pno */ ++ mode = _pno_state->pno_mode; ++ err = _dhd_pno_enable(dhd, PNO_OFF); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to disable PNO\n", __FUNCTION__); ++ goto exit; ++ } ++ /* restore the previous mode */ ++ _pno_state->pno_mode = mode; ++ /* Use the superset for channelist between two mode */ ++ _params2 = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]); ++ if (_params2->params_legacy.nchan > 0 && ++ _params->params_hotlist.nchan > 0) { ++ err = _dhd_pno_chan_merge(_chan_list, &tot_nchan, ++ &_params2->params_legacy.chan_list[0], ++ _params2->params_legacy.nchan, ++ &_params->params_hotlist.chan_list[0], ++ _params->params_hotlist.nchan); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to merge channel list" ++ "between legacy and hotlist\n", ++ __FUNCTION__); ++ goto exit; ++ } ++ } ++ ++ } ++ ++ INIT_LIST_HEAD(&(_params->params_hotlist.bssid_list)); ++ ++ err = _dhd_pno_add_bssid(dhd, p_pfn_bssid, hotlist_params->nbssid); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to call _dhd_pno_add_bssid(err :%d)\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ if ((err = _dhd_pno_set(dhd, _params, DHD_PNO_HOTLIST_MODE)) < 0) { ++ AP6210_ERR("%s : failed to set call pno_set (err %d) in firmware\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ if (tot_nchan > 0) { ++ if ((err = _dhd_pno_cfg(dhd, _chan_list, tot_nchan)) < 0) { ++ AP6210_ERR("%s : failed to set call pno_cfg (err %d) in firmware\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ } ++ for (i = 0; i < hotlist_params->nbssid; i++) { ++ _pno_bssid = kzalloc(sizeof(struct dhd_pno_bssid), GFP_KERNEL); ++ NULL_CHECK(_pno_bssid, "_pfn_bssid is NULL", err); ++ memcpy(&_pno_bssid->macaddr, &p_pfn_bssid[i].macaddr, ETHER_ADDR_LEN); ++ _pno_bssid->flags = p_pfn_bssid[i].flags; ++ list_add_tail(&_pno_bssid->list, &_params->params_hotlist.bssid_list); ++ } ++ _params->params_hotlist.nbssid = hotlist_params->nbssid; ++ if (_pno_state->pno_status == DHD_PNO_DISABLED) { ++ if ((err = _dhd_pno_enable(dhd, PNO_ON)) < 0) ++ AP6210_ERR("%s : failed to enable PNO\n", __FUNCTION__); ++ } ++exit: ++ /* clear mode in case of error */ ++ if (err < 0) ++ _pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE; ++ return err; ++} ++ ++int ++dhd_pno_stop_for_hotlist(dhd_pub_t *dhd) ++{ ++ int err = BCME_OK; ++ uint32 mode = 0; ++ dhd_pno_status_info_t *_pno_state; ++ dhd_pno_params_t *_params; ++ wlc_ssid_t *p_ssid_list; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); ++ _pno_state = PNO_GET_PNOSTATE(dhd); ++ ++ if (!WLS_SUPPORTED(_pno_state)) { ++ AP6210_ERR("%s : wifi location service is not supported\n", ++ __FUNCTION__); ++ err = BCME_UNSUPPORTED; ++ goto exit; ++ } ++ ++ if (!(_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE)) { ++ AP6210_ERR("%s : Hotlist MODE is not enabled\n", ++ __FUNCTION__); ++ goto exit; ++ } ++ _pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE; ++ ++ if (_pno_state->pno_mode & (DHD_PNO_LEGACY_MODE | DHD_PNO_BATCH_MODE)) { ++ /* retrieve the batching data from firmware into host */ ++ dhd_pno_get_for_batch(dhd, NULL, 0, PNO_STATUS_DISABLE); ++ /* save current pno_mode before calling dhd_pno_clean */ ++ mode = _pno_state->pno_mode; ++ err = _dhd_pno_clean(dhd); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to call _dhd_pno_clean (err: %d)\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ /* restore previos pno mode */ ++ _pno_state->pno_mode = mode; ++ if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) { ++ /* restart Legacy PNO Scan */ ++ struct dhd_pno_legacy_params *_params_legacy; ++ struct dhd_pno_ssid *iter, *next; ++ _params_legacy = ++ &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy); ++ p_ssid_list = ++ kzalloc(sizeof(wlc_ssid_t) * _params_legacy->nssid, GFP_KERNEL); ++ if (p_ssid_list == NULL) { ++ AP6210_ERR("%s : failed to allocate wlc_ssid_t array (count: %d)", ++ __FUNCTION__, _params_legacy->nssid); ++ err = BCME_ERROR; ++ _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE; ++ goto exit; ++ } ++ /* convert dhd_pno_ssid to dhd_pno_ssid */ ++ list_for_each_entry_safe(iter, next, &_params_legacy->ssid_list, list) { ++ p_ssid_list->SSID_len = iter->SSID_len; ++ memcpy(p_ssid_list->SSID, iter->SSID, p_ssid_list->SSID_len); ++ p_ssid_list++; ++ } ++ err = dhd_pno_set_for_ssid(dhd, p_ssid_list, _params_legacy->nssid, ++ _params_legacy->scan_fr, _params_legacy->pno_repeat, ++ _params_legacy->pno_freq_expo_max, _params_legacy->chan_list, ++ _params_legacy->nchan); ++ if (err < 0) { ++ _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE; ++ AP6210_ERR("%s : failed to restart legacy PNO scan(err: %d)\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ } else if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) { ++ /* restart Batching Scan */ ++ _params = &(_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]); ++ /* restart BATCH SCAN */ ++ err = dhd_pno_set_for_batch(dhd, &_params->params_batch); ++ if (err < 0) { ++ _pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE; ++ AP6210_ERR("%s : failed to restart batch scan(err: %d)\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ } ++ } else { ++ err = _dhd_pno_clean(dhd); ++ if (err < 0) { ++ AP6210_ERR("%s : failed to call _dhd_pno_clean (err: %d)\n", ++ __FUNCTION__, err); ++ goto exit; ++ } ++ } ++exit: ++ return err; ++} ++ ++int ++dhd_pno_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data) ++{ ++ int err = BCME_OK; ++ uint status, event_type, flags, datalen; ++ dhd_pno_status_info_t *_pno_state; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); ++ _pno_state = PNO_GET_PNOSTATE(dhd); ++ if (!WLS_SUPPORTED(_pno_state)) { ++ AP6210_ERR("%s : wifi location service is not supported\n", __FUNCTION__); ++ err = BCME_UNSUPPORTED; ++ goto exit; ++ } ++ event_type = ntoh32(event->event_type); ++ flags = ntoh16(event->flags); ++ status = ntoh32(event->status); ++ datalen = ntoh32(event->datalen); ++ AP6210_DEBUG("%s enter : event_type :%d\n", __FUNCTION__, event_type); ++ switch (event_type) { ++ case WLC_E_PFN_BSSID_NET_FOUND: ++ case WLC_E_PFN_BSSID_NET_LOST: ++ /* XXX : how can we inform this to framework ? */ ++ /* TODO : need to implement event logic using generic netlink */ ++ break; ++ case WLC_E_PFN_BEST_BATCHING: ++ { ++ struct dhd_pno_batch_params *params_batch; ++ params_batch = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS].params_batch; ++ AP6210_DEBUG("%s : WLC_E_PFN_BEST_BATCHING\n", __FUNCTION__); ++ params_batch->get_batch.buf = NULL; ++ params_batch->get_batch.bufsize = 0; ++ params_batch->get_batch.reason = PNO_STATUS_EVENT; ++ schedule_work(&_pno_state->work); ++ break; ++ } ++ default: ++ AP6210_ERR("unknown event : %d\n", event_type); ++ } ++exit: ++ return err; ++} ++ ++int dhd_pno_init(dhd_pub_t *dhd) ++{ ++ int err = BCME_OK; ++ dhd_pno_status_info_t *_pno_state; ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ UNUSED_PARAMETER(_dhd_pno_suspend); ++ if (dhd->pno_state) ++ goto exit; ++ dhd->pno_state = MALLOC(dhd->osh, sizeof(dhd_pno_status_info_t)); ++ memset(dhd->pno_state, 0, sizeof(dhd_pno_status_info_t)); ++ NULL_CHECK(dhd, "failed to create dhd_pno_state", err); ++ /* need to check whether current firmware support batching and hotlist scan */ ++ _pno_state = PNO_GET_PNOSTATE(dhd); ++ _pno_state->wls_supported = TRUE; ++ _pno_state->dhd = dhd; ++ mutex_init(&_pno_state->pno_mutex); ++ INIT_WORK(&_pno_state->work, _dhd_pno_get_batch_handler); ++ init_completion(&_pno_state->get_batch_done); ++ err = dhd_iovar(dhd, 0, "pfnlbest", NULL, 0, 0); ++ if (err == BCME_UNSUPPORTED) { ++ _pno_state->wls_supported = FALSE; ++ AP6210_DEBUG("Current firmware doesn't support" ++ " Android Location Service\n"); ++ } ++exit: ++ return err; ++} ++int dhd_pno_deinit(dhd_pub_t *dhd) ++{ ++ int err = BCME_OK; ++ dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd); ++ NULL_CHECK(dhd, "dhd is NULL", err); ++ AP6210_DEBUG("%s enter\n", __FUNCTION__); ++ cancel_work_sync(&_pno_state->work); ++ if (dhd->pno_state) ++ MFREE(dhd->osh, dhd->pno_state, sizeof(dhd_pno_status_info_t)); ++ dhd->pno_state = NULL; ++ return err; ++} +diff --git a/drivers/net/wireless/ap6210/dhd_pno.h b/drivers/net/wireless/ap6210/dhd_pno.h +new file mode 100755 +index 0000000..1e02db1 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_pno.h +@@ -0,0 +1,249 @@ ++/* ++ * Header file of Broadcom Dongle Host Driver (DHD) ++ * Prefered Network Offload code and Wi-Fi Location Service(WLS) code. ++ * Copyright (C) 1999-2013, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhd_pno.h 419969 2013-08-23 18:54:36Z $ ++ */ ++ ++#ifndef __DHD_PNO_H__ ++#define __DHD_PNO_H__ ++ ++#define PNO_TLV_PREFIX 'S' ++#define PNO_TLV_VERSION '1' ++#define PNO_TLV_SUBTYPE_LEGACY_PNO '2' ++#define PNO_TLV_RESERVED '0' ++ ++#define PNO_BATCHING_SET "SET" ++#define PNO_BATCHING_GET "GET" ++#define PNO_BATCHING_STOP "STOP" ++ ++#define PNO_PARAMS_DELIMETER " " ++#define PNO_PARAM_CHANNEL_DELIMETER "," ++#define PNO_PARAM_VALUE_DELLIMETER '=' ++#define PNO_PARAM_SCANFREQ "SCANFREQ" ++#define PNO_PARAM_BESTN "BESTN" ++#define PNO_PARAM_MSCAN "MSCAN" ++#define PNO_PARAM_CHANNEL "CHANNEL" ++#define PNO_PARAM_RTT "RTT" ++ ++#define PNO_TLV_TYPE_SSID_IE 'S' ++#define PNO_TLV_TYPE_TIME 'T' ++#define PNO_TLV_FREQ_REPEAT 'R' ++#define PNO_TLV_FREQ_EXPO_MAX 'M' ++ ++#define MAXNUM_SSID_PER_ADD 16 ++#define MAXNUM_PNO_PARAMS 2 ++#define PNO_TLV_COMMON_LENGTH 1 ++#define DEFAULT_BATCH_MSCAN 16 ++ ++#define RESULTS_END_MARKER "----\n" ++#define SCAN_END_MARKER "####\n" ++#define AP_END_MARKER "====\n" ++ ++enum scan_status { ++ /* SCAN ABORT by other scan */ ++ PNO_STATUS_ABORT, ++ /* RTT is presence or not */ ++ PNO_STATUS_RTT_PRESENCE, ++ /* Disable PNO by Driver */ ++ PNO_STATUS_DISABLE, ++ /* NORMAL BATCHING GET */ ++ PNO_STATUS_NORMAL, ++ /* WLC_E_PFN_BEST_BATCHING */ ++ PNO_STATUS_EVENT, ++ PNO_STATUS_MAX ++}; ++#define PNO_STATUS_ABORT_MASK 0x0001 ++#define PNO_STATUS_RTT_MASK 0x0002 ++#define PNO_STATUS_DISABLE_MASK 0x0004 ++#define PNO_STATUS_OOM_MASK 0x0010 ++ ++enum index_mode { ++ INDEX_OF_LEGACY_PARAMS, ++ INDEX_OF_BATCH_PARAMS, ++ INDEX_OF_HOTLIST_PARAMS, ++ INDEX_MODE_MAX ++}; ++enum dhd_pno_status { ++ DHD_PNO_DISABLED, ++ DHD_PNO_ENABLED, ++ DHD_PNO_SUSPEND ++}; ++typedef struct cmd_tlv { ++ char prefix; ++ char version; ++ char subtype; ++ char reserved; ++} cmd_tlv_t; ++typedef enum dhd_pno_mode { ++ /* Wi-Fi Legacy PNO Mode */ ++ DHD_PNO_NONE_MODE = 0, ++ DHD_PNO_LEGACY_MODE = (1 << (0)), ++ /* Wi-Fi Android BATCH SCAN Mode */ ++ DHD_PNO_BATCH_MODE = (1 << (1)), ++ /* Wi-Fi Android Hotlist SCAN Mode */ ++ DHD_PNO_HOTLIST_MODE = (1 << (2)) ++} dhd_pno_mode_t; ++struct dhd_pno_ssid { ++ uint32 SSID_len; ++ uchar SSID[DOT11_MAX_SSID_LEN]; ++ struct list_head list; ++}; ++struct dhd_pno_bssid { ++ struct ether_addr macaddr; ++ /* Bit4: suppress_lost, Bit3: suppress_found */ ++ uint16 flags; ++ struct list_head list; ++}; ++typedef struct dhd_pno_bestnet_entry { ++ struct ether_addr BSSID; ++ uint8 SSID_len; ++ uint8 SSID[DOT11_MAX_SSID_LEN]; ++ int8 RSSI; ++ uint8 channel; ++ uint32 timestamp; ++ uint16 rtt0; /* distance_cm based on RTT */ ++ uint16 rtt1; /* distance_cm based on sample standard deviation */ ++ unsigned long recorded_time; ++ struct list_head list; ++} dhd_pno_bestnet_entry_t; ++#define BESTNET_ENTRY_SIZE (sizeof(dhd_pno_bestnet_entry_t)) ++ ++typedef struct dhd_pno_bestnet_header { ++ struct dhd_pno_bestnet_header *next; ++ uint8 reason; ++ uint32 tot_cnt; ++ uint32 tot_size; ++ struct list_head entry_list; ++} dhd_pno_best_header_t; ++#define BEST_HEADER_SIZE (sizeof(dhd_pno_best_header_t)) ++ ++typedef struct dhd_pno_scan_results { ++ dhd_pno_best_header_t *bestnetheader; ++ uint8 cnt_header; ++ struct list_head list; ++} dhd_pno_scan_results_t; ++#define SCAN_RESULTS_SIZE (sizeof(dhd_pno_scan_results_t)) ++ ++struct dhd_pno_get_batch_info { ++ /* info related to get batch */ ++ char *buf; ++ bool batch_started; ++ uint32 tot_scan_cnt; ++ uint32 expired_tot_scan_cnt; ++ uint32 top_node_cnt; ++ uint32 bufsize; ++ int reason; ++ struct list_head scan_results_list; ++ struct list_head expired_scan_results_list; ++}; ++struct dhd_pno_legacy_params { ++ uint16 scan_fr; ++ uint16 chan_list[WL_NUMCHANNELS]; ++ uint16 nchan; ++ int pno_repeat; ++ int pno_freq_expo_max; ++ int nssid; ++ struct list_head ssid_list; ++}; ++struct dhd_pno_batch_params { ++ int32 scan_fr; ++ uint8 bestn; ++ uint8 mscan; ++ uint8 band; ++ uint16 chan_list[WL_NUMCHANNELS]; ++ uint16 nchan; ++ uint16 rtt; ++ struct dhd_pno_get_batch_info get_batch; ++}; ++struct dhd_pno_hotlist_params { ++ uint8 band; ++ int32 scan_fr; ++ uint16 chan_list[WL_NUMCHANNELS]; ++ uint16 nchan; ++ uint16 nbssid; ++ struct list_head bssid_list; ++}; ++typedef union dhd_pno_params { ++ struct dhd_pno_legacy_params params_legacy; ++ struct dhd_pno_batch_params params_batch; ++ struct dhd_pno_hotlist_params params_hotlist; ++} dhd_pno_params_t; ++typedef struct dhd_pno_status_info { ++ dhd_pub_t *dhd; ++ struct work_struct work; ++ struct mutex pno_mutex; ++ struct completion get_batch_done; ++ bool wls_supported; /* wifi location service supported or not */ ++ enum dhd_pno_status pno_status; ++ enum dhd_pno_mode pno_mode; ++ dhd_pno_params_t pno_params_arr[INDEX_MODE_MAX]; ++ struct list_head head_list; ++} dhd_pno_status_info_t; ++ ++/* wrapper functions */ ++extern int ++dhd_dev_pno_enable(struct net_device *dev, int enable); ++ ++extern int ++dhd_dev_pno_stop_for_ssid(struct net_device *dev); ++ ++extern int ++dhd_dev_pno_set_for_ssid(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, ++ uint16 scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan); ++ ++extern int ++dhd_dev_pno_set_for_batch(struct net_device *dev, ++ struct dhd_pno_batch_params *batch_params); ++ ++extern int ++dhd_dev_pno_get_for_batch(struct net_device *dev, char *buf, int bufsize); ++ ++extern int ++dhd_dev_pno_stop_for_batch(struct net_device *dev); ++ ++extern int ++dhd_dev_pno_set_for_hotlist(struct net_device *dev, wl_pfn_bssid_t *p_pfn_bssid, ++ struct dhd_pno_hotlist_params *hotlist_params); ++ ++/* dhd pno fuctions */ ++extern int dhd_pno_stop_for_ssid(dhd_pub_t *dhd); ++extern int dhd_pno_enable(dhd_pub_t *dhd, int enable); ++extern int dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid, ++ uint16 scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan); ++ ++extern int dhd_pno_set_for_batch(dhd_pub_t *dhd, struct dhd_pno_batch_params *batch_params); ++ ++extern int dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason); ++ ++ ++extern int dhd_pno_stop_for_batch(dhd_pub_t *dhd); ++ ++extern int dhd_pno_set_for_hotlist(dhd_pub_t *dhd, wl_pfn_bssid_t *p_pfn_bssid, ++ struct dhd_pno_hotlist_params *hotlist_params); ++ ++extern int dhd_pno_stop_for_hotlist(dhd_pub_t *dhd); ++ ++extern int dhd_pno_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data); ++extern int dhd_pno_init(dhd_pub_t *dhd); ++extern int dhd_pno_deinit(dhd_pub_t *dhd); ++#endif /* __DHD_PNO_H__ */ +diff --git a/drivers/net/wireless/ap6210/dhd_proto.h b/drivers/net/wireless/ap6210/dhd_proto.h +new file mode 100755 +index 0000000..09d5468 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_proto.h +@@ -0,0 +1,113 @@ ++/* ++ * Header file describing the internal (inter-module) DHD interfaces. ++ * ++ * Provides type definitions and function prototypes used to link the ++ * DHD OS, bus, and protocol modules. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhd_proto.h 343390 2012-07-06 22:34:19Z $ ++ */ ++ ++#ifndef _dhd_proto_h_ ++#define _dhd_proto_h_ ++ ++#include ++#include ++ ++#ifndef IOCTL_RESP_TIMEOUT ++#define IOCTL_RESP_TIMEOUT 2000 /* In milli second default value for Production FW */ ++#endif /* IOCTL_RESP_TIMEOUT */ ++ ++/* ++ * Exported from the dhd protocol module (dhd_cdc, dhd_rndis) ++ */ ++ ++/* Linkage, sets prot link and updates hdrlen in pub */ ++extern int dhd_prot_attach(dhd_pub_t *dhdp); ++ ++/* Unlink, frees allocated protocol memory (including dhd_prot) */ ++extern void dhd_prot_detach(dhd_pub_t *dhdp); ++ ++/* Initialize protocol: sync w/dongle state. ++ * Sets dongle media info (iswl, drv_version, mac address). ++ */ ++extern int dhd_prot_init(dhd_pub_t *dhdp); ++ ++/* Stop protocol: sync w/dongle state. */ ++extern void dhd_prot_stop(dhd_pub_t *dhdp); ++#ifdef PROP_TXSTATUS ++extern int dhd_wlfc_init(dhd_pub_t *dhd); ++extern void dhd_wlfc_deinit(dhd_pub_t *dhd); ++#endif /* PROP_TXSTATUS */ ++ ++/* Add any protocol-specific data header. ++ * Caller must reserve prot_hdrlen prepend space. ++ */ ++extern void dhd_prot_hdrpush(dhd_pub_t *, int ifidx, void *txp); ++ ++/* Remove any protocol-specific data header. */ ++extern int dhd_prot_hdrpull(dhd_pub_t *, int *ifidx, void *rxp, uchar *buf, uint *len); ++ ++/* Use protocol to issue ioctl to dongle */ ++extern int dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len); ++ ++/* Handles a protocol control response asynchronously */ ++extern int dhd_prot_ctl_complete(dhd_pub_t *dhd); ++ ++/* Check for and handle local prot-specific iovar commands */ ++extern int dhd_prot_iovar_op(dhd_pub_t *dhdp, const char *name, ++ void *params, int plen, void *arg, int len, bool set); ++ ++/* Add prot dump output to a buffer */ ++extern void dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf); ++ ++/* Update local copy of dongle statistics */ ++extern void dhd_prot_dstats(dhd_pub_t *dhdp); ++ ++extern int dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void * buf, uint buflen); ++ ++extern int dhd_preinit_ioctls(dhd_pub_t *dhd); ++ ++#ifdef PROP_TXSTATUS ++extern int dhd_wlfc_enque_sendq(void* state, int prec, void* p); ++extern int dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx); ++extern void dhd_wlfc_cleanup(dhd_pub_t *dhd); ++#endif /* PROP_TXSTATUS */ ++ ++extern int dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, ++ uint reorder_info_len, void **pkt, uint32 *free_buf_count); ++ ++ ++/******************************** ++ * For version-string expansion * ++ */ ++#if defined(BDC) ++#define DHD_PROTOCOL "bdc" ++#elif defined(CDC) ++#define DHD_PROTOCOL "cdc" ++#elif defined(RNDIS) ++#define DHD_PROTOCOL "rndis" ++#else ++#define DHD_PROTOCOL "unknown" ++#endif /* proto */ ++ ++#endif /* _dhd_proto_h_ */ +diff --git a/drivers/net/wireless/ap6210/dhd_sdio.c b/drivers/net/wireless/ap6210/dhd_sdio.c +new file mode 100755 +index 0000000..786f287 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_sdio.c +@@ -0,0 +1,7856 @@ ++/* ++ * DHD Bus Module for SDIO ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhd_sdio.c 373330 2012-12-07 04:46:17Z $ ++ */ ++ ++#include ++#include ++#include ++ ++#ifdef BCMEMBEDIMAGE ++#include BCMEMBEDIMAGE ++#endif /* BCMEMBEDIMAGE */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#if defined(DHD_DEBUG) ++#include ++#include ++#endif /* defined(DHD_DEBUG) */ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#ifndef DHDSDIO_MEM_DUMP_FNAME ++#define DHDSDIO_MEM_DUMP_FNAME "mem_dump" ++#endif ++ ++#define QLEN 256 /* bulk rx and tx queue lengths */ ++#define FCHI (QLEN - 10) ++#define FCLOW (FCHI / 2) ++#define PRIOMASK 7 ++ ++#define TXRETRIES 2 /* # of retries for tx frames */ ++ ++#define DHD_RXBOUND 50 /* Default for max rx frames in one scheduling */ ++ ++#define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */ ++ ++#define DHD_TXMINMAX 1 /* Max tx frames if rx still pending */ ++ ++#define MEMBLOCK 2048 /* Block size used for downloading of dongle image */ ++#define MAX_NVRAMBUF_SIZE 4096 /* max nvram buf size */ ++#define MAX_DATA_BUF (32 * 1024) /* Must be large enough to hold biggest possible glom */ ++ ++#ifndef DHD_FIRSTREAD ++#define DHD_FIRSTREAD 32 ++#endif ++#if !ISPOWEROF2(DHD_FIRSTREAD) ++#error DHD_FIRSTREAD is not a power of 2! ++#endif ++ ++#ifdef BCMSDIOH_TXGLOM ++/* Total length of TX frame header for dongle protocol */ ++#define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_HWEXT_LEN + SDPCM_SWHEADER_LEN) ++/* Total length of RX frame for dongle protocol */ ++#else ++/* Total length of TX frame header for dongle protocol */ ++#define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN) ++#endif ++ ++#define SDPCM_HDRLEN_RX (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN) ++ ++#ifdef SDTEST ++#define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN) ++#else ++#define SDPCM_RESERVE (SDPCM_HDRLEN + DHD_SDALIGN) ++#endif ++ ++/* Space for header read, limit for data packets */ ++#ifndef MAX_HDR_READ ++#define MAX_HDR_READ 32 ++#endif ++#if !ISPOWEROF2(MAX_HDR_READ) ++#error MAX_HDR_READ is not a power of 2! ++#endif ++ ++#define MAX_RX_DATASZ 2048 ++ ++/* Maximum milliseconds to wait for F2 to come up */ ++#define DHD_WAIT_F2RDY 3000 ++ ++/* Bump up limit on waiting for HT to account for first startup; ++ * if the image is doing a CRC calculation before programming the PMU ++ * for HT availability, it could take a couple hundred ms more, so ++ * max out at a 1 second (1000000us). ++ */ ++#if (PMU_MAX_TRANSITION_DLY <= 1000000) ++#undef PMU_MAX_TRANSITION_DLY ++#define PMU_MAX_TRANSITION_DLY 1000000 ++#endif ++ ++/* Value for ChipClockCSR during initial setup */ ++#define DHD_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ) ++#define DHD_INIT_CLKCTL2 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP) ++ ++/* Flags for SDH calls */ ++#define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED) ++ ++/* Packet free applicable unconditionally for sdio and sdspi. Conditional if ++ * bufpool was present for gspi bus. ++ */ ++#define PKTFREE2() if ((bus->bus != SPI_BUS) || bus->usebufpool) \ ++ PKTFREE(bus->dhd->osh, pkt, FALSE); ++DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep); ++#if defined(OOB_INTR_ONLY) ++extern void bcmsdh_set_irq(int flag); ++#endif ++#ifdef PROP_TXSTATUS ++extern void dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success, bool wlfc_locked); ++extern void dhd_wlfc_trigger_pktcommit(dhd_pub_t *dhd); ++#endif ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++DEFINE_MUTEX(_dhd_sdio_mutex_lock_); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ ++ ++#ifdef DHD_DEBUG ++/* Device console log buffer state */ ++#define CONSOLE_LINE_MAX 192 ++#define CONSOLE_BUFFER_MAX 2024 ++typedef struct dhd_console { ++ uint count; /* Poll interval msec counter */ ++ uint log_addr; /* Log struct address (fixed) */ ++ hndrte_log_t log; /* Log struct (host copy) */ ++ uint bufsize; /* Size of log buffer */ ++ uint8 *buf; /* Log buffer (host copy) */ ++ uint last; /* Last buffer read index */ ++} dhd_console_t; ++#endif /* DHD_DEBUG */ ++ ++#define REMAP_ENAB(bus) ((bus)->remap) ++#define REMAP_ISADDR(bus, a) (((a) >= ((bus)->orig_ramsize)) && ((a) < ((bus)->ramsize))) ++#define KSO_ENAB(bus) ((bus)->kso) ++#define SR_ENAB(bus) ((bus)->_srenab) ++#define SLPAUTO_ENAB(bus) ((SR_ENAB(bus)) && ((bus)->_slpauto)) ++#define MIN_RSRC_ADDR (SI_ENUM_BASE + 0x618) ++#define MIN_RSRC_SR 0x3 ++#define CORE_CAPEXT_ADDR (SI_ENUM_BASE + 0x64c) ++#define CORE_CAPEXT_SR_SUPPORTED_MASK (1 << 1) ++#define RCTL_MACPHY_DISABLE_MASK (1 << 26) ++#define RCTL_LOGIC_DISABLE_MASK (1 << 27) ++ ++#define OOB_WAKEUP_ENAB(bus) ((bus)->_oobwakeup) ++#define GPIO_DEV_SRSTATE 16 /* Host gpio17 mapped to device gpio0 SR state */ ++#define GPIO_DEV_SRSTATE_TIMEOUT 320000 /* 320ms */ ++#define GPIO_DEV_WAKEUP 17 /* Host gpio17 mapped to device gpio1 wakeup */ ++#define CC_CHIPCTRL2_GPIO1_WAKEUP (1 << 0) ++ ++#define CC_PMUCC3 (0x3) ++/* Private data for SDIO bus interaction */ ++typedef struct dhd_bus { ++ dhd_pub_t *dhd; ++ ++ bcmsdh_info_t *sdh; /* Handle for BCMSDH calls */ ++ si_t *sih; /* Handle for SI calls */ ++ char *vars; /* Variables (from CIS and/or other) */ ++ uint varsz; /* Size of variables buffer */ ++ uint32 sbaddr; /* Current SB window pointer (-1, invalid) */ ++ ++ sdpcmd_regs_t *regs; /* Registers for SDIO core */ ++ uint sdpcmrev; /* SDIO core revision */ ++ uint armrev; /* CPU core revision */ ++ uint ramrev; /* SOCRAM core revision */ ++ uint32 ramsize; /* Size of RAM in SOCRAM (bytes) */ ++ uint32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */ ++ uint32 srmemsize; /* Size of SRMEM */ ++ ++ uint32 bus; /* gSPI or SDIO bus */ ++ uint32 hostintmask; /* Copy of Host Interrupt Mask */ ++ uint32 intstatus; /* Intstatus bits (events) pending */ ++ bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */ ++ bool fcstate; /* State of dongle flow-control */ ++ ++ uint16 cl_devid; /* cached devid for dhdsdio_probe_attach() */ ++ char *fw_path; /* module_param: path to firmware image */ ++ char *nv_path; /* module_param: path to nvram vars file */ ++ const char *nvram_params; /* user specified nvram params. */ ++ ++ uint blocksize; /* Block size of SDIO transfers */ ++ uint roundup; /* Max roundup limit */ ++ ++ struct pktq txq; /* Queue length used for flow-control */ ++ uint8 flowcontrol; /* per prio flow control bitmask */ ++ uint8 tx_seq; /* Transmit sequence number (next) */ ++ uint8 tx_max; /* Maximum transmit sequence allowed */ ++ ++ uint8 hdrbuf[MAX_HDR_READ + DHD_SDALIGN]; ++ uint8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ ++ uint16 nextlen; /* Next Read Len from last header */ ++ uint8 rx_seq; /* Receive sequence number (expected) */ ++ bool rxskip; /* Skip receive (awaiting NAK ACK) */ ++ ++ void *glomd; /* Packet containing glomming descriptor */ ++ void *glom; /* Packet chain for glommed superframe */ ++ uint glomerr; /* Glom packet read errors */ ++ ++ uint8 *rxbuf; /* Buffer for receiving control packets */ ++ uint rxblen; /* Allocated length of rxbuf */ ++ uint8 *rxctl; /* Aligned pointer into rxbuf */ ++ uint8 *databuf; /* Buffer for receiving big glom packet */ ++ uint8 *dataptr; /* Aligned pointer into databuf */ ++ uint rxlen; /* Length of valid data in buffer */ ++ ++ uint8 sdpcm_ver; /* Bus protocol reported by dongle */ ++ ++ bool intr; /* Use interrupts */ ++ bool poll; /* Use polling */ ++ bool ipend; /* Device interrupt is pending */ ++ bool intdis; /* Interrupts disabled by isr */ ++ uint intrcount; /* Count of device interrupt callbacks */ ++ uint lastintrs; /* Count as of last watchdog timer */ ++ uint spurious; /* Count of spurious interrupts */ ++ uint pollrate; /* Ticks between device polls */ ++ uint polltick; /* Tick counter */ ++ uint pollcnt; /* Count of active polls */ ++ ++#ifdef DHD_DEBUG ++ dhd_console_t console; /* Console output polling support */ ++ uint console_addr; /* Console address from shared struct */ ++#endif /* DHD_DEBUG */ ++ ++ uint regfails; /* Count of R_REG/W_REG failures */ ++ ++ uint clkstate; /* State of sd and backplane clock(s) */ ++ bool activity; /* Activity flag for clock down */ ++ int32 idletime; /* Control for activity timeout */ ++ int32 idlecount; /* Activity timeout counter */ ++ int32 idleclock; /* How to set bus driver when idle */ ++ int32 sd_divisor; /* Speed control to bus driver */ ++ int32 sd_mode; /* Mode control to bus driver */ ++ int32 sd_rxchain; /* If bcmsdh api accepts PKT chains */ ++ bool use_rxchain; /* If dhd should use PKT chains */ ++ bool sleeping; /* Is SDIO bus sleeping? */ ++ uint rxflow_mode; /* Rx flow control mode */ ++ bool rxflow; /* Is rx flow control on */ ++ uint prev_rxlim_hit; /* Is prev rx limit exceeded (per dpc schedule) */ ++ bool alp_only; /* Don't use HT clock (ALP only) */ ++ /* Field to decide if rx of control frames happen in rxbuf or lb-pool */ ++ bool usebufpool; ++ ++#ifdef SDTEST ++ /* external loopback */ ++ bool ext_loop; ++ uint8 loopid; ++ ++ /* pktgen configuration */ ++ uint pktgen_freq; /* Ticks between bursts */ ++ uint pktgen_count; /* Packets to send each burst */ ++ uint pktgen_print; /* Bursts between count displays */ ++ uint pktgen_total; /* Stop after this many */ ++ uint pktgen_minlen; /* Minimum packet data len */ ++ uint pktgen_maxlen; /* Maximum packet data len */ ++ uint pktgen_mode; /* Configured mode: tx, rx, or echo */ ++ uint pktgen_stop; /* Number of tx failures causing stop */ ++ ++ /* active pktgen fields */ ++ uint pktgen_tick; /* Tick counter for bursts */ ++ uint pktgen_ptick; /* Burst counter for printing */ ++ uint pktgen_sent; /* Number of test packets generated */ ++ uint pktgen_rcvd; /* Number of test packets received */ ++ uint pktgen_prev_time; /* Time at which previous stats where printed */ ++ uint pktgen_prev_sent; /* Number of test packets generated when ++ * previous stats were printed ++ */ ++ uint pktgen_prev_rcvd; /* Number of test packets received when ++ * previous stats were printed ++ */ ++ uint pktgen_fail; /* Number of failed send attempts */ ++ uint16 pktgen_len; /* Length of next packet to send */ ++#define PKTGEN_RCV_IDLE (0) ++#define PKTGEN_RCV_ONGOING (1) ++ uint16 pktgen_rcv_state; /* receive state */ ++ uint pktgen_rcvd_rcvsession; /* test pkts rcvd per rcv session. */ ++#endif /* SDTEST */ ++ ++ /* Some additional counters */ ++ uint tx_sderrs; /* Count of tx attempts with sd errors */ ++ uint fcqueued; /* Tx packets that got queued */ ++ uint rxrtx; /* Count of rtx requests (NAK to dongle) */ ++ uint rx_toolong; /* Receive frames too long to receive */ ++ uint rxc_errors; /* SDIO errors when reading control frames */ ++ uint rx_hdrfail; /* SDIO errors on header reads */ ++ uint rx_badhdr; /* Bad received headers (roosync?) */ ++ uint rx_badseq; /* Mismatched rx sequence number */ ++ uint fc_rcvd; /* Number of flow-control events received */ ++ uint fc_xoff; /* Number which turned on flow-control */ ++ uint fc_xon; /* Number which turned off flow-control */ ++ uint rxglomfail; /* Failed deglom attempts */ ++ uint rxglomframes; /* Number of glom frames (superframes) */ ++ uint rxglompkts; /* Number of packets from glom frames */ ++ uint f2rxhdrs; /* Number of header reads */ ++ uint f2rxdata; /* Number of frame data reads */ ++ uint f2txdata; /* Number of f2 frame writes */ ++ uint f1regdata; /* Number of f1 register accesses */ ++ ++ uint8 *ctrl_frame_buf; ++ uint32 ctrl_frame_len; ++ bool ctrl_frame_stat; ++ uint32 rxint_mode; /* rx interrupt mode */ ++ bool remap; /* Contiguous 1MB RAM: 512K socram + 512K devram ++ * Available with socram rev 16 ++ * Remap region not DMA-able ++ */ ++ bool kso; ++ bool _slpauto; ++ bool _oobwakeup; ++ bool _srenab; ++ bool readframes; ++ bool reqbussleep; ++ uint32 resetinstr; ++ uint32 dongle_ram_base; ++#ifdef BCMSDIOH_TXGLOM ++ void *glom_pkt_arr[SDPCM_MAXGLOM_SIZE]; /* Array of pkts for glomming */ ++ uint16 glom_cnt; /* Number of pkts in the glom array */ ++ uint16 glom_total_len; /* Total length of pkts in glom array */ ++ bool glom_enable; /* Flag to indicate whether tx glom is enabled/disabled */ ++ uint8 glom_mode; /* Glom mode - 0-copy mode, 1 - Multi-descriptor mode */ ++ uint32 glomsize; /* Glom size limitation */ ++#endif ++} dhd_bus_t; ++ ++/* clkstate */ ++#define CLK_NONE 0 ++#define CLK_SDONLY 1 ++#define CLK_PENDING 2 /* Not used yet */ ++#define CLK_AVAIL 3 ++ ++#define DHD_NOPMU(dhd) (FALSE) ++ ++#ifdef DHD_DEBUG ++static int qcount[NUMPRIO]; ++static int tx_packets[NUMPRIO]; ++#endif /* DHD_DEBUG */ ++ ++/* Deferred transmit */ ++const uint dhd_deferred_tx = 1; ++ ++extern uint dhd_watchdog_ms; ++extern void dhd_os_wd_timer(void *bus, uint wdtick); ++ ++/* Tx/Rx bounds */ ++uint dhd_txbound; ++uint dhd_rxbound; ++uint dhd_txminmax = DHD_TXMINMAX; ++ ++/* override the RAM size if possible */ ++#define DONGLE_MIN_MEMSIZE (128 *1024) ++int dhd_dongle_memsize; ++ ++static bool dhd_doflow; ++static bool dhd_alignctl; ++ ++static bool sd1idle; ++ ++static bool retrydata; ++#define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata) ++ ++#if defined(SDIO_CRC_ERROR_FIX) ++static uint watermark = 48; ++static uint mesbusyctrl = 80; ++#else ++static const uint watermark = 8; ++static const uint mesbusyctrl = 0; ++#endif ++static const uint firstread = DHD_FIRSTREAD; ++ ++#define HDATLEN (firstread - (SDPCM_HDRLEN)) ++ ++/* Retry count for register access failures */ ++static const uint retry_limit = 2; ++ ++/* Force even SD lengths (some host controllers mess up on odd bytes) */ ++static bool forcealign; ++ ++#define FW_TYPE_STA 0 ++#define FW_TYPE_APSTA 1 ++#define FW_TYPE_P2P 2 ++#define FW_TYPE_MFG 3 ++#define FW_TYPE_G 0 ++#define FW_TYPE_AG 1 ++ ++const static char *bcm40183b2_fw_name[] = { ++ "fw_bcm40183b2.bin", ++ "fw_bcm40183b2_apsta.bin", ++ "fw_bcm40183b2_p2p.bin", ++ "fw_bcm40183b2_mfg.bin" ++}; ++ ++const static char *bcm40183b2ag_fw_name[] = { ++ "fw_bcm40183b2_ag.bin", ++ "fw_bcm40183b2_ag_apsta.bin", ++ "fw_bcm40183b2_ag_p2p.bin", ++ "fw_bcm40183b2_ag_mfg.bin" ++}; ++ ++const static char *bcm40181a0_fw_name[] = { ++ "fw_bcm40181a0.bin", ++ "fw_bcm40181a0_apsta.bin", ++ "fw_bcm40181a0_p2p.bin", ++ "fw_bcm40181a0_mfg.bin" ++}; ++ ++const static char *bcm40181a2_fw_name[] = { ++ "fw_bcm40181a2.bin", ++ "fw_bcm40181a2_apsta.bin", ++ "fw_bcm40181a2_p2p.bin", ++ "fw_bcm40181a2_mfg.bin" ++}; ++ ++const static char *bcm43341b0ag_fw_name[] = { ++ "fw_bcm43341b0_ag.bin", ++ "fw_bcm43341b0_ag_apsta.bin", ++ "fw_bcm43341b0_ag_p2p.bin", ++ "fw_bcm43341b0_ag_mfg.bin" ++}; ++ ++const static char *bcm43241b4ag_fw_name[] = { ++ "fw_bcm43241b4_ag.bin", ++ "fw_bcm43241b4_ag_apsta.bin", ++ "fw_bcm43241b4_ag_p2p.bin", ++ "fw_bcm43241b4_ag_mfg.bin" ++}; ++ ++#define BCM4330B2_CHIP_REV 4 ++#define BCM43362A0_CHIP_REV 0 ++#define BCM43362A2_CHIP_REV 1 ++#define BCM43341B0_CHIP_REV 2 ++#define BCM43241B4_CHIP_REV 5 ++ ++#define ALIGNMENT 4 ++ ++#if defined(OOB_INTR_ONLY) && defined(HW_OOB) ++extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable); ++#endif ++ ++#if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) ++#error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD ++#endif /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */ ++#define PKTALIGN(osh, p, len, align) \ ++ do { \ ++ uint datalign; \ ++ datalign = (uintptr)PKTDATA((osh), (p)); \ ++ datalign = ROUNDUP(datalign, (align)) - datalign; \ ++ ASSERT(datalign < (align)); \ ++ ASSERT(PKTLEN((osh), (p)) >= ((len) + datalign)); \ ++ if (datalign) \ ++ PKTPULL((osh), (p), datalign); \ ++ PKTSETLEN((osh), (p), (len)); \ ++ } while (0) ++ ++/* Limit on rounding up frames */ ++static const uint max_roundup = 512; ++ ++/* Try doing readahead */ ++static bool dhd_readahead; ++ ++ ++/* To check if there's window offered */ ++#define DATAOK(bus) \ ++ (((uint8)(bus->tx_max - bus->tx_seq) > 1) && \ ++ (((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0)) ++ ++/* To check if there's window offered for ctrl frame */ ++#define TXCTLOK(bus) \ ++ (((uint8)(bus->tx_max - bus->tx_seq) != 0) && \ ++ (((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0)) ++ ++/* Number of pkts available in dongle for data RX */ ++#define DATABUFCNT(bus) \ ++ ((uint8)(bus->tx_max - bus->tx_seq) - 1) ++ ++/* Macros to get register read/write status */ ++/* NOTE: these assume a local dhdsdio_bus_t *bus! */ ++#define R_SDREG(regvar, regaddr, retryvar) \ ++do { \ ++ retryvar = 0; \ ++ do { \ ++ regvar = R_REG(bus->dhd->osh, regaddr); \ ++ } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \ ++ if (retryvar) { \ ++ bus->regfails += (retryvar-1); \ ++ if (retryvar > retry_limit) { \ ++ AP6210_ERR("%s: FAILED" #regvar "READ, LINE %d\n", \ ++ __FUNCTION__, __LINE__); \ ++ regvar = 0; \ ++ } \ ++ } \ ++} while (0) ++ ++#define W_SDREG(regval, regaddr, retryvar) \ ++do { \ ++ retryvar = 0; \ ++ do { \ ++ W_REG(bus->dhd->osh, regaddr, regval); \ ++ } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \ ++ if (retryvar) { \ ++ bus->regfails += (retryvar-1); \ ++ if (retryvar > retry_limit) \ ++ AP6210_ERR("%s: FAILED REGISTER WRITE, LINE %d\n", \ ++ __FUNCTION__, __LINE__); \ ++ } \ ++} while (0) ++ ++#define BUS_WAKE(bus) \ ++ do { \ ++ bus->idlecount = 0; \ ++ if ((bus)->sleeping) \ ++ dhdsdio_bussleep((bus), FALSE); \ ++ } while (0); ++ ++/* ++ * pktavail interrupts from dongle to host can be managed in 3 different ways ++ * whenever there is a packet available in dongle to transmit to host. ++ * ++ * Mode 0: Dongle writes the software host mailbox and host is interrupted. ++ * Mode 1: (sdiod core rev >= 4) ++ * Device sets a new bit in the intstatus whenever there is a packet ++ * available in fifo. Host can't clear this specific status bit until all the ++ * packets are read from the FIFO. No need to ack dongle intstatus. ++ * Mode 2: (sdiod core rev >= 4) ++ * Device sets a bit in the intstatus, and host acks this by writing ++ * one to this bit. Dongle won't generate anymore packet interrupts ++ * until host reads all the packets from the dongle and reads a zero to ++ * figure that there are no more packets. No need to disable host ints. ++ * Need to ack the intstatus. ++ */ ++ ++#define SDIO_DEVICE_HMB_RXINT 0 /* default old way */ ++#define SDIO_DEVICE_RXDATAINT_MODE_0 1 /* from sdiod rev 4 */ ++#define SDIO_DEVICE_RXDATAINT_MODE_1 2 /* from sdiod rev 4 */ ++ ++ ++#define FRAME_AVAIL_MASK(bus) \ ++ ((bus->rxint_mode == SDIO_DEVICE_HMB_RXINT) ? I_HMB_FRAME_IND : I_XMTDATA_AVAIL) ++ ++#define DHD_BUS SDIO_BUS ++ ++#define PKT_AVAILABLE(bus, intstatus) ((intstatus) & (FRAME_AVAIL_MASK(bus))) ++ ++#define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) ++ ++#define GSPI_PR55150_BAILOUT ++ ++#ifdef SDTEST ++static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq); ++static void dhdsdio_sdtest_set(dhd_bus_t *bus, uint count); ++#endif ++ ++#ifdef DHD_DEBUG ++static int dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size); ++static int dhd_serialconsole(dhd_bus_t *bus, bool get, bool enable, int *bcmerror); ++#endif /* DHD_DEBUG */ ++ ++static int dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap); ++static int dhdsdio_download_state(dhd_bus_t *bus, bool enter); ++ ++static void dhdsdio_release(dhd_bus_t *bus, osl_t *osh); ++static void dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh); ++static void dhdsdio_disconnect(void *ptr); ++static bool dhdsdio_chipmatch(uint16 chipid); ++static bool dhdsdio_probe_attach(dhd_bus_t *bus, osl_t *osh, void *sdh, ++ void * regsva, uint16 devid); ++static bool dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh); ++static bool dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh); ++static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, ++ bool reset_flag); ++ ++static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size); ++static int dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, ++ uint8 *buf, uint nbytes, ++ void *pkt, bcmsdh_cmplt_fn_t complete, void *handle); ++static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, ++ uint8 *buf, uint nbytes, ++ void *pkt, bcmsdh_cmplt_fn_t complete, void *handle); ++#ifdef BCMSDIOH_TXGLOM ++static void dhd_bcmsdh_glom_post(dhd_bus_t *bus, uint8 *frame, uint len); ++static void dhd_bcmsdh_glom_clear(dhd_bus_t *bus); ++#endif ++ ++static bool dhdsdio_download_firmware(dhd_bus_t *bus, osl_t *osh, void *sdh); ++static int _dhdsdio_download_firmware(dhd_bus_t *bus); ++ ++static int dhdsdio_download_code_file(dhd_bus_t *bus, char *image_path); ++static int dhdsdio_download_nvram(dhd_bus_t *bus); ++#ifdef BCMEMBEDIMAGE ++static int dhdsdio_download_code_array(dhd_bus_t *bus); ++#endif ++static int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep); ++static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok); ++static uint8 dhdsdio_sleepcsr_get(dhd_bus_t *bus); ++ ++#ifdef WLMEDIA_HTSF ++#include ++extern uint32 dhd_get_htsf(void *dhd, int ifidx); ++#endif /* WLMEDIA_HTSF */ ++ ++static void ++dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size) ++{ ++ int32 min_size = DONGLE_MIN_MEMSIZE; ++ /* Restrict the memsize to user specified limit */ ++ AP6210_DEBUG("user: Restrict the dongle ram size to %d, min accepted %d\n", ++ dhd_dongle_memsize, min_size); ++ if ((dhd_dongle_memsize > min_size) && ++ (dhd_dongle_memsize < (int32)bus->orig_ramsize)) ++ bus->ramsize = dhd_dongle_memsize; ++} ++ ++static int ++dhdsdio_set_siaddr_window(dhd_bus_t *bus, uint32 address) ++{ ++ int err = 0; ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, ++ (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err); ++ if (!err) ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID, ++ (address >> 16) & SBSDIO_SBADDRMID_MASK, &err); ++ if (!err) ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH, ++ (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err); ++ return err; ++} ++ ++ ++#ifdef USE_OOB_GPIO1 ++static int ++dhdsdio_oobwakeup_init(dhd_bus_t *bus) ++{ ++ uint32 val, addr, data; ++ ++ bcmsdh_gpioouten(bus->sdh, GPIO_DEV_WAKEUP); ++ ++ addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr); ++ data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data); ++ ++ /* Set device for gpio1 wakeup */ ++ bcmsdh_reg_write(bus->sdh, addr, 4, 2); ++ val = bcmsdh_reg_read(bus->sdh, data, 4); ++ val |= CC_CHIPCTRL2_GPIO1_WAKEUP; ++ bcmsdh_reg_write(bus->sdh, data, 4, val); ++ ++ bus->_oobwakeup = TRUE; ++ ++ return 0; ++} ++#endif /* USE_OOB_GPIO1 */ ++ ++/* ++ * Query if FW is in SR mode ++ */ ++static bool ++dhdsdio_sr_cap(dhd_bus_t *bus) ++{ ++ bool cap = FALSE; ++ uint32 min = 0, core_capext, addr, data; ++ if (bus->sih->chip == BCM4324_CHIP_ID) { ++ addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr); ++ data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data); ++ bcmsdh_reg_write(bus->sdh, addr, 4, 3); ++ core_capext = bcmsdh_reg_read(bus->sdh, data, 4); ++ } else if (bus->sih->chip == BCM4330_CHIP_ID || bus->sih->chip == BCM43362_CHIP_ID) { ++ core_capext = FALSE; ++ } else if (bus->sih->chip == BCM4335_CHIP_ID) { ++ core_capext = TRUE; ++ } else { ++ core_capext = bcmsdh_reg_read(bus->sdh, CORE_CAPEXT_ADDR, 4); ++ core_capext = (core_capext & CORE_CAPEXT_SR_SUPPORTED_MASK); ++ } ++ if (!(core_capext)) ++ return FALSE; ++ ++ if (bus->sih->chip == BCM4324_CHIP_ID) { ++ /* FIX: Should change to query SR control register instead */ ++ min = bcmsdh_reg_read(bus->sdh, MIN_RSRC_ADDR, 4); ++ if (min == MIN_RSRC_SR) ++ cap = TRUE; ++ } else if (bus->sih->chip == BCM4335_CHIP_ID) { ++ uint32 enabval = 0; ++ addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr); ++ data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data); ++ bcmsdh_reg_write(bus->sdh, addr, 4, CC_PMUCC3); ++ enabval = bcmsdh_reg_read(bus->sdh, data, 4); ++ ++ if (enabval) ++ cap = TRUE; ++ } else { ++ data = bcmsdh_reg_read(bus->sdh, ++ SI_ENUM_BASE + OFFSETOF(chipcregs_t, retention_ctl), 4); ++ if ((data & (RCTL_MACPHY_DISABLE_MASK | RCTL_LOGIC_DISABLE_MASK)) == 0) ++ cap = TRUE; ++ } ++ ++ return cap; ++} ++ ++static int ++dhdsdio_srwar_init(dhd_bus_t *bus) ++{ ++ ++ bcmsdh_gpio_init(bus->sdh); ++ ++#ifdef USE_OOB_GPIO1 ++ dhdsdio_oobwakeup_init(bus); ++#endif ++ ++ ++ return 0; ++} ++ ++static int ++dhdsdio_sr_init(dhd_bus_t *bus) ++{ ++ uint8 val; ++ int err = 0; ++ ++ if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2)) ++ dhdsdio_srwar_init(bus); ++ ++ val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL); ++ val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT; ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, ++ 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT, &err); ++ val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL); ++ ++ /* Add CMD14 Support */ ++ dhdsdio_devcap_set(bus, ++ (SDIOD_CCCR_BRCM_CARDCAP_CMD14_SUPPORT | SDIOD_CCCR_BRCM_CARDCAP_CMD14_EXT)); ++ ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_FORCE_HT, &err); ++ ++ bus->_slpauto = dhd_slpauto ? TRUE : FALSE; ++ ++ bus->_srenab = TRUE; ++ ++ return 0; ++} ++ ++/* ++ * FIX: Be sure KSO bit is enabled ++ * Currently, it's defaulting to 0 which should be 1. ++ */ ++static int ++dhdsdio_clk_kso_init(dhd_bus_t *bus) ++{ ++ uint8 val; ++ int err = 0; ++ ++ /* set flag */ ++ bus->kso = TRUE; ++ ++ /* ++ * Enable KeepSdioOn (KSO) bit for normal operation ++ * Default is 0 (4334A0) so set it. Fixed in B0. ++ */ ++ val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, NULL); ++ if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) { ++ val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, val, &err); ++ if (err) ++ AP6210_ERR("%s: SBSDIO_FUNC1_SLEEPCSR err: 0x%x\n", __FUNCTION__, err); ++ } ++ ++ return 0; ++} ++ ++#define KSO_DBG(x) ++#define MAX_KSO_ATTEMPTS 64 ++static int ++dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on) ++{ ++ uint8 wr_val = 0, rd_val, cmp_val, bmask; ++ int err = 0; ++ int try_cnt = 0; ++ ++ KSO_DBG(("%s> op:%s\n", __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"))); ++ ++ wr_val |= (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); ++ ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err); ++ ++ if (on) { ++ cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK | SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK; ++ bmask = cmp_val; ++ ++ msleep(3); ++ ++ } else { ++ /* Put device to sleep, turn off KSO */ ++ cmp_val = 0; ++ bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK; ++ } ++ ++ do { ++ rd_val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err); ++ if (((rd_val & bmask) == cmp_val) && !err) ++ break; ++ ++ KSO_DBG(("%s> KSO wr/rd retry:%d, ERR:%x \n", __FUNCTION__, try_cnt, err)); ++ OSL_DELAY(50); ++ ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err); ++ ++ } while (try_cnt++ < MAX_KSO_ATTEMPTS); ++ ++ ++ if (try_cnt > 1) { ++ KSO_DBG(("%s> op:%s, try_cnt:%d, rd_val:%x, ERR:%x \n", ++ __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err)); ++ } ++ ++ if (try_cnt > MAX_KSO_ATTEMPTS) { ++ AP6210_ERR("%s> op:%s, ERROR: try_cnt:%d, rd_val:%x, ERR:%x \n", ++ __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err); ++ } ++ return err; ++} ++ ++static int ++dhdsdio_clk_kso_iovar(dhd_bus_t *bus, bool on) ++{ ++ int err = 0; ++ ++ if (on == FALSE) { ++ ++ BUS_WAKE(bus); ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); ++ ++ AP6210_DEBUG("%s: KSO disable clk: 0x%x\n", __FUNCTION__, ++ bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, &err)); ++ dhdsdio_clk_kso_enab(bus, FALSE); ++ } else { ++ AP6210_DEBUG("%s: KSO enable\n", __FUNCTION__); ++ ++ /* Make sure we have SD bus access */ ++ if (bus->clkstate == CLK_NONE) { ++ AP6210_DEBUG("%s: Request SD clk\n", __FUNCTION__); ++ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); ++ } ++ ++ /* Double-write to be safe in case transition of AOS */ ++ dhdsdio_clk_kso_enab(bus, TRUE); ++ dhdsdio_clk_kso_enab(bus, TRUE); ++ OSL_DELAY(4000); ++ ++ /* Wait for device ready during transition to wake-up */ ++ SPINWAIT(((dhdsdio_sleepcsr_get(bus)) != ++ (SBSDIO_FUNC1_SLEEPCSR_KSO_MASK | ++ SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)), ++ (10000)); ++ ++ AP6210_DEBUG("%s: sleepcsr: 0x%x\n", __FUNCTION__, ++ dhdsdio_sleepcsr_get(bus)); ++ } ++ ++ bus->kso = on; ++ BCM_REFERENCE(err); ++ ++ return 0; ++} ++ ++static uint8 ++dhdsdio_sleepcsr_get(dhd_bus_t *bus) ++{ ++ int err = 0; ++ uint8 val = 0; ++ ++ val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err); ++ if (err) ++ AP6210_DEBUG("Failed to read SLEEPCSR: %d\n", err); ++ ++ return val; ++} ++ ++uint8 ++dhdsdio_devcap_get(dhd_bus_t *bus) ++{ ++ return bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, NULL); ++} ++ ++static int ++dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap) ++{ ++ int err = 0; ++ ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, cap, &err); ++ if (err) ++ AP6210_ERR("%s: devcap set err: 0x%x\n", __FUNCTION__, err); ++ ++ return 0; ++} ++ ++static int ++dhdsdio_clk_devsleep_iovar(dhd_bus_t *bus, bool on) ++{ ++ int err = 0, retry; ++ uint8 val; ++ ++ retry = 0; ++ if (on == TRUE) { ++ /* Enter Sleep */ ++ ++ /* Be sure we request clk before going to sleep ++ * so we can wake-up with clk request already set ++ * else device can go back to sleep immediately ++ */ ++ if (!SLPAUTO_ENAB(bus)) ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); ++ else { ++ val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ if ((val & SBSDIO_CSR_MASK) == 0) { ++ AP6210_DEBUG("%s: No clock before enter sleep:0x%x\n", ++ __FUNCTION__, val); ++ ++ /* Reset clock request */ ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, ++ SBSDIO_ALP_AVAIL_REQ, &err); ++ AP6210_DEBUG("%s: clock before sleep:0x%x\n", __FUNCTION__, ++ bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, &err)); ++ } ++ } ++ ++ AP6210_DEBUG("%s: clk before sleep: 0x%x\n", __FUNCTION__, ++ bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, &err)); ++#ifdef USE_CMD14 ++ err = bcmsdh_sleep(bus->sdh, TRUE); ++#else ++ err = dhdsdio_clk_kso_enab(bus, FALSE); ++ if (OOB_WAKEUP_ENAB(bus)) ++ err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, FALSE); /* GPIO_1 is off */ ++#endif ++ } else { ++ /* Exit Sleep */ ++ /* Make sure we have SD bus access */ ++ if (bus->clkstate == CLK_NONE) { ++ AP6210_DEBUG("%s: Request SD clk\n", __FUNCTION__); ++ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); ++ } ++ ++ if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2)) { ++ SPINWAIT((bcmsdh_gpioin(bus->sdh, GPIO_DEV_SRSTATE) != TRUE), ++ GPIO_DEV_SRSTATE_TIMEOUT); ++ ++ if (bcmsdh_gpioin(bus->sdh, GPIO_DEV_SRSTATE) == FALSE) { ++ AP6210_ERR("ERROR: GPIO_DEV_SRSTATE still low!\n"); ++ } ++ } ++#ifdef USE_CMD14 ++ err = bcmsdh_sleep(bus->sdh, FALSE); ++ if (SLPAUTO_ENAB(bus) && (err != 0)) { ++ OSL_DELAY(10000); ++ AP6210_DEBUG("%s: Resync device sleep\n", __FUNCTION__); ++ ++ /* Toggle sleep to resync with host and device */ ++ err = bcmsdh_sleep(bus->sdh, TRUE); ++ OSL_DELAY(10000); ++ err = bcmsdh_sleep(bus->sdh, FALSE); ++ ++ if (err) { ++ OSL_DELAY(10000); ++ AP6210_ERR("%s: CMD14 exit failed again!\n", __FUNCTION__); ++ ++ /* Toggle sleep to resync with host and device */ ++ err = bcmsdh_sleep(bus->sdh, TRUE); ++ OSL_DELAY(10000); ++ err = bcmsdh_sleep(bus->sdh, FALSE); ++ if (err) { ++ AP6210_ERR("%s: CMD14 exit failed twice!\n", __FUNCTION__); ++ AP6210_ERR("%s: FATAL: Device non-response!\n", ++ __FUNCTION__); ++ err = 0; ++ } ++ } ++ } ++#else ++ if (OOB_WAKEUP_ENAB(bus)) ++ err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, TRUE); /* GPIO_1 is on */ ++ ++ do { ++ err = dhdsdio_clk_kso_enab(bus, TRUE); ++ if (err) ++ OSL_DELAY(10000); ++ } while ((err != 0) && (++retry < 3)); ++ ++ if (err != 0) { ++ AP6210_ERR("ERROR: kso set failed retry: %d\n", retry); ++ err = 0; /* continue anyway */ ++ } ++#endif /* !USE_CMD14 */ ++ ++ if (err == 0) { ++ uint8 csr; ++ ++ /* Wait for device ready during transition to wake-up */ ++ SPINWAIT((((csr = dhdsdio_sleepcsr_get(bus)) & ++ SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK) != ++ (SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)), (20000)); ++ ++ AP6210_DEBUG("%s: ExitSleep sleepcsr: 0x%x\n", __FUNCTION__, csr); ++ ++ if (!(csr & SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)) { ++ AP6210_ERR("%s:ERROR: ExitSleep device NOT Ready! 0x%x\n", ++ __FUNCTION__, csr); ++ err = BCME_NODEVICE; ++ } ++ ++ SPINWAIT((((csr = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, &err)) & SBSDIO_HT_AVAIL) != ++ (SBSDIO_HT_AVAIL)), (10000)); ++ ++ } ++ } ++ ++ /* Update if successful */ ++ if (err == 0) ++ bus->kso = on ? FALSE : TRUE; ++ else { ++ AP6210_ERR("%s: Sleep request failed: on:%d err:%d\n", __FUNCTION__, on, err); ++ if (!on && retry > 2) ++ bus->kso = TRUE; ++ } ++ ++ return err; ++} ++ ++/* Turn backplane clock on or off */ ++static int ++dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) ++{ ++#define HT_AVAIL_ERROR_MAX 10 ++ static int ht_avail_error = 0; ++ int err; ++ uint8 clkctl, clkreq, devctl; ++ bcmsdh_info_t *sdh; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++#if defined(OOB_INTR_ONLY) ++ pendok = FALSE; ++#endif ++ clkctl = 0; ++ sdh = bus->sdh; ++ ++ ++ if (!KSO_ENAB(bus)) ++ return BCME_OK; ++ ++ if (SLPAUTO_ENAB(bus)) { ++ bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY); ++ return BCME_OK; ++ } ++ ++ if (on) { ++ /* Request HT Avail */ ++ clkreq = bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; ++ ++ ++ ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); ++ if (err) { ++ ht_avail_error++; ++ if (ht_avail_error < HT_AVAIL_ERROR_MAX) { ++ AP6210_ERR("%s: HT Avail request error: %d\n", __FUNCTION__, err); ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) ++ else if (ht_avail_error == HT_AVAIL_ERROR_MAX) { ++ dhd_os_send_hang_message(bus->dhd); ++ } ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */ ++ return BCME_ERROR; ++ } else { ++ ht_avail_error = 0; ++ } ++ ++ if (pendok && ++ ((bus->sih->buscoretype == PCMCIA_CORE_ID) && (bus->sih->buscorerev == 9))) { ++ uint32 dummy, retries; ++ R_SDREG(dummy, &bus->regs->clockctlstatus, retries); ++ BCM_REFERENCE(dummy); ++ } ++ ++ /* Check current status */ ++ clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ if (err) { ++ AP6210_ERR("%s: HT Avail read error: %d\n", __FUNCTION__, err); ++ return BCME_ERROR; ++ } ++ ++ /* Go to pending and await interrupt if appropriate */ ++ if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { ++ /* Allow only clock-available interrupt */ ++ devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); ++ if (err) { ++ AP6210_ERR("%s: Devctl access error setting CA: %d\n", ++ __FUNCTION__, err); ++ return BCME_ERROR; ++ } ++ ++ devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); ++ AP6210_DEBUG("CLKCTL: set PENDING\n"); ++ bus->clkstate = CLK_PENDING; ++ return BCME_OK; ++ } else if (bus->clkstate == CLK_PENDING) { ++ /* Cancel CA-only interrupt filter */ ++ devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); ++ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); ++ } ++ ++ /* Otherwise, wait here (polling) for HT Avail */ ++ if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { ++ SPINWAIT_SLEEP(sdioh_spinwait_sleep, ++ ((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, &err)), ++ !SBSDIO_CLKAV(clkctl, bus->alp_only)), PMU_MAX_TRANSITION_DLY); ++ } ++ if (err) { ++ AP6210_ERR("%s: HT Avail request error: %d\n", __FUNCTION__, err); ++ return BCME_ERROR; ++ } ++ if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { ++ AP6210_ERR("%s: HT Avail timeout (%d): clkctl 0x%02x\n", ++ __FUNCTION__, PMU_MAX_TRANSITION_DLY, clkctl); ++ return BCME_ERROR; ++ } ++ ++ /* Mark clock available */ ++ bus->clkstate = CLK_AVAIL; ++ AP6210_DEBUG("CLKCTL: turned ON\n"); ++ ++#if defined(DHD_DEBUG) ++ if (bus->alp_only == TRUE) { ++#if !defined(BCMLXSDMMC) ++ if (!SBSDIO_ALPONLY(clkctl)) { ++ AP6210_ERR("%s: HT Clock, when ALP Only\n", __FUNCTION__); ++ } ++#endif /* !defined(BCMLXSDMMC) */ ++ } else { ++ if (SBSDIO_ALPONLY(clkctl)) { ++ AP6210_ERR("%s: HT Clock should be on.\n", __FUNCTION__); ++ } ++ } ++#endif /* defined (DHD_DEBUG) */ ++ ++ bus->activity = TRUE; ++#ifdef DHD_USE_IDLECOUNT ++ bus->idlecount = 0; ++#endif /* DHD_USE_IDLECOUNT */ ++ } else { ++ clkreq = 0; ++ if (bus->clkstate == CLK_PENDING) { ++ /* Cancel CA-only interrupt filter */ ++ devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); ++ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); ++ } ++ ++ bus->clkstate = CLK_SDONLY; ++ if (!SR_ENAB(bus)) { ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); ++ AP6210_DEBUG("CLKCTL: turned OFF\n"); ++ if (err) { ++ AP6210_ERR("%s: Failed access turning clock off: %d\n", ++ __FUNCTION__, err); ++ return BCME_ERROR; ++ } ++ } ++ } ++ return BCME_OK; ++} ++ ++/* Change idle/active SD state */ ++static int ++dhdsdio_sdclk(dhd_bus_t *bus, bool on) ++{ ++ int err; ++ int32 iovalue; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (on) { ++ if (bus->idleclock == DHD_IDLE_STOP) { ++ /* Turn on clock and restore mode */ ++ iovalue = 1; ++ err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0, ++ &iovalue, sizeof(iovalue), TRUE); ++ if (err) { ++ AP6210_ERR("%s: error enabling sd_clock: %d\n", ++ __FUNCTION__, err); ++ return BCME_ERROR; ++ } ++ ++ iovalue = bus->sd_mode; ++ err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0, ++ &iovalue, sizeof(iovalue), TRUE); ++ if (err) { ++ AP6210_ERR("%s: error changing sd_mode: %d\n", ++ __FUNCTION__, err); ++ return BCME_ERROR; ++ } ++ } else if (bus->idleclock != DHD_IDLE_ACTIVE) { ++ /* Restore clock speed */ ++ iovalue = bus->sd_divisor; ++ err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0, ++ &iovalue, sizeof(iovalue), TRUE); ++ if (err) { ++ AP6210_ERR("%s: error restoring sd_divisor: %d\n", ++ __FUNCTION__, err); ++ return BCME_ERROR; ++ } ++ } ++ bus->clkstate = CLK_SDONLY; ++ } else { ++ /* Stop or slow the SD clock itself */ ++ if ((bus->sd_divisor == -1) || (bus->sd_mode == -1)) { ++ AP6210_DEBUG("%s: can't idle clock, divisor %d mode %d\n", ++ __FUNCTION__, bus->sd_divisor, bus->sd_mode); ++ return BCME_ERROR; ++ } ++ if (bus->idleclock == DHD_IDLE_STOP) { ++ if (sd1idle) { ++ /* Change to SD1 mode and turn off clock */ ++ iovalue = 1; ++ err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0, ++ &iovalue, sizeof(iovalue), TRUE); ++ if (err) { ++ AP6210_ERR("%s: error changing sd_clock: %d\n", ++ __FUNCTION__, err); ++ return BCME_ERROR; ++ } ++ } ++ ++ iovalue = 0; ++ err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0, ++ &iovalue, sizeof(iovalue), TRUE); ++ if (err) { ++ AP6210_ERR("%s: error disabling sd_clock: %d\n", ++ __FUNCTION__, err); ++ return BCME_ERROR; ++ } ++ } else if (bus->idleclock != DHD_IDLE_ACTIVE) { ++ /* Set divisor to idle value */ ++ iovalue = bus->idleclock; ++ err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0, ++ &iovalue, sizeof(iovalue), TRUE); ++ if (err) { ++ AP6210_ERR("%s: error changing sd_divisor: %d\n", ++ __FUNCTION__, err); ++ return BCME_ERROR; ++ } ++ } ++ bus->clkstate = CLK_NONE; ++ } ++ ++ return BCME_OK; ++} ++ ++/* Transition SD and backplane clock readiness */ ++static int ++dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok) ++{ ++ int ret = BCME_OK; ++#ifdef DHD_DEBUG ++ uint oldstate = bus->clkstate; ++#endif /* DHD_DEBUG */ ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ /* Early exit if we're already there */ ++ if (bus->clkstate == target) { ++ if (target == CLK_AVAIL) { ++ dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); ++ bus->activity = TRUE; ++#ifdef DHD_USE_IDLECOUNT ++ bus->idlecount = 0; ++#endif /* DHD_USE_IDLECOUNT */ ++ } ++ return ret; ++ } ++ ++ switch (target) { ++ case CLK_AVAIL: ++ /* Make sure SD clock is available */ ++ if (bus->clkstate == CLK_NONE) ++ dhdsdio_sdclk(bus, TRUE); ++ /* Now request HT Avail on the backplane */ ++ ret = dhdsdio_htclk(bus, TRUE, pendok); ++ if (ret == BCME_OK) { ++ dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); ++ bus->activity = TRUE; ++#ifdef DHD_USE_IDLECOUNT ++ bus->idlecount = 0; ++#endif /* DHD_USE_IDLECOUNT */ ++ } ++ break; ++ ++ case CLK_SDONLY: ++ /* Remove HT request, or bring up SD clock */ ++ if (bus->clkstate == CLK_NONE) ++ ret = dhdsdio_sdclk(bus, TRUE); ++ else if (bus->clkstate == CLK_AVAIL) ++ ret = dhdsdio_htclk(bus, FALSE, FALSE); ++ else ++ AP6210_DEBUG("dhdsdio_clkctl: request for %d -> %d\n", ++ bus->clkstate, target); ++ if (ret == BCME_OK) { ++ dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); ++ } ++ break; ++ ++ case CLK_NONE: ++ /* Make sure to remove HT request */ ++ if (bus->clkstate == CLK_AVAIL) ++ ret = dhdsdio_htclk(bus, FALSE, FALSE); ++ /* Now remove the SD clock */ ++ ret = dhdsdio_sdclk(bus, FALSE); ++#ifdef DHD_DEBUG ++ if (dhd_console_ms == 0) ++#endif /* DHD_DEBUG */ ++ if (bus->poll == 0) ++ dhd_os_wd_timer(bus->dhd, 0); ++ break; ++ } ++#ifdef DHD_DEBUG ++ AP6210_DEBUG("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate); ++#endif /* DHD_DEBUG */ ++ ++ return ret; ++} ++ ++static int ++dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) ++{ ++ int err = 0; ++ bcmsdh_info_t *sdh = bus->sdh; ++ sdpcmd_regs_t *regs = bus->regs; ++ uint retries = 0; ++ ++ AP6210_DEBUG("dhdsdio_bussleep: request %s (currently %s)\n", ++ (sleep ? "SLEEP" : "WAKE"), ++ (bus->sleeping ? "SLEEP" : "WAKE")); ++ ++ /* Done if we're already in the requested state */ ++ if (sleep == bus->sleeping) ++ return BCME_OK; ++ ++ /* Going to sleep: set the alarm and turn off the lights... */ ++ if (sleep) { ++ /* Don't sleep if something is pending */ ++ if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq)) ++ return BCME_BUSY; ++ ++ ++ if (!SLPAUTO_ENAB(bus)) { ++ /* Disable SDIO interrupts (no longer interested) */ ++ bcmsdh_intr_disable(bus->sdh); ++ ++ /* Make sure the controller has the bus up */ ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); ++ ++ /* Tell device to start using OOB wakeup */ ++ W_SDREG(SMB_USE_OOB, ®s->tosbmailbox, retries); ++ if (retries > retry_limit) ++ AP6210_ERR("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"); ++ ++ /* Turn off our contribution to the HT clock request */ ++ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); ++ ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, ++ SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); ++ ++ /* Isolate the bus */ ++ if (bus->sih->chip != BCM4329_CHIP_ID && ++ bus->sih->chip != BCM4319_CHIP_ID) { ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, ++ SBSDIO_DEVCTL_PADS_ISO, NULL); ++ } ++ } else { ++ /* Leave interrupts enabled since device can exit sleep and ++ * interrupt host ++ */ ++ err = dhdsdio_clk_devsleep_iovar(bus, TRUE /* sleep */); ++ } ++ ++ /* Change state */ ++ bus->sleeping = TRUE; ++ ++ } else { ++ /* Waking up: bus power up is ok, set local state */ ++ ++ if (!SLPAUTO_ENAB(bus)) { ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, &err); ++ ++ /* Force pad isolation off if possible (in case power never toggled) */ ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL); ++ ++ ++ /* Make sure the controller has the bus up */ ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); ++ ++ /* Send misc interrupt to indicate OOB not needed */ ++ W_SDREG(0, ®s->tosbmailboxdata, retries); ++ if (retries <= retry_limit) ++ W_SDREG(SMB_DEV_INT, ®s->tosbmailbox, retries); ++ ++ if (retries > retry_limit) ++ AP6210_ERR("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"); ++ ++ /* Make sure we have SD bus access */ ++ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); ++ ++ /* Enable interrupts again */ ++ if (bus->intr && (bus->dhd->busstate == DHD_BUS_DATA)) { ++ bus->intdis = FALSE; ++ bcmsdh_intr_enable(bus->sdh); ++ } ++ } else { ++ err = dhdsdio_clk_devsleep_iovar(bus, FALSE /* wake */); ++ } ++ ++ if (err == 0) { ++ /* Change state */ ++ bus->sleeping = FALSE; ++ } ++ } ++ ++ return err; ++} ++ ++#if defined(OOB_INTR_ONLY) ++void ++dhd_enable_oob_intr(struct dhd_bus *bus, bool enable) ++{ ++#if defined(HW_OOB) ++ bcmsdh_enable_hw_oob_intr(bus->sdh, enable); ++#else ++ sdpcmd_regs_t *regs = bus->regs; ++ uint retries = 0; ++ ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); ++ if (enable == TRUE) { ++ ++ /* Tell device to start using OOB wakeup */ ++ W_SDREG(SMB_USE_OOB, ®s->tosbmailbox, retries); ++ if (retries > retry_limit) ++ AP6210_ERR("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"); ++ ++ } else { ++ /* Send misc interrupt to indicate OOB not needed */ ++ W_SDREG(0, ®s->tosbmailboxdata, retries); ++ if (retries <= retry_limit) ++ W_SDREG(SMB_DEV_INT, ®s->tosbmailbox, retries); ++ } ++ ++ /* Turn off our contribution to the HT clock request */ ++ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); ++#endif /* !defined(HW_OOB) */ ++} ++#endif ++ ++/* Writes a HW/SW header into the packet and sends it. */ ++/* Assumes: (a) header space already there, (b) caller holds lock */ ++static int ++dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt, bool queue_only) ++{ ++ int ret; ++ osl_t *osh; ++ uint8 *frame; ++ uint16 len, pad1 = 0; ++ uint32 swheader; ++ uint retries = 0; ++ bcmsdh_info_t *sdh; ++ void *new; ++ int i; ++ int pkt_cnt; ++#ifdef BCMSDIOH_TXGLOM ++ uint8 *frame_tmp; ++#endif ++#ifdef WLMEDIA_HTSF ++ char *p; ++ htsfts_t *htsf_ts; ++#endif ++ ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ sdh = bus->sdh; ++ osh = bus->dhd->osh; ++ ++ if (bus->dhd->dongle_reset) { ++ ret = BCME_NOTREADY; ++ goto done; ++ } ++ ++ frame = (uint8*)PKTDATA(osh, pkt); ++ ++#ifdef WLMEDIA_HTSF ++ if (PKTLEN(osh, pkt) >= 100) { ++ p = PKTDATA(osh, pkt); ++ htsf_ts = (htsfts_t*) (p + HTSF_HOSTOFFSET + 12); ++ if (htsf_ts->magic == HTSFMAGIC) { ++ htsf_ts->c20 = get_cycles(); ++ htsf_ts->t20 = dhd_get_htsf(bus->dhd->info, 0); ++ } ++ } ++#endif /* WLMEDIA_HTSF */ ++ ++ /* Add alignment padding, allocate new packet if needed */ ++ if (!((uintptr)frame & 1) && (pad1 = ((uintptr)frame % DHD_SDALIGN))) { ++ if (PKTHEADROOM(osh, pkt) < pad1) { ++ AP6210_ERR("%s: insufficient headroom %d for %d pad1\n", ++ __FUNCTION__, (int)PKTHEADROOM(osh, pkt), pad1); ++ bus->dhd->tx_realloc++; ++ new = PKTGET(osh, (PKTLEN(osh, pkt) + DHD_SDALIGN), TRUE); ++ if (!new) { ++ AP6210_ERR("%s: couldn't allocate new %d-byte packet\n", ++ __FUNCTION__, PKTLEN(osh, pkt) + DHD_SDALIGN); ++ ret = BCME_NOMEM; ++ goto done; ++ } ++ ++ PKTALIGN(osh, new, PKTLEN(osh, pkt), DHD_SDALIGN); ++ bcopy(PKTDATA(osh, pkt), PKTDATA(osh, new), PKTLEN(osh, pkt)); ++ if (free_pkt) ++ PKTFREE(osh, pkt, TRUE); ++ /* free the pkt if canned one is not used */ ++ free_pkt = TRUE; ++ pkt = new; ++ frame = (uint8*)PKTDATA(osh, pkt); ++ ASSERT(((uintptr)frame % DHD_SDALIGN) == 0); ++ pad1 = 0; ++ } else { ++ PKTPUSH(osh, pkt, pad1); ++ frame = (uint8*)PKTDATA(osh, pkt); ++ ++ ASSERT((pad1 + SDPCM_HDRLEN) <= (int) PKTLEN(osh, pkt)); ++ bzero(frame, pad1 + SDPCM_HDRLEN); ++ } ++ } ++ ASSERT(pad1 < DHD_SDALIGN); ++ ++ /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ ++ len = (uint16)PKTLEN(osh, pkt); ++ *(uint16*)frame = htol16(len); ++ *(((uint16*)frame) + 1) = htol16(~len); ++ ++#ifdef BCMSDIOH_TXGLOM ++ if (bus->glom_enable) { ++ uint32 hwheader1 = 0, hwheader2 = 0, act_len = len; ++ ++ /* Software tag: channel, sequence number, data offset */ ++ swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | ++ ((bus->tx_seq + bus->glom_cnt) % SDPCM_SEQUENCE_WRAP) | ++ (((pad1 + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); ++ htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN + SDPCM_HWEXT_LEN); ++ htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + SDPCM_HWEXT_LEN + sizeof(swheader)); ++ ++ if (queue_only) { ++ if (forcealign && (len & (ALIGNMENT - 1))) ++ len = ROUNDUP(len, ALIGNMENT); ++ /* Hardware extention tag */ ++ /* 2byte frame length, 1byte-, 1byte frame flag, ++ * 2byte-hdrlength, 2byte padlenght ++ */ ++ hwheader1 = (act_len - SDPCM_FRAMETAG_LEN) | (0 << 24); ++ hwheader2 = (len - act_len) << 16; ++ htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN); ++ htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4); ++ /* Post the frame pointer to sdio glom array */ ++ dhd_bcmsdh_glom_post(bus, frame, len); ++ /* Save the pkt pointer in bus glom array */ ++ bus->glom_pkt_arr[bus->glom_cnt] = pkt; ++ bus->glom_total_len += len; ++ bus->glom_cnt++; ++ return BCME_OK; ++ } else { ++ /* Raise len to next SDIO block to eliminate tail command */ ++ if (bus->roundup && bus->blocksize && ++ ((bus->glom_total_len + len) > bus->blocksize)) { ++ uint16 pad2 = bus->blocksize - ++ ((bus->glom_total_len + len) % bus->blocksize); ++ if ((pad2 <= bus->roundup) && (pad2 < bus->blocksize)) { ++ len += pad2; ++ } else { ++ } ++ } else if ((bus->glom_total_len + len) % DHD_SDALIGN) { ++ len += DHD_SDALIGN ++ - ((bus->glom_total_len + len) % DHD_SDALIGN); ++ } ++ if (forcealign && (len & (ALIGNMENT - 1))) { ++ len = ROUNDUP(len, ALIGNMENT); ++ } ++ ++ /* Hardware extention tag */ ++ /* 2byte frame length, 1byte-, 1byte frame flag, ++ * 2byte-hdrlength, 2byte padlenght ++ */ ++ hwheader1 = (act_len - SDPCM_FRAMETAG_LEN) | (1 << 24); ++ hwheader2 = (len - act_len) << 16; ++ htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN); ++ htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4); ++ ++ /* Post the frame pointer to sdio glom array */ ++ dhd_bcmsdh_glom_post(bus, frame, len); ++ /* Save the pkt pointer in bus glom array */ ++ bus->glom_pkt_arr[bus->glom_cnt] = pkt; ++ bus->glom_cnt++; ++ bus->glom_total_len += len; ++ ++ /* Update the total length on the first pkt */ ++ frame_tmp = (uint8*)PKTDATA(osh, bus->glom_pkt_arr[0]); ++ *(uint16*)frame_tmp = htol16(bus->glom_total_len); ++ *(((uint16*)frame_tmp) + 1) = htol16(~bus->glom_total_len); ++ } ++ } else ++#endif /* BCMSDIOH_TXGLOM */ ++ { ++ /* Software tag: channel, sequence number, data offset */ ++ swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq | ++ (((pad1 + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); ++ htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN); ++ htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); ++ ++#ifdef DHD_DEBUG ++ if (PKTPRIO(pkt) < ARRAYSIZE(tx_packets)) { ++ tx_packets[PKTPRIO(pkt)]++; ++ } ++ if (DHD_BYTES_ON() && ++ (((DHD_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) || ++ (DHD_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) { ++ prhex("Tx Frame", frame, len); ++ } else if (DHD_HDRS_ON()) { ++ prhex("TxHdr", frame, MIN(len, 16)); ++ } ++#endif ++ ++ /* Raise len to next SDIO block to eliminate tail command */ ++ if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { ++ uint16 pad2 = bus->blocksize - (len % bus->blocksize); ++ if ((pad2 <= bus->roundup) && (pad2 < bus->blocksize)) ++#ifdef NOTUSED ++ if (pad2 <= PKTTAILROOM(osh, pkt)) ++#endif /* NOTUSED */ ++ len += pad2; ++ } else if (len % DHD_SDALIGN) { ++ len += DHD_SDALIGN - (len % DHD_SDALIGN); ++ } ++ ++ /* Some controllers have trouble with odd bytes -- round to even */ ++ if (forcealign && (len & (ALIGNMENT - 1))) { ++#ifdef NOTUSED ++ if (PKTTAILROOM(osh, pkt)) ++#endif ++ len = ROUNDUP(len, ALIGNMENT); ++#ifdef NOTUSED ++ else ++ AP6210_DEBUG("%s: sending unrounded %d-byte packet\n", __FUNCTION__, len); ++#endif ++ } ++ } ++ ++ do { ++ ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, ++ frame, len, pkt, NULL, NULL); ++ bus->f2txdata++; ++ ASSERT(ret != BCME_PENDING); ++ ++ if (ret == BCME_NODEVICE) { ++ AP6210_ERR("%s: Device asleep already\n", __FUNCTION__); ++ } else if (ret < 0) { ++ /* On failure, abort the command and terminate the frame */ ++ AP6210_ERR("%s: sdio error %d, abort command and terminate frame.\n", ++ __FUNCTION__, ret); ++ bus->tx_sderrs++; ++ ++ bcmsdh_abort(sdh, SDIO_FUNC_2); ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, ++ SFC_WF_TERM, NULL); ++ bus->f1regdata++; ++ ++ for (i = 0; i < 3; i++) { ++ uint8 hi, lo; ++ hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCHI, NULL); ++ lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCLO, NULL); ++ bus->f1regdata += 2; ++ if ((hi == 0) && (lo == 0)) ++ break; ++ } ++ } ++ if (ret == 0) { ++#ifdef BCMSDIOH_TXGLOM ++ if (bus->glom_enable) { ++ bus->tx_seq = (bus->tx_seq + bus->glom_cnt) % SDPCM_SEQUENCE_WRAP; ++ } else ++#endif ++ { ++ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; ++ } ++ } ++ } while ((ret < 0) && retrydata && retries++ < TXRETRIES); ++ ++done: ++ ++#ifdef BCMSDIOH_TXGLOM ++ if (bus->glom_enable) { ++ dhd_bcmsdh_glom_clear(bus); ++ pkt_cnt = bus->glom_cnt; ++ } else ++#endif ++ { ++ pkt_cnt = 1; ++ } ++ /* restore pkt buffer pointer before calling tx complete routine */ ++ while (pkt_cnt) { ++#ifdef BCMSDIOH_TXGLOM ++ uint32 doff; ++ if (bus->glom_enable) { ++ pkt = bus->glom_pkt_arr[bus->glom_cnt - pkt_cnt]; ++ frame = (uint8*)PKTDATA(osh, pkt); ++ doff = ltoh32_ua(frame + SDPCM_FRAMETAG_LEN + SDPCM_HWEXT_LEN); ++ doff = (doff & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT; ++ PKTPULL(osh, pkt, doff); ++ } else ++#endif ++ { ++ PKTPULL(osh, pkt, SDPCM_HDRLEN + pad1); ++ } ++#ifdef PROP_TXSTATUS ++ if (bus->dhd->wlfc_state) { ++ dhd_os_sdunlock(bus->dhd); ++ dhd_wlfc_txcomplete(bus->dhd, pkt, ret == 0, FALSE); ++ dhd_os_sdlock(bus->dhd); ++ } else { ++#endif /* PROP_TXSTATUS */ ++#ifdef SDTEST ++ if (chan != SDPCM_TEST_CHANNEL) { ++ dhd_txcomplete(bus->dhd, pkt, ret != 0); ++ } ++#else /* SDTEST */ ++ dhd_txcomplete(bus->dhd, pkt, ret != 0); ++#endif /* SDTEST */ ++ if (free_pkt) ++ PKTFREE(osh, pkt, TRUE); ++ ++#ifdef PROP_TXSTATUS ++ } ++#endif ++ pkt_cnt--; ++ } ++ ++#ifdef BCMSDIOH_TXGLOM ++ /* Reset the glom array */ ++ if (bus->glom_enable) { ++ bus->glom_cnt = 0; ++ bus->glom_total_len = 0; ++ } ++#endif ++ return ret; ++} ++ ++int ++dhd_bus_txdata(struct dhd_bus *bus, void *pkt, bool wlfc_locked) ++{ ++ int ret = BCME_ERROR; ++ osl_t *osh; ++ uint datalen, prec; ++#ifdef DHD_TX_DUMP ++ uint8 *dump_data; ++ uint16 protocol; ++#ifdef DHD_TX_FULL_DUMP ++ int i; ++#endif /* DHD_TX_FULL_DUMP */ ++#endif /* DHD_TX_DUMP */ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ osh = bus->dhd->osh; ++ datalen = PKTLEN(osh, pkt); ++ ++#ifdef SDTEST ++ /* Push the test header if doing loopback */ ++ if (bus->ext_loop) { ++ uint8* data; ++ PKTPUSH(osh, pkt, SDPCM_TEST_HDRLEN); ++ data = PKTDATA(osh, pkt); ++ *data++ = SDPCM_TEST_ECHOREQ; ++ *data++ = (uint8)bus->loopid++; ++ *data++ = (datalen >> 0); ++ *data++ = (datalen >> 8); ++ datalen += SDPCM_TEST_HDRLEN; ++ } ++#endif /* SDTEST */ ++ ++#ifdef DHD_TX_DUMP ++ dump_data = PKTDATA(osh, pkt); ++ dump_data += 4; /* skip 4 bytes header */ ++ protocol = (dump_data[12] << 8) | dump_data[13]; ++#ifdef DHD_TX_FULL_DUMP ++ AP6210_DEBUG("TX DUMP\n"); ++ ++ for (i = 0; i < (datalen - 4); i++) { ++ DHD_CONT("%02X ", dump_data[i]); ++ if ((i & 15) == 15) ++ DHD_CONT("\n"); ++ } ++ AP6210_DEBUG("\n"); ++ ++#endif /* DHD_TX_FULL_DUMP */ ++ if (protocol == ETHER_TYPE_802_1X) { ++ AP6210_DEBUG("ETHER_TYPE_802_1X: ver %d, type %d, replay %d\n", ++ dump_data[14], dump_data[15], dump_data[30]); ++ } ++#endif /* DHD_TX_DUMP */ ++ ++ /* Add space for the header */ ++ PKTPUSH(osh, pkt, SDPCM_HDRLEN); ++ ASSERT(ISALIGNED((uintptr)PKTDATA(osh, pkt), 2)); ++ ++ prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK)); ++#ifndef DHDTHREAD ++ /* Lock: we're about to use shared data/code (and SDIO) */ ++ dhd_os_sdlock(bus->dhd); ++#endif /* DHDTHREAD */ ++ ++ /* Check for existing queue, current flow-control, pending event, or pending clock */ ++ if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq) || bus->dpc_sched || ++ (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) || ++ (bus->clkstate != CLK_AVAIL)) { ++ AP6210_DEBUG("%s: deferring pktq len %d\n", __FUNCTION__, ++ pktq_len(&bus->txq)); ++ bus->fcqueued++; ++ ++ /* Priority based enq */ ++ dhd_os_sdlock_txq(bus->dhd); ++ if (dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec) == FALSE) { ++ PKTPULL(osh, pkt, SDPCM_HDRLEN); ++#ifndef DHDTHREAD ++ /* Need to also release txqlock before releasing sdlock. ++ * This thread still has txqlock and releases sdlock. ++ * Deadlock happens when dpc() grabs sdlock first then ++ * attempts to grab txqlock. ++ */ ++ dhd_os_sdunlock_txq(bus->dhd); ++ dhd_os_sdunlock(bus->dhd); ++#endif ++#ifdef PROP_TXSTATUS ++ if (bus->dhd->wlfc_state) ++ dhd_wlfc_txcomplete(bus->dhd, pkt, FALSE, wlfc_locked); ++ else ++#endif ++ dhd_txcomplete(bus->dhd, pkt, FALSE); ++#ifndef DHDTHREAD ++ dhd_os_sdlock(bus->dhd); ++ dhd_os_sdlock_txq(bus->dhd); ++#endif ++#ifdef PROP_TXSTATUS ++ /* let the caller decide whether to free the packet */ ++ if (!bus->dhd->wlfc_state) ++#endif ++ PKTFREE(osh, pkt, TRUE); ++ ret = BCME_NORESOURCE; ++ } ++ else ++ ret = BCME_OK; ++ dhd_os_sdunlock_txq(bus->dhd); ++ ++ if ((pktq_len(&bus->txq) >= FCHI) && dhd_doflow) ++ dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON); ++ ++#ifdef DHD_DEBUG ++ if (pktq_plen(&bus->txq, prec) > qcount[prec]) ++ qcount[prec] = pktq_plen(&bus->txq, prec); ++#endif ++ /* Schedule DPC if needed to send queued packet(s) */ ++ if (dhd_deferred_tx && !bus->dpc_sched) { ++ bus->dpc_sched = TRUE; ++ dhd_sched_dpc(bus->dhd); ++ } ++ } else { ++#ifdef DHDTHREAD ++ /* Lock: we're about to use shared data/code (and SDIO) */ ++ dhd_os_sdlock(bus->dhd); ++#endif /* DHDTHREAD */ ++ ++ /* Otherwise, send it now */ ++ BUS_WAKE(bus); ++ /* Make sure back plane ht clk is on, no pending allowed */ ++ dhdsdio_clkctl(bus, CLK_AVAIL, TRUE); ++#ifndef SDTEST ++ ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, TRUE, FALSE); ++#else ++ ret = dhdsdio_txpkt(bus, pkt, ++ (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL), TRUE, FALSE); ++#endif ++ if (ret) ++ bus->dhd->tx_errors++; ++ else ++ bus->dhd->dstats.tx_bytes += datalen; ++ ++ if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { ++ bus->activity = FALSE; ++ dhdsdio_clkctl(bus, CLK_NONE, TRUE); ++ } ++ ++#ifdef DHDTHREAD ++ dhd_os_sdunlock(bus->dhd); ++#endif /* DHDTHREAD */ ++ } ++ ++#ifndef DHDTHREAD ++ dhd_os_sdunlock(bus->dhd); ++#endif /* DHDTHREAD */ ++ ++ return ret; ++} ++ ++static uint ++dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes) ++{ ++ void *pkt; ++ uint32 intstatus = 0; ++ uint retries = 0; ++ int ret = 0, prec_out; ++ uint cnt = 0; ++ uint datalen; ++ uint8 tx_prec_map; ++#ifdef BCMSDIOH_TXGLOM ++ uint i; ++ uint8 glom_cnt; ++#endif ++ ++ dhd_pub_t *dhd = bus->dhd; ++ sdpcmd_regs_t *regs = bus->regs; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (!KSO_ENAB(bus)) { ++ AP6210_DEBUG("%s: Device asleep\n", __FUNCTION__); ++ return BCME_NODEVICE; ++ } ++ ++ tx_prec_map = ~bus->flowcontrol; ++ ++ /* Send frames until the limit or some other event */ ++ for (cnt = 0; (cnt < maxframes) && DATAOK(bus); cnt++) { ++#ifdef BCMSDIOH_TXGLOM ++ if (bus->glom_enable) { ++ glom_cnt = MIN(DATABUFCNT(bus), bus->glomsize); ++ glom_cnt = MIN(glom_cnt, pktq_mlen(&bus->txq, tx_prec_map)); ++ glom_cnt = MIN(glom_cnt, maxframes-cnt); ++ ++ /* Limiting the size to 2pkts in case of copy */ ++ if (bus->glom_mode == SDPCM_TXGLOM_CPY) ++ glom_cnt = MIN(glom_cnt, 5); ++ ++ if (glom_cnt == 0) ++ break; ++ datalen = 0; ++ for (i = 0; i < glom_cnt; i++) { ++ dhd_os_sdlock_txq(bus->dhd); ++ if ((pkt = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out)) == NULL) { ++ /* This case should not happen */ ++ AP6210_DEBUG("No pkts in the queue for glomming\n"); ++ dhd_os_sdunlock_txq(bus->dhd); ++ break; ++ } ++ dhd_os_sdunlock_txq(bus->dhd); ++ ++ datalen += (PKTLEN(bus->dhd->osh, pkt) - SDPCM_HDRLEN); ++#ifndef SDTEST ++ ret = dhdsdio_txpkt(bus, ++ pkt, ++ SDPCM_DATA_CHANNEL, ++ TRUE, ++ (i == (glom_cnt-1))? FALSE: TRUE); ++#else ++ ret = dhdsdio_txpkt(bus, ++ pkt, ++ (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL), ++ TRUE, ++ (i == (glom_cnt-1))? FALSE: TRUE); ++#endif ++ } ++ cnt += i-1; ++ } else ++#endif /* BCMSDIOH_TXGLOM */ ++ { ++ dhd_os_sdlock_txq(bus->dhd); ++ if ((pkt = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out)) == NULL) { ++ dhd_os_sdunlock_txq(bus->dhd); ++ break; ++ } ++ dhd_os_sdunlock_txq(bus->dhd); ++ datalen = PKTLEN(bus->dhd->osh, pkt) - SDPCM_HDRLEN; ++ ++#ifndef SDTEST ++ ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, TRUE, FALSE); ++#else ++ ret = dhdsdio_txpkt(bus, ++ pkt, ++ (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL), ++ TRUE, ++ FALSE); ++#endif ++ } ++ ++ if (ret) ++ bus->dhd->tx_errors++; ++ else ++ bus->dhd->dstats.tx_bytes += datalen; ++ ++ /* In poll mode, need to check for other events */ ++ if (!bus->intr && cnt) ++ { ++ /* Check device status, signal pending interrupt */ ++ R_SDREG(intstatus, ®s->intstatus, retries); ++ bus->f2txdata++; ++ if (bcmsdh_regfail(bus->sdh)) ++ break; ++ if (intstatus & bus->hostintmask) ++ bus->ipend = TRUE; ++ } ++ } ++ ++ /* Deflow-control stack if needed */ ++ if (dhd_doflow && dhd->up && (dhd->busstate == DHD_BUS_DATA) && ++ dhd->txoff && (pktq_len(&bus->txq) < FCLOW)) ++ dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF); ++ ++ return cnt; ++} ++ ++int ++dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) ++{ ++ uint8 *frame; ++ uint16 len; ++ uint32 swheader; ++ uint retries = 0; ++ bcmsdh_info_t *sdh = bus->sdh; ++ uint8 doff = 0; ++ int ret = -1; ++ int i; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (bus->dhd->dongle_reset) ++ return -EIO; ++ ++ /* Back the pointer to make a room for bus header */ ++ frame = msg - SDPCM_HDRLEN; ++ len = (msglen += SDPCM_HDRLEN); ++ ++ /* Add alignment padding (optional for ctl frames) */ ++ if (dhd_alignctl) { ++ if ((doff = ((uintptr)frame % DHD_SDALIGN))) { ++ frame -= doff; ++ len += doff; ++ msglen += doff; ++ bzero(frame, doff + SDPCM_HDRLEN); ++ } ++ ASSERT(doff < DHD_SDALIGN); ++ } ++ doff += SDPCM_HDRLEN; ++ ++ /* Round send length to next SDIO block */ ++ if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { ++ uint16 pad = bus->blocksize - (len % bus->blocksize); ++ if ((pad <= bus->roundup) && (pad < bus->blocksize)) ++ len += pad; ++ } else if (len % DHD_SDALIGN) { ++ len += DHD_SDALIGN - (len % DHD_SDALIGN); ++ } ++ ++ /* Satisfy length-alignment requirements */ ++ if (forcealign && (len & (ALIGNMENT - 1))) ++ len = ROUNDUP(len, ALIGNMENT); ++ ++ ASSERT(ISALIGNED((uintptr)frame, 2)); ++ ++ ++ /* Need to lock here to protect txseq and SDIO tx calls */ ++ dhd_os_sdlock(bus->dhd); ++ ++ BUS_WAKE(bus); ++ ++ /* Make sure backplane clock is on */ ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); ++ ++ /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ ++ *(uint16*)frame = htol16((uint16)msglen); ++ *(((uint16*)frame) + 1) = htol16(~msglen); ++ ++#ifdef BCMSDIOH_TXGLOM ++ if (bus->glom_enable) { ++ uint32 hwheader1, hwheader2; ++ /* Software tag: channel, sequence number, data offset */ ++ swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) ++ | bus->tx_seq ++ | ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); ++ htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN + SDPCM_HWEXT_LEN); ++ htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN ++ + SDPCM_HWEXT_LEN + sizeof(swheader)); ++ ++ hwheader1 = (msglen - SDPCM_FRAMETAG_LEN) | (1 << 24); ++ hwheader2 = (len - (msglen)) << 16; ++ htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN); ++ htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4); ++ ++ *(uint16*)frame = htol16(len); ++ *(((uint16*)frame) + 1) = htol16(~(len)); ++ } else ++#endif /* BCMSDIOH_TXGLOM */ ++ { ++ /* Software tag: channel, sequence number, data offset */ ++ swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) ++ | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); ++ htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN); ++ htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); ++ } ++ if (!TXCTLOK(bus)) { ++ AP6210_DEBUG("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n", ++ __FUNCTION__, bus->tx_max, bus->tx_seq); ++ bus->ctrl_frame_stat = TRUE; ++ /* Send from dpc */ ++ bus->ctrl_frame_buf = frame; ++ bus->ctrl_frame_len = len; ++ ++ if (!bus->dpc_sched) { ++ bus->dpc_sched = TRUE; ++ dhd_sched_dpc(bus->dhd); ++ } ++ if (bus->ctrl_frame_stat) { ++ dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat); ++ } ++ ++ if (bus->ctrl_frame_stat == FALSE) { ++ AP6210_DEBUG("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__); ++ ret = 0; ++ } else { ++ bus->dhd->txcnt_timeout++; ++ if (!bus->dhd->hang_was_sent) { ++ AP6210_DEBUG("%s: ctrl_frame_stat == TRUE txcnt_timeout=%d\n", ++ __FUNCTION__, bus->dhd->txcnt_timeout); ++ } ++ ret = -1; ++ bus->ctrl_frame_stat = FALSE; ++ goto done; ++ } ++ } ++ ++ bus->dhd->txcnt_timeout = 0; ++ ++ if (ret == -1) { ++#ifdef DHD_DEBUG ++ if (DHD_BYTES_ON() && DHD_CTL_ON()) { ++ prhex("Tx Frame", frame, len); ++ } else if (DHD_HDRS_ON()) { ++ prhex("TxHdr", frame, MIN(len, 16)); ++ } ++#endif ++ ++ do { ++ ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, ++ frame, len, NULL, NULL, NULL); ++ ASSERT(ret != BCME_PENDING); ++ ++ if (ret == BCME_NODEVICE) { ++ AP6210_DEBUG("%s: Device asleep already\n", __FUNCTION__); ++ } else if (ret < 0) { ++ /* On failure, abort the command and terminate the frame */ ++ AP6210_DEBUG("%s: sdio error %d, abort command and terminate frame.\n", ++ __FUNCTION__, ret); ++ bus->tx_sderrs++; ++ ++ bcmsdh_abort(sdh, SDIO_FUNC_2); ++ ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, ++ SFC_WF_TERM, NULL); ++ bus->f1regdata++; ++ ++ for (i = 0; i < 3; i++) { ++ uint8 hi, lo; ++ hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCHI, NULL); ++ lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCLO, NULL); ++ bus->f1regdata += 2; ++ if ((hi == 0) && (lo == 0)) ++ break; ++ } ++ } ++ if (ret == 0) { ++ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; ++ } ++ } while ((ret < 0) && retries++ < TXRETRIES); ++ } ++ ++done: ++ if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { ++ bus->activity = FALSE; ++ dhdsdio_clkctl(bus, CLK_NONE, TRUE); ++ } ++ ++ dhd_os_sdunlock(bus->dhd); ++ ++ if (ret) ++ bus->dhd->tx_ctlerrs++; ++ else ++ bus->dhd->tx_ctlpkts++; ++ ++ if (bus->dhd->txcnt_timeout >= MAX_CNTL_TIMEOUT) ++ return -ETIMEDOUT; ++ ++ return ret ? -EIO : 0; ++} ++ ++int ++dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) ++{ ++ int timeleft; ++ uint rxlen = 0; ++ bool pending; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (bus->dhd->dongle_reset) ++ return -EIO; ++ ++ /* Wait until control frame is available */ ++ timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, &pending); ++ ++ dhd_os_sdlock(bus->dhd); ++ rxlen = bus->rxlen; ++ bcopy(bus->rxctl, msg, MIN(msglen, rxlen)); ++ bus->rxlen = 0; ++ dhd_os_sdunlock(bus->dhd); ++ ++ if (rxlen) { ++ AP6210_DEBUG("%s: resumed on rxctl frame, got %d expected %d\n", ++ __FUNCTION__, rxlen, msglen); ++ } else if (timeleft == 0) { ++#ifdef DHD_DEBUG ++ uint32 status, retry = 0; ++ R_SDREG(status, &bus->regs->intstatus, retry); ++ AP6210_DEBUG("%s: resumed on timeout, INT status=0x%08X\n", ++ __FUNCTION__, status); ++#else ++ AP6210_DEBUG("%s: resumed on timeout\n", __FUNCTION__); ++#endif /* DHD_DEBUG */ ++#ifdef DHD_DEBUG ++ dhd_os_sdlock(bus->dhd); ++ dhdsdio_checkdied(bus, NULL, 0); ++ dhd_os_sdunlock(bus->dhd); ++#endif /* DHD_DEBUG */ ++ } else if (pending == TRUE) { ++ /* signal pending */ ++ AP6210_DEBUG("%s: signal pending\n", __FUNCTION__); ++ return -EINTR; ++ } else { ++ AP6210_DEBUG("%s: resumed for unknown reason?\n", __FUNCTION__); ++#ifdef DHD_DEBUG ++ dhd_os_sdlock(bus->dhd); ++ dhdsdio_checkdied(bus, NULL, 0); ++ dhd_os_sdunlock(bus->dhd); ++#endif /* DHD_DEBUG */ ++ } ++ if (timeleft == 0) { ++ bus->dhd->rxcnt_timeout++; ++ AP6210_DEBUG("%s: rxcnt_timeout=%d\n", __FUNCTION__, bus->dhd->rxcnt_timeout); ++ } ++ else ++ bus->dhd->rxcnt_timeout = 0; ++ ++ if (rxlen) ++ bus->dhd->rx_ctlpkts++; ++ else ++ bus->dhd->rx_ctlerrs++; ++ ++ if (bus->dhd->rxcnt_timeout >= MAX_CNTL_TIMEOUT) ++ return -ETIMEDOUT; ++ ++ if (bus->dhd->dongle_trap_occured) ++ return -EREMOTEIO; ++ ++ return rxlen ? (int)rxlen : -EIO; ++} ++ ++/* IOVar table */ ++enum { ++ IOV_INTR = 1, ++ IOV_POLLRATE, ++ IOV_SDREG, ++ IOV_SBREG, ++ IOV_SDCIS, ++ IOV_MEMBYTES, ++ IOV_MEMSIZE, ++#ifdef DHD_DEBUG ++ IOV_CHECKDIED, ++ IOV_SERIALCONS, ++#endif /* DHD_DEBUG */ ++ IOV_SET_DOWNLOAD_STATE, ++ IOV_SOCRAM_STATE, ++ IOV_FORCEEVEN, ++ IOV_SDIOD_DRIVE, ++ IOV_READAHEAD, ++ IOV_SDRXCHAIN, ++ IOV_ALIGNCTL, ++ IOV_SDALIGN, ++ IOV_DEVRESET, ++ IOV_CPU, ++#if defined(SDIO_CRC_ERROR_FIX) ++ IOV_WATERMARK, ++ IOV_MESBUSYCTRL, ++#endif /* SDIO_CRC_ERROR_FIX */ ++#ifdef SDTEST ++ IOV_PKTGEN, ++ IOV_EXTLOOP, ++#endif /* SDTEST */ ++ IOV_SPROM, ++ IOV_TXBOUND, ++ IOV_RXBOUND, ++ IOV_TXMINMAX, ++ IOV_IDLETIME, ++ IOV_IDLECLOCK, ++ IOV_SD1IDLE, ++ IOV_SLEEP, ++ IOV_DONGLEISOLATION, ++ IOV_KSO, ++ IOV_DEVSLEEP, ++ IOV_DEVCAP, ++ IOV_VARS, ++#ifdef SOFTAP ++ IOV_FWPATH, ++#endif ++ IOV_TXGLOMSIZE, ++ IOV_TXGLOMMODE ++}; ++ ++const bcm_iovar_t dhdsdio_iovars[] = { ++ {"intr", IOV_INTR, 0, IOVT_BOOL, 0 }, ++ {"sleep", IOV_SLEEP, 0, IOVT_BOOL, 0 }, ++ {"pollrate", IOV_POLLRATE, 0, IOVT_UINT32, 0 }, ++ {"idletime", IOV_IDLETIME, 0, IOVT_INT32, 0 }, ++ {"idleclock", IOV_IDLECLOCK, 0, IOVT_INT32, 0 }, ++ {"sd1idle", IOV_SD1IDLE, 0, IOVT_BOOL, 0 }, ++ {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int) }, ++ {"memsize", IOV_MEMSIZE, 0, IOVT_UINT32, 0 }, ++ {"dwnldstate", IOV_SET_DOWNLOAD_STATE, 0, IOVT_BOOL, 0 }, ++ {"socram_state", IOV_SOCRAM_STATE, 0, IOVT_BOOL, 0 }, ++ {"vars", IOV_VARS, 0, IOVT_BUFFER, 0 }, ++ {"sdiod_drive", IOV_SDIOD_DRIVE, 0, IOVT_UINT32, 0 }, ++ {"readahead", IOV_READAHEAD, 0, IOVT_BOOL, 0 }, ++ {"sdrxchain", IOV_SDRXCHAIN, 0, IOVT_BOOL, 0 }, ++ {"alignctl", IOV_ALIGNCTL, 0, IOVT_BOOL, 0 }, ++ {"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0 }, ++ {"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0 }, ++#ifdef DHD_DEBUG ++ {"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, ++ {"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, ++ {"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN }, ++ {"forcealign", IOV_FORCEEVEN, 0, IOVT_BOOL, 0 }, ++ {"txbound", IOV_TXBOUND, 0, IOVT_UINT32, 0 }, ++ {"rxbound", IOV_RXBOUND, 0, IOVT_UINT32, 0 }, ++ {"txminmax", IOV_TXMINMAX, 0, IOVT_UINT32, 0 }, ++ {"cpu", IOV_CPU, 0, IOVT_BOOL, 0 }, ++#ifdef DHD_DEBUG ++ {"checkdied", IOV_CHECKDIED, 0, IOVT_BUFFER, 0 }, ++ {"serial", IOV_SERIALCONS, 0, IOVT_UINT32, 0 }, ++#endif /* DHD_DEBUG */ ++#endif /* DHD_DEBUG */ ++#ifdef SDTEST ++ {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0 }, ++ {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(dhd_pktgen_t) }, ++#endif /* SDTEST */ ++#if defined(SDIO_CRC_ERROR_FIX) ++ {"watermark", IOV_WATERMARK, 0, IOVT_UINT32, 0 }, ++ {"mesbusyctrl", IOV_MESBUSYCTRL, 0, IOVT_UINT32, 0 }, ++#endif /* SDIO_CRC_ERROR_FIX */ ++ {"devcap", IOV_DEVCAP, 0, IOVT_UINT32, 0 }, ++ {"dngl_isolation", IOV_DONGLEISOLATION, 0, IOVT_UINT32, 0 }, ++ {"kso", IOV_KSO, 0, IOVT_UINT32, 0 }, ++ {"devsleep", IOV_DEVSLEEP, 0, IOVT_UINT32, 0 }, ++#ifdef SOFTAP ++ {"fwpath", IOV_FWPATH, 0, IOVT_BUFFER, 0 }, ++#endif ++ {"txglomsize", IOV_TXGLOMSIZE, 0, IOVT_UINT32, 0 }, ++ {"txglommode", IOV_TXGLOMMODE, 0, IOVT_UINT32, 0 }, ++ {NULL, 0, 0, 0, 0 } ++}; ++ ++static void ++dhd_dump_pct(struct bcmstrbuf *strbuf, char *desc, uint num, uint div) ++{ ++ uint q1, q2; ++ ++ if (!div) { ++ bcm_bprintf(strbuf, "%s N/A", desc); ++ } else { ++ q1 = num / div; ++ q2 = (100 * (num - (q1 * div))) / div; ++ bcm_bprintf(strbuf, "%s %d.%02d", desc, q1, q2); ++ } ++} ++ ++void ++dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) ++{ ++ dhd_bus_t *bus = dhdp->bus; ++ ++ bcm_bprintf(strbuf, "Bus SDIO structure:\n"); ++ bcm_bprintf(strbuf, "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n", ++ bus->hostintmask, bus->intstatus, bus->sdpcm_ver); ++ bcm_bprintf(strbuf, "fcstate %d qlen %d tx_seq %d, max %d, rxskip %d rxlen %d rx_seq %d\n", ++ bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max, bus->rxskip, ++ bus->rxlen, bus->rx_seq); ++ bcm_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n", ++ bus->intr, bus->intrcount, bus->lastintrs, bus->spurious); ++ bcm_bprintf(strbuf, "pollrate %d pollcnt %d regfails %d\n", ++ bus->pollrate, bus->pollcnt, bus->regfails); ++ ++ bcm_bprintf(strbuf, "\nAdditional counters:\n"); ++ bcm_bprintf(strbuf, "tx_sderrs %d fcqueued %d rxrtx %d rx_toolong %d rxc_errors %d\n", ++ bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong, ++ bus->rxc_errors); ++ bcm_bprintf(strbuf, "rx_hdrfail %d badhdr %d badseq %d\n", ++ bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq); ++ bcm_bprintf(strbuf, "fc_rcvd %d, fc_xoff %d, fc_xon %d\n", ++ bus->fc_rcvd, bus->fc_xoff, bus->fc_xon); ++ bcm_bprintf(strbuf, "rxglomfail %d, rxglomframes %d, rxglompkts %d\n", ++ bus->rxglomfail, bus->rxglomframes, bus->rxglompkts); ++ bcm_bprintf(strbuf, "f2rx (hdrs/data) %d (%d/%d), f2tx %d f1regs %d\n", ++ (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs, bus->f2rxdata, ++ bus->f2txdata, bus->f1regdata); ++ { ++ dhd_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->dhd->rx_packets, ++ (bus->f2rxhdrs + bus->f2rxdata)); ++ dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->rx_packets, bus->f1regdata); ++ dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->rx_packets, ++ (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata)); ++ dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->rx_packets, bus->intrcount); ++ bcm_bprintf(strbuf, "\n"); ++ ++ dhd_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts), ++ bus->dhd->rx_packets); ++ dhd_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts, bus->rxglomframes); ++ bcm_bprintf(strbuf, "\n"); ++ ++ dhd_dump_pct(strbuf, "Tx: pkts/f2wr", bus->dhd->tx_packets, bus->f2txdata); ++ dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->tx_packets, bus->f1regdata); ++ dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->tx_packets, ++ (bus->f2txdata + bus->f1regdata)); ++ dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->tx_packets, bus->intrcount); ++ bcm_bprintf(strbuf, "\n"); ++ ++ dhd_dump_pct(strbuf, "Total: pkts/f2rw", ++ (bus->dhd->tx_packets + bus->dhd->rx_packets), ++ (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata)); ++ dhd_dump_pct(strbuf, ", pkts/f1sd", ++ (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->f1regdata); ++ dhd_dump_pct(strbuf, ", pkts/sd", ++ (bus->dhd->tx_packets + bus->dhd->rx_packets), ++ (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata)); ++ dhd_dump_pct(strbuf, ", pkts/int", ++ (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->intrcount); ++ bcm_bprintf(strbuf, "\n\n"); ++ } ++ ++#ifdef SDTEST ++ if (bus->pktgen_count) { ++ bcm_bprintf(strbuf, "pktgen config and count:\n"); ++ bcm_bprintf(strbuf, "freq %d count %d print %d total %d min %d len %d\n", ++ bus->pktgen_freq, bus->pktgen_count, bus->pktgen_print, ++ bus->pktgen_total, bus->pktgen_minlen, bus->pktgen_maxlen); ++ bcm_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n", ++ bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail); ++ } ++#endif /* SDTEST */ ++#ifdef DHD_DEBUG ++ bcm_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n", ++ bus->dpc_sched, (bcmsdh_intr_pending(bus->sdh) ? " " : " not ")); ++ bcm_bprintf(strbuf, "blocksize %d roundup %d\n", bus->blocksize, bus->roundup); ++#endif /* DHD_DEBUG */ ++ bcm_bprintf(strbuf, "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n", ++ bus->clkstate, bus->activity, bus->idletime, bus->idlecount, bus->sleeping); ++} ++ ++void ++dhd_bus_clearcounts(dhd_pub_t *dhdp) ++{ ++ dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus; ++ ++ bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0; ++ bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0; ++ bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0; ++ bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0; ++ bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0; ++ bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0; ++} ++ ++#ifdef SDTEST ++static int ++dhdsdio_pktgen_get(dhd_bus_t *bus, uint8 *arg) ++{ ++ dhd_pktgen_t pktgen; ++ ++ pktgen.version = DHD_PKTGEN_VERSION; ++ pktgen.freq = bus->pktgen_freq; ++ pktgen.count = bus->pktgen_count; ++ pktgen.print = bus->pktgen_print; ++ pktgen.total = bus->pktgen_total; ++ pktgen.minlen = bus->pktgen_minlen; ++ pktgen.maxlen = bus->pktgen_maxlen; ++ pktgen.numsent = bus->pktgen_sent; ++ pktgen.numrcvd = bus->pktgen_rcvd; ++ pktgen.numfail = bus->pktgen_fail; ++ pktgen.mode = bus->pktgen_mode; ++ pktgen.stop = bus->pktgen_stop; ++ ++ bcopy(&pktgen, arg, sizeof(pktgen)); ++ ++ return 0; ++} ++ ++static int ++dhdsdio_pktgen_set(dhd_bus_t *bus, uint8 *arg) ++{ ++ dhd_pktgen_t pktgen; ++ uint oldcnt, oldmode; ++ ++ bcopy(arg, &pktgen, sizeof(pktgen)); ++ if (pktgen.version != DHD_PKTGEN_VERSION) ++ return BCME_BADARG; ++ ++ oldcnt = bus->pktgen_count; ++ oldmode = bus->pktgen_mode; ++ ++ bus->pktgen_freq = pktgen.freq; ++ bus->pktgen_count = pktgen.count; ++ bus->pktgen_print = pktgen.print; ++ bus->pktgen_total = pktgen.total; ++ bus->pktgen_minlen = pktgen.minlen; ++ bus->pktgen_maxlen = pktgen.maxlen; ++ bus->pktgen_mode = pktgen.mode; ++ bus->pktgen_stop = pktgen.stop; ++ ++ bus->pktgen_tick = bus->pktgen_ptick = 0; ++ bus->pktgen_prev_time = jiffies; ++ bus->pktgen_len = MAX(bus->pktgen_len, bus->pktgen_minlen); ++ bus->pktgen_len = MIN(bus->pktgen_len, bus->pktgen_maxlen); ++ ++ /* Clear counts for a new pktgen (mode change, or was stopped) */ ++ if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode)) { ++ bus->pktgen_sent = bus->pktgen_prev_sent = bus->pktgen_rcvd = 0; ++ bus->pktgen_prev_rcvd = bus->pktgen_fail = 0; ++ } ++ ++ return 0; ++} ++#endif /* SDTEST */ ++ ++static void ++dhdsdio_devram_remap(dhd_bus_t *bus, bool val) ++{ ++ uint8 enable, protect, remap; ++ ++ si_socdevram(bus->sih, FALSE, &enable, &protect, &remap); ++ remap = val ? TRUE : FALSE; ++ si_socdevram(bus->sih, TRUE, &enable, &protect, &remap); ++} ++ ++static int ++dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint size) ++{ ++ int bcmerror = 0; ++ uint32 sdaddr; ++ uint dsize; ++ ++ /* In remap mode, adjust address beyond socram and redirect ++ * to devram at SOCDEVRAM_BP_ADDR since remap address > orig_ramsize ++ * is not backplane accessible ++ */ ++ if (REMAP_ENAB(bus) && REMAP_ISADDR(bus, address)) { ++ address -= bus->orig_ramsize; ++ address += SOCDEVRAM_BP_ADDR; ++ } ++ ++ /* Determine initial transfer parameters */ ++ sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; ++ if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK) ++ dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr); ++ else ++ dsize = size; ++ ++ /* Set the backplane window to include the start address */ ++ if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) { ++ AP6210_ERR("%s: window change failed\n", __FUNCTION__); ++ goto xfer_done; ++ } ++ ++ /* Do the transfer(s) */ ++ while (size) { ++ AP6210_DEBUG("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n", ++ __FUNCTION__, (write ? "write" : "read"), dsize, sdaddr, ++ (address & SBSDIO_SBWINDOW_MASK)); ++ if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, data, dsize))) { ++ AP6210_ERR("%s: membytes transfer failed\n", __FUNCTION__); ++ break; ++ } ++ ++ /* Adjust for next transfer (if any) */ ++ if ((size -= dsize)) { ++ data += dsize; ++ address += dsize; ++ if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) { ++ AP6210_ERR("%s: window change failed\n", __FUNCTION__); ++ break; ++ } ++ sdaddr = 0; ++ dsize = MIN(SBSDIO_SB_OFT_ADDR_LIMIT, size); ++ } ++ ++ } ++ ++xfer_done: ++ /* Return the window to backplane enumeration space for core access */ ++ if (dhdsdio_set_siaddr_window(bus, bcmsdh_cur_sbwad(bus->sdh))) { ++ AP6210_ERR("%s: FAILED to set window back to 0x%x\n", __FUNCTION__, ++ bcmsdh_cur_sbwad(bus->sdh)); ++ } ++ ++ return bcmerror; ++} ++ ++#ifdef DHD_DEBUG ++static int ++dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh) ++{ ++ uint32 addr; ++ int rv, i; ++ uint32 shaddr = 0; ++ ++ shaddr = bus->dongle_ram_base + bus->ramsize - 4; ++ i = 0; ++ do { ++ /* Read last word in memory to determine address of sdpcm_shared structure */ ++ if ((rv = dhdsdio_membytes(bus, FALSE, shaddr, (uint8 *)&addr, 4)) < 0) ++ return rv; ++ ++ addr = ltoh32(addr); ++ ++ AP6210_DEBUG("sdpcm_shared address 0x%08X\n", addr); ++ ++ /* ++ * Check if addr is valid. ++ * NVRAM length at the end of memory should have been overwritten. ++ */ ++ if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) { ++ if ((bus->srmemsize > 0) && (i++ == 0)) { ++ shaddr -= bus->srmemsize; ++ } else { ++ AP6210_ERR("%s: address (0x%08x) of sdpcm_shared invalid\n", ++ __FUNCTION__, addr); ++ return BCME_ERROR; ++ } ++ } else ++ break; ++ } while (i < 2); ++ ++ /* Read hndrte_shared structure */ ++ if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)sh, sizeof(sdpcm_shared_t))) < 0) ++ return rv; ++ ++ /* Endianness */ ++ sh->flags = ltoh32(sh->flags); ++ sh->trap_addr = ltoh32(sh->trap_addr); ++ sh->assert_exp_addr = ltoh32(sh->assert_exp_addr); ++ sh->assert_file_addr = ltoh32(sh->assert_file_addr); ++ sh->assert_line = ltoh32(sh->assert_line); ++ sh->console_addr = ltoh32(sh->console_addr); ++ sh->msgtrace_addr = ltoh32(sh->msgtrace_addr); ++ ++ if ((sh->flags & SDPCM_SHARED_VERSION_MASK) == 3 && SDPCM_SHARED_VERSION == 1) ++ return BCME_OK; ++ ++ if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) { ++ AP6210_ERR("%s: sdpcm_shared version %d in dhd " ++ "is different than sdpcm_shared version %d in dongle\n", ++ __FUNCTION__, SDPCM_SHARED_VERSION, ++ sh->flags & SDPCM_SHARED_VERSION_MASK); ++ return BCME_ERROR; ++ } ++ ++ return BCME_OK; ++} ++ ++#define CONSOLE_LINE_MAX 192 ++ ++static int ++dhdsdio_readconsole(dhd_bus_t *bus) ++{ ++ dhd_console_t *c = &bus->console; ++ uint8 line[CONSOLE_LINE_MAX], ch; ++ uint32 n, idx, addr; ++ int rv; ++ ++ /* Don't do anything until FWREADY updates console address */ ++ if (bus->console_addr == 0) ++ return 0; ++ ++ if (!KSO_ENAB(bus)) ++ return 0; ++ ++ /* Read console log struct */ ++ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, log); ++ if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0) ++ return rv; ++ ++ /* Allocate console buffer (one time only) */ ++ if (c->buf == NULL) { ++ c->bufsize = ltoh32(c->log.buf_size); ++ if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL) ++ return BCME_NOMEM; ++ } ++ ++ idx = ltoh32(c->log.idx); ++ ++ /* Protect against corrupt value */ ++ if (idx > c->bufsize) ++ return BCME_ERROR; ++ ++ /* Skip reading the console buffer if the index pointer has not moved */ ++ if (idx == c->last) ++ return BCME_OK; ++ ++ /* Read the console buffer */ ++ addr = ltoh32(c->log.buf); ++ if ((rv = dhdsdio_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0) ++ return rv; ++ ++ while (c->last != idx) { ++ for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) { ++ if (c->last == idx) { ++ /* This would output a partial line. Instead, back up ++ * the buffer pointer and output this line next time around. ++ */ ++ if (c->last >= n) ++ c->last -= n; ++ else ++ c->last = c->bufsize - n; ++ goto break2; ++ } ++ ch = c->buf[c->last]; ++ c->last = (c->last + 1) % c->bufsize; ++ if (ch == '\n') ++ break; ++ line[n] = ch; ++ } ++ ++ if (n > 0) { ++ if (line[n - 1] == '\r') ++ n--; ++ line[n] = 0; ++ AP6210_DEBUG("CONSOLE: %s\n", line); ++ } ++ } ++break2: ++ ++ return BCME_OK; ++} ++ ++static int ++dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size) ++{ ++ int bcmerror = 0; ++ uint msize = 512; ++ char *mbuffer = NULL; ++ char *console_buffer = NULL; ++ uint maxstrlen = 256; ++ char *str = NULL; ++ trap_t tr; ++ sdpcm_shared_t sdpcm_shared; ++ struct bcmstrbuf strbuf; ++ uint32 console_ptr, console_size, console_index; ++ uint8 line[CONSOLE_LINE_MAX], ch; ++ uint32 n, i, addr; ++ int rv; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (data == NULL) { ++ /* ++ * Called after a rx ctrl timeout. "data" is NULL. ++ * allocate memory to trace the trap or assert. ++ */ ++ size = msize; ++ mbuffer = data = MALLOC(bus->dhd->osh, msize); ++ if (mbuffer == NULL) { ++ AP6210_ERR("%s: MALLOC(%d) failed \n", __FUNCTION__, msize); ++ bcmerror = BCME_NOMEM; ++ goto done; ++ } ++ } ++ ++ if ((str = MALLOC(bus->dhd->osh, maxstrlen)) == NULL) { ++ AP6210_ERR("%s: MALLOC(%d) failed \n", __FUNCTION__, maxstrlen); ++ bcmerror = BCME_NOMEM; ++ goto done; ++ } ++ ++ if ((bcmerror = dhdsdio_readshared(bus, &sdpcm_shared)) < 0) ++ goto done; ++ ++ bcm_binit(&strbuf, data, size); ++ ++ bcm_bprintf(&strbuf, "msgtrace address : 0x%08X\nconsole address : 0x%08X\n", ++ sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr); ++ ++ if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) { ++ /* NOTE: Misspelled assert is intentional - DO NOT FIX. ++ * (Avoids conflict with real asserts for programmatic parsing of output.) ++ */ ++ bcm_bprintf(&strbuf, "Assrt not built in dongle\n"); ++ } ++ ++ if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT|SDPCM_SHARED_TRAP)) == 0) { ++ /* NOTE: Misspelled assert is intentional - DO NOT FIX. ++ * (Avoids conflict with real asserts for programmatic parsing of output.) ++ */ ++ bcm_bprintf(&strbuf, "No trap%s in dongle", ++ (sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) ++ ?"/assrt" :""); ++ } else { ++ if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) { ++ /* Download assert */ ++ bcm_bprintf(&strbuf, "Dongle assert"); ++ if (sdpcm_shared.assert_exp_addr != 0) { ++ str[0] = '\0'; ++ if ((bcmerror = dhdsdio_membytes(bus, FALSE, ++ sdpcm_shared.assert_exp_addr, ++ (uint8 *)str, maxstrlen)) < 0) ++ goto done; ++ ++ str[maxstrlen - 1] = '\0'; ++ bcm_bprintf(&strbuf, " expr \"%s\"", str); ++ } ++ ++ if (sdpcm_shared.assert_file_addr != 0) { ++ str[0] = '\0'; ++ if ((bcmerror = dhdsdio_membytes(bus, FALSE, ++ sdpcm_shared.assert_file_addr, ++ (uint8 *)str, maxstrlen)) < 0) ++ goto done; ++ ++ str[maxstrlen - 1] = '\0'; ++ bcm_bprintf(&strbuf, " file \"%s\"", str); ++ } ++ ++ bcm_bprintf(&strbuf, " line %d ", sdpcm_shared.assert_line); ++ } ++ ++ if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) { ++ bus->dhd->dongle_trap_occured = TRUE; ++ if ((bcmerror = dhdsdio_membytes(bus, FALSE, ++ sdpcm_shared.trap_addr, ++ (uint8*)&tr, sizeof(trap_t))) < 0) ++ goto done; ++ ++ bcm_bprintf(&strbuf, ++ "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x," ++ "lp 0x%x, rpc 0x%x Trap offset 0x%x, " ++ "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, " ++ "r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n\n", ++ ltoh32(tr.type), ltoh32(tr.epc), ltoh32(tr.cpsr), ltoh32(tr.spsr), ++ ltoh32(tr.r13), ltoh32(tr.r14), ltoh32(tr.pc), ++ ltoh32(sdpcm_shared.trap_addr), ++ ltoh32(tr.r0), ltoh32(tr.r1), ltoh32(tr.r2), ltoh32(tr.r3), ++ ltoh32(tr.r4), ltoh32(tr.r5), ltoh32(tr.r6), ltoh32(tr.r7)); ++ ++ addr = sdpcm_shared.console_addr + OFFSETOF(hndrte_cons_t, log); ++ if ((rv = dhdsdio_membytes(bus, FALSE, addr, ++ (uint8 *)&console_ptr, sizeof(console_ptr))) < 0) ++ goto printbuf; ++ ++ addr = sdpcm_shared.console_addr + OFFSETOF(hndrte_cons_t, log.buf_size); ++ if ((rv = dhdsdio_membytes(bus, FALSE, addr, ++ (uint8 *)&console_size, sizeof(console_size))) < 0) ++ goto printbuf; ++ ++ addr = sdpcm_shared.console_addr + OFFSETOF(hndrte_cons_t, log.idx); ++ if ((rv = dhdsdio_membytes(bus, FALSE, addr, ++ (uint8 *)&console_index, sizeof(console_index))) < 0) ++ goto printbuf; ++ ++ console_ptr = ltoh32(console_ptr); ++ console_size = ltoh32(console_size); ++ console_index = ltoh32(console_index); ++ ++ if (console_size > CONSOLE_BUFFER_MAX || ++ !(console_buffer = MALLOC(bus->dhd->osh, console_size))) ++ goto printbuf; ++ ++ if ((rv = dhdsdio_membytes(bus, FALSE, console_ptr, ++ (uint8 *)console_buffer, console_size)) < 0) ++ goto printbuf; ++ ++ for (i = 0, n = 0; i < console_size; i += n + 1) { ++ for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) { ++ ch = console_buffer[(console_index + i + n) % console_size]; ++ if (ch == '\n') ++ break; ++ line[n] = ch; ++ } ++ ++ ++ if (n > 0) { ++ if (line[n - 1] == '\r') ++ n--; ++ line[n] = 0; ++ /* Don't use DHD_ERROR macro since we print ++ * a lot of information quickly. The macro ++ * will truncate a lot of the printfs ++ */ ++ ++ if (dhd_msg_level & DHD_ERROR_VAL) ++ AP6210_DEBUG("CONSOLE: %s\n", line); ++ } ++ } ++ } ++ } ++ ++printbuf: ++ if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) { ++ AP6210_DEBUG("%s: %s\n", __FUNCTION__, strbuf.origbuf); ++ } ++ ++ ++done: ++ if (mbuffer) ++ MFREE(bus->dhd->osh, mbuffer, msize); ++ if (str) ++ MFREE(bus->dhd->osh, str, maxstrlen); ++ if (console_buffer) ++ MFREE(bus->dhd->osh, console_buffer, console_size); ++ ++ return bcmerror; ++} ++#endif /* #ifdef DHD_DEBUG */ ++ ++ ++int ++dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len) ++{ ++ int bcmerror = BCME_OK; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ /* Basic sanity checks */ ++ if (bus->dhd->up) { ++ bcmerror = BCME_NOTDOWN; ++ goto err; ++ } ++ if (!len) { ++ bcmerror = BCME_BUFTOOSHORT; ++ goto err; ++ } ++ ++ /* Free the old ones and replace with passed variables */ ++ if (bus->vars) ++ MFREE(bus->dhd->osh, bus->vars, bus->varsz); ++ ++ bus->vars = MALLOC(bus->dhd->osh, len); ++ bus->varsz = bus->vars ? len : 0; ++ if (bus->vars == NULL) { ++ bcmerror = BCME_NOMEM; ++ goto err; ++ } ++ ++ /* Copy the passed variables, which should include the terminating double-null */ ++ bcopy(arg, bus->vars, bus->varsz); ++err: ++ return bcmerror; ++} ++ ++#ifdef DHD_DEBUG ++ ++#define CC_PLL_CHIPCTRL_SERIAL_ENAB (1 << 24) ++#define CC_CHIPCTRL_JTAG_SEL (1 << 3) ++#define CC_CHIPCTRL_GPIO_SEL (0x3) ++#define CC_PLL_CHIPCTRL_SERIAL_ENAB_4334 (1 << 28) ++ ++static int ++dhd_serialconsole(dhd_bus_t *bus, bool set, bool enable, int *bcmerror) ++{ ++ int int_val; ++ uint32 addr, data, uart_enab = 0; ++ uint32 jtag_sel = CC_CHIPCTRL_JTAG_SEL; ++ uint32 gpio_sel = CC_CHIPCTRL_GPIO_SEL; ++ ++ addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr); ++ data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data); ++ *bcmerror = 0; ++ ++ bcmsdh_reg_write(bus->sdh, addr, 4, 1); ++ if (bcmsdh_regfail(bus->sdh)) { ++ *bcmerror = BCME_SDIO_ERROR; ++ return -1; ++ } ++ int_val = bcmsdh_reg_read(bus->sdh, data, 4); ++ if (bcmsdh_regfail(bus->sdh)) { ++ *bcmerror = BCME_SDIO_ERROR; ++ return -1; ++ } ++ if (bus->sih->chip == BCM4330_CHIP_ID) { ++ uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB; ++ } ++ else if (bus->sih->chip == BCM4334_CHIP_ID || ++ bus->sih->chip == BCM43341_CHIP_ID) { ++ if (enable) { ++ /* Moved to PMU chipcontrol 1 from 4330 */ ++ int_val &= ~gpio_sel; ++ int_val |= jtag_sel; ++ } else { ++ int_val |= gpio_sel; ++ int_val &= ~jtag_sel; ++ } ++ uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB_4334; ++ } ++ ++ if (!set) ++ return (int_val & uart_enab); ++ if (enable) ++ int_val |= uart_enab; ++ else ++ int_val &= ~uart_enab; ++ bcmsdh_reg_write(bus->sdh, data, 4, int_val); ++ if (bcmsdh_regfail(bus->sdh)) { ++ *bcmerror = BCME_SDIO_ERROR; ++ return -1; ++ } ++ if (bus->sih->chip == BCM4330_CHIP_ID) { ++ uint32 chipcontrol; ++ addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol); ++ chipcontrol = bcmsdh_reg_read(bus->sdh, addr, 4); ++ chipcontrol &= ~jtag_sel; ++ if (enable) { ++ chipcontrol |= jtag_sel; ++ chipcontrol &= ~gpio_sel; ++ } ++ bcmsdh_reg_write(bus->sdh, addr, 4, chipcontrol); ++ } ++ ++ return (int_val & uart_enab); ++} ++#endif ++ ++static int ++dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name, ++ void *params, int plen, void *arg, int len, int val_size) ++{ ++ int bcmerror = 0; ++ int32 int_val = 0; ++ bool bool_val = 0; ++ ++ AP6210_DEBUG("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n", ++ __FUNCTION__, actionid, name, params, plen, arg, len, val_size); ++ ++ if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0) ++ goto exit; ++ ++ if (plen >= (int)sizeof(int_val)) ++ bcopy(params, &int_val, sizeof(int_val)); ++ ++ bool_val = (int_val != 0) ? TRUE : FALSE; ++ ++ ++ /* Some ioctls use the bus */ ++ dhd_os_sdlock(bus->dhd); ++ ++ /* Check if dongle is in reset. If so, only allow DEVRESET iovars */ ++ if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) || ++ actionid == IOV_GVAL(IOV_DEVRESET))) { ++ bcmerror = BCME_NOTREADY; ++ goto exit; ++ } ++ ++ /* ++ * Special handling for keepSdioOn: New SDIO Wake-up Mechanism ++ */ ++ if ((vi->varid == IOV_KSO) && (IOV_ISSET(actionid))) { ++ dhdsdio_clk_kso_iovar(bus, bool_val); ++ goto exit; ++ } else if ((vi->varid == IOV_DEVSLEEP) && (IOV_ISSET(actionid))) { ++ { ++ dhdsdio_clk_devsleep_iovar(bus, bool_val); ++ if (!SLPAUTO_ENAB(bus) && (bool_val == FALSE) && (bus->ipend)) { ++ AP6210_DEBUG("INT pending in devsleep 1, dpc_sched: %d\n", ++ bus->dpc_sched); ++ if (!bus->dpc_sched) { ++ bus->dpc_sched = TRUE; ++ dhd_sched_dpc(bus->dhd); ++ } ++ } ++ } ++ goto exit; ++ } ++ ++ /* Handle sleep stuff before any clock mucking */ ++ if (vi->varid == IOV_SLEEP) { ++ if (IOV_ISSET(actionid)) { ++ bcmerror = dhdsdio_bussleep(bus, bool_val); ++ } else { ++ int_val = (int32)bus->sleeping; ++ bcopy(&int_val, arg, val_size); ++ } ++ goto exit; ++ } ++ ++ /* Request clock to allow SDIO accesses */ ++ if (!bus->dhd->dongle_reset) { ++ BUS_WAKE(bus); ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); ++ } ++ ++ switch (actionid) { ++ case IOV_GVAL(IOV_INTR): ++ int_val = (int32)bus->intr; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_INTR): ++ bus->intr = bool_val; ++ bus->intdis = FALSE; ++ if (bus->dhd->up) { ++ if (bus->intr) { ++ AP6210_DEBUG("%s: enable SDIO device interrupts\n", __FUNCTION__); ++ bcmsdh_intr_enable(bus->sdh); ++ } else { ++ AP6210_DEBUG("%s: disable SDIO interrupts\n", __FUNCTION__); ++ bcmsdh_intr_disable(bus->sdh); ++ } ++ } ++ break; ++ ++ case IOV_GVAL(IOV_POLLRATE): ++ int_val = (int32)bus->pollrate; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_POLLRATE): ++ bus->pollrate = (uint)int_val; ++ bus->poll = (bus->pollrate != 0); ++ break; ++ ++ case IOV_GVAL(IOV_IDLETIME): ++ int_val = bus->idletime; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_IDLETIME): ++ if ((int_val < 0) && (int_val != DHD_IDLE_IMMEDIATE)) { ++ bcmerror = BCME_BADARG; ++ } else { ++ bus->idletime = int_val; ++ } ++ break; ++ ++ case IOV_GVAL(IOV_IDLECLOCK): ++ int_val = (int32)bus->idleclock; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_IDLECLOCK): ++ bus->idleclock = int_val; ++ break; ++ ++ case IOV_GVAL(IOV_SD1IDLE): ++ int_val = (int32)sd1idle; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_SD1IDLE): ++ sd1idle = bool_val; ++ break; ++ ++ ++ case IOV_SVAL(IOV_MEMBYTES): ++ case IOV_GVAL(IOV_MEMBYTES): ++ { ++ uint32 address; ++ uint size, dsize; ++ uint8 *data; ++ ++ bool set = (actionid == IOV_SVAL(IOV_MEMBYTES)); ++ ++ ASSERT(plen >= 2*sizeof(int)); ++ ++ address = (uint32)int_val; ++ bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val)); ++ size = (uint)int_val; ++ ++ /* Do some validation */ ++ dsize = set ? plen - (2 * sizeof(int)) : len; ++ if (dsize < size) { ++ AP6210_ERR("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n", ++ __FUNCTION__, (set ? "set" : "get"), address, size, dsize); ++ bcmerror = BCME_BADARG; ++ break; ++ } ++ ++ AP6210_DEBUG("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__, ++ (set ? "write" : "read"), size, address); ++ ++ /* If we know about SOCRAM, check for a fit */ ++ if ((bus->orig_ramsize) && ++ ((address > bus->orig_ramsize) || (address + size > bus->orig_ramsize))) ++ { ++ uint8 enable, protect, remap; ++ si_socdevram(bus->sih, FALSE, &enable, &protect, &remap); ++ if (!enable || protect) { ++ AP6210_ERR("%s: ramsize 0x%08x doesn't have %d bytes at 0x%08x\n", ++ __FUNCTION__, bus->orig_ramsize, size, address); ++ AP6210_DEBUG("%s: socram enable %d, protect %d\n", ++ __FUNCTION__, enable, protect); ++ bcmerror = BCME_BADARG; ++ break; ++ } ++ ++ if (!REMAP_ENAB(bus) && (address >= SOCDEVRAM_ARM_ADDR)) { ++ uint32 devramsize = si_socdevram_size(bus->sih); ++ if ((address < SOCDEVRAM_ARM_ADDR) || ++ (address + size > (SOCDEVRAM_ARM_ADDR + devramsize))) { ++ AP6210_ERR("%s: bad address 0x%08x, size 0x%08x\n", ++ __FUNCTION__, address, size); ++ AP6210_DEBUG("%s: socram range 0x%08x,size 0x%08x\n", ++ __FUNCTION__, SOCDEVRAM_ARM_ADDR, devramsize); ++ bcmerror = BCME_BADARG; ++ break; ++ } ++ /* move it such that address is real now */ ++ address -= SOCDEVRAM_ARM_ADDR; ++ address += SOCDEVRAM_BP_ADDR; ++ AP6210_DEBUG("%s: Request to %s %d bytes @ Mapped address 0x%08x\n", ++ __FUNCTION__, (set ? "write" : "read"), size, address); ++ } else if (REMAP_ENAB(bus) && REMAP_ISADDR(bus, address) && remap) { ++ /* Can not access remap region while devram remap bit is set ++ * ROM content would be returned in this case ++ */ ++ AP6210_ERR("%s: Need to disable remap for address 0x%08x\n", ++ __FUNCTION__, address); ++ bcmerror = BCME_ERROR; ++ break; ++ } ++ } ++ ++ /* Generate the actual data pointer */ ++ data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg; ++ ++ /* Call to do the transfer */ ++ bcmerror = dhdsdio_membytes(bus, set, address, data, size); ++ ++ break; ++ } ++ ++ case IOV_GVAL(IOV_MEMSIZE): ++ int_val = (int32)bus->ramsize; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_GVAL(IOV_SDIOD_DRIVE): ++ int_val = (int32)dhd_sdiod_drive_strength; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_SDIOD_DRIVE): ++ dhd_sdiod_drive_strength = int_val; ++ si_sdiod_drive_strength_init(bus->sih, bus->dhd->osh, dhd_sdiod_drive_strength); ++ break; ++ ++ case IOV_SVAL(IOV_SET_DOWNLOAD_STATE): ++ bcmerror = dhdsdio_download_state(bus, bool_val); ++ break; ++ ++ case IOV_SVAL(IOV_SOCRAM_STATE): ++ bcmerror = dhdsdio_download_state(bus, bool_val); ++ break; ++ ++ case IOV_SVAL(IOV_VARS): ++ bcmerror = dhdsdio_downloadvars(bus, arg, len); ++ break; ++ ++ case IOV_GVAL(IOV_READAHEAD): ++ int_val = (int32)dhd_readahead; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_READAHEAD): ++ if (bool_val && !dhd_readahead) ++ bus->nextlen = 0; ++ dhd_readahead = bool_val; ++ break; ++ ++ case IOV_GVAL(IOV_SDRXCHAIN): ++ int_val = (int32)bus->use_rxchain; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_SDRXCHAIN): ++ if (bool_val && !bus->sd_rxchain) ++ bcmerror = BCME_UNSUPPORTED; ++ else ++ bus->use_rxchain = bool_val; ++ break; ++ case IOV_GVAL(IOV_ALIGNCTL): ++ int_val = (int32)dhd_alignctl; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_ALIGNCTL): ++ dhd_alignctl = bool_val; ++ break; ++ ++ case IOV_GVAL(IOV_SDALIGN): ++ int_val = DHD_SDALIGN; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++#ifdef DHD_DEBUG ++ case IOV_GVAL(IOV_VARS): ++ if (bus->varsz < (uint)len) ++ bcopy(bus->vars, arg, bus->varsz); ++ else ++ bcmerror = BCME_BUFTOOSHORT; ++ break; ++#endif /* DHD_DEBUG */ ++ ++#ifdef DHD_DEBUG ++ case IOV_GVAL(IOV_SDREG): ++ { ++ sdreg_t *sd_ptr; ++ uint32 addr, size; ++ ++ sd_ptr = (sdreg_t *)params; ++ ++ addr = (uintptr)bus->regs + sd_ptr->offset; ++ size = sd_ptr->func; ++ int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size); ++ if (bcmsdh_regfail(bus->sdh)) ++ bcmerror = BCME_SDIO_ERROR; ++ bcopy(&int_val, arg, sizeof(int32)); ++ break; ++ } ++ ++ case IOV_SVAL(IOV_SDREG): ++ { ++ sdreg_t *sd_ptr; ++ uint32 addr, size; ++ ++ sd_ptr = (sdreg_t *)params; ++ ++ addr = (uintptr)bus->regs + sd_ptr->offset; ++ size = sd_ptr->func; ++ bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value); ++ if (bcmsdh_regfail(bus->sdh)) ++ bcmerror = BCME_SDIO_ERROR; ++ break; ++ } ++ ++ /* Same as above, but offset is not backplane (not SDIO core) */ ++ case IOV_GVAL(IOV_SBREG): ++ { ++ sdreg_t sdreg; ++ uint32 addr, size; ++ ++ bcopy(params, &sdreg, sizeof(sdreg)); ++ ++ addr = SI_ENUM_BASE + sdreg.offset; ++ size = sdreg.func; ++ int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size); ++ if (bcmsdh_regfail(bus->sdh)) ++ bcmerror = BCME_SDIO_ERROR; ++ bcopy(&int_val, arg, sizeof(int32)); ++ break; ++ } ++ ++ case IOV_SVAL(IOV_SBREG): ++ { ++ sdreg_t sdreg; ++ uint32 addr, size; ++ ++ bcopy(params, &sdreg, sizeof(sdreg)); ++ ++ addr = SI_ENUM_BASE + sdreg.offset; ++ size = sdreg.func; ++ bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value); ++ if (bcmsdh_regfail(bus->sdh)) ++ bcmerror = BCME_SDIO_ERROR; ++ break; ++ } ++ ++ case IOV_GVAL(IOV_SDCIS): ++ { ++ *(char *)arg = 0; ++ ++ bcmstrcat(arg, "\nFunc 0\n"); ++ bcmsdh_cis_read(bus->sdh, 0x10, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT); ++ bcmstrcat(arg, "\nFunc 1\n"); ++ bcmsdh_cis_read(bus->sdh, 0x11, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT); ++ bcmstrcat(arg, "\nFunc 2\n"); ++ bcmsdh_cis_read(bus->sdh, 0x12, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT); ++ break; ++ } ++ ++ case IOV_GVAL(IOV_FORCEEVEN): ++ int_val = (int32)forcealign; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_FORCEEVEN): ++ forcealign = bool_val; ++ break; ++ ++ case IOV_GVAL(IOV_TXBOUND): ++ int_val = (int32)dhd_txbound; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_TXBOUND): ++ dhd_txbound = (uint)int_val; ++ break; ++ ++ case IOV_GVAL(IOV_RXBOUND): ++ int_val = (int32)dhd_rxbound; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_RXBOUND): ++ dhd_rxbound = (uint)int_val; ++ break; ++ ++ case IOV_GVAL(IOV_TXMINMAX): ++ int_val = (int32)dhd_txminmax; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_TXMINMAX): ++ dhd_txminmax = (uint)int_val; ++ break; ++ ++ case IOV_GVAL(IOV_SERIALCONS): ++ int_val = dhd_serialconsole(bus, FALSE, 0, &bcmerror); ++ if (bcmerror != 0) ++ break; ++ ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_SERIALCONS): ++ dhd_serialconsole(bus, TRUE, bool_val, &bcmerror); ++ break; ++ ++ ++ ++#endif /* DHD_DEBUG */ ++ ++ ++#ifdef SDTEST ++ case IOV_GVAL(IOV_EXTLOOP): ++ int_val = (int32)bus->ext_loop; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_EXTLOOP): ++ bus->ext_loop = bool_val; ++ break; ++ ++ case IOV_GVAL(IOV_PKTGEN): ++ bcmerror = dhdsdio_pktgen_get(bus, arg); ++ break; ++ ++ case IOV_SVAL(IOV_PKTGEN): ++ bcmerror = dhdsdio_pktgen_set(bus, arg); ++ break; ++#endif /* SDTEST */ ++ ++#if defined(SDIO_CRC_ERROR_FIX) ++ case IOV_GVAL(IOV_WATERMARK): ++ int_val = (int32)watermark; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_WATERMARK): ++ watermark = (uint)int_val; ++ watermark = (watermark > SBSDIO_WATERMARK_MASK) ? SBSDIO_WATERMARK_MASK : watermark; ++ AP6210_DEBUG("Setting watermark as 0x%x.\n", watermark); ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, NULL); ++ break; ++ ++ case IOV_GVAL(IOV_MESBUSYCTRL): ++ int_val = (int32)mesbusyctrl; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_MESBUSYCTRL): ++ mesbusyctrl = (uint)int_val; ++ mesbusyctrl = (mesbusyctrl > SBSDIO_MESBUSYCTRL_MASK) ++ ? SBSDIO_MESBUSYCTRL_MASK : mesbusyctrl; ++ AP6210_DEBUG("Setting mesbusyctrl as 0x%x.\n", mesbusyctrl); ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, ++ ((uint8)mesbusyctrl | 0x80), NULL); ++ break; ++#endif /* SDIO_CRC_ERROR_FIX */ ++ ++ case IOV_GVAL(IOV_DONGLEISOLATION): ++ int_val = bus->dhd->dongle_isolation; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_DONGLEISOLATION): ++ bus->dhd->dongle_isolation = bool_val; ++ break; ++ ++ case IOV_SVAL(IOV_DEVRESET): ++ AP6210_DEBUG("%s: Called set IOV_DEVRESET=%d dongle_reset=%d busstate=%d\n", ++ __FUNCTION__, bool_val, bus->dhd->dongle_reset, ++ bus->dhd->busstate); ++ ++ ASSERT(bus->dhd->osh); ++ /* ASSERT(bus->cl_devid); */ ++ ++ dhd_bus_devreset(bus->dhd, (uint8)bool_val); ++ ++ break; ++#ifdef SOFTAP ++ case IOV_GVAL(IOV_FWPATH): ++ { ++ uint32 fw_path_len; ++ ++ fw_path_len = strlen(bus->fw_path); ++ AP6210_DEBUG("[softap] get fwpath, l=%d\n", len); ++ ++ if (fw_path_len > len-1) { ++ bcmerror = BCME_BUFTOOSHORT; ++ break; ++ } ++ ++ if (fw_path_len) { ++ bcopy(bus->fw_path, arg, fw_path_len); ++ ((uchar*)arg)[fw_path_len] = 0; ++ } ++ break; ++ } ++ ++ case IOV_SVAL(IOV_FWPATH): ++ AP6210_DEBUG("[softap] set fwpath, idx=%d\n", int_val); ++ ++ switch (int_val) { ++ case 1: ++ bus->fw_path = fw_path; /* ordinary one */ ++ break; ++ case 2: ++ bus->fw_path = fw_path2; ++ break; ++ default: ++ bcmerror = BCME_BADARG; ++ break; ++ } ++ ++ AP6210_DEBUG("[softap] new fw path: %s\n", (bus->fw_path[0] ? bus->fw_path : "NULL")); ++ break; ++ ++#endif /* SOFTAP */ ++ case IOV_GVAL(IOV_DEVRESET): ++ AP6210_DEBUG("%s: Called get IOV_DEVRESET\n", __FUNCTION__); ++ ++ /* Get its status */ ++ int_val = (bool) bus->dhd->dongle_reset; ++ bcopy(&int_val, arg, val_size); ++ ++ break; ++ ++ case IOV_GVAL(IOV_KSO): ++ int_val = dhdsdio_sleepcsr_get(bus); ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_GVAL(IOV_DEVCAP): ++ int_val = dhdsdio_devcap_get(bus); ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_DEVCAP): ++ dhdsdio_devcap_set(bus, (uint8) int_val); ++ break; ++ ++#ifdef BCMSDIOH_TXGLOM ++ case IOV_GVAL(IOV_TXGLOMSIZE): ++ int_val = (int32)bus->glomsize; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_TXGLOMSIZE): ++ if (int_val > SDPCM_MAXGLOM_SIZE) { ++ bcmerror = BCME_ERROR; ++ } else { ++ bus->glomsize = (uint)int_val; ++ } ++ break; ++ case IOV_GVAL(IOV_TXGLOMMODE): ++ int_val = (int32)bus->glom_mode; ++ bcopy(&int_val, arg, val_size); ++ break; ++ ++ case IOV_SVAL(IOV_TXGLOMMODE): ++ if ((int_val != SDPCM_TXGLOM_CPY) && (int_val != SDPCM_TXGLOM_MDESC)) { ++ bcmerror = BCME_RANGE; ++ } else { ++ if ((bus->glom_mode = bcmsdh_set_mode(bus->sdh, (uint)int_val)) != int_val) ++ bcmerror = BCME_ERROR; ++ } ++ break; ++#endif /* BCMSDIOH_TXGLOM */ ++ default: ++ bcmerror = BCME_UNSUPPORTED; ++ break; ++ } ++ ++exit: ++ if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { ++ bus->activity = FALSE; ++ dhdsdio_clkctl(bus, CLK_NONE, TRUE); ++ } ++ ++ dhd_os_sdunlock(bus->dhd); ++ ++ return bcmerror; ++} ++ ++static int ++dhdsdio_write_vars(dhd_bus_t *bus) ++{ ++ int bcmerror = 0; ++ uint32 varsize, phys_size; ++ uint32 varaddr; ++ uint8 *vbuffer; ++ uint32 varsizew; ++#ifdef DHD_DEBUG ++ uint8 *nvram_ularray; ++#endif /* DHD_DEBUG */ ++ ++ /* Even if there are no vars are to be written, we still need to set the ramsize. */ ++ varsize = bus->varsz ? ROUNDUP(bus->varsz, 4) : 0; ++ varaddr = (bus->ramsize - 4) - varsize; ++ ++ varaddr += bus->dongle_ram_base; ++ ++ if (bus->vars) { ++ if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 7)) { ++ if (((varaddr & 0x3C) == 0x3C) && (varsize > 4)) { ++ AP6210_DEBUG("PR85623WAR in place\n"); ++ varsize += 4; ++ varaddr -= 4; ++ } ++ } ++ ++ vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize); ++ if (!vbuffer) ++ return BCME_NOMEM; ++ ++ bzero(vbuffer, varsize); ++ bcopy(bus->vars, vbuffer, bus->varsz); ++ ++ /* Write the vars list */ ++ bcmerror = dhdsdio_membytes(bus, TRUE, varaddr, vbuffer, varsize); ++#ifdef DHD_DEBUG ++ /* Verify NVRAM bytes */ ++ AP6210_DEBUG("Compare NVRAM dl & ul; varsize=%d\n", varsize); ++ nvram_ularray = (uint8*)MALLOC(bus->dhd->osh, varsize); ++ if (!nvram_ularray) ++ return BCME_NOMEM; ++ ++ /* Upload image to verify downloaded contents. */ ++ memset(nvram_ularray, 0xaa, varsize); ++ ++ /* Read the vars list to temp buffer for comparison */ ++ bcmerror = dhdsdio_membytes(bus, FALSE, varaddr, nvram_ularray, varsize); ++ if (bcmerror) { ++ AP6210_ERR("%s: error %d on reading %d nvram bytes at 0x%08x\n", ++ __FUNCTION__, bcmerror, varsize, varaddr); ++ } ++ /* Compare the org NVRAM with the one read from RAM */ ++ if (memcmp(vbuffer, nvram_ularray, varsize)) { ++ AP6210_ERR("%s: Downloaded NVRAM image is corrupted.\n", __FUNCTION__); ++ } else ++ AP6210_DEBUG("%s: Download, Upload and compare of NVRAM succeeded.\n", ++ __FUNCTION__); ++ ++ MFREE(bus->dhd->osh, nvram_ularray, varsize); ++#endif /* DHD_DEBUG */ ++ ++ MFREE(bus->dhd->osh, vbuffer, varsize); ++ } ++ ++ phys_size = REMAP_ENAB(bus) ? bus->ramsize : bus->orig_ramsize; ++ ++ phys_size += bus->dongle_ram_base; ++ ++ /* adjust to the user specified RAM */ ++ AP6210_DEBUG("Physical memory size: %d, usable memory size: %d\n", ++ phys_size, bus->ramsize); ++ AP6210_DEBUG("Vars are at %d, orig varsize is %d\n", ++ varaddr, varsize); ++ varsize = ((phys_size - 4) - varaddr); ++ ++ /* ++ * Determine the length token: ++ * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits. ++ */ ++ if (bcmerror) { ++ varsizew = 0; ++ } else { ++ varsizew = varsize / 4; ++ varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF); ++ varsizew = htol32(varsizew); ++ } ++ ++ AP6210_DEBUG("New varsize is %d, length token=0x%08x\n", varsize, varsizew); ++ ++ /* Write the length token to the last word */ ++ bcmerror = dhdsdio_membytes(bus, TRUE, (phys_size - 4), ++ (uint8*)&varsizew, 4); ++ ++ return bcmerror; ++} ++ ++static int ++dhdsdio_download_state(dhd_bus_t *bus, bool enter) ++{ ++ uint retries; ++ int bcmerror = 0; ++ int foundcr4 = 0; ++ ++ /* To enter download state, disable ARM and reset SOCRAM. ++ * To exit download state, simply reset ARM (default is RAM boot). ++ */ ++ if (enter) { ++ bus->alp_only = TRUE; ++ ++ if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) && ++ !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) { ++ if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { ++ foundcr4 = 1; ++ } else { ++ AP6210_ERR("%s: Failed to find ARM core!\n", __FUNCTION__); ++ bcmerror = BCME_ERROR; ++ goto fail; ++ } ++ } ++ ++ if (!foundcr4) { ++ si_core_disable(bus->sih, 0); ++ if (bcmsdh_regfail(bus->sdh)) { ++ bcmerror = BCME_SDIO_ERROR; ++ goto fail; ++ } ++ ++ if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) { ++ AP6210_ERR("%s: Failed to find SOCRAM core!\n", __FUNCTION__); ++ bcmerror = BCME_ERROR; ++ goto fail; ++ } ++ ++ si_core_reset(bus->sih, 0, 0); ++ if (bcmsdh_regfail(bus->sdh)) { ++ AP6210_ERR("%s: Failure trying reset SOCRAM core?\n", __FUNCTION__); ++ bcmerror = BCME_SDIO_ERROR; ++ goto fail; ++ } ++ ++ /* Disable remap for download */ ++ if (REMAP_ENAB(bus) && si_socdevram_remap_isenb(bus->sih)) ++ dhdsdio_devram_remap(bus, FALSE); ++ ++ /* Clear the top bit of memory */ ++ if (bus->ramsize) { ++ uint32 zeros = 0; ++ if (dhdsdio_membytes(bus, TRUE, bus->ramsize - 4, (uint8*)&zeros, 4) < 0) { ++ bcmerror = BCME_SDIO_ERROR; ++ goto fail; ++ } ++ } ++ } else { ++ /* For CR4, ++ * Halt ARM ++ * Remove ARM reset ++ * Read RAM base address [0x18_0000] ++ * [next] Download firmware ++ * [done at else] Populate the reset vector ++ * [done at else] Remove ARM halt ++ */ ++ /* Halt ARM & remove reset */ ++ si_core_reset(bus->sih, SICF_CPUHALT, SICF_CPUHALT); ++ } ++ } else { ++ if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { ++ if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) { ++ AP6210_ERR("%s: Failed to find SOCRAM core!\n", __FUNCTION__); ++ bcmerror = BCME_ERROR; ++ goto fail; ++ } ++ ++ if (!si_iscoreup(bus->sih)) { ++ AP6210_ERR("%s: SOCRAM core is down after reset?\n", __FUNCTION__); ++ bcmerror = BCME_ERROR; ++ goto fail; ++ } ++ ++ if ((bcmerror = dhdsdio_write_vars(bus))) { ++ AP6210_ERR("%s: could not write vars to RAM\n", __FUNCTION__); ++ goto fail; ++ } ++ ++ /* Enable remap before ARM reset but after vars. ++ * No backplane access in remap mode ++ */ ++ if (REMAP_ENAB(bus) && !si_socdevram_remap_isenb(bus->sih)) ++ dhdsdio_devram_remap(bus, TRUE); ++ ++ if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) && ++ !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) { ++ AP6210_ERR("%s: Can't change back to SDIO core?\n", __FUNCTION__); ++ bcmerror = BCME_ERROR; ++ goto fail; ++ } ++ W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries); ++ ++ ++ if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) && ++ !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) { ++ AP6210_ERR("%s: Failed to find ARM core!\n", __FUNCTION__); ++ bcmerror = BCME_ERROR; ++ goto fail; ++ } ++ } else { ++ /* cr4 has no socram, but tcm's */ ++ /* write vars */ ++ if ((bcmerror = dhdsdio_write_vars(bus))) { ++ AP6210_ERR("%s: could not write vars to RAM\n", __FUNCTION__); ++ goto fail; ++ } ++ ++ if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) && ++ !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) { ++ AP6210_ERR("%s: Can't change back to SDIO core?\n", __FUNCTION__); ++ bcmerror = BCME_ERROR; ++ goto fail; ++ } ++ W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries); ++ ++ /* switch back to arm core again */ ++ if (!(si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) { ++ AP6210_ERR("%s: Failed to find ARM CR4 core!\n", __FUNCTION__); ++ bcmerror = BCME_ERROR; ++ goto fail; ++ } ++ /* write address 0 with reset instruction */ ++ bcmerror = dhdsdio_membytes(bus, TRUE, 0, ++ (uint8 *)&bus->resetinstr, sizeof(bus->resetinstr)); ++ ++ /* now remove reset and halt and continue to run CR4 */ ++ } ++ ++ si_core_reset(bus->sih, 0, 0); ++ if (bcmsdh_regfail(bus->sdh)) { ++ AP6210_ERR("%s: Failure trying to reset ARM core?\n", __FUNCTION__); ++ bcmerror = BCME_SDIO_ERROR; ++ goto fail; ++ } ++ ++ /* Allow HT Clock now that the ARM is running. */ ++ bus->alp_only = FALSE; ++ ++ bus->dhd->busstate = DHD_BUS_LOAD; ++ } ++ ++fail: ++ /* Always return to SDIOD core */ ++ if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) ++ si_setcore(bus->sih, SDIOD_CORE_ID, 0); ++ ++ return bcmerror; ++} ++ ++int ++dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name, ++ void *params, int plen, void *arg, int len, bool set) ++{ ++ dhd_bus_t *bus = dhdp->bus; ++ const bcm_iovar_t *vi = NULL; ++ int bcmerror = 0; ++ int val_size; ++ uint32 actionid; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ ASSERT(name); ++ ASSERT(len >= 0); ++ ++ /* Get MUST have return space */ ++ ASSERT(set || (arg && len)); ++ ++ /* Set does NOT take qualifiers */ ++ ASSERT(!set || (!params && !plen)); ++ ++ /* Look up var locally; if not found pass to host driver */ ++ if ((vi = bcm_iovar_lookup(dhdsdio_iovars, name)) == NULL) { ++ dhd_os_sdlock(bus->dhd); ++ ++ BUS_WAKE(bus); ++ ++ /* Turn on clock in case SD command needs backplane */ ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); ++ ++ bcmerror = bcmsdh_iovar_op(bus->sdh, name, params, plen, arg, len, set); ++ ++ /* Check for bus configuration changes of interest */ ++ ++ /* If it was divisor change, read the new one */ ++ if (set && strcmp(name, "sd_divisor") == 0) { ++ if (bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0, ++ &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) { ++ bus->sd_divisor = -1; ++ AP6210_ERR("%s: fail on %s get\n", __FUNCTION__, name); ++ } else { ++ AP6210_DEBUG("%s: noted %s update, value now %d\n", ++ __FUNCTION__, name, bus->sd_divisor); ++ } ++ } ++ /* If it was a mode change, read the new one */ ++ if (set && strcmp(name, "sd_mode") == 0) { ++ if (bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0, ++ &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) { ++ bus->sd_mode = -1; ++ AP6210_ERR("%s: fail on %s get\n", __FUNCTION__, name); ++ } else { ++ AP6210_DEBUG("%s: noted %s update, value now %d\n", ++ __FUNCTION__, name, bus->sd_mode); ++ } ++ } ++ /* Similar check for blocksize change */ ++ if (set && strcmp(name, "sd_blocksize") == 0) { ++ int32 fnum = 2; ++ if (bcmsdh_iovar_op(bus->sdh, "sd_blocksize", &fnum, sizeof(int32), ++ &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) { ++ bus->blocksize = 0; ++ AP6210_ERR("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"); ++ } else { ++ AP6210_DEBUG("%s: noted %s update, value now %d\n", ++ __FUNCTION__, "sd_blocksize", bus->blocksize); ++ } ++ } ++ bus->roundup = MIN(max_roundup, bus->blocksize); ++ ++ if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { ++ bus->activity = FALSE; ++ dhdsdio_clkctl(bus, CLK_NONE, TRUE); ++ } ++ ++ dhd_os_sdunlock(bus->dhd); ++ goto exit; ++ } ++ ++ AP6210_DEBUG("%s: %s %s, len %d plen %d\n", __FUNCTION__, ++ name, (set ? "set" : "get"), len, plen); ++ ++ /* set up 'params' pointer in case this is a set command so that ++ * the convenience int and bool code can be common to set and get ++ */ ++ if (params == NULL) { ++ params = arg; ++ plen = len; ++ } ++ ++ if (vi->type == IOVT_VOID) ++ val_size = 0; ++ else if (vi->type == IOVT_BUFFER) ++ val_size = len; ++ else ++ /* all other types are integer sized */ ++ val_size = sizeof(int); ++ ++ actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); ++ bcmerror = dhdsdio_doiovar(bus, vi, actionid, name, params, plen, arg, len, val_size); ++ ++exit: ++ return bcmerror; ++} ++ ++void ++dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) ++{ ++ osl_t *osh; ++ uint32 local_hostintmask; ++ uint8 saveclk, dat; ++ uint retries; ++ int err; ++ if (!bus->dhd) ++ return; ++ ++ osh = bus->dhd->osh; ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ bcmsdh_waitlockfree(NULL); ++ ++ if (enforce_mutex) ++ dhd_os_sdlock(bus->dhd); ++ ++ if ((bus->dhd->busstate == DHD_BUS_DOWN) || bus->dhd->hang_was_sent) { ++ /* if Firmware already hangs disbale any interrupt */ ++ bus->dhd->busstate = DHD_BUS_DOWN; ++ bus->hostintmask = 0; ++ bcmsdh_intr_disable(bus->sdh); ++ } else { ++ BUS_WAKE(bus); ++ ++ if (KSO_ENAB(bus)) { ++ /* Mask the interrupt */ ++ dat = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, NULL); ++ dat &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN); ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, dat, NULL); ++ } ++ ++ /* Change our idea of bus state */ ++ bus->dhd->busstate = DHD_BUS_DOWN; ++ ++ if (KSO_ENAB(bus)) { ++ ++ /* Enable clock for device interrupts */ ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); ++ ++ /* Disable and clear interrupts at the chip level also */ ++ W_SDREG(0, &bus->regs->hostintmask, retries); ++ local_hostintmask = bus->hostintmask; ++ bus->hostintmask = 0; ++ ++ /* Force clocks on backplane to be sure F2 interrupt propagates */ ++ saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ if (!err) { ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, ++ (saveclk | SBSDIO_FORCE_HT), &err); ++ } ++ if (err) { ++ AP6210_ERR("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err); ++ } ++ ++ /* Turn off the bus (F2), free any pending packets */ ++ AP6210_DEBUG("%s: disable SDIO interrupts\n", __FUNCTION__); ++ bcmsdh_intr_disable(bus->sdh); ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); ++ ++ /* Clear any pending interrupts now that F2 is disabled */ ++ W_SDREG(local_hostintmask, &bus->regs->intstatus, retries); ++ } ++ ++ /* Turn off the backplane clock (only) */ ++ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); ++ } ++ ++ /* Clear the data packet queues */ ++ pktq_flush(osh, &bus->txq, TRUE, NULL, 0); ++ ++ /* Clear any held glomming stuff */ ++ if (bus->glomd) ++ PKTFREE(osh, bus->glomd, FALSE); ++ ++ if (bus->glom) ++ PKTFREE(osh, bus->glom, FALSE); ++ ++ bus->glom = bus->glomd = NULL; ++ ++ /* Clear rx control and wake any waiters */ ++ bus->rxlen = 0; ++ dhd_os_ioctl_resp_wake(bus->dhd); ++ ++ /* Reset some F2 state stuff */ ++ bus->rxskip = FALSE; ++ bus->tx_seq = bus->rx_seq = 0; ++ ++ if (enforce_mutex) ++ dhd_os_sdunlock(bus->dhd); ++} ++ ++#ifdef BCMSDIOH_TXGLOM ++void ++dhd_txglom_enable(dhd_pub_t *dhdp, bool enable) ++{ ++ dhd_bus_t *bus = dhdp->bus; ++ ++ char buf[256]; ++ uint32 rxglom; ++ int32 ret; ++ ++ if (enable) { ++ rxglom = 1; ++ memset(buf, 0, sizeof(buf)); ++ bcm_mkiovar("bus:rxglom", ++ (void *)&rxglom, ++ 4, buf, sizeof(buf)); ++ ret = dhd_wl_ioctl_cmd(dhdp, ++ WLC_SET_VAR, buf, ++ sizeof(buf), TRUE, 0); ++ if (!(ret < 0)) { ++ bus->glom_enable = TRUE; ++ } ++ } else { ++ bus->glom_enable = FALSE; ++ } ++} ++#endif /* BCMSDIOH_TXGLOM */ ++ ++int ++dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) ++{ ++ dhd_bus_t *bus = dhdp->bus; ++ dhd_timeout_t tmo; ++ uint retries = 0; ++ uint8 ready, enable; ++ int err, ret = 0; ++ uint8 saveclk; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ ASSERT(bus->dhd); ++ if (!bus->dhd) ++ return 0; ++ ++ if (enforce_mutex) ++ dhd_os_sdlock(bus->dhd); ++ ++ /* Make sure backplane clock is on, needed to generate F2 interrupt */ ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); ++ if (bus->clkstate != CLK_AVAIL) { ++ AP6210_ERR("%s: clock state is wrong. state = %d\n", __FUNCTION__, bus->clkstate); ++ ret = -1; ++ goto exit; ++ } ++ ++ ++ /* Force clocks on backplane to be sure F2 interrupt propagates */ ++ saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ if (!err) { ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, ++ (saveclk | SBSDIO_FORCE_HT), &err); ++ } ++ if (err) { ++ AP6210_ERR("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err); ++ ret = -1; ++ goto exit; ++ } ++ ++ /* Enable function 2 (frame transfers) */ ++ W_SDREG((SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT), ++ &bus->regs->tosbmailboxdata, retries); ++ enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2); ++ ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL); ++ ++ /* Give the dongle some time to do its thing and set IOR2 */ ++ dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000); ++ ++ ready = 0; ++ while (ready != enable && !dhd_timeout_expired(&tmo)) ++ ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL); ++ ++ AP6210_DEBUG("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n", ++ __FUNCTION__, enable, ready, tmo.elapsed); ++ ++ ++ /* If F2 successfully enabled, set core and enable interrupts */ ++ if (ready == enable) { ++ /* Make sure we're talking to the core. */ ++ if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0))) ++ bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0); ++ ASSERT(bus->regs != NULL); ++ ++ /* Set up the interrupt mask and enable interrupts */ ++ bus->hostintmask = HOSTINTMASK; ++ /* corerev 4 could use the newer interrupt logic to detect the frames */ ++ if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 4) && ++ (bus->rxint_mode != SDIO_DEVICE_HMB_RXINT)) { ++ bus->hostintmask &= ~I_HMB_FRAME_IND; ++ bus->hostintmask |= I_XMTDATA_AVAIL; ++ } ++ W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries); ++#ifdef SDIO_CRC_ERROR_FIX ++ if (bus->blocksize < 512) { ++ mesbusyctrl = watermark = bus->blocksize / 4; ++ } ++#endif /* SDIO_CRC_ERROR_FIX */ ++ ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, &err); ++#ifdef SDIO_CRC_ERROR_FIX ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, ++ (uint8)mesbusyctrl|0x80, &err); ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, ++ SBSDIO_DEVCTL_EN_F2_BLK_WATERMARK, NULL); ++#endif /* SDIO_CRC_ERROR_FIX */ ++ ++ /* Set bus state according to enable result */ ++ dhdp->busstate = DHD_BUS_DATA; ++ ++ /* bcmsdh_intr_unmask(bus->sdh); */ ++ ++ bus->intdis = FALSE; ++ if (bus->intr) { ++ AP6210_DEBUG("%s: enable SDIO device interrupts\n", __FUNCTION__); ++ bcmsdh_intr_enable(bus->sdh); ++ } else { ++ AP6210_DEBUG("%s: disable SDIO interrupts\n", __FUNCTION__); ++ bcmsdh_intr_disable(bus->sdh); ++ } ++ ++ } ++ ++ ++ else { ++ /* Disable F2 again */ ++ enable = SDIO_FUNC_ENABLE_1; ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL); ++ } ++ ++ if (dhdsdio_sr_cap(bus)) ++ dhdsdio_sr_init(bus); ++ else ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); ++ ++ /* If we didn't come up, turn off backplane clock */ ++ if (dhdp->busstate != DHD_BUS_DATA) ++ dhdsdio_clkctl(bus, CLK_NONE, FALSE); ++ ++exit: ++ if (enforce_mutex) ++ dhd_os_sdunlock(bus->dhd); ++ ++ return ret; ++} ++ ++static void ++dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx) ++{ ++ bcmsdh_info_t *sdh = bus->sdh; ++ sdpcmd_regs_t *regs = bus->regs; ++ uint retries = 0; ++ uint16 lastrbc; ++ uint8 hi, lo; ++ int err; ++ ++ AP6210_ERR("%s: %sterminate frame%s\n", __FUNCTION__, ++ (abort ? "abort command, " : ""), (rtx ? ", send NAK" : "")); ++ ++ if (!KSO_ENAB(bus)) { ++ AP6210_ERR("%s: Device asleep\n", __FUNCTION__); ++ return; ++ } ++ ++ if (abort) { ++ bcmsdh_abort(sdh, SDIO_FUNC_2); ++ } ++ ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, &err); ++ bus->f1regdata++; ++ ++ /* Wait until the packet has been flushed (device/FIFO stable) */ ++ for (lastrbc = retries = 0xffff; retries > 0; retries--) { ++ hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI, NULL); ++ lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO, NULL); ++ bus->f1regdata += 2; ++ ++ if ((hi == 0) && (lo == 0)) ++ break; ++ ++ if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) { ++ AP6210_DEBUG("%s: count growing: last 0x%04x now 0x%04x\n", ++ __FUNCTION__, lastrbc, ((hi << 8) + lo)); ++ } ++ lastrbc = (hi << 8) + lo; ++ } ++ ++ if (!retries) { ++ AP6210_ERR("%s: count never zeroed: last 0x%04x\n", __FUNCTION__, lastrbc); ++ } else { ++ AP6210_DEBUG("%s: flush took %d iterations\n", __FUNCTION__, (0xffff - retries)); ++ } ++ ++ if (rtx) { ++ bus->rxrtx++; ++ W_SDREG(SMB_NAK, ®s->tosbmailbox, retries); ++ bus->f1regdata++; ++ if (retries <= retry_limit) { ++ bus->rxskip = TRUE; ++ } ++ } ++ ++ /* Clear partial in any case */ ++ bus->nextlen = 0; ++ ++ /* If we can't reach the device, signal failure */ ++ if (err || bcmsdh_regfail(sdh)) ++ bus->dhd->busstate = DHD_BUS_DOWN; ++} ++ ++static void ++dhdsdio_read_control(dhd_bus_t *bus, uint8 *hdr, uint len, uint doff) ++{ ++ bcmsdh_info_t *sdh = bus->sdh; ++ uint rdlen, pad; ++ ++ int sdret; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ /* Control data already received in aligned rxctl */ ++ if ((bus->bus == SPI_BUS) && (!bus->usebufpool)) ++ goto gotpkt; ++ ++ ASSERT(bus->rxbuf); ++ /* Set rxctl for frame (w/optional alignment) */ ++ bus->rxctl = bus->rxbuf; ++ if (dhd_alignctl) { ++ bus->rxctl += firstread; ++ if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN))) ++ bus->rxctl += (DHD_SDALIGN - pad); ++ bus->rxctl -= firstread; ++ } ++ ASSERT(bus->rxctl >= bus->rxbuf); ++ ++ /* Copy the already-read portion over */ ++ bcopy(hdr, bus->rxctl, firstread); ++ if (len <= firstread) ++ goto gotpkt; ++ ++ /* Copy the full data pkt in gSPI case and process ioctl. */ ++ if (bus->bus == SPI_BUS) { ++ bcopy(hdr, bus->rxctl, len); ++ goto gotpkt; ++ } ++ ++ /* Raise rdlen to next SDIO block to avoid tail command */ ++ rdlen = len - firstread; ++ if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) { ++ pad = bus->blocksize - (rdlen % bus->blocksize); ++ if ((pad <= bus->roundup) && (pad < bus->blocksize) && ++ ((len + pad) < bus->dhd->maxctl)) ++ rdlen += pad; ++ } else if (rdlen % DHD_SDALIGN) { ++ rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN); ++ } ++ ++ /* Satisfy length-alignment requirements */ ++ if (forcealign && (rdlen & (ALIGNMENT - 1))) ++ rdlen = ROUNDUP(rdlen, ALIGNMENT); ++ ++ /* Drop if the read is too big or it exceeds our maximum */ ++ if ((rdlen + firstread) > bus->dhd->maxctl) { ++ AP6210_ERR("%s: %d-byte control read exceeds %d-byte buffer\n", ++ __FUNCTION__, rdlen, bus->dhd->maxctl); ++ bus->dhd->rx_errors++; ++ dhdsdio_rxfail(bus, FALSE, FALSE); ++ goto done; ++ } ++ ++ if ((len - doff) > bus->dhd->maxctl) { ++ AP6210_ERR("%s: %d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n", ++ __FUNCTION__, len, (len - doff), bus->dhd->maxctl); ++ bus->dhd->rx_errors++; bus->rx_toolong++; ++ dhdsdio_rxfail(bus, FALSE, FALSE); ++ goto done; ++ } ++ ++ ++ /* Read remainder of frame body into the rxctl buffer */ ++ sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, ++ (bus->rxctl + firstread), rdlen, NULL, NULL, NULL); ++ bus->f2rxdata++; ++ ASSERT(sdret != BCME_PENDING); ++ ++ /* Control frame failures need retransmission */ ++ if (sdret < 0) { ++ AP6210_ERR("%s: read %d control bytes failed: %d\n", __FUNCTION__, rdlen, sdret); ++ bus->rxc_errors++; /* dhd.rx_ctlerrs is higher level */ ++ dhdsdio_rxfail(bus, TRUE, TRUE); ++ goto done; ++ } ++ ++gotpkt: ++ ++#ifdef DHD_DEBUG ++ if (DHD_BYTES_ON() && DHD_CTL_ON()) { ++ prhex("RxCtrl", bus->rxctl, len); ++ } ++#endif ++ ++ /* Point to valid data and indicate its length */ ++ bus->rxctl += doff; ++ bus->rxlen = len - doff; ++ ++done: ++ /* Awake any waiters */ ++ dhd_os_ioctl_resp_wake(bus->dhd); ++} ++ ++static uint8 ++dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) ++{ ++ uint16 dlen, totlen; ++ uint8 *dptr, num = 0; ++ ++ uint16 sublen, check; ++ void *pfirst, *plast, *pnext; ++ void * list_tail[DHD_MAX_IFS] = { NULL }; ++ void * list_head[DHD_MAX_IFS] = { NULL }; ++ uint8 idx; ++ osl_t *osh = bus->dhd->osh; ++ ++ int errcode; ++ uint8 chan, seq, doff, sfdoff; ++ uint8 txmax; ++ uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN]; ++ uint reorder_info_len; ++ ++ int ifidx = 0; ++ bool usechain = bus->use_rxchain; ++ ++ /* If packets, issue read(s) and send up packet chain */ ++ /* Return sequence numbers consumed? */ ++ ++ AP6210_DEBUG("dhdsdio_rxglom: start: glomd %p glom %p\n", bus->glomd, bus->glom); ++ ++ /* If there's a descriptor, generate the packet chain */ ++ if (bus->glomd) { ++ dhd_os_sdlock_rxq(bus->dhd); ++ ++ pfirst = plast = pnext = NULL; ++ dlen = (uint16)PKTLEN(osh, bus->glomd); ++ dptr = PKTDATA(osh, bus->glomd); ++ if (!dlen || (dlen & 1)) { ++ AP6210_ERR("%s: bad glomd len (%d), ignore descriptor\n", ++ __FUNCTION__, dlen); ++ dlen = 0; ++ } ++ ++ for (totlen = num = 0; dlen; num++) { ++ /* Get (and move past) next length */ ++ sublen = ltoh16_ua(dptr); ++ dlen -= sizeof(uint16); ++ dptr += sizeof(uint16); ++ if ((sublen < SDPCM_HDRLEN_RX) || ++ ((num == 0) && (sublen < (2 * SDPCM_HDRLEN_RX)))) { ++ AP6210_ERR("%s: descriptor len %d bad: %d\n", ++ __FUNCTION__, num, sublen); ++ pnext = NULL; ++ break; ++ } ++ if (sublen % DHD_SDALIGN) { ++ AP6210_ERR("%s: sublen %d not a multiple of %d\n", ++ __FUNCTION__, sublen, DHD_SDALIGN); ++ usechain = FALSE; ++ } ++ totlen += sublen; ++ ++ /* For last frame, adjust read len so total is a block multiple */ ++ if (!dlen) { ++ sublen += (ROUNDUP(totlen, bus->blocksize) - totlen); ++ totlen = ROUNDUP(totlen, bus->blocksize); ++ } ++ ++ /* Allocate/chain packet for next subframe */ ++ if ((pnext = PKTGET(osh, sublen + DHD_SDALIGN, FALSE)) == NULL) { ++ AP6210_ERR("%s: PKTGET failed, num %d len %d\n", ++ __FUNCTION__, num, sublen); ++ break; ++ } ++ ASSERT(!PKTLINK(pnext)); ++ if (!pfirst) { ++ ASSERT(!plast); ++ pfirst = plast = pnext; ++ } else { ++ ASSERT(plast); ++ PKTSETNEXT(osh, plast, pnext); ++ plast = pnext; ++ } ++ ++ /* Adhere to start alignment requirements */ ++ PKTALIGN(osh, pnext, sublen, DHD_SDALIGN); ++ } ++ ++ /* If all allocations succeeded, save packet chain in bus structure */ ++ if (pnext) { ++ AP6210_DEBUG("%s: allocated %d-byte packet chain for %d subframes\n", ++ __FUNCTION__, totlen, num); ++ if (DHD_GLOM_ON() && bus->nextlen) { ++ if (totlen != bus->nextlen) { ++ AP6210_DEBUG("%s: glomdesc mismatch: nextlen %d glomdesc %d " ++ "rxseq %d\n", __FUNCTION__, bus->nextlen, ++ totlen, rxseq); ++ } ++ } ++ bus->glom = pfirst; ++ pfirst = pnext = NULL; ++ } else { ++ if (pfirst) ++ PKTFREE(osh, pfirst, FALSE); ++ bus->glom = NULL; ++ num = 0; ++ } ++ ++ /* Done with descriptor packet */ ++ PKTFREE(osh, bus->glomd, FALSE); ++ bus->glomd = NULL; ++ bus->nextlen = 0; ++ ++ dhd_os_sdunlock_rxq(bus->dhd); ++ } ++ ++ /* Ok -- either we just generated a packet chain, or had one from before */ ++ if (bus->glom) { ++ if (DHD_GLOM_ON()) { ++ AP6210_DEBUG("%s: attempt superframe read, packet chain:\n", __FUNCTION__); ++ for (pnext = bus->glom; pnext; pnext = PKTNEXT(osh, pnext)) { ++ AP6210_DEBUG(" %p: %p len 0x%04x (%d)\n", ++ pnext, (uint8*)PKTDATA(osh, pnext), ++ PKTLEN(osh, pnext), PKTLEN(osh, pnext)); ++ } ++ } ++ ++ pfirst = bus->glom; ++ dlen = (uint16)pkttotlen(osh, pfirst); ++ ++ /* Do an SDIO read for the superframe. Configurable iovar to ++ * read directly into the chained packet, or allocate a large ++ * packet and and copy into the chain. ++ */ ++ if (usechain) { ++ errcode = dhd_bcmsdh_recv_buf(bus, ++ bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2, ++ F2SYNC, (uint8*)PKTDATA(osh, pfirst), ++ dlen, pfirst, NULL, NULL); ++ } else if (bus->dataptr) { ++ errcode = dhd_bcmsdh_recv_buf(bus, ++ bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2, ++ F2SYNC, bus->dataptr, ++ dlen, NULL, NULL, NULL); ++ sublen = (uint16)pktfrombuf(osh, pfirst, 0, dlen, bus->dataptr); ++ if (sublen != dlen) { ++ AP6210_ERR("%s: FAILED TO COPY, dlen %d sublen %d\n", ++ __FUNCTION__, dlen, sublen); ++ errcode = -1; ++ } ++ pnext = NULL; ++ } else { ++ AP6210_ERR("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", dlen); ++ errcode = -1; ++ } ++ bus->f2rxdata++; ++ ASSERT(errcode != BCME_PENDING); ++ ++ /* On failure, kill the superframe, allow a couple retries */ ++ if (errcode < 0) { ++ AP6210_ERR("%s: glom read of %d bytes failed: %d\n", ++ __FUNCTION__, dlen, errcode); ++ bus->dhd->rx_errors++; ++ ++ if (bus->glomerr++ < 3) { ++ dhdsdio_rxfail(bus, TRUE, TRUE); ++ } else { ++ bus->glomerr = 0; ++ dhdsdio_rxfail(bus, TRUE, FALSE); ++ dhd_os_sdlock_rxq(bus->dhd); ++ PKTFREE(osh, bus->glom, FALSE); ++ dhd_os_sdunlock_rxq(bus->dhd); ++ bus->rxglomfail++; ++ bus->glom = NULL; ++ } ++ return 0; ++ } ++ ++#ifdef DHD_DEBUG ++ if (DHD_GLOM_ON()) { ++ prhex("SUPERFRAME", PKTDATA(osh, pfirst), ++ MIN(PKTLEN(osh, pfirst), 48)); ++ } ++#endif ++ ++ ++ /* Validate the superframe header */ ++ dptr = (uint8 *)PKTDATA(osh, pfirst); ++ sublen = ltoh16_ua(dptr); ++ check = ltoh16_ua(dptr + sizeof(uint16)); ++ ++ chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); ++ seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); ++ bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; ++ if ((bus->nextlen << 4) > MAX_RX_DATASZ) { ++ AP6210_DEBUG("%s: got frame w/nextlen too large (%d) seq %d\n", ++ __FUNCTION__, bus->nextlen, seq); ++ bus->nextlen = 0; ++ } ++ doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); ++ txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); ++ ++ errcode = 0; ++ if ((uint16)~(sublen^check)) { ++ AP6210_ERR("%s (superframe): HW hdr error: len/check 0x%04x/0x%04x\n", ++ __FUNCTION__, sublen, check); ++ errcode = -1; ++ } else if (ROUNDUP(sublen, bus->blocksize) != dlen) { ++ AP6210_ERR("%s (superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n", ++ __FUNCTION__, sublen, ROUNDUP(sublen, bus->blocksize), dlen); ++ errcode = -1; ++ } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != SDPCM_GLOM_CHANNEL) { ++ AP6210_ERR("%s (superframe): bad channel %d\n", __FUNCTION__, ++ SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN])); ++ errcode = -1; ++ } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) { ++ AP6210_ERR("%s (superframe): got second descriptor?\n", __FUNCTION__); ++ errcode = -1; ++ } else if ((doff < SDPCM_HDRLEN_RX) || ++ (doff > (PKTLEN(osh, pfirst) - SDPCM_HDRLEN_RX))) { ++ AP6210_ERR("%s (superframe): Bad data offset %d: HW %d pkt %d min %d\n", ++ __FUNCTION__, doff, sublen, PKTLEN(osh, pfirst), ++ SDPCM_HDRLEN_RX); ++ errcode = -1; ++ } ++ ++ /* Check sequence number of superframe SW header */ ++ if (rxseq != seq) { ++ AP6210_DEBUG("%s: (superframe) rx_seq %d, expected %d\n", ++ __FUNCTION__, seq, rxseq); ++ bus->rx_badseq++; ++ rxseq = seq; ++ } ++ ++ /* Check window for sanity */ ++ if ((uint8)(txmax - bus->tx_seq) > 0x40) { ++ AP6210_ERR("%s: got unlikely tx max %d with tx_seq %d\n", ++ __FUNCTION__, txmax, bus->tx_seq); ++ txmax = bus->tx_max; ++ } ++ bus->tx_max = txmax; ++ ++ /* Remove superframe header, remember offset */ ++ PKTPULL(osh, pfirst, doff); ++ sfdoff = doff; ++ ++ /* Validate all the subframe headers */ ++ for (num = 0, pnext = pfirst; pnext && !errcode; ++ num++, pnext = PKTNEXT(osh, pnext)) { ++ dptr = (uint8 *)PKTDATA(osh, pnext); ++ dlen = (uint16)PKTLEN(osh, pnext); ++ sublen = ltoh16_ua(dptr); ++ check = ltoh16_ua(dptr + sizeof(uint16)); ++ chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); ++ doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); ++#ifdef DHD_DEBUG ++ if (DHD_GLOM_ON()) { ++ prhex("subframe", dptr, 32); ++ } ++#endif ++ ++ if ((uint16)~(sublen^check)) { ++ AP6210_ERR("%s (subframe %d): HW hdr error: " ++ "len/check 0x%04x/0x%04x\n", ++ __FUNCTION__, num, sublen, check); ++ errcode = -1; ++ } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN_RX)) { ++ AP6210_ERR("%s (subframe %d): length mismatch: " ++ "len 0x%04x, expect 0x%04x\n", ++ __FUNCTION__, num, sublen, dlen); ++ errcode = -1; ++ } else if ((chan != SDPCM_DATA_CHANNEL) && ++ (chan != SDPCM_EVENT_CHANNEL)) { ++ AP6210_ERR("%s (subframe %d): bad channel %d\n", ++ __FUNCTION__, num, chan); ++ errcode = -1; ++ } else if ((doff < SDPCM_HDRLEN_RX) || (doff > sublen)) { ++ AP6210_ERR("%s (subframe %d): Bad data offset %d: HW %d min %d\n", ++ __FUNCTION__, num, doff, sublen, SDPCM_HDRLEN_RX); ++ errcode = -1; ++ } ++ } ++ ++ if (errcode) { ++ /* Terminate frame on error, request a couple retries */ ++ if (bus->glomerr++ < 3) { ++ /* Restore superframe header space */ ++ PKTPUSH(osh, pfirst, sfdoff); ++ dhdsdio_rxfail(bus, TRUE, TRUE); ++ } else { ++ bus->glomerr = 0; ++ dhdsdio_rxfail(bus, TRUE, FALSE); ++ dhd_os_sdlock_rxq(bus->dhd); ++ PKTFREE(osh, bus->glom, FALSE); ++ dhd_os_sdunlock_rxq(bus->dhd); ++ bus->rxglomfail++; ++ bus->glom = NULL; ++ } ++ bus->nextlen = 0; ++ return 0; ++ } ++ ++ /* Basic SD framing looks ok - process each packet (header) */ ++ bus->glom = NULL; ++ plast = NULL; ++ ++ dhd_os_sdlock_rxq(bus->dhd); ++ for (num = 0; pfirst; rxseq++, pfirst = pnext) { ++ pnext = PKTNEXT(osh, pfirst); ++ PKTSETNEXT(osh, pfirst, NULL); ++ ++ dptr = (uint8 *)PKTDATA(osh, pfirst); ++ sublen = ltoh16_ua(dptr); ++ chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); ++ seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); ++ doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); ++ ++ AP6210_DEBUG("%s: Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n", ++ __FUNCTION__, num, pfirst, PKTDATA(osh, pfirst), ++ PKTLEN(osh, pfirst), sublen, chan, seq); ++ ++ ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL)); ++ ++ if (rxseq != seq) { ++ AP6210_DEBUG("%s: rx_seq %d, expected %d\n", ++ __FUNCTION__, seq, rxseq); ++ bus->rx_badseq++; ++ rxseq = seq; ++ } ++ ++#ifdef DHD_DEBUG ++ if (DHD_BYTES_ON() && DHD_DATA_ON()) { ++ prhex("Rx Subframe Data", dptr, dlen); ++ } ++#endif ++ ++ PKTSETLEN(osh, pfirst, sublen); ++ PKTPULL(osh, pfirst, doff); ++ ++ reorder_info_len = sizeof(reorder_info_buf); ++ ++ if (PKTLEN(osh, pfirst) == 0) { ++ PKTFREE(bus->dhd->osh, pfirst, FALSE); ++ continue; ++ } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst, reorder_info_buf, ++ &reorder_info_len) != 0) { ++ AP6210_ERR("%s: rx protocol error\n", __FUNCTION__); ++ bus->dhd->rx_errors++; ++ PKTFREE(osh, pfirst, FALSE); ++ continue; ++ } ++ if (reorder_info_len) { ++ uint32 free_buf_count; ++ void *ppfirst; ++ ++ ppfirst = pfirst; ++ /* Reordering info from the firmware */ ++ dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf, ++ reorder_info_len, &ppfirst, &free_buf_count); ++ ++ if (free_buf_count == 0) { ++ continue; ++ } ++ else { ++ void *temp; ++ ++ /* go to the end of the chain and attach the pnext there */ ++ temp = ppfirst; ++ while (PKTNEXT(osh, temp) != NULL) { ++ temp = PKTNEXT(osh, temp); ++ } ++ pfirst = temp; ++ if (list_tail[ifidx] == NULL) { ++ list_head[ifidx] = ppfirst; ++ list_tail[ifidx] = pfirst; ++ } ++ else { ++ PKTSETNEXT(osh, list_tail[ifidx], ppfirst); ++ list_tail[ifidx] = pfirst; ++ } ++ } ++ ++ num += (uint8)free_buf_count; ++ } ++ else { ++ /* this packet will go up, link back into chain and count it */ ++ ++ if (list_tail[ifidx] == NULL) { ++ list_head[ifidx] = list_tail[ifidx] = pfirst; ++ } ++ else { ++ PKTSETNEXT(osh, list_tail[ifidx], pfirst); ++ list_tail[ifidx] = pfirst; ++ } ++ num++; ++ } ++#ifdef DHD_DEBUG ++ if (DHD_GLOM_ON()) { ++ AP6210_DEBUG("%s subframe %d to stack, %p(%p/%d) nxt/lnk %p/%p\n", ++ __FUNCTION__, num, pfirst, ++ PKTDATA(osh, pfirst), PKTLEN(osh, pfirst), ++ PKTNEXT(osh, pfirst), PKTLINK(pfirst)); ++ prhex("", (uint8 *)PKTDATA(osh, pfirst), ++ MIN(PKTLEN(osh, pfirst), 32)); ++ } ++#endif /* DHD_DEBUG */ ++ } ++ dhd_os_sdunlock_rxq(bus->dhd); ++ ++ for (idx = 0; idx < DHD_MAX_IFS; idx++) { ++ if (list_head[idx]) { ++ void *temp; ++ uint8 cnt = 0; ++ temp = list_head[idx]; ++ do { ++ temp = PKTNEXT(osh, temp); ++ cnt++; ++ } while (temp); ++ if (cnt) { ++ dhd_os_sdunlock(bus->dhd); ++ dhd_rx_frame(bus->dhd, idx, list_head[idx], cnt, 0); ++ dhd_os_sdlock(bus->dhd); ++ } ++ } ++ } ++ bus->rxglomframes++; ++ bus->rxglompkts += num; ++ } ++ return num; ++} ++ ++ ++/* Return TRUE if there may be more frames to read */ ++static uint ++dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) ++{ ++ osl_t *osh = bus->dhd->osh; ++ bcmsdh_info_t *sdh = bus->sdh; ++ ++ uint16 len, check; /* Extracted hardware header fields */ ++ uint8 chan, seq, doff; /* Extracted software header fields */ ++ uint8 fcbits; /* Extracted fcbits from software header */ ++ uint8 delta; ++ ++ void *pkt; /* Packet for event or data frames */ ++ uint16 pad; /* Number of pad bytes to read */ ++ uint16 rdlen; /* Total number of bytes to read */ ++ uint8 rxseq; /* Next sequence number to expect */ ++ uint rxleft = 0; /* Remaining number of frames allowed */ ++ int sdret; /* Return code from bcmsdh calls */ ++ uint8 txmax; /* Maximum tx sequence offered */ ++ bool len_consistent; /* Result of comparing readahead len and len from hw-hdr */ ++ uint8 *rxbuf; ++ int ifidx = 0; ++ uint rxcount = 0; /* Total frames read */ ++ uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN]; ++ uint reorder_info_len; ++ uint pkt_count; ++ ++#if defined(DHD_DEBUG) || defined(SDTEST) ++ bool sdtest = FALSE; /* To limit message spew from test mode */ ++#endif ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ bus->readframes = TRUE; ++ ++ if (!KSO_ENAB(bus)) { ++ AP6210_DEBUG("%s: KSO off\n", __FUNCTION__); ++ bus->readframes = FALSE; ++ return 0; ++ } ++ ++ ASSERT(maxframes); ++ ++#ifdef SDTEST ++ /* Allow pktgen to override maxframes */ ++ if (bus->pktgen_count && (bus->pktgen_mode == DHD_PKTGEN_RECV)) { ++ maxframes = bus->pktgen_count; ++ sdtest = TRUE; ++ } ++#endif ++ ++ /* Not finished unless we encounter no more frames indication */ ++ *finished = FALSE; ++ ++ ++ for (rxseq = bus->rx_seq, rxleft = maxframes; ++ !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN; ++ rxseq++, rxleft--) { ++ ++#ifdef DHDTHREAD ++ /* terence: fix got unlikely tx max for 43362a0*/ ++ if (bus->sih->chip!=BCM43362_CHIP_ID && bus->sih->chiprev!=BCM43362A0_CHIP_REV) { ++ /* tx more to improve rx performance */ ++ if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && ++ pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) { ++ dhdsdio_sendfromq(bus, dhd_txbound); ++ } ++ } ++#endif /* DHDTHREAD */ ++ ++ /* Handle glomming separately */ ++ if (bus->glom || bus->glomd) { ++ uint8 cnt; ++ AP6210_DEBUG("%s: calling rxglom: glomd %p, glom %p\n", ++ __FUNCTION__, bus->glomd, bus->glom); ++ cnt = dhdsdio_rxglom(bus, rxseq); ++ AP6210_DEBUG("%s: rxglom returned %d\n", __FUNCTION__, cnt); ++ rxseq += cnt - 1; ++ rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1; ++ continue; ++ } ++ ++ /* Try doing single read if we can */ ++ if (dhd_readahead && bus->nextlen) { ++ uint16 nextlen = bus->nextlen; ++ bus->nextlen = 0; ++ ++ if (bus->bus == SPI_BUS) { ++ rdlen = len = nextlen; ++ } ++ else { ++ rdlen = len = nextlen << 4; ++ ++ /* Pad read to blocksize for efficiency */ ++ if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) { ++ pad = bus->blocksize - (rdlen % bus->blocksize); ++ if ((pad <= bus->roundup) && (pad < bus->blocksize) && ++ ((rdlen + pad + firstread) < MAX_RX_DATASZ)) ++ rdlen += pad; ++ } else if (rdlen % DHD_SDALIGN) { ++ rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN); ++ } ++ } ++ ++ /* We use bus->rxctl buffer in WinXP for initial control pkt receives. ++ * Later we use buffer-poll for data as well as control packets. ++ * This is required because dhd receives full frame in gSPI unlike SDIO. ++ * After the frame is received we have to distinguish whether it is data ++ * or non-data frame. ++ */ ++ /* Allocate a packet buffer */ ++ dhd_os_sdlock_rxq(bus->dhd); ++ if (!(pkt = PKTGET(osh, rdlen + DHD_SDALIGN, FALSE))) { ++ if (bus->bus == SPI_BUS) { ++ bus->usebufpool = FALSE; ++ bus->rxctl = bus->rxbuf; ++ if (dhd_alignctl) { ++ bus->rxctl += firstread; ++ if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN))) ++ bus->rxctl += (DHD_SDALIGN - pad); ++ bus->rxctl -= firstread; ++ } ++ ASSERT(bus->rxctl >= bus->rxbuf); ++ rxbuf = bus->rxctl; ++ /* Read the entire frame */ ++ sdret = dhd_bcmsdh_recv_buf(bus, ++ bcmsdh_cur_sbwad(sdh), ++ SDIO_FUNC_2, ++ F2SYNC, rxbuf, rdlen, ++ NULL, NULL, NULL); ++ bus->f2rxdata++; ++ ASSERT(sdret != BCME_PENDING); ++ ++ ++ /* Control frame failures need retransmission */ ++ if (sdret < 0) { ++ AP6210_ERR("%s: read %d control bytes failed: %d\n", ++ __FUNCTION__, rdlen, sdret); ++ /* dhd.rx_ctlerrs is higher level */ ++ bus->rxc_errors++; ++ dhd_os_sdunlock_rxq(bus->dhd); ++ dhdsdio_rxfail(bus, TRUE, ++ (bus->bus == SPI_BUS) ? FALSE : TRUE); ++ continue; ++ } ++ } else { ++ /* Give up on data, request rtx of events */ ++ AP6210_ERR("%s (nextlen): PKTGET failed: len %d rdlen %d " ++ "expected rxseq %d\n", ++ __FUNCTION__, len, rdlen, rxseq); ++ /* Just go try again w/normal header read */ ++ dhd_os_sdunlock_rxq(bus->dhd); ++ continue; ++ } ++ } else { ++ if (bus->bus == SPI_BUS) ++ bus->usebufpool = TRUE; ++ ++ ASSERT(!PKTLINK(pkt)); ++ PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN); ++ rxbuf = (uint8 *)PKTDATA(osh, pkt); ++ /* Read the entire frame */ ++ sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), ++ SDIO_FUNC_2, ++ F2SYNC, rxbuf, rdlen, ++ pkt, NULL, NULL); ++ bus->f2rxdata++; ++ ASSERT(sdret != BCME_PENDING); ++ ++ if (sdret < 0) { ++ AP6210_ERR("%s (nextlen): read %d bytes failed: %d\n", ++ __FUNCTION__, rdlen, sdret); ++ PKTFREE(bus->dhd->osh, pkt, FALSE); ++ bus->dhd->rx_errors++; ++ dhd_os_sdunlock_rxq(bus->dhd); ++ /* Force retry w/normal header read. Don't attempt NAK for ++ * gSPI ++ */ ++ dhdsdio_rxfail(bus, TRUE, ++ (bus->bus == SPI_BUS) ? FALSE : TRUE); ++ continue; ++ } ++ } ++ dhd_os_sdunlock_rxq(bus->dhd); ++ ++ /* Now check the header */ ++ bcopy(rxbuf, bus->rxhdr, SDPCM_HDRLEN_RX); ++ ++ /* Extract hardware header fields */ ++ len = ltoh16_ua(bus->rxhdr); ++ check = ltoh16_ua(bus->rxhdr + sizeof(uint16)); ++ ++ /* All zeros means readahead info was bad */ ++ if (!(len|check)) { ++ AP6210_DEBUG("%s (nextlen): read zeros in HW header???\n", ++ __FUNCTION__); ++ dhd_os_sdlock_rxq(bus->dhd); ++ PKTFREE2(); ++ dhd_os_sdunlock_rxq(bus->dhd); ++ GSPI_PR55150_BAILOUT; ++ continue; ++ } ++ ++ /* Validate check bytes */ ++ if ((uint16)~(len^check)) { ++ AP6210_ERR("%s (nextlen): HW hdr error: nextlen/len/check" ++ " 0x%04x/0x%04x/0x%04x\n", __FUNCTION__, nextlen, ++ len, check); ++ dhd_os_sdlock_rxq(bus->dhd); ++ PKTFREE2(); ++ dhd_os_sdunlock_rxq(bus->dhd); ++ bus->rx_badhdr++; ++ dhdsdio_rxfail(bus, FALSE, FALSE); ++ GSPI_PR55150_BAILOUT; ++ continue; ++ } ++ ++ /* Validate frame length */ ++ if (len < SDPCM_HDRLEN_RX) { ++ AP6210_ERR("%s (nextlen): HW hdr length invalid: %d\n", ++ __FUNCTION__, len); ++ dhd_os_sdlock_rxq(bus->dhd); ++ PKTFREE2(); ++ dhd_os_sdunlock_rxq(bus->dhd); ++ GSPI_PR55150_BAILOUT; ++ continue; ++ } ++ ++ /* Check for consistency with readahead info */ ++ len_consistent = (nextlen != (ROUNDUP(len, 16) >> 4)); ++ if (len_consistent) { ++ /* Mismatch, force retry w/normal header (may be >4K) */ ++ AP6210_ERR("%s (nextlen): mismatch, nextlen %d len %d rnd %d; " ++ "expected rxseq %d\n", ++ __FUNCTION__, nextlen, len, ROUNDUP(len, 16), rxseq); ++ dhd_os_sdlock_rxq(bus->dhd); ++ PKTFREE2(); ++ dhd_os_sdunlock_rxq(bus->dhd); ++ dhdsdio_rxfail(bus, TRUE, (bus->bus == SPI_BUS) ? FALSE : TRUE); ++ GSPI_PR55150_BAILOUT; ++ continue; ++ } ++ ++ ++ /* Extract software header fields */ ++ chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ ++ bus->nextlen = ++ bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; ++ if ((bus->nextlen << 4) > MAX_RX_DATASZ) { ++ AP6210_DEBUG("%s (nextlen): got frame w/nextlen too large" ++ " (%d), seq %d\n", __FUNCTION__, bus->nextlen, ++ seq); ++ bus->nextlen = 0; ++ } ++ ++ bus->dhd->rx_readahead_cnt ++; ++ /* Handle Flow Control */ ++ fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ ++ delta = 0; ++ if (~bus->flowcontrol & fcbits) { ++ bus->fc_xoff++; ++ delta = 1; ++ } ++ if (bus->flowcontrol & ~fcbits) { ++ bus->fc_xon++; ++ delta = 1; ++ } ++ ++ if (delta) { ++ bus->fc_rcvd++; ++ bus->flowcontrol = fcbits; ++ } ++ ++ /* Check and update sequence number */ ++ if (rxseq != seq) { ++ AP6210_DEBUG("%s (nextlen): rx_seq %d, expected %d\n", ++ __FUNCTION__, seq, rxseq); ++ bus->rx_badseq++; ++ rxseq = seq; ++ } ++ ++ /* Check window for sanity */ ++ if ((uint8)(txmax - bus->tx_seq) > 0x40) { ++ AP6210_ERR("%s: got unlikely tx max %d with tx_seq %d\n", ++ __FUNCTION__, txmax, bus->tx_seq); ++ txmax = bus->tx_max; ++ } ++ bus->tx_max = txmax; ++ ++#ifdef DHD_DEBUG ++ if (DHD_BYTES_ON() && DHD_DATA_ON()) { ++ prhex("Rx Data", rxbuf, len); ++ } else if (DHD_HDRS_ON()) { ++ prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN_RX); ++ } ++#endif ++ ++ if (chan == SDPCM_CONTROL_CHANNEL) { ++ if (bus->bus == SPI_BUS) { ++ dhdsdio_read_control(bus, rxbuf, len, doff); ++ if (bus->usebufpool) { ++ dhd_os_sdlock_rxq(bus->dhd); ++ PKTFREE(bus->dhd->osh, pkt, FALSE); ++ dhd_os_sdunlock_rxq(bus->dhd); ++ } ++ continue; ++ } else { ++ AP6210_ERR("%s (nextlen): readahead on control" ++ " packet %d?\n", __FUNCTION__, seq); ++ /* Force retry w/normal header read */ ++ bus->nextlen = 0; ++ dhdsdio_rxfail(bus, FALSE, TRUE); ++ dhd_os_sdlock_rxq(bus->dhd); ++ PKTFREE2(); ++ dhd_os_sdunlock_rxq(bus->dhd); ++ continue; ++ } ++ } ++ ++ if ((bus->bus == SPI_BUS) && !bus->usebufpool) { ++ AP6210_ERR("Received %d bytes on %d channel. Running out of " ++ "rx pktbuf's or not yet malloced.\n", len, chan); ++ continue; ++ } ++ ++ /* Validate data offset */ ++ if ((doff < SDPCM_HDRLEN_RX) || (doff > len)) { ++ AP6210_ERR("%s (nextlen): bad data offset %d: HW len %d min %d\n", ++ __FUNCTION__, doff, len, SDPCM_HDRLEN_RX); ++ dhd_os_sdlock_rxq(bus->dhd); ++ PKTFREE2(); ++ dhd_os_sdunlock_rxq(bus->dhd); ++ ASSERT(0); ++ dhdsdio_rxfail(bus, FALSE, FALSE); ++ continue; ++ } ++ ++ /* All done with this one -- now deliver the packet */ ++ goto deliver; ++ } ++ /* gSPI frames should not be handled in fractions */ ++ if (bus->bus == SPI_BUS) { ++ break; ++ } ++ ++ /* Read frame header (hardware and software) */ ++ sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, ++ bus->rxhdr, firstread, NULL, NULL, NULL); ++ bus->f2rxhdrs++; ++ ASSERT(sdret != BCME_PENDING); ++ ++ if (sdret < 0) { ++ AP6210_ERR("%s: RXHEADER FAILED: %d\n", __FUNCTION__, sdret); ++ bus->rx_hdrfail++; ++ dhdsdio_rxfail(bus, TRUE, TRUE); ++ continue; ++ } ++ ++#ifdef DHD_DEBUG ++ if (DHD_BYTES_ON() || DHD_HDRS_ON()) { ++ prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN_RX); ++ } ++#endif ++ ++ /* Extract hardware header fields */ ++ len = ltoh16_ua(bus->rxhdr); ++ check = ltoh16_ua(bus->rxhdr + sizeof(uint16)); ++ ++ /* All zeros means no more frames */ ++ if (!(len|check)) { ++ *finished = TRUE; ++ break; ++ } ++ ++ /* Validate check bytes */ ++ if ((uint16)~(len^check)) { ++ AP6210_ERR("%s: HW hdr error: len/check 0x%04x/0x%04x\n", ++ __FUNCTION__, len, check); ++ bus->rx_badhdr++; ++ dhdsdio_rxfail(bus, FALSE, FALSE); ++ continue; ++ } ++ ++ /* Validate frame length */ ++ if (len < SDPCM_HDRLEN_RX) { ++ AP6210_ERR("%s: HW hdr length invalid: %d\n", __FUNCTION__, len); ++ continue; ++ } ++ ++ /* Extract software header fields */ ++ chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ ++ /* Validate data offset */ ++ if ((doff < SDPCM_HDRLEN_RX) || (doff > len)) { ++ AP6210_ERR("%s: Bad data offset %d: HW len %d, min %d seq %d\n", ++ __FUNCTION__, doff, len, SDPCM_HDRLEN_RX, seq); ++ bus->rx_badhdr++; ++ ASSERT(0); ++ dhdsdio_rxfail(bus, FALSE, FALSE); ++ continue; ++ } ++ ++ /* Save the readahead length if there is one */ ++ bus->nextlen = bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; ++ if ((bus->nextlen << 4) > MAX_RX_DATASZ) { ++ AP6210_DEBUG("%s (nextlen): got frame w/nextlen too large (%d), seq %d\n", ++ __FUNCTION__, bus->nextlen, seq); ++ bus->nextlen = 0; ++ } ++ ++ /* Handle Flow Control */ ++ fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); ++ ++ delta = 0; ++ if (~bus->flowcontrol & fcbits) { ++ bus->fc_xoff++; ++ delta = 1; ++ } ++ if (bus->flowcontrol & ~fcbits) { ++ bus->fc_xon++; ++ delta = 1; ++ } ++ ++ if (delta) { ++ bus->fc_rcvd++; ++ bus->flowcontrol = fcbits; ++ } ++ ++ /* Check and update sequence number */ ++ if (rxseq != seq) { ++ AP6210_DEBUG("%s: rx_seq %d, expected %d\n", __FUNCTION__, seq, rxseq); ++ bus->rx_badseq++; ++ rxseq = seq; ++ } ++ ++ /* Check window for sanity */ ++ if ((uint8)(txmax - bus->tx_seq) > 0x40) { ++ AP6210_ERR("%s: got unlikely tx max %d with tx_seq %d\n", ++ __FUNCTION__, txmax, bus->tx_seq); ++ txmax = bus->tx_max; ++ } ++ bus->tx_max = txmax; ++ ++ /* Call a separate function for control frames */ ++ if (chan == SDPCM_CONTROL_CHANNEL) { ++ dhdsdio_read_control(bus, bus->rxhdr, len, doff); ++ continue; ++ } ++ ++ ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL) || ++ (chan == SDPCM_TEST_CHANNEL) || (chan == SDPCM_GLOM_CHANNEL)); ++ ++ /* Length to read */ ++ rdlen = (len > firstread) ? (len - firstread) : 0; ++ ++ /* May pad read to blocksize for efficiency */ ++ if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) { ++ pad = bus->blocksize - (rdlen % bus->blocksize); ++ if ((pad <= bus->roundup) && (pad < bus->blocksize) && ++ ((rdlen + pad + firstread) < MAX_RX_DATASZ)) ++ rdlen += pad; ++ } else if (rdlen % DHD_SDALIGN) { ++ rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN); ++ } ++ ++ /* Satisfy length-alignment requirements */ ++ if (forcealign && (rdlen & (ALIGNMENT - 1))) ++ rdlen = ROUNDUP(rdlen, ALIGNMENT); ++ ++ if ((rdlen + firstread) > MAX_RX_DATASZ) { ++ /* Too long -- skip this frame */ ++ AP6210_ERR("%s: too long: len %d rdlen %d\n", __FUNCTION__, len, rdlen); ++ bus->dhd->rx_errors++; bus->rx_toolong++; ++ dhdsdio_rxfail(bus, FALSE, FALSE); ++ continue; ++ } ++ ++ dhd_os_sdlock_rxq(bus->dhd); ++ if (!(pkt = PKTGET(osh, (rdlen + firstread + DHD_SDALIGN), FALSE))) { ++ /* Give up on data, request rtx of events */ ++ AP6210_ERR("%s: PKTGET failed: rdlen %d chan %d\n", ++ __FUNCTION__, rdlen, chan); ++ bus->dhd->rx_dropped++; ++ dhd_os_sdunlock_rxq(bus->dhd); ++ dhdsdio_rxfail(bus, FALSE, RETRYCHAN(chan)); ++ continue; ++ } ++ dhd_os_sdunlock_rxq(bus->dhd); ++ ++ ASSERT(!PKTLINK(pkt)); ++ ++ /* Leave room for what we already read, and align remainder */ ++ ASSERT(firstread < (PKTLEN(osh, pkt))); ++ PKTPULL(osh, pkt, firstread); ++ PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN); ++ ++ /* Read the remaining frame data */ ++ sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, ++ ((uint8 *)PKTDATA(osh, pkt)), rdlen, pkt, NULL, NULL); ++ bus->f2rxdata++; ++ ASSERT(sdret != BCME_PENDING); ++ ++ if (sdret < 0) { ++ AP6210_ERR("%s: read %d %s bytes failed: %d\n", __FUNCTION__, rdlen, ++ ((chan == SDPCM_EVENT_CHANNEL) ? "event" : ++ ((chan == SDPCM_DATA_CHANNEL) ? "data" : "test")), sdret); ++ dhd_os_sdlock_rxq(bus->dhd); ++ PKTFREE(bus->dhd->osh, pkt, FALSE); ++ dhd_os_sdunlock_rxq(bus->dhd); ++ bus->dhd->rx_errors++; ++ dhdsdio_rxfail(bus, TRUE, RETRYCHAN(chan)); ++ continue; ++ } ++ ++ /* Copy the already-read portion */ ++ PKTPUSH(osh, pkt, firstread); ++ bcopy(bus->rxhdr, PKTDATA(osh, pkt), firstread); ++ ++#ifdef DHD_DEBUG ++ if (DHD_BYTES_ON() && DHD_DATA_ON()) { ++ prhex("Rx Data", PKTDATA(osh, pkt), len); ++ } ++#endif ++ ++deliver: ++ /* Save superframe descriptor and allocate packet frame */ ++ if (chan == SDPCM_GLOM_CHANNEL) { ++ if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) { ++ AP6210_DEBUG("%s: got glom descriptor, %d bytes:\n", ++ __FUNCTION__, len); ++#ifdef DHD_DEBUG ++ if (DHD_GLOM_ON()) { ++ prhex("Glom Data", PKTDATA(osh, pkt), len); ++ } ++#endif ++ PKTSETLEN(osh, pkt, len); ++ ASSERT(doff == SDPCM_HDRLEN_RX); ++ PKTPULL(osh, pkt, SDPCM_HDRLEN_RX); ++ bus->glomd = pkt; ++ } else { ++ AP6210_ERR("%s: glom superframe w/o descriptor!\n", __FUNCTION__); ++ dhdsdio_rxfail(bus, FALSE, FALSE); ++ } ++ continue; ++ } ++ ++ /* Fill in packet len and prio, deliver upward */ ++ PKTSETLEN(osh, pkt, len); ++ PKTPULL(osh, pkt, doff); ++ ++#ifdef SDTEST ++ /* Test channel packets are processed separately */ ++ if (chan == SDPCM_TEST_CHANNEL) { ++ dhdsdio_testrcv(bus, pkt, seq); ++ continue; ++ } ++#endif /* SDTEST */ ++ ++ if (PKTLEN(osh, pkt) == 0) { ++ dhd_os_sdlock_rxq(bus->dhd); ++ PKTFREE(bus->dhd->osh, pkt, FALSE); ++ dhd_os_sdunlock_rxq(bus->dhd); ++ continue; ++ } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt, reorder_info_buf, ++ &reorder_info_len) != 0) { ++ AP6210_ERR("%s: rx protocol error\n", __FUNCTION__); ++ dhd_os_sdlock_rxq(bus->dhd); ++ PKTFREE(bus->dhd->osh, pkt, FALSE); ++ dhd_os_sdunlock_rxq(bus->dhd); ++ bus->dhd->rx_errors++; ++ continue; ++ } ++ if (reorder_info_len) { ++ /* Reordering info from the firmware */ ++ dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf, reorder_info_len, ++ &pkt, &pkt_count); ++ if (pkt_count == 0) ++ continue; ++ } ++ else ++ pkt_count = 1; ++ ++ ++ /* Unlock during rx call */ ++ dhd_os_sdunlock(bus->dhd); ++ dhd_rx_frame(bus->dhd, ifidx, pkt, pkt_count, chan); ++ dhd_os_sdlock(bus->dhd); ++ } ++ rxcount = maxframes - rxleft; ++#ifdef DHD_DEBUG ++ /* Message if we hit the limit */ ++ if (!rxleft && !sdtest) ++ AP6210_DEBUG("%s: hit rx limit of %d frames\n", __FUNCTION__, maxframes); ++ else ++#endif /* DHD_DEBUG */ ++ AP6210_DEBUG("%s: processed %d frames\n", __FUNCTION__, rxcount); ++ /* Back off rxseq if awaiting rtx, update rx_seq */ ++ if (bus->rxskip) ++ rxseq--; ++ bus->rx_seq = rxseq; ++ ++ if (bus->reqbussleep) ++ { ++ dhdsdio_bussleep(bus, TRUE); ++ bus->reqbussleep = FALSE; ++ } ++ bus->readframes = FALSE; ++ ++ return rxcount; ++} ++ ++static uint32 ++dhdsdio_hostmail(dhd_bus_t *bus) ++{ ++ sdpcmd_regs_t *regs = bus->regs; ++ uint32 intstatus = 0; ++ uint32 hmb_data; ++ uint8 fcbits; ++ uint retries = 0; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ /* Read mailbox data and ack that we did so */ ++ R_SDREG(hmb_data, ®s->tohostmailboxdata, retries); ++ if (retries <= retry_limit) ++ W_SDREG(SMB_INT_ACK, ®s->tosbmailbox, retries); ++ bus->f1regdata += 2; ++ ++ /* Dongle recomposed rx frames, accept them again */ ++ if (hmb_data & HMB_DATA_NAKHANDLED) { ++ AP6210_DEBUG("Dongle reports NAK handled, expect rtx of %d\n", bus->rx_seq); ++ if (!bus->rxskip) { ++ AP6210_ERR("%s: unexpected NAKHANDLED!\n", __FUNCTION__); ++ } ++ bus->rxskip = FALSE; ++ intstatus |= FRAME_AVAIL_MASK(bus); ++ } ++ ++ /* ++ * DEVREADY does not occur with gSPI. ++ */ ++ if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) { ++ bus->sdpcm_ver = (hmb_data & HMB_DATA_VERSION_MASK) >> HMB_DATA_VERSION_SHIFT; ++ if (bus->sdpcm_ver != SDPCM_PROT_VERSION) ++ AP6210_ERR("Version mismatch, dongle reports %d, expecting %d\n", ++ bus->sdpcm_ver, SDPCM_PROT_VERSION); ++ else ++ AP6210_ERR("Dongle ready, protocol version %d\n", bus->sdpcm_ver); ++ /* make sure for the SDIO_DEVICE_RXDATAINT_MODE_1 corecontrol is proper */ ++ if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) && ++ (bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_1)) { ++ uint32 val; ++ ++ val = R_REG(bus->dhd->osh, &bus->regs->corecontrol); ++ val &= ~CC_XMTDATAAVAIL_MODE; ++ val |= CC_XMTDATAAVAIL_CTRL; ++ W_REG(bus->dhd->osh, &bus->regs->corecontrol, val); ++ ++ val = R_REG(bus->dhd->osh, &bus->regs->corecontrol); ++ } ++ ++#ifdef DHD_DEBUG ++ /* Retrieve console state address now that firmware should have updated it */ ++ { ++ sdpcm_shared_t shared; ++ if (dhdsdio_readshared(bus, &shared) == 0) ++ bus->console_addr = shared.console_addr; ++ } ++#endif /* DHD_DEBUG */ ++ } ++ ++ /* ++ * Flow Control has been moved into the RX headers and this out of band ++ * method isn't used any more. Leave this here for possibly remaining backward ++ * compatible with older dongles ++ */ ++ if (hmb_data & HMB_DATA_FC) { ++ fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >> HMB_DATA_FCDATA_SHIFT; ++ ++ if (fcbits & ~bus->flowcontrol) ++ bus->fc_xoff++; ++ if (bus->flowcontrol & ~fcbits) ++ bus->fc_xon++; ++ ++ bus->fc_rcvd++; ++ bus->flowcontrol = fcbits; ++ } ++ ++#ifdef DHD_DEBUG ++ /* At least print a message if FW halted */ ++ if (hmb_data & HMB_DATA_FWHALT) { ++ AP6210_ERR("INTERNAL ERROR: FIRMWARE HALTED : set BUS DOWN\n"); ++ dhdsdio_checkdied(bus, NULL, 0); ++ bus->dhd->busstate = DHD_BUS_DOWN; ++ } ++#endif /* DHD_DEBUG */ ++ ++ /* Shouldn't be any others */ ++ if (hmb_data & ~(HMB_DATA_DEVREADY | ++ HMB_DATA_FWHALT | ++ HMB_DATA_NAKHANDLED | ++ HMB_DATA_FC | ++ HMB_DATA_FWREADY | ++ HMB_DATA_FCDATA_MASK | ++ HMB_DATA_VERSION_MASK)) { ++ AP6210_ERR("Unknown mailbox data content: 0x%02x\n", hmb_data); ++ } ++ ++ return intstatus; ++} ++ ++static bool ++dhdsdio_dpc(dhd_bus_t *bus) ++{ ++ bcmsdh_info_t *sdh = bus->sdh; ++ sdpcmd_regs_t *regs = bus->regs; ++ uint32 intstatus, newstatus = 0; ++ uint retries = 0; ++ uint rxlimit = dhd_rxbound; /* Rx frames to read before resched */ ++ uint txlimit = dhd_txbound; /* Tx frames to send before resched */ ++ uint framecnt = 0; /* Temporary counter of tx/rx frames */ ++ bool rxdone = TRUE; /* Flag for no more read data */ ++ bool resched = FALSE; /* Flag indicating resched wanted */ ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (bus->dhd->busstate == DHD_BUS_DOWN) { ++ AP6210_ERR("%s: Bus down, ret\n", __FUNCTION__); ++ bus->intstatus = 0; ++ return 0; ++ } ++ ++ /* Start with leftover status bits */ ++ intstatus = bus->intstatus; ++ ++ dhd_os_sdlock(bus->dhd); ++ ++ if (!SLPAUTO_ENAB(bus) && !KSO_ENAB(bus)) { ++ AP6210_ERR("%s: Device asleep\n", __FUNCTION__); ++ goto exit; ++ } ++ ++ /* If waiting for HTAVAIL, check status */ ++ if (!SLPAUTO_ENAB(bus) && (bus->clkstate == CLK_PENDING)) { ++ int err; ++ uint8 clkctl, devctl = 0; ++ ++#ifdef DHD_DEBUG ++ /* Check for inconsistent device control */ ++ devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); ++ if (err) { ++ AP6210_ERR("%s: error reading DEVCTL: %d\n", __FUNCTION__, err); ++ bus->dhd->busstate = DHD_BUS_DOWN; ++ } else { ++ ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY); ++ } ++#endif /* DHD_DEBUG */ ++ ++ /* Read CSR, if clock on switch to AVAIL, else ignore */ ++ clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ if (err) { ++ AP6210_ERR("%s: error reading CSR: %d\n", __FUNCTION__, err); ++ bus->dhd->busstate = DHD_BUS_DOWN; ++ } ++ ++ AP6210_DEBUG("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl, clkctl); ++ ++ if (SBSDIO_HTAV(clkctl)) { ++ devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); ++ if (err) { ++ AP6210_ERR("%s: error reading DEVCTL: %d\n", ++ __FUNCTION__, err); ++ bus->dhd->busstate = DHD_BUS_DOWN; ++ } ++ devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); ++ if (err) { ++ AP6210_ERR("%s: error writing DEVCTL: %d\n", ++ __FUNCTION__, err); ++ bus->dhd->busstate = DHD_BUS_DOWN; ++ } ++ bus->clkstate = CLK_AVAIL; ++ } else { ++ goto clkwait; ++ } ++ } ++ ++ BUS_WAKE(bus); ++ ++ /* Make sure backplane clock is on */ ++ dhdsdio_clkctl(bus, CLK_AVAIL, TRUE); ++ if (bus->clkstate != CLK_AVAIL) ++ goto clkwait; ++ ++ /* Pending interrupt indicates new device status */ ++ if (bus->ipend) { ++ bus->ipend = FALSE; ++ R_SDREG(newstatus, ®s->intstatus, retries); ++ bus->f1regdata++; ++ if (bcmsdh_regfail(bus->sdh)) ++ newstatus = 0; ++ newstatus &= bus->hostintmask; ++ bus->fcstate = !!(newstatus & I_HMB_FC_STATE); ++ if (newstatus) { ++ bus->f1regdata++; ++ if ((bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_0) && ++ (newstatus == I_XMTDATA_AVAIL)) { ++ } ++ else ++ W_SDREG(newstatus, ®s->intstatus, retries); ++ } ++ } ++ ++ /* Merge new bits with previous */ ++ intstatus |= newstatus; ++ bus->intstatus = 0; ++ ++ /* Handle flow-control change: read new state in case our ack ++ * crossed another change interrupt. If change still set, assume ++ * FC ON for safety, let next loop through do the debounce. ++ */ ++ if (intstatus & I_HMB_FC_CHANGE) { ++ intstatus &= ~I_HMB_FC_CHANGE; ++ W_SDREG(I_HMB_FC_CHANGE, ®s->intstatus, retries); ++ R_SDREG(newstatus, ®s->intstatus, retries); ++ bus->f1regdata += 2; ++ bus->fcstate = !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); ++ intstatus |= (newstatus & bus->hostintmask); ++ } ++ ++ /* Just being here means nothing more to do for chipactive */ ++ if (intstatus & I_CHIPACTIVE) { ++ /* ASSERT(bus->clkstate == CLK_AVAIL); */ ++ intstatus &= ~I_CHIPACTIVE; ++ } ++ ++ /* Handle host mailbox indication */ ++ if (intstatus & I_HMB_HOST_INT) { ++ intstatus &= ~I_HMB_HOST_INT; ++ intstatus |= dhdsdio_hostmail(bus); ++ } ++ ++ /* Generally don't ask for these, can get CRC errors... */ ++ if (intstatus & I_WR_OOSYNC) { ++ AP6210_DEBUG("Dongle reports WR_OOSYNC\n"); ++ intstatus &= ~I_WR_OOSYNC; ++ } ++ ++ if (intstatus & I_RD_OOSYNC) { ++ AP6210_DEBUG("Dongle reports RD_OOSYNC\n"); ++ intstatus &= ~I_RD_OOSYNC; ++ } ++ ++ if (intstatus & I_SBINT) { ++ AP6210_DEBUG("Dongle reports SBINT\n"); ++ intstatus &= ~I_SBINT; ++ } ++ ++ /* Would be active due to wake-wlan in gSPI */ ++ if (intstatus & I_CHIPACTIVE) { ++ AP6210_DEBUG("Dongle reports CHIPACTIVE\n"); ++ intstatus &= ~I_CHIPACTIVE; ++ } ++ ++ /* Ignore frame indications if rxskip is set */ ++ if (bus->rxskip) { ++ intstatus &= ~FRAME_AVAIL_MASK(bus); ++ } ++ ++ /* On frame indication, read available frames */ ++ if (PKT_AVAILABLE(bus, intstatus)) { ++ framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone); ++ if (rxdone || bus->rxskip) ++ intstatus &= ~FRAME_AVAIL_MASK(bus); ++ rxlimit -= MIN(framecnt, rxlimit); ++ } ++ ++ /* Keep still-pending events for next scheduling */ ++ bus->intstatus = intstatus; ++ ++clkwait: ++ /* Re-enable interrupts to detect new device events (mailbox, rx frame) ++ * or clock availability. (Allows tx loop to check ipend if desired.) ++ * (Unless register access seems hosed, as we may not be able to ACK...) ++ */ ++ if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) { ++ AP6210_DEBUG("%s: enable SDIO interrupts, rxdone %d framecnt %d\n", ++ __FUNCTION__, rxdone, framecnt); ++ bus->intdis = FALSE; ++#if defined(OOB_INTR_ONLY) ++ bcmsdh_oob_intr_set(1); ++#endif /* defined(OOB_INTR_ONLY) */ ++ bcmsdh_intr_enable(sdh); ++ } ++ ++#if defined(OOB_INTR_ONLY) && !defined(HW_OOB) ++ /* In case of SW-OOB(using edge trigger), ++ * Check interrupt status in the dongle again after enable irq on the host. ++ * and rechedule dpc if interrupt is pended in the dongle. ++ * There is a chance to miss OOB interrupt while irq is disabled on the host. ++ * No need to do this with HW-OOB(level trigger) ++ */ ++ R_SDREG(newstatus, ®s->intstatus, retries); ++ if (bcmsdh_regfail(bus->sdh)) ++ newstatus = 0; ++ if (newstatus & bus->hostintmask) { ++ bus->ipend = TRUE; ++ resched = TRUE; ++ } ++#endif /* defined(OOB_INTR_ONLY) && !defined(HW_OOB) */ ++#ifdef PROP_TXSTATUS ++ dhd_wlfc_trigger_pktcommit(bus->dhd); ++#endif ++ if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) { ++ int ret, i; ++ ++ uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN; ++ ++ if (*frame_seq != bus->tx_seq) { ++ AP6210_DEBUG("%s IOCTL frame seq lag detected!" ++ " frm_seq:%d != bus->tx_seq:%d, corrected\n", ++ __FUNCTION__, *frame_seq, bus->tx_seq); ++ *frame_seq = bus->tx_seq; ++ } ++ ++ ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, ++ (uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len, ++ NULL, NULL, NULL); ++ ASSERT(ret != BCME_PENDING); ++ if (ret == BCME_NODEVICE) { ++ AP6210_ERR("%s: Device asleep already\n", __FUNCTION__); ++ } else if (ret < 0) { ++ /* On failure, abort the command and terminate the frame */ ++ AP6210_DEBUG("%s: sdio error %d, abort command and terminate frame.\n", ++ __FUNCTION__, ret); ++ bus->tx_sderrs++; ++ ++ bcmsdh_abort(sdh, SDIO_FUNC_2); ++ ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, ++ SFC_WF_TERM, NULL); ++ bus->f1regdata++; ++ ++ for (i = 0; i < 3; i++) { ++ uint8 hi, lo; ++ hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCHI, NULL); ++ lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, ++ SBSDIO_FUNC1_WFRAMEBCLO, NULL); ++ bus->f1regdata += 2; ++ if ((hi == 0) && (lo == 0)) ++ break; ++ } ++ } ++ if (ret == 0) { ++ bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; ++ } ++ ++ bus->ctrl_frame_stat = FALSE; ++ dhd_wait_event_wakeup(bus->dhd); ++ } ++ /* Send queued frames (limit 1 if rx may still be pending) */ ++ else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && ++ pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) { ++ framecnt = rxdone ? txlimit : MIN(txlimit, dhd_txminmax); ++ framecnt = dhdsdio_sendfromq(bus, framecnt); ++ txlimit -= framecnt; ++ } ++ /* Resched the DPC if ctrl cmd is pending on bus credit */ ++ if (bus->ctrl_frame_stat) ++ resched = TRUE; ++ ++ /* Resched if events or tx frames are pending, else await next interrupt */ ++ /* On failed register access, all bets are off: no resched or interrupts */ ++ if ((bus->dhd->busstate == DHD_BUS_DOWN) || bcmsdh_regfail(sdh)) { ++ if ((bus->sih && bus->sih->buscorerev >= 12) && !(dhdsdio_sleepcsr_get(bus) & ++ SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) { ++ /* Bus failed because of KSO */ ++ AP6210_ERR("%s: Bus failed due to KSO\n", __FUNCTION__); ++ bus->kso = FALSE; ++ } else { ++ AP6210_ERR("%s: failed backplane access over SDIO, halting operation\n", ++ __FUNCTION__); ++ bus->dhd->busstate = DHD_BUS_DOWN; ++ bus->intstatus = 0; ++ } ++ } else if (bus->clkstate == CLK_PENDING) { ++ /* Awaiting I_CHIPACTIVE; don't resched */ ++ } else if (bus->intstatus || bus->ipend || ++ (!bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) || ++ PKT_AVAILABLE(bus, bus->intstatus)) { /* Read multiple frames */ ++ resched = TRUE; ++ } ++ ++ bus->dpc_sched = resched; ++ ++ /* If we're done for now, turn off clock request. */ ++ if ((bus->idletime == DHD_IDLE_IMMEDIATE) && (bus->clkstate != CLK_PENDING)) { ++ bus->activity = FALSE; ++ dhdsdio_clkctl(bus, CLK_NONE, FALSE); ++ } ++ ++exit: ++ dhd_os_sdunlock(bus->dhd); ++ return resched; ++} ++ ++bool ++dhd_bus_dpc(struct dhd_bus *bus) ++{ ++ bool resched; ++ ++ /* Call the DPC directly. */ ++ AP6210_DEBUG("Calling dhdsdio_dpc() from %s\n", __FUNCTION__); ++ resched = dhdsdio_dpc(bus); ++ ++ return resched; ++} ++ ++void ++dhdsdio_isr(void *arg) ++{ ++ dhd_bus_t *bus = (dhd_bus_t*)arg; ++ bcmsdh_info_t *sdh; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (!bus) { ++ AP6210_ERR("%s : bus is null pointer , exit \n", __FUNCTION__); ++ return; ++ } ++ sdh = bus->sdh; ++ ++ if (bus->dhd->busstate == DHD_BUS_DOWN) { ++ AP6210_ERR("%s : bus is down. we have nothing to do\n", __FUNCTION__); ++ return; ++ } ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ /* Count the interrupt call */ ++ bus->intrcount++; ++ bus->ipend = TRUE; ++ ++ /* Shouldn't get this interrupt if we're sleeping? */ ++ if (!SLPAUTO_ENAB(bus)) { ++ if (bus->sleeping) { ++ AP6210_ERR("INTERRUPT WHILE SLEEPING??\n"); ++ return; ++ } else if (!KSO_ENAB(bus)) { ++ AP6210_ERR("ISR in devsleep 1\n"); ++ } ++ } ++ ++ /* Disable additional interrupts (is this needed now)? */ ++ if (bus->intr) { ++ AP6210_DEBUG("%s: disable SDIO interrupts\n", __FUNCTION__); ++ } else { ++ AP6210_ERR("dhdsdio_isr() w/o interrupt configured!\n"); ++ } ++ ++ bcmsdh_intr_disable(sdh); ++ bus->intdis = TRUE; ++ ++#if defined(SDIO_ISR_THREAD) ++ AP6210_DEBUG("Calling dhdsdio_dpc() from %s\n", __FUNCTION__); ++ DHD_OS_WAKE_LOCK(bus->dhd); ++ while (dhdsdio_dpc(bus)); ++ DHD_OS_WAKE_UNLOCK(bus->dhd); ++#else ++ bus->dpc_sched = TRUE; ++ dhd_sched_dpc(bus->dhd); ++#endif ++ ++} ++ ++#ifdef SDTEST ++static void ++dhdsdio_pktgen_init(dhd_bus_t *bus) ++{ ++ /* Default to specified length, or full range */ ++ if (dhd_pktgen_len) { ++ bus->pktgen_maxlen = MIN(dhd_pktgen_len, MAX_PKTGEN_LEN); ++ bus->pktgen_minlen = bus->pktgen_maxlen; ++ } else { ++ bus->pktgen_maxlen = MAX_PKTGEN_LEN; ++ bus->pktgen_minlen = 0; ++ } ++ bus->pktgen_len = (uint16)bus->pktgen_minlen; ++ ++ /* Default to per-watchdog burst with 10s print time */ ++ bus->pktgen_freq = 1; ++ bus->pktgen_print = dhd_watchdog_ms ? (10000/dhd_watchdog_ms):0; ++ bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000; ++ ++ /* Default to echo mode */ ++ bus->pktgen_mode = DHD_PKTGEN_ECHO; ++ bus->pktgen_stop = 1; ++} ++ ++static void ++dhdsdio_pktgen(dhd_bus_t *bus) ++{ ++ void *pkt; ++ uint8 *data; ++ uint pktcount; ++ uint fillbyte; ++ osl_t *osh = bus->dhd->osh; ++ uint16 len; ++ ulong time_lapse; ++ uint sent_pkts; ++ uint rcvd_pkts; ++ ++ /* Display current count if appropriate */ ++ if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) { ++ bus->pktgen_ptick = 0; ++ AP6210_DEBUG("%s: send attempts %d, rcvd %d, errors %d\n", ++ __FUNCTION__, bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail); ++ ++ /* Print throughput stats only for constant length packet runs */ ++ if (bus->pktgen_minlen == bus->pktgen_maxlen) { ++ time_lapse = jiffies - bus->pktgen_prev_time; ++ bus->pktgen_prev_time = jiffies; ++ sent_pkts = bus->pktgen_sent - bus->pktgen_prev_sent; ++ bus->pktgen_prev_sent = bus->pktgen_sent; ++ rcvd_pkts = bus->pktgen_rcvd - bus->pktgen_prev_rcvd; ++ bus->pktgen_prev_rcvd = bus->pktgen_rcvd; ++ ++ AP6210_DEBUG("%s: Tx Throughput %d kbps, Rx Throughput %d kbps\n", ++ __FUNCTION__, ++ (sent_pkts * bus->pktgen_len / jiffies_to_msecs(time_lapse)) * 8, ++ (rcvd_pkts * bus->pktgen_len / jiffies_to_msecs(time_lapse)) * 8); ++ } ++ } ++ ++ /* For recv mode, just make sure dongle has started sending */ ++ if (bus->pktgen_mode == DHD_PKTGEN_RECV) { ++ if (bus->pktgen_rcv_state == PKTGEN_RCV_IDLE) { ++ bus->pktgen_rcv_state = PKTGEN_RCV_ONGOING; ++ dhdsdio_sdtest_set(bus, bus->pktgen_total); ++ } ++ return; ++ } ++ ++ /* Otherwise, generate or request the specified number of packets */ ++ for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) { ++ /* Stop if total has been reached */ ++ if (bus->pktgen_total && (bus->pktgen_sent >= bus->pktgen_total)) { ++ bus->pktgen_count = 0; ++ break; ++ } ++ ++ /* Allocate an appropriate-sized packet */ ++ if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) { ++ len = SDPCM_TEST_PKT_CNT_FLD_LEN; ++ } else { ++ len = bus->pktgen_len; ++ } ++ if (!(pkt = PKTGET(osh, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN), ++ TRUE))) {; ++ AP6210_ERR("%s: PKTGET failed!\n", __FUNCTION__); ++ break; ++ } ++ PKTALIGN(osh, pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN); ++ data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN; ++ ++ /* Write test header cmd and extra based on mode */ ++ switch (bus->pktgen_mode) { ++ case DHD_PKTGEN_ECHO: ++ *data++ = SDPCM_TEST_ECHOREQ; ++ *data++ = (uint8)bus->pktgen_sent; ++ break; ++ ++ case DHD_PKTGEN_SEND: ++ *data++ = SDPCM_TEST_DISCARD; ++ *data++ = (uint8)bus->pktgen_sent; ++ break; ++ ++ case DHD_PKTGEN_RXBURST: ++ *data++ = SDPCM_TEST_BURST; ++ *data++ = (uint8)bus->pktgen_count; /* Just for backward compatability */ ++ break; ++ ++ default: ++ AP6210_ERR("Unrecognized pktgen mode %d\n", bus->pktgen_mode); ++ PKTFREE(osh, pkt, TRUE); ++ bus->pktgen_count = 0; ++ return; ++ } ++ ++ /* Write test header length field */ ++ *data++ = (bus->pktgen_len >> 0); ++ *data++ = (bus->pktgen_len >> 8); ++ ++ /* Write frame count in a 4 byte field adjucent to SDPCM test header for ++ * burst mode ++ */ ++ if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) { ++ *data++ = (uint8)(bus->pktgen_count >> 0); ++ *data++ = (uint8)(bus->pktgen_count >> 8); ++ *data++ = (uint8)(bus->pktgen_count >> 16); ++ *data++ = (uint8)(bus->pktgen_count >> 24); ++ } else { ++ ++ /* Then fill in the remainder -- N/A for burst */ ++ for (fillbyte = 0; fillbyte < len; fillbyte++) ++ *data++ = SDPCM_TEST_FILL(fillbyte, (uint8)bus->pktgen_sent); ++ } ++ ++#ifdef DHD_DEBUG ++ if (DHD_BYTES_ON() && DHD_DATA_ON()) { ++ data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN; ++ prhex("dhdsdio_pktgen: Tx Data", data, PKTLEN(osh, pkt) - SDPCM_HDRLEN); ++ } ++#endif ++ ++ /* Send it */ ++ if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, TRUE, FALSE)) { ++ bus->pktgen_fail++; ++ if (bus->pktgen_stop && bus->pktgen_stop == bus->pktgen_fail) ++ bus->pktgen_count = 0; ++ } ++ bus->pktgen_sent++; ++ ++ /* Bump length if not fixed, wrap at max */ ++ if (++bus->pktgen_len > bus->pktgen_maxlen) ++ bus->pktgen_len = (uint16)bus->pktgen_minlen; ++ ++ /* Special case for burst mode: just send one request! */ ++ if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) ++ break; ++ } ++} ++ ++static void ++dhdsdio_sdtest_set(dhd_bus_t *bus, uint count) ++{ ++ void *pkt; ++ uint8 *data; ++ osl_t *osh = bus->dhd->osh; ++ ++ /* Allocate the packet */ ++ if (!(pkt = PKTGET(osh, SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + ++ SDPCM_TEST_PKT_CNT_FLD_LEN + DHD_SDALIGN, TRUE))) { ++ AP6210_ERR("%s: PKTGET failed!\n", __FUNCTION__); ++ return; ++ } ++ PKTALIGN(osh, pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + ++ SDPCM_TEST_PKT_CNT_FLD_LEN), DHD_SDALIGN); ++ data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN; ++ ++ /* Fill in the test header */ ++ *data++ = SDPCM_TEST_SEND; ++ *data++ = (count > 0)?TRUE:FALSE; ++ *data++ = (bus->pktgen_maxlen >> 0); ++ *data++ = (bus->pktgen_maxlen >> 8); ++ *data++ = (uint8)(count >> 0); ++ *data++ = (uint8)(count >> 8); ++ *data++ = (uint8)(count >> 16); ++ *data++ = (uint8)(count >> 24); ++ ++ /* Send it */ ++ if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, TRUE, FALSE)) ++ bus->pktgen_fail++; ++} ++ ++ ++static void ++dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq) ++{ ++ osl_t *osh = bus->dhd->osh; ++ uint8 *data; ++ uint pktlen; ++ ++ uint8 cmd; ++ uint8 extra; ++ uint16 len; ++ uint16 offset; ++ ++ /* Check for min length */ ++ if ((pktlen = PKTLEN(osh, pkt)) < SDPCM_TEST_HDRLEN) { ++ AP6210_ERR("dhdsdio_restrcv: toss runt frame, pktlen %d\n", pktlen); ++ PKTFREE(osh, pkt, FALSE); ++ return; ++ } ++ ++ /* Extract header fields */ ++ data = PKTDATA(osh, pkt); ++ cmd = *data++; ++ extra = *data++; ++ len = *data++; len += *data++ << 8; ++ AP6210_DEBUG("%s:cmd:%d, xtra:%d,len:%d\n", __FUNCTION__, cmd, extra, len); ++ /* Check length for relevant commands */ ++ if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ || cmd == SDPCM_TEST_ECHORSP) { ++ if (pktlen != len + SDPCM_TEST_HDRLEN) { ++ AP6210_ERR("dhdsdio_testrcv: frame length mismatch, pktlen %d seq %d" ++ " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len); ++ PKTFREE(osh, pkt, FALSE); ++ return; ++ } ++ } ++ ++ /* Process as per command */ ++ switch (cmd) { ++ case SDPCM_TEST_ECHOREQ: ++ /* Rx->Tx turnaround ok (even on NDIS w/current implementation) */ ++ *(uint8 *)(PKTDATA(osh, pkt)) = SDPCM_TEST_ECHORSP; ++ if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, TRUE, FALSE) == 0) { ++ bus->pktgen_sent++; ++ } else { ++ bus->pktgen_fail++; ++ PKTFREE(osh, pkt, FALSE); ++ } ++ bus->pktgen_rcvd++; ++ break; ++ ++ case SDPCM_TEST_ECHORSP: ++ if (bus->ext_loop) { ++ PKTFREE(osh, pkt, FALSE); ++ bus->pktgen_rcvd++; ++ break; ++ } ++ ++ for (offset = 0; offset < len; offset++, data++) { ++ if (*data != SDPCM_TEST_FILL(offset, extra)) { ++ AP6210_ERR("dhdsdio_testrcv: echo data mismatch: " ++ "offset %d (len %d) expect 0x%02x rcvd 0x%02x\n", ++ offset, len, SDPCM_TEST_FILL(offset, extra), *data); ++ break; ++ } ++ } ++ PKTFREE(osh, pkt, FALSE); ++ bus->pktgen_rcvd++; ++ break; ++ ++ case SDPCM_TEST_DISCARD: ++ { ++ int i = 0; ++ uint8 *prn = data; ++ uint8 testval = extra; ++ for (i = 0; i < len; i++) { ++ if (*prn != testval) { ++ AP6210_ERR("DIErr@Pkt#:%d,Ix:%d, expected:0x%x, got:0x%x\n", ++ i, bus->pktgen_rcvd_rcvsession, testval, *prn); ++ prn++; testval++; ++ } ++ } ++ } ++ PKTFREE(osh, pkt, FALSE); ++ bus->pktgen_rcvd++; ++ break; ++ ++ case SDPCM_TEST_BURST: ++ case SDPCM_TEST_SEND: ++ default: ++ AP6210_DEBUG("dhdsdio_testrcv: unsupported or unknown command, pktlen %d seq %d" ++ " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len); ++ PKTFREE(osh, pkt, FALSE); ++ break; ++ } ++ ++ /* For recv mode, stop at limit (and tell dongle to stop sending) */ ++ if (bus->pktgen_mode == DHD_PKTGEN_RECV) { ++ if (bus->pktgen_rcv_state != PKTGEN_RCV_IDLE) { ++ bus->pktgen_rcvd_rcvsession++; ++ ++ if (bus->pktgen_total && ++ (bus->pktgen_rcvd_rcvsession >= bus->pktgen_total)) { ++ bus->pktgen_count = 0; ++ AP6210_ERR("Pktgen:rcv test complete!\n"); ++ bus->pktgen_rcv_state = PKTGEN_RCV_IDLE; ++ dhdsdio_sdtest_set(bus, FALSE); ++ bus->pktgen_rcvd_rcvsession = 0; ++ } ++ } ++ } ++} ++#endif /* SDTEST */ ++ ++extern void ++dhd_disable_intr(dhd_pub_t *dhdp) ++{ ++ dhd_bus_t *bus; ++ bus = dhdp->bus; ++ bcmsdh_intr_disable(bus->sdh); ++} ++ ++extern bool ++dhd_bus_watchdog(dhd_pub_t *dhdp) ++{ ++ dhd_bus_t *bus; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ bus = dhdp->bus; ++ ++ if (bus->dhd->dongle_reset) ++ return FALSE; ++ ++ /* Ignore the timer if simulating bus down */ ++ if (!SLPAUTO_ENAB(bus) && bus->sleeping) ++ return FALSE; ++ ++ if (dhdp->busstate == DHD_BUS_DOWN) ++ return FALSE; ++ ++ /* Poll period: check device if appropriate. */ ++ if (!SLPAUTO_ENAB(bus) && (bus->poll && (++bus->polltick >= bus->pollrate))) { ++ uint32 intstatus = 0; ++ ++ /* Reset poll tick */ ++ bus->polltick = 0; ++ ++ /* Check device if no interrupts */ ++ if (!bus->intr || (bus->intrcount == bus->lastintrs)) { ++ ++ if (!bus->dpc_sched) { ++ uint8 devpend; ++ devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, ++ SDIOD_CCCR_INTPEND, NULL); ++ intstatus = devpend & (INTR_STATUS_FUNC1 | INTR_STATUS_FUNC2); ++ } ++ ++ /* If there is something, make like the ISR and schedule the DPC */ ++ if (intstatus) { ++ bus->pollcnt++; ++ bus->ipend = TRUE; ++ if (bus->intr) { ++ bcmsdh_intr_disable(bus->sdh); ++ } ++ bus->dpc_sched = TRUE; ++ dhd_sched_dpc(bus->dhd); ++ ++ } ++ } ++ ++ /* Update interrupt tracking */ ++ bus->lastintrs = bus->intrcount; ++ } ++ ++#ifdef DHD_DEBUG ++ /* Poll for console output periodically */ ++ if (dhdp->busstate == DHD_BUS_DATA && dhd_console_ms != 0) { ++ bus->console.count += dhd_watchdog_ms; ++ if (bus->console.count >= dhd_console_ms) { ++ bus->console.count -= dhd_console_ms; ++ /* Make sure backplane clock is on */ ++ if (SLPAUTO_ENAB(bus)) ++ dhdsdio_bussleep(bus, FALSE); ++ else ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); ++ if (dhdsdio_readconsole(bus) < 0) ++ dhd_console_ms = 0; /* On error, stop trying */ ++ } ++ } ++#endif /* DHD_DEBUG */ ++ ++#ifdef SDTEST ++ /* Generate packets if configured */ ++ if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) { ++ /* Make sure backplane clock is on */ ++ if (SLPAUTO_ENAB(bus)) ++ dhdsdio_bussleep(bus, FALSE); ++ else ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); ++ bus->pktgen_tick = 0; ++ dhdsdio_pktgen(bus); ++ } ++#endif ++ ++ /* On idle timeout clear activity flag and/or turn off clock */ ++#ifdef DHD_USE_IDLECOUNT ++ if (bus->activity) ++ bus->activity = FALSE; ++ else { ++ bus->idlecount++; ++ ++ if (bus->idlecount >= bus->idletime) { ++ AP6210_DEBUG("%s: DHD Idle state!!\n", __FUNCTION__); ++ ++ if (SLPAUTO_ENAB(bus)) { ++ if (dhdsdio_bussleep(bus, TRUE) != BCME_BUSY) ++ dhd_os_wd_timer(bus->dhd, 0); ++ } else ++ dhdsdio_clkctl(bus, CLK_NONE, FALSE); ++ ++ bus->idlecount = 0; ++ } ++ } ++#else ++ if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { ++ if (++bus->idlecount > bus->idletime) { ++ bus->idlecount = 0; ++ if (bus->activity) { ++ bus->activity = FALSE; ++ if (SLPAUTO_ENAB(bus)) { ++ if (!bus->readframes) ++ dhdsdio_bussleep(bus, TRUE); ++ else ++ bus->reqbussleep = TRUE; ++ } ++ else ++ dhdsdio_clkctl(bus, CLK_NONE, FALSE); ++ } ++ } ++ } ++#endif /* DHD_USE_IDLECOUNT */ ++ ++ return bus->ipend; ++} ++ ++#ifdef DHD_DEBUG ++extern int ++dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen) ++{ ++ dhd_bus_t *bus = dhdp->bus; ++ uint32 addr, val; ++ int rv; ++ void *pkt; ++ ++ /* Address could be zero if CONSOLE := 0 in dongle Makefile */ ++ if (bus->console_addr == 0) ++ return BCME_UNSUPPORTED; ++ ++ /* Exclusive bus access */ ++ dhd_os_sdlock(bus->dhd); ++ ++ /* Don't allow input if dongle is in reset */ ++ if (bus->dhd->dongle_reset) { ++ dhd_os_sdunlock(bus->dhd); ++ return BCME_NOTREADY; ++ } ++ ++ /* Request clock to allow SDIO accesses */ ++ BUS_WAKE(bus); ++ /* No pend allowed since txpkt is called later, ht clk has to be on */ ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); ++ ++ /* Zero cbuf_index */ ++ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf_idx); ++ val = htol32(0); ++ if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0) ++ goto done; ++ ++ /* Write message into cbuf */ ++ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf); ++ if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)msg, msglen)) < 0) ++ goto done; ++ ++ /* Write length into vcons_in */ ++ addr = bus->console_addr + OFFSETOF(hndrte_cons_t, vcons_in); ++ val = htol32(msglen); ++ if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0) ++ goto done; ++ ++ /* Bump dongle by sending an empty packet on the event channel. ++ * sdpcm_sendup (RX) checks for virtual console input. ++ */ ++ if ((pkt = PKTGET(bus->dhd->osh, 4 + SDPCM_RESERVE, TRUE)) != NULL) ++ dhdsdio_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, TRUE, FALSE); ++ ++done: ++ if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { ++ bus->activity = FALSE; ++ dhdsdio_clkctl(bus, CLK_NONE, TRUE); ++ } ++ ++ dhd_os_sdunlock(bus->dhd); ++ ++ return rv; ++} ++#endif /* DHD_DEBUG */ ++ ++#ifdef DHD_DEBUG ++static void ++dhd_dump_cis(uint fn, uint8 *cis) ++{ ++ uint byte, tag, tdata; ++ AP6210_DEBUG("Function %d CIS:\n", fn); ++ ++ for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) { ++ if ((byte % 16) == 0) ++ AP6210_DUMP(" "); ++ AP6210_DUMP("%02x ", cis[byte]); ++ if ((byte % 16) == 15) ++ AP6210_DUMP("\n"); ++ if (!tdata--) { ++ tag = cis[byte]; ++ if (tag == 0xff) ++ break; ++ else if (!tag) ++ tdata = 0; ++ else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT) ++ tdata = cis[byte + 1] + 1; ++ else ++ AP6210_DUMP("]"); ++ } ++ } ++ if ((byte % 16) != 15) ++ AP6210_DUMP("\n"); ++} ++#endif /* DHD_DEBUG */ ++ ++static bool ++dhdsdio_chipmatch(uint16 chipid) ++{ ++ if (chipid == BCM4325_CHIP_ID) ++ return TRUE; ++ if (chipid == BCM4329_CHIP_ID) ++ return TRUE; ++ if (chipid == BCM4315_CHIP_ID) ++ return TRUE; ++ if (chipid == BCM4319_CHIP_ID) ++ return TRUE; ++ if (chipid == BCM4336_CHIP_ID) ++ return TRUE; ++ if (chipid == BCM4330_CHIP_ID) ++ return TRUE; ++ if (chipid == BCM43237_CHIP_ID) ++ return TRUE; ++ if (chipid == BCM43362_CHIP_ID) ++ return TRUE; ++ if (chipid == BCM4314_CHIP_ID) ++ return TRUE; ++ if (chipid == BCM4334_CHIP_ID) ++ return TRUE; ++ if (chipid == BCM43341_CHIP_ID) ++ return TRUE; ++ if (chipid == BCM43239_CHIP_ID) ++ return TRUE; ++ if (chipid == BCM4324_CHIP_ID) ++ return TRUE; ++ if (chipid == BCM4335_CHIP_ID) ++ return TRUE; ++ return FALSE; ++} ++ ++static void * ++dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, ++ uint16 func, uint bustype, void *regsva, osl_t * osh, void *sdh) ++{ ++ int ret; ++ dhd_bus_t *bus; ++#ifdef GET_CUSTOM_MAC_ENABLE ++ struct ether_addr ea_addr; ++#endif /* GET_CUSTOM_MAC_ENABLE */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++ ++ if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) { ++ AP6210_DEBUG("%s : no mutex held. set lock\n", __FUNCTION__); ++ } ++ else { ++ AP6210_DEBUG("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__); ++ } ++ mutex_lock(&_dhd_sdio_mutex_lock_); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ ++ ++ /* Init global variables at run-time, not as part of the declaration. ++ * This is required to support init/de-init of the driver. Initialization ++ * of globals as part of the declaration results in non-deterministic ++ * behavior since the value of the globals may be different on the ++ * first time that the driver is initialized vs subsequent initializations. ++ */ ++ dhd_txbound = DHD_TXBOUND; ++ dhd_rxbound = DHD_RXBOUND; ++ dhd_alignctl = TRUE; ++ sd1idle = TRUE; ++ dhd_readahead = TRUE; ++ retrydata = FALSE; ++ dhd_doflow = FALSE; ++ dhd_dongle_memsize = 0; ++ dhd_txminmax = DHD_TXMINMAX; ++ ++ forcealign = TRUE; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ AP6210_DEBUG("%s: venid 0x%04x devid 0x%04x\n", __FUNCTION__, venid, devid); ++ ++ /* We make assumptions about address window mappings */ ++ ASSERT((uintptr)regsva == SI_ENUM_BASE); ++ ++ /* BCMSDH passes venid and devid based on CIS parsing -- but low-power start ++ * means early parse could fail, so here we should get either an ID ++ * we recognize OR (-1) indicating we must request power first. ++ */ ++ /* Check the Vendor ID */ ++ switch (venid) { ++ case 0x0000: ++ case VENDOR_BROADCOM: ++ break; ++ default: ++ AP6210_ERR("%s: unknown vendor: 0x%04x\n", ++ __FUNCTION__, venid); ++ goto forcereturn; ++ } ++ ++ /* Check the Device ID and make sure it's one that we support */ ++ switch (devid) { ++ case BCM4325_D11DUAL_ID: /* 4325 802.11a/g id */ ++ case BCM4325_D11G_ID: /* 4325 802.11g 2.4Ghz band id */ ++ case BCM4325_D11A_ID: /* 4325 802.11a 5Ghz band id */ ++ AP6210_DEBUG("%s: found 4325 Dongle\n", __FUNCTION__); ++ break; ++ case BCM4329_D11N_ID: /* 4329 802.11n dualband device */ ++ case BCM4329_D11N2G_ID: /* 4329 802.11n 2.4G device */ ++ case BCM4329_D11N5G_ID: /* 4329 802.11n 5G device */ ++ case 0x4329: ++ AP6210_DEBUG("%s: found 4329 Dongle\n", __FUNCTION__); ++ break; ++ case BCM4315_D11DUAL_ID: /* 4315 802.11a/g id */ ++ case BCM4315_D11G_ID: /* 4315 802.11g id */ ++ case BCM4315_D11A_ID: /* 4315 802.11a id */ ++ AP6210_DEBUG("%s: found 4315 Dongle\n", __FUNCTION__); ++ break; ++ case BCM4319_D11N_ID: /* 4319 802.11n id */ ++ case BCM4319_D11N2G_ID: /* 4319 802.11n2g id */ ++ case BCM4319_D11N5G_ID: /* 4319 802.11n5g id */ ++ AP6210_DEBUG("%s: found 4319 Dongle\n", __FUNCTION__); ++ break; ++ case 0: ++ AP6210_DEBUG("%s: allow device id 0, will check chip internals\n", ++ __FUNCTION__); ++ break; ++ ++ default: ++ AP6210_ERR("%s: skipping 0x%04x/0x%04x, not a dongle\n", ++ __FUNCTION__, venid, devid); ++ goto forcereturn; ++ } ++ ++ if (osh == NULL) { ++ /* Ask the OS interface part for an OSL handle */ ++ if (!(osh = dhd_osl_attach(sdh, DHD_BUS))) { ++ AP6210_ERR("%s: osl_attach failed!\n", __FUNCTION__); ++ goto forcereturn; ++ } ++ } ++ ++ /* Allocate private bus interface state */ ++ if (!(bus = MALLOC(osh, sizeof(dhd_bus_t)))) { ++ AP6210_ERR("%s: MALLOC of dhd_bus_t failed\n", __FUNCTION__); ++ goto fail; ++ } ++ bzero(bus, sizeof(dhd_bus_t)); ++ bus->sdh = sdh; ++ bus->cl_devid = (uint16)devid; ++ bus->bus = DHD_BUS; ++ bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1; ++ bus->usebufpool = FALSE; /* Use bufpool if allocated, else use locally malloced rxbuf */ ++ ++ /* attach the common module */ ++ dhd_common_init(osh); ++ ++ /* attempt to attach to the dongle */ ++ if (!(dhdsdio_probe_attach(bus, osh, sdh, regsva, devid))) { ++ AP6210_ERR("%s: dhdsdio_probe_attach failed\n", __FUNCTION__); ++ goto fail; ++ } ++ ++ /* Attach to the dhd/OS/network interface */ ++ if (!(bus->dhd = dhd_attach(osh, bus, SDPCM_RESERVE))) { ++ AP6210_ERR("%s: dhd_attach failed\n", __FUNCTION__); ++ goto fail; ++ } ++ ++ /* Allocate buffers */ ++ if (!(dhdsdio_probe_malloc(bus, osh, sdh))) { ++ AP6210_ERR("%s: dhdsdio_probe_malloc failed\n", __FUNCTION__); ++ goto fail; ++ } ++ ++ if (!(dhdsdio_probe_init(bus, osh, sdh))) { ++ AP6210_ERR("%s: dhdsdio_probe_init failed\n", __FUNCTION__); ++ goto fail; ++ } ++ ++ if (bus->intr) { ++ /* Register interrupt callback, but mask it (not operational yet). */ ++ AP6210_DEBUG("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__); ++ bcmsdh_intr_disable(sdh); ++ if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) { ++ AP6210_ERR("%s: FAILED: bcmsdh_intr_reg returned %d\n", ++ __FUNCTION__, ret); ++ goto fail; ++ } ++ AP6210_DEBUG("%s: registered SDIO interrupt function ok\n", __FUNCTION__); ++ } else { ++ AP6210_DEBUG("%s: SDIO interrupt function is NOT registered due to polling mode\n", ++ __FUNCTION__); ++ } ++ ++ AP6210_DEBUG("%s: completed!!\n", __FUNCTION__); ++ ++#ifdef GET_CUSTOM_MAC_ENABLE ++ /* Read MAC address from external customer place */ ++ memset(&ea_addr, 0, sizeof(ea_addr)); ++ ret = dhd_custom_get_mac_address(ea_addr.octet); ++ if (!ret) { ++ memcpy(bus->dhd->mac.octet, (void *)&ea_addr, ETHER_ADDR_LEN); ++ } ++#endif /* GET_CUSTOM_MAC_ENABLE */ ++ ++ /* if firmware path present try to download and bring up bus */ ++ if (dhd_download_fw_on_driverload) { ++ if ((ret = dhd_bus_start(bus->dhd)) != 0) { ++ AP6210_ERR("%s: dhd_bus_start failed\n", __FUNCTION__); ++ goto fail; ++ } ++ } ++ /* Ok, have the per-port tell the stack we're open for business */ ++ if (dhd_net_attach(bus->dhd, 0) != 0) { ++ AP6210_ERR("%s: Net attach failed!!\n", __FUNCTION__); ++ goto fail; ++ } ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++ mutex_unlock(&_dhd_sdio_mutex_lock_); ++ AP6210_DEBUG("%s : the lock is released.\n", __FUNCTION__); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++ ++ return bus; ++ ++fail: ++ dhdsdio_release(bus, osh); ++ ++forcereturn: ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++ mutex_unlock(&_dhd_sdio_mutex_lock_); ++ AP6210_DEBUG("%s : the lock is released.\n", __FUNCTION__); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++ ++ return NULL; ++} ++ ++static bool ++dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, ++ uint16 devid) ++{ ++ int err = 0; ++ uint8 clkctl = 0; ++ ++ bus->alp_only = TRUE; ++ bus->sih = NULL; ++ ++ /* Return the window to backplane enumeration space for core access */ ++ if (dhdsdio_set_siaddr_window(bus, SI_ENUM_BASE)) { ++ AP6210_ERR("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__); ++ } ++ ++#ifdef DHD_DEBUG ++ AP6210_DEBUG("F1 signature read @0x18000000=0x%4x\n", ++ bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4)); ++ ++#endif /* DHD_DEBUG */ ++ ++ ++ /* Force PLL off until si_attach() programs PLL control regs */ ++ ++ ++ ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, DHD_INIT_CLKCTL1, &err); ++ if (!err) ++ clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); ++ ++ if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) { ++ AP6210_ERR("dhdsdio_probe: ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n", ++ err, DHD_INIT_CLKCTL1, clkctl); ++ goto fail; ++ } ++ ++#ifdef DHD_DEBUG ++ if (DHD_INFO_ON()) { ++ uint fn, numfn; ++ uint8 *cis[SDIOD_MAX_IOFUNCS]; ++ int err = 0; ++ ++ numfn = bcmsdh_query_iofnum(sdh); ++ ASSERT(numfn <= SDIOD_MAX_IOFUNCS); ++ ++ /* Make sure ALP is available before trying to read CIS */ ++ SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, NULL)), ++ !SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY); ++ ++ /* Now request ALP be put on the bus */ ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, ++ DHD_INIT_CLKCTL2, &err); ++ OSL_DELAY(65); ++ ++ for (fn = 0; fn <= numfn; fn++) { ++ if (!(cis[fn] = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) { ++ AP6210_DEBUG("dhdsdio_probe: fn %d cis malloc failed\n", fn); ++ break; ++ } ++ bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT); ++ ++ if ((err = bcmsdh_cis_read(sdh, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT))) { ++ AP6210_DEBUG("dhdsdio_probe: fn %d cis read err %d\n", fn, err); ++ MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); ++ break; ++ } ++ dhd_dump_cis(fn, cis[fn]); ++ } ++ ++ while (fn-- > 0) { ++ ASSERT(cis[fn]); ++ MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); ++ } ++ ++ if (err) { ++ AP6210_ERR("dhdsdio_probe: failure reading or parsing CIS\n"); ++ goto fail; ++ } ++ } ++#endif /* DHD_DEBUG */ ++ ++ /* si_attach() will provide an SI handle and scan the backplane */ ++ if (!(bus->sih = si_attach((uint)devid, osh, regsva, DHD_BUS, sdh, ++ &bus->vars, &bus->varsz))) { ++ AP6210_ERR("%s: si_attach failed!\n", __FUNCTION__); ++ goto fail; ++ } ++ ++ bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev); ++ ++ if (!dhdsdio_chipmatch((uint16)bus->sih->chip)) { ++ AP6210_ERR("%s: unsupported chip: 0x%04x\n", ++ __FUNCTION__, bus->sih->chip); ++ goto fail; ++ } ++ ++ if (bus->sih->buscorerev >= 12) ++ dhdsdio_clk_kso_init(bus); ++ else ++ bus->kso = TRUE; ++ ++ if (CST4330_CHIPMODE_SDIOD(bus->sih->chipst)) { ++ } ++ ++ si_sdiod_drive_strength_init(bus->sih, osh, dhd_sdiod_drive_strength); ++ ++ ++ /* Get info on the ARM and SOCRAM cores... */ ++ if (!DHD_NOPMU(bus)) { ++ if ((si_setcore(bus->sih, ARM7S_CORE_ID, 0)) || ++ (si_setcore(bus->sih, ARMCM3_CORE_ID, 0)) || ++ (si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) { ++ bus->armrev = si_corerev(bus->sih); ++ } else { ++ AP6210_ERR("%s: failed to find ARM core!\n", __FUNCTION__); ++ goto fail; ++ } ++ ++ if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { ++ if (!(bus->orig_ramsize = si_socram_size(bus->sih))) { ++ AP6210_ERR("%s: failed to find SOCRAM memory!\n", __FUNCTION__); ++ goto fail; ++ } ++ } else { ++ /* cr4 has a different way to find the RAM size from TCM's */ ++ if (!(bus->orig_ramsize = si_tcm_size(bus->sih))) { ++ AP6210_ERR("%s: failed to find CR4-TCM memory!\n", __FUNCTION__); ++ goto fail; ++ } ++ /* also populate base address */ ++ bus->dongle_ram_base = CR4_RAM_BASE; ++ } ++ bus->ramsize = bus->orig_ramsize; ++ if (dhd_dongle_memsize) ++ dhd_dongle_setmemsize(bus, dhd_dongle_memsize); ++ ++ AP6210_DEBUG("DHD: dongle ram size is set to %d(orig %d)\n", ++ bus->ramsize, bus->orig_ramsize); ++ ++ bus->srmemsize = si_socram_srmem_size(bus->sih); ++ } ++ ++ /* ...but normally deal with the SDPCMDEV core */ ++ if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) && ++ !(bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0))) { ++ AP6210_ERR("%s: failed to find SDIODEV core!\n", __FUNCTION__); ++ goto fail; ++ } ++ bus->sdpcmrev = si_corerev(bus->sih); ++ ++ /* Set core control so an SDIO reset does a backplane reset */ ++ OR_REG(osh, &bus->regs->corecontrol, CC_BPRESEN); ++ bus->rxint_mode = SDIO_DEVICE_HMB_RXINT; ++ ++ if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) && ++ (bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_1)) ++ { ++ uint32 val; ++ ++ val = R_REG(osh, &bus->regs->corecontrol); ++ val &= ~CC_XMTDATAAVAIL_MODE; ++ val |= CC_XMTDATAAVAIL_CTRL; ++ W_REG(osh, &bus->regs->corecontrol, val); ++ } ++ ++ ++ pktq_init(&bus->txq, (PRIOMASK + 1), QLEN); ++ ++ /* Locate an appropriately-aligned portion of hdrbuf */ ++ bus->rxhdr = (uint8 *)ROUNDUP((uintptr)&bus->hdrbuf[0], DHD_SDALIGN); ++ ++ /* Set the poll and/or interrupt flags */ ++ bus->intr = (bool)dhd_intr; ++ if ((bus->poll = (bool)dhd_poll)) ++ bus->pollrate = 1; ++ ++#ifdef BCMSDIOH_TXGLOM ++ /* Setting default Glom mode */ ++ bus->glom_mode = SDPCM_TXGLOM_CPY; ++ /* Setting default Glom size */ ++ bus->glomsize = SDPCM_DEFGLOM_SIZE; ++#endif ++ ++ return TRUE; ++ ++fail: ++ if (bus->sih != NULL) { ++ si_detach(bus->sih); ++ bus->sih = NULL; ++ } ++ return FALSE; ++} ++ ++static bool ++dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh) ++{ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (bus->dhd->maxctl) { ++ bus->rxblen = ROUNDUP((bus->dhd->maxctl + SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN; ++ if (!(bus->rxbuf = DHD_OS_PREALLOC(osh, DHD_PREALLOC_RXBUF, bus->rxblen))) { ++ AP6210_ERR("%s: MALLOC of %d-byte rxbuf failed\n", ++ __FUNCTION__, bus->rxblen); ++ goto fail; ++ } ++ } ++ /* Allocate buffer to receive glomed packet */ ++ if (!(bus->databuf = DHD_OS_PREALLOC(osh, DHD_PREALLOC_DATABUF, MAX_DATA_BUF))) { ++ AP6210_ERR("%s: MALLOC of %d-byte databuf failed\n", ++ __FUNCTION__, MAX_DATA_BUF); ++ /* release rxbuf which was already located as above */ ++ if (!bus->rxblen) ++ DHD_OS_PREFREE(osh, bus->rxbuf, bus->rxblen); ++ goto fail; ++ } ++ ++ /* Align the buffer */ ++ if ((uintptr)bus->databuf % DHD_SDALIGN) ++ bus->dataptr = bus->databuf + (DHD_SDALIGN - ((uintptr)bus->databuf % DHD_SDALIGN)); ++ else ++ bus->dataptr = bus->databuf; ++ ++ return TRUE; ++ ++fail: ++ return FALSE; ++} ++ ++static bool ++dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh) ++{ ++ int32 fnum; ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++#ifdef SDTEST ++ dhdsdio_pktgen_init(bus); ++#endif /* SDTEST */ ++ ++ /* Disable F2 to clear any intermediate frame state on the dongle */ ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); ++ ++ bus->dhd->busstate = DHD_BUS_DOWN; ++ bus->sleeping = FALSE; ++ bus->rxflow = FALSE; ++ bus->prev_rxlim_hit = 0; ++ ++ /* Done with backplane-dependent accesses, can drop clock... */ ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); ++ ++ /* ...and initialize clock/power states */ ++ bus->clkstate = CLK_SDONLY; ++ bus->idletime = (int32)dhd_idletime; ++ bus->idleclock = DHD_IDLE_ACTIVE; ++ ++ /* Query the SD clock speed */ ++ if (bcmsdh_iovar_op(sdh, "sd_divisor", NULL, 0, ++ &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) { ++ AP6210_ERR("%s: fail on %s get\n", __FUNCTION__, "sd_divisor"); ++ bus->sd_divisor = -1; ++ } else { ++ AP6210_DEBUG("%s: Initial value for %s is %d\n", ++ __FUNCTION__, "sd_divisor", bus->sd_divisor); ++ } ++ ++ /* Query the SD bus mode */ ++ if (bcmsdh_iovar_op(sdh, "sd_mode", NULL, 0, ++ &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) { ++ AP6210_ERR("%s: fail on %s get\n", __FUNCTION__, "sd_mode"); ++ bus->sd_mode = -1; ++ } else { ++ AP6210_DEBUG("%s: Initial value for %s is %d\n", ++ __FUNCTION__, "sd_mode", bus->sd_mode); ++ } ++ ++ /* Query the F2 block size, set roundup accordingly */ ++ fnum = 2; ++ if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(int32), ++ &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) { ++ bus->blocksize = 0; ++ AP6210_ERR("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"); ++ } else { ++ AP6210_DEBUG("%s: Initial value for %s is %d\n", ++ __FUNCTION__, "sd_blocksize", bus->blocksize); ++ } ++ bus->roundup = MIN(max_roundup, bus->blocksize); ++ ++ /* Query if bus module supports packet chaining, default to use if supported */ ++ if (bcmsdh_iovar_op(sdh, "sd_rxchain", NULL, 0, ++ &bus->sd_rxchain, sizeof(int32), FALSE) != BCME_OK) { ++ bus->sd_rxchain = FALSE; ++ } else { ++ AP6210_DEBUG("%s: bus module (through bcmsdh API) %s chaining\n", ++ __FUNCTION__, (bus->sd_rxchain ? "supports" : "does not support")); ++ } ++ bus->use_rxchain = (bool)bus->sd_rxchain; ++ ++ return TRUE; ++} ++ ++void ++dhd_bus_select_firmware_name_by_chip(struct dhd_bus *bus, char *dst, char *src) ++{ ++ int fw_type, ag_type; ++ static uint chip, chiprev, first=1; ++ int i; ++ ++ if (first) { ++ chip = bus->sih->chip; ++ chiprev = bus->sih->chiprev; ++ first = 0; ++ } ++ if (src[0] == '\0') { ++#ifdef CONFIG_AP6210_FW_PATH ++ bcm_strncpy_s(src, sizeof(fw_path), CONFIG_AP6210_FW_PATH, MOD_PARAM_PATHLEN-1); ++ if (src[0] == '\0') ++#endif ++ { ++ AP6210_DEBUG("src firmware path is null\n"); ++ return; ++ } ++ } ++ ++ strcpy(dst, src); ++#ifndef FW_PATH_AUTO_SELECT ++ return; ++#endif ++ ++ /* find out the last '/' */ ++ i = strlen(dst); ++ while (i>0){ ++ if (dst[i] == '/') break; ++ i--; ++ } ++#ifdef BAND_AG ++ ag_type = FW_TYPE_AG; ++#else ++ ag_type = strstr(&dst[i], "_ag") ? FW_TYPE_AG : FW_TYPE_G; ++#endif ++ fw_type = (strstr(&dst[i], "_mfg") ? ++ FW_TYPE_MFG : (strstr(&dst[i], "_apsta") ? ++ FW_TYPE_APSTA : (strstr(&dst[i], "_p2p") ? ++ FW_TYPE_P2P : FW_TYPE_STA))); ++ ++ ++ switch (chip) { ++ case BCM4330_CHIP_ID: ++ if (ag_type == FW_TYPE_G) { ++ if (chiprev == BCM4330B2_CHIP_REV) ++ strcpy(&dst[i+1], bcm40183b2_fw_name[fw_type]); ++ break; ++ } else { ++ if (chiprev == BCM4330B2_CHIP_REV) ++ strcpy(&dst[i+1], bcm40183b2ag_fw_name[fw_type]); ++ break; ++ } ++ case BCM43362_CHIP_ID: ++ if (chiprev == BCM43362A0_CHIP_REV) ++ strcpy(&dst[i+1], bcm40181a0_fw_name[fw_type]); ++ else ++ strcpy(&dst[i+1], bcm40181a2_fw_name[fw_type]); ++ break; ++ case BCM43341_CHIP_ID: ++ if (chiprev == BCM43341B0_CHIP_REV) ++ strcpy(&dst[i+1], bcm43341b0ag_fw_name[fw_type]); ++ break; ++ case BCM4324_CHIP_ID: ++ if (chiprev == BCM43241B4_CHIP_REV) ++ strcpy(&dst[i+1], bcm43241b4ag_fw_name[fw_type]); ++ break; ++ } ++ ++ AP6210_DEBUG("%s: firmware_path=%s\n", __FUNCTION__, dst); ++} ++ ++bool ++dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh, ++ char *pfw_path, char *pnv_path) ++{ ++ bool ret; ++ bus->fw_path = pfw_path; ++ bus->nv_path = pnv_path; ++ ++ ret = dhdsdio_download_firmware(bus, osh, bus->sdh); ++ ++ ++ return ret; ++} ++ ++static bool ++dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh) ++{ ++ bool ret; ++ ++ DHD_OS_WAKE_LOCK(bus->dhd); ++ ++ /* Download the firmware */ ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); ++ ++ AP6210_ERR("Final fw_path=%s\n", bus->fw_path); ++ AP6210_ERR("Final nv_path=%s\n", bus->nv_path); ++ ret = _dhdsdio_download_firmware(bus) == 0; ++ ++ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); ++ ++ DHD_OS_WAKE_UNLOCK(bus->dhd); ++ return ret; ++} ++ ++/* Detach and free everything */ ++static void ++dhdsdio_release(dhd_bus_t *bus, osl_t *osh) ++{ ++ bool dongle_isolation = FALSE; ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (bus) { ++ ASSERT(osh); ++ ++ if (bus->dhd) { ++ dongle_isolation = bus->dhd->dongle_isolation; ++ dhd_detach(bus->dhd); ++ } ++ ++ /* De-register interrupt handler */ ++ bcmsdh_intr_disable(bus->sdh); ++ bcmsdh_intr_dereg(bus->sdh); ++ ++ if (bus->dhd) { ++ dhdsdio_release_dongle(bus, osh, dongle_isolation, TRUE); ++ dhd_free(bus->dhd); ++ bus->dhd = NULL; ++ } ++ ++ dhdsdio_release_malloc(bus, osh); ++ ++#ifdef DHD_DEBUG ++ if (bus->console.buf != NULL) ++ MFREE(osh, bus->console.buf, bus->console.bufsize); ++#endif ++ ++ MFREE(osh, bus, sizeof(dhd_bus_t)); ++ } ++ ++ if (osh) ++ dhd_osl_detach(osh); ++ ++ AP6210_DEBUG("%s: Disconnected\n", __FUNCTION__); ++} ++ ++static void ++dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh) ++{ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (bus->dhd && bus->dhd->dongle_reset) ++ return; ++ ++ if (bus->rxbuf) { ++#ifndef CONFIG_DHD_USE_STATIC_BUF ++ MFREE(osh, bus->rxbuf, bus->rxblen); ++#endif ++ bus->rxctl = bus->rxbuf = NULL; ++ bus->rxlen = 0; ++ } ++ ++ if (bus->databuf) { ++#ifndef CONFIG_DHD_USE_STATIC_BUF ++ MFREE(osh, bus->databuf, MAX_DATA_BUF); ++#endif ++ bus->databuf = NULL; ++ } ++ ++ if (bus->vars && bus->varsz) { ++ MFREE(osh, bus->vars, bus->varsz); ++ bus->vars = NULL; ++ } ++ ++} ++ ++ ++static void ++dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool reset_flag) ++{ ++ AP6210_DEBUG("%s: Enter bus->dhd %p bus->dhd->dongle_reset %d \n", __FUNCTION__, ++ bus->dhd, bus->dhd->dongle_reset); ++ ++ if ((bus->dhd && bus->dhd->dongle_reset) && reset_flag) ++ return; ++ ++ if (bus->sih) { ++#if !defined(BCMLXSDMMC) ++ if (bus->dhd) { ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); ++ } ++ if (KSO_ENAB(bus) && (dongle_isolation == FALSE)) ++ si_watchdog(bus->sih, 4); ++#endif /* !defined(BCMLXSDMMC) */ ++ if (bus->dhd) { ++ dhdsdio_clkctl(bus, CLK_NONE, FALSE); ++ } ++ si_detach(bus->sih); ++ bus->sih = NULL; ++ if (bus->vars && bus->varsz) ++ MFREE(osh, bus->vars, bus->varsz); ++ bus->vars = NULL; ++ } ++ ++ AP6210_DEBUG("%s: Disconnected\n", __FUNCTION__); ++} ++ ++static void ++dhdsdio_disconnect(void *ptr) ++{ ++ dhd_bus_t *bus = (dhd_bus_t *)ptr; ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++ ++ if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) { ++ AP6210_DEBUG("%s : no mutex held. set lock\n", __FUNCTION__); ++ } ++ else { ++ AP6210_DEBUG("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__); ++ } ++ mutex_lock(&_dhd_sdio_mutex_lock_); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ ++ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ if (bus) { ++ ASSERT(bus->dhd); ++ dhdsdio_release(bus, bus->dhd->osh); ++ } ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++ mutex_unlock(&_dhd_sdio_mutex_lock_); ++ AP6210_ERR("%s : the lock is released.\n", __FUNCTION__); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ ++ ++ AP6210_DEBUG("%s: Disconnected\n", __FUNCTION__); ++} ++ ++ ++/* Register/Unregister functions are called by the main DHD entry ++ * point (e.g. module insertion) to link with the bus driver, in ++ * order to look for or await the device. ++ */ ++ ++static bcmsdh_driver_t dhd_sdio = { ++ dhdsdio_probe, ++ dhdsdio_disconnect ++}; ++ ++int ++dhd_bus_register(void) ++{ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ return bcmsdh_register(&dhd_sdio); ++} ++ ++void ++dhd_bus_unregister(void) ++{ ++ AP6210_DEBUG("%s: Enter\n", __FUNCTION__); ++ ++ bcmsdh_unregister(); ++} ++ ++#if defined(BCMLXSDMMC) ++/* Register a dummy SDIO client driver in order to be notified of new SDIO device */ ++int dhd_bus_reg_sdio_notify(void* semaphore) ++{ ++ return bcmsdh_reg_sdio_notify(semaphore); ++} ++ ++void dhd_bus_unreg_sdio_notify(void) ++{ ++ bcmsdh_unreg_sdio_notify(); ++} ++#endif /* defined(BCMLXSDMMC) */ ++ ++#ifdef BCMEMBEDIMAGE ++static int ++dhdsdio_download_code_array(struct dhd_bus *bus) ++{ ++ int bcmerror = -1; ++ int offset = 0; ++ unsigned char *ularray = NULL; ++ ++ AP6210_ERR("%s: download embedded firmware...\n", __FUNCTION__); ++ ++ /* Download image */ ++ while ((offset + MEMBLOCK) < sizeof(dlarray)) { ++ bcmerror = dhdsdio_membytes(bus, TRUE, offset, ++ (uint8 *) (dlarray + offset), MEMBLOCK); ++ if (bcmerror) { ++ AP6210_ERR("%s: error %d on writing %d membytes at 0x%08x\n", ++ __FUNCTION__, bcmerror, MEMBLOCK, offset); ++ goto err; ++ } ++ ++ offset += MEMBLOCK; ++ } ++ ++ if (offset < sizeof(dlarray)) { ++ bcmerror = dhdsdio_membytes(bus, TRUE, offset, ++ (uint8 *) (dlarray + offset), sizeof(dlarray) - offset); ++ if (bcmerror) { ++ AP6210_ERR("%s: error %d on writing %d membytes at 0x%08x\n", ++ __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset); ++ goto err; ++ } ++ } ++ ++#ifdef DHD_DEBUG ++ /* Upload and compare the downloaded code */ ++ { ++ ularray = MALLOC(bus->dhd->osh, bus->ramsize); ++ /* Upload image to verify downloaded contents. */ ++ offset = 0; ++ memset(ularray, 0xaa, bus->ramsize); ++ while ((offset + MEMBLOCK) < sizeof(dlarray)) { ++ bcmerror = dhdsdio_membytes(bus, FALSE, offset, ularray + offset, MEMBLOCK); ++ if (bcmerror) { ++ AP6210_ERR("%s: error %d on reading %d membytes at 0x%08x\n", ++ __FUNCTION__, bcmerror, MEMBLOCK, offset); ++ goto err; ++ } ++ ++ offset += MEMBLOCK; ++ } ++ ++ if (offset < sizeof(dlarray)) { ++ bcmerror = dhdsdio_membytes(bus, FALSE, offset, ++ ularray + offset, sizeof(dlarray) - offset); ++ if (bcmerror) { ++ AP6210_ERR("%s: error %d on reading %d membytes at 0x%08x\n", ++ __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset); ++ goto err; ++ } ++ } ++ ++ if (memcmp(dlarray, ularray, sizeof(dlarray))) { ++ AP6210_ERR("%s: Downloaded image is corrupted (%s, %s, %s).\n", ++ __FUNCTION__, dlimagename, dlimagever, dlimagedate); ++ goto err; ++ } else ++ AP6210_ERR("%s: Download, Upload and compare succeeded (%s, %s, %s).\n", ++ __FUNCTION__, dlimagename, dlimagever, dlimagedate); ++ ++ } ++#endif /* DHD_DEBUG */ ++ ++err: ++ if (ularray) ++ MFREE(bus->dhd->osh, ularray, bus->ramsize); ++ return bcmerror; ++} ++#endif /* BCMEMBEDIMAGE */ ++ ++static int ++dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path) ++{ ++ int bcmerror = -1; ++ int offset = 0; ++ int len; ++ void *image = NULL; ++ uint8 *memblock = NULL, *memptr; ++ uint8 *memptr_tmp = NULL; // terence: check downloaded firmware is correct ++ ++ AP6210_ERR("download firmware %s\n", pfw_path); ++ ++ image = dhd_os_open_image(pfw_path); ++ if (image == NULL) ++ goto err; ++ ++ memptr = memblock = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN); ++ if (memblock == NULL) { ++ AP6210_ERR("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK); ++ goto err; ++ } ++ if (dhd_msg_level & DHD_TRACE_VAL) { ++ memptr_tmp = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN); ++ if (memptr_tmp == NULL) { ++ AP6210_ERR("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK); ++ goto err; ++ } ++ } ++ if ((uint32)(uintptr)memblock % DHD_SDALIGN) ++ memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN)); ++ ++ /* Download image */ ++ while ((len = dhd_os_get_image_block((char*)memptr, MEMBLOCK, image))) { ++ if (len < 0) { ++ AP6210_ERR("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, len); ++ bcmerror = BCME_ERROR; ++ goto err; ++ } ++ bcmerror = dhdsdio_membytes(bus, TRUE, offset, memptr, len); ++ if (bcmerror) { ++ AP6210_ERR("%s: error %d on writing %d membytes at 0x%08x\n", ++ __FUNCTION__, bcmerror, MEMBLOCK, offset); ++ goto err; ++ } ++ ++ if (dhd_msg_level & DHD_TRACE_VAL) { ++ bcmerror = dhdsdio_membytes(bus, FALSE, offset, memptr_tmp, len); ++ if (bcmerror) { ++ AP6210_ERR("%s: error %d on reading %d membytes at 0x%08x\n", ++ __FUNCTION__, bcmerror, MEMBLOCK, offset); ++ goto err; ++ } ++ if (memcmp(memptr_tmp, memptr, len)) { ++ AP6210_ERR("%s: Downloaded image is corrupted.\n", __FUNCTION__); ++ goto err; ++ } else ++ AP6210_ERR("%s: Download, Upload and compare succeeded.\n", __FUNCTION__); ++ } ++ offset += MEMBLOCK; ++ } ++ ++err: ++ if (memblock) ++ MFREE(bus->dhd->osh, memblock, MEMBLOCK + DHD_SDALIGN); ++ if (dhd_msg_level & DHD_TRACE_VAL) { ++ if (memptr_tmp) ++ MFREE(bus->dhd->osh, memptr_tmp, MEMBLOCK + DHD_SDALIGN); ++ } ++ ++ if (image) ++ dhd_os_close_image(image); ++ ++ return bcmerror; ++} ++ ++/* ++ EXAMPLE: nvram_array ++ nvram_arry format: ++ name=value ++ Use carriage return at the end of each assignment, and an empty string with ++ carriage return at the end of array. ++ ++ For example: ++ unsigned char nvram_array[] = {"name1=value1\n", "name2=value2\n", "\n"}; ++ Hex values start with 0x, and mac addr format: xx:xx:xx:xx:xx:xx. ++ ++ Search "EXAMPLE: nvram_array" to see how the array is activated. ++*/ ++ ++void ++dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_params) ++{ ++ bus->nvram_params = nvram_params; ++} ++ ++static int ++dhdsdio_download_nvram(struct dhd_bus *bus) ++{ ++ int bcmerror = -1; ++ uint len; ++ void * image = NULL; ++ char * memblock = NULL; ++ char *bufp; ++ char *pnv_path; ++ bool nvram_file_exists; ++ ++ pnv_path = bus->nv_path; ++ ++ nvram_file_exists = ((pnv_path != NULL) && (pnv_path[0] != '\0')); ++ if (!nvram_file_exists && (bus->nvram_params == NULL)) ++ return (0); ++ ++ if (nvram_file_exists) { ++ image = dhd_os_open_image(pnv_path); ++ if (image == NULL) ++ goto err; ++ } ++ ++ memblock = MALLOC(bus->dhd->osh, MAX_NVRAMBUF_SIZE); ++ if (memblock == NULL) { ++ AP6210_ERR("%s: Failed to allocate memory %d bytes\n", ++ __FUNCTION__, MAX_NVRAMBUF_SIZE); ++ goto err; ++ } ++ ++ /* Download variables */ ++ if (nvram_file_exists) { ++ len = dhd_os_get_image_block(memblock, MAX_NVRAMBUF_SIZE, image); ++ } ++ else { ++ len = strlen(bus->nvram_params); ++ ASSERT(len <= MAX_NVRAMBUF_SIZE); ++ memcpy(memblock, bus->nvram_params, len); ++ } ++ if (len > 0 && len < MAX_NVRAMBUF_SIZE) { ++ bufp = (char *)memblock; ++ bufp[len] = 0; ++ len = process_nvram_vars(bufp, len); ++ if (len % 4) { ++ len += 4 - (len % 4); ++ } ++ bufp += len; ++ *bufp++ = 0; ++ if (len) ++ bcmerror = dhdsdio_downloadvars(bus, memblock, len + 1); ++ if (bcmerror) { ++ AP6210_ERR("%s: error downloading vars: %d\n", ++ __FUNCTION__, bcmerror); ++ } ++ } ++ else { ++ AP6210_ERR("%s: error reading nvram file: %d\n", ++ __FUNCTION__, len); ++ bcmerror = BCME_SDIO_ERROR; ++ } ++ ++err: ++ if (memblock) ++ MFREE(bus->dhd->osh, memblock, MAX_NVRAMBUF_SIZE); ++ ++ if (image) ++ dhd_os_close_image(image); ++ ++ return bcmerror; ++} ++ ++static int ++_dhdsdio_download_firmware(struct dhd_bus *bus) ++{ ++ int bcmerror = -1; ++ ++ bool embed = FALSE; /* download embedded firmware */ ++ bool dlok = FALSE; /* download firmware succeeded */ ++ ++ /* Out immediately if no image to download */ ++ if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) { ++#ifdef BCMEMBEDIMAGE ++ embed = TRUE; ++#else ++ return 0; ++#endif ++ } ++ ++ /* Keep arm in reset */ ++ if (dhdsdio_download_state(bus, TRUE)) { ++ AP6210_ERR("%s: error placing ARM core in reset\n", __FUNCTION__); ++ goto err; ++ } ++ ++ /* External image takes precedence if specified */ ++ if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) { ++ if (dhdsdio_download_code_file(bus, bus->fw_path)) { ++ AP6210_ERR("%s: dongle image file download failed\n", __FUNCTION__); ++#ifdef BCMEMBEDIMAGE ++ embed = TRUE; ++#else ++ goto err; ++#endif ++ } ++ else { ++ embed = FALSE; ++ dlok = TRUE; ++ } ++ } ++#ifdef BCMEMBEDIMAGE ++ if (embed) { ++ if (dhdsdio_download_code_array(bus)) { ++ AP6210_ERR("%s: dongle image array download failed\n", __FUNCTION__); ++ goto err; ++ } ++ else { ++ dlok = TRUE; ++ } ++ } ++#else ++ BCM_REFERENCE(embed); ++#endif ++ if (!dlok) { ++ AP6210_ERR("%s: dongle image download failed\n", __FUNCTION__); ++ goto err; ++ } ++ ++ /* EXAMPLE: nvram_array */ ++ /* If a valid nvram_arry is specified as above, it can be passed down to dongle */ ++ /* dhd_bus_set_nvram_params(bus, (char *)&nvram_array); */ ++ ++ /* External nvram takes precedence if specified */ ++ if (dhdsdio_download_nvram(bus)) { ++ AP6210_ERR("%s: dongle nvram file download failed\n", __FUNCTION__); ++ goto err; ++ } ++ ++ /* Take arm out of reset */ ++ if (dhdsdio_download_state(bus, FALSE)) { ++ AP6210_ERR("%s: error getting out of ARM core reset\n", __FUNCTION__); ++ goto err; ++ } ++ ++ bcmerror = 0; ++ ++err: ++ return bcmerror; ++} ++ ++static int ++dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes, ++ void *pkt, bcmsdh_cmplt_fn_t complete, void *handle) ++{ ++ int status; ++ ++ if (!KSO_ENAB(bus)) { ++ AP6210_ERR("%s: Device asleep\n", __FUNCTION__); ++ return BCME_NODEVICE; ++ } ++ ++ status = bcmsdh_recv_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete, handle); ++ ++ return status; ++} ++ ++static int ++dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes, ++ void *pkt, bcmsdh_cmplt_fn_t complete, void *handle) ++{ ++ if (!KSO_ENAB(bus)) { ++ AP6210_ERR("%s: Device asleep\n", __FUNCTION__); ++ return BCME_NODEVICE; ++ } ++ ++ return (bcmsdh_send_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete, handle)); ++} ++ ++#ifdef BCMSDIOH_TXGLOM ++static void ++dhd_bcmsdh_glom_post(dhd_bus_t *bus, uint8 *frame, uint len) ++{ ++ bcmsdh_glom_post(bus->sdh, frame, len); ++} ++ ++static void ++dhd_bcmsdh_glom_clear(dhd_bus_t *bus) ++{ ++ bcmsdh_glom_clear(bus->sdh); ++} ++#endif ++ ++uint ++dhd_bus_chip(struct dhd_bus *bus) ++{ ++ ASSERT(bus->sih != NULL); ++ return bus->sih->chip; ++} ++ ++void * ++dhd_bus_pub(struct dhd_bus *bus) ++{ ++ return bus->dhd; ++} ++ ++void * ++dhd_bus_txq(struct dhd_bus *bus) ++{ ++ return &bus->txq; ++} ++ ++uint ++dhd_bus_hdrlen(struct dhd_bus *bus) ++{ ++ return SDPCM_HDRLEN; ++} ++ ++int ++dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) ++{ ++ int bcmerror = 0; ++ dhd_bus_t *bus; ++ ++ bus = dhdp->bus; ++ ++ if (flag == TRUE) { ++ if (!bus->dhd->dongle_reset) { ++ dhd_os_sdlock(dhdp); ++ dhd_os_wd_timer(dhdp, 0); ++#if !defined(IGNORE_ETH0_DOWN) ++ /* Force flow control as protection when stop come before ifconfig_down */ ++ dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON); ++#endif /* !defined(IGNORE_ETH0_DOWN) */ ++ /* Expect app to have torn down any connection before calling */ ++ /* Stop the bus, disable F2 */ ++ dhd_bus_stop(bus, FALSE); ++ ++#if defined(OOB_INTR_ONLY) ++ /* Clean up any pending IRQ */ ++ bcmsdh_set_irq(FALSE); ++#endif ++ ++ /* Clean tx/rx buffer pointers, detach from the dongle */ ++ dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE, TRUE); ++ ++ bus->dhd->dongle_reset = TRUE; ++ bus->dhd->up = FALSE; ++#ifdef BCMSDIOH_TXGLOM ++ dhd_txglom_enable(dhdp, FALSE); ++#endif ++ dhd_os_sdunlock(dhdp); ++ ++ AP6210_ERR("%s: WLAN OFF DONE\n", __FUNCTION__); ++ /* App can now remove power from device */ ++ } else ++ bcmerror = BCME_SDIO_ERROR; ++ } else { ++ /* App must have restored power to device before calling */ ++ ++ AP6210_ERR("%s: WLAN ON\n", __FUNCTION__); ++ ++ if (bus->dhd->dongle_reset) { ++ /* Turn on WLAN */ ++#ifdef DHDTHREAD ++ dhd_os_sdlock(dhdp); ++#endif /* DHDTHREAD */ ++ /* Reset SD client */ ++ bcmsdh_reset(bus->sdh); ++ ++ /* Attempt to re-attach & download */ ++ if (dhdsdio_probe_attach(bus, bus->dhd->osh, bus->sdh, ++ (uint32 *)SI_ENUM_BASE, ++ bus->cl_devid)) { ++ /* Attempt to download binary to the dongle */ ++ COPY_FW_PATH_BY_CHIP(bus, fw_path, firmware_path); // terence ++ if (dhdsdio_probe_init(bus, bus->dhd->osh, bus->sdh) && ++ dhdsdio_download_firmware(bus, bus->dhd->osh, bus->sdh)) { ++ ++ /* Re-init bus, enable F2 transfer */ ++ bcmerror = dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE); ++ if (bcmerror == BCME_OK) { ++#if defined(OOB_INTR_ONLY) ++ bcmsdh_set_irq(TRUE); ++ dhd_enable_oob_intr(bus, TRUE); ++#endif ++ ++ bus->dhd->dongle_reset = FALSE; ++ bus->dhd->up = TRUE; ++ ++#if !defined(IGNORE_ETH0_DOWN) ++ /* Restore flow control */ ++ dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF); ++#endif ++ dhd_os_wd_timer(dhdp, dhd_watchdog_ms); ++#ifdef BCMSDIOH_TXGLOM ++ if ((dhdp->busstate == DHD_BUS_DATA) && ++ bcmsdh_glom_enabled()) { ++ dhd_txglom_enable(dhdp, TRUE); ++ } ++#endif /* BCMSDIOH_TXGLOM */ ++ AP6210_ERR("%s: WLAN ON DONE\n", __FUNCTION__); ++ } else { ++ dhd_bus_stop(bus, FALSE); ++ dhdsdio_release_dongle(bus, bus->dhd->osh, ++ TRUE, FALSE); ++ } ++ } else ++ bcmerror = BCME_SDIO_ERROR; ++ } else ++ bcmerror = BCME_SDIO_ERROR; ++ ++#ifdef DHDTHREAD ++ dhd_os_sdunlock(dhdp); ++#endif /* DHDTHREAD */ ++ } else { ++ bcmerror = BCME_SDIO_ERROR; ++ AP6210_DEBUG("%s called when dongle is not in reset\n", ++ __FUNCTION__); ++ AP6210_DEBUG("Will call dhd_bus_start instead\n"); ++ sdioh_start(NULL, 1); ++#if defined(HW_OOB) ++ bcmsdh_config_hw_oob_intr(bus->sdh, bus->sih->chip); // terence 20120615: fix for OOB initial issue ++#endif ++ COPY_FW_PATH_BY_CHIP(bus, fw_path, firmware_path); ++ if ((bcmerror = dhd_bus_start(dhdp)) != 0) ++ AP6210_ERR("%s: dhd_bus_start fail with %d\n", ++ __FUNCTION__, bcmerror); ++ } ++ } ++ return bcmerror; ++} ++ ++/* Get Chip ID version */ ++uint dhd_bus_chip_id(dhd_pub_t *dhdp) ++{ ++ dhd_bus_t *bus = dhdp->bus; ++ ++ return bus->sih->chip; ++} ++ ++/* Get Chip Rev ID version */ ++uint dhd_bus_chiprev_id(dhd_pub_t *dhdp) ++{ ++ dhd_bus_t *bus = dhdp->bus; ++ ++ return bus->sih->chiprev; ++} ++ ++/* Get Chip Pkg ID version */ ++uint dhd_bus_chippkg_id(dhd_pub_t *dhdp) ++{ ++ dhd_bus_t *bus = dhdp->bus; ++ ++ return bus->sih->chippkg; ++} ++ ++int ++dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size) ++{ ++ dhd_bus_t *bus; ++ ++ bus = dhdp->bus; ++ return dhdsdio_membytes(bus, set, address, data, size); ++} +diff --git a/drivers/net/wireless/ap6210/dhd_wlfc.c b/drivers/net/wireless/ap6210/dhd_wlfc.c +new file mode 100755 +index 0000000..93b4ca3 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_wlfc.c +@@ -0,0 +1,2441 @@ ++/* ++ * DHD PROP_TXSTATUS Module. ++ * ++ * Copyright (C) 1999-2013, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhd_wlfc.c 412994 2013-07-17 12:38:03Z $ ++ * ++ */ ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#ifdef PROP_TXSTATUS ++#include ++#include ++#endif ++ ++ ++ ++ ++#define BUS_RETRIES 1 /* # of retries before aborting a bus tx operation */ ++ ++#ifdef PROP_TXSTATUS ++typedef struct dhd_wlfc_commit_info { ++ uint8 needs_hdr; ++ uint8 ac_fifo_credit_spent; ++ ewlfc_packet_state_t pkt_type; ++ wlfc_mac_descriptor_t* mac_entry; ++ void* p; ++} dhd_wlfc_commit_info_t; ++#endif /* PROP_TXSTATUS */ ++ ++ ++#ifdef PROP_TXSTATUS ++ ++#define DHD_WLFC_QMON_COMPLETE(entry) ++ ++void ++dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) ++{ ++ int i; ++ uint8* ea; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhdp->wlfc_state; ++ wlfc_hanger_t* h; ++ wlfc_mac_descriptor_t* mac_table; ++ wlfc_mac_descriptor_t* interfaces; ++ char* iftypes[] = {"STA", "AP", "WDS", "p2pGO", "p2pCL"}; ++ ++ if (wlfc == NULL) { ++ bcm_bprintf(strbuf, "wlfc not initialized yet\n"); ++ return; ++ } ++ h = (wlfc_hanger_t*)wlfc->hanger; ++ if (h == NULL) { ++ bcm_bprintf(strbuf, "wlfc-hanger not initialized yet\n"); ++ } ++ ++ mac_table = wlfc->destination_entries.nodes; ++ interfaces = wlfc->destination_entries.interfaces; ++ bcm_bprintf(strbuf, "---- wlfc stats ----\n"); ++ if (h) { ++ bcm_bprintf(strbuf, "wlfc hanger (pushed,popped,f_push," ++ "f_pop,f_slot, pending) = (%d,%d,%d,%d,%d,%d)\n", ++ h->pushed, ++ h->popped, ++ h->failed_to_push, ++ h->failed_to_pop, ++ h->failed_slotfind, ++ (h->pushed - h->popped)); ++ } ++ ++ bcm_bprintf(strbuf, "wlfc fail(tlv,credit_rqst,mac_update,psmode_update), " ++ "(dq_full,rollback_fail) = (%d,%d,%d,%d), (%d,%d)\n", ++ wlfc->stats.tlv_parse_failed, ++ wlfc->stats.credit_request_failed, ++ wlfc->stats.mac_update_failed, ++ wlfc->stats.psmode_update_failed, ++ wlfc->stats.delayq_full_error, ++ wlfc->stats.rollback_failed); ++ ++ bcm_bprintf(strbuf, "PKTS (credit,sent) " ++ "(AC0[%d,%d],AC1[%d,%d],AC2[%d,%d],AC3[%d,%d],BC_MC[%d,%d])\n", ++ wlfc->FIFO_credit[0], wlfc->stats.send_pkts[0], ++ wlfc->FIFO_credit[1], wlfc->stats.send_pkts[1], ++ wlfc->FIFO_credit[2], wlfc->stats.send_pkts[2], ++ wlfc->FIFO_credit[3], wlfc->stats.send_pkts[3], ++ wlfc->FIFO_credit[4], wlfc->stats.send_pkts[4]); ++ ++ bcm_bprintf(strbuf, "\n"); ++ for (i = 0; i < WLFC_MAX_IFNUM; i++) { ++ if (interfaces[i].occupied) { ++ char* iftype_desc; ++ ++ if (interfaces[i].iftype > WLC_E_IF_ROLE_P2P_CLIENT) ++ iftype_desc = "hostif_flow_state[i] == OFF) ++ ? " OFF":" ON")); ++ ++ bcm_bprintf(strbuf, "INTERFACE[%d].DELAYQ(len,state,credit)" ++ "= (%d,%s,%d)\n", ++ i, ++ interfaces[i].psq.len, ++ ((interfaces[i].state == ++ WLFC_STATE_OPEN) ? " OPEN":"CLOSE"), ++ interfaces[i].requested_credit); ++ ++ bcm_bprintf(strbuf, "INTERFACE[%d].DELAYQ" ++ "(sup,ac0),(sup,ac1),(sup,ac2),(sup,ac3) = " ++ "(%d,%d),(%d,%d),(%d,%d),(%d,%d)\n", ++ i, ++ interfaces[i].psq.q[0].len, ++ interfaces[i].psq.q[1].len, ++ interfaces[i].psq.q[2].len, ++ interfaces[i].psq.q[3].len, ++ interfaces[i].psq.q[4].len, ++ interfaces[i].psq.q[5].len, ++ interfaces[i].psq.q[6].len, ++ interfaces[i].psq.q[7].len); ++ } ++ } ++ ++ bcm_bprintf(strbuf, "\n"); ++ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { ++ if (mac_table[i].occupied) { ++ ea = mac_table[i].ea; ++ bcm_bprintf(strbuf, "MAC_table[%d].ea = " ++ "[%02x:%02x:%02x:%02x:%02x:%02x], if:%d \n", i, ++ ea[0], ea[1], ea[2], ea[3], ea[4], ea[5], ++ mac_table[i].interface_id); ++ ++ bcm_bprintf(strbuf, "MAC_table[%d].DELAYQ(len,state,credit)" ++ "= (%d,%s,%d)\n", ++ i, ++ mac_table[i].psq.len, ++ ((mac_table[i].state == ++ WLFC_STATE_OPEN) ? " OPEN":"CLOSE"), ++ mac_table[i].requested_credit); ++#ifdef PROP_TXSTATUS_DEBUG ++ bcm_bprintf(strbuf, "MAC_table[%d]: (opened, closed) = (%d, %d)\n", ++ i, mac_table[i].opened_ct, mac_table[i].closed_ct); ++#endif ++ bcm_bprintf(strbuf, "MAC_table[%d].DELAYQ" ++ "(sup,ac0),(sup,ac1),(sup,ac2),(sup,ac3) = " ++ "(%d,%d),(%d,%d),(%d,%d),(%d,%d)\n", ++ i, ++ mac_table[i].psq.q[0].len, ++ mac_table[i].psq.q[1].len, ++ mac_table[i].psq.q[2].len, ++ mac_table[i].psq.q[3].len, ++ mac_table[i].psq.q[4].len, ++ mac_table[i].psq.q[5].len, ++ mac_table[i].psq.q[6].len, ++ mac_table[i].psq.q[7].len); ++ } ++ } ++ ++#ifdef PROP_TXSTATUS_DEBUG ++ { ++ int avg; ++ int moving_avg = 0; ++ int moving_samples; ++ ++ if (wlfc->stats.latency_sample_count) { ++ moving_samples = sizeof(wlfc->stats.deltas)/sizeof(uint32); ++ ++ for (i = 0; i < moving_samples; i++) ++ moving_avg += wlfc->stats.deltas[i]; ++ moving_avg /= moving_samples; ++ ++ avg = (100 * wlfc->stats.total_status_latency) / ++ wlfc->stats.latency_sample_count; ++ bcm_bprintf(strbuf, "txstatus latency (average, last, moving[%d]) = " ++ "(%d.%d, %03d, %03d)\n", ++ moving_samples, avg/100, (avg - (avg/100)*100), ++ wlfc->stats.latency_most_recent, ++ moving_avg); ++ } ++ } ++ ++ bcm_bprintf(strbuf, "wlfc- fifo[0-5] credit stats: sent = (%d,%d,%d,%d,%d,%d), " ++ "back = (%d,%d,%d,%d,%d,%d)\n", ++ wlfc->stats.fifo_credits_sent[0], ++ wlfc->stats.fifo_credits_sent[1], ++ wlfc->stats.fifo_credits_sent[2], ++ wlfc->stats.fifo_credits_sent[3], ++ wlfc->stats.fifo_credits_sent[4], ++ wlfc->stats.fifo_credits_sent[5], ++ ++ wlfc->stats.fifo_credits_back[0], ++ wlfc->stats.fifo_credits_back[1], ++ wlfc->stats.fifo_credits_back[2], ++ wlfc->stats.fifo_credits_back[3], ++ wlfc->stats.fifo_credits_back[4], ++ wlfc->stats.fifo_credits_back[5]); ++ { ++ uint32 fifo_cr_sent = 0; ++ uint32 fifo_cr_acked = 0; ++ uint32 request_cr_sent = 0; ++ uint32 request_cr_ack = 0; ++ uint32 bc_mc_cr_ack = 0; ++ ++ for (i = 0; i < sizeof(wlfc->stats.fifo_credits_sent)/sizeof(uint32); i++) { ++ fifo_cr_sent += wlfc->stats.fifo_credits_sent[i]; ++ } ++ ++ for (i = 0; i < sizeof(wlfc->stats.fifo_credits_back)/sizeof(uint32); i++) { ++ fifo_cr_acked += wlfc->stats.fifo_credits_back[i]; ++ } ++ ++ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { ++ if (wlfc->destination_entries.nodes[i].occupied) { ++ request_cr_sent += ++ wlfc->destination_entries.nodes[i].dstncredit_sent_packets; ++ } ++ } ++ for (i = 0; i < WLFC_MAX_IFNUM; i++) { ++ if (wlfc->destination_entries.interfaces[i].occupied) { ++ request_cr_sent += ++ wlfc->destination_entries.interfaces[i].dstncredit_sent_packets; ++ } ++ } ++ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { ++ if (wlfc->destination_entries.nodes[i].occupied) { ++ request_cr_ack += ++ wlfc->destination_entries.nodes[i].dstncredit_acks; ++ } ++ } ++ for (i = 0; i < WLFC_MAX_IFNUM; i++) { ++ if (wlfc->destination_entries.interfaces[i].occupied) { ++ request_cr_ack += ++ wlfc->destination_entries.interfaces[i].dstncredit_acks; ++ } ++ } ++ bcm_bprintf(strbuf, "wlfc- (sent, status) => pq(%d,%d), vq(%d,%d)," ++ "other:%d, bc_mc:%d, signal-only, (sent,freed): (%d,%d)", ++ fifo_cr_sent, fifo_cr_acked, ++ request_cr_sent, request_cr_ack, ++ wlfc->destination_entries.other.dstncredit_acks, ++ bc_mc_cr_ack, ++ wlfc->stats.signal_only_pkts_sent, wlfc->stats.signal_only_pkts_freed); ++ } ++#endif /* PROP_TXSTATUS_DEBUG */ ++ bcm_bprintf(strbuf, "\n"); ++ bcm_bprintf(strbuf, "wlfc- pkt((in,2bus,txstats,hdrpull),(dropped,hdr_only,wlc_tossed)" ++ "(freed,free_err,rollback)) = " ++ "((%d,%d,%d,%d),(%d,%d,%d),(%d,%d,%d))\n", ++ wlfc->stats.pktin, ++ wlfc->stats.pkt2bus, ++ wlfc->stats.txstatus_in, ++ wlfc->stats.dhd_hdrpulls, ++ ++ wlfc->stats.pktdropped, ++ wlfc->stats.wlfc_header_only_pkt, ++ wlfc->stats.wlc_tossed_pkts, ++ ++ wlfc->stats.pkt_freed, ++ wlfc->stats.pkt_free_err, wlfc->stats.rollback); ++ ++ bcm_bprintf(strbuf, "wlfc- suppress((d11,wlc,err),enq(d11,wl,hq,mac?),retx(d11,wlc,hq)) = " ++ "((%d,%d,%d),(%d,%d,%d,%d),(%d,%d,%d))\n", ++ ++ wlfc->stats.d11_suppress, ++ wlfc->stats.wl_suppress, ++ wlfc->stats.bad_suppress, ++ ++ wlfc->stats.psq_d11sup_enq, ++ wlfc->stats.psq_wlsup_enq, ++ wlfc->stats.psq_hostq_enq, ++ wlfc->stats.mac_handle_notfound, ++ ++ wlfc->stats.psq_d11sup_retx, ++ wlfc->stats.psq_wlsup_retx, ++ wlfc->stats.psq_hostq_retx); ++ bcm_bprintf(strbuf, "wlfc- generic error: %d", wlfc->stats.generic_error); ++ ++ return; ++} ++ ++/* Create a place to store all packet pointers submitted to the firmware until ++ a status comes back, suppress or otherwise. ++ ++ hang-er: noun, a contrivance on which things are hung, as a hook. ++*/ ++static void* ++dhd_wlfc_hanger_create(osl_t *osh, int max_items) ++{ ++ int i; ++ wlfc_hanger_t* hanger; ++ ++ /* allow only up to a specific size for now */ ++ ASSERT(max_items == WLFC_HANGER_MAXITEMS); ++ ++ if ((hanger = (wlfc_hanger_t*)MALLOC(osh, WLFC_HANGER_SIZE(max_items))) == NULL) ++ return NULL; ++ ++ memset(hanger, 0, WLFC_HANGER_SIZE(max_items)); ++ hanger->max_items = max_items; ++ ++ for (i = 0; i < hanger->max_items; i++) { ++ hanger->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; ++ } ++ return hanger; ++} ++ ++static int ++dhd_wlfc_hanger_delete(osl_t *osh, void* hanger) ++{ ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; ++ ++ if (h) { ++ MFREE(osh, h, WLFC_HANGER_SIZE(h->max_items)); ++ return BCME_OK; ++ } ++ return BCME_BADARG; ++} ++ ++static uint16 ++dhd_wlfc_hanger_get_free_slot(void* hanger) ++{ ++ uint32 i; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; ++ ++ if (h) { ++ i = h->slot_pos + 1; ++ if (i == h->max_items) { ++ i = 0; ++ } ++ while (i != h->slot_pos) { ++ if (h->items[i].state == WLFC_HANGER_ITEM_STATE_FREE) { ++ h->slot_pos = i; ++ return (uint16)i; ++ } ++ i++; ++ if (i == h->max_items) ++ i = 0; ++ } ++ h->failed_slotfind++; ++ } ++ return WLFC_HANGER_MAXITEMS; ++} ++ ++static int ++dhd_wlfc_hanger_get_genbit(void* hanger, void* pkt, uint32 slot_id, int* gen) ++{ ++ int rc = BCME_OK; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; ++ ++ *gen = 0xff; ++ ++ /* this packet was not pushed at the time it went to the firmware */ ++ if (slot_id == WLFC_HANGER_MAXITEMS) ++ return BCME_NOTFOUND; ++ ++ if (h) { ++ if ((h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE) || ++ (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED)) { ++ *gen = h->items[slot_id].gen; ++ } ++ else { ++ rc = BCME_NOTFOUND; ++ } ++ } ++ else ++ rc = BCME_BADARG; ++ return rc; ++} ++ ++static int ++dhd_wlfc_hanger_pushpkt(void* hanger, void* pkt, uint32 slot_id) ++{ ++ int rc = BCME_OK; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; ++ ++ if (h && (slot_id < WLFC_HANGER_MAXITEMS)) { ++ if (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_FREE) { ++ h->items[slot_id].state = WLFC_HANGER_ITEM_STATE_INUSE; ++ h->items[slot_id].pkt = pkt; ++ h->items[slot_id].identifier = slot_id; ++ h->pushed++; ++ } ++ else { ++ h->failed_to_push++; ++ rc = BCME_NOTFOUND; ++ } ++ } ++ else ++ rc = BCME_BADARG; ++ return rc; ++} ++ ++static int ++dhd_wlfc_hanger_poppkt(void* hanger, uint32 slot_id, void** pktout, int remove_from_hanger) ++{ ++ int rc = BCME_OK; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; ++ ++ /* this packet was not pushed at the time it went to the firmware */ ++ if (slot_id == WLFC_HANGER_MAXITEMS) ++ return BCME_NOTFOUND; ++ ++ if (h) { ++ if (h->items[slot_id].state != WLFC_HANGER_ITEM_STATE_FREE) { ++ *pktout = h->items[slot_id].pkt; ++ if (remove_from_hanger) { ++ h->items[slot_id].state = ++ WLFC_HANGER_ITEM_STATE_FREE; ++ h->items[slot_id].pkt = NULL; ++ h->items[slot_id].identifier = 0; ++ h->items[slot_id].gen = 0xff; ++ h->popped++; ++ } ++ } ++ else { ++ h->failed_to_pop++; ++ rc = BCME_NOTFOUND; ++ } ++ } ++ else ++ rc = BCME_BADARG; ++ return rc; ++} ++ ++static int ++dhd_wlfc_hanger_mark_suppressed(void* hanger, uint32 slot_id, uint8 gen) ++{ ++ int rc = BCME_OK; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; ++ ++ /* this packet was not pushed at the time it went to the firmware */ ++ if (slot_id == WLFC_HANGER_MAXITEMS) ++ return BCME_NOTFOUND; ++ if (h) { ++ h->items[slot_id].gen = gen; ++ if (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE) { ++ h->items[slot_id].state = WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED; ++ } ++ else ++ rc = BCME_BADARG; ++ } ++ else ++ rc = BCME_BADARG; ++ ++ return rc; ++} ++ ++static int ++_dhd_wlfc_pushheader(athost_wl_status_info_t* ctx, void* p, bool tim_signal, ++ uint8 tim_bmp, uint8 mac_handle, uint32 htodtag) ++{ ++ uint32 wl_pktinfo = 0; ++ uint8* wlh; ++ uint8 dataOffset; ++ uint8 fillers; ++ uint8 tim_signal_len = 0; ++ ++ struct bdc_header *h; ++ ++ if (tim_signal) { ++ tim_signal_len = 1 + 1 + WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP; ++ } ++ ++ /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */ ++ dataOffset = WLFC_CTL_VALUE_LEN_PKTTAG + 2 + tim_signal_len; ++ fillers = ROUNDUP(dataOffset, 4) - dataOffset; ++ dataOffset += fillers; ++ ++ PKTPUSH(ctx->osh, p, dataOffset); ++ wlh = (uint8*) PKTDATA(ctx->osh, p); ++ ++ wl_pktinfo = htol32(htodtag); ++ ++ wlh[0] = WLFC_CTL_TYPE_PKTTAG; ++ wlh[1] = WLFC_CTL_VALUE_LEN_PKTTAG; ++ memcpy(&wlh[2], &wl_pktinfo, sizeof(uint32)); ++ ++ if (tim_signal_len) { ++ wlh[dataOffset - fillers - tim_signal_len ] = ++ WLFC_CTL_TYPE_PENDING_TRAFFIC_BMP; ++ wlh[dataOffset - fillers - tim_signal_len + 1] = ++ WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP; ++ wlh[dataOffset - fillers - tim_signal_len + 2] = mac_handle; ++ wlh[dataOffset - fillers - tim_signal_len + 3] = tim_bmp; ++ } ++ if (fillers) ++ memset(&wlh[dataOffset - fillers], WLFC_CTL_TYPE_FILLER, fillers); ++ ++ PKTPUSH(ctx->osh, p, BDC_HEADER_LEN); ++ h = (struct bdc_header *)PKTDATA(ctx->osh, p); ++ h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); ++ if (PKTSUMNEEDED(p)) ++ h->flags |= BDC_FLAG_SUM_NEEDED; ++ ++ ++ h->priority = (PKTPRIO(p) & BDC_PRIORITY_MASK); ++ h->flags2 = 0; ++ h->dataOffset = dataOffset >> 2; ++ BDC_SET_IF_IDX(h, DHD_PKTTAG_IF(PKTTAG(p))); ++ return BCME_OK; ++} ++ ++static int ++_dhd_wlfc_pullheader(athost_wl_status_info_t* ctx, void* pktbuf) ++{ ++ struct bdc_header *h; ++ ++ if (PKTLEN(ctx->osh, pktbuf) < BDC_HEADER_LEN) { ++ AP6210_DEBUG("%s: rx data too short (%d < %d)\n", __FUNCTION__, ++ PKTLEN(ctx->osh, pktbuf), BDC_HEADER_LEN); ++ return BCME_ERROR; ++ } ++ h = (struct bdc_header *)PKTDATA(ctx->osh, pktbuf); ++ ++ /* pull BDC header */ ++ PKTPULL(ctx->osh, pktbuf, BDC_HEADER_LEN); ++ ++ if (PKTLEN(ctx->osh, pktbuf) < (h->dataOffset << 2)) { ++ AP6210_DEBUG("%s: rx data too short (%d < %d)\n", __FUNCTION__, ++ PKTLEN(ctx->osh, pktbuf), (h->dataOffset << 2)); ++ return BCME_ERROR; ++ } ++ ++ /* pull wl-header */ ++ PKTPULL(ctx->osh, pktbuf, (h->dataOffset << 2)); ++ return BCME_OK; ++} ++ ++static wlfc_mac_descriptor_t* ++_dhd_wlfc_find_table_entry(athost_wl_status_info_t* ctx, void* p) ++{ ++ int i; ++ wlfc_mac_descriptor_t* table = ctx->destination_entries.nodes; ++ uint8 ifid = DHD_PKTTAG_IF(PKTTAG(p)); ++ uint8* dstn = DHD_PKTTAG_DSTN(PKTTAG(p)); ++ wlfc_mac_descriptor_t* entry = NULL; ++ int iftype = ctx->destination_entries.interfaces[ifid].iftype; ++ ++ /* Multicast destination and P2P clients get the interface entry. ++ * STA gets the interface entry if there is no exact match. For ++ * example, TDLS destinations have their own entry. ++ */ ++ if ((iftype == WLC_E_IF_ROLE_STA || ETHER_ISMULTI(dstn) || ++ iftype == WLC_E_IF_ROLE_P2P_CLIENT) && ++ (ctx->destination_entries.interfaces[ifid].occupied)) { ++ entry = &ctx->destination_entries.interfaces[ifid]; ++ } ++ ++ if (entry != NULL && ETHER_ISMULTI(dstn)) ++ return entry; ++ ++ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { ++ if (table[i].occupied) { ++ if (table[i].interface_id == ifid) { ++ if (!memcmp(table[i].ea, dstn, ETHER_ADDR_LEN)) { ++ entry = &table[i]; ++ break; ++ } ++ } ++ } ++ } ++ ++ return entry != NULL ? entry : &ctx->destination_entries.other; ++} ++ ++static int ++_dhd_wlfc_rollback_packet_toq(athost_wl_status_info_t* ctx, ++ void* p, ewlfc_packet_state_t pkt_type, uint32 hslot) ++{ ++ /* ++ put the packet back to the head of queue ++ ++ - suppressed packet goes back to suppress sub-queue ++ - pull out the header, if new or delayed packet ++ ++ Note: hslot is used only when header removal is done. ++ */ ++ wlfc_mac_descriptor_t* entry; ++ void* pktout; ++ int rc = BCME_OK; ++ int prec; ++ ++ entry = _dhd_wlfc_find_table_entry(ctx, p); ++ prec = DHD_PKTTAG_FIFO(PKTTAG(p)); ++ if (entry != NULL) { ++ if (pkt_type == eWLFC_PKTTYPE_SUPPRESSED) { ++ /* wl-header is saved for suppressed packets */ ++ if (WLFC_PKTQ_PENQ_HEAD(&entry->psq, ((prec << 1) + 1), p) == NULL) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ rc = BCME_ERROR; ++ } ++ } ++ else { ++ /* remove header first */ ++ rc = _dhd_wlfc_pullheader(ctx, p); ++ if (rc != BCME_OK) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ /* free the hanger slot */ ++ dhd_wlfc_hanger_poppkt(ctx->hanger, hslot, &pktout, 1); ++ PKTFREE(ctx->osh, p, TRUE); ++ ctx->stats.rollback_failed++; ++ return BCME_ERROR; ++ } ++ ++ if (pkt_type == eWLFC_PKTTYPE_DELAYED) { ++ /* delay-q packets are going to delay-q */ ++ if (WLFC_PKTQ_PENQ_HEAD(&entry->psq, (prec << 1), p) == NULL) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ rc = BCME_ERROR; ++ } ++ } ++ ++ /* free the hanger slot */ ++ dhd_wlfc_hanger_poppkt(ctx->hanger, hslot, &pktout, 1); ++ ++ /* decrement sequence count */ ++ WLFC_DECR_SEQCOUNT(entry, prec); ++ } ++ /* ++ if this packet did not count against FIFO credit, it must have ++ taken a requested_credit from the firmware (for pspoll etc.) ++ */ ++ if (!DHD_PKTTAG_CREDITCHECK(PKTTAG(p))) { ++ entry->requested_credit++; ++ } ++ } ++ else { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ rc = BCME_ERROR; ++ } ++ if (rc != BCME_OK) ++ ctx->stats.rollback_failed++; ++ else ++ ctx->stats.rollback++; ++ ++ return rc; ++} ++ ++static void ++_dhd_wlfc_flow_control_check(athost_wl_status_info_t* ctx, struct pktq* pq, uint8 if_id) ++{ ++ dhd_pub_t *dhdp; ++ ++ ASSERT(ctx); ++ ++ dhdp = (dhd_pub_t *)ctx->dhdp; ++ ++ if (dhdp && dhdp->skip_fc && dhdp->skip_fc()) ++ return; ++ ++ if ((pq->len <= WLFC_FLOWCONTROL_LOWATER) && (ctx->hostif_flow_state[if_id] == ON)) { ++ /* start traffic */ ++ ctx->hostif_flow_state[if_id] = OFF; ++ /* ++ AP6210_DEBUG("qlen:%02d, if:%02d, ->OFF, start traffic %s()\n", ++ pq->len, if_id, __FUNCTION__); ++ */ ++ AP6210_DEBUG("F"); ++ ++ dhd_txflowcontrol(ctx->dhdp, if_id, OFF); ++ ++ ctx->toggle_host_if = 0; ++ } ++ if ((pq->len >= WLFC_FLOWCONTROL_HIWATER) && (ctx->hostif_flow_state[if_id] == OFF)) { ++ /* stop traffic */ ++ ctx->hostif_flow_state[if_id] = ON; ++ /* ++ AP6210_DEBUG("qlen:%02d, if:%02d, ->ON, stop traffic %s()\n", ++ pq->len, if_id, __FUNCTION__); ++ */ ++ AP6210_DEBUG("N"); ++ ++ dhd_txflowcontrol(ctx->dhdp, if_id, ON); ++ ++ ctx->host_ifidx = if_id; ++ ctx->toggle_host_if = 1; ++ } ++ ++ return; ++} ++ ++static int ++_dhd_wlfc_send_signalonly_packet(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry, ++ uint8 ta_bmp) ++{ ++ int rc = BCME_OK; ++ void* p = NULL; ++ int dummylen = ((dhd_pub_t *)ctx->dhdp)->hdrlen+ 12; ++ ++ /* allocate a dummy packet */ ++ p = PKTGET(ctx->osh, dummylen, TRUE); ++ if (p) { ++ PKTPULL(ctx->osh, p, dummylen); ++ DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), 0); ++ _dhd_wlfc_pushheader(ctx, p, TRUE, ta_bmp, entry->mac_handle, 0); ++ DHD_PKTTAG_SETSIGNALONLY(PKTTAG(p), 1); ++#ifdef PROP_TXSTATUS_DEBUG ++ ctx->stats.signal_only_pkts_sent++; ++#endif ++ rc = dhd_bus_txdata(((dhd_pub_t *)ctx->dhdp)->bus, p); ++ if (rc != BCME_OK) { ++ PKTFREE(ctx->osh, p, TRUE); ++ } ++ } ++ else { ++ AP6210_ERR("%s: couldn't allocate new %d-byte packet\n", ++ __FUNCTION__, dummylen); ++ rc = BCME_NOMEM; ++ } ++ return rc; ++} ++ ++/* Return TRUE if traffic availability changed */ ++static bool ++_dhd_wlfc_traffic_pending_check(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry, ++ int prec) ++{ ++ bool rc = FALSE; ++ ++ if (entry->state == WLFC_STATE_CLOSE) { ++ if ((pktq_plen(&entry->psq, (prec << 1)) == 0) && ++ (pktq_plen(&entry->psq, ((prec << 1) + 1)) == 0)) { ++ ++ if (entry->traffic_pending_bmp & NBITVAL(prec)) { ++ rc = TRUE; ++ entry->traffic_pending_bmp = ++ entry->traffic_pending_bmp & ~ NBITVAL(prec); ++ } ++ } ++ else { ++ if (!(entry->traffic_pending_bmp & NBITVAL(prec))) { ++ rc = TRUE; ++ entry->traffic_pending_bmp = ++ entry->traffic_pending_bmp | NBITVAL(prec); ++ } ++ } ++ } ++ if (rc) { ++ /* request a TIM update to firmware at the next piggyback opportunity */ ++ if (entry->traffic_lastreported_bmp != entry->traffic_pending_bmp) { ++ entry->send_tim_signal = 1; ++ _dhd_wlfc_send_signalonly_packet(ctx, entry, entry->traffic_pending_bmp); ++ entry->traffic_lastreported_bmp = entry->traffic_pending_bmp; ++ entry->send_tim_signal = 0; ++ } ++ else { ++ rc = FALSE; ++ } ++ } ++ return rc; ++} ++ ++static int ++_dhd_wlfc_enque_suppressed(athost_wl_status_info_t* ctx, int prec, void* p) ++{ ++ wlfc_mac_descriptor_t* entry; ++ ++ entry = _dhd_wlfc_find_table_entry(ctx, p); ++ if (entry == NULL) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ return BCME_NOTFOUND; ++ } ++ /* ++ - suppressed packets go to sub_queue[2*prec + 1] AND ++ - delayed packets go to sub_queue[2*prec + 0] to ensure ++ order of delivery. ++ */ ++ if (WLFC_PKTQ_PENQ(&entry->psq, ((prec << 1) + 1), p) == NULL) { ++ ctx->stats.delayq_full_error++; ++ /* AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); */ ++ AP6210_DEBUG("s"); ++ return BCME_ERROR; ++ } ++ /* A packet has been pushed, update traffic availability bitmap, if applicable */ ++ _dhd_wlfc_traffic_pending_check(ctx, entry, prec); ++ _dhd_wlfc_flow_control_check(ctx, &entry->psq, DHD_PKTTAG_IF(PKTTAG(p))); ++ return BCME_OK; ++} ++ ++static int ++_dhd_wlfc_pretx_pktprocess(athost_wl_status_info_t* ctx, ++ wlfc_mac_descriptor_t* entry, void* p, int header_needed, uint32* slot) ++{ ++ int rc = BCME_OK; ++ int hslot = WLFC_HANGER_MAXITEMS; ++ bool send_tim_update = FALSE; ++ uint32 htod = 0; ++ uint8 free_ctr; ++ ++ *slot = hslot; ++ ++ if (entry == NULL) { ++ entry = _dhd_wlfc_find_table_entry(ctx, p); ++ } ++ ++ if (entry == NULL) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ return BCME_ERROR; ++ } ++ if (entry->send_tim_signal) { ++ send_tim_update = TRUE; ++ entry->send_tim_signal = 0; ++ entry->traffic_lastreported_bmp = entry->traffic_pending_bmp; ++ } ++ if (header_needed) { ++ hslot = dhd_wlfc_hanger_get_free_slot(ctx->hanger); ++ free_ctr = WLFC_SEQCOUNT(entry, DHD_PKTTAG_FIFO(PKTTAG(p))); ++ DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), htod); ++ WLFC_PKTFLAG_SET_GENERATION(htod, entry->generation); ++ entry->transit_count++; ++ } ++ else { ++ hslot = WLFC_PKTID_HSLOT_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); ++ free_ctr = WLFC_PKTID_FREERUNCTR_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); ++ } ++ WLFC_PKTID_HSLOT_SET(htod, hslot); ++ WLFC_PKTID_FREERUNCTR_SET(htod, free_ctr); ++ DHD_PKTTAG_SETPKTDIR(PKTTAG(p), 1); ++ WL_TXSTATUS_SET_FLAGS(htod, WLFC_PKTFLAG_PKTFROMHOST); ++ WL_TXSTATUS_SET_FIFO(htod, DHD_PKTTAG_FIFO(PKTTAG(p))); ++ ++ ++ if (!DHD_PKTTAG_CREDITCHECK(PKTTAG(p))) { ++ /* ++ Indicate that this packet is being sent in response to an ++ explicit request from the firmware side. ++ */ ++ WLFC_PKTFLAG_SET_PKTREQUESTED(htod); ++ } ++ else { ++ WLFC_PKTFLAG_CLR_PKTREQUESTED(htod); ++ } ++ if (header_needed) { ++ rc = _dhd_wlfc_pushheader(ctx, p, send_tim_update, ++ entry->traffic_lastreported_bmp, entry->mac_handle, htod); ++ if (rc == BCME_OK) { ++ DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), htod); ++ /* ++ a new header was created for this packet. ++ push to hanger slot and scrub q. Since bus ++ send succeeded, increment seq number as well. ++ */ ++ rc = dhd_wlfc_hanger_pushpkt(ctx->hanger, p, hslot); ++ if (rc == BCME_OK) { ++ /* increment free running sequence count */ ++ WLFC_INCR_SEQCOUNT(entry, DHD_PKTTAG_FIFO(PKTTAG(p))); ++#ifdef PROP_TXSTATUS_DEBUG ++ ((wlfc_hanger_t*)(ctx->hanger))->items[hslot].push_time = ++ OSL_SYSUPTIME(); ++#endif ++ } ++ else { ++ AP6210_DEBUG("%s() hanger_pushpkt() failed, rc: %d\n", ++ __FUNCTION__, rc); ++ } ++ } ++ } ++ else { ++ int gen; ++ ++ /* remove old header */ ++ rc = _dhd_wlfc_pullheader(ctx, p); ++ if (rc == BCME_OK) { ++ hslot = WLFC_PKTID_HSLOT_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); ++ dhd_wlfc_hanger_get_genbit(ctx->hanger, p, hslot, &gen); ++ ++ WLFC_PKTFLAG_SET_GENERATION(htod, gen); ++ free_ctr = WLFC_PKTID_FREERUNCTR_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); ++ /* push new header */ ++ _dhd_wlfc_pushheader(ctx, p, send_tim_update, ++ entry->traffic_lastreported_bmp, entry->mac_handle, htod); ++ } ++ } ++ *slot = hslot; ++ return rc; ++} ++ ++static int ++_dhd_wlfc_is_destination_closed(athost_wl_status_info_t* ctx, ++ wlfc_mac_descriptor_t* entry, int prec) ++{ ++ if (ctx->destination_entries.interfaces[entry->interface_id].iftype == ++ WLC_E_IF_ROLE_P2P_GO) { ++ /* - destination interface is of type p2p GO. ++ For a p2pGO interface, if the destination is OPEN but the interface is ++ CLOSEd, do not send traffic. But if the dstn is CLOSEd while there is ++ destination-specific-credit left send packets. This is because the ++ firmware storing the destination-specific-requested packet in queue. ++ */ ++ if ((entry->state == WLFC_STATE_CLOSE) && (entry->requested_credit == 0) && ++ (entry->requested_packet == 0)) ++ return 1; ++ } ++ /* AP, p2p_go -> unicast desc entry, STA/p2p_cl -> interface desc. entry */ ++ if (((entry->state == WLFC_STATE_CLOSE) && (entry->requested_credit == 0) && ++ (entry->requested_packet == 0)) || ++ (!(entry->ac_bitmap & (1 << prec)))) ++ return 1; ++ ++ return 0; ++} ++ ++static void* ++_dhd_wlfc_deque_delayedq(athost_wl_status_info_t* ctx, ++ int prec, uint8* ac_credit_spent, uint8* needs_hdr, wlfc_mac_descriptor_t** entry_out) ++{ ++ wlfc_mac_descriptor_t* entry; ++ wlfc_mac_descriptor_t* table; ++ uint8 token_pos; ++ int total_entries; ++ void* p = NULL; ++ int pout; ++ int i; ++ ++ *entry_out = NULL; ++ token_pos = ctx->token_pos[prec]; ++ /* most cases a packet will count against FIFO credit */ ++ *ac_credit_spent = 1; ++ *needs_hdr = 1; ++ ++ /* search all entries, include nodes as well as interfaces */ ++ table = (wlfc_mac_descriptor_t*)&ctx->destination_entries; ++ total_entries = sizeof(ctx->destination_entries)/sizeof(wlfc_mac_descriptor_t); ++ ++ for (i = 0; i < total_entries; i++) { ++ entry = &table[(token_pos + i) % total_entries]; ++ if (entry->occupied && !entry->deleting) { ++ if (!_dhd_wlfc_is_destination_closed(ctx, entry, prec)) { ++ p = pktq_mdeq(&entry->psq, ++ /* higher precedence will be picked up first, ++ * i.e. suppressed packets before delayed ones ++ */ ++ NBITVAL((prec << 1) + 1), &pout); ++ *needs_hdr = 0; ++ ++ if (p == NULL) { ++ if (entry->suppressed == TRUE) { ++ if ((entry->suppr_transit_count <= ++ entry->suppress_count)) { ++ entry->suppressed = FALSE; ++ } else { ++ return NULL; ++ } ++ } ++ /* De-Q from delay Q */ ++ p = pktq_mdeq(&entry->psq, ++ NBITVAL((prec << 1)), ++ &pout); ++ *needs_hdr = 1; ++ } ++ ++ if (p != NULL) { ++ /* did the packet come from suppress sub-queue? */ ++ if (entry->requested_credit > 0) { ++ entry->requested_credit--; ++#ifdef PROP_TXSTATUS_DEBUG ++ entry->dstncredit_sent_packets++; ++#endif ++ /* ++ if the packet was pulled out while destination is in ++ closed state but had a non-zero packets requested, ++ then this should not count against the FIFO credit. ++ That is due to the fact that the firmware will ++ most likely hold onto this packet until a suitable ++ time later to push it to the appropriate AC FIFO. ++ */ ++ if (entry->state == WLFC_STATE_CLOSE) ++ *ac_credit_spent = 0; ++ } ++ else if (entry->requested_packet > 0) { ++ entry->requested_packet--; ++ DHD_PKTTAG_SETONETIMEPKTRQST(PKTTAG(p)); ++ if (entry->state == WLFC_STATE_CLOSE) ++ *ac_credit_spent = 0; ++ } ++ /* move token to ensure fair round-robin */ ++ ctx->token_pos[prec] = ++ (token_pos + i + 1) % total_entries; ++ *entry_out = entry; ++ _dhd_wlfc_flow_control_check(ctx, &entry->psq, ++ DHD_PKTTAG_IF(PKTTAG(p))); ++ /* ++ A packet has been picked up, update traffic ++ availability bitmap, if applicable ++ */ ++ _dhd_wlfc_traffic_pending_check(ctx, entry, prec); ++ return p; ++ } ++ } ++ } ++ } ++ return NULL; ++} ++ ++void * ++_dhd_wlfc_pktq_peek_tail(struct pktq *pq, int *prec_out) ++{ ++ int prec; ++ ++ ASSERT(pq); ++ ++ if (pq->len == 0) ++ return NULL; ++ ++ for (prec = 0; prec < pq->hi_prec; prec++) ++ /* only pick packets from dealyed-q */ ++ if (((prec & 1) == 0) && pq->q[prec].head) ++ break; ++ ++ if (prec_out) ++ *prec_out = prec; ++ ++ return (pq->q[prec].tail); ++} ++ ++bool ++_dhd_wlfc_prec_enq_with_drop(dhd_pub_t *dhdp, struct pktq *pq, void *pkt, int prec) ++{ ++ void *p = NULL; ++ int eprec = -1; /* precedence to evict from */ ++ ++ ASSERT(dhdp && pq && pkt); ++ ASSERT(prec >= 0 && prec < pq->num_prec); ++ ++ /* Fast case, precedence queue is not full and we are also not ++ * exceeding total queue length ++ */ ++ if (!pktq_pfull(pq, prec) && !pktq_full(pq)) { ++ pktq_penq(pq, prec, pkt); ++ return TRUE; ++ } ++ ++ /* Determine precedence from which to evict packet, if any */ ++ if (pktq_pfull(pq, prec)) ++ eprec = prec; ++ else if (pktq_full(pq)) { ++ p = _dhd_wlfc_pktq_peek_tail(pq, &eprec); ++ if (!p) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ return FALSE; ++ } ++ if ((eprec > prec) || (eprec < 0)) { ++ if (!pktq_pempty(pq, prec)) { ++ eprec = prec; ++ } else { ++ return FALSE; ++ } ++ } ++ } ++ ++ /* Evict if needed */ ++ if (eprec >= 0) { ++ /* Detect queueing to unconfigured precedence */ ++ ASSERT(!pktq_pempty(pq, eprec)); ++ /* Evict all fragmented frames */ ++ dhd_prec_drop_pkts(dhdp->osh, pq, eprec); ++ } ++ ++ /* Enqueue */ ++ p = pktq_penq(pq, prec, pkt); ++ if (!p) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++static int ++_dhd_wlfc_enque_delayq(athost_wl_status_info_t* ctx, void* pktbuf, int prec) ++{ ++ wlfc_mac_descriptor_t* entry; ++ ++ if (pktbuf != NULL) { ++ entry = _dhd_wlfc_find_table_entry(ctx, pktbuf); ++ ++ if (entry == NULL) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ return BCME_ERROR; ++ } ++ ++ /* ++ - suppressed packets go to sub_queue[2*prec + 1] AND ++ - delayed packets go to sub_queue[2*prec + 0] to ensure ++ order of delivery. ++ */ ++ if (_dhd_wlfc_prec_enq_with_drop(ctx->dhdp, &entry->psq, pktbuf, (prec << 1)) ++ == FALSE) { ++ AP6210_DEBUG("D"); ++ /* dhd_txcomplete(ctx->dhdp, pktbuf, FALSE); */ ++ PKTFREE(ctx->osh, pktbuf, TRUE); ++ ctx->stats.delayq_full_error++; ++ return BCME_ERROR; ++ } ++ ++ /* ++ A packet has been pushed, update traffic availability bitmap, ++ if applicable ++ */ ++ _dhd_wlfc_traffic_pending_check(ctx, entry, prec); ++ ++ } ++ return BCME_OK; ++} ++ ++bool ifpkt_fn(void* p, int ifid) ++{ ++ return (ifid == DHD_PKTTAG_IF(PKTTAG(p))); ++} ++ ++static int ++_dhd_wlfc_mac_entry_update(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry, ++ ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea) ++{ ++ int rc = BCME_OK; ++ ++ if (action == eWLFC_MAC_ENTRY_ACTION_ADD) { ++ entry->occupied = 1; ++ entry->state = WLFC_STATE_OPEN; ++ entry->requested_credit = 0; ++ entry->interface_id = ifid; ++ entry->iftype = iftype; ++ entry->ac_bitmap = 0xff; /* update this when handling APSD */ ++ /* for an interface entry we may not care about the MAC address */ ++ if (ea != NULL) ++ memcpy(&entry->ea[0], ea, ETHER_ADDR_LEN); ++ pktq_init(&entry->psq, WLFC_PSQ_PREC_COUNT, WLFC_PSQ_LEN); ++ } ++ else if (action == eWLFC_MAC_ENTRY_ACTION_UPDATE) { ++ entry->occupied = 1; ++ entry->state = WLFC_STATE_OPEN; ++ entry->requested_credit = 0; ++ entry->interface_id = ifid; ++ entry->iftype = iftype; ++ entry->ac_bitmap = 0xff; /* update this when handling APSD */ ++ /* for an interface entry we may not care about the MAC address */ ++ if (ea != NULL) ++ memcpy(&entry->ea[0], ea, ETHER_ADDR_LEN); ++ } ++ else if (action == eWLFC_MAC_ENTRY_ACTION_DEL) { ++ /* When the entry is deleted, the packets that are queued in the entry must be ++ cleanup. The cleanup action should be before the occupied is set as 0. The ++ flag deleting is set to avoid de-queue action when these queues are being ++ cleanup ++ */ ++ entry->deleting = 1; ++ dhd_wlfc_cleanup(ctx->dhdp, ifpkt_fn, ifid); ++ _dhd_wlfc_flow_control_check(ctx, &entry->psq, ifid); ++ entry->deleting = 0; ++ ++ entry->occupied = 0; ++ entry->suppressed = 0; ++ entry->state = WLFC_STATE_CLOSE; ++ entry->requested_credit = 0; ++ entry->transit_count = 0; ++ entry->suppr_transit_count = 0; ++ entry->suppress_count = 0; ++ memset(&entry->ea[0], 0, ETHER_ADDR_LEN); ++ ++ /* enable after packets are queued-deqeued properly. ++ pktq_flush(dhd->osh, &entry->psq, FALSE, NULL, 0); ++ */ ++ } ++ return rc; ++} ++ ++int ++_dhd_wlfc_borrow_credit(athost_wl_status_info_t* ctx, uint8 available_credit_map, int borrower_ac) ++{ ++ int lender_ac; ++ int rc = BCME_ERROR; ++ ++ if (ctx == NULL || available_credit_map == 0) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ return BCME_BADARG; ++ } ++ ++ /* Borrow from lowest priority available AC (including BC/MC credits) */ ++ for (lender_ac = 0; lender_ac <= AC_COUNT; lender_ac++) { ++ if ((available_credit_map && (1 << lender_ac)) && ++ (ctx->FIFO_credit[lender_ac] > 0)) { ++ ctx->credits_borrowed[borrower_ac][lender_ac]++; ++ ctx->FIFO_credit[lender_ac]--; ++ rc = BCME_OK; ++ break; ++ } ++ } ++ ++ return rc; ++} ++ ++int ++dhd_wlfc_interface_entry_update(void* state, ++ ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea) ++{ ++ athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; ++ wlfc_mac_descriptor_t* entry; ++ int ret; ++ ++ if (ifid >= WLFC_MAX_IFNUM) ++ return BCME_BADARG; ++ ++ entry = &ctx->destination_entries.interfaces[ifid]; ++ ret = _dhd_wlfc_mac_entry_update(ctx, entry, action, ifid, iftype, ea); ++ return ret; ++} ++ ++int ++dhd_wlfc_FIFOcreditmap_update(void* state, uint8* credits) ++{ ++ athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; ++ ++ /* update the AC FIFO credit map */ ++ ctx->FIFO_credit[0] = credits[0]; ++ ctx->FIFO_credit[1] = credits[1]; ++ ctx->FIFO_credit[2] = credits[2]; ++ ctx->FIFO_credit[3] = credits[3]; ++ /* credit for bc/mc packets */ ++ ctx->FIFO_credit[4] = credits[4]; ++ /* credit for ATIM FIFO is not used yet. */ ++ ctx->FIFO_credit[5] = 0; ++ return BCME_OK; ++} ++ ++int ++_dhd_wlfc_handle_packet_commit(athost_wl_status_info_t* ctx, int ac, ++ dhd_wlfc_commit_info_t *commit_info, f_commitpkt_t fcommit, void* commit_ctx) ++{ ++ uint32 hslot; ++ int rc; ++ ++ /* ++ if ac_fifo_credit_spent = 0 ++ ++ This packet will not count against the FIFO credit. ++ To ensure the txstatus corresponding to this packet ++ does not provide an implied credit (default behavior) ++ mark the packet accordingly. ++ ++ if ac_fifo_credit_spent = 1 ++ ++ This is a normal packet and it counts against the FIFO ++ credit count. ++ */ ++ DHD_PKTTAG_SETCREDITCHECK(PKTTAG(commit_info->p), commit_info->ac_fifo_credit_spent); ++ rc = _dhd_wlfc_pretx_pktprocess(ctx, commit_info->mac_entry, commit_info->p, ++ commit_info->needs_hdr, &hslot); ++ ++ if (rc == BCME_OK) ++ rc = fcommit(commit_ctx, commit_info->p); ++ else ++ ctx->stats.generic_error++; ++ ++ if (rc == BCME_OK) { ++ ctx->stats.pkt2bus++; ++ if (commit_info->ac_fifo_credit_spent) { ++ ctx->stats.send_pkts[ac]++; ++ WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac); ++ } ++ } else if (rc == BCME_NORESOURCE) ++ rc = BCME_ERROR; ++ else { ++ /* ++ bus commit has failed, rollback. ++ - remove wl-header for a delayed packet ++ - save wl-header header for suppressed packets ++ */ ++ rc = _dhd_wlfc_rollback_packet_toq(ctx, commit_info->p, ++ (commit_info->pkt_type), hslot); ++ ++ rc = BCME_ERROR; ++ } ++ ++ return rc; ++} ++ ++int ++dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx, void *pktbuf) ++{ ++ int ac; ++ int credit; ++ int rc; ++ dhd_wlfc_commit_info_t commit_info; ++ athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; ++ int credit_count = 0; ++ int bus_retry_count = 0; ++ uint8 ac_available = 0; /* Bitmask for 4 ACs + BC/MC */ ++ ++ if ((state == NULL) || ++ (fcommit == NULL)) { ++ AP6210_DEBUG("Error: %s():%d\n", __FUNCTION__, __LINE__); ++ return BCME_BADARG; ++ } ++ ++ memset(&commit_info, 0, sizeof(commit_info)); ++ ++ /* ++ Commit packets for regular AC traffic. Higher priority first. ++ First, use up FIFO credits available to each AC. Based on distribution ++ and credits left, borrow from other ACs as applicable ++ ++ -NOTE: ++ If the bus between the host and firmware is overwhelmed by the ++ traffic from host, it is possible that higher priority traffic ++ starves the lower priority queue. If that occurs often, we may ++ have to employ weighted round-robin or ucode scheme to avoid ++ low priority packet starvation. ++ */ ++ ++ if (pktbuf) { ++ ac = DHD_PKTTAG_FIFO(PKTTAG(pktbuf)); ++ if (ETHER_ISMULTI(DHD_PKTTAG_DSTN(PKTTAG(pktbuf)))) { ++ ASSERT(ac == AC_COUNT); ++ commit_info.needs_hdr = 1; ++ commit_info.mac_entry = NULL; ++ commit_info.pkt_type = eWLFC_PKTTYPE_NEW; ++ commit_info.p = pktbuf; ++ if (ctx->FIFO_credit[ac]) { ++ rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info, ++ fcommit, commit_ctx); ++ ++ /* Bus commits may fail (e.g. flow control); abort after retries */ ++ if (rc == BCME_OK) { ++ if (commit_info.ac_fifo_credit_spent) { ++ (void) _dhd_wlfc_borrow_credit(ctx, ++ ac_available, ac); ++ credit_count--; ++ } ++ } else { ++ bus_retry_count++; ++ if (bus_retry_count >= BUS_RETRIES) { ++ AP6210_ERR(" %s: bus error %d\n", ++ __FUNCTION__, rc); ++ return rc; ++ } ++ } ++ } ++ } ++ else { ++ /* en-queue the packets to respective queue. */ ++ rc = _dhd_wlfc_enque_delayq(ctx, pktbuf, ac); ++ } ++ } ++ ++ for (ac = AC_COUNT; ac >= 0; ac--) { ++ ++ bool bQueueIdle = TRUE; ++ ++ /* packets from delayQ with less priority are fresh and they'd need header and ++ * have no MAC entry ++ */ ++ commit_info.needs_hdr = 1; ++ commit_info.mac_entry = NULL; ++ commit_info.pkt_type = eWLFC_PKTTYPE_NEW; ++ ++ for (credit = 0; credit < ctx->FIFO_credit[ac];) { ++ commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac, ++ &(commit_info.ac_fifo_credit_spent), ++ &(commit_info.needs_hdr), ++ &(commit_info.mac_entry)); ++ ++ if (commit_info.p == NULL) ++ break; ++ ++ bQueueIdle = FALSE; ++ ++ commit_info.pkt_type = (commit_info.needs_hdr) ? eWLFC_PKTTYPE_DELAYED : ++ eWLFC_PKTTYPE_SUPPRESSED; ++ ++ rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info, ++ fcommit, commit_ctx); ++ ++ /* Bus commits may fail (e.g. flow control); abort after retries */ ++ if (rc == BCME_OK) { ++ if (commit_info.ac_fifo_credit_spent) { ++ credit++; ++ } ++ } ++ else { ++ bus_retry_count++; ++ if (bus_retry_count >= BUS_RETRIES) { ++ AP6210_ERR("%s: bus error %d\n", __FUNCTION__, rc); ++ ctx->FIFO_credit[ac] -= credit; ++ return rc; ++ } ++ } ++ } ++ ++ ctx->FIFO_credit[ac] -= credit; ++ ++ ++ /* If no pkts can be dequed, the credit can be borrowed */ ++ if (bQueueIdle) { ++ ac_available |= (1 << ac); ++ credit_count += ctx->FIFO_credit[ac]; ++ } ++ } ++ ++ /* We borrow only for AC_BE and only if no other traffic seen for DEFER_PERIOD ++ ++ Note that (ac_available & WLFC_AC_BE_TRAFFIC_ONLY) is done to: ++ a) ignore BC/MC for deferring borrow ++ b) ignore AC_BE being available along with other ACs ++ (this should happen only for pure BC/MC traffic) ++ ++ i.e. AC_VI, AC_VO, AC_BK all MUST be available (i.e. no traffic) and ++ we do not care if AC_BE and BC/MC are available or not ++ */ ++ if ((ac_available & WLFC_AC_BE_TRAFFIC_ONLY) == WLFC_AC_BE_TRAFFIC_ONLY) { ++ ++ if (ctx->allow_credit_borrow) { ++ ac = 1; /* Set ac to AC_BE and borrow credits */ ++ } ++ else { ++ int delta; ++ int curr_t = OSL_SYSUPTIME(); ++ ++ if (curr_t > ctx->borrow_defer_timestamp) ++ delta = curr_t - ctx->borrow_defer_timestamp; ++ else ++ delta = 0xffffffff + curr_t - ctx->borrow_defer_timestamp; ++ ++ if (delta >= WLFC_BORROW_DEFER_PERIOD_MS) { ++ /* Reset borrow but defer to next iteration (defensive borrowing) */ ++ ctx->allow_credit_borrow = TRUE; ++ ctx->borrow_defer_timestamp = 0; ++ } ++ return BCME_OK; ++ } ++ } ++ else { ++ /* If we have multiple AC traffic, turn off borrowing, mark time and bail out */ ++ ctx->allow_credit_borrow = FALSE; ++ ctx->borrow_defer_timestamp = OSL_SYSUPTIME(); ++ return BCME_OK; ++ } ++ ++ /* At this point, borrow all credits only for "ac" (which should be set above to AC_BE) ++ Generically use "ac" only in case we extend to all ACs in future ++ */ ++ for (; (credit_count > 0);) { ++ ++ commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac, ++ &(commit_info.ac_fifo_credit_spent), ++ &(commit_info.needs_hdr), ++ &(commit_info.mac_entry)); ++ if (commit_info.p == NULL) ++ break; ++ ++ commit_info.pkt_type = (commit_info.needs_hdr) ? eWLFC_PKTTYPE_DELAYED : ++ eWLFC_PKTTYPE_SUPPRESSED; ++ ++ rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info, ++ fcommit, commit_ctx); ++ ++ /* Bus commits may fail (e.g. flow control); abort after retries */ ++ if (rc == BCME_OK) { ++ if (commit_info.ac_fifo_credit_spent) { ++ (void) _dhd_wlfc_borrow_credit(ctx, ac_available, ac); ++ credit_count--; ++ } ++ } ++ else { ++ bus_retry_count++; ++ if (bus_retry_count >= BUS_RETRIES) { ++ AP6210_ERR("%s: bus error %d\n", __FUNCTION__, rc); ++ return rc; ++ } ++ } ++ } ++ return BCME_OK; ++} ++ ++static uint8 ++dhd_wlfc_find_mac_desc_id_from_mac(dhd_pub_t *dhdp, uint8* ea) ++{ ++ wlfc_mac_descriptor_t* table = ++ ((athost_wl_status_info_t*)dhdp->wlfc_state)->destination_entries.nodes; ++ uint8 table_index; ++ ++ if (ea != NULL) { ++ for (table_index = 0; table_index < WLFC_MAC_DESC_TABLE_SIZE; table_index++) { ++ if ((memcmp(ea, &table[table_index].ea[0], ETHER_ADDR_LEN) == 0) && ++ table[table_index].occupied) ++ return table_index; ++ } ++ } ++ return WLFC_MAC_DESC_ID_INVALID; ++} ++ ++void ++dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success) ++{ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ void* p; ++ int fifo_id; ++ ++ if (DHD_PKTTAG_SIGNALONLY(PKTTAG(txp))) { ++#ifdef PROP_TXSTATUS_DEBUG ++ wlfc->stats.signal_only_pkts_freed++; ++#endif ++ /* is this a signal-only packet? */ ++ if (success) ++ PKTFREE(wlfc->osh, txp, TRUE); ++ return; ++ } ++ if (!success) { ++ AP6210_DEBUG("At: %s():%d, bus_complete() failure for %p, htod_tag:0x%08x\n", ++ __FUNCTION__, __LINE__, txp, DHD_PKTTAG_H2DTAG(PKTTAG(txp))); ++ dhd_wlfc_hanger_poppkt(wlfc->hanger, WLFC_PKTID_HSLOT_GET(DHD_PKTTAG_H2DTAG ++ (PKTTAG(txp))), &p, 1); ++ ++ /* indicate failure and free the packet */ ++ dhd_txcomplete(dhd, txp, FALSE); ++ ++ /* return the credit, if necessary */ ++ if (DHD_PKTTAG_CREDITCHECK(PKTTAG(txp))) { ++ int lender, credit_returned = 0; /* Note that borrower is fifo_id */ ++ ++ fifo_id = DHD_PKTTAG_FIFO(PKTTAG(txp)); ++ ++ /* Return credits to highest priority lender first */ ++ for (lender = AC_COUNT; lender >= 0; lender--) { ++ if (wlfc->credits_borrowed[fifo_id][lender] > 0) { ++ wlfc->FIFO_credit[lender]++; ++ wlfc->credits_borrowed[fifo_id][lender]--; ++ credit_returned = 1; ++ break; ++ } ++ } ++ ++ if (!credit_returned) { ++ wlfc->FIFO_credit[fifo_id]++; ++ } ++ } ++ ++ PKTFREE(wlfc->osh, txp, TRUE); ++ } ++ return; ++} ++ ++static int ++dhd_wlfc_compressed_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info, uint8 len) ++{ ++ uint8 status_flag; ++ uint32 status; ++ int ret; ++ int remove_from_hanger = 1; ++ void* pktbuf; ++ uint8 fifo_id; ++ uint8 count = 0; ++ uint32 status_g; ++ uint32 hslot, hcnt; ++ wlfc_mac_descriptor_t* entry = NULL; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ ++ memcpy(&status, pkt_info, sizeof(uint32)); ++ status_flag = WL_TXSTATUS_GET_FLAGS(status); ++ status_g = status & 0xff000000; ++ hslot = (status & 0x00ffff00) >> 8; ++ hcnt = status & 0xff; ++ len = pkt_info[4]; ++ ++ wlfc->stats.txstatus_in++; ++ ++ if (status_flag == WLFC_CTL_PKTFLAG_DISCARD) { ++ wlfc->stats.pkt_freed++; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) { ++ wlfc->stats.d11_suppress++; ++ remove_from_hanger = 0; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS) { ++ wlfc->stats.wl_suppress++; ++ remove_from_hanger = 0; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_TOSSED_BYWLC) { ++ wlfc->stats.wlc_tossed_pkts++; ++ } ++ while (count < len) { ++ status = (status_g << 24) | (hslot << 8) | (hcnt); ++ count++; ++ hslot++; ++ hcnt++; ++ ++ ret = dhd_wlfc_hanger_poppkt(wlfc->hanger, ++ WLFC_PKTID_HSLOT_GET(status), &pktbuf, remove_from_hanger); ++ if (ret != BCME_OK) { ++ /* do something */ ++ continue; ++ } ++ ++ entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); ++ ++ if (!remove_from_hanger) { ++ /* this packet was suppressed */ ++ if (!entry->suppressed || entry->generation != WLFC_PKTID_GEN(status)) { ++ entry->suppressed = TRUE; ++ entry->suppress_count = pktq_mlen(&entry->psq, ++ NBITVAL((WL_TXSTATUS_GET_FIFO(status) << 1) + 1)); ++ entry->suppr_transit_count = entry->transit_count; ++ } ++ entry->generation = WLFC_PKTID_GEN(status); ++ } ++ ++#ifdef PROP_TXSTATUS_DEBUG ++ { ++ uint32 new_t = OSL_SYSUPTIME(); ++ uint32 old_t; ++ uint32 delta; ++ old_t = ((wlfc_hanger_t*)(wlfc->hanger))->items[ ++ WLFC_PKTID_HSLOT_GET(status)].push_time; ++ ++ ++ wlfc->stats.latency_sample_count++; ++ if (new_t > old_t) ++ delta = new_t - old_t; ++ else ++ delta = 0xffffffff + new_t - old_t; ++ wlfc->stats.total_status_latency += delta; ++ wlfc->stats.latency_most_recent = delta; ++ ++ wlfc->stats.deltas[wlfc->stats.idx_delta++] = delta; ++ if (wlfc->stats.idx_delta == sizeof(wlfc->stats.deltas)/sizeof(uint32)) ++ wlfc->stats.idx_delta = 0; ++ } ++#endif /* PROP_TXSTATUS_DEBUG */ ++ ++ fifo_id = DHD_PKTTAG_FIFO(PKTTAG(pktbuf)); ++ ++ /* pick up the implicit credit from this packet */ ++ if (DHD_PKTTAG_CREDITCHECK(PKTTAG(pktbuf))) { ++ if (wlfc->proptxstatus_mode == WLFC_FCMODE_IMPLIED_CREDIT) { ++ ++ int lender, credit_returned = 0; /* Note that borrower is fifo_id */ ++ ++ /* Return credits to highest priority lender first */ ++ for (lender = AC_COUNT; lender >= 0; lender--) { ++ if (wlfc->credits_borrowed[fifo_id][lender] > 0) { ++ wlfc->FIFO_credit[lender]++; ++ wlfc->credits_borrowed[fifo_id][lender]--; ++ credit_returned = 1; ++ break; ++ } ++ } ++ ++ if (!credit_returned) { ++ wlfc->FIFO_credit[fifo_id]++; ++ } ++ } ++ } ++ else { ++ /* ++ if this packet did not count against FIFO credit, it must have ++ taken a requested_credit from the destination entry (for pspoll etc.) ++ */ ++ if (!entry) { ++ ++ entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); ++ } ++ if (!DHD_PKTTAG_ONETIMEPKTRQST(PKTTAG(pktbuf))) ++ entry->requested_credit++; ++#ifdef PROP_TXSTATUS_DEBUG ++ entry->dstncredit_acks++; ++#endif ++ } ++ if ((status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) || ++ (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS)) { ++ ++ ret = _dhd_wlfc_enque_suppressed(wlfc, fifo_id, pktbuf); ++ if (ret != BCME_OK) { ++ /* delay q is full, drop this packet */ ++ dhd_wlfc_hanger_poppkt(wlfc->hanger, WLFC_PKTID_HSLOT_GET(status), ++ &pktbuf, 1); ++ ++ /* indicate failure and free the packet */ ++ dhd_txcomplete(dhd, pktbuf, FALSE); ++ entry->transit_count--; ++ DHD_WLFC_QMON_COMPLETE(entry); ++ /* packet is transmitted Successfully by dongle ++ * after first suppress. ++ */ ++ if (entry->suppressed) { ++ entry->suppr_transit_count--; ++ } ++ PKTFREE(wlfc->osh, pktbuf, TRUE); ++ } else { ++ /* Mark suppressed to avoid a double free during wlfc cleanup */ ++ ++ dhd_wlfc_hanger_mark_suppressed(wlfc->hanger, ++ WLFC_PKTID_HSLOT_GET(status), WLFC_PKTID_GEN(status)); ++ entry->suppress_count++; ++ } ++ } ++ else { ++ dhd_txcomplete(dhd, pktbuf, TRUE); ++ entry->transit_count--; ++ DHD_WLFC_QMON_COMPLETE(entry); ++ ++ /* This packet is transmitted Successfully by dongle ++ * even after first suppress. ++ */ ++ if (entry->suppressed) { ++ entry->suppr_transit_count--; ++ } ++ /* free the packet */ ++ PKTFREE(wlfc->osh, pktbuf, TRUE); ++ } ++ } ++ return BCME_OK; ++} ++ ++/* Handle discard or suppress indication */ ++static int ++dhd_wlfc_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info) ++{ ++ uint8 status_flag; ++ uint32 status; ++ int ret; ++ int remove_from_hanger = 1; ++ void* pktbuf; ++ uint8 fifo_id; ++ wlfc_mac_descriptor_t* entry = NULL; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ ++ memcpy(&status, pkt_info, sizeof(uint32)); ++ status_flag = WL_TXSTATUS_GET_FLAGS(status); ++ wlfc->stats.txstatus_in++; ++ ++ if (status_flag == WLFC_CTL_PKTFLAG_DISCARD) { ++ wlfc->stats.pkt_freed++; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) { ++ wlfc->stats.d11_suppress++; ++ remove_from_hanger = 0; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS) { ++ wlfc->stats.wl_suppress++; ++ remove_from_hanger = 0; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_TOSSED_BYWLC) { ++ wlfc->stats.wlc_tossed_pkts++; ++ } ++ ++ ret = dhd_wlfc_hanger_poppkt(wlfc->hanger, ++ WLFC_PKTID_HSLOT_GET(status), &pktbuf, remove_from_hanger); ++ if (ret != BCME_OK) { ++ /* do something */ ++ return ret; ++ } ++ ++ entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); ++ ++ if (!remove_from_hanger) { ++ /* this packet was suppressed */ ++ if (!entry->suppressed || entry->generation != WLFC_PKTID_GEN(status)) { ++ entry->suppressed = TRUE; ++ entry->suppress_count = pktq_mlen(&entry->psq, ++ NBITVAL((WL_TXSTATUS_GET_FIFO(status) << 1) + 1)); ++ entry->suppr_transit_count = entry->transit_count; ++ } ++ entry->generation = WLFC_PKTID_GEN(status); ++ } ++ ++#ifdef PROP_TXSTATUS_DEBUG ++ { ++ uint32 new_t = OSL_SYSUPTIME(); ++ uint32 old_t; ++ uint32 delta; ++ old_t = ((wlfc_hanger_t*)(wlfc->hanger))->items[ ++ WLFC_PKTID_HSLOT_GET(status)].push_time; ++ ++ ++ wlfc->stats.latency_sample_count++; ++ if (new_t > old_t) ++ delta = new_t - old_t; ++ else ++ delta = 0xffffffff + new_t - old_t; ++ wlfc->stats.total_status_latency += delta; ++ wlfc->stats.latency_most_recent = delta; ++ ++ wlfc->stats.deltas[wlfc->stats.idx_delta++] = delta; ++ if (wlfc->stats.idx_delta == sizeof(wlfc->stats.deltas)/sizeof(uint32)) ++ wlfc->stats.idx_delta = 0; ++ } ++#endif /* PROP_TXSTATUS_DEBUG */ ++ ++ fifo_id = DHD_PKTTAG_FIFO(PKTTAG(pktbuf)); ++ ++ /* pick up the implicit credit from this packet */ ++ if (DHD_PKTTAG_CREDITCHECK(PKTTAG(pktbuf))) { ++ if (wlfc->proptxstatus_mode == WLFC_FCMODE_IMPLIED_CREDIT) { ++ ++ int lender, credit_returned = 0; /* Note that borrower is fifo_id */ ++ ++ /* Return credits to highest priority lender first */ ++ for (lender = AC_COUNT; lender >= 0; lender--) { ++ if (wlfc->credits_borrowed[fifo_id][lender] > 0) { ++ wlfc->FIFO_credit[lender]++; ++ wlfc->credits_borrowed[fifo_id][lender]--; ++ credit_returned = 1; ++ break; ++ } ++ } ++ ++ if (!credit_returned) { ++ wlfc->FIFO_credit[fifo_id]++; ++ } ++ } ++ } ++ else { ++ /* ++ if this packet did not count against FIFO credit, it must have ++ taken a requested_credit from the destination entry (for pspoll etc.) ++ */ ++ if (!entry) { ++ ++ entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); ++ } ++ if (!DHD_PKTTAG_ONETIMEPKTRQST(PKTTAG(pktbuf))) ++ entry->requested_credit++; ++#ifdef PROP_TXSTATUS_DEBUG ++ entry->dstncredit_acks++; ++#endif ++ } ++ if ((status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) || ++ (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS)) { ++ ++ ret = _dhd_wlfc_enque_suppressed(wlfc, fifo_id, pktbuf); ++ if (ret != BCME_OK) { ++ /* delay q is full, drop this packet */ ++ dhd_wlfc_hanger_poppkt(wlfc->hanger, WLFC_PKTID_HSLOT_GET(status), ++ &pktbuf, 1); ++ ++ /* indicate failure and free the packet */ ++ dhd_txcomplete(dhd, pktbuf, FALSE); ++ entry->transit_count--; ++ DHD_WLFC_QMON_COMPLETE(entry); ++ /* This packet is transmitted Successfully by ++ * dongle even after first suppress. ++ */ ++ if (entry->suppressed) { ++ entry->suppr_transit_count--; ++ } ++ PKTFREE(wlfc->osh, pktbuf, TRUE); ++ } else { ++ /* Mark suppressed to avoid a double free during wlfc cleanup */ ++ ++ dhd_wlfc_hanger_mark_suppressed(wlfc->hanger, ++ WLFC_PKTID_HSLOT_GET(status), WLFC_PKTID_GEN(status)); ++ entry->suppress_count++; ++ } ++ } ++ else { ++ dhd_txcomplete(dhd, pktbuf, TRUE); ++ entry->transit_count--; ++ DHD_WLFC_QMON_COMPLETE(entry); ++ ++ /* This packet is transmitted Successfully by dongle even after first suppress. */ ++ if (entry->suppressed) { ++ entry->suppr_transit_count--; ++ } ++ /* free the packet */ ++ PKTFREE(wlfc->osh, pktbuf, TRUE); ++ } ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_fifocreditback_indicate(dhd_pub_t *dhd, uint8* credits) ++{ ++ int i; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ for (i = 0; i < WLFC_CTL_VALUE_LEN_FIFO_CREDITBACK; i++) { ++#ifdef PROP_TXSTATUS_DEBUG ++ wlfc->stats.fifo_credits_back[i] += credits[i]; ++#endif ++ /* update FIFO credits */ ++ if (wlfc->proptxstatus_mode == WLFC_FCMODE_EXPLICIT_CREDIT) ++ { ++ int lender; /* Note that borrower is i */ ++ ++ /* Return credits to highest priority lender first */ ++ for (lender = AC_COUNT; (lender >= 0) && (credits[i] > 0); lender--) { ++ if (wlfc->credits_borrowed[i][lender] > 0) { ++ if (credits[i] >= wlfc->credits_borrowed[i][lender]) { ++ credits[i] -= wlfc->credits_borrowed[i][lender]; ++ wlfc->FIFO_credit[lender] += ++ wlfc->credits_borrowed[i][lender]; ++ wlfc->credits_borrowed[i][lender] = 0; ++ } ++ else { ++ wlfc->credits_borrowed[i][lender] -= credits[i]; ++ wlfc->FIFO_credit[lender] += credits[i]; ++ credits[i] = 0; ++ } ++ } ++ } ++ ++ /* If we have more credits left over, these must belong to the AC */ ++ if (credits[i] > 0) { ++ wlfc->FIFO_credit[i] += credits[i]; ++ } ++ } ++ } ++ ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_dbg_senum_check(dhd_pub_t *dhd, uint8 *value) ++{ ++ uint32 timestamp; ++ ++ (void)dhd; ++ ++ bcopy(&value[2], ×tamp, sizeof(uint32)); ++ AP6210_DEBUG("RXPKT: SEQ: %d, timestamp %d\n", value[1], timestamp); ++ return BCME_OK; ++} ++ ++ ++static int ++dhd_wlfc_rssi_indicate(dhd_pub_t *dhd, uint8* rssi) ++{ ++ (void)dhd; ++ (void)rssi; ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_mac_table_update(dhd_pub_t *dhd, uint8* value, uint8 type) ++{ ++ int rc; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ uint8 existing_index; ++ uint8 table_index; ++ uint8 ifid; ++ uint8* ea; ++ ++ AP6210_DEBUG("%s(), mac [%02x:%02x:%02x:%02x:%02x:%02x],%s,idx:%d,id:0x%02x\n", ++ __FUNCTION__, value[2], value[3], value[4], value[5], value[6], value[7], ++ ((type == WLFC_CTL_TYPE_MACDESC_ADD) ? "ADD":"DEL"), ++ WLFC_MAC_DESC_GET_LOOKUP_INDEX(value[0]), value[0]); ++ ++ table = wlfc->destination_entries.nodes; ++ table_index = WLFC_MAC_DESC_GET_LOOKUP_INDEX(value[0]); ++ ifid = value[1]; ++ ea = &value[2]; ++ ++ if (type == WLFC_CTL_TYPE_MACDESC_ADD) { ++ existing_index = dhd_wlfc_find_mac_desc_id_from_mac(dhd, &value[2]); ++ if (existing_index == WLFC_MAC_DESC_ID_INVALID) { ++ /* this MAC entry does not exist, create one */ ++ if (!table[table_index].occupied) { ++ table[table_index].mac_handle = value[0]; ++ rc = _dhd_wlfc_mac_entry_update(wlfc, &table[table_index], ++ eWLFC_MAC_ENTRY_ACTION_ADD, ifid, ++ wlfc->destination_entries.interfaces[ifid].iftype, ++ ea); ++ } ++ else { ++ /* the space should have been empty, but it's not */ ++ wlfc->stats.mac_update_failed++; ++ } ++ } ++ else { ++ /* ++ there is an existing entry, move it to new index ++ if necessary. ++ */ ++ if (existing_index != table_index) { ++ /* if we already have an entry, free the old one */ ++ table[existing_index].occupied = 0; ++ table[existing_index].state = WLFC_STATE_CLOSE; ++ table[existing_index].requested_credit = 0; ++ table[existing_index].interface_id = 0; ++ /* enable after packets are queued-deqeued properly. ++ pktq_flush(dhd->osh, &table[existing_index].psq, FALSE, NULL, 0); ++ */ ++ } ++ } ++ } ++ if (type == WLFC_CTL_TYPE_MACDESC_DEL) { ++ if (table[table_index].occupied) { ++ rc = _dhd_wlfc_mac_entry_update(wlfc, &table[table_index], ++ eWLFC_MAC_ENTRY_ACTION_DEL, ifid, ++ wlfc->destination_entries.interfaces[ifid].iftype, ++ ea); ++ } ++ else { ++ /* the space should have been occupied, but it's not */ ++ wlfc->stats.mac_update_failed++; ++ } ++ } ++ BCM_REFERENCE(rc); ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_psmode_update(dhd_pub_t *dhd, uint8* value, uint8 type) ++{ ++ /* Handle PS on/off indication */ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ wlfc_mac_descriptor_t* desc; ++ uint8 mac_handle = value[0]; ++ int i; ++ ++ table = wlfc->destination_entries.nodes; ++ desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)]; ++ if (desc->occupied) { ++ /* a fresh PS mode should wipe old ps credits? */ ++ desc->requested_credit = 0; ++ if (type == WLFC_CTL_TYPE_MAC_OPEN) { ++ desc->state = WLFC_STATE_OPEN; ++ DHD_WLFC_CTRINC_MAC_OPEN(desc); ++ } ++ else { ++ desc->state = WLFC_STATE_CLOSE; ++ DHD_WLFC_CTRINC_MAC_CLOSE(desc); ++ /* ++ Indicate to firmware if there is any traffic pending. ++ */ ++ for (i = AC_BE; i < AC_COUNT; i++) { ++ _dhd_wlfc_traffic_pending_check(wlfc, desc, i); ++ } ++ } ++ } ++ else { ++ wlfc->stats.psmode_update_failed++; ++ } ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_interface_update(dhd_pub_t *dhd, uint8* value, uint8 type) ++{ ++ /* Handle PS on/off indication */ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ uint8 if_id = value[0]; ++ ++ if (if_id < WLFC_MAX_IFNUM) { ++ table = wlfc->destination_entries.interfaces; ++ if (table[if_id].occupied) { ++ if (type == WLFC_CTL_TYPE_INTERFACE_OPEN) { ++ table[if_id].state = WLFC_STATE_OPEN; ++ /* AP6210_DEBUG("INTERFACE[%d] OPEN\n", if_id); */ ++ } ++ else { ++ table[if_id].state = WLFC_STATE_CLOSE; ++ /* AP6210_DEBUG("INTERFACE[%d] CLOSE\n", if_id); */ ++ } ++ return BCME_OK; ++ } ++ } ++ wlfc->stats.interface_update_failed++; ++ ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_credit_request(dhd_pub_t *dhd, uint8* value) ++{ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ wlfc_mac_descriptor_t* desc; ++ uint8 mac_handle; ++ uint8 credit; ++ ++ table = wlfc->destination_entries.nodes; ++ mac_handle = value[1]; ++ credit = value[0]; ++ ++ desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)]; ++ if (desc->occupied) { ++ desc->requested_credit = credit; ++ ++ desc->ac_bitmap = value[2]; ++ } ++ else { ++ wlfc->stats.credit_request_failed++; ++ } ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_packet_request(dhd_pub_t *dhd, uint8* value) ++{ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ wlfc_mac_descriptor_t* desc; ++ uint8 mac_handle; ++ uint8 packet_count; ++ ++ table = wlfc->destination_entries.nodes; ++ mac_handle = value[1]; ++ packet_count = value[0]; ++ ++ desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)]; ++ if (desc->occupied) { ++ desc->requested_packet = packet_count; ++ ++ desc->ac_bitmap = value[2]; ++ } ++ else { ++ wlfc->stats.packet_request_failed++; ++ } ++ return BCME_OK; ++} ++ ++static void ++dhd_wlfc_reorderinfo_indicate(uint8 *val, uint8 len, uchar *info_buf, uint *info_len) ++{ ++ if (info_len) { ++ if (info_buf) { ++ bcopy(val, info_buf, len); ++ *info_len = len; ++ } ++ else ++ *info_len = 0; ++ } ++} ++ ++int ++dhd_wlfc_parse_header_info(dhd_pub_t *dhd, void* pktbuf, int tlv_hdr_len, uchar *reorder_info_buf, ++ uint *reorder_info_len) ++{ ++ uint8 type, len; ++ uint8* value; ++ uint8* tmpbuf; ++ uint16 remainder = tlv_hdr_len; ++ uint16 processed = 0; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ tmpbuf = (uint8*)PKTDATA(dhd->osh, pktbuf); ++ if (remainder) { ++ while ((processed < (WLFC_MAX_PENDING_DATALEN * 2)) && (remainder > 0)) { ++ type = tmpbuf[processed]; ++ if (type == WLFC_CTL_TYPE_FILLER) { ++ remainder -= 1; ++ processed += 1; ++ continue; ++ } ++ ++ len = tmpbuf[processed + 1]; ++ value = &tmpbuf[processed + 2]; ++ ++ if (remainder < (2 + len)) ++ break; ++ ++ remainder -= 2 + len; ++ processed += 2 + len; ++ if (type == WLFC_CTL_TYPE_TXSTATUS) ++ dhd_wlfc_txstatus_update(dhd, value); ++ if (type == WLFC_CTL_TYPE_COMP_TXSTATUS) ++ dhd_wlfc_compressed_txstatus_update(dhd, value, len); ++ ++ else if (type == WLFC_CTL_TYPE_HOST_REORDER_RXPKTS) ++ dhd_wlfc_reorderinfo_indicate(value, len, reorder_info_buf, ++ reorder_info_len); ++ else if (type == WLFC_CTL_TYPE_FIFO_CREDITBACK) ++ dhd_wlfc_fifocreditback_indicate(dhd, value); ++ ++ else if (type == WLFC_CTL_TYPE_RSSI) ++ dhd_wlfc_rssi_indicate(dhd, value); ++ ++ else if (type == WLFC_CTL_TYPE_MAC_REQUEST_CREDIT) ++ dhd_wlfc_credit_request(dhd, value); ++ ++ else if (type == WLFC_CTL_TYPE_MAC_REQUEST_PACKET) ++ dhd_wlfc_packet_request(dhd, value); ++ ++ else if ((type == WLFC_CTL_TYPE_MAC_OPEN) || ++ (type == WLFC_CTL_TYPE_MAC_CLOSE)) ++ dhd_wlfc_psmode_update(dhd, value, type); ++ ++ else if ((type == WLFC_CTL_TYPE_MACDESC_ADD) || ++ (type == WLFC_CTL_TYPE_MACDESC_DEL)) ++ dhd_wlfc_mac_table_update(dhd, value, type); ++ ++ else if (type == WLFC_CTL_TYPE_TRANS_ID) ++ dhd_wlfc_dbg_senum_check(dhd, value); ++ ++ else if ((type == WLFC_CTL_TYPE_INTERFACE_OPEN) || ++ (type == WLFC_CTL_TYPE_INTERFACE_CLOSE)) { ++ dhd_wlfc_interface_update(dhd, value, type); ++ } ++ } ++ if (remainder != 0) { ++ /* trouble..., something is not right */ ++ wlfc->stats.tlv_parse_failed++; ++ } ++ } ++ return BCME_OK; ++} ++ ++int ++dhd_wlfc_init(dhd_pub_t *dhd) ++{ ++ char iovbuf[12]; /* Room for "tlv" + '\0' + parameter */ ++ /* enable all signals & indicate host proptxstatus logic is active */ ++ uint32 tlv = dhd->wlfc_enabled? ++ WLFC_FLAGS_RSSI_SIGNALS | ++ WLFC_FLAGS_XONXOFF_SIGNALS | ++ WLFC_FLAGS_CREDIT_STATUS_SIGNALS | ++ WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE | ++ WLFC_FLAGS_HOST_RXRERODER_ACTIVE : 0; ++ /* WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE | WLFC_FLAGS_HOST_RXRERODER_ACTIVE : 0; */ ++ ++ ++ /* ++ try to enable/disable signaling by sending "tlv" iovar. if that fails, ++ fallback to no flow control? Print a message for now. ++ */ ++ ++ /* enable proptxtstatus signaling by default */ ++ bcm_mkiovar("tlv", (char *)&tlv, 4, iovbuf, sizeof(iovbuf)); ++ if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) < 0) { ++ AP6210_ERR("dhd_wlfc_init(): failed to enable/disable bdcv2 tlv signaling\n"); ++ } ++ else { ++ /* ++ Leaving the message for now, it should be removed after a while; once ++ the tlv situation is stable. ++ */ ++ AP6210_ERR("dhd_wlfc_init(): successfully %s bdcv2 tlv signaling, %d\n", ++ dhd->wlfc_enabled?"enabled":"disabled", tlv); ++ } ++ return BCME_OK; ++} ++ ++int ++dhd_wlfc_enable(dhd_pub_t *dhd) ++{ ++ int i; ++ athost_wl_status_info_t* wlfc; ++ ++ if (!dhd->wlfc_enabled || dhd->wlfc_state) ++ return BCME_OK; ++ ++ /* allocate space to track txstatus propagated from firmware */ ++ dhd->wlfc_state = MALLOC(dhd->osh, sizeof(athost_wl_status_info_t)); ++ if (dhd->wlfc_state == NULL) ++ return BCME_NOMEM; ++ ++ /* initialize state space */ ++ wlfc = (athost_wl_status_info_t*)dhd->wlfc_state; ++ memset(wlfc, 0, sizeof(athost_wl_status_info_t)); ++ ++ /* remember osh & dhdp */ ++ wlfc->osh = dhd->osh; ++ wlfc->dhdp = dhd; ++ ++ wlfc->hanger = ++ dhd_wlfc_hanger_create(dhd->osh, WLFC_HANGER_MAXITEMS); ++ if (wlfc->hanger == NULL) { ++ MFREE(dhd->osh, dhd->wlfc_state, sizeof(athost_wl_status_info_t)); ++ dhd->wlfc_state = NULL; ++ AP6210_ERR("Failed to malloc dhd->wlfc_state\n"); ++ return BCME_NOMEM; ++ } ++ ++ /* initialize all interfaces to accept traffic */ ++ for (i = 0; i < WLFC_MAX_IFNUM; i++) { ++ wlfc->hostif_flow_state[i] = OFF; ++ } ++ ++ wlfc->destination_entries.other.state = WLFC_STATE_OPEN; ++ /* bc/mc FIFO is always open [credit aside], i.e. b[5] */ ++ wlfc->destination_entries.other.ac_bitmap = 0x1f; ++ wlfc->destination_entries.other.interface_id = 0; ++ ++ wlfc->proptxstatus_mode = WLFC_FCMODE_EXPLICIT_CREDIT; ++ ++ wlfc->allow_credit_borrow = TRUE; ++ wlfc->borrow_defer_timestamp = 0; ++ ++ return BCME_OK; ++} ++ ++/* release all packet resources */ ++void ++dhd_wlfc_cleanup(dhd_pub_t *dhd, ifpkt_cb_t fn, int arg) ++{ ++ int i; ++ int total_entries; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ wlfc_hanger_t* h; ++ int prec; ++ void *pkt = NULL; ++ struct pktq *txq = NULL; ++ if (dhd->wlfc_state == NULL) ++ return; ++ /* flush bus->txq */ ++ txq = dhd_bus_txq(dhd->bus); ++ /* any in the hanger? */ ++ h = (wlfc_hanger_t*)wlfc->hanger; ++ total_entries = sizeof(wlfc->destination_entries)/sizeof(wlfc_mac_descriptor_t); ++ /* search all entries, include nodes as well as interfaces */ ++ table = (wlfc_mac_descriptor_t*)&wlfc->destination_entries; ++ ++ for (i = 0; i < total_entries; i++) { ++ if (table[i].occupied && (fn == NULL || (arg == table[i].interface_id))) { ++ if (table[i].psq.len) { ++ AP6210_DEBUG("%s(): DELAYQ[%d].len = %d\n", ++ __FUNCTION__, i, table[i].psq.len); ++ /* release packets held in DELAYQ */ ++ pktq_flush(wlfc->osh, &table[i].psq, TRUE, fn, arg); ++ } ++ if (fn == NULL) ++ table[i].occupied = 0; ++ } ++ } ++ for (prec = 0; prec < txq->num_prec; prec++) { ++ pkt = pktq_pdeq_with_fn(txq, prec, fn, arg); ++ while (pkt) { ++ for (i = 0; i < h->max_items; i++) { ++ if (pkt == h->items[i].pkt) { ++ if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { ++ PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); ++ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; ++ } else if (h->items[i].state == ++ WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { ++ /* These are already freed from the psq */ ++ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; ++ } ++ break; ++ } ++ } ++ pkt = pktq_pdeq(txq, prec); ++ } ++ } ++ /* flush remained pkt in hanger queue, not in bus->txq */ ++ for (i = 0; i < h->max_items; i++) { ++ if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { ++ if (fn == NULL || (*fn)(h->items[i].pkt, arg)) { ++ PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); ++ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; ++ } ++ } else if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { ++ if (fn == NULL || (*fn)(h->items[i].pkt, arg)) { ++ /* These are freed from the psq so no need to free again */ ++ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; ++ } ++ } ++ } ++ return; ++} ++ ++void ++dhd_wlfc_deinit(dhd_pub_t *dhd) ++{ ++ /* cleanup all psq related resources */ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ ++ dhd_os_wlfc_block(dhd); ++ if (dhd->wlfc_state == NULL) { ++ dhd_os_wlfc_unblock(dhd); ++ return; ++ } ++ ++#ifdef PROP_TXSTATUS_DEBUG ++ { ++ int i; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)wlfc->hanger; ++ for (i = 0; i < h->max_items; i++) { ++ if (h->items[i].state != WLFC_HANGER_ITEM_STATE_FREE) { ++ AP6210_DEBUG("%s() pkt[%d] = 0x%p, FIFO_credit_used:%d\n", ++ __FUNCTION__, i, h->items[i].pkt, ++ DHD_PKTTAG_CREDITCHECK(PKTTAG(h->items[i].pkt))); ++ } ++ } ++ } ++#endif ++ /* delete hanger */ ++ dhd_wlfc_hanger_delete(dhd->osh, wlfc->hanger); ++ ++ /* free top structure */ ++ MFREE(dhd->osh, dhd->wlfc_state, sizeof(athost_wl_status_info_t)); ++ dhd->wlfc_state = NULL; ++ dhd_os_wlfc_unblock(dhd); ++ ++ return; ++} ++#endif /* PROP_TXSTATUS */ +diff --git a/drivers/net/wireless/ap6210/dhd_wlfc.h b/drivers/net/wireless/ap6210/dhd_wlfc.h +new file mode 100755 +index 0000000..42b350c +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dhd_wlfc.h +@@ -0,0 +1,288 @@ ++/* ++* Copyright (C) 1999-2012, Broadcom Corporation ++* ++* Unless you and Broadcom execute a separate written software license ++* agreement governing use of this software, this software is licensed to you ++* under the terms of the GNU General Public License version 2 (the "GPL"), ++* available at http://www.broadcom.com/licenses/GPLv2.php, with the ++* following added to such license: ++* ++* As a special exception, the copyright holders of this software give you ++* permission to link this software with independent modules, and to copy and ++* distribute the resulting executable under terms of your choice, provided that ++* you also meet, for each linked independent module, the terms and conditions of ++* the license of that module. An independent module is a module which is not ++* derived from this software. The special exception does not apply to any ++* modifications of the software. ++* ++* Notwithstanding the above, under no circumstances may you combine this ++* software in any way with any other Broadcom software provided under a license ++* other than the GPL, without Broadcom's express prior written consent. ++* $Id: dhd_wlfc.h 361006 2012-10-05 07:45:51Z $ ++* ++*/ ++#ifndef __wlfc_host_driver_definitions_h__ ++#define __wlfc_host_driver_definitions_h__ ++ ++/* 16 bits will provide an absolute max of 65536 slots */ ++#define WLFC_HANGER_MAXITEMS 1024 ++ ++#define WLFC_HANGER_ITEM_STATE_FREE 1 ++#define WLFC_HANGER_ITEM_STATE_INUSE 2 ++#define WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED 3 ++#define WLFC_PKTID_HSLOT_MASK 0xffff /* allow 16 bits only */ ++#define WLFC_PKTID_HSLOT_SHIFT 8 ++ ++/* x -> TXSTATUS TAG to/from firmware */ ++#define WLFC_PKTID_HSLOT_GET(x) \ ++ (((x) >> WLFC_PKTID_HSLOT_SHIFT) & WLFC_PKTID_HSLOT_MASK) ++#define WLFC_PKTID_HSLOT_SET(var, slot) \ ++ ((var) = ((var) & ~(WLFC_PKTID_HSLOT_MASK << WLFC_PKTID_HSLOT_SHIFT)) | \ ++ (((slot) & WLFC_PKTID_HSLOT_MASK) << WLFC_PKTID_HSLOT_SHIFT)) ++ ++#define WLFC_PKTID_FREERUNCTR_MASK 0xff ++ ++#define WLFC_PKTID_FREERUNCTR_GET(x) ((x) & WLFC_PKTID_FREERUNCTR_MASK) ++#define WLFC_PKTID_FREERUNCTR_SET(var, ctr) \ ++ ((var) = (((var) & ~WLFC_PKTID_FREERUNCTR_MASK) | \ ++ (((ctr) & WLFC_PKTID_FREERUNCTR_MASK)))) ++ ++#define WLFC_PKTQ_PENQ(pq, prec, p) ((pktq_full((pq)) || pktq_pfull((pq), (prec)))? \ ++ NULL : pktq_penq((pq), (prec), (p))) ++#define WLFC_PKTQ_PENQ_HEAD(pq, prec, p) ((pktq_full((pq)) || pktq_pfull((pq), (prec))) ? \ ++ NULL : pktq_penq_head((pq), (prec), (p))) ++ ++typedef enum ewlfc_packet_state { ++ eWLFC_PKTTYPE_NEW, ++ eWLFC_PKTTYPE_DELAYED, ++ eWLFC_PKTTYPE_SUPPRESSED, ++ eWLFC_PKTTYPE_MAX ++} ewlfc_packet_state_t; ++ ++typedef enum ewlfc_mac_entry_action { ++ eWLFC_MAC_ENTRY_ACTION_ADD, ++ eWLFC_MAC_ENTRY_ACTION_DEL, ++ eWLFC_MAC_ENTRY_ACTION_UPDATE, ++ eWLFC_MAC_ENTRY_ACTION_MAX ++} ewlfc_mac_entry_action_t; ++ ++typedef struct wlfc_hanger_item { ++ uint8 state; ++ uint8 gen; ++ uint8 pad[2]; ++ uint32 identifier; ++ void* pkt; ++#ifdef PROP_TXSTATUS_DEBUG ++ uint32 push_time; ++#endif ++} wlfc_hanger_item_t; ++ ++typedef struct wlfc_hanger { ++ int max_items; ++ uint32 pushed; ++ uint32 popped; ++ uint32 failed_to_push; ++ uint32 failed_to_pop; ++ uint32 failed_slotfind; ++ wlfc_hanger_item_t items[1]; ++ uint32 slot_pos; ++} wlfc_hanger_t; ++ ++#define WLFC_HANGER_SIZE(n) ((sizeof(wlfc_hanger_t) - \ ++ sizeof(wlfc_hanger_item_t)) + ((n)*sizeof(wlfc_hanger_item_t))) ++ ++#define WLFC_STATE_OPEN 1 ++#define WLFC_STATE_CLOSE 2 ++ ++#define WLFC_PSQ_PREC_COUNT ((AC_COUNT + 1) * 2) /* 2 for each AC traffic and bc/mc */ ++ ++#define WLFC_PSQ_LEN 2048 ++ ++#define WLFC_SENDQ_LEN 256 ++ ++ ++#define WLFC_FLOWCONTROL_HIWATER (2048 - 256) ++#define WLFC_FLOWCONTROL_LOWATER 256 ++ ++ ++typedef struct wlfc_mac_descriptor { ++ uint8 occupied; ++ uint8 interface_id; ++ uint8 iftype; ++ uint8 state; ++ uint8 ac_bitmap; /* for APSD */ ++ uint8 requested_credit; ++ uint8 requested_packet; ++ uint8 ea[ETHER_ADDR_LEN]; ++ /* ++ maintain (MAC,AC) based seq count for ++ packets going to the device. As well as bc/mc. ++ */ ++ uint8 seq[AC_COUNT + 1]; ++ uint8 generation; ++ struct pktq psq; ++ /* The AC pending bitmap that was reported to the fw at last change */ ++ uint8 traffic_lastreported_bmp; ++ /* The new AC pending bitmap */ ++ uint8 traffic_pending_bmp; ++ /* 1= send on next opportunity */ ++ uint8 send_tim_signal; ++ uint8 mac_handle; ++ uint transit_count; ++ uint suppr_transit_count; ++ uint suppress_count; ++ uint8 suppressed; ++ ++#ifdef PROP_TXSTATUS_DEBUG ++ uint32 dstncredit_sent_packets; ++ uint32 dstncredit_acks; ++ uint32 opened_ct; ++ uint32 closed_ct; ++#endif ++} wlfc_mac_descriptor_t; ++ ++#define WLFC_DECR_SEQCOUNT(entry, prec) do { if (entry->seq[(prec)] == 0) {\ ++ entry->seq[prec] = 0xff; } else entry->seq[prec]--;} while (0) ++ ++#define WLFC_INCR_SEQCOUNT(entry, prec) entry->seq[(prec)]++ ++#define WLFC_SEQCOUNT(entry, prec) entry->seq[(prec)] ++ ++typedef struct athost_wl_stat_counters { ++ uint32 pktin; ++ uint32 pkt2bus; ++ uint32 pktdropped; ++ uint32 tlv_parse_failed; ++ uint32 rollback; ++ uint32 rollback_failed; ++ uint32 sendq_full_error; ++ uint32 delayq_full_error; ++ uint32 credit_request_failed; ++ uint32 packet_request_failed; ++ uint32 mac_update_failed; ++ uint32 psmode_update_failed; ++ uint32 interface_update_failed; ++ uint32 wlfc_header_only_pkt; ++ uint32 txstatus_in; ++ uint32 d11_suppress; ++ uint32 wl_suppress; ++ uint32 bad_suppress; ++ uint32 pkt_freed; ++ uint32 pkt_free_err; ++ uint32 psq_wlsup_retx; ++ uint32 psq_wlsup_enq; ++ uint32 psq_d11sup_retx; ++ uint32 psq_d11sup_enq; ++ uint32 psq_hostq_retx; ++ uint32 psq_hostq_enq; ++ uint32 mac_handle_notfound; ++ uint32 wlc_tossed_pkts; ++ uint32 dhd_hdrpulls; ++ uint32 generic_error; ++ /* an extra one for bc/mc traffic */ ++ uint32 sendq_pkts[AC_COUNT + 1]; ++#ifdef PROP_TXSTATUS_DEBUG ++ /* all pkt2bus -> txstatus latency accumulated */ ++ uint32 latency_sample_count; ++ uint32 total_status_latency; ++ uint32 latency_most_recent; ++ int idx_delta; ++ uint32 deltas[10]; ++ uint32 fifo_credits_sent[6]; ++ uint32 fifo_credits_back[6]; ++ uint32 dropped_qfull[6]; ++ uint32 signal_only_pkts_sent; ++ uint32 signal_only_pkts_freed; ++#endif ++} athost_wl_stat_counters_t; ++ ++#ifdef PROP_TXSTATUS_DEBUG ++#define WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac) do { \ ++ (ctx)->stats.fifo_credits_sent[(ac)]++;} while (0) ++#define WLFC_HOST_FIFO_CREDIT_INC_BACKCTRS(ctx, ac) do { \ ++ (ctx)->stats.fifo_credits_back[(ac)]++;} while (0) ++#define WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, ac) do { \ ++ (ctx)->stats.dropped_qfull[(ac)]++;} while (0) ++#else ++#define WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac) do {} while (0) ++#define WLFC_HOST_FIFO_CREDIT_INC_BACKCTRS(ctx, ac) do {} while (0) ++#define WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, ac) do {} while (0) ++#endif ++ ++#define WLFC_FCMODE_NONE 0 ++#define WLFC_FCMODE_IMPLIED_CREDIT 1 ++#define WLFC_FCMODE_EXPLICIT_CREDIT 2 ++ ++/* How long to defer borrowing in milliseconds */ ++#define WLFC_BORROW_DEFER_PERIOD_MS 100 ++ ++/* Mask to represent available ACs (note: BC/MC is ignored */ ++#define WLFC_AC_MASK 0xF ++ ++/* Mask to check for only on-going AC_BE traffic */ ++#define WLFC_AC_BE_TRAFFIC_ONLY 0xD ++ ++typedef struct athost_wl_status_info { ++ uint8 last_seqid_to_wlc; ++ ++ /* OSL handle */ ++ osl_t* osh; ++ /* dhd pub */ ++ void* dhdp; ++ ++ /* stats */ ++ athost_wl_stat_counters_t stats; ++ ++ /* the additional ones are for bc/mc and ATIM FIFO */ ++ int FIFO_credit[AC_COUNT + 2]; ++ ++ /* Credit borrow counts for each FIFO from each of the other FIFOs */ ++ int credits_borrowed[AC_COUNT + 2][AC_COUNT + 2]; ++ ++ struct pktq SENDQ; ++ ++ /* packet hanger and MAC->handle lookup table */ ++ void* hanger; ++ struct { ++ /* table for individual nodes */ ++ wlfc_mac_descriptor_t nodes[WLFC_MAC_DESC_TABLE_SIZE]; ++ /* table for interfaces */ ++ wlfc_mac_descriptor_t interfaces[WLFC_MAX_IFNUM]; ++ /* OS may send packets to unknown (unassociated) destinations */ ++ /* A place holder for bc/mc and packets to unknown destinations */ ++ wlfc_mac_descriptor_t other; ++ } destination_entries; ++ /* token position for different priority packets */ ++ uint8 token_pos[AC_COUNT+1]; ++ /* ON/OFF state for flow control to the host network interface */ ++ uint8 hostif_flow_state[WLFC_MAX_IFNUM]; ++ uint8 host_ifidx; ++ /* to flow control an OS interface */ ++ uint8 toggle_host_if; ++ ++ /* ++ Mode in which the dhd flow control shall operate. Must be set before ++ traffic starts to the device. ++ 0 - Do not do any proptxtstatus flow control ++ 1 - Use implied credit from a packet status ++ 2 - Use explicit credit ++ */ ++ uint8 proptxstatus_mode; ++ ++ /* To borrow credits */ ++ uint8 allow_credit_borrow; ++ ++ /* Timestamp to compute how long to defer borrowing for */ ++ uint32 borrow_defer_timestamp; ++ ++ bool wlfc_locked; ++} athost_wl_status_info_t; ++ ++int dhd_wlfc_enable(dhd_pub_t *dhd); ++int dhd_wlfc_interface_event(struct dhd_info *, ++ ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea); ++int dhd_wlfc_FIFOcreditmap_event(struct dhd_info *dhd, uint8* event_data); ++int dhd_wlfc_event(struct dhd_info *dhd); ++int dhd_os_wlfc_block(dhd_pub_t *pub); ++int dhd_os_wlfc_unblock(dhd_pub_t *pub); ++ ++#endif /* __wlfc_host_driver_definitions_h__ */ +diff --git a/drivers/net/wireless/ap6210/dngl_stats.h b/drivers/net/wireless/ap6210/dngl_stats.h +new file mode 100755 +index 0000000..5e5a2e2 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dngl_stats.h +@@ -0,0 +1,43 @@ ++/* ++ * Common stats definitions for clients of dongle ++ * ports ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dngl_stats.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _dngl_stats_h_ ++#define _dngl_stats_h_ ++ ++typedef struct { ++ unsigned long rx_packets; /* total packets received */ ++ unsigned long tx_packets; /* total packets transmitted */ ++ unsigned long rx_bytes; /* total bytes received */ ++ unsigned long tx_bytes; /* total bytes transmitted */ ++ unsigned long rx_errors; /* bad packets received */ ++ unsigned long tx_errors; /* packet transmit problems */ ++ unsigned long rx_dropped; /* packets dropped by dongle */ ++ unsigned long tx_dropped; /* packets dropped by dongle */ ++ unsigned long multicast; /* multicast packets received */ ++} dngl_stats_t; ++ ++#endif /* _dngl_stats_h_ */ +diff --git a/drivers/net/wireless/ap6210/dngl_wlhdr.h b/drivers/net/wireless/ap6210/dngl_wlhdr.h +new file mode 100755 +index 0000000..0e37df6 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/dngl_wlhdr.h +@@ -0,0 +1,40 @@ ++/* ++ * Dongle WL Header definitions ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dngl_wlhdr.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _dngl_wlhdr_h_ ++#define _dngl_wlhdr_h_ ++ ++typedef struct wl_header { ++ uint8 type; /* Header type */ ++ uint8 version; /* Header version */ ++ int8 rssi; /* RSSI */ ++ uint8 pad; /* Unused */ ++} wl_header_t; ++ ++#define WL_HEADER_LEN sizeof(wl_header_t) ++#define WL_HEADER_TYPE 0 ++#define WL_HEADER_VER 1 ++#endif /* _dngl_wlhdr_h_ */ +diff --git a/drivers/net/wireless/ap6210/hndpmu.c b/drivers/net/wireless/ap6210/hndpmu.c +new file mode 100755 +index 0000000..e639015 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/hndpmu.c +@@ -0,0 +1,208 @@ ++/* ++ * Misc utility routines for accessing PMU corerev specific features ++ * of the SiliconBackplane-based Broadcom chips. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: hndpmu.c 354194 2012-08-30 08:39:03Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PMU_ERROR(args) ++ ++#define PMU_MSG(args) ++ ++/* To check in verbose debugging messages not intended ++ * to be on except on private builds. ++ */ ++#define PMU_NONE(args) ++ ++ ++/* SDIO Pad drive strength to select value mappings. ++ * The last strength value in each table must be 0 (the tri-state value). ++ */ ++typedef struct { ++ uint8 strength; /* Pad Drive Strength in mA */ ++ uint8 sel; /* Chip-specific select value */ ++} sdiod_drive_str_t; ++ ++/* SDIO Drive Strength to sel value table for PMU Rev 1 */ ++static const sdiod_drive_str_t sdiod_drive_strength_tab1[] = { ++ {4, 0x2}, ++ {2, 0x3}, ++ {1, 0x0}, ++ {0, 0x0} }; ++ ++/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */ ++static const sdiod_drive_str_t sdiod_drive_strength_tab2[] = { ++ {12, 0x7}, ++ {10, 0x6}, ++ {8, 0x5}, ++ {6, 0x4}, ++ {4, 0x2}, ++ {2, 0x1}, ++ {0, 0x0} }; ++ ++/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */ ++static const sdiod_drive_str_t sdiod_drive_strength_tab3[] = { ++ {32, 0x7}, ++ {26, 0x6}, ++ {22, 0x5}, ++ {16, 0x4}, ++ {12, 0x3}, ++ {8, 0x2}, ++ {4, 0x1}, ++ {0, 0x0} }; ++ ++/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8v) */ ++static const sdiod_drive_str_t sdiod_drive_strength_tab4_1v8[] = { ++ {32, 0x6}, ++ {26, 0x7}, ++ {22, 0x4}, ++ {16, 0x5}, ++ {12, 0x2}, ++ {8, 0x3}, ++ {4, 0x0}, ++ {0, 0x1} }; ++ ++/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.2v) */ ++ ++/* SDIO Drive Strength to sel value table for PMU Rev 11 (2.5v) */ ++ ++/* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */ ++static const sdiod_drive_str_t sdiod_drive_strength_tab5_1v8[] = { ++ {6, 0x7}, ++ {5, 0x6}, ++ {4, 0x5}, ++ {3, 0x4}, ++ {2, 0x2}, ++ {1, 0x1}, ++ {0, 0x0} }; ++ ++/* SDIO Drive Strength to sel value table for PMU Rev 13 (3.3v) */ ++ ++/* SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */ ++static const sdiod_drive_str_t sdiod_drive_strength_tab6_1v8[] = { ++ {3, 0x3}, ++ {2, 0x2}, ++ {1, 0x1}, ++ {0, 0x0} }; ++ ++#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) ++ ++void ++si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength) ++{ ++ chipcregs_t *cc; ++ uint origidx, intr_val = 0; ++ sdiod_drive_str_t *str_tab = NULL; ++ uint32 str_mask = 0; ++ uint32 str_shift = 0; ++ ++ if (!(sih->cccaps & CC_CAP_PMU)) { ++ return; ++ } ++ ++ /* Remember original core before switch to chipc */ ++ cc = (chipcregs_t *) si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val); ++ ++ switch (SDIOD_DRVSTR_KEY(sih->chip, sih->pmurev)) { ++ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1): ++ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab1; ++ str_mask = 0x30000000; ++ str_shift = 28; ++ break; ++ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2): ++ case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3): ++ case SDIOD_DRVSTR_KEY(BCM4315_CHIP_ID, 4): ++ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab2; ++ str_mask = 0x00003800; ++ str_shift = 11; ++ break; ++ case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8): ++ case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 11): ++ if (sih->pmurev == 8) { ++ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab3; ++ } ++ else if (sih->pmurev == 11) { ++ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8; ++ } ++ str_mask = 0x00003800; ++ str_shift = 11; ++ break; ++ case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12): ++ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8; ++ str_mask = 0x00003800; ++ str_shift = 11; ++ break; ++ case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13): ++ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab5_1v8; ++ str_mask = 0x00003800; ++ str_shift = 11; ++ break; ++ case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17): ++ str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab6_1v8; ++ str_mask = 0x00001800; ++ str_shift = 11; ++ break; ++ default: ++ PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", ++ bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev)); ++ ++ break; ++ } ++ ++ if (str_tab != NULL && cc != NULL) { ++ uint32 cc_data_temp; ++ int i; ++ ++ /* Pick the lowest available drive strength equal or greater than the ++ * requested strength. Drive strength of 0 requests tri-state. ++ */ ++ for (i = 0; drivestrength < str_tab[i].strength; i++) ++ ; ++ ++ if (i > 0 && drivestrength > str_tab[i].strength) ++ i--; ++ ++ W_REG(osh, &cc->chipcontrol_addr, 1); ++ cc_data_temp = R_REG(osh, &cc->chipcontrol_data); ++ cc_data_temp &= ~str_mask; ++ cc_data_temp |= str_tab[i].sel << str_shift; ++ W_REG(osh, &cc->chipcontrol_data, cc_data_temp); ++ ++ PMU_MSG(("SDIO: %dmA drive strength requested; set to %dmA\n", ++ drivestrength, str_tab[i].strength)); ++ } ++ ++ /* Return to original core */ ++ si_restore_core(sih, origidx, intr_val); ++} +diff --git a/drivers/net/wireless/ap6210/include/Makefile b/drivers/net/wireless/ap6210/include/Makefile +new file mode 100755 +index 0000000..8483b54 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/Makefile +@@ -0,0 +1,54 @@ ++#!/bin/bash ++# ++# This script serves following purpose: ++# ++# 1. It generates native version information by querying ++# automerger maintained database to see where src/include ++# came from ++# 2. For select components, as listed in compvers.sh ++# it generates component version files ++# ++# Copyright 2005, Broadcom, Inc. ++# ++# $Id: Makefile 241686 2011-02-19 00:22:45Z prakashd $ ++# ++ ++SRCBASE := .. ++ ++TARGETS := epivers.h ++ ++ifdef VERBOSE ++export VERBOSE ++endif ++ ++all release: epivers compvers ++ ++# Generate epivers.h for native branch version ++epivers: ++ bash epivers.sh ++ ++# Generate epivers.h for native branch version ++compvers: ++ @if [ -s "compvers.sh" ]; then \ ++ echo "Generating component versions, if any"; \ ++ bash compvers.sh; \ ++ else \ ++ echo "Skipping component version generation"; \ ++ fi ++ ++# Generate epivers.h for native branch version ++clean_compvers: ++ @if [ -s "compvers.sh" ]; then \ ++ echo "bash compvers.sh clean"; \ ++ bash compvers.sh clean; \ ++ else \ ++ echo "Skipping component version clean"; \ ++ fi ++ ++clean: ++ rm -f $(TARGETS) *.prev ++ ++clean_all: clean clean_compvers ++ ++.PHONY: all release clean epivers compvers clean_compvers ++ +diff --git a/drivers/net/wireless/ap6210/include/aidmp.h b/drivers/net/wireless/ap6210/include/aidmp.h +new file mode 100755 +index 0000000..d557079 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/aidmp.h +@@ -0,0 +1,375 @@ ++/* ++ * Broadcom AMBA Interconnect definitions. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: aidmp.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _AIDMP_H ++#define _AIDMP_H ++ ++/* Manufacturer Ids */ ++#define MFGID_ARM 0x43b ++#define MFGID_BRCM 0x4bf ++#define MFGID_MIPS 0x4a7 ++ ++/* Component Classes */ ++#define CC_SIM 0 ++#define CC_EROM 1 ++#define CC_CORESIGHT 9 ++#define CC_VERIF 0xb ++#define CC_OPTIMO 0xd ++#define CC_GEN 0xe ++#define CC_PRIMECELL 0xf ++ ++/* Enumeration ROM registers */ ++#define ER_EROMENTRY 0x000 ++#define ER_REMAPCONTROL 0xe00 ++#define ER_REMAPSELECT 0xe04 ++#define ER_MASTERSELECT 0xe10 ++#define ER_ITCR 0xf00 ++#define ER_ITIP 0xf04 ++ ++/* Erom entries */ ++#define ER_TAG 0xe ++#define ER_TAG1 0x6 ++#define ER_VALID 1 ++#define ER_CI 0 ++#define ER_MP 2 ++#define ER_ADD 4 ++#define ER_END 0xe ++#define ER_BAD 0xffffffff ++ ++/* EROM CompIdentA */ ++#define CIA_MFG_MASK 0xfff00000 ++#define CIA_MFG_SHIFT 20 ++#define CIA_CID_MASK 0x000fff00 ++#define CIA_CID_SHIFT 8 ++#define CIA_CCL_MASK 0x000000f0 ++#define CIA_CCL_SHIFT 4 ++ ++/* EROM CompIdentB */ ++#define CIB_REV_MASK 0xff000000 ++#define CIB_REV_SHIFT 24 ++#define CIB_NSW_MASK 0x00f80000 ++#define CIB_NSW_SHIFT 19 ++#define CIB_NMW_MASK 0x0007c000 ++#define CIB_NMW_SHIFT 14 ++#define CIB_NSP_MASK 0x00003e00 ++#define CIB_NSP_SHIFT 9 ++#define CIB_NMP_MASK 0x000001f0 ++#define CIB_NMP_SHIFT 4 ++ ++/* EROM MasterPortDesc */ ++#define MPD_MUI_MASK 0x0000ff00 ++#define MPD_MUI_SHIFT 8 ++#define MPD_MP_MASK 0x000000f0 ++#define MPD_MP_SHIFT 4 ++ ++/* EROM AddrDesc */ ++#define AD_ADDR_MASK 0xfffff000 ++#define AD_SP_MASK 0x00000f00 ++#define AD_SP_SHIFT 8 ++#define AD_ST_MASK 0x000000c0 ++#define AD_ST_SHIFT 6 ++#define AD_ST_SLAVE 0x00000000 ++#define AD_ST_BRIDGE 0x00000040 ++#define AD_ST_SWRAP 0x00000080 ++#define AD_ST_MWRAP 0x000000c0 ++#define AD_SZ_MASK 0x00000030 ++#define AD_SZ_SHIFT 4 ++#define AD_SZ_4K 0x00000000 ++#define AD_SZ_8K 0x00000010 ++#define AD_SZ_16K 0x00000020 ++#define AD_SZ_SZD 0x00000030 ++#define AD_AG32 0x00000008 ++#define AD_ADDR_ALIGN 0x00000fff ++#define AD_SZ_BASE 0x00001000 /* 4KB */ ++ ++/* EROM SizeDesc */ ++#define SD_SZ_MASK 0xfffff000 ++#define SD_SG32 0x00000008 ++#define SD_SZ_ALIGN 0x00000fff ++ ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++typedef volatile struct _aidmp { ++ uint32 oobselina30; /* 0x000 */ ++ uint32 oobselina74; /* 0x004 */ ++ uint32 PAD[6]; ++ uint32 oobselinb30; /* 0x020 */ ++ uint32 oobselinb74; /* 0x024 */ ++ uint32 PAD[6]; ++ uint32 oobselinc30; /* 0x040 */ ++ uint32 oobselinc74; /* 0x044 */ ++ uint32 PAD[6]; ++ uint32 oobselind30; /* 0x060 */ ++ uint32 oobselind74; /* 0x064 */ ++ uint32 PAD[38]; ++ uint32 oobselouta30; /* 0x100 */ ++ uint32 oobselouta74; /* 0x104 */ ++ uint32 PAD[6]; ++ uint32 oobseloutb30; /* 0x120 */ ++ uint32 oobseloutb74; /* 0x124 */ ++ uint32 PAD[6]; ++ uint32 oobseloutc30; /* 0x140 */ ++ uint32 oobseloutc74; /* 0x144 */ ++ uint32 PAD[6]; ++ uint32 oobseloutd30; /* 0x160 */ ++ uint32 oobseloutd74; /* 0x164 */ ++ uint32 PAD[38]; ++ uint32 oobsynca; /* 0x200 */ ++ uint32 oobseloutaen; /* 0x204 */ ++ uint32 PAD[6]; ++ uint32 oobsyncb; /* 0x220 */ ++ uint32 oobseloutben; /* 0x224 */ ++ uint32 PAD[6]; ++ uint32 oobsyncc; /* 0x240 */ ++ uint32 oobseloutcen; /* 0x244 */ ++ uint32 PAD[6]; ++ uint32 oobsyncd; /* 0x260 */ ++ uint32 oobseloutden; /* 0x264 */ ++ uint32 PAD[38]; ++ uint32 oobaextwidth; /* 0x300 */ ++ uint32 oobainwidth; /* 0x304 */ ++ uint32 oobaoutwidth; /* 0x308 */ ++ uint32 PAD[5]; ++ uint32 oobbextwidth; /* 0x320 */ ++ uint32 oobbinwidth; /* 0x324 */ ++ uint32 oobboutwidth; /* 0x328 */ ++ uint32 PAD[5]; ++ uint32 oobcextwidth; /* 0x340 */ ++ uint32 oobcinwidth; /* 0x344 */ ++ uint32 oobcoutwidth; /* 0x348 */ ++ uint32 PAD[5]; ++ uint32 oobdextwidth; /* 0x360 */ ++ uint32 oobdinwidth; /* 0x364 */ ++ uint32 oobdoutwidth; /* 0x368 */ ++ uint32 PAD[37]; ++ uint32 ioctrlset; /* 0x400 */ ++ uint32 ioctrlclear; /* 0x404 */ ++ uint32 ioctrl; /* 0x408 */ ++ uint32 PAD[61]; ++ uint32 iostatus; /* 0x500 */ ++ uint32 PAD[127]; ++ uint32 ioctrlwidth; /* 0x700 */ ++ uint32 iostatuswidth; /* 0x704 */ ++ uint32 PAD[62]; ++ uint32 resetctrl; /* 0x800 */ ++ uint32 resetstatus; /* 0x804 */ ++ uint32 resetreadid; /* 0x808 */ ++ uint32 resetwriteid; /* 0x80c */ ++ uint32 PAD[60]; ++ uint32 errlogctrl; /* 0x900 */ ++ uint32 errlogdone; /* 0x904 */ ++ uint32 errlogstatus; /* 0x908 */ ++ uint32 errlogaddrlo; /* 0x90c */ ++ uint32 errlogaddrhi; /* 0x910 */ ++ uint32 errlogid; /* 0x914 */ ++ uint32 errloguser; /* 0x918 */ ++ uint32 errlogflags; /* 0x91c */ ++ uint32 PAD[56]; ++ uint32 intstatus; /* 0xa00 */ ++ uint32 PAD[255]; ++ uint32 config; /* 0xe00 */ ++ uint32 PAD[63]; ++ uint32 itcr; /* 0xf00 */ ++ uint32 PAD[3]; ++ uint32 itipooba; /* 0xf10 */ ++ uint32 itipoobb; /* 0xf14 */ ++ uint32 itipoobc; /* 0xf18 */ ++ uint32 itipoobd; /* 0xf1c */ ++ uint32 PAD[4]; ++ uint32 itipoobaout; /* 0xf30 */ ++ uint32 itipoobbout; /* 0xf34 */ ++ uint32 itipoobcout; /* 0xf38 */ ++ uint32 itipoobdout; /* 0xf3c */ ++ uint32 PAD[4]; ++ uint32 itopooba; /* 0xf50 */ ++ uint32 itopoobb; /* 0xf54 */ ++ uint32 itopoobc; /* 0xf58 */ ++ uint32 itopoobd; /* 0xf5c */ ++ uint32 PAD[4]; ++ uint32 itopoobain; /* 0xf70 */ ++ uint32 itopoobbin; /* 0xf74 */ ++ uint32 itopoobcin; /* 0xf78 */ ++ uint32 itopoobdin; /* 0xf7c */ ++ uint32 PAD[4]; ++ uint32 itopreset; /* 0xf90 */ ++ uint32 PAD[15]; ++ uint32 peripherialid4; /* 0xfd0 */ ++ uint32 peripherialid5; /* 0xfd4 */ ++ uint32 peripherialid6; /* 0xfd8 */ ++ uint32 peripherialid7; /* 0xfdc */ ++ uint32 peripherialid0; /* 0xfe0 */ ++ uint32 peripherialid1; /* 0xfe4 */ ++ uint32 peripherialid2; /* 0xfe8 */ ++ uint32 peripherialid3; /* 0xfec */ ++ uint32 componentid0; /* 0xff0 */ ++ uint32 componentid1; /* 0xff4 */ ++ uint32 componentid2; /* 0xff8 */ ++ uint32 componentid3; /* 0xffc */ ++} aidmp_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++/* Out-of-band Router registers */ ++#define OOB_BUSCONFIG 0x020 ++#define OOB_STATUSA 0x100 ++#define OOB_STATUSB 0x104 ++#define OOB_STATUSC 0x108 ++#define OOB_STATUSD 0x10c ++#define OOB_ENABLEA0 0x200 ++#define OOB_ENABLEA1 0x204 ++#define OOB_ENABLEA2 0x208 ++#define OOB_ENABLEA3 0x20c ++#define OOB_ENABLEB0 0x280 ++#define OOB_ENABLEB1 0x284 ++#define OOB_ENABLEB2 0x288 ++#define OOB_ENABLEB3 0x28c ++#define OOB_ENABLEC0 0x300 ++#define OOB_ENABLEC1 0x304 ++#define OOB_ENABLEC2 0x308 ++#define OOB_ENABLEC3 0x30c ++#define OOB_ENABLED0 0x380 ++#define OOB_ENABLED1 0x384 ++#define OOB_ENABLED2 0x388 ++#define OOB_ENABLED3 0x38c ++#define OOB_ITCR 0xf00 ++#define OOB_ITIPOOBA 0xf10 ++#define OOB_ITIPOOBB 0xf14 ++#define OOB_ITIPOOBC 0xf18 ++#define OOB_ITIPOOBD 0xf1c ++#define OOB_ITOPOOBA 0xf30 ++#define OOB_ITOPOOBB 0xf34 ++#define OOB_ITOPOOBC 0xf38 ++#define OOB_ITOPOOBD 0xf3c ++ ++/* DMP wrapper registers */ ++#define AI_OOBSELINA30 0x000 ++#define AI_OOBSELINA74 0x004 ++#define AI_OOBSELINB30 0x020 ++#define AI_OOBSELINB74 0x024 ++#define AI_OOBSELINC30 0x040 ++#define AI_OOBSELINC74 0x044 ++#define AI_OOBSELIND30 0x060 ++#define AI_OOBSELIND74 0x064 ++#define AI_OOBSELOUTA30 0x100 ++#define AI_OOBSELOUTA74 0x104 ++#define AI_OOBSELOUTB30 0x120 ++#define AI_OOBSELOUTB74 0x124 ++#define AI_OOBSELOUTC30 0x140 ++#define AI_OOBSELOUTC74 0x144 ++#define AI_OOBSELOUTD30 0x160 ++#define AI_OOBSELOUTD74 0x164 ++#define AI_OOBSYNCA 0x200 ++#define AI_OOBSELOUTAEN 0x204 ++#define AI_OOBSYNCB 0x220 ++#define AI_OOBSELOUTBEN 0x224 ++#define AI_OOBSYNCC 0x240 ++#define AI_OOBSELOUTCEN 0x244 ++#define AI_OOBSYNCD 0x260 ++#define AI_OOBSELOUTDEN 0x264 ++#define AI_OOBAEXTWIDTH 0x300 ++#define AI_OOBAINWIDTH 0x304 ++#define AI_OOBAOUTWIDTH 0x308 ++#define AI_OOBBEXTWIDTH 0x320 ++#define AI_OOBBINWIDTH 0x324 ++#define AI_OOBBOUTWIDTH 0x328 ++#define AI_OOBCEXTWIDTH 0x340 ++#define AI_OOBCINWIDTH 0x344 ++#define AI_OOBCOUTWIDTH 0x348 ++#define AI_OOBDEXTWIDTH 0x360 ++#define AI_OOBDINWIDTH 0x364 ++#define AI_OOBDOUTWIDTH 0x368 ++ ++ ++#define AI_IOCTRLSET 0x400 ++#define AI_IOCTRLCLEAR 0x404 ++#define AI_IOCTRL 0x408 ++#define AI_IOSTATUS 0x500 ++#define AI_RESETCTRL 0x800 ++#define AI_RESETSTATUS 0x804 ++ ++#define AI_IOCTRLWIDTH 0x700 ++#define AI_IOSTATUSWIDTH 0x704 ++ ++#define AI_RESETREADID 0x808 ++#define AI_RESETWRITEID 0x80c ++#define AI_ERRLOGCTRL 0xa00 ++#define AI_ERRLOGDONE 0xa04 ++#define AI_ERRLOGSTATUS 0xa08 ++#define AI_ERRLOGADDRLO 0xa0c ++#define AI_ERRLOGADDRHI 0xa10 ++#define AI_ERRLOGID 0xa14 ++#define AI_ERRLOGUSER 0xa18 ++#define AI_ERRLOGFLAGS 0xa1c ++#define AI_INTSTATUS 0xa00 ++#define AI_CONFIG 0xe00 ++#define AI_ITCR 0xf00 ++#define AI_ITIPOOBA 0xf10 ++#define AI_ITIPOOBB 0xf14 ++#define AI_ITIPOOBC 0xf18 ++#define AI_ITIPOOBD 0xf1c ++#define AI_ITIPOOBAOUT 0xf30 ++#define AI_ITIPOOBBOUT 0xf34 ++#define AI_ITIPOOBCOUT 0xf38 ++#define AI_ITIPOOBDOUT 0xf3c ++#define AI_ITOPOOBA 0xf50 ++#define AI_ITOPOOBB 0xf54 ++#define AI_ITOPOOBC 0xf58 ++#define AI_ITOPOOBD 0xf5c ++#define AI_ITOPOOBAIN 0xf70 ++#define AI_ITOPOOBBIN 0xf74 ++#define AI_ITOPOOBCIN 0xf78 ++#define AI_ITOPOOBDIN 0xf7c ++#define AI_ITOPRESET 0xf90 ++#define AI_PERIPHERIALID4 0xfd0 ++#define AI_PERIPHERIALID5 0xfd4 ++#define AI_PERIPHERIALID6 0xfd8 ++#define AI_PERIPHERIALID7 0xfdc ++#define AI_PERIPHERIALID0 0xfe0 ++#define AI_PERIPHERIALID1 0xfe4 ++#define AI_PERIPHERIALID2 0xfe8 ++#define AI_PERIPHERIALID3 0xfec ++#define AI_COMPONENTID0 0xff0 ++#define AI_COMPONENTID1 0xff4 ++#define AI_COMPONENTID2 0xff8 ++#define AI_COMPONENTID3 0xffc ++ ++/* resetctrl */ ++#define AIRC_RESET 1 ++ ++/* config */ ++#define AICFG_OOB 0x00000020 ++#define AICFG_IOS 0x00000010 ++#define AICFG_IOC 0x00000008 ++#define AICFG_TO 0x00000004 ++#define AICFG_ERRL 0x00000002 ++#define AICFG_RST 0x00000001 ++ ++/* bit defines for AI_OOBSELOUTB74 reg */ ++#define OOB_SEL_OUTEN_B_5 15 ++#define OOB_SEL_OUTEN_B_6 23 ++ ++#endif /* _AIDMP_H */ +diff --git a/drivers/net/wireless/ap6210/include/bcm_cfg.h b/drivers/net/wireless/ap6210/include/bcm_cfg.h +new file mode 100755 +index 0000000..ecff4f4 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcm_cfg.h +@@ -0,0 +1,29 @@ ++/* ++ * BCM common config options ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcm_cfg.h 294399 2011-11-07 03:31:22Z $ ++ */ ++ ++#ifndef _bcm_cfg_h_ ++#define _bcm_cfg_h_ ++#endif /* _bcm_cfg_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/bcm_mpool_pub.h b/drivers/net/wireless/ap6210/include/bcm_mpool_pub.h +new file mode 100755 +index 0000000..8fe3de7 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcm_mpool_pub.h +@@ -0,0 +1,361 @@ ++/* ++ * Memory pools library, Public interface ++ * ++ * API Overview ++ * ++ * This package provides a memory allocation subsystem based on pools of ++ * homogenous objects. ++ * ++ * Instrumentation is available for reporting memory utilization both ++ * on a per-data-structure basis and system wide. ++ * ++ * There are two main types defined in this API. ++ * ++ * pool manager: A singleton object that acts as a factory for ++ * pool allocators. It also is used for global ++ * instrumentation, such as reporting all blocks ++ * in use across all data structures. The pool manager ++ * creates and provides individual memory pools ++ * upon request to application code. ++ * ++ * memory pool: An object for allocating homogenous memory blocks. ++ * ++ * Global identifiers in this module use the following prefixes: ++ * bcm_mpm_* Memory pool manager ++ * bcm_mp_* Memory pool ++ * ++ * There are two main types of memory pools: ++ * ++ * prealloc: The contiguous memory block of objects can either be supplied ++ * by the client or malloc'ed by the memory manager. The objects are ++ * allocated out of a block of memory and freed back to the block. ++ * ++ * heap: The memory pool allocator uses the heap (malloc/free) for memory. ++ * In this case, the pool allocator is just providing statistics ++ * and instrumentation on top of the heap, without modifying the heap ++ * allocation implementation. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id$ ++ */ ++ ++#ifndef _BCM_MPOOL_PUB_H ++#define _BCM_MPOOL_PUB_H 1 ++ ++#include /* needed for uint16 */ ++ ++ ++/* ++************************************************************************** ++* ++* Type definitions, handles ++* ++************************************************************************** ++*/ ++ ++/* Forward declaration of OSL handle. */ ++struct osl_info; ++ ++/* Forward declaration of string buffer. */ ++struct bcmstrbuf; ++ ++/* ++ * Opaque type definition for the pool manager handle. This object is used for global ++ * memory pool operations such as obtaining a new pool, deleting a pool, iterating and ++ * instrumentation/debugging. ++ */ ++struct bcm_mpm_mgr; ++typedef struct bcm_mpm_mgr *bcm_mpm_mgr_h; ++ ++/* ++ * Opaque type definition for an instance of a pool. This handle is used for allocating ++ * and freeing memory through the pool, as well as management/instrumentation on this ++ * specific pool. ++ */ ++struct bcm_mp_pool; ++typedef struct bcm_mp_pool *bcm_mp_pool_h; ++ ++ ++/* ++ * To make instrumentation more readable, every memory ++ * pool must have a readable name. Pool names are up to ++ * 8 bytes including '\0' termination. (7 printable characters.) ++ */ ++#define BCM_MP_NAMELEN 8 ++ ++ ++/* ++ * Type definition for pool statistics. ++ */ ++typedef struct bcm_mp_stats { ++ char name[BCM_MP_NAMELEN]; /* Name of this pool. */ ++ unsigned int objsz; /* Object size allocated in this pool */ ++ uint16 nobj; /* Total number of objects in this pool */ ++ uint16 num_alloc; /* Number of objects currently allocated */ ++ uint16 high_water; /* Max number of allocated objects. */ ++ uint16 failed_alloc; /* Failed allocations. */ ++} bcm_mp_stats_t; ++ ++ ++/* ++************************************************************************** ++* ++* API Routines on the pool manager. ++* ++************************************************************************** ++*/ ++ ++/* ++ * bcm_mpm_init() - initialize the whole memory pool system. ++ * ++ * Parameters: ++ * osh: INPUT Operating system handle. Needed for heap memory allocation. ++ * max_pools: INPUT Maximum number of mempools supported. ++ * mgr: OUTPUT The handle is written with the new pools manager object/handle. ++ * ++ * Returns: ++ * BCME_OK Object initialized successfully. May be used. ++ * BCME_NOMEM Initialization failed due to no memory. Object must not be used. ++ */ ++int bcm_mpm_init(struct osl_info *osh, int max_pools, bcm_mpm_mgr_h *mgrp); ++ ++ ++/* ++ * bcm_mpm_deinit() - de-initialize the whole memory pool system. ++ * ++ * Parameters: ++ * mgr: INPUT Pointer to pool manager handle. ++ * ++ * Returns: ++ * BCME_OK Memory pool manager successfully de-initialized. ++ * other Indicated error occured during de-initialization. ++ */ ++int bcm_mpm_deinit(bcm_mpm_mgr_h *mgrp); ++ ++/* ++ * bcm_mpm_create_prealloc_pool() - Create a new pool for fixed size objects. The ++ * pool uses a contiguous block of pre-alloced ++ * memory. The memory block may either be provided ++ * by the client or dynamically allocated by the ++ * pool manager. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pool manager ++ * obj_sz: INPUT Size of objects that will be allocated by the new pool ++ * Must be >= sizeof(void *). ++ * nobj: INPUT Maximum number of concurrently existing objects to support ++ * memstart INPUT Pointer to the memory to use, or NULL to malloc() ++ * memsize INPUT Number of bytes referenced from memstart (for error checking). ++ * Must be 0 if 'memstart' is NULL. ++ * poolname INPUT For instrumentation, the name of the pool ++ * newp: OUTPUT The handle for the new pool, if creation is successful ++ * ++ * Returns: ++ * BCME_OK Pool created ok. ++ * other Pool not created due to indicated error. newpoolp set to NULL. ++ * ++ * ++ */ ++int bcm_mpm_create_prealloc_pool(bcm_mpm_mgr_h mgr, ++ unsigned int obj_sz, ++ int nobj, ++ void *memstart, ++ unsigned int memsize, ++ char poolname[BCM_MP_NAMELEN], ++ bcm_mp_pool_h *newp); ++ ++ ++/* ++ * bcm_mpm_delete_prealloc_pool() - Delete a memory pool. This should only be called after ++ * all memory objects have been freed back to the pool. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * pool: INPUT The handle of the pool to delete ++ * ++ * Returns: ++ * BCME_OK Pool deleted ok. ++ * other Pool not deleted due to indicated error. ++ * ++ */ ++int bcm_mpm_delete_prealloc_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); ++ ++/* ++ * bcm_mpm_create_heap_pool() - Create a new pool for fixed size objects. The memory ++ * pool allocator uses the heap (malloc/free) for memory. ++ * In this case, the pool allocator is just providing ++ * statistics and instrumentation on top of the heap, ++ * without modifying the heap allocation implementation. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pool manager ++ * obj_sz: INPUT Size of objects that will be allocated by the new pool ++ * poolname INPUT For instrumentation, the name of the pool ++ * newp: OUTPUT The handle for the new pool, if creation is successful ++ * ++ * Returns: ++ * BCME_OK Pool created ok. ++ * other Pool not created due to indicated error. newpoolp set to NULL. ++ * ++ * ++ */ ++int bcm_mpm_create_heap_pool(bcm_mpm_mgr_h mgr, unsigned int obj_sz, ++ char poolname[BCM_MP_NAMELEN], ++ bcm_mp_pool_h *newp); ++ ++ ++/* ++ * bcm_mpm_delete_heap_pool() - Delete a memory pool. This should only be called after ++ * all memory objects have been freed back to the pool. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * pool: INPUT The handle of the pool to delete ++ * ++ * Returns: ++ * BCME_OK Pool deleted ok. ++ * other Pool not deleted due to indicated error. ++ * ++ */ ++int bcm_mpm_delete_heap_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); ++ ++ ++/* ++ * bcm_mpm_stats() - Return stats for all pools ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * stats: OUTPUT Array of pool statistics. ++ * nentries: MOD Max elements in 'stats' array on INPUT. Actual number ++ * of array elements copied to 'stats' on OUTPUT. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error getting stats. ++ * ++ */ ++int bcm_mpm_stats(bcm_mpm_mgr_h mgr, bcm_mp_stats_t *stats, int *nentries); ++ ++ ++/* ++ * bcm_mpm_dump() - Display statistics on all pools ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * b: OUTPUT Output buffer. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error during dump. ++ * ++ */ ++int bcm_mpm_dump(bcm_mpm_mgr_h mgr, struct bcmstrbuf *b); ++ ++ ++/* ++ * bcm_mpm_get_obj_size() - The size of memory objects may need to be padded to ++ * compensate for alignment requirements of the objects. ++ * This function provides the padded object size. If clients ++ * pre-allocate a memory slab for a memory pool, the ++ * padded object size should be used by the client to allocate ++ * the memory slab (in order to provide sufficent space for ++ * the maximum number of objects). ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager. ++ * obj_sz: INPUT Input object size. ++ * padded_obj_sz: OUTPUT Padded object size. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * BCME_BADARG Bad arguments. ++ * ++ */ ++int bcm_mpm_get_obj_size(bcm_mpm_mgr_h mgr, unsigned int obj_sz, unsigned int *padded_obj_sz); ++ ++ ++/* ++*************************************************************************** ++* ++* API Routines on a specific pool. ++* ++*************************************************************************** ++*/ ++ ++ ++/* ++ * bcm_mp_alloc() - Allocate a memory pool object. ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool. ++ * ++ * Returns: ++ * A pointer to the new object. NULL on error. ++ * ++ */ ++void* bcm_mp_alloc(bcm_mp_pool_h pool); ++ ++/* ++ * bcm_mp_free() - Free a memory pool object. ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool. ++ * objp: INPUT A pointer to the object to free. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error during free. ++ * ++ */ ++int bcm_mp_free(bcm_mp_pool_h pool, void *objp); ++ ++/* ++ * bcm_mp_stats() - Return stats for this pool ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool ++ * stats: OUTPUT Pool statistics ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error getting statistics. ++ * ++ */ ++int bcm_mp_stats(bcm_mp_pool_h pool, bcm_mp_stats_t *stats); ++ ++ ++/* ++ * bcm_mp_dump() - Dump a pool ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool ++ * b OUTPUT Output buffer ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error during dump. ++ * ++ */ ++int bcm_mp_dump(bcm_mp_pool_h pool, struct bcmstrbuf *b); ++ ++ ++#endif /* _BCM_MPOOL_PUB_H */ +diff --git a/drivers/net/wireless/ap6210/include/bcmcdc.h b/drivers/net/wireless/ap6210/include/bcmcdc.h +new file mode 100755 +index 0000000..a1d1271 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmcdc.h +@@ -0,0 +1,132 @@ ++/* ++ * CDC network driver ioctl/indication encoding ++ * Broadcom 802.11abg Networking Device Driver ++ * ++ * Definitions subject to change without notice. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmcdc.h 318308 2012-03-02 02:23:42Z $ ++ */ ++#ifndef _bcmcdc_h_ ++#define _bcmcdc_h_ ++#include ++ ++typedef struct cdc_ioctl { ++ uint32 cmd; /* ioctl command value */ ++ uint32 len; /* lower 16: output buflen; upper 16: input buflen (excludes header) */ ++ uint32 flags; /* flag defns given below */ ++ uint32 status; /* status code returned from the device */ ++} cdc_ioctl_t; ++ ++/* Max valid buffer size that can be sent to the dongle */ ++#define CDC_MAX_MSG_SIZE ETHER_MAX_LEN ++ ++/* len field is divided into input and output buffer lengths */ ++#define CDCL_IOC_OUTLEN_MASK 0x0000FFFF /* maximum or expected response length, */ ++ /* excluding IOCTL header */ ++#define CDCL_IOC_OUTLEN_SHIFT 0 ++#define CDCL_IOC_INLEN_MASK 0xFFFF0000 /* input buffer length, excluding IOCTL header */ ++#define CDCL_IOC_INLEN_SHIFT 16 ++ ++/* CDC flag definitions */ ++#define CDCF_IOC_ERROR 0x01 /* 0=success, 1=ioctl cmd failed */ ++#define CDCF_IOC_SET 0x02 /* 0=get, 1=set cmd */ ++#define CDCF_IOC_OVL_IDX_MASK 0x3c /* overlay region index mask */ ++#define CDCF_IOC_OVL_RSV 0x40 /* 1=reserve this overlay region */ ++#define CDCF_IOC_OVL 0x80 /* 1=this ioctl corresponds to an overlay */ ++#define CDCF_IOC_ACTION_MASK 0xfe /* SET/GET, OVL_IDX, OVL_RSV, OVL mask */ ++#define CDCF_IOC_ACTION_SHIFT 1 /* SET/GET, OVL_IDX, OVL_RSV, OVL shift */ ++#define CDCF_IOC_IF_MASK 0xF000 /* I/F index */ ++#define CDCF_IOC_IF_SHIFT 12 ++#define CDCF_IOC_ID_MASK 0xFFFF0000 /* used to uniquely id an ioctl req/resp pairing */ ++#define CDCF_IOC_ID_SHIFT 16 /* # of bits of shift for ID Mask */ ++ ++#define CDC_IOC_IF_IDX(flags) (((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT) ++#define CDC_IOC_ID(flags) (((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT) ++ ++#define CDC_GET_IF_IDX(hdr) \ ++ ((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)) ++#define CDC_SET_IF_IDX(hdr, idx) \ ++ ((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | ((idx) << CDCF_IOC_IF_SHIFT))) ++ ++/* ++ * BDC header ++ * ++ * The BDC header is used on data packets to convey priority across USB. ++ */ ++ ++struct bdc_header { ++ uint8 flags; /* Flags */ ++ uint8 priority; /* 802.1d Priority 0:2 bits, 4:7 USB flow control info */ ++ uint8 flags2; ++ uint8 dataOffset; /* Offset from end of BDC header to packet data, in ++ * 4-byte words. Leaves room for optional headers. ++ */ ++}; ++ ++#define BDC_HEADER_LEN 4 ++ ++/* flags field bitmap */ ++#define BDC_FLAG_80211_PKT 0x01 /* Packet is in 802.11 format (dongle -> host) */ ++#define BDC_FLAG_SUM_GOOD 0x04 /* Dongle has verified good RX checksums */ ++#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums: host->device */ ++#define BDC_FLAG_EVENT_MSG 0x08 /* Payload contains an event msg: device->host */ ++#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ ++#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ ++ ++/* priority field bitmap */ ++#define BDC_PRIORITY_MASK 0x07 ++#define BDC_PRIORITY_FC_MASK 0xf0 /* flow control info mask */ ++#define BDC_PRIORITY_FC_SHIFT 4 /* flow control info shift */ ++ ++/* flags2 field bitmap */ ++#define BDC_FLAG2_IF_MASK 0x0f /* interface index (host <-> dongle) */ ++#define BDC_FLAG2_IF_SHIFT 0 ++#define BDC_FLAG2_FC_FLAG 0x10 /* flag to indicate if pkt contains */ ++ /* FLOW CONTROL info only */ ++ ++/* version numbers */ ++#define BDC_PROTO_VER_1 1 /* Old Protocol version */ ++#define BDC_PROTO_VER 2 /* Protocol version */ ++ ++/* flags2.if field access macros */ ++#define BDC_GET_IF_IDX(hdr) \ ++ ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT)) ++#define BDC_SET_IF_IDX(hdr, idx) \ ++ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | ((idx) << BDC_FLAG2_IF_SHIFT))) ++ ++#define BDC_FLAG2_PAD_MASK 0xf0 ++#define BDC_FLAG_PAD_MASK 0x03 ++#define BDC_FLAG2_PAD_SHIFT 2 ++#define BDC_FLAG_PAD_SHIFT 0 ++#define BDC_FLAG2_PAD_IDX 0x3c ++#define BDC_FLAG_PAD_IDX 0x03 ++#define BDC_GET_PAD_LEN(hdr) \ ++ ((int)(((((hdr)->flags2) & BDC_FLAG2_PAD_MASK) >> BDC_FLAG2_PAD_SHIFT) | \ ++ ((((hdr)->flags) & BDC_FLAG_PAD_MASK) >> BDC_FLAG_PAD_SHIFT))) ++#define BDC_SET_PAD_LEN(hdr, idx) \ ++ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_PAD_MASK) | \ ++ (((idx) & BDC_FLAG2_PAD_IDX) << BDC_FLAG2_PAD_SHIFT))); \ ++ ((hdr)->flags = (((hdr)->flags & ~BDC_FLAG_PAD_MASK) | \ ++ (((idx) & BDC_FLAG_PAD_IDX) << BDC_FLAG_PAD_SHIFT))) ++ ++#endif /* _bcmcdc_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/bcmdefs.h b/drivers/net/wireless/ap6210/include/bcmdefs.h +new file mode 100755 +index 0000000..00906e3 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmdefs.h +@@ -0,0 +1,270 @@ ++/* ++ * Misc system wide definitions ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmdefs.h 316830 2012-02-23 20:29:22Z $ ++ */ ++ ++#ifndef _bcmdefs_h_ ++#define _bcmdefs_h_ ++ ++/* ++ * One doesn't need to include this file explicitly, gets included automatically if ++ * typedefs.h is included. ++ */ ++ ++/* Use BCM_REFERENCE to suppress warnings about intentionally-unused function ++ * arguments or local variables. ++ */ ++#define BCM_REFERENCE(data) ((void)(data)) ++ ++/* Compile-time assert can be used in place of ASSERT if the expression evaluates ++ * to a constant at compile time. ++ */ ++#define STATIC_ASSERT(expr) { \ ++ /* Make sure the expression is constant. */ \ ++ typedef enum { _STATIC_ASSERT_NOT_CONSTANT = (expr) } _static_assert_e; \ ++ /* Make sure the expression is true. */ \ ++ typedef char STATIC_ASSERT_FAIL[(expr) ? 1 : -1]; \ ++} ++ ++/* Reclaiming text and data : ++ * The following macros specify special linker sections that can be reclaimed ++ * after a system is considered 'up'. ++ * BCMATTACHFN is also used for detach functions (it's not worth having a BCMDETACHFN, ++ * as in most cases, the attach function calls the detach function to clean up on error). ++ */ ++ ++#define bcmreclaimed 0 ++#define _data _data ++#define _fn _fn ++#define BCMPREATTACHDATA(_data) _data ++#define BCMPREATTACHFN(_fn) _fn ++#define _data _data ++#define _fn _fn ++#define _fn _fn ++#define BCMNMIATTACHFN(_fn) _fn ++#define BCMNMIATTACHDATA(_data) _data ++#define CONST const ++#ifndef BCMFASTPATH ++#define BCMFASTPATH ++#define BCMFASTPATH_HOST ++#endif /* BCMFASTPATH */ ++ ++ ++/* Put some library data/code into ROM to reduce RAM requirements */ ++#define _data _data ++#define BCMROMDAT_NAME(_data) _data ++#define _fn _fn ++#define _fn _fn ++#define STATIC static ++#define BCMROMDAT_ARYSIZ(data) ARRAYSIZE(data) ++#define BCMROMDAT_SIZEOF(data) sizeof(data) ++#define BCMROMDAT_APATCH(data) ++#define BCMROMDAT_SPATCH(data) ++ ++/* Bus types */ ++#define SI_BUS 0 /* SOC Interconnect */ ++#define PCI_BUS 1 /* PCI target */ ++#define PCMCIA_BUS 2 /* PCMCIA target */ ++#define SDIO_BUS 3 /* SDIO target */ ++#define JTAG_BUS 4 /* JTAG */ ++#define USB_BUS 5 /* USB (does not support R/W REG) */ ++#define SPI_BUS 6 /* gSPI target */ ++#define RPC_BUS 7 /* RPC target */ ++ ++/* Allows size optimization for single-bus image */ ++#ifdef BCMBUSTYPE ++#define BUSTYPE(bus) (BCMBUSTYPE) ++#else ++#define BUSTYPE(bus) (bus) ++#endif ++ ++/* Allows size optimization for single-backplane image */ ++#ifdef BCMCHIPTYPE ++#define CHIPTYPE(bus) (BCMCHIPTYPE) ++#else ++#define CHIPTYPE(bus) (bus) ++#endif ++ ++ ++/* Allows size optimization for SPROM support */ ++#if defined(BCMSPROMBUS) ++#define SPROMBUS (BCMSPROMBUS) ++#elif defined(SI_PCMCIA_SROM) ++#define SPROMBUS (PCMCIA_BUS) ++#else ++#define SPROMBUS (PCI_BUS) ++#endif ++ ++/* Allows size optimization for single-chip image */ ++#ifdef BCMCHIPID ++#define CHIPID(chip) (BCMCHIPID) ++#else ++#define CHIPID(chip) (chip) ++#endif ++ ++#ifdef BCMCHIPREV ++#define CHIPREV(rev) (BCMCHIPREV) ++#else ++#define CHIPREV(rev) (rev) ++#endif ++ ++/* Defines for DMA Address Width - Shared between OSL and HNDDMA */ ++#define DMADDR_MASK_32 0x0 /* Address mask for 32-bits */ ++#define DMADDR_MASK_30 0xc0000000 /* Address mask for 30-bits */ ++#define DMADDR_MASK_0 0xffffffff /* Address mask for 0-bits (hi-part) */ ++ ++#define DMADDRWIDTH_30 30 /* 30-bit addressing capability */ ++#define DMADDRWIDTH_32 32 /* 32-bit addressing capability */ ++#define DMADDRWIDTH_63 63 /* 64-bit addressing capability */ ++#define DMADDRWIDTH_64 64 /* 64-bit addressing capability */ ++ ++#ifdef BCMDMA64OSL ++typedef struct { ++ uint32 loaddr; ++ uint32 hiaddr; ++} dma64addr_t; ++ ++typedef dma64addr_t dmaaddr_t; ++#define PHYSADDRHI(_pa) ((_pa).hiaddr) ++#define PHYSADDRHISET(_pa, _val) \ ++ do { \ ++ (_pa).hiaddr = (_val); \ ++ } while (0) ++#define PHYSADDRLO(_pa) ((_pa).loaddr) ++#define PHYSADDRLOSET(_pa, _val) \ ++ do { \ ++ (_pa).loaddr = (_val); \ ++ } while (0) ++ ++#else ++typedef unsigned long dmaaddr_t; ++#define PHYSADDRHI(_pa) (0) ++#define PHYSADDRHISET(_pa, _val) ++#define PHYSADDRLO(_pa) ((_pa)) ++#define PHYSADDRLOSET(_pa, _val) \ ++ do { \ ++ (_pa) = (_val); \ ++ } while (0) ++#endif /* BCMDMA64OSL */ ++ ++/* One physical DMA segment */ ++typedef struct { ++ dmaaddr_t addr; ++ uint32 length; ++} hnddma_seg_t; ++ ++#define MAX_DMA_SEGS 4 ++ ++ ++typedef struct { ++ void *oshdmah; /* Opaque handle for OSL to store its information */ ++ uint origsize; /* Size of the virtual packet */ ++ uint nsegs; ++ hnddma_seg_t segs[MAX_DMA_SEGS]; ++} hnddma_seg_map_t; ++ ++ ++/* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF). ++ * By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL. ++ * There is a compile time check in wlc.c which ensure that this value is at least as big ++ * as TXOFF. This value is used in dma_rxfill (hnddma.c). ++ */ ++ ++#if defined(BCM_RPC_NOCOPY) || defined(BCM_RCP_TXNOCOPY) ++/* add 40 bytes to allow for extra RPC header and info */ ++#define BCMEXTRAHDROOM 220 ++#else /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ ++#define BCMEXTRAHDROOM 172 ++#endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ ++ ++/* Packet alignment for most efficient SDIO (can change based on platform) */ ++#ifndef SDALIGN ++#define SDALIGN 32 ++#endif ++ ++/* Headroom required for dongle-to-host communication. Packets allocated ++ * locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should ++ * leave this much room in front for low-level message headers which may ++ * be needed to get across the dongle bus to the host. (These messages ++ * don't go over the network, so room for the full WL header above would ++ * be a waste.). ++*/ ++#define BCMDONGLEHDRSZ 12 ++#define BCMDONGLEPADSZ 16 ++ ++#define BCMDONGLEOVERHEAD (BCMDONGLEHDRSZ + BCMDONGLEPADSZ) ++ ++ ++#if defined(NO_BCMDBG_ASSERT) ++# undef BCMDBG_ASSERT ++# undef BCMASSERT_LOG ++#endif ++ ++#if defined(BCMASSERT_LOG) ++#define BCMASSERT_SUPPORT ++#endif ++ ++/* Macros for doing definition and get/set of bitfields ++ * Usage example, e.g. a three-bit field (bits 4-6): ++ * #define _M BITFIELD_MASK(3) ++ * #define _S 4 ++ * ... ++ * regval = R_REG(osh, ®s->regfoo); ++ * field = GFIELD(regval, ); ++ * regval = SFIELD(regval, , 1); ++ * W_REG(osh, ®s->regfoo, regval); ++ */ ++#define BITFIELD_MASK(width) \ ++ (((unsigned)1 << (width)) - 1) ++#define GFIELD(val, field) \ ++ (((val) >> field ## _S) & field ## _M) ++#define SFIELD(val, field, bits) \ ++ (((val) & (~(field ## _M << field ## _S))) | \ ++ ((unsigned)(bits) << field ## _S)) ++ ++/* define BCMSMALL to remove misc features for memory-constrained environments */ ++#ifdef BCMSMALL ++#undef BCMSPACE ++#define bcmspace FALSE /* if (bcmspace) code is discarded */ ++#else ++#define BCMSPACE ++#define bcmspace TRUE /* if (bcmspace) code is retained */ ++#endif ++ ++/* Max. nvram variable table size */ ++#define MAXSZ_NVRAM_VARS 4096 ++ ++ ++/* Max size for reclaimable NVRAM array */ ++#ifdef DL_NVRAM ++#define NVRAM_ARRAY_MAXSIZE DL_NVRAM ++#else ++#define NVRAM_ARRAY_MAXSIZE MAXSZ_NVRAM_VARS ++#endif /* DL_NVRAM */ ++ ++#ifdef BCMUSBDEV_ENABLED ++extern uint32 gFWID; ++#endif ++ ++#endif /* _bcmdefs_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/bcmdevs.h b/drivers/net/wireless/ap6210/include/bcmdevs.h +new file mode 100755 +index 0000000..c3dd89f +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmdevs.h +@@ -0,0 +1,503 @@ ++/* ++ * Broadcom device-specific manifest constants. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmdevs.h 329854 2012-04-27 01:42:28Z $ ++ */ ++ ++#ifndef _BCMDEVS_H ++#define _BCMDEVS_H ++ ++/* PCI vendor IDs */ ++#define VENDOR_EPIGRAM 0xfeda ++#define VENDOR_BROADCOM 0x14e4 ++#define VENDOR_3COM 0x10b7 ++#define VENDOR_NETGEAR 0x1385 ++#define VENDOR_DIAMOND 0x1092 ++#define VENDOR_INTEL 0x8086 ++#define VENDOR_DELL 0x1028 ++#define VENDOR_HP 0x103c ++#define VENDOR_HP_COMPAQ 0x0e11 ++#define VENDOR_APPLE 0x106b ++#define VENDOR_SI_IMAGE 0x1095 /* Silicon Image, used by Arasan SDIO Host */ ++#define VENDOR_BUFFALO 0x1154 /* Buffalo vendor id */ ++#define VENDOR_TI 0x104c /* Texas Instruments */ ++#define VENDOR_RICOH 0x1180 /* Ricoh */ ++#define VENDOR_JMICRON 0x197b ++ ++ ++/* PCMCIA vendor IDs */ ++#define VENDOR_BROADCOM_PCMCIA 0x02d0 ++ ++/* SDIO vendor IDs */ ++#define VENDOR_BROADCOM_SDIO 0x00BF ++ ++/* DONGLE VID/PIDs */ ++#define BCM_DNGL_VID 0x0a5c ++#define BCM_DNGL_BL_PID_4328 0xbd12 ++#define BCM_DNGL_BL_PID_4322 0xbd13 ++#define BCM_DNGL_BL_PID_4319 0xbd16 ++#define BCM_DNGL_BL_PID_43236 0xbd17 ++#define BCM_DNGL_BL_PID_4332 0xbd18 ++#define BCM_DNGL_BL_PID_4330 0xbd19 ++#define BCM_DNGL_BL_PID_4334 0xbd1a ++#define BCM_DNGL_BL_PID_43239 0xbd1b ++#define BCM_DNGL_BL_PID_4324 0xbd1c ++#define BCM_DNGL_BL_PID_4360 0xbd1d ++ ++#define BCM_DNGL_BDC_PID 0x0bdc ++#define BCM_DNGL_JTAG_PID 0x4a44 ++ ++/* HW USB BLOCK [CPULESS USB] PIDs */ ++#define BCM_HWUSB_PID_43239 43239 ++ ++/* PCI Device IDs */ ++#define BCM4210_DEVICE_ID 0x1072 /* never used */ ++#define BCM4230_DEVICE_ID 0x1086 /* never used */ ++#define BCM4401_ENET_ID 0x170c /* 4401b0 production enet cards */ ++#define BCM3352_DEVICE_ID 0x3352 /* bcm3352 device id */ ++#define BCM3360_DEVICE_ID 0x3360 /* bcm3360 device id */ ++#define BCM4211_DEVICE_ID 0x4211 ++#define BCM4231_DEVICE_ID 0x4231 ++#define BCM4303_D11B_ID 0x4303 /* 4303 802.11b */ ++#define BCM4311_D11G_ID 0x4311 /* 4311 802.11b/g id */ ++#define BCM4311_D11DUAL_ID 0x4312 /* 4311 802.11a/b/g id */ ++#define BCM4311_D11A_ID 0x4313 /* 4311 802.11a id */ ++#define BCM4328_D11DUAL_ID 0x4314 /* 4328/4312 802.11a/g id */ ++#define BCM4328_D11G_ID 0x4315 /* 4328/4312 802.11g id */ ++#define BCM4328_D11A_ID 0x4316 /* 4328/4312 802.11a id */ ++#define BCM4318_D11G_ID 0x4318 /* 4318 802.11b/g id */ ++#define BCM4318_D11DUAL_ID 0x4319 /* 4318 802.11a/b/g id */ ++#define BCM4318_D11A_ID 0x431a /* 4318 802.11a id */ ++#define BCM4325_D11DUAL_ID 0x431b /* 4325 802.11a/g id */ ++#define BCM4325_D11G_ID 0x431c /* 4325 802.11g id */ ++#define BCM4325_D11A_ID 0x431d /* 4325 802.11a id */ ++#define BCM4306_D11G_ID 0x4320 /* 4306 802.11g */ ++#define BCM4306_D11A_ID 0x4321 /* 4306 802.11a */ ++#define BCM4306_UART_ID 0x4322 /* 4306 uart */ ++#define BCM4306_V90_ID 0x4323 /* 4306 v90 codec */ ++#define BCM4306_D11DUAL_ID 0x4324 /* 4306 dual A+B */ ++#define BCM4306_D11G_ID2 0x4325 /* BCM4306_D11G_ID; INF w/loose binding war */ ++#define BCM4321_D11N_ID 0x4328 /* 4321 802.11n dualband id */ ++#define BCM4321_D11N2G_ID 0x4329 /* 4321 802.11n 2.4Ghz band id */ ++#define BCM4321_D11N5G_ID 0x432a /* 4321 802.11n 5Ghz band id */ ++#define BCM4322_D11N_ID 0x432b /* 4322 802.11n dualband device */ ++#define BCM4322_D11N2G_ID 0x432c /* 4322 802.11n 2.4GHz device */ ++#define BCM4322_D11N5G_ID 0x432d /* 4322 802.11n 5GHz device */ ++#define BCM4329_D11N_ID 0x432e /* 4329 802.11n dualband device */ ++#define BCM4329_D11N2G_ID 0x432f /* 4329 802.11n 2.4G device */ ++#define BCM4329_D11N5G_ID 0x4330 /* 4329 802.11n 5G device */ ++#define BCM4315_D11DUAL_ID 0x4334 /* 4315 802.11a/g id */ ++#define BCM4315_D11G_ID 0x4335 /* 4315 802.11g id */ ++#define BCM4315_D11A_ID 0x4336 /* 4315 802.11a id */ ++#define BCM4319_D11N_ID 0x4337 /* 4319 802.11n dualband device */ ++#define BCM4319_D11N2G_ID 0x4338 /* 4319 802.11n 2.4G device */ ++#define BCM4319_D11N5G_ID 0x4339 /* 4319 802.11n 5G device */ ++#define BCM43231_D11N2G_ID 0x4340 /* 43231 802.11n 2.4GHz device */ ++#define BCM43221_D11N2G_ID 0x4341 /* 43221 802.11n 2.4GHz device */ ++#define BCM43222_D11N_ID 0x4350 /* 43222 802.11n dualband device */ ++#define BCM43222_D11N2G_ID 0x4351 /* 43222 802.11n 2.4GHz device */ ++#define BCM43222_D11N5G_ID 0x4352 /* 43222 802.11n 5GHz device */ ++#define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ ++#define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db device */ ++#define BCM43226_D11N_ID 0x4354 /* 43226 802.11n dualband device */ ++#define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ ++#define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ ++#define BCM43236_D11N5G_ID 0x4348 /* 43236 802.11n 5GHz device */ ++#define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */ ++#define BCM43421_D11N_ID 0xA99D /* 43421 802.11n dualband device */ ++#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ ++#define BCM4330_D11N_ID 0x4360 /* 4330 802.11n dualband device */ ++#define BCM4330_D11N2G_ID 0x4361 /* 4330 802.11n 2.4G device */ ++#define BCM4330_D11N5G_ID 0x4362 /* 4330 802.11n 5G device */ ++#define BCM4336_D11N_ID 0x4343 /* 4336 802.11n 2.4GHz device */ ++#define BCM6362_D11N_ID 0x435f /* 6362 802.11n dualband device */ ++#define BCM4331_D11N_ID 0x4331 /* 4331 802.11n dualband id */ ++#define BCM4331_D11N2G_ID 0x4332 /* 4331 802.11n 2.4Ghz band id */ ++#define BCM4331_D11N5G_ID 0x4333 /* 4331 802.11n 5Ghz band id */ ++#define BCM43237_D11N_ID 0x4355 /* 43237 802.11n dualband device */ ++#define BCM43237_D11N5G_ID 0x4356 /* 43237 802.11n 5GHz device */ ++#define BCM43227_D11N2G_ID 0x4358 /* 43228 802.11n 2.4GHz device */ ++#define BCM43228_D11N_ID 0x4359 /* 43228 802.11n DualBand device */ ++#define BCM43228_D11N5G_ID 0x435a /* 43228 802.11n 5GHz device */ ++#define BCM43362_D11N_ID 0x4363 /* 43362 802.11n 2.4GHz device */ ++#define BCM43239_D11N_ID 0x4370 /* 43239 802.11n dualband device */ ++#define BCM4324_D11N_ID 0x4374 /* 4324 802.11n dualband device */ ++#define BCM43217_D11N2G_ID 0x43a9 /* 43217 802.11n 2.4GHz device */ ++#define BCM43131_D11N2G_ID 0x43aa /* 43131 802.11n 2.4GHz device */ ++#define BCM4314_D11N2G_ID 0x4364 /* 4314 802.11n 2.4G device */ ++#define BCM43142_D11N2G_ID 0x4365 /* 43142 802.11n 2.4G device */ ++#define BCM4334_D11N_ID 0x4380 /* 4334 802.11n dualband device */ ++#define BCM4334_D11N2G_ID 0x4381 /* 4334 802.11n 2.4G device */ ++#define BCM4334_D11N5G_ID 0x4382 /* 4334 802.11n 5G device */ ++#define BCM43341_D11N_ID 0x4386 /* 43341 802.11n dualband device */ ++#define BCM43341_D11N2G_ID 0x4387 /* 43341 802.11n 2.4G device */ ++#define BCM43341_D11N5G_ID 0x4388 /* 43341 802.11n 5G device */ ++#define BCM4360_D11AC_ID 0x43a0 ++#define BCM4360_D11AC2G_ID 0x43a1 ++#define BCM4360_D11AC5G_ID 0x43a2 ++ ++/* PCI Subsystem ID */ ++#define BCM943228HMB_SSID_VEN1 0x0607 ++#define BCM94313HMGBL_SSID_VEN1 0x0608 ++#define BCM94313HMG_SSID_VEN1 0x0609 ++ ++ ++#define BCM4335_D11AC_ID 0x43ae ++#define BCM4335_D11AC2G_ID 0x43af ++#define BCM4335_D11AC5G_ID 0x43b0 ++#define BCM4352_D11AC_ID 0x43b1 /* 4352 802.11ac dualband device */ ++#define BCM4352_D11AC2G_ID 0x43b2 /* 4352 802.11ac 2.4G device */ ++#define BCM4352_D11AC5G_ID 0x43b3 /* 4352 802.11ac 5G device */ ++ ++#define BCMGPRS_UART_ID 0x4333 /* Uart id used by 4306/gprs card */ ++#define BCMGPRS2_UART_ID 0x4344 /* Uart id used by 4306/gprs card */ ++#define FPGA_JTAGM_ID 0x43f0 /* FPGA jtagm device id */ ++#define BCM_JTAGM_ID 0x43f1 /* BCM jtagm device id */ ++#define SDIOH_FPGA_ID 0x43f2 /* sdio host fpga */ ++#define BCM_SDIOH_ID 0x43f3 /* BCM sdio host id */ ++#define SDIOD_FPGA_ID 0x43f4 /* sdio device fpga */ ++#define SPIH_FPGA_ID 0x43f5 /* PCI SPI Host Controller FPGA */ ++#define BCM_SPIH_ID 0x43f6 /* Synopsis SPI Host Controller */ ++#define MIMO_FPGA_ID 0x43f8 /* FPGA mimo minimacphy device id */ ++#define BCM_JTAGM2_ID 0x43f9 /* BCM alternate jtagm device id */ ++#define SDHCI_FPGA_ID 0x43fa /* Standard SDIO Host Controller FPGA */ ++#define BCM4402_ENET_ID 0x4402 /* 4402 enet */ ++#define BCM4402_V90_ID 0x4403 /* 4402 v90 codec */ ++#define BCM4410_DEVICE_ID 0x4410 /* bcm44xx family pci iline */ ++#define BCM4412_DEVICE_ID 0x4412 /* bcm44xx family pci enet */ ++#define BCM4430_DEVICE_ID 0x4430 /* bcm44xx family cardbus iline */ ++#define BCM4432_DEVICE_ID 0x4432 /* bcm44xx family cardbus enet */ ++#define BCM4704_ENET_ID 0x4706 /* 4704 enet (Use 47XX_ENET_ID instead!) */ ++#define BCM4710_DEVICE_ID 0x4710 /* 4710 primary function 0 */ ++#define BCM47XX_AUDIO_ID 0x4711 /* 47xx audio codec */ ++#define BCM47XX_V90_ID 0x4712 /* 47xx v90 codec */ ++#define BCM47XX_ENET_ID 0x4713 /* 47xx enet */ ++#define BCM47XX_EXT_ID 0x4714 /* 47xx external i/f */ ++#define BCM47XX_GMAC_ID 0x4715 /* 47xx Unimac based GbE */ ++#define BCM47XX_USBH_ID 0x4716 /* 47xx usb host */ ++#define BCM47XX_USBD_ID 0x4717 /* 47xx usb device */ ++#define BCM47XX_IPSEC_ID 0x4718 /* 47xx ipsec */ ++#define BCM47XX_ROBO_ID 0x4719 /* 47xx/53xx roboswitch core */ ++#define BCM47XX_USB20H_ID 0x471a /* 47xx usb 2.0 host */ ++#define BCM47XX_USB20D_ID 0x471b /* 47xx usb 2.0 device */ ++#define BCM47XX_ATA100_ID 0x471d /* 47xx parallel ATA */ ++#define BCM47XX_SATAXOR_ID 0x471e /* 47xx serial ATA & XOR DMA */ ++#define BCM47XX_GIGETH_ID 0x471f /* 47xx GbE (5700) */ ++#define BCM4712_MIPS_ID 0x4720 /* 4712 base devid */ ++#define BCM4716_DEVICE_ID 0x4722 /* 4716 base devid */ ++#define BCM47XX_SMBUS_EMU_ID 0x47fe /* 47xx emulated SMBus device */ ++#define BCM47XX_XOR_EMU_ID 0x47ff /* 47xx emulated XOR engine */ ++#define EPI41210_DEVICE_ID 0xa0fa /* bcm4210 */ ++#define EPI41230_DEVICE_ID 0xa10e /* bcm4230 */ ++#define JINVANI_SDIOH_ID 0x4743 /* Jinvani SDIO Gold Host */ ++#define BCM27XX_SDIOH_ID 0x2702 /* BCM27xx Standard SDIO Host */ ++#define PCIXX21_FLASHMEDIA_ID 0x803b /* TI PCI xx21 Standard Host Controller */ ++#define PCIXX21_SDIOH_ID 0x803c /* TI PCI xx21 Standard Host Controller */ ++#define R5C822_SDIOH_ID 0x0822 /* Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host */ ++#define JMICRON_SDIOH_ID 0x2381 /* JMicron Standard SDIO Host Controller */ ++ ++/* Chip IDs */ ++#define BCM4306_CHIP_ID 0x4306 /* 4306 chipcommon chipid */ ++#define BCM4311_CHIP_ID 0x4311 /* 4311 PCIe 802.11a/b/g */ ++#define BCM43111_CHIP_ID 43111 /* 43111 chipcommon chipid (OTP chipid) */ ++#define BCM43112_CHIP_ID 43112 /* 43112 chipcommon chipid (OTP chipid) */ ++#define BCM4312_CHIP_ID 0x4312 /* 4312 chipcommon chipid */ ++#define BCM4313_CHIP_ID 0x4313 /* 4313 chip id */ ++#define BCM43131_CHIP_ID 43131 /* 43131 chip id (OTP chipid) */ ++#define BCM4315_CHIP_ID 0x4315 /* 4315 chip id */ ++#define BCM4318_CHIP_ID 0x4318 /* 4318 chipcommon chipid */ ++#define BCM4319_CHIP_ID 0x4319 /* 4319 chip id */ ++#define BCM4320_CHIP_ID 0x4320 /* 4320 chipcommon chipid */ ++#define BCM4321_CHIP_ID 0x4321 /* 4321 chipcommon chipid */ ++#define BCM43217_CHIP_ID 43217 /* 43217 chip id (OTP chipid) */ ++#define BCM4322_CHIP_ID 0x4322 /* 4322 chipcommon chipid */ ++#define BCM43221_CHIP_ID 43221 /* 43221 chipcommon chipid (OTP chipid) */ ++#define BCM43222_CHIP_ID 43222 /* 43222 chipcommon chipid */ ++#define BCM43224_CHIP_ID 43224 /* 43224 chipcommon chipid */ ++#define BCM43225_CHIP_ID 43225 /* 43225 chipcommon chipid */ ++#define BCM43227_CHIP_ID 43227 /* 43227 chipcommon chipid */ ++#define BCM43228_CHIP_ID 43228 /* 43228 chipcommon chipid */ ++#define BCM43226_CHIP_ID 43226 /* 43226 chipcommon chipid */ ++#define BCM43231_CHIP_ID 43231 /* 43231 chipcommon chipid (OTP chipid) */ ++#define BCM43234_CHIP_ID 43234 /* 43234 chipcommon chipid */ ++#define BCM43235_CHIP_ID 43235 /* 43235 chipcommon chipid */ ++#define BCM43236_CHIP_ID 43236 /* 43236 chipcommon chipid */ ++#define BCM43237_CHIP_ID 43237 /* 43237 chipcommon chipid */ ++#define BCM43238_CHIP_ID 43238 /* 43238 chipcommon chipid */ ++#define BCM43239_CHIP_ID 43239 /* 43239 chipcommon chipid */ ++#define BCM43420_CHIP_ID 43420 /* 43222 chipcommon chipid (OTP, RBBU) */ ++#define BCM43421_CHIP_ID 43421 /* 43224 chipcommon chipid (OTP, RBBU) */ ++#define BCM43428_CHIP_ID 43428 /* 43228 chipcommon chipid (OTP, RBBU) */ ++#define BCM43431_CHIP_ID 43431 /* 4331 chipcommon chipid (OTP, RBBU) */ ++#define BCM43460_CHIP_ID 43460 /* 4360 chipcommon chipid (OTP, RBBU) */ ++#define BCM4325_CHIP_ID 0x4325 /* 4325 chip id */ ++#define BCM4328_CHIP_ID 0x4328 /* 4328 chip id */ ++#define BCM4329_CHIP_ID 0x4329 /* 4329 chipcommon chipid */ ++#define BCM4331_CHIP_ID 0x4331 /* 4331 chipcommon chipid */ ++#define BCM4336_CHIP_ID 0x4336 /* 4336 chipcommon chipid */ ++#define BCM43362_CHIP_ID 43362 /* 43362 chipcommon chipid */ ++#define BCM4330_CHIP_ID 0x4330 /* 4330 chipcommon chipid */ ++#define BCM6362_CHIP_ID 0x6362 /* 6362 chipcommon chipid */ ++#define BCM4314_CHIP_ID 0x4314 /* 4314 chipcommon chipid */ ++#define BCM43142_CHIP_ID 43142 /* 43142 chipcommon chipid */ ++#define BCM4324_CHIP_ID 0x4324 /* 4324 chipcommon chipid */ ++#define BCM43242_CHIP_ID 43242 /* 43242 chipcommon chipid */ ++#define BCM4334_CHIP_ID 0x4334 /* 4334 chipcommon chipid */ ++#define BCM4360_CHIP_ID 0x4360 /* 4360 chipcommon chipid */ ++#define BCM4352_CHIP_ID 0x4352 /* 4352 chipcommon chipid */ ++#define BCM43526_CHIP_ID 0xAA06 ++#define BCM43341_CHIP_ID 43341 /* 43341 chipcommon chipid */ ++#define BCM43342_CHIP_ID 43342 /* 43342 chipcommon chipid */ ++ ++#define BCM4335_CHIP_ID 0x4335 ++ ++#define BCM4342_CHIP_ID 4342 /* 4342 chipcommon chipid (OTP, RBBU) */ ++#define BCM4402_CHIP_ID 0x4402 /* 4402 chipid */ ++#define BCM4704_CHIP_ID 0x4704 /* 4704 chipcommon chipid */ ++#define BCM4706_CHIP_ID 0x5300 /* 4706 chipcommon chipid */ ++#define BCM4710_CHIP_ID 0x4710 /* 4710 chipid */ ++#define BCM4712_CHIP_ID 0x4712 /* 4712 chipcommon chipid */ ++#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */ ++#define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */ ++#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */ ++#define BCM4749_CHIP_ID 0x4749 /* 5357 chipcommon chipid (OTP, RBBU) */ ++#define BCM4785_CHIP_ID 0x4785 /* 4785 chipcommon chipid */ ++#define BCM5350_CHIP_ID 0x5350 /* 5350 chipcommon chipid */ ++#define BCM5352_CHIP_ID 0x5352 /* 5352 chipcommon chipid */ ++#define BCM5354_CHIP_ID 0x5354 /* 5354 chipcommon chipid */ ++#define BCM5365_CHIP_ID 0x5365 /* 5365 chipcommon chipid */ ++#define BCM5356_CHIP_ID 0x5356 /* 5356 chipcommon chipid */ ++#define BCM5357_CHIP_ID 0x5357 /* 5357 chipcommon chipid */ ++#define BCM53572_CHIP_ID 53572 /* 53572 chipcommon chipid */ ++ ++/* Package IDs */ ++#define BCM4303_PKG_ID 2 /* 4303 package id */ ++#define BCM4309_PKG_ID 1 /* 4309 package id */ ++#define BCM4712LARGE_PKG_ID 0 /* 340pin 4712 package id */ ++#define BCM4712SMALL_PKG_ID 1 /* 200pin 4712 package id */ ++#define BCM4712MID_PKG_ID 2 /* 225pin 4712 package id */ ++#define BCM4328USBD11G_PKG_ID 2 /* 4328 802.11g USB package id */ ++#define BCM4328USBDUAL_PKG_ID 3 /* 4328 802.11a/g USB package id */ ++#define BCM4328SDIOD11G_PKG_ID 4 /* 4328 802.11g SDIO package id */ ++#define BCM4328SDIODUAL_PKG_ID 5 /* 4328 802.11a/g SDIO package id */ ++#define BCM4329_289PIN_PKG_ID 0 /* 4329 289-pin package id */ ++#define BCM4329_182PIN_PKG_ID 1 /* 4329N 182-pin package id */ ++#define BCM5354E_PKG_ID 1 /* 5354E package id */ ++#define BCM4716_PKG_ID 8 /* 4716 package id */ ++#define BCM4717_PKG_ID 9 /* 4717 package id */ ++#define BCM4718_PKG_ID 10 /* 4718 package id */ ++#define BCM5356_PKG_NONMODE 1 /* 5356 package without nmode suppport */ ++#define BCM5358U_PKG_ID 8 /* 5358U package id */ ++#define BCM5358_PKG_ID 9 /* 5358 package id */ ++#define BCM47186_PKG_ID 10 /* 47186 package id */ ++#define BCM5357_PKG_ID 11 /* 5357 package id */ ++#define BCM5356U_PKG_ID 12 /* 5356U package id */ ++#define BCM53572_PKG_ID 8 /* 53572 package id */ ++#define BCM5357C0_PKG_ID 8 /* 5357c0 package id (the same as 53572) */ ++#define BCM47188_PKG_ID 9 /* 47188 package id */ ++#define BCM5358C0_PKG_ID 0xa /* 5358c0 package id */ ++#define BCM5356C0_PKG_ID 0xb /* 5356c0 package id */ ++#define BCM4331TT_PKG_ID 8 /* 4331 12x12 package id */ ++#define BCM4331TN_PKG_ID 9 /* 4331 12x9 package id */ ++#define BCM4331TNA0_PKG_ID 0xb /* 4331 12x9 package id */ ++#define BCM4706L_PKG_ID 1 /* 4706L package id */ ++ ++#define HDLSIM5350_PKG_ID 1 /* HDL simulator package id for a 5350 */ ++#define HDLSIM_PKG_ID 14 /* HDL simulator package id */ ++#define HWSIM_PKG_ID 15 /* Hardware simulator package id */ ++#define BCM43224_FAB_CSM 0x8 /* the chip is manufactured by CSM */ ++#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */ ++#define BCM4336_WLBGA_PKG_ID 0x8 ++#define BCM4330_WLBGA_PKG_ID 0x0 ++#define BCM4314PCIE_ARM_PKG_ID (8 | 0) /* 4314 QFN PCI package id, bit 3 tie high */ ++#define BCM4314SDIO_PKG_ID (8 | 1) /* 4314 QFN SDIO package id */ ++#define BCM4314PCIE_PKG_ID (8 | 2) /* 4314 QFN PCI (ARM-less) package id */ ++#define BCM4314SDIO_ARM_PKG_ID (8 | 3) /* 4314 QFN SDIO (ARM-less) package id */ ++#define BCM4314SDIO_FPBGA_PKG_ID (8 | 4) /* 4314 FpBGA SDIO package id */ ++#define BCM4314DEV_PKG_ID (8 | 6) /* 4314 Developement package id */ ++ ++#define PCIXX21_FLASHMEDIA0_ID 0x8033 /* TI PCI xx21 Standard Host Controller */ ++#define PCIXX21_SDIOH0_ID 0x8034 /* TI PCI xx21 Standard Host Controller */ ++ ++/* boardflags */ ++#define BFL_BTC2WIRE 0x00000001 /* old 2wire Bluetooth coexistence, OBSOLETE */ ++#define BFL_BTCOEX 0x00000001 /* Board supports BTCOEX */ ++#define BFL_PACTRL 0x00000002 /* Board has gpio 9 controlling the PA */ ++#define BFL_AIRLINEMODE 0x00000004 /* Board implements gpio 13 radio disable indication, UNUSED */ ++#define BFL_ADCDIV 0x00000008 /* Board has the rssi ADC divider */ ++#define BFL_RFPLL 0x00000008 /* ACPHY: Changing RFPLL BW to be 150 MHz */ ++#define BFL_ENETROBO 0x00000010 /* Board has robo switch or core */ ++#define BFL_NOPLLDOWN 0x00000020 /* Not ok to power down the chip pll and oscillator */ ++#define BFL_CCKHIPWR 0x00000040 /* Can do high-power CCK transmission */ ++#define BFL_ENETADM 0x00000080 /* Board has ADMtek switch */ ++#define BFL_ENETVLAN 0x00000100 /* Board has VLAN capability */ ++#define BFL_UNUSED 0x00000200 ++#define BFL_NOPCI 0x00000400 /* Board leaves PCI floating */ ++#define BFL_FEM 0x00000800 /* Board supports the Front End Module */ ++#define BFL_EXTLNA 0x00001000 /* Board has an external LNA in 2.4GHz band */ ++#define BFL_HGPA 0x00002000 /* Board has a high gain PA */ ++#define BFL_BTC2WIRE_ALTGPIO 0x00004000 /* Board's BTC 2wire is in the alternate gpios */ ++#define BFL_ALTIQ 0x00008000 /* Alternate I/Q settings */ ++#define BFL_NOPA 0x00010000 /* Board has no PA */ ++#define BFL_RSSIINV 0x00020000 /* Board's RSSI uses positive slope(not TSSI) */ ++#define BFL_PAREF 0x00040000 /* Board uses the PARef LDO */ ++#define BFL_3TSWITCH 0x00080000 /* Board uses a triple throw switch shared with BT */ ++#define BFL_PHASESHIFT 0x00100000 /* Board can support phase shifter */ ++#define BFL_BUCKBOOST 0x00200000 /* Power topology uses BUCKBOOST */ ++#define BFL_FEM_BT 0x00400000 /* Board has FEM and switch to share antenna w/ BT */ ++#define BFL_NOCBUCK 0x00800000 /* Power topology doesn't use CBUCK */ ++#define BFL_CCKFAVOREVM 0x01000000 /* Favor CCK EVM over spectral mask */ ++#define BFL_PALDO 0x02000000 /* Power topology uses PALDO */ ++#define BFL_LNLDO2_2P5 0x04000000 /* Select 2.5V as LNLDO2 output voltage */ ++#define BFL_FASTPWR 0x08000000 ++#define BFL_UCPWRCTL_MININDX 0x08000000 /* Enforce min power index to avoid FEM damage */ ++#define BFL_EXTLNA_5GHz 0x10000000 /* Board has an external LNA in 5GHz band */ ++#define BFL_TRSW_1by2 0x20000000 /* Board has 2 TRSW's in 1by2 designs */ ++#define BFL_LO_TRSW_R_5GHz 0x40000000 /* In 5G do not throw TRSW to T for clipLO gain */ ++#define BFL_ELNA_GAINDEF 0x80000000 /* Backoff InitGain based on elna_2g/5g field ++ * when this flag is set ++ */ ++#define BFL_EXTLNA_TX 0x20000000 /* Temp boardflag to indicate to */ ++ ++/* boardflags2 */ ++#define BFL2_RXBB_INT_REG_DIS 0x00000001 /* Board has an external rxbb regulator */ ++#define BFL2_APLL_WAR 0x00000002 /* Flag to implement alternative A-band PLL settings */ ++#define BFL2_TXPWRCTRL_EN 0x00000004 /* Board permits enabling TX Power Control */ ++#define BFL2_2X4_DIV 0x00000008 /* Board supports the 2X4 diversity switch */ ++#define BFL2_5G_PWRGAIN 0x00000010 /* Board supports 5G band power gain */ ++#define BFL2_PCIEWAR_OVR 0x00000020 /* Board overrides ASPM and Clkreq settings */ ++#define BFL2_CAESERS_BRD 0x00000040 /* Board is Caesers brd (unused by sw) */ ++#define BFL2_BTC3WIRE 0x00000080 /* Board support legacy 3 wire or 4 wire */ ++#define BFL2_BTCLEGACY 0x00000080 /* Board support legacy 3/4 wire, to replace ++ * BFL2_BTC3WIRE ++ */ ++#define BFL2_SKWRKFEM_BRD 0x00000100 /* 4321mcm93 board uses Skyworks FEM */ ++#define BFL2_SPUR_WAR 0x00000200 /* Board has a WAR for clock-harmonic spurs */ ++#define BFL2_GPLL_WAR 0x00000400 /* Flag to narrow G-band PLL loop b/w */ ++#define BFL2_TRISTATE_LED 0x00000800 /* Tri-state the LED */ ++#define BFL2_SINGLEANT_CCK 0x00001000 /* Tx CCK pkts on Ant 0 only */ ++#define BFL2_2G_SPUR_WAR 0x00002000 /* WAR to reduce and avoid clock-harmonic spurs in 2G */ ++#define BFL2_BPHY_ALL_TXCORES 0x00004000 /* Transmit bphy frames using all tx cores */ ++#define BFL2_FCC_BANDEDGE_WAR 0x00008000 /* Activates WAR to improve FCC bandedge performance */ ++#define BFL2_GPLL_WAR2 0x00010000 /* Flag to widen G-band PLL loop b/w */ ++#define BFL2_IPALVLSHIFT_3P3 0x00020000 ++#define BFL2_INTERNDET_TXIQCAL 0x00040000 /* Use internal envelope detector for TX IQCAL */ ++#define BFL2_XTALBUFOUTEN 0x00080000 /* Keep the buffered Xtal output from radio on */ ++ /* Most drivers will turn it off without this flag */ ++ /* to save power. */ ++ ++#define BFL2_ANAPACTRL_2G 0x00100000 /* 2G ext PAs are controlled by analog PA ctrl lines */ ++#define BFL2_ANAPACTRL_5G 0x00200000 /* 5G ext PAs are controlled by analog PA ctrl lines */ ++#define BFL2_ELNACTRL_TRSW_2G 0x00400000 /* AZW4329: 2G gmode_elna_gain controls TR Switch */ ++#define BFL2_BT_SHARE_ANT0 0x00800000 /* share core0 antenna with BT */ ++#define BFL2_TEMPSENSE_HIGHER 0x01000000 /* The tempsense threshold can sustain higher value ++ * than programmed. The exact delta is decided by ++ * driver per chip/boardtype. This can be used ++ * when tempsense qualification happens after shipment ++ */ ++#define BFL2_BTC3WIREONLY 0x02000000 /* standard 3 wire btc only. 4 wire not supported */ ++#define BFL2_PWR_NOMINAL 0x04000000 /* 0: power reduction on, 1: no power reduction */ ++#define BFL2_EXTLNA_PWRSAVE 0x08000000 /* boardflag to enable ucode to apply power save */ ++ /* ucode control of eLNA during Tx */ ++#define BFL2_4313_RADIOREG 0x10000000 ++ /* board rework */ ++#define BFL2_SDR_EN 0x20000000 /* SDR enabled or disabled */ ++ ++/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */ ++#define BOARD_GPIO_BTC3W_IN 0x850 /* bit 4 is RF_ACTIVE, bit 6 is STATUS, bit 11 is PRI */ ++#define BOARD_GPIO_BTC3W_OUT 0x020 /* bit 5 is TX_CONF */ ++#define BOARD_GPIO_BTCMOD_IN 0x010 /* bit 4 is the alternate BT Coexistence Input */ ++#define BOARD_GPIO_BTCMOD_OUT 0x020 /* bit 5 is the alternate BT Coexistence Out */ ++#define BOARD_GPIO_BTC_IN 0x080 /* bit 7 is BT Coexistence Input */ ++#define BOARD_GPIO_BTC_OUT 0x100 /* bit 8 is BT Coexistence Out */ ++#define BOARD_GPIO_PACTRL 0x200 /* bit 9 controls the PA on new 4306 boards */ ++#define BOARD_GPIO_12 0x1000 /* gpio 12 */ ++#define BOARD_GPIO_13 0x2000 /* gpio 13 */ ++#define BOARD_GPIO_BTC4_IN 0x0800 /* gpio 11, coex4, in */ ++#define BOARD_GPIO_BTC4_BT 0x2000 /* gpio 12, coex4, bt active */ ++#define BOARD_GPIO_BTC4_STAT 0x4000 /* gpio 14, coex4, status */ ++#define BOARD_GPIO_BTC4_WLAN 0x8000 /* gpio 15, coex4, wlan active */ ++#define BOARD_GPIO_1_WLAN_PWR 0x02 /* throttle WLAN power on X21 board */ ++#define BOARD_GPIO_3_WLAN_PWR 0x08 /* throttle WLAN power on X28 board */ ++#define BOARD_GPIO_4_WLAN_PWR 0x10 /* throttle WLAN power on X19 board */ ++ ++#define GPIO_BTC4W_OUT_4312 0x010 /* bit 4 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_43224 0x020 /* bit 5 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_43224_SHARED 0x0e0 /* bit 5 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_43225 0x0e0 /* bit 5 BT_IODISABLE, bit 6 SW_BT, bit 7 SW_WL */ ++#define GPIO_BTC4W_OUT_43421 0x020 /* bit 5 is BT_IODISABLE */ ++#define GPIO_BTC4W_OUT_4313 0x060 /* bit 5 SW_BT, bit 6 SW_WL */ ++#define GPIO_BTC4W_OUT_4331_SHARED 0x010 /* GPIO 4 */ ++ ++#define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */ ++#define PCI_CFG_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */ ++#define PCI_CFG_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal power-up */ ++#define PCI_CFG_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL power-down */ ++ ++/* power control defines */ ++#define PLL_DELAY 150 /* us pll on delay */ ++#define FREF_DELAY 200 /* us fref change delay */ ++#define MIN_SLOW_CLK 32 /* us Slow clock period */ ++#define XTAL_ON_DELAY 1000 /* us crystal power-on delay */ ++ ++ ++/* 43341 Boards */ ++#define BCM943341WLABGS_SSID 0x062d ++ ++/* # of GPIO pins */ ++#define GPIO_NUMPINS 32 ++ ++/* These values are used by dhd host driver. */ ++#define RDL_RAM_BASE_4319 0x60000000 ++#define RDL_RAM_BASE_4329 0x60000000 ++#define RDL_RAM_SIZE_4319 0x48000 ++#define RDL_RAM_SIZE_4329 0x48000 ++#define RDL_RAM_SIZE_43236 0x70000 ++#define RDL_RAM_BASE_43236 0x60000000 ++#define RDL_RAM_SIZE_4328 0x60000 ++#define RDL_RAM_BASE_4328 0x80000000 ++#define RDL_RAM_SIZE_4322 0x60000 ++#define RDL_RAM_BASE_4322 0x60000000 ++ ++/* generic defs for nvram "muxenab" bits */ ++#define MUXENAB_UART 0x00000001 ++#define MUXENAB_GPIO 0x00000002 ++#define MUXENAB_ERCX 0x00000004 /* External Radio BT coex */ ++#define MUXENAB_JTAG 0x00000008 ++#define MUXENAB_HOST_WAKE 0x00000010 /* configure GPIO for SDIO host_wake */ ++#define MUXENAB_I2S_EN 0x00000020 ++#define MUXENAB_I2S_MASTER 0x00000040 ++#define MUXENAB_I2S_FULL 0x00000080 ++#define MUXENAB_SFLASH 0x00000100 ++#define MUXENAB_RFSWCTRL0 0x00000200 ++#define MUXENAB_RFSWCTRL1 0x00000400 ++#define MUXENAB_RFSWCTRL2 0x00000800 ++#define MUXENAB_SECI 0x00001000 ++#define MUXENAB_BT_LEGACY 0x00002000 ++#define MUXENAB_HOST_WAKE1 0x00004000 /* configure alternative GPIO for SDIO host_wake */ ++ ++/* Boot flags */ ++#define FLASH_KERNEL_NFLASH 0x00000001 ++#define FLASH_BOOT_NFLASH 0x00000002 ++ ++#endif /* _BCMDEVS_H */ +diff --git a/drivers/net/wireless/ap6210/include/bcmendian.h b/drivers/net/wireless/ap6210/include/bcmendian.h +new file mode 100755 +index 0000000..0cf9145 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmendian.h +@@ -0,0 +1,299 @@ ++/* ++ * Byte order utilities ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmendian.h 241182 2011-02-17 21:50:03Z $ ++ * ++ * This file by default provides proper behavior on little-endian architectures. ++ * On big-endian architectures, IL_BIGENDIAN should be defined. ++ */ ++ ++#ifndef _BCMENDIAN_H_ ++#define _BCMENDIAN_H_ ++ ++#include ++ ++/* Reverse the bytes in a 16-bit value */ ++#define BCMSWAP16(val) \ ++ ((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) | \ ++ (((uint16)(val) & (uint16)0xff00U) >> 8))) ++ ++/* Reverse the bytes in a 32-bit value */ ++#define BCMSWAP32(val) \ ++ ((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) | \ ++ (((uint32)(val) & (uint32)0x0000ff00U) << 8) | \ ++ (((uint32)(val) & (uint32)0x00ff0000U) >> 8) | \ ++ (((uint32)(val) & (uint32)0xff000000U) >> 24))) ++ ++/* Reverse the two 16-bit halves of a 32-bit value */ ++#define BCMSWAP32BY16(val) \ ++ ((uint32)((((uint32)(val) & (uint32)0x0000ffffU) << 16) | \ ++ (((uint32)(val) & (uint32)0xffff0000U) >> 16))) ++ ++/* Byte swapping macros ++ * Host <=> Network (Big Endian) for 16- and 32-bit values ++ * Host <=> Little-Endian for 16- and 32-bit values ++ */ ++#ifndef hton16 ++#define HTON16(i) BCMSWAP16(i) ++#define hton16(i) bcmswap16(i) ++#define HTON32(i) BCMSWAP32(i) ++#define hton32(i) bcmswap32(i) ++#define NTOH16(i) BCMSWAP16(i) ++#define ntoh16(i) bcmswap16(i) ++#define NTOH32(i) BCMSWAP32(i) ++#define ntoh32(i) bcmswap32(i) ++#define LTOH16(i) (i) ++#define ltoh16(i) (i) ++#define LTOH32(i) (i) ++#define ltoh32(i) (i) ++#define HTOL16(i) (i) ++#define htol16(i) (i) ++#define HTOL32(i) (i) ++#define htol32(i) (i) ++#endif /* hton16 */ ++ ++#define ltoh16_buf(buf, i) ++#define htol16_buf(buf, i) ++ ++/* Unaligned loads and stores in host byte order */ ++#define load32_ua(a) ltoh32_ua(a) ++#define store32_ua(a, v) htol32_ua_store(v, a) ++#define load16_ua(a) ltoh16_ua(a) ++#define store16_ua(a, v) htol16_ua_store(v, a) ++ ++#define _LTOH16_UA(cp) ((cp)[0] | ((cp)[1] << 8)) ++#define _LTOH32_UA(cp) ((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24)) ++#define _NTOH16_UA(cp) (((cp)[0] << 8) | (cp)[1]) ++#define _NTOH32_UA(cp) (((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3]) ++ ++#define ltoh_ua(ptr) \ ++ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \ ++ sizeof(*(ptr)) == sizeof(uint16) ? _LTOH16_UA((const uint8 *)(ptr)) : \ ++ sizeof(*(ptr)) == sizeof(uint32) ? _LTOH32_UA((const uint8 *)(ptr)) : \ ++ *(uint8 *)0) ++ ++#define ntoh_ua(ptr) \ ++ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \ ++ sizeof(*(ptr)) == sizeof(uint16) ? _NTOH16_UA((const uint8 *)(ptr)) : \ ++ sizeof(*(ptr)) == sizeof(uint32) ? _NTOH32_UA((const uint8 *)(ptr)) : \ ++ *(uint8 *)0) ++ ++#ifdef __GNUC__ ++ ++/* GNU macro versions avoid referencing the argument multiple times, while also ++ * avoiding the -fno-inline used in ROM builds. ++ */ ++ ++#define bcmswap16(val) ({ \ ++ uint16 _val = (val); \ ++ BCMSWAP16(_val); \ ++}) ++ ++#define bcmswap32(val) ({ \ ++ uint32 _val = (val); \ ++ BCMSWAP32(_val); \ ++}) ++ ++#define bcmswap32by16(val) ({ \ ++ uint32 _val = (val); \ ++ BCMSWAP32BY16(_val); \ ++}) ++ ++#define bcmswap16_buf(buf, len) ({ \ ++ uint16 *_buf = (uint16 *)(buf); \ ++ uint _wds = (len) / 2; \ ++ while (_wds--) { \ ++ *_buf = bcmswap16(*_buf); \ ++ _buf++; \ ++ } \ ++}) ++ ++#define htol16_ua_store(val, bytes) ({ \ ++ uint16 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val & 0xff; \ ++ _bytes[1] = _val >> 8; \ ++}) ++ ++#define htol32_ua_store(val, bytes) ({ \ ++ uint32 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val & 0xff; \ ++ _bytes[1] = (_val >> 8) & 0xff; \ ++ _bytes[2] = (_val >> 16) & 0xff; \ ++ _bytes[3] = _val >> 24; \ ++}) ++ ++#define hton16_ua_store(val, bytes) ({ \ ++ uint16 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val >> 8; \ ++ _bytes[1] = _val & 0xff; \ ++}) ++ ++#define hton32_ua_store(val, bytes) ({ \ ++ uint32 _val = (val); \ ++ uint8 *_bytes = (uint8 *)(bytes); \ ++ _bytes[0] = _val >> 24; \ ++ _bytes[1] = (_val >> 16) & 0xff; \ ++ _bytes[2] = (_val >> 8) & 0xff; \ ++ _bytes[3] = _val & 0xff; \ ++}) ++ ++#define ltoh16_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _LTOH16_UA(_bytes); \ ++}) ++ ++#define ltoh32_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _LTOH32_UA(_bytes); \ ++}) ++ ++#define ntoh16_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _NTOH16_UA(_bytes); \ ++}) ++ ++#define ntoh32_ua(bytes) ({ \ ++ const uint8 *_bytes = (const uint8 *)(bytes); \ ++ _NTOH32_UA(_bytes); \ ++}) ++ ++#else /* !__GNUC__ */ ++ ++/* Inline versions avoid referencing the argument multiple times */ ++static INLINE uint16 ++bcmswap16(uint16 val) ++{ ++ return BCMSWAP16(val); ++} ++ ++static INLINE uint32 ++bcmswap32(uint32 val) ++{ ++ return BCMSWAP32(val); ++} ++ ++static INLINE uint32 ++bcmswap32by16(uint32 val) ++{ ++ return BCMSWAP32BY16(val); ++} ++ ++/* Reverse pairs of bytes in a buffer (not for high-performance use) */ ++/* buf - start of buffer of shorts to swap */ ++/* len - byte length of buffer */ ++static INLINE void ++bcmswap16_buf(uint16 *buf, uint len) ++{ ++ len = len / 2; ++ ++ while (len--) { ++ *buf = bcmswap16(*buf); ++ buf++; ++ } ++} ++ ++/* ++ * Store 16-bit value to unaligned little-endian byte array. ++ */ ++static INLINE void ++htol16_ua_store(uint16 val, uint8 *bytes) ++{ ++ bytes[0] = val & 0xff; ++ bytes[1] = val >> 8; ++} ++ ++/* ++ * Store 32-bit value to unaligned little-endian byte array. ++ */ ++static INLINE void ++htol32_ua_store(uint32 val, uint8 *bytes) ++{ ++ bytes[0] = val & 0xff; ++ bytes[1] = (val >> 8) & 0xff; ++ bytes[2] = (val >> 16) & 0xff; ++ bytes[3] = val >> 24; ++} ++ ++/* ++ * Store 16-bit value to unaligned network-(big-)endian byte array. ++ */ ++static INLINE void ++hton16_ua_store(uint16 val, uint8 *bytes) ++{ ++ bytes[0] = val >> 8; ++ bytes[1] = val & 0xff; ++} ++ ++/* ++ * Store 32-bit value to unaligned network-(big-)endian byte array. ++ */ ++static INLINE void ++hton32_ua_store(uint32 val, uint8 *bytes) ++{ ++ bytes[0] = val >> 24; ++ bytes[1] = (val >> 16) & 0xff; ++ bytes[2] = (val >> 8) & 0xff; ++ bytes[3] = val & 0xff; ++} ++ ++/* ++ * Load 16-bit value from unaligned little-endian byte array. ++ */ ++static INLINE uint16 ++ltoh16_ua(const void *bytes) ++{ ++ return _LTOH16_UA((const uint8 *)bytes); ++} ++ ++/* ++ * Load 32-bit value from unaligned little-endian byte array. ++ */ ++static INLINE uint32 ++ltoh32_ua(const void *bytes) ++{ ++ return _LTOH32_UA((const uint8 *)bytes); ++} ++ ++/* ++ * Load 16-bit value from unaligned big-(network-)endian byte array. ++ */ ++static INLINE uint16 ++ntoh16_ua(const void *bytes) ++{ ++ return _NTOH16_UA((const uint8 *)bytes); ++} ++ ++/* ++ * Load 32-bit value from unaligned big-(network-)endian byte array. ++ */ ++static INLINE uint32 ++ntoh32_ua(const void *bytes) ++{ ++ return _NTOH32_UA((const uint8 *)bytes); ++} ++ ++#endif /* !__GNUC__ */ ++#endif /* !_BCMENDIAN_H_ */ +diff --git a/drivers/net/wireless/ap6210/include/bcmpcispi.h b/drivers/net/wireless/ap6210/include/bcmpcispi.h +new file mode 100755 +index 0000000..44b263c +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmpcispi.h +@@ -0,0 +1,181 @@ ++/* ++ * Broadcom PCI-SPI Host Controller Register Definitions ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmpcispi.h 241182 2011-02-17 21:50:03Z $ ++ */ ++#ifndef _BCM_PCI_SPI_H ++#define _BCM_PCI_SPI_H ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++ ++typedef volatile struct { ++ uint32 spih_ctrl; /* 0x00 SPI Control Register */ ++ uint32 spih_stat; /* 0x04 SPI Status Register */ ++ uint32 spih_data; /* 0x08 SPI Data Register, 32-bits wide */ ++ uint32 spih_ext; /* 0x0C SPI Extension Register */ ++ uint32 PAD[4]; /* 0x10-0x1F PADDING */ ++ ++ uint32 spih_gpio_ctrl; /* 0x20 SPI GPIO Control Register */ ++ uint32 spih_gpio_data; /* 0x24 SPI GPIO Data Register */ ++ uint32 PAD[6]; /* 0x28-0x3F PADDING */ ++ ++ uint32 spih_int_edge; /* 0x40 SPI Interrupt Edge Register (0=Level, 1=Edge) */ ++ uint32 spih_int_pol; /* 0x44 SPI Interrupt Polarity Register (0=Active Low, */ ++ /* 1=Active High) */ ++ uint32 spih_int_mask; /* 0x48 SPI Interrupt Mask */ ++ uint32 spih_int_status; /* 0x4C SPI Interrupt Status */ ++ uint32 PAD[4]; /* 0x50-0x5F PADDING */ ++ ++ uint32 spih_hex_disp; /* 0x60 SPI 4-digit hex display value */ ++ uint32 spih_current_ma; /* 0x64 SPI SD card current consumption in mA */ ++ uint32 PAD[1]; /* 0x68 PADDING */ ++ uint32 spih_disp_sel; /* 0x6c SPI 4-digit hex display mode select (1=current) */ ++ uint32 PAD[4]; /* 0x70-0x7F PADDING */ ++ uint32 PAD[8]; /* 0x80-0x9F PADDING */ ++ uint32 PAD[8]; /* 0xA0-0xBF PADDING */ ++ uint32 spih_pll_ctrl; /* 0xC0 PLL Control Register */ ++ uint32 spih_pll_status; /* 0xC4 PLL Status Register */ ++ uint32 spih_xtal_freq; /* 0xC8 External Clock Frequency in units of 10000Hz */ ++ uint32 spih_clk_count; /* 0xCC External Clock Count Register */ ++ ++} spih_regs_t; ++ ++typedef volatile struct { ++ uint32 cfg_space[0x40]; /* 0x000-0x0FF PCI Configuration Space (Read Only) */ ++ uint32 P_IMG_CTRL0; /* 0x100 PCI Image0 Control Register */ ++ ++ uint32 P_BA0; /* 0x104 32 R/W PCI Image0 Base Address register */ ++ uint32 P_AM0; /* 0x108 32 R/W PCI Image0 Address Mask register */ ++ uint32 P_TA0; /* 0x10C 32 R/W PCI Image0 Translation Address register */ ++ uint32 P_IMG_CTRL1; /* 0x110 32 R/W PCI Image1 Control register */ ++ uint32 P_BA1; /* 0x114 32 R/W PCI Image1 Base Address register */ ++ uint32 P_AM1; /* 0x118 32 R/W PCI Image1 Address Mask register */ ++ uint32 P_TA1; /* 0x11C 32 R/W PCI Image1 Translation Address register */ ++ uint32 P_IMG_CTRL2; /* 0x120 32 R/W PCI Image2 Control register */ ++ uint32 P_BA2; /* 0x124 32 R/W PCI Image2 Base Address register */ ++ uint32 P_AM2; /* 0x128 32 R/W PCI Image2 Address Mask register */ ++ uint32 P_TA2; /* 0x12C 32 R/W PCI Image2 Translation Address register */ ++ uint32 P_IMG_CTRL3; /* 0x130 32 R/W PCI Image3 Control register */ ++ uint32 P_BA3; /* 0x134 32 R/W PCI Image3 Base Address register */ ++ uint32 P_AM3; /* 0x138 32 R/W PCI Image3 Address Mask register */ ++ uint32 P_TA3; /* 0x13C 32 R/W PCI Image3 Translation Address register */ ++ uint32 P_IMG_CTRL4; /* 0x140 32 R/W PCI Image4 Control register */ ++ uint32 P_BA4; /* 0x144 32 R/W PCI Image4 Base Address register */ ++ uint32 P_AM4; /* 0x148 32 R/W PCI Image4 Address Mask register */ ++ uint32 P_TA4; /* 0x14C 32 R/W PCI Image4 Translation Address register */ ++ uint32 P_IMG_CTRL5; /* 0x150 32 R/W PCI Image5 Control register */ ++ uint32 P_BA5; /* 0x154 32 R/W PCI Image5 Base Address register */ ++ uint32 P_AM5; /* 0x158 32 R/W PCI Image5 Address Mask register */ ++ uint32 P_TA5; /* 0x15C 32 R/W PCI Image5 Translation Address register */ ++ uint32 P_ERR_CS; /* 0x160 32 R/W PCI Error Control and Status register */ ++ uint32 P_ERR_ADDR; /* 0x164 32 R PCI Erroneous Address register */ ++ uint32 P_ERR_DATA; /* 0x168 32 R PCI Erroneous Data register */ ++ ++ uint32 PAD[5]; /* 0x16C-0x17F PADDING */ ++ ++ uint32 WB_CONF_SPC_BAR; /* 0x180 32 R WISHBONE Configuration Space Base Address */ ++ uint32 W_IMG_CTRL1; /* 0x184 32 R/W WISHBONE Image1 Control register */ ++ uint32 W_BA1; /* 0x188 32 R/W WISHBONE Image1 Base Address register */ ++ uint32 W_AM1; /* 0x18C 32 R/W WISHBONE Image1 Address Mask register */ ++ uint32 W_TA1; /* 0x190 32 R/W WISHBONE Image1 Translation Address reg */ ++ uint32 W_IMG_CTRL2; /* 0x194 32 R/W WISHBONE Image2 Control register */ ++ uint32 W_BA2; /* 0x198 32 R/W WISHBONE Image2 Base Address register */ ++ uint32 W_AM2; /* 0x19C 32 R/W WISHBONE Image2 Address Mask register */ ++ uint32 W_TA2; /* 0x1A0 32 R/W WISHBONE Image2 Translation Address reg */ ++ uint32 W_IMG_CTRL3; /* 0x1A4 32 R/W WISHBONE Image3 Control register */ ++ uint32 W_BA3; /* 0x1A8 32 R/W WISHBONE Image3 Base Address register */ ++ uint32 W_AM3; /* 0x1AC 32 R/W WISHBONE Image3 Address Mask register */ ++ uint32 W_TA3; /* 0x1B0 32 R/W WISHBONE Image3 Translation Address reg */ ++ uint32 W_IMG_CTRL4; /* 0x1B4 32 R/W WISHBONE Image4 Control register */ ++ uint32 W_BA4; /* 0x1B8 32 R/W WISHBONE Image4 Base Address register */ ++ uint32 W_AM4; /* 0x1BC 32 R/W WISHBONE Image4 Address Mask register */ ++ uint32 W_TA4; /* 0x1C0 32 R/W WISHBONE Image4 Translation Address reg */ ++ uint32 W_IMG_CTRL5; /* 0x1C4 32 R/W WISHBONE Image5 Control register */ ++ uint32 W_BA5; /* 0x1C8 32 R/W WISHBONE Image5 Base Address register */ ++ uint32 W_AM5; /* 0x1CC 32 R/W WISHBONE Image5 Address Mask register */ ++ uint32 W_TA5; /* 0x1D0 32 R/W WISHBONE Image5 Translation Address reg */ ++ uint32 W_ERR_CS; /* 0x1D4 32 R/W WISHBONE Error Control and Status reg */ ++ uint32 W_ERR_ADDR; /* 0x1D8 32 R WISHBONE Erroneous Address register */ ++ uint32 W_ERR_DATA; /* 0x1DC 32 R WISHBONE Erroneous Data register */ ++ uint32 CNF_ADDR; /* 0x1E0 32 R/W Configuration Cycle register */ ++ uint32 CNF_DATA; /* 0x1E4 32 R/W Configuration Cycle Generation Data reg */ ++ ++ uint32 INT_ACK; /* 0x1E8 32 R Interrupt Acknowledge register */ ++ uint32 ICR; /* 0x1EC 32 R/W Interrupt Control register */ ++ uint32 ISR; /* 0x1F0 32 R/W Interrupt Status register */ ++} spih_pciregs_t; ++ ++/* ++ * PCI Core interrupt enable and status bit definitions. ++ */ ++ ++/* PCI Core ICR Register bit definitions */ ++#define PCI_INT_PROP_EN (1 << 0) /* Interrupt Propagation Enable */ ++#define PCI_WB_ERR_INT_EN (1 << 1) /* Wishbone Error Interrupt Enable */ ++#define PCI_PCI_ERR_INT_EN (1 << 2) /* PCI Error Interrupt Enable */ ++#define PCI_PAR_ERR_INT_EN (1 << 3) /* Parity Error Interrupt Enable */ ++#define PCI_SYS_ERR_INT_EN (1 << 4) /* System Error Interrupt Enable */ ++#define PCI_SOFTWARE_RESET (1U << 31) /* Software reset of the PCI Core. */ ++ ++ ++/* PCI Core ISR Register bit definitions */ ++#define PCI_INT_PROP_ST (1 << 0) /* Interrupt Propagation Status */ ++#define PCI_WB_ERR_INT_ST (1 << 1) /* Wishbone Error Interrupt Status */ ++#define PCI_PCI_ERR_INT_ST (1 << 2) /* PCI Error Interrupt Status */ ++#define PCI_PAR_ERR_INT_ST (1 << 3) /* Parity Error Interrupt Status */ ++#define PCI_SYS_ERR_INT_ST (1 << 4) /* System Error Interrupt Status */ ++ ++ ++/* Registers on the Wishbone bus */ ++#define SPIH_CTLR_INTR (1 << 0) /* SPI Host Controller Core Interrupt */ ++#define SPIH_DEV_INTR (1 << 1) /* SPI Device Interrupt */ ++#define SPIH_WFIFO_INTR (1 << 2) /* SPI Tx FIFO Empty Intr (FPGA Rev >= 8) */ ++ ++/* GPIO Bit definitions */ ++#define SPIH_CS (1 << 0) /* SPI Chip Select (active low) */ ++#define SPIH_SLOT_POWER (1 << 1) /* SD Card Slot Power Enable */ ++#define SPIH_CARD_DETECT (1 << 2) /* SD Card Detect */ ++ ++/* SPI Status Register Bit definitions */ ++#define SPIH_STATE_MASK 0x30 /* SPI Transfer State Machine state mask */ ++#define SPIH_STATE_SHIFT 4 /* SPI Transfer State Machine state shift */ ++#define SPIH_WFFULL (1 << 3) /* SPI Write FIFO Full */ ++#define SPIH_WFEMPTY (1 << 2) /* SPI Write FIFO Empty */ ++#define SPIH_RFFULL (1 << 1) /* SPI Read FIFO Full */ ++#define SPIH_RFEMPTY (1 << 0) /* SPI Read FIFO Empty */ ++ ++#define SPIH_EXT_CLK (1U << 31) /* Use External Clock as PLL Clock source. */ ++ ++#define SPIH_PLL_NO_CLK (1 << 1) /* Set to 1 if the PLL's input clock is lost. */ ++#define SPIH_PLL_LOCKED (1 << 3) /* Set to 1 when the PLL is locked. */ ++ ++/* Spin bit loop bound check */ ++#define SPI_SPIN_BOUND 0xf4240 /* 1 million */ ++ ++#endif /* _BCM_PCI_SPI_H */ +diff --git a/drivers/net/wireless/ap6210/include/bcmperf.h b/drivers/net/wireless/ap6210/include/bcmperf.h +new file mode 100755 +index 0000000..7438307 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmperf.h +@@ -0,0 +1,36 @@ ++/* ++ * Performance counters software interface. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmperf.h 241182 2011-02-17 21:50:03Z $ ++ */ ++/* essai */ ++#ifndef _BCMPERF_H_ ++#define _BCMPERF_H_ ++/* get cache hits and misses */ ++#define BCMPERF_ENABLE_INSTRCOUNT() ++#define BCMPERF_ENABLE_ICACHE_MISS() ++#define BCMPERF_ENABLE_ICACHE_HIT() ++#define BCMPERF_GETICACHE_MISS(x) ((x) = 0) ++#define BCMPERF_GETICACHE_HIT(x) ((x) = 0) ++#define BCMPERF_GETINSTRCOUNT(x) ((x) = 0) ++#endif /* _BCMPERF_H_ */ +diff --git a/drivers/net/wireless/ap6210/include/bcmsdbus.h b/drivers/net/wireless/ap6210/include/bcmsdbus.h +new file mode 100755 +index 0000000..2fa706d +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmsdbus.h +@@ -0,0 +1,152 @@ ++/* ++ * Definitions for API from sdio common code (bcmsdh) to individual ++ * host controller drivers. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmsdbus.h 347614 2012-07-27 10:24:51Z $ ++ */ ++ ++#ifndef _sdio_api_h_ ++#define _sdio_api_h_ ++ ++ ++#define SDIOH_API_RC_SUCCESS (0x00) ++#define SDIOH_API_RC_FAIL (0x01) ++#define SDIOH_API_SUCCESS(status) (status == 0) ++ ++#define SDIOH_READ 0 /* Read request */ ++#define SDIOH_WRITE 1 /* Write request */ ++ ++#define SDIOH_DATA_FIX 0 /* Fixed addressing */ ++#define SDIOH_DATA_INC 1 /* Incremental addressing */ ++ ++#define SDIOH_CMD_TYPE_NORMAL 0 /* Normal command */ ++#define SDIOH_CMD_TYPE_APPEND 1 /* Append command */ ++#define SDIOH_CMD_TYPE_CUTTHRU 2 /* Cut-through command */ ++ ++#define SDIOH_DATA_PIO 0 /* PIO mode */ ++#define SDIOH_DATA_DMA 1 /* DMA mode */ ++ ++#ifdef BCMSDIOH_TXGLOM ++/* Max number of glommed pkts */ ++#define SDPCM_MAXGLOM_SIZE 10 ++#define SDPCM_DEFGLOM_SIZE 3 ++ ++#define SDPCM_TXGLOM_CPY 0 /* SDIO 2.0 should use copy mode */ ++#define SDPCM_TXGLOM_MDESC 1 /* SDIO 3.0 should use multi-desc mode */ ++#endif ++ ++ ++typedef int SDIOH_API_RC; ++ ++/* SDio Host structure */ ++typedef struct sdioh_info sdioh_info_t; ++ ++/* callback function, taking one arg */ ++typedef void (*sdioh_cb_fn_t)(void *); ++ ++/* attach, return handler on success, NULL if failed. ++ * The handler shall be provided by all subsequent calls. No local cache ++ * cfghdl points to the starting address of pci device mapped memory ++ */ ++extern sdioh_info_t * sdioh_attach(osl_t *osh, void *cfghdl, uint irq); ++extern SDIOH_API_RC sdioh_detach(osl_t *osh, sdioh_info_t *si); ++extern SDIOH_API_RC sdioh_interrupt_register(sdioh_info_t *si, sdioh_cb_fn_t fn, void *argh); ++extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *si); ++ ++/* query whether SD interrupt is enabled or not */ ++extern SDIOH_API_RC sdioh_interrupt_query(sdioh_info_t *si, bool *onoff); ++ ++/* enable or disable SD interrupt */ ++extern SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *si, bool enable_disable); ++ ++#if defined(DHD_DEBUG) ++extern bool sdioh_interrupt_pending(sdioh_info_t *si); ++#endif ++ ++/* read or write one byte using cmd52 */ ++extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *si, uint rw, uint fnc, uint addr, uint8 *byte); ++ ++/* read or write 2/4 bytes using cmd53 */ ++extern SDIOH_API_RC sdioh_request_word(sdioh_info_t *si, uint cmd_type, uint rw, uint fnc, ++ uint addr, uint32 *word, uint nbyte); ++ ++/* read or write any buffer using cmd53 */ ++extern SDIOH_API_RC sdioh_request_buffer(sdioh_info_t *si, uint pio_dma, uint fix_inc, ++ uint rw, uint fnc_num, uint32 addr, uint regwidth, uint32 buflen, uint8 *buffer, ++ void *pkt); ++ ++#ifdef BCMSDIOH_TXGLOM ++extern void sdioh_glom_post(sdioh_info_t *sd, uint8 *frame, uint len); ++extern void sdioh_glom_clear(sdioh_info_t *sd); ++extern uint sdioh_set_mode(sdioh_info_t *sd, uint mode); ++extern bool sdioh_glom_enabled(void); ++#else ++#define sdioh_glom_post(a, b, c) ++#define sdioh_glom_clear(a) ++#define sdioh_set_mode(a) (0) ++#define sdioh_glom_enabled() (FALSE) ++#endif ++ ++/* get cis data */ ++extern SDIOH_API_RC sdioh_cis_read(sdioh_info_t *si, uint fuc, uint8 *cis, uint32 length); ++ ++extern SDIOH_API_RC sdioh_cfg_read(sdioh_info_t *si, uint fuc, uint32 addr, uint8 *data); ++extern SDIOH_API_RC sdioh_cfg_write(sdioh_info_t *si, uint fuc, uint32 addr, uint8 *data); ++ ++/* query number of io functions */ ++extern uint sdioh_query_iofnum(sdioh_info_t *si); ++ ++/* handle iovars */ ++extern int sdioh_iovar_op(sdioh_info_t *si, const char *name, ++ void *params, int plen, void *arg, int len, bool set); ++ ++/* Issue abort to the specified function and clear controller as needed */ ++extern int sdioh_abort(sdioh_info_t *si, uint fnc); ++ ++/* Start and Stop SDIO without re-enumerating the SD card. */ ++extern int sdioh_start(sdioh_info_t *si, int stage); ++extern int sdioh_stop(sdioh_info_t *si); ++ ++/* Wait system lock free */ ++extern int sdioh_waitlockfree(sdioh_info_t *si); ++ ++/* Reset and re-initialize the device */ ++extern int sdioh_sdio_reset(sdioh_info_t *si); ++ ++/* Helper function */ ++void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh); ++ ++ ++ ++#if defined(BCMSDIOH_STD) ++ #define SDIOH_SLEEP_ENABLED ++#endif ++extern SDIOH_API_RC sdioh_sleep(sdioh_info_t *si, bool enab); ++ ++/* GPIO support */ ++extern SDIOH_API_RC sdioh_gpio_init(sdioh_info_t *sd); ++extern bool sdioh_gpioin(sdioh_info_t *sd, uint32 gpio); ++extern SDIOH_API_RC sdioh_gpioouten(sdioh_info_t *sd, uint32 gpio); ++extern SDIOH_API_RC sdioh_gpioout(sdioh_info_t *sd, uint32 gpio, bool enab); ++ ++#endif /* _sdio_api_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/bcmsdh.h b/drivers/net/wireless/ap6210/include/bcmsdh.h +new file mode 100755 +index 0000000..8e5a563 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmsdh.h +@@ -0,0 +1,247 @@ ++/* ++ * SDIO host client driver interface of Broadcom HNBU ++ * export functions to client drivers ++ * abstract OS and BUS specific details of SDIO ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmsdh.h 347614 2012-07-27 10:24:51Z $ ++ */ ++ ++/** ++ * @file bcmsdh.h ++ */ ++ ++#ifndef _bcmsdh_h_ ++#define _bcmsdh_h_ ++ ++#define BCMSDH_ERROR_VAL 0x0001 /* Error */ ++#define BCMSDH_INFO_VAL 0x0002 /* Info */ ++extern const uint bcmsdh_msglevel; ++ ++#define BCMSDH_ERROR(x) ++#define BCMSDH_INFO(x) ++ ++#if (defined(BCMSDIOH_STD) || defined(BCMSDIOH_BCM) || defined(BCMSDIOH_SPI)) ++#define BCMSDH_ADAPTER ++#endif /* BCMSDIO && (BCMSDIOH_STD || BCMSDIOH_BCM || BCMSDIOH_SPI) */ ++ ++/* forward declarations */ ++typedef struct bcmsdh_info bcmsdh_info_t; ++typedef void (*bcmsdh_cb_fn_t)(void *); ++ ++/* Attach and build an interface to the underlying SD host driver. ++ * - Allocates resources (structs, arrays, mem, OS handles, etc) needed by bcmsdh. ++ * - Returns the bcmsdh handle and virtual address base for register access. ++ * The returned handle should be used in all subsequent calls, but the bcmsh ++ * implementation may maintain a single "default" handle (e.g. the first or ++ * most recent one) to enable single-instance implementations to pass NULL. ++ */ ++ ++#if 0 && (NDISVER >= 0x0630) && 1 ++extern bcmsdh_info_t *bcmsdh_attach(osl_t *osh, void *cfghdl, ++ void **regsva, uint irq, shared_info_t *sh); ++#else ++extern bcmsdh_info_t *bcmsdh_attach(osl_t *osh, void *cfghdl, void **regsva, uint irq); ++#endif ++ ++/* Detach - freeup resources allocated in attach */ ++extern int bcmsdh_detach(osl_t *osh, void *sdh); ++ ++/* Query if SD device interrupts are enabled */ ++extern bool bcmsdh_intr_query(void *sdh); ++ ++/* Enable/disable SD interrupt */ ++extern int bcmsdh_intr_enable(void *sdh); ++extern int bcmsdh_intr_disable(void *sdh); ++ ++/* Register/deregister device interrupt handler. */ ++extern int bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh); ++extern int bcmsdh_intr_dereg(void *sdh); ++/* Enable/disable SD card interrupt forward */ ++extern void bcmsdh_intr_forward(void *sdh, bool pass); ++ ++#if defined(DHD_DEBUG) ++/* Query pending interrupt status from the host controller */ ++extern bool bcmsdh_intr_pending(void *sdh); ++#endif ++ ++/* Register a callback to be called if and when bcmsdh detects ++ * device removal. No-op in the case of non-removable/hardwired devices. ++ */ ++extern int bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh); ++ ++/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface). ++ * fn: function number ++ * addr: unmodified SDIO-space address ++ * data: data byte to write ++ * err: pointer to error code (or NULL) ++ */ ++extern uint8 bcmsdh_cfg_read(void *sdh, uint func, uint32 addr, int *err); ++extern void bcmsdh_cfg_write(void *sdh, uint func, uint32 addr, uint8 data, int *err); ++ ++/* Read/Write 4bytes from/to cfg space */ ++extern uint32 bcmsdh_cfg_read_word(void *sdh, uint fnc_num, uint32 addr, int *err); ++extern void bcmsdh_cfg_write_word(void *sdh, uint fnc_num, uint32 addr, uint32 data, int *err); ++ ++/* Read CIS content for specified function. ++ * fn: function whose CIS is being requested (0 is common CIS) ++ * cis: pointer to memory location to place results ++ * length: number of bytes to read ++ * Internally, this routine uses the values from the cis base regs (0x9-0xB) ++ * to form an SDIO-space address to read the data from. ++ */ ++extern int bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length); ++ ++/* Synchronous access to device (client) core registers via CMD53 to F1. ++ * addr: backplane address (i.e. >= regsva from attach) ++ * size: register width in bytes (2 or 4) ++ * data: data for register write ++ */ ++extern uint32 bcmsdh_reg_read(void *sdh, uint32 addr, uint size); ++extern uint32 bcmsdh_reg_write(void *sdh, uint32 addr, uint size, uint32 data); ++ ++/* set sb address window */ ++extern int bcmsdhsdio_set_sbaddr_window(void *sdh, uint32 address, bool force_set); ++ ++/* Indicate if last reg read/write failed */ ++extern bool bcmsdh_regfail(void *sdh); ++ ++/* Buffer transfer to/from device (client) core via cmd53. ++ * fn: function number ++ * addr: backplane address (i.e. >= regsva from attach) ++ * flags: backplane width, address increment, sync/async ++ * buf: pointer to memory data buffer ++ * nbytes: number of bytes to transfer to/from buf ++ * pkt: pointer to packet associated with buf (if any) ++ * complete: callback function for command completion (async only) ++ * handle: handle for completion callback (first arg in callback) ++ * Returns 0 or error code. ++ * NOTE: Async operation is not currently supported. ++ */ ++typedef void (*bcmsdh_cmplt_fn_t)(void *handle, int status, bool sync_waiting); ++extern int bcmsdh_send_buf(void *sdh, uint32 addr, uint fn, uint flags, ++ uint8 *buf, uint nbytes, void *pkt, ++ bcmsdh_cmplt_fn_t complete_fn, void *handle); ++extern int bcmsdh_recv_buf(void *sdh, uint32 addr, uint fn, uint flags, ++ uint8 *buf, uint nbytes, void *pkt, ++ bcmsdh_cmplt_fn_t complete_fn, void *handle); ++ ++extern void bcmsdh_glom_post(void *sdh, uint8 *frame, uint len); ++extern void bcmsdh_glom_clear(void *sdh); ++extern uint bcmsdh_set_mode(void *sdh, uint mode); ++extern bool bcmsdh_glom_enabled(void); ++/* Flags bits */ ++#define SDIO_REQ_4BYTE 0x1 /* Four-byte target (backplane) width (vs. two-byte) */ ++#define SDIO_REQ_FIXED 0x2 /* Fixed address (FIFO) (vs. incrementing address) */ ++#define SDIO_REQ_ASYNC 0x4 /* Async request (vs. sync request) */ ++#define SDIO_BYTE_MODE 0x8 /* Byte mode request(non-block mode) */ ++ ++/* Pending (non-error) return code */ ++#define BCME_PENDING 1 ++ ++/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only). ++ * rw: read or write (0/1) ++ * addr: direct SDIO address ++ * buf: pointer to memory data buffer ++ * nbytes: number of bytes to transfer to/from buf ++ * Returns 0 or error code. ++ */ ++extern int bcmsdh_rwdata(void *sdh, uint rw, uint32 addr, uint8 *buf, uint nbytes); ++ ++/* Issue an abort to the specified function */ ++extern int bcmsdh_abort(void *sdh, uint fn); ++ ++/* Start SDIO Host Controller communication */ ++extern int bcmsdh_start(void *sdh, int stage); ++ ++/* Stop SDIO Host Controller communication */ ++extern int bcmsdh_stop(void *sdh); ++ ++/* Wait system lock free */ ++extern int bcmsdh_waitlockfree(void *sdh); ++ ++/* Returns the "Device ID" of target device on the SDIO bus. */ ++extern int bcmsdh_query_device(void *sdh); ++ ++/* Returns the number of IO functions reported by the device */ ++extern uint bcmsdh_query_iofnum(void *sdh); ++ ++/* Miscellaneous knob tweaker. */ ++extern int bcmsdh_iovar_op(void *sdh, const char *name, ++ void *params, int plen, void *arg, int len, bool set); ++ ++/* Reset and reinitialize the device */ ++extern int bcmsdh_reset(bcmsdh_info_t *sdh); ++ ++/* helper functions */ ++ ++extern void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh); ++ ++/* callback functions */ ++typedef struct { ++ /* attach to device */ ++ void *(*attach)(uint16 vend_id, uint16 dev_id, uint16 bus, uint16 slot, ++ uint16 func, uint bustype, void * regsva, osl_t * osh, ++ void * param); ++ /* detach from device */ ++ void (*detach)(void *ch); ++} bcmsdh_driver_t; ++ ++/* platform specific/high level functions */ ++extern int bcmsdh_register(bcmsdh_driver_t *driver); ++extern void bcmsdh_unregister(void); ++extern bool bcmsdh_chipmatch(uint16 vendor, uint16 device); ++extern void bcmsdh_device_remove(void * sdh); ++ ++extern int bcmsdh_reg_sdio_notify(void* semaphore); ++extern void bcmsdh_unreg_sdio_notify(void); ++ ++extern int bcmsdh_set_drvdata(void * dhdp); ++ ++#if defined(OOB_INTR_ONLY) ++extern int bcmsdh_register_oob_intr(void * dhdp); ++extern void bcmsdh_unregister_oob_intr(void); ++extern void bcmsdh_oob_intr_set(bool enable); ++#endif ++#if defined(HW_OOB) ++void bcmsdh_config_hw_oob_intr(bcmsdh_info_t *sdh, uint chip); ++#endif ++ ++/* Function to pass device-status bits to DHD. */ ++extern uint32 bcmsdh_get_dstatus(void *sdh); ++ ++/* Function to return current window addr */ ++extern uint32 bcmsdh_cur_sbwad(void *sdh); ++ ++/* Function to pass chipid and rev to lower layers for controlling pr's */ ++extern void bcmsdh_chipinfo(void *sdh, uint32 chip, uint32 chiprev); ++ ++ ++extern int bcmsdh_sleep(void *sdh, bool enab); ++ ++/* GPIO support */ ++extern int bcmsdh_gpio_init(void *sd); ++extern bool bcmsdh_gpioin(void *sd, uint32 gpio); ++extern int bcmsdh_gpioouten(void *sd, uint32 gpio); ++extern int bcmsdh_gpioout(void *sd, uint32 gpio, bool enab); ++ ++#endif /* _bcmsdh_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/bcmsdh_sdmmc.h b/drivers/net/wireless/ap6210/include/bcmsdh_sdmmc.h +new file mode 100755 +index 0000000..a169588 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmsdh_sdmmc.h +@@ -0,0 +1,109 @@ ++/* ++ * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmsdh_sdmmc.h 366812 2012-11-05 13:49:32Z $ ++ */ ++ ++#ifndef __BCMSDH_SDMMC_H__ ++#define __BCMSDH_SDMMC_H__ ++ ++#define sd_sync_dma(sd, read, nbytes) ++#define sd_init_dma(sd) ++#define sd_ack_intr(sd) ++#define sd_wakeup(sd); ++ ++/* Allocate/init/free per-OS private data */ ++extern int sdioh_sdmmc_osinit(sdioh_info_t *sd); ++extern void sdioh_sdmmc_osfree(sdioh_info_t *sd); ++ ++#define BLOCK_SIZE_4318 64 ++#define BLOCK_SIZE_4328 512 ++ ++/* internal return code */ ++#define SUCCESS 0 ++#define ERROR 1 ++ ++/* private bus modes */ ++#define SDIOH_MODE_SD4 2 ++#define CLIENT_INTR 0x100 /* Get rid of this! */ ++ ++struct sdioh_info { ++ osl_t *osh; /* osh handler */ ++ bool client_intr_enabled; /* interrupt connnected flag */ ++ bool intr_handler_valid; /* client driver interrupt handler valid */ ++ sdioh_cb_fn_t intr_handler; /* registered interrupt handler */ ++ void *intr_handler_arg; /* argument to call interrupt handler */ ++ uint16 intmask; /* Current active interrupts */ ++ void *sdos_info; /* Pointer to per-OS private data */ ++ ++ uint irq; /* Client irq */ ++ int intrcount; /* Client interrupts */ ++ ++ bool sd_use_dma; /* DMA on CMD53 */ ++ bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */ ++ /* Must be on for sd_multiblock to be effective */ ++ bool use_client_ints; /* If this is false, make sure to restore */ ++ int sd_mode; /* SD1/SD4/SPI */ ++ int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */ ++ uint8 num_funcs; /* Supported funcs on client */ ++ uint32 com_cis_ptr; ++ uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; ++ ++#define SDIOH_SDMMC_MAX_SG_ENTRIES 32 ++ struct scatterlist sg_list[SDIOH_SDMMC_MAX_SG_ENTRIES]; ++ bool use_rxchain; ++}; ++ ++/************************************************************ ++ * Internal interfaces: per-port references into bcmsdh_sdmmc.c ++ */ ++ ++/* Global message bits */ ++extern uint sd_msglevel; ++ ++/* OS-independent interrupt handler */ ++extern bool check_client_intr(sdioh_info_t *sd); ++ ++/* Core interrupt enable/disable of device interrupts */ ++extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd); ++extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd); ++ ++ ++/************************************************************** ++ * Internal interfaces: bcmsdh_sdmmc.c references to per-port code ++ */ ++ ++/* Register mapping routines */ ++extern uint32 *sdioh_sdmmc_reg_map(osl_t *osh, int32 addr, int size); ++extern void sdioh_sdmmc_reg_unmap(osl_t *osh, int32 addr, int size); ++ ++/* Interrupt (de)registration routines */ ++extern int sdioh_sdmmc_register_irq(sdioh_info_t *sd, uint irq); ++extern void sdioh_sdmmc_free_irq(uint irq, sdioh_info_t *sd); ++ ++typedef struct _BCMSDH_SDMMC_INSTANCE { ++ sdioh_info_t *sd; ++ struct sdio_func *func[SDIOD_MAX_IOFUNCS]; ++} BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE; ++ ++#endif /* __BCMSDH_SDMMC_H__ */ +diff --git a/drivers/net/wireless/ap6210/include/bcmsdpcm.h b/drivers/net/wireless/ap6210/include/bcmsdpcm.h +new file mode 100755 +index 0000000..fb2ec3a +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmsdpcm.h +@@ -0,0 +1,281 @@ ++/* ++ * Broadcom SDIO/PCMCIA ++ * Software-specific definitions shared between device and host side ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmsdpcm.h 362722 2012-10-12 23:55:55Z $ ++ */ ++ ++#ifndef _bcmsdpcm_h_ ++#define _bcmsdpcm_h_ ++ ++/* ++ * Software allocation of To SB Mailbox resources ++ */ ++ ++/* intstatus bits */ ++#define I_SMB_NAK I_SMB_SW0 /* To SB Mailbox Frame NAK */ ++#define I_SMB_INT_ACK I_SMB_SW1 /* To SB Mailbox Host Interrupt ACK */ ++#define I_SMB_USE_OOB I_SMB_SW2 /* To SB Mailbox Use OOB Wakeup */ ++#define I_SMB_DEV_INT I_SMB_SW3 /* To SB Mailbox Miscellaneous Interrupt */ ++ ++#define I_TOSBMAIL (I_SMB_NAK | I_SMB_INT_ACK | I_SMB_USE_OOB | I_SMB_DEV_INT) ++ ++/* tosbmailbox bits corresponding to intstatus bits */ ++#define SMB_NAK (1 << 0) /* To SB Mailbox Frame NAK */ ++#define SMB_INT_ACK (1 << 1) /* To SB Mailbox Host Interrupt ACK */ ++#define SMB_USE_OOB (1 << 2) /* To SB Mailbox Use OOB Wakeup */ ++#define SMB_DEV_INT (1 << 3) /* To SB Mailbox Miscellaneous Interrupt */ ++#define SMB_MASK 0x0000000f /* To SB Mailbox Mask */ ++ ++/* tosbmailboxdata */ ++#define SMB_DATA_VERSION_MASK 0x00ff0000 /* host protocol version (sent with F2 enable) */ ++#define SMB_DATA_VERSION_SHIFT 16 /* host protocol version (sent with F2 enable) */ ++ ++/* ++ * Software allocation of To Host Mailbox resources ++ */ ++ ++/* intstatus bits */ ++#define I_HMB_FC_STATE I_HMB_SW0 /* To Host Mailbox Flow Control State */ ++#define I_HMB_FC_CHANGE I_HMB_SW1 /* To Host Mailbox Flow Control State Changed */ ++#define I_HMB_FRAME_IND I_HMB_SW2 /* To Host Mailbox Frame Indication */ ++#define I_HMB_HOST_INT I_HMB_SW3 /* To Host Mailbox Miscellaneous Interrupt */ ++ ++#define I_TOHOSTMAIL (I_HMB_FC_CHANGE | I_HMB_FRAME_IND | I_HMB_HOST_INT) ++ ++/* tohostmailbox bits corresponding to intstatus bits */ ++#define HMB_FC_ON (1 << 0) /* To Host Mailbox Flow Control State */ ++#define HMB_FC_CHANGE (1 << 1) /* To Host Mailbox Flow Control State Changed */ ++#define HMB_FRAME_IND (1 << 2) /* To Host Mailbox Frame Indication */ ++#define HMB_HOST_INT (1 << 3) /* To Host Mailbox Miscellaneous Interrupt */ ++#define HMB_MASK 0x0000000f /* To Host Mailbox Mask */ ++ ++/* tohostmailboxdata */ ++#define HMB_DATA_NAKHANDLED 0x01 /* we're ready to retransmit NAK'd frame to host */ ++#define HMB_DATA_DEVREADY 0x02 /* we're ready to to talk to host after enable */ ++#define HMB_DATA_FC 0x04 /* per prio flowcontrol update flag to host */ ++#define HMB_DATA_FWREADY 0x08 /* firmware is ready for protocol activity */ ++#define HMB_DATA_FWHALT 0x10 /* firmware has halted operation */ ++ ++#define HMB_DATA_FCDATA_MASK 0xff000000 /* per prio flowcontrol data */ ++#define HMB_DATA_FCDATA_SHIFT 24 /* per prio flowcontrol data */ ++ ++#define HMB_DATA_VERSION_MASK 0x00ff0000 /* device protocol version (with devready) */ ++#define HMB_DATA_VERSION_SHIFT 16 /* device protocol version (with devready) */ ++ ++/* ++ * Software-defined protocol header ++ */ ++ ++/* Current protocol version */ ++#define SDPCM_PROT_VERSION 4 ++ ++/* SW frame header */ ++#define SDPCM_SEQUENCE_MASK 0x000000ff /* Sequence Number Mask */ ++#define SDPCM_PACKET_SEQUENCE(p) (((uint8 *)p)[0] & 0xff) /* p starts w/SW Header */ ++ ++#define SDPCM_CHANNEL_MASK 0x00000f00 /* Channel Number Mask */ ++#define SDPCM_CHANNEL_SHIFT 8 /* Channel Number Shift */ ++#define SDPCM_PACKET_CHANNEL(p) (((uint8 *)p)[1] & 0x0f) /* p starts w/SW Header */ ++ ++#define SDPCM_FLAGS_MASK 0x0000f000 /* Mask of flag bits */ ++#define SDPCM_FLAGS_SHIFT 12 /* Flag bits shift */ ++#define SDPCM_PACKET_FLAGS(p) ((((uint8 *)p)[1] & 0xf0) >> 4) /* p starts w/SW Header */ ++ ++/* Next Read Len: lookahead length of next frame, in 16-byte units (rounded up) */ ++#define SDPCM_NEXTLEN_MASK 0x00ff0000 /* Next Read Len Mask */ ++#define SDPCM_NEXTLEN_SHIFT 16 /* Next Read Len Shift */ ++#define SDPCM_NEXTLEN_VALUE(p) ((((uint8 *)p)[2] & 0xff) << 4) /* p starts w/SW Header */ ++#define SDPCM_NEXTLEN_OFFSET 2 ++ ++/* Data Offset from SOF (HW Tag, SW Tag, Pad) */ ++#define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */ ++#define SDPCM_DOFFSET_VALUE(p) (((uint8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff) ++#define SDPCM_DOFFSET_MASK 0xff000000 ++#define SDPCM_DOFFSET_SHIFT 24 ++ ++#define SDPCM_FCMASK_OFFSET 4 /* Flow control */ ++#define SDPCM_FCMASK_VALUE(p) (((uint8 *)p)[SDPCM_FCMASK_OFFSET ] & 0xff) ++#define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */ ++#define SDPCM_WINDOW_VALUE(p) (((uint8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff) ++#define SDPCM_VERSION_OFFSET 6 /* Version # */ ++#define SDPCM_VERSION_VALUE(p) (((uint8 *)p)[SDPCM_VERSION_OFFSET] & 0xff) ++#define SDPCM_UNUSED_OFFSET 7 /* Spare */ ++#define SDPCM_UNUSED_VALUE(p) (((uint8 *)p)[SDPCM_UNUSED_OFFSET] & 0xff) ++ ++#define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */ ++ ++/* logical channel numbers */ ++#define SDPCM_CONTROL_CHANNEL 0 /* Control Request/Response Channel Id */ ++#define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */ ++#define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */ ++#define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets (superframes) */ ++#define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */ ++#define SDPCM_MAX_CHANNEL 15 ++ ++#define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for eight-bit frame seq number */ ++ ++#define SDPCM_FLAG_RESVD0 0x01 ++#define SDPCM_FLAG_RESVD1 0x02 ++#define SDPCM_FLAG_GSPI_TXENAB 0x04 ++#define SDPCM_FLAG_GLOMDESC 0x08 /* Superframe descriptor mask */ ++ ++/* For GLOM_CHANNEL frames, use a flag to indicate descriptor frame */ ++#define SDPCM_GLOMDESC_FLAG (SDPCM_FLAG_GLOMDESC << SDPCM_FLAGS_SHIFT) ++ ++#define SDPCM_GLOMDESC(p) (((uint8 *)p)[1] & 0x80) ++ ++/* For TEST_CHANNEL packets, define another 4-byte header */ ++#define SDPCM_TEST_HDRLEN 4 /* Generally: Cmd(1), Ext(1), Len(2); ++ * Semantics of Ext byte depend on command. ++ * Len is current or requested frame length, not ++ * including test header; sent little-endian. ++ */ ++#define SDPCM_TEST_PKT_CNT_FLD_LEN 4 /* Packet count filed legth */ ++#define SDPCM_TEST_DISCARD 0x01 /* Receiver discards. Ext is a pattern id. */ ++#define SDPCM_TEST_ECHOREQ 0x02 /* Echo request. Ext is a pattern id. */ ++#define SDPCM_TEST_ECHORSP 0x03 /* Echo response. Ext is a pattern id. */ ++#define SDPCM_TEST_BURST 0x04 /* Receiver to send a burst. Ext is a frame count ++ * (Backward compatabilty) Set frame count in a ++ * 4 byte filed adjacent to the HDR ++ */ ++#define SDPCM_TEST_SEND 0x05 /* Receiver sets send mode. Ext is boolean on/off ++ * Set frame count in a 4 byte filed adjacent to ++ * the HDR ++ */ ++ ++/* Handy macro for filling in datagen packets with a pattern */ ++#define SDPCM_TEST_FILL(byteno, id) ((uint8)(id + byteno)) ++ ++/* ++ * Software counters (first part matches hardware counters) ++ */ ++ ++typedef volatile struct { ++ uint32 cmd52rd; /* Cmd52RdCount, SDIO: cmd52 reads */ ++ uint32 cmd52wr; /* Cmd52WrCount, SDIO: cmd52 writes */ ++ uint32 cmd53rd; /* Cmd53RdCount, SDIO: cmd53 reads */ ++ uint32 cmd53wr; /* Cmd53WrCount, SDIO: cmd53 writes */ ++ uint32 abort; /* AbortCount, SDIO: aborts */ ++ uint32 datacrcerror; /* DataCrcErrorCount, SDIO: frames w/CRC error */ ++ uint32 rdoutofsync; /* RdOutOfSyncCount, SDIO/PCMCIA: Rd Frm out of sync */ ++ uint32 wroutofsync; /* RdOutOfSyncCount, SDIO/PCMCIA: Wr Frm out of sync */ ++ uint32 writebusy; /* WriteBusyCount, SDIO: device asserted "busy" */ ++ uint32 readwait; /* ReadWaitCount, SDIO: no data ready for a read cmd */ ++ uint32 readterm; /* ReadTermCount, SDIO: read frame termination cmds */ ++ uint32 writeterm; /* WriteTermCount, SDIO: write frames termination cmds */ ++ uint32 rxdescuflo; /* receive descriptor underflows */ ++ uint32 rxfifooflo; /* receive fifo overflows */ ++ uint32 txfifouflo; /* transmit fifo underflows */ ++ uint32 runt; /* runt (too short) frames recv'd from bus */ ++ uint32 badlen; /* frame's rxh len does not match its hw tag len */ ++ uint32 badcksum; /* frame's hw tag chksum doesn't agree with len value */ ++ uint32 seqbreak; /* break in sequence # space from one rx frame to the next */ ++ uint32 rxfcrc; /* frame rx header indicates crc error */ ++ uint32 rxfwoos; /* frame rx header indicates write out of sync */ ++ uint32 rxfwft; /* frame rx header indicates write frame termination */ ++ uint32 rxfabort; /* frame rx header indicates frame aborted */ ++ uint32 woosint; /* write out of sync interrupt */ ++ uint32 roosint; /* read out of sync interrupt */ ++ uint32 rftermint; /* read frame terminate interrupt */ ++ uint32 wftermint; /* write frame terminate interrupt */ ++} sdpcmd_cnt_t; ++ ++/* ++ * Register Access Macros ++ */ ++ ++#define SDIODREV_IS(var, val) ((var) == (val)) ++#define SDIODREV_GE(var, val) ((var) >= (val)) ++#define SDIODREV_GT(var, val) ((var) > (val)) ++#define SDIODREV_LT(var, val) ((var) < (val)) ++#define SDIODREV_LE(var, val) ((var) <= (val)) ++ ++#define SDIODDMAREG32(h, dir, chnl) \ ++ ((dir) == DMA_TX ? \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].xmt) : \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].rcv)) ++ ++#define SDIODDMAREG64(h, dir, chnl) \ ++ ((dir) == DMA_TX ? \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].xmt) : \ ++ (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].rcv)) ++ ++#define SDIODDMAREG(h, dir, chnl) \ ++ (SDIODREV_LT((h)->corerev, 1) ? \ ++ SDIODDMAREG32((h), (dir), (chnl)) : \ ++ SDIODDMAREG64((h), (dir), (chnl))) ++ ++#define PCMDDMAREG(h, dir, chnl) \ ++ ((dir) == DMA_TX ? \ ++ (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.xmt) : \ ++ (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.rcv)) ++ ++#define SDPCMDMAREG(h, dir, chnl, coreid) \ ++ ((coreid) == SDIOD_CORE_ID ? \ ++ SDIODDMAREG(h, dir, chnl) : \ ++ PCMDDMAREG(h, dir, chnl)) ++ ++#define SDIODFIFOREG(h, corerev) \ ++ (SDIODREV_LT((corerev), 1) ? \ ++ ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod32.dmafifo)) : \ ++ ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod64.dmafifo))) ++ ++#define PCMDFIFOREG(h) \ ++ ((dma32diag_t *)(uintptr)&((h)->regs->dma.pcm32.dmafifo)) ++ ++#define SDPCMFIFOREG(h, coreid, corerev) \ ++ ((coreid) == SDIOD_CORE_ID ? \ ++ SDIODFIFOREG(h, corerev) : \ ++ PCMDFIFOREG(h)) ++ ++/* ++ * Shared structure between dongle and the host. ++ * The structure contains pointers to trap or assert information. ++ */ ++#define SDPCM_SHARED_VERSION 0x0001 ++#define SDPCM_SHARED_VERSION_MASK 0x00FF ++#define SDPCM_SHARED_ASSERT_BUILT 0x0100 ++#define SDPCM_SHARED_ASSERT 0x0200 ++#define SDPCM_SHARED_TRAP 0x0400 ++#define SDPCM_SHARED_IN_BRPT 0x0800 ++#define SDPCM_SHARED_SET_BRPT 0x1000 ++#define SDPCM_SHARED_PENDING_BRPT 0x2000 ++ ++typedef struct { ++ uint32 flags; ++ uint32 trap_addr; ++ uint32 assert_exp_addr; ++ uint32 assert_file_addr; ++ uint32 assert_line; ++ uint32 console_addr; /* Address of hndrte_cons_t */ ++ uint32 msgtrace_addr; ++ uint32 brpt_addr; ++} sdpcm_shared_t; ++ ++extern sdpcm_shared_t sdpcm_shared; ++ ++/* Function can be used to notify host of FW halt */ ++extern void sdpcmd_fwhalt(void); ++ ++#endif /* _bcmsdpcm_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/bcmsdspi.h b/drivers/net/wireless/ap6210/include/bcmsdspi.h +new file mode 100755 +index 0000000..9a7496b +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmsdspi.h +@@ -0,0 +1,119 @@ ++/* ++ * SD-SPI Protocol Conversion - BCMSDH->SPI Translation Layer ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmsdspi.h 294363 2011-11-06 23:02:20Z $ ++ */ ++#ifndef _BCM_SD_SPI_H ++#define _BCM_SD_SPI_H ++ ++#define BLOCK_SIZE_4318 64 ++#define BLOCK_SIZE_4328 512 ++ ++/* internal return code */ ++#define SUCCESS 0 ++#undef ERROR ++#define ERROR 1 ++ ++/* private bus modes */ ++#define SDIOH_MODE_SPI 0 ++ ++#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */ ++#define USE_MULTIBLOCK 0x4 ++ ++struct sdioh_info { ++ uint cfg_bar; /* pci cfg address for bar */ ++ uint32 caps; /* cached value of capabilities reg */ ++ uint bar0; /* BAR0 for PCI Device */ ++ osl_t *osh; /* osh handler */ ++ void *controller; /* Pointer to SPI Controller's private data struct */ ++ ++ uint lockcount; /* nest count of sdspi_lock() calls */ ++ bool client_intr_enabled; /* interrupt connnected flag */ ++ bool intr_handler_valid; /* client driver interrupt handler valid */ ++ sdioh_cb_fn_t intr_handler; /* registered interrupt handler */ ++ void *intr_handler_arg; /* argument to call interrupt handler */ ++ bool initialized; /* card initialized */ ++ uint32 target_dev; /* Target device ID */ ++ uint32 intmask; /* Current active interrupts */ ++ void *sdos_info; /* Pointer to per-OS private data */ ++ ++ uint32 controller_type; /* Host controller type */ ++ uint8 version; /* Host Controller Spec Compliance Version */ ++ uint irq; /* Client irq */ ++ uint32 intrcount; /* Client interrupts */ ++ uint32 local_intrcount; /* Controller interrupts */ ++ bool host_init_done; /* Controller initted */ ++ bool card_init_done; /* Client SDIO interface initted */ ++ bool polled_mode; /* polling for command completion */ ++ ++ bool sd_use_dma; /* DMA on CMD53 */ ++ bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */ ++ /* Must be on for sd_multiblock to be effective */ ++ bool use_client_ints; /* If this is false, make sure to restore */ ++ bool got_hcint; /* Host Controller interrupt. */ ++ /* polling hack in wl_linux.c:wl_timer() */ ++ int adapter_slot; /* Maybe dealing with multiple slots/controllers */ ++ int sd_mode; /* SD1/SD4/SPI */ ++ int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */ ++ uint32 data_xfer_count; /* Current register transfer size */ ++ uint32 cmd53_wr_data; /* Used to pass CMD53 write data */ ++ uint32 card_response; /* Used to pass back response status byte */ ++ uint32 card_rsp_data; /* Used to pass back response data word */ ++ uint16 card_rca; /* Current Address */ ++ uint8 num_funcs; /* Supported funcs on client */ ++ uint32 com_cis_ptr; ++ uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; ++ void *dma_buf; ++ ulong dma_phys; ++ int r_cnt; /* rx count */ ++ int t_cnt; /* tx_count */ ++}; ++ ++/************************************************************ ++ * Internal interfaces: per-port references into bcmsdspi.c ++ */ ++ ++/* Global message bits */ ++extern uint sd_msglevel; ++ ++/************************************************************** ++ * Internal interfaces: bcmsdspi.c references to per-port code ++ */ ++ ++/* Register mapping routines */ ++extern uint32 *spi_reg_map(osl_t *osh, uintptr addr, int size); ++extern void spi_reg_unmap(osl_t *osh, uintptr addr, int size); ++ ++/* Interrupt (de)registration routines */ ++extern int spi_register_irq(sdioh_info_t *sd, uint irq); ++extern void spi_free_irq(uint irq, sdioh_info_t *sd); ++ ++/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */ ++extern void spi_lock(sdioh_info_t *sd); ++extern void spi_unlock(sdioh_info_t *sd); ++ ++/* Allocate/init/free per-OS private data */ ++extern int spi_osinit(sdioh_info_t *sd); ++extern void spi_osfree(sdioh_info_t *sd); ++ ++#endif /* _BCM_SD_SPI_H */ +diff --git a/drivers/net/wireless/ap6210/include/bcmsdstd.h b/drivers/net/wireless/ap6210/include/bcmsdstd.h +new file mode 100755 +index 0000000..1c854b2 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmsdstd.h +@@ -0,0 +1,248 @@ ++0/* ++ * 'Standard' SDIO HOST CONTROLLER driver ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmsdstd.h 347614 2012-07-27 10:24:51Z $ ++ */ ++#ifndef _BCM_SD_STD_H ++#define _BCM_SD_STD_H ++ ++#define sd_sync_dma(sd, read, nbytes) ++#define sd_init_dma(sd) ++#define sd_ack_intr(sd) ++#define sd_wakeup(sd); ++/* Allocate/init/free per-OS private data */ ++extern int sdstd_osinit(sdioh_info_t *sd); ++extern void sdstd_osfree(sdioh_info_t *sd); ++ ++#define BLOCK_SIZE_4318 64 ++#define BLOCK_SIZE_4328 512 ++ ++/* internal return code */ ++#define SUCCESS 0 ++#define ERROR 1 ++ ++/* private bus modes */ ++#define SDIOH_MODE_SPI 0 ++#define SDIOH_MODE_SD1 1 ++#define SDIOH_MODE_SD4 2 ++ ++#define MAX_SLOTS 6 /* For PCI: Only 6 BAR entries => 6 slots */ ++#define SDIOH_REG_WINSZ 0x100 /* Number of registers in Standard Host Controller */ ++ ++#define SDIOH_TYPE_ARASAN_HDK 1 ++#define SDIOH_TYPE_BCM27XX 2 ++#define SDIOH_TYPE_TI_PCIXX21 4 /* TI PCIxx21 Standard Host Controller */ ++#define SDIOH_TYPE_RICOH_R5C822 5 /* Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter */ ++#define SDIOH_TYPE_JMICRON 6 /* JMicron Standard SDIO Host Controller */ ++ ++/* For linux, allow yielding for dongle */ ++#define BCMSDYIELD ++ ++/* Expected card status value for CMD7 */ ++#define SDIOH_CMD7_EXP_STATUS 0x00001E00 ++ ++#define RETRIES_LARGE 100000 ++#define sdstd_os_yield(sd) do {} while (0) ++#define RETRIES_SMALL 100 ++ ++ ++#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */ ++#define USE_MULTIBLOCK 0x4 ++ ++#define USE_FIFO 0x8 /* Fifo vs non-fifo */ ++ ++#define CLIENT_INTR 0x100 /* Get rid of this! */ ++ ++#define HC_INTR_RETUNING 0x1000 ++ ++ ++#ifdef BCMSDIOH_TXGLOM ++/* Setting the MAX limit to 10 */ ++#define SDIOH_MAXGLOM_SIZE 10 ++ ++typedef struct glom_buf { ++ uint32 count; /* Total number of pkts queued */ ++ void *dma_buf_arr[SDIOH_MAXGLOM_SIZE]; /* Frame address */ ++ ulong dma_phys_arr[SDIOH_MAXGLOM_SIZE]; /* DMA_MAPed address of frames */ ++ uint16 nbytes[SDIOH_MAXGLOM_SIZE]; /* Size of each frame */ ++} glom_buf_t; ++#endif ++ ++struct sdioh_info { ++ uint cfg_bar; /* pci cfg address for bar */ ++ uint32 caps; /* cached value of capabilities reg */ ++ uint32 curr_caps; /* max current capabilities reg */ ++ ++ osl_t *osh; /* osh handler */ ++ volatile char *mem_space; /* pci device memory va */ ++ uint lockcount; /* nest count of sdstd_lock() calls */ ++ bool client_intr_enabled; /* interrupt connnected flag */ ++ bool intr_handler_valid; /* client driver interrupt handler valid */ ++ sdioh_cb_fn_t intr_handler; /* registered interrupt handler */ ++ void *intr_handler_arg; /* argument to call interrupt handler */ ++ bool initialized; /* card initialized */ ++ uint target_dev; /* Target device ID */ ++ uint16 intmask; /* Current active interrupts */ ++ void *sdos_info; /* Pointer to per-OS private data */ ++ ++ uint32 controller_type; /* Host controller type */ ++ uint8 version; /* Host Controller Spec Compliance Version */ ++ uint irq; /* Client irq */ ++ int intrcount; /* Client interrupts */ ++ int local_intrcount; /* Controller interrupts */ ++ bool host_init_done; /* Controller initted */ ++ bool card_init_done; /* Client SDIO interface initted */ ++ bool polled_mode; /* polling for command completion */ ++ ++ bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */ ++ /* Must be on for sd_multiblock to be effective */ ++ bool use_client_ints; /* If this is false, make sure to restore */ ++ /* polling hack in wl_linux.c:wl_timer() */ ++ int adapter_slot; /* Maybe dealing with multiple slots/controllers */ ++ int sd_mode; /* SD1/SD4/SPI */ ++ int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */ ++ uint32 data_xfer_count; /* Current transfer */ ++ uint16 card_rca; /* Current Address */ ++ int8 sd_dma_mode; /* DMA Mode (PIO, SDMA, ... ADMA2) on CMD53 */ ++ uint8 num_funcs; /* Supported funcs on client */ ++ uint32 com_cis_ptr; ++ uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; ++ void *dma_buf; /* DMA Buffer virtual address */ ++ ulong dma_phys; /* DMA Buffer physical address */ ++ void *adma2_dscr_buf; /* ADMA2 Descriptor Buffer virtual address */ ++ ulong adma2_dscr_phys; /* ADMA2 Descriptor Buffer physical address */ ++ ++ /* adjustments needed to make the dma align properly */ ++ void *dma_start_buf; ++ ulong dma_start_phys; ++ uint alloced_dma_size; ++ void *adma2_dscr_start_buf; ++ ulong adma2_dscr_start_phys; ++ uint alloced_adma2_dscr_size; ++ ++ int r_cnt; /* rx count */ ++ int t_cnt; /* tx_count */ ++ bool got_hcint; /* local interrupt flag */ ++ uint16 last_intrstatus; /* to cache intrstatus */ ++ int host_UHSISupported; /* whether UHSI is supported for HC. */ ++ int card_UHSI_voltage_Supported; /* whether UHSI is supported for ++ * Card in terms of Voltage [1.8 or 3.3]. ++ */ ++ int global_UHSI_Supp; /* type of UHSI support in both host and card. ++ * HOST_SDR_UNSUPP: capabilities not supported/matched ++ * HOST_SDR_12_25: SDR12 and SDR25 supported ++ * HOST_SDR_50_104_DDR: one of SDR50/SDR104 or DDR50 supptd ++ */ ++ volatile int sd3_dat_state; /* data transfer state used for retuning check */ ++ volatile int sd3_tun_state; /* tuning state used for retuning check */ ++ bool sd3_tuning_reqd; /* tuning requirement parameter */ ++ uint32 caps3; /* cached value of 32 MSbits capabilities reg (SDIO 3.0) */ ++#ifdef BCMSDIOH_TXGLOM ++ glom_buf_t glom_info; /* pkt information used for glomming */ ++ uint txglom_mode; /* Txglom mode: 0 - copy, 1 - multi-descriptor */ ++#endif ++}; ++ ++#define DMA_MODE_NONE 0 ++#define DMA_MODE_SDMA 1 ++#define DMA_MODE_ADMA1 2 ++#define DMA_MODE_ADMA2 3 ++#define DMA_MODE_ADMA2_64 4 ++#define DMA_MODE_AUTO -1 ++ ++#define USE_DMA(sd) ((bool)((sd->sd_dma_mode > 0) ? TRUE : FALSE)) ++ ++/* States for Tuning and corr data */ ++#define TUNING_IDLE 0 ++#define TUNING_START 1 ++#define TUNING_START_AFTER_DAT 2 ++#define TUNING_ONGOING 3 ++ ++#define DATA_TRANSFER_IDLE 0 ++#define DATA_TRANSFER_ONGOING 1 ++ ++#define CHECK_TUNING_PRE_DATA 1 ++#define CHECK_TUNING_POST_DATA 2 ++ ++/************************************************************ ++ * Internal interfaces: per-port references into bcmsdstd.c ++ */ ++ ++/* Global message bits */ ++extern uint sd_msglevel; ++ ++/* OS-independent interrupt handler */ ++extern bool check_client_intr(sdioh_info_t *sd); ++ ++/* Core interrupt enable/disable of device interrupts */ ++extern void sdstd_devintr_on(sdioh_info_t *sd); ++extern void sdstd_devintr_off(sdioh_info_t *sd); ++ ++/* Enable/disable interrupts for local controller events */ ++extern void sdstd_intrs_on(sdioh_info_t *sd, uint16 norm, uint16 err); ++extern void sdstd_intrs_off(sdioh_info_t *sd, uint16 norm, uint16 err); ++ ++/* Wait for specified interrupt and error bits to be set */ ++extern void sdstd_spinbits(sdioh_info_t *sd, uint16 norm, uint16 err); ++ ++ ++/************************************************************** ++ * Internal interfaces: bcmsdstd.c references to per-port code ++ */ ++ ++/* Register mapping routines */ ++extern uint32 *sdstd_reg_map(osl_t *osh, int32 addr, int size); ++extern void sdstd_reg_unmap(osl_t *osh, int32 addr, int size); ++ ++/* Interrupt (de)registration routines */ ++extern int sdstd_register_irq(sdioh_info_t *sd, uint irq); ++extern void sdstd_free_irq(uint irq, sdioh_info_t *sd); ++ ++/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */ ++extern void sdstd_lock(sdioh_info_t *sd); ++extern void sdstd_unlock(sdioh_info_t *sd); ++extern void sdstd_waitlockfree(sdioh_info_t *sd); ++ ++/* OS-specific wait-for-interrupt-or-status */ ++extern int sdstd_waitbits(sdioh_info_t *sd, uint16 norm, uint16 err, bool yield, uint16 *bits); ++ ++/* used by bcmsdstd_linux [implemented in sdstd] */ ++extern void sdstd_3_enable_retuning_int(sdioh_info_t *sd); ++extern void sdstd_3_disable_retuning_int(sdioh_info_t *sd); ++extern bool sdstd_3_is_retuning_int_set(sdioh_info_t *sd); ++extern void sdstd_3_check_and_do_tuning(sdioh_info_t *sd, int tuning_param); ++extern bool sdstd_3_check_and_set_retuning(sdioh_info_t *sd); ++extern int sdstd_3_get_tune_state(sdioh_info_t *sd); ++extern int sdstd_3_get_data_state(sdioh_info_t *sd); ++extern void sdstd_3_set_tune_state(sdioh_info_t *sd, int state); ++extern void sdstd_3_set_data_state(sdioh_info_t *sd, int state); ++extern uint8 sdstd_3_get_tuning_exp(sdioh_info_t *sd); ++extern uint32 sdstd_3_get_uhsi_clkmode(sdioh_info_t *sd); ++extern int sdstd_3_clk_tuning(sdioh_info_t *sd, uint32 sd3ClkMode); ++ ++/* used by sdstd [implemented in bcmsdstd_linux/ndis] */ ++extern void sdstd_3_start_tuning(sdioh_info_t *sd); ++extern void sdstd_3_osinit_tuning(sdioh_info_t *sd); ++extern void sdstd_3_osclean_tuning(sdioh_info_t *sd); ++ ++#endif /* _BCM_SD_STD_H */ +diff --git a/drivers/net/wireless/ap6210/include/bcmspi.h b/drivers/net/wireless/ap6210/include/bcmspi.h +new file mode 100755 +index 0000000..e226cb1 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmspi.h +@@ -0,0 +1,40 @@ ++/* ++ * Broadcom SPI Low-Level Hardware Driver API ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmspi.h 241182 2011-02-17 21:50:03Z $ ++ */ ++#ifndef _BCM_SPI_H ++#define _BCM_SPI_H ++ ++extern void spi_devintr_off(sdioh_info_t *sd); ++extern void spi_devintr_on(sdioh_info_t *sd); ++extern bool spi_start_clock(sdioh_info_t *sd, uint16 new_sd_divisor); ++extern bool spi_controller_highspeed_mode(sdioh_info_t *sd, bool hsmode); ++extern bool spi_check_client_intr(sdioh_info_t *sd, int *is_dev_intr); ++extern bool spi_hw_attach(sdioh_info_t *sd); ++extern bool spi_hw_detach(sdioh_info_t *sd); ++extern void spi_sendrecv(sdioh_info_t *sd, uint8 *msg_out, uint8 *msg_in, int msglen); ++extern void spi_spinbits(sdioh_info_t *sd); ++extern void spi_waitbits(sdioh_info_t *sd, bool yield); ++ ++#endif /* _BCM_SPI_H */ +diff --git a/drivers/net/wireless/ap6210/include/bcmutils.h b/drivers/net/wireless/ap6210/include/bcmutils.h +new file mode 100755 +index 0000000..71af3dc +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmutils.h +@@ -0,0 +1,808 @@ ++/* ++ * Misc useful os-independent macros and functions. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmutils.h 354837 2012-09-04 06:58:44Z $ ++ */ ++ ++#ifndef _bcmutils_h_ ++#define _bcmutils_h_ ++ ++#define bcm_strcpy_s(dst, noOfElements, src) strcpy((dst), (src)) ++#define bcm_strncpy_s(dst, noOfElements, src, count) strncpy((dst), (src), (count)) ++#define bcm_strcat_s(dst, noOfElements, src) strcat((dst), (src)) ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef PKTQ_LOG ++#include ++#endif ++ ++/* ctype replacement */ ++#define _BCM_U 0x01 /* upper */ ++#define _BCM_L 0x02 /* lower */ ++#define _BCM_D 0x04 /* digit */ ++#define _BCM_C 0x08 /* cntrl */ ++#define _BCM_P 0x10 /* punct */ ++#define _BCM_S 0x20 /* white space (space/lf/tab) */ ++#define _BCM_X 0x40 /* hex digit */ ++#define _BCM_SP 0x80 /* hard space (0x20) */ ++ ++extern const unsigned char bcm_ctype[]; ++#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)]) ++ ++#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0) ++#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0) ++#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0) ++#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0) ++#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0) ++#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0) ++#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0) ++#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0) ++#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0) ++#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0) ++#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0) ++#define bcm_tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) ++#define bcm_toupper(c) (bcm_islower((c)) ? ((c) + 'A' - 'a') : (c)) ++ ++/* Buffer structure for collecting string-formatted data ++* using bcm_bprintf() API. ++* Use bcm_binit() to initialize before use ++*/ ++ ++struct bcmstrbuf { ++ char *buf; /* pointer to current position in origbuf */ ++ unsigned int size; /* current (residual) size in bytes */ ++ char *origbuf; /* unmodified pointer to orignal buffer */ ++ unsigned int origsize; /* unmodified orignal buffer size in bytes */ ++}; ++ ++/* ** driver-only section ** */ ++#ifdef BCMDRIVER ++#include ++ ++#define GPIO_PIN_NOTDEFINED 0x20 /* Pin not defined */ ++ ++/* ++ * Spin at most 'us' microseconds while 'exp' is true. ++ * Caller should explicitly test 'exp' when this completes ++ * and take appropriate error action if 'exp' is still true. ++ */ ++#define SPINWAIT(exp, us) { \ ++ uint countdown = (us) + 9; \ ++ while ((exp) && (countdown >= 10)) {\ ++ OSL_DELAY(10); \ ++ countdown -= 10; \ ++ } \ ++} ++ ++/* osl multi-precedence packet queue */ ++#ifndef PKTQ_LEN_DEFAULT ++#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */ ++#endif ++#ifndef PKTQ_MAX_PREC ++#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */ ++#endif ++ ++typedef struct pktq_prec { ++ void *head; /* first packet to dequeue */ ++ void *tail; /* last packet to dequeue */ ++ uint16 len; /* number of queued packets */ ++ uint16 max; /* maximum number of queued packets */ ++} pktq_prec_t; ++ ++#ifdef PKTQ_LOG ++typedef struct { ++ uint32 requested; /* packets requested to be stored */ ++ uint32 stored; /* packets stored */ ++ uint32 saved; /* packets saved, ++ because a lowest priority queue has given away one packet ++ */ ++ uint32 selfsaved; /* packets saved, ++ because an older packet from the same queue has been dropped ++ */ ++ uint32 full_dropped; /* packets dropped, ++ because pktq is full with higher precedence packets ++ */ ++ uint32 dropped; /* packets dropped because pktq per that precedence is full */ ++ uint32 sacrificed; /* packets dropped, ++ in order to save one from a queue of a highest priority ++ */ ++ uint32 busy; /* packets droped because of hardware/transmission error */ ++ uint32 retry; /* packets re-sent because they were not received */ ++ uint32 ps_retry; /* packets retried again prior to moving power save mode */ ++ uint32 retry_drop; /* packets finally dropped after retry limit */ ++ uint32 max_avail; /* the high-water mark of the queue capacity for packets - ++ goes to zero as queue fills ++ */ ++ uint32 max_used; /* the high-water mark of the queue utilisation for packets - ++ increases with use ('inverse' of max_avail) ++ */ ++ uint32 queue_capacity; /* the maximum capacity of the queue */ ++} pktq_counters_t; ++#endif /* PKTQ_LOG */ ++ ++ ++#define PKTQ_COMMON \ ++ uint16 num_prec; /* number of precedences in use */ \ ++ uint16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */ \ ++ uint16 max; /* total max packets */ \ ++ uint16 len; /* total number of packets */ ++ ++/* multi-priority pkt queue */ ++struct pktq { ++ PKTQ_COMMON ++ /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ ++ struct pktq_prec q[PKTQ_MAX_PREC]; ++#ifdef PKTQ_LOG ++ pktq_counters_t _prec_cnt[PKTQ_MAX_PREC]; /* Counters per queue */ ++#endif ++}; ++ ++/* simple, non-priority pkt queue */ ++struct spktq { ++ PKTQ_COMMON ++ /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ ++ struct pktq_prec q[1]; ++}; ++ ++#define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--) ++ ++/* fn(pkt, arg). return true if pkt belongs to if */ ++typedef bool (*ifpkt_cb_t)(void*, int); ++ ++#ifdef BCMPKTPOOL ++#define POOL_ENAB(pool) ((pool) && (pool)->inited) ++#define SHARED_POOL (pktpool_shared) ++#else /* BCMPKTPOOL */ ++#define POOL_ENAB(bus) 0 ++#define SHARED_POOL ((struct pktpool *)NULL) ++#endif /* BCMPKTPOOL */ ++ ++#ifndef PKTPOOL_LEN_MAX ++#define PKTPOOL_LEN_MAX 40 ++#endif /* PKTPOOL_LEN_MAX */ ++#define PKTPOOL_CB_MAX 3 ++ ++struct pktpool; ++typedef void (*pktpool_cb_t)(struct pktpool *pool, void *arg); ++typedef struct { ++ pktpool_cb_t cb; ++ void *arg; ++} pktpool_cbinfo_t; ++ ++#ifdef BCMDBG_POOL ++/* pkt pool debug states */ ++#define POOL_IDLE 0 ++#define POOL_RXFILL 1 ++#define POOL_RXDH 2 ++#define POOL_RXD11 3 ++#define POOL_TXDH 4 ++#define POOL_TXD11 5 ++#define POOL_AMPDU 6 ++#define POOL_TXENQ 7 ++ ++typedef struct { ++ void *p; ++ uint32 cycles; ++ uint32 dur; ++} pktpool_dbg_t; ++ ++typedef struct { ++ uint8 txdh; /* tx to host */ ++ uint8 txd11; /* tx to d11 */ ++ uint8 enq; /* waiting in q */ ++ uint8 rxdh; /* rx from host */ ++ uint8 rxd11; /* rx from d11 */ ++ uint8 rxfill; /* dma_rxfill */ ++ uint8 idle; /* avail in pool */ ++} pktpool_stats_t; ++#endif /* BCMDBG_POOL */ ++ ++typedef struct pktpool { ++ bool inited; ++ uint16 r; ++ uint16 w; ++ uint16 len; ++ uint16 maxlen; ++ uint16 plen; ++ bool istx; ++ bool empty; ++ uint8 cbtoggle; ++ uint8 cbcnt; ++ uint8 ecbcnt; ++ bool emptycb_disable; ++ pktpool_cbinfo_t *availcb_excl; ++ pktpool_cbinfo_t cbs[PKTPOOL_CB_MAX]; ++ pktpool_cbinfo_t ecbs[PKTPOOL_CB_MAX]; ++ void *q[PKTPOOL_LEN_MAX + 1]; ++ ++#ifdef BCMDBG_POOL ++ uint8 dbg_cbcnt; ++ pktpool_cbinfo_t dbg_cbs[PKTPOOL_CB_MAX]; ++ uint16 dbg_qlen; ++ pktpool_dbg_t dbg_q[PKTPOOL_LEN_MAX + 1]; ++#endif ++} pktpool_t; ++ ++extern pktpool_t *pktpool_shared; ++ ++extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *pktplen, int plen, bool istx); ++extern int pktpool_deinit(osl_t *osh, pktpool_t *pktp); ++extern int pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal); ++extern void* pktpool_get(pktpool_t *pktp); ++extern void pktpool_free(pktpool_t *pktp, void *p); ++extern int pktpool_add(pktpool_t *pktp, void *p); ++extern uint16 pktpool_avail(pktpool_t *pktp); ++extern int pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp); ++extern int pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb); ++extern int pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); ++extern int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); ++extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen); ++extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 maxlen); ++extern void pktpool_emptycb_disable(pktpool_t *pktp, bool disable); ++extern bool pktpool_emptycb_disabled(pktpool_t *pktp); ++ ++#define POOLPTR(pp) ((pktpool_t *)(pp)) ++#define pktpool_len(pp) (POOLPTR(pp)->len - 1) ++#define pktpool_plen(pp) (POOLPTR(pp)->plen) ++#define pktpool_maxlen(pp) (POOLPTR(pp)->maxlen) ++ ++#ifdef BCMDBG_POOL ++extern int pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); ++extern int pktpool_start_trigger(pktpool_t *pktp, void *p); ++extern int pktpool_dbg_dump(pktpool_t *pktp); ++extern int pktpool_dbg_notify(pktpool_t *pktp); ++extern int pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats); ++#endif /* BCMDBG_POOL */ ++ ++/* forward definition of ether_addr structure used by some function prototypes */ ++ ++struct ether_addr; ++ ++extern int ether_isbcast(const void *ea); ++extern int ether_isnulladdr(const void *ea); ++ ++/* operations on a specific precedence in packet queue */ ++ ++#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max)) ++#define pktq_pmax(pq, prec) ((pq)->q[prec].max) ++#define pktq_plen(pq, prec) ((pq)->q[prec].len) ++#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len) ++#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max) ++#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0) ++ ++#define pktq_ppeek(pq, prec) ((pq)->q[prec].head) ++#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail) ++ ++extern void *pktq_penq(struct pktq *pq, int prec, void *p); ++extern void *pktq_penq_head(struct pktq *pq, int prec, void *p); ++extern void *pktq_pdeq(struct pktq *pq, int prec); ++extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p); ++extern void *pktq_pdeq_tail(struct pktq *pq, int prec); ++/* Empty the queue at particular precedence level */ ++extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ++ ifpkt_cb_t fn, int arg); ++/* Remove a specified packet from its queue */ ++extern bool pktq_pdel(struct pktq *pq, void *p, int prec); ++ ++/* operations on a set of precedences in packet queue */ ++ ++extern int pktq_mlen(struct pktq *pq, uint prec_bmp); ++extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out); ++extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out); ++ ++/* operations on packet queue as a whole */ ++ ++#define pktq_len(pq) ((int)(pq)->len) ++#define pktq_max(pq) ((int)(pq)->max) ++#define pktq_avail(pq) ((int)((pq)->max - (pq)->len)) ++#define pktq_full(pq) ((pq)->len >= (pq)->max) ++#define pktq_empty(pq) ((pq)->len == 0) ++ ++/* operations for single precedence queues */ ++#define pktenq(pq, p) pktq_penq(((struct pktq *)(void *)pq), 0, (p)) ++#define pktenq_head(pq, p) pktq_penq_head(((struct pktq *)(void *)pq), 0, (p)) ++#define pktdeq(pq) pktq_pdeq(((struct pktq *)(void *)pq), 0) ++#define pktdeq_tail(pq) pktq_pdeq_tail(((struct pktq *)(void *)pq), 0) ++#define pktqinit(pq, len) pktq_init(((struct pktq *)(void *)pq), 1, len) ++ ++extern void pktq_init(struct pktq *pq, int num_prec, int max_len); ++extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len); ++ ++/* prec_out may be NULL if caller is not interested in return value */ ++extern void *pktq_deq(struct pktq *pq, int *prec_out); ++extern void *pktq_deq_tail(struct pktq *pq, int *prec_out); ++extern void *pktq_peek(struct pktq *pq, int *prec_out); ++extern void *pktq_peek_tail(struct pktq *pq, int *prec_out); ++extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir, ifpkt_cb_t fn, int arg); ++ ++/* externs */ ++/* packet */ ++extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf); ++extern uint pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf); ++extern uint pkttotlen(osl_t *osh, void *p); ++extern void *pktlast(osl_t *osh, void *p); ++extern uint pktsegcnt(osl_t *osh, void *p); ++extern uint pktsegcnt_war(osl_t *osh, void *p); ++extern uint8 *pktoffset(osl_t *osh, void *p, uint offset); ++ ++/* Get priority from a packet and pass it back in scb (or equiv) */ ++#define PKTPRIO_VDSCP 0x100 /* DSCP prio found after VLAN tag */ ++#define PKTPRIO_VLAN 0x200 /* VLAN prio found */ ++#define PKTPRIO_UPD 0x400 /* DSCP used to update VLAN prio */ ++#define PKTPRIO_DSCP 0x800 /* DSCP prio found */ ++ ++extern uint pktsetprio(void *pkt, bool update_vtag); ++ ++/* string */ ++extern int bcm_atoi(const char *s); ++extern ulong bcm_strtoul(const char *cp, char **endp, uint base); ++extern char *bcmstrstr(const char *haystack, const char *needle); ++extern char *bcmstrcat(char *dest, const char *src); ++extern char *bcmstrncat(char *dest, const char *src, uint size); ++extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen); ++char* bcmstrtok(char **string, const char *delimiters, char *tokdelim); ++int bcmstricmp(const char *s1, const char *s2); ++int bcmstrnicmp(const char* s1, const char* s2, int cnt); ++ ++ ++/* ethernet address */ ++extern char *bcm_ether_ntoa(const struct ether_addr *ea, char *buf); ++extern int bcm_ether_atoe(const char *p, struct ether_addr *ea); ++ ++/* ip address */ ++struct ipv4_addr; ++extern char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf); ++ ++/* delay */ ++extern void bcm_mdelay(uint ms); ++/* variable access */ ++#define NVRAM_RECLAIM_CHECK(name) ++ ++extern char *getvar(char *vars, const char *name); ++extern int getintvar(char *vars, const char *name); ++extern int getintvararray(char *vars, const char *name, int index); ++extern int getintvararraysize(char *vars, const char *name); ++extern uint getgpiopin(char *vars, char *pin_name, uint def_pin); ++#define bcm_perf_enable() ++#define bcmstats(fmt) ++#define bcmlog(fmt, a1, a2) ++#define bcmdumplog(buf, size) *buf = '\0' ++#define bcmdumplogent(buf, idx) -1 ++ ++#define bcmtslog(tstamp, fmt, a1, a2) ++#define bcmprinttslogs() ++#define bcmprinttstamp(us) ++#define bcmdumptslog(buf, size) ++ ++extern char *bcm_nvram_vars(uint *length); ++extern int bcm_nvram_cache(void *sih); ++ ++/* Support for sharing code across in-driver iovar implementations. ++ * The intent is that a driver use this structure to map iovar names ++ * to its (private) iovar identifiers, and the lookup function to ++ * find the entry. Macros are provided to map ids and get/set actions ++ * into a single number space for a switch statement. ++ */ ++ ++/* iovar structure */ ++typedef struct bcm_iovar { ++ const char *name; /* name for lookup and display */ ++ uint16 varid; /* id for switch */ ++ uint16 flags; /* driver-specific flag bits */ ++ uint16 type; /* base type of argument */ ++ uint16 minlen; /* min length for buffer vars */ ++} bcm_iovar_t; ++ ++/* varid definitions are per-driver, may use these get/set bits */ ++ ++/* IOVar action bits for id mapping */ ++#define IOV_GET 0 /* Get an iovar */ ++#define IOV_SET 1 /* Set an iovar */ ++ ++/* Varid to actionid mapping */ ++#define IOV_GVAL(id) ((id) * 2) ++#define IOV_SVAL(id) ((id) * 2 + IOV_SET) ++#define IOV_ISSET(actionid) ((actionid & IOV_SET) == IOV_SET) ++#define IOV_ID(actionid) (actionid >> 1) ++ ++/* flags are per-driver based on driver attributes */ ++ ++extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name); ++extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool set); ++#if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \ ++ defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) ++extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len); ++#endif ++#endif /* BCMDRIVER */ ++ ++/* Base type definitions */ ++#define IOVT_VOID 0 /* no value (implictly set only) */ ++#define IOVT_BOOL 1 /* any value ok (zero/nonzero) */ ++#define IOVT_INT8 2 /* integer values are range-checked */ ++#define IOVT_UINT8 3 /* unsigned int 8 bits */ ++#define IOVT_INT16 4 /* int 16 bits */ ++#define IOVT_UINT16 5 /* unsigned int 16 bits */ ++#define IOVT_INT32 6 /* int 32 bits */ ++#define IOVT_UINT32 7 /* unsigned int 32 bits */ ++#define IOVT_BUFFER 8 /* buffer is size-checked as per minlen */ ++#define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER) ++ ++/* Initializer for IOV type strings */ ++#define BCM_IOV_TYPE_INIT { \ ++ "void", \ ++ "bool", \ ++ "int8", \ ++ "uint8", \ ++ "int16", \ ++ "uint16", \ ++ "int32", \ ++ "uint32", \ ++ "buffer", \ ++ "" } ++ ++#define BCM_IOVT_IS_INT(type) (\ ++ (type == IOVT_BOOL) || \ ++ (type == IOVT_INT8) || \ ++ (type == IOVT_UINT8) || \ ++ (type == IOVT_INT16) || \ ++ (type == IOVT_UINT16) || \ ++ (type == IOVT_INT32) || \ ++ (type == IOVT_UINT32)) ++ ++/* ** driver/apps-shared section ** */ ++ ++#define BCME_STRLEN 64 /* Max string length for BCM errors */ ++#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST)) ++ ++ ++/* ++ * error codes could be added but the defined ones shouldn't be changed/deleted ++ * these error codes are exposed to the user code ++ * when ever a new error code is added to this list ++ * please update errorstring table with the related error string and ++ * update osl files with os specific errorcode map ++*/ ++ ++#define BCME_OK 0 /* Success */ ++#define BCME_ERROR -1 /* Error generic */ ++#define BCME_BADARG -2 /* Bad Argument */ ++#define BCME_BADOPTION -3 /* Bad option */ ++#define BCME_NOTUP -4 /* Not up */ ++#define BCME_NOTDOWN -5 /* Not down */ ++#define BCME_NOTAP -6 /* Not AP */ ++#define BCME_NOTSTA -7 /* Not STA */ ++#define BCME_BADKEYIDX -8 /* BAD Key Index */ ++#define BCME_RADIOOFF -9 /* Radio Off */ ++#define BCME_NOTBANDLOCKED -10 /* Not band locked */ ++#define BCME_NOCLK -11 /* No Clock */ ++#define BCME_BADRATESET -12 /* BAD Rate valueset */ ++#define BCME_BADBAND -13 /* BAD Band */ ++#define BCME_BUFTOOSHORT -14 /* Buffer too short */ ++#define BCME_BUFTOOLONG -15 /* Buffer too long */ ++#define BCME_BUSY -16 /* Busy */ ++#define BCME_NOTASSOCIATED -17 /* Not Associated */ ++#define BCME_BADSSIDLEN -18 /* Bad SSID len */ ++#define BCME_OUTOFRANGECHAN -19 /* Out of Range Channel */ ++#define BCME_BADCHAN -20 /* Bad Channel */ ++#define BCME_BADADDR -21 /* Bad Address */ ++#define BCME_NORESOURCE -22 /* Not Enough Resources */ ++#define BCME_UNSUPPORTED -23 /* Unsupported */ ++#define BCME_BADLEN -24 /* Bad length */ ++#define BCME_NOTREADY -25 /* Not Ready */ ++#define BCME_EPERM -26 /* Not Permitted */ ++#define BCME_NOMEM -27 /* No Memory */ ++#define BCME_ASSOCIATED -28 /* Associated */ ++#define BCME_RANGE -29 /* Not In Range */ ++#define BCME_NOTFOUND -30 /* Not Found */ ++#define BCME_WME_NOT_ENABLED -31 /* WME Not Enabled */ ++#define BCME_TSPEC_NOTFOUND -32 /* TSPEC Not Found */ ++#define BCME_ACM_NOTSUPPORTED -33 /* ACM Not Supported */ ++#define BCME_NOT_WME_ASSOCIATION -34 /* Not WME Association */ ++#define BCME_SDIO_ERROR -35 /* SDIO Bus Error */ ++#define BCME_DONGLE_DOWN -36 /* Dongle Not Accessible */ ++#define BCME_VERSION -37 /* Incorrect version */ ++#define BCME_TXFAIL -38 /* TX failure */ ++#define BCME_RXFAIL -39 /* RX failure */ ++#define BCME_NODEVICE -40 /* Device not present */ ++#define BCME_NMODE_DISABLED -41 /* NMODE disabled */ ++#define BCME_NONRESIDENT -42 /* access to nonresident overlay */ ++#define BCME_LAST BCME_NONRESIDENT ++ ++/* These are collection of BCME Error strings */ ++#define BCMERRSTRINGTABLE { \ ++ "OK", \ ++ "Undefined error", \ ++ "Bad Argument", \ ++ "Bad Option", \ ++ "Not up", \ ++ "Not down", \ ++ "Not AP", \ ++ "Not STA", \ ++ "Bad Key Index", \ ++ "Radio Off", \ ++ "Not band locked", \ ++ "No clock", \ ++ "Bad Rate valueset", \ ++ "Bad Band", \ ++ "Buffer too short", \ ++ "Buffer too long", \ ++ "Busy", \ ++ "Not Associated", \ ++ "Bad SSID len", \ ++ "Out of Range Channel", \ ++ "Bad Channel", \ ++ "Bad Address", \ ++ "Not Enough Resources", \ ++ "Unsupported", \ ++ "Bad length", \ ++ "Not Ready", \ ++ "Not Permitted", \ ++ "No Memory", \ ++ "Associated", \ ++ "Not In Range", \ ++ "Not Found", \ ++ "WME Not Enabled", \ ++ "TSPEC Not Found", \ ++ "ACM Not Supported", \ ++ "Not WME Association", \ ++ "SDIO Bus Error", \ ++ "Dongle Not Accessible", \ ++ "Incorrect version", \ ++ "TX Failure", \ ++ "RX Failure", \ ++ "Device Not Present", \ ++ "NMODE Disabled", \ ++ "Nonresident overlay access", \ ++} ++ ++#ifndef ABS ++#define ABS(a) (((a) < 0) ? -(a) : (a)) ++#endif /* ABS */ ++ ++#ifndef MIN ++#define MIN(a, b) (((a) < (b)) ? (a) : (b)) ++#endif /* MIN */ ++ ++#ifndef MAX ++#define MAX(a, b) (((a) > (b)) ? (a) : (b)) ++#endif /* MAX */ ++ ++#define CEIL(x, y) (((x) + ((y) - 1)) / (y)) ++#define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) ++#define ISALIGNED(a, x) (((uintptr)(a) & ((x) - 1)) == 0) ++#define ALIGN_ADDR(addr, boundary) (void *)(((uintptr)(addr) + (boundary) - 1) \ ++ & ~((boundary) - 1)) ++#define ALIGN_SIZE(size, boundary) (((size) + (boundary) - 1) \ ++ & ~((boundary) - 1)) ++#define ISPOWEROF2(x) ((((x) - 1) & (x)) == 0) ++#define VALID_MASK(mask) !((mask) & ((mask) + 1)) ++ ++#ifndef OFFSETOF ++#ifdef __ARMCC_VERSION ++/* ++ * The ARM RVCT compiler complains when using OFFSETOF where a constant ++ * expression is expected, such as an initializer for a static object. ++ * offsetof from the runtime library doesn't have that problem. ++ */ ++#include ++#define OFFSETOF(type, member) offsetof(type, member) ++#else ++#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) ++#endif /* __ARMCC_VERSION */ ++#endif /* OFFSETOF */ ++ ++#ifndef ARRAYSIZE ++#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0])) ++#endif ++ ++/* Reference a function; used to prevent a static function from being optimized out */ ++extern void *_bcmutils_dummy_fn; ++#define REFERENCE_FUNCTION(f) (_bcmutils_dummy_fn = (void *)(f)) ++ ++/* bit map related macros */ ++#ifndef setbit ++#ifndef NBBY /* the BSD family defines NBBY */ ++#define NBBY 8 /* 8 bits per byte */ ++#endif /* #ifndef NBBY */ ++#define setbit(a, i) (((uint8 *)a)[(i) / NBBY] |= 1 << ((i) % NBBY)) ++#define clrbit(a, i) (((uint8 *)a)[(i) / NBBY] &= ~(1 << ((i) % NBBY))) ++#define isset(a, i) (((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) ++#define isclr(a, i) ((((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) == 0) ++#endif /* setbit */ ++ ++#define NBITS(type) (sizeof(type) * 8) ++#define NBITVAL(nbits) (1 << (nbits)) ++#define MAXBITVAL(nbits) ((1 << (nbits)) - 1) ++#define NBITMASK(nbits) MAXBITVAL(nbits) ++#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8) ++ ++/* basic mux operation - can be optimized on several architectures */ ++#define MUX(pred, true, false) ((pred) ? (true) : (false)) ++ ++/* modulo inc/dec - assumes x E [0, bound - 1] */ ++#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1) ++#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1) ++ ++/* modulo inc/dec, bound = 2^k */ ++#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1)) ++#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1)) ++ ++/* modulo add/sub - assumes x, y E [0, bound - 1] */ ++#define MODADD(x, y, bound) \ ++ MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y)) ++#define MODSUB(x, y, bound) \ ++ MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y)) ++ ++/* module add/sub, bound = 2^k */ ++#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1)) ++#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1)) ++ ++/* crc defines */ ++#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */ ++#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */ ++#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */ ++#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */ ++#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */ ++#define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */ ++ ++/* use for direct output of MAC address in printf etc */ ++#define MACF "%02x:%02x:%02x:%02x:%02x:%02x" ++#define ETHERP_TO_MACF(ea) ((struct ether_addr *) (ea))->octet[0], \ ++ ((struct ether_addr *) (ea))->octet[1], \ ++ ((struct ether_addr *) (ea))->octet[2], \ ++ ((struct ether_addr *) (ea))->octet[3], \ ++ ((struct ether_addr *) (ea))->octet[4], \ ++ ((struct ether_addr *) (ea))->octet[5] ++ ++#define ETHER_TO_MACF(ea) (ea).octet[0], \ ++ (ea).octet[1], \ ++ (ea).octet[2], \ ++ (ea).octet[3], \ ++ (ea).octet[4], \ ++ (ea).octet[5] ++#if !defined(SIMPLE_MAC_PRINT) ++#define MACDBG "%02x:%02x:%02x:%02x:%02x:%02x" ++#define MAC2STRDBG(ea) (ea)[0], (ea)[1], (ea)[2], (ea)[3], (ea)[4], (ea)[5] ++#else ++#define MACDBG "%02x:%02x:%02x" ++#define MAC2STRDBG(ea) (ea)[0], (ea)[4], (ea)[5] ++#endif /* SIMPLE_MAC_PRINT */ ++ ++/* bcm_format_flags() bit description structure */ ++typedef struct bcm_bit_desc { ++ uint32 bit; ++ const char* name; ++} bcm_bit_desc_t; ++ ++/* tag_ID/length/value_buffer tuple */ ++typedef struct bcm_tlv { ++ uint8 id; ++ uint8 len; ++ uint8 data[1]; ++} bcm_tlv_t; ++ ++/* Check that bcm_tlv_t fits into the given buflen */ ++#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len)) ++ ++/* buffer length for ethernet address from bcm_ether_ntoa() */ ++#define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */ ++ ++/* crypto utility function */ ++/* 128-bit xor: *dst = *src1 xor *src2. dst1, src1 and src2 may have any alignment */ ++static INLINE void ++xor_128bit_block(const uint8 *src1, const uint8 *src2, uint8 *dst) ++{ ++ if ( ++#ifdef __i386__ ++ 1 || ++#endif ++ (((uintptr)src1 | (uintptr)src2 | (uintptr)dst) & 3) == 0) { ++ /* ARM CM3 rel time: 1229 (727 if alignment check could be omitted) */ ++ /* x86 supports unaligned. This version runs 6x-9x faster on x86. */ ++ ((uint32 *)dst)[0] = ((const uint32 *)src1)[0] ^ ((const uint32 *)src2)[0]; ++ ((uint32 *)dst)[1] = ((const uint32 *)src1)[1] ^ ((const uint32 *)src2)[1]; ++ ((uint32 *)dst)[2] = ((const uint32 *)src1)[2] ^ ((const uint32 *)src2)[2]; ++ ((uint32 *)dst)[3] = ((const uint32 *)src1)[3] ^ ((const uint32 *)src2)[3]; ++ } else { ++ /* ARM CM3 rel time: 4668 (4191 if alignment check could be omitted) */ ++ int k; ++ for (k = 0; k < 16; k++) ++ dst[k] = src1[k] ^ src2[k]; ++ } ++} ++ ++/* externs */ ++/* crc */ ++extern uint8 hndcrc8(uint8 *p, uint nbytes, uint8 crc); ++extern uint16 hndcrc16(uint8 *p, uint nbytes, uint16 crc); ++extern uint32 hndcrc32(uint8 *p, uint nbytes, uint32 crc); ++ ++/* format/print */ ++#if defined(DHD_DEBUG) || defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || \ ++ defined(WLMSG_ASSOC) ++extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len); ++#endif ++ ++#if defined(DHD_DEBUG) || defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || \ ++ defined(WLMSG_ASSOC) || defined(WLMEDIA_PEAKRATE) ++extern int bcm_format_hex(char *str, const void *bytes, int len); ++#endif ++ ++extern const char *bcm_crypto_algo_name(uint algo); ++extern char *bcm_chipname(uint chipid, char *buf, uint len); ++extern char *bcm_brev_str(uint32 brev, char *buf); ++extern void printbig(char *buf); ++extern void prhex(const char *msg, uchar *buf, uint len); ++ ++/* IE parsing */ ++extern bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen); ++extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key); ++extern bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key); ++ ++/* bcmerror */ ++extern const char *bcmerrorstr(int bcmerror); ++extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key); ++ ++/* multi-bool data type: set of bools, mbool is true if any is set */ ++typedef uint32 mbool; ++#define mboolset(mb, bit) ((mb) |= (bit)) /* set one bool */ ++#define mboolclr(mb, bit) ((mb) &= ~(bit)) /* clear one bool */ ++#define mboolisset(mb, bit) (((mb) & (bit)) != 0) /* TRUE if one bool is set */ ++#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val))) ++ ++/* generic datastruct to help dump routines */ ++struct fielddesc { ++ const char *nameandfmt; ++ uint32 offset; ++ uint32 len; ++}; ++ ++extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size); ++extern void bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len); ++ ++extern void bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount); ++extern int bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes); ++extern void bcm_print_bytes(const char *name, const uchar *cdata, int len); ++ ++typedef uint32 (*bcmutl_rdreg_rtn)(void *arg0, uint arg1, uint32 offset); ++extern uint bcmdumpfields(bcmutl_rdreg_rtn func_ptr, void *arg0, uint arg1, struct fielddesc *str, ++ char *buf, uint32 bufsize); ++extern uint bcm_bitcount(uint8 *bitmap, uint bytelength); ++ ++extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...); ++ ++/* power conversion */ ++extern uint16 bcm_qdbm_to_mw(uint8 qdbm); ++extern uint8 bcm_mw_to_qdbm(uint16 mw); ++extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len); ++ ++unsigned int process_nvram_vars(char *varbuf, unsigned int len); ++ ++#ifdef __cplusplus ++ } ++#endif ++ ++#endif /* _bcmutils_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/bcmwifi_channels.h b/drivers/net/wireless/ap6210/include/bcmwifi_channels.h +new file mode 100755 +index 0000000..bc57aca +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmwifi_channels.h +@@ -0,0 +1,490 @@ ++/* ++ * Misc utility routines for WL and Apps ++ * This header file housing the define and function prototype use by ++ * both the wl driver, tools & Apps. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmwifi_channels.h 309193 2012-01-19 00:03:57Z $ ++ */ ++ ++#ifndef _bcmwifi_channels_h_ ++#define _bcmwifi_channels_h_ ++ ++ ++/* A chanspec holds the channel number, band, bandwidth and control sideband */ ++typedef uint16 chanspec_t; ++ ++/* channel defines */ ++#define CH_UPPER_SB 0x01 ++#define CH_LOWER_SB 0x02 ++#define CH_EWA_VALID 0x04 ++#define CH_80MHZ_APART 16 ++#define CH_40MHZ_APART 8 ++#define CH_20MHZ_APART 4 ++#define CH_10MHZ_APART 2 ++#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ ++#define CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ ++#define MAXCHANNEL 224 /* max # supported channels. The max channel no is 216, ++ * this is that + 1 rounded up to a multiple of NBBY (8). ++ * DO NOT MAKE it > 255: channels are uint8's all over ++ */ ++#define CHSPEC_CTLOVLP(sp1, sp2, sep) ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < (sep) ++ ++/* All builds use the new 11ac ratespec/chanspec */ ++#undef D11AC_IOTYPES ++#define D11AC_IOTYPES ++ ++#ifndef D11AC_IOTYPES ++ ++#define WL_CHANSPEC_CHAN_MASK 0x00ff ++#define WL_CHANSPEC_CHAN_SHIFT 0 ++ ++#define WL_CHANSPEC_CTL_SB_MASK 0x0300 ++#define WL_CHANSPEC_CTL_SB_SHIFT 8 ++#define WL_CHANSPEC_CTL_SB_LOWER 0x0100 ++#define WL_CHANSPEC_CTL_SB_UPPER 0x0200 ++#define WL_CHANSPEC_CTL_SB_NONE 0x0300 ++ ++#define WL_CHANSPEC_BW_MASK 0x0C00 ++#define WL_CHANSPEC_BW_SHIFT 10 ++#define WL_CHANSPEC_BW_10 0x0400 ++#define WL_CHANSPEC_BW_20 0x0800 ++#define WL_CHANSPEC_BW_40 0x0C00 ++ ++#define WL_CHANSPEC_BAND_MASK 0xf000 ++#define WL_CHANSPEC_BAND_SHIFT 12 ++#ifdef WL_CHANSPEC_BAND_5G ++#undef WL_CHANSPEC_BAND_5G ++#endif ++#ifdef WL_CHANSPEC_BAND_2G ++#undef WL_CHANSPEC_BAND_2G ++#endif ++#define WL_CHANSPEC_BAND_5G 0x1000 ++#define WL_CHANSPEC_BAND_2G 0x2000 ++#define INVCHANSPEC 255 ++ ++/* channel defines */ ++#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0) ++#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ ++ ((channel) + CH_10MHZ_APART) : 0) ++#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) ++#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ ++ WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ ++ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) ++#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ ++ ((channel) + CH_20MHZ_APART) : 0) ++#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ ++ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ ++ WL_CHANSPEC_BAND_5G)) ++#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) ++#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) ++ ++/* chanspec stores radio channel & flags to indicate control channel location, i.e. upper/lower */ ++#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) ++#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) ++ ++#ifdef WL11N_20MHZONLY ++ ++#define CHSPEC_IS10(chspec) 0 ++#define CHSPEC_IS20(chspec) 1 ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) 0 ++#endif ++ ++#else /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) ++#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) ++#endif ++ ++#endif /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) ++#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) ++#define CHSPEC_SB_NONE(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE) ++#define CHSPEC_SB_UPPER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) ++#define CHSPEC_SB_LOWER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) ++#define CHSPEC_CTL_CHAN(chspec) ((CHSPEC_SB_LOWER(chspec)) ? \ ++ (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \ ++ (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK)))) ++#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G) ++ ++#define CHANSPEC_STR_LEN 8 ++ ++#else /* D11AC_IOTYPES */ ++ ++#define WL_CHANSPEC_CHAN_MASK 0x00ff ++#define WL_CHANSPEC_CHAN_SHIFT 0 ++#define WL_CHANSPEC_CHAN1_MASK 0x000f ++#define WL_CHANSPEC_CHAN1_SHIFT 0 ++#define WL_CHANSPEC_CHAN2_MASK 0x00f0 ++#define WL_CHANSPEC_CHAN2_SHIFT 4 ++ ++#define WL_CHANSPEC_CTL_SB_MASK 0x0700 ++#define WL_CHANSPEC_CTL_SB_SHIFT 8 ++#define WL_CHANSPEC_CTL_SB_LLL 0x0000 ++#define WL_CHANSPEC_CTL_SB_LLU 0x0100 ++#define WL_CHANSPEC_CTL_SB_LUL 0x0200 ++#define WL_CHANSPEC_CTL_SB_LUU 0x0300 ++#define WL_CHANSPEC_CTL_SB_ULL 0x0400 ++#define WL_CHANSPEC_CTL_SB_ULU 0x0500 ++#define WL_CHANSPEC_CTL_SB_UUL 0x0600 ++#define WL_CHANSPEC_CTL_SB_UUU 0x0700 ++#define WL_CHANSPEC_CTL_SB_LL WL_CHANSPEC_CTL_SB_LLL ++#define WL_CHANSPEC_CTL_SB_LU WL_CHANSPEC_CTL_SB_LLU ++#define WL_CHANSPEC_CTL_SB_UL WL_CHANSPEC_CTL_SB_LUL ++#define WL_CHANSPEC_CTL_SB_UU WL_CHANSPEC_CTL_SB_LUU ++#define WL_CHANSPEC_CTL_SB_L WL_CHANSPEC_CTL_SB_LLL ++#define WL_CHANSPEC_CTL_SB_U WL_CHANSPEC_CTL_SB_LLU ++#define WL_CHANSPEC_CTL_SB_LOWER WL_CHANSPEC_CTL_SB_LLL ++#define WL_CHANSPEC_CTL_SB_UPPER WL_CHANSPEC_CTL_SB_LLU ++ ++#define WL_CHANSPEC_BW_MASK 0x3800 ++#define WL_CHANSPEC_BW_SHIFT 11 ++#define WL_CHANSPEC_BW_5 0x0000 ++#define WL_CHANSPEC_BW_10 0x0800 ++#define WL_CHANSPEC_BW_20 0x1000 ++#define WL_CHANSPEC_BW_40 0x1800 ++#define WL_CHANSPEC_BW_80 0x2000 ++#define WL_CHANSPEC_BW_160 0x2800 ++#define WL_CHANSPEC_BW_8080 0x3000 ++ ++#define WL_CHANSPEC_BAND_MASK 0xc000 ++#define WL_CHANSPEC_BAND_SHIFT 14 ++#define WL_CHANSPEC_BAND_2G 0x0000 ++#define WL_CHANSPEC_BAND_3G 0x4000 ++#define WL_CHANSPEC_BAND_4G 0x8000 ++#define WL_CHANSPEC_BAND_5G 0xc000 ++#define INVCHANSPEC 255 ++ ++/* channel defines */ ++#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? \ ++ ((channel) - CH_10MHZ_APART) : 0) ++#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ ++ ((channel) + CH_10MHZ_APART) : 0) ++#define LOWER_40_SB(channel) ((channel) - CH_20MHZ_APART) ++#define UPPER_40_SB(channel) ((channel) + CH_20MHZ_APART) ++#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) ++#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ ++ (((channel) <= CH_MAX_2G_CHANNEL) ? \ ++ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) ++#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ ++ ((channel) + CH_20MHZ_APART) : 0) ++#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ ++ ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ ++ WL_CHANSPEC_BAND_5G)) ++#define CH80MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | \ ++ WL_CHANSPEC_BW_80 | WL_CHANSPEC_BAND_5G) ++#define CH160MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ++ ((channel) | (ctlsb) | \ ++ WL_CHANSPEC_BW_160 | WL_CHANSPEC_BAND_5G) ++ ++/* simple MACROs to get different fields of chanspec */ ++#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) ++#define CHSPEC_CHAN1(chspec) ((chspec) & WL_CHANSPEC_CHAN1_MASK) ++#define CHSPEC_CHAN2(chspec) ((chspec) & WL_CHANSPEC_CHAN2_MASK) ++#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) ++#define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) ++#define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) ++ ++#ifdef WL11N_20MHZONLY ++ ++#define CHSPEC_IS10(chspec) 0 ++#define CHSPEC_IS20(chspec) 1 ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) 0 ++#endif ++#ifndef CHSPEC_IS80 ++#define CHSPEC_IS80(chspec) 0 ++#endif ++#ifndef CHSPEC_IS160 ++#define CHSPEC_IS160(chspec) 0 ++#endif ++#ifndef CHSPEC_IS8080 ++#define CHSPEC_IS8080(chspec) 0 ++#endif ++ ++#else /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) ++#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) ++#ifndef CHSPEC_IS40 ++#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) ++#endif ++#ifndef CHSPEC_IS80 ++#define CHSPEC_IS80(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80) ++#endif ++#ifndef CHSPEC_IS160 ++#define CHSPEC_IS160(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_160) ++#endif ++#ifndef CHSPEC_IS8080 ++#define CHSPEC_IS8080(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_8080) ++#endif ++ ++#endif /* !WL11N_20MHZONLY */ ++ ++#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) ++#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) ++#define CHSPEC_SB_UPPER(chspec) \ ++ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) && \ ++ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) ++#define CHSPEC_SB_LOWER(chspec) \ ++ ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) && \ ++ (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) ++#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G) ++ ++/** ++ * Number of chars needed for wf_chspec_ntoa() destination character buffer. ++ */ ++#define CHANSPEC_STR_LEN 20 ++ ++ ++/* Legacy Chanspec defines ++ * These are the defines for the previous format of the chanspec_t ++ */ ++#define WL_LCHANSPEC_CHAN_MASK 0x00ff ++#define WL_LCHANSPEC_CHAN_SHIFT 0 ++ ++#define WL_LCHANSPEC_CTL_SB_MASK 0x0300 ++#define WL_LCHANSPEC_CTL_SB_SHIFT 8 ++#define WL_LCHANSPEC_CTL_SB_LOWER 0x0100 ++#define WL_LCHANSPEC_CTL_SB_UPPER 0x0200 ++#define WL_LCHANSPEC_CTL_SB_NONE 0x0300 ++ ++#define WL_LCHANSPEC_BW_MASK 0x0C00 ++#define WL_LCHANSPEC_BW_SHIFT 10 ++#define WL_LCHANSPEC_BW_10 0x0400 ++#define WL_LCHANSPEC_BW_20 0x0800 ++#define WL_LCHANSPEC_BW_40 0x0C00 ++ ++#define WL_LCHANSPEC_BAND_MASK 0xf000 ++#define WL_LCHANSPEC_BAND_SHIFT 12 ++#define WL_LCHANSPEC_BAND_5G 0x1000 ++#define WL_LCHANSPEC_BAND_2G 0x2000 ++ ++#define LCHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_LCHANSPEC_CHAN_MASK)) ++#define LCHSPEC_BAND(chspec) ((chspec) & WL_LCHANSPEC_BAND_MASK) ++#define LCHSPEC_CTL_SB(chspec) ((chspec) & WL_LCHANSPEC_CTL_SB_MASK) ++#define LCHSPEC_BW(chspec) ((chspec) & WL_LCHANSPEC_BW_MASK) ++#define LCHSPEC_IS10(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_10) ++#define LCHSPEC_IS20(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_20) ++#define LCHSPEC_IS40(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40) ++#define LCHSPEC_IS5G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G) ++#define LCHSPEC_IS2G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G) ++ ++#define LCHSPEC_CREATE(chan, band, bw, sb) ((uint16)((chan) | (sb) | (bw) | (band))) ++ ++#endif /* D11AC_IOTYPES */ ++ ++/* ++ * WF_CHAN_FACTOR_* constants are used to calculate channel frequency ++ * given a channel number. ++ * chan_freq = chan_factor * 500Mhz + chan_number * 5 ++ */ ++ ++/** ++ * Channel Factor for the starting frequence of 2.4 GHz channels. ++ * The value corresponds to 2407 MHz. ++ */ ++#define WF_CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */ ++ ++/** ++ * Channel Factor for the starting frequence of 5 GHz channels. ++ * The value corresponds to 5000 MHz. ++ */ ++#define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */ ++ ++/** ++ * Channel Factor for the starting frequence of 4.9 GHz channels. ++ * The value corresponds to 4000 MHz. ++ */ ++#define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */ ++ ++/* defined rate in 500kbps */ ++#define WLC_MAXRATE 108 /* in 500kbps units */ ++#define WLC_RATE_1M 2 /* in 500kbps units */ ++#define WLC_RATE_2M 4 /* in 500kbps units */ ++#define WLC_RATE_5M5 11 /* in 500kbps units */ ++#define WLC_RATE_11M 22 /* in 500kbps units */ ++#define WLC_RATE_6M 12 /* in 500kbps units */ ++#define WLC_RATE_9M 18 /* in 500kbps units */ ++#define WLC_RATE_12M 24 /* in 500kbps units */ ++#define WLC_RATE_18M 36 /* in 500kbps units */ ++#define WLC_RATE_24M 48 /* in 500kbps units */ ++#define WLC_RATE_36M 72 /* in 500kbps units */ ++#define WLC_RATE_48M 96 /* in 500kbps units */ ++#define WLC_RATE_54M 108 /* in 500kbps units */ ++ ++#define WLC_2G_25MHZ_OFFSET 5 /* 2.4GHz band channel offset */ ++ ++/** ++ * Convert chanspec to ascii string ++ * ++ * @param chspec chanspec format ++ * @param buf ascii string of chanspec ++ * ++ * @return pointer to buf with room for at least CHANSPEC_STR_LEN bytes ++ * ++ * @see CHANSPEC_STR_LEN ++ */ ++extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf); ++ ++/** ++ * Convert ascii string to chanspec ++ * ++ * @param a pointer to input string ++ * ++ * @return >= 0 if successful or 0 otherwise ++ */ ++extern chanspec_t wf_chspec_aton(const char *a); ++ ++/** ++ * Verify the chanspec fields are valid. ++ * ++ * Verify the chanspec is using a legal set field values, i.e. that the chanspec ++ * specified a band, bw, ctl_sb and channel and that the combination could be ++ * legal given some set of circumstances. ++ * ++ * @param chanspec input chanspec to verify ++ * ++ * @return TRUE if the chanspec is malformed, FALSE if it looks good. ++ */ ++extern bool wf_chspec_malformed(chanspec_t chanspec); ++ ++/** ++ * Verify the chanspec specifies a valid channel according to 802.11. ++ * ++ * @param chanspec input chanspec to verify ++ * ++ * @return TRUE if the chanspec is a valid 802.11 channel ++ */ ++extern bool wf_chspec_valid(chanspec_t chanspec); ++ ++/** ++ * Return the primary (control) channel. ++ * ++ * This function returns the channel number of the primary 20MHz channel. For ++ * 20MHz channels this is just the channel number. For 40MHz or wider channels ++ * it is the primary 20MHz channel specified by the chanspec. ++ * ++ * @param chspec input chanspec ++ * ++ * @return Returns the channel number of the primary 20MHz channel ++ */ ++extern uint8 wf_chspec_ctlchan(chanspec_t chspec); ++ ++/** ++ * Return the primary (control) chanspec. ++ * ++ * This function returns the chanspec of the primary 20MHz channel. For 20MHz ++ * channels this is just the chanspec. For 40MHz or wider channels it is the ++ * chanspec of the primary 20MHZ channel specified by the chanspec. ++ * ++ * @param chspec input chanspec ++ * ++ * @return Returns the chanspec of the primary 20MHz channel ++ */ ++extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec); ++ ++/** ++ * Return a channel number corresponding to a frequency. ++ * ++ * This function returns the chanspec for the primary 40MHz of an 80MHz channel. ++ * The control sideband specifies the same 20MHz channel that the 80MHz channel is using ++ * as the primary 20MHz channel. ++ */ ++extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec); ++ ++/* ++ * Return the channel number for a given frequency and base frequency. ++ * The returned channel number is relative to the given base frequency. ++ * If the given base frequency is zero, a base frequency of 5 GHz is assumed for ++ * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz. ++ * ++ * Frequency is specified in MHz. ++ * The base frequency is specified as (start_factor * 500 kHz). ++ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for ++ * 2.4 GHz and 5 GHz bands. ++ * ++ * The returned channel will be in the range [1, 14] in the 2.4 GHz band ++ * and [0, 200] otherwise. ++ * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the ++ * frequency is not a 2.4 GHz channel, or if the frequency is not and even ++ * multiple of 5 MHz from the base frequency to the base plus 1 GHz. ++ * ++ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 ++ * ++ * @param freq frequency in MHz ++ * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz ++ * ++ * @return Returns a channel number ++ * ++ * @see WF_CHAN_FACTOR_2_4_G ++ * @see WF_CHAN_FACTOR_5_G ++ */ ++extern int wf_mhz2channel(uint freq, uint start_factor); ++ ++/** ++ * Return the center frequency in MHz of the given channel and base frequency. ++ * ++ * Return the center frequency in MHz of the given channel and base frequency. ++ * The channel number is interpreted relative to the given base frequency. ++ * ++ * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise. ++ * The base frequency is specified as (start_factor * 500 kHz). ++ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for ++ * 2.4 GHz and 5 GHz bands. ++ * The channel range of [1, 14] is only checked for a start_factor of ++ * WF_CHAN_FACTOR_2_4_G (4814). ++ * Odd start_factors produce channels on .5 MHz boundaries, in which case ++ * the answer is rounded down to an integral MHz. ++ * -1 is returned for an out of range channel. ++ * ++ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 ++ * ++ * @param channel input channel number ++ * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz ++ * ++ * @return Returns a frequency in MHz ++ * ++ * @see WF_CHAN_FACTOR_2_4_G ++ * @see WF_CHAN_FACTOR_5_G ++ */ ++extern int wf_channel2mhz(uint channel, uint start_factor); ++ ++/** ++ * Convert ctl chan and bw to chanspec ++ * ++ * @param ctl_ch channel ++ * @param bw bandwidth ++ * ++ * @return > 0 if successful or 0 otherwise ++ * ++ */ ++extern uint16 wf_channel2chspec(uint ctl_ch, uint bw); ++ ++#endif /* _bcmwifi_channels_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/bcmwifi_rates.h b/drivers/net/wireless/ap6210/include/bcmwifi_rates.h +new file mode 100755 +index 0000000..ddc6ab5 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/bcmwifi_rates.h +@@ -0,0 +1,318 @@ ++/* ++ * Indices for 802.11 a/b/g/n/ac 1-3 chain symmetric transmit rates ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmwifi_rates.h 252708 2011-04-12 06:45:56Z $ ++ */ ++ ++#ifndef _bcmwifi_rates_h_ ++#define _bcmwifi_rates_h_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif /* __cplusplus */ ++ ++ ++#define WL_RATESET_SZ_DSSS 4 ++#define WL_RATESET_SZ_OFDM 8 ++#define WL_RATESET_SZ_HT_MCS 8 ++#define WL_RATESET_SZ_VHT_MCS 10 ++ ++#define WL_TX_CHAINS_MAX 3 ++ ++#define WL_RATE_DISABLED (-128) /* Power value corresponding to unsupported rate */ ++ ++/* Transmit channel bandwidths */ ++typedef enum wl_tx_bw { ++ WL_TX_BW_20, ++ WL_TX_BW_40, ++ WL_TX_BW_80, ++ WL_TX_BW_20IN40, ++ WL_TX_BW_20IN80, ++ WL_TX_BW_40IN80, ++ WL_TX_BW_ALL ++} wl_tx_bw_t; ++ ++ ++/* ++ * Transmit modes. ++ * Not all modes are listed here, only those required for disambiguation. e.g. SPEXP is not listed ++ */ ++typedef enum wl_tx_mode { ++ WL_TX_MODE_NONE, ++ WL_TX_MODE_STBC, ++ WL_TX_MODE_CDD, ++ WL_TX_MODE_SDM ++} wl_tx_mode_t; ++ ++ ++/* Number of transmit chains */ ++typedef enum wl_tx_chains { ++ WL_TX_CHAINS_1 = 1, ++ WL_TX_CHAINS_2, ++ WL_TX_CHAINS_3 ++} wl_tx_chains_t; ++ ++ ++/* Number of transmit streams */ ++typedef enum wl_tx_nss { ++ WL_TX_NSS_1 = 1, ++ WL_TX_NSS_2, ++ WL_TX_NSS_3 ++} wl_tx_nss_t; ++ ++ ++typedef enum clm_rates { ++ /************ ++ * 1 chain * ++ ************ ++ */ ++ ++ /* 1 Stream */ ++ WL_RATE_1X1_DSSS_1 = 0, ++ WL_RATE_1X1_DSSS_2 = 1, ++ WL_RATE_1X1_DSSS_5_5 = 2, ++ WL_RATE_1X1_DSSS_11 = 3, ++ ++ WL_RATE_1X1_OFDM_6 = 4, ++ WL_RATE_1X1_OFDM_9 = 5, ++ WL_RATE_1X1_OFDM_12 = 6, ++ WL_RATE_1X1_OFDM_18 = 7, ++ WL_RATE_1X1_OFDM_24 = 8, ++ WL_RATE_1X1_OFDM_36 = 9, ++ WL_RATE_1X1_OFDM_48 = 10, ++ WL_RATE_1X1_OFDM_54 = 11, ++ ++ WL_RATE_1X1_MCS0 = 12, ++ WL_RATE_1X1_MCS1 = 13, ++ WL_RATE_1X1_MCS2 = 14, ++ WL_RATE_1X1_MCS3 = 15, ++ WL_RATE_1X1_MCS4 = 16, ++ WL_RATE_1X1_MCS5 = 17, ++ WL_RATE_1X1_MCS6 = 18, ++ WL_RATE_1X1_MCS7 = 19, ++ ++ WL_RATE_1X1_VHT0SS1 = 12, ++ WL_RATE_1X1_VHT1SS1 = 13, ++ WL_RATE_1X1_VHT2SS1 = 14, ++ WL_RATE_1X1_VHT3SS1 = 15, ++ WL_RATE_1X1_VHT4SS1 = 16, ++ WL_RATE_1X1_VHT5SS1 = 17, ++ WL_RATE_1X1_VHT6SS1 = 18, ++ WL_RATE_1X1_VHT7SS1 = 19, ++ WL_RATE_1X1_VHT8SS1 = 20, ++ WL_RATE_1X1_VHT9SS1 = 21, ++ ++ ++ /************ ++ * 2 chains * ++ ************ ++ */ ++ ++ /* 1 Stream expanded + 1 */ ++ WL_RATE_1X2_DSSS_1 = 22, ++ WL_RATE_1X2_DSSS_2 = 23, ++ WL_RATE_1X2_DSSS_5_5 = 24, ++ WL_RATE_1X2_DSSS_11 = 25, ++ ++ WL_RATE_1X2_CDD_OFDM_6 = 26, ++ WL_RATE_1X2_CDD_OFDM_9 = 27, ++ WL_RATE_1X2_CDD_OFDM_12 = 28, ++ WL_RATE_1X2_CDD_OFDM_18 = 29, ++ WL_RATE_1X2_CDD_OFDM_24 = 30, ++ WL_RATE_1X2_CDD_OFDM_36 = 31, ++ WL_RATE_1X2_CDD_OFDM_48 = 32, ++ WL_RATE_1X2_CDD_OFDM_54 = 33, ++ ++ WL_RATE_1X2_CDD_MCS0 = 34, ++ WL_RATE_1X2_CDD_MCS1 = 35, ++ WL_RATE_1X2_CDD_MCS2 = 36, ++ WL_RATE_1X2_CDD_MCS3 = 37, ++ WL_RATE_1X2_CDD_MCS4 = 38, ++ WL_RATE_1X2_CDD_MCS5 = 39, ++ WL_RATE_1X2_CDD_MCS6 = 40, ++ WL_RATE_1X2_CDD_MCS7 = 41, ++ ++ WL_RATE_1X2_VHT0SS1 = 34, ++ WL_RATE_1X2_VHT1SS1 = 35, ++ WL_RATE_1X2_VHT2SS1 = 36, ++ WL_RATE_1X2_VHT3SS1 = 37, ++ WL_RATE_1X2_VHT4SS1 = 38, ++ WL_RATE_1X2_VHT5SS1 = 39, ++ WL_RATE_1X2_VHT6SS1 = 40, ++ WL_RATE_1X2_VHT7SS1 = 41, ++ WL_RATE_1X2_VHT8SS1 = 42, ++ WL_RATE_1X2_VHT9SS1 = 43, ++ ++ /* 2 Streams */ ++ WL_RATE_2X2_STBC_MCS0 = 44, ++ WL_RATE_2X2_STBC_MCS1 = 45, ++ WL_RATE_2X2_STBC_MCS2 = 46, ++ WL_RATE_2X2_STBC_MCS3 = 47, ++ WL_RATE_2X2_STBC_MCS4 = 48, ++ WL_RATE_2X2_STBC_MCS5 = 49, ++ WL_RATE_2X2_STBC_MCS6 = 50, ++ WL_RATE_2X2_STBC_MCS7 = 51, ++ ++ WL_RATE_2X2_STBC_VHT0SS1 = 44, ++ WL_RATE_2X2_STBC_VHT1SS1 = 45, ++ WL_RATE_2X2_STBC_VHT2SS1 = 46, ++ WL_RATE_2X2_STBC_VHT3SS1 = 47, ++ WL_RATE_2X2_STBC_VHT4SS1 = 48, ++ WL_RATE_2X2_STBC_VHT5SS1 = 49, ++ WL_RATE_2X2_STBC_VHT6SS1 = 50, ++ WL_RATE_2X2_STBC_VHT7SS1 = 51, ++ WL_RATE_2X2_STBC_VHT8SS1 = 52, ++ WL_RATE_2X2_STBC_VHT9SS1 = 53, ++ ++ WL_RATE_2X2_SDM_MCS8 = 54, ++ WL_RATE_2X2_SDM_MCS9 = 55, ++ WL_RATE_2X2_SDM_MCS10 = 56, ++ WL_RATE_2X2_SDM_MCS11 = 57, ++ WL_RATE_2X2_SDM_MCS12 = 58, ++ WL_RATE_2X2_SDM_MCS13 = 59, ++ WL_RATE_2X2_SDM_MCS14 = 60, ++ WL_RATE_2X2_SDM_MCS15 = 61, ++ ++ WL_RATE_2X2_VHT0SS2 = 54, ++ WL_RATE_2X2_VHT1SS2 = 55, ++ WL_RATE_2X2_VHT2SS2 = 56, ++ WL_RATE_2X2_VHT3SS2 = 57, ++ WL_RATE_2X2_VHT4SS2 = 58, ++ WL_RATE_2X2_VHT5SS2 = 59, ++ WL_RATE_2X2_VHT6SS2 = 60, ++ WL_RATE_2X2_VHT7SS2 = 61, ++ WL_RATE_2X2_VHT8SS2 = 62, ++ WL_RATE_2X2_VHT9SS2 = 63, ++ ++ ++ /************ ++ * 3 chains * ++ ************ ++ */ ++ ++ /* 1 Stream expanded + 2 */ ++ WL_RATE_1X3_DSSS_1 = 64, ++ WL_RATE_1X3_DSSS_2 = 65, ++ WL_RATE_1X3_DSSS_5_5 = 66, ++ WL_RATE_1X3_DSSS_11 = 67, ++ ++ WL_RATE_1X3_CDD_OFDM_6 = 68, ++ WL_RATE_1X3_CDD_OFDM_9 = 69, ++ WL_RATE_1X3_CDD_OFDM_12 = 70, ++ WL_RATE_1X3_CDD_OFDM_18 = 71, ++ WL_RATE_1X3_CDD_OFDM_24 = 72, ++ WL_RATE_1X3_CDD_OFDM_36 = 73, ++ WL_RATE_1X3_CDD_OFDM_48 = 74, ++ WL_RATE_1X3_CDD_OFDM_54 = 75, ++ ++ WL_RATE_1X3_CDD_MCS0 = 76, ++ WL_RATE_1X3_CDD_MCS1 = 77, ++ WL_RATE_1X3_CDD_MCS2 = 78, ++ WL_RATE_1X3_CDD_MCS3 = 79, ++ WL_RATE_1X3_CDD_MCS4 = 80, ++ WL_RATE_1X3_CDD_MCS5 = 81, ++ WL_RATE_1X3_CDD_MCS6 = 82, ++ WL_RATE_1X3_CDD_MCS7 = 83, ++ ++ WL_RATE_1X3_VHT0SS1 = 76, ++ WL_RATE_1X3_VHT1SS1 = 77, ++ WL_RATE_1X3_VHT2SS1 = 78, ++ WL_RATE_1X3_VHT3SS1 = 79, ++ WL_RATE_1X3_VHT4SS1 = 80, ++ WL_RATE_1X3_VHT5SS1 = 81, ++ WL_RATE_1X3_VHT6SS1 = 82, ++ WL_RATE_1X3_VHT7SS1 = 83, ++ WL_RATE_1X3_VHT8SS1 = 84, ++ WL_RATE_1X3_VHT9SS1 = 85, ++ ++ /* 2 Streams expanded + 1 */ ++ WL_RATE_2X3_STBC_MCS0 = 86, ++ WL_RATE_2X3_STBC_MCS1 = 87, ++ WL_RATE_2X3_STBC_MCS2 = 88, ++ WL_RATE_2X3_STBC_MCS3 = 89, ++ WL_RATE_2X3_STBC_MCS4 = 90, ++ WL_RATE_2X3_STBC_MCS5 = 91, ++ WL_RATE_2X3_STBC_MCS6 = 92, ++ WL_RATE_2X3_STBC_MCS7 = 93, ++ ++ WL_RATE_2X3_STBC_VHT0SS1 = 86, ++ WL_RATE_2X3_STBC_VHT1SS1 = 87, ++ WL_RATE_2X3_STBC_VHT2SS1 = 88, ++ WL_RATE_2X3_STBC_VHT3SS1 = 89, ++ WL_RATE_2X3_STBC_VHT4SS1 = 90, ++ WL_RATE_2X3_STBC_VHT5SS1 = 91, ++ WL_RATE_2X3_STBC_VHT6SS1 = 92, ++ WL_RATE_2X3_STBC_VHT7SS1 = 93, ++ WL_RATE_2X3_STBC_VHT8SS1 = 94, ++ WL_RATE_2X3_STBC_VHT9SS1 = 95, ++ ++ WL_RATE_2X3_SDM_MCS8 = 96, ++ WL_RATE_2X3_SDM_MCS9 = 97, ++ WL_RATE_2X3_SDM_MCS10 = 98, ++ WL_RATE_2X3_SDM_MCS11 = 99, ++ WL_RATE_2X3_SDM_MCS12 = 100, ++ WL_RATE_2X3_SDM_MCS13 = 101, ++ WL_RATE_2X3_SDM_MCS14 = 102, ++ WL_RATE_2X3_SDM_MCS15 = 103, ++ ++ WL_RATE_2X3_VHT0SS2 = 96, ++ WL_RATE_2X3_VHT1SS2 = 97, ++ WL_RATE_2X3_VHT2SS2 = 98, ++ WL_RATE_2X3_VHT3SS2 = 99, ++ WL_RATE_2X3_VHT4SS2 = 100, ++ WL_RATE_2X3_VHT5SS2 = 101, ++ WL_RATE_2X3_VHT6SS2 = 102, ++ WL_RATE_2X3_VHT7SS2 = 103, ++ WL_RATE_2X3_VHT8SS2 = 104, ++ WL_RATE_2X3_VHT9SS2 = 105, ++ ++ /* 3 Streams */ ++ WL_RATE_3X3_SDM_MCS16 = 106, ++ WL_RATE_3X3_SDM_MCS17 = 107, ++ WL_RATE_3X3_SDM_MCS18 = 108, ++ WL_RATE_3X3_SDM_MCS19 = 109, ++ WL_RATE_3X3_SDM_MCS20 = 110, ++ WL_RATE_3X3_SDM_MCS21 = 111, ++ WL_RATE_3X3_SDM_MCS22 = 112, ++ WL_RATE_3X3_SDM_MCS23 = 113, ++ ++ WL_RATE_3X3_VHT0SS3 = 106, ++ WL_RATE_3X3_VHT1SS3 = 107, ++ WL_RATE_3X3_VHT2SS3 = 108, ++ WL_RATE_3X3_VHT3SS3 = 109, ++ WL_RATE_3X3_VHT4SS3 = 110, ++ WL_RATE_3X3_VHT5SS3 = 111, ++ WL_RATE_3X3_VHT6SS3 = 112, ++ WL_RATE_3X3_VHT7SS3 = 113, ++ WL_RATE_3X3_VHT8SS3 = 114, ++ WL_RATE_3X3_VHT9SS3 = 115, ++ ++ /* Number of rate codes */ ++ WL_NUMRATES = 116 ++} clm_rates_t; ++ ++#ifdef __cplusplus ++} ++#endif /* __cplusplus */ ++ ++#endif /* _bcmwifi_rates_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/dhdioctl.h b/drivers/net/wireless/ap6210/include/dhdioctl.h +new file mode 100755 +index 0000000..6909dc2 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/dhdioctl.h +@@ -0,0 +1,136 @@ ++/* ++ * Definitions for ioctls to access DHD iovars. ++ * Based on wlioctl.h (for Broadcom 802.11abg driver). ++ * (Moves towards generic ioctls for BCM drivers/iovars.) ++ * ++ * Definitions subject to change without notice. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhdioctl.h 354894 2012-09-04 12:34:07Z $ ++ */ ++ ++#ifndef _dhdioctl_h_ ++#define _dhdioctl_h_ ++ ++#include ++ ++ ++/* require default structure packing */ ++#define BWL_DEFAULT_PACKING ++#include ++ ++ ++/* Linux network driver ioctl encoding */ ++typedef struct dhd_ioctl { ++ uint cmd; /* common ioctl definition */ ++ void *buf; /* pointer to user buffer */ ++ uint len; /* length of user buffer */ ++ bool set; /* get or set request (optional) */ ++ uint used; /* bytes read or written (optional) */ ++ uint needed; /* bytes needed (optional) */ ++ uint driver; /* to identify target driver */ ++} dhd_ioctl_t; ++ ++/* Underlying BUS definition */ ++enum { ++ BUS_TYPE_USB = 0, /* for USB dongles */ ++ BUS_TYPE_SDIO /* for SDIO dongles */ ++}; ++ ++/* per-driver magic numbers */ ++#define DHD_IOCTL_MAGIC 0x00444944 ++ ++/* bump this number if you change the ioctl interface */ ++#define DHD_IOCTL_VERSION 1 ++ ++#define DHD_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */ ++#define DHD_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */ ++ ++/* common ioctl definitions */ ++#define DHD_GET_MAGIC 0 ++#define DHD_GET_VERSION 1 ++#define DHD_GET_VAR 2 ++#define DHD_SET_VAR 3 ++ ++/* message levels */ ++#define DHD_ERROR_VAL 0x0001 ++#define DHD_TRACE_VAL 0x0002 ++#define DHD_INFO_VAL 0x0004 ++#define DHD_DATA_VAL 0x0008 ++#define DHD_CTL_VAL 0x0010 ++#define DHD_TIMER_VAL 0x0020 ++#define DHD_HDRS_VAL 0x0040 ++#define DHD_BYTES_VAL 0x0080 ++#define DHD_INTR_VAL 0x0100 ++#define DHD_LOG_VAL 0x0200 ++#define DHD_GLOM_VAL 0x0400 ++#define DHD_EVENT_VAL 0x0800 ++#define DHD_BTA_VAL 0x1000 ++#if 0 && (NDISVER >= 0x0630) && 1 ++#define DHD_SCAN_VAL 0x2000 ++#else ++#define DHD_ISCAN_VAL 0x2000 ++#endif ++#define DHD_ARPOE_VAL 0x4000 ++#define DHD_REORDER_VAL 0x8000 ++#define DHD_IW_VAL 0x10000 ++#define DHD_CFG_VAL 0x20000 ++ ++#ifdef SDTEST ++/* For pktgen iovar */ ++typedef struct dhd_pktgen { ++ uint version; /* To allow structure change tracking */ ++ uint freq; /* Max ticks between tx/rx attempts */ ++ uint count; /* Test packets to send/rcv each attempt */ ++ uint print; /* Print counts every attempts */ ++ uint total; /* Total packets (or bursts) */ ++ uint minlen; /* Minimum length of packets to send */ ++ uint maxlen; /* Maximum length of packets to send */ ++ uint numsent; /* Count of test packets sent */ ++ uint numrcvd; /* Count of test packets received */ ++ uint numfail; /* Count of test send failures */ ++ uint mode; /* Test mode (type of test packets) */ ++ uint stop; /* Stop after this many tx failures */ ++} dhd_pktgen_t; ++ ++/* Version in case structure changes */ ++#define DHD_PKTGEN_VERSION 2 ++ ++/* Type of test packets to use */ ++#define DHD_PKTGEN_ECHO 1 /* Send echo requests */ ++#define DHD_PKTGEN_SEND 2 /* Send discard packets */ ++#define DHD_PKTGEN_RXBURST 3 /* Request dongle send N packets */ ++#define DHD_PKTGEN_RECV 4 /* Continuous rx from continuous tx dongle */ ++#endif /* SDTEST */ ++ ++/* Enter idle immediately (no timeout) */ ++#define DHD_IDLE_IMMEDIATE (-1) ++ ++/* Values for idleclock iovar: other values are the sd_divisor to use when idle */ ++#define DHD_IDLE_ACTIVE 0 /* Do not request any SD clock change when idle */ ++#define DHD_IDLE_STOP (-1) /* Request SD clock be stopped (and use SD1 mode) */ ++ ++ ++/* require default structure packing */ ++#include ++ ++#endif /* _dhdioctl_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/epivers.h b/drivers/net/wireless/ap6210/include/epivers.h +new file mode 100755 +index 0000000..cff9ebd +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/epivers.h +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: epivers.h.in,v 13.33 2010-09-08 22:08:53 csm Exp $ ++ * ++*/ ++ ++#ifndef _epivers_h_ ++#define _epivers_h_ ++ ++#define EPI_MAJOR_VERSION 1 ++ ++#define EPI_MINOR_VERSION 28 ++ ++#define EPI_RC_NUMBER 23 ++ ++#define EPI_INCREMENTAL_NUMBER 0 ++ ++#define EPI_BUILD_NUMBER 0 ++ ++#define EPI_VERSION 1, 28, 23, 0 ++ ++#define EPI_VERSION_NUM 0x011c1700 ++ ++#define EPI_VERSION_DEV 1.28.23 ++ ++/* Driver Version String, ASCII, 32 chars max */ ++#ifdef BCMINTERNAL ++#define EPI_VERSION_STR "1.28.23.3 (r BCMINT)" ++#else ++#ifdef WLTEST ++#define EPI_VERSION_STR "1.28.23.3 (r WLTEST)" ++#else ++#define EPI_VERSION_STR "1.28.23.3 (r)" ++#endif ++#endif /* BCMINTERNAL */ ++ ++#endif /* _epivers_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/hndpmu.h b/drivers/net/wireless/ap6210/include/hndpmu.h +new file mode 100755 +index 0000000..c41def6 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/hndpmu.h +@@ -0,0 +1,36 @@ ++/* ++ * HND SiliconBackplane PMU support. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: hndpmu.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _hndpmu_h_ ++#define _hndpmu_h_ ++ ++ ++extern void si_pmu_otp_power(si_t *sih, osl_t *osh, bool on); ++extern void si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength); ++ ++extern void si_pmu_minresmask_htavail_set(si_t *sih, osl_t *osh, bool set_clear); ++ ++#endif /* _hndpmu_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/hndrte_armtrap.h b/drivers/net/wireless/ap6210/include/hndrte_armtrap.h +new file mode 100755 +index 0000000..90d9799 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/hndrte_armtrap.h +@@ -0,0 +1,88 @@ ++/* ++ * HNDRTE arm trap handling. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: hndrte_armtrap.h 261365 2011-05-24 20:42:23Z $ ++ */ ++ ++#ifndef _hndrte_armtrap_h ++#define _hndrte_armtrap_h ++ ++ ++/* ARM trap handling */ ++ ++/* Trap types defined by ARM (see arminc.h) */ ++ ++/* Trap locations in lo memory */ ++#define TRAP_STRIDE 4 ++#define FIRST_TRAP TR_RST ++#define LAST_TRAP (TR_FIQ * TRAP_STRIDE) ++ ++#if defined(__ARM_ARCH_4T__) ++#define MAX_TRAP_TYPE (TR_FIQ + 1) ++#elif defined(__ARM_ARCH_7M__) ++#define MAX_TRAP_TYPE (TR_ISR + ARMCM3_NUMINTS) ++#endif /* __ARM_ARCH_7M__ */ ++ ++/* The trap structure is defined here as offsets for assembly */ ++#define TR_TYPE 0x00 ++#define TR_EPC 0x04 ++#define TR_CPSR 0x08 ++#define TR_SPSR 0x0c ++#define TR_REGS 0x10 ++#define TR_REG(n) (TR_REGS + (n) * 4) ++#define TR_SP TR_REG(13) ++#define TR_LR TR_REG(14) ++#define TR_PC TR_REG(15) ++ ++#define TRAP_T_SIZE 80 ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++#include ++ ++typedef struct _trap_struct { ++ uint32 type; ++ uint32 epc; ++ uint32 cpsr; ++ uint32 spsr; ++ uint32 r0; /* a1 */ ++ uint32 r1; /* a2 */ ++ uint32 r2; /* a3 */ ++ uint32 r3; /* a4 */ ++ uint32 r4; /* v1 */ ++ uint32 r5; /* v2 */ ++ uint32 r6; /* v3 */ ++ uint32 r7; /* v4 */ ++ uint32 r8; /* v5 */ ++ uint32 r9; /* sb/v6 */ ++ uint32 r10; /* sl/v7 */ ++ uint32 r11; /* fp/v8 */ ++ uint32 r12; /* ip */ ++ uint32 r13; /* sp */ ++ uint32 r14; /* lr */ ++ uint32 pc; /* r15 */ ++} trap_t; ++ ++#endif /* !_LANGUAGE_ASSEMBLY */ ++ ++#endif /* _hndrte_armtrap_h */ +diff --git a/drivers/net/wireless/ap6210/include/hndrte_cons.h b/drivers/net/wireless/ap6210/include/hndrte_cons.h +new file mode 100755 +index 0000000..57abbbd +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/hndrte_cons.h +@@ -0,0 +1,67 @@ ++/* ++ * Console support for hndrte. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: hndrte_cons.h 300516 2011-12-04 17:39:44Z $ ++ */ ++#ifndef _HNDRTE_CONS_H ++#define _HNDRTE_CONS_H ++ ++#include ++ ++#define CBUF_LEN (128) ++ ++#define LOG_BUF_LEN 1024 ++ ++typedef struct { ++ uint32 buf; /* Can't be pointer on (64-bit) hosts */ ++ uint buf_size; ++ uint idx; ++ char *_buf_compat; /* redundant pointer for backward compat. */ ++} hndrte_log_t; ++ ++typedef struct { ++ /* Virtual UART ++ * When there is no UART (e.g. Quickturn), the host should write a complete ++ * input line directly into cbuf and then write the length into vcons_in. ++ * This may also be used when there is a real UART (at risk of conflicting with ++ * the real UART). vcons_out is currently unused. ++ */ ++ volatile uint vcons_in; ++ volatile uint vcons_out; ++ ++ /* Output (logging) buffer ++ * Console output is written to a ring buffer log_buf at index log_idx. ++ * The host may read the output when it sees log_idx advance. ++ * Output will be lost if the output wraps around faster than the host polls. ++ */ ++ hndrte_log_t log; ++ ++ /* Console input line buffer ++ * Characters are read one at a time into cbuf until is received, then ++ * the buffer is processed as a command line. Also used for virtual UART. ++ */ ++ uint cbuf_idx; ++ char cbuf[CBUF_LEN]; ++} hndrte_cons_t; ++ ++#endif /* _HNDRTE_CONS_H */ +diff --git a/drivers/net/wireless/ap6210/include/hndsoc.h b/drivers/net/wireless/ap6210/include/hndsoc.h +new file mode 100755 +index 0000000..66640c3 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/hndsoc.h +@@ -0,0 +1,235 @@ ++/* ++ * Broadcom HND chip & on-chip-interconnect-related definitions. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: hndsoc.h 309193 2012-01-19 00:03:57Z $ ++ */ ++ ++#ifndef _HNDSOC_H ++#define _HNDSOC_H ++ ++/* Include the soci specific files */ ++#include ++#include ++ ++/* ++ * SOC Interconnect Address Map. ++ * All regions may not exist on all chips. ++ */ ++#define SI_SDRAM_BASE 0x00000000 /* Physical SDRAM */ ++#define SI_PCI_MEM 0x08000000 /* Host Mode sb2pcitranslation0 (64 MB) */ ++#define SI_PCI_MEM_SZ (64 * 1024 * 1024) ++#define SI_PCI_CFG 0x0c000000 /* Host Mode sb2pcitranslation1 (64 MB) */ ++#define SI_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */ ++#define SI_SDRAM_R2 0x80000000 /* Region 2 for sdram (512 MB) */ ++ ++#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */ ++ ++#define SI_WRAP_BASE 0x18100000 /* Wrapper space base */ ++#define SI_CORE_SIZE 0x1000 /* each core gets 4Kbytes for registers */ ++#define SI_MAXCORES 16 /* Max cores (this is arbitrary, for software ++ * convenience and could be changed if we ++ * make any larger chips ++ */ ++ ++#define SI_FASTRAM 0x19000000 /* On-chip RAM on chips that also have DDR */ ++#define SI_FASTRAM_SWAPPED 0x19800000 ++ ++#define SI_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */ ++#define SI_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */ ++#define SI_ARMCM3_ROM 0x1e000000 /* ARM Cortex-M3 ROM */ ++#define SI_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */ ++#define SI_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */ ++#define SI_ARM7S_ROM 0x20000000 /* ARM7TDMI-S ROM */ ++#define SI_ARMCR4_ROM 0x000f0000 /* ARM Cortex-R4 ROM */ ++#define SI_ARMCM3_SRAM2 0x60000000 /* ARM Cortex-M3 SRAM Region 2 */ ++#define SI_ARM7S_SRAM2 0x80000000 /* ARM7TDMI-S SRAM Region 2 */ ++#define SI_ARM_FLASH1 0xffff0000 /* ARM Flash Region 1 */ ++#define SI_ARM_FLASH1_SZ 0x00010000 /* ARM Size of Flash Region 1 */ ++ ++#define SI_PCI_DMA 0x40000000 /* Client Mode sb2pcitranslation2 (1 GB) */ ++#define SI_PCI_DMA2 0x80000000 /* Client Mode sb2pcitranslation2 (1 GB) */ ++#define SI_PCI_DMA_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */ ++#define SI_PCIE_DMA_L32 0x00000000 /* PCIE Client Mode sb2pcitranslation2 ++ * (2 ZettaBytes), low 32 bits ++ */ ++#define SI_PCIE_DMA_H32 0x80000000 /* PCIE Client Mode sb2pcitranslation2 ++ * (2 ZettaBytes), high 32 bits ++ */ ++ ++/* core codes */ ++#define NODEV_CORE_ID 0x700 /* Invalid coreid */ ++#define CC_CORE_ID 0x800 /* chipcommon core */ ++#define ILINE20_CORE_ID 0x801 /* iline20 core */ ++#define SRAM_CORE_ID 0x802 /* sram core */ ++#define SDRAM_CORE_ID 0x803 /* sdram core */ ++#define PCI_CORE_ID 0x804 /* pci core */ ++#define MIPS_CORE_ID 0x805 /* mips core */ ++#define ENET_CORE_ID 0x806 /* enet mac core */ ++#define CODEC_CORE_ID 0x807 /* v90 codec core */ ++#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */ ++#define ADSL_CORE_ID 0x809 /* ADSL core */ ++#define ILINE100_CORE_ID 0x80a /* iline100 core */ ++#define IPSEC_CORE_ID 0x80b /* ipsec core */ ++#define UTOPIA_CORE_ID 0x80c /* utopia core */ ++#define PCMCIA_CORE_ID 0x80d /* pcmcia core */ ++#define SOCRAM_CORE_ID 0x80e /* internal memory core */ ++#define MEMC_CORE_ID 0x80f /* memc sdram core */ ++#define OFDM_CORE_ID 0x810 /* OFDM phy core */ ++#define EXTIF_CORE_ID 0x811 /* external interface core */ ++#define D11_CORE_ID 0x812 /* 802.11 MAC core */ ++#define APHY_CORE_ID 0x813 /* 802.11a phy core */ ++#define BPHY_CORE_ID 0x814 /* 802.11b phy core */ ++#define GPHY_CORE_ID 0x815 /* 802.11g phy core */ ++#define MIPS33_CORE_ID 0x816 /* mips3302 core */ ++#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */ ++#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */ ++#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */ ++#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */ ++#define SDIOH_CORE_ID 0x81b /* sdio host core */ ++#define ROBO_CORE_ID 0x81c /* roboswitch core */ ++#define ATA100_CORE_ID 0x81d /* parallel ATA core */ ++#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */ ++#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */ ++#define PCIE_CORE_ID 0x820 /* pci express core */ ++#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */ ++#define SRAMC_CORE_ID 0x822 /* SRAM controller core */ ++#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */ ++#define ARM11_CORE_ID 0x824 /* ARM 1176 core */ ++#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */ ++#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */ ++#define PMU_CORE_ID 0x827 /* PMU core */ ++#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */ ++#define SDIOD_CORE_ID 0x829 /* SDIO device core */ ++#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */ ++#define HTPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */ ++#define MIPS74K_CORE_ID 0x82c /* mips 74k core */ ++#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ ++#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */ ++#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */ ++#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */ ++#define SC_CORE_ID 0x831 /* shared common core */ ++#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */ ++#define SPIH_CORE_ID 0x833 /* SPI host core */ ++#define I2S_CORE_ID 0x834 /* I2S core */ ++#define DMEMS_CORE_ID 0x835 /* SDR/DDR1 memory controller core */ ++#define DEF_SHIM_COMP 0x837 /* SHIM component in ubus/6362 */ ++ ++#define ACPHY_CORE_ID 0x83b /* Dot11 ACPHY */ ++#define PCIE2_CORE_ID 0x83c /* pci express Gen2 core */ ++#define USB30D_CORE_ID 0x83d /* usb 3.0 device core */ ++#define ARMCR4_CORE_ID 0x83e /* ARM CR4 CPU */ ++#define APB_BRIDGE_CORE_ID 0x135 /* APB bridge core ID */ ++#define AXI_CORE_ID 0x301 /* AXI/GPV core ID */ ++#define EROM_CORE_ID 0x366 /* EROM core ID */ ++#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ ++#define DEF_AI_COMP 0xfff /* Default component, in ai chips it maps all ++ * unused address ranges ++ */ ++ ++#define CC_4706_CORE_ID 0x500 /* chipcommon core */ ++#define SOCRAM_4706_CORE_ID 0x50e /* internal memory core */ ++#define GMAC_COMMON_4706_CORE_ID 0x5dc /* Gigabit MAC core */ ++#define GMAC_4706_CORE_ID 0x52d /* Gigabit MAC core */ ++#define AMEMC_CORE_ID 0x52e /* DDR1/2 memory controller core */ ++#define ALTA_CORE_ID 0x534 /* I2S core */ ++#define DDR23_PHY_CORE_ID 0x5dd ++ ++#define SI_PCI1_MEM 0x40000000 /* Host Mode sb2pcitranslation0 (64 MB) */ ++#define SI_PCI1_CFG 0x44000000 /* Host Mode sb2pcitranslation1 (64 MB) */ ++#define SI_PCIE1_DMA_H32 0xc0000000 /* PCIE Client Mode sb2pcitranslation2 ++ * (2 ZettaBytes), high 32 bits ++ */ ++#define CC_4706B0_CORE_REV 0x8000001f /* chipcommon core */ ++#define SOCRAM_4706B0_CORE_REV 0x80000005 /* internal memory core */ ++#define GMAC_4706B0_CORE_REV 0x80000000 /* Gigabit MAC core */ ++ ++/* There are TWO constants on all HND chips: SI_ENUM_BASE above, ++ * and chipcommon being the first core: ++ */ ++#define SI_CC_IDX 0 ++ ++/* SOC Interconnect types (aka chip types) */ ++#define SOCI_SB 0 ++#define SOCI_AI 1 ++#define SOCI_UBUS 2 ++ ++/* Common core control flags */ ++#define SICF_BIST_EN 0x8000 ++#define SICF_PME_EN 0x4000 ++#define SICF_CORE_BITS 0x3ffc ++#define SICF_FGC 0x0002 ++#define SICF_CLOCK_EN 0x0001 ++ ++/* Common core status flags */ ++#define SISF_BIST_DONE 0x8000 ++#define SISF_BIST_ERROR 0x4000 ++#define SISF_GATED_CLK 0x2000 ++#define SISF_DMA64 0x1000 ++#define SISF_CORE_BITS 0x0fff ++ ++/* A register that is common to all cores to ++ * communicate w/PMU regarding clock control. ++ */ ++#define SI_CLK_CTL_ST 0x1e0 /* clock control and status */ ++ ++/* clk_ctl_st register */ ++#define CCS_FORCEALP 0x00000001 /* force ALP request */ ++#define CCS_FORCEHT 0x00000002 /* force HT request */ ++#define CCS_FORCEILP 0x00000004 /* force ILP request */ ++#define CCS_ALPAREQ 0x00000008 /* ALP Avail Request */ ++#define CCS_HTAREQ 0x00000010 /* HT Avail Request */ ++#define CCS_FORCEHWREQOFF 0x00000020 /* Force HW Clock Request Off */ ++#define CCS_HQCLKREQ 0x00000040 /* HQ Clock Required */ ++#define CCS_USBCLKREQ 0x00000100 /* USB Clock Req */ ++#define CCS_ERSRC_REQ_MASK 0x00000700 /* external resource requests */ ++#define CCS_ERSRC_REQ_SHIFT 8 ++#define CCS_ALPAVAIL 0x00010000 /* ALP is available */ ++#define CCS_HTAVAIL 0x00020000 /* HT is available */ ++#define CCS_BP_ON_APL 0x00040000 /* RO: Backplane is running on ALP clock */ ++#define CCS_BP_ON_HT 0x00080000 /* RO: Backplane is running on HT clock */ ++#define CCS_ERSRC_STS_MASK 0x07000000 /* external resource status */ ++#define CCS_ERSRC_STS_SHIFT 24 ++ ++#define CCS0_HTAVAIL 0x00010000 /* HT avail in chipc and pcmcia on 4328a0 */ ++#define CCS0_ALPAVAIL 0x00020000 /* ALP avail in chipc and pcmcia on 4328a0 */ ++ ++/* Not really related to SOC Interconnect, but a couple of software ++ * conventions for the use the flash space: ++ */ ++ ++/* Minumum amount of flash we support */ ++#define FLASH_MIN 0x00020000 /* Minimum flash size */ ++ ++/* A boot/binary may have an embedded block that describes its size */ ++#define BISZ_OFFSET 0x3e0 /* At this offset into the binary */ ++#define BISZ_MAGIC 0x4249535a /* Marked with this value: 'BISZ' */ ++#define BISZ_MAGIC_IDX 0 /* Word 0: magic */ ++#define BISZ_TXTST_IDX 1 /* 1: text start */ ++#define BISZ_TXTEND_IDX 2 /* 2: text end */ ++#define BISZ_DATAST_IDX 3 /* 3: data start */ ++#define BISZ_DATAEND_IDX 4 /* 4: data end */ ++#define BISZ_BSSST_IDX 5 /* 5: bss start */ ++#define BISZ_BSSEND_IDX 6 /* 6: bss end */ ++#define BISZ_SIZE 7 /* descriptor size in 32-bit integers */ ++ ++#endif /* _HNDSOC_H */ +diff --git a/drivers/net/wireless/ap6210/include/linux_osl.h b/drivers/net/wireless/ap6210/include/linux_osl.h +new file mode 100755 +index 0000000..ca28f6b +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/linux_osl.h +@@ -0,0 +1,430 @@ ++/* ++ * Linux OS Independent Layer ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: linux_osl.h 354452 2012-08-31 04:59:17Z $ ++ */ ++ ++#ifndef _linux_osl_h_ ++#define _linux_osl_h_ ++ ++#include ++ ++/* Linux Kernel: File Operations: start */ ++extern void * osl_os_open_image(char * filename); ++extern int osl_os_get_image_block(char * buf, int len, void * image); ++extern void osl_os_close_image(void * image); ++extern int osl_os_image_size(void *image); ++/* Linux Kernel: File Operations: end */ ++ ++#ifdef BCMDRIVER ++ ++/* OSL initialization */ ++extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag); ++extern void osl_detach(osl_t *osh); ++ ++/* Global ASSERT type */ ++extern uint32 g_assert_type; ++ ++/* ASSERT */ ++#if defined(BCMASSERT_LOG) ++ #define ASSERT(exp) \ ++ do { if (!(exp)) osl_assert(#exp, __FILE__, __LINE__); } while (0) ++extern void osl_assert(const char *exp, const char *file, int line); ++#else ++ #ifdef __GNUC__ ++ #define GCC_VERSION \ ++ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) ++ #if GCC_VERSION > 30100 ++ #define ASSERT(exp) do {} while (0) ++ #else ++ /* ASSERT could cause segmentation fault on GCC3.1, use empty instead */ ++ #define ASSERT(exp) ++ #endif /* GCC_VERSION > 30100 */ ++ #endif /* __GNUC__ */ ++#endif ++ ++/* microsecond delay */ ++#define OSL_DELAY(usec) osl_delay(usec) ++extern void osl_delay(uint usec); ++ ++#define OSL_PCMCIA_READ_ATTR(osh, offset, buf, size) \ ++ osl_pcmcia_read_attr((osh), (offset), (buf), (size)) ++#define OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size) \ ++ osl_pcmcia_write_attr((osh), (offset), (buf), (size)) ++extern void osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size); ++extern void osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size); ++ ++/* PCI configuration space access macros */ ++#define OSL_PCI_READ_CONFIG(osh, offset, size) \ ++ osl_pci_read_config((osh), (offset), (size)) ++#define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \ ++ osl_pci_write_config((osh), (offset), (size), (val)) ++extern uint32 osl_pci_read_config(osl_t *osh, uint offset, uint size); ++extern void osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val); ++ ++/* PCI device bus # and slot # */ ++#define OSL_PCI_BUS(osh) osl_pci_bus(osh) ++#define OSL_PCI_SLOT(osh) osl_pci_slot(osh) ++extern uint osl_pci_bus(osl_t *osh); ++extern uint osl_pci_slot(osl_t *osh); ++extern struct pci_dev *osl_pci_device(osl_t *osh); ++ ++/* Pkttag flag should be part of public information */ ++typedef struct { ++ bool pkttag; ++ uint pktalloced; /* Number of allocated packet buffers */ ++ bool mmbus; /* Bus supports memory-mapped register accesses */ ++ pktfree_cb_fn_t tx_fn; /* Callback function for PKTFREE */ ++ void *tx_ctx; /* Context to the callback function */ ++ void *unused[3]; ++} osl_pubinfo_t; ++ ++#define PKTFREESETCB(osh, _tx_fn, _tx_ctx) \ ++ do { \ ++ ((osl_pubinfo_t*)osh)->tx_fn = _tx_fn; \ ++ ((osl_pubinfo_t*)osh)->tx_ctx = _tx_ctx; \ ++ } while (0) ++ ++ ++/* host/bus architecture-specific byte swap */ ++#define BUS_SWAP32(v) (v) ++ ++ #define MALLOC(osh, size) osl_malloc((osh), (size)) ++ #define MFREE(osh, addr, size) osl_mfree((osh), (addr), (size)) ++ #define MALLOCED(osh) osl_malloced((osh)) ++ extern void *osl_malloc(osl_t *osh, uint size); ++ extern void osl_mfree(osl_t *osh, void *addr, uint size); ++ extern uint osl_malloced(osl_t *osh); ++ ++#define NATIVE_MALLOC(osh, size) kmalloc(size, GFP_ATOMIC) ++#define NATIVE_MFREE(osh, addr, size) kfree(addr) ++ ++#define MALLOC_FAILED(osh) osl_malloc_failed((osh)) ++extern uint osl_malloc_failed(osl_t *osh); ++ ++/* allocate/free shared (dma-able) consistent memory */ ++#define DMA_CONSISTENT_ALIGN osl_dma_consistent_align() ++#define DMA_ALLOC_CONSISTENT(osh, size, align, tot, pap, dmah) \ ++ osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap)) ++#define DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \ ++ osl_dma_free_consistent((osh), (void*)(va), (size), (pa)) ++extern uint osl_dma_consistent_align(void); ++extern void *osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align, uint *tot, ulong *pap); ++extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa); ++ ++/* map/unmap direction */ ++#define DMA_TX 1 /* TX direction for DMA */ ++#define DMA_RX 2 /* RX direction for DMA */ ++ ++/* map/unmap shared (dma-able) memory */ ++#define DMA_UNMAP(osh, pa, size, direction, p, dmah) \ ++ osl_dma_unmap((osh), (pa), (size), (direction)) ++extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction); ++extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction); ++ ++/* API for DMA addressing capability */ ++#define OSL_DMADDRWIDTH(osh, addrwidth) do {} while (0) ++ ++/* register access macros */ ++ #include ++ #define OSL_WRITE_REG(osh, r, v) (bcmsdh_reg_write(NULL, (uintptr)(r), sizeof(*(r)), (v))) ++ #define OSL_READ_REG(osh, r) (bcmsdh_reg_read(NULL, (uintptr)(r), sizeof(*(r)))) ++ ++ #define SELECT_BUS_WRITE(osh, mmap_op, bus_op) if (((osl_pubinfo_t*)(osh))->mmbus) \ ++ mmap_op else bus_op ++ #define SELECT_BUS_READ(osh, mmap_op, bus_op) (((osl_pubinfo_t*)(osh))->mmbus) ? \ ++ mmap_op : bus_op ++ ++#define OSL_ERROR(bcmerror) osl_error(bcmerror) ++extern int osl_error(int bcmerror); ++ ++/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */ ++#define PKTBUFSZ 2048 /* largest reasonable packet buffer, driver uses for ethernet MTU */ ++ ++/* ++ * BINOSL selects the slightly slower function-call-based binary compatible osl. ++ * Macros expand to calls to functions defined in linux_osl.c . ++ */ ++#include /* use current 2.4.x calling conventions */ ++#include /* for vsn/printf's */ ++#include /* for mem*, str* */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 29) ++#define OSL_SYSUPTIME() ((uint32)jiffies_to_msecs(jiffies)) ++#else ++#define OSL_SYSUPTIME() ((uint32)jiffies * (1000 / HZ)) ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 29) */ ++#define printf(fmt, args...) pr_info(fmt , ## args) ++#include /* for vsn/printf's */ ++#include /* for mem*, str* */ ++/* bcopy's: Linux kernel doesn't provide these (anymore) */ ++#define bcopy(src, dst, len) memcpy((dst), (src), (len)) ++#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) ++#define bzero(b, len) memset((b), '\0', (len)) ++ ++/* register access macros */ ++ ++#define R_REG(osh, r) (\ ++ SELECT_BUS_READ(osh, \ ++ ({ \ ++ __typeof(*(r)) __osl_v; \ ++ BCM_REFERENCE(osh); \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): __osl_v = \ ++ readb((volatile uint8*)(r)); break; \ ++ case sizeof(uint16): __osl_v = \ ++ readw((volatile uint16*)(r)); break; \ ++ case sizeof(uint32): __osl_v = \ ++ readl((volatile uint32*)(r)); break; \ ++ } \ ++ __osl_v; \ ++ }), \ ++ OSL_READ_REG(osh, r)) \ ++) ++ ++#define W_REG(osh, r, v) do { \ ++ BCM_REFERENCE(osh); \ ++ SELECT_BUS_WRITE(osh, \ ++ switch (sizeof(*(r))) { \ ++ case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)(r)); break; \ ++ case sizeof(uint16): writew((uint16)(v), (volatile uint16*)(r)); break; \ ++ case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \ ++ }, \ ++ (OSL_WRITE_REG(osh, r, v))); \ ++ } while (0) ++ ++#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) ++#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) ++ ++/* bcopy, bcmp, and bzero functions */ ++#define bcopy(src, dst, len) memcpy((dst), (src), (len)) ++#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) ++#define bzero(b, len) memset((b), '\0', (len)) ++ ++/* uncached/cached virtual address */ ++#define OSL_UNCACHED(va) ((void *)va) ++#define OSL_CACHED(va) ((void *)va) ++ ++#define OSL_PREF_RANGE_LD(va, sz) ++#define OSL_PREF_RANGE_ST(va, sz) ++ ++/* get processor cycle count */ ++#if defined(__i386__) ++#define OSL_GETCYCLES(x) rdtscl((x)) ++#else ++#define OSL_GETCYCLES(x) ((x) = 0) ++#endif ++ ++/* dereference an address that may cause a bus exception */ ++#define BUSPROBE(val, addr) ({ (val) = R_REG(NULL, (addr)); 0; }) ++ ++/* map/unmap physical to virtual I/O */ ++#if !defined(CONFIG_MMC_MSM7X00A) ++#define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size)) ++#else ++#define REG_MAP(pa, size) (void *)(0) ++#endif /* !defined(CONFIG_MMC_MSM7X00A */ ++#define REG_UNMAP(va) iounmap((va)) ++ ++/* shared (dma-able) memory access macros */ ++#define R_SM(r) *(r) ++#define W_SM(r, v) (*(r) = (v)) ++#define BZERO_SM(r, len) memset((r), '\0', (len)) ++ ++/* Because the non BINOSL implemenation of the PKT OSL routines are macros (for ++ * performance reasons), we need the Linux headers. ++ */ ++#include /* use current 2.4.x calling conventions */ ++ ++/* packet primitives */ ++#define PKTGET(osh, len, send) osl_pktget((osh), (len)) ++#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) ++#define PKTLIST_DUMP(osh, buf) ++#define PKTDBG_TRACE(osh, pkt, bit) ++#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++#define PKTGET_STATIC(osh, len, send) osl_pktget_static((osh), (len)) ++#define PKTFREE_STATIC(osh, skb, send) osl_pktfree_static((osh), (skb), (send)) ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++#define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data) ++#define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len) ++#define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head)) ++#define PKTTAILROOM(osh, skb) ((((struct sk_buff*)(skb))->end)-(((struct sk_buff*)(skb))->tail)) ++#define PKTNEXT(osh, skb) (((struct sk_buff*)(skb))->next) ++#define PKTSETNEXT(osh, skb, x) (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)) ++#define PKTSETLEN(osh, skb, len) __skb_trim((struct sk_buff*)(skb), (len)) ++#define PKTPUSH(osh, skb, bytes) skb_push((struct sk_buff*)(skb), (bytes)) ++#define PKTPULL(osh, skb, bytes) skb_pull((struct sk_buff*)(skb), (bytes)) ++#define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb)) ++#define PKTALLOCED(osh) ((osl_pubinfo_t *)(osh))->pktalloced ++#define PKTSETPOOL(osh, skb, x, y) do {} while (0) ++#define PKTPOOL(osh, skb) FALSE ++#define PKTSHRINK(osh, m) (m) ++ ++#ifdef CTFPOOL ++#define CTFPOOL_REFILL_THRESH 3 ++typedef struct ctfpool { ++ void *head; ++ spinlock_t lock; ++ uint max_obj; ++ uint curr_obj; ++ uint obj_size; ++ uint refills; ++ uint fast_allocs; ++ uint fast_frees; ++ uint slow_allocs; ++} ctfpool_t; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) ++#define FASTBUF (1 << 16) ++#define CTFBUF (1 << 17) ++#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= FASTBUF) ++#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~CTFBUF)) ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & FASTBUF) ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & CTFBUF) ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->mac_len) ++#else ++#define FASTBUF (1 << 0) ++#define CTFBUF (1 << 1) ++#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) |= FASTBUF) ++#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->__unused) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->__unused) &= (~CTFBUF)) ++#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) & FASTBUF) ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->__unused) & CTFBUF) ++#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->__unused) ++#endif /* 2.6.22 */ ++ ++#define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->sk) ++#define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->sk)->head) ++ ++extern void *osl_ctfpool_add(osl_t *osh); ++extern void osl_ctfpool_replenish(osl_t *osh, uint thresh); ++extern int32 osl_ctfpool_init(osl_t *osh, uint numobj, uint size); ++extern void osl_ctfpool_cleanup(osl_t *osh); ++extern void osl_ctfpool_stats(osl_t *osh, void *b); ++#endif /* CTFPOOL */ ++ ++ ++#ifdef HNDCTF ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) ++#define SKIPCT (1 << 18) ++#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len |= SKIPCT) ++#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len &= (~SKIPCT)) ++#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len & SKIPCT) ++#else /* 2.6.22 */ ++#define SKIPCT (1 << 2) ++#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused |= SKIPCT) ++#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused &= (~SKIPCT)) ++#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused & SKIPCT) ++#endif /* 2.6.22 */ ++#else /* HNDCTF */ ++#define PKTSETSKIPCT(osh, skb) ++#define PKTCLRSKIPCT(osh, skb) ++#define PKTSKIPCT(osh, skb) ++#endif /* HNDCTF */ ++ ++extern void osl_pktfree(osl_t *osh, void *skb, bool send); ++extern void *osl_pktget_static(osl_t *osh, uint len); ++extern void osl_pktfree_static(osl_t *osh, void *skb, bool send); ++ ++extern void *osl_pkt_frmnative(osl_t *osh, void *skb); ++extern void *osl_pktget(osl_t *osh, uint len); ++extern void *osl_pktdup(osl_t *osh, void *skb); ++extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt); ++#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_t *)osh), (struct sk_buff*)(skb)) ++#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osl_t *)(osh), (pkt)) ++ ++#define PKTLINK(skb) (((struct sk_buff*)(skb))->prev) ++#define PKTSETLINK(skb, x) (((struct sk_buff*)(skb))->prev = (struct sk_buff*)(x)) ++#define PKTPRIO(skb) (((struct sk_buff*)(skb))->priority) ++#define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x)) ++#define PKTSUMNEEDED(skb) (((struct sk_buff*)(skb))->ip_summed == CHECKSUM_HW) ++#define PKTSETSUMGOOD(skb, x) (((struct sk_buff*)(skb))->ip_summed = \ ++ ((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE)) ++/* PKTSETSUMNEEDED and PKTSUMGOOD are not possible because skb->ip_summed is overloaded */ ++#define PKTSHARED(skb) (((struct sk_buff*)(skb))->cloned) ++ ++#define DMA_MAP(osh, va, size, direction, p, dmah) \ ++ osl_dma_map((osh), (va), (size), (direction)) ++ ++#ifdef PKTC ++/* Use 8 bytes of skb tstamp field to store below info */ ++struct chain_node { ++ struct sk_buff *link; ++ unsigned int flags:3, pkts:9, bytes:20; ++}; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++#define CHAIN_NODE(skb) ((struct chain_node*)&(((struct sk_buff*)skb)->tstamp)) ++#else ++#define CHAIN_NODE(skb) ((struct chain_node*)&(((struct sk_buff*)skb)->stamp)) ++#endif ++ ++#define PKTCCNT(skb) (CHAIN_NODE(skb)->pkts) ++#define PKTCLEN(skb) (CHAIN_NODE(skb)->bytes) ++#define PKTCFLAGS(skb) (CHAIN_NODE(skb)->flags) ++#define PKTCSETCNT(skb, c) (CHAIN_NODE(skb)->pkts = (c) & ((1 << 9) - 1)) ++#define PKTCSETLEN(skb, l) (CHAIN_NODE(skb)->bytes = (l) & ((1 << 20) - 1)) ++#define PKTCSETFLAG(skb, fb) (CHAIN_NODE(skb)->flags |= (fb)) ++#define PKTCCLRFLAG(skb, fb) (CHAIN_NODE(skb)->flags &= ~(fb)) ++#define PKTCLINK(skb) (CHAIN_NODE(skb)->link) ++#define PKTSETCLINK(skb, x) (CHAIN_NODE(skb)->link = (struct sk_buff*)(x)) ++#define PKTISCHAINED(skb) (PKTCLINK(skb) != NULL) ++#define FOREACH_CHAINED_PKT(skb, nskb) \ ++ for (; (skb) != NULL; (skb) = (nskb)) \ ++ if ((nskb) = PKTCLINK(skb), PKTSETCLINK((skb), NULL), 1) ++#define PKTCFREE(osh, skb, send) \ ++do { \ ++ void *nskb; \ ++ ASSERT((skb) != NULL); \ ++ FOREACH_CHAINED_PKT((skb), nskb) { \ ++ PKTFREE((osh), (skb), (send)); \ ++ } \ ++} while (0) ++#endif /* PKTC */ ++ ++#else /* ! BCMDRIVER */ ++ ++ ++/* ASSERT */ ++ #define ASSERT(exp) do {} while (0) ++ ++/* MALLOC and MFREE */ ++#define MALLOC(o, l) malloc(l) ++#define MFREE(o, p, l) free(p) ++#include ++ ++/* str* and mem* functions */ ++#include ++ ++/* *printf functions */ ++#include ++ ++/* bcopy, bcmp, and bzero */ ++extern void bcopy(const void *src, void *dst, size_t len); ++extern int bcmp(const void *b1, const void *b2, size_t len); ++extern void bzero(void *b, size_t len); ++#endif /* ! BCMDRIVER */ ++ ++#endif /* _linux_osl_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/linuxver.h b/drivers/net/wireless/ap6210/include/linuxver.h +new file mode 100755 +index 0000000..e01b8f0 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/linuxver.h +@@ -0,0 +1,652 @@ ++/* ++ * Linux-specific abstractions to gain some independence from linux kernel versions. ++ * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: linuxver.h 366812 2012-11-05 13:49:32Z $ ++ */ ++ ++#ifndef _linuxver_h_ ++#define _linuxver_h_ ++ ++#include ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++#include ++#else ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) ++#include ++#else ++#include ++#endif ++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */ ++#include ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)) ++/* __NO_VERSION__ must be defined for all linkables except one in 2.2 */ ++#ifdef __UNDEF_NO_VERSION__ ++#undef __NO_VERSION__ ++#else ++#define __NO_VERSION__ ++#endif ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) ++#define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i") ++#define module_param_string(_name_, _string_, _size_, _perm_) \ ++ MODULE_PARM(_string_, "c" __MODULE_STRING(_size_)) ++#endif ++ ++/* linux/malloc.h is deprecated, use linux/slab.h instead. */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 9)) ++#include ++#else ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++#include ++#else ++#include ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) ++#undef IP_TOS ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) */ ++#include ++ ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41)) ++#include ++#else ++#include ++#ifndef work_struct ++#define work_struct tq_struct ++#endif ++#ifndef INIT_WORK ++#define INIT_WORK(_work, _func, _data) INIT_TQUEUE((_work), (_func), (_data)) ++#endif ++#ifndef schedule_work ++#define schedule_work(_work) schedule_task((_work)) ++#endif ++#ifndef flush_scheduled_work ++#define flush_scheduled_work() flush_scheduled_tasks() ++#endif ++#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41) */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++#define DAEMONIZE(a) daemonize(a); \ ++ allow_signal(SIGKILL); \ ++ allow_signal(SIGTERM); ++#else /* Linux 2.4 (w/o preemption patch) */ ++#define RAISE_RX_SOFTIRQ() \ ++ cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ) ++#define DAEMONIZE(a) daemonize(); \ ++ do { if (a) \ ++ strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a)))); \ ++ } while (0); ++#endif /* LINUX_VERSION_CODE */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) ++#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func) ++#else ++#define MY_INIT_WORK(_work, _func) INIT_WORK(_work, _func, _work) ++#if !(LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18) && defined(RHEL_MAJOR) && \ ++ (RHEL_MAJOR == 5)) ++/* Exclude RHEL 5 */ ++typedef void (*work_func_t)(void *work); ++#endif ++#endif /* >= 2.6.20 */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++/* Some distributions have their own 2.6.x compatibility layers */ ++#ifndef IRQ_NONE ++typedef void irqreturn_t; ++#define IRQ_NONE ++#define IRQ_HANDLED ++#define IRQ_RETVAL(x) ++#endif ++#else ++typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs); ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) ++#define IRQF_SHARED SA_SHIRQ ++#endif /* < 2.6.18 */ ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17) ++#ifdef CONFIG_NET_RADIO ++#define CONFIG_WIRELESS_EXT ++#endif ++#endif /* < 2.6.17 */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) ++#define MOD_INC_USE_COUNT ++#define MOD_DEC_USE_COUNT ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) ++#include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) ++#include ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) ++#include ++#else ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++#include ++#endif ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) */ ++ ++ ++ ++#ifndef __exit ++#define __exit ++#endif ++#ifndef __devexit ++#define __devexit ++#endif ++#ifndef __devinit ++#define __devinit __init ++#endif ++#ifndef __devinitdata ++#define __devinitdata ++#endif ++#ifndef __devexit_p ++#define __devexit_p(x) x ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)) ++ ++#define pci_get_drvdata(dev) (dev)->sysdata ++#define pci_set_drvdata(dev, value) (dev)->sysdata = (value) ++ ++/* ++ * New-style (2.4.x) PCI/hot-pluggable PCI/CardBus registration ++ */ ++ ++struct pci_device_id { ++ unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */ ++ unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ ++ unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */ ++ unsigned long driver_data; /* Data private to the driver */ ++}; ++ ++struct pci_driver { ++ struct list_head node; ++ char *name; ++ const struct pci_device_id *id_table; /* NULL if wants all devices */ ++ int (*probe)(struct pci_dev *dev, ++ const struct pci_device_id *id); /* New device inserted */ ++ void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug ++ * capable driver) ++ */ ++ void (*suspend)(struct pci_dev *dev); /* Device suspended */ ++ void (*resume)(struct pci_dev *dev); /* Device woken up */ ++}; ++ ++#define MODULE_DEVICE_TABLE(type, name) ++#define PCI_ANY_ID (~0) ++ ++/* compatpci.c */ ++#define pci_module_init pci_register_driver ++extern int pci_register_driver(struct pci_driver *drv); ++extern void pci_unregister_driver(struct pci_driver *drv); ++ ++#endif /* PCI registration */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)) ++#define pci_module_init pci_register_driver ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)) ++#ifdef MODULE ++#define module_init(x) int init_module(void) { return x(); } ++#define module_exit(x) void cleanup_module(void) { x(); } ++#else ++#define module_init(x) __initcall(x); ++#define module_exit(x) __exitcall(x); ++#endif ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) ++#define WL_USE_NETDEV_OPS ++#else ++#undef WL_USE_NETDEV_OPS ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) && defined(CONFIG_RFKILL) ++#define WL_CONFIG_RFKILL ++#else ++#undef WL_CONFIG_RFKILL ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 48)) ++#define list_for_each(pos, head) \ ++ for (pos = (head)->next; pos != (head); pos = pos->next) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 13)) ++#define pci_resource_start(dev, bar) ((dev)->base_address[(bar)]) ++#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 44)) ++#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 23)) ++#define pci_enable_device(dev) do { } while (0) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 14)) ++#define net_device device ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 42)) ++ ++/* ++ * DMA mapping ++ * ++ * See linux/Documentation/DMA-mapping.txt ++ */ ++ ++#ifndef PCI_DMA_TODEVICE ++#define PCI_DMA_TODEVICE 1 ++#define PCI_DMA_FROMDEVICE 2 ++#endif ++ ++typedef u32 dma_addr_t; ++ ++/* Pure 2^n version of get_order */ ++static inline int get_order(unsigned long size) ++{ ++ int order; ++ ++ size = (size-1) >> (PAGE_SHIFT-1); ++ order = -1; ++ do { ++ size >>= 1; ++ order++; ++ } while (size); ++ return order; ++} ++ ++static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, ++ dma_addr_t *dma_handle) ++{ ++ void *ret; ++ int gfp = GFP_ATOMIC | GFP_DMA; ++ ++ ret = (void *)__get_free_pages(gfp, get_order(size)); ++ ++ if (ret != NULL) { ++ memset(ret, 0, size); ++ *dma_handle = virt_to_bus(ret); ++ } ++ return ret; ++} ++static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size, ++ void *vaddr, dma_addr_t dma_handle) ++{ ++ free_pages((unsigned long)vaddr, get_order(size)); ++} ++#define pci_map_single(cookie, address, size, dir) virt_to_bus(address) ++#define pci_unmap_single(cookie, address, size, dir) ++ ++#endif /* DMA mapping */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 43)) ++ ++#define dev_kfree_skb_any(a) dev_kfree_skb(a) ++#define netif_down(dev) do { (dev)->start = 0; } while (0) ++ ++/* pcmcia-cs provides its own netdevice compatibility layer */ ++#ifndef _COMPAT_NETDEVICE_H ++ ++/* ++ * SoftNet ++ * ++ * For pre-softnet kernels we need to tell the upper layer not to ++ * re-enter start_xmit() while we are in there. However softnet ++ * guarantees not to enter while we are in there so there is no need ++ * to do the netif_stop_queue() dance unless the transmit queue really ++ * gets stuck. This should also improve performance according to tests ++ * done by Aman Singla. ++ */ ++ ++#define dev_kfree_skb_irq(a) dev_kfree_skb(a) ++#define netif_wake_queue(dev) \ ++ do { clear_bit(0, &(dev)->tbusy); mark_bh(NET_BH); } while (0) ++#define netif_stop_queue(dev) set_bit(0, &(dev)->tbusy) ++ ++static inline void netif_start_queue(struct net_device *dev) ++{ ++ dev->tbusy = 0; ++ dev->interrupt = 0; ++ dev->start = 1; ++} ++ ++#define netif_queue_stopped(dev) (dev)->tbusy ++#define netif_running(dev) (dev)->start ++ ++#endif /* _COMPAT_NETDEVICE_H */ ++ ++#define netif_device_attach(dev) netif_start_queue(dev) ++#define netif_device_detach(dev) netif_stop_queue(dev) ++ ++/* 2.4.x renamed bottom halves to tasklets */ ++#define tasklet_struct tq_struct ++static inline void tasklet_schedule(struct tasklet_struct *tasklet) ++{ ++ queue_task(tasklet, &tq_immediate); ++ mark_bh(IMMEDIATE_BH); ++} ++ ++static inline void tasklet_init(struct tasklet_struct *tasklet, ++ void (*func)(unsigned long), ++ unsigned long data) ++{ ++ tasklet->next = NULL; ++ tasklet->sync = 0; ++ tasklet->routine = (void (*)(void *))func; ++ tasklet->data = (void *)data; ++} ++#define tasklet_kill(tasklet) { do {} while (0); } ++ ++/* 2.4.x introduced del_timer_sync() */ ++#define del_timer_sync(timer) del_timer(timer) ++ ++#else ++ ++#define netif_down(dev) ++ ++#endif /* SoftNet */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3)) ++ ++/* ++ * Emit code to initialise a tq_struct's routine and data pointers ++ */ ++#define PREPARE_TQUEUE(_tq, _routine, _data) \ ++ do { \ ++ (_tq)->routine = _routine; \ ++ (_tq)->data = _data; \ ++ } while (0) ++ ++/* ++ * Emit code to initialise all of a tq_struct ++ */ ++#define INIT_TQUEUE(_tq, _routine, _data) \ ++ do { \ ++ INIT_LIST_HEAD(&(_tq)->list); \ ++ (_tq)->sync = 0; \ ++ PREPARE_TQUEUE((_tq), (_routine), (_data)); \ ++ } while (0) ++ ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3) */ ++ ++/* Power management related macro & routines */ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 9) ++#define PCI_SAVE_STATE(a, b) pci_save_state(a) ++#define PCI_RESTORE_STATE(a, b) pci_restore_state(a) ++#else ++#define PCI_SAVE_STATE(a, b) pci_save_state(a, b) ++#define PCI_RESTORE_STATE(a, b) pci_restore_state(a, b) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6)) ++static inline int ++pci_save_state(struct pci_dev *dev, u32 *buffer) ++{ ++ int i; ++ if (buffer) { ++ for (i = 0; i < 16; i++) ++ pci_read_config_dword(dev, i * 4, &buffer[i]); ++ } ++ return 0; ++} ++ ++static inline int ++pci_restore_state(struct pci_dev *dev, u32 *buffer) ++{ ++ int i; ++ ++ if (buffer) { ++ for (i = 0; i < 16; i++) ++ pci_write_config_dword(dev, i * 4, buffer[i]); ++ } ++ /* ++ * otherwise, write the context information we know from bootup. ++ * This works around a problem where warm-booting from Windows ++ * combined with a D3(hot)->D0 transition causes PCI config ++ * header data to be forgotten. ++ */ ++ else { ++ for (i = 0; i < 6; i ++) ++ pci_write_config_dword(dev, ++ PCI_BASE_ADDRESS_0 + (i * 4), ++ pci_resource_start(dev, i)); ++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); ++ } ++ return 0; ++} ++#endif /* PCI power management */ ++ ++/* Old cp0 access macros deprecated in 2.4.19 */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 19)) ++#define read_c0_count() read_32bit_cp0_register(CP0_COUNT) ++#endif ++ ++/* Module refcount handled internally in 2.6.x */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) ++#ifndef SET_MODULE_OWNER ++#define SET_MODULE_OWNER(dev) do {} while (0) ++#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT ++#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT ++#else ++#define OLD_MOD_INC_USE_COUNT do {} while (0) ++#define OLD_MOD_DEC_USE_COUNT do {} while (0) ++#endif ++#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */ ++#ifndef SET_MODULE_OWNER ++#define SET_MODULE_OWNER(dev) do {} while (0) ++#endif ++#ifndef MOD_INC_USE_COUNT ++#define MOD_INC_USE_COUNT do {} while (0) ++#endif ++#ifndef MOD_DEC_USE_COUNT ++#define MOD_DEC_USE_COUNT do {} while (0) ++#endif ++#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT ++#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */ ++ ++#ifndef SET_NETDEV_DEV ++#define SET_NETDEV_DEV(net, pdev) do {} while (0) ++#endif ++ ++#ifndef HAVE_FREE_NETDEV ++#define free_netdev(dev) kfree(dev) ++#endif ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++/* struct packet_type redefined in 2.6.x */ ++#define af_packet_priv data ++#endif ++ ++/* suspend args */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) ++#define DRV_SUSPEND_STATE_TYPE pm_message_t ++#else ++#define DRV_SUSPEND_STATE_TYPE uint32 ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) ++#define CHECKSUM_HW CHECKSUM_PARTIAL ++#endif ++ ++typedef struct { ++ void *parent; /* some external entity that the thread supposed to work for */ ++ struct task_struct *p_task; ++ long thr_pid; ++ int prio; /* priority */ ++ struct semaphore sema; ++ int terminated; ++ struct completion completed; ++} tsk_ctl_t; ++ ++ ++/* requires tsk_ctl_t tsk argument, the caller's priv data is passed in owner ptr */ ++/* note this macro assumes there may be only one context waiting on thread's completion */ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++#define SMP_RD_BARRIER_DEPENDS(x) smp_read_barrier_depends(x) ++#else ++#define SMP_RD_BARRIER_DEPENDS(x) smp_rmb(x) ++#endif ++ ++ ++#define PROC_START(thread_func, owner, tsk_ctl, flags) \ ++{ \ ++ sema_init(&((tsk_ctl)->sema), 0); \ ++ init_completion(&((tsk_ctl)->completed)); \ ++ (tsk_ctl)->parent = owner; \ ++ (tsk_ctl)->terminated = FALSE; \ ++ (tsk_ctl)->thr_pid = kernel_thread(thread_func, tsk_ctl, flags); \ ++ if ((tsk_ctl)->thr_pid > 0) \ ++ wait_for_completion(&((tsk_ctl)->completed)); \ ++} ++ ++#ifdef USE_KTHREAD_API ++#define PROC_START2(thread_func, owner, tsk_ctl, flags, name) \ ++{ \ ++ sema_init(&((tsk_ctl)->sema), 0); \ ++ init_completion(&((tsk_ctl)->completed)); \ ++ (tsk_ctl)->parent = owner; \ ++ (tsk_ctl)->terminated = FALSE; \ ++ (tsk_ctl)->p_task = kthread_run(thread_func, tsk_ctl, (char*)name); \ ++ (tsk_ctl)->thr_pid = (tsk_ctl)->p_task->pid; \ ++} ++#endif ++ ++#define PROC_STOP(tsk_ctl) \ ++{ \ ++ (tsk_ctl)->terminated = TRUE; \ ++ smp_wmb(); \ ++ up(&((tsk_ctl)->sema)); \ ++ wait_for_completion(&((tsk_ctl)->completed)); \ ++ (tsk_ctl)->thr_pid = -1; \ ++} ++ ++/* ----------------------- */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) ++#define KILL_PROC(nr, sig) \ ++{ \ ++struct task_struct *tsk; \ ++struct pid *pid; \ ++pid = find_get_pid((pid_t)nr); \ ++tsk = pid_task(pid, PIDTYPE_PID); \ ++if (tsk) send_sig(sig, tsk, 1); \ ++} ++#else ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \ ++ KERNEL_VERSION(2, 6, 30)) ++#define KILL_PROC(pid, sig) \ ++{ \ ++ struct task_struct *tsk; \ ++ tsk = find_task_by_vpid(pid); \ ++ if (tsk) send_sig(sig, tsk, 1); \ ++} ++#else ++#define KILL_PROC(pid, sig) \ ++{ \ ++ kill_proc(pid, sig, 1); \ ++} ++#endif ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++#include ++#include ++#else ++#include ++ ++#define __wait_event_interruptible_timeout(wq, condition, ret) \ ++do { \ ++ wait_queue_t __wait; \ ++ init_waitqueue_entry(&__wait, current); \ ++ \ ++ add_wait_queue(&wq, &__wait); \ ++ for (;;) { \ ++ set_current_state(TASK_INTERRUPTIBLE); \ ++ if (condition) \ ++ break; \ ++ if (!signal_pending(current)) { \ ++ ret = schedule_timeout(ret); \ ++ if (!ret) \ ++ break; \ ++ continue; \ ++ } \ ++ ret = -ERESTARTSYS; \ ++ break; \ ++ } \ ++ current->state = TASK_RUNNING; \ ++ remove_wait_queue(&wq, &__wait); \ ++} while (0) ++ ++#define wait_event_interruptible_timeout(wq, condition, timeout) \ ++({ \ ++ long __ret = timeout; \ ++ if (!(condition)) \ ++ __wait_event_interruptible_timeout(wq, condition, __ret); \ ++ __ret; \ ++}) ++ ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */ ++ ++/* ++For < 2.6.24, wl creates its own netdev but doesn't ++align the priv area like the genuine alloc_netdev(). ++Since netdev_priv() always gives us the aligned address, it will ++not match our unaligned address for < 2.6.24 ++*/ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) ++#define DEV_PRIV(dev) (dev->priv) ++#else ++#define DEV_PRIV(dev) netdev_priv(dev) ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) ++#define WL_ISR(i, d, p) wl_isr((i), (d)) ++#else ++#define WL_ISR(i, d, p) wl_isr((i), (d), (p)) ++#endif /* < 2.6.20 */ ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) ++#define netdev_priv(dev) dev->priv ++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */ ++ ++#endif /* _linuxver_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/miniopt.h b/drivers/net/wireless/ap6210/include/miniopt.h +new file mode 100755 +index 0000000..c1eca68 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/miniopt.h +@@ -0,0 +1,77 @@ ++/* ++ * Command line options parser. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * $Id: miniopt.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++ ++#ifndef MINI_OPT_H ++#define MINI_OPT_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* ---- Include Files ---------------------------------------------------- */ ++/* ---- Constants and Types ---------------------------------------------- */ ++ ++#define MINIOPT_MAXKEY 128 /* Max options */ ++typedef struct miniopt { ++ ++ /* These are persistent after miniopt_init() */ ++ const char* name; /* name for prompt in error strings */ ++ const char* flags; /* option chars that take no args */ ++ bool longflags; /* long options may be flags */ ++ bool opt_end; /* at end of options (passed a "--") */ ++ ++ /* These are per-call to miniopt() */ ++ ++ int consumed; /* number of argv entries cosumed in ++ * the most recent call to miniopt() ++ */ ++ bool positional; ++ bool good_int; /* 'val' member is the result of a sucessful ++ * strtol conversion of the option value ++ */ ++ char opt; ++ char key[MINIOPT_MAXKEY]; ++ char* valstr; /* positional param, or value for the option, ++ * or null if the option had ++ * no accompanying value ++ */ ++ uint uval; /* strtol translation of valstr */ ++ int val; /* strtol translation of valstr */ ++} miniopt_t; ++ ++void miniopt_init(miniopt_t *t, const char* name, const char* flags, bool longflags); ++int miniopt(miniopt_t *t, char **argv); ++ ++ ++/* ---- Variable Externs ------------------------------------------------- */ ++/* ---- Function Prototypes ---------------------------------------------- */ ++ ++ ++#ifdef __cplusplus ++ } ++#endif ++ ++#endif /* MINI_OPT_H */ +diff --git a/drivers/net/wireless/ap6210/include/msgtrace.h b/drivers/net/wireless/ap6210/include/msgtrace.h +new file mode 100755 +index 0000000..7c5fd81 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/msgtrace.h +@@ -0,0 +1,74 @@ ++/* ++ * Trace messages sent over HBUS ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: msgtrace.h 281527 2011-09-02 17:12:53Z $ ++ */ ++ ++#ifndef _MSGTRACE_H ++#define _MSGTRACE_H ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#define MSGTRACE_VERSION 1 ++ ++/* Message trace header */ ++typedef BWL_PRE_PACKED_STRUCT struct msgtrace_hdr { ++ uint8 version; ++ uint8 spare; ++ uint16 len; /* Len of the trace */ ++ uint32 seqnum; /* Sequence number of message. Useful if the messsage has been lost ++ * because of DMA error or a bus reset (ex: SDIO Func2) ++ */ ++ uint32 discarded_bytes; /* Number of discarded bytes because of trace overflow */ ++ uint32 discarded_printf; /* Number of discarded printf because of trace overflow */ ++} BWL_POST_PACKED_STRUCT msgtrace_hdr_t; ++ ++#define MSGTRACE_HDRLEN sizeof(msgtrace_hdr_t) ++ ++/* The hbus driver generates traces when sending a trace message. This causes endless traces. ++ * This flag must be set to TRUE in any hbus traces. The flag is reset in the function msgtrace_put. ++ * This prevents endless traces but generates hasardous lost of traces only in bus device code. ++ * It is recommendat to set this flag in macro SD_TRACE but not in SD_ERROR for avoiding missing ++ * hbus error traces. hbus error trace should not generates endless traces. ++ */ ++extern bool msgtrace_hbus_trace; ++ ++typedef void (*msgtrace_func_send_t)(void *hdl1, void *hdl2, uint8 *hdr, ++ uint16 hdrlen, uint8 *buf, uint16 buflen); ++extern void msgtrace_start(void); ++extern void msgtrace_stop(void); ++extern void msgtrace_sent(void); ++extern void msgtrace_put(char *buf, int count); ++extern void msgtrace_init(void *hdl1, void *hdl2, msgtrace_func_send_t func_send); ++extern bool msgtrace_event_enabled(void); ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _MSGTRACE_H */ +diff --git a/drivers/net/wireless/ap6210/include/osl.h b/drivers/net/wireless/ap6210/include/osl.h +new file mode 100755 +index 0000000..0a11d23 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/osl.h +@@ -0,0 +1,90 @@ ++/* ++ * OS Abstraction Layer ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: osl.h 320905 2012-03-13 15:33:25Z $ ++ */ ++ ++#ifndef _osl_h_ ++#define _osl_h_ ++ ++/* osl handle type forward declaration */ ++typedef struct osl_info osl_t; ++typedef struct osl_dmainfo osldma_t; ++ ++#define OSL_PKTTAG_SZ 32 /* Size of PktTag */ ++ ++/* Drivers use PKTFREESETCB to register a callback function when a packet is freed by OSL */ ++typedef void (*pktfree_cb_fn_t)(void *ctx, void *pkt, unsigned int status); ++ ++/* Drivers use REGOPSSET() to register register read/write funcitons */ ++typedef unsigned int (*osl_rreg_fn_t)(void *ctx, volatile void *reg, unsigned int size); ++typedef void (*osl_wreg_fn_t)(void *ctx, volatile void *reg, unsigned int val, unsigned int size); ++ ++ ++#include ++ ++#ifndef PKTDBG_TRACE ++#define PKTDBG_TRACE(osh, pkt, bit) ++#endif ++ ++#define PKTCTFMAP(osh, p) ++ ++/* -------------------------------------------------------------------------- ++** Register manipulation macros. ++*/ ++ ++#define SET_REG(osh, r, mask, val) W_REG((osh), (r), ((R_REG((osh), r) & ~(mask)) | (val))) ++ ++#ifndef AND_REG ++#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) ++#endif /* !AND_REG */ ++ ++#ifndef OR_REG ++#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) ++#endif /* !OR_REG */ ++ ++#if !defined(OSL_SYSUPTIME) ++#define OSL_SYSUPTIME() (0) ++#define OSL_SYSUPTIME_SUPPORT FALSE ++#else ++#define OSL_SYSUPTIME_SUPPORT TRUE ++#endif /* OSL_SYSUPTIME */ ++ ++#if !defined(PKTC) ++#define PKTCCNT(skb) (0) ++#define PKTCLEN(skb) (0) ++#define PKTCFLAGS(skb) (0) ++#define PKTCSETCNT(skb, c) ++#define PKTCSETLEN(skb, l) ++#define PKTCSETFLAG(skb, fb) ++#define PKTCCLRFLAG(skb, fb) ++#define PKTCLINK(skb) PKTLINK(skb) ++#define PKTSETCLINK(skb, x) PKTSETLINK((skb), (x)) ++#define PKTISCHAINED(skb) FALSE ++#define FOREACH_CHAINED_PKT(skb, nskb) \ ++ for ((nskb) = NULL; (skb) != NULL; (skb) = (nskb)) ++#define PKTCFREE PKTFREE ++#endif ++ ++ ++#endif /* _osl_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/packed_section_end.h b/drivers/net/wireless/ap6210/include/packed_section_end.h +new file mode 100755 +index 0000000..0779b04 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/packed_section_end.h +@@ -0,0 +1,59 @@ ++/* ++ * Declare directives for structure packing. No padding will be provided ++ * between the members of packed structures, and therefore, there is no ++ * guarantee that structure members will be aligned. ++ * ++ * Declaring packed structures is compiler specific. In order to handle all ++ * cases, packed structures should be delared as: ++ * ++ * #include ++ * ++ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t { ++ * some_struct_members; ++ * } BWL_POST_PACKED_STRUCT foobar_t; ++ * ++ * #include ++ * ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * $Id: packed_section_end.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++ ++/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h ++ * and undefined in packed_section_end.h. If it is NOT defined at this ++ * point, then there is a missing include of packed_section_start.h. ++ */ ++#ifdef BWL_PACKED_SECTION ++ #undef BWL_PACKED_SECTION ++#else ++ #error "BWL_PACKED_SECTION is NOT defined!" ++#endif ++ ++ ++ ++ ++/* Compiler-specific directives for structure packing are declared in ++ * packed_section_start.h. This marks the end of the structure packing section, ++ * so, undef them here. ++ */ ++#undef BWL_PRE_PACKED_STRUCT ++#undef BWL_POST_PACKED_STRUCT +diff --git a/drivers/net/wireless/ap6210/include/packed_section_start.h b/drivers/net/wireless/ap6210/include/packed_section_start.h +new file mode 100755 +index 0000000..ee93a4b +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/packed_section_start.h +@@ -0,0 +1,63 @@ ++/* ++ * Declare directives for structure packing. No padding will be provided ++ * between the members of packed structures, and therefore, there is no ++ * guarantee that structure members will be aligned. ++ * ++ * Declaring packed structures is compiler specific. In order to handle all ++ * cases, packed structures should be delared as: ++ * ++ * #include ++ * ++ * typedef BWL_PRE_PACKED_STRUCT struct foobar_t { ++ * some_struct_members; ++ * } BWL_POST_PACKED_STRUCT foobar_t; ++ * ++ * #include ++ * ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * $Id: packed_section_start.h 286783 2011-09-29 06:18:57Z $ ++ */ ++ ++ ++/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h ++ * and undefined in packed_section_end.h. If it is already defined at this ++ * point, then there is a missing include of packed_section_end.h. ++ */ ++#ifdef BWL_PACKED_SECTION ++ #error "BWL_PACKED_SECTION is already defined!" ++#else ++ #define BWL_PACKED_SECTION ++#endif ++ ++ ++ ++ ++/* Declare compiler-specific directives for structure packing. */ ++#if defined(__GNUC__) || defined(__lint) ++ #define BWL_PRE_PACKED_STRUCT ++ #define BWL_POST_PACKED_STRUCT __attribute__ ((packed)) ++#elif defined(__CC_ARM) ++ #define BWL_PRE_PACKED_STRUCT __packed ++ #define BWL_POST_PACKED_STRUCT ++#else ++ #error "Unknown compiler!" ++#endif +diff --git a/drivers/net/wireless/ap6210/include/pcicfg.h b/drivers/net/wireless/ap6210/include/pcicfg.h +new file mode 100755 +index 0000000..0278bb2 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/pcicfg.h +@@ -0,0 +1,100 @@ ++/* ++ * pcicfg.h: PCI configuration constants and structures. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: pcicfg.h 309193 2012-01-19 00:03:57Z $ ++ */ ++ ++#ifndef _h_pcicfg_ ++#define _h_pcicfg_ ++ ++/* A structure for the config registers is nice, but in most ++ * systems the config space is not memory mapped, so we need ++ * field offsetts. :-( ++ */ ++#define PCI_CFG_VID 0 ++#define PCI_CFG_DID 2 ++#define PCI_CFG_CMD 4 ++#define PCI_CFG_STAT 6 ++#define PCI_CFG_REV 8 ++#define PCI_CFG_PROGIF 9 ++#define PCI_CFG_SUBCL 0xa ++#define PCI_CFG_BASECL 0xb ++#define PCI_CFG_CLSZ 0xc ++#define PCI_CFG_LATTIM 0xd ++#define PCI_CFG_HDR 0xe ++#define PCI_CFG_BIST 0xf ++#define PCI_CFG_BAR0 0x10 ++#define PCI_CFG_BAR1 0x14 ++#define PCI_CFG_BAR2 0x18 ++#define PCI_CFG_BAR3 0x1c ++#define PCI_CFG_BAR4 0x20 ++#define PCI_CFG_BAR5 0x24 ++#define PCI_CFG_CIS 0x28 ++#define PCI_CFG_SVID 0x2c ++#define PCI_CFG_SSID 0x2e ++#define PCI_CFG_ROMBAR 0x30 ++#define PCI_CFG_CAPPTR 0x34 ++#define PCI_CFG_INT 0x3c ++#define PCI_CFG_PIN 0x3d ++#define PCI_CFG_MINGNT 0x3e ++#define PCI_CFG_MAXLAT 0x3f ++#define PCI_BAR0_WIN 0x80 /* backplane addres space accessed by BAR0 */ ++#define PCI_BAR1_WIN 0x84 /* backplane addres space accessed by BAR1 */ ++#define PCI_SPROM_CONTROL 0x88 /* sprom property control */ ++#define PCI_BAR1_CONTROL 0x8c /* BAR1 region burst control */ ++#define PCI_INT_STATUS 0x90 /* PCI and other cores interrupts */ ++#define PCI_INT_MASK 0x94 /* mask of PCI and other cores interrupts */ ++#define PCI_TO_SB_MB 0x98 /* signal backplane interrupts */ ++#define PCI_BACKPLANE_ADDR 0xa0 /* address an arbitrary location on the system backplane */ ++#define PCI_BACKPLANE_DATA 0xa4 /* data at the location specified by above address */ ++#define PCI_CLK_CTL_ST 0xa8 /* pci config space clock control/status (>=rev14) */ ++#define PCI_BAR0_WIN2 0xac /* backplane addres space accessed by second 4KB of BAR0 */ ++#define PCI_GPIO_IN 0xb0 /* pci config space gpio input (>=rev3) */ ++#define PCI_GPIO_OUT 0xb4 /* pci config space gpio output (>=rev3) */ ++#define PCI_GPIO_OUTEN 0xb8 /* pci config space gpio output enable (>=rev3) */ ++ ++#define PCI_BAR0_SHADOW_OFFSET (2 * 1024) /* bar0 + 2K accesses sprom shadow (in pci core) */ ++#define PCI_BAR0_SPROM_OFFSET (4 * 1024) /* bar0 + 4K accesses external sprom */ ++#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) /* bar0 + 6K accesses pci core registers */ ++#define PCI_BAR0_PCISBR_OFFSET (4 * 1024) /* pci core SB registers are at the end of the ++ * 8KB window, so their address is the "regular" ++ * address plus 4K ++ */ ++/* ++ * PCIE GEN2 changed some of the above locations for ++ * Bar0WrapperBase, SecondaryBAR0Window and SecondaryBAR0WrapperBase ++ * BAR0 maps 32K of register space ++*/ ++#define PCIE2_BAR0_WIN2 0x70 /* backplane addres space accessed by second 4KB of BAR0 */ ++#define PCIE2_BAR0_CORE2_WIN 0x74 /* backplane addres space accessed by second 4KB of BAR0 */ ++#define PCIE2_BAR0_CORE2_WIN2 0x78 /* backplane addres space accessed by second 4KB of BAR0 */ ++ ++#define PCI_BAR0_WINSZ (16 * 1024) /* bar0 window size Match with corerev 13 */ ++/* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */ ++#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) /* bar0 + 8K accesses pci/pcie core registers */ ++#define PCI_16KB0_CCREGS_OFFSET (12 * 1024) /* bar0 + 12K accesses chipc core registers */ ++#define PCI_16KBB0_WINSZ (16 * 1024) /* bar0 window size */ ++ ++ ++#define PCI_CONFIG_SPACE_SIZE 256 ++#endif /* _h_pcicfg_ */ +diff --git a/drivers/net/wireless/ap6210/include/proto/802.11.h b/drivers/net/wireless/ap6210/include/proto/802.11.h +new file mode 100755 +index 0000000..15cd56c +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/proto/802.11.h +@@ -0,0 +1,2355 @@ ++/* ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * Fundamental types and constants relating to 802.11 ++ * ++ * $Id: 802.11.h 346820 2012-07-24 13:53:12Z $ ++ */ ++ ++#ifndef _802_11_H_ ++#define _802_11_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++#ifndef _NET_ETHERNET_H_ ++#include ++#endif ++ ++#include ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++#define DOT11_TU_TO_US 1024 /* 802.11 Time Unit is 1024 microseconds */ ++ ++/* Generic 802.11 frame constants */ ++#define DOT11_A3_HDR_LEN 24 /* d11 header length with A3 */ ++#define DOT11_A4_HDR_LEN 30 /* d11 header length with A4 */ ++#define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN /* MAC header length */ ++#define DOT11_FCS_LEN 4 /* d11 FCS length */ ++#define DOT11_ICV_LEN 4 /* d11 ICV length */ ++#define DOT11_ICV_AES_LEN 8 /* d11 ICV/AES length */ ++#define DOT11_QOS_LEN 2 /* d11 QoS length */ ++#define DOT11_HTC_LEN 4 /* d11 HT Control field length */ ++ ++#define DOT11_KEY_INDEX_SHIFT 6 /* d11 key index shift */ ++#define DOT11_IV_LEN 4 /* d11 IV length */ ++#define DOT11_IV_TKIP_LEN 8 /* d11 IV TKIP length */ ++#define DOT11_IV_AES_OCB_LEN 4 /* d11 IV/AES/OCB length */ ++#define DOT11_IV_AES_CCM_LEN 8 /* d11 IV/AES/CCM length */ ++#define DOT11_IV_MAX_LEN 8 /* maximum iv len for any encryption */ ++ ++/* Includes MIC */ ++#define DOT11_MAX_MPDU_BODY_LEN 2304 /* max MPDU body length */ ++/* A4 header + QoS + CCMP + PDU + ICV + FCS = 2352 */ ++#define DOT11_MAX_MPDU_LEN (DOT11_A4_HDR_LEN + \ ++ DOT11_QOS_LEN + \ ++ DOT11_IV_AES_CCM_LEN + \ ++ DOT11_MAX_MPDU_BODY_LEN + \ ++ DOT11_ICV_LEN + \ ++ DOT11_FCS_LEN) /* d11 max MPDU length */ ++ ++#define DOT11_MAX_SSID_LEN 32 /* d11 max ssid length */ ++ ++/* dot11RTSThreshold */ ++#define DOT11_DEFAULT_RTS_LEN 2347 /* d11 default RTS length */ ++#define DOT11_MAX_RTS_LEN 2347 /* d11 max RTS length */ ++ ++/* dot11FragmentationThreshold */ ++#define DOT11_MIN_FRAG_LEN 256 /* d11 min fragmentation length */ ++#define DOT11_MAX_FRAG_LEN 2346 /* Max frag is also limited by aMPDUMaxLength ++ * of the attached PHY ++ */ ++#define DOT11_DEFAULT_FRAG_LEN 2346 /* d11 default fragmentation length */ ++ ++/* dot11BeaconPeriod */ ++#define DOT11_MIN_BEACON_PERIOD 1 /* d11 min beacon period */ ++#define DOT11_MAX_BEACON_PERIOD 0xFFFF /* d11 max beacon period */ ++ ++/* dot11DTIMPeriod */ ++#define DOT11_MIN_DTIM_PERIOD 1 /* d11 min DTIM period */ ++#define DOT11_MAX_DTIM_PERIOD 0xFF /* d11 max DTIM period */ ++ ++/* 802.2 LLC/SNAP header used by 802.11 per 802.1H */ ++#define DOT11_LLC_SNAP_HDR_LEN 8 /* d11 LLC/SNAP header length */ ++#define DOT11_OUI_LEN 3 /* d11 OUI length */ ++BWL_PRE_PACKED_STRUCT struct dot11_llc_snap_header { ++ uint8 dsap; /* always 0xAA */ ++ uint8 ssap; /* always 0xAA */ ++ uint8 ctl; /* always 0x03 */ ++ uint8 oui[DOT11_OUI_LEN]; /* RFC1042: 0x00 0x00 0x00 ++ * Bridge-Tunnel: 0x00 0x00 0xF8 ++ */ ++ uint16 type; /* ethertype */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* RFC1042 header used by 802.11 per 802.1H */ ++#define RFC1042_HDR_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN) /* RCF1042 header length */ ++ ++/* Generic 802.11 MAC header */ ++/* ++ * N.B.: This struct reflects the full 4 address 802.11 MAC header. ++ * The fields are defined such that the shorter 1, 2, and 3 ++ * address headers just use the first k fields. ++ */ ++BWL_PRE_PACKED_STRUCT struct dot11_header { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr a1; /* address 1 */ ++ struct ether_addr a2; /* address 2 */ ++ struct ether_addr a3; /* address 3 */ ++ uint16 seq; /* sequence control */ ++ struct ether_addr a4; /* address 4 */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* Control frames */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rts_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++ struct ether_addr ta; /* transmitter address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_RTS_LEN 16 /* d11 RTS frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_cts_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_CTS_LEN 10 /* d11 CTS frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_ack_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ACK_LEN 10 /* d11 ACK frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_ps_poll_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* AID */ ++ struct ether_addr bssid; /* receiver address, STA in AP */ ++ struct ether_addr ta; /* transmitter address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_PS_POLL_LEN 16 /* d11 PS poll frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_cf_end_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++ struct ether_addr bssid; /* transmitter address, STA in AP */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_CS_END_LEN 16 /* d11 CF-END frame length */ ++ ++/* RWL wifi protocol: The Vendor Specific Action frame is defined for vendor-specific signaling ++* category+OUI+vendor specific content ( this can be variable) ++*/ ++BWL_PRE_PACKED_STRUCT struct dot11_action_wifi_vendor_specific { ++ uint8 category; ++ uint8 OUI[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 data[1040]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_action_wifi_vendor_specific dot11_action_wifi_vendor_specific_t; ++ ++/* generic vender specific action frame with variable length */ ++BWL_PRE_PACKED_STRUCT struct dot11_action_vs_frmhdr { ++ uint8 category; ++ uint8 OUI[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_action_vs_frmhdr dot11_action_vs_frmhdr_t; ++#define DOT11_ACTION_VS_HDR_LEN 6 ++ ++#define BCM_ACTION_OUI_BYTE0 0x00 ++#define BCM_ACTION_OUI_BYTE1 0x90 ++#define BCM_ACTION_OUI_BYTE2 0x4c ++ ++/* BA/BAR Control parameters */ ++#define DOT11_BA_CTL_POLICY_NORMAL 0x0000 /* normal ack */ ++#define DOT11_BA_CTL_POLICY_NOACK 0x0001 /* no ack */ ++#define DOT11_BA_CTL_POLICY_MASK 0x0001 /* ack policy mask */ ++ ++#define DOT11_BA_CTL_MTID 0x0002 /* multi tid BA */ ++#define DOT11_BA_CTL_COMPRESSED 0x0004 /* compressed bitmap */ ++ ++#define DOT11_BA_CTL_NUMMSDU_MASK 0x0FC0 /* num msdu in bitmap mask */ ++#define DOT11_BA_CTL_NUMMSDU_SHIFT 6 /* num msdu in bitmap shift */ ++ ++#define DOT11_BA_CTL_TID_MASK 0xF000 /* tid mask */ ++#define DOT11_BA_CTL_TID_SHIFT 12 /* tid shift */ ++ ++/* control frame header (BA/BAR) */ ++BWL_PRE_PACKED_STRUCT struct dot11_ctl_header { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++ struct ether_addr ta; /* transmitter address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_CTL_HDR_LEN 16 /* control frame hdr len */ ++ ++/* BAR frame payload */ ++BWL_PRE_PACKED_STRUCT struct dot11_bar { ++ uint16 bar_control; /* BAR Control */ ++ uint16 seqnum; /* Starting Sequence control */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_BAR_LEN 4 /* BAR frame payload length */ ++ ++#define DOT11_BA_BITMAP_LEN 128 /* bitmap length */ ++#define DOT11_BA_CMP_BITMAP_LEN 8 /* compressed bitmap length */ ++/* BA frame payload */ ++BWL_PRE_PACKED_STRUCT struct dot11_ba { ++ uint16 ba_control; /* BA Control */ ++ uint16 seqnum; /* Starting Sequence control */ ++ uint8 bitmap[DOT11_BA_BITMAP_LEN]; /* Block Ack Bitmap */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_BA_LEN 4 /* BA frame payload len (wo bitmap) */ ++ ++/* Management frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_management_header { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr da; /* receiver address */ ++ struct ether_addr sa; /* transmitter address */ ++ struct ether_addr bssid; /* BSS ID */ ++ uint16 seq; /* sequence control */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_MGMT_HDR_LEN 24 /* d11 management header length */ ++ ++/* Management frame payloads */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_bcn_prb { ++ uint32 timestamp[2]; ++ uint16 beacon_interval; ++ uint16 capability; ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_BCN_PRB_LEN 12 /* 802.11 beacon/probe frame fixed length */ ++#define DOT11_BCN_PRB_FIXED_LEN 12 /* 802.11 beacon/probe frame fixed length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_auth { ++ uint16 alg; /* algorithm */ ++ uint16 seq; /* sequence control */ ++ uint16 status; /* status code */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_AUTH_FIXED_LEN 6 /* length of auth frame without challenge IE */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_assoc_req { ++ uint16 capability; /* capability information */ ++ uint16 listen; /* listen interval */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ASSOC_REQ_FIXED_LEN 4 /* length of assoc frame without info elts */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_reassoc_req { ++ uint16 capability; /* capability information */ ++ uint16 listen; /* listen interval */ ++ struct ether_addr ap; /* Current AP address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_REASSOC_REQ_FIXED_LEN 10 /* length of assoc frame without info elts */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_assoc_resp { ++ uint16 capability; /* capability information */ ++ uint16 status; /* status code */ ++ uint16 aid; /* association ID */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ASSOC_RESP_FIXED_LEN 6 /* length of assoc resp frame without info elts */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_measure { ++ uint8 category; ++ uint8 action; ++ uint8 token; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ACTION_MEASURE_LEN 3 /* d11 action measurement header length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_ht_ch_width { ++ uint8 category; ++ uint8 action; ++ uint8 ch_width; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_ht_mimops { ++ uint8 category; ++ uint8 action; ++ uint8 control; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_sa_query { ++ uint8 category; ++ uint8 action; ++ uint16 id; ++} BWL_POST_PACKED_STRUCT; ++ ++#define SM_PWRSAVE_ENABLE 1 ++#define SM_PWRSAVE_MODE 2 ++ ++/* ************* 802.11h related definitions. ************* */ ++BWL_PRE_PACKED_STRUCT struct dot11_power_cnst { ++ uint8 id; ++ uint8 len; ++ uint8 power; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_power_cnst dot11_power_cnst_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_power_cap { ++ uint8 min; ++ uint8 max; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_power_cap dot11_power_cap_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_tpc_rep { ++ uint8 id; ++ uint8 len; ++ uint8 tx_pwr; ++ uint8 margin; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_tpc_rep dot11_tpc_rep_t; ++#define DOT11_MNG_IE_TPC_REPORT_LEN 2 /* length of IE data, not including 2 byte header */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_supp_channels { ++ uint8 id; ++ uint8 len; ++ uint8 first_channel; ++ uint8 num_channels; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_supp_channels dot11_supp_channels_t; ++ ++/* Extension Channel Offset IE: 802.11n-D1.0 spec. added sideband ++ * offset for 40MHz operation. The possible 3 values are: ++ * 1 = above control channel ++ * 3 = below control channel ++ * 0 = no extension channel ++ */ ++BWL_PRE_PACKED_STRUCT struct dot11_extch { ++ uint8 id; /* IE ID, 62, DOT11_MNG_EXT_CHANNEL_OFFSET */ ++ uint8 len; /* IE length */ ++ uint8 extch; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_extch dot11_extch_ie_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_brcm_extch { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* type inidicates what follows */ ++ uint8 extch; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_brcm_extch dot11_brcm_extch_ie_t; ++ ++#define BRCM_EXTCH_IE_LEN 5 ++#define BRCM_EXTCH_IE_TYPE 53 /* 802.11n ID not yet assigned */ ++#define DOT11_EXTCH_IE_LEN 1 ++#define DOT11_EXT_CH_MASK 0x03 /* extension channel mask */ ++#define DOT11_EXT_CH_UPPER 0x01 /* ext. ch. on upper sb */ ++#define DOT11_EXT_CH_LOWER 0x03 /* ext. ch. on lower sb */ ++#define DOT11_EXT_CH_NONE 0x00 /* no extension ch. */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_frmhdr { ++ uint8 category; ++ uint8 action; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ACTION_FRMHDR_LEN 2 ++ ++/* CSA IE data structure */ ++BWL_PRE_PACKED_STRUCT struct dot11_channel_switch { ++ uint8 id; /* id DOT11_MNG_CHANNEL_SWITCH_ID */ ++ uint8 len; /* length of IE */ ++ uint8 mode; /* mode 0 or 1 */ ++ uint8 channel; /* channel switch to */ ++ uint8 count; /* number of beacons before switching */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_channel_switch dot11_chan_switch_ie_t; ++ ++#define DOT11_SWITCH_IE_LEN 3 /* length of IE data, not including 2 byte header */ ++/* CSA mode - 802.11h-2003 $7.3.2.20 */ ++#define DOT11_CSA_MODE_ADVISORY 0 /* no DOT11_CSA_MODE_NO_TX restriction imposed */ ++#define DOT11_CSA_MODE_NO_TX 1 /* no transmission upon receiving CSA frame. */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_switch_channel { ++ uint8 category; ++ uint8 action; ++ dot11_chan_switch_ie_t chan_switch_ie; /* for switch IE */ ++ dot11_brcm_extch_ie_t extch_ie; /* extension channel offset */ ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_csa_body { ++ uint8 mode; /* mode 0 or 1 */ ++ uint8 reg; /* regulatory class */ ++ uint8 channel; /* channel switch to */ ++ uint8 count; /* number of beacons before switching */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* 11n Extended Channel Switch IE data structure */ ++BWL_PRE_PACKED_STRUCT struct dot11_ext_csa { ++ uint8 id; /* id DOT11_MNG_EXT_CHANNEL_SWITCH_ID */ ++ uint8 len; /* length of IE */ ++ struct dot11_csa_body b; /* body of the ie */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ext_csa dot11_ext_csa_ie_t; ++#define DOT11_EXT_CSA_IE_LEN 4 /* length of extended channel switch IE body */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_ext_csa { ++ uint8 category; ++ uint8 action; ++ dot11_ext_csa_ie_t chan_switch_ie; /* for switch IE */ ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11y_action_ext_csa { ++ uint8 category; ++ uint8 action; ++ struct dot11_csa_body b; /* body of the ie */ ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_obss_coex { ++ uint8 id; ++ uint8 len; ++ uint8 info; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_obss_coex dot11_obss_coex_t; ++#define DOT11_OBSS_COEXINFO_LEN 1 /* length of OBSS Coexistence INFO IE */ ++ ++#define DOT11_OBSS_COEX_INFO_REQ 0x01 ++#define DOT11_OBSS_COEX_40MHZ_INTOLERANT 0x02 ++#define DOT11_OBSS_COEX_20MHZ_WIDTH_REQ 0x04 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_obss_chanlist { ++ uint8 id; ++ uint8 len; ++ uint8 regclass; ++ uint8 chanlist[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_obss_chanlist dot11_obss_chanlist_t; ++#define DOT11_OBSS_CHANLIST_FIXED_LEN 1 /* fixed length of regclass */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_extcap_ie { ++ uint8 id; ++ uint8 len; ++ uint8 cap[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_extcap_ie dot11_extcap_ie_t; ++ ++#define DOT11_EXTCAP_LEN_MAX 7 ++#define DOT11_EXTCAP_LEN_COEX 1 ++#define DOT11_EXTCAP_LEN_BT 3 ++#define DOT11_EXTCAP_LEN_IW 4 ++#define DOT11_EXTCAP_LEN_SI 6 ++ ++#define DOT11_EXTCAP_LEN_TDLS 5 ++BWL_PRE_PACKED_STRUCT struct dot11_extcap { ++ uint8 extcap[DOT11_EXTCAP_LEN_TDLS]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_extcap dot11_extcap_t; ++ ++/* TDLS Capabilities */ ++#define TDLS_CAP_TDLS 37 /* TDLS support */ ++#define TDLS_CAP_PU_BUFFER_STA 28 /* TDLS Peer U-APSD buffer STA support */ ++#define TDLS_CAP_PEER_PSM 20 /* TDLS Peer PSM support */ ++#define TDLS_CAP_CH_SW 30 /* TDLS Channel switch */ ++#define TDLS_CAP_PROH 38 /* TDLS prohibited */ ++#define TDLS_CAP_CH_SW_PROH 39 /* TDLS Channel switch prohibited */ ++ ++#define TDLS_CAP_MAX_BIT 39 /* TDLS max bit defined in ext cap */ ++ ++/* 802.11h/802.11k Measurement Request/Report IEs */ ++/* Measurement Type field */ ++#define DOT11_MEASURE_TYPE_BASIC 0 /* d11 measurement basic type */ ++#define DOT11_MEASURE_TYPE_CCA 1 /* d11 measurement CCA type */ ++#define DOT11_MEASURE_TYPE_RPI 2 /* d11 measurement RPI type */ ++#define DOT11_MEASURE_TYPE_CHLOAD 3 /* d11 measurement Channel Load type */ ++#define DOT11_MEASURE_TYPE_NOISE 4 /* d11 measurement Noise Histogram type */ ++#define DOT11_MEASURE_TYPE_BEACON 5 /* d11 measurement Beacon type */ ++#define DOT11_MEASURE_TYPE_FRAME 6 /* d11 measurement Frame type */ ++#define DOT11_MEASURE_TYPE_STATS 7 /* d11 measurement STA Statistics type */ ++#define DOT11_MEASURE_TYPE_LCI 8 /* d11 measurement LCI type */ ++#define DOT11_MEASURE_TYPE_TXSTREAM 9 /* d11 measurement TX Stream type */ ++#define DOT11_MEASURE_TYPE_PAUSE 255 /* d11 measurement pause type */ ++ ++/* Measurement Request Modes */ ++#define DOT11_MEASURE_MODE_PARALLEL (1<<0) /* d11 measurement parallel */ ++#define DOT11_MEASURE_MODE_ENABLE (1<<1) /* d11 measurement enable */ ++#define DOT11_MEASURE_MODE_REQUEST (1<<2) /* d11 measurement request */ ++#define DOT11_MEASURE_MODE_REPORT (1<<3) /* d11 measurement report */ ++#define DOT11_MEASURE_MODE_DUR (1<<4) /* d11 measurement dur mandatory */ ++/* Measurement Report Modes */ ++#define DOT11_MEASURE_MODE_LATE (1<<0) /* d11 measurement late */ ++#define DOT11_MEASURE_MODE_INCAPABLE (1<<1) /* d11 measurement incapable */ ++#define DOT11_MEASURE_MODE_REFUSED (1<<2) /* d11 measurement refuse */ ++/* Basic Measurement Map bits */ ++#define DOT11_MEASURE_BASIC_MAP_BSS ((uint8)(1<<0)) /* d11 measurement basic map BSS */ ++#define DOT11_MEASURE_BASIC_MAP_OFDM ((uint8)(1<<1)) /* d11 measurement map OFDM */ ++#define DOT11_MEASURE_BASIC_MAP_UKNOWN ((uint8)(1<<2)) /* d11 measurement map unknown */ ++#define DOT11_MEASURE_BASIC_MAP_RADAR ((uint8)(1<<3)) /* d11 measurement map radar */ ++#define DOT11_MEASURE_BASIC_MAP_UNMEAS ((uint8)(1<<4)) /* d11 measurement map unmeasuremnt */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_meas_req { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++ uint8 channel; ++ uint8 start_time[8]; ++ uint16 duration; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_meas_req dot11_meas_req_t; ++#define DOT11_MNG_IE_MREQ_LEN 14 /* d11 measurement request IE length */ ++/* length of Measure Request IE data not including variable len */ ++#define DOT11_MNG_IE_MREQ_FIXED_LEN 3 /* d11 measurement request IE fixed length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_meas_rep { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++ BWL_PRE_PACKED_STRUCT union ++ { ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 channel; ++ uint8 start_time[8]; ++ uint16 duration; ++ uint8 map; ++ } BWL_POST_PACKED_STRUCT basic; ++ uint8 data[1]; ++ } BWL_POST_PACKED_STRUCT rep; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_meas_rep dot11_meas_rep_t; ++ ++/* length of Measure Report IE data not including variable len */ ++#define DOT11_MNG_IE_MREP_FIXED_LEN 3 /* d11 measurement response IE fixed length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_meas_rep_basic { ++ uint8 channel; ++ uint8 start_time[8]; ++ uint16 duration; ++ uint8 map; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t; ++#define DOT11_MEASURE_BASIC_REP_LEN 12 /* d11 measurement basic report length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_quiet { ++ uint8 id; ++ uint8 len; ++ uint8 count; /* TBTTs until beacon interval in quiet starts */ ++ uint8 period; /* Beacon intervals between periodic quiet periods ? */ ++ uint16 duration; /* Length of quiet period, in TU's */ ++ uint16 offset; /* TU's offset from TBTT in Count field */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_quiet dot11_quiet_t; ++ ++BWL_PRE_PACKED_STRUCT struct chan_map_tuple { ++ uint8 channel; ++ uint8 map; ++} BWL_POST_PACKED_STRUCT; ++typedef struct chan_map_tuple chan_map_tuple_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_ibss_dfs { ++ uint8 id; ++ uint8 len; ++ uint8 eaddr[ETHER_ADDR_LEN]; ++ uint8 interval; ++ chan_map_tuple_t map[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ibss_dfs dot11_ibss_dfs_t; ++ ++/* WME Elements */ ++#define WME_OUI "\x00\x50\xf2" /* WME OUI */ ++#define WME_OUI_LEN 3 ++#define WME_OUI_TYPE 2 /* WME type */ ++#define WME_TYPE 2 /* WME type, deprecated */ ++#define WME_SUBTYPE_IE 0 /* Information Element */ ++#define WME_SUBTYPE_PARAM_IE 1 /* Parameter Element */ ++#define WME_SUBTYPE_TSPEC 2 /* Traffic Specification */ ++#define WME_VER 1 /* WME version */ ++ ++/* WME Access Category Indices (ACIs) */ ++#define AC_BE 0 /* Best Effort */ ++#define AC_BK 1 /* Background */ ++#define AC_VI 2 /* Video */ ++#define AC_VO 3 /* Voice */ ++#define AC_COUNT 4 /* number of ACs */ ++ ++typedef uint8 ac_bitmap_t; /* AC bitmap of (1 << AC_xx) */ ++ ++#define AC_BITMAP_NONE 0x0 /* No ACs */ ++#define AC_BITMAP_ALL 0xf /* All ACs */ ++#define AC_BITMAP_TST(ab, ac) (((ab) & (1 << (ac))) != 0) ++#define AC_BITMAP_SET(ab, ac) (((ab) |= (1 << (ac)))) ++#define AC_BITMAP_RESET(ab, ac) (((ab) &= ~(1 << (ac)))) ++ ++/* WME Information Element (IE) */ ++BWL_PRE_PACKED_STRUCT struct wme_ie { ++ uint8 oui[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 version; ++ uint8 qosinfo; ++} BWL_POST_PACKED_STRUCT; ++typedef struct wme_ie wme_ie_t; ++#define WME_IE_LEN 7 /* WME IE length */ ++ ++BWL_PRE_PACKED_STRUCT struct edcf_acparam { ++ uint8 ACI; ++ uint8 ECW; ++ uint16 TXOP; /* stored in network order (ls octet first) */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct edcf_acparam edcf_acparam_t; ++ ++/* WME Parameter Element (PE) */ ++BWL_PRE_PACKED_STRUCT struct wme_param_ie { ++ uint8 oui[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 version; ++ uint8 qosinfo; ++ uint8 rsvd; ++ edcf_acparam_t acparam[AC_COUNT]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct wme_param_ie wme_param_ie_t; ++#define WME_PARAM_IE_LEN 24 /* WME Parameter IE length */ ++ ++/* QoS Info field for IE as sent from AP */ ++#define WME_QI_AP_APSD_MASK 0x80 /* U-APSD Supported mask */ ++#define WME_QI_AP_APSD_SHIFT 7 /* U-APSD Supported shift */ ++#define WME_QI_AP_COUNT_MASK 0x0f /* Parameter set count mask */ ++#define WME_QI_AP_COUNT_SHIFT 0 /* Parameter set count shift */ ++ ++/* QoS Info field for IE as sent from STA */ ++#define WME_QI_STA_MAXSPLEN_MASK 0x60 /* Max Service Period Length mask */ ++#define WME_QI_STA_MAXSPLEN_SHIFT 5 /* Max Service Period Length shift */ ++#define WME_QI_STA_APSD_ALL_MASK 0xf /* APSD all AC bits mask */ ++#define WME_QI_STA_APSD_ALL_SHIFT 0 /* APSD all AC bits shift */ ++#define WME_QI_STA_APSD_BE_MASK 0x8 /* APSD AC_BE mask */ ++#define WME_QI_STA_APSD_BE_SHIFT 3 /* APSD AC_BE shift */ ++#define WME_QI_STA_APSD_BK_MASK 0x4 /* APSD AC_BK mask */ ++#define WME_QI_STA_APSD_BK_SHIFT 2 /* APSD AC_BK shift */ ++#define WME_QI_STA_APSD_VI_MASK 0x2 /* APSD AC_VI mask */ ++#define WME_QI_STA_APSD_VI_SHIFT 1 /* APSD AC_VI shift */ ++#define WME_QI_STA_APSD_VO_MASK 0x1 /* APSD AC_VO mask */ ++#define WME_QI_STA_APSD_VO_SHIFT 0 /* APSD AC_VO shift */ ++ ++/* ACI */ ++#define EDCF_AIFSN_MIN 1 /* AIFSN minimum value */ ++#define EDCF_AIFSN_MAX 15 /* AIFSN maximum value */ ++#define EDCF_AIFSN_MASK 0x0f /* AIFSN mask */ ++#define EDCF_ACM_MASK 0x10 /* ACM mask */ ++#define EDCF_ACI_MASK 0x60 /* ACI mask */ ++#define EDCF_ACI_SHIFT 5 /* ACI shift */ ++#define EDCF_AIFSN_SHIFT 12 /* 4 MSB(0xFFF) in ifs_ctl for AC idx */ ++ ++/* ECW */ ++#define EDCF_ECW_MIN 0 /* cwmin/cwmax exponent minimum value */ ++#define EDCF_ECW_MAX 15 /* cwmin/cwmax exponent maximum value */ ++#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1) ++#define EDCF_ECWMIN_MASK 0x0f /* cwmin exponent form mask */ ++#define EDCF_ECWMAX_MASK 0xf0 /* cwmax exponent form mask */ ++#define EDCF_ECWMAX_SHIFT 4 /* cwmax exponent form shift */ ++ ++/* TXOP */ ++#define EDCF_TXOP_MIN 0 /* TXOP minimum value */ ++#define EDCF_TXOP_MAX 65535 /* TXOP maximum value */ ++#define EDCF_TXOP2USEC(txop) ((txop) << 5) ++ ++/* Default BE ACI value for non-WME connection STA */ ++#define NON_EDCF_AC_BE_ACI_STA 0x02 ++ ++/* Default EDCF parameters that AP advertises for STA to use; WMM draft Table 12 */ ++#define EDCF_AC_BE_ACI_STA 0x03 /* STA ACI value for best effort AC */ ++#define EDCF_AC_BE_ECW_STA 0xA4 /* STA ECW value for best effort AC */ ++#define EDCF_AC_BE_TXOP_STA 0x0000 /* STA TXOP value for best effort AC */ ++#define EDCF_AC_BK_ACI_STA 0x27 /* STA ACI value for background AC */ ++#define EDCF_AC_BK_ECW_STA 0xA4 /* STA ECW value for background AC */ ++#define EDCF_AC_BK_TXOP_STA 0x0000 /* STA TXOP value for background AC */ ++#define EDCF_AC_VI_ACI_STA 0x42 /* STA ACI value for video AC */ ++#define EDCF_AC_VI_ECW_STA 0x43 /* STA ECW value for video AC */ ++#define EDCF_AC_VI_TXOP_STA 0x005e /* STA TXOP value for video AC */ ++#define EDCF_AC_VO_ACI_STA 0x62 /* STA ACI value for audio AC */ ++#define EDCF_AC_VO_ECW_STA 0x32 /* STA ECW value for audio AC */ ++#define EDCF_AC_VO_TXOP_STA 0x002f /* STA TXOP value for audio AC */ ++ ++/* Default EDCF parameters that AP uses; WMM draft Table 14 */ ++#define EDCF_AC_BE_ACI_AP 0x03 /* AP ACI value for best effort AC */ ++#define EDCF_AC_BE_ECW_AP 0x64 /* AP ECW value for best effort AC */ ++#define EDCF_AC_BE_TXOP_AP 0x0000 /* AP TXOP value for best effort AC */ ++#define EDCF_AC_BK_ACI_AP 0x27 /* AP ACI value for background AC */ ++#define EDCF_AC_BK_ECW_AP 0xA4 /* AP ECW value for background AC */ ++#define EDCF_AC_BK_TXOP_AP 0x0000 /* AP TXOP value for background AC */ ++#define EDCF_AC_VI_ACI_AP 0x41 /* AP ACI value for video AC */ ++#define EDCF_AC_VI_ECW_AP 0x43 /* AP ECW value for video AC */ ++#define EDCF_AC_VI_TXOP_AP 0x005e /* AP TXOP value for video AC */ ++#define EDCF_AC_VO_ACI_AP 0x61 /* AP ACI value for audio AC */ ++#define EDCF_AC_VO_ECW_AP 0x32 /* AP ECW value for audio AC */ ++#define EDCF_AC_VO_TXOP_AP 0x002f /* AP TXOP value for audio AC */ ++ ++/* EDCA Parameter IE */ ++BWL_PRE_PACKED_STRUCT struct edca_param_ie { ++ uint8 qosinfo; ++ uint8 rsvd; ++ edcf_acparam_t acparam[AC_COUNT]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct edca_param_ie edca_param_ie_t; ++#define EDCA_PARAM_IE_LEN 18 /* EDCA Parameter IE length */ ++ ++/* QoS Capability IE */ ++BWL_PRE_PACKED_STRUCT struct qos_cap_ie { ++ uint8 qosinfo; ++} BWL_POST_PACKED_STRUCT; ++typedef struct qos_cap_ie qos_cap_ie_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_qbss_load_ie { ++ uint8 id; /* 11, DOT11_MNG_QBSS_LOAD_ID */ ++ uint8 length; ++ uint16 station_count; /* total number of STAs associated */ ++ uint8 channel_utilization; /* % of time, normalized to 255, QAP sensed medium busy */ ++ uint16 aac; /* available admission capacity */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t; ++#define BSS_LOAD_IE_SIZE 7 /* BSS load IE size */ ++ ++/* nom_msdu_size */ ++#define FIXED_MSDU_SIZE 0x8000 /* MSDU size is fixed */ ++#define MSDU_SIZE_MASK 0x7fff /* (Nominal or fixed) MSDU size */ ++ ++/* surplus_bandwidth */ ++/* Represented as 3 bits of integer, binary point, 13 bits fraction */ ++#define INTEGER_SHIFT 13 /* integer shift */ ++#define FRACTION_MASK 0x1FFF /* fraction mask */ ++ ++/* Management Notification Frame */ ++BWL_PRE_PACKED_STRUCT struct dot11_management_notification { ++ uint8 category; /* DOT11_ACTION_NOTIFICATION */ ++ uint8 action; ++ uint8 token; ++ uint8 status; ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_MGMT_NOTIFICATION_LEN 4 /* Fixed length */ ++ ++/* Timeout Interval IE */ ++BWL_PRE_PACKED_STRUCT struct ti_ie { ++ uint8 ti_type; ++ uint32 ti_val; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ti_ie ti_ie_t; ++#define TI_TYPE_REASSOC_DEADLINE 1 ++#define TI_TYPE_KEY_LIFETIME 2 ++ ++/* WME Action Codes */ ++#define WME_ADDTS_REQUEST 0 /* WME ADDTS request */ ++#define WME_ADDTS_RESPONSE 1 /* WME ADDTS response */ ++#define WME_DELTS_REQUEST 2 /* WME DELTS request */ ++ ++/* WME Setup Response Status Codes */ ++#define WME_ADMISSION_ACCEPTED 0 /* WME admission accepted */ ++#define WME_INVALID_PARAMETERS 1 /* WME invalide parameters */ ++#define WME_ADMISSION_REFUSED 3 /* WME admission refused */ ++ ++/* Macro to take a pointer to a beacon or probe response ++ * body and return the char* pointer to the SSID info element ++ */ ++#define BCN_PRB_SSID(body) ((char*)(body) + DOT11_BCN_PRB_LEN) ++ ++/* Authentication frame payload constants */ ++#define DOT11_OPEN_SYSTEM 0 /* d11 open authentication */ ++#define DOT11_SHARED_KEY 1 /* d11 shared authentication */ ++#define DOT11_FAST_BSS 2 /* d11 fast bss authentication */ ++#define DOT11_CHALLENGE_LEN 128 /* d11 challenge text length */ ++ ++/* Frame control macros */ ++#define FC_PVER_MASK 0x3 /* PVER mask */ ++#define FC_PVER_SHIFT 0 /* PVER shift */ ++#define FC_TYPE_MASK 0xC /* type mask */ ++#define FC_TYPE_SHIFT 2 /* type shift */ ++#define FC_SUBTYPE_MASK 0xF0 /* subtype mask */ ++#define FC_SUBTYPE_SHIFT 4 /* subtype shift */ ++#define FC_TODS 0x100 /* to DS */ ++#define FC_TODS_SHIFT 8 /* to DS shift */ ++#define FC_FROMDS 0x200 /* from DS */ ++#define FC_FROMDS_SHIFT 9 /* from DS shift */ ++#define FC_MOREFRAG 0x400 /* more frag. */ ++#define FC_MOREFRAG_SHIFT 10 /* more frag. shift */ ++#define FC_RETRY 0x800 /* retry */ ++#define FC_RETRY_SHIFT 11 /* retry shift */ ++#define FC_PM 0x1000 /* PM */ ++#define FC_PM_SHIFT 12 /* PM shift */ ++#define FC_MOREDATA 0x2000 /* more data */ ++#define FC_MOREDATA_SHIFT 13 /* more data shift */ ++#define FC_WEP 0x4000 /* WEP */ ++#define FC_WEP_SHIFT 14 /* WEP shift */ ++#define FC_ORDER 0x8000 /* order */ ++#define FC_ORDER_SHIFT 15 /* order shift */ ++ ++/* sequence control macros */ ++#define SEQNUM_SHIFT 4 /* seq. number shift */ ++#define SEQNUM_MAX 0x1000 /* max seqnum + 1 */ ++#define FRAGNUM_MASK 0xF /* frag. number mask */ ++ ++/* Frame Control type/subtype defs */ ++ ++/* FC Types */ ++#define FC_TYPE_MNG 0 /* management type */ ++#define FC_TYPE_CTL 1 /* control type */ ++#define FC_TYPE_DATA 2 /* data type */ ++ ++/* Management Subtypes */ ++#define FC_SUBTYPE_ASSOC_REQ 0 /* assoc. request */ ++#define FC_SUBTYPE_ASSOC_RESP 1 /* assoc. response */ ++#define FC_SUBTYPE_REASSOC_REQ 2 /* reassoc. request */ ++#define FC_SUBTYPE_REASSOC_RESP 3 /* reassoc. response */ ++#define FC_SUBTYPE_PROBE_REQ 4 /* probe request */ ++#define FC_SUBTYPE_PROBE_RESP 5 /* probe response */ ++#define FC_SUBTYPE_BEACON 8 /* beacon */ ++#define FC_SUBTYPE_ATIM 9 /* ATIM */ ++#define FC_SUBTYPE_DISASSOC 10 /* disassoc. */ ++#define FC_SUBTYPE_AUTH 11 /* authentication */ ++#define FC_SUBTYPE_DEAUTH 12 /* de-authentication */ ++#define FC_SUBTYPE_ACTION 13 /* action */ ++#define FC_SUBTYPE_ACTION_NOACK 14 /* action no-ack */ ++ ++/* Control Subtypes */ ++#define FC_SUBTYPE_CTL_WRAPPER 7 /* Control Wrapper */ ++#define FC_SUBTYPE_BLOCKACK_REQ 8 /* Block Ack Req */ ++#define FC_SUBTYPE_BLOCKACK 9 /* Block Ack */ ++#define FC_SUBTYPE_PS_POLL 10 /* PS poll */ ++#define FC_SUBTYPE_RTS 11 /* RTS */ ++#define FC_SUBTYPE_CTS 12 /* CTS */ ++#define FC_SUBTYPE_ACK 13 /* ACK */ ++#define FC_SUBTYPE_CF_END 14 /* CF-END */ ++#define FC_SUBTYPE_CF_END_ACK 15 /* CF-END ACK */ ++ ++/* Data Subtypes */ ++#define FC_SUBTYPE_DATA 0 /* Data */ ++#define FC_SUBTYPE_DATA_CF_ACK 1 /* Data + CF-ACK */ ++#define FC_SUBTYPE_DATA_CF_POLL 2 /* Data + CF-Poll */ ++#define FC_SUBTYPE_DATA_CF_ACK_POLL 3 /* Data + CF-Ack + CF-Poll */ ++#define FC_SUBTYPE_NULL 4 /* Null */ ++#define FC_SUBTYPE_CF_ACK 5 /* CF-Ack */ ++#define FC_SUBTYPE_CF_POLL 6 /* CF-Poll */ ++#define FC_SUBTYPE_CF_ACK_POLL 7 /* CF-Ack + CF-Poll */ ++#define FC_SUBTYPE_QOS_DATA 8 /* QoS Data */ ++#define FC_SUBTYPE_QOS_DATA_CF_ACK 9 /* QoS Data + CF-Ack */ ++#define FC_SUBTYPE_QOS_DATA_CF_POLL 10 /* QoS Data + CF-Poll */ ++#define FC_SUBTYPE_QOS_DATA_CF_ACK_POLL 11 /* QoS Data + CF-Ack + CF-Poll */ ++#define FC_SUBTYPE_QOS_NULL 12 /* QoS Null */ ++#define FC_SUBTYPE_QOS_CF_POLL 14 /* QoS CF-Poll */ ++#define FC_SUBTYPE_QOS_CF_ACK_POLL 15 /* QoS CF-Ack + CF-Poll */ ++ ++/* Data Subtype Groups */ ++#define FC_SUBTYPE_ANY_QOS(s) (((s) & 8) != 0) ++#define FC_SUBTYPE_ANY_NULL(s) (((s) & 4) != 0) ++#define FC_SUBTYPE_ANY_CF_POLL(s) (((s) & 2) != 0) ++#define FC_SUBTYPE_ANY_CF_ACK(s) (((s) & 1) != 0) ++ ++/* Type/Subtype Combos */ ++#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK) /* FC kind mask */ ++ ++#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT)) /* FC kind */ ++ ++#define FC_SUBTYPE(fc) (((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT) /* Subtype from FC */ ++#define FC_TYPE(fc) (((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT) /* Type from FC */ ++ ++#define FC_ASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ) /* assoc. request */ ++#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP) /* assoc. response */ ++#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ) /* reassoc. request */ ++#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP) /* reassoc. response */ ++#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ) /* probe request */ ++#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP) /* probe response */ ++#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON) /* beacon */ ++#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC) /* disassoc */ ++#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH) /* authentication */ ++#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH) /* deauthentication */ ++#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION) /* action */ ++#define FC_ACTION_NOACK FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK) /* action no-ack */ ++ ++#define FC_CTL_WRAPPER FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTL_WRAPPER) /* Control Wrapper */ ++#define FC_BLOCKACK_REQ FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ) /* Block Ack Req */ ++#define FC_BLOCKACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK) /* Block Ack */ ++#define FC_PS_POLL FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL) /* PS poll */ ++#define FC_RTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS) /* RTS */ ++#define FC_CTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS) /* CTS */ ++#define FC_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK) /* ACK */ ++#define FC_CF_END FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END) /* CF-END */ ++#define FC_CF_END_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK) /* CF-END ACK */ ++ ++#define FC_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA) /* data */ ++#define FC_NULL_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL) /* null data */ ++#define FC_DATA_CF_ACK FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK) /* data CF ACK */ ++#define FC_QOS_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA) /* QoS data */ ++#define FC_QOS_NULL FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL) /* QoS null */ ++ ++/* QoS Control Field */ ++ ++/* 802.1D Priority */ ++#define QOS_PRIO_SHIFT 0 /* QoS priority shift */ ++#define QOS_PRIO_MASK 0x0007 /* QoS priority mask */ ++#define QOS_PRIO(qos) (((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT) /* QoS priority */ ++ ++/* Traffic Identifier */ ++#define QOS_TID_SHIFT 0 /* QoS TID shift */ ++#define QOS_TID_MASK 0x000f /* QoS TID mask */ ++#define QOS_TID(qos) (((qos) & QOS_TID_MASK) >> QOS_TID_SHIFT) /* QoS TID */ ++ ++/* End of Service Period (U-APSD) */ ++#define QOS_EOSP_SHIFT 4 /* QoS End of Service Period shift */ ++#define QOS_EOSP_MASK 0x0010 /* QoS End of Service Period mask */ ++#define QOS_EOSP(qos) (((qos) & QOS_EOSP_MASK) >> QOS_EOSP_SHIFT) /* Qos EOSP */ ++ ++/* Ack Policy */ ++#define QOS_ACK_NORMAL_ACK 0 /* Normal Ack */ ++#define QOS_ACK_NO_ACK 1 /* No Ack (eg mcast) */ ++#define QOS_ACK_NO_EXP_ACK 2 /* No Explicit Ack */ ++#define QOS_ACK_BLOCK_ACK 3 /* Block Ack */ ++#define QOS_ACK_SHIFT 5 /* QoS ACK shift */ ++#define QOS_ACK_MASK 0x0060 /* QoS ACK mask */ ++#define QOS_ACK(qos) (((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT) /* QoS ACK */ ++ ++/* A-MSDU flag */ ++#define QOS_AMSDU_SHIFT 7 /* AMSDU shift */ ++#define QOS_AMSDU_MASK 0x0080 /* AMSDU mask */ ++ ++/* Management Frames */ ++ ++/* Management Frame Constants */ ++ ++/* Fixed fields */ ++#define DOT11_MNG_AUTH_ALGO_LEN 2 /* d11 management auth. algo. length */ ++#define DOT11_MNG_AUTH_SEQ_LEN 2 /* d11 management auth. seq. length */ ++#define DOT11_MNG_BEACON_INT_LEN 2 /* d11 management beacon interval length */ ++#define DOT11_MNG_CAP_LEN 2 /* d11 management cap. length */ ++#define DOT11_MNG_AP_ADDR_LEN 6 /* d11 management AP address length */ ++#define DOT11_MNG_LISTEN_INT_LEN 2 /* d11 management listen interval length */ ++#define DOT11_MNG_REASON_LEN 2 /* d11 management reason length */ ++#define DOT11_MNG_AID_LEN 2 /* d11 management AID length */ ++#define DOT11_MNG_STATUS_LEN 2 /* d11 management status length */ ++#define DOT11_MNG_TIMESTAMP_LEN 8 /* d11 management timestamp length */ ++ ++/* DUR/ID field in assoc resp is 0xc000 | AID */ ++#define DOT11_AID_MASK 0x3fff /* d11 AID mask */ ++ ++/* Reason Codes */ ++#define DOT11_RC_RESERVED 0 /* d11 RC reserved */ ++#define DOT11_RC_UNSPECIFIED 1 /* Unspecified reason */ ++#define DOT11_RC_AUTH_INVAL 2 /* Previous authentication no longer valid */ ++#define DOT11_RC_DEAUTH_LEAVING 3 /* Deauthenticated because sending station ++ * is leaving (or has left) IBSS or ESS ++ */ ++#define DOT11_RC_INACTIVITY 4 /* Disassociated due to inactivity */ ++#define DOT11_RC_BUSY 5 /* Disassociated because AP is unable to handle ++ * all currently associated stations ++ */ ++#define DOT11_RC_INVAL_CLASS_2 6 /* Class 2 frame received from ++ * nonauthenticated station ++ */ ++#define DOT11_RC_INVAL_CLASS_3 7 /* Class 3 frame received from ++ * nonassociated station ++ */ ++#define DOT11_RC_DISASSOC_LEAVING 8 /* Disassociated because sending station is ++ * leaving (or has left) BSS ++ */ ++#define DOT11_RC_NOT_AUTH 9 /* Station requesting (re)association is not ++ * authenticated with responding station ++ */ ++#define DOT11_RC_BAD_PC 10 /* Unacceptable power capability element */ ++#define DOT11_RC_BAD_CHANNELS 11 /* Unacceptable supported channels element */ ++/* 12 is unused */ ++ ++/* 32-39 are QSTA specific reasons added in 11e */ ++#define DOT11_RC_UNSPECIFIED_QOS 32 /* unspecified QoS-related reason */ ++#define DOT11_RC_INSUFFCIENT_BW 33 /* QAP lacks sufficient bandwidth */ ++#define DOT11_RC_EXCESSIVE_FRAMES 34 /* excessive number of frames need ack */ ++#define DOT11_RC_TX_OUTSIDE_TXOP 35 /* transmitting outside the limits of txop */ ++#define DOT11_RC_LEAVING_QBSS 36 /* QSTA is leaving the QBSS (or restting) */ ++#define DOT11_RC_BAD_MECHANISM 37 /* does not want to use the mechanism */ ++#define DOT11_RC_SETUP_NEEDED 38 /* mechanism needs a setup */ ++#define DOT11_RC_TIMEOUT 39 /* timeout */ ++ ++#define DOT11_RC_MAX 23 /* Reason codes > 23 are reserved */ ++ ++#define DOT11_RC_TDLS_PEER_UNREACH 25 ++#define DOT11_RC_TDLS_DOWN_UNSPECIFIED 26 ++ ++/* Status Codes */ ++#define DOT11_SC_SUCCESS 0 /* Successful */ ++#define DOT11_SC_FAILURE 1 /* Unspecified failure */ ++#define DOT11_SC_TDLS_WAKEUP_SCH_ALT 2 /* TDLS wakeup schedule rejected but alternative */ ++ /* schedule provided */ ++#define DOT11_SC_TDLS_WAKEUP_SCH_REJ 3 /* TDLS wakeup schedule rejected */ ++#define DOT11_SC_TDLS_SEC_DISABLED 5 /* TDLS Security disabled */ ++#define DOT11_SC_LIFETIME_REJ 6 /* Unacceptable lifetime */ ++#define DOT11_SC_NOT_SAME_BSS 7 /* Not in same BSS */ ++#define DOT11_SC_CAP_MISMATCH 10 /* Cannot support all requested ++ * capabilities in the Capability ++ * Information field ++ */ ++#define DOT11_SC_REASSOC_FAIL 11 /* Reassociation denied due to inability ++ * to confirm that association exists ++ */ ++#define DOT11_SC_ASSOC_FAIL 12 /* Association denied due to reason ++ * outside the scope of this standard ++ */ ++#define DOT11_SC_AUTH_MISMATCH 13 /* Responding station does not support ++ * the specified authentication ++ * algorithm ++ */ ++#define DOT11_SC_AUTH_SEQ 14 /* Received an Authentication frame ++ * with authentication transaction ++ * sequence number out of expected ++ * sequence ++ */ ++#define DOT11_SC_AUTH_CHALLENGE_FAIL 15 /* Authentication rejected because of ++ * challenge failure ++ */ ++#define DOT11_SC_AUTH_TIMEOUT 16 /* Authentication rejected due to timeout ++ * waiting for next frame in sequence ++ */ ++#define DOT11_SC_ASSOC_BUSY_FAIL 17 /* Association denied because AP is ++ * unable to handle additional ++ * associated stations ++ */ ++#define DOT11_SC_ASSOC_RATE_MISMATCH 18 /* Association denied due to requesting ++ * station not supporting all of the ++ * data rates in the BSSBasicRateSet ++ * parameter ++ */ ++#define DOT11_SC_ASSOC_SHORT_REQUIRED 19 /* Association denied due to requesting ++ * station not supporting the Short ++ * Preamble option ++ */ ++#define DOT11_SC_ASSOC_PBCC_REQUIRED 20 /* Association denied due to requesting ++ * station not supporting the PBCC ++ * Modulation option ++ */ ++#define DOT11_SC_ASSOC_AGILITY_REQUIRED 21 /* Association denied due to requesting ++ * station not supporting the Channel ++ * Agility option ++ */ ++#define DOT11_SC_ASSOC_SPECTRUM_REQUIRED 22 /* Association denied because Spectrum ++ * Management capability is required. ++ */ ++#define DOT11_SC_ASSOC_BAD_POWER_CAP 23 /* Association denied because the info ++ * in the Power Cap element is ++ * unacceptable. ++ */ ++#define DOT11_SC_ASSOC_BAD_SUP_CHANNELS 24 /* Association denied because the info ++ * in the Supported Channel element is ++ * unacceptable ++ */ ++#define DOT11_SC_ASSOC_SHORTSLOT_REQUIRED 25 /* Association denied due to requesting ++ * station not supporting the Short Slot ++ * Time option ++ */ ++#define DOT11_SC_ASSOC_ERPBCC_REQUIRED 26 /* Association denied due to requesting ++ * station not supporting the ER-PBCC ++ * Modulation option ++ */ ++#define DOT11_SC_ASSOC_DSSOFDM_REQUIRED 27 /* Association denied due to requesting ++ * station not supporting the DSS-OFDM ++ * option ++ */ ++#define DOT11_SC_ASSOC_R0KH_UNREACHABLE 28 /* Association denied due to AP ++ * being unable to reach the R0 Key Holder ++ */ ++#define DOT11_SC_ASSOC_TRY_LATER 30 /* Association denied temporarily, try again later ++ */ ++#define DOT11_SC_ASSOC_MFP_VIOLATION 31 /* Association denied due to Robust Management ++ * frame policy violation ++ */ ++ ++#define DOT11_SC_DECLINED 37 /* request declined */ ++#define DOT11_SC_INVALID_PARAMS 38 /* One or more params have invalid values */ ++#define DOT11_SC_INVALID_PAIRWISE_CIPHER 42 /* invalid pairwise cipher */ ++#define DOT11_SC_INVALID_AKMP 43 /* Association denied due to invalid AKMP */ ++#define DOT11_SC_INVALID_RSNIE_CAP 45 /* invalid RSN IE capabilities */ ++#define DOT11_SC_DLS_NOT_ALLOWED 48 /* DLS is not allowed in the BSS by policy */ ++#define DOT11_SC_INVALID_PMKID 53 /* Association denied due to invalid PMKID */ ++#define DOT11_SC_INVALID_MDID 54 /* Association denied due to invalid MDID */ ++#define DOT11_SC_INVALID_FTIE 55 /* Association denied due to invalid FTIE */ ++ ++#define DOT11_SC_UNEXP_MSG 70 /* Unexpected message */ ++#define DOT11_SC_INVALID_SNONCE 71 /* Invalid SNonce */ ++#define DOT11_SC_INVALID_RSNIE 72 /* Invalid contents of RSNIE */ ++ ++/* Info Elts, length of INFORMATION portion of Info Elts */ ++#define DOT11_MNG_DS_PARAM_LEN 1 /* d11 management DS parameter length */ ++#define DOT11_MNG_IBSS_PARAM_LEN 2 /* d11 management IBSS parameter length */ ++ ++/* TIM Info element has 3 bytes fixed info in INFORMATION field, ++ * followed by 1 to 251 bytes of Partial Virtual Bitmap ++ */ ++#define DOT11_MNG_TIM_FIXED_LEN 3 /* d11 management TIM fixed length */ ++#define DOT11_MNG_TIM_DTIM_COUNT 0 /* d11 management DTIM count */ ++#define DOT11_MNG_TIM_DTIM_PERIOD 1 /* d11 management DTIM period */ ++#define DOT11_MNG_TIM_BITMAP_CTL 2 /* d11 management TIM BITMAP control */ ++#define DOT11_MNG_TIM_PVB 3 /* d11 management TIM PVB */ ++ ++/* TLV defines */ ++#define TLV_TAG_OFF 0 /* tag offset */ ++#define TLV_LEN_OFF 1 /* length offset */ ++#define TLV_HDR_LEN 2 /* header length */ ++#define TLV_BODY_OFF 2 /* body offset */ ++ ++/* Management Frame Information Element IDs */ ++#define DOT11_MNG_SSID_ID 0 /* d11 management SSID id */ ++#define DOT11_MNG_RATES_ID 1 /* d11 management rates id */ ++#define DOT11_MNG_FH_PARMS_ID 2 /* d11 management FH parameter id */ ++#define DOT11_MNG_DS_PARMS_ID 3 /* d11 management DS parameter id */ ++#define DOT11_MNG_CF_PARMS_ID 4 /* d11 management CF parameter id */ ++#define DOT11_MNG_TIM_ID 5 /* d11 management TIM id */ ++#define DOT11_MNG_IBSS_PARMS_ID 6 /* d11 management IBSS parameter id */ ++#define DOT11_MNG_COUNTRY_ID 7 /* d11 management country id */ ++#define DOT11_MNG_HOPPING_PARMS_ID 8 /* d11 management hopping parameter id */ ++#define DOT11_MNG_HOPPING_TABLE_ID 9 /* d11 management hopping table id */ ++#define DOT11_MNG_REQUEST_ID 10 /* d11 management request id */ ++#define DOT11_MNG_QBSS_LOAD_ID 11 /* d11 management QBSS Load id */ ++#define DOT11_MNG_EDCA_PARAM_ID 12 /* 11E EDCA Parameter id */ ++#define DOT11_MNG_CHALLENGE_ID 16 /* d11 management chanllenge id */ ++#define DOT11_MNG_PWR_CONSTRAINT_ID 32 /* 11H PowerConstraint */ ++#define DOT11_MNG_PWR_CAP_ID 33 /* 11H PowerCapability */ ++#define DOT11_MNG_TPC_REQUEST_ID 34 /* 11H TPC Request */ ++#define DOT11_MNG_TPC_REPORT_ID 35 /* 11H TPC Report */ ++#define DOT11_MNG_SUPP_CHANNELS_ID 36 /* 11H Supported Channels */ ++#define DOT11_MNG_CHANNEL_SWITCH_ID 37 /* 11H ChannelSwitch Announcement */ ++#define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */ ++#define DOT11_MNG_MEASURE_REPORT_ID 39 /* 11H MeasurementReport */ ++#define DOT11_MNG_QUIET_ID 40 /* 11H Quiet */ ++#define DOT11_MNG_IBSS_DFS_ID 41 /* 11H IBSS_DFS */ ++#define DOT11_MNG_ERP_ID 42 /* d11 management ERP id */ ++#define DOT11_MNG_TS_DELAY_ID 43 /* d11 management TS Delay id */ ++#define DOT11_MNG_HT_CAP 45 /* d11 mgmt HT cap id */ ++#define DOT11_MNG_QOS_CAP_ID 46 /* 11E QoS Capability id */ ++#define DOT11_MNG_NONERP_ID 47 /* d11 management NON-ERP id */ ++#define DOT11_MNG_RSN_ID 48 /* d11 management RSN id */ ++#define DOT11_MNG_EXT_RATES_ID 50 /* d11 management ext. rates id */ ++#define DOT11_MNG_AP_CHREP_ID 51 /* 11k AP Channel report id */ ++#define DOT11_MNG_NBR_REP_ID 52 /* 11k Neighbor report id */ ++#define DOT11_MNG_MDIE_ID 54 /* 11r Mobility domain id */ ++#define DOT11_MNG_FTIE_ID 55 /* 11r Fast Bss Transition id */ ++#define DOT11_MNG_FT_TI_ID 56 /* 11r Timeout Interval id */ ++#define DOT11_MNG_REGCLASS_ID 59 /* d11 management regulatory class id */ ++#define DOT11_MNG_EXT_CSA_ID 60 /* d11 Extended CSA */ ++#define DOT11_MNG_HT_ADD 61 /* d11 mgmt additional HT info */ ++#define DOT11_MNG_EXT_CHANNEL_OFFSET 62 /* d11 mgmt ext channel offset */ ++#ifdef BCMWAPI_WAI ++#define DOT11_MNG_WAPI_ID 68 /* d11 management WAPI id */ ++#endif ++#define DOT11_MNG_WAPI_ID 68 /* d11 management WAPI id */ ++#define DOT11_MNG_TIME_ADVERTISE_ID 69 /* 11p time advertisement */ ++#define DOT11_MNG_RRM_CAP_ID 70 /* 11k radio measurement capability */ ++#define DOT11_MNG_HT_BSS_COEXINFO_ID 72 /* d11 mgmt OBSS Coexistence INFO */ ++#define DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID 73 /* d11 mgmt OBSS Intolerant Channel list */ ++#define DOT11_MNG_HT_OBSS_ID 74 /* d11 mgmt OBSS HT info */ ++#define DOT11_MNG_CHANNEL_USAGE 97 /* 11v channel usage */ ++#define DOT11_MNG_TIME_ZONE_ID 98 /* 11v time zone */ ++#define DOT11_MNG_LINK_IDENTIFIER_ID 101 /* 11z TDLS Link Identifier IE */ ++#define DOT11_MNG_WAKEUP_SCHEDULE_ID 102 /* 11z TDLS Wakeup Schedule IE */ ++#define DOT11_MNG_CHANNEL_SWITCH_TIMING_ID 104 /* 11z TDLS Channel Switch Timing IE */ ++#define DOT11_MNG_PTI_CONTROL_ID 105 /* 11z TDLS PTI Control IE */ ++#define DOT11_MNG_PU_BUFFER_STATUS_ID 106 /* 11z TDLS PU Buffer Status IE */ ++#define DOT11_MNG_INTERWORKING_ID 107 /* 11u interworking */ ++#define DOT11_MNG_ADVERTISEMENT_ID 108 /* 11u advertisement protocol */ ++#define DOT11_MNG_EXP_BW_REQ_ID 109 /* 11u expedited bandwith request */ ++#define DOT11_MNG_QOS_MAP_ID 110 /* 11u QoS map set */ ++#define DOT11_MNG_ROAM_CONSORT_ID 111 /* 11u roaming consortium */ ++#define DOT11_MNG_EMERGCY_ALERT_ID 112 /* 11u emergency alert identifier */ ++#define DOT11_MNG_EXT_CAP_ID 127 /* d11 mgmt ext capability */ ++#define DOT11_MNG_VHT_CAP_ID 191 /* d11 mgmt VHT cap id */ ++#define DOT11_MNG_VHT_OPERATION_ID 192 /* d11 mgmt VHT op id */ ++ ++#define DOT11_MNG_WPA_ID 221 /* d11 management WPA id */ ++#define DOT11_MNG_PROPR_ID 221 /* d11 management proprietary id */ ++/* should start using this one instead of above two */ ++#define DOT11_MNG_VS_ID 221 /* d11 management Vendor Specific IE */ ++ ++/* Rate element Basic flag and rate mask */ ++#define DOT11_RATE_BASIC 0x80 /* flag for a Basic Rate */ ++#define DOT11_RATE_MASK 0x7F /* mask for numeric part of rate */ ++ ++/* ERP info element bit values */ ++#define DOT11_MNG_ERP_LEN 1 /* ERP is currently 1 byte long */ ++#define DOT11_MNG_NONERP_PRESENT 0x01 /* NonERP (802.11b) STAs are present ++ *in the BSS ++ */ ++#define DOT11_MNG_USE_PROTECTION 0x02 /* Use protection mechanisms for ++ *ERP-OFDM frames ++ */ ++#define DOT11_MNG_BARKER_PREAMBLE 0x04 /* Short Preambles: 0 == allowed, ++ * 1 == not allowed ++ */ ++/* TS Delay element offset & size */ ++#define DOT11_MGN_TS_DELAY_LEN 4 /* length of TS DELAY IE */ ++#define TS_DELAY_FIELD_SIZE 4 /* TS DELAY field size */ ++ ++/* Capability Information Field */ ++#define DOT11_CAP_ESS 0x0001 /* d11 cap. ESS */ ++#define DOT11_CAP_IBSS 0x0002 /* d11 cap. IBSS */ ++#define DOT11_CAP_POLLABLE 0x0004 /* d11 cap. pollable */ ++#define DOT11_CAP_POLL_RQ 0x0008 /* d11 cap. poll request */ ++#define DOT11_CAP_PRIVACY 0x0010 /* d11 cap. privacy */ ++#define DOT11_CAP_SHORT 0x0020 /* d11 cap. short */ ++#define DOT11_CAP_PBCC 0x0040 /* d11 cap. PBCC */ ++#define DOT11_CAP_AGILITY 0x0080 /* d11 cap. agility */ ++#define DOT11_CAP_SPECTRUM 0x0100 /* d11 cap. spectrum */ ++#define DOT11_CAP_SHORTSLOT 0x0400 /* d11 cap. shortslot */ ++#define DOT11_CAP_RRM 0x1000 /* d11 cap. 11k radio measurement */ ++#define DOT11_CAP_CCK_OFDM 0x2000 /* d11 cap. CCK/OFDM */ ++ ++/* Extended capabilities IE bitfields */ ++/* 20/40 BSS Coexistence Management support bit position */ ++#define DOT11_EXT_CAP_OBSS_COEX_MGMT 0 ++/* scheduled PSMP support bit position */ ++#define DOT11_EXT_CAP_SPSMP 6 ++/* BSS Transition Management support bit position */ ++#define DOT11_EXT_CAP_BSS_TRANSITION_MGMT 19 ++/* Interworking support bit position */ ++#define DOT11_EXT_CAP_IW 31 ++/* service Interval granularity bit position and mask */ ++#define DOT11_EXT_CAP_SI 41 ++#define DOT11_EXT_CAP_SI_MASK 0x0E ++ ++/* ++ * Action Frame Constants ++ */ ++#define DOT11_ACTION_HDR_LEN 2 /* action frame category + action field */ ++#define DOT11_ACTION_CAT_OFF 0 /* category offset */ ++#define DOT11_ACTION_ACT_OFF 1 /* action offset */ ++ ++/* Action Category field (sec 7.3.1.11) */ ++#define DOT11_ACTION_CAT_ERR_MASK 0x80 /* category error mask */ ++#define DOT11_ACTION_CAT_MASK 0x7F /* category mask */ ++#define DOT11_ACTION_CAT_SPECT_MNG 0 /* category spectrum management */ ++#define DOT11_ACTION_CAT_QOS 1 /* category QoS */ ++#define DOT11_ACTION_CAT_DLS 2 /* category DLS */ ++#define DOT11_ACTION_CAT_BLOCKACK 3 /* category block ack */ ++#define DOT11_ACTION_CAT_PUBLIC 4 /* category public */ ++#define DOT11_ACTION_CAT_RRM 5 /* category radio measurements */ ++#define DOT11_ACTION_CAT_FBT 6 /* category fast bss transition */ ++#define DOT11_ACTION_CAT_HT 7 /* category for HT */ ++#define DOT11_ACTION_CAT_SA_QUERY 8 /* security association query */ ++#define DOT11_ACTION_CAT_PDPA 9 /* protected dual of public action */ ++#define DOT11_ACTION_CAT_BSSMGMT 10 /* category for BSS transition management */ ++#define DOT11_ACTION_NOTIFICATION 17 ++#define DOT11_ACTION_CAT_VSP 126 /* protected vendor specific */ ++#define DOT11_ACTION_CAT_VS 127 /* category Vendor Specific */ ++ ++/* Spectrum Management Action IDs (sec 7.4.1) */ ++#define DOT11_SM_ACTION_M_REQ 0 /* d11 action measurement request */ ++#define DOT11_SM_ACTION_M_REP 1 /* d11 action measurement response */ ++#define DOT11_SM_ACTION_TPC_REQ 2 /* d11 action TPC request */ ++#define DOT11_SM_ACTION_TPC_REP 3 /* d11 action TPC response */ ++#define DOT11_SM_ACTION_CHANNEL_SWITCH 4 /* d11 action channel switch */ ++#define DOT11_SM_ACTION_EXT_CSA 5 /* d11 extened CSA for 11n */ ++ ++/* HT action ids */ ++#define DOT11_ACTION_ID_HT_CH_WIDTH 0 /* notify channel width action id */ ++#define DOT11_ACTION_ID_HT_MIMO_PS 1 /* mimo ps action id */ ++ ++/* Public action ids */ ++#define DOT11_PUB_ACTION_BSS_COEX_MNG 0 /* 20/40 Coexistence Management action id */ ++#define DOT11_PUB_ACTION_CHANNEL_SWITCH 4 /* d11 action channel switch */ ++ ++/* Block Ack action types */ ++#define DOT11_BA_ACTION_ADDBA_REQ 0 /* ADDBA Req action frame type */ ++#define DOT11_BA_ACTION_ADDBA_RESP 1 /* ADDBA Resp action frame type */ ++#define DOT11_BA_ACTION_DELBA 2 /* DELBA action frame type */ ++ ++/* ADDBA action parameters */ ++#define DOT11_ADDBA_PARAM_AMSDU_SUP 0x0001 /* AMSDU supported under BA */ ++#define DOT11_ADDBA_PARAM_POLICY_MASK 0x0002 /* policy mask(ack vs delayed) */ ++#define DOT11_ADDBA_PARAM_POLICY_SHIFT 1 /* policy shift */ ++#define DOT11_ADDBA_PARAM_TID_MASK 0x003c /* tid mask */ ++#define DOT11_ADDBA_PARAM_TID_SHIFT 2 /* tid shift */ ++#define DOT11_ADDBA_PARAM_BSIZE_MASK 0xffc0 /* buffer size mask */ ++#define DOT11_ADDBA_PARAM_BSIZE_SHIFT 6 /* buffer size shift */ ++ ++#define DOT11_ADDBA_POLICY_DELAYED 0 /* delayed BA policy */ ++#define DOT11_ADDBA_POLICY_IMMEDIATE 1 /* immediate BA policy */ ++ ++/* Fast Transition action types */ ++#define DOT11_FT_ACTION_FT_RESERVED 0 ++#define DOT11_FT_ACTION_FT_REQ 1 /* FBT request - for over-the-DS FBT */ ++#define DOT11_FT_ACTION_FT_RES 2 /* FBT response - for over-the-DS FBT */ ++#define DOT11_FT_ACTION_FT_CON 3 /* FBT confirm - for OTDS with RRP */ ++#define DOT11_FT_ACTION_FT_ACK 4 /* FBT ack */ ++ ++/* DLS action types */ ++#define DOT11_DLS_ACTION_REQ 0 /* DLS Request */ ++#define DOT11_DLS_ACTION_RESP 1 /* DLS Response */ ++#define DOT11_DLS_ACTION_TD 2 /* DLS Teardown */ ++ ++/* Wireless Network Management (WNM) action types */ ++#define DOT11_WNM_ACTION_EVENT_REQ 0 ++#define DOT11_WNM_ACTION_EVENT_REP 1 ++#define DOT11_WNM_ACTION_DIAG_REQ 2 ++#define DOT11_WNM_ACTION_DIAG_REP 3 ++#define DOT11_WNM_ACTION_LOC_CFG_REQ 4 ++#define DOT11_WNM_ACTION_LOC_RFG_RESP 5 ++#define DOT11_WNM_ACTION_BSS_TRANS_QURY 6 ++#define DOT11_WNM_ACTION_BSS_TRANS_REQ 7 ++#define DOT11_WNM_ACTION_BSS_TRANS_RESP 8 ++#define DOT11_WNM_ACTION_FMS_REQ 9 ++#define DOT11_WNM_ACTION_FMS_RESP 10 ++#define DOT11_WNM_ACTION_COL_INTRFRNCE_REQ 11 ++#define DOT11_WNM_ACTION_COL_INTRFRNCE_REP 12 ++#define DOT11_WNM_ACTION_TFS_REQ 13 ++#define DOT11_WNM_ACTION_TFS_RESP 14 ++#define DOT11_WNM_ACTION_TFS_NOTIFY 15 ++#define DOT11_WNM_ACTION_WNM_SLEEP_REQ 16 ++#define DOT11_WNM_ACTION_WNM_SLEEP_RESP 17 ++#define DOT11_WNM_ACTION_TIM_BCAST_REQ 18 ++#define DOT11_WNM_ACTION_TIM_BCAST_RESP 19 ++#define DOT11_WNM_ACTION_QOS_TRFC_CAP_UPD 20 ++#define DOT11_WNM_ACTION_CHAN_USAGE_REQ 21 ++#define DOT11_WNM_ACTION_CHAN_USAGE_RESP 22 ++#define DOT11_WNM_ACTION_DMS_REQ 23 ++#define DOT11_WNM_ACTION_DMS_RESP 24 ++#define DOT11_WNM_ACTION_TMNG_MEASUR_REQ 25 ++#define DOT11_WNM_ACTION_NOTFCTN_REQ 26 ++#define DOT11_WNM_ACTION_NOTFCTN_RES 27 ++ ++#define DOT11_MNG_COUNTRY_ID_LEN 3 ++ ++/* DLS Request frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_dls_req { ++ uint8 category; /* category of action frame (2) */ ++ uint8 action; /* DLS action: req (0) */ ++ struct ether_addr da; /* destination address */ ++ struct ether_addr sa; /* source address */ ++ uint16 cap; /* capability */ ++ uint16 timeout; /* timeout value */ ++ uint8 data[1]; /* IE:support rate, extend support rate, HT cap */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_dls_req dot11_dls_req_t; ++#define DOT11_DLS_REQ_LEN 18 /* Fixed length */ ++ ++/* DLS response frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_dls_resp { ++ uint8 category; /* category of action frame (2) */ ++ uint8 action; /* DLS action: req (0) */ ++ uint16 status; /* status code field */ ++ struct ether_addr da; /* destination address */ ++ struct ether_addr sa; /* source address */ ++ uint8 data[1]; /* optional: capability, rate ... */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_dls_resp dot11_dls_resp_t; ++#define DOT11_DLS_RESP_LEN 16 /* Fixed length */ ++ ++ ++/* BSS Management Transition Query frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_query { ++ uint8 category; /* category of action frame (10) */ ++ uint8 action; /* WNM action: trans_query (6) */ ++ uint8 token; /* dialog token */ ++ uint8 reason; /* transition query reason */ ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_bss_trans_query dot11_bss_trans_query_t; ++#define DOT11_BSS_TRANS_QUERY_LEN 4 /* Fixed length */ ++ ++/* BSS Management Transition Request frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_req { ++ uint8 category; /* category of action frame (10) */ ++ uint8 action; /* WNM action: trans_req (7) */ ++ uint8 token; /* dialog token */ ++ uint8 reqmode; /* transition request mode */ ++ uint16 disassoc_tmr; /* disassociation timer */ ++ uint8 validity_intrvl; /* validity interval */ ++ uint8 data[1]; /* optional: BSS term duration, ... */ ++ /* ...session info URL, list */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_bss_trans_req dot11_bss_trans_req_t; ++#define DOT11_BSS_TRANS_REQ_LEN 7 /* Fixed length */ ++ ++#define DOT11_BSS_TERM_DUR_LEN 12 /* Fixed length if present */ ++ ++ ++/* BSS Mgmt Transition Request Mode Field - 802.11v */ ++#define DOT11_BSS_TRNS_REQMODE_PREF_LIST_INCL 0x01 ++#define DOT11_BSS_TRNS_REQMODE_ABRIDGED 0x02 ++#define DOT11_BSS_TRNS_REQMODE_DISASSOC_IMMINENT 0x04 ++#define DOT11_BSS_TRNS_REQMODE_BSS_TERM_INCL 0x08 ++#define DOT11_BSS_TRNS_REQMODE_ESS_DISASSOC_IMNT 0x10 ++ ++ ++/* BSS Management transition response frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_res { ++ uint8 category; /* category of action frame (10) */ ++ uint8 action; /* WNM action: trans_res (8) */ ++ uint8 token; /* dialog token */ ++ uint8 status; /* transition status */ ++ uint8 term_delay; /* validity interval */ ++ uint8 data[1]; /* optional: BSS term duration, ... */ ++ /* ...session info URL, list */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_bss_trans_res dot11_bss_trans_res_t; ++#define DOT11_BSS_TRANS_RES_LEN 5 /* Fixed length */ ++ ++/* BSS Mgmt Transition Response Status Field */ ++#define DOT11_BSS_TRNS_RES_STATUS_ACCEPT 0 ++#define DOT11_BSS_TRNS_RES_STATUS_REJECT 1 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_BCN 2 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_CAP 3 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_UNDESIRED 4 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_DELAY_REQ 5 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_BSS_LIST_PROVIDED 6 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_NO_SUITABLE_BSS 7 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_LEAVING_ESS 8 ++ ++ ++/* Neighbor Report BSSID Information Field */ ++#define DOT11_NBR_RPRT_BSSID_INFO_REACHABILTY 0x0003 ++#define DOT11_NBR_RPRT_BSSID_INFO_SEC 0x0004 ++#define DOT11_NBR_RPRT_BSSID_INFO_KEY_SCOPE 0x0008 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP 0x03f0 ++ ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_SPEC_MGMT 0x0010 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_QOS 0x0020 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_APSD 0x0040 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_RDIO_MSMT 0x0080 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_DEL_BA 0x0100 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_IMM_BA 0x0200 ++ ++/* Neighbor Report Subelements */ ++#define DOT11_NBR_RPRT_SUBELEM_BSS_CANDDT_PREF_ID 3 ++ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_addba_req { ++ uint8 category; /* category of action frame (3) */ ++ uint8 action; /* action: addba req */ ++ uint8 token; /* identifier */ ++ uint16 addba_param_set; /* parameter set */ ++ uint16 timeout; /* timeout in seconds */ ++ uint16 start_seqnum; /* starting sequence number */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_addba_req dot11_addba_req_t; ++#define DOT11_ADDBA_REQ_LEN 9 /* length of addba req frame */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_addba_resp { ++ uint8 category; /* category of action frame (3) */ ++ uint8 action; /* action: addba resp */ ++ uint8 token; /* identifier */ ++ uint16 status; /* status of add request */ ++ uint16 addba_param_set; /* negotiated parameter set */ ++ uint16 timeout; /* negotiated timeout in seconds */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_addba_resp dot11_addba_resp_t; ++#define DOT11_ADDBA_RESP_LEN 9 /* length of addba resp frame */ ++ ++/* DELBA action parameters */ ++#define DOT11_DELBA_PARAM_INIT_MASK 0x0800 /* initiator mask */ ++#define DOT11_DELBA_PARAM_INIT_SHIFT 11 /* initiator shift */ ++#define DOT11_DELBA_PARAM_TID_MASK 0xf000 /* tid mask */ ++#define DOT11_DELBA_PARAM_TID_SHIFT 12 /* tid shift */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_delba { ++ uint8 category; /* category of action frame (3) */ ++ uint8 action; /* action: addba req */ ++ uint16 delba_param_set; /* paarmeter set */ ++ uint16 reason; /* reason for dellba */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_delba dot11_delba_t; ++#define DOT11_DELBA_LEN 6 /* length of delba frame */ ++ ++/* SA Query action field value */ ++#define SA_QUERY_REQUEST 0 ++#define SA_QUERY_RESPONSE 1 ++ ++/* ************* 802.11r related definitions. ************* */ ++ ++/* Over-the-DS Fast Transition Request frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_ft_req { ++ uint8 category; /* category of action frame (6) */ ++ uint8 action; /* action: ft req */ ++ uint8 sta_addr[ETHER_ADDR_LEN]; ++ uint8 tgt_ap_addr[ETHER_ADDR_LEN]; ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ft_req dot11_ft_req_t; ++#define DOT11_FT_REQ_FIXED_LEN 14 ++ ++/* Over-the-DS Fast Transition Response frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_ft_res { ++ uint8 category; /* category of action frame (6) */ ++ uint8 action; /* action: ft resp */ ++ uint8 sta_addr[ETHER_ADDR_LEN]; ++ uint8 tgt_ap_addr[ETHER_ADDR_LEN]; ++ uint16 status; /* status code */ ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ft_res dot11_ft_res_t; ++#define DOT11_FT_RES_FIXED_LEN 16 ++ ++ ++/* ************* 802.11k related definitions. ************* */ ++ ++/* Radio measurements enabled capability ie */ ++ ++#define DOT11_RRM_CAP_LEN 5 /* length of rrm cap bitmap */ ++BWL_PRE_PACKED_STRUCT struct dot11_rrm_cap_ie { ++ uint8 cap[DOT11_RRM_CAP_LEN]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rrm_cap_ie dot11_rrm_cap_ie_t; ++ ++/* Bitmap definitions for cap ie */ ++#define DOT11_RRM_CAP_LINK 0 ++#define DOT11_RRM_CAP_NEIGHBOR_REPORT 1 ++#define DOT11_RRM_CAP_PARALLEL 2 ++#define DOT11_RRM_CAP_REPEATED 3 ++#define DOT11_RRM_CAP_BCN_PASSIVE 4 ++#define DOT11_RRM_CAP_BCN_ACTIVE 5 ++#define DOT11_RRM_CAP_BCN_TABLE 6 ++#define DOT11_RRM_CAP_BCN_REP_COND 7 ++#define DOT11_RRM_CAP_AP_CHANREP 16 ++ ++ ++/* Operating Class (formerly "Regulatory Class") definitions */ ++#define DOT11_OP_CLASS_NONE 255 ++ ++ ++/* Radio Measurements action ids */ ++#define DOT11_RM_ACTION_RM_REQ 0 /* Radio measurement request */ ++#define DOT11_RM_ACTION_RM_REP 1 /* Radio measurement report */ ++#define DOT11_RM_ACTION_LM_REQ 2 /* Link measurement request */ ++#define DOT11_RM_ACTION_LM_REP 3 /* Link measurement report */ ++#define DOT11_RM_ACTION_NR_REQ 4 /* Neighbor report request */ ++#define DOT11_RM_ACTION_NR_REP 5 /* Neighbor report response */ ++ ++/* Generic radio measurement action frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_rm_action { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rm_action dot11_rm_action_t; ++#define DOT11_RM_ACTION_LEN 3 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rmreq { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ uint16 reps; /* no. of repetitions */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmreq dot11_rmreq_t; ++#define DOT11_RMREQ_LEN 5 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rm_ie { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rm_ie dot11_rm_ie_t; ++#define DOT11_RM_IE_LEN 5 ++ ++/* Definitions for "mode" bits in rm req */ ++#define DOT11_RMREQ_MODE_PARALLEL 1 ++#define DOT11_RMREQ_MODE_ENABLE 2 ++#define DOT11_RMREQ_MODE_REQUEST 4 ++#define DOT11_RMREQ_MODE_REPORT 8 ++#define DOT11_RMREQ_MODE_DURMAND 0x10 /* Duration Mandatory */ ++ ++/* Definitions for "mode" bits in rm rep */ ++#define DOT11_RMREP_MODE_LATE 1 ++#define DOT11_RMREP_MODE_INCAPABLE 2 ++#define DOT11_RMREP_MODE_REFUSED 4 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rmreq_bcn { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++ uint8 reg; ++ uint8 channel; ++ uint16 interval; ++ uint16 duration; ++ uint8 bcn_mode; ++ struct ether_addr bssid; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmreq_bcn dot11_rmreq_bcn_t; ++#define DOT11_RMREQ_BCN_LEN 18 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rmrep_bcn { ++ uint8 reg; ++ uint8 channel; ++ uint32 starttime[2]; ++ uint16 duration; ++ uint8 frame_info; ++ uint8 rcpi; ++ uint8 rsni; ++ struct ether_addr bssid; ++ uint8 antenna_id; ++ uint32 parent_tsf; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmrep_bcn dot11_rmrep_bcn_t; ++#define DOT11_RMREP_BCN_LEN 26 ++ ++/* Beacon request measurement mode */ ++#define DOT11_RMREQ_BCN_PASSIVE 0 ++#define DOT11_RMREQ_BCN_ACTIVE 1 ++#define DOT11_RMREQ_BCN_TABLE 2 ++ ++/* Sub-element IDs for Beacon Request */ ++#define DOT11_RMREQ_BCN_SSID_ID 0 ++#define DOT11_RMREQ_BCN_REPINFO_ID 1 ++#define DOT11_RMREQ_BCN_REPDET_ID 2 ++#define DOT11_RMREQ_BCN_REQUEST_ID 10 ++#define DOT11_RMREQ_BCN_APCHREP_ID 51 ++ ++/* Reporting Detail element definition */ ++#define DOT11_RMREQ_BCN_REPDET_FIXED 0 /* Fixed length fields only */ ++#define DOT11_RMREQ_BCN_REPDET_REQUEST 1 /* + requested information elems */ ++#define DOT11_RMREQ_BCN_REPDET_ALL 2 /* All fields */ ++ ++/* Sub-element IDs for Beacon Report */ ++#define DOT11_RMREP_BCN_FRM_BODY 1 ++ ++/* Neighbor measurement report */ ++BWL_PRE_PACKED_STRUCT struct dot11_rmrep_nbr { ++ struct ether_addr bssid; ++ uint32 bssid_info; ++ uint8 reg; ++ uint8 channel; ++ uint8 phytype; ++ uchar sub_elements[1]; /* Variable size data */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmrep_nbr dot11_rmrep_nbr_t; ++#define DOT11_RMREP_NBR_LEN 13 ++ ++/* MLME Enumerations */ ++#define DOT11_BSSTYPE_INFRASTRUCTURE 0 /* d11 infrastructure */ ++#define DOT11_BSSTYPE_INDEPENDENT 1 /* d11 independent */ ++#define DOT11_BSSTYPE_ANY 2 /* d11 any BSS type */ ++#define DOT11_SCANTYPE_ACTIVE 0 /* d11 scan active */ ++#define DOT11_SCANTYPE_PASSIVE 1 /* d11 scan passive */ ++ ++/* Link Measurement */ ++BWL_PRE_PACKED_STRUCT struct dot11_lmreq { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ uint8 txpwr; /* Transmit Power Used */ ++ uint8 maxtxpwr; /* Max Transmit Power */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_lmreq dot11_lmreq_t; ++#define DOT11_LMREQ_LEN 5 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_lmrep { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ dot11_tpc_rep_t tpc; /* TPC element */ ++ uint8 rxant; /* Receive Antenna ID */ ++ uint8 txant; /* Transmit Antenna ID */ ++ uint8 rcpi; /* RCPI */ ++ uint8 rsni; /* RSNI */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_lmrep dot11_lmrep_t; ++#define DOT11_LMREP_LEN 11 ++ ++/* 802.11 BRCM "Compromise" Pre N constants */ ++#define PREN_PREAMBLE 24 /* green field preamble time */ ++#define PREN_MM_EXT 12 /* extra mixed mode preamble time */ ++#define PREN_PREAMBLE_EXT 4 /* extra preamble (multiply by unique_streams-1) */ ++ ++/* 802.11N PHY constants */ ++#define RIFS_11N_TIME 2 /* NPHY RIFS time */ ++ ++/* 802.11 HT PLCP format 802.11n-2009, sec 20.3.9.4.3 ++ * HT-SIG is composed of two 24 bit parts, HT-SIG1 and HT-SIG2 ++ */ ++/* HT-SIG1 */ ++#define HT_SIG1_MCS_MASK 0x00007F ++#define HT_SIG1_CBW 0x000080 ++#define HT_SIG1_HT_LENGTH 0xFFFF00 ++ ++/* HT-SIG2 */ ++#define HT_SIG2_SMOOTHING 0x000001 ++#define HT_SIG2_NOT_SOUNDING 0x000002 ++#define HT_SIG2_RESERVED 0x000004 ++#define HT_SIG2_AGGREGATION 0x000008 ++#define HT_SIG2_STBC_MASK 0x000030 ++#define HT_SIG2_STBC_SHIFT 4 ++#define HT_SIG2_FEC_CODING 0x000040 ++#define HT_SIG2_SHORT_GI 0x000080 ++#define HT_SIG2_ESS_MASK 0x000300 ++#define HT_SIG2_ESS_SHIFT 8 ++#define HT_SIG2_CRC 0x03FC00 ++#define HT_SIG2_TAIL 0x1C0000 ++ ++/* 802.11 A PHY constants */ ++#define APHY_SLOT_TIME 9 /* APHY slot time */ ++#define APHY_SIFS_TIME 16 /* APHY SIFS time */ ++#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME)) /* APHY DIFS time */ ++#define APHY_PREAMBLE_TIME 16 /* APHY preamble time */ ++#define APHY_SIGNAL_TIME 4 /* APHY signal time */ ++#define APHY_SYMBOL_TIME 4 /* APHY symbol time */ ++#define APHY_SERVICE_NBITS 16 /* APHY service nbits */ ++#define APHY_TAIL_NBITS 6 /* APHY tail nbits */ ++#define APHY_CWMIN 15 /* APHY cwmin */ ++ ++/* 802.11 B PHY constants */ ++#define BPHY_SLOT_TIME 20 /* BPHY slot time */ ++#define BPHY_SIFS_TIME 10 /* BPHY SIFS time */ ++#define BPHY_DIFS_TIME 50 /* BPHY DIFS time */ ++#define BPHY_PLCP_TIME 192 /* BPHY PLCP time */ ++#define BPHY_PLCP_SHORT_TIME 96 /* BPHY PLCP short time */ ++#define BPHY_CWMIN 31 /* BPHY cwmin */ ++ ++/* 802.11 G constants */ ++#define DOT11_OFDM_SIGNAL_EXTENSION 6 /* d11 OFDM signal extension */ ++ ++#define PHY_CWMAX 1023 /* PHY cwmax */ ++ ++#define DOT11_MAXNUMFRAGS 16 /* max # fragments per MSDU */ ++ ++/* 802.11 AC (VHT) constants */ ++ ++typedef int vht_group_id_t; ++ ++/* for VHT-A1 */ ++/* SIG-A1 reserved bits */ ++#define VHT_SIGA1_CONST_MASK 0x800004 ++ ++#define VHT_SIGA1_20MHZ_VAL 0x000000 ++#define VHT_SIGA1_40MHZ_VAL 0x000001 ++#define VHT_SIGA1_80MHZ_VAL 0x000002 ++#define VHT_SIGA1_160MHZ_VAL 0x000003 ++ ++#define VHT_SIGA1_STBC 0x000008 ++ ++#define VHT_SIGA1_GID_MAX_GID 0x3f ++#define VHT_SIGA1_GID_SHIFT 4 ++#define VHT_SIGA1_GID_TO_AP 0x00 ++#define VHT_SIGA1_GID_NOT_TO_AP 0x3f ++ ++#define VHT_SIGA1_NSTS_SHIFT 10 ++#define VHT_SIGA1_NSTS_SHIFT_MASK_USER0 0x001C00 ++ ++#define VHT_SIGA1_PARTIAL_AID_SHIFT 13 ++ ++/* for VHT-A2 */ ++#define VHT_SIGA2_GI_NONE 0x000000 ++#define VHT_SIGA2_GI_SHORT 0x000001 ++#define VHT_SIGA2_GI_W_MOD10 0x000002 ++#define VHT_SIGA2_CODING_LDPC 0x000004 ++#define VHT_SIGA2_BEAMFORM_ENABLE 0x000100 ++#define VHT_SIGA2_MCS_SHIFT 4 ++ ++#define VHT_SIGA2_B9_RESERVED 0x000200 ++#define VHT_SIGA2_TAIL_MASK 0xfc0000 ++#define VHT_SIGA2_TAIL_VALUE 0x000000 ++ ++#define VHT_SIGA2_SVC_BITS 16 ++#define VHT_SIGA2_TAIL_BITS 6 ++ ++ ++/* dot11Counters Table - 802.11 spec., Annex D */ ++typedef struct d11cnt { ++ uint32 txfrag; /* dot11TransmittedFragmentCount */ ++ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ ++ uint32 txfail; /* dot11FailedCount */ ++ uint32 txretry; /* dot11RetryCount */ ++ uint32 txretrie; /* dot11MultipleRetryCount */ ++ uint32 rxdup; /* dot11FrameduplicateCount */ ++ uint32 txrts; /* dot11RTSSuccessCount */ ++ uint32 txnocts; /* dot11RTSFailureCount */ ++ uint32 txnoack; /* dot11ACKFailureCount */ ++ uint32 rxfrag; /* dot11ReceivedFragmentCount */ ++ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ ++ uint32 rxcrc; /* dot11FCSErrorCount */ ++ uint32 txfrmsnt; /* dot11TransmittedFrameCount */ ++ uint32 rxundec; /* dot11WEPUndecryptableCount */ ++} d11cnt_t; ++ ++/* OUI for BRCM proprietary IE */ ++#define BRCM_PROP_OUI "\x00\x90\x4C" /* Broadcom proprietary OUI */ ++ ++ ++/* BRCM OUI: Used in the proprietary(221) IE in all broadcom devices */ ++#define BRCM_OUI "\x00\x10\x18" /* Broadcom OUI */ ++ ++/* BRCM info element */ ++BWL_PRE_PACKED_STRUCT struct brcm_ie { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_OUI */ ++ uint8 ver; /* type/ver of this IE */ ++ uint8 assoc; /* # of assoc STAs */ ++ uint8 flags; /* misc flags */ ++ uint8 flags1; /* misc flags */ ++ uint16 amsdu_mtu_pref; /* preferred A-MSDU MTU */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct brcm_ie brcm_ie_t; ++#define BRCM_IE_LEN 11 /* BRCM IE length */ ++#define BRCM_IE_VER 2 /* BRCM IE version */ ++#define BRCM_IE_LEGACY_AES_VER 1 /* BRCM IE legacy AES version */ ++ ++/* brcm_ie flags */ ++#define BRF_LZWDS 0x4 /* lazy wds enabled */ ++#define BRF_BLOCKACK 0x8 /* BlockACK capable */ ++ ++/* brcm_ie flags1 */ ++#define BRF1_AMSDU 0x1 /* A-MSDU capable */ ++#define BRF1_WMEPS 0x4 /* AP is capable of handling WME + PS w/o APSD */ ++#define BRF1_PSOFIX 0x8 /* AP has fixed PS mode out-of-order packets */ ++#define BRF1_RX_LARGE_AGG 0x10 /* device can rx large aggregates */ ++#define BRF1_RFAWARE_DCS 0x20 /* RFAWARE dynamic channel selection (DCS) */ ++#define BRF1_SOFTAP 0x40 /* Configure as Broadcom SOFTAP */ ++ ++/* Vendor IE structure */ ++BWL_PRE_PACKED_STRUCT struct vndr_ie { ++ uchar id; ++ uchar len; ++ uchar oui [3]; ++ uchar data [1]; /* Variable size data */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct vndr_ie vndr_ie_t; ++ ++#define VNDR_IE_HDR_LEN 2 /* id + len field */ ++#define VNDR_IE_MIN_LEN 3 /* size of the oui field */ ++#define VNDR_IE_FIXED_LEN (VNDR_IE_HDR_LEN + VNDR_IE_MIN_LEN) ++#define VNDR_IE_MAX_LEN 256 /* verdor IE max length */ ++ ++/* ************* HT definitions. ************* */ ++#define MCSSET_LEN 16 /* 16-bits per 8-bit set to give 128-bits bitmap of MCS Index */ ++#define MAX_MCS_NUM (128) /* max mcs number = 128 */ ++ ++BWL_PRE_PACKED_STRUCT struct ht_cap_ie { ++ uint16 cap; ++ uint8 params; ++ uint8 supp_mcs[MCSSET_LEN]; ++ uint16 ext_htcap; ++ uint32 txbf_cap; ++ uint8 as_cap; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_cap_ie ht_cap_ie_t; ++ ++/* CAP IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */ ++/* the capability IE is primarily used to convey this nodes abilities */ ++BWL_PRE_PACKED_STRUCT struct ht_prop_cap_ie { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* type inidicates what follows */ ++ ht_cap_ie_t cap_ie; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_prop_cap_ie ht_prop_cap_ie_t; ++ ++#define HT_PROP_IE_OVERHEAD 4 /* overhead bytes for prop oui ie */ ++#define HT_CAP_IE_LEN 26 /* HT capability len (based on .11n d2.0) */ ++#define HT_CAP_IE_TYPE 51 ++ ++#define HT_CAP_LDPC_CODING 0x0001 /* Support for rx of LDPC coded pkts */ ++#define HT_CAP_40MHZ 0x0002 /* FALSE:20Mhz, TRUE:20/40MHZ supported */ ++#define HT_CAP_MIMO_PS_MASK 0x000C /* Mimo PS mask */ ++#define HT_CAP_MIMO_PS_SHIFT 0x0002 /* Mimo PS shift */ ++#define HT_CAP_MIMO_PS_OFF 0x0003 /* Mimo PS, no restriction */ ++#define HT_CAP_MIMO_PS_RTS 0x0001 /* Mimo PS, send RTS/CTS around MIMO frames */ ++#define HT_CAP_MIMO_PS_ON 0x0000 /* Mimo PS, MIMO disallowed */ ++#define HT_CAP_GF 0x0010 /* Greenfield preamble support */ ++#define HT_CAP_SHORT_GI_20 0x0020 /* 20MHZ short guard interval support */ ++#define HT_CAP_SHORT_GI_40 0x0040 /* 40Mhz short guard interval support */ ++#define HT_CAP_TX_STBC 0x0080 /* Tx STBC support */ ++#define HT_CAP_RX_STBC_MASK 0x0300 /* Rx STBC mask */ ++#define HT_CAP_RX_STBC_SHIFT 8 /* Rx STBC shift */ ++#define HT_CAP_DELAYED_BA 0x0400 /* delayed BA support */ ++#define HT_CAP_MAX_AMSDU 0x0800 /* Max AMSDU size in bytes , 0=3839, 1=7935 */ ++ ++#define HT_CAP_DSSS_CCK 0x1000 /* DSSS/CCK supported by the BSS */ ++#define HT_CAP_PSMP 0x2000 /* Power Save Multi Poll support */ ++#define HT_CAP_40MHZ_INTOLERANT 0x4000 /* 40MHz Intolerant */ ++#define HT_CAP_LSIG_TXOP 0x8000 /* L-SIG TXOP protection support */ ++ ++#define HT_CAP_RX_STBC_NO 0x0 /* no rx STBC support */ ++#define HT_CAP_RX_STBC_ONE_STREAM 0x1 /* rx STBC support of 1 spatial stream */ ++#define HT_CAP_RX_STBC_TWO_STREAM 0x2 /* rx STBC support of 1-2 spatial streams */ ++#define HT_CAP_RX_STBC_THREE_STREAM 0x3 /* rx STBC support of 1-3 spatial streams */ ++ ++#define VHT_MAX_MPDU 11454 /* max mpdu size for now (bytes) */ ++#define VHT_MPDU_MSDU_DELTA 56 /* Difference in spec - vht mpdu, amsdu len */ ++/* Max AMSDU len - per spec */ ++#define VHT_MAX_AMSDU (VHT_MAX_MPDU - VHT_MPDU_MSDU_DELTA) ++ ++#define HT_MAX_AMSDU 7935 /* max amsdu size (bytes) per the HT spec */ ++#define HT_MIN_AMSDU 3835 /* min amsdu size (bytes) per the HT spec */ ++ ++#define HT_PARAMS_RX_FACTOR_MASK 0x03 /* ampdu rcv factor mask */ ++#define HT_PARAMS_DENSITY_MASK 0x1C /* ampdu density mask */ ++#define HT_PARAMS_DENSITY_SHIFT 2 /* ampdu density shift */ ++ ++/* HT/AMPDU specific define */ ++#define AMPDU_MAX_MPDU_DENSITY 7 /* max mpdu density; in 1/4 usec units */ ++#define AMPDU_DENSITY_NONE 0 /* No density requirement */ ++#define AMPDU_DENSITY_1over4_US 1 /* 1/4 us density */ ++#define AMPDU_DENSITY_1over2_US 2 /* 1/2 us density */ ++#define AMPDU_DENSITY_1_US 3 /* 1 us density */ ++#define AMPDU_DENSITY_2_US 4 /* 2 us density */ ++#define AMPDU_DENSITY_4_US 5 /* 4 us density */ ++#define AMPDU_DENSITY_8_US 6 /* 8 us density */ ++#define AMPDU_DENSITY_16_US 7 /* 16 us density */ ++#define AMPDU_RX_FACTOR_8K 0 /* max rcv ampdu len (8kb) */ ++#define AMPDU_RX_FACTOR_16K 1 /* max rcv ampdu len (16kb) */ ++#define AMPDU_RX_FACTOR_32K 2 /* max rcv ampdu len (32kb) */ ++#define AMPDU_RX_FACTOR_64K 3 /* max rcv ampdu len (64kb) */ ++#define AMPDU_RX_FACTOR_BASE 8*1024 /* ampdu factor base for rx len */ ++ ++#define AMPDU_DELIMITER_LEN 4 /* length of ampdu delimiter */ ++#define AMPDU_DELIMITER_LEN_MAX 63 /* max length of ampdu delimiter(enforced in HW) */ ++ ++#define HT_CAP_EXT_PCO 0x0001 ++#define HT_CAP_EXT_PCO_TTIME_MASK 0x0006 ++#define HT_CAP_EXT_PCO_TTIME_SHIFT 1 ++#define HT_CAP_EXT_MCS_FEEDBACK_MASK 0x0300 ++#define HT_CAP_EXT_MCS_FEEDBACK_SHIFT 8 ++#define HT_CAP_EXT_HTC 0x0400 ++#define HT_CAP_EXT_RD_RESP 0x0800 ++ ++BWL_PRE_PACKED_STRUCT struct ht_add_ie { ++ uint8 ctl_ch; /* control channel number */ ++ uint8 byte1; /* ext ch,rec. ch. width, RIFS support */ ++ uint16 opmode; /* operation mode */ ++ uint16 misc_bits; /* misc bits */ ++ uint8 basic_mcs[MCSSET_LEN]; /* required MCS set */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_add_ie ht_add_ie_t; ++ ++/* ADD IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */ ++/* the additional IE is primarily used to convey the current BSS configuration */ ++BWL_PRE_PACKED_STRUCT struct ht_prop_add_ie { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* indicates what follows */ ++ ht_add_ie_t add_ie; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_prop_add_ie ht_prop_add_ie_t; ++ ++#define HT_ADD_IE_LEN 22 ++#define HT_ADD_IE_TYPE 52 ++ ++/* byte1 defn's */ ++#define HT_BW_ANY 0x04 /* set, STA can use 20 or 40MHz */ ++#define HT_RIFS_PERMITTED 0x08 /* RIFS allowed */ ++ ++/* opmode defn's */ ++#define HT_OPMODE_MASK 0x0003 /* protection mode mask */ ++#define HT_OPMODE_SHIFT 0 /* protection mode shift */ ++#define HT_OPMODE_PURE 0x0000 /* protection mode PURE */ ++#define HT_OPMODE_OPTIONAL 0x0001 /* protection mode optional */ ++#define HT_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */ ++#define HT_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */ ++#define HT_OPMODE_NONGF 0x0004 /* protection mode non-GF */ ++#define DOT11N_TXBURST 0x0008 /* Tx burst limit */ ++#define DOT11N_OBSS_NONHT 0x0010 /* OBSS Non-HT STA present */ ++ ++/* misc_bites defn's */ ++#define HT_BASIC_STBC_MCS 0x007f /* basic STBC MCS */ ++#define HT_DUAL_STBC_PROT 0x0080 /* Dual STBC Protection */ ++#define HT_SECOND_BCN 0x0100 /* Secondary beacon support */ ++#define HT_LSIG_TXOP 0x0200 /* L-SIG TXOP Protection full support */ ++#define HT_PCO_ACTIVE 0x0400 /* PCO active */ ++#define HT_PCO_PHASE 0x0800 /* PCO phase */ ++#define HT_DUALCTS_PROTECTION 0x0080 /* DUAL CTS protection needed */ ++ ++/* Tx Burst Limits */ ++#define DOT11N_2G_TXBURST_LIMIT 6160 /* 2G band Tx burst limit per 802.11n Draft 1.10 (usec) */ ++#define DOT11N_5G_TXBURST_LIMIT 3080 /* 5G band Tx burst limit per 802.11n Draft 1.10 (usec) */ ++ ++/* Macros for opmode */ ++#define GET_HT_OPMODE(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ >> HT_OPMODE_SHIFT) ++#define HT_MIXEDMODE_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ == HT_OPMODE_MIXED) /* mixed mode present */ ++#define HT_HT20_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ == HT_OPMODE_HT20IN40) /* 20MHz HT present */ ++#define HT_OPTIONAL_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ == HT_OPMODE_OPTIONAL) /* Optional protection present */ ++#define HT_USE_PROTECTION(add_ie) (HT_HT20_PRESENT((add_ie)) || \ ++ HT_MIXEDMODE_PRESENT((add_ie))) /* use protection */ ++#define HT_NONGF_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_NONGF) \ ++ == HT_OPMODE_NONGF) /* non-GF present */ ++#define DOT11N_TXBURST_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_TXBURST) \ ++ == DOT11N_TXBURST) /* Tx Burst present */ ++#define DOT11N_OBSS_NONHT_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_OBSS_NONHT) \ ++ == DOT11N_OBSS_NONHT) /* OBSS Non-HT present */ ++ ++BWL_PRE_PACKED_STRUCT struct obss_params { ++ uint16 passive_dwell; ++ uint16 active_dwell; ++ uint16 bss_widthscan_interval; ++ uint16 passive_total; ++ uint16 active_total; ++ uint16 chanwidth_transition_dly; ++ uint16 activity_threshold; ++} BWL_POST_PACKED_STRUCT; ++typedef struct obss_params obss_params_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_obss_ie { ++ uint8 id; ++ uint8 len; ++ obss_params_t obss_params; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_obss_ie dot11_obss_ie_t; ++#define DOT11_OBSS_SCAN_IE_LEN sizeof(obss_params_t) /* HT OBSS len (based on 802.11n d3.0) */ ++ ++/* HT control field */ ++#define HT_CTRL_LA_TRQ 0x00000002 /* sounding request */ ++#define HT_CTRL_LA_MAI 0x0000003C /* MCS request or antenna selection indication */ ++#define HT_CTRL_LA_MAI_SHIFT 2 ++#define HT_CTRL_LA_MAI_MRQ 0x00000004 /* MCS request */ ++#define HT_CTRL_LA_MAI_MSI 0x00000038 /* MCS request sequence identifier */ ++#define HT_CTRL_LA_MFSI 0x000001C0 /* MFB sequence identifier */ ++#define HT_CTRL_LA_MFSI_SHIFT 6 ++#define HT_CTRL_LA_MFB_ASELC 0x0000FE00 /* MCS feedback, antenna selection command/data */ ++#define HT_CTRL_LA_MFB_ASELC_SH 9 ++#define HT_CTRL_LA_ASELC_CMD 0x00000C00 /* ASEL command */ ++#define HT_CTRL_LA_ASELC_DATA 0x0000F000 /* ASEL data */ ++#define HT_CTRL_CAL_POS 0x00030000 /* Calibration position */ ++#define HT_CTRL_CAL_SEQ 0x000C0000 /* Calibration sequence */ ++#define HT_CTRL_CSI_STEERING 0x00C00000 /* CSI/Steering */ ++#define HT_CTRL_CSI_STEER_SHIFT 22 ++#define HT_CTRL_CSI_STEER_NFB 0 /* no fedback required */ ++#define HT_CTRL_CSI_STEER_CSI 1 /* CSI, H matrix */ ++#define HT_CTRL_CSI_STEER_NCOM 2 /* non-compressed beamforming */ ++#define HT_CTRL_CSI_STEER_COM 3 /* compressed beamforming */ ++#define HT_CTRL_NDP_ANNOUNCE 0x01000000 /* NDP announcement */ ++#define HT_CTRL_AC_CONSTRAINT 0x40000000 /* AC Constraint */ ++#define HT_CTRL_RDG_MOREPPDU 0x80000000 /* RDG/More PPDU */ ++ ++#define HT_OPMODE_OPTIONAL 0x0001 /* protection mode optional */ ++#define HT_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */ ++#define HT_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */ ++#define HT_OPMODE_NONGF 0x0004 /* protection mode non-GF */ ++#define DOT11N_TXBURST 0x0008 /* Tx burst limit */ ++#define DOT11N_OBSS_NONHT 0x0010 /* OBSS Non-HT STA present */ ++ ++/* ************* VHT definitions. ************* */ ++ ++BWL_PRE_PACKED_STRUCT struct vht_cap_ie { ++ uint32 vht_cap_info; ++ /* supported MCS set - 64 bit field */ ++ uint16 rx_mcs_map; ++ uint16 rx_max_rate; ++ uint16 tx_mcs_map; ++ uint16 tx_max_rate; ++} BWL_POST_PACKED_STRUCT; ++typedef struct vht_cap_ie vht_cap_ie_t; ++/* 4B cap_info + 8B supp_mcs */ ++#define VHT_CAP_IE_LEN 12 ++/* 32bit - cap info */ ++#define VHT_CAP_INFO_MAX_MPDU_LEN_MASK 0x00000003 ++#define VHT_CAP_INFO_SUPP_CHAN_WIDTH_MASK 0x0000000c ++#define VHT_CAP_INFO_LDPC 0x00000010 ++#define VHT_CAP_INFO_SGI_80MHZ 0x00000020 ++ ++#define VHT_CAP_INFO_SGI_160MHZ 0x00000040 ++#define VHT_CAP_INFO_TX_STBC 0x00000080 ++ ++#define VHT_CAP_INFO_RX_STBC_MASK 0x00000700 ++#define VHT_CAP_INFO_RX_STBC_SHIFT 8 ++#define VHT_CAP_INFO_SU_BEAMFMR 0x00000800 ++#define VHT_CAP_INFO_SU_BEAMFMEE 0x00001000 ++#define VHT_CAP_INFO_NUM_BMFMR_ANT_MASK 0x0000e000 ++#define VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT 13 ++ ++#define VHT_CAP_INFO_NUM_SOUNDING_DIM_MASK 0x00070000 ++#define VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT 16 ++#define VHT_CAP_INFO_MU_BEAMFMR 0x00080000 ++#define VHT_CAP_INFO_MU_BEAMFMEE 0x00100000 ++#define VHT_CAP_INFO_TXOPPS 0x00200000 ++#define VHT_CAP_INFO_HTCVHT 0x00400000 ++#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_MASK 0x03800000 ++#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT 23 ++ ++#define VHT_CAP_INFO_LINK_ADAPT_CAP_MASK 0x0c000000 ++#define VHT_CAP_INFO_LINK_ADAPT_CAP_SHIFT 26 ++ ++/* 64-bit Supp MCS. */ ++#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_MASK 0x1fff ++#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_SHIFT 0 ++ ++#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_MASK 0x1fff ++#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_SHIFT 0 ++ ++#define VHT_CAP_MCS_MAP_0_7 0 ++#define VHT_CAP_MCS_MAP_0_8 1 ++#define VHT_CAP_MCS_MAP_0_9 2 ++#define VHT_CAP_MCS_MAP_NONE 3 ++ ++#define VHT_CAP_MCS_MAP_NSS_MAX 8 ++ ++/* VHT Capabilities Supported Channel Width */ ++typedef enum vht_cap_chan_width { ++ VHT_CAP_CHAN_WIDTH_20_40 = 0x00, ++ VHT_CAP_CHAN_WIDTH_80 = 0x04, ++ VHT_CAP_CHAN_WIDTH_160 = 0x08 ++} vht_cap_chan_width_t; ++ ++/* VHT Capabilities Supported max MPDU LEN */ ++typedef enum vht_cap_max_mpdu_len { ++ VHT_CAP_MPDU_MAX_4K = 0x00, ++ VHT_CAP_MPDU_MAX_8K = 0x01, ++ VHT_CAP_MPDU_MAX_11K = 0x02 ++} vht_cap_max_mpdu_len_t; ++ ++/* VHT Operation Element */ ++BWL_PRE_PACKED_STRUCT struct vht_op_ie { ++ uint8 chan_width; ++ uint8 chan1; ++ uint8 chan2; ++ uint16 supp_mcs; /* same def as above in vht cap */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct vht_op_ie vht_op_ie_t; ++/* 3B VHT Op info + 2B Basic MCS */ ++#define VHT_OP_IE_LEN 5 ++ ++typedef enum vht_op_chan_width { ++ VHT_OP_CHAN_WIDTH_20_40 = 0, ++ VHT_OP_CHAN_WIDTH_80 = 1, ++ VHT_OP_CHAN_WIDTH_160 = 2, ++ VHT_OP_CHAN_WIDTH_80_80 = 3 ++} vht_op_chan_width_t; ++ ++/* Def for rx & tx basic mcs maps - ea ss num has 2 bits of info */ ++#define VHT_MCS_MAP_GET_SS_IDX(nss) (((nss)-1)*2) ++#define VHT_MCS_MAP_GET_MCS_PER_SS(nss, mcsMap) \ ++ (((mcsMap) >> VHT_MCS_MAP_GET_SS_IDX(nss)) & 0x3) ++#define VHT_MCS_MAP_SET_MCS_PER_SS(nss, numMcs, mcsMap) \ ++ ((mcsMap) |= (((numMcs) & 0x3) << VHT_MCS_MAP_GET_SS_IDX(nss))) ++ ++/* ************* WPA definitions. ************* */ ++#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ ++#define WPA_OUI_LEN 3 /* WPA OUI length */ ++#define WPA_OUI_TYPE 1 ++#define WPA_VERSION 1 /* WPA version */ ++#define WPA2_OUI "\x00\x0F\xAC" /* WPA2 OUI */ ++#define WPA2_OUI_LEN 3 /* WPA2 OUI length */ ++#define WPA2_VERSION 1 /* WPA2 version */ ++#define WPA2_VERSION_LEN 2 /* WAP2 version length */ ++ ++/* ************* WPS definitions. ************* */ ++#define WPS_OUI "\x00\x50\xF2" /* WPS OUI */ ++#define WPS_OUI_LEN 3 /* WPS OUI length */ ++#define WPS_OUI_TYPE 4 ++ ++/* ************* WFA definitions. ************* */ ++ ++#ifdef P2P_IE_OVRD ++#define WFA_OUI MAC_OUI ++#else ++#define WFA_OUI "\x50\x6F\x9A" /* WFA OUI */ ++#endif /* P2P_IE_OVRD */ ++#define WFA_OUI_LEN 3 /* WFA OUI length */ ++#ifdef P2P_IE_OVRD ++#define WFA_OUI_TYPE_P2P MAC_OUI_TYPE_P2P ++#else ++#define WFA_OUI_TYPE_P2P 9 ++#endif ++ ++#define WFA_OUI_TYPE_TPC 8 ++#ifdef WLTDLS ++#define WFA_OUI_TYPE_WFD 10 ++#endif /* WTDLS */ ++ ++/* RSN authenticated key managment suite */ ++#define RSN_AKM_NONE 0 /* None (IBSS) */ ++#define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */ ++#define RSN_AKM_PSK 2 /* Pre-shared Key */ ++#define RSN_AKM_FBT_1X 3 /* Fast Bss transition using 802.1X */ ++#define RSN_AKM_FBT_PSK 4 /* Fast Bss transition using Pre-shared Key */ ++#define RSN_AKM_MFP_1X 5 /* SHA256 key derivation, using 802.1X */ ++#define RSN_AKM_MFP_PSK 6 /* SHA256 key derivation, using Pre-shared Key */ ++#define RSN_AKM_TPK 7 /* TPK(TDLS Peer Key) handshake */ ++ ++/* Key related defines */ ++#define DOT11_MAX_DEFAULT_KEYS 4 /* number of default keys */ ++#define DOT11_MAX_KEY_SIZE 32 /* max size of any key */ ++#define DOT11_MAX_IV_SIZE 16 /* max size of any IV */ ++#define DOT11_EXT_IV_FLAG (1<<5) /* flag to indicate IV is > 4 bytes */ ++#define DOT11_WPA_KEY_RSC_LEN 8 /* WPA RSC key len */ ++ ++#define WEP1_KEY_SIZE 5 /* max size of any WEP key */ ++#define WEP1_KEY_HEX_SIZE 10 /* size of WEP key in hex. */ ++#define WEP128_KEY_SIZE 13 /* max size of any WEP key */ ++#define WEP128_KEY_HEX_SIZE 26 /* size of WEP key in hex. */ ++#define TKIP_MIC_SIZE 8 /* size of TKIP MIC */ ++#define TKIP_EOM_SIZE 7 /* max size of TKIP EOM */ ++#define TKIP_EOM_FLAG 0x5a /* TKIP EOM flag byte */ ++#define TKIP_KEY_SIZE 32 /* size of any TKIP key */ ++#define TKIP_MIC_AUTH_TX 16 /* offset to Authenticator MIC TX key */ ++#define TKIP_MIC_AUTH_RX 24 /* offset to Authenticator MIC RX key */ ++#define TKIP_MIC_SUP_RX TKIP_MIC_AUTH_TX /* offset to Supplicant MIC RX key */ ++#define TKIP_MIC_SUP_TX TKIP_MIC_AUTH_RX /* offset to Supplicant MIC TX key */ ++#define AES_KEY_SIZE 16 /* size of AES key */ ++#define AES_MIC_SIZE 8 /* size of AES MIC */ ++#define BIP_KEY_SIZE 16 /* size of BIP key */ ++ ++/* WCN */ ++#define WCN_OUI "\x00\x50\xf2" /* WCN OUI */ ++#define WCN_TYPE 4 /* WCN type */ ++#ifdef BCMWAPI_WPI ++#define SMS4_KEY_LEN 16 ++#define SMS4_WPI_CBC_MAC_LEN 16 ++#endif ++ ++ ++/* 802.11r protocol definitions */ ++ ++/* Mobility Domain IE */ ++BWL_PRE_PACKED_STRUCT struct dot11_mdid_ie { ++ uint8 id; ++ uint8 len; ++ uint16 mdid; /* Mobility Domain Id */ ++ uint8 cap; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_mdid_ie dot11_mdid_ie_t; ++ ++#define FBT_MDID_CAP_OVERDS 0x01 /* Fast Bss transition over the DS support */ ++#define FBT_MDID_CAP_RRP 0x02 /* Resource request protocol support */ ++ ++/* Fast Bss Transition IE */ ++BWL_PRE_PACKED_STRUCT struct dot11_ft_ie { ++ uint8 id; ++ uint8 len; ++ uint16 mic_control; /* Mic Control */ ++ uint8 mic[16]; ++ uint8 anonce[32]; ++ uint8 snonce[32]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ft_ie dot11_ft_ie_t; ++ ++#define TIE_TYPE_RESERVED 0 ++#define TIE_TYPE_REASSOC_DEADLINE 1 ++#define TIE_TYPE_KEY_LIEFTIME 2 ++#define TIE_TYPE_ASSOC_COMEBACK 3 ++BWL_PRE_PACKED_STRUCT struct dot11_timeout_ie { ++ uint8 id; ++ uint8 len; ++ uint8 type; /* timeout interval type */ ++ uint32 value; /* timeout interval value */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_timeout_ie dot11_timeout_ie_t; ++ ++ ++/* GTK ie */ ++BWL_PRE_PACKED_STRUCT struct dot11_gtk_ie { ++ uint8 id; ++ uint8 len; ++ uint16 key_info; ++ uint8 key_len; ++ uint8 rsc[8]; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_gtk_ie dot11_gtk_ie_t; ++ ++#define BSSID_INVALID "\x00\x00\x00\x00\x00\x00" ++#define BSSID_BROADCAST "\xFF\xFF\xFF\xFF\xFF\xFF" ++ ++ ++/* ************* WMM Parameter definitions. ************* */ ++#define WMM_OUI "\x00\x50\xF2" /* WNN OUI */ ++#define WMM_OUI_LEN 3 /* WMM OUI length */ ++#define WMM_OUI_TYPE 2 /* WMM OUT type */ ++#define WMM_VERSION 1 ++#define WMM_VERSION_LEN 1 ++ ++/* WMM OUI subtype */ ++#define WMM_OUI_SUBTYPE_PARAMETER 1 ++#define WMM_PARAMETER_IE_LEN 24 ++ ++/* Link Identifier Element */ ++BWL_PRE_PACKED_STRUCT struct link_id_ie { ++ uint8 id; ++ uint8 len; ++ struct ether_addr bssid; ++ struct ether_addr tdls_init_mac; ++ struct ether_addr tdls_resp_mac; ++} BWL_POST_PACKED_STRUCT; ++typedef struct link_id_ie link_id_ie_t; ++#define TDLS_LINK_ID_IE_LEN 18 ++ ++/* Link Wakeup Schedule Element */ ++BWL_PRE_PACKED_STRUCT struct wakeup_sch_ie { ++ uint8 id; ++ uint8 len; ++ uint32 offset; /* in ms between TSF0 and start of 1st Awake Window */ ++ uint32 interval; /* in ms bwtween the start of 2 Awake Windows */ ++ uint32 awake_win_slots; /* in backof slots, duration of Awake Window */ ++ uint32 max_wake_win; /* in ms, max duration of Awake Window */ ++ uint16 idle_cnt; /* number of consecutive Awake Windows */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wakeup_sch_ie wakeup_sch_ie_t; ++#define TDLS_WAKEUP_SCH_IE_LEN 18 ++ ++/* Channel Switch Timing Element */ ++BWL_PRE_PACKED_STRUCT struct channel_switch_timing_ie { ++ uint8 id; ++ uint8 len; ++ uint16 switch_time; /* in ms, time to switch channels */ ++ uint16 switch_timeout; /* in ms */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct channel_switch_timing_ie channel_switch_timing_ie_t; ++#define TDLS_CHANNEL_SWITCH_TIMING_IE_LEN 4 ++ ++/* PTI Control Element */ ++BWL_PRE_PACKED_STRUCT struct pti_control_ie { ++ uint8 id; ++ uint8 len; ++ uint8 tid; ++ uint16 seq_control; ++} BWL_POST_PACKED_STRUCT; ++typedef struct pti_control_ie pti_control_ie_t; ++#define TDLS_PTI_CONTROL_IE_LEN 3 ++ ++/* PU Buffer Status Element */ ++BWL_PRE_PACKED_STRUCT struct pu_buffer_status_ie { ++ uint8 id; ++ uint8 len; ++ uint8 status; ++} BWL_POST_PACKED_STRUCT; ++typedef struct pu_buffer_status_ie pu_buffer_status_ie_t; ++#define TDLS_PU_BUFFER_STATUS_IE_LEN 1 ++#define TDLS_PU_BUFFER_STATUS_AC_BK 1 ++#define TDLS_PU_BUFFER_STATUS_AC_BE 2 ++#define TDLS_PU_BUFFER_STATUS_AC_VI 4 ++#define TDLS_PU_BUFFER_STATUS_AC_VO 8 ++ ++#ifdef BCMWAPI_WAI ++#define WAPI_IE_MIN_LEN 20 /* WAPI IE min length */ ++#define WAPI_VERSION 1 /* WAPI version */ ++#define WAPI_VERSION_LEN 2 /* WAPI version length */ ++#define WAPI_OUI "\x00\x14\x72" /* WAPI OUI */ ++#define WAPI_OUI_LEN DOT11_OUI_LEN /* WAPI OUI length */ ++#endif /* BCMWAPI_WAI */ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _802_11_H_ */ +diff --git a/drivers/net/wireless/ap6210/include/proto/802.11_bta.h b/drivers/net/wireless/ap6210/include/proto/802.11_bta.h +new file mode 100755 +index 0000000..3ee5a74 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/proto/802.11_bta.h +@@ -0,0 +1,45 @@ ++/* ++ * BT-AMP (BlueTooth Alternate Mac and Phy) 802.11 PAL (Protocol Adaptation Layer) ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: 802.11_bta.h 294267 2011-11-04 23:41:52Z $ ++*/ ++ ++#ifndef _802_11_BTA_H_ ++#define _802_11_BTA_H_ ++ ++#define BT_SIG_SNAP_MPROT "\xAA\xAA\x03\x00\x19\x58" ++ ++/* BT-AMP 802.11 PAL Protocols */ ++#define BTA_PROT_L2CAP 1 ++#define BTA_PROT_ACTIVITY_REPORT 2 ++#define BTA_PROT_SECURITY 3 ++#define BTA_PROT_LINK_SUPERVISION_REQUEST 4 ++#define BTA_PROT_LINK_SUPERVISION_REPLY 5 ++ ++/* BT-AMP 802.11 PAL AMP_ASSOC Type IDs */ ++#define BTA_TYPE_ID_MAC_ADDRESS 1 ++#define BTA_TYPE_ID_PREFERRED_CHANNELS 2 ++#define BTA_TYPE_ID_CONNECTED_CHANNELS 3 ++#define BTA_TYPE_ID_CAPABILITIES 4 ++#define BTA_TYPE_ID_VERSION 5 ++#endif /* _802_11_bta_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/proto/802.11e.h b/drivers/net/wireless/ap6210/include/proto/802.11e.h +new file mode 100755 +index 0000000..f391e68 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/proto/802.11e.h +@@ -0,0 +1,131 @@ ++/* ++ * 802.11e protocol header file ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: 802.11e.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _802_11e_H_ ++#define _802_11e_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* WME Traffic Specification (TSPEC) element */ ++#define WME_TSPEC_HDR_LEN 2 /* WME TSPEC header length */ ++#define WME_TSPEC_BODY_OFF 2 /* WME TSPEC body offset */ ++ ++#define WME_CATEGORY_CODE_OFFSET 0 /* WME Category code offset */ ++#define WME_ACTION_CODE_OFFSET 1 /* WME Action code offset */ ++#define WME_TOKEN_CODE_OFFSET 2 /* WME Token code offset */ ++#define WME_STATUS_CODE_OFFSET 3 /* WME Status code offset */ ++ ++BWL_PRE_PACKED_STRUCT struct tsinfo { ++ uint8 octets[3]; ++} BWL_POST_PACKED_STRUCT; ++ ++typedef struct tsinfo tsinfo_t; ++ ++/* 802.11e TSPEC IE */ ++typedef BWL_PRE_PACKED_STRUCT struct tspec { ++ uint8 oui[DOT11_OUI_LEN]; /* WME_OUI */ ++ uint8 type; /* WME_TYPE */ ++ uint8 subtype; /* WME_SUBTYPE_TSPEC */ ++ uint8 version; /* WME_VERSION */ ++ tsinfo_t tsinfo; /* TS Info bit field */ ++ uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */ ++ uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */ ++ uint32 min_srv_interval; /* Minimum Service Interval (us) */ ++ uint32 max_srv_interval; /* Maximum Service Interval (us) */ ++ uint32 inactivity_interval; /* Inactivity Interval (us) */ ++ uint32 suspension_interval; /* Suspension Interval (us) */ ++ uint32 srv_start_time; /* Service Start Time (us) */ ++ uint32 min_data_rate; /* Minimum Data Rate (bps) */ ++ uint32 mean_data_rate; /* Mean Data Rate (bps) */ ++ uint32 peak_data_rate; /* Peak Data Rate (bps) */ ++ uint32 max_burst_size; /* Maximum Burst Size (bytes) */ ++ uint32 delay_bound; /* Delay Bound (us) */ ++ uint32 min_phy_rate; /* Minimum PHY Rate (bps) */ ++ uint16 surplus_bw; /* Surplus Bandwidth Allowance (range 1.0-8.0) */ ++ uint16 medium_time; /* Medium Time (32 us/s periods) */ ++} BWL_POST_PACKED_STRUCT tspec_t; ++ ++#define WME_TSPEC_LEN (sizeof(tspec_t)) /* not including 2-bytes of header */ ++ ++/* ts_info */ ++/* 802.1D priority is duplicated - bits 13-11 AND bits 3-1 */ ++#define TS_INFO_TID_SHIFT 1 /* TS info. TID shift */ ++#define TS_INFO_TID_MASK (0xf << TS_INFO_TID_SHIFT) /* TS info. TID mask */ ++#define TS_INFO_CONTENTION_SHIFT 7 /* TS info. contention shift */ ++#define TS_INFO_CONTENTION_MASK (0x1 << TS_INFO_CONTENTION_SHIFT) /* TS info. contention mask */ ++#define TS_INFO_DIRECTION_SHIFT 5 /* TS info. direction shift */ ++#define TS_INFO_DIRECTION_MASK (0x3 << TS_INFO_DIRECTION_SHIFT) /* TS info. direction mask */ ++#define TS_INFO_PSB_SHIFT 2 /* TS info. PSB bit Shift */ ++#define TS_INFO_PSB_MASK (1 << TS_INFO_PSB_SHIFT) /* TS info. PSB mask */ ++#define TS_INFO_UPLINK (0 << TS_INFO_DIRECTION_SHIFT) /* TS info. uplink */ ++#define TS_INFO_DOWNLINK (1 << TS_INFO_DIRECTION_SHIFT) /* TS info. downlink */ ++#define TS_INFO_BIDIRECTIONAL (3 << TS_INFO_DIRECTION_SHIFT) /* TS info. bidirectional */ ++#define TS_INFO_USER_PRIO_SHIFT 3 /* TS info. user priority shift */ ++/* TS info. user priority mask */ ++#define TS_INFO_USER_PRIO_MASK (0x7 << TS_INFO_USER_PRIO_SHIFT) ++ ++/* Macro to get/set bit(s) field in TSINFO */ ++#define WLC_CAC_GET_TID(pt) ((((pt).octets[0]) & TS_INFO_TID_MASK) >> TS_INFO_TID_SHIFT) ++#define WLC_CAC_GET_DIR(pt) ((((pt).octets[0]) & \ ++ TS_INFO_DIRECTION_MASK) >> TS_INFO_DIRECTION_SHIFT) ++#define WLC_CAC_GET_PSB(pt) ((((pt).octets[1]) & TS_INFO_PSB_MASK) >> TS_INFO_PSB_SHIFT) ++#define WLC_CAC_GET_USER_PRIO(pt) ((((pt).octets[1]) & \ ++ TS_INFO_USER_PRIO_MASK) >> TS_INFO_USER_PRIO_SHIFT) ++ ++#define WLC_CAC_SET_TID(pt, id) ((((pt).octets[0]) & (~TS_INFO_TID_MASK)) | \ ++ ((id) << TS_INFO_TID_SHIFT)) ++#define WLC_CAC_SET_USER_PRIO(pt, prio) ((((pt).octets[0]) & (~TS_INFO_USER_PRIO_MASK)) | \ ++ ((prio) << TS_INFO_USER_PRIO_SHIFT)) ++ ++/* 802.11e QBSS Load IE */ ++#define QBSS_LOAD_IE_LEN 5 /* QBSS Load IE length */ ++#define QBSS_LOAD_AAC_OFF 3 /* AAC offset in IE */ ++ ++#define CAC_ADDTS_RESP_TIMEOUT 300 /* default ADDTS response timeout in ms */ ++ ++/* 802.11e ADDTS status code */ ++#define DOT11E_STATUS_ADMISSION_ACCEPTED 0 /* TSPEC Admission accepted status */ ++#define DOT11E_STATUS_ADDTS_INVALID_PARAM 1 /* TSPEC invalid parameter status */ ++#define DOT11E_STATUS_ADDTS_REFUSED_NSBW 3 /* ADDTS refused (non-sufficient BW) */ ++#define DOT11E_STATUS_ADDTS_REFUSED_AWHILE 47 /* ADDTS refused but could retry later */ ++ ++/* 802.11e DELTS status code */ ++#define DOT11E_STATUS_QSTA_LEAVE_QBSS 36 /* STA leave QBSS */ ++#define DOT11E_STATUS_END_TS 37 /* END TS */ ++#define DOT11E_STATUS_UNKNOWN_TS 38 /* UNKNOWN TS */ ++#define DOT11E_STATUS_QSTA_REQ_TIMEOUT 39 /* STA ADDTS request timeout */ ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _802_11e_CAC_H_ */ +diff --git a/drivers/net/wireless/ap6210/include/proto/802.1d.h b/drivers/net/wireless/ap6210/include/proto/802.1d.h +new file mode 100755 +index 0000000..f11cc6c +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/proto/802.1d.h +@@ -0,0 +1,50 @@ ++/* ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * Fundamental types and constants relating to 802.1D ++ * ++ * $Id: 802.1d.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _802_1_D_ ++#define _802_1_D_ ++ ++/* 802.1D priority defines */ ++#define PRIO_8021D_NONE 2 /* None = - */ ++#define PRIO_8021D_BK 1 /* BK - Background */ ++#define PRIO_8021D_BE 0 /* BE - Best-effort */ ++#define PRIO_8021D_EE 3 /* EE - Excellent-effort */ ++#define PRIO_8021D_CL 4 /* CL - Controlled Load */ ++#define PRIO_8021D_VI 5 /* Vi - Video */ ++#define PRIO_8021D_VO 6 /* Vo - Voice */ ++#define PRIO_8021D_NC 7 /* NC - Network Control */ ++#define MAXPRIO 7 /* 0-7 */ ++#define NUMPRIO (MAXPRIO + 1) ++ ++#define ALLPRIO -1 /* All prioirty */ ++ ++/* Converts prio to precedence since the numerical value of ++ * PRIO_8021D_BE and PRIO_8021D_NONE are swapped. ++ */ ++#define PRIO2PREC(prio) \ ++ (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio)) ++ ++#endif /* _802_1_D__ */ +diff --git a/drivers/net/wireless/ap6210/include/proto/bcmeth.h b/drivers/net/wireless/ap6210/include/proto/bcmeth.h +new file mode 100755 +index 0000000..91ae75c +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/proto/bcmeth.h +@@ -0,0 +1,112 @@ ++/* ++ * Broadcom Ethernettype protocol definitions ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmeth.h 294352 2011-11-06 19:23:00Z $ ++ */ ++ ++/* ++ * Broadcom Ethernet protocol defines ++ */ ++ ++#ifndef _BCMETH_H_ ++#define _BCMETH_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++/* ETHER_TYPE_BRCM is defined in ethernet.h */ ++ ++/* ++ * Following the 2byte BRCM ether_type is a 16bit BRCM subtype field ++ * in one of two formats: (only subtypes 32768-65535 are in use now) ++ * ++ * subtypes 0-32767: ++ * 8 bit subtype (0-127) ++ * 8 bit length in bytes (0-255) ++ * ++ * subtypes 32768-65535: ++ * 16 bit big-endian subtype ++ * 16 bit big-endian length in bytes (0-65535) ++ * ++ * length is the number of additional bytes beyond the 4 or 6 byte header ++ * ++ * Reserved values: ++ * 0 reserved ++ * 5-15 reserved for iLine protocol assignments ++ * 17-126 reserved, assignable ++ * 127 reserved ++ * 32768 reserved ++ * 32769-65534 reserved, assignable ++ * 65535 reserved ++ */ ++ ++/* ++ * While adding the subtypes and their specific processing code make sure ++ * bcmeth_bcm_hdr_t is the first data structure in the user specific data structure definition ++ */ ++ ++#define BCMILCP_SUBTYPE_RATE 1 ++#define BCMILCP_SUBTYPE_LINK 2 ++#define BCMILCP_SUBTYPE_CSA 3 ++#define BCMILCP_SUBTYPE_LARQ 4 ++#define BCMILCP_SUBTYPE_VENDOR 5 ++#define BCMILCP_SUBTYPE_FLH 17 ++ ++#define BCMILCP_SUBTYPE_VENDOR_LONG 32769 ++#define BCMILCP_SUBTYPE_CERT 32770 ++#define BCMILCP_SUBTYPE_SES 32771 ++ ++ ++#define BCMILCP_BCM_SUBTYPE_RESERVED 0 ++#define BCMILCP_BCM_SUBTYPE_EVENT 1 ++#define BCMILCP_BCM_SUBTYPE_SES 2 ++/* ++ * The EAPOL type is not used anymore. Instead EAPOL messages are now embedded ++ * within BCMILCP_BCM_SUBTYPE_EVENT type messages ++ */ ++/* #define BCMILCP_BCM_SUBTYPE_EAPOL 3 */ ++#define BCMILCP_BCM_SUBTYPE_DPT 4 ++ ++#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8 ++#define BCMILCP_BCM_SUBTYPEHDR_VERSION 0 ++ ++/* These fields are stored in network order */ ++typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr ++{ ++ uint16 subtype; /* Vendor specific..32769 */ ++ uint16 length; ++ uint8 version; /* Version is 0 */ ++ uint8 oui[3]; /* Broadcom OUI */ ++ /* user specific Data */ ++ uint16 usr_subtype; ++} BWL_POST_PACKED_STRUCT bcmeth_hdr_t; ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _BCMETH_H_ */ +diff --git a/drivers/net/wireless/ap6210/include/proto/bcmevent.h b/drivers/net/wireless/ap6210/include/proto/bcmevent.h +new file mode 100755 +index 0000000..c439707 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/proto/bcmevent.h +@@ -0,0 +1,368 @@ ++/* ++ * Broadcom Event protocol definitions ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * Dependencies: proto/bcmeth.h ++ * ++ * $Id: bcmevent.h 374275 2012-12-12 11:44:18Z $ ++ * ++ */ ++ ++/* ++ * Broadcom Ethernet Events protocol defines ++ * ++ */ ++ ++#ifndef _BCMEVENT_H_ ++#define _BCMEVENT_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#define BCM_EVENT_MSG_VERSION 2 /* wl_event_msg_t struct version */ ++#define BCM_MSG_IFNAME_MAX 16 /* max length of interface name */ ++ ++/* flags */ ++#define WLC_EVENT_MSG_LINK 0x01 /* link is up */ ++#define WLC_EVENT_MSG_FLUSHTXQ 0x02 /* flush tx queue on MIC error */ ++#define WLC_EVENT_MSG_GROUP 0x04 /* group MIC error */ ++#define WLC_EVENT_MSG_UNKBSS 0x08 /* unknown source bsscfg */ ++#define WLC_EVENT_MSG_UNKIF 0x10 /* unknown source OS i/f */ ++ ++/* these fields are stored in network order */ ++ ++/* version 1 */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint16 version; ++ uint16 flags; /* see flags below */ ++ uint32 event_type; /* Message (see below) */ ++ uint32 status; /* Status code (see below) */ ++ uint32 reason; /* Reason code (if applicable) */ ++ uint32 auth_type; /* WLC_E_AUTH */ ++ uint32 datalen; /* data buf */ ++ struct ether_addr addr; /* Station address (if applicable) */ ++ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */ ++} BWL_POST_PACKED_STRUCT wl_event_msg_v1_t; ++ ++/* the current version */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint16 version; ++ uint16 flags; /* see flags below */ ++ uint32 event_type; /* Message (see below) */ ++ uint32 status; /* Status code (see below) */ ++ uint32 reason; /* Reason code (if applicable) */ ++ uint32 auth_type; /* WLC_E_AUTH */ ++ uint32 datalen; /* data buf */ ++ struct ether_addr addr; /* Station address (if applicable) */ ++ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */ ++ uint8 ifidx; /* destination OS i/f index */ ++ uint8 bsscfgidx; /* source bsscfg index */ ++} BWL_POST_PACKED_STRUCT wl_event_msg_t; ++ ++/* used by driver msgs */ ++typedef BWL_PRE_PACKED_STRUCT struct bcm_event { ++ struct ether_header eth; ++ bcmeth_hdr_t bcm_hdr; ++ wl_event_msg_t event; ++ /* data portion follows */ ++} BWL_POST_PACKED_STRUCT bcm_event_t; ++ ++#define BCM_MSG_LEN (sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header)) ++ ++/* Event messages */ ++#define WLC_E_SET_SSID 0 /* indicates status of set SSID */ ++#define WLC_E_JOIN 1 /* differentiates join IBSS from found (WLC_E_START) IBSS */ ++#define WLC_E_START 2 /* STA founded an IBSS or AP started a BSS */ ++#define WLC_E_AUTH 3 /* 802.11 AUTH request */ ++#define WLC_E_AUTH_IND 4 /* 802.11 AUTH indication */ ++#define WLC_E_DEAUTH 5 /* 802.11 DEAUTH request */ ++#define WLC_E_DEAUTH_IND 6 /* 802.11 DEAUTH indication */ ++#define WLC_E_ASSOC 7 /* 802.11 ASSOC request */ ++#define WLC_E_ASSOC_IND 8 /* 802.11 ASSOC indication */ ++#define WLC_E_REASSOC 9 /* 802.11 REASSOC request */ ++#define WLC_E_REASSOC_IND 10 /* 802.11 REASSOC indication */ ++#define WLC_E_DISASSOC 11 /* 802.11 DISASSOC request */ ++#define WLC_E_DISASSOC_IND 12 /* 802.11 DISASSOC indication */ ++#define WLC_E_QUIET_START 13 /* 802.11h Quiet period started */ ++#define WLC_E_QUIET_END 14 /* 802.11h Quiet period ended */ ++#define WLC_E_BEACON_RX 15 /* BEACONS received/lost indication */ ++#define WLC_E_LINK 16 /* generic link indication */ ++#define WLC_E_MIC_ERROR 17 /* TKIP MIC error occurred */ ++#define WLC_E_NDIS_LINK 18 /* NDIS style link indication */ ++#define WLC_E_ROAM 19 /* roam attempt occurred: indicate status & reason */ ++#define WLC_E_TXFAIL 20 /* change in dot11FailedCount (txfail) */ ++#define WLC_E_PMKID_CACHE 21 /* WPA2 pmkid cache indication */ ++#define WLC_E_RETROGRADE_TSF 22 /* current AP's TSF value went backward */ ++#define WLC_E_PRUNE 23 /* AP was pruned from join list for reason */ ++#define WLC_E_AUTOAUTH 24 /* report AutoAuth table entry match for join attempt */ ++#define WLC_E_EAPOL_MSG 25 /* Event encapsulating an EAPOL message */ ++#define WLC_E_SCAN_COMPLETE 26 /* Scan results are ready or scan was aborted */ ++#define WLC_E_ADDTS_IND 27 /* indicate to host addts fail/success */ ++#define WLC_E_DELTS_IND 28 /* indicate to host delts fail/success */ ++#define WLC_E_BCNSENT_IND 29 /* indicate to host of beacon transmit */ ++#define WLC_E_BCNRX_MSG 30 /* Send the received beacon up to the host */ ++#define WLC_E_BCNLOST_MSG 31 /* indicate to host loss of beacon */ ++#define WLC_E_ROAM_PREP 32 /* before attempting to roam */ ++#define WLC_E_PFN_NET_FOUND 33 /* PFN network found event */ ++#define WLC_E_PFN_NET_LOST 34 /* PFN network lost event */ ++#define WLC_E_RESET_COMPLETE 35 ++#define WLC_E_JOIN_START 36 ++#define WLC_E_ROAM_START 37 ++#define WLC_E_ASSOC_START 38 ++#define WLC_E_IBSS_ASSOC 39 ++#define WLC_E_RADIO 40 ++#define WLC_E_PSM_WATCHDOG 41 /* PSM microcode watchdog fired */ ++#define WLC_E_PROBREQ_MSG 44 /* probe request received */ ++#define WLC_E_SCAN_CONFIRM_IND 45 ++#define WLC_E_PSK_SUP 46 /* WPA Handshake fail */ ++#define WLC_E_COUNTRY_CODE_CHANGED 47 ++#define WLC_E_EXCEEDED_MEDIUM_TIME 48 /* WMMAC excedded medium time */ ++#define WLC_E_ICV_ERROR 49 /* WEP ICV error occurred */ ++#define WLC_E_UNICAST_DECODE_ERROR 50 /* Unsupported unicast encrypted frame */ ++#define WLC_E_MULTICAST_DECODE_ERROR 51 /* Unsupported multicast encrypted frame */ ++#define WLC_E_TRACE 52 ++#ifdef WLBTAMP ++#define WLC_E_BTA_HCI_EVENT 53 /* BT-AMP HCI event */ ++#endif ++#define WLC_E_IF 54 /* I/F change (for dongle host notification) */ ++#define WLC_E_P2P_DISC_LISTEN_COMPLETE 55 /* listen state expires */ ++#define WLC_E_RSSI 56 /* indicate RSSI change based on configured levels */ ++#define WLC_E_PFN_SCAN_COMPLETE 57 /* PFN completed scan of network list */ ++#define WLC_E_EXTLOG_MSG 58 ++#define WLC_E_ACTION_FRAME 59 /* Action frame Rx */ ++#define WLC_E_ACTION_FRAME_COMPLETE 60 /* Action frame Tx complete */ ++#define WLC_E_PRE_ASSOC_IND 61 /* assoc request received */ ++#define WLC_E_PRE_REASSOC_IND 62 /* re-assoc request received */ ++#define WLC_E_CHANNEL_ADOPTED 63 ++#define WLC_E_AP_STARTED 64 /* AP started */ ++#define WLC_E_DFS_AP_STOP 65 /* AP stopped due to DFS */ ++#define WLC_E_DFS_AP_RESUME 66 /* AP resumed due to DFS */ ++#define WLC_E_WAI_STA_EVENT 67 /* WAI stations event */ ++#define WLC_E_WAI_MSG 68 /* event encapsulating an WAI message */ ++#define WLC_E_ESCAN_RESULT 69 /* escan result event */ ++#define WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70 /* action frame off channel complete */ ++#define WLC_E_PROBRESP_MSG 71 /* probe response received */ ++#define WLC_E_P2P_PROBREQ_MSG 72 /* P2P Probe request received */ ++#define WLC_E_DCS_REQUEST 73 ++ ++#define WLC_E_FIFO_CREDIT_MAP 74 /* credits for D11 FIFOs. [AC0,AC1,AC2,AC3,BC_MC,ATIM] */ ++ ++#define WLC_E_ACTION_FRAME_RX 75 /* Received action frame event WITH ++ * wl_event_rx_frame_data_t header ++ */ ++#define WLC_E_WAKE_EVENT 76 /* Wake Event timer fired, used for wake WLAN test mode */ ++#define WLC_E_RM_COMPLETE 77 /* Radio measurement complete */ ++#define WLC_E_HTSFSYNC 78 /* Synchronize TSF with the host */ ++#define WLC_E_OVERLAY_REQ 79 /* request an overlay IOCTL/iovar from the host */ ++#define WLC_E_CSA_COMPLETE_IND 80 /* 802.11 CHANNEL SWITCH ACTION completed */ ++#define WLC_E_EXCESS_PM_WAKE_EVENT 81 /* excess PM Wake Event to inform host */ ++#define WLC_E_PFN_SCAN_NONE 82 /* no PFN networks around */ ++#define WLC_E_PFN_SCAN_ALLGONE 83 /* last found PFN network gets lost */ ++#define WLC_E_GTK_PLUMBED 84 ++#define WLC_E_ASSOC_IND_NDIS 85 /* 802.11 ASSOC indication for NDIS only */ ++#define WLC_E_REASSOC_IND_NDIS 86 /* 802.11 REASSOC indication for NDIS only */ ++#define WLC_E_ASSOC_REQ_IE 87 ++#define WLC_E_ASSOC_RESP_IE 88 ++#define WLC_E_ASSOC_RECREATED 89 /* association recreated on resume */ ++#define WLC_E_ACTION_FRAME_RX_NDIS 90 /* rx action frame event for NDIS only */ ++#define WLC_E_AUTH_REQ 91 /* authentication request received */ ++#define WLC_E_TDLS_PEER_EVENT 92 /* discovered peer, connected or disconnected peer */ ++#define WLC_E_SPEEDY_RECREATE_FAIL 93 /* fast assoc recreation failed */ ++#define WLC_E_SERVICE_FOUND 102 /* desired service found */ ++#define WLC_E_GAS_FRAGMENT_RX 103 /* GAS fragment received */ ++#define WLC_E_GAS_COMPLETE 104 /* GAS sessions all complete */ ++#define WLC_E_P2PO_ADD_DEVICE 105 /* New device found by p2p offload */ ++#define WLC_E_P2PO_DEL_DEVICE 106 /* device has been removed by p2p offload */ ++#define WLC_E_LAST 107 /* highest val + 1 for range checking */ ++ ++ ++/* Table of event name strings for UIs and debugging dumps */ ++typedef struct { ++ uint event; ++ const char *name; ++} bcmevent_name_t; ++ ++extern const bcmevent_name_t bcmevent_names[]; ++extern const int bcmevent_names_size; ++ ++/* Event status codes */ ++#define WLC_E_STATUS_SUCCESS 0 /* operation was successful */ ++#define WLC_E_STATUS_FAIL 1 /* operation failed */ ++#define WLC_E_STATUS_TIMEOUT 2 /* operation timed out */ ++#define WLC_E_STATUS_NO_NETWORKS 3 /* failed due to no matching network found */ ++#define WLC_E_STATUS_ABORT 4 /* operation was aborted */ ++#define WLC_E_STATUS_NO_ACK 5 /* protocol failure: packet not ack'd */ ++#define WLC_E_STATUS_UNSOLICITED 6 /* AUTH or ASSOC packet was unsolicited */ ++#define WLC_E_STATUS_ATTEMPT 7 /* attempt to assoc to an auto auth configuration */ ++#define WLC_E_STATUS_PARTIAL 8 /* scan results are incomplete */ ++#define WLC_E_STATUS_NEWSCAN 9 /* scan aborted by another scan */ ++#define WLC_E_STATUS_NEWASSOC 10 /* scan aborted due to assoc in progress */ ++#define WLC_E_STATUS_11HQUIET 11 /* 802.11h quiet period started */ ++#define WLC_E_STATUS_SUPPRESS 12 /* user disabled scanning (WLC_SET_SCANSUPPRESS) */ ++#define WLC_E_STATUS_NOCHANS 13 /* no allowable channels to scan */ ++#define WLC_E_STATUS_CS_ABORT 15 /* abort channel select */ ++#define WLC_E_STATUS_ERROR 16 /* request failed due to error */ ++ ++/* roam reason codes */ ++#define WLC_E_REASON_INITIAL_ASSOC 0 /* initial assoc */ ++#define WLC_E_REASON_LOW_RSSI 1 /* roamed due to low RSSI */ ++#define WLC_E_REASON_DEAUTH 2 /* roamed due to DEAUTH indication */ ++#define WLC_E_REASON_DISASSOC 3 /* roamed due to DISASSOC indication */ ++#define WLC_E_REASON_BCNS_LOST 4 /* roamed due to lost beacons */ ++#define WLC_E_REASON_MINTXRATE 9 /* roamed because at mintxrate for too long */ ++#define WLC_E_REASON_TXFAIL 10 /* We can hear AP, but AP can't hear us */ ++ ++/* Roam codes used primarily by CCX */ ++#define WLC_E_REASON_FAST_ROAM_FAILED 5 /* roamed due to fast roam failure */ ++#define WLC_E_REASON_DIRECTED_ROAM 6 /* roamed due to request by AP */ ++#define WLC_E_REASON_TSPEC_REJECTED 7 /* roamed due to TSPEC rejection */ ++#define WLC_E_REASON_BETTER_AP 8 /* roamed due to finding better AP */ ++ ++ ++#define WLC_E_REASON_REQUESTED_ROAM 11 /* roamed due to BSS Mgmt Transition request by AP */ ++ ++/* prune reason codes */ ++#define WLC_E_PRUNE_ENCR_MISMATCH 1 /* encryption mismatch */ ++#define WLC_E_PRUNE_BCAST_BSSID 2 /* AP uses a broadcast BSSID */ ++#define WLC_E_PRUNE_MAC_DENY 3 /* STA's MAC addr is in AP's MAC deny list */ ++#define WLC_E_PRUNE_MAC_NA 4 /* STA's MAC addr is not in AP's MAC allow list */ ++#define WLC_E_PRUNE_REG_PASSV 5 /* AP not allowed due to regulatory restriction */ ++#define WLC_E_PRUNE_SPCT_MGMT 6 /* AP does not support STA locale spectrum mgmt */ ++#define WLC_E_PRUNE_RADAR 7 /* AP is on a radar channel of STA locale */ ++#define WLC_E_RSN_MISMATCH 8 /* STA does not support AP's RSN */ ++#define WLC_E_PRUNE_NO_COMMON_RATES 9 /* No rates in common with AP */ ++#define WLC_E_PRUNE_BASIC_RATES 10 /* STA does not support all basic rates of BSS */ ++#define WLC_E_PRUNE_CIPHER_NA 12 /* BSS's cipher not supported */ ++#define WLC_E_PRUNE_KNOWN_STA 13 /* AP is already known to us as a STA */ ++#define WLC_E_PRUNE_WDS_PEER 15 /* AP is already known to us as a WDS peer */ ++#define WLC_E_PRUNE_QBSS_LOAD 16 /* QBSS LOAD - AAC is too low */ ++#define WLC_E_PRUNE_HOME_AP 17 /* prune home AP */ ++ ++/* WPA failure reason codes carried in the WLC_E_PSK_SUP event */ ++#define WLC_E_SUP_OTHER 0 /* Other reason */ ++#define WLC_E_SUP_DECRYPT_KEY_DATA 1 /* Decryption of key data failed */ ++#define WLC_E_SUP_BAD_UCAST_WEP128 2 /* Illegal use of ucast WEP128 */ ++#define WLC_E_SUP_BAD_UCAST_WEP40 3 /* Illegal use of ucast WEP40 */ ++#define WLC_E_SUP_UNSUP_KEY_LEN 4 /* Unsupported key length */ ++#define WLC_E_SUP_PW_KEY_CIPHER 5 /* Unicast cipher mismatch in pairwise key */ ++#define WLC_E_SUP_MSG3_TOO_MANY_IE 6 /* WPA IE contains > 1 RSN IE in key msg 3 */ ++#define WLC_E_SUP_MSG3_IE_MISMATCH 7 /* WPA IE mismatch in key message 3 */ ++#define WLC_E_SUP_NO_INSTALL_FLAG 8 /* INSTALL flag unset in 4-way msg */ ++#define WLC_E_SUP_MSG3_NO_GTK 9 /* encapsulated GTK missing from msg 3 */ ++#define WLC_E_SUP_GRP_KEY_CIPHER 10 /* Multicast cipher mismatch in group key */ ++#define WLC_E_SUP_GRP_MSG1_NO_GTK 11 /* encapsulated GTK missing from group msg 1 */ ++#define WLC_E_SUP_GTK_DECRYPT_FAIL 12 /* GTK decrypt failure */ ++#define WLC_E_SUP_SEND_FAIL 13 /* message send failure */ ++#define WLC_E_SUP_DEAUTH 14 /* received FC_DEAUTH */ ++#define WLC_E_SUP_WPA_PSK_TMO 15 /* WPA PSK 4-way handshake timeout */ ++ ++/* Event data for events that include frames received over the air */ ++/* WLC_E_PROBRESP_MSG ++ * WLC_E_P2P_PROBREQ_MSG ++ * WLC_E_ACTION_FRAME_RX ++ */ ++typedef BWL_PRE_PACKED_STRUCT struct wl_event_rx_frame_data { ++ uint16 version; ++ uint16 channel; /* Matches chanspec_t format from bcmwifi_channels.h */ ++ int32 rssi; ++ uint32 mactime; ++ uint32 rate; ++} BWL_POST_PACKED_STRUCT wl_event_rx_frame_data_t; ++ ++#define BCM_RX_FRAME_DATA_VERSION 1 ++ ++/* WLC_E_IF event data */ ++typedef struct wl_event_data_if { ++ uint8 ifidx; /* RTE virtual device index (for dongle) */ ++ uint8 opcode; /* see I/F opcode */ ++ uint8 reserved; ++ uint8 bssidx; /* bsscfg index */ ++ uint8 role; /* see I/F role */ ++} wl_event_data_if_t; ++ ++/* opcode in WLC_E_IF event */ ++#define WLC_E_IF_ADD 1 /* bsscfg add */ ++#define WLC_E_IF_DEL 2 /* bsscfg delete */ ++#define WLC_E_IF_CHANGE 3 /* bsscfg role change */ ++ ++/* I/F role code in WLC_E_IF event */ ++#define WLC_E_IF_ROLE_STA 0 /* Infra STA */ ++#define WLC_E_IF_ROLE_AP 1 /* Access Point */ ++#define WLC_E_IF_ROLE_WDS 2 /* WDS link */ ++#define WLC_E_IF_ROLE_P2P_GO 3 /* P2P Group Owner */ ++#define WLC_E_IF_ROLE_P2P_CLIENT 4 /* P2P Client */ ++#ifdef WLBTAMP ++#define WLC_E_IF_ROLE_BTA_CREATOR 5 /* BT-AMP Creator */ ++#define WLC_E_IF_ROLE_BTA_ACCEPTOR 6 /* BT-AMP Acceptor */ ++#endif ++ ++/* Reason codes for LINK */ ++#define WLC_E_LINK_BCN_LOSS 1 /* Link down because of beacon loss */ ++#define WLC_E_LINK_DISASSOC 2 /* Link down because of disassoc */ ++#define WLC_E_LINK_ASSOC_REC 3 /* Link down because assoc recreate failed */ ++#define WLC_E_LINK_BSSCFG_DIS 4 /* Link down due to bsscfg down */ ++ ++/* reason codes for WLC_E_OVERLAY_REQ event */ ++#define WLC_E_OVL_DOWNLOAD 0 /* overlay download request */ ++#define WLC_E_OVL_UPDATE_IND 1 /* device indication of host overlay update */ ++ ++/* reason codes for WLC_E_TDLS_PEER_EVENT event */ ++#define WLC_E_TDLS_PEER_DISCOVERED 0 /* peer is ready to establish TDLS */ ++#define WLC_E_TDLS_PEER_CONNECTED 1 ++#define WLC_E_TDLS_PEER_DISCONNECTED 2 ++ ++/* GAS event data */ ++typedef BWL_PRE_PACKED_STRUCT struct wl_event_gas { ++ uint16 channel; /* channel of GAS protocol */ ++ uint8 dialog_token; /* GAS dialog token */ ++ uint8 fragment_id; /* fragment id */ ++ uint16 status_code; /* status code on GAS completion */ ++ uint16 data_len; /* length of data to follow */ ++ uint8 data[1]; /* variable length specified by data_len */ ++} BWL_POST_PACKED_STRUCT wl_event_gas_t; ++ ++/* service discovery TLV */ ++typedef BWL_PRE_PACKED_STRUCT struct wl_sd_tlv { ++ uint16 length; /* length of response_data */ ++ uint8 protocol; /* service protocol type */ ++ uint8 transaction_id; /* service transaction id */ ++ uint8 status_code; /* status code */ ++ uint8 data[1]; /* response data */ ++} BWL_POST_PACKED_STRUCT wl_sd_tlv_t; ++ ++/* service discovery event data */ ++typedef BWL_PRE_PACKED_STRUCT struct wl_event_sd { ++ uint16 channel; /* channel */ ++ uint8 count; /* number of tlvs */ ++ wl_sd_tlv_t tlv[1]; /* service discovery TLV */ ++} BWL_POST_PACKED_STRUCT wl_event_sd_t; ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _BCMEVENT_H_ */ +diff --git a/drivers/net/wireless/ap6210/include/proto/bcmip.h b/drivers/net/wireless/ap6210/include/proto/bcmip.h +new file mode 100755 +index 0000000..52cd71d +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/proto/bcmip.h +@@ -0,0 +1,210 @@ ++/* ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * Fundamental constants relating to IP Protocol ++ * ++ * $Id: bcmip.h 290206 2011-10-17 19:13:51Z $ ++ */ ++ ++#ifndef _bcmip_h_ ++#define _bcmip_h_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* IPV4 and IPV6 common */ ++#define IP_VER_OFFSET 0x0 /* offset to version field */ ++#define IP_VER_MASK 0xf0 /* version mask */ ++#define IP_VER_SHIFT 4 /* version shift */ ++#define IP_VER_4 4 /* version number for IPV4 */ ++#define IP_VER_6 6 /* version number for IPV6 */ ++ ++#define IP_VER(ip_body) \ ++ ((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT) ++ ++#define IP_PROT_ICMP 0x1 /* ICMP protocol */ ++#define IP_PROT_IGMP 0x2 /* IGMP protocol */ ++#define IP_PROT_TCP 0x6 /* TCP protocol */ ++#define IP_PROT_UDP 0x11 /* UDP protocol type */ ++#define IP_PROT_ICMP6 0x3a /* ICMPv6 protocol type */ ++ ++/* IPV4 field offsets */ ++#define IPV4_VER_HL_OFFSET 0 /* version and ihl byte offset */ ++#define IPV4_TOS_OFFSET 1 /* type of service offset */ ++#define IPV4_PKTLEN_OFFSET 2 /* packet length offset */ ++#define IPV4_PKTFLAG_OFFSET 6 /* more-frag,dont-frag flag offset */ ++#define IPV4_PROT_OFFSET 9 /* protocol type offset */ ++#define IPV4_CHKSUM_OFFSET 10 /* IP header checksum offset */ ++#define IPV4_SRC_IP_OFFSET 12 /* src IP addr offset */ ++#define IPV4_DEST_IP_OFFSET 16 /* dest IP addr offset */ ++#define IPV4_OPTIONS_OFFSET 20 /* IP options offset */ ++ ++/* IPV4 field decodes */ ++#define IPV4_VER_MASK 0xf0 /* IPV4 version mask */ ++#define IPV4_VER_SHIFT 4 /* IPV4 version shift */ ++ ++#define IPV4_HLEN_MASK 0x0f /* IPV4 header length mask */ ++#define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK)) ++ ++#define IPV4_ADDR_LEN 4 /* IPV4 address length */ ++ ++#define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \ ++ ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0) ++ ++#define IPV4_ADDR_BCAST(a) ((((uint8 *)(a))[0] & ((uint8 *)(a))[1] & \ ++ ((uint8 *)(a))[2] & ((uint8 *)(a))[3]) == 0xff) ++ ++#define IPV4_TOS_DSCP_MASK 0xfc /* DiffServ codepoint mask */ ++#define IPV4_TOS_DSCP_SHIFT 2 /* DiffServ codepoint shift */ ++ ++#define IPV4_TOS(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET]) ++ ++#define IPV4_TOS_PREC_MASK 0xe0 /* Historical precedence mask */ ++#define IPV4_TOS_PREC_SHIFT 5 /* Historical precedence shift */ ++ ++#define IPV4_TOS_LOWDELAY 0x10 /* Lowest delay requested */ ++#define IPV4_TOS_THROUGHPUT 0x8 /* Best throughput requested */ ++#define IPV4_TOS_RELIABILITY 0x4 /* Most reliable delivery requested */ ++ ++#define IPV4_PROT(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET]) ++ ++#define IPV4_FRAG_RESV 0x8000 /* Reserved */ ++#define IPV4_FRAG_DONT 0x4000 /* Don't fragment */ ++#define IPV4_FRAG_MORE 0x2000 /* More fragments */ ++#define IPV4_FRAG_OFFSET_MASK 0x1fff /* Fragment offset */ ++ ++#define IPV4_ADDR_STR_LEN 16 /* Max IP address length in string format */ ++ ++/* IPV4 packet formats */ ++BWL_PRE_PACKED_STRUCT struct ipv4_addr { ++ uint8 addr[IPV4_ADDR_LEN]; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct ipv4_hdr { ++ uint8 version_ihl; /* Version and Internet Header Length */ ++ uint8 tos; /* Type Of Service */ ++ uint16 tot_len; /* Number of bytes in packet (max 65535) */ ++ uint16 id; ++ uint16 frag; /* 3 flag bits and fragment offset */ ++ uint8 ttl; /* Time To Live */ ++ uint8 prot; /* Protocol */ ++ uint16 hdr_chksum; /* IP header checksum */ ++ uint8 src_ip[IPV4_ADDR_LEN]; /* Source IP Address */ ++ uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination IP Address */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* IPV6 field offsets */ ++#define IPV6_PAYLOAD_LEN_OFFSET 4 /* payload length offset */ ++#define IPV6_NEXT_HDR_OFFSET 6 /* next header/protocol offset */ ++#define IPV6_HOP_LIMIT_OFFSET 7 /* hop limit offset */ ++#define IPV6_SRC_IP_OFFSET 8 /* src IP addr offset */ ++#define IPV6_DEST_IP_OFFSET 24 /* dst IP addr offset */ ++ ++/* IPV6 field decodes */ ++#define IPV6_TRAFFIC_CLASS(ipv6_body) \ ++ (((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \ ++ ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4)) ++ ++#define IPV6_FLOW_LABEL(ipv6_body) \ ++ (((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \ ++ (((uint8 *)(ipv6_body))[2] << 8) | \ ++ (((uint8 *)(ipv6_body))[3])) ++ ++#define IPV6_PAYLOAD_LEN(ipv6_body) \ ++ ((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \ ++ ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1]) ++ ++#define IPV6_NEXT_HDR(ipv6_body) \ ++ (((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET]) ++ ++#define IPV6_PROT(ipv6_body) IPV6_NEXT_HDR(ipv6_body) ++ ++#define IPV6_ADDR_LEN 16 /* IPV6 address length */ ++ ++/* IPV4 TOS or IPV6 Traffic Classifier or 0 */ ++#define IP_TOS46(ip_body) \ ++ (IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \ ++ IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0) ++ ++/* IPV6 extension headers (options) */ ++#define IPV6_EXTHDR_HOP 0 ++#define IPV6_EXTHDR_ROUTING 43 ++#define IPV6_EXTHDR_FRAGMENT 44 ++#define IPV6_EXTHDR_AUTH 51 ++#define IPV6_EXTHDR_NONE 59 ++#define IPV6_EXTHDR_DEST 60 ++ ++#define IPV6_EXTHDR(prot) (((prot) == IPV6_EXTHDR_HOP) || \ ++ ((prot) == IPV6_EXTHDR_ROUTING) || \ ++ ((prot) == IPV6_EXTHDR_FRAGMENT) || \ ++ ((prot) == IPV6_EXTHDR_AUTH) || \ ++ ((prot) == IPV6_EXTHDR_NONE) || \ ++ ((prot) == IPV6_EXTHDR_DEST)) ++ ++#define IPV6_MIN_HLEN 40 ++ ++#define IPV6_EXTHDR_LEN(eh) ((((struct ipv6_exthdr *)(eh))->hdrlen + 1) << 3) ++ ++BWL_PRE_PACKED_STRUCT struct ipv6_exthdr { ++ uint8 nexthdr; ++ uint8 hdrlen; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct ipv6_exthdr_frag { ++ uint8 nexthdr; ++ uint8 rsvd; ++ uint16 frag_off; ++ uint32 ident; ++} BWL_POST_PACKED_STRUCT; ++ ++static INLINE int32 ++ipv6_exthdr_len(uint8 *h, uint8 *proto) ++{ ++ uint16 len = 0, hlen; ++ struct ipv6_exthdr *eh = (struct ipv6_exthdr *)h; ++ ++ while (IPV6_EXTHDR(eh->nexthdr)) { ++ if (eh->nexthdr == IPV6_EXTHDR_NONE) ++ return -1; ++ else if (eh->nexthdr == IPV6_EXTHDR_FRAGMENT) ++ hlen = 8; ++ else if (eh->nexthdr == IPV6_EXTHDR_AUTH) ++ hlen = (eh->hdrlen + 2) << 2; ++ else ++ hlen = IPV6_EXTHDR_LEN(eh); ++ ++ len += hlen; ++ eh = (struct ipv6_exthdr *)(h + len); ++ } ++ ++ *proto = eh->nexthdr; ++ return len; ++} ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _bcmip_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/proto/bt_amp_hci.h b/drivers/net/wireless/ap6210/include/proto/bt_amp_hci.h +new file mode 100755 +index 0000000..8617985 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/proto/bt_amp_hci.h +@@ -0,0 +1,441 @@ ++/* ++ * BT-AMP (BlueTooth Alternate Mac and Phy) HCI (Host/Controller Interface) ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bt_amp_hci.h 294267 2011-11-04 23:41:52Z $ ++*/ ++ ++#ifndef _bt_amp_hci_h ++#define _bt_amp_hci_h ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* AMP HCI CMD packet format */ ++typedef BWL_PRE_PACKED_STRUCT struct amp_hci_cmd { ++ uint16 opcode; ++ uint8 plen; ++ uint8 parms[1]; ++} BWL_POST_PACKED_STRUCT amp_hci_cmd_t; ++ ++#define HCI_CMD_PREAMBLE_SIZE OFFSETOF(amp_hci_cmd_t, parms) ++#define HCI_CMD_DATA_SIZE 255 ++ ++/* AMP HCI CMD opcode layout */ ++#define HCI_CMD_OPCODE(ogf, ocf) ((((ogf) & 0x3F) << 10) | ((ocf) & 0x03FF)) ++#define HCI_CMD_OGF(opcode) ((uint8)(((opcode) >> 10) & 0x3F)) ++#define HCI_CMD_OCF(opcode) ((opcode) & 0x03FF) ++ ++/* AMP HCI command opcodes */ ++#define HCI_Read_Failed_Contact_Counter HCI_CMD_OPCODE(0x05, 0x0001) ++#define HCI_Reset_Failed_Contact_Counter HCI_CMD_OPCODE(0x05, 0x0002) ++#define HCI_Read_Link_Quality HCI_CMD_OPCODE(0x05, 0x0003) ++#define HCI_Read_Local_AMP_Info HCI_CMD_OPCODE(0x05, 0x0009) ++#define HCI_Read_Local_AMP_ASSOC HCI_CMD_OPCODE(0x05, 0x000A) ++#define HCI_Write_Remote_AMP_ASSOC HCI_CMD_OPCODE(0x05, 0x000B) ++#define HCI_Create_Physical_Link HCI_CMD_OPCODE(0x01, 0x0035) ++#define HCI_Accept_Physical_Link_Request HCI_CMD_OPCODE(0x01, 0x0036) ++#define HCI_Disconnect_Physical_Link HCI_CMD_OPCODE(0x01, 0x0037) ++#define HCI_Create_Logical_Link HCI_CMD_OPCODE(0x01, 0x0038) ++#define HCI_Accept_Logical_Link HCI_CMD_OPCODE(0x01, 0x0039) ++#define HCI_Disconnect_Logical_Link HCI_CMD_OPCODE(0x01, 0x003A) ++#define HCI_Logical_Link_Cancel HCI_CMD_OPCODE(0x01, 0x003B) ++#define HCI_Flow_Spec_Modify HCI_CMD_OPCODE(0x01, 0x003C) ++#define HCI_Write_Flow_Control_Mode HCI_CMD_OPCODE(0x01, 0x0067) ++#define HCI_Read_Best_Effort_Flush_Timeout HCI_CMD_OPCODE(0x01, 0x0069) ++#define HCI_Write_Best_Effort_Flush_Timeout HCI_CMD_OPCODE(0x01, 0x006A) ++#define HCI_Short_Range_Mode HCI_CMD_OPCODE(0x01, 0x006B) ++#define HCI_Reset HCI_CMD_OPCODE(0x03, 0x0003) ++#define HCI_Read_Connection_Accept_Timeout HCI_CMD_OPCODE(0x03, 0x0015) ++#define HCI_Write_Connection_Accept_Timeout HCI_CMD_OPCODE(0x03, 0x0016) ++#define HCI_Read_Link_Supervision_Timeout HCI_CMD_OPCODE(0x03, 0x0036) ++#define HCI_Write_Link_Supervision_Timeout HCI_CMD_OPCODE(0x03, 0x0037) ++#define HCI_Enhanced_Flush HCI_CMD_OPCODE(0x03, 0x005F) ++#define HCI_Read_Logical_Link_Accept_Timeout HCI_CMD_OPCODE(0x03, 0x0061) ++#define HCI_Write_Logical_Link_Accept_Timeout HCI_CMD_OPCODE(0x03, 0x0062) ++#define HCI_Set_Event_Mask_Page_2 HCI_CMD_OPCODE(0x03, 0x0063) ++#define HCI_Read_Location_Data_Command HCI_CMD_OPCODE(0x03, 0x0064) ++#define HCI_Write_Location_Data_Command HCI_CMD_OPCODE(0x03, 0x0065) ++#define HCI_Read_Local_Version_Info HCI_CMD_OPCODE(0x04, 0x0001) ++#define HCI_Read_Local_Supported_Commands HCI_CMD_OPCODE(0x04, 0x0002) ++#define HCI_Read_Buffer_Size HCI_CMD_OPCODE(0x04, 0x0005) ++#define HCI_Read_Data_Block_Size HCI_CMD_OPCODE(0x04, 0x000A) ++ ++/* AMP HCI command parameters */ ++typedef BWL_PRE_PACKED_STRUCT struct read_local_cmd_parms { ++ uint8 plh; ++ uint8 offset[2]; /* length so far */ ++ uint8 max_remote[2]; ++} BWL_POST_PACKED_STRUCT read_local_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct write_remote_cmd_parms { ++ uint8 plh; ++ uint8 offset[2]; ++ uint8 len[2]; ++ uint8 frag[1]; ++} BWL_POST_PACKED_STRUCT write_remote_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct phy_link_cmd_parms { ++ uint8 plh; ++ uint8 key_length; ++ uint8 key_type; ++ uint8 key[1]; ++} BWL_POST_PACKED_STRUCT phy_link_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct dis_phy_link_cmd_parms { ++ uint8 plh; ++ uint8 reason; ++} BWL_POST_PACKED_STRUCT dis_phy_link_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct log_link_cmd_parms { ++ uint8 plh; ++ uint8 txflow[16]; ++ uint8 rxflow[16]; ++} BWL_POST_PACKED_STRUCT log_link_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct ext_flow_spec { ++ uint8 id; ++ uint8 service_type; ++ uint8 max_sdu[2]; ++ uint8 sdu_ia_time[4]; ++ uint8 access_latency[4]; ++ uint8 flush_timeout[4]; ++} BWL_POST_PACKED_STRUCT ext_flow_spec_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct log_link_cancel_cmd_parms { ++ uint8 plh; ++ uint8 tx_fs_ID; ++} BWL_POST_PACKED_STRUCT log_link_cancel_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct flow_spec_mod_cmd_parms { ++ uint8 llh[2]; ++ uint8 txflow[16]; ++ uint8 rxflow[16]; ++} BWL_POST_PACKED_STRUCT flow_spec_mod_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct plh_pad { ++ uint8 plh; ++ uint8 pad; ++} BWL_POST_PACKED_STRUCT plh_pad_t; ++ ++typedef BWL_PRE_PACKED_STRUCT union hci_handle { ++ uint16 bredr; ++ plh_pad_t amp; ++} BWL_POST_PACKED_STRUCT hci_handle_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct ls_to_cmd_parms { ++ hci_handle_t handle; ++ uint8 timeout[2]; ++} BWL_POST_PACKED_STRUCT ls_to_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct befto_cmd_parms { ++ uint8 llh[2]; ++ uint8 befto[4]; ++} BWL_POST_PACKED_STRUCT befto_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct srm_cmd_parms { ++ uint8 plh; ++ uint8 srm; ++} BWL_POST_PACKED_STRUCT srm_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct ld_cmd_parms { ++ uint8 ld_aware; ++ uint8 ld[2]; ++ uint8 ld_opts; ++ uint8 l_opts; ++} BWL_POST_PACKED_STRUCT ld_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct eflush_cmd_parms { ++ uint8 llh[2]; ++ uint8 packet_type; ++} BWL_POST_PACKED_STRUCT eflush_cmd_parms_t; ++ ++/* Generic AMP extended flow spec service types */ ++#define EFS_SVCTYPE_NO_TRAFFIC 0 ++#define EFS_SVCTYPE_BEST_EFFORT 1 ++#define EFS_SVCTYPE_GUARANTEED 2 ++ ++/* AMP HCI event packet format */ ++typedef BWL_PRE_PACKED_STRUCT struct amp_hci_event { ++ uint8 ecode; ++ uint8 plen; ++ uint8 parms[1]; ++} BWL_POST_PACKED_STRUCT amp_hci_event_t; ++ ++#define HCI_EVT_PREAMBLE_SIZE OFFSETOF(amp_hci_event_t, parms) ++ ++/* AMP HCI event codes */ ++#define HCI_Command_Complete 0x0E ++#define HCI_Command_Status 0x0F ++#define HCI_Flush_Occurred 0x11 ++#define HCI_Enhanced_Flush_Complete 0x39 ++#define HCI_Physical_Link_Complete 0x40 ++#define HCI_Channel_Select 0x41 ++#define HCI_Disconnect_Physical_Link_Complete 0x42 ++#define HCI_Logical_Link_Complete 0x45 ++#define HCI_Disconnect_Logical_Link_Complete 0x46 ++#define HCI_Flow_Spec_Modify_Complete 0x47 ++#define HCI_Number_of_Completed_Data_Blocks 0x48 ++#define HCI_Short_Range_Mode_Change_Complete 0x4C ++#define HCI_Status_Change_Event 0x4D ++#define HCI_Vendor_Specific 0xFF ++ ++/* AMP HCI event mask bit positions */ ++#define HCI_Physical_Link_Complete_Event_Mask 0x0001 ++#define HCI_Channel_Select_Event_Mask 0x0002 ++#define HCI_Disconnect_Physical_Link_Complete_Event_Mask 0x0004 ++#define HCI_Logical_Link_Complete_Event_Mask 0x0020 ++#define HCI_Disconnect_Logical_Link_Complete_Event_Mask 0x0040 ++#define HCI_Flow_Spec_Modify_Complete_Event_Mask 0x0080 ++#define HCI_Number_of_Completed_Data_Blocks_Event_Mask 0x0100 ++#define HCI_Short_Range_Mode_Change_Complete_Event_Mask 0x1000 ++#define HCI_Status_Change_Event_Mask 0x2000 ++#define HCI_All_Event_Mask 0x31e7 ++/* AMP HCI event parameters */ ++typedef BWL_PRE_PACKED_STRUCT struct cmd_status_parms { ++ uint8 status; ++ uint8 cmdpkts; ++ uint16 opcode; ++} BWL_POST_PACKED_STRUCT cmd_status_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct cmd_complete_parms { ++ uint8 cmdpkts; ++ uint16 opcode; ++ uint8 parms[1]; ++} BWL_POST_PACKED_STRUCT cmd_complete_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct flush_occurred_evt_parms { ++ uint16 handle; ++} BWL_POST_PACKED_STRUCT flush_occurred_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct write_remote_evt_parms { ++ uint8 status; ++ uint8 plh; ++} BWL_POST_PACKED_STRUCT write_remote_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct read_local_evt_parms { ++ uint8 status; ++ uint8 plh; ++ uint16 len; ++ uint8 frag[1]; ++} BWL_POST_PACKED_STRUCT read_local_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct read_local_info_evt_parms { ++ uint8 status; ++ uint8 AMP_status; ++ uint32 bandwidth; ++ uint32 gbandwidth; ++ uint32 latency; ++ uint32 PDU_size; ++ uint8 ctrl_type; ++ uint16 PAL_cap; ++ uint16 AMP_ASSOC_len; ++ uint32 max_flush_timeout; ++ uint32 be_flush_timeout; ++} BWL_POST_PACKED_STRUCT read_local_info_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct log_link_evt_parms { ++ uint8 status; ++ uint16 llh; ++ uint8 plh; ++ uint8 tx_fs_ID; ++} BWL_POST_PACKED_STRUCT log_link_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct disc_log_link_evt_parms { ++ uint8 status; ++ uint16 llh; ++ uint8 reason; ++} BWL_POST_PACKED_STRUCT disc_log_link_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct log_link_cancel_evt_parms { ++ uint8 status; ++ uint8 plh; ++ uint8 tx_fs_ID; ++} BWL_POST_PACKED_STRUCT log_link_cancel_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct flow_spec_mod_evt_parms { ++ uint8 status; ++ uint16 llh; ++} BWL_POST_PACKED_STRUCT flow_spec_mod_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct phy_link_evt_parms { ++ uint8 status; ++ uint8 plh; ++} BWL_POST_PACKED_STRUCT phy_link_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct dis_phy_link_evt_parms { ++ uint8 status; ++ uint8 plh; ++ uint8 reason; ++} BWL_POST_PACKED_STRUCT dis_phy_link_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct read_ls_to_evt_parms { ++ uint8 status; ++ hci_handle_t handle; ++ uint16 timeout; ++} BWL_POST_PACKED_STRUCT read_ls_to_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct read_lla_ca_to_evt_parms { ++ uint8 status; ++ uint16 timeout; ++} BWL_POST_PACKED_STRUCT read_lla_ca_to_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct read_data_block_size_evt_parms { ++ uint8 status; ++ uint16 ACL_pkt_len; ++ uint16 data_block_len; ++ uint16 data_block_num; ++} BWL_POST_PACKED_STRUCT read_data_block_size_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct data_blocks { ++ uint16 handle; ++ uint16 pkts; ++ uint16 blocks; ++} BWL_POST_PACKED_STRUCT data_blocks_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct num_completed_data_blocks_evt_parms { ++ uint16 num_blocks; ++ uint8 num_handles; ++ data_blocks_t completed[1]; ++} BWL_POST_PACKED_STRUCT num_completed_data_blocks_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct befto_evt_parms { ++ uint8 status; ++ uint32 befto; ++} BWL_POST_PACKED_STRUCT befto_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct srm_evt_parms { ++ uint8 status; ++ uint8 plh; ++ uint8 srm; ++} BWL_POST_PACKED_STRUCT srm_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct contact_counter_evt_parms { ++ uint8 status; ++ uint8 llh[2]; ++ uint16 counter; ++} BWL_POST_PACKED_STRUCT contact_counter_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct contact_counter_reset_evt_parms { ++ uint8 status; ++ uint8 llh[2]; ++} BWL_POST_PACKED_STRUCT contact_counter_reset_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct read_linkq_evt_parms { ++ uint8 status; ++ hci_handle_t handle; ++ uint8 link_quality; ++} BWL_POST_PACKED_STRUCT read_linkq_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct ld_evt_parms { ++ uint8 status; ++ uint8 ld_aware; ++ uint8 ld[2]; ++ uint8 ld_opts; ++ uint8 l_opts; ++} BWL_POST_PACKED_STRUCT ld_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct eflush_complete_evt_parms { ++ uint16 handle; ++} BWL_POST_PACKED_STRUCT eflush_complete_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct vendor_specific_evt_parms { ++ uint8 len; ++ uint8 parms[1]; ++} BWL_POST_PACKED_STRUCT vendor_specific_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct local_version_info_evt_parms { ++ uint8 status; ++ uint8 hci_version; ++ uint16 hci_revision; ++ uint8 pal_version; ++ uint16 mfg_name; ++ uint16 pal_subversion; ++} BWL_POST_PACKED_STRUCT local_version_info_evt_parms_t; ++ ++#define MAX_SUPPORTED_CMD_BYTE 64 ++typedef BWL_PRE_PACKED_STRUCT struct local_supported_cmd_evt_parms { ++ uint8 status; ++ uint8 cmd[MAX_SUPPORTED_CMD_BYTE]; ++} BWL_POST_PACKED_STRUCT local_supported_cmd_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct status_change_evt_parms { ++ uint8 status; ++ uint8 amp_status; ++} BWL_POST_PACKED_STRUCT status_change_evt_parms_t; ++ ++/* AMP HCI error codes */ ++#define HCI_SUCCESS 0x00 ++#define HCI_ERR_ILLEGAL_COMMAND 0x01 ++#define HCI_ERR_NO_CONNECTION 0x02 ++#define HCI_ERR_MEMORY_FULL 0x07 ++#define HCI_ERR_CONNECTION_TIMEOUT 0x08 ++#define HCI_ERR_MAX_NUM_OF_CONNECTIONS 0x09 ++#define HCI_ERR_CONNECTION_EXISTS 0x0B ++#define HCI_ERR_CONNECTION_DISALLOWED 0x0C ++#define HCI_ERR_CONNECTION_ACCEPT_TIMEOUT 0x10 ++#define HCI_ERR_UNSUPPORTED_VALUE 0x11 ++#define HCI_ERR_ILLEGAL_PARAMETER_FMT 0x12 ++#define HCI_ERR_CONN_TERM_BY_LOCAL_HOST 0x16 ++#define HCI_ERR_UNSPECIFIED 0x1F ++#define HCI_ERR_UNIT_KEY_USED 0x26 ++#define HCI_ERR_QOS_REJECTED 0x2D ++#define HCI_ERR_PARAM_OUT_OF_RANGE 0x30 ++#define HCI_ERR_NO_SUITABLE_CHANNEL 0x39 ++#define HCI_ERR_CHANNEL_MOVE 0xFF ++ ++/* AMP HCI ACL Data packet format */ ++typedef BWL_PRE_PACKED_STRUCT struct amp_hci_ACL_data { ++ uint16 handle; /* 12-bit connection handle + 2-bit PB and 2-bit BC flags */ ++ uint16 dlen; /* data total length */ ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT amp_hci_ACL_data_t; ++ ++#define HCI_ACL_DATA_PREAMBLE_SIZE OFFSETOF(amp_hci_ACL_data_t, data) ++ ++#define HCI_ACL_DATA_BC_FLAGS (0x0 << 14) ++#define HCI_ACL_DATA_PB_FLAGS (0x3 << 12) ++ ++#define HCI_ACL_DATA_HANDLE(handle) ((handle) & 0x0fff) ++#define HCI_ACL_DATA_FLAGS(handle) ((handle) >> 12) ++ ++/* AMP Activity Report packet formats */ ++typedef BWL_PRE_PACKED_STRUCT struct amp_hci_activity_report { ++ uint8 ScheduleKnown; ++ uint8 NumReports; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT amp_hci_activity_report_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct amp_hci_activity_report_triple { ++ uint32 StartTime; ++ uint32 Duration; ++ uint32 Periodicity; ++} BWL_POST_PACKED_STRUCT amp_hci_activity_report_triple_t; ++ ++#define HCI_AR_SCHEDULE_KNOWN 0x01 ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _bt_amp_hci_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/proto/eapol.h b/drivers/net/wireless/ap6210/include/proto/eapol.h +new file mode 100755 +index 0000000..8936d16 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/proto/eapol.h +@@ -0,0 +1,193 @@ ++/* ++ * 802.1x EAPOL definitions ++ * ++ * See ++ * IEEE Std 802.1X-2001 ++ * IEEE 802.1X RADIUS Usage Guidelines ++ * ++ * Copyright (C) 2002 Broadcom Corporation ++ * ++ * $Id: eapol.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _eapol_h_ ++#define _eapol_h_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#include ++ ++/* EAPOL for 802.3/Ethernet */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ struct ether_header eth; /* 802.3/Ethernet header */ ++ unsigned char version; /* EAPOL protocol version */ ++ unsigned char type; /* EAPOL type */ ++ unsigned short length; /* Length of body */ ++ unsigned char body[1]; /* Body (optional) */ ++} BWL_POST_PACKED_STRUCT eapol_header_t; ++ ++#define EAPOL_HEADER_LEN 18 ++ ++typedef struct { ++ unsigned char version; /* EAPOL protocol version */ ++ unsigned char type; /* EAPOL type */ ++ unsigned short length; /* Length of body */ ++} eapol_hdr_t; ++ ++#define EAPOL_HDR_LEN 4 ++ ++/* EAPOL version */ ++#define WPA2_EAPOL_VERSION 2 ++#define WPA_EAPOL_VERSION 1 ++#define LEAP_EAPOL_VERSION 1 ++#define SES_EAPOL_VERSION 1 ++ ++/* EAPOL types */ ++#define EAP_PACKET 0 ++#define EAPOL_START 1 ++#define EAPOL_LOGOFF 2 ++#define EAPOL_KEY 3 ++#define EAPOL_ASF 4 ++ ++/* EAPOL-Key types */ ++#define EAPOL_RC4_KEY 1 ++#define EAPOL_WPA2_KEY 2 /* 802.11i/WPA2 */ ++#define EAPOL_WPA_KEY 254 /* WPA */ ++ ++/* RC4 EAPOL-Key header field sizes */ ++#define EAPOL_KEY_REPLAY_LEN 8 ++#define EAPOL_KEY_IV_LEN 16 ++#define EAPOL_KEY_SIG_LEN 16 ++ ++/* RC4 EAPOL-Key */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ unsigned char type; /* Key Descriptor Type */ ++ unsigned short length; /* Key Length (unaligned) */ ++ unsigned char replay[EAPOL_KEY_REPLAY_LEN]; /* Replay Counter */ ++ unsigned char iv[EAPOL_KEY_IV_LEN]; /* Key IV */ ++ unsigned char index; /* Key Flags & Index */ ++ unsigned char signature[EAPOL_KEY_SIG_LEN]; /* Key Signature */ ++ unsigned char key[1]; /* Key (optional) */ ++} BWL_POST_PACKED_STRUCT eapol_key_header_t; ++ ++#define EAPOL_KEY_HEADER_LEN 44 ++ ++/* RC4 EAPOL-Key flags */ ++#define EAPOL_KEY_FLAGS_MASK 0x80 ++#define EAPOL_KEY_BROADCAST 0 ++#define EAPOL_KEY_UNICAST 0x80 ++ ++/* RC4 EAPOL-Key index */ ++#define EAPOL_KEY_INDEX_MASK 0x7f ++ ++/* WPA/802.11i/WPA2 EAPOL-Key header field sizes */ ++#define EAPOL_WPA_KEY_REPLAY_LEN 8 ++#define EAPOL_WPA_KEY_NONCE_LEN 32 ++#define EAPOL_WPA_KEY_IV_LEN 16 ++#define EAPOL_WPA_KEY_RSC_LEN 8 ++#define EAPOL_WPA_KEY_ID_LEN 8 ++#define EAPOL_WPA_KEY_MIC_LEN 16 ++#define EAPOL_WPA_KEY_DATA_LEN (EAPOL_WPA_MAX_KEY_SIZE + AKW_BLOCK_LEN) ++#define EAPOL_WPA_MAX_KEY_SIZE 32 ++ ++/* WPA EAPOL-Key */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ unsigned char type; /* Key Descriptor Type */ ++ unsigned short key_info; /* Key Information (unaligned) */ ++ unsigned short key_len; /* Key Length (unaligned) */ ++ unsigned char replay[EAPOL_WPA_KEY_REPLAY_LEN]; /* Replay Counter */ ++ unsigned char nonce[EAPOL_WPA_KEY_NONCE_LEN]; /* Nonce */ ++ unsigned char iv[EAPOL_WPA_KEY_IV_LEN]; /* Key IV */ ++ unsigned char rsc[EAPOL_WPA_KEY_RSC_LEN]; /* Key RSC */ ++ unsigned char id[EAPOL_WPA_KEY_ID_LEN]; /* WPA:Key ID, 802.11i/WPA2: Reserved */ ++ unsigned char mic[EAPOL_WPA_KEY_MIC_LEN]; /* Key MIC */ ++ unsigned short data_len; /* Key Data Length */ ++ unsigned char data[EAPOL_WPA_KEY_DATA_LEN]; /* Key data */ ++} BWL_POST_PACKED_STRUCT eapol_wpa_key_header_t; ++ ++#define EAPOL_WPA_KEY_LEN 95 ++ ++/* WPA/802.11i/WPA2 KEY KEY_INFO bits */ ++#define WPA_KEY_DESC_V1 0x01 ++#define WPA_KEY_DESC_V2 0x02 ++#define WPA_KEY_DESC_V3 0x03 ++#define WPA_KEY_PAIRWISE 0x08 ++#define WPA_KEY_INSTALL 0x40 ++#define WPA_KEY_ACK 0x80 ++#define WPA_KEY_MIC 0x100 ++#define WPA_KEY_SECURE 0x200 ++#define WPA_KEY_ERROR 0x400 ++#define WPA_KEY_REQ 0x800 ++ ++#define WPA_KEY_DESC_V2_OR_V3 WPA_KEY_DESC_V2 ++ ++/* WPA-only KEY KEY_INFO bits */ ++#define WPA_KEY_INDEX_0 0x00 ++#define WPA_KEY_INDEX_1 0x10 ++#define WPA_KEY_INDEX_2 0x20 ++#define WPA_KEY_INDEX_3 0x30 ++#define WPA_KEY_INDEX_MASK 0x30 ++#define WPA_KEY_INDEX_SHIFT 0x04 ++ ++/* 802.11i/WPA2-only KEY KEY_INFO bits */ ++#define WPA_KEY_ENCRYPTED_DATA 0x1000 ++ ++/* Key Data encapsulation */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint8 type; ++ uint8 length; ++ uint8 oui[3]; ++ uint8 subtype; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT eapol_wpa2_encap_data_t; ++ ++#define EAPOL_WPA2_ENCAP_DATA_HDR_LEN 6 ++ ++#define WPA2_KEY_DATA_SUBTYPE_GTK 1 ++#define WPA2_KEY_DATA_SUBTYPE_STAKEY 2 ++#define WPA2_KEY_DATA_SUBTYPE_MAC 3 ++#define WPA2_KEY_DATA_SUBTYPE_PMKID 4 ++#define WPA2_KEY_DATA_SUBTYPE_IGTK 9 ++ ++/* GTK encapsulation */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint8 flags; ++ uint8 reserved; ++ uint8 gtk[EAPOL_WPA_MAX_KEY_SIZE]; ++} BWL_POST_PACKED_STRUCT eapol_wpa2_key_gtk_encap_t; ++ ++#define EAPOL_WPA2_KEY_GTK_ENCAP_HDR_LEN 2 ++ ++#define WPA2_GTK_INDEX_MASK 0x03 ++#define WPA2_GTK_INDEX_SHIFT 0x00 ++ ++#define WPA2_GTK_TRANSMIT 0x04 ++ ++/* IGTK encapsulation */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint16 key_id; ++ uint8 ipn[6]; ++ uint8 key[EAPOL_WPA_MAX_KEY_SIZE]; ++} BWL_POST_PACKED_STRUCT eapol_wpa2_key_igtk_encap_t; ++ ++#define EAPOL_WPA2_KEY_IGTK_ENCAP_HDR_LEN 8 ++ ++/* STAKey encapsulation */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint8 reserved[2]; ++ uint8 mac[ETHER_ADDR_LEN]; ++ uint8 stakey[EAPOL_WPA_MAX_KEY_SIZE]; ++} BWL_POST_PACKED_STRUCT eapol_wpa2_key_stakey_encap_t; ++ ++#define WPA2_KEY_DATA_PAD 0xdd ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _eapol_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/proto/ethernet.h b/drivers/net/wireless/ap6210/include/proto/ethernet.h +new file mode 100755 +index 0000000..a6ce6e1 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/proto/ethernet.h +@@ -0,0 +1,190 @@ ++/* ++ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: ethernet.h 309193 2012-01-19 00:03:57Z $ ++ */ ++ ++#ifndef _NET_ETHERNET_H_ /* use native BSD ethernet.h when available */ ++#define _NET_ETHERNET_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include "typedefs.h" ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* ++ * The number of bytes in an ethernet (MAC) address. ++ */ ++#define ETHER_ADDR_LEN 6 ++ ++/* ++ * The number of bytes in the type field. ++ */ ++#define ETHER_TYPE_LEN 2 ++ ++/* ++ * The number of bytes in the trailing CRC field. ++ */ ++#define ETHER_CRC_LEN 4 ++ ++/* ++ * The length of the combined header. ++ */ ++#define ETHER_HDR_LEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN) ++ ++/* ++ * The minimum packet length. ++ */ ++#define ETHER_MIN_LEN 64 ++ ++/* ++ * The minimum packet user data length. ++ */ ++#define ETHER_MIN_DATA 46 ++ ++/* ++ * The maximum packet length. ++ */ ++#define ETHER_MAX_LEN 1518 ++ ++/* ++ * The maximum packet user data length. ++ */ ++#define ETHER_MAX_DATA 1500 ++ ++/* ether types */ ++#define ETHER_TYPE_MIN 0x0600 /* Anything less than MIN is a length */ ++#define ETHER_TYPE_IP 0x0800 /* IP */ ++#define ETHER_TYPE_ARP 0x0806 /* ARP */ ++#define ETHER_TYPE_8021Q 0x8100 /* 802.1Q */ ++#define ETHER_TYPE_IPV6 0x86dd /* IPv6 */ ++#define ETHER_TYPE_BRCM 0x886c /* Broadcom Corp. */ ++#define ETHER_TYPE_802_1X 0x888e /* 802.1x */ ++#define ETHER_TYPE_802_1X_PREAUTH 0x88c7 /* 802.1x preauthentication */ ++#define ETHER_TYPE_WAI 0x88b4 /* WAI */ ++#define ETHER_TYPE_89_0D 0x890d /* 89-0d frame for TDLS */ ++ ++#define ETHER_TYPE_IPV6 0x86dd /* IPV6 */ ++ ++/* Broadcom subtype follows ethertype; First 2 bytes are reserved; Next 2 are subtype; */ ++#define ETHER_BRCM_SUBTYPE_LEN 4 /* Broadcom 4 byte subtype */ ++ ++/* ether header */ ++#define ETHER_DEST_OFFSET (0 * ETHER_ADDR_LEN) /* dest address offset */ ++#define ETHER_SRC_OFFSET (1 * ETHER_ADDR_LEN) /* src address offset */ ++#define ETHER_TYPE_OFFSET (2 * ETHER_ADDR_LEN) /* ether type offset */ ++ ++/* ++ * A macro to validate a length with ++ */ ++#define ETHER_IS_VALID_LEN(foo) \ ++ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) ++ ++#define ETHER_FILL_MCAST_ADDR_FROM_IP(ea, mgrp_ip) { \ ++ ((uint8 *)ea)[0] = 0x01; \ ++ ((uint8 *)ea)[1] = 0x00; \ ++ ((uint8 *)ea)[2] = 0x5e; \ ++ ((uint8 *)ea)[3] = ((mgrp_ip) >> 16) & 0x7f; \ ++ ((uint8 *)ea)[4] = ((mgrp_ip) >> 8) & 0xff; \ ++ ((uint8 *)ea)[5] = ((mgrp_ip) >> 0) & 0xff; \ ++} ++ ++#ifndef __INCif_etherh /* Quick and ugly hack for VxWorks */ ++/* ++ * Structure of a 10Mb/s Ethernet header. ++ */ ++BWL_PRE_PACKED_STRUCT struct ether_header { ++ uint8 ether_dhost[ETHER_ADDR_LEN]; ++ uint8 ether_shost[ETHER_ADDR_LEN]; ++ uint16 ether_type; ++} BWL_POST_PACKED_STRUCT; ++ ++/* ++ * Structure of a 48-bit Ethernet address. ++ */ ++BWL_PRE_PACKED_STRUCT struct ether_addr { ++ uint8 octet[ETHER_ADDR_LEN]; ++} BWL_POST_PACKED_STRUCT; ++#endif /* !__INCif_etherh Quick and ugly hack for VxWorks */ ++ ++/* ++ * Takes a pointer, set, test, clear, toggle locally admininistered ++ * address bit in the 48-bit Ethernet address. ++ */ ++#define ETHER_SET_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2)) ++#define ETHER_IS_LOCALADDR(ea) (((uint8 *)(ea))[0] & 2) ++#define ETHER_CLR_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & 0xfd)) ++#define ETHER_TOGGLE_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] ^ 2)) ++ ++/* Takes a pointer, marks unicast address bit in the MAC address */ ++#define ETHER_SET_UNICAST(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & ~1)) ++ ++/* ++ * Takes a pointer, returns true if a 48-bit multicast address ++ * (including broadcast, since it is all ones) ++ */ ++#define ETHER_ISMULTI(ea) (((const uint8 *)(ea))[0] & 1) ++ ++ ++/* compare two ethernet addresses - assumes the pointers can be referenced as shorts */ ++#define ether_cmp(a, b) (!(((short*)(a))[0] == ((short*)(b))[0]) | \ ++ !(((short*)(a))[1] == ((short*)(b))[1]) | \ ++ !(((short*)(a))[2] == ((short*)(b))[2])) ++ ++/* copy an ethernet address - assumes the pointers can be referenced as shorts */ ++#define ether_copy(s, d) { \ ++ ((short*)(d))[0] = ((const short*)(s))[0]; \ ++ ((short*)(d))[1] = ((const short*)(s))[1]; \ ++ ((short*)(d))[2] = ((const short*)(s))[2]; } ++ ++ ++static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}}; ++static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}}; ++ ++#define ETHER_ISBCAST(ea) ((((uint8 *)(ea))[0] & \ ++ ((uint8 *)(ea))[1] & \ ++ ((uint8 *)(ea))[2] & \ ++ ((uint8 *)(ea))[3] & \ ++ ((uint8 *)(ea))[4] & \ ++ ((uint8 *)(ea))[5]) == 0xff) ++#define ETHER_ISNULLADDR(ea) ((((uint8 *)(ea))[0] | \ ++ ((uint8 *)(ea))[1] | \ ++ ((uint8 *)(ea))[2] | \ ++ ((uint8 *)(ea))[3] | \ ++ ((uint8 *)(ea))[4] | \ ++ ((uint8 *)(ea))[5]) == 0) ++ ++#define ETHER_MOVE_HDR(d, s) \ ++do { \ ++ struct ether_header t; \ ++ t = *(struct ether_header *)(s); \ ++ *(struct ether_header *)(d) = t; \ ++} while (0) ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _NET_ETHERNET_H_ */ +diff --git a/drivers/net/wireless/ap6210/include/proto/p2p.h b/drivers/net/wireless/ap6210/include/proto/p2p.h +new file mode 100755 +index 0000000..6716e2a +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/proto/p2p.h +@@ -0,0 +1,579 @@ ++/* ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * Fundamental types and constants relating to WFA P2P (aka WiFi Direct) ++ * ++ * $Id: p2p.h 356417 2012-09-12 16:41:24Z $ ++ */ ++ ++#ifndef _P2P_H_ ++#define _P2P_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++#include ++#include ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* WiFi P2P OUI values */ ++#define P2P_OUI WFA_OUI /* WiFi P2P OUI */ ++#define P2P_VER WFA_OUI_TYPE_P2P /* P2P version: 9=WiFi P2P v1.0 */ ++ ++#define P2P_IE_ID 0xdd /* P2P IE element ID */ ++ ++/* WiFi P2P IE */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_ie { ++ uint8 id; /* IE ID: 0xDD */ ++ uint8 len; /* IE length */ ++ uint8 OUI[3]; /* WiFi P2P specific OUI: P2P_OUI */ ++ uint8 oui_type; /* Identifies P2P version: P2P_VER */ ++ uint8 subelts[1]; /* variable length subelements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_ie wifi_p2p_ie_t; ++ ++#define P2P_IE_FIXED_LEN 6 ++ ++#define P2P_ATTR_ID_OFF 0 ++#define P2P_ATTR_LEN_OFF 1 ++#define P2P_ATTR_DATA_OFF 3 ++ ++#define P2P_ATTR_ID_LEN 1 /* ID filed length */ ++#define P2P_ATTR_LEN_LEN 2 /* length field length */ ++#define P2P_ATTR_HDR_LEN 3 /* ID + 2-byte length field spec 1.02 */ ++ ++/* P2P IE Subelement IDs from WiFi P2P Technical Spec 1.00 */ ++#define P2P_SEID_STATUS 0 /* Status */ ++#define P2P_SEID_MINOR_RC 1 /* Minor Reason Code */ ++#define P2P_SEID_P2P_INFO 2 /* P2P Capability (capabilities info) */ ++#define P2P_SEID_DEV_ID 3 /* P2P Device ID */ ++#define P2P_SEID_INTENT 4 /* Group Owner Intent */ ++#define P2P_SEID_CFG_TIMEOUT 5 /* Configuration Timeout */ ++#define P2P_SEID_CHANNEL 6 /* Channel */ ++#define P2P_SEID_GRP_BSSID 7 /* P2P Group BSSID */ ++#define P2P_SEID_XT_TIMING 8 /* Extended Listen Timing */ ++#define P2P_SEID_INTINTADDR 9 /* Intended P2P Interface Address */ ++#define P2P_SEID_P2P_MGBTY 10 /* P2P Manageability */ ++#define P2P_SEID_CHAN_LIST 11 /* Channel List */ ++#define P2P_SEID_ABSENCE 12 /* Notice of Absence */ ++#define P2P_SEID_DEV_INFO 13 /* Device Info */ ++#define P2P_SEID_GROUP_INFO 14 /* Group Info */ ++#define P2P_SEID_GROUP_ID 15 /* Group ID */ ++#define P2P_SEID_P2P_IF 16 /* P2P Interface */ ++#define P2P_SEID_OP_CHANNEL 17 /* Operating Channel */ ++#define P2P_SEID_INVITE_FLAGS 18 /* Invitation Flags */ ++#define P2P_SEID_VNDR 221 /* Vendor-specific subelement */ ++ ++#define P2P_SE_VS_ID_SERVICES 0x1b /* BRCM proprietary subel: L2 Services */ ++ ++ ++/* WiFi P2P IE subelement: P2P Capability (capabilities info) */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_info_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_P2P_INFO */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 dev; /* Device Capability Bitmap */ ++ uint8 group; /* Group Capability Bitmap */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_info_se_s wifi_p2p_info_se_t; ++ ++/* P2P Capability subelement's Device Capability Bitmap bit values */ ++#define P2P_CAPSE_DEV_SERVICE_DIS 0x1 /* Service Discovery */ ++#define P2P_CAPSE_DEV_CLIENT_DIS 0x2 /* Client Discoverability */ ++#define P2P_CAPSE_DEV_CONCURRENT 0x4 /* Concurrent Operation */ ++#define P2P_CAPSE_DEV_INFRA_MAN 0x8 /* P2P Infrastructure Managed */ ++#define P2P_CAPSE_DEV_LIMIT 0x10 /* P2P Device Limit */ ++#define P2P_CAPSE_INVITE_PROC 0x20 /* P2P Invitation Procedure */ ++ ++/* P2P Capability subelement's Group Capability Bitmap bit values */ ++#define P2P_CAPSE_GRP_OWNER 0x1 /* P2P Group Owner */ ++#define P2P_CAPSE_PERSIST_GRP 0x2 /* Persistent P2P Group */ ++#define P2P_CAPSE_GRP_LIMIT 0x4 /* P2P Group Limit */ ++#define P2P_CAPSE_GRP_INTRA_BSS 0x8 /* Intra-BSS Distribution */ ++#define P2P_CAPSE_GRP_X_CONNECT 0x10 /* Cross Connection */ ++#define P2P_CAPSE_GRP_PERSISTENT 0x20 /* Persistent Reconnect */ ++#define P2P_CAPSE_GRP_FORMATION 0x40 /* Group Formation */ ++ ++ ++/* WiFi P2P IE subelement: Group Owner Intent */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_intent_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_INTENT */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 intent; /* Intent Value 0...15 (0=legacy 15=master only) */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_intent_se_s wifi_p2p_intent_se_t; ++ ++/* WiFi P2P IE subelement: Configuration Timeout */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_cfg_tmo_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_CFG_TIMEOUT */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 go_tmo; /* GO config timeout in units of 10 ms */ ++ uint8 client_tmo; /* Client config timeout in units of 10 ms */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_cfg_tmo_se_s wifi_p2p_cfg_tmo_se_t; ++ ++/* WiFi P2P IE subelement: Listen Channel */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_listen_channel_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_CHANNEL */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 country[3]; /* Country String */ ++ uint8 op_class; /* Operating Class */ ++ uint8 channel; /* Channel */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_listen_channel_se_s wifi_p2p_listen_channel_se_t; ++ ++/* WiFi P2P IE subelement: P2P Group BSSID */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_grp_bssid_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_GRP_BSSID */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 mac[6]; /* P2P group bssid */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_grp_bssid_se_s wifi_p2p_grp_bssid_se_t; ++ ++/* WiFi P2P IE subelement: P2P Group ID */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_grp_id_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_GROUP_ID */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 mac[6]; /* P2P device address */ ++ uint8 ssid[1]; /* ssid. device id. variable length */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_grp_id_se_s wifi_p2p_grp_id_se_t; ++ ++/* WiFi P2P IE subelement: P2P Interface */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_intf_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_P2P_IF */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 mac[6]; /* P2P device address */ ++ uint8 ifaddrs; /* P2P Interface Address count */ ++ uint8 ifaddr[1][6]; /* P2P Interface Address list */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_intf_se_s wifi_p2p_intf_se_t; ++ ++/* WiFi P2P IE subelement: Status */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_status_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_STATUS */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 status; /* Status Code: P2P_STATSE_* */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_status_se_s wifi_p2p_status_se_t; ++ ++/* Status subelement Status Code definitions */ ++#define P2P_STATSE_SUCCESS 0 ++ /* Success */ ++#define P2P_STATSE_FAIL_INFO_CURR_UNAVAIL 1 ++ /* Failed, information currently unavailable */ ++#define P2P_STATSE_PASSED_UP P2P_STATSE_FAIL_INFO_CURR_UNAVAIL ++ /* Old name for above in P2P spec 1.08 and older */ ++#define P2P_STATSE_FAIL_INCOMPAT_PARAMS 2 ++ /* Failed, incompatible parameters */ ++#define P2P_STATSE_FAIL_LIMIT_REACHED 3 ++ /* Failed, limit reached */ ++#define P2P_STATSE_FAIL_INVALID_PARAMS 4 ++ /* Failed, invalid parameters */ ++#define P2P_STATSE_FAIL_UNABLE_TO_ACCOM 5 ++ /* Failed, unable to accomodate request */ ++#define P2P_STATSE_FAIL_PROTO_ERROR 6 ++ /* Failed, previous protocol error or disruptive behaviour */ ++#define P2P_STATSE_FAIL_NO_COMMON_CHAN 7 ++ /* Failed, no common channels */ ++#define P2P_STATSE_FAIL_UNKNOWN_GROUP 8 ++ /* Failed, unknown P2P Group */ ++#define P2P_STATSE_FAIL_INTENT 9 ++ /* Failed, both peers indicated Intent 15 in GO Negotiation */ ++#define P2P_STATSE_FAIL_INCOMPAT_PROVIS 10 ++ /* Failed, incompatible provisioning method */ ++#define P2P_STATSE_FAIL_USER_REJECT 11 ++ /* Failed, rejected by user */ ++ ++/* WiFi P2P IE attribute: Extended Listen Timing */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_ext_se_s { ++ uint8 eltId; /* ID: P2P_SEID_EXT_TIMING */ ++ uint8 len[2]; /* length not including eltId, len fields */ ++ uint8 avail[2]; /* availibility period */ ++ uint8 interval[2]; /* availibility interval */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_ext_se_s wifi_p2p_ext_se_t; ++ ++#define P2P_EXT_MIN 10 /* minimum 10ms */ ++ ++/* WiFi P2P IE subelement: Intended P2P Interface Address */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_intintad_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_INTINTADDR */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 mac[6]; /* intended P2P interface MAC address */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_intintad_se_s wifi_p2p_intintad_se_t; ++ ++/* WiFi P2P IE subelement: Channel */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_channel_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_STATUS */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 band; /* Regulatory Class (band) */ ++ uint8 channel; /* Channel */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_channel_se_s wifi_p2p_channel_se_t; ++ ++ ++/* Channel Entry structure within the Channel List SE */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_chanlist_entry_s { ++ uint8 band; /* Regulatory Class (band) */ ++ uint8 num_channels; /* # of channels in the channel list */ ++ uint8 channels[WL_NUMCHANNELS]; /* Channel List */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_chanlist_entry_s wifi_p2p_chanlist_entry_t; ++#define WIFI_P2P_CHANLIST_SE_MAX_ENTRIES 2 ++ ++/* WiFi P2P IE subelement: Channel List */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_chanlist_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_CHAN_LIST */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 country[3]; /* Country String */ ++ uint8 num_entries; /* # of channel entries */ ++ wifi_p2p_chanlist_entry_t entries[WIFI_P2P_CHANLIST_SE_MAX_ENTRIES]; ++ /* Channel Entry List */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_chanlist_se_s wifi_p2p_chanlist_se_t; ++ ++/* WiFi Primary Device Type structure */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_pri_devtype_s { ++ uint16 cat_id; /* Category ID */ ++ uint8 OUI[3]; /* WFA OUI: 0x0050F2 */ ++ uint8 oui_type; /* WPS_OUI_TYPE */ ++ uint16 sub_cat_id; /* Sub Category ID */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_pri_devtype_s wifi_p2p_pri_devtype_t; ++ ++/* WiFi P2P IE's Device Info subelement */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_devinfo_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_DEVINFO */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 mac[6]; /* P2P Device MAC address */ ++ uint16 wps_cfg_meths; /* Config Methods: reg_prototlv.h WPS_CONFMET_* */ ++ uint8 pri_devtype[8]; /* Primary Device Type */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_devinfo_se_s wifi_p2p_devinfo_se_t; ++ ++#define P2P_DEV_TYPE_LEN 8 ++ ++/* WiFi P2P IE's Group Info subelement Client Info Descriptor */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_cid_fixed_s { ++ uint8 len; ++ uint8 devaddr[ETHER_ADDR_LEN]; /* P2P Device Address */ ++ uint8 ifaddr[ETHER_ADDR_LEN]; /* P2P Interface Address */ ++ uint8 devcap; /* Device Capability */ ++ uint8 cfg_meths[2]; /* Config Methods: reg_prototlv.h WPS_CONFMET_* */ ++ uint8 pridt[P2P_DEV_TYPE_LEN]; /* Primary Device Type */ ++ uint8 secdts; /* Number of Secondary Device Types */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_cid_fixed_s wifi_p2p_cid_fixed_t; ++ ++/* WiFi P2P IE's Device ID subelement */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_devid_se_s { ++ uint8 eltId; ++ uint8 len[2]; ++ struct ether_addr addr; /* P2P Device MAC address */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_devid_se_s wifi_p2p_devid_se_t; ++ ++/* WiFi P2P IE subelement: P2P Manageability */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_mgbt_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_P2P_MGBTY */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 mg_bitmap; /* manageability bitmap */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_mgbt_se_s wifi_p2p_mgbt_se_t; ++/* mg_bitmap field bit values */ ++#define P2P_MGBTSE_P2PDEVMGMT_FLAG 0x1 /* AP supports Managed P2P Device */ ++ ++/* WiFi P2P IE subelement: Group Info */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_grpinfo_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_GROUP_INFO */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_grpinfo_se_s wifi_p2p_grpinfo_se_t; ++ ++/* WiFi IE subelement: Operating Channel */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_op_channel_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_OP_CHANNEL */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 country[3]; /* Country String */ ++ uint8 op_class; /* Operating Class */ ++ uint8 channel; /* Channel */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_op_channel_se_s wifi_p2p_op_channel_se_t; ++ ++/* WiFi IE subelement: INVITATION FLAGS */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_invite_flags_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_INVITE_FLAGS */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 flags; /* Flags */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_invite_flags_se_s wifi_p2p_invite_flags_se_t; ++ ++/* WiFi P2P Action Frame */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_action_frame { ++ uint8 category; /* P2P_AF_CATEGORY */ ++ uint8 OUI[3]; /* OUI - P2P_OUI */ ++ uint8 type; /* OUI Type - P2P_VER */ ++ uint8 subtype; /* OUI Subtype - P2P_AF_* */ ++ uint8 dialog_token; /* nonzero, identifies req/resp tranaction */ ++ uint8 elts[1]; /* Variable length information elements. Max size = ++ * ACTION_FRAME_SIZE - sizeof(this structure) - 1 ++ */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_action_frame wifi_p2p_action_frame_t; ++#define P2P_AF_CATEGORY 0x7f ++ ++#define P2P_AF_FIXED_LEN 7 ++ ++/* WiFi P2P Action Frame OUI Subtypes */ ++#define P2P_AF_NOTICE_OF_ABSENCE 0 /* Notice of Absence */ ++#define P2P_AF_PRESENCE_REQ 1 /* P2P Presence Request */ ++#define P2P_AF_PRESENCE_RSP 2 /* P2P Presence Response */ ++#define P2P_AF_GO_DISC_REQ 3 /* GO Discoverability Request */ ++ ++ ++/* WiFi P2P Public Action Frame */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_pub_act_frame { ++ uint8 category; /* P2P_PUB_AF_CATEGORY */ ++ uint8 action; /* P2P_PUB_AF_ACTION */ ++ uint8 oui[3]; /* P2P_OUI */ ++ uint8 oui_type; /* OUI type - P2P_VER */ ++ uint8 subtype; /* OUI subtype - P2P_TYPE_* */ ++ uint8 dialog_token; /* nonzero, identifies req/rsp transaction */ ++ uint8 elts[1]; /* Variable length information elements. Max size = ++ * ACTION_FRAME_SIZE - sizeof(this structure) - 1 ++ */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_pub_act_frame wifi_p2p_pub_act_frame_t; ++#define P2P_PUB_AF_FIXED_LEN 8 ++#define P2P_PUB_AF_CATEGORY 0x04 ++#define P2P_PUB_AF_ACTION 0x09 ++ ++/* WiFi P2P Public Action Frame OUI Subtypes */ ++#define P2P_PAF_GON_REQ 0 /* Group Owner Negotiation Req */ ++#define P2P_PAF_GON_RSP 1 /* Group Owner Negotiation Rsp */ ++#define P2P_PAF_GON_CONF 2 /* Group Owner Negotiation Confirm */ ++#define P2P_PAF_INVITE_REQ 3 /* P2P Invitation Request */ ++#define P2P_PAF_INVITE_RSP 4 /* P2P Invitation Response */ ++#define P2P_PAF_DEVDIS_REQ 5 /* Device Discoverability Request */ ++#define P2P_PAF_DEVDIS_RSP 6 /* Device Discoverability Response */ ++#define P2P_PAF_PROVDIS_REQ 7 /* Provision Discovery Request */ ++#define P2P_PAF_PROVDIS_RSP 8 /* Provision Discovery Response */ ++#define P2P_PAF_SUBTYPE_INVALID 255 /* Invalid Subtype */ ++ ++/* TODO: Stop using these obsolete aliases for P2P_PAF_GON_* */ ++#define P2P_TYPE_MNREQ P2P_PAF_GON_REQ ++#define P2P_TYPE_MNRSP P2P_PAF_GON_RSP ++#define P2P_TYPE_MNCONF P2P_PAF_GON_CONF ++ ++/* WiFi P2P IE subelement: Notice of Absence */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_noa_desc { ++ uint8 cnt_type; /* Count/Type */ ++ uint32 duration; /* Duration */ ++ uint32 interval; /* Interval */ ++ uint32 start; /* Start Time */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_noa_desc wifi_p2p_noa_desc_t; ++ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_noa_se { ++ uint8 eltId; /* Subelement ID */ ++ uint8 len[2]; /* Length */ ++ uint8 index; /* Index */ ++ uint8 ops_ctw_parms; /* CTWindow and OppPS Parameters */ ++ wifi_p2p_noa_desc_t desc[1]; /* Notice of Absence Descriptor(s) */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_noa_se wifi_p2p_noa_se_t; ++ ++#define P2P_NOA_SE_FIXED_LEN 5 ++ ++/* cnt_type field values */ ++#define P2P_NOA_DESC_CNT_RESERVED 0 /* reserved and should not be used */ ++#define P2P_NOA_DESC_CNT_REPEAT 255 /* continuous schedule */ ++#define P2P_NOA_DESC_TYPE_PREFERRED 1 /* preferred values */ ++#define P2P_NOA_DESC_TYPE_ACCEPTABLE 2 /* acceptable limits */ ++ ++/* ctw_ops_parms field values */ ++#define P2P_NOA_CTW_MASK 0x7f ++#define P2P_NOA_OPS_MASK 0x80 ++#define P2P_NOA_OPS_SHIFT 7 ++ ++#define P2P_CTW_MIN 10 /* minimum 10TU */ ++ ++/* ++ * P2P Service Discovery related ++ */ ++#define P2PSD_ACTION_CATEGORY 0x04 ++ /* Public action frame */ ++#define P2PSD_ACTION_ID_GAS_IREQ 0x0a ++ /* Action value for GAS Initial Request AF */ ++#define P2PSD_ACTION_ID_GAS_IRESP 0x0b ++ /* Action value for GAS Initial Response AF */ ++#define P2PSD_ACTION_ID_GAS_CREQ 0x0c ++ /* Action value for GAS Comback Request AF */ ++#define P2PSD_ACTION_ID_GAS_CRESP 0x0d ++ /* Action value for GAS Comback Response AF */ ++#define P2PSD_AD_EID 0x6c ++ /* Advertisement Protocol IE ID */ ++#define P2PSD_ADP_TUPLE_QLMT_PAMEBI 0x00 ++ /* Query Response Length Limit 7 bits plus PAME-BI 1 bit */ ++#define P2PSD_ADP_PROTO_ID 0x00 ++ /* Advertisement Protocol ID. Always 0 for P2P SD */ ++#define P2PSD_GAS_OUI P2P_OUI ++ /* WFA OUI */ ++#define P2PSD_GAS_OUI_SUBTYPE P2P_VER ++ /* OUI Subtype for GAS IE */ ++#define P2PSD_GAS_NQP_INFOID 0xDDDD ++ /* NQP Query Info ID: 56797 */ ++#define P2PSD_GAS_COMEBACKDEALY 0x00 ++ /* Not used in the Native GAS protocol */ ++ ++/* Service Protocol Type */ ++typedef enum p2psd_svc_protype { ++ SVC_RPOTYPE_ALL = 0, ++ SVC_RPOTYPE_BONJOUR = 1, ++ SVC_RPOTYPE_UPNP = 2, ++ SVC_RPOTYPE_WSD = 3, ++ SVC_RPOTYPE_VENDOR = 255 ++} p2psd_svc_protype_t; ++ ++/* Service Discovery response status code */ ++typedef enum { ++ P2PSD_RESP_STATUS_SUCCESS = 0, ++ P2PSD_RESP_STATUS_PROTYPE_NA = 1, ++ P2PSD_RESP_STATUS_DATA_NA = 2, ++ P2PSD_RESP_STATUS_BAD_REQUEST = 3 ++} p2psd_resp_status_t; ++ ++/* Advertisement Protocol IE tuple field */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_adp_tpl { ++ uint8 llm_pamebi; /* Query Response Length Limit bit 0-6, set to 0 plus ++ * Pre-Associated Message Exchange BSSID Independent bit 7, set to 0 ++ */ ++ uint8 adp_id; /* Advertisement Protocol ID: 0 for NQP Native Query Protocol */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_adp_tpl wifi_p2psd_adp_tpl_t; ++ ++/* Advertisement Protocol IE */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_adp_ie { ++ uint8 id; /* IE ID: 0x6c - 108 */ ++ uint8 len; /* IE length */ ++ wifi_p2psd_adp_tpl_t adp_tpl; /* Advertisement Protocol Tuple field. Only one ++ * tuple is defined for P2P Service Discovery ++ */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_adp_ie wifi_p2psd_adp_ie_t; ++ ++/* NQP Vendor-specific Content */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_nqp_query_vsc { ++ uint8 oui_subtype; /* OUI Subtype: 0x09 */ ++ uint16 svc_updi; /* Service Update Indicator */ ++ uint8 svc_tlvs[1]; /* wifi_p2psd_qreq_tlv_t type for service request, ++ * wifi_p2psd_qresp_tlv_t type for service response ++ */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_nqp_query_vsc wifi_p2psd_nqp_query_vsc_t; ++ ++/* Service Request TLV */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qreq_tlv { ++ uint16 len; /* Length: 5 plus size of Query Data */ ++ uint8 svc_prot; /* Service Protocol Type */ ++ uint8 svc_tscid; /* Service Transaction ID */ ++ uint8 query_data[1]; /* Query Data, passed in from above Layer 2 */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_qreq_tlv wifi_p2psd_qreq_tlv_t; ++ ++/* Query Request Frame, defined in generic format, instead of NQP specific */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qreq_frame { ++ uint16 info_id; /* Info ID: 0xDDDD */ ++ uint16 len; /* Length of service request TLV, 5 plus the size of request data */ ++ uint8 oui[3]; /* WFA OUI: 0x0050F2 */ ++ uint8 qreq_vsc[1]; /* Vendor-specific Content: wifi_p2psd_nqp_query_vsc_t type for NQP */ ++ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_qreq_frame wifi_p2psd_qreq_frame_t; ++ ++/* GAS Initial Request AF body, "elts" in wifi_p2p_pub_act_frame */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_ireq_frame { ++ wifi_p2psd_adp_ie_t adp_ie; /* Advertisement Protocol IE */ ++ uint16 qreq_len; /* Query Request Length */ ++ uint8 qreq_frm[1]; /* Query Request Frame wifi_p2psd_qreq_frame_t */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_gas_ireq_frame wifi_p2psd_gas_ireq_frame_t; ++ ++/* Service Response TLV */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qresp_tlv { ++ uint16 len; /* Length: 5 plus size of Query Data */ ++ uint8 svc_prot; /* Service Protocol Type */ ++ uint8 svc_tscid; /* Service Transaction ID */ ++ uint8 status; /* Value defined in Table 57 of P2P spec. */ ++ uint8 query_data[1]; /* Response Data, passed in from above Layer 2 */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_qresp_tlv wifi_p2psd_qresp_tlv_t; ++ ++/* Query Response Frame, defined in generic format, instead of NQP specific */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qresp_frame { ++ uint16 info_id; /* Info ID: 0xDDDD */ ++ uint16 len; /* Lenth of service response TLV, 6 plus the size of resp data */ ++ uint8 oui[3]; /* WFA OUI: 0x0050F2 */ ++ uint8 qresp_vsc[1]; /* Vendor-specific Content: wifi_p2psd_qresp_tlv_t type for NQP */ ++ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_qresp_frame wifi_p2psd_qresp_frame_t; ++ ++/* GAS Initial Response AF body, "elts" in wifi_p2p_pub_act_frame */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_iresp_frame { ++ uint16 status; /* Value defined in Table 7-23 of IEEE P802.11u */ ++ uint16 cb_delay; /* GAS Comeback Delay */ ++ wifi_p2psd_adp_ie_t adp_ie; /* Advertisement Protocol IE */ ++ uint16 qresp_len; /* Query Response Length */ ++ uint8 qresp_frm[1]; /* Query Response Frame wifi_p2psd_qresp_frame_t */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_gas_iresp_frame wifi_p2psd_gas_iresp_frame_t; ++ ++/* GAS Comeback Response AF body, "elts" in wifi_p2p_pub_act_frame */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_cresp_frame { ++ uint16 status; /* Value defined in Table 7-23 of IEEE P802.11u */ ++ uint8 fragment_id; /* Fragmentation ID */ ++ uint16 cb_delay; /* GAS Comeback Delay */ ++ wifi_p2psd_adp_ie_t adp_ie; /* Advertisement Protocol IE */ ++ uint16 qresp_len; /* Query Response Length */ ++ uint8 qresp_frm[1]; /* Query Response Frame wifi_p2psd_qresp_frame_t */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_gas_cresp_frame wifi_p2psd_gas_cresp_frame_t; ++ ++/* Wi-Fi GAS Public Action Frame */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_pub_act_frame { ++ uint8 category; /* 0x04 Public Action Frame */ ++ uint8 action; /* 0x6c Advertisement Protocol */ ++ uint8 dialog_token; /* nonzero, identifies req/rsp transaction */ ++ uint8 query_data[1]; /* Query Data. wifi_p2psd_gas_ireq_frame_t ++ * or wifi_p2psd_gas_iresp_frame_t format ++ */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_gas_pub_act_frame wifi_p2psd_gas_pub_act_frame_t; ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _P2P_H_ */ +diff --git a/drivers/net/wireless/ap6210/include/proto/sdspi.h b/drivers/net/wireless/ap6210/include/proto/sdspi.h +new file mode 100755 +index 0000000..a4900ed +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/proto/sdspi.h +@@ -0,0 +1,75 @@ ++/* ++ * SD-SPI Protocol Standard ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: sdspi.h 241182 2011-02-17 21:50:03Z $ ++ */ ++#ifndef _SD_SPI_H ++#define _SD_SPI_H ++ ++#define SPI_START_M BITFIELD_MASK(1) /* Bit [31] - Start Bit */ ++#define SPI_START_S 31 ++#define SPI_DIR_M BITFIELD_MASK(1) /* Bit [30] - Direction */ ++#define SPI_DIR_S 30 ++#define SPI_CMD_INDEX_M BITFIELD_MASK(6) /* Bits [29:24] - Command number */ ++#define SPI_CMD_INDEX_S 24 ++#define SPI_RW_M BITFIELD_MASK(1) /* Bit [23] - Read=0, Write=1 */ ++#define SPI_RW_S 23 ++#define SPI_FUNC_M BITFIELD_MASK(3) /* Bits [22:20] - Function Number */ ++#define SPI_FUNC_S 20 ++#define SPI_RAW_M BITFIELD_MASK(1) /* Bit [19] - Read After Wr */ ++#define SPI_RAW_S 19 ++#define SPI_STUFF_M BITFIELD_MASK(1) /* Bit [18] - Stuff bit */ ++#define SPI_STUFF_S 18 ++#define SPI_BLKMODE_M BITFIELD_MASK(1) /* Bit [19] - Blockmode 1=blk */ ++#define SPI_BLKMODE_S 19 ++#define SPI_OPCODE_M BITFIELD_MASK(1) /* Bit [18] - OP Code */ ++#define SPI_OPCODE_S 18 ++#define SPI_ADDR_M BITFIELD_MASK(17) /* Bits [17:1] - Address */ ++#define SPI_ADDR_S 1 ++#define SPI_STUFF0_M BITFIELD_MASK(1) /* Bit [0] - Stuff bit */ ++#define SPI_STUFF0_S 0 ++ ++#define SPI_RSP_START_M BITFIELD_MASK(1) /* Bit [7] - Start Bit (always 0) */ ++#define SPI_RSP_START_S 7 ++#define SPI_RSP_PARAM_ERR_M BITFIELD_MASK(1) /* Bit [6] - Parameter Error */ ++#define SPI_RSP_PARAM_ERR_S 6 ++#define SPI_RSP_RFU5_M BITFIELD_MASK(1) /* Bit [5] - RFU (Always 0) */ ++#define SPI_RSP_RFU5_S 5 ++#define SPI_RSP_FUNC_ERR_M BITFIELD_MASK(1) /* Bit [4] - Function number error */ ++#define SPI_RSP_FUNC_ERR_S 4 ++#define SPI_RSP_CRC_ERR_M BITFIELD_MASK(1) /* Bit [3] - COM CRC Error */ ++#define SPI_RSP_CRC_ERR_S 3 ++#define SPI_RSP_ILL_CMD_M BITFIELD_MASK(1) /* Bit [2] - Illegal Command error */ ++#define SPI_RSP_ILL_CMD_S 2 ++#define SPI_RSP_RFU1_M BITFIELD_MASK(1) /* Bit [1] - RFU (Always 0) */ ++#define SPI_RSP_RFU1_S 1 ++#define SPI_RSP_IDLE_M BITFIELD_MASK(1) /* Bit [0] - In idle state */ ++#define SPI_RSP_IDLE_S 0 ++ ++/* SD-SPI Protocol Definitions */ ++#define SDSPI_COMMAND_LEN 6 /* Number of bytes in an SD command */ ++#define SDSPI_START_BLOCK 0xFE /* SD Start Block Token */ ++#define SDSPI_IDLE_PAD 0xFF /* SD-SPI idle value for MOSI */ ++#define SDSPI_START_BIT_MASK 0x80 ++ ++#endif /* _SD_SPI_H */ +diff --git a/drivers/net/wireless/ap6210/include/proto/vlan.h b/drivers/net/wireless/ap6210/include/proto/vlan.h +new file mode 100755 +index 0000000..88502bf +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/proto/vlan.h +@@ -0,0 +1,69 @@ ++/* ++ * 802.1Q VLAN protocol definitions ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: vlan.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _vlan_h_ ++#define _vlan_h_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#define VLAN_VID_MASK 0xfff /* low 12 bits are vlan id */ ++#define VLAN_CFI_SHIFT 12 /* canonical format indicator bit */ ++#define VLAN_PRI_SHIFT 13 /* user priority */ ++ ++#define VLAN_PRI_MASK 7 /* 3 bits of priority */ ++ ++#define VLAN_TAG_LEN 4 ++#define VLAN_TAG_OFFSET (2 * ETHER_ADDR_LEN) /* offset in Ethernet II packet only */ ++ ++#define VLAN_TPID 0x8100 /* VLAN ethertype/Tag Protocol ID */ ++ ++struct ethervlan_header { ++ uint8 ether_dhost[ETHER_ADDR_LEN]; ++ uint8 ether_shost[ETHER_ADDR_LEN]; ++ uint16 vlan_type; /* 0x8100 */ ++ uint16 vlan_tag; /* priority, cfi and vid */ ++ uint16 ether_type; ++}; ++ ++#define ETHERVLAN_HDR_LEN (ETHER_HDR_LEN + VLAN_TAG_LEN) ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#define ETHERVLAN_MOVE_HDR(d, s) \ ++do { \ ++ struct ethervlan_header t; \ ++ t = *(struct ethervlan_header *)(s); \ ++ *(struct ethervlan_header *)(d) = t; \ ++} while (0) ++ ++#endif /* _vlan_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/proto/wpa.h b/drivers/net/wireless/ap6210/include/proto/wpa.h +new file mode 100755 +index 0000000..23ab8d6 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/proto/wpa.h +@@ -0,0 +1,206 @@ ++/* ++ * Fundamental types and constants relating to WPA ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: wpa.h 261155 2011-05-23 23:51:32Z $ ++ */ ++ ++#ifndef _proto_wpa_h_ ++#define _proto_wpa_h_ ++ ++#include ++#include ++ ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++/* Reason Codes */ ++ ++/* 13 through 23 taken from IEEE Std 802.11i-2004 */ ++#define DOT11_RC_INVALID_WPA_IE 13 /* Invalid info. element */ ++#define DOT11_RC_MIC_FAILURE 14 /* Michael failure */ ++#define DOT11_RC_4WH_TIMEOUT 15 /* 4-way handshake timeout */ ++#define DOT11_RC_GTK_UPDATE_TIMEOUT 16 /* Group key update timeout */ ++#define DOT11_RC_WPA_IE_MISMATCH 17 /* WPA IE in 4-way handshake differs from ++ * (re-)assoc. request/probe response ++ */ ++#define DOT11_RC_INVALID_MC_CIPHER 18 /* Invalid multicast cipher */ ++#define DOT11_RC_INVALID_UC_CIPHER 19 /* Invalid unicast cipher */ ++#define DOT11_RC_INVALID_AKMP 20 /* Invalid authenticated key management protocol */ ++#define DOT11_RC_BAD_WPA_VERSION 21 /* Unsupported WPA version */ ++#define DOT11_RC_INVALID_WPA_CAP 22 /* Invalid WPA IE capabilities */ ++#define DOT11_RC_8021X_AUTH_FAIL 23 /* 802.1X authentication failure */ ++ ++#define WPA2_PMKID_LEN 16 ++ ++/* WPA IE fixed portion */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint8 tag; /* TAG */ ++ uint8 length; /* TAG length */ ++ uint8 oui[3]; /* IE OUI */ ++ uint8 oui_type; /* OUI type */ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT version; /* IE version */ ++} BWL_POST_PACKED_STRUCT wpa_ie_fixed_t; ++#define WPA_IE_OUITYPE_LEN 4 ++#define WPA_IE_FIXED_LEN 8 ++#define WPA_IE_TAG_FIXED_LEN 6 ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint8 tag; /* TAG */ ++ uint8 length; /* TAG length */ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT version; /* IE version */ ++} BWL_POST_PACKED_STRUCT wpa_rsn_ie_fixed_t; ++#define WPA_RSN_IE_FIXED_LEN 4 ++#define WPA_RSN_IE_TAG_FIXED_LEN 2 ++typedef uint8 wpa_pmkid_t[WPA2_PMKID_LEN]; ++ ++/* WPA suite/multicast suite */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint8 oui[3]; ++ uint8 type; ++} BWL_POST_PACKED_STRUCT wpa_suite_t, wpa_suite_mcast_t; ++#define WPA_SUITE_LEN 4 ++ ++/* WPA unicast suite list/key management suite list */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT count; ++ wpa_suite_t list[1]; ++} BWL_POST_PACKED_STRUCT wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t; ++#define WPA_IE_SUITE_COUNT_LEN 2 ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT count; ++ wpa_pmkid_t list[1]; ++} BWL_POST_PACKED_STRUCT wpa_pmkid_list_t; ++ ++/* WPA cipher suites */ ++#define WPA_CIPHER_NONE 0 /* None */ ++#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */ ++#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */ ++#define WPA_CIPHER_AES_OCB 3 /* AES (OCB) */ ++#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */ ++#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */ ++#define WPA_CIPHER_BIP 6 /* WEP (104-bit) */ ++#define WPA_CIPHER_TPK 7 /* Group addressed traffic not allowed */ ++#ifdef BCMWAPI_WPI ++#define WAPI_CIPHER_NONE WPA_CIPHER_NONE ++#define WAPI_CIPHER_SMS4 11 ++ ++#define WAPI_CSE_WPI_SMS4 1 ++#endif /* BCMWAPI_WPI */ ++ ++ ++#define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \ ++ (cipher) == WPA_CIPHER_WEP_40 || \ ++ (cipher) == WPA_CIPHER_WEP_104 || \ ++ (cipher) == WPA_CIPHER_TKIP || \ ++ (cipher) == WPA_CIPHER_AES_OCB || \ ++ (cipher) == WPA_CIPHER_AES_CCM || \ ++ (cipher) == WPA_CIPHER_TPK) ++ ++#ifdef BCMWAPI_WAI ++#define IS_WAPI_CIPHER(cipher) ((cipher) == WAPI_CIPHER_NONE || \ ++ (cipher) == WAPI_CSE_WPI_SMS4) ++ ++/* convert WAPI_CSE_WPI_XXX to WAPI_CIPHER_XXX */ ++#define WAPI_CSE_WPI_2_CIPHER(cse) ((cse) == WAPI_CSE_WPI_SMS4 ? \ ++ WAPI_CIPHER_SMS4 : WAPI_CIPHER_NONE) ++ ++#define WAPI_CIPHER_2_CSE_WPI(cipher) ((cipher) == WAPI_CIPHER_SMS4 ? \ ++ WAPI_CSE_WPI_SMS4 : WAPI_CIPHER_NONE) ++#endif /* BCMWAPI_WAI */ ++ ++ ++/* WPA TKIP countermeasures parameters */ ++#define WPA_TKIP_CM_DETECT 60 /* multiple MIC failure window (seconds) */ ++#define WPA_TKIP_CM_BLOCK 60 /* countermeasures active window (seconds) */ ++ ++/* RSN IE defines */ ++#define RSN_CAP_LEN 2 /* Length of RSN capabilities field (2 octets) */ ++ ++/* RSN Capabilities defined in 802.11i */ ++#define RSN_CAP_PREAUTH 0x0001 ++#define RSN_CAP_NOPAIRWISE 0x0002 ++#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C ++#define RSN_CAP_PTK_REPLAY_CNTR_SHIFT 2 ++#define RSN_CAP_GTK_REPLAY_CNTR_MASK 0x0030 ++#define RSN_CAP_GTK_REPLAY_CNTR_SHIFT 4 ++#define RSN_CAP_1_REPLAY_CNTR 0 ++#define RSN_CAP_2_REPLAY_CNTRS 1 ++#define RSN_CAP_4_REPLAY_CNTRS 2 ++#define RSN_CAP_16_REPLAY_CNTRS 3 ++#ifdef MFP ++#define RSN_CAP_MFPR 0x0040 ++#define RSN_CAP_MFPC 0x0080 ++#endif ++ ++/* WPA capabilities defined in 802.11i */ ++#define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS ++#define WPA_CAP_16_REPLAY_CNTRS RSN_CAP_16_REPLAY_CNTRS ++#define WPA_CAP_REPLAY_CNTR_SHIFT RSN_CAP_PTK_REPLAY_CNTR_SHIFT ++#define WPA_CAP_REPLAY_CNTR_MASK RSN_CAP_PTK_REPLAY_CNTR_MASK ++ ++/* WPA capabilities defined in 802.11zD9.0 */ ++#define WPA_CAP_PEER_KEY_ENABLE (0x1 << 1) /* bit 9 */ ++ ++/* WPA Specific defines */ ++#define WPA_CAP_LEN RSN_CAP_LEN /* Length of RSN capabilities in RSN IE (2 octets) */ ++#define WPA_PMKID_CNT_LEN 2 /* Length of RSN PMKID count (2 octests) */ ++ ++#define WPA_CAP_WPA2_PREAUTH RSN_CAP_PREAUTH ++ ++#ifdef BCMWAPI_WAI ++#define WAPI_CAP_PREAUTH RSN_CAP_PREAUTH ++ ++/* Other WAI definition */ ++#define WAPI_WAI_REQUEST 0x00F1 ++#define WAPI_UNICAST_REKEY 0x00F2 ++#define WAPI_STA_AGING 0x00F3 ++#define WAPI_MUTIL_REKEY 0x00F4 ++#define WAPI_STA_STATS 0x00F5 ++ ++#define WAPI_USK_REKEY_COUNT 0x4000000 /* 0xA00000 */ ++#define WAPI_MSK_REKEY_COUNT 0x4000000 /* 0xA00000 */ ++#endif /* BCMWAPI_WAI */ ++#define WPA2_PMKID_COUNT_LEN 2 ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _proto_wpa_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/sbchipc.h b/drivers/net/wireless/ap6210/include/sbchipc.h +new file mode 100755 +index 0000000..c694291 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/sbchipc.h +@@ -0,0 +1,2405 @@ ++/* ++ * SiliconBackplane Chipcommon core hardware definitions. ++ * ++ * The chipcommon core provides chip identification, SB control, ++ * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer, ++ * GPIO interface, extbus, and support for serial and parallel flashes. ++ * ++ * $Id: sbchipc.h 347614 2012-07-27 10:24:51Z $ ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ */ ++ ++#ifndef _SBCHIPC_H ++#define _SBCHIPC_H ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++typedef struct eci_prerev35 { ++ uint32 eci_output; ++ uint32 eci_control; ++ uint32 eci_inputlo; ++ uint32 eci_inputmi; ++ uint32 eci_inputhi; ++ uint32 eci_inputintpolaritylo; ++ uint32 eci_inputintpolaritymi; ++ uint32 eci_inputintpolarityhi; ++ uint32 eci_intmasklo; ++ uint32 eci_intmaskmi; ++ uint32 eci_intmaskhi; ++ uint32 eci_eventlo; ++ uint32 eci_eventmi; ++ uint32 eci_eventhi; ++ uint32 eci_eventmasklo; ++ uint32 eci_eventmaskmi; ++ uint32 eci_eventmaskhi; ++ uint32 PAD[3]; ++} eci_prerev35_t; ++ ++typedef struct eci_rev35 { ++ uint32 eci_outputlo; ++ uint32 eci_outputhi; ++ uint32 eci_controllo; ++ uint32 eci_controlhi; ++ uint32 eci_inputlo; ++ uint32 eci_inputhi; ++ uint32 eci_inputintpolaritylo; ++ uint32 eci_inputintpolarityhi; ++ uint32 eci_intmasklo; ++ uint32 eci_intmaskhi; ++ uint32 eci_eventlo; ++ uint32 eci_eventhi; ++ uint32 eci_eventmasklo; ++ uint32 eci_eventmaskhi; ++ uint32 eci_auxtx; ++ uint32 eci_auxrx; ++ uint32 eci_datatag; ++ uint32 eci_uartescvalue; ++ uint32 eci_autobaudctr; ++ uint32 eci_uartfifolevel; ++} eci_rev35_t; ++ ++typedef struct flash_config { ++ uint32 PAD[19]; ++ /* Flash struct configuration registers (0x18c) for BCM4706 (corerev = 31) */ ++ uint32 flashstrconfig; ++} flash_config_t; ++ ++typedef volatile struct { ++ uint32 chipid; /* 0x0 */ ++ uint32 capabilities; ++ uint32 corecontrol; /* corerev >= 1 */ ++ uint32 bist; ++ ++ /* OTP */ ++ uint32 otpstatus; /* 0x10, corerev >= 10 */ ++ uint32 otpcontrol; ++ uint32 otpprog; ++ uint32 otplayout; /* corerev >= 23 */ ++ ++ /* Interrupt control */ ++ uint32 intstatus; /* 0x20 */ ++ uint32 intmask; ++ ++ /* Chip specific regs */ ++ uint32 chipcontrol; /* 0x28, rev >= 11 */ ++ uint32 chipstatus; /* 0x2c, rev >= 11 */ ++ ++ /* Jtag Master */ ++ uint32 jtagcmd; /* 0x30, rev >= 10 */ ++ uint32 jtagir; ++ uint32 jtagdr; ++ uint32 jtagctrl; ++ ++ /* serial flash interface registers */ ++ uint32 flashcontrol; /* 0x40 */ ++ uint32 flashaddress; ++ uint32 flashdata; ++ uint32 otplayoutextension; /* rev >= 35 */ ++ ++ /* Silicon backplane configuration broadcast control */ ++ uint32 broadcastaddress; /* 0x50 */ ++ uint32 broadcastdata; ++ ++ /* gpio - cleared only by power-on-reset */ ++ uint32 gpiopullup; /* 0x58, corerev >= 20 */ ++ uint32 gpiopulldown; /* 0x5c, corerev >= 20 */ ++ uint32 gpioin; /* 0x60 */ ++ uint32 gpioout; /* 0x64 */ ++ uint32 gpioouten; /* 0x68 */ ++ uint32 gpiocontrol; /* 0x6C */ ++ uint32 gpiointpolarity; /* 0x70 */ ++ uint32 gpiointmask; /* 0x74 */ ++ ++ /* GPIO events corerev >= 11 */ ++ uint32 gpioevent; ++ uint32 gpioeventintmask; ++ ++ /* Watchdog timer */ ++ uint32 watchdog; /* 0x80 */ ++ ++ /* GPIO events corerev >= 11 */ ++ uint32 gpioeventintpolarity; ++ ++ /* GPIO based LED powersave registers corerev >= 16 */ ++ uint32 gpiotimerval; /* 0x88 */ ++ uint32 gpiotimeroutmask; ++ ++ /* clock control */ ++ uint32 clockcontrol_n; /* 0x90 */ ++ uint32 clockcontrol_sb; /* aka m0 */ ++ uint32 clockcontrol_pci; /* aka m1 */ ++ uint32 clockcontrol_m2; /* mii/uart/mipsref */ ++ uint32 clockcontrol_m3; /* cpu */ ++ uint32 clkdiv; /* corerev >= 3 */ ++ uint32 gpiodebugsel; /* corerev >= 28 */ ++ uint32 capabilities_ext; /* 0xac */ ++ ++ /* pll delay registers (corerev >= 4) */ ++ uint32 pll_on_delay; /* 0xb0 */ ++ uint32 fref_sel_delay; ++ uint32 slow_clk_ctl; /* 5 < corerev < 10 */ ++ uint32 PAD; ++ ++ /* Instaclock registers (corerev >= 10) */ ++ uint32 system_clk_ctl; /* 0xc0 */ ++ uint32 clkstatestretch; ++ uint32 PAD[2]; ++ ++ /* Indirect backplane access (corerev >= 22) */ ++ uint32 bp_addrlow; /* 0xd0 */ ++ uint32 bp_addrhigh; ++ uint32 bp_data; ++ uint32 PAD; ++ uint32 bp_indaccess; ++ /* SPI registers, corerev >= 37 */ ++ uint32 gsioctrl; ++ uint32 gsioaddress; ++ uint32 gsiodata; ++ ++ /* More clock dividers (corerev >= 32) */ ++ uint32 clkdiv2; ++ /* FAB ID (corerev >= 40) */ ++ uint32 otpcontrol1; ++ uint32 fabid; /* 0xf8 */ ++ ++ /* In AI chips, pointer to erom */ ++ uint32 eromptr; /* 0xfc */ ++ ++ /* ExtBus control registers (corerev >= 3) */ ++ uint32 pcmcia_config; /* 0x100 */ ++ uint32 pcmcia_memwait; ++ uint32 pcmcia_attrwait; ++ uint32 pcmcia_iowait; ++ uint32 ide_config; ++ uint32 ide_memwait; ++ uint32 ide_attrwait; ++ uint32 ide_iowait; ++ uint32 prog_config; ++ uint32 prog_waitcount; ++ uint32 flash_config; ++ uint32 flash_waitcount; ++ uint32 SECI_config; /* 0x130 SECI configuration */ ++ uint32 SECI_status; ++ uint32 SECI_statusmask; ++ uint32 SECI_rxnibchanged; ++ ++ uint32 PAD[20]; ++ ++ /* SROM interface (corerev >= 32) */ ++ uint32 sromcontrol; /* 0x190 */ ++ uint32 sromaddress; ++ uint32 sromdata; ++ uint32 PAD[1]; /* 0x19C */ ++ /* NAND flash registers for BCM4706 (corerev = 31) */ ++ uint32 nflashctrl; /* 0x1a0 */ ++ uint32 nflashconf; ++ uint32 nflashcoladdr; ++ uint32 nflashrowaddr; ++ uint32 nflashdata; ++ uint32 nflashwaitcnt0; /* 0x1b4 */ ++ uint32 PAD[2]; ++ ++ uint32 seci_uart_data; /* 0x1C0 */ ++ uint32 seci_uart_bauddiv; ++ uint32 seci_uart_fcr; ++ uint32 seci_uart_lcr; ++ uint32 seci_uart_mcr; ++ uint32 seci_uart_lsr; ++ uint32 seci_uart_msr; ++ uint32 seci_uart_baudadj; ++ /* Clock control and hardware workarounds (corerev >= 20) */ ++ uint32 clk_ctl_st; /* 0x1e0 */ ++ uint32 hw_war; ++ uint32 PAD[70]; ++ ++ /* UARTs */ ++ uint8 uart0data; /* 0x300 */ ++ uint8 uart0imr; ++ uint8 uart0fcr; ++ uint8 uart0lcr; ++ uint8 uart0mcr; ++ uint8 uart0lsr; ++ uint8 uart0msr; ++ uint8 uart0scratch; ++ uint8 PAD[248]; /* corerev >= 1 */ ++ ++ uint8 uart1data; /* 0x400 */ ++ uint8 uart1imr; ++ uint8 uart1fcr; ++ uint8 uart1lcr; ++ uint8 uart1mcr; ++ uint8 uart1lsr; ++ uint8 uart1msr; ++ uint8 uart1scratch; ++ uint32 PAD[126]; ++ ++ /* PMU registers (corerev >= 20) */ ++ /* Note: all timers driven by ILP clock are updated asynchronously to HT/ALP. ++ * The CPU must read them twice, compare, and retry if different. ++ */ ++ uint32 pmucontrol; /* 0x600 */ ++ uint32 pmucapabilities; ++ uint32 pmustatus; ++ uint32 res_state; ++ uint32 res_pending; ++ uint32 pmutimer; ++ uint32 min_res_mask; ++ uint32 max_res_mask; ++ uint32 res_table_sel; ++ uint32 res_dep_mask; ++ uint32 res_updn_timer; ++ uint32 res_timer; ++ uint32 clkstretch; ++ uint32 pmuwatchdog; ++ uint32 gpiosel; /* 0x638, rev >= 1 */ ++ uint32 gpioenable; /* 0x63c, rev >= 1 */ ++ uint32 res_req_timer_sel; ++ uint32 res_req_timer; ++ uint32 res_req_mask; ++ uint32 PAD; ++ uint32 chipcontrol_addr; /* 0x650 */ ++ uint32 chipcontrol_data; /* 0x654 */ ++ uint32 regcontrol_addr; ++ uint32 regcontrol_data; ++ uint32 pllcontrol_addr; ++ uint32 pllcontrol_data; ++ uint32 pmustrapopt; /* 0x668, corerev >= 28 */ ++ uint32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ ++ uint32 retention_ctl; /* 0x670 */ ++ uint32 PAD[3]; ++ uint32 retention_grpidx; /* 0x680 */ ++ uint32 retention_grpctl; /* 0x684 */ ++ uint32 PAD[94]; ++ uint16 sromotp[512]; /* 0x800 */ ++#ifdef NFLASH_SUPPORT ++ /* Nand flash MLC controller registers (corerev >= 38) */ ++ uint32 nand_revision; /* 0xC00 */ ++ uint32 nand_cmd_start; ++ uint32 nand_cmd_addr_x; ++ uint32 nand_cmd_addr; ++ uint32 nand_cmd_end_addr; ++ uint32 nand_cs_nand_select; ++ uint32 nand_cs_nand_xor; ++ uint32 PAD; ++ uint32 nand_spare_rd0; ++ uint32 nand_spare_rd4; ++ uint32 nand_spare_rd8; ++ uint32 nand_spare_rd12; ++ uint32 nand_spare_wr0; ++ uint32 nand_spare_wr4; ++ uint32 nand_spare_wr8; ++ uint32 nand_spare_wr12; ++ uint32 nand_acc_control; ++ uint32 PAD; ++ uint32 nand_config; ++ uint32 PAD; ++ uint32 nand_timing_1; ++ uint32 nand_timing_2; ++ uint32 nand_semaphore; ++ uint32 PAD; ++ uint32 nand_devid; ++ uint32 nand_devid_x; ++ uint32 nand_block_lock_status; ++ uint32 nand_intfc_status; ++ uint32 nand_ecc_corr_addr_x; ++ uint32 nand_ecc_corr_addr; ++ uint32 nand_ecc_unc_addr_x; ++ uint32 nand_ecc_unc_addr; ++ uint32 nand_read_error_count; ++ uint32 nand_corr_stat_threshold; ++ uint32 PAD[2]; ++ uint32 nand_read_addr_x; ++ uint32 nand_read_addr; ++ uint32 nand_page_program_addr_x; ++ uint32 nand_page_program_addr; ++ uint32 nand_copy_back_addr_x; ++ uint32 nand_copy_back_addr; ++ uint32 nand_block_erase_addr_x; ++ uint32 nand_block_erase_addr; ++ uint32 nand_inv_read_addr_x; ++ uint32 nand_inv_read_addr; ++ uint32 PAD[2]; ++ uint32 nand_blk_wr_protect; ++ uint32 PAD[3]; ++ uint32 nand_acc_control_cs1; ++ uint32 nand_config_cs1; ++ uint32 nand_timing_1_cs1; ++ uint32 nand_timing_2_cs1; ++ uint32 PAD[20]; ++ uint32 nand_spare_rd16; ++ uint32 nand_spare_rd20; ++ uint32 nand_spare_rd24; ++ uint32 nand_spare_rd28; ++ uint32 nand_cache_addr; ++ uint32 nand_cache_data; ++ uint32 nand_ctrl_config; ++ uint32 nand_ctrl_status; ++#endif /* NFLASH_SUPPORT */ ++ uint32 gci_corecaps0; /* GCI starting at 0xC00 */ ++ uint32 gci_corecaps1; ++ uint32 gci_corecaps2; ++ uint32 gci_corectrl; ++ uint32 gci_corestat; /* 0xC10 */ ++ uint32 PAD[11]; ++ uint32 gci_indirect_addr; /* 0xC40 */ ++ uint32 PAD[111]; ++ uint32 gci_chipctrl; /* 0xE00 */ ++} chipcregs_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++ ++#define CC_CHIPID 0 ++#define CC_CAPABILITIES 4 ++#define CC_CHIPST 0x2c ++#define CC_EROMPTR 0xfc ++ ++#define CC_OTPST 0x10 ++#define CC_JTAGCMD 0x30 ++#define CC_JTAGIR 0x34 ++#define CC_JTAGDR 0x38 ++#define CC_JTAGCTRL 0x3c ++#define CC_GPIOPU 0x58 ++#define CC_GPIOPD 0x5c ++#define CC_GPIOIN 0x60 ++#define CC_GPIOOUT 0x64 ++#define CC_GPIOOUTEN 0x68 ++#define CC_GPIOCTRL 0x6c ++#define CC_GPIOPOL 0x70 ++#define CC_GPIOINTM 0x74 ++#define CC_WATCHDOG 0x80 ++#define CC_CLKC_N 0x90 ++#define CC_CLKC_M0 0x94 ++#define CC_CLKC_M1 0x98 ++#define CC_CLKC_M2 0x9c ++#define CC_CLKC_M3 0xa0 ++#define CC_CLKDIV 0xa4 ++#define CC_SYS_CLK_CTL 0xc0 ++#define CC_CLK_CTL_ST SI_CLK_CTL_ST ++#define PMU_CTL 0x600 ++#define PMU_CAP 0x604 ++#define PMU_ST 0x608 ++#define PMU_RES_STATE 0x60c ++#define PMU_TIMER 0x614 ++#define PMU_MIN_RES_MASK 0x618 ++#define PMU_MAX_RES_MASK 0x61c ++#define CC_CHIPCTL_ADDR 0x650 ++#define CC_CHIPCTL_DATA 0x654 ++#define PMU_REG_CONTROL_ADDR 0x658 ++#define PMU_REG_CONTROL_DATA 0x65C ++#define PMU_PLL_CONTROL_ADDR 0x660 ++#define PMU_PLL_CONTROL_DATA 0x664 ++#define CC_SROM_OTP 0x800 /* SROM/OTP address space */ ++#define CC_GCI_INDIRECT_ADDR_REG 0xC40 ++#define CC_GCI_CHIP_CTRL_REG 0xE00 ++#define CC_GCI_CC_OFFSET_2 2 ++#define CC_GCI_CC_OFFSET_5 5 ++ ++#ifdef NFLASH_SUPPORT ++/* NAND flash support */ ++#define CC_NAND_REVISION 0xC00 ++#define CC_NAND_CMD_START 0xC04 ++#define CC_NAND_CMD_ADDR 0xC0C ++#define CC_NAND_SPARE_RD_0 0xC20 ++#define CC_NAND_SPARE_RD_4 0xC24 ++#define CC_NAND_SPARE_RD_8 0xC28 ++#define CC_NAND_SPARE_RD_C 0xC2C ++#define CC_NAND_CONFIG 0xC48 ++#define CC_NAND_DEVID 0xC60 ++#define CC_NAND_DEVID_EXT 0xC64 ++#define CC_NAND_INTFC_STATUS 0xC6C ++#endif /* NFLASH_SUPPORT */ ++ ++/* chipid */ ++#define CID_ID_MASK 0x0000ffff /* Chip Id mask */ ++#define CID_REV_MASK 0x000f0000 /* Chip Revision mask */ ++#define CID_REV_SHIFT 16 /* Chip Revision shift */ ++#define CID_PKG_MASK 0x00f00000 /* Package Option mask */ ++#define CID_PKG_SHIFT 20 /* Package Option shift */ ++#define CID_CC_MASK 0x0f000000 /* CoreCount (corerev >= 4) */ ++#define CID_CC_SHIFT 24 ++#define CID_TYPE_MASK 0xf0000000 /* Chip Type */ ++#define CID_TYPE_SHIFT 28 ++ ++/* capabilities */ ++#define CC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */ ++#define CC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ ++#define CC_CAP_UCLKSEL 0x00000018 /* UARTs clock select */ ++#define CC_CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */ ++#define CC_CAP_UARTGPIO 0x00000020 /* UARTs own GPIOs 15:12 */ ++#define CC_CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */ ++#define CC_CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */ ++#define CC_CAP_EXTBUS_FULL 0x00000040 /* ExtBus: PCMCIA, IDE & Prog */ ++#define CC_CAP_EXTBUS_PROG 0x00000080 /* ExtBus: ProgIf only */ ++#define CC_CAP_FLASH_MASK 0x00000700 /* Type of flash */ ++#define CC_CAP_PLL_MASK 0x00038000 /* Type of PLL */ ++#define CC_CAP_PWR_CTL 0x00040000 /* Power control */ ++#define CC_CAP_OTPSIZE 0x00380000 /* OTP Size (0 = none) */ ++#define CC_CAP_OTPSIZE_SHIFT 19 /* OTP Size shift */ ++#define CC_CAP_OTPSIZE_BASE 5 /* OTP Size base */ ++#define CC_CAP_JTAGP 0x00400000 /* JTAG Master Present */ ++#define CC_CAP_ROM 0x00800000 /* Internal boot rom active */ ++#define CC_CAP_BKPLN64 0x08000000 /* 64-bit backplane */ ++#define CC_CAP_PMU 0x10000000 /* PMU Present, rev >= 20 */ ++#define CC_CAP_ECI 0x20000000 /* ECI Present, rev >= 21 */ ++#define CC_CAP_SROM 0x40000000 /* Srom Present, rev >= 32 */ ++#define CC_CAP_NFLASH 0x80000000 /* Nand flash present, rev >= 35 */ ++ ++#define CC_CAP2_SECI 0x00000001 /* SECI Present, rev >= 36 */ ++#define CC_CAP2_GSIO 0x00000002 /* GSIO (spi/i2c) present, rev >= 37 */ ++ ++/* capabilities extension */ ++#define CC_CAP_EXT_SECI_PRESENT 0x00000001 /* SECI present */ ++ ++/* PLL type */ ++#define PLL_NONE 0x00000000 ++#define PLL_TYPE1 0x00010000 /* 48MHz base, 3 dividers */ ++#define PLL_TYPE2 0x00020000 /* 48MHz, 4 dividers */ ++#define PLL_TYPE3 0x00030000 /* 25MHz, 2 dividers */ ++#define PLL_TYPE4 0x00008000 /* 48MHz, 4 dividers */ ++#define PLL_TYPE5 0x00018000 /* 25MHz, 4 dividers */ ++#define PLL_TYPE6 0x00028000 /* 100/200 or 120/240 only */ ++#define PLL_TYPE7 0x00038000 /* 25MHz, 4 dividers */ ++ ++/* ILP clock */ ++#define ILP_CLOCK 32000 ++ ++/* ALP clock on pre-PMU chips */ ++#define ALP_CLOCK 20000000 ++ ++/* HT clock */ ++#define HT_CLOCK 80000000 ++ ++/* corecontrol */ ++#define CC_UARTCLKO 0x00000001 /* Drive UART with internal clock */ ++#define CC_SE 0x00000002 /* sync clk out enable (corerev >= 3) */ ++#define CC_ASYNCGPIO 0x00000004 /* 1=generate GPIO interrupt without backplane clock */ ++#define CC_UARTCLKEN 0x00000008 /* enable UART Clock (corerev > = 21 */ ++ ++/* 4321 chipcontrol */ ++#define CHIPCTRL_4321A0_DEFAULT 0x3a4 ++#define CHIPCTRL_4321A1_DEFAULT 0x0a4 ++#define CHIPCTRL_4321_PLL_DOWN 0x800000 /* serdes PLL down override */ ++ ++/* Fields in the otpstatus register in rev >= 21 */ ++#define OTPS_OL_MASK 0x000000ff ++#define OTPS_OL_MFG 0x00000001 /* manuf row is locked */ ++#define OTPS_OL_OR1 0x00000002 /* otp redundancy row 1 is locked */ ++#define OTPS_OL_OR2 0x00000004 /* otp redundancy row 2 is locked */ ++#define OTPS_OL_GU 0x00000008 /* general use region is locked */ ++#define OTPS_GUP_MASK 0x00000f00 ++#define OTPS_GUP_SHIFT 8 ++#define OTPS_GUP_HW 0x00000100 /* h/w subregion is programmed */ ++#define OTPS_GUP_SW 0x00000200 /* s/w subregion is programmed */ ++#define OTPS_GUP_CI 0x00000400 /* chipid/pkgopt subregion is programmed */ ++#define OTPS_GUP_FUSE 0x00000800 /* fuse subregion is programmed */ ++#define OTPS_READY 0x00001000 ++#define OTPS_RV(x) (1 << (16 + (x))) /* redundancy entry valid */ ++#define OTPS_RV_MASK 0x0fff0000 ++#define OTPS_PROGOK 0x40000000 ++ ++/* Fields in the otpcontrol register in rev >= 21 */ ++#define OTPC_PROGSEL 0x00000001 ++#define OTPC_PCOUNT_MASK 0x0000000e ++#define OTPC_PCOUNT_SHIFT 1 ++#define OTPC_VSEL_MASK 0x000000f0 ++#define OTPC_VSEL_SHIFT 4 ++#define OTPC_TMM_MASK 0x00000700 ++#define OTPC_TMM_SHIFT 8 ++#define OTPC_ODM 0x00000800 ++#define OTPC_PROGEN 0x80000000 ++ ++/* Fields in the 40nm otpcontrol register in rev >= 40 */ ++#define OTPC_40NM_PROGSEL_SHIFT 0 ++#define OTPC_40NM_PCOUNT_SHIFT 1 ++#define OTPC_40NM_PCOUNT_WR 0xA ++#define OTPC_40NM_PCOUNT_V1X 0xB ++#define OTPC_40NM_REGCSEL_SHIFT 5 ++#define OTPC_40NM_REGCSEL_DEF 0x4 ++#define OTPC_40NM_PROGIN_SHIFT 8 ++#define OTPC_40NM_R2X_SHIFT 10 ++#define OTPC_40NM_ODM_SHIFT 11 ++#define OTPC_40NM_DF_SHIFT 15 ++#define OTPC_40NM_VSEL_SHIFT 16 ++#define OTPC_40NM_VSEL_WR 0xA ++#define OTPC_40NM_VSEL_V1X 0xA ++#define OTPC_40NM_VSEL_R1X 0x5 ++#define OTPC_40NM_COFAIL_SHIFT 30 ++ ++#define OTPC1_CPCSEL_SHIFT 0 ++#define OTPC1_CPCSEL_DEF 6 ++#define OTPC1_TM_SHIFT 8 ++#define OTPC1_TM_WR 0x84 ++#define OTPC1_TM_V1X 0x84 ++#define OTPC1_TM_R1X 0x4 ++ ++/* Fields in otpprog in rev >= 21 and HND OTP */ ++#define OTPP_COL_MASK 0x000000ff ++#define OTPP_COL_SHIFT 0 ++#define OTPP_ROW_MASK 0x0000ff00 ++#define OTPP_ROW_SHIFT 8 ++#define OTPP_OC_MASK 0x0f000000 ++#define OTPP_OC_SHIFT 24 ++#define OTPP_READERR 0x10000000 ++#define OTPP_VALUE_MASK 0x20000000 ++#define OTPP_VALUE_SHIFT 29 ++#define OTPP_START_BUSY 0x80000000 ++#define OTPP_READ 0x40000000 /* HND OTP */ ++ ++/* Fields in otplayout register */ ++#define OTPL_HWRGN_OFF_MASK 0x00000FFF ++#define OTPL_HWRGN_OFF_SHIFT 0 ++#define OTPL_WRAP_REVID_MASK 0x00F80000 ++#define OTPL_WRAP_REVID_SHIFT 19 ++#define OTPL_WRAP_TYPE_MASK 0x00070000 ++#define OTPL_WRAP_TYPE_SHIFT 16 ++#define OTPL_WRAP_TYPE_65NM 0 ++#define OTPL_WRAP_TYPE_40NM 1 ++ ++/* otplayout reg corerev >= 36 */ ++#define OTP_CISFORMAT_NEW 0x80000000 ++ ++/* Opcodes for OTPP_OC field */ ++#define OTPPOC_READ 0 ++#define OTPPOC_BIT_PROG 1 ++#define OTPPOC_VERIFY 3 ++#define OTPPOC_INIT 4 ++#define OTPPOC_SET 5 ++#define OTPPOC_RESET 6 ++#define OTPPOC_OCST 7 ++#define OTPPOC_ROW_LOCK 8 ++#define OTPPOC_PRESCN_TEST 9 ++ ++/* Opcodes for OTPP_OC field (40NM) */ ++#define OTPPOC_READ_40NM 0 ++#define OTPPOC_PROG_ENABLE_40NM 1 ++#define OTPPOC_PROG_DISABLE_40NM 2 ++#define OTPPOC_VERIFY_40NM 3 ++#define OTPPOC_WORD_VERIFY_1_40NM 4 ++#define OTPPOC_ROW_LOCK_40NM 5 ++#define OTPPOC_STBY_40NM 6 ++#define OTPPOC_WAKEUP_40NM 7 ++#define OTPPOC_WORD_VERIFY_0_40NM 8 ++#define OTPPOC_PRESCN_TEST_40NM 9 ++#define OTPPOC_BIT_PROG_40NM 10 ++#define OTPPOC_WORDPROG_40NM 11 ++#define OTPPOC_BURNIN_40NM 12 ++#define OTPPOC_AUTORELOAD_40NM 13 ++#define OTPPOC_OVST_READ_40NM 14 ++#define OTPPOC_OVST_PROG_40NM 15 ++ ++/* Fields in otplayoutextension */ ++#define OTPLAYOUTEXT_FUSE_MASK 0x3FF ++ ++ ++/* Jtagm characteristics that appeared at a given corerev */ ++#define JTAGM_CREV_OLD 10 /* Old command set, 16bit max IR */ ++#define JTAGM_CREV_IRP 22 /* Able to do pause-ir */ ++#define JTAGM_CREV_RTI 28 /* Able to do return-to-idle */ ++ ++/* jtagcmd */ ++#define JCMD_START 0x80000000 ++#define JCMD_BUSY 0x80000000 ++#define JCMD_STATE_MASK 0x60000000 ++#define JCMD_STATE_TLR 0x00000000 /* Test-logic-reset */ ++#define JCMD_STATE_PIR 0x20000000 /* Pause IR */ ++#define JCMD_STATE_PDR 0x40000000 /* Pause DR */ ++#define JCMD_STATE_RTI 0x60000000 /* Run-test-idle */ ++#define JCMD0_ACC_MASK 0x0000f000 ++#define JCMD0_ACC_IRDR 0x00000000 ++#define JCMD0_ACC_DR 0x00001000 ++#define JCMD0_ACC_IR 0x00002000 ++#define JCMD0_ACC_RESET 0x00003000 ++#define JCMD0_ACC_IRPDR 0x00004000 ++#define JCMD0_ACC_PDR 0x00005000 ++#define JCMD0_IRW_MASK 0x00000f00 ++#define JCMD_ACC_MASK 0x000f0000 /* Changes for corerev 11 */ ++#define JCMD_ACC_IRDR 0x00000000 ++#define JCMD_ACC_DR 0x00010000 ++#define JCMD_ACC_IR 0x00020000 ++#define JCMD_ACC_RESET 0x00030000 ++#define JCMD_ACC_IRPDR 0x00040000 ++#define JCMD_ACC_PDR 0x00050000 ++#define JCMD_ACC_PIR 0x00060000 ++#define JCMD_ACC_IRDR_I 0x00070000 /* rev 28: return to run-test-idle */ ++#define JCMD_ACC_DR_I 0x00080000 /* rev 28: return to run-test-idle */ ++#define JCMD_IRW_MASK 0x00001f00 ++#define JCMD_IRW_SHIFT 8 ++#define JCMD_DRW_MASK 0x0000003f ++ ++/* jtagctrl */ ++#define JCTRL_FORCE_CLK 4 /* Force clock */ ++#define JCTRL_EXT_EN 2 /* Enable external targets */ ++#define JCTRL_EN 1 /* Enable Jtag master */ ++ ++/* Fields in clkdiv */ ++#define CLKD_SFLASH 0x0f000000 ++#define CLKD_SFLASH_SHIFT 24 ++#define CLKD_OTP 0x000f0000 ++#define CLKD_OTP_SHIFT 16 ++#define CLKD_JTAG 0x00000f00 ++#define CLKD_JTAG_SHIFT 8 ++#define CLKD_UART 0x000000ff ++ ++#define CLKD2_SROM 0x00000003 ++ ++/* intstatus/intmask */ ++#define CI_GPIO 0x00000001 /* gpio intr */ ++#define CI_EI 0x00000002 /* extif intr (corerev >= 3) */ ++#define CI_TEMP 0x00000004 /* temp. ctrl intr (corerev >= 15) */ ++#define CI_SIRQ 0x00000008 /* serial IRQ intr (corerev >= 15) */ ++#define CI_ECI 0x00000010 /* eci intr (corerev >= 21) */ ++#define CI_PMU 0x00000020 /* pmu intr (corerev >= 21) */ ++#define CI_UART 0x00000040 /* uart intr (corerev >= 21) */ ++#define CI_WDRESET 0x80000000 /* watchdog reset occurred */ ++ ++/* slow_clk_ctl */ ++#define SCC_SS_MASK 0x00000007 /* slow clock source mask */ ++#define SCC_SS_LPO 0x00000000 /* source of slow clock is LPO */ ++#define SCC_SS_XTAL 0x00000001 /* source of slow clock is crystal */ ++#define SCC_SS_PCI 0x00000002 /* source of slow clock is PCI */ ++#define SCC_LF 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ ++#define SCC_LP 0x00000400 /* LPOPowerDown, 1: LPO is disabled, ++ * 0: LPO is enabled ++ */ ++#define SCC_FS 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock, ++ * 0: power logic control ++ */ ++#define SCC_IP 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors ++ * PLL clock disable requests from core ++ */ ++#define SCC_XC 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't ++ * disable crystal when appropriate ++ */ ++#define SCC_XP 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */ ++#define SCC_CD_MASK 0xffff0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */ ++#define SCC_CD_SHIFT 16 ++ ++/* system_clk_ctl */ ++#define SYCC_IE 0x00000001 /* ILPen: Enable Idle Low Power */ ++#define SYCC_AE 0x00000002 /* ALPen: Enable Active Low Power */ ++#define SYCC_FP 0x00000004 /* ForcePLLOn */ ++#define SYCC_AR 0x00000008 /* Force ALP (or HT if ALPen is not set */ ++#define SYCC_HR 0x00000010 /* Force HT */ ++#define SYCC_CD_MASK 0xffff0000 /* ClkDiv (ILP = 1/(4 * (divisor + 1)) */ ++#define SYCC_CD_SHIFT 16 ++ ++/* Indirect backplane access */ ++#define BPIA_BYTEEN 0x0000000f ++#define BPIA_SZ1 0x00000001 ++#define BPIA_SZ2 0x00000003 ++#define BPIA_SZ4 0x00000007 ++#define BPIA_SZ8 0x0000000f ++#define BPIA_WRITE 0x00000100 ++#define BPIA_START 0x00000200 ++#define BPIA_BUSY 0x00000200 ++#define BPIA_ERROR 0x00000400 ++ ++/* pcmcia/prog/flash_config */ ++#define CF_EN 0x00000001 /* enable */ ++#define CF_EM_MASK 0x0000000e /* mode */ ++#define CF_EM_SHIFT 1 ++#define CF_EM_FLASH 0 /* flash/asynchronous mode */ ++#define CF_EM_SYNC 2 /* synchronous mode */ ++#define CF_EM_PCMCIA 4 /* pcmcia mode */ ++#define CF_DS 0x00000010 /* destsize: 0=8bit, 1=16bit */ ++#define CF_BS 0x00000020 /* byteswap */ ++#define CF_CD_MASK 0x000000c0 /* clock divider */ ++#define CF_CD_SHIFT 6 ++#define CF_CD_DIV2 0x00000000 /* backplane/2 */ ++#define CF_CD_DIV3 0x00000040 /* backplane/3 */ ++#define CF_CD_DIV4 0x00000080 /* backplane/4 */ ++#define CF_CE 0x00000100 /* clock enable */ ++#define CF_SB 0x00000200 /* size/bytestrobe (synch only) */ ++ ++/* pcmcia_memwait */ ++#define PM_W0_MASK 0x0000003f /* waitcount0 */ ++#define PM_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PM_W1_SHIFT 8 ++#define PM_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PM_W2_SHIFT 16 ++#define PM_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PM_W3_SHIFT 24 ++ ++/* pcmcia_attrwait */ ++#define PA_W0_MASK 0x0000003f /* waitcount0 */ ++#define PA_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PA_W1_SHIFT 8 ++#define PA_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PA_W2_SHIFT 16 ++#define PA_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PA_W3_SHIFT 24 ++ ++/* pcmcia_iowait */ ++#define PI_W0_MASK 0x0000003f /* waitcount0 */ ++#define PI_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PI_W1_SHIFT 8 ++#define PI_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PI_W2_SHIFT 16 ++#define PI_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PI_W3_SHIFT 24 ++ ++/* prog_waitcount */ ++#define PW_W0_MASK 0x0000001f /* waitcount0 */ ++#define PW_W1_MASK 0x00001f00 /* waitcount1 */ ++#define PW_W1_SHIFT 8 ++#define PW_W2_MASK 0x001f0000 /* waitcount2 */ ++#define PW_W2_SHIFT 16 ++#define PW_W3_MASK 0x1f000000 /* waitcount3 */ ++#define PW_W3_SHIFT 24 ++ ++#define PW_W0 0x0000000c ++#define PW_W1 0x00000a00 ++#define PW_W2 0x00020000 ++#define PW_W3 0x01000000 ++ ++/* flash_waitcount */ ++#define FW_W0_MASK 0x0000003f /* waitcount0 */ ++#define FW_W1_MASK 0x00001f00 /* waitcount1 */ ++#define FW_W1_SHIFT 8 ++#define FW_W2_MASK 0x001f0000 /* waitcount2 */ ++#define FW_W2_SHIFT 16 ++#define FW_W3_MASK 0x1f000000 /* waitcount3 */ ++#define FW_W3_SHIFT 24 ++ ++/* When Srom support present, fields in sromcontrol */ ++#define SRC_START 0x80000000 ++#define SRC_BUSY 0x80000000 ++#define SRC_OPCODE 0x60000000 ++#define SRC_OP_READ 0x00000000 ++#define SRC_OP_WRITE 0x20000000 ++#define SRC_OP_WRDIS 0x40000000 ++#define SRC_OP_WREN 0x60000000 ++#define SRC_OTPSEL 0x00000010 ++#define SRC_LOCK 0x00000008 ++#define SRC_SIZE_MASK 0x00000006 ++#define SRC_SIZE_1K 0x00000000 ++#define SRC_SIZE_4K 0x00000002 ++#define SRC_SIZE_16K 0x00000004 ++#define SRC_SIZE_SHIFT 1 ++#define SRC_PRESENT 0x00000001 ++ ++/* Fields in pmucontrol */ ++#define PCTL_ILP_DIV_MASK 0xffff0000 ++#define PCTL_ILP_DIV_SHIFT 16 ++#define PCTL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */ ++#define PCTL_NOILP_ON_WAIT 0x00000200 /* rev 1 */ ++#define PCTL_HT_REQ_EN 0x00000100 ++#define PCTL_ALP_REQ_EN 0x00000080 ++#define PCTL_XTALFREQ_MASK 0x0000007c ++#define PCTL_XTALFREQ_SHIFT 2 ++#define PCTL_ILP_DIV_EN 0x00000002 ++#define PCTL_LPO_SEL 0x00000001 ++ ++/* Fields in clkstretch */ ++#define CSTRETCH_HT 0xffff0000 ++#define CSTRETCH_ALP 0x0000ffff ++ ++/* gpiotimerval */ ++#define GPIO_ONTIME_SHIFT 16 ++ ++/* clockcontrol_n */ ++#define CN_N1_MASK 0x3f /* n1 control */ ++#define CN_N2_MASK 0x3f00 /* n2 control */ ++#define CN_N2_SHIFT 8 ++#define CN_PLLC_MASK 0xf0000 /* pll control */ ++#define CN_PLLC_SHIFT 16 ++ ++/* clockcontrol_sb/pci/uart */ ++#define CC_M1_MASK 0x3f /* m1 control */ ++#define CC_M2_MASK 0x3f00 /* m2 control */ ++#define CC_M2_SHIFT 8 ++#define CC_M3_MASK 0x3f0000 /* m3 control */ ++#define CC_M3_SHIFT 16 ++#define CC_MC_MASK 0x1f000000 /* mux control */ ++#define CC_MC_SHIFT 24 ++ ++/* N3M Clock control magic field values */ ++#define CC_F6_2 0x02 /* A factor of 2 in */ ++#define CC_F6_3 0x03 /* 6-bit fields like */ ++#define CC_F6_4 0x05 /* N1, M1 or M3 */ ++#define CC_F6_5 0x09 ++#define CC_F6_6 0x11 ++#define CC_F6_7 0x21 ++ ++#define CC_F5_BIAS 5 /* 5-bit fields get this added */ ++ ++#define CC_MC_BYPASS 0x08 ++#define CC_MC_M1 0x04 ++#define CC_MC_M1M2 0x02 ++#define CC_MC_M1M2M3 0x01 ++#define CC_MC_M1M3 0x11 ++ ++/* Type 2 Clock control magic field values */ ++#define CC_T2_BIAS 2 /* n1, n2, m1 & m3 bias */ ++#define CC_T2M2_BIAS 3 /* m2 bias */ ++ ++#define CC_T2MC_M1BYP 1 ++#define CC_T2MC_M2BYP 2 ++#define CC_T2MC_M3BYP 4 ++ ++/* Type 6 Clock control magic field values */ ++#define CC_T6_MMASK 1 /* bits of interest in m */ ++#define CC_T6_M0 120000000 /* sb clock for m = 0 */ ++#define CC_T6_M1 100000000 /* sb clock for m = 1 */ ++#define SB2MIPS_T6(sb) (2 * (sb)) ++ ++/* Common clock base */ ++#define CC_CLOCK_BASE1 24000000 /* Half the clock freq */ ++#define CC_CLOCK_BASE2 12500000 /* Alternate crystal on some PLLs */ ++ ++/* Clock control values for 200MHz in 5350 */ ++#define CLKC_5350_N 0x0311 ++#define CLKC_5350_M 0x04020009 ++ ++/* Flash types in the chipcommon capabilities register */ ++#define FLASH_NONE 0x000 /* No flash */ ++#define SFLASH_ST 0x100 /* ST serial flash */ ++#define SFLASH_AT 0x200 /* Atmel serial flash */ ++#define NFLASH 0x300 ++#define PFLASH 0x700 /* Parallel flash */ ++ ++/* Bits in the ExtBus config registers */ ++#define CC_CFG_EN 0x0001 /* Enable */ ++#define CC_CFG_EM_MASK 0x000e /* Extif Mode */ ++#define CC_CFG_EM_ASYNC 0x0000 /* Async/Parallel flash */ ++#define CC_CFG_EM_SYNC 0x0002 /* Synchronous */ ++#define CC_CFG_EM_PCMCIA 0x0004 /* PCMCIA */ ++#define CC_CFG_EM_IDE 0x0006 /* IDE */ ++#define CC_CFG_DS 0x0010 /* Data size, 0=8bit, 1=16bit */ ++#define CC_CFG_CD_MASK 0x00e0 /* Sync: Clock divisor, rev >= 20 */ ++#define CC_CFG_CE 0x0100 /* Sync: Clock enable, rev >= 20 */ ++#define CC_CFG_SB 0x0200 /* Sync: Size/Bytestrobe, rev >= 20 */ ++#define CC_CFG_IS 0x0400 /* Extif Sync Clk Select, rev >= 20 */ ++ ++/* ExtBus address space */ ++#define CC_EB_BASE 0x1a000000 /* Chipc ExtBus base address */ ++#define CC_EB_PCMCIA_MEM 0x1a000000 /* PCMCIA 0 memory base address */ ++#define CC_EB_PCMCIA_IO 0x1a200000 /* PCMCIA 0 I/O base address */ ++#define CC_EB_PCMCIA_CFG 0x1a400000 /* PCMCIA 0 config base address */ ++#define CC_EB_IDE 0x1a800000 /* IDE memory base */ ++#define CC_EB_PCMCIA1_MEM 0x1a800000 /* PCMCIA 1 memory base address */ ++#define CC_EB_PCMCIA1_IO 0x1aa00000 /* PCMCIA 1 I/O base address */ ++#define CC_EB_PCMCIA1_CFG 0x1ac00000 /* PCMCIA 1 config base address */ ++#define CC_EB_PROGIF 0x1b000000 /* ProgIF Async/Sync base address */ ++ ++ ++/* Start/busy bit in flashcontrol */ ++#define SFLASH_OPCODE 0x000000ff ++#define SFLASH_ACTION 0x00000700 ++#define SFLASH_CS_ACTIVE 0x00001000 /* Chip Select Active, rev >= 20 */ ++#define SFLASH_START 0x80000000 ++#define SFLASH_BUSY SFLASH_START ++ ++/* flashcontrol action codes */ ++#define SFLASH_ACT_OPONLY 0x0000 /* Issue opcode only */ ++#define SFLASH_ACT_OP1D 0x0100 /* opcode + 1 data byte */ ++#define SFLASH_ACT_OP3A 0x0200 /* opcode + 3 addr bytes */ ++#define SFLASH_ACT_OP3A1D 0x0300 /* opcode + 3 addr & 1 data bytes */ ++#define SFLASH_ACT_OP3A4D 0x0400 /* opcode + 3 addr & 4 data bytes */ ++#define SFLASH_ACT_OP3A4X4D 0x0500 /* opcode + 3 addr, 4 don't care & 4 data bytes */ ++#define SFLASH_ACT_OP3A1X4D 0x0700 /* opcode + 3 addr, 1 don't care & 4 data bytes */ ++ ++/* flashcontrol action+opcodes for ST flashes */ ++#define SFLASH_ST_WREN 0x0006 /* Write Enable */ ++#define SFLASH_ST_WRDIS 0x0004 /* Write Disable */ ++#define SFLASH_ST_RDSR 0x0105 /* Read Status Register */ ++#define SFLASH_ST_WRSR 0x0101 /* Write Status Register */ ++#define SFLASH_ST_READ 0x0303 /* Read Data Bytes */ ++#define SFLASH_ST_PP 0x0302 /* Page Program */ ++#define SFLASH_ST_SE 0x02d8 /* Sector Erase */ ++#define SFLASH_ST_BE 0x00c7 /* Bulk Erase */ ++#define SFLASH_ST_DP 0x00b9 /* Deep Power-down */ ++#define SFLASH_ST_RES 0x03ab /* Read Electronic Signature */ ++#define SFLASH_ST_CSA 0x1000 /* Keep chip select asserted */ ++#define SFLASH_ST_SSE 0x0220 /* Sub-sector Erase */ ++ ++#define SFLASH_MXIC_RDID 0x0390 /* Read Manufacture ID */ ++#define SFLASH_MXIC_MFID 0xc2 /* MXIC Manufacture ID */ ++ ++/* Status register bits for ST flashes */ ++#define SFLASH_ST_WIP 0x01 /* Write In Progress */ ++#define SFLASH_ST_WEL 0x02 /* Write Enable Latch */ ++#define SFLASH_ST_BP_MASK 0x1c /* Block Protect */ ++#define SFLASH_ST_BP_SHIFT 2 ++#define SFLASH_ST_SRWD 0x80 /* Status Register Write Disable */ ++ ++/* flashcontrol action+opcodes for Atmel flashes */ ++#define SFLASH_AT_READ 0x07e8 ++#define SFLASH_AT_PAGE_READ 0x07d2 ++#define SFLASH_AT_BUF1_READ ++#define SFLASH_AT_BUF2_READ ++#define SFLASH_AT_STATUS 0x01d7 ++#define SFLASH_AT_BUF1_WRITE 0x0384 ++#define SFLASH_AT_BUF2_WRITE 0x0387 ++#define SFLASH_AT_BUF1_ERASE_PROGRAM 0x0283 ++#define SFLASH_AT_BUF2_ERASE_PROGRAM 0x0286 ++#define SFLASH_AT_BUF1_PROGRAM 0x0288 ++#define SFLASH_AT_BUF2_PROGRAM 0x0289 ++#define SFLASH_AT_PAGE_ERASE 0x0281 ++#define SFLASH_AT_BLOCK_ERASE 0x0250 ++#define SFLASH_AT_BUF1_WRITE_ERASE_PROGRAM 0x0382 ++#define SFLASH_AT_BUF2_WRITE_ERASE_PROGRAM 0x0385 ++#define SFLASH_AT_BUF1_LOAD 0x0253 ++#define SFLASH_AT_BUF2_LOAD 0x0255 ++#define SFLASH_AT_BUF1_COMPARE 0x0260 ++#define SFLASH_AT_BUF2_COMPARE 0x0261 ++#define SFLASH_AT_BUF1_REPROGRAM 0x0258 ++#define SFLASH_AT_BUF2_REPROGRAM 0x0259 ++ ++/* Status register bits for Atmel flashes */ ++#define SFLASH_AT_READY 0x80 ++#define SFLASH_AT_MISMATCH 0x40 ++#define SFLASH_AT_ID_MASK 0x38 ++#define SFLASH_AT_ID_SHIFT 3 ++ ++/* SPI register bits, corerev >= 37 */ ++#define GSIO_START 0x80000000 ++#define GSIO_BUSY GSIO_START ++ ++/* ++ * These are the UART port assignments, expressed as offsets from the base ++ * register. These assignments should hold for any serial port based on ++ * a 8250, 16450, or 16550(A). ++ */ ++ ++#define UART_RX 0 /* In: Receive buffer (DLAB=0) */ ++#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */ ++#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */ ++#define UART_IER 1 /* In/Out: Interrupt Enable Register (DLAB=0) */ ++#define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */ ++#define UART_IIR 2 /* In: Interrupt Identity Register */ ++#define UART_FCR 2 /* Out: FIFO Control Register */ ++#define UART_LCR 3 /* Out: Line Control Register */ ++#define UART_MCR 4 /* Out: Modem Control Register */ ++#define UART_LSR 5 /* In: Line Status Register */ ++#define UART_MSR 6 /* In: Modem Status Register */ ++#define UART_SCR 7 /* I/O: Scratch Register */ ++#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ ++#define UART_LCR_WLEN8 0x03 /* Word length: 8 bits */ ++#define UART_MCR_OUT2 0x08 /* MCR GPIO out 2 */ ++#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ ++#define UART_LSR_RX_FIFO 0x80 /* Receive FIFO error */ ++#define UART_LSR_TDHR 0x40 /* Data-hold-register empty */ ++#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ ++#define UART_LSR_BREAK 0x10 /* Break interrupt */ ++#define UART_LSR_FRAMING 0x08 /* Framing error */ ++#define UART_LSR_PARITY 0x04 /* Parity error */ ++#define UART_LSR_OVERRUN 0x02 /* Overrun error */ ++#define UART_LSR_RXRDY 0x01 /* Receiver ready */ ++#define UART_FCR_FIFO_ENABLE 1 /* FIFO control register bit controlling FIFO enable/disable */ ++ ++/* Interrupt Identity Register (IIR) bits */ ++#define UART_IIR_FIFO_MASK 0xc0 /* IIR FIFO disable/enabled mask */ ++#define UART_IIR_INT_MASK 0xf /* IIR interrupt ID source */ ++#define UART_IIR_MDM_CHG 0x0 /* Modem status changed */ ++#define UART_IIR_NOINT 0x1 /* No interrupt pending */ ++#define UART_IIR_THRE 0x2 /* THR empty */ ++#define UART_IIR_RCVD_DATA 0x4 /* Received data available */ ++#define UART_IIR_RCVR_STATUS 0x6 /* Receiver status */ ++#define UART_IIR_CHAR_TIME 0xc /* Character time */ ++ ++/* Interrupt Enable Register (IER) bits */ ++#define UART_IER_EDSSI 8 /* enable modem status interrupt */ ++#define UART_IER_ELSI 4 /* enable receiver line status interrupt */ ++#define UART_IER_ETBEI 2 /* enable transmitter holding register empty interrupt */ ++#define UART_IER_ERBFI 1 /* enable data available interrupt */ ++ ++/* pmustatus */ ++#define PST_EXTLPOAVAIL 0x0100 ++#define PST_WDRESET 0x0080 ++#define PST_INTPEND 0x0040 ++#define PST_SBCLKST 0x0030 ++#define PST_SBCLKST_ILP 0x0010 ++#define PST_SBCLKST_ALP 0x0020 ++#define PST_SBCLKST_HT 0x0030 ++#define PST_ALPAVAIL 0x0008 ++#define PST_HTAVAIL 0x0004 ++#define PST_RESINIT 0x0003 ++ ++/* pmucapabilities */ ++#define PCAP_REV_MASK 0x000000ff ++#define PCAP_RC_MASK 0x00001f00 ++#define PCAP_RC_SHIFT 8 ++#define PCAP_TC_MASK 0x0001e000 ++#define PCAP_TC_SHIFT 13 ++#define PCAP_PC_MASK 0x001e0000 ++#define PCAP_PC_SHIFT 17 ++#define PCAP_VC_MASK 0x01e00000 ++#define PCAP_VC_SHIFT 21 ++#define PCAP_CC_MASK 0x1e000000 ++#define PCAP_CC_SHIFT 25 ++#define PCAP5_PC_MASK 0x003e0000 /* PMU corerev >= 5 */ ++#define PCAP5_PC_SHIFT 17 ++#define PCAP5_VC_MASK 0x07c00000 ++#define PCAP5_VC_SHIFT 22 ++#define PCAP5_CC_MASK 0xf8000000 ++#define PCAP5_CC_SHIFT 27 ++ ++/* PMU Resource Request Timer registers */ ++/* This is based on PmuRev0 */ ++#define PRRT_TIME_MASK 0x03ff ++#define PRRT_INTEN 0x0400 ++#define PRRT_REQ_ACTIVE 0x0800 ++#define PRRT_ALP_REQ 0x1000 ++#define PRRT_HT_REQ 0x2000 ++#define PRRT_HQ_REQ 0x4000 ++ ++/* PMU resource bit position */ ++#define PMURES_BIT(bit) (1 << (bit)) ++ ++/* PMU resource number limit */ ++#define PMURES_MAX_RESNUM 30 ++ ++/* PMU chip control0 register */ ++#define PMU_CHIPCTL0 0 ++ ++/* clock req types */ ++#define PMU_CC1_CLKREQ_TYPE_SHIFT 19 ++#define PMU_CC1_CLKREQ_TYPE_MASK (1 << PMU_CC1_CLKREQ_TYPE_SHIFT) ++ ++#define CLKREQ_TYPE_CONFIG_OPENDRAIN 0 ++#define CLKREQ_TYPE_CONFIG_PUSHPULL 1 ++ ++/* PMU chip control1 register */ ++#define PMU_CHIPCTL1 1 ++#define PMU_CC1_RXC_DLL_BYPASS 0x00010000 ++ ++#define PMU_CC1_IF_TYPE_MASK 0x00000030 ++#define PMU_CC1_IF_TYPE_RMII 0x00000000 ++#define PMU_CC1_IF_TYPE_MII 0x00000010 ++#define PMU_CC1_IF_TYPE_RGMII 0x00000020 ++ ++#define PMU_CC1_SW_TYPE_MASK 0x000000c0 ++#define PMU_CC1_SW_TYPE_EPHY 0x00000000 ++#define PMU_CC1_SW_TYPE_EPHYMII 0x00000040 ++#define PMU_CC1_SW_TYPE_EPHYRMII 0x00000080 ++#define PMU_CC1_SW_TYPE_RGMII 0x000000c0 ++ ++/* PMU chip control2 register */ ++#define PMU_CHIPCTL2 2 ++ ++/* PMU chip control3 register */ ++#define PMU_CHIPCTL3 3 ++ ++#define PMU_CC3_ENABLE_SDIO_WAKEUP_SHIFT 19 ++#define PMU_CC3_ENABLE_RF_SHIFT 22 ++#define PMU_CC3_RF_DISABLE_IVALUE_SHIFT 23 ++ ++ ++/* PMU corerev and chip specific PLL controls. ++ * PMU_PLL_XX where is PMU corerev and is an arbitrary number ++ * to differentiate different PLLs controlled by the same PMU rev. ++ */ ++/* pllcontrol registers */ ++/* PDIV, div_phy, div_arm, div_adc, dith_sel, ioff, kpd_scale, lsb_sel, mash_sel, lf_c & lf_r */ ++#define PMU0_PLL0_PLLCTL0 0 ++#define PMU0_PLL0_PC0_PDIV_MASK 1 ++#define PMU0_PLL0_PC0_PDIV_FREQ 25000 ++#define PMU0_PLL0_PC0_DIV_ARM_MASK 0x00000038 ++#define PMU0_PLL0_PC0_DIV_ARM_SHIFT 3 ++#define PMU0_PLL0_PC0_DIV_ARM_BASE 8 ++ ++/* PC0_DIV_ARM for PLLOUT_ARM */ ++#define PMU0_PLL0_PC0_DIV_ARM_110MHZ 0 ++#define PMU0_PLL0_PC0_DIV_ARM_97_7MHZ 1 ++#define PMU0_PLL0_PC0_DIV_ARM_88MHZ 2 ++#define PMU0_PLL0_PC0_DIV_ARM_80MHZ 3 /* Default */ ++#define PMU0_PLL0_PC0_DIV_ARM_73_3MHZ 4 ++#define PMU0_PLL0_PC0_DIV_ARM_67_7MHZ 5 ++#define PMU0_PLL0_PC0_DIV_ARM_62_9MHZ 6 ++#define PMU0_PLL0_PC0_DIV_ARM_58_6MHZ 7 ++ ++/* Wildcard base, stop_mod, en_lf_tp, en_cal & lf_r2 */ ++#define PMU0_PLL0_PLLCTL1 1 ++#define PMU0_PLL0_PC1_WILD_INT_MASK 0xf0000000 ++#define PMU0_PLL0_PC1_WILD_INT_SHIFT 28 ++#define PMU0_PLL0_PC1_WILD_FRAC_MASK 0x0fffff00 ++#define PMU0_PLL0_PC1_WILD_FRAC_SHIFT 8 ++#define PMU0_PLL0_PC1_STOP_MOD 0x00000040 ++ ++/* Wildcard base, vco_calvar, vco_swc, vco_var_selref, vso_ical & vco_sel_avdd */ ++#define PMU0_PLL0_PLLCTL2 2 ++#define PMU0_PLL0_PC2_WILD_INT_MASK 0xf ++#define PMU0_PLL0_PC2_WILD_INT_SHIFT 4 ++ ++/* pllcontrol registers */ ++/* ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, p1div, p2div, _bypass_sdmod */ ++#define PMU1_PLL0_PLLCTL0 0 ++#define PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000 ++#define PMU1_PLL0_PC0_P1DIV_SHIFT 20 ++#define PMU1_PLL0_PC0_P2DIV_MASK 0x0f000000 ++#define PMU1_PLL0_PC0_P2DIV_SHIFT 24 ++ ++/* mdiv */ ++#define PMU1_PLL0_PLLCTL1 1 ++#define PMU1_PLL0_PC1_M1DIV_MASK 0x000000ff ++#define PMU1_PLL0_PC1_M1DIV_SHIFT 0 ++#define PMU1_PLL0_PC1_M2DIV_MASK 0x0000ff00 ++#define PMU1_PLL0_PC1_M2DIV_SHIFT 8 ++#define PMU1_PLL0_PC1_M3DIV_MASK 0x00ff0000 ++#define PMU1_PLL0_PC1_M3DIV_SHIFT 16 ++#define PMU1_PLL0_PC1_M4DIV_MASK 0xff000000 ++#define PMU1_PLL0_PC1_M4DIV_SHIFT 24 ++#define PMU1_PLL0_PC1_M4DIV_BY_9 9 ++#define PMU1_PLL0_PC1_M4DIV_BY_18 0x12 ++#define PMU1_PLL0_PC1_M4DIV_BY_36 0x24 ++ ++#define DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT 8 ++#define DOT11MAC_880MHZ_CLK_DIVISOR_MASK (0xFF << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) ++#define DOT11MAC_880MHZ_CLK_DIVISOR_VAL (0xE << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) ++ ++/* mdiv, ndiv_dither_mfb, ndiv_mode, ndiv_int */ ++#define PMU1_PLL0_PLLCTL2 2 ++#define PMU1_PLL0_PC2_M5DIV_MASK 0x000000ff ++#define PMU1_PLL0_PC2_M5DIV_SHIFT 0 ++#define PMU1_PLL0_PC2_M5DIV_BY_12 0xc ++#define PMU1_PLL0_PC2_M5DIV_BY_18 0x12 ++#define PMU1_PLL0_PC2_M5DIV_BY_36 0x24 ++#define PMU1_PLL0_PC2_M6DIV_MASK 0x0000ff00 ++#define PMU1_PLL0_PC2_M6DIV_SHIFT 8 ++#define PMU1_PLL0_PC2_M6DIV_BY_18 0x12 ++#define PMU1_PLL0_PC2_M6DIV_BY_36 0x24 ++#define PMU1_PLL0_PC2_NDIV_MODE_MASK 0x000e0000 ++#define PMU1_PLL0_PC2_NDIV_MODE_SHIFT 17 ++#define PMU1_PLL0_PC2_NDIV_MODE_MASH 1 ++#define PMU1_PLL0_PC2_NDIV_MODE_MFB 2 /* recommended for 4319 */ ++#define PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000 ++#define PMU1_PLL0_PC2_NDIV_INT_SHIFT 20 ++ ++/* ndiv_frac */ ++#define PMU1_PLL0_PLLCTL3 3 ++#define PMU1_PLL0_PC3_NDIV_FRAC_MASK 0x00ffffff ++#define PMU1_PLL0_PC3_NDIV_FRAC_SHIFT 0 ++ ++/* pll_ctrl */ ++#define PMU1_PLL0_PLLCTL4 4 ++ ++/* pll_ctrl, vco_rng, clkdrive_ch */ ++#define PMU1_PLL0_PLLCTL5 5 ++#define PMU1_PLL0_PC5_CLK_DRV_MASK 0xffffff00 ++#define PMU1_PLL0_PC5_CLK_DRV_SHIFT 8 ++ ++/* PMU rev 2 control words */ ++#define PMU2_PHY_PLL_PLLCTL 4 ++#define PMU2_SI_PLL_PLLCTL 10 ++ ++/* PMU rev 2 */ ++/* pllcontrol registers */ ++/* ndiv_pwrdn, pwrdn_ch, refcomp_pwrdn, dly_ch, p1div, p2div, _bypass_sdmod */ ++#define PMU2_PLL_PLLCTL0 0 ++#define PMU2_PLL_PC0_P1DIV_MASK 0x00f00000 ++#define PMU2_PLL_PC0_P1DIV_SHIFT 20 ++#define PMU2_PLL_PC0_P2DIV_MASK 0x0f000000 ++#define PMU2_PLL_PC0_P2DIV_SHIFT 24 ++ ++/* mdiv */ ++#define PMU2_PLL_PLLCTL1 1 ++#define PMU2_PLL_PC1_M1DIV_MASK 0x000000ff ++#define PMU2_PLL_PC1_M1DIV_SHIFT 0 ++#define PMU2_PLL_PC1_M2DIV_MASK 0x0000ff00 ++#define PMU2_PLL_PC1_M2DIV_SHIFT 8 ++#define PMU2_PLL_PC1_M3DIV_MASK 0x00ff0000 ++#define PMU2_PLL_PC1_M3DIV_SHIFT 16 ++#define PMU2_PLL_PC1_M4DIV_MASK 0xff000000 ++#define PMU2_PLL_PC1_M4DIV_SHIFT 24 ++ ++/* mdiv, ndiv_dither_mfb, ndiv_mode, ndiv_int */ ++#define PMU2_PLL_PLLCTL2 2 ++#define PMU2_PLL_PC2_M5DIV_MASK 0x000000ff ++#define PMU2_PLL_PC2_M5DIV_SHIFT 0 ++#define PMU2_PLL_PC2_M6DIV_MASK 0x0000ff00 ++#define PMU2_PLL_PC2_M6DIV_SHIFT 8 ++#define PMU2_PLL_PC2_NDIV_MODE_MASK 0x000e0000 ++#define PMU2_PLL_PC2_NDIV_MODE_SHIFT 17 ++#define PMU2_PLL_PC2_NDIV_INT_MASK 0x1ff00000 ++#define PMU2_PLL_PC2_NDIV_INT_SHIFT 20 ++ ++/* ndiv_frac */ ++#define PMU2_PLL_PLLCTL3 3 ++#define PMU2_PLL_PC3_NDIV_FRAC_MASK 0x00ffffff ++#define PMU2_PLL_PC3_NDIV_FRAC_SHIFT 0 ++ ++/* pll_ctrl */ ++#define PMU2_PLL_PLLCTL4 4 ++ ++/* pll_ctrl, vco_rng, clkdrive_ch */ ++#define PMU2_PLL_PLLCTL5 5 ++#define PMU2_PLL_PC5_CLKDRIVE_CH1_MASK 0x00000f00 ++#define PMU2_PLL_PC5_CLKDRIVE_CH1_SHIFT 8 ++#define PMU2_PLL_PC5_CLKDRIVE_CH2_MASK 0x0000f000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH2_SHIFT 12 ++#define PMU2_PLL_PC5_CLKDRIVE_CH3_MASK 0x000f0000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH3_SHIFT 16 ++#define PMU2_PLL_PC5_CLKDRIVE_CH4_MASK 0x00f00000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH4_SHIFT 20 ++#define PMU2_PLL_PC5_CLKDRIVE_CH5_MASK 0x0f000000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH5_SHIFT 24 ++#define PMU2_PLL_PC5_CLKDRIVE_CH6_MASK 0xf0000000 ++#define PMU2_PLL_PC5_CLKDRIVE_CH6_SHIFT 28 ++ ++/* PMU rev 5 (& 6) */ ++#define PMU5_PLL_P1P2_OFF 0 ++#define PMU5_PLL_P1_MASK 0x0f000000 ++#define PMU5_PLL_P1_SHIFT 24 ++#define PMU5_PLL_P2_MASK 0x00f00000 ++#define PMU5_PLL_P2_SHIFT 20 ++#define PMU5_PLL_M14_OFF 1 ++#define PMU5_PLL_MDIV_MASK 0x000000ff ++#define PMU5_PLL_MDIV_WIDTH 8 ++#define PMU5_PLL_NM5_OFF 2 ++#define PMU5_PLL_NDIV_MASK 0xfff00000 ++#define PMU5_PLL_NDIV_SHIFT 20 ++#define PMU5_PLL_NDIV_MODE_MASK 0x000e0000 ++#define PMU5_PLL_NDIV_MODE_SHIFT 17 ++#define PMU5_PLL_FMAB_OFF 3 ++#define PMU5_PLL_MRAT_MASK 0xf0000000 ++#define PMU5_PLL_MRAT_SHIFT 28 ++#define PMU5_PLL_ABRAT_MASK 0x08000000 ++#define PMU5_PLL_ABRAT_SHIFT 27 ++#define PMU5_PLL_FDIV_MASK 0x07ffffff ++#define PMU5_PLL_PLLCTL_OFF 4 ++#define PMU5_PLL_PCHI_OFF 5 ++#define PMU5_PLL_PCHI_MASK 0x0000003f ++ ++/* pmu XtalFreqRatio */ ++#define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF ++#define PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000 ++#define PMU_XTALFREQ_REG_MEASURE_SHIFT 31 ++ ++/* Divider allocation in 4716/47162/5356/5357 */ ++#define PMU5_MAINPLL_CPU 1 ++#define PMU5_MAINPLL_MEM 2 ++#define PMU5_MAINPLL_SI 3 ++ ++/* 4706 PMU */ ++#define PMU4706_MAINPLL_PLL0 0 ++#define PMU6_4706_PROCPLL_OFF 4 /* The CPU PLL */ ++#define PMU6_4706_PROC_P2DIV_MASK 0x000f0000 ++#define PMU6_4706_PROC_P2DIV_SHIFT 16 ++#define PMU6_4706_PROC_P1DIV_MASK 0x0000f000 ++#define PMU6_4706_PROC_P1DIV_SHIFT 12 ++#define PMU6_4706_PROC_NDIV_INT_MASK 0x00000ff8 ++#define PMU6_4706_PROC_NDIV_INT_SHIFT 3 ++#define PMU6_4706_PROC_NDIV_MODE_MASK 0x00000007 ++#define PMU6_4706_PROC_NDIV_MODE_SHIFT 0 ++ ++#define PMU7_PLL_PLLCTL7 7 ++#define PMU7_PLL_CTL7_M4DIV_MASK 0xff000000 ++#define PMU7_PLL_CTL7_M4DIV_SHIFT 24 ++#define PMU7_PLL_CTL7_M4DIV_BY_6 6 ++#define PMU7_PLL_CTL7_M4DIV_BY_12 0xc ++#define PMU7_PLL_CTL7_M4DIV_BY_24 0x18 ++#define PMU7_PLL_PLLCTL8 8 ++#define PMU7_PLL_CTL8_M5DIV_MASK 0x000000ff ++#define PMU7_PLL_CTL8_M5DIV_SHIFT 0 ++#define PMU7_PLL_CTL8_M5DIV_BY_8 8 ++#define PMU7_PLL_CTL8_M5DIV_BY_12 0xc ++#define PMU7_PLL_CTL8_M5DIV_BY_24 0x18 ++#define PMU7_PLL_CTL8_M6DIV_MASK 0x0000ff00 ++#define PMU7_PLL_CTL8_M6DIV_SHIFT 8 ++#define PMU7_PLL_CTL8_M6DIV_BY_12 0xc ++#define PMU7_PLL_CTL8_M6DIV_BY_24 0x18 ++#define PMU7_PLL_PLLCTL11 11 ++#define PMU7_PLL_PLLCTL11_MASK 0xffffff00 ++#define PMU7_PLL_PLLCTL11_VAL 0x22222200 ++ ++/* PMU rev 15 */ ++#define PMU15_PLL_PLLCTL0 0 ++#define PMU15_PLL_PC0_CLKSEL_MASK 0x00000003 ++#define PMU15_PLL_PC0_CLKSEL_SHIFT 0 ++#define PMU15_PLL_PC0_FREQTGT_MASK 0x003FFFFC ++#define PMU15_PLL_PC0_FREQTGT_SHIFT 2 ++#define PMU15_PLL_PC0_PRESCALE_MASK 0x00C00000 ++#define PMU15_PLL_PC0_PRESCALE_SHIFT 22 ++#define PMU15_PLL_PC0_KPCTRL_MASK 0x07000000 ++#define PMU15_PLL_PC0_KPCTRL_SHIFT 24 ++#define PMU15_PLL_PC0_FCNTCTRL_MASK 0x38000000 ++#define PMU15_PLL_PC0_FCNTCTRL_SHIFT 27 ++#define PMU15_PLL_PC0_FDCMODE_MASK 0x40000000 ++#define PMU15_PLL_PC0_FDCMODE_SHIFT 30 ++#define PMU15_PLL_PC0_CTRLBIAS_MASK 0x80000000 ++#define PMU15_PLL_PC0_CTRLBIAS_SHIFT 31 ++ ++#define PMU15_PLL_PLLCTL1 1 ++#define PMU15_PLL_PC1_BIAS_CTLM_MASK 0x00000060 ++#define PMU15_PLL_PC1_BIAS_CTLM_SHIFT 5 ++#define PMU15_PLL_PC1_BIAS_CTLM_RST_MASK 0x00000040 ++#define PMU15_PLL_PC1_BIAS_CTLM_RST_SHIFT 6 ++#define PMU15_PLL_PC1_BIAS_SS_DIVR_MASK 0x0001FF80 ++#define PMU15_PLL_PC1_BIAS_SS_DIVR_SHIFT 7 ++#define PMU15_PLL_PC1_BIAS_SS_RSTVAL_MASK 0x03FE0000 ++#define PMU15_PLL_PC1_BIAS_SS_RSTVAL_SHIFT 17 ++#define PMU15_PLL_PC1_BIAS_INTG_BW_MASK 0x0C000000 ++#define PMU15_PLL_PC1_BIAS_INTG_BW_SHIFT 26 ++#define PMU15_PLL_PC1_BIAS_INTG_BYP_MASK 0x10000000 ++#define PMU15_PLL_PC1_BIAS_INTG_BYP_SHIFT 28 ++#define PMU15_PLL_PC1_OPENLP_EN_MASK 0x40000000 ++#define PMU15_PLL_PC1_OPENLP_EN_SHIFT 30 ++ ++#define PMU15_PLL_PLLCTL2 2 ++#define PMU15_PLL_PC2_CTEN_MASK 0x00000001 ++#define PMU15_PLL_PC2_CTEN_SHIFT 0 ++ ++#define PMU15_PLL_PLLCTL3 3 ++#define PMU15_PLL_PC3_DITHER_EN_MASK 0x00000001 ++#define PMU15_PLL_PC3_DITHER_EN_SHIFT 0 ++#define PMU15_PLL_PC3_DCOCTLSP_MASK 0xFE000000 ++#define PMU15_PLL_PC3_DCOCTLSP_SHIFT 25 ++#define PMU15_PLL_PC3_DCOCTLSP_DIV2EN_MASK 0x01 ++#define PMU15_PLL_PC3_DCOCTLSP_DIV2EN_SHIFT 0 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0EN_MASK 0x02 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0EN_SHIFT 1 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1EN_MASK 0x04 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1EN_SHIFT 2 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0SEL_MASK 0x18 ++#define PMU15_PLL_PC3_DCOCTLSP_CH0SEL_SHIFT 3 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1SEL_MASK 0x60 ++#define PMU15_PLL_PC3_DCOCTLSP_CH1SEL_SHIFT 5 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV1 0 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV2 1 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV3 2 ++#define PMU15_PLL_PC3_DCOCTLSP_CHSEL_OUTP_DIV5 3 ++ ++#define PMU15_PLL_PLLCTL4 4 ++#define PMU15_PLL_PC4_FLLCLK1_DIV_MASK 0x00000007 ++#define PMU15_PLL_PC4_FLLCLK1_DIV_SHIFT 0 ++#define PMU15_PLL_PC4_FLLCLK2_DIV_MASK 0x00000038 ++#define PMU15_PLL_PC4_FLLCLK2_DIV_SHIFT 3 ++#define PMU15_PLL_PC4_FLLCLK3_DIV_MASK 0x000001C0 ++#define PMU15_PLL_PC4_FLLCLK3_DIV_SHIFT 6 ++#define PMU15_PLL_PC4_DBGMODE_MASK 0x00000E00 ++#define PMU15_PLL_PC4_DBGMODE_SHIFT 9 ++#define PMU15_PLL_PC4_FLL480_CTLSP_LK_MASK 0x00001000 ++#define PMU15_PLL_PC4_FLL480_CTLSP_LK_SHIFT 12 ++#define PMU15_PLL_PC4_FLL480_CTLSP_MASK 0x000FE000 ++#define PMU15_PLL_PC4_FLL480_CTLSP_SHIFT 13 ++#define PMU15_PLL_PC4_DINPOL_MASK 0x00100000 ++#define PMU15_PLL_PC4_DINPOL_SHIFT 20 ++#define PMU15_PLL_PC4_CLKOUT_PD_MASK 0x00200000 ++#define PMU15_PLL_PC4_CLKOUT_PD_SHIFT 21 ++#define PMU15_PLL_PC4_CLKDIV2_PD_MASK 0x00400000 ++#define PMU15_PLL_PC4_CLKDIV2_PD_SHIFT 22 ++#define PMU15_PLL_PC4_CLKDIV4_PD_MASK 0x00800000 ++#define PMU15_PLL_PC4_CLKDIV4_PD_SHIFT 23 ++#define PMU15_PLL_PC4_CLKDIV8_PD_MASK 0x01000000 ++#define PMU15_PLL_PC4_CLKDIV8_PD_SHIFT 24 ++#define PMU15_PLL_PC4_CLKDIV16_PD_MASK 0x02000000 ++#define PMU15_PLL_PC4_CLKDIV16_PD_SHIFT 25 ++#define PMU15_PLL_PC4_TEST_EN_MASK 0x04000000 ++#define PMU15_PLL_PC4_TEST_EN_SHIFT 26 ++ ++#define PMU15_PLL_PLLCTL5 5 ++#define PMU15_PLL_PC5_FREQTGT_MASK 0x000FFFFF ++#define PMU15_PLL_PC5_FREQTGT_SHIFT 0 ++#define PMU15_PLL_PC5_DCOCTLSP_MASK 0x07F00000 ++#define PMU15_PLL_PC5_DCOCTLSP_SHIFT 20 ++#define PMU15_PLL_PC5_PRESCALE_MASK 0x18000000 ++#define PMU15_PLL_PC5_PRESCALE_SHIFT 27 ++ ++#define PMU15_PLL_PLLCTL6 6 ++#define PMU15_PLL_PC6_FREQTGT_MASK 0x000FFFFF ++#define PMU15_PLL_PC6_FREQTGT_SHIFT 0 ++#define PMU15_PLL_PC6_DCOCTLSP_MASK 0x07F00000 ++#define PMU15_PLL_PC6_DCOCTLSP_SHIFT 20 ++#define PMU15_PLL_PC6_PRESCALE_MASK 0x18000000 ++#define PMU15_PLL_PC6_PRESCALE_SHIFT 27 ++ ++#define PMU15_FREQTGT_480_DEFAULT 0x19AB1 ++#define PMU15_FREQTGT_492_DEFAULT 0x1A4F5 ++#define PMU15_ARM_96MHZ 96000000 /* 96 Mhz */ ++#define PMU15_ARM_98MHZ 98400000 /* 98.4 Mhz */ ++#define PMU15_ARM_97MHZ 97000000 /* 97 Mhz */ ++ ++ ++#define PMU17_PLLCTL2_NDIVTYPE_MASK 0x00000070 ++#define PMU17_PLLCTL2_NDIVTYPE_SHIFT 4 ++ ++#define PMU17_PLLCTL2_NDIV_MODE_INT 0 ++#define PMU17_PLLCTL2_NDIV_MODE_INT1B8 1 ++#define PMU17_PLLCTL2_NDIV_MODE_MASH111 2 ++#define PMU17_PLLCTL2_NDIV_MODE_MASH111B8 3 ++ ++#define PMU17_PLLCTL0_BBPLL_PWRDWN 0 ++#define PMU17_PLLCTL0_BBPLL_DRST 3 ++#define PMU17_PLLCTL0_BBPLL_DISBL_CLK 8 ++ ++/* PLL usage in 4716/47162 */ ++#define PMU4716_MAINPLL_PLL0 12 ++ ++/* PLL usage in 5356/5357 */ ++#define PMU5356_MAINPLL_PLL0 0 ++#define PMU5357_MAINPLL_PLL0 0 ++ ++/* 4716/47162 resources */ ++#define RES4716_PROC_PLL_ON 0x00000040 ++#define RES4716_PROC_HT_AVAIL 0x00000080 ++ ++/* 4716/4717/4718 Chip specific ChipControl register bits */ ++#define CCTRL_471X_I2S_PINS_ENABLE 0x0080 /* I2S pins off by default, shared w/ pflash */ ++ ++/* 5357 Chip specific ChipControl register bits */ ++/* 2nd - 32-bit reg */ ++#define CCTRL_5357_I2S_PINS_ENABLE 0x00040000 /* I2S pins enable */ ++#define CCTRL_5357_I2CSPI_PINS_ENABLE 0x00080000 /* I2C/SPI pins enable */ ++ ++/* 5354 resources */ ++#define RES5354_EXT_SWITCHER_PWM 0 /* 0x00001 */ ++#define RES5354_BB_SWITCHER_PWM 1 /* 0x00002 */ ++#define RES5354_BB_SWITCHER_BURST 2 /* 0x00004 */ ++#define RES5354_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */ ++#define RES5354_ILP_REQUEST 4 /* 0x00010 */ ++#define RES5354_RADIO_SWITCHER_PWM 5 /* 0x00020 */ ++#define RES5354_RADIO_SWITCHER_BURST 6 /* 0x00040 */ ++#define RES5354_ROM_SWITCH 7 /* 0x00080 */ ++#define RES5354_PA_REF_LDO 8 /* 0x00100 */ ++#define RES5354_RADIO_LDO 9 /* 0x00200 */ ++#define RES5354_AFE_LDO 10 /* 0x00400 */ ++#define RES5354_PLL_LDO 11 /* 0x00800 */ ++#define RES5354_BG_FILTBYP 12 /* 0x01000 */ ++#define RES5354_TX_FILTBYP 13 /* 0x02000 */ ++#define RES5354_RX_FILTBYP 14 /* 0x04000 */ ++#define RES5354_XTAL_PU 15 /* 0x08000 */ ++#define RES5354_XTAL_EN 16 /* 0x10000 */ ++#define RES5354_BB_PLL_FILTBYP 17 /* 0x20000 */ ++#define RES5354_RF_PLL_FILTBYP 18 /* 0x40000 */ ++#define RES5354_BB_PLL_PU 19 /* 0x80000 */ ++ ++/* 5357 Chip specific ChipControl register bits */ ++#define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */ ++#define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */ ++#define CCTRL5357_NFLASH (1<<16) /* Nandflash in ChipControl 1, bit 16 */ ++ ++/* 43217 Chip specific ChipControl register bits */ ++#define CCTRL43217_EXTPA_C0 (1<<13) /* core0 extPA in ChipControl 1, bit 13 */ ++#define CCTRL43217_EXTPA_C1 (1<<8) /* core1 extPA in ChipControl 1, bit 8 */ ++ ++/* 4328 resources */ ++#define RES4328_EXT_SWITCHER_PWM 0 /* 0x00001 */ ++#define RES4328_BB_SWITCHER_PWM 1 /* 0x00002 */ ++#define RES4328_BB_SWITCHER_BURST 2 /* 0x00004 */ ++#define RES4328_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */ ++#define RES4328_ILP_REQUEST 4 /* 0x00010 */ ++#define RES4328_RADIO_SWITCHER_PWM 5 /* 0x00020 */ ++#define RES4328_RADIO_SWITCHER_BURST 6 /* 0x00040 */ ++#define RES4328_ROM_SWITCH 7 /* 0x00080 */ ++#define RES4328_PA_REF_LDO 8 /* 0x00100 */ ++#define RES4328_RADIO_LDO 9 /* 0x00200 */ ++#define RES4328_AFE_LDO 10 /* 0x00400 */ ++#define RES4328_PLL_LDO 11 /* 0x00800 */ ++#define RES4328_BG_FILTBYP 12 /* 0x01000 */ ++#define RES4328_TX_FILTBYP 13 /* 0x02000 */ ++#define RES4328_RX_FILTBYP 14 /* 0x04000 */ ++#define RES4328_XTAL_PU 15 /* 0x08000 */ ++#define RES4328_XTAL_EN 16 /* 0x10000 */ ++#define RES4328_BB_PLL_FILTBYP 17 /* 0x20000 */ ++#define RES4328_RF_PLL_FILTBYP 18 /* 0x40000 */ ++#define RES4328_BB_PLL_PU 19 /* 0x80000 */ ++ ++/* 4325 A0/A1 resources */ ++#define RES4325_BUCK_BOOST_BURST 0 /* 0x00000001 */ ++#define RES4325_CBUCK_BURST 1 /* 0x00000002 */ ++#define RES4325_CBUCK_PWM 2 /* 0x00000004 */ ++#define RES4325_CLDO_CBUCK_BURST 3 /* 0x00000008 */ ++#define RES4325_CLDO_CBUCK_PWM 4 /* 0x00000010 */ ++#define RES4325_BUCK_BOOST_PWM 5 /* 0x00000020 */ ++#define RES4325_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4325_ABUCK_BURST 7 /* 0x00000080 */ ++#define RES4325_ABUCK_PWM 8 /* 0x00000100 */ ++#define RES4325_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4325_OTP_PU 10 /* 0x00000400 */ ++#define RES4325_LNLDO3_PU 11 /* 0x00000800 */ ++#define RES4325_LNLDO4_PU 12 /* 0x00001000 */ ++#define RES4325_XTAL_PU 13 /* 0x00002000 */ ++#define RES4325_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4325_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4325_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4325_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4325_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4325_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4325_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4325_HT_AVAIL 21 /* 0x00200000 */ ++ ++/* 4325 B0/C0 resources */ ++#define RES4325B0_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4325B0_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4325B0_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4325B0_CLDO_PU 4 /* 0x00000010 */ ++ ++/* 4325 C1 resources */ ++#define RES4325C1_LNLDO2_PU 12 /* 0x00001000 */ ++ ++/* 4325 chip-specific ChipStatus register bits */ ++#define CST4325_SPROM_OTP_SEL_MASK 0x00000003 ++#define CST4325_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ ++#define CST4325_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ ++#define CST4325_OTP_SEL 2 /* OTP is powered up, no SPROM */ ++#define CST4325_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */ ++#define CST4325_SDIO_USB_MODE_MASK 0x00000004 ++#define CST4325_SDIO_USB_MODE_SHIFT 2 ++#define CST4325_RCAL_VALID_MASK 0x00000008 ++#define CST4325_RCAL_VALID_SHIFT 3 ++#define CST4325_RCAL_VALUE_MASK 0x000001f0 ++#define CST4325_RCAL_VALUE_SHIFT 4 ++#define CST4325_PMUTOP_2B_MASK 0x00000200 /* 1 for 2b, 0 for to 2a */ ++#define CST4325_PMUTOP_2B_SHIFT 9 ++ ++#define RES4329_RESERVED0 0 /* 0x00000001 */ ++#define RES4329_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4329_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4329_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4329_CLDO_PU 4 /* 0x00000010 */ ++#define RES4329_PALDO_PU 5 /* 0x00000020 */ ++#define RES4329_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4329_RESERVED7 7 /* 0x00000080 */ ++#define RES4329_RESERVED8 8 /* 0x00000100 */ ++#define RES4329_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4329_OTP_PU 10 /* 0x00000400 */ ++#define RES4329_RESERVED11 11 /* 0x00000800 */ ++#define RES4329_LNLDO2_PU 12 /* 0x00001000 */ ++#define RES4329_XTAL_PU 13 /* 0x00002000 */ ++#define RES4329_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4329_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4329_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4329_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4329_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4329_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4329_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4329_HT_AVAIL 21 /* 0x00200000 */ ++ ++#define CST4329_SPROM_OTP_SEL_MASK 0x00000003 ++#define CST4329_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ ++#define CST4329_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ ++#define CST4329_OTP_SEL 2 /* OTP is powered up, no SPROM */ ++#define CST4329_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */ ++#define CST4329_SPI_SDIO_MODE_MASK 0x00000004 ++#define CST4329_SPI_SDIO_MODE_SHIFT 2 ++ ++/* 4312 chip-specific ChipStatus register bits */ ++#define CST4312_SPROM_OTP_SEL_MASK 0x00000003 ++#define CST4312_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ ++#define CST4312_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ ++#define CST4312_OTP_SEL 2 /* OTP is powered up, no SPROM */ ++#define CST4312_OTP_BAD 3 /* OTP is broken, SPROM is present */ ++ ++/* 4312 resources (all PMU chips with little memory constraint) */ ++#define RES4312_SWITCHER_BURST 0 /* 0x00000001 */ ++#define RES4312_SWITCHER_PWM 1 /* 0x00000002 */ ++#define RES4312_PA_REF_LDO 2 /* 0x00000004 */ ++#define RES4312_CORE_LDO_BURST 3 /* 0x00000008 */ ++#define RES4312_CORE_LDO_PWM 4 /* 0x00000010 */ ++#define RES4312_RADIO_LDO 5 /* 0x00000020 */ ++#define RES4312_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4312_BG_FILTBYP 7 /* 0x00000080 */ ++#define RES4312_TX_FILTBYP 8 /* 0x00000100 */ ++#define RES4312_RX_FILTBYP 9 /* 0x00000200 */ ++#define RES4312_XTAL_PU 10 /* 0x00000400 */ ++#define RES4312_ALP_AVAIL 11 /* 0x00000800 */ ++#define RES4312_BB_PLL_FILTBYP 12 /* 0x00001000 */ ++#define RES4312_RF_PLL_FILTBYP 13 /* 0x00002000 */ ++#define RES4312_HT_AVAIL 14 /* 0x00004000 */ ++ ++/* 4322 resources */ ++#define RES4322_RF_LDO 0 ++#define RES4322_ILP_REQUEST 1 ++#define RES4322_XTAL_PU 2 ++#define RES4322_ALP_AVAIL 3 ++#define RES4322_SI_PLL_ON 4 ++#define RES4322_HT_SI_AVAIL 5 ++#define RES4322_PHY_PLL_ON 6 ++#define RES4322_HT_PHY_AVAIL 7 ++#define RES4322_OTP_PU 8 ++ ++/* 4322 chip-specific ChipStatus register bits */ ++#define CST4322_XTAL_FREQ_20_40MHZ 0x00000020 ++#define CST4322_SPROM_OTP_SEL_MASK 0x000000c0 ++#define CST4322_SPROM_OTP_SEL_SHIFT 6 ++#define CST4322_NO_SPROM_OTP 0 /* no OTP, no SPROM */ ++#define CST4322_SPROM_PRESENT 1 /* SPROM is present */ ++#define CST4322_OTP_PRESENT 2 /* OTP is present */ ++#define CST4322_PCI_OR_USB 0x00000100 ++#define CST4322_BOOT_MASK 0x00000600 ++#define CST4322_BOOT_SHIFT 9 ++#define CST4322_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ ++#define CST4322_BOOT_FROM_ROM 1 /* boot from ROM */ ++#define CST4322_BOOT_FROM_FLASH 2 /* boot from FLASH */ ++#define CST4322_BOOT_FROM_INVALID 3 ++#define CST4322_ILP_DIV_EN 0x00000800 ++#define CST4322_FLASH_TYPE_MASK 0x00001000 ++#define CST4322_FLASH_TYPE_SHIFT 12 ++#define CST4322_FLASH_TYPE_SHIFT_ST 0 /* ST serial FLASH */ ++#define CST4322_FLASH_TYPE_SHIFT_ATMEL 1 /* ATMEL flash */ ++#define CST4322_ARM_TAP_SEL 0x00002000 ++#define CST4322_RES_INIT_MODE_MASK 0x0000c000 ++#define CST4322_RES_INIT_MODE_SHIFT 14 ++#define CST4322_RES_INIT_MODE_ILPAVAIL 0 /* resinitmode: ILP available */ ++#define CST4322_RES_INIT_MODE_ILPREQ 1 /* resinitmode: ILP request */ ++#define CST4322_RES_INIT_MODE_ALPAVAIL 2 /* resinitmode: ALP available */ ++#define CST4322_RES_INIT_MODE_HTAVAIL 3 /* resinitmode: HT available */ ++#define CST4322_PCIPLLCLK_GATING 0x00010000 ++#define CST4322_CLK_SWITCH_PCI_TO_ALP 0x00020000 ++#define CST4322_PCI_CARDBUS_MODE 0x00040000 ++ ++/* 43224 chip-specific ChipControl register bits */ ++#define CCTRL43224_GPIO_TOGGLE 0x8000 /* gpio[3:0] pins as btcoex or s/w gpio */ ++#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */ ++#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */ ++ ++/* 43236 resources */ ++#define RES43236_REGULATOR 0 ++#define RES43236_ILP_REQUEST 1 ++#define RES43236_XTAL_PU 2 ++#define RES43236_ALP_AVAIL 3 ++#define RES43236_SI_PLL_ON 4 ++#define RES43236_HT_SI_AVAIL 5 ++ ++/* 43236 chip-specific ChipControl register bits */ ++#define CCTRL43236_BT_COEXIST (1<<0) /* 0 disable */ ++#define CCTRL43236_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ ++#define CCTRL43236_EXT_LNA (1<<2) /* 0 disable */ ++#define CCTRL43236_ANT_MUX_2o3 (1<<3) /* 2o3 mux, chipcontrol bit 3 */ ++#define CCTRL43236_GSIO (1<<4) /* 0 disable */ ++ ++/* 43236 Chip specific ChipStatus register bits */ ++#define CST43236_SFLASH_MASK 0x00000040 ++#define CST43236_OTP_SEL_MASK 0x00000080 ++#define CST43236_OTP_SEL_SHIFT 7 ++#define CST43236_HSIC_MASK 0x00000100 /* USB/HSIC */ ++#define CST43236_BP_CLK 0x00000200 /* 120/96Mbps */ ++#define CST43236_BOOT_MASK 0x00001800 ++#define CST43236_BOOT_SHIFT 11 ++#define CST43236_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ ++#define CST43236_BOOT_FROM_ROM 1 /* boot from ROM */ ++#define CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */ ++#define CST43236_BOOT_FROM_INVALID 3 ++ ++/* 43237 resources */ ++#define RES43237_REGULATOR 0 ++#define RES43237_ILP_REQUEST 1 ++#define RES43237_XTAL_PU 2 ++#define RES43237_ALP_AVAIL 3 ++#define RES43237_SI_PLL_ON 4 ++#define RES43237_HT_SI_AVAIL 5 ++ ++/* 43237 chip-specific ChipControl register bits */ ++#define CCTRL43237_BT_COEXIST (1<<0) /* 0 disable */ ++#define CCTRL43237_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ ++#define CCTRL43237_EXT_LNA (1<<2) /* 0 disable */ ++#define CCTRL43237_ANT_MUX_2o3 (1<<3) /* 2o3 mux, chipcontrol bit 3 */ ++#define CCTRL43237_GSIO (1<<4) /* 0 disable */ ++ ++/* 43237 Chip specific ChipStatus register bits */ ++#define CST43237_SFLASH_MASK 0x00000040 ++#define CST43237_OTP_SEL_MASK 0x00000080 ++#define CST43237_OTP_SEL_SHIFT 7 ++#define CST43237_HSIC_MASK 0x00000100 /* USB/HSIC */ ++#define CST43237_BP_CLK 0x00000200 /* 120/96Mbps */ ++#define CST43237_BOOT_MASK 0x00001800 ++#define CST43237_BOOT_SHIFT 11 ++#define CST43237_BOOT_FROM_SRAM 0 /* boot from SRAM, ARM in reset */ ++#define CST43237_BOOT_FROM_ROM 1 /* boot from ROM */ ++#define CST43237_BOOT_FROM_FLASH 2 /* boot from FLASH */ ++#define CST43237_BOOT_FROM_INVALID 3 ++ ++/* 43239 resources */ ++#define RES43239_OTP_PU 9 ++#define RES43239_MACPHY_CLKAVAIL 23 ++#define RES43239_HT_AVAIL 24 ++ ++/* 43239 Chip specific ChipStatus register bits */ ++#define CST43239_SPROM_MASK 0x00000002 ++#define CST43239_SFLASH_MASK 0x00000004 ++#define CST43239_RES_INIT_MODE_SHIFT 7 ++#define CST43239_RES_INIT_MODE_MASK 0x000001f0 ++#define CST43239_CHIPMODE_SDIOD(cs) ((cs) & (1 << 15)) /* SDIO || gSPI */ ++#define CST43239_CHIPMODE_USB20D(cs) (~(cs) & (1 << 15)) /* USB || USBDA */ ++#define CST43239_CHIPMODE_SDIO(cs) (((cs) & (1 << 0)) == 0) /* SDIO */ ++#define CST43239_CHIPMODE_GSPI(cs) (((cs) & (1 << 0)) == (1 << 0)) /* gSPI */ ++ ++/* 4324 resources */ ++#define RES4324_OTP_PU 10 ++#define RES4324_HT_AVAIL 29 ++#define RES4324_MACPHY_CLKAVAIL 30 ++ ++/* 4324 Chip specific ChipStatus register bits */ ++#define CST4324_SPROM_MASK 0x00000080 ++#define CST4324_SFLASH_MASK 0x00400000 ++#define CST4324_RES_INIT_MODE_SHIFT 10 ++#define CST4324_RES_INIT_MODE_MASK 0x00000c00 ++#define CST4324_CHIPMODE_MASK 0x7 ++#define CST4324_CHIPMODE_SDIOD(cs) ((~(cs)) & (1 << 2)) /* SDIO || gSPI */ ++#define CST4324_CHIPMODE_USB20D(cs) (((cs) & CST4324_CHIPMODE_MASK) == 0x6) /* USB || USBDA */ ++ ++/* 4331 resources */ ++#define RES4331_REGULATOR 0 ++#define RES4331_ILP_REQUEST 1 ++#define RES4331_XTAL_PU 2 ++#define RES4331_ALP_AVAIL 3 ++#define RES4331_SI_PLL_ON 4 ++#define RES4331_HT_SI_AVAIL 5 ++ ++/* 4331 chip-specific ChipControl register bits */ ++#define CCTRL4331_BT_COEXIST (1<<0) /* 0 disable */ ++#define CCTRL4331_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */ ++#define CCTRL4331_EXT_LNA_G (1<<2) /* 0 disable */ ++#define CCTRL4331_SPROM_GPIO13_15 (1<<3) /* sprom/gpio13-15 mux */ ++#define CCTRL4331_EXTPA_EN (1<<4) /* 0 ext pa disable, 1 ext pa enabled */ ++#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) /* set drive out GPIO_CLK on sprom_cs pin */ ++#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) /* use sprom_cs pin as PCIE mdio interface */ ++#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) /* aband extpa will be at gpio2/5 and sprom_dout */ ++#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) /* override core control on pipe_AuxClkEnable */ ++#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) /* override core control on pipe_AuxPowerDown */ ++#define CCTRL4331_PCIE_AUXCLKEN (1<<10) /* pcie_auxclkenable */ ++#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) /* pcie_pipe_pllpowerdown */ ++#define CCTRL4331_EXTPA_EN2 (1<<12) /* 0 ext pa disable, 1 ext pa enabled */ ++#define CCTRL4331_EXT_LNA_A (1<<13) /* 0 disable */ ++#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) /* enable bt_shd0 at gpio4 */ ++#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) /* enable bt_shd1 at gpio5 */ ++#define CCTRL4331_EXTPA_ANA_EN (1<<24) /* 0 ext pa disable, 1 ext pa enabled */ ++ ++/* 4331 Chip specific ChipStatus register bits */ ++#define CST4331_XTAL_FREQ 0x00000001 /* crystal frequency 20/40Mhz */ ++#define CST4331_SPROM_OTP_SEL_MASK 0x00000006 ++#define CST4331_SPROM_OTP_SEL_SHIFT 1 ++#define CST4331_SPROM_PRESENT 0x00000002 ++#define CST4331_OTP_PRESENT 0x00000004 ++#define CST4331_LDO_RF 0x00000008 ++#define CST4331_LDO_PAR 0x00000010 ++ ++/* 4315 resource */ ++#define RES4315_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4315_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4315_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4315_CLDO_PU 4 /* 0x00000010 */ ++#define RES4315_PALDO_PU 5 /* 0x00000020 */ ++#define RES4315_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4315_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4315_OTP_PU 10 /* 0x00000400 */ ++#define RES4315_LNLDO2_PU 12 /* 0x00001000 */ ++#define RES4315_XTAL_PU 13 /* 0x00002000 */ ++#define RES4315_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4315_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4315_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4315_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4315_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4315_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4315_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4315_HT_AVAIL 21 /* 0x00200000 */ ++ ++/* 4315 chip-specific ChipStatus register bits */ ++#define CST4315_SPROM_OTP_SEL_MASK 0x00000003 /* gpio [7:6], SDIO CIS selection */ ++#define CST4315_DEFCIS_SEL 0x00000000 /* use default CIS, OTP is powered up */ ++#define CST4315_SPROM_SEL 0x00000001 /* use SPROM, OTP is powered up */ ++#define CST4315_OTP_SEL 0x00000002 /* use OTP, OTP is powered up */ ++#define CST4315_OTP_PWRDN 0x00000003 /* use SPROM, OTP is powered down */ ++#define CST4315_SDIO_MODE 0x00000004 /* gpio [8], sdio/usb mode */ ++#define CST4315_RCAL_VALID 0x00000008 ++#define CST4315_RCAL_VALUE_MASK 0x000001f0 ++#define CST4315_RCAL_VALUE_SHIFT 4 ++#define CST4315_PALDO_EXTPNP 0x00000200 /* PALDO is configured with external PNP */ ++#define CST4315_CBUCK_MODE_MASK 0x00000c00 ++#define CST4315_CBUCK_MODE_BURST 0x00000400 ++#define CST4315_CBUCK_MODE_LPBURST 0x00000c00 ++ ++/* 4319 resources */ ++#define RES4319_CBUCK_LPOM 1 /* 0x00000002 */ ++#define RES4319_CBUCK_BURST 2 /* 0x00000004 */ ++#define RES4319_CBUCK_PWM 3 /* 0x00000008 */ ++#define RES4319_CLDO_PU 4 /* 0x00000010 */ ++#define RES4319_PALDO_PU 5 /* 0x00000020 */ ++#define RES4319_ILP_REQUEST 6 /* 0x00000040 */ ++#define RES4319_LNLDO1_PU 9 /* 0x00000200 */ ++#define RES4319_OTP_PU 10 /* 0x00000400 */ ++#define RES4319_LNLDO2_PU 12 /* 0x00001000 */ ++#define RES4319_XTAL_PU 13 /* 0x00002000 */ ++#define RES4319_ALP_AVAIL 14 /* 0x00004000 */ ++#define RES4319_RX_PWRSW_PU 15 /* 0x00008000 */ ++#define RES4319_TX_PWRSW_PU 16 /* 0x00010000 */ ++#define RES4319_RFPLL_PWRSW_PU 17 /* 0x00020000 */ ++#define RES4319_LOGEN_PWRSW_PU 18 /* 0x00040000 */ ++#define RES4319_AFE_PWRSW_PU 19 /* 0x00080000 */ ++#define RES4319_BBPLL_PWRSW_PU 20 /* 0x00100000 */ ++#define RES4319_HT_AVAIL 21 /* 0x00200000 */ ++ ++/* 4319 chip-specific ChipStatus register bits */ ++#define CST4319_SPI_CPULESSUSB 0x00000001 ++#define CST4319_SPI_CLK_POL 0x00000002 ++#define CST4319_SPI_CLK_PH 0x00000008 ++#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 /* gpio [7:6], SDIO CIS selection */ ++#define CST4319_SPROM_OTP_SEL_SHIFT 6 ++#define CST4319_DEFCIS_SEL 0x00000000 /* use default CIS, OTP is powered up */ ++#define CST4319_SPROM_SEL 0x00000040 /* use SPROM, OTP is powered up */ ++#define CST4319_OTP_SEL 0x00000080 /* use OTP, OTP is powered up */ ++#define CST4319_OTP_PWRDN 0x000000c0 /* use SPROM, OTP is powered down */ ++#define CST4319_SDIO_USB_MODE 0x00000100 /* gpio [8], sdio/usb mode */ ++#define CST4319_REMAP_SEL_MASK 0x00000600 ++#define CST4319_ILPDIV_EN 0x00000800 ++#define CST4319_XTAL_PD_POL 0x00001000 ++#define CST4319_LPO_SEL 0x00002000 ++#define CST4319_RES_INIT_MODE 0x0000c000 ++#define CST4319_PALDO_EXTPNP 0x00010000 /* PALDO is configured with external PNP */ ++#define CST4319_CBUCK_MODE_MASK 0x00060000 ++#define CST4319_CBUCK_MODE_BURST 0x00020000 ++#define CST4319_CBUCK_MODE_LPBURST 0x00060000 ++#define CST4319_RCAL_VALID 0x01000000 ++#define CST4319_RCAL_VALUE_MASK 0x3e000000 ++#define CST4319_RCAL_VALUE_SHIFT 25 ++ ++#define PMU1_PLL0_CHIPCTL0 0 ++#define PMU1_PLL0_CHIPCTL1 1 ++#define PMU1_PLL0_CHIPCTL2 2 ++#define CCTL_4319USB_XTAL_SEL_MASK 0x00180000 ++#define CCTL_4319USB_XTAL_SEL_SHIFT 19 ++#define CCTL_4319USB_48MHZ_PLL_SEL 1 ++#define CCTL_4319USB_24MHZ_PLL_SEL 2 ++ ++/* PMU resources for 4336 */ ++#define RES4336_CBUCK_LPOM 0 ++#define RES4336_CBUCK_BURST 1 ++#define RES4336_CBUCK_LP_PWM 2 ++#define RES4336_CBUCK_PWM 3 ++#define RES4336_CLDO_PU 4 ++#define RES4336_DIS_INT_RESET_PD 5 ++#define RES4336_ILP_REQUEST 6 ++#define RES4336_LNLDO_PU 7 ++#define RES4336_LDO3P3_PU 8 ++#define RES4336_OTP_PU 9 ++#define RES4336_XTAL_PU 10 ++#define RES4336_ALP_AVAIL 11 ++#define RES4336_RADIO_PU 12 ++#define RES4336_BG_PU 13 ++#define RES4336_VREG1p4_PU_PU 14 ++#define RES4336_AFE_PWRSW_PU 15 ++#define RES4336_RX_PWRSW_PU 16 ++#define RES4336_TX_PWRSW_PU 17 ++#define RES4336_BB_PWRSW_PU 18 ++#define RES4336_SYNTH_PWRSW_PU 19 ++#define RES4336_MISC_PWRSW_PU 20 ++#define RES4336_LOGEN_PWRSW_PU 21 ++#define RES4336_BBPLL_PWRSW_PU 22 ++#define RES4336_MACPHY_CLKAVAIL 23 ++#define RES4336_HT_AVAIL 24 ++#define RES4336_RSVD 25 ++ ++/* 4336 chip-specific ChipStatus register bits */ ++#define CST4336_SPI_MODE_MASK 0x00000001 ++#define CST4336_SPROM_PRESENT 0x00000002 ++#define CST4336_OTP_PRESENT 0x00000004 ++#define CST4336_ARMREMAP_0 0x00000008 ++#define CST4336_ILPDIV_EN_MASK 0x00000010 ++#define CST4336_ILPDIV_EN_SHIFT 4 ++#define CST4336_XTAL_PD_POL_MASK 0x00000020 ++#define CST4336_XTAL_PD_POL_SHIFT 5 ++#define CST4336_LPO_SEL_MASK 0x00000040 ++#define CST4336_LPO_SEL_SHIFT 6 ++#define CST4336_RES_INIT_MODE_MASK 0x00000180 ++#define CST4336_RES_INIT_MODE_SHIFT 7 ++#define CST4336_CBUCK_MODE_MASK 0x00000600 ++#define CST4336_CBUCK_MODE_SHIFT 9 ++ ++/* 4336 Chip specific PMU ChipControl register bits */ ++#define PCTL_4336_SERIAL_ENAB (1 << 24) ++ ++/* 4330 resources */ ++#define RES4330_CBUCK_LPOM 0 ++#define RES4330_CBUCK_BURST 1 ++#define RES4330_CBUCK_LP_PWM 2 ++#define RES4330_CBUCK_PWM 3 ++#define RES4330_CLDO_PU 4 ++#define RES4330_DIS_INT_RESET_PD 5 ++#define RES4330_ILP_REQUEST 6 ++#define RES4330_LNLDO_PU 7 ++#define RES4330_LDO3P3_PU 8 ++#define RES4330_OTP_PU 9 ++#define RES4330_XTAL_PU 10 ++#define RES4330_ALP_AVAIL 11 ++#define RES4330_RADIO_PU 12 ++#define RES4330_BG_PU 13 ++#define RES4330_VREG1p4_PU_PU 14 ++#define RES4330_AFE_PWRSW_PU 15 ++#define RES4330_RX_PWRSW_PU 16 ++#define RES4330_TX_PWRSW_PU 17 ++#define RES4330_BB_PWRSW_PU 18 ++#define RES4330_SYNTH_PWRSW_PU 19 ++#define RES4330_MISC_PWRSW_PU 20 ++#define RES4330_LOGEN_PWRSW_PU 21 ++#define RES4330_BBPLL_PWRSW_PU 22 ++#define RES4330_MACPHY_CLKAVAIL 23 ++#define RES4330_HT_AVAIL 24 ++#define RES4330_5gRX_PWRSW_PU 25 ++#define RES4330_5gTX_PWRSW_PU 26 ++#define RES4330_5g_LOGEN_PWRSW_PU 27 ++ ++/* 4330 chip-specific ChipStatus register bits */ ++#define CST4330_CHIPMODE_SDIOD(cs) (((cs) & 0x7) < 6) /* SDIO || gSPI */ ++#define CST4330_CHIPMODE_USB20D(cs) (((cs) & 0x7) >= 6) /* USB || USBDA */ ++#define CST4330_CHIPMODE_SDIO(cs) (((cs) & 0x4) == 0) /* SDIO */ ++#define CST4330_CHIPMODE_GSPI(cs) (((cs) & 0x6) == 4) /* gSPI */ ++#define CST4330_CHIPMODE_USB(cs) (((cs) & 0x7) == 6) /* USB packet-oriented */ ++#define CST4330_CHIPMODE_USBDA(cs) (((cs) & 0x7) == 7) /* USB Direct Access */ ++#define CST4330_OTP_PRESENT 0x00000010 ++#define CST4330_LPO_AUTODET_EN 0x00000020 ++#define CST4330_ARMREMAP_0 0x00000040 ++#define CST4330_SPROM_PRESENT 0x00000080 /* takes priority over OTP if both set */ ++#define CST4330_ILPDIV_EN 0x00000100 ++#define CST4330_LPO_SEL 0x00000200 ++#define CST4330_RES_INIT_MODE_SHIFT 10 ++#define CST4330_RES_INIT_MODE_MASK 0x00000c00 ++#define CST4330_CBUCK_MODE_SHIFT 12 ++#define CST4330_CBUCK_MODE_MASK 0x00003000 ++#define CST4330_CBUCK_POWER_OK 0x00004000 ++#define CST4330_BB_PLL_LOCKED 0x00008000 ++#define SOCDEVRAM_BP_ADDR 0x1E000000 ++#define SOCDEVRAM_ARM_ADDR 0x00800000 ++ ++/* 4330 Chip specific PMU ChipControl register bits */ ++#define PCTL_4330_SERIAL_ENAB (1 << 24) ++ ++/* 4330 Chip specific ChipControl register bits */ ++#define CCTRL_4330_GPIO_SEL 0x00000001 /* 1=select GPIOs to be muxed out */ ++#define CCTRL_4330_ERCX_SEL 0x00000002 /* 1=select ERCX BT coex to be muxed out */ ++#define CCTRL_4330_SDIO_HOST_WAKE 0x00000004 /* SDIO: 1=configure GPIO0 for host wake */ ++#define CCTRL_4330_JTAG_DISABLE 0x00000008 /* 1=disable JTAG interface on mux'd pins */ ++ ++#define PMU_VREG0_ADDR 0 ++#define PMU_VREG0_DISABLE_PULLD_BT_SHIFT 2 ++#define PMU_VREG0_DISABLE_PULLD_WL_SHIFT 3 ++ ++/* 4334 resources */ ++#define RES4334_LPLDO_PU 0 ++#define RES4334_RESET_PULLDN_DIS 1 ++#define RES4334_PMU_BG_PU 2 ++#define RES4334_HSIC_LDO_PU 3 ++#define RES4334_CBUCK_LPOM_PU 4 ++#define RES4334_CBUCK_PFM_PU 5 ++#define RES4334_CLDO_PU 6 ++#define RES4334_LPLDO2_LVM 7 ++#define RES4334_LNLDO_PU 8 ++#define RES4334_LDO3P3_PU 9 ++#define RES4334_OTP_PU 10 ++#define RES4334_XTAL_PU 11 ++#define RES4334_WL_PWRSW_PU 12 ++#define RES4334_LQ_AVAIL 13 ++#define RES4334_LOGIC_RET 14 ++#define RES4334_MEM_SLEEP 15 ++#define RES4334_MACPHY_RET 16 ++#define RES4334_WL_CORE_READY 17 ++#define RES4334_ILP_REQ 18 ++#define RES4334_ALP_AVAIL 19 ++#define RES4334_MISC_PWRSW_PU 20 ++#define RES4334_SYNTH_PWRSW_PU 21 ++#define RES4334_RX_PWRSW_PU 22 ++#define RES4334_RADIO_PU 23 ++#define RES4334_WL_PMU_PU 24 ++#define RES4334_VCO_LDO_PU 25 ++#define RES4334_AFE_LDO_PU 26 ++#define RES4334_RX_LDO_PU 27 ++#define RES4334_TX_LDO_PU 28 ++#define RES4334_HT_AVAIL 29 ++#define RES4334_MACPHY_CLK_AVAIL 30 ++ ++/* 4334 chip-specific ChipStatus register bits */ ++#define CST4334_CHIPMODE_MASK 7 ++#define CST4334_SDIO_MODE 0x00000000 ++#define CST4334_SPI_MODE 0x00000004 ++#define CST4334_HSIC_MODE 0x00000006 ++#define CST4334_BLUSB_MODE 0x00000007 ++#define CST4334_CHIPMODE_HSIC(cs) (((cs) & CST4334_CHIPMODE_MASK) == CST4334_HSIC_MODE) ++#define CST4334_OTP_PRESENT 0x00000010 ++#define CST4334_LPO_AUTODET_EN 0x00000020 ++#define CST4334_ARMREMAP_0 0x00000040 ++#define CST4334_SPROM_PRESENT 0x00000080 ++#define CST4334_ILPDIV_EN_MASK 0x00000100 ++#define CST4334_ILPDIV_EN_SHIFT 8 ++#define CST4334_LPO_SEL_MASK 0x00000200 ++#define CST4334_LPO_SEL_SHIFT 9 ++#define CST4334_RES_INIT_MODE_MASK 0x00000C00 ++#define CST4334_RES_INIT_MODE_SHIFT 10 ++ ++/* 4334 Chip specific PMU ChipControl register bits */ ++#define PCTL_4334_GPIO3_ENAB (1 << 3) ++ ++/* 4334 Chip control */ ++#define CCTRL4334_HSIC_LDO_PU (1 << 23) ++ ++/* 4324 Chip specific ChipControl1 register bits */ ++#define CCTRL1_4324_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */ ++#define CCTRL1_4324_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */ ++ ++ ++/* 4313 resources */ ++#define RES4313_BB_PU_RSRC 0 ++#define RES4313_ILP_REQ_RSRC 1 ++#define RES4313_XTAL_PU_RSRC 2 ++#define RES4313_ALP_AVAIL_RSRC 3 ++#define RES4313_RADIO_PU_RSRC 4 ++#define RES4313_BG_PU_RSRC 5 ++#define RES4313_VREG1P4_PU_RSRC 6 ++#define RES4313_AFE_PWRSW_RSRC 7 ++#define RES4313_RX_PWRSW_RSRC 8 ++#define RES4313_TX_PWRSW_RSRC 9 ++#define RES4313_BB_PWRSW_RSRC 10 ++#define RES4313_SYNTH_PWRSW_RSRC 11 ++#define RES4313_MISC_PWRSW_RSRC 12 ++#define RES4313_BB_PLL_PWRSW_RSRC 13 ++#define RES4313_HT_AVAIL_RSRC 14 ++#define RES4313_MACPHY_CLK_AVAIL_RSRC 15 ++ ++/* 4313 chip-specific ChipStatus register bits */ ++#define CST4313_SPROM_PRESENT 1 ++#define CST4313_OTP_PRESENT 2 ++#define CST4313_SPROM_OTP_SEL_MASK 0x00000002 ++#define CST4313_SPROM_OTP_SEL_SHIFT 0 ++ ++/* 4313 Chip specific ChipControl register bits */ ++#define CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */ ++ ++/* PMU respources for 4314 */ ++#define RES4314_LPLDO_PU 0 ++#define RES4314_PMU_SLEEP_DIS 1 ++#define RES4314_PMU_BG_PU 2 ++#define RES4314_CBUCK_LPOM_PU 3 ++#define RES4314_CBUCK_PFM_PU 4 ++#define RES4314_CLDO_PU 5 ++#define RES4314_LPLDO2_LVM 6 ++#define RES4314_WL_PMU_PU 7 ++#define RES4314_LNLDO_PU 8 ++#define RES4314_LDO3P3_PU 9 ++#define RES4314_OTP_PU 10 ++#define RES4314_XTAL_PU 11 ++#define RES4314_WL_PWRSW_PU 12 ++#define RES4314_LQ_AVAIL 13 ++#define RES4314_LOGIC_RET 14 ++#define RES4314_MEM_SLEEP 15 ++#define RES4314_MACPHY_RET 16 ++#define RES4314_WL_CORE_READY 17 ++#define RES4314_ILP_REQ 18 ++#define RES4314_ALP_AVAIL 19 ++#define RES4314_MISC_PWRSW_PU 20 ++#define RES4314_SYNTH_PWRSW_PU 21 ++#define RES4314_RX_PWRSW_PU 22 ++#define RES4314_RADIO_PU 23 ++#define RES4314_VCO_LDO_PU 24 ++#define RES4314_AFE_LDO_PU 25 ++#define RES4314_RX_LDO_PU 26 ++#define RES4314_TX_LDO_PU 27 ++#define RES4314_HT_AVAIL 28 ++#define RES4314_MACPHY_CLK_AVAIL 29 ++ ++/* 4314 chip-specific ChipStatus register bits */ ++#define CST4314_OTP_ENABLED 0x00200000 ++ ++/* 43228 resources */ ++#define RES43228_NOT_USED 0 ++#define RES43228_ILP_REQUEST 1 ++#define RES43228_XTAL_PU 2 ++#define RES43228_ALP_AVAIL 3 ++#define RES43228_PLL_EN 4 ++#define RES43228_HT_PHY_AVAIL 5 ++ ++/* 43228 chipstatus reg bits */ ++#define CST43228_ILP_DIV_EN 0x1 ++#define CST43228_OTP_PRESENT 0x2 ++#define CST43228_SERDES_REFCLK_PADSEL 0x4 ++#define CST43228_SDIO_MODE 0x8 ++#define CST43228_SDIO_OTP_PRESENT 0x10 ++#define CST43228_SDIO_RESET 0x20 ++ ++/* 4706 chipstatus reg bits */ ++#define CST4706_PKG_OPTION (1<<0) /* 0: full-featured package 1: low-cost package */ ++#define CST4706_SFLASH_PRESENT (1<<1) /* 0: parallel, 1: serial flash is present */ ++#define CST4706_SFLASH_TYPE (1<<2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */ ++#define CST4706_MIPS_BENDIAN (1<<3) /* 0: little, 1: big endian */ ++#define CST4706_PCIE1_DISABLE (1<<5) /* PCIE1 enable strap pin */ ++ ++/* 4706 flashstrconfig reg bits */ ++#define FLSTRCF4706_MASK 0x000000ff ++#define FLSTRCF4706_SF1 0x00000001 /* 2nd serial flash present */ ++#define FLSTRCF4706_PF1 0x00000002 /* 2nd parallel flash present */ ++#define FLSTRCF4706_SF1_TYPE 0x00000004 /* 2nd serial flash type : 0 : ST, 1 : Atmel */ ++#define FLSTRCF4706_NF1 0x00000008 /* 2nd NAND flash present */ ++#define FLSTRCF4706_1ST_MADDR_SEG_MASK 0x000000f0 /* Valid value mask */ ++#define FLSTRCF4706_1ST_MADDR_SEG_4MB 0x00000010 /* 4MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_8MB 0x00000020 /* 8MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_16MB 0x00000030 /* 16MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_32MB 0x00000040 /* 32MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_64MB 0x00000050 /* 64MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_128MB 0x00000060 /* 128MB */ ++#define FLSTRCF4706_1ST_MADDR_SEG_256MB 0x00000070 /* 256MB */ ++ ++/* 4360 Chip specific ChipControl register bits */ ++#define CCTRL4360_SECI_MODE (1 << 2) ++#define CCTRL4360_BTSWCTRL_MODE (1 << 3) ++#define CCTRL4360_EXTRA_FEMCTRL_MODE (1 << 8) ++#define CCTRL4360_BT_LGCY_MODE (1 << 9) ++#define CCTRL4360_CORE2FEMCTRL4_ON (1 << 21) ++ ++/* 4360 PMU resources and chip status bits */ ++#define RES4360_REGULATOR 0 ++#define RES4360_ILP_AVAIL 1 ++#define RES4360_ILP_REQ 2 ++#define RES4360_XTAL_LDO_PU 3 ++#define RES4360_XTAL_PU 4 ++#define RES4360_ALP_AVAIL 5 ++#define RES4360_BBPLLPWRSW_PU 6 ++#define RES4360_HT_AVAIL 7 ++#define RES4360_OTP_PU 8 ++ ++#define CST4360_XTAL_40MZ 0x00000001 ++#define CST4360_SFLASH 0x00000002 ++#define CST4360_SPROM_PRESENT 0x00000004 ++#define CST4360_SFLASH_TYPE 0x00000004 ++#define CST4360_OTP_ENABLED 0x00000008 ++#define CST4360_REMAP_ROM 0x00000010 ++#define CST4360_RSRC_INIT_MODE_MASK 0x00000060 ++#define CST4360_RSRC_INIT_MODE_SHIFT 5 ++#define CST4360_ILP_DIVEN 0x00000080 ++#define CST4360_MODE_USB 0x00000100 ++#define CST4360_SPROM_SIZE_MASK 0x00000600 ++#define CST4360_SPROM_SIZE_SHIFT 9 ++#define CST4360_BBPLL_LOCK 0x00000800 ++#define CST4360_AVBBPLL_LOCK 0x00001000 ++#define CST4360_USBBBPLL_LOCK 0x00002000 ++ ++#define CCTRL_4360_UART_SEL 0x2 ++ ++/* 4335 resources */ ++#define RES4335_LPLDO_PO 0 ++#define RES4335_PMU_BG_PU 1 ++#define RES4335_PMU_SLEEP 2 ++#define RES4335_RSVD_3 3 ++#define RES4335_CBUCK_LPOM_PU 4 ++#define RES4335_CBUCK_PFM_PU 5 ++#define RES4335_RSVD_6 6 ++#define RES4335_RSVD_7 7 ++#define RES4335_LNLDO_PU 8 ++#define RES4335_XTALLDO_PU 9 ++#define RES4335_LDO3P3_PU 10 ++#define RES4335_OTP_PU 11 ++#define RES4335_XTAL_PU 12 ++#define RES4335_SR_CLK_START 13 ++#define RES4335_LQ_AVAIL 14 ++#define RES4335_LQ_START 15 ++#define RES4335_RSVD_16 16 ++#define RES4335_WL_CORE_RDY 17 ++#define RES4335_ILP_REQ 18 ++#define RES4335_ALP_AVAIL 19 ++#define RES4335_MINI_PMU 20 ++#define RES4335_RADIO_PU 21 ++#define RES4335_SR_CLK_STABLE 22 ++#define RES4335_SR_SAVE_RESTORE 23 ++#define RES4335_SR_PHY_PWRSW 24 ++#define RES4335_SR_VDDM_PWRSW 25 ++#define RES4335_SR_SUBCORE_PWRSW 26 ++#define RES4335_SR_SLEEP 27 ++#define RES4335_HT_START 28 ++#define RES4335_HT_AVAIL 29 ++#define RES4335_MACPHY_CLKAVAIL 30 ++ ++/* 4335 Chip specific ChipStatus register bits */ ++#define CST4335_SPROM_MASK 0x00000020 ++#define CST4335_SFLASH_MASK 0x00000040 ++#define CST4335_RES_INIT_MODE_SHIFT 7 ++#define CST4335_RES_INIT_MODE_MASK 0x00000180 ++#define CST4335_CHIPMODE_MASK 0xF ++#define CST4335_CHIPMODE_SDIOD(cs) (((cs) & (1 << 0)) != 0) /* SDIO */ ++#define CST4335_CHIPMODE_GSPI(cs) (((cs) & (1 << 1)) != 0) /* gSPI */ ++#define CST4335_CHIPMODE_USB20D(cs) (((cs) & (1 << 2)) != 0) /* USB || USBDA */ ++#define CST4335_CHIPMODE_PCIE(cs) (((cs) & (1 << 3)) != 0) /* PCIE */ ++ ++/* 4335 Chip specific ChipControl1 register bits */ ++#define CCTRL1_4335_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */ ++#define CCTRL1_4335_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */ ++ ++ ++#define CR4_RAM_BASE (0x180000) ++ ++/* 4335 resources--END */ ++ ++/* GCI chipcontrol register indices */ ++#define CC_GCI_CHIPCTRL_00 (0) ++#define CC_GCI_CHIPCTRL_01 (1) ++#define CC_GCI_CHIPCTRL_02 (2) ++#define CC_GCI_CHIPCTRL_03 (3) ++#define CC_GCI_CHIPCTRL_04 (4) ++#define CC_GCI_CHIPCTRL_05 (5) ++#define CC_GCI_CHIPCTRL_06 (6) ++#define CC_GCI_CHIPCTRL_07 (7) ++#define CC_GCI_CHIPCTRL_08 (8) ++ ++#define CC_GCI_NUMCHIPCTRLREGS(cap1) ((cap1 & 0xF00) >> 8) ++ ++/* 4335 pins ++* note: only the values set as default/used are added here. ++*/ ++#define CC4335_PIN_GPIO_00 (0) ++#define CC4335_PIN_GPIO_01 (1) ++#define CC4335_PIN_GPIO_02 (2) ++#define CC4335_PIN_GPIO_03 (3) ++#define CC4335_PIN_GPIO_04 (4) ++#define CC4335_PIN_GPIO_05 (5) ++#define CC4335_PIN_GPIO_06 (6) ++#define CC4335_PIN_GPIO_07 (7) ++#define CC4335_PIN_GPIO_08 (8) ++#define CC4335_PIN_GPIO_09 (9) ++#define CC4335_PIN_GPIO_10 (10) ++#define CC4335_PIN_GPIO_11 (11) ++#define CC4335_PIN_GPIO_12 (12) ++#define CC4335_PIN_GPIO_13 (13) ++#define CC4335_PIN_GPIO_14 (14) ++#define CC4335_PIN_GPIO_15 (15) ++#define CC4335_PIN_SDIO_CLK (16) ++#define CC4335_PIN_SDIO_CMD (17) ++#define CC4335_PIN_SDIO_DATA0 (18) ++#define CC4335_PIN_SDIO_DATA1 (19) ++#define CC4335_PIN_SDIO_DATA2 (20) ++#define CC4335_PIN_SDIO_DATA3 (21) ++#define CC4335_PIN_RF_SW_CTRL_0 (22) ++#define CC4335_PIN_RF_SW_CTRL_1 (23) ++#define CC4335_PIN_RF_SW_CTRL_2 (24) ++#define CC4335_PIN_RF_SW_CTRL_3 (25) ++#define CC4335_PIN_RF_SW_CTRL_4 (26) ++#define CC4335_PIN_RF_SW_CTRL_5 (27) ++#define CC4335_PIN_RF_SW_CTRL_6 (28) ++#define CC4335_PIN_RF_SW_CTRL_7 (29) ++#define CC4335_PIN_RF_SW_CTRL_8 (30) ++#define CC4335_PIN_RF_SW_CTRL_9 (31) ++ ++/* 4335 GCI function sel values ++*/ ++#define CC4335_FNSEL_HWDEF (0) ++#define CC4335_FNSEL_SAMEASPIN (1) ++#define CC4335_FNSEL_GPIO0 (2) ++#define CC4335_FNSEL_GPIO1 (3) ++#define CC4335_FNSEL_GCI0 (4) ++#define CC4335_FNSEL_GCI1 (5) ++#define CC4335_FNSEL_UART (6) ++#define CC4335_FNSEL_SFLASH (7) ++#define CC4335_FNSEL_SPROM (8) ++#define CC4335_FNSEL_MISC0 (9) ++#define CC4335_FNSEL_MISC1 (10) ++#define CC4335_FNSEL_MISC2 (11) ++#define CC4335_FNSEL_IND (12) ++#define CC4335_FNSEL_PDN (13) ++#define CC4335_FNSEL_PUP (14) ++#define CC4335_FNSEL_TRI (15) ++ ++/* find the 4 bit mask given the bit position */ ++#define GCIMASK(pos) (((uint32)0xF) << pos) ++ ++/* get the value which can be used to directly OR with chipcontrol reg */ ++#define GCIPOSVAL(val, pos) ((((uint32)val) << pos) & GCIMASK(pos)) ++ ++/* 4335 MUX options. each nibble belongs to a setting. Non-zero value specifies a logic ++* for now only UART for bootloader. ++*/ ++#define MUXENAB4335_UART_MASK (0x0000000f) ++ ++ ++/* defines to detect active host interface in use */ ++#define CHIP_HOSTIF_USB(sih) (si_chip_hostif(sih) & CST4360_MODE_USB) ++ ++/* ++* Maximum delay for the PMU state transition in us. ++* This is an upper bound intended for spinwaits etc. ++*/ ++#define PMU_MAX_TRANSITION_DLY 15000 ++ ++/* PMU resource up transition time in ILP cycles */ ++#define PMURES_UP_TRANSITION 2 ++ ++ ++/* SECI configuration */ ++#define SECI_MODE_UART 0x0 ++#define SECI_MODE_SECI 0x1 ++#define SECI_MODE_LEGACY_3WIRE_BT 0x2 ++#define SECI_MODE_LEGACY_3WIRE_WLAN 0x3 ++#define SECI_MODE_HALF_SECI 0x4 ++ ++#define SECI_RESET (1 << 0) ++#define SECI_RESET_BAR_UART (1 << 1) ++#define SECI_ENAB_SECI_ECI (1 << 2) ++#define SECI_ENAB_SECIOUT_DIS (1 << 3) ++#define SECI_MODE_MASK 0x7 ++#define SECI_MODE_SHIFT 4 /* (bits 5, 6, 7) */ ++#define SECI_UPD_SECI (1 << 7) ++ ++#define SECI_SIGNOFF_0 0xDB ++#define SECI_SIGNOFF_1 0 ++ ++/* seci clk_ctl_st bits */ ++#define CLKCTL_STS_SECI_CLK_REQ (1 << 8) ++#define CLKCTL_STS_SECI_CLK_AVAIL (1 << 24) ++ ++#define SECI_UART_MSR_CTS_STATE (1 << 0) ++#define SECI_UART_MSR_RTS_STATE (1 << 1) ++#define SECI_UART_SECI_IN_STATE (1 << 2) ++#define SECI_UART_SECI_IN2_STATE (1 << 3) ++ ++/* SECI UART LCR/MCR register bits */ ++#define SECI_UART_LCR_STOP_BITS (1 << 0) /* 0 - 1bit, 1 - 2bits */ ++#define SECI_UART_LCR_PARITY_EN (1 << 1) ++#define SECI_UART_LCR_PARITY (1 << 2) /* 0 - odd, 1 - even */ ++#define SECI_UART_LCR_RX_EN (1 << 3) ++#define SECI_UART_LCR_LBRK_CTRL (1 << 4) /* 1 => SECI_OUT held low */ ++#define SECI_UART_LCR_TXO_EN (1 << 5) ++#define SECI_UART_LCR_RTSO_EN (1 << 6) ++#define SECI_UART_LCR_SLIPMODE_EN (1 << 7) ++#define SECI_UART_LCR_RXCRC_CHK (1 << 8) ++#define SECI_UART_LCR_TXCRC_INV (1 << 9) ++#define SECI_UART_LCR_TXCRC_LSBF (1 << 10) ++#define SECI_UART_LCR_TXCRC_EN (1 << 11) ++ ++#define SECI_UART_MCR_TX_EN (1 << 0) ++#define SECI_UART_MCR_PRTS (1 << 1) ++#define SECI_UART_MCR_SWFLCTRL_EN (1 << 2) ++#define SECI_UART_MCR_HIGHRATE_EN (1 << 3) ++#define SECI_UART_MCR_LOOPBK_EN (1 << 4) ++#define SECI_UART_MCR_AUTO_RTS (1 << 5) ++#define SECI_UART_MCR_AUTO_TX_DIS (1 << 6) ++#define SECI_UART_MCR_BAUD_ADJ_EN (1 << 7) ++#define SECI_UART_MCR_XONOFF_RPT (1 << 9) ++ ++/* WLAN channel numbers - used from wifi.h */ ++ ++/* WLAN BW */ ++#define ECI_BW_20 0x0 ++#define ECI_BW_25 0x1 ++#define ECI_BW_30 0x2 ++#define ECI_BW_35 0x3 ++#define ECI_BW_40 0x4 ++#define ECI_BW_45 0x5 ++#define ECI_BW_50 0x6 ++#define ECI_BW_ALL 0x7 ++ ++/* WLAN - number of antenna */ ++#define WLAN_NUM_ANT1 TXANT_0 ++#define WLAN_NUM_ANT2 TXANT_1 ++ ++#endif /* _SBCHIPC_H */ +diff --git a/drivers/net/wireless/ap6210/include/sbconfig.h b/drivers/net/wireless/ap6210/include/sbconfig.h +new file mode 100755 +index 0000000..73ddadd +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/sbconfig.h +@@ -0,0 +1,282 @@ ++/* ++ * Broadcom SiliconBackplane hardware register definitions. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: sbconfig.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _SBCONFIG_H ++#define _SBCONFIG_H ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif ++ ++/* enumeration in SB is based on the premise that cores are contiguos in the ++ * enumeration space. ++ */ ++#define SB_BUS_SIZE 0x10000 /* Each bus gets 64Kbytes for cores */ ++#define SB_BUS_BASE(b) (SI_ENUM_BASE + (b) * SB_BUS_SIZE) ++#define SB_BUS_MAXCORES (SB_BUS_SIZE / SI_CORE_SIZE) /* Max cores per bus */ ++ ++/* ++ * Sonics Configuration Space Registers. ++ */ ++#define SBCONFIGOFF 0xf00 /* core sbconfig regs are top 256bytes of regs */ ++#define SBCONFIGSIZE 256 /* sizeof (sbconfig_t) */ ++ ++#define SBIPSFLAG 0x08 ++#define SBTPSFLAG 0x18 ++#define SBTMERRLOGA 0x48 /* sonics >= 2.3 */ ++#define SBTMERRLOG 0x50 /* sonics >= 2.3 */ ++#define SBADMATCH3 0x60 ++#define SBADMATCH2 0x68 ++#define SBADMATCH1 0x70 ++#define SBIMSTATE 0x90 ++#define SBINTVEC 0x94 ++#define SBTMSTATELOW 0x98 ++#define SBTMSTATEHIGH 0x9c ++#define SBBWA0 0xa0 ++#define SBIMCONFIGLOW 0xa8 ++#define SBIMCONFIGHIGH 0xac ++#define SBADMATCH0 0xb0 ++#define SBTMCONFIGLOW 0xb8 ++#define SBTMCONFIGHIGH 0xbc ++#define SBBCONFIG 0xc0 ++#define SBBSTATE 0xc8 ++#define SBACTCNFG 0xd8 ++#define SBFLAGST 0xe8 ++#define SBIDLOW 0xf8 ++#define SBIDHIGH 0xfc ++ ++/* All the previous registers are above SBCONFIGOFF, but with Sonics 2.3, we have ++ * a few registers *below* that line. I think it would be very confusing to try ++ * and change the value of SBCONFIGOFF, so I'm definig them as absolute offsets here, ++ */ ++ ++#define SBIMERRLOGA 0xea8 ++#define SBIMERRLOG 0xeb0 ++#define SBTMPORTCONNID0 0xed8 ++#define SBTMPORTLOCK0 0xef8 ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++typedef volatile struct _sbconfig { ++ uint32 PAD[2]; ++ uint32 sbipsflag; /* initiator port ocp slave flag */ ++ uint32 PAD[3]; ++ uint32 sbtpsflag; /* target port ocp slave flag */ ++ uint32 PAD[11]; ++ uint32 sbtmerrloga; /* (sonics >= 2.3) */ ++ uint32 PAD; ++ uint32 sbtmerrlog; /* (sonics >= 2.3) */ ++ uint32 PAD[3]; ++ uint32 sbadmatch3; /* address match3 */ ++ uint32 PAD; ++ uint32 sbadmatch2; /* address match2 */ ++ uint32 PAD; ++ uint32 sbadmatch1; /* address match1 */ ++ uint32 PAD[7]; ++ uint32 sbimstate; /* initiator agent state */ ++ uint32 sbintvec; /* interrupt mask */ ++ uint32 sbtmstatelow; /* target state */ ++ uint32 sbtmstatehigh; /* target state */ ++ uint32 sbbwa0; /* bandwidth allocation table0 */ ++ uint32 PAD; ++ uint32 sbimconfiglow; /* initiator configuration */ ++ uint32 sbimconfighigh; /* initiator configuration */ ++ uint32 sbadmatch0; /* address match0 */ ++ uint32 PAD; ++ uint32 sbtmconfiglow; /* target configuration */ ++ uint32 sbtmconfighigh; /* target configuration */ ++ uint32 sbbconfig; /* broadcast configuration */ ++ uint32 PAD; ++ uint32 sbbstate; /* broadcast state */ ++ uint32 PAD[3]; ++ uint32 sbactcnfg; /* activate configuration */ ++ uint32 PAD[3]; ++ uint32 sbflagst; /* current sbflags */ ++ uint32 PAD[3]; ++ uint32 sbidlow; /* identification */ ++ uint32 sbidhigh; /* identification */ ++} sbconfig_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++/* sbipsflag */ ++#define SBIPS_INT1_MASK 0x3f /* which sbflags get routed to mips interrupt 1 */ ++#define SBIPS_INT1_SHIFT 0 ++#define SBIPS_INT2_MASK 0x3f00 /* which sbflags get routed to mips interrupt 2 */ ++#define SBIPS_INT2_SHIFT 8 ++#define SBIPS_INT3_MASK 0x3f0000 /* which sbflags get routed to mips interrupt 3 */ ++#define SBIPS_INT3_SHIFT 16 ++#define SBIPS_INT4_MASK 0x3f000000 /* which sbflags get routed to mips interrupt 4 */ ++#define SBIPS_INT4_SHIFT 24 ++ ++/* sbtpsflag */ ++#define SBTPS_NUM0_MASK 0x3f /* interrupt sbFlag # generated by this core */ ++#define SBTPS_F0EN0 0x40 /* interrupt is always sent on the backplane */ ++ ++/* sbtmerrlog */ ++#define SBTMEL_CM 0x00000007 /* command */ ++#define SBTMEL_CI 0x0000ff00 /* connection id */ ++#define SBTMEL_EC 0x0f000000 /* error code */ ++#define SBTMEL_ME 0x80000000 /* multiple error */ ++ ++/* sbimstate */ ++#define SBIM_PC 0xf /* pipecount */ ++#define SBIM_AP_MASK 0x30 /* arbitration policy */ ++#define SBIM_AP_BOTH 0x00 /* use both timeslaces and token */ ++#define SBIM_AP_TS 0x10 /* use timesliaces only */ ++#define SBIM_AP_TK 0x20 /* use token only */ ++#define SBIM_AP_RSV 0x30 /* reserved */ ++#define SBIM_IBE 0x20000 /* inbanderror */ ++#define SBIM_TO 0x40000 /* timeout */ ++#define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */ ++#define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */ ++ ++/* sbtmstatelow */ ++#define SBTML_RESET 0x0001 /* reset */ ++#define SBTML_REJ_MASK 0x0006 /* reject field */ ++#define SBTML_REJ 0x0002 /* reject */ ++#define SBTML_TMPREJ 0x0004 /* temporary reject, for error recovery */ ++ ++#define SBTML_SICF_SHIFT 16 /* Shift to locate the SI control flags in sbtml */ ++ ++/* sbtmstatehigh */ ++#define SBTMH_SERR 0x0001 /* serror */ ++#define SBTMH_INT 0x0002 /* interrupt */ ++#define SBTMH_BUSY 0x0004 /* busy */ ++#define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */ ++ ++#define SBTMH_SISF_SHIFT 16 /* Shift to locate the SI status flags in sbtmh */ ++ ++/* sbbwa0 */ ++#define SBBWA_TAB0_MASK 0xffff /* lookup table 0 */ ++#define SBBWA_TAB1_MASK 0xffff /* lookup table 1 */ ++#define SBBWA_TAB1_SHIFT 16 ++ ++/* sbimconfiglow */ ++#define SBIMCL_STO_MASK 0x7 /* service timeout */ ++#define SBIMCL_RTO_MASK 0x70 /* request timeout */ ++#define SBIMCL_RTO_SHIFT 4 ++#define SBIMCL_CID_MASK 0xff0000 /* connection id */ ++#define SBIMCL_CID_SHIFT 16 ++ ++/* sbimconfighigh */ ++#define SBIMCH_IEM_MASK 0xc /* inband error mode */ ++#define SBIMCH_TEM_MASK 0x30 /* timeout error mode */ ++#define SBIMCH_TEM_SHIFT 4 ++#define SBIMCH_BEM_MASK 0xc0 /* bus error mode */ ++#define SBIMCH_BEM_SHIFT 6 ++ ++/* sbadmatch0 */ ++#define SBAM_TYPE_MASK 0x3 /* address type */ ++#define SBAM_AD64 0x4 /* reserved */ ++#define SBAM_ADINT0_MASK 0xf8 /* type0 size */ ++#define SBAM_ADINT0_SHIFT 3 ++#define SBAM_ADINT1_MASK 0x1f8 /* type1 size */ ++#define SBAM_ADINT1_SHIFT 3 ++#define SBAM_ADINT2_MASK 0x1f8 /* type2 size */ ++#define SBAM_ADINT2_SHIFT 3 ++#define SBAM_ADEN 0x400 /* enable */ ++#define SBAM_ADNEG 0x800 /* negative decode */ ++#define SBAM_BASE0_MASK 0xffffff00 /* type0 base address */ ++#define SBAM_BASE0_SHIFT 8 ++#define SBAM_BASE1_MASK 0xfffff000 /* type1 base address for the core */ ++#define SBAM_BASE1_SHIFT 12 ++#define SBAM_BASE2_MASK 0xffff0000 /* type2 base address for the core */ ++#define SBAM_BASE2_SHIFT 16 ++ ++/* sbtmconfiglow */ ++#define SBTMCL_CD_MASK 0xff /* clock divide */ ++#define SBTMCL_CO_MASK 0xf800 /* clock offset */ ++#define SBTMCL_CO_SHIFT 11 ++#define SBTMCL_IF_MASK 0xfc0000 /* interrupt flags */ ++#define SBTMCL_IF_SHIFT 18 ++#define SBTMCL_IM_MASK 0x3000000 /* interrupt mode */ ++#define SBTMCL_IM_SHIFT 24 ++ ++/* sbtmconfighigh */ ++#define SBTMCH_BM_MASK 0x3 /* busy mode */ ++#define SBTMCH_RM_MASK 0x3 /* retry mode */ ++#define SBTMCH_RM_SHIFT 2 ++#define SBTMCH_SM_MASK 0x30 /* stop mode */ ++#define SBTMCH_SM_SHIFT 4 ++#define SBTMCH_EM_MASK 0x300 /* sb error mode */ ++#define SBTMCH_EM_SHIFT 8 ++#define SBTMCH_IM_MASK 0xc00 /* int mode */ ++#define SBTMCH_IM_SHIFT 10 ++ ++/* sbbconfig */ ++#define SBBC_LAT_MASK 0x3 /* sb latency */ ++#define SBBC_MAX0_MASK 0xf0000 /* maxccntr0 */ ++#define SBBC_MAX0_SHIFT 16 ++#define SBBC_MAX1_MASK 0xf00000 /* maxccntr1 */ ++#define SBBC_MAX1_SHIFT 20 ++ ++/* sbbstate */ ++#define SBBS_SRD 0x1 /* st reg disable */ ++#define SBBS_HRD 0x2 /* hold reg disable */ ++ ++/* sbidlow */ ++#define SBIDL_CS_MASK 0x3 /* config space */ ++#define SBIDL_AR_MASK 0x38 /* # address ranges supported */ ++#define SBIDL_AR_SHIFT 3 ++#define SBIDL_SYNCH 0x40 /* sync */ ++#define SBIDL_INIT 0x80 /* initiator */ ++#define SBIDL_MINLAT_MASK 0xf00 /* minimum backplane latency */ ++#define SBIDL_MINLAT_SHIFT 8 ++#define SBIDL_MAXLAT 0xf000 /* maximum backplane latency */ ++#define SBIDL_MAXLAT_SHIFT 12 ++#define SBIDL_FIRST 0x10000 /* this initiator is first */ ++#define SBIDL_CW_MASK 0xc0000 /* cycle counter width */ ++#define SBIDL_CW_SHIFT 18 ++#define SBIDL_TP_MASK 0xf00000 /* target ports */ ++#define SBIDL_TP_SHIFT 20 ++#define SBIDL_IP_MASK 0xf000000 /* initiator ports */ ++#define SBIDL_IP_SHIFT 24 ++#define SBIDL_RV_MASK 0xf0000000 /* sonics backplane revision code */ ++#define SBIDL_RV_SHIFT 28 ++#define SBIDL_RV_2_2 0x00000000 /* version 2.2 or earlier */ ++#define SBIDL_RV_2_3 0x10000000 /* version 2.3 */ ++ ++/* sbidhigh */ ++#define SBIDH_RC_MASK 0x000f /* revision code */ ++#define SBIDH_RCE_MASK 0x7000 /* revision code extension field */ ++#define SBIDH_RCE_SHIFT 8 ++#define SBCOREREV(sbidh) \ ++ ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK)) ++#define SBIDH_CC_MASK 0x8ff0 /* core code */ ++#define SBIDH_CC_SHIFT 4 ++#define SBIDH_VC_MASK 0xffff0000 /* vendor code */ ++#define SBIDH_VC_SHIFT 16 ++ ++#define SB_COMMIT 0xfd8 /* update buffered registers value */ ++ ++/* vendor codes */ ++#define SB_VEND_BCM 0x4243 /* Broadcom's SB vendor code */ ++ ++#endif /* _SBCONFIG_H */ +diff --git a/drivers/net/wireless/ap6210/include/sbhnddma.h b/drivers/net/wireless/ap6210/include/sbhnddma.h +new file mode 100755 +index 0000000..40ebd8a +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/sbhnddma.h +@@ -0,0 +1,384 @@ ++/* ++ * Generic Broadcom Home Networking Division (HND) DMA engine HW interface ++ * This supports the following chips: BCM42xx, 44xx, 47xx . ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: sbhnddma.h 309193 2012-01-19 00:03:57Z $ ++ */ ++ ++#ifndef _sbhnddma_h_ ++#define _sbhnddma_h_ ++ ++/* DMA structure: ++ * support two DMA engines: 32 bits address or 64 bit addressing ++ * basic DMA register set is per channel(transmit or receive) ++ * a pair of channels is defined for convenience ++ */ ++ ++ ++/* 32 bits addressing */ ++ ++/* dma registers per channel(xmt or rcv) */ ++typedef volatile struct { ++ uint32 control; /* enable, et al */ ++ uint32 addr; /* descriptor ring base address (4K aligned) */ ++ uint32 ptr; /* last descriptor posted to chip */ ++ uint32 status; /* current active descriptor, et al */ ++} dma32regs_t; ++ ++typedef volatile struct { ++ dma32regs_t xmt; /* dma tx channel */ ++ dma32regs_t rcv; /* dma rx channel */ ++} dma32regp_t; ++ ++typedef volatile struct { /* diag access */ ++ uint32 fifoaddr; /* diag address */ ++ uint32 fifodatalow; /* low 32bits of data */ ++ uint32 fifodatahigh; /* high 32bits of data */ ++ uint32 pad; /* reserved */ ++} dma32diag_t; ++ ++/* ++ * DMA Descriptor ++ * Descriptors are only read by the hardware, never written back. ++ */ ++typedef volatile struct { ++ uint32 ctrl; /* misc control bits & bufcount */ ++ uint32 addr; /* data buffer address */ ++} dma32dd_t; ++ ++/* ++ * Each descriptor ring must be 4096byte aligned, and fit within a single 4096byte page. ++ */ ++#define D32RINGALIGN_BITS 12 ++#define D32MAXRINGSZ (1 << D32RINGALIGN_BITS) ++#define D32RINGALIGN (1 << D32RINGALIGN_BITS) ++ ++#define D32MAXDD (D32MAXRINGSZ / sizeof (dma32dd_t)) ++ ++/* transmit channel control */ ++#define XC_XE ((uint32)1 << 0) /* transmit enable */ ++#define XC_SE ((uint32)1 << 1) /* transmit suspend request */ ++#define XC_LE ((uint32)1 << 2) /* loopback enable */ ++#define XC_FL ((uint32)1 << 4) /* flush request */ ++#define XC_MR_MASK 0x000000C0 /* Multiple outstanding reads */ ++#define XC_MR_SHIFT 6 ++#define XC_PD ((uint32)1 << 11) /* parity check disable */ ++#define XC_AE ((uint32)3 << 16) /* address extension bits */ ++#define XC_AE_SHIFT 16 ++#define XC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define XC_BL_SHIFT 18 ++#define XC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define XC_PC_SHIFT 21 ++#define XC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define XC_PT_SHIFT 24 ++ ++/* Multiple outstanding reads */ ++#define DMA_MR_1 0 ++#define DMA_MR_2 1 ++/* 2, 3: reserved */ ++ ++/* DMA Burst Length in bytes */ ++#define DMA_BL_16 0 ++#define DMA_BL_32 1 ++#define DMA_BL_64 2 ++#define DMA_BL_128 3 ++#define DMA_BL_256 4 ++#define DMA_BL_512 5 ++#define DMA_BL_1024 6 ++ ++/* Prefetch control */ ++#define DMA_PC_0 0 ++#define DMA_PC_4 1 ++#define DMA_PC_8 2 ++#define DMA_PC_16 3 ++/* others: reserved */ ++ ++/* Prefetch threshold */ ++#define DMA_PT_1 0 ++#define DMA_PT_2 1 ++#define DMA_PT_4 2 ++#define DMA_PT_8 3 ++ ++/* transmit descriptor table pointer */ ++#define XP_LD_MASK 0xfff /* last valid descriptor */ ++ ++/* transmit channel status */ ++#define XS_CD_MASK 0x0fff /* current descriptor pointer */ ++#define XS_XS_MASK 0xf000 /* transmit state */ ++#define XS_XS_SHIFT 12 ++#define XS_XS_DISABLED 0x0000 /* disabled */ ++#define XS_XS_ACTIVE 0x1000 /* active */ ++#define XS_XS_IDLE 0x2000 /* idle wait */ ++#define XS_XS_STOPPED 0x3000 /* stopped */ ++#define XS_XS_SUSP 0x4000 /* suspend pending */ ++#define XS_XE_MASK 0xf0000 /* transmit errors */ ++#define XS_XE_SHIFT 16 ++#define XS_XE_NOERR 0x00000 /* no error */ ++#define XS_XE_DPE 0x10000 /* descriptor protocol error */ ++#define XS_XE_DFU 0x20000 /* data fifo underrun */ ++#define XS_XE_BEBR 0x30000 /* bus error on buffer read */ ++#define XS_XE_BEDA 0x40000 /* bus error on descriptor access */ ++#define XS_AD_MASK 0xfff00000 /* active descriptor */ ++#define XS_AD_SHIFT 20 ++ ++/* receive channel control */ ++#define RC_RE ((uint32)1 << 0) /* receive enable */ ++#define RC_RO_MASK 0xfe /* receive frame offset */ ++#define RC_RO_SHIFT 1 ++#define RC_FM ((uint32)1 << 8) /* direct fifo receive (pio) mode */ ++#define RC_SH ((uint32)1 << 9) /* separate rx header descriptor enable */ ++#define RC_OC ((uint32)1 << 10) /* overflow continue */ ++#define RC_PD ((uint32)1 << 11) /* parity check disable */ ++#define RC_AE ((uint32)3 << 16) /* address extension bits */ ++#define RC_AE_SHIFT 16 ++#define RC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define RC_BL_SHIFT 18 ++#define RC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define RC_PC_SHIFT 21 ++#define RC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define RC_PT_SHIFT 24 ++ ++/* receive descriptor table pointer */ ++#define RP_LD_MASK 0xfff /* last valid descriptor */ ++ ++/* receive channel status */ ++#define RS_CD_MASK 0x0fff /* current descriptor pointer */ ++#define RS_RS_MASK 0xf000 /* receive state */ ++#define RS_RS_SHIFT 12 ++#define RS_RS_DISABLED 0x0000 /* disabled */ ++#define RS_RS_ACTIVE 0x1000 /* active */ ++#define RS_RS_IDLE 0x2000 /* idle wait */ ++#define RS_RS_STOPPED 0x3000 /* reserved */ ++#define RS_RE_MASK 0xf0000 /* receive errors */ ++#define RS_RE_SHIFT 16 ++#define RS_RE_NOERR 0x00000 /* no error */ ++#define RS_RE_DPE 0x10000 /* descriptor protocol error */ ++#define RS_RE_DFO 0x20000 /* data fifo overflow */ ++#define RS_RE_BEBW 0x30000 /* bus error on buffer write */ ++#define RS_RE_BEDA 0x40000 /* bus error on descriptor access */ ++#define RS_AD_MASK 0xfff00000 /* active descriptor */ ++#define RS_AD_SHIFT 20 ++ ++/* fifoaddr */ ++#define FA_OFF_MASK 0xffff /* offset */ ++#define FA_SEL_MASK 0xf0000 /* select */ ++#define FA_SEL_SHIFT 16 ++#define FA_SEL_XDD 0x00000 /* transmit dma data */ ++#define FA_SEL_XDP 0x10000 /* transmit dma pointers */ ++#define FA_SEL_RDD 0x40000 /* receive dma data */ ++#define FA_SEL_RDP 0x50000 /* receive dma pointers */ ++#define FA_SEL_XFD 0x80000 /* transmit fifo data */ ++#define FA_SEL_XFP 0x90000 /* transmit fifo pointers */ ++#define FA_SEL_RFD 0xc0000 /* receive fifo data */ ++#define FA_SEL_RFP 0xd0000 /* receive fifo pointers */ ++#define FA_SEL_RSD 0xe0000 /* receive frame status data */ ++#define FA_SEL_RSP 0xf0000 /* receive frame status pointers */ ++ ++/* descriptor control flags */ ++#define CTRL_BC_MASK 0x00001fff /* buffer byte count, real data len must <= 4KB */ ++#define CTRL_AE ((uint32)3 << 16) /* address extension bits */ ++#define CTRL_AE_SHIFT 16 ++#define CTRL_PARITY ((uint32)3 << 18) /* parity bit */ ++#define CTRL_EOT ((uint32)1 << 28) /* end of descriptor table */ ++#define CTRL_IOC ((uint32)1 << 29) /* interrupt on completion */ ++#define CTRL_EOF ((uint32)1 << 30) /* end of frame */ ++#define CTRL_SOF ((uint32)1 << 31) /* start of frame */ ++ ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define CTRL_CORE_MASK 0x0ff00000 ++ ++/* 64 bits addressing */ ++ ++/* dma registers per channel(xmt or rcv) */ ++typedef volatile struct { ++ uint32 control; /* enable, et al */ ++ uint32 ptr; /* last descriptor posted to chip */ ++ uint32 addrlow; /* descriptor ring base address low 32-bits (8K aligned) */ ++ uint32 addrhigh; /* descriptor ring base address bits 63:32 (8K aligned) */ ++ uint32 status0; /* current descriptor, xmt state */ ++ uint32 status1; /* active descriptor, xmt error */ ++} dma64regs_t; ++ ++typedef volatile struct { ++ dma64regs_t tx; /* dma64 tx channel */ ++ dma64regs_t rx; /* dma64 rx channel */ ++} dma64regp_t; ++ ++typedef volatile struct { /* diag access */ ++ uint32 fifoaddr; /* diag address */ ++ uint32 fifodatalow; /* low 32bits of data */ ++ uint32 fifodatahigh; /* high 32bits of data */ ++ uint32 pad; /* reserved */ ++} dma64diag_t; ++ ++/* ++ * DMA Descriptor ++ * Descriptors are only read by the hardware, never written back. ++ */ ++typedef volatile struct { ++ uint32 ctrl1; /* misc control bits */ ++ uint32 ctrl2; /* buffer count and address extension */ ++ uint32 addrlow; /* memory address of the date buffer, bits 31:0 */ ++ uint32 addrhigh; /* memory address of the date buffer, bits 63:32 */ ++} dma64dd_t; ++ ++/* ++ * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical addresss. ++ */ ++#define D64RINGALIGN_BITS 13 ++#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS) ++#define D64RINGALIGN (1 << D64RINGALIGN_BITS) ++ ++#define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t)) ++ ++/* transmit channel control */ ++#define D64_XC_XE 0x00000001 /* transmit enable */ ++#define D64_XC_SE 0x00000002 /* transmit suspend request */ ++#define D64_XC_LE 0x00000004 /* loopback enable */ ++#define D64_XC_FL 0x00000010 /* flush request */ ++#define D64_XC_MR_MASK 0x000000C0 /* Multiple outstanding reads */ ++#define D64_XC_MR_SHIFT 6 ++#define D64_XC_PD 0x00000800 /* parity check disable */ ++#define D64_XC_AE 0x00030000 /* address extension bits */ ++#define D64_XC_AE_SHIFT 16 ++#define D64_XC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define D64_XC_BL_SHIFT 18 ++#define D64_XC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define D64_XC_PC_SHIFT 21 ++#define D64_XC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define D64_XC_PT_SHIFT 24 ++ ++/* transmit descriptor table pointer */ ++#define D64_XP_LD_MASK 0x00001fff /* last valid descriptor */ ++ ++/* transmit channel status */ ++#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */ ++#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */ ++#define D64_XS0_XS_SHIFT 28 ++#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */ ++#define D64_XS0_XS_ACTIVE 0x10000000 /* active */ ++#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */ ++#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */ ++#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */ ++ ++#define D64_XS1_AD_MASK 0x00001fff /* active descriptor */ ++#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */ ++#define D64_XS1_XE_SHIFT 28 ++#define D64_XS1_XE_NOERR 0x00000000 /* no error */ ++#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */ ++#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */ ++#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */ ++#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */ ++#define D64_XS1_XE_COREE 0x50000000 /* core error */ ++ ++/* receive channel control */ ++#define D64_RC_RE 0x00000001 /* receive enable */ ++#define D64_RC_RO_MASK 0x000000fe /* receive frame offset */ ++#define D64_RC_RO_SHIFT 1 ++#define D64_RC_FM 0x00000100 /* direct fifo receive (pio) mode */ ++#define D64_RC_SH 0x00000200 /* separate rx header descriptor enable */ ++#define D64_RC_OC 0x00000400 /* overflow continue */ ++#define D64_RC_PD 0x00000800 /* parity check disable */ ++#define D64_RC_AE 0x00030000 /* address extension bits */ ++#define D64_RC_AE_SHIFT 16 ++#define D64_RC_BL_MASK 0x001C0000 /* BurstLen bits */ ++#define D64_RC_BL_SHIFT 18 ++#define D64_RC_PC_MASK 0x00E00000 /* Prefetch control */ ++#define D64_RC_PC_SHIFT 21 ++#define D64_RC_PT_MASK 0x03000000 /* Prefetch threshold */ ++#define D64_RC_PT_SHIFT 24 ++ ++/* flags for dma controller */ ++#define DMA_CTRL_PEN (1 << 0) /* partity enable */ ++#define DMA_CTRL_ROC (1 << 1) /* rx overflow continue */ ++#define DMA_CTRL_RXMULTI (1 << 2) /* allow rx scatter to multiple descriptors */ ++#define DMA_CTRL_UNFRAMED (1 << 3) /* Unframed Rx/Tx data */ ++#define DMA_CTRL_USB_BOUNDRY4KB_WAR (1 << 4) ++#define DMA_CTRL_DMA_AVOIDANCE_WAR (1 << 5) /* DMA avoidance WAR for 4331 */ ++ ++/* receive descriptor table pointer */ ++#define D64_RP_LD_MASK 0x00001fff /* last valid descriptor */ ++ ++/* receive channel status */ ++#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */ ++#define D64_RS0_RS_MASK 0xf0000000 /* receive state */ ++#define D64_RS0_RS_SHIFT 28 ++#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */ ++#define D64_RS0_RS_ACTIVE 0x10000000 /* active */ ++#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */ ++#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */ ++#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */ ++ ++#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */ ++#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */ ++#define D64_RS1_RE_SHIFT 28 ++#define D64_RS1_RE_NOERR 0x00000000 /* no error */ ++#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */ ++#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */ ++#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */ ++#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */ ++#define D64_RS1_RE_COREE 0x50000000 /* core error */ ++ ++/* fifoaddr */ ++#define D64_FA_OFF_MASK 0xffff /* offset */ ++#define D64_FA_SEL_MASK 0xf0000 /* select */ ++#define D64_FA_SEL_SHIFT 16 ++#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */ ++#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */ ++#define D64_FA_SEL_RDD 0x40000 /* receive dma data */ ++#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */ ++#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */ ++#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */ ++#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */ ++#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */ ++#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */ ++#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */ ++ ++/* descriptor control flags 1 */ ++#define D64_CTRL_COREFLAGS 0x0ff00000 /* core specific flags */ ++#define D64_CTRL1_EOT ((uint32)1 << 28) /* end of descriptor table */ ++#define D64_CTRL1_IOC ((uint32)1 << 29) /* interrupt on completion */ ++#define D64_CTRL1_EOF ((uint32)1 << 30) /* end of frame */ ++#define D64_CTRL1_SOF ((uint32)1 << 31) /* start of frame */ ++ ++/* descriptor control flags 2 */ ++#define D64_CTRL2_BC_MASK 0x00007fff /* buffer byte count. real data len must <= 16KB */ ++#define D64_CTRL2_AE 0x00030000 /* address extension bits */ ++#define D64_CTRL2_AE_SHIFT 16 ++#define D64_CTRL2_PARITY 0x00040000 /* parity bit */ ++ ++/* control flags in the range [27:20] are core-specific and not defined here */ ++#define D64_CTRL_CORE_MASK 0x0ff00000 ++ ++#define D64_RX_FRM_STS_LEN 0x0000ffff /* frame length mask */ ++#define D64_RX_FRM_STS_OVFL 0x00800000 /* RxOverFlow */ ++#define D64_RX_FRM_STS_DSCRCNT 0x0f000000 /* no. of descriptors used - 1, d11corerev >= 22 */ ++#define D64_RX_FRM_STS_DATATYPE 0xf0000000 /* core-dependent data type */ ++ ++/* receive frame status */ ++typedef volatile struct { ++ uint16 len; ++ uint16 flags; ++} dma_rxh_t; ++ ++#endif /* _sbhnddma_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/sbpcmcia.h b/drivers/net/wireless/ap6210/include/sbpcmcia.h +new file mode 100755 +index 0000000..c4e9d46 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/sbpcmcia.h +@@ -0,0 +1,113 @@ ++/* ++ * BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: sbpcmcia.h 326494 2012-04-09 13:29:57Z $ ++ */ ++ ++#ifndef _SBPCMCIA_H ++#define _SBPCMCIA_H ++ ++/* All the addresses that are offsets in attribute space are divided ++ * by two to account for the fact that odd bytes are invalid in ++ * attribute space and our read/write routines make the space appear ++ * as if they didn't exist. Still we want to show the original numbers ++ * as documented in the hnd_pcmcia core manual. ++ */ ++ ++/* PCMCIA Function Configuration Registers */ ++#define PCMCIA_FCR (0x700 / 2) ++ ++#define FCR0_OFF 0 ++#define FCR1_OFF (0x40 / 2) ++#define FCR2_OFF (0x80 / 2) ++#define FCR3_OFF (0xc0 / 2) ++ ++#define PCMCIA_FCR0 (0x700 / 2) ++#define PCMCIA_FCR1 (0x740 / 2) ++#define PCMCIA_FCR2 (0x780 / 2) ++#define PCMCIA_FCR3 (0x7c0 / 2) ++ ++/* Standard PCMCIA FCR registers */ ++ ++#define PCMCIA_COR 0 ++ ++#define COR_RST 0x80 ++#define COR_LEV 0x40 ++#define COR_IRQEN 0x04 ++#define COR_BLREN 0x01 ++#define COR_FUNEN 0x01 ++ ++ ++#define PCICIA_FCSR (2 / 2) ++#define PCICIA_PRR (4 / 2) ++#define PCICIA_SCR (6 / 2) ++#define PCICIA_ESR (8 / 2) ++ ++ ++#define PCM_MEMOFF 0x0000 ++#define F0_MEMOFF 0x1000 ++#define F1_MEMOFF 0x2000 ++#define F2_MEMOFF 0x3000 ++#define F3_MEMOFF 0x4000 ++ ++/* Memory base in the function fcr's */ ++#define MEM_ADDR0 (0x728 / 2) ++#define MEM_ADDR1 (0x72a / 2) ++#define MEM_ADDR2 (0x72c / 2) ++ ++/* PCMCIA base plus Srom access in fcr0: */ ++#define PCMCIA_ADDR0 (0x072e / 2) ++#define PCMCIA_ADDR1 (0x0730 / 2) ++#define PCMCIA_ADDR2 (0x0732 / 2) ++ ++#define MEM_SEG (0x0734 / 2) ++#define SROM_CS (0x0736 / 2) ++#define SROM_DATAL (0x0738 / 2) ++#define SROM_DATAH (0x073a / 2) ++#define SROM_ADDRL (0x073c / 2) ++#define SROM_ADDRH (0x073e / 2) ++#define SROM_INFO2 (0x0772 / 2) /* Corerev >= 2 && <= 5 */ ++#define SROM_INFO (0x07be / 2) /* Corerev >= 6 */ ++ ++/* Values for srom_cs: */ ++#define SROM_IDLE 0 ++#define SROM_WRITE 1 ++#define SROM_READ 2 ++#define SROM_WEN 4 ++#define SROM_WDS 7 ++#define SROM_DONE 8 ++ ++/* Fields in srom_info: */ ++#define SRI_SZ_MASK 0x03 ++#define SRI_BLANK 0x04 ++#define SRI_OTP 0x80 ++ ++ ++/* sbtmstatelow */ ++#define SBTML_INT_ACK 0x40000 /* ack the sb interrupt */ ++#define SBTML_INT_EN 0x20000 /* enable sb interrupt */ ++ ++/* sbtmstatehigh */ ++#define SBTMH_INT_STATUS 0x40000 /* sb interrupt status */ ++ ++#endif /* _SBPCMCIA_H */ +diff --git a/drivers/net/wireless/ap6210/include/sbsdio.h b/drivers/net/wireless/ap6210/include/sbsdio.h +new file mode 100755 +index 0000000..8d0139d +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/sbsdio.h +@@ -0,0 +1,188 @@ ++/* ++ * SDIO device core hardware definitions. ++ * sdio is a portion of the pcmcia core in core rev 3 - rev 8 ++ * ++ * SDIO core support 1bit, 4 bit SDIO mode as well as SPI mode. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: sbsdio.h 361940 2012-10-10 08:32:12Z $ ++ */ ++ ++#ifndef _SBSDIO_H ++#define _SBSDIO_H ++ ++#define SBSDIO_NUM_FUNCTION 3 /* as of sdiod rev 0, supports 3 functions */ ++ ++/* function 1 miscellaneous registers */ ++#define SBSDIO_SPROM_CS 0x10000 /* sprom command and status */ ++#define SBSDIO_SPROM_INFO 0x10001 /* sprom info register */ ++#define SBSDIO_SPROM_DATA_LOW 0x10002 /* sprom indirect access data byte 0 */ ++#define SBSDIO_SPROM_DATA_HIGH 0x10003 /* sprom indirect access data byte 1 */ ++#define SBSDIO_SPROM_ADDR_LOW 0x10004 /* sprom indirect access addr byte 0 */ ++#define SBSDIO_SPROM_ADDR_HIGH 0x10005 /* sprom indirect access addr byte 0 */ ++#define SBSDIO_CHIP_CTRL_DATA 0x10006 /* xtal_pu (gpio) output */ ++#define SBSDIO_CHIP_CTRL_EN 0x10007 /* xtal_pu (gpio) enable */ ++#define SBSDIO_WATERMARK 0x10008 /* rev < 7, watermark for sdio device */ ++#define SBSDIO_DEVICE_CTL 0x10009 /* control busy signal generation */ ++ ++/* registers introduced in rev 8, some content (mask/bits) defs in sbsdpcmdev.h */ ++#define SBSDIO_FUNC1_SBADDRLOW 0x1000A /* SB Address Window Low (b15) */ ++#define SBSDIO_FUNC1_SBADDRMID 0x1000B /* SB Address Window Mid (b23:b16) */ ++#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C /* SB Address Window High (b31:b24) */ ++#define SBSDIO_FUNC1_FRAMECTRL 0x1000D /* Frame Control (frame term/abort) */ ++#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E /* ChipClockCSR (ALP/HT ctl/status) */ ++#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F /* SdioPullUp (on cmd, d0-d2) */ ++#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019 /* Write Frame Byte Count Low */ ++#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A /* Write Frame Byte Count High */ ++#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B /* Read Frame Byte Count Low */ ++#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C /* Read Frame Byte Count High */ ++#define SBSDIO_FUNC1_MESBUSYCTRL 0x1001D /* MesBusyCtl at 0x1001D (rev 11) */ ++ ++#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */ ++#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */ ++ ++/* Sdio Core Rev 12 */ ++#define SBSDIO_FUNC1_WAKEUPCTRL 0x1001E ++#define SBSDIO_FUNC1_WCTRL_ALPWAIT_MASK 0x1 ++#define SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT 0 ++#define SBSDIO_FUNC1_WCTRL_HTWAIT_MASK 0x2 ++#define SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT 1 ++#define SBSDIO_FUNC1_SLEEPCSR 0x1001F ++#define SBSDIO_FUNC1_SLEEPCSR_KSO_MASK 0x1 ++#define SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT 0 ++#define SBSDIO_FUNC1_SLEEPCSR_KSO_EN 1 ++#define SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK 0x2 ++#define SBSDIO_FUNC1_SLEEPCSR_DEVON_SHIFT 1 ++ ++/* SBSDIO_SPROM_CS */ ++#define SBSDIO_SPROM_IDLE 0 ++#define SBSDIO_SPROM_WRITE 1 ++#define SBSDIO_SPROM_READ 2 ++#define SBSDIO_SPROM_WEN 4 ++#define SBSDIO_SPROM_WDS 7 ++#define SBSDIO_SPROM_DONE 8 ++ ++/* SBSDIO_SPROM_INFO */ ++#define SROM_SZ_MASK 0x03 /* SROM size, 1: 4k, 2: 16k */ ++#define SROM_BLANK 0x04 /* depreciated in corerev 6 */ ++#define SROM_OTP 0x80 /* OTP present */ ++ ++/* SBSDIO_CHIP_CTRL */ ++#define SBSDIO_CHIP_CTRL_XTAL 0x01 /* or'd with onchip xtal_pu, ++ * 1: power on oscillator ++ * (for 4318 only) ++ */ ++/* SBSDIO_WATERMARK */ ++#define SBSDIO_WATERMARK_MASK 0x7f /* number of words - 1 for sd device ++ * to wait before sending data to host ++ */ ++ ++/* SBSDIO_MESBUSYCTRL */ ++/* When RX FIFO has less entries than this & MBE is set ++ * => busy signal is asserted between data blocks. ++*/ ++#define SBSDIO_MESBUSYCTRL_MASK 0x7f ++ ++/* SBSDIO_DEVICE_CTL */ ++#define SBSDIO_DEVCTL_SETBUSY 0x01 /* 1: device will assert busy signal when ++ * receiving CMD53 ++ */ ++#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02 /* 1: assertion of sdio interrupt is ++ * synchronous to the sdio clock ++ */ ++#define SBSDIO_DEVCTL_CA_INT_ONLY 0x04 /* 1: mask all interrupts to host ++ * except the chipActive (rev 8) ++ */ ++#define SBSDIO_DEVCTL_PADS_ISO 0x08 /* 1: isolate internal sdio signals, put ++ * external pads in tri-state; requires ++ * sdio bus power cycle to clear (rev 9) ++ */ ++#define SBSDIO_DEVCTL_SB_RST_CTL 0x30 /* Force SD->SB reset mapping (rev 11) */ ++#define SBSDIO_DEVCTL_RST_CORECTL 0x00 /* Determined by CoreControl bit */ ++#define SBSDIO_DEVCTL_RST_BPRESET 0x10 /* Force backplane reset */ ++#define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 /* Force no backplane reset */ ++#define SBSDIO_DEVCTL_EN_F2_BLK_WATERMARK 0x10 /* Enable function 2 tx for each block */ ++ ++ ++/* SBSDIO_FUNC1_CHIPCLKCSR */ ++#define SBSDIO_FORCE_ALP 0x01 /* Force ALP request to backplane */ ++#define SBSDIO_FORCE_HT 0x02 /* Force HT request to backplane */ ++#define SBSDIO_FORCE_ILP 0x04 /* Force ILP request to backplane */ ++#define SBSDIO_ALP_AVAIL_REQ 0x08 /* Make ALP ready (power up xtal) */ ++#define SBSDIO_HT_AVAIL_REQ 0x10 /* Make HT ready (power up PLL) */ ++#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20 /* Squelch clock requests from HW */ ++#define SBSDIO_ALP_AVAIL 0x40 /* Status: ALP is ready */ ++#define SBSDIO_HT_AVAIL 0x80 /* Status: HT is ready */ ++/* In rev8, actual avail bits followed original docs */ ++#define SBSDIO_Rev8_HT_AVAIL 0x40 ++#define SBSDIO_Rev8_ALP_AVAIL 0x80 ++#define SBSDIO_CSR_MASK 0x1F ++ ++#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL) ++#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS) ++#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS) ++#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval)) ++#define SBSDIO_CLKAV(regval, alponly) (SBSDIO_ALPAV(regval) && \ ++ (alponly ? 1 : SBSDIO_HTAV(regval))) ++ ++/* SBSDIO_FUNC1_SDIOPULLUP */ ++#define SBSDIO_PULLUP_D0 0x01 /* Enable D0/MISO pullup */ ++#define SBSDIO_PULLUP_D1 0x02 /* Enable D1/INT# pullup */ ++#define SBSDIO_PULLUP_D2 0x04 /* Enable D2 pullup */ ++#define SBSDIO_PULLUP_CMD 0x08 /* Enable CMD/MOSI pullup */ ++#define SBSDIO_PULLUP_ALL 0x0f /* All valid bits */ ++ ++/* function 1 OCP space */ ++#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF /* sb offset addr is <= 15 bits, 32k */ ++#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000 ++#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 /* with b15, maps to 32-bit SB access */ ++ ++/* some duplication with sbsdpcmdev.h here */ ++/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */ ++#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */ ++#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */ ++#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */ ++#define SBSDIO_SBWINDOW_MASK 0xffff8000 /* Address bits from SBADDR regs */ ++ ++/* direct(mapped) cis space */ ++#define SBSDIO_CIS_BASE_COMMON 0x1000 /* MAPPED common CIS address */ ++#define SBSDIO_CIS_SIZE_LIMIT 0x200 /* maximum bytes in one CIS */ ++#define SBSDIO_OTP_CIS_SIZE_LIMIT 0x078 /* maximum bytes OTP CIS */ ++ ++#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF /* cis offset addr is < 17 bits */ ++ ++#define SBSDIO_CIS_MANFID_TUPLE_LEN 6 /* manfid tuple length, include tuple, ++ * link bytes ++ */ ++ ++/* indirect cis access (in sprom) */ ++#define SBSDIO_SPROM_CIS_OFFSET 0x8 /* 8 control bytes first, CIS starts from ++ * 8th byte ++ */ ++ ++#define SBSDIO_BYTEMODE_DATALEN_MAX 64 /* sdio byte mode: maximum length of one ++ * data comamnd ++ */ ++ ++#define SBSDIO_CORE_ADDR_MASK 0x1FFFF /* sdio core function one address mask */ ++ ++#endif /* _SBSDIO_H */ +diff --git a/drivers/net/wireless/ap6210/include/sbsdpcmdev.h b/drivers/net/wireless/ap6210/include/sbsdpcmdev.h +new file mode 100755 +index 0000000..10c7401 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/sbsdpcmdev.h +@@ -0,0 +1,295 @@ ++/* ++ * Broadcom SiliconBackplane SDIO/PCMCIA hardware-specific ++ * device core support ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: sbsdpcmdev.h 347614 2012-07-27 10:24:51Z $ ++ */ ++ ++#ifndef _sbsdpcmdev_h_ ++#define _sbsdpcmdev_h_ ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++ ++typedef volatile struct { ++ dma64regs_t xmt; /* dma tx */ ++ uint32 PAD[2]; ++ dma64regs_t rcv; /* dma rx */ ++ uint32 PAD[2]; ++} dma64p_t; ++ ++/* dma64 sdiod corerev >= 1 */ ++typedef volatile struct { ++ dma64p_t dma64regs[2]; ++ dma64diag_t dmafifo; /* DMA Diagnostic Regs, 0x280-0x28c */ ++ uint32 PAD[92]; ++} sdiodma64_t; ++ ++/* dma32 sdiod corerev == 0 */ ++typedef volatile struct { ++ dma32regp_t dma32regs[2]; /* dma tx & rx, 0x200-0x23c */ ++ dma32diag_t dmafifo; /* DMA Diagnostic Regs, 0x240-0x24c */ ++ uint32 PAD[108]; ++} sdiodma32_t; ++ ++/* dma32 regs for pcmcia core */ ++typedef volatile struct { ++ dma32regp_t dmaregs; /* DMA Regs, 0x200-0x21c, rev8 */ ++ dma32diag_t dmafifo; /* DMA Diagnostic Regs, 0x220-0x22c */ ++ uint32 PAD[116]; ++} pcmdma32_t; ++ ++/* core registers */ ++typedef volatile struct { ++ uint32 corecontrol; /* CoreControl, 0x000, rev8 */ ++ uint32 corestatus; /* CoreStatus, 0x004, rev8 */ ++ uint32 PAD[1]; ++ uint32 biststatus; /* BistStatus, 0x00c, rev8 */ ++ ++ /* PCMCIA access */ ++ uint16 pcmciamesportaladdr; /* PcmciaMesPortalAddr, 0x010, rev8 */ ++ uint16 PAD[1]; ++ uint16 pcmciamesportalmask; /* PcmciaMesPortalMask, 0x014, rev8 */ ++ uint16 PAD[1]; ++ uint16 pcmciawrframebc; /* PcmciaWrFrameBC, 0x018, rev8 */ ++ uint16 PAD[1]; ++ uint16 pcmciaunderflowtimer; /* PcmciaUnderflowTimer, 0x01c, rev8 */ ++ uint16 PAD[1]; ++ ++ /* interrupt */ ++ uint32 intstatus; /* IntStatus, 0x020, rev8 */ ++ uint32 hostintmask; /* IntHostMask, 0x024, rev8 */ ++ uint32 intmask; /* IntSbMask, 0x028, rev8 */ ++ uint32 sbintstatus; /* SBIntStatus, 0x02c, rev8 */ ++ uint32 sbintmask; /* SBIntMask, 0x030, rev8 */ ++ uint32 funcintmask; /* SDIO Function Interrupt Mask, SDIO rev4 */ ++ uint32 PAD[2]; ++ uint32 tosbmailbox; /* ToSBMailbox, 0x040, rev8 */ ++ uint32 tohostmailbox; /* ToHostMailbox, 0x044, rev8 */ ++ uint32 tosbmailboxdata; /* ToSbMailboxData, 0x048, rev8 */ ++ uint32 tohostmailboxdata; /* ToHostMailboxData, 0x04c, rev8 */ ++ ++ /* synchronized access to registers in SDIO clock domain */ ++ uint32 sdioaccess; /* SdioAccess, 0x050, rev8 */ ++ uint32 PAD[3]; ++ ++ /* PCMCIA frame control */ ++ uint8 pcmciaframectrl; /* pcmciaFrameCtrl, 0x060, rev8 */ ++ uint8 PAD[3]; ++ uint8 pcmciawatermark; /* pcmciaWaterMark, 0x064, rev8 */ ++ uint8 PAD[155]; ++ ++ /* interrupt batching control */ ++ uint32 intrcvlazy; /* IntRcvLazy, 0x100, rev8 */ ++ uint32 PAD[3]; ++ ++ /* counters */ ++ uint32 cmd52rd; /* Cmd52RdCount, 0x110, rev8, SDIO: cmd52 reads */ ++ uint32 cmd52wr; /* Cmd52WrCount, 0x114, rev8, SDIO: cmd52 writes */ ++ uint32 cmd53rd; /* Cmd53RdCount, 0x118, rev8, SDIO: cmd53 reads */ ++ uint32 cmd53wr; /* Cmd53WrCount, 0x11c, rev8, SDIO: cmd53 writes */ ++ uint32 abort; /* AbortCount, 0x120, rev8, SDIO: aborts */ ++ uint32 datacrcerror; /* DataCrcErrorCount, 0x124, rev8, SDIO: frames w/bad CRC */ ++ uint32 rdoutofsync; /* RdOutOfSyncCount, 0x128, rev8, SDIO/PCMCIA: Rd Frm OOS */ ++ uint32 wroutofsync; /* RdOutOfSyncCount, 0x12c, rev8, SDIO/PCMCIA: Wr Frm OOS */ ++ uint32 writebusy; /* WriteBusyCount, 0x130, rev8, SDIO: dev asserted "busy" */ ++ uint32 readwait; /* ReadWaitCount, 0x134, rev8, SDIO: read: no data avail */ ++ uint32 readterm; /* ReadTermCount, 0x138, rev8, SDIO: rd frm terminates */ ++ uint32 writeterm; /* WriteTermCount, 0x13c, rev8, SDIO: wr frm terminates */ ++ uint32 PAD[40]; ++ uint32 clockctlstatus; /* ClockCtlStatus, 0x1e0, rev8 */ ++ uint32 PAD[7]; ++ ++ /* DMA engines */ ++ volatile union { ++ pcmdma32_t pcm32; ++ sdiodma32_t sdiod32; ++ sdiodma64_t sdiod64; ++ } dma; ++ ++ /* SDIO/PCMCIA CIS region */ ++ char cis[512]; /* 512 byte CIS, 0x400-0x5ff, rev6 */ ++ ++ /* PCMCIA function control registers */ ++ char pcmciafcr[256]; /* PCMCIA FCR, 0x600-6ff, rev6 */ ++ uint16 PAD[55]; ++ ++ /* PCMCIA backplane access */ ++ uint16 backplanecsr; /* BackplaneCSR, 0x76E, rev6 */ ++ uint16 backplaneaddr0; /* BackplaneAddr0, 0x770, rev6 */ ++ uint16 backplaneaddr1; /* BackplaneAddr1, 0x772, rev6 */ ++ uint16 backplaneaddr2; /* BackplaneAddr2, 0x774, rev6 */ ++ uint16 backplaneaddr3; /* BackplaneAddr3, 0x776, rev6 */ ++ uint16 backplanedata0; /* BackplaneData0, 0x778, rev6 */ ++ uint16 backplanedata1; /* BackplaneData1, 0x77a, rev6 */ ++ uint16 backplanedata2; /* BackplaneData2, 0x77c, rev6 */ ++ uint16 backplanedata3; /* BackplaneData3, 0x77e, rev6 */ ++ uint16 PAD[31]; ++ ++ /* sprom "size" & "blank" info */ ++ uint16 spromstatus; /* SPROMStatus, 0x7BE, rev2 */ ++ uint32 PAD[464]; ++ ++ /* Sonics SiliconBackplane registers */ ++ sbconfig_t sbconfig; /* SbConfig Regs, 0xf00-0xfff, rev8 */ ++} sdpcmd_regs_t; ++ ++/* corecontrol */ ++#define CC_CISRDY (1 << 0) /* CIS Ready */ ++#define CC_BPRESEN (1 << 1) /* CCCR RES signal causes backplane reset */ ++#define CC_F2RDY (1 << 2) /* set CCCR IOR2 bit */ ++#define CC_CLRPADSISO (1 << 3) /* clear SDIO pads isolation bit (rev 11) */ ++#define CC_XMTDATAAVAIL_MODE (1 << 4) /* data avail generates an interrupt */ ++#define CC_XMTDATAAVAIL_CTRL (1 << 5) /* data avail interrupt ctrl */ ++ ++/* corestatus */ ++#define CS_PCMCIAMODE (1 << 0) /* Device Mode; 0=SDIO, 1=PCMCIA */ ++#define CS_SMARTDEV (1 << 1) /* 1=smartDev enabled */ ++#define CS_F2ENABLED (1 << 2) /* 1=host has enabled the device */ ++ ++#define PCMCIA_MES_PA_MASK 0x7fff /* PCMCIA Message Portal Address Mask */ ++#define PCMCIA_MES_PM_MASK 0x7fff /* PCMCIA Message Portal Mask Mask */ ++#define PCMCIA_WFBC_MASK 0xffff /* PCMCIA Write Frame Byte Count Mask */ ++#define PCMCIA_UT_MASK 0x07ff /* PCMCIA Underflow Timer Mask */ ++ ++/* intstatus */ ++#define I_SMB_SW0 (1 << 0) /* To SB Mail S/W interrupt 0 */ ++#define I_SMB_SW1 (1 << 1) /* To SB Mail S/W interrupt 1 */ ++#define I_SMB_SW2 (1 << 2) /* To SB Mail S/W interrupt 2 */ ++#define I_SMB_SW3 (1 << 3) /* To SB Mail S/W interrupt 3 */ ++#define I_SMB_SW_MASK 0x0000000f /* To SB Mail S/W interrupts mask */ ++#define I_SMB_SW_SHIFT 0 /* To SB Mail S/W interrupts shift */ ++#define I_HMB_SW0 (1 << 4) /* To Host Mail S/W interrupt 0 */ ++#define I_HMB_SW1 (1 << 5) /* To Host Mail S/W interrupt 1 */ ++#define I_HMB_SW2 (1 << 6) /* To Host Mail S/W interrupt 2 */ ++#define I_HMB_SW3 (1 << 7) /* To Host Mail S/W interrupt 3 */ ++#define I_HMB_SW_MASK 0x000000f0 /* To Host Mail S/W interrupts mask */ ++#define I_HMB_SW_SHIFT 4 /* To Host Mail S/W interrupts shift */ ++#define I_WR_OOSYNC (1 << 8) /* Write Frame Out Of Sync */ ++#define I_RD_OOSYNC (1 << 9) /* Read Frame Out Of Sync */ ++#define I_PC (1 << 10) /* descriptor error */ ++#define I_PD (1 << 11) /* data error */ ++#define I_DE (1 << 12) /* Descriptor protocol Error */ ++#define I_RU (1 << 13) /* Receive descriptor Underflow */ ++#define I_RO (1 << 14) /* Receive fifo Overflow */ ++#define I_XU (1 << 15) /* Transmit fifo Underflow */ ++#define I_RI (1 << 16) /* Receive Interrupt */ ++#define I_BUSPWR (1 << 17) /* SDIO Bus Power Change (rev 9) */ ++#define I_XMTDATA_AVAIL (1 << 23) /* bits in fifo */ ++#define I_XI (1 << 24) /* Transmit Interrupt */ ++#define I_RF_TERM (1 << 25) /* Read Frame Terminate */ ++#define I_WF_TERM (1 << 26) /* Write Frame Terminate */ ++#define I_PCMCIA_XU (1 << 27) /* PCMCIA Transmit FIFO Underflow */ ++#define I_SBINT (1 << 28) /* sbintstatus Interrupt */ ++#define I_CHIPACTIVE (1 << 29) /* chip transitioned from doze to active state */ ++#define I_SRESET (1 << 30) /* CCCR RES interrupt */ ++#define I_IOE2 (1U << 31) /* CCCR IOE2 Bit Changed */ ++#define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU) /* DMA Errors */ ++#define I_DMA (I_RI | I_XI | I_ERRORS) ++ ++/* sbintstatus */ ++#define I_SB_SERR (1 << 8) /* Backplane SError (write) */ ++#define I_SB_RESPERR (1 << 9) /* Backplane Response Error (read) */ ++#define I_SB_SPROMERR (1 << 10) /* Error accessing the sprom */ ++ ++/* sdioaccess */ ++#define SDA_DATA_MASK 0x000000ff /* Read/Write Data Mask */ ++#define SDA_ADDR_MASK 0x000fff00 /* Read/Write Address Mask */ ++#define SDA_ADDR_SHIFT 8 /* Read/Write Address Shift */ ++#define SDA_WRITE 0x01000000 /* Write bit */ ++#define SDA_READ 0x00000000 /* Write bit cleared for Read */ ++#define SDA_BUSY 0x80000000 /* Busy bit */ ++ ++/* sdioaccess-accessible register address spaces */ ++#define SDA_CCCR_SPACE 0x000 /* sdioAccess CCCR register space */ ++#define SDA_F1_FBR_SPACE 0x100 /* sdioAccess F1 FBR register space */ ++#define SDA_F2_FBR_SPACE 0x200 /* sdioAccess F2 FBR register space */ ++#define SDA_F1_REG_SPACE 0x300 /* sdioAccess F1 core-specific register space */ ++ ++/* SDA_F1_REG_SPACE sdioaccess-accessible F1 reg space register offsets */ ++#define SDA_CHIPCONTROLDATA 0x006 /* ChipControlData */ ++#define SDA_CHIPCONTROLENAB 0x007 /* ChipControlEnable */ ++#define SDA_F2WATERMARK 0x008 /* Function 2 Watermark */ ++#define SDA_DEVICECONTROL 0x009 /* DeviceControl */ ++#define SDA_SBADDRLOW 0x00a /* SbAddrLow */ ++#define SDA_SBADDRMID 0x00b /* SbAddrMid */ ++#define SDA_SBADDRHIGH 0x00c /* SbAddrHigh */ ++#define SDA_FRAMECTRL 0x00d /* FrameCtrl */ ++#define SDA_CHIPCLOCKCSR 0x00e /* ChipClockCSR */ ++#define SDA_SDIOPULLUP 0x00f /* SdioPullUp */ ++#define SDA_SDIOWRFRAMEBCLOW 0x019 /* SdioWrFrameBCLow */ ++#define SDA_SDIOWRFRAMEBCHIGH 0x01a /* SdioWrFrameBCHigh */ ++#define SDA_SDIORDFRAMEBCLOW 0x01b /* SdioRdFrameBCLow */ ++#define SDA_SDIORDFRAMEBCHIGH 0x01c /* SdioRdFrameBCHigh */ ++ ++/* SDA_F2WATERMARK */ ++#define SDA_F2WATERMARK_MASK 0x7f /* F2Watermark Mask */ ++ ++/* SDA_SBADDRLOW */ ++#define SDA_SBADDRLOW_MASK 0x80 /* SbAddrLow Mask */ ++ ++/* SDA_SBADDRMID */ ++#define SDA_SBADDRMID_MASK 0xff /* SbAddrMid Mask */ ++ ++/* SDA_SBADDRHIGH */ ++#define SDA_SBADDRHIGH_MASK 0xff /* SbAddrHigh Mask */ ++ ++/* SDA_FRAMECTRL */ ++#define SFC_RF_TERM (1 << 0) /* Read Frame Terminate */ ++#define SFC_WF_TERM (1 << 1) /* Write Frame Terminate */ ++#define SFC_CRC4WOOS (1 << 2) /* HW reports CRC error for write out of sync */ ++#define SFC_ABORTALL (1 << 3) /* Abort cancels all in-progress frames */ ++ ++/* pcmciaframectrl */ ++#define PFC_RF_TERM (1 << 0) /* Read Frame Terminate */ ++#define PFC_WF_TERM (1 << 1) /* Write Frame Terminate */ ++ ++/* intrcvlazy */ ++#define IRL_TO_MASK 0x00ffffff /* timeout */ ++#define IRL_FC_MASK 0xff000000 /* frame count */ ++#define IRL_FC_SHIFT 24 /* frame count */ ++ ++/* rx header */ ++typedef volatile struct { ++ uint16 len; ++ uint16 flags; ++} sdpcmd_rxh_t; ++ ++/* rx header flags */ ++#define RXF_CRC 0x0001 /* CRC error detected */ ++#define RXF_WOOS 0x0002 /* write frame out of sync */ ++#define RXF_WF_TERM 0x0004 /* write frame terminated */ ++#define RXF_ABORT 0x0008 /* write frame aborted */ ++#define RXF_DISCARD (RXF_CRC | RXF_WOOS | RXF_WF_TERM | RXF_ABORT) /* bad frame */ ++ ++/* HW frame tag */ ++#define SDPCM_FRAMETAG_LEN 4 /* HW frametag: 2 bytes len, 2 bytes check val */ ++ ++#define SDPCM_HWEXT_LEN 8 ++ ++#endif /* _sbsdpcmdev_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/sbsocram.h b/drivers/net/wireless/ap6210/include/sbsocram.h +new file mode 100755 +index 0000000..6455f2b +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/sbsocram.h +@@ -0,0 +1,199 @@ ++/* ++ * BCM47XX Sonics SiliconBackplane embedded ram core ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: sbsocram.h 271781 2011-07-13 20:00:06Z $ ++ */ ++ ++#ifndef _SBSOCRAM_H ++#define _SBSOCRAM_H ++ ++#ifndef _LANGUAGE_ASSEMBLY ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++/* Memcsocram core registers */ ++typedef volatile struct sbsocramregs { ++ uint32 coreinfo; ++ uint32 bwalloc; ++ uint32 extracoreinfo; ++ uint32 biststat; ++ uint32 bankidx; ++ uint32 standbyctrl; ++ ++ uint32 errlogstatus; /* rev 6 */ ++ uint32 errlogaddr; /* rev 6 */ ++ /* used for patching rev 3 & 5 */ ++ uint32 cambankidx; ++ uint32 cambankstandbyctrl; ++ uint32 cambankpatchctrl; ++ uint32 cambankpatchtblbaseaddr; ++ uint32 cambankcmdreg; ++ uint32 cambankdatareg; ++ uint32 cambankmaskreg; ++ uint32 PAD[1]; ++ uint32 bankinfo; /* corev 8 */ ++ uint32 PAD[15]; ++ uint32 extmemconfig; ++ uint32 extmemparitycsr; ++ uint32 extmemparityerrdata; ++ uint32 extmemparityerrcnt; ++ uint32 extmemwrctrlandsize; ++ uint32 PAD[84]; ++ uint32 workaround; ++ uint32 pwrctl; /* corerev >= 2 */ ++ uint32 PAD[133]; ++ uint32 sr_control; /* corerev >= 15 */ ++ uint32 sr_status; /* corerev >= 15 */ ++ uint32 sr_address; /* corerev >= 15 */ ++ uint32 sr_data; /* corerev >= 15 */ ++} sbsocramregs_t; ++ ++#endif /* _LANGUAGE_ASSEMBLY */ ++ ++/* Register offsets */ ++#define SR_COREINFO 0x00 ++#define SR_BWALLOC 0x04 ++#define SR_BISTSTAT 0x0c ++#define SR_BANKINDEX 0x10 ++#define SR_BANKSTBYCTL 0x14 ++#define SR_PWRCTL 0x1e8 ++ ++/* Coreinfo register */ ++#define SRCI_PT_MASK 0x00070000 /* corerev >= 6; port type[18:16] */ ++#define SRCI_PT_SHIFT 16 ++/* port types : SRCI_PT__ */ ++#define SRCI_PT_OCP_OCP 0 ++#define SRCI_PT_AXI_OCP 1 ++#define SRCI_PT_ARM7AHB_OCP 2 ++#define SRCI_PT_CM3AHB_OCP 3 ++#define SRCI_PT_AXI_AXI 4 ++#define SRCI_PT_AHB_AXI 5 ++/* corerev >= 3 */ ++#define SRCI_LSS_MASK 0x00f00000 ++#define SRCI_LSS_SHIFT 20 ++#define SRCI_LRS_MASK 0x0f000000 ++#define SRCI_LRS_SHIFT 24 ++ ++/* In corerev 0, the memory size is 2 to the power of the ++ * base plus 16 plus to the contents of the memsize field plus 1. ++ */ ++#define SRCI_MS0_MASK 0xf ++#define SR_MS0_BASE 16 ++ ++/* ++ * In corerev 1 the bank size is 2 ^ the bank size field plus 14, ++ * the memory size is number of banks times bank size. ++ * The same applies to rom size. ++ */ ++#define SRCI_ROMNB_MASK 0xf000 ++#define SRCI_ROMNB_SHIFT 12 ++#define SRCI_ROMBSZ_MASK 0xf00 ++#define SRCI_ROMBSZ_SHIFT 8 ++#define SRCI_SRNB_MASK 0xf0 ++#define SRCI_SRNB_SHIFT 4 ++#define SRCI_SRBSZ_MASK 0xf ++#define SRCI_SRBSZ_SHIFT 0 ++ ++#define SR_BSZ_BASE 14 ++ ++/* Standby control register */ ++#define SRSC_SBYOVR_MASK 0x80000000 ++#define SRSC_SBYOVR_SHIFT 31 ++#define SRSC_SBYOVRVAL_MASK 0x60000000 ++#define SRSC_SBYOVRVAL_SHIFT 29 ++#define SRSC_SBYEN_MASK 0x01000000 /* rev >= 3 */ ++#define SRSC_SBYEN_SHIFT 24 ++ ++/* Power control register */ ++#define SRPC_PMU_STBYDIS_MASK 0x00000010 /* rev >= 3 */ ++#define SRPC_PMU_STBYDIS_SHIFT 4 ++#define SRPC_STBYOVRVAL_MASK 0x00000008 ++#define SRPC_STBYOVRVAL_SHIFT 3 ++#define SRPC_STBYOVR_MASK 0x00000007 ++#define SRPC_STBYOVR_SHIFT 0 ++ ++/* Extra core capability register */ ++#define SRECC_NUM_BANKS_MASK 0x000000F0 ++#define SRECC_NUM_BANKS_SHIFT 4 ++#define SRECC_BANKSIZE_MASK 0x0000000F ++#define SRECC_BANKSIZE_SHIFT 0 ++ ++#define SRECC_BANKSIZE(value) (1 << (value)) ++ ++/* CAM bank patch control */ ++#define SRCBPC_PATCHENABLE 0x80000000 ++ ++#define SRP_ADDRESS 0x0001FFFC ++#define SRP_VALID 0x8000 ++ ++/* CAM bank command reg */ ++#define SRCMD_WRITE 0x00020000 ++#define SRCMD_READ 0x00010000 ++#define SRCMD_DONE 0x80000000 ++ ++#define SRCMD_DONE_DLY 1000 ++ ++/* bankidx and bankinfo reg defines corerev >= 8 */ ++#define SOCRAM_BANKINFO_SZMASK 0x7f ++#define SOCRAM_BANKIDX_ROM_MASK 0x100 ++ ++#define SOCRAM_BANKIDX_MEMTYPE_SHIFT 8 ++/* socram bankinfo memtype */ ++#define SOCRAM_MEMTYPE_RAM 0 ++#define SOCRAM_MEMTYPE_R0M 1 ++#define SOCRAM_MEMTYPE_DEVRAM 2 ++ ++#define SOCRAM_BANKINFO_REG 0x40 ++#define SOCRAM_BANKIDX_REG 0x10 ++#define SOCRAM_BANKINFO_STDBY_MASK 0x400 ++#define SOCRAM_BANKINFO_STDBY_TIMER 0x800 ++ ++/* bankinfo rev >= 10 */ ++#define SOCRAM_BANKINFO_DEVRAMSEL_SHIFT 13 ++#define SOCRAM_BANKINFO_DEVRAMSEL_MASK 0x2000 ++#define SOCRAM_BANKINFO_DEVRAMPRO_SHIFT 14 ++#define SOCRAM_BANKINFO_DEVRAMPRO_MASK 0x4000 ++#define SOCRAM_BANKINFO_SLPSUPP_SHIFT 15 ++#define SOCRAM_BANKINFO_SLPSUPP_MASK 0x8000 ++#define SOCRAM_BANKINFO_RETNTRAM_SHIFT 16 ++#define SOCRAM_BANKINFO_RETNTRAM_MASK 0x00010000 ++#define SOCRAM_BANKINFO_PDASZ_SHIFT 17 ++#define SOCRAM_BANKINFO_PDASZ_MASK 0x003E0000 ++#define SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT 24 ++#define SOCRAM_BANKINFO_DEVRAMREMAP_MASK 0x01000000 ++ ++/* extracoreinfo register */ ++#define SOCRAM_DEVRAMBANK_MASK 0xF000 ++#define SOCRAM_DEVRAMBANK_SHIFT 12 ++ ++/* bank info to calculate bank size */ ++#define SOCRAM_BANKINFO_SZBASE 8192 ++#define SOCRAM_BANKSIZE_SHIFT 13 /* SOCRAM_BANKINFO_SZBASE */ ++ ++ ++#endif /* _SBSOCRAM_H */ +diff --git a/drivers/net/wireless/ap6210/include/sdio.h b/drivers/net/wireless/ap6210/include/sdio.h +new file mode 100755 +index 0000000..b8eee1f +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/sdio.h +@@ -0,0 +1,617 @@ ++/* ++ * SDIO spec header file ++ * Protocol and standard (common) device definitions ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: sdio.h 308973 2012-01-18 04:19:34Z $ ++ */ ++ ++#ifndef _SDIO_H ++#define _SDIO_H ++ ++ ++/* CCCR structure for function 0 */ ++typedef volatile struct { ++ uint8 cccr_sdio_rev; /* RO, cccr and sdio revision */ ++ uint8 sd_rev; /* RO, sd spec revision */ ++ uint8 io_en; /* I/O enable */ ++ uint8 io_rdy; /* I/O ready reg */ ++ uint8 intr_ctl; /* Master and per function interrupt enable control */ ++ uint8 intr_status; /* RO, interrupt pending status */ ++ uint8 io_abort; /* read/write abort or reset all functions */ ++ uint8 bus_inter; /* bus interface control */ ++ uint8 capability; /* RO, card capability */ ++ ++ uint8 cis_base_low; /* 0x9 RO, common CIS base address, LSB */ ++ uint8 cis_base_mid; ++ uint8 cis_base_high; /* 0xB RO, common CIS base address, MSB */ ++ ++ /* suspend/resume registers */ ++ uint8 bus_suspend; /* 0xC */ ++ uint8 func_select; /* 0xD */ ++ uint8 exec_flag; /* 0xE */ ++ uint8 ready_flag; /* 0xF */ ++ ++ uint8 fn0_blk_size[2]; /* 0x10(LSB), 0x11(MSB) */ ++ ++ uint8 power_control; /* 0x12 (SDIO version 1.10) */ ++ ++ uint8 speed_control; /* 0x13 */ ++} sdio_regs_t; ++ ++/* SDIO Device CCCR offsets */ ++#define SDIOD_CCCR_REV 0x00 ++#define SDIOD_CCCR_SDREV 0x01 ++#define SDIOD_CCCR_IOEN 0x02 ++#define SDIOD_CCCR_IORDY 0x03 ++#define SDIOD_CCCR_INTEN 0x04 ++#define SDIOD_CCCR_INTPEND 0x05 ++#define SDIOD_CCCR_IOABORT 0x06 ++#define SDIOD_CCCR_BICTRL 0x07 ++#define SDIOD_CCCR_CAPABLITIES 0x08 ++#define SDIOD_CCCR_CISPTR_0 0x09 ++#define SDIOD_CCCR_CISPTR_1 0x0A ++#define SDIOD_CCCR_CISPTR_2 0x0B ++#define SDIOD_CCCR_BUSSUSP 0x0C ++#define SDIOD_CCCR_FUNCSEL 0x0D ++#define SDIOD_CCCR_EXECFLAGS 0x0E ++#define SDIOD_CCCR_RDYFLAGS 0x0F ++#define SDIOD_CCCR_BLKSIZE_0 0x10 ++#define SDIOD_CCCR_BLKSIZE_1 0x11 ++#define SDIOD_CCCR_POWER_CONTROL 0x12 ++#define SDIOD_CCCR_SPEED_CONTROL 0x13 ++#define SDIOD_CCCR_UHSI_SUPPORT 0x14 ++#define SDIOD_CCCR_DRIVER_STRENGTH 0x15 ++#define SDIOD_CCCR_INTR_EXTN 0x16 ++ ++/* Broadcom extensions (corerev >= 1) */ ++#define SDIOD_CCCR_BRCM_CARDCAP 0xf0 ++#define SDIOD_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02 ++#define SDIOD_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04 ++#define SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08 ++#define SDIOD_CCCR_BRCM_CARDCTL 0xf1 ++#define SDIOD_CCCR_BRCM_SEPINT 0xf2 ++ ++/* cccr_sdio_rev */ ++#define SDIO_REV_SDIOID_MASK 0xf0 /* SDIO spec revision number */ ++#define SDIO_REV_CCCRID_MASK 0x0f /* CCCR format version number */ ++ ++/* sd_rev */ ++#define SD_REV_PHY_MASK 0x0f /* SD format version number */ ++ ++/* io_en */ ++#define SDIO_FUNC_ENABLE_1 0x02 /* function 1 I/O enable */ ++#define SDIO_FUNC_ENABLE_2 0x04 /* function 2 I/O enable */ ++ ++/* io_rdys */ ++#define SDIO_FUNC_READY_1 0x02 /* function 1 I/O ready */ ++#define SDIO_FUNC_READY_2 0x04 /* function 2 I/O ready */ ++ ++/* intr_ctl */ ++#define INTR_CTL_MASTER_EN 0x1 /* interrupt enable master */ ++#define INTR_CTL_FUNC1_EN 0x2 /* interrupt enable for function 1 */ ++#define INTR_CTL_FUNC2_EN 0x4 /* interrupt enable for function 2 */ ++ ++/* intr_status */ ++#define INTR_STATUS_FUNC1 0x2 /* interrupt pending for function 1 */ ++#define INTR_STATUS_FUNC2 0x4 /* interrupt pending for function 2 */ ++ ++/* io_abort */ ++#define IO_ABORT_RESET_ALL 0x08 /* I/O card reset */ ++#define IO_ABORT_FUNC_MASK 0x07 /* abort selction: function x */ ++ ++/* bus_inter */ ++#define BUS_CARD_DETECT_DIS 0x80 /* Card Detect disable */ ++#define BUS_SPI_CONT_INTR_CAP 0x40 /* support continuous SPI interrupt */ ++#define BUS_SPI_CONT_INTR_EN 0x20 /* continuous SPI interrupt enable */ ++#define BUS_SD_DATA_WIDTH_MASK 0x03 /* bus width mask */ ++#define BUS_SD_DATA_WIDTH_4BIT 0x02 /* bus width 4-bit mode */ ++#define BUS_SD_DATA_WIDTH_1BIT 0x00 /* bus width 1-bit mode */ ++ ++/* capability */ ++#define SDIO_CAP_4BLS 0x80 /* 4-bit support for low speed card */ ++#define SDIO_CAP_LSC 0x40 /* low speed card */ ++#define SDIO_CAP_E4MI 0x20 /* enable interrupt between block of data in 4-bit mode */ ++#define SDIO_CAP_S4MI 0x10 /* support interrupt between block of data in 4-bit mode */ ++#define SDIO_CAP_SBS 0x08 /* support suspend/resume */ ++#define SDIO_CAP_SRW 0x04 /* support read wait */ ++#define SDIO_CAP_SMB 0x02 /* support multi-block transfer */ ++#define SDIO_CAP_SDC 0x01 /* Support Direct commands during multi-byte transfer */ ++ ++/* power_control */ ++#define SDIO_POWER_SMPC 0x01 /* supports master power control (RO) */ ++#define SDIO_POWER_EMPC 0x02 /* enable master power control (allow > 200mA) (RW) */ ++ ++/* speed_control (control device entry into high-speed clocking mode) */ ++#define SDIO_SPEED_SHS 0x01 /* supports high-speed [clocking] mode (RO) */ ++#define SDIO_SPEED_EHS 0x02 /* enable high-speed [clocking] mode (RW) */ ++ ++/* for setting bus speed in card: 0x13h */ ++#define SDIO_BUS_SPEED_UHSISEL_M BITFIELD_MASK(3) ++#define SDIO_BUS_SPEED_UHSISEL_S 1 ++ ++/* for getting bus speed cap in card: 0x14h */ ++#define SDIO_BUS_SPEED_UHSICAP_M BITFIELD_MASK(3) ++#define SDIO_BUS_SPEED_UHSICAP_S 0 ++ ++/* for getting driver type CAP in card: 0x15h */ ++#define SDIO_BUS_DRVR_TYPE_CAP_M BITFIELD_MASK(3) ++#define SDIO_BUS_DRVR_TYPE_CAP_S 0 ++ ++/* for setting driver type selection in card: 0x15h */ ++#define SDIO_BUS_DRVR_TYPE_SEL_M BITFIELD_MASK(2) ++#define SDIO_BUS_DRVR_TYPE_SEL_S 4 ++ ++/* for getting async int support in card: 0x16h */ ++#define SDIO_BUS_ASYNCINT_CAP_M BITFIELD_MASK(1) ++#define SDIO_BUS_ASYNCINT_CAP_S 0 ++ ++/* for setting async int selection in card: 0x16h */ ++#define SDIO_BUS_ASYNCINT_SEL_M BITFIELD_MASK(1) ++#define SDIO_BUS_ASYNCINT_SEL_S 1 ++ ++/* brcm sepint */ ++#define SDIO_SEPINT_MASK 0x01 /* route sdpcmdev intr onto separate pad (chip-specific) */ ++#define SDIO_SEPINT_OE 0x02 /* 1 asserts output enable for above pad */ ++#define SDIO_SEPINT_ACT_HI 0x04 /* use active high interrupt level instead of active low */ ++ ++/* FBR structure for function 1-7, FBR addresses and register offsets */ ++typedef volatile struct { ++ uint8 devctr; /* device interface, CSA control */ ++ uint8 ext_dev; /* extended standard I/O device type code */ ++ uint8 pwr_sel; /* power selection support */ ++ uint8 PAD[6]; /* reserved */ ++ ++ uint8 cis_low; /* CIS LSB */ ++ uint8 cis_mid; ++ uint8 cis_high; /* CIS MSB */ ++ uint8 csa_low; /* code storage area, LSB */ ++ uint8 csa_mid; ++ uint8 csa_high; /* code storage area, MSB */ ++ uint8 csa_dat_win; /* data access window to function */ ++ ++ uint8 fnx_blk_size[2]; /* block size, little endian */ ++} sdio_fbr_t; ++ ++/* Maximum number of I/O funcs */ ++#define SDIOD_MAX_FUNCS 8 ++#define SDIOD_MAX_IOFUNCS 7 ++ ++/* SDIO Device FBR Start Address */ ++#define SDIOD_FBR_STARTADDR 0x100 ++ ++/* SDIO Device FBR Size */ ++#define SDIOD_FBR_SIZE 0x100 ++ ++/* Macro to calculate FBR register base */ ++#define SDIOD_FBR_BASE(n) ((n) * 0x100) ++ ++/* Function register offsets */ ++#define SDIOD_FBR_DEVCTR 0x00 /* basic info for function */ ++#define SDIOD_FBR_EXT_DEV 0x01 /* extended I/O device code */ ++#define SDIOD_FBR_PWR_SEL 0x02 /* power selection bits */ ++ ++/* SDIO Function CIS ptr offset */ ++#define SDIOD_FBR_CISPTR_0 0x09 ++#define SDIOD_FBR_CISPTR_1 0x0A ++#define SDIOD_FBR_CISPTR_2 0x0B ++ ++/* Code Storage Area pointer */ ++#define SDIOD_FBR_CSA_ADDR_0 0x0C ++#define SDIOD_FBR_CSA_ADDR_1 0x0D ++#define SDIOD_FBR_CSA_ADDR_2 0x0E ++#define SDIOD_FBR_CSA_DATA 0x0F ++ ++/* SDIO Function I/O Block Size */ ++#define SDIOD_FBR_BLKSIZE_0 0x10 ++#define SDIOD_FBR_BLKSIZE_1 0x11 ++ ++/* devctr */ ++#define SDIOD_FBR_DEVCTR_DIC 0x0f /* device interface code */ ++#define SDIOD_FBR_DECVTR_CSA 0x40 /* CSA support flag */ ++#define SDIOD_FBR_DEVCTR_CSA_EN 0x80 /* CSA enabled */ ++/* interface codes */ ++#define SDIOD_DIC_NONE 0 /* SDIO standard interface is not supported */ ++#define SDIOD_DIC_UART 1 ++#define SDIOD_DIC_BLUETOOTH_A 2 ++#define SDIOD_DIC_BLUETOOTH_B 3 ++#define SDIOD_DIC_GPS 4 ++#define SDIOD_DIC_CAMERA 5 ++#define SDIOD_DIC_PHS 6 ++#define SDIOD_DIC_WLAN 7 ++#define SDIOD_DIC_EXT 0xf /* extended device interface, read ext_dev register */ ++ ++/* pwr_sel */ ++#define SDIOD_PWR_SEL_SPS 0x01 /* supports power selection */ ++#define SDIOD_PWR_SEL_EPS 0x02 /* enable power selection (low-current mode) */ ++ ++/* misc defines */ ++#define SDIO_FUNC_0 0 ++#define SDIO_FUNC_1 1 ++#define SDIO_FUNC_2 2 ++#define SDIO_FUNC_3 3 ++#define SDIO_FUNC_4 4 ++#define SDIO_FUNC_5 5 ++#define SDIO_FUNC_6 6 ++#define SDIO_FUNC_7 7 ++ ++#define SD_CARD_TYPE_UNKNOWN 0 /* bad type or unrecognized */ ++#define SD_CARD_TYPE_IO 1 /* IO only card */ ++#define SD_CARD_TYPE_MEMORY 2 /* memory only card */ ++#define SD_CARD_TYPE_COMBO 3 /* IO and memory combo card */ ++ ++#define SDIO_MAX_BLOCK_SIZE 2048 /* maximum block size for block mode operation */ ++#define SDIO_MIN_BLOCK_SIZE 1 /* minimum block size for block mode operation */ ++ ++/* Card registers: status bit position */ ++#define CARDREG_STATUS_BIT_OUTOFRANGE 31 ++#define CARDREG_STATUS_BIT_COMCRCERROR 23 ++#define CARDREG_STATUS_BIT_ILLEGALCOMMAND 22 ++#define CARDREG_STATUS_BIT_ERROR 19 ++#define CARDREG_STATUS_BIT_IOCURRENTSTATE3 12 ++#define CARDREG_STATUS_BIT_IOCURRENTSTATE2 11 ++#define CARDREG_STATUS_BIT_IOCURRENTSTATE1 10 ++#define CARDREG_STATUS_BIT_IOCURRENTSTATE0 9 ++#define CARDREG_STATUS_BIT_FUN_NUM_ERROR 4 ++ ++ ++ ++#define SD_CMD_GO_IDLE_STATE 0 /* mandatory for SDIO */ ++#define SD_CMD_SEND_OPCOND 1 ++#define SD_CMD_MMC_SET_RCA 3 ++#define SD_CMD_IO_SEND_OP_COND 5 /* mandatory for SDIO */ ++#define SD_CMD_SELECT_DESELECT_CARD 7 ++#define SD_CMD_SEND_CSD 9 ++#define SD_CMD_SEND_CID 10 ++#define SD_CMD_STOP_TRANSMISSION 12 ++#define SD_CMD_SEND_STATUS 13 ++#define SD_CMD_GO_INACTIVE_STATE 15 ++#define SD_CMD_SET_BLOCKLEN 16 ++#define SD_CMD_READ_SINGLE_BLOCK 17 ++#define SD_CMD_READ_MULTIPLE_BLOCK 18 ++#define SD_CMD_WRITE_BLOCK 24 ++#define SD_CMD_WRITE_MULTIPLE_BLOCK 25 ++#define SD_CMD_PROGRAM_CSD 27 ++#define SD_CMD_SET_WRITE_PROT 28 ++#define SD_CMD_CLR_WRITE_PROT 29 ++#define SD_CMD_SEND_WRITE_PROT 30 ++#define SD_CMD_ERASE_WR_BLK_START 32 ++#define SD_CMD_ERASE_WR_BLK_END 33 ++#define SD_CMD_ERASE 38 ++#define SD_CMD_LOCK_UNLOCK 42 ++#define SD_CMD_IO_RW_DIRECT 52 /* mandatory for SDIO */ ++#define SD_CMD_IO_RW_EXTENDED 53 /* mandatory for SDIO */ ++#define SD_CMD_APP_CMD 55 ++#define SD_CMD_GEN_CMD 56 ++#define SD_CMD_READ_OCR 58 ++#define SD_CMD_CRC_ON_OFF 59 /* mandatory for SDIO */ ++#define SD_ACMD_SD_STATUS 13 ++#define SD_ACMD_SEND_NUM_WR_BLOCKS 22 ++#define SD_ACMD_SET_WR_BLOCK_ERASE_CNT 23 ++#define SD_ACMD_SD_SEND_OP_COND 41 ++#define SD_ACMD_SET_CLR_CARD_DETECT 42 ++#define SD_ACMD_SEND_SCR 51 ++ ++/* argument for SD_CMD_IO_RW_DIRECT and SD_CMD_IO_RW_EXTENDED */ ++#define SD_IO_OP_READ 0 /* Read_Write: Read */ ++#define SD_IO_OP_WRITE 1 /* Read_Write: Write */ ++#define SD_IO_RW_NORMAL 0 /* no RAW */ ++#define SD_IO_RW_RAW 1 /* RAW */ ++#define SD_IO_BYTE_MODE 0 /* Byte Mode */ ++#define SD_IO_BLOCK_MODE 1 /* BlockMode */ ++#define SD_IO_FIXED_ADDRESS 0 /* fix Address */ ++#define SD_IO_INCREMENT_ADDRESS 1 /* IncrementAddress */ ++ ++/* build SD_CMD_IO_RW_DIRECT Argument */ ++#define SDIO_IO_RW_DIRECT_ARG(rw, raw, func, addr, data) \ ++ ((((rw) & 1) << 31) | (((func) & 0x7) << 28) | (((raw) & 1) << 27) | \ ++ (((addr) & 0x1FFFF) << 9) | ((data) & 0xFF)) ++ ++/* build SD_CMD_IO_RW_EXTENDED Argument */ ++#define SDIO_IO_RW_EXTENDED_ARG(rw, blk, func, addr, inc_addr, count) \ ++ ((((rw) & 1) << 31) | (((func) & 0x7) << 28) | (((blk) & 1) << 27) | \ ++ (((inc_addr) & 1) << 26) | (((addr) & 0x1FFFF) << 9) | ((count) & 0x1FF)) ++ ++/* SDIO response parameters */ ++#define SD_RSP_NO_NONE 0 ++#define SD_RSP_NO_1 1 ++#define SD_RSP_NO_2 2 ++#define SD_RSP_NO_3 3 ++#define SD_RSP_NO_4 4 ++#define SD_RSP_NO_5 5 ++#define SD_RSP_NO_6 6 ++ ++ /* Modified R6 response (to CMD3) */ ++#define SD_RSP_MR6_COM_CRC_ERROR 0x8000 ++#define SD_RSP_MR6_ILLEGAL_COMMAND 0x4000 ++#define SD_RSP_MR6_ERROR 0x2000 ++ ++ /* Modified R1 in R4 Response (to CMD5) */ ++#define SD_RSP_MR1_SBIT 0x80 ++#define SD_RSP_MR1_PARAMETER_ERROR 0x40 ++#define SD_RSP_MR1_RFU5 0x20 ++#define SD_RSP_MR1_FUNC_NUM_ERROR 0x10 ++#define SD_RSP_MR1_COM_CRC_ERROR 0x08 ++#define SD_RSP_MR1_ILLEGAL_COMMAND 0x04 ++#define SD_RSP_MR1_RFU1 0x02 ++#define SD_RSP_MR1_IDLE_STATE 0x01 ++ ++ /* R5 response (to CMD52 and CMD53) */ ++#define SD_RSP_R5_COM_CRC_ERROR 0x80 ++#define SD_RSP_R5_ILLEGAL_COMMAND 0x40 ++#define SD_RSP_R5_IO_CURRENTSTATE1 0x20 ++#define SD_RSP_R5_IO_CURRENTSTATE0 0x10 ++#define SD_RSP_R5_ERROR 0x08 ++#define SD_RSP_R5_RFU 0x04 ++#define SD_RSP_R5_FUNC_NUM_ERROR 0x02 ++#define SD_RSP_R5_OUT_OF_RANGE 0x01 ++ ++#define SD_RSP_R5_ERRBITS 0xCB ++ ++ ++/* ------------------------------------------------ ++ * SDIO Commands and responses ++ * ++ * I/O only commands are: ++ * CMD0, CMD3, CMD5, CMD7, CMD14, CMD15, CMD52, CMD53 ++ * ------------------------------------------------ ++ */ ++ ++/* SDIO Commands */ ++#define SDIOH_CMD_0 0 ++#define SDIOH_CMD_3 3 ++#define SDIOH_CMD_5 5 ++#define SDIOH_CMD_7 7 ++#define SDIOH_CMD_11 11 ++#define SDIOH_CMD_14 14 ++#define SDIOH_CMD_15 15 ++#define SDIOH_CMD_19 19 ++#define SDIOH_CMD_52 52 ++#define SDIOH_CMD_53 53 ++#define SDIOH_CMD_59 59 ++ ++/* SDIO Command Responses */ ++#define SDIOH_RSP_NONE 0 ++#define SDIOH_RSP_R1 1 ++#define SDIOH_RSP_R2 2 ++#define SDIOH_RSP_R3 3 ++#define SDIOH_RSP_R4 4 ++#define SDIOH_RSP_R5 5 ++#define SDIOH_RSP_R6 6 ++ ++/* ++ * SDIO Response Error flags ++ */ ++#define SDIOH_RSP5_ERROR_FLAGS 0xCB ++ ++/* ------------------------------------------------ ++ * SDIO Command structures. I/O only commands are: ++ * ++ * CMD0, CMD3, CMD5, CMD7, CMD15, CMD52, CMD53 ++ * ------------------------------------------------ ++ */ ++ ++#define CMD5_OCR_M BITFIELD_MASK(24) ++#define CMD5_OCR_S 0 ++ ++#define CMD5_S18R_M BITFIELD_MASK(1) ++#define CMD5_S18R_S 24 ++ ++#define CMD7_RCA_M BITFIELD_MASK(16) ++#define CMD7_RCA_S 16 ++ ++#define CMD14_RCA_M BITFIELD_MASK(16) ++#define CMD14_RCA_S 16 ++#define CMD14_SLEEP_M BITFIELD_MASK(1) ++#define CMD14_SLEEP_S 15 ++ ++#define CMD_15_RCA_M BITFIELD_MASK(16) ++#define CMD_15_RCA_S 16 ++ ++#define CMD52_DATA_M BITFIELD_MASK(8) /* Bits [7:0] - Write Data/Stuff bits of CMD52 ++ */ ++#define CMD52_DATA_S 0 ++#define CMD52_REG_ADDR_M BITFIELD_MASK(17) /* Bits [25:9] - register address */ ++#define CMD52_REG_ADDR_S 9 ++#define CMD52_RAW_M BITFIELD_MASK(1) /* Bit 27 - Read after Write flag */ ++#define CMD52_RAW_S 27 ++#define CMD52_FUNCTION_M BITFIELD_MASK(3) /* Bits [30:28] - Function number */ ++#define CMD52_FUNCTION_S 28 ++#define CMD52_RW_FLAG_M BITFIELD_MASK(1) /* Bit 31 - R/W flag */ ++#define CMD52_RW_FLAG_S 31 ++ ++ ++#define CMD53_BYTE_BLK_CNT_M BITFIELD_MASK(9) /* Bits [8:0] - Byte/Block Count of CMD53 */ ++#define CMD53_BYTE_BLK_CNT_S 0 ++#define CMD53_REG_ADDR_M BITFIELD_MASK(17) /* Bits [25:9] - register address */ ++#define CMD53_REG_ADDR_S 9 ++#define CMD53_OP_CODE_M BITFIELD_MASK(1) /* Bit 26 - R/W Operation Code */ ++#define CMD53_OP_CODE_S 26 ++#define CMD53_BLK_MODE_M BITFIELD_MASK(1) /* Bit 27 - Block Mode */ ++#define CMD53_BLK_MODE_S 27 ++#define CMD53_FUNCTION_M BITFIELD_MASK(3) /* Bits [30:28] - Function number */ ++#define CMD53_FUNCTION_S 28 ++#define CMD53_RW_FLAG_M BITFIELD_MASK(1) /* Bit 31 - R/W flag */ ++#define CMD53_RW_FLAG_S 31 ++ ++/* ------------------------------------------------------ ++ * SDIO Command Response structures for SD1 and SD4 modes ++ * ----------------------------------------------------- ++ */ ++#define RSP4_IO_OCR_M BITFIELD_MASK(24) /* Bits [23:0] - Card's OCR Bits [23:0] */ ++#define RSP4_IO_OCR_S 0 ++ ++#define RSP4_S18A_M BITFIELD_MASK(1) /* Bits [23:0] - Card's OCR Bits [23:0] */ ++#define RSP4_S18A_S 24 ++ ++#define RSP4_STUFF_M BITFIELD_MASK(3) /* Bits [26:24] - Stuff bits */ ++#define RSP4_STUFF_S 24 ++#define RSP4_MEM_PRESENT_M BITFIELD_MASK(1) /* Bit 27 - Memory present */ ++#define RSP4_MEM_PRESENT_S 27 ++#define RSP4_NUM_FUNCS_M BITFIELD_MASK(3) /* Bits [30:28] - Number of I/O funcs */ ++#define RSP4_NUM_FUNCS_S 28 ++#define RSP4_CARD_READY_M BITFIELD_MASK(1) /* Bit 31 - SDIO card ready */ ++#define RSP4_CARD_READY_S 31 ++ ++#define RSP6_STATUS_M BITFIELD_MASK(16) /* Bits [15:0] - Card status bits [19,22,23,12:0] ++ */ ++#define RSP6_STATUS_S 0 ++#define RSP6_IO_RCA_M BITFIELD_MASK(16) /* Bits [31:16] - RCA bits[31-16] */ ++#define RSP6_IO_RCA_S 16 ++ ++#define RSP1_AKE_SEQ_ERROR_M BITFIELD_MASK(1) /* Bit 3 - Authentication seq error */ ++#define RSP1_AKE_SEQ_ERROR_S 3 ++#define RSP1_APP_CMD_M BITFIELD_MASK(1) /* Bit 5 - Card expects ACMD */ ++#define RSP1_APP_CMD_S 5 ++#define RSP1_READY_FOR_DATA_M BITFIELD_MASK(1) /* Bit 8 - Ready for data (buff empty) */ ++#define RSP1_READY_FOR_DATA_S 8 ++#define RSP1_CURR_STATE_M BITFIELD_MASK(4) /* Bits [12:9] - State of card ++ * when Cmd was received ++ */ ++#define RSP1_CURR_STATE_S 9 ++#define RSP1_EARSE_RESET_M BITFIELD_MASK(1) /* Bit 13 - Erase seq cleared */ ++#define RSP1_EARSE_RESET_S 13 ++#define RSP1_CARD_ECC_DISABLE_M BITFIELD_MASK(1) /* Bit 14 - Card ECC disabled */ ++#define RSP1_CARD_ECC_DISABLE_S 14 ++#define RSP1_WP_ERASE_SKIP_M BITFIELD_MASK(1) /* Bit 15 - Partial blocks erased due to W/P */ ++#define RSP1_WP_ERASE_SKIP_S 15 ++#define RSP1_CID_CSD_OVERW_M BITFIELD_MASK(1) /* Bit 16 - Illegal write to CID or R/O bits ++ * of CSD ++ */ ++#define RSP1_CID_CSD_OVERW_S 16 ++#define RSP1_ERROR_M BITFIELD_MASK(1) /* Bit 19 - General/Unknown error */ ++#define RSP1_ERROR_S 19 ++#define RSP1_CC_ERROR_M BITFIELD_MASK(1) /* Bit 20 - Internal Card Control error */ ++#define RSP1_CC_ERROR_S 20 ++#define RSP1_CARD_ECC_FAILED_M BITFIELD_MASK(1) /* Bit 21 - Card internal ECC failed ++ * to correct data ++ */ ++#define RSP1_CARD_ECC_FAILED_S 21 ++#define RSP1_ILLEGAL_CMD_M BITFIELD_MASK(1) /* Bit 22 - Cmd not legal for the card state */ ++#define RSP1_ILLEGAL_CMD_S 22 ++#define RSP1_COM_CRC_ERROR_M BITFIELD_MASK(1) /* Bit 23 - CRC check of previous command failed ++ */ ++#define RSP1_COM_CRC_ERROR_S 23 ++#define RSP1_LOCK_UNLOCK_FAIL_M BITFIELD_MASK(1) /* Bit 24 - Card lock-unlock Cmd Seq error */ ++#define RSP1_LOCK_UNLOCK_FAIL_S 24 ++#define RSP1_CARD_LOCKED_M BITFIELD_MASK(1) /* Bit 25 - Card locked by the host */ ++#define RSP1_CARD_LOCKED_S 25 ++#define RSP1_WP_VIOLATION_M BITFIELD_MASK(1) /* Bit 26 - Attempt to program ++ * write-protected blocks ++ */ ++#define RSP1_WP_VIOLATION_S 26 ++#define RSP1_ERASE_PARAM_M BITFIELD_MASK(1) /* Bit 27 - Invalid erase blocks */ ++#define RSP1_ERASE_PARAM_S 27 ++#define RSP1_ERASE_SEQ_ERR_M BITFIELD_MASK(1) /* Bit 28 - Erase Cmd seq error */ ++#define RSP1_ERASE_SEQ_ERR_S 28 ++#define RSP1_BLK_LEN_ERR_M BITFIELD_MASK(1) /* Bit 29 - Block length error */ ++#define RSP1_BLK_LEN_ERR_S 29 ++#define RSP1_ADDR_ERR_M BITFIELD_MASK(1) /* Bit 30 - Misaligned address */ ++#define RSP1_ADDR_ERR_S 30 ++#define RSP1_OUT_OF_RANGE_M BITFIELD_MASK(1) /* Bit 31 - Cmd arg was out of range */ ++#define RSP1_OUT_OF_RANGE_S 31 ++ ++ ++#define RSP5_DATA_M BITFIELD_MASK(8) /* Bits [0:7] - data */ ++#define RSP5_DATA_S 0 ++#define RSP5_FLAGS_M BITFIELD_MASK(8) /* Bit [15:8] - Rsp flags */ ++#define RSP5_FLAGS_S 8 ++#define RSP5_STUFF_M BITFIELD_MASK(16) /* Bits [31:16] - Stuff bits */ ++#define RSP5_STUFF_S 16 ++ ++/* ---------------------------------------------- ++ * SDIO Command Response structures for SPI mode ++ * ---------------------------------------------- ++ */ ++#define SPIRSP4_IO_OCR_M BITFIELD_MASK(16) /* Bits [15:0] - Card's OCR Bits [23:8] */ ++#define SPIRSP4_IO_OCR_S 0 ++#define SPIRSP4_STUFF_M BITFIELD_MASK(3) /* Bits [18:16] - Stuff bits */ ++#define SPIRSP4_STUFF_S 16 ++#define SPIRSP4_MEM_PRESENT_M BITFIELD_MASK(1) /* Bit 19 - Memory present */ ++#define SPIRSP4_MEM_PRESENT_S 19 ++#define SPIRSP4_NUM_FUNCS_M BITFIELD_MASK(3) /* Bits [22:20] - Number of I/O funcs */ ++#define SPIRSP4_NUM_FUNCS_S 20 ++#define SPIRSP4_CARD_READY_M BITFIELD_MASK(1) /* Bit 23 - SDIO card ready */ ++#define SPIRSP4_CARD_READY_S 23 ++#define SPIRSP4_IDLE_STATE_M BITFIELD_MASK(1) /* Bit 24 - idle state */ ++#define SPIRSP4_IDLE_STATE_S 24 ++#define SPIRSP4_ILLEGAL_CMD_M BITFIELD_MASK(1) /* Bit 26 - Illegal Cmd error */ ++#define SPIRSP4_ILLEGAL_CMD_S 26 ++#define SPIRSP4_COM_CRC_ERROR_M BITFIELD_MASK(1) /* Bit 27 - COM CRC error */ ++#define SPIRSP4_COM_CRC_ERROR_S 27 ++#define SPIRSP4_FUNC_NUM_ERROR_M BITFIELD_MASK(1) /* Bit 28 - Function number error ++ */ ++#define SPIRSP4_FUNC_NUM_ERROR_S 28 ++#define SPIRSP4_PARAM_ERROR_M BITFIELD_MASK(1) /* Bit 30 - Parameter Error Bit */ ++#define SPIRSP4_PARAM_ERROR_S 30 ++#define SPIRSP4_START_BIT_M BITFIELD_MASK(1) /* Bit 31 - Start Bit */ ++#define SPIRSP4_START_BIT_S 31 ++ ++#define SPIRSP5_DATA_M BITFIELD_MASK(8) /* Bits [23:16] - R/W Data */ ++#define SPIRSP5_DATA_S 16 ++#define SPIRSP5_IDLE_STATE_M BITFIELD_MASK(1) /* Bit 24 - Idle state */ ++#define SPIRSP5_IDLE_STATE_S 24 ++#define SPIRSP5_ILLEGAL_CMD_M BITFIELD_MASK(1) /* Bit 26 - Illegal Cmd error */ ++#define SPIRSP5_ILLEGAL_CMD_S 26 ++#define SPIRSP5_COM_CRC_ERROR_M BITFIELD_MASK(1) /* Bit 27 - COM CRC error */ ++#define SPIRSP5_COM_CRC_ERROR_S 27 ++#define SPIRSP5_FUNC_NUM_ERROR_M BITFIELD_MASK(1) /* Bit 28 - Function number error ++ */ ++#define SPIRSP5_FUNC_NUM_ERROR_S 28 ++#define SPIRSP5_PARAM_ERROR_M BITFIELD_MASK(1) /* Bit 30 - Parameter Error Bit */ ++#define SPIRSP5_PARAM_ERROR_S 30 ++#define SPIRSP5_START_BIT_M BITFIELD_MASK(1) /* Bit 31 - Start Bit */ ++#define SPIRSP5_START_BIT_S 31 ++ ++/* RSP6 card status format; Pg 68 Physical Layer spec v 1.10 */ ++#define RSP6STAT_AKE_SEQ_ERROR_M BITFIELD_MASK(1) /* Bit 3 - Authentication seq error ++ */ ++#define RSP6STAT_AKE_SEQ_ERROR_S 3 ++#define RSP6STAT_APP_CMD_M BITFIELD_MASK(1) /* Bit 5 - Card expects ACMD */ ++#define RSP6STAT_APP_CMD_S 5 ++#define RSP6STAT_READY_FOR_DATA_M BITFIELD_MASK(1) /* Bit 8 - Ready for data ++ * (buff empty) ++ */ ++#define RSP6STAT_READY_FOR_DATA_S 8 ++#define RSP6STAT_CURR_STATE_M BITFIELD_MASK(4) /* Bits [12:9] - Card state at ++ * Cmd reception ++ */ ++#define RSP6STAT_CURR_STATE_S 9 ++#define RSP6STAT_ERROR_M BITFIELD_MASK(1) /* Bit 13 - General/Unknown error Bit 19 ++ */ ++#define RSP6STAT_ERROR_S 13 ++#define RSP6STAT_ILLEGAL_CMD_M BITFIELD_MASK(1) /* Bit 14 - Illegal cmd for ++ * card state Bit 22 ++ */ ++#define RSP6STAT_ILLEGAL_CMD_S 14 ++#define RSP6STAT_COM_CRC_ERROR_M BITFIELD_MASK(1) /* Bit 15 - CRC previous command ++ * failed Bit 23 ++ */ ++#define RSP6STAT_COM_CRC_ERROR_S 15 ++ ++#define SDIOH_XFER_TYPE_READ SD_IO_OP_READ ++#define SDIOH_XFER_TYPE_WRITE SD_IO_OP_WRITE ++ ++/* command issue options */ ++#define CMD_OPTION_DEFAULT 0 ++#define CMD_OPTION_TUNING 1 ++#endif /* _SDIO_H */ +diff --git a/drivers/net/wireless/ap6210/include/sdioh.h b/drivers/net/wireless/ap6210/include/sdioh.h +new file mode 100755 +index 0000000..5517a71 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/sdioh.h +@@ -0,0 +1,445 @@ ++/* ++ * SDIO Host Controller Spec header file ++ * Register map and definitions for the Standard Host Controller ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: sdioh.h 347633 2012-07-27 11:02:02Z $ ++ */ ++ ++#ifndef _SDIOH_H ++#define _SDIOH_H ++ ++#define SD_SysAddr 0x000 ++#define SD_BlockSize 0x004 ++#define SD_BlockCount 0x006 ++#define SD_Arg0 0x008 ++#define SD_Arg1 0x00A ++#define SD_TransferMode 0x00C ++#define SD_Command 0x00E ++#define SD_Response0 0x010 ++#define SD_Response1 0x012 ++#define SD_Response2 0x014 ++#define SD_Response3 0x016 ++#define SD_Response4 0x018 ++#define SD_Response5 0x01A ++#define SD_Response6 0x01C ++#define SD_Response7 0x01E ++#define SD_BufferDataPort0 0x020 ++#define SD_BufferDataPort1 0x022 ++#define SD_PresentState 0x024 ++#define SD_HostCntrl 0x028 ++#define SD_PwrCntrl 0x029 ++#define SD_BlockGapCntrl 0x02A ++#define SD_WakeupCntrl 0x02B ++#define SD_ClockCntrl 0x02C ++#define SD_TimeoutCntrl 0x02E ++#define SD_SoftwareReset 0x02F ++#define SD_IntrStatus 0x030 ++#define SD_ErrorIntrStatus 0x032 ++#define SD_IntrStatusEnable 0x034 ++#define SD_ErrorIntrStatusEnable 0x036 ++#define SD_IntrSignalEnable 0x038 ++#define SD_ErrorIntrSignalEnable 0x03A ++#define SD_CMD12ErrorStatus 0x03C ++#define SD_Capabilities 0x040 ++#define SD_Capabilities3 0x044 ++#define SD_MaxCurCap 0x048 ++#define SD_MaxCurCap_Reserved 0x04C ++#define SD_ADMA_ErrStatus 0x054 ++#define SD_ADMA_SysAddr 0x58 ++#define SD_SlotInterruptStatus 0x0FC ++#define SD_HostControllerVersion 0x0FE ++#define SD_GPIO_Reg 0x100 ++#define SD_GPIO_OE 0x104 ++#define SD_GPIO_Enable 0x108 ++ ++/* SD specific registers in PCI config space */ ++#define SD_SlotInfo 0x40 ++ ++/* HC 3.0 specific registers and offsets */ ++#define SD3_HostCntrl2 0x03E ++/* preset regsstart and count */ ++#define SD3_PresetValStart 0x060 ++#define SD3_PresetValCount 8 ++/* preset-indiv regs */ ++#define SD3_PresetVal_init 0x060 ++#define SD3_PresetVal_default 0x062 ++#define SD3_PresetVal_HS 0x064 ++#define SD3_PresetVal_SDR12 0x066 ++#define SD3_PresetVal_SDR25 0x068 ++#define SD3_PresetVal_SDR50 0x06a ++#define SD3_PresetVal_SDR104 0x06c ++#define SD3_PresetVal_DDR50 0x06e ++/* SDIO3.0 Revx specific Registers */ ++#define SD3_Tuning_Info_Register 0x0EC ++#define SD3_WL_BT_reset_register 0x0F0 ++ ++ ++/* preset value indices */ ++#define SD3_PRESETVAL_INITIAL_IX 0 ++#define SD3_PRESETVAL_DESPEED_IX 1 ++#define SD3_PRESETVAL_HISPEED_IX 2 ++#define SD3_PRESETVAL_SDR12_IX 3 ++#define SD3_PRESETVAL_SDR25_IX 4 ++#define SD3_PRESETVAL_SDR50_IX 5 ++#define SD3_PRESETVAL_SDR104_IX 6 ++#define SD3_PRESETVAL_DDR50_IX 7 ++ ++/* SD_Capabilities reg (0x040) */ ++#define CAP_TO_CLKFREQ_M BITFIELD_MASK(6) ++#define CAP_TO_CLKFREQ_S 0 ++#define CAP_TO_CLKUNIT_M BITFIELD_MASK(1) ++#define CAP_TO_CLKUNIT_S 7 ++/* Note: for sdio-2.0 case, this mask has to be 6 bits, but msb 2 ++ bits are reserved. going ahead with 8 bits, as it is req for 3.0 ++*/ ++#define CAP_BASECLK_M BITFIELD_MASK(8) ++#define CAP_BASECLK_S 8 ++#define CAP_MAXBLOCK_M BITFIELD_MASK(2) ++#define CAP_MAXBLOCK_S 16 ++#define CAP_ADMA2_M BITFIELD_MASK(1) ++#define CAP_ADMA2_S 19 ++#define CAP_ADMA1_M BITFIELD_MASK(1) ++#define CAP_ADMA1_S 20 ++#define CAP_HIGHSPEED_M BITFIELD_MASK(1) ++#define CAP_HIGHSPEED_S 21 ++#define CAP_DMA_M BITFIELD_MASK(1) ++#define CAP_DMA_S 22 ++#define CAP_SUSPEND_M BITFIELD_MASK(1) ++#define CAP_SUSPEND_S 23 ++#define CAP_VOLT_3_3_M BITFIELD_MASK(1) ++#define CAP_VOLT_3_3_S 24 ++#define CAP_VOLT_3_0_M BITFIELD_MASK(1) ++#define CAP_VOLT_3_0_S 25 ++#define CAP_VOLT_1_8_M BITFIELD_MASK(1) ++#define CAP_VOLT_1_8_S 26 ++#define CAP_64BIT_HOST_M BITFIELD_MASK(1) ++#define CAP_64BIT_HOST_S 28 ++ ++#define SDIO_OCR_READ_FAIL (2) ++ ++ ++#define CAP_ASYNCINT_SUP_M BITFIELD_MASK(1) ++#define CAP_ASYNCINT_SUP_S 29 ++ ++#define CAP_SLOTTYPE_M BITFIELD_MASK(2) ++#define CAP_SLOTTYPE_S 30 ++ ++#define CAP3_MSBits_OFFSET (32) ++/* note: following are caps MSB32 bits. ++ So the bits start from 0, instead of 32. that is why ++ CAP3_MSBits_OFFSET is subtracted. ++*/ ++#define CAP3_SDR50_SUP_M BITFIELD_MASK(1) ++#define CAP3_SDR50_SUP_S (32 - CAP3_MSBits_OFFSET) ++ ++#define CAP3_SDR104_SUP_M BITFIELD_MASK(1) ++#define CAP3_SDR104_SUP_S (33 - CAP3_MSBits_OFFSET) ++ ++#define CAP3_DDR50_SUP_M BITFIELD_MASK(1) ++#define CAP3_DDR50_SUP_S (34 - CAP3_MSBits_OFFSET) ++ ++/* for knowing the clk caps in a single read */ ++#define CAP3_30CLKCAP_M BITFIELD_MASK(3) ++#define CAP3_30CLKCAP_S (32 - CAP3_MSBits_OFFSET) ++ ++#define CAP3_DRIVTYPE_A_M BITFIELD_MASK(1) ++#define CAP3_DRIVTYPE_A_S (36 - CAP3_MSBits_OFFSET) ++ ++#define CAP3_DRIVTYPE_C_M BITFIELD_MASK(1) ++#define CAP3_DRIVTYPE_C_S (37 - CAP3_MSBits_OFFSET) ++ ++#define CAP3_DRIVTYPE_D_M BITFIELD_MASK(1) ++#define CAP3_DRIVTYPE_D_S (38 - CAP3_MSBits_OFFSET) ++ ++#define CAP3_RETUNING_TC_M BITFIELD_MASK(4) ++#define CAP3_RETUNING_TC_S (40 - CAP3_MSBits_OFFSET) ++ ++#define CAP3_TUNING_SDR50_M BITFIELD_MASK(1) ++#define CAP3_TUNING_SDR50_S (45 - CAP3_MSBits_OFFSET) ++ ++#define CAP3_RETUNING_MODES_M BITFIELD_MASK(2) ++#define CAP3_RETUNING_MODES_S (46 - CAP3_MSBits_OFFSET) ++ ++#define CAP3_CLK_MULT_M BITFIELD_MASK(8) ++#define CAP3_CLK_MULT_S (48 - CAP3_MSBits_OFFSET) ++ ++#define PRESET_DRIVR_SELECT_M BITFIELD_MASK(2) ++#define PRESET_DRIVR_SELECT_S 14 ++ ++#define PRESET_CLK_DIV_M BITFIELD_MASK(10) ++#define PRESET_CLK_DIV_S 0 ++ ++/* SD_MaxCurCap reg (0x048) */ ++#define CAP_CURR_3_3_M BITFIELD_MASK(8) ++#define CAP_CURR_3_3_S 0 ++#define CAP_CURR_3_0_M BITFIELD_MASK(8) ++#define CAP_CURR_3_0_S 8 ++#define CAP_CURR_1_8_M BITFIELD_MASK(8) ++#define CAP_CURR_1_8_S 16 ++ ++/* SD_SysAddr: Offset 0x0000, Size 4 bytes */ ++ ++/* SD_BlockSize: Offset 0x004, Size 2 bytes */ ++#define BLKSZ_BLKSZ_M BITFIELD_MASK(12) ++#define BLKSZ_BLKSZ_S 0 ++#define BLKSZ_BNDRY_M BITFIELD_MASK(3) ++#define BLKSZ_BNDRY_S 12 ++ ++/* SD_BlockCount: Offset 0x006, size 2 bytes */ ++ ++/* SD_Arg0: Offset 0x008, size = 4 bytes */ ++/* SD_TransferMode Offset 0x00C, size = 2 bytes */ ++#define XFER_DMA_ENABLE_M BITFIELD_MASK(1) ++#define XFER_DMA_ENABLE_S 0 ++#define XFER_BLK_COUNT_EN_M BITFIELD_MASK(1) ++#define XFER_BLK_COUNT_EN_S 1 ++#define XFER_CMD_12_EN_M BITFIELD_MASK(1) ++#define XFER_CMD_12_EN_S 2 ++#define XFER_DATA_DIRECTION_M BITFIELD_MASK(1) ++#define XFER_DATA_DIRECTION_S 4 ++#define XFER_MULTI_BLOCK_M BITFIELD_MASK(1) ++#define XFER_MULTI_BLOCK_S 5 ++ ++/* SD_Command: Offset 0x00E, size = 2 bytes */ ++/* resp_type field */ ++#define RESP_TYPE_NONE 0 ++#define RESP_TYPE_136 1 ++#define RESP_TYPE_48 2 ++#define RESP_TYPE_48_BUSY 3 ++/* type field */ ++#define CMD_TYPE_NORMAL 0 ++#define CMD_TYPE_SUSPEND 1 ++#define CMD_TYPE_RESUME 2 ++#define CMD_TYPE_ABORT 3 ++ ++#define CMD_RESP_TYPE_M BITFIELD_MASK(2) /* Bits [0-1] - Response type */ ++#define CMD_RESP_TYPE_S 0 ++#define CMD_CRC_EN_M BITFIELD_MASK(1) /* Bit 3 - CRC enable */ ++#define CMD_CRC_EN_S 3 ++#define CMD_INDEX_EN_M BITFIELD_MASK(1) /* Bit 4 - Enable index checking */ ++#define CMD_INDEX_EN_S 4 ++#define CMD_DATA_EN_M BITFIELD_MASK(1) /* Bit 5 - Using DAT line */ ++#define CMD_DATA_EN_S 5 ++#define CMD_TYPE_M BITFIELD_MASK(2) /* Bit [6-7] - Normal, abort, resume, etc ++ */ ++#define CMD_TYPE_S 6 ++#define CMD_INDEX_M BITFIELD_MASK(6) /* Bits [8-13] - Command number */ ++#define CMD_INDEX_S 8 ++ ++/* SD_BufferDataPort0 : Offset 0x020, size = 2 or 4 bytes */ ++/* SD_BufferDataPort1 : Offset 0x022, size = 2 bytes */ ++/* SD_PresentState : Offset 0x024, size = 4 bytes */ ++#define PRES_CMD_INHIBIT_M BITFIELD_MASK(1) /* Bit 0 May use CMD */ ++#define PRES_CMD_INHIBIT_S 0 ++#define PRES_DAT_INHIBIT_M BITFIELD_MASK(1) /* Bit 1 May use DAT */ ++#define PRES_DAT_INHIBIT_S 1 ++#define PRES_DAT_BUSY_M BITFIELD_MASK(1) /* Bit 2 DAT is busy */ ++#define PRES_DAT_BUSY_S 2 ++#define PRES_PRESENT_RSVD_M BITFIELD_MASK(5) /* Bit [3-7] rsvd */ ++#define PRES_PRESENT_RSVD_S 3 ++#define PRES_WRITE_ACTIVE_M BITFIELD_MASK(1) /* Bit 8 Write is active */ ++#define PRES_WRITE_ACTIVE_S 8 ++#define PRES_READ_ACTIVE_M BITFIELD_MASK(1) /* Bit 9 Read is active */ ++#define PRES_READ_ACTIVE_S 9 ++#define PRES_WRITE_DATA_RDY_M BITFIELD_MASK(1) /* Bit 10 Write buf is avail */ ++#define PRES_WRITE_DATA_RDY_S 10 ++#define PRES_READ_DATA_RDY_M BITFIELD_MASK(1) /* Bit 11 Read buf data avail */ ++#define PRES_READ_DATA_RDY_S 11 ++#define PRES_CARD_PRESENT_M BITFIELD_MASK(1) /* Bit 16 Card present - debounced */ ++#define PRES_CARD_PRESENT_S 16 ++#define PRES_CARD_STABLE_M BITFIELD_MASK(1) /* Bit 17 Debugging */ ++#define PRES_CARD_STABLE_S 17 ++#define PRES_CARD_PRESENT_RAW_M BITFIELD_MASK(1) /* Bit 18 Not debounced */ ++#define PRES_CARD_PRESENT_RAW_S 18 ++#define PRES_WRITE_ENABLED_M BITFIELD_MASK(1) /* Bit 19 Write protected? */ ++#define PRES_WRITE_ENABLED_S 19 ++#define PRES_DAT_SIGNAL_M BITFIELD_MASK(4) /* Bit [20-23] Debugging */ ++#define PRES_DAT_SIGNAL_S 20 ++#define PRES_CMD_SIGNAL_M BITFIELD_MASK(1) /* Bit 24 Debugging */ ++#define PRES_CMD_SIGNAL_S 24 ++ ++/* SD_HostCntrl: Offset 0x028, size = 1 bytes */ ++#define HOST_LED_M BITFIELD_MASK(1) /* Bit 0 LED On/Off */ ++#define HOST_LED_S 0 ++#define HOST_DATA_WIDTH_M BITFIELD_MASK(1) /* Bit 1 4 bit enable */ ++#define HOST_DATA_WIDTH_S 1 ++#define HOST_HI_SPEED_EN_M BITFIELD_MASK(1) /* Bit 2 High speed vs low speed */ ++#define HOST_DMA_SEL_S 3 ++#define HOST_DMA_SEL_M BITFIELD_MASK(2) /* Bit 4:3 DMA Select */ ++#define HOST_HI_SPEED_EN_S 2 ++ ++/* Host Control2: */ ++#define HOSTCtrl2_PRESVAL_EN_M BITFIELD_MASK(1) /* 1 bit */ ++#define HOSTCtrl2_PRESVAL_EN_S 15 /* bit# */ ++ ++#define HOSTCtrl2_ASYINT_EN_M BITFIELD_MASK(1) /* 1 bit */ ++#define HOSTCtrl2_ASYINT_EN_S 14 /* bit# */ ++ ++#define HOSTCtrl2_SAMPCLK_SEL_M BITFIELD_MASK(1) /* 1 bit */ ++#define HOSTCtrl2_SAMPCLK_SEL_S 7 /* bit# */ ++ ++#define HOSTCtrl2_EXEC_TUNING_M BITFIELD_MASK(1) /* 1 bit */ ++#define HOSTCtrl2_EXEC_TUNING_S 6 /* bit# */ ++ ++#define HOSTCtrl2_DRIVSTRENGTH_SEL_M BITFIELD_MASK(2) /* 2 bit */ ++#define HOSTCtrl2_DRIVSTRENGTH_SEL_S 4 /* bit# */ ++ ++#define HOSTCtrl2_1_8SIG_EN_M BITFIELD_MASK(1) /* 1 bit */ ++#define HOSTCtrl2_1_8SIG_EN_S 3 /* bit# */ ++ ++#define HOSTCtrl2_UHSMODE_SEL_M BITFIELD_MASK(3) /* 3 bit */ ++#define HOSTCtrl2_UHSMODE_SEL_S 0 /* bit# */ ++ ++#define HOST_CONTR_VER_2 (1) ++#define HOST_CONTR_VER_3 (2) ++ ++/* misc defines */ ++#define SD1_MODE 0x1 /* SD Host Cntrlr Spec */ ++#define SD4_MODE 0x2 /* SD Host Cntrlr Spec */ ++ ++/* SD_PwrCntrl: Offset 0x029, size = 1 bytes */ ++#define PWR_BUS_EN_M BITFIELD_MASK(1) /* Bit 0 Power the bus */ ++#define PWR_BUS_EN_S 0 ++#define PWR_VOLTS_M BITFIELD_MASK(3) /* Bit [1-3] Voltage Select */ ++#define PWR_VOLTS_S 1 ++ ++/* SD_SoftwareReset: Offset 0x02F, size = 1 byte */ ++#define SW_RESET_ALL_M BITFIELD_MASK(1) /* Bit 0 Reset All */ ++#define SW_RESET_ALL_S 0 ++#define SW_RESET_CMD_M BITFIELD_MASK(1) /* Bit 1 CMD Line Reset */ ++#define SW_RESET_CMD_S 1 ++#define SW_RESET_DAT_M BITFIELD_MASK(1) /* Bit 2 DAT Line Reset */ ++#define SW_RESET_DAT_S 2 ++ ++/* SD_IntrStatus: Offset 0x030, size = 2 bytes */ ++/* Defs also serve SD_IntrStatusEnable and SD_IntrSignalEnable */ ++#define INTSTAT_CMD_COMPLETE_M BITFIELD_MASK(1) /* Bit 0 */ ++#define INTSTAT_CMD_COMPLETE_S 0 ++#define INTSTAT_XFER_COMPLETE_M BITFIELD_MASK(1) ++#define INTSTAT_XFER_COMPLETE_S 1 ++#define INTSTAT_BLOCK_GAP_EVENT_M BITFIELD_MASK(1) ++#define INTSTAT_BLOCK_GAP_EVENT_S 2 ++#define INTSTAT_DMA_INT_M BITFIELD_MASK(1) ++#define INTSTAT_DMA_INT_S 3 ++#define INTSTAT_BUF_WRITE_READY_M BITFIELD_MASK(1) ++#define INTSTAT_BUF_WRITE_READY_S 4 ++#define INTSTAT_BUF_READ_READY_M BITFIELD_MASK(1) ++#define INTSTAT_BUF_READ_READY_S 5 ++#define INTSTAT_CARD_INSERTION_M BITFIELD_MASK(1) ++#define INTSTAT_CARD_INSERTION_S 6 ++#define INTSTAT_CARD_REMOVAL_M BITFIELD_MASK(1) ++#define INTSTAT_CARD_REMOVAL_S 7 ++#define INTSTAT_CARD_INT_M BITFIELD_MASK(1) ++#define INTSTAT_CARD_INT_S 8 ++#define INTSTAT_RETUNING_INT_M BITFIELD_MASK(1) /* Bit 12 */ ++#define INTSTAT_RETUNING_INT_S 12 ++#define INTSTAT_ERROR_INT_M BITFIELD_MASK(1) /* Bit 15 */ ++#define INTSTAT_ERROR_INT_S 15 ++ ++/* SD_ErrorIntrStatus: Offset 0x032, size = 2 bytes */ ++/* Defs also serve SD_ErrorIntrStatusEnable and SD_ErrorIntrSignalEnable */ ++#define ERRINT_CMD_TIMEOUT_M BITFIELD_MASK(1) ++#define ERRINT_CMD_TIMEOUT_S 0 ++#define ERRINT_CMD_CRC_M BITFIELD_MASK(1) ++#define ERRINT_CMD_CRC_S 1 ++#define ERRINT_CMD_ENDBIT_M BITFIELD_MASK(1) ++#define ERRINT_CMD_ENDBIT_S 2 ++#define ERRINT_CMD_INDEX_M BITFIELD_MASK(1) ++#define ERRINT_CMD_INDEX_S 3 ++#define ERRINT_DATA_TIMEOUT_M BITFIELD_MASK(1) ++#define ERRINT_DATA_TIMEOUT_S 4 ++#define ERRINT_DATA_CRC_M BITFIELD_MASK(1) ++#define ERRINT_DATA_CRC_S 5 ++#define ERRINT_DATA_ENDBIT_M BITFIELD_MASK(1) ++#define ERRINT_DATA_ENDBIT_S 6 ++#define ERRINT_CURRENT_LIMIT_M BITFIELD_MASK(1) ++#define ERRINT_CURRENT_LIMIT_S 7 ++#define ERRINT_AUTO_CMD12_M BITFIELD_MASK(1) ++#define ERRINT_AUTO_CMD12_S 8 ++#define ERRINT_VENDOR_M BITFIELD_MASK(4) ++#define ERRINT_VENDOR_S 12 ++#define ERRINT_ADMA_M BITFIELD_MASK(1) ++#define ERRINT_ADMA_S 9 ++ ++/* Also provide definitions in "normal" form to allow combined masks */ ++#define ERRINT_CMD_TIMEOUT_BIT 0x0001 ++#define ERRINT_CMD_CRC_BIT 0x0002 ++#define ERRINT_CMD_ENDBIT_BIT 0x0004 ++#define ERRINT_CMD_INDEX_BIT 0x0008 ++#define ERRINT_DATA_TIMEOUT_BIT 0x0010 ++#define ERRINT_DATA_CRC_BIT 0x0020 ++#define ERRINT_DATA_ENDBIT_BIT 0x0040 ++#define ERRINT_CURRENT_LIMIT_BIT 0x0080 ++#define ERRINT_AUTO_CMD12_BIT 0x0100 ++#define ERRINT_ADMA_BIT 0x0200 ++ ++/* Masks to select CMD vs. DATA errors */ ++#define ERRINT_CMD_ERRS (ERRINT_CMD_TIMEOUT_BIT | ERRINT_CMD_CRC_BIT |\ ++ ERRINT_CMD_ENDBIT_BIT | ERRINT_CMD_INDEX_BIT) ++#define ERRINT_DATA_ERRS (ERRINT_DATA_TIMEOUT_BIT | ERRINT_DATA_CRC_BIT |\ ++ ERRINT_DATA_ENDBIT_BIT | ERRINT_ADMA_BIT) ++#define ERRINT_TRANSFER_ERRS (ERRINT_CMD_ERRS | ERRINT_DATA_ERRS) ++ ++/* SD_WakeupCntr_BlockGapCntrl : Offset 0x02A , size = bytes */ ++/* SD_ClockCntrl : Offset 0x02C , size = bytes */ ++/* SD_SoftwareReset_TimeoutCntrl : Offset 0x02E , size = bytes */ ++/* SD_IntrStatus : Offset 0x030 , size = bytes */ ++/* SD_ErrorIntrStatus : Offset 0x032 , size = bytes */ ++/* SD_IntrStatusEnable : Offset 0x034 , size = bytes */ ++/* SD_ErrorIntrStatusEnable : Offset 0x036 , size = bytes */ ++/* SD_IntrSignalEnable : Offset 0x038 , size = bytes */ ++/* SD_ErrorIntrSignalEnable : Offset 0x03A , size = bytes */ ++/* SD_CMD12ErrorStatus : Offset 0x03C , size = bytes */ ++/* SD_Capabilities : Offset 0x040 , size = bytes */ ++/* SD_MaxCurCap : Offset 0x048 , size = bytes */ ++/* SD_MaxCurCap_Reserved: Offset 0x04C , size = bytes */ ++/* SD_SlotInterruptStatus: Offset 0x0FC , size = bytes */ ++/* SD_HostControllerVersion : Offset 0x0FE , size = bytes */ ++ ++/* SDIO Host Control Register DMA Mode Definitions */ ++#define SDIOH_SDMA_MODE 0 ++#define SDIOH_ADMA1_MODE 1 ++#define SDIOH_ADMA2_MODE 2 ++#define SDIOH_ADMA2_64_MODE 3 ++ ++#define ADMA2_ATTRIBUTE_VALID (1 << 0) /* ADMA Descriptor line valid */ ++#define ADMA2_ATTRIBUTE_END (1 << 1) /* End of Descriptor */ ++#define ADMA2_ATTRIBUTE_INT (1 << 2) /* Interrupt when line is done */ ++#define ADMA2_ATTRIBUTE_ACT_NOP (0 << 4) /* Skip current line, go to next. */ ++#define ADMA2_ATTRIBUTE_ACT_RSV (1 << 4) /* Same as NOP */ ++#define ADMA1_ATTRIBUTE_ACT_SET (1 << 4) /* ADMA1 Only - set transfer length */ ++#define ADMA2_ATTRIBUTE_ACT_TRAN (2 << 4) /* Transfer Data of one descriptor line. */ ++#define ADMA2_ATTRIBUTE_ACT_LINK (3 << 4) /* Link Descriptor */ ++ ++/* ADMA2 Descriptor Table Entry for 32-bit Address */ ++typedef struct adma2_dscr_32b { ++ uint32 len_attr; ++ uint32 phys_addr; ++} adma2_dscr_32b_t; ++ ++/* ADMA1 Descriptor Table Entry */ ++typedef struct adma1_dscr { ++ uint32 phys_addr_attr; ++} adma1_dscr_t; ++ ++#endif /* _SDIOH_H */ +diff --git a/drivers/net/wireless/ap6210/include/sdiovar.h b/drivers/net/wireless/ap6210/include/sdiovar.h +new file mode 100755 +index 0000000..83f82de +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/sdiovar.h +@@ -0,0 +1,58 @@ ++/* ++ * Structure used by apps whose drivers access SDIO drivers. ++ * Pulled out separately so dhdu and wlu can both use it. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: sdiovar.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _sdiovar_h_ ++#define _sdiovar_h_ ++ ++#include ++ ++/* require default structure packing */ ++#define BWL_DEFAULT_PACKING ++#include ++ ++typedef struct sdreg { ++ int func; ++ int offset; ++ int value; ++} sdreg_t; ++ ++/* Common msglevel constants */ ++#define SDH_ERROR_VAL 0x0001 /* Error */ ++#define SDH_TRACE_VAL 0x0002 /* Trace */ ++#define SDH_INFO_VAL 0x0004 /* Info */ ++#define SDH_DEBUG_VAL 0x0008 /* Debug */ ++#define SDH_DATA_VAL 0x0010 /* Data */ ++#define SDH_CTRL_VAL 0x0020 /* Control Regs */ ++#define SDH_LOG_VAL 0x0040 /* Enable bcmlog */ ++#define SDH_DMA_VAL 0x0080 /* DMA */ ++ ++#define NUM_PREV_TRANSACTIONS 16 ++ ++ ++#include ++ ++#endif /* _sdiovar_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/siutils.h b/drivers/net/wireless/ap6210/include/siutils.h +new file mode 100755 +index 0000000..acc72ee +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/siutils.h +@@ -0,0 +1,347 @@ ++/* ++ * Misc utility routines for accessing the SOC Interconnects ++ * of Broadcom HNBU chips. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: siutils.h 347614 2012-07-27 10:24:51Z $ ++ */ ++ ++#ifndef _siutils_h_ ++#define _siutils_h_ ++ ++/* ++ * Data structure to export all chip specific common variables ++ * public (read-only) portion of siutils handle returned by si_attach()/si_kattach() ++ */ ++struct si_pub { ++ uint socitype; /* SOCI_SB, SOCI_AI */ ++ ++ uint bustype; /* SI_BUS, PCI_BUS */ ++ uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */ ++ uint buscorerev; /* buscore rev */ ++ uint buscoreidx; /* buscore index */ ++ int ccrev; /* chip common core rev */ ++ uint32 cccaps; /* chip common capabilities */ ++ uint32 cccaps_ext; /* chip common capabilities extension */ ++ int pmurev; /* pmu core rev */ ++ uint32 pmucaps; /* pmu capabilities */ ++ uint boardtype; /* board type */ ++ uint boardrev; /* board rev */ ++ uint boardvendor; /* board vendor */ ++ uint boardflags; /* board flags */ ++ uint boardflags2; /* board flags2 */ ++ uint chip; /* chip number */ ++ uint chiprev; /* chip revision */ ++ uint chippkg; /* chip package option */ ++ uint32 chipst; /* chip status */ ++ bool issim; /* chip is in simulation or emulation */ ++ uint socirev; /* SOC interconnect rev */ ++ bool pci_pr32414; ++ ++}; ++ ++/* for HIGH_ONLY driver, the si_t must be writable to allow states sync from BMAC to HIGH driver ++ * for monolithic driver, it is readonly to prevent accident change ++ */ ++typedef const struct si_pub si_t; ++ ++ ++/* ++ * Many of the routines below take an 'sih' handle as their first arg. ++ * Allocate this by calling si_attach(). Free it by calling si_detach(). ++ * At any one time, the sih is logically focused on one particular si core ++ * (the "current core"). ++ * Use si_setcore() or si_setcoreidx() to change the association to another core. ++ */ ++#define SI_OSH NULL /* Use for si_kattach when no osh is available */ ++ ++#define BADIDX (SI_MAXCORES + 1) ++ ++/* clkctl xtal what flags */ ++#define XTAL 0x1 /* primary crystal oscillator (2050) */ ++#define PLL 0x2 /* main chip pll */ ++ ++/* clkctl clk mode */ ++#define CLK_FAST 0 /* force fast (pll) clock */ ++#define CLK_DYNAMIC 2 /* enable dynamic clock control */ ++ ++/* GPIO usage priorities */ ++#define GPIO_DRV_PRIORITY 0 /* Driver */ ++#define GPIO_APP_PRIORITY 1 /* Application */ ++#define GPIO_HI_PRIORITY 2 /* Highest priority. Ignore GPIO reservation */ ++ ++/* GPIO pull up/down */ ++#define GPIO_PULLUP 0 ++#define GPIO_PULLDN 1 ++ ++/* GPIO event regtype */ ++#define GPIO_REGEVT 0 /* GPIO register event */ ++#define GPIO_REGEVT_INTMSK 1 /* GPIO register event int mask */ ++#define GPIO_REGEVT_INTPOL 2 /* GPIO register event int polarity */ ++ ++/* device path */ ++#define SI_DEVPATH_BUFSZ 16 /* min buffer size in bytes */ ++ ++/* SI routine enumeration: to be used by update function with multiple hooks */ ++#define SI_DOATTACH 1 ++#define SI_PCIDOWN 2 ++#define SI_PCIUP 3 ++ ++#define ISSIM_ENAB(sih) 0 ++ ++/* PMU clock/power control */ ++#if defined(BCMPMUCTL) ++#define PMUCTL_ENAB(sih) (BCMPMUCTL) ++#else ++#define PMUCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PMU) ++#endif ++ ++/* chipcommon clock/power control (exclusive with PMU's) */ ++#if defined(BCMPMUCTL) && BCMPMUCTL ++#define CCCTL_ENAB(sih) (0) ++#define CCPLL_ENAB(sih) (0) ++#else ++#define CCCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PWR_CTL) ++#define CCPLL_ENAB(sih) ((sih)->cccaps & CC_CAP_PLL_MASK) ++#endif ++ ++typedef void (*gpio_handler_t)(uint32 stat, void *arg); ++/* External BT Coex enable mask */ ++#define CC_BTCOEX_EN_MASK 0x01 ++/* External PA enable mask */ ++#define GPIO_CTRL_EPA_EN_MASK 0x40 ++/* WL/BT control enable mask */ ++#define GPIO_CTRL_5_6_EN_MASK 0x60 ++#define GPIO_CTRL_7_6_EN_MASK 0xC0 ++#define GPIO_OUT_7_EN_MASK 0x80 ++ ++ ++/* CR4 specific defines used by the host driver */ ++#define SI_CR4_CAP (0x04) ++#define SI_CR4_BANKIDX (0x40) ++#define SI_CR4_BANKINFO (0x44) ++ ++#define ARMCR4_TCBBNB_MASK 0xf0 ++#define ARMCR4_TCBBNB_SHIFT 4 ++#define ARMCR4_TCBANB_MASK 0xf ++#define ARMCR4_TCBANB_SHIFT 0 ++ ++#define SICF_CPUHALT (0x0020) ++#define ARMCR4_BSZ_MASK 0x3f ++#define ARMCR4_BSZ_MULT 8192 ++ ++ ++/* === exported functions === */ ++extern si_t *si_attach(uint pcidev, osl_t *osh, void *regs, uint bustype, ++ void *sdh, char **vars, uint *varsz); ++extern si_t *si_kattach(osl_t *osh); ++extern void si_detach(si_t *sih); ++extern bool si_pci_war16165(si_t *sih); ++ ++extern uint si_corelist(si_t *sih, uint coreid[]); ++extern uint si_coreid(si_t *sih); ++extern uint si_flag(si_t *sih); ++extern uint si_intflag(si_t *sih); ++extern uint si_coreidx(si_t *sih); ++extern uint si_coreunit(si_t *sih); ++extern uint si_corevendor(si_t *sih); ++extern uint si_corerev(si_t *sih); ++extern void *si_osh(si_t *sih); ++extern void si_setosh(si_t *sih, osl_t *osh); ++extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); ++extern void *si_coreregs(si_t *sih); ++extern uint si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val); ++extern uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val); ++extern void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); ++extern uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val); ++extern bool si_iscoreup(si_t *sih); ++extern uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit); ++extern void *si_setcoreidx(si_t *sih, uint coreidx); ++extern void *si_setcore(si_t *sih, uint coreid, uint coreunit); ++extern void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val); ++extern void si_restore_core(si_t *sih, uint coreid, uint intr_val); ++extern int si_numaddrspaces(si_t *sih); ++extern uint32 si_addrspace(si_t *sih, uint asidx); ++extern uint32 si_addrspacesize(si_t *sih, uint asidx); ++extern void si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size); ++extern int si_corebist(si_t *sih); ++extern void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits); ++extern void si_core_disable(si_t *sih, uint32 bits); ++extern uint32 si_clock_rate(uint32 pll_type, uint32 n, uint32 m); ++extern bool si_read_pmu_autopll(si_t *sih); ++extern uint32 si_clock(si_t *sih); ++extern uint32 si_alp_clock(si_t *sih); ++extern uint32 si_ilp_clock(si_t *sih); ++extern void si_pci_setup(si_t *sih, uint coremask); ++extern void si_pcmcia_init(si_t *sih); ++extern void si_setint(si_t *sih, int siflag); ++extern bool si_backplane64(si_t *sih); ++extern void si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn, ++ void *intrsenabled_fn, void *intr_arg); ++extern void si_deregister_intr_callback(si_t *sih); ++extern void si_clkctl_init(si_t *sih); ++extern uint16 si_clkctl_fast_pwrup_delay(si_t *sih); ++extern bool si_clkctl_cc(si_t *sih, uint mode); ++extern int si_clkctl_xtal(si_t *sih, uint what, bool on); ++extern uint32 si_gpiotimerval(si_t *sih, uint32 mask, uint32 val); ++extern void si_btcgpiowar(si_t *sih); ++extern bool si_deviceremoved(si_t *sih); ++extern uint32 si_socram_size(si_t *sih); ++extern uint32 si_socdevram_size(si_t *sih); ++extern uint32 si_socram_srmem_size(si_t *sih); ++extern void si_socdevram(si_t *sih, bool set, uint8 *ennable, uint8 *protect, uint8 *remap); ++extern bool si_socdevram_pkg(si_t *sih); ++extern bool si_socdevram_remap_isenb(si_t *sih); ++extern uint32 si_socdevram_remap_size(si_t *sih); ++ ++extern void si_watchdog(si_t *sih, uint ticks); ++extern void si_watchdog_ms(si_t *sih, uint32 ms); ++extern uint32 si_watchdog_msticks(void); ++extern void *si_gpiosetcore(si_t *sih); ++extern uint32 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority); ++extern uint32 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority); ++extern uint32 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority); ++extern uint32 si_gpioin(si_t *sih); ++extern uint32 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority); ++extern uint32 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority); ++extern uint32 si_gpioled(si_t *sih, uint32 mask, uint32 val); ++extern uint32 si_gpioreserve(si_t *sih, uint32 gpio_num, uint8 priority); ++extern uint32 si_gpiorelease(si_t *sih, uint32 gpio_num, uint8 priority); ++extern uint32 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val); ++extern uint32 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val); ++extern uint32 si_gpio_int_enable(si_t *sih, bool enable); ++ ++/* GPIO event handlers */ ++extern void *si_gpio_handler_register(si_t *sih, uint32 e, bool lev, gpio_handler_t cb, void *arg); ++extern void si_gpio_handler_unregister(si_t *sih, void* gpioh); ++extern void si_gpio_handler_process(si_t *sih); ++ ++/* Wake-on-wireless-LAN (WOWL) */ ++extern bool si_pci_pmecap(si_t *sih); ++struct osl_info; ++extern bool si_pci_fastpmecap(struct osl_info *osh); ++extern bool si_pci_pmestat(si_t *sih); ++extern void si_pci_pmeclr(si_t *sih); ++extern void si_pci_pmeen(si_t *sih); ++extern void si_pci_pmestatclr(si_t *sih); ++extern uint si_pcie_readreg(void *sih, uint addrtype, uint offset); ++ ++extern void si_sdio_init(si_t *sih); ++ ++extern uint16 si_d11_devid(si_t *sih); ++extern int si_corepciid(si_t *sih, uint func, uint16 *pcivendor, uint16 *pcidevice, ++ uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif, uint8 *pciheader); ++ ++#define si_eci(sih) 0 ++static INLINE void * si_eci_init(si_t *sih) {return NULL;} ++#define si_eci_notify_bt(sih, type, val) (0) ++#define si_seci(sih) 0 ++#define si_seci_upd(sih, a) do {} while (0) ++static INLINE void * si_seci_init(si_t *sih, uint8 use_seci) {return NULL;} ++#define si_seci_down(sih) do {} while (0) ++ ++/* OTP status */ ++extern bool si_is_otp_disabled(si_t *sih); ++extern bool si_is_otp_powered(si_t *sih); ++extern void si_otp_power(si_t *sih, bool on); ++ ++/* SPROM availability */ ++extern bool si_is_sprom_available(si_t *sih); ++extern bool si_is_sprom_enabled(si_t *sih); ++extern void si_sprom_enable(si_t *sih, bool enable); ++ ++/* OTP/SROM CIS stuff */ ++extern int si_cis_source(si_t *sih); ++#define CIS_DEFAULT 0 ++#define CIS_SROM 1 ++#define CIS_OTP 2 ++ ++/* Fab-id information */ ++#define DEFAULT_FAB 0x0 /* Original/first fab used for this chip */ ++#define CSM_FAB7 0x1 /* CSM Fab7 chip */ ++#define TSMC_FAB12 0x2 /* TSMC Fab12/Fab14 chip */ ++#define SMIC_FAB4 0x3 /* SMIC Fab4 chip */ ++extern int si_otp_fabid(si_t *sih, uint16 *fabid, bool rw); ++extern uint16 si_fabid(si_t *sih); ++ ++/* ++ * Build device path. Path size must be >= SI_DEVPATH_BUFSZ. ++ * The returned path is NULL terminated and has trailing '/'. ++ * Return 0 on success, nonzero otherwise. ++ */ ++extern int si_devpath(si_t *sih, char *path, int size); ++/* Read variable with prepending the devpath to the name */ ++extern char *si_getdevpathvar(si_t *sih, const char *name); ++extern int si_getdevpathintvar(si_t *sih, const char *name); ++extern char *si_coded_devpathvar(si_t *sih, char *varname, int var_len, const char *name); ++ ++ ++extern uint8 si_pcieclkreq(si_t *sih, uint32 mask, uint32 val); ++extern uint32 si_pcielcreg(si_t *sih, uint32 mask, uint32 val); ++extern void si_war42780_clkreq(si_t *sih, bool clkreq); ++extern void si_pci_down(si_t *sih); ++extern void si_pci_up(si_t *sih); ++extern void si_pci_sleep(si_t *sih); ++extern void si_pcie_war_ovr_update(si_t *sih, uint8 aspm); ++extern void si_pcie_power_save_enable(si_t *sih, bool enable); ++extern void si_pcie_extendL1timer(si_t *sih, bool extend); ++extern int si_pci_fixcfg(si_t *sih); ++extern void si_chippkg_set(si_t *sih, uint); ++ ++extern void si_chipcontrl_btshd0_4331(si_t *sih, bool on); ++extern void si_chipcontrl_restore(si_t *sih, uint32 val); ++extern uint32 si_chipcontrl_read(si_t *sih); ++extern void si_chipcontrl_epa4331(si_t *sih, bool on); ++extern void si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl); ++extern void si_chipcontrl_srom4360(si_t *sih, bool on); ++/* Enable BT-COEX & Ex-PA for 4313 */ ++extern void si_epa_4313war(si_t *sih); ++extern void si_btc_enable_chipcontrol(si_t *sih); ++/* BT/WL selection for 4313 bt combo >= P250 boards */ ++extern void si_btcombo_p250_4313_war(si_t *sih); ++extern void si_btcombo_43228_war(si_t *sih); ++extern void si_clk_pmu_htavail_set(si_t *sih, bool set_clear); ++extern uint si_pll_reset(si_t *sih); ++/* === debug routines === */ ++ ++extern bool si_taclear(si_t *sih, bool details); ++ ++ ++ ++extern uint32 si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type); ++extern uint32 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val); ++extern void si_pcie_set_request_size(si_t *sih, uint16 size); ++extern uint16 si_pcie_get_request_size(si_t *sih); ++extern uint16 si_pcie_get_ssid(si_t *sih); ++extern uint32 si_pcie_get_bar0(si_t *sih); ++extern int si_pcie_configspace_cache(si_t *sih); ++extern int si_pcie_configspace_restore(si_t *sih); ++extern int si_pcie_configspace_get(si_t *sih, uint8 *buf, uint size); ++ ++char *si_getnvramflvar(si_t *sih, const char *name); ++ ++ ++extern uint32 si_tcm_size(si_t *sih); ++ ++extern int si_set_sromctl(si_t *sih, uint32 value); ++extern uint32 si_get_sromctl(si_t *sih); ++#endif /* _siutils_h_ */ +diff --git a/drivers/net/wireless/ap6210/include/trxhdr.h b/drivers/net/wireless/ap6210/include/trxhdr.h +new file mode 100755 +index 0000000..bf92a56 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/trxhdr.h +@@ -0,0 +1,53 @@ ++/* ++ * TRX image file header format. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: trxhdr.h 260898 2011-05-20 23:11:12Z $ ++ */ ++ ++#ifndef _TRX_HDR_H ++#define _TRX_HDR_H ++ ++#include ++ ++#define TRX_MAGIC 0x30524448 /* "HDR0" */ ++#define TRX_VERSION 1 /* Version 1 */ ++#define TRX_MAX_LEN 0x3B0000 /* Max length */ ++#define TRX_NO_HEADER 1 /* Do not write TRX header */ ++#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ ++#define TRX_EMBED_UCODE 0x8 /* Trx contains embedded ucode image */ ++#define TRX_ROMSIM_IMAGE 0x10 /* Trx contains ROM simulation image */ ++#define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed rtecdc.bin image */ ++#define TRX_MAX_OFFSET 3 /* Max number of individual files */ ++ ++struct trx_header { ++ uint32 magic; /* "HDR0" */ ++ uint32 len; /* Length of file including header */ ++ uint32 crc32; /* 32-bit CRC from flag_version to end of file */ ++ uint32 flag_version; /* 0:15 flags, 16:31 version */ ++ uint32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ ++}; ++ ++/* Compatibility */ ++typedef struct trx_header TRXHDR, *PTRXHDR; ++ ++#endif /* _TRX_HDR_H */ +diff --git a/drivers/net/wireless/ap6210/include/typedefs.h b/drivers/net/wireless/ap6210/include/typedefs.h +new file mode 100755 +index 0000000..fe1d162 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/typedefs.h +@@ -0,0 +1,343 @@ ++/* ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * $Id: typedefs.h 286783 2011-09-29 06:18:57Z $ ++ */ ++ ++#ifndef _TYPEDEFS_H_ ++#define _TYPEDEFS_H_ ++ ++#ifdef SITE_TYPEDEFS ++ ++/* ++ * Define SITE_TYPEDEFS in the compile to include a site-specific ++ * typedef file "site_typedefs.h". ++ * ++ * If SITE_TYPEDEFS is not defined, then the code section below makes ++ * inferences about the compile environment based on defined symbols and ++ * possibly compiler pragmas. ++ * ++ * Following these two sections is the Default Typedefs section. ++ * This section is only processed if USE_TYPEDEF_DEFAULTS is ++ * defined. This section has a default set of typedefs and a few ++ * preprocessor symbols (TRUE, FALSE, NULL, ...). ++ */ ++ ++#include "site_typedefs.h" ++ ++#else ++ ++/* ++ * Infer the compile environment based on preprocessor symbols and pragmas. ++ * Override type definitions as needed, and include configuration-dependent ++ * header files to define types. ++ */ ++ ++#ifdef __cplusplus ++ ++#define TYPEDEF_BOOL ++#ifndef FALSE ++#define FALSE false ++#endif ++#ifndef TRUE ++#define TRUE true ++#endif ++ ++#else /* ! __cplusplus */ ++ ++ ++#endif /* ! __cplusplus */ ++ ++#if defined(__x86_64__) ++#define TYPEDEF_UINTPTR ++typedef unsigned long long int uintptr; ++#endif ++ ++ ++ ++ ++ ++#if defined(_NEED_SIZE_T_) ++typedef long unsigned int size_t; ++#endif ++ ++ ++ ++ ++#if defined(__sparc__) ++#define TYPEDEF_ULONG ++#endif ++ ++ ++/* ++ * If this is either a Linux hybrid build or the per-port code of a hybrid build ++ * then use the Linux header files to get some of the typedefs. Otherwise, define ++ * them entirely in this file. We can't always define the types because we get ++ * a duplicate typedef error; there is no way to "undefine" a typedef. ++ * We know when it's per-port code because each file defines LINUX_PORT at the top. ++ */ ++#if !defined(LINUX_HYBRID) || defined(LINUX_PORT) ++#define TYPEDEF_UINT ++#ifndef TARGETENV_android ++#define TYPEDEF_USHORT ++#define TYPEDEF_ULONG ++#endif /* TARGETENV_android */ ++#ifdef __KERNEL__ ++#include ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)) ++#define TYPEDEF_BOOL ++#endif /* >= 2.6.19 */ ++/* special detection for 2.6.18-128.7.1.0.1.el5 */ ++#if (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18)) ++#include ++#ifdef noinline_for_stack ++#define TYPEDEF_BOOL ++#endif ++#endif /* == 2.6.18 */ ++#endif /* __KERNEL__ */ ++#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ ++ ++ ++ ++ ++/* Do not support the (u)int64 types with strict ansi for GNU C */ ++#if defined(__GNUC__) && defined(__STRICT_ANSI__) ++#define TYPEDEF_INT64 ++#define TYPEDEF_UINT64 ++#endif ++ ++/* ICL accepts unsigned 64 bit type only, and complains in ANSI mode ++ * for signed or unsigned ++ */ ++#if defined(__ICL) ++ ++#define TYPEDEF_INT64 ++ ++#if defined(__STDC__) ++#define TYPEDEF_UINT64 ++#endif ++ ++#endif /* __ICL */ ++ ++#if !defined(__DJGPP__) ++ ++/* pick up ushort & uint from standard types.h */ ++#if defined(__KERNEL__) ++ ++/* See note above */ ++#if !defined(LINUX_HYBRID) || defined(LINUX_PORT) ++#include /* sys/types.h and linux/types.h are oil and water */ ++#endif /* !defined(LINUX_HYBRID) || defined(LINUX_PORT) */ ++ ++#else ++ ++ ++#include ++ ++#endif /* linux && __KERNEL__ */ ++ ++#endif ++ ++ ++ ++/* use the default typedefs in the next section of this file */ ++#define USE_TYPEDEF_DEFAULTS ++ ++#endif /* SITE_TYPEDEFS */ ++ ++ ++/* ++ * Default Typedefs ++ */ ++ ++#ifdef USE_TYPEDEF_DEFAULTS ++#undef USE_TYPEDEF_DEFAULTS ++ ++#ifndef TYPEDEF_BOOL ++typedef /* @abstract@ */ unsigned char bool; ++#endif ++ ++/* define uchar, ushort, uint, ulong */ ++ ++#ifndef TYPEDEF_UCHAR ++typedef unsigned char uchar; ++#endif ++ ++#ifndef TYPEDEF_USHORT ++typedef unsigned short ushort; ++#endif ++ ++#ifndef TYPEDEF_UINT ++typedef unsigned int uint; ++#endif ++ ++#ifndef TYPEDEF_ULONG ++typedef unsigned long ulong; ++#endif ++ ++/* define [u]int8/16/32/64, uintptr */ ++ ++#ifndef TYPEDEF_UINT8 ++typedef unsigned char uint8; ++#endif ++ ++#ifndef TYPEDEF_UINT16 ++typedef unsigned short uint16; ++#endif ++ ++#ifndef TYPEDEF_UINT32 ++typedef unsigned int uint32; ++#endif ++ ++#ifndef TYPEDEF_UINT64 ++typedef unsigned long long uint64; ++#endif ++ ++#ifndef TYPEDEF_UINTPTR ++typedef unsigned int uintptr; ++#endif ++ ++#ifndef TYPEDEF_INT8 ++typedef signed char int8; ++#endif ++ ++#ifndef TYPEDEF_INT16 ++typedef signed short int16; ++#endif ++ ++#ifndef TYPEDEF_INT32 ++typedef signed int int32; ++#endif ++ ++#ifndef TYPEDEF_INT64 ++typedef signed long long int64; ++#endif ++ ++/* define float32/64, float_t */ ++ ++#ifndef TYPEDEF_FLOAT32 ++typedef float float32; ++#endif ++ ++#ifndef TYPEDEF_FLOAT64 ++typedef double float64; ++#endif ++ ++/* ++ * abstracted floating point type allows for compile time selection of ++ * single or double precision arithmetic. Compiling with -DFLOAT32 ++ * selects single precision; the default is double precision. ++ */ ++ ++#ifndef TYPEDEF_FLOAT_T ++ ++#if defined(FLOAT32) ++typedef float32 float_t; ++#else /* default to double precision floating point */ ++typedef float64 float_t; ++#endif ++ ++#endif /* TYPEDEF_FLOAT_T */ ++ ++/* define macro values */ ++ ++#ifndef FALSE ++#define FALSE 0 ++#endif ++ ++#ifndef TRUE ++#define TRUE 1 /* TRUE */ ++#endif ++ ++#ifndef NULL ++#define NULL 0 ++#endif ++ ++#ifndef OFF ++#define OFF 0 ++#endif ++ ++#ifndef ON ++#define ON 1 /* ON = 1 */ ++#endif ++ ++#define AUTO (-1) /* Auto = -1 */ ++ ++/* define PTRSZ, INLINE */ ++ ++#ifndef PTRSZ ++#define PTRSZ sizeof(char*) ++#endif ++ ++ ++/* Detect compiler type. */ ++#if defined(__GNUC__) || defined(__lint) ++ #define BWL_COMPILER_GNU ++#elif defined(__CC_ARM) && __CC_ARM ++ #define BWL_COMPILER_ARMCC ++#else ++ #error "Unknown compiler!" ++#endif ++ ++ ++#ifndef INLINE ++ #if defined(BWL_COMPILER_MICROSOFT) ++ #define INLINE __inline ++ #elif defined(BWL_COMPILER_GNU) ++ #define INLINE __inline__ ++ #elif defined(BWL_COMPILER_ARMCC) ++ #define INLINE __inline ++ #else ++ #define INLINE ++ #endif ++#endif /* INLINE */ ++ ++#undef TYPEDEF_BOOL ++#undef TYPEDEF_UCHAR ++#undef TYPEDEF_USHORT ++#undef TYPEDEF_UINT ++#undef TYPEDEF_ULONG ++#undef TYPEDEF_UINT8 ++#undef TYPEDEF_UINT16 ++#undef TYPEDEF_UINT32 ++#undef TYPEDEF_UINT64 ++#undef TYPEDEF_UINTPTR ++#undef TYPEDEF_INT8 ++#undef TYPEDEF_INT16 ++#undef TYPEDEF_INT32 ++#undef TYPEDEF_INT64 ++#undef TYPEDEF_FLOAT32 ++#undef TYPEDEF_FLOAT64 ++#undef TYPEDEF_FLOAT_T ++ ++#endif /* USE_TYPEDEF_DEFAULTS */ ++ ++/* Suppress unused parameter warning */ ++#define UNUSED_PARAMETER(x) (void)(x) ++ ++/* Avoid warning for discarded const or volatile qualifier in special cases (-Wcast-qual) */ ++#define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr)) ++ ++/* ++ * Including the bcmdefs.h here, to make sure everyone including typedefs.h ++ * gets this automatically ++*/ ++#include ++#endif /* _TYPEDEFS_H_ */ +diff --git a/drivers/net/wireless/ap6210/include/wlfc_proto.h b/drivers/net/wireless/ap6210/include/wlfc_proto.h +new file mode 100755 +index 0000000..98d2fa9 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/wlfc_proto.h +@@ -0,0 +1,217 @@ ++/* ++* Copyright (C) 1999-2012, Broadcom Corporation ++* ++* Unless you and Broadcom execute a separate written software license ++* agreement governing use of this software, this software is licensed to you ++* under the terms of the GNU General Public License version 2 (the "GPL"), ++* available at http://www.broadcom.com/licenses/GPLv2.php, with the ++* following added to such license: ++* ++* As a special exception, the copyright holders of this software give you ++* permission to link this software with independent modules, and to copy and ++* distribute the resulting executable under terms of your choice, provided that ++* you also meet, for each linked independent module, the terms and conditions of ++* the license of that module. An independent module is a module which is not ++* derived from this software. The special exception does not apply to any ++* modifications of the software. ++* ++* Notwithstanding the above, under no circumstances may you combine this ++* software in any way with any other Broadcom software provided under a license ++* other than the GPL, without Broadcom's express prior written consent. ++* $Id: wlfc_proto.h 361006 2012-10-05 07:45:51Z $ ++* ++*/ ++#ifndef __wlfc_proto_definitions_h__ ++#define __wlfc_proto_definitions_h__ ++ ++ /* Use TLV to convey WLFC information. ++ --------------------------------------------------------------------------- ++ | Type | Len | value | Description ++ --------------------------------------------------------------------------- ++ | 1 | 1 | (handle) | MAC OPEN ++ --------------------------------------------------------------------------- ++ | 2 | 1 | (handle) | MAC CLOSE ++ --------------------------------------------------------------------------- ++ | 3 | 2 | (count, handle, prec_bmp)| Set the credit depth for a MAC dstn ++ --------------------------------------------------------------------------- ++ | 4 | 4 | see pkttag comments | TXSTATUS ++ --------------------------------------------------------------------------- ++ | 5 | 4 | see pkttag comments | PKKTTAG [host->firmware] ++ --------------------------------------------------------------------------- ++ | 6 | 8 | (handle, ifid, MAC) | MAC ADD ++ --------------------------------------------------------------------------- ++ | 7 | 8 | (handle, ifid, MAC) | MAC DEL ++ --------------------------------------------------------------------------- ++ | 8 | 1 | (rssi) | RSSI - RSSI value for the packet. ++ --------------------------------------------------------------------------- ++ | 9 | 1 | (interface ID) | Interface OPEN ++ --------------------------------------------------------------------------- ++ | 10 | 1 | (interface ID) | Interface CLOSE ++ --------------------------------------------------------------------------- ++ | 11 | 8 | fifo credit returns map | FIFO credits back to the host ++ | | | | ++ | | | | -------------------------------------- ++ | | | | | ac0 | ac1 | ac2 | ac3 | bcmc | atim | ++ | | | | -------------------------------------- ++ | | | | ++ --------------------------------------------------------------------------- ++ | 12 | 2 | MAC handle, | Host provides a bitmap of pending ++ | | | AC[0-3] traffic bitmap | unicast traffic for MAC-handle dstn. ++ | | | | [host->firmware] ++ --------------------------------------------------------------------------- ++ | 13 | 3 | (count, handle, prec_bmp)| One time request for packet to a specific ++ | | | | MAC destination. ++ --------------------------------------------------------------------------- ++ | 15 | 1 | interface ID | NIC period start ++ --------------------------------------------------------------------------- ++ | 16 | 1 | interface ID | NIC period end ++ --------------------------------------------------------------------------- ++ | 17 | 3 | (ifid, txs) | Action frame tx status ++ --------------------------------------------------------------------------- ++ | 255 | N/A | N/A | FILLER - This is a special type ++ | | | | that has no length or value. ++ | | | | Typically used for padding. ++ --------------------------------------------------------------------------- ++ */ ++ ++#define WLFC_CTL_TYPE_MAC_OPEN 1 ++#define WLFC_CTL_TYPE_MAC_CLOSE 2 ++#define WLFC_CTL_TYPE_MAC_REQUEST_CREDIT 3 ++#define WLFC_CTL_TYPE_TXSTATUS 4 ++#define WLFC_CTL_TYPE_PKTTAG 5 ++ ++#define WLFC_CTL_TYPE_MACDESC_ADD 6 ++#define WLFC_CTL_TYPE_MACDESC_DEL 7 ++#define WLFC_CTL_TYPE_RSSI 8 ++ ++#define WLFC_CTL_TYPE_INTERFACE_OPEN 9 ++#define WLFC_CTL_TYPE_INTERFACE_CLOSE 10 ++ ++#define WLFC_CTL_TYPE_FIFO_CREDITBACK 11 ++ ++#define WLFC_CTL_TYPE_PENDING_TRAFFIC_BMP 12 ++#define WLFC_CTL_TYPE_MAC_REQUEST_PACKET 13 ++#define WLFC_CTL_TYPE_HOST_REORDER_RXPKTS 14 ++ ++#define WLFC_CTL_TYPE_NIC_PRD_START 15 ++#define WLFC_CTL_TYPE_NIC_PRD_END 16 ++#define WLFC_CTL_TYPE_AF_TXS 17 ++#define WLFC_CTL_TYPE_TRANS_ID 18 ++#define WLFC_CTL_TYPE_COMP_TXSTATUS 19 ++ ++#define WLFC_CTL_TYPE_FILLER 255 ++ ++#define WLFC_CTL_VALUE_LEN_MACDESC 8 /* handle, interface, MAC */ ++ ++#define WLFC_CTL_VALUE_LEN_MAC 1 /* MAC-handle */ ++#define WLFC_CTL_VALUE_LEN_RSSI 1 ++ ++#define WLFC_CTL_VALUE_LEN_INTERFACE 1 ++#define WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP 2 ++ ++#define WLFC_CTL_VALUE_LEN_TXSTATUS 4 ++#define WLFC_CTL_VALUE_LEN_PKTTAG 4 ++ ++/* enough space to host all 4 ACs, bc/mc and atim fifo credit */ ++#define WLFC_CTL_VALUE_LEN_FIFO_CREDITBACK 6 ++ ++#define WLFC_CTL_VALUE_LEN_REQUEST_CREDIT 3 /* credit, MAC-handle, prec_bitmap */ ++#define WLFC_CTL_VALUE_LEN_REQUEST_PACKET 3 /* credit, MAC-handle, prec_bitmap */ ++ ++#define WLFC_CTL_VALUE_LEN_NIC_PRD_START 1 ++#define WLFC_CTL_VALUE_LEN_NIC_PRD_END 1 ++#define WLFC_CTL_VALUE_LEN_AF_TXS 3 ++ ++ ++#define WLFC_PKTID_GEN_MASK 0x80000000 ++#define WLFC_PKTID_GEN_SHIFT 31 ++ ++#define WLFC_PKTID_GEN(x) (((x) & WLFC_PKTID_GEN_MASK) >> WLFC_PKTID_GEN_SHIFT) ++#define WLFC_PKTID_SETGEN(x, gen) (x) = ((x) & ~WLFC_PKTID_GEN_MASK) | \ ++ (((gen) << WLFC_PKTID_GEN_SHIFT) & WLFC_PKTID_GEN_MASK) ++ ++#define WLFC_PKTFLAG_PKTFROMHOST 0x01 ++#define WLFC_PKTFLAG_PKT_REQUESTED 0x02 ++ ++#define WL_TXSTATUS_FLAGS_MASK 0xf /* allow 4 bits only */ ++#define WL_TXSTATUS_FLAGS_SHIFT 27 ++ ++#define WL_TXSTATUS_SET_FLAGS(x, flags) ((x) = \ ++ ((x) & ~(WL_TXSTATUS_FLAGS_MASK << WL_TXSTATUS_FLAGS_SHIFT)) | \ ++ (((flags) & WL_TXSTATUS_FLAGS_MASK) << WL_TXSTATUS_FLAGS_SHIFT)) ++#define WL_TXSTATUS_GET_FLAGS(x) (((x) >> WL_TXSTATUS_FLAGS_SHIFT) & \ ++ WL_TXSTATUS_FLAGS_MASK) ++ ++#define WL_TXSTATUS_FIFO_MASK 0x7 /* allow 3 bits for FIFO ID */ ++#define WL_TXSTATUS_FIFO_SHIFT 24 ++ ++#define WL_TXSTATUS_SET_FIFO(x, flags) ((x) = \ ++ ((x) & ~(WL_TXSTATUS_FIFO_MASK << WL_TXSTATUS_FIFO_SHIFT)) | \ ++ (((flags) & WL_TXSTATUS_FIFO_MASK) << WL_TXSTATUS_FIFO_SHIFT)) ++#define WL_TXSTATUS_GET_FIFO(x) (((x) >> WL_TXSTATUS_FIFO_SHIFT) & WL_TXSTATUS_FIFO_MASK) ++ ++#define WL_TXSTATUS_PKTID_MASK 0xffffff /* allow 24 bits */ ++#define WL_TXSTATUS_SET_PKTID(x, num) ((x) = \ ++ ((x) & ~WL_TXSTATUS_PKTID_MASK) | (num)) ++#define WL_TXSTATUS_GET_PKTID(x) ((x) & WL_TXSTATUS_PKTID_MASK) ++ ++/* 32 STA should be enough??, 6 bits; Must be power of 2 */ ++#define WLFC_MAC_DESC_TABLE_SIZE 32 ++#define WLFC_MAX_IFNUM 16 ++#define WLFC_MAC_DESC_ID_INVALID 0xff ++ ++/* b[7:5] -reuse guard, b[4:0] -value */ ++#define WLFC_MAC_DESC_GET_LOOKUP_INDEX(x) ((x) & 0x1f) ++ ++#define WLFC_PKTFLAG_SET_PKTREQUESTED(x) (x) |= \ ++ (WLFC_PKTFLAG_PKT_REQUESTED << WL_TXSTATUS_FLAGS_SHIFT) ++ ++#define WLFC_PKTFLAG_CLR_PKTREQUESTED(x) (x) &= \ ++ ~(WLFC_PKTFLAG_PKT_REQUESTED << WL_TXSTATUS_FLAGS_SHIFT) ++ ++#define WL_TXSTATUS_GENERATION_MASK 1 ++#define WL_TXSTATUS_GENERATION_SHIFT 31 ++ ++#define WLFC_PKTFLAG_SET_GENERATION(x, gen) ((x) = \ ++ ((x) & ~(WL_TXSTATUS_GENERATION_MASK << WL_TXSTATUS_GENERATION_SHIFT)) | \ ++ (((gen) & WL_TXSTATUS_GENERATION_MASK) << WL_TXSTATUS_GENERATION_SHIFT)) ++ ++#define WLFC_PKTFLAG_GENERATION(x) (((x) >> WL_TXSTATUS_GENERATION_SHIFT) & \ ++ WL_TXSTATUS_GENERATION_MASK) ++ ++#define WLFC_MAX_PENDING_DATALEN 120 ++ ++/* host is free to discard the packet */ ++#define WLFC_CTL_PKTFLAG_DISCARD 0 ++/* D11 suppressed a packet */ ++#define WLFC_CTL_PKTFLAG_D11SUPPRESS 1 ++/* WL firmware suppressed a packet because MAC is ++ already in PSMode (short time window) ++*/ ++#define WLFC_CTL_PKTFLAG_WLSUPPRESS 2 ++/* Firmware tossed this packet */ ++#define WLFC_CTL_PKTFLAG_TOSSED_BYWLC 3 ++ ++#define WLFC_D11_STATUS_INTERPRET(txs) \ ++ (((txs)->status.suppr_ind != 0) ? WLFC_CTL_PKTFLAG_D11SUPPRESS : WLFC_CTL_PKTFLAG_DISCARD) ++ ++/* AMPDU host reorder packet flags */ ++#define WLHOST_REORDERDATA_MAXFLOWS 256 ++#define WLHOST_REORDERDATA_LEN 10 ++#define WLHOST_REORDERDATA_TOTLEN (WLHOST_REORDERDATA_LEN + 1 + 1) /* +tag +len */ ++ ++#define WLHOST_REORDERDATA_FLOWID_OFFSET 0 ++#define WLHOST_REORDERDATA_MAXIDX_OFFSET 2 ++#define WLHOST_REORDERDATA_FLAGS_OFFSET 4 ++#define WLHOST_REORDERDATA_CURIDX_OFFSET 6 ++#define WLHOST_REORDERDATA_EXPIDX_OFFSET 8 ++ ++#define WLHOST_REORDERDATA_DEL_FLOW 0x01 ++#define WLHOST_REORDERDATA_FLUSH_ALL 0x02 ++#define WLHOST_REORDERDATA_CURIDX_VALID 0x04 ++#define WLHOST_REORDERDATA_EXPIDX_VALID 0x08 ++#define WLHOST_REORDERDATA_NEW_HOLE 0x10 ++/* transaction id data len byte 0: rsvd, byte 1: seqnumber, byte 2-5 will be used for timestampe */ ++#define WLFC_CTL_TRANS_ID_LEN 6 ++ ++#endif /* __wlfc_proto_definitions_h__ */ +diff --git a/drivers/net/wireless/ap6210/include/wlioctl.h b/drivers/net/wireless/ap6210/include/wlioctl.h +new file mode 100755 +index 0000000..a3e7003 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/include/wlioctl.h +@@ -0,0 +1,5079 @@ ++/* ++ * Custom OID/ioctl definitions for ++ * Broadcom 802.11abg Networking Device Driver ++ * ++ * Definitions subject to change without notice. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: wlioctl.h 366141 2012-11-01 01:55:06Z $ ++ */ ++ ++#ifndef _wlioctl_h_ ++#define _wlioctl_h_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++#include ++#include ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* LINUX_POSTMOGRIFY_REMOVAL: undefined during compile phase, so its ++ * a no-op for most cases. For hybrid and other open source releases, ++ * its defined during a second pass and mogrified out for distribution. ++ */ ++ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++ ++#ifndef INTF_NAME_SIZ ++#define INTF_NAME_SIZ 16 ++#endif ++ ++/* Used to send ioctls over the transport pipe */ ++typedef struct remote_ioctl { ++ cdc_ioctl_t msg; ++ uint data_len; ++ char intf_name[INTF_NAME_SIZ]; ++} rem_ioctl_t; ++#define REMOTE_SIZE sizeof(rem_ioctl_t) ++ ++#define ACTION_FRAME_SIZE 1800 ++ ++typedef struct wl_action_frame { ++ struct ether_addr da; ++ uint16 len; ++ uint32 packetId; ++ uint8 data[ACTION_FRAME_SIZE]; ++} wl_action_frame_t; ++ ++#define WL_WIFI_ACTION_FRAME_SIZE sizeof(struct wl_action_frame) ++ ++typedef struct ssid_info ++{ ++ uint8 ssid_len; /* the length of SSID */ ++ uint8 ssid[32]; /* SSID string */ ++} ssid_info_t; ++ ++typedef struct wl_af_params { ++ uint32 channel; ++ int32 dwell_time; ++ struct ether_addr BSSID; ++ wl_action_frame_t action_frame; ++} wl_af_params_t; ++ ++#define WL_WIFI_AF_PARAMS_SIZE sizeof(struct wl_af_params) ++ ++#define MFP_TEST_FLAG_NORMAL 0 ++#define MFP_TEST_FLAG_ANY_KEY 1 ++typedef struct wl_sa_query { ++ uint32 flag; ++ uint8 action; ++ uint16 id; ++ struct ether_addr da; ++} wl_sa_query_t; ++ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* require default structure packing */ ++#define BWL_DEFAULT_PACKING ++#include ++ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* Legacy structure to help keep backward compatible wl tool and tray app */ ++ ++#define LEGACY_WL_BSS_INFO_VERSION 107 /* older version of wl_bss_info struct */ ++ ++typedef struct wl_bss_info_107 { ++ uint32 version; /* version field */ ++ uint32 length; /* byte length of data in this record, ++ * starting at version and including IEs ++ */ ++ struct ether_addr BSSID; ++ uint16 beacon_period; /* units are Kusec */ ++ uint16 capability; /* Capability information */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++ struct { ++ uint count; /* # rates in this set */ ++ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ ++ } rateset; /* supported rates */ ++ uint8 channel; /* Channel no. */ ++ uint16 atim_window; /* units are Kusec */ ++ uint8 dtim_period; /* DTIM period */ ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ int8 phy_noise; /* noise (in dBm) */ ++ uint32 ie_length; /* byte length of Information Elements */ ++ /* variable length Information Elements */ ++} wl_bss_info_107_t; ++ ++/* ++ * Per-BSS information structure. ++ */ ++ ++#define LEGACY2_WL_BSS_INFO_VERSION 108 /* old version of wl_bss_info struct */ ++ ++/* BSS info structure ++ * Applications MUST CHECK ie_offset field and length field to access IEs and ++ * next bss_info structure in a vector (in wl_scan_results_t) ++ */ ++typedef struct wl_bss_info_108 { ++ uint32 version; /* version field */ ++ uint32 length; /* byte length of data in this record, ++ * starting at version and including IEs ++ */ ++ struct ether_addr BSSID; ++ uint16 beacon_period; /* units are Kusec */ ++ uint16 capability; /* Capability information */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++ struct { ++ uint count; /* # rates in this set */ ++ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ ++ } rateset; /* supported rates */ ++ chanspec_t chanspec; /* chanspec for bss */ ++ uint16 atim_window; /* units are Kusec */ ++ uint8 dtim_period; /* DTIM period */ ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ int8 phy_noise; /* noise (in dBm) */ ++ ++ uint8 n_cap; /* BSS is 802.11N Capable */ ++ uint32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */ ++ uint8 ctl_ch; /* 802.11N BSS control channel number */ ++ uint32 reserved32[1]; /* Reserved for expansion of BSS properties */ ++ uint8 flags; /* flags */ ++ uint8 reserved[3]; /* Reserved for expansion of BSS properties */ ++ uint8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ ++ ++ uint16 ie_offset; /* offset at which IEs start, from beginning */ ++ uint32 ie_length; /* byte length of Information Elements */ ++ /* Add new fields here */ ++ /* variable length Information Elements */ ++} wl_bss_info_108_t; ++ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++#define WL_BSS_INFO_VERSION 109 /* current version of wl_bss_info struct */ ++ ++/* BSS info structure ++ * Applications MUST CHECK ie_offset field and length field to access IEs and ++ * next bss_info structure in a vector (in wl_scan_results_t) ++ */ ++typedef struct wl_bss_info { ++ uint32 version; /* version field */ ++ uint32 length; /* byte length of data in this record, ++ * starting at version and including IEs ++ */ ++ struct ether_addr BSSID; ++ uint16 beacon_period; /* units are Kusec */ ++ uint16 capability; /* Capability information */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++ struct { ++ uint count; /* # rates in this set */ ++ uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ ++ } rateset; /* supported rates */ ++ chanspec_t chanspec; /* chanspec for bss */ ++ uint16 atim_window; /* units are Kusec */ ++ uint8 dtim_period; /* DTIM period */ ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ int8 phy_noise; /* noise (in dBm) */ ++ ++ uint8 n_cap; /* BSS is 802.11N Capable */ ++ uint32 nbss_cap; /* 802.11N+AC BSS Capabilities */ ++ uint8 ctl_ch; /* 802.11N BSS control channel number */ ++ uint8 padding1[3]; /* explicit struct alignment padding */ ++ uint16 vht_rxmcsmap; /* VHT rx mcs map */ ++ uint16 vht_txmcsmap; /* VHT tx mcs map */ ++ uint8 flags; /* flags */ ++ uint8 vht_cap; /* BSS is vht capable */ ++ uint8 reserved[2]; /* Reserved for expansion of BSS properties */ ++ uint8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ ++ ++ uint16 ie_offset; /* offset at which IEs start, from beginning */ ++ uint32 ie_length; /* byte length of Information Elements */ ++ int16 SNR; /* average SNR of during frame reception */ ++ /* Add new fields here */ ++ /* variable length Information Elements */ ++} wl_bss_info_t; ++ ++/* bss_info_cap_t flags */ ++#define WL_BSS_FLAGS_FROM_BEACON 0x01 /* bss_info derived from beacon */ ++#define WL_BSS_FLAGS_FROM_CACHE 0x02 /* bss_info collected from cache */ ++#define WL_BSS_FLAGS_RSSI_ONCHANNEL 0x04 /* rssi info was received on channel (vs offchannel) */ ++ ++/* bssinfo flag for nbss_cap */ ++#define VHT_BI_SGI_80MHZ 0x00000100 ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++ ++typedef struct wl_bsscfg { ++ uint32 wsec; ++ uint32 WPA_auth; ++ uint32 wsec_index; ++ uint32 associated; ++ uint32 BSS; ++ uint32 phytest_on; ++ struct ether_addr prev_BSSID; ++ struct ether_addr BSSID; ++ uint32 targetbss_wpa2_flags; ++ uint32 assoc_type; ++ uint32 assoc_state; ++} wl_bsscfg_t; ++ ++typedef struct wl_bss_config { ++ uint32 atim_window; ++ uint32 beacon_period; ++ uint32 chanspec; ++} wl_bss_config_t; ++ ++#define DLOAD_HANDLER_VER 1 /* Downloader version */ ++#define DLOAD_FLAG_VER_MASK 0xf000 /* Downloader version mask */ ++#define DLOAD_FLAG_VER_SHIFT 12 /* Downloader version shift */ ++ ++#define DL_CRC_NOT_INUSE 0x0001 ++ ++/* generic download types & flags */ ++enum { ++ DL_TYPE_UCODE = 1, ++ DL_TYPE_CLM = 2 ++}; ++ ++/* ucode type values */ ++enum { ++ UCODE_FW, ++ INIT_VALS, ++ BS_INIT_VALS ++}; ++ ++struct wl_dload_data { ++ uint16 flag; ++ uint16 dload_type; ++ uint32 len; ++ uint32 crc; ++ uint8 data[1]; ++}; ++typedef struct wl_dload_data wl_dload_data_t; ++ ++struct wl_ucode_info { ++ uint32 ucode_type; ++ uint32 num_chunks; ++ uint32 chunk_len; ++ uint32 chunk_num; ++ uint8 data_chunk[1]; ++}; ++typedef struct wl_ucode_info wl_ucode_info_t; ++ ++struct wl_clm_dload_info { ++ uint32 ds_id; ++ uint32 clm_total_len; ++ uint32 num_chunks; ++ uint32 chunk_len; ++ uint32 chunk_offset; ++ uint8 data_chunk[1]; ++}; ++typedef struct wl_clm_dload_info wl_clm_dload_info_t; ++ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++typedef struct wlc_ssid { ++ uint32 SSID_len; ++ uchar SSID[32]; ++} wlc_ssid_t; ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++ ++#define MAX_PREFERRED_AP_NUM 5 ++typedef struct wlc_fastssidinfo { ++ uint32 SSID_channel[MAX_PREFERRED_AP_NUM]; ++ wlc_ssid_t SSID_info[MAX_PREFERRED_AP_NUM]; ++} wlc_fastssidinfo_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct wnm_url { ++ uint8 len; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT wnm_url_t; ++ ++typedef struct chan_scandata { ++ uint8 txpower; ++ uint8 pad; ++ chanspec_t channel; /* Channel num, bw, ctrl_sb and band */ ++ uint32 channel_mintime; ++ uint32 channel_maxtime; ++} chan_scandata_t; ++ ++typedef enum wl_scan_type { ++ EXTDSCAN_FOREGROUND_SCAN, ++ EXTDSCAN_BACKGROUND_SCAN, ++ EXTDSCAN_FORCEDBACKGROUND_SCAN ++} wl_scan_type_t; ++ ++#define WLC_EXTDSCAN_MAX_SSID 5 ++ ++typedef struct wl_extdscan_params { ++ int8 nprobes; /* 0, passive, otherwise active */ ++ int8 split_scan; /* split scan */ ++ int8 band; /* band */ ++ int8 pad; ++ wlc_ssid_t ssid[WLC_EXTDSCAN_MAX_SSID]; /* ssid list */ ++ uint32 tx_rate; /* in 500ksec units */ ++ wl_scan_type_t scan_type; /* enum */ ++ int32 channel_num; ++ chan_scandata_t channel_list[1]; /* list of chandata structs */ ++} wl_extdscan_params_t; ++ ++#define WL_EXTDSCAN_PARAMS_FIXED_SIZE (sizeof(wl_extdscan_params_t) - sizeof(chan_scandata_t)) ++ ++#define WL_BSSTYPE_INFRA 1 ++#define WL_BSSTYPE_INDEP 0 ++#define WL_BSSTYPE_ANY 2 ++ ++/* Bitmask for scan_type */ ++#define WL_SCANFLAGS_PASSIVE 0x01 /* force passive scan */ ++#define WL_SCANFLAGS_RESERVED 0x02 /* Reserved */ ++#define WL_SCANFLAGS_PROHIBITED 0x04 /* allow scanning prohibited channels */ ++ ++#define WL_SCAN_PARAMS_SSID_MAX 10 ++ ++typedef struct wl_scan_params { ++ wlc_ssid_t ssid; /* default: {0, ""} */ ++ struct ether_addr bssid; /* default: bcast */ ++ int8 bss_type; /* default: any, ++ * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT ++ */ ++ uint8 scan_type; /* flags, 0 use default */ ++ int32 nprobes; /* -1 use default, number of probes per channel */ ++ int32 active_time; /* -1 use default, dwell time per channel for ++ * active scanning ++ */ ++ int32 passive_time; /* -1 use default, dwell time per channel ++ * for passive scanning ++ */ ++ int32 home_time; /* -1 use default, dwell time for the home channel ++ * between channel scans ++ */ ++ int32 channel_num; /* count of channels and ssids that follow ++ * ++ * low half is count of channels in channel_list, 0 ++ * means default (use all available channels) ++ * ++ * high half is entries in wlc_ssid_t array that ++ * follows channel_list, aligned for int32 (4 bytes) ++ * meaning an odd channel count implies a 2-byte pad ++ * between end of channel_list and first ssid ++ * ++ * if ssid count is zero, single ssid in the fixed ++ * parameter portion is assumed, otherwise ssid in ++ * the fixed portion is ignored ++ */ ++ uint16 channel_list[1]; /* list of chanspecs */ ++} wl_scan_params_t; ++ ++/* size of wl_scan_params not including variable length array */ ++#define WL_SCAN_PARAMS_FIXED_SIZE 64 ++ ++/* masks for channel and ssid count */ ++#define WL_SCAN_PARAMS_COUNT_MASK 0x0000ffff ++#define WL_SCAN_PARAMS_NSSID_SHIFT 16 ++ ++#define WL_SCAN_ACTION_START 1 ++#define WL_SCAN_ACTION_CONTINUE 2 ++#define WL_SCAN_ACTION_ABORT 3 ++ ++#define ISCAN_REQ_VERSION 1 ++ ++/* incremental scan struct */ ++typedef struct wl_iscan_params { ++ uint32 version; ++ uint16 action; ++ uint16 scan_duration; ++ wl_scan_params_t params; ++} wl_iscan_params_t; ++ ++/* 3 fields + size of wl_scan_params, not including variable length array */ ++#define WL_ISCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_iscan_params_t, params) + sizeof(wlc_ssid_t)) ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++typedef struct wl_scan_results { ++ uint32 buflen; ++ uint32 version; ++ uint32 count; ++ wl_bss_info_t bss_info[1]; ++} wl_scan_results_t; ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* size of wl_scan_results not including variable length array */ ++#define WL_SCAN_RESULTS_FIXED_SIZE (sizeof(wl_scan_results_t) - sizeof(wl_bss_info_t)) ++ ++/* wl_iscan_results status values */ ++#define WL_SCAN_RESULTS_SUCCESS 0 ++#define WL_SCAN_RESULTS_PARTIAL 1 ++#define WL_SCAN_RESULTS_PENDING 2 ++#define WL_SCAN_RESULTS_ABORTED 3 ++#define WL_SCAN_RESULTS_NO_MEM 4 ++ ++/* Used in EXT_STA */ ++#define DNGL_RXCTXT_SIZE 45 ++ ++ ++#define ESCAN_REQ_VERSION 1 ++ ++typedef struct wl_escan_params { ++ uint32 version; ++ uint16 action; ++ uint16 sync_id; ++ wl_scan_params_t params; ++} wl_escan_params_t; ++ ++#define WL_ESCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_escan_params_t, params) + sizeof(wlc_ssid_t)) ++ ++typedef struct wl_escan_result { ++ uint32 buflen; ++ uint32 version; ++ uint16 sync_id; ++ uint16 bss_count; ++ wl_bss_info_t bss_info[1]; ++} wl_escan_result_t; ++ ++#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(wl_escan_result_t) - sizeof(wl_bss_info_t)) ++ ++/* incremental scan results struct */ ++typedef struct wl_iscan_results { ++ uint32 status; ++ wl_scan_results_t results; ++} wl_iscan_results_t; ++ ++/* size of wl_iscan_results not including variable length array */ ++#define WL_ISCAN_RESULTS_FIXED_SIZE \ ++ (WL_SCAN_RESULTS_FIXED_SIZE + OFFSETOF(wl_iscan_results_t, results)) ++ ++typedef struct wl_probe_params { ++ wlc_ssid_t ssid; ++ struct ether_addr bssid; ++ struct ether_addr mac; ++} wl_probe_params_t; ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++#define WL_MAXRATES_IN_SET 16 /* max # of rates in a rateset */ ++typedef struct wl_rateset { ++ uint32 count; /* # rates in this set */ ++ uint8 rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */ ++} wl_rateset_t; ++ ++typedef struct wl_rateset_args { ++ uint32 count; /* # rates in this set */ ++ uint8 rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */ ++ uint8 mcs[MCSSET_LEN]; /* supported mcs index bit map */ ++} wl_rateset_args_t; ++ ++/* uint32 list */ ++typedef struct wl_uint32_list { ++ /* in - # of elements, out - # of entries */ ++ uint32 count; ++ /* variable length uint32 list */ ++ uint32 element[1]; ++} wl_uint32_list_t; ++ ++/* used for association with a specific BSSID and chanspec list */ ++typedef struct wl_assoc_params { ++ struct ether_addr bssid; /* 00:00:00:00:00:00: broadcast scan */ ++ uint16 bssid_cnt; /* 0: use chanspec_num, and the single bssid, ++ * otherwise count of chanspecs in chanspec_list ++ * AND paired bssids following chanspec_list ++ */ ++ int32 chanspec_num; /* 0: all available channels, ++ * otherwise count of chanspecs in chanspec_list ++ */ ++ chanspec_t chanspec_list[1]; /* list of chanspecs */ ++} wl_assoc_params_t; ++#define WL_ASSOC_PARAMS_FIXED_SIZE OFFSETOF(wl_assoc_params_t, chanspec_list) ++ ++/* used for reassociation/roam to a specific BSSID and channel */ ++typedef wl_assoc_params_t wl_reassoc_params_t; ++#define WL_REASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE ++ ++/* used for association to a specific BSSID and channel */ ++typedef wl_assoc_params_t wl_join_assoc_params_t; ++#define WL_JOIN_ASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE ++ ++/* used for join with or without a specific bssid and channel list */ ++typedef struct wl_join_params { ++ wlc_ssid_t ssid; ++ wl_assoc_params_t params; /* optional field, but it must include the fixed portion ++ * of the wl_assoc_params_t struct when it does present. ++ */ ++} wl_join_params_t; ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++#define WL_JOIN_PARAMS_FIXED_SIZE (OFFSETOF(wl_join_params_t, params) + \ ++ WL_ASSOC_PARAMS_FIXED_SIZE) ++/* scan params for extended join */ ++typedef struct wl_join_scan_params { ++ uint8 scan_type; /* 0 use default, active or passive scan */ ++ int32 nprobes; /* -1 use default, number of probes per channel */ ++ int32 active_time; /* -1 use default, dwell time per channel for ++ * active scanning ++ */ ++ int32 passive_time; /* -1 use default, dwell time per channel ++ * for passive scanning ++ */ ++ int32 home_time; /* -1 use default, dwell time for the home channel ++ * between channel scans ++ */ ++} wl_join_scan_params_t; ++ ++/* extended join params */ ++typedef struct wl_extjoin_params { ++ wlc_ssid_t ssid; /* {0, ""}: wildcard scan */ ++ wl_join_scan_params_t scan; ++ wl_join_assoc_params_t assoc; /* optional field, but it must include the fixed portion ++ * of the wl_join_assoc_params_t struct when it does ++ * present. ++ */ ++} wl_extjoin_params_t; ++#define WL_EXTJOIN_PARAMS_FIXED_SIZE (OFFSETOF(wl_extjoin_params_t, assoc) + \ ++ WL_JOIN_ASSOC_PARAMS_FIXED_SIZE) ++ ++/* All builds use the new 11ac ratespec/chanspec */ ++#undef D11AC_IOTYPES ++#define D11AC_IOTYPES ++ ++#ifndef D11AC_IOTYPES ++ ++/* defines used by the nrate iovar */ ++#define NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */ ++#define NRATE_RATE_MASK 0x0000007f /* rate/mcs value */ ++#define NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */ ++#define NRATE_STF_SHIFT 8 /* stf mode shift */ ++#define NRATE_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */ ++#define NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */ ++#define NRATE_SGI_MASK 0x00800000 /* sgi mode */ ++#define NRATE_SGI_SHIFT 23 /* sgi mode */ ++#define NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */ ++#define NRATE_LDPC_SHIFT 22 /* ldpc shift */ ++ ++#define NRATE_STF_SISO 0 /* stf mode SISO */ ++#define NRATE_STF_CDD 1 /* stf mode CDD */ ++#define NRATE_STF_STBC 2 /* stf mode STBC */ ++#define NRATE_STF_SDM 3 /* stf mode SDM */ ++ ++#else /* D11AC_IOTYPES */ ++ ++/* WL_RSPEC defines for rate information */ ++#define WL_RSPEC_RATE_MASK 0x000000FF /* rate or HT MCS value */ ++#define WL_RSPEC_VHT_MCS_MASK 0x0000000F /* VHT MCS value */ ++#define WL_RSPEC_VHT_NSS_MASK 0x000000F0 /* VHT Nss value */ ++#define WL_RSPEC_VHT_NSS_SHIFT 4 /* VHT Nss value shift */ ++#define WL_RSPEC_TXEXP_MASK 0x00000300 ++#define WL_RSPEC_TXEXP_SHIFT 8 ++#define WL_RSPEC_BW_MASK 0x00070000 /* bandwidth mask */ ++#define WL_RSPEC_BW_SHIFT 16 /* bandwidth shift */ ++#define WL_RSPEC_STBC 0x00100000 /* STBC encoding, Nsts = 2 x Nss */ ++#define WL_RSPEC_LDPC 0x00400000 /* bit indicates adv coding in use */ ++#define WL_RSPEC_SGI 0x00800000 /* Short GI mode */ ++#define WL_RSPEC_ENCODING_MASK 0x03000000 /* Encoding of Rate/MCS field */ ++#define WL_RSPEC_OVERRIDE_RATE 0x40000000 /* bit indicate to override mcs only */ ++#define WL_RSPEC_OVERRIDE_MODE 0x80000000 /* bit indicates override both rate & mode */ ++ ++/* WL_RSPEC_ENCODING field defs */ ++#define WL_RSPEC_ENCODE_RATE 0x00000000 /* Legacy rate is stored in RSPEC_RATE_MASK */ ++#define WL_RSPEC_ENCODE_HT 0x01000000 /* HT MCS is stored in RSPEC_RATE_MASK */ ++#define WL_RSPEC_ENCODE_VHT 0x02000000 /* VHT MCS and Nss is stored in RSPEC_RATE_MASK */ ++ ++/* WL_RSPEC_BW field defs */ ++#define WL_RSPEC_BW_UNSPECIFIED 0 ++#define WL_RSPEC_BW_20MHZ 0x00010000 ++#define WL_RSPEC_BW_40MHZ 0x00020000 ++#define WL_RSPEC_BW_80MHZ 0x00030000 ++#define WL_RSPEC_BW_160MHZ 0x00040000 ++ ++/* Legacy defines for the nrate iovar */ ++#define OLD_NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */ ++#define OLD_NRATE_RATE_MASK 0x0000007f /* rate/mcs value */ ++#define OLD_NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */ ++#define OLD_NRATE_STF_SHIFT 8 /* stf mode shift */ ++#define OLD_NRATE_OVERRIDE 0x80000000 /* bit indicates override both rate & mode */ ++#define OLD_NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */ ++#define OLD_NRATE_SGI 0x00800000 /* sgi mode */ ++#define OLD_NRATE_LDPC_CODING 0x00400000 /* bit indicates adv coding in use */ ++ ++#define OLD_NRATE_STF_SISO 0 /* stf mode SISO */ ++#define OLD_NRATE_STF_CDD 1 /* stf mode CDD */ ++#define OLD_NRATE_STF_STBC 2 /* stf mode STBC */ ++#define OLD_NRATE_STF_SDM 3 /* stf mode SDM */ ++ ++#endif /* D11AC_IOTYPES */ ++ ++#define ANTENNA_NUM_1 1 /* total number of antennas to be used */ ++#define ANTENNA_NUM_2 2 ++#define ANTENNA_NUM_3 3 ++#define ANTENNA_NUM_4 4 ++ ++#define ANT_SELCFG_AUTO 0x80 /* bit indicates antenna sel AUTO */ ++#define ANT_SELCFG_MASK 0x33 /* antenna configuration mask */ ++#define ANT_SELCFG_MAX 4 /* max number of antenna configurations */ ++#define ANT_SELCFG_TX_UNICAST 0 /* unicast tx antenna configuration */ ++#define ANT_SELCFG_RX_UNICAST 1 /* unicast rx antenna configuration */ ++#define ANT_SELCFG_TX_DEF 2 /* default tx antenna configuration */ ++#define ANT_SELCFG_RX_DEF 3 /* default rx antenna configuration */ ++ ++#define MAX_STREAMS_SUPPORTED 4 /* max number of streams supported */ ++ ++typedef struct { ++ uint8 ant_config[ANT_SELCFG_MAX]; /* antenna configuration */ ++ uint8 num_antcfg; /* number of available antenna configurations */ ++} wlc_antselcfg_t; ++ ++#define HIGHEST_SINGLE_STREAM_MCS 7 /* MCS values greater than this enable multiple streams */ ++ ++#define MAX_CCA_CHANNELS 38 /* Max number of 20 Mhz wide channels */ ++#define MAX_CCA_SECS 60 /* CCA keeps this many seconds history */ ++ ++#define IBSS_MED 15 /* Mediom in-bss congestion percentage */ ++#define IBSS_HI 25 /* Hi in-bss congestion percentage */ ++#define OBSS_MED 12 ++#define OBSS_HI 25 ++#define INTERFER_MED 5 ++#define INTERFER_HI 10 ++ ++#define CCA_FLAG_2G_ONLY 0x01 /* Return a channel from 2.4 Ghz band */ ++#define CCA_FLAG_5G_ONLY 0x02 /* Return a channel from 2.4 Ghz band */ ++#define CCA_FLAG_IGNORE_DURATION 0x04 /* Ignore dwell time for each channel */ ++#define CCA_FLAGS_PREFER_1_6_11 0x10 ++#define CCA_FLAG_IGNORE_INTERFER 0x20 /* do not exlude channel based on interfer level */ ++ ++#define CCA_ERRNO_BAND 1 /* After filtering for band pref, no choices left */ ++#define CCA_ERRNO_DURATION 2 /* After filtering for duration, no choices left */ ++#define CCA_ERRNO_PREF_CHAN 3 /* After filtering for chan pref, no choices left */ ++#define CCA_ERRNO_INTERFER 4 /* After filtering for interference, no choices left */ ++#define CCA_ERRNO_TOO_FEW 5 /* Only 1 channel was input */ ++ ++typedef struct { ++ uint32 duration; /* millisecs spent sampling this channel */ ++ uint32 congest_ibss; /* millisecs in our bss (presumably this traffic will */ ++ /* move if cur bss moves channels) */ ++ uint32 congest_obss; /* traffic not in our bss */ ++ uint32 interference; /* millisecs detecting a non 802.11 interferer. */ ++ uint32 timestamp; /* second timestamp */ ++} cca_congest_t; ++ ++typedef struct { ++ chanspec_t chanspec; /* Which channel? */ ++ uint8 num_secs; /* How many secs worth of data */ ++ cca_congest_t secs[1]; /* Data */ ++} cca_congest_channel_req_t; ++ ++/* interference source detection and identification mode */ ++#define ITFR_MODE_DISABLE 0 /* disable feature */ ++#define ITFR_MODE_MANUAL_ENABLE 1 /* enable manual detection */ ++#define ITFR_MODE_AUTO_ENABLE 2 /* enable auto detection */ ++ ++/* interference sources */ ++enum interference_source { ++ ITFR_NONE = 0, /* interference */ ++ ITFR_PHONE, /* wireless phone */ ++ ITFR_VIDEO_CAMERA, /* wireless video camera */ ++ ITFR_MICROWAVE_OVEN, /* microwave oven */ ++ ITFR_BABY_MONITOR, /* wireless baby monitor */ ++ ITFR_BLUETOOTH, /* bluetooth */ ++ ITFR_VIDEO_CAMERA_OR_BABY_MONITOR, /* wireless camera or baby monitor */ ++ ITFR_BLUETOOTH_OR_BABY_MONITOR, /* bluetooth or baby monitor */ ++ ITFR_VIDEO_CAMERA_OR_PHONE, /* video camera or phone */ ++ ITFR_UNIDENTIFIED /* interference from unidentified source */ ++}; ++ ++/* structure for interference source report */ ++typedef struct { ++ uint32 flags; /* flags. bit definitions below */ ++ uint32 source; /* last detected interference source */ ++ uint32 timestamp; /* second timestamp on interferenced flag change */ ++} interference_source_rep_t; ++ ++/* bit definitions for flags in interference source report */ ++#define ITFR_INTERFERENCED 1 /* interference detected */ ++#define ITFR_HOME_CHANNEL 2 /* home channel has interference */ ++#define ITFR_NOISY_ENVIRONMENT 4 /* noisy environemnt so feature stopped */ ++ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++#define WLC_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NUL */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++ ++typedef struct wl_country { ++ char country_abbrev[WLC_CNTRY_BUF_SZ]; /* nul-terminated country code used in ++ * the Country IE ++ */ ++ int32 rev; /* revision specifier for ccode ++ * on set, -1 indicates unspecified. ++ * on get, rev >= 0 ++ */ ++ char ccode[WLC_CNTRY_BUF_SZ]; /* nul-terminated built-in country code. ++ * variable length, but fixed size in ++ * struct allows simple allocation for ++ * expected country strings <= 3 chars. ++ */ ++} wl_country_t; ++ ++typedef struct wl_channels_in_country { ++ uint32 buflen; ++ uint32 band; ++ char country_abbrev[WLC_CNTRY_BUF_SZ]; ++ uint32 count; ++ uint32 channel[1]; ++} wl_channels_in_country_t; ++ ++typedef struct wl_country_list { ++ uint32 buflen; ++ uint32 band_set; ++ uint32 band; ++ uint32 count; ++ char country_abbrev[1]; ++} wl_country_list_t; ++ ++#define WL_NUM_RPI_BINS 8 ++#define WL_RM_TYPE_BASIC 1 ++#define WL_RM_TYPE_CCA 2 ++#define WL_RM_TYPE_RPI 3 ++ ++#define WL_RM_FLAG_PARALLEL (1<<0) ++ ++#define WL_RM_FLAG_LATE (1<<1) ++#define WL_RM_FLAG_INCAPABLE (1<<2) ++#define WL_RM_FLAG_REFUSED (1<<3) ++ ++typedef struct wl_rm_req_elt { ++ int8 type; ++ int8 flags; ++ chanspec_t chanspec; ++ uint32 token; /* token for this measurement */ ++ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */ ++ uint32 tsf_l; /* TSF low 32-bits */ ++ uint32 dur; /* TUs */ ++} wl_rm_req_elt_t; ++ ++typedef struct wl_rm_req { ++ uint32 token; /* overall measurement set token */ ++ uint32 count; /* number of measurement requests */ ++ void *cb; /* completion callback function: may be NULL */ ++ void *cb_arg; /* arg to completion callback function */ ++ wl_rm_req_elt_t req[1]; /* variable length block of requests */ ++} wl_rm_req_t; ++#define WL_RM_REQ_FIXED_LEN OFFSETOF(wl_rm_req_t, req) ++ ++typedef struct wl_rm_rep_elt { ++ int8 type; ++ int8 flags; ++ chanspec_t chanspec; ++ uint32 token; /* token for this measurement */ ++ uint32 tsf_h; /* TSF high 32-bits of Measurement start time */ ++ uint32 tsf_l; /* TSF low 32-bits */ ++ uint32 dur; /* TUs */ ++ uint32 len; /* byte length of data block */ ++ uint8 data[1]; /* variable length data block */ ++} wl_rm_rep_elt_t; ++#define WL_RM_REP_ELT_FIXED_LEN 24 /* length excluding data block */ ++ ++#define WL_RPI_REP_BIN_NUM 8 ++typedef struct wl_rm_rpi_rep { ++ uint8 rpi[WL_RPI_REP_BIN_NUM]; ++ int8 rpi_max[WL_RPI_REP_BIN_NUM]; ++} wl_rm_rpi_rep_t; ++ ++typedef struct wl_rm_rep { ++ uint32 token; /* overall measurement set token */ ++ uint32 len; /* length of measurement report block */ ++ wl_rm_rep_elt_t rep[1]; /* variable length block of reports */ ++} wl_rm_rep_t; ++#define WL_RM_REP_FIXED_LEN 8 ++ ++ ++typedef enum sup_auth_status { ++ /* Basic supplicant authentication states */ ++ WLC_SUP_DISCONNECTED = 0, ++ WLC_SUP_CONNECTING, ++ WLC_SUP_IDREQUIRED, ++ WLC_SUP_AUTHENTICATING, ++ WLC_SUP_AUTHENTICATED, ++ WLC_SUP_KEYXCHANGE, ++ WLC_SUP_KEYED, ++ WLC_SUP_TIMEOUT, ++ WLC_SUP_LAST_BASIC_STATE, ++ ++ /* Extended supplicant authentication states */ ++ /* Waiting to receive handshake msg M1 */ ++ WLC_SUP_KEYXCHANGE_WAIT_M1 = WLC_SUP_AUTHENTICATED, ++ /* Preparing to send handshake msg M2 */ ++ WLC_SUP_KEYXCHANGE_PREP_M2 = WLC_SUP_KEYXCHANGE, ++ /* Waiting to receive handshake msg M3 */ ++ WLC_SUP_KEYXCHANGE_WAIT_M3 = WLC_SUP_LAST_BASIC_STATE, ++ WLC_SUP_KEYXCHANGE_PREP_M4, /* Preparing to send handshake msg M4 */ ++ WLC_SUP_KEYXCHANGE_WAIT_G1, /* Waiting to receive handshake msg G1 */ ++ WLC_SUP_KEYXCHANGE_PREP_G2 /* Preparing to send handshake msg G2 */ ++} sup_auth_status_t; ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* Enumerate crypto algorithms */ ++#define CRYPTO_ALGO_OFF 0 ++#define CRYPTO_ALGO_WEP1 1 ++#define CRYPTO_ALGO_TKIP 2 ++#define CRYPTO_ALGO_WEP128 3 ++#define CRYPTO_ALGO_AES_CCM 4 ++#define CRYPTO_ALGO_AES_OCB_MSDU 5 ++#define CRYPTO_ALGO_AES_OCB_MPDU 6 ++#if !defined(BCMEXTCCX) ++#define CRYPTO_ALGO_NALG 7 ++#else ++#define CRYPTO_ALGO_CKIP 7 ++#define CRYPTO_ALGO_CKIP_MMH 8 ++#define CRYPTO_ALGO_WEP_MMH 9 ++#define CRYPTO_ALGO_NALG 10 ++#endif ++#ifdef BCMWAPI_WPI ++#define CRYPTO_ALGO_SMS4 11 ++#endif /* BCMWAPI_WPI */ ++#define CRYPTO_ALGO_PMK 12 /* for 802.1x supp to set PMK before 4-way */ ++ ++#define WSEC_GEN_MIC_ERROR 0x0001 ++#define WSEC_GEN_REPLAY 0x0002 ++#define WSEC_GEN_ICV_ERROR 0x0004 ++#define WSEC_GEN_MFP_ACT_ERROR 0x0008 ++#define WSEC_GEN_MFP_DISASSOC_ERROR 0x0010 ++#define WSEC_GEN_MFP_DEAUTH_ERROR 0x0020 ++ ++#define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */ ++#define WL_PRIMARY_KEY (1 << 1) /* Indicates this key is the primary (ie tx) key */ ++#if defined(BCMEXTCCX) ++#define WL_CKIP_KP (1 << 4) /* CMIC */ ++#define WL_CKIP_MMH (1 << 5) /* CKIP */ ++#else ++#define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */ ++#define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */ ++#endif ++#define WL_IBSS_PEER_GROUP_KEY (1 << 6) /* Indicates a group key for a IBSS PEER */ ++ ++typedef struct wl_wsec_key { ++ uint32 index; /* key index */ ++ uint32 len; /* key length */ ++ uint8 data[DOT11_MAX_KEY_SIZE]; /* key data */ ++ uint32 pad_1[18]; ++ uint32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ ++ uint32 flags; /* misc flags */ ++ uint32 pad_2[2]; ++ int pad_3; ++ int iv_initialized; /* has IV been initialized already? */ ++ int pad_4; ++ /* Rx IV */ ++ struct { ++ uint32 hi; /* upper 32 bits of IV */ ++ uint16 lo; /* lower 16 bits of IV */ ++ } rxiv; ++ uint32 pad_5[2]; ++ struct ether_addr ea; /* per station */ ++} wl_wsec_key_t; ++ ++#define WSEC_MIN_PSK_LEN 8 ++#define WSEC_MAX_PSK_LEN 64 ++ ++/* Flag for key material needing passhash'ing */ ++#define WSEC_PASSPHRASE (1<<0) ++ ++/* receptacle for WLC_SET_WSEC_PMK parameter */ ++typedef struct { ++ ushort key_len; /* octets in key material */ ++ ushort flags; /* key handling qualification */ ++ uint8 key[WSEC_MAX_PSK_LEN]; /* PMK material */ ++} wsec_pmk_t; ++ ++/* wireless security bitvec */ ++#define WEP_ENABLED 0x0001 ++#define TKIP_ENABLED 0x0002 ++#define AES_ENABLED 0x0004 ++#define WSEC_SWFLAG 0x0008 ++#define SES_OW_ENABLED 0x0040 /* to go into transition mode without setting wep */ ++ ++/* wsec macros for operating on the above definitions */ ++#define WSEC_WEP_ENABLED(wsec) ((wsec) & WEP_ENABLED) ++#define WSEC_TKIP_ENABLED(wsec) ((wsec) & TKIP_ENABLED) ++#define WSEC_AES_ENABLED(wsec) ((wsec) & AES_ENABLED) ++ ++#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)) ++#define WSEC_SES_OW_ENABLED(wsec) ((wsec) & SES_OW_ENABLED) ++#ifdef BCMWAPI_WPI ++#define SMS4_ENABLED 0x0100 ++#endif /* BCMWAPI_WPI */ ++ ++#ifdef MFP ++#define MFP_CAPABLE 0x0200 ++#define MFP_REQUIRED 0x0400 ++#define MFP_SHA256 0x0800 /* a special configuration for STA for WIFI test tool */ ++#endif /* MFP */ ++ ++/* WPA authentication mode bitvec */ ++#define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */ ++#define WPA_AUTH_NONE 0x0001 /* none (IBSS) */ ++#define WPA_AUTH_UNSPECIFIED 0x0002 /* over 802.1x */ ++#define WPA_AUTH_PSK 0x0004 /* Pre-shared key */ ++#if defined(BCMEXTCCX) ++#define WPA_AUTH_CCKM 0x0008 /* CCKM */ ++#define WPA2_AUTH_CCKM 0x0010 /* CCKM2 */ ++#endif ++/* #define WPA_AUTH_8021X 0x0020 */ /* 802.1x, reserved */ ++#define WPA2_AUTH_UNSPECIFIED 0x0040 /* over 802.1x */ ++#define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */ ++#define BRCM_AUTH_PSK 0x0100 /* BRCM specific PSK */ ++#define BRCM_AUTH_DPT 0x0200 /* DPT PSK without group keys */ ++#ifdef BCMWAPI_WAI ++#define WPA_AUTH_WAPI 0x0400 ++#define WAPI_AUTH_NONE WPA_AUTH_NONE /* none (IBSS) */ ++#define WAPI_AUTH_UNSPECIFIED 0x0400 /* over AS */ ++#define WAPI_AUTH_PSK 0x0800 /* Pre-shared key */ ++#endif /* BCMWAPI_WAI */ ++#define WPA2_AUTH_MFP 0x1000 /* MFP (11w) in contrast to CCX */ ++#define WPA2_AUTH_TPK 0x2000 /* TDLS Peer Key */ ++#define WPA2_AUTH_FT 0x4000 /* Fast Transition. */ ++#define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */ ++ ++/* pmkid */ ++#define MAXPMKID 16 ++ ++typedef struct _pmkid { ++ struct ether_addr BSSID; ++ uint8 PMKID[WPA2_PMKID_LEN]; ++} pmkid_t; ++ ++typedef struct _pmkid_list { ++ uint32 npmkid; ++ pmkid_t pmkid[1]; ++} pmkid_list_t; ++ ++typedef struct _pmkid_cand { ++ struct ether_addr BSSID; ++ uint8 preauth; ++} pmkid_cand_t; ++ ++typedef struct _pmkid_cand_list { ++ uint32 npmkid_cand; ++ pmkid_cand_t pmkid_cand[1]; ++} pmkid_cand_list_t; ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++typedef struct wl_assoc_info { ++ uint32 req_len; ++ uint32 resp_len; ++ uint32 flags; ++ struct dot11_assoc_req req; ++ struct ether_addr reassoc_bssid; /* used in reassoc's */ ++ struct dot11_assoc_resp resp; ++} wl_assoc_info_t; ++ ++/* flags */ ++#define WLC_ASSOC_REQ_IS_REASSOC 0x01 /* assoc req was actually a reassoc */ ++ ++typedef struct wl_led_info { ++ uint32 index; /* led index */ ++ uint32 behavior; ++ uint8 activehi; ++} wl_led_info_t; ++ ++ ++/* srom read/write struct passed through ioctl */ ++typedef struct { ++ uint byteoff; /* byte offset */ ++ uint nbytes; /* number of bytes */ ++ uint16 buf[1]; ++} srom_rw_t; ++ ++/* similar cis (srom or otp) struct [iovar: may not be aligned] */ ++typedef struct { ++ uint32 source; /* cis source */ ++ uint32 byteoff; /* byte offset */ ++ uint32 nbytes; /* number of bytes */ ++ /* data follows here */ ++} cis_rw_t; ++ ++#define WLC_CIS_DEFAULT 0 /* built-in default */ ++#define WLC_CIS_SROM 1 /* source is sprom */ ++#define WLC_CIS_OTP 2 /* source is otp */ ++ ++/* R_REG and W_REG struct passed through ioctl */ ++typedef struct { ++ uint32 byteoff; /* byte offset of the field in d11regs_t */ ++ uint32 val; /* read/write value of the field */ ++ uint32 size; /* sizeof the field */ ++ uint band; /* band (optional) */ ++} rw_reg_t; ++ ++/* Structure used by GET/SET_ATTEN ioctls - it controls power in b/g-band */ ++/* PCL - Power Control Loop */ ++/* current gain setting is replaced by user input */ ++#define WL_ATTEN_APP_INPUT_PCL_OFF 0 /* turn off PCL, apply supplied input */ ++#define WL_ATTEN_PCL_ON 1 /* turn on PCL */ ++/* current gain setting is maintained */ ++#define WL_ATTEN_PCL_OFF 2 /* turn off PCL. */ ++ ++typedef struct { ++ uint16 auto_ctrl; /* WL_ATTEN_XX */ ++ uint16 bb; /* Baseband attenuation */ ++ uint16 radio; /* Radio attenuation */ ++ uint16 txctl1; /* Radio TX_CTL1 value */ ++} atten_t; ++ ++/* Per-AC retry parameters */ ++struct wme_tx_params_s { ++ uint8 short_retry; ++ uint8 short_fallback; ++ uint8 long_retry; ++ uint8 long_fallback; ++ uint16 max_rate; /* In units of 512 Kbps */ ++}; ++ ++typedef struct wme_tx_params_s wme_tx_params_t; ++ ++#define WL_WME_TX_PARAMS_IO_BYTES (sizeof(wme_tx_params_t) * AC_COUNT) ++ ++/* defines used by poweridx iovar - it controls power in a-band */ ++/* current gain setting is maintained */ ++#define WL_PWRIDX_PCL_OFF -2 /* turn off PCL. */ ++#define WL_PWRIDX_PCL_ON -1 /* turn on PCL */ ++#define WL_PWRIDX_LOWER_LIMIT -2 /* lower limit */ ++#define WL_PWRIDX_UPPER_LIMIT 63 /* upper limit */ ++/* value >= 0 causes ++ * - input to be set to that value ++ * - PCL to be off ++ */ ++ ++/* Used to get specific link/ac parameters */ ++typedef struct { ++ int ac; ++ uint8 val; ++ struct ether_addr ea; ++} link_val_t; ++ ++#define BCM_MAC_STATUS_INDICATION (0x40010200L) ++ ++typedef struct { ++ uint16 ver; /* version of this struct */ ++ uint16 len; /* length in bytes of this structure */ ++ uint16 cap; /* sta's advertised capabilities */ ++ uint32 flags; /* flags defined below */ ++ uint32 idle; /* time since data pkt rx'd from sta */ ++ struct ether_addr ea; /* Station address */ ++ wl_rateset_t rateset; /* rateset in use */ ++ uint32 in; /* seconds elapsed since associated */ ++ uint32 listen_interval_inms; /* Min Listen interval in ms for this STA */ ++ uint32 tx_pkts; /* # of packets transmitted */ ++ uint32 tx_failures; /* # of packets failed */ ++ uint32 rx_ucast_pkts; /* # of unicast packets received */ ++ uint32 rx_mcast_pkts; /* # of multicast packets received */ ++ uint32 tx_rate; /* Rate of last successful tx frame */ ++ uint32 rx_rate; /* Rate of last successful rx frame */ ++ uint32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ ++ uint32 rx_decrypt_failures; /* # of packet decrypted unsuccessfully */ ++} sta_info_t; ++ ++#define WL_OLD_STAINFO_SIZE OFFSETOF(sta_info_t, tx_pkts) ++ ++#define WL_STA_VER 3 ++ ++/* Flags for sta_info_t indicating properties of STA */ ++#define WL_STA_BRCM 0x1 /* Running a Broadcom driver */ ++#define WL_STA_WME 0x2 /* WMM association */ ++#define WL_STA_UNUSED 0x4 ++#define WL_STA_AUTHE 0x8 /* Authenticated */ ++#define WL_STA_ASSOC 0x10 /* Associated */ ++#define WL_STA_AUTHO 0x20 /* Authorized */ ++#define WL_STA_WDS 0x40 /* Wireless Distribution System */ ++#define WL_STA_WDS_LINKUP 0x80 /* WDS traffic/probes flowing properly */ ++#define WL_STA_PS 0x100 /* STA is in power save mode from AP's viewpoint */ ++#define WL_STA_APSD_BE 0x200 /* APSD delv/trigger for AC_BE is default enabled */ ++#define WL_STA_APSD_BK 0x400 /* APSD delv/trigger for AC_BK is default enabled */ ++#define WL_STA_APSD_VI 0x800 /* APSD delv/trigger for AC_VI is default enabled */ ++#define WL_STA_APSD_VO 0x1000 /* APSD delv/trigger for AC_VO is default enabled */ ++#define WL_STA_N_CAP 0x2000 /* STA 802.11n capable */ ++#define WL_STA_SCBSTATS 0x4000 /* Per STA debug stats */ ++ ++#define WL_WDS_LINKUP WL_STA_WDS_LINKUP /* deprecated */ ++ ++/* Values for TX Filter override mode */ ++#define WLC_TXFILTER_OVERRIDE_DISABLED 0 ++#define WLC_TXFILTER_OVERRIDE_ENABLED 1 ++ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* Used to get specific STA parameters */ ++typedef struct { ++ uint32 val; ++ struct ether_addr ea; ++} scb_val_t; ++ ++/* Used by iovar versions of some ioctls, i.e. WLC_SCB_AUTHORIZE et al */ ++typedef struct { ++ uint32 code; ++ scb_val_t ioctl_args; ++} authops_t; ++ ++/* channel encoding */ ++typedef struct channel_info { ++ int hw_channel; ++ int target_channel; ++ int scan_channel; ++} channel_info_t; ++ ++/* For ioctls that take a list of MAC addresses */ ++struct maclist { ++ uint count; /* number of MAC addresses */ ++ struct ether_addr ea[1]; /* variable length array of MAC addresses */ ++}; ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* get pkt count struct passed through ioctl */ ++typedef struct get_pktcnt { ++ uint rx_good_pkt; ++ uint rx_bad_pkt; ++ uint tx_good_pkt; ++ uint tx_bad_pkt; ++ uint rx_ocast_good_pkt; /* unicast packets destined for others */ ++} get_pktcnt_t; ++ ++/* NINTENDO2 */ ++#define LQ_IDX_MIN 0 ++#define LQ_IDX_MAX 1 ++#define LQ_IDX_AVG 2 ++#define LQ_IDX_SUM 2 ++#define LQ_IDX_LAST 3 ++#define LQ_STOP_MONITOR 0 ++#define LQ_START_MONITOR 1 ++ ++/* Get averages RSSI, Rx PHY rate and SNR values */ ++typedef struct { ++ int rssi[LQ_IDX_LAST]; /* Array to keep min, max, avg rssi */ ++ int snr[LQ_IDX_LAST]; /* Array to keep min, max, avg snr */ ++ int isvalid; /* Flag indicating whether above data is valid */ ++} wl_lq_t; /* Link Quality */ ++ ++typedef enum wl_wakeup_reason_type { ++ LCD_ON = 1, ++ LCD_OFF, ++ DRC1_WAKE, ++ DRC2_WAKE, ++ REASON_LAST ++} wl_wr_type_t; ++ ++typedef struct { ++/* Unique filter id */ ++ uint32 id; ++ ++/* stores the reason for the last wake up */ ++ uint8 reason; ++} wl_wr_t; ++ ++/* Get MAC specific rate histogram command */ ++typedef struct { ++ struct ether_addr ea; /* MAC Address */ ++ uint8 ac_cat; /* Access Category */ ++ uint8 num_pkts; /* Number of packet entries to be averaged */ ++} wl_mac_ratehisto_cmd_t; /* MAC Specific Rate Histogram command */ ++ ++/* Get MAC rate histogram response */ ++typedef struct { ++ uint32 rate[WLC_MAXRATE + 1]; /* Rates */ ++ uint32 mcs[WL_RATESET_SZ_HT_MCS * WL_TX_CHAINS_MAX]; /* MCS counts */ ++ uint32 vht[WL_RATESET_SZ_VHT_MCS][WL_TX_CHAINS_MAX]; /* VHT counts */ ++ uint32 tsf_timer[2][2]; /* Start and End time for 8bytes value */ ++} wl_mac_ratehisto_res_t; /* MAC Specific Rate Histogram Response */ ++ ++/* Values for TX Filter override mode */ ++#define WLC_TXFILTER_OVERRIDE_DISABLED 0 ++#define WLC_TXFILTER_OVERRIDE_ENABLED 1 ++ ++#define WL_IOCTL_ACTION_GET 0x0 ++#define WL_IOCTL_ACTION_SET 0x1 ++#define WL_IOCTL_ACTION_OVL_IDX_MASK 0x1e ++#define WL_IOCTL_ACTION_OVL_RSV 0x20 ++#define WL_IOCTL_ACTION_OVL 0x40 ++#define WL_IOCTL_ACTION_MASK 0x7e ++#define WL_IOCTL_ACTION_OVL_SHIFT 1 ++ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* Linux network driver ioctl encoding */ ++typedef struct wl_ioctl { ++ uint cmd; /* common ioctl definition */ ++ void *buf; /* pointer to user buffer */ ++ uint len; /* length of user buffer */ ++ uint8 set; /* 1=set IOCTL; 0=query IOCTL */ ++ uint used; /* bytes read or written (optional) */ ++ uint needed; /* bytes needed (optional) */ ++} wl_ioctl_t; ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++ ++/* reference to wl_ioctl_t struct used by usermode driver */ ++#define ioctl_subtype set /* subtype param */ ++#define ioctl_pid used /* pid param */ ++#define ioctl_status needed /* status param */ ++ ++/* ++ * Structure for passing hardware and software ++ * revision info up from the driver. ++ */ ++typedef struct wlc_rev_info { ++ uint vendorid; /* PCI vendor id */ ++ uint deviceid; /* device id of chip */ ++ uint radiorev; /* radio revision */ ++ uint chiprev; /* chip revision */ ++ uint corerev; /* core revision */ ++ uint boardid; /* board identifier (usu. PCI sub-device id) */ ++ uint boardvendor; /* board vendor (usu. PCI sub-vendor id) */ ++ uint boardrev; /* board revision */ ++ uint driverrev; /* driver version */ ++ uint ucoderev; /* microcode version */ ++ uint bus; /* bus type */ ++ uint chipnum; /* chip number */ ++ uint phytype; /* phy type */ ++ uint phyrev; /* phy revision */ ++ uint anarev; /* anacore rev */ ++ uint chippkg; /* chip package info */ ++} wlc_rev_info_t; ++ ++#define WL_REV_INFO_LEGACY_LENGTH 48 ++ ++#define WL_BRAND_MAX 10 ++typedef struct wl_instance_info { ++ uint instance; ++ char brand[WL_BRAND_MAX]; ++} wl_instance_info_t; ++ ++/* structure to change size of tx fifo */ ++typedef struct wl_txfifo_sz { ++ uint16 magic; ++ uint16 fifo; ++ uint16 size; ++} wl_txfifo_sz_t; ++/* magic pattern used for mismatch driver and wl */ ++#define WL_TXFIFO_SZ_MAGIC 0xa5a5 ++ ++/* Transfer info about an IOVar from the driver */ ++/* Max supported IOV name size in bytes, + 1 for nul termination */ ++#define WLC_IOV_NAME_LEN 30 ++typedef struct wlc_iov_trx_s { ++ uint8 module; ++ uint8 type; ++ char name[WLC_IOV_NAME_LEN]; ++} wlc_iov_trx_t; ++ ++/* check this magic number */ ++#define WLC_IOCTL_MAGIC 0x14e46c77 ++ ++/* bump this number if you change the ioctl interface */ ++#ifdef D11AC_IOTYPES ++#define WLC_IOCTL_VERSION 2 ++#define WLC_IOCTL_VERSION_LEGACY_IOTYPES 1 ++#else ++#define WLC_IOCTL_VERSION 1 ++#endif /* D11AC_IOTYPES */ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++#define WLC_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */ ++#define WLC_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */ ++#define WLC_IOCTL_MEDLEN 1536 /* "med" length ioctl buffer required */ ++#if defined(LCNCONF) || defined(LCN40CONF) ++#define WLC_SAMPLECOLLECT_MAXLEN 8192 /* Max Sample Collect buffer */ ++#else ++#define WLC_SAMPLECOLLECT_MAXLEN 10240 /* Max Sample Collect buffer for two cores */ ++#endif ++ ++/* common ioctl definitions */ ++#define WLC_GET_MAGIC 0 ++#define WLC_GET_VERSION 1 ++#define WLC_UP 2 ++#define WLC_DOWN 3 ++#define WLC_GET_LOOP 4 ++#define WLC_SET_LOOP 5 ++#define WLC_DUMP 6 ++#define WLC_GET_MSGLEVEL 7 ++#define WLC_SET_MSGLEVEL 8 ++#define WLC_GET_PROMISC 9 ++#define WLC_SET_PROMISC 10 ++/* #define WLC_OVERLAY_IOCTL 11 */ /* not supported */ ++#define WLC_GET_RATE 12 ++#define WLC_GET_MAX_RATE 13 ++#define WLC_GET_INSTANCE 14 ++/* #define WLC_GET_FRAG 15 */ /* no longer supported */ ++/* #define WLC_SET_FRAG 16 */ /* no longer supported */ ++/* #define WLC_GET_RTS 17 */ /* no longer supported */ ++/* #define WLC_SET_RTS 18 */ /* no longer supported */ ++#define WLC_GET_INFRA 19 ++#define WLC_SET_INFRA 20 ++#define WLC_GET_AUTH 21 ++#define WLC_SET_AUTH 22 ++#define WLC_GET_BSSID 23 ++#define WLC_SET_BSSID 24 ++#define WLC_GET_SSID 25 ++#define WLC_SET_SSID 26 ++#define WLC_RESTART 27 ++#define WLC_TERMINATED 28 ++/* #define WLC_DUMP_SCB 28 */ /* no longer supported */ ++#define WLC_GET_CHANNEL 29 ++#define WLC_SET_CHANNEL 30 ++#define WLC_GET_SRL 31 ++#define WLC_SET_SRL 32 ++#define WLC_GET_LRL 33 ++#define WLC_SET_LRL 34 ++#define WLC_GET_PLCPHDR 35 ++#define WLC_SET_PLCPHDR 36 ++#define WLC_GET_RADIO 37 ++#define WLC_SET_RADIO 38 ++#define WLC_GET_PHYTYPE 39 ++#define WLC_DUMP_RATE 40 ++#define WLC_SET_RATE_PARAMS 41 ++#define WLC_GET_FIXRATE 42 ++#define WLC_SET_FIXRATE 43 ++/* #define WLC_GET_WEP 42 */ /* no longer supported */ ++/* #define WLC_SET_WEP 43 */ /* no longer supported */ ++#define WLC_GET_KEY 44 ++#define WLC_SET_KEY 45 ++#define WLC_GET_REGULATORY 46 ++#define WLC_SET_REGULATORY 47 ++#define WLC_GET_PASSIVE_SCAN 48 ++#define WLC_SET_PASSIVE_SCAN 49 ++#define WLC_SCAN 50 ++#define WLC_SCAN_RESULTS 51 ++#define WLC_DISASSOC 52 ++#define WLC_REASSOC 53 ++#define WLC_GET_ROAM_TRIGGER 54 ++#define WLC_SET_ROAM_TRIGGER 55 ++#define WLC_GET_ROAM_DELTA 56 ++#define WLC_SET_ROAM_DELTA 57 ++#define WLC_GET_ROAM_SCAN_PERIOD 58 ++#define WLC_SET_ROAM_SCAN_PERIOD 59 ++#define WLC_EVM 60 /* diag */ ++#define WLC_GET_TXANT 61 ++#define WLC_SET_TXANT 62 ++#define WLC_GET_ANTDIV 63 ++#define WLC_SET_ANTDIV 64 ++/* #define WLC_GET_TXPWR 65 */ /* no longer supported */ ++/* #define WLC_SET_TXPWR 66 */ /* no longer supported */ ++#define WLC_GET_CLOSED 67 ++#define WLC_SET_CLOSED 68 ++#define WLC_GET_MACLIST 69 ++#define WLC_SET_MACLIST 70 ++#define WLC_GET_RATESET 71 ++#define WLC_SET_RATESET 72 ++/* #define WLC_GET_LOCALE 73 */ /* no longer supported */ ++#define WLC_LONGTRAIN 74 ++#define WLC_GET_BCNPRD 75 ++#define WLC_SET_BCNPRD 76 ++#define WLC_GET_DTIMPRD 77 ++#define WLC_SET_DTIMPRD 78 ++#define WLC_GET_SROM 79 ++#define WLC_SET_SROM 80 ++#define WLC_GET_WEP_RESTRICT 81 ++#define WLC_SET_WEP_RESTRICT 82 ++#define WLC_GET_COUNTRY 83 ++#define WLC_SET_COUNTRY 84 ++#define WLC_GET_PM 85 ++#define WLC_SET_PM 86 ++#define WLC_GET_WAKE 87 ++#define WLC_SET_WAKE 88 ++/* #define WLC_GET_D11CNTS 89 */ /* -> "counters" iovar */ ++#define WLC_GET_FORCELINK 90 /* ndis only */ ++#define WLC_SET_FORCELINK 91 /* ndis only */ ++#define WLC_FREQ_ACCURACY 92 /* diag */ ++#define WLC_CARRIER_SUPPRESS 93 /* diag */ ++#define WLC_GET_PHYREG 94 ++#define WLC_SET_PHYREG 95 ++#define WLC_GET_RADIOREG 96 ++#define WLC_SET_RADIOREG 97 ++#define WLC_GET_REVINFO 98 ++#define WLC_GET_UCANTDIV 99 ++#define WLC_SET_UCANTDIV 100 ++#define WLC_R_REG 101 ++#define WLC_W_REG 102 ++/* #define WLC_DIAG_LOOPBACK 103 old tray diag */ ++/* #define WLC_RESET_D11CNTS 104 */ /* -> "reset_d11cnts" iovar */ ++#define WLC_GET_MACMODE 105 ++#define WLC_SET_MACMODE 106 ++#define WLC_GET_MONITOR 107 ++#define WLC_SET_MONITOR 108 ++#define WLC_GET_GMODE 109 ++#define WLC_SET_GMODE 110 ++#define WLC_GET_LEGACY_ERP 111 ++#define WLC_SET_LEGACY_ERP 112 ++#define WLC_GET_RX_ANT 113 ++#define WLC_GET_CURR_RATESET 114 /* current rateset */ ++#define WLC_GET_SCANSUPPRESS 115 ++#define WLC_SET_SCANSUPPRESS 116 ++#define WLC_GET_AP 117 ++#define WLC_SET_AP 118 ++#define WLC_GET_EAP_RESTRICT 119 ++#define WLC_SET_EAP_RESTRICT 120 ++#define WLC_SCB_AUTHORIZE 121 ++#define WLC_SCB_DEAUTHORIZE 122 ++#define WLC_GET_WDSLIST 123 ++#define WLC_SET_WDSLIST 124 ++#define WLC_GET_ATIM 125 ++#define WLC_SET_ATIM 126 ++#define WLC_GET_RSSI 127 ++#define WLC_GET_PHYANTDIV 128 ++#define WLC_SET_PHYANTDIV 129 ++#define WLC_AP_RX_ONLY 130 ++#define WLC_GET_TX_PATH_PWR 131 ++#define WLC_SET_TX_PATH_PWR 132 ++#define WLC_GET_WSEC 133 ++#define WLC_SET_WSEC 134 ++#define WLC_GET_PHY_NOISE 135 ++#define WLC_GET_BSS_INFO 136 ++#define WLC_GET_PKTCNTS 137 ++#define WLC_GET_LAZYWDS 138 ++#define WLC_SET_LAZYWDS 139 ++#define WLC_GET_BANDLIST 140 ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++#define WLC_GET_BAND 141 ++#define WLC_SET_BAND 142 ++#define WLC_SCB_DEAUTHENTICATE 143 ++#define WLC_GET_SHORTSLOT 144 ++#define WLC_GET_SHORTSLOT_OVERRIDE 145 ++#define WLC_SET_SHORTSLOT_OVERRIDE 146 ++#define WLC_GET_SHORTSLOT_RESTRICT 147 ++#define WLC_SET_SHORTSLOT_RESTRICT 148 ++#define WLC_GET_GMODE_PROTECTION 149 ++#define WLC_GET_GMODE_PROTECTION_OVERRIDE 150 ++#define WLC_SET_GMODE_PROTECTION_OVERRIDE 151 ++#define WLC_UPGRADE 152 ++/* #define WLC_GET_MRATE 153 */ /* no longer supported */ ++/* #define WLC_SET_MRATE 154 */ /* no longer supported */ ++#define WLC_GET_IGNORE_BCNS 155 ++#define WLC_SET_IGNORE_BCNS 156 ++#define WLC_GET_SCB_TIMEOUT 157 ++#define WLC_SET_SCB_TIMEOUT 158 ++#define WLC_GET_ASSOCLIST 159 ++#define WLC_GET_CLK 160 ++#define WLC_SET_CLK 161 ++#define WLC_GET_UP 162 ++#define WLC_OUT 163 ++#define WLC_GET_WPA_AUTH 164 ++#define WLC_SET_WPA_AUTH 165 ++#define WLC_GET_UCFLAGS 166 ++#define WLC_SET_UCFLAGS 167 ++#define WLC_GET_PWRIDX 168 ++#define WLC_SET_PWRIDX 169 ++#define WLC_GET_TSSI 170 ++#define WLC_GET_SUP_RATESET_OVERRIDE 171 ++#define WLC_SET_SUP_RATESET_OVERRIDE 172 ++/* #define WLC_SET_FAST_TIMER 173 */ /* no longer supported */ ++/* #define WLC_GET_FAST_TIMER 174 */ /* no longer supported */ ++/* #define WLC_SET_SLOW_TIMER 175 */ /* no longer supported */ ++/* #define WLC_GET_SLOW_TIMER 176 */ /* no longer supported */ ++/* #define WLC_DUMP_PHYREGS 177 */ /* no longer supported */ ++#define WLC_GET_PROTECTION_CONTROL 178 ++#define WLC_SET_PROTECTION_CONTROL 179 ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++#define WLC_GET_PHYLIST 180 ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++#define WLC_ENCRYPT_STRENGTH 181 /* ndis only */ ++#define WLC_DECRYPT_STATUS 182 /* ndis only */ ++#define WLC_GET_KEY_SEQ 183 ++#define WLC_GET_SCAN_CHANNEL_TIME 184 ++#define WLC_SET_SCAN_CHANNEL_TIME 185 ++#define WLC_GET_SCAN_UNASSOC_TIME 186 ++#define WLC_SET_SCAN_UNASSOC_TIME 187 ++#define WLC_GET_SCAN_HOME_TIME 188 ++#define WLC_SET_SCAN_HOME_TIME 189 ++#define WLC_GET_SCAN_NPROBES 190 ++#define WLC_SET_SCAN_NPROBES 191 ++#define WLC_GET_PRB_RESP_TIMEOUT 192 ++#define WLC_SET_PRB_RESP_TIMEOUT 193 ++#define WLC_GET_ATTEN 194 ++#define WLC_SET_ATTEN 195 ++#define WLC_GET_SHMEM 196 /* diag */ ++#define WLC_SET_SHMEM 197 /* diag */ ++/* #define WLC_GET_GMODE_PROTECTION_CTS 198 */ /* no longer supported */ ++/* #define WLC_SET_GMODE_PROTECTION_CTS 199 */ /* no longer supported */ ++#define WLC_SET_WSEC_TEST 200 ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++#define WLC_SCB_DEAUTHENTICATE_FOR_REASON 201 ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++#define WLC_TKIP_COUNTERMEASURES 202 ++#define WLC_GET_PIOMODE 203 ++#define WLC_SET_PIOMODE 204 ++#define WLC_SET_ASSOC_PREFER 205 ++#define WLC_GET_ASSOC_PREFER 206 ++#define WLC_SET_ROAM_PREFER 207 ++#define WLC_GET_ROAM_PREFER 208 ++#define WLC_SET_LED 209 ++#define WLC_GET_LED 210 ++#define WLC_GET_INTERFERENCE_MODE 211 ++#define WLC_SET_INTERFERENCE_MODE 212 ++#define WLC_GET_CHANNEL_QA 213 ++#define WLC_START_CHANNEL_QA 214 ++#define WLC_GET_CHANNEL_SEL 215 ++#define WLC_START_CHANNEL_SEL 216 ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++#define WLC_GET_VALID_CHANNELS 217 ++#define WLC_GET_FAKEFRAG 218 ++#define WLC_SET_FAKEFRAG 219 ++#define WLC_GET_PWROUT_PERCENTAGE 220 ++#define WLC_SET_PWROUT_PERCENTAGE 221 ++#define WLC_SET_BAD_FRAME_PREEMPT 222 ++#define WLC_GET_BAD_FRAME_PREEMPT 223 ++#define WLC_SET_LEAP_LIST 224 ++#define WLC_GET_LEAP_LIST 225 ++#define WLC_GET_CWMIN 226 ++#define WLC_SET_CWMIN 227 ++#define WLC_GET_CWMAX 228 ++#define WLC_SET_CWMAX 229 ++#define WLC_GET_WET 230 ++#define WLC_SET_WET 231 ++#define WLC_GET_PUB 232 ++/* #define WLC_SET_GLACIAL_TIMER 233 */ /* no longer supported */ ++/* #define WLC_GET_GLACIAL_TIMER 234 */ /* no longer supported */ ++#define WLC_GET_KEY_PRIMARY 235 ++#define WLC_SET_KEY_PRIMARY 236 ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++ ++/* #define WLC_DUMP_RADIOREGS 237 */ /* no longer supported */ ++#define WLC_GET_ACI_ARGS 238 ++#define WLC_SET_ACI_ARGS 239 ++#define WLC_UNSET_CALLBACK 240 ++#define WLC_SET_CALLBACK 241 ++#define WLC_GET_RADAR 242 ++#define WLC_SET_RADAR 243 ++#define WLC_SET_SPECT_MANAGMENT 244 ++#define WLC_GET_SPECT_MANAGMENT 245 ++#define WLC_WDS_GET_REMOTE_HWADDR 246 /* handled in wl_linux.c/wl_vx.c */ ++#define WLC_WDS_GET_WPA_SUP 247 ++#define WLC_SET_CS_SCAN_TIMER 248 ++#define WLC_GET_CS_SCAN_TIMER 249 ++#define WLC_MEASURE_REQUEST 250 ++#define WLC_INIT 251 ++#define WLC_SEND_QUIET 252 ++#define WLC_KEEPALIVE 253 ++#define WLC_SEND_PWR_CONSTRAINT 254 ++#define WLC_UPGRADE_STATUS 255 ++#define WLC_CURRENT_PWR 256 ++#define WLC_GET_SCAN_PASSIVE_TIME 257 ++#define WLC_SET_SCAN_PASSIVE_TIME 258 ++#define WLC_LEGACY_LINK_BEHAVIOR 259 ++#define WLC_GET_CHANNELS_IN_COUNTRY 260 ++#define WLC_GET_COUNTRY_LIST 261 ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++#define WLC_GET_VAR 262 /* get value of named variable */ ++#define WLC_SET_VAR 263 /* set named variable to value */ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++#define WLC_NVRAM_GET 264 /* deprecated */ ++#define WLC_NVRAM_SET 265 ++#define WLC_NVRAM_DUMP 266 ++#define WLC_REBOOT 267 ++#define WLC_SET_WSEC_PMK 268 ++#define WLC_GET_AUTH_MODE 269 ++#define WLC_SET_AUTH_MODE 270 ++#define WLC_GET_WAKEENTRY 271 ++#define WLC_SET_WAKEENTRY 272 ++#define WLC_NDCONFIG_ITEM 273 /* currently handled in wl_oid.c */ ++#define WLC_NVOTPW 274 ++#define WLC_OTPW 275 ++#define WLC_IOV_BLOCK_GET 276 ++#define WLC_IOV_MODULES_GET 277 ++#define WLC_SOFT_RESET 278 ++#define WLC_GET_ALLOW_MODE 279 ++#define WLC_SET_ALLOW_MODE 280 ++#define WLC_GET_DESIRED_BSSID 281 ++#define WLC_SET_DESIRED_BSSID 282 ++#define WLC_DISASSOC_MYAP 283 ++#define WLC_GET_NBANDS 284 /* for Dongle EXT_STA support */ ++#define WLC_GET_BANDSTATES 285 /* for Dongle EXT_STA support */ ++#define WLC_GET_WLC_BSS_INFO 286 /* for Dongle EXT_STA support */ ++#define WLC_GET_ASSOC_INFO 287 /* for Dongle EXT_STA support */ ++#define WLC_GET_OID_PHY 288 /* for Dongle EXT_STA support */ ++#define WLC_SET_OID_PHY 289 /* for Dongle EXT_STA support */ ++#define WLC_SET_ASSOC_TIME 290 /* for Dongle EXT_STA support */ ++#define WLC_GET_DESIRED_SSID 291 /* for Dongle EXT_STA support */ ++#define WLC_GET_CHANSPEC 292 /* for Dongle EXT_STA support */ ++#define WLC_GET_ASSOC_STATE 293 /* for Dongle EXT_STA support */ ++#define WLC_SET_PHY_STATE 294 /* for Dongle EXT_STA support */ ++#define WLC_GET_SCAN_PENDING 295 /* for Dongle EXT_STA support */ ++#define WLC_GET_SCANREQ_PENDING 296 /* for Dongle EXT_STA support */ ++#define WLC_GET_PREV_ROAM_REASON 297 /* for Dongle EXT_STA support */ ++#define WLC_SET_PREV_ROAM_REASON 298 /* for Dongle EXT_STA support */ ++#define WLC_GET_BANDSTATES_PI 299 /* for Dongle EXT_STA support */ ++#define WLC_GET_PHY_STATE 300 /* for Dongle EXT_STA support */ ++#define WLC_GET_BSS_WPA_RSN 301 /* for Dongle EXT_STA support */ ++#define WLC_GET_BSS_WPA2_RSN 302 /* for Dongle EXT_STA support */ ++#define WLC_GET_BSS_BCN_TS 303 /* for Dongle EXT_STA support */ ++#define WLC_GET_INT_DISASSOC 304 /* for Dongle EXT_STA support */ ++#define WLC_SET_NUM_PEERS 305 /* for Dongle EXT_STA support */ ++#define WLC_GET_NUM_BSS 306 /* for Dongle EXT_STA support */ ++#define WLC_PHY_SAMPLE_COLLECT 307 /* phy sample collect mode */ ++/* #define WLC_UM_PRIV 308 */ /* Deprecated: usermode driver */ ++#define WLC_GET_CMD 309 ++/* #define WLC_LAST 310 */ /* Never used - can be reused */ ++#define WLC_SET_INTERFERENCE_OVERRIDE_MODE 311 /* set inter mode override */ ++#define WLC_GET_INTERFERENCE_OVERRIDE_MODE 312 /* get inter mode override */ ++/* #define WLC_GET_WAI_RESTRICT 313 */ /* for WAPI, deprecated use iovar instead */ ++/* #define WLC_SET_WAI_RESTRICT 314 */ /* for WAPI, deprecated use iovar instead */ ++/* #define WLC_SET_WAI_REKEY 315 */ /* for WAPI, deprecated use iovar instead */ ++#define WLC_SET_NAT_CONFIG 316 /* for configuring NAT filter driver */ ++#define WLC_GET_NAT_STATE 317 ++#define WLC_LAST 318 ++ ++#ifndef EPICTRL_COOKIE ++#define EPICTRL_COOKIE 0xABADCEDE ++#endif ++ ++/* vx wlc ioctl's offset */ ++#define CMN_IOCTL_OFF 0x180 ++ ++/* ++ * custom OID support ++ * ++ * 0xFF - implementation specific OID ++ * 0xE4 - first byte of Broadcom PCI vendor ID ++ * 0x14 - second byte of Broadcom PCI vendor ID ++ * 0xXX - the custom OID number ++ */ ++ ++/* begin 0x1f values beyond the start of the ET driver range. */ ++#define WL_OID_BASE 0xFFE41420 ++ ++/* NDIS overrides */ ++#define OID_WL_GETINSTANCE (WL_OID_BASE + WLC_GET_INSTANCE) ++#define OID_WL_GET_FORCELINK (WL_OID_BASE + WLC_GET_FORCELINK) ++#define OID_WL_SET_FORCELINK (WL_OID_BASE + WLC_SET_FORCELINK) ++#define OID_WL_ENCRYPT_STRENGTH (WL_OID_BASE + WLC_ENCRYPT_STRENGTH) ++#define OID_WL_DECRYPT_STATUS (WL_OID_BASE + WLC_DECRYPT_STATUS) ++#define OID_LEGACY_LINK_BEHAVIOR (WL_OID_BASE + WLC_LEGACY_LINK_BEHAVIOR) ++#define OID_WL_NDCONFIG_ITEM (WL_OID_BASE + WLC_NDCONFIG_ITEM) ++ ++/* EXT_STA Dongle suuport */ ++#define OID_STA_CHANSPEC (WL_OID_BASE + WLC_GET_CHANSPEC) ++#define OID_STA_NBANDS (WL_OID_BASE + WLC_GET_NBANDS) ++#define OID_STA_GET_PHY (WL_OID_BASE + WLC_GET_OID_PHY) ++#define OID_STA_SET_PHY (WL_OID_BASE + WLC_SET_OID_PHY) ++#define OID_STA_ASSOC_TIME (WL_OID_BASE + WLC_SET_ASSOC_TIME) ++#define OID_STA_DESIRED_SSID (WL_OID_BASE + WLC_GET_DESIRED_SSID) ++#define OID_STA_SET_PHY_STATE (WL_OID_BASE + WLC_SET_PHY_STATE) ++#define OID_STA_SCAN_PENDING (WL_OID_BASE + WLC_GET_SCAN_PENDING) ++#define OID_STA_SCANREQ_PENDING (WL_OID_BASE + WLC_GET_SCANREQ_PENDING) ++#define OID_STA_GET_ROAM_REASON (WL_OID_BASE + WLC_GET_PREV_ROAM_REASON) ++#define OID_STA_SET_ROAM_REASON (WL_OID_BASE + WLC_SET_PREV_ROAM_REASON) ++#define OID_STA_GET_PHY_STATE (WL_OID_BASE + WLC_GET_PHY_STATE) ++#define OID_STA_INT_DISASSOC (WL_OID_BASE + WLC_GET_INT_DISASSOC) ++#define OID_STA_SET_NUM_PEERS (WL_OID_BASE + WLC_SET_NUM_PEERS) ++#define OID_STA_GET_NUM_BSS (WL_OID_BASE + WLC_GET_NUM_BSS) ++ ++/* NAT filter driver support */ ++#define OID_NAT_SET_CONFIG (WL_OID_BASE + WLC_SET_NAT_CONFIG) ++#define OID_NAT_GET_STATE (WL_OID_BASE + WLC_GET_NAT_STATE) ++ ++#define WL_DECRYPT_STATUS_SUCCESS 1 ++#define WL_DECRYPT_STATUS_FAILURE 2 ++#define WL_DECRYPT_STATUS_UNKNOWN 3 ++ ++/* allows user-mode app to poll the status of USB image upgrade */ ++#define WLC_UPGRADE_SUCCESS 0 ++#define WLC_UPGRADE_PENDING 1 ++ ++#ifdef CONFIG_USBRNDIS_RETAIL ++/* struct passed in for WLC_NDCONFIG_ITEM */ ++typedef struct { ++ char *name; ++ void *param; ++} ndconfig_item_t; ++#endif ++ ++ ++/* WLC_GET_AUTH, WLC_SET_AUTH values */ ++#define WL_AUTH_OPEN_SYSTEM 0 /* d11 open authentication */ ++#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ ++#ifdef BCM4330_CHIP ++#define WL_AUTH_OPEN_SHARED 2 /* try open, then shared if open failed w/rc 13 */ ++#else ++/* BCM4334(Phoenex branch) value changed to 3 */ ++#define WL_AUTH_OPEN_SHARED 3 /* try open, then shared if open failed w/rc 13 */ ++#endif ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* Bit masks for radio disabled status - returned by WL_GET_RADIO */ ++#define WL_RADIO_SW_DISABLE (1<<0) ++#define WL_RADIO_HW_DISABLE (1<<1) ++#define WL_RADIO_MPC_DISABLE (1<<2) ++#define WL_RADIO_COUNTRY_DISABLE (1<<3) /* some countries don't support any channel */ ++ ++#define WL_SPURAVOID_OFF 0 ++#define WL_SPURAVOID_ON1 1 ++#define WL_SPURAVOID_ON2 2 ++ ++/* Override bit for WLC_SET_TXPWR. if set, ignore other level limits */ ++#define WL_TXPWR_OVERRIDE (1U<<31) ++#define WL_TXPWR_NEG (1U<<30) ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++#define WL_PHY_PAVARS_LEN 32 /* Phy type, Band range, chain, a1[0], b0[0], b1[0] ... */ ++ ++#define WL_PHY_PAVAR_VER 1 /* pavars version */ ++ ++typedef struct wl_po { ++ uint16 phy_type; /* Phy type */ ++ uint16 band; ++ uint16 cckpo; ++ uint32 ofdmpo; ++ uint16 mcspo[8]; ++} wl_po_t; ++ ++/* a large TX Power as an init value to factor out of MIN() calculations, ++ * keep low enough to fit in an int8, units are .25 dBm ++ */ ++#define WLC_TXPWR_MAX (127) /* ~32 dBm = 1,500 mW */ ++ ++/* "diag" iovar argument and error code */ ++#define WL_DIAG_INTERRUPT 1 /* d11 loopback interrupt test */ ++#define WL_DIAG_LOOPBACK 2 /* d11 loopback data test */ ++#define WL_DIAG_MEMORY 3 /* d11 memory test */ ++#define WL_DIAG_LED 4 /* LED test */ ++#define WL_DIAG_REG 5 /* d11/phy register test */ ++#define WL_DIAG_SROM 6 /* srom read/crc test */ ++#define WL_DIAG_DMA 7 /* DMA test */ ++#define WL_DIAG_LOOPBACK_EXT 8 /* enhenced d11 loopback data test */ ++ ++#define WL_DIAGERR_SUCCESS 0 ++#define WL_DIAGERR_FAIL_TO_RUN 1 /* unable to run requested diag */ ++#define WL_DIAGERR_NOT_SUPPORTED 2 /* diag requested is not supported */ ++#define WL_DIAGERR_INTERRUPT_FAIL 3 /* loopback interrupt test failed */ ++#define WL_DIAGERR_LOOPBACK_FAIL 4 /* loopback data test failed */ ++#define WL_DIAGERR_SROM_FAIL 5 /* srom read failed */ ++#define WL_DIAGERR_SROM_BADCRC 6 /* srom crc failed */ ++#define WL_DIAGERR_REG_FAIL 7 /* d11/phy register test failed */ ++#define WL_DIAGERR_MEMORY_FAIL 8 /* d11 memory test failed */ ++#define WL_DIAGERR_NOMEM 9 /* diag test failed due to no memory */ ++#define WL_DIAGERR_DMA_FAIL 10 /* DMA test failed */ ++ ++#define WL_DIAGERR_MEMORY_TIMEOUT 11 /* d11 memory test didn't finish in time */ ++#define WL_DIAGERR_MEMORY_BADPATTERN 12 /* d11 memory test result in bad pattern */ ++ ++/* band types */ ++#define WLC_BAND_AUTO 0 /* auto-select */ ++#define WLC_BAND_5G 1 /* 5 Ghz */ ++#define WLC_BAND_2G 2 /* 2.4 Ghz */ ++#define WLC_BAND_ALL 3 /* all bands */ ++ ++/* band range returned by band_range iovar */ ++#define WL_CHAN_FREQ_RANGE_2G 0 ++#define WL_CHAN_FREQ_RANGE_5GL 1 ++#define WL_CHAN_FREQ_RANGE_5GM 2 ++#define WL_CHAN_FREQ_RANGE_5GH 3 ++ ++#define WL_CHAN_FREQ_RANGE_5G_BAND0 1 ++#define WL_CHAN_FREQ_RANGE_5G_BAND1 2 ++#define WL_CHAN_FREQ_RANGE_5G_BAND2 3 ++#define WL_CHAN_FREQ_RANGE_5G_BAND3 4 ++ ++#define WL_CHAN_FREQ_RANGE_5G_4BAND 5 ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* phy types (returned by WLC_GET_PHYTPE) */ ++#define WLC_PHY_TYPE_A 0 ++#define WLC_PHY_TYPE_B 1 ++#define WLC_PHY_TYPE_G 2 ++#define WLC_PHY_TYPE_N 4 ++#define WLC_PHY_TYPE_LP 5 ++#define WLC_PHY_TYPE_SSN 6 ++#define WLC_PHY_TYPE_HT 7 ++#define WLC_PHY_TYPE_LCN 8 ++#define WLC_PHY_TYPE_LCN40 10 ++#define WLC_PHY_TYPE_AC 11 ++#define WLC_PHY_TYPE_NULL 0xf ++ ++/* Values for PM */ ++#define PM_OFF 0 ++#define PM_MAX 1 ++#define PM_FAST 2 ++#define PM_FORCE_OFF 3 /* use this bit to force PM off even bt is active */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* MAC list modes */ ++#define WLC_MACMODE_DISABLED 0 /* MAC list disabled */ ++#define WLC_MACMODE_DENY 1 /* Deny specified (i.e. allow unspecified) */ ++#define WLC_MACMODE_ALLOW 2 /* Allow specified (i.e. deny unspecified) */ ++ ++/* ++ * 54g modes (basic bits may still be overridden) ++ * ++ * GMODE_LEGACY_B Rateset: 1b, 2b, 5.5, 11 ++ * Preamble: Long ++ * Shortslot: Off ++ * GMODE_AUTO Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 ++ * Extended Rateset: 6, 9, 12, 48 ++ * Preamble: Long ++ * Shortslot: Auto ++ * GMODE_ONLY Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54 ++ * Extended Rateset: 6b, 9, 12b, 48 ++ * Preamble: Short required ++ * Shortslot: Auto ++ * GMODE_B_DEFERRED Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54 ++ * Extended Rateset: 6, 9, 12, 48 ++ * Preamble: Long ++ * Shortslot: On ++ * GMODE_PERFORMANCE Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54 ++ * Preamble: Short required ++ * Shortslot: On and required ++ * GMODE_LRS Rateset: 1b, 2b, 5.5b, 11b ++ * Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54 ++ * Preamble: Long ++ * Shortslot: Auto ++ */ ++#define GMODE_LEGACY_B 0 ++#define GMODE_AUTO 1 ++#define GMODE_ONLY 2 ++#define GMODE_B_DEFERRED 3 ++#define GMODE_PERFORMANCE 4 ++#define GMODE_LRS 5 ++#define GMODE_MAX 6 ++ ++/* values for PLCPHdr_override */ ++#define WLC_PLCP_AUTO -1 ++#define WLC_PLCP_SHORT 0 ++#define WLC_PLCP_LONG 1 ++ ++/* values for g_protection_override and n_protection_override */ ++#define WLC_PROTECTION_AUTO -1 ++#define WLC_PROTECTION_OFF 0 ++#define WLC_PROTECTION_ON 1 ++#define WLC_PROTECTION_MMHDR_ONLY 2 ++#define WLC_PROTECTION_CTS_ONLY 3 ++ ++/* values for g_protection_control and n_protection_control */ ++#define WLC_PROTECTION_CTL_OFF 0 ++#define WLC_PROTECTION_CTL_LOCAL 1 ++#define WLC_PROTECTION_CTL_OVERLAP 2 ++ ++/* values for n_protection */ ++#define WLC_N_PROTECTION_OFF 0 ++#define WLC_N_PROTECTION_OPTIONAL 1 ++#define WLC_N_PROTECTION_20IN40 2 ++#define WLC_N_PROTECTION_MIXEDMODE 3 ++ ++/* values for n_preamble_type */ ++#define WLC_N_PREAMBLE_MIXEDMODE 0 ++#define WLC_N_PREAMBLE_GF 1 ++#define WLC_N_PREAMBLE_GF_BRCM 2 ++ ++/* values for band specific 40MHz capabilities (deprecated) */ ++#define WLC_N_BW_20ALL 0 ++#define WLC_N_BW_40ALL 1 ++#define WLC_N_BW_20IN2G_40IN5G 2 ++ ++#define WLC_BW_20MHZ_BIT (1<<0) ++#define WLC_BW_40MHZ_BIT (1<<1) ++#define WLC_BW_80MHZ_BIT (1<<2) ++ ++/* Bandwidth capabilities */ ++#define WLC_BW_CAP_20MHZ (WLC_BW_20MHZ_BIT) ++#define WLC_BW_CAP_40MHZ (WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT) ++#define WLC_BW_CAP_80MHZ (WLC_BW_80MHZ_BIT|WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT) ++#define WLC_BW_CAP_UNRESTRICTED 0xFF ++ ++#define WL_BW_CAP_20MHZ(bw_cap) (((bw_cap) & WLC_BW_20MHZ_BIT) ? TRUE : FALSE) ++#define WL_BW_CAP_40MHZ(bw_cap) (((bw_cap) & WLC_BW_40MHZ_BIT) ? TRUE : FALSE) ++#define WL_BW_CAP_80MHZ(bw_cap) (((bw_cap) & WLC_BW_80MHZ_BIT) ? TRUE : FALSE) ++ ++/* values to force tx/rx chain */ ++#define WLC_N_TXRX_CHAIN0 0 ++#define WLC_N_TXRX_CHAIN1 1 ++ ++/* bitflags for SGI support (sgi_rx iovar) */ ++#define WLC_N_SGI_20 0x01 ++#define WLC_N_SGI_40 0x02 ++#define WLC_VHT_SGI_80 0x04 ++ ++/* when sgi_tx==WLC_SGI_ALL, bypass rate selection, enable sgi for all mcs */ ++#define WLC_SGI_ALL 0x02 ++ ++#define LISTEN_INTERVAL 10 ++/* interference mitigation options */ ++#define INTERFERE_OVRRIDE_OFF -1 /* interference override off */ ++#define INTERFERE_NONE 0 /* off */ ++#define NON_WLAN 1 /* foreign/non 802.11 interference, no auto detect */ ++#define WLAN_MANUAL 2 /* ACI: no auto detection */ ++#define WLAN_AUTO 3 /* ACI: auto detect */ ++#define WLAN_AUTO_W_NOISE 4 /* ACI: auto - detect and non 802.11 interference */ ++#define AUTO_ACTIVE (1 << 7) /* Auto is currently active */ ++ ++/* AP environment */ ++#define AP_ENV_DETECT_NOT_USED 0 /* We aren't using AP environment detection */ ++#define AP_ENV_DENSE 1 /* "Corporate" or other AP dense environment */ ++#define AP_ENV_SPARSE 2 /* "Home" or other sparse environment */ ++#define AP_ENV_INDETERMINATE 3 /* AP environment hasn't been identified */ ++ ++typedef struct wl_aci_args { ++ int enter_aci_thresh; /* Trigger level to start detecting ACI */ ++ int exit_aci_thresh; /* Trigger level to exit ACI mode */ ++ int usec_spin; /* microsecs to delay between rssi samples */ ++ int glitch_delay; /* interval between ACI scans when glitch count is consistently high */ ++ uint16 nphy_adcpwr_enter_thresh; /* ADC power to enter ACI mitigation mode */ ++ uint16 nphy_adcpwr_exit_thresh; /* ADC power to exit ACI mitigation mode */ ++ uint16 nphy_repeat_ctr; /* Number of tries per channel to compute power */ ++ uint16 nphy_num_samples; /* Number of samples to compute power on one channel */ ++ uint16 nphy_undetect_window_sz; /* num of undetects to exit ACI Mitigation mode */ ++ uint16 nphy_b_energy_lo_aci; /* low ACI power energy threshold for bphy */ ++ uint16 nphy_b_energy_md_aci; /* mid ACI power energy threshold for bphy */ ++ uint16 nphy_b_energy_hi_aci; /* high ACI power energy threshold for bphy */ ++ uint16 nphy_noise_noassoc_glitch_th_up; /* wl interference 4 */ ++ uint16 nphy_noise_noassoc_glitch_th_dn; ++ uint16 nphy_noise_assoc_glitch_th_up; ++ uint16 nphy_noise_assoc_glitch_th_dn; ++ uint16 nphy_noise_assoc_aci_glitch_th_up; ++ uint16 nphy_noise_assoc_aci_glitch_th_dn; ++ uint16 nphy_noise_assoc_enter_th; ++ uint16 nphy_noise_noassoc_enter_th; ++ uint16 nphy_noise_assoc_rx_glitch_badplcp_enter_th; ++ uint16 nphy_noise_noassoc_crsidx_incr; ++ uint16 nphy_noise_assoc_crsidx_incr; ++ uint16 nphy_noise_crsidx_decr; ++} wl_aci_args_t; ++ ++#define TRIGGER_NOW 0 ++#define TRIGGER_CRS 0x01 ++#define TRIGGER_CRSDEASSERT 0x02 ++#define TRIGGER_GOODFCS 0x04 ++#define TRIGGER_BADFCS 0x08 ++#define TRIGGER_BADPLCP 0x10 ++#define TRIGGER_CRSGLITCH 0x20 ++#define WL_ACI_ARGS_LEGACY_LENGTH 16 /* bytes of pre NPHY aci args */ ++#define WL_SAMPLECOLLECT_T_VERSION 2 /* version of wl_samplecollect_args_t struct */ ++typedef struct wl_samplecollect_args { ++ /* version 0 fields */ ++ uint8 coll_us; ++ int cores; ++ /* add'l version 1 fields */ ++ uint16 version; /* see definition of WL_SAMPLECOLLECT_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ int8 trigger; ++ uint16 timeout; ++ uint16 mode; ++ uint32 pre_dur; ++ uint32 post_dur; ++ uint8 gpio_sel; ++ bool downsamp; ++ bool be_deaf; ++ bool agc; /* loop from init gain and going down */ ++ bool filter; /* override high pass corners to lowest */ ++ /* add'l version 2 fields */ ++ uint8 trigger_state; ++ uint8 module_sel1; ++ uint8 module_sel2; ++ uint16 nsamps; ++} wl_samplecollect_args_t; ++ ++#define WL_SAMPLEDATA_HEADER_TYPE 1 ++#define WL_SAMPLEDATA_HEADER_SIZE 80 /* sample collect header size (bytes) */ ++#define WL_SAMPLEDATA_TYPE 2 ++#define WL_SAMPLEDATA_SEQ 0xff /* sequence # */ ++#define WL_SAMPLEDATA_MORE_DATA 0x100 /* more data mask */ ++#define WL_SAMPLEDATA_T_VERSION 1 /* version of wl_samplecollect_args_t struct */ ++/* version for unpacked sample data, int16 {(I,Q),Core(0..N)} */ ++#define WL_SAMPLEDATA_T_VERSION_SPEC_AN 2 ++ ++typedef struct wl_sampledata { ++ uint16 version; /* structure version */ ++ uint16 size; /* size of structure */ ++ uint16 tag; /* Header/Data */ ++ uint16 length; /* data length */ ++ uint32 flag; /* bit def */ ++} wl_sampledata_t; ++ ++/* wl_radar_args_t */ ++typedef struct { ++ int npulses; /* required number of pulses at n * t_int */ ++ int ncontig; /* required number of pulses at t_int */ ++ int min_pw; /* minimum pulse width (20 MHz clocks) */ ++ int max_pw; /* maximum pulse width (20 MHz clocks) */ ++ uint16 thresh0; /* Radar detection, thresh 0 */ ++ uint16 thresh1; /* Radar detection, thresh 1 */ ++ uint16 blank; /* Radar detection, blank control */ ++ uint16 fmdemodcfg; /* Radar detection, fmdemod config */ ++ int npulses_lp; /* Radar detection, minimum long pulses */ ++ int min_pw_lp; /* Minimum pulsewidth for long pulses */ ++ int max_pw_lp; /* Maximum pulsewidth for long pulses */ ++ int min_fm_lp; /* Minimum fm for long pulses */ ++ int max_span_lp; /* Maximum deltat for long pulses */ ++ int min_deltat; /* Minimum spacing between pulses */ ++ int max_deltat; /* Maximum spacing between pulses */ ++ uint16 autocorr; /* Radar detection, autocorr on or off */ ++ uint16 st_level_time; /* Radar detection, start_timing level */ ++ uint16 t2_min; /* minimum clocks needed to remain in state 2 */ ++ uint32 version; /* version */ ++ uint32 fra_pulse_err; /* sample error margin for detecting French radar pulsed */ ++ int npulses_fra; /* Radar detection, minimum French pulses set */ ++ int npulses_stg2; /* Radar detection, minimum staggered-2 pulses set */ ++ int npulses_stg3; /* Radar detection, minimum staggered-3 pulses set */ ++ uint16 percal_mask; /* defines which period cal is masked from radar detection */ ++ int quant; /* quantization resolution to pulse positions */ ++ uint32 min_burst_intv_lp; /* minimum burst to burst interval for bin3 radar */ ++ uint32 max_burst_intv_lp; /* maximum burst to burst interval for bin3 radar */ ++ int nskip_rst_lp; /* number of skipped pulses before resetting lp buffer */ ++ int max_pw_tol; /* maximum tollerance allowed in detected pulse width for radar detection */ ++ uint16 feature_mask; /* 16-bit mask to specify enabled features */ ++} wl_radar_args_t; ++ ++#define WL_RADAR_ARGS_VERSION 2 ++ ++typedef struct { ++ uint32 version; /* version */ ++ uint16 thresh0_20_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 20MHz */ ++ uint16 thresh1_20_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 20MHz */ ++ uint16 thresh0_40_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 40MHz */ ++ uint16 thresh1_40_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 40MHz */ ++ uint16 thresh0_80_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 80MHz */ ++ uint16 thresh1_80_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 80MHz */ ++ uint16 thresh0_160_lo; /* Radar detection, thresh 0 (range 5250-5350MHz) for BW 160MHz */ ++ uint16 thresh1_160_lo; /* Radar detection, thresh 1 (range 5250-5350MHz) for BW 160MHz */ ++ uint16 thresh0_20_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 20MHz */ ++ uint16 thresh1_20_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 20MHz */ ++ uint16 thresh0_40_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 40MHz */ ++ uint16 thresh1_40_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 40MHz */ ++ uint16 thresh0_80_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 80MHz */ ++ uint16 thresh1_80_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 80MHz */ ++ uint16 thresh0_160_hi; /* Radar detection, thresh 0 (range 5470-5725MHz) for BW 160MHz */ ++ uint16 thresh1_160_hi; /* Radar detection, thresh 1 (range 5470-5725MHz) for BW 160MHz */ ++} wl_radar_thr_t; ++ ++#define WL_RADAR_THR_VERSION 2 ++#define WL_THRESHOLD_LO_BAND 70 /* range from 5250MHz - 5350MHz */ ++ ++/* radar iovar SET defines */ ++#define WL_RADAR_DETECTOR_OFF 0 /* radar detector off */ ++#define WL_RADAR_DETECTOR_ON 1 /* radar detector on */ ++#define WL_RADAR_SIMULATED 2 /* force radar detector to declare ++ * detection once ++ */ ++#define WL_RSSI_ANT_VERSION 1 /* current version of wl_rssi_ant_t */ ++#define WL_ANT_RX_MAX 2 /* max 2 receive antennas */ ++#define WL_ANT_HT_RX_MAX 3 /* max 3 receive antennas/cores */ ++#define WL_ANT_IDX_1 0 /* antenna index 1 */ ++#define WL_ANT_IDX_2 1 /* antenna index 2 */ ++ ++#ifndef WL_RSSI_ANT_MAX ++#define WL_RSSI_ANT_MAX 4 /* max possible rx antennas */ ++#elif WL_RSSI_ANT_MAX != 4 ++#error "WL_RSSI_ANT_MAX does not match" ++#endif ++ ++/* RSSI per antenna */ ++typedef struct { ++ uint32 version; /* version field */ ++ uint32 count; /* number of valid antenna rssi */ ++ int8 rssi_ant[WL_RSSI_ANT_MAX]; /* rssi per antenna */ ++} wl_rssi_ant_t; ++ ++/* dfs_status iovar-related defines */ ++ ++/* cac - channel availability check, ++ * ism - in-service monitoring ++ * csa - channel switching announcement ++ */ ++ ++/* cac state values */ ++#define WL_DFS_CACSTATE_IDLE 0 /* state for operating in non-radar channel */ ++#define WL_DFS_CACSTATE_PREISM_CAC 1 /* CAC in progress */ ++#define WL_DFS_CACSTATE_ISM 2 /* ISM in progress */ ++#define WL_DFS_CACSTATE_CSA 3 /* csa */ ++#define WL_DFS_CACSTATE_POSTISM_CAC 4 /* ISM CAC */ ++#define WL_DFS_CACSTATE_PREISM_OOC 5 /* PREISM OOC */ ++#define WL_DFS_CACSTATE_POSTISM_OOC 6 /* POSTISM OOC */ ++#define WL_DFS_CACSTATES 7 /* this many states exist */ ++ ++/* data structure used in 'dfs_status' wl interface, which is used to query dfs status */ ++typedef struct { ++ uint state; /* noted by WL_DFS_CACSTATE_XX. */ ++ uint duration; /* time spent in ms in state. */ ++ /* as dfs enters ISM state, it removes the operational channel from quiet channel ++ * list and notes the channel in channel_cleared. set to 0 if no channel is cleared ++ */ ++ chanspec_t chanspec_cleared; ++ /* chanspec cleared used to be a uint, add another to uint16 to maintain size */ ++ uint16 pad; ++} wl_dfs_status_t; ++ ++#define NUM_PWRCTRL_RATES 12 ++ ++typedef struct { ++ uint8 txpwr_band_max[NUM_PWRCTRL_RATES]; /* User set target */ ++ uint8 txpwr_limit[NUM_PWRCTRL_RATES]; /* reg and local power limit */ ++ uint8 txpwr_local_max; /* local max according to the AP */ ++ uint8 txpwr_local_constraint; /* local constraint according to the AP */ ++ uint8 txpwr_chan_reg_max; /* Regulatory max for this channel */ ++ uint8 txpwr_target[2][NUM_PWRCTRL_RATES]; /* Latest target for 2.4 and 5 Ghz */ ++ uint8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ ++ uint8 txpwr_opo[NUM_PWRCTRL_RATES]; /* On G phy, OFDM power offset */ ++ uint8 txpwr_bphy_cck_max[NUM_PWRCTRL_RATES]; /* Max CCK power for this band (SROM) */ ++ uint8 txpwr_bphy_ofdm_max; /* Max OFDM power for this band (SROM) */ ++ uint8 txpwr_aphy_max[NUM_PWRCTRL_RATES]; /* Max power for A band (SROM) */ ++ int8 txpwr_antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ ++} tx_power_legacy_t; ++ ++#define WL_TX_POWER_RATES_LEGACY 45 ++#define WL_TX_POWER_MCS20_FIRST 12 ++#define WL_TX_POWER_MCS20_NUM 16 ++#define WL_TX_POWER_MCS40_FIRST 28 ++#define WL_TX_POWER_MCS40_NUM 17 ++ ++typedef struct { ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 local_max; /* local max according to the AP */ ++ uint8 local_constraint; /* local constraint according to the AP */ ++ int8 antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 rf_cores; /* count of RF Cores being reported */ ++ uint8 est_Pout[4]; /* Latest tx power out estimate per RF ++ * chain without adjustment ++ */ ++ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ ++ uint8 user_limit[WL_TX_POWER_RATES_LEGACY]; /* User limit */ ++ uint8 reg_limit[WL_TX_POWER_RATES_LEGACY]; /* Regulatory power limit */ ++ uint8 board_limit[WL_TX_POWER_RATES_LEGACY]; /* Max power board can support (SROM) */ ++ uint8 target[WL_TX_POWER_RATES_LEGACY]; /* Latest target power */ ++} tx_power_legacy2_t; ++ ++/* TX Power index defines */ ++#define WL_NUM_RATES_CCK 4 /* 1, 2, 5.5, 11 Mbps */ ++#define WL_NUM_RATES_OFDM 8 /* 6, 9, 12, 18, 24, 36, 48, 54 Mbps SISO/CDD */ ++#define WL_NUM_RATES_MCS_1STREAM 8 /* MCS 0-7 1-stream rates - SISO/CDD/STBC/MCS */ ++#define WL_NUM_RATES_EXTRA_VHT 2 /* Additional VHT 11AC rates */ ++#define WL_NUM_RATES_VHT 10 ++#define WL_NUM_RATES_MCS32 1 ++ ++#define WLC_NUM_RATES_CCK WL_NUM_RATES_CCK ++#define WLC_NUM_RATES_OFDM WL_NUM_RATES_OFDM ++#define WLC_NUM_RATES_MCS_1_STREAM WL_NUM_RATES_MCS_1STREAM ++#define WLC_NUM_RATES_MCS_2_STREAM WL_NUM_RATES_MCS_1STREAM ++#define WLC_NUM_RATES_MCS32 WL_NUM_RATES_MCS32 ++#define WL_TX_POWER_CCK_NUM WL_NUM_RATES_CCK ++#define WL_TX_POWER_OFDM_NUM WL_NUM_RATES_OFDM ++#define WL_TX_POWER_MCS_1_STREAM_NUM WL_NUM_RATES_MCS_1STREAM ++#define WL_TX_POWER_MCS_2_STREAM_NUM WL_NUM_RATES_MCS_1STREAM ++#define WL_TX_POWER_MCS_32_NUM WL_NUM_RATES_MCS32 ++ ++#define WL_NUM_2x2_ELEMENTS 4 ++#define WL_NUM_3x3_ELEMENTS 6 ++ ++typedef struct txppr { ++ /* start of 20MHz tx power limits */ ++ uint8 b20_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b20_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b20_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b20_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b20_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b20_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b20_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b20_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b20_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b20_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b20_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b20_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b20_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b20_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b20_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 40MHz tx power limits */ ++ uint8 b40_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b40_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b40_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 20in40MHz tx power limits */ ++ uint8 b20in40_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b20in40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b20in40_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20in40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b20in40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b20in40_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* 20 in 40 MHz Legacy OFDM CDD */ ++ uint8 b20in40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b20in40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b20in40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b20in40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b20in40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b20in40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b20in40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b20in40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b20in40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b20in40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b20in40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 80MHz tx power limits */ ++ uint8 b80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 20in80MHz tx power limits */ ++ uint8 b20in80_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b20in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b20in80_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b20in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b20in80_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b20in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b20in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b20in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b20in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b20in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b20in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b20in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b20in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b20in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b20in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ /* start of 40in80MHz tx power limits */ ++ uint8 b40in80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b40in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b40in80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b40in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b40in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b40in80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* MHz Legacy OFDM CDD */ ++ uint8 b40in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b40in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b40in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b40in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b40in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b40in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b40in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b40in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b40in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b40in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b40in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ ++ uint8 mcs32; /* C_CHECK - THIS NEEDS TO BE REMOVED THROUGHOUT THE CODE */ ++} txppr_t; ++ ++/* 20MHz */ ++#define WL_TX_POWER_CCK_FIRST OFFSETOF(txppr_t, b20_1x1dsss) ++#define WL_TX_POWER_OFDM20_FIRST OFFSETOF(txppr_t, b20_1x1ofdm) ++#define WL_TX_POWER_MCS20_SISO_FIRST OFFSETOF(txppr_t, b20_1x1mcs0) ++#define WL_TX_POWER_20_S1x1_FIRST OFFSETOF(txppr_t, b20_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_CDD_S1x2_FIRST OFFSETOF(txppr_t, b20_1x2dsss) ++#define WL_TX_POWER_OFDM20_CDD_FIRST OFFSETOF(txppr_t, b20_1x2cdd_ofdm) ++#define WL_TX_POWER_MCS20_CDD_FIRST OFFSETOF(txppr_t, b20_1x2cdd_mcs0) ++#define WL_TX_POWER_20_S1x2_FIRST OFFSETOF(txppr_t, b20_1x2cdd_mcs0) ++#define WL_TX_POWER_MCS20_STBC_FIRST OFFSETOF(txppr_t, b20_2x2stbc_mcs0) ++#define WL_TX_POWER_MCS20_SDM_FIRST OFFSETOF(txppr_t, b20_2x2sdm_mcs8) ++#define WL_TX_POWER_20_S2x2_FIRST OFFSETOF(txppr_t, b20_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20_1x3dsss) ++#define WL_TX_POWER_OFDM20_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20_1x3cdd_ofdm) ++#define WL_TX_POWER_20_S1x3_FIRST OFFSETOF(txppr_t, b20_1x3cdd_mcs0) ++#define WL_TX_POWER_20_STBC_S2x3_FIRST OFFSETOF(txppr_t, b20_2x3stbc_mcs0) ++#define WL_TX_POWER_20_S2x3_FIRST OFFSETOF(txppr_t, b20_2x3sdm_mcs8) ++#define WL_TX_POWER_20_S3x3_FIRST OFFSETOF(txppr_t, b20_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_20_S1X1_VHT OFFSETOF(txppr_t, b20_1x1vht) ++#define WL_TX_POWER_20_S1X2_CDD_VHT OFFSETOF(txppr_t, b20_1x2cdd_vht) ++#define WL_TX_POWER_20_S2X2_STBC_VHT OFFSETOF(txppr_t, b20_2x2stbc_vht) ++#define WL_TX_POWER_20_S2X2_VHT OFFSETOF(txppr_t, b20_2x2sdm_vht) ++#define WL_TX_POWER_20_S1X3_CDD_VHT OFFSETOF(txppr_t, b20_1x3cdd_vht) ++#define WL_TX_POWER_20_S2X3_STBC_VHT OFFSETOF(txppr_t, b20_2x3stbc_vht) ++#define WL_TX_POWER_20_S2X3_VHT OFFSETOF(txppr_t, b20_2x3sdm_vht) ++#define WL_TX_POWER_20_S3X3_VHT OFFSETOF(txppr_t, b20_3x3sdm_vht) ++ ++/* 40MHz */ ++#define WL_TX_POWER_40_DUMMY_CCK_FIRST OFFSETOF(txppr_t, b40_dummy1x1dsss) ++#define WL_TX_POWER_OFDM40_FIRST OFFSETOF(txppr_t, b40_1x1ofdm) ++#define WL_TX_POWER_MCS40_SISO_FIRST OFFSETOF(txppr_t, b40_1x1mcs0) ++#define WL_TX_POWER_40_S1x1_FIRST OFFSETOF(txppr_t, b40_1x1mcs0) ++ ++#define WL_TX_POWER_40_DUMMY_CCK_CDD_S1x2_FIRST OFFSETOF(txppr_t, b40_dummy1x2dsss) ++#define WL_TX_POWER_OFDM40_CDD_FIRST OFFSETOF(txppr_t, b40_1x2cdd_ofdm) ++#define WL_TX_POWER_MCS40_CDD_FIRST OFFSETOF(txppr_t, b40_1x2cdd_mcs0) ++#define WL_TX_POWER_40_S1x2_FIRST OFFSETOF(txppr_t, b40_1x2cdd_mcs0) ++#define WL_TX_POWER_MCS40_STBC_FIRST OFFSETOF(txppr_t, b40_2x2stbc_mcs0) ++#define WL_TX_POWER_MCS40_SDM_FIRST OFFSETOF(txppr_t, b40_2x2sdm_mcs8) ++#define WL_TX_POWER_40_S2x2_FIRST OFFSETOF(txppr_t, b40_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_40_DUMMY_CCK_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40_dummy1x3dsss) ++#define WL_TX_POWER_OFDM40_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40_1x3cdd_ofdm) ++#define WL_TX_POWER_40_S1x3_FIRST OFFSETOF(txppr_t, b40_1x3cdd_mcs0) ++#define WL_TX_POWER_40_STBC_S2x3_FIRST OFFSETOF(txppr_t, b40_2x3stbc_mcs0) ++#define WL_TX_POWER_40_S2x3_FIRST OFFSETOF(txppr_t, b40_2x3sdm_mcs8) ++#define WL_TX_POWER_40_S3x3_FIRST OFFSETOF(txppr_t, b40_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_40_S1X1_VHT OFFSETOF(txppr_t, b40_1x1vht) ++#define WL_TX_POWER_40_S1X2_CDD_VHT OFFSETOF(txppr_t, b40_1x2cdd_vht) ++#define WL_TX_POWER_40_S2X2_STBC_VHT OFFSETOF(txppr_t, b40_2x2stbc_vht) ++#define WL_TX_POWER_40_S2X2_VHT OFFSETOF(txppr_t, b40_2x2sdm_vht) ++#define WL_TX_POWER_40_S1X3_CDD_VHT OFFSETOF(txppr_t, b40_1x3cdd_vht) ++#define WL_TX_POWER_40_S2X3_STBC_VHT OFFSETOF(txppr_t, b40_2x3stbc_vht) ++#define WL_TX_POWER_40_S2X3_VHT OFFSETOF(txppr_t, b40_2x3sdm_vht) ++#define WL_TX_POWER_40_S3X3_VHT OFFSETOF(txppr_t, b40_3x3sdm_vht) ++ ++/* 20 in 40MHz */ ++#define WL_TX_POWER_20UL_CCK_FIRST OFFSETOF(txppr_t, b20in40_1x1dsss) ++#define WL_TX_POWER_20UL_OFDM_FIRST OFFSETOF(txppr_t, b20in40_1x1ofdm) ++#define WL_TX_POWER_20UL_S1x1_FIRST OFFSETOF(txppr_t, b20in40_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_20U_CDD_S1x2_FIRST OFFSETOF(txppr_t, b20in40_1x2dsss) ++#define WL_TX_POWER_20UL_OFDM_CDD_FIRST OFFSETOF(txppr_t, b20in40_1x2cdd_ofdm) ++#define WL_TX_POWER_20UL_S1x2_FIRST OFFSETOF(txppr_t, b20in40_1x2cdd_mcs0) ++#define WL_TX_POWER_20UL_STBC_S2x2_FIRST OFFSETOF(txppr_t, b20in40_2x2stbc_mcs0) ++#define WL_TX_POWER_20UL_S2x2_FIRST OFFSETOF(txppr_t, b20in40_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_20U_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in40_1x3dsss) ++#define WL_TX_POWER_20UL_OFDM_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in40_1x3cdd_ofdm) ++#define WL_TX_POWER_20UL_S1x3_FIRST OFFSETOF(txppr_t, b20in40_1x3cdd_mcs0) ++#define WL_TX_POWER_20UL_STBC_S2x3_FIRST OFFSETOF(txppr_t, b20in40_2x3stbc_mcs0) ++#define WL_TX_POWER_20UL_S2x3_FIRST OFFSETOF(txppr_t, b20in40_2x3sdm_mcs8) ++#define WL_TX_POWER_20UL_S3x3_FIRST OFFSETOF(txppr_t, b20in40_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_20UL_S1X1_VHT OFFSETOF(txppr_t, b20in40_1x1vht) ++#define WL_TX_POWER_20UL_S1X2_CDD_VHT OFFSETOF(txppr_t, b20in40_1x2cdd_vht) ++#define WL_TX_POWER_20UL_S2X2_STBC_VHT OFFSETOF(txppr_t, b20in40_2x2stbc_vht) ++#define WL_TX_POWER_20UL_S2X2_VHT OFFSETOF(txppr_t, b20in40_2x2sdm_vht) ++#define WL_TX_POWER_20UL_S1X3_CDD_VHT OFFSETOF(txppr_t, b20in40_1x3cdd_vht) ++#define WL_TX_POWER_20UL_S2X3_STBC_VHT OFFSETOF(txppr_t, b20in40_2x3stbc_vht) ++#define WL_TX_POWER_20UL_S2X3_VHT OFFSETOF(txppr_t, b20in40_2x3sdm_vht) ++#define WL_TX_POWER_20UL_S3X3_VHT OFFSETOF(txppr_t, b20in40_3x3sdm_vht) ++ ++/* 80MHz */ ++#define WL_TX_POWER_80_DUMMY_CCK_FIRST OFFSETOF(txppr_t, b80_dummy1x1dsss) ++#define WL_TX_POWER_OFDM80_FIRST OFFSETOF(txppr_t, b80_1x1ofdm) ++#define WL_TX_POWER_MCS80_SISO_FIRST OFFSETOF(txppr_t, b80_1x1mcs0) ++#define WL_TX_POWER_80_S1x1_FIRST OFFSETOF(txppr_t, b80_1x1mcs0) ++ ++#define WL_TX_POWER_80_DUMMY_CCK_CDD_S1x2_FIRST OFFSETOF(txppr_t, b80_dummy1x2dsss) ++#define WL_TX_POWER_OFDM80_CDD_FIRST OFFSETOF(txppr_t, b80_1x2cdd_ofdm) ++#define WL_TX_POWER_MCS80_CDD_FIRST OFFSETOF(txppr_t, b80_1x2cdd_mcs0) ++#define WL_TX_POWER_80_S1x2_FIRST OFFSETOF(txppr_t, b80_1x2cdd_mcs0) ++#define WL_TX_POWER_MCS80_STBC_FIRST OFFSETOF(txppr_t, b80_2x2stbc_mcs0) ++#define WL_TX_POWER_MCS80_SDM_FIRST OFFSETOF(txppr_t, b80_2x2sdm_mcs8) ++#define WL_TX_POWER_80_S2x2_FIRST OFFSETOF(txppr_t, b80_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_80_DUMMY_CCK_CDD_S1x3_FIRST OFFSETOF(txppr_t, b80_dummy1x3dsss) ++#define WL_TX_POWER_OFDM80_CDD_S1x3_FIRST OFFSETOF(txppr_t, b80_1x3cdd_ofdm) ++#define WL_TX_POWER_80_S1x3_FIRST OFFSETOF(txppr_t, b80_1x3cdd_mcs0) ++#define WL_TX_POWER_80_STBC_S2x3_FIRST OFFSETOF(txppr_t, b80_2x3stbc_mcs0) ++#define WL_TX_POWER_80_S2x3_FIRST OFFSETOF(txppr_t, b80_2x3sdm_mcs8) ++#define WL_TX_POWER_80_S3x3_FIRST OFFSETOF(txppr_t, b80_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_80_S1X1_VHT OFFSETOF(txppr_t, b80_1x1vht) ++#define WL_TX_POWER_80_S1X2_CDD_VHT OFFSETOF(txppr_t, b80_1x2cdd_vht) ++#define WL_TX_POWER_80_S2X2_STBC_VHT OFFSETOF(txppr_t, b80_2x2stbc_vht) ++#define WL_TX_POWER_80_S2X2_VHT OFFSETOF(txppr_t, b80_2x2sdm_vht) ++#define WL_TX_POWER_80_S1X3_CDD_VHT OFFSETOF(txppr_t, b80_1x3cdd_vht) ++#define WL_TX_POWER_80_S2X3_STBC_VHT OFFSETOF(txppr_t, b80_2x3stbc_vht) ++#define WL_TX_POWER_80_S2X3_VHT OFFSETOF(txppr_t, b80_2x3sdm_vht) ++#define WL_TX_POWER_80_S3X3_VHT OFFSETOF(txppr_t, b80_3x3sdm_vht) ++ ++/* 20 in 80MHz */ ++#define WL_TX_POWER_20UUL_CCK_FIRST OFFSETOF(txppr_t, b20in80_1x1dsss) ++#define WL_TX_POWER_20UUL_OFDM_FIRST OFFSETOF(txppr_t, b20in80_1x1ofdm) ++#define WL_TX_POWER_20UUL_S1x1_FIRST OFFSETOF(txppr_t, b20in80_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_20UU_CDD_S1x2_FIRST OFFSETOF(txppr_t, b20in80_1x2dsss) ++#define WL_TX_POWER_20UUL_OFDM_CDD_FIRST OFFSETOF(txppr_t, b20in80_1x2cdd_ofdm) ++#define WL_TX_POWER_20UUL_S1x2_FIRST OFFSETOF(txppr_t, b20in80_1x2cdd_mcs0) ++#define WL_TX_POWER_20UUL_STBC_S2x2_FIRST OFFSETOF(txppr_t, b20in80_2x2stbc_mcs0) ++#define WL_TX_POWER_20UUL_S2x2_FIRST OFFSETOF(txppr_t, b20in80_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_20UU_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in80_1x3dsss) ++#define WL_TX_POWER_20UUL_OFDM_CDD_S1x3_FIRST OFFSETOF(txppr_t, b20in80_1x3cdd_ofdm) ++#define WL_TX_POWER_20UUL_S1x3_FIRST OFFSETOF(txppr_t, b20in80_1x3cdd_mcs0) ++#define WL_TX_POWER_20UUL_STBC_S2x3_FIRST OFFSETOF(txppr_t, b20in80_2x3stbc_mcs0) ++#define WL_TX_POWER_20UUL_S2x3_FIRST OFFSETOF(txppr_t, b20in80_2x3sdm_mcs8) ++#define WL_TX_POWER_20UUL_S3x3_FIRST OFFSETOF(txppr_t, b20in80_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_20UUL_S1X1_VHT OFFSETOF(txppr_t, b20in80_1x1vht) ++#define WL_TX_POWER_20UUL_S1X2_CDD_VHT OFFSETOF(txppr_t, b20in80_1x2cdd_vht) ++#define WL_TX_POWER_20UUL_S2X2_STBC_VHT OFFSETOF(txppr_t, b20in80_2x2stbc_vht) ++#define WL_TX_POWER_20UUL_S2X2_VHT OFFSETOF(txppr_t, b20in80_2x2sdm_vht) ++#define WL_TX_POWER_20UUL_S1X3_CDD_VHT OFFSETOF(txppr_t, b20in80_1x3cdd_vht) ++#define WL_TX_POWER_20UUL_S2X3_STBC_VHT OFFSETOF(txppr_t, b20in80_2x3stbc_vht) ++#define WL_TX_POWER_20UUL_S2X3_VHT OFFSETOF(txppr_t, b20in80_2x3sdm_vht) ++#define WL_TX_POWER_20UUL_S3X3_VHT OFFSETOF(txppr_t, b20in80_3x3sdm_vht) ++ ++/* 40 in 80MHz */ ++#define WL_TX_POWER_40UUL_DUMMY_CCK_FIRST OFFSETOF(txppr_t, b40in80_dummy1x1dsss) ++#define WL_TX_POWER_40UUL_OFDM_FIRST OFFSETOF(txppr_t, b40in80_1x1ofdm) ++#define WL_TX_POWER_40UUL_S1x1_FIRST OFFSETOF(txppr_t, b40in80_1x1mcs0) ++ ++#define WL_TX_POWER_CCK_40UU_DUMMY_CDD_S1x2_FIRST OFFSETOF(txppr_t, b40in80_dummy1x2dsss) ++#define WL_TX_POWER_40UUL_OFDM_CDD_FIRST OFFSETOF(txppr_t, b40in80_1x2cdd_ofdm) ++#define WL_TX_POWER_40UUL_S1x2_FIRST OFFSETOF(txppr_t, b40in80_1x2cdd_mcs0) ++#define WL_TX_POWER_40UUL_STBC_S2x2_FIRST OFFSETOF(txppr_t, b40in80_2x2stbc_mcs0) ++#define WL_TX_POWER_40UUL_S2x2_FIRST OFFSETOF(txppr_t, b40in80_2x2sdm_mcs8) ++ ++#define WL_TX_POWER_CCK_40UU_DUMMY_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40in80_dummy1x3dsss) ++#define WL_TX_POWER_40UUL_OFDM_CDD_S1x3_FIRST OFFSETOF(txppr_t, b40in80_1x3cdd_ofdm) ++#define WL_TX_POWER_40UUL_S1x3_FIRST OFFSETOF(txppr_t, b40in80_1x3cdd_mcs0) ++#define WL_TX_POWER_40UUL_STBC_S2x3_FIRST OFFSETOF(txppr_t, b40in80_2x3stbc_mcs0) ++#define WL_TX_POWER_40UUL_S2x3_FIRST OFFSETOF(txppr_t, b40in80_2x3sdm_mcs8) ++#define WL_TX_POWER_40UUL_S3x3_FIRST OFFSETOF(txppr_t, b40in80_3x3sdm_mcs16) ++ ++#define WL_TX_POWER_40UUL_S1X1_VHT OFFSETOF(txppr_t, b40in80_1x1vht) ++#define WL_TX_POWER_40UUL_S1X2_CDD_VHT OFFSETOF(txppr_t, b40in80_1x2cdd_vht) ++#define WL_TX_POWER_40UUL_S2X2_STBC_VHT OFFSETOF(txppr_t, b40in80_2x2stbc_vht) ++#define WL_TX_POWER_40UUL_S2X2_VHT OFFSETOF(txppr_t, b40in80_2x2sdm_vht) ++#define WL_TX_POWER_40UUL_S1X3_CDD_VHT OFFSETOF(txppr_t, b40in80_1x3cdd_vht) ++#define WL_TX_POWER_40UUL_S2X3_STBC_VHT OFFSETOF(txppr_t, b40in80_2x3stbc_vht) ++#define WL_TX_POWER_40UUL_S2X3_VHT OFFSETOF(txppr_t, b40in80_2x3sdm_vht) ++#define WL_TX_POWER_40UUL_S3X3_VHT OFFSETOF(txppr_t, b40in80_3x3sdm_vht) ++ ++#define WL_TX_POWER_MCS_32 OFFSETOF(txppr_t, mcs32) /* C_CHECK remove later */ ++ ++#define WL_TX_POWER_RATES sizeof(struct txppr) ++ ++/* sslpnphy specifics */ ++#define WL_TX_POWER_MCS20_SISO_FIRST_SSN WL_TX_POWER_MCS20_SISO_FIRST ++#define WL_TX_POWER_MCS40_SISO_FIRST_SSN WL_TX_POWER_MCS40_SISO_FIRST ++ ++/* tx_power_t.flags bits */ ++#define WL_TX_POWER_F_ENABLED 1 ++#define WL_TX_POWER_F_HW 2 ++#define WL_TX_POWER_F_MIMO 4 ++#define WL_TX_POWER_F_SISO 8 ++#define WL_TX_POWER_F_HT 0x10 ++ ++typedef struct { ++ uint16 ver; /* version of this struct */ ++ uint16 len; /* length in bytes of this structure */ ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 ppr[WL_TX_POWER_RATES]; /* Latest target power */ ++} wl_txppr_t; ++ ++#define WL_TXPPR_VERSION 0 ++#define WL_TXPPR_LENGTH (sizeof(wl_txppr_t)) ++#define TX_POWER_T_VERSION 43 ++ ++/* Defines used with channel_bandwidth for curpower */ ++#define WL_BW_20MHZ 0 ++#define WL_BW_40MHZ 1 ++#define WL_BW_80MHZ 2 ++ ++/* tx_power_t.flags bits */ ++#ifdef PPR_API ++#define WL_TX_POWER2_F_ENABLED 1 ++#define WL_TX_POWER2_F_HW 2 ++#define WL_TX_POWER2_F_MIMO 4 ++#define WL_TX_POWER2_F_SISO 8 ++#define WL_TX_POWER2_F_HT 0x10 ++#else ++#define WL_TX_POWER_F_ENABLED 1 ++#define WL_TX_POWER_F_HW 2 ++#define WL_TX_POWER_F_MIMO 4 ++#define WL_TX_POWER_F_SISO 8 ++#define WL_TX_POWER_F_HT 0x10 ++#endif ++typedef struct { ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 local_max; /* local max according to the AP */ ++ uint8 local_constraint; /* local constraint according to the AP */ ++ int8 antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 rf_cores; /* count of RF Cores being reported */ ++ uint8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ ++ uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain ++ * without adjustment ++ */ ++ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ ++ uint8 tx_power_max[4]; /* Maximum target power among all rates */ ++ uint tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */ ++ uint8 user_limit[WL_TX_POWER_RATES]; /* User limit */ ++ int8 board_limit[WL_TX_POWER_RATES]; /* Max power board can support (SROM) */ ++ int8 target[WL_TX_POWER_RATES]; /* Latest target power */ ++ int8 clm_limits[WL_NUMRATES]; /* regulatory limits - 20, 40 or 80MHz */ ++ int8 clm_limits_subchan1[WL_NUMRATES]; /* regulatory limits - 20in40 or 40in80 */ ++ int8 clm_limits_subchan2[WL_NUMRATES]; /* regulatory limits - 20in80MHz */ ++ int8 sar; /* SAR limit for display by wl executable */ ++ int8 channel_bandwidth; /* 20, 40 or 80 MHz bandwidth? */ ++ uint8 version; /* Version of the data format wlu <--> driver */ ++ uint8 display_core; /* Displayed curpower core */ ++#ifdef PPR_API ++} tx_power_new_t; ++#else ++} tx_power_t; ++#endif ++ ++typedef struct tx_inst_power { ++ uint8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ ++ uint8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ ++} tx_inst_power_t; ++ ++ ++typedef struct { ++ uint32 flags; ++ chanspec_t chanspec; /* txpwr report for this channel */ ++ chanspec_t local_chanspec; /* channel on which we are associated */ ++ uint8 local_max; /* local max according to the AP */ ++ uint8 local_constraint; /* local constraint according to the AP */ ++ int8 antgain[2]; /* Ant gain for each band - from SROM */ ++ uint8 rf_cores; /* count of RF Cores being reported */ ++ uint8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ ++ uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain ++ * without adjustment ++ */ ++ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ ++ uint8 tx_power_max[4]; /* Maximum target power among all rates */ ++ uint tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */ ++ txppr_t user_limit; /* User limit */ ++ txppr_t reg_limit; /* Regulatory power limit */ ++ txppr_t board_limit; /* Max power board can support (SROM) */ ++ txppr_t target; /* Latest target power */ ++} wl_txpwr_t; ++ ++#define WL_NUM_TXCHAIN_MAX 4 ++typedef struct wl_txchain_pwr_offsets { ++ int8 offset[WL_NUM_TXCHAIN_MAX]; /* quarter dBm signed offset for each chain */ ++} wl_txchain_pwr_offsets_t; ++ ++/* 802.11h measurement types */ ++#define WLC_MEASURE_TPC 1 ++#define WLC_MEASURE_CHANNEL_BASIC 2 ++#define WLC_MEASURE_CHANNEL_CCA 3 ++#define WLC_MEASURE_CHANNEL_RPI 4 ++ ++/* regulatory enforcement levels */ ++#define SPECT_MNGMT_OFF 0 /* both 11h and 11d disabled */ ++#define SPECT_MNGMT_LOOSE_11H 1 /* allow non-11h APs in scan lists */ ++#define SPECT_MNGMT_STRICT_11H 2 /* prune out non-11h APs from scan list */ ++#define SPECT_MNGMT_STRICT_11D 3 /* switch to 802.11D mode */ ++/* SPECT_MNGMT_LOOSE_11H_D - same as SPECT_MNGMT_LOOSE with the exception that Country IE ++ * adoption is done regardless of capability spectrum_management ++ */ ++#define SPECT_MNGMT_LOOSE_11H_D 4 /* operation defined above */ ++ ++#define WL_CHAN_VALID_HW (1 << 0) /* valid with current HW */ ++#define WL_CHAN_VALID_SW (1 << 1) /* valid with current country setting */ ++#define WL_CHAN_BAND_5G (1 << 2) /* 5GHz-band channel */ ++#define WL_CHAN_RADAR (1 << 3) /* radar sensitive channel */ ++#define WL_CHAN_INACTIVE (1 << 4) /* temporarily inactive due to radar */ ++#define WL_CHAN_PASSIVE (1 << 5) /* channel is in passive mode */ ++#define WL_CHAN_RESTRICTED (1 << 6) /* restricted use channel */ ++ ++/* BTC mode used by "btc_mode" iovar */ ++#define WL_BTC_DISABLE 0 /* disable BT coexistence */ ++#define WL_BTC_FULLTDM 1 /* full TDM COEX */ ++#define WL_BTC_ENABLE 1 /* full TDM COEX to maintain backward compatiblity */ ++#define WL_BTC_PREMPT 2 /* full TDM COEX with preemption */ ++#define WL_BTC_LITE 3 /* light weight coex for large isolation platform */ ++#define WL_BTC_PARALLEL 4 /* BT and WLAN run in parallel with separate antenna */ ++#define WL_BTC_HYBRID 5 /* hybrid coex, only ack is allowed to transmit in BT slot */ ++#define WL_BTC_DEFAULT 8 /* set the default mode for the device */ ++#define WL_INF_BTC_DISABLE 0 ++#define WL_INF_BTC_ENABLE 1 ++#define WL_INF_BTC_AUTO 3 ++ ++/* BTC wire used by "btc_wire" iovar */ ++#define WL_BTC_DEFWIRE 0 /* use default wire setting */ ++#define WL_BTC_2WIRE 2 /* use 2-wire BTC */ ++#define WL_BTC_3WIRE 3 /* use 3-wire BTC */ ++#define WL_BTC_4WIRE 4 /* use 4-wire BTC */ ++ ++/* BTC flags: BTC configuration that can be set by host */ ++#define WL_BTC_FLAG_PREMPT (1 << 0) ++#define WL_BTC_FLAG_BT_DEF (1 << 1) ++#define WL_BTC_FLAG_ACTIVE_PROT (1 << 2) ++#define WL_BTC_FLAG_SIM_RSP (1 << 3) ++#define WL_BTC_FLAG_PS_PROTECT (1 << 4) ++#define WL_BTC_FLAG_SIM_TX_LP (1 << 5) ++#define WL_BTC_FLAG_ECI (1 << 6) ++#define WL_BTC_FLAG_LIGHT (1 << 7) ++#define WL_BTC_FLAG_PARALLEL (1 << 8) ++ ++/* Message levels */ ++#define WL_ERROR_VAL 0x00000001 ++#define WL_TRACE_VAL 0x00000002 ++#define WL_PRHDRS_VAL 0x00000004 ++#define WL_PRPKT_VAL 0x00000008 ++#define WL_INFORM_VAL 0x00000010 ++#define WL_TMP_VAL 0x00000020 ++#define WL_OID_VAL 0x00000040 ++#define WL_RATE_VAL 0x00000080 ++#define WL_ASSOC_VAL 0x00000100 ++#define WL_PRUSR_VAL 0x00000200 ++#define WL_PS_VAL 0x00000400 ++#define WL_TXPWR_VAL 0x00000800 /* retired in TOT on 6/10/2009 */ ++#define WL_PORT_VAL 0x00001000 ++#define WL_DUAL_VAL 0x00002000 ++#define WL_WSEC_VAL 0x00004000 ++#define WL_WSEC_DUMP_VAL 0x00008000 ++#define WL_LOG_VAL 0x00010000 ++#define WL_NRSSI_VAL 0x00020000 /* retired in TOT on 6/10/2009 */ ++#define WL_LOFT_VAL 0x00040000 /* retired in TOT on 6/10/2009 */ ++#define WL_REGULATORY_VAL 0x00080000 ++#define WL_PHYCAL_VAL 0x00100000 /* retired in TOT on 6/10/2009 */ ++#define WL_RADAR_VAL 0x00200000 /* retired in TOT on 6/10/2009 */ ++#define WL_MPC_VAL 0x00400000 ++#define WL_APSTA_VAL 0x00800000 ++#define WL_DFS_VAL 0x01000000 ++#define WL_BA_VAL 0x02000000 /* retired in TOT on 6/14/2010 */ ++#define WL_ACI_VAL 0x04000000 ++#define WL_MBSS_VAL 0x04000000 ++#define WL_CAC_VAL 0x08000000 ++#define WL_AMSDU_VAL 0x10000000 ++#define WL_AMPDU_VAL 0x20000000 ++#define WL_FFPLD_VAL 0x40000000 ++ ++/* wl_msg_level is full. For new bits take the next one and AND with ++ * wl_msg_level2 in wl_dbg.h ++ */ ++#define WL_DPT_VAL 0x00000001 ++#define WL_SCAN_VAL 0x00000002 ++#define WL_WOWL_VAL 0x00000004 ++#define WL_COEX_VAL 0x00000008 ++#define WL_RTDC_VAL 0x00000010 ++#define WL_PROTO_VAL 0x00000020 ++#define WL_BTA_VAL 0x00000040 ++#define WL_CHANINT_VAL 0x00000080 ++#define WL_THERMAL_VAL 0x00000100 /* retired in TOT on 6/10/2009 */ ++#define WL_P2P_VAL 0x00000200 ++#define WL_ITFR_VAL 0x00000400 ++#define WL_MCHAN_VAL 0x00000800 ++#define WL_TDLS_VAL 0x00001000 ++#define WL_MCNX_VAL 0x00002000 ++#define WL_PROT_VAL 0x00004000 ++#define WL_PSTA_VAL 0x00008000 ++#define WL_TBTT_VAL 0x00010000 ++#define WL_NIC_VAL 0x00020000 ++#define WL_PWRSEL_VAL 0x00040000 ++/* use top-bit for WL_TIME_STAMP_VAL because this is a modifier ++ * rather than a message-type of its own ++ */ ++#define WL_TIMESTAMP_VAL 0x80000000 ++ ++/* max # of leds supported by GPIO (gpio pin# == led index#) */ ++#define WL_LED_NUMGPIO 32 /* gpio 0-31 */ ++ ++/* led per-pin behaviors */ ++#define WL_LED_OFF 0 /* always off */ ++#define WL_LED_ON 1 /* always on */ ++#define WL_LED_ACTIVITY 2 /* activity */ ++#define WL_LED_RADIO 3 /* radio enabled */ ++#define WL_LED_ARADIO 4 /* 5 Ghz radio enabled */ ++#define WL_LED_BRADIO 5 /* 2.4Ghz radio enabled */ ++#define WL_LED_BGMODE 6 /* on if gmode, off if bmode */ ++#define WL_LED_WI1 7 ++#define WL_LED_WI2 8 ++#define WL_LED_WI3 9 ++#define WL_LED_ASSOC 10 /* associated state indicator */ ++#define WL_LED_INACTIVE 11 /* null behavior (clears default behavior) */ ++#define WL_LED_ASSOCACT 12 /* on when associated; blink fast for activity */ ++#define WL_LED_WI4 13 ++#define WL_LED_WI5 14 ++#define WL_LED_BLINKSLOW 15 /* blink slow */ ++#define WL_LED_BLINKMED 16 /* blink med */ ++#define WL_LED_BLINKFAST 17 /* blink fast */ ++#define WL_LED_BLINKCUSTOM 18 /* blink custom */ ++#define WL_LED_BLINKPERIODIC 19 /* blink periodic (custom 1000ms / off 400ms) */ ++#define WL_LED_ASSOC_WITH_SEC 20 /* when connected with security */ ++ /* keep on for 300 sec */ ++#define WL_LED_START_OFF 21 /* off upon boot, could be turned on later */ ++#define WL_LED_NUMBEHAVIOR 22 ++ ++/* led behavior numeric value format */ ++#define WL_LED_BEH_MASK 0x7f /* behavior mask */ ++#define WL_LED_AL_MASK 0x80 /* activelow (polarity) bit */ ++ ++/* maximum channels returned by the get valid channels iovar */ ++#define WL_NUMCHANNELS 64 ++ ++/* max number of chanspecs (used by the iovar to calc. buf space) */ ++#define WL_NUMCHANSPECS 110 ++ ++/* WDS link local endpoint WPA role */ ++#define WL_WDS_WPA_ROLE_AUTH 0 /* authenticator */ ++#define WL_WDS_WPA_ROLE_SUP 1 /* supplicant */ ++#define WL_WDS_WPA_ROLE_AUTO 255 /* auto, based on mac addr value */ ++ ++/* number of bytes needed to define a 128-bit mask for MAC event reporting */ ++#define WL_EVENTING_MASK_LEN 16 ++ ++/* ++ * Join preference iovar value is an array of tuples. Each tuple has a one-byte type, ++ * a one-byte length, and a variable length value. RSSI type tuple must be present ++ * in the array. ++ * ++ * Types are defined in "join preference types" section. ++ * ++ * Length is the value size in octets. It is reserved for WL_JOIN_PREF_WPA type tuple ++ * and must be set to zero. ++ * ++ * Values are defined below. ++ * ++ * 1. RSSI - 2 octets ++ * offset 0: reserved ++ * offset 1: reserved ++ * ++ * 2. WPA - 2 + 12 * n octets (n is # tuples defined below) ++ * offset 0: reserved ++ * offset 1: # of tuples ++ * offset 2: tuple 1 ++ * offset 14: tuple 2 ++ * ... ++ * offset 2 + 12 * (n - 1) octets: tuple n ++ * ++ * struct wpa_cfg_tuple { ++ * uint8 akm[DOT11_OUI_LEN+1]; akm suite ++ * uint8 ucipher[DOT11_OUI_LEN+1]; unicast cipher suite ++ * uint8 mcipher[DOT11_OUI_LEN+1]; multicast cipher suite ++ * }; ++ * ++ * multicast cipher suite can be specified as a specific cipher suite or WL_WPA_ACP_MCS_ANY. ++ * ++ * 3. BAND - 2 octets ++ * offset 0: reserved ++ * offset 1: see "band preference" and "band types" ++ * ++ * 4. BAND RSSI - 2 octets ++ * offset 0: band types ++ * offset 1: +ve RSSI boost balue in dB ++ */ ++ ++/* join preference types */ ++#define WL_JOIN_PREF_RSSI 1 /* by RSSI */ ++#define WL_JOIN_PREF_WPA 2 /* by akm and ciphers */ ++#define WL_JOIN_PREF_BAND 3 /* by 802.11 band */ ++#define WL_JOIN_PREF_RSSI_DELTA 4 /* by 802.11 band only if RSSI delta condition matches */ ++#define WL_JOIN_PREF_TRANS_PREF 5 /* defined by requesting AP */ ++ ++/* band preference */ ++#define WLJP_BAND_ASSOC_PREF 255 /* use what WLC_SET_ASSOC_PREFER ioctl specifies */ ++ ++/* any multicast cipher suite */ ++#define WL_WPA_ACP_MCS_ANY "\x00\x00\x00\x00" ++ ++struct tsinfo_arg { ++ uint8 octets[3]; ++}; ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++#define NFIFO 6 /* # tx/rx fifopairs */ ++ ++#define WL_CNT_T_VERSION 8 /* current version of wl_cnt_t struct */ ++ ++typedef struct { ++ uint16 version; /* see definition of WL_CNT_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txframe; /* tx data frames */ ++ uint32 txbyte; /* tx data bytes */ ++ uint32 txretrans; /* tx mac retransmits */ ++ uint32 txerror; /* tx data errors (derived: sum of others) */ ++ uint32 txctl; /* tx management frames */ ++ uint32 txprshort; /* tx short preamble frames */ ++ uint32 txserr; /* tx status errors */ ++ uint32 txnobuf; /* tx out of buffers errors */ ++ uint32 txnoassoc; /* tx discard because we're not associated */ ++ uint32 txrunt; /* tx runt frames */ ++ uint32 txchit; /* tx header cache hit (fastpath) */ ++ uint32 txcmiss; /* tx header cache miss (slowpath) */ ++ ++ /* transmit chip error counters */ ++ uint32 txuflo; /* tx fifo underflows */ ++ uint32 txphyerr; /* tx phy errors (indicated in tx status) */ ++ uint32 txphycrs; ++ ++ /* receive stat counters */ ++ uint32 rxframe; /* rx data frames */ ++ uint32 rxbyte; /* rx data bytes */ ++ uint32 rxerror; /* rx data errors (derived: sum of others) */ ++ uint32 rxctl; /* rx management frames */ ++ uint32 rxnobuf; /* rx out of buffers errors */ ++ uint32 rxnondata; /* rx non data frames in the data channel errors */ ++ uint32 rxbadds; /* rx bad DS errors */ ++ uint32 rxbadcm; /* rx bad control or management frames */ ++ uint32 rxfragerr; /* rx fragmentation errors */ ++ uint32 rxrunt; /* rx runt frames */ ++ uint32 rxgiant; /* rx giant frames */ ++ uint32 rxnoscb; /* rx no scb error */ ++ uint32 rxbadproto; /* rx invalid frames */ ++ uint32 rxbadsrcmac; /* rx frames with Invalid Src Mac */ ++ uint32 rxbadda; /* rx frames tossed for invalid da */ ++ uint32 rxfilter; /* rx frames filtered out */ ++ ++ /* receive chip error counters */ ++ uint32 rxoflo; /* rx fifo overflow errors */ ++ uint32 rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ ++ ++ uint32 d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ ++ uint32 d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ ++ uint32 d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ ++ ++ /* misc counters */ ++ uint32 dmade; /* tx/rx dma descriptor errors */ ++ uint32 dmada; /* tx/rx dma data errors */ ++ uint32 dmape; /* tx/rx dma descriptor protocol errors */ ++ uint32 reset; /* reset count */ ++ uint32 tbtt; /* cnts the TBTT int's */ ++ uint32 txdmawar; ++ uint32 pkt_callback_reg_fail; /* callbacks register failure */ ++ ++ /* MAC counters: 32-bit version of d11.h's macstat_t */ ++ uint32 txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, ++ * Control Management (includes retransmissions) ++ */ ++ uint32 txrtsfrm; /* number of RTS sent out by the MAC */ ++ uint32 txctsfrm; /* number of CTS sent out by the MAC */ ++ uint32 txackfrm; /* number of ACK frames sent out */ ++ uint32 txdnlfrm; /* Not used */ ++ uint32 txbcnfrm; /* beacons transmitted */ ++ uint32 txfunfl[8]; /* per-fifo tx underflows */ ++ uint32 txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS ++ * or BCN) ++ */ ++ uint32 txphyerror; /* Transmit phy error, type of error is reported in tx-status for ++ * driver enqueued frames ++ */ ++ uint32 rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ ++ uint32 rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ ++ uint32 rxinvmachdr; /* Either the protocol version != 0 or frame type not ++ * data/control/management ++ */ ++ uint32 rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ ++ uint32 rxbadplcp; /* parity check of the PLCP header failed */ ++ uint32 rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ ++ uint32 rxstrt; /* Number of received frames with a good PLCP ++ * (i.e. passing parity check) ++ */ ++ uint32 rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ ++ uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ ++ uint32 rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ ++ uint32 rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ ++ uint32 rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ ++ uint32 rxackucast; /* number of ucast ACKS received (good FCS) */ ++ uint32 rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ ++ uint32 rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ ++ uint32 rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ ++ uint32 rxrtsocast; /* number of received RTS not addressed to the MAC */ ++ uint32 rxctsocast; /* number of received CTS not addressed to the MAC */ ++ uint32 rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ ++ uint32 rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ ++ uint32 rxcfrmmcast; /* number of RX Control multicast frames received by the MAC ++ * (unlikely to see these) ++ */ ++ uint32 rxbeaconmbss; /* beacons received from member of BSS */ ++ uint32 rxdfrmucastobss; /* number of unicast frames addressed to the MAC from ++ * other BSS (WDS FRAME) ++ */ ++ uint32 rxbeaconobss; /* beacons received from other BSS */ ++ uint32 rxrsptmout; /* Number of response timeouts for transmitted frames ++ * expecting a response ++ */ ++ uint32 bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ ++ uint32 rxf0ovfl; /* Number of receive fifo 0 overflows */ ++ uint32 rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ ++ uint32 rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ ++ uint32 txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ ++ uint32 pmqovfl; /* Number of PMQ overflows */ ++ uint32 rxcgprqfrm; /* Number of received Probe requests that made it into ++ * the PRQ fifo ++ */ ++ uint32 rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ ++ uint32 txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did ++ * not get ACK ++ */ ++ uint32 txcgprssuc; /* Tx Probe Response Success (ACK was received) */ ++ uint32 prs_timeout; /* Number of probe requests that were dropped from the PRQ ++ * fifo because a probe response could not be sent out within ++ * the time limit defined in M_PRS_MAXTIME ++ */ ++ uint32 rxnack; /* obsolete */ ++ uint32 frmscons; /* obsolete */ ++ uint32 txnack; /* obsolete */ ++ uint32 txglitch_nack; /* obsolete */ ++ uint32 txburst; /* obsolete */ ++ ++ /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ ++ uint32 txfrag; /* dot11TransmittedFragmentCount */ ++ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ ++ uint32 txfail; /* dot11FailedCount */ ++ uint32 txretry; /* dot11RetryCount */ ++ uint32 txretrie; /* dot11MultipleRetryCount */ ++ uint32 rxdup; /* dot11FrameduplicateCount */ ++ uint32 txrts; /* dot11RTSSuccessCount */ ++ uint32 txnocts; /* dot11RTSFailureCount */ ++ uint32 txnoack; /* dot11ACKFailureCount */ ++ uint32 rxfrag; /* dot11ReceivedFragmentCount */ ++ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ ++ uint32 rxcrc; /* dot11FCSErrorCount */ ++ uint32 txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ ++ uint32 rxundec; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay; /* TKIPReplays */ ++ uint32 ccmpfmterr; /* CCMPFormatErrors */ ++ uint32 ccmpreplay; /* CCMPReplays */ ++ uint32 ccmpundec; /* CCMPDecryptErrors */ ++ uint32 fourwayfail; /* FourWayHandshakeFailures */ ++ uint32 wepundec; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess; /* DecryptSuccessCount */ ++ uint32 tkipicverr; /* TKIPICVErrorCount */ ++ uint32 wepexcluded; /* dot11WEPExcludedCount */ ++ ++ uint32 txchanrej; /* Tx frames suppressed due to channel rejection */ ++ uint32 psmwds; /* Count PSM watchdogs */ ++ uint32 phywatchdog; /* Count Phy watchdogs (triggered by ucode) */ ++ ++ /* MBSS counters, AP only */ ++ uint32 prq_entries_handled; /* PRQ entries read in */ ++ uint32 prq_undirected_entries; /* which were bcast bss & ssid */ ++ uint32 prq_bad_entries; /* which could not be translated to info */ ++ uint32 atim_suppress_count; /* TX suppressions on ATIM fifo */ ++ uint32 bcn_template_not_ready; /* Template marked in use on send bcn ... */ ++ uint32 bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */ ++ uint32 late_tbtt_dpc; /* TBTT DPC did not happen in time */ ++ ++ /* per-rate receive stat counters */ ++ uint32 rx1mbps; /* packets rx at 1Mbps */ ++ uint32 rx2mbps; /* packets rx at 2Mbps */ ++ uint32 rx5mbps5; /* packets rx at 5.5Mbps */ ++ uint32 rx6mbps; /* packets rx at 6Mbps */ ++ uint32 rx9mbps; /* packets rx at 9Mbps */ ++ uint32 rx11mbps; /* packets rx at 11Mbps */ ++ uint32 rx12mbps; /* packets rx at 12Mbps */ ++ uint32 rx18mbps; /* packets rx at 18Mbps */ ++ uint32 rx24mbps; /* packets rx at 24Mbps */ ++ uint32 rx36mbps; /* packets rx at 36Mbps */ ++ uint32 rx48mbps; /* packets rx at 48Mbps */ ++ uint32 rx54mbps; /* packets rx at 54Mbps */ ++ uint32 rx108mbps; /* packets rx at 108mbps */ ++ uint32 rx162mbps; /* packets rx at 162mbps */ ++ uint32 rx216mbps; /* packets rx at 216 mbps */ ++ uint32 rx270mbps; /* packets rx at 270 mbps */ ++ uint32 rx324mbps; /* packets rx at 324 mbps */ ++ uint32 rx378mbps; /* packets rx at 378 mbps */ ++ uint32 rx432mbps; /* packets rx at 432 mbps */ ++ uint32 rx486mbps; /* packets rx at 486 mbps */ ++ uint32 rx540mbps; /* packets rx at 540 mbps */ ++ ++ /* pkteng rx frame stats */ ++ uint32 pktengrxducast; /* unicast frames rxed by the pkteng code */ ++ uint32 pktengrxdmcast; /* multicast frames rxed by the pkteng code */ ++ ++ uint32 rfdisable; /* count of radio disables */ ++ uint32 bphy_rxcrsglitch; /* PHY count of bphy glitches */ ++ ++ uint32 txexptime; /* Tx frames suppressed due to timer expiration */ ++ ++ uint32 txmpdu_sgi; /* count for sgi transmit */ ++ uint32 rxmpdu_sgi; /* count for sgi received */ ++ uint32 txmpdu_stbc; /* count for stbc transmit */ ++ uint32 rxmpdu_stbc; /* count for stbc received */ ++ ++ uint32 rxundec_mcst; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill_mcst; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay_mcst; /* TKIPReplays */ ++ uint32 ccmpfmterr_mcst; /* CCMPFormatErrors */ ++ uint32 ccmpreplay_mcst; /* CCMPReplays */ ++ uint32 ccmpundec_mcst; /* CCMPDecryptErrors */ ++ uint32 fourwayfail_mcst; /* FourWayHandshakeFailures */ ++ uint32 wepundec_mcst; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr_mcst; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess_mcst; /* DecryptSuccessCount */ ++ uint32 tkipicverr_mcst; /* TKIPICVErrorCount */ ++ uint32 wepexcluded_mcst; /* dot11WEPExcludedCount */ ++ ++ uint32 dma_hang; /* count for dma hang */ ++ uint32 reinit; /* count for reinit */ ++ ++ uint32 pstatxucast; /* count of ucast frames xmitted on all psta assoc */ ++ uint32 pstatxnoassoc; /* count of txnoassoc frames xmitted on all psta assoc */ ++ uint32 pstarxucast; /* count of ucast frames received on all psta assoc */ ++ uint32 pstarxbcmc; /* count of bcmc frames received on all psta */ ++ uint32 pstatxbcmc; /* count of bcmc frames transmitted on all psta */ ++ ++ uint32 cso_passthrough; /* hw cso required but passthrough */ ++} wl_cnt_t; ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++typedef struct { ++ uint16 version; /* see definition of WL_CNT_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txframe; /* tx data frames */ ++ uint32 txbyte; /* tx data bytes */ ++ uint32 txretrans; /* tx mac retransmits */ ++ uint32 txerror; /* tx data errors (derived: sum of others) */ ++ uint32 txctl; /* tx management frames */ ++ uint32 txprshort; /* tx short preamble frames */ ++ uint32 txserr; /* tx status errors */ ++ uint32 txnobuf; /* tx out of buffers errors */ ++ uint32 txnoassoc; /* tx discard because we're not associated */ ++ uint32 txrunt; /* tx runt frames */ ++ uint32 txchit; /* tx header cache hit (fastpath) */ ++ uint32 txcmiss; /* tx header cache miss (slowpath) */ ++ ++ /* transmit chip error counters */ ++ uint32 txuflo; /* tx fifo underflows */ ++ uint32 txphyerr; /* tx phy errors (indicated in tx status) */ ++ uint32 txphycrs; ++ ++ /* receive stat counters */ ++ uint32 rxframe; /* rx data frames */ ++ uint32 rxbyte; /* rx data bytes */ ++ uint32 rxerror; /* rx data errors (derived: sum of others) */ ++ uint32 rxctl; /* rx management frames */ ++ uint32 rxnobuf; /* rx out of buffers errors */ ++ uint32 rxnondata; /* rx non data frames in the data channel errors */ ++ uint32 rxbadds; /* rx bad DS errors */ ++ uint32 rxbadcm; /* rx bad control or management frames */ ++ uint32 rxfragerr; /* rx fragmentation errors */ ++ uint32 rxrunt; /* rx runt frames */ ++ uint32 rxgiant; /* rx giant frames */ ++ uint32 rxnoscb; /* rx no scb error */ ++ uint32 rxbadproto; /* rx invalid frames */ ++ uint32 rxbadsrcmac; /* rx frames with Invalid Src Mac */ ++ uint32 rxbadda; /* rx frames tossed for invalid da */ ++ uint32 rxfilter; /* rx frames filtered out */ ++ ++ /* receive chip error counters */ ++ uint32 rxoflo; /* rx fifo overflow errors */ ++ uint32 rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ ++ ++ uint32 d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ ++ uint32 d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ ++ uint32 d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ ++ ++ /* misc counters */ ++ uint32 dmade; /* tx/rx dma descriptor errors */ ++ uint32 dmada; /* tx/rx dma data errors */ ++ uint32 dmape; /* tx/rx dma descriptor protocol errors */ ++ uint32 reset; /* reset count */ ++ uint32 tbtt; /* cnts the TBTT int's */ ++ uint32 txdmawar; ++ uint32 pkt_callback_reg_fail; /* callbacks register failure */ ++ ++ /* MAC counters: 32-bit version of d11.h's macstat_t */ ++ uint32 txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, ++ * Control Management (includes retransmissions) ++ */ ++ uint32 txrtsfrm; /* number of RTS sent out by the MAC */ ++ uint32 txctsfrm; /* number of CTS sent out by the MAC */ ++ uint32 txackfrm; /* number of ACK frames sent out */ ++ uint32 txdnlfrm; /* Not used */ ++ uint32 txbcnfrm; /* beacons transmitted */ ++ uint32 txfunfl[8]; /* per-fifo tx underflows */ ++ uint32 txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS ++ * or BCN) ++ */ ++ uint32 txphyerror; /* Transmit phy error, type of error is reported in tx-status for ++ * driver enqueued frames ++ */ ++ uint32 rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ ++ uint32 rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ ++ uint32 rxinvmachdr; /* Either the protocol version != 0 or frame type not ++ * data/control/management ++ */ ++ uint32 rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ ++ uint32 rxbadplcp; /* parity check of the PLCP header failed */ ++ uint32 rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ ++ uint32 rxstrt; /* Number of received frames with a good PLCP ++ * (i.e. passing parity check) ++ */ ++ uint32 rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ ++ uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ ++ uint32 rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ ++ uint32 rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ ++ uint32 rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ ++ uint32 rxackucast; /* number of ucast ACKS received (good FCS) */ ++ uint32 rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ ++ uint32 rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ ++ uint32 rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ ++ uint32 rxrtsocast; /* number of received RTS not addressed to the MAC */ ++ uint32 rxctsocast; /* number of received CTS not addressed to the MAC */ ++ uint32 rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ ++ uint32 rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ ++ uint32 rxcfrmmcast; /* number of RX Control multicast frames received by the MAC ++ * (unlikely to see these) ++ */ ++ uint32 rxbeaconmbss; /* beacons received from member of BSS */ ++ uint32 rxdfrmucastobss; /* number of unicast frames addressed to the MAC from ++ * other BSS (WDS FRAME) ++ */ ++ uint32 rxbeaconobss; /* beacons received from other BSS */ ++ uint32 rxrsptmout; /* Number of response timeouts for transmitted frames ++ * expecting a response ++ */ ++ uint32 bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ ++ uint32 rxf0ovfl; /* Number of receive fifo 0 overflows */ ++ uint32 rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ ++ uint32 rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ ++ uint32 txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ ++ uint32 pmqovfl; /* Number of PMQ overflows */ ++ uint32 rxcgprqfrm; /* Number of received Probe requests that made it into ++ * the PRQ fifo ++ */ ++ uint32 rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ ++ uint32 txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did ++ * not get ACK ++ */ ++ uint32 txcgprssuc; /* Tx Probe Response Success (ACK was received) */ ++ uint32 prs_timeout; /* Number of probe requests that were dropped from the PRQ ++ * fifo because a probe response could not be sent out within ++ * the time limit defined in M_PRS_MAXTIME ++ */ ++ uint32 rxnack; ++ uint32 frmscons; ++ uint32 txnack; ++ uint32 txglitch_nack; /* obsolete */ ++ uint32 txburst; /* obsolete */ ++ ++ /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ ++ uint32 txfrag; /* dot11TransmittedFragmentCount */ ++ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ ++ uint32 txfail; /* dot11FailedCount */ ++ uint32 txretry; /* dot11RetryCount */ ++ uint32 txretrie; /* dot11MultipleRetryCount */ ++ uint32 rxdup; /* dot11FrameduplicateCount */ ++ uint32 txrts; /* dot11RTSSuccessCount */ ++ uint32 txnocts; /* dot11RTSFailureCount */ ++ uint32 txnoack; /* dot11ACKFailureCount */ ++ uint32 rxfrag; /* dot11ReceivedFragmentCount */ ++ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ ++ uint32 rxcrc; /* dot11FCSErrorCount */ ++ uint32 txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ ++ uint32 rxundec; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay; /* TKIPReplays */ ++ uint32 ccmpfmterr; /* CCMPFormatErrors */ ++ uint32 ccmpreplay; /* CCMPReplays */ ++ uint32 ccmpundec; /* CCMPDecryptErrors */ ++ uint32 fourwayfail; /* FourWayHandshakeFailures */ ++ uint32 wepundec; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess; /* DecryptSuccessCount */ ++ uint32 tkipicverr; /* TKIPICVErrorCount */ ++ uint32 wepexcluded; /* dot11WEPExcludedCount */ ++ ++ uint32 rxundec_mcst; /* dot11WEPUndecryptableCount */ ++ ++ /* WPA2 counters (see rxundec for DecryptFailureCount) */ ++ uint32 tkipmicfaill_mcst; /* TKIPLocalMICFailures */ ++ uint32 tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */ ++ uint32 tkipreplay_mcst; /* TKIPReplays */ ++ uint32 ccmpfmterr_mcst; /* CCMPFormatErrors */ ++ uint32 ccmpreplay_mcst; /* CCMPReplays */ ++ uint32 ccmpundec_mcst; /* CCMPDecryptErrors */ ++ uint32 fourwayfail_mcst; /* FourWayHandshakeFailures */ ++ uint32 wepundec_mcst; /* dot11WEPUndecryptableCount */ ++ uint32 wepicverr_mcst; /* dot11WEPICVErrorCount */ ++ uint32 decsuccess_mcst; /* DecryptSuccessCount */ ++ uint32 tkipicverr_mcst; /* TKIPICVErrorCount */ ++ uint32 wepexcluded_mcst; /* dot11WEPExcludedCount */ ++ ++ uint32 txchanrej; /* Tx frames suppressed due to channel rejection */ ++ uint32 txexptime; /* Tx frames suppressed due to timer expiration */ ++ uint32 psmwds; /* Count PSM watchdogs */ ++ uint32 phywatchdog; /* Count Phy watchdogs (triggered by ucode) */ ++ ++ /* MBSS counters, AP only */ ++ uint32 prq_entries_handled; /* PRQ entries read in */ ++ uint32 prq_undirected_entries; /* which were bcast bss & ssid */ ++ uint32 prq_bad_entries; /* which could not be translated to info */ ++ uint32 atim_suppress_count; /* TX suppressions on ATIM fifo */ ++ uint32 bcn_template_not_ready; /* Template marked in use on send bcn ... */ ++ uint32 bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */ ++ uint32 late_tbtt_dpc; /* TBTT DPC did not happen in time */ ++ ++ /* per-rate receive stat counters */ ++ uint32 rx1mbps; /* packets rx at 1Mbps */ ++ uint32 rx2mbps; /* packets rx at 2Mbps */ ++ uint32 rx5mbps5; /* packets rx at 5.5Mbps */ ++ uint32 rx6mbps; /* packets rx at 6Mbps */ ++ uint32 rx9mbps; /* packets rx at 9Mbps */ ++ uint32 rx11mbps; /* packets rx at 11Mbps */ ++ uint32 rx12mbps; /* packets rx at 12Mbps */ ++ uint32 rx18mbps; /* packets rx at 18Mbps */ ++ uint32 rx24mbps; /* packets rx at 24Mbps */ ++ uint32 rx36mbps; /* packets rx at 36Mbps */ ++ uint32 rx48mbps; /* packets rx at 48Mbps */ ++ uint32 rx54mbps; /* packets rx at 54Mbps */ ++ uint32 rx108mbps; /* packets rx at 108mbps */ ++ uint32 rx162mbps; /* packets rx at 162mbps */ ++ uint32 rx216mbps; /* packets rx at 216 mbps */ ++ uint32 rx270mbps; /* packets rx at 270 mbps */ ++ uint32 rx324mbps; /* packets rx at 324 mbps */ ++ uint32 rx378mbps; /* packets rx at 378 mbps */ ++ uint32 rx432mbps; /* packets rx at 432 mbps */ ++ uint32 rx486mbps; /* packets rx at 486 mbps */ ++ uint32 rx540mbps; /* packets rx at 540 mbps */ ++ ++ /* pkteng rx frame stats */ ++ uint32 pktengrxducast; /* unicast frames rxed by the pkteng code */ ++ uint32 pktengrxdmcast; /* multicast frames rxed by the pkteng code */ ++ ++ uint32 rfdisable; /* count of radio disables */ ++ uint32 bphy_rxcrsglitch; /* PHY count of bphy glitches */ ++ ++ uint32 txmpdu_sgi; /* count for sgi transmit */ ++ uint32 rxmpdu_sgi; /* count for sgi received */ ++ uint32 txmpdu_stbc; /* count for stbc transmit */ ++ uint32 rxmpdu_stbc; /* count for stbc received */ ++} wl_cnt_ver_six_t; ++ ++#define WL_DELTA_STATS_T_VERSION 1 /* current version of wl_delta_stats_t struct */ ++ ++typedef struct { ++ uint16 version; /* see definition of WL_DELTA_STATS_T_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txframe; /* tx data frames */ ++ uint32 txbyte; /* tx data bytes */ ++ uint32 txretrans; /* tx mac retransmits */ ++ uint32 txfail; /* tx failures */ ++ ++ /* receive stat counters */ ++ uint32 rxframe; /* rx data frames */ ++ uint32 rxbyte; /* rx data bytes */ ++ ++ /* per-rate receive stat counters */ ++ uint32 rx1mbps; /* packets rx at 1Mbps */ ++ uint32 rx2mbps; /* packets rx at 2Mbps */ ++ uint32 rx5mbps5; /* packets rx at 5.5Mbps */ ++ uint32 rx6mbps; /* packets rx at 6Mbps */ ++ uint32 rx9mbps; /* packets rx at 9Mbps */ ++ uint32 rx11mbps; /* packets rx at 11Mbps */ ++ uint32 rx12mbps; /* packets rx at 12Mbps */ ++ uint32 rx18mbps; /* packets rx at 18Mbps */ ++ uint32 rx24mbps; /* packets rx at 24Mbps */ ++ uint32 rx36mbps; /* packets rx at 36Mbps */ ++ uint32 rx48mbps; /* packets rx at 48Mbps */ ++ uint32 rx54mbps; /* packets rx at 54Mbps */ ++ uint32 rx108mbps; /* packets rx at 108mbps */ ++ uint32 rx162mbps; /* packets rx at 162mbps */ ++ uint32 rx216mbps; /* packets rx at 216 mbps */ ++ uint32 rx270mbps; /* packets rx at 270 mbps */ ++ uint32 rx324mbps; /* packets rx at 324 mbps */ ++ uint32 rx378mbps; /* packets rx at 378 mbps */ ++ uint32 rx432mbps; /* packets rx at 432 mbps */ ++ uint32 rx486mbps; /* packets rx at 486 mbps */ ++ uint32 rx540mbps; /* packets rx at 540 mbps */ ++} wl_delta_stats_t; ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++#define WL_WME_CNT_VERSION 1 /* current version of wl_wme_cnt_t */ ++ ++typedef struct { ++ uint32 packets; ++ uint32 bytes; ++} wl_traffic_stats_t; ++ ++typedef struct { ++ uint16 version; /* see definition of WL_WME_CNT_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ wl_traffic_stats_t tx[AC_COUNT]; /* Packets transmitted */ ++ wl_traffic_stats_t tx_failed[AC_COUNT]; /* Packets dropped or failed to transmit */ ++ wl_traffic_stats_t rx[AC_COUNT]; /* Packets received */ ++ wl_traffic_stats_t rx_failed[AC_COUNT]; /* Packets failed to receive */ ++ ++ wl_traffic_stats_t forward[AC_COUNT]; /* Packets forwarded by AP */ ++ ++ wl_traffic_stats_t tx_expired[AC_COUNT]; /* packets dropped due to lifetime expiry */ ++ ++} wl_wme_cnt_t; ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++struct wl_msglevel2 { ++ uint32 low; ++ uint32 high; ++}; ++ ++typedef struct wl_mkeep_alive_pkt { ++ uint16 version; /* Version for mkeep_alive */ ++ uint16 length; /* length of fixed parameters in the structure */ ++ uint32 period_msec; ++ uint16 len_bytes; ++ uint8 keep_alive_id; /* 0 - 3 for N = 4 */ ++ uint8 data[1]; ++} wl_mkeep_alive_pkt_t; ++ ++#define WL_MKEEP_ALIVE_VERSION 1 ++#define WL_MKEEP_ALIVE_FIXED_LEN OFFSETOF(wl_mkeep_alive_pkt_t, data) ++#define WL_MKEEP_ALIVE_PRECISION 500 ++ ++#ifdef WLBA ++ ++#define WLC_BA_CNT_VERSION 1 /* current version of wlc_ba_cnt_t */ ++ ++/* block ack related stats */ ++typedef struct wlc_ba_cnt { ++ uint16 version; /* WLC_BA_CNT_VERSION */ ++ uint16 length; /* length of entire structure */ ++ ++ /* transmit stat counters */ ++ uint32 txpdu; /* pdus sent */ ++ uint32 txsdu; /* sdus sent */ ++ uint32 txfc; /* tx side flow controlled packets */ ++ uint32 txfci; /* tx side flow control initiated */ ++ uint32 txretrans; /* retransmitted pdus */ ++ uint32 txbatimer; /* ba resend due to timer */ ++ uint32 txdrop; /* dropped packets */ ++ uint32 txaddbareq; /* addba req sent */ ++ uint32 txaddbaresp; /* addba resp sent */ ++ uint32 txdelba; /* delba sent */ ++ uint32 txba; /* ba sent */ ++ uint32 txbar; /* bar sent */ ++ uint32 txpad[4]; /* future */ ++ ++ /* receive side counters */ ++ uint32 rxpdu; /* pdus recd */ ++ uint32 rxqed; /* pdus buffered before sending up */ ++ uint32 rxdup; /* duplicate pdus */ ++ uint32 rxnobuf; /* pdus discarded due to no buf */ ++ uint32 rxaddbareq; /* addba req recd */ ++ uint32 rxaddbaresp; /* addba resp recd */ ++ uint32 rxdelba; /* delba recd */ ++ uint32 rxba; /* ba recd */ ++ uint32 rxbar; /* bar recd */ ++ uint32 rxinvba; /* invalid ba recd */ ++ uint32 rxbaholes; /* ba recd with holes */ ++ uint32 rxunexp; /* unexpected packets */ ++ uint32 rxpad[4]; /* future */ ++} wlc_ba_cnt_t; ++#endif /* WLBA */ ++ ++/* structure for per-tid ampdu control */ ++struct ampdu_tid_control { ++ uint8 tid; /* tid */ ++ uint8 enable; /* enable/disable */ ++}; ++ ++/* structure for identifying ea/tid for sending addba/delba */ ++struct ampdu_ea_tid { ++ struct ether_addr ea; /* Station address */ ++ uint8 tid; /* tid */ ++}; ++/* structure for identifying retry/tid for retry_limit_tid/rr_retry_limit_tid */ ++struct ampdu_retry_tid { ++ uint8 tid; /* tid */ ++ uint8 retry; /* retry value */ ++}; ++ ++/* Different discovery modes for dpt */ ++#define DPT_DISCOVERY_MANUAL 0x01 /* manual discovery mode */ ++#define DPT_DISCOVERY_AUTO 0x02 /* auto discovery mode */ ++#define DPT_DISCOVERY_SCAN 0x04 /* scan-based discovery mode */ ++ ++/* different path selection values */ ++#define DPT_PATHSEL_AUTO 0 /* auto mode for path selection */ ++#define DPT_PATHSEL_DIRECT 1 /* always use direct DPT path */ ++#define DPT_PATHSEL_APPATH 2 /* always use AP path */ ++ ++/* different ops for deny list */ ++#define DPT_DENY_LIST_ADD 1 /* add to dpt deny list */ ++#define DPT_DENY_LIST_REMOVE 2 /* remove from dpt deny list */ ++ ++/* different ops for manual end point */ ++#define DPT_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */ ++#define DPT_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */ ++#define DPT_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */ ++ ++/* structure for dpt iovars */ ++typedef struct dpt_iovar { ++ struct ether_addr ea; /* Station address */ ++ uint8 mode; /* mode: depends on iovar */ ++ uint32 pad; /* future */ ++} dpt_iovar_t; ++ ++/* flags to indicate DPT status */ ++#define DPT_STATUS_ACTIVE 0x01 /* link active (though may be suspended) */ ++#define DPT_STATUS_AES 0x02 /* link secured through AES encryption */ ++#define DPT_STATUS_FAILED 0x04 /* DPT link failed */ ++ ++#define DPT_FNAME_LEN 48 /* Max length of friendly name */ ++ ++typedef struct dpt_status { ++ uint8 status; /* flags to indicate status */ ++ uint8 fnlen; /* length of friendly name */ ++ uchar name[DPT_FNAME_LEN]; /* friendly name */ ++ uint32 rssi; /* RSSI of the link */ ++ sta_info_t sta; /* sta info */ ++} dpt_status_t; ++ ++/* structure for dpt list */ ++typedef struct dpt_list { ++ uint32 num; /* number of entries in struct */ ++ dpt_status_t status[1]; /* per station info */ ++} dpt_list_t; ++ ++/* structure for dpt friendly name */ ++typedef struct dpt_fname { ++ uint8 len; /* length of friendly name */ ++ uchar name[DPT_FNAME_LEN]; /* friendly name */ ++} dpt_fname_t; ++ ++#define BDD_FNAME_LEN 32 /* Max length of friendly name */ ++typedef struct bdd_fname { ++ uint8 len; /* length of friendly name */ ++ uchar name[BDD_FNAME_LEN]; /* friendly name */ ++} bdd_fname_t; ++ ++/* structure for addts arguments */ ++/* For ioctls that take a list of TSPEC */ ++struct tslist { ++ int count; /* number of tspecs */ ++ struct tsinfo_arg tsinfo[1]; /* variable length array of tsinfo */ ++}; ++ ++#ifdef WLTDLS ++/* different ops for manual end point */ ++#define TDLS_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */ ++#define TDLS_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */ ++#define TDLS_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */ ++#define TDLS_MANUAL_EP_PM 4 /* put dpt endpoint in PM mode */ ++#define TDLS_MANUAL_EP_WAKE 5 /* wake up dpt endpoint from PM */ ++#define TDLS_MANUAL_EP_DISCOVERY 6 /* discover if endpoint is TDLS capable */ ++#define TDLS_MANUAL_EP_CHSW 7 /* channel switch */ ++ ++/* structure for tdls iovars */ ++typedef struct tdls_iovar { ++ struct ether_addr ea; /* Station address */ ++ uint8 mode; /* mode: depends on iovar */ ++ chanspec_t chanspec; ++ uint32 pad; /* future */ ++} tdls_iovar_t; ++ ++/* modes */ ++#define TDLS_WFD_IE_TX 0 ++#define TDLS_WFD_IE_RX 1 ++#define TDLS_WFD_IE_SIZE 255 ++/* structure for tdls wfd ie */ ++typedef struct tdls_wfd_ie_iovar { ++ struct ether_addr ea; /* Station address */ ++ uint8 mode; ++ uint8 length; ++ uint8 data[TDLS_WFD_IE_SIZE]; ++} tdls_wfd_ie_iovar_t; ++#endif /* WLTDLS */ ++ ++/* structure for addts/delts arguments */ ++typedef struct tspec_arg { ++ uint16 version; /* see definition of TSPEC_ARG_VERSION */ ++ uint16 length; /* length of entire structure */ ++ uint flag; /* bit field */ ++ /* TSPEC Arguments */ ++ struct tsinfo_arg tsinfo; /* TS Info bit field */ ++ uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */ ++ uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */ ++ uint min_srv_interval; /* Minimum Service Interval (us) */ ++ uint max_srv_interval; /* Maximum Service Interval (us) */ ++ uint inactivity_interval; /* Inactivity Interval (us) */ ++ uint suspension_interval; /* Suspension Interval (us) */ ++ uint srv_start_time; /* Service Start Time (us) */ ++ uint min_data_rate; /* Minimum Data Rate (bps) */ ++ uint mean_data_rate; /* Mean Data Rate (bps) */ ++ uint peak_data_rate; /* Peak Data Rate (bps) */ ++ uint max_burst_size; /* Maximum Burst Size (bytes) */ ++ uint delay_bound; /* Delay Bound (us) */ ++ uint min_phy_rate; /* Minimum PHY Rate (bps) */ ++ uint16 surplus_bw; /* Surplus Bandwidth Allowance (range 1.0 to 8.0) */ ++ uint16 medium_time; /* Medium Time (32 us/s periods) */ ++ uint8 dialog_token; /* dialog token */ ++} tspec_arg_t; ++ ++/* tspec arg for desired station */ ++typedef struct tspec_per_sta_arg { ++ struct ether_addr ea; ++ struct tspec_arg ts; ++} tspec_per_sta_arg_t; ++ ++/* structure for max bandwidth for each access category */ ++typedef struct wme_max_bandwidth { ++ uint32 ac[AC_COUNT]; /* max bandwidth for each access category */ ++} wme_max_bandwidth_t; ++ ++#define WL_WME_MBW_PARAMS_IO_BYTES (sizeof(wme_max_bandwidth_t)) ++ ++/* current version of wl_tspec_arg_t struct */ ++#define TSPEC_ARG_VERSION 2 /* current version of wl_tspec_arg_t struct */ ++#define TSPEC_ARG_LENGTH 55 /* argument length from tsinfo to medium_time */ ++#define TSPEC_DEFAULT_DIALOG_TOKEN 42 /* default dialog token */ ++#define TSPEC_DEFAULT_SBW_FACTOR 0x3000 /* default surplus bw */ ++ ++ ++#define WL_WOWL_KEEPALIVE_MAX_PACKET_SIZE 80 ++#define WLC_WOWL_MAX_KEEPALIVE 2 ++ ++/* define for flag */ ++#define TSPEC_PENDING 0 /* TSPEC pending */ ++#define TSPEC_ACCEPTED 1 /* TSPEC accepted */ ++#define TSPEC_REJECTED 2 /* TSPEC rejected */ ++#define TSPEC_UNKNOWN 3 /* TSPEC unknown */ ++#define TSPEC_STATUS_MASK 7 /* TSPEC status mask */ ++ ++ ++/* Software feature flag defines used by wlfeatureflag */ ++#ifdef WLAFTERBURNER ++#define WL_SWFL_ABBFL 0x0001 /* Allow Afterburner on systems w/o hardware BFL */ ++#define WL_SWFL_ABENCORE 0x0002 /* Allow AB on non-4318E chips */ ++#endif /* WLAFTERBURNER */ ++#define WL_SWFL_NOHWRADIO 0x0004 ++#define WL_SWFL_FLOWCONTROL 0x0008 /* Enable backpressure to OS stack */ ++#define WL_SWFL_WLBSSSORT 0x0010 /* Per-port supports sorting of BSS */ ++ ++#define WL_LIFETIME_MAX 0xFFFF /* Max value in ms */ ++ ++/* Packet lifetime configuration per ac */ ++typedef struct wl_lifetime { ++ uint32 ac; /* access class */ ++ uint32 lifetime; /* Packet lifetime value in ms */ ++} wl_lifetime_t; ++ ++/* Channel Switch Announcement param */ ++typedef struct wl_chan_switch { ++ uint8 mode; /* value 0 or 1 */ ++ uint8 count; /* count # of beacons before switching */ ++ chanspec_t chspec; /* chanspec */ ++ uint8 reg; /* regulatory class */ ++} wl_chan_switch_t; ++ ++/* Roaming trigger definitions for WLC_SET_ROAM_TRIGGER. ++ * ++ * (-100 < value < 0) value is used directly as a roaming trigger in dBm ++ * (0 <= value) value specifies a logical roaming trigger level from ++ * the list below ++ * ++ * WLC_GET_ROAM_TRIGGER always returns roaming trigger value in dBm, never ++ * the logical roam trigger value. ++ */ ++#define WLC_ROAM_TRIGGER_DEFAULT 0 /* default roaming trigger */ ++#define WLC_ROAM_TRIGGER_BANDWIDTH 1 /* optimize for bandwidth roaming trigger */ ++#define WLC_ROAM_TRIGGER_DISTANCE 2 /* optimize for distance roaming trigger */ ++#define WLC_ROAM_TRIGGER_AUTO 3 /* auto-detect environment */ ++#define WLC_ROAM_TRIGGER_MAX_VALUE 3 /* max. valid value */ ++ ++#define WLC_ROAM_NEVER_ROAM_TRIGGER (-100) /* Avoid Roaming by setting a large value */ ++ ++/* Preferred Network Offload (PNO, formerly PFN) defines */ ++#define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */ ++ ++enum { ++ PFN_LIST_ORDER, ++ PFN_RSSI ++}; ++ ++enum { ++ DISABLE, ++ ENABLE ++}; ++ ++enum { ++ OFF_ADAPT, ++ SMART_ADAPT, ++ STRICT_ADAPT, ++ SLOW_ADAPT ++}; ++ ++#define SORT_CRITERIA_BIT 0 ++#define AUTO_NET_SWITCH_BIT 1 ++#define ENABLE_BKGRD_SCAN_BIT 2 ++#define IMMEDIATE_SCAN_BIT 3 ++#define AUTO_CONNECT_BIT 4 ++#define ENABLE_BD_SCAN_BIT 5 ++#define ENABLE_ADAPTSCAN_BIT 6 ++#define IMMEDIATE_EVENT_BIT 8 ++#define SUPPRESS_SSID_BIT 9 ++#define ENABLE_NET_OFFLOAD_BIT 10 ++ ++#define SORT_CRITERIA_MASK 0x0001 ++#define AUTO_NET_SWITCH_MASK 0x0002 ++#define ENABLE_BKGRD_SCAN_MASK 0x0004 ++#define IMMEDIATE_SCAN_MASK 0x0008 ++#define AUTO_CONNECT_MASK 0x0010 ++ ++#define ENABLE_BD_SCAN_MASK 0x0020 ++#define ENABLE_ADAPTSCAN_MASK 0x00c0 ++#define IMMEDIATE_EVENT_MASK 0x0100 ++#define SUPPRESS_SSID_MASK 0x0200 ++#define ENABLE_NET_OFFLOAD_MASK 0x0400 ++ ++#define PFN_VERSION 2 ++#define PFN_SCANRESULT_VERSION 1 ++#define MAX_PFN_LIST_COUNT 16 ++ ++#define PFN_COMPLETE 1 ++#define PFN_INCOMPLETE 0 ++ ++#define DEFAULT_BESTN 2 ++#define DEFAULT_MSCAN 0 ++#define DEFAULT_REPEAT 10 ++#define DEFAULT_EXP 2 ++ ++/* PFN network info structure */ ++typedef struct wl_pfn_subnet_info { ++ struct ether_addr BSSID; ++ uint8 channel; /* channel number only */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++} wl_pfn_subnet_info_t; ++ ++typedef struct wl_pfn_net_info { ++ wl_pfn_subnet_info_t pfnsubnet; ++ int16 RSSI; /* receive signal strength (in dBm) */ ++ uint16 timestamp; /* age in seconds */ ++} wl_pfn_net_info_t; ++ ++typedef struct wl_pfn_scanresults { ++ uint32 version; ++ uint32 status; ++ uint32 count; ++ wl_pfn_net_info_t netinfo[1]; ++} wl_pfn_scanresults_t; ++ ++/* PFN data structure */ ++typedef struct wl_pfn_param { ++ int32 version; /* PNO parameters version */ ++ int32 scan_freq; /* Scan frequency */ ++ int32 lost_network_timeout; /* Timeout in sec. to declare ++ * discovered network as lost ++ */ ++ int16 flags; /* Bit field to control features ++ * of PFN such as sort criteria auto ++ * enable switch and background scan ++ */ ++ int16 rssi_margin; /* Margin to avoid jitter for choosing a ++ * PFN based on RSSI sort criteria ++ */ ++ uint8 bestn; /* number of best networks in each scan */ ++ uint8 mscan; /* number of scans recorded */ ++ uint8 repeat; /* Minimum number of scan intervals ++ *before scan frequency changes in adaptive scan ++ */ ++ uint8 exp; /* Exponent of 2 for maximum scan interval */ ++ int32 slow_freq; /* slow scan period */ ++} wl_pfn_param_t; ++ ++typedef struct wl_pfn_bssid { ++ struct ether_addr macaddr; ++ /* Bit4: suppress_lost, Bit3: suppress_found */ ++ uint16 flags; ++} wl_pfn_bssid_t; ++#define WL_PFN_SUPPRESSFOUND_MASK 0x08 ++#define WL_PFN_SUPPRESSLOST_MASK 0x10 ++ ++typedef struct wl_pfn_cfg { ++ uint32 reporttype; ++ int32 channel_num; ++ uint16 channel_list[WL_NUMCHANNELS]; ++} wl_pfn_cfg_t; ++#define WL_PFN_REPORT_ALLNET 0 ++#define WL_PFN_REPORT_SSIDNET 1 ++#define WL_PFN_REPORT_BSSIDNET 2 ++ ++typedef struct wl_pfn { ++ wlc_ssid_t ssid; /* ssid name and its length */ ++ int32 flags; /* bit2: hidden */ ++ int32 infra; /* BSS Vs IBSS */ ++ int32 auth; /* Open Vs Closed */ ++ int32 wpa_auth; /* WPA type */ ++ int32 wsec; /* wsec value */ ++} wl_pfn_t; ++#define WL_PFN_HIDDEN_BIT 2 ++#define PNO_SCAN_MAX_FW 508*1000 /* max time scan time in msec */ ++#define PNO_SCAN_MAX_FW_SEC PNO_SCAN_MAX_FW/1000 /* max time scan time in SEC */ ++#define PNO_SCAN_MIN_FW_SEC 10 /* min time scan time in SEC */ ++#define WL_PFN_HIDDEN_MASK 0x4 ++ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* TCP Checksum Offload defines */ ++#define TOE_TX_CSUM_OL 0x00000001 ++#define TOE_RX_CSUM_OL 0x00000002 ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* TCP Checksum Offload error injection for testing */ ++#define TOE_ERRTEST_TX_CSUM 0x00000001 ++#define TOE_ERRTEST_RX_CSUM 0x00000002 ++#define TOE_ERRTEST_RX_CSUM2 0x00000004 ++ ++struct toe_ol_stats_t { ++ /* Num of tx packets that don't need to be checksummed */ ++ uint32 tx_summed; ++ ++ /* Num of tx packets where checksum is filled by offload engine */ ++ uint32 tx_iph_fill; ++ uint32 tx_tcp_fill; ++ uint32 tx_udp_fill; ++ uint32 tx_icmp_fill; ++ ++ /* Num of rx packets where toe finds out if checksum is good or bad */ ++ uint32 rx_iph_good; ++ uint32 rx_iph_bad; ++ uint32 rx_tcp_good; ++ uint32 rx_tcp_bad; ++ uint32 rx_udp_good; ++ uint32 rx_udp_bad; ++ uint32 rx_icmp_good; ++ uint32 rx_icmp_bad; ++ ++ /* Num of tx packets in which csum error is injected */ ++ uint32 tx_tcp_errinj; ++ uint32 tx_udp_errinj; ++ uint32 tx_icmp_errinj; ++ ++ /* Num of rx packets in which csum error is injected */ ++ uint32 rx_tcp_errinj; ++ uint32 rx_udp_errinj; ++ uint32 rx_icmp_errinj; ++}; ++ ++/* ARP Offload feature flags for arp_ol iovar */ ++#define ARP_OL_AGENT 0x00000001 ++#define ARP_OL_SNOOP 0x00000002 ++#define ARP_OL_HOST_AUTO_REPLY 0x00000004 ++#define ARP_OL_PEER_AUTO_REPLY 0x00000008 ++ ++/* ARP Offload error injection */ ++#define ARP_ERRTEST_REPLY_PEER 0x1 ++#define ARP_ERRTEST_REPLY_HOST 0x2 ++ ++#define ARP_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */ ++#define ND_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */ ++ ++/* Arp offload statistic counts */ ++struct arp_ol_stats_t { ++ uint32 host_ip_entries; /* Host IP table addresses (more than one if multihomed) */ ++ uint32 host_ip_overflow; /* Host IP table additions skipped due to overflow */ ++ ++ uint32 arp_table_entries; /* ARP table entries */ ++ uint32 arp_table_overflow; /* ARP table additions skipped due to overflow */ ++ ++ uint32 host_request; /* ARP requests from host */ ++ uint32 host_reply; /* ARP replies from host */ ++ uint32 host_service; /* ARP requests from host serviced by ARP Agent */ ++ ++ uint32 peer_request; /* ARP requests received from network */ ++ uint32 peer_request_drop; /* ARP requests from network that were dropped */ ++ uint32 peer_reply; /* ARP replies received from network */ ++ uint32 peer_reply_drop; /* ARP replies from network that were dropped */ ++ uint32 peer_service; /* ARP request from host serviced by ARP Agent */ ++}; ++ ++/* NS offload statistic counts */ ++struct nd_ol_stats_t { ++ uint32 host_ip_entries; /* Host IP table addresses (more than one if multihomed) */ ++ uint32 host_ip_overflow; /* Host IP table additions skipped due to overflow */ ++ uint32 peer_request; /* NS requests received from network */ ++ uint32 peer_request_drop; /* NS requests from network that were dropped */ ++ uint32 peer_reply_drop; /* NA replies from network that were dropped */ ++ uint32 peer_service; /* NS request from host serviced by firmware */ ++}; ++ ++/* ++ * Keep-alive packet offloading. ++ */ ++ ++/* NAT keep-alive packets format: specifies the re-transmission period, the packet ++ * length, and packet contents. ++ */ ++typedef struct wl_keep_alive_pkt { ++ uint32 period_msec; /* Retransmission period (0 to disable packet re-transmits) */ ++ uint16 len_bytes; /* Size of packet to transmit (0 to disable packet re-transmits) */ ++ uint8 data[1]; /* Variable length packet to transmit. Contents should include ++ * entire ethernet packet (enet header, IP header, UDP header, ++ * and UDP payload) in network byte order. ++ */ ++} wl_keep_alive_pkt_t; ++ ++#define WL_KEEP_ALIVE_FIXED_LEN OFFSETOF(wl_keep_alive_pkt_t, data) ++ ++/* ++ * Dongle pattern matching filter. ++ */ ++ ++/* Packet filter types. Currently, only pattern matching is supported. */ ++typedef enum wl_pkt_filter_type { ++ WL_PKT_FILTER_TYPE_PATTERN_MATCH /* Pattern matching filter */ ++} wl_pkt_filter_type_t; ++ ++#define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t ++ ++/* Pattern matching filter. Specifies an offset within received packets to ++ * start matching, the pattern to match, the size of the pattern, and a bitmask ++ * that indicates which bits within the pattern should be matched. ++ */ ++typedef struct wl_pkt_filter_pattern { ++ uint32 offset; /* Offset within received packet to start pattern matching. ++ * Offset '0' is the first byte of the ethernet header. ++ */ ++ uint32 size_bytes; /* Size of the pattern. Bitmask must be the same size. */ ++ uint8 mask_and_pattern[1]; /* Variable length mask and pattern data. mask starts ++ * at offset 0. Pattern immediately follows mask. ++ */ ++} wl_pkt_filter_pattern_t; ++ ++/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */ ++typedef struct wl_pkt_filter { ++ uint32 id; /* Unique filter id, specified by app. */ ++ uint32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */ ++ uint32 negate_match; /* Negate the result of filter matches */ ++ union { /* Filter definitions */ ++ wl_pkt_filter_pattern_t pattern; /* Pattern matching filter */ ++ } u; ++} wl_pkt_filter_t; ++ ++#define WL_PKT_FILTER_FIXED_LEN OFFSETOF(wl_pkt_filter_t, u) ++#define WL_PKT_FILTER_PATTERN_FIXED_LEN OFFSETOF(wl_pkt_filter_pattern_t, mask_and_pattern) ++ ++/* IOVAR "pkt_filter_enable" parameter. */ ++typedef struct wl_pkt_filter_enable { ++ uint32 id; /* Unique filter id */ ++ uint32 enable; /* Enable/disable bool */ ++} wl_pkt_filter_enable_t; ++ ++/* IOVAR "pkt_filter_list" parameter. Used to retrieve a list of installed filters. */ ++typedef struct wl_pkt_filter_list { ++ uint32 num; /* Number of installed packet filters */ ++ wl_pkt_filter_t filter[1]; /* Variable array of packet filters. */ ++} wl_pkt_filter_list_t; ++ ++#define WL_PKT_FILTER_LIST_FIXED_LEN OFFSETOF(wl_pkt_filter_list_t, filter) ++ ++/* IOVAR "pkt_filter_stats" parameter. Used to retrieve debug statistics. */ ++typedef struct wl_pkt_filter_stats { ++ uint32 num_pkts_matched; /* # filter matches for specified filter id */ ++ uint32 num_pkts_forwarded; /* # packets fwded from dongle to host for all filters */ ++ uint32 num_pkts_discarded; /* # packets discarded by dongle for all filters */ ++} wl_pkt_filter_stats_t; ++ ++/* Sequential Commands ioctl */ ++typedef struct wl_seq_cmd_ioctl { ++ uint32 cmd; /* common ioctl definition */ ++ uint32 len; /* length of user buffer */ ++} wl_seq_cmd_ioctl_t; ++ ++#define WL_SEQ_CMD_ALIGN_BYTES 4 ++ ++/* These are the set of get IOCTLs that should be allowed when using ++ * IOCTL sequence commands. These are issued implicitly by wl.exe each time ++ * it is invoked. We never want to buffer these, or else wl.exe will stop working. ++ */ ++#define WL_SEQ_CMDS_GET_IOCTL_FILTER(cmd) \ ++ (((cmd) == WLC_GET_MAGIC) || \ ++ ((cmd) == WLC_GET_VERSION) || \ ++ ((cmd) == WLC_GET_AP) || \ ++ ((cmd) == WLC_GET_INSTANCE)) ++ ++/* ++ * Packet engine interface ++ */ ++ ++#define WL_PKTENG_PER_TX_START 0x01 ++#define WL_PKTENG_PER_TX_STOP 0x02 ++#define WL_PKTENG_PER_RX_START 0x04 ++#define WL_PKTENG_PER_RX_WITH_ACK_START 0x05 ++#define WL_PKTENG_PER_TX_WITH_ACK_START 0x06 ++#define WL_PKTENG_PER_RX_STOP 0x08 ++#define WL_PKTENG_PER_MASK 0xff ++ ++#define WL_PKTENG_SYNCHRONOUS 0x100 /* synchronous flag */ ++ ++typedef struct wl_pkteng { ++ uint32 flags; ++ uint32 delay; /* Inter-packet delay */ ++ uint32 nframes; /* Number of frames */ ++ uint32 length; /* Packet length */ ++ uint8 seqno; /* Enable/disable sequence no. */ ++ struct ether_addr dest; /* Destination address */ ++ struct ether_addr src; /* Source address */ ++} wl_pkteng_t; ++ ++#define NUM_80211b_RATES 4 ++#define NUM_80211ag_RATES 8 ++#define NUM_80211n_RATES 32 ++#define NUM_80211_RATES (NUM_80211b_RATES+NUM_80211ag_RATES+NUM_80211n_RATES) ++typedef struct wl_pkteng_stats { ++ uint32 lostfrmcnt; /* RX PER test: no of frames lost (skip seqno) */ ++ int32 rssi; /* RSSI */ ++ int32 snr; /* signal to noise ratio */ ++ uint16 rxpktcnt[NUM_80211_RATES+1]; ++} wl_pkteng_stats_t; ++ ++ ++#define WL_WOWL_MAGIC (1 << 0) /* Wakeup on Magic packet */ ++#define WL_WOWL_NET (1 << 1) /* Wakeup on Netpattern */ ++#define WL_WOWL_DIS (1 << 2) /* Wakeup on loss-of-link due to Disassoc/Deauth */ ++#define WL_WOWL_RETR (1 << 3) /* Wakeup on retrograde TSF */ ++#define WL_WOWL_BCN (1 << 4) /* Wakeup on loss of beacon */ ++#define WL_WOWL_TST (1 << 5) /* Wakeup after test */ ++#define WL_WOWL_M1 (1 << 6) /* Wakeup after PTK refresh */ ++#define WL_WOWL_EAPID (1 << 7) /* Wakeup after receipt of EAP-Identity Req */ ++#define WL_WOWL_PME_GPIO (1 << 8) /* Wakeind via PME(0) or GPIO(1) */ ++#define WL_WOWL_NEEDTKIP1 (1 << 9) /* need tkip phase 1 key to be updated by the driver */ ++#define WL_WOWL_GTK_FAILURE (1 << 10) /* enable wakeup if GTK fails */ ++#define WL_WOWL_EXTMAGPAT (1 << 11) /* support extended magic packets */ ++#define WL_WOWL_ARPOFFLOAD (1 << 12) /* support ARP/NS/keepalive offloading */ ++#define WL_WOWL_WPA2 (1 << 13) /* read protocol version for EAPOL frames */ ++#define WL_WOWL_KEYROT (1 << 14) /* If the bit is set, use key rotaton */ ++#define WL_WOWL_BCAST (1 << 15) /* If the bit is set, frm received was bcast frame */ ++ ++#define MAGIC_PKT_MINLEN 102 /* Magic pkt min length is 6 * 0xFF + 16 * ETHER_ADDR_LEN */ ++ ++#define WOWL_PATTEN_TYPE_ARP (1 << 0) /* ARP offload Pattern */ ++#define WOWL_PATTEN_TYPE_NA (1 << 1) /* NA offload Pattern */ ++ ++typedef struct { ++ uint32 masksize; /* Size of the mask in #of bytes */ ++ uint32 offset; /* Offset to start looking for the packet in # of bytes */ ++ uint32 patternoffset; /* Offset of start of pattern in the structure */ ++ uint32 patternsize; /* Size of the pattern itself in #of bytes */ ++ uint32 id; /* id */ ++ uint32 reasonsize; /* Size of the wakeup reason code */ ++ uint32 flags; /* Flags to tell the pattern type and other properties */ ++ /* Mask follows the structure above */ ++ /* Pattern follows the mask is at 'patternoffset' from the start */ ++} wl_wowl_pattern_t; ++ ++typedef struct { ++ uint count; ++ wl_wowl_pattern_t pattern[1]; ++} wl_wowl_pattern_list_t; ++ ++typedef struct { ++ uint8 pci_wakeind; /* Whether PCI PMECSR PMEStatus bit was set */ ++ uint16 ucode_wakeind; /* What wakeup-event indication was set by ucode */ ++} wl_wowl_wakeind_t; ++ ++ ++/* per AC rate control related data structure */ ++typedef struct wl_txrate_class { ++ uint8 init_rate; ++ uint8 min_rate; ++ uint8 max_rate; ++} wl_txrate_class_t; ++ ++ ++ ++/* Overlap BSS Scan parameters default, minimum, maximum */ ++#define WLC_OBSS_SCAN_PASSIVE_DWELL_DEFAULT 20 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_DWELL_MIN 5 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_DWELL_MAX 1000 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_DWELL_DEFAULT 10 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_DWELL_MIN 10 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_DWELL_MAX 1000 /* unit TU */ ++#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_DEFAULT 300 /* unit Sec */ ++#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MIN 10 /* unit Sec */ ++#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MAX 900 /* unit Sec */ ++#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_DEFAULT 5 ++#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MIN 5 ++#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MAX 100 ++#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_DEFAULT 200 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MIN 200 /* unit TU */ ++#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MAX 10000 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_DEFAULT 20 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MIN 20 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MAX 10000 /* unit TU */ ++#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_DEFAULT 25 /* unit percent */ ++#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MIN 0 /* unit percent */ ++#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MAX 100 /* unit percent */ ++ ++/* structure for Overlap BSS scan arguments */ ++typedef struct wl_obss_scan_arg { ++ int16 passive_dwell; ++ int16 active_dwell; ++ int16 bss_widthscan_interval; ++ int16 passive_total; ++ int16 active_total; ++ int16 chanwidth_transition_delay; ++ int16 activity_threshold; ++} wl_obss_scan_arg_t; ++ ++#define WL_OBSS_SCAN_PARAM_LEN sizeof(wl_obss_scan_arg_t) ++#define WL_MIN_NUM_OBSS_SCAN_ARG 7 /* minimum number of arguments required for OBSS Scan */ ++ ++#define WL_COEX_INFO_MASK 0x07 ++#define WL_COEX_INFO_REQ 0x01 ++#define WL_COEX_40MHZ_INTOLERANT 0x02 ++#define WL_COEX_WIDTH20 0x04 ++ ++#define WLC_RSSI_INVALID 0 /* invalid RSSI value */ ++ ++#define MAX_RSSI_LEVELS 8 ++ ++/* RSSI event notification configuration. */ ++typedef struct wl_rssi_event { ++ uint32 rate_limit_msec; /* # of events posted to application will be limited to ++ * one per specified period (0 to disable rate limit). ++ */ ++ uint8 num_rssi_levels; /* Number of entries in rssi_levels[] below */ ++ int8 rssi_levels[MAX_RSSI_LEVELS]; /* Variable number of RSSI levels. An event ++ * will be posted each time the RSSI of received ++ * beacons/packets crosses a level. ++ */ ++} wl_rssi_event_t; ++ ++typedef struct wl_action_obss_coex_req { ++ uint8 info; ++ uint8 num; ++ uint8 ch_list[1]; ++} wl_action_obss_coex_req_t; ++ ++ ++/* IOVar parameter block for small MAC address array with type indicator */ ++#define WL_IOV_MAC_PARAM_LEN 4 ++ ++#define WL_IOV_PKTQ_LOG_PRECS 16 ++ ++typedef struct { ++ uint32 num_addrs; ++ char addr_type[WL_IOV_MAC_PARAM_LEN]; ++ struct ether_addr ea[WL_IOV_MAC_PARAM_LEN]; ++} wl_iov_mac_params_t; ++ ++ ++/* Parameter block for PKTQ_LOG statistics */ ++typedef struct { ++ uint32 requested; /* packets requested to be stored */ ++ uint32 stored; /* packets stored */ ++ uint32 saved; /* packets saved, ++ because a lowest priority queue has given away one packet ++ */ ++ uint32 selfsaved; /* packets saved, ++ because an older packet from the same queue has been dropped ++ */ ++ uint32 full_dropped; /* packets dropped, ++ because pktq is full with higher precedence packets ++ */ ++ uint32 dropped; /* packets dropped because pktq per that precedence is full */ ++ uint32 sacrificed; /* packets dropped, ++ in order to save one from a queue of a highest priority ++ */ ++ uint32 busy; /* packets droped because of hardware/transmission error */ ++ uint32 retry; /* packets re-sent because they were not received */ ++ uint32 ps_retry; /* packets retried again prior to moving power save mode */ ++ uint32 retry_drop; /* packets finally dropped after retry limit */ ++ uint32 max_avail; /* the high-water mark of the queue capacity for packets - ++ goes to zero as queue fills ++ */ ++ uint32 max_used; /* the high-water mark of the queue utilisation for packets - ++ increases with use ('inverse' of max_avail) ++ */ ++ uint32 queue_capacity; /* the maximum capacity of the queue */ ++} pktq_log_counters_v01_t; ++ ++#define sacrified sacrificed ++ ++typedef struct { ++ uint8 num_prec[WL_IOV_MAC_PARAM_LEN]; ++ pktq_log_counters_v01_t counters[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS]; ++ char headings[1]; ++} pktq_log_format_v01_t; ++ ++ ++typedef struct { ++ uint32 version; ++ wl_iov_mac_params_t params; ++ union { ++ pktq_log_format_v01_t v01; ++ } pktq_log; ++} wl_iov_pktq_log_t; ++ ++ ++/* **** EXTLOG **** */ ++#define EXTLOG_CUR_VER 0x0100 ++ ++#define MAX_ARGSTR_LEN 18 /* At least big enough for storing ETHER_ADDR_STR_LEN */ ++ ++/* log modules (bitmap) */ ++#define LOG_MODULE_COMMON 0x0001 ++#define LOG_MODULE_ASSOC 0x0002 ++#define LOG_MODULE_EVENT 0x0004 ++#define LOG_MODULE_MAX 3 /* Update when adding module */ ++ ++/* log levels */ ++#define WL_LOG_LEVEL_DISABLE 0 ++#define WL_LOG_LEVEL_ERR 1 ++#define WL_LOG_LEVEL_WARN 2 ++#define WL_LOG_LEVEL_INFO 3 ++#define WL_LOG_LEVEL_MAX WL_LOG_LEVEL_INFO /* Update when adding level */ ++ ++/* flag */ ++#define LOG_FLAG_EVENT 1 ++ ++/* log arg_type */ ++#define LOG_ARGTYPE_NULL 0 ++#define LOG_ARGTYPE_STR 1 /* %s */ ++#define LOG_ARGTYPE_INT 2 /* %d */ ++#define LOG_ARGTYPE_INT_STR 3 /* %d...%s */ ++#define LOG_ARGTYPE_STR_INT 4 /* %s...%d */ ++ ++typedef struct wlc_extlog_cfg { ++ int max_number; ++ uint16 module; /* bitmap */ ++ uint8 level; ++ uint8 flag; ++ uint16 version; ++} wlc_extlog_cfg_t; ++ ++typedef struct log_record { ++ uint32 time; ++ uint16 module; ++ uint16 id; ++ uint8 level; ++ uint8 sub_unit; ++ uint8 seq_num; ++ int32 arg; ++ char str[MAX_ARGSTR_LEN]; ++} log_record_t; ++ ++typedef struct wlc_extlog_req { ++ uint32 from_last; ++ uint32 num; ++} wlc_extlog_req_t; ++ ++typedef struct wlc_extlog_results { ++ uint16 version; ++ uint16 record_len; ++ uint32 num; ++ log_record_t logs[1]; ++} wlc_extlog_results_t; ++ ++typedef struct log_idstr { ++ uint16 id; ++ uint16 flag; ++ uint8 arg_type; ++ const char *fmt_str; ++} log_idstr_t; ++ ++#define FMTSTRF_USER 1 ++ ++/* flat ID definitions ++ * New definitions HAVE TO BE ADDED at the end of the table. Otherwise, it will ++ * affect backward compatibility with pre-existing apps ++ */ ++typedef enum { ++ FMTSTR_DRIVER_UP_ID = 0, ++ FMTSTR_DRIVER_DOWN_ID = 1, ++ FMTSTR_SUSPEND_MAC_FAIL_ID = 2, ++ FMTSTR_NO_PROGRESS_ID = 3, ++ FMTSTR_RFDISABLE_ID = 4, ++ FMTSTR_REG_PRINT_ID = 5, ++ FMTSTR_EXPTIME_ID = 6, ++ FMTSTR_JOIN_START_ID = 7, ++ FMTSTR_JOIN_COMPLETE_ID = 8, ++ FMTSTR_NO_NETWORKS_ID = 9, ++ FMTSTR_SECURITY_MISMATCH_ID = 10, ++ FMTSTR_RATE_MISMATCH_ID = 11, ++ FMTSTR_AP_PRUNED_ID = 12, ++ FMTSTR_KEY_INSERTED_ID = 13, ++ FMTSTR_DEAUTH_ID = 14, ++ FMTSTR_DISASSOC_ID = 15, ++ FMTSTR_LINK_UP_ID = 16, ++ FMTSTR_LINK_DOWN_ID = 17, ++ FMTSTR_RADIO_HW_OFF_ID = 18, ++ FMTSTR_RADIO_HW_ON_ID = 19, ++ FMTSTR_EVENT_DESC_ID = 20, ++ FMTSTR_PNP_SET_POWER_ID = 21, ++ FMTSTR_RADIO_SW_OFF_ID = 22, ++ FMTSTR_RADIO_SW_ON_ID = 23, ++ FMTSTR_PWD_MISMATCH_ID = 24, ++ FMTSTR_FATAL_ERROR_ID = 25, ++ FMTSTR_AUTH_FAIL_ID = 26, ++ FMTSTR_ASSOC_FAIL_ID = 27, ++ FMTSTR_IBSS_FAIL_ID = 28, ++ FMTSTR_EXTAP_FAIL_ID = 29, ++ FMTSTR_MAX_ID ++} log_fmtstr_id_t; ++ ++#ifdef DONGLEOVERLAYS ++typedef struct { ++ uint32 flags_idx; /* lower 8 bits: overlay index; upper 24 bits: flags */ ++ uint32 offset; /* offset into overlay region to write code */ ++ uint32 len; /* overlay code len */ ++ /* overlay code follows this struct */ ++} wl_ioctl_overlay_t; ++ ++#define OVERLAY_IDX_MASK 0x000000ff ++#define OVERLAY_IDX_SHIFT 0 ++#define OVERLAY_FLAGS_MASK 0xffffff00 ++#define OVERLAY_FLAGS_SHIFT 8 ++/* overlay written to device memory immediately after loading the base image */ ++#define OVERLAY_FLAG_POSTLOAD 0x100 ++/* defer overlay download until the device responds w/WLC_E_OVL_DOWNLOAD event */ ++#define OVERLAY_FLAG_DEFER_DL 0x200 ++/* overlay downloaded prior to the host going to sleep */ ++#define OVERLAY_FLAG_PRESLEEP 0x400 ++ ++#define OVERLAY_DOWNLOAD_CHUNKSIZE 1024 ++#endif /* DONGLEOVERLAYS */ ++ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* no default structure packing */ ++#include ++ ++/* require strict packing */ ++#include ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++ ++/* Structures and constants used for "vndr_ie" IOVar interface */ ++#define VNDR_IE_CMD_LEN 4 /* length of the set command string: ++ * "add", "del" (+ NUL) ++ */ ++ ++/* 802.11 Mgmt Packet flags */ ++#define VNDR_IE_BEACON_FLAG 0x1 ++#define VNDR_IE_PRBRSP_FLAG 0x2 ++#define VNDR_IE_ASSOCRSP_FLAG 0x4 ++#define VNDR_IE_AUTHRSP_FLAG 0x8 ++#define VNDR_IE_PRBREQ_FLAG 0x10 ++#define VNDR_IE_ASSOCREQ_FLAG 0x20 ++#define VNDR_IE_IWAPID_FLAG 0x40 /* vendor IE in IW advertisement protocol ID field */ ++#define VNDR_IE_CUSTOM_FLAG 0x100 /* allow custom IE id */ ++ ++#define VNDR_IE_INFO_HDR_LEN (sizeof(uint32)) ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ ++ vndr_ie_t vndr_ie_data; /* vendor IE data */ ++} BWL_POST_PACKED_STRUCT vndr_ie_info_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ int iecount; /* number of entries in the vndr_ie_list[] array */ ++ vndr_ie_info_t vndr_ie_list[1]; /* variable size list of vndr_ie_info_t structs */ ++} BWL_POST_PACKED_STRUCT vndr_ie_buf_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ char cmd[VNDR_IE_CMD_LEN]; /* vndr_ie IOVar set command : "add", "del" + NUL */ ++ vndr_ie_buf_t vndr_ie_buffer; /* buffer containing Vendor IE list information */ ++} BWL_POST_PACKED_STRUCT vndr_ie_setbuf_t; ++ ++/* tag_ID/length/value_buffer tuple */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint8 id; ++ uint8 len; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT tlv_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ ++ tlv_t ie_data; /* IE data */ ++} BWL_POST_PACKED_STRUCT ie_info_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ int iecount; /* number of entries in the ie_list[] array */ ++ ie_info_t ie_list[1]; /* variable size list of ie_info_t structs */ ++} BWL_POST_PACKED_STRUCT ie_buf_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ char cmd[VNDR_IE_CMD_LEN]; /* ie IOVar set command : "add" + NUL */ ++ ie_buf_t ie_buffer; /* buffer containing IE list information */ ++} BWL_POST_PACKED_STRUCT ie_setbuf_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ ++ uint8 id; /* IE type */ ++} BWL_POST_PACKED_STRUCT ie_getbuf_t; ++ ++/* structures used to define format of wps ie data from probe requests */ ++/* passed up to applications via iovar "prbreq_wpsie" */ ++typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_hdr { ++ struct ether_addr staAddr; ++ uint16 ieLen; ++} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_hdr_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_data { ++ sta_prbreq_wps_ie_hdr_t hdr; ++ uint8 ieData[1]; ++} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_data_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_list { ++ uint32 totLen; ++ uint8 ieDataList[1]; ++} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_list_t; ++ ++ ++#ifdef WLMEDIA_TXFAILEVENT ++typedef BWL_PRE_PACKED_STRUCT struct { ++ char dest[ETHER_ADDR_LEN]; /* destination MAC */ ++ uint8 prio; /* Packet Priority */ ++ uint8 flags; /* Flags */ ++ uint32 tsf_l; /* TSF timer low */ ++ uint32 tsf_h; /* TSF timer high */ ++ uint16 rates; /* Main Rates */ ++ uint16 txstatus; /* TX Status */ ++} BWL_POST_PACKED_STRUCT txfailinfo_t; ++#endif /* WLMEDIA_TXFAILEVENT */ ++ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++ ++/* no strict structure packing */ ++#include ++ ++#ifdef BCMWAPI_WAI ++#define IV_LEN 16 /* XXX, same as SMS4_WPI_PN_LEN */ ++struct wapi_sta_msg_t ++{ ++ uint16 msg_type; ++ uint16 datalen; ++ uint8 vap_mac[6]; ++ uint8 reserve_data1[2]; ++ uint8 sta_mac[6]; ++ uint8 reserve_data2[2]; ++ uint8 gsn[IV_LEN]; ++ uint8 wie[256]; ++}; ++#endif /* BCMWAPI_WAI */ ++ ++#ifndef LINUX_POSTMOGRIFY_REMOVAL ++/* Global ASSERT Logging */ ++#define ASSERTLOG_CUR_VER 0x0100 ++#define MAX_ASSRTSTR_LEN 64 ++ ++typedef struct assert_record { ++ uint32 time; ++ uint8 seq_num; ++ char str[MAX_ASSRTSTR_LEN]; ++} assert_record_t; ++ ++typedef struct assertlog_results { ++ uint16 version; ++ uint16 record_len; ++ uint32 num; ++ assert_record_t logs[1]; ++} assertlog_results_t; ++ ++#define LOGRRC_FIX_LEN 8 ++#define IOBUF_ALLOWED_NUM_OF_LOGREC(type, len) ((len - LOGRRC_FIX_LEN)/sizeof(type)) ++ ++ ++/* channel interference measurement (chanim) related defines */ ++ ++/* chanim mode */ ++#define CHANIM_DISABLE 0 /* disabled */ ++#define CHANIM_DETECT 1 /* detection only */ ++#define CHANIM_EXT 2 /* external state machine */ ++#define CHANIM_ACT 3 /* full internal state machine, detect + act */ ++#define CHANIM_MODE_MAX 4 ++ ++/* define for apcs reason code */ ++#define APCS_INIT 0 ++#define APCS_IOCTL 1 ++#define APCS_CHANIM 2 ++#define APCS_CSTIMER 3 ++#define APCS_BTA 4 ++ ++/* number of ACS record entries */ ++#define CHANIM_ACS_RECORD 10 ++ ++/* CHANIM */ ++#define CCASTATS_TXDUR 0 ++#define CCASTATS_INBSS 1 ++#define CCASTATS_OBSS 2 ++#define CCASTATS_NOCTG 3 ++#define CCASTATS_NOPKT 4 ++#define CCASTATS_DOZE 5 ++#define CCASTATS_TXOP 6 ++#define CCASTATS_GDTXDUR 7 ++#define CCASTATS_BDTXDUR 8 ++#define CCASTATS_MAX 9 ++ ++/* chanim acs record */ ++typedef struct { ++ bool valid; ++ uint8 trigger; ++ chanspec_t selected_chspc; ++ int8 bgnoise; ++ uint32 glitch_cnt; ++ uint8 ccastats; ++ uint timestamp; ++} chanim_acs_record_t; ++ ++typedef struct { ++ chanim_acs_record_t acs_record[CHANIM_ACS_RECORD]; ++ uint8 count; ++ uint timestamp; ++} wl_acs_record_t; ++ ++typedef struct chanim_stats { ++ uint32 glitchcnt; /* normalized as per second count */ ++ uint32 badplcp; /* normalized as per second count */ ++ uint8 ccastats[CCASTATS_MAX]; /* normalized as 0-255 */ ++ int8 bgnoise; /* background noise level (in dBm) */ ++ chanspec_t chanspec; ++ uint32 timestamp; ++} chanim_stats_t; ++ ++#define WL_CHANIM_STATS_VERSION 1 ++#define WL_CHANIM_COUNT_ALL 0xff ++#define WL_CHANIM_COUNT_ONE 0x1 ++ ++typedef struct { ++ uint32 buflen; ++ uint32 version; ++ uint32 count; ++ chanim_stats_t stats[1]; ++} wl_chanim_stats_t; ++ ++#define WL_CHANIM_STATS_FIXED_LEN OFFSETOF(wl_chanim_stats_t, stats) ++ ++/* Noise measurement metrics. */ ++#define NOISE_MEASURE_KNOISE 0x1 ++ ++/* scb probe parameter */ ++typedef struct { ++ uint32 scb_timeout; ++ uint32 scb_activity_time; ++ uint32 scb_max_probe; ++} wl_scb_probe_t; ++ ++/* ap tpc modes */ ++#define AP_TPC_OFF 0 ++#define AP_TPC_BSS_PWR 1 /* BSS power control */ ++#define AP_TPC_AP_PWR 2 /* AP power control */ ++#define AP_TPC_AP_BSS_PWR 3 /* Both AP and BSS power control */ ++#define AP_TPC_MAX_LINK_MARGIN 127 ++ ++/* ap tpc modes */ ++#define AP_TPC_OFF 0 ++#define AP_TPC_BSS_PWR 1 /* BSS power control */ ++#define AP_TPC_AP_PWR 2 /* AP power control */ ++#define AP_TPC_AP_BSS_PWR 3 /* Both AP and BSS power control */ ++#define AP_TPC_MAX_LINK_MARGIN 127 ++ ++/* structure/defines for selective mgmt frame (smf) stats support */ ++ ++#define SMFS_VERSION 1 ++/* selected mgmt frame (smf) stats element */ ++typedef struct wl_smfs_elem { ++ uint32 count; ++ uint16 code; /* SC or RC code */ ++} wl_smfs_elem_t; ++ ++typedef struct wl_smf_stats { ++ uint32 version; ++ uint16 length; /* reserved for future usage */ ++ uint8 type; ++ uint8 codetype; ++ uint32 ignored_cnt; ++ uint32 malformed_cnt; ++ uint32 count_total; /* count included the interested group */ ++ wl_smfs_elem_t elem[1]; ++} wl_smf_stats_t; ++ ++#define WL_SMFSTATS_FIXED_LEN OFFSETOF(wl_smf_stats_t, elem); ++ ++enum { ++ SMFS_CODETYPE_SC, ++ SMFS_CODETYPE_RC ++}; ++ ++/* reuse two number in the sc/rc space */ ++#define SMFS_CODE_MALFORMED 0xFFFE ++#define SMFS_CODE_IGNORED 0xFFFD ++ ++typedef enum smfs_type { ++ SMFS_TYPE_AUTH, ++ SMFS_TYPE_ASSOC, ++ SMFS_TYPE_REASSOC, ++ SMFS_TYPE_DISASSOC_TX, ++ SMFS_TYPE_DISASSOC_RX, ++ SMFS_TYPE_DEAUTH_TX, ++ SMFS_TYPE_DEAUTH_RX, ++ SMFS_TYPE_MAX ++} smfs_type_t; ++ ++#ifdef PHYMON ++ ++#define PHYMON_VERSION 1 ++ ++typedef struct wl_phycal_core_state { ++ /* Tx IQ/LO calibration coeffs */ ++ int16 tx_iqlocal_a; ++ int16 tx_iqlocal_b; ++ int8 tx_iqlocal_ci; ++ int8 tx_iqlocal_cq; ++ int8 tx_iqlocal_di; ++ int8 tx_iqlocal_dq; ++ int8 tx_iqlocal_ei; ++ int8 tx_iqlocal_eq; ++ int8 tx_iqlocal_fi; ++ int8 tx_iqlocal_fq; ++ ++ /* Rx IQ calibration coeffs */ ++ int16 rx_iqcal_a; ++ int16 rx_iqcal_b; ++ ++ uint8 tx_iqlocal_pwridx; /* Tx Power Index for Tx IQ/LO calibration */ ++ uint32 papd_epsilon_table[64]; /* PAPD epsilon table */ ++ int16 papd_epsilon_offset; /* PAPD epsilon offset */ ++ uint8 curr_tx_pwrindex; /* Tx power index */ ++ int8 idle_tssi; /* Idle TSSI */ ++ int8 est_tx_pwr; /* Estimated Tx Power (dB) */ ++ int8 est_rx_pwr; /* Estimated Rx Power (dB) from RSSI */ ++ uint16 rx_gaininfo; /* Rx gain applied on last Rx pkt */ ++ uint16 init_gaincode; /* initgain required for ACI */ ++ int8 estirr_tx; ++ int8 estirr_rx; ++ ++} wl_phycal_core_state_t; ++ ++typedef struct wl_phycal_state { ++ int version; ++ int8 num_phy_cores; /* number of cores */ ++ int8 curr_temperature; /* on-chip temperature sensor reading */ ++ chanspec_t chspec; /* channspec for this state */ ++ bool aci_state; /* ACI state: ON/OFF */ ++ uint16 crsminpower; /* crsminpower required for ACI */ ++ uint16 crsminpowerl; /* crsminpowerl required for ACI */ ++ uint16 crsminpoweru; /* crsminpoweru required for ACI */ ++ wl_phycal_core_state_t phycal_core[1]; ++} wl_phycal_state_t; ++ ++#define WL_PHYCAL_STAT_FIXED_LEN OFFSETOF(wl_phycal_state_t, phycal_core) ++#endif /* PHYMON */ ++ ++/* discovery state */ ++typedef struct wl_p2p_disc_st { ++ uint8 state; /* see state */ ++ chanspec_t chspec; /* valid in listen state */ ++ uint16 dwell; /* valid in listen state, in ms */ ++} wl_p2p_disc_st_t; ++ ++/* state */ ++#define WL_P2P_DISC_ST_SCAN 0 ++#define WL_P2P_DISC_ST_LISTEN 1 ++#define WL_P2P_DISC_ST_SEARCH 2 ++ ++/* scan request */ ++typedef struct wl_p2p_scan { ++ uint8 type; /* 'S' for WLC_SCAN, 'E' for "escan" */ ++ uint8 reserved[3]; ++ /* scan or escan parms... */ ++} wl_p2p_scan_t; ++ ++/* i/f request */ ++typedef struct wl_p2p_if { ++ struct ether_addr addr; ++ uint8 type; /* see i/f type */ ++ chanspec_t chspec; /* for p2p_ifadd GO */ ++} wl_p2p_if_t; ++ ++/* i/f type */ ++#define WL_P2P_IF_CLIENT 0 ++#define WL_P2P_IF_GO 1 ++#define WL_P2P_IF_DYNBCN_GO 2 ++#define WL_P2P_IF_DEV 3 ++ ++/* i/f query */ ++typedef struct wl_p2p_ifq { ++ uint bsscfgidx; ++ char ifname[BCM_MSG_IFNAME_MAX]; ++} wl_p2p_ifq_t; ++ ++/* OppPS & CTWindow */ ++typedef struct wl_p2p_ops { ++ uint8 ops; /* 0: disable 1: enable */ ++ uint8 ctw; /* >= 10 */ ++} wl_p2p_ops_t; ++ ++/* absence and presence request */ ++typedef struct wl_p2p_sched_desc { ++ uint32 start; ++ uint32 interval; ++ uint32 duration; ++ uint32 count; /* see count */ ++} wl_p2p_sched_desc_t; ++ ++/* count */ ++#define WL_P2P_SCHED_RSVD 0 ++#define WL_P2P_SCHED_REPEAT 255 /* anything > 255 will be treated as 255 */ ++ ++typedef struct wl_p2p_sched { ++ uint8 type; /* see schedule type */ ++ uint8 action; /* see schedule action */ ++ uint8 option; /* see schedule option */ ++ wl_p2p_sched_desc_t desc[1]; ++} wl_p2p_sched_t; ++#define WL_P2P_SCHED_FIXED_LEN 3 ++ ++/* schedule type */ ++#define WL_P2P_SCHED_TYPE_ABS 0 /* Scheduled Absence */ ++#define WL_P2P_SCHED_TYPE_REQ_ABS 1 /* Requested Absence */ ++ ++/* schedule action during absence periods (for WL_P2P_SCHED_ABS type) */ ++#define WL_P2P_SCHED_ACTION_NONE 0 /* no action */ ++#define WL_P2P_SCHED_ACTION_DOZE 1 /* doze */ ++/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */ ++#define WL_P2P_SCHED_ACTION_GOOFF 2 /* turn off GO beacon/prbrsp functions */ ++/* schedule option - WL_P2P_SCHED_TYPE_XXX */ ++#define WL_P2P_SCHED_ACTION_RESET 255 /* reset */ ++ ++/* schedule option - WL_P2P_SCHED_TYPE_ABS */ ++#define WL_P2P_SCHED_OPTION_NORMAL 0 /* normal start/interval/duration/count */ ++#define WL_P2P_SCHED_OPTION_BCNPCT 1 /* percentage of beacon interval */ ++/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */ ++#define WL_P2P_SCHED_OPTION_TSFOFS 2 /* normal start/internal/duration/count with ++ * start being an offset of the 'current' TSF ++ */ ++ ++/* feature flags */ ++#define WL_P2P_FEAT_GO_CSA (1 << 0) /* GO moves with the STA using CSA method */ ++#define WL_P2P_FEAT_GO_NOLEGACY (1 << 1) /* GO does not probe respond to non-p2p probe ++ * requests ++ */ ++#define WL_P2P_FEAT_RESTRICT_DEV_RESP (1 << 2) /* Restrict p2p dev interface from responding */ ++ ++#ifdef WLNIC ++/* nic_cnx iovar */ ++typedef struct wl_nic_cnx { ++ uint8 opcode; ++ struct ether_addr addr; ++ /* the following are valid for WL_NIC_CNX_CONN */ ++ uint8 SSID_len; ++ uint8 SSID[32]; ++ struct ether_addr abssid; ++ uint8 join_period; ++} wl_nic_cnx_t; ++ ++/* opcode */ ++#define WL_NIC_CNX_ADD 0 /* add NIC connection */ ++#define WL_NIC_CNX_DEL 1 /* delete NIC connection */ ++#define WL_NIC_CNX_IDX 2 /* query NIC connection index */ ++#define WL_NIC_CNX_CONN 3 /* join/create network */ ++#define WL_NIC_CNX_DIS 4 /* disconnect from network */ ++ ++/* nic_cfg iovar */ ++typedef struct wl_nic_cfg { ++ uint8 version; ++ uint8 beacon_mode; ++ uint16 beacon_interval; ++ uint8 diluted_beacon_period; ++ uint8 repeat_EQC; ++ uint8 scan_length; ++ uint8 scan_interval; ++ uint8 scan_probability; ++ uint8 awake_window_length; ++ int8 TSF_correction; ++ uint8 ASID; ++ uint8 channel_usage_mode; ++} wl_nic_cfg_t; ++ ++/* version */ ++#define WL_NIC_CFG_VER 1 ++ ++/* beacon_mode */ ++#define WL_NIC_BCN_NORM 0 ++#define WL_NIC_BCN_DILUTED 1 ++ ++/* channel_usage_mode */ ++#define WL_NIC_CHAN_STATIC 0 ++#define WL_NIC_CHAN_CYCLE 1 ++ ++/* nic_cfg iovar */ ++typedef struct wl_nic_frm { ++ uint8 type; ++ struct ether_addr da; ++ uint8 body[1]; ++} wl_nic_frm_t; ++ ++/* type */ ++#define WL_NIC_FRM_MYNET 1 ++#define WL_NIC_FRM_ACTION 2 ++ ++/* i/f query */ ++typedef struct wl_nic_ifq { ++ uint bsscfgidx; ++ char ifname[BCM_MSG_IFNAME_MAX]; ++} wl_nic_ifq_t; ++ ++/* data mode */ ++/* nic_dm iovar */ ++typedef struct wl_nic_dm { ++ uint8 enab; ++ chanspec_t chspec; ++} wl_nic_dm_t; ++#endif /* WLNIC */ ++ ++/* RFAWARE def */ ++#define BCM_ACTION_RFAWARE 0x77 ++#define BCM_ACTION_RFAWARE_DCS 0x01 ++ ++/* DCS reason code define */ ++#define BCM_DCS_IOVAR 0x1 ++#define BCM_DCS_UNKNOWN 0xFF ++ ++typedef struct wl_bcmdcs_data { ++ uint reason; ++ chanspec_t chspec; ++} wl_bcmdcs_data_t; ++ ++/* n-mode support capability */ ++/* 2x2 includes both 1x1 & 2x2 devices ++ * reserved #define 2 for future when we want to separate 1x1 & 2x2 and ++ * control it independently ++ */ ++#define WL_11N_2x2 1 ++#define WL_11N_3x3 3 ++#define WL_11N_4x4 4 ++ ++/* define 11n feature disable flags */ ++#define WLFEATURE_DISABLE_11N 0x00000001 ++#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002 ++#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004 ++#define WLFEATURE_DISABLE_11N_SGI_TX 0x00000008 ++#define WLFEATURE_DISABLE_11N_SGI_RX 0x00000010 ++#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020 ++#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040 ++#define WLFEATURE_DISABLE_11N_GF 0x00000080 ++ ++/* Proxy STA modes */ ++#define PSTA_MODE_DISABLED 0 ++#define PSTA_MODE_PROXY 1 ++#define PSTA_MODE_REPEATER 2 ++ ++ ++/* NAT configuration */ ++typedef struct { ++ uint32 ipaddr; /* interface ip address */ ++ uint32 ipaddr_mask; /* interface ip address mask */ ++ uint32 ipaddr_gateway; /* gateway ip address */ ++ uint8 mac_gateway[6]; /* gateway mac address */ ++ uint32 ipaddr_dns; /* DNS server ip address, valid only for public if */ ++ uint8 mac_dns[6]; /* DNS server mac address, valid only for public if */ ++ uint8 GUID[38]; /* interface GUID */ ++} nat_if_info_t; ++ ++typedef struct { ++ uint op; /* operation code */ ++ bool pub_if; /* set for public if, clear for private if */ ++ nat_if_info_t if_info; /* interface info */ ++} nat_cfg_t; ++ ++/* op code in nat_cfg */ ++#define NAT_OP_ENABLE 1 /* enable NAT on given interface */ ++#define NAT_OP_DISABLE 2 /* disable NAT on given interface */ ++#define NAT_OP_DISABLE_ALL 3 /* disable NAT on all interfaces */ ++ ++/* NAT state */ ++#define NAT_STATE_ENABLED 1 /* NAT is enabled */ ++#define NAT_STATE_DISABLED 2 /* NAT is disabled */ ++ ++typedef struct { ++ int state; /* NAT state returned */ ++} nat_state_t; ++ ++#ifdef PROP_TXSTATUS ++/* Bit definitions for tlv iovar */ ++/* ++ * enable RSSI signals: ++ * WLFC_CTL_TYPE_RSSI ++ */ ++#define WLFC_FLAGS_RSSI_SIGNALS 0x0001 ++ ++/* enable (if/mac_open, if/mac_close,, mac_add, mac_del) signals: ++ * ++ * WLFC_CTL_TYPE_MAC_OPEN ++ * WLFC_CTL_TYPE_MAC_CLOSE ++ * ++ * WLFC_CTL_TYPE_INTERFACE_OPEN ++ * WLFC_CTL_TYPE_INTERFACE_CLOSE ++ * ++ * WLFC_CTL_TYPE_MACDESC_ADD ++ * WLFC_CTL_TYPE_MACDESC_DEL ++ * ++ */ ++#define WLFC_FLAGS_XONXOFF_SIGNALS 0x0002 ++ ++/* enable (status, fifo_credit, mac_credit) signals ++ * WLFC_CTL_TYPE_MAC_REQUEST_CREDIT ++ * WLFC_CTL_TYPE_TXSTATUS ++ * WLFC_CTL_TYPE_FIFO_CREDITBACK ++ */ ++#define WLFC_FLAGS_CREDIT_STATUS_SIGNALS 0x0004 ++ ++#define WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE 0x0008 ++#define WLFC_FLAGS_PSQ_GENERATIONFSM_ENABLE 0x0010 ++#define WLFC_FLAGS_PSQ_ZERO_BUFFER_ENABLE 0x0020 ++#define WLFC_FLAGS_HOST_RXRERODER_ACTIVE 0x0040 ++#endif /* PROP_TXSTATUS */ ++ ++#define BTA_STATE_LOG_SZ 64 ++ ++/* BTAMP Statemachine states */ ++enum { ++ HCIReset = 1, ++ HCIReadLocalAMPInfo, ++ HCIReadLocalAMPASSOC, ++ HCIWriteRemoteAMPASSOC, ++ HCICreatePhysicalLink, ++ HCIAcceptPhysicalLinkRequest, ++ HCIDisconnectPhysicalLink, ++ HCICreateLogicalLink, ++ HCIAcceptLogicalLink, ++ HCIDisconnectLogicalLink, ++ HCILogicalLinkCancel, ++ HCIAmpStateChange, ++ HCIWriteLogicalLinkAcceptTimeout ++}; ++ ++typedef struct flush_txfifo { ++ uint32 txfifobmp; ++ uint32 hwtxfifoflush; ++ struct ether_addr ea; ++} flush_txfifo_t; ++ ++#define CHANNEL_5G_LOW_START 36 /* 5G low (36..48) CDD enable/disable bit mask */ ++#define CHANNEL_5G_MID_START 52 /* 5G mid (52..64) CDD enable/disable bit mask */ ++#define CHANNEL_5G_HIGH_START 100 /* 5G high (100..140) CDD enable/disable bit mask */ ++#define CHANNEL_5G_UPPER_START 149 /* 5G upper (149..161) CDD enable/disable bit mask */ ++ ++enum { ++ SPATIAL_MODE_2G_IDX = 0, ++ SPATIAL_MODE_5G_LOW_IDX, ++ SPATIAL_MODE_5G_MID_IDX, ++ SPATIAL_MODE_5G_HIGH_IDX, ++ SPATIAL_MODE_5G_UPPER_IDX, ++ SPATIAL_MODE_MAX_IDX ++}; ++ ++/* IOVAR "mempool" parameter. Used to retrieve a list of memory pool statistics. */ ++typedef struct wl_mempool_stats { ++ int num; /* Number of memory pools */ ++ bcm_mp_stats_t s[1]; /* Variable array of memory pool stats. */ ++} wl_mempool_stats_t; ++ ++ ++/* D0 Coalescing */ ++#define IPV4_ARP_FILTER 0x0001 ++#define IPV4_NETBT_FILTER 0x0002 ++#define IPV4_LLMNR_FILTER 0x0004 ++#define IPV4_SSDP_FILTER 0x0008 ++#define IPV4_WSD_FILTER 0x0010 ++#define IPV6_NETBT_FILTER 0x0200 ++#define IPV6_LLMNR_FILTER 0x0400 ++#define IPV6_SSDP_FILTER 0x0800 ++#define IPV6_WSD_FILTER 0x1000 ++ ++/* Network Offload Engine */ ++#define NWOE_OL_ENABLE 0x00000001 ++ ++typedef struct { ++ uint32 ipaddr; ++ uint32 ipaddr_netmask; ++ uint32 ipaddr_gateway; ++} nwoe_ifconfig_t; ++ ++/* ++ * Traffic management structures/defines. ++ */ ++ ++/* Traffic management bandwidth parameters */ ++#define TRF_MGMT_MAX_PRIORITIES 3 ++ ++#define TRF_MGMT_FLAG_ADD_DSCP 0x0001 /* Add DSCP to IP TOS field */ ++#define TRF_MGMT_FLAG_DISABLE_SHAPING 0x0002 /* Only support traffic clasification */ ++#define TRF_MGMT_FLAG_DISABLE_PRIORITY_TAGGING 0x0004 /* Don't override packet's priority */ ++ ++/* Traffic management priority classes */ ++typedef enum trf_mgmt_priority_class { ++ trf_mgmt_priority_low = 0, /* Maps to 802.1p BO */ ++ trf_mgmt_priority_medium = 1, /* Maps to 802.1p BE */ ++ trf_mgmt_priority_high = 2, /* Maps to 802.1p VI */ ++ trf_mgmt_priority_invalid = (trf_mgmt_priority_high + 1) ++} trf_mgmt_priority_class_t; ++ ++/* Traffic management configuration parameters */ ++typedef struct trf_mgmt_config { ++ uint32 trf_mgmt_enabled; /* 0 - disabled, 1 - enabled */ ++ uint32 flags; /* See TRF_MGMT_FLAG_xxx defines */ ++ uint32 host_ip_addr; /* My IP address to determine subnet */ ++ uint32 host_subnet_mask; /* My subnet mask */ ++ uint32 downlink_bandwidth; /* In units of kbps */ ++ uint32 uplink_bandwidth; /* In units of kbps */ ++ uint32 min_tx_bandwidth[TRF_MGMT_MAX_PRIORITIES]; /* Minimum guaranteed tx bandwidth */ ++ uint32 min_rx_bandwidth[TRF_MGMT_MAX_PRIORITIES]; /* Minimum guaranteed rx bandwidth */ ++} trf_mgmt_config_t; ++ ++/* Traffic management filter */ ++typedef struct trf_mgmt_filter { ++ struct ether_addr dst_ether_addr; /* His L2 address */ ++ uint32 dst_ip_addr; /* His IP address */ ++ uint16 dst_port; /* His L4 port */ ++ uint16 src_port; /* My L4 port */ ++ uint16 prot; /* L4 protocol (only TCP or UDP) */ ++ uint16 flags; /* TBD. For now, this must be zero. */ ++ trf_mgmt_priority_class_t priority; /* Priority for filtered packets */ ++} trf_mgmt_filter_t; ++ ++/* Traffic management filter list (variable length) */ ++typedef struct trf_mgmt_filter_list { ++ uint32 num_filters; ++ trf_mgmt_filter_t filter[1]; ++} trf_mgmt_filter_list_t; ++ ++/* Traffic management global info used for all queues */ ++typedef struct trf_mgmt_global_info { ++ uint32 maximum_bytes_per_second; ++ uint32 maximum_bytes_per_sampling_period; ++ uint32 total_bytes_consumed_per_second; ++ uint32 total_bytes_consumed_per_sampling_period; ++ uint32 total_unused_bytes_per_sampling_period; ++} trf_mgmt_global_info_t; ++ ++/* Traffic management shaping info per priority queue */ ++typedef struct trf_mgmt_shaping_info { ++ uint32 gauranteed_bandwidth_percentage; ++ uint32 guaranteed_bytes_per_second; ++ uint32 guaranteed_bytes_per_sampling_period; ++ uint32 num_bytes_produced_per_second; ++ uint32 num_bytes_consumed_per_second; ++ uint32 num_queued_packets; /* Number of packets in queue */ ++ uint32 num_queued_bytes; /* Number of bytes in queue */ ++} trf_mgmt_shaping_info_t; ++ ++/* Traffic management shaping info array */ ++typedef struct trf_mgmt_shaping_info_array { ++ trf_mgmt_global_info_t tx_global_shaping_info; ++ trf_mgmt_shaping_info_t tx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES]; ++ trf_mgmt_global_info_t rx_global_shaping_info; ++ trf_mgmt_shaping_info_t rx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES]; ++} trf_mgmt_shaping_info_array_t; ++ ++ ++/* Traffic management statistical counters */ ++typedef struct trf_mgmt_stats { ++ uint32 num_processed_packets; /* Number of packets processed */ ++ uint32 num_processed_bytes; /* Number of bytes processed */ ++ uint32 num_discarded_packets; /* Number of packets discarded from queue */ ++} trf_mgmt_stats_t; ++ ++/* Traffic management statisics array */ ++typedef struct trf_mgmt_stats_array { ++ trf_mgmt_stats_t tx_queue_stats[TRF_MGMT_MAX_PRIORITIES]; ++ trf_mgmt_stats_t rx_queue_stats[TRF_MGMT_MAX_PRIORITIES]; ++} trf_mgmt_stats_array_t; ++ ++typedef struct powersel_params { ++ /* LPC Params exposed via IOVAR */ ++ int32 tp_ratio_thresh; /* Throughput ratio threshold */ ++ uint8 rate_stab_thresh; /* Thresh for rate stability based on nupd */ ++ uint8 pwr_stab_thresh; /* Number of successes before power step down */ ++ uint8 pwr_sel_exp_time; /* Time lapse for expiry of database */ ++} powersel_params_t; ++ ++#endif /* LINUX_POSTMOGRIFY_REMOVAL */ ++#endif /* _wlioctl_h_ */ +diff --git a/drivers/net/wireless/ap6210/linux_osl.c b/drivers/net/wireless/ap6210/linux_osl.c +new file mode 100755 +index 0000000..d74eee3 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/linux_osl.c +@@ -0,0 +1,1138 @@ ++/* ++ * Linux OS Independent Layer ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: linux_osl.c 373382 2012-12-07 07:59:52Z $ ++ */ ++ ++#define LINUX_PORT ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#include ++ ++#define PCI_CFG_RETRY 10 ++ ++#define OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognize osh */ ++#define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */ ++ ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++#define DHD_SKB_HDRSIZE 336 ++#define DHD_SKB_1PAGE_BUFSIZE ((PAGE_SIZE*1)-DHD_SKB_HDRSIZE) ++#define DHD_SKB_2PAGE_BUFSIZE ((PAGE_SIZE*2)-DHD_SKB_HDRSIZE) ++#define DHD_SKB_4PAGE_BUFSIZE ((PAGE_SIZE*4)-DHD_SKB_HDRSIZE) ++ ++#define STATIC_BUF_MAX_NUM 16 ++#define STATIC_BUF_SIZE (PAGE_SIZE*2) ++#define STATIC_BUF_TOTAL_LEN (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE) ++ ++typedef struct bcm_static_buf { ++ struct semaphore static_sem; ++ unsigned char *buf_ptr; ++ unsigned char buf_use[STATIC_BUF_MAX_NUM]; ++} bcm_static_buf_t; ++ ++static bcm_static_buf_t *bcm_static_buf = 0; ++ ++#define STATIC_PKT_MAX_NUM 8 ++#if defined(ENHANCED_STATIC_BUF) ++#define STATIC_PKT_4PAGE_NUM 1 ++#define DHD_SKB_MAX_BUFSIZE DHD_SKB_4PAGE_BUFSIZE ++#else ++#define STATIC_PKT_4PAGE_NUM 0 ++#define DHD_SKB_MAX_BUFSIZE DHD_SKB_2PAGE_BUFSIZE ++#endif /* ENHANCED_STATIC_BUF */ ++ ++typedef struct bcm_static_pkt { ++ struct sk_buff *skb_4k[STATIC_PKT_MAX_NUM]; ++ struct sk_buff *skb_8k[STATIC_PKT_MAX_NUM]; ++#ifdef ENHANCED_STATIC_BUF ++ struct sk_buff *skb_16k; ++#endif ++ struct semaphore osl_pkt_sem; ++ unsigned char pkt_use[STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM]; ++} bcm_static_pkt_t; ++ ++static bcm_static_pkt_t *bcm_static_skb = 0; ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ ++typedef struct bcm_mem_link { ++ struct bcm_mem_link *prev; ++ struct bcm_mem_link *next; ++ uint size; ++ int line; ++ void *osh; ++ char file[BCM_MEM_FILENAME_LEN]; ++} bcm_mem_link_t; ++ ++struct osl_info { ++ osl_pubinfo_t pub; ++#ifdef CTFPOOL ++ ctfpool_t *ctfpool; ++#endif /* CTFPOOL */ ++ uint magic; ++ void *pdev; ++ atomic_t malloced; ++ uint failed; ++ uint bustype; ++ bcm_mem_link_t *dbgmem_list; ++ spinlock_t dbgmem_lock; ++ spinlock_t pktalloc_lock; ++}; ++ ++/* PCMCIA attribute space access macros */ ++ ++/* Global ASSERT type flag */ ++uint32 g_assert_type = FALSE; ++ ++static int16 linuxbcmerrormap[] = ++{ 0, /* 0 */ ++ -EINVAL, /* BCME_ERROR */ ++ -EINVAL, /* BCME_BADARG */ ++ -EINVAL, /* BCME_BADOPTION */ ++ -EINVAL, /* BCME_NOTUP */ ++ -EINVAL, /* BCME_NOTDOWN */ ++ -EINVAL, /* BCME_NOTAP */ ++ -EINVAL, /* BCME_NOTSTA */ ++ -EINVAL, /* BCME_BADKEYIDX */ ++ -EINVAL, /* BCME_RADIOOFF */ ++ -EINVAL, /* BCME_NOTBANDLOCKED */ ++ -EINVAL, /* BCME_NOCLK */ ++ -EINVAL, /* BCME_BADRATESET */ ++ -EINVAL, /* BCME_BADBAND */ ++ -E2BIG, /* BCME_BUFTOOSHORT */ ++ -E2BIG, /* BCME_BUFTOOLONG */ ++ -EBUSY, /* BCME_BUSY */ ++ -EINVAL, /* BCME_NOTASSOCIATED */ ++ -EINVAL, /* BCME_BADSSIDLEN */ ++ -EINVAL, /* BCME_OUTOFRANGECHAN */ ++ -EINVAL, /* BCME_BADCHAN */ ++ -EFAULT, /* BCME_BADADDR */ ++ -ENOMEM, /* BCME_NORESOURCE */ ++ -EOPNOTSUPP, /* BCME_UNSUPPORTED */ ++ -EMSGSIZE, /* BCME_BADLENGTH */ ++ -EINVAL, /* BCME_NOTREADY */ ++ -EPERM, /* BCME_EPERM */ ++ -ENOMEM, /* BCME_NOMEM */ ++ -EINVAL, /* BCME_ASSOCIATED */ ++ -ERANGE, /* BCME_RANGE */ ++ -EINVAL, /* BCME_NOTFOUND */ ++ -EINVAL, /* BCME_WME_NOT_ENABLED */ ++ -EINVAL, /* BCME_TSPEC_NOTFOUND */ ++ -EINVAL, /* BCME_ACM_NOTSUPPORTED */ ++ -EINVAL, /* BCME_NOT_WME_ASSOCIATION */ ++ -EIO, /* BCME_SDIO_ERROR */ ++ -ENODEV, /* BCME_DONGLE_DOWN */ ++ -EINVAL, /* BCME_VERSION */ ++ -EIO, /* BCME_TXFAIL */ ++ -EIO, /* BCME_RXFAIL */ ++ -ENODEV, /* BCME_NODEVICE */ ++ -EINVAL, /* BCME_NMODE_DISABLED */ ++ -ENODATA, /* BCME_NONRESIDENT */ ++ ++/* When an new error code is added to bcmutils.h, add os ++ * specific error translation here as well ++ */ ++/* check if BCME_LAST changed since the last time this function was updated */ ++#if BCME_LAST != -42 ++#error "You need to add a OS error translation in the linuxbcmerrormap \ ++ for new error code defined in bcmutils.h" ++#endif ++}; ++ ++/* translate bcmerrors into linux errors */ ++int ++osl_error(int bcmerror) ++{ ++ if (bcmerror > 0) ++ bcmerror = 0; ++ else if (bcmerror < BCME_LAST) ++ bcmerror = BCME_ERROR; ++ ++ /* Array bounds covered by ASSERT in osl_attach */ ++ return linuxbcmerrormap[-bcmerror]; ++} ++ ++extern uint8* dhd_os_prealloc(void *osh, int section, int size); ++ ++osl_t * ++osl_attach(void *pdev, uint bustype, bool pkttag) ++{ ++ osl_t *osh; ++ ++ if (!(osh = kmalloc(sizeof(osl_t), GFP_ATOMIC))) ++ return osh; ++ ++ ASSERT(osh); ++ ++ bzero(osh, sizeof(osl_t)); ++ ++ /* Check that error map has the right number of entries in it */ ++ ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1)); ++ ++ osh->magic = OS_HANDLE_MAGIC; ++ atomic_set(&osh->malloced, 0); ++ osh->failed = 0; ++ osh->dbgmem_list = NULL; ++ spin_lock_init(&(osh->dbgmem_lock)); ++ osh->pdev = pdev; ++ osh->pub.pkttag = pkttag; ++ osh->bustype = bustype; ++ ++ switch (bustype) { ++ case PCI_BUS: ++ case SI_BUS: ++ case PCMCIA_BUS: ++ osh->pub.mmbus = TRUE; ++ break; ++ case JTAG_BUS: ++ case SDIO_BUS: ++ case USB_BUS: ++ case SPI_BUS: ++ case RPC_BUS: ++ osh->pub.mmbus = FALSE; ++ break; ++ default: ++ ASSERT(FALSE); ++ break; ++ } ++ ++#if defined(CONFIG_DHD_USE_STATIC_BUF) ++ if (!bcm_static_buf) { ++ if (!(bcm_static_buf = (bcm_static_buf_t *)dhd_os_prealloc(osh, 3, STATIC_BUF_SIZE+ ++ STATIC_BUF_TOTAL_LEN))) { ++ AP6210_DEBUG("can not alloc static buf!\n"); ++ } ++ else ++ AP6210_DEBUG("alloc static buf at %x!\n", (unsigned int)bcm_static_buf); ++ ++ ++ sema_init(&bcm_static_buf->static_sem, 1); ++ ++ bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE; ++ } ++ ++ if (!bcm_static_skb) { ++ int i; ++ void *skb_buff_ptr = 0; ++ bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); ++ skb_buff_ptr = dhd_os_prealloc(osh, 4, 0); ++ ++ bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *)* ++ (STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM)); ++ for (i = 0; i < (STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM); i++) ++ bcm_static_skb->pkt_use[i] = 0; ++ ++ sema_init(&bcm_static_skb->osl_pkt_sem, 1); ++ } ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ ++ spin_lock_init(&(osh->pktalloc_lock)); ++ ++ return osh; ++} ++ ++void ++osl_detach(osl_t *osh) ++{ ++ if (osh == NULL) ++ return; ++ ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++ if (bcm_static_buf) { ++ bcm_static_buf = 0; ++ } ++ if (bcm_static_skb) { ++ bcm_static_skb = 0; ++ } ++#endif ++ ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ kfree(osh); ++} ++ ++static struct sk_buff *osl_alloc_skb(unsigned int len) ++{ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) ++ return __dev_alloc_skb(len, GFP_ATOMIC); ++#else ++ return dev_alloc_skb(len); ++#endif ++} ++ ++#ifdef CTFPOOL ++ ++#ifdef CTFPOOL_SPINLOCK ++#define CTFPOOL_LOCK(ctfpool, flags) spin_lock_irqsave(&(ctfpool)->lock, flags) ++#define CTFPOOL_UNLOCK(ctfpool, flags) spin_unlock_irqrestore(&(ctfpool)->lock, flags) ++#else ++#define CTFPOOL_LOCK(ctfpool, flags) spin_lock_bh(&(ctfpool)->lock) ++#define CTFPOOL_UNLOCK(ctfpool, flags) spin_unlock_bh(&(ctfpool)->lock) ++#endif /* CTFPOOL_SPINLOCK */ ++/* ++ * Allocate and add an object to packet pool. ++ */ ++void * ++osl_ctfpool_add(osl_t *osh) ++{ ++ struct sk_buff *skb; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return NULL; ++ ++ CTFPOOL_LOCK(osh->ctfpool, flags); ++ ASSERT(osh->ctfpool->curr_obj <= osh->ctfpool->max_obj); ++ ++ /* No need to allocate more objects */ ++ if (osh->ctfpool->curr_obj == osh->ctfpool->max_obj) { ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ return NULL; ++ } ++ ++ /* Allocate a new skb and add it to the ctfpool */ ++ skb = osl_alloc_skb(osh->ctfpool->obj_size); ++ if (skb == NULL) { ++ AP6210_DEBUG("%s: skb alloc of len %d failed\n", __FUNCTION__, ++ osh->ctfpool->obj_size); ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ return NULL; ++ } ++ ++ /* Add to ctfpool */ ++ skb->next = (struct sk_buff *)osh->ctfpool->head; ++ osh->ctfpool->head = skb; ++ osh->ctfpool->fast_frees++; ++ osh->ctfpool->curr_obj++; ++ ++ /* Hijack a skb member to store ptr to ctfpool */ ++ CTFPOOLPTR(osh, skb) = (void *)osh->ctfpool; ++ ++ /* Use bit flag to indicate skb from fast ctfpool */ ++ PKTFAST(osh, skb) = FASTBUF; ++ ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ ++ return skb; ++} ++ ++/* ++ * Add new objects to the pool. ++ */ ++void ++osl_ctfpool_replenish(osl_t *osh, uint thresh) ++{ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return; ++ ++ /* Do nothing if no refills are required */ ++ while ((osh->ctfpool->refills > 0) && (thresh--)) { ++ osl_ctfpool_add(osh); ++ osh->ctfpool->refills--; ++ } ++} ++ ++/* ++ * Initialize the packet pool with specified number of objects. ++ */ ++int32 ++osl_ctfpool_init(osl_t *osh, uint numobj, uint size) ++{ ++ osh->ctfpool = kmalloc(sizeof(ctfpool_t), GFP_ATOMIC); ++ ASSERT(osh->ctfpool); ++ bzero(osh->ctfpool, sizeof(ctfpool_t)); ++ ++ osh->ctfpool->max_obj = numobj; ++ osh->ctfpool->obj_size = size; ++ ++ spin_lock_init(&osh->ctfpool->lock); ++ ++ while (numobj--) { ++ if (!osl_ctfpool_add(osh)) ++ return -1; ++ osh->ctfpool->fast_frees--; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Cleanup the packet pool objects. ++ */ ++void ++osl_ctfpool_cleanup(osl_t *osh) ++{ ++ struct sk_buff *skb, *nskb; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return; ++ ++ CTFPOOL_LOCK(osh->ctfpool, flags); ++ ++ skb = osh->ctfpool->head; ++ ++ while (skb != NULL) { ++ nskb = skb->next; ++ dev_kfree_skb(skb); ++ skb = nskb; ++ osh->ctfpool->curr_obj--; ++ } ++ ++ ASSERT(osh->ctfpool->curr_obj == 0); ++ osh->ctfpool->head = NULL; ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ ++ kfree(osh->ctfpool); ++ osh->ctfpool = NULL; ++} ++ ++void ++osl_ctfpool_stats(osl_t *osh, void *b) ++{ ++ struct bcmstrbuf *bb; ++ ++ if ((osh == NULL) || (osh->ctfpool == NULL)) ++ return; ++ ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++ if (bcm_static_buf) { ++ bcm_static_buf = 0; ++ } ++ if (bcm_static_skb) { ++ bcm_static_skb = 0; ++ } ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ ++ bb = b; ++ ++ ASSERT((osh != NULL) && (bb != NULL)); ++ ++ bcm_bprintf(bb, "max_obj %d obj_size %d curr_obj %d refills %d\n", ++ osh->ctfpool->max_obj, osh->ctfpool->obj_size, ++ osh->ctfpool->curr_obj, osh->ctfpool->refills); ++ bcm_bprintf(bb, "fast_allocs %d fast_frees %d slow_allocs %d\n", ++ osh->ctfpool->fast_allocs, osh->ctfpool->fast_frees, ++ osh->ctfpool->slow_allocs); ++} ++ ++static inline struct sk_buff * ++osl_pktfastget(osl_t *osh, uint len) ++{ ++ struct sk_buff *skb; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++ /* Try to do fast allocate. Return null if ctfpool is not in use ++ * or if there are no items in the ctfpool. ++ */ ++ if (osh->ctfpool == NULL) ++ return NULL; ++ ++ CTFPOOL_LOCK(osh->ctfpool, flags); ++ if (osh->ctfpool->head == NULL) { ++ ASSERT(osh->ctfpool->curr_obj == 0); ++ osh->ctfpool->slow_allocs++; ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ return NULL; ++ } ++ ++ ASSERT(len <= osh->ctfpool->obj_size); ++ ++ /* Get an object from ctfpool */ ++ skb = (struct sk_buff *)osh->ctfpool->head; ++ osh->ctfpool->head = (void *)skb->next; ++ ++ osh->ctfpool->fast_allocs++; ++ osh->ctfpool->curr_obj--; ++ ASSERT(CTFPOOLHEAD(osh, skb) == (struct sock *)osh->ctfpool->head); ++ CTFPOOL_UNLOCK(osh->ctfpool, flags); ++ ++ /* Init skb struct */ ++ skb->next = skb->prev = NULL; ++ skb->data = skb->head + 16; ++ skb->tail = skb->head + 16; ++ ++ skb->len = 0; ++ skb->cloned = 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) ++ skb->list = NULL; ++#endif ++ atomic_set(&skb->users, 1); ++ ++ return skb; ++} ++#endif /* CTFPOOL */ ++/* Convert a driver packet to native(OS) packet ++ * In the process, packettag is zeroed out before sending up ++ * IP code depends on skb->cb to be setup correctly with various options ++ * In our case, that means it should be 0 ++ */ ++struct sk_buff * BCMFASTPATH ++osl_pkt_tonative(osl_t *osh, void *pkt) ++{ ++#ifndef WL_UMK ++ struct sk_buff *nskb; ++ unsigned long flags; ++#endif ++ ++ if (osh->pub.pkttag) ++ bzero((void*)((struct sk_buff *)pkt)->cb, OSL_PKTTAG_SZ); ++ ++#ifndef WL_UMK ++ /* Decrement the packet counter */ ++ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { ++ spin_lock_irqsave(&osh->pktalloc_lock, flags); ++ osh->pub.pktalloced--; ++ spin_unlock_irqrestore(&osh->pktalloc_lock, flags); ++ } ++#endif /* WL_UMK */ ++ return (struct sk_buff *)pkt; ++} ++ ++/* Convert a native(OS) packet to driver packet. ++ * In the process, native packet is destroyed, there is no copying ++ * Also, a packettag is zeroed out ++ */ ++void * BCMFASTPATH ++osl_pkt_frmnative(osl_t *osh, void *pkt) ++{ ++#ifndef WL_UMK ++ struct sk_buff *nskb; ++ unsigned long flags; ++#endif ++ ++ if (osh->pub.pkttag) ++ bzero((void*)((struct sk_buff *)pkt)->cb, OSL_PKTTAG_SZ); ++ ++#ifndef WL_UMK ++ /* Increment the packet counter */ ++ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { ++ spin_lock_irqsave(&osh->pktalloc_lock, flags); ++ osh->pub.pktalloced++; ++ spin_unlock_irqrestore(&osh->pktalloc_lock, flags); ++ } ++#endif /* WL_UMK */ ++ return (void *)pkt; ++} ++ ++/* Return a new packet. zero out pkttag */ ++void * BCMFASTPATH ++osl_pktget(osl_t *osh, uint len) ++{ ++ struct sk_buff *skb; ++ unsigned long flags; ++ ++#ifdef CTFPOOL ++ /* Allocate from local pool */ ++ skb = osl_pktfastget(osh, len); ++ if ((skb != NULL) || ((skb = osl_alloc_skb(len)) != NULL)) { ++#else /* CTFPOOL */ ++ if ((skb = osl_alloc_skb(len))) { ++#endif /* CTFPOOL */ ++ skb_put(skb, len); ++ skb->priority = 0; ++ ++ ++ spin_lock_irqsave(&osh->pktalloc_lock, flags); ++ osh->pub.pktalloced++; ++ spin_unlock_irqrestore(&osh->pktalloc_lock, flags); ++ } ++ ++ return ((void*) skb); ++} ++ ++#ifdef CTFPOOL ++static inline void ++osl_pktfastfree(osl_t *osh, struct sk_buff *skb) ++{ ++ ctfpool_t *ctfpool; ++#ifdef CTFPOOL_SPINLOCK ++ unsigned long flags; ++#endif /* CTFPOOL_SPINLOCK */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++ skb->tstamp.tv.sec = 0; ++#else ++ skb->stamp.tv_sec = 0; ++#endif ++ ++ /* We only need to init the fields that we change */ ++ skb->dev = NULL; ++ skb->dst = NULL; ++ memset(skb->cb, 0, sizeof(skb->cb)); ++ skb->ip_summed = 0; ++ skb->destructor = NULL; ++ ++ ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb); ++ ASSERT(ctfpool != NULL); ++ ++ /* Add object to the ctfpool */ ++ CTFPOOL_LOCK(ctfpool, flags); ++ skb->next = (struct sk_buff *)ctfpool->head; ++ ctfpool->head = (void *)skb; ++ ++ ctfpool->fast_frees++; ++ ctfpool->curr_obj++; ++ ++ ASSERT(ctfpool->curr_obj <= ctfpool->max_obj); ++ CTFPOOL_UNLOCK(ctfpool, flags); ++} ++#endif /* CTFPOOL */ ++ ++/* Free the driver packet. Free the tag if present */ ++void BCMFASTPATH ++osl_pktfree(osl_t *osh, void *p, bool send) ++{ ++ struct sk_buff *skb, *nskb; ++ unsigned long flags; ++ ++ skb = (struct sk_buff*) p; ++ ++ if (send && osh->pub.tx_fn) ++ osh->pub.tx_fn(osh->pub.tx_ctx, p, 0); ++ ++ PKTDBG_TRACE(osh, (void *) skb, PKTLIST_PKTFREE); ++ ++ /* perversion: we use skb->next to chain multi-skb packets */ ++ while (skb) { ++ nskb = skb->next; ++ skb->next = NULL; ++ ++ ++ ++#ifdef CTFPOOL ++ if ((PKTISFAST(osh, skb)) && (atomic_read(&skb->users) == 1)) ++ osl_pktfastfree(osh, skb); ++ else { ++#else /* CTFPOOL */ ++ { ++#endif /* CTFPOOL */ ++ ++ if (skb->destructor) ++ /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if ++ * destructor exists ++ */ ++ dev_kfree_skb_any(skb); ++ else ++ /* can free immediately (even in_irq()) if destructor ++ * does not exist ++ */ ++ dev_kfree_skb(skb); ++ } ++ spin_lock_irqsave(&osh->pktalloc_lock, flags); ++ osh->pub.pktalloced--; ++ spin_unlock_irqrestore(&osh->pktalloc_lock, flags); ++ skb = nskb; ++ } ++} ++ ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++void* ++osl_pktget_static(osl_t *osh, uint len) ++{ ++ int i = 0; ++ struct sk_buff *skb; ++ ++ ++ if (len > DHD_SKB_MAX_BUFSIZE) { ++ AP6210_DEBUG("osl_pktget_static: Do we really need this big skb??" ++ " len=%d\n", len); ++ return osl_pktget(osh, len); ++ } ++ ++ down(&bcm_static_skb->osl_pkt_sem); ++ ++ if (len <= DHD_SKB_1PAGE_BUFSIZE) { ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (bcm_static_skb->pkt_use[i] == 0) ++ break; ++ } ++ ++ if (i != STATIC_PKT_MAX_NUM) { ++ bcm_static_skb->pkt_use[i] = 1; ++ ++ skb = bcm_static_skb->skb_4k[i]; ++ skb->tail = skb->data + len; ++ skb->len = len; ++ ++ up(&bcm_static_skb->osl_pkt_sem); ++ return skb; ++ } ++ } ++ ++ if (len <= DHD_SKB_2PAGE_BUFSIZE) { ++ ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] ++ == 0) ++ break; ++ } ++ ++ if (i != STATIC_PKT_MAX_NUM) { ++ bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 1; ++ skb = bcm_static_skb->skb_8k[i]; ++ skb->tail = skb->data + len; ++ skb->len = len; ++ ++ up(&bcm_static_skb->osl_pkt_sem); ++ return skb; ++ } ++ } ++ ++#if defined(ENHANCED_STATIC_BUF) ++ if (bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM * 2] == 0) { ++ bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM * 2] = 1; ++ ++ skb = bcm_static_skb->skb_16k; ++ skb->tail = skb->data + len; ++ skb->len = len; ++ ++ up(&bcm_static_skb->osl_pkt_sem); ++ return skb; ++ } ++#endif ++ ++ up(&bcm_static_skb->osl_pkt_sem); ++ AP6210_DEBUG("osl_pktget_static: all static pkt in use!\n"); ++ return osl_pktget(osh, len); ++} ++ ++void ++osl_pktfree_static(osl_t *osh, void *p, bool send) ++{ ++ int i; ++ if (!bcm_static_skb) { ++ osl_pktfree(osh, p, send); ++ return; ++ } ++ ++ down(&bcm_static_skb->osl_pkt_sem); ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (p == bcm_static_skb->skb_4k[i]) { ++ bcm_static_skb->pkt_use[i] = 0; ++ up(&bcm_static_skb->osl_pkt_sem); ++ return; ++ } ++ } ++ ++ for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { ++ if (p == bcm_static_skb->skb_8k[i]) { ++ bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 0; ++ up(&bcm_static_skb->osl_pkt_sem); ++ return; ++ } ++ } ++#ifdef ENHANCED_STATIC_BUF ++ if (p == bcm_static_skb->skb_16k) { ++ bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM*2] = 0; ++ up(&bcm_static_skb->osl_pkt_sem); ++ return; ++ } ++#endif ++ up(&bcm_static_skb->osl_pkt_sem); ++ ++ osl_pktfree(osh, p, send); ++ return; ++} ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ ++uint32 ++osl_pci_read_config(osl_t *osh, uint offset, uint size) ++{ ++ uint val = 0; ++ uint retry = PCI_CFG_RETRY; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ /* only 4byte access supported */ ++ ASSERT(size == 4); ++ ++ do { ++ pci_read_config_dword(osh->pdev, offset, &val); ++ if (val != 0xffffffff) ++ break; ++ } while (retry--); ++ ++ ++ return (val); ++} ++ ++void ++osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val) ++{ ++ uint retry = PCI_CFG_RETRY; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ /* only 4byte access supported */ ++ ASSERT(size == 4); ++ ++ do { ++ pci_write_config_dword(osh->pdev, offset, val); ++ if (offset != PCI_BAR0_WIN) ++ break; ++ if (osl_pci_read_config(osh, offset, size) == val) ++ break; ++ } while (retry--); ++ ++} ++ ++/* return bus # for the pci device pointed by osh->pdev */ ++uint ++osl_pci_bus(osl_t *osh) ++{ ++ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); ++ ++ return ((struct pci_dev *)osh->pdev)->bus->number; ++} ++ ++/* return slot # for the pci device pointed by osh->pdev */ ++uint ++osl_pci_slot(osl_t *osh) ++{ ++ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); ++ ++ return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); ++} ++ ++/* return the pci device pointed by osh->pdev */ ++struct pci_dev * ++osl_pci_device(osl_t *osh) ++{ ++ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); ++ ++ return osh->pdev; ++} ++ ++static void ++osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write) ++{ ++} ++ ++void ++osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size) ++{ ++ osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE); ++} ++ ++void ++osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size) ++{ ++ osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE); ++} ++ ++void * ++osl_malloc(osl_t *osh, uint size) ++{ ++ void *addr; ++ ++ /* only ASSERT if osh is defined */ ++ if (osh) ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++ if (bcm_static_buf) ++ { ++ int i = 0; ++ if ((size >= PAGE_SIZE)&&(size <= STATIC_BUF_SIZE)) ++ { ++ down(&bcm_static_buf->static_sem); ++ ++ for (i = 0; i < STATIC_BUF_MAX_NUM; i++) ++ { ++ if (bcm_static_buf->buf_use[i] == 0) ++ break; ++ } ++ ++ if (i == STATIC_BUF_MAX_NUM) ++ { ++ up(&bcm_static_buf->static_sem); ++ AP6210_DEBUG("all static buff in use!\n"); ++ goto original; ++ } ++ ++ bcm_static_buf->buf_use[i] = 1; ++ up(&bcm_static_buf->static_sem); ++ ++ bzero(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i, size); ++ if (osh) ++ atomic_add(size, &osh->malloced); ++ ++ return ((void *)(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i)); ++ } ++ } ++original: ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ ++ if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { ++ if (osh) ++ osh->failed++; ++ return (NULL); ++ } ++ if (osh) ++ atomic_add(size, &osh->malloced); ++ ++ return (addr); ++} ++ ++void ++osl_mfree(osl_t *osh, void *addr, uint size) ++{ ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++ if (bcm_static_buf) ++ { ++ if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr ++ <= ((unsigned char *)bcm_static_buf + STATIC_BUF_TOTAL_LEN))) ++ { ++ int buf_idx = 0; ++ ++ buf_idx = ((unsigned char *)addr - bcm_static_buf->buf_ptr)/STATIC_BUF_SIZE; ++ ++ down(&bcm_static_buf->static_sem); ++ bcm_static_buf->buf_use[buf_idx] = 0; ++ up(&bcm_static_buf->static_sem); ++ ++ if (osh) { ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ atomic_sub(size, &osh->malloced); ++ } ++ return; ++ } ++ } ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ if (osh) { ++ ASSERT(osh->magic == OS_HANDLE_MAGIC); ++ atomic_sub(size, &osh->malloced); ++ } ++ kfree(addr); ++} ++ ++uint ++osl_malloced(osl_t *osh) ++{ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ return (atomic_read(&osh->malloced)); ++} ++ ++uint ++osl_malloc_failed(osl_t *osh) ++{ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ return (osh->failed); ++} ++ ++ ++uint ++osl_dma_consistent_align(void) ++{ ++ return (PAGE_SIZE); ++} ++ ++void* ++osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits, uint *alloced, ulong *pap) ++{ ++ uint16 align = (1 << align_bits); ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align)) ++ size += align; ++ *alloced = size; ++ ++ return (pci_alloc_consistent(osh->pdev, size, (dma_addr_t*)pap)); ++} ++ ++void ++osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) ++{ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ ++ pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa); ++} ++ ++uint BCMFASTPATH ++osl_dma_map(osl_t *osh, void *va, uint size, int direction) ++{ ++ int dir; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; ++ return (pci_map_single(osh->pdev, va, size, dir)); ++} ++ ++void BCMFASTPATH ++osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction) ++{ ++ int dir; ++ ++ ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); ++ dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; ++ pci_unmap_single(osh->pdev, (uint32)pa, size, dir); ++} ++ ++#if defined(BCMASSERT_LOG) ++void ++osl_assert(const char *exp, const char *file, int line) ++{ ++ char tempbuf[256]; ++ const char *basename; ++ ++ basename = strrchr(file, '/'); ++ /* skip the '/' */ ++ if (basename) ++ basename++; ++ ++ if (!basename) ++ basename = file; ++ ++ snprintf(tempbuf, 64, "\"%s\": file \"%s\", line %d\n", ++ exp, basename, line); ++ ++ AP6210_DEBUG("%s", tempbuf); ++ ++ ++} ++#endif ++ ++void ++osl_delay(uint usec) ++{ ++ uint d; ++ ++ while (usec > 0) { ++ d = MIN(usec, 1000); ++ udelay(d); ++ usec -= d; ++ } ++} ++ ++ ++/* Clone a packet. ++ * The pkttag contents are NOT cloned. ++ */ ++void * ++osl_pktdup(osl_t *osh, void *skb) ++{ ++ void * p; ++ unsigned long irqflags; ++ ++ /* clear the CTFBUF flag if set and map the rest of the buffer ++ * before cloning. ++ */ ++ PKTCTFMAP(osh, skb); ++ ++ if ((p = skb_clone((struct sk_buff *)skb, GFP_ATOMIC)) == NULL) ++ return NULL; ++ ++#ifdef CTFPOOL ++ if (PKTISFAST(osh, skb)) { ++ ctfpool_t *ctfpool; ++ ++ /* if the buffer allocated from ctfpool is cloned then ++ * we can't be sure when it will be freed. since there ++ * is a chance that we will be losing a buffer ++ * from our pool, we increment the refill count for the ++ * object to be alloced later. ++ */ ++ ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb); ++ ASSERT(ctfpool != NULL); ++ PKTCLRFAST(osh, p); ++ PKTCLRFAST(osh, skb); ++ ctfpool->refills++; ++ } ++#endif /* CTFPOOL */ ++ ++ /* skb_clone copies skb->cb.. we don't want that */ ++ if (osh->pub.pkttag) ++ bzero((void*)((struct sk_buff *)p)->cb, OSL_PKTTAG_SZ); ++ ++ /* Increment the packet counter */ ++ spin_lock_irqsave(&osh->pktalloc_lock, irqflags); ++ osh->pub.pktalloced++; ++ spin_unlock_irqrestore(&osh->pktalloc_lock, irqflags); ++ return (p); ++} ++ ++ ++/* ++ * OSLREGOPS specifies the use of osl_XXX routines to be used for register access ++ */ ++ ++/* ++ * BINOSL selects the slightly slower function-call-based binary compatible osl. ++ */ ++ ++/* Linux Kernel: File Operations: start */ ++void * ++osl_os_open_image(char *filename) ++{ ++ struct file *fp; ++ ++ fp = filp_open(filename, O_RDONLY, 0); ++ /* ++ * 2.6.11 (FC4) supports filp_open() but later revs don't? ++ * Alternative: ++ * fp = open_namei(AT_FDCWD, filename, O_RD, 0); ++ * ??? ++ */ ++ if (IS_ERR(fp)) ++ fp = NULL; ++ ++ return fp; ++} ++ ++int ++osl_os_get_image_block(char *buf, int len, void *image) ++{ ++ struct file *fp = (struct file *)image; ++ int rdlen; ++ ++ if (!image) ++ return 0; ++ ++ rdlen = kernel_read(fp, fp->f_pos, buf, len); ++ if (rdlen > 0) ++ fp->f_pos += rdlen; ++ ++ return rdlen; ++} ++ ++void ++osl_os_close_image(void *image) ++{ ++ if (image) ++ filp_close((struct file *)image, NULL); ++} ++/* Linux Kernel: File Operations: end */ +diff --git a/drivers/net/wireless/ap6210/sbutils.c b/drivers/net/wireless/ap6210/sbutils.c +new file mode 100755 +index 0000000..89f9eb3 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/sbutils.c +@@ -0,0 +1,1003 @@ ++/* ++ * Misc utility routines for accessing chip-specific features ++ * of the SiliconBackplane-based Broadcom chips. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: sbutils.c 310902 2012-01-26 19:45:33Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "siutils_priv.h" ++ ++#include ++ ++ ++/* local prototypes */ ++static uint _sb_coreidx(si_info_t *sii, uint32 sba); ++static uint _sb_scan(si_info_t *sii, uint32 sba, void *regs, uint bus, uint32 sbba, ++ uint ncores); ++static uint32 _sb_coresba(si_info_t *sii); ++static void *_sb_setcoreidx(si_info_t *sii, uint coreidx); ++ ++#define SET_SBREG(sii, r, mask, val) \ ++ W_SBREG((sii), (r), ((R_SBREG((sii), (r)) & ~(mask)) | (val))) ++#define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF) ++ ++/* sonicsrev */ ++#define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT) ++#define SONICS_2_3 (SBIDL_RV_2_3 >> SBIDL_RV_SHIFT) ++ ++#define R_SBREG(sii, sbr) sb_read_sbreg((sii), (sbr)) ++#define W_SBREG(sii, sbr, v) sb_write_sbreg((sii), (sbr), (v)) ++#define AND_SBREG(sii, sbr, v) W_SBREG((sii), (sbr), (R_SBREG((sii), (sbr)) & (v))) ++#define OR_SBREG(sii, sbr, v) W_SBREG((sii), (sbr), (R_SBREG((sii), (sbr)) | (v))) ++ ++static uint32 ++sb_read_sbreg(si_info_t *sii, volatile uint32 *sbr) ++{ ++ uint8 tmp; ++ uint32 val, intr_val = 0; ++ ++ ++ /* ++ * compact flash only has 11 bits address, while we needs 12 bits address. ++ * MEM_SEG will be OR'd with other 11 bits address in hardware, ++ * so we program MEM_SEG with 12th bit when necessary(access sb regsiters). ++ * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special ++ */ ++ if (PCMCIA(sii)) { ++ INTR_OFF(sii, intr_val); ++ tmp = 1; ++ OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1); ++ sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */ ++ } ++ ++ val = R_REG(sii->osh, sbr); ++ ++ if (PCMCIA(sii)) { ++ tmp = 0; ++ OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1); ++ INTR_RESTORE(sii, intr_val); ++ } ++ ++ return (val); ++} ++ ++static void ++sb_write_sbreg(si_info_t *sii, volatile uint32 *sbr, uint32 v) ++{ ++ uint8 tmp; ++ volatile uint32 dummy; ++ uint32 intr_val = 0; ++ ++ ++ /* ++ * compact flash only has 11 bits address, while we needs 12 bits address. ++ * MEM_SEG will be OR'd with other 11 bits address in hardware, ++ * so we program MEM_SEG with 12th bit when necessary(access sb regsiters). ++ * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special ++ */ ++ if (PCMCIA(sii)) { ++ INTR_OFF(sii, intr_val); ++ tmp = 1; ++ OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1); ++ sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */ ++ } ++ ++ if (BUSTYPE(sii->pub.bustype) == PCMCIA_BUS) { ++ dummy = R_REG(sii->osh, sbr); ++ BCM_REFERENCE(dummy); ++ W_REG(sii->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff)); ++ dummy = R_REG(sii->osh, sbr); ++ BCM_REFERENCE(dummy); ++ W_REG(sii->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff)); ++ } else ++ W_REG(sii->osh, sbr, v); ++ ++ if (PCMCIA(sii)) { ++ tmp = 0; ++ OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1); ++ INTR_RESTORE(sii, intr_val); ++ } ++} ++ ++uint ++sb_coreid(si_t *sih) ++{ ++ si_info_t *sii; ++ sbconfig_t *sb; ++ ++ sii = SI_INFO(sih); ++ sb = REGS2SB(sii->curmap); ++ ++ return ((R_SBREG(sii, &sb->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT); ++} ++ ++uint ++sb_intflag(si_t *sih) ++{ ++ si_info_t *sii; ++ void *corereg; ++ sbconfig_t *sb; ++ uint origidx, intflag, intr_val = 0; ++ ++ sii = SI_INFO(sih); ++ ++ INTR_OFF(sii, intr_val); ++ origidx = si_coreidx(sih); ++ corereg = si_setcore(sih, CC_CORE_ID, 0); ++ ASSERT(corereg != NULL); ++ sb = REGS2SB(corereg); ++ intflag = R_SBREG(sii, &sb->sbflagst); ++ sb_setcoreidx(sih, origidx); ++ INTR_RESTORE(sii, intr_val); ++ ++ return intflag; ++} ++ ++uint ++sb_flag(si_t *sih) ++{ ++ si_info_t *sii; ++ sbconfig_t *sb; ++ ++ sii = SI_INFO(sih); ++ sb = REGS2SB(sii->curmap); ++ ++ return R_SBREG(sii, &sb->sbtpsflag) & SBTPS_NUM0_MASK; ++} ++ ++void ++sb_setint(si_t *sih, int siflag) ++{ ++ si_info_t *sii; ++ sbconfig_t *sb; ++ uint32 vec; ++ ++ sii = SI_INFO(sih); ++ sb = REGS2SB(sii->curmap); ++ ++ if (siflag == -1) ++ vec = 0; ++ else ++ vec = 1 << siflag; ++ W_SBREG(sii, &sb->sbintvec, vec); ++} ++ ++/* return core index of the core with address 'sba' */ ++static uint ++_sb_coreidx(si_info_t *sii, uint32 sba) ++{ ++ uint i; ++ ++ for (i = 0; i < sii->numcores; i ++) ++ if (sba == sii->coresba[i]) ++ return i; ++ return BADIDX; ++} ++ ++/* return core address of the current core */ ++static uint32 ++_sb_coresba(si_info_t *sii) ++{ ++ uint32 sbaddr; ++ ++ ++ switch (BUSTYPE(sii->pub.bustype)) { ++ case SI_BUS: { ++ sbconfig_t *sb = REGS2SB(sii->curmap); ++ sbaddr = sb_base(R_SBREG(sii, &sb->sbadmatch0)); ++ break; ++ } ++ ++ case PCI_BUS: ++ sbaddr = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); ++ break; ++ ++ case PCMCIA_BUS: { ++ uint8 tmp = 0; ++ OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR0, &tmp, 1); ++ sbaddr = (uint32)tmp << 12; ++ OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR1, &tmp, 1); ++ sbaddr |= (uint32)tmp << 16; ++ OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR2, &tmp, 1); ++ sbaddr |= (uint32)tmp << 24; ++ break; ++ } ++ ++ case SPI_BUS: ++ case SDIO_BUS: ++ sbaddr = (uint32)(uintptr)sii->curmap; ++ break; ++ ++ ++ default: ++ sbaddr = BADCOREADDR; ++ break; ++ } ++ ++ return sbaddr; ++} ++ ++uint ++sb_corevendor(si_t *sih) ++{ ++ si_info_t *sii; ++ sbconfig_t *sb; ++ ++ sii = SI_INFO(sih); ++ sb = REGS2SB(sii->curmap); ++ ++ return ((R_SBREG(sii, &sb->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT); ++} ++ ++uint ++sb_corerev(si_t *sih) ++{ ++ si_info_t *sii; ++ sbconfig_t *sb; ++ uint sbidh; ++ ++ sii = SI_INFO(sih); ++ sb = REGS2SB(sii->curmap); ++ sbidh = R_SBREG(sii, &sb->sbidhigh); ++ ++ return (SBCOREREV(sbidh)); ++} ++ ++/* set core-specific control flags */ ++void ++sb_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) ++{ ++ si_info_t *sii; ++ sbconfig_t *sb; ++ uint32 w; ++ ++ sii = SI_INFO(sih); ++ sb = REGS2SB(sii->curmap); ++ ++ ASSERT((val & ~mask) == 0); ++ ++ /* mask and set */ ++ w = (R_SBREG(sii, &sb->sbtmstatelow) & ~(mask << SBTML_SICF_SHIFT)) | ++ (val << SBTML_SICF_SHIFT); ++ W_SBREG(sii, &sb->sbtmstatelow, w); ++} ++ ++/* set/clear core-specific control flags */ ++uint32 ++sb_core_cflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ si_info_t *sii; ++ sbconfig_t *sb; ++ uint32 w; ++ ++ sii = SI_INFO(sih); ++ sb = REGS2SB(sii->curmap); ++ ++ ASSERT((val & ~mask) == 0); ++ ++ /* mask and set */ ++ if (mask || val) { ++ w = (R_SBREG(sii, &sb->sbtmstatelow) & ~(mask << SBTML_SICF_SHIFT)) | ++ (val << SBTML_SICF_SHIFT); ++ W_SBREG(sii, &sb->sbtmstatelow, w); ++ } ++ ++ /* return the new value ++ * for write operation, the following readback ensures the completion of write opration. ++ */ ++ return (R_SBREG(sii, &sb->sbtmstatelow) >> SBTML_SICF_SHIFT); ++} ++ ++/* set/clear core-specific status flags */ ++uint32 ++sb_core_sflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ si_info_t *sii; ++ sbconfig_t *sb; ++ uint32 w; ++ ++ sii = SI_INFO(sih); ++ sb = REGS2SB(sii->curmap); ++ ++ ASSERT((val & ~mask) == 0); ++ ASSERT((mask & ~SISF_CORE_BITS) == 0); ++ ++ /* mask and set */ ++ if (mask || val) { ++ w = (R_SBREG(sii, &sb->sbtmstatehigh) & ~(mask << SBTMH_SISF_SHIFT)) | ++ (val << SBTMH_SISF_SHIFT); ++ W_SBREG(sii, &sb->sbtmstatehigh, w); ++ } ++ ++ /* return the new value */ ++ return (R_SBREG(sii, &sb->sbtmstatehigh) >> SBTMH_SISF_SHIFT); ++} ++ ++bool ++sb_iscoreup(si_t *sih) ++{ ++ si_info_t *sii; ++ sbconfig_t *sb; ++ ++ sii = SI_INFO(sih); ++ sb = REGS2SB(sii->curmap); ++ ++ return ((R_SBREG(sii, &sb->sbtmstatelow) & ++ (SBTML_RESET | SBTML_REJ_MASK | (SICF_CLOCK_EN << SBTML_SICF_SHIFT))) == ++ (SICF_CLOCK_EN << SBTML_SICF_SHIFT)); ++} ++ ++/* ++ * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation, ++ * switch back to the original core, and return the new value. ++ * ++ * When using the silicon backplane, no fidleing with interrupts or core switches are needed. ++ * ++ * Also, when using pci/pcie, we can optimize away the core switching for pci registers ++ * and (on newer pci cores) chipcommon registers. ++ */ ++uint ++sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) ++{ ++ uint origidx = 0; ++ uint32 *r = NULL; ++ uint w; ++ uint intr_val = 0; ++ bool fast = FALSE; ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ ASSERT(GOODIDX(coreidx)); ++ ASSERT(regoff < SI_CORE_SIZE); ++ ASSERT((val & ~mask) == 0); ++ ++ if (coreidx >= SI_MAXCORES) ++ return 0; ++ ++ if (BUSTYPE(sii->pub.bustype) == SI_BUS) { ++ /* If internal bus, we can always get at everything */ ++ fast = TRUE; ++ /* map if does not exist */ ++ if (!sii->regs[coreidx]) { ++ sii->regs[coreidx] = REG_MAP(sii->coresba[coreidx], ++ SI_CORE_SIZE); ++ ASSERT(GOODREGS(sii->regs[coreidx])); ++ } ++ r = (uint32 *)((uchar *)sii->regs[coreidx] + regoff); ++ } else if (BUSTYPE(sii->pub.bustype) == PCI_BUS) { ++ /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ ++ ++ if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) { ++ /* Chipc registers are mapped at 12KB */ ++ ++ fast = TRUE; ++ r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff); ++ } else if (sii->pub.buscoreidx == coreidx) { ++ /* pci registers are at either in the last 2KB of an 8KB window ++ * or, in pcie and pci rev 13 at 8KB ++ */ ++ fast = TRUE; ++ if (SI_FAST(sii)) ++ r = (uint32 *)((char *)sii->curmap + ++ PCI_16KB0_PCIREGS_OFFSET + regoff); ++ else ++ r = (uint32 *)((char *)sii->curmap + ++ ((regoff >= SBCONFIGOFF) ? ++ PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + ++ regoff); ++ } ++ } ++ ++ if (!fast) { ++ INTR_OFF(sii, intr_val); ++ ++ /* save current core index */ ++ origidx = si_coreidx(&sii->pub); ++ ++ /* switch core */ ++ r = (uint32*) ((uchar*)sb_setcoreidx(&sii->pub, coreidx) + regoff); ++ } ++ ASSERT(r != NULL); ++ ++ /* mask and set */ ++ if (mask || val) { ++ if (regoff >= SBCONFIGOFF) { ++ w = (R_SBREG(sii, r) & ~mask) | val; ++ W_SBREG(sii, r, w); ++ } else { ++ w = (R_REG(sii->osh, r) & ~mask) | val; ++ W_REG(sii->osh, r, w); ++ } ++ } ++ ++ /* readback */ ++ if (regoff >= SBCONFIGOFF) ++ w = R_SBREG(sii, r); ++ else { ++ if ((CHIPID(sii->pub.chip) == BCM5354_CHIP_ID) && ++ (coreidx == SI_CC_IDX) && ++ (regoff == OFFSETOF(chipcregs_t, watchdog))) { ++ w = val; ++ } else ++ w = R_REG(sii->osh, r); ++ } ++ ++ if (!fast) { ++ /* restore core index */ ++ if (origidx != coreidx) ++ sb_setcoreidx(&sii->pub, origidx); ++ ++ INTR_RESTORE(sii, intr_val); ++ } ++ ++ return (w); ++} ++ ++/* Scan the enumeration space to find all cores starting from the given ++ * bus 'sbba'. Append coreid and other info to the lists in 'si'. 'sba' ++ * is the default core address at chip POR time and 'regs' is the virtual ++ * address that the default core is mapped at. 'ncores' is the number of ++ * cores expected on bus 'sbba'. It returns the total number of cores ++ * starting from bus 'sbba', inclusive. ++ */ ++#define SB_MAXBUSES 2 ++static uint ++_sb_scan(si_info_t *sii, uint32 sba, void *regs, uint bus, uint32 sbba, uint numcores) ++{ ++ uint next; ++ uint ncc = 0; ++ uint i; ++ ++ if (bus >= SB_MAXBUSES) { ++ AP6210_ERR("_sb_scan: bus 0x%08x at level %d is too deep to scan\n", sbba, bus); ++ return 0; ++ } ++ AP6210_DEBUG("_sb_scan: scan bus 0x%08x assume %u cores\n", sbba, numcores); ++ ++ /* Scan all cores on the bus starting from core 0. ++ * Core addresses must be contiguous on each bus. ++ */ ++ for (i = 0, next = sii->numcores; i < numcores && next < SB_BUS_MAXCORES; i++, next++) { ++ sii->coresba[next] = sbba + (i * SI_CORE_SIZE); ++ ++ /* keep and reuse the initial register mapping */ ++ if ((BUSTYPE(sii->pub.bustype) == SI_BUS) && (sii->coresba[next] == sba)) { ++ AP6210_DEBUG("_sb_scan: reuse mapped regs %p for core %u\n", regs, next); ++ sii->regs[next] = regs; ++ } ++ ++ /* change core to 'next' and read its coreid */ ++ sii->curmap = _sb_setcoreidx(sii, next); ++ sii->curidx = next; ++ ++ sii->coreid[next] = sb_coreid(&sii->pub); ++ ++ /* core specific processing... */ ++ /* chipc provides # cores */ ++ if (sii->coreid[next] == CC_CORE_ID) { ++ chipcregs_t *cc = (chipcregs_t *)sii->curmap; ++ uint32 ccrev = sb_corerev(&sii->pub); ++ ++ /* determine numcores - this is the total # cores in the chip */ ++ if (((ccrev == 4) || (ccrev >= 6))) ++ numcores = (R_REG(sii->osh, &cc->chipid) & CID_CC_MASK) >> ++ CID_CC_SHIFT; ++ else { ++ /* Older chips */ ++ uint chip = CHIPID(sii->pub.chip); ++ ++ if (chip == BCM4306_CHIP_ID) /* < 4306c0 */ ++ numcores = 6; ++ else if (chip == BCM4704_CHIP_ID) ++ numcores = 9; ++ else if (chip == BCM5365_CHIP_ID) ++ numcores = 7; ++ else { ++ AP6210_ERR("sb_chip2numcores: unsupported chip 0x%x\n", ++ chip); ++ ASSERT(0); ++ numcores = 1; ++ } ++ } ++ AP6210_DEBUG("_sb_scan: there are %u cores in the chip %s\n", numcores, ++ sii->pub.issim ? "QT" : ""); ++ } ++ /* scan bridged SB(s) and add results to the end of the list */ ++ else if (sii->coreid[next] == OCP_CORE_ID) { ++ sbconfig_t *sb = REGS2SB(sii->curmap); ++ uint32 nsbba = R_SBREG(sii, &sb->sbadmatch1); ++ uint nsbcc; ++ ++ sii->numcores = next + 1; ++ ++ if ((nsbba & 0xfff00000) != SI_ENUM_BASE) ++ continue; ++ nsbba &= 0xfffff000; ++ if (_sb_coreidx(sii, nsbba) != BADIDX) ++ continue; ++ ++ nsbcc = (R_SBREG(sii, &sb->sbtmstatehigh) & 0x000f0000) >> 16; ++ nsbcc = _sb_scan(sii, sba, regs, bus + 1, nsbba, nsbcc); ++ if (sbba == SI_ENUM_BASE) ++ numcores -= nsbcc; ++ ncc += nsbcc; ++ } ++ } ++ ++ AP6210_DEBUG("_sb_scan: found %u cores on bus 0x%08x\n", i, sbba); ++ ++ sii->numcores = i + ncc; ++ return sii->numcores; ++} ++ ++/* scan the sb enumerated space to identify all cores */ ++void ++sb_scan(si_t *sih, void *regs, uint devid) ++{ ++ si_info_t *sii; ++ uint32 origsba; ++ sbconfig_t *sb; ++ ++ sii = SI_INFO(sih); ++ sb = REGS2SB(sii->curmap); ++ ++ sii->pub.socirev = (R_SBREG(sii, &sb->sbidlow) & SBIDL_RV_MASK) >> SBIDL_RV_SHIFT; ++ ++ /* Save the current core info and validate it later till we know ++ * for sure what is good and what is bad. ++ */ ++ origsba = _sb_coresba(sii); ++ ++ /* scan all SB(s) starting from SI_ENUM_BASE */ ++ sii->numcores = _sb_scan(sii, origsba, regs, 0, SI_ENUM_BASE, 1); ++} ++ ++/* ++ * This function changes logical "focus" to the indicated core; ++ * must be called with interrupts off. ++ * Moreover, callers should keep interrupts off during switching out of and back to d11 core ++ */ ++void * ++sb_setcoreidx(si_t *sih, uint coreidx) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ if (coreidx >= sii->numcores) ++ return (NULL); ++ ++ /* ++ * If the user has provided an interrupt mask enabled function, ++ * then assert interrupts are disabled before switching the core. ++ */ ++ ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg)); ++ ++ sii->curmap = _sb_setcoreidx(sii, coreidx); ++ sii->curidx = coreidx; ++ ++ return (sii->curmap); ++} ++ ++/* This function changes the logical "focus" to the indicated core. ++ * Return the current core's virtual address. ++ */ ++static void * ++_sb_setcoreidx(si_info_t *sii, uint coreidx) ++{ ++ uint32 sbaddr = sii->coresba[coreidx]; ++ void *regs; ++ ++ switch (BUSTYPE(sii->pub.bustype)) { ++ case SI_BUS: ++ /* map new one */ ++ if (!sii->regs[coreidx]) { ++ sii->regs[coreidx] = REG_MAP(sbaddr, SI_CORE_SIZE); ++ ASSERT(GOODREGS(sii->regs[coreidx])); ++ } ++ regs = sii->regs[coreidx]; ++ break; ++ ++ case PCI_BUS: ++ /* point bar0 window */ ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, sbaddr); ++ regs = sii->curmap; ++ break; ++ ++ case PCMCIA_BUS: { ++ uint8 tmp = (sbaddr >> 12) & 0x0f; ++ OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR0, &tmp, 1); ++ tmp = (sbaddr >> 16) & 0xff; ++ OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR1, &tmp, 1); ++ tmp = (sbaddr >> 24) & 0xff; ++ OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR2, &tmp, 1); ++ regs = sii->curmap; ++ break; ++ } ++ case SPI_BUS: ++ case SDIO_BUS: ++ /* map new one */ ++ if (!sii->regs[coreidx]) { ++ sii->regs[coreidx] = (void *)(uintptr)sbaddr; ++ ASSERT(GOODREGS(sii->regs[coreidx])); ++ } ++ regs = sii->regs[coreidx]; ++ break; ++ ++ ++ default: ++ ASSERT(0); ++ regs = NULL; ++ break; ++ } ++ ++ return regs; ++} ++ ++/* Return the address of sbadmatch0/1/2/3 register */ ++static volatile uint32 * ++sb_admatch(si_info_t *sii, uint asidx) ++{ ++ sbconfig_t *sb; ++ volatile uint32 *addrm; ++ ++ sb = REGS2SB(sii->curmap); ++ ++ switch (asidx) { ++ case 0: ++ addrm = &sb->sbadmatch0; ++ break; ++ ++ case 1: ++ addrm = &sb->sbadmatch1; ++ break; ++ ++ case 2: ++ addrm = &sb->sbadmatch2; ++ break; ++ ++ case 3: ++ addrm = &sb->sbadmatch3; ++ break; ++ ++ default: ++ AP6210_ERR("%s: Address space index (%d) out of range\n", __FUNCTION__, asidx); ++ return 0; ++ } ++ ++ return (addrm); ++} ++ ++/* Return the number of address spaces in current core */ ++int ++sb_numaddrspaces(si_t *sih) ++{ ++ si_info_t *sii; ++ sbconfig_t *sb; ++ ++ sii = SI_INFO(sih); ++ sb = REGS2SB(sii->curmap); ++ ++ /* + 1 because of enumeration space */ ++ return ((R_SBREG(sii, &sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT) + 1; ++} ++ ++/* Return the address of the nth address space in the current core */ ++uint32 ++sb_addrspace(si_t *sih, uint asidx) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ return (sb_base(R_SBREG(sii, sb_admatch(sii, asidx)))); ++} ++ ++/* Return the size of the nth address space in the current core */ ++uint32 ++sb_addrspacesize(si_t *sih, uint asidx) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ return (sb_size(R_SBREG(sii, sb_admatch(sii, asidx)))); ++} ++ ++ ++/* do buffered registers update */ ++void ++sb_commit(si_t *sih) ++{ ++ si_info_t *sii; ++ uint origidx; ++ uint intr_val = 0; ++ ++ sii = SI_INFO(sih); ++ ++ origidx = sii->curidx; ++ ASSERT(GOODIDX(origidx)); ++ ++ INTR_OFF(sii, intr_val); ++ ++ /* switch over to chipcommon core if there is one, else use pci */ ++ if (sii->pub.ccrev != NOREV) { ++ chipcregs_t *ccregs = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ASSERT(ccregs != NULL); ++ ++ /* do the buffer registers update */ ++ W_REG(sii->osh, &ccregs->broadcastaddress, SB_COMMIT); ++ W_REG(sii->osh, &ccregs->broadcastdata, 0x0); ++ } else ++ ASSERT(0); ++ ++ /* restore core index */ ++ sb_setcoreidx(sih, origidx); ++ INTR_RESTORE(sii, intr_val); ++} ++ ++void ++sb_core_disable(si_t *sih, uint32 bits) ++{ ++ si_info_t *sii; ++ volatile uint32 dummy; ++ sbconfig_t *sb; ++ ++ sii = SI_INFO(sih); ++ ++ ASSERT(GOODREGS(sii->curmap)); ++ sb = REGS2SB(sii->curmap); ++ ++ /* if core is already in reset, just return */ ++ if (R_SBREG(sii, &sb->sbtmstatelow) & SBTML_RESET) ++ return; ++ ++ /* if clocks are not enabled, put into reset and return */ ++ if ((R_SBREG(sii, &sb->sbtmstatelow) & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) == 0) ++ goto disable; ++ ++ /* set target reject and spin until busy is clear (preserve core-specific bits) */ ++ OR_SBREG(sii, &sb->sbtmstatelow, SBTML_REJ); ++ dummy = R_SBREG(sii, &sb->sbtmstatelow); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++ SPINWAIT((R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_BUSY), 100000); ++ if (R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_BUSY) ++ AP6210_ERR("%s: target state still busy\n", __FUNCTION__); ++ ++ if (R_SBREG(sii, &sb->sbidlow) & SBIDL_INIT) { ++ OR_SBREG(sii, &sb->sbimstate, SBIM_RJ); ++ dummy = R_SBREG(sii, &sb->sbimstate); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++ SPINWAIT((R_SBREG(sii, &sb->sbimstate) & SBIM_BY), 100000); ++ } ++ ++ /* set reset and reject while enabling the clocks */ ++ W_SBREG(sii, &sb->sbtmstatelow, ++ (((bits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | ++ SBTML_REJ | SBTML_RESET)); ++ dummy = R_SBREG(sii, &sb->sbtmstatelow); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(10); ++ ++ /* don't forget to clear the initiator reject bit */ ++ if (R_SBREG(sii, &sb->sbidlow) & SBIDL_INIT) ++ AND_SBREG(sii, &sb->sbimstate, ~SBIM_RJ); ++ ++disable: ++ /* leave reset and reject asserted */ ++ W_SBREG(sii, &sb->sbtmstatelow, ((bits << SBTML_SICF_SHIFT) | SBTML_REJ | SBTML_RESET)); ++ OSL_DELAY(1); ++} ++ ++/* reset and re-enable a core ++ * inputs: ++ * bits - core specific bits that are set during and after reset sequence ++ * resetbits - core specific bits that are set only during reset sequence ++ */ ++void ++sb_core_reset(si_t *sih, uint32 bits, uint32 resetbits) ++{ ++ si_info_t *sii; ++ sbconfig_t *sb; ++ volatile uint32 dummy; ++ ++ sii = SI_INFO(sih); ++ ASSERT(GOODREGS(sii->curmap)); ++ sb = REGS2SB(sii->curmap); ++ ++ /* ++ * Must do the disable sequence first to work for arbitrary current core state. ++ */ ++ sb_core_disable(sih, (bits | resetbits)); ++ ++ /* ++ * Now do the initialization sequence. ++ */ ++ ++ /* set reset while enabling the clock and forcing them on throughout the core */ ++ W_SBREG(sii, &sb->sbtmstatelow, ++ (((bits | resetbits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | ++ SBTML_RESET)); ++ dummy = R_SBREG(sii, &sb->sbtmstatelow); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++ ++ if (R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_SERR) { ++ W_SBREG(sii, &sb->sbtmstatehigh, 0); ++ } ++ if ((dummy = R_SBREG(sii, &sb->sbimstate)) & (SBIM_IBE | SBIM_TO)) { ++ AND_SBREG(sii, &sb->sbimstate, ~(SBIM_IBE | SBIM_TO)); ++ } ++ ++ /* clear reset and allow it to propagate throughout the core */ ++ W_SBREG(sii, &sb->sbtmstatelow, ++ ((bits | resetbits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT)); ++ dummy = R_SBREG(sii, &sb->sbtmstatelow); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++ ++ /* leave clock enabled */ ++ W_SBREG(sii, &sb->sbtmstatelow, ((bits | SICF_CLOCK_EN) << SBTML_SICF_SHIFT)); ++ dummy = R_SBREG(sii, &sb->sbtmstatelow); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); ++} ++ ++/* ++ * Set the initiator timeout for the "master core". ++ * The master core is defined to be the core in control ++ * of the chip and so it issues accesses to non-memory ++ * locations (Because of dma *any* core can access memeory). ++ * ++ * The routine uses the bus to decide who is the master: ++ * SI_BUS => mips ++ * JTAG_BUS => chipc ++ * PCI_BUS => pci or pcie ++ * PCMCIA_BUS => pcmcia ++ * SDIO_BUS => pcmcia ++ * ++ * This routine exists so callers can disable initiator ++ * timeouts so accesses to very slow devices like otp ++ * won't cause an abort. The routine allows arbitrary ++ * settings of the service and request timeouts, though. ++ * ++ * Returns the timeout state before changing it or -1 ++ * on error. ++ */ ++ ++#define TO_MASK (SBIMCL_RTO_MASK | SBIMCL_STO_MASK) ++ ++uint32 ++sb_set_initiator_to(si_t *sih, uint32 to, uint idx) ++{ ++ si_info_t *sii; ++ uint origidx; ++ uint intr_val = 0; ++ uint32 tmp, ret = 0xffffffff; ++ sbconfig_t *sb; ++ ++ sii = SI_INFO(sih); ++ ++ if ((to & ~TO_MASK) != 0) ++ return ret; ++ ++ /* Figure out the master core */ ++ if (idx == BADIDX) { ++ switch (BUSTYPE(sii->pub.bustype)) { ++ case PCI_BUS: ++ idx = sii->pub.buscoreidx; ++ break; ++ case JTAG_BUS: ++ idx = SI_CC_IDX; ++ break; ++ case PCMCIA_BUS: ++ case SDIO_BUS: ++ idx = si_findcoreidx(sih, PCMCIA_CORE_ID, 0); ++ break; ++ case SI_BUS: ++ idx = si_findcoreidx(sih, MIPS33_CORE_ID, 0); ++ break; ++ default: ++ ASSERT(0); ++ } ++ if (idx == BADIDX) ++ return ret; ++ } ++ ++ INTR_OFF(sii, intr_val); ++ origidx = si_coreidx(sih); ++ ++ sb = REGS2SB(sb_setcoreidx(sih, idx)); ++ ++ tmp = R_SBREG(sii, &sb->sbimconfiglow); ++ ret = tmp & TO_MASK; ++ W_SBREG(sii, &sb->sbimconfiglow, (tmp & ~TO_MASK) | to); ++ ++ sb_commit(sih); ++ sb_setcoreidx(sih, origidx); ++ INTR_RESTORE(sii, intr_val); ++ return ret; ++} ++ ++uint32 ++sb_base(uint32 admatch) ++{ ++ uint32 base; ++ uint type; ++ ++ type = admatch & SBAM_TYPE_MASK; ++ ASSERT(type < 3); ++ ++ base = 0; ++ ++ if (type == 0) { ++ base = admatch & SBAM_BASE0_MASK; ++ } else if (type == 1) { ++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ ++ base = admatch & SBAM_BASE1_MASK; ++ } else if (type == 2) { ++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ ++ base = admatch & SBAM_BASE2_MASK; ++ } ++ ++ return (base); ++} ++ ++uint32 ++sb_size(uint32 admatch) ++{ ++ uint32 size; ++ uint type; ++ ++ type = admatch & SBAM_TYPE_MASK; ++ ASSERT(type < 3); ++ ++ size = 0; ++ ++ if (type == 0) { ++ size = 1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) + 1); ++ } else if (type == 1) { ++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ ++ size = 1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) + 1); ++ } else if (type == 2) { ++ ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ ++ size = 1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) + 1); ++ } ++ ++ return (size); ++} +diff --git a/drivers/net/wireless/ap6210/siutils.c b/drivers/net/wireless/ap6210/siutils.c +new file mode 100755 +index 0000000..f917c41 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/siutils.c +@@ -0,0 +1,2472 @@ ++/* ++ * Misc utility routines for accessing chip-specific features ++ * of the SiliconBackplane-based Broadcom chips. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: siutils.c 347632 2012-07-27 11:00:35Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "siutils_priv.h" ++ ++#include ++ ++/* local prototypes */ ++static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, ++ uint bustype, void *sdh, char **vars, uint *varsz); ++static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh); ++static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, ++ uint *origidx, void *regs); ++ ++ ++ ++/* global variable to indicate reservation/release of gpio's */ ++static uint32 si_gpioreservation = 0; ++ ++/* global flag to prevent shared resources from being initialized multiple times in si_attach() */ ++ ++int do_4360_pcie2_war = 0; ++ ++/* ++ * Allocate a si handle. ++ * devid - pci device id (used to determine chip#) ++ * osh - opaque OS handle ++ * regs - virtual address of initial core registers ++ * bustype - pci/pcmcia/sb/sdio/etc ++ * vars - pointer to a pointer area for "environment" variables ++ * varsz - pointer to int to return the size of the vars ++ */ ++si_t * ++si_attach(uint devid, osl_t *osh, void *regs, ++ uint bustype, void *sdh, char **vars, uint *varsz) ++{ ++ si_info_t *sii; ++ ++ /* alloc si_info_t */ ++ if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) { ++ AP6210_ERR("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)); ++ return (NULL); ++ } ++ ++ if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) { ++ MFREE(osh, sii, sizeof(si_info_t)); ++ return (NULL); ++ } ++ sii->vars = vars ? *vars : NULL; ++ sii->varsz = varsz ? *varsz : 0; ++ ++ return (si_t *)sii; ++} ++ ++/* global kernel resource */ ++static si_info_t ksii; ++ ++static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */ ++ ++/* generic kernel variant of si_attach() */ ++si_t * ++si_kattach(osl_t *osh) ++{ ++ static bool ksii_attached = FALSE; ++ ++ if (!ksii_attached) { ++ void *regs = NULL; ++ regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); ++ ++ if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs, ++ SI_BUS, NULL, ++ osh != SI_OSH ? &ksii.vars : NULL, ++ osh != SI_OSH ? &ksii.varsz : NULL) == NULL) { ++ AP6210_ERR("si_kattach: si_doattach failed\n"); ++ REG_UNMAP(regs); ++ return NULL; ++ } ++ REG_UNMAP(regs); ++ ++ /* save ticks normalized to ms for si_watchdog_ms() */ ++ if (PMUCTL_ENAB(&ksii.pub)) { ++ /* based on 32KHz ILP clock */ ++ wd_msticks = 32; ++ } else { ++ wd_msticks = ALP_CLOCK / 1000; ++ } ++ ++ ksii_attached = TRUE; ++ AP6210_DEBUG("si_kattach done. ccrev = %d, wd_msticks = %d\n", ++ ksii.pub.ccrev, wd_msticks); ++ } ++ ++ return &ksii.pub; ++} ++ ++ ++static bool ++si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh) ++{ ++ /* need to set memseg flag for CF card first before any sb registers access */ ++ if (BUSTYPE(bustype) == PCMCIA_BUS) ++ sii->memseg = TRUE; ++ ++ ++ if (BUSTYPE(bustype) == SDIO_BUS) { ++ int err; ++ uint8 clkset; ++ ++ /* Try forcing SDIO core to do ALPAvail request only */ ++ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); ++ if (!err) { ++ uint8 clkval; ++ ++ /* If register supported, wait for ALPAvail and then force ALP */ ++ clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, NULL); ++ if ((clkval & ~SBSDIO_AVBITS) == clkset) { ++ SPINWAIT(((clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, ++ SBSDIO_FUNC1_CHIPCLKCSR, NULL)), !SBSDIO_ALPAV(clkval)), ++ PMU_MAX_TRANSITION_DLY); ++ if (!SBSDIO_ALPAV(clkval)) { ++ AP6210_ERR("timeout on ALPAV wait, clkval 0x%02x\n", ++ clkval); ++ return FALSE; ++ } ++ clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP; ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, ++ clkset, &err); ++ OSL_DELAY(65); ++ } ++ } ++ ++ /* Also, disable the extra SDIO pull-ups */ ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); ++ } ++ ++ ++ return TRUE; ++} ++ ++static bool ++si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, ++ uint *origidx, void *regs) ++{ ++ bool pci, pcie, pcie_gen2 = FALSE; ++ uint i; ++ uint pciidx, pcieidx, pcirev, pcierev; ++ ++ cc = si_setcoreidx(&sii->pub, SI_CC_IDX); ++ ASSERT((uintptr)cc); ++ ++ /* get chipcommon rev */ ++ sii->pub.ccrev = (int)si_corerev(&sii->pub); ++ ++ /* get chipcommon chipstatus */ ++ if (sii->pub.ccrev >= 11) ++ sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus); ++ ++ /* get chipcommon capabilites */ ++ sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities); ++ /* get chipcommon extended capabilities */ ++ ++ if (sii->pub.ccrev >= 35) ++ sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext); ++ ++ /* get pmu rev and caps */ ++ if (sii->pub.cccaps & CC_CAP_PMU) { ++ sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities); ++ sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; ++ } ++ ++ AP6210_DEBUG("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n", ++ sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev, ++ sii->pub.pmucaps); ++ ++ /* figure out bus/orignal core idx */ ++ sii->pub.buscoretype = NODEV_CORE_ID; ++ sii->pub.buscorerev = (uint)NOREV; ++ sii->pub.buscoreidx = BADIDX; ++ ++ pci = pcie = FALSE; ++ pcirev = pcierev = (uint)NOREV; ++ pciidx = pcieidx = BADIDX; ++ ++ for (i = 0; i < sii->numcores; i++) { ++ uint cid, crev; ++ ++ si_setcoreidx(&sii->pub, i); ++ cid = si_coreid(&sii->pub); ++ crev = si_corerev(&sii->pub); ++ ++ /* Display cores found */ ++ AP6210_DEBUG("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", ++ i, cid, crev, sii->coresba[i], sii->regs[i]); ++ ++ if (BUSTYPE(bustype) == PCI_BUS) { ++ if (cid == PCI_CORE_ID) { ++ pciidx = i; ++ pcirev = crev; ++ pci = TRUE; ++ } else if ((cid == PCIE_CORE_ID) || (cid == PCIE2_CORE_ID)) { ++ pcieidx = i; ++ pcierev = crev; ++ pcie = TRUE; ++ if (cid == PCIE2_CORE_ID) ++ pcie_gen2 = TRUE; ++ } ++ } else if ((BUSTYPE(bustype) == PCMCIA_BUS) && ++ (cid == PCMCIA_CORE_ID)) { ++ sii->pub.buscorerev = crev; ++ sii->pub.buscoretype = cid; ++ sii->pub.buscoreidx = i; ++ } ++ else if (((BUSTYPE(bustype) == SDIO_BUS) || ++ (BUSTYPE(bustype) == SPI_BUS)) && ++ ((cid == PCMCIA_CORE_ID) || ++ (cid == SDIOD_CORE_ID))) { ++ sii->pub.buscorerev = crev; ++ sii->pub.buscoretype = cid; ++ sii->pub.buscoreidx = i; ++ } ++ ++ /* find the core idx before entering this func. */ ++ if ((savewin && (savewin == sii->coresba[i])) || ++ (regs == sii->regs[i])) ++ *origidx = i; ++ } ++ ++ if (pci) { ++ sii->pub.buscoretype = PCI_CORE_ID; ++ sii->pub.buscorerev = pcirev; ++ sii->pub.buscoreidx = pciidx; ++ } else if (pcie) { ++ if (pcie_gen2) ++ sii->pub.buscoretype = PCIE2_CORE_ID; ++ else ++ sii->pub.buscoretype = PCIE_CORE_ID; ++ sii->pub.buscorerev = pcierev; ++ sii->pub.buscoreidx = pcieidx; ++ } ++ ++ AP6210_DEBUG("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype, ++ sii->pub.buscorerev); ++ ++ if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) && ++ (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3)) ++ OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL); ++ ++ ++ /* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was ++ * already running. ++ */ ++ if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) { ++ if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) || ++ si_setcore(&sii->pub, ARMCM3_CORE_ID, 0)) ++ si_core_disable(&sii->pub, 0); ++ } ++ ++ /* return to the original core */ ++ si_setcoreidx(&sii->pub, *origidx); ++ ++ return TRUE; ++} ++ ++ ++ ++ ++static si_info_t * ++si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, ++ uint bustype, void *sdh, char **vars, uint *varsz) ++{ ++ struct si_pub *sih = &sii->pub; ++ uint32 w, savewin; ++ chipcregs_t *cc; ++ char *pvars = NULL; ++ uint origidx; ++ ++ ASSERT(GOODREGS(regs)); ++ ++ bzero((uchar*)sii, sizeof(si_info_t)); ++ ++ savewin = 0; ++ ++ sih->buscoreidx = BADIDX; ++ ++ sii->curmap = regs; ++ sii->sdh = sdh; ++ sii->osh = osh; ++ ++ ++ ++ /* find Chipcommon address */ ++ if (bustype == PCI_BUS) { ++ savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); ++ if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) ++ savewin = SI_ENUM_BASE; ++ OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE); ++ if (!regs) ++ return NULL; ++ cc = (chipcregs_t *)regs; ++ } else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) { ++ cc = (chipcregs_t *)sii->curmap; ++ } else { ++ cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); ++ } ++ ++ sih->bustype = bustype; ++ if (bustype != BUSTYPE(bustype)) { ++ AP6210_ERR("si_doattach: bus type %d does not match configured bus type %d\n", ++ bustype, BUSTYPE(bustype)); ++ return NULL; ++ } ++ ++ /* bus/core/clk setup for register access */ ++ if (!si_buscore_prep(sii, bustype, devid, sdh)) { ++ AP6210_ERR("si_doattach: si_core_clk_prep failed %d\n", bustype); ++ return NULL; ++ } ++ ++ /* ChipID recognition. ++ * We assume we can read chipid at offset 0 from the regs arg. ++ * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon), ++ * some way of recognizing them needs to be added here. ++ */ ++ if (!cc) { ++ AP6210_ERR("%s: chipcommon register space is null \n", __FUNCTION__); ++ return NULL; ++ } ++ w = R_REG(osh, &cc->chipid); ++ sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; ++ /* Might as wll fill in chip id rev & pkg */ ++ sih->chip = w & CID_ID_MASK; ++ sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; ++ sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; ++ ++#if defined(HW_OOB) ++ bcmsdh_config_hw_oob_intr(sdh, sih->chip); ++#endif ++ ++ if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) && ++ (sih->chippkg != BCM4329_289PIN_PKG_ID)) { ++ sih->chippkg = BCM4329_182PIN_PKG_ID; ++ } ++ sih->issim = IS_SIM(sih->chippkg); ++ ++ /* scan for cores */ ++ if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) { ++ AP6210_DEBUG("Found chip type SB (0x%08x)\n", w); ++ sb_scan(&sii->pub, regs, devid); ++ } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) { ++ AP6210_DEBUG("Found chip type AI (0x%08x)\n", w); ++ /* pass chipc address instead of original core base */ ++ ai_scan(&sii->pub, (void *)(uintptr)cc, devid); ++ } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) { ++ AP6210_DEBUG("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip); ++ /* pass chipc address instead of original core base */ ++ ub_scan(&sii->pub, (void *)(uintptr)cc, devid); ++ } else { ++ AP6210_ERR("Found chip of unknown type (0x%08x)\n", w); ++ return NULL; ++ } ++ /* no cores found, bail out */ ++ if (sii->numcores == 0) { ++ AP6210_ERR("si_doattach: could not find any cores\n"); ++ return NULL; ++ } ++ /* bus/core/clk setup */ ++ origidx = SI_CC_IDX; ++ if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) { ++ AP6210_ERR("si_doattach: si_buscore_setup failed\n"); ++ goto exit; ++ } ++ ++ if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK) ++ >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT | ++ CST4322_SPROM_PRESENT))) { ++ AP6210_ERR("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__); ++ return NULL; ++ } ++ ++ /* assume current core is CC */ ++ if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID || ++ CHIPID(sih->chip) == BCM43235_CHIP_ID || ++ CHIPID(sih->chip) == BCM43234_CHIP_ID || ++ CHIPID(sih->chip) == BCM43238_CHIP_ID) && ++ (CHIPREV(sii->pub.chiprev) <= 2))) { ++ ++ if ((cc->chipstatus & CST43236_BP_CLK) != 0) { ++ uint clkdiv; ++ clkdiv = R_REG(osh, &cc->clkdiv); ++ /* otp_clk_div is even number, 120/14 < 9mhz */ ++ clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT); ++ W_REG(osh, &cc->clkdiv, clkdiv); ++ AP6210_ERR("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv); ++ } ++ OSL_DELAY(10); ++ } ++ ++ if (bustype == PCI_BUS) { ++ ++ } ++ ++ pvars = NULL; ++ BCM_REFERENCE(pvars); ++ ++ ++ ++ if (sii->pub.ccrev >= 20) { ++ uint32 gpiopullup = 0, gpiopulldown = 0; ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ASSERT(cc != NULL); ++ ++ /* 4314/43142 has pin muxing, don't clear gpio bits */ ++ if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43142_CHIP_ID)) { ++ gpiopullup |= 0x402e0; ++ gpiopulldown |= 0x20500; ++ } ++ ++ W_REG(osh, &cc->gpiopullup, gpiopullup); ++ W_REG(osh, &cc->gpiopulldown, gpiopulldown); ++ si_setcoreidx(sih, origidx); ++ } ++ ++ ++ /* clear any previous epidiag-induced target abort */ ++ ASSERT(!si_taclear(sih, FALSE)); ++ ++ return (sii); ++ ++exit: ++ ++ return NULL; ++} ++ ++/* may be called with core in reset */ ++void ++si_detach(si_t *sih) ++{ ++ si_info_t *sii; ++ uint idx; ++ ++ ++ sii = SI_INFO(sih); ++ ++ if (sii == NULL) ++ return; ++ ++ if (BUSTYPE(sih->bustype) == SI_BUS) ++ for (idx = 0; idx < SI_MAXCORES; idx++) ++ if (sii->regs[idx]) { ++ REG_UNMAP(sii->regs[idx]); ++ sii->regs[idx] = NULL; ++ } ++ ++ ++ ++#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS) ++ if (sii != &ksii) ++#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */ ++ MFREE(sii->osh, sii, sizeof(si_info_t)); ++} ++ ++void * ++si_osh(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ return sii->osh; ++} ++ ++void ++si_setosh(si_t *sih, osl_t *osh) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ if (sii->osh != NULL) { ++ AP6210_ERR("osh is already set....\n"); ++ ASSERT(!sii->osh); ++ } ++ sii->osh = osh; ++} ++ ++/* register driver interrupt disabling and restoring callback functions */ ++void ++si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn, ++ void *intrsenabled_fn, void *intr_arg) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ sii->intr_arg = intr_arg; ++ sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn; ++ sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn; ++ sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn; ++ /* save current core id. when this function called, the current core ++ * must be the core which provides driver functions(il, et, wl, etc.) ++ */ ++ sii->dev_coreid = sii->coreid[sii->curidx]; ++} ++ ++void ++si_deregister_intr_callback(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ sii->intrsoff_fn = NULL; ++} ++ ++uint ++si_intflag(si_t *sih) ++{ ++ si_info_t *sii = SI_INFO(sih); ++ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_intflag(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ return R_REG(sii->osh, ((uint32 *)(uintptr) ++ (sii->oob_router + OOB_STATUSA))); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++uint ++si_flag(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_flag(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ return ai_flag(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_flag(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_setint(si_t *sih, int siflag) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_setint(sih, siflag); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ ai_setint(sih, siflag); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_setint(sih, siflag); ++ else ++ ASSERT(0); ++} ++ ++uint ++si_coreid(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ return sii->coreid[sii->curidx]; ++} ++ ++uint ++si_coreidx(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ return sii->curidx; ++} ++ ++/* return the core-type instantiation # of the current core */ ++uint ++si_coreunit(si_t *sih) ++{ ++ si_info_t *sii; ++ uint idx; ++ uint coreid; ++ uint coreunit; ++ uint i; ++ ++ sii = SI_INFO(sih); ++ coreunit = 0; ++ ++ idx = sii->curidx; ++ ++ ASSERT(GOODREGS(sii->curmap)); ++ coreid = si_coreid(sih); ++ ++ /* count the cores of our type */ ++ for (i = 0; i < idx; i++) ++ if (sii->coreid[i] == coreid) ++ coreunit++; ++ ++ return (coreunit); ++} ++ ++uint ++si_corevendor(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_corevendor(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ return ai_corevendor(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_corevendor(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++bool ++si_backplane64(si_t *sih) ++{ ++ return ((sih->cccaps & CC_CAP_BKPLN64) != 0); ++} ++ ++uint ++si_corerev(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_corerev(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ return ai_corerev(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_corerev(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++/* return index of coreid or BADIDX if not found */ ++uint ++si_findcoreidx(si_t *sih, uint coreid, uint coreunit) ++{ ++ si_info_t *sii; ++ uint found; ++ uint i; ++ ++ sii = SI_INFO(sih); ++ ++ found = 0; ++ ++ for (i = 0; i < sii->numcores; i++) ++ if (sii->coreid[i] == coreid) { ++ if (found == coreunit) ++ return (i); ++ found++; ++ } ++ ++ return (BADIDX); ++} ++ ++/* return list of found cores */ ++uint ++si_corelist(si_t *sih, uint coreid[]) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint))); ++ return (sii->numcores); ++} ++ ++/* return current register mapping */ ++void * ++si_coreregs(si_t *sih) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ASSERT(GOODREGS(sii->curmap)); ++ ++ return (sii->curmap); ++} ++ ++/* ++ * This function changes logical "focus" to the indicated core; ++ * must be called with interrupts off. ++ * Moreover, callers should keep interrupts off during switching out of and back to d11 core ++ */ ++void * ++si_setcore(si_t *sih, uint coreid, uint coreunit) ++{ ++ uint idx; ++ ++ idx = si_findcoreidx(sih, coreid, coreunit); ++ if (!GOODIDX(idx)) ++ return (NULL); ++ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_setcoreidx(sih, idx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ return ai_setcoreidx(sih, idx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_setcoreidx(sih, idx); ++ else { ++ ASSERT(0); ++ return NULL; ++ } ++} ++ ++void * ++si_setcoreidx(si_t *sih, uint coreidx) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_setcoreidx(sih, coreidx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ return ai_setcoreidx(sih, coreidx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_setcoreidx(sih, coreidx); ++ else { ++ ASSERT(0); ++ return NULL; ++ } ++} ++ ++/* Turn off interrupt as required by sb_setcore, before switch core */ ++void * ++si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val) ++{ ++ void *cc; ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ if (SI_FAST(sii)) { ++ /* Overloading the origidx variable to remember the coreid, ++ * this works because the core ids cannot be confused with ++ * core indices. ++ */ ++ *origidx = coreid; ++ if (coreid == CC_CORE_ID) ++ return (void *)CCREGS_FAST(sii); ++ else if (coreid == sih->buscoretype) ++ return (void *)PCIEREGS(sii); ++ } ++ INTR_OFF(sii, *intr_val); ++ *origidx = sii->curidx; ++ cc = si_setcore(sih, coreid, 0); ++ ASSERT(cc != NULL); ++ ++ return cc; ++} ++ ++/* restore coreidx and restore interrupt */ ++void ++si_restore_core(si_t *sih, uint coreid, uint intr_val) ++{ ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype))) ++ return; ++ ++ si_setcoreidx(sih, coreid); ++ INTR_RESTORE(sii, intr_val); ++} ++ ++int ++si_numaddrspaces(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_numaddrspaces(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ return ai_numaddrspaces(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_numaddrspaces(sih); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++uint32 ++si_addrspace(si_t *sih, uint asidx) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_addrspace(sih, asidx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ return ai_addrspace(sih, asidx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_addrspace(sih, asidx); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++uint32 ++si_addrspacesize(si_t *sih, uint asidx) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_addrspacesize(sih, asidx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ return ai_addrspacesize(sih, asidx); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_addrspacesize(sih, asidx); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) ++{ ++ /* Only supported for SOCI_AI */ ++ if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ ai_coreaddrspaceX(sih, asidx, addr, size); ++ else ++ *size = 0; ++} ++ ++uint32 ++si_core_cflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_core_cflags(sih, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ return ai_core_cflags(sih, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_core_cflags(sih, mask, val); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_core_cflags_wo(sih, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ ai_core_cflags_wo(sih, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_core_cflags_wo(sih, mask, val); ++ else ++ ASSERT(0); ++} ++ ++uint32 ++si_core_sflags(si_t *sih, uint32 mask, uint32 val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_core_sflags(sih, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ return ai_core_sflags(sih, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_core_sflags(sih, mask, val); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++bool ++si_iscoreup(si_t *sih) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_iscoreup(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ return ai_iscoreup(sih); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_iscoreup(sih); ++ else { ++ ASSERT(0); ++ return FALSE; ++ } ++} ++ ++uint ++si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val) ++{ ++ /* only for AI back plane chips */ ++ if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ return (ai_wrap_reg(sih, offset, mask, val)); ++ return 0; ++} ++ ++uint ++si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ return sb_corereg(sih, coreidx, regoff, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ return ai_corereg(sih, coreidx, regoff, mask, val); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ return ub_corereg(sih, coreidx, regoff, mask, val); ++ else { ++ ASSERT(0); ++ return 0; ++ } ++} ++ ++void ++si_core_disable(si_t *sih, uint32 bits) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_core_disable(sih, bits); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ ai_core_disable(sih, bits); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_core_disable(sih, bits); ++} ++ ++void ++si_core_reset(si_t *sih, uint32 bits, uint32 resetbits) ++{ ++ if (CHIPTYPE(sih->socitype) == SOCI_SB) ++ sb_core_reset(sih, bits, resetbits); ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) ++ ai_core_reset(sih, bits, resetbits); ++ else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ++ ub_core_reset(sih, bits, resetbits); ++} ++ ++/* Run bist on current core. Caller needs to take care of core-specific bist hazards */ ++int ++si_corebist(si_t *sih) ++{ ++ uint32 cflags; ++ int result = 0; ++ ++ /* Read core control flags */ ++ cflags = si_core_cflags(sih, 0, 0); ++ ++ /* Set bist & fgc */ ++ si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC)); ++ ++ /* Wait for bist done */ ++ SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000); ++ ++ if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR) ++ result = BCME_ERROR; ++ ++ /* Reset core control flags */ ++ si_core_cflags(sih, 0xffff, cflags); ++ ++ return result; ++} ++ ++static uint32 ++factor6(uint32 x) ++{ ++ switch (x) { ++ case CC_F6_2: return 2; ++ case CC_F6_3: return 3; ++ case CC_F6_4: return 4; ++ case CC_F6_5: return 5; ++ case CC_F6_6: return 6; ++ case CC_F6_7: return 7; ++ default: return 0; ++ } ++} ++ ++/* calculate the speed the SI would run at given a set of clockcontrol values */ ++uint32 ++si_clock_rate(uint32 pll_type, uint32 n, uint32 m) ++{ ++ uint32 n1, n2, clock, m1, m2, m3, mc; ++ ++ n1 = n & CN_N1_MASK; ++ n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT; ++ ++ if (pll_type == PLL_TYPE6) { ++ if (m & CC_T6_MMASK) ++ return CC_T6_M1; ++ else ++ return CC_T6_M0; ++ } else if ((pll_type == PLL_TYPE1) || ++ (pll_type == PLL_TYPE3) || ++ (pll_type == PLL_TYPE4) || ++ (pll_type == PLL_TYPE7)) { ++ n1 = factor6(n1); ++ n2 += CC_F5_BIAS; ++ } else if (pll_type == PLL_TYPE2) { ++ n1 += CC_T2_BIAS; ++ n2 += CC_T2_BIAS; ++ ASSERT((n1 >= 2) && (n1 <= 7)); ++ ASSERT((n2 >= 5) && (n2 <= 23)); ++ } else if (pll_type == PLL_TYPE5) { ++ return (100000000); ++ } else ++ ASSERT(0); ++ /* PLL types 3 and 7 use BASE2 (25Mhz) */ ++ if ((pll_type == PLL_TYPE3) || ++ (pll_type == PLL_TYPE7)) { ++ clock = CC_CLOCK_BASE2 * n1 * n2; ++ } else ++ clock = CC_CLOCK_BASE1 * n1 * n2; ++ ++ if (clock == 0) ++ return 0; ++ ++ m1 = m & CC_M1_MASK; ++ m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT; ++ m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT; ++ mc = (m & CC_MC_MASK) >> CC_MC_SHIFT; ++ ++ if ((pll_type == PLL_TYPE1) || ++ (pll_type == PLL_TYPE3) || ++ (pll_type == PLL_TYPE4) || ++ (pll_type == PLL_TYPE7)) { ++ m1 = factor6(m1); ++ if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3)) ++ m2 += CC_F5_BIAS; ++ else ++ m2 = factor6(m2); ++ m3 = factor6(m3); ++ ++ switch (mc) { ++ case CC_MC_BYPASS: return (clock); ++ case CC_MC_M1: return (clock / m1); ++ case CC_MC_M1M2: return (clock / (m1 * m2)); ++ case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3)); ++ case CC_MC_M1M3: return (clock / (m1 * m3)); ++ default: return (0); ++ } ++ } else { ++ ASSERT(pll_type == PLL_TYPE2); ++ ++ m1 += CC_T2_BIAS; ++ m2 += CC_T2M2_BIAS; ++ m3 += CC_T2_BIAS; ++ ASSERT((m1 >= 2) && (m1 <= 7)); ++ ASSERT((m2 >= 3) && (m2 <= 10)); ++ ASSERT((m3 >= 2) && (m3 <= 7)); ++ ++ if ((mc & CC_T2MC_M1BYP) == 0) ++ clock /= m1; ++ if ((mc & CC_T2MC_M2BYP) == 0) ++ clock /= m2; ++ if ((mc & CC_T2MC_M3BYP) == 0) ++ clock /= m3; ++ ++ return (clock); ++ } ++} ++ ++ ++/* set chip watchdog reset timer to fire in 'ticks' */ ++void ++si_watchdog(si_t *sih, uint ticks) ++{ ++ uint nb, maxt; ++ ++ if (PMUCTL_ENAB(sih)) { ++ ++ if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) && ++ (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) { ++ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2); ++ si_setcore(sih, USB20D_CORE_ID, 0); ++ si_core_disable(sih, 1); ++ si_setcore(sih, CC_CORE_ID, 0); ++ } ++ ++ nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24); ++ /* The mips compiler uses the sllv instruction, ++ * so we specially handle the 32-bit case. ++ */ ++ if (nb == 32) ++ maxt = 0xffffffff; ++ else ++ maxt = ((1 << nb) - 1); ++ ++ if (ticks == 1) ++ ticks = 2; ++ else if (ticks > maxt) ++ ticks = maxt; ++ ++ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks); ++ } else { ++ maxt = (1 << 28) - 1; ++ if (ticks > maxt) ++ ticks = maxt; ++ ++ si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks); ++ } ++} ++ ++/* trigger watchdog reset after ms milliseconds */ ++void ++si_watchdog_ms(si_t *sih, uint32 ms) ++{ ++ si_watchdog(sih, wd_msticks * ms); ++} ++ ++uint32 si_watchdog_msticks(void) ++{ ++ return wd_msticks; ++} ++ ++bool ++si_taclear(si_t *sih, bool details) ++{ ++ return FALSE; ++} ++ ++ ++ ++/* return the slow clock source - LPO, XTAL, or PCI */ ++static uint ++si_slowclk_src(si_info_t *sii) ++{ ++ chipcregs_t *cc; ++ ++ ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); ++ ++ if (sii->pub.ccrev < 6) { ++ if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) && ++ (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) & ++ PCI_CFG_GPIO_SCS)) ++ return (SCC_SS_PCI); ++ else ++ return (SCC_SS_XTAL); ++ } else if (sii->pub.ccrev < 10) { ++ cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx); ++ return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK); ++ } else /* Insta-clock */ ++ return (SCC_SS_XTAL); ++} ++ ++/* return the ILP (slowclock) min or max frequency */ ++static uint ++si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc) ++{ ++ uint32 slowclk; ++ uint div; ++ ++ ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); ++ ++ /* shouldn't be here unless we've established the chip has dynamic clk control */ ++ ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL); ++ ++ slowclk = si_slowclk_src(sii); ++ if (sii->pub.ccrev < 6) { ++ if (slowclk == SCC_SS_PCI) ++ return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64)); ++ else ++ return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32)); ++ } else if (sii->pub.ccrev < 10) { ++ div = 4 * ++ (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); ++ if (slowclk == SCC_SS_LPO) ++ return (max_freq ? LPOMAXFREQ : LPOMINFREQ); ++ else if (slowclk == SCC_SS_XTAL) ++ return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div)); ++ else if (slowclk == SCC_SS_PCI) ++ return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div)); ++ else ++ ASSERT(0); ++ } else { ++ /* Chipc rev 10 is InstaClock */ ++ div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT; ++ div = 4 * (div + 1); ++ return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div)); ++ } ++ return (0); ++} ++ ++static void ++si_clkctl_setdelay(si_info_t *sii, void *chipcregs) ++{ ++ chipcregs_t *cc = (chipcregs_t *)chipcregs; ++ uint slowmaxfreq, pll_delay, slowclk; ++ uint pll_on_delay, fref_sel_delay; ++ ++ pll_delay = PLL_DELAY; ++ ++ /* If the slow clock is not sourced by the xtal then add the xtal_on_delay ++ * since the xtal will also be powered down by dynamic clk control logic. ++ */ ++ ++ slowclk = si_slowclk_src(sii); ++ if (slowclk != SCC_SS_XTAL) ++ pll_delay += XTAL_ON_DELAY; ++ ++ /* Starting with 4318 it is ILP that is used for the delays */ ++ slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc); ++ ++ pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; ++ fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; ++ ++ W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay); ++ W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay); ++} ++ ++/* initialize power control delay registers */ ++void ++si_clkctl_init(si_t *sih) ++{ ++ si_info_t *sii; ++ uint origidx = 0; ++ chipcregs_t *cc; ++ bool fast; ++ ++ if (!CCCTL_ENAB(sih)) ++ return; ++ ++ sii = SI_INFO(sih); ++ fast = SI_FAST(sii); ++ if (!fast) { ++ origidx = sii->curidx; ++ if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) ++ return; ++ } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL) ++ return; ++ ASSERT(cc != NULL); ++ ++ /* set all Instaclk chip ILP to 1 MHz */ ++ if (sih->ccrev >= 10) ++ SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK, ++ (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); ++ ++ si_clkctl_setdelay(sii, (void *)(uintptr)cc); ++ ++ if (!fast) ++ si_setcoreidx(sih, origidx); ++} ++ ++ ++/* change logical "focus" to the gpio core for optimized access */ ++void * ++si_gpiosetcore(si_t *sih) ++{ ++ return (si_setcoreidx(sih, SI_CC_IDX)); ++} ++ ++/* ++ * mask & set gpiocontrol bits. ++ * If a gpiocontrol bit is set to 0, chipcommon controls the corresponding GPIO pin. ++ * If a gpiocontrol bit is set to 1, the GPIO pin is no longer a GPIO and becomes dedicated ++ * to some chip-specific purpose. ++ */ ++uint32 ++si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority) ++{ ++ uint regoff; ++ ++ regoff = 0; ++ ++ /* gpios could be shared on router platforms ++ * ignore reservation if it's high priority (e.g., test apps) ++ */ ++ if ((priority != GPIO_HI_PRIORITY) && ++ (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { ++ mask = priority ? (si_gpioreservation & mask) : ++ ((si_gpioreservation | mask) & ~(si_gpioreservation)); ++ val &= mask; ++ } ++ ++ regoff = OFFSETOF(chipcregs_t, gpiocontrol); ++ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); ++} ++ ++/* mask&set gpio output enable bits */ ++uint32 ++si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority) ++{ ++ uint regoff; ++ ++ regoff = 0; ++ ++ /* gpios could be shared on router platforms ++ * ignore reservation if it's high priority (e.g., test apps) ++ */ ++ if ((priority != GPIO_HI_PRIORITY) && ++ (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { ++ mask = priority ? (si_gpioreservation & mask) : ++ ((si_gpioreservation | mask) & ~(si_gpioreservation)); ++ val &= mask; ++ } ++ ++ regoff = OFFSETOF(chipcregs_t, gpioouten); ++ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); ++} ++ ++/* mask&set gpio output bits */ ++uint32 ++si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority) ++{ ++ uint regoff; ++ ++ regoff = 0; ++ ++ /* gpios could be shared on router platforms ++ * ignore reservation if it's high priority (e.g., test apps) ++ */ ++ if ((priority != GPIO_HI_PRIORITY) && ++ (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { ++ mask = priority ? (si_gpioreservation & mask) : ++ ((si_gpioreservation | mask) & ~(si_gpioreservation)); ++ val &= mask; ++ } ++ ++ regoff = OFFSETOF(chipcregs_t, gpioout); ++ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); ++} ++ ++/* reserve one gpio */ ++uint32 ++si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority) ++{ ++ /* only cores on SI_BUS share GPIO's and only applcation users need to ++ * reserve/release GPIO ++ */ ++ if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) { ++ ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority)); ++ return 0xffffffff; ++ } ++ /* make sure only one bit is set */ ++ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { ++ ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); ++ return 0xffffffff; ++ } ++ ++ /* already reserved */ ++ if (si_gpioreservation & gpio_bitmask) ++ return 0xffffffff; ++ /* set reservation */ ++ si_gpioreservation |= gpio_bitmask; ++ ++ return si_gpioreservation; ++} ++ ++/* release one gpio */ ++/* ++ * releasing the gpio doesn't change the current value on the GPIO last write value ++ * persists till some one overwrites it ++ */ ++ ++uint32 ++si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority) ++{ ++ /* only cores on SI_BUS share GPIO's and only applcation users need to ++ * reserve/release GPIO ++ */ ++ if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) { ++ ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority)); ++ return 0xffffffff; ++ } ++ /* make sure only one bit is set */ ++ if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { ++ ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); ++ return 0xffffffff; ++ } ++ ++ /* already released */ ++ if (!(si_gpioreservation & gpio_bitmask)) ++ return 0xffffffff; ++ ++ /* clear reservation */ ++ si_gpioreservation &= ~gpio_bitmask; ++ ++ return si_gpioreservation; ++} ++ ++/* return the current gpioin register value */ ++uint32 ++si_gpioin(si_t *sih) ++{ ++ uint regoff; ++ ++ regoff = OFFSETOF(chipcregs_t, gpioin); ++ return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0)); ++} ++ ++/* mask&set gpio interrupt polarity bits */ ++uint32 ++si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority) ++{ ++ uint regoff; ++ ++ /* gpios could be shared on router platforms */ ++ if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { ++ mask = priority ? (si_gpioreservation & mask) : ++ ((si_gpioreservation | mask) & ~(si_gpioreservation)); ++ val &= mask; ++ } ++ ++ regoff = OFFSETOF(chipcregs_t, gpiointpolarity); ++ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); ++} ++ ++/* mask&set gpio interrupt mask bits */ ++uint32 ++si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority) ++{ ++ uint regoff; ++ ++ /* gpios could be shared on router platforms */ ++ if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { ++ mask = priority ? (si_gpioreservation & mask) : ++ ((si_gpioreservation | mask) & ~(si_gpioreservation)); ++ val &= mask; ++ } ++ ++ regoff = OFFSETOF(chipcregs_t, gpiointmask); ++ return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); ++} ++ ++/* assign the gpio to an led */ ++uint32 ++si_gpioled(si_t *sih, uint32 mask, uint32 val) ++{ ++ if (sih->ccrev < 16) ++ return 0xffffffff; ++ ++ /* gpio led powersave reg */ ++ return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val)); ++} ++ ++/* mask&set gpio timer val */ ++uint32 ++si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval) ++{ ++ if (sih->ccrev < 16) ++ return 0xffffffff; ++ ++ return (si_corereg(sih, SI_CC_IDX, ++ OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval)); ++} ++ ++uint32 ++si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val) ++{ ++ uint offs; ++ ++ if (sih->ccrev < 20) ++ return 0xffffffff; ++ ++ offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup)); ++ return (si_corereg(sih, SI_CC_IDX, offs, mask, val)); ++} ++ ++uint32 ++si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val) ++{ ++ uint offs; ++ ++ if (sih->ccrev < 11) ++ return 0xffffffff; ++ ++ if (regtype == GPIO_REGEVT) ++ offs = OFFSETOF(chipcregs_t, gpioevent); ++ else if (regtype == GPIO_REGEVT_INTMSK) ++ offs = OFFSETOF(chipcregs_t, gpioeventintmask); ++ else if (regtype == GPIO_REGEVT_INTPOL) ++ offs = OFFSETOF(chipcregs_t, gpioeventintpolarity); ++ else ++ return 0xffffffff; ++ ++ return (si_corereg(sih, SI_CC_IDX, offs, mask, val)); ++} ++ ++void * ++si_gpio_handler_register(si_t *sih, uint32 event, ++ bool level, gpio_handler_t cb, void *arg) ++{ ++ si_info_t *sii; ++ gpioh_item_t *gi; ++ ++ ASSERT(event); ++ ASSERT(cb != NULL); ++ ++ sii = SI_INFO(sih); ++ if (sih->ccrev < 11) ++ return NULL; ++ ++ if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL) ++ return NULL; ++ ++ bzero(gi, sizeof(gpioh_item_t)); ++ gi->event = event; ++ gi->handler = cb; ++ gi->arg = arg; ++ gi->level = level; ++ ++ gi->next = sii->gpioh_head; ++ sii->gpioh_head = gi; ++ ++ return (void *)(gi); ++} ++ ++void ++si_gpio_handler_unregister(si_t *sih, void *gpioh) ++{ ++ si_info_t *sii; ++ gpioh_item_t *p, *n; ++ ++ sii = SI_INFO(sih); ++ if (sih->ccrev < 11) ++ return; ++ ++ ASSERT(sii->gpioh_head != NULL); ++ if ((void*)sii->gpioh_head == gpioh) { ++ sii->gpioh_head = sii->gpioh_head->next; ++ MFREE(sii->osh, gpioh, sizeof(gpioh_item_t)); ++ return; ++ } else { ++ p = sii->gpioh_head; ++ n = p->next; ++ while (n) { ++ if ((void*)n == gpioh) { ++ p->next = n->next; ++ MFREE(sii->osh, gpioh, sizeof(gpioh_item_t)); ++ return; ++ } ++ p = n; ++ n = n->next; ++ } ++ } ++ ++ ASSERT(0); /* Not found in list */ ++} ++ ++void ++si_gpio_handler_process(si_t *sih) ++{ ++ si_info_t *sii; ++ gpioh_item_t *h; ++ uint32 level = si_gpioin(sih); ++ uint32 levelp = si_gpiointpolarity(sih, 0, 0, 0); ++ uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0); ++ uint32 edgep = si_gpioevent(sih, GPIO_REGEVT_INTPOL, 0, 0); ++ ++ sii = SI_INFO(sih); ++ for (h = sii->gpioh_head; h != NULL; h = h->next) { ++ if (h->handler) { ++ uint32 status = (h->level ? level : edge) & h->event; ++ uint32 polarity = (h->level ? levelp : edgep) & h->event; ++ ++ /* polarity bitval is opposite of status bitval */ ++ if (status ^ polarity) ++ h->handler(status, h->arg); ++ } ++ } ++ ++ si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */ ++} ++ ++uint32 ++si_gpio_int_enable(si_t *sih, bool enable) ++{ ++ uint offs; ++ ++ if (sih->ccrev < 11) ++ return 0xffffffff; ++ ++ offs = OFFSETOF(chipcregs_t, intmask); ++ return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0))); ++} ++ ++ ++/* Return the size of the specified SOCRAM bank */ ++static uint ++socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 idx, uint8 mem_type) ++{ ++ uint banksize, bankinfo; ++ uint bankidx = idx | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT); ++ ++ ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM); ++ ++ W_REG(sii->osh, ®s->bankidx, bankidx); ++ bankinfo = R_REG(sii->osh, ®s->bankinfo); ++ banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1); ++ return banksize; ++} ++ ++void ++si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect, uint8 *remap) ++{ ++ si_info_t *sii; ++ uint origidx; ++ uint intr_val = 0; ++ sbsocramregs_t *regs; ++ bool wasup; ++ uint corerev; ++ ++ sii = SI_INFO(sih); ++ ++ /* Block ints and save current core */ ++ INTR_OFF(sii, intr_val); ++ origidx = si_coreidx(sih); ++ ++ if (!set) ++ *enable = *protect = *remap = 0; ++ ++ /* Switch to SOCRAM core */ ++ if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) ++ goto done; ++ ++ /* Get info for determining size */ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, 0, 0); ++ ++ corerev = si_corerev(sih); ++ if (corerev >= 10) { ++ uint32 extcinfo; ++ uint8 nb; ++ uint8 i; ++ uint32 bankidx, bankinfo; ++ ++ extcinfo = R_REG(sii->osh, ®s->extracoreinfo); ++ nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT); ++ for (i = 0; i < nb; i++) { ++ bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT); ++ W_REG(sii->osh, ®s->bankidx, bankidx); ++ bankinfo = R_REG(sii->osh, ®s->bankinfo); ++ if (set) { ++ bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK; ++ bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK; ++ bankinfo &= ~SOCRAM_BANKINFO_DEVRAMREMAP_MASK; ++ if (*enable) { ++ bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT); ++ if (*protect) ++ bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT); ++ if ((corerev >= 16) && *remap) ++ bankinfo |= ++ (1 << SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT); ++ } ++ W_REG(sii->osh, ®s->bankinfo, bankinfo); ++ } ++ else if (i == 0) { ++ if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) { ++ *enable = 1; ++ if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK) ++ *protect = 1; ++ if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) ++ *remap = 1; ++ } ++ } ++ } ++ } ++ ++ /* Return to previous state and core */ ++ if (!wasup) ++ si_core_disable(sih, 0); ++ si_setcoreidx(sih, origidx); ++ ++done: ++ INTR_RESTORE(sii, intr_val); ++} ++ ++bool ++si_socdevram_remap_isenb(si_t *sih) ++{ ++ si_info_t *sii; ++ uint origidx; ++ uint intr_val = 0; ++ sbsocramregs_t *regs; ++ bool wasup, remap = FALSE; ++ uint corerev; ++ uint32 extcinfo; ++ uint8 nb; ++ uint8 i; ++ uint32 bankidx, bankinfo; ++ ++ sii = SI_INFO(sih); ++ ++ /* Block ints and save current core */ ++ INTR_OFF(sii, intr_val); ++ origidx = si_coreidx(sih); ++ ++ /* Switch to SOCRAM core */ ++ if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) ++ goto done; ++ ++ /* Get info for determining size */ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, 0, 0); ++ ++ corerev = si_corerev(sih); ++ if (corerev >= 16) { ++ extcinfo = R_REG(sii->osh, ®s->extracoreinfo); ++ nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT); ++ for (i = 0; i < nb; i++) { ++ bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT); ++ W_REG(sii->osh, ®s->bankidx, bankidx); ++ bankinfo = R_REG(sii->osh, ®s->bankinfo); ++ if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) { ++ remap = TRUE; ++ break; ++ } ++ } ++ } ++ ++ /* Return to previous state and core */ ++ if (!wasup) ++ si_core_disable(sih, 0); ++ si_setcoreidx(sih, origidx); ++ ++done: ++ INTR_RESTORE(sii, intr_val); ++ return remap; ++} ++ ++bool ++si_socdevram_pkg(si_t *sih) ++{ ++ if (si_socdevram_size(sih) > 0) ++ return TRUE; ++ else ++ return FALSE; ++} ++ ++uint32 ++si_socdevram_size(si_t *sih) ++{ ++ si_info_t *sii; ++ uint origidx; ++ uint intr_val = 0; ++ uint32 memsize = 0; ++ sbsocramregs_t *regs; ++ bool wasup; ++ uint corerev; ++ ++ sii = SI_INFO(sih); ++ ++ /* Block ints and save current core */ ++ INTR_OFF(sii, intr_val); ++ origidx = si_coreidx(sih); ++ ++ /* Switch to SOCRAM core */ ++ if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) ++ goto done; ++ ++ /* Get info for determining size */ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, 0, 0); ++ ++ corerev = si_corerev(sih); ++ if (corerev >= 10) { ++ uint32 extcinfo; ++ uint8 nb; ++ uint8 i; ++ ++ extcinfo = R_REG(sii->osh, ®s->extracoreinfo); ++ nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT)); ++ for (i = 0; i < nb; i++) ++ memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM); ++ } ++ ++ /* Return to previous state and core */ ++ if (!wasup) ++ si_core_disable(sih, 0); ++ si_setcoreidx(sih, origidx); ++ ++done: ++ INTR_RESTORE(sii, intr_val); ++ ++ return memsize; ++} ++ ++uint32 ++si_socdevram_remap_size(si_t *sih) ++{ ++ si_info_t *sii; ++ uint origidx; ++ uint intr_val = 0; ++ uint32 memsize = 0, banksz; ++ sbsocramregs_t *regs; ++ bool wasup; ++ uint corerev; ++ uint32 extcinfo; ++ uint8 nb; ++ uint8 i; ++ uint32 bankidx, bankinfo; ++ ++ sii = SI_INFO(sih); ++ ++ /* Block ints and save current core */ ++ INTR_OFF(sii, intr_val); ++ origidx = si_coreidx(sih); ++ ++ /* Switch to SOCRAM core */ ++ if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) ++ goto done; ++ ++ /* Get info for determining size */ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, 0, 0); ++ ++ corerev = si_corerev(sih); ++ if (corerev >= 16) { ++ extcinfo = R_REG(sii->osh, ®s->extracoreinfo); ++ nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT)); ++ ++ /* ++ * FIX: A0 Issue: Max addressable is 512KB, instead 640KB ++ * Only four banks are accessible to ARM ++ */ ++ if ((corerev == 16) && (nb == 5)) ++ nb = 4; ++ ++ for (i = 0; i < nb; i++) { ++ bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT); ++ W_REG(sii->osh, ®s->bankidx, bankidx); ++ bankinfo = R_REG(sii->osh, ®s->bankinfo); ++ if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) { ++ banksz = socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM); ++ memsize += banksz; ++ } else { ++ /* Account only consecutive banks for now */ ++ break; ++ } ++ } ++ } ++ ++ /* Return to previous state and core */ ++ if (!wasup) ++ si_core_disable(sih, 0); ++ si_setcoreidx(sih, origidx); ++ ++done: ++ INTR_RESTORE(sii, intr_val); ++ ++ return memsize; ++} ++ ++/* Return the RAM size of the SOCRAM core */ ++uint32 ++si_socram_size(si_t *sih) ++{ ++ si_info_t *sii; ++ uint origidx; ++ uint intr_val = 0; ++ ++ sbsocramregs_t *regs; ++ bool wasup; ++ uint corerev; ++ uint32 coreinfo; ++ uint memsize = 0; ++ ++ sii = SI_INFO(sih); ++ ++ /* Block ints and save current core */ ++ INTR_OFF(sii, intr_val); ++ origidx = si_coreidx(sih); ++ ++ /* Switch to SOCRAM core */ ++ if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) ++ goto done; ++ ++ /* Get info for determining size */ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, 0, 0); ++ corerev = si_corerev(sih); ++ coreinfo = R_REG(sii->osh, ®s->coreinfo); ++ ++ /* Calculate size from coreinfo based on rev */ ++ if (corerev == 0) ++ memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK)); ++ else if (corerev < 3) { ++ memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK)); ++ memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; ++ } else if ((corerev <= 7) || (corerev == 12)) { ++ uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; ++ uint bsz = (coreinfo & SRCI_SRBSZ_MASK); ++ uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT; ++ if (lss != 0) ++ nb --; ++ memsize = nb * (1 << (bsz + SR_BSZ_BASE)); ++ if (lss != 0) ++ memsize += (1 << ((lss - 1) + SR_BSZ_BASE)); ++ } else { ++ uint8 i; ++ uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; ++ for (i = 0; i < nb; i++) ++ memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM); ++ } ++ ++ /* Return to previous state and core */ ++ if (!wasup) ++ si_core_disable(sih, 0); ++ si_setcoreidx(sih, origidx); ++ ++done: ++ INTR_RESTORE(sii, intr_val); ++ ++ return memsize; ++} ++ ++ ++/* Return the TCM-RAM size of the ARMCR4 core. */ ++uint32 ++si_tcm_size(si_t *sih) ++{ ++ si_info_t *sii; ++ uint origidx; ++ uint intr_val = 0; ++ uint8 *regs; ++ bool wasup; ++ uint32 corecap; ++ uint memsize = 0; ++ uint32 nab = 0; ++ uint32 nbb = 0; ++ uint32 totb = 0; ++ uint32 bxinfo = 0; ++ uint32 idx = 0; ++ uint32 *arm_cap_reg; ++ uint32 *arm_bidx; ++ uint32 *arm_binfo; ++ ++ sii = SI_INFO(sih); ++ ++ /* Block ints and save current core */ ++ INTR_OFF(sii, intr_val); ++ origidx = si_coreidx(sih); ++ ++ /* Switch to CR4 core */ ++ if (!(regs = si_setcore(sih, ARMCR4_CORE_ID, 0))) ++ goto done; ++ ++ /* Get info for determining size. If in reset, come out of reset, ++ * but remain in halt ++ */ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, SICF_CPUHALT, SICF_CPUHALT); ++ ++ arm_cap_reg = (uint32 *)(regs + SI_CR4_CAP); ++ corecap = R_REG(sii->osh, arm_cap_reg); ++ ++ nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT; ++ nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT; ++ totb = nab + nbb; ++ ++ arm_bidx = (uint32 *)(regs + SI_CR4_BANKIDX); ++ arm_binfo = (uint32 *)(regs + SI_CR4_BANKINFO); ++ for (idx = 0; idx < totb; idx++) { ++ W_REG(sii->osh, arm_bidx, idx); ++ ++ bxinfo = R_REG(sii->osh, arm_binfo); ++ memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT; ++ } ++ ++ /* Return to previous state and core */ ++ if (!wasup) ++ si_core_disable(sih, 0); ++ si_setcoreidx(sih, origidx); ++ ++done: ++ INTR_RESTORE(sii, intr_val); ++ ++ return memsize; ++} ++ ++uint32 ++si_socram_srmem_size(si_t *sih) ++{ ++ si_info_t *sii; ++ uint origidx; ++ uint intr_val = 0; ++ ++ sbsocramregs_t *regs; ++ bool wasup; ++ uint corerev; ++ uint32 coreinfo; ++ uint memsize = 0; ++ ++ if ((CHIPID(sih->chip) == BCM4334_CHIP_ID) && (CHIPREV(sih->chiprev) < 2)) { ++ return (32 * 1024); ++ } ++ ++ sii = SI_INFO(sih); ++ ++ /* Block ints and save current core */ ++ INTR_OFF(sii, intr_val); ++ origidx = si_coreidx(sih); ++ ++ /* Switch to SOCRAM core */ ++ if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) ++ goto done; ++ ++ /* Get info for determining size */ ++ if (!(wasup = si_iscoreup(sih))) ++ si_core_reset(sih, 0, 0); ++ corerev = si_corerev(sih); ++ coreinfo = R_REG(sii->osh, ®s->coreinfo); ++ ++ /* Calculate size from coreinfo based on rev */ ++ if (corerev >= 16) { ++ uint8 i; ++ uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; ++ for (i = 0; i < nb; i++) { ++ W_REG(sii->osh, ®s->bankidx, i); ++ if (R_REG(sii->osh, ®s->bankinfo) & SOCRAM_BANKINFO_RETNTRAM_MASK) ++ memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM); ++ } ++ } ++ ++ /* Return to previous state and core */ ++ if (!wasup) ++ si_core_disable(sih, 0); ++ si_setcoreidx(sih, origidx); ++ ++done: ++ INTR_RESTORE(sii, intr_val); ++ ++ return memsize; ++} ++ ++ ++void ++si_btcgpiowar(si_t *sih) ++{ ++ si_info_t *sii; ++ uint origidx; ++ uint intr_val = 0; ++ chipcregs_t *cc; ++ ++ sii = SI_INFO(sih); ++ ++ /* Make sure that there is ChipCommon core present && ++ * UART_TX is strapped to 1 ++ */ ++ if (!(sih->cccaps & CC_CAP_UARTGPIO)) ++ return; ++ ++ /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */ ++ INTR_OFF(sii, intr_val); ++ ++ origidx = si_coreidx(sih); ++ ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ASSERT(cc != NULL); ++ ++ W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04); ++ ++ /* restore the original index */ ++ si_setcoreidx(sih, origidx); ++ ++ INTR_RESTORE(sii, intr_val); ++} ++ ++void ++si_chipcontrl_btshd0_4331(si_t *sih, bool on) ++{ ++ si_info_t *sii; ++ chipcregs_t *cc; ++ uint origidx; ++ uint32 val; ++ uint intr_val = 0; ++ ++ sii = SI_INFO(sih); ++ ++ INTR_OFF(sii, intr_val); ++ ++ origidx = si_coreidx(sih); ++ ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ++ val = R_REG(sii->osh, &cc->chipcontrol); ++ ++ /* bt_shd0 controls are same for 4331 chiprevs 0 and 1, packages 12x9 and 12x12 */ ++ if (on) { ++ /* Enable bt_shd0 on gpio4: */ ++ val |= (CCTRL4331_BT_SHD0_ON_GPIO4); ++ W_REG(sii->osh, &cc->chipcontrol, val); ++ } else { ++ val &= ~(CCTRL4331_BT_SHD0_ON_GPIO4); ++ W_REG(sii->osh, &cc->chipcontrol, val); ++ } ++ ++ /* restore the original index */ ++ si_setcoreidx(sih, origidx); ++ ++ INTR_RESTORE(sii, intr_val); ++} ++ ++void ++si_chipcontrl_restore(si_t *sih, uint32 val) ++{ ++ si_info_t *sii; ++ chipcregs_t *cc; ++ uint origidx; ++ ++ sii = SI_INFO(sih); ++ origidx = si_coreidx(sih); ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ W_REG(sii->osh, &cc->chipcontrol, val); ++ si_setcoreidx(sih, origidx); ++} ++ ++uint32 ++si_chipcontrl_read(si_t *sih) ++{ ++ si_info_t *sii; ++ chipcregs_t *cc; ++ uint origidx; ++ uint32 val; ++ ++ sii = SI_INFO(sih); ++ origidx = si_coreidx(sih); ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ val = R_REG(sii->osh, &cc->chipcontrol); ++ si_setcoreidx(sih, origidx); ++ return val; ++} ++ ++void ++si_chipcontrl_epa4331(si_t *sih, bool on) ++{ ++ si_info_t *sii; ++ chipcregs_t *cc; ++ uint origidx; ++ uint32 val; ++ ++ sii = SI_INFO(sih); ++ origidx = si_coreidx(sih); ++ ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ++ val = R_REG(sii->osh, &cc->chipcontrol); ++ ++ if (on) { ++ if (sih->chippkg == 9 || sih->chippkg == 0xb) { ++ val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); ++ /* Ext PA Controls for 4331 12x9 Package */ ++ W_REG(sii->osh, &cc->chipcontrol, val); ++ } else { ++ /* Ext PA Controls for 4331 12x12 Package */ ++ if (sih->chiprev > 0) { ++ W_REG(sii->osh, &cc->chipcontrol, val | ++ (CCTRL4331_EXTPA_EN) | (CCTRL4331_EXTPA_EN2)); ++ } else { ++ W_REG(sii->osh, &cc->chipcontrol, val | (CCTRL4331_EXTPA_EN)); ++ } ++ } ++ } else { ++ val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_EN2 | CCTRL4331_EXTPA_ON_GPIO2_5); ++ W_REG(sii->osh, &cc->chipcontrol, val); ++ } ++ ++ si_setcoreidx(sih, origidx); ++} ++ ++/* switch muxed pins, on: SROM, off: FEMCTRL */ ++void ++si_chipcontrl_srom4360(si_t *sih, bool on) ++{ ++ si_info_t *sii; ++ chipcregs_t *cc; ++ uint origidx; ++ uint32 val; ++ ++ sii = SI_INFO(sih); ++ origidx = si_coreidx(sih); ++ ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ++ val = R_REG(sii->osh, &cc->chipcontrol); ++ ++ if (on) { ++ val &= ~(CCTRL4360_SECI_MODE | ++ CCTRL4360_BTSWCTRL_MODE | ++ CCTRL4360_EXTRA_FEMCTRL_MODE | ++ CCTRL4360_BT_LGCY_MODE | ++ CCTRL4360_CORE2FEMCTRL4_ON); ++ ++ W_REG(sii->osh, &cc->chipcontrol, val); ++ } else { ++ } ++ ++ si_setcoreidx(sih, origidx); ++} ++ ++void ++si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl) ++{ ++ si_info_t *sii; ++ chipcregs_t *cc; ++ uint origidx; ++ uint32 val; ++ bool sel_chip; ++ ++ sel_chip = (CHIPID(sih->chip) == BCM4331_CHIP_ID) || ++ (CHIPID(sih->chip) == BCM43431_CHIP_ID); ++ sel_chip &= ((sih->chippkg == 9 || sih->chippkg == 0xb)); ++ ++ if (!sel_chip) ++ return; ++ ++ sii = SI_INFO(sih); ++ origidx = si_coreidx(sih); ++ ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ++ val = R_REG(sii->osh, &cc->chipcontrol); ++ ++ if (enter_wowl) { ++ val |= CCTRL4331_EXTPA_EN; ++ W_REG(sii->osh, &cc->chipcontrol, val); ++ } else { ++ val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); ++ W_REG(sii->osh, &cc->chipcontrol, val); ++ } ++ si_setcoreidx(sih, origidx); ++} ++ ++uint ++si_pll_reset(si_t *sih) ++{ ++ uint err = 0; ++ ++ return (err); ++} ++ ++/* Enable BT-COEX & Ex-PA for 4313 */ ++void ++si_epa_4313war(si_t *sih) ++{ ++ si_info_t *sii; ++ chipcregs_t *cc; ++ uint origidx; ++ ++ sii = SI_INFO(sih); ++ origidx = si_coreidx(sih); ++ ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ++ /* EPA Fix */ ++ W_REG(sii->osh, &cc->gpiocontrol, ++ R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK); ++ ++ si_setcoreidx(sih, origidx); ++} ++ ++void ++si_clk_pmu_htavail_set(si_t *sih, bool set_clear) ++{ ++} ++ ++/* WL/BT control for 4313 btcombo boards >= P250 */ ++void ++si_btcombo_p250_4313_war(si_t *sih) ++{ ++ si_info_t *sii; ++ chipcregs_t *cc; ++ uint origidx; ++ ++ sii = SI_INFO(sih); ++ origidx = si_coreidx(sih); ++ ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ W_REG(sii->osh, &cc->gpiocontrol, ++ R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_5_6_EN_MASK); ++ ++ W_REG(sii->osh, &cc->gpioouten, ++ R_REG(sii->osh, &cc->gpioouten) | GPIO_CTRL_5_6_EN_MASK); ++ ++ si_setcoreidx(sih, origidx); ++} ++void ++si_btc_enable_chipcontrol(si_t *sih) ++{ ++ si_info_t *sii; ++ chipcregs_t *cc; ++ uint origidx; ++ ++ sii = SI_INFO(sih); ++ origidx = si_coreidx(sih); ++ ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ++ /* BT fix */ ++ W_REG(sii->osh, &cc->chipcontrol, ++ R_REG(sii->osh, &cc->chipcontrol) | CC_BTCOEX_EN_MASK); ++ ++ si_setcoreidx(sih, origidx); ++} ++void ++si_btcombo_43228_war(si_t *sih) ++{ ++ si_info_t *sii; ++ chipcregs_t *cc; ++ uint origidx; ++ ++ sii = SI_INFO(sih); ++ origidx = si_coreidx(sih); ++ ++ cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ++ ++ W_REG(sii->osh, &cc->gpioouten, GPIO_CTRL_7_6_EN_MASK); ++ W_REG(sii->osh, &cc->gpioout, GPIO_OUT_7_EN_MASK); ++ ++ si_setcoreidx(sih, origidx); ++} ++ ++/* check if the device is removed */ ++bool ++si_deviceremoved(si_t *sih) ++{ ++ uint32 w; ++ si_info_t *sii; ++ ++ sii = SI_INFO(sih); ++ ++ switch (BUSTYPE(sih->bustype)) { ++ case PCI_BUS: ++ ASSERT(sii->osh != NULL); ++ w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32)); ++ if ((w & 0xFFFF) != VENDOR_BROADCOM) ++ return TRUE; ++ break; ++ } ++ return FALSE; ++} ++ ++bool ++si_is_sprom_available(si_t *sih) ++{ ++ if (sih->ccrev >= 31) { ++ si_info_t *sii; ++ uint origidx; ++ chipcregs_t *cc; ++ uint32 sromctrl; ++ ++ if ((sih->cccaps & CC_CAP_SROM) == 0) ++ return FALSE; ++ ++ sii = SI_INFO(sih); ++ origidx = sii->curidx; ++ cc = si_setcoreidx(sih, SI_CC_IDX); ++ sromctrl = R_REG(sii->osh, &cc->sromcontrol); ++ si_setcoreidx(sih, origidx); ++ return (sromctrl & SRC_PRESENT); ++ } ++ ++ switch (CHIPID(sih->chip)) { ++ case BCM4312_CHIP_ID: ++ return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL); ++ case BCM4325_CHIP_ID: ++ return (sih->chipst & CST4325_SPROM_SEL) != 0; ++ case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID: ++ case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID: ++ case BCM4342_CHIP_ID: { ++ uint32 spromotp; ++ spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >> ++ CST4322_SPROM_OTP_SEL_SHIFT; ++ return (spromotp & CST4322_SPROM_PRESENT) != 0; ++ } ++ case BCM4329_CHIP_ID: ++ return (sih->chipst & CST4329_SPROM_SEL) != 0; ++ case BCM4315_CHIP_ID: ++ return (sih->chipst & CST4315_SPROM_SEL) != 0; ++ case BCM4319_CHIP_ID: ++ return (sih->chipst & CST4319_SPROM_SEL) != 0; ++ case BCM4336_CHIP_ID: ++ case BCM43362_CHIP_ID: ++ return (sih->chipst & CST4336_SPROM_PRESENT) != 0; ++ case BCM4330_CHIP_ID: ++ return (sih->chipst & CST4330_SPROM_PRESENT) != 0; ++ case BCM4313_CHIP_ID: ++ return (sih->chipst & CST4313_SPROM_PRESENT) != 0; ++ case BCM4331_CHIP_ID: ++ case BCM43431_CHIP_ID: ++ return (sih->chipst & CST4331_SPROM_PRESENT) != 0; ++ case BCM43239_CHIP_ID: ++ return ((sih->chipst & CST43239_SPROM_MASK) && ++ !(sih->chipst & CST43239_SFLASH_MASK)); ++ case BCM4324_CHIP_ID: ++ return ((sih->chipst & CST4324_SPROM_MASK) && ++ !(sih->chipst & CST4324_SFLASH_MASK)); ++ case BCM4335_CHIP_ID: ++ return ((sih->chipst & CST4335_SPROM_MASK) && ++ !(sih->chipst & CST4335_SFLASH_MASK)); ++ case BCM43131_CHIP_ID: ++ case BCM43217_CHIP_ID: ++ case BCM43227_CHIP_ID: ++ case BCM43228_CHIP_ID: ++ case BCM43428_CHIP_ID: ++ return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT; ++ default: ++ return TRUE; ++ } ++} ++ ++ ++uint32 si_get_sromctl(si_t *sih) ++{ ++ chipcregs_t *cc; ++ uint origidx; ++ uint32 sromctl; ++ osl_t *osh; ++ ++ osh = si_osh(sih); ++ origidx = si_coreidx(sih); ++ cc = si_setcoreidx(sih, SI_CC_IDX); ++ ASSERT((uintptr)cc); ++ ++ sromctl = R_REG(osh, &cc->sromcontrol); ++ ++ /* return to the original core */ ++ si_setcoreidx(sih, origidx); ++ return sromctl; ++} ++ ++int si_set_sromctl(si_t *sih, uint32 value) ++{ ++ chipcregs_t *cc; ++ uint origidx; ++ osl_t *osh; ++ ++ osh = si_osh(sih); ++ origidx = si_coreidx(sih); ++ cc = si_setcoreidx(sih, SI_CC_IDX); ++ ASSERT((uintptr)cc); ++ ++ /* get chipcommon rev */ ++ if (si_corerev(sih) < 32) ++ return BCME_UNSUPPORTED; ++ ++ W_REG(osh, &cc->sromcontrol, value); ++ ++ /* return to the original core */ ++ si_setcoreidx(sih, origidx); ++ return BCME_OK; ++ ++} +diff --git a/drivers/net/wireless/ap6210/siutils_priv.h b/drivers/net/wireless/ap6210/siutils_priv.h +new file mode 100755 +index 0000000..34fc3fa +--- /dev/null ++++ b/drivers/net/wireless/ap6210/siutils_priv.h +@@ -0,0 +1,236 @@ ++/* ++ * Include file private to the SOC Interconnect support files. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: siutils_priv.h 309193 2012-01-19 00:03:57Z $ ++ */ ++ ++#ifndef _siutils_priv_h_ ++#define _siutils_priv_h_ ++ ++#define IS_SIM(chippkg) ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) ++ ++typedef uint32 (*si_intrsoff_t)(void *intr_arg); ++typedef void (*si_intrsrestore_t)(void *intr_arg, uint32 arg); ++typedef bool (*si_intrsenabled_t)(void *intr_arg); ++ ++typedef struct gpioh_item { ++ void *arg; ++ bool level; ++ gpio_handler_t handler; ++ uint32 event; ++ struct gpioh_item *next; ++} gpioh_item_t; ++ ++/* misc si info needed by some of the routines */ ++typedef struct si_info { ++ struct si_pub pub; /* back plane public state (must be first field) */ ++ ++ void *osh; /* osl os handle */ ++ void *sdh; /* bcmsdh handle */ ++ ++ uint dev_coreid; /* the core provides driver functions */ ++ void *intr_arg; /* interrupt callback function arg */ ++ si_intrsoff_t intrsoff_fn; /* turns chip interrupts off */ ++ si_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */ ++ si_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */ ++ ++ void *pch; /* PCI/E core handle */ ++ ++ gpioh_item_t *gpioh_head; /* GPIO event handlers list */ ++ ++ bool memseg; /* flag to toggle MEM_SEG register */ ++ ++ char *vars; ++ uint varsz; ++ ++ void *curmap; /* current regs va */ ++ void *regs[SI_MAXCORES]; /* other regs va */ ++ ++ uint curidx; /* current core index */ ++ uint numcores; /* # discovered cores */ ++ uint coreid[SI_MAXCORES]; /* id of each core */ ++ uint32 coresba[SI_MAXCORES]; /* backplane address of each core */ ++ void *regs2[SI_MAXCORES]; /* va of each core second register set (usbh20) */ ++ uint32 coresba2[SI_MAXCORES]; /* address of each core second register set (usbh20) */ ++ uint32 coresba_size[SI_MAXCORES]; /* backplane address space size */ ++ uint32 coresba2_size[SI_MAXCORES]; /* second address space size */ ++ ++ void *curwrap; /* current wrapper va */ ++ void *wrappers[SI_MAXCORES]; /* other cores wrapper va */ ++ uint32 wrapba[SI_MAXCORES]; /* address of controlling wrapper */ ++ ++ uint32 cia[SI_MAXCORES]; /* erom cia entry for each core */ ++ uint32 cib[SI_MAXCORES]; /* erom cia entry for each core */ ++ uint32 oob_router; /* oob router registers for axi */ ++} si_info_t; ++ ++#define SI_INFO(sih) (si_info_t *)(uintptr)sih ++ ++#define GOODCOREADDR(x, b) (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ ++ ISALIGNED((x), SI_CORE_SIZE)) ++#define GOODREGS(regs) ((regs) != NULL && ISALIGNED((uintptr)(regs), SI_CORE_SIZE)) ++#define BADCOREADDR 0 ++#define GOODIDX(idx) (((uint)idx) < SI_MAXCORES) ++#define NOREV -1 /* Invalid rev */ ++ ++#define PCI(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ ++ ((si)->pub.buscoretype == PCI_CORE_ID)) ++ ++#define PCIE_GEN1(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ ++ ((si)->pub.buscoretype == PCIE_CORE_ID)) ++ ++#define PCIE_GEN2(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ ++ ((si)->pub.buscoretype == PCIE2_CORE_ID)) ++ ++#define PCIE(si) (PCIE_GEN1(si) || PCIE_GEN2(si)) ++ ++#define PCMCIA(si) ((BUSTYPE((si)->pub.bustype) == PCMCIA_BUS) && ((si)->memseg == TRUE)) ++ ++/* Newer chips can access PCI/PCIE and CC core without requiring to change ++ * PCI BAR0 WIN ++ */ ++#define SI_FAST(si) (PCIE(si) || (PCI(si) && ((si)->pub.buscorerev >= 13))) ++ ++#define PCIEREGS(si) (((char *)((si)->curmap) + PCI_16KB0_PCIREGS_OFFSET)) ++#define CCREGS_FAST(si) (((char *)((si)->curmap) + PCI_16KB0_CCREGS_OFFSET)) ++ ++/* ++ * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/ ++ * after core switching to avoid invalid register accesss inside ISR. ++ */ ++#define INTR_OFF(si, intr_val) \ ++ if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \ ++ intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); } ++#define INTR_RESTORE(si, intr_val) \ ++ if ((si)->intrsrestore_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) { \ ++ (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); } ++ ++/* dynamic clock control defines */ ++#define LPOMINFREQ 25000 /* low power oscillator min */ ++#define LPOMAXFREQ 43000 /* low power oscillator max */ ++#define XTALMINFREQ 19800000 /* 20 MHz - 1% */ ++#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */ ++#define PCIMINFREQ 25000000 /* 25 MHz */ ++#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */ ++ ++#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ ++#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ ++ ++#define PCI_FORCEHT(si) \ ++ (((PCIE_GEN1(si)) && (si->pub.chip == BCM4311_CHIP_ID) && ((si->pub.chiprev <= 1))) || \ ++ ((PCI(si) || PCIE_GEN1(si)) && (si->pub.chip == BCM4321_CHIP_ID)) || \ ++ (PCIE_GEN1(si) && (si->pub.chip == BCM4716_CHIP_ID)) || \ ++ (PCIE_GEN1(si) && (si->pub.chip == BCM4748_CHIP_ID))) ++ ++/* GPIO Based LED powersave defines */ ++#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */ ++#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */ ++ ++#ifndef DEFAULT_GPIOTIMERVAL ++#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) ++#endif ++ ++/* Silicon Backplane externs */ ++extern void sb_scan(si_t *sih, void *regs, uint devid); ++extern uint sb_coreid(si_t *sih); ++extern uint sb_intflag(si_t *sih); ++extern uint sb_flag(si_t *sih); ++extern void sb_setint(si_t *sih, int siflag); ++extern uint sb_corevendor(si_t *sih); ++extern uint sb_corerev(si_t *sih); ++extern uint sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); ++extern bool sb_iscoreup(si_t *sih); ++extern void *sb_setcoreidx(si_t *sih, uint coreidx); ++extern uint32 sb_core_cflags(si_t *sih, uint32 mask, uint32 val); ++extern void sb_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); ++extern uint32 sb_core_sflags(si_t *sih, uint32 mask, uint32 val); ++extern void sb_commit(si_t *sih); ++extern uint32 sb_base(uint32 admatch); ++extern uint32 sb_size(uint32 admatch); ++extern void sb_core_reset(si_t *sih, uint32 bits, uint32 resetbits); ++extern void sb_core_disable(si_t *sih, uint32 bits); ++extern uint32 sb_addrspace(si_t *sih, uint asidx); ++extern uint32 sb_addrspacesize(si_t *sih, uint asidx); ++extern int sb_numaddrspaces(si_t *sih); ++ ++extern uint32 sb_set_initiator_to(si_t *sih, uint32 to, uint idx); ++ ++extern bool sb_taclear(si_t *sih, bool details); ++ ++ ++/* Wake-on-wireless-LAN (WOWL) */ ++extern bool sb_pci_pmecap(si_t *sih); ++struct osl_info; ++extern bool sb_pci_fastpmecap(struct osl_info *osh); ++extern bool sb_pci_pmeclr(si_t *sih); ++extern void sb_pci_pmeen(si_t *sih); ++extern uint sb_pcie_readreg(void *sih, uint addrtype, uint offset); ++ ++/* AMBA Interconnect exported externs */ ++extern si_t *ai_attach(uint pcidev, osl_t *osh, void *regs, uint bustype, ++ void *sdh, char **vars, uint *varsz); ++extern si_t *ai_kattach(osl_t *osh); ++extern void ai_scan(si_t *sih, void *regs, uint devid); ++ ++extern uint ai_flag(si_t *sih); ++extern void ai_setint(si_t *sih, int siflag); ++extern uint ai_coreidx(si_t *sih); ++extern uint ai_corevendor(si_t *sih); ++extern uint ai_corerev(si_t *sih); ++extern bool ai_iscoreup(si_t *sih); ++extern void *ai_setcoreidx(si_t *sih, uint coreidx); ++extern uint32 ai_core_cflags(si_t *sih, uint32 mask, uint32 val); ++extern void ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); ++extern uint32 ai_core_sflags(si_t *sih, uint32 mask, uint32 val); ++extern uint ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); ++extern void ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits); ++extern void ai_core_disable(si_t *sih, uint32 bits); ++extern int ai_numaddrspaces(si_t *sih); ++extern uint32 ai_addrspace(si_t *sih, uint asidx); ++extern uint32 ai_addrspacesize(si_t *sih, uint asidx); ++extern void ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size); ++extern uint ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val); ++ ++ ++ ++#define ub_scan(a, b, c) do {} while (0) ++#define ub_flag(a) (0) ++#define ub_setint(a, b) do {} while (0) ++#define ub_coreidx(a) (0) ++#define ub_corevendor(a) (0) ++#define ub_corerev(a) (0) ++#define ub_iscoreup(a) (0) ++#define ub_setcoreidx(a, b) (0) ++#define ub_core_cflags(a, b, c) (0) ++#define ub_core_cflags_wo(a, b, c) do {} while (0) ++#define ub_core_sflags(a, b, c) (0) ++#define ub_corereg(a, b, c, d, e) (0) ++#define ub_core_reset(a, b, c) do {} while (0) ++#define ub_core_disable(a, b) do {} while (0) ++#define ub_numaddrspaces(a) (0) ++#define ub_addrspace(a, b) (0) ++#define ub_addrspacesize(a, b) (0) ++#define ub_view(a, b) do {} while (0) ++#define ub_dumpregs(a, b) do {} while (0) ++ ++#endif /* _siutils_priv_h_ */ +diff --git a/drivers/net/wireless/ap6210/uamp_api.h b/drivers/net/wireless/ap6210/uamp_api.h +new file mode 100755 +index 0000000..673dce0 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/uamp_api.h +@@ -0,0 +1,176 @@ ++/* ++ * Name: uamp_api.h ++ * ++ * Description: Universal AMP API ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: uamp_api.h 294267 2011-11-04 23:41:52Z $ ++ * ++ */ ++#ifndef UAMP_API_H ++#define UAMP_API_H ++ ++ ++#include "typedefs.h" ++ ++ ++/***************************************************************************** ++** Constant and Type Definitions ++****************************************************************************** ++*/ ++ ++#define BT_API ++ ++/* Types. */ ++typedef bool BOOLEAN; ++typedef uint8 UINT8; ++typedef uint16 UINT16; ++ ++ ++/* UAMP identifiers */ ++#define UAMP_ID_1 1 ++#define UAMP_ID_2 2 ++typedef UINT8 tUAMP_ID; ++ ++/* UAMP event ids (used by UAMP_CBACK) */ ++#define UAMP_EVT_RX_READY 0 /* Data from AMP controller is ready to be read */ ++#define UAMP_EVT_CTLR_REMOVED 1 /* Controller removed */ ++#define UAMP_EVT_CTLR_READY 2 /* Controller added/ready */ ++typedef UINT8 tUAMP_EVT; ++ ++ ++/* UAMP Channels */ ++#define UAMP_CH_HCI_CMD 0 /* HCI Command channel */ ++#define UAMP_CH_HCI_EVT 1 /* HCI Event channel */ ++#define UAMP_CH_HCI_DATA 2 /* HCI ACL Data channel */ ++typedef UINT8 tUAMP_CH; ++ ++/* tUAMP_EVT_DATA: union for event-specific data, used by UAMP_CBACK */ ++typedef union { ++ tUAMP_CH channel; /* UAMP_EVT_RX_READY: channel for which rx occured */ ++} tUAMP_EVT_DATA; ++ ++ ++/***************************************************************************** ++** ++** Function: UAMP_CBACK ++** ++** Description: Callback for events. Register callback using UAMP_Init. ++** ++** Parameters amp_id: AMP device identifier that generated the event ++** amp_evt: event id ++** p_amp_evt_data: pointer to event-specific data ++** ++****************************************************************************** ++*/ ++typedef void (*tUAMP_CBACK)(tUAMP_ID amp_id, tUAMP_EVT amp_evt, tUAMP_EVT_DATA *p_amp_evt_data); ++ ++/***************************************************************************** ++** external function declarations ++****************************************************************************** ++*/ ++#ifdef __cplusplus ++extern "C" ++{ ++#endif ++ ++/***************************************************************************** ++** ++** Function: UAMP_Init ++** ++** Description: Initialize UAMP driver ++** ++** Parameters p_cback: Callback function for UAMP event notification ++** ++****************************************************************************** ++*/ ++BT_API BOOLEAN UAMP_Init(tUAMP_CBACK p_cback); ++ ++ ++/***************************************************************************** ++** ++** Function: UAMP_Open ++** ++** Description: Open connection to local AMP device. ++** ++** Parameters app_id: Application specific AMP identifer. This value ++** will be included in AMP messages sent to the ++** BTU task, to identify source of the message ++** ++****************************************************************************** ++*/ ++BT_API BOOLEAN UAMP_Open(tUAMP_ID amp_id); ++ ++/***************************************************************************** ++** ++** Function: UAMP_Close ++** ++** Description: Close connection to local AMP device. ++** ++** Parameters app_id: Application specific AMP identifer. ++** ++****************************************************************************** ++*/ ++BT_API void UAMP_Close(tUAMP_ID amp_id); ++ ++ ++/***************************************************************************** ++** ++** Function: UAMP_Write ++** ++** Description: Send buffer to AMP device. Frees GKI buffer when done. ++** ++** ++** Parameters: app_id: AMP identifer. ++** p_buf: pointer to buffer to write ++** num_bytes: number of bytes to write ++** channel: UAMP_CH_HCI_ACL, or UAMP_CH_HCI_CMD ++** ++** Returns: number of bytes written ++** ++****************************************************************************** ++*/ ++BT_API UINT16 UAMP_Write(tUAMP_ID amp_id, UINT8 *p_buf, UINT16 num_bytes, tUAMP_CH channel); ++ ++/***************************************************************************** ++** ++** Function: UAMP_Read ++** ++** Description: Read incoming data from AMP. Call after receiving a ++** UAMP_EVT_RX_READY callback event. ++** ++** Parameters: app_id: AMP identifer. ++** p_buf: pointer to buffer for holding incoming AMP data ++** buf_size: size of p_buf ++** channel: UAMP_CH_HCI_ACL, or UAMP_CH_HCI_EVT ++** ++** Returns: number of bytes read ++** ++****************************************************************************** ++*/ ++BT_API UINT16 UAMP_Read(tUAMP_ID amp_id, UINT8 *p_buf, UINT16 buf_size, tUAMP_CH channel); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* UAMP_API_H */ +diff --git a/drivers/net/wireless/ap6210/wl_android.c b/drivers/net/wireless/ap6210/wl_android.c +new file mode 100755 +index 0000000..7e8b724 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/wl_android.c +@@ -0,0 +1,1448 @@ ++/* ++ * Linux cfg80211 driver - Android related functions ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: wl_android.c 372668 2012-12-04 14:07:12Z $ ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef WL_CFG80211 ++#include ++#endif ++#if defined(CONFIG_WIFI_CONTROL_FUNC) ++#include ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) ++#include ++#else ++#include ++#endif ++#endif /* CONFIG_WIFI_CONTROL_FUNC */ ++ ++#include ++ ++#ifndef WL_CFG80211 ++#define htod32(i) i ++#define htod16(i) i ++#define dtoh32(i) i ++#define dtoh16(i) i ++#define htodchanspec(i) i ++#define dtohchanspec(i) i ++#endif ++ ++/* ++ * Android private command strings, PLEASE define new private commands here ++ * so they can be updated easily in the future (if needed) ++ */ ++ ++#define CMD_START "START" ++#define CMD_STOP "STOP" ++#define CMD_SCAN_ACTIVE "SCAN-ACTIVE" ++#define CMD_SCAN_PASSIVE "SCAN-PASSIVE" ++#define CMD_RSSI "RSSI" ++#define CMD_LINKSPEED "LINKSPEED" ++#define CMD_RXFILTER_START "RXFILTER-START" ++#define CMD_RXFILTER_STOP "RXFILTER-STOP" ++#define CMD_RXFILTER_ADD "RXFILTER-ADD" ++#define CMD_RXFILTER_REMOVE "RXFILTER-REMOVE" ++#define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START" ++#define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP" ++#define CMD_BTCOEXMODE "BTCOEXMODE" ++#define CMD_SETSUSPENDOPT "SETSUSPENDOPT" ++#define CMD_SETSUSPENDMODE "SETSUSPENDMODE" ++#define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR" ++#define CMD_SETFWPATH "SETFWPATH" ++#define CMD_SETBAND "SETBAND" ++#define CMD_GETBAND "GETBAND" ++#define CMD_COUNTRY "COUNTRY" ++#define CMD_P2P_SET_NOA "P2P_SET_NOA" ++#if !defined WL_ENABLE_P2P_IF ++#define CMD_P2P_GET_NOA "P2P_GET_NOA" ++#endif ++#define CMD_P2P_SD_OFFLOAD "P2P_SD_" ++#define CMD_P2P_SET_PS "P2P_SET_PS" ++#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" ++#define CMD_SETROAMMODE "SETROAMMODE" ++ ++ ++/* CCX Private Commands */ ++ ++#ifdef PNO_SUPPORT ++#define CMD_PNOSSIDCLR_SET "PNOSSIDCLR" ++#define CMD_PNOSETUP_SET "PNOSETUP " ++#define CMD_PNOENABLE_SET "PNOFORCE" ++#define CMD_PNODEBUG_SET "PNODEBUG" ++ ++#define PNO_TLV_PREFIX 'S' ++#define PNO_TLV_VERSION '1' ++#define PNO_TLV_SUBVERSION '2' ++#define PNO_TLV_RESERVED '0' ++#define PNO_TLV_TYPE_SSID_IE 'S' ++#define PNO_TLV_TYPE_TIME 'T' ++#define PNO_TLV_FREQ_REPEAT 'R' ++#define PNO_TLV_FREQ_EXPO_MAX 'M' ++ ++typedef struct cmd_tlv { ++ char prefix; ++ char version; ++ char subver; ++ char reserved; ++} cmd_tlv_t; ++#endif /* PNO_SUPPORT */ ++ ++#define CMD_OKC_SET_PMK "SET_PMK" ++#define CMD_OKC_ENABLE "OKC_ENABLE" ++ ++ ++typedef struct android_wifi_priv_cmd { ++ char *buf; ++ int used_len; ++ int total_len; ++} android_wifi_priv_cmd; ++ ++/** ++ * Extern function declarations (TODO: move them to dhd_linux.h) ++ */ ++void dhd_customer_gpio_wlan_ctrl(int onoff); ++int dhd_dev_reset(struct net_device *dev, uint8 flag); ++int dhd_dev_init_ioctl(struct net_device *dev); ++#ifdef WL_CFG80211 ++int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr); ++int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command); ++#else ++int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr) ++{ return 0; } ++int wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len) ++{ return 0; } ++int wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len) ++{ return 0; } ++int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len) ++{ return 0; } ++#endif /* WL_CFG80211 */ ++ ++extern int dhd_os_check_wakelock(void *dhdp); ++extern int dhd_os_check_if_up(void *dhdp); ++extern void *bcmsdh_get_drvdata(void); ++#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) ++extern int dhd_wlfc_init(dhd_pub_t *dhd); ++extern void dhd_wlfc_deinit(dhd_pub_t *dhd); ++#endif ++ ++extern bool ap_fw_loaded; ++extern char iface_name[IFNAMSIZ]; ++ ++#define WIFI_TURNOFF_DELAY 0 ++/** ++ * Local (static) functions and variables ++ */ ++ ++/* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first ++ * time (only) in dhd_open, subsequential wifi on will be handled by ++ * wl_android_wifi_on ++ */ ++static int g_wifi_on = TRUE; ++ ++/** ++ * Local (static) function definitions ++ */ ++static int wl_android_get_link_speed(struct net_device *net, char *command, int total_len) ++{ ++ int link_speed; ++ int bytes_written; ++ int error; ++ ++ error = wldev_get_link_speed(net, &link_speed); ++ if (error) ++ return -1; ++ ++ /* Convert Kbps to Android Mbps */ ++ link_speed = link_speed / 1000; ++ bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed); ++ AP6210_DEBUG("%s: command result is %s\n", __FUNCTION__, command); ++ return bytes_written; ++} ++ ++static int wl_android_get_rssi(struct net_device *net, char *command, int total_len) ++{ ++ wlc_ssid_t ssid = {0}; ++ int rssi; ++ int bytes_written = 0; ++ int error; ++ ++ error = wldev_get_rssi(net, &rssi); ++ if (error) ++ return -1; ++#if defined(RSSIOFFSET) ++ rssi = wl_update_rssi_offset(rssi); ++#endif ++ ++ error = wldev_get_ssid(net, &ssid); ++ if (error) ++ return -1; ++ if ((ssid.SSID_len == 0) || (ssid.SSID_len > DOT11_MAX_SSID_LEN)) { ++ AP6210_ERR("%s: wldev_get_ssid failed\n", __FUNCTION__); ++ } else { ++ memcpy(command, ssid.SSID, ssid.SSID_len); ++ bytes_written = ssid.SSID_len; ++ } ++ bytes_written += snprintf(&command[bytes_written], total_len, " rssi %d", rssi); ++ AP6210_DEBUG("%s: command result is %s (%d)\n", __FUNCTION__, command, bytes_written); ++ return bytes_written; ++} ++ ++static int wl_android_set_suspendopt(struct net_device *dev, char *command, int total_len) ++{ ++ int suspend_flag; ++ int ret_now; ++ int ret = 0; ++ ++ suspend_flag = *(command + strlen(CMD_SETSUSPENDOPT) + 1) - '0'; ++ ++ if (suspend_flag != 0) ++ suspend_flag = 1; ++ ret_now = net_os_set_suspend_disable(dev, suspend_flag); ++ ++ if (ret_now != suspend_flag) { ++ if (!(ret = net_os_set_suspend(dev, ret_now, 1))) ++ AP6210_DEBUG("%s: Suspend Flag %d -> %d\n", ++ __FUNCTION__, ret_now, suspend_flag); ++ else ++ AP6210_ERR("%s: failed %d\n", __FUNCTION__, ret); ++ } ++ return ret; ++} ++ ++static int wl_android_set_suspendmode(struct net_device *dev, char *command, int total_len) ++{ ++ int ret = 0; ++ ++#if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(DHD_USE_EARLYSUSPEND) ++ int suspend_flag; ++ ++ suspend_flag = *(command + strlen(CMD_SETSUSPENDMODE) + 1) - '0'; ++ ++ if (suspend_flag != 0) ++ suspend_flag = 1; ++ ++ if (!(ret = net_os_set_suspend(dev, suspend_flag, 0))) ++ AP6210_DEBUG("%s: Suspend Mode %d\n",__FUNCTION__,suspend_flag); ++ else ++ AP6210_ERR("%s: failed %d\n",__FUNCTION__,ret); ++#endif ++ return ret; ++} ++ ++static int wl_android_get_band(struct net_device *dev, char *command, int total_len) ++{ ++ uint band; ++ int bytes_written; ++ int error; ++ ++ error = wldev_get_band(dev, &band); ++ if (error) ++ return -1; ++ bytes_written = snprintf(command, total_len, "Band %d", band); ++ return bytes_written; ++} ++ ++#if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN) ++static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len) ++{ ++ wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT]; ++ int res = -1; ++ int nssid = 0; ++ cmd_tlv_t *cmd_tlv_temp; ++ char *str_ptr; ++ int tlv_size_left; ++ int pno_time = 0; ++ int pno_repeat = 0; ++ int pno_freq_expo_max = 0; ++ ++#ifdef PNO_SET_DEBUG ++ int i; ++ char pno_in_example[] = { ++ 'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ', ++ 'S', '1', '2', '0', ++ 'S', ++ 0x05, ++ 'd', 'l', 'i', 'n', 'k', ++ 'S', ++ 0x04, ++ 'G', 'O', 'O', 'G', ++ 'T', ++ '0', 'B', ++ 'R', ++ '2', ++ 'M', ++ '2', ++ 0x00 ++ }; ++#endif /* PNO_SET_DEBUG */ ++ ++ AP6210_DEBUG("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len); ++ ++ if (total_len < (strlen(CMD_PNOSETUP_SET) + sizeof(cmd_tlv_t))) { ++ AP6210_ERR("%s argument=%d less min size\n", __FUNCTION__, total_len); ++ goto exit_proc; ++ } ++ ++ ++#ifdef PNO_SET_DEBUG ++ memcpy(command, pno_in_example, sizeof(pno_in_example)); ++ for (i = 0; i < sizeof(pno_in_example); i++) ++ AP6210_DUMP("%02X ", command[i]); ++ AP6210_DUMP("\n"); ++ total_len = sizeof(pno_in_example); ++#endif ++ ++ str_ptr = command + strlen(CMD_PNOSETUP_SET); ++ tlv_size_left = total_len - strlen(CMD_PNOSETUP_SET); ++ ++ cmd_tlv_temp = (cmd_tlv_t *)str_ptr; ++ memset(ssids_local, 0, sizeof(ssids_local)); ++ ++ if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) && ++ (cmd_tlv_temp->version == PNO_TLV_VERSION) && ++ (cmd_tlv_temp->subver == PNO_TLV_SUBVERSION)) { ++ ++ str_ptr += sizeof(cmd_tlv_t); ++ tlv_size_left -= sizeof(cmd_tlv_t); ++ ++ if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local, ++ MAX_PFN_LIST_COUNT, &tlv_size_left)) <= 0) { ++ AP6210_ERR("SSID is not presented or corrupted ret=%d\n", nssid); ++ goto exit_proc; ++ } else { ++ if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) { ++ AP6210_ERR("%s scan duration corrupted field size %d\n", ++ __FUNCTION__, tlv_size_left); ++ goto exit_proc; ++ } ++ str_ptr++; ++ pno_time = simple_strtoul(str_ptr, &str_ptr, 16); ++ AP6210_DEBUG("%s: pno_time=%d\n", __FUNCTION__, pno_time); ++ ++ if (str_ptr[0] != 0) { ++ if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) { ++ AP6210_ERR("%s pno repeat : corrupted field\n", ++ __FUNCTION__); ++ goto exit_proc; ++ } ++ str_ptr++; ++ pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16); ++ AP6210_DEBUG("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat); ++ if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) { ++ AP6210_ERR("%s FREQ_EXPO_MAX corrupted field size\n", ++ __FUNCTION__); ++ goto exit_proc; ++ } ++ str_ptr++; ++ pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16); ++ AP6210_DEBUG("%s: pno_freq_expo_max=%d\n", ++ __FUNCTION__, pno_freq_expo_max); ++ } ++ } ++ } else { ++ AP6210_ERR("%s get wrong TLV command\n", __FUNCTION__); ++ goto exit_proc; ++ } ++ ++ res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max); ++ ++exit_proc: ++ return res; ++} ++#endif /* PNO_SUPPORT && !WL_SCHED_SCAN */ ++ ++static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len) ++{ ++ int ret; ++ int bytes_written = 0; ++ ++ ret = wl_cfg80211_get_p2p_dev_addr(ndev, (struct ether_addr*)command); ++ if (ret) ++ return 0; ++ bytes_written = sizeof(struct ether_addr); ++ return bytes_written; ++} ++ ++/** ++ * Global function definitions (declared in wl_android.h) ++ */ ++ ++int wl_android_wifi_on(struct net_device *dev) ++{ ++ int ret = 0; ++ int retry = POWERUP_MAX_RETRY; ++ ++ AP6210_DEBUG("%s in\n", __FUNCTION__); ++ if (!dev) { ++ AP6210_ERR("%s: dev is null\n", __FUNCTION__); ++ return -EINVAL; ++ } ++ ++ dhd_net_if_lock(dev); ++ if (!g_wifi_on) { ++ do { ++ dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON); ++ ret = sdioh_start(NULL, 0); ++ if (ret == 0) ++ break; ++ AP6210_ERR("failed to power up wifi chip, retry again (%d left) **\n\n", ++ retry+1); ++ dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); ++ } while (retry-- >= 0); ++ if (ret != 0) { ++ AP6210_ERR("failed to power up wifi chip, max retry reached **\n\n"); ++ goto exit; ++ } ++ ret = dhd_dev_reset(dev, FALSE); ++ if (ret) ++ goto err; ++ sdioh_start(NULL, 1); ++ if (!ret) { ++ if (dhd_dev_init_ioctl(dev) < 0) { ++ ret = -EFAULT; ++ goto err; ++ } ++ } ++#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) ++ dhd_wlfc_init(bcmsdh_get_drvdata()); ++#endif ++ g_wifi_on = TRUE; ++ } ++ ++exit: ++ dhd_net_if_unlock(dev); ++ AP6210_DEBUG("%s: Success\n", __FUNCTION__); ++ return ret; ++err: ++ dhd_dev_reset(dev, TRUE); ++ sdioh_stop(NULL); ++ dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); ++ dhd_net_if_unlock(dev); ++ AP6210_DEBUG("%s: Failed\n", __FUNCTION__); ++ ++ return ret; ++} ++ ++int wl_android_wifi_off(struct net_device *dev) ++{ ++ int ret = 0; ++ ++ AP6210_DEBUG("%s in\n", __FUNCTION__); ++ if (!dev) { ++ AP6210_DEBUG("%s: dev is null\n", __FUNCTION__); ++ return -EINVAL; ++ } ++ ++ dhd_net_if_lock(dev); ++ if (g_wifi_on) { ++#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) ++ dhd_wlfc_deinit(bcmsdh_get_drvdata()); ++#endif ++ ret = dhd_dev_reset(dev, TRUE); ++ sdioh_stop(NULL); ++ dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); ++ g_wifi_on = FALSE; ++ } ++ dhd_net_if_unlock(dev); ++ ++ return ret; ++} ++ ++static int wl_android_set_fwpath(struct net_device *net, char *command, int total_len) ++{ ++ if ((strlen(command) - strlen(CMD_SETFWPATH)) > MOD_PARAM_PATHLEN) ++ return -1; ++ bcm_strncpy_s(fw_path, sizeof(fw_path), ++ command + strlen(CMD_SETFWPATH) + 1, MOD_PARAM_PATHLEN - 1); ++ if (strstr(fw_path, "apsta") != NULL) { ++ AP6210_DEBUG("GOT APSTA FIRMWARE\n"); ++ ap_fw_loaded = TRUE; ++ } else { ++ AP6210_DEBUG("GOT STA FIRMWARE\n"); ++ ap_fw_loaded = FALSE; ++ } ++ return 0; ++} ++ ++static int ++wl_android_set_pmk(struct net_device *dev, char *command, int total_len) ++{ ++ uchar pmk[33]; ++ int error = 0; ++ char smbuf[WLC_IOCTL_SMLEN]; ++#ifdef OKC_DEBUG ++ int i = 0; ++#endif ++ ++ bzero(pmk, sizeof(pmk)); ++ memcpy((char *)pmk, command + strlen("SET_PMK "), 32); ++ error = wldev_iovar_setbuf(dev, "okc_info_pmk", pmk, 32, smbuf, sizeof(smbuf), NULL); ++ if (error) { ++ AP6210_ERR("Failed to set PMK for OKC, error = %d\n", error); ++ } ++#ifdef OKC_DEBUG ++ AP6210_ERR("PMK is "); ++ for (i = 0; i < 32; i++) ++ AP6210_ERR("%02X ", pmk[i]); ++ ++ AP6210_ERR("\n"); ++#endif ++ return error; ++} ++ ++static int ++wl_android_okc_enable(struct net_device *dev, char *command, int total_len) ++{ ++ int error = 0; ++ char okc_enable = 0; ++ ++ okc_enable = command[strlen(CMD_OKC_ENABLE) + 1] - '0'; ++ error = wldev_iovar_setint(dev, "okc_enable", okc_enable); ++ if (error) { ++ AP6210_ERR("Failed to %s OKC, error = %d\n", ++ okc_enable ? "enable" : "disable", error); ++ } ++ ++ return error; ++} ++ ++int wl_android_set_roam_mode(struct net_device *dev, char *command, int total_len) ++{ ++ int error = 0; ++ int mode = 0; ++ ++ if (sscanf(command, "%*s %d", &mode) != 1) { ++ AP6210_ERR("%s: Failed to get Parameter\n", __FUNCTION__); ++ return -1; ++ } ++ ++ error = wldev_iovar_setint(dev, "roam_off", mode); ++ if (error) { ++ AP6210_ERR("%s: Failed to set roaming Mode %d, error = %d\n", ++ __FUNCTION__, mode, error); ++ return -1; ++ } ++ else ++ AP6210_ERR("%s: succeeded to set roaming Mode %d, error = %d\n", ++ __FUNCTION__, mode, error); ++ return 0; ++} ++ ++int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) ++{ ++#define PRIVATE_COMMAND_MAX_LEN 8192 ++ int ret = 0; ++ char *command = NULL; ++ int bytes_written = 0; ++ android_wifi_priv_cmd priv_cmd; ++ ++ net_os_wake_lock(net); ++ ++ if (!ifr->ifr_data) { ++ ret = -EINVAL; ++ goto exit; ++ } ++ if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ if (priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) ++ { ++ AP6210_ERR("%s: too long priavte command\n", __FUNCTION__); ++ ret = -EINVAL; ++ } ++ command = kmalloc(priv_cmd.total_len, GFP_KERNEL); ++ if (!command) ++ { ++ AP6210_ERR("%s: failed to allocate memory\n", __FUNCTION__); ++ ret = -ENOMEM; ++ goto exit; ++ } ++ if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) { ++ ret = -EFAULT; ++ goto exit; ++ } ++ ++ AP6210_DEBUG("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name); ++ ++ if (strnicmp(command, CMD_START, strlen(CMD_START)) == 0) { ++ AP6210_DEBUG("%s, Received regular START command\n", __FUNCTION__); ++ bytes_written = wl_android_wifi_on(net); ++ } ++ else if (strnicmp(command, CMD_SETFWPATH, strlen(CMD_SETFWPATH)) == 0) { ++ bytes_written = wl_android_set_fwpath(net, command, priv_cmd.total_len); ++ } ++ ++ if (!g_wifi_on) { ++ AP6210_ERR("%s: Ignore private cmd \"%s\" - iface %s is down\n", ++ __FUNCTION__, command, ifr->ifr_name); ++ ret = 0; ++ goto exit; ++ } ++ ++ if (strnicmp(command, CMD_STOP, strlen(CMD_STOP)) == 0) { ++ bytes_written = wl_android_wifi_off(net); ++ } ++ else if (strnicmp(command, CMD_SCAN_ACTIVE, strlen(CMD_SCAN_ACTIVE)) == 0) { ++ /* TBD: SCAN-ACTIVE */ ++ } ++ else if (strnicmp(command, CMD_SCAN_PASSIVE, strlen(CMD_SCAN_PASSIVE)) == 0) { ++ /* TBD: SCAN-PASSIVE */ ++ } ++ else if (strnicmp(command, CMD_RSSI, strlen(CMD_RSSI)) == 0) { ++ bytes_written = wl_android_get_rssi(net, command, priv_cmd.total_len); ++ } ++ else if (strnicmp(command, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) { ++ bytes_written = wl_android_get_link_speed(net, command, priv_cmd.total_len); ++ } ++#ifdef PKT_FILTER_SUPPORT ++ else if (strnicmp(command, CMD_RXFILTER_START, strlen(CMD_RXFILTER_START)) == 0) { ++ bytes_written = net_os_enable_packet_filter(net, 1); ++ } ++ else if (strnicmp(command, CMD_RXFILTER_STOP, strlen(CMD_RXFILTER_STOP)) == 0) { ++ bytes_written = net_os_enable_packet_filter(net, 0); ++ } ++ else if (strnicmp(command, CMD_RXFILTER_ADD, strlen(CMD_RXFILTER_ADD)) == 0) { ++ int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0'; ++ bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num); ++ } ++ else if (strnicmp(command, CMD_RXFILTER_REMOVE, strlen(CMD_RXFILTER_REMOVE)) == 0) { ++ int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0'; ++ bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num); ++ } ++#endif /* PKT_FILTER_SUPPORT */ ++ else if (strnicmp(command, CMD_BTCOEXSCAN_START, strlen(CMD_BTCOEXSCAN_START)) == 0) { ++ /* TBD: BTCOEXSCAN-START */ ++ } ++ else if (strnicmp(command, CMD_BTCOEXSCAN_STOP, strlen(CMD_BTCOEXSCAN_STOP)) == 0) { ++ /* TBD: BTCOEXSCAN-STOP */ ++ } ++ else if (strnicmp(command, CMD_BTCOEXMODE, strlen(CMD_BTCOEXMODE)) == 0) { ++#ifdef WL_CFG80211 ++ bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command); ++#else ++#ifdef PKT_FILTER_SUPPORT ++ uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0'; ++ ++ if (mode == 1) ++ net_os_enable_packet_filter(net, 0); /* DHCP starts */ ++ else ++ net_os_enable_packet_filter(net, 1); /* DHCP ends */ ++#endif /* PKT_FILTER_SUPPORT */ ++#endif /* WL_CFG80211 */ ++ } ++ else if (strnicmp(command, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) { ++ bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len); ++ } ++ else if (strnicmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) { ++ bytes_written = wl_android_set_suspendmode(net, command, priv_cmd.total_len); ++ } ++ else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { ++ uint band = *(command + strlen(CMD_SETBAND) + 1) - '0'; ++#ifdef WL_HOST_BAND_MGMT ++ if (wl_cfg80211_set_band(net, band) < 0) { ++ bytes_written = -1; ++ goto exit; ++ } ++ if (band == WLC_BAND_AUTO) ++ bytes_written = wldev_set_band(net, band); ++#else ++ bytes_written = wldev_set_band(net, band); ++#endif /* WL_HOST_BAND_MGMT */ ++ } ++ else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) { ++ bytes_written = wl_android_get_band(net, command, priv_cmd.total_len); ++ } ++#ifdef WL_CFG80211 ++ /* CUSTOMER_SET_COUNTRY feature is define for only GGSM model */ ++ else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) { ++ char *country_code = command + strlen(CMD_COUNTRY) + 1; ++ bytes_written = wldev_set_country(net, country_code); ++ } ++#endif /* WL_CFG80211 */ ++#if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN) ++ else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) { ++ bytes_written = dhd_dev_pno_reset(net); ++ } ++ else if (strnicmp(command, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) { ++ bytes_written = wl_android_set_pno_setup(net, command, priv_cmd.total_len); ++ } ++ else if (strnicmp(command, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) { ++ uint pfn_enabled = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0'; ++ bytes_written = dhd_dev_pno_enable(net, pfn_enabled); ++ } ++#endif /* PNO_SUPPORT && !WL_SCHED_SCAN */ ++ else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) { ++ bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len); ++ } ++ else if (strnicmp(command, CMD_P2P_SET_NOA, strlen(CMD_P2P_SET_NOA)) == 0) { ++ int skip = strlen(CMD_P2P_SET_NOA) + 1; ++ bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, ++ priv_cmd.total_len - skip); ++ } ++#if !defined WL_ENABLE_P2P_IF ++ else if (strnicmp(command, CMD_P2P_GET_NOA, strlen(CMD_P2P_GET_NOA)) == 0) { ++ bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len); ++ } ++#endif /* WL_ENABLE_P2P_IF */ ++ else if (strnicmp(command, CMD_P2P_SET_PS, strlen(CMD_P2P_SET_PS)) == 0) { ++ int skip = strlen(CMD_P2P_SET_PS) + 1; ++ bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, ++ priv_cmd.total_len - skip); ++ } ++#ifdef WL_CFG80211 ++ else if (strnicmp(command, CMD_SET_AP_WPS_P2P_IE, ++ strlen(CMD_SET_AP_WPS_P2P_IE)) == 0) { ++ int skip = strlen(CMD_SET_AP_WPS_P2P_IE) + 3; ++ bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip, ++ priv_cmd.total_len - skip, *(command + skip - 2) - '0'); ++ } ++#endif /* WL_CFG80211 */ ++ else if (strnicmp(command, CMD_OKC_SET_PMK, strlen(CMD_OKC_SET_PMK)) == 0) ++ bytes_written = wl_android_set_pmk(net, command, priv_cmd.total_len); ++ else if (strnicmp(command, CMD_OKC_ENABLE, strlen(CMD_OKC_ENABLE)) == 0) ++ bytes_written = wl_android_okc_enable(net, command, priv_cmd.total_len); ++ else if (strnicmp(command, CMD_SETROAMMODE, strlen(CMD_SETROAMMODE)) == 0) ++ bytes_written = wl_android_set_roam_mode(net, command, priv_cmd.total_len); ++ else { ++ AP6210_ERR("Unknown PRIVATE command %s - ignored\n", command); ++ snprintf(command, 3, "OK"); ++ bytes_written = strlen("OK"); ++ } ++ ++ if (bytes_written >= 0) { ++ if ((bytes_written == 0) && (priv_cmd.total_len > 0)) ++ command[0] = '\0'; ++ if (bytes_written >= priv_cmd.total_len) { ++ AP6210_ERR("%s: bytes_written = %d\n", __FUNCTION__, bytes_written); ++ bytes_written = priv_cmd.total_len; ++ } else { ++ bytes_written++; ++ } ++ priv_cmd.used_len = bytes_written; ++ if (copy_to_user(priv_cmd.buf, command, bytes_written)) { ++ AP6210_ERR("%s: failed to copy data to user buffer\n", __FUNCTION__); ++ ret = -EFAULT; ++ } ++ } ++ else { ++ ret = bytes_written; ++ } ++ ++exit: ++ net_os_wake_unlock(net); ++ if (command) { ++ kfree(command); ++ } ++ ++ return ret; ++} ++ ++int wl_android_init(void) ++{ ++ int ret = 0; ++ ++ dhd_msg_level |= DHD_ERROR_VAL; ++#ifdef ENABLE_INSMOD_NO_FW_LOAD ++ dhd_download_fw_on_driverload = FALSE; ++#endif /* ENABLE_INSMOD_NO_FW_LOAD */ ++ if (!iface_name[0]) { ++ memset(iface_name, 0, IFNAMSIZ); ++ bcm_strncpy_s(iface_name, IFNAMSIZ, "wlan", IFNAMSIZ); ++ } ++ return ret; ++} ++ ++int wl_android_exit(void) ++{ ++ int ret = 0; ++ ++ return ret; ++} ++ ++void wl_android_post_init(void) ++{ ++ if (!dhd_download_fw_on_driverload) { ++ /* Call customer gpio to turn off power with WL_REG_ON signal */ ++ dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); ++ g_wifi_on = 0; ++ } ++} ++ ++#if defined(RSSIAVG) ++void ++wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) ++{ ++ wl_rssi_cache_t *node, *cur, **rssi_head; ++ int i=0; ++ ++ rssi_head = &rssi_cache_ctrl->m_cache_head; ++ node = *rssi_head; ++ ++ for (;node;) { ++ AP6210_DEBUG("%s: Free %d with BSSID %pM\n", ++ __FUNCTION__, i, &node->BSSID); ++ cur = node; ++ node = cur->next; ++ kfree(cur); ++ i++; ++ } ++ *rssi_head = NULL; ++} ++ ++void ++wl_delete_dirty_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) ++{ ++ wl_rssi_cache_t *node, *prev, **rssi_head; ++ int i = -1, tmp = 0; ++#if defined(BSSCACHE) ++ int max = BSSCACHE_LEN; ++#else ++ int max = RSSICACHE_LEN; ++#endif ++ ++ rssi_head = &rssi_cache_ctrl->m_cache_head; ++ node = *rssi_head; ++ prev = node; ++ for (;node;) { ++ i++; ++ if (node->dirty >= max || node->dirty >= RSSICACHE_LEN) { ++ if (node == *rssi_head) { ++ tmp = 1; ++ *rssi_head = node->next; ++ } else { ++ tmp = 0; ++ prev->next = node->next; ++ } ++ AP6210_DEBUG("%s: Del %d with BSSID %pM\n", ++ __FUNCTION__, i, &node->BSSID); ++ kfree(node); ++ if (tmp == 1) { ++ node = *rssi_head; ++ prev = node; ++ } else { ++ node = prev->next; ++ } ++ continue; ++ } ++ prev = node; ++ node = node->next; ++ } ++} ++ ++void ++wl_reset_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) ++{ ++ wl_rssi_cache_t *node, **rssi_head; ++ ++ rssi_head = &rssi_cache_ctrl->m_cache_head; ++ ++ /* reset dirty */ ++ node = *rssi_head; ++ for (;node;) { ++ node->dirty += 1; ++ node = node->next; ++ } ++} ++ ++void ++wl_update_connected_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, struct net_device *net) ++{ ++ wl_rssi_cache_t *node, *prev, **rssi_head; ++ int j, k=0; ++ int rssi, error; ++ struct ether_addr bssid; ++ ++ error = wldev_ioctl(net, WLC_GET_BSSID, &bssid, sizeof(bssid), false); ++ if (error) ++ return; ++ error = wldev_get_rssi(net, &rssi); ++ if (error) ++ return; ++ ++ /* update RSSI */ ++ rssi_head = &rssi_cache_ctrl->m_cache_head; ++ node = *rssi_head; ++ for (;node;) { ++ if (!memcmp(&node->BSSID, &bssid, ETHER_ADDR_LEN)) { ++ AP6210_DEBUG("%s: Update %d with BSSID %pM, RSSI=%d\n", ++ __FUNCTION__, k, &bssid, rssi); ++ for(j=0; jRSSI[j] = node->RSSI[j+1]; ++ node->RSSI[j] = rssi; ++ node->dirty = 0; ++ break; ++ } ++ prev = node; ++ node = node->next; ++ k++; ++ } ++} ++ ++void ++wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, wl_scan_results_t *ss_list) ++{ ++ wl_rssi_cache_t *node, *prev, *leaf, **rssi_head; ++ wl_bss_info_t *bi = NULL; ++ int i, j, k; ++ ++ if (!ss_list->count) ++ return; ++ ++ rssi_head = &rssi_cache_ctrl->m_cache_head; ++ ++ /* update RSSI */ ++ for (i = 0; i < ss_list->count; i++) { ++ node = *rssi_head; ++ prev = NULL; ++ k = 0; ++ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info; ++ for (;node;) { ++ if (!memcmp(&node->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) { ++ AP6210_DEBUG("%s: Update %d with BSSID %pM, RSSI=%d, SSID \"%s\"\n", ++ __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID); ++ for(j=0; jRSSI[j] = node->RSSI[j+1]; ++ node->RSSI[j] = dtoh16(bi->RSSI); ++ node->dirty = 0; ++ break; ++ } ++ prev = node; ++ node = node->next; ++ k++; ++ } ++ ++ if (node) ++ continue; ++ ++ leaf = kmalloc(sizeof(wl_rssi_cache_t), GFP_KERNEL); ++ if (!leaf) { ++ AP6210_ERR("%s: Memory alloc failure %d\n", ++ __FUNCTION__, sizeof(wl_rssi_cache_t)); ++ return; ++ } ++ AP6210_DEBUG("%s: Add %d with cached BSSID %pM, RSSI=%d, SSID \"%s\" in the leaf\n", ++ __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID); ++ ++ leaf->next = NULL; ++ leaf->dirty = 0; ++ memcpy(&leaf->BSSID, &bi->BSSID, ETHER_ADDR_LEN); ++ for (j=0; jRSSI[j] = dtoh16(bi->RSSI); ++ ++ if (!prev) ++ *rssi_head = leaf; ++ else ++ prev->next = leaf; ++ } ++} ++ ++int16 ++wl_get_avg_rssi(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, void *addr) ++{ ++ wl_rssi_cache_t *node, **rssi_head; ++ int j, rssi_sum, rssi=-200; ++ ++ rssi_head = &rssi_cache_ctrl->m_cache_head; ++ ++ /* reset dirty */ ++ node = *rssi_head; ++ for (;node;) { ++ if (!memcmp(&node->BSSID, addr, ETHER_ADDR_LEN)) { ++ rssi_sum = 0; ++ rssi = 0; ++ for (j=0; jRSSI[RSSIAVG_LEN-j-1]; ++ rssi = rssi_sum / j; ++ break; ++ } ++ node = node->next; ++ } ++ if (rssi >= -2) ++ rssi = -2; ++ if (rssi == -200) { ++ AP6210_ERR("%s: BSSID %pM does not in RSSI cache\n", ++ __FUNCTION__, addr); ++ } ++ return (int16)rssi; ++} ++#endif ++ ++#if defined(RSSIOFFSET) ++int ++wl_update_rssi_offset(int rssi) ++{ ++ uint chip, chiprev; ++ ++ chip = dhd_bus_chip_id(bcmsdh_get_drvdata()); ++ chiprev = dhd_bus_chiprev_id(bcmsdh_get_drvdata()); ++ if (chip == BCM4330_CHIP_ID && chiprev == BCM4330B2_CHIP_REV) { ++#if defined(RSSIOFFSET_NEW) ++ int j; ++ for (j=0; j= -2) ++ rssi = -2; ++ return rssi; ++} ++#endif ++ ++#if defined(BSSCACHE) ++#define WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN 32 ++ ++void ++wl_free_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl) ++{ ++ wl_bss_cache_t *node, *cur, **bss_head; ++ int i=0; ++ ++ AP6210_DEBUG("%s called\n", __FUNCTION__); ++ ++ bss_head = &bss_cache_ctrl->m_cache_head; ++ node = *bss_head; ++ ++ for (;node;) { ++ AP6210_DEBUG("%s: Free %d with BSSID %pM\n", ++ __FUNCTION__, i, &node->results.bss_info->BSSID); ++ cur = node; ++ node = cur->next; ++ kfree(cur); ++ i++; ++ } ++ *bss_head = NULL; ++} ++ ++void ++wl_delete_dirty_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl) ++{ ++ wl_bss_cache_t *node, *prev, **bss_head; ++ int i = -1, tmp = 0; ++ ++ bss_head = &bss_cache_ctrl->m_cache_head; ++ node = *bss_head; ++ prev = node; ++ for (;node;) { ++ i++; ++ if (node->dirty >= BSSCACHE_LEN) { ++ if (node == *bss_head) { ++ tmp = 1; ++ *bss_head = node->next; ++ } else { ++ tmp = 0; ++ prev->next = node->next; ++ } ++ AP6210_DEBUG("%s: Del %d with BSSID %pM, RSSI=%d, SSID \"%s\"\n", ++ __FUNCTION__, i, &node->results.bss_info->BSSID, ++ dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID); ++ kfree(node); ++ if (tmp == 1) { ++ node = *bss_head; ++ prev = node; ++ } else { ++ node = prev->next; ++ } ++ continue; ++ } ++ prev = node; ++ node = node->next; ++ } ++} ++ ++void ++wl_reset_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl) ++{ ++ wl_bss_cache_t *node, **bss_head; ++ ++ bss_head = &bss_cache_ctrl->m_cache_head; ++ ++ /* reset dirty */ ++ node = *bss_head; ++ for (;node;) { ++ node->dirty += 1; ++ node = node->next; ++ } ++} ++ ++void ++wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, wl_scan_results_t *ss_list) ++{ ++ wl_bss_cache_t *node, *prev, *leaf, *tmp, **bss_head; ++ wl_bss_info_t *bi = NULL; ++ int i, k=0; ++ ++ if (!ss_list->count) ++ return; ++ ++ bss_head = &bss_cache_ctrl->m_cache_head; ++ ++ for (i=0; i < ss_list->count; i++) { ++ node = *bss_head; ++ prev = NULL; ++ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info; ++ ++ for (;node;) { ++ if (!memcmp(&node->results.bss_info->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) { ++ tmp = node; ++ leaf = kmalloc(dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN, GFP_KERNEL); ++ if (!leaf) { ++ AP6210_ERR("%s: Memory alloc failure %d and keep old BSS info\n", ++ __FUNCTION__, dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN); ++ break; ++ } ++ ++ memcpy(leaf->results.bss_info, bi, dtoh32(bi->length)); ++ leaf->next = node->next; ++ leaf->dirty = 0; ++ leaf->results.count = 1; ++ leaf->results.version = ss_list->version; ++ AP6210_DEBUG("%s: Update %d with BSSID %pM, RSSI=%d, SSID \"%s\"\n", ++ __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID); ++ if (!prev) ++ *bss_head = leaf; ++ else ++ prev->next = leaf; ++ node = leaf; ++ prev = node; ++ ++ kfree(tmp); ++ k++; ++ break; ++ } ++ prev = node; ++ node = node->next; ++ } ++ ++ if (node) ++ continue; ++ ++ leaf = kmalloc(dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN, GFP_KERNEL); ++ if (!leaf) { ++ AP6210_ERR("%s: Memory alloc failure %d\n", __FUNCTION__, ++ dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN); ++ return; ++ } ++ AP6210_DEBUG("%s: Add %d with cached BSSID %pM, RSSI=%d, SSID \"%s\" in the leaf\n", ++ __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID); ++ ++ memcpy(leaf->results.bss_info, bi, dtoh32(bi->length)); ++ leaf->next = NULL; ++ leaf->dirty = 0; ++ leaf->results.count = 1; ++ leaf->results.version = ss_list->version; ++ k++; ++ ++ if (!prev) ++ *bss_head = leaf; ++ else ++ prev->next = leaf; ++ } ++} ++ ++void ++wl_run_bss_cache_timer(wl_bss_cache_ctrl_t *bss_cache_ctrl, int kick_off) ++{ ++ struct timer_list **timer; ++ ++ timer = &bss_cache_ctrl->m_timer; ++ ++ if (*timer) { ++ if (kick_off) { ++ (*timer)->expires = jiffies + BSSCACHE_TIME * HZ / 1000; ++ add_timer(*timer); ++ AP6210_DEBUG("%s: timer starts\n", __FUNCTION__); ++ } else { ++ del_timer_sync(*timer); ++ AP6210_DEBUG("%s: timer stops\n", __FUNCTION__); ++ } ++ } ++} ++ ++void ++wl_set_bss_cache_timer_flag(ulong data) ++{ ++ wl_bss_cache_ctrl_t *bss_cache_ctrl = (wl_bss_cache_ctrl_t *)data; ++ ++ bss_cache_ctrl->m_timer_expired = 1; ++ AP6210_DEBUG("%s called\n", __FUNCTION__); ++} ++ ++void ++wl_release_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl) ++{ ++ AP6210_DEBUG("%s:\n", __FUNCTION__); ++ wl_free_bss_cache(bss_cache_ctrl); ++ wl_run_bss_cache_timer(bss_cache_ctrl, 0); ++ if (bss_cache_ctrl->m_timer) { ++ kfree(bss_cache_ctrl->m_timer); ++ } ++} ++ ++void ++wl_init_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl) ++{ ++ AP6210_DEBUG("%s:\n", __FUNCTION__); ++ bss_cache_ctrl->m_timer_expired = 0; ++ ++ bss_cache_ctrl->m_timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); ++ if (!bss_cache_ctrl->m_timer) { ++ AP6210_ERR("%s: Memory alloc failure\n", __FUNCTION__ ); ++ return; ++ } ++ init_timer(bss_cache_ctrl->m_timer); ++ bss_cache_ctrl->m_timer->function = (void *)wl_set_bss_cache_timer_flag; ++ bss_cache_ctrl->m_timer->data = (ulong)bss_cache_ctrl; ++} ++#endif ++ ++/** ++ * Functions for Android WiFi card detection ++ */ ++#if defined(CONFIG_WIFI_CONTROL_FUNC) ++ ++static int g_wifidev_registered = 0; ++static struct semaphore wifi_control_sem; ++static struct wifi_platform_data *wifi_control_data = NULL; ++static struct resource *wifi_irqres = NULL; ++ ++static int wifi_add_dev(void); ++static void wifi_del_dev(void); ++ ++int wl_android_wifictrl_func_add(void) ++{ ++ int ret = 0; ++ sema_init(&wifi_control_sem, 0); ++ ++ ret = wifi_add_dev(); ++ if (ret) { ++ AP6210_ERR("%s: platform_driver_register failed\n", __FUNCTION__); ++ return ret; ++ } ++ g_wifidev_registered = 1; ++ ++ /* Waiting callback after platform_driver_register is done or exit with error */ ++ if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) { ++ ret = -EINVAL; ++ AP6210_ERR("%s: platform_driver_register timeout\n", __FUNCTION__); ++ } ++ ++ return ret; ++} ++ ++void wl_android_wifictrl_func_del(void) ++{ ++ if (g_wifidev_registered) ++ { ++ wifi_del_dev(); ++ g_wifidev_registered = 0; ++ } ++} ++ ++void* wl_android_prealloc(int section, unsigned long size) ++{ ++ void *alloc_ptr = NULL; ++ if (wifi_control_data && wifi_control_data->mem_prealloc) { ++ alloc_ptr = wifi_control_data->mem_prealloc(section, size); ++ if (alloc_ptr) { ++ AP6210_DEBUG("success alloc section %d\n", section); ++ if (size != 0L) ++ bzero(alloc_ptr, size); ++ return alloc_ptr; ++ } ++ } ++ ++ AP6210_ERR("can't alloc section %d\n", section); ++ return NULL; ++} ++ ++int wifi_get_irq_number(unsigned long *irq_flags_ptr) ++{ ++ if (wifi_irqres) { ++ *irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK; ++ return (int)wifi_irqres->start; ++ } ++#ifdef CUSTOM_OOB_GPIO_NUM ++ return CUSTOM_OOB_GPIO_NUM; ++#else ++ return -1; ++#endif ++} ++ ++int wifi_set_power(int on, unsigned long msec) ++{ ++ AP6210_ERR("%s = %d\n", __FUNCTION__, on); ++ if (wifi_control_data && wifi_control_data->set_power) { ++ wifi_control_data->set_power(on); ++ } ++ if (msec) ++ msleep(msec); ++ return 0; ++} ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) ++int wifi_get_mac_addr(unsigned char *buf) ++{ ++ AP6210_ERR("%s\n", __FUNCTION__); ++ if (!buf) ++ return -EINVAL; ++ if (wifi_control_data && wifi_control_data->get_mac_addr) { ++ return wifi_control_data->get_mac_addr(buf); ++ } ++ return -EOPNOTSUPP; ++} ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) */ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) ++void *wifi_get_country_code(char *ccode) ++{ ++ AP6210_DEBUG("%s\n", __FUNCTION__); ++ if (!ccode) ++ return NULL; ++ if (wifi_control_data && wifi_control_data->get_country_code) { ++ return wifi_control_data->get_country_code(ccode); ++ } ++ return NULL; ++} ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */ ++ ++static int wifi_set_carddetect(int on) ++{ ++ AP6210_ERR("%s = %d\n", __FUNCTION__, on); ++ if (wifi_control_data && wifi_control_data->set_carddetect) { ++ wifi_control_data->set_carddetect(on); ++ } ++ return 0; ++} ++ ++static int wifi_probe(struct platform_device *pdev) ++{ ++ struct wifi_platform_data *wifi_ctrl = ++ (struct wifi_platform_data *)(pdev->dev.platform_data); ++ ++ wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq"); ++ if (wifi_irqres == NULL) ++ wifi_irqres = platform_get_resource_byname(pdev, ++ IORESOURCE_IRQ, "bcm4329_wlan_irq"); ++ wifi_control_data = wifi_ctrl; ++ wifi_set_power(1, 0); /* Power On */ ++ wifi_set_carddetect(1); /* CardDetect (0->1) */ ++ ++ up(&wifi_control_sem); ++ return 0; ++} ++ ++static int wifi_remove(struct platform_device *pdev) ++{ ++ struct wifi_platform_data *wifi_ctrl = ++ (struct wifi_platform_data *)(pdev->dev.platform_data); ++ ++ AP6210_ERR("## %s\n", __FUNCTION__); ++ wifi_control_data = wifi_ctrl; ++ ++ wifi_set_power(0, WIFI_TURNOFF_DELAY); /* Power Off */ ++ wifi_set_carddetect(0); /* CardDetect (1->0) */ ++ ++ up(&wifi_control_sem); ++ return 0; ++} ++ ++static int wifi_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ AP6210_DEBUG("##> %s\n", __FUNCTION__); ++#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) ++ if (dhd_os_check_wakelock(bcmsdh_get_drvdata())) ++ return -EBUSY; ++#endif /* defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) */ ++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) && 1 ++ bcmsdh_oob_intr_set(0); ++#endif /* (OOB_INTR_ONLY) */ ++ return 0; ++} ++ ++static int wifi_resume(struct platform_device *pdev) ++{ ++ AP6210_DEBUG("##> %s\n", __FUNCTION__); ++#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) && 1 ++ if (dhd_os_check_if_up(bcmsdh_get_drvdata())) ++ bcmsdh_oob_intr_set(1); ++#endif /* (OOB_INTR_ONLY) */ ++ return 0; ++} ++ ++static struct platform_driver wifi_device = { ++ .probe = wifi_probe, ++ .remove = wifi_remove, ++ .suspend = wifi_suspend, ++ .resume = wifi_resume, ++ .driver = { ++ .name = "bcmdhd_wlan", ++ } ++}; ++ ++static struct platform_driver wifi_device_legacy = { ++ .probe = wifi_probe, ++ .remove = wifi_remove, ++ .suspend = wifi_suspend, ++ .resume = wifi_resume, ++ .driver = { ++ .name = "bcm4329_wlan", ++ } ++}; ++ ++static int wifi_add_dev(void) ++{ ++ int ret = 0; ++ AP6210_DEBUG("## Calling platform_driver_register\n"); ++ ret = platform_driver_register(&wifi_device); ++ if (ret) ++ return ret; ++ ++ ret = platform_driver_register(&wifi_device_legacy); ++ return ret; ++} ++ ++static void wifi_del_dev(void) ++{ ++ AP6210_DEBUG("## Unregister platform_driver_register\n"); ++ platform_driver_unregister(&wifi_device); ++ platform_driver_unregister(&wifi_device_legacy); ++} ++#endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */ +diff --git a/drivers/net/wireless/ap6210/wl_android.h b/drivers/net/wireless/ap6210/wl_android.h +new file mode 100755 +index 0000000..d933e06 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/wl_android.h +@@ -0,0 +1,124 @@ ++/* ++ * Linux cfg80211 driver - Android related functions ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: wl_android.h 367273 2012-11-07 09:58:55Z $ ++ */ ++ ++#include ++#include ++#include ++ ++/* If any feature uses the Generic Netlink Interface, put it here to enable WL_GENL ++ * automatically ++ */ ++ ++/** ++ * Android platform dependent functions, feel free to add Android specific functions here ++ * (save the macros in dhd). Please do NOT declare functions that are NOT exposed to dhd ++ * or cfg, define them as static in wl_android.c ++ */ ++ ++/** ++ * wl_android_init will be called from module init function (dhd_module_init now), similarly ++ * wl_android_exit will be called from module exit function (dhd_module_cleanup now) ++ */ ++int wl_android_init(void); ++int wl_android_exit(void); ++void wl_android_post_init(void); ++int wl_android_wifi_on(struct net_device *dev); ++int wl_android_wifi_off(struct net_device *dev); ++int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd); ++ ++#define BSSCACHE ++#define RSSIAVG ++#define RSSIOFFSET ++//#define RSSIOFFSET_NEW ++ ++#if defined(RSSIAVG) ++#define RSSIAVG_LEN 8 ++#define RSSICACHE_LEN 8 ++ ++typedef struct wl_rssi_cache { ++ struct wl_rssi_cache *next; ++ int dirty; ++ struct ether_addr BSSID; ++ int16 RSSI[RSSIAVG_LEN]; ++} wl_rssi_cache_t; ++ ++typedef struct wl_rssi_cache_ctrl { ++ wl_rssi_cache_t *m_cache_head; ++} wl_rssi_cache_ctrl_t; ++ ++void wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl); ++void wl_delete_dirty_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl); ++void wl_reset_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl); ++void wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, wl_scan_results_t *ss_list); ++void wl_update_connected_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, struct net_device *net); ++int16 wl_get_avg_rssi(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, void *addr); ++#endif ++ ++#if defined(RSSIOFFSET) ++#define RSSI_OFFSET 5 ++#define RSSI_MAX -80 ++#define RSSI_MIN -94 ++#define RSSI_INT ((RSSI_MAX-RSSI_MIN)/RSSI_OFFSET) ++#define BCM4330_CHIP_ID 0x4330 ++#define BCM4330B2_CHIP_REV 4 ++int wl_update_rssi_offset(int rssi); ++#endif ++ ++#if defined(BSSCACHE) ++#define BSSCACHE_LEN 8 ++#define BSSCACHE_TIME 15000 ++ ++typedef struct wl_bss_cache { ++ struct wl_bss_cache *next; ++ int dirty; ++ wl_scan_results_t results; ++} wl_bss_cache_t; ++ ++typedef struct wl_bss_cache_ctrl { ++ wl_bss_cache_t *m_cache_head; ++ struct timer_list *m_timer; ++ int m_timer_expired; ++} wl_bss_cache_ctrl_t; ++ ++void wl_free_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl); ++void wl_delete_dirty_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl); ++void wl_reset_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl); ++void wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, wl_scan_results_t *ss_list); ++void wl_run_bss_cache_timer(wl_bss_cache_ctrl_t *bss_cache_ctrl, int kick_off); ++void wl_release_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl); ++void wl_init_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl); ++#endif ++ ++#if defined(CONFIG_WIFI_CONTROL_FUNC) ++int wl_android_wifictrl_func_add(void); ++void wl_android_wifictrl_func_del(void); ++void* wl_android_prealloc(int section, unsigned long size); ++ ++int wifi_get_irq_number(unsigned long *irq_flags_ptr); ++int wifi_set_power(int on, unsigned long msec); ++int wifi_get_mac_addr(unsigned char *buf); ++void *wifi_get_country_code(char *ccode); ++#endif /* CONFIG_WIFI_CONTROL_FUNC */ +diff --git a/drivers/net/wireless/ap6210/wl_cfg80211.c b/drivers/net/wireless/ap6210/wl_cfg80211.c +new file mode 100755 +index 0000000..1ebce14 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/wl_cfg80211.c +@@ -0,0 +1,10129 @@ ++/* ++ * Linux cfg80211 driver ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: wl_cfg80211.c 374275 2012-12-12 11:44:18Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#ifdef PROP_TXSTATUS ++#include ++#endif ++#ifdef BCMWAPI_WPI ++/* these items should evetually go into wireless.h of the linux system headfile dir */ ++#ifndef IW_ENCODE_ALG_SM4 ++#define IW_ENCODE_ALG_SM4 0x20 ++#endif ++ ++#ifndef IW_AUTH_WAPI_ENABLED ++#define IW_AUTH_WAPI_ENABLED 0x20 ++#endif ++ ++#ifndef IW_AUTH_WAPI_VERSION_1 ++#define IW_AUTH_WAPI_VERSION_1 0x00000008 ++#endif ++ ++#ifndef IW_AUTH_CIPHER_SMS4 ++#define IW_AUTH_CIPHER_SMS4 0x00000020 ++#endif ++ ++#ifndef IW_AUTH_KEY_MGMT_WAPI_PSK ++#define IW_AUTH_KEY_MGMT_WAPI_PSK 4 ++#endif ++ ++#ifndef IW_AUTH_KEY_MGMT_WAPI_CERT ++#define IW_AUTH_KEY_MGMT_WAPI_CERT 8 ++#endif ++#endif /* BCMWAPI_WPI */ ++ ++#ifdef BCMWAPI_WPI ++#define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED)) ++#else /* BCMWAPI_WPI */ ++#define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)) ++#endif /* BCMWAPI_WPI */ ++#ifdef WL11U ++#ifndef WL_ENABLE_P2P_IF ++#error "You should enable WL_ENABLE_P2P_IF and Only supported in JB" ++#endif ++#endif /* WL11U */ ++ ++#define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)) ++ ++static struct device *cfg80211_parent_dev = NULL; ++struct wl_priv *wlcfg_drv_priv = NULL; ++u32 wl_dbg_level = WL_DBG_ERR; ++ ++#define MAX_WAIT_TIME 1500 ++ ++#ifdef VSDB ++/* sleep time to keep STA's connecting or connection for continuous af tx or finding a peer */ ++#define DEFAULT_SLEEP_TIME_VSDB 200 ++#define OFF_CHAN_TIME_THRESHOLD_MS 200 ++ ++/* if sta is connected or connecting, sleep for a while before retry af tx or finding a peer */ ++#define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl) \ ++ do { \ ++ if (wl_get_drv_status(wl, CONNECTED, wl_to_prmry_ndev(wl)) || \ ++ wl_get_drv_status(wl, CONNECTING, wl_to_prmry_ndev(wl))) { \ ++ msleep(DEFAULT_SLEEP_TIME_VSDB); \ ++ } \ ++ } while (0) ++#else /* VSDB */ ++/* if not VSDB, do nothing */ ++#define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl) ++#endif /* VSDB */ ++ ++#ifdef WL_CFG80211_SYNC_GON ++#define WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl) \ ++ (wl_get_drv_status_all(wl, SENDING_ACT_FRM) || \ ++ wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) ++#else ++#define WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl) wl_get_drv_status_all(wl, SENDING_ACT_FRM) ++#endif /* WL_CFG80211_SYNC_GON */ ++ ++#define WL_CHANSPEC_CTL_SB_NONE WL_CHANSPEC_CTL_SB_LLL ++ ++ ++#define DNGL_FUNC(func, parameters) func parameters; ++#define COEX_DHCP ++ ++#define WLAN_EID_SSID 0 ++#define CH_MIN_5G_CHANNEL 34 ++#define CH_MIN_2G_CHANNEL 1 ++ ++/* This is to override regulatory domains defined in cfg80211 module (reg.c) ++ * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN ++ * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165). ++ * With respect to these flags, wpa_supplicant doesn't start p2p operations on 5GHz channels. ++ * All the chnages in world regulatory domain are to be done here. ++ */ ++static const struct ieee80211_regdomain brcm_regdom = { ++ .n_reg_rules = 4, ++ .alpha2 = "99", ++ .reg_rules = { ++ /* IEEE 802.11b/g, channels 1..11 */ ++ REG_RULE(2412-10, 2472+10, 40, 6, 20, 0), ++ /* If any */ ++ /* IEEE 802.11 channel 14 - Only JP enables ++ * this and for 802.11b only ++ */ ++ REG_RULE(2484-10, 2484+10, 20, 6, 20, 0), ++ /* IEEE 802.11a, channel 36..64 */ ++ REG_RULE(5150-10, 5350+10, 40, 6, 20, 0), ++ /* IEEE 802.11a, channel 100..165 */ ++ REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), } ++}; ++ ++ ++/* Data Element Definitions */ ++#define WPS_ID_CONFIG_METHODS 0x1008 ++#define WPS_ID_REQ_TYPE 0x103A ++#define WPS_ID_DEVICE_NAME 0x1011 ++#define WPS_ID_VERSION 0x104A ++#define WPS_ID_DEVICE_PWD_ID 0x1012 ++#define WPS_ID_REQ_DEV_TYPE 0x106A ++#define WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS 0x1053 ++#define WPS_ID_PRIM_DEV_TYPE 0x1054 ++ ++/* Device Password ID */ ++#define DEV_PW_DEFAULT 0x0000 ++#define DEV_PW_USER_SPECIFIED 0x0001, ++#define DEV_PW_MACHINE_SPECIFIED 0x0002 ++#define DEV_PW_REKEY 0x0003 ++#define DEV_PW_PUSHBUTTON 0x0004 ++#define DEV_PW_REGISTRAR_SPECIFIED 0x0005 ++ ++/* Config Methods */ ++#define WPS_CONFIG_USBA 0x0001 ++#define WPS_CONFIG_ETHERNET 0x0002 ++#define WPS_CONFIG_LABEL 0x0004 ++#define WPS_CONFIG_DISPLAY 0x0008 ++#define WPS_CONFIG_EXT_NFC_TOKEN 0x0010 ++#define WPS_CONFIG_INT_NFC_TOKEN 0x0020 ++#define WPS_CONFIG_NFC_INTERFACE 0x0040 ++#define WPS_CONFIG_PUSHBUTTON 0x0080 ++#define WPS_CONFIG_KEYPAD 0x0100 ++#define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280 ++#define WPS_CONFIG_PHY_PUSHBUTTON 0x0480 ++#define WPS_CONFIG_VIRT_DISPLAY 0x2008 ++#define WPS_CONFIG_PHY_DISPLAY 0x4008 ++ ++#define PM_BLOCK 1 ++#define PM_ENABLE 0 ++/* ++ * cfg80211_ops api/callback list ++ */ ++static s32 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da, ++ const struct ether_addr *sa, const struct ether_addr *bssid, ++ u8 **pheader, u32 *body_len, u8 *pbody); ++static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_scan_request *request, ++ struct cfg80211_ssid *this_ssid); ++static s32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_scan_request *request); ++static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed); ++static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_ibss_params *params); ++static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, ++ struct net_device *dev); ++static s32 wl_cfg80211_get_station(struct wiphy *wiphy, ++ struct net_device *dev, u8 *mac, ++ struct station_info *sinfo); ++static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, ++ struct net_device *dev, bool enabled, ++ s32 timeout); ++static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_connect_params *sme); ++static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, ++ u16 reason_code); ++static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy, ++ enum nl80211_tx_power_setting type, ++ s32 dbm); ++static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm); ++static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy, ++ struct net_device *dev, ++ u8 key_idx, bool unicast, bool multicast); ++static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, ++ u8 key_idx, bool pairwise, const u8 *mac_addr, ++ struct key_params *params); ++static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, ++ u8 key_idx, bool pairwise, const u8 *mac_addr); ++static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, ++ u8 key_idx, bool pairwise, const u8 *mac_addr, ++ void *cookie, void (*callback) (void *cookie, ++ struct key_params *params)); ++static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, ++ struct net_device *dev, u8 key_idx); ++static s32 wl_cfg80211_resume(struct wiphy *wiphy); ++#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ ++ 2, 0)) ++static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, ++ struct net_device *dev, u64 cookie); ++static s32 wl_cfg80211_del_station(struct wiphy *wiphy, ++ struct net_device *ndev, u8* mac_addr); ++#endif ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) ++static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow); ++#else ++static s32 wl_cfg80211_suspend(struct wiphy *wiphy); ++#endif ++static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_pmksa *pmksa); ++static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_pmksa *pmksa); ++static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, ++ struct net_device *dev); ++static s32 wl_notify_escan_complete(struct wl_priv *wl, ++ struct net_device *ndev, bool aborted, bool fw_abort); ++/* ++ * event & event Q handlers for cfg80211 interfaces ++ */ ++static s32 wl_create_event_handler(struct wl_priv *wl); ++static void wl_destroy_event_handler(struct wl_priv *wl); ++static s32 wl_event_handler(void *data); ++static void wl_init_eq(struct wl_priv *wl); ++static void wl_flush_eq(struct wl_priv *wl); ++static unsigned long wl_lock_eq(struct wl_priv *wl); ++static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags); ++static void wl_init_eq_lock(struct wl_priv *wl); ++static void wl_init_event_handler(struct wl_priv *wl); ++static struct wl_event_q *wl_deq_event(struct wl_priv *wl); ++static s32 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 type, ++ const wl_event_msg_t *msg, void *data); ++static void wl_put_event(struct wl_event_q *e); ++static void wl_wakeup_event(struct wl_priv *wl); ++static s32 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data); ++static s32 wl_notify_connect_status(struct wl_priv *wl, ++ struct net_device *ndev, ++ const wl_event_msg_t *e, void *data); ++static s32 wl_notify_roaming_status(struct wl_priv *wl, ++ struct net_device *ndev, ++ const wl_event_msg_t *e, void *data); ++static s32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data); ++static s32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data, bool completed); ++static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data); ++static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data); ++#ifdef WL_SCHED_SCAN ++static s32 ++wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data); ++#endif /* WL_SCHED_SCAN */ ++#ifdef PNO_SUPPORT ++static s32 wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data); ++#endif /* PNO_SUPPORT */ ++static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info, ++ enum wl_status state, bool set); ++/* ++ * register/deregister parent device ++ */ ++static void wl_cfg80211_clear_parent_dev(void); ++ ++/* ++ * ioctl utilites ++ */ ++ ++/* ++ * cfg80211 set_wiphy_params utilities ++ */ ++static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold); ++static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold); ++static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l); ++ ++/* ++ * wl profile utilities ++ */ ++static s32 wl_update_prof(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data, s32 item); ++static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item); ++static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev); ++ ++/* ++ * cfg80211 connect utilites ++ */ ++static s32 wl_set_wpa_version(struct net_device *dev, ++ struct cfg80211_connect_params *sme); ++static s32 wl_set_auth_type(struct net_device *dev, ++ struct cfg80211_connect_params *sme); ++static s32 wl_set_set_cipher(struct net_device *dev, ++ struct cfg80211_connect_params *sme); ++static s32 wl_set_key_mgmt(struct net_device *dev, ++ struct cfg80211_connect_params *sme); ++static s32 wl_set_set_sharedkey(struct net_device *dev, ++ struct cfg80211_connect_params *sme); ++#ifdef BCMWAPI_WPI ++static s32 wl_set_set_wapi_ie(struct net_device *dev, ++ struct cfg80211_connect_params *sme); ++#endif ++static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev); ++static void wl_ch_to_chanspec(int ch, ++ struct wl_join_params *join_params, size_t *join_params_size); ++ ++/* ++ * information element utilities ++ */ ++static void wl_rst_ie(struct wl_priv *wl); ++static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v); ++static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size); ++static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size); ++static u32 wl_get_ielen(struct wl_priv *wl); ++ ++#ifdef WL11U ++bcm_tlv_t * ++wl_cfg80211_find_interworking_ie(u8 *parse, u32 len); ++static s32 ++wl_cfg80211_add_iw_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag, ++ uint8 ie_id, uint8 *data, uint8 data_len); ++#endif /* WL11U */ ++ ++static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev); ++static void wl_free_wdev(struct wl_priv *wl); ++static int ++wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); ++ ++static s32 wl_inform_bss(struct wl_priv *wl); ++static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 is_roam_done); ++static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 is_roam_done); ++static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy); ++s32 wl_cfg80211_channel_to_freq(u32 channel); ++ ++#if defined(DHCP_SCAN_SUPPRESS) ++static void wl_cfg80211_work_handler(struct work_struct *work); ++static void wl_cfg80211_scan_supp_timerfunc(ulong data); ++#endif /* DHCP_SCAN_SUPPRESS */ ++ ++static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, ++ u8 key_idx, const u8 *mac_addr, ++ struct key_params *params); ++/* ++ * key indianess swap utilities ++ */ ++static void swap_key_from_BE(struct wl_wsec_key *key); ++static void swap_key_to_BE(struct wl_wsec_key *key); ++ ++/* ++ * wl_priv memory init/deinit utilities ++ */ ++static s32 wl_init_priv_mem(struct wl_priv *wl); ++static void wl_deinit_priv_mem(struct wl_priv *wl); ++ ++static void wl_delay(u32 ms); ++ ++/* ++ * ibss mode utilities ++ */ ++static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev); ++static __used bool wl_is_ibssstarter(struct wl_priv *wl); ++ ++/* ++ * link up/down , default configuration utilities ++ */ ++static s32 __wl_cfg80211_up(struct wl_priv *wl); ++static s32 __wl_cfg80211_down(struct wl_priv *wl); ++static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e); ++static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev); ++static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e); ++static void wl_link_up(struct wl_priv *wl); ++static void wl_link_down(struct wl_priv *wl); ++static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype); ++static void wl_init_conf(struct wl_conf *conf); ++ ++/* ++ * iscan handler ++ */ ++static void wl_iscan_timer(unsigned long data); ++static void wl_term_iscan(struct wl_priv *wl); ++static s32 wl_init_scan(struct wl_priv *wl); ++static s32 wl_iscan_thread(void *data); ++static s32 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request, ++ u16 action); ++static s32 wl_do_iscan(struct wl_priv *wl, struct cfg80211_scan_request *request); ++static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan); ++static s32 wl_invoke_iscan(struct wl_priv *wl); ++static s32 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status, ++ struct wl_scan_results **bss_list); ++static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted); ++static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan); ++static s32 wl_iscan_done(struct wl_priv *wl); ++static s32 wl_iscan_pending(struct wl_priv *wl); ++static s32 wl_iscan_inprogress(struct wl_priv *wl); ++static s32 wl_iscan_aborted(struct wl_priv *wl); ++ ++/* ++ * find most significant bit set ++ */ ++static __used u32 wl_find_msb(u16 bit16); ++ ++/* ++ * rfkill support ++ */ ++static int wl_setup_rfkill(struct wl_priv *wl, bool setup); ++static int wl_rfkill_set(void *data, bool blocked); ++ ++static wl_scan_params_t *wl_cfg80211_scan_alloc_params(int channel, ++ int nprobes, int *out_params_size); ++static void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac); ++ ++/* ++ * Some external functions, TODO: move them to dhd_linux.h ++ */ ++int dhd_add_monitor(char *name, struct net_device **new_ndev); ++int dhd_del_monitor(struct net_device *ndev); ++int dhd_monitor_init(void *dhd_pub); ++int dhd_monitor_uninit(void); ++int dhd_start_xmit(struct sk_buff *skb, struct net_device *net); ++ ++ ++ ++#define CHECK_SYS_UP(wlpriv) \ ++do { \ ++ struct net_device *ndev = wl_to_prmry_ndev(wlpriv); \ ++ if (unlikely(!wl_get_drv_status(wlpriv, READY, ndev))) { \ ++ AP6210_DEBUG("device is not ready\n"); \ ++ return -EIO; \ ++ } \ ++} while (0) ++ ++ ++#define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE || \ ++ (akm) == RSN_AKM_UNSPECIFIED || \ ++ (akm) == RSN_AKM_PSK) ++ ++ ++extern int dhd_wait_pend8021x(struct net_device *dev); ++#ifdef PROP_TXSTATUS_VSDB ++extern int disable_proptx; ++extern int dhd_wlfc_init(dhd_pub_t *dhd); ++extern void dhd_wlfc_deinit(dhd_pub_t *dhd); ++#endif /* PROP_TXSTATUS_VSDB */ ++ ++#if (WL_DBG_LEVEL > 0) ++#define WL_DBG_ESTR_MAX 50 ++static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = { ++ "SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND", ++ "DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC", ++ "REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END", ++ "BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM", ++ "TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH", ++ "EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND", ++ "BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND", ++ "PFN_NET_LOST", ++ "RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START", ++ "IBSS_ASSOC", ++ "RADIO", "PSM_WATCHDOG", "WLC_E_CCX_ASSOC_START", "WLC_E_CCX_ASSOC_ABORT", ++ "PROBREQ_MSG", ++ "SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED", ++ "EXCEEDED_MEDIUM_TIME", "ICV_ERROR", ++ "UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE", ++ "WLC_E_BTA_HCI_EVENT", "IF", "WLC_E_P2P_DISC_LISTEN_COMPLETE", ++ "RSSI", "PFN_SCAN_COMPLETE", "WLC_E_EXTLOG_MSG", ++ "ACTION_FRAME", "ACTION_FRAME_COMPLETE", "WLC_E_PRE_ASSOC_IND", ++ "WLC_E_PRE_REASSOC_IND", "WLC_E_CHANNEL_ADOPTED", "WLC_E_AP_STARTED", ++ "WLC_E_DFS_AP_STOP", "WLC_E_DFS_AP_RESUME", "WLC_E_WAI_STA_EVENT", ++ "WLC_E_WAI_MSG", "WLC_E_ESCAN_RESULT", "WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE", ++ "WLC_E_PROBRESP_MSG", "WLC_E_P2P_PROBREQ_MSG", "WLC_E_DCS_REQUEST", "WLC_E_FIFO_CREDIT_MAP", ++ "WLC_E_ACTION_FRAME_RX", "WLC_E_WAKE_EVENT", "WLC_E_RM_COMPLETE" ++}; ++#endif /* WL_DBG_LEVEL */ ++ ++#define CHAN2G(_channel, _freq, _flags) { \ ++ .band = IEEE80211_BAND_2GHZ, \ ++ .center_freq = (_freq), \ ++ .hw_value = (_channel), \ ++ .flags = (_flags), \ ++ .max_antenna_gain = 0, \ ++ .max_power = 30, \ ++} ++ ++#define CHAN5G(_channel, _flags) { \ ++ .band = IEEE80211_BAND_5GHZ, \ ++ .center_freq = 5000 + (5 * (_channel)), \ ++ .hw_value = (_channel), \ ++ .flags = (_flags), \ ++ .max_antenna_gain = 0, \ ++ .max_power = 30, \ ++} ++ ++#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2) ++#define RATETAB_ENT(_rateid, _flags) \ ++ { \ ++ .bitrate = RATE_TO_BASE100KBPS(_rateid), \ ++ .hw_value = (_rateid), \ ++ .flags = (_flags), \ ++ } ++ ++static struct ieee80211_rate __wl_rates[] = { ++ RATETAB_ENT(WLC_RATE_1M, 0), ++ RATETAB_ENT(WLC_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATETAB_ENT(WLC_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATETAB_ENT(WLC_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE), ++ RATETAB_ENT(WLC_RATE_6M, 0), ++ RATETAB_ENT(WLC_RATE_9M, 0), ++ RATETAB_ENT(WLC_RATE_12M, 0), ++ RATETAB_ENT(WLC_RATE_18M, 0), ++ RATETAB_ENT(WLC_RATE_24M, 0), ++ RATETAB_ENT(WLC_RATE_36M, 0), ++ RATETAB_ENT(WLC_RATE_48M, 0), ++ RATETAB_ENT(WLC_RATE_54M, 0) ++}; ++ ++#define wl_a_rates (__wl_rates + 4) ++#define wl_a_rates_size 8 ++#define wl_g_rates (__wl_rates + 0) ++#define wl_g_rates_size 12 ++ ++static struct ieee80211_channel __wl_2ghz_channels[] = { ++ CHAN2G(1, 2412, 0), ++ CHAN2G(2, 2417, 0), ++ CHAN2G(3, 2422, 0), ++ CHAN2G(4, 2427, 0), ++ CHAN2G(5, 2432, 0), ++ CHAN2G(6, 2437, 0), ++ CHAN2G(7, 2442, 0), ++ CHAN2G(8, 2447, 0), ++ CHAN2G(9, 2452, 0), ++ CHAN2G(10, 2457, 0), ++ CHAN2G(11, 2462, 0), ++ CHAN2G(12, 2467, 0), ++ CHAN2G(13, 2472, 0), ++ CHAN2G(14, 2484, 0) ++}; ++ ++static struct ieee80211_channel __wl_5ghz_a_channels[] = { ++ CHAN5G(34, 0), CHAN5G(36, 0), ++ CHAN5G(38, 0), CHAN5G(40, 0), ++ CHAN5G(42, 0), CHAN5G(44, 0), ++ CHAN5G(46, 0), CHAN5G(48, 0), ++ CHAN5G(52, 0), CHAN5G(56, 0), ++ CHAN5G(60, 0), CHAN5G(64, 0), ++ CHAN5G(100, 0), CHAN5G(104, 0), ++ CHAN5G(108, 0), CHAN5G(112, 0), ++ CHAN5G(116, 0), CHAN5G(120, 0), ++ CHAN5G(124, 0), CHAN5G(128, 0), ++ CHAN5G(132, 0), CHAN5G(136, 0), ++ CHAN5G(140, 0), CHAN5G(149, 0), ++ CHAN5G(153, 0), CHAN5G(157, 0), ++ CHAN5G(161, 0), CHAN5G(165, 0) ++}; ++ ++static struct ieee80211_supported_band __wl_band_2ghz = { ++ .band = IEEE80211_BAND_2GHZ, ++ .channels = __wl_2ghz_channels, ++ .n_channels = ARRAY_SIZE(__wl_2ghz_channels), ++ .bitrates = wl_g_rates, ++ .n_bitrates = wl_g_rates_size ++}; ++ ++static struct ieee80211_supported_band __wl_band_5ghz_a = { ++ .band = IEEE80211_BAND_5GHZ, ++ .channels = __wl_5ghz_a_channels, ++ .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels), ++ .bitrates = wl_a_rates, ++ .n_bitrates = wl_a_rates_size ++}; ++ ++static const u32 __wl_cipher_suites[] = { ++ WLAN_CIPHER_SUITE_WEP40, ++ WLAN_CIPHER_SUITE_WEP104, ++ WLAN_CIPHER_SUITE_TKIP, ++ WLAN_CIPHER_SUITE_CCMP, ++ WLAN_CIPHER_SUITE_AES_CMAC, ++#ifdef BCMWAPI_WPI ++ WLAN_CIPHER_SUITE_SMS4 ++#endif ++}; ++ ++ ++/* IOCtl version read from targeted driver */ ++static int ioctl_version; ++ ++/* Return a new chanspec given a legacy chanspec ++ * Returns INVCHANSPEC on error ++ */ ++static chanspec_t ++wl_chspec_from_legacy(chanspec_t legacy_chspec) ++{ ++ chanspec_t chspec; ++ ++ /* get the channel number */ ++ chspec = LCHSPEC_CHANNEL(legacy_chspec); ++ ++ /* convert the band */ ++ if (LCHSPEC_IS2G(legacy_chspec)) { ++ chspec |= WL_CHANSPEC_BAND_2G; ++ } else { ++ chspec |= WL_CHANSPEC_BAND_5G; ++ } ++ ++ /* convert the bw and sideband */ ++ if (LCHSPEC_IS20(legacy_chspec)) { ++ chspec |= WL_CHANSPEC_BW_20; ++ } else { ++ chspec |= WL_CHANSPEC_BW_40; ++ if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) { ++ chspec |= WL_CHANSPEC_CTL_SB_L; ++ } else { ++ chspec |= WL_CHANSPEC_CTL_SB_U; ++ } ++ } ++ ++ if (wf_chspec_malformed(chspec)) { ++ AP6210_ERR("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n", ++ chspec); ++ return INVCHANSPEC; ++ } ++ ++ return chspec; ++} ++ ++/* Return a legacy chanspec given a new chanspec ++ * Returns INVCHANSPEC on error ++ */ ++static chanspec_t ++wl_chspec_to_legacy(chanspec_t chspec) ++{ ++ chanspec_t lchspec; ++ ++ if (wf_chspec_malformed(chspec)) { ++ AP6210_ERR("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n", ++ chspec); ++ return INVCHANSPEC; ++ } ++ ++ /* get the channel number */ ++ lchspec = CHSPEC_CHANNEL(chspec); ++ ++ /* convert the band */ ++ if (CHSPEC_IS2G(chspec)) { ++ lchspec |= WL_LCHANSPEC_BAND_2G; ++ } else { ++ lchspec |= WL_LCHANSPEC_BAND_5G; ++ } ++ ++ /* convert the bw and sideband */ ++ if (CHSPEC_IS20(chspec)) { ++ lchspec |= WL_LCHANSPEC_BW_20; ++ lchspec |= WL_LCHANSPEC_CTL_SB_NONE; ++ } else if (CHSPEC_IS40(chspec)) { ++ lchspec |= WL_LCHANSPEC_BW_40; ++ if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) { ++ lchspec |= WL_LCHANSPEC_CTL_SB_LOWER; ++ } else { ++ lchspec |= WL_LCHANSPEC_CTL_SB_UPPER; ++ } ++ } else { ++ /* cannot express the bandwidth */ ++ char chanbuf[CHANSPEC_STR_LEN]; ++ AP6210_ERR( ++ "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) " ++ "to pre-11ac format\n", ++ wf_chspec_ntoa(chspec, chanbuf), chspec); ++ return INVCHANSPEC; ++ } ++ ++ return lchspec; ++} ++ ++/* given a chanspec value, do the endian and chanspec version conversion to ++ * a chanspec_t value ++ * Returns INVCHANSPEC on error ++ */ ++static chanspec_t ++wl_chspec_host_to_driver(chanspec_t chanspec) ++{ ++ if (ioctl_version == 1) { ++ chanspec = wl_chspec_to_legacy(chanspec); ++ if (chanspec == INVCHANSPEC) { ++ return chanspec; ++ } ++ } ++ chanspec = htodchanspec(chanspec); ++ ++ return chanspec; ++} ++ ++/* given a channel value, do the endian and chanspec version conversion to ++ * a chanspec_t value ++ * Returns INVCHANSPEC on error ++ */ ++chanspec_t ++wl_ch_host_to_driver(u16 channel) ++{ ++ ++ chanspec_t chanspec; ++ ++ chanspec = channel & WL_CHANSPEC_CHAN_MASK; ++ ++ if (channel <= CH_MAX_2G_CHANNEL) ++ chanspec |= WL_CHANSPEC_BAND_2G; ++ else ++ chanspec |= WL_CHANSPEC_BAND_5G; ++ ++ chanspec |= WL_CHANSPEC_BW_20; ++ chanspec |= WL_CHANSPEC_CTL_SB_NONE; ++ ++ return wl_chspec_host_to_driver(chanspec); ++} ++ ++/* given a chanspec value from the driver, do the endian and chanspec version conversion to ++ * a chanspec_t value ++ * Returns INVCHANSPEC on error ++ */ ++static chanspec_t ++wl_chspec_driver_to_host(chanspec_t chanspec) ++{ ++ chanspec = dtohchanspec(chanspec); ++ if (ioctl_version == 1) { ++ chanspec = wl_chspec_from_legacy(chanspec); ++ } ++ ++ return chanspec; ++} ++ ++/* There isn't a lot of sense in it, but you can transmit anything you like */ ++static const struct ieee80211_txrx_stypes ++wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { ++ [NL80211_IFTYPE_ADHOC] = { ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) ++ }, ++ [NL80211_IFTYPE_STATION] = { ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | ++ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) ++ }, ++ [NL80211_IFTYPE_AP] = { ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | ++ BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | ++ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ++ BIT(IEEE80211_STYPE_DISASSOC >> 4) | ++ BIT(IEEE80211_STYPE_AUTH >> 4) | ++ BIT(IEEE80211_STYPE_DEAUTH >> 4) | ++ BIT(IEEE80211_STYPE_ACTION >> 4) ++ }, ++ [NL80211_IFTYPE_AP_VLAN] = { ++ /* copy AP */ ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | ++ BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | ++ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ++ BIT(IEEE80211_STYPE_DISASSOC >> 4) | ++ BIT(IEEE80211_STYPE_AUTH >> 4) | ++ BIT(IEEE80211_STYPE_DEAUTH >> 4) | ++ BIT(IEEE80211_STYPE_ACTION >> 4) ++ }, ++ [NL80211_IFTYPE_P2P_CLIENT] = { ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | ++ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) ++ }, ++ [NL80211_IFTYPE_P2P_GO] = { ++ .tx = 0xffff, ++ .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | ++ BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | ++ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ++ BIT(IEEE80211_STYPE_DISASSOC >> 4) | ++ BIT(IEEE80211_STYPE_AUTH >> 4) | ++ BIT(IEEE80211_STYPE_DEAUTH >> 4) | ++ BIT(IEEE80211_STYPE_ACTION >> 4) ++ } ++}; ++ ++static void swap_key_from_BE(struct wl_wsec_key *key) ++{ ++ key->index = htod32(key->index); ++ key->len = htod32(key->len); ++ key->algo = htod32(key->algo); ++ key->flags = htod32(key->flags); ++ key->rxiv.hi = htod32(key->rxiv.hi); ++ key->rxiv.lo = htod16(key->rxiv.lo); ++ key->iv_initialized = htod32(key->iv_initialized); ++} ++ ++static void swap_key_to_BE(struct wl_wsec_key *key) ++{ ++ key->index = dtoh32(key->index); ++ key->len = dtoh32(key->len); ++ key->algo = dtoh32(key->algo); ++ key->flags = dtoh32(key->flags); ++ key->rxiv.hi = dtoh32(key->rxiv.hi); ++ key->rxiv.lo = dtoh16(key->rxiv.lo); ++ key->iv_initialized = dtoh32(key->iv_initialized); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) ++/* For debug: Dump the contents of the encoded wps ie buffe */ ++static void ++wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc) ++{ ++ #define WPS_IE_FIXED_LEN 6 ++ u16 len; ++ u8 *subel = NULL; ++ u16 subelt_id; ++ u16 subelt_len; ++ u16 val; ++ u8 *valptr = (uint8*) &val; ++ if (wps_ie == NULL || wps_ie_len < WPS_IE_FIXED_LEN) { ++ AP6210_ERR("invalid argument : NULL\n")); ++ return; ++ } ++ len = (u16)wps_ie[TLV_LEN_OFF]; ++ ++ if (len > wps_ie_len) { ++ AP6210_ERR("invalid length len %d, wps ie len %d\n", len, wps_ie_len); ++ return; ++ } ++ AP6210_DEBUG("wps_ie len=%d\n", len); ++ len -= 4; /* for the WPS IE's OUI, oui_type fields */ ++ subel = wps_ie + WPS_IE_FIXED_LEN; ++ while (len >= 4) { /* must have attr id, attr len fields */ ++ valptr[0] = *subel++; ++ valptr[1] = *subel++; ++ subelt_id = HTON16(val); ++ ++ valptr[0] = *subel++; ++ valptr[1] = *subel++; ++ subelt_len = HTON16(val); ++ ++ len -= 4; /* for the attr id, attr len fields */ ++ len -= subelt_len; /* for the remaining fields in this attribute */ ++ AP6210_DEBUG(" subel=%p, subelt_id=0x%x subelt_len=%u\n", ++ subel, subelt_id, subelt_len); ++ ++ if (subelt_id == WPS_ID_VERSION) { ++ AP6210_DEBUG(" attr WPS_ID_VERSION: %u\n", *subel); ++ } else if (subelt_id == WPS_ID_REQ_TYPE) { ++ AP6210_DEBUG(" attr WPS_ID_REQ_TYPE: %u\n", *subel); ++ } else if (subelt_id == WPS_ID_CONFIG_METHODS) { ++ valptr[0] = *subel; ++ valptr[1] = *(subel + 1); ++ AP6210_DEBUG(" attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)); ++ } else if (subelt_id == WPS_ID_DEVICE_NAME) { ++ char devname[100]; ++ memcpy(devname, subel, subelt_len); ++ devname[subelt_len] = '\0'; ++ AP6210_DEBUG(" attr WPS_ID_DEVICE_NAME: %s (len %u)\n", ++ devname, subelt_len); ++ } else if (subelt_id == WPS_ID_DEVICE_PWD_ID) { ++ valptr[0] = *subel; ++ valptr[1] = *(subel + 1); ++ AP6210_DEBUG(" attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val)); ++ *pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false; ++ } else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) { ++ valptr[0] = *subel; ++ valptr[1] = *(subel + 1); ++ AP6210_DEBUG(" attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val)); ++ valptr[0] = *(subel + 6); ++ valptr[1] = *(subel + 7); ++ AP6210_DEBUG(" attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val)); ++ } else if (subelt_id == WPS_ID_REQ_DEV_TYPE) { ++ valptr[0] = *subel; ++ valptr[1] = *(subel + 1); ++ AP6210_DEBUG(" attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val)); ++ valptr[0] = *(subel + 6); ++ valptr[1] = *(subel + 7); ++ AP6210_DEBUG(" attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val)); ++ } else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) { ++ valptr[0] = *subel; ++ valptr[1] = *(subel + 1); ++ AP6210_DEBUG(" attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS" ++ ": cat=%u\n", HTON16(val)); ++ } else { ++ AP6210_DEBUG(" unknown attr 0x%x\n", subelt_id); ++ } ++ ++ subel += subelt_len; ++ } ++} ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */ ++ ++static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy) ++{ ++ chanspec_t chspec; ++ int err = 0; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct net_device *dev = wl_to_prmry_ndev(wl); ++ struct ether_addr bssid; ++ struct wl_bss_info *bss = NULL; ++ ++ if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) { ++ /* STA interface is not associated. So start the new interface on a temp ++ * channel . Later proper channel will be applied by the above framework ++ * via set_channel (cfg80211 API). ++ */ ++ AP6210_DEBUG("Not associated. Return a temp channel. \n"); ++ return wl_ch_host_to_driver(WL_P2P_TEMP_CHAN); ++ } ++ ++ ++ *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX); ++ if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, wl->extra_buf, ++ WL_EXTRA_BUF_MAX, false))) { ++ AP6210_ERR("Failed to get associated bss info, use temp channel \n"); ++ chspec = wl_ch_host_to_driver(WL_P2P_TEMP_CHAN); ++ } ++ else { ++ bss = (struct wl_bss_info *) (wl->extra_buf + 4); ++ chspec = bss->chanspec; ++ AP6210_DEBUG("Valid BSS Found. chanspec:%d \n", chspec); ++ } ++ return chspec; ++} ++ ++static struct net_device* wl_cfg80211_add_monitor_if(char *name) ++{ ++#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) ++ AP6210_DEBUG("wl_cfg80211_add_monitor_if: No more support monitor interface\n"); ++ return ERR_PTR(-EOPNOTSUPP); ++#else ++ struct net_device* ndev = NULL; ++ ++ dhd_add_monitor(name, &ndev); ++ AP6210_DEBUG("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev); ++ return ndev; ++#endif /* defined(WLP2P) && defined(WL_ENABLE_P2P_IF) */ ++} ++ ++static struct net_device * ++wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, ++ enum nl80211_iftype type, u32 *flags, ++ struct vif_params *params) ++{ ++ s32 err; ++ s32 timeout = -1; ++ s32 wlif_type = -1; ++ s32 mode = 0; ++ s32 val = 0; ++ s32 dhd_mode = 0; ++ chanspec_t chspec; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct net_device *_ndev; ++ struct ether_addr primary_mac; ++ int (*net_attach)(void *dhdp, int ifidx); ++ bool rollback_lock = false; ++#ifdef PROP_TXSTATUS_VSDB ++ s32 up = 1; ++ dhd_pub_t *dhd; ++#endif /* PROP_TXSTATUS_VSDB */ ++ ++ if (!wl) ++ return ERR_PTR(-EINVAL); ++ ++#ifdef PROP_TXSTATUS_VSDB ++ dhd = (dhd_pub_t *)(wl->pub); ++#endif /* PROP_TXSTATUS_VSDB */ ++ ++ ++ /* Use primary I/F for sending cmds down to firmware */ ++ _ndev = wl_to_prmry_ndev(wl); ++ ++ AP6210_DEBUG("if name: %s, type: %d\n", name, type); ++ switch (type) { ++ case NL80211_IFTYPE_ADHOC: ++ case NL80211_IFTYPE_AP_VLAN: ++ case NL80211_IFTYPE_WDS: ++ case NL80211_IFTYPE_MESH_POINT: ++ AP6210_ERR("Unsupported interface type\n"); ++ mode = WL_MODE_IBSS; ++ return NULL; ++ case NL80211_IFTYPE_MONITOR: ++ return wl_cfg80211_add_monitor_if(name); ++ case NL80211_IFTYPE_P2P_CLIENT: ++ case NL80211_IFTYPE_STATION: ++ wlif_type = WL_P2P_IF_CLIENT; ++ mode = WL_MODE_BSS; ++ break; ++ case NL80211_IFTYPE_P2P_GO: ++ case NL80211_IFTYPE_AP: ++ wlif_type = WL_P2P_IF_GO; ++ mode = WL_MODE_AP; ++ break; ++ default: ++ AP6210_ERR("Unsupported interface type\n"); ++ return NULL; ++ break; ++ } ++ ++ if (!name) { ++ AP6210_ERR("name is NULL\n"); ++ return NULL; ++ } ++ if (wl->p2p_supported && (wlif_type != -1)) { ++ if (wl_get_p2p_status(wl, IF_DELETING)) { ++ /* wait till IF_DEL is complete ++ * release the lock for the unregister to proceed ++ */ ++ if (rtnl_is_locked()) { ++ rtnl_unlock(); ++ rollback_lock = true; ++ } ++ AP6210_DEBUG("%s: Released the lock and wait till IF_DEL is complete\n", ++ __func__); ++ timeout = wait_event_interruptible_timeout(wl->netif_change_event, ++ (wl_get_p2p_status(wl, IF_DELETING) == false), ++ msecs_to_jiffies(MAX_WAIT_TIME)); ++ ++ /* put back the rtnl_lock again */ ++ if (rollback_lock) { ++ rtnl_lock(); ++ rollback_lock = false; ++ } ++ if (timeout > 0) { ++ AP6210_ERR("IF DEL is Success\n"); ++ ++ } else { ++ AP6210_ERR("timeount < 0, return -EAGAIN\n"); ++ return ERR_PTR(-EAGAIN); ++ } ++ /* It should be now be safe to put this check here since we are sure ++ * by now netdev_notifier (unregister) would have been called ++ */ ++ if (wl->iface_cnt == IFACE_MAX_CNT) ++ return ERR_PTR(-ENOMEM); ++ } ++ ++#ifdef PROP_TXSTATUS_VSDB ++ if (!dhd) ++ return ERR_PTR(-ENODEV); ++#endif /* PROP_TXSTATUS_VSDB */ ++ if (!wl->p2p) ++ return ERR_PTR(-ENODEV); ++ ++ if (wl->p2p && !wl->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) { ++ p2p_on(wl) = true; ++ wl_cfgp2p_set_firm_p2p(wl); ++ wl_cfgp2p_init_discovery(wl); ++ get_primary_mac(wl, &primary_mac); ++ wl_cfgp2p_generate_bss_mac(&primary_mac, ++ &wl->p2p->dev_addr, &wl->p2p->int_addr); ++ } ++ ++ memset(wl->p2p->vir_ifname, 0, IFNAMSIZ); ++ strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1); ++ ++ wl_notify_escan_complete(wl, _ndev, true, true); ++#ifdef PROP_TXSTATUS_VSDB ++ if (!wl->wlfc_on && !disable_proptx) { ++ dhd->wlfc_enabled = true; ++ dhd_wlfc_init(dhd); ++ err = wldev_ioctl(_ndev, WLC_UP, &up, sizeof(s32), true); ++ if (err < 0) ++ AP6210_ERR("WLC_UP return err:%d\n", err); ++ wl->wlfc_on = true; ++ } ++#endif /* PROP_TXSTATUS_VSDB */ ++ ++ /* In concurrency case, STA may be already associated in a particular channel. ++ * so retrieve the current channel of primary interface and then start the virtual ++ * interface on that. ++ */ ++ chspec = wl_cfg80211_get_shared_freq(wiphy); ++ ++ /* For P2P mode, use P2P-specific driver features to create the ++ * bss: "wl p2p_ifadd" ++ */ ++ wl_set_p2p_status(wl, IF_ADD); ++ if (wlif_type == WL_P2P_IF_GO) ++ wldev_iovar_setint(_ndev, "mpc", 0); ++ err = wl_cfgp2p_ifadd(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec); ++ ++ if (unlikely(err)) { ++ AP6210_ERR(" virtual iface add failed (%d) \n", err); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ timeout = wait_event_interruptible_timeout(wl->netif_change_event, ++ (wl_get_p2p_status(wl, IF_ADD) == false), ++ msecs_to_jiffies(MAX_WAIT_TIME)); ++ if (timeout > 0 && (!wl_get_p2p_status(wl, IF_ADD))) { ++ ++ struct wireless_dev *vwdev; ++ vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL); ++ if (unlikely(!vwdev)) { ++ AP6210_ERR("Could not allocate wireless device\n"); ++ return ERR_PTR(-ENOMEM); ++ } ++ vwdev->wiphy = wl->wdev->wiphy; ++ AP6210_DEBUG(" virtual interface(%s) is created memalloc done \n", ++ wl->p2p->vir_ifname); ++ vwdev->iftype = type; ++ _ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); ++ _ndev->ieee80211_ptr = vwdev; ++ SET_NETDEV_DEV(_ndev, wiphy_dev(vwdev->wiphy)); ++ vwdev->netdev = _ndev; ++ wl_set_drv_status(wl, READY, _ndev); ++ wl->p2p->vif_created = true; ++ wl_set_mode_by_netdev(wl, _ndev, mode); ++ net_attach = wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION); ++ if (rtnl_is_locked()) { ++ rtnl_unlock(); ++ rollback_lock = true; ++ } ++ if (net_attach && !net_attach(wl->pub, _ndev->ifindex)) { ++ wl_alloc_netinfo(wl, _ndev, vwdev, mode, PM_ENABLE); ++ val = 1; ++ /* Disable firmware roaming for P2P interface */ ++ wldev_iovar_setint(_ndev, "roam_off", val); ++ AP6210_ERR(" virtual interface(%s) is " ++ "created net attach done\n", wl->p2p->vir_ifname); ++ if (mode == WL_MODE_AP) ++ wl_set_drv_status(wl, CONNECTED, _ndev); ++ if (type == NL80211_IFTYPE_P2P_CLIENT) ++ dhd_mode = DHD_FLAG_P2P_GC_MODE; ++ else if (type == NL80211_IFTYPE_P2P_GO) ++ dhd_mode = DHD_FLAG_P2P_GO_MODE; ++ DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode)); ++ } else { ++ /* put back the rtnl_lock again */ ++ if (rollback_lock) ++ rtnl_lock(); ++ goto fail; ++ } ++ /* put back the rtnl_lock again */ ++ if (rollback_lock) ++ rtnl_lock(); ++ return _ndev; ++ ++ } else { ++ wl_clr_p2p_status(wl, IF_ADD); ++ AP6210_ERR(" virtual interface(%s) is not created \n", wl->p2p->vir_ifname); ++ memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ); ++ wl->p2p->vif_created = false; ++#ifdef PROP_TXSTATUS_VSDB ++ if (dhd->wlfc_enabled && wl->wlfc_on) { ++ dhd->wlfc_enabled = false; ++ dhd_wlfc_deinit(dhd); ++ wl->wlfc_on = false; ++ } ++#endif /* PROP_TXSTATUS_VSDB */ ++ } ++ } ++fail: ++ if (wlif_type == WL_P2P_IF_GO) ++ wldev_iovar_setint(_ndev, "mpc", 1); ++ return ERR_PTR(-ENODEV); ++} ++ ++static s32 ++wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) ++{ ++ struct ether_addr p2p_mac; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ s32 timeout = -1; ++ s32 ret = 0; ++ AP6210_DEBUG("Enter\n"); ++ ++ if (wl->p2p_net == dev) { ++ /* Since there is no ifidx corresponding to p2p0, cmds to ++ * firmware should be routed through primary I/F ++ */ ++ dev = wl_to_prmry_ndev(wl); ++ } ++ ++ if (wl->p2p_supported) { ++ memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN); ++ ++ /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases ++ */ ++ AP6210_DEBUG("P2P: GO_NEG_PHASE status cleared "); ++ wl_clr_p2p_status(wl, GO_NEG_PHASE); ++ if (wl->p2p->vif_created) { ++ if (wl_get_drv_status(wl, SCANNING, dev)) { ++ wl_notify_escan_complete(wl, dev, true, true); ++ } ++ wldev_iovar_setint(dev, "mpc", 1); ++ ++ /* for GC */ ++ if (wl_get_drv_status(wl, DISCONNECTING, dev) && ++ (wl_get_mode_by_netdev(wl, dev) != WL_MODE_AP)) { ++ AP6210_ERR("Wait for Link Down event for GC !\n"); ++ wait_for_completion_timeout ++ (&wl->iface_disable, msecs_to_jiffies(500)); ++ } ++ wl_set_p2p_status(wl, IF_DELETING); ++ DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (wl)); ++ ++ /* for GO */ ++ if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) { ++ wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false); ++ /* disable interface before bsscfg free */ ++ ret = wl_cfgp2p_ifdisable(wl, &p2p_mac); ++ /* if fw doesn't support "ifdis", ++ do not wait for link down of ap mode ++ */ ++ if (ret == 0) { ++ AP6210_ERR("Wait for Link Down event for GO !!!\n"); ++ wait_for_completion_timeout(&wl->iface_disable, ++ msecs_to_jiffies(500)); ++ } else { ++ msleep(300); ++ } ++ } ++ wl_cfgp2p_clear_management_ie(wl, wl_cfgp2p_find_idx(wl, dev)); ++ /* delete interface after link down */ ++ ret = wl_cfgp2p_ifdel(wl, &p2p_mac); ++ /* Firmware could not delete the interface so we will not get WLC_E_IF ++ * event for cleaning the dhd virtual nw interace ++ * So lets do it here. Failures from fw will ensure the application to do ++ * ifconfig down and up sequnce, which will reload the fw ++ * however we should cleanup the linux network virtual interfaces ++ */ ++ /* Request framework to RESET and clean up */ ++ if (ret) { ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++ AP6210_ERR("Firmware returned an error (%d) from p2p_ifdel" ++ "HANG Notification sent to %s\n", ret, ndev->name); ++ net_os_send_hang_message(ndev); ++ } ++ /* Wait for IF_DEL operation to be finished in firmware */ ++ timeout = wait_event_interruptible_timeout(wl->netif_change_event, ++ (wl->p2p->vif_created == false), ++ msecs_to_jiffies(MAX_WAIT_TIME)); ++ if (timeout > 0 && (wl->p2p->vif_created == false)) { ++ AP6210_DEBUG("IFDEL operation done\n"); ++ } else { ++ AP6210_ERR("IFDEL didn't complete properly\n"); ++ } ++ ret = dhd_del_monitor(dev); ++ } ++ } ++ return ret; ++} ++ ++static s32 ++wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, ++ enum nl80211_iftype type, u32 *flags, ++ struct vif_params *params) ++{ ++ s32 ap = 0; ++ s32 infra = 0; ++ s32 wlif_type; ++ s32 mode = 0; ++ chanspec_t chspec; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); ++ AP6210_DEBUG("Enter type %d\n", type); ++ switch (type) { ++ case NL80211_IFTYPE_MONITOR: ++ case NL80211_IFTYPE_WDS: ++ case NL80211_IFTYPE_MESH_POINT: ++ ap = 1; ++ AP6210_ERR("type (%d) : currently we do not support this type\n", ++ type); ++ break; ++ case NL80211_IFTYPE_ADHOC: ++ mode = WL_MODE_IBSS; ++ break; ++ case NL80211_IFTYPE_STATION: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ mode = WL_MODE_BSS; ++ infra = 1; ++ break; ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_AP_VLAN: ++ case NL80211_IFTYPE_P2P_GO: ++ mode = WL_MODE_AP; ++ ap = 1; ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (!dhd) ++ return -EINVAL; ++ if (ap) { ++ wl_set_mode_by_netdev(wl, ndev, mode); ++ if (wl->p2p_supported && wl->p2p->vif_created) { ++ AP6210_DEBUG("p2p_vif_created (%d) p2p_on (%d)\n", wl->p2p->vif_created, ++ p2p_on(wl)); ++ wldev_iovar_setint(ndev, "mpc", 0); ++ wl_notify_escan_complete(wl, ndev, true, true); ++ ++ /* In concurrency case, STA may be already associated in a particular ++ * channel. so retrieve the current channel of primary interface and ++ * then start the virtual interface on that. ++ */ ++ chspec = wl_cfg80211_get_shared_freq(wiphy); ++ ++ wlif_type = WL_P2P_IF_GO; ++ AP6210_ERR("%s : ap (%d), infra (%d), iftype: (%d)\n", ++ ndev->name, ap, infra, type); ++ wl_set_p2p_status(wl, IF_CHANGING); ++ wl_clr_p2p_status(wl, IF_CHANGED); ++ wl_cfgp2p_ifchange(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec); ++ wait_event_interruptible_timeout(wl->netif_change_event, ++ (wl_get_p2p_status(wl, IF_CHANGED) == true), ++ msecs_to_jiffies(MAX_WAIT_TIME)); ++ wl_set_mode_by_netdev(wl, ndev, mode); ++ dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE; ++ dhd->op_mode |= DHD_FLAG_P2P_GO_MODE; ++ wl_clr_p2p_status(wl, IF_CHANGING); ++ wl_clr_p2p_status(wl, IF_CHANGED); ++ if (mode == WL_MODE_AP) ++ wl_set_drv_status(wl, CONNECTED, ndev); ++ } else if (ndev == wl_to_prmry_ndev(wl) && ++ !wl_get_drv_status(wl, AP_CREATED, ndev)) { ++ wl_set_drv_status(wl, AP_CREATING, ndev); ++ if (!wl->ap_info && ++ !(wl->ap_info = kzalloc(sizeof(struct ap_info), GFP_KERNEL))) { ++ AP6210_ERR("struct ap_saved_ie allocation failed\n"); ++ return -ENOMEM; ++ } ++ } else { ++ AP6210_ERR("Cannot change the interface for GO or SOFTAP\n"); ++ return -EINVAL; ++ } ++ } else { ++ AP6210_DEBUG("Change_virtual_iface for transition from GO/AP to client/STA"); ++ } ++ ++ ndev->ieee80211_ptr->iftype = type; ++ return 0; ++} ++ ++s32 ++wl_cfg80211_notify_ifadd(struct net_device *ndev, s32 idx, s32 bssidx, ++ void* _net_attach) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ s32 ret = BCME_OK; ++ AP6210_DEBUG("Enter"); ++ if (!ndev) { ++ AP6210_ERR("net is NULL\n"); ++ return 0; ++ } ++ if (wl->p2p_supported && wl_get_p2p_status(wl, IF_ADD)) { ++ AP6210_DEBUG("IF_ADD event called from dongle, old interface name: %s," ++ "new name: %s\n", ndev->name, wl->p2p->vir_ifname); ++ /* Assign the net device to CONNECT BSSCFG */ ++ strncpy(ndev->name, wl->p2p->vir_ifname, IFNAMSIZ - 1); ++ wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = ndev; ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = bssidx; ++ wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION) = _net_attach; ++ ndev->ifindex = idx; ++ wl_clr_p2p_status(wl, IF_ADD); ++ ++ wake_up_interruptible(&wl->netif_change_event); ++ } else { ++ ret = BCME_NOTREADY; ++ } ++ return ret; ++} ++ ++s32 ++wl_cfg80211_notify_ifdel(void) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ ++ AP6210_DEBUG("Enter \n"); ++ wl_clr_p2p_status(wl, IF_DELETING); ++ wake_up_interruptible(&wl->netif_change_event); ++ return 0; ++} ++ ++s32 ++wl_cfg80211_ifdel_ops(struct net_device *ndev) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ bool rollback_lock = false; ++ s32 index = 0; ++#ifdef PROP_TXSTATUS_VSDB ++ dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); ++#endif /* PROP_TXSTATUS_VSDB */ ++ if (!ndev || (strlen(ndev->name) == 0)) { ++ AP6210_ERR("net is NULL\n"); ++ return 0; ++ } ++ ++ if (p2p_is_on(wl) && wl->p2p->vif_created && ++ wl_get_p2p_status(wl, IF_DELETING)) { ++ if (wl->scan_request && ++ (wl->escan_info.ndev == ndev)) { ++ /* Abort any pending scan requests */ ++ wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; ++ if (!rtnl_is_locked()) { ++ rtnl_lock(); ++ rollback_lock = true; ++ } ++ AP6210_DEBUG("ESCAN COMPLETED\n"); ++ wl_notify_escan_complete(wl, ndev, true, false); ++ if (rollback_lock) ++ rtnl_unlock(); ++ } ++ AP6210_ERR("IF_DEL event called from dongle, net %x, vif name: %s\n", ++ (unsigned int)ndev, wl->p2p->vir_ifname); ++ ++ memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ); ++ index = wl_cfgp2p_find_idx(wl, ndev); ++ wl_to_p2p_bss_ndev(wl, index) = NULL; ++ wl_to_p2p_bss_bssidx(wl, index) = WL_INVALID; ++ wl->p2p->vif_created = false; ++ ++ AP6210_DEBUG("index : %d\n", index); ++#ifdef PROP_TXSTATUS_VSDB ++ if (dhd->wlfc_enabled && wl->wlfc_on) { ++ dhd->wlfc_enabled = false; ++ dhd_wlfc_deinit(dhd); ++ wl->wlfc_on = false; ++ } ++#endif /* PROP_TXSTATUS_VSDB */ ++ wl_clr_drv_status(wl, CONNECTED, ndev); ++ } ++ /* Wake up any waiting thread */ ++ wake_up_interruptible(&wl->netif_change_event); ++ ++ return 0; ++} ++ ++s32 ++wl_cfg80211_is_progress_ifadd(void) ++{ ++ s32 is_progress = 0; ++ struct wl_priv *wl = wlcfg_drv_priv; ++ if (wl_get_p2p_status(wl, IF_ADD)) ++ is_progress = 1; ++ return is_progress; ++} ++ ++s32 ++wl_cfg80211_is_progress_ifchange(void) ++{ ++ s32 is_progress = 0; ++ struct wl_priv *wl = wlcfg_drv_priv; ++ if (wl_get_p2p_status(wl, IF_CHANGING)) ++ is_progress = 1; ++ return is_progress; ++} ++ ++ ++s32 ++wl_cfg80211_notify_ifchange(void) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ if (wl_get_p2p_status(wl, IF_CHANGING)) { ++ wl_set_p2p_status(wl, IF_CHANGED); ++ wake_up_interruptible(&wl->netif_change_event); ++ } ++ return 0; ++} ++ ++/* Find listen channel */ ++static s32 wl_find_listen_channel(struct wl_priv *wl, ++ u8 *ie, u32 ie_len) ++{ ++ wifi_p2p_ie_t *p2p_ie; ++ u8 *end, *pos; ++ s32 listen_channel; ++ ++ p2p_ie = wl_cfgp2p_find_p2pie(ie, ie_len); ++ ++ if (p2p_ie == NULL) ++ return 0; ++ ++ pos = p2p_ie->subelts; ++ end = p2p_ie->subelts + (p2p_ie->len - 4); ++ ++ AP6210_DEBUG(" found p2p ie ! lenth %d \n", ++ p2p_ie->len); ++ ++ while (pos < end) { ++ uint16 attr_len; ++ if (pos + 2 >= end) { ++ AP6210_DEBUG(" -- Invalid P2P attribute"); ++ return 0; ++ } ++ attr_len = ((uint16) (((pos + 1)[1] << 8) | (pos + 1)[0])); ++ ++ if (pos + 3 + attr_len > end) { ++ AP6210_DEBUG("P2P: Attribute underflow " ++ "(len=%u left=%d)", ++ attr_len, (int) (end - pos - 3)); ++ return 0; ++ } ++ ++ /* if Listen Channel att id is 6 and the vailue is valid, ++ * return the listen channel ++ */ ++ if (pos[0] == 6) { ++ /* listen channel subel length format ++ * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num) ++ */ ++ listen_channel = pos[1 + 2 + 3 + 1]; ++ ++ if (listen_channel == SOCIAL_CHAN_1 || ++ listen_channel == SOCIAL_CHAN_2 || ++ listen_channel == SOCIAL_CHAN_3) { ++ AP6210_DEBUG(" Found my Listen Channel %d \n", listen_channel); ++ return listen_channel; ++ } ++ } ++ pos += 3 + attr_len; ++ } ++ return 0; ++} ++ ++static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_request *request) ++{ ++ u32 n_ssids; ++ u32 n_channels; ++ u16 channel; ++ chanspec_t chanspec; ++ s32 i = 0, j = 0, offset; ++ char *ptr; ++ wlc_ssid_t ssid; ++ struct wl_priv *wl = wlcfg_drv_priv; ++ ++ memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN); ++ params->bss_type = DOT11_BSSTYPE_ANY; ++ params->scan_type = 0; ++ params->nprobes = -1; ++ params->active_time = -1; ++ params->passive_time = -1; ++ params->home_time = -1; ++ params->channel_num = 0; ++ memset(¶ms->ssid, 0, sizeof(wlc_ssid_t)); ++ ++ AP6210_DEBUG("Preparing Scan request\n"); ++ AP6210_DEBUG("nprobes=%d\n", params->nprobes); ++ AP6210_DEBUG("active_time=%d\n", params->active_time); ++ AP6210_DEBUG("passive_time=%d\n", params->passive_time); ++ AP6210_DEBUG("home_time=%d\n", params->home_time); ++ AP6210_DEBUG("scan_type=%d\n", params->scan_type); ++ ++ params->nprobes = htod32(params->nprobes); ++ params->active_time = htod32(params->active_time); ++ params->passive_time = htod32(params->passive_time); ++ params->home_time = htod32(params->home_time); ++ ++ /* if request is null just exit so it will be all channel broadcast scan */ ++ if (!request) ++ return; ++ ++ n_ssids = request->n_ssids; ++ n_channels = request->n_channels; ++ ++ /* Copy channel array if applicable */ ++ AP6210_DEBUG("### List of channelspecs to scan ###\n"); ++ if (n_channels > 0) { ++ for (i = 0; i < n_channels; i++) { ++ chanspec = 0; ++ channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq); ++ /* SKIP DFS channels for Secondary interface */ ++ if ((wl->escan_info.ndev != wl_to_prmry_ndev(wl)) && ++ (request->channels[i]->flags & ++ (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN))) ++ continue; ++ ++ if (request->channels[i]->band == IEEE80211_BAND_2GHZ) { ++#ifdef WL_HOST_BAND_MGMT ++ if (wl->curr_band == WLC_BAND_5G) { ++ AP6210_DEBUG("In 5G only mode, omit 2G channel:%d\n", channel); ++ continue; ++ } ++#endif /* WL_HOST_BAND_MGMT */ ++ chanspec |= WL_CHANSPEC_BAND_2G; ++ } else { ++#ifdef WL_HOST_BAND_MGMT ++ if (wl->curr_band == WLC_BAND_2G) { ++ AP6210_DEBUG("In 2G only mode, omit 5G channel:%d\n", channel); ++ continue; ++ } ++#endif /* WL_HOST_BAND_MGMT */ ++ chanspec |= WL_CHANSPEC_BAND_5G; ++ } ++ ++ chanspec |= WL_CHANSPEC_BW_20; ++ chanspec |= WL_CHANSPEC_CTL_SB_NONE; ++ ++ params->channel_list[j] = channel; ++ params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK; ++ params->channel_list[j] |= chanspec; ++ AP6210_DEBUG("Chan : %d, Channel spec: %x \n", ++ channel, params->channel_list[j]); ++ params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]); ++ j++; ++ } ++ } else { ++ AP6210_DEBUG("Scanning all channels\n"); ++ } ++ n_channels = j; ++ /* Copy ssid array if applicable */ ++ AP6210_DEBUG("### List of SSIDs to scan ###\n"); ++ if (n_ssids > 0) { ++ offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16); ++ offset = roundup(offset, sizeof(u32)); ++ ptr = (char*)params + offset; ++ for (i = 0; i < n_ssids; i++) { ++ memset(&ssid, 0, sizeof(wlc_ssid_t)); ++ ssid.SSID_len = request->ssids[i].ssid_len; ++ memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len); ++ if (!ssid.SSID_len) ++ AP6210_DEBUG("%d: Broadcast scan\n", i); ++ else ++ AP6210_DEBUG("%d: scan for %s size =%d\n", i, ++ ssid.SSID, ssid.SSID_len); ++ memcpy(ptr, &ssid, sizeof(wlc_ssid_t)); ++ ptr += sizeof(wlc_ssid_t); ++ } ++ } else { ++ AP6210_DEBUG("Broadcast scan\n"); ++ } ++ /* Adding mask to channel numbers */ ++ params->channel_num = ++ htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) | ++ (n_channels & WL_SCAN_PARAMS_COUNT_MASK)); ++ ++ if (n_channels == 1 && wl_get_drv_status_all(wl, CONNECTED)) { ++ params->active_time = WL_SCAN_CONNECT_DWELL_TIME_MS; ++ } ++} ++ ++static s32 ++wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request, u16 action) ++{ ++ u32 n_channels; ++ u32 n_ssids; ++ s32 params_size = ++ (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params)); ++ struct wl_iscan_params *params = NULL; ++ s32 err = 0; ++ ++ if (request != NULL) { ++ n_channels = request->n_channels; ++ n_ssids = request->n_ssids; ++ /* Allocate space for populating ssids in wl_iscan_params struct */ ++ if (n_channels % 2) ++ /* If n_channels is odd, add a padd of u16 */ ++ params_size += sizeof(u16) * (n_channels + 1); ++ else ++ params_size += sizeof(u16) * n_channels; ++ ++ /* Allocate space for populating ssids in wl_iscan_params struct */ ++ params_size += sizeof(struct wlc_ssid) * n_ssids; ++ } ++ params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL); ++ if (!params) { ++ err = -ENOMEM; ++ goto done; ++ } ++ wl_scan_prep(¶ms->params, request); ++ ++ params->version = htod32(ISCAN_REQ_VERSION); ++ params->action = htod16(action); ++ params->scan_duration = htod16(0); ++ ++ if (params_size + sizeof("iscan") >= WLC_IOCTL_MEDLEN) { ++ AP6210_ERR("ioctl buffer length is not sufficient\n"); ++ err = -ENOMEM; ++ goto done; ++ } ++ err = wldev_iovar_setbuf(iscan->dev, "iscan", params, params_size, ++ iscan->ioctl_buf, WLC_IOCTL_MEDLEN, NULL); ++ if (unlikely(err)) { ++ if (err == -EBUSY) { ++ AP6210_ERR("system busy : iscan canceled\n"); ++ } else { ++ AP6210_ERR("error (%d)\n", err); ++ } ++ } ++ ++done: ++ if (params) ++ kfree(params); ++ return err; ++} ++ ++static s32 wl_do_iscan(struct wl_priv *wl, struct cfg80211_scan_request *request) ++{ ++ struct wl_iscan_ctrl *iscan = wl_to_iscan(wl); ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++ s32 passive_scan; ++ s32 err = 0; ++ ++ iscan->state = WL_ISCAN_STATE_SCANING; ++ ++ passive_scan = wl->active_scan ? 0 : 1; ++ err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, ++ &passive_scan, sizeof(passive_scan), true); ++ if (unlikely(err)) { ++ AP6210_DEBUG("error (%d)\n", err); ++ return err; ++ } ++ wl->iscan_kickstart = true; ++ wl_run_iscan(iscan, request, WL_SCAN_ACTION_START); ++ mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms)); ++ iscan->timer_on = 1; ++ ++ return err; ++} ++ ++static s32 ++wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size) ++{ ++ wl_uint32_list_t *list; ++ s32 err = BCME_OK; ++ if (valid_chan_list == NULL || size <= 0) ++ return -ENOMEM; ++ ++ memset(valid_chan_list, 0, size); ++ list = (wl_uint32_list_t *)(void *) valid_chan_list; ++ list->count = htod32(WL_NUMCHANNELS); ++ err = wldev_ioctl(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size, false); ++ if (err != 0) { ++ AP6210_ERR("get channels failed with %d\n", err); ++ } ++ ++ return err; ++} ++ ++static s32 ++wl_run_escan(struct wl_priv *wl, struct net_device *ndev, ++ struct cfg80211_scan_request *request, uint16 action) ++{ ++ s32 err = BCME_OK; ++ u32 n_channels; ++ u32 n_ssids; ++ s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params)); ++ wl_escan_params_t *params = NULL; ++ u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)]; ++ u32 num_chans = 0; ++ s32 channel; ++ s32 n_valid_chan; ++ s32 search_state = WL_P2P_DISC_ST_SCAN; ++ u32 i, j, n_nodfs = 0; ++ u16 *default_chan_list = NULL; ++ wl_uint32_list_t *list; ++ struct net_device *dev = NULL; ++ ++ AP6210_DEBUG("Enter \n"); ++ ++ if (!wl) { ++ err = -EINVAL; ++ goto exit; ++ } ++ if (!wl->p2p_supported || !p2p_scan(wl)) { ++ /* LEGACY SCAN TRIGGER */ ++ AP6210_DEBUG(" LEGACY E-SCAN START\n"); ++ ++ /* if scan request is not empty parse scan request paramters */ ++ if (request != NULL) { ++ n_channels = request->n_channels; ++ n_ssids = request->n_ssids; ++ /* Allocate space for populating ssids in wl_iscan_params struct */ ++ if (n_channels % 2) ++ /* If n_channels is odd, add a padd of u16 */ ++ params_size += sizeof(u16) * (n_channels + 1); ++ else ++ params_size += sizeof(u16) * n_channels; ++ ++ /* Allocate space for populating ssids in wl_iscan_params struct */ ++ params_size += sizeof(struct wlc_ssid) * n_ssids; ++ } ++ params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL); ++ if (params == NULL) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ ++ wl_scan_prep(¶ms->params, request); ++ ++ params->version = htod32(ESCAN_REQ_VERSION); ++ params->action = htod16(action); ++ params->sync_id = htod16(0x1234); ++ if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) { ++ AP6210_ERR("ioctl buffer length not sufficient\n"); ++ kfree(params); ++ err = -ENOMEM; ++ goto exit; ++ } ++ err = wldev_iovar_setbuf(ndev, "escan", params, params_size, ++ wl->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL); ++ if (unlikely(err)) { ++ if (err == BCME_EPERM) ++ /* Scan Not permitted at this point of time */ ++ AP6210_DEBUG(" Escan not permitted at this time (%d)\n", err); ++ else ++ AP6210_ERR(" Escan set error (%d)\n", err); ++ } ++ kfree(params); ++ } ++ else if (p2p_is_on(wl) && p2p_scan(wl)) { ++ /* P2P SCAN TRIGGER */ ++ s32 _freq = 0; ++ n_nodfs = 0; ++ if (request && request->n_channels) { ++ num_chans = request->n_channels; ++ AP6210_DEBUG(" chann number : %d\n", num_chans); ++ default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list), ++ GFP_KERNEL); ++ if (default_chan_list == NULL) { ++ AP6210_ERR("channel list allocation failed \n"); ++ err = -ENOMEM; ++ goto exit; ++ } ++ if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) { ++ list = (wl_uint32_list_t *) chan_buf; ++ n_valid_chan = dtoh32(list->count); ++ for (i = 0; i < num_chans; i++) ++ { ++#ifdef WL_HOST_BAND_MGMT ++ int channel_band = 0; ++#endif /* WL_HOST_BAND_MGMT */ ++ _freq = request->channels[i]->center_freq; ++ channel = ieee80211_frequency_to_channel(_freq); ++#ifdef WL_HOST_BAND_MGMT ++ channel_band = (channel > CH_MAX_2G_CHANNEL) ? ++ WLC_BAND_5G : WLC_BAND_2G; ++ if ((wl->curr_band != WLC_BAND_AUTO) && ++ (wl->curr_band != channel_band) && ++ !IS_P2P_SOCIAL_CHANNEL(channel)) ++ continue; ++#endif /* WL_HOST_BAND_MGMT */ ++ ++ /* ignore DFS channels */ ++ if (request->channels[i]->flags & ++ (IEEE80211_CHAN_RADAR ++ | IEEE80211_CHAN_PASSIVE_SCAN)) ++ continue; ++ ++ for (j = 0; j < n_valid_chan; j++) { ++ /* allows only supported channel on ++ * current reguatory ++ */ ++ if (channel == (dtoh32(list->element[j]))) ++ default_chan_list[n_nodfs++] = ++ channel; ++ } ++ ++ } ++ } ++ if (num_chans == 3 && ( ++ (default_chan_list[0] == SOCIAL_CHAN_1) && ++ (default_chan_list[1] == SOCIAL_CHAN_2) && ++ (default_chan_list[2] == SOCIAL_CHAN_3))) { ++ /* SOCIAL CHANNELS 1, 6, 11 */ ++ search_state = WL_P2P_DISC_ST_SEARCH; ++ AP6210_DEBUG("P2P SEARCH PHASE START \n"); ++ } else if ((dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION)) && ++ (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP)) { ++ /* If you are already a GO, then do SEARCH only */ ++ AP6210_DEBUG("Already a GO. Do SEARCH Only"); ++ search_state = WL_P2P_DISC_ST_SEARCH; ++ num_chans = n_nodfs; ++ ++ } else { ++ AP6210_DEBUG("P2P SCAN STATE START \n"); ++ num_chans = n_nodfs; ++ } ++ ++ } ++ err = wl_cfgp2p_escan(wl, ndev, wl->active_scan, num_chans, default_chan_list, ++ search_state, action, ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); ++ kfree(default_chan_list); ++ } ++exit: ++ if (unlikely(err)) { ++ /* Don't print Error incase of Scan suppress */ ++ if ((err == BCME_EPERM) && wl->scan_suppressed) ++ AP6210_DEBUG("Escan failed: Scan Suppressed \n"); ++ else ++ AP6210_ERR("error (%d)\n", err); ++ } ++ return err; ++} ++ ++ ++static s32 ++wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_scan_request *request) ++{ ++ s32 err = BCME_OK; ++ s32 passive_scan; ++ wl_scan_results_t *results; ++ AP6210_DEBUG("Enter \n"); ++ mutex_lock(&wl->usr_sync); ++ results = (wl_scan_results_t *) wl->escan_info.escan_buf; ++ results->version = 0; ++ results->count = 0; ++ results->buflen = WL_SCAN_RESULTS_FIXED_SIZE; ++ ++ wl->escan_info.ndev = ndev; ++ wl->escan_info.wiphy = wiphy; ++ wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING; ++ passive_scan = wl->active_scan ? 0 : 1; ++ err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, ++ &passive_scan, sizeof(passive_scan), true); ++ if (unlikely(err)) { ++ AP6210_ERR("error (%d)\n", err); ++ goto exit; ++ } ++ ++ err = wl_run_escan(wl, ndev, request, WL_SCAN_ACTION_START); ++exit: ++ mutex_unlock(&wl->usr_sync); ++ return err; ++} ++ ++static s32 ++__wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_scan_request *request, ++ struct cfg80211_ssid *this_ssid) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct cfg80211_ssid *ssids; ++ struct wl_scan_req *sr = wl_to_sr(wl); ++ struct ether_addr primary_mac; ++ s32 passive_scan; ++ bool iscan_req; ++ bool escan_req = false; ++ bool p2p_ssid; ++#ifdef WL11U ++ bcm_tlv_t *interworking_ie; ++ u32 ie_len; ++#endif ++ s32 err = 0; ++ s32 bssidx = -1; ++ s32 i; ++ ++ unsigned long flags; ++ static s32 busy_count = 0; ++ ++ /* If scan req comes for p2p0, send it over primary I/F ++ * Scan results will be delivered corresponding to cfg80211_scan_request ++ */ ++ if (ndev == wl->p2p_net) { ++ ndev = wl_to_prmry_ndev(wl); ++ } ++ ++ if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl)) { ++ AP6210_ERR("Sending Action Frames. Try it again.\n"); ++ return -EAGAIN; ++ } ++ ++ AP6210_DEBUG("Enter wiphy (%p)\n", wiphy); ++ if (wl_get_drv_status_all(wl, SCANNING)) { ++ if (wl->scan_request == NULL) { ++ wl_clr_drv_status_all(wl, SCANNING); ++ AP6210_DEBUG("<<<<<<<<<<>>>>>>>>>>\n"); ++ } else { ++ AP6210_ERR("Scanning already\n"); ++ return -EAGAIN; ++ } ++ } ++ if (wl_get_drv_status(wl, SCAN_ABORTING, ndev)) { ++ AP6210_ERR("Scanning being aborted\n"); ++ return -EAGAIN; ++ } ++ if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) { ++ AP6210_ERR("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"); ++ return -EOPNOTSUPP; ++ } ++#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST ++ if (wl_get_drv_status_all(wl, REMAINING_ON_CHANNEL)) { ++ AP6210_DEBUG("Remain_on_channel bit is set, somehow it didn't get cleared\n"); ++ wl_notify_escan_complete(wl, ndev, true, true); ++ } ++#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ ++ ++ /* Arm scan timeout timer */ ++ mod_timer(&wl->scan_timeout, jiffies + msecs_to_jiffies(WL_SCAN_TIMER_INTERVAL_MS)); ++ iscan_req = false; ++ if (request) { /* scan bss */ ++ ssids = request->ssids; ++ if (wl->iscan_on && (!ssids || !ssids->ssid_len || request->n_ssids != 1)) { ++ iscan_req = true; ++ } else if (wl->escan_on) { ++ escan_req = true; ++ p2p_ssid = false; ++ for (i = 0; i < request->n_ssids; i++) { ++ if (ssids[i].ssid_len && ++ IS_P2P_SSID(ssids[i].ssid, ssids[i].ssid_len)) { ++ p2p_ssid = true; ++ break; ++ } ++ } ++ if (p2p_ssid) { ++ if (wl->p2p_supported) { ++ /* p2p scan trigger */ ++ if (p2p_on(wl) == false) { ++ /* p2p on at the first time */ ++ p2p_on(wl) = true; ++ wl_cfgp2p_set_firm_p2p(wl); ++ get_primary_mac(wl, &primary_mac); ++ wl_cfgp2p_generate_bss_mac(&primary_mac, ++ &wl->p2p->dev_addr, &wl->p2p->int_addr); ++ } ++ wl_clr_p2p_status(wl, GO_NEG_PHASE); ++ AP6210_DEBUG("P2P: GO_NEG_PHASE status cleared \n"); ++ p2p_scan(wl) = true; ++ } ++ } else { ++ /* legacy scan trigger ++ * So, we have to disable p2p discovery if p2p discovery is on ++ */ ++ if (wl->p2p_supported) { ++ p2p_scan(wl) = false; ++ /* If Netdevice is not equals to primary and p2p is on ++ * , we will do p2p scan using P2PAPI_BSSCFG_DEVICE. ++ */ ++ ++ if (p2p_scan(wl) == false) { ++ if (wl_get_p2p_status(wl, DISCOVERY_ON)) { ++ err = wl_cfgp2p_discover_enable_search(wl, ++ false); ++ if (unlikely(err)) { ++ goto scan_out; ++ } ++ ++ } ++ } ++ } ++ if (!wl->p2p_supported || !p2p_scan(wl)) { ++ bssidx = wl_cfgp2p_find_idx(wl, ndev); ++ ++#ifdef WL11U ++ if ((interworking_ie = wl_cfg80211_find_interworking_ie( ++ (u8 *)request->ie, request->ie_len)) != NULL) { ++ ie_len = interworking_ie->len; ++ ++ err = wl_cfg80211_add_iw_ie(wl, ndev, bssidx, ++ VNDR_IE_CUSTOM_FLAG, interworking_ie->id, ++ interworking_ie->data, interworking_ie->len); ++ ++ if (unlikely(err)) { ++ goto scan_out; ++ } ++ } else if (wl->iw_ie_len != 0) { ++ /* we have to clear IW IE and disable gratuitous APR */ ++ wl_cfg80211_add_iw_ie(wl, ndev, bssidx, ++ VNDR_IE_CUSTOM_FLAG, ++ DOT11_MNG_INTERWORKING_ID, ++ 0, 0); ++ ++ wldev_iovar_setint_bsscfg(ndev, "grat_arp", 0, ++ bssidx); ++ /* we don't care about error */ ++ } ++#endif /* WL11U */ ++ err = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, ++ VNDR_IE_PRBREQ_FLAG, (u8 *)request->ie, ++ request->ie_len); ++ ++ if (unlikely(err)) { ++ goto scan_out; ++ } ++ ++ } ++ } ++ } ++ } else { /* scan in ibss */ ++ /* we don't do iscan in ibss */ ++ ssids = this_ssid; ++ } ++ wl->scan_request = request; ++ wl_set_drv_status(wl, SCANNING, ndev); ++ if (iscan_req) { ++ err = wl_do_iscan(wl, request); ++ if (likely(!err)) ++ goto scan_success; ++ else ++ goto scan_out; ++ } else if (escan_req) { ++ if (wl->p2p_supported) { ++ if (p2p_on(wl) && p2p_scan(wl)) { ++ ++ /* find my listen channel */ ++ wl->afx_hdl->my_listen_chan = ++ wl_find_listen_channel(wl, (u8 *)request->ie, ++ request->ie_len); ++ err = wl_cfgp2p_enable_discovery(wl, ndev, ++ request->ie, request->ie_len); ++ ++ if (unlikely(err)) { ++ goto scan_out; ++ } ++ } ++ } ++ err = wl_do_escan(wl, wiphy, ndev, request); ++ if (likely(!err)) ++ goto scan_success; ++ else ++ goto scan_out; ++ ++ ++ } else { ++ memset(&sr->ssid, 0, sizeof(sr->ssid)); ++ sr->ssid.SSID_len = ++ min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len); ++ if (sr->ssid.SSID_len) { ++ memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len); ++ sr->ssid.SSID_len = htod32(sr->ssid.SSID_len); ++ AP6210_DEBUG("Specific scan ssid=\"%s\" len=%d\n", ++ sr->ssid.SSID, sr->ssid.SSID_len); ++ } else { ++ AP6210_DEBUG("Broadcast scan\n"); ++ } ++ AP6210_DEBUG("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len); ++ passive_scan = wl->active_scan ? 0 : 1; ++ err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, ++ &passive_scan, sizeof(passive_scan), true); ++ if (unlikely(err)) { ++ AP6210_DEBUG("WLC_SET_PASSIVE_SCAN error (%d)\n", err); ++ goto scan_out; ++ } ++ err = wldev_ioctl(ndev, WLC_SCAN, &sr->ssid, ++ sizeof(sr->ssid), false); ++ if (err) { ++ if (err == -EBUSY) { ++ AP6210_ERR("system busy : scan for \"%s\" " ++ "canceled\n", sr->ssid.SSID); ++ } else { ++ AP6210_ERR("WLC_SCAN error (%d)\n", err); ++ } ++ goto scan_out; ++ } ++ } ++ ++scan_success: ++ ++ busy_count = 0; ++ ++ return 0; ++ ++scan_out: ++ ++ if (err == BCME_BUSY || err == BCME_NOTREADY) { ++ AP6210_ERR("Scan err = (%d), busy?%d", err, -EBUSY); ++ err = -EBUSY; ++ } ++ ++#define SCAN_EBUSY_RETRY_LIMIT 10 ++ if (err == -EBUSY) { ++ if (busy_count++ > SCAN_EBUSY_RETRY_LIMIT) { ++ struct ether_addr bssid; ++ s32 ret = 0; ++ busy_count = 0; ++ AP6210_ERR("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n", ++ wl_get_drv_status(wl, SCANNING, ndev), ++ wl_get_drv_status(wl, SCAN_ABORTING, ndev), ++ wl_get_drv_status(wl, CONNECTING, ndev), ++ wl_get_drv_status(wl, CONNECTED, ndev), ++ wl_get_drv_status(wl, DISCONNECTING, ndev), ++ wl_get_drv_status(wl, AP_CREATING, ndev), ++ wl_get_drv_status(wl, AP_CREATED, ndev), ++ wl_get_drv_status(wl, SENDING_ACT_FRM, ndev), ++ wl_get_drv_status(wl, SENDING_ACT_FRM, ndev)); ++ ++ bzero(&bssid, sizeof(bssid)); ++ if ((ret = wldev_ioctl(ndev, WLC_GET_BSSID, ++ &bssid, ETHER_ADDR_LEN, false)) == 0) ++ AP6210_ERR("FW is connected with " MACDBG "/n", ++ MAC2STRDBG(bssid.octet)); ++ else ++ AP6210_ERR("GET BSSID failed with %d\n", ret); ++ ++ wl_cfg80211_disconnect(wiphy, ndev, DOT11_RC_DISASSOC_LEAVING); ++ } ++ } else { ++ busy_count = 0; ++ } ++ wl_clr_drv_status(wl, SCANNING, ndev); ++ if (timer_pending(&wl->scan_timeout)) ++ del_timer_sync(&wl->scan_timeout); ++ spin_lock_irqsave(&wl->cfgdrv_lock, flags); ++ wl->scan_request = NULL; ++ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); ++ return err; ++} ++ ++static s32 ++wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, ++ struct cfg80211_scan_request *request) ++{ ++ s32 err = 0; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ ++ AP6210_DEBUG("Enter \n"); ++ CHECK_SYS_UP(wl); ++ ++ err = __wl_cfg80211_scan(wiphy, ndev, request, NULL); ++ if (unlikely(err)) { ++ if ((err == BCME_EPERM) && wl->scan_suppressed) ++ AP6210_DEBUG("scan not permitted at this time (%d)\n", err); ++ else ++ AP6210_ERR("scan error (%d)\n", err); ++ return err; ++ } ++ ++ return err; ++} ++ ++static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold) ++{ ++ s32 err = 0; ++ ++ err = wldev_iovar_setint(dev, "rtsthresh", rts_threshold); ++ if (unlikely(err)) { ++ AP6210_ERR("Error (%d)\n", err); ++ return err; ++ } ++ return err; ++} ++ ++static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold) ++{ ++ s32 err = 0; ++ ++ err = wldev_iovar_setint_bsscfg(dev, "fragthresh", frag_threshold, 0); ++ if (unlikely(err)) { ++ AP6210_ERR("Error (%d)\n", err); ++ return err; ++ } ++ return err; ++} ++ ++static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l) ++{ ++ s32 err = 0; ++ u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL); ++ ++ retry = htod32(retry); ++ err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), true); ++ if (unlikely(err)) { ++ AP6210_ERR("cmd (%d) , error (%d)\n", cmd, err); ++ return err; ++ } ++ return err; ++} ++ ++static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) ++{ ++ struct wl_priv *wl = (struct wl_priv *)wiphy_priv(wiphy); ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++ s32 err = 0; ++ ++ CHECK_SYS_UP(wl); ++ AP6210_DEBUG("Enter\n"); ++ if (changed & WIPHY_PARAM_RTS_THRESHOLD && ++ (wl->conf->rts_threshold != wiphy->rts_threshold)) { ++ wl->conf->rts_threshold = wiphy->rts_threshold; ++ err = wl_set_rts(ndev, wl->conf->rts_threshold); ++ if (!err) ++ return err; ++ } ++ if (changed & WIPHY_PARAM_FRAG_THRESHOLD && ++ (wl->conf->frag_threshold != wiphy->frag_threshold)) { ++ wl->conf->frag_threshold = wiphy->frag_threshold; ++ err = wl_set_frag(ndev, wl->conf->frag_threshold); ++ if (!err) ++ return err; ++ } ++ if (changed & WIPHY_PARAM_RETRY_LONG && ++ (wl->conf->retry_long != wiphy->retry_long)) { ++ wl->conf->retry_long = wiphy->retry_long; ++ err = wl_set_retry(ndev, wl->conf->retry_long, true); ++ if (!err) ++ return err; ++ } ++ if (changed & WIPHY_PARAM_RETRY_SHORT && ++ (wl->conf->retry_short != wiphy->retry_short)) { ++ wl->conf->retry_short = wiphy->retry_short; ++ err = wl_set_retry(ndev, wl->conf->retry_short, false); ++ if (!err) { ++ return err; ++ } ++ } ++ ++ return err; ++} ++ ++static s32 ++wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_ibss_params *params) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct cfg80211_bss *bss; ++ struct ieee80211_channel *chan; ++ struct wl_join_params join_params; ++ struct cfg80211_ssid ssid; ++ s32 scan_retry = 0; ++ s32 err = 0; ++ bool rollback_lock = false; ++ ++ AP6210_DEBUG("In\n"); ++ CHECK_SYS_UP(wl); ++ if (params->bssid) { ++ AP6210_ERR("Invalid bssid\n"); ++ return -EOPNOTSUPP; ++ } ++ bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len); ++ if (!bss) { ++ memcpy(ssid.ssid, params->ssid, params->ssid_len); ++ ssid.ssid_len = params->ssid_len; ++ do { ++ if (unlikely ++ (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) == ++ -EBUSY)) { ++ wl_delay(150); ++ } else { ++ break; ++ } ++ } while (++scan_retry < WL_SCAN_RETRY_MAX); ++ /* to allow scan_inform to propagate to cfg80211 plane */ ++ if (rtnl_is_locked()) { ++ rtnl_unlock(); ++ rollback_lock = true; ++ } ++ ++ /* wait 4 secons till scan done.... */ ++ schedule_timeout_interruptible(msecs_to_jiffies(4000)); ++ if (rollback_lock) ++ rtnl_lock(); ++ bss = cfg80211_get_ibss(wiphy, NULL, ++ params->ssid, params->ssid_len); ++ } ++ if (bss) { ++ wl->ibss_starter = false; ++ AP6210_DEBUG("Found IBSS\n"); ++ } else { ++ wl->ibss_starter = true; ++ } ++ chan = params->channel; ++ if (chan) ++ wl->channel = ieee80211_frequency_to_channel(chan->center_freq); ++ /* ++ * Join with specific BSSID and cached SSID ++ * If SSID is zero join based on BSSID only ++ */ ++ memset(&join_params, 0, sizeof(join_params)); ++ memcpy((void *)join_params.ssid.SSID, (void *)params->ssid, ++ params->ssid_len); ++ join_params.ssid.SSID_len = htod32(params->ssid_len); ++ if (params->bssid) ++ memcpy(&join_params.params.bssid, params->bssid, ++ ETHER_ADDR_LEN); ++ else ++ memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN); ++ ++ err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, ++ sizeof(join_params), true); ++ if (unlikely(err)) { ++ AP6210_ERR("Error (%d)\n", err); ++ return err; ++ } ++ return err; ++} ++ ++static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ s32 err = 0; ++ ++ CHECK_SYS_UP(wl); ++ wl_link_down(wl); ++ ++ return err; ++} ++ ++static s32 ++wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ struct wl_security *sec; ++ s32 val = 0; ++ s32 err = 0; ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); ++ ++ if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) ++ val = WPA_AUTH_PSK | ++ WPA_AUTH_UNSPECIFIED; ++ else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) ++ val = WPA2_AUTH_PSK| ++ WPA2_AUTH_UNSPECIFIED; ++ else ++ val = WPA_AUTH_DISABLED; ++ ++ if (is_wps_conn(sme)) ++ val = WPA_AUTH_DISABLED; ++ ++#ifdef BCMWAPI_WPI ++ if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) { ++ AP6210_DEBUG(" * wl_set_wpa_version, set wpa_auth" ++ " to WPA_AUTH_WAPI 0x400"); ++ val = WAPI_AUTH_PSK; /* | WAPI_AUTH_UNSPECIFIED; */ ++ } ++#endif ++ AP6210_DEBUG("setting wpa_auth to 0x%0x\n", val); ++ err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx); ++ if (unlikely(err)) { ++ AP6210_ERR("set wpa_auth failed (%d)\n", err); ++ return err; ++ } ++ sec = wl_read_prof(wl, dev, WL_PROF_SEC); ++ sec->wpa_versions = sme->crypto.wpa_versions; ++ return err; ++} ++ ++#ifdef BCMWAPI_WPI ++static s32 ++wl_set_set_wapi_ie(struct net_device *dev, struct cfg80211_connect_params *sme) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ s32 err = 0; ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); ++ ++ AP6210_DEBUG(" %s \n", __FUNCTION__); ++ ++ if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) { ++ err = wldev_iovar_setbuf_bsscfg(dev, "wapiie", sme->ie, ++ sme->ie_len, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); ++ if (unlikely(err)) { ++ AP6210_ERR("===> set_wapi_ie Error (%d)\n", err); ++ return err; ++ } ++ } else ++ AP6210_DEBUG(" * skip \n"); ++ return err; ++} ++#endif /* BCMWAPI_WPI */ ++ ++static s32 ++wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ struct wl_security *sec; ++ s32 val = 0; ++ s32 err = 0; ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); ++ switch (sme->auth_type) { ++ case NL80211_AUTHTYPE_OPEN_SYSTEM: ++ val = WL_AUTH_OPEN_SYSTEM; ++ AP6210_DEBUG("open system\n"); ++ break; ++ case NL80211_AUTHTYPE_SHARED_KEY: ++ val = WL_AUTH_SHARED_KEY; ++ AP6210_DEBUG("shared key\n"); ++ break; ++ case NL80211_AUTHTYPE_AUTOMATIC: ++ val = WL_AUTH_OPEN_SHARED; ++ AP6210_DEBUG("automatic\n"); ++ break; ++ default: ++ val = WL_AUTH_OPEN_SHARED; ++ AP6210_ERR("invalid auth type (%d)\n", sme->auth_type); ++ break; ++ } ++ ++ err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx); ++ if (unlikely(err)) { ++ AP6210_ERR("set auth failed (%d)\n", err); ++ return err; ++ } ++ sec = wl_read_prof(wl, dev, WL_PROF_SEC); ++ sec->auth_type = sme->auth_type; ++ return err; ++} ++ ++static s32 ++wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ struct wl_security *sec; ++ s32 pval = 0; ++ s32 gval = 0; ++ s32 err = 0; ++#ifdef BCMWAPI_WPI ++ s32 val = 0; ++#endif ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); ++ ++ if (sme->crypto.n_ciphers_pairwise) { ++ switch (sme->crypto.ciphers_pairwise[0]) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ case WLAN_CIPHER_SUITE_WEP104: ++ pval = WEP_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ pval = TKIP_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ pval = AES_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ pval = AES_ENABLED; ++ break; ++#ifdef BCMWAPI_WPI ++ case WLAN_CIPHER_SUITE_SMS4: ++ val = SMS4_ENABLED; ++ pval = SMS4_ENABLED; ++ break; ++#endif ++ default: ++ AP6210_ERR("invalid cipher pairwise (%d)\n", ++ sme->crypto.ciphers_pairwise[0]); ++ return -EINVAL; ++ } ++ } ++ if (sme->crypto.cipher_group) { ++ switch (sme->crypto.cipher_group) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ case WLAN_CIPHER_SUITE_WEP104: ++ gval = WEP_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ gval = TKIP_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ gval = AES_ENABLED; ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ gval = AES_ENABLED; ++ break; ++#ifdef BCMWAPI_WPI ++ case WLAN_CIPHER_SUITE_SMS4: ++ val = SMS4_ENABLED; ++ gval = SMS4_ENABLED; ++ break; ++#endif ++ default: ++ AP6210_ERR("invalid cipher group (%d)\n", ++ sme->crypto.cipher_group); ++ return -EINVAL; ++ } ++ } ++ ++ AP6210_DEBUG("pval (%d) gval (%d)\n", pval, gval); ++ ++ if (is_wps_conn(sme)) { ++ if (sme->privacy) ++ err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx); ++#ifdef BCMWAPI_WPI ++ else if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_SMS4) { ++ AP6210_DEBUG(" NO, is_wps_conn, WAPI set to SMS4_ENABLED"); ++ err = wldev_iovar_setint_bsscfg(dev, "wsec", val, bssidx); ++ } ++#endif ++ else ++ /* WPS-2.0 allows no security */ ++ err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx); ++ } else { ++ AP6210_DEBUG(" NO, is_wps_conn, Set pval | gval to WSEC"); ++ err = wldev_iovar_setint_bsscfg(dev, "wsec", ++ pval | gval, bssidx); ++ } ++ if (unlikely(err)) { ++ AP6210_ERR("error (%d)\n", err); ++ return err; ++ } ++ ++ sec = wl_read_prof(wl, dev, WL_PROF_SEC); ++ sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0]; ++ sec->cipher_group = sme->crypto.cipher_group; ++ ++ return err; ++} ++ ++static s32 ++wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ struct wl_security *sec; ++ s32 val = 0; ++ s32 err = 0; ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); ++ ++ if (sme->crypto.n_akm_suites) { ++ err = wldev_iovar_getint(dev, "wpa_auth", &val); ++ if (unlikely(err)) { ++ AP6210_ERR("could not get wpa_auth (%d)\n", err); ++ return err; ++ } ++ if (val & (WPA_AUTH_PSK | ++ WPA_AUTH_UNSPECIFIED)) { ++ switch (sme->crypto.akm_suites[0]) { ++ case WLAN_AKM_SUITE_8021X: ++ val = WPA_AUTH_UNSPECIFIED; ++ break; ++ case WLAN_AKM_SUITE_PSK: ++ val = WPA_AUTH_PSK; ++ break; ++ default: ++ AP6210_ERR("invalid cipher group (%d)\n", ++ sme->crypto.cipher_group); ++ return -EINVAL; ++ } ++ } else if (val & (WPA2_AUTH_PSK | ++ WPA2_AUTH_UNSPECIFIED)) { ++ switch (sme->crypto.akm_suites[0]) { ++ case WLAN_AKM_SUITE_8021X: ++ val = WPA2_AUTH_UNSPECIFIED; ++ break; ++ case WLAN_AKM_SUITE_PSK: ++ val = WPA2_AUTH_PSK; ++ break; ++ default: ++ AP6210_ERR("invalid cipher group (%d)\n", ++ sme->crypto.cipher_group); ++ return -EINVAL; ++ } ++ } ++#ifdef BCMWAPI_WPI ++ else if (val & (WAPI_AUTH_PSK | WAPI_AUTH_UNSPECIFIED)) { ++ switch (sme->crypto.akm_suites[0]) { ++ case WLAN_AKM_SUITE_WAPI_CERT: ++ val = WAPI_AUTH_UNSPECIFIED; ++ break; ++ case WLAN_AKM_SUITE_WAPI_PSK: ++ val = WAPI_AUTH_PSK; ++ break; ++ default: ++ AP6210_ERR("invalid cipher group (%d)\n", ++ sme->crypto.cipher_group); ++ return -EINVAL; ++ } ++ } ++#endif ++ AP6210_DEBUG("setting wpa_auth to %d\n", val); ++ ++ err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx); ++ if (unlikely(err)) { ++ AP6210_ERR("could not set wpa_auth (%d)\n", err); ++ return err; ++ } ++ } ++ sec = wl_read_prof(wl, dev, WL_PROF_SEC); ++ sec->wpa_auth = sme->crypto.akm_suites[0]; ++ ++ return err; ++} ++ ++static s32 ++wl_set_set_sharedkey(struct net_device *dev, ++ struct cfg80211_connect_params *sme) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ struct wl_security *sec; ++ struct wl_wsec_key key; ++ s32 val; ++ s32 err = 0; ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); ++ ++ AP6210_DEBUG("key len (%d)\n", sme->key_len); ++ if (sme->key_len) { ++ sec = wl_read_prof(wl, dev, WL_PROF_SEC); ++ AP6210_DEBUG("wpa_versions 0x%x cipher_pairwise 0x%x\n", ++ sec->wpa_versions, sec->cipher_pairwise); ++ if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 | ++ NL80211_WPA_VERSION_2 ++#ifdef BCMWAPI_WPI ++ | NL80211_WAPI_VERSION_1 ++#endif ++ )) && ++ (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 | ++ WLAN_CIPHER_SUITE_WEP104 ++#ifdef BCMWAPI_WPI ++ | WLAN_CIPHER_SUITE_SMS4 ++#endif ++ ))) ++ { ++ memset(&key, 0, sizeof(key)); ++ key.len = (u32) sme->key_len; ++ key.index = (u32) sme->key_idx; ++ if (unlikely(key.len > sizeof(key.data))) { ++ AP6210_ERR("Too long key length (%u)\n", key.len); ++ return -EINVAL; ++ } ++ memcpy(key.data, sme->key, key.len); ++ key.flags = WL_PRIMARY_KEY; ++ switch (sec->cipher_pairwise) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ key.algo = CRYPTO_ALGO_WEP1; ++ break; ++ case WLAN_CIPHER_SUITE_WEP104: ++ key.algo = CRYPTO_ALGO_WEP128; ++ break; ++#ifdef BCMWAPI_WPI ++ case WLAN_CIPHER_SUITE_SMS4: ++ key.algo = CRYPTO_ALGO_SMS4; ++ break; ++#endif ++ default: ++ AP6210_ERR("Invalid algorithm (%d)\n", ++ sme->crypto.ciphers_pairwise[0]); ++ return -EINVAL; ++ } ++ /* Set the new key/index */ ++ AP6210_DEBUG("key length (%d) key index (%d) algo (%d)\n", ++ key.len, key.index, key.algo); ++ AP6210_DEBUG("key \"%s\"\n", key.data); ++ swap_key_from_BE(&key); ++ err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); ++ if (unlikely(err)) { ++ AP6210_ERR("WLC_SET_KEY error (%d)\n", err); ++ return err; ++ } ++ if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) { ++ AP6210_DEBUG("set auth_type to shared key\n"); ++ val = WL_AUTH_SHARED_KEY; /* shared key */ ++ err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx); ++ if (unlikely(err)) { ++ AP6210_ERR("set auth failed (%d)\n", err); ++ return err; ++ } ++ } ++ } ++ } ++ return err; ++} ++ ++#ifdef ESCAN_RESULT_PATCH ++static u8 connect_req_bssid[6]; ++static u8 broad_bssid[6]; ++#endif ++ ++ ++static s32 ++wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_connect_params *sme) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct ieee80211_channel *chan = sme->channel; ++ wl_extjoin_params_t *ext_join_params; ++ struct wl_join_params join_params; ++ size_t join_params_size; ++ s32 err = 0; ++ wpa_ie_fixed_t *wpa_ie; ++ bcm_tlv_t *wpa2_ie; ++ u8* wpaie = 0; ++ u32 wpaie_len = 0; ++ u32 chan_cnt = 0; ++ struct ether_addr bssid; ++ int ret; ++ ++ AP6210_DEBUG("In\n"); ++ ++ if (unlikely(!sme->ssid)) { ++ AP6210_ERR("Invalid ssid\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ CHECK_SYS_UP(wl); ++ ++ /* ++ * Cancel ongoing scan to sync up with sme state machine of cfg80211. ++ */ ++#if !defined(ESCAN_RESULT_PATCH) ++ if (wl->scan_request) { ++ wl_notify_escan_complete(wl, dev, true, true); ++ } ++#endif ++#ifdef ESCAN_RESULT_PATCH ++ if (sme->bssid) { ++ memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN); ++ } ++ else { ++ bzero(connect_req_bssid, ETHER_ADDR_LEN); ++ } ++ bzero(broad_bssid, ETHER_ADDR_LEN); ++#endif ++ ++ bzero(&bssid, sizeof(bssid)); ++ if (!wl_get_drv_status(wl, CONNECTED, dev)&& ++ (ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) { ++ if (!ETHER_ISNULLADDR(&bssid)) { ++ scb_val_t scbval; ++ wl_set_drv_status(wl, DISCONNECTING, dev); ++ scbval.val = DOT11_RC_DISASSOC_LEAVING; ++ memcpy(&scbval.ea, &bssid, ETHER_ADDR_LEN); ++ scbval.val = htod32(scbval.val); ++ ++ AP6210_DEBUG("drv status CONNECTED is not set, but connected in FW!" MACDBG "\n", ++ MAC2STRDBG(bssid.octet)); ++ err = wldev_ioctl(dev, WLC_DISASSOC, &scbval, ++ sizeof(scb_val_t), true); ++ if (unlikely(err)) { ++ wl_clr_drv_status(wl, DISCONNECTING, dev); ++ AP6210_ERR("error (%d)\n", err); ++ return err; ++ } ++ while (wl_get_drv_status(wl, DISCONNECTING, dev)) { ++ AP6210_ERR("Waiting for disconnection terminated.\n"); ++ msleep(20); ++ } ++ } else ++ AP6210_DEBUG("Currently not associated!\n"); ++ } ++ ++ /* Clean BSSID */ ++ bzero(&bssid, sizeof(bssid)); ++ if (!wl_get_drv_status(wl, DISCONNECTING, dev)) ++ wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID); ++ ++ if (p2p_is_on(wl) && (dev != wl_to_prmry_ndev(wl))) { ++ /* we only allow to connect using virtual interface in case of P2P */ ++ wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), ++ VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len); ++ } else if (dev == wl_to_prmry_ndev(wl)) { ++ /* find the RSN_IE */ ++ if ((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len, ++ DOT11_MNG_RSN_ID)) != NULL) { ++ AP6210_DEBUG(" WPA2 IE is found\n"); ++ } ++ /* find the WPA_IE */ ++ if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)sme->ie, ++ sme->ie_len)) != NULL) { ++ AP6210_DEBUG(" WPA IE is found\n"); ++ } ++ if (wpa_ie != NULL || wpa2_ie != NULL) { ++ wpaie = (wpa_ie != NULL) ? (u8 *)wpa_ie : (u8 *)wpa2_ie; ++ wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len; ++ wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN; ++ wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len, ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); ++ } else { ++ wldev_iovar_setbuf(dev, "wpaie", NULL, 0, ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); ++ } ++ ++ err = wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), ++ VNDR_IE_ASSOCREQ_FLAG, (u8 *)sme->ie, sme->ie_len); ++ if (unlikely(err)) { ++ return err; ++ } ++ } ++ ++ if (chan) { ++ wl->channel = ieee80211_frequency_to_channel(chan->center_freq); ++ chan_cnt = 1; ++ AP6210_DEBUG("channel (%d), center_req (%d), %d channels\n", wl->channel, ++ chan->center_freq, chan_cnt); ++ } else ++ wl->channel = 0; ++ ++#ifdef BCMWAPI_WPI ++ AP6210_DEBUG("1. enable wapi auth\n"); ++ if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) { ++ AP6210_DEBUG("2. set wapi ie \n"); ++ err = wl_set_set_wapi_ie(dev, sme); ++ if (unlikely(err)) ++ return err; ++ } else ++ AP6210_DEBUG("2. Not wapi ie \n"); ++#endif ++ AP6210_DEBUG("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len); ++ AP6210_DEBUG("3. set wapi version \n"); ++ err = wl_set_wpa_version(dev, sme); ++ if (unlikely(err)) { ++ AP6210_ERR("Invalid wpa_version\n"); ++ return err; ++ } ++#ifdef BCMWAPI_WPI ++ if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) ++ AP6210_DEBUG("4. WAPI Dont Set wl_set_auth_type\n"); ++ else { ++ AP6210_DEBUG("4. wl_set_auth_type\n"); ++#endif ++ err = wl_set_auth_type(dev, sme); ++ if (unlikely(err)) { ++ AP6210_ERR("Invalid auth type\n"); ++ return err; ++ } ++#ifdef BCMWAPI_WPI ++ ++ } ++#endif ++ ++ err = wl_set_set_cipher(dev, sme); ++ if (unlikely(err)) { ++ AP6210_ERR("Invalid ciper\n"); ++ return err; ++ } ++ ++ err = wl_set_key_mgmt(dev, sme); ++ if (unlikely(err)) { ++ AP6210_ERR("Invalid key mgmt\n"); ++ return err; ++ } ++ ++ err = wl_set_set_sharedkey(dev, sme); ++ if (unlikely(err)) { ++ AP6210_ERR("Invalid shared key\n"); ++ return err; ++ } ++ ++ /* ++ * Join with specific BSSID and cached SSID ++ * If SSID is zero join based on BSSID only ++ */ ++ join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE + ++ chan_cnt * sizeof(chanspec_t); ++ ext_join_params = (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL); ++ if (ext_join_params == NULL) { ++ err = -ENOMEM; ++ wl_clr_drv_status(wl, CONNECTING, dev); ++ goto exit; ++ } ++ ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len); ++ memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len); ++ wl_update_prof(wl, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID); ++ ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len); ++ /* increate dwell time to receive probe response or detect Beacon ++ * from target AP at a noisy air only during connect command ++ */ ++ ext_join_params->scan.active_time = WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS; ++ ext_join_params->scan.passive_time = WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS; ++ /* Set up join scan parameters */ ++ ext_join_params->scan.scan_type = -1; ++ ext_join_params->scan.nprobes ++ = (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS); ++ ext_join_params->scan.home_time = -1; ++ ++ if (sme->bssid) ++ memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN); ++ else ++ memcpy(&ext_join_params->assoc.bssid, ðer_bcast, ETH_ALEN); ++ ext_join_params->assoc.chanspec_num = chan_cnt; ++ if (chan_cnt) { ++ u16 channel, band, bw, ctl_sb; ++ chanspec_t chspec; ++ channel = wl->channel; ++ band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G ++ : WL_CHANSPEC_BAND_5G; ++ bw = WL_CHANSPEC_BW_20; ++ ctl_sb = WL_CHANSPEC_CTL_SB_NONE; ++ chspec = (channel | band | bw | ctl_sb); ++ ext_join_params->assoc.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK; ++ ext_join_params->assoc.chanspec_list[0] |= chspec; ++ ext_join_params->assoc.chanspec_list[0] = ++ wl_chspec_host_to_driver(ext_join_params->assoc.chanspec_list[0]); ++ } ++ ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num); ++ if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) { ++ AP6210_DEBUG("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID, ++ ext_join_params->ssid.SSID_len); ++ } ++ wl_set_drv_status(wl, CONNECTING, dev); ++ err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size, ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, wl_cfgp2p_find_idx(wl, dev), &wl->ioctl_buf_sync); ++ kfree(ext_join_params); ++ if (err) { ++ wl_clr_drv_status(wl, CONNECTING, dev); ++ if (err == BCME_UNSUPPORTED) { ++ AP6210_DEBUG("join iovar is not supported\n"); ++ goto set_ssid; ++ } else ++ AP6210_ERR("error (%d)\n", err); ++ } else ++ goto exit; ++ ++set_ssid: ++ memset(&join_params, 0, sizeof(join_params)); ++ join_params_size = sizeof(join_params.ssid); ++ ++ join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len); ++ memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len); ++ join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len); ++ wl_update_prof(wl, dev, NULL, &join_params.ssid, WL_PROF_SSID); ++ if (sme->bssid) ++ memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN); ++ else ++ memcpy(&join_params.params.bssid, ðer_bcast, ETH_ALEN); ++ ++ wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size); ++ AP6210_DEBUG("join_param_size %d\n", join_params_size); ++ ++ if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) { ++ AP6210_DEBUG("ssid \"%s\", len (%d)\n", join_params.ssid.SSID, ++ join_params.ssid.SSID_len); ++ } ++ wl_set_drv_status(wl, CONNECTING, dev); ++ err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true); ++ if (err) { ++ AP6210_ERR("error (%d)\n", err); ++ wl_clr_drv_status(wl, CONNECTING, dev); ++ } ++exit: ++ return err; ++} ++ ++static s32 ++wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, ++ u16 reason_code) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ scb_val_t scbval; ++ bool act = false; ++ s32 err = 0; ++ u8 *curbssid; ++ AP6210_ERR("Reason %d\n", reason_code); ++ CHECK_SYS_UP(wl); ++ act = *(bool *) wl_read_prof(wl, dev, WL_PROF_ACT); ++ curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID); ++ if (act) { ++ /* ++ * Cancel ongoing scan to sync up with sme state machine of cfg80211. ++ */ ++#if !defined(ESCAN_RESULT_PATCH) ++ /* Let scan aborted by F/W */ ++ if (wl->scan_request) { ++ wl_notify_escan_complete(wl, dev, true, true); ++ } ++#endif /* ESCAN_RESULT_PATCH */ ++ wl_set_drv_status(wl, DISCONNECTING, dev); ++ scbval.val = reason_code; ++ memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN); ++ scbval.val = htod32(scbval.val); ++ err = wldev_ioctl(dev, WLC_DISASSOC, &scbval, ++ sizeof(scb_val_t), true); ++ if (unlikely(err)) { ++ wl_clr_drv_status(wl, DISCONNECTING, dev); ++ AP6210_ERR("error (%d)\n", err); ++ return err; ++ } ++ } ++ ++ return err; ++} ++ ++static s32 ++wl_cfg80211_set_tx_power(struct wiphy *wiphy, ++ enum nl80211_tx_power_setting type, s32 dbm) ++{ ++ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++ u16 txpwrmw; ++ s32 err = 0; ++ s32 disable = 0; ++ ++ CHECK_SYS_UP(wl); ++ switch (type) { ++ case NL80211_TX_POWER_AUTOMATIC: ++ break; ++ case NL80211_TX_POWER_LIMITED: ++ if (dbm < 0) { ++ AP6210_ERR("TX_POWER_LIMITTED - dbm is negative\n"); ++ return -EINVAL; ++ } ++ break; ++ case NL80211_TX_POWER_FIXED: ++ if (dbm < 0) { ++ AP6210_ERR("TX_POWER_FIXED - dbm is negative..\n"); ++ return -EINVAL; ++ } ++ break; ++ } ++ /* Make sure radio is off or on as far as software is concerned */ ++ disable = WL_RADIO_SW_DISABLE << 16; ++ disable = htod32(disable); ++ err = wldev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable), true); ++ if (unlikely(err)) { ++ AP6210_ERR("WLC_SET_RADIO error (%d)\n", err); ++ return err; ++ } ++ ++ if (dbm > 0xffff) ++ txpwrmw = 0xffff; ++ else ++ txpwrmw = (u16) dbm; ++ err = wldev_iovar_setint(ndev, "qtxpower", ++ (s32) (bcm_mw_to_qdbm(txpwrmw))); ++ if (unlikely(err)) { ++ AP6210_ERR("qtxpower error (%d)\n", err); ++ return err; ++ } ++ wl->conf->tx_power = dbm; ++ ++ return err; ++} ++ ++static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++ s32 txpwrdbm; ++ u8 result; ++ s32 err = 0; ++ ++ CHECK_SYS_UP(wl); ++ err = wldev_iovar_getint(ndev, "qtxpower", &txpwrdbm); ++ if (unlikely(err)) { ++ AP6210_ERR("error (%d)\n", err); ++ return err; ++ } ++ result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE); ++ *dbm = (s32) bcm_qdbm_to_mw(result); ++ ++ return err; ++} ++ ++static s32 ++wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev, ++ u8 key_idx, bool unicast, bool multicast) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ u32 index; ++ s32 wsec; ++ s32 err = 0; ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); ++ ++ AP6210_DEBUG("key index (%d)\n", key_idx); ++ CHECK_SYS_UP(wl); ++ err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx); ++ if (unlikely(err)) { ++ AP6210_ERR("WLC_GET_WSEC error (%d)\n", err); ++ return err; ++ } ++ if (wsec & WEP_ENABLED) { ++ /* Just select a new current key */ ++ index = (u32) key_idx; ++ index = htod32(index); ++ err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index, ++ sizeof(index), true); ++ if (unlikely(err)) { ++ AP6210_ERR("error (%d)\n", err); ++ } ++ } ++ return err; ++} ++ ++static s32 ++wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, ++ u8 key_idx, const u8 *mac_addr, struct key_params *params) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct wl_wsec_key key; ++ s32 err = 0; ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); ++ s32 mode = wl_get_mode_by_netdev(wl, dev); ++ memset(&key, 0, sizeof(key)); ++ key.index = (u32) key_idx; ++ ++ if (!ETHER_ISMULTI(mac_addr)) ++ memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN); ++ key.len = (u32) params->key_len; ++ ++ /* check for key index change */ ++ if (key.len == 0) { ++ /* key delete */ ++ swap_key_from_BE(&key); ++ err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); ++ if (unlikely(err)) { ++ AP6210_ERR("key delete error (%d)\n", err); ++ return err; ++ } ++ } else { ++ if (key.len > sizeof(key.data)) { ++ AP6210_ERR("Invalid key length (%d)\n", key.len); ++ return -EINVAL; ++ } ++ AP6210_DEBUG("Setting the key index %d\n", key.index); ++ memcpy(key.data, params->key, key.len); ++ ++ if ((mode == WL_MODE_BSS) && ++ (params->cipher == WLAN_CIPHER_SUITE_TKIP)) { ++ u8 keybuf[8]; ++ memcpy(keybuf, &key.data[24], sizeof(keybuf)); ++ memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); ++ memcpy(&key.data[16], keybuf, sizeof(keybuf)); ++ } ++ ++ /* if IW_ENCODE_EXT_RX_SEQ_VALID set */ ++ if (params->seq && params->seq_len == 6) { ++ /* rx iv */ ++ u8 *ivptr; ++ ivptr = (u8 *) params->seq; ++ key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) | ++ (ivptr[3] << 8) | ivptr[2]; ++ key.rxiv.lo = (ivptr[1] << 8) | ivptr[0]; ++ key.iv_initialized = true; ++ } ++ ++ switch (params->cipher) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ key.algo = CRYPTO_ALGO_WEP1; ++ AP6210_DEBUG("WLAN_CIPHER_SUITE_WEP40\n"); ++ break; ++ case WLAN_CIPHER_SUITE_WEP104: ++ key.algo = CRYPTO_ALGO_WEP128; ++ AP6210_DEBUG("WLAN_CIPHER_SUITE_WEP104\n"); ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ key.algo = CRYPTO_ALGO_TKIP; ++ AP6210_DEBUG("WLAN_CIPHER_SUITE_TKIP\n"); ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ key.algo = CRYPTO_ALGO_AES_CCM; ++ AP6210_DEBUG("WLAN_CIPHER_SUITE_AES_CMAC\n"); ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ key.algo = CRYPTO_ALGO_AES_CCM; ++ AP6210_DEBUG("WLAN_CIPHER_SUITE_CCMP\n"); ++ break; ++#ifdef BCMWAPI_WPI ++ case WLAN_CIPHER_SUITE_SMS4: ++ key.algo = CRYPTO_ALGO_SMS4; ++ AP6210_DEBUG("WLAN_CIPHER_SUITE_SMS4\n"); ++ break; ++#endif ++ default: ++ AP6210_ERR("Invalid cipher (0x%x)\n", params->cipher); ++ return -EINVAL; ++ } ++ swap_key_from_BE(&key); ++ /* need to guarantee EAPOL 4/4 send out before set key */ ++ dhd_wait_pend8021x(dev); ++ err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); ++ if (unlikely(err)) { ++ AP6210_ERR("WLC_SET_KEY error (%d)\n", err); ++ return err; ++ } ++ } ++ return err; ++} ++ ++static s32 ++wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, ++ u8 key_idx, bool pairwise, const u8 *mac_addr, ++ struct key_params *params) ++{ ++ struct wl_wsec_key key; ++ s32 val = 0; ++ s32 wsec = 0; ++ s32 err = 0; ++ u8 keybuf[8]; ++ s32 bssidx = 0; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ s32 mode = wl_get_mode_by_netdev(wl, dev); ++ AP6210_DEBUG("key index (%d)\n", key_idx); ++ CHECK_SYS_UP(wl); ++ ++ bssidx = wl_cfgp2p_find_idx(wl, dev); ++ ++ if (mac_addr) { ++ wl_add_keyext(wiphy, dev, key_idx, mac_addr, params); ++ goto exit; ++ } ++ memset(&key, 0, sizeof(key)); ++ ++ key.len = (u32) params->key_len; ++ key.index = (u32) key_idx; ++ ++ if (unlikely(key.len > sizeof(key.data))) { ++ AP6210_ERR("Too long key length (%u)\n", key.len); ++ return -EINVAL; ++ } ++ memcpy(key.data, params->key, key.len); ++ ++ key.flags = WL_PRIMARY_KEY; ++ switch (params->cipher) { ++ case WLAN_CIPHER_SUITE_WEP40: ++ key.algo = CRYPTO_ALGO_WEP1; ++ val = WEP_ENABLED; ++ AP6210_DEBUG("WLAN_CIPHER_SUITE_WEP40\n"); ++ break; ++ case WLAN_CIPHER_SUITE_WEP104: ++ key.algo = CRYPTO_ALGO_WEP128; ++ val = WEP_ENABLED; ++ AP6210_DEBUG("WLAN_CIPHER_SUITE_WEP104\n"); ++ break; ++ case WLAN_CIPHER_SUITE_TKIP: ++ key.algo = CRYPTO_ALGO_TKIP; ++ val = TKIP_ENABLED; ++ /* wpa_supplicant switches the third and fourth quarters of the TKIP key */ ++ if (mode == WL_MODE_BSS) { ++ bcopy(&key.data[24], keybuf, sizeof(keybuf)); ++ bcopy(&key.data[16], &key.data[24], sizeof(keybuf)); ++ bcopy(keybuf, &key.data[16], sizeof(keybuf)); ++ } ++ AP6210_DEBUG("WLAN_CIPHER_SUITE_TKIP\n"); ++ break; ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ key.algo = CRYPTO_ALGO_AES_CCM; ++ val = AES_ENABLED; ++ AP6210_DEBUG("WLAN_CIPHER_SUITE_AES_CMAC\n"); ++ break; ++ case WLAN_CIPHER_SUITE_CCMP: ++ key.algo = CRYPTO_ALGO_AES_CCM; ++ val = AES_ENABLED; ++ AP6210_DEBUG("WLAN_CIPHER_SUITE_CCMP\n"); ++ break; ++#ifdef BCMWAPI_WPI ++ case WLAN_CIPHER_SUITE_SMS4: ++ key.algo = CRYPTO_ALGO_SMS4; ++ val = SMS4_ENABLED; ++ AP6210_DEBUG(" * wl_cfg80211_add_key, set key " ++ " to WLAN_CIPHER_SUITE_SMS4\n"); ++ break; ++#endif /* BCMWAPI_WPI */ ++ default: ++ AP6210_ERR("Invalid cipher (0x%x)\n", params->cipher); ++ return -EINVAL; ++ } ++ ++ /* Set the new key/index */ ++ swap_key_from_BE(&key); ++ err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf, ++ WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); ++ if (unlikely(err)) { ++ AP6210_ERR("WLC_SET_KEY error (%d)\n", err); ++ return err; ++ } ++ ++exit: ++ err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx); ++ if (unlikely(err)) { ++ AP6210_ERR("get wsec error (%d)\n", err); ++ return err; ++ } ++ ++ wsec |= val; ++ err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx); ++ if (unlikely(err)) { ++ AP6210_ERR("set wsec error (%d)\n", err); ++ return err; ++ } ++ ++ return err; ++} ++ ++static s32 ++wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, ++ u8 key_idx, bool pairwise, const u8 *mac_addr) ++{ ++ struct wl_wsec_key key; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ s32 err = 0; ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); ++ ++ AP6210_DEBUG("Enter\n"); ++#ifndef IEEE80211W ++ if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2)) ++ return -EINVAL; ++#endif ++ CHECK_SYS_UP(wl); ++ memset(&key, 0, sizeof(key)); ++ ++ key.flags = WL_PRIMARY_KEY; ++ key.algo = CRYPTO_ALGO_OFF; ++ key.index = (u32) key_idx; ++ ++ AP6210_DEBUG("key index (%d)\n", key_idx); ++ /* Set the new key/index */ ++ swap_key_from_BE(&key); ++ err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf, ++ WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); ++ if (unlikely(err)) { ++ if (err == -EINVAL) { ++ if (key.index >= DOT11_MAX_DEFAULT_KEYS) { ++ /* we ignore this key index in this case */ ++ AP6210_DEBUG("invalid key index (%d)\n", key_idx); ++ } ++ } else { ++ AP6210_ERR("WLC_SET_KEY error (%d)\n", err); ++ } ++ return err; ++ } ++ return err; ++} ++ ++static s32 ++wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, ++ u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie, ++ void (*callback) (void *cookie, struct key_params * params)) ++{ ++ struct key_params params; ++ struct wl_wsec_key key; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct wl_security *sec; ++ s32 wsec; ++ s32 err = 0; ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); ++ ++ AP6210_DEBUG("key index (%d)\n", key_idx); ++ CHECK_SYS_UP(wl); ++ memset(&key, 0, sizeof(key)); ++ key.index = key_idx; ++ swap_key_to_BE(&key); ++ memset(¶ms, 0, sizeof(params)); ++ params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len); ++ memcpy(params.key, key.data, params.key_len); ++ ++ wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx); ++ if (unlikely(err)) { ++ AP6210_ERR("WLC_GET_WSEC error (%d)\n", err); ++ return err; ++ } ++ switch (wsec & ~SES_OW_ENABLED) { ++ case WEP_ENABLED: ++ sec = wl_read_prof(wl, dev, WL_PROF_SEC); ++ if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { ++ params.cipher = WLAN_CIPHER_SUITE_WEP40; ++ AP6210_DEBUG("WLAN_CIPHER_SUITE_WEP40\n"); ++ } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) { ++ params.cipher = WLAN_CIPHER_SUITE_WEP104; ++ AP6210_DEBUG("WLAN_CIPHER_SUITE_WEP104\n"); ++ } ++ break; ++ case TKIP_ENABLED: ++ params.cipher = WLAN_CIPHER_SUITE_TKIP; ++ AP6210_DEBUG("WLAN_CIPHER_SUITE_TKIP\n"); ++ break; ++ case AES_ENABLED: ++ params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; ++ AP6210_DEBUG("WLAN_CIPHER_SUITE_AES_CMAC\n"); ++ break; ++#ifdef BCMWAPI_WPI ++ case WLAN_CIPHER_SUITE_SMS4: ++ key.algo = CRYPTO_ALGO_SMS4; ++ AP6210_DEBUG(" * wl_cfg80211_add_key, set key" ++ "to WLAN_CIPHER_SUITE_SMS4\n"); ++ break; ++#endif ++ default: ++ AP6210_ERR("Invalid algo (0x%x)\n", wsec); ++ return -EINVAL; ++ } ++ ++ callback(cookie, ¶ms); ++ return err; ++} ++ ++static s32 ++wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, ++ struct net_device *dev, u8 key_idx) ++{ ++ AP6210_DEBUG("Not supported\n"); ++ return -EOPNOTSUPP; ++} ++ ++static s32 ++wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, ++ u8 *mac, struct station_info *sinfo) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ scb_val_t scb_val; ++ s32 rssi; ++ s32 rate; ++ s32 err = 0; ++ sta_info_t *sta; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) ++ s8 eabuf[ETHER_ADDR_STR_LEN]; ++#endif ++ dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); ++ CHECK_SYS_UP(wl); ++ if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) { ++ err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac, ++ ETHER_ADDR_LEN, wl->ioctl_buf, WLC_IOCTL_SMLEN, &wl->ioctl_buf_sync); ++ if (err < 0) { ++ AP6210_ERR("GET STA INFO failed, %d\n", err); ++ return err; ++ } ++ sinfo->filled = STATION_INFO_INACTIVE_TIME; ++ sta = (sta_info_t *)wl->ioctl_buf; ++ sta->len = dtoh16(sta->len); ++ sta->cap = dtoh16(sta->cap); ++ sta->flags = dtoh32(sta->flags); ++ sta->idle = dtoh32(sta->idle); ++ sta->in = dtoh32(sta->in); ++ sinfo->inactive_time = sta->idle * 1000; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) ++ if (sta->flags & WL_STA_ASSOC) { ++ sinfo->filled |= STATION_INFO_CONNECTED_TIME; ++ sinfo->connected_time = sta->in; ++ } ++ AP6210_DEBUG("STA %s : idle time : %d sec, connected time :%d ms\n", ++ bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time, ++ sta->idle * 1000); ++#endif ++ } else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS) { ++ get_pktcnt_t pktcnt; ++ u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID); ++ if (!wl_get_drv_status(wl, CONNECTED, dev) || ++ (dhd_is_associated(dhd, NULL, &err) == FALSE)) { ++ AP6210_ERR("NOT assoc\n"); ++ if (err == -ERESTARTSYS) ++ return err; ++ err = -ENODEV; ++ return err; ++ } ++ if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) { ++ AP6210_ERR("Wrong Mac address: "MACDBG" != "MACDBG"\n", ++ MAC2STRDBG(mac), MAC2STRDBG(curmacp)); ++ } ++ ++ /* Report the current tx rate */ ++ err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false); ++ if (err) { ++ AP6210_ERR("Could not get rate (%d)\n", err); ++ } else { ++ rate = dtoh32(rate); ++ sinfo->filled |= STATION_INFO_TX_BITRATE; ++ sinfo->txrate.legacy = rate * 5; ++ AP6210_DEBUG("Rate %d Mbps\n", (rate / 2)); ++ } ++ ++ memset(&scb_val, 0, sizeof(scb_val)); ++ scb_val.val = 0; ++ err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val, ++ sizeof(scb_val_t), false); ++ if (err) { ++ AP6210_ERR("Could not get rssi (%d)\n", err); ++ goto get_station_err; ++ } ++ rssi = dtoh32(scb_val.val); ++#if defined(RSSIOFFSET) ++ rssi = wl_update_rssi_offset(rssi); ++#endif ++ sinfo->filled |= STATION_INFO_SIGNAL; ++ sinfo->signal = rssi; ++ AP6210_DEBUG("RSSI %d dBm\n", rssi); ++ err = wldev_ioctl(dev, WLC_GET_PKTCNTS, &pktcnt, ++ sizeof(pktcnt), false); ++ if (!err) { ++ sinfo->filled |= (STATION_INFO_RX_PACKETS | ++ STATION_INFO_RX_DROP_MISC | ++ STATION_INFO_TX_PACKETS | ++ STATION_INFO_TX_FAILED); ++ sinfo->rx_packets = pktcnt.rx_good_pkt; ++ sinfo->rx_dropped_misc = pktcnt.rx_bad_pkt; ++ sinfo->tx_packets = pktcnt.tx_good_pkt; ++ sinfo->tx_failed = pktcnt.tx_bad_pkt; ++ } ++get_station_err: ++ if (err && (err != -ERESTARTSYS)) { ++ /* Disconnect due to zero BSSID or error to get RSSI */ ++ AP6210_ERR("force cfg80211_disconnected\n"); ++ wl_clr_drv_status(wl, CONNECTED, dev); ++ cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL); ++ wl_link_down(wl); ++ } ++ } ++ ++ return err; ++} ++ ++/* Function to update sta power save mode for Kernel wifi stack */ ++int wl_cfg80211_update_power_mode(struct net_device *dev) ++{ ++ int pm = -1; ++ int err; ++ ++ err = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), false); ++ if (err || (pm == -1)) { ++ AP6210_ERR("error (%d)\n", err); ++ } else { ++ pm = (pm == PM_OFF) ? false : true; ++ AP6210_DEBUG("%s: %d\n", __func__, pm); ++ if (dev->ieee80211_ptr) ++ dev->ieee80211_ptr->ps = pm; ++ } ++ return err; ++} ++ ++static s32 ++wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, ++ bool enabled, s32 timeout) ++{ ++ s32 pm; ++ s32 err = 0; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct net_info *_net_info = wl_get_netinfo_by_netdev(wl, dev); ++#if !defined(SUPPORT_PM2_ONLY) ++ dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); ++#endif /* (OEM_ANDROID) */ ++ CHECK_SYS_UP(wl); ++ ++ if (wl->p2p_net == dev || _net_info == NULL) { ++ return err; ++ } ++ AP6210_DEBUG("%s: Enter power save enabled %d\n", dev->name, enabled); ++ ++#if !defined(SUPPORT_PM2_ONLY) ++ /* android has special hooks to change pm when kernel suspended */ ++ pm = enabled ? ((dhd->in_suspend) ? PM_MAX : PM_FAST) : PM_OFF; ++#else ++ pm = enabled ? PM_FAST : PM_OFF; ++#endif /* SUPPORT_PM2_ONLY */ ++ ++ if (_net_info->pm_block || wl->vsdb_mode) { ++ /* Do not enable the power save if it is p2p interface or vsdb mode is set */ ++ AP6210_DEBUG("%s:Do not enable the power save for pm_block %d or vsdb_mode %d\n", ++ dev->name, _net_info->pm_block, wl->vsdb_mode); ++ pm = PM_OFF; ++ } ++ pm = htod32(pm); ++ AP6210_DEBUG("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled")); ++ err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true); ++ if (unlikely(err)) { ++ if (err == -ENODEV) ++ AP6210_DEBUG("net_device is not ready yet\n"); ++ else ++ AP6210_ERR("error (%d)\n", err); ++ return err; ++ } ++ return err; ++} ++ ++static __used u32 wl_find_msb(u16 bit16) ++{ ++ u32 ret = 0; ++ ++ if (bit16 & 0xff00) { ++ ret += 8; ++ bit16 >>= 8; ++ } ++ ++ if (bit16 & 0xf0) { ++ ret += 4; ++ bit16 >>= 4; ++ } ++ ++ if (bit16 & 0xc) { ++ ret += 2; ++ bit16 >>= 2; ++ } ++ ++ if (bit16 & 2) ++ ret += bit16 & 2; ++ else if (bit16) ++ ret += bit16; ++ ++ return ret; ++} ++ ++static s32 wl_cfg80211_resume(struct wiphy *wiphy) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++ s32 err = 0; ++ ++ if (unlikely(!wl_get_drv_status(wl, READY, ndev))) { ++ AP6210_DEBUG("device is not ready\n"); ++ return 0; ++ } ++ ++ wl_invoke_iscan(wl); ++ ++ return err; ++} ++ ++static s32 ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) ++wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) ++#else ++wl_cfg80211_suspend(struct wiphy *wiphy) ++#endif ++{ ++#ifdef DHD_CLEAR_ON_SUSPEND ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct net_info *iter, *next; ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++ unsigned long flags; ++ if (unlikely(!wl_get_drv_status(wl, READY, ndev))) { ++ AP6210_DEBUG("device is not ready : status (%d)\n", ++ (int)wl->status); ++ return 0; ++ } ++ for_each_ndev(wl, iter, next) ++ wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev); ++ wl_term_iscan(wl); ++ spin_lock_irqsave(&wl->cfgdrv_lock, flags); ++ if (wl->scan_request) { ++ cfg80211_scan_done(wl->scan_request, true); ++ wl->scan_request = NULL; ++ } ++ for_each_ndev(wl, iter, next) { ++ wl_clr_drv_status(wl, SCANNING, iter->ndev); ++ wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev); ++ } ++ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); ++ for_each_ndev(wl, iter, next) { ++ if (wl_get_drv_status(wl, CONNECTING, iter->ndev)) { ++ wl_bss_connect_done(wl, iter->ndev, NULL, NULL, false); ++ } ++ } ++#endif /* DHD_CLEAR_ON_SUSPEND */ ++ return 0; ++} ++ ++static s32 ++wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list, ++ s32 err) ++{ ++ int i, j; ++ struct wl_priv *wl = wlcfg_drv_priv; ++ struct net_device *primary_dev = wl_to_prmry_ndev(wl); ++ ++ if (!pmk_list) { ++ AP6210_DEBUG("pmk_list is NULL\n"); ++ return -EINVAL; ++ } ++ /* pmk list is supported only for STA interface i.e. primary interface ++ * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init ++ */ ++ if (primary_dev != dev) { ++ AP6210_DEBUG("Not supporting Flushing pmklist on virtual" ++ " interfaces than primary interface\n"); ++ return err; ++ } ++ ++ AP6210_DEBUG("No of elements %d\n", pmk_list->pmkids.npmkid); ++ for (i = 0; i < pmk_list->pmkids.npmkid; i++) { ++ AP6210_DEBUG("PMKID[%d]: %pM =\n", i, ++ &pmk_list->pmkids.pmkid[i].BSSID); ++ for (j = 0; j < WPA2_PMKID_LEN; j++) { ++ AP6210_DEBUG("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]); ++ } ++ } ++ if (likely(!err)) { ++ err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list, ++ sizeof(*pmk_list), wl->ioctl_buf, WLC_IOCTL_MAXLEN, NULL); ++ } ++ ++ return err; ++} ++ ++static s32 ++wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_pmksa *pmksa) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ s32 err = 0; ++ int i; ++ ++ CHECK_SYS_UP(wl); ++ for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++) ++ if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID, ++ ETHER_ADDR_LEN)) ++ break; ++ if (i < WL_NUM_PMKIDS_MAX) { ++ memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid, ++ ETHER_ADDR_LEN); ++ memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid, ++ WPA2_PMKID_LEN); ++ if (i == wl->pmk_list->pmkids.npmkid) ++ wl->pmk_list->pmkids.npmkid++; ++ } else { ++ err = -EINVAL; ++ } ++ AP6210_DEBUG("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n", ++ &wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid - 1].BSSID); ++ for (i = 0; i < WPA2_PMKID_LEN; i++) { ++ AP6210_DEBUG("%02x\n", ++ wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid - 1]. ++ PMKID[i]); ++ } ++ ++ err = wl_update_pmklist(dev, wl->pmk_list, err); ++ ++ return err; ++} ++ ++static s32 ++wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_pmksa *pmksa) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct _pmkid_list pmkid; ++ s32 err = 0; ++ int i; ++ ++ CHECK_SYS_UP(wl); ++ memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN); ++ memcpy(pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN); ++ ++ AP6210_DEBUG("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n", ++ &pmkid.pmkid[0].BSSID); ++ for (i = 0; i < WPA2_PMKID_LEN; i++) { ++ AP6210_DEBUG("%02x\n", pmkid.pmkid[0].PMKID[i]); ++ } ++ ++ for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++) ++ if (!memcmp ++ (pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID, ++ ETHER_ADDR_LEN)) ++ break; ++ ++ if ((wl->pmk_list->pmkids.npmkid > 0) && ++ (i < wl->pmk_list->pmkids.npmkid)) { ++ memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t)); ++ for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) { ++ memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, ++ &wl->pmk_list->pmkids.pmkid[i + 1].BSSID, ++ ETHER_ADDR_LEN); ++ memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, ++ &wl->pmk_list->pmkids.pmkid[i + 1].PMKID, ++ WPA2_PMKID_LEN); ++ } ++ wl->pmk_list->pmkids.npmkid--; ++ } else { ++ err = -EINVAL; ++ } ++ ++ err = wl_update_pmklist(dev, wl->pmk_list, err); ++ ++ return err; ++ ++} ++ ++static s32 ++wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ s32 err = 0; ++ CHECK_SYS_UP(wl); ++ memset(wl->pmk_list, 0, sizeof(*wl->pmk_list)); ++ err = wl_update_pmklist(dev, wl->pmk_list, err); ++ return err; ++ ++} ++ ++static wl_scan_params_t * ++wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size) ++{ ++ wl_scan_params_t *params; ++ int params_size; ++ int num_chans; ++ ++ *out_params_size = 0; ++ ++ /* Our scan params only need space for 1 channel and 0 ssids */ ++ params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16); ++ params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL); ++ if (params == NULL) { ++ AP6210_ERR("%s: mem alloc failed (%d bytes)\n", __func__, params_size); ++ return params; ++ } ++ memset(params, 0, params_size); ++ params->nprobes = nprobes; ++ ++ num_chans = (channel == 0) ? 0 : 1; ++ ++ memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN); ++ params->bss_type = DOT11_BSSTYPE_ANY; ++ params->scan_type = DOT11_SCANTYPE_ACTIVE; ++ params->nprobes = htod32(1); ++ params->active_time = htod32(-1); ++ params->passive_time = htod32(-1); ++ params->home_time = htod32(10); ++ if (channel == -1) ++ params->channel_list[0] = htodchanspec(channel); ++ else ++ params->channel_list[0] = wl_ch_host_to_driver(channel); ++ ++ /* Our scan params have 1 channel and 0 ssids */ ++ params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) | ++ (num_chans & WL_SCAN_PARAMS_COUNT_MASK)); ++ ++ *out_params_size = params_size; /* rtn size to the caller */ ++ return params; ++} ++ ++static s32 ++wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, ++ struct ieee80211_channel * channel, ++ enum nl80211_channel_type channel_type, ++ unsigned int duration, u64 *cookie) ++{ ++ s32 target_channel; ++ u32 id; ++ struct ether_addr primary_mac; ++ struct net_device *ndev = NULL; ++ ++ s32 err = BCME_OK; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ ++ AP6210_DEBUG("Enter, ifindex: %d, channel: %d, duration ms (%d) SCANNING ?? %s \n", ++ dev->ifindex, ieee80211_frequency_to_channel(channel->center_freq), ++ duration, (wl_get_drv_status(wl, SCANNING, ndev)) ? "YES":"NO"); ++ ++ if (wl->p2p_net == dev) { ++ ndev = wl_to_prmry_ndev(wl); ++ } else { ++ ndev = dev; ++ } ++ ++ if (!wl->p2p) { ++ AP6210_ERR("wl->p2p is not initialized\n"); ++ err = BCME_ERROR; ++ goto exit; ++ } ++ ++#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST ++ if (wl_get_drv_status(wl, SCANNING, ndev)) { ++ wl_notify_escan_complete(wl, ndev, true, true); ++ } ++#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ ++ ++ target_channel = ieee80211_frequency_to_channel(channel->center_freq); ++ memcpy(&wl->remain_on_chan, channel, sizeof(struct ieee80211_channel)); ++ wl->remain_on_chan_type = channel_type; ++ id = ++wl->last_roc_id; ++ if (id == 0) ++ id = ++wl->last_roc_id; ++ *cookie = id; ++ ++#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST ++ if (wl_get_drv_status(wl, SCANNING, ndev)) { ++ struct timer_list *_timer; ++ AP6210_DEBUG("scan is running. go to fake listen state\n"); ++ ++ wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev); ++ ++ if (timer_pending(&wl->p2p->listen_timer)) { ++ AP6210_DEBUG("cancel current listen timer \n"); ++ del_timer_sync(&wl->p2p->listen_timer); ++ } ++ ++ _timer = &wl->p2p->listen_timer; ++ wl_clr_p2p_status(wl, LISTEN_EXPIRED); ++ ++ INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration, 0); ++ ++ err = BCME_OK; ++ goto exit; ++ } ++#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ ++ ++#ifdef WL_CFG80211_SYNC_GON ++ if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) { ++ /* do not enter listen mode again if we are in listen mode already for next af. ++ * remain on channel completion will be returned by waiting next af completion. ++ */ ++#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST ++ wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev); ++#else ++ wl_set_drv_status(wl, REMAINING_ON_CHANNEL, ndev); ++#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ ++ goto exit; ++ } ++#endif /* WL_CFG80211_SYNC_GON */ ++ if (wl->p2p && !wl->p2p->on) { ++ /* In case of p2p_listen command, supplicant send remain_on_channel ++ * without turning on P2P ++ */ ++ get_primary_mac(wl, &primary_mac); ++ wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); ++ p2p_on(wl) = true; ++ } ++ ++ if (p2p_is_on(wl)) { ++ err = wl_cfgp2p_enable_discovery(wl, ndev, NULL, 0); ++ if (unlikely(err)) { ++ goto exit; ++ } ++#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST ++ wl_set_drv_status(wl, REMAINING_ON_CHANNEL, ndev); ++#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ ++ err = wl_cfgp2p_discover_listen(wl, target_channel, duration); ++ ++#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST ++ if (err == BCME_OK) { ++ wl_set_drv_status(wl, REMAINING_ON_CHANNEL, ndev); ++ } else { ++ /* if failed, firmware may be internal scanning state. ++ * so other scan request shall not abort it ++ */ ++ wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev); ++ } ++#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ ++ /* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant ++ * and expire timer will send a completion to the upper layer ++ */ ++ err = BCME_OK; ++ } ++ ++exit: ++ if (err == BCME_OK) { ++ AP6210_DEBUG("Success\n"); ++ cfg80211_ready_on_channel(dev, *cookie, channel, ++ channel_type, duration, GFP_KERNEL); ++ } else { ++ AP6210_ERR("Fail to Set (err=%d cookie:%llu)\n", err, *cookie); ++ } ++ return err; ++} ++ ++static s32 ++wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, ++ u64 cookie) ++{ ++ s32 err = 0; ++ AP6210_DEBUG(" enter ) netdev_ifidx: %d \n", dev->ifindex); ++ return err; ++} ++ ++static void ++wl_cfg80211_afx_handler(struct work_struct *work) ++{ ++ struct afx_hdl *afx_instance; ++ struct wl_priv *wl = wlcfg_drv_priv; ++ s32 ret = BCME_OK; ++ ++ afx_instance = container_of(work, struct afx_hdl, work); ++ if (afx_instance != NULL && wl->afx_hdl->is_active) { ++ if (wl->afx_hdl->is_listen && wl->afx_hdl->my_listen_chan) { ++ ret = wl_cfgp2p_discover_listen(wl, wl->afx_hdl->my_listen_chan, ++ (100 * (1 + (random32() % 3)))); /* 100ms ~ 300ms */ ++ } else { ++ ret = wl_cfgp2p_act_frm_search(wl, wl->afx_hdl->dev, ++ wl->afx_hdl->bssidx, wl->afx_hdl->peer_listen_chan); ++ } ++ if (unlikely(ret != BCME_OK)) { ++ AP6210_ERR("ERROR occurred! returned value is (%d)\n", ret); ++ if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) ++ complete(&wl->act_frm_scan); ++ } ++ } ++} ++ ++static s32 ++wl_cfg80211_af_searching_channel(struct wl_priv *wl, struct net_device *dev) ++{ ++ u32 max_retry = WL_CHANNEL_SYNC_RETRY; ++ ++ if (dev == NULL) ++ return -1; ++ ++ AP6210_DEBUG(" enter ) \n"); ++ ++ wl_set_drv_status(wl, FINDING_COMMON_CHANNEL, dev); ++ wl->afx_hdl->is_active = TRUE; ++ ++ /* Loop to wait until we find a peer's channel or the ++ * pending action frame tx is cancelled. ++ */ ++ while ((wl->afx_hdl->retry < max_retry) && ++ (wl->afx_hdl->peer_chan == WL_INVALID)) { ++ wl->afx_hdl->is_listen = FALSE; ++ wl_set_drv_status(wl, SCANNING, dev); ++ AP6210_DEBUG("Scheduling the action frame for sending.. retry %d\n", ++ wl->afx_hdl->retry); ++ /* search peer on peer's listen channel */ ++ schedule_work(&wl->afx_hdl->work); ++ wait_for_completion_timeout(&wl->act_frm_scan, ++ msecs_to_jiffies(MAX_WAIT_TIME)); ++ ++ if ((wl->afx_hdl->peer_chan != WL_INVALID) || ++ !(wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev))) ++ break; ++ ++ if (wl->afx_hdl->my_listen_chan) { ++ AP6210_DEBUG("Scheduling Listen peer in my listen channel = %d\n", ++ wl->afx_hdl->my_listen_chan); ++ /* listen on my listen channel */ ++ wl->afx_hdl->is_listen = TRUE; ++ schedule_work(&wl->afx_hdl->work); ++ wait_for_completion_timeout(&wl->act_frm_scan, ++ msecs_to_jiffies(MAX_WAIT_TIME)); ++ } ++ if (!wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev)) ++ break; ++ wl->afx_hdl->retry++; ++ ++ WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl); ++ } ++ ++ wl->afx_hdl->is_active = FALSE; ++ ++ wl_clr_drv_status(wl, SCANNING, dev); ++ wl_clr_drv_status(wl, FINDING_COMMON_CHANNEL, dev); ++ ++ return (wl->afx_hdl->peer_chan); ++} ++ ++struct p2p_config_af_params { ++ s32 max_tx_retry; /* max tx retry count if tx no ack */ ++ /* To make sure to send successfully action frame, we have to turn off mpc ++ * 0: off, 1: on, (-1): do nothing ++ */ ++ s32 mpc_onoff; ++#ifdef WL_CFG80211_SYNC_GON ++ bool extra_listen; ++#endif ++ bool search_channel; /* 1: search peer's channel to send af */ ++}; ++ ++static s32 ++wl_cfg80211_config_p2p_pub_af_tx(struct wiphy *wiphy, ++ wl_action_frame_t *action_frame, wl_af_params_t *af_params, ++ struct p2p_config_af_params *config_af_params) ++{ ++ s32 err = BCME_OK; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ wifi_p2p_pub_act_frame_t *act_frm = ++ (wifi_p2p_pub_act_frame_t *) (action_frame->data); ++ ++ /* initialize default value */ ++#ifdef WL_CFG80211_SYNC_GON ++ config_af_params->extra_listen = true; ++#endif ++ config_af_params->search_channel = false; ++ config_af_params->max_tx_retry = WL_AF_TX_MAX_RETRY; ++ config_af_params->mpc_onoff = -1; ++ ++ switch (act_frm->subtype) { ++ case P2P_PAF_GON_REQ: { ++ AP6210_DEBUG("P2P: GO_NEG_PHASE status set \n"); ++ wl_set_p2p_status(wl, GO_NEG_PHASE); ++ ++ config_af_params->mpc_onoff = 0; ++ config_af_params->search_channel = true; ++ wl->next_af_subtype = act_frm->subtype + 1; ++ ++ /* increase dwell time to wait for RESP frame */ ++ af_params->dwell_time = WL_MED_DWELL_TIME; ++ ++ break; ++ } ++ case P2P_PAF_GON_RSP: { ++ wl->next_af_subtype = act_frm->subtype + 1; ++ /* increase dwell time to wait for CONF frame */ ++ af_params->dwell_time = WL_MED_DWELL_TIME; ++ break; ++ } ++ case P2P_PAF_GON_CONF: { ++ /* If we reached till GO Neg confirmation reset the filter */ ++ AP6210_DEBUG("P2P: GO_NEG_PHASE status cleared \n"); ++ wl_clr_p2p_status(wl, GO_NEG_PHASE); ++ ++ /* turn on mpc again if go nego is done */ ++ config_af_params->mpc_onoff = 1; ++ ++ /* minimize dwell time */ ++ af_params->dwell_time = WL_MIN_DWELL_TIME; ++ ++#ifdef WL_CFG80211_SYNC_GON ++ config_af_params->extra_listen = false; ++#endif /* WL_CFG80211_SYNC_GON */ ++ break; ++ } ++ case P2P_PAF_INVITE_REQ: { ++ config_af_params->search_channel = true; ++ wl->next_af_subtype = act_frm->subtype + 1; ++ ++ /* increase dwell time */ ++ af_params->dwell_time = WL_MED_DWELL_TIME; ++ break; ++ } ++ case P2P_PAF_INVITE_RSP: ++ /* minimize dwell time */ ++ af_params->dwell_time = WL_MIN_DWELL_TIME; ++#ifdef WL_CFG80211_SYNC_GON ++ config_af_params->extra_listen = false; ++#endif /* WL_CFG80211_SYNC_GON */ ++ break; ++ case P2P_PAF_DEVDIS_REQ: { ++ config_af_params->search_channel = true; ++ ++ wl->next_af_subtype = act_frm->subtype + 1; ++ /* maximize dwell time to wait for RESP frame */ ++ af_params->dwell_time = WL_LONG_DWELL_TIME; ++ break; ++ } ++ case P2P_PAF_DEVDIS_RSP: ++ /* minimize dwell time */ ++ af_params->dwell_time = WL_MIN_DWELL_TIME; ++#ifdef WL_CFG80211_SYNC_GON ++ config_af_params->extra_listen = false; ++#endif /* WL_CFG80211_SYNC_GON */ ++ break; ++ case P2P_PAF_PROVDIS_REQ: { ++ if (IS_PROV_DISC_WITHOUT_GROUP_ID(&act_frm->elts[0], ++ action_frame->len)) { ++ config_af_params->search_channel = true; ++ } ++ ++ config_af_params->mpc_onoff = 0; ++ wl->next_af_subtype = act_frm->subtype + 1; ++ /* increase dwell time to wait for RESP frame */ ++ af_params->dwell_time = WL_MED_DWELL_TIME; ++ break; ++ } ++ case P2P_PAF_PROVDIS_RSP: { ++ wl->next_af_subtype = P2P_PAF_GON_REQ; ++ /* increase dwell time to MED level */ ++ af_params->dwell_time = WL_MED_DWELL_TIME; ++#ifdef WL_CFG80211_SYNC_GON ++ config_af_params->extra_listen = false; ++#endif /* WL_CFG80211_SYNC_GON */ ++ break; ++ } ++ default: ++ AP6210_DEBUG("Unknown p2p pub act frame subtype: %d\n", ++ act_frm->subtype); ++ err = BCME_BADARG; ++ } ++ return err; ++} ++ ++ ++static bool ++wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev, ++ struct net_device *ndev, wl_af_params_t *af_params, ++ wl_action_frame_t *action_frame, u16 action_frame_len, s32 bssidx) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ bool ack = false; ++ u8 category, action; ++ s32 tx_retry; ++ struct p2p_config_af_params config_af_params; ++#ifdef VSDB ++ ulong off_chan_started_jiffies = 0; ++#endif ++ dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); ++ ++ wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len); ++ ++ category = action_frame->data[DOT11_ACTION_CAT_OFF]; ++ action = action_frame->data[DOT11_ACTION_ACT_OFF]; ++ ++ /* initialize variables */ ++ tx_retry = 0; ++ wl->next_af_subtype = P2P_PAF_SUBTYPE_INVALID; ++ config_af_params.max_tx_retry = WL_AF_TX_MAX_RETRY; ++ config_af_params.mpc_onoff = -1; ++ config_af_params.search_channel = false; ++#ifdef WL_CFG80211_SYNC_GON ++ config_af_params.extra_listen = false; ++#endif ++ ++ /* config parameters */ ++ /* Public Action Frame Process - DOT11_ACTION_CAT_PUBLIC */ ++ if (category == DOT11_ACTION_CAT_PUBLIC) { ++ if ((action == P2P_PUB_AF_ACTION) && ++ (action_frame_len >= sizeof(wifi_p2p_pub_act_frame_t))) { ++ /* p2p public action frame process */ ++ if (BCME_OK != wl_cfg80211_config_p2p_pub_af_tx(wiphy, ++ action_frame, af_params, &config_af_params)) { ++ AP6210_DEBUG("Unknown subtype.\n"); ++ } ++ ++ } else if (action_frame_len >= sizeof(wifi_p2psd_gas_pub_act_frame_t)) { ++ /* service discovery process */ ++ if (action == P2PSD_ACTION_ID_GAS_IREQ || ++ action == P2PSD_ACTION_ID_GAS_CREQ) { ++ /* configure service discovery query frame */ ++ ++ config_af_params.search_channel = true; ++ ++ /* save next af suptype to cancel remained dwell time */ ++ wl->next_af_subtype = action + 1; ++ ++ af_params->dwell_time = WL_MED_DWELL_TIME; ++ } else if (action == P2PSD_ACTION_ID_GAS_IRESP || ++ action == P2PSD_ACTION_ID_GAS_CRESP) { ++ /* configure service discovery response frame */ ++ af_params->dwell_time = WL_MIN_DWELL_TIME; ++ } else { ++ AP6210_DEBUG("Unknown action type: %d\n", action); ++ } ++ } else { ++ AP6210_DEBUG("Unknown Frame: category 0x%x, action 0x%x, length %d\n", ++ category, action, action_frame_len); ++ } ++ } else if (category == P2P_AF_CATEGORY) { ++ /* do not configure anything. it will be sent with a default configuration */ ++ } else { ++ AP6210_DEBUG("Unknown Frame: category 0x%x, action 0x%x\n", ++ category, action); ++ if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { ++ wl_clr_drv_status(wl, SENDING_ACT_FRM, dev); ++ return false; ++ } ++ } ++ ++ /* To make sure to send successfully action frame, we have to turn off mpc */ ++ if (config_af_params.mpc_onoff == 0) { ++ wldev_iovar_setint(dev, "mpc", 0); ++ } ++ ++ /* validate channel and p2p ies */ ++ if (config_af_params.search_channel && IS_P2P_SOCIAL(af_params->channel) && ++ wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) { ++ config_af_params.search_channel = true; ++ } else { ++ config_af_params.search_channel = false; ++ } ++ ++#ifdef WL11U ++ if (ndev == wl_to_prmry_ndev(wl)) ++ config_af_params.search_channel = false; ++#endif /* WL11U */ ++ ++#ifdef VSDB ++ /* if connecting on primary iface, sleep for a while before sending af tx for VSDB */ ++ if (wl_get_drv_status(wl, CONNECTING, wl_to_prmry_ndev(wl))) { ++ msleep(50); ++ } ++#endif ++ ++ /* if scan is ongoing, abort current scan. */ ++ if (wl_get_drv_status_all(wl, SCANNING)) { ++ wl_notify_escan_complete(wl, ndev, true, true); ++ } ++ ++ /* set status and destination address before sending af */ ++ if (wl->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) { ++ /* set this status to cancel the remained dwell time in rx process */ ++ wl_set_drv_status(wl, WAITING_NEXT_ACT_FRM, dev); ++ } ++ wl_set_drv_status(wl, SENDING_ACT_FRM, dev); ++ memcpy(wl->afx_hdl->tx_dst_addr.octet, ++ af_params->action_frame.da.octet, ++ sizeof(wl->afx_hdl->tx_dst_addr.octet)); ++ ++ /* save af_params for rx process */ ++ wl->afx_hdl->pending_tx_act_frm = af_params; ++ ++ /* search peer's channel */ ++ if (config_af_params.search_channel) { ++ /* initialize afx_hdl */ ++ wl->afx_hdl->bssidx = wl_cfgp2p_find_idx(wl, dev); ++ wl->afx_hdl->dev = dev; ++ wl->afx_hdl->retry = 0; ++ wl->afx_hdl->peer_chan = WL_INVALID; ++ ++ if (wl_cfg80211_af_searching_channel(wl, dev) == WL_INVALID) { ++ AP6210_ERR("couldn't find peer's channel.\n"); ++ goto exit; ++ } ++ ++ /* Suspend P2P discovery's search-listen to prevent it from ++ * starting a scan or changing the channel. ++ */ ++ wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); ++/* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary */ ++#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST ++ wl_notify_escan_complete(wl, dev, true, true); ++#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ ++ wl_cfgp2p_discover_enable_search(wl, false); ++ ++ /* update channel */ ++ af_params->channel = wl->afx_hdl->peer_chan; ++ } ++ ++#ifdef VSDB ++ off_chan_started_jiffies = jiffies; ++#endif /* VSDB */ ++ ++ /* Now send a tx action frame */ ++ ack = wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx) ? false : true; ++ ++ /* if failed, retry it. tx_retry_max value is configure by .... */ ++ while ((ack == false) && (tx_retry++ < config_af_params.max_tx_retry)) { ++#ifdef VSDB ++ if (af_params->channel) { ++ if (jiffies_to_msecs(jiffies - off_chan_started_jiffies) > ++ OFF_CHAN_TIME_THRESHOLD_MS) { ++ WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl); ++ off_chan_started_jiffies = jiffies; ++ } ++ } ++#endif /* VSDB */ ++ ack = wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx) ? ++ false : true; ++ } ++ if (ack == false) { ++ AP6210_ERR("Failed to send Action Frame(retry %d)\n", tx_retry); ++ } ++exit: ++ /* Clear SENDING_ACT_FRM after all sending af is done */ ++ wl_clr_drv_status(wl, SENDING_ACT_FRM, dev); ++ ++#ifdef WL_CFG80211_SYNC_GON ++ /* WAR: sometimes dongle does not keep the dwell time of 'actframe'. ++ * if we coundn't get the next action response frame and dongle does not keep ++ * the dwell time, go to listen state again to get next action response frame. ++ */ ++ if (ack && config_af_params.extra_listen && ++ wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM) && ++ wl->af_sent_channel == wl->afx_hdl->my_listen_chan) { ++ s32 extar_listen_time; ++ ++ extar_listen_time = af_params->dwell_time - ++ jiffies_to_msecs(jiffies - wl->af_tx_sent_jiffies); ++ ++ if (extar_listen_time > 50) { ++ wl_set_drv_status(wl, WAITING_NEXT_ACT_FRM_LISTEN, dev); ++ AP6210_DEBUG("Wait more time! actual af time:%d," ++ "calculated extar listen:%d\n", ++ af_params->dwell_time, extar_listen_time); ++ if (wl_cfgp2p_discover_listen(wl, wl->af_sent_channel, ++ extar_listen_time + 100) == BCME_OK) { ++ wait_for_completion_timeout(&wl->wait_next_af, ++ msecs_to_jiffies(extar_listen_time + 100 + 300)); ++ } ++ wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM_LISTEN, dev); ++ } ++ } ++#endif /* WL_CFG80211_SYNC_GON */ ++ wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, dev); ++ ++ if (wl->afx_hdl->pending_tx_act_frm) ++ wl->afx_hdl->pending_tx_act_frm = NULL; ++ ++ AP6210_DEBUG("-- sending Action Frame is %s, listen chan: %d\n", ++ (ack) ? "Succeeded!!":"Failed!!", wl->afx_hdl->my_listen_chan); ++ ++ ++ /* if all done, turn mpc on again */ ++ if (config_af_params.mpc_onoff == 1) { ++ wldev_iovar_setint(dev, "mpc", 1); ++ } ++ ++ return ack; ++} ++ ++static s32 ++wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, ++ struct ieee80211_channel *channel, bool offchan, ++ enum nl80211_channel_type channel_type, ++ bool channel_type_valid, unsigned int wait, ++ const u8* buf, size_t len, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) ++ bool no_cck, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) ++ bool dont_wait_for_ack, ++#endif ++ u64 *cookie) ++{ ++ wl_action_frame_t *action_frame; ++ wl_af_params_t *af_params; ++ scb_val_t scb_val; ++ const struct ieee80211_mgmt *mgmt; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct net_device *dev = NULL; ++ s32 err = BCME_OK; ++ s32 bssidx = 0; ++ u32 id; ++ bool ack = false; ++ s8 eabuf[ETHER_ADDR_STR_LEN]; ++ ++ AP6210_DEBUG("Enter \n"); ++ ++ if (ndev == wl->p2p_net) { ++ dev = wl_to_prmry_ndev(wl); ++ } else { ++ /* If TX req is for any valid ifidx. Use as is */ ++ dev = ndev; ++ } ++ ++ /* find bssidx based on ndev */ ++ bssidx = wl_cfgp2p_find_idx(wl, dev); ++ if (bssidx == -1) { ++ ++ AP6210_ERR("Can not find the bssidx for dev( %p )\n", dev); ++ return -ENODEV; ++ } ++ if (p2p_is_on(wl)) { ++ /* Suspend P2P discovery search-listen to prevent it from changing the ++ * channel. ++ */ ++ if ((err = wl_cfgp2p_discover_enable_search(wl, false)) < 0) { ++ AP6210_ERR("Can not disable discovery mode\n"); ++ return -EFAULT; ++ } ++ } ++ *cookie = 0; ++ id = wl->send_action_id++; ++ if (id == 0) ++ id = wl->send_action_id++; ++ *cookie = id; ++ mgmt = (const struct ieee80211_mgmt *)buf; ++ if (ieee80211_is_mgmt(mgmt->frame_control)) { ++ if (ieee80211_is_probe_resp(mgmt->frame_control)) { ++ s32 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN; ++ s32 ie_len = len - ie_offset; ++ if (dev == wl_to_prmry_ndev(wl)) ++ bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); ++ wl_cfgp2p_set_management_ie(wl, dev, bssidx, ++ VNDR_IE_PRBRSP_FLAG, (u8 *)(buf + ie_offset), ie_len); ++ cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); ++ goto exit; ++ } else if (ieee80211_is_disassoc(mgmt->frame_control) || ++ ieee80211_is_deauth(mgmt->frame_control)) { ++ memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN); ++ scb_val.val = mgmt->u.disassoc.reason_code; ++ err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, ++ sizeof(scb_val_t), true); ++ if (err < 0) ++ AP6210_ERR("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err); ++ AP6210_DEBUG("Disconnect STA : %s scb_val.val %d\n", ++ bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf), ++ scb_val.val); ++ wl_delay(400); ++ cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); ++ goto exit; ++ ++ } else if (ieee80211_is_action(mgmt->frame_control)) { ++ /* Abort the dwell time of any previous off-channel ++ * action frame that may be still in effect. Sending ++ * off-channel action frames relies on the driver's ++ * scan engine. If a previous off-channel action frame ++ * tx is still in progress (including the dwell time), ++ * then this new action frame will not be sent out. ++ */ ++/* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary. ++ * And previous off-channel action frame must be ended before new af tx. ++ */ ++#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST ++ wl_notify_escan_complete(wl, dev, true, true); ++#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ ++ } ++ ++ } else { ++ AP6210_ERR("Driver only allows MGMT packet type\n"); ++ goto exit; ++ } ++ ++ af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL); ++ ++ if (af_params == NULL) ++ { ++ AP6210_ERR("unable to allocate frame\n"); ++ return -ENOMEM; ++ } ++ ++ action_frame = &af_params->action_frame; ++ ++ /* Add the packet Id */ ++ action_frame->packetId = *cookie; ++ AP6210_DEBUG("action frame %d\n", action_frame->packetId); ++ /* Add BSSID */ ++ memcpy(&action_frame->da, &mgmt->da[0], ETHER_ADDR_LEN); ++ memcpy(&af_params->BSSID, &mgmt->bssid[0], ETHER_ADDR_LEN); ++ ++ /* Add the length exepted for 802.11 header */ ++ action_frame->len = len - DOT11_MGMT_HDR_LEN; ++ AP6210_DEBUG("action_frame->len: %d\n", action_frame->len); ++ ++ /* Add the channel */ ++ af_params->channel = ++ ieee80211_frequency_to_channel(channel->center_freq); ++ ++ /* Save listen_chan for searching common channel */ ++ wl->afx_hdl->peer_listen_chan = af_params->channel; ++ AP6210_DEBUG("channel from upper layer %d\n", wl->afx_hdl->peer_listen_chan); ++ ++ /* Add the default dwell time ++ * Dwell time to stay off-channel to wait for a response action frame ++ * after transmitting an GO Negotiation action frame ++ */ ++ af_params->dwell_time = WL_DWELL_TIME; ++ ++ memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len); ++ ++ ack = wl_cfg80211_send_action_frame(wiphy, dev, ndev, af_params, ++ action_frame, action_frame->len, bssidx); ++ ++ cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL); ++ ++ kfree(af_params); ++exit: ++ return err; ++} ++ ++ ++static void ++wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, struct net_device *dev, ++ u16 frame_type, bool reg) ++{ ++ ++ AP6210_DEBUG("%s: frame_type: %x, reg: %d\n", __func__, frame_type, reg); ++ ++ if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ)) ++ return; ++ ++ return; ++} ++ ++ ++static s32 ++wl_cfg80211_change_bss(struct wiphy *wiphy, ++ struct net_device *dev, ++ struct bss_parameters *params) ++{ ++ if (params->use_cts_prot >= 0) { ++ } ++ ++ if (params->use_short_preamble >= 0) { ++ } ++ ++ if (params->use_short_slot_time >= 0) { ++ } ++ ++ if (params->basic_rates) { ++ } ++ ++ if (params->ap_isolate >= 0) { ++ } ++ ++ if (params->ht_opmode >= 0) { ++ } ++ ++ return 0; ++} ++ ++static s32 ++wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, ++ struct ieee80211_channel *chan, ++ enum nl80211_channel_type channel_type) ++{ ++ s32 _chan; ++ chanspec_t chspec = 0; ++ chanspec_t fw_chspec = 0; ++ u32 bw = WL_CHANSPEC_BW_20; ++ ++ s32 err = BCME_OK; ++ s32 bw_cap = 0; ++ struct { ++ u32 band; ++ u32 bw_cap; ++ } param = {0, 0}; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ ++ if (wl->p2p_net == dev) { ++ dev = wl_to_prmry_ndev(wl); ++ } ++ _chan = ieee80211_frequency_to_channel(chan->center_freq); ++ AP6210_ERR("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n", ++ dev->ifindex, channel_type, _chan); ++ ++ ++ if (chan->band == IEEE80211_BAND_5GHZ) { ++ param.band = WLC_BAND_5G; ++ err = wldev_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param), ++ wl->ioctl_buf, WLC_IOCTL_SMLEN, &wl->ioctl_buf_sync); ++ if (err) { ++ if (err != BCME_UNSUPPORTED) { ++ AP6210_ERR("bw_cap failed, %d\n", err); ++ return err; ++ } else { ++ err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap); ++ if (err) { ++ AP6210_ERR("error get mimo_bw_cap (%d)\n", err); ++ } ++ if (bw_cap != WLC_N_BW_20ALL) ++ bw = WL_CHANSPEC_BW_40; ++ } ++ } else { ++ if (WL_BW_CAP_80MHZ(wl->ioctl_buf[0])) ++ bw = WL_CHANSPEC_BW_80; ++ else if (WL_BW_CAP_40MHZ(wl->ioctl_buf[0])) ++ bw = WL_CHANSPEC_BW_40; ++ else ++ bw = WL_CHANSPEC_BW_20; ++ ++ } ++ ++ } else if (chan->band == IEEE80211_BAND_2GHZ) ++ bw = WL_CHANSPEC_BW_20; ++set_channel: ++ chspec = wf_channel2chspec(_chan, bw); ++ if (wf_chspec_valid(chspec)) { ++ fw_chspec = wl_chspec_host_to_driver(chspec); ++ if (fw_chspec != INVCHANSPEC) { ++ if ((err = wldev_iovar_setint(dev, "chanspec", ++ fw_chspec)) == BCME_BADCHAN) { ++ if (bw == WL_CHANSPEC_BW_80) ++ goto change_bw; ++ err = wldev_ioctl(dev, WLC_SET_CHANNEL, ++ &_chan, sizeof(_chan), true); ++ if (err < 0) { ++ AP6210_ERR("WLC_SET_CHANNEL error %d" ++ "chip may not be supporting this channel\n", err); ++ } ++ } else if (err) { ++ AP6210_ERR("failed to set chanspec error %d\n", err); ++ } ++ } else { ++ AP6210_ERR("failed to convert host chanspec to fw chanspec\n"); ++ err = BCME_ERROR; ++ } ++ } else { ++change_bw: ++ if (bw == WL_CHANSPEC_BW_80) ++ bw = WL_CHANSPEC_BW_40; ++ else if (bw == WL_CHANSPEC_BW_40) ++ bw = WL_CHANSPEC_BW_20; ++ else ++ bw = 0; ++ if (bw) ++ goto set_channel; ++ AP6210_ERR("Invalid chanspec 0x%x\n", chspec); ++ err = BCME_ERROR; ++ } ++ return err; ++} ++ ++static s32 ++wl_validate_opensecurity(struct net_device *dev, s32 bssidx) ++{ ++ s32 err = BCME_OK; ++ ++ /* set auth */ ++ err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx); ++ if (err < 0) { ++ AP6210_ERR("auth error %d\n", err); ++ return BCME_ERROR; ++ } ++ /* set wsec */ ++ err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx); ++ if (err < 0) { ++ AP6210_ERR("wsec error %d\n", err); ++ return BCME_ERROR; ++ } ++ /* set upper-layer auth */ ++ err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", WPA_AUTH_NONE, bssidx); ++ if (err < 0) { ++ AP6210_ERR("wpa_auth error %d\n", err); ++ return BCME_ERROR; ++ } ++ ++ return 0; ++} ++ ++static s32 ++wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx) ++{ ++ s32 len = 0; ++ s32 err = BCME_OK; ++ u16 auth = 0; /* d11 open authentication */ ++ u32 wsec; ++ u32 pval = 0; ++ u32 gval = 0; ++ u32 wpa_auth = 0; ++ wpa_suite_mcast_t *mcast; ++ wpa_suite_ucast_t *ucast; ++ wpa_suite_auth_key_mgmt_t *mgmt; ++ ++ u16 suite_count; ++ u8 rsn_cap[2]; ++ u32 wme_bss_disable; ++ ++ if (wpa2ie == NULL) ++ goto exit; ++ ++ AP6210_DEBUG("Enter \n"); ++ len = wpa2ie->len; ++ /* check the mcast cipher */ ++ mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN]; ++ switch (mcast->type) { ++ case WPA_CIPHER_NONE: ++ gval = 0; ++ break; ++ case WPA_CIPHER_WEP_40: ++ case WPA_CIPHER_WEP_104: ++ gval = WEP_ENABLED; ++ break; ++ case WPA_CIPHER_TKIP: ++ gval = TKIP_ENABLED; ++ break; ++ case WPA_CIPHER_AES_CCM: ++ gval = AES_ENABLED; ++ break; ++#ifdef BCMWAPI_WPI ++ case WAPI_CIPHER_SMS4: ++ gval = SMS4_ENABLED; ++ break; ++#endif ++ default: ++ AP6210_ERR("No Security Info\n"); ++ break; ++ } ++ if ((len -= WPA_SUITE_LEN) <= 0) ++ return BCME_BADLEN; ++ ++ /* check the unicast cipher */ ++ ucast = (wpa_suite_ucast_t *)&mcast[1]; ++ suite_count = ltoh16_ua(&ucast->count); ++ switch (ucast->list[0].type) { ++ case WPA_CIPHER_NONE: ++ pval = 0; ++ break; ++ case WPA_CIPHER_WEP_40: ++ case WPA_CIPHER_WEP_104: ++ pval = WEP_ENABLED; ++ break; ++ case WPA_CIPHER_TKIP: ++ pval = TKIP_ENABLED; ++ break; ++ case WPA_CIPHER_AES_CCM: ++ pval = AES_ENABLED; ++ break; ++#ifdef BCMWAPI_WPI ++ case WAPI_CIPHER_SMS4: ++ pval = SMS4_ENABLED; ++ break; ++#endif ++ default: ++ AP6210_ERR("No Security Info\n"); ++ } ++ if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0) ++ return BCME_BADLEN; ++ ++ /* FOR WPS , set SEC_OW_ENABLED */ ++ wsec = (pval | gval | SES_OW_ENABLED); ++ /* check the AKM */ ++ mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count]; ++ suite_count = ltoh16_ua(&mgmt->count); ++ switch (mgmt->list[0].type) { ++ case RSN_AKM_NONE: ++ wpa_auth = WPA_AUTH_NONE; ++ break; ++ case RSN_AKM_UNSPECIFIED: ++ wpa_auth = WPA2_AUTH_UNSPECIFIED; ++ break; ++ case RSN_AKM_PSK: ++ wpa_auth = WPA2_AUTH_PSK; ++ break; ++ default: ++ AP6210_ERR("No Key Mgmt Info\n"); ++ } ++ ++ if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) { ++ rsn_cap[0] = *(u8 *)&mgmt->list[suite_count]; ++ rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1); ++ ++ if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) { ++ wme_bss_disable = 0; ++ } else { ++ wme_bss_disable = 1; ++ } ++ ++ /* set wme_bss_disable to sync RSN Capabilities */ ++ err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx); ++ if (err < 0) { ++ AP6210_ERR("wme_bss_disable error %d\n", err); ++ return BCME_ERROR; ++ } ++ } else { ++ AP6210_DEBUG("There is no RSN Capabilities. remained len %d\n", len); ++ } ++ ++ /* set auth */ ++ err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx); ++ if (err < 0) { ++ AP6210_ERR("auth error %d\n", err); ++ return BCME_ERROR; ++ } ++ /* set wsec */ ++ err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx); ++ if (err < 0) { ++ AP6210_ERR("wsec error %d\n", err); ++ return BCME_ERROR; ++ } ++ /* set upper-layer auth */ ++ err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx); ++ if (err < 0) { ++ AP6210_ERR("wpa_auth error %d\n", err); ++ return BCME_ERROR; ++ } ++exit: ++ return 0; ++} ++ ++static s32 ++wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx) ++{ ++ wpa_suite_mcast_t *mcast; ++ wpa_suite_ucast_t *ucast; ++ wpa_suite_auth_key_mgmt_t *mgmt; ++ u16 auth = 0; /* d11 open authentication */ ++ u16 count; ++ s32 err = BCME_OK; ++ s32 len = 0; ++ u32 i; ++ u32 wsec; ++ u32 pval = 0; ++ u32 gval = 0; ++ u32 wpa_auth = 0; ++ u32 tmp = 0; ++ ++ if (wpaie == NULL) ++ goto exit; ++ AP6210_DEBUG("Enter \n"); ++ len = wpaie->length; /* value length */ ++ len -= WPA_IE_TAG_FIXED_LEN; ++ /* check for multicast cipher suite */ ++ if (len < WPA_SUITE_LEN) { ++ AP6210_DEBUG("no multicast cipher suite\n"); ++ goto exit; ++ } ++ ++ /* pick up multicast cipher */ ++ mcast = (wpa_suite_mcast_t *)&wpaie[1]; ++ len -= WPA_SUITE_LEN; ++ if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) { ++ if (IS_WPA_CIPHER(mcast->type)) { ++ tmp = 0; ++ switch (mcast->type) { ++ case WPA_CIPHER_NONE: ++ tmp = 0; ++ break; ++ case WPA_CIPHER_WEP_40: ++ case WPA_CIPHER_WEP_104: ++ tmp = WEP_ENABLED; ++ break; ++ case WPA_CIPHER_TKIP: ++ tmp = TKIP_ENABLED; ++ break; ++ case WPA_CIPHER_AES_CCM: ++ tmp = AES_ENABLED; ++ break; ++ default: ++ AP6210_ERR("No Security Info\n"); ++ } ++ gval |= tmp; ++ } ++ } ++ /* Check for unicast suite(s) */ ++ if (len < WPA_IE_SUITE_COUNT_LEN) { ++ AP6210_DEBUG("no unicast suite\n"); ++ goto exit; ++ } ++ /* walk thru unicast cipher list and pick up what we recognize */ ++ ucast = (wpa_suite_ucast_t *)&mcast[1]; ++ count = ltoh16_ua(&ucast->count); ++ len -= WPA_IE_SUITE_COUNT_LEN; ++ for (i = 0; i < count && len >= WPA_SUITE_LEN; ++ i++, len -= WPA_SUITE_LEN) { ++ if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) { ++ if (IS_WPA_CIPHER(ucast->list[i].type)) { ++ tmp = 0; ++ switch (ucast->list[i].type) { ++ case WPA_CIPHER_NONE: ++ tmp = 0; ++ break; ++ case WPA_CIPHER_WEP_40: ++ case WPA_CIPHER_WEP_104: ++ tmp = WEP_ENABLED; ++ break; ++ case WPA_CIPHER_TKIP: ++ tmp = TKIP_ENABLED; ++ break; ++ case WPA_CIPHER_AES_CCM: ++ tmp = AES_ENABLED; ++ break; ++ default: ++ AP6210_ERR("No Security Info\n"); ++ } ++ pval |= tmp; ++ } ++ } ++ } ++ len -= (count - i) * WPA_SUITE_LEN; ++ /* Check for auth key management suite(s) */ ++ if (len < WPA_IE_SUITE_COUNT_LEN) { ++ AP6210_DEBUG(" no auth key mgmt suite\n"); ++ goto exit; ++ } ++ /* walk thru auth management suite list and pick up what we recognize */ ++ mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count]; ++ count = ltoh16_ua(&mgmt->count); ++ len -= WPA_IE_SUITE_COUNT_LEN; ++ for (i = 0; i < count && len >= WPA_SUITE_LEN; ++ i++, len -= WPA_SUITE_LEN) { ++ if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) { ++ if (IS_WPA_AKM(mgmt->list[i].type)) { ++ tmp = 0; ++ switch (mgmt->list[i].type) { ++ case RSN_AKM_NONE: ++ tmp = WPA_AUTH_NONE; ++ break; ++ case RSN_AKM_UNSPECIFIED: ++ tmp = WPA_AUTH_UNSPECIFIED; ++ break; ++ case RSN_AKM_PSK: ++ tmp = WPA_AUTH_PSK; ++ break; ++ default: ++ AP6210_ERR("No Key Mgmt Info\n"); ++ } ++ wpa_auth |= tmp; ++ } ++ } ++ ++ } ++ /* FOR WPS , set SEC_OW_ENABLED */ ++ wsec = (pval | gval | SES_OW_ENABLED); ++ /* set auth */ ++ err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx); ++ if (err < 0) { ++ AP6210_ERR("auth error %d\n", err); ++ return BCME_ERROR; ++ } ++ /* set wsec */ ++ err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx); ++ if (err < 0) { ++ AP6210_ERR("wsec error %d\n", err); ++ return BCME_ERROR; ++ } ++ /* set upper-layer auth */ ++ err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx); ++ if (err < 0) { ++ AP6210_ERR("wpa_auth error %d\n", err); ++ return BCME_ERROR; ++ } ++exit: ++ return 0; ++} ++ ++static s32 ++wl_cfg80211_bcn_validate_sec( ++ struct net_device *dev, ++ struct parsed_ies *ies, ++ u32 dev_role, ++ s32 bssidx) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ ++ if (dev_role == NL80211_IFTYPE_P2P_GO && (ies->wpa2_ie)) { ++ /* For P2P GO, the sec type is WPA2-PSK */ ++ AP6210_DEBUG("P2P GO: validating wpa2_ie"); ++ if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0) ++ return BCME_ERROR; ++ ++ } else if (dev_role == NL80211_IFTYPE_AP) { ++ ++ AP6210_DEBUG("SoftAP: validating security"); ++ /* If wpa2_ie or wpa_ie is present validate it */ ++ if ((ies->wpa2_ie || ies->wpa_ie) && ++ ((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 || ++ wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) { ++ wl->ap_info->security_mode = false; ++ return BCME_ERROR; ++ } ++ ++ wl->ap_info->security_mode = true; ++ if (wl->ap_info->rsn_ie) { ++ kfree(wl->ap_info->rsn_ie); ++ wl->ap_info->rsn_ie = NULL; ++ } ++ if (wl->ap_info->wpa_ie) { ++ kfree(wl->ap_info->wpa_ie); ++ wl->ap_info->wpa_ie = NULL; ++ } ++ if (wl->ap_info->wps_ie) { ++ kfree(wl->ap_info->wps_ie); ++ wl->ap_info->wps_ie = NULL; ++ } ++ if (ies->wpa_ie != NULL) { ++ /* WPAIE */ ++ wl->ap_info->rsn_ie = NULL; ++ wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie, ++ ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN, ++ GFP_KERNEL); ++ } else if (ies->wpa2_ie != NULL) { ++ /* RSNIE */ ++ wl->ap_info->wpa_ie = NULL; ++ wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie, ++ ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN, ++ GFP_KERNEL); ++ } ++ ++ if (!ies->wpa2_ie && !ies->wpa_ie) { ++ wl_validate_opensecurity(dev, bssidx); ++ wl->ap_info->security_mode = false; ++ } ++ ++ if (ies->wps_ie) { ++ wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL); ++ } ++ } ++ ++ return 0; ++ ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++static s32 wl_cfg80211_bcn_set_params( ++ struct cfg80211_ap_settings *info, ++ struct net_device *dev, ++ u32 dev_role, s32 bssidx) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ s32 err = BCME_OK; ++ ++ AP6210_DEBUG("interval (%d) \ndtim_period (%d) \n", ++ info->beacon_interval, info->dtim_period); ++ ++ if (info->beacon_interval) { ++ if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD, ++ &info->beacon_interval, sizeof(s32), true)) < 0) { ++ AP6210_ERR("Beacon Interval Set Error, %d\n", err); ++ return err; ++ } ++ } ++ ++ if (info->dtim_period) { ++ if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD, ++ &info->dtim_period, sizeof(s32), true)) < 0) { ++ AP6210_ERR("DTIM Interval Set Error, %d\n", err); ++ return err; ++ } ++ } ++ ++ if ((info->ssid) && (info->ssid_len > 0) && ++ (info->ssid_len <= 32)) { ++ AP6210_DEBUG("SSID (%s) len:%d \n", info->ssid, info->ssid_len); ++ if (dev_role == NL80211_IFTYPE_AP) { ++ /* Store the hostapd SSID */ ++ memset(wl->hostapd_ssid.SSID, 0x00, 32); ++ memcpy(wl->hostapd_ssid.SSID, info->ssid, info->ssid_len); ++ wl->hostapd_ssid.SSID_len = info->ssid_len; ++ } else { ++ /* P2P GO */ ++ memset(wl->p2p->ssid.SSID, 0x00, 32); ++ memcpy(wl->p2p->ssid.SSID, info->ssid, info->ssid_len); ++ wl->p2p->ssid.SSID_len = info->ssid_len; ++ } ++ } ++ ++ if (info->hidden_ssid) { ++ if ((err = wldev_iovar_setint(dev, "closednet", 1)) < 0) ++ AP6210_ERR("failed to set hidden : %d\n", err); ++ AP6210_DEBUG("hidden_ssid_enum_val: %d \n", info->hidden_ssid); ++ } ++ ++ return err; ++} ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */ ++ ++static s32 ++wl_cfg80211_parse_ies(u8 *ptr, u32 len, struct parsed_ies *ies) ++{ ++ s32 err = BCME_OK; ++ ++ memset(ies, 0, sizeof(struct parsed_ies)); ++ ++ /* find the WPSIE */ ++ if ((ies->wps_ie = wl_cfgp2p_find_wpsie(ptr, len)) != NULL) { ++ AP6210_DEBUG("WPSIE in beacon \n"); ++ ies->wps_ie_len = ies->wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN; ++ } else { ++ AP6210_ERR("No WPSIE in beacon \n"); ++ } ++ ++ /* find the RSN_IE */ ++ if ((ies->wpa2_ie = bcm_parse_tlvs(ptr, len, ++ DOT11_MNG_RSN_ID)) != NULL) { ++ AP6210_DEBUG(" WPA2 IE found\n"); ++ ies->wpa2_ie_len = ies->wpa2_ie->len; ++ } ++ ++ /* find the WPA_IE */ ++ if ((ies->wpa_ie = wl_cfgp2p_find_wpaie(ptr, len)) != NULL) { ++ AP6210_DEBUG(" WPA found\n"); ++ ies->wpa_ie_len = ies->wpa_ie->length; ++ } ++ ++ return err; ++ ++} ++ ++static s32 ++wl_cfg80211_bcn_bringup_ap( ++ struct net_device *dev, ++ struct parsed_ies *ies, ++ u32 dev_role, s32 bssidx) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ struct wl_join_params join_params; ++ bool is_bssup = false; ++ s32 infra = 1; ++ s32 join_params_size = 0; ++ s32 ap = 1; ++ s32 err = BCME_OK; ++ ++ AP6210_DEBUG("Enter dev_role: %d\n", dev_role); ++ ++ /* Common code for SoftAP and P2P GO */ ++ wldev_iovar_setint(dev, "mpc", 0); ++ ++ if (dev_role == NL80211_IFTYPE_P2P_GO) { ++ is_bssup = wl_cfgp2p_bss_isup(dev, bssidx); ++ if (!is_bssup && (ies->wpa2_ie != NULL)) { ++ ++ err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true); ++ if (err < 0) { ++ AP6210_ERR("SET INFRA error %d\n", err); ++ goto exit; ++ } ++ ++ err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p->ssid, ++ sizeof(wl->p2p->ssid), wl->ioctl_buf, WLC_IOCTL_MAXLEN, ++ bssidx, &wl->ioctl_buf_sync); ++ if (err < 0) { ++ AP6210_ERR("GO SSID setting error %d\n", err); ++ goto exit; ++ } ++ ++ if ((err = wl_cfgp2p_bss(wl, dev, bssidx, 1)) < 0) { ++ AP6210_ERR("GO Bring up error %d\n", err); ++ goto exit; ++ } ++ } else ++ AP6210_DEBUG("Bss is already up\n"); ++ } else if ((dev_role == NL80211_IFTYPE_AP) && ++ (wl_get_drv_status(wl, AP_CREATING, dev))) { ++ /* Device role SoftAP */ ++ err = wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), true); ++ if (err < 0) { ++ AP6210_ERR("WLC_DOWN error %d\n", err); ++ goto exit; ++ } ++ err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true); ++ if (err < 0) { ++ AP6210_ERR("SET INFRA error %d\n", err); ++ goto exit; ++ } ++ if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) { ++ AP6210_ERR("setting AP mode failed %d \n", err); ++ goto exit; ++ } ++ ++ err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true); ++ if (unlikely(err)) { ++ AP6210_ERR("WLC_UP error (%d)\n", err); ++ goto exit; ++ } ++ ++ memset(&join_params, 0, sizeof(join_params)); ++ /* join parameters starts with ssid */ ++ join_params_size = sizeof(join_params.ssid); ++ memcpy(join_params.ssid.SSID, wl->hostapd_ssid.SSID, ++ wl->hostapd_ssid.SSID_len); ++ join_params.ssid.SSID_len = htod32(wl->hostapd_ssid.SSID_len); ++ ++ /* create softap */ ++ if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, ++ join_params_size, true)) == 0) { ++ AP6210_DEBUG("SoftAP set SSID (%s) success\n", join_params.ssid.SSID); ++ wl_clr_drv_status(wl, AP_CREATING, dev); ++ wl_set_drv_status(wl, AP_CREATED, dev); ++ } ++ } ++ ++ ++exit: ++ return err; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++s32 ++wl_cfg80211_parse_set_ies( ++ struct net_device *dev, ++ struct cfg80211_beacon_data *info, ++ struct parsed_ies *ies, ++ u32 dev_role, ++ s32 bssidx) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ struct parsed_ies prb_ies; ++ s32 err = BCME_OK; ++ ++ memset(ies, 0, sizeof(struct parsed_ies)); ++ memset(&prb_ies, 0, sizeof(struct parsed_ies)); ++ ++ /* Parse Beacon IEs */ ++ if (wl_cfg80211_parse_ies((u8 *)info->tail, ++ info->tail_len, ies) < 0) { ++ AP6210_ERR("Beacon get IEs failed \n"); ++ err = -EINVAL; ++ goto fail; ++ } ++ ++ /* Set Beacon IEs to FW */ ++ if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx, ++ VNDR_IE_BEACON_FLAG, (u8 *)info->tail, ++ info->tail_len)) < 0) { ++ AP6210_ERR("Set Beacon IE Failed \n"); ++ } else { ++ AP6210_DEBUG("Applied Vndr IEs for Beacon \n"); ++ } ++ ++ /* Parse Probe Response IEs */ ++ if (wl_cfg80211_parse_ies((u8 *)info->proberesp_ies, ++ info->proberesp_ies_len, &prb_ies) < 0) { ++ AP6210_ERR("PRB RESP get IEs failed \n"); ++ err = -EINVAL; ++ goto fail; ++ } ++ ++ /* Set Probe Response IEs to FW */ ++ if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx, ++ VNDR_IE_PRBRSP_FLAG, (u8 *)info->proberesp_ies, ++ info->proberesp_ies_len)) < 0) { ++ AP6210_ERR("Set Probe Resp IE Failed \n"); ++ } else { ++ AP6210_DEBUG("Applied Vndr IEs for Probe Resp \n"); ++ } ++ ++fail: ++ ++ return err; ++} ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */ ++ ++static s32 wl_cfg80211_hostapd_sec( ++ struct net_device *dev, ++ struct parsed_ies *ies, ++ s32 bssidx) ++{ ++ bool update_bss = 0; ++ struct wl_priv *wl = wlcfg_drv_priv; ++ ++ ++ if (ies->wps_ie) { ++ if (wl->ap_info->wps_ie && ++ memcmp(wl->ap_info->wps_ie, ies->wps_ie, ies->wps_ie_len)) { ++ AP6210_DEBUG(" WPS IE is changed\n"); ++ kfree(wl->ap_info->wps_ie); ++ wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL); ++ } else if (wl->ap_info->wps_ie == NULL) { ++ AP6210_DEBUG(" WPS IE is added\n"); ++ wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL); ++ } ++ if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) { ++ if (!wl->ap_info->security_mode) { ++ /* change from open mode to security mode */ ++ update_bss = true; ++ if (ies->wpa_ie != NULL) { ++ wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie, ++ ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN, ++ GFP_KERNEL); ++ } else { ++ wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie, ++ ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN, ++ GFP_KERNEL); ++ } ++ } else if (wl->ap_info->wpa_ie) { ++ /* change from WPA2 mode to WPA mode */ ++ if (ies->wpa_ie != NULL) { ++ update_bss = true; ++ kfree(wl->ap_info->rsn_ie); ++ wl->ap_info->rsn_ie = NULL; ++ wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie, ++ ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN, ++ GFP_KERNEL); ++ } else if (memcmp(wl->ap_info->rsn_ie, ++ ies->wpa2_ie, ies->wpa2_ie->len ++ + WPA_RSN_IE_TAG_FIXED_LEN)) { ++ update_bss = true; ++ kfree(wl->ap_info->rsn_ie); ++ wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie, ++ ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN, ++ GFP_KERNEL); ++ wl->ap_info->wpa_ie = NULL; ++ } ++ } ++ if (update_bss) { ++ wl->ap_info->security_mode = true; ++ wl_cfgp2p_bss(wl, dev, bssidx, 0); ++ if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 || ++ wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0) { ++ return BCME_ERROR; ++ } ++ wl_cfgp2p_bss(wl, dev, bssidx, 1); ++ } ++ } ++ } else { ++ AP6210_ERR("No WPSIE in beacon \n"); ++ } ++ return 0; ++} ++ ++#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ ++ 2, 0)) ++static s32 ++wl_cfg80211_del_station( ++ struct wiphy *wiphy, ++ struct net_device *ndev, ++ u8* mac_addr) ++{ ++ struct net_device *dev; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ scb_val_t scb_val; ++ s8 eabuf[ETHER_ADDR_STR_LEN]; ++ ++ AP6210_DEBUG("Entry\n"); ++ if (mac_addr == NULL) { ++ AP6210_DEBUG("mac_addr is NULL ignore it\n"); ++ return 0; ++ } ++ ++ if (ndev == wl->p2p_net) { ++ dev = wl_to_prmry_ndev(wl); ++ } else { ++ dev = ndev; ++ } ++ ++ if (p2p_is_on(wl)) { ++ /* Suspend P2P discovery search-listen to prevent it from changing the ++ * channel. ++ */ ++ if ((wl_cfgp2p_discover_enable_search(wl, false)) < 0) { ++ AP6210_ERR("Can not disable discovery mode\n"); ++ return -EFAULT; ++ } ++ } ++ ++ memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN); ++ scb_val.val = DOT11_RC_DEAUTH_LEAVING; ++ if (wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, ++ sizeof(scb_val_t), true)) ++ AP6210_ERR("WLC_SCB_DEAUTHENTICATE_FOR_REASON failed\n"); ++ AP6210_DEBUG("Disconnect STA : %s scb_val.val %d\n", ++ bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf), ++ scb_val.val); ++ wl_delay(400); ++ return 0; ++} ++#endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */ ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++static s32 ++wl_cfg80211_start_ap( ++ struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_ap_settings *info) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ s32 err = BCME_OK; ++ struct parsed_ies ies; ++ s32 bssidx = 0; ++ u32 dev_role = 0; ++ ++ AP6210_DEBUG("Enter \n"); ++ if (dev == wl_to_prmry_ndev(wl)) { ++ AP6210_DEBUG("Start AP req on primary iface: Softap\n"); ++ dev_role = NL80211_IFTYPE_AP; ++ } else if (dev == wl->p2p_net) { ++ /* Group Add request on p2p0 */ ++ AP6210_DEBUG("Start AP req on P2P iface: GO\n"); ++ dev = wl_to_prmry_ndev(wl); ++ dev_role = NL80211_IFTYPE_P2P_GO; ++ } ++ ++ bssidx = wl_cfgp2p_find_idx(wl, dev); ++ if (p2p_is_on(wl) && ++ (bssidx == wl_to_p2p_bss_bssidx(wl, ++ P2PAPI_BSSCFG_CONNECTION))) { ++ dev_role = NL80211_IFTYPE_P2P_GO; ++ AP6210_DEBUG("Start AP req on P2P connection iface\n"); ++ } ++ ++ if ((err = wl_cfg80211_bcn_set_params(info, dev, ++ dev_role, bssidx)) < 0) { ++ AP6210_ERR("Beacon params set failed \n"); ++ goto fail; ++ } ++ ++ /* Set IEs to FW */ ++ if ((err = wl_cfg80211_parse_set_ies(dev, &info->beacon, ++ &ies, dev_role, bssidx) < 0)) { ++ AP6210_ERR("Set IEs failed \n"); ++ goto fail; ++ } ++ ++ if ((wl_cfg80211_bcn_validate_sec(dev, &ies, ++ dev_role, bssidx)) < 0) ++ { ++ AP6210_ERR("Beacon set security failed \n"); ++ goto fail; ++ } ++ ++ if ((err = wl_cfg80211_bcn_bringup_ap(dev, &ies, ++ dev_role, bssidx)) < 0) { ++ AP6210_ERR("Beacon bring up AP/GO failed \n"); ++ goto fail; ++ } ++ ++ AP6210_DEBUG("** AP/GO Created **\n"); ++ ++fail: ++ if (err) { ++ AP6210_ERR("ADD/SET beacon failed\n"); ++ wldev_iovar_setint(dev, "mpc", 1); ++ } ++ ++ return err; ++} ++ ++static s32 ++wl_cfg80211_stop_ap( ++ struct wiphy *wiphy, ++ struct net_device *dev) ++{ ++ int err = 0; ++ u32 dev_role = 0; ++ int infra = 0; ++ int ap = 0; ++ s32 bssidx = 0; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ ++ AP6210_DEBUG("Enter \n"); ++ if (dev == wl_to_prmry_ndev(wl)) { ++ dev_role = NL80211_IFTYPE_AP; ++ } else if (dev == wl->p2p_net) { ++ /* Group Add request on p2p0 */ ++ dev = wl_to_prmry_ndev(wl); ++ dev_role = NL80211_IFTYPE_P2P_GO; ++ } ++ bssidx = wl_cfgp2p_find_idx(wl, dev); ++ if (p2p_is_on(wl) && ++ (bssidx == wl_to_p2p_bss_bssidx(wl, ++ P2PAPI_BSSCFG_CONNECTION))) { ++ dev_role = NL80211_IFTYPE_P2P_GO; ++ } ++ ++ if (dev_role == NL80211_IFTYPE_AP) { ++ /* SoftAp on primary Interface. ++ * Shut down AP and turn on MPC ++ */ ++ err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true); ++ if (err < 0) { ++ AP6210_ERR("SET INFRA error %d\n", err); ++ err = -ENOTSUPP; ++ goto exit; ++ } ++ if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) { ++ AP6210_ERR("setting AP mode failed %d \n", err); ++ err = -ENOTSUPP; ++ goto exit; ++ } ++ ++ err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true); ++ if (unlikely(err)) { ++ AP6210_ERR("WLC_UP error (%d)\n", err); ++ err = -EINVAL; ++ goto exit; ++ } ++ ++ wl_clr_drv_status(wl, AP_CREATED, dev); ++ /* Turn on the MPC */ ++ wldev_iovar_setint(dev, "mpc", 1); ++ } else { ++ AP6210_DEBUG("Stopping P2P GO \n"); ++ } ++ ++exit: ++ return err; ++} ++ ++static s32 ++wl_cfg80211_change_beacon( ++ struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_beacon_data *info) ++{ ++ s32 err = BCME_OK; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct parsed_ies ies; ++ u32 dev_role = 0; ++ s32 bssidx = 0; ++ ++ AP6210_DEBUG("Enter \n"); ++ ++ if (dev == wl_to_prmry_ndev(wl)) { ++ dev_role = NL80211_IFTYPE_AP; ++ } else if (dev == wl->p2p_net) { ++ /* Group Add request on p2p0 */ ++ dev = wl_to_prmry_ndev(wl); ++ dev_role = NL80211_IFTYPE_P2P_GO; ++ } ++ ++ bssidx = wl_cfgp2p_find_idx(wl, dev); ++ if (p2p_is_on(wl) && ++ (bssidx == wl_to_p2p_bss_bssidx(wl, ++ P2PAPI_BSSCFG_CONNECTION))) { ++ dev_role = NL80211_IFTYPE_P2P_GO; ++ } ++ ++ /* Set IEs to FW */ ++ if ((err = wl_cfg80211_parse_set_ies(dev, info, ++ &ies, dev_role, bssidx) < 0)) { ++ AP6210_ERR("Set IEs failed \n"); ++ goto fail; ++ } ++ ++ if (dev_role == NL80211_IFTYPE_AP) { ++ if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) { ++ AP6210_ERR("Hostapd update sec failed \n"); ++ err = -EINVAL; ++ goto fail; ++ } ++ } ++ ++fail: ++ return err; ++} ++#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */ ++static s32 ++wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, ++ struct beacon_parameters *info) ++{ ++ s32 err = BCME_OK; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ s32 ie_offset = 0; ++ s32 bssidx = 0; ++ u32 dev_role = NL80211_IFTYPE_AP; ++ struct parsed_ies ies; ++ bcm_tlv_t *ssid_ie; ++ bool pbc = 0; ++ ++ AP6210_DEBUG("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n", ++ info->interval, info->dtim_period, info->head_len, info->tail_len); ++ ++ if (dev == wl_to_prmry_ndev(wl)) { ++ dev_role = NL80211_IFTYPE_AP; ++ } else if (dev == wl->p2p_net) { ++ /* Group Add request on p2p0 */ ++ dev = wl_to_prmry_ndev(wl); ++ dev_role = NL80211_IFTYPE_P2P_GO; ++ } ++ ++ bssidx = wl_cfgp2p_find_idx(wl, dev); ++ if (p2p_is_on(wl) && ++ (bssidx == wl_to_p2p_bss_bssidx(wl, ++ P2PAPI_BSSCFG_CONNECTION))) { ++ dev_role = NL80211_IFTYPE_P2P_GO; ++ } ++ ++ ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN; ++ /* find the SSID */ ++ if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset], ++ info->head_len - ie_offset, ++ DOT11_MNG_SSID_ID)) != NULL) { ++ if (dev_role == NL80211_IFTYPE_AP) { ++ /* Store the hostapd SSID */ ++ memset(&wl->hostapd_ssid.SSID[0], 0x00, 32); ++ memcpy(&wl->hostapd_ssid.SSID[0], ssid_ie->data, ssid_ie->len); ++ wl->hostapd_ssid.SSID_len = ssid_ie->len; ++ } else { ++ /* P2P GO */ ++ memset(&wl->p2p->ssid.SSID[0], 0x00, 32); ++ memcpy(wl->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len); ++ wl->p2p->ssid.SSID_len = ssid_ie->len; ++ } ++ } ++ ++ if (wl_cfg80211_parse_ies((u8 *)info->tail, ++ info->tail_len, &ies) < 0) { ++ AP6210_ERR("Beacon get IEs failed \n"); ++ err = -EINVAL; ++ goto fail; ++ } ++ ++ if (wl_cfgp2p_set_management_ie(wl, dev, bssidx, ++ VNDR_IE_BEACON_FLAG, (u8 *)info->tail, ++ info->tail_len) < 0) { ++ AP6210_ERR("Beacon set IEs failed \n"); ++ goto fail; ++ } else { ++ AP6210_DEBUG("Applied Vndr IEs for Beacon \n"); ++ } ++ if (!wl_cfgp2p_bss_isup(dev, bssidx) && ++ (wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx) < 0)) ++ { ++ AP6210_ERR("Beacon set security failed \n"); ++ goto fail; ++ } ++ ++ /* Set BI and DTIM period */ ++ if (info->interval) { ++ if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD, ++ &info->interval, sizeof(s32), true)) < 0) { ++ AP6210_ERR("Beacon Interval Set Error, %d\n", err); ++ return err; ++ } ++ } ++ if (info->dtim_period) { ++ if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD, ++ &info->dtim_period, sizeof(s32), true)) < 0) { ++ AP6210_ERR("DTIM Interval Set Error, %d\n", err); ++ return err; ++ } ++ } ++ ++ if (wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx) < 0) { ++ AP6210_ERR("Beacon bring up AP/GO failed \n"); ++ goto fail; ++ } ++ ++ if (wl_get_drv_status(wl, AP_CREATED, dev)) { ++ /* Soft AP already running. Update changed params */ ++ if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) { ++ AP6210_ERR("Hostapd update sec failed \n"); ++ err = -EINVAL; ++ goto fail; ++ } ++ } ++ ++ /* Enable Probe Req filter */ ++ if (((dev_role == NL80211_IFTYPE_P2P_GO) || ++ (dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) { ++ wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc); ++ if (pbc) ++ wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true); ++ } ++ ++ AP6210_DEBUG("** ADD/SET beacon done **\n"); ++ ++fail: ++ if (err) { ++ AP6210_ERR("ADD/SET beacon failed\n"); ++ wldev_iovar_setint(dev, "mpc", 1); ++ } ++ return err; ++ ++} ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */ ++ ++#ifdef WL_SCHED_SCAN ++#define PNO_TIME 30 ++#define PNO_REPEAT 4 ++#define PNO_FREQ_EXPO_MAX 2 ++int wl_cfg80211_sched_scan_start(struct wiphy *wiphy, ++ struct net_device *dev, ++ struct cfg80211_sched_scan_request *request) ++{ ++ ushort pno_time = PNO_TIME; ++ int pno_repeat = PNO_REPEAT; ++ int pno_freq_expo_max = PNO_FREQ_EXPO_MAX; ++ wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT]; ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ struct cfg80211_ssid *ssid = NULL; ++ int ssid_count = 0; ++ int i; ++ int ret = 0; ++ ++ AP6210_DEBUG("Enter \n"); ++ AP6210_DEBUG(">>> SCHED SCAN START\n"); ++ AP6210_DEBUG("Enter n_match_sets:%d n_ssids:%d \n", ++ request->n_match_sets, request->n_ssids); ++ AP6210_DEBUG("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n", ++ request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max); ++ ++ ++ if (!request || !request->n_ssids || !request->n_match_sets) { ++ AP6210_ERR("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids); ++ return -EINVAL; ++ } ++ ++ memset(&ssids_local, 0, sizeof(ssids_local)); ++ ++ if (request->n_match_sets > 0) { ++ for (i = 0; i < request->n_match_sets; i++) { ++ ssid = &request->match_sets[i].ssid; ++ memcpy(ssids_local[i].SSID, ssid->ssid, ssid->ssid_len); ++ ssids_local[i].SSID_len = ssid->ssid_len; ++ AP6210_DEBUG(">>> PNO filter set for ssid (%s) \n", ssid->ssid); ++ ssid_count++; ++ } ++ } ++ ++ if (request->n_ssids > 0) { ++ for (i = 0; i < request->n_ssids; i++) { ++ /* Active scan req for ssids */ ++ AP6210_DEBUG(">>> Active scan req for ssid (%s) \n", request->ssids[i].ssid); ++ ++ /* match_set ssids is a supert set of n_ssid list, so we need ++ * not add these set seperately ++ */ ++ } ++ } ++ ++ if (ssid_count) { ++ if ((ret = dhd_dev_pno_set(dev, ssids_local, request->n_match_sets, ++ pno_time, pno_repeat, pno_freq_expo_max)) < 0) { ++ AP6210_ERR("PNO setup failed!! ret=%d \n", ret); ++ return -EINVAL; ++ } ++ ++ /* Enable the PNO */ ++ if (dhd_dev_pno_enable(dev, 1) < 0) { ++ AP6210_ERR("PNO enable failed!! ret=%d \n", ret); ++ return -EINVAL; ++ } ++ wl->sched_scan_req = request; ++ } else { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) ++{ ++ struct wl_priv *wl = wiphy_priv(wiphy); ++ ++ AP6210_DEBUG("Enter \n"); ++ AP6210_DEBUG(">>> SCHED SCAN STOP\n"); ++ ++ if (dhd_dev_pno_enable(dev, 0) < 0) ++ AP6210_ERR("PNO disable failed"); ++ ++ if (dhd_dev_pno_reset(dev) < 0) ++ AP6210_ERR("PNO reset failed"); ++ ++ if (wl->scan_request && wl->sched_scan_running) { ++ AP6210_DEBUG(">>> Sched scan running. Aborting it..\n"); ++ wl_notify_escan_complete(wl, dev, true, true); ++ } ++ ++ wl->sched_scan_req = NULL; ++ wl->sched_scan_running = FALSE; ++ ++ return 0; ++} ++#endif /* WL_SCHED_SCAN */ ++ ++static struct cfg80211_ops wl_cfg80211_ops = { ++ .add_virtual_intf = wl_cfg80211_add_virtual_iface, ++ .del_virtual_intf = wl_cfg80211_del_virtual_iface, ++ .change_virtual_intf = wl_cfg80211_change_virtual_iface, ++ .scan = wl_cfg80211_scan, ++ .set_wiphy_params = wl_cfg80211_set_wiphy_params, ++ .join_ibss = wl_cfg80211_join_ibss, ++ .leave_ibss = wl_cfg80211_leave_ibss, ++ .get_station = wl_cfg80211_get_station, ++ .set_tx_power = wl_cfg80211_set_tx_power, ++ .get_tx_power = wl_cfg80211_get_tx_power, ++ .add_key = wl_cfg80211_add_key, ++ .del_key = wl_cfg80211_del_key, ++ .get_key = wl_cfg80211_get_key, ++ .set_default_key = wl_cfg80211_config_default_key, ++ .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key, ++ .set_power_mgmt = wl_cfg80211_set_power_mgmt, ++ .connect = wl_cfg80211_connect, ++ .disconnect = wl_cfg80211_disconnect, ++ .suspend = wl_cfg80211_suspend, ++ .resume = wl_cfg80211_resume, ++ .set_pmksa = wl_cfg80211_set_pmksa, ++ .del_pmksa = wl_cfg80211_del_pmksa, ++ .flush_pmksa = wl_cfg80211_flush_pmksa, ++ .remain_on_channel = wl_cfg80211_remain_on_channel, ++ .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel, ++ .mgmt_tx = wl_cfg80211_mgmt_tx, ++ .mgmt_frame_register = wl_cfg80211_mgmt_frame_register, ++ .change_bss = wl_cfg80211_change_bss, ++ .set_channel = wl_cfg80211_set_channel, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) ++ .set_beacon = wl_cfg80211_add_set_beacon, ++ .add_beacon = wl_cfg80211_add_set_beacon, ++#else ++ .change_beacon = wl_cfg80211_change_beacon, ++ .start_ap = wl_cfg80211_start_ap, ++ .stop_ap = wl_cfg80211_stop_ap, ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */ ++#ifdef WL_SCHED_SCAN ++ .sched_scan_start = wl_cfg80211_sched_scan_start, ++ .sched_scan_stop = wl_cfg80211_sched_scan_stop, ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ ++#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ ++ 2, 0)) ++ .del_station = wl_cfg80211_del_station, ++ .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait, ++#endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */ ++}; ++ ++s32 wl_mode_to_nl80211_iftype(s32 mode) ++{ ++ s32 err = 0; ++ ++ switch (mode) { ++ case WL_MODE_BSS: ++ return NL80211_IFTYPE_STATION; ++ case WL_MODE_IBSS: ++ return NL80211_IFTYPE_ADHOC; ++ case WL_MODE_AP: ++ return NL80211_IFTYPE_AP; ++ default: ++ return NL80211_IFTYPE_UNSPECIFIED; ++ } ++ ++ return err; ++} ++ ++static int ++wl_cfg80211_reg_notifier( ++ struct wiphy *wiphy, ++ struct regulatory_request *request) ++{ ++ struct wl_priv *wl = (struct wl_priv *)wiphy_priv(wiphy); ++ wl_country_t cspec = {{0}, 0, {0} }; ++ int ret = 0; ++ ++ if (!request || !wl) { ++ AP6210_ERR("Invalid arg\n"); ++ return -EINVAL; ++ } ++ ++ AP6210_DEBUG("ccode: %c%c Initiator: %d\n", ++ request->alpha2[0], request->alpha2[1], request->initiator); ++ ++ /* We support only REGDOM_SET_BY_USER as of now */ ++ if (request->initiator != NL80211_REGDOM_SET_BY_USER) { ++ AP6210_ERR("reg_notifier for intiator:%d not supported \n", ++ request->initiator); ++ return -ENOTSUPP; ++ } ++ ++ if (request->alpha2[0] == '0' && request->alpha2[1] == '0') { ++ /* world domain */ ++ AP6210_ERR("World domain. Setting XY/4 \n"); ++ strncpy(cspec.country_abbrev, "XY", strlen("XY")); ++ cspec.rev = 4; ++ } else { ++ memcpy(cspec.country_abbrev, request->alpha2, 2); ++ cspec.country_abbrev[3] = '\0'; ++ cspec.rev = -1; /* Unspecified */ ++ } ++ ++ if ((ret = wldev_iovar_setbuf(wl_to_prmry_ndev(wl), "country", (char *)&cspec, ++ sizeof(cspec), wl->ioctl_buf, WLC_IOCTL_SMLEN, NULL)) < 0) { ++ AP6210_ERR("set country Failed :%d\n", ret); ++ goto exit; ++ } ++ ++ if ((ret = wl_update_wiphybands(wl, false)) < 0) { ++ AP6210_ERR("wl_update_wiphybands failed\n"); ++ goto exit; ++ } ++ ++ AP6210_DEBUG("%s: set country '%s/%d' done\n", ++ __FUNCTION__, cspec.country_abbrev, cspec.rev); ++ ++exit: ++ return ret; ++} ++ ++static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev) ++{ ++ s32 err = 0; ++ wdev->wiphy = ++ wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv)); ++ if (unlikely(!wdev->wiphy)) { ++ AP6210_ERR("Couldn not allocate wiphy device\n"); ++ err = -ENOMEM; ++ return err; ++ } ++ set_wiphy_dev(wdev->wiphy, sdiofunc_dev); ++ wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX; ++ /* Report how many SSIDs Driver can support per Scan request */ ++ wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX; ++ wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; ++#ifdef WL_SCHED_SCAN ++ wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT; ++ wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT; ++ wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX; ++ wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; ++#endif /* WL_SCHED_SCAN */ ++ wdev->wiphy->interface_modes = ++ BIT(NL80211_IFTYPE_STATION) ++#if !(defined(WLP2P) && defined(WL_ENABLE_P2P_IF)) ++ | BIT(NL80211_IFTYPE_MONITOR) ++#endif ++ | BIT(NL80211_IFTYPE_AP); ++ ++ wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; ++ ++ wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; ++ wdev->wiphy->cipher_suites = __wl_cipher_suites; ++ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); ++ wdev->wiphy->max_remain_on_channel_duration = 5000; ++ wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes; ++#ifndef WL_POWERSAVE_DISABLED ++ wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; ++#else ++ wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; ++#endif /* !WL_POWERSAVE_DISABLED */ ++ wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK | ++ WIPHY_FLAG_4ADDR_AP | ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39) ++ WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS | ++#endif ++ WIPHY_FLAG_4ADDR_STATION; ++ /* If driver advertises FW_ROAM, the supplicant wouldn't ++ * send the BSSID & Freq in the connect command allowing the ++ * the driver to choose the AP to connect to. But unless we ++ * support ROAM_CACHE in firware this will delay the ASSOC as ++ * as the FW need to do a full scan before attempting to connect ++ * So that feature will just increase assoc. The better approach ++ * to let Supplicant to provide channel info and FW letter may roam ++ * if needed so DON'T advertise that featur eto Supplicant. ++ */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) ++ /* wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; */ ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) ++ wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | ++ WIPHY_FLAG_OFFCHAN_TX; ++#endif ++#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ ++ 4, 0)) ++ /* From 3.4 kernel ownards AP_SME flag can be advertised ++ * to remove the patch from supplicant ++ */ ++ wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME; ++#endif ++ ++ wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier; ++ ++ AP6210_DEBUG("Registering custom regulatory)\n"); ++ wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; ++ wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom); ++ /* Now we can register wiphy with cfg80211 module */ ++ err = wiphy_register(wdev->wiphy); ++ if (unlikely(err < 0)) { ++ AP6210_ERR("Couldn not register wiphy device (%d)\n", err); ++ wiphy_free(wdev->wiphy); ++ } ++ return err; ++} ++ ++static void wl_free_wdev(struct wl_priv *wl) ++{ ++ struct wireless_dev *wdev = wl->wdev; ++ struct wiphy *wiphy; ++ if (!wdev) { ++ AP6210_ERR("wdev is invalid\n"); ++ return; ++ } ++ wiphy = wdev->wiphy; ++ wiphy_unregister(wdev->wiphy); ++ wdev->wiphy->dev.parent = NULL; ++ ++ wl_delete_all_netinfo(wl); ++ wiphy_free(wiphy); ++ /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "wl", ++ * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!! ++ */ ++} ++ ++#if defined(RSSIAVG) ++static wl_rssi_cache_ctrl_t g_rssi_cache_ctrl; ++#endif ++#if defined(BSSCACHE) ++static wl_bss_cache_ctrl_t g_bss_cache_ctrl; ++#endif ++ ++static s32 wl_inform_bss(struct wl_priv *wl) ++{ ++ struct wl_scan_results *bss_list; ++ struct wl_bss_info *bi = NULL; /* must be initialized */ ++ s32 err = 0; ++ s32 i; ++#if defined(RSSIAVG) ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++#endif ++#if defined(BSSCACHE) ++ wl_bss_cache_t *node; ++#endif ++ ++ bss_list = wl->bss_list; ++#if defined(BSSCACHE) ++ if (g_bss_cache_ctrl.m_timer_expired || (p2p_is_on(wl) && p2p_scan(wl))) { ++#if defined(RSSIAVG) ++ wl_free_rssi_cache(&g_rssi_cache_ctrl); ++#endif ++ wl_free_bss_cache(&g_bss_cache_ctrl); ++ g_bss_cache_ctrl.m_timer_expired ^= 1; ++ } ++ wl_update_bss_cache(&g_bss_cache_ctrl, bss_list); ++ wl_delete_dirty_bss_cache(&g_bss_cache_ctrl); ++ wl_reset_bss_cache(&g_bss_cache_ctrl); ++#endif ++ ++#if defined(RSSIAVG) ++#if defined(BSSCACHE) ++ node = g_bss_cache_ctrl.m_cache_head; ++ for (;node;) { ++ wl_update_rssi_cache(&g_rssi_cache_ctrl, &node->results); ++ node = node->next; ++ } ++#else ++ wl_update_rssi_cache(&g_rssi_cache_ctrl, bss_list); ++#endif ++ if (!in_atomic()) ++ wl_update_connected_rssi_cache(&g_rssi_cache_ctrl, ndev); ++ wl_delete_dirty_rssi_cache(&g_rssi_cache_ctrl); ++ wl_reset_rssi_cache(&g_rssi_cache_ctrl); ++#endif ++ ++ AP6210_DEBUG("scanned AP count (%d)\n", bss_list->count); ++ ++#if defined(BSSCACHE) ++ node = g_bss_cache_ctrl.m_cache_head; ++ for (i=0; node && iresults.bss_info; ++ err = wl_inform_single_bss(wl, bi, 0); ++ if (unlikely(err)) ++ break; ++ node = node->next; ++ } ++ wl_run_bss_cache_timer(&g_bss_cache_ctrl, 0); ++ wl_run_bss_cache_timer(&g_bss_cache_ctrl, 1); ++#else ++ bi = next_bss(bss_list, bi); ++ for_each_bss(bss_list, bi, i) { ++ err = wl_inform_single_bss(wl, bi, 0); ++ if (unlikely(err)) ++ break; ++ } ++#endif ++ return err; ++} ++ ++static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 is_roam_done) ++{ ++ struct wiphy *wiphy = wl_to_wiphy(wl); ++ struct ieee80211_mgmt *mgmt; ++ struct ieee80211_channel *channel; ++ struct ieee80211_supported_band *band; ++ struct wl_cfg80211_bss_info *notif_bss_info; ++ struct wl_scan_req *sr = wl_to_sr(wl); ++ struct beacon_proberesp *beacon_proberesp; ++ struct cfg80211_bss *cbss = NULL; ++ s32 mgmt_type; ++ s32 signal; ++ u32 freq; ++ s32 err = 0; ++ gfp_t aflags; ++ u8 *ie_offset = NULL; ++ ++ if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) { ++ AP6210_DEBUG("Beacon is larger than buffer. Discarding\n"); ++ return err; ++ } ++ aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; ++ notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt) ++ - sizeof(u8) + WL_BSS_INFO_MAX, aflags); ++ if (unlikely(!notif_bss_info)) { ++ AP6210_ERR("notif_bss_info alloc failed\n"); ++ return -ENOMEM; ++ } ++ mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf; ++ notif_bss_info->channel = ++ bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec)); ++ ++ if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL) ++ band = wiphy->bands[IEEE80211_BAND_2GHZ]; ++ else ++ band = wiphy->bands[IEEE80211_BAND_5GHZ]; ++ if (!band) { ++ AP6210_ERR("No valid band"); ++ kfree(notif_bss_info); ++ return -EINVAL; ++ } ++ notif_bss_info->rssi = dtoh16(bi->RSSI); ++#if defined(RSSIAVG) ++ notif_bss_info->rssi = wl_get_avg_rssi(&g_rssi_cache_ctrl, &bi->BSSID); ++#endif ++#if defined(RSSIOFFSET) ++ notif_bss_info->rssi = wl_update_rssi_offset(notif_bss_info->rssi); ++#endif ++ memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN); ++ mgmt_type = wl->active_scan ? ++ IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON; ++ if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) { ++ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type); ++ } ++ beacon_proberesp = wl->active_scan ? ++ (struct beacon_proberesp *)&mgmt->u.probe_resp : ++ (struct beacon_proberesp *)&mgmt->u.beacon; ++ beacon_proberesp->timestamp = 0; ++ beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period); ++ beacon_proberesp->capab_info = cpu_to_le16(bi->capability); ++ wl_rst_ie(wl); ++ ++ ie_offset = ((u8 *) bi) + bi->ie_offset; ++ ++ if (is_roam_done && ((int)(*(ie_offset)) == WLAN_EID_SSID && ++ ((int)(*(ie_offset+1)) == 0 || (int)(*(ie_offset+2)) == 0))) { ++ u8 *ie_new_offset = NULL; ++ uint8 ie_new_length; ++ ++ AP6210_ERR("WAR trace: Changing the SSID Info, from beacon %d\n", ++ bi->flags & WL_BSS_FLAGS_FROM_BEACON); ++ ++ ie_new_offset = (u8 *)kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); ++ if (ie_new_offset) { ++ *(ie_new_offset) = WLAN_EID_SSID; ++ *(ie_new_offset+1) = bi->SSID_len; ++ memcpy(ie_new_offset+2, bi->SSID, bi->SSID_len); ++ ie_new_length = bi->ie_length - *(ie_offset+1) + bi->SSID_len; ++ ++ /* Copy the remaining IE apart from SSID IE from bi */ ++ memcpy(ie_new_offset+2 + bi->SSID_len, ++ ie_offset+2 + *(ie_offset+1), ++ bi->ie_length - 2 - *(ie_offset+1)); ++ wl_mrg_ie(wl, ie_new_offset, ie_new_length); ++ kfree(ie_new_offset); ++ } else { ++ wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); ++ } ++ } else { ++ wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); ++ } ++ ++ wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX - ++ offsetof(struct wl_cfg80211_bss_info, frame_buf)); ++ notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt, ++ u.beacon.variable) + wl_get_ielen(wl); ++#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) ++ freq = ieee80211_channel_to_frequency(notif_bss_info->channel); ++ (void)band->band; ++#else ++ freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band); ++#endif ++ if (freq == 0) { ++ AP6210_ERR("Invalid channel, fail to chcnage channel to freq\n"); ++ kfree(notif_bss_info); ++ return -EINVAL; ++ } ++ channel = ieee80211_get_channel(wiphy, freq); ++ if (unlikely(!channel)) { ++ AP6210_ERR("ieee80211_get_channel error\n"); ++ kfree(notif_bss_info); ++ return -EINVAL; ++ } ++ AP6210_DEBUG("BSSID %pM, channel %d, rssi %d, capability 0x04%x, mgmt_type %d, " ++ "frame_len %d, SSID \"%s\"\n", &bi->BSSID, notif_bss_info->channel, ++ notif_bss_info->rssi, mgmt->u.beacon.capab_info, mgmt_type, ++ notif_bss_info->frame_len, bi->SSID); ++ ++ signal = notif_bss_info->rssi * 100; ++ if (!mgmt->u.probe_resp.timestamp) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) ++ struct timespec ts; ++ get_monotonic_boottime(&ts); ++ mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000) ++ + ts.tv_nsec / 1000; ++#else ++ struct timeval tv; ++ do_gettimeofday(&tv); ++ mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000) ++ + tv.tv_usec; ++#endif ++ } ++ ++ cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt, ++ le16_to_cpu(notif_bss_info->frame_len), signal, aflags); ++ if (unlikely(!cbss)) { ++ AP6210_ERR("cfg80211_inform_bss_frame error\n"); ++ kfree(notif_bss_info); ++ return -EINVAL; ++ } ++ ++ cfg80211_put_bss(cbss); ++ kfree(notif_bss_info); ++ return err; ++} ++ ++static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev) ++{ ++ u32 event = ntoh32(e->event_type); ++ u32 status = ntoh32(e->status); ++ u16 flags = ntoh16(e->flags); ++ ++ AP6210_DEBUG("event %d, status %d flags %x\n", event, status, flags); ++ if (event == WLC_E_SET_SSID) { ++ if (status == WLC_E_STATUS_SUCCESS) { ++ if (!wl_is_ibssmode(wl, ndev)) ++ return true; ++ } ++ } else if (event == WLC_E_LINK) { ++ if (flags & WLC_EVENT_MSG_LINK) ++ return true; ++ } ++ ++ AP6210_DEBUG("wl_is_linkup false\n"); ++ return false; ++} ++ ++static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e) ++{ ++ u32 event = ntoh32(e->event_type); ++ u16 flags = ntoh16(e->flags); ++ ++ if (event == WLC_E_DEAUTH_IND || ++ event == WLC_E_DISASSOC_IND || ++ event == WLC_E_DISASSOC || ++ event == WLC_E_DEAUTH) { ++#if (WL_DBG_LEVEL > 0) ++ AP6210_ERR("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]); ++#endif /* (WL_DBG_LEVEL > 0) */ ++ return true; ++ } else if (event == WLC_E_LINK) { ++ if (!(flags & WLC_EVENT_MSG_LINK)) { ++#if (WL_DBG_LEVEL > 0) ++ AP6210_ERR("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]); ++#endif /* (WL_DBG_LEVEL > 0) */ ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e) ++{ ++ u32 event = ntoh32(e->event_type); ++ u32 status = ntoh32(e->status); ++ ++ if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS) ++ return true; ++ if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS) ++ return true; ++ ++ return false; ++} ++ ++/* The mainline kernel >= 3.2.0 has support for indicating new/del station ++ * to AP/P2P GO via events. If this change is backported to kernel for which ++ * this driver is being built, then define WL_CFG80211_STA_EVENT. You ++ * should use this new/del sta event mechanism for BRCM supplicant >= 22. ++ */ ++static s32 ++wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data) ++{ ++ s32 err = 0; ++ u32 event = ntoh32(e->event_type); ++ u32 reason = ntoh32(e->reason); ++ u32 len = ntoh32(e->datalen); ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) ++ bool isfree = false; ++ u8 *mgmt_frame; ++ u8 bsscfgidx = e->bsscfgidx; ++ s32 freq; ++ s32 channel; ++ u8 *body = NULL; ++ u16 fc = 0; ++ ++ struct ieee80211_supported_band *band; ++ struct ether_addr da; ++ struct ether_addr bssid; ++ struct wiphy *wiphy = wl_to_wiphy(wl); ++ channel_info_t ci; ++#else ++ struct station_info sinfo; ++#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !WL_CFG80211_STA_EVENT */ ++ ++ AP6210_DEBUG("event %d status %d reason %d\n", event, ntoh32(e->status), reason); ++ /* if link down, bsscfg is disabled. */ ++ if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS && ++ wl_get_p2p_status(wl, IF_DELETING) && (ndev != wl_to_prmry_ndev(wl))) { ++ wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false); ++ AP6210_DEBUG("AP mode link down !! \n"); ++ complete(&wl->iface_disable); ++ return 0; ++ } ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) ++ AP6210_DEBUG("Enter \n"); ++ if (!len && (event == WLC_E_DEAUTH)) { ++ len = 2; /* reason code field */ ++ data = &reason; ++ } ++ if (len) { ++ body = kzalloc(len, GFP_KERNEL); ++ ++ if (body == NULL) { ++ AP6210_ERR("wl_notify_connect_status: Failed to allocate body\n"); ++ return WL_INVALID; ++ } ++ } ++ memset(&bssid, 0, ETHER_ADDR_LEN); ++ AP6210_DEBUG("Enter event %d ndev %p\n", event, ndev); ++ if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID) { ++ kfree(body); ++ return WL_INVALID; ++ } ++ if (len) ++ memcpy(body, data, len); ++ ++ wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr", ++ NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync); ++ memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN); ++ err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); ++ switch (event) { ++ case WLC_E_ASSOC_IND: ++ fc = FC_ASSOC_REQ; ++ break; ++ case WLC_E_REASSOC_IND: ++ fc = FC_REASSOC_REQ; ++ break; ++ case WLC_E_DISASSOC_IND: ++ fc = FC_DISASSOC; ++ break; ++ case WLC_E_DEAUTH_IND: ++ fc = FC_DISASSOC; ++ break; ++ case WLC_E_DEAUTH: ++ fc = FC_DISASSOC; ++ break; ++ default: ++ fc = 0; ++ goto exit; ++ } ++ if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) { ++ kfree(body); ++ return err; ++ } ++ ++ channel = dtoh32(ci.hw_channel); ++ if (channel <= CH_MAX_2G_CHANNEL) ++ band = wiphy->bands[IEEE80211_BAND_2GHZ]; ++ else ++ band = wiphy->bands[IEEE80211_BAND_5GHZ]; ++ if (!band) { ++ AP6210_ERR("No valid band"); ++ if (body) ++ kfree(body); ++ return -EINVAL; ++ } ++#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) ++ freq = ieee80211_channel_to_frequency(channel); ++ (void)band->band; ++#else ++ freq = ieee80211_channel_to_frequency(channel, band->band); ++#endif ++ ++ err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid, ++ &mgmt_frame, &len, body); ++ if (err < 0) ++ goto exit; ++ isfree = true; ++ ++ if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC); ++#else ++ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */ ++ } else if (event == WLC_E_DISASSOC_IND) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC); ++#else ++ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */ ++ } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC); ++#else ++ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */ ++ } ++ ++exit: ++ if (isfree) ++ kfree(mgmt_frame); ++ if (body) ++ kfree(body); ++ return err; ++#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !WL_CFG80211_STA_EVENT */ ++ sinfo.filled = 0; ++ if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) && ++ reason == DOT11_SC_SUCCESS) { ++ sinfo.filled = STATION_INFO_ASSOC_REQ_IES; ++ if (!data) { ++ AP6210_ERR("No IEs present in ASSOC/REASSOC_IND"); ++ return -EINVAL; ++ } ++ sinfo.assoc_req_ies = data; ++ sinfo.assoc_req_ies_len = len; ++ cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC); ++ } else if (event == WLC_E_DISASSOC_IND) { ++ cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); ++ } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) { ++ cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); ++ } ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !WL_CFG80211_STA_EVENT */ ++ return err; ++} ++ ++static s32 ++wl_get_auth_assoc_status(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e) ++{ ++ u32 reason = ntoh32(e->reason); ++ u32 event = ntoh32(e->event_type); ++ struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC); ++ AP6210_DEBUG("event type : %d, reason : %d\n", event, reason); ++ if (sec) { ++ switch (event) { ++ case WLC_E_ASSOC: ++ case WLC_E_AUTH: ++ sec->auth_assoc_res_status = reason; ++ default: ++ break; ++ } ++ } else ++ AP6210_ERR("sec is NULL\n"); ++ return 0; ++} ++ ++static s32 ++wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data) ++{ ++ bool act; ++ s32 err = 0; ++ u32 event = ntoh32(e->event_type); ++ ++ if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { ++ wl_notify_connect_status_ap(wl, ndev, e, data); ++ } else { ++ AP6210_DEBUG("wl_notify_connect_status : event %d status : %d ndev %p\n", ++ ntoh32(e->event_type), ntoh32(e->status), ndev); ++ if (event == WLC_E_ASSOC || event == WLC_E_AUTH) { ++ wl_get_auth_assoc_status(wl, ndev, e); ++ return err; ++ } ++ if (wl_is_linkup(wl, e, ndev)) { ++ wl_link_up(wl); ++ act = true; ++ if (wl_is_ibssmode(wl, ndev)) { ++ AP6210_DEBUG("cfg80211_ibss_joined\n"); ++ cfg80211_ibss_joined(ndev, (s8 *)&e->addr, ++ GFP_KERNEL); ++ AP6210_DEBUG("joined in IBSS network\n"); ++ } else { ++ if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) { ++ AP6210_DEBUG("wl_bss_connect_done succeeded with " MACDBG "\n", ++ MAC2STRDBG((u8*)(&e->addr))); ++ wl_bss_connect_done(wl, ndev, e, data, true); ++ AP6210_DEBUG("joined in BSS network \"%s\"\n", ++ ((struct wlc_ssid *) ++ wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID); ++ } ++ } ++ wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT); ++ wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID); ++ ++ } else if (wl_is_linkdown(wl, e)) { ++ if (wl->scan_request) { ++ if (wl->escan_on) { ++ wl_notify_escan_complete(wl, ndev, true, true); ++ } else { ++ del_timer_sync(&wl->scan_timeout); ++ wl_iscan_aborted(wl); ++ } ++ } ++ if (wl_get_drv_status(wl, CONNECTED, ndev)) { ++ scb_val_t scbval; ++ u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); ++ s32 reason = 0; ++ if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) ++ reason = ntoh32(e->reason); ++ /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */ ++ reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason; ++ ++ AP6210_DEBUG("link down if %s may call cfg80211_disconnected. " ++ "event : %d, reason=%d from " MACDBG "\n", ++ ndev->name, event, ntoh32(e->reason), ++ MAC2STRDBG((u8*)(&e->addr))); ++ if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) { ++ AP6210_ERR("BSSID of event is not the connected BSSID" ++ "(ignore it) cur: " MACDBG " event: " MACDBG"\n", ++ MAC2STRDBG(curbssid), MAC2STRDBG((u8*)(&e->addr))); ++ return 0; ++ } ++ wl_clr_drv_status(wl, CONNECTED, ndev); ++ if (! wl_get_drv_status(wl, DISCONNECTING, ndev)) { ++ /* To make sure disconnect, explictly send dissassoc ++ * for BSSID 00:00:00:00:00:00 issue ++ */ ++ scbval.val = WLAN_REASON_DEAUTH_LEAVING; ++ ++ memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN); ++ scbval.val = htod32(scbval.val); ++ err = wldev_ioctl(ndev, WLC_DISASSOC, &scbval, ++ sizeof(scb_val_t), true); ++ if (err < 0) { ++ AP6210_ERR("WLC_DISASSOC error %d\n", err); ++ err = 0; ++ } ++ cfg80211_disconnected(ndev, reason, NULL, 0, GFP_KERNEL); ++ wl_link_down(wl); ++ wl_init_prof(wl, ndev); ++ } ++ } ++ else if (wl_get_drv_status(wl, CONNECTING, ndev)) { ++ AP6210_DEBUG("link down, during connecting\n"); ++#ifdef ESCAN_RESULT_PATCH ++ if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) || ++ (memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) || ++ (memcmp(&e->addr, connect_req_bssid, ETHER_ADDR_LEN) == 0)) ++ /* In case this event comes while associating another AP */ ++#endif /* ESCAN_RESULT_PATCH */ ++ wl_bss_connect_done(wl, ndev, e, data, false); ++ } ++ wl_clr_drv_status(wl, DISCONNECTING, ndev); ++ ++ /* if link down, bsscfg is diabled */ ++ if (ndev != wl_to_prmry_ndev(wl)) ++ complete(&wl->iface_disable); ++ ++ } else if (wl_is_nonetwork(wl, e)) { ++ AP6210_DEBUG("connect failed event=%d e->status %d e->reason %d \n", ++ event, (int)ntoh32(e->status), (int)ntoh32(e->reason)); ++ /* Clean up any pending scan request */ ++ if (wl->scan_request) { ++ if (wl->escan_on) { ++ wl_notify_escan_complete(wl, ndev, true, true); ++ } else { ++ del_timer_sync(&wl->scan_timeout); ++ wl_iscan_aborted(wl); ++ } ++ } ++ if (wl_get_drv_status(wl, CONNECTING, ndev)) ++ wl_bss_connect_done(wl, ndev, e, data, false); ++ } else { ++ AP6210_DEBUG("%s nothing\n", __FUNCTION__); ++ } ++ } ++ return err; ++} ++ ++static s32 ++wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data) ++{ ++ bool act; ++ s32 err = 0; ++ u32 event = be32_to_cpu(e->event_type); ++ u32 status = be32_to_cpu(e->status); ++ AP6210_DEBUG("Enter \n"); ++ if (event == WLC_E_ROAM && status == WLC_E_STATUS_SUCCESS) { ++ if (wl_get_drv_status(wl, CONNECTED, ndev)) ++ wl_bss_roaming_done(wl, ndev, e, data); ++ else ++ wl_bss_connect_done(wl, ndev, e, data, true); ++ act = true; ++ wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT); ++ wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID); ++ } ++ return err; ++} ++ ++static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev) ++{ ++ wl_assoc_info_t assoc_info; ++ struct wl_connect_info *conn_info = wl_to_conn(wl); ++ s32 err = 0; ++ ++ AP6210_DEBUG("Enter \n"); ++ err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, wl->extra_buf, ++ WL_ASSOC_INFO_MAX, NULL); ++ if (unlikely(err)) { ++ AP6210_ERR("could not get assoc info (%d)\n", err); ++ return err; ++ } ++ memcpy(&assoc_info, wl->extra_buf, sizeof(wl_assoc_info_t)); ++ assoc_info.req_len = htod32(assoc_info.req_len); ++ assoc_info.resp_len = htod32(assoc_info.resp_len); ++ assoc_info.flags = htod32(assoc_info.flags); ++ if (conn_info->req_ie_len) { ++ conn_info->req_ie_len = 0; ++ bzero(conn_info->req_ie, sizeof(conn_info->req_ie)); ++ } ++ if (conn_info->resp_ie_len) { ++ conn_info->resp_ie_len = 0; ++ bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie)); ++ } ++ if (assoc_info.req_len) { ++ err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, wl->extra_buf, ++ WL_ASSOC_INFO_MAX, NULL); ++ if (unlikely(err)) { ++ AP6210_ERR("could not get assoc req (%d)\n", err); ++ return err; ++ } ++ conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req); ++ if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) { ++ conn_info->req_ie_len -= ETHER_ADDR_LEN; ++ } ++ if (conn_info->req_ie_len <= MAX_REQ_LINE) ++ memcpy(conn_info->req_ie, wl->extra_buf, conn_info->req_ie_len); ++ else { ++ AP6210_ERR("%s IE size %d above max %d size \n", ++ __FUNCTION__, conn_info->req_ie_len, MAX_REQ_LINE); ++ return err; ++ } ++ } else { ++ conn_info->req_ie_len = 0; ++ } ++ if (assoc_info.resp_len) { ++ err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, wl->extra_buf, ++ WL_ASSOC_INFO_MAX, NULL); ++ if (unlikely(err)) { ++ AP6210_ERR("could not get assoc resp (%d)\n", err); ++ return err; ++ } ++ conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp); ++ if (conn_info->resp_ie_len <= MAX_REQ_LINE) ++ memcpy(conn_info->resp_ie, wl->extra_buf, conn_info->resp_ie_len); ++ else { ++ AP6210_ERR("%s IE size %d above max %d size \n", ++ __FUNCTION__, conn_info->resp_ie_len, MAX_REQ_LINE); ++ return err; ++ } ++ } else { ++ conn_info->resp_ie_len = 0; ++ } ++ AP6210_DEBUG("req len (%d) resp len (%d)\n", conn_info->req_ie_len, ++ conn_info->resp_ie_len); ++ ++ return err; ++} ++ ++static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params, ++ size_t *join_params_size) ++{ ++ chanspec_t chanspec = 0; ++ if (ch != 0) { ++ join_params->params.chanspec_num = 1; ++ join_params->params.chanspec_list[0] = ch; ++ ++ if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL) ++ chanspec |= WL_CHANSPEC_BAND_2G; ++ else ++ chanspec |= WL_CHANSPEC_BAND_5G; ++ ++ chanspec |= WL_CHANSPEC_BW_20; ++ chanspec |= WL_CHANSPEC_CTL_SB_NONE; ++ ++ *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE + ++ join_params->params.chanspec_num * sizeof(chanspec_t); ++ ++ join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK; ++ join_params->params.chanspec_list[0] |= chanspec; ++ join_params->params.chanspec_list[0] = ++ wl_chspec_host_to_driver(join_params->params.chanspec_list[0]); ++ ++ join_params->params.chanspec_num = ++ htod32(join_params->params.chanspec_num); ++ AP6210_DEBUG("join_params->params.chanspec_list[0]= %X, %d channels\n", ++ join_params->params.chanspec_list[0], ++ join_params->params.chanspec_num); ++ } ++} ++ ++static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 is_roam_done) ++{ ++ struct cfg80211_bss *bss; ++ struct wl_bss_info *bi; ++ struct wlc_ssid *ssid; ++ struct bcm_tlv *tim; ++ s32 beacon_interval; ++ s32 dtim_period; ++ size_t ie_len; ++ u8 *ie; ++ u8 *ssidie; ++ u8 *curbssid; ++ s32 err = 0; ++ struct wiphy *wiphy; ++ ++ wiphy = wl_to_wiphy(wl); ++ ++ if (wl_is_ibssmode(wl, ndev)) ++ return err; ++ ++ ssid = (struct wlc_ssid *)wl_read_prof(wl, ndev, WL_PROF_SSID); ++ curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); ++ bss = cfg80211_get_bss(wiphy, NULL, curbssid, ++ ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS, ++ WLAN_CAPABILITY_ESS); ++ ++ mutex_lock(&wl->usr_sync); ++ if (!bss) { ++ AP6210_DEBUG("Could not find the AP\n"); ++ *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX); ++ err = wldev_ioctl(ndev, WLC_GET_BSS_INFO, ++ wl->extra_buf, WL_EXTRA_BUF_MAX, false); ++ if (unlikely(err)) { ++ AP6210_ERR("Could not get bss info %d\n", err); ++ goto update_bss_info_out; ++ } ++ bi = (struct wl_bss_info *)(wl->extra_buf + 4); ++ if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) { ++ err = -EIO; ++ goto update_bss_info_out; ++ } ++ ++ ie = ((u8 *)bi) + bi->ie_offset; ++ ie_len = bi->ie_length; ++ ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie, ie_len); ++ if (ssidie && ssidie[1] == bi->SSID_len && !ssidie[2] && bi->SSID[0]) ++ memcpy(ssidie + 2, bi->SSID, bi->SSID_len); ++ ++ err = wl_inform_single_bss(wl, bi, is_roam_done); ++ if (unlikely(err)) ++ goto update_bss_info_out; ++ ++ ie = ((u8 *)bi) + bi->ie_offset; ++ ie_len = bi->ie_length; ++ beacon_interval = cpu_to_le16(bi->beacon_period); ++ } else { ++ AP6210_DEBUG("Found the AP in the list - BSSID %pM\n", bss->bssid); ++ ie = bss->information_elements; ++ ie_len = bss->len_information_elements; ++ beacon_interval = bss->beacon_interval; ++ cfg80211_put_bss(bss); ++ } ++ ++ tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM); ++ if (tim) { ++ dtim_period = tim->data[1]; ++ } else { ++ /* ++ * active scan was done so we could not get dtim ++ * information out of probe response. ++ * so we speficially query dtim information. ++ */ ++ err = wldev_ioctl(ndev, WLC_GET_DTIMPRD, ++ &dtim_period, sizeof(dtim_period), false); ++ if (unlikely(err)) { ++ AP6210_ERR("WLC_GET_DTIMPRD error (%d)\n", err); ++ goto update_bss_info_out; ++ } ++ } ++ ++ wl_update_prof(wl, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT); ++ wl_update_prof(wl, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD); ++ ++update_bss_info_out: ++ mutex_unlock(&wl->usr_sync); ++ return err; ++} ++ ++static s32 ++wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data) ++{ ++ struct wl_connect_info *conn_info = wl_to_conn(wl); ++ s32 err = 0; ++ u8 *curbssid; ++ ++ wl_get_assoc_ies(wl, ndev); ++ wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); ++ curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); ++ wl_update_bss_info(wl, ndev, 1); ++ wl_update_pmklist(ndev, wl->pmk_list, err); ++ AP6210_DEBUG("wl_bss_roaming_done succeeded to " MACDBG "\n", ++ MAC2STRDBG((u8*)(&e->addr))); ++ ++ cfg80211_roamed(ndev, ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) ++ NULL, /* struct cfg80211_bss *bss */ ++#elif LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) ++ NULL, ++#endif ++ curbssid, ++ conn_info->req_ie, conn_info->req_ie_len, ++ conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); ++ AP6210_DEBUG("Report roaming result\n"); ++ ++ wl_set_drv_status(wl, CONNECTED, ndev); ++ ++ return err; ++} ++ ++static s32 ++wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data, bool completed) ++{ ++ struct wl_connect_info *conn_info = wl_to_conn(wl); ++ struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC); ++ s32 err = 0; ++ u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); ++ if (!sec) { ++ AP6210_ERR("sec is NULL\n"); ++ return -ENODEV; ++ } ++ AP6210_DEBUG(" enter\n"); ++#ifdef ESCAN_RESULT_PATCH ++ if (wl_get_drv_status(wl, CONNECTED, ndev)) { ++ if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) { ++ AP6210_DEBUG(" Connected event of connected device e=%d s=%d, ignore it\n", ++ ntoh32(e->event_type), ntoh32(e->status)); ++ return err; ++ } ++ } ++ if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 && ++ memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) { ++ AP6210_DEBUG("copy bssid\n"); ++ memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN); ++ } ++ ++#else ++ if (wl->scan_request) { ++ wl_notify_escan_complete(wl, ndev, true, true); ++ } ++#endif /* ESCAN_RESULT_PATCH */ ++ if (wl_get_drv_status(wl, CONNECTING, ndev)) { ++ wl_clr_drv_status(wl, CONNECTING, ndev); ++ if (completed) { ++ wl_get_assoc_ies(wl, ndev); ++ wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); ++ curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); ++ wl_update_bss_info(wl, ndev, 0); ++ wl_update_pmklist(ndev, wl->pmk_list, err); ++ wl_set_drv_status(wl, CONNECTED, ndev); ++ } ++ cfg80211_connect_result(ndev, ++ curbssid, ++ conn_info->req_ie, ++ conn_info->req_ie_len, ++ conn_info->resp_ie, ++ conn_info->resp_ie_len, ++ completed ? WLAN_STATUS_SUCCESS : ++ (sec->auth_assoc_res_status) ? ++ sec->auth_assoc_res_status : ++ WLAN_STATUS_UNSPECIFIED_FAILURE, ++ GFP_KERNEL); ++ if (completed) ++ AP6210_DEBUG("Report connect result - connection succeeded\n"); ++ else ++ AP6210_ERR("Report connect result - connection failed\n"); ++ } ++ return err; ++} ++ ++static s32 ++wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data) ++{ ++ u16 flags = ntoh16(e->flags); ++ enum nl80211_key_type key_type; ++ ++ mutex_lock(&wl->usr_sync); ++ if (flags & WLC_EVENT_MSG_GROUP) ++ key_type = NL80211_KEYTYPE_GROUP; ++ else ++ key_type = NL80211_KEYTYPE_PAIRWISE; ++ ++ cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1, ++ NULL, GFP_KERNEL); ++ mutex_unlock(&wl->usr_sync); ++ ++ return 0; ++} ++ ++#ifdef PNO_SUPPORT ++static s32 ++wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data) ++{ ++ AP6210_ERR(">>> PNO Event\n"); ++ ++#ifndef WL_SCHED_SCAN ++ mutex_lock(&wl->usr_sync); ++ /* TODO: Use cfg80211_sched_scan_results(wiphy); */ ++ cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); ++ mutex_unlock(&wl->usr_sync); ++#else ++ /* If cfg80211 scheduled scan is supported, report the pno results via sched ++ * scan results ++ */ ++ wl_notify_sched_scan_results(wl, ndev, e, data); ++#endif /* WL_SCHED_SCAN */ ++ return 0; ++} ++#endif /* PNO_SUPPORT */ ++ ++static s32 ++wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data) ++{ ++ struct channel_info channel_inform; ++ struct wl_scan_results *bss_list; ++ u32 len = WL_SCAN_BUF_MAX; ++ s32 err = 0; ++ unsigned long flags; ++ ++ AP6210_DEBUG("Enter \n"); ++ if (!wl_get_drv_status(wl, SCANNING, ndev)) { ++ AP6210_ERR("scan is not ready \n"); ++ return err; ++ } ++ if (wl->iscan_on && wl->iscan_kickstart) ++ return wl_wakeup_iscan(wl_to_iscan(wl)); ++ ++ mutex_lock(&wl->usr_sync); ++ wl_clr_drv_status(wl, SCANNING, ndev); ++ err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform, ++ sizeof(channel_inform), false); ++ if (unlikely(err)) { ++ AP6210_ERR("scan busy (%d)\n", err); ++ goto scan_done_out; ++ } ++ channel_inform.scan_channel = dtoh32(channel_inform.scan_channel); ++ if (unlikely(channel_inform.scan_channel)) { ++ ++ AP6210_DEBUG("channel_inform.scan_channel (%d)\n", ++ channel_inform.scan_channel); ++ } ++ wl->bss_list = wl->scan_results; ++ bss_list = wl->bss_list; ++ memset(bss_list, 0, len); ++ bss_list->buflen = htod32(len); ++ err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false); ++ if (unlikely(err) && unlikely(!wl->scan_suppressed)) { ++ AP6210_ERR("%s Scan_results error (%d)\n", ndev->name, err); ++ err = -EINVAL; ++ goto scan_done_out; ++ } ++ bss_list->buflen = dtoh32(bss_list->buflen); ++ bss_list->version = dtoh32(bss_list->version); ++ bss_list->count = dtoh32(bss_list->count); ++ ++ err = wl_inform_bss(wl); ++ ++scan_done_out: ++ del_timer_sync(&wl->scan_timeout); ++ spin_lock_irqsave(&wl->cfgdrv_lock, flags); ++ if (wl->scan_request) { ++ cfg80211_scan_done(wl->scan_request, false); ++ wl->scan_request = NULL; ++ } ++ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); ++ AP6210_DEBUG("cfg80211_scan_done\n"); ++ mutex_unlock(&wl->usr_sync); ++ return err; ++} ++static s32 ++wl_frame_get_mgmt(u16 fc, const struct ether_addr *da, ++ const struct ether_addr *sa, const struct ether_addr *bssid, ++ u8 **pheader, u32 *body_len, u8 *pbody) ++{ ++ struct dot11_management_header *hdr; ++ u32 totlen = 0; ++ s32 err = 0; ++ u8 *offset; ++ u32 prebody_len = *body_len; ++ switch (fc) { ++ case FC_ASSOC_REQ: ++ /* capability , listen interval */ ++ totlen = DOT11_ASSOC_REQ_FIXED_LEN; ++ *body_len += DOT11_ASSOC_REQ_FIXED_LEN; ++ break; ++ ++ case FC_REASSOC_REQ: ++ /* capability, listen inteval, ap address */ ++ totlen = DOT11_REASSOC_REQ_FIXED_LEN; ++ *body_len += DOT11_REASSOC_REQ_FIXED_LEN; ++ break; ++ } ++ totlen += DOT11_MGMT_HDR_LEN + prebody_len; ++ *pheader = kzalloc(totlen, GFP_KERNEL); ++ if (*pheader == NULL) { ++ AP6210_ERR("memory alloc failed \n"); ++ return -ENOMEM; ++ } ++ hdr = (struct dot11_management_header *) (*pheader); ++ hdr->fc = htol16(fc); ++ hdr->durid = 0; ++ hdr->seq = 0; ++ offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len); ++ bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN); ++ bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN); ++ bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN); ++ if ((pbody != NULL) && prebody_len) ++ bcopy((const char*)pbody, offset, prebody_len); ++ *body_len = totlen; ++ return err; ++} ++ ++ ++void ++wl_stop_wait_next_action_frame(struct wl_priv *wl, struct net_device *ndev) ++{ ++ if (wl_get_drv_status_all(wl, SENDING_ACT_FRM) && ++ (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || ++ wl_get_p2p_status(wl, ACTION_TX_NOACK))) { ++ AP6210_DEBUG("*** Wake UP ** abort actframe iovar\n"); ++ /* if channel is not zero, "actfame" uses off channel scan. ++ * So abort scan for off channel completion. ++ */ ++ if (wl->af_sent_channel) ++ /* wl_cfg80211_scan_abort(wl, ndev); */ ++ wl_notify_escan_complete(wl, ++ (ndev == wl->p2p_net) ? wl_to_prmry_ndev(wl) : ndev, true, true); ++ } ++#ifdef WL_CFG80211_SYNC_GON ++ else if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) { ++ AP6210_DEBUG("*** Wake UP ** abort listen for next af frame\n"); ++ /* So abort scan to cancel listen */ ++ wl_notify_escan_complete(wl, ++ (ndev == wl->p2p_net) ? wl_to_prmry_ndev(wl) : ndev, true, true); ++ } ++#endif /* WL_CFG80211_SYNC_GON */ ++} ++ ++static s32 ++wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data) ++{ ++ struct ieee80211_supported_band *band; ++ struct wiphy *wiphy = wl_to_wiphy(wl); ++ struct ether_addr da; ++ struct ether_addr bssid; ++ bool isfree = false; ++ s32 err = 0; ++ s32 freq; ++ struct net_device *dev = NULL; ++ wifi_p2p_pub_act_frame_t *act_frm = NULL; ++ wifi_p2p_action_frame_t *p2p_act_frm = NULL; ++ wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL; ++ wl_event_rx_frame_data_t *rxframe = ++ (wl_event_rx_frame_data_t*)data; ++ u32 event = ntoh32(e->event_type); ++ u8 *mgmt_frame; ++ u8 bsscfgidx = e->bsscfgidx; ++ u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t); ++ u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK)); ++ ++ memset(&bssid, 0, ETHER_ADDR_LEN); ++ ++ if (wl->p2p_net == ndev) { ++ dev = wl_to_prmry_ndev(wl); ++ } else { ++ dev = ndev; ++ } ++ ++ if (channel <= CH_MAX_2G_CHANNEL) ++ band = wiphy->bands[IEEE80211_BAND_2GHZ]; ++ else ++ band = wiphy->bands[IEEE80211_BAND_5GHZ]; ++ if (!band) { ++ AP6210_ERR("No valid band"); ++ return -EINVAL; ++ } ++#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) ++ freq = ieee80211_channel_to_frequency(channel); ++ (void)band->band; ++#else ++ freq = ieee80211_channel_to_frequency(channel, band->band); ++#endif ++ if (event == WLC_E_ACTION_FRAME_RX) { ++ wldev_iovar_getbuf_bsscfg(dev, "cur_etheraddr", ++ NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync); ++ ++ err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); ++ if (err < 0) ++ AP6210_ERR("WLC_GET_BSSID error %d\n", err); ++ memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN); ++ err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid, ++ &mgmt_frame, &mgmt_frame_len, ++ (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1)); ++ if (err < 0) { ++ AP6210_ERR("%s: Error in receiving action frame len %d channel %d freq %d\n", ++ __func__, mgmt_frame_len, channel, freq); ++ goto exit; ++ } ++ isfree = true; ++ if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN], ++ mgmt_frame_len - DOT11_MGMT_HDR_LEN)) { ++ act_frm = (wifi_p2p_pub_act_frame_t *) ++ (&mgmt_frame[DOT11_MGMT_HDR_LEN]); ++ } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN], ++ mgmt_frame_len - DOT11_MGMT_HDR_LEN)) { ++ p2p_act_frm = (wifi_p2p_action_frame_t *) ++ (&mgmt_frame[DOT11_MGMT_HDR_LEN]); ++ (void) p2p_act_frm; ++ } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN], ++ mgmt_frame_len - DOT11_MGMT_HDR_LEN)) { ++ sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *) ++ (&mgmt_frame[DOT11_MGMT_HDR_LEN]); ++ if (sd_act_frm && wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) { ++ if (wl->next_af_subtype == sd_act_frm->action) { ++ AP6210_DEBUG("We got a right next frame of SD!(%d)\n", ++ sd_act_frm->action); ++ wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ++ (ndev == wl->p2p_net) ? ++ wl_to_prmry_ndev(wl) : ndev); ++ ++ /* Stop waiting for next AF. */ ++ wl_stop_wait_next_action_frame(wl, ndev); ++ } ++ } ++ (void) sd_act_frm; ++ } else { ++ /* ++ * if we got normal action frame and ndev is p2p0, ++ * we have to change ndev from p2p0 to wlan0 ++ */ ++ if (wl->p2p_net == ndev) ++ ndev = wl_to_prmry_ndev(wl); ++ } ++ ++ if (act_frm) { ++ ++ if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) { ++ if (wl->next_af_subtype == act_frm->subtype) { ++ AP6210_DEBUG("We got a right next frame!(%d)\n", ++ act_frm->subtype); ++ wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ++ (ndev == wl->p2p_net) ? ++ wl_to_prmry_ndev(wl) : ndev); ++ ++ /* Stop waiting for next AF. */ ++ wl_stop_wait_next_action_frame(wl, ndev); ++ } ++ } ++ } ++ ++ wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN], ++ mgmt_frame_len - DOT11_MGMT_HDR_LEN); ++ /* ++ * After complete GO Negotiation, roll back to mpc mode ++ */ ++ if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) || ++ (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) { ++ wldev_iovar_setint(dev, "mpc", 1); ++ } ++ if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) { ++ AP6210_DEBUG("P2P: GO_NEG_PHASE status cleared \n"); ++ wl_clr_p2p_status(wl, GO_NEG_PHASE); ++ } ++ } else { ++ mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1); ++ ++ /* wpa supplicant use probe request event for restarting another GON Req. ++ * but it makes GON Req repetition. ++ * so if src addr of prb req is same as my target device, ++ * do not send probe request event during sending action frame. ++ */ ++ if (event == WLC_E_P2P_PROBREQ_MSG) { ++ AP6210_DEBUG(" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ? ++ "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"); ++ ++ ++ /* Filter any P2P probe reqs arriving during the ++ * GO-NEG Phase ++ */ ++ if (wl->p2p && ++ wl_get_p2p_status(wl, GO_NEG_PHASE)) { ++ AP6210_DEBUG("Filtering P2P probe_req while " ++ "being in GO-Neg state\n"); ++ return 0; ++ } ++ } ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC); ++#else ++ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC); ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */ ++ ++ AP6210_DEBUG("%s: mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n", __func__, ++ mgmt_frame_len, ntoh32(e->datalen), channel, freq); ++exit: ++ if (isfree) ++ kfree(mgmt_frame); ++ return 0; ++} ++ ++#ifdef WL_SCHED_SCAN ++/* If target scan is not reliable, set the below define to "1" to do a ++ * full escan ++ */ ++#define FULL_ESCAN_ON_PFN_NET_FOUND 0 ++static s32 ++wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data) ++{ ++ wl_pfn_net_info_t *netinfo, *pnetinfo; ++ struct cfg80211_scan_request request; ++ struct wiphy *wiphy = wl_to_wiphy(wl); ++ int err = 0; ++ struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT]; ++ struct ieee80211_channel *channel = NULL; ++ int channel_req = 0; ++ int band = 0; ++ struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data; ++ ++ AP6210_DEBUG("Enter\n"); ++ ++ if (e->event_type == WLC_E_PFN_NET_LOST) { ++ AP6210_DEBUG("PFN NET LOST event. Do Nothing \n"); ++ return 0; ++ } ++ AP6210_DEBUG(">>> PFN NET FOUND event. count:%d \n", pfn_result->count); ++ if (pfn_result->count > 0) { ++ int i; ++ ++ memset(&request, 0x00, sizeof(struct cfg80211_scan_request)); ++ memset(&ssid, 0x00, sizeof(ssid)); ++ request.wiphy = wiphy; ++ ++ pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t) ++ - sizeof(wl_pfn_net_info_t)); ++ channel = (struct ieee80211_channel *)kzalloc( ++ (sizeof(struct ieee80211_channel) * MAX_PFN_LIST_COUNT), ++ GFP_KERNEL); ++ if (!channel) { ++ AP6210_ERR("No memory"); ++ err = -ENOMEM; ++ goto out_err; ++ } ++ ++ for (i = 0; i < pfn_result->count; i++) { ++ netinfo = &pnetinfo[i]; ++ if (!netinfo) { ++ AP6210_ERR("Invalid netinfo ptr. index:%d", i); ++ err = -EINVAL; ++ goto out_err; ++ } ++ AP6210_DEBUG(">>> SSID:%s Channel:%d \n", ++ netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel); ++ /* PFN result doesn't have all the info which are required by the supplicant ++ * (For e.g IEs) Do a target Escan so that sched scan results are reported ++ * via wl_inform_single_bss in the required format. Escan does require the ++ * scan request in the form of cfg80211_scan_request. For timebeing, create ++ * cfg80211_scan_request one out of the received PNO event. ++ */ ++ memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID, ++ netinfo->pfnsubnet.SSID_len); ++ ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len; ++ request.n_ssids++; ++ ++ channel_req = netinfo->pfnsubnet.channel; ++ band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ ++ : NL80211_BAND_5GHZ; ++ channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band); ++ channel[i].band = band; ++ channel[i].flags |= IEEE80211_CHAN_NO_HT40; ++ request.channels[i] = &channel[i]; ++ request.n_channels++; ++ } ++ ++ /* assign parsed ssid array */ ++ if (request.n_ssids) ++ request.ssids = &ssid[0]; ++ ++ if (wl_get_drv_status_all(wl, SCANNING)) { ++ /* Abort any on-going scan */ ++ wl_notify_escan_complete(wl, ndev, true, true); ++ } ++ ++ if (wl_get_p2p_status(wl, DISCOVERY_ON)) { ++ AP6210_DEBUG(">>> P2P discovery was ON. Disabling it\n"); ++ err = wl_cfgp2p_discover_enable_search(wl, false); ++ if (unlikely(err)) { ++ wl_clr_drv_status(wl, SCANNING, ndev); ++ goto out_err; ++ } ++ } ++ ++ wl_set_drv_status(wl, SCANNING, ndev); ++#if FULL_ESCAN_ON_PFN_NET_FOUND ++ AP6210_DEBUG(">>> Doing Full ESCAN on PNO event\n"); ++ err = wl_do_escan(wl, wiphy, ndev, NULL); ++#else ++ AP6210_DEBUG(">>> Doing targeted ESCAN on PNO event\n"); ++ err = wl_do_escan(wl, wiphy, ndev, &request); ++#endif ++ if (err) { ++ wl_clr_drv_status(wl, SCANNING, ndev); ++ goto out_err; ++ } ++ wl->sched_scan_running = TRUE; ++ } ++ else { ++ AP6210_ERR("FALSE PNO Event. (pfn_count == 0) \n"); ++ } ++out_err: ++ if (channel) ++ kfree(channel); ++ return err; ++} ++#endif /* WL_SCHED_SCAN */ ++ ++static void wl_init_conf(struct wl_conf *conf) ++{ ++ AP6210_DEBUG("Enter \n"); ++ conf->frag_threshold = (u32)-1; ++ conf->rts_threshold = (u32)-1; ++ conf->retry_short = (u32)-1; ++ conf->retry_long = (u32)-1; ++ conf->tx_power = -1; ++} ++ ++static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev) ++{ ++ unsigned long flags; ++ struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev); ++ ++ spin_lock_irqsave(&wl->cfgdrv_lock, flags); ++ memset(profile, 0, sizeof(struct wl_profile)); ++ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); ++} ++ ++static void wl_init_event_handler(struct wl_priv *wl) ++{ ++ memset(wl->evt_handler, 0, sizeof(wl->evt_handler)); ++ ++ wl->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status; ++ wl->evt_handler[WLC_E_AUTH] = wl_notify_connect_status; ++ wl->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status; ++ wl->evt_handler[WLC_E_LINK] = wl_notify_connect_status; ++ wl->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status; ++ wl->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status; ++ wl->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status; ++ wl->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status; ++ wl->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status; ++ wl->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status; ++ wl->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status; ++ wl->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status; ++ wl->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame; ++ wl->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame; ++ wl->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame; ++ wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete; ++ wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete; ++ wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete; ++#ifdef PNO_SUPPORT ++ wl->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status; ++#endif /* PNO_SUPPORT */ ++} ++ ++static s32 wl_init_priv_mem(struct wl_priv *wl) ++{ ++ AP6210_DEBUG("Enter \n"); ++ wl->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL); ++ if (unlikely(!wl->scan_results)) { ++ AP6210_ERR("Scan results alloc failed\n"); ++ goto init_priv_mem_out; ++ } ++ wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL); ++ if (unlikely(!wl->conf)) { ++ AP6210_ERR("wl_conf alloc failed\n"); ++ goto init_priv_mem_out; ++ } ++ wl->scan_req_int = ++ (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL); ++ if (unlikely(!wl->scan_req_int)) { ++ AP6210_ERR("Scan req alloc failed\n"); ++ goto init_priv_mem_out; ++ } ++ wl->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL); ++ if (unlikely(!wl->ioctl_buf)) { ++ AP6210_ERR("Ioctl buf alloc failed\n"); ++ goto init_priv_mem_out; ++ } ++ wl->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL); ++ if (unlikely(!wl->escan_ioctl_buf)) { ++ AP6210_ERR("Ioctl buf alloc failed\n"); ++ goto init_priv_mem_out; ++ } ++ wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); ++ if (unlikely(!wl->extra_buf)) { ++ AP6210_ERR("Extra buf alloc failed\n"); ++ goto init_priv_mem_out; ++ } ++ wl->iscan = (void *)kzalloc(sizeof(*wl->iscan), GFP_KERNEL); ++ if (unlikely(!wl->iscan)) { ++ AP6210_ERR("Iscan buf alloc failed\n"); ++ goto init_priv_mem_out; ++ } ++ wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL); ++ if (unlikely(!wl->pmk_list)) { ++ AP6210_ERR("pmk list alloc failed\n"); ++ goto init_priv_mem_out; ++ } ++ wl->sta_info = (void *)kzalloc(sizeof(*wl->sta_info), GFP_KERNEL); ++ if (unlikely(!wl->sta_info)) { ++ AP6210_ERR("sta info alloc failed\n"); ++ goto init_priv_mem_out; ++ } ++ ++#if defined(STATIC_WL_PRIV_STRUCT) ++ wl->conn_info = (void *)kzalloc(sizeof(*wl->conn_info), GFP_KERNEL); ++ if (unlikely(!wl->conn_info)) { ++ AP6210_ERR("wl->conn_info alloc failed\n"); ++ goto init_priv_mem_out; ++ } ++ wl->ie = (void *)kzalloc(sizeof(*wl->ie), GFP_KERNEL); ++ if (unlikely(!wl->ie)) { ++ AP6210_ERR("wl->ie alloc failed\n"); ++ goto init_priv_mem_out; ++ } ++ wl->escan_info.escan_buf = dhd_os_prealloc(NULL, DHD_PREALLOC_WIPHY_ESCAN0, 0); ++ bzero(wl->escan_info.escan_buf, ESCAN_BUF_SIZE); ++#endif /* STATIC_WL_PRIV_STRUCT */ ++ wl->afx_hdl = (void *)kzalloc(sizeof(*wl->afx_hdl), GFP_KERNEL); ++ if (unlikely(!wl->afx_hdl)) { ++ AP6210_ERR("afx hdl alloc failed\n"); ++ goto init_priv_mem_out; ++ } else { ++ init_completion(&wl->act_frm_scan); ++ init_completion(&wl->wait_next_af); ++ ++ INIT_WORK(&wl->afx_hdl->work, wl_cfg80211_afx_handler); ++ } ++ return 0; ++ ++init_priv_mem_out: ++ wl_deinit_priv_mem(wl); ++ ++ return -ENOMEM; ++} ++ ++static void wl_deinit_priv_mem(struct wl_priv *wl) ++{ ++ kfree(wl->scan_results); ++ wl->scan_results = NULL; ++ kfree(wl->conf); ++ wl->conf = NULL; ++ kfree(wl->scan_req_int); ++ wl->scan_req_int = NULL; ++ kfree(wl->ioctl_buf); ++ wl->ioctl_buf = NULL; ++ kfree(wl->escan_ioctl_buf); ++ wl->escan_ioctl_buf = NULL; ++ kfree(wl->extra_buf); ++ wl->extra_buf = NULL; ++ kfree(wl->iscan); ++ wl->iscan = NULL; ++ kfree(wl->pmk_list); ++ wl->pmk_list = NULL; ++ kfree(wl->sta_info); ++ wl->sta_info = NULL; ++#if defined(STATIC_WL_PRIV_STRUCT) ++ kfree(wl->conn_info); ++ wl->conn_info = NULL; ++ kfree(wl->ie); ++ wl->ie = NULL; ++ wl->escan_info.escan_buf = NULL; ++#endif /* STATIC_WL_PRIV_STRUCT */ ++ if (wl->afx_hdl) { ++ cancel_work_sync(&wl->afx_hdl->work); ++ kfree(wl->afx_hdl); ++ wl->afx_hdl = NULL; ++ } ++ ++ if (wl->ap_info) { ++ kfree(wl->ap_info->wpa_ie); ++ kfree(wl->ap_info->rsn_ie); ++ kfree(wl->ap_info->wps_ie); ++ kfree(wl->ap_info); ++ wl->ap_info = NULL; ++ } ++} ++ ++static s32 wl_create_event_handler(struct wl_priv *wl) ++{ ++ int ret = 0; ++ AP6210_DEBUG("Enter \n"); ++ ++ /* Do not use DHD in cfg driver */ ++ wl->event_tsk.thr_pid = -1; ++ ++#ifdef USE_KTHREAD_API ++ PROC_START2(wl_event_handler, wl, &wl->event_tsk, 0, "wl_event_handler"); ++#else ++ PROC_START(wl_event_handler, wl, &wl->event_tsk, 0); ++#endif ++ if (wl->event_tsk.thr_pid < 0) ++ ret = -ENOMEM; ++ return ret; ++} ++ ++static void wl_destroy_event_handler(struct wl_priv *wl) ++{ ++ if (wl->event_tsk.thr_pid >= 0) ++ PROC_STOP(&wl->event_tsk); ++} ++ ++static void wl_term_iscan(struct wl_priv *wl) ++{ ++ struct wl_iscan_ctrl *iscan = wl_to_iscan(wl); ++ AP6210_DEBUG("In\n"); ++ if (wl->iscan_on && iscan->tsk) { ++ iscan->state = WL_ISCAN_STATE_IDLE; ++ AP6210_DEBUG("SIGTERM\n"); ++ send_sig(SIGTERM, iscan->tsk, 1); ++ AP6210_DEBUG("kthread_stop\n"); ++ kthread_stop(iscan->tsk); ++ iscan->tsk = NULL; ++ } ++} ++ ++static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted) ++{ ++ struct wl_priv *wl = iscan_to_wl(iscan); ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++ unsigned long flags; ++ ++ AP6210_DEBUG("Enter \n"); ++ if (!wl_get_drv_status(wl, SCANNING, ndev)) { ++ wl_clr_drv_status(wl, SCANNING, ndev); ++ AP6210_ERR("Scan complete while device not scanning\n"); ++ return; ++ } ++ spin_lock_irqsave(&wl->cfgdrv_lock, flags); ++ wl_clr_drv_status(wl, SCANNING, ndev); ++ if (likely(wl->scan_request)) { ++ cfg80211_scan_done(wl->scan_request, aborted); ++ wl->scan_request = NULL; ++ } ++ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); ++ wl->iscan_kickstart = false; ++} ++ ++static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan) ++{ ++ if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) { ++ AP6210_DEBUG("wake up iscan\n"); ++ up(&iscan->sync); ++ return 0; ++ } ++ ++ return -EIO; ++} ++ ++static s32 ++wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status, ++ struct wl_scan_results **bss_list) ++{ ++ struct wl_iscan_results list; ++ struct wl_scan_results *results; ++ struct wl_iscan_results *list_buf; ++ s32 err = 0; ++ ++ AP6210_DEBUG("Enter \n"); ++ memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX); ++ list_buf = (struct wl_iscan_results *)iscan->scan_buf; ++ results = &list_buf->results; ++ results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE; ++ results->version = 0; ++ results->count = 0; ++ ++ memset(&list, 0, sizeof(list)); ++ list.results.buflen = htod32(WL_ISCAN_BUF_MAX); ++ err = wldev_iovar_getbuf(iscan->dev, "iscanresults", &list, ++ WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf, ++ WL_ISCAN_BUF_MAX, NULL); ++ if (unlikely(err)) { ++ AP6210_ERR("error (%d)\n", err); ++ return err; ++ } ++ results->buflen = dtoh32(results->buflen); ++ results->version = dtoh32(results->version); ++ results->count = dtoh32(results->count); ++ AP6210_DEBUG("results->count = %d\n", results->count); ++ AP6210_DEBUG("results->buflen = %d\n", results->buflen); ++ *status = dtoh32(list_buf->status); ++ *bss_list = results; ++ ++ return err; ++} ++ ++static s32 wl_iscan_done(struct wl_priv *wl) ++{ ++ struct wl_iscan_ctrl *iscan = wl->iscan; ++ s32 err = 0; ++ ++ iscan->state = WL_ISCAN_STATE_IDLE; ++ mutex_lock(&wl->usr_sync); ++ wl_inform_bss(wl); ++ wl_notify_iscan_complete(iscan, false); ++ mutex_unlock(&wl->usr_sync); ++ ++ return err; ++} ++ ++static s32 wl_iscan_pending(struct wl_priv *wl) ++{ ++ struct wl_iscan_ctrl *iscan = wl->iscan; ++ s32 err = 0; ++ ++ /* Reschedule the timer */ ++ mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms)); ++ iscan->timer_on = 1; ++ ++ return err; ++} ++ ++static s32 wl_iscan_inprogress(struct wl_priv *wl) ++{ ++ struct wl_iscan_ctrl *iscan = wl->iscan; ++ s32 err = 0; ++ ++ mutex_lock(&wl->usr_sync); ++ wl_inform_bss(wl); ++ wl_run_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE); ++ mutex_unlock(&wl->usr_sync); ++ /* Reschedule the timer */ ++ mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms)); ++ iscan->timer_on = 1; ++ ++ return err; ++} ++ ++static s32 wl_iscan_aborted(struct wl_priv *wl) ++{ ++ struct wl_iscan_ctrl *iscan = wl->iscan; ++ s32 err = 0; ++ ++ iscan->state = WL_ISCAN_STATE_IDLE; ++ mutex_lock(&wl->usr_sync); ++ wl_notify_iscan_complete(iscan, true); ++ mutex_unlock(&wl->usr_sync); ++ ++ return err; ++} ++ ++static s32 wl_iscan_thread(void *data) ++{ ++ struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data; ++ struct wl_priv *wl = iscan_to_wl(iscan); ++ u32 status; ++ int err = 0; ++ ++ allow_signal(SIGTERM); ++ status = WL_SCAN_RESULTS_PARTIAL; ++ while (likely(!down_interruptible(&iscan->sync))) { ++ if (kthread_should_stop()) ++ break; ++ if (iscan->timer_on) { ++ del_timer_sync(&iscan->timer); ++ iscan->timer_on = 0; ++ } ++ mutex_lock(&wl->usr_sync); ++ err = wl_get_iscan_results(iscan, &status, &wl->bss_list); ++ if (unlikely(err)) { ++ status = WL_SCAN_RESULTS_ABORTED; ++ AP6210_ERR("Abort iscan\n"); ++ } ++ mutex_unlock(&wl->usr_sync); ++ iscan->iscan_handler[status] (wl); ++ } ++ if (iscan->timer_on) { ++ del_timer_sync(&iscan->timer); ++ iscan->timer_on = 0; ++ } ++ AP6210_DEBUG("%s was terminated\n", __func__); ++ ++ return 0; ++} ++ ++static void wl_scan_timeout(unsigned long data) ++{ ++ wl_event_msg_t msg; ++ struct wl_priv *wl = (struct wl_priv *)data; ++ ++ if (!(wl->scan_request)) { ++ AP6210_ERR("timer expired but no scan request\n"); ++ return; ++ } ++ bzero(&msg, sizeof(wl_event_msg_t)); ++ AP6210_ERR("timer expired\n"); ++ if (wl->escan_on) { ++ msg.event_type = hton32(WLC_E_ESCAN_RESULT); ++ msg.status = hton32(WLC_E_STATUS_TIMEOUT); ++ msg.reason = 0xFFFFFFFF; ++ wl_cfg80211_event(wl_to_prmry_ndev(wl), &msg, NULL); ++ } else { ++ AP6210_ERR("SCAN Timeout(ISCAN)\n"); ++ wl_notify_iscan_complete(wl_to_iscan(wl), true); ++ } ++} ++static void wl_iscan_timer(unsigned long data) ++{ ++ struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data; ++ ++ if (iscan) { ++ iscan->timer_on = 0; ++ AP6210_DEBUG("timer expired\n"); ++ wl_wakeup_iscan(iscan); ++ } ++} ++ ++static s32 wl_invoke_iscan(struct wl_priv *wl) ++{ ++ struct wl_iscan_ctrl *iscan = wl_to_iscan(wl); ++ int err = 0; ++ ++ if (wl->iscan_on && !iscan->tsk) { ++ iscan->state = WL_ISCAN_STATE_IDLE; ++ sema_init(&iscan->sync, 0); ++ iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan"); ++ if (IS_ERR(iscan->tsk)) { ++ AP6210_ERR("Could not create iscan thread\n"); ++ iscan->tsk = NULL; ++ return -ENOMEM; ++ } ++ } ++ ++ return err; ++} ++ ++static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan) ++{ ++ memset(iscan->iscan_handler, 0, sizeof(iscan->iscan_handler)); ++ iscan->iscan_handler[WL_SCAN_RESULTS_SUCCESS] = wl_iscan_done; ++ iscan->iscan_handler[WL_SCAN_RESULTS_PARTIAL] = wl_iscan_inprogress; ++ iscan->iscan_handler[WL_SCAN_RESULTS_PENDING] = wl_iscan_pending; ++ iscan->iscan_handler[WL_SCAN_RESULTS_ABORTED] = wl_iscan_aborted; ++ iscan->iscan_handler[WL_SCAN_RESULTS_NO_MEM] = wl_iscan_aborted; ++} ++ ++static s32 ++wl_cfg80211_netdev_notifier_call(struct notifier_block * nb, ++ unsigned long state, ++ void *ndev) ++{ ++ struct net_device *dev = ndev; ++ struct wireless_dev *wdev = dev->ieee80211_ptr; ++ struct wl_priv *wl = wlcfg_drv_priv; ++ int refcnt = 0; ++ ++ AP6210_DEBUG("Enter \n"); ++ if (!wdev || !wl || dev == wl_to_prmry_ndev(wl)) ++ return NOTIFY_DONE; ++ switch (state) { ++ case NETDEV_DOWN: ++ while (work_pending(&wdev->cleanup_work) && refcnt < 100) { ++ if (refcnt%5 == 0) ++ AP6210_ERR("%s : [NETDEV_DOWN] work_pending (%d th)\n", ++ __FUNCTION__, refcnt); ++ set_current_state(TASK_INTERRUPTIBLE); ++ schedule_timeout(100); ++ set_current_state(TASK_RUNNING); ++ refcnt++; ++ } ++ break; ++ ++ case NETDEV_UNREGISTER: ++ /* after calling list_del_rcu(&wdev->list) */ ++ wl_dealloc_netinfo(wl, ndev); ++ break; ++ case NETDEV_GOING_DOWN: ++ /* At NETDEV_DOWN state, wdev_cleanup_work work will be called. ++ * In front of door, the function checks ++ * whether current scan is working or not. ++ * If the scanning is still working, wdev_cleanup_work call WARN_ON and ++ * make the scan done forcibly. ++ */ ++ if (wl_get_drv_status(wl, SCANNING, dev)) { ++ if (wl->escan_on) { ++ wl_notify_escan_complete(wl, dev, true, true); ++ } ++ } ++ break; ++ } ++ return NOTIFY_DONE; ++} ++static struct notifier_block wl_cfg80211_netdev_notifier = { ++ .notifier_call = wl_cfg80211_netdev_notifier_call, ++}; ++ ++static s32 wl_notify_escan_complete(struct wl_priv *wl, ++ struct net_device *ndev, ++ bool aborted, bool fw_abort) ++{ ++ wl_scan_params_t *params = NULL; ++ s32 params_size = 0; ++ s32 err = BCME_OK; ++ unsigned long flags; ++ struct net_device *dev; ++ ++ AP6210_DEBUG("Enter \n"); ++ ++ if (wl->escan_info.ndev != ndev) ++ { ++ AP6210_ERR("ndev is different %p %p\n", wl->escan_info.ndev, ndev); ++ return err; ++ } ++ ++ if (wl->scan_request) { ++ if (wl->scan_request->dev == wl->p2p_net) ++ dev = wl_to_prmry_ndev(wl); ++ else ++ dev = wl->scan_request->dev; ++ } ++ else { ++ AP6210_DEBUG("wl->scan_request is NULL may be internal scan." ++ "doing scan_abort for ndev %p primary %p p2p_net %p", ++ ndev, wl_to_prmry_ndev(wl), wl->p2p_net); ++ dev = ndev; ++ } ++ if (fw_abort && !in_atomic()) { ++ /* Our scan params only need space for 1 channel and 0 ssids */ ++ params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size); ++ if (params == NULL) { ++ AP6210_ERR("scan params allocation failed \n"); ++ err = -ENOMEM; ++ } else { ++ /* Do a scan abort to stop the driver's scan engine */ ++ err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true); ++ if (err < 0) { ++ AP6210_ERR("scan abort failed \n"); ++ } ++ } ++ } ++ if (timer_pending(&wl->scan_timeout)) ++ del_timer_sync(&wl->scan_timeout); ++#if defined(ESCAN_RESULT_PATCH) ++ if (likely(wl->scan_request)) { ++ wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; ++ wl_inform_bss(wl); ++ } ++#endif /* ESCAN_RESULT_PATCH */ ++ spin_lock_irqsave(&wl->cfgdrv_lock, flags); ++#ifdef WL_SCHED_SCAN ++ if (wl->sched_scan_req && !wl->scan_request) { ++ AP6210_DEBUG(">>> REPORTING SCHED SCAN RESULTS \n"); ++ if (aborted) ++ cfg80211_sched_scan_stopped(wl->sched_scan_req->wiphy); ++ else ++ cfg80211_sched_scan_results(wl->sched_scan_req->wiphy); ++ wl->sched_scan_running = FALSE; ++ wl->sched_scan_req = NULL; ++ } ++#endif /* WL_SCHED_SCAN */ ++ if (likely(wl->scan_request)) { ++ cfg80211_scan_done(wl->scan_request, aborted); ++ wl->scan_request = NULL; ++ } ++ if (p2p_is_on(wl)) ++ wl_clr_p2p_status(wl, SCANNING); ++ wl_clr_drv_status(wl, SCANNING, dev); ++ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); ++ if (params) ++ kfree(params); ++ ++ return err; ++} ++ ++static s32 wl_escan_handler(struct wl_priv *wl, ++ struct net_device *ndev, ++ const wl_event_msg_t *e, void *data) ++{ ++ s32 err = BCME_OK; ++ s32 status = ntoh32(e->status); ++ wl_bss_info_t *bi; ++ wl_escan_result_t *escan_result; ++ wl_bss_info_t *bss = NULL; ++ wl_scan_results_t *list; ++ wifi_p2p_ie_t * p2p_ie; ++ u32 bi_length; ++ u32 i; ++ u8 *p2p_dev_addr = NULL; ++ ++ AP6210_DEBUG(" enter event type : %d, status : %d \n", ++ ntoh32(e->event_type), ntoh32(e->status)); ++ ++ mutex_lock(&wl->usr_sync); ++ /* P2P SCAN is coming from primary interface */ ++ if (wl_get_p2p_status(wl, SCANNING)) { ++ if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) ++ ndev = wl->afx_hdl->dev; ++ else ++ ndev = wl->escan_info.ndev; ++ ++ } ++ if (!ndev || !wl->escan_on || ++ (!wl_get_drv_status(wl, SCANNING, ndev) && ++ !wl->sched_scan_running)) { ++ AP6210_ERR("escan is not ready ndev %p wl->escan_on %d drv_status 0x%x\n", ++ ndev, wl->escan_on, wl_get_drv_status(wl, SCANNING, ndev)); ++ goto exit; ++ } ++ if (status == WLC_E_STATUS_PARTIAL) { ++ AP6210_DEBUG("WLC_E_STATUS_PARTIAL \n"); ++ escan_result = (wl_escan_result_t *) data; ++ if (!escan_result) { ++ AP6210_ERR("Invalid escan result (NULL pointer)\n"); ++ goto exit; ++ } ++ if (dtoh16(escan_result->bss_count) != 1) { ++ AP6210_ERR("Invalid bss_count %d: ignoring\n", escan_result->bss_count); ++ goto exit; ++ } ++ bi = escan_result->bss_info; ++ if (!bi) { ++ AP6210_ERR("Invalid escan bss info (NULL pointer)\n"); ++ goto exit; ++ } ++ bi_length = dtoh32(bi->length); ++ if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) { ++ AP6210_ERR("Invalid bss_info length %d: ignoring\n", bi_length); ++ goto exit; ++ } ++ ++ if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) { ++ if (dtoh16(bi->capability) & DOT11_CAP_IBSS) { ++ AP6210_DEBUG("Ignoring IBSS result\n"); ++ goto exit; ++ } ++ } ++ ++ if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) { ++ p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length); ++ if (p2p_dev_addr && !memcmp(p2p_dev_addr, ++ wl->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) { ++ s32 channel = CHSPEC_CHANNEL( ++ wl_chspec_driver_to_host(bi->chanspec)); ++ AP6210_DEBUG("ACTION FRAME SCAN : Peer " MACDBG " found, channel : %d\n", ++ MAC2STRDBG(wl->afx_hdl->tx_dst_addr.octet), channel); ++ wl_clr_p2p_status(wl, SCANNING); ++ wl->afx_hdl->peer_chan = channel; ++ complete(&wl->act_frm_scan); ++ goto exit; ++ } ++ ++ } else { ++ int cur_len = WL_SCAN_RESULTS_FIXED_SIZE; ++ list = (wl_scan_results_t *)wl->escan_info.escan_buf; ++#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) ++ if (wl->p2p_net && wl->scan_request && ++ wl->scan_request->dev == wl->p2p_net) ++#else ++ if (p2p_is_on(wl) && p2p_scan(wl)) ++#endif ++ { ++#ifdef WL_HOST_BAND_MGMT ++ s32 channel = 0; ++ s32 channel_band = 0; ++#endif /* WL_HOST_BAND_MGMT */ ++ /* p2p scan && allow only probe response */ ++ if (bi->flags & WL_BSS_FLAGS_FROM_BEACON) ++ goto exit; ++ if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset, ++ bi->ie_length)) == NULL) { ++ AP6210_ERR("Couldn't find P2PIE in probe" ++ " response/beacon\n"); ++ goto exit; ++ } ++#ifdef WL_HOST_BAND_MGMT ++ channel = CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec)); ++ channel_band = (channel > CH_MAX_2G_CHANNEL) ? ++ WLC_BAND_5G : WLC_BAND_2G; ++ ++ ++ if ((wl->curr_band == WLC_BAND_5G) && ++ (channel_band == WLC_BAND_2G)) { ++ /* Avoid sending the GO results in band conflict */ ++ if (wl_cfgp2p_retreive_p2pattrib(p2p_ie, ++ P2P_SEID_GROUP_ID) != NULL) ++ goto exit; ++ } ++#endif /* WL_HOST_BAND_MGMT */ ++ } ++ for (i = 0; i < list->count; i++) { ++ bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) ++ : list->bss_info; ++ ++ if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) && ++ (CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec)) ++ == CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) && ++ bi->SSID_len == bss->SSID_len && ++ !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) { ++ ++ /* do not allow beacon data to update ++ *the data recd from a probe response ++ */ ++ if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) && ++ (bi->flags & WL_BSS_FLAGS_FROM_BEACON)) ++ goto exit; ++ ++ AP6210_DEBUG("%s("MACDBG"), i=%d prev: RSSI %d" ++ " flags 0x%x, new: RSSI %d flags 0x%x\n", ++ bss->SSID, MAC2STRDBG(bi->BSSID.octet), i, ++ bss->RSSI, bss->flags, bi->RSSI, bi->flags); ++ ++ if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == ++ (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) { ++ /* preserve max RSSI if the measurements are ++ * both on-channel or both off-channel ++ */ ++ AP6210_DEBUG("%s("MACDBG"), same onchan" ++ ", RSSI: prev %d new %d\n", ++ bss->SSID, MAC2STRDBG(bi->BSSID.octet), ++ bss->RSSI, bi->RSSI); ++ bi->RSSI = MAX(bss->RSSI, bi->RSSI); ++ } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) && ++ (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) { ++ /* preserve the on-channel rssi measurement ++ * if the new measurement is off channel ++ */ ++ AP6210_DEBUG("%s("MACDBG"), prev onchan" ++ ", RSSI: prev %d new %d\n", ++ bss->SSID, MAC2STRDBG(bi->BSSID.octet), ++ bss->RSSI, bi->RSSI); ++ bi->RSSI = bss->RSSI; ++ bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL; ++ } ++ if (dtoh32(bss->length) != bi_length) { ++ u32 prev_len = dtoh32(bss->length); ++ ++ AP6210_DEBUG("bss info replacement" ++ " is occured(bcast:%d->probresp%d)\n", ++ bss->ie_length, bi->ie_length); ++ AP6210_DEBUG("%s("MACDBG"), replacement!(%d -> %d)\n", ++ bss->SSID, MAC2STRDBG(bi->BSSID.octet), ++ prev_len, bi_length); ++ ++ if (list->buflen - prev_len + bi_length ++ > ESCAN_BUF_SIZE) { ++ AP6210_ERR("Buffer is too small: keep the" ++ " previous result of this AP\n"); ++ /* Only update RSSI */ ++ bss->RSSI = bi->RSSI; ++ bss->flags |= (bi->flags ++ & WL_BSS_FLAGS_RSSI_ONCHANNEL); ++ goto exit; ++ } ++ ++ if (i < list->count - 1) { ++ /* memory copy required by this case only */ ++ memmove((u8 *)bss + bi_length, ++ (u8 *)bss + prev_len, ++ list->buflen - cur_len - prev_len); ++ } ++ list->buflen -= prev_len; ++ list->buflen += bi_length; ++ } ++ list->version = dtoh32(bi->version); ++ memcpy((u8 *)bss, (u8 *)bi, bi_length); ++ goto exit; ++ } ++ cur_len += dtoh32(bss->length); ++ } ++ if (bi_length > ESCAN_BUF_SIZE - list->buflen) { ++ AP6210_ERR("Buffer is too small: ignoring\n"); ++ goto exit; ++ } ++ if (strlen(bi->SSID) == 0) { // terence: fix for hidden SSID ++ AP6210_DEBUG("Skip hidden SSID %pM\n", &bi->BSSID); ++ goto exit; ++ } ++ memcpy(&(wl->escan_info.escan_buf[list->buflen]), bi, bi_length); ++ list->version = dtoh32(bi->version); ++ list->buflen += bi_length; ++ list->count++; ++ } ++ ++ } ++ else if (status == WLC_E_STATUS_SUCCESS) { ++ wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; ++ if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) { ++ AP6210_DEBUG("ACTION FRAME SCAN DONE\n"); ++ wl_clr_p2p_status(wl, SCANNING); ++ wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); ++ if (wl->afx_hdl->peer_chan == WL_INVALID) ++ complete(&wl->act_frm_scan); ++ } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) { ++ AP6210_DEBUG("ESCAN COMPLETED\n"); ++ wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; ++ wl_inform_bss(wl); ++ wl_notify_escan_complete(wl, ndev, false, false); ++ } ++ } ++ else if (status == WLC_E_STATUS_ABORT) { ++ wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; ++ if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) { ++ AP6210_DEBUG("ACTION FRAME SCAN DONE\n"); ++ wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); ++ wl_clr_p2p_status(wl, SCANNING); ++ if (wl->afx_hdl->peer_chan == WL_INVALID) ++ complete(&wl->act_frm_scan); ++ } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) { ++ AP6210_DEBUG("ESCAN ABORTED\n"); ++ wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; ++ wl_inform_bss(wl); ++ wl_notify_escan_complete(wl, ndev, true, false); ++ } ++ } ++ else if (status == WLC_E_STATUS_NEWSCAN) ++ { ++ escan_result = (wl_escan_result_t *) data; ++ AP6210_ERR("WLC_E_STATUS_NEWSCAN : scan_request[%p]\n", wl->scan_request); ++ AP6210_ERR("sync_id[%d], bss_count[%d]\n", escan_result->sync_id, ++ escan_result->bss_count); ++ } else if (status == WLC_E_STATUS_TIMEOUT) { ++ AP6210_ERR("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", wl->scan_request); ++ AP6210_ERR("escan_on[%d], reason[0x%x]\n", wl->escan_on, e->reason); ++ if (e->reason == 0xFFFFFFFF) { ++ wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true); ++ } ++ } else { ++ AP6210_ERR("unexpected Escan Event %d : abort\n", status); ++ wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; ++ if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) { ++ AP6210_DEBUG("ACTION FRAME SCAN DONE\n"); ++ wl_clr_p2p_status(wl, SCANNING); ++ wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); ++ if (wl->afx_hdl->peer_chan == WL_INVALID) ++ complete(&wl->act_frm_scan); ++ } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) { ++ wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; ++ wl_inform_bss(wl); ++ wl_notify_escan_complete(wl, ndev, true, false); ++ } ++ } ++exit: ++ mutex_unlock(&wl->usr_sync); ++ return err; ++} ++static void wl_cfg80211_concurrent_roam(struct wl_priv *wl, int enable) ++{ ++ u32 connected_cnt = wl_get_drv_status_all(wl, CONNECTED); ++ struct net_info *iter, *next; ++ int err; ++ ++ if (!wl->roamoff_on_concurrent) ++ return; ++ if (enable && connected_cnt > 1) { ++ for_each_ndev(wl, iter, next) { ++ /* Save the current roam setting */ ++ if ((err = wldev_iovar_getint(iter->ndev, "roam_off", ++ (s32 *)&iter->roam_off)) != BCME_OK) { ++ AP6210_ERR("%s:Failed to get current roam setting err %d\n", ++ iter->ndev->name, err); ++ continue; ++ } ++ if ((err = wldev_iovar_setint(iter->ndev, "roam_off", 1)) != BCME_OK) { ++ AP6210_ERR(" %s:failed to set roam_off : %d\n", ++ iter->ndev->name, err); ++ } ++ } ++ } ++ else if (!enable) { ++ for_each_ndev(wl, iter, next) { ++ if (iter->roam_off != WL_INVALID) { ++ if ((err = wldev_iovar_setint(iter->ndev, "roam_off", ++ iter->roam_off)) == BCME_OK) ++ iter->roam_off = WL_INVALID; ++ else { ++ AP6210_ERR(" %s:failed to set roam_off : %d\n", ++ iter->ndev->name, err); ++ } ++ } ++ } ++ } ++ return; ++} ++ ++static void wl_cfg80211_determine_vsdb_mode(struct wl_priv *wl) ++{ ++ struct net_info *iter, *next; ++ u32 chan = 0; ++ u32 chanspec = 0; ++ u32 prev_chan = 0; ++ u32 connected_cnt = wl_get_drv_status_all(wl, CONNECTED); ++ wl->vsdb_mode = false; ++ ++ if (connected_cnt <= 1) { ++ return; ++ } ++ for_each_ndev(wl, iter, next) { ++ chanspec = 0; ++ chan = 0; ++ if (wl_get_drv_status(wl, CONNECTED, iter->ndev)) { ++ if (wldev_iovar_getint(iter->ndev, "chanspec", ++ (s32 *)&chanspec) == BCME_OK) { ++ chan = CHSPEC_CHANNEL(chanspec); ++ if (CHSPEC_IS40(chanspec)) { ++ if (CHSPEC_SB_UPPER(chanspec)) ++ chan += CH_10MHZ_APART; ++ else ++ chan -= CH_10MHZ_APART; ++ } ++ wl_update_prof(wl, iter->ndev, NULL, ++ &chan, WL_PROF_CHAN); ++ } ++ if (!prev_chan && chan) ++ prev_chan = chan; ++ else if (prev_chan && (prev_chan != chan)) ++ wl->vsdb_mode = true; ++ } ++ } ++ return; ++} ++static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info, ++ enum wl_status state, bool set) ++{ ++ s32 pm = PM_FAST; ++ s32 err = BCME_OK; ++ u32 chan = 0; ++ struct net_info *iter, *next; ++ struct net_device *primary_dev = wl_to_prmry_ndev(wl); ++ AP6210_DEBUG("Enter state %d set %d _net_info->pm_restore %d iface %s\n", ++ state, set, _net_info->pm_restore, _net_info->ndev->name); ++ ++ if (state != WL_STATUS_CONNECTED) ++ return 0; ++ ++ if (set) { ++ wl_cfg80211_concurrent_roam(wl, 1); ++ ++ if (wl_get_mode_by_netdev(wl, _net_info->ndev) == WL_MODE_AP) { ++ pm = PM_OFF; ++ AP6210_DEBUG("%s:AP power save %s\n", _net_info->ndev->name, ++ pm ? "enabled" : "disabled"); ++ if ((err = wldev_ioctl(_net_info->ndev, WLC_SET_PM, ++ &pm, sizeof(pm), true)) != 0) { ++ if (err == -ENODEV) ++ AP6210_DEBUG("%s:net_device is not ready\n", ++ _net_info->ndev->name); ++ else ++ AP6210_ERR("%s:error (%d)\n", _net_info->ndev->name, err); ++ } ++ if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false)) ++ AP6210_ERR(" failed to unset WLC_E_P2P_PROPREQ_MSG\n"); ++ return 0; ++ } ++ wl_cfg80211_determine_vsdb_mode(wl); ++ pm = PM_OFF; ++ for_each_ndev(wl, iter, next) { ++ if ((!wl->vsdb_mode) && (iter->ndev != _net_info->ndev)) { ++ /* Do not touch the other interfaces power save ++ * if we are not in vsdb mode ++ */ ++ continue; ++ } ++ /* Save the current power mode */ ++ iter->pm_restore = true; ++ err = wldev_ioctl(iter->ndev, WLC_GET_PM, &iter->pm, ++ sizeof(iter->pm), false); ++ AP6210_DEBUG("%s:power save %s\n", iter->ndev->name, ++ iter->pm ? "enabled" : "disabled"); ++ if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm, ++ sizeof(pm), true)) != 0) { ++ if (err == -ENODEV) ++ AP6210_DEBUG("%s:netdev not ready\n", iter->ndev->name); ++ else ++ AP6210_ERR("%s:error (%d)\n", iter->ndev->name, err); ++ iter->ndev->ieee80211_ptr->ps = pm ? true: false; ++ } ++ } ++ } ++ else { /* clear */ ++ chan = 0; ++ /* clear chan information when the net device is disconnected */ ++ wl_update_prof(wl, _net_info->ndev, NULL, &chan, WL_PROF_CHAN); ++ wl_cfg80211_determine_vsdb_mode(wl); ++ for_each_ndev(wl, iter, next) { ++ if (iter->pm_restore) { ++ AP6210_DEBUG("%s:restoring power save %s\n", ++ iter->ndev->name, (iter->pm ? "enabled" : "disabled")); ++ err = wldev_ioctl(iter->ndev, ++ WLC_SET_PM, &iter->pm, sizeof(iter->pm), true); ++ if (unlikely(err)) { ++ if (err == -ENODEV) ++ AP6210_DEBUG("%s:netdev not ready\n", iter->ndev->name); ++ else ++ AP6210_ERR("%s:error(%d)\n", iter->ndev->name, err); ++ break; ++ } ++ iter->pm_restore = 0; ++ } ++ } ++ wl_cfg80211_concurrent_roam(wl, 0); ++ } ++ return err; ++} ++ ++static s32 wl_init_scan(struct wl_priv *wl) ++{ ++ struct wl_iscan_ctrl *iscan = wl_to_iscan(wl); ++ int err = 0; ++ ++ if (wl->iscan_on) { ++ iscan->dev = wl_to_prmry_ndev(wl); ++ iscan->state = WL_ISCAN_STATE_IDLE; ++ wl_init_iscan_handler(iscan); ++ iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS; ++ init_timer(&iscan->timer); ++ iscan->timer.data = (unsigned long) iscan; ++ iscan->timer.function = wl_iscan_timer; ++ sema_init(&iscan->sync, 0); ++ iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan"); ++ if (IS_ERR(iscan->tsk)) { ++ AP6210_ERR("Could not create iscan thread\n"); ++ iscan->tsk = NULL; ++ return -ENOMEM; ++ } ++ iscan->data = wl; ++ } else if (wl->escan_on) { ++ wl->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler; ++ wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; ++ } ++ /* Init scan_timeout timer */ ++ init_timer(&wl->scan_timeout); ++ wl->scan_timeout.data = (unsigned long) wl; ++ wl->scan_timeout.function = wl_scan_timeout; ++ ++ return err; ++} ++ ++static s32 wl_init_priv(struct wl_priv *wl) ++{ ++ struct wiphy *wiphy = wl_to_wiphy(wl); ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++ s32 err = 0; ++ ++ wl->scan_request = NULL; ++ wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT); ++ wl->iscan_on = false; ++ wl->escan_on = true; ++ wl->roam_on = false; ++ wl->iscan_kickstart = false; ++ wl->active_scan = true; ++ wl->rf_blocked = false; ++ wl->vsdb_mode = false; ++ wl->wlfc_on = false; ++ wl->roamoff_on_concurrent = true; ++ /* register interested state */ ++ set_bit(WL_STATUS_CONNECTED, &wl->interrested_state); ++ spin_lock_init(&wl->cfgdrv_lock); ++ mutex_init(&wl->ioctl_buf_sync); ++ init_waitqueue_head(&wl->netif_change_event); ++ init_completion(&wl->send_af_done); ++ init_completion(&wl->iface_disable); ++ wl_init_eq(wl); ++ err = wl_init_priv_mem(wl); ++ if (err) ++ return err; ++ if (wl_create_event_handler(wl)) ++ return -ENOMEM; ++ wl_init_event_handler(wl); ++ mutex_init(&wl->usr_sync); ++ mutex_init(&wl->event_sync); ++ err = wl_init_scan(wl); ++ if (err) ++ return err; ++ wl_init_conf(wl->conf); ++ wl_init_prof(wl, ndev); ++ wl_link_down(wl); ++ DNGL_FUNC(dhd_cfg80211_init, (wl)); ++ ++ return err; ++} ++ ++static void wl_deinit_priv(struct wl_priv *wl) ++{ ++ DNGL_FUNC(dhd_cfg80211_deinit, (wl)); ++ wl_destroy_event_handler(wl); ++ wl_flush_eq(wl); ++ wl_link_down(wl); ++ del_timer_sync(&wl->scan_timeout); ++ wl_term_iscan(wl); ++ wl_deinit_priv_mem(wl); ++ unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier); ++} ++ ++#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) ++static s32 wl_cfg80211_attach_p2p(void) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ ++ AP6210_DEBUG("Enter \n"); ++ ++ if (wl_cfgp2p_register_ndev(wl) < 0) { ++ AP6210_ERR("%s: P2P attach failed. \n", __func__); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static s32 wl_cfg80211_detach_p2p(void) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ struct wireless_dev *wdev = wl->p2p_wdev; ++ ++ AP6210_DEBUG("Enter \n"); ++ if (!wdev || !wl) { ++ AP6210_ERR("Invalid Ptr\n"); ++ return -EINVAL; ++ } ++ ++ wl_cfgp2p_unregister_ndev(wl); ++ ++ wl->p2p_wdev = NULL; ++ wl->p2p_net = NULL; ++ AP6210_DEBUG("Freeing 0x%08x \n", (unsigned int)wdev); ++ kfree(wdev); ++ ++ return 0; ++} ++#endif /* defined(WLP2P) && defined(WL_ENABLE_P2P_IF) */ ++ ++s32 wl_cfg80211_attach_post(struct net_device *ndev) ++{ ++ struct wl_priv * wl = NULL; ++ s32 err = 0; ++ AP6210_DEBUG("In\n"); ++ if (unlikely(!ndev)) { ++ AP6210_ERR("ndev is invaild\n"); ++ return -ENODEV; ++ } ++ wl = wlcfg_drv_priv; ++ if (unlikely(!wl)) { ++ AP6210_ERR("wl is invaild\n"); ++ return -EINVAL; ++ } ++ if (!wl_get_drv_status(wl, READY, ndev)) { ++ if (wl->wdev && ++ wl_cfgp2p_supported(wl, ndev)) { ++#if !defined(WL_ENABLE_P2P_IF) ++ wl->wdev->wiphy->interface_modes |= ++ (BIT(NL80211_IFTYPE_P2P_CLIENT)| ++ BIT(NL80211_IFTYPE_P2P_GO)); ++#endif ++ if ((err = wl_cfgp2p_init_priv(wl)) != 0) ++ goto fail; ++ ++#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) ++ if (wl->p2p_net) { ++ /* Update MAC addr for p2p0 interface here. */ ++ memcpy(wl->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN); ++ wl->p2p_net->dev_addr[0] |= 0x02; ++ AP6210_ERR("%s: p2p_dev_addr="MACDBG "\n", ++ wl->p2p_net->name, ++ MAC2STRDBG(wl->p2p_net->dev_addr)); ++ } else { ++ AP6210_ERR("p2p_net not yet populated." ++ " Couldn't update the MAC Address for p2p0 \n"); ++ return -ENODEV; ++ } ++#endif /* defined(WLP2P) && (WL_ENABLE_P2P_IF) */ ++ ++ wl->p2p_supported = true; ++ } ++ } ++ wl_set_drv_status(wl, READY, ndev); ++fail: ++ return err; ++} ++ ++s32 wl_cfg80211_attach(struct net_device *ndev, void *data) ++{ ++ struct wireless_dev *wdev; ++ struct wl_priv *wl; ++ s32 err = 0; ++ struct device *dev; ++ ++ AP6210_DEBUG("In\n"); ++ if (!ndev) { ++ AP6210_ERR("ndev is invaild\n"); ++ return -ENODEV; ++ } ++ AP6210_DEBUG("func %p\n", wl_cfg80211_get_parent_dev()); ++ dev = wl_cfg80211_get_parent_dev(); ++ ++ wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); ++ if (unlikely(!wdev)) { ++ AP6210_ERR("Could not allocate wireless device\n"); ++ return -ENOMEM; ++ } ++ err = wl_setup_wiphy(wdev, dev); ++ if (unlikely(err)) { ++ kfree(wdev); ++ return -ENOMEM; ++ } ++ wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS); ++ wl = (struct wl_priv *)wiphy_priv(wdev->wiphy); ++ wl->wdev = wdev; ++ wl->pub = data; ++ INIT_LIST_HEAD(&wl->net_list); ++ ndev->ieee80211_ptr = wdev; ++ SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); ++ wdev->netdev = ndev; ++ wl->state_notifier = wl_notifier_change_state; ++ err = wl_alloc_netinfo(wl, ndev, wdev, WL_MODE_BSS, PM_ENABLE); ++ if (err) { ++ AP6210_ERR("Failed to alloc net_info (%d)\n", err); ++ goto cfg80211_attach_out; ++ } ++ err = wl_init_priv(wl); ++ if (err) { ++ AP6210_ERR("Failed to init iwm_priv (%d)\n", err); ++ goto cfg80211_attach_out; ++ } ++ ++ err = wl_setup_rfkill(wl, TRUE); ++ if (err) { ++ AP6210_ERR("Failed to setup rfkill %d\n", err); ++ goto cfg80211_attach_out; ++ } ++ err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier); ++ if (err) { ++ AP6210_ERR("Failed to register notifierl %d\n", err); ++ goto cfg80211_attach_out; ++ } ++#if defined(COEX_DHCP) ++ if (wl_cfg80211_btcoex_init(wl)) ++ goto cfg80211_attach_out; ++#endif ++#if defined(BSSCACHE) ++ wl_init_bss_cache_ctrl(&g_bss_cache_ctrl); ++#endif ++ ++ wlcfg_drv_priv = wl; ++ ++#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) ++ err = wl_cfg80211_attach_p2p(); ++ if (err) ++ goto cfg80211_attach_out; ++#endif ++ ++ return err; ++ ++cfg80211_attach_out: ++ err = wl_setup_rfkill(wl, FALSE); ++ wl_free_wdev(wl); ++ return err; ++} ++ ++void wl_cfg80211_detach(void *para) ++{ ++ struct wl_priv *wl; ++ ++ (void)para; ++ wl = wlcfg_drv_priv; ++ ++ AP6210_DEBUG("In\n"); ++ ++#if defined(COEX_DHCP) ++ wl_cfg80211_btcoex_deinit(wl); ++#endif ++ ++ wl_setup_rfkill(wl, FALSE); ++ if (wl->p2p_supported) { ++ if (timer_pending(&wl->p2p->listen_timer)) ++ del_timer_sync(&wl->p2p->listen_timer); ++ wl_cfgp2p_deinit_priv(wl); ++ } ++ ++#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) ++ wl_cfg80211_detach_p2p(); ++#endif ++ wl_deinit_priv(wl); ++ wlcfg_drv_priv = NULL; ++ wl_cfg80211_clear_parent_dev(); ++ wl_free_wdev(wl); ++#if defined(RSSIAVG) ++ wl_free_rssi_cache(&g_rssi_cache_ctrl); ++#endif ++#if defined(BSSCACHE) ++ wl_release_bss_cache_ctrl(&g_bss_cache_ctrl); ++#endif ++ /* PLEASE do NOT call any function after wl_free_wdev, the driver's private structure "wl", ++ * which is the private part of wiphy, has been freed in wl_free_wdev !!!!!!!!!!! ++ */ ++} ++ ++static void wl_wakeup_event(struct wl_priv *wl) ++{ ++ if (wl->event_tsk.thr_pid >= 0) { ++ DHD_OS_WAKE_LOCK(wl->pub); ++ up(&wl->event_tsk.sema); ++ } ++} ++ ++static int wl_is_p2p_event(struct wl_event_q *e) ++{ ++ switch (e->etype) { ++ /* We have to seperate out the P2P events received ++ * on primary interface so that it can be send up ++ * via p2p0 interface. ++ */ ++ case WLC_E_P2P_PROBREQ_MSG: ++ case WLC_E_P2P_DISC_LISTEN_COMPLETE: ++ case WLC_E_ACTION_FRAME_RX: ++ case WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE: ++ case WLC_E_ACTION_FRAME_COMPLETE: ++ ++ if (e->emsg.ifidx != 0) { ++ AP6210_DEBUG("P2P Event on Virtual I/F (ifidx:%d) \n", ++ e->emsg.ifidx); ++ /* We are only bothered about the P2P events received ++ * on primary interface. For rest of them return false ++ * so that it is sent over the interface corresponding ++ * to the ifidx. ++ */ ++ return FALSE; ++ } else { ++ AP6210_DEBUG("P2P Event on Primary I/F (ifidx:%d)." ++ " Sent it to p2p0 \n", e->emsg.ifidx); ++ return TRUE; ++ } ++ break; ++ ++ default: ++ AP6210_DEBUG("NON-P2P Event %d on ifidx (ifidx:%d) \n", ++ e->etype, e->emsg.ifidx); ++ return FALSE; ++ } ++} ++ ++static s32 wl_event_handler(void *data) ++{ ++ struct net_device *netdev; ++ struct wl_priv *wl = NULL; ++ struct wl_event_q *e; ++ tsk_ctl_t *tsk = (tsk_ctl_t *)data; ++ ++ wl = (struct wl_priv *)tsk->parent; ++#ifndef USE_KTHREAD_API ++ DAEMONIZE("dhd_cfg80211_event"); ++ complete(&tsk->completed); ++#else ++ AP6210_ERR("tsk Enter, tsk = 0x%08x\n", (unsigned int)tsk); ++#endif ++ ++ while (down_interruptible (&tsk->sema) == 0) { ++ SMP_RD_BARRIER_DEPENDS(); ++ if (tsk->terminated) ++ break; ++ while ((e = wl_deq_event(wl))) { ++ AP6210_DEBUG("event type (%d), if idx: %d\n", e->etype, e->emsg.ifidx); ++ /* All P2P device address related events comes on primary interface since ++ * there is no corresponding bsscfg for P2P interface. Map it to p2p0 ++ * interface. ++ */ ++ if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_net)) { ++ netdev = wl->p2p_net; ++ } else { ++ netdev = dhd_idx2net((struct dhd_pub *)(wl->pub), e->emsg.ifidx); ++ } ++ if (!netdev) ++ netdev = wl_to_prmry_ndev(wl); ++ if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) { ++ wl->evt_handler[e->etype] (wl, netdev, &e->emsg, e->edata); ++ } else { ++ AP6210_DEBUG("Unknown Event (%d): ignoring\n", e->etype); ++ } ++ wl_put_event(e); ++ } ++ DHD_OS_WAKE_UNLOCK(wl->pub); ++ } ++ AP6210_ERR("%s was terminated\n", __func__); ++ complete_and_exit(&tsk->completed, 0); ++ return 0; ++} ++ ++void ++wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data) ++{ ++ u32 event_type = ntoh32(e->event_type); ++ struct wl_priv *wl = wlcfg_drv_priv; ++ ++#if (WL_DBG_LEVEL > 0) ++ s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ? ++ wl_dbg_estr[event_type] : (s8 *) "Unknown"; ++ AP6210_DEBUG("event_type (%d):" "WLC_E_" "%s\n", event_type, estr); ++#endif /* (WL_DBG_LEVEL > 0) */ ++ ++ if (event_type == WLC_E_PFN_NET_FOUND) { ++ AP6210_DEBUG(" PNOEVENT: PNO_NET_FOUND\n"); ++ } ++ else if (event_type == WLC_E_PFN_NET_LOST) { ++ AP6210_DEBUG(" PNOEVENT: PNO_NET_LOST\n"); ++ } ++ ++ if (likely(!wl_enq_event(wl, ndev, event_type, e, data))) ++ wl_wakeup_event(wl); ++} ++ ++static void wl_init_eq(struct wl_priv *wl) ++{ ++ wl_init_eq_lock(wl); ++ INIT_LIST_HEAD(&wl->eq_list); ++} ++ ++static void wl_flush_eq(struct wl_priv *wl) ++{ ++ struct wl_event_q *e; ++ unsigned long flags; ++ ++ flags = wl_lock_eq(wl); ++ while (!list_empty(&wl->eq_list)) { ++ e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list); ++ list_del(&e->eq_list); ++ kfree(e); ++ } ++ wl_unlock_eq(wl, flags); ++} ++ ++/* ++* retrieve first queued event from head ++*/ ++ ++static struct wl_event_q *wl_deq_event(struct wl_priv *wl) ++{ ++ struct wl_event_q *e = NULL; ++ unsigned long flags; ++ ++ flags = wl_lock_eq(wl); ++ if (likely(!list_empty(&wl->eq_list))) { ++ e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list); ++ list_del(&e->eq_list); ++ } ++ wl_unlock_eq(wl, flags); ++ ++ return e; ++} ++ ++/* ++ * push event to tail of the queue ++ */ ++ ++static s32 ++wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 event, const wl_event_msg_t *msg, ++ void *data) ++{ ++ struct wl_event_q *e; ++ s32 err = 0; ++ uint32 evtq_size; ++ uint32 data_len; ++ unsigned long flags; ++ gfp_t aflags; ++ ++ data_len = 0; ++ if (data) ++ data_len = ntoh32(msg->datalen); ++ evtq_size = sizeof(struct wl_event_q) + data_len; ++ aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; ++ e = kzalloc(evtq_size, aflags); ++ if (unlikely(!e)) { ++ AP6210_ERR("event alloc failed\n"); ++ return -ENOMEM; ++ } ++ e->etype = event; ++ memcpy(&e->emsg, msg, sizeof(wl_event_msg_t)); ++ if (data) ++ memcpy(e->edata, data, data_len); ++ flags = wl_lock_eq(wl); ++ list_add_tail(&e->eq_list, &wl->eq_list); ++ wl_unlock_eq(wl, flags); ++ ++ return err; ++} ++ ++static void wl_put_event(struct wl_event_q *e) ++{ ++ kfree(e); ++} ++ ++static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype) ++{ ++ s32 infra = 0; ++ s32 err = 0; ++ s32 mode = 0; ++ switch (iftype) { ++ case NL80211_IFTYPE_MONITOR: ++ case NL80211_IFTYPE_WDS: ++ AP6210_ERR("type (%d) : currently we do not support this mode\n", ++ iftype); ++ err = -EINVAL; ++ return err; ++ case NL80211_IFTYPE_ADHOC: ++ mode = WL_MODE_IBSS; ++ break; ++ case NL80211_IFTYPE_STATION: ++ case NL80211_IFTYPE_P2P_CLIENT: ++ mode = WL_MODE_BSS; ++ infra = 1; ++ break; ++ case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_P2P_GO: ++ mode = WL_MODE_AP; ++ infra = 1; ++ break; ++ default: ++ err = -EINVAL; ++ AP6210_ERR("invalid type (%d)\n", iftype); ++ return err; ++ } ++ infra = htod32(infra); ++ err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true); ++ if (unlikely(err)) { ++ AP6210_ERR("WLC_SET_INFRA error (%d)\n", err); ++ return err; ++ } ++ ++ wl_set_mode_by_netdev(wl, ndev, mode); ++ ++ return 0; ++} ++ ++void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set) ++{ ++ if (!ev || (event > WLC_E_LAST)) ++ return; ++ ++ if (ev->num < MAX_EVENT_BUF_NUM) { ++ ev->event[ev->num].type = event; ++ ev->event[ev->num].set = set; ++ ev->num++; ++ } else { ++ AP6210_ERR("evenbuffer doesn't support > %u events. Update" ++ " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM); ++ ASSERT(0); ++ } ++} ++ ++s32 wl_cfg80211_apply_eventbuffer( ++ struct net_device *ndev, ++ struct wl_priv *wl, ++ wl_eventmsg_buf_t *ev) ++{ ++ char eventmask[WL_EVENTING_MASK_LEN]; ++ int i, ret = 0; ++ s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; ++ ++ if (!ev || (!ev->num)) ++ return -EINVAL; ++ ++ mutex_lock(&wl->event_sync); ++ ++ /* Read event_msgs mask */ ++ bcm_mkiovar("event_msgs", NULL, 0, iovbuf, ++ sizeof(iovbuf)); ++ ret = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false); ++ if (unlikely(ret)) { ++ AP6210_ERR("Get event_msgs error (%d)\n", ret); ++ goto exit; ++ } ++ memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN); ++ ++ /* apply the set bits */ ++ for (i = 0; i < ev->num; i++) { ++ if (ev->event[i].set) ++ setbit(eventmask, ev->event[i].type); ++ else ++ clrbit(eventmask, ev->event[i].type); ++ } ++ ++ /* Write updated Event mask */ ++ bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, ++ sizeof(iovbuf)); ++ ret = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); ++ if (unlikely(ret)) { ++ AP6210_ERR("Set event_msgs error (%d)\n", ret); ++ } ++ ++exit: ++ mutex_unlock(&wl->event_sync); ++ return ret; ++} ++ ++s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add) ++{ ++ s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; ++ s8 eventmask[WL_EVENTING_MASK_LEN]; ++ s32 err = 0; ++ struct wl_priv *wl = wlcfg_drv_priv; ++ ++ if (!ndev || !wl) ++ return -ENODEV; ++ ++ mutex_lock(&wl->event_sync); ++ ++ /* Setup event_msgs */ ++ bcm_mkiovar("event_msgs", NULL, 0, iovbuf, ++ sizeof(iovbuf)); ++ err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false); ++ if (unlikely(err)) { ++ AP6210_ERR("Get event_msgs error (%d)\n", err); ++ goto eventmsg_out; ++ } ++ memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN); ++ if (add) { ++ setbit(eventmask, event); ++ } else { ++ clrbit(eventmask, event); ++ } ++ bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, ++ sizeof(iovbuf)); ++ err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); ++ if (unlikely(err)) { ++ AP6210_ERR("Set event_msgs error (%d)\n", err); ++ goto eventmsg_out; ++ } ++ ++eventmsg_out: ++ mutex_unlock(&wl->event_sync); ++ return err; ++} ++ ++static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap) ++{ ++ struct net_device *dev = wl_to_prmry_ndev(wl); ++ struct ieee80211_channel *band_chan_arr = NULL; ++ wl_uint32_list_t *list; ++ u32 i, j, index, n_2g, n_5g, band, channel, array_size; ++ u32 *n_cnt = NULL; ++ chanspec_t c = 0; ++ s32 err = BCME_OK; ++ bool update; ++ bool ht40_allowed; ++ u8 *pbuf = NULL; ++ ++#define LOCAL_BUF_LEN 1024 ++ pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL); ++ ++ if (pbuf == NULL) { ++ AP6210_ERR("failed to allocate local buf\n"); ++ return -ENOMEM; ++ } ++ list = (wl_uint32_list_t *)(void *) pbuf; ++ list->count = htod32(WL_NUMCHANSPECS); ++ ++ ++ err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL, ++ 0, pbuf, LOCAL_BUF_LEN, 0, &wl->ioctl_buf_sync); ++ if (err != 0) { ++ AP6210_ERR("get chanspecs failed with %d\n", err); ++ kfree(pbuf); ++ return err; ++ } ++#undef LOCAL_BUF_LEN ++ ++ list = (wl_uint32_list_t *)(void *)pbuf; ++ band = array_size = n_2g = n_5g = 0; ++ for (i = 0; i < dtoh32(list->count); i++) { ++ index = 0; ++ update = false; ++ ht40_allowed = false; ++ c = (chanspec_t)dtoh32(list->element[i]); ++ c = wl_chspec_driver_to_host(c); ++ channel = CHSPEC_CHANNEL(c); ++ if (CHSPEC_IS40(c)) { ++ if (CHSPEC_SB_UPPER(c)) ++ channel += CH_10MHZ_APART; ++ else ++ channel -= CH_10MHZ_APART; ++ } else if (CHSPEC_IS80(c)) { ++ AP6210_DEBUG("HT80 center channel : %d\n", channel); ++ continue; ++ } ++ if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) && ++ (channel <= CH_MAX_2G_CHANNEL)) { ++ band_chan_arr = __wl_2ghz_channels; ++ array_size = ARRAYSIZE(__wl_2ghz_channels); ++ n_cnt = &n_2g; ++ band = IEEE80211_BAND_2GHZ; ++ ht40_allowed = (bw_cap == WLC_N_BW_40ALL)? true : false; ++ } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) { ++ band_chan_arr = __wl_5ghz_a_channels; ++ array_size = ARRAYSIZE(__wl_5ghz_a_channels); ++ n_cnt = &n_5g; ++ band = IEEE80211_BAND_5GHZ; ++ ht40_allowed = (bw_cap == WLC_N_BW_20ALL)? false : true; ++ } else { ++ AP6210_ERR("Invalid channel Sepc. 0x%x.\n", c); ++ continue; ++ } ++ if (!ht40_allowed && CHSPEC_IS40(c)) ++ continue; ++ for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) { ++ if (band_chan_arr[j].hw_value == channel) { ++ update = true; ++ break; ++ } ++ } ++ if (update) ++ index = j; ++ else ++ index = *n_cnt; ++ if (index < array_size) { ++#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) ++ band_chan_arr[index].center_freq = ++ ieee80211_channel_to_frequency(channel); ++#else ++ band_chan_arr[index].center_freq = ++ ieee80211_channel_to_frequency(channel, band); ++#endif ++ band_chan_arr[index].hw_value = channel; ++ ++ if (CHSPEC_IS40(c) && ht40_allowed) { ++ /* assuming the order is HT20, HT40 Upper, ++ HT40 lower from chanspecs ++ */ ++ u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40; ++ if (CHSPEC_SB_UPPER(c)) { ++ if (ht40_flag == IEEE80211_CHAN_NO_HT40) ++ band_chan_arr[index].flags &= ++ ~IEEE80211_CHAN_NO_HT40; ++ band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS; ++ } else { ++ /* It should be one of ++ IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS ++ */ ++ band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40; ++ if (ht40_flag == IEEE80211_CHAN_NO_HT40) ++ band_chan_arr[index].flags |= ++ IEEE80211_CHAN_NO_HT40MINUS; ++ } ++ } else { ++ band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40; ++ if (band == IEEE80211_BAND_2GHZ) ++ channel |= WL_CHANSPEC_BAND_2G; ++ else ++ channel |= WL_CHANSPEC_BAND_5G; ++ channel |= WL_CHANSPEC_BW_20; ++ channel = wl_chspec_host_to_driver(channel); ++ err = wldev_iovar_getint(dev, "per_chan_info", &channel); ++ if (!err) { ++ if (channel & WL_CHAN_RADAR) ++ band_chan_arr[index].flags |= ++ (IEEE80211_CHAN_RADAR | ++ IEEE80211_CHAN_NO_IBSS); ++ if (channel & WL_CHAN_PASSIVE) ++ band_chan_arr[index].flags |= ++ IEEE80211_CHAN_PASSIVE_SCAN; ++ } ++ } ++ if (!update) ++ (*n_cnt)++; ++ } ++ ++ } ++ __wl_band_2ghz.n_channels = n_2g; ++ __wl_band_5ghz_a.n_channels = n_5g; ++ kfree(pbuf); ++ return err; ++} ++ ++s32 wl_update_wiphybands(struct wl_priv *wl, bool notify) ++{ ++ struct wiphy *wiphy; ++ struct net_device *dev; ++ u32 bandlist[3]; ++ u32 nband = 0; ++ u32 i = 0; ++ s32 err = 0; ++ s32 index = 0; ++ s32 nmode = 0; ++ bool rollback_lock = false; ++ s32 bw_cap = 0; ++ s32 cur_band = -1; ++ struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, }; ++ ++ if (wl == NULL) { ++ wl = wlcfg_drv_priv; ++ mutex_lock(&wl->usr_sync); ++ rollback_lock = true; ++ } ++ dev = wl_to_prmry_ndev(wl); ++ ++ memset(bandlist, 0, sizeof(bandlist)); ++ err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist, ++ sizeof(bandlist), false); ++ if (unlikely(err)) { ++ AP6210_ERR("error read bandlist (%d)\n", err); ++ goto end_bands; ++ } ++ ++ wiphy = wl_to_wiphy(wl); ++ ++ err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band, ++ sizeof(s32), false); ++ if (unlikely(err)) { ++ AP6210_ERR("error (%d)\n", err); ++ goto end_bands; ++ } ++ ++ err = wldev_iovar_getint(dev, "nmode", &nmode); ++ if (unlikely(err)) { ++ AP6210_ERR("error reading nmode (%d)\n", err); ++ } else { ++ /* For nmodeonly check bw cap */ ++ err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap); ++ if (unlikely(err)) { ++ AP6210_ERR("error get mimo_bw_cap (%d)\n", err); ++ } ++ } ++ ++ err = wl_construct_reginfo(wl, bw_cap); ++ if (err) { ++ AP6210_ERR("wl_construct_reginfo() fails err=%d\n", err); ++ if (err != BCME_UNSUPPORTED) ++ goto end_bands; ++ err = 0; ++ } ++ ++ nband = bandlist[0]; ++ ++ for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) { ++ index = -1; ++ if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) { ++ bands[IEEE80211_BAND_5GHZ] = ++ &__wl_band_5ghz_a; ++ index = IEEE80211_BAND_5GHZ; ++ if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G) ++ bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; ++ } ++ else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) { ++ bands[IEEE80211_BAND_2GHZ] = ++ &__wl_band_2ghz; ++ index = IEEE80211_BAND_2GHZ; ++ if (bw_cap == WLC_N_BW_40ALL) ++ bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; ++ } ++ ++ if ((index >= 0) && nmode) { ++ bands[index]->ht_cap.cap |= ++ (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40); ++ bands[index]->ht_cap.ht_supported = TRUE; ++ bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; ++ bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; ++ /* An HT shall support all EQM rates for one spatial stream */ ++ bands[index]->ht_cap.mcs.rx_mask[0] = 0xff; ++ } ++ ++ } ++ ++ wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ]; ++ wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ]; ++ ++ if (notify) ++ wiphy_apply_custom_regulatory(wiphy, &brcm_regdom); ++ ++end_bands: ++ if (rollback_lock) ++ mutex_unlock(&wl->usr_sync); ++ return err; ++} ++ ++static s32 __wl_cfg80211_up(struct wl_priv *wl) ++{ ++ s32 err = 0; ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++ struct wireless_dev *wdev = ndev->ieee80211_ptr; ++ ++ AP6210_DEBUG("In\n"); ++ ++ err = dhd_config_dongle(wl, false); ++ if (unlikely(err)) ++ return err; ++ ++ err = wl_config_ifmode(wl, ndev, wdev->iftype); ++ if (unlikely(err && err != -EINPROGRESS)) { ++ AP6210_ERR("wl_config_ifmode failed\n"); ++ } ++ err = wl_update_wiphybands(wl, true); ++ if (unlikely(err)) { ++ AP6210_ERR("wl_update_wiphybands failed\n"); ++ } ++ ++ err = dhd_monitor_init(wl->pub); ++ err = wl_invoke_iscan(wl); ++ ++#ifdef WL_HOST_BAND_MGMT ++ /* By default the curr_band is initialized to BAND_AUTO */ ++ if (wl_cfg80211_set_band(ndev, WLC_BAND_AUTO) < 0) { ++ AP6210_ERR("roam_band set failed\n"); ++ err = -1; ++ } ++#endif /* WL_HOST_BAND_MGMT */ ++ ++#if defined(DHCP_SCAN_SUPPRESS) ++ /* wlan scan_supp timer and work thread info */ ++ init_timer(&wl->scan_supp_timer); ++ wl->scan_supp_timer.data = (ulong)wl; ++ wl->scan_supp_timer.function = wl_cfg80211_scan_supp_timerfunc; ++ INIT_WORK(&wl->wlan_work, wl_cfg80211_work_handler); ++#endif /* DHCP_SCAN_SUPPRESS */ ++ ++ wl_set_drv_status(wl, READY, ndev); ++ return err; ++} ++ ++static s32 __wl_cfg80211_down(struct wl_priv *wl) ++{ ++ s32 err = 0; ++ unsigned long flags; ++ struct net_info *iter, *next; ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++ struct net_device *p2p_net = wl->p2p_net; ++ u32 bssidx = wl_cfgp2p_find_idx(wl, ndev); ++ AP6210_DEBUG("In\n"); ++ ++#if defined(DHCP_SCAN_SUPPRESS) ++ /* Force clear of scan_suppress */ ++ if (wl->scan_suppressed) ++ wl_cfg80211_scan_suppress(ndev, 0); ++ if (timer_pending(&wl->scan_supp_timer)) ++ del_timer_sync(&wl->scan_supp_timer); ++ cancel_work_sync(&wl->wlan_work); ++#endif /* DHCP_SCAN_SUPPRESS */ ++ ++ /* If BSS is operational (e.g SoftAp), bring it down */ ++ if (wl_cfgp2p_bss_isup(ndev, bssidx)) { ++ if (wl_cfgp2p_bss(wl, ndev, bssidx, 0) < 0) ++ AP6210_ERR("BSS down failed \n"); ++ } ++ ++ /* Check if cfg80211 interface is already down */ ++ if (!wl_get_drv_status(wl, READY, ndev)) ++ return err; /* it is even not ready */ ++ ++ for_each_ndev(wl, iter, next) ++ wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev); ++ ++ wl_term_iscan(wl); ++ spin_lock_irqsave(&wl->cfgdrv_lock, flags); ++ if (wl->scan_request) { ++ cfg80211_scan_done(wl->scan_request, true); ++ wl->scan_request = NULL; ++ } ++ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); ++ ++ for_each_ndev(wl, iter, next) { ++ wl_clr_drv_status(wl, READY, iter->ndev); ++ wl_clr_drv_status(wl, SCANNING, iter->ndev); ++ wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev); ++ wl_clr_drv_status(wl, CONNECTING, iter->ndev); ++ wl_clr_drv_status(wl, CONNECTED, iter->ndev); ++ wl_clr_drv_status(wl, DISCONNECTING, iter->ndev); ++ wl_clr_drv_status(wl, AP_CREATED, iter->ndev); ++ wl_clr_drv_status(wl, AP_CREATING, iter->ndev); ++ } ++ wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype = ++ NL80211_IFTYPE_STATION; ++ if (p2p_net) ++ dev_close(p2p_net); ++ DNGL_FUNC(dhd_cfg80211_down, (wl)); ++ wl_flush_eq(wl); ++ wl_link_down(wl); ++ if (wl->p2p_supported) ++ wl_cfgp2p_down(wl); ++ dhd_monitor_uninit(); ++ ++ return err; ++} ++ ++s32 wl_cfg80211_up(void *para) ++{ ++ struct wl_priv *wl; ++ s32 err = 0; ++ int val = 1; ++ dhd_pub_t *dhd; ++ ++ (void)para; ++ AP6210_DEBUG("In\n"); ++ wl = wlcfg_drv_priv; ++ ++ if ((err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_VERSION, &val, ++ sizeof(int), false) < 0)) { ++ AP6210_ERR("WLC_GET_VERSION failed, err=%d\n", err); ++ return err; ++ } ++ val = dtoh32(val); ++ if (val != WLC_IOCTL_VERSION && val != 1) { ++ AP6210_ERR("Version mismatch, please upgrade. Got %d, expected %d or 1\n", ++ val, WLC_IOCTL_VERSION); ++ return BCME_VERSION; ++ } ++ ioctl_version = val; ++ AP6210_DEBUG("WLC_GET_VERSION=%d\n", ioctl_version); ++ ++ mutex_lock(&wl->usr_sync); ++ dhd = (dhd_pub_t *)(wl->pub); ++ if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) { ++ err = wl_cfg80211_attach_post(wl_to_prmry_ndev(wl)); ++ if (unlikely(err)) ++ return err; ++ } ++ err = __wl_cfg80211_up(wl); ++ if (unlikely(err)) ++ AP6210_ERR("__wl_cfg80211_up failed\n"); ++ mutex_unlock(&wl->usr_sync); ++ return err; ++} ++ ++/* Private Event to Supplicant with indication that chip hangs */ ++int wl_cfg80211_hang(struct net_device *dev, u16 reason) ++{ ++ struct wl_priv *wl; ++ wl = wlcfg_drv_priv; ++ ++ AP6210_ERR("In : chip crash eventing\n"); ++ cfg80211_disconnected(dev, reason, NULL, 0, GFP_KERNEL); ++#if defined(RSSIAVG) ++ wl_free_rssi_cache(&g_rssi_cache_ctrl); ++#endif ++#if defined(BSSCACHE) ++ wl_free_bss_cache(&g_bss_cache_ctrl); ++ wl_run_bss_cache_timer(&g_bss_cache_ctrl, 0); ++#endif ++ if (wl != NULL) { ++ wl_link_down(wl); ++ } ++ return 0; ++} ++ ++s32 wl_cfg80211_down(void *para) ++{ ++ struct wl_priv *wl; ++ s32 err = 0; ++ ++ (void)para; ++ AP6210_DEBUG("In\n"); ++ wl = wlcfg_drv_priv; ++ mutex_lock(&wl->usr_sync); ++#if defined(RSSIAVG) ++ wl_free_rssi_cache(&g_rssi_cache_ctrl); ++#endif ++#if defined(BSSCACHE) ++ wl_free_bss_cache(&g_bss_cache_ctrl); ++ wl_run_bss_cache_timer(&g_bss_cache_ctrl, 0); ++#endif ++ err = __wl_cfg80211_down(wl); ++ mutex_unlock(&wl->usr_sync); ++ ++ return err; ++} ++ ++static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item) ++{ ++ unsigned long flags; ++ void *rptr = NULL; ++ struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev); ++ ++ if (!profile) ++ return NULL; ++ spin_lock_irqsave(&wl->cfgdrv_lock, flags); ++ switch (item) { ++ case WL_PROF_SEC: ++ rptr = &profile->sec; ++ break; ++ case WL_PROF_ACT: ++ rptr = &profile->active; ++ break; ++ case WL_PROF_BSSID: ++ rptr = profile->bssid; ++ break; ++ case WL_PROF_SSID: ++ rptr = &profile->ssid; ++ break; ++ case WL_PROF_CHAN: ++ rptr = &profile->channel; ++ break; ++ } ++ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); ++ if (!rptr) ++ AP6210_ERR("invalid item (%d)\n", item); ++ return rptr; ++} ++ ++static s32 ++wl_update_prof(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data, s32 item) ++{ ++ s32 err = 0; ++ struct wlc_ssid *ssid; ++ unsigned long flags; ++ struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev); ++ ++ if (!profile) ++ return WL_INVALID; ++ spin_lock_irqsave(&wl->cfgdrv_lock, flags); ++ switch (item) { ++ case WL_PROF_SSID: ++ ssid = (wlc_ssid_t *) data; ++ memset(profile->ssid.SSID, 0, ++ sizeof(profile->ssid.SSID)); ++ memcpy(profile->ssid.SSID, ssid->SSID, ssid->SSID_len); ++ profile->ssid.SSID_len = ssid->SSID_len; ++ break; ++ case WL_PROF_BSSID: ++ if (data) ++ memcpy(profile->bssid, data, ETHER_ADDR_LEN); ++ else ++ memset(profile->bssid, 0, ETHER_ADDR_LEN); ++ break; ++ case WL_PROF_SEC: ++ memcpy(&profile->sec, data, sizeof(profile->sec)); ++ break; ++ case WL_PROF_ACT: ++ profile->active = *(bool *)data; ++ break; ++ case WL_PROF_BEACONINT: ++ profile->beacon_interval = *(u16 *)data; ++ break; ++ case WL_PROF_DTIMPERIOD: ++ profile->dtim_period = *(u8 *)data; ++ break; ++ case WL_PROF_CHAN: ++ profile->channel = *(u32*)data; ++ default: ++ err = -EOPNOTSUPP; ++ break; ++ } ++ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); ++ ++ if (err == EOPNOTSUPP) ++ AP6210_ERR("unsupported item (%d)\n", item); ++ ++ return err; ++} ++ ++void wl_cfg80211_dbg_level(u32 level) ++{ ++ /* ++ * prohibit to change debug level ++ * by insmod parameter. ++ * eventually debug level will be configured ++ * in compile time by using CONFIG_XXX ++ */ ++ /* wl_dbg_level = level; */ ++} ++ ++static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev) ++{ ++ return wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS; ++} ++ ++static __used bool wl_is_ibssstarter(struct wl_priv *wl) ++{ ++ return wl->ibss_starter; ++} ++ ++static void wl_rst_ie(struct wl_priv *wl) ++{ ++ struct wl_ie *ie = wl_to_ie(wl); ++ ++ ie->offset = 0; ++} ++ ++static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v) ++{ ++ struct wl_ie *ie = wl_to_ie(wl); ++ s32 err = 0; ++ ++ if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) { ++ AP6210_ERR("ei crosses buffer boundary\n"); ++ return -ENOSPC; ++ } ++ ie->buf[ie->offset] = t; ++ ie->buf[ie->offset + 1] = l; ++ memcpy(&ie->buf[ie->offset + 2], v, l); ++ ie->offset += l + 2; ++ ++ return err; ++} ++ ++static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size) ++{ ++ struct wl_ie *ie = wl_to_ie(wl); ++ s32 err = 0; ++ ++ if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) { ++ AP6210_ERR("ei_stream crosses buffer boundary\n"); ++ return -ENOSPC; ++ } ++ memcpy(&ie->buf[ie->offset], ie_stream, ie_size); ++ ie->offset += ie_size; ++ ++ return err; ++} ++ ++static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size) ++{ ++ struct wl_ie *ie = wl_to_ie(wl); ++ s32 err = 0; ++ ++ if (unlikely(ie->offset > dst_size)) { ++ AP6210_ERR("dst_size is not enough\n"); ++ return -ENOSPC; ++ } ++ memcpy(dst, &ie->buf[0], ie->offset); ++ ++ return err; ++} ++ ++static u32 wl_get_ielen(struct wl_priv *wl) ++{ ++ struct wl_ie *ie = wl_to_ie(wl); ++ ++ return ie->offset; ++} ++ ++static void wl_link_up(struct wl_priv *wl) ++{ ++ wl->link_up = true; ++} ++ ++static void wl_link_down(struct wl_priv *wl) ++{ ++ struct wl_connect_info *conn_info = wl_to_conn(wl); ++ ++ AP6210_DEBUG("In\n"); ++ wl->link_up = false; ++ conn_info->req_ie_len = 0; ++ conn_info->resp_ie_len = 0; ++} ++ ++static unsigned long wl_lock_eq(struct wl_priv *wl) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&wl->eq_lock, flags); ++ return flags; ++} ++ ++static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags) ++{ ++ spin_unlock_irqrestore(&wl->eq_lock, flags); ++} ++ ++static void wl_init_eq_lock(struct wl_priv *wl) ++{ ++ spin_lock_init(&wl->eq_lock); ++} ++ ++static void wl_delay(u32 ms) ++{ ++ if (in_atomic() || (ms < jiffies_to_msecs(1))) { ++ mdelay(ms); ++ } else { ++ msleep(ms); ++ } ++} ++ ++s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ struct ether_addr p2pif_addr; ++ struct ether_addr primary_mac; ++ if (!wl->p2p) ++ return -1; ++ if (!p2p_is_on(wl)) { ++ get_primary_mac(wl, &primary_mac); ++ wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr); ++ } else { ++ memcpy(p2pdev_addr->octet, ++ wl->p2p->dev_addr.octet, ETHER_ADDR_LEN); ++ } ++ ++ ++ return 0; ++} ++s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len) ++{ ++ struct wl_priv *wl; ++ ++ wl = wlcfg_drv_priv; ++ ++ return wl_cfgp2p_set_p2p_noa(wl, net, buf, len); ++} ++ ++s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len) ++{ ++ struct wl_priv *wl; ++ wl = wlcfg_drv_priv; ++ ++ return wl_cfgp2p_get_p2p_noa(wl, net, buf, len); ++} ++ ++s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len) ++{ ++ struct wl_priv *wl; ++ wl = wlcfg_drv_priv; ++ ++ return wl_cfgp2p_set_p2p_ps(wl, net, buf, len); ++} ++ ++s32 wl_cfg80211_channel_to_freq(u32 channel) ++{ ++ int freq = 0; ++ ++#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) ++ freq = ieee80211_channel_to_frequency(channel); ++#else ++ { ++ u16 band = 0; ++ if (channel <= CH_MAX_2G_CHANNEL) ++ band = IEEE80211_BAND_2GHZ; ++ else ++ band = IEEE80211_BAND_5GHZ; ++ freq = ieee80211_channel_to_frequency(channel, band); ++ } ++#endif ++ return freq; ++} ++ ++s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len, ++ enum wl_management_type type) ++{ ++ struct wl_priv *wl; ++ struct net_device *ndev = NULL; ++ struct ether_addr primary_mac; ++ s32 ret = 0; ++ s32 bssidx = 0; ++ s32 pktflag = 0; ++ wl = wlcfg_drv_priv; ++ ++ if (wl_get_drv_status(wl, AP_CREATING, net) || ++ wl_get_drv_status(wl, AP_CREATED, net)) { ++ ndev = net; ++ bssidx = 0; ++ } else if (wl->p2p) { ++ if (net == wl->p2p_net) { ++ net = wl_to_prmry_ndev(wl); ++ } ++ if (!wl->p2p->on) { ++ get_primary_mac(wl, &primary_mac); ++ wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, ++ &wl->p2p->int_addr); ++ /* In case of p2p_listen command, supplicant send remain_on_channel ++ * without turning on P2P ++ */ ++ ++ p2p_on(wl) = true; ++ ret = wl_cfgp2p_enable_discovery(wl, net, NULL, 0); ++ ++ if (unlikely(ret)) { ++ goto exit; ++ } ++ } ++ if (net != wl_to_prmry_ndev(wl)) { ++ if (wl_get_mode_by_netdev(wl, net) == WL_MODE_AP) { ++ ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); ++ bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION); ++ } ++ } else { ++ ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY); ++ bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); ++ } ++ } ++ if (ndev != NULL) { ++ switch (type) { ++ case WL_BEACON: ++ pktflag = VNDR_IE_BEACON_FLAG; ++ break; ++ case WL_PROBE_RESP: ++ pktflag = VNDR_IE_PRBRSP_FLAG; ++ break; ++ case WL_ASSOC_RESP: ++ pktflag = VNDR_IE_ASSOCRSP_FLAG; ++ break; ++ } ++ if (pktflag) ++ ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len); ++ } ++exit: ++ return ret; ++} ++ ++static const struct rfkill_ops wl_rfkill_ops = { ++ .set_block = wl_rfkill_set ++}; ++ ++static int wl_rfkill_set(void *data, bool blocked) ++{ ++ struct wl_priv *wl = (struct wl_priv *)data; ++ ++ AP6210_DEBUG("Enter \n"); ++ AP6210_DEBUG("RF %s\n", blocked ? "blocked" : "unblocked"); ++ ++ if (!wl) ++ return -EINVAL; ++ ++ wl->rf_blocked = blocked; ++ ++ return 0; ++} ++ ++static int wl_setup_rfkill(struct wl_priv *wl, bool setup) ++{ ++ s32 err = 0; ++ ++ AP6210_DEBUG("Enter \n"); ++ if (!wl) ++ return -EINVAL; ++ if (setup) { ++ wl->rfkill = rfkill_alloc("brcmfmac-wifi", ++ wl_cfg80211_get_parent_dev(), ++ RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)wl); ++ ++ if (!wl->rfkill) { ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++ err = rfkill_register(wl->rfkill); ++ ++ if (err) ++ rfkill_destroy(wl->rfkill); ++ } else { ++ if (!wl->rfkill) { ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++ rfkill_unregister(wl->rfkill); ++ rfkill_destroy(wl->rfkill); ++ } ++ ++err_out: ++ return err; ++} ++ ++struct device *wl_cfg80211_get_parent_dev(void) ++{ ++ return cfg80211_parent_dev; ++} ++ ++void wl_cfg80211_set_parent_dev(void *dev) ++{ ++ cfg80211_parent_dev = dev; ++} ++ ++static void wl_cfg80211_clear_parent_dev(void) ++{ ++ cfg80211_parent_dev = NULL; ++} ++ ++static void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac) ++{ ++ wldev_iovar_getbuf_bsscfg(wl_to_prmry_ndev(wl), "cur_etheraddr", NULL, ++ 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, 0, &wl->ioctl_buf_sync); ++ memcpy(mac->octet, wl->ioctl_buf, ETHER_ADDR_LEN); ++} ++ ++int wl_cfg80211_do_driver_init(struct net_device *net) ++{ ++ struct wl_priv *wl = *(struct wl_priv **)netdev_priv(net); ++ ++ if (!wl || !wl->wdev) ++ return -EINVAL; ++ ++ if (dhd_do_driver_init(wl->wdev->netdev) < 0) ++ return -1; ++ ++ return 0; ++} ++ ++void wl_cfg80211_enable_trace(u32 level) ++{ ++ wl_dbg_level = level; ++ AP6210_DEBUG("%s: wl_dbg_level = 0x%x\n", __FUNCTION__, wl_dbg_level); ++} ++ ++#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ ++ 2, 0)) ++static s32 ++wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, ++ struct net_device *dev, u64 cookie) ++{ ++ /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION ++ * is passed with CMD_FRAME. This callback is supposed to cancel ++ * the OFFCHANNEL Wait. Since we are already taking care of that ++ * with the tx_mgmt logic, do nothing here. ++ */ ++ ++ return 0; ++} ++#endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL >= 3.2.0 */ ++ ++#ifdef WL11U ++bcm_tlv_t * ++wl_cfg80211_find_interworking_ie(u8 *parse, u32 len) ++{ ++ bcm_tlv_t *ie; ++ ++ while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_INTERWORKING_ID))) { ++ return (bcm_tlv_t *)ie; ++ } ++ return NULL; ++} ++ ++static s32 ++wl_cfg80211_add_iw_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag, ++ uint8 ie_id, uint8 *data, uint8 data_len) ++{ ++ s32 err = BCME_OK; ++ s32 buf_len; ++ s32 iecount; ++ ie_setbuf_t *ie_setbuf; ++ ++ if (ie_id != DOT11_MNG_INTERWORKING_ID) ++ return BCME_UNSUPPORTED; ++ ++ /* Validate the pktflag parameter */ ++ if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG | ++ VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG | ++ VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG| ++ VNDR_IE_CUSTOM_FLAG))) { ++ AP6210_ERR("cfg80211 Add IE: Invalid packet flag 0x%x\n", pktflag); ++ return -1; ++ } ++ ++ /* use VNDR_IE_CUSTOM_FLAG flags for none vendor IE . currently fixed value */ ++ pktflag = htod32(pktflag); ++ ++ buf_len = sizeof(ie_setbuf_t) + data_len - 1; ++ ie_setbuf = (ie_setbuf_t *) kzalloc(buf_len, GFP_KERNEL); ++ ++ if (!ie_setbuf) { ++ AP6210_ERR("Error allocating buffer for IE\n"); ++ return -ENOMEM; ++ } ++ ++ if (wl->iw_ie_len == data_len && !memcmp(wl->iw_ie, data, data_len)) { ++ AP6210_ERR("Previous IW IE is equals to current IE\n"); ++ return err; ++ } ++ ++ strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1); ++ ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0'; ++ ++ /* Buffer contains only 1 IE */ ++ iecount = htod32(1); ++ memcpy((void *)&ie_setbuf->ie_buffer.iecount, &iecount, sizeof(int)); ++ memcpy((void *)&ie_setbuf->ie_buffer.ie_list[0].pktflag, &pktflag, sizeof(uint32)); ++ ++ /* Now, add the IE to the buffer */ ++ ie_setbuf->ie_buffer.ie_list[0].ie_data.id = ie_id; ++ ++ /* if already set with previous values, delete it first */ ++ if (wl->iw_ie_len != 0) { ++ AP6210_DEBUG("Different IW_IE was already set. clear first\n"); ++ ++ ie_setbuf->ie_buffer.ie_list[0].ie_data.len = 0; ++ ++ err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len, ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); ++ ++ if (err != BCME_OK) ++ return err; ++ } ++ ++ ie_setbuf->ie_buffer.ie_list[0].ie_data.len = data_len; ++ memcpy((uchar *)&ie_setbuf->ie_buffer.ie_list[0].ie_data.data[0], data, data_len); ++ ++ err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len, ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); ++ ++ if (err == BCME_OK) { ++ memcpy(wl->iw_ie, data, data_len); ++ wl->iw_ie_len = data_len; ++ wl->wl11u = TRUE; ++ ++ err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 1, bssidx); ++ } ++ ++ kfree(ie_setbuf); ++ return err; ++} ++#endif /* WL11U */ ++ ++#ifdef WL_HOST_BAND_MGMT ++s32 ++wl_cfg80211_set_band(struct net_device *ndev, int band) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ int ret = 0; ++ char ioctl_buf[50]; ++ ++ if ((band < WLC_BAND_AUTO) || (band > WLC_BAND_2G)) { ++ AP6210_ERR("Invalid band\n"); ++ return -EINVAL; ++ } ++ ++ if ((ret = wldev_iovar_setbuf(ndev, "roam_band", &band, ++ sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) { ++ AP6210_ERR("seting roam_band failed code=%d\n", ret); ++ return ret; ++ } ++ ++ AP6210_DEBUG("Setting band to %d\n", band); ++ wl->curr_band = band; ++ ++ return 0; ++} ++#endif /* WL_HOST_BAND_MGMT */ ++ ++#if defined(DHCP_SCAN_SUPPRESS) ++static void wl_cfg80211_scan_supp_timerfunc(ulong data) ++{ ++ struct wl_priv *wl = (struct wl_priv *)data; ++ ++ AP6210_DEBUG("Enter \n"); ++ schedule_work(&wl->wlan_work); ++} ++ ++static void wl_cfg80211_work_handler(struct work_struct *work) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ ++ wl = container_of(work, struct wl_priv, wlan_work); ++ ++ if (!wl) { ++ AP6210_ERR("wl_priv ptr NULL\n"); ++ return; ++ } ++ ++ if (wl->scan_suppressed) { ++ /* There is pending scan_suppress. Clean it */ ++ AP6210_ERR("Clean up from timer after %d msec\n", WL_SCAN_SUPPRESS_TIMEOUT); ++ wl_cfg80211_scan_suppress(wl_to_prmry_ndev(wl), 0); ++ } ++} ++ ++int wl_cfg80211_scan_suppress(struct net_device *dev, int suppress) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ int ret = 0; ++ ++ if (!dev || !wl || ((suppress != 0) && (suppress != 1))) ++ return -EINVAL; ++ ++ if (suppress == wl->scan_suppressed) { ++ AP6210_DEBUG("No change in scan_suppress state. Ignoring cmd..\n"); ++ return 0; ++ } ++ ++ if (timer_pending(&wl->scan_supp_timer)) ++ del_timer_sync(&wl->scan_supp_timer); ++ ++ if ((ret = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS, ++ &suppress, sizeof(int), true)) < 0) { ++ AP6210_ERR("Scan suppress setting failed ret:%d \n", ret); ++ } else { ++ AP6210_DEBUG("Scan suppress %s \n", suppress ? "Enabled" : "Disabled"); ++ wl->scan_suppressed = suppress; ++ } ++ ++ /* If scan_suppress is set, Start a timer to monitor it (just incase) */ ++ if (wl->scan_suppressed) { ++ if (ret) { ++ AP6210_ERR("Retry scan_suppress reset at a later time \n"); ++ mod_timer(&wl->scan_supp_timer, ++ jiffies + msecs_to_jiffies(WL_SCAN_SUPPRESS_RETRY)); ++ } else { ++ AP6210_DEBUG("Start wlan_timer to clear of scan_suppress \n"); ++ mod_timer(&wl->scan_supp_timer, ++ jiffies + msecs_to_jiffies(WL_SCAN_SUPPRESS_TIMEOUT)); ++ } ++ } ++ ++ return ret; ++} ++#endif /* DHCP_SCAN_SUPPRESS */ +diff --git a/drivers/net/wireless/ap6210/wl_cfg80211.h b/drivers/net/wireless/ap6210/wl_cfg80211.h +new file mode 100755 +index 0000000..01dd136 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/wl_cfg80211.h +@@ -0,0 +1,791 @@ ++/* ++ * Linux cfg80211 driver ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: wl_cfg80211.h 374275 2012-12-12 11:44:18Z $ ++ */ ++ ++#ifndef _wl_cfg80211_h_ ++#define _wl_cfg80211_h_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++struct wl_conf; ++struct wl_iface; ++struct wl_priv; ++struct wl_security; ++struct wl_ibss; ++ ++ ++#define htod32(i) i ++#define htod16(i) i ++#define dtoh32(i) i ++#define dtoh16(i) i ++#define htodchanspec(i) i ++#define dtohchanspec(i) i ++ ++#define WL_DBG_NONE 0 ++#define WL_DBG_P2P_ACTION (1 << 5) ++#define WL_DBG_TRACE (1 << 4) ++#define WL_DBG_SCAN (1 << 3) ++#define WL_DBG_DBG (1 << 2) ++#define WL_DBG_INFO (1 << 1) ++#define WL_DBG_ERR (1 << 0) ++ ++/* 0 invalidates all debug messages. default is 1 */ ++#define WL_DBG_LEVEL 0xFF ++ ++#define WL_SCAN_RETRY_MAX 3 ++#define WL_NUM_PMKIDS_MAX MAXPMKID ++#define WL_SCAN_BUF_MAX (1024 * 8) ++#define WL_TLV_INFO_MAX 1500 ++#define WL_SCAN_IE_LEN_MAX 2048 ++#define WL_BSS_INFO_MAX 2048 ++#define WL_ASSOC_INFO_MAX 512 ++#define WL_IOCTL_LEN_MAX 1024 ++#define WL_EXTRA_BUF_MAX 2048 ++#define WL_ISCAN_BUF_MAX 2048 ++#define WL_ISCAN_TIMER_INTERVAL_MS 3000 ++#define WL_SCAN_ERSULTS_LAST (WL_SCAN_RESULTS_NO_MEM+1) ++#define WL_AP_MAX 256 ++#define WL_FILE_NAME_MAX 256 ++#define WL_DWELL_TIME 200 ++#define WL_MED_DWELL_TIME 400 ++#define WL_MIN_DWELL_TIME 100 ++#define WL_LONG_DWELL_TIME 1000 ++#define IFACE_MAX_CNT 2 ++#define WL_SCAN_CONNECT_DWELL_TIME_MS 200 ++#define WL_SCAN_JOIN_PROBE_INTERVAL_MS 20 ++#define WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS 320 ++#define WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS 400 ++#define WL_AF_TX_MAX_RETRY 5 ++ ++#define WL_SCAN_TIMER_INTERVAL_MS 8000 /* Scan timeout */ ++#define WL_CHANNEL_SYNC_RETRY 5 ++#define WL_INVALID -1 ++ ++/* Bring down SCB Timeout to 20secs from 60secs default */ ++#ifndef WL_SCB_TIMEOUT ++#define WL_SCB_TIMEOUT 20 ++#endif ++ ++/* SCAN_SUPPRESS timer values in ms */ ++#define WL_SCAN_SUPPRESS_TIMEOUT 31000 /* default Framwork DHCP timeout is 30 sec */ ++#define WL_SCAN_SUPPRESS_RETRY 3000 ++ ++/* driver status */ ++enum wl_status { ++ WL_STATUS_READY = 0, ++ WL_STATUS_SCANNING, ++ WL_STATUS_SCAN_ABORTING, ++ WL_STATUS_CONNECTING, ++ WL_STATUS_CONNECTED, ++ WL_STATUS_DISCONNECTING, ++ WL_STATUS_AP_CREATING, ++ WL_STATUS_AP_CREATED, ++ /* whole sending action frame procedure: ++ * includes a) 'finding common channel' for public action request frame ++ * and b) 'sending af via 'actframe' iovar' ++ */ ++ WL_STATUS_SENDING_ACT_FRM, ++ /* find a peer to go to a common channel before sending public action req frame */ ++ WL_STATUS_FINDING_COMMON_CHANNEL, ++ /* waiting for next af to sync time of supplicant. ++ * it includes SENDING_ACT_FRM and WAITING_NEXT_ACT_FRM_LISTEN ++ */ ++ WL_STATUS_WAITING_NEXT_ACT_FRM, ++#ifdef WL_CFG80211_SYNC_GON ++ /* go to listen state to wait for next af after SENDING_ACT_FRM */ ++ WL_STATUS_WAITING_NEXT_ACT_FRM_LISTEN, ++#endif /* WL_CFG80211_SYNC_GON */ ++ /* it will be set when upper layer requests listen and succeed in setting listen mode. ++ * if set, other scan request can abort current listen state ++ */ ++ WL_STATUS_REMAINING_ON_CHANNEL, ++#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST ++ /* it's fake listen state to keep current scan state. ++ * it will be set when upper layer requests listen but scan is running. then just run ++ * a expire timer without actual listen state. ++ * if set, other scan request does not need to abort scan. ++ */ ++ WL_STATUS_FAKE_REMAINING_ON_CHANNEL ++#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ ++}; ++ ++/* wi-fi mode */ ++enum wl_mode { ++ WL_MODE_BSS, ++ WL_MODE_IBSS, ++ WL_MODE_AP ++}; ++ ++/* driver profile list */ ++enum wl_prof_list { ++ WL_PROF_MODE, ++ WL_PROF_SSID, ++ WL_PROF_SEC, ++ WL_PROF_IBSS, ++ WL_PROF_BAND, ++ WL_PROF_CHAN, ++ WL_PROF_BSSID, ++ WL_PROF_ACT, ++ WL_PROF_BEACONINT, ++ WL_PROF_DTIMPERIOD ++}; ++ ++/* driver iscan state */ ++enum wl_iscan_state { ++ WL_ISCAN_STATE_IDLE, ++ WL_ISCAN_STATE_SCANING ++}; ++ ++/* donlge escan state */ ++enum wl_escan_state { ++ WL_ESCAN_STATE_IDLE, ++ WL_ESCAN_STATE_SCANING ++}; ++/* fw downloading status */ ++enum wl_fw_status { ++ WL_FW_LOADING_DONE, ++ WL_NVRAM_LOADING_DONE ++}; ++ ++enum wl_management_type { ++ WL_BEACON = 0x1, ++ WL_PROBE_RESP = 0x2, ++ WL_ASSOC_RESP = 0x4 ++}; ++/* beacon / probe_response */ ++struct beacon_proberesp { ++ __le64 timestamp; ++ __le16 beacon_int; ++ __le16 capab_info; ++ u8 variable[0]; ++} __attribute__ ((packed)); ++ ++/* driver configuration */ ++struct wl_conf { ++ u32 frag_threshold; ++ u32 rts_threshold; ++ u32 retry_short; ++ u32 retry_long; ++ s32 tx_power; ++ struct ieee80211_channel channel; ++}; ++ ++typedef s32(*EVENT_HANDLER) (struct wl_priv *wl, ++ struct net_device *ndev, const wl_event_msg_t *e, void *data); ++ ++/* bss inform structure for cfg80211 interface */ ++struct wl_cfg80211_bss_info { ++ u16 band; ++ u16 channel; ++ s16 rssi; ++ u16 frame_len; ++ u8 frame_buf[1]; ++}; ++ ++/* basic structure of scan request */ ++struct wl_scan_req { ++ struct wlc_ssid ssid; ++}; ++ ++/* basic structure of information element */ ++struct wl_ie { ++ u16 offset; ++ u8 buf[WL_TLV_INFO_MAX]; ++}; ++ ++/* event queue for cfg80211 main event */ ++struct wl_event_q { ++ struct list_head eq_list; ++ u32 etype; ++ wl_event_msg_t emsg; ++ s8 edata[1]; ++}; ++ ++/* security information with currently associated ap */ ++struct wl_security { ++ u32 wpa_versions; ++ u32 auth_type; ++ u32 cipher_pairwise; ++ u32 cipher_group; ++ u32 wpa_auth; ++ u32 auth_assoc_res_status; ++}; ++ ++/* ibss information for currently joined ibss network */ ++struct wl_ibss { ++ u8 beacon_interval; /* in millisecond */ ++ u8 atim; /* in millisecond */ ++ s8 join_only; ++ u8 band; ++ u8 channel; ++}; ++ ++/* wl driver profile */ ++struct wl_profile { ++ u32 mode; ++ s32 band; ++ u32 channel; ++ struct wlc_ssid ssid; ++ struct wl_security sec; ++ struct wl_ibss ibss; ++ u8 bssid[ETHER_ADDR_LEN]; ++ u16 beacon_interval; ++ u8 dtim_period; ++ bool active; ++}; ++ ++struct net_info { ++ struct net_device *ndev; ++ struct wireless_dev *wdev; ++ struct wl_profile profile; ++ s32 mode; ++ s32 roam_off; ++ unsigned long sme_state; ++ bool pm_restore; ++ bool pm_block; ++ s32 pm; ++ struct list_head list; /* list of all net_info structure */ ++}; ++typedef s32(*ISCAN_HANDLER) (struct wl_priv *wl); ++ ++/* iscan controller */ ++struct wl_iscan_ctrl { ++ struct net_device *dev; ++ struct timer_list timer; ++ u32 timer_ms; ++ u32 timer_on; ++ s32 state; ++ struct task_struct *tsk; ++ struct semaphore sync; ++ ISCAN_HANDLER iscan_handler[WL_SCAN_ERSULTS_LAST]; ++ void *data; ++ s8 ioctl_buf[WLC_IOCTL_SMLEN]; ++ s8 scan_buf[WL_ISCAN_BUF_MAX]; ++}; ++ ++/* association inform */ ++#define MAX_REQ_LINE 1024 ++struct wl_connect_info { ++ u8 req_ie[MAX_REQ_LINE]; ++ s32 req_ie_len; ++ u8 resp_ie[MAX_REQ_LINE]; ++ s32 resp_ie_len; ++}; ++ ++/* firmware /nvram downloading controller */ ++struct wl_fw_ctrl { ++ const struct firmware *fw_entry; ++ unsigned long status; ++ u32 ptr; ++ s8 fw_name[WL_FILE_NAME_MAX]; ++ s8 nvram_name[WL_FILE_NAME_MAX]; ++}; ++ ++/* assoc ie length */ ++struct wl_assoc_ielen { ++ u32 req_len; ++ u32 resp_len; ++}; ++ ++/* wpa2 pmk list */ ++struct wl_pmk_list { ++ pmkid_list_t pmkids; ++ pmkid_t foo[MAXPMKID - 1]; ++}; ++ ++ ++#define ESCAN_BUF_SIZE (64 * 1024) ++ ++struct escan_info { ++ u32 escan_state; ++#if defined(STATIC_WL_PRIV_STRUCT) ++#ifndef CONFIG_DHD_USE_STATIC_BUF ++#error STATIC_WL_PRIV_STRUCT should be used with CONFIG_DHD_USE_STATIC_BUF ++#endif ++ u8 *escan_buf; ++#else ++ u8 escan_buf[ESCAN_BUF_SIZE]; ++#endif /* STATIC_WL_PRIV_STRUCT */ ++ struct wiphy *wiphy; ++ struct net_device *ndev; ++}; ++ ++struct ap_info { ++/* Structure to hold WPS, WPA IEs for a AP */ ++ u8 probe_res_ie[VNDR_IES_MAX_BUF_LEN]; ++ u8 beacon_ie[VNDR_IES_MAX_BUF_LEN]; ++ u32 probe_res_ie_len; ++ u32 beacon_ie_len; ++ u8 *wpa_ie; ++ u8 *rsn_ie; ++ u8 *wps_ie; ++ bool security_mode; ++}; ++struct btcoex_info { ++ struct timer_list timer; ++ u32 timer_ms; ++ u32 timer_on; ++ u32 ts_dhcp_start; /* ms ts ecord time stats */ ++ u32 ts_dhcp_ok; /* ms ts ecord time stats */ ++ bool dhcp_done; /* flag, indicates that host done with ++ * dhcp before t1/t2 expiration ++ */ ++ s32 bt_state; ++ struct work_struct work; ++ struct net_device *dev; ++}; ++ ++struct sta_info { ++ /* Structure to hold WPS IE for a STA */ ++ u8 probe_req_ie[VNDR_IES_BUF_LEN]; ++ u8 assoc_req_ie[VNDR_IES_BUF_LEN]; ++ u32 probe_req_ie_len; ++ u32 assoc_req_ie_len; ++}; ++ ++struct afx_hdl { ++ wl_af_params_t *pending_tx_act_frm; ++ struct ether_addr tx_dst_addr; ++ struct net_device *dev; ++ struct work_struct work; ++ u32 bssidx; ++ u32 retry; ++ s32 peer_chan; ++ s32 peer_listen_chan; /* search channel: configured by upper layer */ ++ s32 my_listen_chan; /* listen chanel: extract it from prb req or gon req */ ++ bool is_listen; ++ bool ack_recv; ++ bool is_active; ++}; ++ ++struct parsed_ies { ++ wpa_ie_fixed_t *wps_ie; ++ u32 wps_ie_len; ++ wpa_ie_fixed_t *wpa_ie; ++ u32 wpa_ie_len; ++ bcm_tlv_t *wpa2_ie; ++ u32 wpa2_ie_len; ++}; ++ ++ ++#ifdef WL11U ++/* Max length of Interworking element */ ++#define IW_IES_MAX_BUF_LEN 9 ++#endif ++ ++#define MAX_EVENT_BUF_NUM 16 ++typedef struct wl_eventmsg_buf { ++ u16 num; ++ struct { ++ u16 type; ++ bool set; ++ } event [MAX_EVENT_BUF_NUM]; ++} wl_eventmsg_buf_t; ++ ++/* private data of cfg80211 interface */ ++struct wl_priv { ++ struct wireless_dev *wdev; /* representing wl cfg80211 device */ ++ ++ struct wireless_dev *p2p_wdev; /* representing wl cfg80211 device for P2P */ ++ struct net_device *p2p_net; /* reference to p2p0 interface */ ++ ++ struct wl_conf *conf; ++ struct cfg80211_scan_request *scan_request; /* scan request object */ ++ EVENT_HANDLER evt_handler[WLC_E_LAST]; ++ struct list_head eq_list; /* used for event queue */ ++ struct list_head net_list; /* used for struct net_info */ ++ spinlock_t eq_lock; /* for event queue synchronization */ ++ spinlock_t cfgdrv_lock; /* to protect scan status (and others if needed) */ ++ struct completion act_frm_scan; ++ struct completion iface_disable; ++ struct completion wait_next_af; ++ struct mutex usr_sync; /* maily for up/down synchronization */ ++ struct wl_scan_results *bss_list; ++ struct wl_scan_results *scan_results; ++ ++ /* scan request object for internal purpose */ ++ struct wl_scan_req *scan_req_int; ++ /* information element object for internal purpose */ ++#if defined(STATIC_WL_PRIV_STRUCT) ++ struct wl_ie *ie; ++#else ++ struct wl_ie ie; ++#endif ++ struct wl_iscan_ctrl *iscan; /* iscan controller */ ++ ++ /* association information container */ ++#if defined(STATIC_WL_PRIV_STRUCT) ++ struct wl_connect_info *conn_info; ++#else ++ struct wl_connect_info conn_info; ++#endif ++ ++ struct wl_pmk_list *pmk_list; /* wpa2 pmk list */ ++ tsk_ctl_t event_tsk; /* task of main event handler thread */ ++ void *pub; ++ u32 iface_cnt; ++ u32 channel; /* current channel */ ++ u32 af_sent_channel; /* channel action frame is sent */ ++ /* next af subtype to cancel the remained dwell time in rx process */ ++ u8 next_af_subtype; ++#ifdef WL_CFG80211_SYNC_GON ++ ulong af_tx_sent_jiffies; ++#endif /* WL_CFG80211_SYNC_GON */ ++ bool iscan_on; /* iscan on/off switch */ ++ bool iscan_kickstart; /* indicate iscan already started */ ++ bool escan_on; /* escan on/off switch */ ++ struct escan_info escan_info; /* escan information */ ++ bool active_scan; /* current scan mode */ ++ bool ibss_starter; /* indicates this sta is ibss starter */ ++ bool link_up; /* link/connection up flag */ ++ ++ /* indicate whether chip to support power save mode */ ++ bool pwr_save; ++ bool roam_on; /* on/off switch for self-roaming */ ++ bool scan_tried; /* indicates if first scan attempted */ ++ bool wlfc_on; ++ bool vsdb_mode; ++ bool roamoff_on_concurrent; ++ u8 *ioctl_buf; /* ioctl buffer */ ++ struct mutex ioctl_buf_sync; ++ u8 *escan_ioctl_buf; ++ u8 *extra_buf; /* maily to grab assoc information */ ++ struct dentry *debugfsdir; ++ struct rfkill *rfkill; ++ bool rf_blocked; ++ struct ieee80211_channel remain_on_chan; ++ enum nl80211_channel_type remain_on_chan_type; ++ u64 send_action_id; ++ u64 last_roc_id; ++ wait_queue_head_t netif_change_event; ++ struct completion send_af_done; ++ struct afx_hdl *afx_hdl; ++ struct ap_info *ap_info; ++ struct sta_info *sta_info; ++ struct p2p_info *p2p; ++ bool p2p_supported; ++ struct btcoex_info *btcoex_info; ++ struct timer_list scan_timeout; /* Timer for catch scan event timeout */ ++ s32(*state_notifier) (struct wl_priv *wl, ++ struct net_info *_net_info, enum wl_status state, bool set); ++ unsigned long interrested_state; ++ wlc_ssid_t hostapd_ssid; ++#ifdef WL11U ++ bool wl11u; ++ u8 iw_ie[IW_IES_MAX_BUF_LEN]; ++ u32 iw_ie_len; ++#endif /* WL11U */ ++ bool sched_scan_running; /* scheduled scan req status */ ++#ifdef WL_SCHED_SCAN ++ struct cfg80211_sched_scan_request *sched_scan_req; /* scheduled scan req */ ++#endif /* WL_SCHED_SCAN */ ++#ifdef WL_HOST_BAND_MGMT ++ u8 curr_band; ++#endif /* WL_HOST_BAND_MGMT */ ++ bool scan_suppressed; ++ struct timer_list scan_supp_timer; ++ struct work_struct wlan_work; ++ struct mutex event_sync; /* maily for up/down synchronization */ ++}; ++ ++ ++static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss) ++{ ++ return bss = bss ? ++ (struct wl_bss_info *)((uintptr) bss + dtoh32(bss->length)) : list->bss_info; ++} ++static inline s32 ++wl_alloc_netinfo(struct wl_priv *wl, struct net_device *ndev, ++ struct wireless_dev * wdev, s32 mode, bool pm_block) ++{ ++ struct net_info *_net_info; ++ s32 err = 0; ++ if (wl->iface_cnt == IFACE_MAX_CNT) ++ return -ENOMEM; ++ _net_info = kzalloc(sizeof(struct net_info), GFP_KERNEL); ++ if (!_net_info) ++ err = -ENOMEM; ++ else { ++ _net_info->mode = mode; ++ _net_info->ndev = ndev; ++ _net_info->wdev = wdev; ++ _net_info->pm_restore = 0; ++ _net_info->pm = 0; ++ _net_info->pm_block = pm_block; ++ _net_info->roam_off = WL_INVALID; ++ wl->iface_cnt++; ++ list_add(&_net_info->list, &wl->net_list); ++ } ++ return err; ++} ++static inline void ++wl_dealloc_netinfo(struct wl_priv *wl, struct net_device *ndev) ++{ ++ struct net_info *_net_info, *next; ++ ++ list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { ++ if (ndev && (_net_info->ndev == ndev)) { ++ list_del(&_net_info->list); ++ wl->iface_cnt--; ++ if (_net_info->wdev) { ++ kfree(_net_info->wdev); ++ ndev->ieee80211_ptr = NULL; ++ } ++ kfree(_net_info); ++ } ++ } ++ ++} ++static inline void ++wl_delete_all_netinfo(struct wl_priv *wl) ++{ ++ struct net_info *_net_info, *next; ++ ++ list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { ++ list_del(&_net_info->list); ++ if (_net_info->wdev) ++ kfree(_net_info->wdev); ++ kfree(_net_info); ++ } ++ wl->iface_cnt = 0; ++} ++static inline u32 ++wl_get_status_all(struct wl_priv *wl, s32 status) ++ ++{ ++ struct net_info *_net_info, *next; ++ u32 cnt = 0; ++ list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { ++ if (_net_info->ndev && ++ test_bit(status, &_net_info->sme_state)) ++ cnt++; ++ } ++ return cnt; ++} ++static inline void ++wl_set_status_all(struct wl_priv *wl, s32 status, u32 op) ++{ ++ struct net_info *_net_info, *next; ++ list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { ++ switch (op) { ++ case 1: ++ return; /* set all status is not allowed */ ++ case 2: ++ clear_bit(status, &_net_info->sme_state); ++ if (wl->state_notifier && ++ test_bit(status, &(wl->interrested_state))) ++ wl->state_notifier(wl, _net_info, status, false); ++ break; ++ case 4: ++ return; /* change all status is not allowed */ ++ default: ++ return; /* unknown operation */ ++ } ++ } ++} ++static inline void ++wl_set_status_by_netdev(struct wl_priv *wl, s32 status, ++ struct net_device *ndev, u32 op) ++{ ++ ++ struct net_info *_net_info, *next; ++ ++ list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { ++ if (ndev && (_net_info->ndev == ndev)) { ++ switch (op) { ++ case 1: ++ set_bit(status, &_net_info->sme_state); ++ if (wl->state_notifier && ++ test_bit(status, &(wl->interrested_state))) ++ wl->state_notifier(wl, _net_info, status, true); ++ break; ++ case 2: ++ clear_bit(status, &_net_info->sme_state); ++ if (wl->state_notifier && ++ test_bit(status, &(wl->interrested_state))) ++ wl->state_notifier(wl, _net_info, status, false); ++ break; ++ case 4: ++ change_bit(status, &_net_info->sme_state); ++ break; ++ } ++ } ++ ++ } ++ ++} ++ ++static inline u32 ++wl_get_status_by_netdev(struct wl_priv *wl, s32 status, ++ struct net_device *ndev) ++{ ++ struct net_info *_net_info, *next; ++ ++ list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { ++ if (ndev && (_net_info->ndev == ndev)) ++ return test_bit(status, &_net_info->sme_state); ++ } ++ return 0; ++} ++ ++static inline s32 ++wl_get_mode_by_netdev(struct wl_priv *wl, struct net_device *ndev) ++{ ++ struct net_info *_net_info, *next; ++ ++ list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { ++ if (ndev && (_net_info->ndev == ndev)) ++ return _net_info->mode; ++ } ++ return -1; ++} ++ ++ ++static inline void ++wl_set_mode_by_netdev(struct wl_priv *wl, struct net_device *ndev, ++ s32 mode) ++{ ++ struct net_info *_net_info, *next; ++ ++ list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { ++ if (ndev && (_net_info->ndev == ndev)) ++ _net_info->mode = mode; ++ } ++} ++static inline struct wl_profile * ++wl_get_profile_by_netdev(struct wl_priv *wl, struct net_device *ndev) ++{ ++ struct net_info *_net_info, *next; ++ ++ list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { ++ if (ndev && (_net_info->ndev == ndev)) ++ return &_net_info->profile; ++ } ++ return NULL; ++} ++static inline struct net_info * ++wl_get_netinfo_by_netdev(struct wl_priv *wl, struct net_device *ndev) ++{ ++ struct net_info *_net_info, *next; ++ ++ list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { ++ if (ndev && (_net_info->ndev == ndev)) ++ return _net_info; ++ } ++ return NULL; ++} ++#define wl_to_wiphy(w) (w->wdev->wiphy) ++#define wl_to_prmry_ndev(w) (w->wdev->netdev) ++#define ndev_to_wl(n) (wdev_to_wl(n->ieee80211_ptr)) ++#define wl_to_sr(w) (w->scan_req_int) ++#if defined(STATIC_WL_PRIV_STRUCT) ++#define wl_to_ie(w) (w->ie) ++#define wl_to_conn(w) (w->conn_info) ++#else ++#define wl_to_ie(w) (&w->ie) ++#define wl_to_conn(w) (&w->conn_info) ++#endif ++#define iscan_to_wl(i) ((struct wl_priv *)(i->data)) ++#define wl_to_iscan(w) (w->iscan) ++#define wiphy_from_scan(w) (w->escan_info.wiphy) ++#define wl_get_drv_status_all(wl, stat) \ ++ (wl_get_status_all(wl, WL_STATUS_ ## stat)) ++#define wl_get_drv_status(wl, stat, ndev) \ ++ (wl_get_status_by_netdev(wl, WL_STATUS_ ## stat, ndev)) ++#define wl_set_drv_status(wl, stat, ndev) \ ++ (wl_set_status_by_netdev(wl, WL_STATUS_ ## stat, ndev, 1)) ++#define wl_clr_drv_status(wl, stat, ndev) \ ++ (wl_set_status_by_netdev(wl, WL_STATUS_ ## stat, ndev, 2)) ++#define wl_clr_drv_status_all(wl, stat) \ ++ (wl_set_status_all(wl, WL_STATUS_ ## stat, 2)) ++#define wl_chg_drv_status(wl, stat, ndev) \ ++ (wl_set_status_by_netdev(wl, WL_STATUS_ ## stat, ndev, 4)) ++ ++#define for_each_bss(list, bss, __i) \ ++ for (__i = 0; __i < list->count && __i < WL_AP_MAX; __i++, bss = next_bss(list, bss)) ++ ++#define for_each_ndev(wl, iter, next) \ ++ list_for_each_entry_safe(iter, next, &wl->net_list, list) ++ ++ ++/* In case of WPS from wpa_supplicant, pairwise siute and group suite is 0. ++ * In addtion to that, wpa_version is WPA_VERSION_1 ++ */ ++#define is_wps_conn(_sme) \ ++ ((wl_cfgp2p_find_wpsie((u8 *)_sme->ie, _sme->ie_len) != NULL) && \ ++ (!_sme->crypto.n_ciphers_pairwise) && \ ++ (!_sme->crypto.cipher_group)) ++extern s32 wl_cfg80211_attach(struct net_device *ndev, void *data); ++extern s32 wl_cfg80211_attach_post(struct net_device *ndev); ++extern void wl_cfg80211_detach(void *para); ++ ++extern void wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e, ++ void *data); ++void wl_cfg80211_set_parent_dev(void *dev); ++struct device *wl_cfg80211_get_parent_dev(void); ++ ++extern s32 wl_cfg80211_up(void *para); ++extern s32 wl_cfg80211_down(void *para); ++extern s32 wl_cfg80211_notify_ifadd(struct net_device *ndev, s32 idx, s32 bssidx, ++ void* _net_attach); ++extern s32 wl_cfg80211_ifdel_ops(struct net_device *net); ++extern s32 wl_cfg80211_notify_ifdel(void); ++extern s32 wl_cfg80211_is_progress_ifadd(void); ++extern s32 wl_cfg80211_is_progress_ifchange(void); ++extern s32 wl_cfg80211_is_progress_ifadd(void); ++extern s32 wl_cfg80211_notify_ifchange(void); ++extern void wl_cfg80211_dbg_level(u32 level); ++extern s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr); ++extern s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len); ++extern s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len); ++extern s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len, ++ enum wl_management_type type); ++extern s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len); ++extern int wl_cfg80211_hang(struct net_device *dev, u16 reason); ++extern s32 wl_mode_to_nl80211_iftype(s32 mode); ++int wl_cfg80211_do_driver_init(struct net_device *net); ++void wl_cfg80211_enable_trace(u32 level); ++extern s32 wl_update_wiphybands(struct wl_priv *wl, bool notify); ++extern s32 wl_cfg80211_if_is_group_owner(void); ++extern chanspec_t wl_ch_host_to_driver(u16 channel); ++extern s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add); ++extern void wl_stop_wait_next_action_frame(struct wl_priv *wl, struct net_device *ndev); ++extern s32 wl_cfg80211_set_band(struct net_device *ndev, int band); ++extern int wl_cfg80211_update_power_mode(struct net_device *dev); ++#if defined(DHCP_SCAN_SUPPRESS) ++extern int wl_cfg80211_scan_suppress(struct net_device *dev, int suppress); ++#endif /* OEM_ANDROID */ ++extern void wl_cfg80211_add_to_eventbuffer(wl_eventmsg_buf_t *ev, u16 event, bool set); ++extern s32 wl_cfg80211_apply_eventbuffer(struct net_device *ndev, ++ struct wl_priv *wl, wl_eventmsg_buf_t *ev); ++#endif /* _wl_cfg80211_h_ */ +diff --git a/drivers/net/wireless/ap6210/wl_cfgp2p.c b/drivers/net/wireless/ap6210/wl_cfgp2p.c +new file mode 100755 +index 0000000..eb7df08 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/wl_cfgp2p.c +@@ -0,0 +1,2393 @@ ++/* ++ * Linux cfgp2p driver ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: wl_cfgp2p.c 372668 2012-12-04 14:07:12Z $ ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++static s8 scanparambuf[WLC_IOCTL_SMLEN]; ++static s8 g_mgmt_ie_buf[2048]; ++static bool ++wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type); ++ ++static u32 ++wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 bssidx, s32 pktflag, ++ s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd); ++ ++static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev); ++static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd); ++static int wl_cfgp2p_if_open(struct net_device *net); ++static int wl_cfgp2p_if_stop(struct net_device *net); ++static s32 wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev, ++ bool notify); ++ ++static const struct net_device_ops wl_cfgp2p_if_ops = { ++ .ndo_open = wl_cfgp2p_if_open, ++ .ndo_stop = wl_cfgp2p_if_stop, ++ .ndo_do_ioctl = wl_cfgp2p_do_ioctl, ++ .ndo_start_xmit = wl_cfgp2p_start_xmit, ++}; ++ ++bool wl_cfgp2p_is_pub_action(void *frame, u32 frame_len) ++{ ++ wifi_p2p_pub_act_frame_t *pact_frm; ++ ++ if (frame == NULL) ++ return false; ++ pact_frm = (wifi_p2p_pub_act_frame_t *)frame; ++ if (frame_len < sizeof(wifi_p2p_pub_act_frame_t) -1) ++ return false; ++ ++ if (pact_frm->category == P2P_PUB_AF_CATEGORY && ++ pact_frm->action == P2P_PUB_AF_ACTION && ++ pact_frm->oui_type == P2P_VER && ++ memcmp(pact_frm->oui, P2P_OUI, sizeof(pact_frm->oui)) == 0) { ++ return true; ++ } ++ ++ return false; ++} ++ ++bool wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len) ++{ ++ wifi_p2p_action_frame_t *act_frm; ++ ++ if (frame == NULL) ++ return false; ++ act_frm = (wifi_p2p_action_frame_t *)frame; ++ if (frame_len < sizeof(wifi_p2p_action_frame_t) -1) ++ return false; ++ ++ if (act_frm->category == P2P_AF_CATEGORY && ++ act_frm->type == P2P_VER && ++ memcmp(act_frm->OUI, P2P_OUI, DOT11_OUI_LEN) == 0) { ++ return true; ++ } ++ ++ return false; ++} ++ ++/* ++* Currently Action frame just pass to P2P interface regardless real dst. ++* but GAS Action can be used for Hotspot2.0 as well ++* Need to distingush that it's for P2P or HS20 ++*/ ++#ifdef WL11U ++#define GAS_RESP_LEN 2 ++#define DOUBLE_TLV_BODY_OFF 4 ++#define GAS_RESP_OFFSET 4 ++#define GAS_CRESP_OFFSET 5 ++ ++bool wl_cfgp2p_find_gas_subtype(u8 subtype, u8* data, u32 len) ++{ ++ bcm_tlv_t *ie = (bcm_tlv_t *)data; ++ u8 *frame = NULL; ++ u16 id, flen; ++ ++ /* Skipped first ANQP Element, if frame has anqp elemnt */ ++ ie = bcm_parse_tlvs(ie, (int)len, DOT11_MNG_ADVERTISEMENT_ID); ++ ++ if (ie == NULL) ++ return false; ++ ++ frame = (uint8 *)ie + ie->len + TLV_HDR_LEN + GAS_RESP_LEN; ++ id = ((u16) (((frame)[1] << 8) | (frame)[0])); ++ flen = ((u16) (((frame)[3] << 8) | (frame)[2])); ++ ++ /* If the contents match the OUI and the type */ ++ if (flen >= WFA_OUI_LEN + 1 && ++ id == P2PSD_GAS_NQP_INFOID && ++ !bcmp(&frame[DOUBLE_TLV_BODY_OFF], (const uint8*)WFA_OUI, WFA_OUI_LEN) && ++ subtype == frame[DOUBLE_TLV_BODY_OFF+WFA_OUI_LEN]) { ++ return true; ++ } ++ ++ return false; ++} ++#endif /* WL11U */ ++ ++bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len) ++{ ++ ++ wifi_p2psd_gas_pub_act_frame_t *sd_act_frm; ++ ++ if (frame == NULL) ++ return false; ++ ++ sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame; ++ if (frame_len < sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1) ++ return false; ++ if (sd_act_frm->category != P2PSD_ACTION_CATEGORY) ++ return false; ++ ++#ifdef WL11U ++ if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IRESP) ++ return wl_cfgp2p_find_gas_subtype(P2PSD_GAS_OUI_SUBTYPE, ++ (u8 *)sd_act_frm->query_data + GAS_RESP_OFFSET, ++ frame_len); ++ ++ else if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_CRESP) ++ return wl_cfgp2p_find_gas_subtype(P2PSD_GAS_OUI_SUBTYPE, ++ (u8 *)sd_act_frm->query_data + GAS_CRESP_OFFSET, ++ frame_len); ++ else if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ || ++ sd_act_frm->action == P2PSD_ACTION_ID_GAS_CREQ) ++ return true; ++ else ++ return false; ++#else ++ if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ || ++ sd_act_frm->action == P2PSD_ACTION_ID_GAS_IRESP || ++ sd_act_frm->action == P2PSD_ACTION_ID_GAS_CREQ || ++ sd_act_frm->action == P2PSD_ACTION_ID_GAS_CRESP) ++ return true; ++ else ++ return false; ++#endif /* WLC11U */ ++} ++void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len) ++{ ++ wifi_p2p_pub_act_frame_t *pact_frm; ++ wifi_p2p_action_frame_t *act_frm; ++ wifi_p2psd_gas_pub_act_frame_t *sd_act_frm; ++ if (!frame || frame_len <= 2) ++ return; ++ ++ if (wl_cfgp2p_is_pub_action(frame, frame_len)) { ++ pact_frm = (wifi_p2p_pub_act_frame_t *)frame; ++ switch (pact_frm->subtype) { ++ case P2P_PAF_GON_REQ: ++ AP6210_DEBUG("%s P2P Group Owner Negotiation Req Frame\n", ++ (tx)? "TX": "RX"); ++ break; ++ case P2P_PAF_GON_RSP: ++ AP6210_DEBUG("%s P2P Group Owner Negotiation Rsp Frame\n", ++ (tx)? "TX": "RX"); ++ break; ++ case P2P_PAF_GON_CONF: ++ AP6210_DEBUG("%s P2P Group Owner Negotiation Confirm Frame\n", ++ (tx)? "TX": "RX"); ++ break; ++ case P2P_PAF_INVITE_REQ: ++ AP6210_DEBUG("%s P2P Invitation Request Frame\n", ++ (tx)? "TX": "RX"); ++ break; ++ case P2P_PAF_INVITE_RSP: ++ AP6210_DEBUG("%s P2P Invitation Response Frame\n", ++ (tx)? "TX": "RX"); ++ break; ++ case P2P_PAF_DEVDIS_REQ: ++ AP6210_DEBUG("%s P2P Device Discoverability Request Frame\n", ++ (tx)? "TX": "RX"); ++ break; ++ case P2P_PAF_DEVDIS_RSP: ++ AP6210_DEBUG("%s P2P Device Discoverability Response Frame\n", ++ (tx)? "TX": "RX"); ++ break; ++ case P2P_PAF_PROVDIS_REQ: ++ AP6210_DEBUG("%s P2P Provision Discovery Request Frame\n", ++ (tx)? "TX": "RX"); ++ break; ++ case P2P_PAF_PROVDIS_RSP: ++ AP6210_DEBUG("%s P2P Provision Discovery Response Frame\n", ++ (tx)? "TX": "RX"); ++ break; ++ default: ++ AP6210_DEBUG("%s Unknown P2P Public Action Frame\n", ++ (tx)? "TX": "RX"); ++ ++ } ++ ++ } else if (wl_cfgp2p_is_p2p_action(frame, frame_len)) { ++ act_frm = (wifi_p2p_action_frame_t *)frame; ++ switch (act_frm->subtype) { ++ case P2P_AF_NOTICE_OF_ABSENCE: ++ AP6210_DEBUG("%s P2P Notice of Absence Frame\n", ++ (tx)? "TX": "RX"); ++ break; ++ case P2P_AF_PRESENCE_REQ: ++ AP6210_DEBUG("%s P2P Presence Request Frame\n", ++ (tx)? "TX": "RX"); ++ break; ++ case P2P_AF_PRESENCE_RSP: ++ AP6210_DEBUG("%s P2P Presence Response Frame\n", ++ (tx)? "TX": "RX"); ++ break; ++ case P2P_AF_GO_DISC_REQ: ++ AP6210_DEBUG("%s P2P Discoverability Request Frame\n", ++ (tx)? "TX": "RX"); ++ break; ++ default: ++ AP6210_DEBUG("%s Unknown P2P Action Frame\n", ++ (tx)? "TX": "RX"); ++ } ++ ++ } else if (wl_cfgp2p_is_gas_action(frame, frame_len)) { ++ sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame; ++ switch (sd_act_frm->action) { ++ case P2PSD_ACTION_ID_GAS_IREQ: ++ AP6210_DEBUG("%s P2P GAS Initial Request\n", ++ (tx)? "TX" : "RX"); ++ break; ++ case P2PSD_ACTION_ID_GAS_IRESP: ++ AP6210_DEBUG("%s P2P GAS Initial Response\n", ++ (tx)? "TX" : "RX"); ++ break; ++ case P2PSD_ACTION_ID_GAS_CREQ: ++ AP6210_DEBUG("%s P2P GAS Comback Request\n", ++ (tx)? "TX" : "RX"); ++ break; ++ case P2PSD_ACTION_ID_GAS_CRESP: ++ AP6210_DEBUG("%s P2P GAS Comback Response\n", ++ (tx)? "TX" : "RX"); ++ break; ++ default: ++ AP6210_DEBUG("%s Unknown P2P GAS Frame\n", ++ (tx)? "TX" : "RX"); ++ } ++ ++ ++ } ++} ++ ++/* ++ * Initialize variables related to P2P ++ * ++ */ ++s32 ++wl_cfgp2p_init_priv(struct wl_priv *wl) ++{ ++ if (!(wl->p2p = kzalloc(sizeof(struct p2p_info), GFP_KERNEL))) { ++ AP6210_ERR("struct p2p_info allocation failed\n"); ++ return -ENOMEM; ++ } ++#define INIT_IE(IE_TYPE, BSS_TYPE) \ ++ do { \ ++ memset(wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie, 0, \ ++ sizeof(wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie)); \ ++ wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie_len = 0; \ ++ } while (0); ++ ++ INIT_IE(probe_req, P2PAPI_BSSCFG_PRIMARY); ++ INIT_IE(probe_res, P2PAPI_BSSCFG_PRIMARY); ++ INIT_IE(assoc_req, P2PAPI_BSSCFG_PRIMARY); ++ INIT_IE(assoc_res, P2PAPI_BSSCFG_PRIMARY); ++ INIT_IE(beacon, P2PAPI_BSSCFG_PRIMARY); ++ INIT_IE(probe_req, P2PAPI_BSSCFG_DEVICE); ++ INIT_IE(probe_res, P2PAPI_BSSCFG_DEVICE); ++ INIT_IE(assoc_req, P2PAPI_BSSCFG_DEVICE); ++ INIT_IE(assoc_res, P2PAPI_BSSCFG_DEVICE); ++ INIT_IE(beacon, P2PAPI_BSSCFG_DEVICE); ++ INIT_IE(probe_req, P2PAPI_BSSCFG_CONNECTION); ++ INIT_IE(probe_res, P2PAPI_BSSCFG_CONNECTION); ++ INIT_IE(assoc_req, P2PAPI_BSSCFG_CONNECTION); ++ INIT_IE(assoc_res, P2PAPI_BSSCFG_CONNECTION); ++ INIT_IE(beacon, P2PAPI_BSSCFG_CONNECTION); ++#undef INIT_IE ++ wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY) = wl_to_prmry_ndev(wl); ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY) = 0; ++ wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE) = NULL; ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) = 0; ++ wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = NULL; ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = 0; ++ return BCME_OK; ++ ++} ++/* ++ * Deinitialize variables related to P2P ++ * ++ */ ++void ++wl_cfgp2p_deinit_priv(struct wl_priv *wl) ++{ ++ AP6210_DEBUG("In\n"); ++ if (wl->p2p) { ++ kfree(wl->p2p); ++ wl->p2p = NULL; ++ } ++ wl->p2p_supported = 0; ++} ++/* ++ * Set P2P functions into firmware ++ */ ++s32 ++wl_cfgp2p_set_firm_p2p(struct wl_priv *wl) ++{ ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++ struct ether_addr null_eth_addr = { { 0, 0, 0, 0, 0, 0 } }; ++ s32 ret = BCME_OK; ++ s32 val = 0; ++ /* Do we have to check whether APSTA is enabled or not ? */ ++ wldev_iovar_getint(ndev, "apsta", &val); ++ if (val == 0) { ++ val = 1; ++ ret = wldev_ioctl(ndev, WLC_DOWN, &val, sizeof(s32), true); ++ if (ret < 0) { ++ AP6210_ERR("WLC_DOWN error %d\n", ret); ++ return ret; ++ } ++ wldev_iovar_setint(ndev, "apsta", val); ++ ret = wldev_ioctl(ndev, WLC_UP, &val, sizeof(s32), true); ++ if (ret < 0) { ++ AP6210_ERR("WLC_UP error %d\n", ret); ++ return ret; ++ } ++ } ++ ++ /* In case of COB type, firmware has default mac address ++ * After Initializing firmware, we have to set current mac address to ++ * firmware for P2P device address ++ */ ++ ret = wldev_iovar_setbuf_bsscfg(ndev, "p2p_da_override", &null_eth_addr, ++ sizeof(null_eth_addr), wl->ioctl_buf, WLC_IOCTL_MAXLEN, 0, &wl->ioctl_buf_sync); ++ if (ret && ret != BCME_UNSUPPORTED) { ++ AP6210_ERR("failed to update device address ret %d\n", ret); ++ } ++ return ret; ++} ++ ++/* Create a new P2P BSS. ++ * Parameters: ++ * @mac : MAC address of the BSS to create ++ * @if_type : interface type: WL_P2P_IF_GO or WL_P2P_IF_CLIENT ++ * @chspec : chspec to use if creating a GO BSS. ++ * Returns 0 if success. ++ */ ++s32 ++wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, ++ chanspec_t chspec) ++{ ++ wl_p2p_if_t ifreq; ++ s32 err; ++ u32 scb_timeout = WL_SCB_TIMEOUT; ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++ ++ ifreq.type = if_type; ++ ifreq.chspec = chspec; ++ memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet)); ++ ++ AP6210_DEBUG("---wl p2p_ifadd "MACDBG" %s %u\n", ++ MAC2STRDBG(ifreq.addr.octet), ++ (if_type == WL_P2P_IF_GO) ? "go" : "client", ++ (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT); ++ ++ err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq), ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); ++ ++ if (unlikely(err < 0)) ++ AP6210_DEBUG("'wl p2p_ifadd' error %d\n", err); ++ else if (if_type == WL_P2P_IF_GO) { ++ err = wldev_ioctl(ndev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true); ++ if (unlikely(err < 0)) ++ AP6210_DEBUG("'wl scb_timeout' error %d\n", err); ++ } ++ return err; ++} ++ ++/* Disable a P2P BSS. ++ * Parameters: ++ * @mac : MAC address of the BSS to create ++ * Returns 0 if success. ++ */ ++s32 ++wl_cfgp2p_ifdisable(struct wl_priv *wl, struct ether_addr *mac) ++{ ++ s32 ret; ++ struct net_device *netdev = wl_to_prmry_ndev(wl); ++ ++ AP6210_DEBUG("------primary idx %d : wl p2p_ifdis "MACDBG"\n", ++ netdev->ifindex, MAC2STRDBG(mac->octet)); ++ ret = wldev_iovar_setbuf(netdev, "p2p_ifdis", mac, sizeof(*mac), ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); ++ if (unlikely(ret < 0)) { ++ AP6210_DEBUG("'wl p2p_ifdis' error %d\n", ret); ++ } ++ return ret; ++} ++ ++/* Delete a P2P BSS. ++ * Parameters: ++ * @mac : MAC address of the BSS to create ++ * Returns 0 if success. ++ */ ++s32 ++wl_cfgp2p_ifdel(struct wl_priv *wl, struct ether_addr *mac) ++{ ++ s32 ret; ++ struct net_device *netdev = wl_to_prmry_ndev(wl); ++ ++ AP6210_DEBUG("------primary idx %d : wl p2p_ifdel "MACDBG"\n", ++ netdev->ifindex, MAC2STRDBG(mac->octet)); ++ ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac), ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); ++ if (unlikely(ret < 0)) { ++ AP6210_DEBUG("'wl p2p_ifdel' error %d\n", ret); ++ } ++ return ret; ++} ++ ++/* Change a P2P Role. ++ * Parameters: ++ * @mac : MAC address of the BSS to change a role ++ * Returns 0 if success. ++ */ ++s32 ++wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, ++ chanspec_t chspec) ++{ ++ wl_p2p_if_t ifreq; ++ s32 err; ++ u32 scb_timeout = WL_SCB_TIMEOUT; ++ ++ struct net_device *netdev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); ++ ++ ifreq.type = if_type; ++ ifreq.chspec = chspec; ++ memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet)); ++ ++ AP6210_DEBUG("---wl p2p_ifchange "MACDBG" %s %u" ++ " chanspec 0x%04x\n", MAC2STRDBG(ifreq.addr.octet), ++ (if_type == WL_P2P_IF_GO) ? "go" : "client", ++ (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT, ++ ifreq.chspec); ++ ++ err = wldev_iovar_setbuf(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq), ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); ++ ++ if (unlikely(err < 0)) { ++ AP6210_DEBUG("'wl p2p_ifupd' error %d\n", err); ++ } else if (if_type == WL_P2P_IF_GO) { ++ err = wldev_ioctl(netdev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true); ++ if (unlikely(err < 0)) ++ AP6210_DEBUG("'wl scb_timeout' error %d\n", err); ++ } ++ return err; ++} ++ ++ ++/* Get the index of a created P2P BSS. ++ * Parameters: ++ * @mac : MAC address of the created BSS ++ * @index : output: index of created BSS ++ * Returns 0 if success. ++ */ ++s32 ++wl_cfgp2p_ifidx(struct wl_priv *wl, struct ether_addr *mac, s32 *index) ++{ ++ s32 ret; ++ u8 getbuf[64]; ++ struct net_device *dev = wl_to_prmry_ndev(wl); ++ ++ AP6210_DEBUG("---wl p2p_if "MACDBG"\n", MAC2STRDBG(mac->octet)); ++ ++ ret = wldev_iovar_getbuf_bsscfg(dev, "p2p_if", mac, sizeof(*mac), getbuf, ++ sizeof(getbuf), wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY), NULL); ++ ++ if (ret == 0) { ++ memcpy(index, getbuf, sizeof(s32)); ++ AP6210_DEBUG("---wl p2p_if ==> %d\n", *index); ++ } ++ ++ return ret; ++} ++ ++static s32 ++wl_cfgp2p_set_discovery(struct wl_priv *wl, s32 on) ++{ ++ s32 ret = BCME_OK; ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++ AP6210_DEBUG("enter\n"); ++ ++ ret = wldev_iovar_setint(ndev, "p2p_disc", on); ++ ++ if (unlikely(ret < 0)) { ++ AP6210_ERR("p2p_disc %d error %d\n", on, ret); ++ } ++ ++ return ret; ++} ++ ++/* Set the WL driver's P2P mode. ++ * Parameters : ++ * @mode : is one of WL_P2P_DISC_ST_{SCAN,LISTEN,SEARCH}. ++ * @channel : the channel to listen ++ * @listen_ms : the time (milli seconds) to wait ++ * @bssidx : bss index for BSSCFG ++ * Returns 0 if success ++ */ ++ ++s32 ++wl_cfgp2p_set_p2p_mode(struct wl_priv *wl, u8 mode, u32 channel, u16 listen_ms, int bssidx) ++{ ++ wl_p2p_disc_st_t discovery_mode; ++ s32 ret; ++ struct net_device *dev; ++ AP6210_DEBUG("enter\n"); ++ ++ if (unlikely(bssidx == WL_INVALID || bssidx >= P2PAPI_BSSCFG_MAX)) { ++ AP6210_ERR(" %d index out of range\n", bssidx); ++ return -1; ++ } ++ ++ dev = wl_to_p2p_bss_ndev(wl, bssidx); ++ if (unlikely(dev == NULL)) { ++ AP6210_ERR("bssidx %d is not assigned\n", bssidx); ++ return BCME_NOTFOUND; ++ } ++ ++ /* Put the WL driver into P2P Listen Mode to respond to P2P probe reqs */ ++ discovery_mode.state = mode; ++ discovery_mode.chspec = wl_ch_host_to_driver(channel); ++ discovery_mode.dwell = listen_ms; ++ ret = wldev_iovar_setbuf_bsscfg(dev, "p2p_state", &discovery_mode, ++ sizeof(discovery_mode), wl->ioctl_buf, WLC_IOCTL_MAXLEN, ++ bssidx, &wl->ioctl_buf_sync); ++ ++ return ret; ++} ++ ++/* Get the index of the P2P Discovery BSS */ ++static s32 ++wl_cfgp2p_get_disc_idx(struct wl_priv *wl, s32 *index) ++{ ++ s32 ret; ++ struct net_device *dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY); ++ ++ ret = wldev_iovar_getint(dev, "p2p_dev", index); ++ AP6210_DEBUG("p2p_dev bsscfg_idx=%d ret=%d\n", *index, ret); ++ ++ if (unlikely(ret < 0)) { ++ AP6210_ERR("'p2p_dev' error %d\n", ret); ++ return ret; ++ } ++ return ret; ++} ++ ++s32 ++wl_cfgp2p_init_discovery(struct wl_priv *wl) ++{ ++ ++ s32 index = 0; ++ s32 ret = BCME_OK; ++ ++ AP6210_DEBUG("enter\n"); ++ ++ if (wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) != 0) { ++ AP6210_ERR("do nothing, already initialized\n"); ++ return ret; ++ } ++ ++ ret = wl_cfgp2p_set_discovery(wl, 1); ++ if (ret < 0) { ++ AP6210_ERR("set discover error\n"); ++ return ret; ++ } ++ /* Enable P2P Discovery in the WL Driver */ ++ ret = wl_cfgp2p_get_disc_idx(wl, &index); ++ ++ if (ret < 0) { ++ return ret; ++ } ++ wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE) = ++ wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY); ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) = index; ++ ++ /* Set the initial discovery state to SCAN */ ++ ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); ++ ++ if (unlikely(ret != 0)) { ++ AP6210_ERR("unable to set WL_P2P_DISC_ST_SCAN\n"); ++ wl_cfgp2p_set_discovery(wl, 0); ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) = 0; ++ wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE) = NULL; ++ return 0; ++ } ++ return ret; ++} ++ ++/* Deinitialize P2P Discovery ++ * Parameters : ++ * @wl : wl_private data ++ * Returns 0 if succes ++ */ ++static s32 ++wl_cfgp2p_deinit_discovery(struct wl_priv *wl) ++{ ++ s32 ret = BCME_OK; ++ AP6210_DEBUG("enter\n"); ++ ++ if (wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) == 0) { ++ AP6210_ERR("do nothing, not initialized\n"); ++ return -1; ++ } ++ /* Set the discovery state to SCAN */ ++ ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); ++ /* Disable P2P discovery in the WL driver (deletes the discovery BSSCFG) */ ++ ret = wl_cfgp2p_set_discovery(wl, 0); ++ ++ /* Clear our saved WPS and P2P IEs for the discovery BSS. The driver ++ * deleted these IEs when wl_cfgp2p_set_discovery() deleted the discovery ++ * BSS. ++ */ ++ ++ /* Clear the saved bsscfg index of the discovery BSSCFG to indicate we ++ * have no discovery BSS. ++ */ ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) = WL_INVALID; ++ wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE) = NULL; ++ ++ return ret; ++ ++} ++/* Enable P2P Discovery ++ * Parameters: ++ * @wl : wl_private data ++ * @ie : probe request ie (WPS IE + P2P IE) ++ * @ie_len : probe request ie length ++ * Returns 0 if success. ++ */ ++s32 ++wl_cfgp2p_enable_discovery(struct wl_priv *wl, struct net_device *dev, ++ const u8 *ie, u32 ie_len) ++{ ++ s32 ret = BCME_OK; ++ s32 bssidx = (wl_to_prmry_ndev(wl) == dev) ? ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) : wl_cfgp2p_find_idx(wl, dev); ++ if (wl_get_p2p_status(wl, DISCOVERY_ON)) { ++ AP6210_DEBUG(" DISCOVERY is already initialized, we have nothing to do\n"); ++ goto set_ie; ++ } ++ ++ wl_set_p2p_status(wl, DISCOVERY_ON); ++ ++ AP6210_DEBUG("enter\n"); ++ ++ ret = wl_cfgp2p_init_discovery(wl); ++ if (unlikely(ret < 0)) { ++ AP6210_ERR(" init discovery error %d\n", ret); ++ goto exit; ++ } ++ /* Set wsec to any non-zero value in the discovery bsscfg to ensure our ++ * P2P probe responses have the privacy bit set in the 802.11 WPA IE. ++ * Some peer devices may not initiate WPS with us if this bit is not set. ++ */ ++ ret = wldev_iovar_setint_bsscfg(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), ++ "wsec", AES_ENABLED, wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); ++ if (unlikely(ret < 0)) { ++ AP6210_ERR(" wsec error %d\n", ret); ++ } ++set_ie: ++ if (ie_len) { ++ ret = wl_cfgp2p_set_management_ie(wl, dev, ++ bssidx, ++ VNDR_IE_PRBREQ_FLAG, ie, ie_len); ++ ++ if (unlikely(ret < 0)) { ++ AP6210_ERR("set probreq ie occurs error %d\n", ret); ++ goto exit; ++ } ++ } ++exit: ++ return ret; ++} ++ ++/* Disable P2P Discovery ++ * Parameters: ++ * @wl : wl_private_data ++ * Returns 0 if success. ++ */ ++s32 ++wl_cfgp2p_disable_discovery(struct wl_priv *wl) ++{ ++ s32 ret = BCME_OK; ++ AP6210_DEBUG(" enter\n"); ++ wl_clr_p2p_status(wl, DISCOVERY_ON); ++ ++ if (wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) == 0) { ++ AP6210_ERR(" do nothing, not initialized\n"); ++ goto exit; ++ } ++ ++ ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); ++ ++ if (unlikely(ret < 0)) { ++ ++ AP6210_ERR("unable to set WL_P2P_DISC_ST_SCAN\n"); ++ } ++ /* Do a scan abort to stop the driver's scan engine in case it is still ++ * waiting out an action frame tx dwell time. ++ */ ++ wl_clr_p2p_status(wl, DISCOVERY_ON); ++ ret = wl_cfgp2p_deinit_discovery(wl); ++ ++exit: ++ return ret; ++} ++ ++s32 ++wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, ++ u32 num_chans, u16 *channels, ++ s32 search_state, u16 action, u32 bssidx) ++{ ++ s32 ret = BCME_OK; ++ s32 memsize; ++ s32 eparams_size; ++ u32 i; ++ s8 *memblk; ++ wl_p2p_scan_t *p2p_params; ++ wl_escan_params_t *eparams; ++ wlc_ssid_t ssid; ++ /* Scan parameters */ ++#define P2PAPI_SCAN_NPROBES 1 ++#define P2PAPI_SCAN_DWELL_TIME_MS 80 ++#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40 ++#define P2PAPI_SCAN_HOME_TIME_MS 60 ++#define P2PAPI_SCAN_NPROBS_TIME_MS 30 ++#define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100 ++ ++ struct net_device *pri_dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY); ++ /* Allocate scan params which need space for 3 channels and 0 ssids */ ++ eparams_size = (WL_SCAN_PARAMS_FIXED_SIZE + ++ OFFSETOF(wl_escan_params_t, params)) + ++ num_chans * sizeof(eparams->params.channel_list[0]); ++ ++ memsize = sizeof(wl_p2p_scan_t) + eparams_size; ++ memblk = scanparambuf; ++ if (memsize > sizeof(scanparambuf)) { ++ AP6210_ERR(" scanpar buf too small (%u > %u)\n", ++ memsize, sizeof(scanparambuf)); ++ return -1; ++ } ++ memset(memblk, 0, memsize); ++ memset(wl->ioctl_buf, 0, WLC_IOCTL_MAXLEN); ++ if (search_state == WL_P2P_DISC_ST_SEARCH) { ++ /* ++ * If we in SEARCH STATE, we don't need to set SSID explictly ++ * because dongle use P2P WILDCARD internally by default ++ */ ++ wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SEARCH, 0, 0, bssidx); ++ ssid.SSID_len = htod32(0); ++ ++ } else if (search_state == WL_P2P_DISC_ST_SCAN) { ++ /* SCAN STATE 802.11 SCAN ++ * WFD Supplicant has p2p_find command with (type=progressive, type= full) ++ * So if P2P_find command with type=progressive, ++ * we have to set ssid to P2P WILDCARD because ++ * we just do broadcast scan unless setting SSID ++ */ ++ strncpy(ssid.SSID, WL_P2P_WILDCARD_SSID, sizeof(ssid.SSID) - 1); ++ ssid.SSID[sizeof(ssid.SSID) - 1] = 0; ++ ssid.SSID_len = htod32(WL_P2P_WILDCARD_SSID_LEN); ++ wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx); ++ } ++ else { ++ AP6210_ERR(" invalid search state %d\n", search_state); ++ return -1; ++ } ++ ++ ++ /* Fill in the P2P scan structure at the start of the iovar param block */ ++ p2p_params = (wl_p2p_scan_t*) memblk; ++ p2p_params->type = 'E'; ++ /* Fill in the Scan structure that follows the P2P scan structure */ ++ eparams = (wl_escan_params_t*) (p2p_params + 1); ++ eparams->params.bss_type = DOT11_BSSTYPE_ANY; ++ if (active) ++ eparams->params.scan_type = DOT11_SCANTYPE_ACTIVE; ++ else ++ eparams->params.scan_type = DOT11_SCANTYPE_PASSIVE; ++ ++ memcpy(&eparams->params.bssid, ðer_bcast, ETHER_ADDR_LEN); ++ if (ssid.SSID_len) ++ memcpy(&eparams->params.ssid, &ssid, sizeof(wlc_ssid_t)); ++ ++ eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS); ++ ++ /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by ++ * the supplicant ++ */ ++ if ((num_chans == SOCIAL_CHAN_CNT) || (num_chans == SOCIAL_CHAN_CNT + 1)) ++ eparams->params.active_time = htod32(P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS); ++ else if (num_chans == AF_PEER_SEARCH_CNT) ++ eparams->params.active_time = htod32(P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS); ++ else if (wl_get_drv_status_all(wl, CONNECTED)) ++ eparams->params.active_time = -1; ++ else ++ eparams->params.active_time = htod32(P2PAPI_SCAN_DWELL_TIME_MS); ++ eparams->params.nprobes = htod32((eparams->params.active_time / ++ P2PAPI_SCAN_NPROBS_TIME_MS)); ++ ++ /* Override scan params to find a peer for a connection */ ++ if (num_chans == 1) { ++ eparams->params.active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS); ++ eparams->params.nprobes = htod32(eparams->params.active_time / ++ WL_SCAN_JOIN_PROBE_INTERVAL_MS); ++ } ++ ++ if (eparams->params.nprobes <= 0) ++ eparams->params.nprobes = 1; ++ AP6210_DEBUG("nprobes # %d, active_time %d\n", ++ eparams->params.nprobes, eparams->params.active_time); ++ eparams->params.passive_time = htod32(-1); ++ eparams->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) | ++ (num_chans & WL_SCAN_PARAMS_COUNT_MASK)); ++ ++ for (i = 0; i < num_chans; i++) { ++ eparams->params.channel_list[i] = wl_ch_host_to_driver(channels[i]); ++ } ++ eparams->version = htod32(ESCAN_REQ_VERSION); ++ eparams->action = htod16(action); ++ eparams->sync_id = htod16(0x1234); ++ AP6210_DEBUG("SCAN CHANNELS : "); ++ ++ for (i = 0; i < num_chans; i++) { ++ if (i == 0) AP6210_DEBUG("%d", channels[i]); ++ else AP6210_DEBUG(",%d", channels[i]); ++ } ++ ++ AP6210_DEBUG("\n"); ++ ++ ret = wldev_iovar_setbuf_bsscfg(pri_dev, "p2p_scan", ++ memblk, memsize, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); ++ if (ret == BCME_OK) ++ wl_set_p2p_status(wl, SCANNING); ++ return ret; ++} ++ ++/* search function to reach at common channel to send action frame ++ * Parameters: ++ * @wl : wl_private data ++ * @ndev : net device for bssidx ++ * @bssidx : bssidx for BSS ++ * Returns 0 if success. ++ */ ++s32 ++wl_cfgp2p_act_frm_search(struct wl_priv *wl, struct net_device *ndev, ++ s32 bssidx, s32 channel) ++{ ++ s32 ret = 0; ++ u32 chan_cnt = 0; ++ u16 *default_chan_list = NULL; ++ if (!p2p_is_on(wl) || ndev == NULL || bssidx == WL_INVALID) ++ return -BCME_ERROR; ++ AP6210_DEBUG(" Enter\n"); ++ if (bssidx == P2PAPI_BSSCFG_PRIMARY) ++ bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); ++ if (channel) ++ chan_cnt = AF_PEER_SEARCH_CNT; ++ else ++ chan_cnt = SOCIAL_CHAN_CNT; ++ default_chan_list = kzalloc(chan_cnt * sizeof(*default_chan_list), GFP_KERNEL); ++ if (default_chan_list == NULL) { ++ AP6210_ERR("channel list allocation failed \n"); ++ ret = -ENOMEM; ++ goto exit; ++ } ++ if (channel) { ++ u32 i; ++ /* insert same channel to the chan_list */ ++ for (i = 0; i < chan_cnt; i++) { ++ default_chan_list[i] = channel; ++ } ++ } else { ++ default_chan_list[0] = SOCIAL_CHAN_1; ++ default_chan_list[1] = SOCIAL_CHAN_2; ++ default_chan_list[2] = SOCIAL_CHAN_3; ++ } ++ ret = wl_cfgp2p_escan(wl, ndev, true, chan_cnt, ++ default_chan_list, WL_P2P_DISC_ST_SEARCH, ++ WL_SCAN_ACTION_START, bssidx); ++ kfree(default_chan_list); ++exit: ++ return ret; ++} ++ ++/* Check whether pointed-to IE looks like WPA. */ ++#define wl_cfgp2p_is_wpa_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \ ++ (const uint8 *)WPS_OUI, WPS_OUI_LEN, WPA_OUI_TYPE) ++/* Check whether pointed-to IE looks like WPS. */ ++#define wl_cfgp2p_is_wps_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \ ++ (const uint8 *)WPS_OUI, WPS_OUI_LEN, WPS_OUI_TYPE) ++/* Check whether the given IE looks like WFA P2P IE. */ ++#define wl_cfgp2p_is_p2p_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \ ++ (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P) ++/* Check whether the given IE looks like WFA WFDisplay IE. */ ++#define WFA_OUI_TYPE_WFD 0x0a /* WiFi Display OUI TYPE */ ++#define wl_cfgp2p_is_wfd_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \ ++ (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD) ++ ++static s32 ++wl_cfgp2p_parse_vndr_ies(u8 *parse, u32 len, ++ struct parsed_vndr_ies *vndr_ies) ++{ ++ s32 err = BCME_OK; ++ vndr_ie_t *vndrie; ++ bcm_tlv_t *ie; ++ struct parsed_vndr_ie_info *parsed_info; ++ u32 count = 0; ++ s32 remained_len; ++ ++ remained_len = (s32)len; ++ memset(vndr_ies, 0, sizeof(*vndr_ies)); ++ ++ AP6210_DEBUG("---> len %d\n", len); ++ ie = (bcm_tlv_t *) parse; ++ if (!bcm_valid_tlv(ie, remained_len)) ++ ie = NULL; ++ while (ie) { ++ if (count >= MAX_VNDR_IE_NUMBER) ++ break; ++ if (ie->id == DOT11_MNG_VS_ID) { ++ vndrie = (vndr_ie_t *) ie; ++ /* len should be bigger than OUI length + one data length at least */ ++ if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) { ++ AP6210_ERR("%s: invalid vndr ie. length is too small %d\n", ++ __FUNCTION__, vndrie->len); ++ goto end; ++ } ++ /* if wpa or wme ie, do not add ie */ ++ if (!bcmp(vndrie->oui, (u8*)WPA_OUI, WPA_OUI_LEN) && ++ ((vndrie->data[0] == WPA_OUI_TYPE) || ++ (vndrie->data[0] == WME_OUI_TYPE))) { ++ AP6210_DEBUG("Found WPA/WME oui. Do not add it\n"); ++ goto end; ++ } ++ ++ parsed_info = &vndr_ies->ie_info[count++]; ++ ++ /* save vndr ie information */ ++ parsed_info->ie_ptr = (char *)vndrie; ++ parsed_info->ie_len = (vndrie->len + TLV_HDR_LEN); ++ memcpy(&parsed_info->vndrie, vndrie, sizeof(vndr_ie_t)); ++ ++ vndr_ies->count = count; ++ ++ AP6210_DEBUG("\t ** OUI %02x %02x %02x, type 0x%02x \n", ++ parsed_info->vndrie.oui[0], parsed_info->vndrie.oui[1], ++ parsed_info->vndrie.oui[2], parsed_info->vndrie.data[0]); ++ } ++end: ++ ie = bcm_next_tlv(ie, &remained_len); ++ } ++ return err; ++} ++ ++ ++/* Delete and Set a management vndr ie to firmware ++ * Parameters: ++ * @wl : wl_private data ++ * @ndev : net device for bssidx ++ * @bssidx : bssidx for BSS ++ * @pktflag : packet flag for IE (VNDR_IE_PRBREQ_FLAG,VNDR_IE_PRBRSP_FLAG, VNDR_IE_ASSOCRSP_FLAG, ++ * VNDR_IE_ASSOCREQ_FLAG) ++ * @ie : VNDR IE (such as P2P IE , WPS IE) ++ * @ie_len : VNDR IE Length ++ * Returns 0 if success. ++ */ ++ ++s32 ++wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, ++ s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len) ++{ ++ s32 ret = BCME_OK; ++ u8 *curr_ie_buf = NULL; ++ u8 *mgmt_ie_buf = NULL; ++ u32 mgmt_ie_buf_len = 0; ++ u32 *mgmt_ie_len = 0; ++ u32 del_add_ie_buf_len = 0; ++ u32 total_ie_buf_len = 0; ++ u32 parsed_ie_buf_len = 0; ++ struct parsed_vndr_ies old_vndr_ies; ++ struct parsed_vndr_ies new_vndr_ies; ++ s32 i; ++ u8 *ptr; ++ s32 remained_buf_len; ++ ++#define IE_TYPE(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie) ++#define IE_TYPE_LEN(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie_len) ++ memset(g_mgmt_ie_buf, 0, sizeof(g_mgmt_ie_buf)); ++ curr_ie_buf = g_mgmt_ie_buf; ++ AP6210_DEBUG(" bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag); ++ if (wl->p2p != NULL) { ++ switch (pktflag) { ++ case VNDR_IE_PRBREQ_FLAG : ++ mgmt_ie_buf = IE_TYPE(probe_req, bssidx); ++ mgmt_ie_len = &IE_TYPE_LEN(probe_req, bssidx); ++ mgmt_ie_buf_len = sizeof(IE_TYPE(probe_req, bssidx)); ++ break; ++ case VNDR_IE_PRBRSP_FLAG : ++ mgmt_ie_buf = IE_TYPE(probe_res, bssidx); ++ mgmt_ie_len = &IE_TYPE_LEN(probe_res, bssidx); ++ mgmt_ie_buf_len = sizeof(IE_TYPE(probe_res, bssidx)); ++ break; ++ case VNDR_IE_ASSOCREQ_FLAG : ++ mgmt_ie_buf = IE_TYPE(assoc_req, bssidx); ++ mgmt_ie_len = &IE_TYPE_LEN(assoc_req, bssidx); ++ mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_req, bssidx)); ++ break; ++ case VNDR_IE_ASSOCRSP_FLAG : ++ mgmt_ie_buf = IE_TYPE(assoc_res, bssidx); ++ mgmt_ie_len = &IE_TYPE_LEN(assoc_res, bssidx); ++ mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_res, bssidx)); ++ break; ++ case VNDR_IE_BEACON_FLAG : ++ mgmt_ie_buf = IE_TYPE(beacon, bssidx); ++ mgmt_ie_len = &IE_TYPE_LEN(beacon, bssidx); ++ mgmt_ie_buf_len = sizeof(IE_TYPE(beacon, bssidx)); ++ break; ++ default: ++ mgmt_ie_buf = NULL; ++ mgmt_ie_len = NULL; ++ AP6210_ERR("not suitable type\n"); ++ return -1; ++ } ++ } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { ++ switch (pktflag) { ++ case VNDR_IE_PRBRSP_FLAG : ++ mgmt_ie_buf = wl->ap_info->probe_res_ie; ++ mgmt_ie_len = &wl->ap_info->probe_res_ie_len; ++ mgmt_ie_buf_len = sizeof(wl->ap_info->probe_res_ie); ++ break; ++ case VNDR_IE_BEACON_FLAG : ++ mgmt_ie_buf = wl->ap_info->beacon_ie; ++ mgmt_ie_len = &wl->ap_info->beacon_ie_len; ++ mgmt_ie_buf_len = sizeof(wl->ap_info->beacon_ie); ++ break; ++ default: ++ mgmt_ie_buf = NULL; ++ mgmt_ie_len = NULL; ++ AP6210_ERR("not suitable type\n"); ++ return -1; ++ } ++ bssidx = 0; ++ } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_BSS) { ++ switch (pktflag) { ++ case VNDR_IE_PRBREQ_FLAG : ++ mgmt_ie_buf = wl->sta_info->probe_req_ie; ++ mgmt_ie_len = &wl->sta_info->probe_req_ie_len; ++ mgmt_ie_buf_len = sizeof(wl->sta_info->probe_req_ie); ++ break; ++ case VNDR_IE_ASSOCREQ_FLAG : ++ mgmt_ie_buf = wl->sta_info->assoc_req_ie; ++ mgmt_ie_len = &wl->sta_info->assoc_req_ie_len; ++ mgmt_ie_buf_len = sizeof(wl->sta_info->assoc_req_ie); ++ break; ++ default: ++ mgmt_ie_buf = NULL; ++ mgmt_ie_len = NULL; ++ AP6210_ERR("not suitable type\n"); ++ return -1; ++ } ++ bssidx = 0; ++ } else { ++ AP6210_ERR("not suitable type\n"); ++ return -1; ++ } ++ ++ if (vndr_ie_len > mgmt_ie_buf_len) { ++ AP6210_ERR("extra IE size too big\n"); ++ ret = -ENOMEM; ++ } else { ++ /* parse and save new vndr_ie in curr_ie_buff before comparing it */ ++ if (vndr_ie && vndr_ie_len && curr_ie_buf) { ++ ptr = curr_ie_buf; ++ ++ wl_cfgp2p_parse_vndr_ies((u8*)vndr_ie, ++ vndr_ie_len, &new_vndr_ies); ++ ++ for (i = 0; i < new_vndr_ies.count; i++) { ++ struct parsed_vndr_ie_info *vndrie_info = ++ &new_vndr_ies.ie_info[i]; ++ ++ memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr, ++ vndrie_info->ie_len); ++ parsed_ie_buf_len += vndrie_info->ie_len; ++ } ++ } ++ ++ if (mgmt_ie_buf != NULL) { ++ if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) && ++ (memcmp(mgmt_ie_buf, curr_ie_buf, parsed_ie_buf_len) == 0)) { ++ AP6210_DEBUG("Previous mgmt IE is equals to current IE"); ++ goto exit; ++ } ++ ++ /* parse old vndr_ie */ ++ wl_cfgp2p_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len, ++ &old_vndr_ies); ++ ++ /* make a command to delete old ie */ ++ for (i = 0; i < old_vndr_ies.count; i++) { ++ struct parsed_vndr_ie_info *vndrie_info = ++ &old_vndr_ies.ie_info[i]; ++ ++ AP6210_DEBUG("DELETED ID : %d, Len: %d , OUI:%02x:%02x:%02x\n", ++ vndrie_info->vndrie.id, vndrie_info->vndrie.len, ++ vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1], ++ vndrie_info->vndrie.oui[2]); ++ ++ del_add_ie_buf_len = wl_cfgp2p_vndr_ie(wl, curr_ie_buf, ++ bssidx, pktflag, vndrie_info->vndrie.oui, ++ vndrie_info->vndrie.id, ++ vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN, ++ vndrie_info->ie_len - VNDR_IE_FIXED_LEN, ++ "del"); ++ ++ curr_ie_buf += del_add_ie_buf_len; ++ total_ie_buf_len += del_add_ie_buf_len; ++ } ++ } ++ ++ *mgmt_ie_len = 0; ++ /* Add if there is any extra IE */ ++ if (mgmt_ie_buf && parsed_ie_buf_len) { ++ ptr = mgmt_ie_buf; ++ ++ remained_buf_len = mgmt_ie_buf_len; ++ ++ /* make a command to add new ie */ ++ for (i = 0; i < new_vndr_ies.count; i++) { ++ struct parsed_vndr_ie_info *vndrie_info = ++ &new_vndr_ies.ie_info[i]; ++ ++ AP6210_DEBUG("ADDED ID : %d, Len: %d(%d), OUI:%02x:%02x:%02x\n", ++ vndrie_info->vndrie.id, vndrie_info->vndrie.len, ++ vndrie_info->ie_len - 2, ++ vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1], ++ vndrie_info->vndrie.oui[2]); ++ ++ del_add_ie_buf_len = wl_cfgp2p_vndr_ie(wl, curr_ie_buf, ++ bssidx, pktflag, vndrie_info->vndrie.oui, ++ vndrie_info->vndrie.id, ++ vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN, ++ vndrie_info->ie_len - VNDR_IE_FIXED_LEN, ++ "add"); ++ ++ /* verify remained buf size before copy data */ ++ if (remained_buf_len >= vndrie_info->ie_len) { ++ remained_buf_len -= vndrie_info->ie_len; ++ } else { ++ AP6210_ERR("no space in mgmt_ie_buf: pktflag = %d, " ++ "found vndr ies # = %d(cur %d), remained len %d, " ++ "cur mgmt_ie_len %d, new ie len = %d\n", ++ pktflag, new_vndr_ies.count, i, remained_buf_len, ++ *mgmt_ie_len, vndrie_info->ie_len); ++ break; ++ } ++ ++ /* save the parsed IE in wl struct */ ++ memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr, ++ vndrie_info->ie_len); ++ *mgmt_ie_len += vndrie_info->ie_len; ++ ++ curr_ie_buf += del_add_ie_buf_len; ++ total_ie_buf_len += del_add_ie_buf_len; ++ } ++ } ++ if (total_ie_buf_len) { ++ ret = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", g_mgmt_ie_buf, ++ total_ie_buf_len, wl->ioctl_buf, WLC_IOCTL_MAXLEN, ++ bssidx, &wl->ioctl_buf_sync); ++ if (ret) ++ AP6210_ERR("vndr ie set error : %d\n", ret); ++ } ++ } ++#undef IE_TYPE ++#undef IE_TYPE_LEN ++exit: ++ return ret; ++} ++ ++/* Clear the manament IE buffer of BSSCFG ++ * Parameters: ++ * @wl : wl_private data ++ * @bssidx : bssidx for BSS ++ * ++ * Returns 0 if success. ++ */ ++s32 ++wl_cfgp2p_clear_management_ie(struct wl_priv *wl, s32 bssidx) ++{ ++ s32 vndrie_flag[] = {VNDR_IE_BEACON_FLAG, VNDR_IE_PRBRSP_FLAG, VNDR_IE_ASSOCRSP_FLAG, ++ VNDR_IE_PRBREQ_FLAG, VNDR_IE_ASSOCREQ_FLAG}; ++ s32 index = -1; ++ struct net_device *ndev = wl_cfgp2p_find_ndev(wl, bssidx); ++#define INIT_IE(IE_TYPE, BSS_TYPE) \ ++ do { \ ++ memset(wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie, 0, \ ++ sizeof(wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie)); \ ++ wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie_len = 0; \ ++ } while (0); ++ ++ if (bssidx < 0 || ndev == NULL) { ++ AP6210_ERR("invalid %s\n", (bssidx < 0) ? "bssidx" : "ndev"); ++ return BCME_BADARG; ++ } ++ for (index = 0; index < ARRAYSIZE(vndrie_flag); index++) { ++ /* clean up vndr ies in dongle */ ++ wl_cfgp2p_set_management_ie(wl, ndev, bssidx, vndrie_flag[index], NULL, 0); ++ } ++ INIT_IE(probe_req, bssidx); ++ INIT_IE(probe_res, bssidx); ++ INIT_IE(assoc_req, bssidx); ++ INIT_IE(assoc_res, bssidx); ++ INIT_IE(beacon, bssidx); ++ return BCME_OK; ++} ++ ++ ++/* Is any of the tlvs the expected entry? If ++ * not update the tlvs buffer pointer/length. ++ */ ++static bool ++wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type) ++{ ++ /* If the contents match the OUI and the type */ ++ if (ie[TLV_LEN_OFF] >= oui_len + 1 && ++ !bcmp(&ie[TLV_BODY_OFF], oui, oui_len) && ++ type == ie[TLV_BODY_OFF + oui_len]) { ++ return TRUE; ++ } ++ ++ if (tlvs == NULL) ++ return FALSE; ++ /* point to the next ie */ ++ ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN; ++ /* calculate the length of the rest of the buffer */ ++ *tlvs_len -= (int)(ie - *tlvs); ++ /* update the pointer to the start of the buffer */ ++ *tlvs = ie; ++ ++ return FALSE; ++} ++ ++wpa_ie_fixed_t * ++wl_cfgp2p_find_wpaie(u8 *parse, u32 len) ++{ ++ bcm_tlv_t *ie; ++ ++ while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_VS_ID))) { ++ if (wl_cfgp2p_is_wpa_ie((u8*)ie, &parse, &len)) { ++ return (wpa_ie_fixed_t *)ie; ++ } ++ } ++ return NULL; ++} ++ ++wpa_ie_fixed_t * ++wl_cfgp2p_find_wpsie(u8 *parse, u32 len) ++{ ++ bcm_tlv_t *ie; ++ ++ while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_VS_ID))) { ++ if (wl_cfgp2p_is_wps_ie((u8*)ie, &parse, &len)) { ++ return (wpa_ie_fixed_t *)ie; ++ } ++ } ++ return NULL; ++} ++ ++wifi_p2p_ie_t * ++wl_cfgp2p_find_p2pie(u8 *parse, u32 len) ++{ ++ bcm_tlv_t *ie; ++ ++ while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) { ++ if (wl_cfgp2p_is_p2p_ie((uint8*)ie, &parse, &len)) { ++ return (wifi_p2p_ie_t *)ie; ++ } ++ } ++ return NULL; ++} ++ ++wifi_wfd_ie_t * ++wl_cfgp2p_find_wfdie(u8 *parse, u32 len) ++{ ++ bcm_tlv_t *ie; ++ ++ while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) { ++ if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) { ++ return (wifi_wfd_ie_t *)ie; ++ } ++ } ++ return NULL; ++} ++static u32 ++wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 bssidx, s32 pktflag, ++ s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd) ++{ ++ vndr_ie_setbuf_t hdr; /* aligned temporary vndr_ie buffer header */ ++ s32 iecount; ++ u32 data_offset; ++ ++ /* Validate the pktflag parameter */ ++ if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG | ++ VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG | ++ VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG))) { ++ AP6210_ERR("p2pwl_vndr_ie: Invalid packet flag 0x%x\n", pktflag); ++ return -1; ++ } ++ ++ /* Copy the vndr_ie SET command ("add"/"del") to the buffer */ ++ strncpy(hdr.cmd, add_del_cmd, VNDR_IE_CMD_LEN - 1); ++ hdr.cmd[VNDR_IE_CMD_LEN - 1] = '\0'; ++ ++ /* Set the IE count - the buffer contains only 1 IE */ ++ iecount = htod32(1); ++ memcpy((void *)&hdr.vndr_ie_buffer.iecount, &iecount, sizeof(s32)); ++ ++ /* Copy packet flags that indicate which packets will contain this IE */ ++ pktflag = htod32(pktflag); ++ memcpy((void *)&hdr.vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag, ++ sizeof(u32)); ++ ++ /* Add the IE ID to the buffer */ ++ hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = ie_id; ++ ++ /* Add the IE length to the buffer */ ++ hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = ++ (uint8) VNDR_IE_MIN_LEN + datalen; ++ ++ /* Add the IE OUI to the buffer */ ++ hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[0] = oui[0]; ++ hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[1] = oui[1]; ++ hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[2] = oui[2]; ++ ++ /* Copy the aligned temporary vndr_ie buffer header to the IE buffer */ ++ memcpy(iebuf, &hdr, sizeof(hdr) - 1); ++ ++ /* Copy the IE data to the IE buffer */ ++ data_offset = ++ (u8*)&hdr.vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data[0] - ++ (u8*)&hdr; ++ memcpy(iebuf + data_offset, data, datalen); ++ return data_offset + datalen; ++ ++} ++ ++/* ++ * Search the bssidx based on dev argument ++ * Parameters: ++ * @wl : wl_private data ++ * @ndev : net device to search bssidx ++ * Returns bssidx for ndev ++ */ ++s32 ++wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev) ++{ ++ u32 i; ++ s32 index = -1; ++ ++ if (ndev == NULL) { ++ AP6210_ERR(" ndev is NULL\n"); ++ goto exit; ++ } ++ if (!wl->p2p_supported) { ++ return P2PAPI_BSSCFG_PRIMARY; ++ } ++ for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) { ++ if (ndev == wl_to_p2p_bss_ndev(wl, i)) { ++ index = wl_to_p2p_bss_bssidx(wl, i); ++ break; ++ } ++ } ++ if (index == -1) ++ return P2PAPI_BSSCFG_PRIMARY; ++exit: ++ return index; ++} ++ ++struct net_device * ++wl_cfgp2p_find_ndev(struct wl_priv *wl, s32 bssidx) ++{ ++ u32 i; ++ struct net_device *ndev = NULL; ++ if (bssidx < 0) { ++ AP6210_ERR(" bsscfg idx is invalid\n"); ++ goto exit; ++ } ++ ++ for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) { ++ if (bssidx == wl_to_p2p_bss_bssidx(wl, i)) { ++ ndev = wl_to_p2p_bss_ndev(wl, i); ++ break; ++ } ++ } ++ ++exit: ++ return ndev; ++} ++ ++/* ++ * Callback function for WLC_E_P2P_DISC_LISTEN_COMPLETE ++ */ ++s32 ++wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data) ++{ ++ s32 ret = BCME_OK; ++ struct net_device *netdev; ++ if (!wl || !wl->p2p) ++ return BCME_ERROR; ++ if (wl->p2p_net == ndev) { ++ netdev = wl_to_prmry_ndev(wl); ++ } else { ++ netdev = ndev; ++ } ++ AP6210_DEBUG(" Enter\n"); ++ if (wl_get_p2p_status(wl, LISTEN_EXPIRED) == 0) { ++ wl_set_p2p_status(wl, LISTEN_EXPIRED); ++ if (timer_pending(&wl->p2p->listen_timer)) { ++ del_timer_sync(&wl->p2p->listen_timer); ++ } ++ ++ if (wl->afx_hdl->is_listen == TRUE && ++ wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) { ++ AP6210_DEBUG("Listen DONE for action frame\n"); ++ complete(&wl->act_frm_scan); ++ } ++#ifdef WL_CFG80211_SYNC_GON ++ else if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) { ++ wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM_LISTEN, netdev); ++ AP6210_DEBUG("Listen DONE and wake up wait_next_af !!(%d)\n", ++ jiffies_to_msecs(jiffies - wl->af_tx_sent_jiffies)); ++ ++ if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) ++ wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, netdev); ++ ++ complete(&wl->wait_next_af); ++ } ++#endif /* WL_CFG80211_SYNC_GON */ ++ ++#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST ++ if (wl_get_drv_status_all(wl, REMAINING_ON_CHANNEL)) { ++#else ++ if (wl_get_drv_status_all(wl, REMAINING_ON_CHANNEL) || ++ wl_get_drv_status_all(wl, FAKE_REMAINING_ON_CHANNEL)) { ++#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ ++ AP6210_DEBUG("Listen DONE for ramain on channel expired\n"); ++ wl_clr_drv_status(wl, REMAINING_ON_CHANNEL, netdev); ++#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST ++ wl_clr_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, netdev); ++#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ ++ if (ndev && (ndev->ieee80211_ptr != NULL)) { ++ cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id, ++ &wl->remain_on_chan, wl->remain_on_chan_type, GFP_KERNEL); ++ } ++ } ++ if (wl_add_remove_eventmsg(wl_to_prmry_ndev(wl), ++ WLC_E_P2P_PROBREQ_MSG, false) != BCME_OK) { ++ AP6210_ERR(" failed to unset WLC_E_P2P_PROPREQ_MSG\n"); ++ } ++ } else ++ wl_clr_p2p_status(wl, LISTEN_EXPIRED); ++ ++ return ret; ++ ++} ++ ++/* ++ * Timer expire callback function for LISTEN ++ * We can't report cfg80211_remain_on_channel_expired from Timer ISR context, ++ * so lets do it from thread context. ++ */ ++void ++wl_cfgp2p_listen_expired(unsigned long data) ++{ ++ wl_event_msg_t msg; ++ struct wl_priv *wl = (struct wl_priv *) data; ++ AP6210_DEBUG(" Enter\n"); ++ bzero(&msg, sizeof(wl_event_msg_t)); ++ msg.event_type = hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE); ++ wl_cfg80211_event(wl->p2p_net ? wl->p2p_net : ++ wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), &msg, NULL); ++} ++/* ++ * Routine for cancelling the P2P LISTEN ++ */ ++static s32 ++wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev, ++ bool notify) ++{ ++ AP6210_DEBUG("Enter \n"); ++ /* Irrespective of whether timer is running or not, reset ++ * the LISTEN state. ++ */ ++ if (timer_pending(&wl->p2p->listen_timer)) { ++ del_timer_sync(&wl->p2p->listen_timer); ++ if (notify) ++ if (ndev && ndev->ieee80211_ptr) { ++ cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id, ++ &wl->remain_on_chan, wl->remain_on_chan_type, ++ GFP_KERNEL); ++ } ++ } ++ return 0; ++} ++/* ++ * Do a P2P Listen on the given channel for the given duration. ++ * A listen consists of sitting idle and responding to P2P probe requests ++ * with a P2P probe response. ++ * ++ * This fn assumes dongle p2p device discovery is already enabled. ++ * Parameters : ++ * @wl : wl_private data ++ * @channel : channel to listen ++ * @duration_ms : the time (milli seconds) to wait ++ */ ++s32 ++wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms) ++{ ++#define EXTRA_DELAY_TIME 100 ++ s32 ret = BCME_OK; ++ struct timer_list *_timer; ++ s32 extra_delay; ++ struct net_device *netdev = wl_to_prmry_ndev(wl); ++ ++ AP6210_DEBUG(" Enter Listen Channel : %d, Duration : %d\n", channel, duration_ms); ++ if (unlikely(wl_get_p2p_status(wl, DISCOVERY_ON) == 0)) { ++ ++ AP6210_ERR(" Discovery is not set, so we have noting to do\n"); ++ ++ ret = BCME_NOTREADY; ++ goto exit; ++ } ++ if (timer_pending(&wl->p2p->listen_timer)) { ++ AP6210_DEBUG("previous LISTEN is not completed yet\n"); ++ goto exit; ++ ++ } ++#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST ++ else ++ wl_clr_p2p_status(wl, LISTEN_EXPIRED); ++#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ ++ if (wl_add_remove_eventmsg(netdev, WLC_E_P2P_PROBREQ_MSG, true) != BCME_OK) { ++ AP6210_ERR(" failed to set WLC_E_P2P_PROPREQ_MSG\n"); ++ } ++ ++ ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_LISTEN, channel, (u16) duration_ms, ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); ++ _timer = &wl->p2p->listen_timer; ++ ++ /* We will wait to receive WLC_E_P2P_DISC_LISTEN_COMPLETE from dongle , ++ * otherwise we will wait up to duration_ms + 100ms + duration / 10 ++ */ ++ if (ret == BCME_OK) { ++ extra_delay = EXTRA_DELAY_TIME + (duration_ms / 10); ++ } else { ++ /* if failed to set listen, it doesn't need to wait whole duration. */ ++ duration_ms = 100 + duration_ms / 20; ++ extra_delay = 0; ++ } ++ ++ INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration_ms, extra_delay); ++#ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST ++ wl_clr_p2p_status(wl, LISTEN_EXPIRED); ++#endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ ++ ++#undef EXTRA_DELAY_TIME ++exit: ++ return ret; ++} ++ ++ ++s32 ++wl_cfgp2p_discover_enable_search(struct wl_priv *wl, u8 enable) ++{ ++ s32 ret = BCME_OK; ++ AP6210_DEBUG(" Enter\n"); ++ if (!wl_get_p2p_status(wl, DISCOVERY_ON)) { ++ ++ AP6210_DEBUG(" do nothing, discovery is off\n"); ++ return ret; ++ } ++ if (wl_get_p2p_status(wl, SEARCH_ENABLED) == enable) { ++ AP6210_DEBUG("already : %d\n", enable); ++ return ret; ++ } ++ ++ wl_chg_p2p_status(wl, SEARCH_ENABLED); ++ /* When disabling Search, reset the WL driver's p2p discovery state to ++ * WL_P2P_DISC_ST_SCAN. ++ */ ++ if (!enable) { ++ wl_clr_p2p_status(wl, SCANNING); ++ ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); ++ } ++ ++ return ret; ++} ++ ++/* ++ * Callback function for WLC_E_ACTION_FRAME_COMPLETE, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE ++ */ ++s32 ++wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data) ++{ ++ s32 ret = BCME_OK; ++ u32 event_type = ntoh32(e->event_type); ++ u32 status = ntoh32(e->status); ++ AP6210_DEBUG(" Enter\n"); ++ if (event_type == WLC_E_ACTION_FRAME_COMPLETE) { ++ ++ AP6210_DEBUG(" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status); ++ if (status == WLC_E_STATUS_SUCCESS) { ++ wl_set_p2p_status(wl, ACTION_TX_COMPLETED); ++ AP6210_DEBUG("WLC_E_ACTION_FRAME_COMPLETE : ACK\n"); ++ } ++ else { ++ wl_set_p2p_status(wl, ACTION_TX_NOACK); ++ AP6210_DEBUG("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n"); ++ wl_stop_wait_next_action_frame(wl, ndev); ++ } ++ } else { ++ AP6210_DEBUG(" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received," ++ "status : %d\n", status); ++ ++ if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) ++ complete(&wl->send_af_done); ++ } ++ return ret; ++} ++/* Send an action frame immediately without doing channel synchronization. ++ * ++ * This function does not wait for a completion event before returning. ++ * The WLC_E_ACTION_FRAME_COMPLETE event will be received when the action ++ * frame is transmitted. ++ * The WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE event will be received when an ++ * 802.11 ack has been received for the sent action frame. ++ */ ++s32 ++wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, ++ wl_af_params_t *af_params, s32 bssidx) ++{ ++ s32 ret = BCME_OK; ++ s32 timeout = 0; ++ wl_eventmsg_buf_t buf; ++ ++ ++ AP6210_DEBUG("\n"); ++ AP6210_DEBUG("channel : %u , dwell time : %u\n", ++ af_params->channel, af_params->dwell_time); ++ ++ wl_clr_p2p_status(wl, ACTION_TX_COMPLETED); ++ wl_clr_p2p_status(wl, ACTION_TX_NOACK); ++ ++ bzero(&buf, sizeof(wl_eventmsg_buf_t)); ++ wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, true); ++ wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_COMPLETE, true); ++ if ((ret = wl_cfg80211_apply_eventbuffer(wl_to_prmry_ndev(wl), wl, &buf)) < 0) ++ return ret; ++ ++#define MAX_WAIT_TIME 2000 ++ if (bssidx == P2PAPI_BSSCFG_PRIMARY) ++ bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); ++ ++ wl->af_sent_channel = af_params->channel; ++#ifdef WL_CFG80211_SYNC_GON ++ wl->af_tx_sent_jiffies = jiffies; ++#endif /* WL_CFG80211_SYNC_GON */ ++ ++ ret = wldev_iovar_setbuf_bsscfg(dev, "actframe", af_params, sizeof(*af_params), ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); ++ ++ if (ret < 0) { ++ AP6210_ERR(" sending action frame is failed\n"); ++ goto exit; ++ } ++ ++ timeout = wait_for_completion_timeout(&wl->send_af_done, msecs_to_jiffies(MAX_WAIT_TIME)); ++ ++ if (timeout > 0 && wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) { ++ AP6210_DEBUG("tx action frame operation is completed\n"); ++ ret = BCME_OK; ++ } else { ++ ret = BCME_ERROR; ++ AP6210_DEBUG("tx action frame operation is failed\n"); ++ } ++ /* clear status bit for action tx */ ++ wl_clr_p2p_status(wl, ACTION_TX_COMPLETED); ++ wl_clr_p2p_status(wl, ACTION_TX_NOACK); ++ ++exit: ++ AP6210_DEBUG(" via act frame iovar : status = %d\n", ret); ++ ++ bzero(&buf, sizeof(wl_eventmsg_buf_t)); ++ wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, false); ++ wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_COMPLETE, false); ++ if ((ret = wl_cfg80211_apply_eventbuffer(wl_to_prmry_ndev(wl), wl, &buf)) < 0) ++ AP6210_ERR("TX frame events revert back failed \n"); ++ ++#undef MAX_WAIT_TIME ++ return ret; ++} ++ ++/* Generate our P2P Device Address and P2P Interface Address from our primary ++ * MAC address. ++ */ ++void ++wl_cfgp2p_generate_bss_mac(struct ether_addr *primary_addr, ++ struct ether_addr *out_dev_addr, struct ether_addr *out_int_addr) ++{ ++ memset(out_dev_addr, 0, sizeof(*out_dev_addr)); ++ memset(out_int_addr, 0, sizeof(*out_int_addr)); ++ ++ /* Generate the P2P Device Address. This consists of the device's ++ * primary MAC address with the locally administered bit set. ++ */ ++ memcpy(out_dev_addr, primary_addr, sizeof(*out_dev_addr)); ++ out_dev_addr->octet[0] |= 0x02; ++ ++ /* Generate the P2P Interface Address. If the discovery and connection ++ * BSSCFGs need to simultaneously co-exist, then this address must be ++ * different from the P2P Device Address. ++ */ ++ memcpy(out_int_addr, out_dev_addr, sizeof(*out_int_addr)); ++ out_int_addr->octet[4] ^= 0x80; ++ ++} ++ ++/* P2P IF Address change to Virtual Interface MAC Address */ ++void ++wl_cfg80211_change_ifaddr(u8* buf, struct ether_addr *p2p_int_addr, u8 element_id) ++{ ++ wifi_p2p_ie_t *ie = (wifi_p2p_ie_t*) buf; ++ u16 len = ie->len; ++ u8 *subel; ++ u8 subelt_id; ++ u16 subelt_len; ++ AP6210_DEBUG(" Enter\n"); ++ ++ /* Point subel to the P2P IE's subelt field. ++ * Subtract the preceding fields (id, len, OUI, oui_type) from the length. ++ */ ++ subel = ie->subelts; ++ len -= 4; /* exclude OUI + OUI_TYPE */ ++ ++ while (len >= 3) { ++ /* attribute id */ ++ subelt_id = *subel; ++ subel += 1; ++ len -= 1; ++ ++ /* 2-byte little endian */ ++ subelt_len = *subel++; ++ subelt_len |= *subel++ << 8; ++ ++ len -= 2; ++ len -= subelt_len; /* for the remaining subelt fields */ ++ ++ if (subelt_id == element_id) { ++ if (subelt_id == P2P_SEID_INTINTADDR) { ++ memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN); ++ AP6210_DEBUG("Intended P2P Interface Address ATTR FOUND\n"); ++ } else if (subelt_id == P2P_SEID_DEV_ID) { ++ memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN); ++ AP6210_DEBUG("Device ID ATTR FOUND\n"); ++ } else if (subelt_id == P2P_SEID_DEV_INFO) { ++ memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN); ++ AP6210_DEBUG("Device INFO ATTR FOUND\n"); ++ } else if (subelt_id == P2P_SEID_GROUP_ID) { ++ memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN); ++ AP6210_DEBUG("GROUP ID ATTR FOUND\n"); ++ } return; ++ } else { ++ AP6210_DEBUG("OTHER id : %d\n", subelt_id); ++ } ++ subel += subelt_len; ++ } ++} ++/* ++ * Check if a BSS is up. ++ * This is a common implementation called by most OSL implementations of ++ * p2posl_bss_isup(). DO NOT call this function directly from the ++ * common code -- call p2posl_bss_isup() instead to allow the OSL to ++ * override the common implementation if necessary. ++ */ ++bool ++wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx) ++{ ++ s32 result, val; ++ bool isup = false; ++ s8 getbuf[64]; ++ ++ /* Check if the BSS is up */ ++ *(int*)getbuf = -1; ++ result = wldev_iovar_getbuf_bsscfg(ndev, "bss", &bsscfg_idx, ++ sizeof(bsscfg_idx), getbuf, sizeof(getbuf), 0, NULL); ++ if (result != 0) { ++ AP6210_ERR("'wl bss -C %d' failed: %d\n", bsscfg_idx, result); ++ AP6210_ERR("NOTE: this ioctl error is normal " ++ "when the BSS has not been created yet.\n"); ++ } else { ++ val = *(int*)getbuf; ++ val = dtoh32(val); ++ AP6210_DEBUG("---wl bss -C %d ==> %d\n", bsscfg_idx, val); ++ isup = (val ? TRUE : FALSE); ++ } ++ return isup; ++} ++ ++ ++/* Bring up or down a BSS */ ++s32 ++wl_cfgp2p_bss(struct wl_priv *wl, struct net_device *ndev, s32 bsscfg_idx, s32 up) ++{ ++ s32 ret = BCME_OK; ++ s32 val = up ? 1 : 0; ++ ++ struct { ++ s32 cfg; ++ s32 val; ++ } bss_setbuf; ++ ++ bss_setbuf.cfg = htod32(bsscfg_idx); ++ bss_setbuf.val = htod32(val); ++ AP6210_DEBUG("---wl bss -C %d %s\n", bsscfg_idx, up ? "up" : "down"); ++ ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf), ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); ++ ++ if (ret != 0) { ++ AP6210_ERR("'bss %d' failed with %d\n", up, ret); ++ } ++ ++ return ret; ++} ++ ++/* Check if 'p2p' is supported in the driver */ ++s32 ++wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev) ++{ ++ s32 ret = BCME_OK; ++ s32 p2p_supported = 0; ++ ret = wldev_iovar_getint(ndev, "p2p", ++ &p2p_supported); ++ if (ret < 0) { ++ AP6210_ERR("wl p2p error %d\n", ret); ++ return 0; ++ } ++ if (p2p_supported == 1) { ++ AP6210_DEBUG("p2p is supported\n"); ++ } else { ++ AP6210_DEBUG("p2p is unsupported\n"); ++ p2p_supported = 0; ++ } ++ return p2p_supported; ++} ++ ++/* Cleanup P2P resources */ ++s32 ++wl_cfgp2p_down(struct wl_priv *wl) ++{ ++ s32 i = 0, index = -1; ++ wl_cfgp2p_cancel_listen(wl, ++ wl->p2p_net ? wl->p2p_net : wl_to_prmry_ndev(wl), TRUE); ++ for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) { ++ index = wl_to_p2p_bss_bssidx(wl, i); ++ if (index != WL_INVALID) ++ wl_cfgp2p_clear_management_ie(wl, index); ++ } ++ wl_cfgp2p_deinit_priv(wl); ++ return 0; ++} ++ ++s32 ++wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len) ++{ ++ s32 ret = -1; ++ int count, start, duration; ++ wl_p2p_sched_t dongle_noa; ++ ++ AP6210_DEBUG(" Enter\n"); ++ ++ memset(&dongle_noa, 0, sizeof(dongle_noa)); ++ ++ if (wl->p2p && wl->p2p->vif_created) { ++ ++ wl->p2p->noa.desc[0].start = 0; ++ ++ sscanf(buf, "%10d %10d %10d", &count, &start, &duration); ++ AP6210_DEBUG("set_p2p_noa count %d start %d duration %d\n", ++ count, start, duration); ++ if (count != -1) ++ wl->p2p->noa.desc[0].count = count; ++ ++ /* supplicant gives interval as start */ ++ if (start != -1) ++ wl->p2p->noa.desc[0].interval = start; ++ ++ if (duration != -1) ++ wl->p2p->noa.desc[0].duration = duration; ++ ++ if (wl->p2p->noa.desc[0].count != 255) { ++ wl->p2p->noa.desc[0].start = 200; ++ dongle_noa.type = WL_P2P_SCHED_TYPE_REQ_ABS; ++ dongle_noa.action = WL_P2P_SCHED_ACTION_GOOFF; ++ dongle_noa.option = WL_P2P_SCHED_OPTION_TSFOFS; ++ } ++ else { ++ /* Continuous NoA interval. */ ++ dongle_noa.action = WL_P2P_SCHED_ACTION_NONE; ++ dongle_noa.type = WL_P2P_SCHED_TYPE_ABS; ++ if ((wl->p2p->noa.desc[0].interval == 102) || ++ (wl->p2p->noa.desc[0].interval == 100)) { ++ wl->p2p->noa.desc[0].start = 100 - ++ wl->p2p->noa.desc[0].duration; ++ dongle_noa.option = WL_P2P_SCHED_OPTION_BCNPCT; ++ } ++ else { ++ dongle_noa.option = WL_P2P_SCHED_OPTION_NORMAL; ++ } ++ } ++ /* Put the noa descriptor in dongle format for dongle */ ++ dongle_noa.desc[0].count = htod32(wl->p2p->noa.desc[0].count); ++ if (dongle_noa.option == WL_P2P_SCHED_OPTION_BCNPCT) { ++ dongle_noa.desc[0].start = htod32(wl->p2p->noa.desc[0].start); ++ dongle_noa.desc[0].duration = htod32(wl->p2p->noa.desc[0].duration); ++ } ++ else { ++ dongle_noa.desc[0].start = htod32(wl->p2p->noa.desc[0].start*1000); ++ dongle_noa.desc[0].duration = htod32(wl->p2p->noa.desc[0].duration*1000); ++ } ++ dongle_noa.desc[0].interval = htod32(wl->p2p->noa.desc[0].interval*1000); ++ ++ ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION), ++ "p2p_noa", &dongle_noa, sizeof(dongle_noa), wl->ioctl_buf, WLC_IOCTL_MAXLEN, ++ &wl->ioctl_buf_sync); ++ ++ if (ret < 0) { ++ AP6210_ERR("fw set p2p_noa failed %d\n", ret); ++ } ++ } ++ else { ++ AP6210_ERR("ERROR: set_noa in non-p2p mode\n"); ++ } ++ return ret; ++} ++s32 ++wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int buf_len) ++{ ++ ++ wifi_p2p_noa_desc_t *noa_desc; ++ int len = 0, i; ++ char _buf[200]; ++ ++ AP6210_DEBUG(" Enter\n"); ++ buf[0] = '\0'; ++ if (wl->p2p && wl->p2p->vif_created) { ++ if (wl->p2p->noa.desc[0].count || wl->p2p->ops.ops) { ++ _buf[0] = 1; /* noa index */ ++ _buf[1] = (wl->p2p->ops.ops ? 0x80: 0) | ++ (wl->p2p->ops.ctw & 0x7f); /* ops + ctw */ ++ len += 2; ++ if (wl->p2p->noa.desc[0].count) { ++ noa_desc = (wifi_p2p_noa_desc_t*)&_buf[len]; ++ noa_desc->cnt_type = wl->p2p->noa.desc[0].count; ++ noa_desc->duration = wl->p2p->noa.desc[0].duration; ++ noa_desc->interval = wl->p2p->noa.desc[0].interval; ++ noa_desc->start = wl->p2p->noa.desc[0].start; ++ len += sizeof(wifi_p2p_noa_desc_t); ++ } ++ if (buf_len <= len * 2) { ++ AP6210_ERR("ERROR: buf_len %d in not enough for" ++ "returning noa in string format\n", buf_len); ++ return -1; ++ } ++ /* We have to convert the buffer data into ASCII strings */ ++ for (i = 0; i < len; i++) { ++ snprintf(buf, 3, "%02x", _buf[i]); ++ buf += 2; ++ } ++ buf[i*2] = '\0'; ++ } ++ } ++ else { ++ AP6210_ERR("ERROR: get_noa in non-p2p mode\n"); ++ return -1; ++ } ++ return len * 2; ++} ++s32 ++wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int len) ++{ ++ int ps, ctw; ++ int ret = -1; ++ s32 legacy_ps; ++ ++ AP6210_DEBUG(" Enter\n"); ++ if (wl->p2p && wl->p2p->vif_created) { ++ sscanf(buf, "%10d %10d %10d", &legacy_ps, &ps, &ctw); ++ AP6210_DEBUG(" Enter legacy_ps %d ps %d ctw %d\n", legacy_ps, ps, ctw); ++ if (ctw != -1) { ++ wl->p2p->ops.ctw = ctw; ++ ret = 0; ++ } ++ if (ps != -1) { ++ wl->p2p->ops.ops = ps; ++ ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION), ++ "p2p_ops", &wl->p2p->ops, sizeof(wl->p2p->ops), ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); ++ if (ret < 0) { ++ AP6210_ERR("fw set p2p_ops failed %d\n", ret); ++ } ++ } ++ ++ if ((legacy_ps != -1) && ((legacy_ps == PM_MAX) || (legacy_ps == PM_OFF))) { ++#if !defined(SUPPORT_PM2_ONLY) ++ if (legacy_ps == PM_MAX) ++ legacy_ps = PM_FAST; ++#endif /* SUPPORT_PM2_ONLY */ ++ ++ ret = wldev_ioctl(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION), ++ WLC_SET_PM, &legacy_ps, sizeof(legacy_ps), true); ++ if (unlikely(ret)) { ++ AP6210_ERR("error (%d)\n", ret); ++ } else { ++ wl_cfg80211_update_power_mode(ndev); ++ } ++ } ++ else ++ AP6210_ERR("ilegal setting\n"); ++ } ++ else { ++ AP6210_ERR("ERROR: set_p2p_ps in non-p2p mode\n"); ++ ret = -1; ++ } ++ return ret; ++} ++ ++u8 * ++wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id) ++{ ++ wifi_p2p_ie_t *ie = NULL; ++ u16 len = 0; ++ u8 *subel; ++ u8 subelt_id; ++ u16 subelt_len; ++ ++ if (!buf) { ++ AP6210_ERR("P2P IE not present"); ++ return 0; ++ } ++ ++ ie = (wifi_p2p_ie_t*) buf; ++ len = ie->len; ++ ++ /* Point subel to the P2P IE's subelt field. ++ * Subtract the preceding fields (id, len, OUI, oui_type) from the length. ++ */ ++ subel = ie->subelts; ++ len -= 4; /* exclude OUI + OUI_TYPE */ ++ ++ while (len >= 3) { ++ /* attribute id */ ++ subelt_id = *subel; ++ subel += 1; ++ len -= 1; ++ ++ /* 2-byte little endian */ ++ subelt_len = *subel++; ++ subelt_len |= *subel++ << 8; ++ ++ len -= 2; ++ len -= subelt_len; /* for the remaining subelt fields */ ++ ++ if (subelt_id == element_id) { ++ /* This will point to start of subelement attrib after ++ * attribute id & len ++ */ ++ return subel; ++ } ++ ++ /* Go to next subelement */ ++ subel += subelt_len; ++ } ++ ++ /* Not Found */ ++ return NULL; ++} ++ ++#define P2P_GROUP_CAPAB_GO_BIT 0x01 ++u8 * ++wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length) ++{ ++ wifi_p2p_ie_t * p2p_ie = NULL; ++ u8 *capability = NULL; ++ bool p2p_go = 0; ++ u8 *ptr = NULL; ++ ++ if (!(p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset, bi->ie_length))) { ++ AP6210_ERR("P2P IE not found"); ++ return NULL; ++ } ++ ++ if (!(capability = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_P2P_INFO))) { ++ AP6210_ERR("P2P Capability attribute not found"); ++ return NULL; ++ } ++ ++ /* Check Group capability for Group Owner bit */ ++ p2p_go = capability[1] & P2P_GROUP_CAPAB_GO_BIT; ++ if (!p2p_go) { ++ return bi->BSSID.octet; ++ } ++ ++ /* In probe responses, DEVICE INFO attribute will be present */ ++ if (!(ptr = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_DEV_INFO))) { ++ /* If DEVICE_INFO is not found, this might be a beacon frame. ++ * check for DEVICE_ID in the beacon frame. ++ */ ++ ptr = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_DEV_ID); ++ } ++ ++ if (!ptr) ++ AP6210_ERR(" Both DEVICE_ID & DEVICE_INFO attribute not present in P2P IE "); ++ ++ return ptr; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) ++static void ++wl_cfgp2p_ethtool_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) ++{ ++ snprintf(info->driver, sizeof(info->driver), "p2p"); ++ snprintf(info->version, sizeof(info->version), "%lu", (unsigned long)(0)); ++} ++ ++struct ethtool_ops cfgp2p_ethtool_ops = { ++ .get_drvinfo = wl_cfgp2p_ethtool_get_drvinfo ++}; ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ ++ ++s32 ++wl_cfgp2p_register_ndev(struct wl_priv *wl) ++{ ++ int ret = 0; ++ struct net_device* net = NULL; ++ struct wireless_dev *wdev = NULL; ++ uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x33, 0x22, 0x11 }; ++ ++ if (wl->p2p_net) { ++ AP6210_ERR("p2p_net defined already.\n"); ++ return -EINVAL; ++ } ++ ++ /* Allocate etherdev, including space for private structure */ ++ if (!(net = alloc_etherdev(sizeof(struct wl_priv *)))) { ++ AP6210_ERR("%s: OOM - alloc_etherdev\n", __FUNCTION__); ++ return -ENODEV; ++ } ++ ++ wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); ++ if (unlikely(!wdev)) { ++ AP6210_ERR("Could not allocate wireless device\n"); ++ free_netdev(net); ++ return -ENOMEM; ++ } ++ ++ strncpy(net->name, "p2p%d", sizeof(net->name) - 1); ++ net->name[IFNAMSIZ - 1] = '\0'; ++ ++ /* Copy the reference to wl_priv */ ++ memcpy((void *)netdev_priv(net), &wl, sizeof(struct wl_priv *)); ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) ++ ASSERT(!net->open); ++ net->do_ioctl = wl_cfgp2p_do_ioctl; ++ net->hard_start_xmit = wl_cfgp2p_start_xmit; ++ net->open = wl_cfgp2p_if_open; ++ net->stop = wl_cfgp2p_if_stop; ++#else ++ ASSERT(!net->netdev_ops); ++ net->netdev_ops = &wl_cfgp2p_if_ops; ++#endif ++ ++ /* Register with a dummy MAC addr */ ++ memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN); ++ ++ wdev->wiphy = wl->wdev->wiphy; ++ ++ wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS); ++ ++ net->ieee80211_ptr = wdev; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) ++ net->ethtool_ops = &cfgp2p_ethtool_ops; ++#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ ++ ++ SET_NETDEV_DEV(net, wiphy_dev(wdev->wiphy)); ++ ++ /* Associate p2p0 network interface with new wdev */ ++ wdev->netdev = net; ++ ++ ret = register_netdev(net); ++ if (ret) { ++ AP6210_ERR(" register_netdevice failed (%d)\n", ret); ++ free_netdev(net); ++ kfree(wdev); ++ return -ENODEV; ++ } ++ ++ /* store p2p net ptr for further reference. Note that iflist won't have this ++ * entry as there corresponding firmware interface is a "Hidden" interface. ++ */ ++ wl->p2p_wdev = wdev; ++ wl->p2p_net = net; ++ ++ AP6210_DEBUG("%s: P2P Interface Registered\n", net->name); ++ ++ return ret; ++} ++ ++s32 ++wl_cfgp2p_unregister_ndev(struct wl_priv *wl) ++{ ++ ++ if (!wl || !wl->p2p_net) { ++ AP6210_ERR("Invalid Ptr\n"); ++ return -EINVAL; ++ } ++ ++ unregister_netdev(wl->p2p_net); ++ free_netdev(wl->p2p_net); ++ ++ return 0; ++} ++static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev) ++{ ++ if (skb) ++ { ++ AP6210_DEBUG("(%s) is not used for data operations.Droping the packet.\n", ++ ndev->name); ++ dev_kfree_skb_any(skb); ++ } ++ ++ return 0; ++} ++ ++static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd) ++{ ++ int ret = 0; ++ struct wl_priv *wl = *(struct wl_priv **)netdev_priv(net); ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++ ++ /* There is no ifidx corresponding to p2p0 in our firmware. So we should ++ * not Handle any IOCTL cmds on p2p0 other than ANDROID PRIVATE CMDs. ++ * For Android PRIV CMD handling map it to primary I/F ++ */ ++ if (cmd == SIOCDEVPRIVATE+1) { ++ ret = wl_android_priv_cmd(ndev, ifr, cmd); ++ ++ } else { ++ AP6210_ERR("%s: IOCTL req 0x%x on p2p0 I/F. Ignoring. \n", ++ __FUNCTION__, cmd); ++ return -1; ++ } ++ ++ return ret; ++} ++ ++static int wl_cfgp2p_if_open(struct net_device *net) ++{ ++ extern struct wl_priv *wlcfg_drv_priv; ++ struct wireless_dev *wdev = net->ieee80211_ptr; ++ struct wl_priv *wl = NULL; ++ wl = wlcfg_drv_priv; ++ if (!wdev || !wl || !wl->p2p) ++ return -EINVAL; ++ AP6210_DEBUG("Enter\n"); ++ /* If suppose F/W download (ifconfig wlan0 up) hasn't been done by now, ++ * do it here. This will make sure that in concurrent mode, supplicant ++ * is not dependent on a particular order of interface initialization. ++ * i.e you may give wpa_supp -iwlan0 -N -ip2p0 or wpa_supp -ip2p0 -N ++ * -iwlan0. ++ */ ++ wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT) ++ | BIT(NL80211_IFTYPE_P2P_GO)); ++ wl_cfg80211_do_driver_init(net); ++ ++ return 0; ++} ++ ++static int wl_cfgp2p_if_stop(struct net_device *net) ++{ ++ extern struct wl_priv *wlcfg_drv_priv; ++ struct wl_priv *wl = NULL; ++ unsigned long flags; ++ struct wireless_dev *wdev = net->ieee80211_ptr; ++ int clear_flag = 0; ++ if (!wdev) ++ return -EINVAL; ++ ++ AP6210_DEBUG("Enter\n"); ++ wl = wlcfg_drv_priv; ++ if (!wl) ++ return -EINVAL; ++ spin_lock_irqsave(&wl->cfgdrv_lock, flags); ++ if (wl->scan_request && wl->scan_request->dev == net) { ++ cfg80211_scan_done(wl->scan_request, true); ++ wl->scan_request = NULL; ++ clear_flag = 1; ++ } ++ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); ++ if (clear_flag) ++ wl_clr_drv_status(wl, SCANNING, net); ++ wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes) ++ & (~(BIT(NL80211_IFTYPE_P2P_CLIENT)| ++ BIT(NL80211_IFTYPE_P2P_GO))); ++ return 0; ++} ++ ++bool wl_cfgp2p_is_ifops(const struct net_device_ops *if_ops) ++{ ++ return (if_ops == &wl_cfgp2p_if_ops); ++} +diff --git a/drivers/net/wireless/ap6210/wl_cfgp2p.h b/drivers/net/wireless/ap6210/wl_cfgp2p.h +new file mode 100755 +index 0000000..d3552d6 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/wl_cfgp2p.h +@@ -0,0 +1,311 @@ ++/* ++ * Linux cfgp2p driver ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: wl_cfgp2p.h 368091 2012-11-12 04:28:31Z $ ++ */ ++#ifndef _wl_cfgp2p_h_ ++#define _wl_cfgp2p_h_ ++#include ++#include ++ ++struct wl_priv; ++extern u32 wl_dbg_level; ++ ++typedef struct wifi_p2p_ie wifi_wfd_ie_t; ++/* Enumeration of the usages of the BSSCFGs used by the P2P Library. Do not ++ * confuse this with a bsscfg index. This value is an index into the ++ * saved_ie[] array of structures which in turn contains a bsscfg index field. ++ */ ++typedef enum { ++ P2PAPI_BSSCFG_PRIMARY, /* maps to driver's primary bsscfg */ ++ P2PAPI_BSSCFG_DEVICE, /* maps to driver's P2P device discovery bsscfg */ ++ P2PAPI_BSSCFG_CONNECTION, /* maps to driver's P2P connection bsscfg */ ++ P2PAPI_BSSCFG_MAX ++} p2p_bsscfg_type_t; ++ ++/* vendor ies max buffer length for probe response or beacon */ ++#define VNDR_IES_MAX_BUF_LEN 1400 ++/* normal vendor ies buffer length */ ++#define VNDR_IES_BUF_LEN 512 ++ ++/* Structure to hold all saved P2P and WPS IEs for a BSSCFG */ ++struct p2p_saved_ie { ++ u8 p2p_probe_req_ie[VNDR_IES_BUF_LEN]; ++ u8 p2p_probe_res_ie[VNDR_IES_MAX_BUF_LEN]; ++ u8 p2p_assoc_req_ie[VNDR_IES_BUF_LEN]; ++ u8 p2p_assoc_res_ie[VNDR_IES_BUF_LEN]; ++ u8 p2p_beacon_ie[VNDR_IES_MAX_BUF_LEN]; ++ u32 p2p_probe_req_ie_len; ++ u32 p2p_probe_res_ie_len; ++ u32 p2p_assoc_req_ie_len; ++ u32 p2p_assoc_res_ie_len; ++ u32 p2p_beacon_ie_len; ++}; ++ ++struct p2p_bss { ++ u32 bssidx; ++ struct net_device *dev; ++ struct p2p_saved_ie saved_ie; ++ void *private_data; ++}; ++ ++struct p2p_info { ++ bool on; /* p2p on/off switch */ ++ bool scan; ++ bool vif_created; ++ s8 vir_ifname[IFNAMSIZ]; ++ unsigned long status; ++ struct ether_addr dev_addr; ++ struct ether_addr int_addr; ++ struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX]; ++ struct timer_list listen_timer; ++ wl_p2p_sched_t noa; ++ wl_p2p_ops_t ops; ++ wlc_ssid_t ssid; ++}; ++ ++#define MAX_VNDR_IE_NUMBER 5 ++ ++struct parsed_vndr_ie_info { ++ char *ie_ptr; ++ u32 ie_len; /* total length including id & length field */ ++ vndr_ie_t vndrie; ++}; ++ ++struct parsed_vndr_ies { ++ u32 count; ++ struct parsed_vndr_ie_info ie_info[MAX_VNDR_IE_NUMBER]; ++}; ++ ++/* dongle status */ ++enum wl_cfgp2p_status { ++ WLP2P_STATUS_DISCOVERY_ON = 0, ++ WLP2P_STATUS_SEARCH_ENABLED, ++ WLP2P_STATUS_IF_ADD, ++ WLP2P_STATUS_IF_DEL, ++ WLP2P_STATUS_IF_DELETING, ++ WLP2P_STATUS_IF_CHANGING, ++ WLP2P_STATUS_IF_CHANGED, ++ WLP2P_STATUS_LISTEN_EXPIRED, ++ WLP2P_STATUS_ACTION_TX_COMPLETED, ++ WLP2P_STATUS_ACTION_TX_NOACK, ++ WLP2P_STATUS_SCANNING, ++ WLP2P_STATUS_GO_NEG_PHASE, ++ WLP2P_STATUS_DISC_IN_PROGRESS ++}; ++ ++ ++#define wl_to_p2p_bss_ndev(wl, type) ((wl)->p2p->bss_idx[type].dev) ++#define wl_to_p2p_bss_bssidx(wl, type) ((wl)->p2p->bss_idx[type].bssidx) ++#define wl_to_p2p_bss_saved_ie(wl, type) ((wl)->p2p->bss_idx[type].saved_ie) ++#define wl_to_p2p_bss_private(wl, type) ((wl)->p2p->bss_idx[type].private_data) ++#define wl_to_p2p_bss(wl, type) ((wl)->p2p->bss_idx[type]) ++#define wl_get_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : test_bit(WLP2P_STATUS_ ## stat, \ ++ &(wl)->p2p->status)) ++#define wl_set_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : set_bit(WLP2P_STATUS_ ## stat, \ ++ &(wl)->p2p->status)) ++#define wl_clr_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : clear_bit(WLP2P_STATUS_ ## stat, \ ++ &(wl)->p2p->status)) ++#define wl_chg_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0:change_bit(WLP2P_STATUS_ ## stat, \ ++ &(wl)->p2p->status)) ++#define p2p_on(wl) ((wl)->p2p->on) ++#define p2p_scan(wl) ((wl)->p2p->scan) ++#define p2p_is_on(wl) ((wl)->p2p && (wl)->p2p->on) ++ ++/* dword align allocation */ ++#define WLC_IOCTL_MAXLEN 8192 ++ ++#define INIT_TIMER(timer, func, duration, extra_delay) \ ++ do { \ ++ init_timer(timer); \ ++ timer->function = func; \ ++ timer->expires = jiffies + msecs_to_jiffies(duration + extra_delay); \ ++ timer->data = (unsigned long) wl; \ ++ add_timer(timer); \ ++ } while (0); ++extern void ++wl_cfgp2p_listen_expired(unsigned long data); ++extern bool ++wl_cfgp2p_is_pub_action(void *frame, u32 frame_len); ++extern bool ++wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len); ++extern bool ++wl_cfgp2p_is_gas_action(void *frame, u32 frame_len); ++extern void ++wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len); ++extern s32 ++wl_cfgp2p_init_priv(struct wl_priv *wl); ++extern void ++wl_cfgp2p_deinit_priv(struct wl_priv *wl); ++extern s32 ++wl_cfgp2p_set_firm_p2p(struct wl_priv *wl); ++extern s32 ++wl_cfgp2p_set_p2p_mode(struct wl_priv *wl, u8 mode, ++ u32 channel, u16 listen_ms, int bssidx); ++extern s32 ++wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, ++ chanspec_t chspec); ++extern s32 ++wl_cfgp2p_ifdisable(struct wl_priv *wl, struct ether_addr *mac); ++extern s32 ++wl_cfgp2p_ifdel(struct wl_priv *wl, struct ether_addr *mac); ++extern s32 ++wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, chanspec_t chspec); ++ ++extern s32 ++wl_cfgp2p_ifidx(struct wl_priv *wl, struct ether_addr *mac, s32 *index); ++ ++extern s32 ++wl_cfgp2p_init_discovery(struct wl_priv *wl); ++extern s32 ++wl_cfgp2p_enable_discovery(struct wl_priv *wl, struct net_device *dev, const u8 *ie, u32 ie_len); ++extern s32 ++wl_cfgp2p_disable_discovery(struct wl_priv *wl); ++extern s32 ++wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, u32 num_chans, ++ u16 *channels, ++ s32 search_state, u16 action, u32 bssidx); ++ ++extern s32 ++wl_cfgp2p_act_frm_search(struct wl_priv *wl, struct net_device *ndev, ++ s32 bssidx, s32 channel); ++ ++extern wpa_ie_fixed_t * ++wl_cfgp2p_find_wpaie(u8 *parse, u32 len); ++ ++extern wpa_ie_fixed_t * ++wl_cfgp2p_find_wpsie(u8 *parse, u32 len); ++ ++extern wifi_p2p_ie_t * ++wl_cfgp2p_find_p2pie(u8 *parse, u32 len); ++ ++extern wifi_wfd_ie_t * ++wl_cfgp2p_find_wfdie(u8 *parse, u32 len); ++extern s32 ++wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, ++ s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len); ++extern s32 ++wl_cfgp2p_clear_management_ie(struct wl_priv *wl, s32 bssidx); ++ ++extern s32 ++wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev); ++extern struct net_device * ++wl_cfgp2p_find_ndev(struct wl_priv *wl, s32 bssidx); ++ ++ ++extern s32 ++wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data); ++extern s32 ++wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms); ++ ++extern s32 ++wl_cfgp2p_discover_enable_search(struct wl_priv *wl, u8 enable); ++ ++extern s32 ++wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data); ++extern s32 ++wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, ++ wl_af_params_t *af_params, s32 bssidx); ++ ++extern void ++wl_cfgp2p_generate_bss_mac(struct ether_addr *primary_addr, struct ether_addr *out_dev_addr, ++ struct ether_addr *out_int_addr); ++ ++extern void ++wl_cfg80211_change_ifaddr(u8* buf, struct ether_addr *p2p_int_addr, u8 element_id); ++extern bool ++wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx); ++ ++extern s32 ++wl_cfgp2p_bss(struct wl_priv *wl, struct net_device *ndev, s32 bsscfg_idx, s32 up); ++ ++ ++extern s32 ++wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev); ++ ++extern s32 ++wl_cfgp2p_down(struct wl_priv *wl); ++ ++extern s32 ++wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len); ++ ++extern s32 ++wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len); ++ ++extern s32 ++wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int len); ++ ++extern u8 * ++wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id); ++ ++extern u8 * ++wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length); ++ ++extern s32 ++wl_cfgp2p_register_ndev(struct wl_priv *wl); ++ ++extern s32 ++wl_cfgp2p_unregister_ndev(struct wl_priv *wl); ++ ++extern bool ++wl_cfgp2p_is_ifops(const struct net_device_ops *if_ops); ++ ++/* WiFi Direct */ ++#define SOCIAL_CHAN_1 1 ++#define SOCIAL_CHAN_2 6 ++#define SOCIAL_CHAN_3 11 ++#define IS_P2P_SOCIAL_CHANNEL(channel) ((channel == SOCIAL_CHAN_1) || \ ++ (channel == SOCIAL_CHAN_2) || \ ++ (channel == SOCIAL_CHAN_3)) ++#define SOCIAL_CHAN_CNT 3 ++#define AF_PEER_SEARCH_CNT 2 ++#define WL_P2P_WILDCARD_SSID "DIRECT-" ++#define WL_P2P_WILDCARD_SSID_LEN 7 ++#define WL_P2P_INTERFACE_PREFIX "p2p" ++#define WL_P2P_TEMP_CHAN 11 ++ ++/* If the provision discovery is for JOIN operations, ++ * then we need not do an internal scan to find GO. ++ */ ++#define IS_PROV_DISC_WITHOUT_GROUP_ID(p2p_ie, len) \ ++ (wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_GROUP_ID) == NULL) ++ ++#define IS_GAS_REQ(frame, len) (wl_cfgp2p_is_gas_action(frame, len) && \ ++ ((frame->action == P2PSD_ACTION_ID_GAS_IREQ) || \ ++ (frame->action == P2PSD_ACTION_ID_GAS_CREQ))) ++#define IS_P2P_PUB_ACT_REQ(frame, p2p_ie, len) \ ++ (wl_cfgp2p_is_pub_action(frame, len) && \ ++ ((frame->subtype == P2P_PAF_GON_REQ) || \ ++ (frame->subtype == P2P_PAF_INVITE_REQ) || \ ++ ((frame->subtype == P2P_PAF_PROVDIS_REQ) && \ ++ IS_PROV_DISC_WITHOUT_GROUP_ID(p2p_ie, len)))) ++#define IS_P2P_PUB_ACT_RSP_SUBTYPE(subtype) ((subtype == P2P_PAF_GON_RSP) || \ ++ ((subtype == P2P_PAF_GON_CONF) || \ ++ (subtype == P2P_PAF_INVITE_RSP) || \ ++ (subtype == P2P_PAF_PROVDIS_RSP))) ++#define IS_P2P_SOCIAL(ch) ((ch == SOCIAL_CHAN_1) || (ch == SOCIAL_CHAN_2) || (ch == SOCIAL_CHAN_3)) ++#define IS_P2P_SSID(ssid, len) (!memcmp(ssid, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN) && \ ++ (len == WL_P2P_WILDCARD_SSID_LEN)) ++#endif /* _wl_cfgp2p_h_ */ +diff --git a/drivers/net/wireless/ap6210/wl_iw.c b/drivers/net/wireless/ap6210/wl_iw.c +new file mode 100755 +index 0000000..8e067f4 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/wl_iw.c +@@ -0,0 +1,3622 @@ ++/* ++ * Linux Wireless Extensions support ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: wl_iw.c 352251 2012-08-22 06:08:38Z $ ++ */ ++ ++#if defined(USE_IW) ++#define LINUX_PORT ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++ ++typedef const struct si_pub si_t; ++#include ++ ++ ++#include ++ ++#include ++ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++#include ++#endif ++#if defined(SOFTAP) ++struct net_device *ap_net_dev = NULL; ++tsk_ctl_t ap_eth_ctl; /* apsta AP netdev waiter thread */ ++#endif /* SOFTAP */ ++ ++extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status, ++ uint32 reason, char* stringBuf, uint buflen); ++ ++uint iw_msg_level = WL_ERROR_VAL; ++ ++#define MAX_WLIW_IOCTL_LEN 1024 ++ ++/* IOCTL swapping mode for Big Endian host with Little Endian dongle. Default to off */ ++#define htod32(i) i ++#define htod16(i) i ++#define dtoh32(i) i ++#define dtoh16(i) i ++#define htodchanspec(i) i ++#define dtohchanspec(i) i ++ ++extern struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev); ++extern int dhd_wait_pend8021x(struct net_device *dev); ++ ++#if WIRELESS_EXT < 19 ++#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) ++#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST) ++#endif /* WIRELESS_EXT < 19 */ ++ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++#define DAEMONIZE(a) daemonize(a); \ ++ allow_signal(SIGKILL); \ ++ allow_signal(SIGTERM); ++#else /* Linux 2.4 (w/o preemption patch) */ ++#define RAISE_RX_SOFTIRQ() \ ++ cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ) ++#define DAEMONIZE(a) daemonize(); \ ++ do { if (a) \ ++ strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a) + 1))); \ ++ } while (0); ++#endif /* LINUX_VERSION_CODE */ ++ ++#define ISCAN_STATE_IDLE 0 ++#define ISCAN_STATE_SCANING 1 ++ ++/* the buf lengh can be WLC_IOCTL_MAXLEN (8K) to reduce iteration */ ++#define WLC_IW_ISCAN_MAXLEN 2048 ++typedef struct iscan_buf { ++ struct iscan_buf * next; ++ char iscan_buf[WLC_IW_ISCAN_MAXLEN]; ++} iscan_buf_t; ++ ++typedef struct iscan_info { ++ struct net_device *dev; ++ struct timer_list timer; ++ uint32 timer_ms; ++ uint32 timer_on; ++ int iscan_state; ++ iscan_buf_t * list_hdr; ++ iscan_buf_t * list_cur; ++ ++ /* Thread to work on iscan */ ++ long sysioc_pid; ++ struct semaphore sysioc_sem; ++ struct completion sysioc_exited; ++ ++ ++ char ioctlbuf[WLC_IOCTL_SMLEN]; ++} iscan_info_t; ++iscan_info_t *g_iscan = NULL; ++static void wl_iw_timerfunc(ulong data); ++static void wl_iw_set_event_mask(struct net_device *dev); ++static int wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action); ++ ++/* priv_link becomes netdev->priv and is the link between netdev and wlif struct */ ++typedef struct priv_link { ++ wl_iw_t *wliw; ++} priv_link_t; ++ ++/* dev to priv_link */ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) ++#define WL_DEV_LINK(dev) (priv_link_t*)(dev->priv) ++#else ++#define WL_DEV_LINK(dev) (priv_link_t*)netdev_priv(dev) ++#endif ++ ++/* dev to wl_iw_t */ ++#define IW_DEV_IF(dev) ((wl_iw_t*)(WL_DEV_LINK(dev))->wliw) ++ ++static void swap_key_from_BE( ++ wl_wsec_key_t *key ++) ++{ ++ key->index = htod32(key->index); ++ key->len = htod32(key->len); ++ key->algo = htod32(key->algo); ++ key->flags = htod32(key->flags); ++ key->rxiv.hi = htod32(key->rxiv.hi); ++ key->rxiv.lo = htod16(key->rxiv.lo); ++ key->iv_initialized = htod32(key->iv_initialized); ++} ++ ++static void swap_key_to_BE( ++ wl_wsec_key_t *key ++) ++{ ++ key->index = dtoh32(key->index); ++ key->len = dtoh32(key->len); ++ key->algo = dtoh32(key->algo); ++ key->flags = dtoh32(key->flags); ++ key->rxiv.hi = dtoh32(key->rxiv.hi); ++ key->rxiv.lo = dtoh16(key->rxiv.lo); ++ key->iv_initialized = dtoh32(key->iv_initialized); ++} ++ ++static int ++dev_wlc_ioctl( ++ struct net_device *dev, ++ int cmd, ++ void *arg, ++ int len ++) ++{ ++ struct ifreq ifr; ++ wl_ioctl_t ioc; ++ mm_segment_t fs; ++ int ret; ++ ++ memset(&ioc, 0, sizeof(ioc)); ++ ioc.cmd = cmd; ++ ioc.buf = arg; ++ ioc.len = len; ++ ++ strcpy(ifr.ifr_name, dev->name); ++ ifr.ifr_data = (caddr_t) &ioc; ++ ++#ifndef LINUX_HYBRID ++ /* Causes an extraneous 'up'. If specific ioctls are failing due ++ to device down, then we can investigate those ioctls. ++ */ ++ dev_open(dev); ++#endif ++ ++ fs = get_fs(); ++ set_fs(get_ds()); ++#if defined(WL_USE_NETDEV_OPS) ++ ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE); ++#else ++ ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE); ++#endif ++ set_fs(fs); ++ ++ return ret; ++} ++ ++/* ++set named driver variable to int value and return error indication ++calling example: dev_wlc_intvar_set(dev, "arate", rate) ++*/ ++ ++static int ++dev_wlc_intvar_set( ++ struct net_device *dev, ++ char *name, ++ int val) ++{ ++ char buf[WLC_IOCTL_SMLEN]; ++ uint len; ++ ++ val = htod32(val); ++ len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf)); ++ ASSERT(len); ++ ++ return (dev_wlc_ioctl(dev, WLC_SET_VAR, buf, len)); ++} ++ ++static int ++dev_iw_iovar_setbuf( ++ struct net_device *dev, ++ char *iovar, ++ void *param, ++ int paramlen, ++ void *bufptr, ++ int buflen) ++{ ++ int iolen; ++ ++ iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen); ++ ASSERT(iolen); ++ BCM_REFERENCE(iolen); ++ ++ return (dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen)); ++} ++ ++static int ++dev_iw_iovar_getbuf( ++ struct net_device *dev, ++ char *iovar, ++ void *param, ++ int paramlen, ++ void *bufptr, ++ int buflen) ++{ ++ int iolen; ++ ++ iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen); ++ ASSERT(iolen); ++ BCM_REFERENCE(iolen); ++ ++ return (dev_wlc_ioctl(dev, WLC_GET_VAR, bufptr, buflen)); ++} ++ ++#if WIRELESS_EXT > 17 ++static int ++dev_wlc_bufvar_set( ++ struct net_device *dev, ++ char *name, ++ char *buf, int len) ++{ ++ char *ioctlbuf; ++ uint buflen; ++ int error; ++ ++ ioctlbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL); ++ if (!ioctlbuf) ++ return -ENOMEM; ++ ++ buflen = bcm_mkiovar(name, buf, len, ioctlbuf, MAX_WLIW_IOCTL_LEN); ++ ASSERT(buflen); ++ error = dev_wlc_ioctl(dev, WLC_SET_VAR, ioctlbuf, buflen); ++ ++ kfree(ioctlbuf); ++ return error; ++} ++#endif /* WIRELESS_EXT > 17 */ ++ ++/* ++get named driver variable to int value and return error indication ++calling example: dev_wlc_bufvar_get(dev, "arate", &rate) ++*/ ++ ++static int ++dev_wlc_bufvar_get( ++ struct net_device *dev, ++ char *name, ++ char *buf, int buflen) ++{ ++ char *ioctlbuf; ++ int error; ++ ++ uint len; ++ ++ ioctlbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL); ++ if (!ioctlbuf) ++ return -ENOMEM; ++ len = bcm_mkiovar(name, NULL, 0, ioctlbuf, MAX_WLIW_IOCTL_LEN); ++ ASSERT(len); ++ BCM_REFERENCE(len); ++ error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctlbuf, MAX_WLIW_IOCTL_LEN); ++ if (!error) ++ bcopy(ioctlbuf, buf, buflen); ++ ++ kfree(ioctlbuf); ++ return (error); ++} ++ ++/* ++get named driver variable to int value and return error indication ++calling example: dev_wlc_intvar_get(dev, "arate", &rate) ++*/ ++ ++static int ++dev_wlc_intvar_get( ++ struct net_device *dev, ++ char *name, ++ int *retval) ++{ ++ union { ++ char buf[WLC_IOCTL_SMLEN]; ++ int val; ++ } var; ++ int error; ++ ++ uint len; ++ uint data_null; ++ ++ len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf)); ++ ASSERT(len); ++ error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len); ++ ++ *retval = dtoh32(var.val); ++ ++ return (error); ++} ++ ++/* Maintain backward compatibility */ ++#if WIRELESS_EXT < 13 ++struct iw_request_info ++{ ++ __u16 cmd; /* Wireless Extension command */ ++ __u16 flags; /* More to come ;-) */ ++}; ++ ++typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info, ++ void *wrqu, char *extra); ++#endif /* WIRELESS_EXT < 13 */ ++ ++#if WIRELESS_EXT > 12 ++static int ++wl_iw_set_leddc( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, ++ char *extra ++) ++{ ++ int dc = *(int *)extra; ++ int error; ++ ++ error = dev_wlc_intvar_set(dev, "leddc", dc); ++ return error; ++} ++ ++static int ++wl_iw_set_vlanmode( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, ++ char *extra ++) ++{ ++ int mode = *(int *)extra; ++ int error; ++ ++ mode = htod32(mode); ++ error = dev_wlc_intvar_set(dev, "vlan_mode", mode); ++ return error; ++} ++ ++static int ++wl_iw_set_pm( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, ++ char *extra ++) ++{ ++ int pm = *(int *)extra; ++ int error; ++ ++ pm = htod32(pm); ++ error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm)); ++ return error; ++} ++#endif /* WIRELESS_EXT > 12 */ ++ ++int ++wl_iw_send_priv_event( ++ struct net_device *dev, ++ char *flag ++) ++{ ++ union iwreq_data wrqu; ++ char extra[IW_CUSTOM_MAX + 1]; ++ int cmd; ++ ++ cmd = IWEVCUSTOM; ++ memset(&wrqu, 0, sizeof(wrqu)); ++ if (strlen(flag) > sizeof(extra)) ++ return -1; ++ ++ strcpy(extra, flag); ++ wrqu.data.length = strlen(extra); ++ wireless_send_event(dev, cmd, &wrqu, extra); ++ AP6210_DEBUG("Send IWEVCUSTOM Event as %s\n", extra); ++ ++ return 0; ++} ++ ++static int ++wl_iw_config_commit( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ void *zwrq, ++ char *extra ++) ++{ ++ wlc_ssid_t ssid; ++ int error; ++ struct sockaddr bssid; ++ ++ AP6210_DEBUG("%s: SIOCSIWCOMMIT\n", dev->name); ++ ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) ++ return error; ++ ++ ssid.SSID_len = dtoh32(ssid.SSID_len); ++ ++ if (!ssid.SSID_len) ++ return 0; ++ ++ bzero(&bssid, sizeof(struct sockaddr)); ++ if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, &bssid, ETHER_ADDR_LEN))) { ++ AP6210_ERR("%s: WLC_REASSOC failed (%d)\n", __FUNCTION__, error); ++ return error; ++ } ++ ++ return 0; ++} ++ ++static int ++wl_iw_get_name( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *cwrq, ++ char *extra ++) ++{ ++ int phytype, err; ++ uint band[3]; ++ char cap[5]; ++ ++ AP6210_DEBUG("%s: SIOCGIWNAME\n", dev->name); ++ ++ cap[0] = 0; ++ if ((err = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype))) < 0) ++ goto done; ++ if ((err = dev_wlc_ioctl(dev, WLC_GET_BANDLIST, band, sizeof(band))) < 0) ++ goto done; ++ ++ band[0] = dtoh32(band[0]); ++ switch (phytype) { ++ case WLC_PHY_TYPE_A: ++ strcpy(cap, "a"); ++ break; ++ case WLC_PHY_TYPE_B: ++ strcpy(cap, "b"); ++ break; ++ case WLC_PHY_TYPE_LP: ++ case WLC_PHY_TYPE_G: ++ if (band[0] >= 2) ++ strcpy(cap, "abg"); ++ else ++ strcpy(cap, "bg"); ++ break; ++ case WLC_PHY_TYPE_N: ++ if (band[0] >= 2) ++ strcpy(cap, "abgn"); ++ else ++ strcpy(cap, "bgn"); ++ break; ++ } ++done: ++ snprintf(cwrq->name, IFNAMSIZ, "IEEE 802.11%s", cap); ++ return 0; ++} ++ ++static int ++wl_iw_set_freq( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_freq *fwrq, ++ char *extra ++) ++{ ++ int error, chan; ++ uint sf = 0; ++ ++ AP6210_DEBUG("%s: SIOCSIWFREQ\n", dev->name); ++ ++ /* Setting by channel number */ ++ if (fwrq->e == 0 && fwrq->m < MAXCHANNEL) { ++ chan = fwrq->m; ++ } ++ ++ /* Setting by frequency */ ++ else { ++ /* Convert to MHz as best we can */ ++ if (fwrq->e >= 6) { ++ fwrq->e -= 6; ++ while (fwrq->e--) ++ fwrq->m *= 10; ++ } else if (fwrq->e < 6) { ++ while (fwrq->e++ < 6) ++ fwrq->m /= 10; ++ } ++ /* handle 4.9GHz frequencies as Japan 4 GHz based channelization */ ++ if (fwrq->m > 4000 && fwrq->m < 5000) ++ sf = WF_CHAN_FACTOR_4_G; /* start factor for 4 GHz */ ++ ++ chan = wf_mhz2channel(fwrq->m, sf); ++ } ++ chan = htod32(chan); ++ if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan)))) ++ return error; ++ ++ /* -EINPROGRESS: Call commit handler */ ++ return -EINPROGRESS; ++} ++ ++static int ++wl_iw_get_freq( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_freq *fwrq, ++ char *extra ++) ++{ ++ channel_info_t ci; ++ int error; ++ ++ AP6210_DEBUG("%s: SIOCGIWFREQ\n", dev->name); ++ ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) ++ return error; ++ ++ /* Return radio channel in channel form */ ++ fwrq->m = dtoh32(ci.hw_channel); ++ fwrq->e = dtoh32(0); ++ return 0; ++} ++ ++static int ++wl_iw_set_mode( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ __u32 *uwrq, ++ char *extra ++) ++{ ++ int infra = 0, ap = 0, error = 0; ++ ++ AP6210_DEBUG("%s: SIOCSIWMODE\n", dev->name); ++ ++ switch (*uwrq) { ++ case IW_MODE_MASTER: ++ infra = ap = 1; ++ break; ++ case IW_MODE_ADHOC: ++ case IW_MODE_AUTO: ++ break; ++ case IW_MODE_INFRA: ++ infra = 1; ++ break; ++ default: ++ return -EINVAL; ++ } ++ infra = htod32(infra); ++ ap = htod32(ap); ++ ++ if ((error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra))) || ++ (error = dev_wlc_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap)))) ++ return error; ++ ++ /* -EINPROGRESS: Call commit handler */ ++ return -EINPROGRESS; ++} ++ ++static int ++wl_iw_get_mode( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ __u32 *uwrq, ++ char *extra ++) ++{ ++ int error, infra = 0, ap = 0; ++ ++ AP6210_DEBUG("%s: SIOCGIWMODE\n", dev->name); ++ ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_INFRA, &infra, sizeof(infra))) || ++ (error = dev_wlc_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap)))) ++ return error; ++ ++ infra = dtoh32(infra); ++ ap = dtoh32(ap); ++ *uwrq = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC; ++ ++ return 0; ++} ++ ++static int ++wl_iw_get_range( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *dwrq, ++ char *extra ++) ++{ ++ struct iw_range *range = (struct iw_range *) extra; ++ static int channels[MAXCHANNEL+1]; ++ wl_uint32_list_t *list = (wl_uint32_list_t *) channels; ++ wl_rateset_t rateset; ++ int error, i, k; ++ uint sf, ch; ++ ++ int phytype; ++ int bw_cap = 0, sgi_tx = 0, nmode = 0; ++ channel_info_t ci; ++ uint8 nrate_list2copy = 0; ++ uint16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130}, ++ {14, 29, 43, 58, 87, 116, 130, 144}, ++ {27, 54, 81, 108, 162, 216, 243, 270}, ++ {30, 60, 90, 120, 180, 240, 270, 300}}; ++ ++ AP6210_DEBUG("%s: SIOCGIWRANGE\n", dev->name); ++ ++ if (!extra) ++ return -EINVAL; ++ ++ dwrq->length = sizeof(struct iw_range); ++ memset(range, 0, sizeof(*range)); ++ ++ /* We don't use nwids */ ++ range->min_nwid = range->max_nwid = 0; ++ ++ /* Set available channels/frequencies */ ++ list->count = htod32(MAXCHANNEL); ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, sizeof(channels)))) ++ return error; ++ for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) { ++ range->freq[i].i = dtoh32(list->element[i]); ++ ++ ch = dtoh32(list->element[i]); ++ if (ch <= CH_MAX_2G_CHANNEL) ++ sf = WF_CHAN_FACTOR_2_4_G; ++ else ++ sf = WF_CHAN_FACTOR_5_G; ++ ++ range->freq[i].m = wf_channel2mhz(ch, sf); ++ range->freq[i].e = 6; ++ } ++ range->num_frequency = range->num_channels = i; ++ ++ /* Link quality (use NDIS cutoffs) */ ++ range->max_qual.qual = 5; ++ /* Signal level (use RSSI) */ ++ range->max_qual.level = 0x100 - 200; /* -200 dBm */ ++ /* Noise level (use noise) */ ++ range->max_qual.noise = 0x100 - 200; /* -200 dBm */ ++ /* Signal level threshold range (?) */ ++ range->sensitivity = 65535; ++ ++#if WIRELESS_EXT > 11 ++ /* Link quality (use NDIS cutoffs) */ ++ range->avg_qual.qual = 3; ++ /* Signal level (use RSSI) */ ++ range->avg_qual.level = 0x100 + WL_IW_RSSI_GOOD; ++ /* Noise level (use noise) */ ++ range->avg_qual.noise = 0x100 - 75; /* -75 dBm */ ++#endif /* WIRELESS_EXT > 11 */ ++ ++ /* Set available bitrates */ ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset)))) ++ return error; ++ rateset.count = dtoh32(rateset.count); ++ range->num_bitrates = rateset.count; ++ for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++) ++ range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000; /* convert to bps */ ++ dev_wlc_intvar_get(dev, "nmode", &nmode); ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype)))) ++ return error; ++ ++ if (nmode == 1 && ((phytype == WLC_PHY_TYPE_SSN) || (phytype == WLC_PHY_TYPE_LCN) || ++ (phytype == WLC_PHY_TYPE_LCN40))) { ++ dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap); ++ dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx); ++ dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t)); ++ ci.hw_channel = dtoh32(ci.hw_channel); ++ ++ if (bw_cap == 0 || ++ (bw_cap == 2 && ci.hw_channel <= 14)) { ++ if (sgi_tx == 0) ++ nrate_list2copy = 0; ++ else ++ nrate_list2copy = 1; ++ } ++ if (bw_cap == 1 || ++ (bw_cap == 2 && ci.hw_channel >= 36)) { ++ if (sgi_tx == 0) ++ nrate_list2copy = 2; ++ else ++ nrate_list2copy = 3; ++ } ++ range->num_bitrates += 8; ++ for (k = 0; i < range->num_bitrates; k++, i++) { ++ /* convert to bps */ ++ range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000; ++ } ++ } ++ ++ /* Set an indication of the max TCP throughput ++ * in bit/s that we can expect using this interface. ++ * May be use for QoS stuff... Jean II ++ */ ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i)))) ++ return error; ++ i = dtoh32(i); ++ if (i == WLC_PHY_TYPE_A) ++ range->throughput = 24000000; /* 24 Mbits/s */ ++ else ++ range->throughput = 1500000; /* 1.5 Mbits/s */ ++ ++ /* RTS and fragmentation thresholds */ ++ range->min_rts = 0; ++ range->max_rts = 2347; ++ range->min_frag = 256; ++ range->max_frag = 2346; ++ ++ range->max_encoding_tokens = DOT11_MAX_DEFAULT_KEYS; ++ range->num_encoding_sizes = 4; ++ range->encoding_size[0] = WEP1_KEY_SIZE; ++ range->encoding_size[1] = WEP128_KEY_SIZE; ++#if WIRELESS_EXT > 17 ++ range->encoding_size[2] = TKIP_KEY_SIZE; ++#else ++ range->encoding_size[2] = 0; ++#endif ++ range->encoding_size[3] = AES_KEY_SIZE; ++ ++ /* Do not support power micro-management */ ++ range->min_pmp = 0; ++ range->max_pmp = 0; ++ range->min_pmt = 0; ++ range->max_pmt = 0; ++ range->pmp_flags = 0; ++ range->pm_capa = 0; ++ ++ /* Transmit Power - values are in mW */ ++ range->num_txpower = 2; ++ range->txpower[0] = 1; ++ range->txpower[1] = 255; ++ range->txpower_capa = IW_TXPOW_MWATT; ++ ++#if WIRELESS_EXT > 10 ++ range->we_version_compiled = WIRELESS_EXT; ++ range->we_version_source = 19; ++ ++ /* Only support retry limits */ ++ range->retry_capa = IW_RETRY_LIMIT; ++ range->retry_flags = IW_RETRY_LIMIT; ++ range->r_time_flags = 0; ++ /* SRL and LRL limits */ ++ range->min_retry = 1; ++ range->max_retry = 255; ++ /* Retry lifetime limits unsupported */ ++ range->min_r_time = 0; ++ range->max_r_time = 0; ++#endif /* WIRELESS_EXT > 10 */ ++ ++#if WIRELESS_EXT > 17 ++ range->enc_capa = IW_ENC_CAPA_WPA; ++ range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP; ++ range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP; ++ range->enc_capa |= IW_ENC_CAPA_WPA2; ++#if (defined(BCMSUP_PSK) && defined(WLFBT)) ++ /* Tell the host (e.g. wpa_supplicant) to let us do the handshake */ ++ range->enc_capa |= IW_ENC_CAPA_4WAY_HANDSHAKE; ++#endif /* (defined (BCMSUP_PSK) && defined(WLFBT)) */ ++ ++ /* Event capability (kernel) */ ++ IW_EVENT_CAPA_SET_KERNEL(range->event_capa); ++ /* Event capability (driver) */ ++ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); ++ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); ++ IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP); ++ IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE); ++ IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE); ++ IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE); ++ IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND); ++ ++#if WIRELESS_EXT >= 22 && defined(IW_SCAN_CAPA_ESSID) ++ /* FC7 wireless.h defines EXT 22 but doesn't define scan_capa bits */ ++ range->scan_capa = IW_SCAN_CAPA_ESSID; ++#endif ++#endif /* WIRELESS_EXT > 17 */ ++ ++ return 0; ++} ++ ++static int ++rssi_to_qual(int rssi) ++{ ++ if (rssi <= WL_IW_RSSI_NO_SIGNAL) ++ return 0; ++ else if (rssi <= WL_IW_RSSI_VERY_LOW) ++ return 1; ++ else if (rssi <= WL_IW_RSSI_LOW) ++ return 2; ++ else if (rssi <= WL_IW_RSSI_GOOD) ++ return 3; ++ else if (rssi <= WL_IW_RSSI_VERY_GOOD) ++ return 4; ++ else ++ return 5; ++} ++ ++static int ++wl_iw_set_spy( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *dwrq, ++ char *extra ++) ++{ ++ wl_iw_t *iw = IW_DEV_IF(dev); ++ struct sockaddr *addr = (struct sockaddr *) extra; ++ int i; ++ ++ AP6210_DEBUG("%s: SIOCSIWSPY\n", dev->name); ++ ++ if (!extra) ++ return -EINVAL; ++ ++ iw->spy_num = MIN(ARRAYSIZE(iw->spy_addr), dwrq->length); ++ for (i = 0; i < iw->spy_num; i++) ++ memcpy(&iw->spy_addr[i], addr[i].sa_data, ETHER_ADDR_LEN); ++ memset(iw->spy_qual, 0, sizeof(iw->spy_qual)); ++ ++ return 0; ++} ++ ++static int ++wl_iw_get_spy( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *dwrq, ++ char *extra ++) ++{ ++ wl_iw_t *iw = IW_DEV_IF(dev); ++ struct sockaddr *addr = (struct sockaddr *) extra; ++ struct iw_quality *qual = (struct iw_quality *) &addr[iw->spy_num]; ++ int i; ++ ++ AP6210_DEBUG("%s: SIOCGIWSPY\n", dev->name); ++ ++ if (!extra) ++ return -EINVAL; ++ ++ dwrq->length = iw->spy_num; ++ for (i = 0; i < iw->spy_num; i++) { ++ memcpy(addr[i].sa_data, &iw->spy_addr[i], ETHER_ADDR_LEN); ++ addr[i].sa_family = AF_UNIX; ++ memcpy(&qual[i], &iw->spy_qual[i], sizeof(struct iw_quality)); ++ iw->spy_qual[i].updated = 0; ++ } ++ ++ return 0; ++} ++ ++static int ++wl_iw_set_wap( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct sockaddr *awrq, ++ char *extra ++) ++{ ++ int error = -EINVAL; ++ ++ AP6210_DEBUG("%s: SIOCSIWAP\n", dev->name); ++ ++ if (awrq->sa_family != ARPHRD_ETHER) { ++ AP6210_ERR("%s: Invalid Header...sa_family\n", __FUNCTION__); ++ return -EINVAL; ++ } ++ ++ /* Ignore "auto" or "off" */ ++ if (ETHER_ISBCAST(awrq->sa_data) || ETHER_ISNULLADDR(awrq->sa_data)) { ++ scb_val_t scbval; ++ bzero(&scbval, sizeof(scb_val_t)); ++ if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)))) { ++ AP6210_ERR("%s: WLC_DISASSOC failed (%d).\n", __FUNCTION__, error); ++ } ++ return 0; ++ } ++ /* WL_ASSOC(("Assoc to %s\n", bcm_ether_ntoa((struct ether_addr *)&(awrq->sa_data), ++ * eabuf))); ++ */ ++ /* Reassociate to the specified AP */ ++ if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, awrq->sa_data, ETHER_ADDR_LEN))) { ++ AP6210_ERR("%s: WLC_REASSOC failed (%d).\n", __FUNCTION__, error); ++ return error; ++ } ++ ++ return 0; ++} ++ ++static int ++wl_iw_get_wap( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct sockaddr *awrq, ++ char *extra ++) ++{ ++ AP6210_DEBUG("%s: SIOCGIWAP\n", dev->name); ++ ++ awrq->sa_family = ARPHRD_ETHER; ++ memset(awrq->sa_data, 0, ETHER_ADDR_LEN); ++ ++ /* Ignore error (may be down or disassociated) */ ++ (void) dev_wlc_ioctl(dev, WLC_GET_BSSID, awrq->sa_data, ETHER_ADDR_LEN); ++ ++ return 0; ++} ++ ++#if WIRELESS_EXT > 17 ++static int ++wl_iw_mlme( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct sockaddr *awrq, ++ char *extra ++) ++{ ++ struct iw_mlme *mlme; ++ scb_val_t scbval; ++ int error = -EINVAL; ++ ++ AP6210_DEBUG("%s: SIOCSIWMLME\n", dev->name); ++ ++ mlme = (struct iw_mlme *)extra; ++ if (mlme == NULL) { ++ AP6210_ERR("Invalid ioctl data.\n"); ++ return error; ++ } ++ ++ scbval.val = mlme->reason_code; ++ bcopy(&mlme->addr.sa_data, &scbval.ea, ETHER_ADDR_LEN); ++ ++ if (mlme->cmd == IW_MLME_DISASSOC) { ++ scbval.val = htod32(scbval.val); ++ error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)); ++ } ++ else if (mlme->cmd == IW_MLME_DEAUTH) { ++ scbval.val = htod32(scbval.val); ++ error = dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, ++ sizeof(scb_val_t)); ++ } ++ else { ++ AP6210_ERR("%s: Invalid ioctl data.\n", __FUNCTION__); ++ return error; ++ } ++ ++ return error; ++} ++#endif /* WIRELESS_EXT > 17 */ ++ ++static int ++wl_iw_get_aplist( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *dwrq, ++ char *extra ++) ++{ ++ wl_scan_results_t *list; ++ struct sockaddr *addr = (struct sockaddr *) extra; ++ struct iw_quality qual[IW_MAX_AP]; ++ wl_bss_info_t *bi = NULL; ++ int error, i; ++ uint buflen = dwrq->length; ++ ++ AP6210_DEBUG("%s: SIOCGIWAPLIST\n", dev->name); ++ ++ if (!extra) ++ return -EINVAL; ++ ++ /* Get scan results (too large to put on the stack) */ ++ list = kmalloc(buflen, GFP_KERNEL); ++ if (!list) ++ return -ENOMEM; ++ memset(list, 0, buflen); ++ list->buflen = htod32(buflen); ++ if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) { ++ AP6210_ERR("%d: Scan results error %d\n", __LINE__, error); ++ kfree(list); ++ return error; ++ } ++ list->buflen = dtoh32(list->buflen); ++ list->version = dtoh32(list->version); ++ list->count = dtoh32(list->count); ++ ASSERT(list->version == WL_BSS_INFO_VERSION); ++ ++ for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) { ++ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; ++ ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list + ++ buflen)); ++ ++ /* Infrastructure only */ ++ if (!(dtoh16(bi->capability) & DOT11_CAP_ESS)) ++ continue; ++ ++ /* BSSID */ ++ memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN); ++ addr[dwrq->length].sa_family = ARPHRD_ETHER; ++ qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI)); ++ qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI); ++ qual[dwrq->length].noise = 0x100 + bi->phy_noise; ++ ++ /* Updated qual, level, and noise */ ++#if WIRELESS_EXT > 18 ++ qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; ++#else ++ qual[dwrq->length].updated = 7; ++#endif /* WIRELESS_EXT > 18 */ ++ ++ dwrq->length++; ++ } ++ ++ kfree(list); ++ ++ if (dwrq->length) { ++ memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length); ++ /* Provided qual */ ++ dwrq->flags = 1; ++ } ++ ++ return 0; ++} ++ ++static int ++wl_iw_iscan_get_aplist( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *dwrq, ++ char *extra ++) ++{ ++ wl_scan_results_t *list; ++ iscan_buf_t * buf; ++ iscan_info_t *iscan = g_iscan; ++ ++ struct sockaddr *addr = (struct sockaddr *) extra; ++ struct iw_quality qual[IW_MAX_AP]; ++ wl_bss_info_t *bi = NULL; ++ int i; ++ ++ AP6210_DEBUG("%s: SIOCGIWAPLIST\n", dev->name); ++ ++ if (!extra) ++ return -EINVAL; ++ ++ if ((!iscan) || (iscan->sysioc_pid < 0)) { ++ return wl_iw_get_aplist(dev, info, dwrq, extra); ++ } ++ ++ buf = iscan->list_hdr; ++ /* Get scan results (too large to put on the stack) */ ++ while (buf) { ++ list = &((wl_iscan_results_t*)buf->iscan_buf)->results; ++ ASSERT(list->version == WL_BSS_INFO_VERSION); ++ ++ bi = NULL; ++ for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) { ++ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; ++ ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list + ++ WLC_IW_ISCAN_MAXLEN)); ++ ++ /* Infrastructure only */ ++ if (!(dtoh16(bi->capability) & DOT11_CAP_ESS)) ++ continue; ++ ++ /* BSSID */ ++ memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN); ++ addr[dwrq->length].sa_family = ARPHRD_ETHER; ++ qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI)); ++ qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI); ++ qual[dwrq->length].noise = 0x100 + bi->phy_noise; ++ ++ /* Updated qual, level, and noise */ ++#if WIRELESS_EXT > 18 ++ qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; ++#else ++ qual[dwrq->length].updated = 7; ++#endif /* WIRELESS_EXT > 18 */ ++ ++ dwrq->length++; ++ } ++ buf = buf->next; ++ } ++ if (dwrq->length) { ++ memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length); ++ /* Provided qual */ ++ dwrq->flags = 1; ++ } ++ ++ return 0; ++} ++ ++#if WIRELESS_EXT > 13 ++static int ++wl_iw_set_scan( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, ++ char *extra ++) ++{ ++ wlc_ssid_t ssid; ++ ++ AP6210_DEBUG("%s: SIOCSIWSCAN\n", dev->name); ++ ++ /* default Broadcast scan */ ++ memset(&ssid, 0, sizeof(ssid)); ++ ++#if WIRELESS_EXT > 17 ++ /* check for given essid */ ++ if (wrqu->data.length == sizeof(struct iw_scan_req)) { ++ if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { ++ struct iw_scan_req *req = (struct iw_scan_req *)extra; ++ ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len); ++ memcpy(ssid.SSID, req->essid, ssid.SSID_len); ++ ssid.SSID_len = htod32(ssid.SSID_len); ++ } ++ } ++#endif ++ /* Ignore error (most likely scan in progress) */ ++ (void) dev_wlc_ioctl(dev, WLC_SCAN, &ssid, sizeof(ssid)); ++ ++ return 0; ++} ++ ++static int ++wl_iw_iscan_set_scan( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ union iwreq_data *wrqu, ++ char *extra ++) ++{ ++ wlc_ssid_t ssid; ++ iscan_info_t *iscan = g_iscan; ++ ++ AP6210_DEBUG("%s: SIOCSIWSCAN\n", dev->name); ++ ++ /* use backup if our thread is not successful */ ++ if ((!iscan) || (iscan->sysioc_pid < 0)) { ++ return wl_iw_set_scan(dev, info, wrqu, extra); ++ } ++ if (iscan->iscan_state == ISCAN_STATE_SCANING) { ++ return 0; ++ } ++ ++ /* default Broadcast scan */ ++ memset(&ssid, 0, sizeof(ssid)); ++ ++#if WIRELESS_EXT > 17 ++ /* check for given essid */ ++ if (wrqu->data.length == sizeof(struct iw_scan_req)) { ++ if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { ++ struct iw_scan_req *req = (struct iw_scan_req *)extra; ++ ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len); ++ memcpy(ssid.SSID, req->essid, ssid.SSID_len); ++ ssid.SSID_len = htod32(ssid.SSID_len); ++ } ++ } ++#endif ++ ++ iscan->list_cur = iscan->list_hdr; ++ iscan->iscan_state = ISCAN_STATE_SCANING; ++ ++ ++ wl_iw_set_event_mask(dev); ++ wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START); ++ ++ iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms); ++ add_timer(&iscan->timer); ++ iscan->timer_on = 1; ++ ++ return 0; ++} ++ ++#if WIRELESS_EXT > 17 ++static bool ++ie_is_wpa_ie(uint8 **wpaie, uint8 **tlvs, int *tlvs_len) ++{ ++/* Is this body of this tlvs entry a WPA entry? If */ ++/* not update the tlvs buffer pointer/length */ ++ uint8 *ie = *wpaie; ++ ++ /* If the contents match the WPA_OUI and type=1 */ ++ if ((ie[1] >= 6) && ++ !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x01"), 4)) { ++ return TRUE; ++ } ++ ++ /* point to the next ie */ ++ ie += ie[1] + 2; ++ /* calculate the length of the rest of the buffer */ ++ *tlvs_len -= (int)(ie - *tlvs); ++ /* update the pointer to the start of the buffer */ ++ *tlvs = ie; ++ return FALSE; ++} ++ ++static bool ++ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len) ++{ ++/* Is this body of this tlvs entry a WPS entry? If */ ++/* not update the tlvs buffer pointer/length */ ++ uint8 *ie = *wpsie; ++ ++ /* If the contents match the WPA_OUI and type=4 */ ++ if ((ie[1] >= 4) && ++ !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x04"), 4)) { ++ return TRUE; ++ } ++ ++ /* point to the next ie */ ++ ie += ie[1] + 2; ++ /* calculate the length of the rest of the buffer */ ++ *tlvs_len -= (int)(ie - *tlvs); ++ /* update the pointer to the start of the buffer */ ++ *tlvs = ie; ++ return FALSE; ++} ++#endif /* WIRELESS_EXT > 17 */ ++ ++ ++static int ++wl_iw_handle_scanresults_ies(char **event_p, char *end, ++ struct iw_request_info *info, wl_bss_info_t *bi) ++{ ++#if WIRELESS_EXT > 17 ++ struct iw_event iwe; ++ char *event; ++ ++ event = *event_p; ++ if (bi->ie_length) { ++ /* look for wpa/rsn ies in the ie list... */ ++ bcm_tlv_t *ie; ++ uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); ++ int ptr_len = bi->ie_length; ++ ++ if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) { ++ iwe.cmd = IWEVGENIE; ++ iwe.u.data.length = ie->len + 2; ++ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); ++ } ++ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); ++ ++#if defined(WLFBT) ++ if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_MDIE_ID))) { ++ iwe.cmd = IWEVGENIE; ++ iwe.u.data.length = ie->len + 2; ++ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); ++ } ++ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); ++#endif /* WLFBT */ ++ ++ while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) { ++ /* look for WPS IE */ ++ if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) { ++ iwe.cmd = IWEVGENIE; ++ iwe.u.data.length = ie->len + 2; ++ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); ++ break; ++ } ++ } ++ ++ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); ++ ptr_len = bi->ie_length; ++ while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) { ++ if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) { ++ iwe.cmd = IWEVGENIE; ++ iwe.u.data.length = ie->len + 2; ++ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); ++ break; ++ } ++ } ++ ++ *event_p = event; ++ } ++ ++#endif /* WIRELESS_EXT > 17 */ ++ return 0; ++} ++static int ++wl_iw_get_scan( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *dwrq, ++ char *extra ++) ++{ ++ channel_info_t ci; ++ wl_scan_results_t *list; ++ struct iw_event iwe; ++ wl_bss_info_t *bi = NULL; ++ int error, i, j; ++ char *event = extra, *end = extra + dwrq->length, *value; ++ uint buflen = dwrq->length; ++ ++ AP6210_DEBUG("%s: SIOCGIWSCAN\n", dev->name); ++ ++ if (!extra) ++ return -EINVAL; ++ ++ /* Check for scan in progress */ ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) ++ return error; ++ ci.scan_channel = dtoh32(ci.scan_channel); ++ if (ci.scan_channel) ++ return -EAGAIN; ++ ++ /* Get scan results (too large to put on the stack) */ ++ list = kmalloc(buflen, GFP_KERNEL); ++ if (!list) ++ return -ENOMEM; ++ memset(list, 0, buflen); ++ list->buflen = htod32(buflen); ++ if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) { ++ kfree(list); ++ return error; ++ } ++ list->buflen = dtoh32(list->buflen); ++ list->version = dtoh32(list->version); ++ list->count = dtoh32(list->count); ++ ++ ASSERT(list->version == WL_BSS_INFO_VERSION); ++ ++ for (i = 0; i < list->count && i < IW_MAX_AP; i++) { ++ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; ++ ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list + ++ buflen)); ++ ++ /* First entry must be the BSSID */ ++ iwe.cmd = SIOCGIWAP; ++ iwe.u.ap_addr.sa_family = ARPHRD_ETHER; ++ memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN); ++ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN); ++ ++ /* SSID */ ++ iwe.u.data.length = dtoh32(bi->SSID_len); ++ iwe.cmd = SIOCGIWESSID; ++ iwe.u.data.flags = 1; ++ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID); ++ ++ /* Mode */ ++ if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) { ++ iwe.cmd = SIOCGIWMODE; ++ if (dtoh16(bi->capability) & DOT11_CAP_ESS) ++ iwe.u.mode = IW_MODE_INFRA; ++ else ++ iwe.u.mode = IW_MODE_ADHOC; ++ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN); ++ } ++ ++ /* Channel */ ++ iwe.cmd = SIOCGIWFREQ; ++ iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec), ++ CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ? ++ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G); ++ iwe.u.freq.e = 6; ++ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN); ++ ++ /* Channel quality */ ++ iwe.cmd = IWEVQUAL; ++ iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI)); ++ iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI); ++ iwe.u.qual.noise = 0x100 + bi->phy_noise; ++ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN); ++ ++ /* WPA, WPA2, WPS, WAPI IEs */ ++ wl_iw_handle_scanresults_ies(&event, end, info, bi); ++ ++ /* Encryption */ ++ iwe.cmd = SIOCGIWENCODE; ++ if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY) ++ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; ++ else ++ iwe.u.data.flags = IW_ENCODE_DISABLED; ++ iwe.u.data.length = 0; ++ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event); ++ ++ /* Rates */ ++ if (bi->rateset.count) { ++ value = event + IW_EV_LCP_LEN; ++ iwe.cmd = SIOCGIWRATE; ++ /* Those two flags are ignored... */ ++ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; ++ for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) { ++ iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000; ++ value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe, ++ IW_EV_PARAM_LEN); ++ } ++ event = value; ++ } ++ } ++ ++ kfree(list); ++ ++ dwrq->length = event - extra; ++ dwrq->flags = 0; /* todo */ ++ ++ return 0; ++} ++ ++static int ++wl_iw_iscan_get_scan( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *dwrq, ++ char *extra ++) ++{ ++ wl_scan_results_t *list; ++ struct iw_event iwe; ++ wl_bss_info_t *bi = NULL; ++ int ii, j; ++ int apcnt; ++ char *event = extra, *end = extra + dwrq->length, *value; ++ iscan_info_t *iscan = g_iscan; ++ iscan_buf_t * p_buf; ++ ++ AP6210_DEBUG("%s: SIOCGIWSCAN\n", dev->name); ++ ++ if (!extra) ++ return -EINVAL; ++ ++ /* use backup if our thread is not successful */ ++ if ((!iscan) || (iscan->sysioc_pid < 0)) { ++ return wl_iw_get_scan(dev, info, dwrq, extra); ++ } ++ ++ /* Check for scan in progress */ ++ if (iscan->iscan_state == ISCAN_STATE_SCANING) ++ return -EAGAIN; ++ ++ apcnt = 0; ++ p_buf = iscan->list_hdr; ++ /* Get scan results */ ++ while (p_buf != iscan->list_cur) { ++ list = &((wl_iscan_results_t*)p_buf->iscan_buf)->results; ++ ++ if (list->version != WL_BSS_INFO_VERSION) { ++ AP6210_ERR("list->version %d != WL_BSS_INFO_VERSION\n", list->version); ++ } ++ ++ bi = NULL; ++ for (ii = 0; ii < list->count && apcnt < IW_MAX_AP; apcnt++, ii++) { ++ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; ++ ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list + ++ WLC_IW_ISCAN_MAXLEN)); ++ ++ /* overflow check cover fields before wpa IEs */ ++ if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN + ++ IW_EV_QUAL_LEN >= end) ++ return -E2BIG; ++ /* First entry must be the BSSID */ ++ iwe.cmd = SIOCGIWAP; ++ iwe.u.ap_addr.sa_family = ARPHRD_ETHER; ++ memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN); ++ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN); ++ ++ /* SSID */ ++ iwe.u.data.length = dtoh32(bi->SSID_len); ++ iwe.cmd = SIOCGIWESSID; ++ iwe.u.data.flags = 1; ++ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID); ++ ++ /* Mode */ ++ if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) { ++ iwe.cmd = SIOCGIWMODE; ++ if (dtoh16(bi->capability) & DOT11_CAP_ESS) ++ iwe.u.mode = IW_MODE_INFRA; ++ else ++ iwe.u.mode = IW_MODE_ADHOC; ++ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN); ++ } ++ ++ /* Channel */ ++ iwe.cmd = SIOCGIWFREQ; ++ iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec), ++ CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ? ++ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G); ++ iwe.u.freq.e = 6; ++ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN); ++ ++ /* Channel quality */ ++ iwe.cmd = IWEVQUAL; ++ iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI)); ++ iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI); ++ iwe.u.qual.noise = 0x100 + bi->phy_noise; ++ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN); ++ ++ /* WPA, WPA2, WPS, WAPI IEs */ ++ wl_iw_handle_scanresults_ies(&event, end, info, bi); ++ ++ /* Encryption */ ++ iwe.cmd = SIOCGIWENCODE; ++ if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY) ++ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; ++ else ++ iwe.u.data.flags = IW_ENCODE_DISABLED; ++ iwe.u.data.length = 0; ++ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event); ++ ++ /* Rates */ ++ if (bi->rateset.count <= sizeof(bi->rateset.rates)) { ++ if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end) ++ return -E2BIG; ++ ++ value = event + IW_EV_LCP_LEN; ++ iwe.cmd = SIOCGIWRATE; ++ /* Those two flags are ignored... */ ++ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; ++ for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) { ++ iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000; ++ value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe, ++ IW_EV_PARAM_LEN); ++ } ++ event = value; ++ } ++ } ++ p_buf = p_buf->next; ++ } /* while (p_buf) */ ++ ++ dwrq->length = event - extra; ++ dwrq->flags = 0; /* todo */ ++ ++ return 0; ++} ++ ++#endif /* WIRELESS_EXT > 13 */ ++ ++ ++static int ++wl_iw_set_essid( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *dwrq, ++ char *extra ++) ++{ ++ wlc_ssid_t ssid; ++ int error; ++ ++ AP6210_DEBUG("%s: SIOCSIWESSID\n", dev->name); ++ ++ /* default Broadcast SSID */ ++ memset(&ssid, 0, sizeof(ssid)); ++ if (dwrq->length && extra) { ++#if WIRELESS_EXT > 20 ++ ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length); ++#else ++ ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length-1); ++#endif ++ memcpy(ssid.SSID, extra, ssid.SSID_len); ++ ssid.SSID_len = htod32(ssid.SSID_len); ++ ++ if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid)))) ++ return error; ++ } ++ /* If essid null then it is "iwconfig essid off" command */ ++ else { ++ scb_val_t scbval; ++ bzero(&scbval, sizeof(scb_val_t)); ++ if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)))) ++ return error; ++ } ++ return 0; ++} ++ ++static int ++wl_iw_get_essid( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *dwrq, ++ char *extra ++) ++{ ++ wlc_ssid_t ssid; ++ int error; ++ ++ AP6210_DEBUG("%s: SIOCGIWESSID\n", dev->name); ++ ++ if (!extra) ++ return -EINVAL; ++ ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) { ++ AP6210_ERR("Error getting the SSID\n"); ++ return error; ++ } ++ ++ ssid.SSID_len = dtoh32(ssid.SSID_len); ++ ++ /* Get the current SSID */ ++ memcpy(extra, ssid.SSID, ssid.SSID_len); ++ ++ dwrq->length = ssid.SSID_len; ++ ++ dwrq->flags = 1; /* active */ ++ ++ return 0; ++} ++ ++static int ++wl_iw_set_nick( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *dwrq, ++ char *extra ++) ++{ ++ wl_iw_t *iw = IW_DEV_IF(dev); ++ AP6210_DEBUG("%s: SIOCSIWNICKN\n", dev->name); ++ ++ if (!extra) ++ return -EINVAL; ++ ++ /* Check the size of the string */ ++ if (dwrq->length > sizeof(iw->nickname)) ++ return -E2BIG; ++ ++ memcpy(iw->nickname, extra, dwrq->length); ++ iw->nickname[dwrq->length - 1] = '\0'; ++ ++ return 0; ++} ++ ++static int ++wl_iw_get_nick( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *dwrq, ++ char *extra ++) ++{ ++ wl_iw_t *iw = IW_DEV_IF(dev); ++ AP6210_DEBUG("%s: SIOCGIWNICKN\n", dev->name); ++ ++ if (!extra) ++ return -EINVAL; ++ ++ strcpy(extra, iw->nickname); ++ dwrq->length = strlen(extra) + 1; ++ ++ return 0; ++} ++ ++static int wl_iw_set_rate( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ wl_rateset_t rateset; ++ int error, rate, i, error_bg, error_a; ++ ++ AP6210_DEBUG("%s: SIOCSIWRATE\n", dev->name); ++ ++ /* Get current rateset */ ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset)))) ++ return error; ++ ++ rateset.count = dtoh32(rateset.count); ++ ++ if (vwrq->value < 0) { ++ /* Select maximum rate */ ++ rate = rateset.rates[rateset.count - 1] & 0x7f; ++ } else if (vwrq->value < rateset.count) { ++ /* Select rate by rateset index */ ++ rate = rateset.rates[vwrq->value] & 0x7f; ++ } else { ++ /* Specified rate in bps */ ++ rate = vwrq->value / 500000; ++ } ++ ++ if (vwrq->fixed) { ++ /* ++ Set rate override, ++ Since the is a/b/g-blind, both a/bg_rate are enforced. ++ */ ++ error_bg = dev_wlc_intvar_set(dev, "bg_rate", rate); ++ error_a = dev_wlc_intvar_set(dev, "a_rate", rate); ++ ++ if (error_bg && error_a) ++ return (error_bg | error_a); ++ } else { ++ /* ++ clear rate override ++ Since the is a/b/g-blind, both a/bg_rate are enforced. ++ */ ++ /* 0 is for clearing rate override */ ++ error_bg = dev_wlc_intvar_set(dev, "bg_rate", 0); ++ /* 0 is for clearing rate override */ ++ error_a = dev_wlc_intvar_set(dev, "a_rate", 0); ++ ++ if (error_bg && error_a) ++ return (error_bg | error_a); ++ ++ /* Remove rates above selected rate */ ++ for (i = 0; i < rateset.count; i++) ++ if ((rateset.rates[i] & 0x7f) > rate) ++ break; ++ rateset.count = htod32(i); ++ ++ /* Set current rateset */ ++ if ((error = dev_wlc_ioctl(dev, WLC_SET_RATESET, &rateset, sizeof(rateset)))) ++ return error; ++ } ++ ++ return 0; ++} ++ ++static int wl_iw_get_rate( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ int error, rate; ++ ++ AP6210_DEBUG("%s: SIOCGIWRATE\n", dev->name); ++ ++ /* Report the current tx rate */ ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate)))) ++ return error; ++ rate = dtoh32(rate); ++ vwrq->value = rate * 500000; ++ ++ return 0; ++} ++ ++static int ++wl_iw_set_rts( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ int error, rts; ++ ++ AP6210_DEBUG("%s: SIOCSIWRTS\n", dev->name); ++ ++ if (vwrq->disabled) ++ rts = DOT11_DEFAULT_RTS_LEN; ++ else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_RTS_LEN) ++ return -EINVAL; ++ else ++ rts = vwrq->value; ++ ++ if ((error = dev_wlc_intvar_set(dev, "rtsthresh", rts))) ++ return error; ++ ++ return 0; ++} ++ ++static int ++wl_iw_get_rts( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ int error, rts; ++ ++ AP6210_DEBUG("%s: SIOCGIWRTS\n", dev->name); ++ ++ if ((error = dev_wlc_intvar_get(dev, "rtsthresh", &rts))) ++ return error; ++ ++ vwrq->value = rts; ++ vwrq->disabled = (rts >= DOT11_DEFAULT_RTS_LEN); ++ vwrq->fixed = 1; ++ ++ return 0; ++} ++ ++static int ++wl_iw_set_frag( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ int error, frag; ++ ++ AP6210_DEBUG("%s: SIOCSIWFRAG\n", dev->name); ++ ++ if (vwrq->disabled) ++ frag = DOT11_DEFAULT_FRAG_LEN; ++ else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_FRAG_LEN) ++ return -EINVAL; ++ else ++ frag = vwrq->value; ++ ++ if ((error = dev_wlc_intvar_set(dev, "fragthresh", frag))) ++ return error; ++ ++ return 0; ++} ++ ++static int ++wl_iw_get_frag( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ int error, fragthreshold; ++ ++ AP6210_DEBUG("%s: SIOCGIWFRAG\n", dev->name); ++ ++ if ((error = dev_wlc_intvar_get(dev, "fragthresh", &fragthreshold))) ++ return error; ++ ++ vwrq->value = fragthreshold; ++ vwrq->disabled = (fragthreshold >= DOT11_DEFAULT_FRAG_LEN); ++ vwrq->fixed = 1; ++ ++ return 0; ++} ++ ++static int ++wl_iw_set_txpow( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ int error, disable; ++ uint16 txpwrmw; ++ AP6210_DEBUG("%s: SIOCSIWTXPOW\n", dev->name); ++ ++ /* Make sure radio is off or on as far as software is concerned */ ++ disable = vwrq->disabled ? WL_RADIO_SW_DISABLE : 0; ++ disable += WL_RADIO_SW_DISABLE << 16; ++ ++ disable = htod32(disable); ++ if ((error = dev_wlc_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable)))) ++ return error; ++ ++ /* If Radio is off, nothing more to do */ ++ if (disable & WL_RADIO_SW_DISABLE) ++ return 0; ++ ++ /* Only handle mW */ ++ if (!(vwrq->flags & IW_TXPOW_MWATT)) ++ return -EINVAL; ++ ++ /* Value < 0 means just "on" or "off" */ ++ if (vwrq->value < 0) ++ return 0; ++ ++ if (vwrq->value > 0xffff) txpwrmw = 0xffff; ++ else txpwrmw = (uint16)vwrq->value; ++ ++ ++ error = dev_wlc_intvar_set(dev, "qtxpower", (int)(bcm_mw_to_qdbm(txpwrmw))); ++ return error; ++} ++ ++static int ++wl_iw_get_txpow( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ int error, disable, txpwrdbm; ++ uint8 result; ++ ++ AP6210_DEBUG("%s: SIOCGIWTXPOW\n", dev->name); ++ ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_RADIO, &disable, sizeof(disable))) || ++ (error = dev_wlc_intvar_get(dev, "qtxpower", &txpwrdbm))) ++ return error; ++ ++ disable = dtoh32(disable); ++ result = (uint8)(txpwrdbm & ~WL_TXPWR_OVERRIDE); ++ vwrq->value = (int32)bcm_qdbm_to_mw(result); ++ vwrq->fixed = 0; ++ vwrq->disabled = (disable & (WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE)) ? 1 : 0; ++ vwrq->flags = IW_TXPOW_MWATT; ++ ++ return 0; ++} ++ ++#if WIRELESS_EXT > 10 ++static int ++wl_iw_set_retry( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ int error, lrl, srl; ++ ++ AP6210_DEBUG("%s: SIOCSIWRETRY\n", dev->name); ++ ++ /* Do not handle "off" or "lifetime" */ ++ if (vwrq->disabled || (vwrq->flags & IW_RETRY_LIFETIME)) ++ return -EINVAL; ++ ++ /* Handle "[min|max] limit" */ ++ if (vwrq->flags & IW_RETRY_LIMIT) { ++ /* "max limit" or just "limit" */ ++#if WIRELESS_EXT > 20 ++ if ((vwrq->flags & IW_RETRY_LONG) ||(vwrq->flags & IW_RETRY_MAX) || ++ !((vwrq->flags & IW_RETRY_SHORT) || (vwrq->flags & IW_RETRY_MIN))) { ++#else ++ if ((vwrq->flags & IW_RETRY_MAX) || !(vwrq->flags & IW_RETRY_MIN)) { ++#endif /* WIRELESS_EXT > 20 */ ++ ++ lrl = htod32(vwrq->value); ++ if ((error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl, sizeof(lrl)))) ++ return error; ++ } ++ /* "min limit" or just "limit" */ ++#if WIRELESS_EXT > 20 ++ if ((vwrq->flags & IW_RETRY_SHORT) ||(vwrq->flags & IW_RETRY_MIN) || ++ !((vwrq->flags & IW_RETRY_LONG) || (vwrq->flags & IW_RETRY_MAX))) { ++#else ++ if ((vwrq->flags & IW_RETRY_MIN) || !(vwrq->flags & IW_RETRY_MAX)) { ++#endif /* WIRELESS_EXT > 20 */ ++ ++ srl = htod32(vwrq->value); ++ if ((error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl, sizeof(srl)))) ++ return error; ++ } ++ } ++ ++ return 0; ++} ++ ++static int ++wl_iw_get_retry( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ int error, lrl, srl; ++ ++ AP6210_DEBUG("%s: SIOCGIWRETRY\n", dev->name); ++ ++ vwrq->disabled = 0; /* Can't be disabled */ ++ ++ /* Do not handle lifetime queries */ ++ if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) ++ return -EINVAL; ++ ++ /* Get retry limits */ ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_LRL, &lrl, sizeof(lrl))) || ++ (error = dev_wlc_ioctl(dev, WLC_GET_SRL, &srl, sizeof(srl)))) ++ return error; ++ ++ lrl = dtoh32(lrl); ++ srl = dtoh32(srl); ++ ++ /* Note : by default, display the min retry number */ ++ if (vwrq->flags & IW_RETRY_MAX) { ++ vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; ++ vwrq->value = lrl; ++ } else { ++ vwrq->flags = IW_RETRY_LIMIT; ++ vwrq->value = srl; ++ if (srl != lrl) ++ vwrq->flags |= IW_RETRY_MIN; ++ } ++ ++ return 0; ++} ++#endif /* WIRELESS_EXT > 10 */ ++ ++static int ++wl_iw_set_encode( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *dwrq, ++ char *extra ++) ++{ ++ wl_wsec_key_t key; ++ int error, val, wsec; ++ ++ AP6210_DEBUG("%s: SIOCSIWENCODE\n", dev->name); ++ ++ memset(&key, 0, sizeof(key)); ++ ++ if ((dwrq->flags & IW_ENCODE_INDEX) == 0) { ++ /* Find the current key */ ++ for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) { ++ val = htod32(key.index); ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val)))) ++ return error; ++ val = dtoh32(val); ++ if (val) ++ break; ++ } ++ /* Default to 0 */ ++ if (key.index == DOT11_MAX_DEFAULT_KEYS) ++ key.index = 0; ++ } else { ++ key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1; ++ if (key.index >= DOT11_MAX_DEFAULT_KEYS) ++ return -EINVAL; ++ } ++ ++ /* Interpret "off" to mean no encryption */ ++ wsec = (dwrq->flags & IW_ENCODE_DISABLED) ? 0 : WEP_ENABLED; ++ ++ if ((error = dev_wlc_intvar_set(dev, "wsec", wsec))) ++ return error; ++ ++ /* Old API used to pass a NULL pointer instead of IW_ENCODE_NOKEY */ ++ if (!extra || !dwrq->length || (dwrq->flags & IW_ENCODE_NOKEY)) { ++ /* Just select a new current key */ ++ val = htod32(key.index); ++ if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, &val, sizeof(val)))) ++ return error; ++ } else { ++ key.len = dwrq->length; ++ ++ if (dwrq->length > sizeof(key.data)) ++ return -EINVAL; ++ ++ memcpy(key.data, extra, dwrq->length); ++ ++ key.flags = WL_PRIMARY_KEY; ++ switch (key.len) { ++ case WEP1_KEY_SIZE: ++ key.algo = CRYPTO_ALGO_WEP1; ++ break; ++ case WEP128_KEY_SIZE: ++ key.algo = CRYPTO_ALGO_WEP128; ++ break; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++ case TKIP_KEY_SIZE: ++ key.algo = CRYPTO_ALGO_TKIP; ++ break; ++#endif ++ case AES_KEY_SIZE: ++ key.algo = CRYPTO_ALGO_AES_CCM; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* Set the new key/index */ ++ swap_key_from_BE(&key); ++ if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)))) ++ return error; ++ } ++ ++ /* Interpret "restricted" to mean shared key authentication */ ++ val = (dwrq->flags & IW_ENCODE_RESTRICTED) ? 1 : 0; ++ val = htod32(val); ++ if ((error = dev_wlc_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val)))) ++ return error; ++ ++ return 0; ++} ++ ++static int ++wl_iw_get_encode( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *dwrq, ++ char *extra ++) ++{ ++ wl_wsec_key_t key; ++ int error, val, wsec, auth; ++ ++ AP6210_DEBUG("%s: SIOCGIWENCODE\n", dev->name); ++ ++ /* assure default values of zero for things we don't touch */ ++ bzero(&key, sizeof(wl_wsec_key_t)); ++ ++ if ((dwrq->flags & IW_ENCODE_INDEX) == 0) { ++ /* Find the current key */ ++ for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) { ++ val = key.index; ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val)))) ++ return error; ++ val = dtoh32(val); ++ if (val) ++ break; ++ } ++ } else ++ key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1; ++ ++ if (key.index >= DOT11_MAX_DEFAULT_KEYS) ++ key.index = 0; ++ ++ /* Get info */ ++ ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec))) || ++ (error = dev_wlc_ioctl(dev, WLC_GET_AUTH, &auth, sizeof(auth)))) ++ return error; ++ ++ swap_key_to_BE(&key); ++ ++ wsec = dtoh32(wsec); ++ auth = dtoh32(auth); ++ /* Get key length */ ++ dwrq->length = MIN(IW_ENCODING_TOKEN_MAX, key.len); ++ ++ /* Get flags */ ++ dwrq->flags = key.index + 1; ++ if (!(wsec & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))) { ++ /* Interpret "off" to mean no encryption */ ++ dwrq->flags |= IW_ENCODE_DISABLED; ++ } ++ if (auth) { ++ /* Interpret "restricted" to mean shared key authentication */ ++ dwrq->flags |= IW_ENCODE_RESTRICTED; ++ } ++ ++ /* Get key */ ++ if (dwrq->length && extra) ++ memcpy(extra, key.data, dwrq->length); ++ ++ return 0; ++} ++ ++static int ++wl_iw_set_power( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ int error, pm; ++ ++ AP6210_DEBUG("%s: SIOCSIWPOWER\n", dev->name); ++ ++ pm = vwrq->disabled ? PM_OFF : PM_MAX; ++ ++ pm = htod32(pm); ++ if ((error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm)))) ++ return error; ++ ++ return 0; ++} ++ ++static int ++wl_iw_get_power( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ int error, pm; ++ ++ AP6210_DEBUG("%s: SIOCGIWPOWER\n", dev->name); ++ ++ if ((error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm)))) ++ return error; ++ ++ pm = dtoh32(pm); ++ vwrq->disabled = pm ? 0 : 1; ++ vwrq->flags = IW_POWER_ALL_R; ++ ++ return 0; ++} ++ ++#if WIRELESS_EXT > 17 ++static int ++wl_iw_set_wpaie( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *iwp, ++ char *extra ++) ++{ ++ dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length); ++ ++ return 0; ++} ++ ++static int ++wl_iw_get_wpaie( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *iwp, ++ char *extra ++) ++{ ++ AP6210_DEBUG("%s: SIOCGIWGENIE\n", dev->name); ++ iwp->length = 64; ++ dev_wlc_bufvar_get(dev, "wpaie", extra, iwp->length); ++ return 0; ++} ++ ++static int ++wl_iw_set_encodeext( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_point *dwrq, ++ char *extra ++) ++{ ++ wl_wsec_key_t key; ++ int error; ++ struct iw_encode_ext *iwe; ++ ++ AP6210_DEBUG("%s: SIOCSIWENCODEEXT\n", dev->name); ++ ++ memset(&key, 0, sizeof(key)); ++ iwe = (struct iw_encode_ext *)extra; ++ ++ /* disable encryption completely */ ++ if (dwrq->flags & IW_ENCODE_DISABLED) { ++ ++ } ++ ++ /* get the key index */ ++ key.index = 0; ++ if (dwrq->flags & IW_ENCODE_INDEX) ++ key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1; ++ ++ key.len = iwe->key_len; ++ ++ /* Instead of bcast for ea address for default wep keys, driver needs it to be Null */ ++ if (!ETHER_ISMULTI(iwe->addr.sa_data)) ++ bcopy((void *)&iwe->addr.sa_data, (char *)&key.ea, ETHER_ADDR_LEN); ++ ++ /* check for key index change */ ++ if (key.len == 0) { ++ if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { ++ AP6210_DEBUG("Changing the the primary Key to %d\n", key.index); ++ /* change the key index .... */ ++ key.index = htod32(key.index); ++ error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, ++ &key.index, sizeof(key.index)); ++ if (error) ++ return error; ++ } ++ /* key delete */ ++ else { ++ swap_key_from_BE(&key); ++ error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)); ++ if (error) ++ return error; ++ } ++ } ++#if (defined(BCMSUP_PSK) && defined(WLFBT)) ++ /* This case is used to allow an external 802.1x supplicant ++ * to pass the PMK to the in-driver supplicant for use in ++ * the 4-way handshake. ++ */ ++ else if (iwe->alg == IW_ENCODE_ALG_PMK) { ++ int j; ++ wsec_pmk_t pmk; ++ char keystring[WSEC_MAX_PSK_LEN + 1]; ++ char* charptr = keystring; ++ uint len; ++ ++ /* copy the raw hex key to the appropriate format */ ++ for (j = 0; j < (WSEC_MAX_PSK_LEN / 2); j++) { ++ sprintf(charptr, "%02x", iwe->key[j]); ++ charptr += 2; ++ } ++ len = strlen(keystring); ++ pmk.key_len = htod16(len); ++ bcopy(keystring, pmk.key, len); ++ pmk.flags = htod16(WSEC_PASSPHRASE); ++ ++ error = dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk)); ++ if (error) ++ return error; ++ } ++#endif /* (defined (BCMSUP_PSK) && defined(WLFBT)) */ ++ ++ else { ++ if (iwe->key_len > sizeof(key.data)) ++ return -EINVAL; ++ ++ AP6210_DEBUG("Setting the key index %d\n", key.index); ++ if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { ++ AP6210_DEBUG("key is a Primary Key\n"); ++ key.flags = WL_PRIMARY_KEY; ++ } ++ ++ bcopy((void *)iwe->key, key.data, iwe->key_len); ++ ++ if (iwe->alg == IW_ENCODE_ALG_TKIP) { ++ uint8 keybuf[8]; ++ bcopy(&key.data[24], keybuf, sizeof(keybuf)); ++ bcopy(&key.data[16], &key.data[24], sizeof(keybuf)); ++ bcopy(keybuf, &key.data[16], sizeof(keybuf)); ++ } ++ ++ /* rx iv */ ++ if (iwe->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { ++ uchar *ivptr; ++ ivptr = (uchar *)iwe->rx_seq; ++ key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) | ++ (ivptr[3] << 8) | ivptr[2]; ++ key.rxiv.lo = (ivptr[1] << 8) | ivptr[0]; ++ key.iv_initialized = TRUE; ++ } ++ ++ switch (iwe->alg) { ++ case IW_ENCODE_ALG_NONE: ++ key.algo = CRYPTO_ALGO_OFF; ++ break; ++ case IW_ENCODE_ALG_WEP: ++ if (iwe->key_len == WEP1_KEY_SIZE) ++ key.algo = CRYPTO_ALGO_WEP1; ++ else ++ key.algo = CRYPTO_ALGO_WEP128; ++ break; ++ case IW_ENCODE_ALG_TKIP: ++ key.algo = CRYPTO_ALGO_TKIP; ++ break; ++ case IW_ENCODE_ALG_CCMP: ++ key.algo = CRYPTO_ALGO_AES_CCM; ++ break; ++ default: ++ break; ++ } ++ swap_key_from_BE(&key); ++ ++ dhd_wait_pend8021x(dev); ++ ++ error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)); ++ if (error) ++ return error; ++ } ++ return 0; ++} ++ ++ ++#if WIRELESS_EXT > 17 ++struct { ++ pmkid_list_t pmkids; ++ pmkid_t foo[MAXPMKID-1]; ++} pmkid_list; ++static int ++wl_iw_set_pmksa( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ struct iw_pmksa *iwpmksa; ++ uint i; ++ char eabuf[ETHER_ADDR_STR_LEN]; ++ pmkid_t * pmkid_array = pmkid_list.pmkids.pmkid; ++ ++ AP6210_DEBUG("%s: SIOCSIWPMKSA\n", dev->name); ++ iwpmksa = (struct iw_pmksa *)extra; ++ bzero((char *)eabuf, ETHER_ADDR_STR_LEN); ++ if (iwpmksa->cmd == IW_PMKSA_FLUSH) { ++ AP6210_DEBUG("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n"); ++ bzero((char *)&pmkid_list, sizeof(pmkid_list)); ++ } ++ if (iwpmksa->cmd == IW_PMKSA_REMOVE) { ++ pmkid_list_t pmkid, *pmkidptr; ++ pmkidptr = &pmkid; ++ bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID, ETHER_ADDR_LEN); ++ bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID, WPA2_PMKID_LEN); ++ { ++ uint j; ++ AP6210_DEBUG("wl_iw_set_pmksa,IW_PMKSA_REMOVE - PMKID: %s = ", ++ bcm_ether_ntoa(&pmkidptr->pmkid[0].BSSID, ++ eabuf)); ++ for (j = 0; j < WPA2_PMKID_LEN; j++) ++ AP6210_DUMP("%02x ", pmkidptr->pmkid[0].PMKID[j]); ++ AP6210_DUMP("\n"); ++ } ++ for (i = 0; i < pmkid_list.pmkids.npmkid; i++) ++ if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_array[i].BSSID, ++ ETHER_ADDR_LEN)) ++ break; ++ for (; i < pmkid_list.pmkids.npmkid; i++) { ++ bcopy(&pmkid_array[i+1].BSSID, ++ &pmkid_array[i].BSSID, ++ ETHER_ADDR_LEN); ++ bcopy(&pmkid_array[i+1].PMKID, ++ &pmkid_array[i].PMKID, ++ WPA2_PMKID_LEN); ++ } ++ pmkid_list.pmkids.npmkid--; ++ } ++ if (iwpmksa->cmd == IW_PMKSA_ADD) { ++ bcopy(&iwpmksa->bssid.sa_data[0], ++ &pmkid_array[pmkid_list.pmkids.npmkid].BSSID, ++ ETHER_ADDR_LEN); ++ bcopy(&iwpmksa->pmkid[0], &pmkid_array[pmkid_list.pmkids.npmkid].PMKID, ++ WPA2_PMKID_LEN); ++ { ++ uint j; ++ uint k; ++ k = pmkid_list.pmkids.npmkid; ++ BCM_REFERENCE(k); ++ AP6210_DEBUG("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ", ++ bcm_ether_ntoa(&pmkid_array[k].BSSID, ++ eabuf)); ++ for (j = 0; j < WPA2_PMKID_LEN; j++) ++ AP6210_DUMP("%02x ", pmkid_array[k].PMKID[j]); ++ AP6210_DUMP("\n"); ++ } ++ pmkid_list.pmkids.npmkid++; ++ } ++ AP6210_DEBUG("PRINTING pmkid LIST - No of elements %d\n", pmkid_list.pmkids.npmkid); ++ for (i = 0; i < pmkid_list.pmkids.npmkid; i++) { ++ uint j; ++ AP6210_DEBUG("PMKID[%d]: %s = ", i, ++ bcm_ether_ntoa(&pmkid_array[i].BSSID, ++ eabuf)); ++ for (j = 0; j < WPA2_PMKID_LEN; j++) ++ AP6210_DUMP("%02x ", pmkid_array[i].PMKID[j]); ++ AP6210_DEBUG("\n"); ++ } ++ AP6210_DEBUG("\n"); ++ dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list, sizeof(pmkid_list)); ++ return 0; ++} ++#endif /* WIRELESS_EXT > 17 */ ++ ++static int ++wl_iw_get_encodeext( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ AP6210_DEBUG("%s: SIOCGIWENCODEEXT\n", dev->name); ++ return 0; ++} ++ ++static int ++wl_iw_set_wpaauth( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ int error = 0; ++ int paramid; ++ int paramval; ++ uint32 cipher_combined; ++ int val = 0; ++ wl_iw_t *iw = IW_DEV_IF(dev); ++ ++ AP6210_DEBUG("%s: SIOCSIWAUTH\n", dev->name); ++ ++ paramid = vwrq->flags & IW_AUTH_INDEX; ++ paramval = vwrq->value; ++ ++ AP6210_DEBUG("%s: SIOCSIWAUTH, paramid = 0x%0x, paramval = 0x%0x\n", ++ dev->name, paramid, paramval); ++ ++ switch (paramid) { ++ ++ case IW_AUTH_WPA_VERSION: ++ /* supported wpa version disabled or wpa or wpa2 */ ++ if (paramval & IW_AUTH_WPA_VERSION_DISABLED) ++ val = WPA_AUTH_DISABLED; ++ else if (paramval & (IW_AUTH_WPA_VERSION_WPA)) ++ val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED; ++ else if (paramval & IW_AUTH_WPA_VERSION_WPA2) ++ val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; ++ AP6210_DEBUG("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val); ++ if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) ++ return error; ++ break; ++ ++ case IW_AUTH_CIPHER_PAIRWISE: ++ case IW_AUTH_CIPHER_GROUP: ++ ++ if (paramid == IW_AUTH_CIPHER_PAIRWISE) { ++ iw->pwsec = paramval; ++ } ++ else { ++ iw->gwsec = paramval; ++ } ++ ++ if ((error = dev_wlc_intvar_get(dev, "wsec", &val))) ++ return error; ++ ++ cipher_combined = iw->gwsec | iw->pwsec; ++ val &= ~(WEP_ENABLED | TKIP_ENABLED | AES_ENABLED); ++ if (cipher_combined & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104)) ++ val |= WEP_ENABLED; ++ if (cipher_combined & IW_AUTH_CIPHER_TKIP) ++ val |= TKIP_ENABLED; ++ if (cipher_combined & IW_AUTH_CIPHER_CCMP) ++ val |= AES_ENABLED; ++ ++ if (iw->privacy_invoked && !val) { ++ AP6210_DEBUG("%s: %s: 'Privacy invoked' TRUE but clearing wsec, assuming " ++ "we're a WPS enrollee\n", dev->name, __FUNCTION__); ++ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) { ++ AP6210_DEBUG("Failed to set iovar is_WPS_enrollee\n"); ++ return error; ++ } ++ } else if (val) { ++ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) { ++ AP6210_DEBUG("Failed to clear iovar is_WPS_enrollee\n"); ++ return error; ++ } ++ } ++ ++ if ((error = dev_wlc_intvar_set(dev, "wsec", val))) ++ return error; ++#ifdef WLFBT ++ if ((paramid == IW_AUTH_CIPHER_PAIRWISE) && (val | AES_ENABLED)) { ++ if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 1))) ++ return error; ++ } ++ else if (val == 0) { ++ if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 0))) ++ return error; ++ } ++#endif /* WLFBT */ ++ break; ++ ++ case IW_AUTH_KEY_MGMT: ++ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) ++ return error; ++ ++ if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { ++ if (paramval & IW_AUTH_KEY_MGMT_PSK) ++ val = WPA_AUTH_PSK; ++ else ++ val = WPA_AUTH_UNSPECIFIED; ++ } ++ else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { ++ if (paramval & IW_AUTH_KEY_MGMT_PSK) ++ val = WPA2_AUTH_PSK; ++ else ++ val = WPA2_AUTH_UNSPECIFIED; ++ } ++ AP6210_DEBUG("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val); ++ if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) ++ return error; ++ break; ++ ++ case IW_AUTH_TKIP_COUNTERMEASURES: ++ dev_wlc_bufvar_set(dev, "tkip_countermeasures", (char *)¶mval, 1); ++ break; ++ ++ case IW_AUTH_80211_AUTH_ALG: ++ /* open shared */ ++ AP6210_ERR("Setting the D11auth %d\n", paramval); ++ if (paramval & IW_AUTH_ALG_OPEN_SYSTEM) ++ val = 0; ++ else if (paramval & IW_AUTH_ALG_SHARED_KEY) ++ val = 1; ++ else ++ error = 1; ++ if (!error && (error = dev_wlc_intvar_set(dev, "auth", val))) ++ return error; ++ break; ++ ++ case IW_AUTH_WPA_ENABLED: ++ if (paramval == 0) { ++ val = 0; ++ AP6210_DEBUG("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val); ++ error = dev_wlc_intvar_set(dev, "wpa_auth", val); ++ return error; ++ } ++ else { ++ /* If WPA is enabled, wpa_auth is set elsewhere */ ++ } ++ break; ++ ++ case IW_AUTH_DROP_UNENCRYPTED: ++ dev_wlc_bufvar_set(dev, "wsec_restrict", (char *)¶mval, 1); ++ break; ++ ++ case IW_AUTH_RX_UNENCRYPTED_EAPOL: ++ dev_wlc_bufvar_set(dev, "rx_unencrypted_eapol", (char *)¶mval, 1); ++ break; ++ ++#if WIRELESS_EXT > 17 ++ ++ case IW_AUTH_ROAMING_CONTROL: ++ AP6210_DEBUG("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__); ++ /* driver control or user space app control */ ++ break; ++ ++ case IW_AUTH_PRIVACY_INVOKED: { ++ int wsec; ++ ++ if (paramval == 0) { ++ iw->privacy_invoked = FALSE; ++ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) { ++ AP6210_DEBUG("Failed to clear iovar is_WPS_enrollee\n"); ++ return error; ++ } ++ } else { ++ iw->privacy_invoked = TRUE; ++ if ((error = dev_wlc_intvar_get(dev, "wsec", &wsec))) ++ return error; ++ ++ if (!WSEC_ENABLED(wsec)) { ++ /* if privacy is true, but wsec is false, we are a WPS enrollee */ ++ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) { ++ AP6210_DEBUG("Failed to set iovar is_WPS_enrollee\n"); ++ return error; ++ } ++ } else { ++ if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) { ++ AP6210_DEBUG("Failed to clear iovar is_WPS_enrollee\n"); ++ return error; ++ } ++ } ++ } ++ break; ++ } ++ ++ ++#endif /* WIRELESS_EXT > 17 */ ++ ++ ++ default: ++ break; ++ } ++ return 0; ++} ++#define VAL_PSK(_val) (((_val) & WPA_AUTH_PSK) || ((_val) & WPA2_AUTH_PSK)) ++ ++static int ++wl_iw_get_wpaauth( ++ struct net_device *dev, ++ struct iw_request_info *info, ++ struct iw_param *vwrq, ++ char *extra ++) ++{ ++ int error; ++ int paramid; ++ int paramval = 0; ++ int val; ++ wl_iw_t *iw = IW_DEV_IF(dev); ++ ++ AP6210_DEBUG("%s: SIOCGIWAUTH\n", dev->name); ++ ++ paramid = vwrq->flags & IW_AUTH_INDEX; ++ ++ switch (paramid) { ++ case IW_AUTH_WPA_VERSION: ++ /* supported wpa version disabled or wpa or wpa2 */ ++ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) ++ return error; ++ if (val & (WPA_AUTH_NONE | WPA_AUTH_DISABLED)) ++ paramval = IW_AUTH_WPA_VERSION_DISABLED; ++ else if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) ++ paramval = IW_AUTH_WPA_VERSION_WPA; ++ else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) ++ paramval = IW_AUTH_WPA_VERSION_WPA2; ++ break; ++ ++ case IW_AUTH_CIPHER_PAIRWISE: ++ paramval = iw->pwsec; ++ break; ++ ++ case IW_AUTH_CIPHER_GROUP: ++ paramval = iw->gwsec; ++ break; ++ ++ case IW_AUTH_KEY_MGMT: ++ /* psk, 1x */ ++ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) ++ return error; ++ if (VAL_PSK(val)) ++ paramval = IW_AUTH_KEY_MGMT_PSK; ++ else ++ paramval = IW_AUTH_KEY_MGMT_802_1X; ++ ++ break; ++ case IW_AUTH_TKIP_COUNTERMEASURES: ++ dev_wlc_bufvar_get(dev, "tkip_countermeasures", (char *)¶mval, 1); ++ break; ++ ++ case IW_AUTH_DROP_UNENCRYPTED: ++ dev_wlc_bufvar_get(dev, "wsec_restrict", (char *)¶mval, 1); ++ break; ++ ++ case IW_AUTH_RX_UNENCRYPTED_EAPOL: ++ dev_wlc_bufvar_get(dev, "rx_unencrypted_eapol", (char *)¶mval, 1); ++ break; ++ ++ case IW_AUTH_80211_AUTH_ALG: ++ /* open, shared, leap */ ++ if ((error = dev_wlc_intvar_get(dev, "auth", &val))) ++ return error; ++ if (!val) ++ paramval = IW_AUTH_ALG_OPEN_SYSTEM; ++ else ++ paramval = IW_AUTH_ALG_SHARED_KEY; ++ break; ++ case IW_AUTH_WPA_ENABLED: ++ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) ++ return error; ++ if (val) ++ paramval = TRUE; ++ else ++ paramval = FALSE; ++ break; ++ ++#if WIRELESS_EXT > 17 ++ ++ case IW_AUTH_ROAMING_CONTROL: ++ AP6210_ERR("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__); ++ /* driver control or user space app control */ ++ break; ++ ++ case IW_AUTH_PRIVACY_INVOKED: ++ paramval = iw->privacy_invoked; ++ break; ++ ++#endif /* WIRELESS_EXT > 17 */ ++ } ++ vwrq->value = paramval; ++ return 0; ++} ++#endif /* WIRELESS_EXT > 17 */ ++ ++static const iw_handler wl_iw_handler[] = ++{ ++ (iw_handler) wl_iw_config_commit, /* SIOCSIWCOMMIT */ ++ (iw_handler) wl_iw_get_name, /* SIOCGIWNAME */ ++ (iw_handler) NULL, /* SIOCSIWNWID */ ++ (iw_handler) NULL, /* SIOCGIWNWID */ ++ (iw_handler) wl_iw_set_freq, /* SIOCSIWFREQ */ ++ (iw_handler) wl_iw_get_freq, /* SIOCGIWFREQ */ ++ (iw_handler) wl_iw_set_mode, /* SIOCSIWMODE */ ++ (iw_handler) wl_iw_get_mode, /* SIOCGIWMODE */ ++ (iw_handler) NULL, /* SIOCSIWSENS */ ++ (iw_handler) NULL, /* SIOCGIWSENS */ ++ (iw_handler) NULL, /* SIOCSIWRANGE */ ++ (iw_handler) wl_iw_get_range, /* SIOCGIWRANGE */ ++ (iw_handler) NULL, /* SIOCSIWPRIV */ ++ (iw_handler) NULL, /* SIOCGIWPRIV */ ++ (iw_handler) NULL, /* SIOCSIWSTATS */ ++ (iw_handler) NULL, /* SIOCGIWSTATS */ ++ (iw_handler) wl_iw_set_spy, /* SIOCSIWSPY */ ++ (iw_handler) wl_iw_get_spy, /* SIOCGIWSPY */ ++ (iw_handler) NULL, /* -- hole -- */ ++ (iw_handler) NULL, /* -- hole -- */ ++ (iw_handler) wl_iw_set_wap, /* SIOCSIWAP */ ++ (iw_handler) wl_iw_get_wap, /* SIOCGIWAP */ ++#if WIRELESS_EXT > 17 ++ (iw_handler) wl_iw_mlme, /* SIOCSIWMLME */ ++#else ++ (iw_handler) NULL, /* -- hole -- */ ++#endif ++ (iw_handler) wl_iw_iscan_get_aplist, /* SIOCGIWAPLIST */ ++#if WIRELESS_EXT > 13 ++ (iw_handler) wl_iw_iscan_set_scan, /* SIOCSIWSCAN */ ++ (iw_handler) wl_iw_iscan_get_scan, /* SIOCGIWSCAN */ ++#else /* WIRELESS_EXT > 13 */ ++ (iw_handler) NULL, /* SIOCSIWSCAN */ ++ (iw_handler) NULL, /* SIOCGIWSCAN */ ++#endif /* WIRELESS_EXT > 13 */ ++ (iw_handler) wl_iw_set_essid, /* SIOCSIWESSID */ ++ (iw_handler) wl_iw_get_essid, /* SIOCGIWESSID */ ++ (iw_handler) wl_iw_set_nick, /* SIOCSIWNICKN */ ++ (iw_handler) wl_iw_get_nick, /* SIOCGIWNICKN */ ++ (iw_handler) NULL, /* -- hole -- */ ++ (iw_handler) NULL, /* -- hole -- */ ++ (iw_handler) wl_iw_set_rate, /* SIOCSIWRATE */ ++ (iw_handler) wl_iw_get_rate, /* SIOCGIWRATE */ ++ (iw_handler) wl_iw_set_rts, /* SIOCSIWRTS */ ++ (iw_handler) wl_iw_get_rts, /* SIOCGIWRTS */ ++ (iw_handler) wl_iw_set_frag, /* SIOCSIWFRAG */ ++ (iw_handler) wl_iw_get_frag, /* SIOCGIWFRAG */ ++ (iw_handler) wl_iw_set_txpow, /* SIOCSIWTXPOW */ ++ (iw_handler) wl_iw_get_txpow, /* SIOCGIWTXPOW */ ++#if WIRELESS_EXT > 10 ++ (iw_handler) wl_iw_set_retry, /* SIOCSIWRETRY */ ++ (iw_handler) wl_iw_get_retry, /* SIOCGIWRETRY */ ++#endif /* WIRELESS_EXT > 10 */ ++ (iw_handler) wl_iw_set_encode, /* SIOCSIWENCODE */ ++ (iw_handler) wl_iw_get_encode, /* SIOCGIWENCODE */ ++ (iw_handler) wl_iw_set_power, /* SIOCSIWPOWER */ ++ (iw_handler) wl_iw_get_power, /* SIOCGIWPOWER */ ++#if WIRELESS_EXT > 17 ++ (iw_handler) NULL, /* -- hole -- */ ++ (iw_handler) NULL, /* -- hole -- */ ++ (iw_handler) wl_iw_set_wpaie, /* SIOCSIWGENIE */ ++ (iw_handler) wl_iw_get_wpaie, /* SIOCGIWGENIE */ ++ (iw_handler) wl_iw_set_wpaauth, /* SIOCSIWAUTH */ ++ (iw_handler) wl_iw_get_wpaauth, /* SIOCGIWAUTH */ ++ (iw_handler) wl_iw_set_encodeext, /* SIOCSIWENCODEEXT */ ++ (iw_handler) wl_iw_get_encodeext, /* SIOCGIWENCODEEXT */ ++ (iw_handler) wl_iw_set_pmksa, /* SIOCSIWPMKSA */ ++#endif /* WIRELESS_EXT > 17 */ ++}; ++ ++#if WIRELESS_EXT > 12 ++enum { ++ WL_IW_SET_LEDDC = SIOCIWFIRSTPRIV, ++ WL_IW_SET_VLANMODE, ++ WL_IW_SET_PM ++}; ++ ++static iw_handler wl_iw_priv_handler[] = { ++ wl_iw_set_leddc, ++ wl_iw_set_vlanmode, ++ wl_iw_set_pm ++}; ++ ++static struct iw_priv_args wl_iw_priv_args[] = { ++ { ++ WL_IW_SET_LEDDC, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ++ 0, ++ "set_leddc" ++ }, ++ { ++ WL_IW_SET_VLANMODE, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ++ 0, ++ "set_vlanmode" ++ }, ++ { ++ WL_IW_SET_PM, ++ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ++ 0, ++ "set_pm" ++ } ++}; ++ ++const struct iw_handler_def wl_iw_handler_def = ++{ ++ .num_standard = ARRAYSIZE(wl_iw_handler), ++ .num_private = ARRAY_SIZE(wl_iw_priv_handler), ++ .num_private_args = ARRAY_SIZE(wl_iw_priv_args), ++ .standard = (iw_handler *) wl_iw_handler, ++ .private = wl_iw_priv_handler, ++ .private_args = wl_iw_priv_args, ++#if WIRELESS_EXT >= 19 ++ get_wireless_stats: dhd_get_wireless_stats, ++#endif /* WIRELESS_EXT >= 19 */ ++ }; ++#endif /* WIRELESS_EXT > 12 */ ++ ++int ++wl_iw_ioctl( ++ struct net_device *dev, ++ struct ifreq *rq, ++ int cmd ++) ++{ ++ struct iwreq *wrq = (struct iwreq *) rq; ++ struct iw_request_info info; ++ iw_handler handler; ++ char *extra = NULL; ++ size_t token_size = 1; ++ int max_tokens = 0, ret = 0; ++ ++ if (cmd < SIOCIWFIRST || ++ IW_IOCTL_IDX(cmd) >= ARRAYSIZE(wl_iw_handler) || ++ !(handler = wl_iw_handler[IW_IOCTL_IDX(cmd)])) ++ return -EOPNOTSUPP; ++ ++ switch (cmd) { ++ ++ case SIOCSIWESSID: ++ case SIOCGIWESSID: ++ case SIOCSIWNICKN: ++ case SIOCGIWNICKN: ++ max_tokens = IW_ESSID_MAX_SIZE + 1; ++ break; ++ ++ case SIOCSIWENCODE: ++ case SIOCGIWENCODE: ++#if WIRELESS_EXT > 17 ++ case SIOCSIWENCODEEXT: ++ case SIOCGIWENCODEEXT: ++#endif ++ max_tokens = IW_ENCODING_TOKEN_MAX; ++ break; ++ ++ case SIOCGIWRANGE: ++ max_tokens = sizeof(struct iw_range); ++ break; ++ ++ case SIOCGIWAPLIST: ++ token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality); ++ max_tokens = IW_MAX_AP; ++ break; ++ ++#if WIRELESS_EXT > 13 ++ case SIOCGIWSCAN: ++ if (g_iscan) ++ max_tokens = wrq->u.data.length; ++ else ++ max_tokens = IW_SCAN_MAX_DATA; ++ break; ++#endif /* WIRELESS_EXT > 13 */ ++ ++ case SIOCSIWSPY: ++ token_size = sizeof(struct sockaddr); ++ max_tokens = IW_MAX_SPY; ++ break; ++ ++ case SIOCGIWSPY: ++ token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality); ++ max_tokens = IW_MAX_SPY; ++ break; ++ default: ++ break; ++ } ++ ++ if (max_tokens && wrq->u.data.pointer) { ++ if (wrq->u.data.length > max_tokens) ++ return -E2BIG; ++ ++ if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL))) ++ return -ENOMEM; ++ ++ if (copy_from_user(extra, wrq->u.data.pointer, wrq->u.data.length * token_size)) { ++ kfree(extra); ++ return -EFAULT; ++ } ++ } ++ ++ info.cmd = cmd; ++ info.flags = 0; ++ ++ ret = handler(dev, &info, &wrq->u, extra); ++ ++ if (extra) { ++ if (copy_to_user(wrq->u.data.pointer, extra, wrq->u.data.length * token_size)) { ++ kfree(extra); ++ return -EFAULT; ++ } ++ ++ kfree(extra); ++ } ++ ++ return ret; ++} ++ ++/* Convert a connection status event into a connection status string. ++ * Returns TRUE if a matching connection status string was found. ++ */ ++bool ++wl_iw_conn_status_str(uint32 event_type, uint32 status, uint32 reason, ++ char* stringBuf, uint buflen) ++{ ++ typedef struct conn_fail_event_map_t { ++ uint32 inEvent; /* input: event type to match */ ++ uint32 inStatus; /* input: event status code to match */ ++ uint32 inReason; /* input: event reason code to match */ ++ const char* outName; /* output: failure type */ ++ const char* outCause; /* output: failure cause */ ++ } conn_fail_event_map_t; ++ ++ /* Map of WLC_E events to connection failure strings */ ++# define WL_IW_DONT_CARE 9999 ++ const conn_fail_event_map_t event_map [] = { ++ /* inEvent inStatus inReason */ ++ /* outName outCause */ ++ {WLC_E_SET_SSID, WLC_E_STATUS_SUCCESS, WL_IW_DONT_CARE, ++ "Conn", "Success"}, ++ {WLC_E_SET_SSID, WLC_E_STATUS_NO_NETWORKS, WL_IW_DONT_CARE, ++ "Conn", "NoNetworks"}, ++ {WLC_E_SET_SSID, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE, ++ "Conn", "ConfigMismatch"}, ++ {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_PRUNE_ENCR_MISMATCH, ++ "Conn", "EncrypMismatch"}, ++ {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_RSN_MISMATCH, ++ "Conn", "RsnMismatch"}, ++ {WLC_E_AUTH, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE, ++ "Conn", "AuthTimeout"}, ++ {WLC_E_AUTH, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE, ++ "Conn", "AuthFail"}, ++ {WLC_E_AUTH, WLC_E_STATUS_NO_ACK, WL_IW_DONT_CARE, ++ "Conn", "AuthNoAck"}, ++ {WLC_E_REASSOC, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE, ++ "Conn", "ReassocFail"}, ++ {WLC_E_REASSOC, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE, ++ "Conn", "ReassocTimeout"}, ++ {WLC_E_REASSOC, WLC_E_STATUS_ABORT, WL_IW_DONT_CARE, ++ "Conn", "ReassocAbort"}, ++ {WLC_E_PSK_SUP, WLC_SUP_KEYED, WL_IW_DONT_CARE, ++ "Sup", "ConnSuccess"}, ++ {WLC_E_PSK_SUP, WL_IW_DONT_CARE, WL_IW_DONT_CARE, ++ "Sup", "WpaHandshakeFail"}, ++ {WLC_E_DEAUTH_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE, ++ "Conn", "Deauth"}, ++ {WLC_E_DISASSOC_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE, ++ "Conn", "DisassocInd"}, ++ {WLC_E_DISASSOC, WL_IW_DONT_CARE, WL_IW_DONT_CARE, ++ "Conn", "Disassoc"} ++ }; ++ ++ const char* name = ""; ++ const char* cause = NULL; ++ int i; ++ ++ /* Search the event map table for a matching event */ ++ for (i = 0; i < sizeof(event_map)/sizeof(event_map[0]); i++) { ++ const conn_fail_event_map_t* row = &event_map[i]; ++ if (row->inEvent == event_type && ++ (row->inStatus == status || row->inStatus == WL_IW_DONT_CARE) && ++ (row->inReason == reason || row->inReason == WL_IW_DONT_CARE)) { ++ name = row->outName; ++ cause = row->outCause; ++ break; ++ } ++ } ++ ++ /* If found, generate a connection failure string and return TRUE */ ++ if (cause) { ++ memset(stringBuf, 0, buflen); ++ snprintf(stringBuf, buflen, "%s %s %02d %02d", ++ name, cause, status, reason); ++ AP6210_DEBUG("Connection status: %s\n", stringBuf); ++ return TRUE; ++ } else { ++ return FALSE; ++ } ++} ++ ++#if (WIRELESS_EXT > 14) ++/* Check if we have received an event that indicates connection failure ++ * If so, generate a connection failure report string. ++ * The caller supplies a buffer to hold the generated string. ++ */ ++static bool ++wl_iw_check_conn_fail(wl_event_msg_t *e, char* stringBuf, uint buflen) ++{ ++ uint32 event = ntoh32(e->event_type); ++ uint32 status = ntoh32(e->status); ++ uint32 reason = ntoh32(e->reason); ++ ++ if (wl_iw_conn_status_str(event, status, reason, stringBuf, buflen)) { ++ return TRUE; ++ } else ++ { ++ return FALSE; ++ } ++} ++#endif /* WIRELESS_EXT > 14 */ ++ ++#ifndef IW_CUSTOM_MAX ++#define IW_CUSTOM_MAX 256 /* size of extra buffer used for translation of events */ ++#endif /* IW_CUSTOM_MAX */ ++ ++void ++wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) ++{ ++#if WIRELESS_EXT > 13 ++ union iwreq_data wrqu; ++ char extra[IW_CUSTOM_MAX + 1]; ++ int cmd = 0; ++ uint32 event_type = ntoh32(e->event_type); ++ uint16 flags = ntoh16(e->flags); ++ uint32 datalen = ntoh32(e->datalen); ++ uint32 status = ntoh32(e->status); ++ ++ memset(&wrqu, 0, sizeof(wrqu)); ++ memset(extra, 0, sizeof(extra)); ++ ++ memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN); ++ wrqu.addr.sa_family = ARPHRD_ETHER; ++ ++ switch (event_type) { ++ case WLC_E_TXFAIL: ++ cmd = IWEVTXDROP; ++ break; ++#if WIRELESS_EXT > 14 ++ case WLC_E_JOIN: ++ case WLC_E_ASSOC_IND: ++ case WLC_E_REASSOC_IND: ++ cmd = IWEVREGISTERED; ++ break; ++ case WLC_E_DEAUTH_IND: ++ case WLC_E_DISASSOC_IND: ++ cmd = SIOCGIWAP; ++ wrqu.data.length = strlen(extra); ++ bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); ++ bzero(&extra, ETHER_ADDR_LEN); ++ break; ++ ++ case WLC_E_LINK: ++ case WLC_E_NDIS_LINK: ++ cmd = SIOCGIWAP; ++ wrqu.data.length = strlen(extra); ++ if (!(flags & WLC_EVENT_MSG_LINK)) { ++ bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); ++ bzero(&extra, ETHER_ADDR_LEN); ++ } ++ break; ++ case WLC_E_ACTION_FRAME: ++ cmd = IWEVCUSTOM; ++ if (datalen + 1 <= sizeof(extra)) { ++ wrqu.data.length = datalen + 1; ++ extra[0] = WLC_E_ACTION_FRAME; ++ memcpy(&extra[1], data, datalen); ++ AP6210_DEBUG("WLC_E_ACTION_FRAME len %d \n", wrqu.data.length); ++ } ++ break; ++ ++ case WLC_E_ACTION_FRAME_COMPLETE: ++ cmd = IWEVCUSTOM; ++ if (sizeof(status) + 1 <= sizeof(extra)) { ++ wrqu.data.length = sizeof(status) + 1; ++ extra[0] = WLC_E_ACTION_FRAME_COMPLETE; ++ memcpy(&extra[1], &status, sizeof(status)); ++ AP6210_DEBUG("wl_iw_event status %d \n", status); ++ } ++ break; ++#endif /* WIRELESS_EXT > 14 */ ++#if WIRELESS_EXT > 17 ++ case WLC_E_MIC_ERROR: { ++ struct iw_michaelmicfailure *micerrevt = (struct iw_michaelmicfailure *)&extra; ++ cmd = IWEVMICHAELMICFAILURE; ++ wrqu.data.length = sizeof(struct iw_michaelmicfailure); ++ if (flags & WLC_EVENT_MSG_GROUP) ++ micerrevt->flags |= IW_MICFAILURE_GROUP; ++ else ++ micerrevt->flags |= IW_MICFAILURE_PAIRWISE; ++ memcpy(micerrevt->src_addr.sa_data, &e->addr, ETHER_ADDR_LEN); ++ micerrevt->src_addr.sa_family = ARPHRD_ETHER; ++ ++ break; ++ } ++ ++ case WLC_E_ASSOC_REQ_IE: ++ cmd = IWEVASSOCREQIE; ++ wrqu.data.length = datalen; ++ if (datalen < sizeof(extra)) ++ memcpy(extra, data, datalen); ++ break; ++ ++ case WLC_E_ASSOC_RESP_IE: ++ cmd = IWEVASSOCRESPIE; ++ wrqu.data.length = datalen; ++ if (datalen < sizeof(extra)) ++ memcpy(extra, data, datalen); ++ break; ++ ++ case WLC_E_PMKID_CACHE: { ++ struct iw_pmkid_cand *iwpmkidcand = (struct iw_pmkid_cand *)&extra; ++ pmkid_cand_list_t *pmkcandlist; ++ pmkid_cand_t *pmkidcand; ++ int count; ++ ++ if (data == NULL) ++ break; ++ ++ cmd = IWEVPMKIDCAND; ++ pmkcandlist = data; ++ count = ntoh32_ua((uint8 *)&pmkcandlist->npmkid_cand); ++ wrqu.data.length = sizeof(struct iw_pmkid_cand); ++ pmkidcand = pmkcandlist->pmkid_cand; ++ while (count) { ++ bzero(iwpmkidcand, sizeof(struct iw_pmkid_cand)); ++ if (pmkidcand->preauth) ++ iwpmkidcand->flags |= IW_PMKID_CAND_PREAUTH; ++ bcopy(&pmkidcand->BSSID, &iwpmkidcand->bssid.sa_data, ++ ETHER_ADDR_LEN); ++ wireless_send_event(dev, cmd, &wrqu, extra); ++ pmkidcand++; ++ count--; ++ } ++ break; ++ } ++#endif /* WIRELESS_EXT > 17 */ ++ ++ case WLC_E_SCAN_COMPLETE: ++#if WIRELESS_EXT > 14 ++ cmd = SIOCGIWSCAN; ++#endif ++ AP6210_DEBUG("event WLC_E_SCAN_COMPLETE\n"); ++ if ((g_iscan) && (g_iscan->sysioc_pid >= 0) && ++ (g_iscan->iscan_state != ISCAN_STATE_IDLE)) ++ up(&g_iscan->sysioc_sem); ++ break; ++ ++ default: ++ /* Cannot translate event */ ++ break; ++ } ++ ++ if (cmd) { ++ if (cmd == SIOCGIWSCAN) ++ wireless_send_event(dev, cmd, &wrqu, NULL); ++ else ++ wireless_send_event(dev, cmd, &wrqu, extra); ++ } ++ ++#if WIRELESS_EXT > 14 ++ /* Look for WLC events that indicate a connection failure. ++ * If found, generate an IWEVCUSTOM event. ++ */ ++ memset(extra, 0, sizeof(extra)); ++ if (wl_iw_check_conn_fail(e, extra, sizeof(extra))) { ++ cmd = IWEVCUSTOM; ++ wrqu.data.length = strlen(extra); ++ wireless_send_event(dev, cmd, &wrqu, extra); ++ } ++#endif /* WIRELESS_EXT > 14 */ ++ ++#endif /* WIRELESS_EXT > 13 */ ++} ++ ++int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats) ++{ ++ int res = 0; ++ wl_cnt_t cnt; ++ int phy_noise; ++ int rssi; ++ scb_val_t scb_val; ++ ++ phy_noise = 0; ++ if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise)))) ++ goto done; ++ ++ phy_noise = dtoh32(phy_noise); ++ AP6210_DEBUG("wl_iw_get_wireless_stats phy noise=%d\n *****", phy_noise); ++ ++ scb_val.val = 0; ++ if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)))) ++ goto done; ++ ++ rssi = dtoh32(scb_val.val); ++ AP6210_DEBUG("wl_iw_get_wireless_stats rssi=%d ****** \n", rssi); ++ if (rssi <= WL_IW_RSSI_NO_SIGNAL) ++ wstats->qual.qual = 0; ++ else if (rssi <= WL_IW_RSSI_VERY_LOW) ++ wstats->qual.qual = 1; ++ else if (rssi <= WL_IW_RSSI_LOW) ++ wstats->qual.qual = 2; ++ else if (rssi <= WL_IW_RSSI_GOOD) ++ wstats->qual.qual = 3; ++ else if (rssi <= WL_IW_RSSI_VERY_GOOD) ++ wstats->qual.qual = 4; ++ else ++ wstats->qual.qual = 5; ++ ++ /* Wraps to 0 if RSSI is 0 */ ++ wstats->qual.level = 0x100 + rssi; ++ wstats->qual.noise = 0x100 + phy_noise; ++#if WIRELESS_EXT > 18 ++ wstats->qual.updated |= (IW_QUAL_ALL_UPDATED | IW_QUAL_DBM); ++#else ++ wstats->qual.updated |= 7; ++#endif /* WIRELESS_EXT > 18 */ ++ ++#if WIRELESS_EXT > 11 ++ AP6210_DEBUG("wl_iw_get_wireless_stats counters=%d\n *****", (int)sizeof(wl_cnt_t)); ++ ++ memset(&cnt, 0, sizeof(wl_cnt_t)); ++ res = dev_wlc_bufvar_get(dev, "counters", (char *)&cnt, sizeof(wl_cnt_t)); ++ if (res) ++ { ++ AP6210_ERR("wl_iw_get_wireless_stats counters failed error=%d ****** \n", res); ++ goto done; ++ } ++ ++ cnt.version = dtoh16(cnt.version); ++ if (cnt.version != WL_CNT_T_VERSION) { ++ AP6210_DEBUG("\tIncorrect version of counters struct: expected %d; got %d\n", ++ WL_CNT_T_VERSION, cnt.version); ++ goto done; ++ } ++ ++ wstats->discard.nwid = 0; ++ wstats->discard.code = dtoh32(cnt.rxundec); ++ wstats->discard.fragment = dtoh32(cnt.rxfragerr); ++ wstats->discard.retries = dtoh32(cnt.txfail); ++ wstats->discard.misc = dtoh32(cnt.rxrunt) + dtoh32(cnt.rxgiant); ++ wstats->miss.beacon = 0; ++ ++ AP6210_DEBUG("wl_iw_get_wireless_stats counters txframe=%d txbyte=%d\n", ++ dtoh32(cnt.txframe), dtoh32(cnt.txbyte)); ++ AP6210_DEBUG("wl_iw_get_wireless_stats counters rxfrmtoolong=%d\n", dtoh32(cnt.rxfrmtoolong)); ++ AP6210_DEBUG("wl_iw_get_wireless_stats counters rxbadplcp=%d\n", dtoh32(cnt.rxbadplcp)); ++ AP6210_DEBUG("wl_iw_get_wireless_stats counters rxundec=%d\n", dtoh32(cnt.rxundec)); ++ AP6210_DEBUG("wl_iw_get_wireless_stats counters rxfragerr=%d\n", dtoh32(cnt.rxfragerr)); ++ AP6210_DEBUG("wl_iw_get_wireless_stats counters txfail=%d\n", dtoh32(cnt.txfail)); ++ AP6210_DEBUG("wl_iw_get_wireless_stats counters rxrunt=%d\n", dtoh32(cnt.rxrunt)); ++ AP6210_DEBUG("wl_iw_get_wireless_stats counters rxgiant=%d\n", dtoh32(cnt.rxgiant)); ++ ++#endif /* WIRELESS_EXT > 11 */ ++ ++done: ++ return res; ++} ++ ++static void ++wl_iw_timerfunc(ulong data) ++{ ++ iscan_info_t *iscan = (iscan_info_t *)data; ++ iscan->timer_on = 0; ++ if (iscan->iscan_state != ISCAN_STATE_IDLE) { ++ AP6210_DEBUG("timer trigger\n"); ++ up(&iscan->sysioc_sem); ++ } ++} ++ ++static void ++wl_iw_set_event_mask(struct net_device *dev) ++{ ++ char eventmask[WL_EVENTING_MASK_LEN]; ++ char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ ++ ++ dev_iw_iovar_getbuf(dev, "event_msgs", "", 0, iovbuf, sizeof(iovbuf)); ++ bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN); ++ setbit(eventmask, WLC_E_SCAN_COMPLETE); ++ dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, ++ iovbuf, sizeof(iovbuf)); ++ ++} ++ ++static int ++wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid) ++{ ++ int err = 0; ++ ++ memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN); ++ params->bss_type = DOT11_BSSTYPE_ANY; ++ params->scan_type = 0; ++ params->nprobes = -1; ++ params->active_time = -1; ++ params->passive_time = -1; ++ params->home_time = -1; ++ params->channel_num = 0; ++ ++ params->nprobes = htod32(params->nprobes); ++ params->active_time = htod32(params->active_time); ++ params->passive_time = htod32(params->passive_time); ++ params->home_time = htod32(params->home_time); ++ if (ssid && ssid->SSID_len) ++ memcpy(¶ms->ssid, ssid, sizeof(wlc_ssid_t)); ++ ++ return err; ++} ++ ++static int ++wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action) ++{ ++ int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)); ++ wl_iscan_params_t *params; ++ int err = 0; ++ ++ if (ssid && ssid->SSID_len) { ++ params_size += sizeof(wlc_ssid_t); ++ } ++ params = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL); ++ if (params == NULL) { ++ return -ENOMEM; ++ } ++ memset(params, 0, params_size); ++ ASSERT(params_size < WLC_IOCTL_SMLEN); ++ ++ err = wl_iw_iscan_prep(¶ms->params, ssid); ++ ++ if (!err) { ++ params->version = htod32(ISCAN_REQ_VERSION); ++ params->action = htod16(action); ++ params->scan_duration = htod16(0); ++ ++ /* params_size += OFFSETOF(wl_iscan_params_t, params); */ ++ (void) dev_iw_iovar_setbuf(iscan->dev, "iscan", params, params_size, ++ iscan->ioctlbuf, WLC_IOCTL_SMLEN); ++ } ++ ++ kfree(params); ++ return err; ++} ++ ++static uint32 ++wl_iw_iscan_get(iscan_info_t *iscan) ++{ ++ iscan_buf_t * buf; ++ iscan_buf_t * ptr; ++ wl_iscan_results_t * list_buf; ++ wl_iscan_results_t list; ++ wl_scan_results_t *results; ++ uint32 status; ++ ++ /* buffers are allocated on demand */ ++ if (iscan->list_cur) { ++ buf = iscan->list_cur; ++ iscan->list_cur = buf->next; ++ } ++ else { ++ buf = kmalloc(sizeof(iscan_buf_t), GFP_KERNEL); ++ if (!buf) ++ return WL_SCAN_RESULTS_ABORTED; ++ buf->next = NULL; ++ if (!iscan->list_hdr) ++ iscan->list_hdr = buf; ++ else { ++ ptr = iscan->list_hdr; ++ while (ptr->next) { ++ ptr = ptr->next; ++ } ++ ptr->next = buf; ++ } ++ } ++ memset(buf->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN); ++ list_buf = (wl_iscan_results_t*)buf->iscan_buf; ++ results = &list_buf->results; ++ results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE; ++ results->version = 0; ++ results->count = 0; ++ ++ memset(&list, 0, sizeof(list)); ++ list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN); ++ (void) dev_iw_iovar_getbuf( ++ iscan->dev, ++ "iscanresults", ++ &list, ++ WL_ISCAN_RESULTS_FIXED_SIZE, ++ buf->iscan_buf, ++ WLC_IW_ISCAN_MAXLEN); ++ results->buflen = dtoh32(results->buflen); ++ results->version = dtoh32(results->version); ++ results->count = dtoh32(results->count); ++ AP6210_DEBUG("results->count = %d\n", results->count); ++ ++ AP6210_DEBUG("results->buflen = %d\n", results->buflen); ++ status = dtoh32(list_buf->status); ++ return status; ++} ++ ++static void wl_iw_send_scan_complete(iscan_info_t *iscan) ++{ ++ union iwreq_data wrqu; ++ ++ memset(&wrqu, 0, sizeof(wrqu)); ++ ++ /* wext expects to get no data for SIOCGIWSCAN Event */ ++ wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL); ++} ++ ++static int ++_iscan_sysioc_thread(void *data) ++{ ++ uint32 status; ++ iscan_info_t *iscan = (iscan_info_t *)data; ++ ++ DAEMONIZE("iscan_sysioc"); ++ ++ status = WL_SCAN_RESULTS_PARTIAL; ++ while (down_interruptible(&iscan->sysioc_sem) == 0) { ++ if (iscan->timer_on) { ++ del_timer(&iscan->timer); ++ iscan->timer_on = 0; ++ } ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ rtnl_lock(); ++#endif ++ status = wl_iw_iscan_get(iscan); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ rtnl_unlock(); ++#endif ++ ++ switch (status) { ++ case WL_SCAN_RESULTS_PARTIAL: ++ AP6210_DEBUG("iscanresults incomplete\n"); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ rtnl_lock(); ++#endif ++ /* make sure our buffer size is enough before going next round */ ++ wl_iw_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++ rtnl_unlock(); ++#endif ++ /* Reschedule the timer */ ++ iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms); ++ add_timer(&iscan->timer); ++ iscan->timer_on = 1; ++ break; ++ case WL_SCAN_RESULTS_SUCCESS: ++ AP6210_DEBUG("iscanresults complete\n"); ++ iscan->iscan_state = ISCAN_STATE_IDLE; ++ wl_iw_send_scan_complete(iscan); ++ break; ++ case WL_SCAN_RESULTS_PENDING: ++ AP6210_DEBUG("iscanresults pending\n"); ++ /* Reschedule the timer */ ++ iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms); ++ add_timer(&iscan->timer); ++ iscan->timer_on = 1; ++ break; ++ case WL_SCAN_RESULTS_ABORTED: ++ AP6210_DEBUG("iscanresults aborted\n"); ++ iscan->iscan_state = ISCAN_STATE_IDLE; ++ wl_iw_send_scan_complete(iscan); ++ break; ++ default: ++ AP6210_DEBUG("iscanresults returned unknown status %d\n", status); ++ break; ++ } ++ } ++ complete_and_exit(&iscan->sysioc_exited, 0); ++} ++ ++int ++wl_iw_attach(struct net_device *dev, void * dhdp) ++{ ++ iscan_info_t *iscan = NULL; ++ ++ if (!dev) ++ return 0; ++ ++ iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL); ++ if (!iscan) ++ return -ENOMEM; ++ memset(iscan, 0, sizeof(iscan_info_t)); ++ iscan->sysioc_pid = -1; ++ /* we only care about main interface so save a global here */ ++ g_iscan = iscan; ++ iscan->dev = dev; ++ iscan->iscan_state = ISCAN_STATE_IDLE; ++ ++ ++ /* Set up the timer */ ++ iscan->timer_ms = 2000; ++ init_timer(&iscan->timer); ++ iscan->timer.data = (ulong)iscan; ++ iscan->timer.function = wl_iw_timerfunc; ++ ++ sema_init(&iscan->sysioc_sem, 0); ++ init_completion(&iscan->sysioc_exited); ++ iscan->sysioc_pid = kernel_thread(_iscan_sysioc_thread, iscan, 0); ++ if (iscan->sysioc_pid < 0) ++ return -ENOMEM; ++ return 0; ++} ++ ++void wl_iw_detach(void) ++{ ++ iscan_buf_t *buf; ++ iscan_info_t *iscan = g_iscan; ++ if (!iscan) ++ return; ++ if (iscan->sysioc_pid >= 0) { ++ KILL_PROC(iscan->sysioc_pid, SIGTERM); ++ wait_for_completion(&iscan->sysioc_exited); ++ } ++ ++ while (iscan->list_hdr) { ++ buf = iscan->list_hdr->next; ++ kfree(iscan->list_hdr); ++ iscan->list_hdr = buf; ++ } ++ kfree(iscan); ++ g_iscan = NULL; ++} ++ ++#endif /* USE_IW */ +diff --git a/drivers/net/wireless/ap6210/wl_iw.h b/drivers/net/wireless/ap6210/wl_iw.h +new file mode 100755 +index 0000000..c675a56 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/wl_iw.h +@@ -0,0 +1,161 @@ ++/* ++ * Linux Wireless Extensions support ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: wl_iw.h 291086 2011-10-21 01:17:24Z $ ++ */ ++ ++#ifndef _wl_iw_h_ ++#define _wl_iw_h_ ++ ++#include ++ ++#include ++#include ++#include ++ ++#define WL_SCAN_PARAMS_SSID_MAX 10 ++#define GET_SSID "SSID=" ++#define GET_CHANNEL "CH=" ++#define GET_NPROBE "NPROBE=" ++#define GET_ACTIVE_ASSOC_DWELL "ACTIVE=" ++#define GET_PASSIVE_ASSOC_DWELL "PASSIVE=" ++#define GET_HOME_DWELL "HOME=" ++#define GET_SCAN_TYPE "TYPE=" ++ ++#define BAND_GET_CMD "GETBAND" ++#define BAND_SET_CMD "SETBAND" ++#define DTIM_SKIP_GET_CMD "DTIMSKIPGET" ++#define DTIM_SKIP_SET_CMD "DTIMSKIPSET" ++#define SETSUSPEND_CMD "SETSUSPENDOPT" ++#define PNOSSIDCLR_SET_CMD "PNOSSIDCLR" ++/* Lin - Is the extra space needed? */ ++#define PNOSETUP_SET_CMD "PNOSETUP " /* TLV command has extra end space */ ++#define PNOENABLE_SET_CMD "PNOFORCE" ++#define PNODEBUG_SET_CMD "PNODEBUG" ++#define TXPOWER_SET_CMD "TXPOWER" ++ ++#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] ++#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" ++ ++/* Structure to keep global parameters */ ++typedef struct wl_iw_extra_params { ++ int target_channel; /* target channel */ ++} wl_iw_extra_params_t; ++ ++struct cntry_locales_custom { ++ char iso_abbrev[WLC_CNTRY_BUF_SZ]; /* ISO 3166-1 country abbreviation */ ++ char custom_locale[WLC_CNTRY_BUF_SZ]; /* Custom firmware locale */ ++ int32 custom_locale_rev; /* Custom local revisin default -1 */ ++}; ++/* ============================================== */ ++/* Defines from wlc_pub.h */ ++#define WL_IW_RSSI_MINVAL -200 /* Low value, e.g. for forcing roam */ ++#define WL_IW_RSSI_NO_SIGNAL -91 /* NDIS RSSI link quality cutoffs */ ++#define WL_IW_RSSI_VERY_LOW -80 /* Very low quality cutoffs */ ++#define WL_IW_RSSI_LOW -70 /* Low quality cutoffs */ ++#define WL_IW_RSSI_GOOD -68 /* Good quality cutoffs */ ++#define WL_IW_RSSI_VERY_GOOD -58 /* Very good quality cutoffs */ ++#define WL_IW_RSSI_EXCELLENT -57 /* Excellent quality cutoffs */ ++#define WL_IW_RSSI_INVALID 0 /* invalid RSSI value */ ++#define MAX_WX_STRING 80 ++#define SSID_FMT_BUF_LEN ((4 * 32) + 1) ++#define isprint(c) bcm_isprint(c) ++#define WL_IW_SET_ACTIVE_SCAN (SIOCIWFIRSTPRIV+1) ++#define WL_IW_GET_RSSI (SIOCIWFIRSTPRIV+3) ++#define WL_IW_SET_PASSIVE_SCAN (SIOCIWFIRSTPRIV+5) ++#define WL_IW_GET_LINK_SPEED (SIOCIWFIRSTPRIV+7) ++#define WL_IW_GET_CURR_MACADDR (SIOCIWFIRSTPRIV+9) ++#define WL_IW_SET_STOP (SIOCIWFIRSTPRIV+11) ++#define WL_IW_SET_START (SIOCIWFIRSTPRIV+13) ++ ++#define G_SCAN_RESULTS 8*1024 ++#define WE_ADD_EVENT_FIX 0x80 ++#define G_WLAN_SET_ON 0 ++#define G_WLAN_SET_OFF 1 ++ ++ ++typedef struct wl_iw { ++ char nickname[IW_ESSID_MAX_SIZE]; ++ ++ struct iw_statistics wstats; ++ ++ int spy_num; ++ uint32 pwsec; /* pairwise wsec setting */ ++ uint32 gwsec; /* group wsec setting */ ++ bool privacy_invoked; /* IW_AUTH_PRIVACY_INVOKED setting */ ++ struct ether_addr spy_addr[IW_MAX_SPY]; ++ struct iw_quality spy_qual[IW_MAX_SPY]; ++ void *wlinfo; ++} wl_iw_t; ++ ++struct wl_ctrl { ++ struct timer_list *timer; ++ struct net_device *dev; ++ long sysioc_pid; ++ struct semaphore sysioc_sem; ++ struct completion sysioc_exited; ++}; ++ ++ ++#if WIRELESS_EXT > 12 ++#include ++extern const struct iw_handler_def wl_iw_handler_def; ++#endif /* WIRELESS_EXT > 12 */ ++ ++extern int wl_iw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); ++extern void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data); ++extern int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats); ++int wl_iw_attach(struct net_device *dev, void * dhdp); ++int wl_iw_send_priv_event(struct net_device *dev, char *flag); ++ ++void wl_iw_detach(void); ++ ++#define CSCAN_COMMAND "CSCAN " ++#define CSCAN_TLV_PREFIX 'S' ++#define CSCAN_TLV_VERSION 1 ++#define CSCAN_TLV_SUBVERSION 0 ++#define CSCAN_TLV_TYPE_SSID_IE 'S' ++#define CSCAN_TLV_TYPE_CHANNEL_IE 'C' ++#define CSCAN_TLV_TYPE_NPROBE_IE 'N' ++#define CSCAN_TLV_TYPE_ACTIVE_IE 'A' ++#define CSCAN_TLV_TYPE_PASSIVE_IE 'P' ++#define CSCAN_TLV_TYPE_HOME_IE 'H' ++#define CSCAN_TLV_TYPE_STYPE_IE 'T' ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) ++#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \ ++ iwe_stream_add_event(info, stream, ends, iwe, extra) ++#define IWE_STREAM_ADD_VALUE(info, event, value, ends, iwe, event_len) \ ++ iwe_stream_add_value(info, event, value, ends, iwe, event_len) ++#define IWE_STREAM_ADD_POINT(info, stream, ends, iwe, extra) \ ++ iwe_stream_add_point(info, stream, ends, iwe, extra) ++#else ++#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \ ++ iwe_stream_add_event(stream, ends, iwe, extra) ++#define IWE_STREAM_ADD_VALUE(info, event, value, ends, iwe, event_len) \ ++ iwe_stream_add_value(event, value, ends, iwe, event_len) ++#define IWE_STREAM_ADD_POINT(info, stream, ends, iwe, extra) \ ++ iwe_stream_add_point(stream, ends, iwe, extra) ++#endif ++ ++#endif /* _wl_iw_h_ */ +diff --git a/drivers/net/wireless/ap6210/wl_linux_mon.c b/drivers/net/wireless/ap6210/wl_linux_mon.c +new file mode 100755 +index 0000000..3210664 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/wl_linux_mon.c +@@ -0,0 +1,422 @@ ++/* ++ * Broadcom Dongle Host Driver (DHD), Linux monitor network interface ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: dhd_linux_mon.c 280623 2011-08-30 14:49:39Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++typedef enum monitor_states ++{ ++ MONITOR_STATE_DEINIT = 0x0, ++ MONITOR_STATE_INIT = 0x1, ++ MONITOR_STATE_INTERFACE_ADDED = 0x2, ++ MONITOR_STATE_INTERFACE_DELETED = 0x4 ++} monitor_states_t; ++int dhd_add_monitor(char *name, struct net_device **new_ndev); ++extern int dhd_start_xmit(struct sk_buff *skb, struct net_device *net); ++int dhd_del_monitor(struct net_device *ndev); ++int dhd_monitor_init(void *dhd_pub); ++int dhd_monitor_uninit(void); ++ ++/** ++ * Local declarations and defintions (not exposed) ++ */ ++#ifndef DHD_MAX_IFS ++#define DHD_MAX_IFS 16 ++#endif ++ ++typedef struct monitor_interface { ++ int radiotap_enabled; ++ struct net_device* real_ndev; /* The real interface that the monitor is on */ ++ struct net_device* mon_ndev; ++} monitor_interface; ++ ++typedef struct dhd_linux_monitor { ++ void *dhd_pub; ++ monitor_states_t monitor_state; ++ monitor_interface mon_if[DHD_MAX_IFS]; ++ struct mutex lock; /* lock to protect mon_if */ ++} dhd_linux_monitor_t; ++ ++static dhd_linux_monitor_t g_monitor; ++ ++static struct net_device* lookup_real_netdev(char *name); ++static monitor_interface* ndev_to_monif(struct net_device *ndev); ++static int dhd_mon_if_open(struct net_device *ndev); ++static int dhd_mon_if_stop(struct net_device *ndev); ++static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *ndev); ++static void dhd_mon_if_set_multicast_list(struct net_device *ndev); ++static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr); ++ ++static const struct net_device_ops dhd_mon_if_ops = { ++ .ndo_open = dhd_mon_if_open, ++ .ndo_stop = dhd_mon_if_stop, ++ .ndo_start_xmit = dhd_mon_if_subif_start_xmit, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) ++ .ndo_set_rx_mode = dhd_mon_if_set_multicast_list, ++#else ++ .ndo_set_multicast_list = dhd_mon_if_set_multicast_list, ++#endif ++ .ndo_set_mac_address = dhd_mon_if_change_mac, ++}; ++ ++/** ++ * Local static function defintions ++ */ ++ ++/* Look up dhd's net device table to find a match (e.g. interface "eth0" is a match for "mon.eth0" ++ * "p2p-eth0-0" is a match for "mon.p2p-eth0-0") ++ */ ++static struct net_device* lookup_real_netdev(char *name) ++{ ++ struct net_device *ndev_found = NULL; ++ ++ int i; ++ int len = 0; ++ int last_name_len = 0; ++ struct net_device *ndev; ++ ++ /* We need to find interface "p2p-p2p-0" corresponding to monitor interface "mon-p2p-0", ++ * Once mon iface name reaches IFNAMSIZ, it is reset to p2p0-0 and corresponding mon ++ * iface would be mon-p2p0-0. ++ */ ++ for (i = 0; i < DHD_MAX_IFS; i++) { ++ ndev = dhd_idx2net(g_monitor.dhd_pub, i); ++ ++ /* Skip "p2p" and look for "-p2p0-x" in monitor interface name. If it ++ * it matches, then this netdev is the corresponding real_netdev. ++ */ ++ if (ndev && strstr(ndev->name, "p2p-p2p0")) { ++ len = strlen("p2p"); ++ } else { ++ /* if p2p- is not present, then the IFNAMSIZ have reached and name ++ * would have got reset. In this casse,look for p2p0-x in mon-p2p0-x ++ */ ++ len = 0; ++ } ++ if (ndev && strstr(name, (ndev->name + len))) { ++ if (strlen(ndev->name) > last_name_len) { ++ ndev_found = ndev; ++ last_name_len = strlen(ndev->name); ++ } ++ } ++ } ++ ++ return ndev_found; ++} ++ ++static monitor_interface* ndev_to_monif(struct net_device *ndev) ++{ ++ int i; ++ ++ for (i = 0; i < DHD_MAX_IFS; i++) { ++ if (g_monitor.mon_if[i].mon_ndev == ndev) ++ return &g_monitor.mon_if[i]; ++ } ++ ++ return NULL; ++} ++ ++static int dhd_mon_if_open(struct net_device *ndev) ++{ ++ int ret = 0; ++ ++ AP6210_DEBUG("enter\n"); ++ return ret; ++} ++ ++static int dhd_mon_if_stop(struct net_device *ndev) ++{ ++ int ret = 0; ++ ++ AP6210_DEBUG("enter\n"); ++ return ret; ++} ++ ++static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *ndev) ++{ ++ int ret = 0; ++ int rtap_len; ++ int qos_len = 0; ++ int dot11_hdr_len = 24; ++ int snap_len = 6; ++ unsigned char *pdata; ++ unsigned short frame_ctl; ++ unsigned char src_mac_addr[6]; ++ unsigned char dst_mac_addr[6]; ++ struct ieee80211_hdr *dot11_hdr; ++ struct ieee80211_radiotap_header *rtap_hdr; ++ monitor_interface* mon_if; ++ ++ AP6210_DEBUG("enter\n"); ++ ++ mon_if = ndev_to_monif(ndev); ++ if (mon_if == NULL || mon_if->real_ndev == NULL) { ++ AP6210_DEBUG(" cannot find matched net dev, skip the packet\n"); ++ goto fail; ++ } ++ ++ if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) ++ goto fail; ++ ++ rtap_hdr = (struct ieee80211_radiotap_header *)skb->data; ++ if (unlikely(rtap_hdr->it_version)) ++ goto fail; ++ ++ rtap_len = ieee80211_get_radiotap_len(skb->data); ++ if (unlikely(skb->len < rtap_len)) ++ goto fail; ++ ++ AP6210_DEBUG("radiotap len (should be 14): %d\n", rtap_len); ++ ++ /* Skip the ratio tap header */ ++ skb_pull(skb, rtap_len); ++ ++ dot11_hdr = (struct ieee80211_hdr *)skb->data; ++ frame_ctl = le16_to_cpu(dot11_hdr->frame_control); ++ /* Check if the QoS bit is set */ ++ if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) { ++ /* Check if this ia a Wireless Distribution System (WDS) frame ++ * which has 4 MAC addresses ++ */ ++ if (dot11_hdr->frame_control & 0x0080) ++ qos_len = 2; ++ if ((dot11_hdr->frame_control & 0x0300) == 0x0300) ++ dot11_hdr_len += 6; ++ ++ memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr)); ++ memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr)); ++ ++ /* Skip the 802.11 header, QoS (if any) and SNAP, but leave spaces for ++ * for two MAC addresses ++ */ ++ skb_pull(skb, dot11_hdr_len + qos_len + snap_len - sizeof(src_mac_addr) * 2); ++ pdata = (unsigned char*)skb->data; ++ memcpy(pdata, dst_mac_addr, sizeof(dst_mac_addr)); ++ memcpy(pdata + sizeof(dst_mac_addr), src_mac_addr, sizeof(src_mac_addr)); ++ PKTSETPRIO(skb, 0); ++ ++ AP6210_DEBUG("if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name); ++ ++ /* Use the real net device to transmit the packet */ ++ ret = dhd_start_xmit(skb, mon_if->real_ndev); ++ ++ return ret; ++ } ++fail: ++ dev_kfree_skb(skb); ++ return 0; ++} ++ ++static void dhd_mon_if_set_multicast_list(struct net_device *ndev) ++{ ++ monitor_interface* mon_if; ++ ++ mon_if = ndev_to_monif(ndev); ++ if (mon_if == NULL || mon_if->real_ndev == NULL) { ++ AP6210_DEBUG(" cannot find matched net dev, skip the packet\n"); ++ } else { ++ AP6210_DEBUG("enter, if name: %s, matched if name %s\n", ++ ndev->name, mon_if->real_ndev->name); ++ } ++} ++ ++static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr) ++{ ++ int ret = 0; ++ monitor_interface* mon_if; ++ ++ mon_if = ndev_to_monif(ndev); ++ if (mon_if == NULL || mon_if->real_ndev == NULL) { ++ AP6210_DEBUG(" cannot find matched net dev, skip the packet\n"); ++ } else { ++ AP6210_DEBUG("enter, if name: %s, matched if name %s\n", ++ ndev->name, mon_if->real_ndev->name); ++ } ++ return ret; ++} ++ ++/** ++ * Global function definitions (declared in dhd_linux_mon.h) ++ */ ++ ++int dhd_add_monitor(char *name, struct net_device **new_ndev) ++{ ++ int i; ++ int idx = -1; ++ int ret = 0; ++ struct net_device* ndev = NULL; ++ dhd_linux_monitor_t **dhd_mon; ++ ++ mutex_lock(&g_monitor.lock); ++ ++ AP6210_DEBUG("enter, if name: %s\n", name); ++ if (!name || !new_ndev) { ++ AP6210_DEBUG("invalid parameters\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* ++ * Find a vacancy ++ */ ++ for (i = 0; i < DHD_MAX_IFS; i++) ++ if (g_monitor.mon_if[i].mon_ndev == NULL) { ++ idx = i; ++ break; ++ } ++ if (idx == -1) { ++ AP6210_DEBUG("exceeds maximum interfaces\n"); ++ ret = -EFAULT; ++ goto out; ++ } ++ ++ ndev = alloc_etherdev(sizeof(dhd_linux_monitor_t*)); ++ if (!ndev) { ++ AP6210_DEBUG("failed to allocate memory\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ ndev->type = ARPHRD_IEEE80211_RADIOTAP; ++ strncpy(ndev->name, name, IFNAMSIZ); ++ ndev->name[IFNAMSIZ - 1] = 0; ++ ndev->netdev_ops = &dhd_mon_if_ops; ++ ++ ret = register_netdevice(ndev); ++ if (ret) { ++ AP6210_DEBUG(" register_netdevice failed (%d)\n", ret); ++ goto out; ++ } ++ ++ *new_ndev = ndev; ++ g_monitor.mon_if[idx].radiotap_enabled = TRUE; ++ g_monitor.mon_if[idx].mon_ndev = ndev; ++ g_monitor.mon_if[idx].real_ndev = lookup_real_netdev(name); ++ dhd_mon = (dhd_linux_monitor_t **)netdev_priv(ndev); ++ *dhd_mon = &g_monitor; ++ g_monitor.monitor_state = MONITOR_STATE_INTERFACE_ADDED; ++ AP6210_DEBUG("net device returned: 0x%p\n", ndev); ++ AP6210_DEBUG("found a matched net device, name %s\n", g_monitor.mon_if[idx].real_ndev->name); ++ ++out: ++ if (ret && ndev) ++ free_netdev(ndev); ++ ++ mutex_unlock(&g_monitor.lock); ++ return ret; ++ ++} ++ ++int dhd_del_monitor(struct net_device *ndev) ++{ ++ int i; ++ bool rollback_lock = false; ++ if (!ndev) ++ return -EINVAL; ++ mutex_lock(&g_monitor.lock); ++ for (i = 0; i < DHD_MAX_IFS; i++) { ++ if (g_monitor.mon_if[i].mon_ndev == ndev || ++ g_monitor.mon_if[i].real_ndev == ndev) { ++ g_monitor.mon_if[i].real_ndev = NULL; ++ if (rtnl_is_locked()) { ++ rtnl_unlock(); ++ rollback_lock = true; ++ } ++ unregister_netdev(g_monitor.mon_if[i].mon_ndev); ++ free_netdev(g_monitor.mon_if[i].mon_ndev); ++ g_monitor.mon_if[i].mon_ndev = NULL; ++ g_monitor.monitor_state = MONITOR_STATE_INTERFACE_DELETED; ++ break; ++ } ++ } ++ if (rollback_lock) { ++ rtnl_lock(); ++ rollback_lock = false; ++ } ++ ++ if (g_monitor.monitor_state != ++ MONITOR_STATE_INTERFACE_DELETED) ++ AP6210_DEBUG("interface not found in monitor IF array, is this a monitor IF? 0x%p\n", ++ ndev); ++ mutex_unlock(&g_monitor.lock); ++ ++ return 0; ++} ++ ++int dhd_monitor_init(void *dhd_pub) ++{ ++ if (g_monitor.monitor_state == MONITOR_STATE_DEINIT) { ++ g_monitor.dhd_pub = dhd_pub; ++ mutex_init(&g_monitor.lock); ++ g_monitor.monitor_state = MONITOR_STATE_INIT; ++ } ++ return 0; ++} ++ ++int dhd_monitor_uninit(void) ++{ ++ int i; ++ struct net_device *ndev; ++ bool rollback_lock = false; ++ mutex_lock(&g_monitor.lock); ++ if (g_monitor.monitor_state != MONITOR_STATE_DEINIT) { ++ for (i = 0; i < DHD_MAX_IFS; i++) { ++ ndev = g_monitor.mon_if[i].mon_ndev; ++ if (ndev) { ++ if (rtnl_is_locked()) { ++ rtnl_unlock(); ++ rollback_lock = true; ++ } ++ unregister_netdev(ndev); ++ free_netdev(ndev); ++ g_monitor.mon_if[i].real_ndev = NULL; ++ g_monitor.mon_if[i].mon_ndev = NULL; ++ if (rollback_lock) { ++ rtnl_lock(); ++ rollback_lock = false; ++ } ++ } ++ } ++ g_monitor.monitor_state = MONITOR_STATE_DEINIT; ++ } ++ mutex_unlock(&g_monitor.lock); ++ return 0; ++} +diff --git a/drivers/net/wireless/ap6210/wldev_common.c b/drivers/net/wireless/ap6210/wldev_common.c +new file mode 100755 +index 0000000..596e448 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/wldev_common.c +@@ -0,0 +1,374 @@ ++/* ++ * Common function shared by Linux WEXT, cfg80211 and p2p drivers ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: wldev_common.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 $ ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++ ++#define htod32(i) i ++#define htod16(i) i ++#define dtoh32(i) i ++#define dtoh16(i) i ++#define htodchanspec(i) i ++#define dtohchanspec(i) i ++ ++extern int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd); ++ ++s32 wldev_ioctl( ++ struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set) ++{ ++ s32 ret = 0; ++ struct wl_ioctl ioc; ++ ++ ++ memset(&ioc, 0, sizeof(ioc)); ++ ioc.cmd = cmd; ++ ioc.buf = arg; ++ ioc.len = len; ++ ioc.set = set; ++ ++ ret = dhd_ioctl_entry_local(dev, &ioc, cmd); ++ ++ return ret; ++} ++ ++/* Format a iovar buffer, not bsscfg indexed. The bsscfg index will be ++ * taken care of in dhd_ioctl_entry. Internal use only, not exposed to ++ * wl_iw, wl_cfg80211 and wl_cfgp2p ++ */ ++static s32 wldev_mkiovar( ++ s8 *iovar_name, s8 *param, s32 paramlen, ++ s8 *iovar_buf, u32 buflen) ++{ ++ s32 iolen = 0; ++ ++ iolen = bcm_mkiovar(iovar_name, param, paramlen, iovar_buf, buflen); ++ return iolen; ++} ++ ++s32 wldev_iovar_getbuf( ++ struct net_device *dev, s8 *iovar_name, ++ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) ++{ ++ s32 ret = 0; ++ if (buf_sync) { ++ mutex_lock(buf_sync); ++ } ++ wldev_mkiovar(iovar_name, param, paramlen, buf, buflen); ++ ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE); ++ if (buf_sync) ++ mutex_unlock(buf_sync); ++ return ret; ++} ++ ++ ++s32 wldev_iovar_setbuf( ++ struct net_device *dev, s8 *iovar_name, ++ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) ++{ ++ s32 ret = 0; ++ s32 iovar_len; ++ if (buf_sync) { ++ mutex_lock(buf_sync); ++ } ++ iovar_len = wldev_mkiovar(iovar_name, param, paramlen, buf, buflen); ++ if (iovar_len > 0) ++ ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE); ++ else ++ ret = BCME_BUFTOOSHORT; ++ if (buf_sync) ++ mutex_unlock(buf_sync); ++ return ret; ++} ++ ++s32 wldev_iovar_setint( ++ struct net_device *dev, s8 *iovar, s32 val) ++{ ++ s8 iovar_buf[WLC_IOCTL_SMLEN]; ++ ++ val = htod32(val); ++ memset(iovar_buf, 0, sizeof(iovar_buf)); ++ return wldev_iovar_setbuf(dev, iovar, &val, sizeof(val), iovar_buf, ++ sizeof(iovar_buf), NULL); ++} ++ ++ ++s32 wldev_iovar_getint( ++ struct net_device *dev, s8 *iovar, s32 *pval) ++{ ++ s8 iovar_buf[WLC_IOCTL_SMLEN]; ++ s32 err; ++ ++ memset(iovar_buf, 0, sizeof(iovar_buf)); ++ err = wldev_iovar_getbuf(dev, iovar, pval, sizeof(*pval), iovar_buf, ++ sizeof(iovar_buf), NULL); ++ if (err == 0) ++ { ++ memcpy(pval, iovar_buf, sizeof(*pval)); ++ *pval = dtoh32(*pval); ++ } ++ return err; ++} ++ ++/** Format a bsscfg indexed iovar buffer. The bsscfg index will be ++ * taken care of in dhd_ioctl_entry. Internal use only, not exposed to ++ * wl_iw, wl_cfg80211 and wl_cfgp2p ++ */ ++s32 wldev_mkiovar_bsscfg( ++ const s8 *iovar_name, s8 *param, s32 paramlen, ++ s8 *iovar_buf, s32 buflen, s32 bssidx) ++{ ++ const s8 *prefix = "bsscfg:"; ++ s8 *p; ++ u32 prefixlen; ++ u32 namelen; ++ u32 iolen; ++ ++ if (bssidx == 0) { ++ return wldev_mkiovar((s8*)iovar_name, (s8 *)param, paramlen, ++ (s8 *) iovar_buf, buflen); ++ } ++ ++ prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */ ++ namelen = (u32) strlen(iovar_name) + 1; /* lengh of iovar name + null */ ++ iolen = prefixlen + namelen + sizeof(u32) + paramlen; ++ ++ if (buflen < 0 || iolen > (u32)buflen) ++ { ++ AP6210_ERR("%s: buffer is too short\n", __FUNCTION__); ++ return BCME_BUFTOOSHORT; ++ } ++ ++ p = (s8 *)iovar_buf; ++ ++ /* copy prefix, no null */ ++ memcpy(p, prefix, prefixlen); ++ p += prefixlen; ++ ++ /* copy iovar name including null */ ++ memcpy(p, iovar_name, namelen); ++ p += namelen; ++ ++ /* bss config index as first param */ ++ bssidx = htod32(bssidx); ++ memcpy(p, &bssidx, sizeof(u32)); ++ p += sizeof(u32); ++ ++ /* parameter buffer follows */ ++ if (paramlen) ++ memcpy(p, param, paramlen); ++ ++ return iolen; ++ ++} ++ ++s32 wldev_iovar_getbuf_bsscfg( ++ struct net_device *dev, s8 *iovar_name, ++ void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync) ++{ ++ s32 ret = 0; ++ if (buf_sync) { ++ mutex_lock(buf_sync); ++ } ++ ++ wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx); ++ ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE); ++ if (buf_sync) { ++ mutex_unlock(buf_sync); ++ } ++ return ret; ++ ++} ++ ++s32 wldev_iovar_setbuf_bsscfg( ++ struct net_device *dev, s8 *iovar_name, ++ void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync) ++{ ++ s32 ret = 0; ++ s32 iovar_len; ++ if (buf_sync) { ++ mutex_lock(buf_sync); ++ } ++ iovar_len = wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx); ++ if (iovar_len > 0) ++ ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE); ++ else { ++ ret = BCME_BUFTOOSHORT; ++ } ++ ++ if (buf_sync) { ++ mutex_unlock(buf_sync); ++ } ++ return ret; ++} ++ ++s32 wldev_iovar_setint_bsscfg( ++ struct net_device *dev, s8 *iovar, s32 val, s32 bssidx) ++{ ++ s8 iovar_buf[WLC_IOCTL_SMLEN]; ++ ++ val = htod32(val); ++ memset(iovar_buf, 0, sizeof(iovar_buf)); ++ return wldev_iovar_setbuf_bsscfg(dev, iovar, &val, sizeof(val), iovar_buf, ++ sizeof(iovar_buf), bssidx, NULL); ++} ++ ++ ++s32 wldev_iovar_getint_bsscfg( ++ struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx) ++{ ++ s8 iovar_buf[WLC_IOCTL_SMLEN]; ++ s32 err; ++ ++ memset(iovar_buf, 0, sizeof(iovar_buf)); ++ err = wldev_iovar_getbuf_bsscfg(dev, iovar, pval, sizeof(*pval), iovar_buf, ++ sizeof(iovar_buf), bssidx, NULL); ++ if (err == 0) ++ { ++ memcpy(pval, iovar_buf, sizeof(*pval)); ++ *pval = dtoh32(*pval); ++ } ++ return err; ++} ++ ++int wldev_get_link_speed( ++ struct net_device *dev, int *plink_speed) ++{ ++ int error; ++ ++ if (!plink_speed) ++ return -ENOMEM; ++ error = wldev_ioctl(dev, WLC_GET_RATE, plink_speed, sizeof(int), 0); ++ if (unlikely(error)) ++ return error; ++ ++ /* Convert internal 500Kbps to Kbps */ ++ *plink_speed *= 500; ++ return error; ++} ++ ++int wldev_get_rssi( ++ struct net_device *dev, int *prssi) ++{ ++ scb_val_t scb_val; ++ int error; ++ ++ if (!prssi) ++ return -ENOMEM; ++ bzero(&scb_val, sizeof(scb_val_t)); ++ ++ error = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t), 0); ++ if (unlikely(error)) ++ return error; ++ ++ *prssi = dtoh32(scb_val.val); ++ return error; ++} ++ ++int wldev_get_ssid( ++ struct net_device *dev, wlc_ssid_t *pssid) ++{ ++ int error; ++ ++ if (!pssid) ++ return -ENOMEM; ++ error = wldev_ioctl(dev, WLC_GET_SSID, pssid, sizeof(wlc_ssid_t), 0); ++ if (unlikely(error)) ++ return error; ++ pssid->SSID_len = dtoh32(pssid->SSID_len); ++ return error; ++} ++ ++int wldev_get_band( ++ struct net_device *dev, uint *pband) ++{ ++ int error; ++ ++ error = wldev_ioctl(dev, WLC_GET_BAND, pband, sizeof(uint), 0); ++ return error; ++} ++ ++int wldev_set_band( ++ struct net_device *dev, uint band) ++{ ++ int error = -1; ++ ++ if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) { ++ error = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true); ++ if (!error) ++ dhd_bus_band_set(dev, band); ++ } ++ return error; ++} ++ ++int wldev_set_country( ++ struct net_device *dev, char *country_code) ++{ ++ int error = -1; ++ wl_country_t cspec = {{0}, 0, {0}}; ++ scb_val_t scbval; ++ char smbuf[WLC_IOCTL_SMLEN]; ++ ++ if (!country_code) ++ return error; ++ ++ error = wldev_iovar_getbuf(dev, "country", &cspec, sizeof(cspec), ++ smbuf, sizeof(smbuf), NULL); ++ if (error < 0) ++ AP6210_ERR("%s: get country failed = %d\n", __FUNCTION__, error); ++ ++ if ((error < 0) || ++ (strncmp(country_code, smbuf, WLC_CNTRY_BUF_SZ) != 0)) { ++ bzero(&scbval, sizeof(scb_val_t)); ++ error = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true); ++ if (error < 0) { ++ AP6210_ERR("%s: set country failed due to Disassoc error %d\n", ++ __FUNCTION__, error); ++ return error; ++ } ++ cspec.rev = -1; ++ memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ); ++ memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ); ++ get_customized_country_code((char *)&cspec.country_abbrev, &cspec); ++ error = wldev_iovar_setbuf(dev, "country", &cspec, sizeof(cspec), ++ smbuf, sizeof(smbuf), NULL); ++ if (error < 0) { ++ AP6210_ERR("%s: set country for %s as %s rev %d failed\n", ++ __FUNCTION__, country_code, cspec.ccode, cspec.rev); ++ return error; ++ } ++ dhd_bus_country_set(dev, &cspec); ++ AP6210_ERR("%s: set country for %s as %s rev %d\n", ++ __FUNCTION__, country_code, cspec.ccode, cspec.rev); ++ } ++ return 0; ++} +diff --git a/drivers/net/wireless/ap6210/wldev_common.h b/drivers/net/wireless/ap6210/wldev_common.h +new file mode 100755 +index 0000000..f9bf425 +--- /dev/null ++++ b/drivers/net/wireless/ap6210/wldev_common.h +@@ -0,0 +1,111 @@ ++/* ++ * Common function shared by Linux WEXT, cfg80211 and p2p drivers ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: wldev_common.h,v 1.1.4.1.2.14 2011-02-09 01:40:07 $ ++ */ ++#ifndef __WLDEV_COMMON_H__ ++#define __WLDEV_COMMON_H__ ++ ++#include ++ ++/* wl_dev_ioctl - get/set IOCTLs, will call net_device's do_ioctl (or ++ * netdev_ops->ndo_do_ioctl in new kernels) ++ * @dev: the net_device handle ++ */ ++s32 wldev_ioctl( ++ struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set); ++ ++/** Retrieve named IOVARs, this function calls wl_dev_ioctl with ++ * WLC_GET_VAR IOCTL code ++ */ ++s32 wldev_iovar_getbuf( ++ struct net_device *dev, s8 *iovar_name, ++ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync); ++ ++/** Set named IOVARs, this function calls wl_dev_ioctl with ++ * WLC_SET_VAR IOCTL code ++ */ ++s32 wldev_iovar_setbuf( ++ struct net_device *dev, s8 *iovar_name, ++ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync); ++ ++s32 wldev_iovar_setint( ++ struct net_device *dev, s8 *iovar, s32 val); ++ ++s32 wldev_iovar_getint( ++ struct net_device *dev, s8 *iovar, s32 *pval); ++ ++/** The following function can be implemented if there is a need for bsscfg ++ * indexed IOVARs ++ */ ++ ++s32 wldev_mkiovar_bsscfg( ++ const s8 *iovar_name, s8 *param, s32 paramlen, ++ s8 *iovar_buf, s32 buflen, s32 bssidx); ++ ++/** Retrieve named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with ++ * WLC_GET_VAR IOCTL code ++ */ ++s32 wldev_iovar_getbuf_bsscfg( ++ struct net_device *dev, s8 *iovar_name, void *param, s32 paramlen, ++ void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync); ++ ++/** Set named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with ++ * WLC_SET_VAR IOCTL code ++ */ ++s32 wldev_iovar_setbuf_bsscfg( ++ struct net_device *dev, s8 *iovar_name, void *param, s32 paramlen, ++ void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync); ++ ++s32 wldev_iovar_getint_bsscfg( ++ struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx); ++ ++s32 wldev_iovar_setint_bsscfg( ++ struct net_device *dev, s8 *iovar, s32 val, s32 bssidx); ++ ++extern void get_customized_country_code(char *country_iso_code, wl_country_t *cspec); ++extern void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec); ++extern void dhd_bus_band_set(struct net_device *dev, uint band); ++extern int wldev_set_country(struct net_device *dev, char *country_code); ++extern int net_os_wake_lock(struct net_device *dev); ++extern int net_os_wake_unlock(struct net_device *dev); ++extern int net_os_wake_lock_timeout(struct net_device *dev); ++extern int net_os_wake_lock_timeout_enable(struct net_device *dev, int val); ++extern int net_os_set_dtim_skip(struct net_device *dev, int val); ++extern int net_os_set_suspend_disable(struct net_device *dev, int val); ++extern int net_os_set_suspend(struct net_device *dev, int val, int force); ++extern int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, ++ int max, int *bytes_left); ++ ++/* Get the link speed from dongle, speed is in kpbs */ ++int wldev_get_link_speed(struct net_device *dev, int *plink_speed); ++ ++int wldev_get_rssi(struct net_device *dev, int *prssi); ++ ++int wldev_get_ssid(struct net_device *dev, wlc_ssid_t *pssid); ++ ++int wldev_get_band(struct net_device *dev, uint *pband); ++ ++int wldev_set_band(struct net_device *dev, uint band); ++ ++#endif /* __WLDEV_COMMON_H__ */ +-- +1.9.1 + diff --git a/patch/kernel/builddeb-fixed-udoo b/patch/kernel/builddeb-fixed-udoo new file mode 100644 index 000000000..d6b844de3 --- /dev/null +++ b/patch/kernel/builddeb-fixed-udoo @@ -0,0 +1,429 @@ +#!/bin/sh +# +# builddeb 1.3 +# Copyright 2003 Wichert Akkerman +# +# Simple script to generate a deb package for a Linux kernel. All the +# complexity of what to do with a kernel after it is installed or removed +# is left to other scripts and packages: they can install scripts in the +# /etc/kernel/{pre,post}{inst,rm}.d/ directories (or an alternative location +# specified in KDEB_HOOKDIR) that will be called on package install and +# removal. + +set -e + +create_package() { + local pname="$1" pdir="$2" + + cp debian/copyright "$pdir/usr/share/doc/$pname/" + cp debian/changelog "$pdir/usr/share/doc/$pname/changelog.Debian" + gzip -9 "$pdir/usr/share/doc/$pname/changelog.Debian" + sh -c "cd '$pdir'; find . -type f ! -path './DEBIAN/*' -printf '%P\0' \ + | xargs -r0 md5sum > DEBIAN/md5sums" + + # Fix ownership and permissions + chown -R root:root "$pdir" + chmod -R go-w "$pdir" + + # Attempt to find the correct Debian architecture + local forcearch="" debarch="" + case "$UTS_MACHINE" in + i386|ia64|alpha) + debarch="$UTS_MACHINE" ;; + x86_64) + debarch=amd64 ;; + sparc*) + debarch=sparc ;; + s390*) + debarch=s390$(grep -q CONFIG_64BIT=y $KCONFIG_CONFIG && echo x || true) ;; + ppc*) + debarch=$(grep -q CPU_LITTLE_ENDIAN=y $KCONFIG_CONFIG && echo ppc64el || echo powerpc) ;; + parisc*) + debarch=hppa ;; + mips*) + debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y $KCONFIG_CONFIG && echo el || true) ;; + arm64) + debarch=arm64 ;; + arm*) + debarch=arm$(grep -q CONFIG_AEABI=y $KCONFIG_CONFIG && echo el || true) ;; + *) + echo "" >&2 + echo "** ** ** WARNING ** ** **" >&2 + echo "" >&2 + echo "Your architecture doesn't have it's equivalent" >&2 + echo "Debian userspace architecture defined!" >&2 + echo "Falling back to using your current userspace instead!" >&2 + echo "Please add support for $UTS_MACHINE to ${0} ..." >&2 + echo "" >&2 + esac + if [ -n "$KBUILD_DEBARCH" ] ; then + debarch="$KBUILD_DEBARCH" + fi + if [ -n "$debarch" ] ; then + forcearch="-DArchitecture=$debarch" + fi + + # Create the package + dpkg-gencontrol $forcearch -Vkernel:debarch="${debarch:-$(dpkg --print-architecture)}" -p$pname -P"$pdir" + dpkg --build "$pdir" .. +} + +# Some variables and settings used throughout the script +version=$KERNELRELEASE +revision=$(cat .version) +if [ -n "$KDEB_PKGVERSION" ]; then + packageversion=$KDEB_PKGVERSION +else + packageversion=$version-$revision +fi +tmpdir="$objtree/debian/tmp" +fwdir="$objtree/debian/fwtmp" +kernel_headers_dir="$objtree/debian/hdrtmp" +libc_headers_dir="$objtree/debian/headertmp" +dtb_dir="$objtree/debian/dtbtmp" +dbg_dir="$objtree/debian/dbgtmp" +packagename=linux-image"$LOCALVERSION" +fwpackagename=linux-firmware-image"$LOCALVERSION" +kernel_headers_packagename=linux-headers"$LOCALVERSION" +dtb_packagename=linux-dtb"$LOCALVERSION" +libc_headers_packagename=linux-libc-dev"$LOCALVERSION" +dbg_packagename=$packagename-dbg + +if [ "$ARCH" = "um" ] ; then + packagename=user-mode-linux-$version +fi + +# Not all arches have the same installed path in debian +# XXX: have each arch Makefile export a variable of the canonical image install +# path instead +case $ARCH in +um) + installed_image_path="usr/bin/linux-$version" + ;; +parisc|mips|powerpc) + installed_image_path="boot/vmlinux-$version" + ;; +*) + installed_image_path="boot/vmlinuz-$version" +esac + +BUILD_DEBUG="$(grep -s '^CONFIG_DEBUG_INFO=y' $KCONFIG_CONFIG || true)" + +# Setup the directory structure +rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" "$dtb_dir" +mkdir -m 755 -p "$tmpdir/DEBIAN" +mkdir -p "$tmpdir/lib" "$tmpdir/boot" "$tmpdir/usr/share/doc/$packagename" +mkdir -m 755 -p "$fwdir/DEBIAN" +mkdir -p "$fwdir/lib/firmware/$version/" "$fwdir/usr/share/doc/$fwpackagename" +mkdir -m 755 -p "$libc_headers_dir/DEBIAN" +mkdir -p "$libc_headers_dir/usr/share/doc/$libc_headers_packagename" + +mkdir -m 755 -p "$dtb_dir/DEBIAN" +mkdir -p "$dtb_dir/boot/dtb" "$dtb_dir/usr/share/doc/$dtb_packagename" + +mkdir -m 755 -p "$kernel_headers_dir/DEBIAN" +mkdir -p "$kernel_headers_dir/usr/share/doc/$kernel_headers_packagename" +mkdir -p "$kernel_headers_dir/lib/modules/$version/" +if [ "$ARCH" = "um" ] ; then + mkdir -p "$tmpdir/usr/lib/uml/modules/$version" "$tmpdir/usr/bin" +fi +if [ -n "$BUILD_DEBUG" ] ; then + mkdir -p "$dbg_dir/usr/share/doc/$dbg_packagename" + mkdir -m 755 -p "$dbg_dir/DEBIAN" +fi + +# Build and install the kernel +if [ "$ARCH" = "um" ] ; then + $MAKE linux + cp System.map "$tmpdir/usr/lib/uml/modules/$version/System.map" + cp $KCONFIG_CONFIG "$tmpdir/usr/share/doc/$packagename/config" + gzip "$tmpdir/usr/share/doc/$packagename/config" +else + cp System.map "$tmpdir/boot/System.map-$version" + cp $KCONFIG_CONFIG "$tmpdir/boot/config-$version" +fi +# Not all arches include the boot path in KBUILD_IMAGE +if [ -e $KBUILD_IMAGE ]; then + cp $KBUILD_IMAGE "$tmpdir/$installed_image_path" +else + cp arch/$ARCH/boot/$KBUILD_IMAGE "$tmpdir/$installed_image_path" +fi + +if grep -q '^CONFIG_MODULES=y' $KCONFIG_CONFIG ; then + INSTALL_MOD_PATH="$tmpdir" $MAKE KBUILD_SRC= modules_install + rm -f "$tmpdir/lib/modules/$version/build" + rm -f "$tmpdir/lib/modules/$version/source" + if [ "$ARCH" = "um" ] ; then + mv "$tmpdir/lib/modules/$version"/* "$tmpdir/usr/lib/uml/modules/$version/" + rmdir "$tmpdir/lib/modules/$version" + fi + if [ -n "$BUILD_DEBUG" ] ; then + for module in $(find $tmpdir/lib/modules/ -name *.ko -printf '%P\n'); do + module=lib/modules/$module + mkdir -p $(dirname $dbg_dir/usr/lib/debug/$module) + # only keep debug symbols in the debug file + $OBJCOPY --only-keep-debug $tmpdir/$module $dbg_dir/usr/lib/debug/$module + # strip original module from debug symbols + $OBJCOPY --strip-debug $tmpdir/$module + # then add a link to those + $OBJCOPY --add-gnu-debuglink=$dbg_dir/usr/lib/debug/$module $tmpdir/$module + done + fi +fi + +if grep -q '^CONFIG_OF=y' $KCONFIG_CONFIG ; then + mkdir -p "$tmpdir/boot/dtb" + cp $objtree/arch/arm/boot/dts/*.dtb $dtb_dir/boot/dtb + #INSTALL_DTBS_PATH="$dtb_dir/boot/dtb" $MAKE KBUILD_SRC= dtbs_install +fi + +if [ "$ARCH" != "um" ]; then + $MAKE headers_check KBUILD_SRC= + $MAKE headers_install KBUILD_SRC= INSTALL_HDR_PATH="$libc_headers_dir/usr" +fi + +# Install the maintainer scripts +# Note: hook scripts under /etc/kernel are also executed by official Debian +# kernel packages, as well as kernel packages built using make-kpkg. +# make-kpkg sets $INITRD to indicate whether an initramfs is wanted, and +# so do we; recent versions of dracut and initramfs-tools will obey this. +debhookdir=${KDEB_HOOKDIR:-/etc/kernel} +if grep -q '^CONFIG_BLK_DEV_INITRD=y' $KCONFIG_CONFIG; then + want_initrd=Yes +else + want_initrd=No +fi +for script in postinst postrm preinst prerm ; do + mkdir -p "$tmpdir$debhookdir/$script.d" + cat < "$tmpdir/DEBIAN/$script" +#!/bin/sh + +set -e + +# Pass maintainer script parameters to hook scripts + +export DEB_MAINT_PARAMS="\$*" + +# Tell initramfs builder whether it's wanted + +export INITRD=$want_initrd + +test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d +exit 0 +EOF + chmod 755 "$tmpdir/DEBIAN/$script" +done + +## +## Create sym link to kernel image +## +sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/postinst +cat >> $tmpdir/DEBIAN/postinst < /dev/null 2>&1 +rm -f /$installed_image_path /boot/zImage +else +ln -sf /$installed_image_path /boot/zImage > /dev/null 2>&1 || mv /$installed_image_path /boot/zImage +fi +rm -f /boot/.next +exit 0 +EOT +## +## FAT install workaround +## +sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/preinst +cat >> $tmpdir/DEBIAN/preinst <> $tmpdir/DEBIAN/preinst + + +# Try to determine maintainer and email values +if [ -n "$DEBEMAIL" ]; then + email=$DEBEMAIL +elif [ -n "$EMAIL" ]; then + email=$EMAIL +else + email=$(id -nu)@$(hostname -f) +fi +if [ -n "$DEBFULLNAME" ]; then + name=$DEBFULLNAME +elif [ -n "$NAME" ]; then + name=$NAME +else + name="Anonymous" +fi +maintainer="$name <$email>" + +# Generate a simple changelog template +cat < debian/changelog +linux-upstream ($packageversion) unstable; urgency=low + + * Custom built Linux kernel. + + -- $maintainer $(date -R) +EOF + +# Generate copyright file +cat < debian/copyright +This is a packacked upstream version of the Linux kernel. + +The sources may be found at most Linux ftp sites, including: +ftp://ftp.kernel.org/pub/linux/kernel + +Copyright: 1991 - 2009 Linus Torvalds and others. + +The git repository for mainline kernel development is at: +git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991. + +On Debian GNU/Linux systems, the complete text of the GNU General Public +License version 2 can be found in \`/usr/share/common-licenses/GPL-2'. +EOF + +# Generate a control file +cat < debian/control +Source: linux-upstream +Section: kernel +Priority: optional +Maintainer: $maintainer +Standards-Version: 3.8.4 +Homepage: http://www.kernel.org/ +EOF + +if [ "$ARCH" = "um" ]; then + cat <> debian/control + +Package: $packagename +Provides: linux-image, linux-image-2.6, linux-modules-$version +Architecture: any +Description: User Mode Linux kernel, version $version + User-mode Linux is a port of the Linux kernel to its own system call + interface. It provides a kind of virtual machine, which runs Linux + as a user process under another Linux kernel. This is useful for + kernel development, sandboxes, jails, experimentation, and + many other things. + . + This package contains the Linux kernel, modules and corresponding other + files, version: $version. +EOF + +else + cat <> debian/control + +Package: $packagename +Provides: linux-image, linux-image-2.6, linux-modules-$version +Suggests: $fwpackagename +Architecture: any +Description: Linux kernel, version $version + This package contains the Linux kernel, modules and corresponding other + files, version: $version. +EOF + +fi + +# Build kernel header package +(cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl) > "$objtree/debian/hdrsrcfiles" +(cd $srctree; find arch/$SRCARCH/include include scripts -type f) >> "$objtree/debian/hdrsrcfiles" +(cd $srctree; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$objtree/debian/hdrsrcfiles" +(cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$objtree/debian/hdrsrcfiles" +(cd $objtree; find arch/$SRCARCH/include Module.symvers include scripts -type f) >> "$objtree/debian/hdrobjfiles" +destdir=$kernel_headers_dir/usr/src/linux-headers-$version +mkdir -p "$destdir" +######################## headers patch +ZACNI=$(pwd) +cd $destdir +patch -p1 < /tmp/headers-debian-byteshift.patch +cd $ZACNI +######################## headers patch +(cd $srctree; tar -c -f - -T -) < "$objtree/debian/hdrsrcfiles" | (cd $destdir; tar -xf -) +(cd $objtree; tar -c -f - -T -) < "$objtree/debian/hdrobjfiles" | (cd $destdir; tar -xf -) +(cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be +ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build" +rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles" + +cat <> debian/control + +Package: $kernel_headers_packagename +Provides: linux-headers +Architecture: any +Description: Linux kernel headers for $KERNELRELEASE on \${kernel:debarch} + This package provides kernel header files for $KERNELRELEASE on \${kernel:debarch} + . + This is useful for people who need to build external modules +EOF + +# Do we have firmware? Move it out of the way and build it into a package. +if [ -e "$tmpdir/lib/firmware" ]; then + mv "$tmpdir/lib/firmware"/* "$fwdir/lib/firmware/$version/" + rmdir "$tmpdir/lib/firmware" + + cat <> debian/control + +Package: $fwpackagename +Architecture: all +Description: Linux kernel firmware, version $version + This package contains firmware from the Linux kernel, version $version. +EOF + + create_package "$fwpackagename" "$fwdir" +fi + +cat <> debian/control + +Package: $dtb_packagename +Architecture: any +Description: Linux DTB, version $version + This package contains device blobs from the Linux kernel, version $version. +EOF + +create_package "$dtb_packagename" "$dtb_dir" + +cat <> debian/control + +Package: $libc_headers_packagename +Section: devel +Provides: linux-kernel-headers +Architecture: any +Description: Linux support headers for userspace development + This package provides userspaces headers from the Linux kernel. These headers + are used by the installed headers for GNU glibc and other system libraries. +EOF + +if [ "$ARCH" != "um" ]; then + create_package "$kernel_headers_packagename" "$kernel_headers_dir" +# create_package "$libc_headers_packagename" "$libc_headers_dir" +fi + +create_package "$packagename" "$tmpdir" + +if [ -n "$BUILD_DEBUG" ] ; then + # Build debug package + # Different tools want the image in different locations + # perf + mkdir -p $dbg_dir/usr/lib/debug/lib/modules/$version/ + cp vmlinux $dbg_dir/usr/lib/debug/lib/modules/$version/ + # systemtap + mkdir -p $dbg_dir/usr/lib/debug/boot/ + ln -s ../lib/modules/$version/vmlinux $dbg_dir/usr/lib/debug/boot/vmlinux-$version + # kdump-tools + ln -s lib/modules/$version/vmlinux $dbg_dir/usr/lib/debug/vmlinux-$version + + cat <> debian/control + +Package: $dbg_packagename +Section: debug +Provides: linux-debug, linux-debug-$version +Architecture: any +Description: Linux kernel debugging symbols for $version + This package will come in handy if you need to debug the kernel. It provides + all the necessary debug symbols for the kernel and its modules. +EOF + + create_package "$dbg_packagename" "$dbg_dir" +fi + +exit 0 \ No newline at end of file diff --git a/patch/compiler.patch b/patch/kernel/compiler.patch similarity index 100% rename from patch/compiler.patch rename to patch/kernel/compiler.patch diff --git a/patch/hb-i2c-spi.patch b/patch/kernel/cubox-default/hb-i2c-spi.patch similarity index 90% rename from patch/hb-i2c-spi.patch rename to patch/kernel/cubox-default/hb-i2c-spi.patch index f955bdff6..8e7e25124 100644 --- a/patch/hb-i2c-spi.patch +++ b/patch/kernel/cubox-default/hb-i2c-spi.patch @@ -40,11 +40,11 @@ + MX6QDL_PAD_EIM_OE__ECSPI2_MISO 0x100b1 + MX6QDL_PAD_EIM_CS1__ECSPI2_MOSI 0x100b1 + MX6QDL_PAD_EIM_CS0__ECSPI2_SCLK 0x100b1 -+ /* MX6QDL_PAD_EIM_RW__ECSPI2_SS0 0x100b1 */ -+ MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x100b1 -+ MX6QDL_PAD_EIM_LBA__ECSPI2_SS1 0x100b1 ++ MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x80000000 ++ MX6QDL_PAD_EIM_LBA__GPIO2_IO27 0x80000000 + >; + }; ++ + pinctrl_hummingboard_gpio3_5: hummingboard-gpio3_5 { fsl,pins = < diff --git a/patch/kernel/cubox-default/packaging-cubox.patch b/patch/kernel/cubox-default/packaging-cubox.patch new file mode 100644 index 000000000..ca9be7a68 --- /dev/null +++ b/patch/kernel/cubox-default/packaging-cubox.patch @@ -0,0 +1,240 @@ +--- a/scripts/package/builddeb ++++ b/scripts/package/builddeb +@@ -35,13 +35,15 @@ + sparc*) + debarch=sparc ;; + s390*) +- debarch=s390 ;; ++ debarch=s390$(grep -q CONFIG_64BIT=y $KCONFIG_CONFIG && echo x || true) ;; + ppc*) +- debarch=powerpc ;; ++ debarch=$(grep -q CPU_LITTLE_ENDIAN=y $KCONFIG_CONFIG && echo ppc64el || echo powerpc) ;; + parisc*) + debarch=hppa ;; + mips*) + debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y $KCONFIG_CONFIG && echo el || true) ;; ++ arm64) ++ debarch=arm64 ;; + arm*) + debarch=arm$(grep -q CONFIG_AEABI=y $KCONFIG_CONFIG && echo el || true) ;; + *) +@@ -62,7 +64,7 @@ + fi + + # Create the package +- dpkg-gencontrol -isp $forcearch -Vkernel:debarch="${debarch:-$(dpkg --print-architecture)}" -p$pname -P"$pdir" ++ dpkg-gencontrol $forcearch -Vkernel:debarch="${debarch:-$(dpkg --print-architecture)}" -p$pname -P"$pdir" + dpkg --build "$pdir" .. + } + +@@ -78,11 +80,13 @@ + fwdir="$objtree/debian/fwtmp" + kernel_headers_dir="$objtree/debian/hdrtmp" + libc_headers_dir="$objtree/debian/headertmp" ++dtb_dir="$objtree/debian/dtbtmp" + dbg_dir="$objtree/debian/dbgtmp" +-packagename=linux-image-$version +-fwpackagename=linux-firmware-image-$version +-kernel_headers_packagename=linux-headers-$version +-libc_headers_packagename=linux-libc-dev ++packagename=linux-image"$LOCALVERSION" ++fwpackagename=linux-firmware-image"$LOCALVERSION" ++kernel_headers_packagename=linux-headers"$LOCALVERSION" ++dtb_packagename=linux-dtb"$LOCALVERSION" ++libc_headers_packagename=linux-libc-dev"$LOCALVERSION" + dbg_packagename=$packagename-dbg + + if [ "$ARCH" = "um" ] ; then +@@ -106,13 +110,17 @@ + BUILD_DEBUG="$(grep -s '^CONFIG_DEBUG_INFO=y' $KCONFIG_CONFIG || true)" + + # Setup the directory structure +-rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" ++rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" "$dtb_dir" + mkdir -m 755 -p "$tmpdir/DEBIAN" + mkdir -p "$tmpdir/lib" "$tmpdir/boot" "$tmpdir/usr/share/doc/$packagename" + mkdir -m 755 -p "$fwdir/DEBIAN" + mkdir -p "$fwdir/lib/firmware/$version/" "$fwdir/usr/share/doc/$fwpackagename" + mkdir -m 755 -p "$libc_headers_dir/DEBIAN" + mkdir -p "$libc_headers_dir/usr/share/doc/$libc_headers_packagename" ++ ++mkdir -m 755 -p "$dtb_dir/DEBIAN" ++mkdir -p "$dtb_dir/boot/dtb" "$dtb_dir/usr/share/doc/$dtb_packagename" ++ + mkdir -m 755 -p "$kernel_headers_dir/DEBIAN" + mkdir -p "$kernel_headers_dir/usr/share/doc/$kernel_headers_packagename" + mkdir -p "$kernel_headers_dir/lib/modules/$version/" +@@ -130,7 +138,7 @@ + cp System.map "$tmpdir/usr/lib/uml/modules/$version/System.map" + cp $KCONFIG_CONFIG "$tmpdir/usr/share/doc/$packagename/config" + gzip "$tmpdir/usr/share/doc/$packagename/config" +-else ++else + cp System.map "$tmpdir/boot/System.map-$version" + cp $KCONFIG_CONFIG "$tmpdir/boot/config-$version" + fi +@@ -150,21 +158,25 @@ + rmdir "$tmpdir/lib/modules/$version" + fi + if [ -n "$BUILD_DEBUG" ] ; then +- ( +- cd $tmpdir +- for module in $(find lib/modules/ -name *.ko); do +- mkdir -p $(dirname $dbg_dir/usr/lib/debug/$module) +- # only keep debug symbols in the debug file +- $OBJCOPY --only-keep-debug $module $dbg_dir/usr/lib/debug/$module +- # strip original module from debug symbols +- $OBJCOPY --strip-debug $module +- # then add a link to those +- $OBJCOPY --add-gnu-debuglink=$dbg_dir/usr/lib/debug/$module $module +- done +- ) ++ for module in $(find $tmpdir/lib/modules/ -name *.ko -printf '%P\n'); do ++ module=lib/modules/$module ++ mkdir -p $(dirname $dbg_dir/usr/lib/debug/$module) ++ # only keep debug symbols in the debug file ++ $OBJCOPY --only-keep-debug $tmpdir/$module $dbg_dir/usr/lib/debug/$module ++ # strip original module from debug symbols ++ $OBJCOPY --strip-debug $tmpdir/$module ++ # then add a link to those ++ $OBJCOPY --add-gnu-debuglink=$dbg_dir/usr/lib/debug/$module $tmpdir/$module ++ done + fi + fi + ++if grep -q '^CONFIG_OF=y' $KCONFIG_CONFIG ; then ++ mkdir -p "$tmpdir/boot/dtb" ++ cp $objtree/arch/arm/boot/dts/*.dtb $dtb_dir/boot/dtb ++ #INSTALL_DTBS_PATH="$dtb_dir/boot/dtb" $MAKE KBUILD_SRC= dtbs_install ++fi ++ + if [ "$ARCH" != "um" ]; then + $MAKE headers_check KBUILD_SRC= + $MAKE headers_install KBUILD_SRC= INSTALL_HDR_PATH="$libc_headers_dir/usr" +@@ -189,9 +201,11 @@ + set -e + + # Pass maintainer script parameters to hook scripts ++ + export DEB_MAINT_PARAMS="\$*" + + # Tell initramfs builder whether it's wanted ++ + export INITRD=$want_initrd + + test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d +@@ -200,6 +214,15 @@ + chmod 755 "$tmpdir/DEBIAN/$script" + done + ++## ++## Create sym link to kernel image ++## ++kernel_tmp_version="${installed_image_path////\\/}" ++sed -e "s/exit 0/ln -sf \/$kernel_tmp_version \/boot\/zImage || cp \/$kernel_tmp_version \/boot\/zImage/g" -i $tmpdir/DEBIAN/postinst ++#echo "touch /boot/.next" >> $tmpdir/DEBIAN/postinst ++echo "exit 0" >> $tmpdir/DEBIAN/postinst ++ ++ + # Try to determine maintainer and email values + if [ -n "$DEBEMAIL" ]; then + email=$DEBEMAIL +@@ -217,9 +240,20 @@ + fi + maintainer="$name <$email>" + ++# Try to determine distribution ++if [ -n "$KDEB_CHANGELOG_DIST" ]; then ++ distribution=$KDEB_CHANGELOG_DIST ++elif distribution=$(lsb_release -cs 2>/dev/null) && [ -n "$distribution" ]; then ++ : # nothing to do in this case ++else ++ distribution="unstable" ++ echo >&2 "Using default distribution of 'unstable' in the changelog" ++ echo >&2 "Install lsb-release or set \$KDEB_CHANGELOG_DIST explicitly" ++fi ++ + # Generate a simple changelog template + cat < debian/changelog +-linux-upstream ($packageversion) unstable; urgency=low ++linux-upstream ($packageversion) $distribution; urgency=low + + * Custom built Linux kernel. + +@@ -233,10 +267,10 @@ + The sources may be found at most Linux ftp sites, including: + ftp://ftp.kernel.org/pub/linux/kernel + +-Copyright: 1991 - 2009 Linus Torvalds and others. ++Copyright: 1991 - 2015 Linus Torvalds and others. + + The git repository for mainline kernel development is at: +-git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git ++git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +@@ -287,14 +321,22 @@ + + fi + +-# Build header package +-(cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl > "$objtree/debian/hdrsrcfiles") +-(cd $srctree; find arch/$SRCARCH/include include scripts -type f >> "$objtree/debian/hdrsrcfiles") +-(cd $objtree; find arch/$SRCARCH/include Module.symvers include scripts -type f >> "$objtree/debian/hdrobjfiles") ++# Build kernel header package ++(cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl) > "$objtree/debian/hdrsrcfiles" ++(cd $srctree; find arch/$SRCARCH/include include scripts -type f) >> "$objtree/debian/hdrsrcfiles" ++(cd $srctree; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$objtree/debian/hdrsrcfiles" ++(cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$objtree/debian/hdrsrcfiles" ++(cd $objtree; find arch/$SRCARCH/include Module.symvers include scripts -type f) >> "$objtree/debian/hdrobjfiles" + destdir=$kernel_headers_dir/usr/src/linux-headers-$version + mkdir -p "$destdir" +-(cd $srctree; tar -c -f - -T "$objtree/debian/hdrsrcfiles") | (cd $destdir; tar -xf -) +-(cd $objtree; tar -c -f - -T "$objtree/debian/hdrobjfiles") | (cd $destdir; tar -xf -) ++######################## headers patch ++ZACNI=$(pwd) ++cd $destdir ++patch -p1 < /tmp/headers-debian-byteshift.patch ++cd $ZACNI ++######################## headers patch ++(cd $srctree; tar -c -f - -T -) < "$objtree/debian/hdrsrcfiles" | (cd $destdir; tar -xf -) ++(cd $objtree; tar -c -f - -T -) < "$objtree/debian/hdrobjfiles" | (cd $destdir; tar -xf -) + (cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be + ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build" + rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles" +@@ -302,7 +344,7 @@ + cat <> debian/control + + Package: $kernel_headers_packagename +-Provides: linux-headers, linux-headers-2.6 ++Provides: linux-headers + Architecture: any + Description: Linux kernel headers for $KERNELRELEASE on \${kernel:debarch} + This package provides kernel header files for $KERNELRELEASE on \${kernel:debarch} +@@ -328,6 +370,16 @@ + + cat <> debian/control + ++Package: $dtb_packagename ++Architecture: any ++Description: Linux DTB, version $version ++ This package contains device blobs from the Linux kernel, version $version. ++EOF ++ ++create_package "$dtb_packagename" "$dtb_dir" ++ ++cat <> debian/control ++ + Package: $libc_headers_packagename + Section: devel + Provides: linux-kernel-headers +@@ -339,7 +391,7 @@ + + if [ "$ARCH" != "um" ]; then + create_package "$kernel_headers_packagename" "$kernel_headers_dir" +- create_package "$libc_headers_packagename" "$libc_headers_dir" ++# create_package "$libc_headers_packagename" "$libc_headers_dir" + fi + + create_package "$packagename" "$tmpdir" diff --git a/patch/kernel/cubox-default/patch-3.14.14-15.patch b/patch/kernel/cubox-default/patch-3.14.14-15.patch new file mode 100644 index 000000000..f1730277b --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.14-15.patch @@ -0,0 +1,893 @@ +diff --git a/Makefile b/Makefile +index 230c7f694ab7..188523e9e880 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 14 ++SUBLEVEL = 15 + EXTRAVERSION = + NAME = Remembering Coco + +@@ -639,6 +639,8 @@ KBUILD_CFLAGS += -fomit-frame-pointer + endif + endif + ++KBUILD_CFLAGS += $(call cc-option, -fno-var-tracking-assignments) ++ + ifdef CONFIG_DEBUG_INFO + KBUILD_CFLAGS += -g + KBUILD_AFLAGS += -Wa,--gdwarf-2 +diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h +index a2fa297196bc..f5645d6a89f2 100644 +--- a/arch/parisc/include/uapi/asm/signal.h ++++ b/arch/parisc/include/uapi/asm/signal.h +@@ -69,8 +69,6 @@ + #define SA_NOMASK SA_NODEFER + #define SA_ONESHOT SA_RESETHAND + +-#define SA_RESTORER 0x04000000 /* obsolete -- ignored */ +- + #define MINSIGSTKSZ 2048 + #define SIGSTKSZ 8192 + +diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c +index a48bc79a111f..184d305af3e7 100644 +--- a/arch/s390/kernel/ptrace.c ++++ b/arch/s390/kernel/ptrace.c +@@ -323,9 +323,14 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data) + unsigned long mask = PSW_MASK_USER; + + mask |= is_ri_task(child) ? PSW_MASK_RI : 0; +- if ((data & ~mask) != PSW_USER_BITS) ++ if ((data ^ PSW_USER_BITS) & ~mask) ++ /* Invalid psw mask. */ ++ return -EINVAL; ++ if ((data & PSW_MASK_ASC) == PSW_ASC_HOME) ++ /* Invalid address-space-control bits */ + return -EINVAL; + if ((data & PSW_MASK_EA) && !(data & PSW_MASK_BA)) ++ /* Invalid addressing mode bits */ + return -EINVAL; + } + *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data; +@@ -661,9 +666,12 @@ static int __poke_user_compat(struct task_struct *child, + + mask |= is_ri_task(child) ? PSW32_MASK_RI : 0; + /* Build a 64 bit psw mask from 31 bit mask. */ +- if ((tmp & ~mask) != PSW32_USER_BITS) ++ if ((tmp ^ PSW32_USER_BITS) & ~mask) + /* Invalid psw mask. */ + return -EINVAL; ++ if ((data & PSW32_MASK_ASC) == PSW32_ASC_HOME) ++ /* Invalid address-space-control bits */ ++ return -EINVAL; + regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | + (regs->psw.mask & PSW_MASK_BA) | + (__u64)(tmp & mask) << 32; +diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S +index ec3b8ba68096..04da6c2194ba 100644 +--- a/arch/x86/boot/header.S ++++ b/arch/x86/boot/header.S +@@ -91,10 +91,9 @@ bs_die: + + .section ".bsdata", "a" + bugger_off_msg: +- .ascii "Direct floppy boot is not supported. " +- .ascii "Use a boot loader program instead.\r\n" ++ .ascii "Use a boot loader.\r\n" + .ascii "\n" +- .ascii "Remove disk and press any key to reboot ...\r\n" ++ .ascii "Remove disk and press any key to reboot...\r\n" + .byte 0 + + #ifdef CONFIG_EFI_STUB +@@ -108,7 +107,7 @@ coff_header: + #else + .word 0x8664 # x86-64 + #endif +- .word 3 # nr_sections ++ .word 4 # nr_sections + .long 0 # TimeDateStamp + .long 0 # PointerToSymbolTable + .long 1 # NumberOfSymbols +@@ -250,6 +249,25 @@ section_table: + .word 0 # NumberOfLineNumbers + .long 0x60500020 # Characteristics (section flags) + ++ # ++ # The offset & size fields are filled in by build.c. ++ # ++ .ascii ".bss" ++ .byte 0 ++ .byte 0 ++ .byte 0 ++ .byte 0 ++ .long 0 ++ .long 0x0 ++ .long 0 # Size of initialized data ++ # on disk ++ .long 0x0 ++ .long 0 # PointerToRelocations ++ .long 0 # PointerToLineNumbers ++ .word 0 # NumberOfRelocations ++ .word 0 # NumberOfLineNumbers ++ .long 0xc8000080 # Characteristics (section flags) ++ + #endif /* CONFIG_EFI_STUB */ + + # Kernel attributes; used by setup. This is part 1 of the +diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c +index 8e15b22391fc..3dafaeb9f549 100644 +--- a/arch/x86/boot/tools/build.c ++++ b/arch/x86/boot/tools/build.c +@@ -142,7 +142,7 @@ static void usage(void) + + #ifdef CONFIG_EFI_STUB + +-static void update_pecoff_section_header(char *section_name, u32 offset, u32 size) ++static void update_pecoff_section_header_fields(char *section_name, u32 vma, u32 size, u32 datasz, u32 offset) + { + unsigned int pe_header; + unsigned short num_sections; +@@ -163,10 +163,10 @@ static void update_pecoff_section_header(char *section_name, u32 offset, u32 siz + put_unaligned_le32(size, section + 0x8); + + /* section header vma field */ +- put_unaligned_le32(offset, section + 0xc); ++ put_unaligned_le32(vma, section + 0xc); + + /* section header 'size of initialised data' field */ +- put_unaligned_le32(size, section + 0x10); ++ put_unaligned_le32(datasz, section + 0x10); + + /* section header 'file offset' field */ + put_unaligned_le32(offset, section + 0x14); +@@ -178,6 +178,11 @@ static void update_pecoff_section_header(char *section_name, u32 offset, u32 siz + } + } + ++static void update_pecoff_section_header(char *section_name, u32 offset, u32 size) ++{ ++ update_pecoff_section_header_fields(section_name, offset, size, size, offset); ++} ++ + static void update_pecoff_setup_and_reloc(unsigned int size) + { + u32 setup_offset = 0x200; +@@ -202,9 +207,6 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz) + + pe_header = get_unaligned_le32(&buf[0x3c]); + +- /* Size of image */ +- put_unaligned_le32(file_sz, &buf[pe_header + 0x50]); +- + /* + * Size of code: Subtract the size of the first sector (512 bytes) + * which includes the header. +@@ -219,6 +221,22 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz) + update_pecoff_section_header(".text", text_start, text_sz); + } + ++static void update_pecoff_bss(unsigned int file_sz, unsigned int init_sz) ++{ ++ unsigned int pe_header; ++ unsigned int bss_sz = init_sz - file_sz; ++ ++ pe_header = get_unaligned_le32(&buf[0x3c]); ++ ++ /* Size of uninitialized data */ ++ put_unaligned_le32(bss_sz, &buf[pe_header + 0x24]); ++ ++ /* Size of image */ ++ put_unaligned_le32(init_sz, &buf[pe_header + 0x50]); ++ ++ update_pecoff_section_header_fields(".bss", file_sz, bss_sz, 0, 0); ++} ++ + #endif /* CONFIG_EFI_STUB */ + + +@@ -270,6 +288,9 @@ int main(int argc, char ** argv) + int fd; + void *kernel; + u32 crc = 0xffffffffUL; ++#ifdef CONFIG_EFI_STUB ++ unsigned int init_sz; ++#endif + + /* Defaults for old kernel */ + #ifdef CONFIG_X86_32 +@@ -343,7 +364,9 @@ int main(int argc, char ** argv) + put_unaligned_le32(sys_size, &buf[0x1f4]); + + #ifdef CONFIG_EFI_STUB +- update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz)); ++ update_pecoff_text(setup_sectors * 512, i + (sys_size * 16)); ++ init_sz = get_unaligned_le32(&buf[0x260]); ++ update_pecoff_bss(i + (sys_size * 16), init_sz); + + #ifdef CONFIG_X86_64 /* Yes, this is really how we defined it :( */ + efi_stub_entry -= 0x200; +diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S +index 6491353cc9aa..c87810b1b557 100644 +--- a/arch/x86/kernel/entry_32.S ++++ b/arch/x86/kernel/entry_32.S +@@ -433,8 +433,8 @@ sysenter_do_call: + cmpl $(NR_syscalls), %eax + jae sysenter_badsys + call *sys_call_table(,%eax,4) +- movl %eax,PT_EAX(%esp) + sysenter_after_call: ++ movl %eax,PT_EAX(%esp) + LOCKDEP_SYS_EXIT + DISABLE_INTERRUPTS(CLBR_ANY) + TRACE_IRQS_OFF +@@ -514,6 +514,7 @@ ENTRY(system_call) + jae syscall_badsys + syscall_call: + call *sys_call_table(,%eax,4) ++syscall_after_call: + movl %eax,PT_EAX(%esp) # store the return value + syscall_exit: + LOCKDEP_SYS_EXIT +@@ -683,12 +684,12 @@ syscall_fault: + END(syscall_fault) + + syscall_badsys: +- movl $-ENOSYS,PT_EAX(%esp) +- jmp syscall_exit ++ movl $-ENOSYS,%eax ++ jmp syscall_after_call + END(syscall_badsys) + + sysenter_badsys: +- movl $-ENOSYS,PT_EAX(%esp) ++ movl $-ENOSYS,%eax + jmp sysenter_after_call + END(syscall_badsys) + CFI_ENDPROC +diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c +index dd0dd2d4ceca..d8f80e733cf8 100644 +--- a/block/blk-cgroup.c ++++ b/block/blk-cgroup.c +@@ -859,6 +859,13 @@ void blkcg_drain_queue(struct request_queue *q) + { + lockdep_assert_held(q->queue_lock); + ++ /* ++ * @q could be exiting and already have destroyed all blkgs as ++ * indicated by NULL root_blkg. If so, don't confuse policies. ++ */ ++ if (!q->root_blkg) ++ return; ++ + blk_throtl_drain(q); + } + +diff --git a/block/blk-tag.c b/block/blk-tag.c +index 3f33d8672268..a185b86741e5 100644 +--- a/block/blk-tag.c ++++ b/block/blk-tag.c +@@ -27,18 +27,15 @@ struct request *blk_queue_find_tag(struct request_queue *q, int tag) + EXPORT_SYMBOL(blk_queue_find_tag); + + /** +- * __blk_free_tags - release a given set of tag maintenance info ++ * blk_free_tags - release a given set of tag maintenance info + * @bqt: the tag map to free + * +- * Tries to free the specified @bqt. Returns true if it was +- * actually freed and false if there are still references using it ++ * Drop the reference count on @bqt and frees it when the last reference ++ * is dropped. + */ +-static int __blk_free_tags(struct blk_queue_tag *bqt) ++void blk_free_tags(struct blk_queue_tag *bqt) + { +- int retval; +- +- retval = atomic_dec_and_test(&bqt->refcnt); +- if (retval) { ++ if (atomic_dec_and_test(&bqt->refcnt)) { + BUG_ON(find_first_bit(bqt->tag_map, bqt->max_depth) < + bqt->max_depth); + +@@ -50,9 +47,8 @@ static int __blk_free_tags(struct blk_queue_tag *bqt) + + kfree(bqt); + } +- +- return retval; + } ++EXPORT_SYMBOL(blk_free_tags); + + /** + * __blk_queue_free_tags - release tag maintenance info +@@ -69,28 +65,13 @@ void __blk_queue_free_tags(struct request_queue *q) + if (!bqt) + return; + +- __blk_free_tags(bqt); ++ blk_free_tags(bqt); + + q->queue_tags = NULL; + queue_flag_clear_unlocked(QUEUE_FLAG_QUEUED, q); + } + + /** +- * blk_free_tags - release a given set of tag maintenance info +- * @bqt: the tag map to free +- * +- * For externally managed @bqt frees the map. Callers of this +- * function must guarantee to have released all the queues that +- * might have been using this tag map. +- */ +-void blk_free_tags(struct blk_queue_tag *bqt) +-{ +- if (unlikely(!__blk_free_tags(bqt))) +- BUG(); +-} +-EXPORT_SYMBOL(blk_free_tags); +- +-/** + * blk_queue_free_tags - release tag maintenance info + * @q: the request queue for the device + * +diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c +index fbd5a67cb773..a0926a6094b2 100644 +--- a/block/compat_ioctl.c ++++ b/block/compat_ioctl.c +@@ -690,6 +690,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + case BLKROSET: + case BLKDISCARD: + case BLKSECDISCARD: ++ case BLKZEROOUT: + /* + * the ones below are implemented in blkdev_locked_ioctl, + * but we call blkdev_ioctl, which gets the lock for us +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index 9aa42998d757..b54f8b3c7924 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -457,6 +457,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { + + /* Promise */ + { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ ++ { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */ + + /* Asmedia */ + { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index 62fda16c8377..f7616036663b 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -4787,6 +4787,10 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) + * ata_qc_new - Request an available ATA command, for queueing + * @ap: target port + * ++ * Some ATA host controllers may implement a queue depth which is less ++ * than ATA_MAX_QUEUE. So we shouldn't allocate a tag which is beyond ++ * the hardware limitation. ++ * + * LOCKING: + * None. + */ +@@ -4794,14 +4798,15 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) + static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) + { + struct ata_queued_cmd *qc = NULL; ++ unsigned int max_queue = ap->host->n_tags; + unsigned int i, tag; + + /* no command while frozen */ + if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) + return NULL; + +- for (i = 0; i < ATA_MAX_QUEUE; i++) { +- tag = (i + ap->last_tag + 1) % ATA_MAX_QUEUE; ++ for (i = 0, tag = ap->last_tag + 1; i < max_queue; i++, tag++) { ++ tag = tag < max_queue ? tag : 0; + + /* the last tag is reserved for internal command. */ + if (tag == ATA_TAG_INTERNAL) +@@ -6103,6 +6108,7 @@ void ata_host_init(struct ata_host *host, struct device *dev, + { + spin_lock_init(&host->lock); + mutex_init(&host->eh_mutex); ++ host->n_tags = ATA_MAX_QUEUE - 1; + host->dev = dev; + host->ops = ops; + } +@@ -6184,6 +6190,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) + { + int i, rc; + ++ host->n_tags = clamp(sht->can_queue, 1, ATA_MAX_QUEUE - 1); ++ + /* host must have been started */ + if (!(host->flags & ATA_HOST_STARTED)) { + dev_err(host->dev, "BUG: trying to register unstarted host\n"); +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index 3c51eb0bd659..9dbf4ef2b2a3 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -89,8 +89,13 @@ int platform_get_irq(struct platform_device *dev, unsigned int num) + return dev->archdata.irqs[num]; + #else + struct resource *r; +- if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) +- return of_irq_get(dev->dev.of_node, num); ++ if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) { ++ int ret; ++ ++ ret = of_irq_get(dev->dev.of_node, num); ++ if (ret >= 0 || ret == -EPROBE_DEFER) ++ return ret; ++ } + + r = platform_get_resource(dev, IORESOURCE_IRQ, num); + +diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c +index 270f68a6b724..7164045c06e4 100644 +--- a/drivers/gpu/drm/radeon/cik.c ++++ b/drivers/gpu/drm/radeon/cik.c +@@ -2219,6 +2219,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev) + gb_tile_moden = 0; + break; + } ++ rdev->config.cik.macrotile_mode_array[reg_offset] = gb_tile_moden; + WREG32(GB_MACROTILE_MODE0 + (reg_offset * 4), gb_tile_moden); + } + } else if (num_pipe_configs == 8) { +@@ -7270,6 +7271,7 @@ static inline u32 cik_get_ih_wptr(struct radeon_device *rdev) + tmp = RREG32(IH_RB_CNTL); + tmp |= IH_WPTR_OVERFLOW_CLEAR; + WREG32(IH_RB_CNTL, tmp); ++ wptr &= ~RB_OVERFLOW; + } + return (wptr & rdev->ih.ptr_mask); + } +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index 64108dbc7d45..4b3c5f7ae63b 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -4763,6 +4763,7 @@ static u32 evergreen_get_ih_wptr(struct radeon_device *rdev) + tmp = RREG32(IH_RB_CNTL); + tmp |= IH_WPTR_OVERFLOW_CLEAR; + WREG32(IH_RB_CNTL, tmp); ++ wptr &= ~RB_OVERFLOW; + } + return (wptr & rdev->ih.ptr_mask); + } +diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c +index f28ab840cc23..788f602e8989 100644 +--- a/drivers/gpu/drm/radeon/r600.c ++++ b/drivers/gpu/drm/radeon/r600.c +@@ -3795,6 +3795,7 @@ static u32 r600_get_ih_wptr(struct radeon_device *rdev) + tmp = RREG32(IH_RB_CNTL); + tmp |= IH_WPTR_OVERFLOW_CLEAR; + WREG32(IH_RB_CNTL, tmp); ++ wptr &= ~RB_OVERFLOW; + } + return (wptr & rdev->ih.ptr_mask); + } +diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c +index cb7508dc94f3..ea93393374df 100644 +--- a/drivers/gpu/drm/radeon/si.c ++++ b/drivers/gpu/drm/radeon/si.c +@@ -6098,6 +6098,7 @@ static inline u32 si_get_ih_wptr(struct radeon_device *rdev) + tmp = RREG32(IH_RB_CNTL); + tmp |= IH_WPTR_OVERFLOW_CLEAR; + WREG32(IH_RB_CNTL, tmp); ++ wptr &= ~RB_OVERFLOW; + } + return (wptr & rdev->ih.ptr_mask); + } +diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c +index efee4c59239f..34b9a601ad07 100644 +--- a/drivers/hwmon/smsc47m192.c ++++ b/drivers/hwmon/smsc47m192.c +@@ -86,7 +86,7 @@ static inline u8 IN_TO_REG(unsigned long val, int n) + */ + static inline s8 TEMP_TO_REG(int val) + { +- return clamp_val(SCALE(val, 1, 1000), -128000, 127000); ++ return SCALE(clamp_val(val, -128000, 127000), 1, 1000); + } + + static inline int TEMP_FROM_REG(s8 val) +@@ -384,6 +384,8 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, + err = kstrtoul(buf, 10, &val); + if (err) + return err; ++ if (val > 255) ++ return -EINVAL; + + data->vrm = val; + return count; +diff --git a/drivers/input/input.c b/drivers/input/input.c +index 1c4c0db05550..29ca0bb4f561 100644 +--- a/drivers/input/input.c ++++ b/drivers/input/input.c +@@ -257,9 +257,10 @@ static int input_handle_abs_event(struct input_dev *dev, + } + + static int input_get_disposition(struct input_dev *dev, +- unsigned int type, unsigned int code, int value) ++ unsigned int type, unsigned int code, int *pval) + { + int disposition = INPUT_IGNORE_EVENT; ++ int value = *pval; + + switch (type) { + +@@ -357,6 +358,7 @@ static int input_get_disposition(struct input_dev *dev, + break; + } + ++ *pval = value; + return disposition; + } + +@@ -365,7 +367,7 @@ static void input_handle_event(struct input_dev *dev, + { + int disposition; + +- disposition = input_get_disposition(dev, type, code, value); ++ disposition = input_get_disposition(dev, type, code, &value); + + if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event) + dev->event(dev, type, code, value); +diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c +index ec772d962f06..ef9e0b8a9aa7 100644 +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -132,7 +132,8 @@ static const struct min_max_quirk min_max_pnpid_table[] = { + 1232, 5710, 1156, 4696 + }, + { +- (const char * const []){"LEN0034", "LEN0036", "LEN2004", NULL}, ++ (const char * const []){"LEN0034", "LEN0036", "LEN2002", ++ "LEN2004", NULL}, + 1024, 5112, 2024, 4832 + }, + { +@@ -168,7 +169,7 @@ static const char * const topbuttonpad_pnp_ids[] = { + "LEN0049", + "LEN2000", + "LEN2001", /* Edge E431 */ +- "LEN2002", ++ "LEN2002", /* Edge E531 */ + "LEN2003", + "LEN2004", /* L440 */ + "LEN2005", +diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c +index 8ad3a57cf640..287b977862e2 100644 +--- a/drivers/media/dvb-frontends/tda10071.c ++++ b/drivers/media/dvb-frontends/tda10071.c +@@ -667,6 +667,7 @@ static int tda10071_set_frontend(struct dvb_frontend *fe) + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int ret, i; + u8 mode, rolloff, pilot, inversion, div; ++ fe_modulation_t modulation; + + dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d modulation=%d " \ + "frequency=%d symbol_rate=%d inversion=%d pilot=%d " \ +@@ -701,10 +702,13 @@ static int tda10071_set_frontend(struct dvb_frontend *fe) + + switch (c->delivery_system) { + case SYS_DVBS: ++ modulation = QPSK; + rolloff = 0; + pilot = 2; + break; + case SYS_DVBS2: ++ modulation = c->modulation; ++ + switch (c->rolloff) { + case ROLLOFF_20: + rolloff = 2; +@@ -749,7 +753,7 @@ static int tda10071_set_frontend(struct dvb_frontend *fe) + + for (i = 0, mode = 0xff; i < ARRAY_SIZE(TDA10071_MODCOD); i++) { + if (c->delivery_system == TDA10071_MODCOD[i].delivery_system && +- c->modulation == TDA10071_MODCOD[i].modulation && ++ modulation == TDA10071_MODCOD[i].modulation && + c->fec_inner == TDA10071_MODCOD[i].fec) { + mode = TDA10071_MODCOD[i].val; + dev_dbg(&priv->i2c->dev, "%s: mode found=%02x\n", +diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c +index 0500c4175d5f..6bce01a674f9 100644 +--- a/drivers/media/usb/hdpvr/hdpvr-video.c ++++ b/drivers/media/usb/hdpvr/hdpvr-video.c +@@ -82,7 +82,7 @@ static void hdpvr_read_bulk_callback(struct urb *urb) + } + + /*=========================================================================*/ +-/* bufffer bits */ ++/* buffer bits */ + + /* function expects dev->io_mutex to be hold by caller */ + int hdpvr_cancel_queue(struct hdpvr_device *dev) +@@ -926,7 +926,7 @@ static int hdpvr_s_ctrl(struct v4l2_ctrl *ctrl) + case V4L2_CID_MPEG_AUDIO_ENCODING: + if (dev->flags & HDPVR_FLAG_AC3_CAP) { + opt->audio_codec = ctrl->val; +- return hdpvr_set_audio(dev, opt->audio_input, ++ return hdpvr_set_audio(dev, opt->audio_input + 1, + opt->audio_codec); + } + return 0; +@@ -1198,7 +1198,7 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, + v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops, + V4L2_CID_MPEG_AUDIO_ENCODING, + ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : V4L2_MPEG_AUDIO_ENCODING_AAC, +- 0x7, V4L2_MPEG_AUDIO_ENCODING_AAC); ++ 0x7, ac3 ? dev->options.audio_codec : V4L2_MPEG_AUDIO_ENCODING_AAC); + v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops, + V4L2_CID_MPEG_VIDEO_ENCODING, + V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 0x3, +diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c +index a2e257970fec..78d99b137d91 100644 +--- a/drivers/media/v4l2-core/v4l2-dv-timings.c ++++ b/drivers/media/v4l2-core/v4l2-dv-timings.c +@@ -595,10 +595,10 @@ struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait) + aspect.denominator = 9; + } else if (ratio == 34) { + aspect.numerator = 4; +- aspect.numerator = 3; ++ aspect.denominator = 3; + } else if (ratio == 68) { + aspect.numerator = 15; +- aspect.numerator = 9; ++ aspect.denominator = 9; + } else { + aspect.numerator = hor_landscape + 99; + aspect.denominator = 100; +diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig +index 2872ece81f35..44333bd8f908 100644 +--- a/drivers/parport/Kconfig ++++ b/drivers/parport/Kconfig +@@ -5,6 +5,12 @@ + # Parport configuration. + # + ++config ARCH_MIGHT_HAVE_PC_PARPORT ++ bool ++ help ++ Select this config option from the architecture Kconfig if ++ the architecture might have PC parallel port hardware. ++ + menuconfig PARPORT + tristate "Parallel port support" + depends on HAS_IOMEM +@@ -31,12 +37,6 @@ menuconfig PARPORT + + If unsure, say Y. + +-config ARCH_MIGHT_HAVE_PC_PARPORT +- bool +- help +- Select this config option from the architecture Kconfig if +- the architecture might have PC parallel port hardware. +- + if PARPORT + + config PARPORT_PC +diff --git a/drivers/staging/media/omap4iss/Kconfig b/drivers/staging/media/omap4iss/Kconfig +index b9fe753969bd..15940f8fdd24 100644 +--- a/drivers/staging/media/omap4iss/Kconfig ++++ b/drivers/staging/media/omap4iss/Kconfig +@@ -1,6 +1,6 @@ + config VIDEO_OMAP4 + bool "OMAP 4 Camera support" +- depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && I2C && ARCH_OMAP4 ++ depends on VIDEO_V4L2=y && VIDEO_V4L2_SUBDEV_API && I2C=y && ARCH_OMAP4 + select VIDEOBUF2_DMA_CONTIG + ---help--- + Driver for an OMAP 4 ISS controller. +diff --git a/fs/coredump.c b/fs/coredump.c +index 0b2528fb640e..a93f7e6ea4cf 100644 +--- a/fs/coredump.c ++++ b/fs/coredump.c +@@ -306,7 +306,7 @@ static int zap_threads(struct task_struct *tsk, struct mm_struct *mm, + if (unlikely(nr < 0)) + return nr; + +- tsk->flags = PF_DUMPCORE; ++ tsk->flags |= PF_DUMPCORE; + if (atomic_read(&mm->mm_users) == nr + 1) + goto done; + /* +diff --git a/fs/namei.c b/fs/namei.c +index 8274c8d39b03..bdea10963aa5 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -2247,9 +2247,10 @@ done: + goto out; + } + path->dentry = dentry; +- path->mnt = mntget(nd->path.mnt); ++ path->mnt = nd->path.mnt; + if (should_follow_link(dentry, nd->flags & LOOKUP_FOLLOW)) + return 1; ++ mntget(path->mnt); + follow_mount(path); + error = 0; + out: +diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c +index 871d6eda8dba..8f854dde4150 100644 +--- a/fs/nfs/nfs3acl.c ++++ b/fs/nfs/nfs3acl.c +@@ -247,3 +247,46 @@ const struct xattr_handler *nfs3_xattr_handlers[] = { + &posix_acl_default_xattr_handler, + NULL, + }; ++ ++static int ++nfs3_list_one_acl(struct inode *inode, int type, const char *name, void *data, ++ size_t size, ssize_t *result) ++{ ++ struct posix_acl *acl; ++ char *p = data + *result; ++ ++ acl = get_acl(inode, type); ++ if (!acl) ++ return 0; ++ ++ posix_acl_release(acl); ++ ++ *result += strlen(name); ++ *result += 1; ++ if (!size) ++ return 0; ++ if (*result > size) ++ return -ERANGE; ++ ++ strcpy(p, name); ++ return 0; ++} ++ ++ssize_t ++nfs3_listxattr(struct dentry *dentry, char *data, size_t size) ++{ ++ struct inode *inode = dentry->d_inode; ++ ssize_t result = 0; ++ int error; ++ ++ error = nfs3_list_one_acl(inode, ACL_TYPE_ACCESS, ++ POSIX_ACL_XATTR_ACCESS, data, size, &result); ++ if (error) ++ return error; ++ ++ error = nfs3_list_one_acl(inode, ACL_TYPE_DEFAULT, ++ POSIX_ACL_XATTR_DEFAULT, data, size, &result); ++ if (error) ++ return error; ++ return result; ++} +diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c +index a462ef0fb5d6..8a18b4a0a4ee 100644 +--- a/fs/nfs/nfs3proc.c ++++ b/fs/nfs/nfs3proc.c +@@ -926,7 +926,7 @@ static const struct inode_operations nfs3_dir_inode_operations = { + .getattr = nfs_getattr, + .setattr = nfs_setattr, + #ifdef CONFIG_NFS_V3_ACL +- .listxattr = generic_listxattr, ++ .listxattr = nfs3_listxattr, + .getxattr = generic_getxattr, + .setxattr = generic_setxattr, + .removexattr = generic_removexattr, +@@ -940,7 +940,7 @@ static const struct inode_operations nfs3_file_inode_operations = { + .getattr = nfs_getattr, + .setattr = nfs_setattr, + #ifdef CONFIG_NFS_V3_ACL +- .listxattr = generic_listxattr, ++ .listxattr = nfs3_listxattr, + .getxattr = generic_getxattr, + .setxattr = generic_setxattr, + .removexattr = generic_removexattr, +diff --git a/include/linux/libata.h b/include/linux/libata.h +index 3fee55e73e5e..e13b3aef0b0c 100644 +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -593,6 +593,7 @@ struct ata_host { + struct device *dev; + void __iomem * const *iomap; + unsigned int n_ports; ++ unsigned int n_tags; /* nr of NCQ tags */ + void *private_data; + struct ata_port_operations *ops; + unsigned long flags; +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index 7e259b2bdf44..71136720ffa1 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -811,7 +811,7 @@ static struct { + { trace_clock_local, "local", 1 }, + { trace_clock_global, "global", 1 }, + { trace_clock_counter, "counter", 0 }, +- { trace_clock_jiffies, "uptime", 1 }, ++ { trace_clock_jiffies, "uptime", 0 }, + { trace_clock, "perf", 1 }, + ARCH_TRACE_CLOCKS + }; +diff --git a/kernel/trace/trace_clock.c b/kernel/trace/trace_clock.c +index 26dc348332b7..57b67b1f24d1 100644 +--- a/kernel/trace/trace_clock.c ++++ b/kernel/trace/trace_clock.c +@@ -59,13 +59,14 @@ u64 notrace trace_clock(void) + + /* + * trace_jiffy_clock(): Simply use jiffies as a clock counter. ++ * Note that this use of jiffies_64 is not completely safe on ++ * 32-bit systems. But the window is tiny, and the effect if ++ * we are affected is that we will have an obviously bogus ++ * timestamp on a trace event - i.e. not life threatening. + */ + u64 notrace trace_clock_jiffies(void) + { +- u64 jiffy = jiffies - INITIAL_JIFFIES; +- +- /* Return nsecs */ +- return (u64)jiffies_to_usecs(jiffy) * 1000ULL; ++ return jiffies_64_to_clock_t(jiffies_64 - INITIAL_JIFFIES); + } + + /* +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 30dd6265a141..923f38e62bcf 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -2422,6 +2422,7 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, + } else { + if (cow) + huge_ptep_set_wrprotect(src, addr, src_pte); ++ entry = huge_ptep_get(src_pte); + ptepage = pte_page(entry); + get_page(ptepage); + page_dup_rmap(ptepage); +diff --git a/mm/slab_common.c b/mm/slab_common.c +index 1ec3c619ba04..f149e6724411 100644 +--- a/mm/slab_common.c ++++ b/mm/slab_common.c +@@ -56,7 +56,7 @@ static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name, + continue; + } + +-#if !defined(CONFIG_SLUB) || !defined(CONFIG_SLUB_DEBUG_ON) ++#if !defined(CONFIG_SLUB) + /* + * For simplicity, we won't check this in the list of memcg + * caches. We have control over memcg naming, and if there +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 4fe2e6e2bc76..e6283464a8e6 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -1450,18 +1450,17 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, + } + CMD(start_p2p_device, START_P2P_DEVICE); + CMD(set_mcast_rate, SET_MCAST_RATE); ++#ifdef CONFIG_NL80211_TESTMODE ++ CMD(testmode_cmd, TESTMODE); ++#endif + if (state->split) { + CMD(crit_proto_start, CRIT_PROTOCOL_START); + CMD(crit_proto_stop, CRIT_PROTOCOL_STOP); + if (dev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH) + CMD(channel_switch, CHANNEL_SWITCH); ++ CMD(set_qos_map, SET_QOS_MAP); + } +- CMD(set_qos_map, SET_QOS_MAP); +- +-#ifdef CONFIG_NL80211_TESTMODE +- CMD(testmode_cmd, TESTMODE); +-#endif +- ++ /* add into the if now */ + #undef CMD + + if (dev->ops->connect || dev->ops->auth) { diff --git a/patch/kernel/cubox-default/patch-3.14.15-16.patch b/patch/kernel/cubox-default/patch-3.14.15-16.patch new file mode 100644 index 000000000..346b10378 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.15-16.patch @@ -0,0 +1,1740 @@ +diff --git a/Documentation/x86/x86_64/mm.txt b/Documentation/x86/x86_64/mm.txt +index c584a51add15..afe68ddbe6a4 100644 +--- a/Documentation/x86/x86_64/mm.txt ++++ b/Documentation/x86/x86_64/mm.txt +@@ -12,6 +12,8 @@ ffffc90000000000 - ffffe8ffffffffff (=45 bits) vmalloc/ioremap space + ffffe90000000000 - ffffe9ffffffffff (=40 bits) hole + ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB) + ... unused hole ... ++ffffff0000000000 - ffffff7fffffffff (=39 bits) %esp fixup stacks ++... unused hole ... + ffffffff80000000 - ffffffffa0000000 (=512 MB) kernel text mapping, from phys 0 + ffffffffa0000000 - ffffffffff5fffff (=1525 MB) module mapping space + ffffffffff600000 - ffffffffffdfffff (=8 MB) vsyscalls +diff --git a/Makefile b/Makefile +index 188523e9e880..8b22e24a2d8e 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 15 ++SUBLEVEL = 16 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts +index 5babba0a3a75..904dcf5973f3 100644 +--- a/arch/arm/boot/dts/dra7-evm.dts ++++ b/arch/arm/boot/dts/dra7-evm.dts +@@ -182,6 +182,7 @@ + regulator-name = "ldo3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; ++ regulator-always-on; + regulator-boot-on; + }; + +diff --git a/arch/arm/boot/dts/hi3620.dtsi b/arch/arm/boot/dts/hi3620.dtsi +index ab1116d086be..83a5b8685bd9 100644 +--- a/arch/arm/boot/dts/hi3620.dtsi ++++ b/arch/arm/boot/dts/hi3620.dtsi +@@ -73,7 +73,7 @@ + + L2: l2-cache { + compatible = "arm,pl310-cache"; +- reg = <0xfc10000 0x100000>; ++ reg = <0x100000 0x100000>; + interrupts = <0 15 4>; + cache-unified; + cache-level = <2>; +diff --git a/arch/arm/crypto/aesbs-glue.c b/arch/arm/crypto/aesbs-glue.c +index 4522366da759..15468fbbdea3 100644 +--- a/arch/arm/crypto/aesbs-glue.c ++++ b/arch/arm/crypto/aesbs-glue.c +@@ -137,7 +137,7 @@ static int aesbs_cbc_encrypt(struct blkcipher_desc *desc, + dst += AES_BLOCK_SIZE; + } while (--blocks); + } +- err = blkcipher_walk_done(desc, &walk, 0); ++ err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + } + return err; + } +@@ -158,7 +158,7 @@ static int aesbs_cbc_decrypt(struct blkcipher_desc *desc, + bsaes_cbc_encrypt(walk.src.virt.addr, walk.dst.virt.addr, + walk.nbytes, &ctx->dec, walk.iv); + kernel_neon_end(); +- err = blkcipher_walk_done(desc, &walk, 0); ++ err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + } + while (walk.nbytes) { + u32 blocks = walk.nbytes / AES_BLOCK_SIZE; +@@ -182,7 +182,7 @@ static int aesbs_cbc_decrypt(struct blkcipher_desc *desc, + dst += AES_BLOCK_SIZE; + src += AES_BLOCK_SIZE; + } while (--blocks); +- err = blkcipher_walk_done(desc, &walk, 0); ++ err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + } + return err; + } +@@ -268,7 +268,7 @@ static int aesbs_xts_encrypt(struct blkcipher_desc *desc, + bsaes_xts_encrypt(walk.src.virt.addr, walk.dst.virt.addr, + walk.nbytes, &ctx->enc, walk.iv); + kernel_neon_end(); +- err = blkcipher_walk_done(desc, &walk, 0); ++ err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + } + return err; + } +@@ -292,7 +292,7 @@ static int aesbs_xts_decrypt(struct blkcipher_desc *desc, + bsaes_xts_decrypt(walk.src.virt.addr, walk.dst.virt.addr, + walk.nbytes, &ctx->dec, walk.iv); + kernel_neon_end(); +- err = blkcipher_walk_done(desc, &walk, 0); ++ err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + } + return err; + } +diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c +index 8e0e52eb76b5..d7a0ee898d24 100644 +--- a/arch/arm/mm/idmap.c ++++ b/arch/arm/mm/idmap.c +@@ -25,6 +25,13 @@ static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, + pr_warning("Failed to allocate identity pmd.\n"); + return; + } ++ /* ++ * Copy the original PMD to ensure that the PMD entries for ++ * the kernel image are preserved. ++ */ ++ if (!pud_none(*pud)) ++ memcpy(pmd, pmd_offset(pud, 0), ++ PTRS_PER_PMD * sizeof(pmd_t)); + pud_populate(&init_mm, pud, pmd); + pmd += pmd_index(addr); + } else +diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c +index b68c6b22e1c8..f15c22e8bcd5 100644 +--- a/arch/arm/mm/mmu.c ++++ b/arch/arm/mm/mmu.c +@@ -1436,8 +1436,8 @@ void __init early_paging_init(const struct machine_desc *mdesc, + return; + + /* remap kernel code and data */ +- map_start = init_mm.start_code; +- map_end = init_mm.brk; ++ map_start = init_mm.start_code & PMD_MASK; ++ map_end = ALIGN(init_mm.brk, PMD_SIZE); + + /* get a handle on things... */ + pgd0 = pgd_offset_k(0); +@@ -1472,7 +1472,7 @@ void __init early_paging_init(const struct machine_desc *mdesc, + } + + /* remap pmds for kernel mapping */ +- phys = __pa(map_start) & PMD_MASK; ++ phys = __pa(map_start); + do { + *pmdk++ = __pmd(phys | pmdprot); + phys += PMD_SIZE; +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index 7324107acb40..c718d9f25900 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -966,10 +966,27 @@ config VM86 + default y + depends on X86_32 + ---help--- +- This option is required by programs like DOSEMU to run 16-bit legacy +- code on X86 processors. It also may be needed by software like +- XFree86 to initialize some video cards via BIOS. Disabling this +- option saves about 6k. ++ This option is required by programs like DOSEMU to run ++ 16-bit real mode legacy code on x86 processors. It also may ++ be needed by software like XFree86 to initialize some video ++ cards via BIOS. Disabling this option saves about 6K. ++ ++config X86_16BIT ++ bool "Enable support for 16-bit segments" if EXPERT ++ default y ++ ---help--- ++ This option is required by programs like Wine to run 16-bit ++ protected mode legacy code on x86 processors. Disabling ++ this option saves about 300 bytes on i386, or around 6K text ++ plus 16K runtime memory on x86-64, ++ ++config X86_ESPFIX32 ++ def_bool y ++ depends on X86_16BIT && X86_32 ++ ++config X86_ESPFIX64 ++ def_bool y ++ depends on X86_16BIT && X86_64 + + config TOSHIBA + tristate "Toshiba Laptop support" +diff --git a/arch/x86/include/asm/espfix.h b/arch/x86/include/asm/espfix.h +new file mode 100644 +index 000000000000..99efebb2f69d +--- /dev/null ++++ b/arch/x86/include/asm/espfix.h +@@ -0,0 +1,16 @@ ++#ifndef _ASM_X86_ESPFIX_H ++#define _ASM_X86_ESPFIX_H ++ ++#ifdef CONFIG_X86_64 ++ ++#include ++ ++DECLARE_PER_CPU_READ_MOSTLY(unsigned long, espfix_stack); ++DECLARE_PER_CPU_READ_MOSTLY(unsigned long, espfix_waddr); ++ ++extern void init_espfix_bsp(void); ++extern void init_espfix_ap(void); ++ ++#endif /* CONFIG_X86_64 */ ++ ++#endif /* _ASM_X86_ESPFIX_H */ +diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h +index bba3cf88e624..0a8b519226b8 100644 +--- a/arch/x86/include/asm/irqflags.h ++++ b/arch/x86/include/asm/irqflags.h +@@ -129,7 +129,7 @@ static inline notrace unsigned long arch_local_irq_save(void) + + #define PARAVIRT_ADJUST_EXCEPTION_FRAME /* */ + +-#define INTERRUPT_RETURN iretq ++#define INTERRUPT_RETURN jmp native_iret + #define USERGS_SYSRET64 \ + swapgs; \ + sysretq; +diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h +index c883bf726398..7166e25ecb57 100644 +--- a/arch/x86/include/asm/pgtable_64_types.h ++++ b/arch/x86/include/asm/pgtable_64_types.h +@@ -61,6 +61,8 @@ typedef struct { pteval_t pte; } pte_t; + #define MODULES_VADDR (__START_KERNEL_map + KERNEL_IMAGE_SIZE) + #define MODULES_END _AC(0xffffffffff000000, UL) + #define MODULES_LEN (MODULES_END - MODULES_VADDR) ++#define ESPFIX_PGD_ENTRY _AC(-2, UL) ++#define ESPFIX_BASE_ADDR (ESPFIX_PGD_ENTRY << PGDIR_SHIFT) + + #define EARLY_DYNAMIC_PAGE_TABLES 64 + +diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h +index d62c9f809bc5..75b14ca135be 100644 +--- a/arch/x86/include/asm/setup.h ++++ b/arch/x86/include/asm/setup.h +@@ -65,6 +65,8 @@ static inline void x86_ce4100_early_setup(void) { } + + #ifndef _SETUP + ++#include ++ + /* + * This is set up by the setup-routine at boot-time + */ +diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile +index cb648c84b327..56bac868cb91 100644 +--- a/arch/x86/kernel/Makefile ++++ b/arch/x86/kernel/Makefile +@@ -29,6 +29,7 @@ obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o + obj-y += syscall_$(BITS).o + obj-$(CONFIG_X86_64) += vsyscall_64.o + obj-$(CONFIG_X86_64) += vsyscall_emu_64.o ++obj-$(CONFIG_X86_ESPFIX64) += espfix_64.o + obj-$(CONFIG_SYSFS) += ksysfs.o + obj-y += bootflag.o e820.o + obj-y += pci-dma.o quirks.o topology.o kdebugfs.o +diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S +index c87810b1b557..c5a9cb94dee6 100644 +--- a/arch/x86/kernel/entry_32.S ++++ b/arch/x86/kernel/entry_32.S +@@ -529,6 +529,7 @@ syscall_exit: + restore_all: + TRACE_IRQS_IRET + restore_all_notrace: ++#ifdef CONFIG_X86_ESPFIX32 + movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS + # Warning: PT_OLDSS(%esp) contains the wrong/random values if we + # are returning to the kernel. +@@ -539,6 +540,7 @@ restore_all_notrace: + cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax + CFI_REMEMBER_STATE + je ldt_ss # returning to user-space with LDT SS ++#endif + restore_nocheck: + RESTORE_REGS 4 # skip orig_eax/error_code + irq_return: +@@ -551,6 +553,7 @@ ENTRY(iret_exc) + .previous + _ASM_EXTABLE(irq_return,iret_exc) + ++#ifdef CONFIG_X86_ESPFIX32 + CFI_RESTORE_STATE + ldt_ss: + #ifdef CONFIG_PARAVIRT +@@ -594,6 +597,7 @@ ldt_ss: + lss (%esp), %esp /* switch to espfix segment */ + CFI_ADJUST_CFA_OFFSET -8 + jmp restore_nocheck ++#endif + CFI_ENDPROC + ENDPROC(system_call) + +@@ -706,6 +710,7 @@ END(syscall_badsys) + * the high word of the segment base from the GDT and swiches to the + * normal stack and adjusts ESP with the matching offset. + */ ++#ifdef CONFIG_X86_ESPFIX32 + /* fixup the stack */ + mov GDT_ESPFIX_SS + 4, %al /* bits 16..23 */ + mov GDT_ESPFIX_SS + 7, %ah /* bits 24..31 */ +@@ -715,8 +720,10 @@ END(syscall_badsys) + pushl_cfi %eax + lss (%esp), %esp /* switch to the normal stack segment */ + CFI_ADJUST_CFA_OFFSET -8 ++#endif + .endm + .macro UNWIND_ESPFIX_STACK ++#ifdef CONFIG_X86_ESPFIX32 + movl %ss, %eax + /* see if on espfix stack */ + cmpw $__ESPFIX_SS, %ax +@@ -727,6 +734,7 @@ END(syscall_badsys) + /* switch to normal stack */ + FIXUP_ESPFIX_STACK + 27: ++#endif + .endm + + /* +@@ -1357,11 +1365,13 @@ END(debug) + ENTRY(nmi) + RING0_INT_FRAME + ASM_CLAC ++#ifdef CONFIG_X86_ESPFIX32 + pushl_cfi %eax + movl %ss, %eax + cmpw $__ESPFIX_SS, %ax + popl_cfi %eax + je nmi_espfix_stack ++#endif + cmpl $ia32_sysenter_target,(%esp) + je nmi_stack_fixup + pushl_cfi %eax +@@ -1401,6 +1411,7 @@ nmi_debug_stack_check: + FIX_STACK 24, nmi_stack_correct, 1 + jmp nmi_stack_correct + ++#ifdef CONFIG_X86_ESPFIX32 + nmi_espfix_stack: + /* We have a RING0_INT_FRAME here. + * +@@ -1422,6 +1433,7 @@ nmi_espfix_stack: + lss 12+4(%esp), %esp # back to espfix stack + CFI_ADJUST_CFA_OFFSET -24 + jmp irq_return ++#endif + CFI_ENDPROC + END(nmi) + +diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S +index 1e96c3628bf2..03cd2a8f6009 100644 +--- a/arch/x86/kernel/entry_64.S ++++ b/arch/x86/kernel/entry_64.S +@@ -58,6 +58,7 @@ + #include + #include + #include ++#include + #include + + /* Avoid __ASSEMBLER__'ifying just for this. */ +@@ -1041,12 +1042,45 @@ restore_args: + + irq_return: + INTERRUPT_RETURN +- _ASM_EXTABLE(irq_return, bad_iret) + +-#ifdef CONFIG_PARAVIRT + ENTRY(native_iret) ++ /* ++ * Are we returning to a stack segment from the LDT? Note: in ++ * 64-bit mode SS:RSP on the exception stack is always valid. ++ */ ++#ifdef CONFIG_X86_ESPFIX64 ++ testb $4,(SS-RIP)(%rsp) ++ jnz native_irq_return_ldt ++#endif ++ ++native_irq_return_iret: + iretq +- _ASM_EXTABLE(native_iret, bad_iret) ++ _ASM_EXTABLE(native_irq_return_iret, bad_iret) ++ ++#ifdef CONFIG_X86_ESPFIX64 ++native_irq_return_ldt: ++ pushq_cfi %rax ++ pushq_cfi %rdi ++ SWAPGS ++ movq PER_CPU_VAR(espfix_waddr),%rdi ++ movq %rax,(0*8)(%rdi) /* RAX */ ++ movq (2*8)(%rsp),%rax /* RIP */ ++ movq %rax,(1*8)(%rdi) ++ movq (3*8)(%rsp),%rax /* CS */ ++ movq %rax,(2*8)(%rdi) ++ movq (4*8)(%rsp),%rax /* RFLAGS */ ++ movq %rax,(3*8)(%rdi) ++ movq (6*8)(%rsp),%rax /* SS */ ++ movq %rax,(5*8)(%rdi) ++ movq (5*8)(%rsp),%rax /* RSP */ ++ movq %rax,(4*8)(%rdi) ++ andl $0xffff0000,%eax ++ popq_cfi %rdi ++ orq PER_CPU_VAR(espfix_stack),%rax ++ SWAPGS ++ movq %rax,%rsp ++ popq_cfi %rax ++ jmp native_irq_return_iret + #endif + + .section .fixup,"ax" +@@ -1110,9 +1144,40 @@ ENTRY(retint_kernel) + call preempt_schedule_irq + jmp exit_intr + #endif +- + CFI_ENDPROC + END(common_interrupt) ++ ++ /* ++ * If IRET takes a fault on the espfix stack, then we ++ * end up promoting it to a doublefault. In that case, ++ * modify the stack to make it look like we just entered ++ * the #GP handler from user space, similar to bad_iret. ++ */ ++#ifdef CONFIG_X86_ESPFIX64 ++ ALIGN ++__do_double_fault: ++ XCPT_FRAME 1 RDI+8 ++ movq RSP(%rdi),%rax /* Trap on the espfix stack? */ ++ sarq $PGDIR_SHIFT,%rax ++ cmpl $ESPFIX_PGD_ENTRY,%eax ++ jne do_double_fault /* No, just deliver the fault */ ++ cmpl $__KERNEL_CS,CS(%rdi) ++ jne do_double_fault ++ movq RIP(%rdi),%rax ++ cmpq $native_irq_return_iret,%rax ++ jne do_double_fault /* This shouldn't happen... */ ++ movq PER_CPU_VAR(kernel_stack),%rax ++ subq $(6*8-KERNEL_STACK_OFFSET),%rax /* Reset to original stack */ ++ movq %rax,RSP(%rdi) ++ movq $0,(%rax) /* Missing (lost) #GP error code */ ++ movq $general_protection,RIP(%rdi) ++ retq ++ CFI_ENDPROC ++END(__do_double_fault) ++#else ++# define __do_double_fault do_double_fault ++#endif ++ + /* + * End of kprobes section + */ +@@ -1314,7 +1379,7 @@ zeroentry overflow do_overflow + zeroentry bounds do_bounds + zeroentry invalid_op do_invalid_op + zeroentry device_not_available do_device_not_available +-paranoiderrorentry double_fault do_double_fault ++paranoiderrorentry double_fault __do_double_fault + zeroentry coprocessor_segment_overrun do_coprocessor_segment_overrun + errorentry invalid_TSS do_invalid_TSS + errorentry segment_not_present do_segment_not_present +@@ -1601,7 +1666,7 @@ error_sti: + */ + error_kernelspace: + incl %ebx +- leaq irq_return(%rip),%rcx ++ leaq native_irq_return_iret(%rip),%rcx + cmpq %rcx,RIP+8(%rsp) + je error_swapgs + movl %ecx,%eax /* zero extend */ +diff --git a/arch/x86/kernel/espfix_64.c b/arch/x86/kernel/espfix_64.c +new file mode 100644 +index 000000000000..94d857fb1033 +--- /dev/null ++++ b/arch/x86/kernel/espfix_64.c +@@ -0,0 +1,208 @@ ++/* ----------------------------------------------------------------------- * ++ * ++ * Copyright 2014 Intel Corporation; author: H. Peter Anvin ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * ----------------------------------------------------------------------- */ ++ ++/* ++ * The IRET instruction, when returning to a 16-bit segment, only ++ * restores the bottom 16 bits of the user space stack pointer. This ++ * causes some 16-bit software to break, but it also leaks kernel state ++ * to user space. ++ * ++ * This works around this by creating percpu "ministacks", each of which ++ * is mapped 2^16 times 64K apart. When we detect that the return SS is ++ * on the LDT, we copy the IRET frame to the ministack and use the ++ * relevant alias to return to userspace. The ministacks are mapped ++ * readonly, so if the IRET fault we promote #GP to #DF which is an IST ++ * vector and thus has its own stack; we then do the fixup in the #DF ++ * handler. ++ * ++ * This file sets up the ministacks and the related page tables. The ++ * actual ministack invocation is in entry_64.S. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * Note: we only need 6*8 = 48 bytes for the espfix stack, but round ++ * it up to a cache line to avoid unnecessary sharing. ++ */ ++#define ESPFIX_STACK_SIZE (8*8UL) ++#define ESPFIX_STACKS_PER_PAGE (PAGE_SIZE/ESPFIX_STACK_SIZE) ++ ++/* There is address space for how many espfix pages? */ ++#define ESPFIX_PAGE_SPACE (1UL << (PGDIR_SHIFT-PAGE_SHIFT-16)) ++ ++#define ESPFIX_MAX_CPUS (ESPFIX_STACKS_PER_PAGE * ESPFIX_PAGE_SPACE) ++#if CONFIG_NR_CPUS > ESPFIX_MAX_CPUS ++# error "Need more than one PGD for the ESPFIX hack" ++#endif ++ ++#define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO) ++ ++/* This contains the *bottom* address of the espfix stack */ ++DEFINE_PER_CPU_READ_MOSTLY(unsigned long, espfix_stack); ++DEFINE_PER_CPU_READ_MOSTLY(unsigned long, espfix_waddr); ++ ++/* Initialization mutex - should this be a spinlock? */ ++static DEFINE_MUTEX(espfix_init_mutex); ++ ++/* Page allocation bitmap - each page serves ESPFIX_STACKS_PER_PAGE CPUs */ ++#define ESPFIX_MAX_PAGES DIV_ROUND_UP(CONFIG_NR_CPUS, ESPFIX_STACKS_PER_PAGE) ++static void *espfix_pages[ESPFIX_MAX_PAGES]; ++ ++static __page_aligned_bss pud_t espfix_pud_page[PTRS_PER_PUD] ++ __aligned(PAGE_SIZE); ++ ++static unsigned int page_random, slot_random; ++ ++/* ++ * This returns the bottom address of the espfix stack for a specific CPU. ++ * The math allows for a non-power-of-two ESPFIX_STACK_SIZE, in which case ++ * we have to account for some amount of padding at the end of each page. ++ */ ++static inline unsigned long espfix_base_addr(unsigned int cpu) ++{ ++ unsigned long page, slot; ++ unsigned long addr; ++ ++ page = (cpu / ESPFIX_STACKS_PER_PAGE) ^ page_random; ++ slot = (cpu + slot_random) % ESPFIX_STACKS_PER_PAGE; ++ addr = (page << PAGE_SHIFT) + (slot * ESPFIX_STACK_SIZE); ++ addr = (addr & 0xffffUL) | ((addr & ~0xffffUL) << 16); ++ addr += ESPFIX_BASE_ADDR; ++ return addr; ++} ++ ++#define PTE_STRIDE (65536/PAGE_SIZE) ++#define ESPFIX_PTE_CLONES (PTRS_PER_PTE/PTE_STRIDE) ++#define ESPFIX_PMD_CLONES PTRS_PER_PMD ++#define ESPFIX_PUD_CLONES (65536/(ESPFIX_PTE_CLONES*ESPFIX_PMD_CLONES)) ++ ++#define PGTABLE_PROT ((_KERNPG_TABLE & ~_PAGE_RW) | _PAGE_NX) ++ ++static void init_espfix_random(void) ++{ ++ unsigned long rand; ++ ++ /* ++ * This is run before the entropy pools are initialized, ++ * but this is hopefully better than nothing. ++ */ ++ if (!arch_get_random_long(&rand)) { ++ /* The constant is an arbitrary large prime */ ++ rdtscll(rand); ++ rand *= 0xc345c6b72fd16123UL; ++ } ++ ++ slot_random = rand % ESPFIX_STACKS_PER_PAGE; ++ page_random = (rand / ESPFIX_STACKS_PER_PAGE) ++ & (ESPFIX_PAGE_SPACE - 1); ++} ++ ++void __init init_espfix_bsp(void) ++{ ++ pgd_t *pgd_p; ++ pteval_t ptemask; ++ ++ ptemask = __supported_pte_mask; ++ ++ /* Install the espfix pud into the kernel page directory */ ++ pgd_p = &init_level4_pgt[pgd_index(ESPFIX_BASE_ADDR)]; ++ pgd_populate(&init_mm, pgd_p, (pud_t *)espfix_pud_page); ++ ++ /* Randomize the locations */ ++ init_espfix_random(); ++ ++ /* The rest is the same as for any other processor */ ++ init_espfix_ap(); ++} ++ ++void init_espfix_ap(void) ++{ ++ unsigned int cpu, page; ++ unsigned long addr; ++ pud_t pud, *pud_p; ++ pmd_t pmd, *pmd_p; ++ pte_t pte, *pte_p; ++ int n; ++ void *stack_page; ++ pteval_t ptemask; ++ ++ /* We only have to do this once... */ ++ if (likely(this_cpu_read(espfix_stack))) ++ return; /* Already initialized */ ++ ++ cpu = smp_processor_id(); ++ addr = espfix_base_addr(cpu); ++ page = cpu/ESPFIX_STACKS_PER_PAGE; ++ ++ /* Did another CPU already set this up? */ ++ stack_page = ACCESS_ONCE(espfix_pages[page]); ++ if (likely(stack_page)) ++ goto done; ++ ++ mutex_lock(&espfix_init_mutex); ++ ++ /* Did we race on the lock? */ ++ stack_page = ACCESS_ONCE(espfix_pages[page]); ++ if (stack_page) ++ goto unlock_done; ++ ++ ptemask = __supported_pte_mask; ++ ++ pud_p = &espfix_pud_page[pud_index(addr)]; ++ pud = *pud_p; ++ if (!pud_present(pud)) { ++ pmd_p = (pmd_t *)__get_free_page(PGALLOC_GFP); ++ pud = __pud(__pa(pmd_p) | (PGTABLE_PROT & ptemask)); ++ paravirt_alloc_pmd(&init_mm, __pa(pmd_p) >> PAGE_SHIFT); ++ for (n = 0; n < ESPFIX_PUD_CLONES; n++) ++ set_pud(&pud_p[n], pud); ++ } ++ ++ pmd_p = pmd_offset(&pud, addr); ++ pmd = *pmd_p; ++ if (!pmd_present(pmd)) { ++ pte_p = (pte_t *)__get_free_page(PGALLOC_GFP); ++ pmd = __pmd(__pa(pte_p) | (PGTABLE_PROT & ptemask)); ++ paravirt_alloc_pte(&init_mm, __pa(pte_p) >> PAGE_SHIFT); ++ for (n = 0; n < ESPFIX_PMD_CLONES; n++) ++ set_pmd(&pmd_p[n], pmd); ++ } ++ ++ pte_p = pte_offset_kernel(&pmd, addr); ++ stack_page = (void *)__get_free_page(GFP_KERNEL); ++ pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask)); ++ for (n = 0; n < ESPFIX_PTE_CLONES; n++) ++ set_pte(&pte_p[n*PTE_STRIDE], pte); ++ ++ /* Job is done for this CPU and any CPU which shares this page */ ++ ACCESS_ONCE(espfix_pages[page]) = stack_page; ++ ++unlock_done: ++ mutex_unlock(&espfix_init_mutex); ++done: ++ this_cpu_write(espfix_stack, addr); ++ this_cpu_write(espfix_waddr, (unsigned long)stack_page ++ + (addr & ~PAGE_MASK)); ++} +diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c +index dcbbaa165bde..c37886d759cc 100644 +--- a/arch/x86/kernel/ldt.c ++++ b/arch/x86/kernel/ldt.c +@@ -20,8 +20,6 @@ + #include + #include + +-int sysctl_ldt16 = 0; +- + #ifdef CONFIG_SMP + static void flush_ldt(void *current_mm) + { +@@ -231,16 +229,10 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode) + } + } + +- /* +- * On x86-64 we do not support 16-bit segments due to +- * IRET leaking the high bits of the kernel stack address. +- */ +-#ifdef CONFIG_X86_64 +- if (!ldt_info.seg_32bit && !sysctl_ldt16) { ++ if (!IS_ENABLED(CONFIG_X86_16BIT) && !ldt_info.seg_32bit) { + error = -EINVAL; + goto out_unlock; + } +-#endif + + fill_ldt(&ldt, &ldt_info); + if (oldmode) +diff --git a/arch/x86/kernel/paravirt_patch_64.c b/arch/x86/kernel/paravirt_patch_64.c +index 3f08f34f93eb..a1da6737ba5b 100644 +--- a/arch/x86/kernel/paravirt_patch_64.c ++++ b/arch/x86/kernel/paravirt_patch_64.c +@@ -6,7 +6,6 @@ DEF_NATIVE(pv_irq_ops, irq_disable, "cli"); + DEF_NATIVE(pv_irq_ops, irq_enable, "sti"); + DEF_NATIVE(pv_irq_ops, restore_fl, "pushq %rdi; popfq"); + DEF_NATIVE(pv_irq_ops, save_fl, "pushfq; popq %rax"); +-DEF_NATIVE(pv_cpu_ops, iret, "iretq"); + DEF_NATIVE(pv_mmu_ops, read_cr2, "movq %cr2, %rax"); + DEF_NATIVE(pv_mmu_ops, read_cr3, "movq %cr3, %rax"); + DEF_NATIVE(pv_mmu_ops, write_cr3, "movq %rdi, %cr3"); +@@ -50,7 +49,6 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf, + PATCH_SITE(pv_irq_ops, save_fl); + PATCH_SITE(pv_irq_ops, irq_enable); + PATCH_SITE(pv_irq_ops, irq_disable); +- PATCH_SITE(pv_cpu_ops, iret); + PATCH_SITE(pv_cpu_ops, irq_enable_sysexit); + PATCH_SITE(pv_cpu_ops, usergs_sysret32); + PATCH_SITE(pv_cpu_ops, usergs_sysret64); +diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c +index a32da804252e..395be6d8bbde 100644 +--- a/arch/x86/kernel/smpboot.c ++++ b/arch/x86/kernel/smpboot.c +@@ -243,6 +243,13 @@ static void notrace start_secondary(void *unused) + check_tsc_sync_target(); + + /* ++ * Enable the espfix hack for this CPU ++ */ ++#ifdef CONFIG_X86_ESPFIX64 ++ init_espfix_ap(); ++#endif ++ ++ /* + * We need to hold vector_lock so there the set of online cpus + * does not change while we are assigning vectors to cpus. Holding + * this lock ensures we don't half assign or remove an irq from a cpu. +diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c +index 0002a3a33081..3620928631ce 100644 +--- a/arch/x86/mm/dump_pagetables.c ++++ b/arch/x86/mm/dump_pagetables.c +@@ -30,11 +30,13 @@ struct pg_state { + unsigned long start_address; + unsigned long current_address; + const struct addr_marker *marker; ++ unsigned long lines; + }; + + struct addr_marker { + unsigned long start_address; + const char *name; ++ unsigned long max_lines; + }; + + /* indices for address_markers; keep sync'd w/ address_markers below */ +@@ -45,6 +47,7 @@ enum address_markers_idx { + LOW_KERNEL_NR, + VMALLOC_START_NR, + VMEMMAP_START_NR, ++ ESPFIX_START_NR, + HIGH_KERNEL_NR, + MODULES_VADDR_NR, + MODULES_END_NR, +@@ -67,6 +70,7 @@ static struct addr_marker address_markers[] = { + { PAGE_OFFSET, "Low Kernel Mapping" }, + { VMALLOC_START, "vmalloc() Area" }, + { VMEMMAP_START, "Vmemmap" }, ++ { ESPFIX_BASE_ADDR, "ESPfix Area", 16 }, + { __START_KERNEL_map, "High Kernel Mapping" }, + { MODULES_VADDR, "Modules" }, + { MODULES_END, "End Modules" }, +@@ -163,7 +167,7 @@ static void note_page(struct seq_file *m, struct pg_state *st, + pgprot_t new_prot, int level) + { + pgprotval_t prot, cur; +- static const char units[] = "KMGTPE"; ++ static const char units[] = "BKMGTPE"; + + /* + * If we have a "break" in the series, we need to flush the state that +@@ -178,6 +182,7 @@ static void note_page(struct seq_file *m, struct pg_state *st, + st->current_prot = new_prot; + st->level = level; + st->marker = address_markers; ++ st->lines = 0; + seq_printf(m, "---[ %s ]---\n", st->marker->name); + } else if (prot != cur || level != st->level || + st->current_address >= st->marker[1].start_address) { +@@ -188,17 +193,21 @@ static void note_page(struct seq_file *m, struct pg_state *st, + /* + * Now print the actual finished series + */ +- seq_printf(m, "0x%0*lx-0x%0*lx ", +- width, st->start_address, +- width, st->current_address); +- +- delta = (st->current_address - st->start_address) >> 10; +- while (!(delta & 1023) && unit[1]) { +- delta >>= 10; +- unit++; ++ if (!st->marker->max_lines || ++ st->lines < st->marker->max_lines) { ++ seq_printf(m, "0x%0*lx-0x%0*lx ", ++ width, st->start_address, ++ width, st->current_address); ++ ++ delta = (st->current_address - st->start_address) >> 10; ++ while (!(delta & 1023) && unit[1]) { ++ delta >>= 10; ++ unit++; ++ } ++ seq_printf(m, "%9lu%c ", delta, *unit); ++ printk_prot(m, st->current_prot, st->level); + } +- seq_printf(m, "%9lu%c ", delta, *unit); +- printk_prot(m, st->current_prot, st->level); ++ st->lines++; + + /* + * We print markers for special areas of address space, +diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c +index f1d633a43f8e..d6bfb876cfb0 100644 +--- a/arch/x86/vdso/vdso32-setup.c ++++ b/arch/x86/vdso/vdso32-setup.c +@@ -41,7 +41,6 @@ enum { + #ifdef CONFIG_X86_64 + #define vdso_enabled sysctl_vsyscall32 + #define arch_setup_additional_pages syscall32_setup_pages +-extern int sysctl_ldt16; + #endif + + /* +@@ -381,13 +380,6 @@ static struct ctl_table abi_table2[] = { + .mode = 0644, + .proc_handler = proc_dointvec + }, +- { +- .procname = "ldt16", +- .data = &sysctl_ldt16, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = proc_dointvec +- }, + {} + }; + +diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c +index 0982233b9b84..a6a72ce8630f 100644 +--- a/arch/x86/xen/setup.c ++++ b/arch/x86/xen/setup.c +@@ -574,13 +574,7 @@ void xen_enable_syscall(void) + } + #endif /* CONFIG_X86_64 */ + } +-void xen_enable_nmi(void) +-{ +-#ifdef CONFIG_X86_64 +- if (register_callback(CALLBACKTYPE_nmi, (char *)nmi)) +- BUG(); +-#endif +-} ++ + void __init xen_pvmmu_arch_setup(void) + { + HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments); +@@ -595,7 +589,6 @@ void __init xen_pvmmu_arch_setup(void) + + xen_enable_sysenter(); + xen_enable_syscall(); +- xen_enable_nmi(); + } + + /* This function is not called for HVM domains */ +diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S +index f9e1ec346e35..8453e6e39895 100644 +--- a/arch/xtensa/kernel/vectors.S ++++ b/arch/xtensa/kernel/vectors.S +@@ -376,38 +376,42 @@ _DoubleExceptionVector_WindowOverflow: + beqz a2, 1f # if at start of vector, don't restore + + addi a0, a0, -128 +- bbsi a0, 8, 1f # don't restore except for overflow 8 and 12 +- bbsi a0, 7, 2f ++ bbsi.l a0, 8, 1f # don't restore except for overflow 8 and 12 ++ ++ /* ++ * This fixup handler is for the extremely unlikely case where the ++ * overflow handler's reference thru a0 gets a hardware TLB refill ++ * that bumps out the (distinct, aliasing) TLB entry that mapped its ++ * prior references thru a9/a13, and where our reference now thru ++ * a9/a13 gets a 2nd-level miss exception (not hardware TLB refill). ++ */ ++ movi a2, window_overflow_restore_a0_fixup ++ s32i a2, a3, EXC_TABLE_FIXUP ++ l32i a2, a3, EXC_TABLE_DOUBLE_SAVE ++ xsr a3, excsave1 ++ ++ bbsi.l a0, 7, 2f + + /* + * Restore a0 as saved by _WindowOverflow8(). +- * +- * FIXME: we really need a fixup handler for this L32E, +- * for the extremely unlikely case where the overflow handler's +- * reference thru a0 gets a hardware TLB refill that bumps out +- * the (distinct, aliasing) TLB entry that mapped its prior +- * references thru a9, and where our reference now thru a9 +- * gets a 2nd-level miss exception (not hardware TLB refill). + */ + +- l32e a2, a9, -16 +- wsr a2, depc # replace the saved a0 +- j 1f ++ l32e a0, a9, -16 ++ wsr a0, depc # replace the saved a0 ++ j 3f + + 2: + /* + * Restore a0 as saved by _WindowOverflow12(). +- * +- * FIXME: we really need a fixup handler for this L32E, +- * for the extremely unlikely case where the overflow handler's +- * reference thru a0 gets a hardware TLB refill that bumps out +- * the (distinct, aliasing) TLB entry that mapped its prior +- * references thru a13, and where our reference now thru a13 +- * gets a 2nd-level miss exception (not hardware TLB refill). + */ + +- l32e a2, a13, -16 +- wsr a2, depc # replace the saved a0 ++ l32e a0, a13, -16 ++ wsr a0, depc # replace the saved a0 ++3: ++ xsr a3, excsave1 ++ movi a0, 0 ++ s32i a0, a3, EXC_TABLE_FIXUP ++ s32i a2, a3, EXC_TABLE_DOUBLE_SAVE + 1: + /* + * Restore WindowBase while leaving all address registers restored. +@@ -449,6 +453,7 @@ _DoubleExceptionVector_WindowOverflow: + + s32i a0, a2, PT_DEPC + ++_DoubleExceptionVector_handle_exception: + addx4 a0, a0, a3 + l32i a0, a0, EXC_TABLE_FAST_USER + xsr a3, excsave1 +@@ -464,11 +469,120 @@ _DoubleExceptionVector_WindowOverflow: + rotw -3 + j 1b + +- .end literal_prefix + + ENDPROC(_DoubleExceptionVector) + + /* ++ * Fixup handler for TLB miss in double exception handler for window owerflow. ++ * We get here with windowbase set to the window that was being spilled and ++ * a0 trashed. a0 bit 7 determines if this is a call8 (bit clear) or call12 ++ * (bit set) window. ++ * ++ * We do the following here: ++ * - go to the original window retaining a0 value; ++ * - set up exception stack to return back to appropriate a0 restore code ++ * (we'll need to rotate window back and there's no place to save this ++ * information, use different return address for that); ++ * - handle the exception; ++ * - go to the window that was being spilled; ++ * - set up window_overflow_restore_a0_fixup as a fixup routine; ++ * - reload a0; ++ * - restore the original window; ++ * - reset the default fixup routine; ++ * - return to user. By the time we get to this fixup handler all information ++ * about the conditions of the original double exception that happened in ++ * the window overflow handler is lost, so we just return to userspace to ++ * retry overflow from start. ++ * ++ * a0: value of depc, original value in depc ++ * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE ++ * a3: exctable, original value in excsave1 ++ */ ++ ++ENTRY(window_overflow_restore_a0_fixup) ++ ++ rsr a0, ps ++ extui a0, a0, PS_OWB_SHIFT, PS_OWB_WIDTH ++ rsr a2, windowbase ++ sub a0, a2, a0 ++ extui a0, a0, 0, 3 ++ l32i a2, a3, EXC_TABLE_DOUBLE_SAVE ++ xsr a3, excsave1 ++ ++ _beqi a0, 1, .Lhandle_1 ++ _beqi a0, 3, .Lhandle_3 ++ ++ .macro overflow_fixup_handle_exception_pane n ++ ++ rsr a0, depc ++ rotw -\n ++ ++ xsr a3, excsave1 ++ wsr a2, depc ++ l32i a2, a3, EXC_TABLE_KSTK ++ s32i a0, a2, PT_AREG0 ++ ++ movi a0, .Lrestore_\n ++ s32i a0, a2, PT_DEPC ++ rsr a0, exccause ++ j _DoubleExceptionVector_handle_exception ++ ++ .endm ++ ++ overflow_fixup_handle_exception_pane 2 ++.Lhandle_1: ++ overflow_fixup_handle_exception_pane 1 ++.Lhandle_3: ++ overflow_fixup_handle_exception_pane 3 ++ ++ .macro overflow_fixup_restore_a0_pane n ++ ++ rotw \n ++ /* Need to preserve a0 value here to be able to handle exception ++ * that may occur on a0 reload from stack. It may occur because ++ * TLB miss handler may not be atomic and pointer to page table ++ * may be lost before we get here. There are no free registers, ++ * so we need to use EXC_TABLE_DOUBLE_SAVE area. ++ */ ++ xsr a3, excsave1 ++ s32i a2, a3, EXC_TABLE_DOUBLE_SAVE ++ movi a2, window_overflow_restore_a0_fixup ++ s32i a2, a3, EXC_TABLE_FIXUP ++ l32i a2, a3, EXC_TABLE_DOUBLE_SAVE ++ xsr a3, excsave1 ++ bbsi.l a0, 7, 1f ++ l32e a0, a9, -16 ++ j 2f ++1: ++ l32e a0, a13, -16 ++2: ++ rotw -\n ++ ++ .endm ++ ++.Lrestore_2: ++ overflow_fixup_restore_a0_pane 2 ++ ++.Lset_default_fixup: ++ xsr a3, excsave1 ++ s32i a2, a3, EXC_TABLE_DOUBLE_SAVE ++ movi a2, 0 ++ s32i a2, a3, EXC_TABLE_FIXUP ++ l32i a2, a3, EXC_TABLE_DOUBLE_SAVE ++ xsr a3, excsave1 ++ rfe ++ ++.Lrestore_1: ++ overflow_fixup_restore_a0_pane 1 ++ j .Lset_default_fixup ++.Lrestore_3: ++ overflow_fixup_restore_a0_pane 3 ++ j .Lset_default_fixup ++ ++ENDPROC(window_overflow_restore_a0_fixup) ++ ++ .end literal_prefix ++/* + * Debug interrupt vector + * + * There is not much space here, so simply jump to another handler. +diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S +index ee32c0085dff..d16db6df86f8 100644 +--- a/arch/xtensa/kernel/vmlinux.lds.S ++++ b/arch/xtensa/kernel/vmlinux.lds.S +@@ -269,13 +269,13 @@ SECTIONS + .UserExceptionVector.literal) + SECTION_VECTOR (_DoubleExceptionVector_literal, + .DoubleExceptionVector.literal, +- DOUBLEEXC_VECTOR_VADDR - 16, ++ DOUBLEEXC_VECTOR_VADDR - 40, + SIZEOF(.UserExceptionVector.text), + .UserExceptionVector.text) + SECTION_VECTOR (_DoubleExceptionVector_text, + .DoubleExceptionVector.text, + DOUBLEEXC_VECTOR_VADDR, +- 32, ++ 40, + .DoubleExceptionVector.literal) + + . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3; +diff --git a/crypto/af_alg.c b/crypto/af_alg.c +index 966f893711b3..6a3ad8011585 100644 +--- a/crypto/af_alg.c ++++ b/crypto/af_alg.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + struct alg_type_list { + const struct af_alg_type *type; +@@ -243,6 +244,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock) + + sock_init_data(newsock, sk2); + sock_graft(sk2, newsock); ++ security_sk_clone(sk, sk2); + + err = type->accept(ask->private, sk2); + if (err) { +diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c +index 199b52b7c3e1..153f4b92cc05 100644 +--- a/drivers/cpufreq/cpufreq.c ++++ b/drivers/cpufreq/cpufreq.c +@@ -1089,10 +1089,12 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, + * the creation of a brand new one. So we need to perform this update + * by invoking update_policy_cpu(). + */ +- if (frozen && cpu != policy->cpu) ++ if (frozen && cpu != policy->cpu) { + update_policy_cpu(policy, cpu); +- else ++ WARN_ON(kobject_move(&policy->kobj, &dev->kobj)); ++ } else { + policy->cpu = cpu; ++ } + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + cpumask_copy(policy->cpus, cpumask_of(cpu)); +diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c +index bfec313492b3..fe83d04784c8 100644 +--- a/drivers/iio/accel/bma180.c ++++ b/drivers/iio/accel/bma180.c +@@ -68,13 +68,13 @@ + /* Defaults values */ + #define BMA180_DEF_PMODE 0 + #define BMA180_DEF_BW 20 +-#define BMA180_DEF_SCALE 250 ++#define BMA180_DEF_SCALE 2452 + + /* Available values for sysfs */ + #define BMA180_FLP_FREQ_AVAILABLE \ + "10 20 40 75 150 300" + #define BMA180_SCALE_AVAILABLE \ +- "0.000130 0.000190 0.000250 0.000380 0.000500 0.000990 0.001980" ++ "0.001275 0.001863 0.002452 0.003727 0.004903 0.009709 0.019417" + + struct bma180_data { + struct i2c_client *client; +@@ -94,7 +94,7 @@ enum bma180_axis { + }; + + static int bw_table[] = { 10, 20, 40, 75, 150, 300 }; /* Hz */ +-static int scale_table[] = { 130, 190, 250, 380, 500, 990, 1980 }; ++static int scale_table[] = { 1275, 1863, 2452, 3727, 4903, 9709, 19417 }; + + static int bma180_get_acc_reg(struct bma180_data *data, enum bma180_axis axis) + { +@@ -376,6 +376,8 @@ static int bma180_write_raw(struct iio_dev *indio_dev, + mutex_unlock(&data->mutex); + return ret; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: ++ if (val2) ++ return -EINVAL; + mutex_lock(&data->mutex); + ret = bma180_set_bw(data, val); + mutex_unlock(&data->mutex); +diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c +index fe25042f056a..0f1d9b2ccdfa 100644 +--- a/drivers/iio/industrialio-buffer.c ++++ b/drivers/iio/industrialio-buffer.c +@@ -953,7 +953,7 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, + + /* Now we have the two masks, work from least sig and build up sizes */ + for_each_set_bit(out_ind, +- indio_dev->active_scan_mask, ++ buffer->scan_mask, + indio_dev->masklength) { + in_ind = find_next_bit(indio_dev->active_scan_mask, + indio_dev->masklength, +diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c +index 66c5d130c8c2..0e722c103562 100644 +--- a/drivers/md/dm-bufio.c ++++ b/drivers/md/dm-bufio.c +@@ -1541,7 +1541,7 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign + BUG_ON(block_size < 1 << SECTOR_SHIFT || + (block_size & (block_size - 1))); + +- c = kmalloc(sizeof(*c), GFP_KERNEL); ++ c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) { + r = -ENOMEM; + goto bad_client; +diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c +index c0ad90d91252..735e939a846d 100644 +--- a/drivers/md/dm-cache-target.c ++++ b/drivers/md/dm-cache-target.c +@@ -231,7 +231,7 @@ struct cache { + /* + * cache_size entries, dirty if set + */ +- dm_cblock_t nr_dirty; ++ atomic_t nr_dirty; + unsigned long *dirty_bitset; + + /* +@@ -493,7 +493,7 @@ static bool is_dirty(struct cache *cache, dm_cblock_t b) + static void set_dirty(struct cache *cache, dm_oblock_t oblock, dm_cblock_t cblock) + { + if (!test_and_set_bit(from_cblock(cblock), cache->dirty_bitset)) { +- cache->nr_dirty = to_cblock(from_cblock(cache->nr_dirty) + 1); ++ atomic_inc(&cache->nr_dirty); + policy_set_dirty(cache->policy, oblock); + } + } +@@ -502,8 +502,7 @@ static void clear_dirty(struct cache *cache, dm_oblock_t oblock, dm_cblock_t cbl + { + if (test_and_clear_bit(from_cblock(cblock), cache->dirty_bitset)) { + policy_clear_dirty(cache->policy, oblock); +- cache->nr_dirty = to_cblock(from_cblock(cache->nr_dirty) - 1); +- if (!from_cblock(cache->nr_dirty)) ++ if (atomic_dec_return(&cache->nr_dirty) == 0) + dm_table_event(cache->ti->table); + } + } +@@ -2286,7 +2285,7 @@ static int cache_create(struct cache_args *ca, struct cache **result) + atomic_set(&cache->quiescing_ack, 0); + + r = -ENOMEM; +- cache->nr_dirty = 0; ++ atomic_set(&cache->nr_dirty, 0); + cache->dirty_bitset = alloc_bitset(from_cblock(cache->cache_size)); + if (!cache->dirty_bitset) { + *error = "could not allocate dirty bitset"; +@@ -2828,7 +2827,7 @@ static void cache_status(struct dm_target *ti, status_type_t type, + + residency = policy_residency(cache->policy); + +- DMEMIT("%u %llu/%llu %u %llu/%llu %u %u %u %u %u %u %llu ", ++ DMEMIT("%u %llu/%llu %u %llu/%llu %u %u %u %u %u %u %lu ", + (unsigned)(DM_CACHE_METADATA_BLOCK_SIZE >> SECTOR_SHIFT), + (unsigned long long)(nr_blocks_metadata - nr_free_blocks_metadata), + (unsigned long long)nr_blocks_metadata, +@@ -2841,7 +2840,7 @@ static void cache_status(struct dm_target *ti, status_type_t type, + (unsigned) atomic_read(&cache->stats.write_miss), + (unsigned) atomic_read(&cache->stats.demotion), + (unsigned) atomic_read(&cache->stats.promotion), +- (unsigned long long) from_cblock(cache->nr_dirty)); ++ (unsigned long) atomic_read(&cache->nr_dirty)); + + if (writethrough_mode(&cache->features)) + DMEMIT("1 writethrough "); +diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c +index 0526ddff977d..0fe7674ad100 100644 +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -890,6 +890,15 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, + + tx_info = IEEE80211_SKB_CB(skb); + tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT; ++ ++ /* ++ * No aggregation session is running, but there may be frames ++ * from a previous session or a failed attempt in the queue. ++ * Send them out as normal data frames ++ */ ++ if (!tid->active) ++ tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU; ++ + if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) { + bf->bf_state.bf_type = 0; + return bf; +diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c +index c31aa07b3ba5..da1c6cb1a41e 100644 +--- a/drivers/pnp/pnpacpi/core.c ++++ b/drivers/pnp/pnpacpi/core.c +@@ -339,8 +339,7 @@ static int __init acpi_pnp_match(struct device *dev, void *_pnp) + struct pnp_dev *pnp = _pnp; + + /* true means it matched */ +- return !acpi->physical_node_count +- && compare_pnp_id(pnp->id, acpi_device_hid(acpi)); ++ return pnp->data == acpi; + } + + static struct acpi_device * __init acpi_pnp_find_companion(struct device *dev) +diff --git a/drivers/rapidio/devices/tsi721_dma.c b/drivers/rapidio/devices/tsi721_dma.c +index 91245f5dbe81..47257b6eea84 100644 +--- a/drivers/rapidio/devices/tsi721_dma.c ++++ b/drivers/rapidio/devices/tsi721_dma.c +@@ -287,6 +287,12 @@ struct tsi721_tx_desc *tsi721_desc_get(struct tsi721_bdma_chan *bdma_chan) + "desc %p not ACKed\n", tx_desc); + } + ++ if (ret == NULL) { ++ dev_dbg(bdma_chan->dchan.device->dev, ++ "%s: unable to obtain tx descriptor\n", __func__); ++ goto err_out; ++ } ++ + i = bdma_chan->wr_count_next % bdma_chan->bd_num; + if (i == bdma_chan->bd_num - 1) { + i = 0; +@@ -297,7 +303,7 @@ struct tsi721_tx_desc *tsi721_desc_get(struct tsi721_bdma_chan *bdma_chan) + tx_desc->txd.phys = bdma_chan->bd_phys + + i * sizeof(struct tsi721_dma_desc); + tx_desc->hw_desc = &((struct tsi721_dma_desc *)bdma_chan->bd_base)[i]; +- ++err_out: + spin_unlock_bh(&bdma_chan->lock); + + return ret; +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index 62ec84b42e31..64e487a8bf59 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -831,6 +831,14 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) + scsi_next_command(cmd); + return; + } ++ } else if (blk_rq_bytes(req) == 0 && result && !sense_deferred) { ++ /* ++ * Certain non BLOCK_PC requests are commands that don't ++ * actually transfer anything (FLUSH), so cannot use ++ * good_bytes != blk_rq_bytes(req) as the signal for an error. ++ * This sets the error explicitly for the problem case. ++ */ ++ error = __scsi_error_from_host_byte(cmd, result); + } + + /* no bidi support for !REQ_TYPE_BLOCK_PC yet */ +diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c +index d7efd0173a9a..7d7578872a84 100644 +--- a/drivers/staging/vt6655/bssdb.c ++++ b/drivers/staging/vt6655/bssdb.c +@@ -983,7 +983,7 @@ start: + pDevice->byERPFlag &= ~(WLAN_SET_ERP_USE_PROTECTION(1)); + } + +- { ++ if (pDevice->eCommandState == WLAN_ASSOCIATE_WAIT) { + pDevice->byReAssocCount++; + /* 10 sec timeout */ + if ((pDevice->byReAssocCount > 10) && (!pDevice->bLinkPass)) { +diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c +index a952df1bf9d6..6f13f0e597f8 100644 +--- a/drivers/staging/vt6655/device_main.c ++++ b/drivers/staging/vt6655/device_main.c +@@ -2430,6 +2430,7 @@ static irqreturn_t device_intr(int irq, void *dev_instance) { + int handled = 0; + unsigned char byData = 0; + int ii = 0; ++ unsigned long flags; + // unsigned char byRSSI; + + MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr); +@@ -2455,7 +2456,8 @@ static irqreturn_t device_intr(int irq, void *dev_instance) { + + handled = 1; + MACvIntDisable(pDevice->PortOffset); +- spin_lock_irq(&pDevice->lock); ++ ++ spin_lock_irqsave(&pDevice->lock, flags); + + //Make sure current page is 0 + VNSvInPortB(pDevice->PortOffset + MAC_REG_PAGE1SEL, &byOrgPageSel); +@@ -2696,7 +2698,8 @@ static irqreturn_t device_intr(int irq, void *dev_instance) { + MACvSelectPage1(pDevice->PortOffset); + } + +- spin_unlock_irq(&pDevice->lock); ++ spin_unlock_irqrestore(&pDevice->lock, flags); ++ + MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); + + return IRQ_RETVAL(handled); +diff --git a/include/dt-bindings/pinctrl/dra.h b/include/dt-bindings/pinctrl/dra.h +index 002a2855c046..3d33794e4f3e 100644 +--- a/include/dt-bindings/pinctrl/dra.h ++++ b/include/dt-bindings/pinctrl/dra.h +@@ -30,7 +30,8 @@ + #define MUX_MODE14 0xe + #define MUX_MODE15 0xf + +-#define PULL_ENA (1 << 16) ++#define PULL_ENA (0 << 16) ++#define PULL_DIS (1 << 16) + #define PULL_UP (1 << 17) + #define INPUT_EN (1 << 18) + #define SLEWCONTROL (1 << 19) +@@ -38,10 +39,10 @@ + #define WAKEUP_EVENT (1 << 25) + + /* Active pin states */ +-#define PIN_OUTPUT 0 ++#define PIN_OUTPUT (0 | PULL_DIS) + #define PIN_OUTPUT_PULLUP (PIN_OUTPUT | PULL_ENA | PULL_UP) + #define PIN_OUTPUT_PULLDOWN (PIN_OUTPUT | PULL_ENA) +-#define PIN_INPUT INPUT_EN ++#define PIN_INPUT (INPUT_EN | PULL_DIS) + #define PIN_INPUT_SLEW (INPUT_EN | SLEWCONTROL) + #define PIN_INPUT_PULLUP (PULL_ENA | INPUT_EN | PULL_UP) + #define PIN_INPUT_PULLDOWN (PULL_ENA | INPUT_EN) +diff --git a/include/linux/printk.h b/include/linux/printk.h +index fa47e2708c01..cbf094f993f4 100644 +--- a/include/linux/printk.h ++++ b/include/linux/printk.h +@@ -132,9 +132,9 @@ asmlinkage __printf(1, 2) __cold + int printk(const char *fmt, ...); + + /* +- * Special printk facility for scheduler use only, _DO_NOT_USE_ ! ++ * Special printk facility for scheduler/timekeeping use only, _DO_NOT_USE_ ! + */ +-__printf(1, 2) __cold int printk_sched(const char *fmt, ...); ++__printf(1, 2) __cold int printk_deferred(const char *fmt, ...); + + /* + * Please don't use printk_ratelimit(), because it shares ratelimiting state +@@ -169,7 +169,7 @@ int printk(const char *s, ...) + return 0; + } + static inline __printf(1, 2) __cold +-int printk_sched(const char *s, ...) ++int printk_deferred(const char *s, ...) + { + return 0; + } +diff --git a/init/main.c b/init/main.c +index 9c7fd4c9249f..58c132d7de4b 100644 +--- a/init/main.c ++++ b/init/main.c +@@ -617,6 +617,10 @@ asmlinkage void __init start_kernel(void) + if (efi_enabled(EFI_RUNTIME_SERVICES)) + efi_enter_virtual_mode(); + #endif ++#ifdef CONFIG_X86_ESPFIX64 ++ /* Should be run before the first non-init thread is created */ ++ init_espfix_bsp(); ++#endif + thread_info_cache_init(); + cred_init(); + fork_init(totalram_pages); +diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c +index 4dae9cbe9259..8c086e6049b9 100644 +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -2468,7 +2468,7 @@ void wake_up_klogd(void) + preempt_enable(); + } + +-int printk_sched(const char *fmt, ...) ++int printk_deferred(const char *fmt, ...) + { + unsigned long flags; + va_list args; +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 0aae0fcec026..515e212421c0 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -1322,7 +1322,7 @@ out: + * leave kernel. + */ + if (p->mm && printk_ratelimit()) { +- printk_sched("process %d (%s) no longer affine to cpu%d\n", ++ printk_deferred("process %d (%s) no longer affine to cpu%d\n", + task_pid_nr(p), p->comm, cpu); + } + } +diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c +index ce852643854b..37dac98c0749 100644 +--- a/kernel/sched/deadline.c ++++ b/kernel/sched/deadline.c +@@ -329,7 +329,7 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se, + + if (!lag_once) { + lag_once = true; +- printk_sched("sched: DL replenish lagged to much\n"); ++ printk_deferred("sched: DL replenish lagged to much\n"); + } + dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline; + dl_se->runtime = pi_se->dl_runtime; +diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c +index 1999021042c7..27b8e836307f 100644 +--- a/kernel/sched/rt.c ++++ b/kernel/sched/rt.c +@@ -837,7 +837,7 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq) + + if (!once) { + once = true; +- printk_sched("sched: RT throttling activated\n"); ++ printk_deferred("sched: RT throttling activated\n"); + } + } else { + /* +diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c +index 086ad6043bcb..60ba1af801c3 100644 +--- a/kernel/time/clockevents.c ++++ b/kernel/time/clockevents.c +@@ -146,7 +146,8 @@ static int clockevents_increase_min_delta(struct clock_event_device *dev) + { + /* Nothing to do if we already reached the limit */ + if (dev->min_delta_ns >= MIN_DELTA_LIMIT) { +- printk(KERN_WARNING "CE: Reprogramming failure. Giving up\n"); ++ printk_deferred(KERN_WARNING ++ "CE: Reprogramming failure. Giving up\n"); + dev->next_event.tv64 = KTIME_MAX; + return -ETIME; + } +@@ -159,9 +160,10 @@ static int clockevents_increase_min_delta(struct clock_event_device *dev) + if (dev->min_delta_ns > MIN_DELTA_LIMIT) + dev->min_delta_ns = MIN_DELTA_LIMIT; + +- printk(KERN_WARNING "CE: %s increased min_delta_ns to %llu nsec\n", +- dev->name ? dev->name : "?", +- (unsigned long long) dev->min_delta_ns); ++ printk_deferred(KERN_WARNING ++ "CE: %s increased min_delta_ns to %llu nsec\n", ++ dev->name ? dev->name : "?", ++ (unsigned long long) dev->min_delta_ns); + return 0; + } + +diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c +index 4d23dc4d8139..313a662911b1 100644 +--- a/kernel/time/sched_clock.c ++++ b/kernel/time/sched_clock.c +@@ -204,7 +204,8 @@ void __init sched_clock_postinit(void) + + static int sched_clock_suspend(void) + { +- sched_clock_poll(&sched_clock_timer); ++ update_sched_clock(); ++ hrtimer_cancel(&sched_clock_timer); + cd.suspended = true; + return 0; + } +@@ -212,6 +213,7 @@ static int sched_clock_suspend(void) + static void sched_clock_resume(void) + { + cd.epoch_cyc = read_sched_clock(); ++ hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL); + cd.suspended = false; + } + +diff --git a/lib/btree.c b/lib/btree.c +index f9a484676cb6..4264871ea1a0 100644 +--- a/lib/btree.c ++++ b/lib/btree.c +@@ -198,6 +198,7 @@ EXPORT_SYMBOL_GPL(btree_init); + + void btree_destroy(struct btree_head *head) + { ++ mempool_free(head->node, head->mempool); + mempool_destroy(head->mempool); + head->mempool = NULL; + } +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index 5b6b0039f725..9b35da28b587 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -5670,8 +5670,12 @@ static int mem_cgroup_oom_notify_cb(struct mem_cgroup *memcg) + { + struct mem_cgroup_eventfd_list *ev; + ++ spin_lock(&memcg_oom_lock); ++ + list_for_each_entry(ev, &memcg->oom_notify, list) + eventfd_signal(ev->eventfd, 1); ++ ++ spin_unlock(&memcg_oom_lock); + return 0; + } + +diff --git a/mm/page-writeback.c b/mm/page-writeback.c +index d013dba21429..9f45f87a5859 100644 +--- a/mm/page-writeback.c ++++ b/mm/page-writeback.c +@@ -1324,9 +1324,9 @@ static inline void bdi_dirty_limits(struct backing_dev_info *bdi, + *bdi_thresh = bdi_dirty_limit(bdi, dirty_thresh); + + if (bdi_bg_thresh) +- *bdi_bg_thresh = div_u64((u64)*bdi_thresh * +- background_thresh, +- dirty_thresh); ++ *bdi_bg_thresh = dirty_thresh ? div_u64((u64)*bdi_thresh * ++ background_thresh, ++ dirty_thresh) : 0; + + /* + * In order to avoid the stacked BDI deadlock we need +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 7e7f94755ab5..62e400d00e3f 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -2434,7 +2434,7 @@ static inline int + gfp_to_alloc_flags(gfp_t gfp_mask) + { + int alloc_flags = ALLOC_WMARK_MIN | ALLOC_CPUSET; +- const gfp_t wait = gfp_mask & __GFP_WAIT; ++ const bool atomic = !(gfp_mask & (__GFP_WAIT | __GFP_NO_KSWAPD)); + + /* __GFP_HIGH is assumed to be the same as ALLOC_HIGH to save a branch. */ + BUILD_BUG_ON(__GFP_HIGH != (__force gfp_t) ALLOC_HIGH); +@@ -2443,20 +2443,20 @@ gfp_to_alloc_flags(gfp_t gfp_mask) + * The caller may dip into page reserves a bit more if the caller + * cannot run direct reclaim, or if the caller has realtime scheduling + * policy or is asking for __GFP_HIGH memory. GFP_ATOMIC requests will +- * set both ALLOC_HARDER (!wait) and ALLOC_HIGH (__GFP_HIGH). ++ * set both ALLOC_HARDER (atomic == true) and ALLOC_HIGH (__GFP_HIGH). + */ + alloc_flags |= (__force int) (gfp_mask & __GFP_HIGH); + +- if (!wait) { ++ if (atomic) { + /* +- * Not worth trying to allocate harder for +- * __GFP_NOMEMALLOC even if it can't schedule. ++ * Not worth trying to allocate harder for __GFP_NOMEMALLOC even ++ * if it can't schedule. + */ +- if (!(gfp_mask & __GFP_NOMEMALLOC)) ++ if (!(gfp_mask & __GFP_NOMEMALLOC)) + alloc_flags |= ALLOC_HARDER; + /* +- * Ignore cpuset if GFP_ATOMIC (!wait) rather than fail alloc. +- * See also cpuset_zone_allowed() comment in kernel/cpuset.c. ++ * Ignore cpuset mems for GFP_ATOMIC rather than fail, see the ++ * comment for __cpuset_node_allowed_softwall(). + */ + alloc_flags &= ~ALLOC_CPUSET; + } else if (unlikely(rt_task(current)) && !in_interrupt()) +diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c +index ec6606325cda..1e05bbde47ba 100644 +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -1368,7 +1368,7 @@ static int pppol2tp_setsockopt(struct socket *sock, int level, int optname, + int err; + + if (level != SOL_PPPOL2TP) +- return udp_prot.setsockopt(sk, level, optname, optval, optlen); ++ return -EINVAL; + + if (optlen < sizeof(int)) + return -EINVAL; +@@ -1494,7 +1494,7 @@ static int pppol2tp_getsockopt(struct socket *sock, int level, int optname, + struct pppol2tp_session *ps; + + if (level != SOL_PPPOL2TP) +- return udp_prot.getsockopt(sk, level, optname, optval, optlen); ++ return -EINVAL; + + if (get_user(len, optlen)) + return -EFAULT; +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index c14c16a6d62d..e5a7ac2f3687 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -414,6 +414,9 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) + if (ieee80211_has_order(hdr->frame_control)) + return TX_CONTINUE; + ++ if (ieee80211_is_probe_req(hdr->frame_control)) ++ return TX_CONTINUE; ++ + if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) + info->hw_queue = tx->sdata->vif.cab_queue; + +@@ -464,6 +467,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) + { + struct sta_info *sta = tx->sta; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; + struct ieee80211_local *local = tx->local; + + if (unlikely(!sta)) +@@ -474,6 +478,15 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) + !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) { + int ac = skb_get_queue_mapping(tx->skb); + ++ /* only deauth, disassoc and action are bufferable MMPDUs */ ++ if (ieee80211_is_mgmt(hdr->frame_control) && ++ !ieee80211_is_deauth(hdr->frame_control) && ++ !ieee80211_is_disassoc(hdr->frame_control) && ++ !ieee80211_is_action(hdr->frame_control)) { ++ info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; ++ return TX_CONTINUE; ++ } ++ + ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n", + sta->sta.addr, sta->sta.aid, ac); + if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) +@@ -532,22 +545,8 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) + static ieee80211_tx_result debug_noinline + ieee80211_tx_h_ps_buf(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(tx->flags & IEEE80211_TX_PS_BUFFERED)) + return TX_CONTINUE; +- +- /* only deauth, disassoc and action are bufferable MMPDUs */ +- if (ieee80211_is_mgmt(hdr->frame_control) && +- !ieee80211_is_deauth(hdr->frame_control) && +- !ieee80211_is_disassoc(hdr->frame_control) && +- !ieee80211_is_action(hdr->frame_control)) { +- if (tx->flags & IEEE80211_TX_UNICAST) +- info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; +- return TX_CONTINUE; +- } +- + if (tx->flags & IEEE80211_TX_UNICAST) + return ieee80211_tx_h_unicast_ps_buf(tx); + else +diff --git a/net/wireless/trace.h b/net/wireless/trace.h +index fbcc23edee54..b89eb3990f0a 100644 +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -2068,7 +2068,8 @@ TRACE_EVENT(cfg80211_michael_mic_failure, + MAC_ASSIGN(addr, addr); + __entry->key_type = key_type; + __entry->key_id = key_id; +- memcpy(__entry->tsc, tsc, 6); ++ if (tsc) ++ memcpy(__entry->tsc, tsc, 6); + ), + TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT ", key type: %d, key id: %d, tsc: %pm", + NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->key_type, diff --git a/patch/kernel/cubox-default/patch-3.14.16-17.patch b/patch/kernel/cubox-default/patch-3.14.16-17.patch new file mode 100644 index 000000000..19c672077 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.16-17.patch @@ -0,0 +1,1765 @@ +diff --git a/Makefile b/Makefile +index 8b22e24a2d8e..12aac0325888 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 16 ++SUBLEVEL = 17 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h +index 0f9e94537eee..1a49ffdf9da9 100644 +--- a/arch/sparc/include/asm/pgtable_64.h ++++ b/arch/sparc/include/asm/pgtable_64.h +@@ -24,7 +24,8 @@ + + /* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB). + * The page copy blockops can use 0x6000000 to 0x8000000. +- * The TSB is mapped in the 0x8000000 to 0xa000000 range. ++ * The 8K TSB is mapped in the 0x8000000 to 0x8400000 range. ++ * The 4M TSB is mapped in the 0x8400000 to 0x8800000 range. + * The PROM resides in an area spanning 0xf0000000 to 0x100000000. + * The vmalloc area spans 0x100000000 to 0x200000000. + * Since modules need to be in the lowest 32-bits of the address space, +@@ -33,7 +34,8 @@ + * 0x400000000. + */ + #define TLBTEMP_BASE _AC(0x0000000006000000,UL) +-#define TSBMAP_BASE _AC(0x0000000008000000,UL) ++#define TSBMAP_8K_BASE _AC(0x0000000008000000,UL) ++#define TSBMAP_4M_BASE _AC(0x0000000008400000,UL) + #define MODULES_VADDR _AC(0x0000000010000000,UL) + #define MODULES_LEN _AC(0x00000000e0000000,UL) + #define MODULES_END _AC(0x00000000f0000000,UL) +@@ -71,6 +73,23 @@ + + #include + ++extern unsigned long sparc64_valid_addr_bitmap[]; ++ ++/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ ++static inline bool __kern_addr_valid(unsigned long paddr) ++{ ++ if ((paddr >> MAX_PHYS_ADDRESS_BITS) != 0UL) ++ return false; ++ return test_bit(paddr >> ILOG2_4MB, sparc64_valid_addr_bitmap); ++} ++ ++static inline bool kern_addr_valid(unsigned long addr) ++{ ++ unsigned long paddr = __pa(addr); ++ ++ return __kern_addr_valid(paddr); ++} ++ + /* Entries per page directory level. */ + #define PTRS_PER_PTE (1UL << (PAGE_SHIFT-3)) + #define PTRS_PER_PMD (1UL << PMD_BITS) +@@ -79,9 +98,12 @@ + /* Kernel has a separate 44bit address space. */ + #define FIRST_USER_ADDRESS 0 + +-#define pte_ERROR(e) __builtin_trap() +-#define pmd_ERROR(e) __builtin_trap() +-#define pgd_ERROR(e) __builtin_trap() ++#define pmd_ERROR(e) \ ++ pr_err("%s:%d: bad pmd %p(%016lx) seen at (%pS)\n", \ ++ __FILE__, __LINE__, &(e), pmd_val(e), __builtin_return_address(0)) ++#define pgd_ERROR(e) \ ++ pr_err("%s:%d: bad pgd %p(%016lx) seen at (%pS)\n", \ ++ __FILE__, __LINE__, &(e), pgd_val(e), __builtin_return_address(0)) + + #endif /* !(__ASSEMBLY__) */ + +@@ -258,8 +280,8 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot) + { + unsigned long mask, tmp; + +- /* SUN4U: 0x600307ffffffecb8 (negated == 0x9ffcf80000001347) +- * SUN4V: 0x30ffffffffffee17 (negated == 0xcf000000000011e8) ++ /* SUN4U: 0x630107ffffffec38 (negated == 0x9cfef800000013c7) ++ * SUN4V: 0x33ffffffffffee07 (negated == 0xcc000000000011f8) + * + * Even if we use negation tricks the result is still a 6 + * instruction sequence, so don't try to play fancy and just +@@ -289,10 +311,10 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot) + " .previous\n" + : "=r" (mask), "=r" (tmp) + : "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U | +- _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | _PAGE_PRESENT_4U | ++ _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | + _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4U), + "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V | +- _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | _PAGE_PRESENT_4V | ++ _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | + _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V)); + + return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask)); +@@ -633,7 +655,7 @@ static inline unsigned long pmd_large(pmd_t pmd) + { + pte_t pte = __pte(pmd_val(pmd)); + +- return (pte_val(pte) & _PAGE_PMD_HUGE) && pte_present(pte); ++ return pte_val(pte) & _PAGE_PMD_HUGE; + } + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE +@@ -719,20 +741,6 @@ static inline pmd_t pmd_mkwrite(pmd_t pmd) + return __pmd(pte_val(pte)); + } + +-static inline pmd_t pmd_mknotpresent(pmd_t pmd) +-{ +- unsigned long mask; +- +- if (tlb_type == hypervisor) +- mask = _PAGE_PRESENT_4V; +- else +- mask = _PAGE_PRESENT_4U; +- +- pmd_val(pmd) &= ~mask; +- +- return pmd; +-} +- + static inline pmd_t pmd_mksplitting(pmd_t pmd) + { + pte_t pte = __pte(pmd_val(pmd)); +@@ -757,6 +765,20 @@ static inline int pmd_present(pmd_t pmd) + + #define pmd_none(pmd) (!pmd_val(pmd)) + ++/* pmd_bad() is only called on non-trans-huge PMDs. Our encoding is ++ * very simple, it's just the physical address. PTE tables are of ++ * size PAGE_SIZE so make sure the sub-PAGE_SIZE bits are clear and ++ * the top bits outside of the range of any physical address size we ++ * support are clear as well. We also validate the physical itself. ++ */ ++#define pmd_bad(pmd) ((pmd_val(pmd) & ~PAGE_MASK) || \ ++ !__kern_addr_valid(pmd_val(pmd))) ++ ++#define pud_none(pud) (!pud_val(pud)) ++ ++#define pud_bad(pud) ((pud_val(pud) & ~PAGE_MASK) || \ ++ !__kern_addr_valid(pud_val(pud))) ++ + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + extern void set_pmd_at(struct mm_struct *mm, unsigned long addr, + pmd_t *pmdp, pmd_t pmd); +@@ -790,10 +812,7 @@ static inline unsigned long __pmd_page(pmd_t pmd) + #define pud_page_vaddr(pud) \ + ((unsigned long) __va(pud_val(pud))) + #define pud_page(pud) virt_to_page((void *)pud_page_vaddr(pud)) +-#define pmd_bad(pmd) (0) + #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0UL) +-#define pud_none(pud) (!pud_val(pud)) +-#define pud_bad(pud) (0) + #define pud_present(pud) (pud_val(pud) != 0U) + #define pud_clear(pudp) (pud_val(*(pudp)) = 0UL) + +@@ -893,6 +912,10 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *); + extern void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr, + pmd_t *pmd); + ++#define __HAVE_ARCH_PMDP_INVALIDATE ++extern void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, ++ pmd_t *pmdp); ++ + #define __HAVE_ARCH_PGTABLE_DEPOSIT + extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp, + pgtable_t pgtable); +@@ -919,18 +942,6 @@ extern unsigned long pte_file(pte_t); + extern pte_t pgoff_to_pte(unsigned long); + #define PTE_FILE_MAX_BITS (64UL - PAGE_SHIFT - 1UL) + +-extern unsigned long sparc64_valid_addr_bitmap[]; +- +-/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ +-static inline bool kern_addr_valid(unsigned long addr) +-{ +- unsigned long paddr = __pa(addr); +- +- if ((paddr >> 41UL) != 0UL) +- return false; +- return test_bit(paddr >> 22, sparc64_valid_addr_bitmap); +-} +- + extern int page_in_phys_avail(unsigned long paddr); + + /* +diff --git a/arch/sparc/include/asm/tlbflush_64.h b/arch/sparc/include/asm/tlbflush_64.h +index 3c3c89f52643..7f9bab26a499 100644 +--- a/arch/sparc/include/asm/tlbflush_64.h ++++ b/arch/sparc/include/asm/tlbflush_64.h +@@ -34,6 +34,8 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, + { + } + ++void flush_tlb_kernel_range(unsigned long start, unsigned long end); ++ + #define __HAVE_ARCH_ENTER_LAZY_MMU_MODE + + extern void flush_tlb_pending(void); +@@ -48,11 +50,6 @@ extern void __flush_tlb_kernel_range(unsigned long start, unsigned long end); + + #ifndef CONFIG_SMP + +-#define flush_tlb_kernel_range(start,end) \ +-do { flush_tsb_kernel_range(start,end); \ +- __flush_tlb_kernel_range(start,end); \ +-} while (0) +- + static inline void global_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr) + { + __flush_tlb_page(CTX_HWBITS(mm->context), vaddr); +@@ -63,11 +60,6 @@ static inline void global_flush_tlb_page(struct mm_struct *mm, unsigned long vad + extern void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end); + extern void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr); + +-#define flush_tlb_kernel_range(start, end) \ +-do { flush_tsb_kernel_range(start,end); \ +- smp_flush_tlb_kernel_range(start, end); \ +-} while (0) +- + #define global_flush_tlb_page(mm, vaddr) \ + smp_flush_tlb_page(mm, vaddr) + +diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h +index 2230f80d9fe3..90916f955cac 100644 +--- a/arch/sparc/include/asm/tsb.h ++++ b/arch/sparc/include/asm/tsb.h +@@ -171,7 +171,8 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; + andcc REG1, REG2, %g0; \ + be,pt %xcc, 700f; \ + sethi %hi(4 * 1024 * 1024), REG2; \ +- andn REG1, REG2, REG1; \ ++ brgez,pn REG1, FAIL_LABEL; \ ++ andn REG1, REG2, REG1; \ + and VADDR, REG2, REG2; \ + brlz,pt REG1, PTE_LABEL; \ + or REG1, REG2, REG1; \ +diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S +index 26b706a1867d..452f04fe8da6 100644 +--- a/arch/sparc/kernel/head_64.S ++++ b/arch/sparc/kernel/head_64.S +@@ -282,8 +282,8 @@ sun4v_chip_type: + stx %l2, [%l4 + 0x0] + ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low + /* 4MB align */ +- srlx %l3, 22, %l3 +- sllx %l3, 22, %l3 ++ srlx %l3, ILOG2_4MB, %l3 ++ sllx %l3, ILOG2_4MB, %l3 + stx %l3, [%l4 + 0x8] + + /* Leave service as-is, "call-method" */ +diff --git a/arch/sparc/kernel/ktlb.S b/arch/sparc/kernel/ktlb.S +index 542e96ac4d39..605d49204580 100644 +--- a/arch/sparc/kernel/ktlb.S ++++ b/arch/sparc/kernel/ktlb.S +@@ -277,7 +277,7 @@ kvmap_dtlb_load: + #ifdef CONFIG_SPARSEMEM_VMEMMAP + kvmap_vmemmap: + sub %g4, %g5, %g5 +- srlx %g5, 22, %g5 ++ srlx %g5, ILOG2_4MB, %g5 + sethi %hi(vmemmap_table), %g1 + sllx %g5, 3, %g5 + or %g1, %lo(vmemmap_table), %g1 +diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c +index e01d75d40329..66dacd56bb10 100644 +--- a/arch/sparc/kernel/ldc.c ++++ b/arch/sparc/kernel/ldc.c +@@ -1336,7 +1336,7 @@ int ldc_connect(struct ldc_channel *lp) + if (!(lp->flags & LDC_FLAG_ALLOCED_QUEUES) || + !(lp->flags & LDC_FLAG_REGISTERED_QUEUES) || + lp->hs_state != LDC_HS_OPEN) +- err = -EINVAL; ++ err = ((lp->hs_state > LDC_HS_OPEN) ? 0 : -EINVAL); + else + err = start_handshake(lp); + +diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c +index b085311dcd0e..8416d7fadcce 100644 +--- a/arch/sparc/kernel/smp_64.c ++++ b/arch/sparc/kernel/smp_64.c +@@ -151,7 +151,7 @@ void cpu_panic(void) + #define NUM_ROUNDS 64 /* magic value */ + #define NUM_ITERS 5 /* likewise */ + +-static DEFINE_SPINLOCK(itc_sync_lock); ++static DEFINE_RAW_SPINLOCK(itc_sync_lock); + static unsigned long go[SLAVE + 1]; + + #define DEBUG_TICK_SYNC 0 +@@ -259,7 +259,7 @@ static void smp_synchronize_one_tick(int cpu) + go[MASTER] = 0; + membar_safe("#StoreLoad"); + +- spin_lock_irqsave(&itc_sync_lock, flags); ++ raw_spin_lock_irqsave(&itc_sync_lock, flags); + { + for (i = 0; i < NUM_ROUNDS*NUM_ITERS; i++) { + while (!go[MASTER]) +@@ -270,7 +270,7 @@ static void smp_synchronize_one_tick(int cpu) + membar_safe("#StoreLoad"); + } + } +- spin_unlock_irqrestore(&itc_sync_lock, flags); ++ raw_spin_unlock_irqrestore(&itc_sync_lock, flags); + } + + #if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU) +diff --git a/arch/sparc/kernel/sys32.S b/arch/sparc/kernel/sys32.S +index f7c72b6efc27..d066eb18650c 100644 +--- a/arch/sparc/kernel/sys32.S ++++ b/arch/sparc/kernel/sys32.S +@@ -44,7 +44,7 @@ SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1) + SIGN1(sys32_io_submit, compat_sys_io_submit, %o1) + SIGN1(sys32_mq_open, compat_sys_mq_open, %o1) + SIGN1(sys32_select, compat_sys_select, %o0) +-SIGN3(sys32_futex, compat_sys_futex, %o1, %o2, %o5) ++SIGN1(sys32_futex, compat_sys_futex, %o1) + SIGN1(sys32_recvfrom, compat_sys_recvfrom, %o0) + SIGN1(sys32_recvmsg, compat_sys_recvmsg, %o0) + SIGN1(sys32_sendmsg, compat_sys_sendmsg, %o0) +diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c +index 3c1a7cb31579..35ab8b60d256 100644 +--- a/arch/sparc/kernel/unaligned_64.c ++++ b/arch/sparc/kernel/unaligned_64.c +@@ -166,17 +166,23 @@ static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs) + unsigned long compute_effective_address(struct pt_regs *regs, + unsigned int insn, unsigned int rd) + { ++ int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; + unsigned int rs1 = (insn >> 14) & 0x1f; + unsigned int rs2 = insn & 0x1f; +- int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; ++ unsigned long addr; + + if (insn & 0x2000) { + maybe_flush_windows(rs1, 0, rd, from_kernel); +- return (fetch_reg(rs1, regs) + sign_extend_imm13(insn)); ++ addr = (fetch_reg(rs1, regs) + sign_extend_imm13(insn)); + } else { + maybe_flush_windows(rs1, rs2, rd, from_kernel); +- return (fetch_reg(rs1, regs) + fetch_reg(rs2, regs)); ++ addr = (fetch_reg(rs1, regs) + fetch_reg(rs2, regs)); + } ++ ++ if (!from_kernel && test_thread_flag(TIF_32BIT)) ++ addr &= 0xffffffff; ++ ++ return addr; + } + + /* This is just to make gcc think die_if_kernel does return... */ +diff --git a/arch/sparc/lib/NG2memcpy.S b/arch/sparc/lib/NG2memcpy.S +index 2c20ad63ddbf..30eee6e8a81b 100644 +--- a/arch/sparc/lib/NG2memcpy.S ++++ b/arch/sparc/lib/NG2memcpy.S +@@ -236,6 +236,7 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ + */ + VISEntryHalf + ++ membar #Sync + alignaddr %o1, %g0, %g0 + + add %o1, (64 - 1), %o4 +diff --git a/arch/sparc/math-emu/math_32.c b/arch/sparc/math-emu/math_32.c +index aa4d55b0bdf0..5ce8f2f64604 100644 +--- a/arch/sparc/math-emu/math_32.c ++++ b/arch/sparc/math-emu/math_32.c +@@ -499,7 +499,7 @@ static int do_one_mathemu(u32 insn, unsigned long *pfsr, unsigned long *fregs) + case 0: fsr = *pfsr; + if (IR == -1) IR = 2; + /* fcc is always fcc0 */ +- fsr &= ~0xc00; fsr |= (IR << 10); break; ++ fsr &= ~0xc00; fsr |= (IR << 10); + *pfsr = fsr; + break; + case 1: rd->s = IR; break; +diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c +index 69bb818fdd79..4ced3fc66130 100644 +--- a/arch/sparc/mm/fault_64.c ++++ b/arch/sparc/mm/fault_64.c +@@ -96,38 +96,51 @@ static unsigned int get_user_insn(unsigned long tpc) + pte_t *ptep, pte; + unsigned long pa; + u32 insn = 0; +- unsigned long pstate; + +- if (pgd_none(*pgdp)) +- goto outret; ++ if (pgd_none(*pgdp) || unlikely(pgd_bad(*pgdp))) ++ goto out; + pudp = pud_offset(pgdp, tpc); +- if (pud_none(*pudp)) +- goto outret; +- pmdp = pmd_offset(pudp, tpc); +- if (pmd_none(*pmdp)) +- goto outret; ++ if (pud_none(*pudp) || unlikely(pud_bad(*pudp))) ++ goto out; + + /* This disables preemption for us as well. */ +- __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); +- __asm__ __volatile__("wrpr %0, %1, %%pstate" +- : : "r" (pstate), "i" (PSTATE_IE)); +- ptep = pte_offset_map(pmdp, tpc); +- pte = *ptep; +- if (!pte_present(pte)) +- goto out; ++ local_irq_disable(); ++ ++ pmdp = pmd_offset(pudp, tpc); ++ if (pmd_none(*pmdp) || unlikely(pmd_bad(*pmdp))) ++ goto out_irq_enable; + +- pa = (pte_pfn(pte) << PAGE_SHIFT); +- pa += (tpc & ~PAGE_MASK); ++#ifdef CONFIG_TRANSPARENT_HUGEPAGE ++ if (pmd_trans_huge(*pmdp)) { ++ if (pmd_trans_splitting(*pmdp)) ++ goto out_irq_enable; + +- /* Use phys bypass so we don't pollute dtlb/dcache. */ +- __asm__ __volatile__("lduwa [%1] %2, %0" +- : "=r" (insn) +- : "r" (pa), "i" (ASI_PHYS_USE_EC)); ++ pa = pmd_pfn(*pmdp) << PAGE_SHIFT; ++ pa += tpc & ~HPAGE_MASK; + ++ /* Use phys bypass so we don't pollute dtlb/dcache. */ ++ __asm__ __volatile__("lduwa [%1] %2, %0" ++ : "=r" (insn) ++ : "r" (pa), "i" (ASI_PHYS_USE_EC)); ++ } else ++#endif ++ { ++ ptep = pte_offset_map(pmdp, tpc); ++ pte = *ptep; ++ if (pte_present(pte)) { ++ pa = (pte_pfn(pte) << PAGE_SHIFT); ++ pa += (tpc & ~PAGE_MASK); ++ ++ /* Use phys bypass so we don't pollute dtlb/dcache. */ ++ __asm__ __volatile__("lduwa [%1] %2, %0" ++ : "=r" (insn) ++ : "r" (pa), "i" (ASI_PHYS_USE_EC)); ++ } ++ pte_unmap(ptep); ++ } ++out_irq_enable: ++ local_irq_enable(); + out: +- pte_unmap(ptep); +- __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); +-outret: + return insn; + } + +@@ -153,7 +166,8 @@ show_signal_msg(struct pt_regs *regs, int sig, int code, + } + + static void do_fault_siginfo(int code, int sig, struct pt_regs *regs, +- unsigned int insn, int fault_code) ++ unsigned long fault_addr, unsigned int insn, ++ int fault_code) + { + unsigned long addr; + siginfo_t info; +@@ -161,10 +175,18 @@ static void do_fault_siginfo(int code, int sig, struct pt_regs *regs, + info.si_code = code; + info.si_signo = sig; + info.si_errno = 0; +- if (fault_code & FAULT_CODE_ITLB) ++ if (fault_code & FAULT_CODE_ITLB) { + addr = regs->tpc; +- else +- addr = compute_effective_address(regs, insn, 0); ++ } else { ++ /* If we were able to probe the faulting instruction, use it ++ * to compute a precise fault address. Otherwise use the fault ++ * time provided address which may only have page granularity. ++ */ ++ if (insn) ++ addr = compute_effective_address(regs, insn, 0); ++ else ++ addr = fault_addr; ++ } + info.si_addr = (void __user *) addr; + info.si_trapno = 0; + +@@ -239,7 +261,7 @@ static void __kprobes do_kernel_fault(struct pt_regs *regs, int si_code, + /* The si_code was set to make clear whether + * this was a SEGV_MAPERR or SEGV_ACCERR fault. + */ +- do_fault_siginfo(si_code, SIGSEGV, regs, insn, fault_code); ++ do_fault_siginfo(si_code, SIGSEGV, regs, address, insn, fault_code); + return; + } + +@@ -259,18 +281,6 @@ static void noinline __kprobes bogus_32bit_fault_tpc(struct pt_regs *regs) + show_regs(regs); + } + +-static void noinline __kprobes bogus_32bit_fault_address(struct pt_regs *regs, +- unsigned long addr) +-{ +- static int times; +- +- if (times++ < 10) +- printk(KERN_ERR "FAULT[%s:%d]: 32-bit process " +- "reports 64-bit fault address [%lx]\n", +- current->comm, current->pid, addr); +- show_regs(regs); +-} +- + asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) + { + enum ctx_state prev_state = exception_enter(); +@@ -300,10 +310,8 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) + goto intr_or_no_mm; + } + } +- if (unlikely((address >> 32) != 0)) { +- bogus_32bit_fault_address(regs, address); ++ if (unlikely((address >> 32) != 0)) + goto intr_or_no_mm; +- } + } + + if (regs->tstate & TSTATE_PRIV) { +@@ -525,7 +533,7 @@ do_sigbus: + * Send a sigbus, regardless of whether we were in kernel + * or user mode. + */ +- do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, insn, fault_code); ++ do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, address, insn, fault_code); + + /* Kernel mode? Handle exceptions or die */ + if (regs->tstate & TSTATE_PRIV) +diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c +index c4d3da68b800..1aed0432c64b 100644 +--- a/arch/sparc/mm/gup.c ++++ b/arch/sparc/mm/gup.c +@@ -73,7 +73,7 @@ static int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr, + struct page *head, *page, *tail; + int refs; + +- if (!pmd_large(pmd)) ++ if (!(pmd_val(pmd) & _PAGE_VALID)) + return 0; + + if (write && !pmd_write(pmd)) +diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c +index eafbc65c9c47..96862241b342 100644 +--- a/arch/sparc/mm/init_64.c ++++ b/arch/sparc/mm/init_64.c +@@ -350,6 +350,10 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t * + + mm = vma->vm_mm; + ++ /* Don't insert a non-valid PTE into the TSB, we'll deadlock. */ ++ if (!pte_accessible(mm, pte)) ++ return; ++ + spin_lock_irqsave(&mm->context.lock, flags); + + #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) +@@ -588,7 +592,7 @@ static void __init remap_kernel(void) + int i, tlb_ent = sparc64_highest_locked_tlbent(); + + tte_vaddr = (unsigned long) KERNBASE; +- phys_page = (prom_boot_mapping_phys_low >> 22UL) << 22UL; ++ phys_page = (prom_boot_mapping_phys_low >> ILOG2_4MB) << ILOG2_4MB; + tte_data = kern_large_tte(phys_page); + + kern_locked_tte_data = tte_data; +@@ -1881,7 +1885,7 @@ void __init paging_init(void) + + BUILD_BUG_ON(NR_CPUS > 4096); + +- kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; ++ kern_base = (prom_boot_mapping_phys_low >> ILOG2_4MB) << ILOG2_4MB; + kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; + + /* Invalidate both kernel TSBs. */ +@@ -1937,7 +1941,7 @@ void __init paging_init(void) + shift = kern_base + PAGE_OFFSET - ((unsigned long)KERNBASE); + + real_end = (unsigned long)_end; +- num_kernel_image_mappings = DIV_ROUND_UP(real_end - KERNBASE, 1 << 22); ++ num_kernel_image_mappings = DIV_ROUND_UP(real_end - KERNBASE, 1 << ILOG2_4MB); + printk("Kernel: Using %d locked TLB entries for main kernel image.\n", + num_kernel_image_mappings); + +@@ -2094,7 +2098,7 @@ static void __init setup_valid_addr_bitmap_from_pavail(unsigned long *bitmap) + + if (new_start <= old_start && + new_end >= (old_start + PAGE_SIZE)) { +- set_bit(old_start >> 22, bitmap); ++ set_bit(old_start >> ILOG2_4MB, bitmap); + goto do_next_page; + } + } +@@ -2143,7 +2147,7 @@ void __init mem_init(void) + addr = PAGE_OFFSET + kern_base; + last = PAGE_ALIGN(kern_size) + addr; + while (addr < last) { +- set_bit(__pa(addr) >> 22, sparc64_valid_addr_bitmap); ++ set_bit(__pa(addr) >> ILOG2_4MB, sparc64_valid_addr_bitmap); + addr += PAGE_SIZE; + } + +@@ -2267,7 +2271,7 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend, + void *block; + + if (!(*vmem_pp & _PAGE_VALID)) { +- block = vmemmap_alloc_block(1UL << 22, node); ++ block = vmemmap_alloc_block(1UL << ILOG2_4MB, node); + if (!block) + return -ENOMEM; + +@@ -2614,6 +2618,10 @@ void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr, + + pte = pmd_val(entry); + ++ /* Don't insert a non-valid PMD into the TSB, we'll deadlock. */ ++ if (!(pte & _PAGE_VALID)) ++ return; ++ + /* We are fabricating 8MB pages using 4MB real hw pages. */ + pte |= (addr & (1UL << REAL_HPAGE_SHIFT)); + +@@ -2694,3 +2702,26 @@ void hugetlb_setup(struct pt_regs *regs) + } + } + #endif ++ ++#ifdef CONFIG_SMP ++#define do_flush_tlb_kernel_range smp_flush_tlb_kernel_range ++#else ++#define do_flush_tlb_kernel_range __flush_tlb_kernel_range ++#endif ++ ++void flush_tlb_kernel_range(unsigned long start, unsigned long end) ++{ ++ if (start < HI_OBP_ADDRESS && end > LOW_OBP_ADDRESS) { ++ if (start < LOW_OBP_ADDRESS) { ++ flush_tsb_kernel_range(start, LOW_OBP_ADDRESS); ++ do_flush_tlb_kernel_range(start, LOW_OBP_ADDRESS); ++ } ++ if (end > HI_OBP_ADDRESS) { ++ flush_tsb_kernel_range(end, HI_OBP_ADDRESS); ++ do_flush_tlb_kernel_range(end, HI_OBP_ADDRESS); ++ } ++ } else { ++ flush_tsb_kernel_range(start, end); ++ do_flush_tlb_kernel_range(start, end); ++ } ++} +diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c +index b12cb5e72812..b89aba217e3b 100644 +--- a/arch/sparc/mm/tlb.c ++++ b/arch/sparc/mm/tlb.c +@@ -134,7 +134,7 @@ no_cache_flush: + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + static void tlb_batch_pmd_scan(struct mm_struct *mm, unsigned long vaddr, +- pmd_t pmd, bool exec) ++ pmd_t pmd) + { + unsigned long end; + pte_t *pte; +@@ -142,8 +142,11 @@ static void tlb_batch_pmd_scan(struct mm_struct *mm, unsigned long vaddr, + pte = pte_offset_map(&pmd, vaddr); + end = vaddr + HPAGE_SIZE; + while (vaddr < end) { +- if (pte_val(*pte) & _PAGE_VALID) ++ if (pte_val(*pte) & _PAGE_VALID) { ++ bool exec = pte_exec(*pte); ++ + tlb_batch_add_one(mm, vaddr, exec); ++ } + pte++; + vaddr += PAGE_SIZE; + } +@@ -177,19 +180,30 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, + } + + if (!pmd_none(orig)) { +- pte_t orig_pte = __pte(pmd_val(orig)); +- bool exec = pte_exec(orig_pte); +- + addr &= HPAGE_MASK; + if (pmd_trans_huge(orig)) { ++ pte_t orig_pte = __pte(pmd_val(orig)); ++ bool exec = pte_exec(orig_pte); ++ + tlb_batch_add_one(mm, addr, exec); + tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec); + } else { +- tlb_batch_pmd_scan(mm, addr, orig, exec); ++ tlb_batch_pmd_scan(mm, addr, orig); + } + } + } + ++void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, ++ pmd_t *pmdp) ++{ ++ pmd_t entry = *pmdp; ++ ++ pmd_val(entry) &= ~_PAGE_VALID; ++ ++ set_pmd_at(vma->vm_mm, address, pmdp, entry); ++ flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); ++} ++ + void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp, + pgtable_t pgtable) + { +diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c +index f5d506fdddad..fe19b81acc09 100644 +--- a/arch/sparc/mm/tsb.c ++++ b/arch/sparc/mm/tsb.c +@@ -133,7 +133,19 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign + mm->context.tsb_block[tsb_idx].tsb_nentries = + tsb_bytes / sizeof(struct tsb); + +- base = TSBMAP_BASE; ++ switch (tsb_idx) { ++ case MM_TSB_BASE: ++ base = TSBMAP_8K_BASE; ++ break; ++#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) ++ case MM_TSB_HUGE: ++ base = TSBMAP_4M_BASE; ++ break; ++#endif ++ default: ++ BUG(); ++ } ++ + tte = pgprot_val(PAGE_KERNEL_LOCKED); + tsb_paddr = __pa(mm->context.tsb_block[tsb_idx].tsb); + BUG_ON(tsb_paddr & (tsb_bytes - 1UL)); +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +index 391f29ef6d2e..1fbeaa9dd202 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +@@ -337,6 +337,7 @@ struct sw_tx_bd { + u8 flags; + /* Set on the first BD descriptor when there is a split BD */ + #define BNX2X_TSO_SPLIT_BD (1<<0) ++#define BNX2X_HAS_SECOND_PBD (1<<1) + }; + + struct sw_rx_page { +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +index 5ed512473b12..afa4a1f63270 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +@@ -223,6 +223,12 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata, + --nbd; + bd_idx = TX_BD(NEXT_TX_IDX(bd_idx)); + ++ if (tx_buf->flags & BNX2X_HAS_SECOND_PBD) { ++ /* Skip second parse bd... */ ++ --nbd; ++ bd_idx = TX_BD(NEXT_TX_IDX(bd_idx)); ++ } ++ + /* TSO headers+data bds share a common mapping. See bnx2x_tx_split() */ + if (tx_buf->flags & BNX2X_TSO_SPLIT_BD) { + tx_data_bd = &txdata->tx_desc_ring[bd_idx].reg_bd; +@@ -3868,6 +3874,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + /* set encapsulation flag in start BD */ + SET_FLAG(tx_start_bd->general_data, + ETH_TX_START_BD_TUNNEL_EXIST, 1); ++ ++ tx_buf->flags |= BNX2X_HAS_SECOND_PBD; ++ + nbd++; + } else if (xmit_type & XMIT_CSUM) { + /* Set PBD in checksum offload case w/o encapsulation */ +diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c +index 4ad1187e82fb..669eeb4eb247 100644 +--- a/drivers/net/ethernet/brocade/bna/bnad.c ++++ b/drivers/net/ethernet/brocade/bna/bnad.c +@@ -600,9 +600,9 @@ bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget) + prefetch(bnad->netdev); + + cq = ccb->sw_q; +- cmpl = &cq[ccb->producer_index]; + + while (packets < budget) { ++ cmpl = &cq[ccb->producer_index]; + if (!cmpl->valid) + break; + /* The 'valid' field is set by the adapter, only after writing +diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c +index 5adecc5f52b7..7f1abb7c18f2 100644 +--- a/drivers/net/macvlan.c ++++ b/drivers/net/macvlan.c +@@ -548,6 +548,7 @@ static int macvlan_init(struct net_device *dev) + (lowerdev->state & MACVLAN_STATE_MASK); + dev->features = lowerdev->features & MACVLAN_FEATURES; + dev->features |= ALWAYS_ON_FEATURES; ++ dev->vlan_features = lowerdev->vlan_features & MACVLAN_FEATURES; + dev->gso_max_size = lowerdev->gso_max_size; + dev->iflink = lowerdev->ifindex; + dev->hard_header_len = lowerdev->hard_header_len; +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index 365375408904..25f74191a788 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -353,7 +353,7 @@ int phy_device_register(struct phy_device *phydev) + phydev->bus->phy_map[phydev->addr] = phydev; + + /* Run all of the fixups for this PHY */ +- err = phy_init_hw(phydev); ++ err = phy_scan_fixups(phydev); + if (err) { + pr_err("PHY %d failed to initialize\n", phydev->addr); + goto out; +diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c +index 01805319e1e0..1aff970be33e 100644 +--- a/drivers/net/ppp/pptp.c ++++ b/drivers/net/ppp/pptp.c +@@ -281,7 +281,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) + nf_reset(skb); + + skb->ip_summed = CHECKSUM_NONE; +- ip_select_ident(skb, &rt->dst, NULL); ++ ip_select_ident(skb, NULL); + ip_send_check(iph); + + ip_local_out(skb); +diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c +index 160e7510aca6..0787b9756165 100644 +--- a/drivers/sbus/char/bbc_envctrl.c ++++ b/drivers/sbus/char/bbc_envctrl.c +@@ -452,6 +452,9 @@ static void attach_one_temp(struct bbc_i2c_bus *bp, struct platform_device *op, + if (!tp) + return; + ++ INIT_LIST_HEAD(&tp->bp_list); ++ INIT_LIST_HEAD(&tp->glob_list); ++ + tp->client = bbc_i2c_attach(bp, op); + if (!tp->client) { + kfree(tp); +@@ -497,6 +500,9 @@ static void attach_one_fan(struct bbc_i2c_bus *bp, struct platform_device *op, + if (!fp) + return; + ++ INIT_LIST_HEAD(&fp->bp_list); ++ INIT_LIST_HEAD(&fp->glob_list); ++ + fp->client = bbc_i2c_attach(bp, op); + if (!fp->client) { + kfree(fp); +diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c +index c7763e482eb2..812b5f0361b6 100644 +--- a/drivers/sbus/char/bbc_i2c.c ++++ b/drivers/sbus/char/bbc_i2c.c +@@ -300,13 +300,18 @@ static struct bbc_i2c_bus * attach_one_i2c(struct platform_device *op, int index + if (!bp) + return NULL; + ++ INIT_LIST_HEAD(&bp->temps); ++ INIT_LIST_HEAD(&bp->fans); ++ + bp->i2c_control_regs = of_ioremap(&op->resource[0], 0, 0x2, "bbc_i2c_regs"); + if (!bp->i2c_control_regs) + goto fail; + +- bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel"); +- if (!bp->i2c_bussel_reg) +- goto fail; ++ if (op->num_resources == 2) { ++ bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel"); ++ if (!bp->i2c_bussel_reg) ++ goto fail; ++ } + + bp->waiting = 0; + init_waitqueue_head(&bp->wq); +diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c +index 80a58eca785b..e8f77606561b 100644 +--- a/drivers/tty/serial/sunsab.c ++++ b/drivers/tty/serial/sunsab.c +@@ -157,6 +157,15 @@ receive_chars(struct uart_sunsab_port *up, + (up->port.line == up->port.cons->index)) + saw_console_brk = 1; + ++ if (count == 0) { ++ if (unlikely(stat->sreg.isr1 & SAB82532_ISR1_BRK)) { ++ stat->sreg.isr0 &= ~(SAB82532_ISR0_PERR | ++ SAB82532_ISR0_FERR); ++ up->port.icount.brk++; ++ uart_handle_break(&up->port); ++ } ++ } ++ + for (i = 0; i < count; i++) { + unsigned char ch = buf[i], flag; + +diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h +index b0f4ef77fa70..bf9781e9fd92 100644 +--- a/fs/xfs/xfs_log.h ++++ b/fs/xfs/xfs_log.h +@@ -24,7 +24,8 @@ struct xfs_log_vec { + struct xfs_log_iovec *lv_iovecp; /* iovec array */ + struct xfs_log_item *lv_item; /* owner */ + char *lv_buf; /* formatted buffer */ +- int lv_buf_len; /* size of formatted buffer */ ++ int lv_bytes; /* accounted space in buffer */ ++ int lv_buf_len; /* aligned size of buffer */ + int lv_size; /* size of allocated lv */ + }; + +@@ -52,15 +53,21 @@ xlog_prepare_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec **vecp, + return vec->i_addr; + } + ++/* ++ * We need to make sure the next buffer is naturally aligned for the biggest ++ * basic data type we put into it. We already accounted for this padding when ++ * sizing the buffer. ++ * ++ * However, this padding does not get written into the log, and hence we have to ++ * track the space used by the log vectors separately to prevent log space hangs ++ * due to inaccurate accounting (i.e. a leak) of the used log space through the ++ * CIL context ticket. ++ */ + static inline void + xlog_finish_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec *vec, int len) + { +- /* +- * We need to make sure the next buffer is naturally aligned for the +- * biggest basic data type we put into it. We already accounted for +- * this when sizing the buffer. +- */ + lv->lv_buf_len += round_up(len, sizeof(uint64_t)); ++ lv->lv_bytes += len; + vec->i_len = len; + } + +diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c +index 4ef6fdbced78..bcfbaae4702c 100644 +--- a/fs/xfs/xfs_log_cil.c ++++ b/fs/xfs/xfs_log_cil.c +@@ -97,7 +97,7 @@ xfs_cil_prepare_item( + { + /* Account for the new LV being passed in */ + if (lv->lv_buf_len != XFS_LOG_VEC_ORDERED) { +- *diff_len += lv->lv_buf_len; ++ *diff_len += lv->lv_bytes; + *diff_iovecs += lv->lv_niovecs; + } + +@@ -111,7 +111,7 @@ xfs_cil_prepare_item( + else if (old_lv != lv) { + ASSERT(lv->lv_buf_len != XFS_LOG_VEC_ORDERED); + +- *diff_len -= old_lv->lv_buf_len; ++ *diff_len -= old_lv->lv_bytes; + *diff_iovecs -= old_lv->lv_niovecs; + kmem_free(old_lv); + } +@@ -239,7 +239,7 @@ xlog_cil_insert_format_items( + * that the space reservation accounting is correct. + */ + *diff_iovecs -= lv->lv_niovecs; +- *diff_len -= lv->lv_buf_len; ++ *diff_len -= lv->lv_bytes; + } else { + /* allocate new data chunk */ + lv = kmem_zalloc(buf_size, KM_SLEEP|KM_NOFS); +@@ -259,6 +259,7 @@ xlog_cil_insert_format_items( + + /* The allocated data region lies beyond the iovec region */ + lv->lv_buf_len = 0; ++ lv->lv_bytes = 0; + lv->lv_buf = (char *)lv + buf_size - nbytes; + ASSERT(IS_ALIGNED((unsigned long)lv->lv_buf, sizeof(uint64_t))); + +diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h +index 058271bde27a..823ec7bb9c67 100644 +--- a/include/net/inetpeer.h ++++ b/include/net/inetpeer.h +@@ -41,14 +41,13 @@ struct inet_peer { + struct rcu_head gc_rcu; + }; + /* +- * Once inet_peer is queued for deletion (refcnt == -1), following fields +- * are not available: rid, ip_id_count ++ * Once inet_peer is queued for deletion (refcnt == -1), following field ++ * is not available: rid + * We can share memory with rcu_head to help keep inet_peer small. + */ + union { + struct { + atomic_t rid; /* Frag reception counter */ +- atomic_t ip_id_count; /* IP ID for the next packet */ + }; + struct rcu_head rcu; + struct inet_peer *gc_next; +@@ -165,7 +164,7 @@ bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout); + void inetpeer_invalidate_tree(struct inet_peer_base *); + + /* +- * temporary check to make sure we dont access rid, ip_id_count, tcp_ts, ++ * temporary check to make sure we dont access rid, tcp_ts, + * tcp_ts_stamp if no refcount is taken on inet_peer + */ + static inline void inet_peer_refcheck(const struct inet_peer *p) +@@ -173,13 +172,4 @@ static inline void inet_peer_refcheck(const struct inet_peer *p) + WARN_ON_ONCE(atomic_read(&p->refcnt) <= 0); + } + +- +-/* can be called with or without local BH being disabled */ +-static inline int inet_getid(struct inet_peer *p, int more) +-{ +- more++; +- inet_peer_refcheck(p); +- return atomic_add_return(more, &p->ip_id_count) - more; +-} +- + #endif /* _NET_INETPEER_H */ +diff --git a/include/net/ip.h b/include/net/ip.h +index 23be0fd37937..937f19681426 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -297,9 +297,10 @@ static inline unsigned int ip_skb_dst_mtu(const struct sk_buff *skb) + } + } + +-void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more); ++u32 ip_idents_reserve(u32 hash, int segs); ++void __ip_select_ident(struct iphdr *iph, int segs); + +-static inline void ip_select_ident(struct sk_buff *skb, struct dst_entry *dst, struct sock *sk) ++static inline void ip_select_ident_segs(struct sk_buff *skb, struct sock *sk, int segs) + { + struct iphdr *iph = ip_hdr(skb); + +@@ -309,24 +310,20 @@ static inline void ip_select_ident(struct sk_buff *skb, struct dst_entry *dst, s + * does not change, they drop every other packet in + * a TCP stream using header compression. + */ +- iph->id = (sk && inet_sk(sk)->inet_daddr) ? +- htons(inet_sk(sk)->inet_id++) : 0; +- } else +- __ip_select_ident(iph, dst, 0); +-} +- +-static inline void ip_select_ident_more(struct sk_buff *skb, struct dst_entry *dst, struct sock *sk, int more) +-{ +- struct iphdr *iph = ip_hdr(skb); +- +- if ((iph->frag_off & htons(IP_DF)) && !skb->local_df) { + if (sk && inet_sk(sk)->inet_daddr) { + iph->id = htons(inet_sk(sk)->inet_id); +- inet_sk(sk)->inet_id += 1 + more; +- } else ++ inet_sk(sk)->inet_id += segs; ++ } else { + iph->id = 0; +- } else +- __ip_select_ident(iph, dst, more); ++ } ++ } else { ++ __ip_select_ident(iph, segs); ++ } ++} ++ ++static inline void ip_select_ident(struct sk_buff *skb, struct sock *sk) ++{ ++ ip_select_ident_segs(skb, sk, 1); + } + + /* +diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h +index e77c10405d51..7b9ec5837496 100644 +--- a/include/net/ip_tunnels.h ++++ b/include/net/ip_tunnels.h +@@ -40,6 +40,7 @@ struct ip_tunnel_prl_entry { + + struct ip_tunnel_dst { + struct dst_entry __rcu *dst; ++ __be32 saddr; + }; + + struct ip_tunnel { +diff --git a/include/net/ipv6.h b/include/net/ipv6.h +index 4f541f11ce63..9ac65781d44b 100644 +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -660,8 +660,6 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add + return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr)); + } + +-void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt); +- + int ip6_dst_hoplimit(struct dst_entry *dst); + + /* +diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h +index f257486f17be..3f36d45b714a 100644 +--- a/include/net/secure_seq.h ++++ b/include/net/secure_seq.h +@@ -3,8 +3,6 @@ + + #include + +-__u32 secure_ip_id(__be32 daddr); +-__u32 secure_ipv6_id(const __be32 daddr[4]); + u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport); + u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, + __be16 dport); +diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c +index cc1cfd60c094..c46387a46535 100644 +--- a/net/batman-adv/fragmentation.c ++++ b/net/batman-adv/fragmentation.c +@@ -128,6 +128,7 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node, + { + struct batadv_frag_table_entry *chain; + struct batadv_frag_list_entry *frag_entry_new = NULL, *frag_entry_curr; ++ struct batadv_frag_list_entry *frag_entry_last = NULL; + struct batadv_frag_packet *frag_packet; + uint8_t bucket; + uint16_t seqno, hdr_size = sizeof(struct batadv_frag_packet); +@@ -180,11 +181,14 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node, + ret = true; + goto out; + } ++ ++ /* store current entry because it could be the last in list */ ++ frag_entry_last = frag_entry_curr; + } + +- /* Reached the end of the list, so insert after 'frag_entry_curr'. */ +- if (likely(frag_entry_curr)) { +- hlist_add_after(&frag_entry_curr->list, &frag_entry_new->list); ++ /* Reached the end of the list, so insert after 'frag_entry_last'. */ ++ if (likely(frag_entry_last)) { ++ hlist_add_after(&frag_entry_last->list, &frag_entry_new->list); + chain->size += skb->len - hdr_size; + chain->timestamp = jiffies; + ret = true; +diff --git a/net/compat.c b/net/compat.c +index f50161fb812e..cbc1a2a26587 100644 +--- a/net/compat.c ++++ b/net/compat.c +@@ -85,7 +85,7 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, + { + int tot_len; + +- if (kern_msg->msg_namelen) { ++ if (kern_msg->msg_name && kern_msg->msg_namelen) { + if (mode == VERIFY_READ) { + int err = move_addr_to_kernel(kern_msg->msg_name, + kern_msg->msg_namelen, +@@ -93,10 +93,11 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, + if (err < 0) + return err; + } +- if (kern_msg->msg_name) +- kern_msg->msg_name = kern_address; +- } else ++ kern_msg->msg_name = kern_address; ++ } else { + kern_msg->msg_name = NULL; ++ kern_msg->msg_namelen = 0; ++ } + + tot_len = iov_from_user_compat_to_kern(kern_iov, + (struct compat_iovec __user *)kern_msg->msg_iov, +diff --git a/net/core/iovec.c b/net/core/iovec.c +index b61869429f4c..26dc0062652f 100644 +--- a/net/core/iovec.c ++++ b/net/core/iovec.c +@@ -39,7 +39,7 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a + { + int size, ct, err; + +- if (m->msg_namelen) { ++ if (m->msg_name && m->msg_namelen) { + if (mode == VERIFY_READ) { + void __user *namep; + namep = (void __user __force *) m->msg_name; +@@ -48,10 +48,10 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a + if (err < 0) + return err; + } +- if (m->msg_name) +- m->msg_name = address; ++ m->msg_name = address; + } else { + m->msg_name = NULL; ++ m->msg_namelen = 0; + } + + size = m->msg_iovlen * sizeof(struct iovec); +@@ -107,6 +107,10 @@ EXPORT_SYMBOL(memcpy_toiovecend); + int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, + int offset, int len) + { ++ /* No data? Done! */ ++ if (len == 0) ++ return 0; ++ + /* Skip over the finished iovecs */ + while (offset >= iov->iov_len) { + offset -= iov->iov_len; +diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c +index 897da56f3aff..ba71212f0251 100644 +--- a/net/core/secure_seq.c ++++ b/net/core/secure_seq.c +@@ -85,31 +85,6 @@ EXPORT_SYMBOL(secure_ipv6_port_ephemeral); + #endif + + #ifdef CONFIG_INET +-__u32 secure_ip_id(__be32 daddr) +-{ +- u32 hash[MD5_DIGEST_WORDS]; +- +- net_secret_init(); +- hash[0] = (__force __u32) daddr; +- hash[1] = net_secret[13]; +- hash[2] = net_secret[14]; +- hash[3] = net_secret[15]; +- +- md5_transform(hash, net_secret); +- +- return hash[0]; +-} +- +-__u32 secure_ipv6_id(const __be32 daddr[4]) +-{ +- __u32 hash[4]; +- +- net_secret_init(); +- memcpy(hash, daddr, 16); +- md5_transform(hash, net_secret); +- +- return hash[0]; +-} + + __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, + __be16 sport, __be16 dport) +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index 7f2e1fce706e..8f6391bbf509 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -2968,9 +2968,9 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb, + tail = nskb; + + __copy_skb_header(nskb, head_skb); +- nskb->mac_len = head_skb->mac_len; + + skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom); ++ skb_reset_mac_len(nskb); + + skb_copy_from_linear_data_offset(head_skb, -tnl_hlen, + nskb->data - tnl_hlen, +diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c +index 9db3b877fcaf..0ffcd4d64e0a 100644 +--- a/net/ipv4/igmp.c ++++ b/net/ipv4/igmp.c +@@ -369,7 +369,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) + pip->saddr = fl4.saddr; + pip->protocol = IPPROTO_IGMP; + pip->tot_len = 0; /* filled in later */ +- ip_select_ident(skb, &rt->dst, NULL); ++ ip_select_ident(skb, NULL); + ((u8 *)&pip[1])[0] = IPOPT_RA; + ((u8 *)&pip[1])[1] = 4; + ((u8 *)&pip[1])[2] = 0; +@@ -714,7 +714,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, + iph->daddr = dst; + iph->saddr = fl4.saddr; + iph->protocol = IPPROTO_IGMP; +- ip_select_ident(skb, &rt->dst, NULL); ++ ip_select_ident(skb, NULL); + ((u8 *)&iph[1])[0] = IPOPT_RA; + ((u8 *)&iph[1])[1] = 4; + ((u8 *)&iph[1])[2] = 0; +diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c +index 48f424465112..bf2cb4a4714b 100644 +--- a/net/ipv4/inetpeer.c ++++ b/net/ipv4/inetpeer.c +@@ -26,20 +26,7 @@ + * Theory of operations. + * We keep one entry for each peer IP address. The nodes contains long-living + * information about the peer which doesn't depend on routes. +- * At this moment this information consists only of ID field for the next +- * outgoing IP packet. This field is incremented with each packet as encoded +- * in inet_getid() function (include/net/inetpeer.h). +- * At the moment of writing this notes identifier of IP packets is generated +- * to be unpredictable using this code only for packets subjected +- * (actually or potentially) to defragmentation. I.e. DF packets less than +- * PMTU in size when local fragmentation is disabled use a constant ID and do +- * not use this code (see ip_select_ident() in include/net/ip.h). + * +- * Route cache entries hold references to our nodes. +- * New cache entries get references via lookup by destination IP address in +- * the avl tree. The reference is grabbed only when it's needed i.e. only +- * when we try to output IP packet which needs an unpredictable ID (see +- * __ip_select_ident() in net/ipv4/route.c). + * Nodes are removed only when reference counter goes to 0. + * When it's happened the node may be removed when a sufficient amount of + * time has been passed since its last use. The less-recently-used entry can +@@ -62,7 +49,6 @@ + * refcnt: atomically against modifications on other CPU; + * usually under some other lock to prevent node disappearing + * daddr: unchangeable +- * ip_id_count: atomic value (no lock needed) + */ + + static struct kmem_cache *peer_cachep __read_mostly; +@@ -497,10 +483,6 @@ relookup: + p->daddr = *daddr; + atomic_set(&p->refcnt, 1); + atomic_set(&p->rid, 0); +- atomic_set(&p->ip_id_count, +- (daddr->family == AF_INET) ? +- secure_ip_id(daddr->addr.a4) : +- secure_ipv6_id(daddr->addr.a6)); + p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW; + p->rate_tokens = 0; + /* 60*HZ is arbitrary, but chosen enough high so that the first +diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +index 73c6b63bba74..ed88d781248f 100644 +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -148,7 +148,7 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, + iph->daddr = (opt && opt->opt.srr ? opt->opt.faddr : daddr); + iph->saddr = saddr; + iph->protocol = sk->sk_protocol; +- ip_select_ident(skb, &rt->dst, sk); ++ ip_select_ident(skb, sk); + + if (opt && opt->opt.optlen) { + iph->ihl += opt->opt.optlen>>2; +@@ -386,8 +386,7 @@ packet_routed: + ip_options_build(skb, &inet_opt->opt, inet->inet_daddr, rt, 0); + } + +- ip_select_ident_more(skb, &rt->dst, sk, +- (skb_shinfo(skb)->gso_segs ?: 1) - 1); ++ ip_select_ident_segs(skb, sk, skb_shinfo(skb)->gso_segs ?: 1); + + skb->priority = sk->sk_priority; + skb->mark = sk->sk_mark; +@@ -1338,7 +1337,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk, + iph->ttl = ttl; + iph->protocol = sk->sk_protocol; + ip_copy_addrs(iph, fl4); +- ip_select_ident(skb, &rt->dst, sk); ++ ip_select_ident(skb, sk); + + if (opt) { + iph->ihl += opt->optlen>>2; +diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c +index 62cd9e0ae35b..0a4af0920af3 100644 +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -69,23 +69,25 @@ static unsigned int ip_tunnel_hash(__be32 key, __be32 remote) + } + + static void __tunnel_dst_set(struct ip_tunnel_dst *idst, +- struct dst_entry *dst) ++ struct dst_entry *dst, __be32 saddr) + { + struct dst_entry *old_dst; + + dst_clone(dst); + old_dst = xchg((__force struct dst_entry **)&idst->dst, dst); + dst_release(old_dst); ++ idst->saddr = saddr; + } + +-static void tunnel_dst_set(struct ip_tunnel *t, struct dst_entry *dst) ++static void tunnel_dst_set(struct ip_tunnel *t, ++ struct dst_entry *dst, __be32 saddr) + { +- __tunnel_dst_set(this_cpu_ptr(t->dst_cache), dst); ++ __tunnel_dst_set(this_cpu_ptr(t->dst_cache), dst, saddr); + } + + static void tunnel_dst_reset(struct ip_tunnel *t) + { +- tunnel_dst_set(t, NULL); ++ tunnel_dst_set(t, NULL, 0); + } + + void ip_tunnel_dst_reset_all(struct ip_tunnel *t) +@@ -93,20 +95,25 @@ void ip_tunnel_dst_reset_all(struct ip_tunnel *t) + int i; + + for_each_possible_cpu(i) +- __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL); ++ __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL, 0); + } + EXPORT_SYMBOL(ip_tunnel_dst_reset_all); + +-static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie) ++static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, ++ u32 cookie, __be32 *saddr) + { ++ struct ip_tunnel_dst *idst; + struct dst_entry *dst; + + rcu_read_lock(); +- dst = rcu_dereference(this_cpu_ptr(t->dst_cache)->dst); ++ idst = this_cpu_ptr(t->dst_cache); ++ dst = rcu_dereference(idst->dst); + if (dst && !atomic_inc_not_zero(&dst->__refcnt)) + dst = NULL; + if (dst) { +- if (dst->obsolete && dst->ops->check(dst, cookie) == NULL) { ++ if (!dst->obsolete || dst->ops->check(dst, cookie)) { ++ *saddr = idst->saddr; ++ } else { + tunnel_dst_reset(t); + dst_release(dst); + dst = NULL; +@@ -362,7 +369,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev) + + if (!IS_ERR(rt)) { + tdev = rt->dst.dev; +- tunnel_dst_set(tunnel, &rt->dst); ++ tunnel_dst_set(tunnel, &rt->dst, fl4.saddr); + ip_rt_put(rt); + } + if (dev->type != ARPHRD_ETHER) +@@ -606,7 +613,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, + init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr, + tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link); + +- rt = connected ? tunnel_rtable_get(tunnel, 0) : NULL; ++ rt = connected ? tunnel_rtable_get(tunnel, 0, &fl4.saddr) : NULL; + + if (!rt) { + rt = ip_route_output_key(tunnel->net, &fl4); +@@ -616,7 +623,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, + goto tx_error; + } + if (connected) +- tunnel_dst_set(tunnel, &rt->dst); ++ tunnel_dst_set(tunnel, &rt->dst, fl4.saddr); + } + + if (rt->dst.dev == dev) { +diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c +index 8d69626f2206..65b664d30fa1 100644 +--- a/net/ipv4/ip_tunnel_core.c ++++ b/net/ipv4/ip_tunnel_core.c +@@ -74,7 +74,7 @@ int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb, + iph->daddr = dst; + iph->saddr = src; + iph->ttl = ttl; +- __ip_select_ident(iph, &rt->dst, (skb_shinfo(skb)->gso_segs ?: 1) - 1); ++ __ip_select_ident(iph, skb_shinfo(skb)->gso_segs ?: 1); + + err = ip_local_out(skb); + if (unlikely(net_xmit_eval(err))) +diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c +index 28863570dd60..1149fc2290e2 100644 +--- a/net/ipv4/ipmr.c ++++ b/net/ipv4/ipmr.c +@@ -1663,7 +1663,7 @@ static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr) + iph->protocol = IPPROTO_IPIP; + iph->ihl = 5; + iph->tot_len = htons(skb->len); +- ip_select_ident(skb, skb_dst(skb), NULL); ++ ip_select_ident(skb, NULL); + ip_send_check(iph); + + memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); +diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c +index c04518f4850a..11c8d81fdc59 100644 +--- a/net/ipv4/raw.c ++++ b/net/ipv4/raw.c +@@ -389,7 +389,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, + iph->check = 0; + iph->tot_len = htons(length); + if (!iph->id) +- ip_select_ident(skb, &rt->dst, NULL); ++ ip_select_ident(skb, NULL); + + iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); + } +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 031553f8a306..ca5a01ed8ed6 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -89,6 +89,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -462,39 +463,45 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, + return neigh_create(&arp_tbl, pkey, dev); + } + +-/* +- * Peer allocation may fail only in serious out-of-memory conditions. However +- * we still can generate some output. +- * Random ID selection looks a bit dangerous because we have no chances to +- * select ID being unique in a reasonable period of time. +- * But broken packet identifier may be better than no packet at all. ++#define IP_IDENTS_SZ 2048u ++struct ip_ident_bucket { ++ atomic_t id; ++ u32 stamp32; ++}; ++ ++static struct ip_ident_bucket *ip_idents __read_mostly; ++ ++/* In order to protect privacy, we add a perturbation to identifiers ++ * if one generator is seldom used. This makes hard for an attacker ++ * to infer how many packets were sent between two points in time. + */ +-static void ip_select_fb_ident(struct iphdr *iph) ++u32 ip_idents_reserve(u32 hash, int segs) + { +- static DEFINE_SPINLOCK(ip_fb_id_lock); +- static u32 ip_fallback_id; +- u32 salt; ++ struct ip_ident_bucket *bucket = ip_idents + hash % IP_IDENTS_SZ; ++ u32 old = ACCESS_ONCE(bucket->stamp32); ++ u32 now = (u32)jiffies; ++ u32 delta = 0; ++ ++ if (old != now && cmpxchg(&bucket->stamp32, old, now) == old) ++ delta = prandom_u32_max(now - old); + +- spin_lock_bh(&ip_fb_id_lock); +- salt = secure_ip_id((__force __be32)ip_fallback_id ^ iph->daddr); +- iph->id = htons(salt & 0xFFFF); +- ip_fallback_id = salt; +- spin_unlock_bh(&ip_fb_id_lock); ++ return atomic_add_return(segs + delta, &bucket->id) - segs; + } ++EXPORT_SYMBOL(ip_idents_reserve); + +-void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more) ++void __ip_select_ident(struct iphdr *iph, int segs) + { +- struct net *net = dev_net(dst->dev); +- struct inet_peer *peer; ++ static u32 ip_idents_hashrnd __read_mostly; ++ u32 hash, id; + +- peer = inet_getpeer_v4(net->ipv4.peers, iph->daddr, 1); +- if (peer) { +- iph->id = htons(inet_getid(peer, more)); +- inet_putpeer(peer); +- return; +- } ++ net_get_random_once(&ip_idents_hashrnd, sizeof(ip_idents_hashrnd)); + +- ip_select_fb_ident(iph); ++ hash = jhash_3words((__force u32)iph->daddr, ++ (__force u32)iph->saddr, ++ iph->protocol, ++ ip_idents_hashrnd); ++ id = ip_idents_reserve(hash, segs); ++ iph->id = htons(id); + } + EXPORT_SYMBOL(__ip_select_ident); + +@@ -2718,6 +2725,12 @@ int __init ip_rt_init(void) + { + int rc = 0; + ++ ip_idents = kmalloc(IP_IDENTS_SZ * sizeof(*ip_idents), GFP_KERNEL); ++ if (!ip_idents) ++ panic("IP: failed to allocate ip_idents\n"); ++ ++ prandom_bytes(ip_idents, IP_IDENTS_SZ * sizeof(*ip_idents)); ++ + #ifdef CONFIG_IP_ROUTE_CLASSID + ip_rt_acct = __alloc_percpu(256 * sizeof(struct ip_rt_acct), __alignof__(struct ip_rt_acct)); + if (!ip_rt_acct) +diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c +index 06cae62bf208..6b1a5fd60598 100644 +--- a/net/ipv4/tcp_vegas.c ++++ b/net/ipv4/tcp_vegas.c +@@ -219,7 +219,8 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 acked, + * This is: + * (actual rate in segments) * baseRTT + */ +- target_cwnd = tp->snd_cwnd * vegas->baseRTT / rtt; ++ target_cwnd = (u64)tp->snd_cwnd * vegas->baseRTT; ++ do_div(target_cwnd, rtt); + + /* Calculate the difference between the window we had, + * and the window we would like to have. This quantity +diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c +index 326475a94865..603ad498e18a 100644 +--- a/net/ipv4/tcp_veno.c ++++ b/net/ipv4/tcp_veno.c +@@ -145,7 +145,7 @@ static void tcp_veno_cong_avoid(struct sock *sk, u32 ack, u32 acked, + + rtt = veno->minrtt; + +- target_cwnd = (tp->snd_cwnd * veno->basertt); ++ target_cwnd = (u64)tp->snd_cwnd * veno->basertt; + target_cwnd <<= V_PARAM_SHIFT; + do_div(target_cwnd, rtt); + +diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c +index 31b18152528f..1f564a1487a3 100644 +--- a/net/ipv4/xfrm4_mode_tunnel.c ++++ b/net/ipv4/xfrm4_mode_tunnel.c +@@ -117,12 +117,12 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) + + top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ? + 0 : (XFRM_MODE_SKB_CB(skb)->frag_off & htons(IP_DF)); +- ip_select_ident(skb, dst->child, NULL); + + top_iph->ttl = ip4_dst_hoplimit(dst->child); + + top_iph->saddr = x->props.saddr.a4; + top_iph->daddr = x->id.daddr.a4; ++ ip_select_ident(skb, NULL); + + return 0; + } +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index a62b610307ec..073e5a6fc631 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -537,6 +537,20 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) + skb_copy_secmark(to, from); + } + ++static void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) ++{ ++ static u32 ip6_idents_hashrnd __read_mostly; ++ u32 hash, id; ++ ++ net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd)); ++ ++ hash = __ipv6_addr_jhash(&rt->rt6i_dst.addr, ip6_idents_hashrnd); ++ hash = __ipv6_addr_jhash(&rt->rt6i_src.addr, hash); ++ ++ id = ip_idents_reserve(hash, 1); ++ fhdr->identification = htonl(id); ++} ++ + int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) + { + struct sk_buff *frag; +diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c +index b31a01263185..798eb0f79078 100644 +--- a/net/ipv6/output_core.c ++++ b/net/ipv6/output_core.c +@@ -7,29 +7,6 @@ + #include + #include + +-void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) +-{ +- static atomic_t ipv6_fragmentation_id; +- int ident; +- +-#if IS_ENABLED(CONFIG_IPV6) +- if (rt && !(rt->dst.flags & DST_NOPEER)) { +- struct inet_peer *peer; +- struct net *net; +- +- net = dev_net(rt->dst.dev); +- peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1); +- if (peer) { +- fhdr->identification = htonl(inet_getid(peer, 0)); +- inet_putpeer(peer); +- return; +- } +- } +-#endif +- ident = atomic_inc_return(&ipv6_fragmentation_id); +- fhdr->identification = htonl(ident); +-} +-EXPORT_SYMBOL(ipv6_select_ident); + + int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) + { +diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c +index c47444e4cf8c..7f0e1cf2d7e8 100644 +--- a/net/netfilter/ipvs/ip_vs_xmit.c ++++ b/net/netfilter/ipvs/ip_vs_xmit.c +@@ -883,7 +883,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, + iph->daddr = cp->daddr.ip; + iph->saddr = saddr; + iph->ttl = old_iph->ttl; +- ip_select_ident(skb, &rt->dst, NULL); ++ ip_select_ident(skb, NULL); + + /* Another hack: avoid icmp_send in ip_fragment */ + skb->local_df = 1; +diff --git a/net/sctp/associola.c b/net/sctp/associola.c +index a4d570126f5d..5d97d8fe4be7 100644 +--- a/net/sctp/associola.c ++++ b/net/sctp/associola.c +@@ -1151,6 +1151,7 @@ void sctp_assoc_update(struct sctp_association *asoc, + asoc->c = new->c; + asoc->peer.rwnd = new->peer.rwnd; + asoc->peer.sack_needed = new->peer.sack_needed; ++ asoc->peer.auth_capable = new->peer.auth_capable; + asoc->peer.i = new->peer.i; + sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL, + asoc->peer.i.initial_tsn, GFP_ATOMIC); +diff --git a/net/sctp/output.c b/net/sctp/output.c +index 0f4d15fc2627..8267b06c3646 100644 +--- a/net/sctp/output.c ++++ b/net/sctp/output.c +@@ -599,7 +599,7 @@ out: + return err; + no_route: + kfree_skb(nskb); +- IP_INC_STATS_BH(sock_net(asoc->base.sk), IPSTATS_MIB_OUTNOROUTES); ++ IP_INC_STATS(sock_net(asoc->base.sk), IPSTATS_MIB_OUTNOROUTES); + + /* FIXME: Returning the 'err' will effect all the associations + * associated with a socket, although only one of the paths of the +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index b10d04fa3933..3bea4ddc699d 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -176,9 +176,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, + attrs[XFRMA_ALG_AEAD] || + attrs[XFRMA_ALG_CRYPT] || + attrs[XFRMA_ALG_COMP] || +- attrs[XFRMA_TFCPAD] || +- (ntohl(p->id.spi) >= 0x10000)) +- ++ attrs[XFRMA_TFCPAD]) + goto out; + break; + +@@ -206,7 +204,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, + attrs[XFRMA_ALG_AUTH] || + attrs[XFRMA_ALG_AUTH_TRUNC] || + attrs[XFRMA_ALG_CRYPT] || +- attrs[XFRMA_TFCPAD]) ++ attrs[XFRMA_TFCPAD] || ++ (ntohl(p->id.spi) >= 0x10000)) + goto out; + break; + diff --git a/patch/kernel/cubox-default/patch-3.14.17-18.patch b/patch/kernel/cubox-default/patch-3.14.17-18.patch new file mode 100644 index 000000000..077896b31 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.17-18.patch @@ -0,0 +1,3331 @@ +diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt +index b8dd0df76952..0fd40b15e2d5 100644 +--- a/Documentation/sound/alsa/ALSA-Configuration.txt ++++ b/Documentation/sound/alsa/ALSA-Configuration.txt +@@ -2026,8 +2026,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. + ------------------- + + Module for sound cards based on the Asus AV66/AV100/AV200 chips, +- i.e., Xonar D1, DX, D2, D2X, DS, Essence ST (Deluxe), Essence STX, +- HDAV1.3 (Deluxe), and HDAV1.3 Slim. ++ i.e., Xonar D1, DX, D2, D2X, DS, DSX, Essence ST (Deluxe), ++ Essence STX (II), HDAV1.3 (Deluxe), and HDAV1.3 Slim. + + This module supports autoprobe and multiple cards. + +diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt +index b0714d8f678a..8dfb6a5f427d 100644 +--- a/Documentation/stable_kernel_rules.txt ++++ b/Documentation/stable_kernel_rules.txt +@@ -29,6 +29,9 @@ Rules on what kind of patches are accepted, and which ones are not, into the + + Procedure for submitting patches to the -stable tree: + ++ - If the patch covers files in net/ or drivers/net please follow netdev stable ++ submission guidelines as described in ++ Documentation/networking/netdev-FAQ.txt + - Send the patch, after verifying that it follows the above rules, to + stable@vger.kernel.org. You must note the upstream commit ID in the + changelog of your submission, as well as the kernel version you wish +diff --git a/Makefile b/Makefile +index 12aac0325888..05279d4f44c9 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 17 ++SUBLEVEL = 18 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi +index c6bd4d986c29..8775681df7ed 100644 +--- a/arch/arm/boot/dts/am4372.dtsi ++++ b/arch/arm/boot/dts/am4372.dtsi +@@ -161,9 +161,6 @@ + ti,hwmods = "mailbox"; + ti,mbox-num-users = <4>; + ti,mbox-num-fifos = <8>; +- ti,mbox-names = "wkup_m3"; +- ti,mbox-data = <0 0 0 0>; +- status = "disabled"; + }; + + timer1: timer@44e31000 { +diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h +index 43876245fc57..21ca0cebcab0 100644 +--- a/arch/arm/include/asm/unistd.h ++++ b/arch/arm/include/asm/unistd.h +@@ -15,7 +15,17 @@ + + #include + ++/* ++ * This may need to be greater than __NR_last_syscall+1 in order to ++ * account for the padding in the syscall table ++ */ + #define __NR_syscalls (384) ++ ++/* ++ * *NOTE*: This is a ghost syscall private to the kernel. Only the ++ * __kuser_cmpxchg code in entry-armv.S should be aware of its ++ * existence. Don't ever use this from user code. ++ */ + #define __ARM_NR_cmpxchg (__ARM_NR_BASE+0x00fff0) + + #define __ARCH_WANT_STAT64 +diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h +index fb5584d0cc05..c3776331f407 100644 +--- a/arch/arm/include/uapi/asm/unistd.h ++++ b/arch/arm/include/uapi/asm/unistd.h +@@ -410,11 +410,6 @@ + #define __NR_sched_getattr (__NR_SYSCALL_BASE+381) + + /* +- * This may need to be greater than __NR_last_syscall+1 in order to +- * account for the padding in the syscall table +- */ +- +-/* + * The following SWIs are ARM private. + */ + #define __ARM_NR_BASE (__NR_SYSCALL_BASE+0x0f0000) +@@ -425,12 +420,6 @@ + #define __ARM_NR_set_tls (__ARM_NR_BASE+5) + + /* +- * *NOTE*: This is a ghost syscall private to the kernel. Only the +- * __kuser_cmpxchg code in entry-armv.S should be aware of its +- * existence. Don't ever use this from user code. +- */ +- +-/* + * The following syscalls are obsolete and no longer available for EABI. + */ + #if !defined(__KERNEL__) +diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c +index 44bb4d544dcf..89cde0786d25 100644 +--- a/arch/arm/mach-omap2/control.c ++++ b/arch/arm/mach-omap2/control.c +@@ -314,7 +314,8 @@ void omap3_save_scratchpad_contents(void) + scratchpad_contents.public_restore_ptr = + virt_to_phys(omap3_restore_3630); + else if (omap_rev() != OMAP3430_REV_ES3_0 && +- omap_rev() != OMAP3430_REV_ES3_1) ++ omap_rev() != OMAP3430_REV_ES3_1 && ++ omap_rev() != OMAP3430_REV_ES3_1_2) + scratchpad_contents.public_restore_ptr = + virt_to_phys(omap3_restore); + else +diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c +index 66c60fe1104c..c914b0052fb9 100644 +--- a/arch/arm/mach-omap2/omap_hwmod.c ++++ b/arch/arm/mach-omap2/omap_hwmod.c +@@ -2185,6 +2185,8 @@ static int _enable(struct omap_hwmod *oh) + oh->mux->pads_dynamic))) { + omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED); + _reconfigure_io_chain(); ++ } else if (oh->flags & HWMOD_FORCE_MSTANDBY) { ++ _reconfigure_io_chain(); + } + + _add_initiator_dep(oh, mpu_oh); +@@ -2291,6 +2293,8 @@ static int _idle(struct omap_hwmod *oh) + if (oh->mux && oh->mux->pads_dynamic) { + omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE); + _reconfigure_io_chain(); ++ } else if (oh->flags & HWMOD_FORCE_MSTANDBY) { ++ _reconfigure_io_chain(); + } + + oh->_state = _HWMOD_STATE_IDLE; +diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c +index 3b2b4fb3585b..beedaf0c5e75 100644 +--- a/arch/powerpc/platforms/powernv/pci-ioda.c ++++ b/arch/powerpc/platforms/powernv/pci-ioda.c +@@ -491,6 +491,7 @@ static int pnv_pci_ioda_dma_set_mask(struct pnv_phb *phb, + set_dma_ops(&pdev->dev, &dma_iommu_ops); + set_iommu_table_base(&pdev->dev, &pe->tce32_table); + } ++ *pdev->dev.dma_mask = dma_mask; + return 0; + } + +diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c +index efe61374f6ea..e68922b0d4f5 100644 +--- a/arch/powerpc/platforms/pseries/pci_dlpar.c ++++ b/arch/powerpc/platforms/pseries/pci_dlpar.c +@@ -118,10 +118,10 @@ int remove_phb_dynamic(struct pci_controller *phb) + } + } + +- /* Unregister the bridge device from sysfs and remove the PCI bus */ +- device_unregister(b->bridge); ++ /* Remove the PCI bus and unregister the bridge device from sysfs */ + phb->bus = NULL; + pci_remove_bus(b); ++ device_unregister(b->bridge); + + /* Now release the IO resource */ + if (res->flags & IORESOURCE_IO) +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index c718d9f25900..e4098912fef2 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -1597,6 +1597,7 @@ config EFI + config EFI_STUB + bool "EFI stub support" + depends on EFI ++ select RELOCATABLE + ---help--- + This kernel feature allows a bzImage to be loaded directly + by EFI firmware without the use of a bootloader. +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index 3092300a07cd..d71d5ac78e42 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -99,7 +99,7 @@ static inline gfn_t gfn_to_index(gfn_t gfn, gfn_t base_gfn, int level) + #define KVM_REFILL_PAGES 25 + #define KVM_MAX_CPUID_ENTRIES 80 + #define KVM_NR_FIXED_MTRR_REGION 88 +-#define KVM_NR_VAR_MTRR 10 ++#define KVM_NR_VAR_MTRR 8 + + #define ASYNC_PF_PER_VCPU 64 + +diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c +index 2a26819bb6a8..80eab01c1a68 100644 +--- a/arch/x86/kernel/resource.c ++++ b/arch/x86/kernel/resource.c +@@ -37,10 +37,12 @@ static void remove_e820_regions(struct resource *avail) + + void arch_remove_reservations(struct resource *avail) + { +- /* Trim out BIOS areas (low 1MB and high 2MB) and E820 regions */ ++ /* ++ * Trim out BIOS area (high 2MB) and E820 regions. We do not remove ++ * the low 1MB unconditionally, as this area is needed for some ISA ++ * cards requiring a memory range, e.g. the i82365 PCMCIA controller. ++ */ + if (avail->flags & IORESOURCE_MEM) { +- if (avail->start < BIOS_END) +- avail->start = BIOS_END; + resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END); + + remove_e820_regions(avail); +diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c +index 1f96f9347ed9..09ce23ae370c 100644 +--- a/arch/x86/kernel/vsyscall_64.c ++++ b/arch/x86/kernel/vsyscall_64.c +@@ -125,10 +125,10 @@ static void warn_bad_vsyscall(const char *level, struct pt_regs *regs, + if (!show_unhandled_signals) + return; + +- pr_notice_ratelimited("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n", +- level, current->comm, task_pid_nr(current), +- message, regs->ip, regs->cs, +- regs->sp, regs->ax, regs->si, regs->di); ++ printk_ratelimited("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n", ++ level, current->comm, task_pid_nr(current), ++ message, regs->ip, regs->cs, ++ regs->sp, regs->ax, regs->si, regs->di); + } + + static int addr_to_vsyscall_nr(unsigned long addr) +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index 07ffca0a89e9..7bff3e2a7a11 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -2006,6 +2006,7 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt) + { + int rc; + unsigned long cs; ++ int cpl = ctxt->ops->cpl(ctxt); + + rc = emulate_pop(ctxt, &ctxt->_eip, ctxt->op_bytes); + if (rc != X86EMUL_CONTINUE) +@@ -2015,6 +2016,9 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt) + rc = emulate_pop(ctxt, &cs, ctxt->op_bytes); + if (rc != X86EMUL_CONTINUE) + return rc; ++ /* Outer-privilege level return is not implemented */ ++ if (ctxt->mode >= X86EMUL_MODE_PROT16 && (cs & 3) > cpl) ++ return X86EMUL_UNHANDLEABLE; + rc = load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS); + return rc; + } +diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c +index 484bc874688b..3ec38cb56bd5 100644 +--- a/arch/x86/kvm/irq.c ++++ b/arch/x86/kvm/irq.c +@@ -108,7 +108,7 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v) + + vector = kvm_cpu_get_extint(v); + +- if (kvm_apic_vid_enabled(v->kvm) || vector != -1) ++ if (vector != -1) + return vector; /* PIC */ + + return kvm_get_apic_interrupt(v); /* APIC */ +diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c +index 006911858174..453e5fbbb7ae 100644 +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -352,25 +352,46 @@ static inline int apic_find_highest_irr(struct kvm_lapic *apic) + + static inline void apic_clear_irr(int vec, struct kvm_lapic *apic) + { +- apic->irr_pending = false; ++ struct kvm_vcpu *vcpu; ++ ++ vcpu = apic->vcpu; ++ + apic_clear_vector(vec, apic->regs + APIC_IRR); +- if (apic_search_irr(apic) != -1) +- apic->irr_pending = true; ++ if (unlikely(kvm_apic_vid_enabled(vcpu->kvm))) ++ /* try to update RVI */ ++ kvm_make_request(KVM_REQ_EVENT, vcpu); ++ else { ++ vec = apic_search_irr(apic); ++ apic->irr_pending = (vec != -1); ++ } + } + + static inline void apic_set_isr(int vec, struct kvm_lapic *apic) + { +- /* Note that we never get here with APIC virtualization enabled. */ ++ struct kvm_vcpu *vcpu; ++ ++ if (__apic_test_and_set_vector(vec, apic->regs + APIC_ISR)) ++ return; ++ ++ vcpu = apic->vcpu; + +- if (!__apic_test_and_set_vector(vec, apic->regs + APIC_ISR)) +- ++apic->isr_count; +- BUG_ON(apic->isr_count > MAX_APIC_VECTOR); + /* +- * ISR (in service register) bit is set when injecting an interrupt. +- * The highest vector is injected. Thus the latest bit set matches +- * the highest bit in ISR. ++ * With APIC virtualization enabled, all caching is disabled ++ * because the processor can modify ISR under the hood. Instead ++ * just set SVI. + */ +- apic->highest_isr_cache = vec; ++ if (unlikely(kvm_apic_vid_enabled(vcpu->kvm))) ++ kvm_x86_ops->hwapic_isr_update(vcpu->kvm, vec); ++ else { ++ ++apic->isr_count; ++ BUG_ON(apic->isr_count > MAX_APIC_VECTOR); ++ /* ++ * ISR (in service register) bit is set when injecting an interrupt. ++ * The highest vector is injected. Thus the latest bit set matches ++ * the highest bit in ISR. ++ */ ++ apic->highest_isr_cache = vec; ++ } + } + + static inline int apic_find_highest_isr(struct kvm_lapic *apic) +@@ -1627,11 +1648,16 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu) + int vector = kvm_apic_has_interrupt(vcpu); + struct kvm_lapic *apic = vcpu->arch.apic; + +- /* Note that we never get here with APIC virtualization enabled. */ +- + if (vector == -1) + return -1; + ++ /* ++ * We get here even with APIC virtualization enabled, if doing ++ * nested virtualization and L1 runs with the "acknowledge interrupt ++ * on exit" mode. Then we cannot inject the interrupt via RVI, ++ * because the process would deliver it through the IDT. ++ */ ++ + apic_set_isr(vector, apic); + apic_update_ppr(apic); + apic_clear_irr(vector, apic); +diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c +index db6b1ab43255..96a159afe3c6 100644 +--- a/arch/x86/pci/i386.c ++++ b/arch/x86/pci/i386.c +@@ -162,6 +162,10 @@ pcibios_align_resource(void *data, const struct resource *res, + return start; + if (start & 0x300) + start = (start + 0x3ff) & ~0x3ff; ++ } else if (res->flags & IORESOURCE_MEM) { ++ /* The low 1MB range is reserved for ISA cards */ ++ if (start < BIOS_END) ++ start = BIOS_END; + } + return start; + } +diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c +index c98583588580..5b406fc45674 100644 +--- a/arch/x86/xen/grant-table.c ++++ b/arch/x86/xen/grant-table.c +@@ -134,6 +134,7 @@ static int __init xlated_setup_gnttab_pages(void) + { + struct page **pages; + xen_pfn_t *pfns; ++ void *vaddr; + int rc; + unsigned int i; + unsigned long nr_grant_frames = gnttab_max_grant_frames(); +@@ -159,21 +160,20 @@ static int __init xlated_setup_gnttab_pages(void) + for (i = 0; i < nr_grant_frames; i++) + pfns[i] = page_to_pfn(pages[i]); + +- rc = arch_gnttab_map_shared(pfns, nr_grant_frames, nr_grant_frames, +- &xen_auto_xlat_grant_frames.vaddr); +- +- if (rc) { ++ vaddr = vmap(pages, nr_grant_frames, 0, PAGE_KERNEL); ++ if (!vaddr) { + pr_warn("%s Couldn't map %ld pfns rc:%d\n", __func__, + nr_grant_frames, rc); + free_xenballooned_pages(nr_grant_frames, pages); + kfree(pages); + kfree(pfns); +- return rc; ++ return -ENOMEM; + } + kfree(pages); + + xen_auto_xlat_grant_frames.pfn = pfns; + xen_auto_xlat_grant_frames.count = nr_grant_frames; ++ xen_auto_xlat_grant_frames.vaddr = vaddr; + + return 0; + } +diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c +index 7b78f88c1707..5718b0b58b60 100644 +--- a/arch/x86/xen/time.c ++++ b/arch/x86/xen/time.c +@@ -444,7 +444,7 @@ void xen_setup_timer(int cpu) + + irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt, + IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER| +- IRQF_FORCE_RESUME, ++ IRQF_FORCE_RESUME|IRQF_EARLY_RESUME, + name, NULL); + (void)xen_set_irq_priority(irq, XEN_IRQ_PRIORITY_MAX); + +diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c +index 5b0dd8ef74c0..be9af2e6ca5a 100644 +--- a/drivers/char/tpm/tpm_i2c_stm_st33.c ++++ b/drivers/char/tpm/tpm_i2c_stm_st33.c +@@ -715,6 +715,7 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) + } + + tpm_get_timeouts(chip); ++ tpm_do_selftest(chip); + + dev_info(chip->dev, "TPM I2C Initialized\n"); + return 0; +diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c +index a999f537228f..92105f3dc8e0 100644 +--- a/drivers/crypto/ux500/cryp/cryp_core.c ++++ b/drivers/crypto/ux500/cryp/cryp_core.c +@@ -190,7 +190,7 @@ static void add_session_id(struct cryp_ctx *ctx) + static irqreturn_t cryp_interrupt_handler(int irq, void *param) + { + struct cryp_ctx *ctx; +- int i; ++ int count; + struct cryp_device_data *device_data; + + if (param == NULL) { +@@ -215,12 +215,11 @@ static irqreturn_t cryp_interrupt_handler(int irq, void *param) + if (cryp_pending_irq_src(device_data, + CRYP_IRQ_SRC_OUTPUT_FIFO)) { + if (ctx->outlen / ctx->blocksize > 0) { +- for (i = 0; i < ctx->blocksize / 4; i++) { +- *(ctx->outdata) = readl_relaxed( +- &device_data->base->dout); +- ctx->outdata += 4; +- ctx->outlen -= 4; +- } ++ count = ctx->blocksize / 4; ++ ++ readsl(&device_data->base->dout, ctx->outdata, count); ++ ctx->outdata += count; ++ ctx->outlen -= count; + + if (ctx->outlen == 0) { + cryp_disable_irq_src(device_data, +@@ -230,12 +229,12 @@ static irqreturn_t cryp_interrupt_handler(int irq, void *param) + } else if (cryp_pending_irq_src(device_data, + CRYP_IRQ_SRC_INPUT_FIFO)) { + if (ctx->datalen / ctx->blocksize > 0) { +- for (i = 0 ; i < ctx->blocksize / 4; i++) { +- writel_relaxed(ctx->indata, +- &device_data->base->din); +- ctx->indata += 4; +- ctx->datalen -= 4; +- } ++ count = ctx->blocksize / 4; ++ ++ writesl(&device_data->base->din, ctx->indata, count); ++ ++ ctx->indata += count; ++ ctx->datalen -= count; + + if (ctx->datalen == 0) + cryp_disable_irq_src(device_data, +diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +index f926b4caf449..56c60552abba 100644 +--- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c ++++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +@@ -199,7 +199,7 @@ static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm) + static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area, + struct page **pages, uint32_t npages, uint32_t roll) + { +- dma_addr_t pat_pa = 0; ++ dma_addr_t pat_pa = 0, data_pa = 0; + uint32_t *data; + struct pat *pat; + struct refill_engine *engine = txn->engine_handle; +@@ -223,7 +223,9 @@ static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area, + .lut_id = engine->tcm->lut_id, + }; + +- data = alloc_dma(txn, 4*i, &pat->data_pa); ++ data = alloc_dma(txn, 4*i, &data_pa); ++ /* FIXME: what if data_pa is more than 32-bit ? */ ++ pat->data_pa = data_pa; + + while (i--) { + int n = i + roll; +diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c +index 5aec3e81fe24..5fd3bab8b803 100644 +--- a/drivers/gpu/drm/omapdrm/omap_gem.c ++++ b/drivers/gpu/drm/omapdrm/omap_gem.c +@@ -791,7 +791,7 @@ int omap_gem_get_paddr(struct drm_gem_object *obj, + omap_obj->paddr = tiler_ssptr(block); + omap_obj->block = block; + +- DBG("got paddr: %08x", omap_obj->paddr); ++ DBG("got paddr: %pad", &omap_obj->paddr); + } + + omap_obj->paddr_cnt++; +@@ -988,9 +988,9 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) + + off = drm_vma_node_start(&obj->vma_node); + +- seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d", ++ seq_printf(m, "%08x: %2d (%2d) %08llx %pad (%2d) %p %4d", + omap_obj->flags, obj->name, obj->refcount.refcount.counter, +- off, omap_obj->paddr, omap_obj->paddr_cnt, ++ off, &omap_obj->paddr, omap_obj->paddr_cnt, + omap_obj->vaddr, omap_obj->roll); + + if (omap_obj->flags & OMAP_BO_TILED) { +@@ -1468,8 +1468,8 @@ void omap_gem_init(struct drm_device *dev) + entry->paddr = tiler_ssptr(block); + entry->block = block; + +- DBG("%d:%d: %dx%d: paddr=%08x stride=%d", i, j, w, h, +- entry->paddr, ++ DBG("%d:%d: %dx%d: paddr=%pad stride=%d", i, j, w, h, ++ &entry->paddr, + usergart[i].stride_pfn << PAGE_SHIFT); + } + } +diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c +index 046d5e660c04..5b62e212cbe5 100644 +--- a/drivers/gpu/drm/omapdrm/omap_plane.c ++++ b/drivers/gpu/drm/omapdrm/omap_plane.c +@@ -142,8 +142,8 @@ static void omap_plane_pre_apply(struct omap_drm_apply *apply) + DBG("%dx%d -> %dx%d (%d)", info->width, info->height, + info->out_width, info->out_height, + info->screen_width); +- DBG("%d,%d %08x %08x", info->pos_x, info->pos_y, +- info->paddr, info->p_uv_addr); ++ DBG("%d,%d %pad %pad", info->pos_x, info->pos_y, ++ &info->paddr, &info->p_uv_addr); + + /* TODO: */ + ilace = false; +diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c +index 7164045c06e4..bc9e56eb4e9c 100644 +--- a/drivers/gpu/drm/radeon/cik.c ++++ b/drivers/gpu/drm/radeon/cik.c +@@ -3231,6 +3231,7 @@ static void cik_gpu_init(struct radeon_device *rdev) + (rdev->pdev->device == 0x130B) || + (rdev->pdev->device == 0x130E) || + (rdev->pdev->device == 0x1315) || ++ (rdev->pdev->device == 0x1318) || + (rdev->pdev->device == 0x131B)) { + rdev->config.cik.max_cu_per_sh = 4; + rdev->config.cik.max_backends_per_se = 1; +diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c +index 1bdcccc54a1d..f745d2c1325e 100644 +--- a/drivers/hid/hid-cherry.c ++++ b/drivers/hid/hid-cherry.c +@@ -28,7 +28,7 @@ + static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) + { +- if (*rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { ++ if (*rsize >= 18 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { + hid_info(hdev, "fixing up Cherry Cymotion report descriptor\n"); + rdesc[11] = rdesc[16] = 0xff; + rdesc[12] = rdesc[17] = 0x03; +diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c +index e77696367591..b92bf01a1ae8 100644 +--- a/drivers/hid/hid-kye.c ++++ b/drivers/hid/hid-kye.c +@@ -300,7 +300,7 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, + * - change the button usage range to 4-7 for the extra + * buttons + */ +- if (*rsize >= 74 && ++ if (*rsize >= 75 && + rdesc[61] == 0x05 && rdesc[62] == 0x08 && + rdesc[63] == 0x19 && rdesc[64] == 0x08 && + rdesc[65] == 0x29 && rdesc[66] == 0x0f && +diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c +index 9fe9d4ac3114..b8207e0bfdc0 100644 +--- a/drivers/hid/hid-lg.c ++++ b/drivers/hid/hid-lg.c +@@ -345,14 +345,14 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, + struct usb_device_descriptor *udesc; + __u16 bcdDevice, rev_maj, rev_min; + +- if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 && ++ if ((drv_data->quirks & LG_RDESC) && *rsize >= 91 && rdesc[83] == 0x26 && + rdesc[84] == 0x8c && rdesc[85] == 0x02) { + hid_info(hdev, + "fixing up Logitech keyboard report descriptor\n"); + rdesc[84] = rdesc[89] = 0x4d; + rdesc[85] = rdesc[90] = 0x10; + } +- if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 50 && ++ if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 51 && + rdesc[32] == 0x81 && rdesc[33] == 0x06 && + rdesc[49] == 0x81 && rdesc[50] == 0x06) { + hid_info(hdev, +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index f45279c3b11a..0b14d3261531 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -237,13 +237,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, + return; + } + +- if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) || +- (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) { +- dev_err(&djrcv_hdev->dev, "%s: invalid device index:%d\n", +- __func__, dj_report->device_index); +- return; +- } +- + if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { + /* The device is already known. No need to reallocate it. */ + dbg_hid("%s: device is already known\n", __func__); +@@ -721,6 +714,12 @@ static int logi_dj_raw_event(struct hid_device *hdev, + * device (via hid_input_report() ) and return 1 so hid-core does not do + * anything else with it. + */ ++ if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) || ++ (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) { ++ dev_err(&hdev->dev, "%s: invalid device index:%d\n", ++ __func__, dj_report->device_index); ++ return false; ++ } + + spin_lock_irqsave(&djrcv_dev->lock, flags); + if (dj_report->report_id == REPORT_ID_DJ_SHORT) { +diff --git a/drivers/hid/hid-monterey.c b/drivers/hid/hid-monterey.c +index 9e14c00eb1b6..25daf28b26bd 100644 +--- a/drivers/hid/hid-monterey.c ++++ b/drivers/hid/hid-monterey.c +@@ -24,7 +24,7 @@ + static __u8 *mr_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) + { +- if (*rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) { ++ if (*rsize >= 31 && rdesc[29] == 0x05 && rdesc[30] == 0x09) { + hid_info(hdev, "fixing up button/consumer in HID report descriptor\n"); + rdesc[30] = 0x0c; + } +diff --git a/drivers/hid/hid-petalynx.c b/drivers/hid/hid-petalynx.c +index 736b2502df4f..6aca4f2554bf 100644 +--- a/drivers/hid/hid-petalynx.c ++++ b/drivers/hid/hid-petalynx.c +@@ -25,7 +25,7 @@ + static __u8 *pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) + { +- if (*rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 && ++ if (*rsize >= 62 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 && + rdesc[41] == 0x00 && rdesc[59] == 0x26 && + rdesc[60] == 0xf9 && rdesc[61] == 0x00) { + hid_info(hdev, "fixing up Petalynx Maxter Remote report descriptor\n"); +diff --git a/drivers/hid/hid-sunplus.c b/drivers/hid/hid-sunplus.c +index 87fc91e1c8de..91072fa54663 100644 +--- a/drivers/hid/hid-sunplus.c ++++ b/drivers/hid/hid-sunplus.c +@@ -24,7 +24,7 @@ + static __u8 *sp_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) + { +- if (*rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 && ++ if (*rsize >= 112 && rdesc[104] == 0x26 && rdesc[105] == 0x80 && + rdesc[106] == 0x03) { + hid_info(hdev, "fixing up Sunplus Wireless Desktop report descriptor\n"); + rdesc[105] = rdesc[110] = 0x03; +diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c +index 7f9dc2f86b63..126516414c11 100644 +--- a/drivers/hwmon/ads1015.c ++++ b/drivers/hwmon/ads1015.c +@@ -198,7 +198,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) + } + + channel = be32_to_cpup(property); +- if (channel > ADS1015_CHANNELS) { ++ if (channel >= ADS1015_CHANNELS) { + dev_err(&client->dev, + "invalid channel index %d on %s\n", + channel, node->full_name); +@@ -212,6 +212,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) + dev_err(&client->dev, + "invalid gain on %s\n", + node->full_name); ++ return -EINVAL; + } + } + +@@ -222,6 +223,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) + dev_err(&client->dev, + "invalid data_rate on %s\n", + node->full_name); ++ return -EINVAL; + } + } + +diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c +index 9f2be3dd28f3..8a67ec6279a4 100644 +--- a/drivers/hwmon/amc6821.c ++++ b/drivers/hwmon/amc6821.c +@@ -360,11 +360,13 @@ static ssize_t set_pwm1_enable( + if (config) + return config; + ++ mutex_lock(&data->update_lock); + config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); + if (config < 0) { + dev_err(&client->dev, + "Error reading configuration register, aborting.\n"); +- return config; ++ count = config; ++ goto unlock; + } + + switch (val) { +@@ -381,14 +383,15 @@ static ssize_t set_pwm1_enable( + config |= AMC6821_CONF1_FDRC1; + break; + default: +- return -EINVAL; ++ count = -EINVAL; ++ goto unlock; + } +- mutex_lock(&data->update_lock); + if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) { + dev_err(&client->dev, + "Configuration register write error, aborting.\n"); + count = -EIO; + } ++unlock: + mutex_unlock(&data->update_lock); + return count; + } +@@ -493,8 +496,9 @@ static ssize_t set_temp_auto_point_temp( + return -EINVAL; + } + +- data->valid = 0; + mutex_lock(&data->update_lock); ++ data->valid = 0; ++ + switch (ix) { + case 0: + ptemp[0] = clamp_val(val / 1000, 0, +@@ -658,13 +662,14 @@ static ssize_t set_fan1_div( + if (config) + return config; + ++ mutex_lock(&data->update_lock); + config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4); + if (config < 0) { + dev_err(&client->dev, + "Error reading configuration register, aborting.\n"); +- return config; ++ count = config; ++ goto EXIT; + } +- mutex_lock(&data->update_lock); + switch (val) { + case 2: + config &= ~AMC6821_CONF4_PSPR; +diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c +index 4ae3fff13f44..bea0a344fab5 100644 +--- a/drivers/hwmon/dme1737.c ++++ b/drivers/hwmon/dme1737.c +@@ -247,8 +247,8 @@ struct dme1737_data { + u8 pwm_acz[3]; + u8 pwm_freq[6]; + u8 pwm_rr[2]; +- u8 zone_low[3]; +- u8 zone_abs[3]; ++ s8 zone_low[3]; ++ s8 zone_abs[3]; + u8 zone_hyst[2]; + u32 alarms; + }; +@@ -277,7 +277,7 @@ static inline int IN_FROM_REG(int reg, int nominal, int res) + return (reg * nominal + (3 << (res - 3))) / (3 << (res - 2)); + } + +-static inline int IN_TO_REG(int val, int nominal) ++static inline int IN_TO_REG(long val, int nominal) + { + return clamp_val((val * 192 + nominal / 2) / nominal, 0, 255); + } +@@ -293,7 +293,7 @@ static inline int TEMP_FROM_REG(int reg, int res) + return (reg * 1000) >> (res - 8); + } + +-static inline int TEMP_TO_REG(int val) ++static inline int TEMP_TO_REG(long val) + { + return clamp_val((val < 0 ? val - 500 : val + 500) / 1000, -128, 127); + } +@@ -308,7 +308,7 @@ static inline int TEMP_RANGE_FROM_REG(int reg) + return TEMP_RANGE[(reg >> 4) & 0x0f]; + } + +-static int TEMP_RANGE_TO_REG(int val, int reg) ++static int TEMP_RANGE_TO_REG(long val, int reg) + { + int i; + +@@ -331,7 +331,7 @@ static inline int TEMP_HYST_FROM_REG(int reg, int ix) + return (((ix == 1) ? reg : reg >> 4) & 0x0f) * 1000; + } + +-static inline int TEMP_HYST_TO_REG(int val, int ix, int reg) ++static inline int TEMP_HYST_TO_REG(long val, int ix, int reg) + { + int hyst = clamp_val((val + 500) / 1000, 0, 15); + +@@ -347,7 +347,7 @@ static inline int FAN_FROM_REG(int reg, int tpc) + return (reg == 0 || reg == 0xffff) ? 0 : 90000 * 60 / reg; + } + +-static inline int FAN_TO_REG(int val, int tpc) ++static inline int FAN_TO_REG(long val, int tpc) + { + if (tpc) { + return clamp_val(val / tpc, 0, 0xffff); +@@ -379,7 +379,7 @@ static inline int FAN_TYPE_FROM_REG(int reg) + return (edge > 0) ? 1 << (edge - 1) : 0; + } + +-static inline int FAN_TYPE_TO_REG(int val, int reg) ++static inline int FAN_TYPE_TO_REG(long val, int reg) + { + int edge = (val == 4) ? 3 : val; + +@@ -402,7 +402,7 @@ static int FAN_MAX_FROM_REG(int reg) + return 1000 + i * 500; + } + +-static int FAN_MAX_TO_REG(int val) ++static int FAN_MAX_TO_REG(long val) + { + int i; + +@@ -460,7 +460,7 @@ static inline int PWM_ACZ_FROM_REG(int reg) + return acz[(reg >> 5) & 0x07]; + } + +-static inline int PWM_ACZ_TO_REG(int val, int reg) ++static inline int PWM_ACZ_TO_REG(long val, int reg) + { + int acz = (val == 4) ? 2 : val - 1; + +@@ -476,7 +476,7 @@ static inline int PWM_FREQ_FROM_REG(int reg) + return PWM_FREQ[reg & 0x0f]; + } + +-static int PWM_FREQ_TO_REG(int val, int reg) ++static int PWM_FREQ_TO_REG(long val, int reg) + { + int i; + +@@ -510,7 +510,7 @@ static inline int PWM_RR_FROM_REG(int reg, int ix) + return (rr & 0x08) ? PWM_RR[rr & 0x07] : 0; + } + +-static int PWM_RR_TO_REG(int val, int ix, int reg) ++static int PWM_RR_TO_REG(long val, int ix, int reg) + { + int i; + +@@ -528,7 +528,7 @@ static inline int PWM_RR_EN_FROM_REG(int reg, int ix) + return PWM_RR_FROM_REG(reg, ix) ? 1 : 0; + } + +-static inline int PWM_RR_EN_TO_REG(int val, int ix, int reg) ++static inline int PWM_RR_EN_TO_REG(long val, int ix, int reg) + { + int en = (ix == 1) ? 0x80 : 0x08; + +@@ -1481,13 +1481,16 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) + { + struct dme1737_data *data = dev_get_drvdata(dev); +- long val; ++ unsigned long val; + int err; + +- err = kstrtol(buf, 10, &val); ++ err = kstrtoul(buf, 10, &val); + if (err) + return err; + ++ if (val > 255) ++ return -EINVAL; ++ + data->vrm = val; + return count; + } +diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c +index 73181be5b30b..814f7ee9026b 100644 +--- a/drivers/hwmon/gpio-fan.c ++++ b/drivers/hwmon/gpio-fan.c +@@ -173,7 +173,7 @@ static int get_fan_speed_index(struct gpio_fan_data *fan_data) + return -ENODEV; + } + +-static int rpm_to_speed_index(struct gpio_fan_data *fan_data, int rpm) ++static int rpm_to_speed_index(struct gpio_fan_data *fan_data, unsigned long rpm) + { + struct gpio_fan_speed *speed = fan_data->speed; + int i; +diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c +index 9efadfc851bc..c1eb464f0fd0 100644 +--- a/drivers/hwmon/lm78.c ++++ b/drivers/hwmon/lm78.c +@@ -108,7 +108,7 @@ static inline int FAN_FROM_REG(u8 val, int div) + * TEMP: mC (-128C to +127C) + * REG: 1C/bit, two's complement + */ +-static inline s8 TEMP_TO_REG(int val) ++static inline s8 TEMP_TO_REG(long val) + { + int nval = clamp_val(val, -128000, 127000) ; + return nval < 0 ? (nval - 500) / 1000 : (nval + 500) / 1000; +diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c +index bed4af358308..21d6cc813a6d 100644 +--- a/drivers/hwmon/lm85.c ++++ b/drivers/hwmon/lm85.c +@@ -158,7 +158,7 @@ static inline u16 FAN_TO_REG(unsigned long val) + + /* Temperature is reported in .001 degC increments */ + #define TEMP_TO_REG(val) \ +- clamp_val(SCALE(val, 1000, 1), -127, 127) ++ DIV_ROUND_CLOSEST(clamp_val((val), -127000, 127000), 1000) + #define TEMPEXT_FROM_REG(val, ext) \ + SCALE(((val) << 4) + (ext), 16, 1000) + #define TEMP_FROM_REG(val) ((val) * 1000) +@@ -192,7 +192,7 @@ static const int lm85_range_map[] = { + 13300, 16000, 20000, 26600, 32000, 40000, 53300, 80000 + }; + +-static int RANGE_TO_REG(int range) ++static int RANGE_TO_REG(long range) + { + int i; + +@@ -214,7 +214,7 @@ static const int adm1027_freq_map[8] = { /* 1 Hz */ + 11, 15, 22, 29, 35, 44, 59, 88 + }; + +-static int FREQ_TO_REG(const int *map, int freq) ++static int FREQ_TO_REG(const int *map, unsigned long freq) + { + int i; + +@@ -463,6 +463,9 @@ static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, + if (err) + return err; + ++ if (val > 255) ++ return -EINVAL; ++ + data->vrm = val; + return count; + } +diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c +index 3532026e25da..bf1d7893d51c 100644 +--- a/drivers/hwmon/sis5595.c ++++ b/drivers/hwmon/sis5595.c +@@ -159,7 +159,7 @@ static inline int TEMP_FROM_REG(s8 val) + { + return val * 830 + 52120; + } +-static inline s8 TEMP_TO_REG(int val) ++static inline s8 TEMP_TO_REG(long val) + { + int nval = clamp_val(val, -54120, 157530) ; + return nval < 0 ? (nval - 5212 - 415) / 830 : (nval - 5212 + 415) / 830; +diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c +index 843d01268ae9..c56be739006b 100644 +--- a/drivers/i2c/busses/i2c-at91.c ++++ b/drivers/i2c/busses/i2c-at91.c +@@ -210,7 +210,7 @@ static void at91_twi_write_data_dma_callback(void *data) + struct at91_twi_dev *dev = (struct at91_twi_dev *)data; + + dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg), +- dev->buf_len, DMA_MEM_TO_DEV); ++ dev->buf_len, DMA_TO_DEVICE); + + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP); + } +@@ -289,7 +289,7 @@ static void at91_twi_read_data_dma_callback(void *data) + struct at91_twi_dev *dev = (struct at91_twi_dev *)data; + + dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg), +- dev->buf_len, DMA_DEV_TO_MEM); ++ dev->buf_len, DMA_FROM_DEVICE); + + /* The last two bytes have to be read without using dma */ + dev->buf += dev->buf_len - 2; +diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c +index 5a9bfa71df86..540fe114ec60 100644 +--- a/drivers/misc/mei/client.c ++++ b/drivers/misc/mei/client.c +@@ -459,6 +459,7 @@ int mei_cl_disconnect(struct mei_cl *cl) + cl_err(dev, cl, "failed to disconnect.\n"); + goto free; + } ++ cl->timer_count = MEI_CONNECT_TIMEOUT; + mdelay(10); /* Wait for hardware disconnection ready */ + list_add_tail(&cb->list, &dev->ctrl_rd_list.list); + } else { +@@ -563,6 +564,7 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file) + cl->timer_count = MEI_CONNECT_TIMEOUT; + list_add_tail(&cb->list, &dev->ctrl_rd_list.list); + } else { ++ cl->state = MEI_FILE_INITIALIZING; + list_add_tail(&cb->list, &dev->ctrl_wr_list.list); + } + +diff --git a/drivers/misc/mei/nfc.c b/drivers/misc/mei/nfc.c +index a58320c0c049..31149010224b 100644 +--- a/drivers/misc/mei/nfc.c ++++ b/drivers/misc/mei/nfc.c +@@ -342,9 +342,10 @@ static int mei_nfc_send(struct mei_cl_device *cldev, u8 *buf, size_t length) + ndev = (struct mei_nfc_dev *) cldev->priv_data; + dev = ndev->cl->dev; + ++ err = -ENOMEM; + mei_buf = kzalloc(length + MEI_NFC_HEADER_SIZE, GFP_KERNEL); + if (!mei_buf) +- return -ENOMEM; ++ goto out; + + hdr = (struct mei_nfc_hci_hdr *) mei_buf; + hdr->cmd = MEI_NFC_CMD_HCI_SEND; +@@ -354,12 +355,9 @@ static int mei_nfc_send(struct mei_cl_device *cldev, u8 *buf, size_t length) + hdr->data_size = length; + + memcpy(mei_buf + MEI_NFC_HEADER_SIZE, buf, length); +- + err = __mei_cl_send(ndev->cl, mei_buf, length + MEI_NFC_HEADER_SIZE); + if (err < 0) +- return err; +- +- kfree(mei_buf); ++ goto out; + + if (!wait_event_interruptible_timeout(ndev->send_wq, + ndev->recv_req_id == ndev->req_id, HZ)) { +@@ -368,7 +366,8 @@ static int mei_nfc_send(struct mei_cl_device *cldev, u8 *buf, size_t length) + } else { + ndev->req_id++; + } +- ++out: ++ kfree(mei_buf); + return err; + } + +diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c +index 45113daaa778..e27a3dc9f4e8 100644 +--- a/drivers/pci/pci-label.c ++++ b/drivers/pci/pci-label.c +@@ -168,8 +168,8 @@ enum acpi_attr_enum { + static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf) + { + int len; +- len = utf16s_to_utf8s((const wchar_t *)obj->string.pointer, +- obj->string.length, ++ len = utf16s_to_utf8s((const wchar_t *)obj->buffer.pointer, ++ obj->buffer.length, + UTF16_LITTLE_ENDIAN, + buf, PAGE_SIZE); + buf[len] = '\n'; +@@ -194,16 +194,22 @@ dsm_get_label(struct device *dev, char *buf, enum acpi_attr_enum attr) + tmp = obj->package.elements; + if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 2 && + tmp[0].type == ACPI_TYPE_INTEGER && +- tmp[1].type == ACPI_TYPE_STRING) { ++ (tmp[1].type == ACPI_TYPE_STRING || ++ tmp[1].type == ACPI_TYPE_BUFFER)) { + /* + * The second string element is optional even when + * this _DSM is implemented; when not implemented, + * this entry must return a null string. + */ +- if (attr == ACPI_ATTR_INDEX_SHOW) ++ if (attr == ACPI_ATTR_INDEX_SHOW) { + scnprintf(buf, PAGE_SIZE, "%llu\n", tmp->integer.value); +- else if (attr == ACPI_ATTR_LABEL_SHOW) +- dsm_label_utf16s_to_utf8s(tmp + 1, buf); ++ } else if (attr == ACPI_ATTR_LABEL_SHOW) { ++ if (tmp[1].type == ACPI_TYPE_STRING) ++ scnprintf(buf, PAGE_SIZE, "%s\n", ++ tmp[1].string.pointer); ++ else if (tmp[1].type == ACPI_TYPE_BUFFER) ++ dsm_label_utf16s_to_utf8s(tmp + 1, buf); ++ } + len = strlen(buf) > 0 ? strlen(buf) : -1; + } + +diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c +index be36adf33ab0..dae70d216762 100644 +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -830,12 +830,6 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) + + if (!__pci_complete_power_transition(dev, state)) + error = 0; +- /* +- * When aspm_policy is "powersave" this call ensures +- * that ASPM is configured. +- */ +- if (!error && dev->bus->self) +- pcie_aspm_powersave_config_link(dev->bus->self); + + return error; + } +@@ -1181,12 +1175,18 @@ EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state); + static int do_pci_enable_device(struct pci_dev *dev, int bars) + { + int err; ++ struct pci_dev *bridge; + u16 cmd; + u8 pin; + + err = pci_set_power_state(dev, PCI_D0); + if (err < 0 && err != -EIO) + return err; ++ ++ bridge = pci_upstream_bridge(dev); ++ if (bridge) ++ pcie_aspm_powersave_config_link(bridge); ++ + err = pcibios_enable_device(dev, bars); + if (err < 0) + return err; +diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c +index 868318a7067c..528bff5ec91f 100644 +--- a/drivers/scsi/hpsa.c ++++ b/drivers/scsi/hpsa.c +@@ -3131,7 +3131,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) + } + if (ioc->Request.Type.Direction == XFER_WRITE) { + if (copy_from_user(buff[sg_used], data_ptr, sz)) { +- status = -ENOMEM; ++ status = -EFAULT; + goto cleanup1; + } + } else +@@ -4367,9 +4367,9 @@ static inline void hpsa_set_driver_support_bits(struct ctlr_info *h) + { + u32 driver_support; + +-#ifdef CONFIG_X86 +- /* Need to enable prefetch in the SCSI core for 6400 in x86 */ + driver_support = readl(&(h->cfgtable->driver_support)); ++ /* Need to enable prefetch in the SCSI core for 6400 in x86 */ ++#ifdef CONFIG_X86 + driver_support |= ENABLE_SCSI_PREFETCH; + #endif + driver_support |= ENABLE_UNIT_ATTN; +diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c +index e516bb69f3b4..907aa3078946 100644 +--- a/drivers/staging/et131x/et131x.c ++++ b/drivers/staging/et131x/et131x.c +@@ -1422,22 +1422,16 @@ static int et131x_mii_read(struct et131x_adapter *adapter, u8 reg, u16 *value) + * @reg: the register to read + * @value: 16-bit value to write + */ +-static int et131x_mii_write(struct et131x_adapter *adapter, u8 reg, u16 value) ++static int et131x_mii_write(struct et131x_adapter *adapter, u8 addr, u8 reg, ++ u16 value) + { + struct mac_regs __iomem *mac = &adapter->regs->mac; +- struct phy_device *phydev = adapter->phydev; + int status = 0; +- u8 addr; + u32 delay = 0; + u32 mii_addr; + u32 mii_cmd; + u32 mii_indicator; + +- if (!phydev) +- return -EIO; +- +- addr = phydev->addr; +- + /* Save a local copy of the registers we are dealing with so we can + * set them back + */ +@@ -1632,17 +1626,7 @@ static int et131x_mdio_write(struct mii_bus *bus, int phy_addr, + struct net_device *netdev = bus->priv; + struct et131x_adapter *adapter = netdev_priv(netdev); + +- return et131x_mii_write(adapter, reg, value); +-} +- +-static int et131x_mdio_reset(struct mii_bus *bus) +-{ +- struct net_device *netdev = bus->priv; +- struct et131x_adapter *adapter = netdev_priv(netdev); +- +- et131x_mii_write(adapter, MII_BMCR, BMCR_RESET); +- +- return 0; ++ return et131x_mii_write(adapter, phy_addr, reg, value); + } + + /* et1310_phy_power_switch - PHY power control +@@ -1657,18 +1641,20 @@ static int et131x_mdio_reset(struct mii_bus *bus) + static void et1310_phy_power_switch(struct et131x_adapter *adapter, bool down) + { + u16 data; ++ struct phy_device *phydev = adapter->phydev; + + et131x_mii_read(adapter, MII_BMCR, &data); + data &= ~BMCR_PDOWN; + if (down) + data |= BMCR_PDOWN; +- et131x_mii_write(adapter, MII_BMCR, data); ++ et131x_mii_write(adapter, phydev->addr, MII_BMCR, data); + } + + /* et131x_xcvr_init - Init the phy if we are setting it into force mode */ + static void et131x_xcvr_init(struct et131x_adapter *adapter) + { + u16 lcr2; ++ struct phy_device *phydev = adapter->phydev; + + /* Set the LED behavior such that LED 1 indicates speed (off = + * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates +@@ -1689,7 +1675,7 @@ static void et131x_xcvr_init(struct et131x_adapter *adapter) + else + lcr2 |= (LED_VAL_LINKON << LED_TXRX_SHIFT); + +- et131x_mii_write(adapter, PHY_LED_2, lcr2); ++ et131x_mii_write(adapter, phydev->addr, PHY_LED_2, lcr2); + } + } + +@@ -3638,14 +3624,14 @@ static void et131x_adjust_link(struct net_device *netdev) + + et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG, + ®ister18); +- et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, +- register18 | 0x4); +- et131x_mii_write(adapter, PHY_INDEX_REG, ++ et131x_mii_write(adapter, phydev->addr, ++ PHY_MPHY_CONTROL_REG, register18 | 0x4); ++ et131x_mii_write(adapter, phydev->addr, PHY_INDEX_REG, + register18 | 0x8402); +- et131x_mii_write(adapter, PHY_DATA_REG, ++ et131x_mii_write(adapter, phydev->addr, PHY_DATA_REG, + register18 | 511); +- et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, +- register18); ++ et131x_mii_write(adapter, phydev->addr, ++ PHY_MPHY_CONTROL_REG, register18); + } + + et1310_config_flow_control(adapter); +@@ -3657,7 +3643,8 @@ static void et131x_adjust_link(struct net_device *netdev) + et131x_mii_read(adapter, PHY_CONFIG, ®); + reg &= ~ET_PHY_CONFIG_TX_FIFO_DEPTH; + reg |= ET_PHY_CONFIG_FIFO_DEPTH_32; +- et131x_mii_write(adapter, PHY_CONFIG, reg); ++ et131x_mii_write(adapter, phydev->addr, PHY_CONFIG, ++ reg); + } + + et131x_set_rx_dma_timer(adapter); +@@ -3670,14 +3657,14 @@ static void et131x_adjust_link(struct net_device *netdev) + + et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG, + ®ister18); +- et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, +- register18 | 0x4); +- et131x_mii_write(adapter, PHY_INDEX_REG, +- register18 | 0x8402); +- et131x_mii_write(adapter, PHY_DATA_REG, +- register18 | 511); +- et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, +- register18); ++ et131x_mii_write(adapter, phydev->addr, ++ PHY_MPHY_CONTROL_REG, register18 | 0x4); ++ et131x_mii_write(adapter, phydev->addr, ++ PHY_INDEX_REG, register18 | 0x8402); ++ et131x_mii_write(adapter, phydev->addr, ++ PHY_DATA_REG, register18 | 511); ++ et131x_mii_write(adapter, phydev->addr, ++ PHY_MPHY_CONTROL_REG, register18); + } + + /* Free the packets being actively sent & stopped */ +@@ -4646,10 +4633,6 @@ static int et131x_pci_setup(struct pci_dev *pdev, + /* Copy address into the net_device struct */ + memcpy(netdev->dev_addr, adapter->addr, ETH_ALEN); + +- /* Init variable for counting how long we do not have link status */ +- adapter->boot_coma = 0; +- et1310_disable_phy_coma(adapter); +- + rc = -ENOMEM; + + /* Setup the mii_bus struct */ +@@ -4665,7 +4648,6 @@ static int et131x_pci_setup(struct pci_dev *pdev, + adapter->mii_bus->priv = netdev; + adapter->mii_bus->read = et131x_mdio_read; + adapter->mii_bus->write = et131x_mdio_write; +- adapter->mii_bus->reset = et131x_mdio_reset; + adapter->mii_bus->irq = kmalloc_array(PHY_MAX_ADDR, sizeof(int), + GFP_KERNEL); + if (!adapter->mii_bus->irq) +@@ -4689,6 +4671,10 @@ static int et131x_pci_setup(struct pci_dev *pdev, + /* Setup et1310 as per the documentation */ + et131x_adapter_setup(adapter); + ++ /* Init variable for counting how long we do not have link status */ ++ adapter->boot_coma = 0; ++ et1310_disable_phy_coma(adapter); ++ + /* We can enable interrupts now + * + * NOTE - Because registration of interrupt handler is done in the +diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c +index 2f40ff5901d6..fed699fc5918 100644 +--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c ++++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c +@@ -53,9 +53,11 @@ static struct usb_device_id rtw_usb_id_tbl[] = { + {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179)}, /* 8188ETV */ + /*=== Customer ID ===*/ + /****** 8188EUS ********/ ++ {USB_DEVICE(0x056e, 0x4008)}, /* Elecom WDC-150SU2M */ + {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */ + {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */ + {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */ ++ {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */ + {} /* Terminating entry */ + }; + +diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c +index ece2049bd270..25b8f6868788 100644 +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -235,6 +235,9 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) + /* + * Turn off DTR and RTS early. + */ ++ if (uart_console(uport) && tty) ++ uport->cons->cflag = tty->termios.c_cflag; ++ + if (!tty || (tty->termios.c_cflag & HUPCL)) + uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); + +diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c +index 90e18f6fa2bb..9ca77166d37e 100644 +--- a/drivers/usb/core/devio.c ++++ b/drivers/usb/core/devio.c +@@ -1411,7 +1411,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, + u = (is_in ? URB_DIR_IN : URB_DIR_OUT); + if (uurb->flags & USBDEVFS_URB_ISO_ASAP) + u |= URB_ISO_ASAP; +- if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK) ++ if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK && is_in) + u |= URB_SHORT_NOT_OK; + if (uurb->flags & USBDEVFS_URB_NO_FSBR) + u |= URB_NO_FSBR; +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 36b1e856bd00..6650df70bb35 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -1695,8 +1695,14 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) + * - Change autosuspend delay of hub can avoid unnecessary auto + * suspend timer for hub, also may decrease power consumption + * of USB bus. ++ * ++ * - If user has indicated to prevent autosuspend by passing ++ * usbcore.autosuspend = -1 then keep autosuspend disabled. + */ +- pm_runtime_set_autosuspend_delay(&hdev->dev, 0); ++#ifdef CONFIG_PM_RUNTIME ++ if (hdev->dev.power.autosuspend_delay >= 0) ++ pm_runtime_set_autosuspend_delay(&hdev->dev, 0); ++#endif + + /* + * Hubs have proper suspend/resume support, except for root hubs +@@ -3174,6 +3180,43 @@ static int finish_port_resume(struct usb_device *udev) + } + + /* ++ * There are some SS USB devices which take longer time for link training. ++ * XHCI specs 4.19.4 says that when Link training is successful, port ++ * sets CSC bit to 1. So if SW reads port status before successful link ++ * training, then it will not find device to be present. ++ * USB Analyzer log with such buggy devices show that in some cases ++ * device switch on the RX termination after long delay of host enabling ++ * the VBUS. In few other cases it has been seen that device fails to ++ * negotiate link training in first attempt. It has been ++ * reported till now that few devices take as long as 2000 ms to train ++ * the link after host enabling its VBUS and termination. Following ++ * routine implements a 2000 ms timeout for link training. If in a case ++ * link trains before timeout, loop will exit earlier. ++ * ++ * FIXME: If a device was connected before suspend, but was removed ++ * while system was asleep, then the loop in the following routine will ++ * only exit at timeout. ++ * ++ * This routine should only be called when persist is enabled for a SS ++ * device. ++ */ ++static int wait_for_ss_port_enable(struct usb_device *udev, ++ struct usb_hub *hub, int *port1, ++ u16 *portchange, u16 *portstatus) ++{ ++ int status = 0, delay_ms = 0; ++ ++ while (delay_ms < 2000) { ++ if (status || *portstatus & USB_PORT_STAT_CONNECTION) ++ break; ++ msleep(20); ++ delay_ms += 20; ++ status = hub_port_status(hub, *port1, portstatus, portchange); ++ } ++ return status; ++} ++ ++/* + * usb_port_resume - re-activate a suspended usb device's upstream port + * @udev: device to re-activate, not a root hub + * Context: must be able to sleep; device not locked; pm locks held +@@ -3275,6 +3318,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) + + clear_bit(port1, hub->busy_bits); + ++ if (udev->persist_enabled && hub_is_superspeed(hub->hdev)) ++ status = wait_for_ss_port_enable(udev, hub, &port1, &portchange, ++ &portstatus); ++ + status = check_port_resume_type(udev, + hub, port1, status, portchange, portstatus); + if (status == 0) +diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c +index 7ae0c4d51741..7d6f64c447bf 100644 +--- a/drivers/usb/host/ehci-hub.c ++++ b/drivers/usb/host/ehci-hub.c +@@ -1239,7 +1239,7 @@ static int ehci_hub_control ( + if (selector == EHSET_TEST_SINGLE_STEP_SET_FEATURE) { + spin_unlock_irqrestore(&ehci->lock, flags); + retval = ehset_single_step_set_feature(hcd, +- wIndex); ++ wIndex + 1); + spin_lock_irqsave(&ehci->lock, flags); + break; + } +diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c +index 3e86bf4371b3..ca7b964124af 100644 +--- a/drivers/usb/host/ehci-pci.c ++++ b/drivers/usb/host/ehci-pci.c +@@ -35,6 +35,21 @@ static const char hcd_name[] = "ehci-pci"; + #define PCI_DEVICE_ID_INTEL_CE4100_USB 0x2e70 + + /*-------------------------------------------------------------------------*/ ++#define PCI_DEVICE_ID_INTEL_QUARK_X1000_SOC 0x0939 ++static inline bool is_intel_quark_x1000(struct pci_dev *pdev) ++{ ++ return pdev->vendor == PCI_VENDOR_ID_INTEL && ++ pdev->device == PCI_DEVICE_ID_INTEL_QUARK_X1000_SOC; ++} ++ ++/* ++ * 0x84 is the offset of in/out threshold register, ++ * and it is the same offset as the register of 'hostpc'. ++ */ ++#define intel_quark_x1000_insnreg01 hostpc ++ ++/* Maximum usable threshold value is 0x7f dwords for both IN and OUT */ ++#define INTEL_QUARK_X1000_EHCI_MAX_THRESHOLD 0x007f007f + + /* called after powerup, by probe or system-pm "wakeup" */ + static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) +@@ -50,6 +65,16 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) + if (!retval) + ehci_dbg(ehci, "MWI active\n"); + ++ /* Reset the threshold limit */ ++ if (is_intel_quark_x1000(pdev)) { ++ /* ++ * For the Intel QUARK X1000, raise the I/O threshold to the ++ * maximum usable value in order to improve performance. ++ */ ++ ehci_writel(ehci, INTEL_QUARK_X1000_EHCI_MAX_THRESHOLD, ++ ehci->regs->intel_quark_x1000_insnreg01); ++ } ++ + return 0; + } + +diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c +index 45032e933e18..04f2186939d2 100644 +--- a/drivers/usb/host/ohci-dbg.c ++++ b/drivers/usb/host/ohci-dbg.c +@@ -236,7 +236,7 @@ ohci_dump_roothub ( + } + } + +-static void ohci_dump (struct ohci_hcd *controller, int verbose) ++static void ohci_dump(struct ohci_hcd *controller) + { + ohci_dbg (controller, "OHCI controller state\n"); + +@@ -464,15 +464,16 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) + static ssize_t fill_async_buffer(struct debug_buffer *buf) + { + struct ohci_hcd *ohci; +- size_t temp; ++ size_t temp, size; + unsigned long flags; + + ohci = buf->ohci; ++ size = PAGE_SIZE; + + /* display control and bulk lists together, for simplicity */ + spin_lock_irqsave (&ohci->lock, flags); +- temp = show_list(ohci, buf->page, buf->count, ohci->ed_controltail); +- temp += show_list(ohci, buf->page + temp, buf->count - temp, ++ temp = show_list(ohci, buf->page, size, ohci->ed_controltail); ++ temp += show_list(ohci, buf->page + temp, size - temp, + ohci->ed_bulktail); + spin_unlock_irqrestore (&ohci->lock, flags); + +diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c +index 3586460fb2a1..34fc86ccb591 100644 +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -76,8 +76,8 @@ static const char hcd_name [] = "ohci_hcd"; + #include "ohci.h" + #include "pci-quirks.h" + +-static void ohci_dump (struct ohci_hcd *ohci, int verbose); +-static void ohci_stop (struct usb_hcd *hcd); ++static void ohci_dump(struct ohci_hcd *ohci); ++static void ohci_stop(struct usb_hcd *hcd); + + #include "ohci-hub.c" + #include "ohci-dbg.c" +@@ -744,7 +744,7 @@ retry: + ohci->ed_to_check = NULL; + } + +- ohci_dump (ohci, 1); ++ ohci_dump(ohci); + + return 0; + } +@@ -825,7 +825,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) + usb_hc_died(hcd); + } + +- ohci_dump (ohci, 1); ++ ohci_dump(ohci); + ohci_usb_reset (ohci); + } + +@@ -925,7 +925,7 @@ static void ohci_stop (struct usb_hcd *hcd) + { + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + +- ohci_dump (ohci, 1); ++ ohci_dump(ohci); + + if (quirk_nec(ohci)) + flush_work(&ohci->nec_work); +diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c +index d4253e319428..a8bde5b8cbdd 100644 +--- a/drivers/usb/host/ohci-q.c ++++ b/drivers/usb/host/ohci-q.c +@@ -311,8 +311,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) + * - ED_OPER: when there's any request queued, the ED gets rescheduled + * immediately. HC should be working on them. + * +- * - ED_IDLE: when there's no TD queue. there's no reason for the HC +- * to care about this ED; safe to disable the endpoint. ++ * - ED_IDLE: when there's no TD queue or the HC isn't running. + * + * When finish_unlinks() runs later, after SOF interrupt, it will often + * complete one or more URB unlinks before making that state change. +@@ -926,6 +925,10 @@ rescan_all: + int completed, modified; + __hc32 *prev; + ++ /* Is this ED already invisible to the hardware? */ ++ if (ed->state == ED_IDLE) ++ goto ed_idle; ++ + /* only take off EDs that the HC isn't using, accounting for + * frame counter wraps and EDs with partially retired TDs + */ +@@ -955,12 +958,20 @@ skip_ed: + } + } + ++ /* ED's now officially unlinked, hc doesn't see */ ++ ed->state = ED_IDLE; ++ if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT) ++ ohci->eds_scheduled--; ++ ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H); ++ ed->hwNextED = 0; ++ wmb(); ++ ed->hwINFO &= ~cpu_to_hc32(ohci, ED_SKIP | ED_DEQUEUE); ++ed_idle: ++ + /* reentrancy: if we drop the schedule lock, someone might + * have modified this list. normally it's just prepending + * entries (which we'd ignore), but paranoia won't hurt. + */ +- *last = ed->ed_next; +- ed->ed_next = NULL; + modified = 0; + + /* unlink urbs as requested, but rescan the list after +@@ -1018,19 +1029,20 @@ rescan_this: + if (completed && !list_empty (&ed->td_list)) + goto rescan_this; + +- /* ED's now officially unlinked, hc doesn't see */ +- ed->state = ED_IDLE; +- if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT) +- ohci->eds_scheduled--; +- ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H); +- ed->hwNextED = 0; +- wmb (); +- ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP | ED_DEQUEUE); +- +- /* but if there's work queued, reschedule */ +- if (!list_empty (&ed->td_list)) { +- if (ohci->rh_state == OHCI_RH_RUNNING) +- ed_schedule (ohci, ed); ++ /* ++ * If no TDs are queued, take ED off the ed_rm_list. ++ * Otherwise, if the HC is running, reschedule. ++ * If not, leave it on the list for further dequeues. ++ */ ++ if (list_empty(&ed->td_list)) { ++ *last = ed->ed_next; ++ ed->ed_next = NULL; ++ } else if (ohci->rh_state == OHCI_RH_RUNNING) { ++ *last = ed->ed_next; ++ ed->ed_next = NULL; ++ ed_schedule(ohci, ed); ++ } else { ++ last = &ed->ed_next; + } + + if (modified) +diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c +index 08a5f92d6c54..75cb1ff9d26b 100644 +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -101,6 +101,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + /* AMD PLL quirk */ + if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info()) + xhci->quirks |= XHCI_AMD_PLL_FIX; ++ ++ if (pdev->vendor == PCI_VENDOR_ID_AMD) ++ xhci->quirks |= XHCI_TRUST_TX_LENGTH; ++ + if (pdev->vendor == PCI_VENDOR_ID_INTEL) { + xhci->quirks |= XHCI_LPM_SUPPORT; + xhci->quirks |= XHCI_INTEL_HOST; +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index 65091d9aa997..0e6665a82e88 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -2612,7 +2612,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, + * last TRB of the previous TD. The command completion handle + * will take care the rest. + */ +- if (!event_seg && trb_comp_code == COMP_STOP_INVAL) { ++ if (!event_seg && (trb_comp_code == COMP_STOP || ++ trb_comp_code == COMP_STOP_INVAL)) { + ret = 0; + goto cleanup; + } +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index 8a3813be1b28..8b0f517abb6b 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -151,6 +151,7 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) }, ++ { USB_DEVICE(FTDI_VID, FTDI_BM_ATOM_NANO_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_NXTCAM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_EV3CON_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) }, +@@ -673,6 +674,8 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) }, + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) }, + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, ++ { USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) }, ++ { USB_DEVICE(XSENS_VID, XSENS_MTW_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) }, + { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, +@@ -945,6 +948,8 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_3_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_4_PID) }, ++ /* ekey Devices */ ++ { USB_DEVICE(FTDI_VID, FTDI_EKEY_CONV_USB_PID) }, + /* Infineon Devices */ + { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) }, + { } /* Terminating entry */ +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index c4777bc6aee0..70b0b1d88ae9 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -42,6 +42,8 @@ + /* www.candapter.com Ewert Energy Systems CANdapter device */ + #define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */ + ++#define FTDI_BM_ATOM_NANO_PID 0xa559 /* Basic Micro ATOM Nano USB2Serial */ ++ + /* + * Texas Instruments XDS100v2 JTAG / BeagleBone A3 + * http://processors.wiki.ti.com/index.php/XDS100 +@@ -140,12 +142,15 @@ + /* + * Xsens Technologies BV products (http://www.xsens.com). + */ +-#define XSENS_CONVERTER_0_PID 0xD388 +-#define XSENS_CONVERTER_1_PID 0xD389 ++#define XSENS_VID 0x2639 ++#define XSENS_CONVERTER_PID 0xD00D /* Xsens USB-serial converter */ ++#define XSENS_MTW_PID 0x0200 /* Xsens MTw */ ++#define XSENS_CONVERTER_0_PID 0xD388 /* Xsens USB converter */ ++#define XSENS_CONVERTER_1_PID 0xD389 /* Xsens Wireless Receiver */ + #define XSENS_CONVERTER_2_PID 0xD38A +-#define XSENS_CONVERTER_3_PID 0xD38B +-#define XSENS_CONVERTER_4_PID 0xD38C +-#define XSENS_CONVERTER_5_PID 0xD38D ++#define XSENS_CONVERTER_3_PID 0xD38B /* Xsens USB-serial converter */ ++#define XSENS_CONVERTER_4_PID 0xD38C /* Xsens Wireless Receiver */ ++#define XSENS_CONVERTER_5_PID 0xD38D /* Xsens Awinda Station */ + #define XSENS_CONVERTER_6_PID 0xD38E + #define XSENS_CONVERTER_7_PID 0xD38F + +@@ -1375,3 +1380,8 @@ + #define BRAINBOXES_US_160_6_PID 0x9006 /* US-160 16xRS232 1Mbaud Port 11 and 12 */ + #define BRAINBOXES_US_160_7_PID 0x9007 /* US-160 16xRS232 1Mbaud Port 13 and 14 */ + #define BRAINBOXES_US_160_8_PID 0x9008 /* US-160 16xRS232 1Mbaud Port 15 and 16 */ ++ ++/* ++ * ekey biometric systems GmbH (http://ekey.net/) ++ */ ++#define FTDI_EKEY_CONV_USB_PID 0xCB08 /* Converter USB */ +diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c +index e62f2dff8b7d..6c3734d2b45a 100644 +--- a/drivers/usb/serial/whiteheat.c ++++ b/drivers/usb/serial/whiteheat.c +@@ -514,6 +514,10 @@ static void command_port_read_callback(struct urb *urb) + dev_dbg(&urb->dev->dev, "%s - command_info is NULL, exiting.\n", __func__); + return; + } ++ if (!urb->actual_length) { ++ dev_dbg(&urb->dev->dev, "%s - empty response, exiting.\n", __func__); ++ return; ++ } + if (status) { + dev_dbg(&urb->dev->dev, "%s - nonzero urb status: %d\n", __func__, status); + if (status != -ENOENT) +@@ -534,7 +538,8 @@ static void command_port_read_callback(struct urb *urb) + /* These are unsolicited reports from the firmware, hence no + waiting command to wakeup */ + dev_dbg(&urb->dev->dev, "%s - event received\n", __func__); +- } else if (data[0] == WHITEHEAT_GET_DTR_RTS) { ++ } else if ((data[0] == WHITEHEAT_GET_DTR_RTS) && ++ (urb->actual_length - 1 <= sizeof(command_info->result_buffer))) { + memcpy(command_info->result_buffer, &data[1], + urb->actual_length - 1); + command_info->command_finished = WHITEHEAT_CMD_COMPLETE; +diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c +index 640b3cf1a338..172a8bc27abd 100644 +--- a/drivers/xen/events/events_fifo.c ++++ b/drivers/xen/events/events_fifo.c +@@ -67,10 +67,9 @@ static event_word_t *event_array[MAX_EVENT_ARRAY_PAGES] __read_mostly; + static unsigned event_array_pages __read_mostly; + + /* +- * sync_set_bit() and friends must be unsigned long aligned on non-x86 +- * platforms. ++ * sync_set_bit() and friends must be unsigned long aligned. + */ +-#if !defined(CONFIG_X86) && BITS_PER_LONG > 32 ++#if BITS_PER_LONG > 32 + + #define BM(w) (unsigned long *)((unsigned long)w & ~0x7UL) + #define EVTCHN_FIFO_BIT(b, w) \ +diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c +index 14d29d02097d..6244f9cf8ae3 100644 +--- a/fs/btrfs/backref.c ++++ b/fs/btrfs/backref.c +@@ -275,9 +275,8 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, + } + if (ret > 0) + goto next; +- ret = ulist_add_merge(parents, eb->start, +- (uintptr_t)eie, +- (u64 *)&old, GFP_NOFS); ++ ret = ulist_add_merge_ptr(parents, eb->start, ++ eie, (void **)&old, GFP_NOFS); + if (ret < 0) + break; + if (!ret && extent_item_pos) { +@@ -985,16 +984,19 @@ again: + ret = -EIO; + goto out; + } ++ btrfs_tree_read_lock(eb); ++ btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); + ret = find_extent_in_eb(eb, bytenr, + *extent_item_pos, &eie); ++ btrfs_tree_read_unlock_blocking(eb); + free_extent_buffer(eb); + if (ret < 0) + goto out; + ref->inode_list = eie; + } +- ret = ulist_add_merge(refs, ref->parent, +- (uintptr_t)ref->inode_list, +- (u64 *)&eie, GFP_NOFS); ++ ret = ulist_add_merge_ptr(refs, ref->parent, ++ ref->inode_list, ++ (void **)&eie, GFP_NOFS); + if (ret < 0) + goto out; + if (!ret && extent_item_pos) { +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 2eea43f5067c..1a858947006e 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -2525,6 +2525,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err) + test_bit(BIO_UPTODATE, &bio->bi_flags); + if (err) + uptodate = 0; ++ offset += len; + continue; + } + } +diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c +index 127555b29f58..ca248b0687f4 100644 +--- a/fs/btrfs/file-item.c ++++ b/fs/btrfs/file-item.c +@@ -756,7 +756,7 @@ again: + found_next = 1; + if (ret != 0) + goto insert; +- slot = 0; ++ slot = path->slots[0]; + } + btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot); + if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index d3d44486290b..c69c76351f12 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -701,6 +701,18 @@ retry: + unlock_extent(io_tree, async_extent->start, + async_extent->start + + async_extent->ram_size - 1); ++ ++ /* ++ * we need to redirty the pages if we decide to ++ * fallback to uncompressed IO, otherwise we ++ * will not submit these pages down to lower ++ * layers. ++ */ ++ extent_range_redirty_for_io(inode, ++ async_extent->start, ++ async_extent->start + ++ async_extent->ram_size - 1); ++ + goto retry; + } + goto out_free; +diff --git a/fs/btrfs/ulist.h b/fs/btrfs/ulist.h +index 7f78cbf5cf41..4c29db604bbe 100644 +--- a/fs/btrfs/ulist.h ++++ b/fs/btrfs/ulist.h +@@ -57,6 +57,21 @@ void ulist_free(struct ulist *ulist); + int ulist_add(struct ulist *ulist, u64 val, u64 aux, gfp_t gfp_mask); + int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux, + u64 *old_aux, gfp_t gfp_mask); ++ ++/* just like ulist_add_merge() but take a pointer for the aux data */ ++static inline int ulist_add_merge_ptr(struct ulist *ulist, u64 val, void *aux, ++ void **old_aux, gfp_t gfp_mask) ++{ ++#if BITS_PER_LONG == 32 ++ u64 old64 = (uintptr_t)*old_aux; ++ int ret = ulist_add_merge(ulist, val, (uintptr_t)aux, &old64, gfp_mask); ++ *old_aux = (void *)((uintptr_t)old64); ++ return ret; ++#else ++ return ulist_add_merge(ulist, val, (u64)aux, (u64 *)old_aux, gfp_mask); ++#endif ++} ++ + struct ulist_node *ulist_next(struct ulist *ulist, + struct ulist_iterator *uiter); + +diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c +index 9c0444cccbe1..15761957cc3f 100644 +--- a/fs/debugfs/inode.c ++++ b/fs/debugfs/inode.c +@@ -533,7 +533,7 @@ EXPORT_SYMBOL_GPL(debugfs_remove); + */ + void debugfs_remove_recursive(struct dentry *dentry) + { +- struct dentry *child, *next, *parent; ++ struct dentry *child, *parent; + + if (IS_ERR_OR_NULL(dentry)) + return; +@@ -545,30 +545,49 @@ void debugfs_remove_recursive(struct dentry *dentry) + parent = dentry; + down: + mutex_lock(&parent->d_inode->i_mutex); +- list_for_each_entry_safe(child, next, &parent->d_subdirs, d_u.d_child) { ++ loop: ++ /* ++ * The parent->d_subdirs is protected by the d_lock. Outside that ++ * lock, the child can be unlinked and set to be freed which can ++ * use the d_u.d_child as the rcu head and corrupt this list. ++ */ ++ spin_lock(&parent->d_lock); ++ list_for_each_entry(child, &parent->d_subdirs, d_u.d_child) { + if (!debugfs_positive(child)) + continue; + + /* perhaps simple_empty(child) makes more sense */ + if (!list_empty(&child->d_subdirs)) { ++ spin_unlock(&parent->d_lock); + mutex_unlock(&parent->d_inode->i_mutex); + parent = child; + goto down; + } +- up: ++ ++ spin_unlock(&parent->d_lock); ++ + if (!__debugfs_remove(child, parent)) + simple_release_fs(&debugfs_mount, &debugfs_mount_count); ++ ++ /* ++ * The parent->d_lock protects agaist child from unlinking ++ * from d_subdirs. When releasing the parent->d_lock we can ++ * no longer trust that the next pointer is valid. ++ * Restart the loop. We'll skip this one with the ++ * debugfs_positive() check. ++ */ ++ goto loop; + } ++ spin_unlock(&parent->d_lock); + + mutex_unlock(&parent->d_inode->i_mutex); + child = parent; + parent = parent->d_parent; + mutex_lock(&parent->d_inode->i_mutex); + +- if (child != dentry) { +- next = list_next_entry(child, d_u.d_child); +- goto up; +- } ++ if (child != dentry) ++ /* go up */ ++ goto loop; + + if (!__debugfs_remove(child, parent)) + simple_release_fs(&debugfs_mount, &debugfs_mount_count); +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index a7029f481b7b..b56062dc8b62 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -2195,6 +2195,7 @@ static int mpage_map_and_submit_extent(handle_t *handle, + struct ext4_map_blocks *map = &mpd->map; + int err; + loff_t disksize; ++ int progress = 0; + + mpd->io_submit.io_end->offset = + ((loff_t)map->m_lblk) << inode->i_blkbits; +@@ -2211,8 +2212,11 @@ static int mpage_map_and_submit_extent(handle_t *handle, + * is non-zero, a commit should free up blocks. + */ + if ((err == -ENOMEM) || +- (err == -ENOSPC && ext4_count_free_clusters(sb))) ++ (err == -ENOSPC && ext4_count_free_clusters(sb))) { ++ if (progress) ++ goto update_disksize; + return err; ++ } + ext4_msg(sb, KERN_CRIT, + "Delayed block allocation failed for " + "inode %lu at logical offset %llu with" +@@ -2229,15 +2233,17 @@ static int mpage_map_and_submit_extent(handle_t *handle, + *give_up_on_write = true; + return err; + } ++ progress = 1; + /* + * Update buffer state, submit mapped pages, and get us new + * extent to map + */ + err = mpage_map_and_submit_buffers(mpd); + if (err < 0) +- return err; ++ goto update_disksize; + } while (map->m_len); + ++update_disksize: + /* + * Update on-disk size after IO is submitted. Races with + * truncate are avoided by checking i_size under i_data_sem. +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 502f0fd71470..242226a87be7 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -1398,6 +1398,8 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, + int last = first + count - 1; + struct super_block *sb = e4b->bd_sb; + ++ if (WARN_ON(count == 0)) ++ return; + BUG_ON(last >= (sb->s_blocksize << 3)); + assert_spin_locked(ext4_group_lock_ptr(sb, e4b->bd_group)); + /* Don't bother if the block group is corrupt. */ +@@ -3196,8 +3198,30 @@ static void ext4_mb_collect_stats(struct ext4_allocation_context *ac) + static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac) + { + struct ext4_prealloc_space *pa = ac->ac_pa; ++ struct ext4_buddy e4b; ++ int err; + +- if (pa && pa->pa_type == MB_INODE_PA) ++ if (pa == NULL) { ++ if (ac->ac_f_ex.fe_len == 0) ++ return; ++ err = ext4_mb_load_buddy(ac->ac_sb, ac->ac_f_ex.fe_group, &e4b); ++ if (err) { ++ /* ++ * This should never happen since we pin the ++ * pages in the ext4_allocation_context so ++ * ext4_mb_load_buddy() should never fail. ++ */ ++ WARN(1, "mb_load_buddy failed (%d)", err); ++ return; ++ } ++ ext4_lock_group(ac->ac_sb, ac->ac_f_ex.fe_group); ++ mb_free_blocks(ac->ac_inode, &e4b, ac->ac_f_ex.fe_start, ++ ac->ac_f_ex.fe_len); ++ ext4_unlock_group(ac->ac_sb, ac->ac_f_ex.fe_group); ++ ext4_mb_unload_buddy(&e4b); ++ return; ++ } ++ if (pa->pa_type == MB_INODE_PA) + pa->pa_free += ac->ac_b_ex.fe_len; + } + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 25b327e87318..a46030d6b4af 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3169,9 +3169,9 @@ static int set_journal_csum_feature_set(struct super_block *sb) + + if (EXT4_HAS_RO_COMPAT_FEATURE(sb, + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { +- /* journal checksum v2 */ ++ /* journal checksum v3 */ + compat = 0; +- incompat = JBD2_FEATURE_INCOMPAT_CSUM_V2; ++ incompat = JBD2_FEATURE_INCOMPAT_CSUM_V3; + } else { + /* journal checksum v1 */ + compat = JBD2_FEATURE_COMPAT_CHECKSUM; +@@ -3193,6 +3193,7 @@ static int set_journal_csum_feature_set(struct super_block *sb) + jbd2_journal_clear_features(sbi->s_journal, + JBD2_FEATURE_COMPAT_CHECKSUM, 0, + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT | ++ JBD2_FEATURE_INCOMPAT_CSUM_V3 | + JBD2_FEATURE_INCOMPAT_CSUM_V2); + } + +diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c +index 4a9e10ea13f2..a9daccbd8fe7 100644 +--- a/fs/isofs/inode.c ++++ b/fs/isofs/inode.c +@@ -61,7 +61,7 @@ static void isofs_put_super(struct super_block *sb) + return; + } + +-static int isofs_read_inode(struct inode *); ++static int isofs_read_inode(struct inode *, int relocated); + static int isofs_statfs (struct dentry *, struct kstatfs *); + + static struct kmem_cache *isofs_inode_cachep; +@@ -1258,7 +1258,7 @@ out_toomany: + goto out; + } + +-static int isofs_read_inode(struct inode *inode) ++static int isofs_read_inode(struct inode *inode, int relocated) + { + struct super_block *sb = inode->i_sb; + struct isofs_sb_info *sbi = ISOFS_SB(sb); +@@ -1403,7 +1403,7 @@ static int isofs_read_inode(struct inode *inode) + */ + + if (!high_sierra) { +- parse_rock_ridge_inode(de, inode); ++ parse_rock_ridge_inode(de, inode, relocated); + /* if we want uid/gid set, override the rock ridge setting */ + if (sbi->s_uid_set) + inode->i_uid = sbi->s_uid; +@@ -1482,9 +1482,10 @@ static int isofs_iget5_set(struct inode *ino, void *data) + * offset that point to the underlying meta-data for the inode. The + * code below is otherwise similar to the iget() code in + * include/linux/fs.h */ +-struct inode *isofs_iget(struct super_block *sb, +- unsigned long block, +- unsigned long offset) ++struct inode *__isofs_iget(struct super_block *sb, ++ unsigned long block, ++ unsigned long offset, ++ int relocated) + { + unsigned long hashval; + struct inode *inode; +@@ -1506,7 +1507,7 @@ struct inode *isofs_iget(struct super_block *sb, + return ERR_PTR(-ENOMEM); + + if (inode->i_state & I_NEW) { +- ret = isofs_read_inode(inode); ++ ret = isofs_read_inode(inode, relocated); + if (ret < 0) { + iget_failed(inode); + inode = ERR_PTR(ret); +diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h +index 99167238518d..0ac4c1f73fbd 100644 +--- a/fs/isofs/isofs.h ++++ b/fs/isofs/isofs.h +@@ -107,7 +107,7 @@ extern int iso_date(char *, int); + + struct inode; /* To make gcc happy */ + +-extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *); ++extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *, int relocated); + extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *); + extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *); + +@@ -118,9 +118,24 @@ extern struct dentry *isofs_lookup(struct inode *, struct dentry *, unsigned int + extern struct buffer_head *isofs_bread(struct inode *, sector_t); + extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long); + +-extern struct inode *isofs_iget(struct super_block *sb, +- unsigned long block, +- unsigned long offset); ++struct inode *__isofs_iget(struct super_block *sb, ++ unsigned long block, ++ unsigned long offset, ++ int relocated); ++ ++static inline struct inode *isofs_iget(struct super_block *sb, ++ unsigned long block, ++ unsigned long offset) ++{ ++ return __isofs_iget(sb, block, offset, 0); ++} ++ ++static inline struct inode *isofs_iget_reloc(struct super_block *sb, ++ unsigned long block, ++ unsigned long offset) ++{ ++ return __isofs_iget(sb, block, offset, 1); ++} + + /* Because the inode number is no longer relevant to finding the + * underlying meta-data for an inode, we are free to choose a more +diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c +index c0bf42472e40..f488bbae541a 100644 +--- a/fs/isofs/rock.c ++++ b/fs/isofs/rock.c +@@ -288,12 +288,16 @@ eio: + goto out; + } + ++#define RR_REGARD_XA 1 ++#define RR_RELOC_DE 2 ++ + static int + parse_rock_ridge_inode_internal(struct iso_directory_record *de, +- struct inode *inode, int regard_xa) ++ struct inode *inode, int flags) + { + int symlink_len = 0; + int cnt, sig; ++ unsigned int reloc_block; + struct inode *reloc; + struct rock_ridge *rr; + int rootflag; +@@ -305,7 +309,7 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de, + + init_rock_state(&rs, inode); + setup_rock_ridge(de, inode, &rs); +- if (regard_xa) { ++ if (flags & RR_REGARD_XA) { + rs.chr += 14; + rs.len -= 14; + if (rs.len < 0) +@@ -485,12 +489,22 @@ repeat: + "relocated directory\n"); + goto out; + case SIG('C', 'L'): +- ISOFS_I(inode)->i_first_extent = +- isonum_733(rr->u.CL.location); +- reloc = +- isofs_iget(inode->i_sb, +- ISOFS_I(inode)->i_first_extent, +- 0); ++ if (flags & RR_RELOC_DE) { ++ printk(KERN_ERR ++ "ISOFS: Recursive directory relocation " ++ "is not supported\n"); ++ goto eio; ++ } ++ reloc_block = isonum_733(rr->u.CL.location); ++ if (reloc_block == ISOFS_I(inode)->i_iget5_block && ++ ISOFS_I(inode)->i_iget5_offset == 0) { ++ printk(KERN_ERR ++ "ISOFS: Directory relocation points to " ++ "itself\n"); ++ goto eio; ++ } ++ ISOFS_I(inode)->i_first_extent = reloc_block; ++ reloc = isofs_iget_reloc(inode->i_sb, reloc_block, 0); + if (IS_ERR(reloc)) { + ret = PTR_ERR(reloc); + goto out; +@@ -637,9 +651,11 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit) + return rpnt; + } + +-int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode) ++int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode, ++ int relocated) + { +- int result = parse_rock_ridge_inode_internal(de, inode, 0); ++ int flags = relocated ? RR_RELOC_DE : 0; ++ int result = parse_rock_ridge_inode_internal(de, inode, flags); + + /* + * if rockridge flag was reset and we didn't look for attributes +@@ -647,7 +663,8 @@ int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode) + */ + if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1) + && (ISOFS_SB(inode->i_sb)->s_rock == 2)) { +- result = parse_rock_ridge_inode_internal(de, inode, 14); ++ result = parse_rock_ridge_inode_internal(de, inode, ++ flags | RR_REGARD_XA); + } + return result; + } +diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c +index cf2fc0594063..9181c2b22b3c 100644 +--- a/fs/jbd2/commit.c ++++ b/fs/jbd2/commit.c +@@ -97,7 +97,7 @@ static void jbd2_commit_block_csum_set(journal_t *j, struct buffer_head *bh) + struct commit_header *h; + __u32 csum; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return; + + h = (struct commit_header *)(bh->b_data); +@@ -313,11 +313,11 @@ static __u32 jbd2_checksum_data(__u32 crc32_sum, struct buffer_head *bh) + return checksum; + } + +-static void write_tag_block(int tag_bytes, journal_block_tag_t *tag, ++static void write_tag_block(journal_t *j, journal_block_tag_t *tag, + unsigned long long block) + { + tag->t_blocknr = cpu_to_be32(block & (u32)~0); +- if (tag_bytes > JBD2_TAG_SIZE32) ++ if (JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_64BIT)) + tag->t_blocknr_high = cpu_to_be32((block >> 31) >> 1); + } + +@@ -327,7 +327,7 @@ static void jbd2_descr_block_csum_set(journal_t *j, + struct jbd2_journal_block_tail *tail; + __u32 csum; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return; + + tail = (struct jbd2_journal_block_tail *)(bh->b_data + j->j_blocksize - +@@ -340,12 +340,13 @@ static void jbd2_descr_block_csum_set(journal_t *j, + static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag, + struct buffer_head *bh, __u32 sequence) + { ++ journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag; + struct page *page = bh->b_page; + __u8 *addr; + __u32 csum32; + __be32 seq; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return; + + seq = cpu_to_be32(sequence); +@@ -355,8 +356,10 @@ static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag, + bh->b_size); + kunmap_atomic(addr); + +- /* We only have space to store the lower 16 bits of the crc32c. */ +- tag->t_checksum = cpu_to_be16(csum32); ++ if (JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V3)) ++ tag3->t_checksum = cpu_to_be32(csum32); ++ else ++ tag->t_checksum = cpu_to_be16(csum32); + } + /* + * jbd2_journal_commit_transaction +@@ -396,7 +399,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) + LIST_HEAD(io_bufs); + LIST_HEAD(log_bufs); + +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (jbd2_journal_has_csum_v2or3(journal)) + csum_size = sizeof(struct jbd2_journal_block_tail); + + /* +@@ -692,7 +695,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) + tag_flag |= JBD2_FLAG_SAME_UUID; + + tag = (journal_block_tag_t *) tagp; +- write_tag_block(tag_bytes, tag, jh2bh(jh)->b_blocknr); ++ write_tag_block(journal, tag, jh2bh(jh)->b_blocknr); + tag->t_flags = cpu_to_be16(tag_flag); + jbd2_block_tag_csum_set(journal, tag, wbuf[bufs], + commit_transaction->t_tid); +diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c +index 5fa344afb49a..f2d78a3dae43 100644 +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -124,7 +124,7 @@ EXPORT_SYMBOL(__jbd2_debug); + /* Checksumming functions */ + int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb) + { +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return 1; + + return sb->s_checksum_type == JBD2_CRC32C_CHKSUM; +@@ -145,7 +145,7 @@ static __be32 jbd2_superblock_csum(journal_t *j, journal_superblock_t *sb) + + int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb) + { +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return 1; + + return sb->s_checksum == jbd2_superblock_csum(j, sb); +@@ -153,7 +153,7 @@ int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb) + + void jbd2_superblock_csum_set(journal_t *j, journal_superblock_t *sb) + { +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return; + + sb->s_checksum = jbd2_superblock_csum(j, sb); +@@ -1522,21 +1522,29 @@ static int journal_get_superblock(journal_t *journal) + goto out; + } + +- if (JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM) && +- JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) { ++ if (jbd2_journal_has_csum_v2or3(journal) && ++ JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM)) { + /* Can't have checksum v1 and v2 on at the same time! */ + printk(KERN_ERR "JBD2: Can't enable checksumming v1 and v2 " + "at the same time!\n"); + goto out; + } + ++ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2) && ++ JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3)) { ++ /* Can't have checksum v2 and v3 at the same time! */ ++ printk(KERN_ERR "JBD2: Can't enable checksumming v2 and v3 " ++ "at the same time!\n"); ++ goto out; ++ } ++ + if (!jbd2_verify_csum_type(journal, sb)) { + printk(KERN_ERR "JBD2: Unknown checksum type\n"); + goto out; + } + + /* Load the checksum driver */ +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) { ++ if (jbd2_journal_has_csum_v2or3(journal)) { + journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0); + if (IS_ERR(journal->j_chksum_driver)) { + printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n"); +@@ -1553,7 +1561,7 @@ static int journal_get_superblock(journal_t *journal) + } + + /* Precompute checksum seed for all metadata */ +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (jbd2_journal_has_csum_v2or3(journal)) + journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid, + sizeof(sb->s_uuid)); + +@@ -1813,8 +1821,14 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, + if (!jbd2_journal_check_available_features(journal, compat, ro, incompat)) + return 0; + +- /* Asking for checksumming v2 and v1? Only give them v2. */ +- if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V2 && ++ /* If enabling v2 checksums, turn on v3 instead */ ++ if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V2) { ++ incompat &= ~JBD2_FEATURE_INCOMPAT_CSUM_V2; ++ incompat |= JBD2_FEATURE_INCOMPAT_CSUM_V3; ++ } ++ ++ /* Asking for checksumming v3 and v1? Only give them v3. */ ++ if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V3 && + compat & JBD2_FEATURE_COMPAT_CHECKSUM) + compat &= ~JBD2_FEATURE_COMPAT_CHECKSUM; + +@@ -1823,8 +1837,8 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, + + sb = journal->j_superblock; + +- /* If enabling v2 checksums, update superblock */ +- if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V2)) { ++ /* If enabling v3 checksums, update superblock */ ++ if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) { + sb->s_checksum_type = JBD2_CRC32C_CHKSUM; + sb->s_feature_compat &= + ~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM); +@@ -1842,8 +1856,7 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, + } + + /* Precompute checksum seed for all metadata */ +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, +- JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (jbd2_journal_has_csum_v2or3(journal)) + journal->j_csum_seed = jbd2_chksum(journal, ~0, + sb->s_uuid, + sizeof(sb->s_uuid)); +@@ -1852,7 +1865,8 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, + /* If enabling v1 checksums, downgrade superblock */ + if (COMPAT_FEATURE_ON(JBD2_FEATURE_COMPAT_CHECKSUM)) + sb->s_feature_incompat &= +- ~cpu_to_be32(JBD2_FEATURE_INCOMPAT_CSUM_V2); ++ ~cpu_to_be32(JBD2_FEATURE_INCOMPAT_CSUM_V2 | ++ JBD2_FEATURE_INCOMPAT_CSUM_V3); + + sb->s_feature_compat |= cpu_to_be32(compat); + sb->s_feature_ro_compat |= cpu_to_be32(ro); +@@ -2165,16 +2179,20 @@ int jbd2_journal_blocks_per_page(struct inode *inode) + */ + size_t journal_tag_bytes(journal_t *journal) + { +- journal_block_tag_t tag; +- size_t x = 0; ++ size_t sz; ++ ++ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3)) ++ return sizeof(journal_block_tag3_t); ++ ++ sz = sizeof(journal_block_tag_t); + + if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) +- x += sizeof(tag.t_checksum); ++ sz += sizeof(__u16); + + if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) +- return x + JBD2_TAG_SIZE64; ++ return sz; + else +- return x + JBD2_TAG_SIZE32; ++ return sz - sizeof(__u32); + } + + /* +diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c +index 3b6bb19d60b1..9b329b55ffe3 100644 +--- a/fs/jbd2/recovery.c ++++ b/fs/jbd2/recovery.c +@@ -181,7 +181,7 @@ static int jbd2_descr_block_csum_verify(journal_t *j, + __be32 provided; + __u32 calculated; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return 1; + + tail = (struct jbd2_journal_block_tail *)(buf + j->j_blocksize - +@@ -205,7 +205,7 @@ static int count_tags(journal_t *journal, struct buffer_head *bh) + int nr = 0, size = journal->j_blocksize; + int tag_bytes = journal_tag_bytes(journal); + +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (jbd2_journal_has_csum_v2or3(journal)) + size -= sizeof(struct jbd2_journal_block_tail); + + tagp = &bh->b_data[sizeof(journal_header_t)]; +@@ -338,10 +338,11 @@ int jbd2_journal_skip_recovery(journal_t *journal) + return err; + } + +-static inline unsigned long long read_tag_block(int tag_bytes, journal_block_tag_t *tag) ++static inline unsigned long long read_tag_block(journal_t *journal, ++ journal_block_tag_t *tag) + { + unsigned long long block = be32_to_cpu(tag->t_blocknr); +- if (tag_bytes > JBD2_TAG_SIZE32) ++ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) + block |= (u64)be32_to_cpu(tag->t_blocknr_high) << 32; + return block; + } +@@ -384,7 +385,7 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf) + __be32 provided; + __u32 calculated; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return 1; + + h = buf; +@@ -399,17 +400,21 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf) + static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag, + void *buf, __u32 sequence) + { ++ journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag; + __u32 csum32; + __be32 seq; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return 1; + + seq = cpu_to_be32(sequence); + csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq)); + csum32 = jbd2_chksum(j, csum32, buf, j->j_blocksize); + +- return tag->t_checksum == cpu_to_be16(csum32); ++ if (JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V3)) ++ return tag3->t_checksum == cpu_to_be32(csum32); ++ else ++ return tag->t_checksum == cpu_to_be16(csum32); + } + + static int do_one_pass(journal_t *journal, +@@ -426,6 +431,7 @@ static int do_one_pass(journal_t *journal, + int tag_bytes = journal_tag_bytes(journal); + __u32 crc32_sum = ~0; /* Transactional Checksums */ + int descr_csum_size = 0; ++ int block_error = 0; + + /* + * First thing is to establish what we expect to find in the log +@@ -512,8 +518,7 @@ static int do_one_pass(journal_t *journal, + switch(blocktype) { + case JBD2_DESCRIPTOR_BLOCK: + /* Verify checksum first */ +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, +- JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (jbd2_journal_has_csum_v2or3(journal)) + descr_csum_size = + sizeof(struct jbd2_journal_block_tail); + if (descr_csum_size > 0 && +@@ -574,7 +579,7 @@ static int do_one_pass(journal_t *journal, + unsigned long long blocknr; + + J_ASSERT(obh != NULL); +- blocknr = read_tag_block(tag_bytes, ++ blocknr = read_tag_block(journal, + tag); + + /* If the block has been +@@ -598,7 +603,8 @@ static int do_one_pass(journal_t *journal, + "checksum recovering " + "block %llu in log\n", + blocknr); +- continue; ++ block_error = 1; ++ goto skip_write; + } + + /* Find a buffer for the new +@@ -797,7 +803,8 @@ static int do_one_pass(journal_t *journal, + success = -EIO; + } + } +- ++ if (block_error && success == 0) ++ success = -EIO; + return success; + + failed: +@@ -811,7 +818,7 @@ static int jbd2_revoke_block_csum_verify(journal_t *j, + __be32 provided; + __u32 calculated; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return 1; + + tail = (struct jbd2_journal_revoke_tail *)(buf + j->j_blocksize - +diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c +index 198c9c10276d..d5e95a175c92 100644 +--- a/fs/jbd2/revoke.c ++++ b/fs/jbd2/revoke.c +@@ -91,8 +91,8 @@ + #include + #include + #include +-#endif + #include ++#endif + + static struct kmem_cache *jbd2_revoke_record_cache; + static struct kmem_cache *jbd2_revoke_table_cache; +@@ -597,7 +597,7 @@ static void write_one_revoke_record(journal_t *journal, + offset = *offsetp; + + /* Do we need to leave space at the end for a checksum? */ +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (jbd2_journal_has_csum_v2or3(journal)) + csum_size = sizeof(struct jbd2_journal_revoke_tail); + + /* Make sure we have a descriptor with space left for the record */ +@@ -644,7 +644,7 @@ static void jbd2_revoke_csum_set(journal_t *j, struct buffer_head *bh) + struct jbd2_journal_revoke_tail *tail; + __u32 csum; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return; + + tail = (struct jbd2_journal_revoke_tail *)(bh->b_data + j->j_blocksize - +diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c +index 8f854dde4150..24c6898159cc 100644 +--- a/fs/nfs/nfs3acl.c ++++ b/fs/nfs/nfs3acl.c +@@ -129,7 +129,10 @@ static int __nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, + .rpc_argp = &args, + .rpc_resp = &fattr, + }; +- int status; ++ int status = 0; ++ ++ if (acl == NULL && (!S_ISDIR(inode->i_mode) || dfacl == NULL)) ++ goto out; + + status = -EOPNOTSUPP; + if (!nfs_server_capable(inode, NFS_CAP_ACLS)) +@@ -256,7 +259,7 @@ nfs3_list_one_acl(struct inode *inode, int type, const char *name, void *data, + char *p = data + *result; + + acl = get_acl(inode, type); +- if (!acl) ++ if (IS_ERR_OR_NULL(acl)) + return 0; + + posix_acl_release(acl); +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index d5d06e868841..17f91a72840b 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -2546,6 +2546,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) + struct nfs4_closedata *calldata = data; + struct nfs4_state *state = calldata->state; + struct inode *inode = calldata->inode; ++ bool is_rdonly, is_wronly, is_rdwr; + int call_close = 0; + + dprintk("%s: begin!\n", __func__); +@@ -2553,18 +2554,24 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) + goto out_wait; + + task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; +- calldata->arg.fmode = FMODE_READ|FMODE_WRITE; + spin_lock(&state->owner->so_lock); ++ is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); ++ is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); ++ is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags); ++ /* Calculate the current open share mode */ ++ calldata->arg.fmode = 0; ++ if (is_rdonly || is_rdwr) ++ calldata->arg.fmode |= FMODE_READ; ++ if (is_wronly || is_rdwr) ++ calldata->arg.fmode |= FMODE_WRITE; + /* Calculate the change in open mode */ + if (state->n_rdwr == 0) { + if (state->n_rdonly == 0) { +- call_close |= test_bit(NFS_O_RDONLY_STATE, &state->flags); +- call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags); ++ call_close |= is_rdonly || is_rdwr; + calldata->arg.fmode &= ~FMODE_READ; + } + if (state->n_wronly == 0) { +- call_close |= test_bit(NFS_O_WRONLY_STATE, &state->flags); +- call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags); ++ call_close |= is_wronly || is_rdwr; + calldata->arg.fmode &= ~FMODE_WRITE; + } + } +diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c +index 3eaa6e30a2dc..cc8c5b32043c 100644 +--- a/fs/nfsd/nfs4callback.c ++++ b/fs/nfsd/nfs4callback.c +@@ -672,7 +672,8 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c + clp->cl_cb_session = ses; + args.bc_xprt = conn->cb_xprt; + args.prognumber = clp->cl_cb_session->se_cb_prog; +- args.protocol = XPRT_TRANSPORT_BC_TCP; ++ args.protocol = conn->cb_xprt->xpt_class->xcl_ident | ++ XPRT_TRANSPORT_BC; + args.authflavor = ses->se_cb_sec.flavor; + } + /* Create RPC client */ +diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c +index 9a4a5f9e7468..c34e45d1539b 100644 +--- a/fs/nfsd/nfssvc.c ++++ b/fs/nfsd/nfssvc.c +@@ -221,7 +221,8 @@ static int nfsd_startup_generic(int nrservs) + */ + ret = nfsd_racache_init(2*nrservs); + if (ret) +- return ret; ++ goto dec_users; ++ + ret = nfs4_state_start(); + if (ret) + goto out_racache; +@@ -229,6 +230,8 @@ static int nfsd_startup_generic(int nrservs) + + out_racache: + nfsd_racache_shutdown(); ++dec_users: ++ nfsd_users--; + return ret; + } + +diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h +index 49376aec2fbb..bcec4c46cc2e 100644 +--- a/include/drm/drm_pciids.h ++++ b/include/drm/drm_pciids.h +@@ -17,6 +17,7 @@ + {0x1002, 0x1315, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x1316, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x1317, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ ++ {0x1002, 0x1318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x131B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x131C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x131D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +@@ -164,8 +165,11 @@ + {0x1002, 0x6601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6602, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6603, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6604, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6605, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6606, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6607, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6608, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6610, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6611, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6613, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \ +@@ -175,6 +179,8 @@ + {0x1002, 0x6631, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ +@@ -297,6 +303,7 @@ + {0x1002, 0x6829, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x682A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x682B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x682C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x682D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x682F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ +diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h +index d5b50a19463c..0dae71e9971c 100644 +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -159,7 +159,11 @@ typedef struct journal_header_s + * journal_block_tag (in the descriptor). The other h_chksum* fields are + * not used. + * +- * Checksum v1 and v2 are mutually exclusive features. ++ * If FEATURE_INCOMPAT_CSUM_V3 is set, the descriptor block uses ++ * journal_block_tag3_t to store a full 32-bit checksum. Everything else ++ * is the same as v2. ++ * ++ * Checksum v1, v2, and v3 are mutually exclusive features. + */ + struct commit_header { + __be32 h_magic; +@@ -179,6 +183,14 @@ struct commit_header { + * raw struct shouldn't be used for pointer math or sizeof() - use + * journal_tag_bytes(journal) instead to compute this. + */ ++typedef struct journal_block_tag3_s ++{ ++ __be32 t_blocknr; /* The on-disk block number */ ++ __be32 t_flags; /* See below */ ++ __be32 t_blocknr_high; /* most-significant high 32bits. */ ++ __be32 t_checksum; /* crc32c(uuid+seq+block) */ ++} journal_block_tag3_t; ++ + typedef struct journal_block_tag_s + { + __be32 t_blocknr; /* The on-disk block number */ +@@ -187,9 +199,6 @@ typedef struct journal_block_tag_s + __be32 t_blocknr_high; /* most-significant high 32bits. */ + } journal_block_tag_t; + +-#define JBD2_TAG_SIZE32 (offsetof(journal_block_tag_t, t_blocknr_high)) +-#define JBD2_TAG_SIZE64 (sizeof(journal_block_tag_t)) +- + /* Tail of descriptor block, for checksumming */ + struct jbd2_journal_block_tail { + __be32 t_checksum; /* crc32c(uuid+descr_block) */ +@@ -284,6 +293,7 @@ typedef struct journal_superblock_s + #define JBD2_FEATURE_INCOMPAT_64BIT 0x00000002 + #define JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT 0x00000004 + #define JBD2_FEATURE_INCOMPAT_CSUM_V2 0x00000008 ++#define JBD2_FEATURE_INCOMPAT_CSUM_V3 0x00000010 + + /* Features known to this kernel version: */ + #define JBD2_KNOWN_COMPAT_FEATURES JBD2_FEATURE_COMPAT_CHECKSUM +@@ -291,7 +301,8 @@ typedef struct journal_superblock_s + #define JBD2_KNOWN_INCOMPAT_FEATURES (JBD2_FEATURE_INCOMPAT_REVOKE | \ + JBD2_FEATURE_INCOMPAT_64BIT | \ + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT | \ +- JBD2_FEATURE_INCOMPAT_CSUM_V2) ++ JBD2_FEATURE_INCOMPAT_CSUM_V2 | \ ++ JBD2_FEATURE_INCOMPAT_CSUM_V3) + + #ifdef __KERNEL__ + +@@ -1296,6 +1307,15 @@ static inline int tid_geq(tid_t x, tid_t y) + extern int jbd2_journal_blocks_per_page(struct inode *inode); + extern size_t journal_tag_bytes(journal_t *journal); + ++static inline int jbd2_journal_has_csum_v2or3(journal_t *journal) ++{ ++ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2) || ++ JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3)) ++ return 1; ++ ++ return 0; ++} ++ + /* + * We reserve t_outstanding_credits >> JBD2_CONTROL_BLOCKS_SHIFT for + * transaction control blocks. +diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h +index b05963f09ebf..f5bfb1a80abe 100644 +--- a/include/linux/sunrpc/svc_xprt.h ++++ b/include/linux/sunrpc/svc_xprt.h +@@ -32,6 +32,7 @@ struct svc_xprt_class { + struct svc_xprt_ops *xcl_ops; + struct list_head xcl_list; + u32 xcl_max_payload; ++ int xcl_ident; + }; + + /* +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 515e212421c0..677ebad70ce1 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -3511,9 +3511,10 @@ static int _sched_setscheduler(struct task_struct *p, int policy, + }; + + /* +- * Fixup the legacy SCHED_RESET_ON_FORK hack ++ * Fixup the legacy SCHED_RESET_ON_FORK hack, except if ++ * the policy=-1 was passed by sched_setparam(). + */ +- if (policy & SCHED_RESET_ON_FORK) { ++ if ((policy != -1) && (policy & SCHED_RESET_ON_FORK)) { + attr.sched_flags |= SCHED_FLAG_RESET_ON_FORK; + policy &= ~SCHED_RESET_ON_FORK; + attr.sched_policy = policy; +diff --git a/mm/util.c b/mm/util.c +index a24aa22f2473..c1010cb7ca0c 100644 +--- a/mm/util.c ++++ b/mm/util.c +@@ -275,17 +275,14 @@ pid_t vm_is_stack(struct task_struct *task, + + if (in_group) { + struct task_struct *t; +- rcu_read_lock(); +- if (!pid_alive(task)) +- goto done; + +- t = task; +- do { ++ rcu_read_lock(); ++ for_each_thread(task, t) { + if (vm_is_stack_for_task(t, vma)) { + ret = t->pid; + goto done; + } +- } while_each_thread(task, t); ++ } + done: + rcu_read_unlock(); + } +diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c +index d06cb8752dcd..5e8fe777772b 100644 +--- a/net/sunrpc/svcsock.c ++++ b/net/sunrpc/svcsock.c +@@ -685,6 +685,7 @@ static struct svc_xprt_class svc_udp_class = { + .xcl_owner = THIS_MODULE, + .xcl_ops = &svc_udp_ops, + .xcl_max_payload = RPCSVC_MAXPAYLOAD_UDP, ++ .xcl_ident = XPRT_TRANSPORT_UDP, + }; + + static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) +@@ -1279,6 +1280,7 @@ static struct svc_xprt_class svc_tcp_class = { + .xcl_owner = THIS_MODULE, + .xcl_ops = &svc_tcp_ops, + .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, ++ .xcl_ident = XPRT_TRANSPORT_TCP, + }; + + void svc_init_xprt_sock(void) +diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c +index 7d4df99f761f..03ac88431984 100644 +--- a/net/sunrpc/xprt.c ++++ b/net/sunrpc/xprt.c +@@ -1316,7 +1316,7 @@ struct rpc_xprt *xprt_create_transport(struct xprt_create *args) + } + } + spin_unlock(&xprt_list_lock); +- printk(KERN_ERR "RPC: transport (%d) not supported\n", args->ident); ++ dprintk("RPC: transport (%d) not supported\n", args->ident); + return ERR_PTR(-EIO); + + found: +diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c +index 62e4f9bcc387..ed36cb52cd86 100644 +--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c ++++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c +@@ -89,6 +89,7 @@ struct svc_xprt_class svc_rdma_class = { + .xcl_owner = THIS_MODULE, + .xcl_ops = &svc_rdma_ops, + .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, ++ .xcl_ident = XPRT_TRANSPORT_RDMA, + }; + + struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) +diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig +index 8756c8e32922..46e563046bfb 100644 +--- a/sound/pci/Kconfig ++++ b/sound/pci/Kconfig +@@ -859,8 +859,8 @@ config SND_VIRTUOSO + select SND_JACK if INPUT=y || INPUT=SND + help + Say Y here to include support for sound cards based on the +- Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS, +- Essence ST (Deluxe), and Essence STX. ++ Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS, DSX, ++ Essence ST (Deluxe), and Essence STX (II). + Support for the HDAV1.3 (Deluxe) and HDAV1.3 Slim is experimental; + for the Xense, missing. + +diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c +index 46ecdbb9053f..d5843da4ae19 100644 +--- a/sound/pci/hda/patch_ca0132.c ++++ b/sound/pci/hda/patch_ca0132.c +@@ -4379,6 +4379,9 @@ static void ca0132_download_dsp(struct hda_codec *codec) + return; /* NOP */ + #endif + ++ if (spec->dsp_state == DSP_DOWNLOAD_FAILED) ++ return; /* don't retry failures */ ++ + chipio_enable_clocks(codec); + spec->dsp_state = DSP_DOWNLOADING; + if (!ca0132_download_dsp_images(codec)) +@@ -4555,7 +4558,8 @@ static int ca0132_init(struct hda_codec *codec) + struct auto_pin_cfg *cfg = &spec->autocfg; + int i; + +- spec->dsp_state = DSP_DOWNLOAD_INIT; ++ if (spec->dsp_state != DSP_DOWNLOAD_FAILED) ++ spec->dsp_state = DSP_DOWNLOAD_INIT; + spec->curr_chip_addx = INVALID_CHIP_ADDRESS; + + snd_hda_power_up(codec); +@@ -4666,6 +4670,7 @@ static int patch_ca0132(struct hda_codec *codec) + codec->spec = spec; + spec->codec = codec; + ++ spec->dsp_state = DSP_DOWNLOAD_INIT; + spec->num_mixers = 1; + spec->mixers[0] = ca0132_mixer; + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 2a16a90fd952..b35dbe25a6e3 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -180,6 +180,8 @@ static void alc_fix_pll(struct hda_codec *codec) + spec->pll_coef_idx); + val = snd_hda_codec_read(codec, spec->pll_nid, 0, + AC_VERB_GET_PROC_COEF, 0); ++ if (val == -1) ++ return; + snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX, + spec->pll_coef_idx); + snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF, +@@ -2765,6 +2767,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec) + static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up) + { + int val = alc_read_coef_idx(codec, 0x04); ++ if (val == -1) ++ return; + if (power_up) + val |= 1 << 11; + else +@@ -3064,6 +3068,15 @@ static int alc269_resume(struct hda_codec *codec) + snd_hda_codec_resume_cache(codec); + alc_inv_dmic_sync(codec, true); + hda_call_check_power_status(codec, 0x01); ++ ++ /* on some machine, the BIOS will clear the codec gpio data when enter ++ * suspend, and won't restore the data after resume, so we restore it ++ * in the driver. ++ */ ++ if (spec->gpio_led) ++ snd_hda_codec_write(codec, codec->afg, 0, AC_VERB_SET_GPIO_DATA, ++ spec->gpio_led); ++ + if (spec->has_alc5505_dsp) + alc5505_dsp_resume(codec); + +@@ -4435,6 +4448,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), + SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED), + /* ALC282 */ ++ SND_PCI_QUIRK(0x103c, 0x2191, "HP Touchsmart 14", ALC269_FIXUP_HP_MUTE_LED_MIC1), ++ SND_PCI_QUIRK(0x103c, 0x2192, "HP Touchsmart 15", ALC269_FIXUP_HP_MUTE_LED_MIC1), + SND_PCI_QUIRK(0x103c, 0x220d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), + SND_PCI_QUIRK(0x103c, 0x220e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), + SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), +@@ -4633,27 +4648,30 @@ static void alc269_fill_coef(struct hda_codec *codec) + if ((alc_get_coef0(codec) & 0x00ff) == 0x017) { + val = alc_read_coef_idx(codec, 0x04); + /* Power up output pin */ +- alc_write_coef_idx(codec, 0x04, val | (1<<11)); ++ if (val != -1) ++ alc_write_coef_idx(codec, 0x04, val | (1<<11)); + } + + if ((alc_get_coef0(codec) & 0x00ff) == 0x018) { + val = alc_read_coef_idx(codec, 0xd); +- if ((val & 0x0c00) >> 10 != 0x1) { ++ if (val != -1 && (val & 0x0c00) >> 10 != 0x1) { + /* Capless ramp up clock control */ + alc_write_coef_idx(codec, 0xd, val | (1<<10)); + } + val = alc_read_coef_idx(codec, 0x17); +- if ((val & 0x01c0) >> 6 != 0x4) { ++ if (val != -1 && (val & 0x01c0) >> 6 != 0x4) { + /* Class D power on reset */ + alc_write_coef_idx(codec, 0x17, val | (1<<7)); + } + } + + val = alc_read_coef_idx(codec, 0xd); /* Class D */ +- alc_write_coef_idx(codec, 0xd, val | (1<<14)); ++ if (val != -1) ++ alc_write_coef_idx(codec, 0xd, val | (1<<14)); + + val = alc_read_coef_idx(codec, 0x4); /* HP */ +- alc_write_coef_idx(codec, 0x4, val | (1<<11)); ++ if (val != -1) ++ alc_write_coef_idx(codec, 0x4, val | (1<<11)); + } + + /* +diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c +index 3bc29c9b2529..978df990f27c 100644 +--- a/sound/pci/hda/patch_sigmatel.c ++++ b/sound/pci/hda/patch_sigmatel.c +@@ -84,6 +84,7 @@ enum { + STAC_DELL_EQ, + STAC_ALIENWARE_M17X, + STAC_92HD89XX_HP_FRONT_JACK, ++ STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK, + STAC_92HD73XX_MODELS + }; + +@@ -1803,6 +1804,11 @@ static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = { + {} + }; + ++static const struct hda_pintbl stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs[] = { ++ { 0x0e, 0x400000f0 }, ++ {} ++}; ++ + static void stac92hd73xx_fixup_ref(struct hda_codec *codec, + const struct hda_fixup *fix, int action) + { +@@ -1925,6 +1931,10 @@ static const struct hda_fixup stac92hd73xx_fixups[] = { + [STAC_92HD89XX_HP_FRONT_JACK] = { + .type = HDA_FIXUP_PINS, + .v.pins = stac92hd89xx_hp_front_jack_pin_configs, ++ }, ++ [STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs, + } + }; + +@@ -1985,6 +1995,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = { + "Alienware M17x", STAC_ALIENWARE_M17X), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, + "Alienware M17x R3", STAC_DELL_EQ), ++ SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1927, ++ "HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17, + "unknown HP", STAC_92HD89XX_HP_FRONT_JACK), + {} /* terminator */ +diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c +index 64b9fda5f04a..dbbbacfd535e 100644 +--- a/sound/pci/oxygen/virtuoso.c ++++ b/sound/pci/oxygen/virtuoso.c +@@ -53,6 +53,7 @@ static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = { + { OXYGEN_PCI_SUBID(0x1043, 0x835e) }, + { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, + { OXYGEN_PCI_SUBID(0x1043, 0x8522) }, ++ { OXYGEN_PCI_SUBID(0x1043, 0x85f4) }, + { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, + { } + }; +diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c +index c8c7f2c9b355..e02605931669 100644 +--- a/sound/pci/oxygen/xonar_pcm179x.c ++++ b/sound/pci/oxygen/xonar_pcm179x.c +@@ -100,8 +100,8 @@ + */ + + /* +- * Xonar Essence ST (Deluxe)/STX +- * ----------------------------- ++ * Xonar Essence ST (Deluxe)/STX (II) ++ * ---------------------------------- + * + * CMI8788: + * +@@ -1138,6 +1138,14 @@ int get_xonar_pcm179x_model(struct oxygen *chip, + chip->model.resume = xonar_stx_resume; + chip->model.set_dac_params = set_pcm1796_params; + break; ++ case 0x85f4: ++ chip->model = model_xonar_st; ++ /* TODO: daughterboard support */ ++ chip->model.shortname = "Xonar STX II"; ++ chip->model.init = xonar_stx_init; ++ chip->model.resume = xonar_stx_resume; ++ chip->model.set_dac_params = set_pcm1796_params; ++ break; + default: + return -EINVAL; + } +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index f652b10ce905..223c47b33ba3 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -1581,6 +1581,35 @@ YAMAHA_DEVICE(0x7010, "UB99"), + } + }, + { ++ /* BOSS ME-25 */ ++ USB_DEVICE(0x0582, 0x0113), ++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { ++ .ifnum = QUIRK_ANY_INTERFACE, ++ .type = QUIRK_COMPOSITE, ++ .data = (const struct snd_usb_audio_quirk[]) { ++ { ++ .ifnum = 0, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 1, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 2, ++ .type = QUIRK_MIDI_FIXED_ENDPOINT, ++ .data = & (const struct snd_usb_midi_endpoint_info) { ++ .out_cables = 0x0001, ++ .in_cables = 0x0001 ++ } ++ }, ++ { ++ .ifnum = -1 ++ } ++ } ++ } ++}, ++{ + /* only 44.1 kHz works at the moment */ + USB_DEVICE(0x0582, 0x0120), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 89730707614c..c64a3d96db22 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -666,7 +666,7 @@ static int snd_usb_gamecon780_boot_quirk(struct usb_device *dev) + /* set the initial volume and don't change; other values are either + * too loud or silent due to firmware bug (bko#65251) + */ +- u8 buf[2] = { 0x74, 0xdc }; ++ u8 buf[2] = { 0x74, 0xe3 }; + return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, + UAC_FU_VOLUME << 8, 9 << 8, buf, 2); +diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c +index 8c805a071507..b47541dd798f 100644 +--- a/virt/kvm/ioapic.c ++++ b/virt/kvm/ioapic.c +@@ -203,10 +203,9 @@ void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap, + spin_lock(&ioapic->lock); + for (index = 0; index < IOAPIC_NUM_PINS; index++) { + e = &ioapic->redirtbl[index]; +- if (!e->fields.mask && +- (e->fields.trig_mode == IOAPIC_LEVEL_TRIG || +- kvm_irq_has_notifier(ioapic->kvm, KVM_IRQCHIP_IOAPIC, +- index) || index == RTC_GSI)) { ++ if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG || ++ kvm_irq_has_notifier(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index) || ++ index == RTC_GSI) { + if (kvm_apic_match_dest(vcpu, NULL, 0, + e->fields.dest_id, e->fields.dest_mode)) { + __set_bit(e->fields.vector, +diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c +index 0df7d4b34dfe..714b94932312 100644 +--- a/virt/kvm/iommu.c ++++ b/virt/kvm/iommu.c +@@ -61,6 +61,14 @@ static pfn_t kvm_pin_pages(struct kvm_memory_slot *slot, gfn_t gfn, + return pfn; + } + ++static void kvm_unpin_pages(struct kvm *kvm, pfn_t pfn, unsigned long npages) ++{ ++ unsigned long i; ++ ++ for (i = 0; i < npages; ++i) ++ kvm_release_pfn_clean(pfn + i); ++} ++ + int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) + { + gfn_t gfn, end_gfn; +@@ -123,6 +131,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) + if (r) { + printk(KERN_ERR "kvm_iommu_map_address:" + "iommu failed to map pfn=%llx\n", pfn); ++ kvm_unpin_pages(kvm, pfn, page_size); + goto unmap_pages; + } + +@@ -134,7 +143,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) + return 0; + + unmap_pages: +- kvm_iommu_put_pages(kvm, slot->base_gfn, gfn); ++ kvm_iommu_put_pages(kvm, slot->base_gfn, gfn - slot->base_gfn); + return r; + } + +@@ -266,14 +275,6 @@ out_unlock: + return r; + } + +-static void kvm_unpin_pages(struct kvm *kvm, pfn_t pfn, unsigned long npages) +-{ +- unsigned long i; +- +- for (i = 0; i < npages; ++i) +- kvm_release_pfn_clean(pfn + i); +-} +- + static void kvm_iommu_put_pages(struct kvm *kvm, + gfn_t base_gfn, unsigned long npages) + { diff --git a/patch/kernel/cubox-default/patch-3.14.18-19.patch b/patch/kernel/cubox-default/patch-3.14.18-19.patch new file mode 100644 index 000000000..3b52b4ab6 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.18-19.patch @@ -0,0 +1,4843 @@ +diff --git a/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt b/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt +index 46f344965313..4eb7997674a0 100644 +--- a/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt ++++ b/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt +@@ -1,7 +1,7 @@ + ADI AXI-SPDIF controller + + Required properties: +- - compatible : Must be "adi,axi-spdif-1.00.a" ++ - compatible : Must be "adi,axi-spdif-tx-1.00.a" + - reg : Must contain SPDIF core's registers location and length + - clocks : Pairs of phandle and specifier referencing the controller's clocks. + The controller expects two clocks, the clock used for the AXI interface and +diff --git a/Makefile b/Makefile +index 05279d4f44c9..b1746b486646 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 18 ++SUBLEVEL = 19 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c +index 331b837cec57..270cb3c6c498 100644 +--- a/arch/mips/cavium-octeon/setup.c ++++ b/arch/mips/cavium-octeon/setup.c +@@ -458,6 +458,18 @@ static void octeon_halt(void) + octeon_kill_core(NULL); + } + ++static char __read_mostly octeon_system_type[80]; ++ ++static int __init init_octeon_system_type(void) ++{ ++ snprintf(octeon_system_type, sizeof(octeon_system_type), "%s (%s)", ++ cvmx_board_type_to_string(octeon_bootinfo->board_type), ++ octeon_model_get_string(read_c0_prid())); ++ ++ return 0; ++} ++early_initcall(init_octeon_system_type); ++ + /** + * Return a string representing the system type + * +@@ -465,11 +477,7 @@ static void octeon_halt(void) + */ + const char *octeon_board_type_string(void) + { +- static char name[80]; +- sprintf(name, "%s (%s)", +- cvmx_board_type_to_string(octeon_bootinfo->board_type), +- octeon_model_get_string(read_c0_prid())); +- return name; ++ return octeon_system_type; + } + + const char *get_system_type(void) +diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h +index 7bba9da110af..6d019ca1bead 100644 +--- a/arch/mips/include/asm/ptrace.h ++++ b/arch/mips/include/asm/ptrace.h +@@ -23,7 +23,7 @@ + struct pt_regs { + #ifdef CONFIG_32BIT + /* Pad bytes for argument save space on the stack. */ +- unsigned long pad0[6]; ++ unsigned long pad0[8]; + #endif + + /* Saved main processor registers. */ +diff --git a/arch/mips/include/asm/reg.h b/arch/mips/include/asm/reg.h +index 910e71a12466..b8343ccbc989 100644 +--- a/arch/mips/include/asm/reg.h ++++ b/arch/mips/include/asm/reg.h +@@ -12,116 +12,194 @@ + #ifndef __ASM_MIPS_REG_H + #define __ASM_MIPS_REG_H + +- +-#if defined(CONFIG_32BIT) || defined(WANT_COMPAT_REG_H) +- +-#define EF_R0 6 +-#define EF_R1 7 +-#define EF_R2 8 +-#define EF_R3 9 +-#define EF_R4 10 +-#define EF_R5 11 +-#define EF_R6 12 +-#define EF_R7 13 +-#define EF_R8 14 +-#define EF_R9 15 +-#define EF_R10 16 +-#define EF_R11 17 +-#define EF_R12 18 +-#define EF_R13 19 +-#define EF_R14 20 +-#define EF_R15 21 +-#define EF_R16 22 +-#define EF_R17 23 +-#define EF_R18 24 +-#define EF_R19 25 +-#define EF_R20 26 +-#define EF_R21 27 +-#define EF_R22 28 +-#define EF_R23 29 +-#define EF_R24 30 +-#define EF_R25 31 ++#define MIPS32_EF_R0 6 ++#define MIPS32_EF_R1 7 ++#define MIPS32_EF_R2 8 ++#define MIPS32_EF_R3 9 ++#define MIPS32_EF_R4 10 ++#define MIPS32_EF_R5 11 ++#define MIPS32_EF_R6 12 ++#define MIPS32_EF_R7 13 ++#define MIPS32_EF_R8 14 ++#define MIPS32_EF_R9 15 ++#define MIPS32_EF_R10 16 ++#define MIPS32_EF_R11 17 ++#define MIPS32_EF_R12 18 ++#define MIPS32_EF_R13 19 ++#define MIPS32_EF_R14 20 ++#define MIPS32_EF_R15 21 ++#define MIPS32_EF_R16 22 ++#define MIPS32_EF_R17 23 ++#define MIPS32_EF_R18 24 ++#define MIPS32_EF_R19 25 ++#define MIPS32_EF_R20 26 ++#define MIPS32_EF_R21 27 ++#define MIPS32_EF_R22 28 ++#define MIPS32_EF_R23 29 ++#define MIPS32_EF_R24 30 ++#define MIPS32_EF_R25 31 + + /* + * k0/k1 unsaved + */ +-#define EF_R26 32 +-#define EF_R27 33 ++#define MIPS32_EF_R26 32 ++#define MIPS32_EF_R27 33 + +-#define EF_R28 34 +-#define EF_R29 35 +-#define EF_R30 36 +-#define EF_R31 37 ++#define MIPS32_EF_R28 34 ++#define MIPS32_EF_R29 35 ++#define MIPS32_EF_R30 36 ++#define MIPS32_EF_R31 37 + + /* + * Saved special registers + */ +-#define EF_LO 38 +-#define EF_HI 39 +- +-#define EF_CP0_EPC 40 +-#define EF_CP0_BADVADDR 41 +-#define EF_CP0_STATUS 42 +-#define EF_CP0_CAUSE 43 +-#define EF_UNUSED0 44 +- +-#define EF_SIZE 180 +- +-#endif +- +-#if defined(CONFIG_64BIT) && !defined(WANT_COMPAT_REG_H) +- +-#define EF_R0 0 +-#define EF_R1 1 +-#define EF_R2 2 +-#define EF_R3 3 +-#define EF_R4 4 +-#define EF_R5 5 +-#define EF_R6 6 +-#define EF_R7 7 +-#define EF_R8 8 +-#define EF_R9 9 +-#define EF_R10 10 +-#define EF_R11 11 +-#define EF_R12 12 +-#define EF_R13 13 +-#define EF_R14 14 +-#define EF_R15 15 +-#define EF_R16 16 +-#define EF_R17 17 +-#define EF_R18 18 +-#define EF_R19 19 +-#define EF_R20 20 +-#define EF_R21 21 +-#define EF_R22 22 +-#define EF_R23 23 +-#define EF_R24 24 +-#define EF_R25 25 ++#define MIPS32_EF_LO 38 ++#define MIPS32_EF_HI 39 ++ ++#define MIPS32_EF_CP0_EPC 40 ++#define MIPS32_EF_CP0_BADVADDR 41 ++#define MIPS32_EF_CP0_STATUS 42 ++#define MIPS32_EF_CP0_CAUSE 43 ++#define MIPS32_EF_UNUSED0 44 ++ ++#define MIPS32_EF_SIZE 180 ++ ++#define MIPS64_EF_R0 0 ++#define MIPS64_EF_R1 1 ++#define MIPS64_EF_R2 2 ++#define MIPS64_EF_R3 3 ++#define MIPS64_EF_R4 4 ++#define MIPS64_EF_R5 5 ++#define MIPS64_EF_R6 6 ++#define MIPS64_EF_R7 7 ++#define MIPS64_EF_R8 8 ++#define MIPS64_EF_R9 9 ++#define MIPS64_EF_R10 10 ++#define MIPS64_EF_R11 11 ++#define MIPS64_EF_R12 12 ++#define MIPS64_EF_R13 13 ++#define MIPS64_EF_R14 14 ++#define MIPS64_EF_R15 15 ++#define MIPS64_EF_R16 16 ++#define MIPS64_EF_R17 17 ++#define MIPS64_EF_R18 18 ++#define MIPS64_EF_R19 19 ++#define MIPS64_EF_R20 20 ++#define MIPS64_EF_R21 21 ++#define MIPS64_EF_R22 22 ++#define MIPS64_EF_R23 23 ++#define MIPS64_EF_R24 24 ++#define MIPS64_EF_R25 25 + + /* + * k0/k1 unsaved + */ +-#define EF_R26 26 +-#define EF_R27 27 ++#define MIPS64_EF_R26 26 ++#define MIPS64_EF_R27 27 + + +-#define EF_R28 28 +-#define EF_R29 29 +-#define EF_R30 30 +-#define EF_R31 31 ++#define MIPS64_EF_R28 28 ++#define MIPS64_EF_R29 29 ++#define MIPS64_EF_R30 30 ++#define MIPS64_EF_R31 31 + + /* + * Saved special registers + */ +-#define EF_LO 32 +-#define EF_HI 33 +- +-#define EF_CP0_EPC 34 +-#define EF_CP0_BADVADDR 35 +-#define EF_CP0_STATUS 36 +-#define EF_CP0_CAUSE 37 +- +-#define EF_SIZE 304 /* size in bytes */ ++#define MIPS64_EF_LO 32 ++#define MIPS64_EF_HI 33 ++ ++#define MIPS64_EF_CP0_EPC 34 ++#define MIPS64_EF_CP0_BADVADDR 35 ++#define MIPS64_EF_CP0_STATUS 36 ++#define MIPS64_EF_CP0_CAUSE 37 ++ ++#define MIPS64_EF_SIZE 304 /* size in bytes */ ++ ++#if defined(CONFIG_32BIT) ++ ++#define EF_R0 MIPS32_EF_R0 ++#define EF_R1 MIPS32_EF_R1 ++#define EF_R2 MIPS32_EF_R2 ++#define EF_R3 MIPS32_EF_R3 ++#define EF_R4 MIPS32_EF_R4 ++#define EF_R5 MIPS32_EF_R5 ++#define EF_R6 MIPS32_EF_R6 ++#define EF_R7 MIPS32_EF_R7 ++#define EF_R8 MIPS32_EF_R8 ++#define EF_R9 MIPS32_EF_R9 ++#define EF_R10 MIPS32_EF_R10 ++#define EF_R11 MIPS32_EF_R11 ++#define EF_R12 MIPS32_EF_R12 ++#define EF_R13 MIPS32_EF_R13 ++#define EF_R14 MIPS32_EF_R14 ++#define EF_R15 MIPS32_EF_R15 ++#define EF_R16 MIPS32_EF_R16 ++#define EF_R17 MIPS32_EF_R17 ++#define EF_R18 MIPS32_EF_R18 ++#define EF_R19 MIPS32_EF_R19 ++#define EF_R20 MIPS32_EF_R20 ++#define EF_R21 MIPS32_EF_R21 ++#define EF_R22 MIPS32_EF_R22 ++#define EF_R23 MIPS32_EF_R23 ++#define EF_R24 MIPS32_EF_R24 ++#define EF_R25 MIPS32_EF_R25 ++#define EF_R26 MIPS32_EF_R26 ++#define EF_R27 MIPS32_EF_R27 ++#define EF_R28 MIPS32_EF_R28 ++#define EF_R29 MIPS32_EF_R29 ++#define EF_R30 MIPS32_EF_R30 ++#define EF_R31 MIPS32_EF_R31 ++#define EF_LO MIPS32_EF_LO ++#define EF_HI MIPS32_EF_HI ++#define EF_CP0_EPC MIPS32_EF_CP0_EPC ++#define EF_CP0_BADVADDR MIPS32_EF_CP0_BADVADDR ++#define EF_CP0_STATUS MIPS32_EF_CP0_STATUS ++#define EF_CP0_CAUSE MIPS32_EF_CP0_CAUSE ++#define EF_UNUSED0 MIPS32_EF_UNUSED0 ++#define EF_SIZE MIPS32_EF_SIZE ++ ++#elif defined(CONFIG_64BIT) ++ ++#define EF_R0 MIPS64_EF_R0 ++#define EF_R1 MIPS64_EF_R1 ++#define EF_R2 MIPS64_EF_R2 ++#define EF_R3 MIPS64_EF_R3 ++#define EF_R4 MIPS64_EF_R4 ++#define EF_R5 MIPS64_EF_R5 ++#define EF_R6 MIPS64_EF_R6 ++#define EF_R7 MIPS64_EF_R7 ++#define EF_R8 MIPS64_EF_R8 ++#define EF_R9 MIPS64_EF_R9 ++#define EF_R10 MIPS64_EF_R10 ++#define EF_R11 MIPS64_EF_R11 ++#define EF_R12 MIPS64_EF_R12 ++#define EF_R13 MIPS64_EF_R13 ++#define EF_R14 MIPS64_EF_R14 ++#define EF_R15 MIPS64_EF_R15 ++#define EF_R16 MIPS64_EF_R16 ++#define EF_R17 MIPS64_EF_R17 ++#define EF_R18 MIPS64_EF_R18 ++#define EF_R19 MIPS64_EF_R19 ++#define EF_R20 MIPS64_EF_R20 ++#define EF_R21 MIPS64_EF_R21 ++#define EF_R22 MIPS64_EF_R22 ++#define EF_R23 MIPS64_EF_R23 ++#define EF_R24 MIPS64_EF_R24 ++#define EF_R25 MIPS64_EF_R25 ++#define EF_R26 MIPS64_EF_R26 ++#define EF_R27 MIPS64_EF_R27 ++#define EF_R28 MIPS64_EF_R28 ++#define EF_R29 MIPS64_EF_R29 ++#define EF_R30 MIPS64_EF_R30 ++#define EF_R31 MIPS64_EF_R31 ++#define EF_LO MIPS64_EF_LO ++#define EF_HI MIPS64_EF_HI ++#define EF_CP0_EPC MIPS64_EF_CP0_EPC ++#define EF_CP0_BADVADDR MIPS64_EF_CP0_BADVADDR ++#define EF_CP0_STATUS MIPS64_EF_CP0_STATUS ++#define EF_CP0_CAUSE MIPS64_EF_CP0_CAUSE ++#define EF_SIZE MIPS64_EF_SIZE + + #endif /* CONFIG_64BIT */ + +diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c +index 7faf5f2bee25..71df942fb77c 100644 +--- a/arch/mips/kernel/binfmt_elfo32.c ++++ b/arch/mips/kernel/binfmt_elfo32.c +@@ -72,12 +72,6 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + + #include + +-/* +- * When this file is selected, we are definitely running a 64bit kernel. +- * So using the right regs define in asm/reg.h +- */ +-#define WANT_COMPAT_REG_H +- + /* These MUST be defined before elf.h gets included */ + extern void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs); + #define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs); +@@ -149,21 +143,21 @@ void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs) + { + int i; + +- for (i = 0; i < EF_R0; i++) ++ for (i = 0; i < MIPS32_EF_R0; i++) + grp[i] = 0; +- grp[EF_R0] = 0; ++ grp[MIPS32_EF_R0] = 0; + for (i = 1; i <= 31; i++) +- grp[EF_R0 + i] = (elf_greg_t) regs->regs[i]; +- grp[EF_R26] = 0; +- grp[EF_R27] = 0; +- grp[EF_LO] = (elf_greg_t) regs->lo; +- grp[EF_HI] = (elf_greg_t) regs->hi; +- grp[EF_CP0_EPC] = (elf_greg_t) regs->cp0_epc; +- grp[EF_CP0_BADVADDR] = (elf_greg_t) regs->cp0_badvaddr; +- grp[EF_CP0_STATUS] = (elf_greg_t) regs->cp0_status; +- grp[EF_CP0_CAUSE] = (elf_greg_t) regs->cp0_cause; +-#ifdef EF_UNUSED0 +- grp[EF_UNUSED0] = 0; ++ grp[MIPS32_EF_R0 + i] = (elf_greg_t) regs->regs[i]; ++ grp[MIPS32_EF_R26] = 0; ++ grp[MIPS32_EF_R27] = 0; ++ grp[MIPS32_EF_LO] = (elf_greg_t) regs->lo; ++ grp[MIPS32_EF_HI] = (elf_greg_t) regs->hi; ++ grp[MIPS32_EF_CP0_EPC] = (elf_greg_t) regs->cp0_epc; ++ grp[MIPS32_EF_CP0_BADVADDR] = (elf_greg_t) regs->cp0_badvaddr; ++ grp[MIPS32_EF_CP0_STATUS] = (elf_greg_t) regs->cp0_status; ++ grp[MIPS32_EF_CP0_CAUSE] = (elf_greg_t) regs->cp0_cause; ++#ifdef MIPS32_EF_UNUSED0 ++ grp[MIPS32_EF_UNUSED0] = 0; + #endif + } + +diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c +index 5b5ddb231f26..78f18436cdf2 100644 +--- a/arch/mips/kernel/irq-gic.c ++++ b/arch/mips/kernel/irq-gic.c +@@ -255,11 +255,13 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu, + + /* Setup Intr to Pin mapping */ + if (pin & GIC_MAP_TO_NMI_MSK) { ++ int i; ++ + GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin); + /* FIXME: hack to route NMI to all cpu's */ +- for (cpu = 0; cpu < NR_CPUS; cpu += 32) { ++ for (i = 0; i < NR_CPUS; i += 32) { + GICWRITE(GIC_REG_ADDR(SHARED, +- GIC_SH_MAP_TO_VPE_REG_OFF(intr, cpu)), ++ GIC_SH_MAP_TO_VPE_REG_OFF(intr, i)), + 0xffffffff); + } + } else { +diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c +index 7da9b76db4d9..60f48febe762 100644 +--- a/arch/mips/kernel/ptrace.c ++++ b/arch/mips/kernel/ptrace.c +@@ -170,6 +170,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) + __get_user(fregs[i], i + (__u64 __user *) data); + + __get_user(child->thread.fpu.fcr31, data + 64); ++ child->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; + + /* FIR may not be written. */ + +@@ -265,36 +266,160 @@ int ptrace_set_watch_regs(struct task_struct *child, + + /* regset get/set implementations */ + +-static int gpr_get(struct task_struct *target, +- const struct user_regset *regset, +- unsigned int pos, unsigned int count, +- void *kbuf, void __user *ubuf) ++#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32) ++ ++static int gpr32_get(struct task_struct *target, ++ const struct user_regset *regset, ++ unsigned int pos, unsigned int count, ++ void *kbuf, void __user *ubuf) + { + struct pt_regs *regs = task_pt_regs(target); ++ u32 uregs[ELF_NGREG] = {}; ++ unsigned i; + +- return user_regset_copyout(&pos, &count, &kbuf, &ubuf, +- regs, 0, sizeof(*regs)); ++ for (i = MIPS32_EF_R1; i <= MIPS32_EF_R31; i++) { ++ /* k0/k1 are copied as zero. */ ++ if (i == MIPS32_EF_R26 || i == MIPS32_EF_R27) ++ continue; ++ ++ uregs[i] = regs->regs[i - MIPS32_EF_R0]; ++ } ++ ++ uregs[MIPS32_EF_LO] = regs->lo; ++ uregs[MIPS32_EF_HI] = regs->hi; ++ uregs[MIPS32_EF_CP0_EPC] = regs->cp0_epc; ++ uregs[MIPS32_EF_CP0_BADVADDR] = regs->cp0_badvaddr; ++ uregs[MIPS32_EF_CP0_STATUS] = regs->cp0_status; ++ uregs[MIPS32_EF_CP0_CAUSE] = regs->cp0_cause; ++ ++ return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, ++ sizeof(uregs)); + } + +-static int gpr_set(struct task_struct *target, +- const struct user_regset *regset, +- unsigned int pos, unsigned int count, +- const void *kbuf, const void __user *ubuf) ++static int gpr32_set(struct task_struct *target, ++ const struct user_regset *regset, ++ unsigned int pos, unsigned int count, ++ const void *kbuf, const void __user *ubuf) + { +- struct pt_regs newregs; +- int ret; ++ struct pt_regs *regs = task_pt_regs(target); ++ u32 uregs[ELF_NGREG]; ++ unsigned start, num_regs, i; ++ int err; + +- ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, +- &newregs, +- 0, sizeof(newregs)); +- if (ret) +- return ret; ++ start = pos / sizeof(u32); ++ num_regs = count / sizeof(u32); + +- *task_pt_regs(target) = newregs; ++ if (start + num_regs > ELF_NGREG) ++ return -EIO; ++ ++ err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0, ++ sizeof(uregs)); ++ if (err) ++ return err; ++ ++ for (i = start; i < num_regs; i++) { ++ /* ++ * Cast all values to signed here so that if this is a 64-bit ++ * kernel, the supplied 32-bit values will be sign extended. ++ */ ++ switch (i) { ++ case MIPS32_EF_R1 ... MIPS32_EF_R25: ++ /* k0/k1 are ignored. */ ++ case MIPS32_EF_R28 ... MIPS32_EF_R31: ++ regs->regs[i - MIPS32_EF_R0] = (s32)uregs[i]; ++ break; ++ case MIPS32_EF_LO: ++ regs->lo = (s32)uregs[i]; ++ break; ++ case MIPS32_EF_HI: ++ regs->hi = (s32)uregs[i]; ++ break; ++ case MIPS32_EF_CP0_EPC: ++ regs->cp0_epc = (s32)uregs[i]; ++ break; ++ } ++ } + + return 0; + } + ++#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */ ++ ++#ifdef CONFIG_64BIT ++ ++static int gpr64_get(struct task_struct *target, ++ const struct user_regset *regset, ++ unsigned int pos, unsigned int count, ++ void *kbuf, void __user *ubuf) ++{ ++ struct pt_regs *regs = task_pt_regs(target); ++ u64 uregs[ELF_NGREG] = {}; ++ unsigned i; ++ ++ for (i = MIPS64_EF_R1; i <= MIPS64_EF_R31; i++) { ++ /* k0/k1 are copied as zero. */ ++ if (i == MIPS64_EF_R26 || i == MIPS64_EF_R27) ++ continue; ++ ++ uregs[i] = regs->regs[i - MIPS64_EF_R0]; ++ } ++ ++ uregs[MIPS64_EF_LO] = regs->lo; ++ uregs[MIPS64_EF_HI] = regs->hi; ++ uregs[MIPS64_EF_CP0_EPC] = regs->cp0_epc; ++ uregs[MIPS64_EF_CP0_BADVADDR] = regs->cp0_badvaddr; ++ uregs[MIPS64_EF_CP0_STATUS] = regs->cp0_status; ++ uregs[MIPS64_EF_CP0_CAUSE] = regs->cp0_cause; ++ ++ return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, ++ sizeof(uregs)); ++} ++ ++static int gpr64_set(struct task_struct *target, ++ const struct user_regset *regset, ++ unsigned int pos, unsigned int count, ++ const void *kbuf, const void __user *ubuf) ++{ ++ struct pt_regs *regs = task_pt_regs(target); ++ u64 uregs[ELF_NGREG]; ++ unsigned start, num_regs, i; ++ int err; ++ ++ start = pos / sizeof(u64); ++ num_regs = count / sizeof(u64); ++ ++ if (start + num_regs > ELF_NGREG) ++ return -EIO; ++ ++ err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0, ++ sizeof(uregs)); ++ if (err) ++ return err; ++ ++ for (i = start; i < num_regs; i++) { ++ switch (i) { ++ case MIPS64_EF_R1 ... MIPS64_EF_R25: ++ /* k0/k1 are ignored. */ ++ case MIPS64_EF_R28 ... MIPS64_EF_R31: ++ regs->regs[i - MIPS64_EF_R0] = uregs[i]; ++ break; ++ case MIPS64_EF_LO: ++ regs->lo = uregs[i]; ++ break; ++ case MIPS64_EF_HI: ++ regs->hi = uregs[i]; ++ break; ++ case MIPS64_EF_CP0_EPC: ++ regs->cp0_epc = uregs[i]; ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++#endif /* CONFIG_64BIT */ ++ + static int fpr_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, +@@ -322,14 +447,16 @@ enum mips_regset { + REGSET_FPR, + }; + ++#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32) ++ + static const struct user_regset mips_regsets[] = { + [REGSET_GPR] = { + .core_note_type = NT_PRSTATUS, + .n = ELF_NGREG, + .size = sizeof(unsigned int), + .align = sizeof(unsigned int), +- .get = gpr_get, +- .set = gpr_set, ++ .get = gpr32_get, ++ .set = gpr32_set, + }, + [REGSET_FPR] = { + .core_note_type = NT_PRFPREG, +@@ -349,14 +476,18 @@ static const struct user_regset_view user_mips_view = { + .n = ARRAY_SIZE(mips_regsets), + }; + ++#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */ ++ ++#ifdef CONFIG_64BIT ++ + static const struct user_regset mips64_regsets[] = { + [REGSET_GPR] = { + .core_note_type = NT_PRSTATUS, + .n = ELF_NGREG, + .size = sizeof(unsigned long), + .align = sizeof(unsigned long), +- .get = gpr_get, +- .set = gpr_set, ++ .get = gpr64_get, ++ .set = gpr64_set, + }, + [REGSET_FPR] = { + .core_note_type = NT_PRFPREG, +@@ -369,25 +500,26 @@ static const struct user_regset mips64_regsets[] = { + }; + + static const struct user_regset_view user_mips64_view = { +- .name = "mips", ++ .name = "mips64", + .e_machine = ELF_ARCH, + .ei_osabi = ELF_OSABI, + .regsets = mips64_regsets, +- .n = ARRAY_SIZE(mips_regsets), ++ .n = ARRAY_SIZE(mips64_regsets), + }; + ++#endif /* CONFIG_64BIT */ ++ + const struct user_regset_view *task_user_regset_view(struct task_struct *task) + { + #ifdef CONFIG_32BIT + return &user_mips_view; +-#endif +- ++#else + #ifdef CONFIG_MIPS32_O32 +- if (test_thread_flag(TIF_32BIT_REGS)) +- return &user_mips_view; ++ if (test_tsk_thread_flag(task, TIF_32BIT_REGS)) ++ return &user_mips_view; + #endif +- + return &user_mips64_view; ++#endif + } + + long arch_ptrace(struct task_struct *child, long request, +@@ -593,7 +725,7 @@ long arch_ptrace(struct task_struct *child, long request, + break; + #endif + case FPC_CSR: +- child->thread.fpu.fcr31 = data; ++ child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X; + break; + case DSP_BASE ... DSP_BASE + 5: { + dspreg_t *dregs; +diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c +index c369a5d35527..b897dde93e7a 100644 +--- a/arch/mips/kernel/unaligned.c ++++ b/arch/mips/kernel/unaligned.c +@@ -605,7 +605,6 @@ static void emulate_load_store_insn(struct pt_regs *regs, + case sdc1_op: + die_if_kernel("Unaligned FP access in kernel code", regs); + BUG_ON(!used_math()); +- BUG_ON(!is_fpu_owner()); + + lose_fpu(1); /* Save FPU state for the emulator. */ + res = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, +diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c +index b234b1b5ccad..65d452aa1fda 100644 +--- a/arch/mips/mm/tlbex.c ++++ b/arch/mips/mm/tlbex.c +@@ -1295,6 +1295,7 @@ static void build_r4000_tlb_refill_handler(void) + } + #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT + uasm_l_tlb_huge_update(&l, p); ++ UASM_i_LW(&p, K0, 0, K1); + build_huge_update_entries(&p, htlb_info.huge_pte, K1); + build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random, + htlb_info.restore_scratch); +diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h +index ad3025d0880b..f20786825b8f 100644 +--- a/arch/powerpc/include/asm/machdep.h ++++ b/arch/powerpc/include/asm/machdep.h +@@ -57,10 +57,10 @@ struct machdep_calls { + void (*hpte_removebolted)(unsigned long ea, + int psize, int ssize); + void (*flush_hash_range)(unsigned long number, int local); +- void (*hugepage_invalidate)(struct mm_struct *mm, ++ void (*hugepage_invalidate)(unsigned long vsid, ++ unsigned long addr, + unsigned char *hpte_slot_array, +- unsigned long addr, int psize); +- ++ int psize, int ssize); + /* special for kexec, to be called in real mode, linear mapping is + * destroyed as well */ + void (*hpte_clear_all)(void); +diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h +index eb9261024f51..7b3d54fae46f 100644 +--- a/arch/powerpc/include/asm/pgtable-ppc64.h ++++ b/arch/powerpc/include/asm/pgtable-ppc64.h +@@ -413,7 +413,7 @@ static inline char *get_hpte_slot_array(pmd_t *pmdp) + } + + extern void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, +- pmd_t *pmdp); ++ pmd_t *pmdp, unsigned long old_pmd); + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + extern pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot); + extern pmd_t mk_pmd(struct page *page, pgprot_t pgprot); +diff --git a/arch/powerpc/include/asm/pte-hash64-64k.h b/arch/powerpc/include/asm/pte-hash64-64k.h +index d836d945068d..9ecede1e124c 100644 +--- a/arch/powerpc/include/asm/pte-hash64-64k.h ++++ b/arch/powerpc/include/asm/pte-hash64-64k.h +@@ -46,11 +46,31 @@ + * in order to deal with 64K made of 4K HW pages. Thus we override the + * generic accessors and iterators here + */ +-#define __real_pte(e,p) ((real_pte_t) { \ +- (e), (pte_val(e) & _PAGE_COMBO) ? \ +- (pte_val(*((p) + PTRS_PER_PTE))) : 0 }) +-#define __rpte_to_hidx(r,index) ((pte_val((r).pte) & _PAGE_COMBO) ? \ +- (((r).hidx >> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf)) ++#define __real_pte __real_pte ++static inline real_pte_t __real_pte(pte_t pte, pte_t *ptep) ++{ ++ real_pte_t rpte; ++ ++ rpte.pte = pte; ++ rpte.hidx = 0; ++ if (pte_val(pte) & _PAGE_COMBO) { ++ /* ++ * Make sure we order the hidx load against the _PAGE_COMBO ++ * check. The store side ordering is done in __hash_page_4K ++ */ ++ smp_rmb(); ++ rpte.hidx = pte_val(*((ptep) + PTRS_PER_PTE)); ++ } ++ return rpte; ++} ++ ++static inline unsigned long __rpte_to_hidx(real_pte_t rpte, unsigned long index) ++{ ++ if ((pte_val(rpte.pte) & _PAGE_COMBO)) ++ return (rpte.hidx >> (index<<2)) & 0xf; ++ return (pte_val(rpte.pte) >> 12) & 0xf; ++} ++ + #define __rpte_to_pte(r) ((r).pte) + #define __rpte_sub_valid(rpte, index) \ + (pte_val(rpte.pte) & (_PAGE_HPTE_SUB0 >> (index))) +diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c +index 3ea26c25590b..838de8e17dc5 100644 +--- a/arch/powerpc/mm/hash_native_64.c ++++ b/arch/powerpc/mm/hash_native_64.c +@@ -418,18 +418,18 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long vpn, + local_irq_restore(flags); + } + +-static void native_hugepage_invalidate(struct mm_struct *mm, ++static void native_hugepage_invalidate(unsigned long vsid, ++ unsigned long addr, + unsigned char *hpte_slot_array, +- unsigned long addr, int psize) ++ int psize, int ssize) + { +- int ssize = 0, i; +- int lock_tlbie; ++ int i; + struct hash_pte *hptep; + int actual_psize = MMU_PAGE_16M; + unsigned int max_hpte_count, valid; + unsigned long flags, s_addr = addr; + unsigned long hpte_v, want_v, shift; +- unsigned long hidx, vpn = 0, vsid, hash, slot; ++ unsigned long hidx, vpn = 0, hash, slot; + + shift = mmu_psize_defs[psize].shift; + max_hpte_count = 1U << (PMD_SHIFT - shift); +@@ -443,15 +443,6 @@ static void native_hugepage_invalidate(struct mm_struct *mm, + + /* get the vpn */ + addr = s_addr + (i * (1ul << shift)); +- if (!is_kernel_addr(addr)) { +- ssize = user_segment_size(addr); +- vsid = get_vsid(mm->context.id, addr, ssize); +- WARN_ON(vsid == 0); +- } else { +- vsid = get_kernel_vsid(addr, mmu_kernel_ssize); +- ssize = mmu_kernel_ssize; +- } +- + vpn = hpt_vpn(addr, vsid, ssize); + hash = hpt_hash(vpn, shift, ssize); + if (hidx & _PTEIDX_SECONDARY) +@@ -471,22 +462,13 @@ static void native_hugepage_invalidate(struct mm_struct *mm, + else + /* Invalidate the hpte. NOTE: this also unlocks it */ + hptep->v = 0; ++ /* ++ * We need to do tlb invalidate for all the address, tlbie ++ * instruction compares entry_VA in tlb with the VA specified ++ * here ++ */ ++ tlbie(vpn, psize, actual_psize, ssize, 0); + } +- /* +- * Since this is a hugepage, we just need a single tlbie. +- * use the last vpn. +- */ +- lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); +- if (lock_tlbie) +- raw_spin_lock(&native_tlbie_lock); +- +- asm volatile("ptesync":::"memory"); +- __tlbie(vpn, psize, actual_psize, ssize); +- asm volatile("eieio; tlbsync; ptesync":::"memory"); +- +- if (lock_tlbie) +- raw_spin_unlock(&native_tlbie_lock); +- + local_irq_restore(flags); + } + +diff --git a/arch/powerpc/mm/hugepage-hash64.c b/arch/powerpc/mm/hugepage-hash64.c +index 826893fcb3a7..5f5e6328c21c 100644 +--- a/arch/powerpc/mm/hugepage-hash64.c ++++ b/arch/powerpc/mm/hugepage-hash64.c +@@ -18,6 +18,57 @@ + #include + #include + ++static void invalidate_old_hpte(unsigned long vsid, unsigned long addr, ++ pmd_t *pmdp, unsigned int psize, int ssize) ++{ ++ int i, max_hpte_count, valid; ++ unsigned long s_addr; ++ unsigned char *hpte_slot_array; ++ unsigned long hidx, shift, vpn, hash, slot; ++ ++ s_addr = addr & HPAGE_PMD_MASK; ++ hpte_slot_array = get_hpte_slot_array(pmdp); ++ /* ++ * IF we try to do a HUGE PTE update after a withdraw is done. ++ * we will find the below NULL. This happens when we do ++ * split_huge_page_pmd ++ */ ++ if (!hpte_slot_array) ++ return; ++ ++ if (ppc_md.hugepage_invalidate) ++ return ppc_md.hugepage_invalidate(vsid, s_addr, hpte_slot_array, ++ psize, ssize); ++ /* ++ * No bluk hpte removal support, invalidate each entry ++ */ ++ shift = mmu_psize_defs[psize].shift; ++ max_hpte_count = HPAGE_PMD_SIZE >> shift; ++ for (i = 0; i < max_hpte_count; i++) { ++ /* ++ * 8 bits per each hpte entries ++ * 000| [ secondary group (one bit) | hidx (3 bits) | valid bit] ++ */ ++ valid = hpte_valid(hpte_slot_array, i); ++ if (!valid) ++ continue; ++ hidx = hpte_hash_index(hpte_slot_array, i); ++ ++ /* get the vpn */ ++ addr = s_addr + (i * (1ul << shift)); ++ vpn = hpt_vpn(addr, vsid, ssize); ++ hash = hpt_hash(vpn, shift, ssize); ++ if (hidx & _PTEIDX_SECONDARY) ++ hash = ~hash; ++ ++ slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; ++ slot += hidx & _PTEIDX_GROUP_IX; ++ ppc_md.hpte_invalidate(slot, vpn, psize, ++ MMU_PAGE_16M, ssize, 0); ++ } ++} ++ ++ + int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, + pmd_t *pmdp, unsigned long trap, int local, int ssize, + unsigned int psize) +@@ -33,7 +84,9 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, + * atomically mark the linux large page PMD busy and dirty + */ + do { +- old_pmd = pmd_val(*pmdp); ++ pmd_t pmd = ACCESS_ONCE(*pmdp); ++ ++ old_pmd = pmd_val(pmd); + /* If PMD busy, retry the access */ + if (unlikely(old_pmd & _PAGE_BUSY)) + return 0; +@@ -85,6 +138,15 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, + vpn = hpt_vpn(ea, vsid, ssize); + hash = hpt_hash(vpn, shift, ssize); + hpte_slot_array = get_hpte_slot_array(pmdp); ++ if (psize == MMU_PAGE_4K) { ++ /* ++ * invalidate the old hpte entry if we have that mapped via 64K ++ * base page size. This is because demote_segment won't flush ++ * hash page table entries. ++ */ ++ if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO)) ++ invalidate_old_hpte(vsid, ea, pmdp, MMU_PAGE_64K, ssize); ++ } + + valid = hpte_valid(hpte_slot_array, index); + if (valid) { +@@ -107,11 +169,8 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, + * safely update this here. + */ + valid = 0; +- new_pmd &= ~_PAGE_HPTEFLAGS; + hpte_slot_array[index] = 0; +- } else +- /* clear the busy bits and set the hash pte bits */ +- new_pmd = (new_pmd & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE; ++ } + } + + if (!valid) { +@@ -119,11 +178,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, + + /* insert new entry */ + pa = pmd_pfn(__pmd(old_pmd)) << PAGE_SHIFT; +-repeat: +- hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; +- +- /* clear the busy bits and set the hash pte bits */ +- new_pmd = (new_pmd & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE; ++ new_pmd |= _PAGE_HASHPTE; + + /* Add in WIMG bits */ + rflags |= (new_pmd & (_PAGE_WRITETHRU | _PAGE_NO_CACHE | +@@ -132,6 +187,8 @@ repeat: + * enable the memory coherence always + */ + rflags |= HPTE_R_M; ++repeat: ++ hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; + + /* Insert into the hash table, primary slot */ + slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0, +@@ -172,8 +229,17 @@ repeat: + mark_hpte_slot_valid(hpte_slot_array, index, slot); + } + /* +- * No need to use ldarx/stdcx here ++ * Mark the pte with _PAGE_COMBO, if we are trying to hash it with ++ * base page size 4k. ++ */ ++ if (psize == MMU_PAGE_4K) ++ new_pmd |= _PAGE_COMBO; ++ /* ++ * The hpte valid is stored in the pgtable whose address is in the ++ * second half of the PMD. Order this against clearing of the busy bit in ++ * huge pmd. + */ ++ smp_wmb(); + *pmdp = __pmd(new_pmd & ~_PAGE_BUSY); + return 0; + } +diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c +index 30a42e24bf14..a5fff173be4f 100644 +--- a/arch/powerpc/mm/numa.c ++++ b/arch/powerpc/mm/numa.c +@@ -610,8 +610,8 @@ static int cpu_numa_callback(struct notifier_block *nfb, unsigned long action, + case CPU_UP_CANCELED: + case CPU_UP_CANCELED_FROZEN: + unmap_cpu_from_node(lcpu); +- break; + ret = NOTIFY_OK; ++ break; + #endif + } + return ret; +diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c +index 62bf5e8e78da..c64da56d7582 100644 +--- a/arch/powerpc/mm/pgtable_64.c ++++ b/arch/powerpc/mm/pgtable_64.c +@@ -538,7 +538,7 @@ unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr, + *pmdp = __pmd((old & ~clr) | set); + #endif + if (old & _PAGE_HASHPTE) +- hpte_do_hugepage_flush(mm, addr, pmdp); ++ hpte_do_hugepage_flush(mm, addr, pmdp, old); + return old; + } + +@@ -645,7 +645,7 @@ void pmdp_splitting_flush(struct vm_area_struct *vma, + if (!(old & _PAGE_SPLITTING)) { + /* We need to flush the hpte */ + if (old & _PAGE_HASHPTE) +- hpte_do_hugepage_flush(vma->vm_mm, address, pmdp); ++ hpte_do_hugepage_flush(vma->vm_mm, address, pmdp, old); + } + } + +@@ -718,7 +718,7 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, + * neesd to be flushed. + */ + void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, +- pmd_t *pmdp) ++ pmd_t *pmdp, unsigned long old_pmd) + { + int ssize, i; + unsigned long s_addr; +@@ -740,12 +740,29 @@ void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, + if (!hpte_slot_array) + return; + +- /* get the base page size */ ++ /* get the base page size,vsid and segment size */ ++#ifdef CONFIG_DEBUG_VM + psize = get_slice_psize(mm, s_addr); ++ BUG_ON(psize == MMU_PAGE_16M); ++#endif ++ if (old_pmd & _PAGE_COMBO) ++ psize = MMU_PAGE_4K; ++ else ++ psize = MMU_PAGE_64K; ++ ++ if (!is_kernel_addr(s_addr)) { ++ ssize = user_segment_size(s_addr); ++ vsid = get_vsid(mm->context.id, s_addr, ssize); ++ WARN_ON(vsid == 0); ++ } else { ++ vsid = get_kernel_vsid(s_addr, mmu_kernel_ssize); ++ ssize = mmu_kernel_ssize; ++ } + + if (ppc_md.hugepage_invalidate) +- return ppc_md.hugepage_invalidate(mm, hpte_slot_array, +- s_addr, psize); ++ return ppc_md.hugepage_invalidate(vsid, s_addr, ++ hpte_slot_array, ++ psize, ssize); + /* + * No bluk hpte removal support, invalidate each entry + */ +@@ -763,15 +780,6 @@ void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, + + /* get the vpn */ + addr = s_addr + (i * (1ul << shift)); +- if (!is_kernel_addr(addr)) { +- ssize = user_segment_size(addr); +- vsid = get_vsid(mm->context.id, addr, ssize); +- WARN_ON(vsid == 0); +- } else { +- vsid = get_kernel_vsid(addr, mmu_kernel_ssize); +- ssize = mmu_kernel_ssize; +- } +- + vpn = hpt_vpn(addr, vsid, ssize); + hash = hpt_hash(vpn, shift, ssize); + if (hidx & _PTEIDX_SECONDARY) +diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c +index c99f6510a0b2..9adda5790463 100644 +--- a/arch/powerpc/mm/tlb_hash64.c ++++ b/arch/powerpc/mm/tlb_hash64.c +@@ -216,7 +216,7 @@ void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, + if (!(pte & _PAGE_HASHPTE)) + continue; + if (unlikely(hugepage_shift && pmd_trans_huge(*(pmd_t *)pte))) +- hpte_do_hugepage_flush(mm, start, (pmd_t *)pte); ++ hpte_do_hugepage_flush(mm, start, (pmd_t *)ptep, pte); + else + hpte_need_flush(mm, start, ptep, pte, 0); + } +diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c +index 9590dbb756f2..b9a82042760f 100644 +--- a/arch/powerpc/platforms/pseries/hotplug-memory.c ++++ b/arch/powerpc/platforms/pseries/hotplug-memory.c +@@ -160,7 +160,7 @@ static int pseries_remove_memory(struct device_node *np) + static inline int pseries_remove_memblock(unsigned long base, + unsigned int memblock_size) + { +- return -EOPNOTSUPP; ++ return 0; + } + static inline int pseries_remove_memory(struct device_node *np) + { +diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c +index 33b552ffbe57..4642d6a4d356 100644 +--- a/arch/powerpc/platforms/pseries/iommu.c ++++ b/arch/powerpc/platforms/pseries/iommu.c +@@ -721,13 +721,13 @@ static int __init disable_ddw_setup(char *str) + + early_param("disable_ddw", disable_ddw_setup); + +-static void remove_ddw(struct device_node *np) ++static void remove_ddw(struct device_node *np, bool remove_prop) + { + struct dynamic_dma_window_prop *dwp; + struct property *win64; + const u32 *ddw_avail; + u64 liobn; +- int len, ret; ++ int len, ret = 0; + + ddw_avail = of_get_property(np, "ibm,ddw-applicable", &len); + win64 = of_find_property(np, DIRECT64_PROPNAME, NULL); +@@ -761,7 +761,8 @@ static void remove_ddw(struct device_node *np) + np->full_name, ret, ddw_avail[2], liobn); + + delprop: +- ret = of_remove_property(np, win64); ++ if (remove_prop) ++ ret = of_remove_property(np, win64); + if (ret) + pr_warning("%s: failed to remove direct window property: %d\n", + np->full_name, ret); +@@ -805,7 +806,7 @@ static int find_existing_ddw_windows(void) + window = kzalloc(sizeof(*window), GFP_KERNEL); + if (!window || len < sizeof(struct dynamic_dma_window_prop)) { + kfree(window); +- remove_ddw(pdn); ++ remove_ddw(pdn, true); + continue; + } + +@@ -1045,7 +1046,7 @@ out_free_window: + kfree(window); + + out_clear_window: +- remove_ddw(pdn); ++ remove_ddw(pdn, true); + + out_free_prop: + kfree(win64->name); +@@ -1255,7 +1256,14 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti + + switch (action) { + case OF_RECONFIG_DETACH_NODE: +- remove_ddw(np); ++ /* ++ * Removing the property will invoke the reconfig ++ * notifier again, which causes dead-lock on the ++ * read-write semaphore of the notifier chain. So ++ * we have to remove the property when releasing ++ * the device node. ++ */ ++ remove_ddw(np, false); + if (pci && pci->iommu_table) + iommu_free_table(pci->iommu_table, np->full_name); + +diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c +index b02af9ef3ff6..ccf6f162f69c 100644 +--- a/arch/powerpc/platforms/pseries/lpar.c ++++ b/arch/powerpc/platforms/pseries/lpar.c +@@ -430,16 +430,17 @@ static void __pSeries_lpar_hugepage_invalidate(unsigned long *slot, + spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); + } + +-static void pSeries_lpar_hugepage_invalidate(struct mm_struct *mm, +- unsigned char *hpte_slot_array, +- unsigned long addr, int psize) ++static void pSeries_lpar_hugepage_invalidate(unsigned long vsid, ++ unsigned long addr, ++ unsigned char *hpte_slot_array, ++ int psize, int ssize) + { +- int ssize = 0, i, index = 0; ++ int i, index = 0; + unsigned long s_addr = addr; + unsigned int max_hpte_count, valid; + unsigned long vpn_array[PPC64_HUGE_HPTE_BATCH]; + unsigned long slot_array[PPC64_HUGE_HPTE_BATCH]; +- unsigned long shift, hidx, vpn = 0, vsid, hash, slot; ++ unsigned long shift, hidx, vpn = 0, hash, slot; + + shift = mmu_psize_defs[psize].shift; + max_hpte_count = 1U << (PMD_SHIFT - shift); +@@ -452,15 +453,6 @@ static void pSeries_lpar_hugepage_invalidate(struct mm_struct *mm, + + /* get the vpn */ + addr = s_addr + (i * (1ul << shift)); +- if (!is_kernel_addr(addr)) { +- ssize = user_segment_size(addr); +- vsid = get_vsid(mm->context.id, addr, ssize); +- WARN_ON(vsid == 0); +- } else { +- vsid = get_kernel_vsid(addr, mmu_kernel_ssize); +- ssize = mmu_kernel_ssize; +- } +- + vpn = hpt_vpn(addr, vsid, ssize); + hash = hpt_hash(vpn, shift, ssize); + if (hidx & _PTEIDX_SECONDARY) +diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig +index bb74b21f007a..a0a3bed6e4dc 100644 +--- a/arch/s390/Kconfig ++++ b/arch/s390/Kconfig +@@ -93,6 +93,7 @@ config S390 + select ARCH_INLINE_WRITE_UNLOCK_IRQ + select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE + select ARCH_SAVE_PAGE_KEYS if HIBERNATION ++ select ARCH_SUPPORTS_ATOMIC_RMW + select ARCH_USE_CMPXCHG_LOCKREF + select ARCH_WANT_IPC_PARSE_VERSION + select BUILDTIME_EXTABLE_SORT +diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c +index edff4e653d9a..c66bca17e736 100644 +--- a/drivers/acpi/acpica/utcopy.c ++++ b/drivers/acpi/acpica/utcopy.c +@@ -1001,5 +1001,11 @@ acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc, + status = acpi_ut_copy_simple_object(source_desc, *dest_desc); + } + ++ /* Delete the allocated object if copy failed */ ++ ++ if (ACPI_FAILURE(status)) { ++ acpi_ut_remove_reference(*dest_desc); ++ } ++ + return_ACPI_STATUS(status); + } +diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c +index 3dca36d4ad26..17f9ec501972 100644 +--- a/drivers/acpi/processor_idle.c ++++ b/drivers/acpi/processor_idle.c +@@ -1071,9 +1071,9 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) + + if (pr->id == 0 && cpuidle_get_driver() == &acpi_idle_driver) { + +- cpuidle_pause_and_lock(); + /* Protect against cpu-hotplug */ + get_online_cpus(); ++ cpuidle_pause_and_lock(); + + /* Disable all cpuidle devices */ + for_each_online_cpu(cpu) { +@@ -1100,8 +1100,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) + cpuidle_enable_device(dev); + } + } +- put_online_cpus(); + cpuidle_resume_and_unlock(); ++ put_online_cpus(); + } + + return 0; +diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c +index 57b053f424d1..92d5184e3654 100644 +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -329,7 +329,8 @@ static int acpi_scan_hot_remove(struct acpi_device *device) + unsigned long long sta; + acpi_status status; + +- if (device->handler->hotplug.demand_offline && !acpi_force_hot_remove) { ++ if (device->handler && device->handler->hotplug.demand_offline ++ && !acpi_force_hot_remove) { + if (!acpi_scan_is_offline(device, true)) + return -EBUSY; + } else { +@@ -660,8 +661,14 @@ static ssize_t + acpi_device_sun_show(struct device *dev, struct device_attribute *attr, + char *buf) { + struct acpi_device *acpi_dev = to_acpi_device(dev); ++ acpi_status status; ++ unsigned long long sun; ++ ++ status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun); ++ if (ACPI_FAILURE(status)) ++ return -ENODEV; + +- return sprintf(buf, "%lu\n", acpi_dev->pnp.sun); ++ return sprintf(buf, "%llu\n", sun); + } + static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL); + +@@ -683,7 +690,6 @@ static int acpi_device_setup_files(struct acpi_device *dev) + { + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_status status; +- unsigned long long sun; + int result = 0; + + /* +@@ -724,14 +730,10 @@ static int acpi_device_setup_files(struct acpi_device *dev) + if (dev->pnp.unique_id) + result = device_create_file(&dev->dev, &dev_attr_uid); + +- status = acpi_evaluate_integer(dev->handle, "_SUN", NULL, &sun); +- if (ACPI_SUCCESS(status)) { +- dev->pnp.sun = (unsigned long)sun; ++ if (acpi_has_method(dev->handle, "_SUN")) { + result = device_create_file(&dev->dev, &dev_attr_sun); + if (result) + goto end; +- } else { +- dev->pnp.sun = (unsigned long)-1; + } + + if (acpi_has_method(dev->handle, "_STA")) { +@@ -915,12 +917,17 @@ static void acpi_device_notify(acpi_handle handle, u32 event, void *data) + device->driver->ops.notify(device, event); + } + +-static acpi_status acpi_device_notify_fixed(void *data) ++static void acpi_device_notify_fixed(void *data) + { + struct acpi_device *device = data; + + /* Fixed hardware devices have no handles */ + acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device); ++} ++ ++static acpi_status acpi_device_fixed_event(void *data) ++{ ++ acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data); + return AE_OK; + } + +@@ -931,12 +938,12 @@ static int acpi_device_install_notify_handler(struct acpi_device *device) + if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) + status = + acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, +- acpi_device_notify_fixed, ++ acpi_device_fixed_event, + device); + else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON) + status = + acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, +- acpi_device_notify_fixed, ++ acpi_device_fixed_event, + device); + else + status = acpi_install_notify_handler(device->handle, +@@ -953,10 +960,10 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device) + { + if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) + acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, +- acpi_device_notify_fixed); ++ acpi_device_fixed_event); + else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON) + acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, +- acpi_device_notify_fixed); ++ acpi_device_fixed_event); + else + acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, + acpi_device_notify); +diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h +index 7399303d7d99..9e81a3d01d2b 100644 +--- a/drivers/bluetooth/btmrvl_drv.h ++++ b/drivers/bluetooth/btmrvl_drv.h +@@ -66,6 +66,7 @@ struct btmrvl_adapter { + u8 hs_state; + u8 wakeup_tries; + wait_queue_head_t cmd_wait_q; ++ wait_queue_head_t event_hs_wait_q; + u8 cmd_complete; + bool is_suspended; + }; +diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c +index 1e0320af00c6..49d20989b45a 100644 +--- a/drivers/bluetooth/btmrvl_main.c ++++ b/drivers/bluetooth/btmrvl_main.c +@@ -112,6 +112,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) + adapter->hs_state = HS_ACTIVATED; + if (adapter->psmode) + adapter->ps_state = PS_SLEEP; ++ wake_up_interruptible(&adapter->event_hs_wait_q); + BT_DBG("HS ACTIVATED!"); + } else { + BT_DBG("HS Enable failed"); +@@ -251,11 +252,31 @@ EXPORT_SYMBOL_GPL(btmrvl_enable_ps); + + int btmrvl_enable_hs(struct btmrvl_private *priv) + { ++ struct btmrvl_adapter *adapter = priv->adapter; + int ret; + + ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0); +- if (ret) ++ if (ret) { + BT_ERR("Host sleep enable command failed\n"); ++ return ret; ++ } ++ ++ ret = wait_event_interruptible_timeout(adapter->event_hs_wait_q, ++ adapter->hs_state, ++ msecs_to_jiffies(WAIT_UNTIL_HS_STATE_CHANGED)); ++ if (ret < 0) { ++ BT_ERR("event_hs_wait_q terminated (%d): %d,%d,%d", ++ ret, adapter->hs_state, adapter->ps_state, ++ adapter->wakeup_tries); ++ } else if (!ret) { ++ BT_ERR("hs_enable timeout: %d,%d,%d", adapter->hs_state, ++ adapter->ps_state, adapter->wakeup_tries); ++ ret = -ETIMEDOUT; ++ } else { ++ BT_DBG("host sleep enabled: %d,%d,%d", adapter->hs_state, ++ adapter->ps_state, adapter->wakeup_tries); ++ ret = 0; ++ } + + return ret; + } +@@ -341,6 +362,7 @@ static void btmrvl_init_adapter(struct btmrvl_private *priv) + priv->adapter->ps_state = PS_AWAKE; + + init_waitqueue_head(&priv->adapter->cmd_wait_q); ++ init_waitqueue_head(&priv->adapter->event_hs_wait_q); + } + + static void btmrvl_free_adapter(struct btmrvl_private *priv) +@@ -648,6 +670,7 @@ int btmrvl_remove_card(struct btmrvl_private *priv) + hdev = priv->btmrvl_dev.hcidev; + + wake_up_interruptible(&priv->adapter->cmd_wait_q); ++ wake_up_interruptible(&priv->adapter->event_hs_wait_q); + + kthread_stop(priv->main_thread.task); + +diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c +index 62e10fd1e1cb..6af17002a115 100644 +--- a/drivers/char/tpm/tpm-interface.c ++++ b/drivers/char/tpm/tpm-interface.c +@@ -491,11 +491,10 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type) + int tpm_get_timeouts(struct tpm_chip *chip) + { + struct tpm_cmd_t tpm_cmd; +- struct timeout_t *timeout_cap; ++ unsigned long new_timeout[4]; ++ unsigned long old_timeout[4]; + struct duration_t *duration_cap; + ssize_t rc; +- u32 timeout; +- unsigned int scale = 1; + + tpm_cmd.header.in = tpm_getcap_header; + tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; +@@ -529,25 +528,46 @@ int tpm_get_timeouts(struct tpm_chip *chip) + != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) + return -EINVAL; + +- timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; +- /* Don't overwrite default if value is 0 */ +- timeout = be32_to_cpu(timeout_cap->a); +- if (timeout && timeout < 1000) { +- /* timeouts in msec rather usec */ +- scale = 1000; +- chip->vendor.timeout_adjusted = true; ++ old_timeout[0] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.a); ++ old_timeout[1] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.b); ++ old_timeout[2] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.c); ++ old_timeout[3] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.d); ++ memcpy(new_timeout, old_timeout, sizeof(new_timeout)); ++ ++ /* ++ * Provide ability for vendor overrides of timeout values in case ++ * of misreporting. ++ */ ++ if (chip->ops->update_timeouts != NULL) ++ chip->vendor.timeout_adjusted = ++ chip->ops->update_timeouts(chip, new_timeout); ++ ++ if (!chip->vendor.timeout_adjusted) { ++ /* Don't overwrite default if value is 0 */ ++ if (new_timeout[0] != 0 && new_timeout[0] < 1000) { ++ int i; ++ ++ /* timeouts in msec rather usec */ ++ for (i = 0; i != ARRAY_SIZE(new_timeout); i++) ++ new_timeout[i] *= 1000; ++ chip->vendor.timeout_adjusted = true; ++ } ++ } ++ ++ /* Report adjusted timeouts */ ++ if (chip->vendor.timeout_adjusted) { ++ dev_info(chip->dev, ++ HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n", ++ old_timeout[0], new_timeout[0], ++ old_timeout[1], new_timeout[1], ++ old_timeout[2], new_timeout[2], ++ old_timeout[3], new_timeout[3]); + } +- if (timeout) +- chip->vendor.timeout_a = usecs_to_jiffies(timeout * scale); +- timeout = be32_to_cpu(timeout_cap->b); +- if (timeout) +- chip->vendor.timeout_b = usecs_to_jiffies(timeout * scale); +- timeout = be32_to_cpu(timeout_cap->c); +- if (timeout) +- chip->vendor.timeout_c = usecs_to_jiffies(timeout * scale); +- timeout = be32_to_cpu(timeout_cap->d); +- if (timeout) +- chip->vendor.timeout_d = usecs_to_jiffies(timeout * scale); ++ ++ chip->vendor.timeout_a = usecs_to_jiffies(new_timeout[0]); ++ chip->vendor.timeout_b = usecs_to_jiffies(new_timeout[1]); ++ chip->vendor.timeout_c = usecs_to_jiffies(new_timeout[2]); ++ chip->vendor.timeout_d = usecs_to_jiffies(new_timeout[3]); + + duration: + tpm_cmd.header.in = tpm_getcap_header; +@@ -991,13 +1011,13 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) + int err, total = 0, retries = 5; + u8 *dest = out; + ++ if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) ++ return -EINVAL; ++ + chip = tpm_chip_find_get(chip_num); + if (chip == NULL) + return -ENODEV; + +- if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) +- return -EINVAL; +- + do { + tpm_cmd.header.in = tpm_getrandom_header; + tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); +@@ -1016,6 +1036,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) + num_bytes -= recd; + } while (retries-- && total < max); + ++ tpm_chip_put(chip); + return total ? total : -EIO; + } + EXPORT_SYMBOL_GPL(tpm_get_random); +@@ -1095,7 +1116,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, + goto del_misc; + + if (tpm_add_ppi(&dev->kobj)) +- goto del_misc; ++ goto del_sysfs; + + chip->bios_dir = tpm_bios_log_setup(chip->devname); + +@@ -1106,6 +1127,8 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, + + return chip; + ++del_sysfs: ++ tpm_sysfs_del_device(chip); + del_misc: + tpm_dev_del_device(chip); + put_device: +diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c +index a9ed2270c25d..2c46734b266d 100644 +--- a/drivers/char/tpm/tpm_tis.c ++++ b/drivers/char/tpm/tpm_tis.c +@@ -373,6 +373,36 @@ out_err: + return rc; + } + ++struct tis_vendor_timeout_override { ++ u32 did_vid; ++ unsigned long timeout_us[4]; ++}; ++ ++static const struct tis_vendor_timeout_override vendor_timeout_overrides[] = { ++ /* Atmel 3204 */ ++ { 0x32041114, { (TIS_SHORT_TIMEOUT*1000), (TIS_LONG_TIMEOUT*1000), ++ (TIS_SHORT_TIMEOUT*1000), (TIS_SHORT_TIMEOUT*1000) } }, ++}; ++ ++static bool tpm_tis_update_timeouts(struct tpm_chip *chip, ++ unsigned long *timeout_cap) ++{ ++ int i; ++ u32 did_vid; ++ ++ did_vid = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); ++ ++ for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) { ++ if (vendor_timeout_overrides[i].did_vid != did_vid) ++ continue; ++ memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us, ++ sizeof(vendor_timeout_overrides[i].timeout_us)); ++ return true; ++ } ++ ++ return false; ++} ++ + /* + * Early probing for iTPM with STS_DATA_EXPECT flaw. + * Try sending command without itpm flag set and if that +@@ -437,6 +467,7 @@ static const struct tpm_class_ops tpm_tis = { + .recv = tpm_tis_recv, + .send = tpm_tis_send, + .cancel = tpm_tis_ready, ++ .update_timeouts = tpm_tis_update_timeouts, + .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, + .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, + .req_canceled = tpm_tis_req_canceled, +diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c +index b22659cccca4..e6125522860a 100644 +--- a/drivers/firmware/efi/vars.c ++++ b/drivers/firmware/efi/vars.c +@@ -481,7 +481,7 @@ EXPORT_SYMBOL_GPL(efivar_entry_remove); + */ + static void efivar_entry_list_del_unlock(struct efivar_entry *entry) + { +- WARN_ON(!spin_is_locked(&__efivars->lock)); ++ lockdep_assert_held(&__efivars->lock); + + list_del(&entry->list); + spin_unlock_irq(&__efivars->lock); +@@ -507,7 +507,7 @@ int __efivar_entry_delete(struct efivar_entry *entry) + const struct efivar_operations *ops = __efivars->ops; + efi_status_t status; + +- WARN_ON(!spin_is_locked(&__efivars->lock)); ++ lockdep_assert_held(&__efivars->lock); + + status = ops->set_variable(entry->var.VariableName, + &entry->var.VendorGuid, +@@ -667,7 +667,7 @@ struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid, + int strsize1, strsize2; + bool found = false; + +- WARN_ON(!spin_is_locked(&__efivars->lock)); ++ lockdep_assert_held(&__efivars->lock); + + list_for_each_entry_safe(entry, n, head, list) { + strsize1 = ucs2_strsize(name, 1024); +@@ -739,7 +739,7 @@ int __efivar_entry_get(struct efivar_entry *entry, u32 *attributes, + const struct efivar_operations *ops = __efivars->ops; + efi_status_t status; + +- WARN_ON(!spin_is_locked(&__efivars->lock)); ++ lockdep_assert_held(&__efivars->lock); + + status = ops->get_variable(entry->var.VariableName, + &entry->var.VendorGuid, +diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h +index 23ca7a517246..74ed08a750f4 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_drm.h ++++ b/drivers/gpu/drm/nouveau/nouveau_drm.h +@@ -10,7 +10,7 @@ + + #define DRIVER_MAJOR 1 + #define DRIVER_MINOR 1 +-#define DRIVER_PATCHLEVEL 1 ++#define DRIVER_PATCHLEVEL 2 + + /* + * 1.1.1: +@@ -21,6 +21,8 @@ + * to control registers on the MPs to enable performance counters, + * and to control the warp error enable mask (OpenGL requires out of + * bounds access to local memory to be silently ignored / return 0). ++ * 1.1.2: ++ * - fixes multiple bugs in flip completion events and timestamping + */ + + #include +diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c +index bc9e56eb4e9c..7b3537c55c77 100644 +--- a/drivers/gpu/drm/radeon/cik.c ++++ b/drivers/gpu/drm/radeon/cik.c +@@ -7779,6 +7779,7 @@ restart_ih: + static int cik_startup(struct radeon_device *rdev) + { + struct radeon_ring *ring; ++ u32 nop; + int r; + + /* enable pcie gen2/3 link */ +@@ -7896,9 +7897,15 @@ static int cik_startup(struct radeon_device *rdev) + } + cik_irq_set(rdev); + ++ if (rdev->family == CHIP_HAWAII) { ++ nop = RADEON_CP_PACKET2; ++ } else { ++ nop = PACKET3(PACKET3_NOP, 0x3FFF); ++ } ++ + ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, +- PACKET3(PACKET3_NOP, 0x3FFF)); ++ nop); + if (r) + return r; + +@@ -7906,7 +7913,7 @@ static int cik_startup(struct radeon_device *rdev) + /* type-2 packets are deprecated on MEC, use type-3 instead */ + ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET, +- PACKET3(PACKET3_NOP, 0x3FFF)); ++ nop); + if (r) + return r; + ring->me = 1; /* first MEC */ +@@ -7917,7 +7924,7 @@ static int cik_startup(struct radeon_device *rdev) + /* type-2 packets are deprecated on MEC, use type-3 instead */ + ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET, +- PACKET3(PACKET3_NOP, 0x3FFF)); ++ nop); + if (r) + return r; + /* dGPU only have 1 MEC */ +diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c +index 3d2e489ab732..ff9163dc1596 100644 +--- a/drivers/infiniband/core/iwcm.c ++++ b/drivers/infiniband/core/iwcm.c +@@ -46,6 +46,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -65,6 +66,20 @@ struct iwcm_work { + struct list_head free_list; + }; + ++static unsigned int default_backlog = 256; ++ ++static struct ctl_table_header *iwcm_ctl_table_hdr; ++static struct ctl_table iwcm_ctl_table[] = { ++ { ++ .procname = "default_backlog", ++ .data = &default_backlog, ++ .maxlen = sizeof(default_backlog), ++ .mode = 0644, ++ .proc_handler = proc_dointvec, ++ }, ++ { } ++}; ++ + /* + * The following services provide a mechanism for pre-allocating iwcm_work + * elements. The design pre-allocates them based on the cm_id type: +@@ -425,6 +440,9 @@ int iw_cm_listen(struct iw_cm_id *cm_id, int backlog) + + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); + ++ if (!backlog) ++ backlog = default_backlog; ++ + ret = alloc_work_entries(cm_id_priv, backlog); + if (ret) + return ret; +@@ -1030,11 +1048,20 @@ static int __init iw_cm_init(void) + if (!iwcm_wq) + return -ENOMEM; + ++ iwcm_ctl_table_hdr = register_net_sysctl(&init_net, "net/iw_cm", ++ iwcm_ctl_table); ++ if (!iwcm_ctl_table_hdr) { ++ pr_err("iw_cm: couldn't register sysctl paths\n"); ++ destroy_workqueue(iwcm_wq); ++ return -ENOMEM; ++ } ++ + return 0; + } + + static void __exit iw_cm_cleanup(void) + { ++ unregister_net_sysctl_table(iwcm_ctl_table_hdr); + destroy_workqueue(iwcm_wq); + } + +diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c +index e96c07ee6756..ca0bc6c67abe 100644 +--- a/drivers/infiniband/ulp/srp/ib_srp.c ++++ b/drivers/infiniband/ulp/srp/ib_srp.c +@@ -120,6 +120,7 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr); + static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event); + + static struct scsi_transport_template *ib_srp_transport_template; ++static struct workqueue_struct *srp_remove_wq; + + static struct ib_client srp_client = { + .name = "srp", +@@ -539,7 +540,7 @@ static bool srp_queue_remove_work(struct srp_target_port *target) + spin_unlock_irq(&target->lock); + + if (changed) +- queue_work(system_long_wq, &target->remove_work); ++ queue_work(srp_remove_wq, &target->remove_work); + + return changed; + } +@@ -2886,9 +2887,10 @@ static void srp_remove_one(struct ib_device *device) + spin_unlock(&host->target_lock); + + /* +- * Wait for target port removal tasks. ++ * Wait for tl_err and target port removal tasks. + */ + flush_workqueue(system_long_wq); ++ flush_workqueue(srp_remove_wq); + + kfree(host); + } +@@ -2940,16 +2942,22 @@ static int __init srp_init_module(void) + indirect_sg_entries = cmd_sg_entries; + } + ++ srp_remove_wq = create_workqueue("srp_remove"); ++ if (IS_ERR(srp_remove_wq)) { ++ ret = PTR_ERR(srp_remove_wq); ++ goto out; ++ } ++ ++ ret = -ENOMEM; + ib_srp_transport_template = + srp_attach_transport(&ib_srp_transport_functions); + if (!ib_srp_transport_template) +- return -ENOMEM; ++ goto destroy_wq; + + ret = class_register(&srp_class); + if (ret) { + pr_err("couldn't register class infiniband_srp\n"); +- srp_release_transport(ib_srp_transport_template); +- return ret; ++ goto release_tr; + } + + ib_sa_register_client(&srp_sa_client); +@@ -2957,13 +2965,22 @@ static int __init srp_init_module(void) + ret = ib_register_client(&srp_client); + if (ret) { + pr_err("couldn't register IB client\n"); +- srp_release_transport(ib_srp_transport_template); +- ib_sa_unregister_client(&srp_sa_client); +- class_unregister(&srp_class); +- return ret; ++ goto unreg_sa; + } + +- return 0; ++out: ++ return ret; ++ ++unreg_sa: ++ ib_sa_unregister_client(&srp_sa_client); ++ class_unregister(&srp_class); ++ ++release_tr: ++ srp_release_transport(ib_srp_transport_template); ++ ++destroy_wq: ++ destroy_workqueue(srp_remove_wq); ++ goto out; + } + + static void __exit srp_cleanup_module(void) +@@ -2972,6 +2989,7 @@ static void __exit srp_cleanup_module(void) + ib_sa_unregister_client(&srp_sa_client); + class_unregister(&srp_class); + srp_release_transport(ib_srp_transport_template); ++ destroy_workqueue(srp_remove_wq); + } + + module_init(srp_init_module); +diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c +index 71776ff5aedc..9cbef59d404a 100644 +--- a/drivers/iommu/amd_iommu.c ++++ b/drivers/iommu/amd_iommu.c +@@ -3227,14 +3227,16 @@ free_domains: + + static void cleanup_domain(struct protection_domain *domain) + { +- struct iommu_dev_data *dev_data, *next; ++ struct iommu_dev_data *entry; + unsigned long flags; + + write_lock_irqsave(&amd_iommu_devtable_lock, flags); + +- list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) { +- __detach_device(dev_data); +- atomic_set(&dev_data->bind, 0); ++ while (!list_empty(&domain->dev_list)) { ++ entry = list_first_entry(&domain->dev_list, ++ struct iommu_dev_data, list); ++ __detach_device(entry); ++ atomic_set(&entry->bind, 0); + } + + write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 56e24c072b62..d7690f86fdb9 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -1501,12 +1501,12 @@ static void error(struct mddev *mddev, struct md_rdev *rdev) + mddev->degraded++; + set_bit(Faulty, &rdev->flags); + spin_unlock_irqrestore(&conf->device_lock, flags); +- /* +- * if recovery is running, make sure it aborts. +- */ +- set_bit(MD_RECOVERY_INTR, &mddev->recovery); + } else + set_bit(Faulty, &rdev->flags); ++ /* ++ * if recovery is running, make sure it aborts. ++ */ ++ set_bit(MD_RECOVERY_INTR, &mddev->recovery); + set_bit(MD_CHANGE_DEVS, &mddev->flags); + printk(KERN_ALERT + "md/raid1:%s: Disk failure on %s, disabling device.\n" +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index cb882aae9e20..a46124ecafc7 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -1684,13 +1684,12 @@ static void error(struct mddev *mddev, struct md_rdev *rdev) + spin_unlock_irqrestore(&conf->device_lock, flags); + return; + } +- if (test_and_clear_bit(In_sync, &rdev->flags)) { ++ if (test_and_clear_bit(In_sync, &rdev->flags)) + mddev->degraded++; +- /* +- * if recovery is running, make sure it aborts. +- */ +- set_bit(MD_RECOVERY_INTR, &mddev->recovery); +- } ++ /* ++ * If recovery is running, make sure it aborts. ++ */ ++ set_bit(MD_RECOVERY_INTR, &mddev->recovery); + set_bit(Blocked, &rdev->flags); + set_bit(Faulty, &rdev->flags); + set_bit(MD_CHANGE_DEVS, &mddev->flags); +@@ -2954,6 +2953,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, + */ + if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) { + end_reshape(conf); ++ close_sync(conf); + return 0; + } + +@@ -4411,7 +4411,7 @@ read_more: + read_bio->bi_private = r10_bio; + read_bio->bi_end_io = end_sync_read; + read_bio->bi_rw = READ; +- read_bio->bi_flags &= ~(BIO_POOL_MASK - 1); ++ read_bio->bi_flags &= (~0UL << BIO_RESET_BITS); + read_bio->bi_flags |= 1 << BIO_UPTODATE; + read_bio->bi_vcnt = 0; + read_bio->bi_iter.bi_size = 0; +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 16f5c21963db..18cda77b4f79 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -3779,6 +3779,8 @@ static void handle_stripe(struct stripe_head *sh) + set_bit(R5_Wantwrite, &dev->flags); + if (prexor) + continue; ++ if (s.failed > 1) ++ continue; + if (!test_bit(R5_Insync, &dev->flags) || + ((i == sh->pd_idx || i == sh->qd_idx) && + s.failed == 0)) +diff --git a/drivers/media/common/siano/Kconfig b/drivers/media/common/siano/Kconfig +index f953d33ee151..4bfbd5f463d1 100644 +--- a/drivers/media/common/siano/Kconfig ++++ b/drivers/media/common/siano/Kconfig +@@ -22,8 +22,7 @@ config SMS_SIANO_DEBUGFS + bool "Enable debugfs for smsdvb" + depends on SMS_SIANO_MDTV + depends on DEBUG_FS +- depends on SMS_USB_DRV +- depends on CONFIG_SMS_USB_DRV = CONFIG_SMS_SDIO_DRV ++ depends on SMS_USB_DRV = SMS_SDIO_DRV + + ---help--- + Choose Y to enable visualizing a dump of the frontend +diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c +index 36c504b78f2c..008ac87a9031 100644 +--- a/drivers/media/i2c/mt9v032.c ++++ b/drivers/media/i2c/mt9v032.c +@@ -305,8 +305,8 @@ mt9v032_update_hblank(struct mt9v032 *mt9v032) + + if (mt9v032->version->version == MT9V034_CHIP_ID_REV1) + min_hblank += (mt9v032->hratio - 1) * 10; +- min_hblank = max_t(unsigned int, (int)mt9v032->model->data->min_row_time - crop->width, +- (int)min_hblank); ++ min_hblank = max_t(int, mt9v032->model->data->min_row_time - crop->width, ++ min_hblank); + hblank = max_t(unsigned int, mt9v032->hblank, min_hblank); + + return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, hblank); +diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c +index 703560fa5e73..88c1606fd555 100644 +--- a/drivers/media/media-device.c ++++ b/drivers/media/media-device.c +@@ -106,8 +106,6 @@ static long media_device_enum_entities(struct media_device *mdev, + if (ent->name) { + strncpy(u_ent.name, ent->name, sizeof(u_ent.name)); + u_ent.name[sizeof(u_ent.name) - 1] = '\0'; +- } else { +- memset(u_ent.name, 0, sizeof(u_ent.name)); + } + u_ent.type = ent->type; + u_ent.revision = ent->revision; +diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c +index b4687a834f85..7245cca89257 100644 +--- a/drivers/media/platform/vsp1/vsp1_video.c ++++ b/drivers/media/platform/vsp1/vsp1_video.c +@@ -635,8 +635,6 @@ static int vsp1_video_buffer_prepare(struct vb2_buffer *vb) + if (vb->num_planes < format->num_planes) + return -EINVAL; + +- buf->video = video; +- + for (i = 0; i < vb->num_planes; ++i) { + buf->addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); + buf->length[i] = vb2_plane_size(vb, i); +diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h +index d8612a378345..47b7a8ab5e2f 100644 +--- a/drivers/media/platform/vsp1/vsp1_video.h ++++ b/drivers/media/platform/vsp1/vsp1_video.h +@@ -89,7 +89,6 @@ static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e) + } + + struct vsp1_video_buffer { +- struct vsp1_video *video; + struct vb2_buffer buf; + struct list_head queue; + +diff --git a/drivers/media/tuners/xc4000.c b/drivers/media/tuners/xc4000.c +index 2018befabb5a..e71decbfd0af 100644 +--- a/drivers/media/tuners/xc4000.c ++++ b/drivers/media/tuners/xc4000.c +@@ -93,7 +93,7 @@ struct xc4000_priv { + struct firmware_description *firm; + int firm_size; + u32 if_khz; +- u32 freq_hz; ++ u32 freq_hz, freq_offset; + u32 bandwidth; + u8 video_standard; + u8 rf_mode; +@@ -1157,14 +1157,14 @@ static int xc4000_set_params(struct dvb_frontend *fe) + case SYS_ATSC: + dprintk(1, "%s() VSB modulation\n", __func__); + priv->rf_mode = XC_RF_MODE_AIR; +- priv->freq_hz = c->frequency - 1750000; ++ priv->freq_offset = 1750000; + priv->video_standard = XC4000_DTV6; + type = DTV6; + break; + case SYS_DVBC_ANNEX_B: + dprintk(1, "%s() QAM modulation\n", __func__); + priv->rf_mode = XC_RF_MODE_CABLE; +- priv->freq_hz = c->frequency - 1750000; ++ priv->freq_offset = 1750000; + priv->video_standard = XC4000_DTV6; + type = DTV6; + break; +@@ -1173,23 +1173,23 @@ static int xc4000_set_params(struct dvb_frontend *fe) + dprintk(1, "%s() OFDM\n", __func__); + if (bw == 0) { + if (c->frequency < 400000000) { +- priv->freq_hz = c->frequency - 2250000; ++ priv->freq_offset = 2250000; + } else { +- priv->freq_hz = c->frequency - 2750000; ++ priv->freq_offset = 2750000; + } + priv->video_standard = XC4000_DTV7_8; + type = DTV78; + } else if (bw <= 6000000) { + priv->video_standard = XC4000_DTV6; +- priv->freq_hz = c->frequency - 1750000; ++ priv->freq_offset = 1750000; + type = DTV6; + } else if (bw <= 7000000) { + priv->video_standard = XC4000_DTV7; +- priv->freq_hz = c->frequency - 2250000; ++ priv->freq_offset = 2250000; + type = DTV7; + } else { + priv->video_standard = XC4000_DTV8; +- priv->freq_hz = c->frequency - 2750000; ++ priv->freq_offset = 2750000; + type = DTV8; + } + priv->rf_mode = XC_RF_MODE_AIR; +@@ -1200,6 +1200,8 @@ static int xc4000_set_params(struct dvb_frontend *fe) + goto fail; + } + ++ priv->freq_hz = c->frequency - priv->freq_offset; ++ + dprintk(1, "%s() frequency=%d (compensated)\n", + __func__, priv->freq_hz); + +@@ -1520,7 +1522,7 @@ static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq) + { + struct xc4000_priv *priv = fe->tuner_priv; + +- *freq = priv->freq_hz; ++ *freq = priv->freq_hz + priv->freq_offset; + + if (debug) { + mutex_lock(&priv->lock); +diff --git a/drivers/media/tuners/xc5000.c b/drivers/media/tuners/xc5000.c +index 5cd09a681b6a..b2d9e9cb97f7 100644 +--- a/drivers/media/tuners/xc5000.c ++++ b/drivers/media/tuners/xc5000.c +@@ -55,7 +55,7 @@ struct xc5000_priv { + + u32 if_khz; + u16 xtal_khz; +- u32 freq_hz; ++ u32 freq_hz, freq_offset; + u32 bandwidth; + u8 video_standard; + u8 rf_mode; +@@ -755,13 +755,13 @@ static int xc5000_set_params(struct dvb_frontend *fe) + case SYS_ATSC: + dprintk(1, "%s() VSB modulation\n", __func__); + priv->rf_mode = XC_RF_MODE_AIR; +- priv->freq_hz = freq - 1750000; ++ priv->freq_offset = 1750000; + priv->video_standard = DTV6; + break; + case SYS_DVBC_ANNEX_B: + dprintk(1, "%s() QAM modulation\n", __func__); + priv->rf_mode = XC_RF_MODE_CABLE; +- priv->freq_hz = freq - 1750000; ++ priv->freq_offset = 1750000; + priv->video_standard = DTV6; + break; + case SYS_ISDBT: +@@ -776,15 +776,15 @@ static int xc5000_set_params(struct dvb_frontend *fe) + switch (bw) { + case 6000000: + priv->video_standard = DTV6; +- priv->freq_hz = freq - 1750000; ++ priv->freq_offset = 1750000; + break; + case 7000000: + priv->video_standard = DTV7; +- priv->freq_hz = freq - 2250000; ++ priv->freq_offset = 2250000; + break; + case 8000000: + priv->video_standard = DTV8; +- priv->freq_hz = freq - 2750000; ++ priv->freq_offset = 2750000; + break; + default: + printk(KERN_ERR "xc5000 bandwidth not set!\n"); +@@ -798,15 +798,15 @@ static int xc5000_set_params(struct dvb_frontend *fe) + priv->rf_mode = XC_RF_MODE_CABLE; + if (bw <= 6000000) { + priv->video_standard = DTV6; +- priv->freq_hz = freq - 1750000; ++ priv->freq_offset = 1750000; + b = 6; + } else if (bw <= 7000000) { + priv->video_standard = DTV7; +- priv->freq_hz = freq - 2250000; ++ priv->freq_offset = 2250000; + b = 7; + } else { + priv->video_standard = DTV7_8; +- priv->freq_hz = freq - 2750000; ++ priv->freq_offset = 2750000; + b = 8; + } + dprintk(1, "%s() Bandwidth %dMHz (%d)\n", __func__, +@@ -817,6 +817,8 @@ static int xc5000_set_params(struct dvb_frontend *fe) + return -EINVAL; + } + ++ priv->freq_hz = freq - priv->freq_offset; ++ + dprintk(1, "%s() frequency=%d (compensated to %d)\n", + __func__, freq, priv->freq_hz); + +@@ -1067,7 +1069,7 @@ static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq) + { + struct xc5000_priv *priv = fe->tuner_priv; + dprintk(1, "%s()\n", __func__); +- *freq = priv->freq_hz; ++ *freq = priv->freq_hz + priv->freq_offset; + return 0; + } + +diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c +index f6154546b5c0..7ed75efa1c36 100644 +--- a/drivers/media/usb/au0828/au0828-video.c ++++ b/drivers/media/usb/au0828/au0828-video.c +@@ -787,11 +787,27 @@ static int au0828_i2s_init(struct au0828_dev *dev) + + /* + * Auvitek au0828 analog stream enable +- * Please set interface0 to AS5 before enable the stream + */ + static int au0828_analog_stream_enable(struct au0828_dev *d) + { ++ struct usb_interface *iface; ++ int ret; ++ + dprintk(1, "au0828_analog_stream_enable called\n"); ++ ++ iface = usb_ifnum_to_if(d->usbdev, 0); ++ if (iface && iface->cur_altsetting->desc.bAlternateSetting != 5) { ++ dprintk(1, "Changing intf#0 to alt 5\n"); ++ /* set au0828 interface0 to AS5 here again */ ++ ret = usb_set_interface(d->usbdev, 0, 5); ++ if (ret < 0) { ++ printk(KERN_INFO "Au0828 can't set alt setting to 5!\n"); ++ return -EBUSY; ++ } ++ } ++ ++ /* FIXME: size should be calculated using d->width, d->height */ ++ + au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00); + au0828_writereg(d, 0x106, 0x00); + /* set x position */ +@@ -1002,15 +1018,6 @@ static int au0828_v4l2_open(struct file *filp) + return -ERESTARTSYS; + } + if (dev->users == 0) { +- /* set au0828 interface0 to AS5 here again */ +- ret = usb_set_interface(dev->usbdev, 0, 5); +- if (ret < 0) { +- mutex_unlock(&dev->lock); +- printk(KERN_INFO "Au0828 can't set alternate to 5!\n"); +- kfree(fh); +- return -EBUSY; +- } +- + au0828_analog_stream_enable(dev); + au0828_analog_stream_reset(dev); + +@@ -1252,13 +1259,6 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, + } + } + +- /* set au0828 interface0 to AS5 here again */ +- ret = usb_set_interface(dev->usbdev, 0, 5); +- if (ret < 0) { +- printk(KERN_INFO "Au0828 can't set alt setting to 5!\n"); +- return -EBUSY; +- } +- + au0828_analog_stream_enable(dev); + + return 0; +diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c +index 90b630ccc8bc..0aefe501fd3c 100644 +--- a/drivers/mfd/omap-usb-host.c ++++ b/drivers/mfd/omap-usb-host.c +@@ -445,7 +445,7 @@ static unsigned omap_usbhs_rev1_hostconfig(struct usbhs_hcd_omap *omap, + + for (i = 0; i < omap->nports; i++) { + if (is_ehci_phy_mode(pdata->port_mode[i])) { +- reg &= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; ++ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; + break; + } + } +diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c +index 19d637266fcd..71e4f6ccae2f 100644 +--- a/drivers/mtd/ftl.c ++++ b/drivers/mtd/ftl.c +@@ -1075,7 +1075,6 @@ static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) + return; + } + +- ftl_freepart(partition); + kfree(partition); + } + +diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c +index 6f55d92dc233..64d8e32b6ca0 100644 +--- a/drivers/mtd/nand/omap2.c ++++ b/drivers/mtd/nand/omap2.c +@@ -933,7 +933,7 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat, + u32 val; + + val = readl(info->reg.gpmc_ecc_config); +- if (((val >> ECC_CONFIG_CS_SHIFT) & ~CS_MASK) != info->gpmc_cs) ++ if (((val >> ECC_CONFIG_CS_SHIFT) & CS_MASK) != info->gpmc_cs) + return -EINVAL; + + /* read ecc result */ +diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c +index 79a37f6d3307..e384844a1ae1 100644 +--- a/drivers/power/bq2415x_charger.c ++++ b/drivers/power/bq2415x_charger.c +@@ -840,8 +840,7 @@ static int bq2415x_notifier_call(struct notifier_block *nb, + if (bq->automode < 1) + return NOTIFY_OK; + +- sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode"); +- bq2415x_set_mode(bq, bq->reported_mode); ++ schedule_delayed_work(&bq->work, 0); + + return NOTIFY_OK; + } +@@ -892,6 +891,11 @@ static void bq2415x_timer_work(struct work_struct *work) + int error; + int boost; + ++ if (bq->automode > 0 && (bq->reported_mode != bq->mode)) { ++ sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode"); ++ bq2415x_set_mode(bq, bq->reported_mode); ++ } ++ + if (!bq->autotimer) + return; + +diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c +index f0ea4fdfde87..8b963a757883 100644 +--- a/drivers/regulator/arizona-ldo1.c ++++ b/drivers/regulator/arizona-ldo1.c +@@ -141,8 +141,6 @@ static struct regulator_ops arizona_ldo1_ops = { + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, +- .get_bypass = regulator_get_bypass_regmap, +- .set_bypass = regulator_set_bypass_regmap, + }; + + static const struct regulator_desc arizona_ldo1 = { +diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h +index 2e28392c2fb6..a38aafa030b3 100644 +--- a/drivers/scsi/bfa/bfa_ioc.h ++++ b/drivers/scsi/bfa/bfa_ioc.h +@@ -72,7 +72,7 @@ struct bfa_sge_s { + } while (0) + + #define bfa_swap_words(_x) ( \ +- ((_x) << 32) | ((_x) >> 32)) ++ ((u64)(_x) << 32) | ((u64)(_x) >> 32)) + + #ifdef __BIG_ENDIAN + #define bfa_sge_to_be(_x) +diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c +index f969aca0b54e..49014a143c6a 100644 +--- a/drivers/scsi/scsi_devinfo.c ++++ b/drivers/scsi/scsi_devinfo.c +@@ -222,6 +222,7 @@ static struct { + {"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, ++ {"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC}, + {"Promise", "", NULL, BLIST_SPARSELUN}, + {"QUANTUM", "XP34301", "1071", BLIST_NOTQ}, + {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN}, +diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c +index 4109530e92a0..054ec2c412a4 100644 +--- a/drivers/scsi/scsi_scan.c ++++ b/drivers/scsi/scsi_scan.c +@@ -922,6 +922,12 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, + if (*bflags & BLIST_USE_10_BYTE_MS) + sdev->use_10_for_ms = 1; + ++ /* some devices don't like REPORT SUPPORTED OPERATION CODES ++ * and will simply timeout causing sd_mod init to take a very ++ * very long time */ ++ if (*bflags & BLIST_NO_RSOC) ++ sdev->no_report_opcodes = 1; ++ + /* set the device running here so that slave configure + * may do I/O */ + ret = scsi_device_set_state(sdev, SDEV_RUNNING); +@@ -950,7 +956,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, + + sdev->eh_timeout = SCSI_DEFAULT_EH_TIMEOUT; + +- if (*bflags & BLIST_SKIP_VPD_PAGES) ++ if (*bflags & BLIST_TRY_VPD_PAGES) ++ sdev->try_vpd_pages = 1; ++ else if (*bflags & BLIST_SKIP_VPD_PAGES) + sdev->skip_vpd_pages = 1; + + transport_configure_device(&sdev->sdev_gendev); +@@ -1236,6 +1244,12 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget, + max_dev_lun = min(8U, max_dev_lun); + + /* ++ * Stop scanning at 255 unless BLIST_SCSI3LUN ++ */ ++ if (!(bflags & BLIST_SCSI3LUN)) ++ max_dev_lun = min(256U, max_dev_lun); ++ ++ /* + * We have already scanned LUN 0, so start at LUN 1. Keep scanning + * until we reach the max, or no LUN is found and we are not + * sparse_lun. +diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c +index d47ffc8d3e43..e3e794ee7ddd 100644 +--- a/drivers/scsi/scsi_transport_srp.c ++++ b/drivers/scsi/scsi_transport_srp.c +@@ -473,7 +473,8 @@ static void __srp_start_tl_fail_timers(struct srp_rport *rport) + if (delay > 0) + queue_delayed_work(system_long_wq, &rport->reconnect_work, + 1UL * delay * HZ); +- if (srp_rport_set_state(rport, SRP_RPORT_BLOCKED) == 0) { ++ if ((fast_io_fail_tmo >= 0 || dev_loss_tmo >= 0) && ++ srp_rport_set_state(rport, SRP_RPORT_BLOCKED) == 0) { + pr_debug("%s new state: %d\n", dev_name(&shost->shost_gendev), + rport->state); + scsi_target_block(&shost->shost_gendev); +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index 36d1a23f14be..e8abb731c7ec 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -2686,6 +2686,11 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) + + static int sd_try_extended_inquiry(struct scsi_device *sdp) + { ++ /* Attempt VPD inquiry if the device blacklist explicitly calls ++ * for it. ++ */ ++ if (sdp->try_vpd_pages) ++ return 1; + /* + * Although VPD inquiries can go to SCSI-2 type devices, + * some USB ones crash on receiving them, and the pages +diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c +index 9969fa1ef7c4..ed0f899e8aa5 100644 +--- a/drivers/scsi/storvsc_drv.c ++++ b/drivers/scsi/storvsc_drv.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -330,17 +331,17 @@ static int storvsc_timeout = 180; + + static void storvsc_on_channel_callback(void *context); + +-/* +- * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In +- * reality, the path/target is not used (ie always set to 0) so our +- * scsi host adapter essentially has 1 bus with 1 target that contains +- * up to 256 luns. +- */ +-#define STORVSC_MAX_LUNS_PER_TARGET 64 +-#define STORVSC_MAX_TARGETS 1 +-#define STORVSC_MAX_CHANNELS 1 ++#define STORVSC_MAX_LUNS_PER_TARGET 255 ++#define STORVSC_MAX_TARGETS 2 ++#define STORVSC_MAX_CHANNELS 8 + ++#define STORVSC_FC_MAX_LUNS_PER_TARGET 255 ++#define STORVSC_FC_MAX_TARGETS 128 ++#define STORVSC_FC_MAX_CHANNELS 8 + ++#define STORVSC_IDE_MAX_LUNS_PER_TARGET 64 ++#define STORVSC_IDE_MAX_TARGETS 1 ++#define STORVSC_IDE_MAX_CHANNELS 1 + + struct storvsc_cmd_request { + struct list_head entry; +@@ -1017,6 +1018,13 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, + case ATA_12: + set_host_byte(scmnd, DID_PASSTHROUGH); + break; ++ /* ++ * On Some Windows hosts TEST_UNIT_READY command can return ++ * SRB_STATUS_ERROR, let the upper level code deal with it ++ * based on the sense information. ++ */ ++ case TEST_UNIT_READY: ++ break; + default: + set_host_byte(scmnd, DID_TARGET_FAILURE); + } +@@ -1518,6 +1526,16 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) + return SUCCESS; + } + ++/* ++ * The host guarantees to respond to each command, although I/O latencies might ++ * be unbounded on Azure. Reset the timer unconditionally to give the host a ++ * chance to perform EH. ++ */ ++static enum blk_eh_timer_return storvsc_eh_timed_out(struct scsi_cmnd *scmnd) ++{ ++ return BLK_EH_RESET_TIMER; ++} ++ + static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd) + { + bool allowed = true; +@@ -1553,9 +1571,19 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) + struct vmscsi_request *vm_srb; + struct stor_mem_pools *memp = scmnd->device->hostdata; + +- if (!storvsc_scsi_cmd_ok(scmnd)) { +- scmnd->scsi_done(scmnd); +- return 0; ++ if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) { ++ /* ++ * On legacy hosts filter unimplemented commands. ++ * Future hosts are expected to correctly handle ++ * unsupported commands. Furthermore, it is ++ * possible that some of the currently ++ * unsupported commands maybe supported in ++ * future versions of the host. ++ */ ++ if (!storvsc_scsi_cmd_ok(scmnd)) { ++ scmnd->scsi_done(scmnd); ++ return 0; ++ } + } + + request_size = sizeof(struct storvsc_cmd_request); +@@ -1580,26 +1608,24 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) + vm_srb = &cmd_request->vstor_packet.vm_srb; + vm_srb->win8_extension.time_out_value = 60; + ++ vm_srb->win8_extension.srb_flags |= ++ (SRB_FLAGS_QUEUE_ACTION_ENABLE | ++ SRB_FLAGS_DISABLE_SYNCH_TRANSFER); + + /* Build the SRB */ + switch (scmnd->sc_data_direction) { + case DMA_TO_DEVICE: + vm_srb->data_in = WRITE_TYPE; + vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_OUT; +- vm_srb->win8_extension.srb_flags |= +- (SRB_FLAGS_QUEUE_ACTION_ENABLE | +- SRB_FLAGS_DISABLE_SYNCH_TRANSFER); + break; + case DMA_FROM_DEVICE: + vm_srb->data_in = READ_TYPE; + vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_IN; +- vm_srb->win8_extension.srb_flags |= +- (SRB_FLAGS_QUEUE_ACTION_ENABLE | +- SRB_FLAGS_DISABLE_SYNCH_TRANSFER); + break; + default: + vm_srb->data_in = UNKNOWN_TYPE; +- vm_srb->win8_extension.srb_flags = 0; ++ vm_srb->win8_extension.srb_flags |= (SRB_FLAGS_DATA_IN | ++ SRB_FLAGS_DATA_OUT); + break; + } + +@@ -1687,11 +1713,11 @@ static struct scsi_host_template scsi_driver = { + .bios_param = storvsc_get_chs, + .queuecommand = storvsc_queuecommand, + .eh_host_reset_handler = storvsc_host_reset_handler, ++ .eh_timed_out = storvsc_eh_timed_out, + .slave_alloc = storvsc_device_alloc, + .slave_destroy = storvsc_device_destroy, + .slave_configure = storvsc_device_configure, +- .cmd_per_lun = 1, +- /* 64 max_queue * 1 target */ ++ .cmd_per_lun = 255, + .can_queue = STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS, + .this_id = -1, + /* no use setting to 0 since ll_blk_rw reset it to 1 */ +@@ -1743,19 +1769,25 @@ static int storvsc_probe(struct hv_device *device, + * set state to properly communicate with the host. + */ + +- if (vmbus_proto_version == VERSION_WIN8) { +- sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; +- vmscsi_size_delta = 0; +- vmstor_current_major = VMSTOR_WIN8_MAJOR; +- vmstor_current_minor = VMSTOR_WIN8_MINOR; +- } else { ++ switch (vmbus_proto_version) { ++ case VERSION_WS2008: ++ case VERSION_WIN7: + sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; + vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); + vmstor_current_major = VMSTOR_WIN7_MAJOR; + vmstor_current_minor = VMSTOR_WIN7_MINOR; ++ break; ++ default: ++ sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; ++ vmscsi_size_delta = 0; ++ vmstor_current_major = VMSTOR_WIN8_MAJOR; ++ vmstor_current_minor = VMSTOR_WIN8_MINOR; ++ break; + } + +- ++ if (dev_id->driver_data == SFC_GUID) ++ scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS * ++ STORVSC_FC_MAX_TARGETS); + host = scsi_host_alloc(&scsi_driver, + sizeof(struct hv_host_device)); + if (!host) +@@ -1789,12 +1821,25 @@ static int storvsc_probe(struct hv_device *device, + host_dev->path = stor_device->path_id; + host_dev->target = stor_device->target_id; + +- /* max # of devices per target */ +- host->max_lun = STORVSC_MAX_LUNS_PER_TARGET; +- /* max # of targets per channel */ +- host->max_id = STORVSC_MAX_TARGETS; +- /* max # of channels */ +- host->max_channel = STORVSC_MAX_CHANNELS - 1; ++ switch (dev_id->driver_data) { ++ case SFC_GUID: ++ host->max_lun = STORVSC_FC_MAX_LUNS_PER_TARGET; ++ host->max_id = STORVSC_FC_MAX_TARGETS; ++ host->max_channel = STORVSC_FC_MAX_CHANNELS - 1; ++ break; ++ ++ case SCSI_GUID: ++ host->max_lun = STORVSC_MAX_LUNS_PER_TARGET; ++ host->max_id = STORVSC_MAX_TARGETS; ++ host->max_channel = STORVSC_MAX_CHANNELS - 1; ++ break; ++ ++ default: ++ host->max_lun = STORVSC_IDE_MAX_LUNS_PER_TARGET; ++ host->max_id = STORVSC_IDE_MAX_TARGETS; ++ host->max_channel = STORVSC_IDE_MAX_CHANNELS - 1; ++ break; ++ } + /* max cmd length */ + host->max_cmd_len = STORVSC_MAX_CMD_LEN; + +diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c +index a72127f08e39..a64f1557c156 100644 +--- a/drivers/spi/spi-omap2-mcspi.c ++++ b/drivers/spi/spi-omap2-mcspi.c +@@ -147,6 +147,7 @@ struct omap2_mcspi_cs { + void __iomem *base; + unsigned long phys; + int word_len; ++ u16 mode; + struct list_head node; + /* Context save and restore shadow register */ + u32 chconf0; +@@ -899,6 +900,8 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, + + mcspi_write_chconf0(spi, l); + ++ cs->mode = spi->mode; ++ + dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", + OMAP2_MCSPI_MAX_FREQ >> div, + (spi->mode & SPI_CPHA) ? "trailing" : "leading", +@@ -971,6 +974,7 @@ static int omap2_mcspi_setup(struct spi_device *spi) + return -ENOMEM; + cs->base = mcspi->base + spi->chip_select * 0x14; + cs->phys = mcspi->phys + spi->chip_select * 0x14; ++ cs->mode = 0; + cs->chconf0 = 0; + spi->controller_state = cs; + /* Link this to context save list */ +@@ -1051,6 +1055,16 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) + cs = spi->controller_state; + cd = spi->controller_data; + ++ /* ++ * The slave driver could have changed spi->mode in which case ++ * it will be different from cs->mode (the current hardware setup). ++ * If so, set par_override (even though its not a parity issue) so ++ * omap2_mcspi_setup_transfer will be called to configure the hardware ++ * with the correct mode on the first iteration of the loop below. ++ */ ++ if (spi->mode != cs->mode) ++ par_override = 1; ++ + omap2_mcspi_set_enable(spi, 0); + list_for_each_entry(t, &m->transfers, transfer_list) { + if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { +diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c +index 7f2121fe2622..977b0619bb78 100644 +--- a/drivers/spi/spi-orion.c ++++ b/drivers/spi/spi-orion.c +@@ -404,8 +404,6 @@ static int orion_spi_probe(struct platform_device *pdev) + struct resource *r; + unsigned long tclk_hz; + int status = 0; +- const u32 *iprop; +- int size; + + master = spi_alloc_master(&pdev->dev, sizeof(*spi)); + if (master == NULL) { +@@ -416,10 +414,10 @@ static int orion_spi_probe(struct platform_device *pdev) + if (pdev->id != -1) + master->bus_num = pdev->id; + if (pdev->dev.of_node) { +- iprop = of_get_property(pdev->dev.of_node, "cell-index", +- &size); +- if (iprop && size == sizeof(*iprop)) +- master->bus_num = *iprop; ++ u32 cell_index; ++ if (!of_property_read_u32(pdev->dev.of_node, "cell-index", ++ &cell_index)) ++ master->bus_num = cell_index; + } + + /* we support only mode 0, and no options */ +diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c +index c702fc536a77..ced9ecffa163 100644 +--- a/drivers/spi/spi-pxa2xx.c ++++ b/drivers/spi/spi-pxa2xx.c +@@ -1078,6 +1078,7 @@ static struct acpi_device_id pxa2xx_spi_acpi_match[] = { + { "INT3430", 0 }, + { "INT3431", 0 }, + { "80860F0E", 0 }, ++ { "8086228E", 0 }, + { }, + }; + MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match); +diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c +index 172a8bc27abd..ef7d446e07ee 100644 +--- a/drivers/xen/events/events_fifo.c ++++ b/drivers/xen/events/events_fifo.c +@@ -99,6 +99,25 @@ static unsigned evtchn_fifo_nr_channels(void) + return event_array_pages * EVENT_WORDS_PER_PAGE; + } + ++static int init_control_block(int cpu, ++ struct evtchn_fifo_control_block *control_block) ++{ ++ struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu); ++ struct evtchn_init_control init_control; ++ unsigned int i; ++ ++ /* Reset the control block and the local HEADs. */ ++ clear_page(control_block); ++ for (i = 0; i < EVTCHN_FIFO_MAX_QUEUES; i++) ++ q->head[i] = 0; ++ ++ init_control.control_gfn = virt_to_mfn(control_block); ++ init_control.offset = 0; ++ init_control.vcpu = cpu; ++ ++ return HYPERVISOR_event_channel_op(EVTCHNOP_init_control, &init_control); ++} ++ + static void free_unused_array_pages(void) + { + unsigned i; +@@ -327,7 +346,6 @@ static void evtchn_fifo_resume(void) + + for_each_possible_cpu(cpu) { + void *control_block = per_cpu(cpu_control_block, cpu); +- struct evtchn_init_control init_control; + int ret; + + if (!control_block) +@@ -344,12 +362,7 @@ static void evtchn_fifo_resume(void) + continue; + } + +- init_control.control_gfn = virt_to_mfn(control_block); +- init_control.offset = 0; +- init_control.vcpu = cpu; +- +- ret = HYPERVISOR_event_channel_op(EVTCHNOP_init_control, +- &init_control); ++ ret = init_control_block(cpu, control_block); + if (ret < 0) + BUG(); + } +@@ -377,30 +390,25 @@ static const struct evtchn_ops evtchn_ops_fifo = { + .resume = evtchn_fifo_resume, + }; + +-static int evtchn_fifo_init_control_block(unsigned cpu) ++static int evtchn_fifo_alloc_control_block(unsigned cpu) + { +- struct page *control_block = NULL; +- struct evtchn_init_control init_control; ++ void *control_block = NULL; + int ret = -ENOMEM; + +- control_block = alloc_page(GFP_KERNEL|__GFP_ZERO); ++ control_block = (void *)__get_free_page(GFP_KERNEL); + if (control_block == NULL) + goto error; + +- init_control.control_gfn = virt_to_mfn(page_address(control_block)); +- init_control.offset = 0; +- init_control.vcpu = cpu; +- +- ret = HYPERVISOR_event_channel_op(EVTCHNOP_init_control, &init_control); ++ ret = init_control_block(cpu, control_block); + if (ret < 0) + goto error; + +- per_cpu(cpu_control_block, cpu) = page_address(control_block); ++ per_cpu(cpu_control_block, cpu) = control_block; + + return 0; + + error: +- __free_page(control_block); ++ free_page((unsigned long)control_block); + return ret; + } + +@@ -414,7 +422,7 @@ static int evtchn_fifo_cpu_notification(struct notifier_block *self, + switch (action) { + case CPU_UP_PREPARE: + if (!per_cpu(cpu_control_block, cpu)) +- ret = evtchn_fifo_init_control_block(cpu); ++ ret = evtchn_fifo_alloc_control_block(cpu); + break; + default: + break; +@@ -431,7 +439,7 @@ int __init xen_evtchn_fifo_init(void) + int cpu = get_cpu(); + int ret; + +- ret = evtchn_fifo_init_control_block(cpu); ++ ret = evtchn_fifo_alloc_control_block(cpu); + if (ret < 0) + goto out; + +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index 30f6e9251a4a..f15d4353f30f 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -70,11 +70,6 @@ + #define SERVER_NAME_LENGTH 40 + #define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1) + +-/* used to define string lengths for reversing unicode strings */ +-/* (256+1)*2 = 514 */ +-/* (max path length + 1 for null) * 2 for unicode */ +-#define MAX_NAME 514 +- + /* SMB echo "timeout" -- FIXME: tunable? */ + #define SMB_ECHO_INTERVAL (60 * HZ) + +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index 87c4dd072cde..8175b18df819 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -2844,7 +2844,7 @@ cifs_uncached_read_into_pages(struct TCP_Server_Info *server, + total_read += result; + } + +- return total_read > 0 ? total_read : result; ++ return total_read > 0 && result != -EAGAIN ? total_read : result; + } + + static ssize_t +@@ -3267,7 +3267,7 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server, + total_read += result; + } + +- return total_read > 0 ? total_read : result; ++ return total_read > 0 && result != -EAGAIN ? total_read : result; + } + + static int cifs_readpages(struct file *file, struct address_space *mapping, +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index aadc2b68678b..f2ddcf7ac9c3 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -1706,13 +1706,22 @@ cifs_rename(struct inode *source_dir, struct dentry *source_dentry, + unlink_target: + /* Try unlinking the target dentry if it's not negative */ + if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) { +- tmprc = cifs_unlink(target_dir, target_dentry); ++ if (d_is_dir(target_dentry)) ++ tmprc = cifs_rmdir(target_dir, target_dentry); ++ else ++ tmprc = cifs_unlink(target_dir, target_dentry); + if (tmprc) + goto cifs_rename_exit; + rc = cifs_do_rename(xid, source_dentry, from_name, + target_dentry, to_name); + } + ++ /* force revalidate to go get info when needed */ ++ CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0; ++ ++ source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime = ++ target_dir->i_mtime = current_fs_time(source_dir->i_sb); ++ + cifs_rename_exit: + kfree(info_buf_source); + kfree(from_name); +diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c +index b15862e0f68c..2bbf11b09214 100644 +--- a/fs/cifs/readdir.c ++++ b/fs/cifs/readdir.c +@@ -596,8 +596,8 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos, + if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) { + cfile->invalidHandle = true; + spin_unlock(&cifs_file_list_lock); +- if (server->ops->close) +- server->ops->close(xid, tcon, &cfile->fid); ++ if (server->ops->close_dir) ++ server->ops->close_dir(xid, tcon, &cfile->fid); + } else + spin_unlock(&cifs_file_list_lock); + if (cfile->srch_inf.ntwrk_buf_start) { +diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c +index 3f17b4550831..45992944e238 100644 +--- a/fs/cifs/smb2file.c ++++ b/fs/cifs/smb2file.c +@@ -50,7 +50,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, + goto out; + } + +- smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2, ++ smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, + GFP_KERNEL); + if (smb2_data == NULL) { + rc = -ENOMEM; +diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c +index 84c012a6aba0..215f8d3e3e53 100644 +--- a/fs/cifs/smb2inode.c ++++ b/fs/cifs/smb2inode.c +@@ -131,7 +131,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, + *adjust_tz = false; + *symlink = false; + +- smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2, ++ smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, + GFP_KERNEL); + if (smb2_data == NULL) + return -ENOMEM; +diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c +index 94bd4fbb13d3..e31a9dfdcd39 100644 +--- a/fs/cifs/smb2maperror.c ++++ b/fs/cifs/smb2maperror.c +@@ -605,7 +605,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = { + {STATUS_MAPPED_FILE_SIZE_ZERO, -EIO, "STATUS_MAPPED_FILE_SIZE_ZERO"}, + {STATUS_TOO_MANY_OPENED_FILES, -EMFILE, "STATUS_TOO_MANY_OPENED_FILES"}, + {STATUS_CANCELLED, -EIO, "STATUS_CANCELLED"}, +- {STATUS_CANNOT_DELETE, -EIO, "STATUS_CANNOT_DELETE"}, ++ {STATUS_CANNOT_DELETE, -EACCES, "STATUS_CANNOT_DELETE"}, + {STATUS_INVALID_COMPUTER_NAME, -EIO, "STATUS_INVALID_COMPUTER_NAME"}, + {STATUS_FILE_DELETED, -EIO, "STATUS_FILE_DELETED"}, + {STATUS_SPECIAL_ACCOUNT, -EIO, "STATUS_SPECIAL_ACCOUNT"}, +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 35ddc3ed119d..f8977b2d9187 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -339,7 +339,7 @@ smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon, + int rc; + struct smb2_file_all_info *smb2_data; + +- smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2, ++ smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, + GFP_KERNEL); + if (smb2_data == NULL) + return -ENOMEM; +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 049a3f2693ba..9aab8fe0e508 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -916,7 +916,8 @@ tcon_exit: + tcon_error_exit: + if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) { + cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); +- tcon->bad_network_name = true; ++ if (tcon) ++ tcon->bad_network_name = true; + } + goto tcon_exit; + } +@@ -1539,7 +1540,7 @@ SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, + { + return query_info(xid, tcon, persistent_fid, volatile_fid, + FILE_ALL_INFORMATION, +- sizeof(struct smb2_file_all_info) + MAX_NAME * 2, ++ sizeof(struct smb2_file_all_info) + PATH_MAX * 2, + sizeof(struct smb2_file_all_info), data); + } + +diff --git a/fs/dcache.c b/fs/dcache.c +index 7f3b4004c6c3..58d57da91d2a 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -106,8 +106,7 @@ static inline struct hlist_bl_head *d_hash(const struct dentry *parent, + unsigned int hash) + { + hash += (unsigned long) parent / L1_CACHE_BYTES; +- hash = hash + (hash >> d_hash_shift); +- return dentry_hashtable + (hash & d_hash_mask); ++ return dentry_hashtable + hash_32(hash, d_hash_shift); + } + + /* Statistics gathering. */ +diff --git a/fs/namei.c b/fs/namei.c +index bdea10963aa5..d5a4faeb39a5 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include + + #include "internal.h" +@@ -1624,8 +1625,7 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd) + + static inline unsigned int fold_hash(unsigned long hash) + { +- hash += hash >> (8*sizeof(int)); +- return hash; ++ return hash_64(hash, 32); + } + + #else /* 32-bit case */ +@@ -1797,7 +1797,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) + if (err) + return err; + } +- if (!d_is_directory(nd->path.dentry)) { ++ if (!d_can_lookup(nd->path.dentry)) { + err = -ENOTDIR; + break; + } +@@ -1818,7 +1818,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, + struct dentry *root = nd->root.dentry; + struct inode *inode = root->d_inode; + if (*name) { +- if (!d_is_directory(root)) ++ if (!d_can_lookup(root)) + return -ENOTDIR; + retval = inode_permission(inode, MAY_EXEC); + if (retval) +@@ -1874,7 +1874,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, + dentry = f.file->f_path.dentry; + + if (*name) { +- if (!d_is_directory(dentry)) { ++ if (!d_can_lookup(dentry)) { + fdput(f); + return -ENOTDIR; + } +@@ -1956,7 +1956,7 @@ static int path_lookupat(int dfd, const char *name, + err = complete_walk(nd); + + if (!err && nd->flags & LOOKUP_DIRECTORY) { +- if (!d_is_directory(nd->path.dentry)) { ++ if (!d_can_lookup(nd->path.dentry)) { + path_put(&nd->path); + err = -ENOTDIR; + } +@@ -2416,11 +2416,11 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) + IS_IMMUTABLE(inode) || IS_SWAPFILE(inode)) + return -EPERM; + if (isdir) { +- if (!d_is_directory(victim) && !d_is_autodir(victim)) ++ if (!d_is_dir(victim)) + return -ENOTDIR; + if (IS_ROOT(victim)) + return -EBUSY; +- } else if (d_is_directory(victim) || d_is_autodir(victim)) ++ } else if (d_is_dir(victim)) + return -EISDIR; + if (IS_DEADDIR(dir)) + return -ENOENT; +@@ -3018,11 +3018,10 @@ finish_open: + } + audit_inode(name, nd->path.dentry, 0); + error = -EISDIR; +- if ((open_flag & O_CREAT) && +- (d_is_directory(nd->path.dentry) || d_is_autodir(nd->path.dentry))) ++ if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry)) + goto out; + error = -ENOTDIR; +- if ((nd->flags & LOOKUP_DIRECTORY) && !d_is_directory(nd->path.dentry)) ++ if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry)) + goto out; + if (!S_ISREG(nd->inode->i_mode)) + will_truncate = false; +@@ -3746,7 +3745,7 @@ exit1: + slashes: + if (d_is_negative(dentry)) + error = -ENOENT; +- else if (d_is_directory(dentry) || d_is_autodir(dentry)) ++ else if (d_is_dir(dentry)) + error = -EISDIR; + else + error = -ENOTDIR; +@@ -4125,7 +4124,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode **delegated_inode) + { + int error; +- int is_dir = d_is_directory(old_dentry) || d_is_autodir(old_dentry); ++ int is_dir = d_is_dir(old_dentry); + const unsigned char *old_name; + + if (old_dentry->d_inode == new_dentry->d_inode) +@@ -4218,7 +4217,7 @@ retry_deleg: + if (d_is_negative(old_dentry)) + goto exit4; + /* unless the source is a directory trailing slashes give -ENOTDIR */ +- if (!d_is_directory(old_dentry) && !d_is_autodir(old_dentry)) { ++ if (!d_is_dir(old_dentry)) { + error = -ENOTDIR; + if (oldnd.last.name[oldnd.last.len]) + goto exit4; +diff --git a/fs/namespace.c b/fs/namespace.c +index 65233a5f390a..75536db4b69b 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -777,6 +777,20 @@ static void attach_mnt(struct mount *mnt, + list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); + } + ++static void attach_shadowed(struct mount *mnt, ++ struct mount *parent, ++ struct mount *shadows) ++{ ++ if (shadows) { ++ hlist_add_after_rcu(&shadows->mnt_hash, &mnt->mnt_hash); ++ list_add(&mnt->mnt_child, &shadows->mnt_child); ++ } else { ++ hlist_add_head_rcu(&mnt->mnt_hash, ++ m_hash(&parent->mnt, mnt->mnt_mountpoint)); ++ list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); ++ } ++} ++ + /* + * vfsmount lock must be held for write + */ +@@ -795,12 +809,7 @@ static void commit_tree(struct mount *mnt, struct mount *shadows) + + list_splice(&head, n->list.prev); + +- if (shadows) +- hlist_add_after_rcu(&shadows->mnt_hash, &mnt->mnt_hash); +- else +- hlist_add_head_rcu(&mnt->mnt_hash, +- m_hash(&parent->mnt, mnt->mnt_mountpoint)); +- list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); ++ attach_shadowed(mnt, parent, shadows); + touch_mnt_namespace(n); + } + +@@ -887,8 +896,21 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, + + mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~(MNT_WRITE_HOLD|MNT_MARKED); + /* Don't allow unprivileged users to change mount flags */ +- if ((flag & CL_UNPRIVILEGED) && (mnt->mnt.mnt_flags & MNT_READONLY)) +- mnt->mnt.mnt_flags |= MNT_LOCK_READONLY; ++ if (flag & CL_UNPRIVILEGED) { ++ mnt->mnt.mnt_flags |= MNT_LOCK_ATIME; ++ ++ if (mnt->mnt.mnt_flags & MNT_READONLY) ++ mnt->mnt.mnt_flags |= MNT_LOCK_READONLY; ++ ++ if (mnt->mnt.mnt_flags & MNT_NODEV) ++ mnt->mnt.mnt_flags |= MNT_LOCK_NODEV; ++ ++ if (mnt->mnt.mnt_flags & MNT_NOSUID) ++ mnt->mnt.mnt_flags |= MNT_LOCK_NOSUID; ++ ++ if (mnt->mnt.mnt_flags & MNT_NOEXEC) ++ mnt->mnt.mnt_flags |= MNT_LOCK_NOEXEC; ++ } + + /* Don't allow unprivileged users to reveal what is under a mount */ + if ((flag & CL_UNPRIVILEGED) && list_empty(&old->mnt_expire)) +@@ -1204,6 +1226,11 @@ static void namespace_unlock(void) + head.first->pprev = &head.first; + INIT_HLIST_HEAD(&unmounted); + ++ /* undo decrements we'd done in umount_tree() */ ++ hlist_for_each_entry(mnt, &head, mnt_hash) ++ if (mnt->mnt_ex_mountpoint.mnt) ++ mntget(mnt->mnt_ex_mountpoint.mnt); ++ + up_write(&namespace_sem); + + synchronize_rcu(); +@@ -1240,6 +1267,9 @@ void umount_tree(struct mount *mnt, int how) + hlist_add_head(&p->mnt_hash, &tmp_list); + } + ++ hlist_for_each_entry(p, &tmp_list, mnt_hash) ++ list_del_init(&p->mnt_child); ++ + if (how) + propagate_umount(&tmp_list); + +@@ -1250,9 +1280,9 @@ void umount_tree(struct mount *mnt, int how) + p->mnt_ns = NULL; + if (how < 2) + p->mnt.mnt_flags |= MNT_SYNC_UMOUNT; +- list_del_init(&p->mnt_child); + if (mnt_has_parent(p)) { + put_mountpoint(p->mnt_mp); ++ mnt_add_count(p->mnt_parent, -1); + /* move the reference to mountpoint into ->mnt_ex_mountpoint */ + p->mnt_ex_mountpoint.dentry = p->mnt_mountpoint; + p->mnt_ex_mountpoint.mnt = &p->mnt_parent->mnt; +@@ -1483,6 +1513,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, + continue; + + for (s = r; s; s = next_mnt(s, r)) { ++ struct mount *t = NULL; + if (!(flag & CL_COPY_UNBINDABLE) && + IS_MNT_UNBINDABLE(s)) { + s = skip_mnt_tree(s); +@@ -1504,7 +1535,14 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, + goto out; + lock_mount_hash(); + list_add_tail(&q->mnt_list, &res->mnt_list); +- attach_mnt(q, parent, p->mnt_mp); ++ mnt_set_mountpoint(parent, p->mnt_mp, q); ++ if (!list_empty(&parent->mnt_mounts)) { ++ t = list_last_entry(&parent->mnt_mounts, ++ struct mount, mnt_child); ++ if (t->mnt_mp != p->mnt_mp) ++ t = NULL; ++ } ++ attach_shadowed(q, parent, t); + unlock_mount_hash(); + } + } +@@ -1887,9 +1925,6 @@ static int change_mount_flags(struct vfsmount *mnt, int ms_flags) + if (readonly_request == __mnt_is_readonly(mnt)) + return 0; + +- if (mnt->mnt_flags & MNT_LOCK_READONLY) +- return -EPERM; +- + if (readonly_request) + error = mnt_make_readonly(real_mount(mnt)); + else +@@ -1915,6 +1950,33 @@ static int do_remount(struct path *path, int flags, int mnt_flags, + if (path->dentry != path->mnt->mnt_root) + return -EINVAL; + ++ /* Don't allow changing of locked mnt flags. ++ * ++ * No locks need to be held here while testing the various ++ * MNT_LOCK flags because those flags can never be cleared ++ * once they are set. ++ */ ++ if ((mnt->mnt.mnt_flags & MNT_LOCK_READONLY) && ++ !(mnt_flags & MNT_READONLY)) { ++ return -EPERM; ++ } ++ if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) && ++ !(mnt_flags & MNT_NODEV)) { ++ return -EPERM; ++ } ++ if ((mnt->mnt.mnt_flags & MNT_LOCK_NOSUID) && ++ !(mnt_flags & MNT_NOSUID)) { ++ return -EPERM; ++ } ++ if ((mnt->mnt.mnt_flags & MNT_LOCK_NOEXEC) && ++ !(mnt_flags & MNT_NOEXEC)) { ++ return -EPERM; ++ } ++ if ((mnt->mnt.mnt_flags & MNT_LOCK_ATIME) && ++ ((mnt->mnt.mnt_flags & MNT_ATIME_MASK) != (mnt_flags & MNT_ATIME_MASK))) { ++ return -EPERM; ++ } ++ + err = security_sb_remount(sb, data); + if (err) + return err; +@@ -1928,7 +1990,7 @@ static int do_remount(struct path *path, int flags, int mnt_flags, + err = do_remount_sb(sb, flags, data, 0); + if (!err) { + lock_mount_hash(); +- mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK; ++ mnt_flags |= mnt->mnt.mnt_flags & ~MNT_USER_SETTABLE_MASK; + mnt->mnt.mnt_flags = mnt_flags; + touch_mnt_namespace(mnt->mnt_ns); + unlock_mount_hash(); +@@ -2113,7 +2175,7 @@ static int do_new_mount(struct path *path, const char *fstype, int flags, + */ + if (!(type->fs_flags & FS_USERNS_DEV_MOUNT)) { + flags |= MS_NODEV; +- mnt_flags |= MNT_NODEV; ++ mnt_flags |= MNT_NODEV | MNT_LOCK_NODEV; + } + } + +@@ -2427,6 +2489,14 @@ long do_mount(const char *dev_name, const char *dir_name, + if (flags & MS_RDONLY) + mnt_flags |= MNT_READONLY; + ++ /* The default atime for remount is preservation */ ++ if ((flags & MS_REMOUNT) && ++ ((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME | ++ MS_STRICTATIME)) == 0)) { ++ mnt_flags &= ~MNT_ATIME_MASK; ++ mnt_flags |= path.mnt->mnt_flags & MNT_ATIME_MASK; ++ } ++ + flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN | + MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT | + MS_STRICTATIME); +diff --git a/fs/pnode.c b/fs/pnode.c +index a364a704333b..b7f831089500 100644 +--- a/fs/pnode.c ++++ b/fs/pnode.c +@@ -381,6 +381,7 @@ static void __propagate_umount(struct mount *mnt) + * other children + */ + if (child && list_empty(&child->mnt_mounts)) { ++ list_del_init(&child->mnt_child); + hlist_del_init_rcu(&child->mnt_hash); + hlist_add_before_rcu(&child->mnt_hash, &mnt->mnt_hash); + } +diff --git a/fs/proc/array.c b/fs/proc/array.c +index 656e401794de..baf3464bbce0 100644 +--- a/fs/proc/array.c ++++ b/fs/proc/array.c +@@ -297,15 +297,11 @@ static void render_cap_t(struct seq_file *m, const char *header, + seq_puts(m, header); + CAP_FOR_EACH_U32(__capi) { + seq_printf(m, "%08x", +- a->cap[(_KERNEL_CAPABILITY_U32S-1) - __capi]); ++ a->cap[CAP_LAST_U32 - __capi]); + } + seq_putc(m, '\n'); + } + +-/* Remove non-existent capabilities */ +-#define NORM_CAPS(v) (v.cap[CAP_TO_INDEX(CAP_LAST_CAP)] &= \ +- CAP_TO_MASK(CAP_LAST_CAP + 1) - 1) +- + static inline void task_cap(struct seq_file *m, struct task_struct *p) + { + const struct cred *cred; +@@ -319,11 +315,6 @@ static inline void task_cap(struct seq_file *m, struct task_struct *p) + cap_bset = cred->cap_bset; + rcu_read_unlock(); + +- NORM_CAPS(cap_inheritable); +- NORM_CAPS(cap_permitted); +- NORM_CAPS(cap_effective); +- NORM_CAPS(cap_bset); +- + render_cap_t(m, "CapInh:\t", &cap_inheritable); + render_cap_t(m, "CapPrm:\t", &cap_permitted); + render_cap_t(m, "CapEff:\t", &cap_effective); +diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c +index db2cfb067d0b..5d2518b24cea 100644 +--- a/fs/xfs/xfs_aops.c ++++ b/fs/xfs/xfs_aops.c +@@ -1660,11 +1660,72 @@ xfs_vm_readpages( + return mpage_readpages(mapping, pages, nr_pages, xfs_get_blocks); + } + ++/* ++ * This is basically a copy of __set_page_dirty_buffers() with one ++ * small tweak: buffers beyond EOF do not get marked dirty. If we mark them ++ * dirty, we'll never be able to clean them because we don't write buffers ++ * beyond EOF, and that means we can't invalidate pages that span EOF ++ * that have been marked dirty. Further, the dirty state can leak into ++ * the file interior if the file is extended, resulting in all sorts of ++ * bad things happening as the state does not match the underlying data. ++ * ++ * XXX: this really indicates that bufferheads in XFS need to die. Warts like ++ * this only exist because of bufferheads and how the generic code manages them. ++ */ ++STATIC int ++xfs_vm_set_page_dirty( ++ struct page *page) ++{ ++ struct address_space *mapping = page->mapping; ++ struct inode *inode = mapping->host; ++ loff_t end_offset; ++ loff_t offset; ++ int newly_dirty; ++ ++ if (unlikely(!mapping)) ++ return !TestSetPageDirty(page); ++ ++ end_offset = i_size_read(inode); ++ offset = page_offset(page); ++ ++ spin_lock(&mapping->private_lock); ++ if (page_has_buffers(page)) { ++ struct buffer_head *head = page_buffers(page); ++ struct buffer_head *bh = head; ++ ++ do { ++ if (offset < end_offset) ++ set_buffer_dirty(bh); ++ bh = bh->b_this_page; ++ offset += 1 << inode->i_blkbits; ++ } while (bh != head); ++ } ++ newly_dirty = !TestSetPageDirty(page); ++ spin_unlock(&mapping->private_lock); ++ ++ if (newly_dirty) { ++ /* sigh - __set_page_dirty() is static, so copy it here, too */ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&mapping->tree_lock, flags); ++ if (page->mapping) { /* Race with truncate? */ ++ WARN_ON_ONCE(!PageUptodate(page)); ++ account_page_dirtied(page, mapping); ++ radix_tree_tag_set(&mapping->page_tree, ++ page_index(page), PAGECACHE_TAG_DIRTY); ++ } ++ spin_unlock_irqrestore(&mapping->tree_lock, flags); ++ __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); ++ } ++ return newly_dirty; ++} ++ + const struct address_space_operations xfs_address_space_operations = { + .readpage = xfs_vm_readpage, + .readpages = xfs_vm_readpages, + .writepage = xfs_vm_writepage, + .writepages = xfs_vm_writepages, ++ .set_page_dirty = xfs_vm_set_page_dirty, + .releasepage = xfs_vm_releasepage, + .invalidatepage = xfs_vm_invalidatepage, + .write_begin = xfs_vm_write_begin, +diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c +index 7aeb4c895b32..95f94483c3d7 100644 +--- a/fs/xfs/xfs_dquot.c ++++ b/fs/xfs/xfs_dquot.c +@@ -1011,7 +1011,8 @@ xfs_qm_dqflush( + * Get the buffer containing the on-disk dquot + */ + error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno, +- mp->m_quotainfo->qi_dqchunklen, 0, &bp, NULL); ++ mp->m_quotainfo->qi_dqchunklen, 0, &bp, ++ &xfs_dquot_buf_ops); + if (error) + goto out_unlock; + +diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c +index 64b48eade91d..f50def6018a9 100644 +--- a/fs/xfs/xfs_file.c ++++ b/fs/xfs/xfs_file.c +@@ -302,7 +302,16 @@ xfs_file_aio_read( + xfs_rw_iunlock(ip, XFS_IOLOCK_EXCL); + return ret; + } +- truncate_pagecache_range(VFS_I(ip), pos, -1); ++ ++ /* ++ * Invalidate whole pages. This can return an error if ++ * we fail to invalidate a page, but this should never ++ * happen on XFS. Warn if it does fail. ++ */ ++ ret = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping, ++ pos >> PAGE_CACHE_SHIFT, -1); ++ WARN_ON_ONCE(ret); ++ ret = 0; + } + xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); + } +@@ -683,7 +692,15 @@ xfs_file_dio_aio_write( + pos, -1); + if (ret) + goto out; +- truncate_pagecache_range(VFS_I(ip), pos, -1); ++ /* ++ * Invalidate whole pages. This can return an error if ++ * we fail to invalidate a page, but this should never ++ * happen on XFS. Warn if it does fail. ++ */ ++ ret = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping, ++ pos >> PAGE_CACHE_SHIFT, -1); ++ WARN_ON_ONCE(ret); ++ ret = 0; + } + + /* +diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c +index bce53ac81096..eb26418814fe 100644 +--- a/fs/xfs/xfs_log_recover.c ++++ b/fs/xfs/xfs_log_recover.c +@@ -2125,6 +2125,17 @@ xlog_recover_validate_buf_type( + __uint16_t magic16; + __uint16_t magicda; + ++ /* ++ * We can only do post recovery validation on items on CRC enabled ++ * fielsystems as we need to know when the buffer was written to be able ++ * to determine if we should have replayed the item. If we replay old ++ * metadata over a newer buffer, then it will enter a temporarily ++ * inconsistent state resulting in verification failures. Hence for now ++ * just avoid the verification stage for non-crc filesystems ++ */ ++ if (!xfs_sb_version_hascrc(&mp->m_sb)) ++ return; ++ + magic32 = be32_to_cpu(*(__be32 *)bp->b_addr); + magic16 = be16_to_cpu(*(__be16*)bp->b_addr); + magicda = be16_to_cpu(info->magic); +@@ -2160,8 +2171,6 @@ xlog_recover_validate_buf_type( + bp->b_ops = &xfs_agf_buf_ops; + break; + case XFS_BLFT_AGFL_BUF: +- if (!xfs_sb_version_hascrc(&mp->m_sb)) +- break; + if (magic32 != XFS_AGFL_MAGIC) { + xfs_warn(mp, "Bad AGFL block magic!"); + ASSERT(0); +@@ -2194,10 +2203,6 @@ xlog_recover_validate_buf_type( + #endif + break; + case XFS_BLFT_DINO_BUF: +- /* +- * we get here with inode allocation buffers, not buffers that +- * track unlinked list changes. +- */ + if (magic16 != XFS_DINODE_MAGIC) { + xfs_warn(mp, "Bad INODE block magic!"); + ASSERT(0); +@@ -2277,8 +2282,6 @@ xlog_recover_validate_buf_type( + bp->b_ops = &xfs_attr3_leaf_buf_ops; + break; + case XFS_BLFT_ATTR_RMT_BUF: +- if (!xfs_sb_version_hascrc(&mp->m_sb)) +- break; + if (magic32 != XFS_ATTR3_RMT_MAGIC) { + xfs_warn(mp, "Bad attr remote magic!"); + ASSERT(0); +@@ -2385,16 +2388,7 @@ xlog_recover_do_reg_buffer( + /* Shouldn't be any more regions */ + ASSERT(i == item->ri_total); + +- /* +- * We can only do post recovery validation on items on CRC enabled +- * fielsystems as we need to know when the buffer was written to be able +- * to determine if we should have replayed the item. If we replay old +- * metadata over a newer buffer, then it will enter a temporarily +- * inconsistent state resulting in verification failures. Hence for now +- * just avoid the verification stage for non-crc filesystems +- */ +- if (xfs_sb_version_hascrc(&mp->m_sb)) +- xlog_recover_validate_buf_type(mp, bp, buf_f); ++ xlog_recover_validate_buf_type(mp, bp, buf_f); + } + + /* +@@ -2502,12 +2496,29 @@ xlog_recover_buffer_pass2( + } + + /* +- * recover the buffer only if we get an LSN from it and it's less than ++ * Recover the buffer only if we get an LSN from it and it's less than + * the lsn of the transaction we are replaying. ++ * ++ * Note that we have to be extremely careful of readahead here. ++ * Readahead does not attach verfiers to the buffers so if we don't ++ * actually do any replay after readahead because of the LSN we found ++ * in the buffer if more recent than that current transaction then we ++ * need to attach the verifier directly. Failure to do so can lead to ++ * future recovery actions (e.g. EFI and unlinked list recovery) can ++ * operate on the buffers and they won't get the verifier attached. This ++ * can lead to blocks on disk having the correct content but a stale ++ * CRC. ++ * ++ * It is safe to assume these clean buffers are currently up to date. ++ * If the buffer is dirtied by a later transaction being replayed, then ++ * the verifier will be reset to match whatever recover turns that ++ * buffer into. + */ + lsn = xlog_recover_get_buf_lsn(mp, bp); +- if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) ++ if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) { ++ xlog_recover_validate_buf_type(mp, bp, buf_f); + goto out_release; ++ } + + if (buf_f->blf_flags & XFS_BLF_INODE_BUF) { + error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f); +diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c +index 348e4d2ed6e6..6d7d1de13403 100644 +--- a/fs/xfs/xfs_qm.c ++++ b/fs/xfs/xfs_qm.c +@@ -1176,6 +1176,12 @@ xfs_qm_dqiter_bufs( + if (error) + break; + ++ /* ++ * A corrupt buffer might not have a verifier attached, so ++ * make sure we have the correct one attached before writeback ++ * occurs. ++ */ ++ bp->b_ops = &xfs_dquot_buf_ops; + xfs_qm_reset_dqcounts(mp, bp, firstid, type); + xfs_buf_delwri_queue(bp, buffer_list); + xfs_buf_relse(bp); +@@ -1261,7 +1267,7 @@ xfs_qm_dqiterate( + xfs_buf_readahead(mp->m_ddev_targp, + XFS_FSB_TO_DADDR(mp, rablkno), + mp->m_quotainfo->qi_dqchunklen, +- NULL); ++ &xfs_dquot_buf_ops); + rablkno++; + } + } +diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h +index 8256eb4ad057..e9c4f190ffae 100644 +--- a/include/acpi/acpi_bus.h ++++ b/include/acpi/acpi_bus.h +@@ -228,7 +228,6 @@ struct acpi_device_pnp { + acpi_device_name device_name; /* Driver-determined */ + acpi_device_class device_class; /* " */ + union acpi_object *str_obj; /* unicode string for _STR method */ +- unsigned long sun; /* _SUN */ + }; + + #define acpi_device_bid(d) ((d)->pnp.bus_id) +diff --git a/include/linux/capability.h b/include/linux/capability.h +index 84b13ad67c1c..aa93e5ef594c 100644 +--- a/include/linux/capability.h ++++ b/include/linux/capability.h +@@ -78,8 +78,11 @@ extern const kernel_cap_t __cap_init_eff_set; + # error Fix up hand-coded capability macro initializers + #else /* HAND-CODED capability initializers */ + ++#define CAP_LAST_U32 ((_KERNEL_CAPABILITY_U32S) - 1) ++#define CAP_LAST_U32_VALID_MASK (CAP_TO_MASK(CAP_LAST_CAP + 1) -1) ++ + # define CAP_EMPTY_SET ((kernel_cap_t){{ 0, 0 }}) +-# define CAP_FULL_SET ((kernel_cap_t){{ ~0, ~0 }}) ++# define CAP_FULL_SET ((kernel_cap_t){{ ~0, CAP_LAST_U32_VALID_MASK }}) + # define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ + | CAP_TO_MASK(CAP_LINUX_IMMUTABLE), \ + CAP_FS_MASK_B1 } }) +diff --git a/include/linux/dcache.h b/include/linux/dcache.h +index bf72e9ac6de0..3b50cac7ccb3 100644 +--- a/include/linux/dcache.h ++++ b/include/linux/dcache.h +@@ -429,7 +429,7 @@ static inline unsigned __d_entry_type(const struct dentry *dentry) + return dentry->d_flags & DCACHE_ENTRY_TYPE; + } + +-static inline bool d_is_directory(const struct dentry *dentry) ++static inline bool d_can_lookup(const struct dentry *dentry) + { + return __d_entry_type(dentry) == DCACHE_DIRECTORY_TYPE; + } +@@ -439,6 +439,11 @@ static inline bool d_is_autodir(const struct dentry *dentry) + return __d_entry_type(dentry) == DCACHE_AUTODIR_TYPE; + } + ++static inline bool d_is_dir(const struct dentry *dentry) ++{ ++ return d_can_lookup(dentry) || d_is_autodir(dentry); ++} ++ + static inline bool d_is_symlink(const struct dentry *dentry) + { + return __d_entry_type(dentry) == DCACHE_SYMLINK_TYPE; +diff --git a/include/linux/mount.h b/include/linux/mount.h +index 839bac270904..b0c1e6574e7f 100644 +--- a/include/linux/mount.h ++++ b/include/linux/mount.h +@@ -42,13 +42,20 @@ struct mnt_namespace; + * flag, consider how it interacts with shared mounts. + */ + #define MNT_SHARED_MASK (MNT_UNBINDABLE) +-#define MNT_PROPAGATION_MASK (MNT_SHARED | MNT_UNBINDABLE) ++#define MNT_USER_SETTABLE_MASK (MNT_NOSUID | MNT_NODEV | MNT_NOEXEC \ ++ | MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME \ ++ | MNT_READONLY) ++#define MNT_ATIME_MASK (MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME ) + + #define MNT_INTERNAL_FLAGS (MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL | \ + MNT_DOOMED | MNT_SYNC_UMOUNT | MNT_MARKED) + + #define MNT_INTERNAL 0x4000 + ++#define MNT_LOCK_ATIME 0x040000 ++#define MNT_LOCK_NOEXEC 0x080000 ++#define MNT_LOCK_NOSUID 0x100000 ++#define MNT_LOCK_NODEV 0x200000 + #define MNT_LOCK_READONLY 0x400000 + #define MNT_LOCKED 0x800000 + #define MNT_DOOMED 0x1000000 +diff --git a/include/linux/tpm.h b/include/linux/tpm.h +index fff1d0976f80..8350c538b486 100644 +--- a/include/linux/tpm.h ++++ b/include/linux/tpm.h +@@ -39,6 +39,9 @@ struct tpm_class_ops { + int (*send) (struct tpm_chip *chip, u8 *buf, size_t len); + void (*cancel) (struct tpm_chip *chip); + u8 (*status) (struct tpm_chip *chip); ++ bool (*update_timeouts)(struct tpm_chip *chip, ++ unsigned long *timeout_cap); ++ + }; + + #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) +diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h +index b4f1effc9216..409fafb63f63 100644 +--- a/include/scsi/scsi_device.h ++++ b/include/scsi/scsi_device.h +@@ -149,6 +149,7 @@ struct scsi_device { + unsigned skip_ms_page_8:1; /* do not use MODE SENSE page 0x08 */ + unsigned skip_ms_page_3f:1; /* do not use MODE SENSE page 0x3f */ + unsigned skip_vpd_pages:1; /* do not read VPD pages */ ++ unsigned try_vpd_pages:1; /* attempt to read VPD pages */ + unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */ + unsigned no_start_on_add:1; /* do not issue start on add */ + unsigned allow_restart:1; /* issue START_UNIT in error handler */ +diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h +index 447d2d7466fc..183eaab7c380 100644 +--- a/include/scsi/scsi_devinfo.h ++++ b/include/scsi/scsi_devinfo.h +@@ -32,4 +32,9 @@ + #define BLIST_ATTACH_PQ3 0x1000000 /* Scan: Attach to PQ3 devices */ + #define BLIST_NO_DIF 0x2000000 /* Disable T10 PI (DIF) */ + #define BLIST_SKIP_VPD_PAGES 0x4000000 /* Ignore SBC-3 VPD pages */ ++#define BLIST_SCSI3LUN 0x8000000 /* Scan more than 256 LUNs ++ for sequential scan */ ++#define BLIST_TRY_VPD_PAGES 0x10000000 /* Attempt to read VPD pages */ ++#define BLIST_NO_RSOC 0x20000000 /* don't try to issue RSOC */ ++ + #endif +diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h +index 99b80abf360a..3066718eb120 100644 +--- a/include/uapi/rdma/rdma_user_cm.h ++++ b/include/uapi/rdma/rdma_user_cm.h +@@ -34,6 +34,7 @@ + #define RDMA_USER_CM_H + + #include ++#include + #include + #include + #include +diff --git a/kernel/audit.c b/kernel/audit.c +index 0c9dc860cc15..2c0ecd1753de 100644 +--- a/kernel/audit.c ++++ b/kernel/audit.c +@@ -1628,7 +1628,7 @@ void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap) + audit_log_format(ab, " %s=", prefix); + CAP_FOR_EACH_U32(i) { + audit_log_format(ab, "%08x", +- cap->cap[(_KERNEL_CAPABILITY_U32S-1) - i]); ++ cap->cap[CAP_LAST_U32 - i]); + } + } + +diff --git a/kernel/capability.c b/kernel/capability.c +index 1191a44786df..00adb2193d01 100644 +--- a/kernel/capability.c ++++ b/kernel/capability.c +@@ -268,6 +268,10 @@ SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data) + i++; + } + ++ effective.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; ++ permitted.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; ++ inheritable.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; ++ + new = prepare_creds(); + if (!new) + return -ENOMEM; +diff --git a/kernel/smp.c b/kernel/smp.c +index ffee35bef179..ff87d4479558 100644 +--- a/kernel/smp.c ++++ b/kernel/smp.c +@@ -617,7 +617,7 @@ void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info), + if (cond_func(cpu, info)) { + ret = smp_call_function_single(cpu, func, + info, wait); +- WARN_ON_ONCE(!ret); ++ WARN_ON_ONCE(ret); + } + preempt_enable(); + } +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index 0954450df7dc..a53f1bbc546b 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -1981,7 +1981,7 @@ rb_add_time_stamp(struct ring_buffer_event *event, u64 delta) + + /** + * rb_update_event - update event type and data +- * @event: the even to update ++ * @event: the event to update + * @type: the type of event + * @length: the size of the event field in the ring buffer + * +@@ -3354,21 +3354,16 @@ static void rb_iter_reset(struct ring_buffer_iter *iter) + struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer; + + /* Iterator usage is expected to have record disabled */ +- if (list_empty(&cpu_buffer->reader_page->list)) { +- iter->head_page = rb_set_head_page(cpu_buffer); +- if (unlikely(!iter->head_page)) +- return; +- iter->head = iter->head_page->read; +- } else { +- iter->head_page = cpu_buffer->reader_page; +- iter->head = cpu_buffer->reader_page->read; +- } ++ iter->head_page = cpu_buffer->reader_page; ++ iter->head = cpu_buffer->reader_page->read; ++ ++ iter->cache_reader_page = iter->head_page; ++ iter->cache_read = iter->head; ++ + if (iter->head) + iter->read_stamp = cpu_buffer->read_stamp; + else + iter->read_stamp = iter->head_page->page->time_stamp; +- iter->cache_reader_page = cpu_buffer->reader_page; +- iter->cache_read = cpu_buffer->read; + } + + /** +@@ -3761,12 +3756,14 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) + return NULL; + + /* +- * We repeat when a time extend is encountered. +- * Since the time extend is always attached to a data event, +- * we should never loop more than once. +- * (We never hit the following condition more than twice). ++ * We repeat when a time extend is encountered or we hit ++ * the end of the page. Since the time extend is always attached ++ * to a data event, we should never loop more than three times. ++ * Once for going to next page, once on time extend, and ++ * finally once to get the event. ++ * (We never hit the following condition more than thrice). + */ +- if (RB_WARN_ON(cpu_buffer, ++nr_loops > 2)) ++ if (RB_WARN_ON(cpu_buffer, ++nr_loops > 3)) + return NULL; + + if (rb_per_cpu_empty(cpu_buffer)) +diff --git a/lib/assoc_array.c b/lib/assoc_array.c +index c0b1007011e1..2404d03e251a 100644 +--- a/lib/assoc_array.c ++++ b/lib/assoc_array.c +@@ -1723,11 +1723,13 @@ ascend_old_tree: + shortcut = assoc_array_ptr_to_shortcut(ptr); + slot = shortcut->parent_slot; + cursor = shortcut->back_pointer; ++ if (!cursor) ++ goto gc_complete; + } else { + slot = node->parent_slot; + cursor = ptr; + } +- BUG_ON(!ptr); ++ BUG_ON(!cursor); + node = assoc_array_ptr_to_node(cursor); + slot++; + goto continue_node; +@@ -1735,7 +1737,7 @@ ascend_old_tree: + gc_complete: + edit->set[0].to = new_root; + assoc_array_apply_edit(edit); +- edit->array->nr_leaves_on_tree = nr_leaves_on_tree; ++ array->nr_leaves_on_tree = nr_leaves_on_tree; + return 0; + + enomem: +diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c +index 27ae84154586..06a7a769737f 100644 +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1112,7 +1112,8 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) + l2cap_chan_close(chan, 0); + lock_sock(sk); + +- if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) ++ if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && ++ !(current->flags & PF_EXITING)) + err = bt_sock_wait_state(sk, BT_CLOSED, + sk->sk_lingertime); + } +diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c +index facd8a79c038..b08865111024 100644 +--- a/net/bluetooth/rfcomm/core.c ++++ b/net/bluetooth/rfcomm/core.c +@@ -1859,10 +1859,13 @@ static struct rfcomm_session *rfcomm_process_rx(struct rfcomm_session *s) + /* Get data directly from socket receive queue without copying it. */ + while ((skb = skb_dequeue(&sk->sk_receive_queue))) { + skb_orphan(skb); +- if (!skb_linearize(skb)) ++ if (!skb_linearize(skb)) { + s = rfcomm_recv_frame(s, skb); +- else ++ if (!s) ++ break; ++ } else { + kfree_skb(skb); ++ } + } + + if (s && (sk->sk_state == BT_CLOSED)) +diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c +index 3c2d3e4aa2f5..a0050de6f1f1 100644 +--- a/net/bluetooth/rfcomm/sock.c ++++ b/net/bluetooth/rfcomm/sock.c +@@ -898,7 +898,8 @@ static int rfcomm_sock_shutdown(struct socket *sock, int how) + sk->sk_shutdown = SHUTDOWN_MASK; + __rfcomm_sock_close(sk); + +- if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) ++ if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && ++ !(current->flags & PF_EXITING)) + err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); + } + release_sock(sk); +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index 24fa3964b3c8..316dd4e0af39 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -909,7 +909,8 @@ static int sco_sock_shutdown(struct socket *sock, int how) + sco_sock_clear_timer(sk); + __sco_sock_close(sk); + +- if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) ++ if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && ++ !(current->flags & PF_EXITING)) + err = bt_sock_wait_state(sk, BT_CLOSED, + sk->sk_lingertime); + } +@@ -929,7 +930,8 @@ static int sco_sock_release(struct socket *sock) + + sco_sock_close(sk); + +- if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) { ++ if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && ++ !(current->flags & PF_EXITING)) { + lock_sock(sk); + err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); + release_sock(sk); +diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c +index 96238ba95f2b..de6662b14e1f 100644 +--- a/net/ceph/auth_x.c ++++ b/net/ceph/auth_x.c +@@ -13,8 +13,6 @@ + #include "auth_x.h" + #include "auth_x_protocol.h" + +-#define TEMP_TICKET_BUF_LEN 256 +- + static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed); + + static int ceph_x_is_authenticated(struct ceph_auth_client *ac) +@@ -64,7 +62,7 @@ static int ceph_x_encrypt(struct ceph_crypto_key *secret, + } + + static int ceph_x_decrypt(struct ceph_crypto_key *secret, +- void **p, void *end, void *obuf, size_t olen) ++ void **p, void *end, void **obuf, size_t olen) + { + struct ceph_x_encrypt_header head; + size_t head_len = sizeof(head); +@@ -75,8 +73,14 @@ static int ceph_x_decrypt(struct ceph_crypto_key *secret, + return -EINVAL; + + dout("ceph_x_decrypt len %d\n", len); +- ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen, +- *p, len); ++ if (*obuf == NULL) { ++ *obuf = kmalloc(len, GFP_NOFS); ++ if (!*obuf) ++ return -ENOMEM; ++ olen = len; ++ } ++ ++ ret = ceph_decrypt2(secret, &head, &head_len, *obuf, &olen, *p, len); + if (ret) + return ret; + if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC) +@@ -129,139 +133,120 @@ static void remove_ticket_handler(struct ceph_auth_client *ac, + kfree(th); + } + +-static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac, +- struct ceph_crypto_key *secret, +- void *buf, void *end) ++static int process_one_ticket(struct ceph_auth_client *ac, ++ struct ceph_crypto_key *secret, ++ void **p, void *end) + { + struct ceph_x_info *xi = ac->private; +- int num; +- void *p = buf; ++ int type; ++ u8 tkt_struct_v, blob_struct_v; ++ struct ceph_x_ticket_handler *th; ++ void *dbuf = NULL; ++ void *dp, *dend; ++ int dlen; ++ char is_enc; ++ struct timespec validity; ++ struct ceph_crypto_key old_key; ++ void *ticket_buf = NULL; ++ void *tp, *tpend; ++ struct ceph_timespec new_validity; ++ struct ceph_crypto_key new_session_key; ++ struct ceph_buffer *new_ticket_blob; ++ unsigned long new_expires, new_renew_after; ++ u64 new_secret_id; + int ret; +- char *dbuf; +- char *ticket_buf; +- u8 reply_struct_v; + +- dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS); +- if (!dbuf) +- return -ENOMEM; ++ ceph_decode_need(p, end, sizeof(u32) + 1, bad); + +- ret = -ENOMEM; +- ticket_buf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS); +- if (!ticket_buf) +- goto out_dbuf; ++ type = ceph_decode_32(p); ++ dout(" ticket type %d %s\n", type, ceph_entity_type_name(type)); + +- ceph_decode_need(&p, end, 1 + sizeof(u32), bad); +- reply_struct_v = ceph_decode_8(&p); +- if (reply_struct_v != 1) ++ tkt_struct_v = ceph_decode_8(p); ++ if (tkt_struct_v != 1) + goto bad; +- num = ceph_decode_32(&p); +- dout("%d tickets\n", num); +- while (num--) { +- int type; +- u8 tkt_struct_v, blob_struct_v; +- struct ceph_x_ticket_handler *th; +- void *dp, *dend; +- int dlen; +- char is_enc; +- struct timespec validity; +- struct ceph_crypto_key old_key; +- void *tp, *tpend; +- struct ceph_timespec new_validity; +- struct ceph_crypto_key new_session_key; +- struct ceph_buffer *new_ticket_blob; +- unsigned long new_expires, new_renew_after; +- u64 new_secret_id; +- +- ceph_decode_need(&p, end, sizeof(u32) + 1, bad); +- +- type = ceph_decode_32(&p); +- dout(" ticket type %d %s\n", type, ceph_entity_type_name(type)); +- +- tkt_struct_v = ceph_decode_8(&p); +- if (tkt_struct_v != 1) +- goto bad; +- +- th = get_ticket_handler(ac, type); +- if (IS_ERR(th)) { +- ret = PTR_ERR(th); +- goto out; +- } + +- /* blob for me */ +- dlen = ceph_x_decrypt(secret, &p, end, dbuf, +- TEMP_TICKET_BUF_LEN); +- if (dlen <= 0) { +- ret = dlen; +- goto out; +- } +- dout(" decrypted %d bytes\n", dlen); +- dend = dbuf + dlen; +- dp = dbuf; ++ th = get_ticket_handler(ac, type); ++ if (IS_ERR(th)) { ++ ret = PTR_ERR(th); ++ goto out; ++ } + +- tkt_struct_v = ceph_decode_8(&dp); +- if (tkt_struct_v != 1) +- goto bad; ++ /* blob for me */ ++ dlen = ceph_x_decrypt(secret, p, end, &dbuf, 0); ++ if (dlen <= 0) { ++ ret = dlen; ++ goto out; ++ } ++ dout(" decrypted %d bytes\n", dlen); ++ dp = dbuf; ++ dend = dp + dlen; + +- memcpy(&old_key, &th->session_key, sizeof(old_key)); +- ret = ceph_crypto_key_decode(&new_session_key, &dp, dend); +- if (ret) +- goto out; ++ tkt_struct_v = ceph_decode_8(&dp); ++ if (tkt_struct_v != 1) ++ goto bad; + +- ceph_decode_copy(&dp, &new_validity, sizeof(new_validity)); +- ceph_decode_timespec(&validity, &new_validity); +- new_expires = get_seconds() + validity.tv_sec; +- new_renew_after = new_expires - (validity.tv_sec / 4); +- dout(" expires=%lu renew_after=%lu\n", new_expires, +- new_renew_after); ++ memcpy(&old_key, &th->session_key, sizeof(old_key)); ++ ret = ceph_crypto_key_decode(&new_session_key, &dp, dend); ++ if (ret) ++ goto out; + +- /* ticket blob for service */ +- ceph_decode_8_safe(&p, end, is_enc, bad); +- tp = ticket_buf; +- if (is_enc) { +- /* encrypted */ +- dout(" encrypted ticket\n"); +- dlen = ceph_x_decrypt(&old_key, &p, end, ticket_buf, +- TEMP_TICKET_BUF_LEN); +- if (dlen < 0) { +- ret = dlen; +- goto out; +- } +- dlen = ceph_decode_32(&tp); +- } else { +- /* unencrypted */ +- ceph_decode_32_safe(&p, end, dlen, bad); +- ceph_decode_need(&p, end, dlen, bad); +- ceph_decode_copy(&p, ticket_buf, dlen); ++ ceph_decode_copy(&dp, &new_validity, sizeof(new_validity)); ++ ceph_decode_timespec(&validity, &new_validity); ++ new_expires = get_seconds() + validity.tv_sec; ++ new_renew_after = new_expires - (validity.tv_sec / 4); ++ dout(" expires=%lu renew_after=%lu\n", new_expires, ++ new_renew_after); ++ ++ /* ticket blob for service */ ++ ceph_decode_8_safe(p, end, is_enc, bad); ++ if (is_enc) { ++ /* encrypted */ ++ dout(" encrypted ticket\n"); ++ dlen = ceph_x_decrypt(&old_key, p, end, &ticket_buf, 0); ++ if (dlen < 0) { ++ ret = dlen; ++ goto out; + } +- tpend = tp + dlen; +- dout(" ticket blob is %d bytes\n", dlen); +- ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad); +- blob_struct_v = ceph_decode_8(&tp); +- new_secret_id = ceph_decode_64(&tp); +- ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend); +- if (ret) ++ tp = ticket_buf; ++ dlen = ceph_decode_32(&tp); ++ } else { ++ /* unencrypted */ ++ ceph_decode_32_safe(p, end, dlen, bad); ++ ticket_buf = kmalloc(dlen, GFP_NOFS); ++ if (!ticket_buf) { ++ ret = -ENOMEM; + goto out; +- +- /* all is well, update our ticket */ +- ceph_crypto_key_destroy(&th->session_key); +- if (th->ticket_blob) +- ceph_buffer_put(th->ticket_blob); +- th->session_key = new_session_key; +- th->ticket_blob = new_ticket_blob; +- th->validity = new_validity; +- th->secret_id = new_secret_id; +- th->expires = new_expires; +- th->renew_after = new_renew_after; +- dout(" got ticket service %d (%s) secret_id %lld len %d\n", +- type, ceph_entity_type_name(type), th->secret_id, +- (int)th->ticket_blob->vec.iov_len); +- xi->have_keys |= th->service; ++ } ++ tp = ticket_buf; ++ ceph_decode_need(p, end, dlen, bad); ++ ceph_decode_copy(p, ticket_buf, dlen); + } ++ tpend = tp + dlen; ++ dout(" ticket blob is %d bytes\n", dlen); ++ ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad); ++ blob_struct_v = ceph_decode_8(&tp); ++ new_secret_id = ceph_decode_64(&tp); ++ ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend); ++ if (ret) ++ goto out; ++ ++ /* all is well, update our ticket */ ++ ceph_crypto_key_destroy(&th->session_key); ++ if (th->ticket_blob) ++ ceph_buffer_put(th->ticket_blob); ++ th->session_key = new_session_key; ++ th->ticket_blob = new_ticket_blob; ++ th->validity = new_validity; ++ th->secret_id = new_secret_id; ++ th->expires = new_expires; ++ th->renew_after = new_renew_after; ++ dout(" got ticket service %d (%s) secret_id %lld len %d\n", ++ type, ceph_entity_type_name(type), th->secret_id, ++ (int)th->ticket_blob->vec.iov_len); ++ xi->have_keys |= th->service; + +- ret = 0; + out: + kfree(ticket_buf); +-out_dbuf: + kfree(dbuf); + return ret; + +@@ -270,6 +255,34 @@ bad: + goto out; + } + ++static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac, ++ struct ceph_crypto_key *secret, ++ void *buf, void *end) ++{ ++ void *p = buf; ++ u8 reply_struct_v; ++ u32 num; ++ int ret; ++ ++ ceph_decode_8_safe(&p, end, reply_struct_v, bad); ++ if (reply_struct_v != 1) ++ return -EINVAL; ++ ++ ceph_decode_32_safe(&p, end, num, bad); ++ dout("%d tickets\n", num); ++ ++ while (num--) { ++ ret = process_one_ticket(ac, secret, &p, end); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++ ++bad: ++ return -EINVAL; ++} ++ + static int ceph_x_build_authorizer(struct ceph_auth_client *ac, + struct ceph_x_ticket_handler *th, + struct ceph_x_authorizer *au) +@@ -583,13 +596,14 @@ static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac, + struct ceph_x_ticket_handler *th; + int ret = 0; + struct ceph_x_authorize_reply reply; ++ void *preply = &reply; + void *p = au->reply_buf; + void *end = p + sizeof(au->reply_buf); + + th = get_ticket_handler(ac, au->service); + if (IS_ERR(th)) + return PTR_ERR(th); +- ret = ceph_x_decrypt(&th->session_key, &p, end, &reply, sizeof(reply)); ++ ret = ceph_x_decrypt(&th->session_key, &p, end, &preply, sizeof(reply)); + if (ret < 0) + return ret; + if (ret != sizeof(reply)) +diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c +index 988721a629eb..0a31298737ac 100644 +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -900,7 +900,7 @@ static void ceph_msg_data_pages_cursor_init(struct ceph_msg_data_cursor *cursor, + BUG_ON(page_count > (int)USHRT_MAX); + cursor->page_count = (unsigned short)page_count; + BUG_ON(length > SIZE_MAX - cursor->page_offset); +- cursor->last_piece = (size_t)cursor->page_offset + length <= PAGE_SIZE; ++ cursor->last_piece = cursor->page_offset + cursor->resid <= PAGE_SIZE; + } + + static struct page * +diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c +index 2ac9ef35110b..dbcbf5a4707f 100644 +--- a/net/ceph/mon_client.c ++++ b/net/ceph/mon_client.c +@@ -1041,7 +1041,15 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con, + if (!m) { + pr_info("alloc_msg unknown type %d\n", type); + *skip = 1; ++ } else if (front_len > m->front_alloc_len) { ++ pr_warning("mon_alloc_msg front %d > prealloc %d (%u#%llu)\n", ++ front_len, m->front_alloc_len, ++ (unsigned int)con->peer_name.type, ++ le64_to_cpu(con->peer_name.num)); ++ ceph_msg_put(m); ++ m = ceph_msg_new(type, front_len, GFP_NOFS, false); + } ++ + return m; + } + +diff --git a/security/commoncap.c b/security/commoncap.c +index b9d613e0ef14..963dc5981661 100644 +--- a/security/commoncap.c ++++ b/security/commoncap.c +@@ -421,6 +421,9 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data + cpu_caps->inheritable.cap[i] = le32_to_cpu(caps.data[i].inheritable); + } + ++ cpu_caps->permitted.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; ++ cpu_caps->inheritable.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; ++ + return 0; + } + +diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c +index a3881c4381c9..bcf591373a7a 100644 +--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c ++++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c +@@ -290,19 +290,19 @@ static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, + unsigned int sample_size = runtime->sample_bits / 8; + void *buf = runtime->dma_area; + struct bf5xx_i2s_pcm_data *dma_data; +- unsigned int offset, size; ++ unsigned int offset, samples; + + dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + + if (dma_data->tdm_mode) { + offset = pos * 8 * sample_size; +- size = count * 8 * sample_size; ++ samples = count * 8; + } else { + offset = frames_to_bytes(runtime, pos); +- size = frames_to_bytes(runtime, count); ++ samples = count * runtime->channels; + } + +- snd_pcm_format_set_silence(runtime->format, buf + offset, size); ++ snd_pcm_format_set_silence(runtime->format, buf + offset, samples); + + return 0; + } +diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c +index d71c59cf7bdd..370b742117ef 100644 +--- a/sound/soc/codecs/adau1701.c ++++ b/sound/soc/codecs/adau1701.c +@@ -230,8 +230,10 @@ static int adau1701_reg_read(void *context, unsigned int reg, + + *value = 0; + +- for (i = 0; i < size; i++) +- *value |= recv_buf[i] << (i * 8); ++ for (i = 0; i < size; i++) { ++ *value <<= 8; ++ *value |= recv_buf[i]; ++ } + + return 0; + } +diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c +index b3f7c9026a29..ddfb0fddd030 100644 +--- a/sound/soc/codecs/max98090.c ++++ b/sound/soc/codecs/max98090.c +@@ -2250,7 +2250,7 @@ static int max98090_probe(struct snd_soc_codec *codec) + /* Register for interrupts */ + dev_dbg(codec->dev, "irq = %d\n", max98090->irq); + +- ret = request_threaded_irq(max98090->irq, NULL, ++ ret = devm_request_threaded_irq(codec->dev, max98090->irq, NULL, + max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "max98090_interrupt", codec); + if (ret < 0) { +diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c +index 886924934aa5..5cb515b08a32 100644 +--- a/sound/soc/codecs/rt5640.c ++++ b/sound/soc/codecs/rt5640.c +@@ -2071,6 +2071,7 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5640 = { + static const struct regmap_config rt5640_regmap = { + .reg_bits = 8, + .val_bits = 16, ++ .use_single_rw = true, + + .max_register = RT5640_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5640_ranges) * + RT5640_PR_SPACING), +diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c +index adb72063d44e..d98e52f647d2 100644 +--- a/sound/soc/codecs/wm8994.c ++++ b/sound/soc/codecs/wm8994.c +@@ -3497,6 +3497,7 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data) + return IRQ_HANDLED; + } + ++/* Should be called with accdet_lock held */ + static void wm1811_micd_stop(struct snd_soc_codec *codec) + { + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); +@@ -3504,14 +3505,10 @@ static void wm1811_micd_stop(struct snd_soc_codec *codec) + if (!wm8994->jackdet) + return; + +- mutex_lock(&wm8994->accdet_lock); +- + snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, WM8958_MICD_ENA, 0); + + wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK); + +- mutex_unlock(&wm8994->accdet_lock); +- + if (wm8994->wm8994->pdata.jd_ext_cap) + snd_soc_dapm_disable_pin(&codec->dapm, + "MICBIAS2"); +@@ -3552,10 +3549,10 @@ static void wm8958_open_circuit_work(struct work_struct *work) + open_circuit_work.work); + struct device *dev = wm8994->wm8994->dev; + +- wm1811_micd_stop(wm8994->hubs.codec); +- + mutex_lock(&wm8994->accdet_lock); + ++ wm1811_micd_stop(wm8994->hubs.codec); ++ + dev_dbg(dev, "Reporting open circuit\n"); + + wm8994->jack_mic = false; +diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c +index 444626fcab40..53c03aff762e 100644 +--- a/sound/soc/codecs/wm_adsp.c ++++ b/sound/soc/codecs/wm_adsp.c +@@ -1745,3 +1745,5 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs) + return 0; + } + EXPORT_SYMBOL_GPL(wm_adsp2_init); ++ ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c +index a3119a00d8fa..6c6b35e471c8 100644 +--- a/sound/soc/pxa/pxa-ssp.c ++++ b/sound/soc/pxa/pxa-ssp.c +@@ -725,7 +725,8 @@ static int pxa_ssp_probe(struct snd_soc_dai *dai) + ssp_handle = of_parse_phandle(dev->of_node, "port", 0); + if (!ssp_handle) { + dev_err(dev, "unable to get 'port' phandle\n"); +- return -ENODEV; ++ ret = -ENODEV; ++ goto err_priv; + } + + priv->ssp = pxa_ssp_request_of(ssp_handle, "SoC audio"); +@@ -766,9 +767,7 @@ static int pxa_ssp_remove(struct snd_soc_dai *dai) + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) + +-#define PXA_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ +- SNDRV_PCM_FMTBIT_S24_LE | \ +- SNDRV_PCM_FMTBIT_S32_LE) ++#define PXA_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) + + static const struct snd_soc_dai_ops pxa_ssp_dai_ops = { + .startup = pxa_ssp_startup, +diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c +index 0a9b44c940ce..5dae66002a11 100644 +--- a/sound/soc/samsung/i2s.c ++++ b/sound/soc/samsung/i2s.c +@@ -915,11 +915,9 @@ static int i2s_suspend(struct snd_soc_dai *dai) + { + struct i2s_dai *i2s = to_info(dai); + +- if (dai->active) { +- i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); +- i2s->suspend_i2scon = readl(i2s->addr + I2SCON); +- i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR); +- } ++ i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); ++ i2s->suspend_i2scon = readl(i2s->addr + I2SCON); ++ i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR); + + return 0; + } +@@ -928,11 +926,9 @@ static int i2s_resume(struct snd_soc_dai *dai) + { + struct i2s_dai *i2s = to_info(dai); + +- if (dai->active) { +- writel(i2s->suspend_i2scon, i2s->addr + I2SCON); +- writel(i2s->suspend_i2smod, i2s->addr + I2SMOD); +- writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR); +- } ++ writel(i2s->suspend_i2scon, i2s->addr + I2SCON); ++ writel(i2s->suspend_i2smod, i2s->addr + I2SMOD); ++ writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR); + + return 0; + } +diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c +index 47e1ce771e65..02733ded2cb1 100644 +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -2011,6 +2011,7 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card) + dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK); + } + ++ dpcm_path_put(&list); + capture: + /* skip if FE doesn't have capture capability */ + if (!fe->cpu_dai->driver->capture.channels_min) +diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile +index 32487ed18354..3d5979b23e50 100644 +--- a/tools/testing/selftests/Makefile ++++ b/tools/testing/selftests/Makefile +@@ -4,6 +4,7 @@ TARGETS += efivarfs + TARGETS += kcmp + TARGETS += memory-hotplug + TARGETS += mqueue ++TARGETS += mount + TARGETS += net + TARGETS += ptrace + TARGETS += timers +diff --git a/tools/testing/selftests/mount/Makefile b/tools/testing/selftests/mount/Makefile +new file mode 100644 +index 000000000000..337d853c2b72 +--- /dev/null ++++ b/tools/testing/selftests/mount/Makefile +@@ -0,0 +1,17 @@ ++# Makefile for mount selftests. ++ ++all: unprivileged-remount-test ++ ++unprivileged-remount-test: unprivileged-remount-test.c ++ gcc -Wall -O2 unprivileged-remount-test.c -o unprivileged-remount-test ++ ++# Allow specific tests to be selected. ++test_unprivileged_remount: unprivileged-remount-test ++ @if [ -f /proc/self/uid_map ] ; then ./unprivileged-remount-test ; fi ++ ++run_tests: all test_unprivileged_remount ++ ++clean: ++ rm -f unprivileged-remount-test ++ ++.PHONY: all test_unprivileged_remount +diff --git a/tools/testing/selftests/mount/unprivileged-remount-test.c b/tools/testing/selftests/mount/unprivileged-remount-test.c +new file mode 100644 +index 000000000000..1b3ff2fda4d0 +--- /dev/null ++++ b/tools/testing/selftests/mount/unprivileged-remount-test.c +@@ -0,0 +1,242 @@ ++#define _GNU_SOURCE ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifndef CLONE_NEWNS ++# define CLONE_NEWNS 0x00020000 ++#endif ++#ifndef CLONE_NEWUTS ++# define CLONE_NEWUTS 0x04000000 ++#endif ++#ifndef CLONE_NEWIPC ++# define CLONE_NEWIPC 0x08000000 ++#endif ++#ifndef CLONE_NEWNET ++# define CLONE_NEWNET 0x40000000 ++#endif ++#ifndef CLONE_NEWUSER ++# define CLONE_NEWUSER 0x10000000 ++#endif ++#ifndef CLONE_NEWPID ++# define CLONE_NEWPID 0x20000000 ++#endif ++ ++#ifndef MS_RELATIME ++#define MS_RELATIME (1 << 21) ++#endif ++#ifndef MS_STRICTATIME ++#define MS_STRICTATIME (1 << 24) ++#endif ++ ++static void die(char *fmt, ...) ++{ ++ va_list ap; ++ va_start(ap, fmt); ++ vfprintf(stderr, fmt, ap); ++ va_end(ap); ++ exit(EXIT_FAILURE); ++} ++ ++static void write_file(char *filename, char *fmt, ...) ++{ ++ char buf[4096]; ++ int fd; ++ ssize_t written; ++ int buf_len; ++ va_list ap; ++ ++ va_start(ap, fmt); ++ buf_len = vsnprintf(buf, sizeof(buf), fmt, ap); ++ va_end(ap); ++ if (buf_len < 0) { ++ die("vsnprintf failed: %s\n", ++ strerror(errno)); ++ } ++ if (buf_len >= sizeof(buf)) { ++ die("vsnprintf output truncated\n"); ++ } ++ ++ fd = open(filename, O_WRONLY); ++ if (fd < 0) { ++ die("open of %s failed: %s\n", ++ filename, strerror(errno)); ++ } ++ written = write(fd, buf, buf_len); ++ if (written != buf_len) { ++ if (written >= 0) { ++ die("short write to %s\n", filename); ++ } else { ++ die("write to %s failed: %s\n", ++ filename, strerror(errno)); ++ } ++ } ++ if (close(fd) != 0) { ++ die("close of %s failed: %s\n", ++ filename, strerror(errno)); ++ } ++} ++ ++static void create_and_enter_userns(void) ++{ ++ uid_t uid; ++ gid_t gid; ++ ++ uid = getuid(); ++ gid = getgid(); ++ ++ if (unshare(CLONE_NEWUSER) !=0) { ++ die("unshare(CLONE_NEWUSER) failed: %s\n", ++ strerror(errno)); ++ } ++ ++ write_file("/proc/self/uid_map", "0 %d 1", uid); ++ write_file("/proc/self/gid_map", "0 %d 1", gid); ++ ++ if (setgroups(0, NULL) != 0) { ++ die("setgroups failed: %s\n", ++ strerror(errno)); ++ } ++ if (setgid(0) != 0) { ++ die ("setgid(0) failed %s\n", ++ strerror(errno)); ++ } ++ if (setuid(0) != 0) { ++ die("setuid(0) failed %s\n", ++ strerror(errno)); ++ } ++} ++ ++static ++bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags) ++{ ++ pid_t child; ++ ++ child = fork(); ++ if (child == -1) { ++ die("fork failed: %s\n", ++ strerror(errno)); ++ } ++ if (child != 0) { /* parent */ ++ pid_t pid; ++ int status; ++ pid = waitpid(child, &status, 0); ++ if (pid == -1) { ++ die("waitpid failed: %s\n", ++ strerror(errno)); ++ } ++ if (pid != child) { ++ die("waited for %d got %d\n", ++ child, pid); ++ } ++ if (!WIFEXITED(status)) { ++ die("child did not terminate cleanly\n"); ++ } ++ return WEXITSTATUS(status) == EXIT_SUCCESS ? true : false; ++ } ++ ++ create_and_enter_userns(); ++ if (unshare(CLONE_NEWNS) != 0) { ++ die("unshare(CLONE_NEWNS) failed: %s\n", ++ strerror(errno)); ++ } ++ ++ if (mount("testing", "/tmp", "ramfs", mount_flags, NULL) != 0) { ++ die("mount of /tmp failed: %s\n", ++ strerror(errno)); ++ } ++ ++ create_and_enter_userns(); ++ ++ if (unshare(CLONE_NEWNS) != 0) { ++ die("unshare(CLONE_NEWNS) failed: %s\n", ++ strerror(errno)); ++ } ++ ++ if (mount("/tmp", "/tmp", "none", ++ MS_REMOUNT | MS_BIND | remount_flags, NULL) != 0) { ++ /* system("cat /proc/self/mounts"); */ ++ die("remount of /tmp failed: %s\n", ++ strerror(errno)); ++ } ++ ++ if (mount("/tmp", "/tmp", "none", ++ MS_REMOUNT | MS_BIND | invalid_flags, NULL) == 0) { ++ /* system("cat /proc/self/mounts"); */ ++ die("remount of /tmp with invalid flags " ++ "succeeded unexpectedly\n"); ++ } ++ exit(EXIT_SUCCESS); ++} ++ ++static bool test_unpriv_remount_simple(int mount_flags) ++{ ++ return test_unpriv_remount(mount_flags, mount_flags, 0); ++} ++ ++static bool test_unpriv_remount_atime(int mount_flags, int invalid_flags) ++{ ++ return test_unpriv_remount(mount_flags, mount_flags, invalid_flags); ++} ++ ++int main(int argc, char **argv) ++{ ++ if (!test_unpriv_remount_simple(MS_RDONLY|MS_NODEV)) { ++ die("MS_RDONLY malfunctions\n"); ++ } ++ if (!test_unpriv_remount_simple(MS_NODEV)) { ++ die("MS_NODEV malfunctions\n"); ++ } ++ if (!test_unpriv_remount_simple(MS_NOSUID|MS_NODEV)) { ++ die("MS_NOSUID malfunctions\n"); ++ } ++ if (!test_unpriv_remount_simple(MS_NOEXEC|MS_NODEV)) { ++ die("MS_NOEXEC malfunctions\n"); ++ } ++ if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODEV, ++ MS_NOATIME|MS_NODEV)) ++ { ++ die("MS_RELATIME malfunctions\n"); ++ } ++ if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODEV, ++ MS_NOATIME|MS_NODEV)) ++ { ++ die("MS_STRICTATIME malfunctions\n"); ++ } ++ if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODEV, ++ MS_STRICTATIME|MS_NODEV)) ++ { ++ die("MS_RELATIME malfunctions\n"); ++ } ++ if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME|MS_NODEV, ++ MS_NOATIME|MS_NODEV)) ++ { ++ die("MS_RELATIME malfunctions\n"); ++ } ++ if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME|MS_NODEV, ++ MS_NOATIME|MS_NODEV)) ++ { ++ die("MS_RELATIME malfunctions\n"); ++ } ++ if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME|MS_NODEV, ++ MS_STRICTATIME|MS_NODEV)) ++ { ++ die("MS_RELATIME malfunctions\n"); ++ } ++ if (!test_unpriv_remount(MS_STRICTATIME|MS_NODEV, MS_NODEV, ++ MS_NOATIME|MS_NODEV)) ++ { ++ die("Default atime malfunctions\n"); ++ } ++ return EXIT_SUCCESS; ++} diff --git a/patch/kernel/cubox-default/patch-3.14.19-20.patch b/patch/kernel/cubox-default/patch-3.14.19-20.patch new file mode 100644 index 000000000..863b597c8 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.19-20.patch @@ -0,0 +1,7396 @@ +diff --git a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +index 1486497a24c1..ce6a1a072028 100644 +--- a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt ++++ b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +@@ -4,11 +4,13 @@ Specifying interrupt information for devices + 1) Interrupt client nodes + ------------------------- + +-Nodes that describe devices which generate interrupts must contain an either an +-"interrupts" property or an "interrupts-extended" property. These properties +-contain a list of interrupt specifiers, one per output interrupt. The format of +-the interrupt specifier is determined by the interrupt controller to which the +-interrupts are routed; see section 2 below for details. ++Nodes that describe devices which generate interrupts must contain an ++"interrupts" property, an "interrupts-extended" property, or both. If both are ++present, the latter should take precedence; the former may be provided simply ++for compatibility with software that does not recognize the latter. These ++properties contain a list of interrupt specifiers, one per output interrupt. The ++format of the interrupt specifier is determined by the interrupt controller to ++which the interrupts are routed; see section 2 below for details. + + Example: + interrupt-parent = <&intc1>; +diff --git a/Makefile b/Makefile +index b1746b486646..beb7e6f0803b 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 19 ++SUBLEVEL = 20 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts +index 904dcf5973f3..9381754b35cc 100644 +--- a/arch/arm/boot/dts/dra7-evm.dts ++++ b/arch/arm/boot/dts/dra7-evm.dts +@@ -50,13 +50,13 @@ + + mcspi1_pins: pinmux_mcspi1_pins { + pinctrl-single,pins = < +- 0x3a4 (PIN_INPUT | MUX_MODE0) /* spi2_clk */ +- 0x3a8 (PIN_INPUT | MUX_MODE0) /* spi2_d1 */ +- 0x3ac (PIN_INPUT | MUX_MODE0) /* spi2_d0 */ +- 0x3b0 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs0 */ +- 0x3b4 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs1 */ +- 0x3b8 (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs2 */ +- 0x3bc (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs3 */ ++ 0x3a4 (PIN_INPUT | MUX_MODE0) /* spi1_sclk */ ++ 0x3a8 (PIN_INPUT | MUX_MODE0) /* spi1_d1 */ ++ 0x3ac (PIN_INPUT | MUX_MODE0) /* spi1_d0 */ ++ 0x3b0 (PIN_INPUT_SLEW | MUX_MODE0) /* spi1_cs0 */ ++ 0x3b4 (PIN_INPUT_SLEW | MUX_MODE0) /* spi1_cs1 */ ++ 0x3b8 (PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs2.hdmi1_hpd */ ++ 0x3bc (PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs3.hdmi1_cec */ + >; + }; + +diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi +index 1fd75aa4639d..767f0e376f4d 100644 +--- a/arch/arm/boot/dts/dra7.dtsi ++++ b/arch/arm/boot/dts/dra7.dtsi +@@ -178,7 +178,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + gpio2: gpio@48055000 { +@@ -189,7 +189,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + gpio3: gpio@48057000 { +@@ -200,7 +200,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + gpio4: gpio@48059000 { +@@ -211,7 +211,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + gpio5: gpio@4805b000 { +@@ -222,7 +222,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + gpio6: gpio@4805d000 { +@@ -233,7 +233,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + gpio7: gpio@48051000 { +@@ -244,7 +244,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + gpio8: gpio@48053000 { +@@ -255,7 +255,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + uart1: serial@4806a000 { +diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h +index 83259b873333..5f833f7adba1 100644 +--- a/arch/arm/include/asm/tls.h ++++ b/arch/arm/include/asm/tls.h +@@ -1,6 +1,9 @@ + #ifndef __ASMARM_TLS_H + #define __ASMARM_TLS_H + ++#include ++#include ++ + #ifdef __ASSEMBLY__ + #include + .macro switch_tls_none, base, tp, tpuser, tmp1, tmp2 +@@ -50,6 +53,49 @@ + #endif + + #ifndef __ASSEMBLY__ ++ ++static inline void set_tls(unsigned long val) ++{ ++ struct thread_info *thread; ++ ++ thread = current_thread_info(); ++ ++ thread->tp_value[0] = val; ++ ++ /* ++ * This code runs with preemption enabled and therefore must ++ * be reentrant with respect to switch_tls. ++ * ++ * We need to ensure ordering between the shadow state and the ++ * hardware state, so that we don't corrupt the hardware state ++ * with a stale shadow state during context switch. ++ * ++ * If we're preempted here, switch_tls will load TPIDRURO from ++ * thread_info upon resuming execution and the following mcr ++ * is merely redundant. ++ */ ++ barrier(); ++ ++ if (!tls_emu) { ++ if (has_tls_reg) { ++ asm("mcr p15, 0, %0, c13, c0, 3" ++ : : "r" (val)); ++ } else { ++#ifdef CONFIG_KUSER_HELPERS ++ /* ++ * User space must never try to access this ++ * directly. Expect your app to break ++ * eventually if you do so. The user helper ++ * at 0xffff0fe0 must be used instead. (see ++ * entry-armv.S for details) ++ */ ++ *((unsigned int *)0xffff0ff0) = val; ++#endif ++ } ++ ++ } ++} ++ + static inline unsigned long get_tpuser(void) + { + unsigned long reg = 0; +@@ -59,5 +105,23 @@ static inline unsigned long get_tpuser(void) + + return reg; + } ++ ++static inline void set_tpuser(unsigned long val) ++{ ++ /* Since TPIDRURW is fully context-switched (unlike TPIDRURO), ++ * we need not update thread_info. ++ */ ++ if (has_tls_reg && !tls_emu) { ++ asm("mcr p15, 0, %0, c13, c0, 2" ++ : : "r" (val)); ++ } ++} ++ ++static inline void flush_tls(void) ++{ ++ set_tls(0); ++ set_tpuser(0); ++} ++ + #endif + #endif /* __ASMARM_TLS_H */ +diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c +index 9723d17b8f38..1e782bdeee49 100644 +--- a/arch/arm/kernel/irq.c ++++ b/arch/arm/kernel/irq.c +@@ -163,7 +163,7 @@ static bool migrate_one_irq(struct irq_desc *desc) + c = irq_data_get_irq_chip(d); + if (!c->irq_set_affinity) + pr_debug("IRQ%u: unable to set affinity\n", d->irq); +- else if (c->irq_set_affinity(d, affinity, true) == IRQ_SET_MASK_OK && ret) ++ else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret) + cpumask_copy(d->affinity, affinity); + + return ret; +diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c +index 92f7b15dd221..5f6e650ec9ab 100644 +--- a/arch/arm/kernel/process.c ++++ b/arch/arm/kernel/process.c +@@ -334,6 +334,8 @@ void flush_thread(void) + memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); + memset(&thread->fpstate, 0, sizeof(union fp_state)); + ++ flush_tls(); ++ + thread_notify(THREAD_NOTIFY_FLUSH, thread); + } + +diff --git a/arch/arm/kernel/thumbee.c b/arch/arm/kernel/thumbee.c +index 7b8403b76666..80f0d69205e7 100644 +--- a/arch/arm/kernel/thumbee.c ++++ b/arch/arm/kernel/thumbee.c +@@ -45,7 +45,7 @@ static int thumbee_notifier(struct notifier_block *self, unsigned long cmd, void + + switch (cmd) { + case THREAD_NOTIFY_FLUSH: +- thread->thumbee_state = 0; ++ teehbr_write(0); + break; + case THREAD_NOTIFY_SWITCH: + current_thread_info()->thumbee_state = teehbr_read(); +diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c +index 172ee18ff124..9265b8bb529a 100644 +--- a/arch/arm/kernel/traps.c ++++ b/arch/arm/kernel/traps.c +@@ -578,7 +578,6 @@ do_cache_op(unsigned long start, unsigned long end, int flags) + #define NR(x) ((__ARM_NR_##x) - __ARM_NR_BASE) + asmlinkage int arm_syscall(int no, struct pt_regs *regs) + { +- struct thread_info *thread = current_thread_info(); + siginfo_t info; + + if ((no >> 16) != (__ARM_NR_BASE>> 16)) +@@ -629,21 +628,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) + return regs->ARM_r0; + + case NR(set_tls): +- thread->tp_value[0] = regs->ARM_r0; +- if (tls_emu) +- return 0; +- if (has_tls_reg) { +- asm ("mcr p15, 0, %0, c13, c0, 3" +- : : "r" (regs->ARM_r0)); +- } else { +- /* +- * User space must never try to access this directly. +- * Expect your app to break eventually if you do so. +- * The user helper at 0xffff0fe0 must be used instead. +- * (see entry-armv.S for details) +- */ +- *((unsigned int *)0xffff0ff0) = regs->ARM_r0; +- } ++ set_tls(regs->ARM_r0); + return 0; + + #ifdef CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG +diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c +index 0de91fc6de0f..ec4fa868a7ba 100644 +--- a/arch/arm/kvm/handle_exit.c ++++ b/arch/arm/kvm/handle_exit.c +@@ -89,6 +89,8 @@ static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run) + else + kvm_vcpu_block(vcpu); + ++ kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); ++ + return 1; + } + +diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S +index 1b9844d369cc..ee4f7447a1d3 100644 +--- a/arch/arm/kvm/init.S ++++ b/arch/arm/kvm/init.S +@@ -98,6 +98,10 @@ __do_hyp_init: + mrc p15, 0, r0, c10, c2, 1 + mcr p15, 4, r0, c10, c2, 1 + ++ @ Invalidate the stale TLBs from Bootloader ++ mcr p15, 4, r0, c8, c7, 0 @ TLBIALLH ++ dsb ish ++ + @ Set the HSCTLR to: + @ - ARM/THUMB exceptions: Kernel config (Thumb-2 kernel) + @ - Endianness: Kernel config +diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c +index c914b0052fb9..4551efd28f8d 100644 +--- a/arch/arm/mach-omap2/omap_hwmod.c ++++ b/arch/arm/mach-omap2/omap_hwmod.c +@@ -3349,6 +3349,9 @@ int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois) + if (!ois) + return 0; + ++ if (ois[0] == NULL) /* Empty list */ ++ return 0; ++ + if (!linkspace) { + if (_alloc_linkspace(ois)) { + pr_err("omap_hwmod: could not allocate link space\n"); +diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +index 810c205d668b..2e35ff99f60e 100644 +--- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c ++++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +@@ -35,6 +35,7 @@ + #include "i2c.h" + #include "mmc.h" + #include "wd_timer.h" ++#include "soc.h" + + /* Base offset for all DRA7XX interrupts external to MPUSS */ + #define DRA7XX_IRQ_GIC_START 32 +@@ -2707,7 +2708,6 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = { + &dra7xx_l4_per3__usb_otg_ss1, + &dra7xx_l4_per3__usb_otg_ss2, + &dra7xx_l4_per3__usb_otg_ss3, +- &dra7xx_l4_per3__usb_otg_ss4, + &dra7xx_l3_main_1__vcp1, + &dra7xx_l4_per2__vcp1, + &dra7xx_l3_main_1__vcp2, +@@ -2716,8 +2716,26 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = { + NULL, + }; + ++static struct omap_hwmod_ocp_if *dra74x_hwmod_ocp_ifs[] __initdata = { ++ &dra7xx_l4_per3__usb_otg_ss4, ++ NULL, ++}; ++ ++static struct omap_hwmod_ocp_if *dra72x_hwmod_ocp_ifs[] __initdata = { ++ NULL, ++}; ++ + int __init dra7xx_hwmod_init(void) + { ++ int ret; ++ + omap_hwmod_init(); +- return omap_hwmod_register_links(dra7xx_hwmod_ocp_ifs); ++ ret = omap_hwmod_register_links(dra7xx_hwmod_ocp_ifs); ++ ++ if (!ret && soc_is_dra74x()) ++ return omap_hwmod_register_links(dra74x_hwmod_ocp_ifs); ++ else if (!ret && soc_is_dra72x()) ++ return omap_hwmod_register_links(dra72x_hwmod_ocp_ifs); ++ ++ return ret; + } +diff --git a/arch/arm/mach-omap2/soc.h b/arch/arm/mach-omap2/soc.h +index 076bd90a6ce0..8a9be09d9f38 100644 +--- a/arch/arm/mach-omap2/soc.h ++++ b/arch/arm/mach-omap2/soc.h +@@ -245,6 +245,8 @@ IS_AM_SUBCLASS(437x, 0x437) + #define soc_is_omap54xx() 0 + #define soc_is_omap543x() 0 + #define soc_is_dra7xx() 0 ++#define soc_is_dra74x() 0 ++#define soc_is_dra72x() 0 + + #if defined(MULTI_OMAP2) + # if defined(CONFIG_ARCH_OMAP2) +@@ -393,7 +395,11 @@ IS_OMAP_TYPE(3430, 0x3430) + + #if defined(CONFIG_SOC_DRA7XX) + #undef soc_is_dra7xx ++#undef soc_is_dra74x ++#undef soc_is_dra72x + #define soc_is_dra7xx() (of_machine_is_compatible("ti,dra7")) ++#define soc_is_dra74x() (of_machine_is_compatible("ti,dra74")) ++#define soc_is_dra72x() (of_machine_is_compatible("ti,dra72")) + #endif + + /* Various silicon revisions for omap2 */ +diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S +index 3815a8262af0..8c48c5c22a33 100644 +--- a/arch/arm/mm/abort-ev6.S ++++ b/arch/arm/mm/abort-ev6.S +@@ -17,12 +17,6 @@ + */ + .align 5 + ENTRY(v6_early_abort) +-#ifdef CONFIG_CPU_V6 +- sub r1, sp, #4 @ Get unused stack location +- strex r0, r1, [r1] @ Clear the exclusive monitor +-#elif defined(CONFIG_CPU_32v6K) +- clrex +-#endif + mrc p15, 0, r1, c5, c0, 0 @ get FSR + mrc p15, 0, r0, c6, c0, 0 @ get FAR + /* +diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S +index 703375277ba6..4812ad054214 100644 +--- a/arch/arm/mm/abort-ev7.S ++++ b/arch/arm/mm/abort-ev7.S +@@ -13,12 +13,6 @@ + */ + .align 5 + ENTRY(v7_early_abort) +- /* +- * The effect of data aborts on on the exclusive access monitor are +- * UNPREDICTABLE. Do a CLREX to clear the state +- */ +- clrex +- + mrc p15, 0, r1, c5, c0, 0 @ get FSR + mrc p15, 0, r0, c6, c0, 0 @ get FAR + +diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c +index 924036473b16..d301662b7b32 100644 +--- a/arch/arm/mm/alignment.c ++++ b/arch/arm/mm/alignment.c +@@ -40,6 +40,7 @@ + * This code is not portable to processors with late data abort handling. + */ + #define CODING_BITS(i) (i & 0x0e000000) ++#define COND_BITS(i) (i & 0xf0000000) + + #define LDST_I_BIT(i) (i & (1 << 26)) /* Immediate constant */ + #define LDST_P_BIT(i) (i & (1 << 24)) /* Preindex */ +@@ -817,6 +818,8 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) + break; + + case 0x04000000: /* ldr or str immediate */ ++ if (COND_BITS(instr) == 0xf0000000) /* NEON VLDn, VSTn */ ++ goto bad; + offset.un = OFFSET_BITS(instr); + handler = do_alignment_ldrstr; + break; +diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h +index d064047612b1..52b484b6aa1a 100644 +--- a/arch/arm64/include/asm/hw_breakpoint.h ++++ b/arch/arm64/include/asm/hw_breakpoint.h +@@ -79,7 +79,6 @@ static inline void decode_ctrl_reg(u32 reg, + */ + #define ARM_MAX_BRP 16 + #define ARM_MAX_WRP 16 +-#define ARM_MAX_HBP_SLOTS (ARM_MAX_BRP + ARM_MAX_WRP) + + /* Virtual debug register bases. */ + #define AARCH64_DBG_REG_BVR 0 +diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c +index 0f08dfd69ebc..dfa6e3e74fdd 100644 +--- a/arch/arm64/kernel/irq.c ++++ b/arch/arm64/kernel/irq.c +@@ -97,19 +97,15 @@ static bool migrate_one_irq(struct irq_desc *desc) + if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity)) + return false; + +- if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) ++ if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { ++ affinity = cpu_online_mask; + ret = true; ++ } + +- /* +- * when using forced irq_set_affinity we must ensure that the cpu +- * being offlined is not present in the affinity mask, it may be +- * selected as the target CPU otherwise +- */ +- affinity = cpu_online_mask; + c = irq_data_get_irq_chip(d); + if (!c->irq_set_affinity) + pr_debug("IRQ%u: unable to set affinity\n", d->irq); +- else if (c->irq_set_affinity(d, affinity, true) == IRQ_SET_MASK_OK && ret) ++ else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret) + cpumask_copy(d->affinity, affinity); + + return ret; +diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c +index 1c0a9be2ffa8..6e7e579c629d 100644 +--- a/arch/arm64/kernel/process.c ++++ b/arch/arm64/kernel/process.c +@@ -187,9 +187,27 @@ void exit_thread(void) + { + } + ++static void tls_thread_flush(void) ++{ ++ asm ("msr tpidr_el0, xzr"); ++ ++ if (is_compat_task()) { ++ current->thread.tp_value = 0; ++ ++ /* ++ * We need to ensure ordering between the shadow state and the ++ * hardware state, so that we don't corrupt the hardware state ++ * with a stale shadow state during context switch. ++ */ ++ barrier(); ++ asm ("msr tpidrro_el0, xzr"); ++ } ++} ++ + void flush_thread(void) + { + fpsimd_flush_thread(); ++ tls_thread_flush(); + flush_ptrace_hw_breakpoint(current); + } + +diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c +index 7a50b86464cc..b1269dac1289 100644 +--- a/arch/arm64/kernel/ptrace.c ++++ b/arch/arm64/kernel/ptrace.c +@@ -81,7 +81,8 @@ static void ptrace_hbptriggered(struct perf_event *bp, + break; + } + } +- for (i = ARM_MAX_BRP; i < ARM_MAX_HBP_SLOTS && !bp; ++i) { ++ ++ for (i = 0; i < ARM_MAX_WRP; ++i) { + if (current->thread.debug.hbp_watch[i] == bp) { + info.si_errno = -((i << 1) + 1); + break; +diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c +index 26e9c4eeaba8..78039927c807 100644 +--- a/arch/arm64/kernel/sys_compat.c ++++ b/arch/arm64/kernel/sys_compat.c +@@ -79,6 +79,12 @@ long compat_arm_syscall(struct pt_regs *regs) + + case __ARM_NR_compat_set_tls: + current->thread.tp_value = regs->regs[0]; ++ ++ /* ++ * Protect against register corruption from context switch. ++ * See comment in tls_thread_flush. ++ */ ++ barrier(); + asm ("msr tpidrro_el0, %0" : : "r" (regs->regs[0])); + return 0; + +diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c +index 7bc41eab4c64..fd9aeba99683 100644 +--- a/arch/arm64/kvm/handle_exit.c ++++ b/arch/arm64/kvm/handle_exit.c +@@ -62,6 +62,8 @@ static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run) + else + kvm_vcpu_block(vcpu); + ++ kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); ++ + return 1; + } + +diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S +index 2b0244d65c16..12e26f358c31 100644 +--- a/arch/arm64/kvm/hyp-init.S ++++ b/arch/arm64/kvm/hyp-init.S +@@ -74,6 +74,10 @@ __do_hyp_init: + msr mair_el2, x4 + isb + ++ /* Invalidate the stale TLBs from Bootloader */ ++ tlbi alle2 ++ dsb sy ++ + mrs x4, sctlr_el2 + and x4, x4, #SCTLR_EL2_EE // preserve endianness of EL2 + ldr x5, =SCTLR_EL2_FLAGS +diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c +index c00c4ddf4514..5244cecf1e45 100644 +--- a/arch/mips/boot/compressed/decompress.c ++++ b/arch/mips/boot/compressed/decompress.c +@@ -13,6 +13,7 @@ + + #include + #include ++#include + + #include + +diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S +index 539b6294b613..8f89ff4ed524 100644 +--- a/arch/mips/kernel/mcount.S ++++ b/arch/mips/kernel/mcount.S +@@ -123,7 +123,11 @@ NESTED(_mcount, PT_SIZE, ra) + nop + #endif + b ftrace_stub ++#ifdef CONFIG_32BIT ++ addiu sp, sp, 8 ++#else + nop ++#endif + + static_trace: + MCOUNT_SAVE_REGS +@@ -133,6 +137,9 @@ static_trace: + move a1, AT /* arg2: parent's return address */ + + MCOUNT_RESTORE_REGS ++#ifdef CONFIG_32BIT ++ addiu sp, sp, 8 ++#endif + .globl ftrace_stub + ftrace_stub: + RETURN_BACK +@@ -177,6 +184,11 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra) + jal prepare_ftrace_return + nop + MCOUNT_RESTORE_REGS ++#ifndef CONFIG_DYNAMIC_FTRACE ++#ifdef CONFIG_32BIT ++ addiu sp, sp, 8 ++#endif ++#endif + RETURN_BACK + END(ftrace_graph_caller) + +diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile +index 7187664034c3..5db8882f732c 100644 +--- a/arch/parisc/Makefile ++++ b/arch/parisc/Makefile +@@ -48,7 +48,12 @@ cflags-y := -pipe + + # These flags should be implied by an hppa-linux configuration, but they + # are not in gcc 3.2. +-cflags-y += -mno-space-regs -mfast-indirect-calls ++cflags-y += -mno-space-regs ++ ++# -mfast-indirect-calls is only relevant for 32-bit kernels. ++ifndef CONFIG_64BIT ++cflags-y += -mfast-indirect-calls ++endif + + # Currently we save and restore fpregs on all kernel entry/interruption paths. + # If that gets optimized, we might need to disable the use of fpregs in the +diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S +index 838786011037..7ef22e3387e0 100644 +--- a/arch/parisc/kernel/syscall.S ++++ b/arch/parisc/kernel/syscall.S +@@ -74,7 +74,7 @@ ENTRY(linux_gateway_page) + /* ADDRESS 0xb0 to 0xb8, lws uses two insns for entry */ + /* Light-weight-syscall entry must always be located at 0xb0 */ + /* WARNING: Keep this number updated with table size changes */ +-#define __NR_lws_entries (2) ++#define __NR_lws_entries (3) + + lws_entry: + gate lws_start, %r0 /* increase privilege */ +@@ -502,7 +502,7 @@ lws_exit: + + + /*************************************************** +- Implementing CAS as an atomic operation: ++ Implementing 32bit CAS as an atomic operation: + + %r26 - Address to examine + %r25 - Old value to check (old) +@@ -659,6 +659,230 @@ cas_action: + ASM_EXCEPTIONTABLE_ENTRY(2b-linux_gateway_page, 3b-linux_gateway_page) + + ++ /*************************************************** ++ New CAS implementation which uses pointers and variable size ++ information. The value pointed by old and new MUST NOT change ++ while performing CAS. The lock only protect the value at %r26. ++ ++ %r26 - Address to examine ++ %r25 - Pointer to the value to check (old) ++ %r24 - Pointer to the value to set (new) ++ %r23 - Size of the variable (0/1/2/3 for 8/16/32/64 bit) ++ %r28 - Return non-zero on failure ++ %r21 - Kernel error code ++ ++ %r21 has the following meanings: ++ ++ EAGAIN - CAS is busy, ldcw failed, try again. ++ EFAULT - Read or write failed. ++ ++ Scratch: r20, r22, r28, r29, r1, fr4 (32bit for 64bit CAS only) ++ ++ ****************************************************/ ++ ++ /* ELF32 Process entry path */ ++lws_compare_and_swap_2: ++#ifdef CONFIG_64BIT ++ /* Clip the input registers */ ++ depdi 0, 31, 32, %r26 ++ depdi 0, 31, 32, %r25 ++ depdi 0, 31, 32, %r24 ++ depdi 0, 31, 32, %r23 ++#endif ++ ++ /* Check the validity of the size pointer */ ++ subi,>>= 4, %r23, %r0 ++ b,n lws_exit_nosys ++ ++ /* Jump to the functions which will load the old and new values into ++ registers depending on the their size */ ++ shlw %r23, 2, %r29 ++ blr %r29, %r0 ++ nop ++ ++ /* 8bit load */ ++4: ldb 0(%sr3,%r25), %r25 ++ b cas2_lock_start ++5: ldb 0(%sr3,%r24), %r24 ++ nop ++ nop ++ nop ++ nop ++ nop ++ ++ /* 16bit load */ ++6: ldh 0(%sr3,%r25), %r25 ++ b cas2_lock_start ++7: ldh 0(%sr3,%r24), %r24 ++ nop ++ nop ++ nop ++ nop ++ nop ++ ++ /* 32bit load */ ++8: ldw 0(%sr3,%r25), %r25 ++ b cas2_lock_start ++9: ldw 0(%sr3,%r24), %r24 ++ nop ++ nop ++ nop ++ nop ++ nop ++ ++ /* 64bit load */ ++#ifdef CONFIG_64BIT ++10: ldd 0(%sr3,%r25), %r25 ++11: ldd 0(%sr3,%r24), %r24 ++#else ++ /* Load new value into r22/r23 - high/low */ ++10: ldw 0(%sr3,%r25), %r22 ++11: ldw 4(%sr3,%r25), %r23 ++ /* Load new value into fr4 for atomic store later */ ++12: flddx 0(%sr3,%r24), %fr4 ++#endif ++ ++cas2_lock_start: ++ /* Load start of lock table */ ++ ldil L%lws_lock_start, %r20 ++ ldo R%lws_lock_start(%r20), %r28 ++ ++ /* Extract four bits from r26 and hash lock (Bits 4-7) */ ++ extru %r26, 27, 4, %r20 ++ ++ /* Find lock to use, the hash is either one of 0 to ++ 15, multiplied by 16 (keep it 16-byte aligned) ++ and add to the lock table offset. */ ++ shlw %r20, 4, %r20 ++ add %r20, %r28, %r20 ++ ++ rsm PSW_SM_I, %r0 /* Disable interrupts */ ++ /* COW breaks can cause contention on UP systems */ ++ LDCW 0(%sr2,%r20), %r28 /* Try to acquire the lock */ ++ cmpb,<>,n %r0, %r28, cas2_action /* Did we get it? */ ++cas2_wouldblock: ++ ldo 2(%r0), %r28 /* 2nd case */ ++ ssm PSW_SM_I, %r0 ++ b lws_exit /* Contended... */ ++ ldo -EAGAIN(%r0), %r21 /* Spin in userspace */ ++ ++ /* ++ prev = *addr; ++ if ( prev == old ) ++ *addr = new; ++ return prev; ++ */ ++ ++ /* NOTES: ++ This all works becuse intr_do_signal ++ and schedule both check the return iasq ++ and see that we are on the kernel page ++ so this process is never scheduled off ++ or is ever sent any signal of any sort, ++ thus it is wholly atomic from usrspaces ++ perspective ++ */ ++cas2_action: ++ /* Jump to the correct function */ ++ blr %r29, %r0 ++ /* Set %r28 as non-zero for now */ ++ ldo 1(%r0),%r28 ++ ++ /* 8bit CAS */ ++13: ldb,ma 0(%sr3,%r26), %r29 ++ sub,= %r29, %r25, %r0 ++ b,n cas2_end ++14: stb,ma %r24, 0(%sr3,%r26) ++ b cas2_end ++ copy %r0, %r28 ++ nop ++ nop ++ ++ /* 16bit CAS */ ++15: ldh,ma 0(%sr3,%r26), %r29 ++ sub,= %r29, %r25, %r0 ++ b,n cas2_end ++16: sth,ma %r24, 0(%sr3,%r26) ++ b cas2_end ++ copy %r0, %r28 ++ nop ++ nop ++ ++ /* 32bit CAS */ ++17: ldw,ma 0(%sr3,%r26), %r29 ++ sub,= %r29, %r25, %r0 ++ b,n cas2_end ++18: stw,ma %r24, 0(%sr3,%r26) ++ b cas2_end ++ copy %r0, %r28 ++ nop ++ nop ++ ++ /* 64bit CAS */ ++#ifdef CONFIG_64BIT ++19: ldd,ma 0(%sr3,%r26), %r29 ++ sub,= %r29, %r25, %r0 ++ b,n cas2_end ++20: std,ma %r24, 0(%sr3,%r26) ++ copy %r0, %r28 ++#else ++ /* Compare first word */ ++19: ldw,ma 0(%sr3,%r26), %r29 ++ sub,= %r29, %r22, %r0 ++ b,n cas2_end ++ /* Compare second word */ ++20: ldw,ma 4(%sr3,%r26), %r29 ++ sub,= %r29, %r23, %r0 ++ b,n cas2_end ++ /* Perform the store */ ++21: fstdx %fr4, 0(%sr3,%r26) ++ copy %r0, %r28 ++#endif ++ ++cas2_end: ++ /* Free lock */ ++ stw,ma %r20, 0(%sr2,%r20) ++ /* Enable interrupts */ ++ ssm PSW_SM_I, %r0 ++ /* Return to userspace, set no error */ ++ b lws_exit ++ copy %r0, %r21 ++ ++22: ++ /* Error occurred on load or store */ ++ /* Free lock */ ++ stw %r20, 0(%sr2,%r20) ++ ssm PSW_SM_I, %r0 ++ ldo 1(%r0),%r28 ++ b lws_exit ++ ldo -EFAULT(%r0),%r21 /* set errno */ ++ nop ++ nop ++ nop ++ ++ /* Exception table entries, for the load and store, return EFAULT. ++ Each of the entries must be relocated. */ ++ ASM_EXCEPTIONTABLE_ENTRY(4b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(5b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(6b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(7b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(8b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(9b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(10b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(11b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(13b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(14b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(15b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(16b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(17b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(18b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(19b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(20b-linux_gateway_page, 22b-linux_gateway_page) ++#ifndef CONFIG_64BIT ++ ASM_EXCEPTIONTABLE_ENTRY(12b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(21b-linux_gateway_page, 22b-linux_gateway_page) ++#endif ++ + /* Make sure nothing else is placed on this page */ + .align PAGE_SIZE + END(linux_gateway_page) +@@ -675,8 +899,9 @@ ENTRY(end_linux_gateway_page) + /* Light-weight-syscall table */ + /* Start of lws table. */ + ENTRY(lws_table) +- LWS_ENTRY(compare_and_swap32) /* 0 - ELF32 Atomic compare and swap */ +- LWS_ENTRY(compare_and_swap64) /* 1 - ELF64 Atomic compare and swap */ ++ LWS_ENTRY(compare_and_swap32) /* 0 - ELF32 Atomic 32bit CAS */ ++ LWS_ENTRY(compare_and_swap64) /* 1 - ELF64 Atomic 32bit CAS */ ++ LWS_ENTRY(compare_and_swap_2) /* 2 - ELF32 Atomic 64bit CAS */ + END(lws_table) + /* End of lws table */ + +diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h +index 279b80f3bb29..c0c61fa9cd9e 100644 +--- a/arch/powerpc/include/asm/ptrace.h ++++ b/arch/powerpc/include/asm/ptrace.h +@@ -47,6 +47,12 @@ + STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE) + #define STACK_FRAME_MARKER 12 + ++#if defined(_CALL_ELF) && _CALL_ELF == 2 ++#define STACK_FRAME_MIN_SIZE 32 ++#else ++#define STACK_FRAME_MIN_SIZE STACK_FRAME_OVERHEAD ++#endif ++ + /* Size of dummy stack frame allocated when calling signal handler. */ + #define __SIGNAL_FRAMESIZE 128 + #define __SIGNAL_FRAMESIZE32 64 +@@ -60,6 +66,7 @@ + #define STACK_FRAME_REGS_MARKER ASM_CONST(0x72656773) + #define STACK_INT_FRAME_SIZE (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD) + #define STACK_FRAME_MARKER 2 ++#define STACK_FRAME_MIN_SIZE STACK_FRAME_OVERHEAD + + /* Size of stack frame allocated when calling signal handler. */ + #define __SIGNAL_FRAMESIZE 64 +diff --git a/arch/powerpc/include/asm/spinlock.h b/arch/powerpc/include/asm/spinlock.h +index 35aa339410bd..4dbe072eecbe 100644 +--- a/arch/powerpc/include/asm/spinlock.h ++++ b/arch/powerpc/include/asm/spinlock.h +@@ -61,6 +61,7 @@ static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock) + + static inline int arch_spin_is_locked(arch_spinlock_t *lock) + { ++ smp_mb(); + return !arch_spin_value_unlocked(*lock); + } + +diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c +index 0c9c8d7d0734..170a0346f756 100644 +--- a/arch/powerpc/lib/locks.c ++++ b/arch/powerpc/lib/locks.c +@@ -70,12 +70,16 @@ void __rw_yield(arch_rwlock_t *rw) + + void arch_spin_unlock_wait(arch_spinlock_t *lock) + { ++ smp_mb(); ++ + while (lock->slock) { + HMT_low(); + if (SHARED_PROCESSOR) + __spin_yield(lock); + } + HMT_medium(); ++ ++ smp_mb(); + } + + EXPORT_SYMBOL(arch_spin_unlock_wait); +diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c +index 74d1e780748b..2396dda282cd 100644 +--- a/arch/powerpc/perf/callchain.c ++++ b/arch/powerpc/perf/callchain.c +@@ -35,7 +35,7 @@ static int valid_next_sp(unsigned long sp, unsigned long prev_sp) + return 0; /* must be 16-byte aligned */ + if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD)) + return 0; +- if (sp >= prev_sp + STACK_FRAME_OVERHEAD) ++ if (sp >= prev_sp + STACK_FRAME_MIN_SIZE) + return 1; + /* + * sp could decrease when we jump off an interrupt stack +diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c +index 3584ed9b20a1..e309c5c41158 100644 +--- a/arch/s390/mm/pgtable.c ++++ b/arch/s390/mm/pgtable.c +@@ -810,11 +810,21 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr, + pte_t *ptep; + + down_read(&mm->mmap_sem); ++retry: + ptep = get_locked_pte(current->mm, addr, &ptl); + if (unlikely(!ptep)) { + up_read(&mm->mmap_sem); + return -EFAULT; + } ++ if (!(pte_val(*ptep) & _PAGE_INVALID) && ++ (pte_val(*ptep) & _PAGE_PROTECT)) { ++ pte_unmap_unlock(*ptep, ptl); ++ if (fixup_user_fault(current, mm, addr, FAULT_FLAG_WRITE)) { ++ up_read(&mm->mmap_sem); ++ return -EFAULT; ++ } ++ goto retry; ++ } + + new = old = pgste_get_lock(ptep); + pgste_val(new) &= ~(PGSTE_GR_BIT | PGSTE_GC_BIT | +diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c +index 4dbf967da50d..6cfcf2a2eb93 100644 +--- a/arch/x86/boot/compressed/aslr.c ++++ b/arch/x86/boot/compressed/aslr.c +@@ -183,12 +183,27 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size, + static bool mem_avoid_overlap(struct mem_vector *img) + { + int i; ++ struct setup_data *ptr; + + for (i = 0; i < MEM_AVOID_MAX; i++) { + if (mem_overlaps(img, &mem_avoid[i])) + return true; + } + ++ /* Avoid all entries in the setup_data linked list. */ ++ ptr = (struct setup_data *)(unsigned long)real_mode->hdr.setup_data; ++ while (ptr) { ++ struct mem_vector avoid; ++ ++ avoid.start = (u64)ptr; ++ avoid.size = sizeof(*ptr) + ptr->len; ++ ++ if (mem_overlaps(img, &avoid)) ++ return true; ++ ++ ptr = (struct setup_data *)(unsigned long)ptr->next; ++ } ++ + return false; + } + +diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h +index 7252cd339175..6762a55b798a 100644 +--- a/arch/x86/include/asm/fixmap.h ++++ b/arch/x86/include/asm/fixmap.h +@@ -123,14 +123,14 @@ enum fixed_addresses { + __end_of_permanent_fixed_addresses, + + /* +- * 256 temporary boot-time mappings, used by early_ioremap(), ++ * 512 temporary boot-time mappings, used by early_ioremap(), + * before ioremap() is functional. + * +- * If necessary we round it up to the next 256 pages boundary so ++ * If necessary we round it up to the next 512 pages boundary so + * that we can have a single pgd entry and a single pte table: + */ + #define NR_FIX_BTMAPS 64 +-#define FIX_BTMAPS_SLOTS 4 ++#define FIX_BTMAPS_SLOTS 8 + #define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS) + FIX_BTMAP_END = + (__end_of_permanent_fixed_addresses ^ +diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h +index e22c1dbf7feb..d869931bde62 100644 +--- a/arch/x86/include/asm/pgtable_64.h ++++ b/arch/x86/include/asm/pgtable_64.h +@@ -19,6 +19,7 @@ extern pud_t level3_ident_pgt[512]; + extern pmd_t level2_kernel_pgt[512]; + extern pmd_t level2_fixmap_pgt[512]; + extern pmd_t level2_ident_pgt[512]; ++extern pte_t level1_fixmap_pgt[512]; + extern pgd_t init_level4_pgt[]; + + #define swapper_pg_dir init_level4_pgt +diff --git a/arch/x86/kernel/cpu/perf_event_intel_rapl.c b/arch/x86/kernel/cpu/perf_event_intel_rapl.c +index 5ad35ad94d0f..95700e52061d 100644 +--- a/arch/x86/kernel/cpu/perf_event_intel_rapl.c ++++ b/arch/x86/kernel/cpu/perf_event_intel_rapl.c +@@ -511,6 +511,7 @@ static int rapl_cpu_prepare(int cpu) + struct rapl_pmu *pmu = per_cpu(rapl_pmu, cpu); + int phys_id = topology_physical_package_id(cpu); + u64 ms; ++ u64 msr_rapl_power_unit_bits; + + if (pmu) + return 0; +@@ -518,6 +519,9 @@ static int rapl_cpu_prepare(int cpu) + if (phys_id < 0) + return -1; + ++ if (!rdmsrl_safe(MSR_RAPL_POWER_UNIT, &msr_rapl_power_unit_bits)) ++ return -1; ++ + pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu)); + if (!pmu) + return -1; +@@ -531,8 +535,7 @@ static int rapl_cpu_prepare(int cpu) + * + * we cache in local PMU instance + */ +- rdmsrl(MSR_RAPL_POWER_UNIT, pmu->hw_unit); +- pmu->hw_unit = (pmu->hw_unit >> 8) & 0x1FULL; ++ pmu->hw_unit = (msr_rapl_power_unit_bits >> 8) & 0x1FULL; + pmu->pmu = &rapl_pmu_class; + + /* +@@ -649,7 +652,9 @@ static int __init rapl_pmu_init(void) + get_online_cpus(); + + for_each_online_cpu(cpu) { +- rapl_cpu_prepare(cpu); ++ ret = rapl_cpu_prepare(cpu); ++ if (ret) ++ goto out; + rapl_cpu_init(cpu); + } + +@@ -672,6 +677,7 @@ static int __init rapl_pmu_init(void) + hweight32(rapl_cntr_mask), + ktime_to_ms(pmu->timer_interval)); + ++out: + put_online_cpus(); + + return 0; +diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c +index 395be6d8bbde..682876533ed9 100644 +--- a/arch/x86/kernel/smpboot.c ++++ b/arch/x86/kernel/smpboot.c +@@ -1287,6 +1287,9 @@ static void remove_siblinginfo(int cpu) + + for_each_cpu(sibling, cpu_sibling_mask(cpu)) + cpumask_clear_cpu(cpu, cpu_sibling_mask(sibling)); ++ for_each_cpu(sibling, cpu_llc_shared_mask(cpu)) ++ cpumask_clear_cpu(cpu, cpu_llc_shared_mask(sibling)); ++ cpumask_clear(cpu_llc_shared_mask(cpu)); + cpumask_clear(cpu_sibling_mask(cpu)); + cpumask_clear(cpu_core_mask(cpu)); + c->phys_proc_id = 0; +diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c +index 2423ef04ffea..c83da6fb2dee 100644 +--- a/arch/x86/xen/mmu.c ++++ b/arch/x86/xen/mmu.c +@@ -1866,12 +1866,11 @@ static void __init check_pt_base(unsigned long *pt_base, unsigned long *pt_end, + * + * We can construct this by grafting the Xen provided pagetable into + * head_64.S's preconstructed pagetables. We copy the Xen L2's into +- * level2_ident_pgt, level2_kernel_pgt and level2_fixmap_pgt. This +- * means that only the kernel has a physical mapping to start with - +- * but that's enough to get __va working. We need to fill in the rest +- * of the physical mapping once some sort of allocator has been set +- * up. +- * NOTE: for PVH, the page tables are native. ++ * level2_ident_pgt, and level2_kernel_pgt. This means that only the ++ * kernel has a physical mapping to start with - but that's enough to ++ * get __va working. We need to fill in the rest of the physical ++ * mapping once some sort of allocator has been set up. NOTE: for ++ * PVH, the page tables are native. + */ + void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) + { +@@ -1902,8 +1901,11 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) + /* L3_i[0] -> level2_ident_pgt */ + convert_pfn_mfn(level3_ident_pgt); + /* L3_k[510] -> level2_kernel_pgt +- * L3_i[511] -> level2_fixmap_pgt */ ++ * L3_k[511] -> level2_fixmap_pgt */ + convert_pfn_mfn(level3_kernel_pgt); ++ ++ /* L3_k[511][506] -> level1_fixmap_pgt */ ++ convert_pfn_mfn(level2_fixmap_pgt); + } + /* We get [511][511] and have Xen's version of level2_kernel_pgt */ + l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd); +@@ -1913,21 +1915,15 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) + addr[1] = (unsigned long)l3; + addr[2] = (unsigned long)l2; + /* Graft it onto L4[272][0]. Note that we creating an aliasing problem: +- * Both L4[272][0] and L4[511][511] have entries that point to the same ++ * Both L4[272][0] and L4[511][510] have entries that point to the same + * L2 (PMD) tables. Meaning that if you modify it in __va space + * it will be also modified in the __ka space! (But if you just + * modify the PMD table to point to other PTE's or none, then you + * are OK - which is what cleanup_highmap does) */ + copy_page(level2_ident_pgt, l2); +- /* Graft it onto L4[511][511] */ ++ /* Graft it onto L4[511][510] */ + copy_page(level2_kernel_pgt, l2); + +- /* Get [511][510] and graft that in level2_fixmap_pgt */ +- l3 = m2v(pgd[pgd_index(__START_KERNEL_map + PMD_SIZE)].pgd); +- l2 = m2v(l3[pud_index(__START_KERNEL_map + PMD_SIZE)].pud); +- copy_page(level2_fixmap_pgt, l2); +- /* Note that we don't do anything with level1_fixmap_pgt which +- * we don't need. */ + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + /* Make pagetable pieces RO */ + set_page_prot(init_level4_pgt, PAGE_KERNEL_RO); +@@ -1937,6 +1933,7 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) + set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO); + set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); + set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); ++ set_page_prot(level1_fixmap_pgt, PAGE_KERNEL_RO); + + /* Pin down new L4 */ + pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE, +diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h +index 216446295ada..51230ba97bef 100644 +--- a/arch/xtensa/include/asm/pgtable.h ++++ b/arch/xtensa/include/asm/pgtable.h +@@ -67,7 +67,12 @@ + #define VMALLOC_START 0xC0000000 + #define VMALLOC_END 0xC7FEFFFF + #define TLBTEMP_BASE_1 0xC7FF0000 +-#define TLBTEMP_BASE_2 0xC7FF8000 ++#define TLBTEMP_BASE_2 (TLBTEMP_BASE_1 + DCACHE_WAY_SIZE) ++#if 2 * DCACHE_WAY_SIZE > ICACHE_WAY_SIZE ++#define TLBTEMP_SIZE (2 * DCACHE_WAY_SIZE) ++#else ++#define TLBTEMP_SIZE ICACHE_WAY_SIZE ++#endif + + /* + * For the Xtensa architecture, the PTE layout is as follows: +diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h +index fd686dc45d1a..c7211e7e182d 100644 +--- a/arch/xtensa/include/asm/uaccess.h ++++ b/arch/xtensa/include/asm/uaccess.h +@@ -52,7 +52,12 @@ + */ + .macro get_fs ad, sp + GET_CURRENT(\ad,\sp) ++#if THREAD_CURRENT_DS > 1020 ++ addi \ad, \ad, TASK_THREAD ++ l32i \ad, \ad, THREAD_CURRENT_DS - TASK_THREAD ++#else + l32i \ad, \ad, THREAD_CURRENT_DS ++#endif + .endm + + /* +diff --git a/arch/xtensa/include/uapi/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h +index b4cb1100c0fb..a47909f0c34b 100644 +--- a/arch/xtensa/include/uapi/asm/ioctls.h ++++ b/arch/xtensa/include/uapi/asm/ioctls.h +@@ -28,17 +28,17 @@ + #define TCSETSW 0x5403 + #define TCSETSF 0x5404 + +-#define TCGETA _IOR('t', 23, struct termio) +-#define TCSETA _IOW('t', 24, struct termio) +-#define TCSETAW _IOW('t', 25, struct termio) +-#define TCSETAF _IOW('t', 28, struct termio) ++#define TCGETA 0x80127417 /* _IOR('t', 23, struct termio) */ ++#define TCSETA 0x40127418 /* _IOW('t', 24, struct termio) */ ++#define TCSETAW 0x40127419 /* _IOW('t', 25, struct termio) */ ++#define TCSETAF 0x4012741C /* _IOW('t', 28, struct termio) */ + + #define TCSBRK _IO('t', 29) + #define TCXONC _IO('t', 30) + #define TCFLSH _IO('t', 31) + +-#define TIOCSWINSZ _IOW('t', 103, struct winsize) +-#define TIOCGWINSZ _IOR('t', 104, struct winsize) ++#define TIOCSWINSZ 0x40087467 /* _IOW('t', 103, struct winsize) */ ++#define TIOCGWINSZ 0x80087468 /* _IOR('t', 104, struct winsize) */ + #define TIOCSTART _IO('t', 110) /* start output, like ^Q */ + #define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ + #define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ +@@ -88,7 +88,6 @@ + #define TIOCSETD _IOW('T', 35, int) + #define TIOCGETD _IOR('T', 36, int) + #define TCSBRKP _IOW('T', 37, int) /* Needed for POSIX tcsendbreak()*/ +-#define TIOCTTYGSTRUCT _IOR('T', 38, struct tty_struct) /* For debugging only*/ + #define TIOCSBRK _IO('T', 39) /* BSD compatibility */ + #define TIOCCBRK _IO('T', 40) /* BSD compatibility */ + #define TIOCGSID _IOR('T', 41, pid_t) /* Return the session ID of FD*/ +@@ -114,8 +113,10 @@ + #define TIOCSERGETLSR _IOR('T', 89, unsigned int) /* Get line status reg. */ + /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ + # define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ +-#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* Get multiport config */ +-#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */ ++#define TIOCSERGETMULTI 0x80a8545a /* Get multiport config */ ++ /* _IOR('T', 90, struct serial_multiport_struct) */ ++#define TIOCSERSETMULTI 0x40a8545b /* Set multiport config */ ++ /* _IOW('T', 91, struct serial_multiport_struct) */ + + #define TIOCMIWAIT _IO('T', 92) /* wait for a change on serial input line(s) */ + #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S +index ef7f4990722b..a06b7efaae82 100644 +--- a/arch/xtensa/kernel/entry.S ++++ b/arch/xtensa/kernel/entry.S +@@ -1001,9 +1001,8 @@ ENTRY(fast_syscall_xtensa) + movi a7, 4 # sizeof(unsigned int) + access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp + +- addi a6, a6, -1 # assuming SYS_XTENSA_ATOMIC_SET = 1 +- _bgeui a6, SYS_XTENSA_COUNT - 1, .Lill +- _bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP - 1, .Lnswp ++ _bgeui a6, SYS_XTENSA_COUNT, .Lill ++ _bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP, .Lnswp + + /* Fall through for ATOMIC_CMP_SWP. */ + +@@ -1015,27 +1014,26 @@ TRY s32i a5, a3, 0 # different, modify value + l32i a7, a2, PT_AREG7 # restore a7 + l32i a0, a2, PT_AREG0 # restore a0 + movi a2, 1 # and return 1 +- addi a6, a6, 1 # restore a6 (really necessary?) + rfe + + 1: l32i a7, a2, PT_AREG7 # restore a7 + l32i a0, a2, PT_AREG0 # restore a0 + movi a2, 0 # return 0 (note that we cannot set +- addi a6, a6, 1 # restore a6 (really necessary?) + rfe + + .Lnswp: /* Atomic set, add, and exg_add. */ + + TRY l32i a7, a3, 0 # orig ++ addi a6, a6, -SYS_XTENSA_ATOMIC_SET + add a0, a4, a7 # + arg + moveqz a0, a4, a6 # set ++ addi a6, a6, SYS_XTENSA_ATOMIC_SET + TRY s32i a0, a3, 0 # write new value + + mov a0, a2 + mov a2, a7 + l32i a7, a0, PT_AREG7 # restore a7 + l32i a0, a0, PT_AREG0 # restore a0 +- addi a6, a6, 1 # restore a6 (really necessary?) + rfe + + CATCH +@@ -1044,7 +1042,7 @@ CATCH + movi a2, -EFAULT + rfe + +-.Lill: l32i a7, a2, PT_AREG0 # restore a7 ++.Lill: l32i a7, a2, PT_AREG7 # restore a7 + l32i a0, a2, PT_AREG0 # restore a0 + movi a2, -EINVAL + rfe +@@ -1565,7 +1563,7 @@ ENTRY(fast_second_level_miss) + rsr a0, excvaddr + bltu a0, a3, 2f + +- addi a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT)) ++ addi a1, a0, -TLBTEMP_SIZE + bgeu a1, a3, 2f + + /* Check if we have to restore an ITLB mapping. */ +@@ -1820,7 +1818,6 @@ ENTRY(_switch_to) + + entry a1, 16 + +- mov a10, a2 # preserve 'prev' (a2) + mov a11, a3 # and 'next' (a3) + + l32i a4, a2, TASK_THREAD_INFO +@@ -1828,8 +1825,14 @@ ENTRY(_switch_to) + + save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER + +- s32i a0, a10, THREAD_RA # save return address +- s32i a1, a10, THREAD_SP # save stack pointer ++#if THREAD_RA > 1020 || THREAD_SP > 1020 ++ addi a10, a2, TASK_THREAD ++ s32i a0, a10, THREAD_RA - TASK_THREAD # save return address ++ s32i a1, a10, THREAD_SP - TASK_THREAD # save stack pointer ++#else ++ s32i a0, a2, THREAD_RA # save return address ++ s32i a1, a2, THREAD_SP # save stack pointer ++#endif + + /* Disable ints while we manipulate the stack pointer. */ + +@@ -1870,7 +1873,6 @@ ENTRY(_switch_to) + load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER + + wsr a14, ps +- mov a2, a10 # return 'prev' + rsync + + retw +diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c +index 2d9cc6dbfd78..e8b76b8e4b29 100644 +--- a/arch/xtensa/kernel/pci-dma.c ++++ b/arch/xtensa/kernel/pci-dma.c +@@ -49,9 +49,8 @@ dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag) + + /* We currently don't support coherent memory outside KSEG */ + +- if (ret < XCHAL_KSEG_CACHED_VADDR +- || ret >= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE) +- BUG(); ++ BUG_ON(ret < XCHAL_KSEG_CACHED_VADDR || ++ ret > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1); + + + if (ret != 0) { +@@ -68,10 +67,11 @@ EXPORT_SYMBOL(dma_alloc_coherent); + void dma_free_coherent(struct device *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) + { +- long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR; ++ unsigned long addr = (unsigned long)vaddr + ++ XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR; + +- if (addr < 0 || addr >= XCHAL_KSEG_SIZE) +- BUG(); ++ BUG_ON(addr < XCHAL_KSEG_CACHED_VADDR || ++ addr > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1); + + free_pages(addr, get_order(size)); + } +diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c +index 744833b630c6..91c25f261c91 100644 +--- a/block/cfq-iosched.c ++++ b/block/cfq-iosched.c +@@ -1275,12 +1275,16 @@ __cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg) + static void + cfq_update_group_weight(struct cfq_group *cfqg) + { +- BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node)); +- + if (cfqg->new_weight) { + cfqg->weight = cfqg->new_weight; + cfqg->new_weight = 0; + } ++} ++ ++static void ++cfq_update_group_leaf_weight(struct cfq_group *cfqg) ++{ ++ BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node)); + + if (cfqg->new_leaf_weight) { + cfqg->leaf_weight = cfqg->new_leaf_weight; +@@ -1299,7 +1303,7 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg) + /* add to the service tree */ + BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node)); + +- cfq_update_group_weight(cfqg); ++ cfq_update_group_leaf_weight(cfqg); + __cfq_group_service_tree_add(st, cfqg); + + /* +@@ -1323,6 +1327,7 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg) + */ + while ((parent = cfqg_parent(pos))) { + if (propagate) { ++ cfq_update_group_weight(pos); + propagate = !parent->nr_active++; + parent->children_weight += pos->weight; + } +diff --git a/block/genhd.c b/block/genhd.c +index 791f41943132..e6723bd4d7a1 100644 +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -28,10 +28,10 @@ struct kobject *block_depr; + /* for extended dynamic devt allocation, currently only one major is used */ + #define NR_EXT_DEVT (1 << MINORBITS) + +-/* For extended devt allocation. ext_devt_mutex prevents look up ++/* For extended devt allocation. ext_devt_lock prevents look up + * results from going away underneath its user. + */ +-static DEFINE_MUTEX(ext_devt_mutex); ++static DEFINE_SPINLOCK(ext_devt_lock); + static DEFINE_IDR(ext_devt_idr); + + static struct device_type disk_type; +@@ -420,9 +420,13 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt) + } + + /* allocate ext devt */ +- mutex_lock(&ext_devt_mutex); +- idx = idr_alloc(&ext_devt_idr, part, 0, NR_EXT_DEVT, GFP_KERNEL); +- mutex_unlock(&ext_devt_mutex); ++ idr_preload(GFP_KERNEL); ++ ++ spin_lock(&ext_devt_lock); ++ idx = idr_alloc(&ext_devt_idr, part, 0, NR_EXT_DEVT, GFP_NOWAIT); ++ spin_unlock(&ext_devt_lock); ++ ++ idr_preload_end(); + if (idx < 0) + return idx == -ENOSPC ? -EBUSY : idx; + +@@ -441,15 +445,13 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt) + */ + void blk_free_devt(dev_t devt) + { +- might_sleep(); +- + if (devt == MKDEV(0, 0)) + return; + + if (MAJOR(devt) == BLOCK_EXT_MAJOR) { +- mutex_lock(&ext_devt_mutex); ++ spin_lock(&ext_devt_lock); + idr_remove(&ext_devt_idr, blk_mangle_minor(MINOR(devt))); +- mutex_unlock(&ext_devt_mutex); ++ spin_unlock(&ext_devt_lock); + } + } + +@@ -665,7 +667,6 @@ void del_gendisk(struct gendisk *disk) + sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk))); + pm_runtime_set_memalloc_noio(disk_to_dev(disk), false); + device_del(disk_to_dev(disk)); +- blk_free_devt(disk_to_dev(disk)->devt); + } + EXPORT_SYMBOL(del_gendisk); + +@@ -690,13 +691,13 @@ struct gendisk *get_gendisk(dev_t devt, int *partno) + } else { + struct hd_struct *part; + +- mutex_lock(&ext_devt_mutex); ++ spin_lock(&ext_devt_lock); + part = idr_find(&ext_devt_idr, blk_mangle_minor(MINOR(devt))); + if (part && get_disk(part_to_disk(part))) { + *partno = part->partno; + disk = part_to_disk(part); + } +- mutex_unlock(&ext_devt_mutex); ++ spin_unlock(&ext_devt_lock); + } + + return disk; +@@ -1098,6 +1099,7 @@ static void disk_release(struct device *dev) + { + struct gendisk *disk = dev_to_disk(dev); + ++ blk_free_devt(dev->devt); + disk_release_events(disk); + kfree(disk->random); + disk_replace_part_tbl(disk, NULL); +diff --git a/block/partition-generic.c b/block/partition-generic.c +index 789cdea05893..0d9e5f97f0a8 100644 +--- a/block/partition-generic.c ++++ b/block/partition-generic.c +@@ -211,6 +211,7 @@ static const struct attribute_group *part_attr_groups[] = { + static void part_release(struct device *dev) + { + struct hd_struct *p = dev_to_part(dev); ++ blk_free_devt(dev->devt); + free_part_stats(p); + free_part_info(p); + kfree(p); +@@ -253,7 +254,6 @@ void delete_partition(struct gendisk *disk, int partno) + rcu_assign_pointer(ptbl->last_lookup, NULL); + kobject_put(part->holder_dir); + device_del(part_to_dev(part)); +- blk_free_devt(part_devt(part)); + + hd_struct_put(part); + } +diff --git a/block/partitions/aix.c b/block/partitions/aix.c +index 43be471d9b1d..0931f5136ab2 100644 +--- a/block/partitions/aix.c ++++ b/block/partitions/aix.c +@@ -253,7 +253,7 @@ int aix_partition(struct parsed_partitions *state) + continue; + } + lv_ix = be16_to_cpu(p->lv_ix) - 1; +- if (lv_ix > state->limit) { ++ if (lv_ix >= state->limit) { + cur_lv_ix = -1; + continue; + } +diff --git a/drivers/acpi/acpi_cmos_rtc.c b/drivers/acpi/acpi_cmos_rtc.c +index 84190ed89c04..aff69d9bfcbf 100644 +--- a/drivers/acpi/acpi_cmos_rtc.c ++++ b/drivers/acpi/acpi_cmos_rtc.c +@@ -35,7 +35,7 @@ acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address, + void *handler_context, void *region_context) + { + int i; +- u8 *value = (u8 *)&value64; ++ u8 *value = (u8 *)value64; + + if (address > 0xff || !value64) + return AE_BAD_PARAMETER; +diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h +index d95ca5449ace..e6ab104afe42 100644 +--- a/drivers/acpi/acpica/aclocal.h ++++ b/drivers/acpi/acpica/aclocal.h +@@ -254,6 +254,7 @@ struct acpi_create_field_info { + u32 field_bit_position; + u32 field_bit_length; + u16 resource_length; ++ u16 pin_number_index; + u8 field_flags; + u8 attribute; + u8 field_type; +diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h +index cc7ab6dd724e..a47cc78ffd4f 100644 +--- a/drivers/acpi/acpica/acobject.h ++++ b/drivers/acpi/acpica/acobject.h +@@ -263,6 +263,7 @@ struct acpi_object_region_field { + ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length; + union acpi_operand_object *region_obj; /* Containing op_region object */ + u8 *resource_buffer; /* resource_template for serial regions/fields */ ++ u16 pin_number_index; /* Index relative to previous Connection/Template */ + }; + + struct acpi_object_bank_field { +diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c +index e7a57c554e84..9af55bd6c4d7 100644 +--- a/drivers/acpi/acpica/dsfield.c ++++ b/drivers/acpi/acpica/dsfield.c +@@ -360,6 +360,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, + */ + info->resource_buffer = NULL; + info->connection_node = NULL; ++ info->pin_number_index = 0; + + /* + * A Connection() is either an actual resource descriptor (buffer) +@@ -437,6 +438,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, + } + + info->field_bit_position += info->field_bit_length; ++ info->pin_number_index++; /* Index relative to previous Connection() */ + break; + + default: +diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c +index 144cbb9b73bc..cd4b231ae760 100644 +--- a/drivers/acpi/acpica/evregion.c ++++ b/drivers/acpi/acpica/evregion.c +@@ -142,6 +142,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, + union acpi_operand_object *region_obj2; + void *region_context = NULL; + struct acpi_connection_info *context; ++ acpi_physical_address address; + + ACPI_FUNCTION_TRACE(ev_address_space_dispatch); + +@@ -231,25 +232,23 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, + /* We have everything we need, we can invoke the address space handler */ + + handler = handler_desc->address_space.handler; +- +- ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, +- "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", +- ®ion_obj->region.handler->address_space, handler, +- ACPI_FORMAT_NATIVE_UINT(region_obj->region.address + +- region_offset), +- acpi_ut_get_region_name(region_obj->region. +- space_id))); ++ address = (region_obj->region.address + region_offset); + + /* + * Special handling for generic_serial_bus and general_purpose_io: + * There are three extra parameters that must be passed to the + * handler via the context: +- * 1) Connection buffer, a resource template from Connection() op. +- * 2) Length of the above buffer. +- * 3) Actual access length from the access_as() op. ++ * 1) Connection buffer, a resource template from Connection() op ++ * 2) Length of the above buffer ++ * 3) Actual access length from the access_as() op ++ * ++ * In addition, for general_purpose_io, the Address and bit_width fields ++ * are defined as follows: ++ * 1) Address is the pin number index of the field (bit offset from ++ * the previous Connection) ++ * 2) bit_width is the actual bit length of the field (number of pins) + */ +- if (((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) || +- (region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) && ++ if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) && + context && field_obj) { + + /* Get the Connection (resource_template) buffer */ +@@ -258,6 +257,24 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, + context->length = field_obj->field.resource_length; + context->access_length = field_obj->field.access_length; + } ++ if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) && ++ context && field_obj) { ++ ++ /* Get the Connection (resource_template) buffer */ ++ ++ context->connection = field_obj->field.resource_buffer; ++ context->length = field_obj->field.resource_length; ++ context->access_length = field_obj->field.access_length; ++ address = field_obj->field.pin_number_index; ++ bit_width = field_obj->field.bit_length; ++ } ++ ++ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, ++ "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", ++ ®ion_obj->region.handler->address_space, handler, ++ ACPI_FORMAT_NATIVE_UINT(address), ++ acpi_ut_get_region_name(region_obj->region. ++ space_id))); + + if (!(handler_desc->address_space.handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { +@@ -271,9 +288,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, + + /* Call the handler */ + +- status = handler(function, +- (region_obj->region.address + region_offset), +- bit_width, value, context, ++ status = handler(function, address, bit_width, value, context, + region_obj2->extra.region_context); + + if (ACPI_FAILURE(status)) { +diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c +index cfd875243421..d36894a228b1 100644 +--- a/drivers/acpi/acpica/exfield.c ++++ b/drivers/acpi/acpica/exfield.c +@@ -178,6 +178,37 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, + buffer = &buffer_desc->integer.value; + } + ++ if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && ++ (obj_desc->field.region_obj->region.space_id == ++ ACPI_ADR_SPACE_GPIO)) { ++ /* ++ * For GPIO (general_purpose_io), the Address will be the bit offset ++ * from the previous Connection() operator, making it effectively a ++ * pin number index. The bit_length is the length of the field, which ++ * is thus the number of pins. ++ */ ++ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, ++ "GPIO FieldRead [FROM]: Pin %u Bits %u\n", ++ obj_desc->field.pin_number_index, ++ obj_desc->field.bit_length)); ++ ++ /* Lock entire transaction if requested */ ++ ++ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); ++ ++ /* Perform the write */ ++ ++ status = acpi_ex_access_region(obj_desc, 0, ++ (u64 *)buffer, ACPI_READ); ++ acpi_ex_release_global_lock(obj_desc->common_field.field_flags); ++ if (ACPI_FAILURE(status)) { ++ acpi_ut_remove_reference(buffer_desc); ++ } else { ++ *ret_buffer_desc = buffer_desc; ++ } ++ return_ACPI_STATUS(status); ++ } ++ + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", + obj_desc, obj_desc->common.type, buffer, +@@ -325,6 +356,42 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, + + *result_desc = buffer_desc; + return_ACPI_STATUS(status); ++ } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && ++ (obj_desc->field.region_obj->region.space_id == ++ ACPI_ADR_SPACE_GPIO)) { ++ /* ++ * For GPIO (general_purpose_io), we will bypass the entire field ++ * mechanism and handoff the bit address and bit width directly to ++ * the handler. The Address will be the bit offset ++ * from the previous Connection() operator, making it effectively a ++ * pin number index. The bit_length is the length of the field, which ++ * is thus the number of pins. ++ */ ++ if (source_desc->common.type != ACPI_TYPE_INTEGER) { ++ return_ACPI_STATUS(AE_AML_OPERAND_TYPE); ++ } ++ ++ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, ++ "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n", ++ acpi_ut_get_type_name(source_desc->common. ++ type), ++ source_desc->common.type, ++ (u32)source_desc->integer.value, ++ obj_desc->field.pin_number_index, ++ obj_desc->field.bit_length)); ++ ++ buffer = &source_desc->integer.value; ++ ++ /* Lock entire transaction if requested */ ++ ++ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); ++ ++ /* Perform the write */ ++ ++ status = acpi_ex_access_region(obj_desc, 0, ++ (u64 *)buffer, ACPI_WRITE); ++ acpi_ex_release_global_lock(obj_desc->common_field.field_flags); ++ return_ACPI_STATUS(status); + } + + /* Get a pointer to the data to be written */ +diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c +index 5a588611ab48..8c88cfdec441 100644 +--- a/drivers/acpi/acpica/exprep.c ++++ b/drivers/acpi/acpica/exprep.c +@@ -484,6 +484,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) + obj_desc->field.resource_length = info->resource_length; + } + ++ obj_desc->field.pin_number_index = info->pin_number_index; ++ + /* Allow full data read from EC address space */ + + if ((obj_desc->field.region_obj->region.space_id == +diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c +index 368f9ddb8480..e4a6f78f3bbc 100644 +--- a/drivers/acpi/container.c ++++ b/drivers/acpi/container.c +@@ -96,6 +96,13 @@ static void container_device_detach(struct acpi_device *adev) + device_unregister(dev); + } + ++static void container_device_online(struct acpi_device *adev) ++{ ++ struct device *dev = acpi_driver_data(adev); ++ ++ kobject_uevent(&dev->kobj, KOBJ_ONLINE); ++} ++ + static struct acpi_scan_handler container_handler = { + .ids = container_device_ids, + .attach = container_device_attach, +@@ -103,6 +110,7 @@ static struct acpi_scan_handler container_handler = { + .hotplug = { + .enabled = true, + .demand_offline = true, ++ .notify_online = container_device_online, + }, + }; + +diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c +index 92d5184e3654..493a342efa44 100644 +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -106,7 +106,7 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, + list_for_each_entry(id, &acpi_dev->pnp.ids, list) { + count = snprintf(&modalias[len], size, "%s:", id->id); + if (count < 0) +- return EINVAL; ++ return -EINVAL; + if (count >= size) + return -ENOMEM; + len += count; +@@ -2068,6 +2068,9 @@ static void acpi_bus_attach(struct acpi_device *device) + ok: + list_for_each_entry(child, &device->children, node) + acpi_bus_attach(child); ++ ++ if (device->handler && device->handler->hotplug.notify_online) ++ device->handler->hotplug.notify_online(device); + } + + /** +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index b54f8b3c7924..00663d60f6d4 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -306,6 +306,14 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */ ++ { PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series AHCI */ ++ { PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */ + + /* JMicron 360/1/3/5/6, match class to avoid IDE function */ + { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, +@@ -443,6 +451,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a), + .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172), ++ .driver_data = board_ahci_yes_fbs }, /* 88se9182 */ ++ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182), + .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192), + .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ +diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c +index 6334c8d7c3f1..39f76b987c75 100644 +--- a/drivers/ata/ata_piix.c ++++ b/drivers/ata/ata_piix.c +@@ -340,6 +340,14 @@ static const struct pci_device_id piix_pci_tbl[] = { + { 0x8086, 0x0F21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt }, + /* SATA Controller IDE (Coleto Creek) */ + { 0x8086, 0x23a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, ++ /* SATA Controller IDE (9 Series) */ ++ { 0x8086, 0x8c88, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb }, ++ /* SATA Controller IDE (9 Series) */ ++ { 0x8086, 0x8c89, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb }, ++ /* SATA Controller IDE (9 Series) */ ++ { 0x8086, 0x8c80, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, ++ /* SATA Controller IDE (9 Series) */ ++ { 0x8086, 0x8c81, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + + { } /* terminate list */ + }; +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index f7616036663b..538574f98e22 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -4227,7 +4227,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { + { "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Crucial_CT???M500SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Micron_M550*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, +- { "Crucial_CT???M550SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, ++ { "Crucial_CT*M550SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + + /* + * Some WD SATA-I drives spin up and down erratically when the link +diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c +index f35f15f4d83e..f7badaa39eb6 100644 +--- a/drivers/ata/pata_scc.c ++++ b/drivers/ata/pata_scc.c +@@ -586,7 +586,7 @@ static int scc_wait_after_reset(struct ata_link *link, unsigned int devmask, + * Note: Original code is ata_bus_softreset(). + */ + +-static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask, ++static int scc_bus_softreset(struct ata_port *ap, unsigned int devmask, + unsigned long deadline) + { + struct ata_ioports *ioaddr = &ap->ioaddr; +@@ -600,9 +600,7 @@ static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask, + udelay(20); + out_be32(ioaddr->ctl_addr, ap->ctl); + +- scc_wait_after_reset(&ap->link, devmask, deadline); +- +- return 0; ++ return scc_wait_after_reset(&ap->link, devmask, deadline); + } + + /** +@@ -619,7 +617,8 @@ static int scc_softreset(struct ata_link *link, unsigned int *classes, + { + struct ata_port *ap = link->ap; + unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; +- unsigned int devmask = 0, err_mask; ++ unsigned int devmask = 0; ++ int rc; + u8 err; + + DPRINTK("ENTER\n"); +@@ -635,9 +634,9 @@ static int scc_softreset(struct ata_link *link, unsigned int *classes, + + /* issue bus reset */ + DPRINTK("about to softreset, devmask=%x\n", devmask); +- err_mask = scc_bus_softreset(ap, devmask, deadline); +- if (err_mask) { +- ata_port_err(ap, "SRST failed (err_mask=0x%x)\n", err_mask); ++ rc = scc_bus_softreset(ap, devmask, deadline); ++ if (rc) { ++ ata_port_err(ap, "SRST failed (err_mask=0x%x)\n", rc); + return -EIO; + } + +diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c +index d4dd77134814..154e7a8c0a04 100644 +--- a/drivers/base/regmap/regcache.c ++++ b/drivers/base/regmap/regcache.c +@@ -701,7 +701,7 @@ int regcache_sync_block(struct regmap *map, void *block, + unsigned int block_base, unsigned int start, + unsigned int end) + { +- if (regmap_can_raw_write(map)) ++ if (regmap_can_raw_write(map) && !map->use_single_rw) + return regcache_sync_block_raw(map, block, cache_present, + block_base, start, end); + else +diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c +index 6a19515f8a45..2ea056c09aeb 100644 +--- a/drivers/base/regmap/regmap.c ++++ b/drivers/base/regmap/regmap.c +@@ -105,7 +105,7 @@ bool regmap_readable(struct regmap *map, unsigned int reg) + + bool regmap_volatile(struct regmap *map, unsigned int reg) + { +- if (!regmap_readable(map, reg)) ++ if (!map->format.format_write && !regmap_readable(map, reg)) + return false; + + if (map->volatile_reg) +diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c +index b94a311e5ab6..f9c4632d4dd3 100644 +--- a/drivers/clk/clk.c ++++ b/drivers/clk/clk.c +@@ -1487,6 +1487,7 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even + static void clk_change_rate(struct clk *clk) + { + struct clk *child; ++ struct hlist_node *tmp; + unsigned long old_rate; + unsigned long best_parent_rate = 0; + bool skip_set_rate = false; +@@ -1525,7 +1526,11 @@ static void clk_change_rate(struct clk *clk) + if (clk->notifier_count && old_rate != clk->rate) + __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); + +- hlist_for_each_entry(child, &clk->children, child_node) { ++ /* ++ * Use safe iteration, as change_rate can actually swap parents ++ * for certain clock types. ++ */ ++ hlist_for_each_entry_safe(child, tmp, &clk->children, child_node) { + /* Skip children who will be reparented to another clock */ + if (child->new_parent && child->new_parent != clk) + continue; +diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c +index 9be47a829144..f3c95d648a53 100644 +--- a/drivers/clk/qcom/mmcc-msm8960.c ++++ b/drivers/clk/qcom/mmcc-msm8960.c +@@ -37,6 +37,8 @@ + #define P_PLL2 2 + #define P_PLL3 3 + ++#define F_MN(f, s, _m, _n) { .freq = f, .src = s, .m = _m, .n = _n } ++ + static u8 mmcc_pxo_pll8_pll2_map[] = { + [P_PXO] = 0, + [P_PLL8] = 2, +@@ -58,8 +60,8 @@ static u8 mmcc_pxo_pll8_pll2_pll3_map[] = { + + static const char *mmcc_pxo_pll8_pll2_pll3[] = { + "pxo", +- "pll2", + "pll8_vote", ++ "pll2", + "pll3", + }; + +@@ -709,18 +711,18 @@ static struct clk_branch csiphy2_timer_clk = { + }; + + static struct freq_tbl clk_tbl_gfx2d[] = { +- { 27000000, P_PXO, 1, 0 }, +- { 48000000, P_PLL8, 1, 8 }, +- { 54857000, P_PLL8, 1, 7 }, +- { 64000000, P_PLL8, 1, 6 }, +- { 76800000, P_PLL8, 1, 5 }, +- { 96000000, P_PLL8, 1, 4 }, +- { 128000000, P_PLL8, 1, 3 }, +- { 145455000, P_PLL2, 2, 11 }, +- { 160000000, P_PLL2, 1, 5 }, +- { 177778000, P_PLL2, 2, 9 }, +- { 200000000, P_PLL2, 1, 4 }, +- { 228571000, P_PLL2, 2, 7 }, ++ F_MN( 27000000, P_PXO, 1, 0), ++ F_MN( 48000000, P_PLL8, 1, 8), ++ F_MN( 54857000, P_PLL8, 1, 7), ++ F_MN( 64000000, P_PLL8, 1, 6), ++ F_MN( 76800000, P_PLL8, 1, 5), ++ F_MN( 96000000, P_PLL8, 1, 4), ++ F_MN(128000000, P_PLL8, 1, 3), ++ F_MN(145455000, P_PLL2, 2, 11), ++ F_MN(160000000, P_PLL2, 1, 5), ++ F_MN(177778000, P_PLL2, 2, 9), ++ F_MN(200000000, P_PLL2, 1, 4), ++ F_MN(228571000, P_PLL2, 2, 7), + { } + }; + +@@ -841,22 +843,22 @@ static struct clk_branch gfx2d1_clk = { + }; + + static struct freq_tbl clk_tbl_gfx3d[] = { +- { 27000000, P_PXO, 1, 0 }, +- { 48000000, P_PLL8, 1, 8 }, +- { 54857000, P_PLL8, 1, 7 }, +- { 64000000, P_PLL8, 1, 6 }, +- { 76800000, P_PLL8, 1, 5 }, +- { 96000000, P_PLL8, 1, 4 }, +- { 128000000, P_PLL8, 1, 3 }, +- { 145455000, P_PLL2, 2, 11 }, +- { 160000000, P_PLL2, 1, 5 }, +- { 177778000, P_PLL2, 2, 9 }, +- { 200000000, P_PLL2, 1, 4 }, +- { 228571000, P_PLL2, 2, 7 }, +- { 266667000, P_PLL2, 1, 3 }, +- { 300000000, P_PLL3, 1, 4 }, +- { 320000000, P_PLL2, 2, 5 }, +- { 400000000, P_PLL2, 1, 2 }, ++ F_MN( 27000000, P_PXO, 1, 0), ++ F_MN( 48000000, P_PLL8, 1, 8), ++ F_MN( 54857000, P_PLL8, 1, 7), ++ F_MN( 64000000, P_PLL8, 1, 6), ++ F_MN( 76800000, P_PLL8, 1, 5), ++ F_MN( 96000000, P_PLL8, 1, 4), ++ F_MN(128000000, P_PLL8, 1, 3), ++ F_MN(145455000, P_PLL2, 2, 11), ++ F_MN(160000000, P_PLL2, 1, 5), ++ F_MN(177778000, P_PLL2, 2, 9), ++ F_MN(200000000, P_PLL2, 1, 4), ++ F_MN(228571000, P_PLL2, 2, 7), ++ F_MN(266667000, P_PLL2, 1, 3), ++ F_MN(300000000, P_PLL3, 1, 4), ++ F_MN(320000000, P_PLL2, 2, 5), ++ F_MN(400000000, P_PLL2, 1, 2), + { } + }; + +@@ -896,7 +898,7 @@ static struct clk_dyn_rcg gfx3d_src = { + .hw.init = &(struct clk_init_data){ + .name = "gfx3d_src", + .parent_names = mmcc_pxo_pll8_pll2_pll3, +- .num_parents = 3, ++ .num_parents = 4, + .ops = &clk_dyn_rcg_ops, + }, + }, +@@ -994,7 +996,7 @@ static struct clk_rcg jpegd_src = { + .ns_reg = 0x00ac, + .p = { + .pre_div_shift = 12, +- .pre_div_width = 2, ++ .pre_div_width = 4, + }, + .s = { + .src_sel_shift = 0, +@@ -1114,7 +1116,7 @@ static struct clk_branch mdp_lut_clk = { + .enable_reg = 0x016c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ +- .parent_names = (const char *[]){ "mdp_clk" }, ++ .parent_names = (const char *[]){ "mdp_src" }, + .num_parents = 1, + .name = "mdp_lut_clk", + .ops = &clk_branch_ops, +@@ -1341,15 +1343,15 @@ static struct clk_branch hdmi_app_clk = { + }; + + static struct freq_tbl clk_tbl_vcodec[] = { +- { 27000000, P_PXO, 1, 0 }, +- { 32000000, P_PLL8, 1, 12 }, +- { 48000000, P_PLL8, 1, 8 }, +- { 54860000, P_PLL8, 1, 7 }, +- { 96000000, P_PLL8, 1, 4 }, +- { 133330000, P_PLL2, 1, 6 }, +- { 200000000, P_PLL2, 1, 4 }, +- { 228570000, P_PLL2, 2, 7 }, +- { 266670000, P_PLL2, 1, 3 }, ++ F_MN( 27000000, P_PXO, 1, 0), ++ F_MN( 32000000, P_PLL8, 1, 12), ++ F_MN( 48000000, P_PLL8, 1, 8), ++ F_MN( 54860000, P_PLL8, 1, 7), ++ F_MN( 96000000, P_PLL8, 1, 4), ++ F_MN(133330000, P_PLL2, 1, 6), ++ F_MN(200000000, P_PLL2, 1, 4), ++ F_MN(228570000, P_PLL2, 2, 7), ++ F_MN(266670000, P_PLL2, 1, 3), + { } + }; + +diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c +index 153f4b92cc05..415923606164 100644 +--- a/drivers/cpufreq/cpufreq.c ++++ b/drivers/cpufreq/cpufreq.c +@@ -1225,6 +1225,8 @@ err_get_freq: + per_cpu(cpufreq_cpu_data, j) = NULL; + write_unlock_irqrestore(&cpufreq_driver_lock, flags); + ++ up_write(&policy->rwsem); ++ + if (cpufreq_driver->exit) + cpufreq_driver->exit(policy); + err_set_policy_cpu: +diff --git a/drivers/dma/TODO b/drivers/dma/TODO +index 734ed0206cd5..b8045cd42ee1 100644 +--- a/drivers/dma/TODO ++++ b/drivers/dma/TODO +@@ -7,7 +7,6 @@ TODO for slave dma + - imx-dma + - imx-sdma + - mxs-dma.c +- - dw_dmac + - intel_mid_dma + 4. Check other subsystems for dma drivers and merge/move to dmaengine + 5. Remove dma_slave_config's dma direction. +diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c +index 01a200cd0189..b0972b3869c7 100644 +--- a/drivers/dma/dw/core.c ++++ b/drivers/dma/dw/core.c +@@ -279,6 +279,15 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) + channel_set_bit(dw, CH_EN, dwc->mask); + } + ++static void dwc_dostart_first_queued(struct dw_dma_chan *dwc) ++{ ++ if (list_empty(&dwc->queue)) ++ return; ++ ++ list_move(dwc->queue.next, &dwc->active_list); ++ dwc_dostart(dwc, dwc_first_active(dwc)); ++} ++ + /*----------------------------------------------------------------------*/ + + static void +@@ -335,10 +344,7 @@ static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc) + * the completed ones. + */ + list_splice_init(&dwc->active_list, &list); +- if (!list_empty(&dwc->queue)) { +- list_move(dwc->queue.next, &dwc->active_list); +- dwc_dostart(dwc, dwc_first_active(dwc)); +- } ++ dwc_dostart_first_queued(dwc); + + spin_unlock_irqrestore(&dwc->lock, flags); + +@@ -467,10 +473,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) + /* Try to continue after resetting the channel... */ + dwc_chan_disable(dw, dwc); + +- if (!list_empty(&dwc->queue)) { +- list_move(dwc->queue.next, &dwc->active_list); +- dwc_dostart(dwc, dwc_first_active(dwc)); +- } ++ dwc_dostart_first_queued(dwc); + spin_unlock_irqrestore(&dwc->lock, flags); + } + +@@ -677,17 +680,9 @@ static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx) + * possible, perhaps even appending to those already submitted + * for DMA. But this is hard to do in a race-free manner. + */ +- if (list_empty(&dwc->active_list)) { +- dev_vdbg(chan2dev(tx->chan), "%s: started %u\n", __func__, +- desc->txd.cookie); +- list_add_tail(&desc->desc_node, &dwc->active_list); +- dwc_dostart(dwc, dwc_first_active(dwc)); +- } else { +- dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", __func__, +- desc->txd.cookie); + +- list_add_tail(&desc->desc_node, &dwc->queue); +- } ++ dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", __func__, desc->txd.cookie); ++ list_add_tail(&desc->desc_node, &dwc->queue); + + spin_unlock_irqrestore(&dwc->lock, flags); + +@@ -1092,9 +1087,12 @@ dwc_tx_status(struct dma_chan *chan, + static void dwc_issue_pending(struct dma_chan *chan) + { + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); ++ unsigned long flags; + +- if (!list_empty(&dwc->queue)) +- dwc_scan_descriptors(to_dw_dma(chan->device), dwc); ++ spin_lock_irqsave(&dwc->lock, flags); ++ if (list_empty(&dwc->active_list)) ++ dwc_dostart_first_queued(dwc); ++ spin_unlock_irqrestore(&dwc->lock, flags); + } + + static int dwc_alloc_chan_resources(struct dma_chan *chan) +diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c +index 50535fd5a88d..d830b38e54f6 100644 +--- a/drivers/gpu/drm/ast/ast_main.c ++++ b/drivers/gpu/drm/ast/ast_main.c +@@ -100,7 +100,7 @@ static int ast_detect_chip(struct drm_device *dev) + } + ast->vga2_clone = false; + } else { +- ast->chip = 2000; ++ ast->chip = AST2000; + DRM_INFO("AST 2000 detected\n"); + } + } +diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c +index 3ecb332e7cfa..7410a507eacc 100644 +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -1426,10 +1426,13 @@ unlock: + out: + switch (ret) { + case -EIO: +- /* If this -EIO is due to a gpu hang, give the reset code a +- * chance to clean up the mess. Otherwise return the proper +- * SIGBUS. */ +- if (i915_terminally_wedged(&dev_priv->gpu_error)) { ++ /* ++ * We eat errors when the gpu is terminally wedged to avoid ++ * userspace unduly crashing (gl has no provisions for mmaps to ++ * fail). But any other -EIO isn't ours (e.g. swap in failure) ++ * and so needs to be reported. ++ */ ++ if (!i915_terminally_wedged(&dev_priv->gpu_error)) { + ret = VM_FAULT_SIGBUS; + break; + } +diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c +index f22041973f3a..08105fddfd2a 100644 +--- a/drivers/gpu/drm/i915/intel_bios.c ++++ b/drivers/gpu/drm/i915/intel_bios.c +@@ -839,7 +839,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) + } + } + +-static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id) ++static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id) + { + DRM_DEBUG_KMS("Falling back to manually reading VBT from " + "VBIOS ROM for %s\n", +diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c +index b19ddacbe19d..834847527982 100644 +--- a/drivers/gpu/drm/i915/intel_crt.c ++++ b/drivers/gpu/drm/i915/intel_crt.c +@@ -750,7 +750,7 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = { + .destroy = intel_encoder_destroy, + }; + +-static int __init intel_no_crt_dmi_callback(const struct dmi_system_id *id) ++static int intel_no_crt_dmi_callback(const struct dmi_system_id *id) + { + DRM_INFO("Skipping CRT initialization for %s\n", id->ident); + return 1; +diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c +index eb8f64b5fb85..67c9ff389989 100644 +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -544,7 +544,7 @@ static const struct drm_encoder_funcs intel_lvds_enc_funcs = { + .destroy = intel_encoder_destroy, + }; + +-static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id) ++static int intel_no_lvds_dmi_callback(const struct dmi_system_id *id) + { + DRM_INFO("Skipping LVDS initialization for %s\n", id->ident); + return 1; +diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c +index 31b36c5ac894..d488fc71ef49 100644 +--- a/drivers/gpu/drm/i915/intel_ringbuffer.c ++++ b/drivers/gpu/drm/i915/intel_ringbuffer.c +@@ -475,6 +475,9 @@ static int init_ring_common(struct intel_ring_buffer *ring) + } + } + ++ /* Enforce ordering by reading HEAD register back */ ++ I915_READ_HEAD(ring); ++ + /* Initialize the ring. This must happen _after_ we've cleared the ring + * registers with the above sequence (the readback of the HEAD registers + * also enforces ordering), otherwise the hw might lose the new ring +diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c +index 365c7c47c46c..9c9606c8bb1a 100644 +--- a/drivers/gpu/drm/i915/intel_tv.c ++++ b/drivers/gpu/drm/i915/intel_tv.c +@@ -854,6 +854,10 @@ intel_enable_tv(struct intel_encoder *encoder) + struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + ++ /* Prevents vblank waits from timing out in intel_tv_detect_type() */ ++ intel_wait_for_vblank(encoder->base.dev, ++ to_intel_crtc(encoder->base.crtc)->pipe); ++ + I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE); + } + +diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c +index 471347edc27e..a92fb01459c9 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_vga.c ++++ b/drivers/gpu/drm/nouveau/nouveau_vga.c +@@ -100,7 +100,16 @@ void + nouveau_vga_fini(struct nouveau_drm *drm) + { + struct drm_device *dev = drm->dev; ++ bool runtime = false; ++ ++ if (nouveau_runtime_pm == 1) ++ runtime = true; ++ if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm())) ++ runtime = true; ++ + vga_switcheroo_unregister_client(dev->pdev); ++ if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus()) ++ vga_switcheroo_fini_domain_pm_ops(drm->dev->dev); + vga_client_register(dev->pdev, NULL, NULL, NULL); + } + +diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c +index 5fa854c84d62..543ba2d4a659 100644 +--- a/drivers/gpu/drm/radeon/ci_dpm.c ++++ b/drivers/gpu/drm/radeon/ci_dpm.c +@@ -851,6 +851,9 @@ static int ci_set_thermal_temperature_range(struct radeon_device *rdev, + WREG32_SMC(CG_THERMAL_CTRL, tmp); + #endif + ++ rdev->pm.dpm.thermal.min_temp = low_temp; ++ rdev->pm.dpm.thermal.max_temp = high_temp; ++ + return 0; + } + +@@ -922,7 +925,18 @@ static void ci_get_leakage_voltages(struct radeon_device *rdev) + pi->vddc_leakage.count = 0; + pi->vddci_leakage.count = 0; + +- if (radeon_atom_get_leakage_id_from_vbios(rdev, &leakage_id) == 0) { ++ if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) { ++ for (i = 0; i < CISLANDS_MAX_LEAKAGE_COUNT; i++) { ++ virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; ++ if (radeon_atom_get_voltage_evv(rdev, virtual_voltage_id, &vddc) != 0) ++ continue; ++ if (vddc != 0 && vddc != virtual_voltage_id) { ++ pi->vddc_leakage.actual_voltage[pi->vddc_leakage.count] = vddc; ++ pi->vddc_leakage.leakage_id[pi->vddc_leakage.count] = virtual_voltage_id; ++ pi->vddc_leakage.count++; ++ } ++ } ++ } else if (radeon_atom_get_leakage_id_from_vbios(rdev, &leakage_id) == 0) { + for (i = 0; i < CISLANDS_MAX_LEAKAGE_COUNT; i++) { + virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; + if (radeon_atom_get_leakage_vddc_based_on_leakage_params(rdev, &vddc, &vddci, +diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c +index 7b3537c55c77..ab5c26575622 100644 +--- a/drivers/gpu/drm/radeon/cik.c ++++ b/drivers/gpu/drm/radeon/cik.c +@@ -4392,7 +4392,7 @@ struct bonaire_mqd + */ + static int cik_cp_compute_resume(struct radeon_device *rdev) + { +- int r, i, idx; ++ int r, i, j, idx; + u32 tmp; + bool use_doorbell = true; + u64 hqd_gpu_addr; +@@ -4511,7 +4511,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev) + mqd->queue_state.cp_hqd_pq_wptr= 0; + if (RREG32(CP_HQD_ACTIVE) & 1) { + WREG32(CP_HQD_DEQUEUE_REQUEST, 1); +- for (i = 0; i < rdev->usec_timeout; i++) { ++ for (j = 0; j < rdev->usec_timeout; j++) { + if (!(RREG32(CP_HQD_ACTIVE) & 1)) + break; + udelay(1); +@@ -5545,12 +5545,13 @@ static void cik_vm_decode_fault(struct radeon_device *rdev, + void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) + { + struct radeon_ring *ring = &rdev->ring[ridx]; ++ int usepfp = (ridx == RADEON_RING_TYPE_GFX_INDEX); + + if (vm == NULL) + return; + + radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); +- radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | ++ radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) | + WRITE_DATA_DST_SEL(0))); + if (vm->id < 8) { + radeon_ring_write(ring, +@@ -5600,7 +5601,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) + radeon_ring_write(ring, 1 << vm->id); + + /* compute doesn't have PFP */ +- if (ridx == RADEON_RING_TYPE_GFX_INDEX) { ++ if (usepfp) { + /* sync PFP to ME, otherwise we might get invalid PFP reads */ + radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); + radeon_ring_write(ring, 0x0); +diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c +index aac8f487e6df..66ba713ba7d7 100644 +--- a/drivers/gpu/drm/radeon/cik_sdma.c ++++ b/drivers/gpu/drm/radeon/cik_sdma.c +@@ -461,13 +461,6 @@ int cik_sdma_resume(struct radeon_device *rdev) + { + int r; + +- /* Reset dma */ +- WREG32(SRBM_SOFT_RESET, SOFT_RESET_SDMA | SOFT_RESET_SDMA1); +- RREG32(SRBM_SOFT_RESET); +- udelay(50); +- WREG32(SRBM_SOFT_RESET, 0); +- RREG32(SRBM_SOFT_RESET); +- + r = cik_sdma_load_microcode(rdev); + if (r) + return r; +diff --git a/drivers/gpu/drm/radeon/ni_dma.c b/drivers/gpu/drm/radeon/ni_dma.c +index 7cf96b15377f..94fa49e974eb 100644 +--- a/drivers/gpu/drm/radeon/ni_dma.c ++++ b/drivers/gpu/drm/radeon/ni_dma.c +@@ -191,12 +191,6 @@ int cayman_dma_resume(struct radeon_device *rdev) + u32 reg_offset, wb_offset; + int i, r; + +- /* Reset dma */ +- WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1); +- RREG32(SRBM_SOFT_RESET); +- udelay(50); +- WREG32(SRBM_SOFT_RESET, 0); +- + for (i = 0; i < 2; i++) { + if (i == 0) { + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; +diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c +index b2d4c91e6272..99495513f6b1 100644 +--- a/drivers/gpu/drm/radeon/r600_dma.c ++++ b/drivers/gpu/drm/radeon/r600_dma.c +@@ -124,15 +124,6 @@ int r600_dma_resume(struct radeon_device *rdev) + u32 rb_bufsz; + int r; + +- /* Reset dma */ +- if (rdev->family >= CHIP_RV770) +- WREG32(SRBM_SOFT_RESET, RV770_SOFT_RESET_DMA); +- else +- WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA); +- RREG32(SRBM_SOFT_RESET); +- udelay(50); +- WREG32(SRBM_SOFT_RESET, 0); +- + WREG32(DMA_SEM_INCOMPLETE_TIMER_CNTL, 0); + WREG32(DMA_SEM_WAIT_FAIL_TIMER_CNTL, 0); + +diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h +index 08e86f90c9a4..b837e9f9f8ce 100644 +--- a/drivers/gpu/drm/radeon/radeon.h ++++ b/drivers/gpu/drm/radeon/radeon.h +@@ -294,6 +294,9 @@ int radeon_atom_get_leakage_vddc_based_on_leakage_params(struct radeon_device *r + u16 *vddc, u16 *vddci, + u16 virtual_voltage_id, + u16 vbios_voltage_id); ++int radeon_atom_get_voltage_evv(struct radeon_device *rdev, ++ u16 virtual_voltage_id, ++ u16 *voltage); + int radeon_atom_round_to_true_voltage(struct radeon_device *rdev, + u8 voltage_type, + u16 nominal_voltage, +diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c +index 30844814c25a..e2de749327ad 100644 +--- a/drivers/gpu/drm/radeon/radeon_atombios.c ++++ b/drivers/gpu/drm/radeon/radeon_atombios.c +@@ -447,6 +447,13 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, + } + } + ++ /* Fujitsu D3003-S2 board lists DVI-I as DVI-I and VGA */ ++ if ((dev->pdev->device == 0x9805) && ++ (dev->pdev->subsystem_vendor == 0x1734) && ++ (dev->pdev->subsystem_device == 0x11bd)) { ++ if (*connector_type == DRM_MODE_CONNECTOR_VGA) ++ return false; ++ } + + return true; + } +@@ -1955,7 +1962,7 @@ static const char *thermal_controller_names[] = { + "adm1032", + "adm1030", + "max6649", +- "lm64", ++ "lm63", /* lm64 */ + "f75375", + "asc7xxx", + }; +@@ -1966,7 +1973,7 @@ static const char *pp_lib_thermal_controller_names[] = { + "adm1032", + "adm1030", + "max6649", +- "lm64", ++ "lm63", /* lm64 */ + "f75375", + "RV6xx", + "RV770", +@@ -2273,19 +2280,31 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_KV; +- } else if ((controller->ucType == +- ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) || +- (controller->ucType == +- ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) || +- (controller->ucType == +- ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL)) { +- DRM_INFO("Special thermal controller config\n"); ++ } else if (controller->ucType == ++ ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) { ++ DRM_INFO("External GPIO thermal controller %s fan control\n", ++ (controller->ucFanParameters & ++ ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); ++ rdev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO; ++ } else if (controller->ucType == ++ ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) { ++ DRM_INFO("ADT7473 with internal thermal controller %s fan control\n", ++ (controller->ucFanParameters & ++ ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); ++ rdev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL; ++ } else if (controller->ucType == ++ ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) { ++ DRM_INFO("EMC2103 with internal thermal controller %s fan control\n", ++ (controller->ucFanParameters & ++ ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); ++ rdev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL; + } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) { + DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", + pp_lib_thermal_controller_names[controller->ucType], + controller->ucI2cAddress >> 1, + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); ++ rdev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL; + i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); + rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); + if (rdev->pm.i2c_bus) { +@@ -3228,6 +3247,41 @@ int radeon_atom_get_leakage_vddc_based_on_leakage_params(struct radeon_device *r + return 0; + } + ++union get_voltage_info { ++ struct _GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2 in; ++ struct _GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2 evv_out; ++}; ++ ++int radeon_atom_get_voltage_evv(struct radeon_device *rdev, ++ u16 virtual_voltage_id, ++ u16 *voltage) ++{ ++ int index = GetIndexIntoMasterTable(COMMAND, GetVoltageInfo); ++ u32 entry_id; ++ u32 count = rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; ++ union get_voltage_info args; ++ ++ for (entry_id = 0; entry_id < count; entry_id++) { ++ if (rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[entry_id].v == ++ virtual_voltage_id) ++ break; ++ } ++ ++ if (entry_id >= count) ++ return -EINVAL; ++ ++ args.in.ucVoltageType = VOLTAGE_TYPE_VDDC; ++ args.in.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE; ++ args.in.ulSCLKFreq = ++ cpu_to_le32(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[entry_id].clk); ++ ++ atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); ++ ++ *voltage = le16_to_cpu(args.evv_out.usVoltageLevel); ++ ++ return 0; ++} ++ + int radeon_atom_get_voltage_gpio_settings(struct radeon_device *rdev, + u16 voltage_level, u8 voltage_type, + u32 *gpio_value, u32 *gpio_mask) +diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c +index 0bf6f4a2bb97..e39026cc7d07 100644 +--- a/drivers/gpu/drm/radeon/radeon_device.c ++++ b/drivers/gpu/drm/radeon/radeon_device.c +@@ -1314,7 +1314,7 @@ int radeon_device_init(struct radeon_device *rdev, + + r = radeon_init(rdev); + if (r) +- return r; ++ goto failed; + + r = radeon_ib_ring_tests(rdev); + if (r) +@@ -1334,7 +1334,7 @@ int radeon_device_init(struct radeon_device *rdev, + radeon_agp_disable(rdev); + r = radeon_init(rdev); + if (r) +- return r; ++ goto failed; + } + + if ((radeon_testing & 1)) { +@@ -1356,6 +1356,11 @@ int radeon_device_init(struct radeon_device *rdev, + DRM_INFO("radeon: acceleration disabled, skipping benchmarks\n"); + } + return 0; ++ ++failed: ++ if (runtime) ++ vga_switcheroo_fini_domain_pm_ops(rdev->dev); ++ return r; + } + + static void radeon_debugfs_remove_files(struct radeon_device *rdev); +@@ -1376,6 +1381,8 @@ void radeon_device_fini(struct radeon_device *rdev) + radeon_bo_evict_vram(rdev); + radeon_fini(rdev); + vga_switcheroo_unregister_client(rdev->pdev); ++ if (rdev->flags & RADEON_IS_PX) ++ vga_switcheroo_fini_domain_pm_ops(rdev->dev); + vga_client_register(rdev->pdev, NULL, NULL, NULL); + if (rdev->rio_mem) + pci_iounmap(rdev->pdev, rdev->rio_mem); +@@ -1600,7 +1607,6 @@ int radeon_gpu_reset(struct radeon_device *rdev) + radeon_save_bios_scratch_regs(rdev); + /* block TTM */ + resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); +- radeon_pm_suspend(rdev); + radeon_suspend(rdev); + + for (i = 0; i < RADEON_NUM_RINGS; ++i) { +@@ -1646,9 +1652,24 @@ retry: + } + } + +- radeon_pm_resume(rdev); ++ if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) { ++ /* do dpm late init */ ++ r = radeon_pm_late_init(rdev); ++ if (r) { ++ rdev->pm.dpm_enabled = false; ++ DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n"); ++ } ++ } else { ++ /* resume old pm late */ ++ radeon_pm_resume(rdev); ++ } ++ + drm_helper_resume_force_mode(rdev->ddev); + ++ /* set the power state here in case we are a PX system or headless */ ++ if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) ++ radeon_pm_compute_clocks(rdev); ++ + ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); + if (r) { + /* bad news, how to tell it to userspace ? */ +diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c +index ea34a31d3bc8..0bc9106ef435 100644 +--- a/drivers/gpu/drm/radeon/radeon_kms.c ++++ b/drivers/gpu/drm/radeon/radeon_kms.c +@@ -254,7 +254,14 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file + } + break; + case RADEON_INFO_ACCEL_WORKING2: +- *value = rdev->accel_working; ++ if (rdev->family == CHIP_HAWAII) { ++ if (rdev->accel_working) ++ *value = 2; ++ else ++ *value = 0; ++ } else { ++ *value = rdev->accel_working; ++ } + break; + case RADEON_INFO_TILING_CONFIG: + if (rdev->family >= CHIP_BONAIRE) +diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c +index f77d9d0d54b5..cfb513f933d5 100644 +--- a/drivers/gpu/drm/radeon/radeon_pm.c ++++ b/drivers/gpu/drm/radeon/radeon_pm.c +@@ -458,10 +458,6 @@ static ssize_t radeon_get_dpm_state(struct device *dev, + struct radeon_device *rdev = ddev->dev_private; + enum radeon_pm_state_type pm = rdev->pm.dpm.user_state; + +- if ((rdev->flags & RADEON_IS_PX) && +- (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) +- return snprintf(buf, PAGE_SIZE, "off\n"); +- + return snprintf(buf, PAGE_SIZE, "%s\n", + (pm == POWER_STATE_TYPE_BATTERY) ? "battery" : + (pm == POWER_STATE_TYPE_BALANCED) ? "balanced" : "performance"); +@@ -475,11 +471,6 @@ static ssize_t radeon_set_dpm_state(struct device *dev, + struct drm_device *ddev = dev_get_drvdata(dev); + struct radeon_device *rdev = ddev->dev_private; + +- /* Can't set dpm state when the card is off */ +- if ((rdev->flags & RADEON_IS_PX) && +- (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) +- return -EINVAL; +- + mutex_lock(&rdev->pm.mutex); + if (strncmp("battery", buf, strlen("battery")) == 0) + rdev->pm.dpm.user_state = POWER_STATE_TYPE_BATTERY; +@@ -493,7 +484,12 @@ static ssize_t radeon_set_dpm_state(struct device *dev, + goto fail; + } + mutex_unlock(&rdev->pm.mutex); +- radeon_pm_compute_clocks(rdev); ++ ++ /* Can't set dpm state when the card is off */ ++ if (!(rdev->flags & RADEON_IS_PX) || ++ (ddev->switch_power_state == DRM_SWITCH_POWER_ON)) ++ radeon_pm_compute_clocks(rdev); ++ + fail: + return count; + } +@@ -1276,10 +1272,6 @@ int radeon_pm_init(struct radeon_device *rdev) + case CHIP_RS780: + case CHIP_RS880: + case CHIP_RV770: +- case CHIP_BARTS: +- case CHIP_TURKS: +- case CHIP_CAICOS: +- case CHIP_CAYMAN: + /* DPM requires the RLC, RV770+ dGPU requires SMC */ + if (!rdev->rlc_fw) + rdev->pm.pm_method = PM_METHOD_PROFILE; +@@ -1303,6 +1295,10 @@ int radeon_pm_init(struct radeon_device *rdev) + case CHIP_PALM: + case CHIP_SUMO: + case CHIP_SUMO2: ++ case CHIP_BARTS: ++ case CHIP_TURKS: ++ case CHIP_CAICOS: ++ case CHIP_CAYMAN: + case CHIP_ARUBA: + case CHIP_TAHITI: + case CHIP_PITCAIRN: +diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c +index 9006b32d5eed..eb7b60047e86 100644 +--- a/drivers/gpu/drm/radeon/radeon_semaphore.c ++++ b/drivers/gpu/drm/radeon/radeon_semaphore.c +@@ -34,7 +34,7 @@ + int radeon_semaphore_create(struct radeon_device *rdev, + struct radeon_semaphore **semaphore) + { +- uint32_t *cpu_addr; ++ uint64_t *cpu_addr; + int i, r; + + *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL); +diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c +index ea93393374df..559564c1dc97 100644 +--- a/drivers/gpu/drm/radeon/si.c ++++ b/drivers/gpu/drm/radeon/si.c +@@ -4810,7 +4810,7 @@ void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) + + /* write new base address */ + radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); +- radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | ++ radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) | + WRITE_DATA_DST_SEL(0))); + + if (vm->id < 8) { +diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c +index 2da0e17eb960..d9cfa09b2e3f 100644 +--- a/drivers/gpu/drm/radeon/trinity_dpm.c ++++ b/drivers/gpu/drm/radeon/trinity_dpm.c +@@ -1877,7 +1877,16 @@ int trinity_dpm_init(struct radeon_device *rdev) + for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) + pi->at[i] = TRINITY_AT_DFLT; + +- pi->enable_bapm = false; ++ /* There are stability issues reported on with ++ * bapm enabled when switching between AC and battery ++ * power. At the same time, some MSI boards hang ++ * if it's not enabled and dpm is enabled. Just enable ++ * it for MSI boards right now. ++ */ ++ if (rdev->pdev->subsystem_vendor == 0x1462) ++ pi->enable_bapm = true; ++ else ++ pi->enable_bapm = false; + pi->enable_nbps_policy = true; + pi->enable_sclk_ds = true; + pi->enable_gfx_power_gating = true; +diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c +index 171a8203892c..0644429f8559 100644 +--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c ++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c +@@ -122,6 +122,7 @@ static int tilcdc_unload(struct drm_device *dev) + struct tilcdc_drm_private *priv = dev->dev_private; + struct tilcdc_module *mod, *cur; + ++ drm_fbdev_cma_fini(priv->fbdev); + drm_kms_helper_poll_fini(dev); + drm_mode_config_cleanup(dev); + drm_vblank_cleanup(dev); +@@ -628,10 +629,10 @@ static int __init tilcdc_drm_init(void) + static void __exit tilcdc_drm_fini(void) + { + DBG("fini"); +- tilcdc_tfp410_fini(); +- tilcdc_slave_fini(); +- tilcdc_panel_fini(); + platform_driver_unregister(&tilcdc_platform_driver); ++ tilcdc_panel_fini(); ++ tilcdc_slave_fini(); ++ tilcdc_tfp410_fini(); + } + + late_initcall(tilcdc_drm_init); +diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c +index 86c67329b605..b085dcc54fb5 100644 +--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c ++++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c +@@ -151,6 +151,7 @@ struct panel_connector { + static void panel_connector_destroy(struct drm_connector *connector) + { + struct panel_connector *panel_connector = to_panel_connector(connector); ++ drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(panel_connector); + } +@@ -285,10 +286,8 @@ static void panel_destroy(struct tilcdc_module *mod) + { + struct panel_module *panel_mod = to_panel_module(mod); + +- if (panel_mod->timings) { ++ if (panel_mod->timings) + display_timings_release(panel_mod->timings); +- kfree(panel_mod->timings); +- } + + tilcdc_module_cleanup(mod); + kfree(panel_mod->info); +diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c +index 595068ba2d5e..2f83ffb7f37e 100644 +--- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c ++++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c +@@ -166,6 +166,7 @@ struct slave_connector { + static void slave_connector_destroy(struct drm_connector *connector) + { + struct slave_connector *slave_connector = to_slave_connector(connector); ++ drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(slave_connector); + } +diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +index c38b56b268ac..ce75ac8de4f8 100644 +--- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c ++++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +@@ -167,6 +167,7 @@ struct tfp410_connector { + static void tfp410_connector_destroy(struct drm_connector *connector) + { + struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector); ++ drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(tfp410_connector); + } +diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c +index 863bef9f9234..cf4bad2c1d59 100644 +--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c ++++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c +@@ -297,8 +297,10 @@ static void ttm_pool_update_free_locked(struct ttm_page_pool *pool, + * + * @pool: to free the pages from + * @free_all: If set to true will free all pages in pool ++ * @gfp: GFP flags. + **/ +-static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free) ++static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free, ++ gfp_t gfp) + { + unsigned long irq_flags; + struct page *p; +@@ -309,8 +311,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free) + if (NUM_PAGES_TO_ALLOC < nr_free) + npages_to_free = NUM_PAGES_TO_ALLOC; + +- pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), +- GFP_KERNEL); ++ pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp); + if (!pages_to_free) { + pr_err("Failed to allocate memory for pool free operation\n"); + return 0; +@@ -382,32 +383,35 @@ out: + * + * XXX: (dchinner) Deadlock warning! + * +- * ttm_page_pool_free() does memory allocation using GFP_KERNEL. that means +- * this can deadlock when called a sc->gfp_mask that is not equal to +- * GFP_KERNEL. ++ * We need to pass sc->gfp_mask to ttm_page_pool_free(). + * + * This code is crying out for a shrinker per pool.... + */ + static unsigned long + ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) + { +- static atomic_t start_pool = ATOMIC_INIT(0); ++ static DEFINE_MUTEX(lock); ++ static unsigned start_pool; + unsigned i; +- unsigned pool_offset = atomic_add_return(1, &start_pool); ++ unsigned pool_offset; + struct ttm_page_pool *pool; + int shrink_pages = sc->nr_to_scan; + unsigned long freed = 0; + +- pool_offset = pool_offset % NUM_POOLS; ++ if (!mutex_trylock(&lock)) ++ return SHRINK_STOP; ++ pool_offset = ++start_pool % NUM_POOLS; + /* select start pool in round robin fashion */ + for (i = 0; i < NUM_POOLS; ++i) { + unsigned nr_free = shrink_pages; + if (shrink_pages == 0) + break; + pool = &_manager->pools[(i + pool_offset)%NUM_POOLS]; +- shrink_pages = ttm_page_pool_free(pool, nr_free); ++ shrink_pages = ttm_page_pool_free(pool, nr_free, ++ sc->gfp_mask); + freed += nr_free - shrink_pages; + } ++ mutex_unlock(&lock); + return freed; + } + +@@ -706,7 +710,7 @@ static void ttm_put_pages(struct page **pages, unsigned npages, int flags, + } + spin_unlock_irqrestore(&pool->lock, irq_flags); + if (npages) +- ttm_page_pool_free(pool, npages); ++ ttm_page_pool_free(pool, npages, GFP_KERNEL); + } + + /* +@@ -846,7 +850,8 @@ void ttm_page_alloc_fini(void) + ttm_pool_mm_shrink_fini(_manager); + + for (i = 0; i < NUM_POOLS; ++i) +- ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES); ++ ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES, ++ GFP_KERNEL); + + kobject_put(&_manager->kobj); + _manager = NULL; +diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +index fb8259f69839..ca65df144765 100644 +--- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c ++++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +@@ -411,8 +411,10 @@ static void ttm_dma_page_put(struct dma_pool *pool, struct dma_page *d_page) + * + * @pool: to free the pages from + * @nr_free: If set to true will free all pages in pool ++ * @gfp: GFP flags. + **/ +-static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free) ++static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free, ++ gfp_t gfp) + { + unsigned long irq_flags; + struct dma_page *dma_p, *tmp; +@@ -430,8 +432,7 @@ static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free) + npages_to_free, nr_free); + } + #endif +- pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), +- GFP_KERNEL); ++ pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp); + + if (!pages_to_free) { + pr_err("%s: Failed to allocate memory for pool free operation\n", +@@ -530,7 +531,7 @@ static void ttm_dma_free_pool(struct device *dev, enum pool_type type) + if (pool->type != type) + continue; + /* Takes a spinlock.. */ +- ttm_dma_page_pool_free(pool, FREE_ALL_PAGES); ++ ttm_dma_page_pool_free(pool, FREE_ALL_PAGES, GFP_KERNEL); + WARN_ON(((pool->npages_in_use + pool->npages_free) != 0)); + /* This code path is called after _all_ references to the + * struct device has been dropped - so nobody should be +@@ -983,7 +984,7 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev) + + /* shrink pool if necessary (only on !is_cached pools)*/ + if (npages) +- ttm_dma_page_pool_free(pool, npages); ++ ttm_dma_page_pool_free(pool, npages, GFP_KERNEL); + ttm->state = tt_unpopulated; + } + EXPORT_SYMBOL_GPL(ttm_dma_unpopulate); +@@ -993,10 +994,7 @@ EXPORT_SYMBOL_GPL(ttm_dma_unpopulate); + * + * XXX: (dchinner) Deadlock warning! + * +- * ttm_dma_page_pool_free() does GFP_KERNEL memory allocation, and so attention +- * needs to be paid to sc->gfp_mask to determine if this can be done or not. +- * GFP_KERNEL memory allocation in a GFP_ATOMIC reclaim context woul dbe really +- * bad. ++ * We need to pass sc->gfp_mask to ttm_dma_page_pool_free(). + * + * I'm getting sadder as I hear more pathetical whimpers about needing per-pool + * shrinkers +@@ -1004,9 +1002,9 @@ EXPORT_SYMBOL_GPL(ttm_dma_unpopulate); + static unsigned long + ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) + { +- static atomic_t start_pool = ATOMIC_INIT(0); ++ static unsigned start_pool; + unsigned idx = 0; +- unsigned pool_offset = atomic_add_return(1, &start_pool); ++ unsigned pool_offset; + unsigned shrink_pages = sc->nr_to_scan; + struct device_pools *p; + unsigned long freed = 0; +@@ -1014,8 +1012,11 @@ ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) + if (list_empty(&_manager->pools)) + return SHRINK_STOP; + +- mutex_lock(&_manager->lock); +- pool_offset = pool_offset % _manager->npools; ++ if (!mutex_trylock(&_manager->lock)) ++ return SHRINK_STOP; ++ if (!_manager->npools) ++ goto out; ++ pool_offset = ++start_pool % _manager->npools; + list_for_each_entry(p, &_manager->pools, pools) { + unsigned nr_free; + +@@ -1027,13 +1028,15 @@ ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) + if (++idx < pool_offset) + continue; + nr_free = shrink_pages; +- shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free); ++ shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free, ++ sc->gfp_mask); + freed += nr_free - shrink_pages; + + pr_debug("%s: (%s:%d) Asked to shrink %d, have %d more to go\n", + p->pool->dev_name, p->pool->name, current->pid, + nr_free, shrink_pages); + } ++out: + mutex_unlock(&_manager->lock); + return freed; + } +@@ -1044,7 +1047,8 @@ ttm_dma_pool_shrink_count(struct shrinker *shrink, struct shrink_control *sc) + struct device_pools *p; + unsigned long count = 0; + +- mutex_lock(&_manager->lock); ++ if (!mutex_trylock(&_manager->lock)) ++ return 0; + list_for_each_entry(p, &_manager->pools, pools) + count += p->pool->npages_free; + mutex_unlock(&_manager->lock); +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +index 6ccd993e26bf..6eae14d2a3f7 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +@@ -180,8 +180,9 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) + + mutex_lock(&dev_priv->hw_mutex); + ++ vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC); + while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0) +- vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC); ++ ; + + dev_priv->last_read_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE); + +diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c +index 6866448083b2..37ac7b5dbd06 100644 +--- a/drivers/gpu/vga/vga_switcheroo.c ++++ b/drivers/gpu/vga/vga_switcheroo.c +@@ -660,6 +660,12 @@ int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain * + } + EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_ops); + ++void vga_switcheroo_fini_domain_pm_ops(struct device *dev) ++{ ++ dev->pm_domain = NULL; ++} ++EXPORT_SYMBOL(vga_switcheroo_fini_domain_pm_ops); ++ + static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev) + { + struct pci_dev *pdev = to_pci_dev(dev); +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 0b14d3261531..5da115a6fd22 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -687,7 +687,6 @@ static int logi_dj_raw_event(struct hid_device *hdev, + struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); + struct dj_report *dj_report = (struct dj_report *) data; + unsigned long flags; +- bool report_processed = false; + + dbg_hid("%s, size:%d\n", __func__, size); + +@@ -714,34 +713,42 @@ static int logi_dj_raw_event(struct hid_device *hdev, + * device (via hid_input_report() ) and return 1 so hid-core does not do + * anything else with it. + */ ++ ++ /* case 1) */ ++ if (data[0] != REPORT_ID_DJ_SHORT) ++ return false; ++ + if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) || + (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) { +- dev_err(&hdev->dev, "%s: invalid device index:%d\n", ++ /* ++ * Device index is wrong, bail out. ++ * This driver can ignore safely the receiver notifications, ++ * so ignore those reports too. ++ */ ++ if (dj_report->device_index != DJ_RECEIVER_INDEX) ++ dev_err(&hdev->dev, "%s: invalid device index:%d\n", + __func__, dj_report->device_index); + return false; + } + + spin_lock_irqsave(&djrcv_dev->lock, flags); +- if (dj_report->report_id == REPORT_ID_DJ_SHORT) { +- switch (dj_report->report_type) { +- case REPORT_TYPE_NOTIF_DEVICE_PAIRED: +- case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED: +- logi_dj_recv_queue_notification(djrcv_dev, dj_report); +- break; +- case REPORT_TYPE_NOTIF_CONNECTION_STATUS: +- if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] == +- STATUS_LINKLOSS) { +- logi_dj_recv_forward_null_report(djrcv_dev, dj_report); +- } +- break; +- default: +- logi_dj_recv_forward_report(djrcv_dev, dj_report); ++ switch (dj_report->report_type) { ++ case REPORT_TYPE_NOTIF_DEVICE_PAIRED: ++ case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED: ++ logi_dj_recv_queue_notification(djrcv_dev, dj_report); ++ break; ++ case REPORT_TYPE_NOTIF_CONNECTION_STATUS: ++ if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] == ++ STATUS_LINKLOSS) { ++ logi_dj_recv_forward_null_report(djrcv_dev, dj_report); + } +- report_processed = true; ++ break; ++ default: ++ logi_dj_recv_forward_report(djrcv_dev, dj_report); + } + spin_unlock_irqrestore(&djrcv_dev->lock, flags); + +- return report_processed; ++ return true; + } + + static int logi_dj_probe(struct hid_device *hdev, +diff --git a/drivers/hid/hid-logitech-dj.h b/drivers/hid/hid-logitech-dj.h +index 4a4000340ce1..daeb0aa4bee9 100644 +--- a/drivers/hid/hid-logitech-dj.h ++++ b/drivers/hid/hid-logitech-dj.h +@@ -27,6 +27,7 @@ + + #define DJ_MAX_PAIRED_DEVICES 6 + #define DJ_MAX_NUMBER_NOTIFICATIONS 8 ++#define DJ_RECEIVER_INDEX 0 + #define DJ_DEVICE_INDEX_MIN 1 + #define DJ_DEVICE_INDEX_MAX 6 + +diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c +index 3b43d1cfa936..991ba79cfc72 100644 +--- a/drivers/hid/hid-magicmouse.c ++++ b/drivers/hid/hid-magicmouse.c +@@ -290,6 +290,11 @@ static int magicmouse_raw_event(struct hid_device *hdev, + if (size < 4 || ((size - 4) % 9) != 0) + return 0; + npoints = (size - 4) / 9; ++ if (npoints > 15) { ++ hid_warn(hdev, "invalid size value (%d) for TRACKPAD_REPORT_ID\n", ++ size); ++ return 0; ++ } + msc->ntouches = 0; + for (ii = 0; ii < npoints; ii++) + magicmouse_emit_touch(msc, ii, data + ii * 9 + 4); +@@ -307,6 +312,11 @@ static int magicmouse_raw_event(struct hid_device *hdev, + if (size < 6 || ((size - 6) % 8) != 0) + return 0; + npoints = (size - 6) / 8; ++ if (npoints > 15) { ++ hid_warn(hdev, "invalid size value (%d) for MOUSE_REPORT_ID\n", ++ size); ++ return 0; ++ } + msc->ntouches = 0; + for (ii = 0; ii < npoints; ii++) + magicmouse_emit_touch(msc, ii, data + ii * 8 + 6); +diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c +index acbb021065ec..020df3c2e8b4 100644 +--- a/drivers/hid/hid-picolcd_core.c ++++ b/drivers/hid/hid-picolcd_core.c +@@ -350,6 +350,12 @@ static int picolcd_raw_event(struct hid_device *hdev, + if (!data) + return 1; + ++ if (size > 64) { ++ hid_warn(hdev, "invalid size value (%d) for picolcd raw event\n", ++ size); ++ return 0; ++ } ++ + if (report->id == REPORT_KEY_STATE) { + if (data->input_keys) + ret = picolcd_raw_keypad(data, report, raw_data+1, size-1); +diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c +index fc6f5d54e7f7..8890870309e4 100644 +--- a/drivers/hwmon/ds1621.c ++++ b/drivers/hwmon/ds1621.c +@@ -309,6 +309,7 @@ static ssize_t set_convrate(struct device *dev, struct device_attribute *da, + data->conf |= (resol << DS1621_REG_CONFIG_RESOL_SHIFT); + i2c_smbus_write_byte_data(client, DS1621_REG_CONF, data->conf); + data->update_interval = ds1721_convrates[resol]; ++ data->zbits = 7 - resol; + mutex_unlock(&data->update_lock); + + return count; +diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c +index c56be739006b..11e9c7f9bf9b 100644 +--- a/drivers/i2c/busses/i2c-at91.c ++++ b/drivers/i2c/busses/i2c-at91.c +@@ -101,6 +101,7 @@ struct at91_twi_dev { + unsigned twi_cwgr_reg; + struct at91_twi_pdata *pdata; + bool use_dma; ++ bool recv_len_abort; + struct at91_twi_dma dma; + }; + +@@ -267,12 +268,24 @@ static void at91_twi_read_next_byte(struct at91_twi_dev *dev) + *dev->buf = at91_twi_read(dev, AT91_TWI_RHR) & 0xff; + --dev->buf_len; + ++ /* return if aborting, we only needed to read RHR to clear RXRDY*/ ++ if (dev->recv_len_abort) ++ return; ++ + /* handle I2C_SMBUS_BLOCK_DATA */ + if (unlikely(dev->msg->flags & I2C_M_RECV_LEN)) { +- dev->msg->flags &= ~I2C_M_RECV_LEN; +- dev->buf_len += *dev->buf; +- dev->msg->len = dev->buf_len + 1; +- dev_dbg(dev->dev, "received block length %d\n", dev->buf_len); ++ /* ensure length byte is a valid value */ ++ if (*dev->buf <= I2C_SMBUS_BLOCK_MAX && *dev->buf > 0) { ++ dev->msg->flags &= ~I2C_M_RECV_LEN; ++ dev->buf_len += *dev->buf; ++ dev->msg->len = dev->buf_len + 1; ++ dev_dbg(dev->dev, "received block length %d\n", ++ dev->buf_len); ++ } else { ++ /* abort and send the stop by reading one more byte */ ++ dev->recv_len_abort = true; ++ dev->buf_len = 1; ++ } + } + + /* send stop if second but last byte has been read */ +@@ -421,8 +434,8 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) + } + } + +- ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, +- dev->adapter.timeout); ++ ret = wait_for_completion_io_timeout(&dev->cmd_complete, ++ dev->adapter.timeout); + if (ret == 0) { + dev_err(dev->dev, "controller timed out\n"); + at91_init_twi_bus(dev); +@@ -444,6 +457,12 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) + ret = -EIO; + goto error; + } ++ if (dev->recv_len_abort) { ++ dev_err(dev->dev, "invalid smbus block length recvd\n"); ++ ret = -EPROTO; ++ goto error; ++ } ++ + dev_dbg(dev->dev, "transfer complete\n"); + + return 0; +@@ -500,6 +519,7 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) + dev->buf_len = m_start->len; + dev->buf = m_start->buf; + dev->msg = m_start; ++ dev->recv_len_abort = false; + + ret = at91_do_twi_transfer(dev); + +diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c +index 8ce4f517fc56..6e932d140573 100644 +--- a/drivers/i2c/busses/i2c-ismt.c ++++ b/drivers/i2c/busses/i2c-ismt.c +@@ -497,7 +497,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, + desc->wr_len_cmd = dma_size; + desc->control |= ISMT_DESC_BLK; + priv->dma_buffer[0] = command; +- memcpy(&priv->dma_buffer[1], &data->block[1], dma_size); ++ memcpy(&priv->dma_buffer[1], &data->block[1], dma_size - 1); + } else { + /* Block Read */ + dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA: READ\n"); +@@ -525,7 +525,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, + desc->wr_len_cmd = dma_size; + desc->control |= ISMT_DESC_I2C; + priv->dma_buffer[0] = command; +- memcpy(&priv->dma_buffer[1], &data->block[1], dma_size); ++ memcpy(&priv->dma_buffer[1], &data->block[1], dma_size - 1); + } else { + /* i2c Block Read */ + dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA: READ\n"); +diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c +index d52d84937ad3..cf891752cc73 100644 +--- a/drivers/i2c/busses/i2c-mv64xxx.c ++++ b/drivers/i2c/busses/i2c-mv64xxx.c +@@ -748,8 +748,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, + } + tclk = clk_get_rate(drv_data->clk); + +- rc = of_property_read_u32(np, "clock-frequency", &bus_freq); +- if (rc) ++ if (of_property_read_u32(np, "clock-frequency", &bus_freq)) + bus_freq = 100000; /* 100kHz by default */ + + if (!mv64xxx_find_baud_factors(bus_freq, tclk, +diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c +index fe83d04784c8..6f039c300141 100644 +--- a/drivers/iio/accel/bma180.c ++++ b/drivers/iio/accel/bma180.c +@@ -571,7 +571,7 @@ static int bma180_probe(struct i2c_client *client, + trig->ops = &bma180_trigger_ops; + iio_trigger_set_drvdata(trig, indio_dev); + data->trig = trig; +- indio_dev->trig = trig; ++ indio_dev->trig = iio_trigger_get(trig); + + ret = iio_trigger_register(trig); + if (ret) +diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c +index 9a4e0e32a771..eb799a43aef0 100644 +--- a/drivers/iio/adc/ad_sigma_delta.c ++++ b/drivers/iio/adc/ad_sigma_delta.c +@@ -472,7 +472,7 @@ static int ad_sd_probe_trigger(struct iio_dev *indio_dev) + goto error_free_irq; + + /* select default trigger */ +- indio_dev->trig = sigma_delta->trig; ++ indio_dev->trig = iio_trigger_get(sigma_delta->trig); + + return 0; + +diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +index 7dcf83998e6f..1be235b01934 100644 +--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c ++++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +@@ -99,7 +99,8 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, + dev_err(&indio_dev->dev, "Trigger Register Failed\n"); + goto error_free_trig; + } +- indio_dev->trig = attrb->trigger = trig; ++ attrb->trigger = trig; ++ indio_dev->trig = iio_trigger_get(trig); + + return ret; + +diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c +index 8fc3a97eb266..8d8ca6f1e16a 100644 +--- a/drivers/iio/common/st_sensors/st_sensors_trigger.c ++++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c +@@ -49,7 +49,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, + dev_err(&indio_dev->dev, "failed to register iio trigger.\n"); + goto iio_trigger_register_error; + } +- indio_dev->trig = sdata->trig; ++ indio_dev->trig = iio_trigger_get(sdata->trig); + + return 0; + +diff --git a/drivers/iio/gyro/itg3200_buffer.c b/drivers/iio/gyro/itg3200_buffer.c +index e3b3c5084070..eef50e91f17c 100644 +--- a/drivers/iio/gyro/itg3200_buffer.c ++++ b/drivers/iio/gyro/itg3200_buffer.c +@@ -132,7 +132,7 @@ int itg3200_probe_trigger(struct iio_dev *indio_dev) + goto error_free_irq; + + /* select default trigger */ +- indio_dev->trig = st->trig; ++ indio_dev->trig = iio_trigger_get(st->trig); + + return 0; + +diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +index 03b9372c1212..926fccea8de0 100644 +--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c ++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +@@ -135,7 +135,7 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev) + ret = iio_trigger_register(st->trig); + if (ret) + goto error_free_irq; +- indio_dev->trig = st->trig; ++ indio_dev->trig = iio_trigger_get(st->trig); + + return 0; + +diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c +index 1e8e94d4db7d..4fc88e617acf 100644 +--- a/drivers/iio/inkern.c ++++ b/drivers/iio/inkern.c +@@ -178,7 +178,7 @@ static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np, + index = of_property_match_string(np, "io-channel-names", + name); + chan = of_iio_channel_get(np, index); +- if (!IS_ERR(chan)) ++ if (!IS_ERR(chan) || PTR_ERR(chan) == -EPROBE_DEFER) + break; + else if (name && index >= 0) { + pr_err("ERROR: could not get IIO channel %s:%s(%i)\n", +diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c +index 52bbcfa1e077..476aa132a192 100644 +--- a/drivers/iio/magnetometer/st_magn_core.c ++++ b/drivers/iio/magnetometer/st_magn_core.c +@@ -42,7 +42,8 @@ + #define ST_MAGN_FS_AVL_5600MG 5600 + #define ST_MAGN_FS_AVL_8000MG 8000 + #define ST_MAGN_FS_AVL_8100MG 8100 +-#define ST_MAGN_FS_AVL_10000MG 10000 ++#define ST_MAGN_FS_AVL_12000MG 12000 ++#define ST_MAGN_FS_AVL_16000MG 16000 + + /* CUSTOM VALUES FOR SENSOR 1 */ + #define ST_MAGN_1_WAI_EXP 0x3c +@@ -69,20 +70,20 @@ + #define ST_MAGN_1_FS_AVL_4700_VAL 0x05 + #define ST_MAGN_1_FS_AVL_5600_VAL 0x06 + #define ST_MAGN_1_FS_AVL_8100_VAL 0x07 +-#define ST_MAGN_1_FS_AVL_1300_GAIN_XY 1100 +-#define ST_MAGN_1_FS_AVL_1900_GAIN_XY 855 +-#define ST_MAGN_1_FS_AVL_2500_GAIN_XY 670 +-#define ST_MAGN_1_FS_AVL_4000_GAIN_XY 450 +-#define ST_MAGN_1_FS_AVL_4700_GAIN_XY 400 +-#define ST_MAGN_1_FS_AVL_5600_GAIN_XY 330 +-#define ST_MAGN_1_FS_AVL_8100_GAIN_XY 230 +-#define ST_MAGN_1_FS_AVL_1300_GAIN_Z 980 +-#define ST_MAGN_1_FS_AVL_1900_GAIN_Z 760 +-#define ST_MAGN_1_FS_AVL_2500_GAIN_Z 600 +-#define ST_MAGN_1_FS_AVL_4000_GAIN_Z 400 +-#define ST_MAGN_1_FS_AVL_4700_GAIN_Z 355 +-#define ST_MAGN_1_FS_AVL_5600_GAIN_Z 295 +-#define ST_MAGN_1_FS_AVL_8100_GAIN_Z 205 ++#define ST_MAGN_1_FS_AVL_1300_GAIN_XY 909 ++#define ST_MAGN_1_FS_AVL_1900_GAIN_XY 1169 ++#define ST_MAGN_1_FS_AVL_2500_GAIN_XY 1492 ++#define ST_MAGN_1_FS_AVL_4000_GAIN_XY 2222 ++#define ST_MAGN_1_FS_AVL_4700_GAIN_XY 2500 ++#define ST_MAGN_1_FS_AVL_5600_GAIN_XY 3030 ++#define ST_MAGN_1_FS_AVL_8100_GAIN_XY 4347 ++#define ST_MAGN_1_FS_AVL_1300_GAIN_Z 1020 ++#define ST_MAGN_1_FS_AVL_1900_GAIN_Z 1315 ++#define ST_MAGN_1_FS_AVL_2500_GAIN_Z 1666 ++#define ST_MAGN_1_FS_AVL_4000_GAIN_Z 2500 ++#define ST_MAGN_1_FS_AVL_4700_GAIN_Z 2816 ++#define ST_MAGN_1_FS_AVL_5600_GAIN_Z 3389 ++#define ST_MAGN_1_FS_AVL_8100_GAIN_Z 4878 + #define ST_MAGN_1_MULTIREAD_BIT false + + /* CUSTOM VALUES FOR SENSOR 2 */ +@@ -105,10 +106,12 @@ + #define ST_MAGN_2_FS_MASK 0x60 + #define ST_MAGN_2_FS_AVL_4000_VAL 0x00 + #define ST_MAGN_2_FS_AVL_8000_VAL 0x01 +-#define ST_MAGN_2_FS_AVL_10000_VAL 0x02 +-#define ST_MAGN_2_FS_AVL_4000_GAIN 430 +-#define ST_MAGN_2_FS_AVL_8000_GAIN 230 +-#define ST_MAGN_2_FS_AVL_10000_GAIN 230 ++#define ST_MAGN_2_FS_AVL_12000_VAL 0x02 ++#define ST_MAGN_2_FS_AVL_16000_VAL 0x03 ++#define ST_MAGN_2_FS_AVL_4000_GAIN 146 ++#define ST_MAGN_2_FS_AVL_8000_GAIN 292 ++#define ST_MAGN_2_FS_AVL_12000_GAIN 438 ++#define ST_MAGN_2_FS_AVL_16000_GAIN 584 + #define ST_MAGN_2_MULTIREAD_BIT false + #define ST_MAGN_2_OUT_X_L_ADDR 0x28 + #define ST_MAGN_2_OUT_Y_L_ADDR 0x2a +@@ -266,9 +269,14 @@ static const struct st_sensors st_magn_sensors[] = { + .gain = ST_MAGN_2_FS_AVL_8000_GAIN, + }, + [2] = { +- .num = ST_MAGN_FS_AVL_10000MG, +- .value = ST_MAGN_2_FS_AVL_10000_VAL, +- .gain = ST_MAGN_2_FS_AVL_10000_GAIN, ++ .num = ST_MAGN_FS_AVL_12000MG, ++ .value = ST_MAGN_2_FS_AVL_12000_VAL, ++ .gain = ST_MAGN_2_FS_AVL_12000_GAIN, ++ }, ++ [3] = { ++ .num = ST_MAGN_FS_AVL_16000MG, ++ .value = ST_MAGN_2_FS_AVL_16000_VAL, ++ .gain = ST_MAGN_2_FS_AVL_16000_GAIN, + }, + }, + }, +diff --git a/drivers/infiniband/core/uverbs_marshall.c b/drivers/infiniband/core/uverbs_marshall.c +index e7bee46868d1..abd97247443e 100644 +--- a/drivers/infiniband/core/uverbs_marshall.c ++++ b/drivers/infiniband/core/uverbs_marshall.c +@@ -140,5 +140,9 @@ void ib_copy_path_rec_from_user(struct ib_sa_path_rec *dst, + dst->packet_life_time = src->packet_life_time; + dst->preference = src->preference; + dst->packet_life_time_selector = src->packet_life_time_selector; ++ ++ memset(dst->smac, 0, sizeof(dst->smac)); ++ memset(dst->dmac, 0, sizeof(dst->dmac)); ++ dst->vlan_id = 0xffff; + } + EXPORT_SYMBOL(ib_copy_path_rec_from_user); +diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c +index f9c12e92fdd6..11f0606792bb 100644 +--- a/drivers/infiniband/hw/mlx4/main.c ++++ b/drivers/infiniband/hw/mlx4/main.c +@@ -1622,6 +1622,7 @@ static void mlx4_ib_get_dev_addr(struct net_device *dev, + struct inet6_dev *in6_dev; + union ib_gid *pgid; + struct inet6_ifaddr *ifp; ++ union ib_gid default_gid; + #endif + union ib_gid gid; + +@@ -1642,12 +1643,15 @@ static void mlx4_ib_get_dev_addr(struct net_device *dev, + in_dev_put(in_dev); + } + #if IS_ENABLED(CONFIG_IPV6) ++ mlx4_make_default_gid(dev, &default_gid); + /* IPv6 gids */ + in6_dev = in6_dev_get(dev); + if (in6_dev) { + read_lock_bh(&in6_dev->lock); + list_for_each_entry(ifp, &in6_dev->addr_list, if_list) { + pgid = (union ib_gid *)&ifp->addr; ++ if (!memcmp(pgid, &default_gid, sizeof(*pgid))) ++ continue; + update_gid_table(ibdev, port, pgid, 0, 0); + } + read_unlock_bh(&in6_dev->lock); +@@ -1723,31 +1727,34 @@ static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev) + port_state = (netif_running(curr_netdev) && netif_carrier_ok(curr_netdev)) ? + IB_PORT_ACTIVE : IB_PORT_DOWN; + mlx4_ib_set_default_gid(ibdev, curr_netdev, port); +- } else { +- reset_gid_table(ibdev, port); +- } +- /* if using bonding/team and a slave port is down, we don't the bond IP +- * based gids in the table since flows that select port by gid may get +- * the down port. +- */ +- if (curr_master && (port_state == IB_PORT_DOWN)) { +- reset_gid_table(ibdev, port); +- mlx4_ib_set_default_gid(ibdev, curr_netdev, port); +- } +- /* if bonding is used it is possible that we add it to masters +- * only after IP address is assigned to the net bonding +- * interface. +- */ +- if (curr_master && (old_master != curr_master)) { +- reset_gid_table(ibdev, port); +- mlx4_ib_set_default_gid(ibdev, curr_netdev, port); +- mlx4_ib_get_dev_addr(curr_master, ibdev, port); +- } ++ /* if using bonding/team and a slave port is down, we ++ * don't the bond IP based gids in the table since ++ * flows that select port by gid may get the down port. ++ */ ++ if (curr_master && (port_state == IB_PORT_DOWN)) { ++ reset_gid_table(ibdev, port); ++ mlx4_ib_set_default_gid(ibdev, ++ curr_netdev, port); ++ } ++ /* if bonding is used it is possible that we add it to ++ * masters only after IP address is assigned to the ++ * net bonding interface. ++ */ ++ if (curr_master && (old_master != curr_master)) { ++ reset_gid_table(ibdev, port); ++ mlx4_ib_set_default_gid(ibdev, ++ curr_netdev, port); ++ mlx4_ib_get_dev_addr(curr_master, ibdev, port); ++ } + +- if (!curr_master && (old_master != curr_master)) { ++ if (!curr_master && (old_master != curr_master)) { ++ reset_gid_table(ibdev, port); ++ mlx4_ib_set_default_gid(ibdev, ++ curr_netdev, port); ++ mlx4_ib_get_dev_addr(curr_netdev, ibdev, port); ++ } ++ } else { + reset_gid_table(ibdev, port); +- mlx4_ib_set_default_gid(ibdev, curr_netdev, port); +- mlx4_ib_get_dev_addr(curr_netdev, ibdev, port); + } + } + +diff --git a/drivers/infiniband/hw/qib/qib_debugfs.c b/drivers/infiniband/hw/qib/qib_debugfs.c +index 799a0c3bffc4..6abd3ed3cd51 100644 +--- a/drivers/infiniband/hw/qib/qib_debugfs.c ++++ b/drivers/infiniband/hw/qib/qib_debugfs.c +@@ -193,6 +193,7 @@ static void *_qp_stats_seq_start(struct seq_file *s, loff_t *pos) + struct qib_qp_iter *iter; + loff_t n = *pos; + ++ rcu_read_lock(); + iter = qib_qp_iter_init(s->private); + if (!iter) + return NULL; +@@ -224,7 +225,7 @@ static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr, + + static void _qp_stats_seq_stop(struct seq_file *s, void *iter_ptr) + { +- /* nothing for now */ ++ rcu_read_unlock(); + } + + static int _qp_stats_seq_show(struct seq_file *s, void *iter_ptr) +diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c +index 0cad0c40d742..6a71b2b41b27 100644 +--- a/drivers/infiniband/hw/qib/qib_qp.c ++++ b/drivers/infiniband/hw/qib/qib_qp.c +@@ -1324,7 +1324,6 @@ int qib_qp_iter_next(struct qib_qp_iter *iter) + struct qib_qp *pqp = iter->qp; + struct qib_qp *qp; + +- rcu_read_lock(); + for (; n < dev->qp_table_size; n++) { + if (pqp) + qp = rcu_dereference(pqp->next); +@@ -1332,18 +1331,11 @@ int qib_qp_iter_next(struct qib_qp_iter *iter) + qp = rcu_dereference(dev->qp_table[n]); + pqp = qp; + if (qp) { +- if (iter->qp) +- atomic_dec(&iter->qp->refcount); +- atomic_inc(&qp->refcount); +- rcu_read_unlock(); + iter->qp = qp; + iter->n = n; + return 0; + } + } +- rcu_read_unlock(); +- if (iter->qp) +- atomic_dec(&iter->qp->refcount); + return ret; + } + +diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c +index 156205a81523..c5c194c2e0b6 100644 +--- a/drivers/infiniband/ulp/isert/ib_isert.c ++++ b/drivers/infiniband/ulp/isert/ib_isert.c +@@ -511,7 +511,6 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + init_completion(&isert_conn->conn_wait); + init_completion(&isert_conn->conn_wait_comp_err); + kref_init(&isert_conn->conn_kref); +- kref_get(&isert_conn->conn_kref); + mutex_init(&isert_conn->conn_mutex); + spin_lock_init(&isert_conn->conn_lock); + INIT_LIST_HEAD(&isert_conn->conn_fr_pool); +@@ -663,7 +662,9 @@ isert_connect_release(struct isert_conn *isert_conn) + static void + isert_connected_handler(struct rdma_cm_id *cma_id) + { +- return; ++ struct isert_conn *isert_conn = cma_id->context; ++ ++ kref_get(&isert_conn->conn_kref); + } + + static void +@@ -715,7 +716,6 @@ isert_disconnect_work(struct work_struct *work) + + wake_up: + complete(&isert_conn->conn_wait); +- isert_put_conn(isert_conn); + } + + static void +@@ -2800,6 +2800,7 @@ static void isert_wait_conn(struct iscsi_conn *conn) + wait_for_completion(&isert_conn->conn_wait_comp_err); + + wait_for_completion(&isert_conn->conn_wait); ++ isert_put_conn(isert_conn); + } + + static void isert_free_conn(struct iscsi_conn *conn) +diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c +index 2dd1d0dd4f7d..6f5d79569136 100644 +--- a/drivers/input/keyboard/atkbd.c ++++ b/drivers/input/keyboard/atkbd.c +@@ -1791,14 +1791,6 @@ static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), +- DMI_MATCH(DMI_PRODUCT_NAME, "LW25-B7HV"), +- }, +- .callback = atkbd_deactivate_fixup, +- }, +- { +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), +- DMI_MATCH(DMI_PRODUCT_NAME, "P1-J273B"), + }, + .callback = atkbd_deactivate_fixup, + }, +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 233516aff595..0b75b5764f31 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -1253,6 +1253,13 @@ static bool elantech_is_signature_valid(const unsigned char *param) + if (param[1] == 0) + return true; + ++ /* ++ * Some models have a revision higher then 20. Meaning param[2] may ++ * be 10 or 20, skip the rates check for these. ++ */ ++ if (param[0] == 0x46 && (param[1] & 0xef) == 0x0f && param[2] < 40) ++ return true; ++ + for (i = 0; i < ARRAY_SIZE(rates); i++) + if (param[2] == rates[i]) + return false; +diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c +index ef9e0b8a9aa7..a50a2a7a43f7 100644 +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -626,10 +626,61 @@ static int synaptics_parse_hw_state(const unsigned char buf[], + ((buf[0] & 0x04) >> 1) | + ((buf[3] & 0x04) >> 2)); + ++ if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || ++ SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) && ++ hw->w == 2) { ++ synaptics_parse_agm(buf, priv, hw); ++ return 1; ++ } ++ ++ hw->x = (((buf[3] & 0x10) << 8) | ++ ((buf[1] & 0x0f) << 8) | ++ buf[4]); ++ hw->y = (((buf[3] & 0x20) << 7) | ++ ((buf[1] & 0xf0) << 4) | ++ buf[5]); ++ hw->z = buf[2]; ++ + hw->left = (buf[0] & 0x01) ? 1 : 0; + hw->right = (buf[0] & 0x02) ? 1 : 0; + +- if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { ++ if (SYN_CAP_FORCEPAD(priv->ext_cap_0c)) { ++ /* ++ * ForcePads, like Clickpads, use middle button ++ * bits to report primary button clicks. ++ * Unfortunately they report primary button not ++ * only when user presses on the pad above certain ++ * threshold, but also when there are more than one ++ * finger on the touchpad, which interferes with ++ * out multi-finger gestures. ++ */ ++ if (hw->z == 0) { ++ /* No contacts */ ++ priv->press = priv->report_press = false; ++ } else if (hw->w >= 4 && ((buf[0] ^ buf[3]) & 0x01)) { ++ /* ++ * Single-finger touch with pressure above ++ * the threshold. If pressure stays long ++ * enough, we'll start reporting primary ++ * button. We rely on the device continuing ++ * sending data even if finger does not ++ * move. ++ */ ++ if (!priv->press) { ++ priv->press_start = jiffies; ++ priv->press = true; ++ } else if (time_after(jiffies, ++ priv->press_start + ++ msecs_to_jiffies(50))) { ++ priv->report_press = true; ++ } ++ } else { ++ priv->press = false; ++ } ++ ++ hw->left = priv->report_press; ++ ++ } else if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { + /* + * Clickpad's button is transmitted as middle button, + * however, since it is primary button, we will report +@@ -648,21 +699,6 @@ static int synaptics_parse_hw_state(const unsigned char buf[], + hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; + } + +- if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || +- SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) && +- hw->w == 2) { +- synaptics_parse_agm(buf, priv, hw); +- return 1; +- } +- +- hw->x = (((buf[3] & 0x10) << 8) | +- ((buf[1] & 0x0f) << 8) | +- buf[4]); +- hw->y = (((buf[3] & 0x20) << 7) | +- ((buf[1] & 0xf0) << 4) | +- buf[5]); +- hw->z = buf[2]; +- + if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && + ((buf[0] ^ buf[3]) & 0x02)) { + switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { +diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h +index e594af0b264b..fb2e076738ae 100644 +--- a/drivers/input/mouse/synaptics.h ++++ b/drivers/input/mouse/synaptics.h +@@ -78,6 +78,11 @@ + * 2 0x08 image sensor image sensor tracks 5 fingers, but only + * reports 2. + * 2 0x20 report min query 0x0f gives min coord reported ++ * 2 0x80 forcepad forcepad is a variant of clickpad that ++ * does not have physical buttons but rather ++ * uses pressure above certain threshold to ++ * report primary clicks. Forcepads also have ++ * clickpad bit set. + */ + #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ + #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ +@@ -86,6 +91,7 @@ + #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) + #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) + #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) ++#define SYN_CAP_FORCEPAD(ex0c) ((ex0c) & 0x008000) + + /* synaptics modes query bits */ + #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) +@@ -177,6 +183,11 @@ struct synaptics_data { + */ + struct synaptics_hw_state agm; + bool agm_pending; /* new AGM packet received */ ++ ++ /* ForcePad handling */ ++ unsigned long press_start; ++ bool press; ++ bool report_press; + }; + + void synaptics_module_init(void); +diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h +index 381b20d4c561..f1da362c3e65 100644 +--- a/drivers/input/serio/i8042-x86ia64io.h ++++ b/drivers/input/serio/i8042-x86ia64io.h +@@ -458,6 +458,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"), + }, + }, ++ { ++ /* Avatar AVIU-145A6 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Intel"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "IC4I"), ++ }, ++ }, + { } + }; + +@@ -601,6 +608,14 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"), + }, + }, ++ { ++ /* Fujitsu U574 laptop */ ++ /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"), ++ }, ++ }, + { } + }; + +diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c +index 0cb7ef59071b..69175b825346 100644 +--- a/drivers/input/serio/serport.c ++++ b/drivers/input/serio/serport.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + MODULE_AUTHOR("Vojtech Pavlik "); + MODULE_DESCRIPTION("Input device TTY line discipline"); +@@ -198,28 +199,55 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u + return 0; + } + ++static void serport_set_type(struct tty_struct *tty, unsigned long type) ++{ ++ struct serport *serport = tty->disc_data; ++ ++ serport->id.proto = type & 0x000000ff; ++ serport->id.id = (type & 0x0000ff00) >> 8; ++ serport->id.extra = (type & 0x00ff0000) >> 16; ++} ++ + /* + * serport_ldisc_ioctl() allows to set the port protocol, and device ID + */ + +-static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg) ++static int serport_ldisc_ioctl(struct tty_struct *tty, struct file *file, ++ unsigned int cmd, unsigned long arg) + { +- struct serport *serport = (struct serport*) tty->disc_data; +- unsigned long type; +- + if (cmd == SPIOCSTYPE) { ++ unsigned long type; ++ + if (get_user(type, (unsigned long __user *) arg)) + return -EFAULT; + +- serport->id.proto = type & 0x000000ff; +- serport->id.id = (type & 0x0000ff00) >> 8; +- serport->id.extra = (type & 0x00ff0000) >> 16; ++ serport_set_type(tty, type); ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++#ifdef CONFIG_COMPAT ++#define COMPAT_SPIOCSTYPE _IOW('q', 0x01, compat_ulong_t) ++static long serport_ldisc_compat_ioctl(struct tty_struct *tty, ++ struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ if (cmd == COMPAT_SPIOCSTYPE) { ++ void __user *uarg = compat_ptr(arg); ++ compat_ulong_t compat_type; ++ ++ if (get_user(compat_type, (compat_ulong_t __user *)uarg)) ++ return -EFAULT; + ++ serport_set_type(tty, compat_type); + return 0; + } + + return -EINVAL; + } ++#endif + + static void serport_ldisc_write_wakeup(struct tty_struct * tty) + { +@@ -243,6 +271,9 @@ static struct tty_ldisc_ops serport_ldisc = { + .close = serport_ldisc_close, + .read = serport_ldisc_read, + .ioctl = serport_ldisc_ioctl, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = serport_ldisc_compat_ioctl, ++#endif + .receive_buf = serport_ldisc_receive, + .write_wakeup = serport_ldisc_write_wakeup + }; +diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c +index 1d9ab39af29f..2ecac467f78f 100644 +--- a/drivers/iommu/arm-smmu.c ++++ b/drivers/iommu/arm-smmu.c +@@ -794,8 +794,11 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) + reg |= TTBCR_EAE | + (TTBCR_SH_IS << TTBCR_SH0_SHIFT) | + (TTBCR_RGN_WBWA << TTBCR_ORGN0_SHIFT) | +- (TTBCR_RGN_WBWA << TTBCR_IRGN0_SHIFT) | +- (TTBCR_SL0_LVL_1 << TTBCR_SL0_SHIFT); ++ (TTBCR_RGN_WBWA << TTBCR_IRGN0_SHIFT); ++ ++ if (!stage1) ++ reg |= (TTBCR_SL0_LVL_1 << TTBCR_SL0_SHIFT); ++ + writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR); + + /* MAIR0 (stage-1 only) */ +diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c +index 735e939a846d..2331543005b2 100644 +--- a/drivers/md/dm-cache-target.c ++++ b/drivers/md/dm-cache-target.c +@@ -890,8 +890,8 @@ static void migration_success_pre_commit(struct dm_cache_migration *mg) + struct cache *cache = mg->cache; + + if (mg->writeback) { +- cell_defer(cache, mg->old_ocell, false); + clear_dirty(cache, mg->old_oblock, mg->cblock); ++ cell_defer(cache, mg->old_ocell, false); + cleanup_migration(mg); + return; + +@@ -946,13 +946,13 @@ static void migration_success_post_commit(struct dm_cache_migration *mg) + } + + } else { ++ clear_dirty(cache, mg->new_oblock, mg->cblock); + if (mg->requeue_holder) + cell_defer(cache, mg->new_ocell, true); + else { + bio_endio(mg->new_ocell->holder, 0); + cell_defer(cache, mg->new_ocell, false); + } +- clear_dirty(cache, mg->new_oblock, mg->cblock); + cleanup_migration(mg); + } + } +diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c +index 53b213226c01..9533f835ce07 100644 +--- a/drivers/md/dm-crypt.c ++++ b/drivers/md/dm-crypt.c +@@ -1681,6 +1681,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) + unsigned int key_size, opt_params; + unsigned long long tmpll; + int ret; ++ size_t iv_size_padding; + struct dm_arg_set as; + const char *opt_string; + char dummy; +@@ -1717,12 +1718,23 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) + + cc->dmreq_start = sizeof(struct ablkcipher_request); + cc->dmreq_start += crypto_ablkcipher_reqsize(any_tfm(cc)); +- cc->dmreq_start = ALIGN(cc->dmreq_start, crypto_tfm_ctx_alignment()); +- cc->dmreq_start += crypto_ablkcipher_alignmask(any_tfm(cc)) & +- ~(crypto_tfm_ctx_alignment() - 1); ++ cc->dmreq_start = ALIGN(cc->dmreq_start, __alignof__(struct dm_crypt_request)); ++ ++ if (crypto_ablkcipher_alignmask(any_tfm(cc)) < CRYPTO_MINALIGN) { ++ /* Allocate the padding exactly */ ++ iv_size_padding = -(cc->dmreq_start + sizeof(struct dm_crypt_request)) ++ & crypto_ablkcipher_alignmask(any_tfm(cc)); ++ } else { ++ /* ++ * If the cipher requires greater alignment than kmalloc ++ * alignment, we don't know the exact position of the ++ * initialization vector. We must assume worst case. ++ */ ++ iv_size_padding = crypto_ablkcipher_alignmask(any_tfm(cc)); ++ } + + cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start + +- sizeof(struct dm_crypt_request) + cc->iv_size); ++ sizeof(struct dm_crypt_request) + iv_size_padding + cc->iv_size); + if (!cc->req_pool) { + ti->error = "Cannot allocate crypt request mempool"; + goto bad; +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index d7690f86fdb9..55de4f6f7eaf 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -540,11 +540,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect + has_nonrot_disk = 0; + choose_next_idle = 0; + +- if (conf->mddev->recovery_cp < MaxSector && +- (this_sector + sectors >= conf->next_resync)) +- choose_first = 1; +- else +- choose_first = 0; ++ choose_first = (conf->mddev->recovery_cp < this_sector + sectors); + + for (disk = 0 ; disk < conf->raid_disks * 2 ; disk++) { + sector_t dist; +@@ -831,7 +827,7 @@ static void flush_pending_writes(struct r1conf *conf) + * there is no normal IO happeing. It must arrange to call + * lower_barrier when the particular background IO completes. + */ +-static void raise_barrier(struct r1conf *conf) ++static void raise_barrier(struct r1conf *conf, sector_t sector_nr) + { + spin_lock_irq(&conf->resync_lock); + +@@ -841,6 +837,7 @@ static void raise_barrier(struct r1conf *conf) + + /* block any new IO from starting */ + conf->barrier++; ++ conf->next_resync = sector_nr; + + /* For these conditions we must wait: + * A: while the array is in frozen state +@@ -849,14 +846,17 @@ static void raise_barrier(struct r1conf *conf) + * C: next_resync + RESYNC_SECTORS > start_next_window, meaning + * next resync will reach to the window which normal bios are + * handling. ++ * D: while there are any active requests in the current window. + */ + wait_event_lock_irq(conf->wait_barrier, + !conf->array_frozen && + conf->barrier < RESYNC_DEPTH && ++ conf->current_window_requests == 0 && + (conf->start_next_window >= + conf->next_resync + RESYNC_SECTORS), + conf->resync_lock); + ++ conf->nr_pending++; + spin_unlock_irq(&conf->resync_lock); + } + +@@ -866,6 +866,7 @@ static void lower_barrier(struct r1conf *conf) + BUG_ON(conf->barrier <= 0); + spin_lock_irqsave(&conf->resync_lock, flags); + conf->barrier--; ++ conf->nr_pending--; + spin_unlock_irqrestore(&conf->resync_lock, flags); + wake_up(&conf->wait_barrier); + } +@@ -877,12 +878,10 @@ static bool need_to_wait_for_sync(struct r1conf *conf, struct bio *bio) + if (conf->array_frozen || !bio) + wait = true; + else if (conf->barrier && bio_data_dir(bio) == WRITE) { +- if (conf->next_resync < RESYNC_WINDOW_SECTORS) +- wait = true; +- else if ((conf->next_resync - RESYNC_WINDOW_SECTORS +- >= bio_end_sector(bio)) || +- (conf->next_resync + NEXT_NORMALIO_DISTANCE +- <= bio->bi_iter.bi_sector)) ++ if ((conf->mddev->curr_resync_completed ++ >= bio_end_sector(bio)) || ++ (conf->next_resync + NEXT_NORMALIO_DISTANCE ++ <= bio->bi_iter.bi_sector)) + wait = false; + else + wait = true; +@@ -919,8 +918,8 @@ static sector_t wait_barrier(struct r1conf *conf, struct bio *bio) + } + + if (bio && bio_data_dir(bio) == WRITE) { +- if (conf->next_resync + NEXT_NORMALIO_DISTANCE +- <= bio->bi_iter.bi_sector) { ++ if (bio->bi_iter.bi_sector >= ++ conf->mddev->curr_resync_completed) { + if (conf->start_next_window == MaxSector) + conf->start_next_window = + conf->next_resync + +@@ -1186,6 +1185,7 @@ read_again: + atomic_read(&bitmap->behind_writes) == 0); + } + r1_bio->read_disk = rdisk; ++ r1_bio->start_next_window = 0; + + read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev); + bio_trim(read_bio, r1_bio->sector - bio->bi_iter.bi_sector, +@@ -1548,8 +1548,13 @@ static void close_sync(struct r1conf *conf) + mempool_destroy(conf->r1buf_pool); + conf->r1buf_pool = NULL; + ++ spin_lock_irq(&conf->resync_lock); + conf->next_resync = 0; + conf->start_next_window = MaxSector; ++ conf->current_window_requests += ++ conf->next_window_requests; ++ conf->next_window_requests = 0; ++ spin_unlock_irq(&conf->resync_lock); + } + + static int raid1_spare_active(struct mddev *mddev) +@@ -2150,7 +2155,7 @@ static void fix_read_error(struct r1conf *conf, int read_disk, + d--; + rdev = conf->mirrors[d].rdev; + if (rdev && +- test_bit(In_sync, &rdev->flags)) ++ !test_bit(Faulty, &rdev->flags)) + r1_sync_page_io(rdev, sect, s, + conf->tmppage, WRITE); + } +@@ -2162,7 +2167,7 @@ static void fix_read_error(struct r1conf *conf, int read_disk, + d--; + rdev = conf->mirrors[d].rdev; + if (rdev && +- test_bit(In_sync, &rdev->flags)) { ++ !test_bit(Faulty, &rdev->flags)) { + if (r1_sync_page_io(rdev, sect, s, + conf->tmppage, READ)) { + atomic_add(s, &rdev->corrected_errors); +@@ -2541,9 +2546,8 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp + + bitmap_cond_end_sync(mddev->bitmap, sector_nr); + r1_bio = mempool_alloc(conf->r1buf_pool, GFP_NOIO); +- raise_barrier(conf); + +- conf->next_resync = sector_nr; ++ raise_barrier(conf, sector_nr); + + rcu_read_lock(); + /* +diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h +index 80643ef9183f..fabe2fce9bc5 100644 +--- a/drivers/media/dvb-core/dvb-usb-ids.h ++++ b/drivers/media/dvb-core/dvb-usb-ids.h +@@ -279,6 +279,8 @@ + #define USB_PID_PCTV_400E 0x020f + #define USB_PID_PCTV_450E 0x0222 + #define USB_PID_PCTV_452E 0x021f ++#define USB_PID_PCTV_78E 0x025a ++#define USB_PID_PCTV_79E 0x0262 + #define USB_PID_REALTEK_RTL2831U 0x2831 + #define USB_PID_REALTEK_RTL2832U 0x2832 + #define USB_PID_TECHNOTREND_CONNECT_S2_3600 0x3007 +diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c +index 71c8570bd9ea..112394d138c9 100644 +--- a/drivers/media/i2c/adv7604.c ++++ b/drivers/media/i2c/adv7604.c +@@ -1984,7 +1984,7 @@ static int adv7604_log_status(struct v4l2_subdev *sd) + v4l2_info(sd, "HDCP keys read: %s%s\n", + (hdmi_read(sd, 0x04) & 0x20) ? "yes" : "no", + (hdmi_read(sd, 0x04) & 0x10) ? "ERROR" : ""); +- if (!is_hdmi(sd)) { ++ if (is_hdmi(sd)) { + bool audio_pll_locked = hdmi_read(sd, 0x04) & 0x01; + bool audio_sample_packet_detect = hdmi_read(sd, 0x18) & 0x01; + bool audio_mute = io_read(sd, 0x65) & 0x40; +diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c +index 716bdc57fac6..83f5074706f9 100644 +--- a/drivers/media/pci/cx18/cx18-driver.c ++++ b/drivers/media/pci/cx18/cx18-driver.c +@@ -1091,6 +1091,7 @@ static int cx18_probe(struct pci_dev *pci_dev, + setup.addr = ADDR_UNSET; + setup.type = cx->options.tuner; + setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */ ++ setup.config = NULL; + if (cx->options.radio > 0) + setup.mode_mask |= T_RADIO; + setup.tuner_callback = (setup.type == TUNER_XC2028) ? +diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c +index 8ede8ea762e6..88228f735342 100644 +--- a/drivers/media/usb/dvb-usb-v2/af9035.c ++++ b/drivers/media/usb/dvb-usb-v2/af9035.c +@@ -1541,6 +1541,10 @@ static const struct usb_device_id af9035_id_table[] = { + &af9035_props, "Leadtek WinFast DTV Dongle Dual", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xf900, + &af9035_props, "Hauppauge WinTV-MiniStick 2", NULL) }, ++ { DVB_USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_78E, ++ &af9035_props, "PCTV 78e", RC_MAP_IT913X_V1) }, ++ { DVB_USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_79E, ++ &af9035_props, "PCTV 79e", RC_MAP_IT913X_V2) }, + { } + }; + MODULE_DEVICE_TABLE(usb, af9035_id_table); +diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c +index 1fc8334fc181..55e3075492da 100644 +--- a/drivers/net/ethernet/ibm/ibmveth.c ++++ b/drivers/net/ethernet/ibm/ibmveth.c +@@ -292,6 +292,18 @@ failure: + atomic_add(buffers_added, &(pool->available)); + } + ++/* ++ * The final 8 bytes of the buffer list is a counter of frames dropped ++ * because there was not a buffer in the buffer list capable of holding ++ * the frame. ++ */ ++static void ibmveth_update_rx_no_buffer(struct ibmveth_adapter *adapter) ++{ ++ __be64 *p = adapter->buffer_list_addr + 4096 - 8; ++ ++ adapter->rx_no_buffer = be64_to_cpup(p); ++} ++ + /* replenish routine */ + static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) + { +@@ -307,8 +319,7 @@ static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) + ibmveth_replenish_buffer_pool(adapter, pool); + } + +- adapter->rx_no_buffer = *(u64 *)(((char*)adapter->buffer_list_addr) + +- 4096 - 8); ++ ibmveth_update_rx_no_buffer(adapter); + } + + /* empty and free ana buffer pool - also used to do cleanup in error paths */ +@@ -698,8 +709,7 @@ static int ibmveth_close(struct net_device *netdev) + + free_irq(netdev->irq, netdev); + +- adapter->rx_no_buffer = *(u64 *)(((char *)adapter->buffer_list_addr) + +- 4096 - 8); ++ ibmveth_update_rx_no_buffer(adapter); + + ibmveth_cleanup(adapter); + +diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h +index 8596aba34f96..237d0cda1bcb 100644 +--- a/drivers/net/wireless/ath/carl9170/carl9170.h ++++ b/drivers/net/wireless/ath/carl9170/carl9170.h +@@ -256,6 +256,7 @@ struct ar9170 { + atomic_t rx_work_urbs; + atomic_t rx_pool_urbs; + kernel_ulong_t features; ++ bool usb_ep_cmd_is_bulk; + + /* firmware settings */ + struct completion fw_load_wait; +diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c +index ca115f33746f..bc931f6f1f0f 100644 +--- a/drivers/net/wireless/ath/carl9170/usb.c ++++ b/drivers/net/wireless/ath/carl9170/usb.c +@@ -621,9 +621,16 @@ int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd, + goto err_free; + } + +- usb_fill_int_urb(urb, ar->udev, usb_sndintpipe(ar->udev, +- AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4, +- carl9170_usb_cmd_complete, ar, 1); ++ if (ar->usb_ep_cmd_is_bulk) ++ usb_fill_bulk_urb(urb, ar->udev, ++ usb_sndbulkpipe(ar->udev, AR9170_USB_EP_CMD), ++ cmd, cmd->hdr.len + 4, ++ carl9170_usb_cmd_complete, ar); ++ else ++ usb_fill_int_urb(urb, ar->udev, ++ usb_sndintpipe(ar->udev, AR9170_USB_EP_CMD), ++ cmd, cmd->hdr.len + 4, ++ carl9170_usb_cmd_complete, ar, 1); + + if (free_buf) + urb->transfer_flags |= URB_FREE_BUFFER; +@@ -1032,9 +1039,10 @@ static void carl9170_usb_firmware_step2(const struct firmware *fw, + static int carl9170_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) + { ++ struct usb_endpoint_descriptor *ep; + struct ar9170 *ar; + struct usb_device *udev; +- int err; ++ int i, err; + + err = usb_reset_device(interface_to_usbdev(intf)); + if (err) +@@ -1050,6 +1058,21 @@ static int carl9170_usb_probe(struct usb_interface *intf, + ar->intf = intf; + ar->features = id->driver_info; + ++ /* We need to remember the type of endpoint 4 because it differs ++ * between high- and full-speed configuration. The high-speed ++ * configuration specifies it as interrupt and the full-speed ++ * configuration as bulk endpoint. This information is required ++ * later when sending urbs to that endpoint. ++ */ ++ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; ++i) { ++ ep = &intf->cur_altsetting->endpoint[i].desc; ++ ++ if (usb_endpoint_num(ep) == AR9170_USB_EP_CMD && ++ usb_endpoint_dir_out(ep) && ++ usb_endpoint_type(ep) == USB_ENDPOINT_XFER_BULK) ++ ar->usb_ep_cmd_is_bulk = true; ++ } ++ + usb_set_intfdata(intf, ar); + SET_IEEE80211_DEV(ar->hw, &intf->dev); + +diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +index fad77dd2a3a5..3f9cb894d001 100644 +--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +@@ -185,7 +185,13 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, + ifevent->action, ifevent->ifidx, ifevent->bssidx, + ifevent->flags, ifevent->role); + +- if (ifevent->flags & BRCMF_E_IF_FLAG_NOIF) { ++ /* The P2P Device interface event must not be ignored ++ * contrary to what firmware tells us. The only way to ++ * distinguish the P2P Device is by looking at the ifidx ++ * and bssidx received. ++ */ ++ if (!(ifevent->ifidx == 0 && ifevent->bssidx == 1) && ++ (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) { + brcmf_dbg(EVENT, "event can be ignored\n"); + return; + } +@@ -210,12 +216,12 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, + return; + } + +- if (ifevent->action == BRCMF_E_IF_CHANGE) ++ if (ifp && ifevent->action == BRCMF_E_IF_CHANGE) + brcmf_fws_reset_interface(ifp); + + err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data); + +- if (ifevent->action == BRCMF_E_IF_DEL) { ++ if (ifp && ifevent->action == BRCMF_E_IF_DEL) { + brcmf_fws_del_interface(ifp); + brcmf_del_if(drvr, ifevent->bssidx); + } +diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +index 51b53a73d074..d26b47698f68 100644 +--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h ++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +@@ -167,6 +167,8 @@ enum brcmf_fweh_event_code { + #define BRCMF_E_IF_ROLE_STA 0 + #define BRCMF_E_IF_ROLE_AP 1 + #define BRCMF_E_IF_ROLE_WDS 2 ++#define BRCMF_E_IF_ROLE_P2P_GO 3 ++#define BRCMF_E_IF_ROLE_P2P_CLIENT 4 + + /** + * definitions for event packet validation. +diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c +index c1e311341b74..503a81e58185 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/rxon.c ++++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c +@@ -1068,6 +1068,13 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) + /* recalculate basic rates */ + iwl_calc_basic_rates(priv, ctx); + ++ /* ++ * force CTS-to-self frames protection if RTS-CTS is not preferred ++ * one aggregation protection method ++ */ ++ if (!priv->hw_params.use_rts_for_aggregation) ++ ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; ++ + if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || + !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK)) + ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; +@@ -1473,6 +1480,11 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, + else + ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; + ++ if (bss_conf->use_cts_prot) ++ ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; ++ else ++ ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN; ++ + memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN); + + if (vif->type == NL80211_IFTYPE_AP || +diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h +index 1ced525157dc..b45d78f53f08 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-config.h ++++ b/drivers/net/wireless/iwlwifi/iwl-config.h +@@ -119,6 +119,8 @@ enum iwl_led_mode { + #define IWL_LONG_WD_TIMEOUT 10000 + #define IWL_MAX_WD_TIMEOUT 120000 + ++#define IWL_DEFAULT_MAX_TX_POWER 22 ++ + /* Antenna presence definitions */ + #define ANT_NONE 0x0 + #define ANT_A BIT(0) +diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +index 725e954d8475..3c3eb7842c62 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c ++++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +@@ -118,8 +118,6 @@ static const u8 iwl_nvm_channels[] = { + #define LAST_2GHZ_HT_PLUS 9 + #define LAST_5GHZ_HT 161 + +-#define DEFAULT_MAX_TX_POWER 16 +- + /* rate data (static) */ + static struct ieee80211_rate iwl_cfg80211_rates[] = { + { .bitrate = 1 * 10, .hw_value = 0, .hw_value_short = 0, }, +@@ -242,7 +240,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, + * Default value - highest tx power value. max_power + * is not used in mvm, and is used for backwards compatibility + */ +- channel->max_power = DEFAULT_MAX_TX_POWER; ++ channel->max_power = IWL_DEFAULT_MAX_TX_POWER; + is_5ghz = channel->band == IEEE80211_BAND_5GHZ; + IWL_DEBUG_EEPROM(dev, + "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", +diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h +index 989d7dbdca6c..d0a04779d734 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h ++++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h +@@ -1415,14 +1415,14 @@ enum iwl_sf_scenario { + + /** + * Smart Fifo configuration command. +- * @state: smart fifo state, types listed in iwl_sf_sate. ++ * @state: smart fifo state, types listed in enum %iwl_sf_sate. + * @watermark: Minimum allowed availabe free space in RXF for transient state. + * @long_delay_timeouts: aging and idle timer values for each scenario + * in long delay state. + * @full_on_timeouts: timer values for each scenario in full on state. + */ + struct iwl_sf_cfg_cmd { +- enum iwl_sf_state state; ++ __le32 state; + __le32 watermark[SF_TRANSIENT_STATES_NUMBER]; + __le32 long_delay_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES]; + __le32 full_on_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES]; +diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c +index 88809b2d1654..dab8fd13857a 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/sf.c ++++ b/drivers/net/wireless/iwlwifi/mvm/sf.c +@@ -172,7 +172,7 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, + enum iwl_sf_state new_state) + { + struct iwl_sf_cfg_cmd sf_cmd = { +- .state = new_state, ++ .state = cpu_to_le32(new_state), + }; + struct ieee80211_sta *sta; + int ret = 0; +diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c +index 76ee486039d7..2ca62af3f81b 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/tx.c ++++ b/drivers/net/wireless/iwlwifi/mvm/tx.c +@@ -173,10 +173,14 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, + + /* + * for data packets, rate info comes from the table inside the fw. This +- * table is controlled by LINK_QUALITY commands ++ * table is controlled by LINK_QUALITY commands. Exclude ctrl port ++ * frames like EAPOLs which should be treated as mgmt frames. This ++ * avoids them being sent initially in high rates which increases the ++ * chances for completion of the 4-Way handshake. + */ + +- if (ieee80211_is_data(fc) && sta) { ++ if (ieee80211_is_data(fc) && sta && ++ !(info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) { + tx_cmd->initial_rate_index = 0; + tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE); + return; +diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +index c61311084d7e..f58316769159 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +@@ -317,6 +317,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { + {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/ + {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ + {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ ++ {RTL_USB_DEVICE(0x0df6, 0x0070, rtl92cu_hal_cfg)}, /*Sitecom - 150N */ + {RTL_USB_DEVICE(0x0df6, 0x0077, rtl92cu_hal_cfg)}, /*Sitecom-WLA2100V2*/ + {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/ + {RTL_USB_DEVICE(0x4856, 0x0091, rtl92cu_hal_cfg)}, /*NetweeN - Feixun*/ +diff --git a/drivers/nfc/microread/microread.c b/drivers/nfc/microread/microread.c +index f868333271aa..963a4a5dc88e 100644 +--- a/drivers/nfc/microread/microread.c ++++ b/drivers/nfc/microread/microread.c +@@ -501,9 +501,13 @@ static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate, + targets->sens_res = + be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A_ATQA]); + targets->sel_res = skb->data[MICROREAD_EMCF_A_SAK]; +- memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A_UID], +- skb->data[MICROREAD_EMCF_A_LEN]); + targets->nfcid1_len = skb->data[MICROREAD_EMCF_A_LEN]; ++ if (targets->nfcid1_len > sizeof(targets->nfcid1)) { ++ r = -EINVAL; ++ goto exit_free; ++ } ++ memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A_UID], ++ targets->nfcid1_len); + break; + case MICROREAD_GATE_ID_MREAD_ISO_A_3: + targets->supported_protocols = +@@ -511,9 +515,13 @@ static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate, + targets->sens_res = + be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A3_ATQA]); + targets->sel_res = skb->data[MICROREAD_EMCF_A3_SAK]; +- memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A3_UID], +- skb->data[MICROREAD_EMCF_A3_LEN]); + targets->nfcid1_len = skb->data[MICROREAD_EMCF_A3_LEN]; ++ if (targets->nfcid1_len > sizeof(targets->nfcid1)) { ++ r = -EINVAL; ++ goto exit_free; ++ } ++ memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A3_UID], ++ targets->nfcid1_len); + break; + case MICROREAD_GATE_ID_MREAD_ISO_B: + targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK; +diff --git a/drivers/of/irq.c b/drivers/of/irq.c +index ca0189308d72..48f20ff1add9 100644 +--- a/drivers/of/irq.c ++++ b/drivers/of/irq.c +@@ -301,16 +301,17 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar + /* Get the reg property (if any) */ + addr = of_get_property(device, "reg", NULL); + ++ /* Try the new-style interrupts-extended first */ ++ res = of_parse_phandle_with_args(device, "interrupts-extended", ++ "#interrupt-cells", index, out_irq); ++ if (!res) ++ return of_irq_parse_raw(addr, out_irq); ++ + /* Get the interrupts property */ + intspec = of_get_property(device, "interrupts", &intlen); +- if (intspec == NULL) { +- /* Try the new-style interrupts-extended */ +- res = of_parse_phandle_with_args(device, "interrupts-extended", +- "#interrupt-cells", index, out_irq); +- if (res) +- return -EINVAL; +- return of_irq_parse_raw(addr, out_irq); +- } ++ if (intspec == NULL) ++ return -EINVAL; ++ + intlen /= sizeof(*intspec); + + pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen); +diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c +index c3ace1db8136..aaac3594f83b 100644 +--- a/drivers/phy/phy-twl4030-usb.c ++++ b/drivers/phy/phy-twl4030-usb.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -422,37 +423,55 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) + } + } + +-static int twl4030_phy_power_off(struct phy *phy) ++static int twl4030_usb_runtime_suspend(struct device *dev) + { +- struct twl4030_usb *twl = phy_get_drvdata(phy); ++ struct twl4030_usb *twl = dev_get_drvdata(dev); + ++ dev_dbg(twl->dev, "%s\n", __func__); + if (twl->asleep) + return 0; + + twl4030_phy_power(twl, 0); + twl->asleep = 1; +- dev_dbg(twl->dev, "%s\n", __func__); ++ + return 0; + } + +-static void __twl4030_phy_power_on(struct twl4030_usb *twl) ++static int twl4030_usb_runtime_resume(struct device *dev) + { ++ struct twl4030_usb *twl = dev_get_drvdata(dev); ++ ++ dev_dbg(twl->dev, "%s\n", __func__); ++ if (!twl->asleep) ++ return 0; ++ + twl4030_phy_power(twl, 1); +- twl4030_i2c_access(twl, 1); +- twl4030_usb_set_mode(twl, twl->usb_mode); +- if (twl->usb_mode == T2_USB_MODE_ULPI) +- twl4030_i2c_access(twl, 0); ++ twl->asleep = 0; ++ ++ return 0; ++} ++ ++static int twl4030_phy_power_off(struct phy *phy) ++{ ++ struct twl4030_usb *twl = phy_get_drvdata(phy); ++ ++ dev_dbg(twl->dev, "%s\n", __func__); ++ pm_runtime_mark_last_busy(twl->dev); ++ pm_runtime_put_autosuspend(twl->dev); ++ ++ return 0; + } + + static int twl4030_phy_power_on(struct phy *phy) + { + struct twl4030_usb *twl = phy_get_drvdata(phy); + +- if (!twl->asleep) +- return 0; +- __twl4030_phy_power_on(twl); +- twl->asleep = 0; + dev_dbg(twl->dev, "%s\n", __func__); ++ pm_runtime_get_sync(twl->dev); ++ twl4030_i2c_access(twl, 1); ++ twl4030_usb_set_mode(twl, twl->usb_mode); ++ if (twl->usb_mode == T2_USB_MODE_ULPI) ++ twl4030_i2c_access(twl, 0); + + /* + * XXX When VBUS gets driven after musb goes to A mode, +@@ -558,9 +577,27 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) + * USB_LINK_VBUS state. musb_hdrc won't care until it + * starts to handle softconnect right. + */ ++ if ((status == OMAP_MUSB_VBUS_VALID) || ++ (status == OMAP_MUSB_ID_GROUND)) { ++ if (twl->asleep) ++ pm_runtime_get_sync(twl->dev); ++ } else { ++ if (!twl->asleep) { ++ pm_runtime_mark_last_busy(twl->dev); ++ pm_runtime_put_autosuspend(twl->dev); ++ } ++ } + omap_musb_mailbox(status); + } +- sysfs_notify(&twl->dev->kobj, NULL, "vbus"); ++ ++ /* don't schedule during sleep - irq works right then */ ++ if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) { ++ cancel_delayed_work(&twl->id_workaround_work); ++ schedule_delayed_work(&twl->id_workaround_work, HZ); ++ } ++ ++ if (irq) ++ sysfs_notify(&twl->dev->kobj, NULL, "vbus"); + + return IRQ_HANDLED; + } +@@ -569,29 +606,8 @@ static void twl4030_id_workaround_work(struct work_struct *work) + { + struct twl4030_usb *twl = container_of(work, struct twl4030_usb, + id_workaround_work.work); +- enum omap_musb_vbus_id_status status; +- bool status_changed = false; +- +- status = twl4030_usb_linkstat(twl); +- +- spin_lock_irq(&twl->lock); +- if (status >= 0 && status != twl->linkstat) { +- twl->linkstat = status; +- status_changed = true; +- } +- spin_unlock_irq(&twl->lock); +- +- if (status_changed) { +- dev_dbg(twl->dev, "handle missing status change to %d\n", +- status); +- omap_musb_mailbox(status); +- } + +- /* don't schedule during sleep - irq works right then */ +- if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) { +- cancel_delayed_work(&twl->id_workaround_work); +- schedule_delayed_work(&twl->id_workaround_work, HZ); +- } ++ twl4030_usb_irq(0, twl); + } + + static int twl4030_phy_init(struct phy *phy) +@@ -599,22 +615,17 @@ static int twl4030_phy_init(struct phy *phy) + struct twl4030_usb *twl = phy_get_drvdata(phy); + enum omap_musb_vbus_id_status status; + +- /* +- * Start in sleep state, we'll get called through set_suspend() +- * callback when musb is runtime resumed and it's time to start. +- */ +- __twl4030_phy_power(twl, 0); +- twl->asleep = 1; +- ++ pm_runtime_get_sync(twl->dev); + status = twl4030_usb_linkstat(twl); + twl->linkstat = status; + +- if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) { ++ if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) + omap_musb_mailbox(twl->linkstat); +- twl4030_phy_power_on(phy); +- } + + sysfs_notify(&twl->dev->kobj, NULL, "vbus"); ++ pm_runtime_mark_last_busy(twl->dev); ++ pm_runtime_put_autosuspend(twl->dev); ++ + return 0; + } + +@@ -650,6 +661,11 @@ static const struct phy_ops ops = { + .owner = THIS_MODULE, + }; + ++static const struct dev_pm_ops twl4030_usb_pm_ops = { ++ SET_RUNTIME_PM_OPS(twl4030_usb_runtime_suspend, ++ twl4030_usb_runtime_resume, NULL) ++}; ++ + static int twl4030_usb_probe(struct platform_device *pdev) + { + struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev); +@@ -726,6 +742,11 @@ static int twl4030_usb_probe(struct platform_device *pdev) + + ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); + ++ pm_runtime_use_autosuspend(&pdev->dev); ++ pm_runtime_set_autosuspend_delay(&pdev->dev, 2000); ++ pm_runtime_enable(&pdev->dev); ++ pm_runtime_get_sync(&pdev->dev); ++ + /* Our job is to use irqs and status from the power module + * to keep the transceiver disabled when nothing's connected. + * +@@ -744,6 +765,9 @@ static int twl4030_usb_probe(struct platform_device *pdev) + return status; + } + ++ pm_runtime_mark_last_busy(&pdev->dev); ++ pm_runtime_put_autosuspend(twl->dev); ++ + dev_info(&pdev->dev, "Initialized TWL4030 USB module\n"); + return 0; + } +@@ -753,6 +777,7 @@ static int twl4030_usb_remove(struct platform_device *pdev) + struct twl4030_usb *twl = platform_get_drvdata(pdev); + int val; + ++ pm_runtime_get_sync(twl->dev); + cancel_delayed_work(&twl->id_workaround_work); + device_remove_file(twl->dev, &dev_attr_vbus); + +@@ -772,9 +797,8 @@ static int twl4030_usb_remove(struct platform_device *pdev) + + /* disable complete OTG block */ + twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); +- +- if (!twl->asleep) +- twl4030_phy_power(twl, 0); ++ pm_runtime_mark_last_busy(twl->dev); ++ pm_runtime_put(twl->dev); + + return 0; + } +@@ -792,6 +816,7 @@ static struct platform_driver twl4030_usb_driver = { + .remove = twl4030_usb_remove, + .driver = { + .name = "twl4030_usb", ++ .pm = &twl4030_usb_pm_ops, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(twl4030_usb_id_table), + }, +diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c +index 40462415291e..454998669c2a 100644 +--- a/drivers/scsi/libiscsi.c ++++ b/drivers/scsi/libiscsi.c +@@ -717,11 +717,21 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + return NULL; + } + ++ if (data_size > ISCSI_DEF_MAX_RECV_SEG_LEN) { ++ iscsi_conn_printk(KERN_ERR, conn, "Invalid buffer len of %u for login task. Max len is %u\n", data_size, ISCSI_DEF_MAX_RECV_SEG_LEN); ++ return NULL; ++ } ++ + task = conn->login_task; + } else { + if (session->state != ISCSI_STATE_LOGGED_IN) + return NULL; + ++ if (data_size != 0) { ++ iscsi_conn_printk(KERN_ERR, conn, "Can not send data buffer of len %u for op 0x%x\n", data_size, opcode); ++ return NULL; ++ } ++ + BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); + BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); + +diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c +index 3f3dc1226edf..e14960470d8d 100644 +--- a/drivers/spi/spi-dw-pci.c ++++ b/drivers/spi/spi-dw-pci.c +@@ -62,6 +62,8 @@ static int spi_pci_probe(struct pci_dev *pdev, + if (ret) + return ret; + ++ dws->regs = pcim_iomap_table(pdev)[pci_bar]; ++ + dws->bus_num = 0; + dws->num_cs = 4; + dws->irq = pdev->irq; +diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c +index a64f1557c156..b0059e7552b0 100644 +--- a/drivers/spi/spi-omap2-mcspi.c ++++ b/drivers/spi/spi-omap2-mcspi.c +@@ -321,7 +321,8 @@ static void omap2_mcspi_set_fifo(const struct spi_device *spi, + disable_fifo: + if (t->rx_buf != NULL) + chconf &= ~OMAP2_MCSPI_CHCONF_FFER; +- else ++ ++ if (t->tx_buf != NULL) + chconf &= ~OMAP2_MCSPI_CHCONF_FFET; + + mcspi_write_chconf0(spi, chconf); +diff --git a/drivers/staging/iio/meter/ade7758_trigger.c b/drivers/staging/iio/meter/ade7758_trigger.c +index 7a94ddd42f59..8c4f2896cd0d 100644 +--- a/drivers/staging/iio/meter/ade7758_trigger.c ++++ b/drivers/staging/iio/meter/ade7758_trigger.c +@@ -85,7 +85,7 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev) + ret = iio_trigger_register(st->trig); + + /* select default trigger */ +- indio_dev->trig = st->trig; ++ indio_dev->trig = iio_trigger_get(st->trig); + if (ret) + goto error_free_irq; + +diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c +index 34b642a12f8b..c70f1734b274 100644 +--- a/drivers/staging/imx-drm/ipuv3-plane.c ++++ b/drivers/staging/imx-drm/ipuv3-plane.c +@@ -277,7 +277,8 @@ static void ipu_plane_dpms(struct ipu_plane *ipu_plane, int mode) + + ipu_idmac_put(ipu_plane->ipu_ch); + ipu_dmfc_put(ipu_plane->dmfc); +- ipu_dp_put(ipu_plane->dp); ++ if (ipu_plane->dp) ++ ipu_dp_put(ipu_plane->dp); + } + } + +diff --git a/drivers/staging/lustre/lustre/Kconfig b/drivers/staging/lustre/lustre/Kconfig +index 209e4c7e6f8a..4f65ba1158bf 100644 +--- a/drivers/staging/lustre/lustre/Kconfig ++++ b/drivers/staging/lustre/lustre/Kconfig +@@ -57,4 +57,5 @@ config LUSTRE_TRANSLATE_ERRNOS + config LUSTRE_LLITE_LLOOP + tristate "Lustre virtual block device" + depends on LUSTRE_FS && BLOCK ++ depends on !PPC_64K_PAGES && !ARM64_64K_PAGES + default m +diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c +index f329ad294fc0..104f29e6b290 100644 +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -4513,6 +4513,7 @@ static void iscsit_logout_post_handler_diffcid( + { + struct iscsi_conn *l_conn; + struct iscsi_session *sess = conn->sess; ++ bool conn_found = false; + + if (!sess) + return; +@@ -4521,12 +4522,13 @@ static void iscsit_logout_post_handler_diffcid( + list_for_each_entry(l_conn, &sess->sess_conn_list, conn_list) { + if (l_conn->cid == cid) { + iscsit_inc_conn_usage_count(l_conn); ++ conn_found = true; + break; + } + } + spin_unlock_bh(&sess->conn_lock); + +- if (!l_conn) ++ if (!conn_found) + return; + + if (l_conn->sock) +diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c +index 4d2e23fc76fd..43b7e6a616b8 100644 +--- a/drivers/target/iscsi/iscsi_target_parameters.c ++++ b/drivers/target/iscsi/iscsi_target_parameters.c +@@ -601,7 +601,7 @@ int iscsi_copy_param_list( + param_list = kzalloc(sizeof(struct iscsi_param_list), GFP_KERNEL); + if (!param_list) { + pr_err("Unable to allocate memory for struct iscsi_param_list.\n"); +- goto err_out; ++ return -1; + } + INIT_LIST_HEAD(¶m_list->param_list); + INIT_LIST_HEAD(¶m_list->extra_response_list); +diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c +index 483d324020a6..f30385385544 100644 +--- a/drivers/target/target_core_configfs.c ++++ b/drivers/target/target_core_configfs.c +@@ -2359,7 +2359,7 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_support_##_name(\ + pr_err("Invalid value '%ld', must be '0' or '1'\n", tmp); \ + return -EINVAL; \ + } \ +- if (!tmp) \ ++ if (tmp) \ + t->_var |= _bit; \ + else \ + t->_var &= ~_bit; \ +diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c +index ab9096dc3849..148ffe4c232f 100644 +--- a/drivers/tty/serial/8250/8250_dma.c ++++ b/drivers/tty/serial/8250/8250_dma.c +@@ -192,21 +192,28 @@ int serial8250_request_dma(struct uart_8250_port *p) + + dma->rx_buf = dma_alloc_coherent(dma->rxchan->device->dev, dma->rx_size, + &dma->rx_addr, GFP_KERNEL); +- if (!dma->rx_buf) { +- dma_release_channel(dma->rxchan); +- dma_release_channel(dma->txchan); +- return -ENOMEM; +- } ++ if (!dma->rx_buf) ++ goto err; + + /* TX buffer */ + dma->tx_addr = dma_map_single(dma->txchan->device->dev, + p->port.state->xmit.buf, + UART_XMIT_SIZE, + DMA_TO_DEVICE); ++ if (dma_mapping_error(dma->txchan->device->dev, dma->tx_addr)) { ++ dma_free_coherent(dma->rxchan->device->dev, dma->rx_size, ++ dma->rx_buf, dma->rx_addr); ++ goto err; ++ } + + dev_dbg_ratelimited(p->port.dev, "got both dma channels\n"); + + return 0; ++err: ++ dma_release_channel(dma->rxchan); ++ dma_release_channel(dma->txchan); ++ ++ return -ENOMEM; + } + EXPORT_SYMBOL_GPL(serial8250_request_dma); + +diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c +index 2d51d852b474..ca1123d415c5 100644 +--- a/drivers/usb/chipidea/ci_hdrc_msm.c ++++ b/drivers/usb/chipidea/ci_hdrc_msm.c +@@ -20,13 +20,13 @@ + static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) + { + struct device *dev = ci->gadget.dev.parent; +- int val; + + switch (event) { + case CI_HDRC_CONTROLLER_RESET_EVENT: + dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n"); + writel(0, USB_AHBBURST); + writel(0, USB_AHBMODE); ++ usb_phy_init(ci->transceiver); + break; + case CI_HDRC_CONTROLLER_STOPPED_EVENT: + dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n"); +@@ -34,10 +34,7 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) + * Put the transceiver in non-driving mode. Otherwise host + * may not detect soft-disconnection. + */ +- val = usb_phy_io_read(ci->transceiver, ULPI_FUNC_CTRL); +- val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; +- val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; +- usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL); ++ usb_phy_notify_disconnect(ci->transceiver, USB_SPEED_UNKNOWN); + break; + default: + dev_dbg(dev, "unknown ci_hdrc event\n"); +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 6650df70bb35..263612ce1f62 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -4764,9 +4764,10 @@ static void hub_events(void) + + hub = list_entry(tmp, struct usb_hub, event_list); + kref_get(&hub->kref); ++ hdev = hub->hdev; ++ usb_get_dev(hdev); + spin_unlock_irq(&hub_event_lock); + +- hdev = hub->hdev; + hub_dev = hub->intfdev; + intf = to_usb_interface(hub_dev); + dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n", +@@ -4979,6 +4980,7 @@ static void hub_events(void) + usb_autopm_put_interface(intf); + loop_disconnected: + usb_unlock_device(hdev); ++ usb_put_dev(hdev); + kref_put(&hub->kref, hub_release); + + } /* end while (1) */ +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index a49217ae3533..f074755372a0 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -583,12 +583,6 @@ static int dwc3_remove(struct platform_device *pdev) + { + struct dwc3 *dwc = platform_get_drvdata(pdev); + +- usb_phy_set_suspend(dwc->usb2_phy, 1); +- usb_phy_set_suspend(dwc->usb3_phy, 1); +- +- pm_runtime_put_sync(&pdev->dev); +- pm_runtime_disable(&pdev->dev); +- + dwc3_debugfs_exit(dwc); + + switch (dwc->dr_mode) { +@@ -609,8 +603,15 @@ static int dwc3_remove(struct platform_device *pdev) + + dwc3_event_buffers_cleanup(dwc); + dwc3_free_event_buffers(dwc); ++ ++ usb_phy_set_suspend(dwc->usb2_phy, 1); ++ usb_phy_set_suspend(dwc->usb3_phy, 1); ++ + dwc3_core_exit(dwc); + ++ pm_runtime_put_sync(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); ++ + return 0; + } + +diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c +index b269dbd47fc4..2a6841c95b64 100644 +--- a/drivers/usb/dwc3/dwc3-omap.c ++++ b/drivers/usb/dwc3/dwc3-omap.c +@@ -582,9 +582,9 @@ static int dwc3_omap_remove(struct platform_device *pdev) + if (omap->extcon_id_dev.edev) + extcon_unregister_interest(&omap->extcon_id_dev); + dwc3_omap_disable_irqs(omap); ++ device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); +- device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core); + + return 0; + } +diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c +index 81cda09b47e3..488a30836c36 100644 +--- a/drivers/usb/host/ehci-hcd.c ++++ b/drivers/usb/host/ehci-hcd.c +@@ -965,8 +965,6 @@ rescan: + } + + qh->exception = 1; +- if (ehci->rh_state < EHCI_RH_RUNNING) +- qh->qh_state = QH_STATE_IDLE; + switch (qh->qh_state) { + case QH_STATE_LINKED: + WARN_ON(!list_empty(&qh->qtd_list)); +diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c +index 9992fbfec85f..93fe089cd51a 100644 +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -470,7 +470,8 @@ static void xhci_hub_report_usb2_link_state(u32 *status, u32 status_reg) + } + + /* Updates Link Status for super Speed port */ +-static void xhci_hub_report_usb3_link_state(u32 *status, u32 status_reg) ++static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, ++ u32 *status, u32 status_reg) + { + u32 pls = status_reg & PORT_PLS_MASK; + +@@ -509,7 +510,8 @@ static void xhci_hub_report_usb3_link_state(u32 *status, u32 status_reg) + * in which sometimes the port enters compliance mode + * caused by a delay on the host-device negotiation. + */ +- if (pls == USB_SS_PORT_LS_COMP_MOD) ++ if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && ++ (pls == USB_SS_PORT_LS_COMP_MOD)) + pls |= USB_PORT_STAT_CONNECTION; + } + +@@ -668,7 +670,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, + } + /* Update Port Link State */ + if (hcd->speed == HCD_USB3) { +- xhci_hub_report_usb3_link_state(&status, raw_port_status); ++ xhci_hub_report_usb3_link_state(xhci, &status, raw_port_status); + /* + * Verify if all USB3 Ports Have entered U0 already. + * Delete Compliance Mode Timer if so. +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index 4133a00461b1..9bce4f0e99be 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -1723,7 +1723,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) + } + + num_ports = HCS_MAX_PORTS(xhci->hcs_params1); +- for (i = 0; i < num_ports; i++) { ++ for (i = 0; i < num_ports && xhci->rh_bw; i++) { + struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table; + for (j = 0; j < XHCI_MAX_INTERVAL; j++) { + struct list_head *ep = &bwt->interval_bw[j].endpoints; +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index ab831048e8a4..82b563fc4fd6 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -3928,13 +3928,21 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci, + int ret; + + spin_lock_irqsave(&xhci->lock, flags); +- if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) { ++ ++ virt_dev = xhci->devs[udev->slot_id]; ++ ++ /* ++ * virt_dev might not exists yet if xHC resumed from hibernate (S4) and ++ * xHC was re-initialized. Exit latency will be set later after ++ * hub_port_finish_reset() is done and xhci->devs[] are re-allocated ++ */ ++ ++ if (!virt_dev || max_exit_latency == virt_dev->current_mel) { + spin_unlock_irqrestore(&xhci->lock, flags); + return 0; + } + + /* Attempt to issue an Evaluate Context command to change the MEL. */ +- virt_dev = xhci->devs[udev->slot_id]; + command = xhci->lpm_command; + ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx); + if (!ctrl_ctx) { +diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c +index de98906f786d..0aef801edbc1 100644 +--- a/drivers/usb/misc/sisusbvga/sisusb.c ++++ b/drivers/usb/misc/sisusbvga/sisusb.c +@@ -3248,6 +3248,7 @@ static const struct usb_device_id sisusb_table[] = { + { USB_DEVICE(0x0711, 0x0918) }, + { USB_DEVICE(0x0711, 0x0920) }, + { USB_DEVICE(0x0711, 0x0950) }, ++ { USB_DEVICE(0x0711, 0x5200) }, + { USB_DEVICE(0x182d, 0x021c) }, + { USB_DEVICE(0x182d, 0x0269) }, + { } +diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c +index bbe4f8e6e8d7..8834b70c868c 100644 +--- a/drivers/usb/phy/phy-tegra-usb.c ++++ b/drivers/usb/phy/phy-tegra-usb.c +@@ -881,8 +881,8 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy, + return -ENOMEM; + } + +- tegra_phy->config = devm_kzalloc(&pdev->dev, +- sizeof(*tegra_phy->config), GFP_KERNEL); ++ tegra_phy->config = devm_kzalloc(&pdev->dev, sizeof(*config), ++ GFP_KERNEL); + if (!tegra_phy->config) { + dev_err(&pdev->dev, + "unable to allocate memory for USB UTMIP config\n"); +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index 8b0f517abb6b..3614620e09e1 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -741,6 +741,7 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID), + .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, + { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, ++ { USB_DEVICE(NOVITUS_VID, NOVITUS_BONO_E_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S03_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_59_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57A_PID) }, +@@ -952,6 +953,8 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(FTDI_VID, FTDI_EKEY_CONV_USB_PID) }, + /* Infineon Devices */ + { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) }, ++ /* GE Healthcare devices */ ++ { USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) }, + { } /* Terminating entry */ + }; + +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index 70b0b1d88ae9..5937b2d242f2 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -837,6 +837,12 @@ + #define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */ + + /* ++ * NOVITUS printers ++ */ ++#define NOVITUS_VID 0x1a28 ++#define NOVITUS_BONO_E_PID 0x6010 ++ ++/* + * RT Systems programming cables for various ham radios + */ + #define RTSYSTEMS_VID 0x2100 /* Vendor ID */ +@@ -1385,3 +1391,9 @@ + * ekey biometric systems GmbH (http://ekey.net/) + */ + #define FTDI_EKEY_CONV_USB_PID 0xCB08 /* Converter USB */ ++ ++/* ++ * GE Healthcare devices ++ */ ++#define GE_HEALTHCARE_VID 0x1901 ++#define GE_HEALTHCARE_NEMO_TRACKER_PID 0x0015 +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index 9da566a3f5c8..e47aabe0c760 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -275,8 +275,12 @@ static void option_instat_callback(struct urb *urb); + #define ZTE_PRODUCT_MF622 0x0001 + #define ZTE_PRODUCT_MF628 0x0015 + #define ZTE_PRODUCT_MF626 0x0031 +-#define ZTE_PRODUCT_MC2718 0xffe8 + #define ZTE_PRODUCT_AC2726 0xfff1 ++#define ZTE_PRODUCT_CDMA_TECH 0xfffe ++#define ZTE_PRODUCT_AC8710T 0xffff ++#define ZTE_PRODUCT_MC2718 0xffe8 ++#define ZTE_PRODUCT_AD3812 0xffeb ++#define ZTE_PRODUCT_MC2716 0xffed + + #define BENQ_VENDOR_ID 0x04a5 + #define BENQ_PRODUCT_H10 0x4068 +@@ -494,6 +498,10 @@ static void option_instat_callback(struct urb *urb); + #define INOVIA_VENDOR_ID 0x20a6 + #define INOVIA_SEW858 0x1105 + ++/* VIA Telecom */ ++#define VIATELECOM_VENDOR_ID 0x15eb ++#define VIATELECOM_PRODUCT_CDS7 0x0001 ++ + /* some devices interfaces need special handling due to a number of reasons */ + enum option_blacklist_reason { + OPTION_BLACKLIST_NONE = 0, +@@ -527,10 +535,18 @@ static const struct option_blacklist_info zte_k3765_z_blacklist = { + .reserved = BIT(4), + }; + ++static const struct option_blacklist_info zte_ad3812_z_blacklist = { ++ .sendsetup = BIT(0) | BIT(1) | BIT(2), ++}; ++ + static const struct option_blacklist_info zte_mc2718_z_blacklist = { + .sendsetup = BIT(1) | BIT(2) | BIT(3) | BIT(4), + }; + ++static const struct option_blacklist_info zte_mc2716_z_blacklist = { ++ .sendsetup = BIT(1) | BIT(2) | BIT(3), ++}; ++ + static const struct option_blacklist_info huawei_cdc12_blacklist = { + .reserved = BIT(1) | BIT(2), + }; +@@ -1070,6 +1086,7 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012, 0xff) }, + { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) }, + { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) }, ++ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */ + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */ +@@ -1544,13 +1561,18 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff93, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff94, 0xff, 0xff, 0xff) }, + +- /* NOTE: most ZTE CDMA devices should be driven by zte_ev, not option */ ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2718, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&zte_mc2718_z_blacklist }, ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AD3812, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist }, ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) }, +- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) }, + + { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, + { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, +@@ -1724,6 +1746,7 @@ 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(INOVIA_VENDOR_ID, INOVIA_SEW858) }, ++ { USB_DEVICE(VIATELECOM_VENDOR_ID, VIATELECOM_PRODUCT_CDS7) }, + { } /* Terminating entry */ + }; + MODULE_DEVICE_TABLE(usb, option_ids); +@@ -1917,6 +1940,8 @@ static void option_instat_callback(struct urb *urb) + dev_dbg(dev, "%s: type %x req %x\n", __func__, + req_pkt->bRequestType, req_pkt->bRequest); + } ++ } else if (status == -ENOENT || status == -ESHUTDOWN) { ++ dev_dbg(dev, "%s: urb stopped: %d\n", __func__, status); + } else + dev_err(dev, "%s: error %d\n", __func__, status); + +diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c +index b3d5a35c0d4b..e9bad928039f 100644 +--- a/drivers/usb/serial/pl2303.c ++++ b/drivers/usb/serial/pl2303.c +@@ -45,6 +45,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) }, ++ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) }, + { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, + { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, + { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, +diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h +index 42bc082896ac..71fd9da1d6e7 100644 +--- a/drivers/usb/serial/pl2303.h ++++ b/drivers/usb/serial/pl2303.h +@@ -22,6 +22,7 @@ + #define PL2303_PRODUCT_ID_GPRS 0x0609 + #define PL2303_PRODUCT_ID_HCR331 0x331a + #define PL2303_PRODUCT_ID_MOTOROLA 0x0307 ++#define PL2303_PRODUCT_ID_ZTEK 0xe1f1 + + #define ATEN_VENDOR_ID 0x0557 + #define ATEN_VENDOR_ID2 0x0547 +diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c +index 37480348e39b..74a9375a9bb5 100644 +--- a/drivers/usb/serial/sierra.c ++++ b/drivers/usb/serial/sierra.c +@@ -282,14 +282,19 @@ static const struct usb_device_id id_table[] = { + /* Sierra Wireless HSPA Non-Composite Device */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)}, + { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */ +- { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ ++ /* Sierra Wireless Direct IP modems */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68A3, 0xFF, 0xFF, 0xFF), ++ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist ++ }, ++ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68AA, 0xFF, 0xFF, 0xFF), + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, + /* AT&T Direct IP LTE modems */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF), + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, +- { USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */ ++ /* Airprime/Sierra Wireless Direct IP modems */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68A3, 0xFF, 0xFF, 0xFF), + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, + +diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c +index b169b0f9b3a2..9a08e18e09b9 100644 +--- a/drivers/usb/serial/usb-serial.c ++++ b/drivers/usb/serial/usb-serial.c +@@ -764,29 +764,39 @@ static int usb_serial_probe(struct usb_interface *interface, + if (usb_endpoint_is_bulk_in(endpoint)) { + /* we found a bulk in endpoint */ + dev_dbg(ddev, "found bulk in on endpoint %d\n", i); +- bulk_in_endpoint[num_bulk_in] = endpoint; +- ++num_bulk_in; ++ if (num_bulk_in < MAX_NUM_PORTS) { ++ bulk_in_endpoint[num_bulk_in] = endpoint; ++ ++num_bulk_in; ++ } + } + + if (usb_endpoint_is_bulk_out(endpoint)) { + /* we found a bulk out endpoint */ + dev_dbg(ddev, "found bulk out on endpoint %d\n", i); +- bulk_out_endpoint[num_bulk_out] = endpoint; +- ++num_bulk_out; ++ if (num_bulk_out < MAX_NUM_PORTS) { ++ bulk_out_endpoint[num_bulk_out] = endpoint; ++ ++num_bulk_out; ++ } + } + + if (usb_endpoint_is_int_in(endpoint)) { + /* we found a interrupt in endpoint */ + dev_dbg(ddev, "found interrupt in on endpoint %d\n", i); +- interrupt_in_endpoint[num_interrupt_in] = endpoint; +- ++num_interrupt_in; ++ if (num_interrupt_in < MAX_NUM_PORTS) { ++ interrupt_in_endpoint[num_interrupt_in] = ++ endpoint; ++ ++num_interrupt_in; ++ } + } + + if (usb_endpoint_is_int_out(endpoint)) { + /* we found an interrupt out endpoint */ + dev_dbg(ddev, "found interrupt out on endpoint %d\n", i); +- interrupt_out_endpoint[num_interrupt_out] = endpoint; +- ++num_interrupt_out; ++ if (num_interrupt_out < MAX_NUM_PORTS) { ++ interrupt_out_endpoint[num_interrupt_out] = ++ endpoint; ++ ++num_interrupt_out; ++ } + } + } + +@@ -809,8 +819,10 @@ static int usb_serial_probe(struct usb_interface *interface, + if (usb_endpoint_is_int_in(endpoint)) { + /* we found a interrupt in endpoint */ + dev_dbg(ddev, "found interrupt in for Prolific device on separate interface\n"); +- interrupt_in_endpoint[num_interrupt_in] = endpoint; +- ++num_interrupt_in; ++ if (num_interrupt_in < MAX_NUM_PORTS) { ++ interrupt_in_endpoint[num_interrupt_in] = endpoint; ++ ++num_interrupt_in; ++ } + } + } + } +@@ -850,6 +862,11 @@ static int usb_serial_probe(struct usb_interface *interface, + num_ports = type->num_ports; + } + ++ if (num_ports > MAX_NUM_PORTS) { ++ dev_warn(ddev, "too many ports requested: %d\n", num_ports); ++ num_ports = MAX_NUM_PORTS; ++ } ++ + serial->num_ports = num_ports; + serial->num_bulk_in = num_bulk_in; + serial->num_bulk_out = num_bulk_out; +diff --git a/drivers/usb/serial/zte_ev.c b/drivers/usb/serial/zte_ev.c +index e40ab739c4a6..c9bb107d5e5c 100644 +--- a/drivers/usb/serial/zte_ev.c ++++ b/drivers/usb/serial/zte_ev.c +@@ -272,28 +272,16 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port) + } + + static const struct usb_device_id id_table[] = { +- /* AC8710, AC8710T */ +- { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffff, 0xff, 0xff, 0xff) }, +- /* AC8700 */ +- { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xfffe, 0xff, 0xff, 0xff) }, +- /* MG880 */ +- { USB_DEVICE(0x19d2, 0xfffd) }, +- { USB_DEVICE(0x19d2, 0xfffc) }, +- { USB_DEVICE(0x19d2, 0xfffb) }, +- /* AC8710_V3 */ ++ { USB_DEVICE(0x19d2, 0xffec) }, ++ { USB_DEVICE(0x19d2, 0xffee) }, + { USB_DEVICE(0x19d2, 0xfff6) }, + { USB_DEVICE(0x19d2, 0xfff7) }, + { USB_DEVICE(0x19d2, 0xfff8) }, + { USB_DEVICE(0x19d2, 0xfff9) }, +- { USB_DEVICE(0x19d2, 0xffee) }, +- /* AC2716, MC2716 */ +- { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffed, 0xff, 0xff, 0xff) }, +- /* AD3812 */ +- { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffeb, 0xff, 0xff, 0xff) }, +- { USB_DEVICE(0x19d2, 0xffec) }, +- { USB_DEVICE(0x05C6, 0x3197) }, +- { USB_DEVICE(0x05C6, 0x6000) }, +- { USB_DEVICE(0x05C6, 0x9008) }, ++ { USB_DEVICE(0x19d2, 0xfffb) }, ++ { USB_DEVICE(0x19d2, 0xfffc) }, ++ /* MG880 */ ++ { USB_DEVICE(0x19d2, 0xfffd) }, + { }, + }; + MODULE_DEVICE_TABLE(usb, id_table); +diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h +index 042c83b01046..7f625306ea80 100644 +--- a/drivers/usb/storage/unusual_devs.h ++++ b/drivers/usb/storage/unusual_devs.h +@@ -101,6 +101,12 @@ UNUSUAL_DEV( 0x03f0, 0x4002, 0x0001, 0x0001, + "PhotoSmart R707", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), + ++UNUSUAL_DEV( 0x03f3, 0x0001, 0x0000, 0x9999, ++ "Adaptec", ++ "USBConnect 2000", ++ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, ++ US_FL_SCM_MULT_TARG ), ++ + /* Reported by Sebastian Kapfer + * and Olaf Hering (different bcd's, same vendor/product) + * for USB floppies that need the SINGLE_LUN enforcement. +@@ -741,6 +747,12 @@ UNUSUAL_DEV( 0x059b, 0x0001, 0x0100, 0x0100, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_SINGLE_LUN ), + ++UNUSUAL_DEV( 0x059b, 0x0040, 0x0100, 0x0100, ++ "Iomega", ++ "Jaz USB Adapter", ++ USB_SC_DEVICE, USB_PR_DEVICE, NULL, ++ US_FL_SINGLE_LUN ), ++ + /* Reported by */ + UNUSUAL_DEV( 0x059f, 0x0643, 0x0000, 0x0000, + "LaCie", +@@ -1113,6 +1125,18 @@ UNUSUAL_DEV( 0x0851, 0x1543, 0x0200, 0x0200, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NOT_LOCKABLE), + ++UNUSUAL_DEV( 0x085a, 0x0026, 0x0100, 0x0133, ++ "Xircom", ++ "PortGear USB-SCSI (Mac USB Dock)", ++ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, ++ US_FL_SCM_MULT_TARG ), ++ ++UNUSUAL_DEV( 0x085a, 0x0028, 0x0100, 0x0133, ++ "Xircom", ++ "PortGear USB to SCSI Converter", ++ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, ++ US_FL_SCM_MULT_TARG ), ++ + /* Submitted by Jan De Luyck */ + UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000, + "CITIZEN", +@@ -1945,6 +1969,14 @@ UNUSUAL_DEV( 0x152d, 0x2329, 0x0100, 0x0100, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ), + ++/* Entrega Technologies U1-SC25 (later Xircom PortGear PGSCSI) ++ * and Mac USB Dock USB-SCSI */ ++UNUSUAL_DEV( 0x1645, 0x0007, 0x0100, 0x0133, ++ "Entrega Technologies", ++ "USB to SCSI Converter", ++ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, ++ US_FL_SCM_MULT_TARG ), ++ + /* Reported by Robert Schedel + * Note: this is a 'super top' device like the above 14cd/6600 device */ + UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, +@@ -1967,6 +1999,12 @@ UNUSUAL_DEV( 0x177f, 0x0400, 0x0000, 0x0000, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ), + ++UNUSUAL_DEV( 0x1822, 0x0001, 0x0000, 0x9999, ++ "Ariston Technologies", ++ "iConnect USB to SCSI adapter", ++ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, ++ US_FL_SCM_MULT_TARG ), ++ + /* Reported by Hans de Goede + * These Appotech controllers are found in Picture Frames, they provide a + * (buggy) emulation of a cdrom drive which contains the windows software +diff --git a/drivers/uwb/lc-dev.c b/drivers/uwb/lc-dev.c +index 80079b8fed15..d0303f0dbe15 100644 +--- a/drivers/uwb/lc-dev.c ++++ b/drivers/uwb/lc-dev.c +@@ -431,16 +431,19 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce) + uwb_dev->mac_addr = *bce->mac_addr; + uwb_dev->dev_addr = bce->dev_addr; + dev_set_name(&uwb_dev->dev, "%s", macbuf); ++ ++ /* plug the beacon cache */ ++ bce->uwb_dev = uwb_dev; ++ uwb_dev->bce = bce; ++ uwb_bce_get(bce); /* released in uwb_dev_sys_release() */ ++ + result = uwb_dev_add(uwb_dev, &rc->uwb_dev.dev, rc); + if (result < 0) { + dev_err(dev, "new device %s: cannot instantiate device\n", + macbuf); + goto error_dev_add; + } +- /* plug the beacon cache */ +- bce->uwb_dev = uwb_dev; +- uwb_dev->bce = bce; +- uwb_bce_get(bce); /* released in uwb_dev_sys_release() */ ++ + dev_info(dev, "uwb device (mac %s dev %s) connected to %s %s\n", + macbuf, devbuf, rc->uwb_dev.dev.parent->bus->name, + dev_name(rc->uwb_dev.dev.parent)); +@@ -448,6 +451,8 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce) + return; + + error_dev_add: ++ bce->uwb_dev = NULL; ++ uwb_bce_put(bce); + kfree(uwb_dev); + return; + } +diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c +index 624e8dc24532..602913d7ae03 100644 +--- a/drivers/xen/manage.c ++++ b/drivers/xen/manage.c +@@ -111,16 +111,11 @@ static void do_suspend(void) + + shutting_down = SHUTDOWN_SUSPEND; + +-#ifdef CONFIG_PREEMPT +- /* If the kernel is preemptible, we need to freeze all the processes +- to prevent them from being in the middle of a pagetable update +- during suspend. */ + err = freeze_processes(); + if (err) { + pr_err("%s: freeze failed %d\n", __func__, err); + goto out; + } +-#endif + + err = dpm_suspend_start(PMSG_FREEZE); + if (err) { +@@ -169,10 +164,8 @@ out_resume: + dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE); + + out_thaw: +-#ifdef CONFIG_PREEMPT + thaw_processes(); + out: +-#endif + shutting_down = SHUTDOWN_INVALID; + } + #endif /* CONFIG_HIBERNATE_CALLBACKS */ +diff --git a/fs/aio.c b/fs/aio.c +index 6d68e01dc7ca..f45ddaa4fffa 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -141,6 +141,7 @@ struct kioctx { + + struct { + unsigned tail; ++ unsigned completed_events; + spinlock_t completion_lock; + } ____cacheline_aligned_in_smp; + +@@ -796,6 +797,9 @@ void exit_aio(struct mm_struct *mm) + unsigned i = 0; + + while (1) { ++ struct completion requests_done = ++ COMPLETION_INITIALIZER_ONSTACK(requests_done); ++ + rcu_read_lock(); + table = rcu_dereference(mm->ioctx_table); + +@@ -823,7 +827,10 @@ void exit_aio(struct mm_struct *mm) + */ + ctx->mmap_size = 0; + +- kill_ioctx(mm, ctx, NULL); ++ kill_ioctx(mm, ctx, &requests_done); ++ ++ /* Wait until all IO for the context are done. */ ++ wait_for_completion(&requests_done); + } + } + +@@ -880,6 +887,68 @@ out: + return ret; + } + ++/* refill_reqs_available ++ * Updates the reqs_available reference counts used for tracking the ++ * number of free slots in the completion ring. This can be called ++ * from aio_complete() (to optimistically update reqs_available) or ++ * from aio_get_req() (the we're out of events case). It must be ++ * called holding ctx->completion_lock. ++ */ ++static void refill_reqs_available(struct kioctx *ctx, unsigned head, ++ unsigned tail) ++{ ++ unsigned events_in_ring, completed; ++ ++ /* Clamp head since userland can write to it. */ ++ head %= ctx->nr_events; ++ if (head <= tail) ++ events_in_ring = tail - head; ++ else ++ events_in_ring = ctx->nr_events - (head - tail); ++ ++ completed = ctx->completed_events; ++ if (events_in_ring < completed) ++ completed -= events_in_ring; ++ else ++ completed = 0; ++ ++ if (!completed) ++ return; ++ ++ ctx->completed_events -= completed; ++ put_reqs_available(ctx, completed); ++} ++ ++/* user_refill_reqs_available ++ * Called to refill reqs_available when aio_get_req() encounters an ++ * out of space in the completion ring. ++ */ ++static void user_refill_reqs_available(struct kioctx *ctx) ++{ ++ spin_lock_irq(&ctx->completion_lock); ++ if (ctx->completed_events) { ++ struct aio_ring *ring; ++ unsigned head; ++ ++ /* Access of ring->head may race with aio_read_events_ring() ++ * here, but that's okay since whether we read the old version ++ * or the new version, and either will be valid. The important ++ * part is that head cannot pass tail since we prevent ++ * aio_complete() from updating tail by holding ++ * ctx->completion_lock. Even if head is invalid, the check ++ * against ctx->completed_events below will make sure we do the ++ * safe/right thing. ++ */ ++ ring = kmap_atomic(ctx->ring_pages[0]); ++ head = ring->head; ++ kunmap_atomic(ring); ++ ++ refill_reqs_available(ctx, head, ctx->tail); ++ } ++ ++ spin_unlock_irq(&ctx->completion_lock); ++} ++ + /* aio_get_req + * Allocate a slot for an aio request. + * Returns NULL if no requests are free. +@@ -888,8 +957,11 @@ static inline struct kiocb *aio_get_req(struct kioctx *ctx) + { + struct kiocb *req; + +- if (!get_reqs_available(ctx)) +- return NULL; ++ if (!get_reqs_available(ctx)) { ++ user_refill_reqs_available(ctx); ++ if (!get_reqs_available(ctx)) ++ return NULL; ++ } + + req = kmem_cache_alloc(kiocb_cachep, GFP_KERNEL|__GFP_ZERO); + if (unlikely(!req)) +@@ -948,8 +1020,8 @@ void aio_complete(struct kiocb *iocb, long res, long res2) + struct kioctx *ctx = iocb->ki_ctx; + struct aio_ring *ring; + struct io_event *ev_page, *event; ++ unsigned tail, pos, head; + unsigned long flags; +- unsigned tail, pos; + + /* + * Special case handling for sync iocbs: +@@ -1010,10 +1082,14 @@ void aio_complete(struct kiocb *iocb, long res, long res2) + ctx->tail = tail; + + ring = kmap_atomic(ctx->ring_pages[0]); ++ head = ring->head; + ring->tail = tail; + kunmap_atomic(ring); + flush_dcache_page(ctx->ring_pages[0]); + ++ ctx->completed_events++; ++ if (ctx->completed_events > 1) ++ refill_reqs_available(ctx, head, tail); + spin_unlock_irqrestore(&ctx->completion_lock, flags); + + pr_debug("added to ring %p at [%u]\n", iocb, tail); +@@ -1028,7 +1104,6 @@ void aio_complete(struct kiocb *iocb, long res, long res2) + + /* everything turned out well, dispose of the aiocb. */ + kiocb_free(iocb); +- put_reqs_available(ctx, 1); + + /* + * We have to order our ring_info tail store above and test +@@ -1065,6 +1140,12 @@ static long aio_read_events_ring(struct kioctx *ctx, + tail = ring->tail; + kunmap_atomic(ring); + ++ /* ++ * Ensure that once we've read the current tail pointer, that ++ * we also see the events that were stored up to the tail. ++ */ ++ smp_rmb(); ++ + pr_debug("h%u t%u m%u\n", head, tail, ctx->nr_events); + + if (head == tail) +diff --git a/fs/buffer.c b/fs/buffer.c +index 27265a8b43c1..71e2d0ed8530 100644 +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -1029,7 +1029,8 @@ grow_dev_page(struct block_device *bdev, sector_t block, + bh = page_buffers(page); + if (bh->b_size == size) { + end_block = init_page_buffers(page, bdev, +- index << sizebits, size); ++ (sector_t)index << sizebits, ++ size); + goto done; + } + if (!try_to_free_buffers(page)) +@@ -1050,7 +1051,8 @@ grow_dev_page(struct block_device *bdev, sector_t block, + */ + spin_lock(&inode->i_mapping->private_lock); + link_dev_buffers(page, bh); +- end_block = init_page_buffers(page, bdev, index << sizebits, size); ++ end_block = init_page_buffers(page, bdev, (sector_t)index << sizebits, ++ size); + spin_unlock(&inode->i_mapping->private_lock); + done: + ret = (block < end_block) ? 1 : -ENXIO; +diff --git a/fs/cifs/link.c b/fs/cifs/link.c +index 68559fd557fb..a5c2812ead68 100644 +--- a/fs/cifs/link.c ++++ b/fs/cifs/link.c +@@ -213,8 +213,12 @@ create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, + if (rc) + goto out; + +- rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon, cifs_sb, +- fromName, buf, &bytes_written); ++ if (tcon->ses->server->ops->create_mf_symlink) ++ rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon, ++ cifs_sb, fromName, buf, &bytes_written); ++ else ++ rc = -EOPNOTSUPP; ++ + if (rc) + goto out; + +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index ead00467282d..f50d79eb52db 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -1852,7 +1852,8 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, + goto error_tgt_fput; + + /* Check if EPOLLWAKEUP is allowed */ +- ep_take_care_of_epollwakeup(&epds); ++ if (ep_op_has_event(op)) ++ ep_take_care_of_epollwakeup(&epds); + + /* + * We have to check that the file structure underneath the file descriptor +diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c +index 5c524180c98e..bc643b97423c 100644 +--- a/fs/gfs2/inode.c ++++ b/fs/gfs2/inode.c +@@ -606,8 +606,10 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, + if (!IS_ERR(inode)) { + d = d_splice_alias(inode, dentry); + error = PTR_ERR(d); +- if (IS_ERR(d)) ++ if (IS_ERR(d)) { ++ inode = ERR_CAST(d); + goto fail_gunlock; ++ } + error = 0; + if (file) { + if (S_ISREG(inode->i_mode)) { +@@ -823,7 +825,6 @@ static struct dentry *__gfs2_lookup(struct inode *dir, struct dentry *dentry, + + d = d_splice_alias(inode, dentry); + if (IS_ERR(d)) { +- iput(inode); + gfs2_glock_dq_uninit(&gh); + return d; + } +diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c +index 6bf06a07f3e0..223e1cb14345 100644 +--- a/fs/lockd/svc.c ++++ b/fs/lockd/svc.c +@@ -253,13 +253,11 @@ static int lockd_up_net(struct svc_serv *serv, struct net *net) + + error = make_socks(serv, net); + if (error < 0) +- goto err_socks; ++ goto err_bind; + set_grace_period(net); + dprintk("lockd_up_net: per-net data created; net=%p\n", net); + return 0; + +-err_socks: +- svc_rpcb_cleanup(serv, net); + err_bind: + ln->nlmsvc_users--; + return error; +diff --git a/fs/namei.c b/fs/namei.c +index d5a4faeb39a5..dd2f2c5bda55 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -642,24 +642,22 @@ static int complete_walk(struct nameidata *nd) + + static __always_inline void set_root(struct nameidata *nd) + { +- if (!nd->root.mnt) +- get_fs_root(current->fs, &nd->root); ++ get_fs_root(current->fs, &nd->root); + } + + static int link_path_walk(const char *, struct nameidata *); + +-static __always_inline void set_root_rcu(struct nameidata *nd) ++static __always_inline unsigned set_root_rcu(struct nameidata *nd) + { +- if (!nd->root.mnt) { +- struct fs_struct *fs = current->fs; +- unsigned seq; ++ struct fs_struct *fs = current->fs; ++ unsigned seq, res; + +- do { +- seq = read_seqcount_begin(&fs->seq); +- nd->root = fs->root; +- nd->seq = __read_seqcount_begin(&nd->root.dentry->d_seq); +- } while (read_seqcount_retry(&fs->seq, seq)); +- } ++ do { ++ seq = read_seqcount_begin(&fs->seq); ++ nd->root = fs->root; ++ res = __read_seqcount_begin(&nd->root.dentry->d_seq); ++ } while (read_seqcount_retry(&fs->seq, seq)); ++ return res; + } + + static void path_put_conditional(struct path *path, struct nameidata *nd) +@@ -859,7 +857,8 @@ follow_link(struct path *link, struct nameidata *nd, void **p) + return PTR_ERR(s); + } + if (*s == '/') { +- set_root(nd); ++ if (!nd->root.mnt) ++ set_root(nd); + path_put(&nd->path); + nd->path = nd->root; + path_get(&nd->root); +@@ -1132,7 +1131,8 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, + + static int follow_dotdot_rcu(struct nameidata *nd) + { +- set_root_rcu(nd); ++ if (!nd->root.mnt) ++ set_root_rcu(nd); + + while (1) { + if (nd->path.dentry == nd->root.dentry && +@@ -1244,7 +1244,8 @@ static void follow_mount(struct path *path) + + static void follow_dotdot(struct nameidata *nd) + { +- set_root(nd); ++ if (!nd->root.mnt) ++ set_root(nd); + + while(1) { + struct dentry *old = nd->path.dentry; +@@ -1842,7 +1843,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, + if (*name=='/') { + if (flags & LOOKUP_RCU) { + rcu_read_lock(); +- set_root_rcu(nd); ++ nd->seq = set_root_rcu(nd); + } else { + set_root(nd); + path_get(&nd->root); +diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c +index 0e46d3d1b6cc..1abe4f55dea2 100644 +--- a/fs/nfs/nfs4client.c ++++ b/fs/nfs/nfs4client.c +@@ -482,6 +482,16 @@ int nfs40_walk_client_list(struct nfs_client *new, + + spin_lock(&nn->nfs_client_lock); + list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { ++ ++ if (pos->rpc_ops != new->rpc_ops) ++ continue; ++ ++ if (pos->cl_proto != new->cl_proto) ++ continue; ++ ++ if (pos->cl_minorversion != new->cl_minorversion) ++ continue; ++ + /* If "pos" isn't marked ready, we can't trust the + * remaining fields in "pos" */ + if (pos->cl_cons_state > NFS_CS_READY) { +@@ -501,15 +511,6 @@ int nfs40_walk_client_list(struct nfs_client *new, + if (pos->cl_cons_state != NFS_CS_READY) + continue; + +- if (pos->rpc_ops != new->rpc_ops) +- continue; +- +- if (pos->cl_proto != new->cl_proto) +- continue; +- +- if (pos->cl_minorversion != new->cl_minorversion) +- continue; +- + if (pos->cl_clientid != new->cl_clientid) + continue; + +@@ -615,6 +616,16 @@ int nfs41_walk_client_list(struct nfs_client *new, + + spin_lock(&nn->nfs_client_lock); + list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { ++ ++ if (pos->rpc_ops != new->rpc_ops) ++ continue; ++ ++ if (pos->cl_proto != new->cl_proto) ++ continue; ++ ++ if (pos->cl_minorversion != new->cl_minorversion) ++ continue; ++ + /* If "pos" isn't marked ready, we can't trust the + * remaining fields in "pos", especially the client + * ID and serverowner fields. Wait for CREATE_SESSION +@@ -640,15 +651,6 @@ int nfs41_walk_client_list(struct nfs_client *new, + if (pos->cl_cons_state != NFS_CS_READY) + continue; + +- if (pos->rpc_ops != new->rpc_ops) +- continue; +- +- if (pos->cl_proto != new->cl_proto) +- continue; +- +- if (pos->cl_minorversion != new->cl_minorversion) +- continue; +- + if (!nfs4_match_clientids(pos, new)) + continue; + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 17f91a72840b..2e9662ea5451 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -2558,23 +2558,23 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) + is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); + is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); + is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags); +- /* Calculate the current open share mode */ +- calldata->arg.fmode = 0; +- if (is_rdonly || is_rdwr) +- calldata->arg.fmode |= FMODE_READ; +- if (is_wronly || is_rdwr) +- calldata->arg.fmode |= FMODE_WRITE; + /* Calculate the change in open mode */ ++ calldata->arg.fmode = 0; + if (state->n_rdwr == 0) { +- if (state->n_rdonly == 0) { +- call_close |= is_rdonly || is_rdwr; +- calldata->arg.fmode &= ~FMODE_READ; +- } +- if (state->n_wronly == 0) { +- call_close |= is_wronly || is_rdwr; +- calldata->arg.fmode &= ~FMODE_WRITE; +- } +- } ++ if (state->n_rdonly == 0) ++ call_close |= is_rdonly; ++ else if (is_rdonly) ++ calldata->arg.fmode |= FMODE_READ; ++ if (state->n_wronly == 0) ++ call_close |= is_wronly; ++ else if (is_wronly) ++ calldata->arg.fmode |= FMODE_WRITE; ++ } else if (is_rdwr) ++ calldata->arg.fmode |= FMODE_READ|FMODE_WRITE; ++ ++ if (calldata->arg.fmode == 0) ++ call_close |= is_rdwr; ++ + if (!nfs4_valid_open_stateid(state)) + call_close = 0; + spin_unlock(&state->owner->so_lock); +diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c +index 7e350c562e0e..1e0bbae06ee7 100644 +--- a/fs/nilfs2/inode.c ++++ b/fs/nilfs2/inode.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + #include "nilfs.h" +@@ -219,10 +220,10 @@ static int nilfs_writepage(struct page *page, struct writeback_control *wbc) + + static int nilfs_set_page_dirty(struct page *page) + { ++ struct inode *inode = page->mapping->host; + int ret = __set_page_dirty_nobuffers(page); + + if (page_has_buffers(page)) { +- struct inode *inode = page->mapping->host; + unsigned nr_dirty = 0; + struct buffer_head *bh, *head; + +@@ -245,6 +246,10 @@ static int nilfs_set_page_dirty(struct page *page) + + if (nr_dirty) + nilfs_set_file_dirty(inode, nr_dirty); ++ } else if (ret) { ++ unsigned nr_dirty = 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits); ++ ++ nilfs_set_file_dirty(inode, nr_dirty); + } + return ret; + } +diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c +index 238a5930cb3c..9d7e2b9659cb 100644 +--- a/fs/notify/fdinfo.c ++++ b/fs/notify/fdinfo.c +@@ -42,7 +42,7 @@ static int show_mark_fhandle(struct seq_file *m, struct inode *inode) + { + struct { + struct file_handle handle; +- u8 pad[64]; ++ u8 pad[MAX_HANDLE_SZ]; + } f; + int size, ret, i; + +@@ -50,7 +50,7 @@ static int show_mark_fhandle(struct seq_file *m, struct inode *inode) + size = f.handle.handle_bytes >> 2; + + ret = exportfs_encode_inode_fh(inode, (struct fid *)f.handle.f_handle, &size, 0); +- if ((ret == 255) || (ret == -ENOSPC)) { ++ if ((ret == FILEID_INVALID) || (ret < 0)) { + WARN_ONCE(1, "Can't encode file handler for inotify: %d\n", ret); + return 0; + } +diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c +index af3f7aa73e13..1be3398c96f6 100644 +--- a/fs/ocfs2/dlm/dlmmaster.c ++++ b/fs/ocfs2/dlm/dlmmaster.c +@@ -650,12 +650,9 @@ void dlm_lockres_clear_refmap_bit(struct dlm_ctxt *dlm, + clear_bit(bit, res->refmap); + } + +- +-void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, ++static void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res) + { +- assert_spin_locked(&res->spinlock); +- + res->inflight_locks++; + + mlog(0, "%s: res %.*s, inflight++: now %u, %ps()\n", dlm->name, +@@ -663,6 +660,13 @@ void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, + __builtin_return_address(0)); + } + ++void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, ++ struct dlm_lock_resource *res) ++{ ++ assert_spin_locked(&res->spinlock); ++ __dlm_lockres_grab_inflight_ref(dlm, res); ++} ++ + void dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res) + { +@@ -852,10 +856,8 @@ lookup: + /* finally add the lockres to its hash bucket */ + __dlm_insert_lockres(dlm, res); + +- /* Grab inflight ref to pin the resource */ +- spin_lock(&res->spinlock); +- dlm_lockres_grab_inflight_ref(dlm, res); +- spin_unlock(&res->spinlock); ++ /* since this lockres is new it doesn't not require the spinlock */ ++ __dlm_lockres_grab_inflight_ref(dlm, res); + + /* get an extra ref on the mle in case this is a BLOCK + * if so, the creator of the BLOCK may try to put the last +diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h +index e9c4f190ffae..ac46782c10d3 100644 +--- a/include/acpi/acpi_bus.h ++++ b/include/acpi/acpi_bus.h +@@ -118,6 +118,7 @@ struct acpi_device; + struct acpi_hotplug_profile { + struct kobject kobj; + int (*scan_dependent)(struct acpi_device *adev); ++ void (*notify_online)(struct acpi_device *adev); + bool enabled:1; + bool demand_offline:1; + }; +diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h +index 369cf2cd5144..68f46cd5d514 100644 +--- a/include/linux/iio/trigger.h ++++ b/include/linux/iio/trigger.h +@@ -84,10 +84,12 @@ static inline void iio_trigger_put(struct iio_trigger *trig) + put_device(&trig->dev); + } + +-static inline void iio_trigger_get(struct iio_trigger *trig) ++static inline struct iio_trigger *iio_trigger_get(struct iio_trigger *trig) + { + get_device(&trig->dev); + __module_get(trig->ops->owner); ++ ++ return trig; + } + + /** +diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h +index 535f158977b9..8cf350325dc6 100644 +--- a/include/linux/seqlock.h ++++ b/include/linux/seqlock.h +@@ -164,8 +164,6 @@ static inline unsigned read_seqcount_begin(const seqcount_t *s) + static inline unsigned raw_seqcount_begin(const seqcount_t *s) + { + unsigned ret = ACCESS_ONCE(s->sequence); +- +- seqcount_lockdep_reader_access(s); + smp_rmb(); + return ret & ~1; + } +diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h +index 502073a53dd3..b483abd34493 100644 +--- a/include/linux/vga_switcheroo.h ++++ b/include/linux/vga_switcheroo.h +@@ -64,6 +64,7 @@ int vga_switcheroo_get_client_state(struct pci_dev *dev); + void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo_state dynamic); + + int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain); ++void vga_switcheroo_fini_domain_pm_ops(struct device *dev); + int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct dev_pm_domain *domain); + #else + +@@ -82,6 +83,7 @@ static inline int vga_switcheroo_get_client_state(struct pci_dev *dev) { return + static inline void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo_state dynamic) {} + + static inline int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain) { return -EINVAL; } ++static inline void vga_switcheroo_fini_domain_pm_ops(struct device *dev) {} + static inline int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct dev_pm_domain *domain) { return -EINVAL; } + + #endif +diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h +index 704f4f652d0a..6c62cfa25f1a 100644 +--- a/include/linux/workqueue.h ++++ b/include/linux/workqueue.h +@@ -452,7 +452,7 @@ __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active, + alloc_workqueue("%s", WQ_FREEZABLE | WQ_UNBOUND | WQ_MEM_RECLAIM, \ + 1, (name)) + #define create_singlethread_workqueue(name) \ +- alloc_workqueue("%s", WQ_UNBOUND | WQ_MEM_RECLAIM, 1, (name)) ++ alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM, name) + + extern void destroy_workqueue(struct workqueue_struct *wq); + +diff --git a/include/net/regulatory.h b/include/net/regulatory.h +index b07cdc9fa454..f103f30122a1 100644 +--- a/include/net/regulatory.h ++++ b/include/net/regulatory.h +@@ -160,7 +160,7 @@ struct ieee80211_reg_rule { + struct ieee80211_regdomain { + struct rcu_head rcu_head; + u32 n_reg_rules; +- char alpha2[2]; ++ char alpha2[3]; + enum nl80211_dfs_regions dfs_region; + struct ieee80211_reg_rule reg_rules[]; + }; +diff --git a/include/uapi/linux/usb/functionfs.h b/include/uapi/linux/usb/functionfs.h +index 29e9c7aa9c66..f279394aafb0 100644 +--- a/include/uapi/linux/usb/functionfs.h ++++ b/include/uapi/linux/usb/functionfs.h +@@ -27,24 +27,18 @@ struct usb_endpoint_descriptor_no_audio { + __u8 bInterval; + } __attribute__((packed)); + +-/* Legacy format, deprecated as of 3.14. */ +-struct usb_functionfs_descs_head { +- __le32 magic; +- __le32 length; +- __le32 fs_count; +- __le32 hs_count; +-} __attribute__((packed, deprecated)); + + /* + * All numbers must be in little endian order. + */ + ++/* Legacy format, deprecated as of 3.14. */ + struct usb_functionfs_descs_head { + __le32 magic; + __le32 length; + __le32 fs_count; + __le32 hs_count; +-} __attribute__((packed)); ++} __attribute__((packed, deprecated)); + + /* + * Descriptors format: +diff --git a/include/uapi/linux/xattr.h b/include/uapi/linux/xattr.h +index c38355c1f3c9..1590c49cae57 100644 +--- a/include/uapi/linux/xattr.h ++++ b/include/uapi/linux/xattr.h +@@ -13,7 +13,7 @@ + #ifndef _UAPI_LINUX_XATTR_H + #define _UAPI_LINUX_XATTR_H + +-#ifdef __UAPI_DEF_XATTR ++#if __UAPI_DEF_XATTR + #define __USE_KERNEL_XATTR_DEFS + + #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */ +diff --git a/kernel/cgroup.c b/kernel/cgroup.c +index 0c753ddd223b..550e2050d778 100644 +--- a/kernel/cgroup.c ++++ b/kernel/cgroup.c +@@ -3663,7 +3663,6 @@ static int pidlist_array_load(struct cgroup *cgrp, enum cgroup_filetype type, + + l = cgroup_pidlist_find_create(cgrp, type); + if (!l) { +- mutex_unlock(&cgrp->pidlist_mutex); + pidlist_free(array); + return -ENOMEM; + } +diff --git a/kernel/events/core.c b/kernel/events/core.c +index f774e9365a03..3a140ca37777 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -1516,6 +1516,11 @@ retry: + */ + if (ctx->is_active) { + raw_spin_unlock_irq(&ctx->lock); ++ /* ++ * Reload the task pointer, it might have been changed by ++ * a concurrent perf_event_context_sched_out(). ++ */ ++ task = ctx->task; + goto retry; + } + +@@ -1957,6 +1962,11 @@ retry: + */ + if (ctx->is_active) { + raw_spin_unlock_irq(&ctx->lock); ++ /* ++ * Reload the task pointer, it might have been changed by ++ * a concurrent perf_event_context_sched_out(). ++ */ ++ task = ctx->task; + goto retry; + } + +diff --git a/kernel/futex.c b/kernel/futex.c +index e3087afb7429..0b0dc02aabce 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -2614,6 +2614,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, + * shared futexes. We need to compare the keys: + */ + if (match_futex(&q.key, &key2)) { ++ queue_unlock(hb); + ret = -EINVAL; + goto out_put_keys; + } +diff --git a/kernel/kcmp.c b/kernel/kcmp.c +index e30ac0fe61c3..0aa69ea1d8fd 100644 +--- a/kernel/kcmp.c ++++ b/kernel/kcmp.c +@@ -44,11 +44,12 @@ static long kptr_obfuscate(long v, int type) + */ + static int kcmp_ptr(void *v1, void *v2, enum kcmp_type type) + { +- long ret; ++ long t1, t2; + +- ret = kptr_obfuscate((long)v1, type) - kptr_obfuscate((long)v2, type); ++ t1 = kptr_obfuscate((long)v1, type); ++ t2 = kptr_obfuscate((long)v2, type); + +- return (ret < 0) | ((ret > 0) << 1); ++ return (t1 < t2) | ((t1 > t2) << 1); + } + + /* The caller must have pinned the task */ +diff --git a/kernel/power/main.c b/kernel/power/main.c +index 1d1bf630e6e9..3ae41cdd804a 100644 +--- a/kernel/power/main.c ++++ b/kernel/power/main.c +@@ -293,12 +293,12 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, + { + char *s = buf; + #ifdef CONFIG_SUSPEND +- int i; ++ suspend_state_t i; ++ ++ for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++) ++ if (pm_states[i].state) ++ s += sprintf(s,"%s ", pm_states[i].label); + +- for (i = 0; i < PM_SUSPEND_MAX; i++) { +- if (pm_states[i] && valid_state(i)) +- s += sprintf(s,"%s ", pm_states[i]); +- } + #endif + #ifdef CONFIG_HIBERNATION + s += sprintf(s, "%s\n", "disk"); +@@ -314,7 +314,7 @@ static suspend_state_t decode_state(const char *buf, size_t n) + { + #ifdef CONFIG_SUSPEND + suspend_state_t state = PM_SUSPEND_MIN; +- const char * const *s; ++ struct pm_sleep_state *s; + #endif + char *p; + int len; +@@ -328,8 +328,9 @@ static suspend_state_t decode_state(const char *buf, size_t n) + + #ifdef CONFIG_SUSPEND + for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) +- if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) +- return state; ++ if (s->state && len == strlen(s->label) ++ && !strncmp(buf, s->label, len)) ++ return s->state; + #endif + + return PM_SUSPEND_ON; +@@ -447,8 +448,8 @@ static ssize_t autosleep_show(struct kobject *kobj, + + #ifdef CONFIG_SUSPEND + if (state < PM_SUSPEND_MAX) +- return sprintf(buf, "%s\n", valid_state(state) ? +- pm_states[state] : "error"); ++ return sprintf(buf, "%s\n", pm_states[state].state ? ++ pm_states[state].label : "error"); + #endif + #ifdef CONFIG_HIBERNATION + return sprintf(buf, "disk\n"); +diff --git a/kernel/power/power.h b/kernel/power/power.h +index 7d4b7ffb3c1d..f770cad3666c 100644 +--- a/kernel/power/power.h ++++ b/kernel/power/power.h +@@ -175,17 +175,20 @@ extern void swsusp_show_speed(struct timeval *, struct timeval *, + unsigned int, char *); + + #ifdef CONFIG_SUSPEND ++struct pm_sleep_state { ++ const char *label; ++ suspend_state_t state; ++}; ++ + /* kernel/power/suspend.c */ +-extern const char *const pm_states[]; ++extern struct pm_sleep_state pm_states[]; + +-extern bool valid_state(suspend_state_t state); + extern int suspend_devices_and_enter(suspend_state_t state); + #else /* !CONFIG_SUSPEND */ + static inline int suspend_devices_and_enter(suspend_state_t state) + { + return -ENOSYS; + } +-static inline bool valid_state(suspend_state_t state) { return false; } + #endif /* !CONFIG_SUSPEND */ + + #ifdef CONFIG_PM_TEST_SUSPEND +diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c +index 62ee437b5c7e..5455d5c3c149 100644 +--- a/kernel/power/suspend.c ++++ b/kernel/power/suspend.c +@@ -29,10 +29,10 @@ + + #include "power.h" + +-const char *const pm_states[PM_SUSPEND_MAX] = { +- [PM_SUSPEND_FREEZE] = "freeze", +- [PM_SUSPEND_STANDBY] = "standby", +- [PM_SUSPEND_MEM] = "mem", ++struct pm_sleep_state pm_states[PM_SUSPEND_MAX] = { ++ [PM_SUSPEND_FREEZE] = { .label = "freeze", .state = PM_SUSPEND_FREEZE }, ++ [PM_SUSPEND_STANDBY] = { .label = "standby", }, ++ [PM_SUSPEND_MEM] = { .label = "mem", }, + }; + + static const struct platform_suspend_ops *suspend_ops; +@@ -62,42 +62,34 @@ void freeze_wake(void) + } + EXPORT_SYMBOL_GPL(freeze_wake); + ++static bool valid_state(suspend_state_t state) ++{ ++ /* ++ * PM_SUSPEND_STANDBY and PM_SUSPEND_MEM states need low level ++ * support and need to be valid to the low level ++ * implementation, no valid callback implies that none are valid. ++ */ ++ return suspend_ops && suspend_ops->valid && suspend_ops->valid(state); ++} ++ + /** + * suspend_set_ops - Set the global suspend method table. + * @ops: Suspend operations to use. + */ + void suspend_set_ops(const struct platform_suspend_ops *ops) + { ++ suspend_state_t i; ++ + lock_system_sleep(); ++ + suspend_ops = ops; ++ for (i = PM_SUSPEND_STANDBY; i <= PM_SUSPEND_MEM; i++) ++ pm_states[i].state = valid_state(i) ? i : 0; ++ + unlock_system_sleep(); + } + EXPORT_SYMBOL_GPL(suspend_set_ops); + +-bool valid_state(suspend_state_t state) +-{ +- if (state == PM_SUSPEND_FREEZE) { +-#ifdef CONFIG_PM_DEBUG +- if (pm_test_level != TEST_NONE && +- pm_test_level != TEST_FREEZER && +- pm_test_level != TEST_DEVICES && +- pm_test_level != TEST_PLATFORM) { +- printk(KERN_WARNING "Unsupported pm_test mode for " +- "freeze state, please choose " +- "none/freezer/devices/platform.\n"); +- return false; +- } +-#endif +- return true; +- } +- /* +- * PM_SUSPEND_STANDBY and PM_SUSPEND_MEMORY states need lowlevel +- * support and need to be valid to the lowlevel +- * implementation, no valid callback implies that none are valid. +- */ +- return suspend_ops && suspend_ops->valid && suspend_ops->valid(state); +-} +- + /** + * suspend_valid_only_mem - Generic memory-only valid callback. + * +@@ -324,9 +316,17 @@ static int enter_state(suspend_state_t state) + { + int error; + +- if (!valid_state(state)) +- return -ENODEV; +- ++ if (state == PM_SUSPEND_FREEZE) { ++#ifdef CONFIG_PM_DEBUG ++ if (pm_test_level != TEST_NONE && pm_test_level <= TEST_CPUS) { ++ pr_warning("PM: Unsupported test mode for freeze state," ++ "please choose none/freezer/devices/platform.\n"); ++ return -EAGAIN; ++ } ++#endif ++ } else if (!valid_state(state)) { ++ return -EINVAL; ++ } + if (!mutex_trylock(&pm_mutex)) + return -EBUSY; + +@@ -337,7 +337,7 @@ static int enter_state(suspend_state_t state) + sys_sync(); + printk("done.\n"); + +- pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); ++ pr_debug("PM: Preparing system for %s sleep\n", pm_states[state].label); + error = suspend_prepare(state); + if (error) + goto Unlock; +@@ -345,7 +345,7 @@ static int enter_state(suspend_state_t state) + if (suspend_test(TEST_FREEZER)) + goto Finish; + +- pr_debug("PM: Entering %s sleep\n", pm_states[state]); ++ pr_debug("PM: Entering %s sleep\n", pm_states[state].label); + pm_restrict_gfp_mask(); + error = suspend_devices_and_enter(state); + pm_restore_gfp_mask(); +diff --git a/kernel/power/suspend_test.c b/kernel/power/suspend_test.c +index 9b2a1d58558d..269b097e78ea 100644 +--- a/kernel/power/suspend_test.c ++++ b/kernel/power/suspend_test.c +@@ -92,13 +92,13 @@ static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state) + } + + if (state == PM_SUSPEND_MEM) { +- printk(info_test, pm_states[state]); ++ printk(info_test, pm_states[state].label); + status = pm_suspend(state); + if (status == -ENODEV) + state = PM_SUSPEND_STANDBY; + } + if (state == PM_SUSPEND_STANDBY) { +- printk(info_test, pm_states[state]); ++ printk(info_test, pm_states[state].label); + status = pm_suspend(state); + } + if (status < 0) +@@ -136,18 +136,16 @@ static char warn_bad_state[] __initdata = + + static int __init setup_test_suspend(char *value) + { +- unsigned i; ++ suspend_state_t i; + + /* "=mem" ==> "mem" */ + value++; +- for (i = 0; i < PM_SUSPEND_MAX; i++) { +- if (!pm_states[i]) +- continue; +- if (strcmp(pm_states[i], value) != 0) +- continue; +- test_state = (__force suspend_state_t) i; +- return 0; +- } ++ for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++) ++ if (!strcmp(pm_states[i].label, value)) { ++ test_state = pm_states[i].state; ++ return 0; ++ } ++ + printk(warn_bad_state, value); + return 0; + } +@@ -164,8 +162,8 @@ static int __init test_suspend(void) + /* PM is initialized by now; is that state testable? */ + if (test_state == PM_SUSPEND_ON) + goto done; +- if (!valid_state(test_state)) { +- printk(warn_bad_state, pm_states[test_state]); ++ if (!pm_states[test_state].state) { ++ printk(warn_bad_state, pm_states[test_state].label); + goto done; + } + +diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c +index fe75444ae7ec..cd45a0727a16 100644 +--- a/kernel/time/alarmtimer.c ++++ b/kernel/time/alarmtimer.c +@@ -464,18 +464,26 @@ static enum alarmtimer_type clock2alarm(clockid_t clockid) + static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, + ktime_t now) + { ++ unsigned long flags; + struct k_itimer *ptr = container_of(alarm, struct k_itimer, + it.alarm.alarmtimer); +- if (posix_timer_event(ptr, 0) != 0) +- ptr->it_overrun++; ++ enum alarmtimer_restart result = ALARMTIMER_NORESTART; ++ ++ spin_lock_irqsave(&ptr->it_lock, flags); ++ if ((ptr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) { ++ if (posix_timer_event(ptr, 0) != 0) ++ ptr->it_overrun++; ++ } + + /* Re-add periodic timers */ + if (ptr->it.alarm.interval.tv64) { + ptr->it_overrun += alarm_forward(alarm, now, + ptr->it.alarm.interval); +- return ALARMTIMER_RESTART; ++ result = ALARMTIMER_RESTART; + } +- return ALARMTIMER_NORESTART; ++ spin_unlock_irqrestore(&ptr->it_lock, flags); ++ ++ return result; + } + + /** +@@ -541,18 +549,22 @@ static int alarm_timer_create(struct k_itimer *new_timer) + * @new_timer: k_itimer pointer + * @cur_setting: itimerspec data to fill + * +- * Copies the itimerspec data out from the k_itimer ++ * Copies out the current itimerspec data + */ + static void alarm_timer_get(struct k_itimer *timr, + struct itimerspec *cur_setting) + { +- memset(cur_setting, 0, sizeof(struct itimerspec)); ++ ktime_t relative_expiry_time = ++ alarm_expires_remaining(&(timr->it.alarm.alarmtimer)); ++ ++ if (ktime_to_ns(relative_expiry_time) > 0) { ++ cur_setting->it_value = ktime_to_timespec(relative_expiry_time); ++ } else { ++ cur_setting->it_value.tv_sec = 0; ++ cur_setting->it_value.tv_nsec = 0; ++ } + +- cur_setting->it_interval = +- ktime_to_timespec(timr->it.alarm.interval); +- cur_setting->it_value = +- ktime_to_timespec(timr->it.alarm.alarmtimer.node.expires); +- return; ++ cur_setting->it_interval = ktime_to_timespec(timr->it.alarm.interval); + } + + /** +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index a53f1bbc546b..773aba836e81 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -626,8 +626,22 @@ int ring_buffer_poll_wait(struct ring_buffer *buffer, int cpu, + work = &cpu_buffer->irq_work; + } + +- work->waiters_pending = true; + poll_wait(filp, &work->waiters, poll_table); ++ work->waiters_pending = true; ++ /* ++ * There's a tight race between setting the waiters_pending and ++ * checking if the ring buffer is empty. Once the waiters_pending bit ++ * is set, the next event will wake the task up, but we can get stuck ++ * if there's only a single event in. ++ * ++ * FIXME: Ideally, we need a memory barrier on the writer side as well, ++ * but adding a memory barrier to all events will cause too much of a ++ * performance hit in the fast path. We only need a memory barrier when ++ * the buffer goes from empty to having content. But as this race is ++ * extremely small, and it's not a problem if another event comes in, we ++ * will fix it later. ++ */ ++ smp_mb(); + + if ((cpu == RING_BUFFER_ALL_CPUS && !ring_buffer_empty(buffer)) || + (cpu != RING_BUFFER_ALL_CPUS && !ring_buffer_empty_cpu(buffer, cpu))) +diff --git a/mm/memblock.c b/mm/memblock.c +index 39a31e7f0045..0739dc1b4095 100644 +--- a/mm/memblock.c ++++ b/mm/memblock.c +@@ -183,8 +183,7 @@ phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size, + phys_addr_t align, phys_addr_t start, + phys_addr_t end, int nid) + { +- int ret; +- phys_addr_t kernel_end; ++ phys_addr_t kernel_end, ret; + + /* pump up @end */ + if (end == MEMBLOCK_ALLOC_ACCESSIBLE) +diff --git a/mm/memory.c b/mm/memory.c +index 2121d8b8db56..492e36f27f43 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -1120,7 +1120,7 @@ again: + addr) != page->index) { + pte_t ptfile = pgoff_to_pte(page->index); + if (pte_soft_dirty(ptent)) +- pte_file_mksoft_dirty(ptfile); ++ ptfile = pte_file_mksoft_dirty(ptfile); + set_pte_at(mm, addr, pte, ptfile); + } + if (PageAnon(page)) +diff --git a/mm/percpu-vm.c b/mm/percpu-vm.c +index 3707c71ae4cd..51108165f829 100644 +--- a/mm/percpu-vm.c ++++ b/mm/percpu-vm.c +@@ -108,7 +108,7 @@ static int pcpu_alloc_pages(struct pcpu_chunk *chunk, + int page_start, int page_end) + { + const gfp_t gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD; +- unsigned int cpu; ++ unsigned int cpu, tcpu; + int i; + + for_each_possible_cpu(cpu) { +@@ -116,14 +116,23 @@ static int pcpu_alloc_pages(struct pcpu_chunk *chunk, + struct page **pagep = &pages[pcpu_page_idx(cpu, i)]; + + *pagep = alloc_pages_node(cpu_to_node(cpu), gfp, 0); +- if (!*pagep) { +- pcpu_free_pages(chunk, pages, populated, +- page_start, page_end); +- return -ENOMEM; +- } ++ if (!*pagep) ++ goto err; + } + } + return 0; ++ ++err: ++ while (--i >= page_start) ++ __free_page(pages[pcpu_page_idx(cpu, i)]); ++ ++ for_each_possible_cpu(tcpu) { ++ if (tcpu == cpu) ++ break; ++ for (i = page_start; i < page_end; i++) ++ __free_page(pages[pcpu_page_idx(tcpu, i)]); ++ } ++ return -ENOMEM; + } + + /** +@@ -263,6 +272,7 @@ err: + __pcpu_unmap_pages(pcpu_chunk_addr(chunk, tcpu, page_start), + page_end - page_start); + } ++ pcpu_post_unmap_tlb_flush(chunk, page_start, page_end); + return err; + } + +diff --git a/mm/percpu.c b/mm/percpu.c +index a2a54a85f691..8cd4308471c3 100644 +--- a/mm/percpu.c ++++ b/mm/percpu.c +@@ -1917,6 +1917,8 @@ void __init setup_per_cpu_areas(void) + + if (pcpu_setup_first_chunk(ai, fc) < 0) + panic("Failed to initialize percpu areas."); ++ ++ pcpu_free_alloc_info(ai); + } + + #endif /* CONFIG_SMP */ +diff --git a/mm/shmem.c b/mm/shmem.c +index ff85863587ee..f0d698ba7d0f 100644 +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -2143,8 +2143,10 @@ static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct + + if (new_dentry->d_inode) { + (void) shmem_unlink(new_dir, new_dentry); +- if (they_are_dirs) ++ if (they_are_dirs) { ++ drop_nlink(new_dentry->d_inode); + drop_nlink(old_dir); ++ } + } else if (they_are_dirs) { + drop_nlink(old_dir); + inc_nlink(new_dir); +diff --git a/mm/slab.c b/mm/slab.c +index 6dd8d5f3a3ac..ea854eb2388c 100644 +--- a/mm/slab.c ++++ b/mm/slab.c +@@ -2189,7 +2189,8 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) + int + __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) + { +- size_t left_over, freelist_size, ralign; ++ size_t left_over, freelist_size; ++ size_t ralign = BYTES_PER_WORD; + gfp_t gfp; + int err; + size_t size = cachep->size; +@@ -2222,14 +2223,6 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) + size &= ~(BYTES_PER_WORD - 1); + } + +- /* +- * Redzoning and user store require word alignment or possibly larger. +- * Note this will be overridden by architecture or caller mandated +- * alignment if either is greater than BYTES_PER_WORD. +- */ +- if (flags & SLAB_STORE_USER) +- ralign = BYTES_PER_WORD; +- + if (flags & SLAB_RED_ZONE) { + ralign = REDZONE_ALIGN; + /* If redzoning, ensure that the second redzone is suitably +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index e6a84cb1a5e4..189eef014c4f 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -4240,8 +4240,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, + rcu_read_unlock(); + + if (bss->wmm_used && bss->uapsd_supported && +- (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) && +- sdata->wmm_acm != 0xff) { ++ (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { + assoc_data->uapsd = true; + ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; + } else { +diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c +index a8eb0a89326a..610e19c0e13f 100644 +--- a/net/netfilter/ipvs/ip_vs_conn.c ++++ b/net/netfilter/ipvs/ip_vs_conn.c +@@ -797,7 +797,6 @@ static void ip_vs_conn_expire(unsigned long data) + ip_vs_control_del(cp); + + if (cp->flags & IP_VS_CONN_F_NFCT) { +- ip_vs_conn_drop_conntrack(cp); + /* Do not access conntracks during subsys cleanup + * because nf_conntrack_find_get can not be used after + * conntrack cleanup for the net. +diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c +index 3d2d2c8108ca..27d3f40de3cd 100644 +--- a/net/netfilter/ipvs/ip_vs_core.c ++++ b/net/netfilter/ipvs/ip_vs_core.c +@@ -1906,7 +1906,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { + { + .hook = ip_vs_local_reply6, + .owner = THIS_MODULE, +- .pf = NFPROTO_IPV4, ++ .pf = NFPROTO_IPV6, + .hooknum = NF_INET_LOCAL_OUT, + .priority = NF_IP6_PRI_NAT_DST + 1, + }, +diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c +index 7f0e1cf2d7e8..1692e7534759 100644 +--- a/net/netfilter/ipvs/ip_vs_xmit.c ++++ b/net/netfilter/ipvs/ip_vs_xmit.c +@@ -967,8 +967,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + iph->nexthdr = IPPROTO_IPV6; + iph->payload_len = old_iph->payload_len; + be16_add_cpu(&iph->payload_len, sizeof(*old_iph)); +- iph->priority = old_iph->priority; + memset(&iph->flow_lbl, 0, sizeof(iph->flow_lbl)); ++ ipv6_change_dsfield(iph, 0, ipv6_get_dsfield(old_iph)); + iph->daddr = cp->daddr.in6; + iph->saddr = saddr; + iph->hop_limit = old_iph->hop_limit; +diff --git a/net/netfilter/xt_cgroup.c b/net/netfilter/xt_cgroup.c +index 9a8e77e7f8d4..ef5c75a5b200 100644 +--- a/net/netfilter/xt_cgroup.c ++++ b/net/netfilter/xt_cgroup.c +@@ -31,7 +31,7 @@ static int cgroup_mt_check(const struct xt_mtchk_param *par) + if (info->invert & ~1) + return -EINVAL; + +- return info->id ? 0 : -EINVAL; ++ return 0; + } + + static bool +diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c +index a3910fc2122b..47dc6836830a 100644 +--- a/net/netfilter/xt_hashlimit.c ++++ b/net/netfilter/xt_hashlimit.c +@@ -104,7 +104,7 @@ struct xt_hashlimit_htable { + spinlock_t lock; /* lock for list_head */ + u_int32_t rnd; /* random seed for hash */ + unsigned int count; /* number entries in table */ +- struct timer_list timer; /* timer for gc */ ++ struct delayed_work gc_work; + + /* seq_file stuff */ + struct proc_dir_entry *pde; +@@ -213,7 +213,7 @@ dsthash_free(struct xt_hashlimit_htable *ht, struct dsthash_ent *ent) + call_rcu_bh(&ent->rcu, dsthash_free_rcu); + ht->count--; + } +-static void htable_gc(unsigned long htlong); ++static void htable_gc(struct work_struct *work); + + static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, + u_int8_t family) +@@ -273,9 +273,9 @@ static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, + } + hinfo->net = net; + +- setup_timer(&hinfo->timer, htable_gc, (unsigned long)hinfo); +- hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); +- add_timer(&hinfo->timer); ++ INIT_DEFERRABLE_WORK(&hinfo->gc_work, htable_gc); ++ queue_delayed_work(system_power_efficient_wq, &hinfo->gc_work, ++ msecs_to_jiffies(hinfo->cfg.gc_interval)); + + hlist_add_head(&hinfo->node, &hashlimit_net->htables); + +@@ -300,29 +300,30 @@ static void htable_selective_cleanup(struct xt_hashlimit_htable *ht, + { + unsigned int i; + +- /* lock hash table and iterate over it */ +- spin_lock_bh(&ht->lock); + for (i = 0; i < ht->cfg.size; i++) { + struct dsthash_ent *dh; + struct hlist_node *n; ++ ++ spin_lock_bh(&ht->lock); + hlist_for_each_entry_safe(dh, n, &ht->hash[i], node) { + if ((*select)(ht, dh)) + dsthash_free(ht, dh); + } ++ spin_unlock_bh(&ht->lock); ++ cond_resched(); + } +- spin_unlock_bh(&ht->lock); + } + +-/* hash table garbage collector, run by timer */ +-static void htable_gc(unsigned long htlong) ++static void htable_gc(struct work_struct *work) + { +- struct xt_hashlimit_htable *ht = (struct xt_hashlimit_htable *)htlong; ++ struct xt_hashlimit_htable *ht; ++ ++ ht = container_of(work, struct xt_hashlimit_htable, gc_work.work); + + htable_selective_cleanup(ht, select_gc); + +- /* re-add the timer accordingly */ +- ht->timer.expires = jiffies + msecs_to_jiffies(ht->cfg.gc_interval); +- add_timer(&ht->timer); ++ queue_delayed_work(system_power_efficient_wq, ++ &ht->gc_work, msecs_to_jiffies(ht->cfg.gc_interval)); + } + + static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo) +@@ -341,7 +342,7 @@ static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo) + + static void htable_destroy(struct xt_hashlimit_htable *hinfo) + { +- del_timer_sync(&hinfo->timer); ++ cancel_delayed_work_sync(&hinfo->gc_work); + htable_remove_proc_entry(hinfo); + htable_selective_cleanup(hinfo, select_all); + kfree(hinfo->name); +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index e6283464a8e6..df33156ecd2d 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -6796,6 +6796,9 @@ void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp) + struct nlattr *data = ((void **)skb->cb)[2]; + enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE; + ++ /* clear CB data for netlink core to own from now on */ ++ memset(skb->cb, 0, sizeof(skb->cb)); ++ + nla_nest_end(skb, data); + genlmsg_end(skb, hdr); + +@@ -9075,6 +9078,9 @@ int cfg80211_vendor_cmd_reply(struct sk_buff *skb) + void *hdr = ((void **)skb->cb)[1]; + struct nlattr *data = ((void **)skb->cb)[2]; + ++ /* clear CB data for netlink core to own from now on */ ++ memset(skb->cb, 0, sizeof(skb->cb)); ++ + if (WARN_ON(!rdev->cur_cmd_info)) { + kfree_skb(skb); + return -EINVAL; +diff --git a/sound/core/info.c b/sound/core/info.c +index e79baa11b60e..08070e1eefeb 100644 +--- a/sound/core/info.c ++++ b/sound/core/info.c +@@ -679,7 +679,7 @@ int snd_info_card_free(struct snd_card *card) + * snd_info_get_line - read one line from the procfs buffer + * @buffer: the procfs buffer + * @line: the buffer to store +- * @len: the max. buffer size - 1 ++ * @len: the max. buffer size + * + * Reads one line from the buffer and stores the string. + * +@@ -699,7 +699,7 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len) + buffer->stop = 1; + if (c == '\n') + break; +- if (len) { ++ if (len > 1) { + len--; + *line++ = c; + } +diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c +index a2104671f51d..e1ef106c8a6f 100644 +--- a/sound/core/pcm_lib.c ++++ b/sound/core/pcm_lib.c +@@ -1783,14 +1783,16 @@ static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream, + { + struct snd_pcm_hw_params *params = arg; + snd_pcm_format_t format; +- int channels, width; ++ int channels; ++ ssize_t frame_size; + + params->fifo_size = substream->runtime->hw.fifo_size; + if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_FIFO_IN_FRAMES)) { + format = params_format(params); + channels = params_channels(params); +- width = snd_pcm_format_physical_width(format); +- params->fifo_size /= width * channels; ++ frame_size = snd_pcm_format_size(format, channels); ++ if (frame_size > 0) ++ params->fifo_size /= (unsigned)frame_size; + } + return 0; + } +diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c +index bcf91bea3317..ffc19464b978 100644 +--- a/sound/pci/hda/patch_conexant.c ++++ b/sound/pci/hda/patch_conexant.c +@@ -3237,6 +3237,7 @@ enum { + CXT_FIXUP_HEADPHONE_MIC_PIN, + CXT_FIXUP_HEADPHONE_MIC, + CXT_FIXUP_GPIO1, ++ CXT_FIXUP_ASPIRE_DMIC, + CXT_FIXUP_THINKPAD_ACPI, + }; + +@@ -3397,6 +3398,12 @@ static const struct hda_fixup cxt_fixups[] = { + { } + }, + }, ++ [CXT_FIXUP_ASPIRE_DMIC] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = cxt_fixup_stereo_dmic, ++ .chained = true, ++ .chain_id = CXT_FIXUP_GPIO1, ++ }, + [CXT_FIXUP_THINKPAD_ACPI] = { + .type = HDA_FIXUP_FUNC, + .v.func = hda_fixup_thinkpad_acpi, +@@ -3410,7 +3417,7 @@ static const struct snd_pci_quirk cxt5051_fixups[] = { + + static const struct snd_pci_quirk cxt5066_fixups[] = { + SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC), +- SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_GPIO1), ++ SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC), + SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN), + SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410), + SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410), +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index b35dbe25a6e3..5d0058bd6259 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -327,6 +327,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) + case 0x10ec0885: + case 0x10ec0887: + /*case 0x10ec0889:*/ /* this causes an SPDIF problem */ ++ case 0x10ec0900: + alc889_coef_init(codec); + break; + case 0x10ec0888: +@@ -2330,6 +2331,7 @@ static int patch_alc882(struct hda_codec *codec) + switch (codec->vendor_id) { + case 0x10ec0882: + case 0x10ec0885: ++ case 0x10ec0900: + break; + default: + /* ALC883 and variants */ +diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c +index 978df990f27c..15270a2e71cc 100644 +--- a/sound/pci/hda/patch_sigmatel.c ++++ b/sound/pci/hda/patch_sigmatel.c +@@ -559,8 +559,8 @@ static void stac_init_power_map(struct hda_codec *codec) + if (snd_hda_jack_tbl_get(codec, nid)) + continue; + if (def_conf == AC_JACK_PORT_COMPLEX && +- !(spec->vref_mute_led_nid == nid || +- is_jack_detectable(codec, nid))) { ++ spec->vref_mute_led_nid != nid && ++ is_jack_detectable(codec, nid)) { + snd_hda_jack_detect_enable_callback(codec, nid, + STAC_PWR_EVENT, + jack_update_power); +@@ -4212,11 +4212,18 @@ static int stac_parse_auto_config(struct hda_codec *codec) + return err; + } + +- stac_init_power_map(codec); +- + return 0; + } + ++static int stac_build_controls(struct hda_codec *codec) ++{ ++ int err = snd_hda_gen_build_controls(codec); ++ ++ if (err < 0) ++ return err; ++ stac_init_power_map(codec); ++ return 0; ++} + + static int stac_init(struct hda_codec *codec) + { +@@ -4328,7 +4335,7 @@ static int stac_suspend(struct hda_codec *codec) + #endif /* CONFIG_PM */ + + static const struct hda_codec_ops stac_patch_ops = { +- .build_controls = snd_hda_gen_build_controls, ++ .build_controls = stac_build_controls, + .build_pcms = snd_hda_gen_build_pcms, + .init = stac_init, + .free = stac_free, +diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c +index 670afa29e30d..7350ebbae642 100644 +--- a/sound/soc/davinci/davinci-mcasp.c ++++ b/sound/soc/davinci/davinci-mcasp.c +@@ -418,8 +418,17 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, + { + u32 fmt; + u32 tx_rotate = (word_length / 4) & 0x7; +- u32 rx_rotate = (32 - word_length) / 4; + u32 mask = (1ULL << word_length) - 1; ++ /* ++ * For captured data we should not rotate, inversion and masking is ++ * enoguh to get the data to the right position: ++ * Format data from bus after reverse (XRBUF) ++ * S16_LE: |LSB|MSB|xxx|xxx| |xxx|xxx|MSB|LSB| ++ * S24_3LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB| ++ * S24_LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB| ++ * S32_LE: |LSB|DAT|DAT|MSB| |MSB|DAT|DAT|LSB| ++ */ ++ u32 rx_rotate = 0; + + /* + * if s BCLK-to-LRCLK ratio has been configured via the set_clkdiv() diff --git a/patch/kernel/cubox-default/patch-3.14.20-21.patch b/patch/kernel/cubox-default/patch-3.14.20-21.patch new file mode 100644 index 000000000..a8ab18d36 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.20-21.patch @@ -0,0 +1,2520 @@ +diff --git a/Makefile b/Makefile +index beb7e6f0803b..41e6e19fe2e9 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 20 ++SUBLEVEL = 21 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/unicore32/include/asm/mmu_context.h b/arch/unicore32/include/asm/mmu_context.h +index fb5e4c658f7a..ef470a7a3d0f 100644 +--- a/arch/unicore32/include/asm/mmu_context.h ++++ b/arch/unicore32/include/asm/mmu_context.h +@@ -14,6 +14,8 @@ + + #include + #include ++#include ++#include + #include + + #include +@@ -73,7 +75,7 @@ do { \ + else \ + mm->mmap = NULL; \ + rb_erase(&high_vma->vm_rb, &mm->mm_rb); \ +- mm->mmap_cache = NULL; \ ++ vmacache_invalidate(mm); \ + mm->map_count--; \ + remove_vma(high_vma); \ + } \ +diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c +index c706d50a8b06..8c16c2f97026 100644 +--- a/drivers/block/drbd/drbd_nl.c ++++ b/drivers/block/drbd/drbd_nl.c +@@ -525,6 +525,12 @@ void conn_try_outdate_peer_async(struct drbd_tconn *tconn) + struct task_struct *opa; + + kref_get(&tconn->kref); ++ /* We may just have force_sig()'ed this thread ++ * to get it out of some blocking network function. ++ * Clear signals; otherwise kthread_run(), which internally uses ++ * wait_on_completion_killable(), will mistake our pending signal ++ * for a new fatal signal and fail. */ ++ flush_signals(current); + opa = kthread_run(_try_outdate_peer_async, tconn, "drbd_async_h"); + if (IS_ERR(opa)) { + conn_err(tconn, "out of mem, failed to invoke fence-peer helper\n"); +diff --git a/drivers/cpufreq/integrator-cpufreq.c b/drivers/cpufreq/integrator-cpufreq.c +index 0e27844e8c2d..8089dd2cd9d8 100644 +--- a/drivers/cpufreq/integrator-cpufreq.c ++++ b/drivers/cpufreq/integrator-cpufreq.c +@@ -213,9 +213,9 @@ static int __init integrator_cpufreq_probe(struct platform_device *pdev) + return cpufreq_register_driver(&integrator_driver); + } + +-static void __exit integrator_cpufreq_remove(struct platform_device *pdev) ++static int __exit integrator_cpufreq_remove(struct platform_device *pdev) + { +- cpufreq_unregister_driver(&integrator_driver); ++ return cpufreq_unregister_driver(&integrator_driver); + } + + static const struct of_device_id integrator_cpufreq_match[] = { +diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c +index d278be110805..1855cdca39cd 100644 +--- a/drivers/gpu/drm/i915/i915_gem_gtt.c ++++ b/drivers/gpu/drm/i915/i915_gem_gtt.c +@@ -827,6 +827,16 @@ void i915_check_and_clear_faults(struct drm_device *dev) + POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS])); + } + ++static void i915_ggtt_flush(struct drm_i915_private *dev_priv) ++{ ++ if (INTEL_INFO(dev_priv->dev)->gen < 6) { ++ intel_gtt_chipset_flush(); ++ } else { ++ I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); ++ POSTING_READ(GFX_FLSH_CNTL_GEN6); ++ } ++} ++ + void i915_gem_suspend_gtt_mappings(struct drm_device *dev) + { + struct drm_i915_private *dev_priv = dev->dev_private; +@@ -843,6 +853,8 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev) + dev_priv->gtt.base.start / PAGE_SIZE, + dev_priv->gtt.base.total / PAGE_SIZE, + true); ++ ++ i915_ggtt_flush(dev_priv); + } + + void i915_gem_restore_gtt_mappings(struct drm_device *dev) +@@ -863,7 +875,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) + i915_gem_gtt_bind_object(obj, obj->cache_level); + } + +- i915_gem_chipset_flush(dev); ++ i915_ggtt_flush(dev_priv); + } + + int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 18cda77b4f79..4913c0690872 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -64,6 +64,10 @@ + #define cpu_to_group(cpu) cpu_to_node(cpu) + #define ANY_GROUP NUMA_NO_NODE + ++static bool devices_handle_discard_safely = false; ++module_param(devices_handle_discard_safely, bool, 0644); ++MODULE_PARM_DESC(devices_handle_discard_safely, ++ "Set to Y if all devices in each array reliably return zeroes on reads from discarded regions"); + static struct workqueue_struct *raid5_wq; + /* + * Stripe cache +@@ -6117,7 +6121,7 @@ static int run(struct mddev *mddev) + mddev->queue->limits.discard_granularity = stripe; + /* + * unaligned part of discard request will be ignored, so can't +- * guarantee discard_zerors_data ++ * guarantee discard_zeroes_data + */ + mddev->queue->limits.discard_zeroes_data = 0; + +@@ -6142,6 +6146,18 @@ static int run(struct mddev *mddev) + !bdev_get_queue(rdev->bdev)-> + limits.discard_zeroes_data) + discard_supported = false; ++ /* Unfortunately, discard_zeroes_data is not currently ++ * a guarantee - just a hint. So we only allow DISCARD ++ * if the sysadmin has confirmed that only safe devices ++ * are in use by setting a module parameter. ++ */ ++ if (!devices_handle_discard_safely) { ++ if (discard_supported) { ++ pr_info("md/raid456: discard support disabled due to uncertainty.\n"); ++ pr_info("Set raid456.devices_handle_discard_safely=Y to override.\n"); ++ } ++ discard_supported = false; ++ } + } + + if (discard_supported && +diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c +index a127925c9d61..06faea4d60ee 100644 +--- a/drivers/media/v4l2-core/videobuf2-core.c ++++ b/drivers/media/v4l2-core/videobuf2-core.c +@@ -745,6 +745,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) + * to the userspace. + */ + req->count = allocated_buffers; ++ q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type); + + return 0; + } +@@ -793,6 +794,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create + memset(q->plane_sizes, 0, sizeof(q->plane_sizes)); + memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx)); + q->memory = create->memory; ++ q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type); + } + + num_buffers = min(create->count, VIDEO_MAX_FRAME - q->num_buffers); +@@ -1447,6 +1449,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) + * dequeued in dqbuf. + */ + list_add_tail(&vb->queued_entry, &q->queued_list); ++ q->waiting_for_buffers = false; + vb->state = VB2_BUF_STATE_QUEUED; + + /* +@@ -1841,6 +1844,7 @@ static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type) + * and videobuf, effectively returning control over them to userspace. + */ + __vb2_queue_cancel(q); ++ q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type); + + dprintk(3, "Streamoff successful\n"); + return 0; +@@ -2150,9 +2154,16 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) + } + + /* +- * There is nothing to wait for if no buffers have already been queued. ++ * There is nothing to wait for if the queue isn't streaming. + */ +- if (list_empty(&q->queued_list)) ++ if (!vb2_is_streaming(q)) ++ return res | POLLERR; ++ /* ++ * For compatibility with vb1: if QBUF hasn't been called yet, then ++ * return POLLERR as well. This only affects capture queues, output ++ * queues will always initialize waiting_for_buffers to false. ++ */ ++ if (q->waiting_for_buffers) + return res | POLLERR; + + if (list_empty(&q->done_list)) +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index f15d4353f30f..5d12d69e2045 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -399,6 +399,8 @@ struct smb_version_operations { + const struct cifs_fid *, u32 *); + int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *, + int); ++ /* check if we need to issue closedir */ ++ bool (*dir_needs_close)(struct cifsFileInfo *); + }; + + struct smb_version_values { +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index 8175b18df819..d375322b6cec 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -762,7 +762,7 @@ int cifs_closedir(struct inode *inode, struct file *file) + + cifs_dbg(FYI, "Freeing private data in close dir\n"); + spin_lock(&cifs_file_list_lock); +- if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) { ++ if (server->ops->dir_needs_close(cfile)) { + cfile->invalidHandle = true; + spin_unlock(&cifs_file_list_lock); + if (server->ops->close_dir) +diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c +index 2bbf11b09214..b334a89d6a66 100644 +--- a/fs/cifs/readdir.c ++++ b/fs/cifs/readdir.c +@@ -593,7 +593,7 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos, + /* close and restart search */ + cifs_dbg(FYI, "search backing up - close and restart search\n"); + spin_lock(&cifs_file_list_lock); +- if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) { ++ if (server->ops->dir_needs_close(cfile)) { + cfile->invalidHandle = true; + spin_unlock(&cifs_file_list_lock); + if (server->ops->close_dir) +diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c +index d1fdfa848703..e9ad8d37bb00 100644 +--- a/fs/cifs/smb1ops.c ++++ b/fs/cifs/smb1ops.c +@@ -586,7 +586,7 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, + tmprc = CIFS_open(xid, &oparms, &oplock, NULL); + if (tmprc == -EOPNOTSUPP) + *symlink = true; +- else ++ else if (tmprc == 0) + CIFSSMBClose(xid, tcon, fid.netfid); + } + +@@ -1009,6 +1009,12 @@ cifs_is_read_op(__u32 oplock) + return oplock == OPLOCK_READ; + } + ++static bool ++cifs_dir_needs_close(struct cifsFileInfo *cfile) ++{ ++ return !cfile->srch_inf.endOfSearch && !cfile->invalidHandle; ++} ++ + struct smb_version_operations smb1_operations = { + .send_cancel = send_nt_cancel, + .compare_fids = cifs_compare_fids, +@@ -1078,6 +1084,7 @@ struct smb_version_operations smb1_operations = { + .query_mf_symlink = cifs_query_mf_symlink, + .create_mf_symlink = cifs_create_mf_symlink, + .is_read_op = cifs_is_read_op, ++ .dir_needs_close = cifs_dir_needs_close, + #ifdef CONFIG_CIFS_XATTR + .query_all_EAs = CIFSSMBQAllEAs, + .set_EA = CIFSSMBSetEA, +diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c +index e31a9dfdcd39..a491814cb2c0 100644 +--- a/fs/cifs/smb2maperror.c ++++ b/fs/cifs/smb2maperror.c +@@ -214,7 +214,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = { + {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"}, + {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"}, + {STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"}, +- {STATUS_NO_MORE_FILES, -EIO, "STATUS_NO_MORE_FILES"}, ++ {STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"}, + {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"}, + {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"}, + {STATUS_NO_INHERITANCE, -EIO, "STATUS_NO_INHERITANCE"}, +@@ -256,6 +256,8 @@ static const struct status_to_posix_error smb2_error_map_table[] = { + {STATUS_DLL_MIGHT_BE_INCOMPATIBLE, -EIO, + "STATUS_DLL_MIGHT_BE_INCOMPATIBLE"}, + {STATUS_STOPPED_ON_SYMLINK, -EOPNOTSUPP, "STATUS_STOPPED_ON_SYMLINK"}, ++ {STATUS_IO_REPARSE_TAG_NOT_HANDLED, -EOPNOTSUPP, ++ "STATUS_REPARSE_NOT_HANDLED"}, + {STATUS_DEVICE_REQUIRES_CLEANING, -EIO, + "STATUS_DEVICE_REQUIRES_CLEANING"}, + {STATUS_DEVICE_DOOR_OPEN, -EIO, "STATUS_DEVICE_DOOR_OPEN"}, +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index f8977b2d9187..34a17d425be6 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -1102,6 +1102,12 @@ smb3_parse_lease_buf(void *buf, unsigned int *epoch) + return le32_to_cpu(lc->lcontext.LeaseState); + } + ++static bool ++smb2_dir_needs_close(struct cifsFileInfo *cfile) ++{ ++ return !cfile->invalidHandle; ++} ++ + struct smb_version_operations smb20_operations = { + .compare_fids = smb2_compare_fids, + .setup_request = smb2_setup_request, +@@ -1175,6 +1181,7 @@ struct smb_version_operations smb20_operations = { + .create_lease_buf = smb2_create_lease_buf, + .parse_lease_buf = smb2_parse_lease_buf, + .clone_range = smb2_clone_range, ++ .dir_needs_close = smb2_dir_needs_close, + }; + + struct smb_version_operations smb21_operations = { +@@ -1250,6 +1257,7 @@ struct smb_version_operations smb21_operations = { + .create_lease_buf = smb2_create_lease_buf, + .parse_lease_buf = smb2_parse_lease_buf, + .clone_range = smb2_clone_range, ++ .dir_needs_close = smb2_dir_needs_close, + }; + + struct smb_version_operations smb30_operations = { +@@ -1328,6 +1336,7 @@ struct smb_version_operations smb30_operations = { + .parse_lease_buf = smb3_parse_lease_buf, + .clone_range = smb2_clone_range, + .validate_negotiate = smb3_validate_negotiate, ++ .dir_needs_close = smb2_dir_needs_close, + }; + + struct smb_version_values smb20_values = { +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 9aab8fe0e508..348792911e1f 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -2136,6 +2136,10 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + rsp = (struct smb2_query_directory_rsp *)iov[0].iov_base; + + if (rc) { ++ if (rc == -ENODATA && rsp->hdr.Status == STATUS_NO_MORE_FILES) { ++ srch_inf->endOfSearch = true; ++ rc = 0; ++ } + cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE); + goto qdir_exit; + } +@@ -2173,11 +2177,6 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + else + cifs_dbg(VFS, "illegal search buffer type\n"); + +- if (rsp->hdr.Status == STATUS_NO_MORE_FILES) +- srch_inf->endOfSearch = 1; +- else +- srch_inf->endOfSearch = 0; +- + return rc; + + qdir_exit: +diff --git a/fs/exec.c b/fs/exec.c +index 31e46b1b358b..ea4449d0536a 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -820,7 +821,7 @@ EXPORT_SYMBOL(read_code); + static int exec_mmap(struct mm_struct *mm) + { + struct task_struct *tsk; +- struct mm_struct * old_mm, *active_mm; ++ struct mm_struct *old_mm, *active_mm; + + /* Notify parent that we're no longer interested in the old VM */ + tsk = current; +@@ -846,6 +847,8 @@ static int exec_mmap(struct mm_struct *mm) + tsk->mm = mm; + tsk->active_mm = mm; + activate_mm(active_mm, mm); ++ tsk->mm->vmacache_seqnum = 0; ++ vmacache_flush(tsk); + task_unlock(tsk); + if (old_mm) { + up_read(&old_mm->mmap_sem); +diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c +index d19b30ababf1..a4a8ed56e438 100644 +--- a/fs/hugetlbfs/inode.c ++++ b/fs/hugetlbfs/inode.c +@@ -1017,6 +1017,11 @@ static int __init init_hugetlbfs_fs(void) + int error; + int i; + ++ if (!hugepages_supported()) { ++ pr_info("hugetlbfs: disabling because there are no supported hugepage sizes\n"); ++ return -ENOTSUPP; ++ } ++ + error = bdi_init(&hugetlbfs_backing_dev_info); + if (error) + return error; +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index 8f788193e3d4..c4b2646b6d7c 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -1,4 +1,5 @@ + #include ++#include + #include + #include + #include +@@ -152,7 +153,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) + + /* + * We remember last_addr rather than next_addr to hit with +- * mmap_cache most of the time. We have zero last_addr at ++ * vmacache most of the time. We have zero last_addr at + * the beginning and also after lseek. We will have -1 last_addr + * after the end of the vmas. + */ +diff --git a/fs/udf/inode.c b/fs/udf/inode.c +index 982ce05c87ed..287cd5f23421 100644 +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -1271,13 +1271,22 @@ update_time: + return 0; + } + ++/* ++ * Maximum length of linked list formed by ICB hierarchy. The chosen number is ++ * arbitrary - just that we hopefully don't limit any real use of rewritten ++ * inode on write-once media but avoid looping for too long on corrupted media. ++ */ ++#define UDF_MAX_ICB_NESTING 1024 ++ + static void __udf_read_inode(struct inode *inode) + { + struct buffer_head *bh = NULL; + struct fileEntry *fe; + uint16_t ident; + struct udf_inode_info *iinfo = UDF_I(inode); ++ unsigned int indirections = 0; + ++reread: + /* + * Set defaults, but the inode is still incomplete! + * Note: get_new_inode() sets the following on a new inode: +@@ -1314,28 +1323,26 @@ static void __udf_read_inode(struct inode *inode) + ibh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 1, + &ident); + if (ident == TAG_IDENT_IE && ibh) { +- struct buffer_head *nbh = NULL; + struct kernel_lb_addr loc; + struct indirectEntry *ie; + + ie = (struct indirectEntry *)ibh->b_data; + loc = lelb_to_cpu(ie->indirectICB.extLocation); + +- if (ie->indirectICB.extLength && +- (nbh = udf_read_ptagged(inode->i_sb, &loc, 0, +- &ident))) { +- if (ident == TAG_IDENT_FE || +- ident == TAG_IDENT_EFE) { +- memcpy(&iinfo->i_location, +- &loc, +- sizeof(struct kernel_lb_addr)); +- brelse(bh); +- brelse(ibh); +- brelse(nbh); +- __udf_read_inode(inode); ++ if (ie->indirectICB.extLength) { ++ brelse(bh); ++ brelse(ibh); ++ memcpy(&iinfo->i_location, &loc, ++ sizeof(struct kernel_lb_addr)); ++ if (++indirections > UDF_MAX_ICB_NESTING) { ++ udf_err(inode->i_sb, ++ "too many ICBs in ICB hierarchy" ++ " (max %d supported)\n", ++ UDF_MAX_ICB_NESTING); ++ make_bad_inode(inode); + return; + } +- brelse(nbh); ++ goto reread; + } + } + brelse(ibh); +diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h +index 3fe661fe96d1..b19d3dc2e651 100644 +--- a/include/linux/cpuset.h ++++ b/include/linux/cpuset.h +@@ -87,25 +87,26 @@ extern void rebuild_sched_domains(void); + extern void cpuset_print_task_mems_allowed(struct task_struct *p); + + /* +- * get_mems_allowed is required when making decisions involving mems_allowed +- * such as during page allocation. mems_allowed can be updated in parallel +- * and depending on the new value an operation can fail potentially causing +- * process failure. A retry loop with get_mems_allowed and put_mems_allowed +- * prevents these artificial failures. ++ * read_mems_allowed_begin is required when making decisions involving ++ * mems_allowed such as during page allocation. mems_allowed can be updated in ++ * parallel and depending on the new value an operation can fail potentially ++ * causing process failure. A retry loop with read_mems_allowed_begin and ++ * read_mems_allowed_retry prevents these artificial failures. + */ +-static inline unsigned int get_mems_allowed(void) ++static inline unsigned int read_mems_allowed_begin(void) + { + return read_seqcount_begin(¤t->mems_allowed_seq); + } + + /* +- * If this returns false, the operation that took place after get_mems_allowed +- * may have failed. It is up to the caller to retry the operation if ++ * If this returns true, the operation that took place after ++ * read_mems_allowed_begin may have failed artificially due to a concurrent ++ * update of mems_allowed. It is up to the caller to retry the operation if + * appropriate. + */ +-static inline bool put_mems_allowed(unsigned int seq) ++static inline bool read_mems_allowed_retry(unsigned int seq) + { +- return !read_seqcount_retry(¤t->mems_allowed_seq, seq); ++ return read_seqcount_retry(¤t->mems_allowed_seq, seq); + } + + static inline void set_mems_allowed(nodemask_t nodemask) +@@ -225,14 +226,14 @@ static inline void set_mems_allowed(nodemask_t nodemask) + { + } + +-static inline unsigned int get_mems_allowed(void) ++static inline unsigned int read_mems_allowed_begin(void) + { + return 0; + } + +-static inline bool put_mems_allowed(unsigned int seq) ++static inline bool read_mems_allowed_retry(unsigned int seq) + { +- return true; ++ return false; + } + + #endif /* !CONFIG_CPUSETS */ +diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h +index bd1e9bcec547..42b05c4c53e5 100644 +--- a/include/linux/hugetlb.h ++++ b/include/linux/hugetlb.h +@@ -400,6 +400,16 @@ static inline spinlock_t *huge_pte_lockptr(struct hstate *h, + return &mm->page_table_lock; + } + ++static inline bool hugepages_supported(void) ++{ ++ /* ++ * Some platform decide whether they support huge pages at boot ++ * time. On these, such as powerpc, HPAGE_SHIFT is set to 0 when ++ * there is no such support ++ */ ++ return HPAGE_SHIFT != 0; ++} ++ + #else /* CONFIG_HUGETLB_PAGE */ + struct hstate {}; + #define alloc_huge_page_node(h, nid) NULL +diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h +index 1f44466c1e9d..c367cbdf73ab 100644 +--- a/include/linux/jiffies.h ++++ b/include/linux/jiffies.h +@@ -258,23 +258,11 @@ extern unsigned long preset_lpj; + #define SEC_JIFFIE_SC (32 - SHIFT_HZ) + #endif + #define NSEC_JIFFIE_SC (SEC_JIFFIE_SC + 29) +-#define USEC_JIFFIE_SC (SEC_JIFFIE_SC + 19) + #define SEC_CONVERSION ((unsigned long)((((u64)NSEC_PER_SEC << SEC_JIFFIE_SC) +\ + TICK_NSEC -1) / (u64)TICK_NSEC)) + + #define NSEC_CONVERSION ((unsigned long)((((u64)1 << NSEC_JIFFIE_SC) +\ + TICK_NSEC -1) / (u64)TICK_NSEC)) +-#define USEC_CONVERSION \ +- ((unsigned long)((((u64)NSEC_PER_USEC << USEC_JIFFIE_SC) +\ +- TICK_NSEC -1) / (u64)TICK_NSEC)) +-/* +- * USEC_ROUND is used in the timeval to jiffie conversion. See there +- * for more details. It is the scaled resolution rounding value. Note +- * that it is a 64-bit value. Since, when it is applied, we are already +- * in jiffies (albit scaled), it is nothing but the bits we will shift +- * off. +- */ +-#define USEC_ROUND (u64)(((u64)1 << USEC_JIFFIE_SC) - 1) + /* + * The maximum jiffie value is (MAX_INT >> 1). Here we translate that + * into seconds. The 64-bit case will overflow if we are not careful, +diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h +index 290901a8c1de..2b58d192ea24 100644 +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -342,9 +342,9 @@ struct mm_rss_stat { + + struct kioctx_table; + struct mm_struct { +- struct vm_area_struct * mmap; /* list of VMAs */ ++ struct vm_area_struct *mmap; /* list of VMAs */ + struct rb_root mm_rb; +- struct vm_area_struct * mmap_cache; /* last find_vma result */ ++ u32 vmacache_seqnum; /* per-thread vmacache */ + #ifdef CONFIG_MMU + unsigned long (*get_unmapped_area) (struct file *filp, + unsigned long addr, unsigned long len, +diff --git a/include/linux/plist.h b/include/linux/plist.h +index aa0fb390bd29..8b6c970cff6c 100644 +--- a/include/linux/plist.h ++++ b/include/linux/plist.h +@@ -98,6 +98,13 @@ struct plist_node { + } + + /** ++ * PLIST_HEAD - declare and init plist_head ++ * @head: name for struct plist_head variable ++ */ ++#define PLIST_HEAD(head) \ ++ struct plist_head head = PLIST_HEAD_INIT(head) ++ ++/** + * PLIST_NODE_INIT - static struct plist_node initializer + * @node: struct plist_node variable name + * @__prio: initial node priority +@@ -134,6 +141,8 @@ static inline void plist_node_init(struct plist_node *node, int prio) + extern void plist_add(struct plist_node *node, struct plist_head *head); + extern void plist_del(struct plist_node *node, struct plist_head *head); + ++extern void plist_requeue(struct plist_node *node, struct plist_head *head); ++ + /** + * plist_for_each - iterate over the plist + * @pos: the type * to use as a loop counter +@@ -143,6 +152,16 @@ extern void plist_del(struct plist_node *node, struct plist_head *head); + list_for_each_entry(pos, &(head)->node_list, node_list) + + /** ++ * plist_for_each_continue - continue iteration over the plist ++ * @pos: the type * to use as a loop cursor ++ * @head: the head for your list ++ * ++ * Continue to iterate over plist, continuing after the current position. ++ */ ++#define plist_for_each_continue(pos, head) \ ++ list_for_each_entry_continue(pos, &(head)->node_list, node_list) ++ ++/** + * plist_for_each_safe - iterate safely over a plist of given type + * @pos: the type * to use as a loop counter + * @n: another type * to use as temporary storage +@@ -163,6 +182,18 @@ extern void plist_del(struct plist_node *node, struct plist_head *head); + list_for_each_entry(pos, &(head)->node_list, mem.node_list) + + /** ++ * plist_for_each_entry_continue - continue iteration over list of given type ++ * @pos: the type * to use as a loop cursor ++ * @head: the head for your list ++ * @m: the name of the list_struct within the struct ++ * ++ * Continue to iterate over list of given type, continuing after ++ * the current position. ++ */ ++#define plist_for_each_entry_continue(pos, head, m) \ ++ list_for_each_entry_continue(pos, &(head)->node_list, m.node_list) ++ ++/** + * plist_for_each_entry_safe - iterate safely over list of given type + * @pos: the type * to use as a loop counter + * @n: another type * to use as temporary storage +@@ -229,6 +260,20 @@ static inline int plist_node_empty(const struct plist_node *node) + #endif + + /** ++ * plist_next - get the next entry in list ++ * @pos: the type * to cursor ++ */ ++#define plist_next(pos) \ ++ list_next_entry(pos, node_list) ++ ++/** ++ * plist_prev - get the prev entry in list ++ * @pos: the type * to cursor ++ */ ++#define plist_prev(pos) \ ++ list_prev_entry(pos, node_list) ++ ++/** + * plist_first - return the first node (and thus, highest priority) + * @head: the &struct plist_head pointer + * +diff --git a/include/linux/sched.h b/include/linux/sched.h +index ccd0c6f24f2c..d7ca410ace93 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -59,6 +59,10 @@ struct sched_param { + + #define SCHED_ATTR_SIZE_VER0 48 /* sizeof first published struct */ + ++#define VMACACHE_BITS 2 ++#define VMACACHE_SIZE (1U << VMACACHE_BITS) ++#define VMACACHE_MASK (VMACACHE_SIZE - 1) ++ + /* + * Extended scheduling parameters data structure. + * +@@ -1228,6 +1232,9 @@ struct task_struct { + #ifdef CONFIG_COMPAT_BRK + unsigned brk_randomized:1; + #endif ++ /* per-thread vma caching */ ++ u32 vmacache_seqnum; ++ struct vm_area_struct *vmacache[VMACACHE_SIZE]; + #if defined(SPLIT_RSS_COUNTING) + struct task_rss_stat rss_stat; + #endif +diff --git a/include/linux/swap.h b/include/linux/swap.h +index 46ba0c6c219f..789324976801 100644 +--- a/include/linux/swap.h ++++ b/include/linux/swap.h +@@ -214,8 +214,9 @@ struct percpu_cluster { + struct swap_info_struct { + unsigned long flags; /* SWP_USED etc: see above */ + signed short prio; /* swap priority of this type */ ++ struct plist_node list; /* entry in swap_active_head */ ++ struct plist_node avail_list; /* entry in swap_avail_head */ + signed char type; /* strange name for an index */ +- signed char next; /* next type on the swap list */ + unsigned int max; /* extent of the swap_map */ + unsigned char *swap_map; /* vmalloc'ed array of usage counts */ + struct swap_cluster_info *cluster_info; /* cluster info. Only for SSD */ +@@ -255,11 +256,6 @@ struct swap_info_struct { + struct swap_cluster_info discard_cluster_tail; /* list tail of discard clusters */ + }; + +-struct swap_list_t { +- int head; /* head of priority-ordered swapfile list */ +- int next; /* swapfile to be used next */ +-}; +- + /* linux/mm/page_alloc.c */ + extern unsigned long totalram_pages; + extern unsigned long totalreserve_pages; +diff --git a/include/linux/swapfile.h b/include/linux/swapfile.h +index e282624e8c10..388293a91e8c 100644 +--- a/include/linux/swapfile.h ++++ b/include/linux/swapfile.h +@@ -6,7 +6,7 @@ + * want to expose them to the dozens of source files that include swap.h + */ + extern spinlock_t swap_lock; +-extern struct swap_list_t swap_list; ++extern struct plist_head swap_active_head; + extern struct swap_info_struct *swap_info[]; + extern int try_to_unuse(unsigned int, bool, unsigned long); + +diff --git a/include/linux/vmacache.h b/include/linux/vmacache.h +new file mode 100644 +index 000000000000..c3fa0fd43949 +--- /dev/null ++++ b/include/linux/vmacache.h +@@ -0,0 +1,38 @@ ++#ifndef __LINUX_VMACACHE_H ++#define __LINUX_VMACACHE_H ++ ++#include ++#include ++ ++/* ++ * Hash based on the page number. Provides a good hit rate for ++ * workloads with good locality and those with random accesses as well. ++ */ ++#define VMACACHE_HASH(addr) ((addr >> PAGE_SHIFT) & VMACACHE_MASK) ++ ++static inline void vmacache_flush(struct task_struct *tsk) ++{ ++ memset(tsk->vmacache, 0, sizeof(tsk->vmacache)); ++} ++ ++extern void vmacache_flush_all(struct mm_struct *mm); ++extern void vmacache_update(unsigned long addr, struct vm_area_struct *newvma); ++extern struct vm_area_struct *vmacache_find(struct mm_struct *mm, ++ unsigned long addr); ++ ++#ifndef CONFIG_MMU ++extern struct vm_area_struct *vmacache_find_exact(struct mm_struct *mm, ++ unsigned long start, ++ unsigned long end); ++#endif ++ ++static inline void vmacache_invalidate(struct mm_struct *mm) ++{ ++ mm->vmacache_seqnum++; ++ ++ /* deal with overflows */ ++ if (unlikely(mm->vmacache_seqnum == 0)) ++ vmacache_flush_all(mm); ++} ++ ++#endif /* __LINUX_VMACACHE_H */ +diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h +index bef53ce555d2..b10682cb138c 100644 +--- a/include/media/videobuf2-core.h ++++ b/include/media/videobuf2-core.h +@@ -329,6 +329,9 @@ struct v4l2_fh; + * @retry_start_streaming: start_streaming() was called, but there were not enough + * buffers queued. If set, then retry calling start_streaming when + * queuing a new buffer. ++ * @waiting_for_buffers: used in poll() to check if vb2 is still waiting for ++ * buffers. Only set for capture queues if qbuf has not yet been ++ * called since poll() needs to return POLLERR in that situation. + * @fileio: file io emulator internal data, used only if emulator is active + */ + struct vb2_queue { +@@ -362,6 +365,7 @@ struct vb2_queue { + + unsigned int streaming:1; + unsigned int retry_start_streaming:1; ++ unsigned int waiting_for_buffers:1; + + struct vb2_fileio_data *fileio; + }; +diff --git a/init/Kconfig b/init/Kconfig +index 93c5ef0c5210..8b9521a2d2c1 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1389,6 +1389,7 @@ config FUTEX + + config HAVE_FUTEX_CMPXCHG + bool ++ depends on FUTEX + help + Architectures should select this if futex_atomic_cmpxchg_inatomic() + is implemented and always working. This removes a couple of runtime +diff --git a/kernel/cpuset.c b/kernel/cpuset.c +index 6b27e5c0cd86..15b3ea693225 100644 +--- a/kernel/cpuset.c ++++ b/kernel/cpuset.c +@@ -1022,7 +1022,7 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk, + task_lock(tsk); + /* + * Determine if a loop is necessary if another thread is doing +- * get_mems_allowed(). If at least one node remains unchanged and ++ * read_mems_allowed_begin(). If at least one node remains unchanged and + * tsk does not have a mempolicy, then an empty nodemask will not be + * possible when mems_allowed is larger than a word. + */ +diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c +index 334b3980ffc1..8865caec45fb 100644 +--- a/kernel/debug/debug_core.c ++++ b/kernel/debug/debug_core.c +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -224,10 +225,17 @@ static void kgdb_flush_swbreak_addr(unsigned long addr) + if (!CACHE_FLUSH_IS_SAFE) + return; + +- if (current->mm && current->mm->mmap_cache) { +- flush_cache_range(current->mm->mmap_cache, +- addr, addr + BREAK_INSTR_SIZE); ++ if (current->mm) { ++ int i; ++ ++ for (i = 0; i < VMACACHE_SIZE; i++) { ++ if (!current->vmacache[i]) ++ continue; ++ flush_cache_range(current->vmacache[i], ++ addr, addr + BREAK_INSTR_SIZE); ++ } + } ++ + /* Force flush instruction cache if it was outside the mm */ + flush_icache_range(addr, addr + BREAK_INSTR_SIZE); + } +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 3a140ca37777..4ced342f1ba9 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -7836,8 +7836,10 @@ int perf_event_init_task(struct task_struct *child) + + for_each_task_context_nr(ctxn) { + ret = perf_event_init_context(child, ctxn); +- if (ret) ++ if (ret) { ++ perf_event_free_task(child); + return ret; ++ } + } + + return 0; +diff --git a/kernel/fork.c b/kernel/fork.c +index c44bff8097f5..e2c685396295 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -28,6 +28,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -363,7 +365,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) + + mm->locked_vm = 0; + mm->mmap = NULL; +- mm->mmap_cache = NULL; ++ mm->vmacache_seqnum = 0; + mm->map_count = 0; + cpumask_clear(mm_cpumask(mm)); + mm->mm_rb = RB_ROOT; +@@ -876,6 +878,9 @@ static int copy_mm(unsigned long clone_flags, struct task_struct *tsk) + if (!oldmm) + return 0; + ++ /* initialize the new vmacache entries */ ++ vmacache_flush(tsk); ++ + if (clone_flags & CLONE_VM) { + atomic_inc(&oldmm->mm_users); + mm = oldmm; +@@ -1323,7 +1328,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, + goto bad_fork_cleanup_policy; + retval = audit_alloc(p); + if (retval) +- goto bad_fork_cleanup_policy; ++ goto bad_fork_cleanup_perf; + /* copy all the process information */ + retval = copy_semundo(clone_flags, p); + if (retval) +@@ -1522,8 +1527,9 @@ bad_fork_cleanup_semundo: + exit_sem(p); + bad_fork_cleanup_audit: + audit_free(p); +-bad_fork_cleanup_policy: ++bad_fork_cleanup_perf: + perf_event_free_task(p); ++bad_fork_cleanup_policy: + #ifdef CONFIG_NUMA + mpol_put(p->mempolicy); + bad_fork_cleanup_cgroup: +diff --git a/kernel/time.c b/kernel/time.c +index 7c7964c33ae7..3c49ab45f822 100644 +--- a/kernel/time.c ++++ b/kernel/time.c +@@ -496,17 +496,20 @@ EXPORT_SYMBOL(usecs_to_jiffies); + * that a remainder subtract here would not do the right thing as the + * resolution values don't fall on second boundries. I.e. the line: + * nsec -= nsec % TICK_NSEC; is NOT a correct resolution rounding. ++ * Note that due to the small error in the multiplier here, this ++ * rounding is incorrect for sufficiently large values of tv_nsec, but ++ * well formed timespecs should have tv_nsec < NSEC_PER_SEC, so we're ++ * OK. + * + * Rather, we just shift the bits off the right. + * + * The >> (NSEC_JIFFIE_SC - SEC_JIFFIE_SC) converts the scaled nsec + * value to a scaled second value. + */ +-unsigned long +-timespec_to_jiffies(const struct timespec *value) ++static unsigned long ++__timespec_to_jiffies(unsigned long sec, long nsec) + { +- unsigned long sec = value->tv_sec; +- long nsec = value->tv_nsec + TICK_NSEC - 1; ++ nsec = nsec + TICK_NSEC - 1; + + if (sec >= MAX_SEC_IN_JIFFIES){ + sec = MAX_SEC_IN_JIFFIES; +@@ -517,6 +520,13 @@ timespec_to_jiffies(const struct timespec *value) + (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC; + + } ++ ++unsigned long ++timespec_to_jiffies(const struct timespec *value) ++{ ++ return __timespec_to_jiffies(value->tv_sec, value->tv_nsec); ++} ++ + EXPORT_SYMBOL(timespec_to_jiffies); + + void +@@ -533,31 +543,27 @@ jiffies_to_timespec(const unsigned long jiffies, struct timespec *value) + } + EXPORT_SYMBOL(jiffies_to_timespec); + +-/* Same for "timeval" ++/* ++ * We could use a similar algorithm to timespec_to_jiffies (with a ++ * different multiplier for usec instead of nsec). But this has a ++ * problem with rounding: we can't exactly add TICK_NSEC - 1 to the ++ * usec value, since it's not necessarily integral. + * +- * Well, almost. The problem here is that the real system resolution is +- * in nanoseconds and the value being converted is in micro seconds. +- * Also for some machines (those that use HZ = 1024, in-particular), +- * there is a LARGE error in the tick size in microseconds. +- +- * The solution we use is to do the rounding AFTER we convert the +- * microsecond part. Thus the USEC_ROUND, the bits to be shifted off. +- * Instruction wise, this should cost only an additional add with carry +- * instruction above the way it was done above. ++ * We could instead round in the intermediate scaled representation ++ * (i.e. in units of 1/2^(large scale) jiffies) but that's also ++ * perilous: the scaling introduces a small positive error, which ++ * combined with a division-rounding-upward (i.e. adding 2^(scale) - 1 ++ * units to the intermediate before shifting) leads to accidental ++ * overflow and overestimates. ++ * ++ * At the cost of one additional multiplication by a constant, just ++ * use the timespec implementation. + */ + unsigned long + timeval_to_jiffies(const struct timeval *value) + { +- unsigned long sec = value->tv_sec; +- long usec = value->tv_usec; +- +- if (sec >= MAX_SEC_IN_JIFFIES){ +- sec = MAX_SEC_IN_JIFFIES; +- usec = 0; +- } +- return (((u64)sec * SEC_CONVERSION) + +- (((u64)usec * USEC_CONVERSION + USEC_ROUND) >> +- (USEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC; ++ return __timespec_to_jiffies(value->tv_sec, ++ value->tv_usec * NSEC_PER_USEC); + } + EXPORT_SYMBOL(timeval_to_jiffies); + +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index 773aba836e81..774a0807fe81 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -3372,7 +3372,7 @@ static void rb_iter_reset(struct ring_buffer_iter *iter) + iter->head = cpu_buffer->reader_page->read; + + iter->cache_reader_page = iter->head_page; +- iter->cache_read = iter->head; ++ iter->cache_read = cpu_buffer->read; + + if (iter->head) + iter->read_stamp = cpu_buffer->read_stamp; +diff --git a/lib/plist.c b/lib/plist.c +index 1ebc95f7a46f..0f2084d30798 100644 +--- a/lib/plist.c ++++ b/lib/plist.c +@@ -134,6 +134,46 @@ void plist_del(struct plist_node *node, struct plist_head *head) + plist_check_head(head); + } + ++/** ++ * plist_requeue - Requeue @node at end of same-prio entries. ++ * ++ * This is essentially an optimized plist_del() followed by ++ * plist_add(). It moves an entry already in the plist to ++ * after any other same-priority entries. ++ * ++ * @node: &struct plist_node pointer - entry to be moved ++ * @head: &struct plist_head pointer - list head ++ */ ++void plist_requeue(struct plist_node *node, struct plist_head *head) ++{ ++ struct plist_node *iter; ++ struct list_head *node_next = &head->node_list; ++ ++ plist_check_head(head); ++ BUG_ON(plist_head_empty(head)); ++ BUG_ON(plist_node_empty(node)); ++ ++ if (node == plist_last(head)) ++ return; ++ ++ iter = plist_next(node); ++ ++ if (node->prio != iter->prio) ++ return; ++ ++ plist_del(node, head); ++ ++ plist_for_each_continue(iter, head) { ++ if (node->prio != iter->prio) { ++ node_next = &iter->node_list; ++ break; ++ } ++ } ++ list_add_tail(&node->node_list, node_next); ++ ++ plist_check_head(head); ++} ++ + #ifdef CONFIG_DEBUG_PI_LIST + #include + #include +@@ -170,6 +210,14 @@ static void __init plist_test_check(int nr_expect) + BUG_ON(prio_pos->prio_list.next != &first->prio_list); + } + ++static void __init plist_test_requeue(struct plist_node *node) ++{ ++ plist_requeue(node, &test_head); ++ ++ if (node != plist_last(&test_head)) ++ BUG_ON(node->prio == plist_next(node)->prio); ++} ++ + static int __init plist_test(void) + { + int nr_expect = 0, i, loop; +@@ -193,6 +241,10 @@ static int __init plist_test(void) + nr_expect--; + } + plist_test_check(nr_expect); ++ if (!plist_node_empty(test_node + i)) { ++ plist_test_requeue(test_node + i); ++ plist_test_check(nr_expect); ++ } + } + + for (i = 0; i < ARRAY_SIZE(test_node); i++) { +diff --git a/mm/Makefile b/mm/Makefile +index 310c90a09264..c561f1f6bca0 100644 +--- a/mm/Makefile ++++ b/mm/Makefile +@@ -16,7 +16,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \ + readahead.o swap.o truncate.o vmscan.o shmem.o \ + util.o mmzone.o vmstat.o backing-dev.o \ + mm_init.o mmu_context.o percpu.o slab_common.o \ +- compaction.o balloon_compaction.o \ ++ compaction.o balloon_compaction.o vmacache.o \ + interval_tree.o list_lru.o $(mmu-y) + + obj-y += init-mm.o +diff --git a/mm/compaction.c b/mm/compaction.c +index 5f702ef0a65f..5e38e5706f62 100644 +--- a/mm/compaction.c ++++ b/mm/compaction.c +@@ -217,21 +217,12 @@ static inline bool compact_trylock_irqsave(spinlock_t *lock, + /* Returns true if the page is within a block suitable for migration to */ + static bool suitable_migration_target(struct page *page) + { +- int migratetype = get_pageblock_migratetype(page); +- +- /* Don't interfere with memory hot-remove or the min_free_kbytes blocks */ +- if (migratetype == MIGRATE_RESERVE) +- return false; +- +- if (is_migrate_isolate(migratetype)) +- return false; +- +- /* If the page is a large free page, then allow migration */ ++ /* If the page is a large free page, then disallow migration */ + if (PageBuddy(page) && page_order(page) >= pageblock_order) +- return true; ++ return false; + + /* If the block is MIGRATE_MOVABLE or MIGRATE_CMA, allow migration */ +- if (migrate_async_suitable(migratetype)) ++ if (migrate_async_suitable(get_pageblock_migratetype(page))) + return true; + + /* Otherwise skip the block */ +@@ -253,6 +244,7 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, + struct page *cursor, *valid_page = NULL; + unsigned long flags; + bool locked = false; ++ bool checked_pageblock = false; + + cursor = pfn_to_page(blockpfn); + +@@ -284,8 +276,16 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, + break; + + /* Recheck this is a suitable migration target under lock */ +- if (!strict && !suitable_migration_target(page)) +- break; ++ if (!strict && !checked_pageblock) { ++ /* ++ * We need to check suitability of pageblock only once ++ * and this isolate_freepages_block() is called with ++ * pageblock range, so just check once is sufficient. ++ */ ++ checked_pageblock = true; ++ if (!suitable_migration_target(page)) ++ break; ++ } + + /* Recheck this is a buddy page under lock */ + if (!PageBuddy(page)) +@@ -460,12 +460,13 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + unsigned long last_pageblock_nr = 0, pageblock_nr; + unsigned long nr_scanned = 0, nr_isolated = 0; + struct list_head *migratelist = &cc->migratepages; +- isolate_mode_t mode = 0; + struct lruvec *lruvec; + unsigned long flags; + bool locked = false; + struct page *page = NULL, *valid_page = NULL; + bool skipped_async_unsuitable = false; ++ const isolate_mode_t mode = (!cc->sync ? ISOLATE_ASYNC_MIGRATE : 0) | ++ (unevictable ? ISOLATE_UNEVICTABLE : 0); + + /* + * Ensure that there are not too many pages isolated from the LRU +@@ -487,7 +488,7 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + cond_resched(); + for (; low_pfn < end_pfn; low_pfn++) { + /* give a chance to irqs before checking need_resched() */ +- if (locked && !((low_pfn+1) % SWAP_CLUSTER_MAX)) { ++ if (locked && !(low_pfn % SWAP_CLUSTER_MAX)) { + if (should_release_lock(&zone->lru_lock)) { + spin_unlock_irqrestore(&zone->lru_lock, flags); + locked = false; +@@ -526,8 +527,25 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + + /* If isolation recently failed, do not retry */ + pageblock_nr = low_pfn >> pageblock_order; +- if (!isolation_suitable(cc, page)) +- goto next_pageblock; ++ if (last_pageblock_nr != pageblock_nr) { ++ int mt; ++ ++ last_pageblock_nr = pageblock_nr; ++ if (!isolation_suitable(cc, page)) ++ goto next_pageblock; ++ ++ /* ++ * For async migration, also only scan in MOVABLE ++ * blocks. Async migration is optimistic to see if ++ * the minimum amount of work satisfies the allocation ++ */ ++ mt = get_pageblock_migratetype(page); ++ if (!cc->sync && !migrate_async_suitable(mt)) { ++ cc->finished_update_migrate = true; ++ skipped_async_unsuitable = true; ++ goto next_pageblock; ++ } ++ } + + /* + * Skip if free. page_order cannot be used without zone->lock +@@ -537,18 +555,6 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + continue; + + /* +- * For async migration, also only scan in MOVABLE blocks. Async +- * migration is optimistic to see if the minimum amount of work +- * satisfies the allocation +- */ +- if (!cc->sync && last_pageblock_nr != pageblock_nr && +- !migrate_async_suitable(get_pageblock_migratetype(page))) { +- cc->finished_update_migrate = true; +- skipped_async_unsuitable = true; +- goto next_pageblock; +- } +- +- /* + * Check may be lockless but that's ok as we recheck later. + * It's possible to migrate LRU pages and balloon pages + * Skip any other type of page +@@ -557,11 +563,7 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + if (unlikely(balloon_page_movable(page))) { + if (locked && balloon_page_isolate(page)) { + /* Successfully isolated */ +- cc->finished_update_migrate = true; +- list_add(&page->lru, migratelist); +- cc->nr_migratepages++; +- nr_isolated++; +- goto check_compact_cluster; ++ goto isolate_success; + } + } + continue; +@@ -584,6 +586,15 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + continue; + } + ++ /* ++ * Migration will fail if an anonymous page is pinned in memory, ++ * so avoid taking lru_lock and isolating it unnecessarily in an ++ * admittedly racy check. ++ */ ++ if (!page_mapping(page) && ++ page_count(page) > page_mapcount(page)) ++ continue; ++ + /* Check if it is ok to still hold the lock */ + locked = compact_checklock_irqsave(&zone->lru_lock, &flags, + locked, cc); +@@ -598,12 +609,6 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + continue; + } + +- if (!cc->sync) +- mode |= ISOLATE_ASYNC_MIGRATE; +- +- if (unevictable) +- mode |= ISOLATE_UNEVICTABLE; +- + lruvec = mem_cgroup_page_lruvec(page, zone); + + /* Try isolate the page */ +@@ -613,13 +618,14 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + VM_BUG_ON_PAGE(PageTransCompound(page), page); + + /* Successfully isolated */ +- cc->finished_update_migrate = true; + del_page_from_lru_list(page, lruvec, page_lru(page)); ++ ++isolate_success: ++ cc->finished_update_migrate = true; + list_add(&page->lru, migratelist); + cc->nr_migratepages++; + nr_isolated++; + +-check_compact_cluster: + /* Avoid isolating too much */ + if (cc->nr_migratepages == COMPACT_CLUSTER_MAX) { + ++low_pfn; +@@ -630,7 +636,6 @@ check_compact_cluster: + + next_pageblock: + low_pfn = ALIGN(low_pfn + 1, pageblock_nr_pages) - 1; +- last_pageblock_nr = pageblock_nr; + } + + acct_isolated(zone, locked, cc); +@@ -1188,6 +1193,7 @@ static void compact_node(int nid) + struct compact_control cc = { + .order = -1, + .sync = true, ++ .ignore_skip_hint = true, + }; + + __compact_pgdat(NODE_DATA(nid), &cc); +diff --git a/mm/filemap.c b/mm/filemap.c +index 7a13f6ac5421..c2cc7c95eff1 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -192,9 +192,11 @@ static int filemap_check_errors(struct address_space *mapping) + { + int ret = 0; + /* Check for outstanding write errors */ +- if (test_and_clear_bit(AS_ENOSPC, &mapping->flags)) ++ if (test_bit(AS_ENOSPC, &mapping->flags) && ++ test_and_clear_bit(AS_ENOSPC, &mapping->flags)) + ret = -ENOSPC; +- if (test_and_clear_bit(AS_EIO, &mapping->flags)) ++ if (test_bit(AS_EIO, &mapping->flags) && ++ test_and_clear_bit(AS_EIO, &mapping->flags)) + ret = -EIO; + return ret; + } +@@ -520,10 +522,10 @@ struct page *__page_cache_alloc(gfp_t gfp) + if (cpuset_do_page_mem_spread()) { + unsigned int cpuset_mems_cookie; + do { +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + n = cpuset_mem_spread_node(); + page = alloc_pages_exact_node(n, gfp, 0); +- } while (!put_mems_allowed(cpuset_mems_cookie) && !page); ++ } while (!page && read_mems_allowed_retry(cpuset_mems_cookie)); + + return page; + } +diff --git a/mm/frontswap.c b/mm/frontswap.c +index 1b24bdcb3197..c30eec536f03 100644 +--- a/mm/frontswap.c ++++ b/mm/frontswap.c +@@ -327,15 +327,12 @@ EXPORT_SYMBOL(__frontswap_invalidate_area); + + static unsigned long __frontswap_curr_pages(void) + { +- int type; + unsigned long totalpages = 0; + struct swap_info_struct *si = NULL; + + assert_spin_locked(&swap_lock); +- for (type = swap_list.head; type >= 0; type = si->next) { +- si = swap_info[type]; ++ plist_for_each_entry(si, &swap_active_head, list) + totalpages += atomic_read(&si->frontswap_pages); +- } + return totalpages; + } + +@@ -347,11 +344,9 @@ static int __frontswap_unuse_pages(unsigned long total, unsigned long *unused, + int si_frontswap_pages; + unsigned long total_pages_to_unuse = total; + unsigned long pages = 0, pages_to_unuse = 0; +- int type; + + assert_spin_locked(&swap_lock); +- for (type = swap_list.head; type >= 0; type = si->next) { +- si = swap_info[type]; ++ plist_for_each_entry(si, &swap_active_head, list) { + si_frontswap_pages = atomic_read(&si->frontswap_pages); + if (total_pages_to_unuse < si_frontswap_pages) { + pages = pages_to_unuse = total_pages_to_unuse; +@@ -366,7 +361,7 @@ static int __frontswap_unuse_pages(unsigned long total, unsigned long *unused, + } + vm_unacct_memory(pages); + *unused = pages_to_unuse; +- *swapid = type; ++ *swapid = si->type; + ret = 0; + break; + } +@@ -413,7 +408,7 @@ void frontswap_shrink(unsigned long target_pages) + /* + * we don't want to hold swap_lock while doing a very + * lengthy try_to_unuse, but swap_list may change +- * so restart scan from swap_list.head each time ++ * so restart scan from swap_active_head each time + */ + spin_lock(&swap_lock); + ret = __frontswap_shrink(target_pages, &pages_to_unuse, &type); +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index 1c42d0c36d0b..718bfa16a36f 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -1819,21 +1819,24 @@ static int __split_huge_page_map(struct page *page, + if (pmd) { + pgtable = pgtable_trans_huge_withdraw(mm, pmd); + pmd_populate(mm, &_pmd, pgtable); ++ if (pmd_write(*pmd)) ++ BUG_ON(page_mapcount(page) != 1); + + haddr = address; + for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) { + pte_t *pte, entry; + BUG_ON(PageCompound(page+i)); ++ /* ++ * Note that pmd_numa is not transferred deliberately ++ * to avoid any possibility that pte_numa leaks to ++ * a PROT_NONE VMA by accident. ++ */ + entry = mk_pte(page + i, vma->vm_page_prot); + entry = maybe_mkwrite(pte_mkdirty(entry), vma); + if (!pmd_write(*pmd)) + entry = pte_wrprotect(entry); +- else +- BUG_ON(page_mapcount(page) != 1); + if (!pmd_young(*pmd)) + entry = pte_mkold(entry); +- if (pmd_numa(*pmd)) +- entry = pte_mknuma(entry); + pte = pte_offset_map(&_pmd, haddr); + BUG_ON(!pte_none(*pte)); + set_pte_at(mm, haddr, pte, entry); +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 923f38e62bcf..67d0c175efcf 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -540,7 +540,7 @@ static struct page *dequeue_huge_page_vma(struct hstate *h, + goto err; + + retry_cpuset: +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + zonelist = huge_zonelist(vma, address, + htlb_alloc_mask(h), &mpol, &nodemask); + +@@ -562,7 +562,7 @@ retry_cpuset: + } + + mpol_cond_put(mpol); +- if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) ++ if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie))) + goto retry_cpuset; + return page; + +@@ -2071,6 +2071,9 @@ static int hugetlb_sysctl_handler_common(bool obey_mempolicy, + unsigned long tmp; + int ret; + ++ if (!hugepages_supported()) ++ return -ENOTSUPP; ++ + tmp = h->max_huge_pages; + + if (write && h->order >= MAX_ORDER) +@@ -2124,6 +2127,9 @@ int hugetlb_overcommit_handler(struct ctl_table *table, int write, + unsigned long tmp; + int ret; + ++ if (!hugepages_supported()) ++ return -ENOTSUPP; ++ + tmp = h->nr_overcommit_huge_pages; + + if (write && h->order >= MAX_ORDER) +@@ -2149,6 +2155,8 @@ out: + void hugetlb_report_meminfo(struct seq_file *m) + { + struct hstate *h = &default_hstate; ++ if (!hugepages_supported()) ++ return; + seq_printf(m, + "HugePages_Total: %5lu\n" + "HugePages_Free: %5lu\n" +@@ -2165,6 +2173,8 @@ void hugetlb_report_meminfo(struct seq_file *m) + int hugetlb_report_node_meminfo(int nid, char *buf) + { + struct hstate *h = &default_hstate; ++ if (!hugepages_supported()) ++ return 0; + return sprintf(buf, + "Node %d HugePages_Total: %5u\n" + "Node %d HugePages_Free: %5u\n" +@@ -2179,6 +2189,9 @@ void hugetlb_show_meminfo(void) + struct hstate *h; + int nid; + ++ if (!hugepages_supported()) ++ return; ++ + for_each_node_state(nid, N_MEMORY) + for_each_hstate(h) + pr_info("Node %d hugepages_total=%u hugepages_free=%u hugepages_surp=%u hugepages_size=%lukB\n", +diff --git a/mm/mempolicy.c b/mm/mempolicy.c +index 15a8ea031526..796c7e6cf93b 100644 +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -1897,7 +1897,7 @@ int node_random(const nodemask_t *maskp) + * If the effective policy is 'BIND, returns a pointer to the mempolicy's + * @nodemask for filtering the zonelist. + * +- * Must be protected by get_mems_allowed() ++ * Must be protected by read_mems_allowed_begin() + */ + struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr, + gfp_t gfp_flags, struct mempolicy **mpol, +@@ -2061,7 +2061,7 @@ alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma, + + retry_cpuset: + pol = get_vma_policy(current, vma, addr); +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + + if (unlikely(pol->mode == MPOL_INTERLEAVE)) { + unsigned nid; +@@ -2069,7 +2069,7 @@ retry_cpuset: + nid = interleave_nid(pol, vma, addr, PAGE_SHIFT + order); + mpol_cond_put(pol); + page = alloc_page_interleave(gfp, order, nid); +- if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) ++ if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie))) + goto retry_cpuset; + + return page; +@@ -2079,7 +2079,7 @@ retry_cpuset: + policy_nodemask(gfp, pol)); + if (unlikely(mpol_needs_cond_ref(pol))) + __mpol_put(pol); +- if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) ++ if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie))) + goto retry_cpuset; + return page; + } +@@ -2113,7 +2113,7 @@ struct page *alloc_pages_current(gfp_t gfp, unsigned order) + pol = &default_policy; + + retry_cpuset: +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + + /* + * No reference counting needed for current->mempolicy +@@ -2126,7 +2126,7 @@ retry_cpuset: + policy_zonelist(gfp, pol, numa_node_id()), + policy_nodemask(gfp, pol)); + +- if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) ++ if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie))) + goto retry_cpuset; + + return page; +diff --git a/mm/migrate.c b/mm/migrate.c +index bed48809e5d0..13f47fbe3550 100644 +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -148,8 +148,11 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma, + pte = pte_mkold(mk_pte(new, vma->vm_page_prot)); + if (pte_swp_soft_dirty(*ptep)) + pte = pte_mksoft_dirty(pte); ++ ++ /* Recheck VMA as permissions can change since migration started */ + if (is_write_migration_entry(entry)) +- pte = pte_mkwrite(pte); ++ pte = maybe_mkwrite(pte, vma); ++ + #ifdef CONFIG_HUGETLB_PAGE + if (PageHuge(new)) { + pte = pte_mkhuge(pte); +diff --git a/mm/mmap.c b/mm/mmap.c +index 20ff0c33274c..dfe90657a6db 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -681,8 +682,9 @@ __vma_unlink(struct mm_struct *mm, struct vm_area_struct *vma, + prev->vm_next = next = vma->vm_next; + if (next) + next->vm_prev = prev; +- if (mm->mmap_cache == vma) +- mm->mmap_cache = prev; ++ ++ /* Kill the cache */ ++ vmacache_invalidate(mm); + } + + /* +@@ -1989,34 +1991,33 @@ EXPORT_SYMBOL(get_unmapped_area); + /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ + struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) + { +- struct vm_area_struct *vma = NULL; ++ struct rb_node *rb_node; ++ struct vm_area_struct *vma; + + /* Check the cache first. */ +- /* (Cache hit rate is typically around 35%.) */ +- vma = ACCESS_ONCE(mm->mmap_cache); +- if (!(vma && vma->vm_end > addr && vma->vm_start <= addr)) { +- struct rb_node *rb_node; ++ vma = vmacache_find(mm, addr); ++ if (likely(vma)) ++ return vma; + +- rb_node = mm->mm_rb.rb_node; +- vma = NULL; ++ rb_node = mm->mm_rb.rb_node; ++ vma = NULL; + +- while (rb_node) { +- struct vm_area_struct *vma_tmp; +- +- vma_tmp = rb_entry(rb_node, +- struct vm_area_struct, vm_rb); +- +- if (vma_tmp->vm_end > addr) { +- vma = vma_tmp; +- if (vma_tmp->vm_start <= addr) +- break; +- rb_node = rb_node->rb_left; +- } else +- rb_node = rb_node->rb_right; +- } +- if (vma) +- mm->mmap_cache = vma; ++ while (rb_node) { ++ struct vm_area_struct *tmp; ++ ++ tmp = rb_entry(rb_node, struct vm_area_struct, vm_rb); ++ ++ if (tmp->vm_end > addr) { ++ vma = tmp; ++ if (tmp->vm_start <= addr) ++ break; ++ rb_node = rb_node->rb_left; ++ } else ++ rb_node = rb_node->rb_right; + } ++ ++ if (vma) ++ vmacache_update(addr, vma); + return vma; + } + +@@ -2388,7 +2389,9 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, + } else + mm->highest_vm_end = prev ? prev->vm_end : 0; + tail_vma->vm_next = NULL; +- mm->mmap_cache = NULL; /* Kill the cache. */ ++ ++ /* Kill the cache */ ++ vmacache_invalidate(mm); + } + + /* +diff --git a/mm/nommu.c b/mm/nommu.c +index 8740213b1647..3ee4f74fbfbe 100644 +--- a/mm/nommu.c ++++ b/mm/nommu.c +@@ -15,6 +15,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -768,16 +769,23 @@ static void add_vma_to_mm(struct mm_struct *mm, struct vm_area_struct *vma) + */ + static void delete_vma_from_mm(struct vm_area_struct *vma) + { ++ int i; + struct address_space *mapping; + struct mm_struct *mm = vma->vm_mm; ++ struct task_struct *curr = current; + + kenter("%p", vma); + + protect_vma(vma, 0); + + mm->map_count--; +- if (mm->mmap_cache == vma) +- mm->mmap_cache = NULL; ++ for (i = 0; i < VMACACHE_SIZE; i++) { ++ /* if the vma is cached, invalidate the entire cache */ ++ if (curr->vmacache[i] == vma) { ++ vmacache_invalidate(curr->mm); ++ break; ++ } ++ } + + /* remove the VMA from the mapping */ + if (vma->vm_file) { +@@ -825,8 +833,8 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) + struct vm_area_struct *vma; + + /* check the cache first */ +- vma = ACCESS_ONCE(mm->mmap_cache); +- if (vma && vma->vm_start <= addr && vma->vm_end > addr) ++ vma = vmacache_find(mm, addr); ++ if (likely(vma)) + return vma; + + /* trawl the list (there may be multiple mappings in which addr +@@ -835,7 +843,7 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) + if (vma->vm_start > addr) + return NULL; + if (vma->vm_end > addr) { +- mm->mmap_cache = vma; ++ vmacache_update(addr, vma); + return vma; + } + } +@@ -874,8 +882,8 @@ static struct vm_area_struct *find_vma_exact(struct mm_struct *mm, + unsigned long end = addr + len; + + /* check the cache first */ +- vma = mm->mmap_cache; +- if (vma && vma->vm_start == addr && vma->vm_end == end) ++ vma = vmacache_find_exact(mm, addr, end); ++ if (vma) + return vma; + + /* trawl the list (there may be multiple mappings in which addr +@@ -886,7 +894,7 @@ static struct vm_area_struct *find_vma_exact(struct mm_struct *mm, + if (vma->vm_start > addr) + return NULL; + if (vma->vm_end == end) { +- mm->mmap_cache = vma; ++ vmacache_update(addr, vma); + return vma; + } + } +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 62e400d00e3f..ff0f6b13f32f 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -1869,7 +1869,7 @@ static void __paginginit init_zone_allows_reclaim(int nid) + { + int i; + +- for_each_online_node(i) ++ for_each_node_state(i, N_MEMORY) + if (node_distance(nid, i) <= RECLAIM_DISTANCE) + node_set(i, NODE_DATA(nid)->reclaim_nodes); + else +@@ -2736,7 +2736,7 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, + return NULL; + + retry_cpuset: +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + + /* The preferred zone is used for statistics later */ + first_zones_zonelist(zonelist, high_zoneidx, +@@ -2791,7 +2791,7 @@ out: + * the mask is being updated. If a page allocation is about to fail, + * check if the cpuset changed during allocation and if so, retry. + */ +- if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) ++ if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie))) + goto retry_cpuset; + + memcg_kmem_commit_charge(page, memcg, order); +@@ -3059,9 +3059,9 @@ bool skip_free_areas_node(unsigned int flags, int nid) + goto out; + + do { +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + ret = !node_isset(nid, cpuset_current_mems_allowed); +- } while (!put_mems_allowed(cpuset_mems_cookie)); ++ } while (read_mems_allowed_retry(cpuset_mems_cookie)); + out: + return ret; + } +@@ -4933,7 +4933,8 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size, + + pgdat->node_id = nid; + pgdat->node_start_pfn = node_start_pfn; +- init_zone_allows_reclaim(nid); ++ if (node_state(nid, N_MEMORY)) ++ init_zone_allows_reclaim(nid); + #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP + get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); + #endif +diff --git a/mm/readahead.c b/mm/readahead.c +index 0de2360d65f3..1fa0d6fca556 100644 +--- a/mm/readahead.c ++++ b/mm/readahead.c +@@ -233,14 +233,14 @@ int force_page_cache_readahead(struct address_space *mapping, struct file *filp, + return 0; + } + ++#define MAX_READAHEAD ((512*4096)/PAGE_CACHE_SIZE) + /* + * Given a desired number of PAGE_CACHE_SIZE readahead pages, return a + * sensible upper limit. + */ + unsigned long max_sane_readahead(unsigned long nr) + { +- return min(nr, (node_page_state(numa_node_id(), NR_INACTIVE_FILE) +- + node_page_state(numa_node_id(), NR_FREE_PAGES)) / 2); ++ return min(nr, MAX_READAHEAD); + } + + /* +diff --git a/mm/slab.c b/mm/slab.c +index ea854eb2388c..0b1c2a58559d 100644 +--- a/mm/slab.c ++++ b/mm/slab.c +@@ -3122,7 +3122,7 @@ static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags) + local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK); + + retry_cpuset: +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + zonelist = node_zonelist(slab_node(), flags); + + retry: +@@ -3180,7 +3180,7 @@ retry: + } + } + +- if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !obj)) ++ if (unlikely(!obj && read_mems_allowed_retry(cpuset_mems_cookie))) + goto retry_cpuset; + return obj; + } +diff --git a/mm/slub.c b/mm/slub.c +index 25f14ad8f817..7611f148ee81 100644 +--- a/mm/slub.c ++++ b/mm/slub.c +@@ -1684,7 +1684,7 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags, + return NULL; + + do { +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + zonelist = node_zonelist(slab_node(), flags); + for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) { + struct kmem_cache_node *n; +@@ -1696,19 +1696,17 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags, + object = get_partial_node(s, n, c, flags); + if (object) { + /* +- * Return the object even if +- * put_mems_allowed indicated that +- * the cpuset mems_allowed was +- * updated in parallel. It's a +- * harmless race between the alloc +- * and the cpuset update. ++ * Don't check read_mems_allowed_retry() ++ * here - if mems_allowed was updated in ++ * parallel, that was a harmless race ++ * between allocation and the cpuset ++ * update + */ +- put_mems_allowed(cpuset_mems_cookie); + return object; + } + } + } +- } while (!put_mems_allowed(cpuset_mems_cookie)); ++ } while (read_mems_allowed_retry(cpuset_mems_cookie)); + #endif + return NULL; + } +diff --git a/mm/swapfile.c b/mm/swapfile.c +index 4a7f7e6992b6..beeeef8a1b2d 100644 +--- a/mm/swapfile.c ++++ b/mm/swapfile.c +@@ -51,14 +51,32 @@ atomic_long_t nr_swap_pages; + /* protected with swap_lock. reading in vm_swap_full() doesn't need lock */ + long total_swap_pages; + static int least_priority; +-static atomic_t highest_priority_index = ATOMIC_INIT(-1); + + static const char Bad_file[] = "Bad swap file entry "; + static const char Unused_file[] = "Unused swap file entry "; + static const char Bad_offset[] = "Bad swap offset entry "; + static const char Unused_offset[] = "Unused swap offset entry "; + +-struct swap_list_t swap_list = {-1, -1}; ++/* ++ * all active swap_info_structs ++ * protected with swap_lock, and ordered by priority. ++ */ ++PLIST_HEAD(swap_active_head); ++ ++/* ++ * all available (active, not full) swap_info_structs ++ * protected with swap_avail_lock, ordered by priority. ++ * This is used by get_swap_page() instead of swap_active_head ++ * because swap_active_head includes all swap_info_structs, ++ * but get_swap_page() doesn't need to look at full ones. ++ * This uses its own lock instead of swap_lock because when a ++ * swap_info_struct changes between not-full/full, it needs to ++ * add/remove itself to/from this list, but the swap_info_struct->lock ++ * is held and the locking order requires swap_lock to be taken ++ * before any swap_info_struct->lock. ++ */ ++static PLIST_HEAD(swap_avail_head); ++static DEFINE_SPINLOCK(swap_avail_lock); + + struct swap_info_struct *swap_info[MAX_SWAPFILES]; + +@@ -591,6 +609,9 @@ checks: + if (si->inuse_pages == si->pages) { + si->lowest_bit = si->max; + si->highest_bit = 0; ++ spin_lock(&swap_avail_lock); ++ plist_del(&si->avail_list, &swap_avail_head); ++ spin_unlock(&swap_avail_lock); + } + si->swap_map[offset] = usage; + inc_cluster_info_page(si, si->cluster_info, offset); +@@ -640,71 +661,65 @@ no_page: + + swp_entry_t get_swap_page(void) + { +- struct swap_info_struct *si; ++ struct swap_info_struct *si, *next; + pgoff_t offset; +- int type, next; +- int wrapped = 0; +- int hp_index; + +- spin_lock(&swap_lock); + if (atomic_long_read(&nr_swap_pages) <= 0) + goto noswap; + atomic_long_dec(&nr_swap_pages); + +- for (type = swap_list.next; type >= 0 && wrapped < 2; type = next) { +- hp_index = atomic_xchg(&highest_priority_index, -1); +- /* +- * highest_priority_index records current highest priority swap +- * type which just frees swap entries. If its priority is +- * higher than that of swap_list.next swap type, we use it. It +- * isn't protected by swap_lock, so it can be an invalid value +- * if the corresponding swap type is swapoff. We double check +- * the flags here. It's even possible the swap type is swapoff +- * and swapon again and its priority is changed. In such rare +- * case, low prority swap type might be used, but eventually +- * high priority swap will be used after several rounds of +- * swap. +- */ +- if (hp_index != -1 && hp_index != type && +- swap_info[type]->prio < swap_info[hp_index]->prio && +- (swap_info[hp_index]->flags & SWP_WRITEOK)) { +- type = hp_index; +- swap_list.next = type; +- } +- +- si = swap_info[type]; +- next = si->next; +- if (next < 0 || +- (!wrapped && si->prio != swap_info[next]->prio)) { +- next = swap_list.head; +- wrapped++; +- } ++ spin_lock(&swap_avail_lock); + ++start_over: ++ plist_for_each_entry_safe(si, next, &swap_avail_head, avail_list) { ++ /* requeue si to after same-priority siblings */ ++ plist_requeue(&si->avail_list, &swap_avail_head); ++ spin_unlock(&swap_avail_lock); + spin_lock(&si->lock); +- if (!si->highest_bit) { ++ if (!si->highest_bit || !(si->flags & SWP_WRITEOK)) { ++ spin_lock(&swap_avail_lock); ++ if (plist_node_empty(&si->avail_list)) { ++ spin_unlock(&si->lock); ++ goto nextsi; ++ } ++ WARN(!si->highest_bit, ++ "swap_info %d in list but !highest_bit\n", ++ si->type); ++ WARN(!(si->flags & SWP_WRITEOK), ++ "swap_info %d in list but !SWP_WRITEOK\n", ++ si->type); ++ plist_del(&si->avail_list, &swap_avail_head); + spin_unlock(&si->lock); +- continue; ++ goto nextsi; + } +- if (!(si->flags & SWP_WRITEOK)) { +- spin_unlock(&si->lock); +- continue; +- } +- +- swap_list.next = next; + +- spin_unlock(&swap_lock); + /* This is called for allocating swap entry for cache */ + offset = scan_swap_map(si, SWAP_HAS_CACHE); + spin_unlock(&si->lock); + if (offset) +- return swp_entry(type, offset); +- spin_lock(&swap_lock); +- next = swap_list.next; ++ return swp_entry(si->type, offset); ++ pr_debug("scan_swap_map of si %d failed to find offset\n", ++ si->type); ++ spin_lock(&swap_avail_lock); ++nextsi: ++ /* ++ * if we got here, it's likely that si was almost full before, ++ * and since scan_swap_map() can drop the si->lock, multiple ++ * callers probably all tried to get a page from the same si ++ * and it filled up before we could get one; or, the si filled ++ * up between us dropping swap_avail_lock and taking si->lock. ++ * Since we dropped the swap_avail_lock, the swap_avail_head ++ * list may have been modified; so if next is still in the ++ * swap_avail_head list then try it, otherwise start over. ++ */ ++ if (plist_node_empty(&next->avail_list)) ++ goto start_over; + } + ++ spin_unlock(&swap_avail_lock); ++ + atomic_long_inc(&nr_swap_pages); + noswap: +- spin_unlock(&swap_lock); + return (swp_entry_t) {0}; + } + +@@ -766,27 +781,6 @@ out: + return NULL; + } + +-/* +- * This swap type frees swap entry, check if it is the highest priority swap +- * type which just frees swap entry. get_swap_page() uses +- * highest_priority_index to search highest priority swap type. The +- * swap_info_struct.lock can't protect us if there are multiple swap types +- * active, so we use atomic_cmpxchg. +- */ +-static void set_highest_priority_index(int type) +-{ +- int old_hp_index, new_hp_index; +- +- do { +- old_hp_index = atomic_read(&highest_priority_index); +- if (old_hp_index != -1 && +- swap_info[old_hp_index]->prio >= swap_info[type]->prio) +- break; +- new_hp_index = type; +- } while (atomic_cmpxchg(&highest_priority_index, +- old_hp_index, new_hp_index) != old_hp_index); +-} +- + static unsigned char swap_entry_free(struct swap_info_struct *p, + swp_entry_t entry, unsigned char usage) + { +@@ -828,9 +822,18 @@ static unsigned char swap_entry_free(struct swap_info_struct *p, + dec_cluster_info_page(p, p->cluster_info, offset); + if (offset < p->lowest_bit) + p->lowest_bit = offset; +- if (offset > p->highest_bit) ++ if (offset > p->highest_bit) { ++ bool was_full = !p->highest_bit; + p->highest_bit = offset; +- set_highest_priority_index(p->type); ++ if (was_full && (p->flags & SWP_WRITEOK)) { ++ spin_lock(&swap_avail_lock); ++ WARN_ON(!plist_node_empty(&p->avail_list)); ++ if (plist_node_empty(&p->avail_list)) ++ plist_add(&p->avail_list, ++ &swap_avail_head); ++ spin_unlock(&swap_avail_lock); ++ } ++ } + atomic_long_inc(&nr_swap_pages); + p->inuse_pages--; + frontswap_invalidate_page(p->type, offset); +@@ -1765,30 +1768,37 @@ static void _enable_swap_info(struct swap_info_struct *p, int prio, + unsigned char *swap_map, + struct swap_cluster_info *cluster_info) + { +- int i, prev; +- + if (prio >= 0) + p->prio = prio; + else + p->prio = --least_priority; ++ /* ++ * the plist prio is negated because plist ordering is ++ * low-to-high, while swap ordering is high-to-low ++ */ ++ p->list.prio = -p->prio; ++ p->avail_list.prio = -p->prio; + p->swap_map = swap_map; + p->cluster_info = cluster_info; + p->flags |= SWP_WRITEOK; + atomic_long_add(p->pages, &nr_swap_pages); + total_swap_pages += p->pages; + +- /* insert swap space into swap_list: */ +- prev = -1; +- for (i = swap_list.head; i >= 0; i = swap_info[i]->next) { +- if (p->prio >= swap_info[i]->prio) +- break; +- prev = i; +- } +- p->next = i; +- if (prev < 0) +- swap_list.head = swap_list.next = p->type; +- else +- swap_info[prev]->next = p->type; ++ assert_spin_locked(&swap_lock); ++ /* ++ * both lists are plists, and thus priority ordered. ++ * swap_active_head needs to be priority ordered for swapoff(), ++ * which on removal of any swap_info_struct with an auto-assigned ++ * (i.e. negative) priority increments the auto-assigned priority ++ * of any lower-priority swap_info_structs. ++ * swap_avail_head needs to be priority ordered for get_swap_page(), ++ * which allocates swap pages from the highest available priority ++ * swap_info_struct. ++ */ ++ plist_add(&p->list, &swap_active_head); ++ spin_lock(&swap_avail_lock); ++ plist_add(&p->avail_list, &swap_avail_head); ++ spin_unlock(&swap_avail_lock); + } + + static void enable_swap_info(struct swap_info_struct *p, int prio, +@@ -1823,8 +1833,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) + struct address_space *mapping; + struct inode *inode; + struct filename *pathname; +- int i, type, prev; +- int err; ++ int err, found = 0; + unsigned int old_block_size; + + if (!capable(CAP_SYS_ADMIN)) +@@ -1842,17 +1851,16 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) + goto out; + + mapping = victim->f_mapping; +- prev = -1; + spin_lock(&swap_lock); +- for (type = swap_list.head; type >= 0; type = swap_info[type]->next) { +- p = swap_info[type]; ++ plist_for_each_entry(p, &swap_active_head, list) { + if (p->flags & SWP_WRITEOK) { +- if (p->swap_file->f_mapping == mapping) ++ if (p->swap_file->f_mapping == mapping) { ++ found = 1; + break; ++ } + } +- prev = type; + } +- if (type < 0) { ++ if (!found) { + err = -EINVAL; + spin_unlock(&swap_lock); + goto out_dput; +@@ -1864,20 +1872,21 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) + spin_unlock(&swap_lock); + goto out_dput; + } +- if (prev < 0) +- swap_list.head = p->next; +- else +- swap_info[prev]->next = p->next; +- if (type == swap_list.next) { +- /* just pick something that's safe... */ +- swap_list.next = swap_list.head; +- } ++ spin_lock(&swap_avail_lock); ++ plist_del(&p->avail_list, &swap_avail_head); ++ spin_unlock(&swap_avail_lock); + spin_lock(&p->lock); + if (p->prio < 0) { +- for (i = p->next; i >= 0; i = swap_info[i]->next) +- swap_info[i]->prio = p->prio--; ++ struct swap_info_struct *si = p; ++ ++ plist_for_each_entry_continue(si, &swap_active_head, list) { ++ si->prio++; ++ si->list.prio--; ++ si->avail_list.prio--; ++ } + least_priority++; + } ++ plist_del(&p->list, &swap_active_head); + atomic_long_sub(p->pages, &nr_swap_pages); + total_swap_pages -= p->pages; + p->flags &= ~SWP_WRITEOK; +@@ -1885,7 +1894,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) + spin_unlock(&swap_lock); + + set_current_oom_origin(); +- err = try_to_unuse(type, false, 0); /* force all pages to be unused */ ++ err = try_to_unuse(p->type, false, 0); /* force unuse all pages */ + clear_current_oom_origin(); + + if (err) { +@@ -1926,7 +1935,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) + frontswap_map = frontswap_map_get(p); + spin_unlock(&p->lock); + spin_unlock(&swap_lock); +- frontswap_invalidate_area(type); ++ frontswap_invalidate_area(p->type); + frontswap_map_set(p, NULL); + mutex_unlock(&swapon_mutex); + free_percpu(p->percpu_cluster); +@@ -1935,7 +1944,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) + vfree(cluster_info); + vfree(frontswap_map); + /* Destroy swap account information */ +- swap_cgroup_swapoff(type); ++ swap_cgroup_swapoff(p->type); + + inode = mapping->host; + if (S_ISBLK(inode->i_mode)) { +@@ -2142,8 +2151,9 @@ static struct swap_info_struct *alloc_swap_info(void) + */ + } + INIT_LIST_HEAD(&p->first_swap_extent.list); ++ plist_node_init(&p->list, 0); ++ plist_node_init(&p->avail_list, 0); + p->flags = SWP_USED; +- p->next = -1; + spin_unlock(&swap_lock); + spin_lock_init(&p->lock); + +diff --git a/mm/vmacache.c b/mm/vmacache.c +new file mode 100644 +index 000000000000..1037a3bab505 +--- /dev/null ++++ b/mm/vmacache.c +@@ -0,0 +1,114 @@ ++/* ++ * Copyright (C) 2014 Davidlohr Bueso. ++ */ ++#include ++#include ++#include ++ ++/* ++ * Flush vma caches for threads that share a given mm. ++ * ++ * The operation is safe because the caller holds the mmap_sem ++ * exclusively and other threads accessing the vma cache will ++ * have mmap_sem held at least for read, so no extra locking ++ * is required to maintain the vma cache. ++ */ ++void vmacache_flush_all(struct mm_struct *mm) ++{ ++ struct task_struct *g, *p; ++ ++ rcu_read_lock(); ++ for_each_process_thread(g, p) { ++ /* ++ * Only flush the vmacache pointers as the ++ * mm seqnum is already set and curr's will ++ * be set upon invalidation when the next ++ * lookup is done. ++ */ ++ if (mm == p->mm) ++ vmacache_flush(p); ++ } ++ rcu_read_unlock(); ++} ++ ++/* ++ * This task may be accessing a foreign mm via (for example) ++ * get_user_pages()->find_vma(). The vmacache is task-local and this ++ * task's vmacache pertains to a different mm (ie, its own). There is ++ * nothing we can do here. ++ * ++ * Also handle the case where a kernel thread has adopted this mm via use_mm(). ++ * That kernel thread's vmacache is not applicable to this mm. ++ */ ++static bool vmacache_valid_mm(struct mm_struct *mm) ++{ ++ return current->mm == mm && !(current->flags & PF_KTHREAD); ++} ++ ++void vmacache_update(unsigned long addr, struct vm_area_struct *newvma) ++{ ++ if (vmacache_valid_mm(newvma->vm_mm)) ++ current->vmacache[VMACACHE_HASH(addr)] = newvma; ++} ++ ++static bool vmacache_valid(struct mm_struct *mm) ++{ ++ struct task_struct *curr; ++ ++ if (!vmacache_valid_mm(mm)) ++ return false; ++ ++ curr = current; ++ if (mm->vmacache_seqnum != curr->vmacache_seqnum) { ++ /* ++ * First attempt will always be invalid, initialize ++ * the new cache for this task here. ++ */ ++ curr->vmacache_seqnum = mm->vmacache_seqnum; ++ vmacache_flush(curr); ++ return false; ++ } ++ return true; ++} ++ ++struct vm_area_struct *vmacache_find(struct mm_struct *mm, unsigned long addr) ++{ ++ int i; ++ ++ if (!vmacache_valid(mm)) ++ return NULL; ++ ++ for (i = 0; i < VMACACHE_SIZE; i++) { ++ struct vm_area_struct *vma = current->vmacache[i]; ++ ++ if (!vma) ++ continue; ++ if (WARN_ON_ONCE(vma->vm_mm != mm)) ++ break; ++ if (vma->vm_start <= addr && vma->vm_end > addr) ++ return vma; ++ } ++ ++ return NULL; ++} ++ ++#ifndef CONFIG_MMU ++struct vm_area_struct *vmacache_find_exact(struct mm_struct *mm, ++ unsigned long start, ++ unsigned long end) ++{ ++ int i; ++ ++ if (!vmacache_valid(mm)) ++ return NULL; ++ ++ for (i = 0; i < VMACACHE_SIZE; i++) { ++ struct vm_area_struct *vma = current->vmacache[i]; ++ ++ if (vma && vma->vm_start == start && vma->vm_end == end) ++ return vma; ++ } ++ ++ return NULL; ++} ++#endif +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 6ef484f0777f..0c0b36e5b4f8 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -224,15 +224,15 @@ shrink_slab_node(struct shrink_control *shrinkctl, struct shrinker *shrinker, + unsigned long freed = 0; + unsigned long long delta; + long total_scan; +- long max_pass; ++ long freeable; + long nr; + long new_nr; + int nid = shrinkctl->nid; + long batch_size = shrinker->batch ? shrinker->batch + : SHRINK_BATCH; + +- max_pass = shrinker->count_objects(shrinker, shrinkctl); +- if (max_pass == 0) ++ freeable = shrinker->count_objects(shrinker, shrinkctl); ++ if (freeable == 0) + return 0; + + /* +@@ -244,14 +244,14 @@ shrink_slab_node(struct shrink_control *shrinkctl, struct shrinker *shrinker, + + total_scan = nr; + delta = (4 * nr_pages_scanned) / shrinker->seeks; +- delta *= max_pass; ++ delta *= freeable; + do_div(delta, lru_pages + 1); + total_scan += delta; + if (total_scan < 0) { + printk(KERN_ERR + "shrink_slab: %pF negative objects to delete nr=%ld\n", + shrinker->scan_objects, total_scan); +- total_scan = max_pass; ++ total_scan = freeable; + } + + /* +@@ -260,26 +260,26 @@ shrink_slab_node(struct shrink_control *shrinkctl, struct shrinker *shrinker, + * shrinkers to return -1 all the time. This results in a large + * nr being built up so when a shrink that can do some work + * comes along it empties the entire cache due to nr >>> +- * max_pass. This is bad for sustaining a working set in ++ * freeable. This is bad for sustaining a working set in + * memory. + * + * Hence only allow the shrinker to scan the entire cache when + * a large delta change is calculated directly. + */ +- if (delta < max_pass / 4) +- total_scan = min(total_scan, max_pass / 2); ++ if (delta < freeable / 4) ++ total_scan = min(total_scan, freeable / 2); + + /* + * Avoid risking looping forever due to too large nr value: + * never try to free more than twice the estimate number of + * freeable entries. + */ +- if (total_scan > max_pass * 2) +- total_scan = max_pass * 2; ++ if (total_scan > freeable * 2) ++ total_scan = freeable * 2; + + trace_mm_shrink_slab_start(shrinker, shrinkctl, nr, + nr_pages_scanned, lru_pages, +- max_pass, delta, total_scan); ++ freeable, delta, total_scan); + + /* + * Normally, we should not scan less than batch_size objects in one +@@ -292,12 +292,12 @@ shrink_slab_node(struct shrink_control *shrinkctl, struct shrinker *shrinker, + * + * We detect the "tight on memory" situations by looking at the total + * number of objects we want to scan (total_scan). If it is greater +- * than the total number of objects on slab (max_pass), we must be ++ * than the total number of objects on slab (freeable), we must be + * scanning at high prio and therefore should try to reclaim as much as + * possible. + */ + while (total_scan >= batch_size || +- total_scan >= max_pass) { ++ total_scan >= freeable) { + unsigned long ret; + unsigned long nr_to_scan = min(batch_size, total_scan); + +@@ -1144,7 +1144,7 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone, + TTU_UNMAP|TTU_IGNORE_ACCESS, + &dummy1, &dummy2, &dummy3, &dummy4, &dummy5, true); + list_splice(&clean_pages, page_list); +- __mod_zone_page_state(zone, NR_ISOLATED_FILE, -ret); ++ mod_zone_page_state(zone, NR_ISOLATED_FILE, -ret); + return ret; + } + +@@ -2424,8 +2424,8 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, + unsigned long lru_pages = 0; + + nodes_clear(shrink->nodes_to_scan); +- for_each_zone_zonelist(zone, z, zonelist, +- gfp_zone(sc->gfp_mask)) { ++ for_each_zone_zonelist_nodemask(zone, z, zonelist, ++ gfp_zone(sc->gfp_mask), sc->nodemask) { + if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL)) + continue; + diff --git a/patch/kernel/cubox-default/patch-3.14.21-22.patch b/patch/kernel/cubox-default/patch-3.14.21-22.patch new file mode 100644 index 000000000..23599bd34 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.21-22.patch @@ -0,0 +1,1795 @@ +diff --git a/Makefile b/Makefile +index 41e6e19fe2e9..a59980eb4557 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 21 ++SUBLEVEL = 22 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c +index 0378328f47a7..a4127453baae 100644 +--- a/drivers/crypto/caam/caamhash.c ++++ b/drivers/crypto/caam/caamhash.c +@@ -1348,9 +1348,9 @@ static int ahash_update_first(struct ahash_request *req) + struct device *jrdev = ctx->jrdev; + gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; +- u8 *next_buf = state->buf_0 + state->current_buf * +- CAAM_MAX_HASH_BLOCK_SIZE; +- int *next_buflen = &state->buflen_0 + state->current_buf; ++ u8 *next_buf = state->current_buf ? state->buf_1 : state->buf_0; ++ int *next_buflen = state->current_buf ? ++ &state->buflen_1 : &state->buflen_0; + int to_hash; + u32 *sh_desc = ctx->sh_desc_update_first, *desc; + dma_addr_t ptr = ctx->sh_desc_update_first_dma; +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index a95b322f0924..cc38948cf65d 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -3624,8 +3624,14 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev + else + bond_xmit_slave_id(bond, skb, 0); + } else { +- slave_id = bond_rr_gen_slave_id(bond); +- bond_xmit_slave_id(bond, skb, slave_id % bond->slave_cnt); ++ int slave_cnt = ACCESS_ONCE(bond->slave_cnt); ++ ++ if (likely(slave_cnt)) { ++ slave_id = bond_rr_gen_slave_id(bond); ++ bond_xmit_slave_id(bond, skb, slave_id % slave_cnt); ++ } else { ++ dev_kfree_skb_any(skb); ++ } + } + + return NETDEV_TX_OK; +@@ -3656,8 +3662,13 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d + static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev) + { + struct bonding *bond = netdev_priv(bond_dev); ++ int slave_cnt = ACCESS_ONCE(bond->slave_cnt); + +- bond_xmit_slave_id(bond, skb, bond_xmit_hash(bond, skb, bond->slave_cnt)); ++ if (likely(slave_cnt)) ++ bond_xmit_slave_id(bond, skb, ++ bond_xmit_hash(bond, skb, bond->slave_cnt)); ++ else ++ dev_kfree_skb_any(skb); + + return NETDEV_TX_OK; + } +diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c +index a210766279d3..9373f1f59605 100644 +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -6923,7 +6923,8 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) + skb->protocol = eth_type_trans(skb, tp->dev); + + if (len > (tp->dev->mtu + ETH_HLEN) && +- skb->protocol != htons(ETH_P_8021Q)) { ++ skb->protocol != htons(ETH_P_8021Q) && ++ skb->protocol != htons(ETH_P_8021AD)) { + dev_kfree_skb(skb); + goto drop_it_no_recycle; + } +@@ -7915,8 +7916,6 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) + + entry = tnapi->tx_prod; + base_flags = 0; +- if (skb->ip_summed == CHECKSUM_PARTIAL) +- base_flags |= TXD_FLAG_TCPUDP_CSUM; + + mss = skb_shinfo(skb)->gso_size; + if (mss) { +@@ -7932,6 +7931,13 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) + + hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb) - ETH_HLEN; + ++ /* HW/FW can not correctly segment packets that have been ++ * vlan encapsulated. ++ */ ++ if (skb->protocol == htons(ETH_P_8021Q) || ++ skb->protocol == htons(ETH_P_8021AD)) ++ return tg3_tso_bug(tp, skb); ++ + if (!skb_is_gso_v6(skb)) { + iph->check = 0; + iph->tot_len = htons(mss + hdr_len); +@@ -7978,6 +7984,17 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) + base_flags |= tsflags << 12; + } + } ++ } else if (skb->ip_summed == CHECKSUM_PARTIAL) { ++ /* HW/FW can not correctly checksum packets that have been ++ * vlan encapsulated. ++ */ ++ if (skb->protocol == htons(ETH_P_8021Q) || ++ skb->protocol == htons(ETH_P_8021AD)) { ++ if (skb_checksum_help(skb)) ++ goto drop; ++ } else { ++ base_flags |= TXD_FLAG_TCPUDP_CSUM; ++ } + } + + if (tg3_flag(tp, USE_JUMBO_BDFLAG) && +diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c +index d0c38e01e99f..0085476a0258 100644 +--- a/drivers/net/ethernet/cadence/macb.c ++++ b/drivers/net/ethernet/cadence/macb.c +@@ -30,7 +30,6 @@ + #include + #include + #include +-#include + + #include "macb.h" + +@@ -1810,7 +1809,6 @@ static int __init macb_probe(struct platform_device *pdev) + struct phy_device *phydev; + u32 config; + int err = -ENXIO; +- struct pinctrl *pinctrl; + const char *mac; + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); +@@ -1819,15 +1817,6 @@ static int __init macb_probe(struct platform_device *pdev) + goto err_out; + } + +- pinctrl = devm_pinctrl_get_select_default(&pdev->dev); +- if (IS_ERR(pinctrl)) { +- err = PTR_ERR(pinctrl); +- if (err == -EPROBE_DEFER) +- goto err_out; +- +- dev_warn(&pdev->dev, "No pinctrl provided\n"); +- } +- + err = -ENOMEM; + dev = alloc_etherdev(sizeof(*bp)); + if (!dev) +diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c +index b901371ca361..5d3206d5cb07 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_main.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c +@@ -4024,6 +4024,9 @@ static int i40e_init_pf_dcb(struct i40e_pf *pf) + DCB_CAP_DCBX_VER_IEEE; + pf->flags |= I40E_FLAG_DCB_ENABLED; + } ++ } else { ++ dev_info(&pf->pdev->dev, "AQ Querying DCB configuration failed: %d\n", ++ pf->hw.aq.asq_last_status); + } + + out: +@@ -8003,7 +8006,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + if (err) { + dev_info(&pdev->dev, "init_pf_dcb failed: %d\n", err); + pf->flags &= ~I40E_FLAG_DCB_ENABLED; +- goto err_init_dcb; ++ /* Continue without DCB enabled */ + } + #endif /* CONFIG_I40E_DCB */ + +@@ -8119,9 +8122,6 @@ err_vsis: + err_switch_setup: + i40e_reset_interrupt_capability(pf); + del_timer_sync(&pf->service_timer); +-#ifdef CONFIG_I40E_DCB +-err_init_dcb: +-#endif /* CONFIG_I40E_DCB */ + err_mac_addr: + err_configure_lan_hmc: + (void)i40e_shutdown_lan_hmc(hw); +diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +index 68026f7e8ba3..4a474dd9c910 100644 +--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c ++++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +@@ -872,6 +872,10 @@ static int myri10ge_dma_test(struct myri10ge_priv *mgp, int test_type) + return -ENOMEM; + dmatest_bus = pci_map_page(mgp->pdev, dmatest_page, 0, PAGE_SIZE, + DMA_BIDIRECTIONAL); ++ if (unlikely(pci_dma_mapping_error(mgp->pdev, dmatest_bus))) { ++ __free_page(dmatest_page); ++ return -ENOMEM; ++ } + + /* Run a small DMA test. + * The magic multipliers to the length tell the firmware +@@ -1293,6 +1297,7 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, + int bytes, int watchdog) + { + struct page *page; ++ dma_addr_t bus; + int idx; + #if MYRI10GE_ALLOC_SIZE > 4096 + int end_offset; +@@ -1317,11 +1322,21 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, + rx->watchdog_needed = 1; + return; + } ++ ++ bus = pci_map_page(mgp->pdev, page, 0, ++ MYRI10GE_ALLOC_SIZE, ++ PCI_DMA_FROMDEVICE); ++ if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) { ++ __free_pages(page, MYRI10GE_ALLOC_ORDER); ++ if (rx->fill_cnt - rx->cnt < 16) ++ rx->watchdog_needed = 1; ++ return; ++ } ++ + rx->page = page; + rx->page_offset = 0; +- rx->bus = pci_map_page(mgp->pdev, page, 0, +- MYRI10GE_ALLOC_SIZE, +- PCI_DMA_FROMDEVICE); ++ rx->bus = bus; ++ + } + rx->info[idx].page = rx->page; + rx->info[idx].page_offset = rx->page_offset; +@@ -2765,6 +2780,35 @@ myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src, + mb(); + } + ++static void myri10ge_unmap_tx_dma(struct myri10ge_priv *mgp, ++ struct myri10ge_tx_buf *tx, int idx) ++{ ++ unsigned int len; ++ int last_idx; ++ ++ /* Free any DMA resources we've alloced and clear out the skb slot */ ++ last_idx = (idx + 1) & tx->mask; ++ idx = tx->req & tx->mask; ++ do { ++ len = dma_unmap_len(&tx->info[idx], len); ++ if (len) { ++ if (tx->info[idx].skb != NULL) ++ pci_unmap_single(mgp->pdev, ++ dma_unmap_addr(&tx->info[idx], ++ bus), len, ++ PCI_DMA_TODEVICE); ++ else ++ pci_unmap_page(mgp->pdev, ++ dma_unmap_addr(&tx->info[idx], ++ bus), len, ++ PCI_DMA_TODEVICE); ++ dma_unmap_len_set(&tx->info[idx], len, 0); ++ tx->info[idx].skb = NULL; ++ } ++ idx = (idx + 1) & tx->mask; ++ } while (idx != last_idx); ++} ++ + /* + * Transmit a packet. We need to split the packet so that a single + * segment does not cross myri10ge->tx_boundary, so this makes segment +@@ -2788,7 +2832,7 @@ static netdev_tx_t myri10ge_xmit(struct sk_buff *skb, + u32 low; + __be32 high_swapped; + unsigned int len; +- int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments; ++ int idx, avail, frag_cnt, frag_idx, count, mss, max_segments; + u16 pseudo_hdr_offset, cksum_offset, queue; + int cum_len, seglen, boundary, rdma_count; + u8 flags, odd_flag; +@@ -2885,9 +2929,12 @@ again: + + /* map the skb for DMA */ + len = skb_headlen(skb); ++ bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE); ++ if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) ++ goto drop; ++ + idx = tx->req & tx->mask; + tx->info[idx].skb = skb; +- bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE); + dma_unmap_addr_set(&tx->info[idx], bus, bus); + dma_unmap_len_set(&tx->info[idx], len, len); + +@@ -2986,12 +3033,16 @@ again: + break; + + /* map next fragment for DMA */ +- idx = (count + tx->req) & tx->mask; + frag = &skb_shinfo(skb)->frags[frag_idx]; + frag_idx++; + len = skb_frag_size(frag); + bus = skb_frag_dma_map(&mgp->pdev->dev, frag, 0, len, + DMA_TO_DEVICE); ++ if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) { ++ myri10ge_unmap_tx_dma(mgp, tx, idx); ++ goto drop; ++ } ++ idx = (count + tx->req) & tx->mask; + dma_unmap_addr_set(&tx->info[idx], bus, bus); + dma_unmap_len_set(&tx->info[idx], len, len); + } +@@ -3022,31 +3073,8 @@ again: + return NETDEV_TX_OK; + + abort_linearize: +- /* Free any DMA resources we've alloced and clear out the skb +- * slot so as to not trip up assertions, and to avoid a +- * double-free if linearizing fails */ ++ myri10ge_unmap_tx_dma(mgp, tx, idx); + +- last_idx = (idx + 1) & tx->mask; +- idx = tx->req & tx->mask; +- tx->info[idx].skb = NULL; +- do { +- len = dma_unmap_len(&tx->info[idx], len); +- if (len) { +- if (tx->info[idx].skb != NULL) +- pci_unmap_single(mgp->pdev, +- dma_unmap_addr(&tx->info[idx], +- bus), len, +- PCI_DMA_TODEVICE); +- else +- pci_unmap_page(mgp->pdev, +- dma_unmap_addr(&tx->info[idx], +- bus), len, +- PCI_DMA_TODEVICE); +- dma_unmap_len_set(&tx->info[idx], len, 0); +- tx->info[idx].skb = NULL; +- } +- idx = (idx + 1) & tx->mask; +- } while (idx != last_idx); + if (skb_is_gso(skb)) { + netdev_err(mgp->dev, "TSO but wanted to linearize?!?!?\n"); + goto drop; +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +index d6fce9750b95..3c1c33ceffba 100644 +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -146,6 +146,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) + struct hv_netvsc_packet *packet; + int ret; + unsigned int i, num_pages, npg_data; ++ u32 skb_length = skb->len; + + /* Add multipages for skb->data and additional 2 for RNDIS */ + npg_data = (((unsigned long)skb->data + skb_headlen(skb) - 1) +@@ -216,7 +217,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) + ret = rndis_filter_send(net_device_ctx->device_ctx, + packet); + if (ret == 0) { +- net->stats.tx_bytes += skb->len; ++ net->stats.tx_bytes += skb_length; + net->stats.tx_packets++; + } else { + kfree(packet); +diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c +index 7f1abb7c18f2..fbf7dcdc22b0 100644 +--- a/drivers/net/macvlan.c ++++ b/drivers/net/macvlan.c +@@ -709,6 +709,7 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev, + features, + mask); + features |= ALWAYS_ON_FEATURES; ++ features &= ~NETIF_F_NETNS_LOCAL; + + return features; + } +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index 3381c4f91a8c..0c6adaaf898c 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -112,17 +112,15 @@ out: + return err; + } + ++/* Requires RTNL */ + static int macvtap_set_queue(struct net_device *dev, struct file *file, + struct macvtap_queue *q) + { + struct macvlan_dev *vlan = netdev_priv(dev); +- int err = -EBUSY; + +- rtnl_lock(); + if (vlan->numqueues == MAX_MACVTAP_QUEUES) +- goto out; ++ return -EBUSY; + +- err = 0; + rcu_assign_pointer(q->vlan, vlan); + rcu_assign_pointer(vlan->taps[vlan->numvtaps], q); + sock_hold(&q->sk); +@@ -136,9 +134,7 @@ static int macvtap_set_queue(struct net_device *dev, struct file *file, + vlan->numvtaps++; + vlan->numqueues++; + +-out: +- rtnl_unlock(); +- return err; ++ return 0; + } + + static int macvtap_disable_queue(struct macvtap_queue *q) +@@ -454,11 +450,12 @@ static void macvtap_sock_destruct(struct sock *sk) + static int macvtap_open(struct inode *inode, struct file *file) + { + struct net *net = current->nsproxy->net_ns; +- struct net_device *dev = dev_get_by_macvtap_minor(iminor(inode)); ++ struct net_device *dev; + struct macvtap_queue *q; +- int err; ++ int err = -ENODEV; + +- err = -ENODEV; ++ rtnl_lock(); ++ dev = dev_get_by_macvtap_minor(iminor(inode)); + if (!dev) + goto out; + +@@ -498,6 +495,7 @@ out: + if (dev) + dev_put(dev); + ++ rtnl_unlock(); + return err; + } + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 26d8c29b59de..979fe433278c 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -647,7 +647,7 @@ static void team_notify_peers(struct team *team) + { + if (!team->notify_peers.count || !netif_running(team->dev)) + return; +- atomic_set(&team->notify_peers.count_pending, team->notify_peers.count); ++ atomic_add(team->notify_peers.count, &team->notify_peers.count_pending); + schedule_delayed_work(&team->notify_peers.dw, 0); + } + +@@ -687,7 +687,7 @@ static void team_mcast_rejoin(struct team *team) + { + if (!team->mcast_rejoin.count || !netif_running(team->dev)) + return; +- atomic_set(&team->mcast_rejoin.count_pending, team->mcast_rejoin.count); ++ atomic_add(team->mcast_rejoin.count, &team->mcast_rejoin.count_pending); + schedule_delayed_work(&team->mcast_rejoin.dw, 0); + } + +diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c +index 40ad25d7f28b..9b40532041cb 100644 +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -1334,7 +1334,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb) + } else if (vxlan->flags & VXLAN_F_L3MISS) { + union vxlan_addr ipa = { + .sin.sin_addr.s_addr = tip, +- .sa.sa_family = AF_INET, ++ .sin.sin_family = AF_INET, + }; + + vxlan_ip_miss(dev, &ipa); +@@ -1495,7 +1495,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb) + } else if (vxlan->flags & VXLAN_F_L3MISS) { + union vxlan_addr ipa = { + .sin6.sin6_addr = msg->target, +- .sa.sa_family = AF_INET6, ++ .sin6.sin6_family = AF_INET6, + }; + + vxlan_ip_miss(dev, &ipa); +@@ -1528,7 +1528,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb) + if (!n && (vxlan->flags & VXLAN_F_L3MISS)) { + union vxlan_addr ipa = { + .sin.sin_addr.s_addr = pip->daddr, +- .sa.sa_family = AF_INET, ++ .sin.sin_family = AF_INET, + }; + + vxlan_ip_miss(dev, &ipa); +@@ -1549,7 +1549,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb) + if (!n && (vxlan->flags & VXLAN_F_L3MISS)) { + union vxlan_addr ipa = { + .sin6.sin6_addr = pip6->daddr, +- .sa.sa_family = AF_INET6, ++ .sin6.sin6_family = AF_INET6, + }; + + vxlan_ip_miss(dev, &ipa); +diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c +index 0ff3e3624d4c..feda34404ed0 100644 +--- a/drivers/tty/serial/8250/8250_pci.c ++++ b/drivers/tty/serial/8250/8250_pci.c +@@ -1766,6 +1766,7 @@ pci_wch_ch353_setup(struct serial_private *priv, + #define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022 + #define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a + #define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e ++#define PCI_DEVICE_ID_INTEL_QRK_UART 0x0936 + + #define PCI_VENDOR_ID_SUNIX 0x1fd4 + #define PCI_DEVICE_ID_SUNIX_1999 0x1999 +@@ -1876,6 +1877,13 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { + .subdevice = PCI_ANY_ID, + .setup = byt_serial_setup, + }, ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_QRK_UART, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .setup = pci_default_setup, ++ }, + /* + * ITE + */ +@@ -2710,6 +2718,7 @@ enum pci_board_num_t { + pbn_ADDIDATA_PCIe_8_3906250, + pbn_ce4100_1_115200, + pbn_byt, ++ pbn_qrk, + pbn_omegapci, + pbn_NETMOS9900_2s_115200, + pbn_brcm_trumanage, +@@ -3456,6 +3465,12 @@ static struct pciserial_board pci_boards[] = { + .uart_offset = 0x80, + .reg_shift = 2, + }, ++ [pbn_qrk] = { ++ .flags = FL_BASE0, ++ .num_ports = 1, ++ .base_baud = 2764800, ++ .reg_shift = 2, ++ }, + [pbn_omegapci] = { + .flags = FL_BASE0, + .num_ports = 8, +@@ -5150,6 +5165,12 @@ static struct pci_device_id serial_pci_tbl[] = { + pbn_byt }, + + /* ++ * Intel Quark x1000 ++ */ ++ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_UART, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_qrk }, ++ /* + * Cronyx Omega PCI + */ + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_CRONYX_OMEGA, +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 263612ce1f62..445d62a4316a 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -1948,8 +1948,10 @@ void usb_set_device_state(struct usb_device *udev, + || new_state == USB_STATE_SUSPENDED) + ; /* No change to wakeup settings */ + else if (new_state == USB_STATE_CONFIGURED) +- wakeup = udev->actconfig->desc.bmAttributes +- & USB_CONFIG_ATT_WAKEUP; ++ wakeup = (udev->quirks & ++ USB_QUIRK_IGNORE_REMOTE_WAKEUP) ? 0 : ++ udev->actconfig->desc.bmAttributes & ++ USB_CONFIG_ATT_WAKEUP; + else + wakeup = 0; + } +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index 739ee8e8bdfd..5144d11d032c 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -160,6 +160,10 @@ static const struct usb_device_id usb_interface_quirk_list[] = { + { USB_VENDOR_AND_INTERFACE_INFO(0x046d, USB_CLASS_VIDEO, 1, 0), + .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* ASUS Base Station(T100) */ ++ { USB_DEVICE(0x0b05, 0x17e0), .driver_info = ++ USB_QUIRK_IGNORE_REMOTE_WAKEUP }, ++ + { } /* terminating entry must be last */ + }; + +diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c +index 7a109eae9b9a..85f5215871de 100644 +--- a/drivers/usb/musb/musb_dsps.c ++++ b/drivers/usb/musb/musb_dsps.c +@@ -707,6 +707,7 @@ static int dsps_suspend(struct device *dev) + struct musb *musb = platform_get_drvdata(glue->musb); + void __iomem *mbase = musb->ctrl_base; + ++ del_timer_sync(&glue->timer); + glue->context.control = dsps_readl(mbase, wrp->control); + glue->context.epintr = dsps_readl(mbase, wrp->epintr_set); + glue->context.coreintr = dsps_readl(mbase, wrp->coreintr_set); +@@ -732,6 +733,7 @@ static int dsps_resume(struct device *dev) + dsps_writel(mbase, wrp->mode, glue->context.mode); + dsps_writel(mbase, wrp->tx_mode, glue->context.tx_mode); + dsps_writel(mbase, wrp->rx_mode, glue->context.rx_mode); ++ setup_timer(&glue->timer, otg_timer, (unsigned long) musb); + + return 0; + } +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 330df5ce435b..63b2af2a87c0 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -122,6 +122,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ + { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */ ++ { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */ + { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ +@@ -155,6 +156,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ + { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ + { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ ++ { USB_DEVICE(0x1D6F, 0x0010) }, /* Seluxit ApS RF Dongle */ + { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */ + { USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */ + { USB_DEVICE(0x1FB9, 0x0100) }, /* Lake Shore Model 121 Current Source */ +diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h +index 72ba6f5cbc8d..2abe67bd4df8 100644 +--- a/include/linux/if_vlan.h ++++ b/include/linux/if_vlan.h +@@ -186,7 +186,6 @@ vlan_dev_get_egress_qos_mask(struct net_device *dev, u32 skprio) + } + + extern bool vlan_do_receive(struct sk_buff **skb); +-extern struct sk_buff *vlan_untag(struct sk_buff *skb); + + extern int vlan_vid_add(struct net_device *dev, __be16 proto, u16 vid); + extern void vlan_vid_del(struct net_device *dev, __be16 proto, u16 vid); +@@ -228,11 +227,6 @@ static inline bool vlan_do_receive(struct sk_buff **skb) + return false; + } + +-static inline struct sk_buff *vlan_untag(struct sk_buff *skb) +-{ +- return skb; +-} +- + static inline int vlan_vid_add(struct net_device *dev, __be16 proto, u16 vid) + { + return 0; +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 15ede6a823a6..ad8f85908a56 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -2458,6 +2458,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen); + void skb_scrub_packet(struct sk_buff *skb, bool xnet); + unsigned int skb_gso_transport_seglen(const struct sk_buff *skb); + struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features); ++struct sk_buff *skb_vlan_untag(struct sk_buff *skb); + + struct skb_checksum_ops { + __wsum (*update)(const void *mem, int len, __wsum wsum); +diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h +index 52f944dfe2fd..49587dc22f5d 100644 +--- a/include/linux/usb/quirks.h ++++ b/include/linux/usb/quirks.h +@@ -30,4 +30,7 @@ + descriptor */ + #define USB_QUIRK_DELAY_INIT 0x00000040 + ++/* device generates spurious wakeup, ignore remote wakeup capability */ ++#define USB_QUIRK_IGNORE_REMOTE_WAKEUP 0x00000200 ++ + #endif /* __LINUX_USB_QUIRKS_H */ +diff --git a/include/net/dst.h b/include/net/dst.h +index 77eb53fabfb0..909032821c37 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -466,6 +466,7 @@ void dst_init(void); + /* Flags for xfrm_lookup flags argument. */ + enum { + XFRM_LOOKUP_ICMP = 1 << 0, ++ XFRM_LOOKUP_QUEUE = 1 << 1, + }; + + struct flowi; +@@ -476,7 +477,16 @@ static inline struct dst_entry *xfrm_lookup(struct net *net, + int flags) + { + return dst_orig; +-} ++} ++ ++static inline struct dst_entry *xfrm_lookup_route(struct net *net, ++ struct dst_entry *dst_orig, ++ const struct flowi *fl, ++ struct sock *sk, ++ int flags) ++{ ++ return dst_orig; ++} + + static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) + { +@@ -488,6 +498,10 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, + const struct flowi *fl, struct sock *sk, + int flags); + ++struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig, ++ const struct flowi *fl, struct sock *sk, ++ int flags); ++ + /* skb attached with this dst needs transformation if dst->xfrm is valid */ + static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) + { +diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h +index c55aeed41ace..cf9272807788 100644 +--- a/include/net/inet_connection_sock.h ++++ b/include/net/inet_connection_sock.h +@@ -62,6 +62,7 @@ struct inet_connection_sock_af_ops { + void (*addr2sockaddr)(struct sock *sk, struct sockaddr *); + int (*bind_conflict)(const struct sock *sk, + const struct inet_bind_bucket *tb, bool relax); ++ void (*mtu_reduced)(struct sock *sk); + }; + + /** inet_connection_sock - INET connection oriented sock +diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h +index 4b7cd695e431..cfcbc3f627bd 100644 +--- a/include/net/sctp/command.h ++++ b/include/net/sctp/command.h +@@ -115,7 +115,7 @@ typedef enum { + * analysis of the state functions, but in reality just taken from + * thin air in the hopes othat we don't trigger a kernel panic. + */ +-#define SCTP_MAX_NUM_COMMANDS 14 ++#define SCTP_MAX_NUM_COMMANDS 20 + + typedef union { + __s32 i32; +diff --git a/include/net/sock.h b/include/net/sock.h +index 2f7bc435c93d..f66b2b19a6e4 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -969,7 +969,6 @@ struct proto { + struct sk_buff *skb); + + void (*release_cb)(struct sock *sk); +- void (*mtu_reduced)(struct sock *sk); + + /* Keeping track of sk's, looking them up, and port selection methods. */ + void (*hash)(struct sock *sk); +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 743accec6c76..1f0d8479e15f 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -453,6 +453,7 @@ const u8 *tcp_parse_md5sig_option(const struct tcphdr *th); + */ + + void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb); ++void tcp_v4_mtu_reduced(struct sock *sk); + int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb); + struct sock *tcp_create_openreq_child(struct sock *sk, + struct request_sock *req, +@@ -720,8 +721,10 @@ struct tcp_skb_cb { + #define TCPCB_SACKED_RETRANS 0x02 /* SKB retransmitted */ + #define TCPCB_LOST 0x04 /* SKB is lost */ + #define TCPCB_TAGBITS 0x07 /* All tag bits */ ++#define TCPCB_REPAIRED 0x10 /* SKB repaired (no skb_mstamp) */ + #define TCPCB_EVER_RETRANS 0x80 /* Ever retransmitted frame */ +-#define TCPCB_RETRANS (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS) ++#define TCPCB_RETRANS (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS| \ ++ TCPCB_REPAIRED) + + __u8 ip_dsfield; /* IPv4 tos or IPv6 dsfield */ + /* 1 byte hole */ +diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c +index 7e57135c7cc4..5d56e05d83dd 100644 +--- a/net/8021q/vlan_core.c ++++ b/net/8021q/vlan_core.c +@@ -106,59 +106,6 @@ u16 vlan_dev_vlan_id(const struct net_device *dev) + } + EXPORT_SYMBOL(vlan_dev_vlan_id); + +-static struct sk_buff *vlan_reorder_header(struct sk_buff *skb) +-{ +- if (skb_cow(skb, skb_headroom(skb)) < 0) { +- kfree_skb(skb); +- return NULL; +- } +- +- memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN); +- skb->mac_header += VLAN_HLEN; +- return skb; +-} +- +-struct sk_buff *vlan_untag(struct sk_buff *skb) +-{ +- struct vlan_hdr *vhdr; +- u16 vlan_tci; +- +- if (unlikely(vlan_tx_tag_present(skb))) { +- /* vlan_tci is already set-up so leave this for another time */ +- return skb; +- } +- +- skb = skb_share_check(skb, GFP_ATOMIC); +- if (unlikely(!skb)) +- goto err_free; +- +- if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) +- goto err_free; +- +- vhdr = (struct vlan_hdr *) skb->data; +- vlan_tci = ntohs(vhdr->h_vlan_TCI); +- __vlan_hwaccel_put_tag(skb, skb->protocol, vlan_tci); +- +- skb_pull_rcsum(skb, VLAN_HLEN); +- vlan_set_encap_proto(skb, vhdr); +- +- skb = vlan_reorder_header(skb); +- if (unlikely(!skb)) +- goto err_free; +- +- skb_reset_network_header(skb); +- skb_reset_transport_header(skb); +- skb_reset_mac_len(skb); +- +- return skb; +- +-err_free: +- kfree_skb(skb); +- return NULL; +-} +-EXPORT_SYMBOL(vlan_untag); +- +- + /* + * vlan info and vid list + */ +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index f2d254b69353..4acfc3eef56a 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -302,6 +302,9 @@ struct br_input_skb_cb { + int igmp; + int mrouters_only; + #endif ++#ifdef CONFIG_BRIDGE_VLAN_FILTERING ++ bool vlan_filtered; ++#endif + }; + + #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) +diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c +index b1c637208497..e1bd2539f9dc 100644 +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -125,7 +125,8 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br, + { + u16 vid; + +- if (!br->vlan_enabled) ++ /* If this packet was not filtered at input, let it pass */ ++ if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) + goto out; + + /* Vlan filter table must be configured at this point. The +@@ -163,8 +164,10 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, + /* If VLAN filtering is disabled on the bridge, all packets are + * permitted. + */ +- if (!br->vlan_enabled) ++ if (!br->vlan_enabled) { ++ BR_INPUT_SKB_CB(skb)->vlan_filtered = false; + return true; ++ } + + /* If there are no vlan in the permitted list, all packets are + * rejected. +@@ -172,6 +175,8 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, + if (!v) + goto drop; + ++ BR_INPUT_SKB_CB(skb)->vlan_filtered = true; ++ + /* If vlan tx offload is disabled on bridge device and frame was + * sent from vlan device on the bridge device, it does not have + * HW accelerated vlan tag. +@@ -179,7 +184,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, + if (unlikely(!vlan_tx_tag_present(skb) && + (skb->protocol == htons(ETH_P_8021Q) || + skb->protocol == htons(ETH_P_8021AD)))) { +- skb = vlan_untag(skb); ++ skb = skb_vlan_untag(skb); + if (unlikely(!skb)) + return false; + } +@@ -228,7 +233,8 @@ bool br_allowed_egress(struct net_bridge *br, + { + u16 vid; + +- if (!br->vlan_enabled) ++ /* If this packet was not filtered at input, let it pass */ ++ if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) + return true; + + if (!v) +@@ -247,6 +253,7 @@ bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid) + struct net_bridge *br = p->br; + struct net_port_vlans *v; + ++ /* If filtering was disabled at input, let it pass. */ + if (!br->vlan_enabled) + return true; + +diff --git a/net/core/dev.c b/net/core/dev.c +index 37bddf729e77..3ed11a555834 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -3554,7 +3554,7 @@ another_round: + + if (skb->protocol == cpu_to_be16(ETH_P_8021Q) || + skb->protocol == cpu_to_be16(ETH_P_8021AD)) { +- skb = vlan_untag(skb); ++ skb = skb_vlan_untag(skb); + if (unlikely(!skb)) + goto unlock; + } +diff --git a/net/core/netpoll.c b/net/core/netpoll.c +index df9e6b1a9759..723fa7da8025 100644 +--- a/net/core/netpoll.c ++++ b/net/core/netpoll.c +@@ -788,7 +788,7 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) + } + + if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { +- skb = vlan_untag(skb); ++ skb = skb_vlan_untag(skb); + if (unlikely(!skb)) + goto out; + } +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index aef1500ebc05..b0db904f083d 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -799,7 +799,8 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev, + (nla_total_size(sizeof(struct ifla_vf_mac)) + + nla_total_size(sizeof(struct ifla_vf_vlan)) + + nla_total_size(sizeof(struct ifla_vf_tx_rate)) + +- nla_total_size(sizeof(struct ifla_vf_spoofchk))); ++ nla_total_size(sizeof(struct ifla_vf_spoofchk)) + ++ nla_total_size(sizeof(struct ifla_vf_link_state))); + return size; + } else + return 0; +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index 8f6391bbf509..baf6fc457df9 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -62,6 +62,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -3139,6 +3140,9 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) + NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE_STOLEN_HEAD; + goto done; + } ++ /* switch back to head shinfo */ ++ pinfo = skb_shinfo(p); ++ + if (pinfo->frag_list) + goto merge; + if (skb_gro_len(p) != pinfo->gso_size) +@@ -3963,3 +3967,55 @@ unsigned int skb_gso_transport_seglen(const struct sk_buff *skb) + return shinfo->gso_size; + } + EXPORT_SYMBOL_GPL(skb_gso_transport_seglen); ++ ++static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb) ++{ ++ if (skb_cow(skb, skb_headroom(skb)) < 0) { ++ kfree_skb(skb); ++ return NULL; ++ } ++ ++ memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN); ++ skb->mac_header += VLAN_HLEN; ++ return skb; ++} ++ ++struct sk_buff *skb_vlan_untag(struct sk_buff *skb) ++{ ++ struct vlan_hdr *vhdr; ++ u16 vlan_tci; ++ ++ if (unlikely(vlan_tx_tag_present(skb))) { ++ /* vlan_tci is already set-up so leave this for another time */ ++ return skb; ++ } ++ ++ skb = skb_share_check(skb, GFP_ATOMIC); ++ if (unlikely(!skb)) ++ goto err_free; ++ ++ if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) ++ goto err_free; ++ ++ vhdr = (struct vlan_hdr *)skb->data; ++ vlan_tci = ntohs(vhdr->h_vlan_TCI); ++ __vlan_hwaccel_put_tag(skb, skb->protocol, vlan_tci); ++ ++ skb_pull_rcsum(skb, VLAN_HLEN); ++ vlan_set_encap_proto(skb, vhdr); ++ ++ skb = skb_reorder_vlan_header(skb); ++ if (unlikely(!skb)) ++ goto err_free; ++ ++ skb_reset_network_header(skb); ++ skb_reset_transport_header(skb); ++ skb_reset_mac_len(skb); ++ ++ return skb; ++ ++err_free: ++ kfree_skb(skb); ++ return NULL; ++} ++EXPORT_SYMBOL(skb_vlan_untag); +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index ca5a01ed8ed6..487bb6252520 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -2268,9 +2268,9 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4, + return rt; + + if (flp4->flowi4_proto) +- rt = (struct rtable *) xfrm_lookup(net, &rt->dst, +- flowi4_to_flowi(flp4), +- sk, 0); ++ rt = (struct rtable *)xfrm_lookup_route(net, &rt->dst, ++ flowi4_to_flowi(flp4), ++ sk, 0); + + return rt; + } +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index b48fba0aaa92..f7d71ec72a47 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -1175,13 +1175,6 @@ new_segment: + goto wait_for_memory; + + /* +- * All packets are restored as if they have +- * already been sent. +- */ +- if (tp->repair) +- TCP_SKB_CB(skb)->when = tcp_time_stamp; +- +- /* + * Check whether we can use HW checksum. + */ + if (sk->sk_route_caps & NETIF_F_ALL_CSUM) +@@ -1190,6 +1183,13 @@ new_segment: + skb_entail(sk, skb); + copy = size_goal; + max = size_goal; ++ ++ /* All packets are restored as if they have ++ * already been sent. skb_mstamp isn't set to ++ * avoid wrong rtt estimation. ++ */ ++ if (tp->repair) ++ TCP_SKB_CB(skb)->sacked |= TCPCB_REPAIRED; + } + + /* Try to append data to the end of skb. */ +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 3898694d0300..22917918fa80 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -2678,7 +2678,6 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack) + */ + static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) + { +- struct inet_connection_sock *icsk = inet_csk(sk); + struct tcp_sock *tp = tcp_sk(sk); + bool recovered = !before(tp->snd_una, tp->high_seq); + +@@ -2704,12 +2703,9 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) + + if (recovered) { + /* F-RTO RFC5682 sec 3.1 step 2.a and 1st part of step 3.a */ +- icsk->icsk_retransmits = 0; + tcp_try_undo_recovery(sk); + return; + } +- if (flag & FLAG_DATA_ACKED) +- icsk->icsk_retransmits = 0; + if (tcp_is_reno(tp)) { + /* A Reno DUPACK means new data in F-RTO step 2.b above are + * delivered. Lower inflight to clock out (re)tranmissions. +@@ -3398,8 +3394,10 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) + icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) + tcp_rearm_rto(sk); + +- if (after(ack, prior_snd_una)) ++ if (after(ack, prior_snd_una)) { + flag |= FLAG_SND_UNA_ADVANCED; ++ icsk->icsk_retransmits = 0; ++ } + + prior_fackets = tp->fackets_out; + prior_in_flight = tcp_packets_in_flight(tp); +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index 1e4eac779f51..a782d5be132e 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -269,7 +269,7 @@ EXPORT_SYMBOL(tcp_v4_connect); + * It can be called through tcp_release_cb() if socket was owned by user + * at the time tcp_v4_err() was called to handle ICMP message. + */ +-static void tcp_v4_mtu_reduced(struct sock *sk) ++void tcp_v4_mtu_reduced(struct sock *sk) + { + struct dst_entry *dst; + struct inet_sock *inet = inet_sk(sk); +@@ -300,6 +300,7 @@ static void tcp_v4_mtu_reduced(struct sock *sk) + tcp_simple_retransmit(sk); + } /* else let the usual retransmit timer handle it */ + } ++EXPORT_SYMBOL(tcp_v4_mtu_reduced); + + static void do_redirect(struct sk_buff *skb, struct sock *sk) + { +@@ -2117,6 +2118,7 @@ const struct inet_connection_sock_af_ops ipv4_specific = { + .compat_setsockopt = compat_ip_setsockopt, + .compat_getsockopt = compat_ip_getsockopt, + #endif ++ .mtu_reduced = tcp_v4_mtu_reduced, + }; + EXPORT_SYMBOL(ipv4_specific); + +@@ -2736,7 +2738,6 @@ struct proto tcp_prot = { + .sendpage = tcp_sendpage, + .backlog_rcv = tcp_v4_do_rcv, + .release_cb = tcp_release_cb, +- .mtu_reduced = tcp_v4_mtu_reduced, + .hash = inet_hash, + .unhash = inet_unhash, + .get_port = inet_csk_get_port, +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index b3d1addd816b..91b98e5a17aa 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -787,7 +787,7 @@ void tcp_release_cb(struct sock *sk) + __sock_put(sk); + } + if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) { +- sk->sk_prot->mtu_reduced(sk); ++ inet_csk(sk)->icsk_af_ops->mtu_reduced(sk); + __sock_put(sk); + } + } +@@ -1876,8 +1876,11 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, + tso_segs = tcp_init_tso_segs(sk, skb, mss_now); + BUG_ON(!tso_segs); + +- if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE) ++ if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE) { ++ /* "when" is used as a start point for the retransmit timer */ ++ TCP_SKB_CB(skb)->when = tcp_time_stamp; + goto repair; /* Skip network transmission */ ++ } + + cwnd_quota = tcp_cwnd_test(tp, skb); + if (!cwnd_quota) { +@@ -2066,9 +2069,7 @@ void tcp_send_loss_probe(struct sock *sk) + if (WARN_ON(!skb || !tcp_skb_pcount(skb))) + goto rearm_timer; + +- /* Probe with zero data doesn't trigger fast recovery. */ +- if (skb->len > 0) +- err = __tcp_retransmit_skb(sk, skb); ++ err = __tcp_retransmit_skb(sk, skb); + + /* Record snd_nxt for loss detection. */ + if (likely(!err)) +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index 6c7fa0853fc7..3f0ec063d7f8 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -1684,14 +1684,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) + addrconf_mod_dad_work(ifp, 0); + } + +-/* Join to solicited addr multicast group. */ +- ++/* Join to solicited addr multicast group. ++ * caller must hold RTNL */ + void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) + { + struct in6_addr maddr; + +- ASSERT_RTNL(); +- + if (dev->flags&(IFF_LOOPBACK|IFF_NOARP)) + return; + +@@ -1699,12 +1697,11 @@ void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) + ipv6_dev_mc_inc(dev, &maddr); + } + ++/* caller must hold RTNL */ + void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) + { + struct in6_addr maddr; + +- ASSERT_RTNL(); +- + if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP)) + return; + +@@ -1712,12 +1709,11 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) + __ipv6_dev_mc_dec(idev, &maddr); + } + ++/* caller must hold RTNL */ + static void addrconf_join_anycast(struct inet6_ifaddr *ifp) + { + struct in6_addr addr; + +- ASSERT_RTNL(); +- + if (ifp->prefix_len >= 127) /* RFC 6164 */ + return; + ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); +@@ -1726,12 +1722,11 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp) + ipv6_dev_ac_inc(ifp->idev->dev, &addr); + } + ++/* caller must hold RTNL */ + static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) + { + struct in6_addr addr; + +- ASSERT_RTNL(); +- + if (ifp->prefix_len >= 127) /* RFC 6164 */ + return; + ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); +diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c +index 210183244689..ff2de7d9d8e6 100644 +--- a/net/ipv6/anycast.c ++++ b/net/ipv6/anycast.c +@@ -77,6 +77,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr) + pac->acl_next = NULL; + pac->acl_addr = *addr; + ++ rtnl_lock(); + rcu_read_lock(); + if (ifindex == 0) { + struct rt6_info *rt; +@@ -137,6 +138,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr) + + error: + rcu_read_unlock(); ++ rtnl_unlock(); + if (pac) + sock_kfree_s(sk, pac, sizeof(*pac)); + return err; +@@ -171,11 +173,13 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) + + spin_unlock_bh(&ipv6_sk_ac_lock); + ++ rtnl_lock(); + rcu_read_lock(); + dev = dev_get_by_index_rcu(net, pac->acl_ifindex); + if (dev) + ipv6_dev_ac_dec(dev, &pac->acl_addr); + rcu_read_unlock(); ++ rtnl_unlock(); + + sock_kfree_s(sk, pac, sizeof(*pac)); + return 0; +@@ -198,6 +202,7 @@ void ipv6_sock_ac_close(struct sock *sk) + spin_unlock_bh(&ipv6_sk_ac_lock); + + prev_index = 0; ++ rtnl_lock(); + rcu_read_lock(); + while (pac) { + struct ipv6_ac_socklist *next = pac->acl_next; +@@ -212,6 +217,7 @@ void ipv6_sock_ac_close(struct sock *sk) + pac = next; + } + rcu_read_unlock(); ++ rtnl_unlock(); + } + + static void aca_put(struct ifacaddr6 *ac) +@@ -233,6 +239,8 @@ int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr) + struct rt6_info *rt; + int err; + ++ ASSERT_RTNL(); ++ + idev = in6_dev_get(dev); + + if (idev == NULL) +@@ -302,6 +310,8 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr) + { + struct ifacaddr6 *aca, *prev_aca; + ++ ASSERT_RTNL(); ++ + write_lock_bh(&idev->lock); + prev_aca = NULL; + for (aca = idev->ac_list; aca; aca = aca->aca_next) { +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index 2465d18e8a26..cb57aa862177 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -787,7 +787,7 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev) + encap_limit = t->parms.encap_limit; + + memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); +- fl6.flowi6_proto = IPPROTO_IPIP; ++ fl6.flowi6_proto = IPPROTO_GRE; + + dsfield = ipv4_get_dsfield(iph); + +@@ -837,7 +837,7 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev) + encap_limit = t->parms.encap_limit; + + memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); +- fl6.flowi6_proto = IPPROTO_IPV6; ++ fl6.flowi6_proto = IPPROTO_GRE; + + dsfield = ipv6_get_dsfield(ipv6h); + if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 073e5a6fc631..12f7ef0f243a 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1008,7 +1008,7 @@ struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, + if (final_dst) + fl6->daddr = *final_dst; + +- return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); ++ return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); + } + EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow); + +@@ -1040,7 +1040,7 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, + if (final_dst) + fl6->daddr = *final_dst; + +- return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); ++ return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); + } + EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); + +diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c +index 08b367c6b9cf..761e4586ab5f 100644 +--- a/net/ipv6/mcast.c ++++ b/net/ipv6/mcast.c +@@ -172,6 +172,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) + mc_lst->next = NULL; + mc_lst->addr = *addr; + ++ rtnl_lock(); + rcu_read_lock(); + if (ifindex == 0) { + struct rt6_info *rt; +@@ -185,6 +186,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) + + if (dev == NULL) { + rcu_read_unlock(); ++ rtnl_unlock(); + sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); + return -ENODEV; + } +@@ -202,6 +204,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) + + if (err) { + rcu_read_unlock(); ++ rtnl_unlock(); + sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); + return err; + } +@@ -212,6 +215,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) + spin_unlock(&ipv6_sk_mc_lock); + + rcu_read_unlock(); ++ rtnl_unlock(); + + return 0; + } +@@ -229,6 +233,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) + if (!ipv6_addr_is_multicast(addr)) + return -EINVAL; + ++ rtnl_lock(); + spin_lock(&ipv6_sk_mc_lock); + for (lnk = &np->ipv6_mc_list; + (mc_lst = rcu_dereference_protected(*lnk, +@@ -252,12 +257,15 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) + } else + (void) ip6_mc_leave_src(sk, mc_lst, NULL); + rcu_read_unlock(); ++ rtnl_unlock(); ++ + atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc); + kfree_rcu(mc_lst, rcu); + return 0; + } + } + spin_unlock(&ipv6_sk_mc_lock); ++ rtnl_unlock(); + + return -EADDRNOTAVAIL; + } +@@ -302,6 +310,7 @@ void ipv6_sock_mc_close(struct sock *sk) + if (!rcu_access_pointer(np->ipv6_mc_list)) + return; + ++ rtnl_lock(); + spin_lock(&ipv6_sk_mc_lock); + while ((mc_lst = rcu_dereference_protected(np->ipv6_mc_list, + lockdep_is_held(&ipv6_sk_mc_lock))) != NULL) { +@@ -328,6 +337,7 @@ void ipv6_sock_mc_close(struct sock *sk) + spin_lock(&ipv6_sk_mc_lock); + } + spin_unlock(&ipv6_sk_mc_lock); ++ rtnl_unlock(); + } + + int ip6_mc_source(int add, int omode, struct sock *sk, +@@ -845,6 +855,8 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr) + struct ifmcaddr6 *mc; + struct inet6_dev *idev; + ++ ASSERT_RTNL(); ++ + /* we need to take a reference on idev */ + idev = in6_dev_get(dev); + +@@ -916,6 +928,8 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr) + { + struct ifmcaddr6 *ma, **map; + ++ ASSERT_RTNL(); ++ + write_lock_bh(&idev->lock); + for (map = &idev->mc_list; (ma=*map) != NULL; map = &ma->next) { + if (ipv6_addr_equal(&ma->mca_addr, addr)) { +diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c +index fe548ba72687..b12b11b123ff 100644 +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -101,19 +101,19 @@ static struct ip_tunnel *ipip6_tunnel_lookup(struct net *net, + for_each_ip_tunnel_rcu(t, sitn->tunnels_r_l[h0 ^ h1]) { + if (local == t->parms.iph.saddr && + remote == t->parms.iph.daddr && +- (!dev || !t->parms.link || dev->iflink == t->parms.link) && ++ (!dev || !t->parms.link || dev->ifindex == t->parms.link) && + (t->dev->flags & IFF_UP)) + return t; + } + for_each_ip_tunnel_rcu(t, sitn->tunnels_r[h0]) { + if (remote == t->parms.iph.daddr && +- (!dev || !t->parms.link || dev->iflink == t->parms.link) && ++ (!dev || !t->parms.link || dev->ifindex == t->parms.link) && + (t->dev->flags & IFF_UP)) + return t; + } + for_each_ip_tunnel_rcu(t, sitn->tunnels_l[h1]) { + if (local == t->parms.iph.saddr && +- (!dev || !t->parms.link || dev->iflink == t->parms.link) && ++ (!dev || !t->parms.link || dev->ifindex == t->parms.link) && + (t->dev->flags & IFF_UP)) + return t; + } +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 889079b2ea85..a4f890dd223a 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1668,6 +1668,7 @@ static const struct inet_connection_sock_af_ops ipv6_specific = { + .compat_setsockopt = compat_ipv6_setsockopt, + .compat_getsockopt = compat_ipv6_getsockopt, + #endif ++ .mtu_reduced = tcp_v6_mtu_reduced, + }; + + #ifdef CONFIG_TCP_MD5SIG +@@ -1699,6 +1700,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = { + .compat_setsockopt = compat_ipv6_setsockopt, + .compat_getsockopt = compat_ipv6_getsockopt, + #endif ++ .mtu_reduced = tcp_v4_mtu_reduced, + }; + + #ifdef CONFIG_TCP_MD5SIG +@@ -1935,7 +1937,6 @@ struct proto tcpv6_prot = { + .sendpage = tcp_sendpage, + .backlog_rcv = tcp_v6_do_rcv, + .release_cb = tcp_release_cb, +- .mtu_reduced = tcp_v6_mtu_reduced, + .hash = tcp_v6_hash, + .unhash = inet_unhash, + .get_port = inet_csk_get_port, +diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c +index 1e05bbde47ba..da8d067d6107 100644 +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -758,7 +758,8 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, + /* If PMTU discovery was enabled, use the MTU that was discovered */ + dst = sk_dst_get(tunnel->sock); + if (dst != NULL) { +- u32 pmtu = dst_mtu(__sk_dst_get(tunnel->sock)); ++ u32 pmtu = dst_mtu(dst); ++ + if (pmtu != 0) + session->mtu = session->mru = pmtu - + PPPOL2TP_HEADER_OVERHEAD; +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 0dfe894afd48..c375d731587f 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -205,7 +205,7 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb, + nskb->protocol = htons((u16) sk->sk_protocol); + nskb->pkt_type = netlink_is_kernel(sk) ? + PACKET_KERNEL : PACKET_USER; +- ++ skb_reset_network_header(nskb); + ret = dev_queue_xmit(nskb); + if (unlikely(ret > 0)) + ret = net_xmit_errno(ret); +diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c +index 2c77e7b1a913..600c7646b3d3 100644 +--- a/net/openvswitch/actions.c ++++ b/net/openvswitch/actions.c +@@ -42,6 +42,9 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, + + static int make_writable(struct sk_buff *skb, int write_len) + { ++ if (!pskb_may_pull(skb, write_len)) ++ return -ENOMEM; ++ + if (!skb_cloned(skb) || skb_clone_writable(skb, write_len)) + return 0; + +@@ -70,6 +73,8 @@ static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci) + + vlan_set_encap_proto(skb, vhdr); + skb->mac_header += VLAN_HLEN; ++ if (skb_network_offset(skb) < ETH_HLEN) ++ skb_set_network_header(skb, ETH_HLEN); + skb_reset_mac_len(skb); + + return 0; +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 48a6a93db296..48b181797d7b 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -635,6 +635,7 @@ static void init_prb_bdqc(struct packet_sock *po, + p1->tov_in_jiffies = msecs_to_jiffies(p1->retire_blk_tov); + p1->blk_sizeof_priv = req_u->req3.tp_sizeof_priv; + ++ p1->max_frame_len = p1->kblk_size - BLK_PLUS_PRIV(p1->blk_sizeof_priv); + prb_init_ft_ops(p1, req_u); + prb_setup_retire_blk_timer(po, tx_ring); + prb_open_block(p1, pbd); +@@ -1946,6 +1947,18 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, + if ((int)snaplen < 0) + snaplen = 0; + } ++ } else if (unlikely(macoff + snaplen > ++ GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len)) { ++ u32 nval; ++ ++ nval = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len - macoff; ++ pr_err_once("tpacket_rcv: packet too big, clamped from %u to %u. macoff=%u\n", ++ snaplen, nval, macoff); ++ snaplen = nval; ++ if (unlikely((int)snaplen < 0)) { ++ snaplen = 0; ++ macoff = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len; ++ } + } + spin_lock(&sk->sk_receive_queue.lock); + h.raw = packet_current_rx_frame(po, skb, +@@ -3779,6 +3792,10 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, + goto out; + if (unlikely(req->tp_block_size & (PAGE_SIZE - 1))) + goto out; ++ if (po->tp_version >= TPACKET_V3 && ++ (int)(req->tp_block_size - ++ BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0) ++ goto out; + if (unlikely(req->tp_frame_size < po->tp_hdrlen + + po->tp_reserve)) + goto out; +diff --git a/net/packet/internal.h b/net/packet/internal.h +index eb9580a6b25f..cdddf6a30399 100644 +--- a/net/packet/internal.h ++++ b/net/packet/internal.h +@@ -29,6 +29,7 @@ struct tpacket_kbdq_core { + char *pkblk_start; + char *pkblk_end; + int kblk_size; ++ unsigned int max_frame_len; + unsigned int knum_blocks; + uint64_t knxt_seq_num; + char *prev; +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index 5170a1ff95a1..7194fe8589b0 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -1775,9 +1775,22 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(struct net *net, + /* Update the content of current association. */ + sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); + sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); +- sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, +- SCTP_STATE(SCTP_STATE_ESTABLISHED)); +- sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); ++ if (sctp_state(asoc, SHUTDOWN_PENDING) && ++ (sctp_sstate(asoc->base.sk, CLOSING) || ++ sock_flag(asoc->base.sk, SOCK_DEAD))) { ++ /* if were currently in SHUTDOWN_PENDING, but the socket ++ * has been closed by user, don't transition to ESTABLISHED. ++ * Instead trigger SHUTDOWN bundled with COOKIE_ACK. ++ */ ++ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); ++ return sctp_sf_do_9_2_start_shutdown(net, ep, asoc, ++ SCTP_ST_CHUNK(0), NULL, ++ commands); ++ } else { ++ sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, ++ SCTP_STATE(SCTP_STATE_ESTABLISHED)); ++ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); ++ } + return SCTP_DISPOSITION_CONSUME; + + nomem_ev: +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 1d5c7bf29938..59cf325f2772 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -41,6 +41,11 @@ + + static struct dst_entry *xfrm_policy_sk_bundles; + ++struct xfrm_flo { ++ struct dst_entry *dst_orig; ++ u8 flags; ++}; ++ + static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock); + static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO] + __read_mostly; +@@ -1889,13 +1894,14 @@ static int xdst_queue_output(struct sk_buff *skb) + } + + static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, +- struct dst_entry *dst, ++ struct xfrm_flo *xflo, + const struct flowi *fl, + int num_xfrms, + u16 family) + { + int err; + struct net_device *dev; ++ struct dst_entry *dst; + struct dst_entry *dst1; + struct xfrm_dst *xdst; + +@@ -1903,9 +1909,12 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, + if (IS_ERR(xdst)) + return xdst; + +- if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0) ++ if (!(xflo->flags & XFRM_LOOKUP_QUEUE) || ++ net->xfrm.sysctl_larval_drop || ++ num_xfrms <= 0) + return xdst; + ++ dst = xflo->dst_orig; + dst1 = &xdst->u.dst; + dst_hold(dst); + xdst->route = dst; +@@ -1947,7 +1956,7 @@ static struct flow_cache_object * + xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir, + struct flow_cache_object *oldflo, void *ctx) + { +- struct dst_entry *dst_orig = (struct dst_entry *)ctx; ++ struct xfrm_flo *xflo = (struct xfrm_flo *)ctx; + struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; + struct xfrm_dst *xdst, *new_xdst; + int num_pols = 0, num_xfrms = 0, i, err, pol_dead; +@@ -1988,7 +1997,8 @@ xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir, + goto make_dummy_bundle; + } + +- new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family, dst_orig); ++ new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family, ++ xflo->dst_orig); + if (IS_ERR(new_xdst)) { + err = PTR_ERR(new_xdst); + if (err != -EAGAIN) +@@ -2022,7 +2032,7 @@ make_dummy_bundle: + /* We found policies, but there's no bundles to instantiate: + * either because the policy blocks, has no transformations or + * we could not build template (no xfrm_states).*/ +- xdst = xfrm_create_dummy_bundle(net, dst_orig, fl, num_xfrms, family); ++ xdst = xfrm_create_dummy_bundle(net, xflo, fl, num_xfrms, family); + if (IS_ERR(xdst)) { + xfrm_pols_put(pols, num_pols); + return ERR_CAST(xdst); +@@ -2121,13 +2131,18 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, + } + + if (xdst == NULL) { ++ struct xfrm_flo xflo; ++ ++ xflo.dst_orig = dst_orig; ++ xflo.flags = flags; ++ + /* To accelerate a bit... */ + if ((dst_orig->flags & DST_NOXFRM) || + !net->xfrm.policy_count[XFRM_POLICY_OUT]) + goto nopol; + + flo = flow_cache_lookup(net, fl, family, dir, +- xfrm_bundle_lookup, dst_orig); ++ xfrm_bundle_lookup, &xflo); + if (flo == NULL) + goto nopol; + if (IS_ERR(flo)) { +@@ -2155,7 +2170,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, + xfrm_pols_put(pols, drop_pols); + XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); + +- return make_blackhole(net, family, dst_orig); ++ return ERR_PTR(-EREMOTE); + } + + err = -EAGAIN; +@@ -2212,6 +2227,23 @@ dropdst: + } + EXPORT_SYMBOL(xfrm_lookup); + ++/* Callers of xfrm_lookup_route() must ensure a call to dst_output(). ++ * Otherwise we may send out blackholed packets. ++ */ ++struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig, ++ const struct flowi *fl, ++ struct sock *sk, int flags) ++{ ++ struct dst_entry *dst = xfrm_lookup(net, dst_orig, fl, sk, ++ flags | XFRM_LOOKUP_QUEUE); ++ ++ if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE) ++ return make_blackhole(net, dst_orig->ops->family, dst_orig); ++ ++ return dst; ++} ++EXPORT_SYMBOL(xfrm_lookup_route); ++ + static inline int + xfrm_secpath_reject(int idx, struct sk_buff *skb, const struct flowi *fl) + { +@@ -2477,7 +2509,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) + + skb_dst_force(skb); + +- dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, 0); ++ dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, XFRM_LOOKUP_QUEUE); + if (IS_ERR(dst)) { + res = 0; + dst = NULL; diff --git a/patch/kernel/cubox-default/patch-3.14.22-23.patch b/patch/kernel/cubox-default/patch-3.14.22-23.patch new file mode 100644 index 000000000..62db8b47c --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.22-23.patch @@ -0,0 +1,5877 @@ +diff --git a/Documentation/lzo.txt b/Documentation/lzo.txt +new file mode 100644 +index 000000000000..ea45dd3901e3 +--- /dev/null ++++ b/Documentation/lzo.txt +@@ -0,0 +1,164 @@ ++ ++LZO stream format as understood by Linux's LZO decompressor ++=========================================================== ++ ++Introduction ++ ++ This is not a specification. No specification seems to be publicly available ++ for the LZO stream format. This document describes what input format the LZO ++ decompressor as implemented in the Linux kernel understands. The file subject ++ of this analysis is lib/lzo/lzo1x_decompress_safe.c. No analysis was made on ++ the compressor nor on any other implementations though it seems likely that ++ the format matches the standard one. The purpose of this document is to ++ better understand what the code does in order to propose more efficient fixes ++ for future bug reports. ++ ++Description ++ ++ The stream is composed of a series of instructions, operands, and data. The ++ instructions consist in a few bits representing an opcode, and bits forming ++ the operands for the instruction, whose size and position depend on the ++ opcode and on the number of literals copied by previous instruction. The ++ operands are used to indicate : ++ ++ - a distance when copying data from the dictionary (past output buffer) ++ - a length (number of bytes to copy from dictionary) ++ - the number of literals to copy, which is retained in variable "state" ++ as a piece of information for next instructions. ++ ++ Optionally depending on the opcode and operands, extra data may follow. These ++ extra data can be a complement for the operand (eg: a length or a distance ++ encoded on larger values), or a literal to be copied to the output buffer. ++ ++ The first byte of the block follows a different encoding from other bytes, it ++ seems to be optimized for literal use only, since there is no dictionary yet ++ prior to that byte. ++ ++ Lengths are always encoded on a variable size starting with a small number ++ of bits in the operand. If the number of bits isn't enough to represent the ++ length, up to 255 may be added in increments by consuming more bytes with a ++ rate of at most 255 per extra byte (thus the compression ratio cannot exceed ++ around 255:1). The variable length encoding using #bits is always the same : ++ ++ length = byte & ((1 << #bits) - 1) ++ if (!length) { ++ length = ((1 << #bits) - 1) ++ length += 255*(number of zero bytes) ++ length += first-non-zero-byte ++ } ++ length += constant (generally 2 or 3) ++ ++ For references to the dictionary, distances are relative to the output ++ pointer. Distances are encoded using very few bits belonging to certain ++ ranges, resulting in multiple copy instructions using different encodings. ++ Certain encodings involve one extra byte, others involve two extra bytes ++ forming a little-endian 16-bit quantity (marked LE16 below). ++ ++ After any instruction except the large literal copy, 0, 1, 2 or 3 literals ++ are copied before starting the next instruction. The number of literals that ++ were copied may change the meaning and behaviour of the next instruction. In ++ practice, only one instruction needs to know whether 0, less than 4, or more ++ literals were copied. This is the information stored in the variable ++ in this implementation. This number of immediate literals to be copied is ++ generally encoded in the last two bits of the instruction but may also be ++ taken from the last two bits of an extra operand (eg: distance). ++ ++ End of stream is declared when a block copy of distance 0 is seen. Only one ++ instruction may encode this distance (0001HLLL), it takes one LE16 operand ++ for the distance, thus requiring 3 bytes. ++ ++ IMPORTANT NOTE : in the code some length checks are missing because certain ++ instructions are called under the assumption that a certain number of bytes ++ follow because it has already been garanteed before parsing the instructions. ++ They just have to "refill" this credit if they consume extra bytes. This is ++ an implementation design choice independant on the algorithm or encoding. ++ ++Byte sequences ++ ++ First byte encoding : ++ ++ 0..17 : follow regular instruction encoding, see below. It is worth ++ noting that codes 16 and 17 will represent a block copy from ++ the dictionary which is empty, and that they will always be ++ invalid at this place. ++ ++ 18..21 : copy 0..3 literals ++ state = (byte - 17) = 0..3 [ copy literals ] ++ skip byte ++ ++ 22..255 : copy literal string ++ length = (byte - 17) = 4..238 ++ state = 4 [ don't copy extra literals ] ++ skip byte ++ ++ Instruction encoding : ++ ++ 0 0 0 0 X X X X (0..15) ++ Depends on the number of literals copied by the last instruction. ++ If last instruction did not copy any literal (state == 0), this ++ encoding will be a copy of 4 or more literal, and must be interpreted ++ like this : ++ ++ 0 0 0 0 L L L L (0..15) : copy long literal string ++ length = 3 + (L ?: 15 + (zero_bytes * 255) + non_zero_byte) ++ state = 4 (no extra literals are copied) ++ ++ If last instruction used to copy between 1 to 3 literals (encoded in ++ the instruction's opcode or distance), the instruction is a copy of a ++ 2-byte block from the dictionary within a 1kB distance. It is worth ++ noting that this instruction provides little savings since it uses 2 ++ bytes to encode a copy of 2 other bytes but it encodes the number of ++ following literals for free. It must be interpreted like this : ++ ++ 0 0 0 0 D D S S (0..15) : copy 2 bytes from <= 1kB distance ++ length = 2 ++ state = S (copy S literals after this block) ++ Always followed by exactly one byte : H H H H H H H H ++ distance = (H << 2) + D + 1 ++ ++ If last instruction used to copy 4 or more literals (as detected by ++ state == 4), the instruction becomes a copy of a 3-byte block from the ++ dictionary from a 2..3kB distance, and must be interpreted like this : ++ ++ 0 0 0 0 D D S S (0..15) : copy 3 bytes from 2..3 kB distance ++ length = 3 ++ state = S (copy S literals after this block) ++ Always followed by exactly one byte : H H H H H H H H ++ distance = (H << 2) + D + 2049 ++ ++ 0 0 0 1 H L L L (16..31) ++ Copy of a block within 16..48kB distance (preferably less than 10B) ++ length = 2 + (L ?: 7 + (zero_bytes * 255) + non_zero_byte) ++ Always followed by exactly one LE16 : D D D D D D D D : D D D D D D S S ++ distance = 16384 + (H << 14) + D ++ state = S (copy S literals after this block) ++ End of stream is reached if distance == 16384 ++ ++ 0 0 1 L L L L L (32..63) ++ Copy of small block within 16kB distance (preferably less than 34B) ++ length = 2 + (L ?: 31 + (zero_bytes * 255) + non_zero_byte) ++ Always followed by exactly one LE16 : D D D D D D D D : D D D D D D S S ++ distance = D + 1 ++ state = S (copy S literals after this block) ++ ++ 0 1 L D D D S S (64..127) ++ Copy 3-4 bytes from block within 2kB distance ++ state = S (copy S literals after this block) ++ length = 3 + L ++ Always followed by exactly one byte : H H H H H H H H ++ distance = (H << 3) + D + 1 ++ ++ 1 L L D D D S S (128..255) ++ Copy 5-8 bytes from block within 2kB distance ++ state = S (copy S literals after this block) ++ length = 5 + L ++ Always followed by exactly one byte : H H H H H H H H ++ distance = (H << 3) + D + 1 ++ ++Authors ++ ++ This document was written by Willy Tarreau on 2014/07/19 during an ++ analysis of the decompression code available in Linux 3.16-rc5. The code is ++ tricky, it is possible that this document contains mistakes or that a few ++ corner cases were overlooked. In any case, please report any doubt, fix, or ++ proposed updates to the author(s) so that the document can be updated. +diff --git a/Documentation/virtual/kvm/mmu.txt b/Documentation/virtual/kvm/mmu.txt +index 290894176142..53838d9c6295 100644 +--- a/Documentation/virtual/kvm/mmu.txt ++++ b/Documentation/virtual/kvm/mmu.txt +@@ -425,6 +425,20 @@ fault through the slow path. + Since only 19 bits are used to store generation-number on mmio spte, all + pages are zapped when there is an overflow. + ++Unfortunately, a single memory access might access kvm_memslots(kvm) multiple ++times, the last one happening when the generation number is retrieved and ++stored into the MMIO spte. Thus, the MMIO spte might be created based on ++out-of-date information, but with an up-to-date generation number. ++ ++To avoid this, the generation number is incremented again after synchronize_srcu ++returns; thus, the low bit of kvm_memslots(kvm)->generation is only 1 during a ++memslot update, while some SRCU readers might be using the old copy. We do not ++want to use an MMIO sptes created with an odd generation number, and we can do ++this without losing a bit in the MMIO spte. The low bit of the generation ++is not stored in MMIO spte, and presumed zero when it is extracted out of the ++spte. If KVM is unlucky and creates an MMIO spte while the low bit is 1, ++the next access to the spte will always be a cache miss. ++ + + Further reading + =============== +diff --git a/Makefile b/Makefile +index a59980eb4557..135a04a26076 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 22 ++SUBLEVEL = 23 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/boot/dts/armada-370-netgear-rn102.dts b/arch/arm/boot/dts/armada-370-netgear-rn102.dts +index 651aeb5ef439..f3188e953de4 100644 +--- a/arch/arm/boot/dts/armada-370-netgear-rn102.dts ++++ b/arch/arm/boot/dts/armada-370-netgear-rn102.dts +@@ -144,6 +144,10 @@ + marvell,nand-enable-arbiter; + nand-on-flash-bbt; + ++ /* Use Hardware BCH ECC */ ++ nand-ecc-strength = <4>; ++ nand-ecc-step-size = <512>; ++ + partition@0 { + label = "u-boot"; + reg = <0x0000000 0x180000>; /* 1.5MB */ +diff --git a/arch/arm/boot/dts/armada-370-netgear-rn104.dts b/arch/arm/boot/dts/armada-370-netgear-rn104.dts +index 4e27587667bf..da406c1c726a 100644 +--- a/arch/arm/boot/dts/armada-370-netgear-rn104.dts ++++ b/arch/arm/boot/dts/armada-370-netgear-rn104.dts +@@ -146,6 +146,10 @@ + marvell,nand-enable-arbiter; + nand-on-flash-bbt; + ++ /* Use Hardware BCH ECC */ ++ nand-ecc-strength = <4>; ++ nand-ecc-step-size = <512>; ++ + partition@0 { + label = "u-boot"; + reg = <0x0000000 0x180000>; /* 1.5MB */ +diff --git a/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts b/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts +index ff049ee862eb..b4aba09de911 100644 +--- a/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts ++++ b/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts +@@ -224,6 +224,10 @@ + marvell,nand-enable-arbiter; + nand-on-flash-bbt; + ++ /* Use Hardware BCH ECC */ ++ nand-ecc-strength = <4>; ++ nand-ecc-step-size = <512>; ++ + partition@0 { + label = "u-boot"; + reg = <0x0000000 0x180000>; /* 1.5MB */ +diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi +index fece8665fb63..b8f234bf7de8 100644 +--- a/arch/arm/boot/dts/at91sam9263.dtsi ++++ b/arch/arm/boot/dts/at91sam9263.dtsi +@@ -535,6 +535,7 @@ + compatible = "atmel,hsmci"; + reg = <0xfff80000 0x600>; + interrupts = <10 IRQ_TYPE_LEVEL_HIGH 0>; ++ pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +@@ -544,6 +545,7 @@ + compatible = "atmel,hsmci"; + reg = <0xfff84000 0x600>; + interrupts = <11 IRQ_TYPE_LEVEL_HIGH 0>; ++ pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +diff --git a/arch/arm/boot/dts/sama5d3_can.dtsi b/arch/arm/boot/dts/sama5d3_can.dtsi +index a0775851cce5..eaf41451ad0c 100644 +--- a/arch/arm/boot/dts/sama5d3_can.dtsi ++++ b/arch/arm/boot/dts/sama5d3_can.dtsi +@@ -40,7 +40,7 @@ + atmel,clk-output-range = <0 66000000>; + }; + +- can1_clk: can0_clk { ++ can1_clk: can1_clk { + #clock-cells = <0>; + reg = <41>; + atmel,clk-output-range = <0 66000000>; +diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c +index 034529d801b2..d66f102c352a 100644 +--- a/arch/arm/mach-at91/clock.c ++++ b/arch/arm/mach-at91/clock.c +@@ -962,6 +962,7 @@ static int __init at91_clock_reset(void) + } + + at91_pmc_write(AT91_PMC_SCDR, scdr); ++ at91_pmc_write(AT91_PMC_PCDR, pcdr); + if (cpu_is_sama5d3()) + at91_pmc_write(AT91_PMC_PCDR1, pcdr1); + +diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h +index fda2704b3f9f..e72289a97367 100644 +--- a/arch/arm64/include/asm/compat.h ++++ b/arch/arm64/include/asm/compat.h +@@ -37,8 +37,8 @@ typedef s32 compat_ssize_t; + typedef s32 compat_time_t; + typedef s32 compat_clock_t; + typedef s32 compat_pid_t; +-typedef u32 __compat_uid_t; +-typedef u32 __compat_gid_t; ++typedef u16 __compat_uid_t; ++typedef u16 __compat_gid_t; + typedef u16 __compat_uid16_t; + typedef u16 __compat_gid16_t; + typedef u32 __compat_uid32_t; +diff --git a/arch/m68k/mm/hwtest.c b/arch/m68k/mm/hwtest.c +index 2c7dde3c6430..2a5259fd23eb 100644 +--- a/arch/m68k/mm/hwtest.c ++++ b/arch/m68k/mm/hwtest.c +@@ -28,9 +28,11 @@ + int hwreg_present( volatile void *regp ) + { + int ret = 0; ++ unsigned long flags; + long save_sp, save_vbr; + long tmp_vectors[3]; + ++ local_irq_save(flags); + __asm__ __volatile__ + ( "movec %/vbr,%2\n\t" + "movel #Lberr1,%4@(8)\n\t" +@@ -46,6 +48,7 @@ int hwreg_present( volatile void *regp ) + : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr) + : "a" (regp), "a" (tmp_vectors) + ); ++ local_irq_restore(flags); + + return( ret ); + } +@@ -58,9 +61,11 @@ EXPORT_SYMBOL(hwreg_present); + int hwreg_write( volatile void *regp, unsigned short val ) + { + int ret; ++ unsigned long flags; + long save_sp, save_vbr; + long tmp_vectors[3]; + ++ local_irq_save(flags); + __asm__ __volatile__ + ( "movec %/vbr,%2\n\t" + "movel #Lberr2,%4@(8)\n\t" +@@ -78,6 +83,7 @@ int hwreg_write( volatile void *regp, unsigned short val ) + : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr) + : "a" (regp), "a" (tmp_vectors), "g" (val) + ); ++ local_irq_restore(flags); + + return( ret ); + } +diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c +index 4642d6a4d356..de1ec54a2a57 100644 +--- a/arch/powerpc/platforms/pseries/iommu.c ++++ b/arch/powerpc/platforms/pseries/iommu.c +@@ -329,16 +329,16 @@ struct direct_window { + + /* Dynamic DMA Window support */ + struct ddw_query_response { +- __be32 windows_available; +- __be32 largest_available_block; +- __be32 page_size; +- __be32 migration_capable; ++ u32 windows_available; ++ u32 largest_available_block; ++ u32 page_size; ++ u32 migration_capable; + }; + + struct ddw_create_response { +- __be32 liobn; +- __be32 addr_hi; +- __be32 addr_lo; ++ u32 liobn; ++ u32 addr_hi; ++ u32 addr_lo; + }; + + static LIST_HEAD(direct_window_list); +@@ -725,16 +725,18 @@ static void remove_ddw(struct device_node *np, bool remove_prop) + { + struct dynamic_dma_window_prop *dwp; + struct property *win64; +- const u32 *ddw_avail; ++ u32 ddw_avail[3]; + u64 liobn; +- int len, ret = 0; ++ int ret = 0; ++ ++ ret = of_property_read_u32_array(np, "ibm,ddw-applicable", ++ &ddw_avail[0], 3); + +- ddw_avail = of_get_property(np, "ibm,ddw-applicable", &len); + win64 = of_find_property(np, DIRECT64_PROPNAME, NULL); + if (!win64) + return; + +- if (!ddw_avail || len < 3 * sizeof(u32) || win64->length < sizeof(*dwp)) ++ if (ret || win64->length < sizeof(*dwp)) + goto delprop; + + dwp = win64->value; +@@ -872,8 +874,9 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail, + + do { + /* extra outputs are LIOBN and dma-addr (hi, lo) */ +- ret = rtas_call(ddw_avail[1], 5, 4, (u32 *)create, cfg_addr, +- BUID_HI(buid), BUID_LO(buid), page_shift, window_shift); ++ ret = rtas_call(ddw_avail[1], 5, 4, (u32 *)create, ++ cfg_addr, BUID_HI(buid), BUID_LO(buid), ++ page_shift, window_shift); + } while (rtas_busy_delay(ret)); + dev_info(&dev->dev, + "ibm,create-pe-dma-window(%x) %x %x %x %x %x returned %d " +@@ -910,7 +913,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) + int page_shift; + u64 dma_addr, max_addr; + struct device_node *dn; +- const u32 *uninitialized_var(ddw_avail); ++ u32 ddw_avail[3]; + struct direct_window *window; + struct property *win64; + struct dynamic_dma_window_prop *ddwprop; +@@ -942,8 +945,9 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) + * for the given node in that order. + * the property is actually in the parent, not the PE + */ +- ddw_avail = of_get_property(pdn, "ibm,ddw-applicable", &len); +- if (!ddw_avail || len < 3 * sizeof(u32)) ++ ret = of_property_read_u32_array(pdn, "ibm,ddw-applicable", ++ &ddw_avail[0], 3); ++ if (ret) + goto out_failed; + + /* +@@ -966,11 +970,11 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) + dev_dbg(&dev->dev, "no free dynamic windows"); + goto out_failed; + } +- if (be32_to_cpu(query.page_size) & 4) { ++ if (query.page_size & 4) { + page_shift = 24; /* 16MB */ +- } else if (be32_to_cpu(query.page_size) & 2) { ++ } else if (query.page_size & 2) { + page_shift = 16; /* 64kB */ +- } else if (be32_to_cpu(query.page_size) & 1) { ++ } else if (query.page_size & 1) { + page_shift = 12; /* 4kB */ + } else { + dev_dbg(&dev->dev, "no supported direct page size in mask %x", +@@ -980,7 +984,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) + /* verify the window * number of ptes will map the partition */ + /* check largest block * page size > max memory hotplug addr */ + max_addr = memory_hotplug_max(); +- if (be32_to_cpu(query.largest_available_block) < (max_addr >> page_shift)) { ++ if (query.largest_available_block < (max_addr >> page_shift)) { + dev_dbg(&dev->dev, "can't map partiton max 0x%llx with %u " + "%llu-sized pages\n", max_addr, query.largest_available_block, + 1ULL << page_shift); +@@ -1006,8 +1010,9 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) + if (ret != 0) + goto out_free_prop; + +- ddwprop->liobn = create.liobn; +- ddwprop->dma_base = cpu_to_be64(of_read_number(&create.addr_hi, 2)); ++ ddwprop->liobn = cpu_to_be32(create.liobn); ++ ddwprop->dma_base = cpu_to_be64(((u64)create.addr_hi << 32) | ++ create.addr_lo); + ddwprop->tce_shift = cpu_to_be32(page_shift); + ddwprop->window_shift = cpu_to_be32(len); + +@@ -1039,7 +1044,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) + list_add(&window->list, &direct_window_list); + spin_unlock(&direct_window_list_lock); + +- dma_addr = of_read_number(&create.addr_hi, 2); ++ dma_addr = be64_to_cpu(ddwprop->dma_base); + goto out_unlock; + + out_free_window: +diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c +index 5f79d2d79ca7..f1ba119878ec 100644 +--- a/arch/s390/kvm/interrupt.c ++++ b/arch/s390/kvm/interrupt.c +@@ -71,6 +71,7 @@ static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu, + return 0; + if (vcpu->arch.sie_block->gcr[0] & 0x2000ul) + return 1; ++ return 0; + case KVM_S390_INT_EMERGENCY: + if (psw_extint_disabled(vcpu)) + return 0; +diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig +index b398c68b2713..a38513c33a62 100644 +--- a/arch/sparc/Kconfig ++++ b/arch/sparc/Kconfig +@@ -67,6 +67,7 @@ config SPARC64 + select HAVE_SYSCALL_TRACEPOINTS + select HAVE_CONTEXT_TRACKING + select HAVE_DEBUG_KMEMLEAK ++ select SPARSE_IRQ + select RTC_DRV_CMOS + select RTC_DRV_BQ4802 + select RTC_DRV_SUN4V +diff --git a/arch/sparc/include/asm/hypervisor.h b/arch/sparc/include/asm/hypervisor.h +index ca121f0fa3ec..17be9d618335 100644 +--- a/arch/sparc/include/asm/hypervisor.h ++++ b/arch/sparc/include/asm/hypervisor.h +@@ -2944,6 +2944,16 @@ extern unsigned long sun4v_vt_set_perfreg(unsigned long reg_num, + unsigned long reg_val); + #endif + ++#define HV_FAST_T5_GET_PERFREG 0x1a8 ++#define HV_FAST_T5_SET_PERFREG 0x1a9 ++ ++#ifndef __ASSEMBLY__ ++unsigned long sun4v_t5_get_perfreg(unsigned long reg_num, ++ unsigned long *reg_val); ++unsigned long sun4v_t5_set_perfreg(unsigned long reg_num, ++ unsigned long reg_val); ++#endif ++ + /* Function numbers for HV_CORE_TRAP. */ + #define HV_CORE_SET_VER 0x00 + #define HV_CORE_PUTCHAR 0x01 +@@ -2975,6 +2985,7 @@ extern unsigned long sun4v_vt_set_perfreg(unsigned long reg_num, + #define HV_GRP_VF_CPU 0x0205 + #define HV_GRP_KT_CPU 0x0209 + #define HV_GRP_VT_CPU 0x020c ++#define HV_GRP_T5_CPU 0x0211 + #define HV_GRP_DIAG 0x0300 + + #ifndef __ASSEMBLY__ +diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h +index abf6afe82ca8..3deb07ff1e00 100644 +--- a/arch/sparc/include/asm/irq_64.h ++++ b/arch/sparc/include/asm/irq_64.h +@@ -37,7 +37,7 @@ + * + * ino_bucket->irq allocation is made during {sun4v_,}build_irq(). + */ +-#define NR_IRQS 255 ++#define NR_IRQS (2048) + + extern void irq_install_pre_handler(int irq, + void (*func)(unsigned int, void *, void *), +@@ -57,11 +57,8 @@ extern unsigned int sun4u_build_msi(u32 portid, unsigned int *irq_p, + unsigned long iclr_base); + extern void sun4u_destroy_msi(unsigned int irq); + +-extern unsigned char irq_alloc(unsigned int dev_handle, +- unsigned int dev_ino); +-#ifdef CONFIG_PCI_MSI +-extern void irq_free(unsigned int irq); +-#endif ++unsigned int irq_alloc(unsigned int dev_handle, unsigned int dev_ino); ++void irq_free(unsigned int irq); + + extern void __init init_IRQ(void); + extern void fixup_irqs(void); +diff --git a/arch/sparc/include/asm/ldc.h b/arch/sparc/include/asm/ldc.h +index bdb524a7b814..8732ed391aff 100644 +--- a/arch/sparc/include/asm/ldc.h ++++ b/arch/sparc/include/asm/ldc.h +@@ -53,13 +53,14 @@ struct ldc_channel; + /* Allocate state for a channel. */ + extern struct ldc_channel *ldc_alloc(unsigned long id, + const struct ldc_channel_config *cfgp, +- void *event_arg); ++ void *event_arg, ++ const char *name); + + /* Shut down and free state for a channel. */ + extern void ldc_free(struct ldc_channel *lp); + + /* Register TX and RX queues of the link with the hypervisor. */ +-extern int ldc_bind(struct ldc_channel *lp, const char *name); ++extern int ldc_bind(struct ldc_channel *lp); + + /* For non-RAW protocols we need to complete a handshake before + * communication can proceed. ldc_connect() does that, if the +diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h +index a12dbe3b7762..e48fdf4e16ff 100644 +--- a/arch/sparc/include/asm/oplib_64.h ++++ b/arch/sparc/include/asm/oplib_64.h +@@ -62,7 +62,8 @@ struct linux_mem_p1275 { + /* You must call prom_init() before using any of the library services, + * preferably as early as possible. Pass it the romvec pointer. + */ +-extern void prom_init(void *cif_handler, void *cif_stack); ++extern void prom_init(void *cif_handler); ++extern void prom_init_report(void); + + /* Boot argument acquisition, returns the boot command line string. */ + extern char *prom_getbootargs(void); +diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h +index aac53fcea807..b18e602fcac4 100644 +--- a/arch/sparc/include/asm/page_64.h ++++ b/arch/sparc/include/asm/page_64.h +@@ -57,18 +57,21 @@ extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct pag + typedef struct { unsigned long pte; } pte_t; + typedef struct { unsigned long iopte; } iopte_t; + typedef struct { unsigned long pmd; } pmd_t; ++typedef struct { unsigned long pud; } pud_t; + typedef struct { unsigned long pgd; } pgd_t; + typedef struct { unsigned long pgprot; } pgprot_t; + + #define pte_val(x) ((x).pte) + #define iopte_val(x) ((x).iopte) + #define pmd_val(x) ((x).pmd) ++#define pud_val(x) ((x).pud) + #define pgd_val(x) ((x).pgd) + #define pgprot_val(x) ((x).pgprot) + + #define __pte(x) ((pte_t) { (x) } ) + #define __iopte(x) ((iopte_t) { (x) } ) + #define __pmd(x) ((pmd_t) { (x) } ) ++#define __pud(x) ((pud_t) { (x) } ) + #define __pgd(x) ((pgd_t) { (x) } ) + #define __pgprot(x) ((pgprot_t) { (x) } ) + +@@ -77,18 +80,21 @@ typedef struct { unsigned long pgprot; } pgprot_t; + typedef unsigned long pte_t; + typedef unsigned long iopte_t; + typedef unsigned long pmd_t; ++typedef unsigned long pud_t; + typedef unsigned long pgd_t; + typedef unsigned long pgprot_t; + + #define pte_val(x) (x) + #define iopte_val(x) (x) + #define pmd_val(x) (x) ++#define pud_val(x) (x) + #define pgd_val(x) (x) + #define pgprot_val(x) (x) + + #define __pte(x) (x) + #define __iopte(x) (x) + #define __pmd(x) (x) ++#define __pud(x) (x) + #define __pgd(x) (x) + #define __pgprot(x) (x) + +@@ -96,21 +102,14 @@ typedef unsigned long pgprot_t; + + typedef pte_t *pgtable_t; + +-/* These two values define the virtual address space range in which we +- * must forbid 64-bit user processes from making mappings. It used to +- * represent precisely the virtual address space hole present in most +- * early sparc64 chips including UltraSPARC-I. But now it also is +- * further constrained by the limits of our page tables, which is +- * 43-bits of virtual address. +- */ +-#define SPARC64_VA_HOLE_TOP _AC(0xfffffc0000000000,UL) +-#define SPARC64_VA_HOLE_BOTTOM _AC(0x0000040000000000,UL) ++extern unsigned long sparc64_va_hole_top; ++extern unsigned long sparc64_va_hole_bottom; + + /* The next two defines specify the actual exclusion region we + * enforce, wherein we use a 4GB red zone on each side of the VA hole. + */ +-#define VA_EXCLUDE_START (SPARC64_VA_HOLE_BOTTOM - (1UL << 32UL)) +-#define VA_EXCLUDE_END (SPARC64_VA_HOLE_TOP + (1UL << 32UL)) ++#define VA_EXCLUDE_START (sparc64_va_hole_bottom - (1UL << 32UL)) ++#define VA_EXCLUDE_END (sparc64_va_hole_top + (1UL << 32UL)) + + #define TASK_UNMAPPED_BASE (test_thread_flag(TIF_32BIT) ? \ + _AC(0x0000000070000000,UL) : \ +@@ -118,20 +117,16 @@ typedef pte_t *pgtable_t; + + #include + +-#define PAGE_OFFSET_BY_BITS(X) (-(_AC(1,UL) << (X))) + extern unsigned long PAGE_OFFSET; + + #endif /* !(__ASSEMBLY__) */ + +-/* The maximum number of physical memory address bits we support, this +- * is used to size various tables used to manage kernel TLB misses and +- * also the sparsemem code. ++/* The maximum number of physical memory address bits we support. The ++ * largest value we can support is whatever "KPGD_SHIFT + KPTE_BITS" ++ * evaluates to. + */ +-#define MAX_PHYS_ADDRESS_BITS 47 ++#define MAX_PHYS_ADDRESS_BITS 53 + +-/* These two shift counts are used when indexing sparc64_valid_addr_bitmap +- * and kpte_linear_bitmap. +- */ + #define ILOG2_4MB 22 + #define ILOG2_256MB 28 + +diff --git a/arch/sparc/include/asm/pgalloc_64.h b/arch/sparc/include/asm/pgalloc_64.h +index bcfe063bce23..2c8d41fb13a4 100644 +--- a/arch/sparc/include/asm/pgalloc_64.h ++++ b/arch/sparc/include/asm/pgalloc_64.h +@@ -15,6 +15,13 @@ + + extern struct kmem_cache *pgtable_cache; + ++static inline void __pgd_populate(pgd_t *pgd, pud_t *pud) ++{ ++ pgd_set(pgd, pud); ++} ++ ++#define pgd_populate(MM, PGD, PUD) __pgd_populate(PGD, PUD) ++ + static inline pgd_t *pgd_alloc(struct mm_struct *mm) + { + return kmem_cache_alloc(pgtable_cache, GFP_KERNEL); +@@ -25,7 +32,23 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) + kmem_cache_free(pgtable_cache, pgd); + } + +-#define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD) ++static inline void __pud_populate(pud_t *pud, pmd_t *pmd) ++{ ++ pud_set(pud, pmd); ++} ++ ++#define pud_populate(MM, PUD, PMD) __pud_populate(PUD, PMD) ++ ++static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) ++{ ++ return kmem_cache_alloc(pgtable_cache, ++ GFP_KERNEL|__GFP_REPEAT); ++} ++ ++static inline void pud_free(struct mm_struct *mm, pud_t *pud) ++{ ++ kmem_cache_free(pgtable_cache, pud); ++} + + static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) + { +@@ -91,4 +114,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pte_t *pte, + #define __pmd_free_tlb(tlb, pmd, addr) \ + pgtable_free_tlb(tlb, pmd, false) + ++#define __pud_free_tlb(tlb, pud, addr) \ ++ pgtable_free_tlb(tlb, pud, false) ++ + #endif /* _SPARC64_PGALLOC_H */ +diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h +index 1a49ffdf9da9..e8dfabf156c7 100644 +--- a/arch/sparc/include/asm/pgtable_64.h ++++ b/arch/sparc/include/asm/pgtable_64.h +@@ -20,8 +20,6 @@ + #include + #include + +-#include +- + /* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB). + * The page copy blockops can use 0x6000000 to 0x8000000. + * The 8K TSB is mapped in the 0x8000000 to 0x8400000 range. +@@ -42,10 +40,7 @@ + #define LOW_OBP_ADDRESS _AC(0x00000000f0000000,UL) + #define HI_OBP_ADDRESS _AC(0x0000000100000000,UL) + #define VMALLOC_START _AC(0x0000000100000000,UL) +-#define VMALLOC_END _AC(0x0000010000000000,UL) +-#define VMEMMAP_BASE _AC(0x0000010000000000,UL) +- +-#define vmemmap ((struct page *)VMEMMAP_BASE) ++#define VMEMMAP_BASE VMALLOC_END + + /* PMD_SHIFT determines the size of the area a second-level page + * table can map +@@ -55,13 +50,25 @@ + #define PMD_MASK (~(PMD_SIZE-1)) + #define PMD_BITS (PAGE_SHIFT - 3) + +-/* PGDIR_SHIFT determines what a third-level page table entry can map */ +-#define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-3) + PMD_BITS) ++/* PUD_SHIFT determines the size of the area a third-level page ++ * table can map ++ */ ++#define PUD_SHIFT (PMD_SHIFT + PMD_BITS) ++#define PUD_SIZE (_AC(1,UL) << PUD_SHIFT) ++#define PUD_MASK (~(PUD_SIZE-1)) ++#define PUD_BITS (PAGE_SHIFT - 3) ++ ++/* PGDIR_SHIFT determines what a fourth-level page table entry can map */ ++#define PGDIR_SHIFT (PUD_SHIFT + PUD_BITS) + #define PGDIR_SIZE (_AC(1,UL) << PGDIR_SHIFT) + #define PGDIR_MASK (~(PGDIR_SIZE-1)) + #define PGDIR_BITS (PAGE_SHIFT - 3) + +-#if (PGDIR_SHIFT + PGDIR_BITS) != 43 ++#if (MAX_PHYS_ADDRESS_BITS > PGDIR_SHIFT + PGDIR_BITS) ++#error MAX_PHYS_ADDRESS_BITS exceeds what kernel page tables can support ++#endif ++ ++#if (PGDIR_SHIFT + PGDIR_BITS) != 53 + #error Page table parameters do not cover virtual address space properly. + #endif + +@@ -71,28 +78,18 @@ + + #ifndef __ASSEMBLY__ + +-#include +- +-extern unsigned long sparc64_valid_addr_bitmap[]; ++extern unsigned long VMALLOC_END; + +-/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ +-static inline bool __kern_addr_valid(unsigned long paddr) +-{ +- if ((paddr >> MAX_PHYS_ADDRESS_BITS) != 0UL) +- return false; +- return test_bit(paddr >> ILOG2_4MB, sparc64_valid_addr_bitmap); +-} ++#define vmemmap ((struct page *)VMEMMAP_BASE) + +-static inline bool kern_addr_valid(unsigned long addr) +-{ +- unsigned long paddr = __pa(addr); ++#include + +- return __kern_addr_valid(paddr); +-} ++bool kern_addr_valid(unsigned long addr); + + /* Entries per page directory level. */ + #define PTRS_PER_PTE (1UL << (PAGE_SHIFT-3)) + #define PTRS_PER_PMD (1UL << PMD_BITS) ++#define PTRS_PER_PUD (1UL << PUD_BITS) + #define PTRS_PER_PGD (1UL << PGDIR_BITS) + + /* Kernel has a separate 44bit address space. */ +@@ -101,6 +98,9 @@ static inline bool kern_addr_valid(unsigned long addr) + #define pmd_ERROR(e) \ + pr_err("%s:%d: bad pmd %p(%016lx) seen at (%pS)\n", \ + __FILE__, __LINE__, &(e), pmd_val(e), __builtin_return_address(0)) ++#define pud_ERROR(e) \ ++ pr_err("%s:%d: bad pud %p(%016lx) seen at (%pS)\n", \ ++ __FILE__, __LINE__, &(e), pud_val(e), __builtin_return_address(0)) + #define pgd_ERROR(e) \ + pr_err("%s:%d: bad pgd %p(%016lx) seen at (%pS)\n", \ + __FILE__, __LINE__, &(e), pgd_val(e), __builtin_return_address(0)) +@@ -112,6 +112,7 @@ static inline bool kern_addr_valid(unsigned long addr) + #define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/ + #define _PAGE_SPECIAL _AC(0x0200000000000000,UL) /* Special page */ + #define _PAGE_PMD_HUGE _AC(0x0100000000000000,UL) /* Huge page */ ++#define _PAGE_PUD_HUGE _PAGE_PMD_HUGE + + /* Advertise support for _PAGE_SPECIAL */ + #define __HAVE_ARCH_PTE_SPECIAL +@@ -658,26 +659,26 @@ static inline unsigned long pmd_large(pmd_t pmd) + return pte_val(pte) & _PAGE_PMD_HUGE; + } + +-#ifdef CONFIG_TRANSPARENT_HUGEPAGE +-static inline unsigned long pmd_young(pmd_t pmd) ++static inline unsigned long pmd_pfn(pmd_t pmd) + { + pte_t pte = __pte(pmd_val(pmd)); + +- return pte_young(pte); ++ return pte_pfn(pte); + } + +-static inline unsigned long pmd_write(pmd_t pmd) ++#ifdef CONFIG_TRANSPARENT_HUGEPAGE ++static inline unsigned long pmd_young(pmd_t pmd) + { + pte_t pte = __pte(pmd_val(pmd)); + +- return pte_write(pte); ++ return pte_young(pte); + } + +-static inline unsigned long pmd_pfn(pmd_t pmd) ++static inline unsigned long pmd_write(pmd_t pmd) + { + pte_t pte = __pte(pmd_val(pmd)); + +- return pte_pfn(pte); ++ return pte_write(pte); + } + + static inline unsigned long pmd_trans_huge(pmd_t pmd) +@@ -771,13 +772,15 @@ static inline int pmd_present(pmd_t pmd) + * the top bits outside of the range of any physical address size we + * support are clear as well. We also validate the physical itself. + */ +-#define pmd_bad(pmd) ((pmd_val(pmd) & ~PAGE_MASK) || \ +- !__kern_addr_valid(pmd_val(pmd))) ++#define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK) + + #define pud_none(pud) (!pud_val(pud)) + +-#define pud_bad(pud) ((pud_val(pud) & ~PAGE_MASK) || \ +- !__kern_addr_valid(pud_val(pud))) ++#define pud_bad(pud) (pud_val(pud) & ~PAGE_MASK) ++ ++#define pgd_none(pgd) (!pgd_val(pgd)) ++ ++#define pgd_bad(pgd) (pgd_val(pgd) & ~PAGE_MASK) + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + extern void set_pmd_at(struct mm_struct *mm, unsigned long addr, +@@ -815,10 +818,31 @@ static inline unsigned long __pmd_page(pmd_t pmd) + #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0UL) + #define pud_present(pud) (pud_val(pud) != 0U) + #define pud_clear(pudp) (pud_val(*(pudp)) = 0UL) ++#define pgd_page_vaddr(pgd) \ ++ ((unsigned long) __va(pgd_val(pgd))) ++#define pgd_present(pgd) (pgd_val(pgd) != 0U) ++#define pgd_clear(pgdp) (pgd_val(*(pgd)) = 0UL) ++ ++static inline unsigned long pud_large(pud_t pud) ++{ ++ pte_t pte = __pte(pud_val(pud)); ++ ++ return pte_val(pte) & _PAGE_PMD_HUGE; ++} ++ ++static inline unsigned long pud_pfn(pud_t pud) ++{ ++ pte_t pte = __pte(pud_val(pud)); ++ ++ return pte_pfn(pte); ++} + + /* Same in both SUN4V and SUN4U. */ + #define pte_none(pte) (!pte_val(pte)) + ++#define pgd_set(pgdp, pudp) \ ++ (pgd_val(*(pgdp)) = (__pa((unsigned long) (pudp)))) ++ + /* to find an entry in a page-table-directory. */ + #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) + #define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) +@@ -826,6 +850,11 @@ static inline unsigned long __pmd_page(pmd_t pmd) + /* to find an entry in a kernel page-table-directory */ + #define pgd_offset_k(address) pgd_offset(&init_mm, address) + ++/* Find an entry in the third-level page table.. */ ++#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) ++#define pud_offset(pgdp, address) \ ++ ((pud_t *) pgd_page_vaddr(*(pgdp)) + pud_index(address)) ++ + /* Find an entry in the second-level page table.. */ + #define pmd_offset(pudp, address) \ + ((pmd_t *) pud_page_vaddr(*(pudp)) + \ +@@ -898,7 +927,6 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, + #endif + + extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; +-extern pmd_t swapper_low_pmd_dir[PTRS_PER_PMD]; + + extern void paging_init(void); + extern unsigned long find_ecache_flush_span(unsigned long size); +diff --git a/arch/sparc/include/asm/setup.h b/arch/sparc/include/asm/setup.h +index 5e35e0517318..acd614668ec1 100644 +--- a/arch/sparc/include/asm/setup.h ++++ b/arch/sparc/include/asm/setup.h +@@ -24,6 +24,10 @@ static inline int con_is_present(void) + } + #endif + ++#ifdef CONFIG_SPARC64 ++extern void __init start_early_boot(void); ++#endif ++ + extern void sun_do_break(void); + extern int stop_a_enabled; + extern int scons_pwroff; +diff --git a/arch/sparc/include/asm/spitfire.h b/arch/sparc/include/asm/spitfire.h +index 6b67e50fb9b4..69424d48cbb7 100644 +--- a/arch/sparc/include/asm/spitfire.h ++++ b/arch/sparc/include/asm/spitfire.h +@@ -45,6 +45,8 @@ + #define SUN4V_CHIP_NIAGARA3 0x03 + #define SUN4V_CHIP_NIAGARA4 0x04 + #define SUN4V_CHIP_NIAGARA5 0x05 ++#define SUN4V_CHIP_SPARC_M6 0x06 ++#define SUN4V_CHIP_SPARC_M7 0x07 + #define SUN4V_CHIP_SPARC64X 0x8a + #define SUN4V_CHIP_UNKNOWN 0xff + +diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h +index a5f01ac6d0f1..cc6275c931a5 100644 +--- a/arch/sparc/include/asm/thread_info_64.h ++++ b/arch/sparc/include/asm/thread_info_64.h +@@ -63,7 +63,8 @@ struct thread_info { + struct pt_regs *kern_una_regs; + unsigned int kern_una_insn; + +- unsigned long fpregs[0] __attribute__ ((aligned(64))); ++ unsigned long fpregs[(7 * 256) / sizeof(unsigned long)] ++ __attribute__ ((aligned(64))); + }; + + #endif /* !(__ASSEMBLY__) */ +@@ -102,6 +103,7 @@ struct thread_info { + #define FAULT_CODE_ITLB 0x04 /* Miss happened in I-TLB */ + #define FAULT_CODE_WINFIXUP 0x08 /* Miss happened during spill/fill */ + #define FAULT_CODE_BLKCOMMIT 0x10 /* Use blk-commit ASI in copy_page */ ++#define FAULT_CODE_BAD_RA 0x20 /* Bad RA for sun4v */ + + #if PAGE_SHIFT == 13 + #define THREAD_SIZE (2*PAGE_SIZE) +diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h +index 90916f955cac..ecb49cfa3be9 100644 +--- a/arch/sparc/include/asm/tsb.h ++++ b/arch/sparc/include/asm/tsb.h +@@ -133,9 +133,24 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; + sub TSB, 0x8, TSB; \ + TSB_STORE(TSB, TAG); + +- /* Do a kernel page table walk. Leaves physical PTE pointer in +- * REG1. Jumps to FAIL_LABEL on early page table walk termination. +- * VADDR will not be clobbered, but REG2 will. ++ /* Do a kernel page table walk. Leaves valid PTE value in ++ * REG1. Jumps to FAIL_LABEL on early page table walk ++ * termination. VADDR will not be clobbered, but REG2 will. ++ * ++ * There are two masks we must apply to propagate bits from ++ * the virtual address into the PTE physical address field ++ * when dealing with huge pages. This is because the page ++ * table boundaries do not match the huge page size(s) the ++ * hardware supports. ++ * ++ * In these cases we propagate the bits that are below the ++ * page table level where we saw the huge page mapping, but ++ * are still within the relevant physical bits for the huge ++ * page size in question. So for PMD mappings (which fall on ++ * bit 23, for 8MB per PMD) we must propagate bit 22 for a ++ * 4MB huge page. For huge PUDs (which fall on bit 33, for ++ * 8GB per PUD), we have to accomodate 256MB and 2GB huge ++ * pages. So for those we propagate bits 32 to 28. + */ + #define KERN_PGTABLE_WALK(VADDR, REG1, REG2, FAIL_LABEL) \ + sethi %hi(swapper_pg_dir), REG1; \ +@@ -145,15 +160,40 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; + andn REG2, 0x7, REG2; \ + ldx [REG1 + REG2], REG1; \ + brz,pn REG1, FAIL_LABEL; \ +- sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ ++ sllx VADDR, 64 - (PUD_SHIFT + PUD_BITS), REG2; \ + srlx REG2, 64 - PAGE_SHIFT, REG2; \ + andn REG2, 0x7, REG2; \ + ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ + brz,pn REG1, FAIL_LABEL; \ +- sllx VADDR, 64 - PMD_SHIFT, REG2; \ ++ sethi %uhi(_PAGE_PUD_HUGE), REG2; \ ++ brz,pn REG1, FAIL_LABEL; \ ++ sllx REG2, 32, REG2; \ ++ andcc REG1, REG2, %g0; \ ++ sethi %hi(0xf8000000), REG2; \ ++ bne,pt %xcc, 697f; \ ++ sllx REG2, 1, REG2; \ ++ sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ + srlx REG2, 64 - PAGE_SHIFT, REG2; \ + andn REG2, 0x7, REG2; \ +- add REG1, REG2, REG1; ++ ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ ++ sethi %uhi(_PAGE_PMD_HUGE), REG2; \ ++ brz,pn REG1, FAIL_LABEL; \ ++ sllx REG2, 32, REG2; \ ++ andcc REG1, REG2, %g0; \ ++ be,pn %xcc, 698f; \ ++ sethi %hi(0x400000), REG2; \ ++697: brgez,pn REG1, FAIL_LABEL; \ ++ andn REG1, REG2, REG1; \ ++ and VADDR, REG2, REG2; \ ++ ba,pt %xcc, 699f; \ ++ or REG1, REG2, REG1; \ ++698: sllx VADDR, 64 - PMD_SHIFT, REG2; \ ++ srlx REG2, 64 - PAGE_SHIFT, REG2; \ ++ andn REG2, 0x7, REG2; \ ++ ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ ++ brgez,pn REG1, FAIL_LABEL; \ ++ nop; \ ++699: + + /* PMD has been loaded into REG1, interpret the value, seeing + * if it is a HUGE PMD or a normal one. If it is not valid +@@ -198,6 +238,11 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; + andn REG2, 0x7, REG2; \ + ldxa [PHYS_PGD + REG2] ASI_PHYS_USE_EC, REG1; \ + brz,pn REG1, FAIL_LABEL; \ ++ sllx VADDR, 64 - (PUD_SHIFT + PUD_BITS), REG2; \ ++ srlx REG2, 64 - PAGE_SHIFT, REG2; \ ++ andn REG2, 0x7, REG2; \ ++ ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ ++ brz,pn REG1, FAIL_LABEL; \ + sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ + srlx REG2, 64 - PAGE_SHIFT, REG2; \ + andn REG2, 0x7, REG2; \ +@@ -246,8 +291,6 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; + (KERNEL_TSB_SIZE_BYTES / 16) + #define KERNEL_TSB4M_NENTRIES 4096 + +-#define KTSB_PHYS_SHIFT 15 +- + /* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL + * on TSB hit. REG1, REG2, REG3, and REG4 are used as temporaries + * and the found TTE will be left in REG1. REG3 and REG4 must +@@ -256,17 +299,15 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; + * VADDR and TAG will be preserved and not clobbered by this macro. + */ + #define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \ +-661: sethi %hi(swapper_tsb), REG1; \ +- or REG1, %lo(swapper_tsb), REG1; \ ++661: sethi %uhi(swapper_tsb), REG1; \ ++ sethi %hi(swapper_tsb), REG2; \ ++ or REG1, %ulo(swapper_tsb), REG1; \ ++ or REG2, %lo(swapper_tsb), REG2; \ + .section .swapper_tsb_phys_patch, "ax"; \ + .word 661b; \ + .previous; \ +-661: nop; \ +- .section .tsb_ldquad_phys_patch, "ax"; \ +- .word 661b; \ +- sllx REG1, KTSB_PHYS_SHIFT, REG1; \ +- sllx REG1, KTSB_PHYS_SHIFT, REG1; \ +- .previous; \ ++ sllx REG1, 32, REG1; \ ++ or REG1, REG2, REG1; \ + srlx VADDR, PAGE_SHIFT, REG2; \ + and REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \ + sllx REG2, 4, REG2; \ +@@ -281,17 +322,15 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; + * we can make use of that for the index computation. + */ + #define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \ +-661: sethi %hi(swapper_4m_tsb), REG1; \ +- or REG1, %lo(swapper_4m_tsb), REG1; \ ++661: sethi %uhi(swapper_4m_tsb), REG1; \ ++ sethi %hi(swapper_4m_tsb), REG2; \ ++ or REG1, %ulo(swapper_4m_tsb), REG1; \ ++ or REG2, %lo(swapper_4m_tsb), REG2; \ + .section .swapper_4m_tsb_phys_patch, "ax"; \ + .word 661b; \ + .previous; \ +-661: nop; \ +- .section .tsb_ldquad_phys_patch, "ax"; \ +- .word 661b; \ +- sllx REG1, KTSB_PHYS_SHIFT, REG1; \ +- sllx REG1, KTSB_PHYS_SHIFT, REG1; \ +- .previous; \ ++ sllx REG1, 32, REG1; \ ++ or REG1, REG2, REG1; \ + and TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \ + sllx REG2, 4, REG2; \ + add REG1, REG2, REG2; \ +diff --git a/arch/sparc/include/asm/visasm.h b/arch/sparc/include/asm/visasm.h +index 39ca301920db..11fdf0ef50bb 100644 +--- a/arch/sparc/include/asm/visasm.h ++++ b/arch/sparc/include/asm/visasm.h +@@ -39,6 +39,14 @@ + 297: wr %o5, FPRS_FEF, %fprs; \ + 298: + ++#define VISEntryHalfFast(fail_label) \ ++ rd %fprs, %o5; \ ++ andcc %o5, FPRS_FEF, %g0; \ ++ be,pt %icc, 297f; \ ++ nop; \ ++ ba,a,pt %xcc, fail_label; \ ++297: wr %o5, FPRS_FEF, %fprs; ++ + #define VISExitHalf \ + wr %o5, 0, %fprs; + +diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c +index 5c5125895db8..52e10defedc4 100644 +--- a/arch/sparc/kernel/cpu.c ++++ b/arch/sparc/kernel/cpu.c +@@ -493,6 +493,18 @@ static void __init sun4v_cpu_probe(void) + sparc_pmu_type = "niagara5"; + break; + ++ case SUN4V_CHIP_SPARC_M6: ++ sparc_cpu_type = "SPARC-M6"; ++ sparc_fpu_type = "SPARC-M6 integrated FPU"; ++ sparc_pmu_type = "sparc-m6"; ++ break; ++ ++ case SUN4V_CHIP_SPARC_M7: ++ sparc_cpu_type = "SPARC-M7"; ++ sparc_fpu_type = "SPARC-M7 integrated FPU"; ++ sparc_pmu_type = "sparc-m7"; ++ break; ++ + case SUN4V_CHIP_SPARC64X: + sparc_cpu_type = "SPARC64-X"; + sparc_fpu_type = "SPARC64-X integrated FPU"; +diff --git a/arch/sparc/kernel/cpumap.c b/arch/sparc/kernel/cpumap.c +index de1c844dfabc..e69ec0e3f155 100644 +--- a/arch/sparc/kernel/cpumap.c ++++ b/arch/sparc/kernel/cpumap.c +@@ -326,6 +326,8 @@ static int iterate_cpu(struct cpuinfo_tree *t, unsigned int root_index) + case SUN4V_CHIP_NIAGARA3: + case SUN4V_CHIP_NIAGARA4: + case SUN4V_CHIP_NIAGARA5: ++ case SUN4V_CHIP_SPARC_M6: ++ case SUN4V_CHIP_SPARC_M7: + case SUN4V_CHIP_SPARC64X: + rover_inc_table = niagara_iterate_method; + break; +diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c +index dff60abbea01..f87a55d77094 100644 +--- a/arch/sparc/kernel/ds.c ++++ b/arch/sparc/kernel/ds.c +@@ -1200,14 +1200,14 @@ static int ds_probe(struct vio_dev *vdev, const struct vio_device_id *id) + ds_cfg.tx_irq = vdev->tx_irq; + ds_cfg.rx_irq = vdev->rx_irq; + +- lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp); ++ lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp, "DS"); + if (IS_ERR(lp)) { + err = PTR_ERR(lp); + goto out_free_ds_states; + } + dp->lp = lp; + +- err = ldc_bind(lp, "DS"); ++ err = ldc_bind(lp); + if (err) + goto out_free_ldc; + +diff --git a/arch/sparc/kernel/dtlb_prot.S b/arch/sparc/kernel/dtlb_prot.S +index b2c2c5be281c..d668ca149e64 100644 +--- a/arch/sparc/kernel/dtlb_prot.S ++++ b/arch/sparc/kernel/dtlb_prot.S +@@ -24,11 +24,11 @@ + mov TLB_TAG_ACCESS, %g4 ! For reload of vaddr + + /* PROT ** ICACHE line 2: More real fault processing */ ++ ldxa [%g4] ASI_DMMU, %g5 ! Put tagaccess in %g5 + bgu,pn %xcc, winfix_trampoline ! Yes, perform winfixup +- ldxa [%g4] ASI_DMMU, %g5 ! Put tagaccess in %g5 +- ba,pt %xcc, sparc64_realfault_common ! Nope, normal fault + mov FAULT_CODE_DTLB | FAULT_CODE_WRITE, %g4 +- nop ++ ba,pt %xcc, sparc64_realfault_common ! Nope, normal fault ++ nop + nop + nop + nop +diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h +index 140966fbd303..c88ffb9ee482 100644 +--- a/arch/sparc/kernel/entry.h ++++ b/arch/sparc/kernel/entry.h +@@ -66,13 +66,10 @@ struct pause_patch_entry { + extern struct pause_patch_entry __pause_3insn_patch, + __pause_3insn_patch_end; + +-extern void __init per_cpu_patch(void); + extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *, + struct sun4v_1insn_patch_entry *); + extern void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *, + struct sun4v_2insn_patch_entry *); +-extern void __init sun4v_patch(void); +-extern void __init boot_cpu_id_too_large(int cpu); + extern unsigned int dcache_parity_tl1_occurred; + extern unsigned int icache_parity_tl1_occurred; + +diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S +index 452f04fe8da6..3d61fcae7ee3 100644 +--- a/arch/sparc/kernel/head_64.S ++++ b/arch/sparc/kernel/head_64.S +@@ -427,6 +427,12 @@ sun4v_chip_type: + cmp %g2, '5' + be,pt %xcc, 5f + mov SUN4V_CHIP_NIAGARA5, %g4 ++ cmp %g2, '6' ++ be,pt %xcc, 5f ++ mov SUN4V_CHIP_SPARC_M6, %g4 ++ cmp %g2, '7' ++ be,pt %xcc, 5f ++ mov SUN4V_CHIP_SPARC_M7, %g4 + ba,pt %xcc, 49f + nop + +@@ -585,6 +591,12 @@ niagara_tlb_fixup: + cmp %g1, SUN4V_CHIP_NIAGARA5 + be,pt %xcc, niagara4_patch + nop ++ cmp %g1, SUN4V_CHIP_SPARC_M6 ++ be,pt %xcc, niagara4_patch ++ nop ++ cmp %g1, SUN4V_CHIP_SPARC_M7 ++ be,pt %xcc, niagara4_patch ++ nop + + call generic_patch_copyops + nop +@@ -660,14 +672,12 @@ tlb_fixup_done: + sethi %hi(init_thread_union), %g6 + or %g6, %lo(init_thread_union), %g6 + ldx [%g6 + TI_TASK], %g4 +- mov %sp, %l6 + + wr %g0, ASI_P, %asi + mov 1, %g1 + sllx %g1, THREAD_SHIFT, %g1 + sub %g1, (STACKFRAME_SZ + STACK_BIAS), %g1 + add %g6, %g1, %sp +- mov 0, %fp + + /* Set per-cpu pointer initially to zero, this makes + * the boot-cpu use the in-kernel-image per-cpu areas +@@ -694,44 +704,14 @@ tlb_fixup_done: + nop + #endif + +- mov %l6, %o1 ! OpenPROM stack + call prom_init + mov %l7, %o0 ! OpenPROM cif handler + +- /* Initialize current_thread_info()->cpu as early as possible. +- * In order to do that accurately we have to patch up the get_cpuid() +- * assembler sequences. And that, in turn, requires that we know +- * if we are on a Starfire box or not. While we're here, patch up +- * the sun4v sequences as well. ++ /* To create a one-register-window buffer between the kernel's ++ * initial stack and the last stack frame we use from the firmware, ++ * do the rest of the boot from a C helper function. + */ +- call check_if_starfire +- nop +- call per_cpu_patch +- nop +- call sun4v_patch +- nop +- +-#ifdef CONFIG_SMP +- call hard_smp_processor_id +- nop +- cmp %o0, NR_CPUS +- blu,pt %xcc, 1f +- nop +- call boot_cpu_id_too_large +- nop +- /* Not reached... */ +- +-1: +-#else +- mov 0, %o0 +-#endif +- sth %o0, [%g6 + TI_CPU] +- +- call prom_init_report +- nop +- +- /* Off we go.... */ +- call start_kernel ++ call start_early_boot + nop + /* Not reached... */ + +diff --git a/arch/sparc/kernel/hvapi.c b/arch/sparc/kernel/hvapi.c +index c0a2de0fd624..5c55145bfbf0 100644 +--- a/arch/sparc/kernel/hvapi.c ++++ b/arch/sparc/kernel/hvapi.c +@@ -46,6 +46,7 @@ static struct api_info api_table[] = { + { .group = HV_GRP_VF_CPU, }, + { .group = HV_GRP_KT_CPU, }, + { .group = HV_GRP_VT_CPU, }, ++ { .group = HV_GRP_T5_CPU, }, + { .group = HV_GRP_DIAG, .flags = FLAG_PRE_API }, + }; + +diff --git a/arch/sparc/kernel/hvcalls.S b/arch/sparc/kernel/hvcalls.S +index f3ab509b76a8..caedf8320416 100644 +--- a/arch/sparc/kernel/hvcalls.S ++++ b/arch/sparc/kernel/hvcalls.S +@@ -821,3 +821,19 @@ ENTRY(sun4v_vt_set_perfreg) + retl + nop + ENDPROC(sun4v_vt_set_perfreg) ++ ++ENTRY(sun4v_t5_get_perfreg) ++ mov %o1, %o4 ++ mov HV_FAST_T5_GET_PERFREG, %o5 ++ ta HV_FAST_TRAP ++ stx %o1, [%o4] ++ retl ++ nop ++ENDPROC(sun4v_t5_get_perfreg) ++ ++ENTRY(sun4v_t5_set_perfreg) ++ mov HV_FAST_T5_SET_PERFREG, %o5 ++ ta HV_FAST_TRAP ++ retl ++ nop ++ENDPROC(sun4v_t5_set_perfreg) +diff --git a/arch/sparc/kernel/hvtramp.S b/arch/sparc/kernel/hvtramp.S +index b7ddcdd1dea9..cdbfec299f2f 100644 +--- a/arch/sparc/kernel/hvtramp.S ++++ b/arch/sparc/kernel/hvtramp.S +@@ -109,7 +109,6 @@ hv_cpu_startup: + sllx %g5, THREAD_SHIFT, %g5 + sub %g5, (STACKFRAME_SZ + STACK_BIAS), %g5 + add %g6, %g5, %sp +- mov 0, %fp + + call init_irqwork_curcpu + nop +diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c +index e7e215dfa866..c2d81ad62e78 100644 +--- a/arch/sparc/kernel/ioport.c ++++ b/arch/sparc/kernel/ioport.c +@@ -278,7 +278,8 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len, + } + + order = get_order(len_total); +- if ((va = __get_free_pages(GFP_KERNEL|__GFP_COMP, order)) == 0) ++ va = __get_free_pages(gfp, order); ++ if (va == 0) + goto err_nopages; + + if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) +@@ -443,7 +444,7 @@ static void *pci32_alloc_coherent(struct device *dev, size_t len, + } + + order = get_order(len_total); +- va = (void *) __get_free_pages(GFP_KERNEL, order); ++ va = (void *) __get_free_pages(gfp, order); + if (va == NULL) { + printk("pci_alloc_consistent: no %ld pages\n", len_total>>PAGE_SHIFT); + goto err_nopages; +diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c +index 666193f4e8bb..4033c23bdfa6 100644 +--- a/arch/sparc/kernel/irq_64.c ++++ b/arch/sparc/kernel/irq_64.c +@@ -47,8 +47,6 @@ + #include "cpumap.h" + #include "kstack.h" + +-#define NUM_IVECS (IMAP_INR + 1) +- + struct ino_bucket *ivector_table; + unsigned long ivector_table_pa; + +@@ -107,55 +105,196 @@ static void bucket_set_irq(unsigned long bucket_pa, unsigned int irq) + + #define irq_work_pa(__cpu) &(trap_block[(__cpu)].irq_worklist_pa) + +-static struct { +- unsigned int dev_handle; +- unsigned int dev_ino; +- unsigned int in_use; +-} irq_table[NR_IRQS]; +-static DEFINE_SPINLOCK(irq_alloc_lock); ++static unsigned long hvirq_major __initdata; ++static int __init early_hvirq_major(char *p) ++{ ++ int rc = kstrtoul(p, 10, &hvirq_major); ++ ++ return rc; ++} ++early_param("hvirq", early_hvirq_major); ++ ++static int hv_irq_version; ++ ++/* Major version 2.0 of HV_GRP_INTR added support for the VIRQ cookie ++ * based interfaces, but: ++ * ++ * 1) Several OSs, Solaris and Linux included, use them even when only ++ * negotiating version 1.0 (or failing to negotiate at all). So the ++ * hypervisor has a workaround that provides the VIRQ interfaces even ++ * when only verion 1.0 of the API is in use. ++ * ++ * 2) Second, and more importantly, with major version 2.0 these VIRQ ++ * interfaces only were actually hooked up for LDC interrupts, even ++ * though the Hypervisor specification clearly stated: ++ * ++ * The new interrupt API functions will be available to a guest ++ * when it negotiates version 2.0 in the interrupt API group 0x2. When ++ * a guest negotiates version 2.0, all interrupt sources will only ++ * support using the cookie interface, and any attempt to use the ++ * version 1.0 interrupt APIs numbered 0xa0 to 0xa6 will result in the ++ * ENOTSUPPORTED error being returned. ++ * ++ * with an emphasis on "all interrupt sources". ++ * ++ * To correct this, major version 3.0 was created which does actually ++ * support VIRQs for all interrupt sources (not just LDC devices). So ++ * if we want to move completely over the cookie based VIRQs we must ++ * negotiate major version 3.0 or later of HV_GRP_INTR. ++ */ ++static bool sun4v_cookie_only_virqs(void) ++{ ++ if (hv_irq_version >= 3) ++ return true; ++ return false; ++} + +-unsigned char irq_alloc(unsigned int dev_handle, unsigned int dev_ino) ++static void __init irq_init_hv(void) + { +- unsigned long flags; +- unsigned char ent; ++ unsigned long hv_error, major, minor = 0; ++ ++ if (tlb_type != hypervisor) ++ return; + +- BUILD_BUG_ON(NR_IRQS >= 256); ++ if (hvirq_major) ++ major = hvirq_major; ++ else ++ major = 3; + +- spin_lock_irqsave(&irq_alloc_lock, flags); ++ hv_error = sun4v_hvapi_register(HV_GRP_INTR, major, &minor); ++ if (!hv_error) ++ hv_irq_version = major; ++ else ++ hv_irq_version = 1; + +- for (ent = 1; ent < NR_IRQS; ent++) { +- if (!irq_table[ent].in_use) ++ pr_info("SUN4V: Using IRQ API major %d, cookie only virqs %s\n", ++ hv_irq_version, ++ sun4v_cookie_only_virqs() ? "enabled" : "disabled"); ++} ++ ++/* This function is for the timer interrupt.*/ ++int __init arch_probe_nr_irqs(void) ++{ ++ return 1; ++} ++ ++#define DEFAULT_NUM_IVECS (0xfffU) ++static unsigned int nr_ivec = DEFAULT_NUM_IVECS; ++#define NUM_IVECS (nr_ivec) ++ ++static unsigned int __init size_nr_ivec(void) ++{ ++ if (tlb_type == hypervisor) { ++ switch (sun4v_chip_type) { ++ /* Athena's devhandle|devino is large.*/ ++ case SUN4V_CHIP_SPARC64X: ++ nr_ivec = 0xffff; + break; ++ } + } +- if (ent >= NR_IRQS) { +- printk(KERN_ERR "IRQ: Out of virtual IRQs.\n"); +- ent = 0; +- } else { +- irq_table[ent].dev_handle = dev_handle; +- irq_table[ent].dev_ino = dev_ino; +- irq_table[ent].in_use = 1; +- } ++ return nr_ivec; ++} ++ ++struct irq_handler_data { ++ union { ++ struct { ++ unsigned int dev_handle; ++ unsigned int dev_ino; ++ }; ++ unsigned long sysino; ++ }; ++ struct ino_bucket bucket; ++ unsigned long iclr; ++ unsigned long imap; ++}; ++ ++static inline unsigned int irq_data_to_handle(struct irq_data *data) ++{ ++ struct irq_handler_data *ihd = data->handler_data; ++ ++ return ihd->dev_handle; ++} ++ ++static inline unsigned int irq_data_to_ino(struct irq_data *data) ++{ ++ struct irq_handler_data *ihd = data->handler_data; + +- spin_unlock_irqrestore(&irq_alloc_lock, flags); ++ return ihd->dev_ino; ++} ++ ++static inline unsigned long irq_data_to_sysino(struct irq_data *data) ++{ ++ struct irq_handler_data *ihd = data->handler_data; + +- return ent; ++ return ihd->sysino; + } + +-#ifdef CONFIG_PCI_MSI + void irq_free(unsigned int irq) + { +- unsigned long flags; ++ void *data = irq_get_handler_data(irq); + +- if (irq >= NR_IRQS) +- return; ++ kfree(data); ++ irq_set_handler_data(irq, NULL); ++ irq_free_descs(irq, 1); ++} + +- spin_lock_irqsave(&irq_alloc_lock, flags); ++unsigned int irq_alloc(unsigned int dev_handle, unsigned int dev_ino) ++{ ++ int irq; + +- irq_table[irq].in_use = 0; ++ irq = __irq_alloc_descs(-1, 1, 1, numa_node_id(), NULL); ++ if (irq <= 0) ++ goto out; + +- spin_unlock_irqrestore(&irq_alloc_lock, flags); ++ return irq; ++out: ++ return 0; ++} ++ ++static unsigned int cookie_exists(u32 devhandle, unsigned int devino) ++{ ++ unsigned long hv_err, cookie; ++ struct ino_bucket *bucket; ++ unsigned int irq = 0U; ++ ++ hv_err = sun4v_vintr_get_cookie(devhandle, devino, &cookie); ++ if (hv_err) { ++ pr_err("HV get cookie failed hv_err = %ld\n", hv_err); ++ goto out; ++ } ++ ++ if (cookie & ((1UL << 63UL))) { ++ cookie = ~cookie; ++ bucket = (struct ino_bucket *) __va(cookie); ++ irq = bucket->__irq; ++ } ++out: ++ return irq; ++} ++ ++static unsigned int sysino_exists(u32 devhandle, unsigned int devino) ++{ ++ unsigned long sysino = sun4v_devino_to_sysino(devhandle, devino); ++ struct ino_bucket *bucket; ++ unsigned int irq; ++ ++ bucket = &ivector_table[sysino]; ++ irq = bucket_get_irq(__pa(bucket)); ++ ++ return irq; ++} ++ ++void ack_bad_irq(unsigned int irq) ++{ ++ pr_crit("BAD IRQ ack %d\n", irq); ++} ++ ++void irq_install_pre_handler(int irq, ++ void (*func)(unsigned int, void *, void *), ++ void *arg1, void *arg2) ++{ ++ pr_warn("IRQ pre handler NOT supported.\n"); + } +-#endif + + /* + * /proc/interrupts printing: +@@ -206,15 +345,6 @@ static unsigned int sun4u_compute_tid(unsigned long imap, unsigned long cpuid) + return tid; + } + +-struct irq_handler_data { +- unsigned long iclr; +- unsigned long imap; +- +- void (*pre_handler)(unsigned int, void *, void *); +- void *arg1; +- void *arg2; +-}; +- + #ifdef CONFIG_SMP + static int irq_choose_cpu(unsigned int irq, const struct cpumask *affinity) + { +@@ -316,8 +446,8 @@ static void sun4u_irq_eoi(struct irq_data *data) + + static void sun4v_irq_enable(struct irq_data *data) + { +- unsigned int ino = irq_table[data->irq].dev_ino; + unsigned long cpuid = irq_choose_cpu(data->irq, data->affinity); ++ unsigned int ino = irq_data_to_sysino(data); + int err; + + err = sun4v_intr_settarget(ino, cpuid); +@@ -337,8 +467,8 @@ static void sun4v_irq_enable(struct irq_data *data) + static int sun4v_set_affinity(struct irq_data *data, + const struct cpumask *mask, bool force) + { +- unsigned int ino = irq_table[data->irq].dev_ino; + unsigned long cpuid = irq_choose_cpu(data->irq, mask); ++ unsigned int ino = irq_data_to_sysino(data); + int err; + + err = sun4v_intr_settarget(ino, cpuid); +@@ -351,7 +481,7 @@ static int sun4v_set_affinity(struct irq_data *data, + + static void sun4v_irq_disable(struct irq_data *data) + { +- unsigned int ino = irq_table[data->irq].dev_ino; ++ unsigned int ino = irq_data_to_sysino(data); + int err; + + err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); +@@ -362,7 +492,7 @@ static void sun4v_irq_disable(struct irq_data *data) + + static void sun4v_irq_eoi(struct irq_data *data) + { +- unsigned int ino = irq_table[data->irq].dev_ino; ++ unsigned int ino = irq_data_to_sysino(data); + int err; + + err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); +@@ -373,14 +503,13 @@ static void sun4v_irq_eoi(struct irq_data *data) + + static void sun4v_virq_enable(struct irq_data *data) + { +- unsigned long cpuid, dev_handle, dev_ino; ++ unsigned long dev_handle = irq_data_to_handle(data); ++ unsigned long dev_ino = irq_data_to_ino(data); ++ unsigned long cpuid; + int err; + + cpuid = irq_choose_cpu(data->irq, data->affinity); + +- dev_handle = irq_table[data->irq].dev_handle; +- dev_ino = irq_table[data->irq].dev_ino; +- + err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): " +@@ -403,14 +532,13 @@ static void sun4v_virq_enable(struct irq_data *data) + static int sun4v_virt_set_affinity(struct irq_data *data, + const struct cpumask *mask, bool force) + { +- unsigned long cpuid, dev_handle, dev_ino; ++ unsigned long dev_handle = irq_data_to_handle(data); ++ unsigned long dev_ino = irq_data_to_ino(data); ++ unsigned long cpuid; + int err; + + cpuid = irq_choose_cpu(data->irq, mask); + +- dev_handle = irq_table[data->irq].dev_handle; +- dev_ino = irq_table[data->irq].dev_ino; +- + err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): " +@@ -422,11 +550,10 @@ static int sun4v_virt_set_affinity(struct irq_data *data, + + static void sun4v_virq_disable(struct irq_data *data) + { +- unsigned long dev_handle, dev_ino; ++ unsigned long dev_handle = irq_data_to_handle(data); ++ unsigned long dev_ino = irq_data_to_ino(data); + int err; + +- dev_handle = irq_table[data->irq].dev_handle; +- dev_ino = irq_table[data->irq].dev_ino; + + err = sun4v_vintr_set_valid(dev_handle, dev_ino, + HV_INTR_DISABLED); +@@ -438,12 +565,10 @@ static void sun4v_virq_disable(struct irq_data *data) + + static void sun4v_virq_eoi(struct irq_data *data) + { +- unsigned long dev_handle, dev_ino; ++ unsigned long dev_handle = irq_data_to_handle(data); ++ unsigned long dev_ino = irq_data_to_ino(data); + int err; + +- dev_handle = irq_table[data->irq].dev_handle; +- dev_ino = irq_table[data->irq].dev_ino; +- + err = sun4v_vintr_set_state(dev_handle, dev_ino, + HV_INTR_STATE_IDLE); + if (err != HV_EOK) +@@ -479,31 +604,10 @@ static struct irq_chip sun4v_virq = { + .flags = IRQCHIP_EOI_IF_HANDLED, + }; + +-static void pre_flow_handler(struct irq_data *d) +-{ +- struct irq_handler_data *handler_data = irq_data_get_irq_handler_data(d); +- unsigned int ino = irq_table[d->irq].dev_ino; +- +- handler_data->pre_handler(ino, handler_data->arg1, handler_data->arg2); +-} +- +-void irq_install_pre_handler(int irq, +- void (*func)(unsigned int, void *, void *), +- void *arg1, void *arg2) +-{ +- struct irq_handler_data *handler_data = irq_get_handler_data(irq); +- +- handler_data->pre_handler = func; +- handler_data->arg1 = arg1; +- handler_data->arg2 = arg2; +- +- __irq_set_preflow_handler(irq, pre_flow_handler); +-} +- + unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) + { +- struct ino_bucket *bucket; + struct irq_handler_data *handler_data; ++ struct ino_bucket *bucket; + unsigned int irq; + int ino; + +@@ -537,119 +641,166 @@ out: + return irq; + } + +-static unsigned int sun4v_build_common(unsigned long sysino, +- struct irq_chip *chip) ++static unsigned int sun4v_build_common(u32 devhandle, unsigned int devino, ++ void (*handler_data_init)(struct irq_handler_data *data, ++ u32 devhandle, unsigned int devino), ++ struct irq_chip *chip) + { +- struct ino_bucket *bucket; +- struct irq_handler_data *handler_data; ++ struct irq_handler_data *data; + unsigned int irq; + +- BUG_ON(tlb_type != hypervisor); ++ irq = irq_alloc(devhandle, devino); ++ if (!irq) ++ goto out; + +- bucket = &ivector_table[sysino]; +- irq = bucket_get_irq(__pa(bucket)); +- if (!irq) { +- irq = irq_alloc(0, sysino); +- bucket_set_irq(__pa(bucket), irq); +- irq_set_chip_and_handler_name(irq, chip, handle_fasteoi_irq, +- "IVEC"); ++ data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); ++ if (unlikely(!data)) { ++ pr_err("IRQ handler data allocation failed.\n"); ++ irq_free(irq); ++ irq = 0; ++ goto out; + } + +- handler_data = irq_get_handler_data(irq); +- if (unlikely(handler_data)) +- goto out; ++ irq_set_handler_data(irq, data); ++ handler_data_init(data, devhandle, devino); ++ irq_set_chip_and_handler_name(irq, chip, handle_fasteoi_irq, "IVEC"); ++ data->imap = ~0UL; ++ data->iclr = ~0UL; ++out: ++ return irq; ++} + +- handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); +- if (unlikely(!handler_data)) { +- prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); +- prom_halt(); +- } +- irq_set_handler_data(irq, handler_data); ++static unsigned long cookie_assign(unsigned int irq, u32 devhandle, ++ unsigned int devino) ++{ ++ struct irq_handler_data *ihd = irq_get_handler_data(irq); ++ unsigned long hv_error, cookie; + +- /* Catch accidental accesses to these things. IMAP/ICLR handling +- * is done by hypervisor calls on sun4v platforms, not by direct +- * register accesses. ++ /* handler_irq needs to find the irq. cookie is seen signed in ++ * sun4v_dev_mondo and treated as a non ivector_table delivery. + */ +- handler_data->imap = ~0UL; +- handler_data->iclr = ~0UL; ++ ihd->bucket.__irq = irq; ++ cookie = ~__pa(&ihd->bucket); + +-out: +- return irq; ++ hv_error = sun4v_vintr_set_cookie(devhandle, devino, cookie); ++ if (hv_error) ++ pr_err("HV vintr set cookie failed = %ld\n", hv_error); ++ ++ return hv_error; + } + +-unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) ++static void cookie_handler_data(struct irq_handler_data *data, ++ u32 devhandle, unsigned int devino) + { +- unsigned long sysino = sun4v_devino_to_sysino(devhandle, devino); ++ data->dev_handle = devhandle; ++ data->dev_ino = devino; ++} + +- return sun4v_build_common(sysino, &sun4v_irq); ++static unsigned int cookie_build_irq(u32 devhandle, unsigned int devino, ++ struct irq_chip *chip) ++{ ++ unsigned long hv_error; ++ unsigned int irq; ++ ++ irq = sun4v_build_common(devhandle, devino, cookie_handler_data, chip); ++ ++ hv_error = cookie_assign(irq, devhandle, devino); ++ if (hv_error) { ++ irq_free(irq); ++ irq = 0; ++ } ++ ++ return irq; + } + +-unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) ++static unsigned int sun4v_build_cookie(u32 devhandle, unsigned int devino) + { +- struct irq_handler_data *handler_data; +- unsigned long hv_err, cookie; +- struct ino_bucket *bucket; + unsigned int irq; + +- bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC); +- if (unlikely(!bucket)) +- return 0; ++ irq = cookie_exists(devhandle, devino); ++ if (irq) ++ goto out; + +- /* The only reference we store to the IRQ bucket is +- * by physical address which kmemleak can't see, tell +- * it that this object explicitly is not a leak and +- * should be scanned. +- */ +- kmemleak_not_leak(bucket); ++ irq = cookie_build_irq(devhandle, devino, &sun4v_virq); + +- __flush_dcache_range((unsigned long) bucket, +- ((unsigned long) bucket + +- sizeof(struct ino_bucket))); ++out: ++ return irq; ++} + +- irq = irq_alloc(devhandle, devino); ++static void sysino_set_bucket(unsigned int irq) ++{ ++ struct irq_handler_data *ihd = irq_get_handler_data(irq); ++ struct ino_bucket *bucket; ++ unsigned long sysino; ++ ++ sysino = sun4v_devino_to_sysino(ihd->dev_handle, ihd->dev_ino); ++ BUG_ON(sysino >= nr_ivec); ++ bucket = &ivector_table[sysino]; + bucket_set_irq(__pa(bucket), irq); ++} + +- irq_set_chip_and_handler_name(irq, &sun4v_virq, handle_fasteoi_irq, +- "IVEC"); ++static void sysino_handler_data(struct irq_handler_data *data, ++ u32 devhandle, unsigned int devino) ++{ ++ unsigned long sysino; + +- handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); +- if (unlikely(!handler_data)) +- return 0; ++ sysino = sun4v_devino_to_sysino(devhandle, devino); ++ data->sysino = sysino; ++} + +- /* In order to make the LDC channel startup sequence easier, +- * especially wrt. locking, we do not let request_irq() enable +- * the interrupt. +- */ +- irq_set_status_flags(irq, IRQ_NOAUTOEN); +- irq_set_handler_data(irq, handler_data); ++static unsigned int sysino_build_irq(u32 devhandle, unsigned int devino, ++ struct irq_chip *chip) ++{ ++ unsigned int irq; + +- /* Catch accidental accesses to these things. IMAP/ICLR handling +- * is done by hypervisor calls on sun4v platforms, not by direct +- * register accesses. +- */ +- handler_data->imap = ~0UL; +- handler_data->iclr = ~0UL; ++ irq = sun4v_build_common(devhandle, devino, sysino_handler_data, chip); ++ if (!irq) ++ goto out; + +- cookie = ~__pa(bucket); +- hv_err = sun4v_vintr_set_cookie(devhandle, devino, cookie); +- if (hv_err) { +- prom_printf("IRQ: Fatal, cannot set cookie for [%x:%x] " +- "err=%lu\n", devhandle, devino, hv_err); +- prom_halt(); +- } ++ sysino_set_bucket(irq); ++out: ++ return irq; ++} + ++static int sun4v_build_sysino(u32 devhandle, unsigned int devino) ++{ ++ int irq; ++ ++ irq = sysino_exists(devhandle, devino); ++ if (irq) ++ goto out; ++ ++ irq = sysino_build_irq(devhandle, devino, &sun4v_irq); ++out: + return irq; + } + +-void ack_bad_irq(unsigned int irq) ++unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) + { +- unsigned int ino = irq_table[irq].dev_ino; ++ unsigned int irq; + +- if (!ino) +- ino = 0xdeadbeef; ++ if (sun4v_cookie_only_virqs()) ++ irq = sun4v_build_cookie(devhandle, devino); ++ else ++ irq = sun4v_build_sysino(devhandle, devino); + +- printk(KERN_CRIT "Unexpected IRQ from ino[%x] irq[%u]\n", +- ino, irq); ++ return irq; ++} ++ ++unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) ++{ ++ int irq; ++ ++ irq = cookie_build_irq(devhandle, devino, &sun4v_virq); ++ if (!irq) ++ goto out; ++ ++ /* This is borrowed from the original function. ++ */ ++ irq_set_status_flags(irq, IRQ_NOAUTOEN); ++ ++out: ++ return irq; + } + + void *hardirq_stack[NR_CPUS]; +@@ -720,9 +871,12 @@ void fixup_irqs(void) + + for (irq = 0; irq < NR_IRQS; irq++) { + struct irq_desc *desc = irq_to_desc(irq); +- struct irq_data *data = irq_desc_get_irq_data(desc); ++ struct irq_data *data; + unsigned long flags; + ++ if (!desc) ++ continue; ++ data = irq_desc_get_irq_data(desc); + raw_spin_lock_irqsave(&desc->lock, flags); + if (desc->action && !irqd_is_per_cpu(data)) { + if (data->chip->irq_set_affinity) +@@ -922,16 +1076,22 @@ static struct irqaction timer_irq_action = { + .name = "timer", + }; + +-/* Only invoked on boot processor. */ +-void __init init_IRQ(void) ++static void __init irq_ivector_init(void) + { +- unsigned long size; ++ unsigned long size, order; ++ unsigned int ivecs; + +- map_prom_timers(); +- kill_prom_timer(); ++ /* If we are doing cookie only VIRQs then we do not need the ivector ++ * table to process interrupts. ++ */ ++ if (sun4v_cookie_only_virqs()) ++ return; + +- size = sizeof(struct ino_bucket) * NUM_IVECS; +- ivector_table = kzalloc(size, GFP_KERNEL); ++ ivecs = size_nr_ivec(); ++ size = sizeof(struct ino_bucket) * ivecs; ++ order = get_order(size); ++ ivector_table = (struct ino_bucket *) ++ __get_free_pages(GFP_KERNEL | __GFP_ZERO, order); + if (!ivector_table) { + prom_printf("Fatal error, cannot allocate ivector_table\n"); + prom_halt(); +@@ -940,6 +1100,15 @@ void __init init_IRQ(void) + ((unsigned long) ivector_table) + size); + + ivector_table_pa = __pa(ivector_table); ++} ++ ++/* Only invoked on boot processor.*/ ++void __init init_IRQ(void) ++{ ++ irq_init_hv(); ++ irq_ivector_init(); ++ map_prom_timers(); ++ kill_prom_timer(); + + if (tlb_type == hypervisor) + sun4v_init_mondo_queues(); +diff --git a/arch/sparc/kernel/ktlb.S b/arch/sparc/kernel/ktlb.S +index 605d49204580..ef0d8e9e1210 100644 +--- a/arch/sparc/kernel/ktlb.S ++++ b/arch/sparc/kernel/ktlb.S +@@ -47,14 +47,6 @@ kvmap_itlb_vmalloc_addr: + KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_itlb_longpath) + + TSB_LOCK_TAG(%g1, %g2, %g7) +- +- /* Load and check PTE. */ +- ldxa [%g5] ASI_PHYS_USE_EC, %g5 +- mov 1, %g7 +- sllx %g7, TSB_TAG_INVALID_BIT, %g7 +- brgez,a,pn %g5, kvmap_itlb_longpath +- TSB_STORE(%g1, %g7) +- + TSB_WRITE(%g1, %g5, %g6) + + /* fallthrough to TLB load */ +@@ -118,6 +110,12 @@ kvmap_dtlb_obp: + ba,pt %xcc, kvmap_dtlb_load + nop + ++kvmap_linear_early: ++ sethi %hi(kern_linear_pte_xor), %g7 ++ ldx [%g7 + %lo(kern_linear_pte_xor)], %g2 ++ ba,pt %xcc, kvmap_dtlb_tsb4m_load ++ xor %g2, %g4, %g5 ++ + .align 32 + kvmap_dtlb_tsb4m_load: + TSB_LOCK_TAG(%g1, %g2, %g7) +@@ -146,105 +144,17 @@ kvmap_dtlb_4v: + /* Correct TAG_TARGET is already in %g6, check 4mb TSB. */ + KERN_TSB4M_LOOKUP_TL1(%g6, %g5, %g1, %g2, %g3, kvmap_dtlb_load) + #endif +- /* TSB entry address left in %g1, lookup linear PTE. +- * Must preserve %g1 and %g6 (TAG). +- */ +-kvmap_dtlb_tsb4m_miss: +- /* Clear the PAGE_OFFSET top virtual bits, shift +- * down to get PFN, and make sure PFN is in range. +- */ +-661: sllx %g4, 0, %g5 +- .section .page_offset_shift_patch, "ax" +- .word 661b +- .previous +- +- /* Check to see if we know about valid memory at the 4MB +- * chunk this physical address will reside within. ++ /* Linear mapping TSB lookup failed. Fallthrough to kernel ++ * page table based lookup. + */ +-661: srlx %g5, MAX_PHYS_ADDRESS_BITS, %g2 +- .section .page_offset_shift_patch, "ax" +- .word 661b +- .previous +- +- brnz,pn %g2, kvmap_dtlb_longpath +- nop +- +- /* This unconditional branch and delay-slot nop gets patched +- * by the sethi sequence once the bitmap is properly setup. +- */ +- .globl valid_addr_bitmap_insn +-valid_addr_bitmap_insn: +- ba,pt %xcc, 2f +- nop +- .subsection 2 +- .globl valid_addr_bitmap_patch +-valid_addr_bitmap_patch: +- sethi %hi(sparc64_valid_addr_bitmap), %g7 +- or %g7, %lo(sparc64_valid_addr_bitmap), %g7 +- .previous +- +-661: srlx %g5, ILOG2_4MB, %g2 +- .section .page_offset_shift_patch, "ax" +- .word 661b +- .previous +- +- srlx %g2, 6, %g5 +- and %g2, 63, %g2 +- sllx %g5, 3, %g5 +- ldx [%g7 + %g5], %g5 +- mov 1, %g7 +- sllx %g7, %g2, %g7 +- andcc %g5, %g7, %g0 +- be,pn %xcc, kvmap_dtlb_longpath +- +-2: sethi %hi(kpte_linear_bitmap), %g2 +- +- /* Get the 256MB physical address index. */ +-661: sllx %g4, 0, %g5 +- .section .page_offset_shift_patch, "ax" +- .word 661b +- .previous +- +- or %g2, %lo(kpte_linear_bitmap), %g2 +- +-661: srlx %g5, ILOG2_256MB, %g5 +- .section .page_offset_shift_patch, "ax" +- .word 661b +- .previous +- +- and %g5, (32 - 1), %g7 +- +- /* Divide by 32 to get the offset into the bitmask. */ +- srlx %g5, 5, %g5 +- add %g7, %g7, %g7 +- sllx %g5, 3, %g5 +- +- /* kern_linear_pte_xor[(mask >> shift) & 3)] */ +- ldx [%g2 + %g5], %g2 +- srlx %g2, %g7, %g7 +- sethi %hi(kern_linear_pte_xor), %g5 +- and %g7, 3, %g7 +- or %g5, %lo(kern_linear_pte_xor), %g5 +- sllx %g7, 3, %g7 +- ldx [%g5 + %g7], %g2 +- + .globl kvmap_linear_patch + kvmap_linear_patch: +- ba,pt %xcc, kvmap_dtlb_tsb4m_load +- xor %g2, %g4, %g5 ++ ba,a,pt %xcc, kvmap_linear_early + + kvmap_dtlb_vmalloc_addr: + KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_dtlb_longpath) + + TSB_LOCK_TAG(%g1, %g2, %g7) +- +- /* Load and check PTE. */ +- ldxa [%g5] ASI_PHYS_USE_EC, %g5 +- mov 1, %g7 +- sllx %g7, TSB_TAG_INVALID_BIT, %g7 +- brgez,a,pn %g5, kvmap_dtlb_longpath +- TSB_STORE(%g1, %g7) +- + TSB_WRITE(%g1, %g5, %g6) + + /* fallthrough to TLB load */ +@@ -276,13 +186,8 @@ kvmap_dtlb_load: + + #ifdef CONFIG_SPARSEMEM_VMEMMAP + kvmap_vmemmap: +- sub %g4, %g5, %g5 +- srlx %g5, ILOG2_4MB, %g5 +- sethi %hi(vmemmap_table), %g1 +- sllx %g5, 3, %g5 +- or %g1, %lo(vmemmap_table), %g1 +- ba,pt %xcc, kvmap_dtlb_load +- ldx [%g1 + %g5], %g5 ++ KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_dtlb_longpath) ++ ba,a,pt %xcc, kvmap_dtlb_load + #endif + + kvmap_dtlb_nonlinear: +@@ -294,8 +199,8 @@ kvmap_dtlb_nonlinear: + + #ifdef CONFIG_SPARSEMEM_VMEMMAP + /* Do not use the TSB for vmemmap. */ +- mov (VMEMMAP_BASE >> 40), %g5 +- sllx %g5, 40, %g5 ++ sethi %hi(VMEMMAP_BASE), %g5 ++ ldx [%g5 + %lo(VMEMMAP_BASE)], %g5 + cmp %g4,%g5 + bgeu,pn %xcc, kvmap_vmemmap + nop +@@ -307,8 +212,8 @@ kvmap_dtlb_tsbmiss: + sethi %hi(MODULES_VADDR), %g5 + cmp %g4, %g5 + blu,pn %xcc, kvmap_dtlb_longpath +- mov (VMALLOC_END >> 40), %g5 +- sllx %g5, 40, %g5 ++ sethi %hi(VMALLOC_END), %g5 ++ ldx [%g5 + %lo(VMALLOC_END)], %g5 + cmp %g4, %g5 + bgeu,pn %xcc, kvmap_dtlb_longpath + nop +diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c +index 66dacd56bb10..27bb55485472 100644 +--- a/arch/sparc/kernel/ldc.c ++++ b/arch/sparc/kernel/ldc.c +@@ -1078,7 +1078,8 @@ static void ldc_iommu_release(struct ldc_channel *lp) + + struct ldc_channel *ldc_alloc(unsigned long id, + const struct ldc_channel_config *cfgp, +- void *event_arg) ++ void *event_arg, ++ const char *name) + { + struct ldc_channel *lp; + const struct ldc_mode_ops *mops; +@@ -1093,6 +1094,8 @@ struct ldc_channel *ldc_alloc(unsigned long id, + err = -EINVAL; + if (!cfgp) + goto out_err; ++ if (!name) ++ goto out_err; + + switch (cfgp->mode) { + case LDC_MODE_RAW: +@@ -1185,6 +1188,21 @@ struct ldc_channel *ldc_alloc(unsigned long id, + + INIT_HLIST_HEAD(&lp->mh_list); + ++ snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name); ++ snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name); ++ ++ err = request_irq(lp->cfg.rx_irq, ldc_rx, 0, ++ lp->rx_irq_name, lp); ++ if (err) ++ goto out_free_txq; ++ ++ err = request_irq(lp->cfg.tx_irq, ldc_tx, 0, ++ lp->tx_irq_name, lp); ++ if (err) { ++ free_irq(lp->cfg.rx_irq, lp); ++ goto out_free_txq; ++ } ++ + return lp; + + out_free_txq: +@@ -1237,31 +1255,14 @@ EXPORT_SYMBOL(ldc_free); + * state. This does not initiate a handshake, ldc_connect() does + * that. + */ +-int ldc_bind(struct ldc_channel *lp, const char *name) ++int ldc_bind(struct ldc_channel *lp) + { + unsigned long hv_err, flags; + int err = -EINVAL; + +- if (!name || +- (lp->state != LDC_STATE_INIT)) ++ if (lp->state != LDC_STATE_INIT) + return -EINVAL; + +- snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name); +- snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name); +- +- err = request_irq(lp->cfg.rx_irq, ldc_rx, 0, +- lp->rx_irq_name, lp); +- if (err) +- return err; +- +- err = request_irq(lp->cfg.tx_irq, ldc_tx, 0, +- lp->tx_irq_name, lp); +- if (err) { +- free_irq(lp->cfg.rx_irq, lp); +- return err; +- } +- +- + spin_lock_irqsave(&lp->lock, flags); + + enable_irq(lp->cfg.rx_irq); +diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c +index 6479256fd5a4..fce8ab17bcbb 100644 +--- a/arch/sparc/kernel/nmi.c ++++ b/arch/sparc/kernel/nmi.c +@@ -141,7 +141,6 @@ static inline unsigned int get_nmi_count(int cpu) + + static __init void nmi_cpu_busy(void *data) + { +- local_irq_enable_in_hardirq(); + while (endflag == 0) + mb(); + } +diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c +index 269af58497aa..7e967c8018c8 100644 +--- a/arch/sparc/kernel/pcr.c ++++ b/arch/sparc/kernel/pcr.c +@@ -191,12 +191,41 @@ static const struct pcr_ops n4_pcr_ops = { + .pcr_nmi_disable = PCR_N4_PICNPT, + }; + ++static u64 n5_pcr_read(unsigned long reg_num) ++{ ++ unsigned long val; ++ ++ (void) sun4v_t5_get_perfreg(reg_num, &val); ++ ++ return val; ++} ++ ++static void n5_pcr_write(unsigned long reg_num, u64 val) ++{ ++ (void) sun4v_t5_set_perfreg(reg_num, val); ++} ++ ++static const struct pcr_ops n5_pcr_ops = { ++ .read_pcr = n5_pcr_read, ++ .write_pcr = n5_pcr_write, ++ .read_pic = n4_pic_read, ++ .write_pic = n4_pic_write, ++ .nmi_picl_value = n4_picl_value, ++ .pcr_nmi_enable = (PCR_N4_PICNPT | PCR_N4_STRACE | ++ PCR_N4_UTRACE | PCR_N4_TOE | ++ (26 << PCR_N4_SL_SHIFT)), ++ .pcr_nmi_disable = PCR_N4_PICNPT, ++}; ++ ++ + static unsigned long perf_hsvc_group; + static unsigned long perf_hsvc_major; + static unsigned long perf_hsvc_minor; + + static int __init register_perf_hsvc(void) + { ++ unsigned long hverror; ++ + if (tlb_type == hypervisor) { + switch (sun4v_chip_type) { + case SUN4V_CHIP_NIAGARA1: +@@ -215,6 +244,10 @@ static int __init register_perf_hsvc(void) + perf_hsvc_group = HV_GRP_VT_CPU; + break; + ++ case SUN4V_CHIP_NIAGARA5: ++ perf_hsvc_group = HV_GRP_T5_CPU; ++ break; ++ + default: + return -ENODEV; + } +@@ -222,10 +255,12 @@ static int __init register_perf_hsvc(void) + + perf_hsvc_major = 1; + perf_hsvc_minor = 0; +- if (sun4v_hvapi_register(perf_hsvc_group, +- perf_hsvc_major, +- &perf_hsvc_minor)) { +- printk("perfmon: Could not register hvapi.\n"); ++ hverror = sun4v_hvapi_register(perf_hsvc_group, ++ perf_hsvc_major, ++ &perf_hsvc_minor); ++ if (hverror) { ++ pr_err("perfmon: Could not register hvapi(0x%lx).\n", ++ hverror); + return -ENODEV; + } + } +@@ -254,6 +289,10 @@ static int __init setup_sun4v_pcr_ops(void) + pcr_ops = &n4_pcr_ops; + break; + ++ case SUN4V_CHIP_NIAGARA5: ++ pcr_ops = &n5_pcr_ops; ++ break; ++ + default: + ret = -ENODEV; + break; +diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c +index b5c38faa4ead..617b9fe33771 100644 +--- a/arch/sparc/kernel/perf_event.c ++++ b/arch/sparc/kernel/perf_event.c +@@ -1662,7 +1662,8 @@ static bool __init supported_pmu(void) + sparc_pmu = &niagara2_pmu; + return true; + } +- if (!strcmp(sparc_pmu_type, "niagara4")) { ++ if (!strcmp(sparc_pmu_type, "niagara4") || ++ !strcmp(sparc_pmu_type, "niagara5")) { + sparc_pmu = &niagara4_pmu; + return true; + } +@@ -1671,9 +1672,12 @@ static bool __init supported_pmu(void) + + int __init init_hw_perf_events(void) + { ++ int err; ++ + pr_info("Performance events: "); + +- if (!supported_pmu()) { ++ err = pcr_arch_init(); ++ if (err || !supported_pmu()) { + pr_cont("No support for PMU type '%s'\n", sparc_pmu_type); + return 0; + } +@@ -1685,7 +1689,7 @@ int __init init_hw_perf_events(void) + + return 0; + } +-early_initcall(init_hw_perf_events); ++pure_initcall(init_hw_perf_events); + + void perf_callchain_kernel(struct perf_callchain_entry *entry, + struct pt_regs *regs) +diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c +index d7b4967f8fa6..c6f7113b6e2f 100644 +--- a/arch/sparc/kernel/process_64.c ++++ b/arch/sparc/kernel/process_64.c +@@ -306,6 +306,9 @@ static void __global_pmu_self(int this_cpu) + struct global_pmu_snapshot *pp; + int i, num; + ++ if (!pcr_ops) ++ return; ++ + pp = &global_cpu_snapshot[this_cpu].pmu; + + num = 1; +diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c +index 3fdb455e3318..61a519808cb7 100644 +--- a/arch/sparc/kernel/setup_64.c ++++ b/arch/sparc/kernel/setup_64.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -174,7 +175,7 @@ char reboot_command[COMMAND_LINE_SIZE]; + + static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 }; + +-void __init per_cpu_patch(void) ++static void __init per_cpu_patch(void) + { + struct cpuid_patch_entry *p; + unsigned long ver; +@@ -266,7 +267,7 @@ void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start, + } + } + +-void __init sun4v_patch(void) ++static void __init sun4v_patch(void) + { + extern void sun4v_hvapi_init(void); + +@@ -335,14 +336,25 @@ static void __init pause_patch(void) + } + } + +-#ifdef CONFIG_SMP +-void __init boot_cpu_id_too_large(int cpu) ++void __init start_early_boot(void) + { +- prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n", +- cpu, NR_CPUS); +- prom_halt(); ++ int cpu; ++ ++ check_if_starfire(); ++ per_cpu_patch(); ++ sun4v_patch(); ++ ++ cpu = hard_smp_processor_id(); ++ if (cpu >= NR_CPUS) { ++ prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n", ++ cpu, NR_CPUS); ++ prom_halt(); ++ } ++ current_thread_info()->cpu = cpu; ++ ++ prom_init_report(); ++ start_kernel(); + } +-#endif + + /* On Ultra, we support all of the v8 capabilities. */ + unsigned long sparc64_elf_hwcap = (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | +@@ -500,12 +512,16 @@ static void __init init_sparc64_elf_hwcap(void) + sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA5 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M6 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M7 || + sun4v_chip_type == SUN4V_CHIP_SPARC64X) + cap |= HWCAP_SPARC_BLKINIT; + if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA5 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M6 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M7 || + sun4v_chip_type == SUN4V_CHIP_SPARC64X) + cap |= HWCAP_SPARC_N2; + } +@@ -533,6 +549,8 @@ static void __init init_sparc64_elf_hwcap(void) + sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA5 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M6 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M7 || + sun4v_chip_type == SUN4V_CHIP_SPARC64X) + cap |= (AV_SPARC_VIS | AV_SPARC_VIS2 | + AV_SPARC_ASI_BLK_INIT | +@@ -540,6 +558,8 @@ static void __init init_sparc64_elf_hwcap(void) + if (sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA5 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M6 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M7 || + sun4v_chip_type == SUN4V_CHIP_SPARC64X) + cap |= (AV_SPARC_VIS3 | AV_SPARC_HPC | + AV_SPARC_FMAF); +diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c +index 8416d7fadcce..50c3dd03be31 100644 +--- a/arch/sparc/kernel/smp_64.c ++++ b/arch/sparc/kernel/smp_64.c +@@ -1395,7 +1395,6 @@ void __cpu_die(unsigned int cpu) + + void __init smp_cpus_done(unsigned int max_cpus) + { +- pcr_arch_init(); + } + + void smp_send_reschedule(int cpu) +@@ -1480,6 +1479,13 @@ static void __init pcpu_populate_pte(unsigned long addr) + pud_t *pud; + pmd_t *pmd; + ++ if (pgd_none(*pgd)) { ++ pud_t *new; ++ ++ new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); ++ pgd_populate(&init_mm, pgd, new); ++ } ++ + pud = pud_offset(pgd, addr); + if (pud_none(*pud)) { + pmd_t *new; +diff --git a/arch/sparc/kernel/sun4v_tlb_miss.S b/arch/sparc/kernel/sun4v_tlb_miss.S +index e0c09bf85610..6179e19bc9b9 100644 +--- a/arch/sparc/kernel/sun4v_tlb_miss.S ++++ b/arch/sparc/kernel/sun4v_tlb_miss.S +@@ -195,6 +195,11 @@ sun4v_tsb_miss_common: + ldx [%g2 + TRAP_PER_CPU_PGD_PADDR], %g7 + + sun4v_itlb_error: ++ rdpr %tl, %g1 ++ cmp %g1, 1 ++ ble,pt %icc, sun4v_bad_ra ++ or %g0, FAULT_CODE_BAD_RA | FAULT_CODE_ITLB, %g1 ++ + sethi %hi(sun4v_err_itlb_vaddr), %g1 + stx %g4, [%g1 + %lo(sun4v_err_itlb_vaddr)] + sethi %hi(sun4v_err_itlb_ctx), %g1 +@@ -206,15 +211,10 @@ sun4v_itlb_error: + sethi %hi(sun4v_err_itlb_error), %g1 + stx %o0, [%g1 + %lo(sun4v_err_itlb_error)] + ++ sethi %hi(1f), %g7 + rdpr %tl, %g4 +- cmp %g4, 1 +- ble,pt %icc, 1f +- sethi %hi(2f), %g7 + ba,pt %xcc, etraptl1 +- or %g7, %lo(2f), %g7 +- +-1: ba,pt %xcc, etrap +-2: or %g7, %lo(2b), %g7 ++1: or %g7, %lo(1f), %g7 + mov %l4, %o1 + call sun4v_itlb_error_report + add %sp, PTREGS_OFF, %o0 +@@ -222,6 +222,11 @@ sun4v_itlb_error: + /* NOTREACHED */ + + sun4v_dtlb_error: ++ rdpr %tl, %g1 ++ cmp %g1, 1 ++ ble,pt %icc, sun4v_bad_ra ++ or %g0, FAULT_CODE_BAD_RA | FAULT_CODE_DTLB, %g1 ++ + sethi %hi(sun4v_err_dtlb_vaddr), %g1 + stx %g4, [%g1 + %lo(sun4v_err_dtlb_vaddr)] + sethi %hi(sun4v_err_dtlb_ctx), %g1 +@@ -233,21 +238,23 @@ sun4v_dtlb_error: + sethi %hi(sun4v_err_dtlb_error), %g1 + stx %o0, [%g1 + %lo(sun4v_err_dtlb_error)] + ++ sethi %hi(1f), %g7 + rdpr %tl, %g4 +- cmp %g4, 1 +- ble,pt %icc, 1f +- sethi %hi(2f), %g7 + ba,pt %xcc, etraptl1 +- or %g7, %lo(2f), %g7 +- +-1: ba,pt %xcc, etrap +-2: or %g7, %lo(2b), %g7 ++1: or %g7, %lo(1f), %g7 + mov %l4, %o1 + call sun4v_dtlb_error_report + add %sp, PTREGS_OFF, %o0 + + /* NOTREACHED */ + ++sun4v_bad_ra: ++ or %g0, %g4, %g5 ++ ba,pt %xcc, sparc64_realfault_common ++ or %g1, %g0, %g4 ++ ++ /* NOTREACHED */ ++ + /* Instruction Access Exception, tl0. */ + sun4v_iacc: + ldxa [%g0] ASI_SCRATCHPAD, %g2 +diff --git a/arch/sparc/kernel/trampoline_64.S b/arch/sparc/kernel/trampoline_64.S +index 737f8cbc7d56..88ede1d53b4c 100644 +--- a/arch/sparc/kernel/trampoline_64.S ++++ b/arch/sparc/kernel/trampoline_64.S +@@ -109,10 +109,13 @@ startup_continue: + brnz,pn %g1, 1b + nop + +- sethi %hi(p1275buf), %g2 +- or %g2, %lo(p1275buf), %g2 +- ldx [%g2 + 0x10], %l2 +- add %l2, -(192 + 128), %sp ++ /* Get onto temporary stack which will be in the locked ++ * kernel image. ++ */ ++ sethi %hi(tramp_stack), %g1 ++ or %g1, %lo(tramp_stack), %g1 ++ add %g1, TRAMP_STACK_SIZE, %g1 ++ sub %g1, STACKFRAME_SZ + STACK_BIAS + 256, %sp + flushw + + /* Setup the loop variables: +@@ -394,7 +397,6 @@ after_lock_tlb: + sllx %g5, THREAD_SHIFT, %g5 + sub %g5, (STACKFRAME_SZ + STACK_BIAS), %g5 + add %g6, %g5, %sp +- mov 0, %fp + + rdpr %pstate, %o1 + or %o1, PSTATE_IE, %o1 +diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c +index 4ced92f05358..25d0c7ece9cc 100644 +--- a/arch/sparc/kernel/traps_64.c ++++ b/arch/sparc/kernel/traps_64.c +@@ -2102,6 +2102,11 @@ void sun4v_nonresum_overflow(struct pt_regs *regs) + atomic_inc(&sun4v_nonresum_oflow_cnt); + } + ++static void sun4v_tlb_error(struct pt_regs *regs) ++{ ++ die_if_kernel("TLB/TSB error", regs); ++} ++ + unsigned long sun4v_err_itlb_vaddr; + unsigned long sun4v_err_itlb_ctx; + unsigned long sun4v_err_itlb_pte; +@@ -2109,8 +2114,7 @@ unsigned long sun4v_err_itlb_error; + + void sun4v_itlb_error_report(struct pt_regs *regs, int tl) + { +- if (tl > 1) +- dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); ++ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); + + printk(KERN_EMERG "SUN4V-ITLB: Error at TPC[%lx], tl %d\n", + regs->tpc, tl); +@@ -2123,7 +2127,7 @@ void sun4v_itlb_error_report(struct pt_regs *regs, int tl) + sun4v_err_itlb_vaddr, sun4v_err_itlb_ctx, + sun4v_err_itlb_pte, sun4v_err_itlb_error); + +- prom_halt(); ++ sun4v_tlb_error(regs); + } + + unsigned long sun4v_err_dtlb_vaddr; +@@ -2133,8 +2137,7 @@ unsigned long sun4v_err_dtlb_error; + + void sun4v_dtlb_error_report(struct pt_regs *regs, int tl) + { +- if (tl > 1) +- dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); ++ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); + + printk(KERN_EMERG "SUN4V-DTLB: Error at TPC[%lx], tl %d\n", + regs->tpc, tl); +@@ -2147,7 +2150,7 @@ void sun4v_dtlb_error_report(struct pt_regs *regs, int tl) + sun4v_err_dtlb_vaddr, sun4v_err_dtlb_ctx, + sun4v_err_dtlb_pte, sun4v_err_dtlb_error); + +- prom_halt(); ++ sun4v_tlb_error(regs); + } + + void hypervisor_tlbop_error(unsigned long err, unsigned long op) +diff --git a/arch/sparc/kernel/tsb.S b/arch/sparc/kernel/tsb.S +index 14158d40ba76..be98685c14c6 100644 +--- a/arch/sparc/kernel/tsb.S ++++ b/arch/sparc/kernel/tsb.S +@@ -162,10 +162,10 @@ tsb_miss_page_table_walk_sun4v_fastpath: + nop + .previous + +- rdpr %tl, %g3 +- cmp %g3, 1 ++ rdpr %tl, %g7 ++ cmp %g7, 1 + bne,pn %xcc, winfix_trampoline +- nop ++ mov %g3, %g4 + ba,pt %xcc, etrap + rd %pc, %g7 + call hugetlb_setup +diff --git a/arch/sparc/kernel/viohs.c b/arch/sparc/kernel/viohs.c +index f8e7dd53e1c7..9c5fbd0b8a04 100644 +--- a/arch/sparc/kernel/viohs.c ++++ b/arch/sparc/kernel/viohs.c +@@ -714,7 +714,7 @@ int vio_ldc_alloc(struct vio_driver_state *vio, + cfg.tx_irq = vio->vdev->tx_irq; + cfg.rx_irq = vio->vdev->rx_irq; + +- lp = ldc_alloc(vio->vdev->channel_id, &cfg, event_arg); ++ lp = ldc_alloc(vio->vdev->channel_id, &cfg, event_arg, vio->name); + if (IS_ERR(lp)) + return PTR_ERR(lp); + +@@ -746,7 +746,7 @@ void vio_port_up(struct vio_driver_state *vio) + + err = 0; + if (state == LDC_STATE_INIT) { +- err = ldc_bind(vio->lp, vio->name); ++ err = ldc_bind(vio->lp); + if (err) + printk(KERN_WARNING "%s: Port %lu bind failed, " + "err=%d\n", +diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S +index 932ff90fd760..09243057cb0b 100644 +--- a/arch/sparc/kernel/vmlinux.lds.S ++++ b/arch/sparc/kernel/vmlinux.lds.S +@@ -35,8 +35,9 @@ jiffies = jiffies_64; + + SECTIONS + { +- /* swapper_low_pmd_dir is sparc64 only */ +- swapper_low_pmd_dir = 0x0000000000402000; ++#ifdef CONFIG_SPARC64 ++ swapper_pg_dir = 0x0000000000402000; ++#endif + . = INITIAL_ADDRESS; + .text TEXTSTART : + { +@@ -122,11 +123,6 @@ SECTIONS + *(.swapper_4m_tsb_phys_patch) + __swapper_4m_tsb_phys_patch_end = .; + } +- .page_offset_shift_patch : { +- __page_offset_shift_patch = .; +- *(.page_offset_shift_patch) +- __page_offset_shift_patch_end = .; +- } + .popc_3insn_patch : { + __popc_3insn_patch = .; + *(.popc_3insn_patch) +diff --git a/arch/sparc/lib/NG4memcpy.S b/arch/sparc/lib/NG4memcpy.S +index 9cf2ee01cee3..140527a20e7d 100644 +--- a/arch/sparc/lib/NG4memcpy.S ++++ b/arch/sparc/lib/NG4memcpy.S +@@ -41,6 +41,10 @@ + #endif + #endif + ++#if !defined(EX_LD) && !defined(EX_ST) ++#define NON_USER_COPY ++#endif ++ + #ifndef EX_LD + #define EX_LD(x) x + #endif +@@ -197,9 +201,13 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ + mov EX_RETVAL(%o3), %o0 + + .Llarge_src_unaligned: ++#ifdef NON_USER_COPY ++ VISEntryHalfFast(.Lmedium_vis_entry_fail) ++#else ++ VISEntryHalf ++#endif + andn %o2, 0x3f, %o4 + sub %o2, %o4, %o2 +- VISEntryHalf + alignaddr %o1, %g0, %g1 + add %o1, %o4, %o1 + EX_LD(LOAD(ldd, %g1 + 0x00, %f0)) +@@ -240,6 +248,10 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ + nop + ba,a,pt %icc, .Lmedium_unaligned + ++#ifdef NON_USER_COPY ++.Lmedium_vis_entry_fail: ++ or %o0, %o1, %g2 ++#endif + .Lmedium: + LOAD(prefetch, %o1 + 0x40, #n_reads_strong) + andcc %g2, 0x7, %g0 +diff --git a/arch/sparc/lib/memset.S b/arch/sparc/lib/memset.S +index 99c017be8719..f75e6906df14 100644 +--- a/arch/sparc/lib/memset.S ++++ b/arch/sparc/lib/memset.S +@@ -3,8 +3,9 @@ + * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + * +- * Returns 0, if ok, and number of bytes not yet set if exception +- * occurs and we were called as clear_user. ++ * Calls to memset returns initial %o0. Calls to bzero returns 0, if ok, and ++ * number of bytes not yet set if exception occurs and we were called as ++ * clear_user. + */ + + #include +@@ -65,6 +66,8 @@ __bzero_begin: + .globl __memset_start, __memset_end + __memset_start: + memset: ++ mov %o0, %g1 ++ mov 1, %g4 + and %o1, 0xff, %g3 + sll %g3, 8, %g2 + or %g3, %g2, %g3 +@@ -89,6 +92,7 @@ memset: + sub %o0, %o2, %o0 + + __bzero: ++ clr %g4 + mov %g0, %g3 + 1: + cmp %o1, 7 +@@ -151,8 +155,8 @@ __bzero: + bne,a 8f + EX(stb %g3, [%o0], and %o1, 1) + 8: +- retl +- clr %o0 ++ b 0f ++ nop + 7: + be 13b + orcc %o1, 0, %g0 +@@ -164,6 +168,12 @@ __bzero: + bne 8b + EX(stb %g3, [%o0 - 1], add %o1, 1) + 0: ++ andcc %g4, 1, %g0 ++ be 5f ++ nop ++ retl ++ mov %g1, %o0 ++5: + retl + clr %o0 + __memset_end: +diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c +index 4ced3fc66130..45a413e4380a 100644 +--- a/arch/sparc/mm/fault_64.c ++++ b/arch/sparc/mm/fault_64.c +@@ -348,6 +348,9 @@ retry: + down_read(&mm->mmap_sem); + } + ++ if (fault_code & FAULT_CODE_BAD_RA) ++ goto do_sigbus; ++ + vma = find_vma(mm, address); + if (!vma) + goto bad_area; +diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c +index 1aed0432c64b..ae6ce383d4df 100644 +--- a/arch/sparc/mm/gup.c ++++ b/arch/sparc/mm/gup.c +@@ -160,6 +160,36 @@ static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end, + return 1; + } + ++int __get_user_pages_fast(unsigned long start, int nr_pages, int write, ++ struct page **pages) ++{ ++ struct mm_struct *mm = current->mm; ++ unsigned long addr, len, end; ++ unsigned long next, flags; ++ pgd_t *pgdp; ++ int nr = 0; ++ ++ start &= PAGE_MASK; ++ addr = start; ++ len = (unsigned long) nr_pages << PAGE_SHIFT; ++ end = start + len; ++ ++ local_irq_save(flags); ++ pgdp = pgd_offset(mm, addr); ++ do { ++ pgd_t pgd = *pgdp; ++ ++ next = pgd_addr_end(addr, end); ++ if (pgd_none(pgd)) ++ break; ++ if (!gup_pud_range(pgd, addr, next, write, pages, &nr)) ++ break; ++ } while (pgdp++, addr = next, addr != end); ++ local_irq_restore(flags); ++ ++ return nr; ++} ++ + int get_user_pages_fast(unsigned long start, int nr_pages, int write, + struct page **pages) + { +diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c +index 96862241b342..34506f292533 100644 +--- a/arch/sparc/mm/init_64.c ++++ b/arch/sparc/mm/init_64.c +@@ -73,7 +73,6 @@ unsigned long kern_linear_pte_xor[4] __read_mostly; + * 'cpu' properties, but we need to have this table setup before the + * MDESC is initialized. + */ +-unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; + + #ifndef CONFIG_DEBUG_PAGEALLOC + /* A special kernel TSB for 4MB, 256MB, 2GB and 16GB linear mappings. +@@ -82,10 +81,11 @@ unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; + */ + extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES]; + #endif ++extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES]; + + static unsigned long cpu_pgsz_mask; + +-#define MAX_BANKS 32 ++#define MAX_BANKS 1024 + + static struct linux_prom64_registers pavail[MAX_BANKS]; + static int pavail_ents; +@@ -163,10 +163,6 @@ static void __init read_obp_memory(const char *property, + cmp_p64, NULL); + } + +-unsigned long sparc64_valid_addr_bitmap[VALID_ADDR_BITMAP_BYTES / +- sizeof(unsigned long)]; +-EXPORT_SYMBOL(sparc64_valid_addr_bitmap); +- + /* Kernel physical address base and size in bytes. */ + unsigned long kern_base __read_mostly; + unsigned long kern_size __read_mostly; +@@ -838,7 +834,10 @@ static int find_node(unsigned long addr) + if ((addr & p->mask) == p->val) + return i; + } +- return -1; ++ /* The following condition has been observed on LDOM guests.*/ ++ WARN_ONCE(1, "find_node: A physical address doesn't match a NUMA node" ++ " rule. Some physical memory will be owned by node 0."); ++ return 0; + } + + static u64 memblock_nid_range(u64 start, u64 end, int *nid) +@@ -1360,9 +1359,144 @@ static unsigned long __init bootmem_init(unsigned long phys_base) + static struct linux_prom64_registers pall[MAX_BANKS] __initdata; + static int pall_ents __initdata; + +-#ifdef CONFIG_DEBUG_PAGEALLOC ++static unsigned long max_phys_bits = 40; ++ ++bool kern_addr_valid(unsigned long addr) ++{ ++ pgd_t *pgd; ++ pud_t *pud; ++ pmd_t *pmd; ++ pte_t *pte; ++ ++ if ((long)addr < 0L) { ++ unsigned long pa = __pa(addr); ++ ++ if ((addr >> max_phys_bits) != 0UL) ++ return false; ++ ++ return pfn_valid(pa >> PAGE_SHIFT); ++ } ++ ++ if (addr >= (unsigned long) KERNBASE && ++ addr < (unsigned long)&_end) ++ return true; ++ ++ pgd = pgd_offset_k(addr); ++ if (pgd_none(*pgd)) ++ return 0; ++ ++ pud = pud_offset(pgd, addr); ++ if (pud_none(*pud)) ++ return 0; ++ ++ if (pud_large(*pud)) ++ return pfn_valid(pud_pfn(*pud)); ++ ++ pmd = pmd_offset(pud, addr); ++ if (pmd_none(*pmd)) ++ return 0; ++ ++ if (pmd_large(*pmd)) ++ return pfn_valid(pmd_pfn(*pmd)); ++ ++ pte = pte_offset_kernel(pmd, addr); ++ if (pte_none(*pte)) ++ return 0; ++ ++ return pfn_valid(pte_pfn(*pte)); ++} ++EXPORT_SYMBOL(kern_addr_valid); ++ ++static unsigned long __ref kernel_map_hugepud(unsigned long vstart, ++ unsigned long vend, ++ pud_t *pud) ++{ ++ const unsigned long mask16gb = (1UL << 34) - 1UL; ++ u64 pte_val = vstart; ++ ++ /* Each PUD is 8GB */ ++ if ((vstart & mask16gb) || ++ (vend - vstart <= mask16gb)) { ++ pte_val ^= kern_linear_pte_xor[2]; ++ pud_val(*pud) = pte_val | _PAGE_PUD_HUGE; ++ ++ return vstart + PUD_SIZE; ++ } ++ ++ pte_val ^= kern_linear_pte_xor[3]; ++ pte_val |= _PAGE_PUD_HUGE; ++ ++ vend = vstart + mask16gb + 1UL; ++ while (vstart < vend) { ++ pud_val(*pud) = pte_val; ++ ++ pte_val += PUD_SIZE; ++ vstart += PUD_SIZE; ++ pud++; ++ } ++ return vstart; ++} ++ ++static bool kernel_can_map_hugepud(unsigned long vstart, unsigned long vend, ++ bool guard) ++{ ++ if (guard && !(vstart & ~PUD_MASK) && (vend - vstart) >= PUD_SIZE) ++ return true; ++ ++ return false; ++} ++ ++static unsigned long __ref kernel_map_hugepmd(unsigned long vstart, ++ unsigned long vend, ++ pmd_t *pmd) ++{ ++ const unsigned long mask256mb = (1UL << 28) - 1UL; ++ const unsigned long mask2gb = (1UL << 31) - 1UL; ++ u64 pte_val = vstart; ++ ++ /* Each PMD is 8MB */ ++ if ((vstart & mask256mb) || ++ (vend - vstart <= mask256mb)) { ++ pte_val ^= kern_linear_pte_xor[0]; ++ pmd_val(*pmd) = pte_val | _PAGE_PMD_HUGE; ++ ++ return vstart + PMD_SIZE; ++ } ++ ++ if ((vstart & mask2gb) || ++ (vend - vstart <= mask2gb)) { ++ pte_val ^= kern_linear_pte_xor[1]; ++ pte_val |= _PAGE_PMD_HUGE; ++ vend = vstart + mask256mb + 1UL; ++ } else { ++ pte_val ^= kern_linear_pte_xor[2]; ++ pte_val |= _PAGE_PMD_HUGE; ++ vend = vstart + mask2gb + 1UL; ++ } ++ ++ while (vstart < vend) { ++ pmd_val(*pmd) = pte_val; ++ ++ pte_val += PMD_SIZE; ++ vstart += PMD_SIZE; ++ pmd++; ++ } ++ ++ return vstart; ++} ++ ++static bool kernel_can_map_hugepmd(unsigned long vstart, unsigned long vend, ++ bool guard) ++{ ++ if (guard && !(vstart & ~PMD_MASK) && (vend - vstart) >= PMD_SIZE) ++ return true; ++ ++ return false; ++} ++ + static unsigned long __ref kernel_map_range(unsigned long pstart, +- unsigned long pend, pgprot_t prot) ++ unsigned long pend, pgprot_t prot, ++ bool use_huge) + { + unsigned long vstart = PAGE_OFFSET + pstart; + unsigned long vend = PAGE_OFFSET + pend; +@@ -1381,19 +1515,34 @@ static unsigned long __ref kernel_map_range(unsigned long pstart, + pmd_t *pmd; + pte_t *pte; + ++ if (pgd_none(*pgd)) { ++ pud_t *new; ++ ++ new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); ++ alloc_bytes += PAGE_SIZE; ++ pgd_populate(&init_mm, pgd, new); ++ } + pud = pud_offset(pgd, vstart); + if (pud_none(*pud)) { + pmd_t *new; + ++ if (kernel_can_map_hugepud(vstart, vend, use_huge)) { ++ vstart = kernel_map_hugepud(vstart, vend, pud); ++ continue; ++ } + new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + alloc_bytes += PAGE_SIZE; + pud_populate(&init_mm, pud, new); + } + + pmd = pmd_offset(pud, vstart); +- if (!pmd_present(*pmd)) { ++ if (pmd_none(*pmd)) { + pte_t *new; + ++ if (kernel_can_map_hugepmd(vstart, vend, use_huge)) { ++ vstart = kernel_map_hugepmd(vstart, vend, pmd); ++ continue; ++ } + new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + alloc_bytes += PAGE_SIZE; + pmd_populate_kernel(&init_mm, pmd, new); +@@ -1416,100 +1565,34 @@ static unsigned long __ref kernel_map_range(unsigned long pstart, + return alloc_bytes; + } + +-extern unsigned int kvmap_linear_patch[1]; +-#endif /* CONFIG_DEBUG_PAGEALLOC */ +- +-static void __init kpte_set_val(unsigned long index, unsigned long val) ++static void __init flush_all_kernel_tsbs(void) + { +- unsigned long *ptr = kpte_linear_bitmap; +- +- val <<= ((index % (BITS_PER_LONG / 2)) * 2); +- ptr += (index / (BITS_PER_LONG / 2)); +- +- *ptr |= val; +-} +- +-static const unsigned long kpte_shift_min = 28; /* 256MB */ +-static const unsigned long kpte_shift_max = 34; /* 16GB */ +-static const unsigned long kpte_shift_incr = 3; +- +-static unsigned long kpte_mark_using_shift(unsigned long start, unsigned long end, +- unsigned long shift) +-{ +- unsigned long size = (1UL << shift); +- unsigned long mask = (size - 1UL); +- unsigned long remains = end - start; +- unsigned long val; +- +- if (remains < size || (start & mask)) +- return start; +- +- /* VAL maps: +- * +- * shift 28 --> kern_linear_pte_xor index 1 +- * shift 31 --> kern_linear_pte_xor index 2 +- * shift 34 --> kern_linear_pte_xor index 3 +- */ +- val = ((shift - kpte_shift_min) / kpte_shift_incr) + 1; +- +- remains &= ~mask; +- if (shift != kpte_shift_max) +- remains = size; +- +- while (remains) { +- unsigned long index = start >> kpte_shift_min; ++ int i; + +- kpte_set_val(index, val); ++ for (i = 0; i < KERNEL_TSB_NENTRIES; i++) { ++ struct tsb *ent = &swapper_tsb[i]; + +- start += 1UL << kpte_shift_min; +- remains -= 1UL << kpte_shift_min; ++ ent->tag = (1UL << TSB_TAG_INVALID_BIT); + } ++#ifndef CONFIG_DEBUG_PAGEALLOC ++ for (i = 0; i < KERNEL_TSB4M_NENTRIES; i++) { ++ struct tsb *ent = &swapper_4m_tsb[i]; + +- return start; +-} +- +-static void __init mark_kpte_bitmap(unsigned long start, unsigned long end) +-{ +- unsigned long smallest_size, smallest_mask; +- unsigned long s; +- +- smallest_size = (1UL << kpte_shift_min); +- smallest_mask = (smallest_size - 1UL); +- +- while (start < end) { +- unsigned long orig_start = start; +- +- for (s = kpte_shift_max; s >= kpte_shift_min; s -= kpte_shift_incr) { +- start = kpte_mark_using_shift(start, end, s); +- +- if (start != orig_start) +- break; +- } +- +- if (start == orig_start) +- start = (start + smallest_size) & ~smallest_mask; ++ ent->tag = (1UL << TSB_TAG_INVALID_BIT); + } ++#endif + } + +-static void __init init_kpte_bitmap(void) +-{ +- unsigned long i; +- +- for (i = 0; i < pall_ents; i++) { +- unsigned long phys_start, phys_end; +- +- phys_start = pall[i].phys_addr; +- phys_end = phys_start + pall[i].reg_size; +- +- mark_kpte_bitmap(phys_start, phys_end); +- } +-} ++extern unsigned int kvmap_linear_patch[1]; + + static void __init kernel_physical_mapping_init(void) + { +-#ifdef CONFIG_DEBUG_PAGEALLOC + unsigned long i, mem_alloced = 0UL; ++ bool use_huge = true; + ++#ifdef CONFIG_DEBUG_PAGEALLOC ++ use_huge = false; ++#endif + for (i = 0; i < pall_ents; i++) { + unsigned long phys_start, phys_end; + +@@ -1517,7 +1600,7 @@ static void __init kernel_physical_mapping_init(void) + phys_end = phys_start + pall[i].reg_size; + + mem_alloced += kernel_map_range(phys_start, phys_end, +- PAGE_KERNEL); ++ PAGE_KERNEL, use_huge); + } + + printk("Allocated %ld bytes for kernel page tables.\n", +@@ -1526,8 +1609,9 @@ static void __init kernel_physical_mapping_init(void) + kvmap_linear_patch[0] = 0x01000000; /* nop */ + flushi(&kvmap_linear_patch[0]); + ++ flush_all_kernel_tsbs(); ++ + __flush_tlb_all(); +-#endif + } + + #ifdef CONFIG_DEBUG_PAGEALLOC +@@ -1537,7 +1621,7 @@ void kernel_map_pages(struct page *page, int numpages, int enable) + unsigned long phys_end = phys_start + (numpages * PAGE_SIZE); + + kernel_map_range(phys_start, phys_end, +- (enable ? PAGE_KERNEL : __pgprot(0))); ++ (enable ? PAGE_KERNEL : __pgprot(0)), false); + + flush_tsb_kernel_range(PAGE_OFFSET + phys_start, + PAGE_OFFSET + phys_end); +@@ -1565,76 +1649,56 @@ unsigned long __init find_ecache_flush_span(unsigned long size) + unsigned long PAGE_OFFSET; + EXPORT_SYMBOL(PAGE_OFFSET); + +-static void __init page_offset_shift_patch_one(unsigned int *insn, unsigned long phys_bits) +-{ +- unsigned long final_shift; +- unsigned int val = *insn; +- unsigned int cnt; +- +- /* We are patching in ilog2(max_supported_phys_address), and +- * we are doing so in a manner similar to a relocation addend. +- * That is, we are adding the shift value to whatever value +- * is in the shift instruction count field already. +- */ +- cnt = (val & 0x3f); +- val &= ~0x3f; +- +- /* If we are trying to shift >= 64 bits, clear the destination +- * register. This can happen when phys_bits ends up being equal +- * to MAX_PHYS_ADDRESS_BITS. +- */ +- final_shift = (cnt + (64 - phys_bits)); +- if (final_shift >= 64) { +- unsigned int rd = (val >> 25) & 0x1f; +- +- val = 0x80100000 | (rd << 25); +- } else { +- val |= final_shift; +- } +- *insn = val; +- +- __asm__ __volatile__("flush %0" +- : /* no outputs */ +- : "r" (insn)); +-} +- +-static void __init page_offset_shift_patch(unsigned long phys_bits) +-{ +- extern unsigned int __page_offset_shift_patch; +- extern unsigned int __page_offset_shift_patch_end; +- unsigned int *p; +- +- p = &__page_offset_shift_patch; +- while (p < &__page_offset_shift_patch_end) { +- unsigned int *insn = (unsigned int *)(unsigned long)*p; ++unsigned long VMALLOC_END = 0x0000010000000000UL; ++EXPORT_SYMBOL(VMALLOC_END); + +- page_offset_shift_patch_one(insn, phys_bits); +- +- p++; +- } +-} ++unsigned long sparc64_va_hole_top = 0xfffff80000000000UL; ++unsigned long sparc64_va_hole_bottom = 0x0000080000000000UL; + + static void __init setup_page_offset(void) + { +- unsigned long max_phys_bits = 40; +- + if (tlb_type == cheetah || tlb_type == cheetah_plus) { ++ /* Cheetah/Panther support a full 64-bit virtual ++ * address, so we can use all that our page tables ++ * support. ++ */ ++ sparc64_va_hole_top = 0xfff0000000000000UL; ++ sparc64_va_hole_bottom = 0x0010000000000000UL; ++ + max_phys_bits = 42; + } else if (tlb_type == hypervisor) { + switch (sun4v_chip_type) { + case SUN4V_CHIP_NIAGARA1: + case SUN4V_CHIP_NIAGARA2: ++ /* T1 and T2 support 48-bit virtual addresses. */ ++ sparc64_va_hole_top = 0xffff800000000000UL; ++ sparc64_va_hole_bottom = 0x0000800000000000UL; ++ + max_phys_bits = 39; + break; + case SUN4V_CHIP_NIAGARA3: ++ /* T3 supports 48-bit virtual addresses. */ ++ sparc64_va_hole_top = 0xffff800000000000UL; ++ sparc64_va_hole_bottom = 0x0000800000000000UL; ++ + max_phys_bits = 43; + break; + case SUN4V_CHIP_NIAGARA4: + case SUN4V_CHIP_NIAGARA5: + case SUN4V_CHIP_SPARC64X: +- default: ++ case SUN4V_CHIP_SPARC_M6: ++ /* T4 and later support 52-bit virtual addresses. */ ++ sparc64_va_hole_top = 0xfff8000000000000UL; ++ sparc64_va_hole_bottom = 0x0008000000000000UL; + max_phys_bits = 47; + break; ++ case SUN4V_CHIP_SPARC_M7: ++ default: ++ /* M7 and later support 52-bit virtual addresses. */ ++ sparc64_va_hole_top = 0xfff8000000000000UL; ++ sparc64_va_hole_bottom = 0x0008000000000000UL; ++ max_phys_bits = 49; ++ break; + } + } + +@@ -1644,12 +1708,16 @@ static void __init setup_page_offset(void) + prom_halt(); + } + +- PAGE_OFFSET = PAGE_OFFSET_BY_BITS(max_phys_bits); ++ PAGE_OFFSET = sparc64_va_hole_top; ++ VMALLOC_END = ((sparc64_va_hole_bottom >> 1) + ++ (sparc64_va_hole_bottom >> 2)); + +- pr_info("PAGE_OFFSET is 0x%016lx (max_phys_bits == %lu)\n", ++ pr_info("MM: PAGE_OFFSET is 0x%016lx (max_phys_bits == %lu)\n", + PAGE_OFFSET, max_phys_bits); +- +- page_offset_shift_patch(max_phys_bits); ++ pr_info("MM: VMALLOC [0x%016lx --> 0x%016lx]\n", ++ VMALLOC_START, VMALLOC_END); ++ pr_info("MM: VMEMMAP [0x%016lx --> 0x%016lx]\n", ++ VMEMMAP_BASE, VMEMMAP_BASE << 1); + } + + static void __init tsb_phys_patch(void) +@@ -1694,21 +1762,42 @@ static void __init tsb_phys_patch(void) + #define NUM_KTSB_DESCR 1 + #endif + static struct hv_tsb_descr ktsb_descr[NUM_KTSB_DESCR]; +-extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES]; ++ ++/* The swapper TSBs are loaded with a base sequence of: ++ * ++ * sethi %uhi(SYMBOL), REG1 ++ * sethi %hi(SYMBOL), REG2 ++ * or REG1, %ulo(SYMBOL), REG1 ++ * or REG2, %lo(SYMBOL), REG2 ++ * sllx REG1, 32, REG1 ++ * or REG1, REG2, REG1 ++ * ++ * When we use physical addressing for the TSB accesses, we patch the ++ * first four instructions in the above sequence. ++ */ + + static void patch_one_ktsb_phys(unsigned int *start, unsigned int *end, unsigned long pa) + { +- pa >>= KTSB_PHYS_SHIFT; ++ unsigned long high_bits, low_bits; ++ ++ high_bits = (pa >> 32) & 0xffffffff; ++ low_bits = (pa >> 0) & 0xffffffff; + + while (start < end) { + unsigned int *ia = (unsigned int *)(unsigned long)*start; + +- ia[0] = (ia[0] & ~0x3fffff) | (pa >> 10); ++ ia[0] = (ia[0] & ~0x3fffff) | (high_bits >> 10); + __asm__ __volatile__("flush %0" : : "r" (ia)); + +- ia[1] = (ia[1] & ~0x3ff) | (pa & 0x3ff); ++ ia[1] = (ia[1] & ~0x3fffff) | (low_bits >> 10); + __asm__ __volatile__("flush %0" : : "r" (ia + 1)); + ++ ia[2] = (ia[2] & ~0x1fff) | (high_bits & 0x3ff); ++ __asm__ __volatile__("flush %0" : : "r" (ia + 2)); ++ ++ ia[3] = (ia[3] & ~0x1fff) | (low_bits & 0x3ff); ++ __asm__ __volatile__("flush %0" : : "r" (ia + 3)); ++ + start++; + } + } +@@ -1847,7 +1936,6 @@ static void __init sun4v_linear_pte_xor_finalize(void) + /* paging_init() sets up the page tables */ + + static unsigned long last_valid_pfn; +-pgd_t swapper_pg_dir[PTRS_PER_PGD]; + + static void sun4u_pgprot_init(void); + static void sun4v_pgprot_init(void); +@@ -1950,16 +2038,10 @@ void __init paging_init(void) + */ + init_mm.pgd += ((shift) / (sizeof(pgd_t))); + +- memset(swapper_low_pmd_dir, 0, sizeof(swapper_low_pmd_dir)); ++ memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir)); + +- /* Now can init the kernel/bad page tables. */ +- pud_set(pud_offset(&swapper_pg_dir[0], 0), +- swapper_low_pmd_dir + (shift / sizeof(pgd_t))); +- + inherit_prom_mappings(); + +- init_kpte_bitmap(); +- + /* Ok, we can use our TLB miss and window trap handlers safely. */ + setup_tba(); + +@@ -2066,70 +2148,6 @@ int page_in_phys_avail(unsigned long paddr) + return 0; + } + +-static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata; +-static int pavail_rescan_ents __initdata; +- +-/* Certain OBP calls, such as fetching "available" properties, can +- * claim physical memory. So, along with initializing the valid +- * address bitmap, what we do here is refetch the physical available +- * memory list again, and make sure it provides at least as much +- * memory as 'pavail' does. +- */ +-static void __init setup_valid_addr_bitmap_from_pavail(unsigned long *bitmap) +-{ +- int i; +- +- read_obp_memory("available", &pavail_rescan[0], &pavail_rescan_ents); +- +- for (i = 0; i < pavail_ents; i++) { +- unsigned long old_start, old_end; +- +- old_start = pavail[i].phys_addr; +- old_end = old_start + pavail[i].reg_size; +- while (old_start < old_end) { +- int n; +- +- for (n = 0; n < pavail_rescan_ents; n++) { +- unsigned long new_start, new_end; +- +- new_start = pavail_rescan[n].phys_addr; +- new_end = new_start + +- pavail_rescan[n].reg_size; +- +- if (new_start <= old_start && +- new_end >= (old_start + PAGE_SIZE)) { +- set_bit(old_start >> ILOG2_4MB, bitmap); +- goto do_next_page; +- } +- } +- +- prom_printf("mem_init: Lost memory in pavail\n"); +- prom_printf("mem_init: OLD start[%lx] size[%lx]\n", +- pavail[i].phys_addr, +- pavail[i].reg_size); +- prom_printf("mem_init: NEW start[%lx] size[%lx]\n", +- pavail_rescan[i].phys_addr, +- pavail_rescan[i].reg_size); +- prom_printf("mem_init: Cannot continue, aborting.\n"); +- prom_halt(); +- +- do_next_page: +- old_start += PAGE_SIZE; +- } +- } +-} +- +-static void __init patch_tlb_miss_handler_bitmap(void) +-{ +- extern unsigned int valid_addr_bitmap_insn[]; +- extern unsigned int valid_addr_bitmap_patch[]; +- +- valid_addr_bitmap_insn[1] = valid_addr_bitmap_patch[1]; +- mb(); +- valid_addr_bitmap_insn[0] = valid_addr_bitmap_patch[0]; +- flushi(&valid_addr_bitmap_insn[0]); +-} +- + static void __init register_page_bootmem_info(void) + { + #ifdef CONFIG_NEED_MULTIPLE_NODES +@@ -2142,18 +2160,6 @@ static void __init register_page_bootmem_info(void) + } + void __init mem_init(void) + { +- unsigned long addr, last; +- +- addr = PAGE_OFFSET + kern_base; +- last = PAGE_ALIGN(kern_size) + addr; +- while (addr < last) { +- set_bit(__pa(addr) >> ILOG2_4MB, sparc64_valid_addr_bitmap); +- addr += PAGE_SIZE; +- } +- +- setup_valid_addr_bitmap_from_pavail(sparc64_valid_addr_bitmap); +- patch_tlb_miss_handler_bitmap(); +- + high_memory = __va(last_valid_pfn << PAGE_SHIFT); + + register_page_bootmem_info(); +@@ -2243,18 +2249,9 @@ unsigned long _PAGE_CACHE __read_mostly; + EXPORT_SYMBOL(_PAGE_CACHE); + + #ifdef CONFIG_SPARSEMEM_VMEMMAP +-unsigned long vmemmap_table[VMEMMAP_SIZE]; +- +-static long __meminitdata addr_start, addr_end; +-static int __meminitdata node_start; +- + int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend, + int node) + { +- unsigned long phys_start = (vstart - VMEMMAP_BASE); +- unsigned long phys_end = (vend - VMEMMAP_BASE); +- unsigned long addr = phys_start & VMEMMAP_CHUNK_MASK; +- unsigned long end = VMEMMAP_ALIGN(phys_end); + unsigned long pte_base; + + pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4U | +@@ -2265,47 +2262,52 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend, + _PAGE_CP_4V | _PAGE_CV_4V | + _PAGE_P_4V | _PAGE_W_4V); + +- for (; addr < end; addr += VMEMMAP_CHUNK) { +- unsigned long *vmem_pp = +- vmemmap_table + (addr >> VMEMMAP_CHUNK_SHIFT); +- void *block; ++ pte_base |= _PAGE_PMD_HUGE; + +- if (!(*vmem_pp & _PAGE_VALID)) { +- block = vmemmap_alloc_block(1UL << ILOG2_4MB, node); +- if (!block) ++ vstart = vstart & PMD_MASK; ++ vend = ALIGN(vend, PMD_SIZE); ++ for (; vstart < vend; vstart += PMD_SIZE) { ++ pgd_t *pgd = pgd_offset_k(vstart); ++ unsigned long pte; ++ pud_t *pud; ++ pmd_t *pmd; ++ ++ if (pgd_none(*pgd)) { ++ pud_t *new = vmemmap_alloc_block(PAGE_SIZE, node); ++ ++ if (!new) + return -ENOMEM; ++ pgd_populate(&init_mm, pgd, new); ++ } + +- *vmem_pp = pte_base | __pa(block); ++ pud = pud_offset(pgd, vstart); ++ if (pud_none(*pud)) { ++ pmd_t *new = vmemmap_alloc_block(PAGE_SIZE, node); + +- /* check to see if we have contiguous blocks */ +- if (addr_end != addr || node_start != node) { +- if (addr_start) +- printk(KERN_DEBUG " [%lx-%lx] on node %d\n", +- addr_start, addr_end-1, node_start); +- addr_start = addr; +- node_start = node; +- } +- addr_end = addr + VMEMMAP_CHUNK; ++ if (!new) ++ return -ENOMEM; ++ pud_populate(&init_mm, pud, new); + } +- } +- return 0; +-} + +-void __meminit vmemmap_populate_print_last(void) +-{ +- if (addr_start) { +- printk(KERN_DEBUG " [%lx-%lx] on node %d\n", +- addr_start, addr_end-1, node_start); +- addr_start = 0; +- addr_end = 0; +- node_start = 0; ++ pmd = pmd_offset(pud, vstart); ++ ++ pte = pmd_val(*pmd); ++ if (!(pte & _PAGE_VALID)) { ++ void *block = vmemmap_alloc_block(PMD_SIZE, node); ++ ++ if (!block) ++ return -ENOMEM; ++ ++ pmd_val(*pmd) = pte_base | __pa(block); ++ } + } ++ ++ return 0; + } + + void vmemmap_free(unsigned long start, unsigned long end) + { + } +- + #endif /* CONFIG_SPARSEMEM_VMEMMAP */ + + static void prot_init_common(unsigned long page_none, +@@ -2717,8 +2719,8 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end) + do_flush_tlb_kernel_range(start, LOW_OBP_ADDRESS); + } + if (end > HI_OBP_ADDRESS) { +- flush_tsb_kernel_range(end, HI_OBP_ADDRESS); +- do_flush_tlb_kernel_range(end, HI_OBP_ADDRESS); ++ flush_tsb_kernel_range(HI_OBP_ADDRESS, end); ++ do_flush_tlb_kernel_range(HI_OBP_ADDRESS, end); + } + } else { + flush_tsb_kernel_range(start, end); +diff --git a/arch/sparc/mm/init_64.h b/arch/sparc/mm/init_64.h +index 5d3782deb403..ac491193cb54 100644 +--- a/arch/sparc/mm/init_64.h ++++ b/arch/sparc/mm/init_64.h +@@ -8,15 +8,8 @@ + */ + + #define MAX_PHYS_ADDRESS (1UL << MAX_PHYS_ADDRESS_BITS) +-#define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL) +-#define KPTE_BITMAP_BYTES \ +- ((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 4) +-#define VALID_ADDR_BITMAP_CHUNK_SZ (4UL * 1024UL * 1024UL) +-#define VALID_ADDR_BITMAP_BYTES \ +- ((MAX_PHYS_ADDRESS / VALID_ADDR_BITMAP_CHUNK_SZ) / 8) + + extern unsigned long kern_linear_pte_xor[4]; +-extern unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; + extern unsigned int sparc64_highest_unlocked_tlb_ent; + extern unsigned long sparc64_kern_pri_context; + extern unsigned long sparc64_kern_pri_nuc_bits; +@@ -38,15 +31,4 @@ extern unsigned long kern_locked_tte_data; + + extern void prom_world(int enter); + +-#ifdef CONFIG_SPARSEMEM_VMEMMAP +-#define VMEMMAP_CHUNK_SHIFT 22 +-#define VMEMMAP_CHUNK (1UL << VMEMMAP_CHUNK_SHIFT) +-#define VMEMMAP_CHUNK_MASK ~(VMEMMAP_CHUNK - 1UL) +-#define VMEMMAP_ALIGN(x) (((x)+VMEMMAP_CHUNK-1UL)&VMEMMAP_CHUNK_MASK) +- +-#define VMEMMAP_SIZE ((((1UL << MAX_PHYSADDR_BITS) >> PAGE_SHIFT) * \ +- sizeof(struct page)) >> VMEMMAP_CHUNK_SHIFT) +-extern unsigned long vmemmap_table[VMEMMAP_SIZE]; +-#endif +- + #endif /* _SPARC64_MM_INIT_H */ +diff --git a/arch/sparc/power/hibernate_asm.S b/arch/sparc/power/hibernate_asm.S +index 79942166df84..d7d9017dcb15 100644 +--- a/arch/sparc/power/hibernate_asm.S ++++ b/arch/sparc/power/hibernate_asm.S +@@ -54,8 +54,8 @@ ENTRY(swsusp_arch_resume) + nop + + /* Write PAGE_OFFSET to %g7 */ +- sethi %uhi(PAGE_OFFSET), %g7 +- sllx %g7, 32, %g7 ++ sethi %hi(PAGE_OFFSET), %g7 ++ ldx [%g7 + %lo(PAGE_OFFSET)], %g7 + + setuw (PAGE_SIZE-8), %g3 + +diff --git a/arch/sparc/prom/bootstr_64.c b/arch/sparc/prom/bootstr_64.c +index ab9ccc63b388..7149e77714a4 100644 +--- a/arch/sparc/prom/bootstr_64.c ++++ b/arch/sparc/prom/bootstr_64.c +@@ -14,7 +14,10 @@ + * the .bss section or it will break things. + */ + +-#define BARG_LEN 256 ++/* We limit BARG_LEN to 1024 because this is the size of the ++ * 'barg_out' command line buffer in the SILO bootloader. ++ */ ++#define BARG_LEN 1024 + struct { + int bootstr_len; + int bootstr_valid; +diff --git a/arch/sparc/prom/cif.S b/arch/sparc/prom/cif.S +index 9c86b4b7d429..8050f381f518 100644 +--- a/arch/sparc/prom/cif.S ++++ b/arch/sparc/prom/cif.S +@@ -11,11 +11,10 @@ + .text + .globl prom_cif_direct + prom_cif_direct: ++ save %sp, -192, %sp + sethi %hi(p1275buf), %o1 + or %o1, %lo(p1275buf), %o1 +- ldx [%o1 + 0x0010], %o2 ! prom_cif_stack +- save %o2, -192, %sp +- ldx [%i1 + 0x0008], %l2 ! prom_cif_handler ++ ldx [%o1 + 0x0008], %l2 ! prom_cif_handler + mov %g4, %l0 + mov %g5, %l1 + mov %g6, %l3 +diff --git a/arch/sparc/prom/init_64.c b/arch/sparc/prom/init_64.c +index d95db755828f..110b0d78b864 100644 +--- a/arch/sparc/prom/init_64.c ++++ b/arch/sparc/prom/init_64.c +@@ -26,13 +26,13 @@ phandle prom_chosen_node; + * It gets passed the pointer to the PROM vector. + */ + +-extern void prom_cif_init(void *, void *); ++extern void prom_cif_init(void *); + +-void __init prom_init(void *cif_handler, void *cif_stack) ++void __init prom_init(void *cif_handler) + { + phandle node; + +- prom_cif_init(cif_handler, cif_stack); ++ prom_cif_init(cif_handler); + + prom_chosen_node = prom_finddevice(prom_chosen_path); + if (!prom_chosen_node || (s32)prom_chosen_node == -1) +diff --git a/arch/sparc/prom/p1275.c b/arch/sparc/prom/p1275.c +index e58b81726319..545d8bb79b65 100644 +--- a/arch/sparc/prom/p1275.c ++++ b/arch/sparc/prom/p1275.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -19,7 +20,6 @@ + struct { + long prom_callback; /* 0x00 */ + void (*prom_cif_handler)(long *); /* 0x08 */ +- unsigned long prom_cif_stack; /* 0x10 */ + } p1275buf; + + extern void prom_world(int); +@@ -36,8 +36,8 @@ void p1275_cmd_direct(unsigned long *args) + { + unsigned long flags; + +- raw_local_save_flags(flags); +- raw_local_irq_restore((unsigned long)PIL_NMI); ++ local_save_flags(flags); ++ local_irq_restore((unsigned long)PIL_NMI); + raw_spin_lock(&prom_entry_lock); + + prom_world(1); +@@ -45,11 +45,10 @@ void p1275_cmd_direct(unsigned long *args) + prom_world(0); + + raw_spin_unlock(&prom_entry_lock); +- raw_local_irq_restore(flags); ++ local_irq_restore(flags); + } + + void prom_cif_init(void *cif_handler, void *cif_stack) + { + p1275buf.prom_cif_handler = (void (*)(long *))cif_handler; +- p1275buf.prom_cif_stack = (unsigned long)cif_stack; + } +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index d71d5ac78e42..ac63ea4af5b0 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -480,6 +480,7 @@ struct kvm_vcpu_arch { + u64 mmio_gva; + unsigned access; + gfn_t mmio_gfn; ++ u64 mmio_gen; + + struct kvm_pmu pmu; + +diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c +index 5cd9bfabd645..c1a07d33e67e 100644 +--- a/arch/x86/kernel/cpu/intel.c ++++ b/arch/x86/kernel/cpu/intel.c +@@ -153,6 +153,21 @@ static void early_init_intel(struct cpuinfo_x86 *c) + setup_clear_cpu_cap(X86_FEATURE_ERMS); + } + } ++ ++ /* ++ * Intel Quark Core DevMan_001.pdf section 6.4.11 ++ * "The operating system also is required to invalidate (i.e., flush) ++ * the TLB when any changes are made to any of the page table entries. ++ * The operating system must reload CR3 to cause the TLB to be flushed" ++ * ++ * As a result cpu_has_pge() in arch/x86/include/asm/tlbflush.h should ++ * be false so that __flush_tlb_all() causes CR3 insted of CR4.PGE ++ * to be modified ++ */ ++ if (c->x86 == 5 && c->x86_model == 9) { ++ pr_info("Disabling PGE capability bit\n"); ++ setup_clear_cpu_cap(X86_FEATURE_PGE); ++ } + } + + #ifdef CONFIG_X86_32 +diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c +index 9b531351a587..49088b8a3ee3 100644 +--- a/arch/x86/kvm/mmu.c ++++ b/arch/x86/kvm/mmu.c +@@ -198,16 +198,20 @@ void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask) + EXPORT_SYMBOL_GPL(kvm_mmu_set_mmio_spte_mask); + + /* +- * spte bits of bit 3 ~ bit 11 are used as low 9 bits of generation number, +- * the bits of bits 52 ~ bit 61 are used as high 10 bits of generation +- * number. ++ * the low bit of the generation number is always presumed to be zero. ++ * This disables mmio caching during memslot updates. The concept is ++ * similar to a seqcount but instead of retrying the access we just punt ++ * and ignore the cache. ++ * ++ * spte bits 3-11 are used as bits 1-9 of the generation number, ++ * the bits 52-61 are used as bits 10-19 of the generation number. + */ +-#define MMIO_SPTE_GEN_LOW_SHIFT 3 ++#define MMIO_SPTE_GEN_LOW_SHIFT 2 + #define MMIO_SPTE_GEN_HIGH_SHIFT 52 + +-#define MMIO_GEN_SHIFT 19 +-#define MMIO_GEN_LOW_SHIFT 9 +-#define MMIO_GEN_LOW_MASK ((1 << MMIO_GEN_LOW_SHIFT) - 1) ++#define MMIO_GEN_SHIFT 20 ++#define MMIO_GEN_LOW_SHIFT 10 ++#define MMIO_GEN_LOW_MASK ((1 << MMIO_GEN_LOW_SHIFT) - 2) + #define MMIO_GEN_MASK ((1 << MMIO_GEN_SHIFT) - 1) + #define MMIO_MAX_GEN ((1 << MMIO_GEN_SHIFT) - 1) + +@@ -3157,7 +3161,7 @@ static void mmu_sync_roots(struct kvm_vcpu *vcpu) + if (!VALID_PAGE(vcpu->arch.mmu.root_hpa)) + return; + +- vcpu_clear_mmio_info(vcpu, ~0ul); ++ vcpu_clear_mmio_info(vcpu, MMIO_GVA_ANY); + kvm_mmu_audit(vcpu, AUDIT_PRE_SYNC); + if (vcpu->arch.mmu.root_level == PT64_ROOT_LEVEL) { + hpa_t root = vcpu->arch.mmu.root_hpa; +@@ -4379,7 +4383,7 @@ void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm) + * The very rare case: if the generation-number is round, + * zap all shadow pages. + */ +- if (unlikely(kvm_current_mmio_generation(kvm) >= MMIO_MAX_GEN)) { ++ if (unlikely(kvm_current_mmio_generation(kvm) == 0)) { + printk_ratelimited(KERN_INFO "kvm: zapping shadow pages for mmio generation wraparound\n"); + kvm_mmu_invalidate_zap_all_pages(kvm); + } +diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h +index 8da5823bcde6..21ea4fc91b5b 100644 +--- a/arch/x86/kvm/x86.h ++++ b/arch/x86/kvm/x86.h +@@ -78,15 +78,23 @@ static inline void vcpu_cache_mmio_info(struct kvm_vcpu *vcpu, + vcpu->arch.mmio_gva = gva & PAGE_MASK; + vcpu->arch.access = access; + vcpu->arch.mmio_gfn = gfn; ++ vcpu->arch.mmio_gen = kvm_memslots(vcpu->kvm)->generation; ++} ++ ++static inline bool vcpu_match_mmio_gen(struct kvm_vcpu *vcpu) ++{ ++ return vcpu->arch.mmio_gen == kvm_memslots(vcpu->kvm)->generation; + } + + /* +- * Clear the mmio cache info for the given gva, +- * specially, if gva is ~0ul, we clear all mmio cache info. ++ * Clear the mmio cache info for the given gva. If gva is MMIO_GVA_ANY, we ++ * clear all mmio cache info. + */ ++#define MMIO_GVA_ANY (~(gva_t)0) ++ + static inline void vcpu_clear_mmio_info(struct kvm_vcpu *vcpu, gva_t gva) + { +- if (gva != (~0ul) && vcpu->arch.mmio_gva != (gva & PAGE_MASK)) ++ if (gva != MMIO_GVA_ANY && vcpu->arch.mmio_gva != (gva & PAGE_MASK)) + return; + + vcpu->arch.mmio_gva = 0; +@@ -94,7 +102,8 @@ static inline void vcpu_clear_mmio_info(struct kvm_vcpu *vcpu, gva_t gva) + + static inline bool vcpu_match_mmio_gva(struct kvm_vcpu *vcpu, unsigned long gva) + { +- if (vcpu->arch.mmio_gva && vcpu->arch.mmio_gva == (gva & PAGE_MASK)) ++ if (vcpu_match_mmio_gen(vcpu) && vcpu->arch.mmio_gva && ++ vcpu->arch.mmio_gva == (gva & PAGE_MASK)) + return true; + + return false; +@@ -102,7 +111,8 @@ static inline bool vcpu_match_mmio_gva(struct kvm_vcpu *vcpu, unsigned long gva) + + static inline bool vcpu_match_mmio_gpa(struct kvm_vcpu *vcpu, gpa_t gpa) + { +- if (vcpu->arch.mmio_gfn && vcpu->arch.mmio_gfn == gpa >> PAGE_SHIFT) ++ if (vcpu_match_mmio_gen(vcpu) && vcpu->arch.mmio_gfn && ++ vcpu->arch.mmio_gfn == gpa >> PAGE_SHIFT) + return true; + + return false; +diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c +index 3c562f5a60bb..e1bce26cd4f9 100644 +--- a/crypto/async_tx/async_xor.c ++++ b/crypto/async_tx/async_xor.c +@@ -78,8 +78,6 @@ do_async_xor(struct dma_chan *chan, struct dmaengine_unmap_data *unmap, + tx = dma->device_prep_dma_xor(chan, dma_dest, src_list, + xor_src_cnt, unmap->len, + dma_flags); +- src_list[0] = tmp; +- + + if (unlikely(!tx)) + async_tx_quiesce(&submit->depend_tx); +@@ -92,6 +90,7 @@ do_async_xor(struct dma_chan *chan, struct dmaengine_unmap_data *unmap, + xor_src_cnt, unmap->len, + dma_flags); + } ++ src_list[0] = tmp; + + dma_set_unmap(tx, unmap); + async_tx_submit(chan, tx, submit); +diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c +index c30df50e4440..2495ee577a64 100644 +--- a/drivers/base/firmware_class.c ++++ b/drivers/base/firmware_class.c +@@ -1081,6 +1081,9 @@ _request_firmware(const struct firmware **firmware_p, const char *name, + if (!firmware_p) + return -EINVAL; + ++ if (!name || name[0] == '\0') ++ return -EINVAL; ++ + ret = _request_firmware_prepare(&fw, name, device); + if (ret <= 0) /* error or already assigned */ + goto out; +diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c +index c5471cd6ebb7..d39fd610aa3b 100644 +--- a/drivers/base/regmap/regmap-debugfs.c ++++ b/drivers/base/regmap/regmap-debugfs.c +@@ -473,6 +473,7 @@ void regmap_debugfs_init(struct regmap *map, const char *name) + { + struct rb_node *next; + struct regmap_range_node *range_node; ++ const char *devname = "dummy"; + + /* If we don't have the debugfs root yet, postpone init */ + if (!regmap_debugfs_root) { +@@ -491,12 +492,15 @@ void regmap_debugfs_init(struct regmap *map, const char *name) + INIT_LIST_HEAD(&map->debugfs_off_cache); + mutex_init(&map->cache_lock); + ++ if (map->dev) ++ devname = dev_name(map->dev); ++ + if (name) { + map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s", +- dev_name(map->dev), name); ++ devname, name); + name = map->debugfs_name; + } else { +- name = dev_name(map->dev); ++ name = devname; + } + + map->debugfs = debugfs_create_dir(name, regmap_debugfs_root); +diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c +index 2ea056c09aeb..f6cff3be0ed7 100644 +--- a/drivers/base/regmap/regmap.c ++++ b/drivers/base/regmap/regmap.c +@@ -1308,7 +1308,7 @@ int _regmap_write(struct regmap *map, unsigned int reg, + } + + #ifdef LOG_DEVICE +- if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) ++ if (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0) + dev_info(map->dev, "%x <= %x\n", reg, val); + #endif + +@@ -1557,6 +1557,9 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, + } else { + void *wval; + ++ if (!val_count) ++ return -EINVAL; ++ + wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL); + if (!wval) { + ret = -ENOMEM; +@@ -1739,7 +1742,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg, + ret = map->reg_read(context, reg, val); + if (ret == 0) { + #ifdef LOG_DEVICE +- if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) ++ if (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0) + dev_info(map->dev, "%x => %x\n", reg, *val); + #endif + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 1c7b5040d921..e00c3f84a4cf 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -309,6 +309,9 @@ static void btusb_intr_complete(struct urb *urb) + BT_ERR("%s corrupted event packet", hdev->name); + hdev->stat.err_rx++; + } ++ } else if (urb->status == -ENOENT) { ++ /* Avoid suspend failed when usb_kill_urb */ ++ return; + } + + if (!test_bit(BTUSB_INTR_RUNNING, &data->flags)) +@@ -397,6 +400,9 @@ static void btusb_bulk_complete(struct urb *urb) + BT_ERR("%s corrupted ACL packet", hdev->name); + hdev->stat.err_rx++; + } ++ } else if (urb->status == -ENOENT) { ++ /* Avoid suspend failed when usb_kill_urb */ ++ return; + } + + if (!test_bit(BTUSB_BULK_RUNNING, &data->flags)) +@@ -491,6 +497,9 @@ static void btusb_isoc_complete(struct urb *urb) + hdev->stat.err_rx++; + } + } ++ } else if (urb->status == -ENOENT) { ++ /* Avoid suspend failed when usb_kill_urb */ ++ return; + } + + if (!test_bit(BTUSB_ISOC_RUNNING, &data->flags)) +diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c +index e36a0245f2c1..56519927479f 100644 +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -237,7 +237,7 @@ static void h5_pkt_cull(struct h5 *h5) + break; + + to_remove--; +- seq = (seq - 1) % 8; ++ seq = (seq - 1) & 0x07; + } + + if (seq != h5->rx_ack) +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +index 69ea36f07b4d..e99e71a6ea59 100644 +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -164,8 +164,10 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, + ret = vmbus_post_msg(open_msg, + sizeof(struct vmbus_channel_open_channel)); + +- if (ret != 0) ++ if (ret != 0) { ++ err = ret; + goto error1; ++ } + + t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ); + if (t == 0) { +@@ -362,7 +364,6 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, + u32 next_gpadl_handle; + unsigned long flags; + int ret = 0; +- int t; + + next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle); + atomic_inc(&vmbus_connection.next_gpadl_handle); +@@ -409,9 +410,7 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, + + } + } +- t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ); +- BUG_ON(t == 0); +- ++ wait_for_completion(&msginfo->waitevent); + + /* At this point, we received the gpadl created msg */ + *gpadl_handle = gpadlmsg->gpadl; +@@ -434,7 +433,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) + struct vmbus_channel_gpadl_teardown *msg; + struct vmbus_channel_msginfo *info; + unsigned long flags; +- int ret, t; ++ int ret; + + info = kmalloc(sizeof(*info) + + sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL); +@@ -456,11 +455,12 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) + ret = vmbus_post_msg(msg, + sizeof(struct vmbus_channel_gpadl_teardown)); + +- BUG_ON(ret != 0); +- t = wait_for_completion_timeout(&info->waitevent, 5*HZ); +- BUG_ON(t == 0); ++ if (ret) ++ goto post_msg_err; ++ ++ wait_for_completion(&info->waitevent); + +- /* Received a torndown response */ ++post_msg_err: + spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); + list_del(&info->msglistentry); + spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); +@@ -470,7 +470,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) + } + EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl); + +-static void vmbus_close_internal(struct vmbus_channel *channel) ++static int vmbus_close_internal(struct vmbus_channel *channel) + { + struct vmbus_channel_close_channel *msg; + int ret; +@@ -492,11 +492,28 @@ static void vmbus_close_internal(struct vmbus_channel *channel) + + ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel)); + +- BUG_ON(ret != 0); ++ if (ret) { ++ pr_err("Close failed: close post msg return is %d\n", ret); ++ /* ++ * If we failed to post the close msg, ++ * it is perhaps better to leak memory. ++ */ ++ return ret; ++ } ++ + /* Tear down the gpadl for the channel's ring buffer */ +- if (channel->ringbuffer_gpadlhandle) +- vmbus_teardown_gpadl(channel, +- channel->ringbuffer_gpadlhandle); ++ if (channel->ringbuffer_gpadlhandle) { ++ ret = vmbus_teardown_gpadl(channel, ++ channel->ringbuffer_gpadlhandle); ++ if (ret) { ++ pr_err("Close failed: teardown gpadl return %d\n", ret); ++ /* ++ * If we failed to teardown gpadl, ++ * it is perhaps better to leak memory. ++ */ ++ return ret; ++ } ++ } + + /* Cleanup the ring buffers for this channel */ + hv_ringbuffer_cleanup(&channel->outbound); +@@ -505,7 +522,7 @@ static void vmbus_close_internal(struct vmbus_channel *channel) + free_pages((unsigned long)channel->ringbuffer_pages, + get_order(channel->ringbuffer_pagecount * PAGE_SIZE)); + +- ++ return ret; + } + + /* +diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c +index ce5a9f2584f3..d8fd95cb0456 100644 +--- a/drivers/hv/connection.c ++++ b/drivers/hv/connection.c +@@ -408,10 +408,21 @@ int vmbus_post_msg(void *buffer, size_t buflen) + * insufficient resources. Retry the operation a couple of + * times before giving up. + */ +- while (retries < 3) { +- ret = hv_post_message(conn_id, 1, buffer, buflen); +- if (ret != HV_STATUS_INSUFFICIENT_BUFFERS) ++ while (retries < 10) { ++ ret = hv_post_message(conn_id, 1, buffer, buflen); ++ ++ switch (ret) { ++ case HV_STATUS_INSUFFICIENT_BUFFERS: ++ ret = -ENOMEM; ++ case -ENOMEM: ++ break; ++ case HV_STATUS_SUCCESS: + return ret; ++ default: ++ pr_err("hv_post_msg() failed; error code:%d\n", ret); ++ return -EINVAL; ++ } ++ + retries++; + msleep(100); + } +diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c +index 5653e505f91f..424f51d1e2ce 100644 +--- a/drivers/message/fusion/mptspi.c ++++ b/drivers/message/fusion/mptspi.c +@@ -1422,6 +1422,11 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) + goto out_mptspi_probe; + } + ++ /* VMWare emulation doesn't properly implement WRITE_SAME ++ */ ++ if (pdev->subsystem_vendor == 0x15AD) ++ sh->no_write_same = 1; ++ + spin_lock_irqsave(&ioc->FreeQlock, flags); + + /* Attach the SCSI Host to the IOC structure +diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c +index 4bc7d620d695..9a07bba3ade4 100644 +--- a/drivers/misc/mei/bus.c ++++ b/drivers/misc/mei/bus.c +@@ -71,7 +71,7 @@ static int mei_cl_device_probe(struct device *dev) + + dev_dbg(dev, "Device probe\n"); + +- strncpy(id.name, dev_name(dev), sizeof(id.name)); ++ strlcpy(id.name, dev_name(dev), sizeof(id.name)); + + return driver->probe(device, &id); + } +diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c +index df1f5e732ab5..1ac33d9cd396 100644 +--- a/drivers/net/wireless/iwlwifi/pcie/drv.c ++++ b/drivers/net/wireless/iwlwifi/pcie/drv.c +@@ -272,6 +272,8 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { + {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4072, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)}, ++ {IWL_PCI_DEVICE(0x08B1, 0x4C60, iwl7260_2ac_cfg)}, ++ {IWL_PCI_DEVICE(0x08B1, 0x4C70, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4060, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x406A, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4160, iwl7260_2n_cfg)}, +@@ -315,6 +317,8 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { + {IWL_PCI_DEVICE(0x08B1, 0xC770, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC760, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC270, iwl7260_2ac_cfg)}, ++ {IWL_PCI_DEVICE(0x08B1, 0xCC70, iwl7260_2ac_cfg)}, ++ {IWL_PCI_DEVICE(0x08B1, 0xCC60, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC272, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC260, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC26A, iwl7260_n_cfg)}, +diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h +index a394a9a95919..7cf6081a05a1 100644 +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -2039,7 +2039,7 @@ struct mac_iveiv_entry { + * 2 - drop tx power by 12dBm, + * 3 - increase tx power by 6dBm + */ +-#define BBP1_TX_POWER_CTRL FIELD8(0x07) ++#define BBP1_TX_POWER_CTRL FIELD8(0x03) + #define BBP1_TX_ANTENNA FIELD8(0x18) + + /* +diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c +index 483d9ad89705..97736674ddcd 100644 +--- a/drivers/pci/host/pci-mvebu.c ++++ b/drivers/pci/host/pci-mvebu.c +@@ -855,7 +855,7 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn, + rangesz = pna + na + ns; + nranges = rlen / sizeof(__be32) / rangesz; + +- for (i = 0; i < nranges; i++) { ++ for (i = 0; i < nranges; i++, range += rangesz) { + u32 flags = of_read_number(range, 1); + u32 slot = of_read_number(range + 1, 1); + u64 cpuaddr = of_read_number(range + na, pna); +@@ -865,14 +865,14 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn, + rtype = IORESOURCE_IO; + else if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_MEM32) + rtype = IORESOURCE_MEM; ++ else ++ continue; + + if (slot == PCI_SLOT(devfn) && type == rtype) { + *tgt = DT_CPUADDR_TO_TARGET(cpuaddr); + *attr = DT_CPUADDR_TO_ATTR(cpuaddr); + return 0; + } +- +- range += rangesz; + } + + return -ENOENT; +diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c +index 276ef9c18802..39a207abaa10 100644 +--- a/drivers/pci/pci-sysfs.c ++++ b/drivers/pci/pci-sysfs.c +@@ -178,7 +178,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + { + struct pci_dev *pci_dev = to_pci_dev(dev); + +- return sprintf(buf, "pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n", ++ return sprintf(buf, "pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02X\n", + pci_dev->vendor, pci_dev->device, + pci_dev->subsystem_vendor, pci_dev->subsystem_device, + (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8), +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 813f437f3ee8..6e8776b59a2c 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include /* isa_dma_bridge_buggy */ + #include "pci.h" + +@@ -287,6 +288,25 @@ static void quirk_citrine(struct pci_dev *dev) + } + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, quirk_citrine); + ++/* On IBM Crocodile ipr SAS adapters, expand BAR to system page size */ ++static void quirk_extend_bar_to_page(struct pci_dev *dev) ++{ ++ int i; ++ ++ for (i = 0; i < PCI_STD_RESOURCE_END; i++) { ++ struct resource *r = &dev->resource[i]; ++ ++ if (r->flags & IORESOURCE_MEM && resource_size(r) < PAGE_SIZE) { ++ r->end = PAGE_SIZE - 1; ++ r->start = 0; ++ r->flags |= IORESOURCE_UNSET; ++ dev_info(&dev->dev, "expanded BAR %d to page size: %pR\n", ++ i, r); ++ } ++ } ++} ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, 0x034a, quirk_extend_bar_to_page); ++ + /* + * S3 868 and 968 chips report region size equal to 32M, but they decode 64M. + * If it's needed, re-allocate the region. +diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c +index b2fcac78feaa..5bb9406688c9 100644 +--- a/drivers/scsi/be2iscsi/be_mgmt.c ++++ b/drivers/scsi/be2iscsi/be_mgmt.c +@@ -897,17 +897,20 @@ mgmt_static_ip_modify(struct beiscsi_hba *phba, + + if (ip_action == IP_ACTION_ADD) { + memcpy(req->ip_params.ip_record.ip_addr.addr, ip_param->value, +- ip_param->len); ++ sizeof(req->ip_params.ip_record.ip_addr.addr)); + + if (subnet_param) + memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, +- subnet_param->value, subnet_param->len); ++ subnet_param->value, ++ sizeof(req->ip_params.ip_record.ip_addr.subnet_mask)); + } else { + memcpy(req->ip_params.ip_record.ip_addr.addr, +- if_info->ip_addr.addr, ip_param->len); ++ if_info->ip_addr.addr, ++ sizeof(req->ip_params.ip_record.ip_addr.addr)); + + memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, +- if_info->ip_addr.subnet_mask, ip_param->len); ++ if_info->ip_addr.subnet_mask, ++ sizeof(req->ip_params.ip_record.ip_addr.subnet_mask)); + } + + rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); +@@ -935,7 +938,7 @@ static int mgmt_modify_gateway(struct beiscsi_hba *phba, uint8_t *gt_addr, + req->action = gtway_action; + req->ip_addr.ip_type = BE2_IPV4; + +- memcpy(req->ip_addr.addr, gt_addr, param_len); ++ memcpy(req->ip_addr.addr, gt_addr, sizeof(req->ip_addr.addr)); + + return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); + } +diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c +index 83cb61266979..23c1b0cd3074 100644 +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -3039,10 +3039,8 @@ qla2x00_unmap_iobases(struct qla_hw_data *ha) + } + + static void +-qla2x00_clear_drv_active(scsi_qla_host_t *vha) ++qla2x00_clear_drv_active(struct qla_hw_data *ha) + { +- struct qla_hw_data *ha = vha->hw; +- + if (IS_QLA8044(ha)) { + qla8044_idc_lock(ha); + qla8044_clear_drv_active(ha); +@@ -3111,7 +3109,7 @@ qla2x00_remove_one(struct pci_dev *pdev) + + scsi_host_put(base_vha->host); + +- qla2x00_clear_drv_active(base_vha); ++ qla2x00_clear_drv_active(ha); + + qla2x00_unmap_iobases(ha); + +diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c +index 0cb73074c199..2f264ac79546 100644 +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -1382,12 +1382,10 @@ static inline void qlt_unmap_sg(struct scsi_qla_host *vha, + static int qlt_check_reserve_free_req(struct scsi_qla_host *vha, + uint32_t req_cnt) + { +- struct qla_hw_data *ha = vha->hw; +- device_reg_t __iomem *reg = ha->iobase; + uint32_t cnt; + + if (vha->req->cnt < (req_cnt + 2)) { +- cnt = (uint16_t)RD_REG_DWORD(®->isp24.req_q_out); ++ cnt = (uint16_t)RD_REG_DWORD(vha->req->req_q_out); + + ql_dbg(ql_dbg_tgt, vha, 0xe00a, + "Request ring circled: cnt=%d, vha->->ring_index=%d, " +diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c +index 6d207afec8cb..a4c45ea8f688 100644 +--- a/drivers/spi/spi-dw-mid.c ++++ b/drivers/spi/spi-dw-mid.c +@@ -89,7 +89,13 @@ err_exit: + + static void mid_spi_dma_exit(struct dw_spi *dws) + { ++ if (!dws->dma_inited) ++ return; ++ ++ dmaengine_terminate_all(dws->txchan); + dma_release_channel(dws->txchan); ++ ++ dmaengine_terminate_all(dws->rxchan); + dma_release_channel(dws->rxchan); + } + +@@ -136,7 +142,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) + txconf.dst_addr = dws->dma_addr; + txconf.dst_maxburst = LNW_DMA_MSIZE_16; + txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +- txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; ++ txconf.dst_addr_width = dws->dma_width; + txconf.device_fc = false; + + txchan->device->device_control(txchan, DMA_SLAVE_CONFIG, +@@ -159,7 +165,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) + rxconf.src_addr = dws->dma_addr; + rxconf.src_maxburst = LNW_DMA_MSIZE_16; + rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +- rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; ++ rxconf.src_addr_width = dws->dma_width; + rxconf.device_fc = false; + + rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG, +diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c +index db8434d3def9..f4e68b3fc39d 100644 +--- a/drivers/tty/serial/omap-serial.c ++++ b/drivers/tty/serial/omap-serial.c +@@ -260,8 +260,16 @@ serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud) + { + unsigned int n13 = port->uartclk / (13 * baud); + unsigned int n16 = port->uartclk / (16 * baud); +- int baudAbsDiff13 = baud - (port->uartclk / (13 * n13)); +- int baudAbsDiff16 = baud - (port->uartclk / (16 * n16)); ++ int baudAbsDiff13; ++ int baudAbsDiff16; ++ ++ if (n13 == 0) ++ n13 = 1; ++ if (n16 == 0) ++ n16 = 1; ++ ++ baudAbsDiff13 = baud - (port->uartclk / (13 * n13)); ++ baudAbsDiff16 = baud - (port->uartclk / (16 * n16)); + if (baudAbsDiff13 < 0) + baudAbsDiff13 = -baudAbsDiff13; + if (baudAbsDiff16 < 0) +diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig +index 8154165aa601..fd13ef0a96c9 100644 +--- a/drivers/usb/gadget/Kconfig ++++ b/drivers/usb/gadget/Kconfig +@@ -445,7 +445,7 @@ config USB_GOKU + gadget drivers to also be dynamically linked. + + config USB_EG20T +- tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC" ++ tristate "Intel QUARK X1000/EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC" + depends on PCI + help + This is a USB device driver for EG20T PCH. +@@ -466,6 +466,7 @@ config USB_EG20T + ML7213/ML7831 is companion chip for Intel Atom E6xx series. + ML7213/ML7831 is completely compatible for Intel EG20T PCH. + ++ This driver can be used with Intel's Quark X1000 SOC platform + # + # LAST -- dummy/emulated controller + # +diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c +index eb8c3bedb57a..460d953c91b6 100644 +--- a/drivers/usb/gadget/pch_udc.c ++++ b/drivers/usb/gadget/pch_udc.c +@@ -343,6 +343,7 @@ struct pch_vbus_gpio_data { + * @setup_data: Received setup data + * @phys_addr: of device memory + * @base_addr: for mapped device memory ++ * @bar: Indicates which PCI BAR for USB regs + * @irq: IRQ line for the device + * @cfg_data: current cfg, intf, and alt in use + * @vbus_gpio: GPIO informaton for detecting VBUS +@@ -370,14 +371,17 @@ struct pch_udc_dev { + struct usb_ctrlrequest setup_data; + unsigned long phys_addr; + void __iomem *base_addr; ++ unsigned bar; + unsigned irq; + struct pch_udc_cfg_data cfg_data; + struct pch_vbus_gpio_data vbus_gpio; + }; + #define to_pch_udc(g) (container_of((g), struct pch_udc_dev, gadget)) + ++#define PCH_UDC_PCI_BAR_QUARK_X1000 0 + #define PCH_UDC_PCI_BAR 1 + #define PCI_DEVICE_ID_INTEL_EG20T_UDC 0x8808 ++#define PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC 0x0939 + #define PCI_VENDOR_ID_ROHM 0x10DB + #define PCI_DEVICE_ID_ML7213_IOH_UDC 0x801D + #define PCI_DEVICE_ID_ML7831_IOH_UDC 0x8808 +@@ -3076,7 +3080,7 @@ static void pch_udc_remove(struct pci_dev *pdev) + iounmap(dev->base_addr); + if (dev->mem_region) + release_mem_region(dev->phys_addr, +- pci_resource_len(pdev, PCH_UDC_PCI_BAR)); ++ pci_resource_len(pdev, dev->bar)); + if (dev->active) + pci_disable_device(pdev); + kfree(dev); +@@ -3144,9 +3148,15 @@ static int pch_udc_probe(struct pci_dev *pdev, + dev->active = 1; + pci_set_drvdata(pdev, dev); + ++ /* Determine BAR based on PCI ID */ ++ if (id->device == PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC) ++ dev->bar = PCH_UDC_PCI_BAR_QUARK_X1000; ++ else ++ dev->bar = PCH_UDC_PCI_BAR; ++ + /* PCI resource allocation */ +- resource = pci_resource_start(pdev, 1); +- len = pci_resource_len(pdev, 1); ++ resource = pci_resource_start(pdev, dev->bar); ++ len = pci_resource_len(pdev, dev->bar); + + if (!request_mem_region(resource, len, KBUILD_MODNAME)) { + dev_err(&pdev->dev, "%s: pci device used already\n", __func__); +@@ -3212,6 +3222,12 @@ finished: + + static const struct pci_device_id pch_udc_pcidev_id[] = { + { ++ PCI_DEVICE(PCI_VENDOR_ID_INTEL, ++ PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC), ++ .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, ++ .class_mask = 0xffffffff, ++ }, ++ { + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EG20T_UDC), + .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, + .class_mask = 0xffffffff, +diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c +index 0165b8672f09..a9a881ed8cbe 100644 +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -2510,23 +2510,28 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int whence) + struct btrfs_root *root = BTRFS_I(inode)->root; + struct extent_map *em = NULL; + struct extent_state *cached_state = NULL; +- u64 lockstart = *offset; +- u64 lockend = i_size_read(inode); +- u64 start = *offset; +- u64 len = i_size_read(inode); ++ u64 lockstart; ++ u64 lockend; ++ u64 start; ++ u64 len; + int ret = 0; + +- lockend = max_t(u64, root->sectorsize, lockend); ++ if (inode->i_size == 0) ++ return -ENXIO; ++ ++ /* ++ * *offset can be negative, in this case we start finding DATA/HOLE from ++ * the very start of the file. ++ */ ++ start = max_t(loff_t, 0, *offset); ++ ++ lockstart = round_down(start, root->sectorsize); ++ lockend = round_up(i_size_read(inode), root->sectorsize); + if (lockend <= lockstart) + lockend = lockstart + root->sectorsize; +- + lockend--; + len = lockend - lockstart + 1; + +- len = max_t(u64, len, root->sectorsize); +- if (inode->i_size == 0) +- return -ENXIO; +- + lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend, 0, + &cached_state); + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index c69c76351f12..d68a7250f00b 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -3596,7 +3596,8 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, + * without delay + */ + if (!btrfs_is_free_space_inode(inode) +- && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) { ++ && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID ++ && !root->fs_info->log_root_recovering) { + btrfs_update_root_times(trans, root); + + ret = btrfs_delayed_update_inode(trans, root, inode); +diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c +index a6d8efa46bfe..0b72006aecbe 100644 +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -302,6 +302,9 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) + goto out_drop; + + } else { ++ ret = btrfs_set_prop(inode, "btrfs.compression", NULL, 0, 0); ++ if (ret && ret != -ENODATA) ++ goto out_drop; + ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS); + } + +@@ -4750,6 +4753,12 @@ long btrfs_ioctl(struct file *file, unsigned int + if (ret) + return ret; + ret = btrfs_sync_fs(file->f_dentry->d_sb, 1); ++ /* ++ * The transaction thread may want to do more work, ++ * namely it pokes the cleaner ktread that will start ++ * processing uncleaned subvols. ++ */ ++ wake_up_process(root->fs_info->transaction_kthread); + return ret; + } + case BTRFS_IOC_START_SYNC: +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 07b3b36f40ee..01f977e3ce09 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -736,7 +736,8 @@ again: + err = ret; + goto out; + } +- BUG_ON(!ret || !path1->slots[0]); ++ ASSERT(ret); ++ ASSERT(path1->slots[0]); + + path1->slots[0]--; + +@@ -746,10 +747,10 @@ again: + * the backref was added previously when processing + * backref of type BTRFS_TREE_BLOCK_REF_KEY + */ +- BUG_ON(!list_is_singular(&cur->upper)); ++ ASSERT(list_is_singular(&cur->upper)); + edge = list_entry(cur->upper.next, struct backref_edge, + list[LOWER]); +- BUG_ON(!list_empty(&edge->list[UPPER])); ++ ASSERT(list_empty(&edge->list[UPPER])); + exist = edge->node[UPPER]; + /* + * add the upper level block to pending list if we need +@@ -831,7 +832,7 @@ again: + cur->cowonly = 1; + } + #else +- BUG_ON(key.type == BTRFS_EXTENT_REF_V0_KEY); ++ ASSERT(key.type != BTRFS_EXTENT_REF_V0_KEY); + if (key.type == BTRFS_SHARED_BLOCK_REF_KEY) { + #endif + if (key.objectid == key.offset) { +@@ -840,7 +841,7 @@ again: + * backref of this type. + */ + root = find_reloc_root(rc, cur->bytenr); +- BUG_ON(!root); ++ ASSERT(root); + cur->root = root; + break; + } +@@ -868,7 +869,7 @@ again: + } else { + upper = rb_entry(rb_node, struct backref_node, + rb_node); +- BUG_ON(!upper->checked); ++ ASSERT(upper->checked); + INIT_LIST_HEAD(&edge->list[UPPER]); + } + list_add_tail(&edge->list[LOWER], &cur->upper); +@@ -892,7 +893,7 @@ again: + + if (btrfs_root_level(&root->root_item) == cur->level) { + /* tree root */ +- BUG_ON(btrfs_root_bytenr(&root->root_item) != ++ ASSERT(btrfs_root_bytenr(&root->root_item) == + cur->bytenr); + if (should_ignore_root(root)) + list_add(&cur->list, &useless); +@@ -927,7 +928,7 @@ again: + need_check = true; + for (; level < BTRFS_MAX_LEVEL; level++) { + if (!path2->nodes[level]) { +- BUG_ON(btrfs_root_bytenr(&root->root_item) != ++ ASSERT(btrfs_root_bytenr(&root->root_item) == + lower->bytenr); + if (should_ignore_root(root)) + list_add(&lower->list, &useless); +@@ -976,12 +977,15 @@ again: + need_check = false; + list_add_tail(&edge->list[UPPER], + &list); +- } else ++ } else { ++ if (upper->checked) ++ need_check = true; + INIT_LIST_HEAD(&edge->list[UPPER]); ++ } + } else { + upper = rb_entry(rb_node, struct backref_node, + rb_node); +- BUG_ON(!upper->checked); ++ ASSERT(upper->checked); + INIT_LIST_HEAD(&edge->list[UPPER]); + if (!upper->owner) + upper->owner = btrfs_header_owner(eb); +@@ -1025,7 +1029,7 @@ next: + * everything goes well, connect backref nodes and insert backref nodes + * into the cache. + */ +- BUG_ON(!node->checked); ++ ASSERT(node->checked); + cowonly = node->cowonly; + if (!cowonly) { + rb_node = tree_insert(&cache->rb_root, node->bytenr, +@@ -1061,8 +1065,21 @@ next: + continue; + } + +- BUG_ON(!upper->checked); +- BUG_ON(cowonly != upper->cowonly); ++ if (!upper->checked) { ++ /* ++ * Still want to blow up for developers since this is a ++ * logic bug. ++ */ ++ ASSERT(0); ++ err = -EINVAL; ++ goto out; ++ } ++ if (cowonly != upper->cowonly) { ++ ASSERT(0); ++ err = -EINVAL; ++ goto out; ++ } ++ + if (!cowonly) { + rb_node = tree_insert(&cache->rb_root, upper->bytenr, + &upper->rb_node); +@@ -1085,7 +1102,7 @@ next: + while (!list_empty(&useless)) { + upper = list_entry(useless.next, struct backref_node, list); + list_del_init(&upper->list); +- BUG_ON(!list_empty(&upper->upper)); ++ ASSERT(list_empty(&upper->upper)); + if (upper == node) + node = NULL; + if (upper->lowest) { +@@ -1118,29 +1135,45 @@ out: + if (err) { + while (!list_empty(&useless)) { + lower = list_entry(useless.next, +- struct backref_node, upper); +- list_del_init(&lower->upper); ++ struct backref_node, list); ++ list_del_init(&lower->list); + } +- upper = node; +- INIT_LIST_HEAD(&list); +- while (upper) { +- if (RB_EMPTY_NODE(&upper->rb_node)) { +- list_splice_tail(&upper->upper, &list); +- free_backref_node(cache, upper); +- } +- +- if (list_empty(&list)) +- break; +- +- edge = list_entry(list.next, struct backref_edge, +- list[LOWER]); ++ while (!list_empty(&list)) { ++ edge = list_first_entry(&list, struct backref_edge, ++ list[UPPER]); ++ list_del(&edge->list[UPPER]); + list_del(&edge->list[LOWER]); ++ lower = edge->node[LOWER]; + upper = edge->node[UPPER]; + free_backref_edge(cache, edge); ++ ++ /* ++ * Lower is no longer linked to any upper backref nodes ++ * and isn't in the cache, we can free it ourselves. ++ */ ++ if (list_empty(&lower->upper) && ++ RB_EMPTY_NODE(&lower->rb_node)) ++ list_add(&lower->list, &useless); ++ ++ if (!RB_EMPTY_NODE(&upper->rb_node)) ++ continue; ++ ++ /* Add this guy's upper edges to the list to proces */ ++ list_for_each_entry(edge, &upper->upper, list[LOWER]) ++ list_add_tail(&edge->list[UPPER], &list); ++ if (list_empty(&upper->upper)) ++ list_add(&upper->list, &useless); ++ } ++ ++ while (!list_empty(&useless)) { ++ lower = list_entry(useless.next, ++ struct backref_node, list); ++ list_del_init(&lower->list); ++ free_backref_node(cache, lower); + } + return ERR_PTR(err); + } +- BUG_ON(node && node->detached); ++ ASSERT(!node || !node->detached); + return node; + } + +diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c +index a65ed4cb436b..20d793542096 100644 +--- a/fs/btrfs/send.c ++++ b/fs/btrfs/send.c +@@ -4728,7 +4728,9 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end) + + if (S_ISREG(sctx->cur_inode_mode)) { + if (need_send_hole(sctx)) { +- if (sctx->cur_inode_last_extent == (u64)-1) { ++ if (sctx->cur_inode_last_extent == (u64)-1 || ++ sctx->cur_inode_last_extent < ++ sctx->cur_inode_size) { + ret = get_last_extent(sctx, (u64)-1); + if (ret) + goto out; +diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c +index b05bf58b9395..a0b65a01fed7 100644 +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -592,7 +592,6 @@ int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid) + if (transid <= root->fs_info->last_trans_committed) + goto out; + +- ret = -EINVAL; + /* find specified transaction */ + spin_lock(&root->fs_info->trans_lock); + list_for_each_entry(t, &root->fs_info->trans_list, list) { +@@ -608,9 +607,16 @@ int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid) + } + } + spin_unlock(&root->fs_info->trans_lock); +- /* The specified transaction doesn't exist */ +- if (!cur_trans) ++ ++ /* ++ * The specified transaction doesn't exist, or we ++ * raced with btrfs_commit_transaction ++ */ ++ if (!cur_trans) { ++ if (transid > root->fs_info->last_trans_committed) ++ ret = -EINVAL; + goto out; ++ } + } else { + /* find newest transaction that is committing | committed */ + spin_lock(&root->fs_info->trans_lock); +diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c +index b167ca48b8ee..a85ceb7c91bc 100644 +--- a/fs/ecryptfs/inode.c ++++ b/fs/ecryptfs/inode.c +@@ -1039,7 +1039,7 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, + } + + rc = vfs_setxattr(lower_dentry, name, value, size, flags); +- if (!rc) ++ if (!rc && dentry->d_inode) + fsstack_copy_attr_all(dentry->d_inode, lower_dentry->d_inode); + out: + return rc; +diff --git a/fs/namespace.c b/fs/namespace.c +index 75536db4b69b..c7d4a0ae2c65 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1365,6 +1365,8 @@ static int do_umount(struct mount *mnt, int flags) + * Special case for "unmounting" root ... + * we just try to remount it readonly. + */ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; + down_write(&sb->s_umount); + if (!(sb->s_flags & MS_RDONLY)) + retval = do_remount_sb(sb, MS_RDONLY, NULL, 0); +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 2e9662ea5451..da657b7804a5 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -7242,7 +7242,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr + int ret = 0; + + if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) +- return 0; ++ return -EAGAIN; + task = _nfs41_proc_sequence(clp, cred, false); + if (IS_ERR(task)) + ret = PTR_ERR(task); +diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c +index 1720d32ffa54..e1ba58c3d1ad 100644 +--- a/fs/nfs/nfs4renewd.c ++++ b/fs/nfs/nfs4renewd.c +@@ -88,10 +88,18 @@ nfs4_renew_state(struct work_struct *work) + } + nfs_expire_all_delegations(clp); + } else { ++ int ret; ++ + /* Queue an asynchronous RENEW. */ +- ops->sched_state_renewal(clp, cred, renew_flags); ++ ret = ops->sched_state_renewal(clp, cred, renew_flags); + put_rpccred(cred); +- goto out_exp; ++ switch (ret) { ++ default: ++ goto out_exp; ++ case -EAGAIN: ++ case -ENOMEM: ++ break; ++ } + } + } else { + dprintk("%s: failed to call renewd. Reason: lease not expired \n", +diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c +index 27f5f858502b..b4f177f1d405 100644 +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -1732,7 +1732,8 @@ restart: + if (status < 0) { + set_bit(ops->owner_flag_bit, &sp->so_flags); + nfs4_put_state_owner(sp); +- return nfs4_recovery_handle_error(clp, status); ++ status = nfs4_recovery_handle_error(clp, status); ++ return (status != 0) ? status : -EAGAIN; + } + + nfs4_put_state_owner(sp); +@@ -1741,7 +1742,7 @@ restart: + spin_unlock(&clp->cl_lock); + } + rcu_read_unlock(); +- return status; ++ return 0; + } + + static int nfs4_check_lease(struct nfs_client *clp) +@@ -1788,7 +1789,6 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status) + break; + case -NFS4ERR_STALE_CLIENTID: + clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); +- nfs4_state_clear_reclaim_reboot(clp); + nfs4_state_start_reclaim_reboot(clp); + break; + case -NFS4ERR_CLID_INUSE: +@@ -2370,6 +2370,7 @@ static void nfs4_state_manager(struct nfs_client *clp) + status = nfs4_check_lease(clp); + if (status < 0) + goto out_error; ++ continue; + } + + if (test_and_clear_bit(NFS4CLNT_MOVED, &clp->cl_state)) { +@@ -2391,14 +2392,11 @@ static void nfs4_state_manager(struct nfs_client *clp) + section = "reclaim reboot"; + status = nfs4_do_reclaim(clp, + clp->cl_mvops->reboot_recovery_ops); +- if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || +- test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) +- continue; +- nfs4_state_end_reclaim_reboot(clp); +- if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) ++ if (status == -EAGAIN) + continue; + if (status < 0) + goto out_error; ++ nfs4_state_end_reclaim_reboot(clp); + } + + /* Now recover expired state... */ +@@ -2406,9 +2404,7 @@ static void nfs4_state_manager(struct nfs_client *clp) + section = "reclaim nograce"; + status = nfs4_do_reclaim(clp, + clp->cl_mvops->nograce_recovery_ops); +- if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || +- test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) || +- test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) ++ if (status == -EAGAIN) + continue; + if (status < 0) + goto out_error; +diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c +index 287a22c04149..de6323eb0113 100644 +--- a/fs/notify/fanotify/fanotify_user.c ++++ b/fs/notify/fanotify/fanotify_user.c +@@ -71,7 +71,7 @@ static int create_fd(struct fsnotify_group *group, + + pr_debug("%s: group=%p event=%p\n", __func__, group, event); + +- client_fd = get_unused_fd(); ++ client_fd = get_unused_fd_flags(group->fanotify_data.f_flags); + if (client_fd < 0) + return client_fd; + +diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c +index 5d2518b24cea..0461fbe405b7 100644 +--- a/fs/xfs/xfs_aops.c ++++ b/fs/xfs/xfs_aops.c +@@ -434,10 +434,22 @@ xfs_start_page_writeback( + { + ASSERT(PageLocked(page)); + ASSERT(!PageWriteback(page)); +- if (clear_dirty) ++ ++ /* ++ * if the page was not fully cleaned, we need to ensure that the higher ++ * layers come back to it correctly. That means we need to keep the page ++ * dirty, and for WB_SYNC_ALL writeback we need to ensure the ++ * PAGECACHE_TAG_TOWRITE index mark is not removed so another attempt to ++ * write this page in this writeback sweep will be made. ++ */ ++ if (clear_dirty) { + clear_page_dirty_for_io(page); +- set_page_writeback(page); ++ set_page_writeback(page); ++ } else ++ set_page_writeback_keepwrite(page); ++ + unlock_page(page); ++ + /* If no buffers on the page are to be written, finish it here */ + if (!buffers) + end_page_writeback(page); +diff --git a/include/linux/compiler-gcc5.h b/include/linux/compiler-gcc5.h +new file mode 100644 +index 000000000000..cdd1cc202d51 +--- /dev/null ++++ b/include/linux/compiler-gcc5.h +@@ -0,0 +1,66 @@ ++#ifndef __LINUX_COMPILER_H ++#error "Please don't include directly, include instead." ++#endif ++ ++#define __used __attribute__((__used__)) ++#define __must_check __attribute__((warn_unused_result)) ++#define __compiler_offsetof(a, b) __builtin_offsetof(a, b) ++ ++/* Mark functions as cold. gcc will assume any path leading to a call ++ to them will be unlikely. This means a lot of manual unlikely()s ++ are unnecessary now for any paths leading to the usual suspects ++ like BUG(), printk(), panic() etc. [but let's keep them for now for ++ older compilers] ++ ++ Early snapshots of gcc 4.3 don't support this and we can't detect this ++ in the preprocessor, but we can live with this because they're unreleased. ++ Maketime probing would be overkill here. ++ ++ gcc also has a __attribute__((__hot__)) to move hot functions into ++ a special section, but I don't see any sense in this right now in ++ the kernel context */ ++#define __cold __attribute__((__cold__)) ++ ++#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) ++ ++#ifndef __CHECKER__ ++# define __compiletime_warning(message) __attribute__((warning(message))) ++# define __compiletime_error(message) __attribute__((error(message))) ++#endif /* __CHECKER__ */ ++ ++/* ++ * Mark a position in code as unreachable. This can be used to ++ * suppress control flow warnings after asm blocks that transfer ++ * control elsewhere. ++ * ++ * Early snapshots of gcc 4.5 don't support this and we can't detect ++ * this in the preprocessor, but we can live with this because they're ++ * unreleased. Really, we need to have autoconf for the kernel. ++ */ ++#define unreachable() __builtin_unreachable() ++ ++/* Mark a function definition as prohibited from being cloned. */ ++#define __noclone __attribute__((__noclone__)) ++ ++/* ++ * Tell the optimizer that something else uses this function or variable. ++ */ ++#define __visible __attribute__((externally_visible)) ++ ++/* ++ * GCC 'asm goto' miscompiles certain code sequences: ++ * ++ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 ++ * ++ * Work it around via a compiler barrier quirk suggested by Jakub Jelinek. ++ * Fixed in GCC 4.8.2 and later versions. ++ * ++ * (asm goto is automatically volatile - the naming reflects this.) ++ */ ++#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) ++ ++#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP ++#define __HAVE_BUILTIN_BSWAP32__ ++#define __HAVE_BUILTIN_BSWAP64__ ++#define __HAVE_BUILTIN_BSWAP16__ ++#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ +diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h +index 97fbecdd7a40..057c1d8c77e5 100644 +--- a/include/linux/pci_ids.h ++++ b/include/linux/pci_ids.h +@@ -2551,6 +2551,7 @@ + #define PCI_DEVICE_ID_INTEL_MFD_EMMC0 0x0823 + #define PCI_DEVICE_ID_INTEL_MFD_EMMC1 0x0824 + #define PCI_DEVICE_ID_INTEL_MRST_SD2 0x084F ++#define PCI_DEVICE_ID_INTEL_QUARK_X1000_ILB 0x095E + #define PCI_DEVICE_ID_INTEL_I960 0x0960 + #define PCI_DEVICE_ID_INTEL_I960RM 0x0962 + #define PCI_DEVICE_ID_INTEL_CENTERTON_ILB 0x0c60 +diff --git a/include/linux/sched.h b/include/linux/sched.h +index d7ca410ace93..218b058060f1 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -1876,11 +1876,13 @@ extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, + #define tsk_used_math(p) ((p)->flags & PF_USED_MATH) + #define used_math() tsk_used_math(current) + +-/* __GFP_IO isn't allowed if PF_MEMALLOC_NOIO is set in current->flags */ ++/* __GFP_IO isn't allowed if PF_MEMALLOC_NOIO is set in current->flags ++ * __GFP_FS is also cleared as it implies __GFP_IO. ++ */ + static inline gfp_t memalloc_noio_flags(gfp_t flags) + { + if (unlikely(current->flags & PF_MEMALLOC_NOIO)) +- flags &= ~__GFP_IO; ++ flags &= ~(__GFP_IO | __GFP_FS); + return flags; + } + +diff --git a/kernel/futex.c b/kernel/futex.c +index 0b0dc02aabce..fda2950f2ce4 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -329,6 +329,8 @@ static void get_futex_key_refs(union futex_key *key) + case FUT_OFF_MMSHARED: + futex_get_mm(key); /* implies MB (B) */ + break; ++ default: ++ smp_mb(); /* explicit MB (B) */ + } + } + +diff --git a/lib/lzo/lzo1x_decompress_safe.c b/lib/lzo/lzo1x_decompress_safe.c +index 8563081e8da3..a1c387f6afba 100644 +--- a/lib/lzo/lzo1x_decompress_safe.c ++++ b/lib/lzo/lzo1x_decompress_safe.c +@@ -19,31 +19,21 @@ + #include + #include "lzodefs.h" + +-#define HAVE_IP(t, x) \ +- (((size_t)(ip_end - ip) >= (size_t)(t + x)) && \ +- (((t + x) >= t) && ((t + x) >= x))) ++#define HAVE_IP(x) ((size_t)(ip_end - ip) >= (size_t)(x)) ++#define HAVE_OP(x) ((size_t)(op_end - op) >= (size_t)(x)) ++#define NEED_IP(x) if (!HAVE_IP(x)) goto input_overrun ++#define NEED_OP(x) if (!HAVE_OP(x)) goto output_overrun ++#define TEST_LB(m_pos) if ((m_pos) < out) goto lookbehind_overrun + +-#define HAVE_OP(t, x) \ +- (((size_t)(op_end - op) >= (size_t)(t + x)) && \ +- (((t + x) >= t) && ((t + x) >= x))) +- +-#define NEED_IP(t, x) \ +- do { \ +- if (!HAVE_IP(t, x)) \ +- goto input_overrun; \ +- } while (0) +- +-#define NEED_OP(t, x) \ +- do { \ +- if (!HAVE_OP(t, x)) \ +- goto output_overrun; \ +- } while (0) +- +-#define TEST_LB(m_pos) \ +- do { \ +- if ((m_pos) < out) \ +- goto lookbehind_overrun; \ +- } while (0) ++/* This MAX_255_COUNT is the maximum number of times we can add 255 to a base ++ * count without overflowing an integer. The multiply will overflow when ++ * multiplying 255 by more than MAXINT/255. The sum will overflow earlier ++ * depending on the base count. Since the base count is taken from a u8 ++ * and a few bits, it is safe to assume that it will always be lower than ++ * or equal to 2*255, thus we can always prevent any overflow by accepting ++ * two less 255 steps. See Documentation/lzo.txt for more information. ++ */ ++#define MAX_255_COUNT ((((size_t)~0) / 255) - 2) + + int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, + unsigned char *out, size_t *out_len) +@@ -75,17 +65,24 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, + if (t < 16) { + if (likely(state == 0)) { + if (unlikely(t == 0)) { ++ size_t offset; ++ const unsigned char *ip_last = ip; ++ + while (unlikely(*ip == 0)) { +- t += 255; + ip++; +- NEED_IP(1, 0); ++ NEED_IP(1); + } +- t += 15 + *ip++; ++ offset = ip - ip_last; ++ if (unlikely(offset > MAX_255_COUNT)) ++ return LZO_E_ERROR; ++ ++ offset = (offset << 8) - offset; ++ t += offset + 15 + *ip++; + } + t += 3; + copy_literal_run: + #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) +- if (likely(HAVE_IP(t, 15) && HAVE_OP(t, 15))) { ++ if (likely(HAVE_IP(t + 15) && HAVE_OP(t + 15))) { + const unsigned char *ie = ip + t; + unsigned char *oe = op + t; + do { +@@ -101,8 +98,8 @@ copy_literal_run: + } else + #endif + { +- NEED_OP(t, 0); +- NEED_IP(t, 3); ++ NEED_OP(t); ++ NEED_IP(t + 3); + do { + *op++ = *ip++; + } while (--t > 0); +@@ -115,7 +112,7 @@ copy_literal_run: + m_pos -= t >> 2; + m_pos -= *ip++ << 2; + TEST_LB(m_pos); +- NEED_OP(2, 0); ++ NEED_OP(2); + op[0] = m_pos[0]; + op[1] = m_pos[1]; + op += 2; +@@ -136,13 +133,20 @@ copy_literal_run: + } else if (t >= 32) { + t = (t & 31) + (3 - 1); + if (unlikely(t == 2)) { ++ size_t offset; ++ const unsigned char *ip_last = ip; ++ + while (unlikely(*ip == 0)) { +- t += 255; + ip++; +- NEED_IP(1, 0); ++ NEED_IP(1); + } +- t += 31 + *ip++; +- NEED_IP(2, 0); ++ offset = ip - ip_last; ++ if (unlikely(offset > MAX_255_COUNT)) ++ return LZO_E_ERROR; ++ ++ offset = (offset << 8) - offset; ++ t += offset + 31 + *ip++; ++ NEED_IP(2); + } + m_pos = op - 1; + next = get_unaligned_le16(ip); +@@ -154,13 +158,20 @@ copy_literal_run: + m_pos -= (t & 8) << 11; + t = (t & 7) + (3 - 1); + if (unlikely(t == 2)) { ++ size_t offset; ++ const unsigned char *ip_last = ip; ++ + while (unlikely(*ip == 0)) { +- t += 255; + ip++; +- NEED_IP(1, 0); ++ NEED_IP(1); + } +- t += 7 + *ip++; +- NEED_IP(2, 0); ++ offset = ip - ip_last; ++ if (unlikely(offset > MAX_255_COUNT)) ++ return LZO_E_ERROR; ++ ++ offset = (offset << 8) - offset; ++ t += offset + 7 + *ip++; ++ NEED_IP(2); + } + next = get_unaligned_le16(ip); + ip += 2; +@@ -174,7 +185,7 @@ copy_literal_run: + #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) + if (op - m_pos >= 8) { + unsigned char *oe = op + t; +- if (likely(HAVE_OP(t, 15))) { ++ if (likely(HAVE_OP(t + 15))) { + do { + COPY8(op, m_pos); + op += 8; +@@ -184,7 +195,7 @@ copy_literal_run: + m_pos += 8; + } while (op < oe); + op = oe; +- if (HAVE_IP(6, 0)) { ++ if (HAVE_IP(6)) { + state = next; + COPY4(op, ip); + op += next; +@@ -192,7 +203,7 @@ copy_literal_run: + continue; + } + } else { +- NEED_OP(t, 0); ++ NEED_OP(t); + do { + *op++ = *m_pos++; + } while (op < oe); +@@ -201,7 +212,7 @@ copy_literal_run: + #endif + { + unsigned char *oe = op + t; +- NEED_OP(t, 0); ++ NEED_OP(t); + op[0] = m_pos[0]; + op[1] = m_pos[1]; + op += 2; +@@ -214,15 +225,15 @@ match_next: + state = next; + t = next; + #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) +- if (likely(HAVE_IP(6, 0) && HAVE_OP(4, 0))) { ++ if (likely(HAVE_IP(6) && HAVE_OP(4))) { + COPY4(op, ip); + op += t; + ip += t; + } else + #endif + { +- NEED_IP(t, 3); +- NEED_OP(t, 0); ++ NEED_IP(t + 3); ++ NEED_OP(t); + while (t > 0) { + *op++ = *ip++; + t--; +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 6afa3b45f25a..0007c9e9853a 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -2608,12 +2608,8 @@ static int l2cap_segment_le_sdu(struct l2cap_chan *chan, + + BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); + +- pdu_len = chan->conn->mtu - L2CAP_HDR_SIZE; +- +- pdu_len = min_t(size_t, pdu_len, chan->remote_mps); +- + sdu_len = len; +- pdu_len -= L2CAP_SDULEN_SIZE; ++ pdu_len = chan->remote_mps - L2CAP_SDULEN_SIZE; + + while (len > 0) { + if (len <= pdu_len) +diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c +index 734e9468aca0..6df1b2527d02 100644 +--- a/security/integrity/ima/ima_appraise.c ++++ b/security/integrity/ima/ima_appraise.c +@@ -194,8 +194,11 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, + goto out; + + cause = "missing-hash"; +- status = +- (inode->i_size == 0) ? INTEGRITY_PASS : INTEGRITY_NOLABEL; ++ status = INTEGRITY_NOLABEL; ++ if (inode->i_size == 0) { ++ iint->flags |= IMA_NEW_FILE; ++ status = INTEGRITY_PASS; ++ } + goto out; + } + +diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c +index 76d8aad146a8..9f70efd08058 100644 +--- a/security/integrity/ima/ima_main.c ++++ b/security/integrity/ima/ima_main.c +@@ -131,11 +131,13 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, + return; + + mutex_lock(&inode->i_mutex); +- if (atomic_read(&inode->i_writecount) == 1 && +- iint->version != inode->i_version) { +- iint->flags &= ~IMA_DONE_MASK; +- if (iint->flags & IMA_APPRAISE) +- ima_update_xattr(iint, file); ++ if (atomic_read(&inode->i_writecount) == 1) { ++ if ((iint->version != inode->i_version) || ++ (iint->flags & IMA_NEW_FILE)) { ++ iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE); ++ if (iint->flags & IMA_APPRAISE) ++ ima_update_xattr(iint, file); ++ } + } + mutex_unlock(&inode->i_mutex); + } +diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h +index 33c0a70f6b15..2f8715d77a5a 100644 +--- a/security/integrity/integrity.h ++++ b/security/integrity/integrity.h +@@ -31,6 +31,7 @@ + #define IMA_DIGSIG 0x01000000 + #define IMA_DIGSIG_REQUIRED 0x02000000 + #define IMA_PERMIT_DIRECTIO 0x04000000 ++#define IMA_NEW_FILE 0x08000000 + + #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ + IMA_APPRAISE_SUBMASK) +diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c +index 01a5e05ede95..566b0f69d628 100644 +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -3189,7 +3189,7 @@ static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = { + + #ifndef ARCH_HAS_DMA_MMAP_COHERENT + /* This should be defined / handled globally! */ +-#ifdef CONFIG_ARM ++#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) + #define ARCH_HAS_DMA_MMAP_COHERENT + #endif + #endif +diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c +index cae36597aa71..0a34b5f1c475 100644 +--- a/sound/pci/emu10k1/emu10k1_callback.c ++++ b/sound/pci/emu10k1/emu10k1_callback.c +@@ -85,6 +85,8 @@ snd_emu10k1_ops_setup(struct snd_emux *emux) + * get more voice for pcm + * + * terminate most inactive voice and give it as a pcm voice. ++ * ++ * voice_lock is already held. + */ + int + snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw) +@@ -92,12 +94,10 @@ snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw) + struct snd_emux *emu; + struct snd_emux_voice *vp; + struct best_voice best[V_END]; +- unsigned long flags; + int i; + + emu = hw->synth; + +- spin_lock_irqsave(&emu->voice_lock, flags); + lookup_voices(emu, hw, best, 1); /* no OFF voices */ + for (i = 0; i < V_END; i++) { + if (best[i].voice >= 0) { +@@ -113,11 +113,9 @@ snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw) + vp->emu->num_voices--; + vp->ch = -1; + vp->state = SNDRV_EMUX_ST_OFF; +- spin_unlock_irqrestore(&emu->voice_lock, flags); + return ch; + } + } +- spin_unlock_irqrestore(&emu->voice_lock, flags); + + /* not found */ + return -ENOMEM; +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index d135c906caff..8253b48a435b 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -1557,19 +1557,22 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) + } + } + +- if (pin_eld->eld_valid && !eld->eld_valid) { +- update_eld = true; ++ if (pin_eld->eld_valid != eld->eld_valid) + eld_changed = true; +- } ++ ++ if (pin_eld->eld_valid && !eld->eld_valid) ++ update_eld = true; ++ + if (update_eld) { + bool old_eld_valid = pin_eld->eld_valid; + pin_eld->eld_valid = eld->eld_valid; +- eld_changed = pin_eld->eld_size != eld->eld_size || ++ if (pin_eld->eld_size != eld->eld_size || + memcmp(pin_eld->eld_buffer, eld->eld_buffer, +- eld->eld_size) != 0; +- if (eld_changed) ++ eld->eld_size) != 0) { + memcpy(pin_eld->eld_buffer, eld->eld_buffer, + eld->eld_size); ++ eld_changed = true; ++ } + pin_eld->eld_size = eld->eld_size; + pin_eld->info = eld->info; + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 5d0058bd6259..4c826a40705c 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -2926,6 +2926,9 @@ static void alc283_shutup(struct hda_codec *codec) + + alc_write_coef_idx(codec, 0x43, 0x9004); + ++ /*depop hp during suspend*/ ++ alc_write_coef_idx(codec, 0x06, 0x2100); ++ + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index 223c47b33ba3..c657752a420c 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -385,6 +385,36 @@ YAMAHA_DEVICE(0x105d, NULL), + } + }, + { ++ USB_DEVICE(0x0499, 0x1509), ++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { ++ /* .vendor_name = "Yamaha", */ ++ /* .product_name = "Steinberg UR22", */ ++ .ifnum = QUIRK_ANY_INTERFACE, ++ .type = QUIRK_COMPOSITE, ++ .data = (const struct snd_usb_audio_quirk[]) { ++ { ++ .ifnum = 1, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 2, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 3, ++ .type = QUIRK_MIDI_YAMAHA ++ }, ++ { ++ .ifnum = 4, ++ .type = QUIRK_IGNORE_INTERFACE ++ }, ++ { ++ .ifnum = -1 ++ } ++ } ++ } ++}, ++{ + USB_DEVICE(0x0499, 0x150a), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + /* .vendor_name = "Yamaha", */ +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 03a0381b1cb7..66112533b1e9 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -52,6 +52,7 @@ + + #include + #include ++#include + #include + #include + +@@ -95,8 +96,6 @@ static int hardware_enable_all(void); + static void hardware_disable_all(void); + + static void kvm_io_bus_destroy(struct kvm_io_bus *bus); +-static void update_memslots(struct kvm_memslots *slots, +- struct kvm_memory_slot *new, u64 last_generation); + + static void kvm_release_pfn_dirty(pfn_t pfn); + static void mark_page_dirty_in_slot(struct kvm *kvm, +@@ -682,8 +681,7 @@ static void sort_memslots(struct kvm_memslots *slots) + } + + static void update_memslots(struct kvm_memslots *slots, +- struct kvm_memory_slot *new, +- u64 last_generation) ++ struct kvm_memory_slot *new) + { + if (new) { + int id = new->id; +@@ -694,8 +692,6 @@ static void update_memslots(struct kvm_memslots *slots, + if (new->npages != npages) + sort_memslots(slots); + } +- +- slots->generation = last_generation + 1; + } + + static int check_memory_region_flags(struct kvm_userspace_memory_region *mem) +@@ -717,10 +713,24 @@ static struct kvm_memslots *install_new_memslots(struct kvm *kvm, + { + struct kvm_memslots *old_memslots = kvm->memslots; + +- update_memslots(slots, new, kvm->memslots->generation); ++ /* ++ * Set the low bit in the generation, which disables SPTE caching ++ * until the end of synchronize_srcu_expedited. ++ */ ++ WARN_ON(old_memslots->generation & 1); ++ slots->generation = old_memslots->generation + 1; ++ ++ update_memslots(slots, new); + rcu_assign_pointer(kvm->memslots, slots); + synchronize_srcu_expedited(&kvm->srcu); + ++ /* ++ * Increment the new memslot generation a second time. This prevents ++ * vm exits that race with memslot updates from caching a memslot ++ * generation that will (potentially) be valid forever. ++ */ ++ slots->generation++; ++ + kvm_arch_memslots_updated(kvm); + + return old_memslots; +@@ -1970,6 +1980,9 @@ static long kvm_vcpu_ioctl(struct file *filp, + if (vcpu->kvm->mm != current->mm) + return -EIO; + ++ if (unlikely(_IOC_TYPE(ioctl) != KVMIO)) ++ return -EINVAL; ++ + #if defined(CONFIG_S390) || defined(CONFIG_PPC) || defined(CONFIG_MIPS) + /* + * Special cases: vcpu ioctls that are asynchronous to vcpu execution, diff --git a/patch/kernel/cubox-default/patch-3.14.23-24.patch b/patch/kernel/cubox-default/patch-3.14.23-24.patch new file mode 100644 index 000000000..0e862921c --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.23-24.patch @@ -0,0 +1,7091 @@ +diff --git a/Makefile b/Makefile +index 135a04a26076..8fd06101c482 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 23 ++SUBLEVEL = 24 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arc/boot/dts/nsimosci.dts b/arch/arc/boot/dts/nsimosci.dts +index 4f31b2eb5cdf..398064cef746 100644 +--- a/arch/arc/boot/dts/nsimosci.dts ++++ b/arch/arc/boot/dts/nsimosci.dts +@@ -20,7 +20,7 @@ + /* this is for console on PGU */ + /* bootargs = "console=tty0 consoleblank=0"; */ + /* this is for console on serial */ +- bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=ttyS0,115200n8 consoleblank=0 debug"; ++ bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug"; + }; + + aliases { +diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h +index 2fd3162ec4df..c1d3d2da1191 100644 +--- a/arch/arc/include/asm/cache.h ++++ b/arch/arc/include/asm/cache.h +@@ -55,4 +55,31 @@ extern void read_decode_cache_bcr(void); + + #endif /* !__ASSEMBLY__ */ + ++/* Instruction cache related Auxiliary registers */ ++#define ARC_REG_IC_BCR 0x77 /* Build Config reg */ ++#define ARC_REG_IC_IVIC 0x10 ++#define ARC_REG_IC_CTRL 0x11 ++#define ARC_REG_IC_IVIL 0x19 ++#if defined(CONFIG_ARC_MMU_V3) || defined (CONFIG_ARC_MMU_V4) ++#define ARC_REG_IC_PTAG 0x1E ++#endif ++ ++/* Bit val in IC_CTRL */ ++#define IC_CTRL_CACHE_DISABLE 0x1 ++ ++/* Data cache related Auxiliary registers */ ++#define ARC_REG_DC_BCR 0x72 /* Build Config reg */ ++#define ARC_REG_DC_IVDC 0x47 ++#define ARC_REG_DC_CTRL 0x48 ++#define ARC_REG_DC_IVDL 0x4A ++#define ARC_REG_DC_FLSH 0x4B ++#define ARC_REG_DC_FLDL 0x4C ++#if defined(CONFIG_ARC_MMU_V3) || defined (CONFIG_ARC_MMU_V4) ++#define ARC_REG_DC_PTAG 0x5C ++#endif ++ ++/* Bit val in DC_CTRL */ ++#define DC_CTRL_INV_MODE_FLUSH 0x40 ++#define DC_CTRL_FLUSH_STATUS 0x100 ++ + #endif /* _ASM_CACHE_H */ +diff --git a/arch/arc/include/asm/kgdb.h b/arch/arc/include/asm/kgdb.h +index b65fca7ffeb5..fea931634136 100644 +--- a/arch/arc/include/asm/kgdb.h ++++ b/arch/arc/include/asm/kgdb.h +@@ -19,7 +19,7 @@ + * register API yet */ + #undef DBG_MAX_REG_NUM + +-#define GDB_MAX_REGS 39 ++#define GDB_MAX_REGS 87 + + #define BREAK_INSTR_SIZE 2 + #define CACHE_FLUSH_IS_SAFE 1 +@@ -33,23 +33,27 @@ static inline void arch_kgdb_breakpoint(void) + + extern void kgdb_trap(struct pt_regs *regs); + +-enum arc700_linux_regnums { ++/* This is the numbering of registers according to the GDB. See GDB's ++ * arc-tdep.h for details. ++ * ++ * Registers are ordered for GDB 7.5. It is incompatible with GDB 6.8. */ ++enum arc_linux_regnums { + _R0 = 0, + _R1, _R2, _R3, _R4, _R5, _R6, _R7, _R8, _R9, _R10, _R11, _R12, _R13, + _R14, _R15, _R16, _R17, _R18, _R19, _R20, _R21, _R22, _R23, _R24, + _R25, _R26, +- _BTA = 27, +- _LP_START = 28, +- _LP_END = 29, +- _LP_COUNT = 30, +- _STATUS32 = 31, +- _BLINK = 32, +- _FP = 33, +- __SP = 34, +- _EFA = 35, +- _RET = 36, +- _ORIG_R8 = 37, +- _STOP_PC = 38 ++ _FP = 27, ++ __SP = 28, ++ _R30 = 30, ++ _BLINK = 31, ++ _LP_COUNT = 60, ++ _STOP_PC = 64, ++ _RET = 64, ++ _LP_START = 65, ++ _LP_END = 66, ++ _STATUS32 = 67, ++ _ECR = 76, ++ _BTA = 82, + }; + + #else +diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S +index 991997269d02..07a58f2d3077 100644 +--- a/arch/arc/kernel/head.S ++++ b/arch/arc/kernel/head.S +@@ -12,10 +12,42 @@ + * to skip certain things during boot on simulator + */ + ++#include + #include + #include +-#include + #include ++#include ++ ++.macro CPU_EARLY_SETUP ++ ++ ; Setting up Vectror Table (in case exception happens in early boot ++ sr @_int_vec_base_lds, [AUX_INTR_VEC_BASE] ++ ++ ; Disable I-cache/D-cache if kernel so configured ++ lr r5, [ARC_REG_IC_BCR] ++ breq r5, 0, 1f ; I$ doesn't exist ++ lr r5, [ARC_REG_IC_CTRL] ++#ifdef CONFIG_ARC_HAS_ICACHE ++ bclr r5, r5, 0 ; 0 - Enable, 1 is Disable ++#else ++ bset r5, r5, 0 ; I$ exists, but is not used ++#endif ++ sr r5, [ARC_REG_IC_CTRL] ++ ++1: ++ lr r5, [ARC_REG_DC_BCR] ++ breq r5, 0, 1f ; D$ doesn't exist ++ lr r5, [ARC_REG_DC_CTRL] ++ bclr r5, r5, 6 ; Invalidate (discard w/o wback) ++#ifdef CONFIG_ARC_HAS_DCACHE ++ bclr r5, r5, 0 ; Enable (+Inv) ++#else ++ bset r5, r5, 0 ; Disable (+Inv) ++#endif ++ sr r5, [ARC_REG_DC_CTRL] ++ ++1: ++.endm + + .cpu A7 + +@@ -24,13 +56,13 @@ + .globl stext + stext: + ;------------------------------------------------------------------- +- ; Don't clobber r0-r4 yet. It might have bootloader provided info ++ ; Don't clobber r0-r2 yet. It might have bootloader provided info + ;------------------------------------------------------------------- + +- sr @_int_vec_base_lds, [AUX_INTR_VEC_BASE] ++ CPU_EARLY_SETUP + + #ifdef CONFIG_SMP +- ; Only Boot (Master) proceeds. Others wait in platform dependent way ++ ; Ensure Boot (Master) proceeds. Others wait in platform dependent way + ; IDENTITY Reg [ 3 2 1 0 ] + ; (cpu-id) ^^^ => Zero for UP ARC700 + ; => #Core-ID if SMP (Master 0) +@@ -39,7 +71,8 @@ stext: + ; need to make sure only boot cpu takes this path. + GET_CPU_ID r5 + cmp r5, 0 +- jnz arc_platform_smp_wait_to_boot ++ mov.ne r0, r5 ++ jne arc_platform_smp_wait_to_boot + #endif + ; Clear BSS before updating any globals + ; XXX: use ZOL here +@@ -89,7 +122,7 @@ stext: + + first_lines_of_secondary: + +- sr @_int_vec_base_lds, [AUX_INTR_VEC_BASE] ++ CPU_EARLY_SETUP + + ; setup per-cpu idle task as "current" on this CPU + ld r0, [@secondary_idle_tsk] +diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c +index 400c663b21c2..1f676c4794e0 100644 +--- a/arch/arc/mm/cache_arc700.c ++++ b/arch/arc/mm/cache_arc700.c +@@ -73,37 +73,9 @@ + #include + #include + +-/* Instruction cache related Auxiliary registers */ +-#define ARC_REG_IC_BCR 0x77 /* Build Config reg */ +-#define ARC_REG_IC_IVIC 0x10 +-#define ARC_REG_IC_CTRL 0x11 +-#define ARC_REG_IC_IVIL 0x19 +-#if (CONFIG_ARC_MMU_VER > 2) +-#define ARC_REG_IC_PTAG 0x1E +-#endif +- +-/* Bit val in IC_CTRL */ +-#define IC_CTRL_CACHE_DISABLE 0x1 +- +-/* Data cache related Auxiliary registers */ +-#define ARC_REG_DC_BCR 0x72 /* Build Config reg */ +-#define ARC_REG_DC_IVDC 0x47 +-#define ARC_REG_DC_CTRL 0x48 +-#define ARC_REG_DC_IVDL 0x4A +-#define ARC_REG_DC_FLSH 0x4B +-#define ARC_REG_DC_FLDL 0x4C +-#if (CONFIG_ARC_MMU_VER > 2) +-#define ARC_REG_DC_PTAG 0x5C +-#endif +- +-/* Bit val in DC_CTRL */ +-#define DC_CTRL_INV_MODE_FLUSH 0x40 +-#define DC_CTRL_FLUSH_STATUS 0x100 +- +-char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len) ++char *arc_cache_mumbojumbo(int c, char *buf, int len) + { + int n = 0; +- unsigned int c = smp_processor_id(); + + #define PR_CACHE(p, enb, str) \ + { \ +@@ -169,72 +141,43 @@ void read_decode_cache_bcr(void) + */ + void arc_cache_init(void) + { +- unsigned int cpu = smp_processor_id(); +- struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache; +- struct cpuinfo_arc_cache *dc = &cpuinfo_arc700[cpu].dcache; +- unsigned int dcache_does_alias, temp; ++ unsigned int __maybe_unused cpu = smp_processor_id(); ++ struct cpuinfo_arc_cache __maybe_unused *ic, __maybe_unused *dc; + char str[256]; + + printk(arc_cache_mumbojumbo(0, str, sizeof(str))); + +- if (!ic->ver) +- goto chk_dc; +- +-#ifdef CONFIG_ARC_HAS_ICACHE +- /* 1. Confirm some of I-cache params which Linux assumes */ +- if (ic->line_len != L1_CACHE_BYTES) +- panic("Cache H/W doesn't match kernel Config"); +- +- if (ic->ver != CONFIG_ARC_MMU_VER) +- panic("Cache ver doesn't match MMU ver\n"); +-#endif +- +- /* Enable/disable I-Cache */ +- temp = read_aux_reg(ARC_REG_IC_CTRL); +- + #ifdef CONFIG_ARC_HAS_ICACHE +- temp &= ~IC_CTRL_CACHE_DISABLE; +-#else +- temp |= IC_CTRL_CACHE_DISABLE; ++ ic = &cpuinfo_arc700[cpu].icache; ++ if (ic->ver) { ++ if (ic->line_len != L1_CACHE_BYTES) ++ panic("ICache line [%d] != kernel Config [%d]", ++ ic->line_len, L1_CACHE_BYTES); ++ ++ if (ic->ver != CONFIG_ARC_MMU_VER) ++ panic("Cache ver [%d] doesn't match MMU ver [%d]\n", ++ ic->ver, CONFIG_ARC_MMU_VER); ++ } + #endif + +- write_aux_reg(ARC_REG_IC_CTRL, temp); +- +-chk_dc: +- if (!dc->ver) +- return; +- + #ifdef CONFIG_ARC_HAS_DCACHE +- if (dc->line_len != L1_CACHE_BYTES) +- panic("Cache H/W doesn't match kernel Config"); ++ dc = &cpuinfo_arc700[cpu].dcache; ++ if (dc->ver) { ++ unsigned int dcache_does_alias; + +- /* check for D-Cache aliasing */ +- dcache_does_alias = (dc->sz / dc->assoc) > PAGE_SIZE; ++ if (dc->line_len != L1_CACHE_BYTES) ++ panic("DCache line [%d] != kernel Config [%d]", ++ dc->line_len, L1_CACHE_BYTES); + +- if (dcache_does_alias && !cache_is_vipt_aliasing()) +- panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n"); +- else if (!dcache_does_alias && cache_is_vipt_aliasing()) +- panic("Don't need CONFIG_ARC_CACHE_VIPT_ALIASING\n"); +-#endif +- +- /* Set the default Invalidate Mode to "simpy discard dirty lines" +- * as this is more frequent then flush before invalidate +- * Ofcourse we toggle this default behviour when desired +- */ +- temp = read_aux_reg(ARC_REG_DC_CTRL); +- temp &= ~DC_CTRL_INV_MODE_FLUSH; ++ /* check for D-Cache aliasing */ ++ dcache_does_alias = (dc->sz / dc->assoc) > PAGE_SIZE; + +-#ifdef CONFIG_ARC_HAS_DCACHE +- /* Enable D-Cache: Clear Bit 0 */ +- write_aux_reg(ARC_REG_DC_CTRL, temp & ~IC_CTRL_CACHE_DISABLE); +-#else +- /* Flush D cache */ +- write_aux_reg(ARC_REG_DC_FLSH, 0x1); +- /* Disable D cache */ +- write_aux_reg(ARC_REG_DC_CTRL, temp | IC_CTRL_CACHE_DISABLE); ++ if (dcache_does_alias && !cache_is_vipt_aliasing()) ++ panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n"); ++ else if (!dcache_does_alias && cache_is_vipt_aliasing()) ++ panic("Don't need CONFIG_ARC_CACHE_VIPT_ALIASING\n"); ++ } + #endif +- +- return; + } + + #define OP_INV 0x1 +@@ -254,12 +197,16 @@ static inline void __cache_line_loop(unsigned long paddr, unsigned long vaddr, + + if (cacheop == OP_INV_IC) { + aux_cmd = ARC_REG_IC_IVIL; ++#if (CONFIG_ARC_MMU_VER > 2) + aux_tag = ARC_REG_IC_PTAG; ++#endif + } + else { + /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ + aux_cmd = cacheop & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL; ++#if (CONFIG_ARC_MMU_VER > 2) + aux_tag = ARC_REG_DC_PTAG; ++#endif + } + + /* Ensure we properly floor/ceil the non-line aligned/sized requests +diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h +index 992aaba603b5..b463f2aa5a61 100644 +--- a/arch/mips/include/asm/ftrace.h ++++ b/arch/mips/include/asm/ftrace.h +@@ -24,7 +24,7 @@ do { \ + asm volatile ( \ + "1: " load " %[tmp_dst], 0(%[tmp_src])\n" \ + " li %[tmp_err], 0\n" \ +- "2:\n" \ ++ "2: .insn\n" \ + \ + ".section .fixup, \"ax\"\n" \ + "3: li %[tmp_err], 1\n" \ +@@ -46,7 +46,7 @@ do { \ + asm volatile ( \ + "1: " store " %[tmp_src], 0(%[tmp_dst])\n"\ + " li %[tmp_err], 0\n" \ +- "2:\n" \ ++ "2: .insn\n" \ + \ + ".section .fixup, \"ax\"\n" \ + "3: li %[tmp_err], 1\n" \ +diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c +index 65d452aa1fda..dd012c599ad1 100644 +--- a/arch/mips/mm/tlbex.c ++++ b/arch/mips/mm/tlbex.c +@@ -1057,6 +1057,7 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) + struct mips_huge_tlb_info { + int huge_pte; + int restore_scratch; ++ bool need_reload_pte; + }; + + static struct mips_huge_tlb_info +@@ -1071,6 +1072,7 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, + + rv.huge_pte = scratch; + rv.restore_scratch = 0; ++ rv.need_reload_pte = false; + + if (check_for_high_segbits) { + UASM_i_MFC0(p, tmp, C0_BADVADDR); +@@ -1259,6 +1261,7 @@ static void build_r4000_tlb_refill_handler(void) + } else { + htlb_info.huge_pte = K0; + htlb_info.restore_scratch = 0; ++ htlb_info.need_reload_pte = true; + vmalloc_mode = refill_noscratch; + /* + * create the plain linear handler +@@ -1295,7 +1298,8 @@ static void build_r4000_tlb_refill_handler(void) + } + #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT + uasm_l_tlb_huge_update(&l, p); +- UASM_i_LW(&p, K0, 0, K1); ++ if (htlb_info.need_reload_pte) ++ UASM_i_LW(&p, htlb_info.huge_pte, 0, K1); + build_huge_update_entries(&p, htlb_info.huge_pte, K1); + build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random, + htlb_info.restore_scratch); +diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c +index a8fe5aa3d34f..3b46eed1dcf6 100644 +--- a/arch/powerpc/platforms/pseries/dlpar.c ++++ b/arch/powerpc/platforms/pseries/dlpar.c +@@ -380,7 +380,7 @@ static int dlpar_online_cpu(struct device_node *dn) + BUG_ON(get_cpu_current_state(cpu) + != CPU_STATE_OFFLINE); + cpu_maps_update_done(); +- rc = cpu_up(cpu); ++ rc = device_online(get_cpu_device(cpu)); + if (rc) + goto out; + cpu_maps_update_begin(); +@@ -463,7 +463,7 @@ static int dlpar_offline_cpu(struct device_node *dn) + if (get_cpu_current_state(cpu) == CPU_STATE_ONLINE) { + set_preferred_offline_state(cpu, CPU_STATE_OFFLINE); + cpu_maps_update_done(); +- rc = cpu_down(cpu); ++ rc = device_offline(get_cpu_device(cpu)); + if (rc) + goto out; + cpu_maps_update_begin(); +diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c +index ff1465c0519c..5acf89c1afc5 100644 +--- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c ++++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c +@@ -118,7 +118,7 @@ static struct plat_sci_port scif0_platform_data = { + }; + + static struct resource scif0_resources[] = { +- DEFINE_RES_MEM(0xfffffe80, 0x100), ++ DEFINE_RES_MEM(0xfffffe80, 0x10), + DEFINE_RES_IRQ(evt2irq(0x4e0)), + }; + +@@ -143,7 +143,7 @@ static struct plat_sci_port scif1_platform_data = { + }; + + static struct resource scif1_resources[] = { +- DEFINE_RES_MEM(0xa4000150, 0x100), ++ DEFINE_RES_MEM(0xa4000150, 0x10), + DEFINE_RES_IRQ(evt2irq(0x900)), + }; + +@@ -169,7 +169,7 @@ static struct plat_sci_port scif2_platform_data = { + }; + + static struct resource scif2_resources[] = { +- DEFINE_RES_MEM(0xa4000140, 0x100), ++ DEFINE_RES_MEM(0xa4000140, 0x10), + DEFINE_RES_IRQ(evt2irq(0x880)), + }; + +diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c +index 3716e6952554..e8ab93c3e638 100644 +--- a/arch/um/drivers/ubd_kern.c ++++ b/arch/um/drivers/ubd_kern.c +@@ -1277,7 +1277,7 @@ static void do_ubd_request(struct request_queue *q) + + while(1){ + struct ubd *dev = q->queuedata; +- if(dev->end_sg == 0){ ++ if(dev->request == NULL){ + struct request *req = blk_fetch_request(q); + if(req == NULL) + return; +@@ -1299,7 +1299,8 @@ static void do_ubd_request(struct request_queue *q) + return; + } + prepare_flush_request(req, io_req); +- submit_request(io_req, dev); ++ if (submit_request(io_req, dev) == false) ++ return; + } + + while(dev->start_sg < dev->end_sg){ +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index e4098912fef2..98aa930230ec 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -2436,12 +2436,9 @@ config X86_DMA_REMAP + depends on STA2X11 + + config IOSF_MBI +- bool ++ tristate ++ default m + depends on PCI +- ---help--- +- To be selected by modules requiring access to the Intel OnChip System +- Fabric (IOSF) Sideband MailBox Interface (MBI). For MBI platforms +- enumerable by PCI. + + source "net/Kconfig" + +diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S +index 4299eb05023c..92a2e9333620 100644 +--- a/arch/x86/ia32/ia32entry.S ++++ b/arch/x86/ia32/ia32entry.S +@@ -151,6 +151,16 @@ ENTRY(ia32_sysenter_target) + 1: movl (%rbp),%ebp + _ASM_EXTABLE(1b,ia32_badarg) + ASM_CLAC ++ ++ /* ++ * Sysenter doesn't filter flags, so we need to clear NT ++ * ourselves. To save a few cycles, we can check whether ++ * NT was set instead of doing an unconditional popfq. ++ */ ++ testl $X86_EFLAGS_NT,EFLAGS-ARGOFFSET(%rsp) ++ jnz sysenter_fix_flags ++sysenter_flags_fixed: ++ + orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + CFI_REMEMBER_STATE +@@ -184,6 +194,8 @@ sysexit_from_sys_call: + TRACE_IRQS_ON + ENABLE_INTERRUPTS_SYSEXIT32 + ++ CFI_RESTORE_STATE ++ + #ifdef CONFIG_AUDITSYSCALL + .macro auditsys_entry_common + movl %esi,%r9d /* 6th arg: 4th syscall arg */ +@@ -226,7 +238,6 @@ sysexit_from_sys_call: + .endm + + sysenter_auditsys: +- CFI_RESTORE_STATE + auditsys_entry_common + movl %ebp,%r9d /* reload 6th syscall arg */ + jmp sysenter_dispatch +@@ -235,6 +246,11 @@ sysexit_audit: + auditsys_exit sysexit_from_sys_call + #endif + ++sysenter_fix_flags: ++ pushq_cfi $(X86_EFLAGS_IF|X86_EFLAGS_FIXED) ++ popfq_cfi ++ jmp sysenter_flags_fixed ++ + sysenter_tracesys: + #ifdef CONFIG_AUDITSYSCALL + testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) +diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h +index 9c999c1674fa..01f15b227d7e 100644 +--- a/arch/x86/include/asm/elf.h ++++ b/arch/x86/include/asm/elf.h +@@ -155,8 +155,9 @@ do { \ + #define elf_check_arch(x) \ + ((x)->e_machine == EM_X86_64) + +-#define compat_elf_check_arch(x) \ +- (elf_check_arch_ia32(x) || (x)->e_machine == EM_X86_64) ++#define compat_elf_check_arch(x) \ ++ (elf_check_arch_ia32(x) || \ ++ (IS_ENABLED(CONFIG_X86_X32_ABI) && (x)->e_machine == EM_X86_64)) + + #if __USER32_DS != __USER_DS + # error "The following code assumes __USER32_DS == __USER_DS" +diff --git a/arch/x86/include/asm/iosf_mbi.h b/arch/x86/include/asm/iosf_mbi.h +index 8e71c7941767..57995f0596a6 100644 +--- a/arch/x86/include/asm/iosf_mbi.h ++++ b/arch/x86/include/asm/iosf_mbi.h +@@ -50,6 +50,32 @@ + #define BT_MBI_PCIE_READ 0x00 + #define BT_MBI_PCIE_WRITE 0x01 + ++/* Quark available units */ ++#define QRK_MBI_UNIT_HBA 0x00 ++#define QRK_MBI_UNIT_HB 0x03 ++#define QRK_MBI_UNIT_RMU 0x04 ++#define QRK_MBI_UNIT_MM 0x05 ++#define QRK_MBI_UNIT_MMESRAM 0x05 ++#define QRK_MBI_UNIT_SOC 0x31 ++ ++/* Quark read/write opcodes */ ++#define QRK_MBI_HBA_READ 0x10 ++#define QRK_MBI_HBA_WRITE 0x11 ++#define QRK_MBI_HB_READ 0x10 ++#define QRK_MBI_HB_WRITE 0x11 ++#define QRK_MBI_RMU_READ 0x10 ++#define QRK_MBI_RMU_WRITE 0x11 ++#define QRK_MBI_MM_READ 0x10 ++#define QRK_MBI_MM_WRITE 0x11 ++#define QRK_MBI_MMESRAM_READ 0x12 ++#define QRK_MBI_MMESRAM_WRITE 0x13 ++#define QRK_MBI_SOC_READ 0x06 ++#define QRK_MBI_SOC_WRITE 0x07 ++ ++#if IS_ENABLED(CONFIG_IOSF_MBI) ++ ++bool iosf_mbi_available(void); ++ + /** + * iosf_mbi_read() - MailBox Interface read command + * @port: port indicating subunit being accessed +@@ -87,4 +113,33 @@ int iosf_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr); + */ + int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask); + ++#else /* CONFIG_IOSF_MBI is not enabled */ ++static inline ++bool iosf_mbi_available(void) ++{ ++ return false; ++} ++ ++static inline ++int iosf_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr) ++{ ++ WARN(1, "IOSF_MBI driver not available"); ++ return -EPERM; ++} ++ ++static inline ++int iosf_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr) ++{ ++ WARN(1, "IOSF_MBI driver not available"); ++ return -EPERM; ++} ++ ++static inline ++int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask) ++{ ++ WARN(1, "IOSF_MBI driver not available"); ++ return -EPERM; ++} ++#endif /* CONFIG_IOSF_MBI */ ++ + #endif /* IOSF_MBI_SYMS_H */ +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index ac63ea4af5b0..e9dc02968cf8 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -984,6 +984,20 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code) + kvm_queue_exception_e(vcpu, GP_VECTOR, error_code); + } + ++static inline u64 get_canonical(u64 la) ++{ ++ return ((int64_t)la << 16) >> 16; ++} ++ ++static inline bool is_noncanonical_address(u64 la) ++{ ++#ifdef CONFIG_X86_64 ++ return get_canonical(la) != la; ++#else ++ return false; ++#endif ++} ++ + #define TSS_IOPB_BASE_OFFSET 0x66 + #define TSS_BASE_SIZE 0x68 + #define TSS_IOPB_SIZE (65536 / 8) +@@ -1042,7 +1056,7 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v); + void kvm_vcpu_reset(struct kvm_vcpu *vcpu); + + void kvm_define_shared_msr(unsigned index, u32 msr); +-void kvm_set_shared_msr(unsigned index, u64 val, u64 mask); ++int kvm_set_shared_msr(unsigned index, u64 val, u64 mask); + + bool kvm_is_linear_rip(struct kvm_vcpu *vcpu, unsigned long linear_rip); + +diff --git a/arch/x86/include/uapi/asm/vmx.h b/arch/x86/include/uapi/asm/vmx.h +index 0e79420376eb..990a2fe1588d 100644 +--- a/arch/x86/include/uapi/asm/vmx.h ++++ b/arch/x86/include/uapi/asm/vmx.h +@@ -67,6 +67,7 @@ + #define EXIT_REASON_EPT_MISCONFIG 49 + #define EXIT_REASON_INVEPT 50 + #define EXIT_REASON_PREEMPTION_TIMER 52 ++#define EXIT_REASON_INVVPID 53 + #define EXIT_REASON_WBINVD 54 + #define EXIT_REASON_XSETBV 55 + #define EXIT_REASON_APIC_WRITE 56 +@@ -114,6 +115,7 @@ + { EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, \ + { EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, \ + { EXIT_REASON_INVD, "INVD" }, \ ++ { EXIT_REASON_INVVPID, "INVVPID" }, \ + { EXIT_REASON_INVPCID, "INVPCID" } + + #endif /* _UAPIVMX_H */ +diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c +index 7f26c9a70a9e..523f147b2470 100644 +--- a/arch/x86/kernel/apic/apic.c ++++ b/arch/x86/kernel/apic/apic.c +@@ -1290,7 +1290,7 @@ void setup_local_APIC(void) + unsigned int value, queued; + int i, j, acked = 0; + unsigned long long tsc = 0, ntsc; +- long long max_loops = cpu_khz; ++ long long max_loops = cpu_khz ? cpu_khz : 1000000; + + if (cpu_has_tsc) + rdtscll(tsc); +@@ -1387,7 +1387,7 @@ void setup_local_APIC(void) + break; + } + if (queued) { +- if (cpu_has_tsc) { ++ if (cpu_has_tsc && cpu_khz) { + rdtscll(ntsc); + max_loops = (cpu_khz << 10) - (ntsc - tsc); + } else +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +index 8e28bf2fc3ef..3f27f5fd0847 100644 +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -1141,7 +1141,7 @@ void syscall_init(void) + /* Flags to clear on syscall */ + wrmsrl(MSR_SYSCALL_MASK, + X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF| +- X86_EFLAGS_IOPL|X86_EFLAGS_AC); ++ X86_EFLAGS_IOPL|X86_EFLAGS_AC|X86_EFLAGS_NT); + } + + /* +diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c +index c1a07d33e67e..66746a880dec 100644 +--- a/arch/x86/kernel/cpu/intel.c ++++ b/arch/x86/kernel/cpu/intel.c +@@ -383,6 +383,13 @@ static void init_intel(struct cpuinfo_x86 *c) + detect_extended_topology(c); + + l2 = init_intel_cacheinfo(c); ++ ++ /* Detect legacy cache sizes if init_intel_cacheinfo did not */ ++ if (l2 == 0) { ++ cpu_detect_cache_sizes(c); ++ l2 = c->x86_cache_size; ++ } ++ + if (c->cpuid_level > 9) { + unsigned eax = cpuid_eax(10); + /* Check for version and the number of counters */ +@@ -497,6 +504,13 @@ static unsigned int intel_size_cache(struct cpuinfo_x86 *c, unsigned int size) + */ + if ((c->x86 == 6) && (c->x86_model == 11) && (size == 0)) + size = 256; ++ ++ /* ++ * Intel Quark SoC X1000 contains a 4-way set associative ++ * 16K cache with a 16 byte cache line and 256 lines per tag ++ */ ++ if ((c->x86 == 5) && (c->x86_model == 9)) ++ size = 16; + return size; + } + #endif +@@ -724,7 +738,8 @@ static const struct cpu_dev intel_cpu_dev = { + [3] = "OverDrive PODP5V83", + [4] = "Pentium MMX", + [7] = "Mobile Pentium 75 - 200", +- [8] = "Mobile Pentium MMX" ++ [8] = "Mobile Pentium MMX", ++ [9] = "Quark SoC X1000", + } + }, + { .family = 6, .model_names = +diff --git a/arch/x86/kernel/iosf_mbi.c b/arch/x86/kernel/iosf_mbi.c +index c3aae6672843..2e97b3cfa6c7 100644 +--- a/arch/x86/kernel/iosf_mbi.c ++++ b/arch/x86/kernel/iosf_mbi.c +@@ -25,6 +25,10 @@ + + #include + ++#define PCI_DEVICE_ID_BAYTRAIL 0x0F00 ++#define PCI_DEVICE_ID_BRASWELL 0x2280 ++#define PCI_DEVICE_ID_QUARK_X1000 0x0958 ++ + static DEFINE_SPINLOCK(iosf_mbi_lock); + + static inline u32 iosf_mbi_form_mcr(u8 op, u8 port, u8 offset) +@@ -177,6 +181,13 @@ int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask) + } + EXPORT_SYMBOL(iosf_mbi_modify); + ++bool iosf_mbi_available(void) ++{ ++ /* Mbi isn't hot-pluggable. No remove routine is provided */ ++ return mbi_pdev; ++} ++EXPORT_SYMBOL(iosf_mbi_available); ++ + static int iosf_mbi_probe(struct pci_dev *pdev, + const struct pci_device_id *unused) + { +@@ -193,7 +204,9 @@ static int iosf_mbi_probe(struct pci_dev *pdev, + } + + static DEFINE_PCI_DEVICE_TABLE(iosf_mbi_pci_ids) = { +- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0F00) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_BAYTRAIL) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_BRASWELL) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_QUARK_X1000) }, + { 0, }, + }; + MODULE_DEVICE_TABLE(pci, iosf_mbi_pci_ids); +diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c +index 9e5de6813e1f..b88fc86309bc 100644 +--- a/arch/x86/kernel/signal.c ++++ b/arch/x86/kernel/signal.c +@@ -673,6 +673,11 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs) + * handler too. + */ + regs->flags &= ~(X86_EFLAGS_DF|X86_EFLAGS_RF|X86_EFLAGS_TF); ++ /* ++ * Ensure the signal handler starts with the new fpu state. ++ */ ++ if (used_math()) ++ drop_init_fpu(current); + } + signal_setup_done(failed, ksig, test_thread_flag(TIF_SINGLESTEP)); + } +diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c +index e0d1d7a8354e..de0290605903 100644 +--- a/arch/x86/kernel/tsc.c ++++ b/arch/x86/kernel/tsc.c +@@ -1173,14 +1173,17 @@ void __init tsc_init(void) + + x86_init.timers.tsc_pre_init(); + +- if (!cpu_has_tsc) ++ if (!cpu_has_tsc) { ++ setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER); + return; ++ } + + tsc_khz = x86_platform.calibrate_tsc(); + cpu_khz = tsc_khz; + + if (!tsc_khz) { + mark_tsc_unstable("could not calculate TSC khz"); ++ setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER); + return; + } + +diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c +index a4b451c6addf..dd50e26c58f6 100644 +--- a/arch/x86/kernel/xsave.c ++++ b/arch/x86/kernel/xsave.c +@@ -268,8 +268,6 @@ int save_xstate_sig(void __user *buf, void __user *buf_fx, int size) + if (use_fxsr() && save_xstate_epilog(buf_fx, ia32_fxstate)) + return -1; + +- drop_init_fpu(tsk); /* trigger finit */ +- + return 0; + } + +@@ -399,8 +397,11 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size) + set_used_math(); + } + +- if (use_eager_fpu()) ++ if (use_eager_fpu()) { ++ preempt_disable(); + math_state_restore(); ++ preempt_enable(); ++ } + + return err; + } else { +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index 7bff3e2a7a11..38d3751472e4 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -498,11 +498,6 @@ static void rsp_increment(struct x86_emulate_ctxt *ctxt, int inc) + masked_increment(reg_rmw(ctxt, VCPU_REGS_RSP), stack_mask(ctxt), inc); + } + +-static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel) +-{ +- register_address_increment(ctxt, &ctxt->_eip, rel); +-} +- + static u32 desc_limit_scaled(struct desc_struct *desc) + { + u32 limit = get_desc_limit(desc); +@@ -576,6 +571,38 @@ static int emulate_nm(struct x86_emulate_ctxt *ctxt) + return emulate_exception(ctxt, NM_VECTOR, 0, false); + } + ++static inline int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst, ++ int cs_l) ++{ ++ switch (ctxt->op_bytes) { ++ case 2: ++ ctxt->_eip = (u16)dst; ++ break; ++ case 4: ++ ctxt->_eip = (u32)dst; ++ break; ++ case 8: ++ if ((cs_l && is_noncanonical_address(dst)) || ++ (!cs_l && (dst & ~(u32)-1))) ++ return emulate_gp(ctxt, 0); ++ ctxt->_eip = dst; ++ break; ++ default: ++ WARN(1, "unsupported eip assignment size\n"); ++ } ++ return X86EMUL_CONTINUE; ++} ++ ++static inline int assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst) ++{ ++ return assign_eip_far(ctxt, dst, ctxt->mode == X86EMUL_MODE_PROT64); ++} ++ ++static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel) ++{ ++ return assign_eip_near(ctxt, ctxt->_eip + rel); ++} ++ + static u16 get_segment_selector(struct x86_emulate_ctxt *ctxt, unsigned seg) + { + u16 selector; +@@ -1958,13 +1985,15 @@ static int em_grp45(struct x86_emulate_ctxt *ctxt) + case 2: /* call near abs */ { + long int old_eip; + old_eip = ctxt->_eip; +- ctxt->_eip = ctxt->src.val; ++ rc = assign_eip_near(ctxt, ctxt->src.val); ++ if (rc != X86EMUL_CONTINUE) ++ break; + ctxt->src.val = old_eip; + rc = em_push(ctxt); + break; + } + case 4: /* jmp abs */ +- ctxt->_eip = ctxt->src.val; ++ rc = assign_eip_near(ctxt, ctxt->src.val); + break; + case 5: /* jmp far */ + rc = em_jmp_far(ctxt); +@@ -1996,10 +2025,14 @@ static int em_cmpxchg8b(struct x86_emulate_ctxt *ctxt) + + static int em_ret(struct x86_emulate_ctxt *ctxt) + { +- ctxt->dst.type = OP_REG; +- ctxt->dst.addr.reg = &ctxt->_eip; +- ctxt->dst.bytes = ctxt->op_bytes; +- return em_pop(ctxt); ++ int rc; ++ unsigned long eip; ++ ++ rc = emulate_pop(ctxt, &eip, ctxt->op_bytes); ++ if (rc != X86EMUL_CONTINUE) ++ return rc; ++ ++ return assign_eip_near(ctxt, eip); + } + + static int em_ret_far(struct x86_emulate_ctxt *ctxt) +@@ -2277,7 +2310,7 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt) + { + const struct x86_emulate_ops *ops = ctxt->ops; + struct desc_struct cs, ss; +- u64 msr_data; ++ u64 msr_data, rcx, rdx; + int usermode; + u16 cs_sel = 0, ss_sel = 0; + +@@ -2293,6 +2326,9 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt) + else + usermode = X86EMUL_MODE_PROT32; + ++ rcx = reg_read(ctxt, VCPU_REGS_RCX); ++ rdx = reg_read(ctxt, VCPU_REGS_RDX); ++ + cs.dpl = 3; + ss.dpl = 3; + ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data); +@@ -2310,6 +2346,9 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt) + ss_sel = cs_sel + 8; + cs.d = 0; + cs.l = 1; ++ if (is_noncanonical_address(rcx) || ++ is_noncanonical_address(rdx)) ++ return emulate_gp(ctxt, 0); + break; + } + cs_sel |= SELECTOR_RPL_MASK; +@@ -2318,8 +2357,8 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt) + ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS); + ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS); + +- ctxt->_eip = reg_read(ctxt, VCPU_REGS_RDX); +- *reg_write(ctxt, VCPU_REGS_RSP) = reg_read(ctxt, VCPU_REGS_RCX); ++ ctxt->_eip = rdx; ++ *reg_write(ctxt, VCPU_REGS_RSP) = rcx; + + return X86EMUL_CONTINUE; + } +@@ -2858,10 +2897,13 @@ static int em_aad(struct x86_emulate_ctxt *ctxt) + + static int em_call(struct x86_emulate_ctxt *ctxt) + { ++ int rc; + long rel = ctxt->src.val; + + ctxt->src.val = (unsigned long)ctxt->_eip; +- jmp_rel(ctxt, rel); ++ rc = jmp_rel(ctxt, rel); ++ if (rc != X86EMUL_CONTINUE) ++ return rc; + return em_push(ctxt); + } + +@@ -2893,11 +2935,12 @@ static int em_call_far(struct x86_emulate_ctxt *ctxt) + static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt) + { + int rc; ++ unsigned long eip; + +- ctxt->dst.type = OP_REG; +- ctxt->dst.addr.reg = &ctxt->_eip; +- ctxt->dst.bytes = ctxt->op_bytes; +- rc = emulate_pop(ctxt, &ctxt->dst.val, ctxt->op_bytes); ++ rc = emulate_pop(ctxt, &eip, ctxt->op_bytes); ++ if (rc != X86EMUL_CONTINUE) ++ return rc; ++ rc = assign_eip_near(ctxt, eip); + if (rc != X86EMUL_CONTINUE) + return rc; + rsp_increment(ctxt, ctxt->src.val); +@@ -3227,20 +3270,24 @@ static int em_lmsw(struct x86_emulate_ctxt *ctxt) + + static int em_loop(struct x86_emulate_ctxt *ctxt) + { ++ int rc = X86EMUL_CONTINUE; ++ + register_address_increment(ctxt, reg_rmw(ctxt, VCPU_REGS_RCX), -1); + if ((address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) != 0) && + (ctxt->b == 0xe2 || test_cc(ctxt->b ^ 0x5, ctxt->eflags))) +- jmp_rel(ctxt, ctxt->src.val); ++ rc = jmp_rel(ctxt, ctxt->src.val); + +- return X86EMUL_CONTINUE; ++ return rc; + } + + static int em_jcxz(struct x86_emulate_ctxt *ctxt) + { ++ int rc = X86EMUL_CONTINUE; ++ + if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0) +- jmp_rel(ctxt, ctxt->src.val); ++ rc = jmp_rel(ctxt, ctxt->src.val); + +- return X86EMUL_CONTINUE; ++ return rc; + } + + static int em_in(struct x86_emulate_ctxt *ctxt) +@@ -4637,7 +4684,7 @@ special_insn: + break; + case 0x70 ... 0x7f: /* jcc (short) */ + if (test_cc(ctxt->b, ctxt->eflags)) +- jmp_rel(ctxt, ctxt->src.val); ++ rc = jmp_rel(ctxt, ctxt->src.val); + break; + case 0x8d: /* lea r16/r32, m */ + ctxt->dst.val = ctxt->src.addr.mem.ea; +@@ -4666,7 +4713,7 @@ special_insn: + break; + case 0xe9: /* jmp rel */ + case 0xeb: /* jmp rel short */ +- jmp_rel(ctxt, ctxt->src.val); ++ rc = jmp_rel(ctxt, ctxt->src.val); + ctxt->dst.type = OP_NONE; /* Disable writeback. */ + break; + case 0xf4: /* hlt */ +@@ -4786,7 +4833,7 @@ twobyte_insn: + break; + case 0x80 ... 0x8f: /* jnz rel, etc*/ + if (test_cc(ctxt->b, ctxt->eflags)) +- jmp_rel(ctxt, ctxt->src.val); ++ rc = jmp_rel(ctxt, ctxt->src.val); + break; + case 0x90 ... 0x9f: /* setcc r/m8 */ + ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags); +diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c +index 518d86471b76..298781d4cfb4 100644 +--- a/arch/x86/kvm/i8254.c ++++ b/arch/x86/kvm/i8254.c +@@ -262,8 +262,10 @@ void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu) + return; + + timer = &pit->pit_state.timer; ++ mutex_lock(&pit->pit_state.lock); + if (hrtimer_cancel(timer)) + hrtimer_start_expires(timer, HRTIMER_MODE_ABS); ++ mutex_unlock(&pit->pit_state.lock); + } + + static void destroy_pit_timer(struct kvm_pit *pit) +diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c +index 2de1bc09a8d4..9643eda60a52 100644 +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -3213,7 +3213,7 @@ static int wrmsr_interception(struct vcpu_svm *svm) + msr.host_initiated = false; + + svm->next_rip = kvm_rip_read(&svm->vcpu) + 2; +- if (svm_set_msr(&svm->vcpu, &msr)) { ++ if (kvm_set_msr(&svm->vcpu, &msr)) { + trace_kvm_msr_write_ex(ecx, data); + kvm_inject_gp(&svm->vcpu, 0); + } else { +@@ -3495,9 +3495,9 @@ static int handle_exit(struct kvm_vcpu *vcpu) + + if (exit_code >= ARRAY_SIZE(svm_exit_handlers) + || !svm_exit_handlers[exit_code]) { +- kvm_run->exit_reason = KVM_EXIT_UNKNOWN; +- kvm_run->hw.hardware_exit_reason = exit_code; +- return 0; ++ WARN_ONCE(1, "vmx: unexpected exit reason 0x%x\n", exit_code); ++ kvm_queue_exception(vcpu, UD_VECTOR); ++ return 1; + } + + return svm_exit_handlers[exit_code](svm); +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 392752834751..0c90f4b3f835 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -2582,12 +2582,15 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) + default: + msr = find_msr_entry(vmx, msr_index); + if (msr) { ++ u64 old_msr_data = msr->data; + msr->data = data; + if (msr - vmx->guest_msrs < vmx->save_nmsrs) { + preempt_disable(); +- kvm_set_shared_msr(msr->index, msr->data, +- msr->mask); ++ ret = kvm_set_shared_msr(msr->index, msr->data, ++ msr->mask); + preempt_enable(); ++ if (ret) ++ msr->data = old_msr_data; + } + break; + } +@@ -5169,7 +5172,7 @@ static int handle_wrmsr(struct kvm_vcpu *vcpu) + msr.data = data; + msr.index = ecx; + msr.host_initiated = false; +- if (vmx_set_msr(vcpu, &msr) != 0) { ++ if (kvm_set_msr(vcpu, &msr) != 0) { + trace_kvm_msr_write_ex(ecx, data); + kvm_inject_gp(vcpu, 0); + return 1; +@@ -6441,6 +6444,12 @@ static int handle_invept(struct kvm_vcpu *vcpu) + return 1; + } + ++static int handle_invvpid(struct kvm_vcpu *vcpu) ++{ ++ kvm_queue_exception(vcpu, UD_VECTOR); ++ return 1; ++} ++ + /* + * The exit handlers return 1 if the exit was handled fully and guest execution + * may resume. Otherwise they set the kvm_run parameter to indicate what needs +@@ -6486,6 +6495,7 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = { + [EXIT_REASON_MWAIT_INSTRUCTION] = handle_invalid_op, + [EXIT_REASON_MONITOR_INSTRUCTION] = handle_invalid_op, + [EXIT_REASON_INVEPT] = handle_invept, ++ [EXIT_REASON_INVVPID] = handle_invvpid, + }; + + static const int kvm_vmx_max_exit_handlers = +@@ -6719,7 +6729,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu) + case EXIT_REASON_VMPTRST: case EXIT_REASON_VMREAD: + case EXIT_REASON_VMRESUME: case EXIT_REASON_VMWRITE: + case EXIT_REASON_VMOFF: case EXIT_REASON_VMON: +- case EXIT_REASON_INVEPT: ++ case EXIT_REASON_INVEPT: case EXIT_REASON_INVVPID: + /* + * VMX instructions trap unconditionally. This allows L1 to + * emulate them for its L2 guest, i.e., allows 3-level nesting! +@@ -6884,10 +6894,10 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu) + && kvm_vmx_exit_handlers[exit_reason]) + return kvm_vmx_exit_handlers[exit_reason](vcpu); + else { +- vcpu->run->exit_reason = KVM_EXIT_UNKNOWN; +- vcpu->run->hw.hardware_exit_reason = exit_reason; ++ WARN_ONCE(1, "vmx: unexpected exit reason 0x%x\n", exit_reason); ++ kvm_queue_exception(vcpu, UD_VECTOR); ++ return 1; + } +- return 0; + } + + static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr) +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 8fbd1a772272..51c2851ca243 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -225,20 +225,25 @@ static void kvm_shared_msr_cpu_online(void) + shared_msr_update(i, shared_msrs_global.msrs[i]); + } + +-void kvm_set_shared_msr(unsigned slot, u64 value, u64 mask) ++int kvm_set_shared_msr(unsigned slot, u64 value, u64 mask) + { + unsigned int cpu = smp_processor_id(); + struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu); ++ int err; + + if (((value ^ smsr->values[slot].curr) & mask) == 0) +- return; ++ return 0; + smsr->values[slot].curr = value; +- wrmsrl(shared_msrs_global.msrs[slot], value); ++ err = wrmsrl_safe(shared_msrs_global.msrs[slot], value); ++ if (err) ++ return 1; ++ + if (!smsr->registered) { + smsr->urn.on_user_return = kvm_on_user_return; + user_return_notifier_register(&smsr->urn); + smsr->registered = true; + } ++ return 0; + } + EXPORT_SYMBOL_GPL(kvm_set_shared_msr); + +@@ -946,7 +951,6 @@ void kvm_enable_efer_bits(u64 mask) + } + EXPORT_SYMBOL_GPL(kvm_enable_efer_bits); + +- + /* + * Writes msr value into into the appropriate "register". + * Returns 0 on success, non-0 otherwise. +@@ -954,8 +958,34 @@ EXPORT_SYMBOL_GPL(kvm_enable_efer_bits); + */ + int kvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) + { ++ switch (msr->index) { ++ case MSR_FS_BASE: ++ case MSR_GS_BASE: ++ case MSR_KERNEL_GS_BASE: ++ case MSR_CSTAR: ++ case MSR_LSTAR: ++ if (is_noncanonical_address(msr->data)) ++ return 1; ++ break; ++ case MSR_IA32_SYSENTER_EIP: ++ case MSR_IA32_SYSENTER_ESP: ++ /* ++ * IA32_SYSENTER_ESP and IA32_SYSENTER_EIP cause #GP if ++ * non-canonical address is written on Intel but not on ++ * AMD (which ignores the top 32-bits, because it does ++ * not implement 64-bit SYSENTER). ++ * ++ * 64-bit code should hence be able to write a non-canonical ++ * value on AMD. Making the address canonical ensures that ++ * vmentry does not fail on Intel after writing a non-canonical ++ * value, and that something deterministic happens if the guest ++ * invokes 64-bit SYSENTER. ++ */ ++ msr->data = get_canonical(msr->data); ++ } + return kvm_x86_ops->set_msr(vcpu, msr); + } ++EXPORT_SYMBOL_GPL(kvm_set_msr); + + /* + * Adapt set_msr() to msr_io()'s calling convention +diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c +index a3488689e301..fed892de9baf 100644 +--- a/arch/x86/mm/pageattr.c ++++ b/arch/x86/mm/pageattr.c +@@ -405,7 +405,7 @@ phys_addr_t slow_virt_to_phys(void *__virt_addr) + psize = page_level_size(level); + pmask = page_level_mask(level); + offset = virt_addr & ~pmask; +- phys_addr = pte_pfn(*pte) << PAGE_SHIFT; ++ phys_addr = (phys_addr_t)pte_pfn(*pte) << PAGE_SHIFT; + return (phys_addr | offset); + } + EXPORT_SYMBOL_GPL(slow_virt_to_phys); +diff --git a/block/blk-settings.c b/block/blk-settings.c +index 5d21239bc859..95138e9d0ad5 100644 +--- a/block/blk-settings.c ++++ b/block/blk-settings.c +@@ -553,7 +553,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, + bottom = max(b->physical_block_size, b->io_min) + alignment; + + /* Verify that top and bottom intervals line up */ +- if (max(top, bottom) & (min(top, bottom) - 1)) { ++ if (max(top, bottom) % min(top, bottom)) { + t->misaligned = 1; + ret = -1; + } +@@ -598,7 +598,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, + + /* Find lowest common alignment_offset */ + t->alignment_offset = lcm(t->alignment_offset, alignment) +- & (max(t->physical_block_size, t->io_min) - 1); ++ % max(t->physical_block_size, t->io_min); + + /* Verify that new alignment_offset is on a logical block boundary */ + if (t->alignment_offset & (t->logical_block_size - 1)) { +diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c +index 26487972ac54..4044cf789c7a 100644 +--- a/block/scsi_ioctl.c ++++ b/block/scsi_ioctl.c +@@ -489,7 +489,7 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode, + + if (bytes && blk_rq_map_kern(q, rq, buffer, bytes, __GFP_WAIT)) { + err = DRIVER_ERROR << 24; +- goto out; ++ goto error; + } + + memset(sense, 0, sizeof(sense)); +@@ -499,7 +499,6 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode, + + blk_execute_rq(q, disk, rq, 0); + +-out: + err = rq->errors & 0xff; /* only 8 bit SCSI status */ + if (err) { + if (rq->sense_len && rq->sense) { +diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c +index a19c027b29bd..83187f497c7c 100644 +--- a/crypto/algif_skcipher.c ++++ b/crypto/algif_skcipher.c +@@ -49,7 +49,7 @@ struct skcipher_ctx { + struct ablkcipher_request req; + }; + +-#define MAX_SGL_ENTS ((PAGE_SIZE - sizeof(struct skcipher_sg_list)) / \ ++#define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \ + sizeof(struct scatterlist) - 1) + + static inline int skcipher_sndbuf(struct sock *sk) +diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c +index b603720b877d..37acda6fa7e4 100644 +--- a/drivers/ata/libata-sff.c ++++ b/drivers/ata/libata-sff.c +@@ -2008,13 +2008,15 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask, + + DPRINTK("ata%u: bus reset via SRST\n", ap->print_id); + +- /* software reset. causes dev0 to be selected */ +- iowrite8(ap->ctl, ioaddr->ctl_addr); +- udelay(20); /* FIXME: flush */ +- iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr); +- udelay(20); /* FIXME: flush */ +- iowrite8(ap->ctl, ioaddr->ctl_addr); +- ap->last_ctl = ap->ctl; ++ if (ap->ioaddr.ctl_addr) { ++ /* software reset. causes dev0 to be selected */ ++ iowrite8(ap->ctl, ioaddr->ctl_addr); ++ udelay(20); /* FIXME: flush */ ++ iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr); ++ udelay(20); /* FIXME: flush */ ++ iowrite8(ap->ctl, ioaddr->ctl_addr); ++ ap->last_ctl = ap->ctl; ++ } + + /* wait the port to become ready */ + return ata_sff_wait_after_reset(&ap->link, devmask, deadline); +@@ -2215,10 +2217,6 @@ void ata_sff_error_handler(struct ata_port *ap) + + spin_unlock_irqrestore(ap->lock, flags); + +- /* ignore ata_sff_softreset if ctl isn't accessible */ +- if (softreset == ata_sff_softreset && !ap->ioaddr.ctl_addr) +- softreset = NULL; +- + /* ignore built-in hardresets if SCR access is not available */ + if ((hardreset == sata_std_hardreset || + hardreset == sata_sff_hardreset) && !sata_scr_valid(&ap->link)) +diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c +index 96c6a79ef606..79dedbae282c 100644 +--- a/drivers/ata/pata_serverworks.c ++++ b/drivers/ata/pata_serverworks.c +@@ -252,12 +252,18 @@ static void serverworks_set_dmamode(struct ata_port *ap, struct ata_device *adev + pci_write_config_byte(pdev, 0x54, ultra_cfg); + } + +-static struct scsi_host_template serverworks_sht = { ++static struct scsi_host_template serverworks_osb4_sht = { ++ ATA_BMDMA_SHT(DRV_NAME), ++ .sg_tablesize = LIBATA_DUMB_MAX_PRD, ++}; ++ ++static struct scsi_host_template serverworks_csb_sht = { + ATA_BMDMA_SHT(DRV_NAME), + }; + + static struct ata_port_operations serverworks_osb4_port_ops = { + .inherits = &ata_bmdma_port_ops, ++ .qc_prep = ata_bmdma_dumb_qc_prep, + .cable_detect = serverworks_cable_detect, + .mode_filter = serverworks_osb4_filter, + .set_piomode = serverworks_set_piomode, +@@ -266,6 +272,7 @@ static struct ata_port_operations serverworks_osb4_port_ops = { + + static struct ata_port_operations serverworks_csb_port_ops = { + .inherits = &serverworks_osb4_port_ops, ++ .qc_prep = ata_bmdma_qc_prep, + .mode_filter = serverworks_csb_filter, + }; + +@@ -405,6 +412,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id + } + }; + const struct ata_port_info *ppi[] = { &info[id->driver_data], NULL }; ++ struct scsi_host_template *sht = &serverworks_csb_sht; + int rc; + + rc = pcim_enable_device(pdev); +@@ -418,6 +426,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id + /* Select non UDMA capable OSB4 if we can't do fixups */ + if (rc < 0) + ppi[0] = &info[1]; ++ sht = &serverworks_osb4_sht; + } + /* setup CSB5/CSB6 : South Bridge and IDE option RAID */ + else if ((pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) || +@@ -434,7 +443,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id + ppi[1] = &ata_dummy_port_info; + } + +- return ata_pci_bmdma_init_one(pdev, ppi, &serverworks_sht, NULL, 0); ++ return ata_pci_bmdma_init_one(pdev, ppi, sht, NULL, 0); + } + + #ifdef CONFIG_PM +diff --git a/drivers/base/core.c b/drivers/base/core.c +index 2b567177ef78..6a8955e78610 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -741,12 +741,12 @@ class_dir_create_and_add(struct class *class, struct kobject *parent_kobj) + return &dir->kobj; + } + ++static DEFINE_MUTEX(gdp_mutex); + + static struct kobject *get_device_parent(struct device *dev, + struct device *parent) + { + if (dev->class) { +- static DEFINE_MUTEX(gdp_mutex); + struct kobject *kobj = NULL; + struct kobject *parent_kobj; + struct kobject *k; +@@ -810,7 +810,9 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir) + glue_dir->kset != &dev->class->p->glue_dirs) + return; + ++ mutex_lock(&gdp_mutex); + kobject_put(glue_dir); ++ mutex_unlock(&gdp_mutex); + } + + static void cleanup_device_parent(struct device *dev) +diff --git a/drivers/block/drbd/drbd_interval.c b/drivers/block/drbd/drbd_interval.c +index 89c497c630b4..04a14e0f8878 100644 +--- a/drivers/block/drbd/drbd_interval.c ++++ b/drivers/block/drbd/drbd_interval.c +@@ -79,6 +79,7 @@ bool + drbd_insert_interval(struct rb_root *root, struct drbd_interval *this) + { + struct rb_node **new = &root->rb_node, *parent = NULL; ++ sector_t this_end = this->sector + (this->size >> 9); + + BUG_ON(!IS_ALIGNED(this->size, 512)); + +@@ -87,6 +88,8 @@ drbd_insert_interval(struct rb_root *root, struct drbd_interval *this) + rb_entry(*new, struct drbd_interval, rb); + + parent = *new; ++ if (here->end < this_end) ++ here->end = this_end; + if (this->sector < here->sector) + new = &(*new)->rb_left; + else if (this->sector > here->sector) +@@ -99,6 +102,7 @@ drbd_insert_interval(struct rb_root *root, struct drbd_interval *this) + return false; + } + ++ this->end = this_end; + rb_link_node(&this->rb, parent, new); + rb_insert_augmented(&this->rb, root, &augment_callbacks); + return true; +diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c +index 7296c7f074bd..255ca232ecc7 100644 +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -3217,7 +3217,7 @@ static int rbd_obj_read_sync(struct rbd_device *rbd_dev, + page_count = (u32) calc_pages_for(offset, length); + pages = ceph_alloc_page_vector(page_count, GFP_KERNEL); + if (IS_ERR(pages)) +- ret = PTR_ERR(pages); ++ return PTR_ERR(pages); + + ret = -ENOMEM; + obj_request = rbd_obj_request_create(object_name, offset, length, +diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c +index 64c60edcdfbc..63fc7f06a014 100644 +--- a/drivers/block/xen-blkback/blkback.c ++++ b/drivers/block/xen-blkback/blkback.c +@@ -763,6 +763,7 @@ again: + BUG_ON(new_map_idx >= segs_to_map); + if (unlikely(map[new_map_idx].status != 0)) { + pr_debug(DRV_PFX "invalid buffer -- could not remap it\n"); ++ put_free_pages(blkif, &pages[seg_idx]->page, 1); + pages[seg_idx]->handle = BLKBACK_INVALID_HANDLE; + ret |= 1; + goto next; +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 429b75bb60e8..8a64dbeae7b1 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -1063,8 +1063,8 @@ static void extract_buf(struct entropy_store *r, __u8 *out) + * pool while mixing, and hash one final time. + */ + sha_transform(hash.w, extract, workspace); +- memset(extract, 0, sizeof(extract)); +- memset(workspace, 0, sizeof(workspace)); ++ memzero_explicit(extract, sizeof(extract)); ++ memzero_explicit(workspace, sizeof(workspace)); + + /* + * In case the hash function has some recognizable output +@@ -1076,7 +1076,7 @@ static void extract_buf(struct entropy_store *r, __u8 *out) + hash.w[2] ^= rol32(hash.w[2], 16); + + memcpy(out, &hash, EXTRACT_SIZE); +- memset(&hash, 0, sizeof(hash)); ++ memzero_explicit(&hash, sizeof(hash)); + } + + static ssize_t extract_entropy(struct entropy_store *r, void *buf, +@@ -1124,7 +1124,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, + } + + /* Wipe data just returned from memory */ +- memset(tmp, 0, sizeof(tmp)); ++ memzero_explicit(tmp, sizeof(tmp)); + + return ret; + } +@@ -1162,7 +1162,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, + } + + /* Wipe data just returned from memory */ +- memset(tmp, 0, sizeof(tmp)); ++ memzero_explicit(tmp, sizeof(tmp)); + + return ret; + } +diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c +index 415923606164..4854f81d038b 100644 +--- a/drivers/cpufreq/cpufreq.c ++++ b/drivers/cpufreq/cpufreq.c +@@ -460,7 +460,18 @@ show_one(cpuinfo_max_freq, cpuinfo.max_freq); + show_one(cpuinfo_transition_latency, cpuinfo.transition_latency); + show_one(scaling_min_freq, min); + show_one(scaling_max_freq, max); +-show_one(scaling_cur_freq, cur); ++ ++static ssize_t show_scaling_cur_freq( ++ struct cpufreq_policy *policy, char *buf) ++{ ++ ssize_t ret; ++ ++ if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get) ++ ret = sprintf(buf, "%u\n", cpufreq_driver->get(policy->cpu)); ++ else ++ ret = sprintf(buf, "%u\n", policy->cur); ++ return ret; ++} + + static int cpufreq_set_policy(struct cpufreq_policy *policy, + struct cpufreq_policy *new_policy); +@@ -854,11 +865,11 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy, + if (ret) + goto err_out_kobj_put; + } +- if (has_target()) { +- ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); +- if (ret) +- goto err_out_kobj_put; +- } ++ ++ ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); ++ if (ret) ++ goto err_out_kobj_put; ++ + if (cpufreq_driver->bios_limit) { + ret = sysfs_create_file(&policy->kobj, &bios_limit.attr); + if (ret) +diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c +index ae52c777339d..533a509439ca 100644 +--- a/drivers/cpufreq/intel_pstate.c ++++ b/drivers/cpufreq/intel_pstate.c +@@ -55,6 +55,17 @@ static inline int32_t div_fp(int32_t x, int32_t y) + return div_s64((int64_t)x << FRAC_BITS, (int64_t)y); + } + ++static inline int ceiling_fp(int32_t x) ++{ ++ int mask, ret; ++ ++ ret = fp_toint(x); ++ mask = (1 << FRAC_BITS) - 1; ++ if (x & mask) ++ ret += 1; ++ return ret; ++} ++ + struct sample { + int32_t core_pct_busy; + u64 aperf; +@@ -67,6 +78,7 @@ struct pstate_data { + int current_pstate; + int min_pstate; + int max_pstate; ++ int scaling; + int turbo_pstate; + }; + +@@ -118,6 +130,7 @@ struct pstate_funcs { + int (*get_max)(void); + int (*get_min)(void); + int (*get_turbo)(void); ++ int (*get_scaling)(void); + void (*set)(struct cpudata*, int pstate); + void (*get_vid)(struct cpudata *); + }; +@@ -397,7 +410,7 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate) + cpudata->vid.ratio); + + vid_fp = clamp_t(int32_t, vid_fp, cpudata->vid.min, cpudata->vid.max); +- vid = fp_toint(vid_fp); ++ vid = ceiling_fp(vid_fp); + + if (pstate > cpudata->pstate.max_pstate) + vid = cpudata->vid.turbo; +@@ -407,6 +420,22 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate) + wrmsrl(MSR_IA32_PERF_CTL, val); + } + ++#define BYT_BCLK_FREQS 5 ++static int byt_freq_table[BYT_BCLK_FREQS] = { 833, 1000, 1333, 1167, 800}; ++ ++static int byt_get_scaling(void) ++{ ++ u64 value; ++ int i; ++ ++ rdmsrl(MSR_FSB_FREQ, value); ++ i = value & 0x3; ++ ++ BUG_ON(i > BYT_BCLK_FREQS); ++ ++ return byt_freq_table[i] * 100; ++} ++ + static void byt_get_vid(struct cpudata *cpudata) + { + u64 value; +@@ -451,6 +480,11 @@ static int core_get_turbo_pstate(void) + return ret; + } + ++static inline int core_get_scaling(void) ++{ ++ return 100000; ++} ++ + static void core_set_pstate(struct cpudata *cpudata, int pstate) + { + u64 val; +@@ -475,6 +509,7 @@ static struct cpu_defaults core_params = { + .get_max = core_get_max_pstate, + .get_min = core_get_min_pstate, + .get_turbo = core_get_turbo_pstate, ++ .get_scaling = core_get_scaling, + .set = core_set_pstate, + }, + }; +@@ -493,6 +528,7 @@ static struct cpu_defaults byt_params = { + .get_min = byt_get_min_pstate, + .get_turbo = byt_get_turbo_pstate, + .set = byt_set_pstate, ++ .get_scaling = byt_get_scaling, + .get_vid = byt_get_vid, + }, + }; +@@ -526,7 +562,7 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) + if (pstate == cpu->pstate.current_pstate) + return; + +- trace_cpu_frequency(pstate * 100000, cpu->cpu); ++ trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu); + + cpu->pstate.current_pstate = pstate; + +@@ -555,6 +591,7 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) + cpu->pstate.min_pstate = pstate_funcs.get_min(); + cpu->pstate.max_pstate = pstate_funcs.get_max(); + cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); ++ cpu->pstate.scaling = pstate_funcs.get_scaling(); + + if (pstate_funcs.get_vid) + pstate_funcs.get_vid(cpu); +@@ -574,7 +611,9 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu, + core_pct += 1; + + sample->freq = fp_toint( +- mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct)); ++ mul_fp(int_tofp( ++ cpu->pstate.max_pstate * cpu->pstate.scaling / 100), ++ core_pct)); + + sample->core_pct_busy = (int32_t)core_pct; + } +@@ -685,10 +724,14 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = { + ICPU(0x37, byt_params), + ICPU(0x3a, core_params), + ICPU(0x3c, core_params), ++ ICPU(0x3d, core_params), + ICPU(0x3e, core_params), + ICPU(0x3f, core_params), + ICPU(0x45, core_params), + ICPU(0x46, core_params), ++ ICPU(0x4c, byt_params), ++ ICPU(0x4f, core_params), ++ ICPU(0x56, core_params), + {} + }; + MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); +@@ -751,6 +794,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) { + limits.min_perf_pct = 100; + limits.min_perf = int_tofp(1); ++ limits.max_policy_pct = 100; + limits.max_perf_pct = 100; + limits.max_perf = int_tofp(1); + limits.no_turbo = limits.turbo_disabled; +@@ -812,12 +856,13 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy) + else + policy->policy = CPUFREQ_POLICY_POWERSAVE; + +- policy->min = cpu->pstate.min_pstate * 100000; +- policy->max = cpu->pstate.turbo_pstate * 100000; ++ policy->min = cpu->pstate.min_pstate * cpu->pstate.scaling; ++ policy->max = cpu->pstate.turbo_pstate * cpu->pstate.scaling; + + /* cpuinfo and default policy values */ +- policy->cpuinfo.min_freq = cpu->pstate.min_pstate * 100000; +- policy->cpuinfo.max_freq = cpu->pstate.turbo_pstate * 100000; ++ policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling; ++ policy->cpuinfo.max_freq = ++ cpu->pstate.turbo_pstate * cpu->pstate.scaling; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + cpumask_set_cpu(policy->cpu, policy->cpus); + +@@ -875,6 +920,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs) + pstate_funcs.get_max = funcs->get_max; + pstate_funcs.get_min = funcs->get_min; + pstate_funcs.get_turbo = funcs->get_turbo; ++ pstate_funcs.get_scaling = funcs->get_scaling; + pstate_funcs.set = funcs->set; + pstate_funcs.get_vid = funcs->get_vid; + } +diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c +index df6575f1430d..682288ced4ac 100644 +--- a/drivers/edac/cpc925_edac.c ++++ b/drivers/edac/cpc925_edac.c +@@ -562,7 +562,7 @@ static void cpc925_mc_check(struct mem_ctl_info *mci) + + if (apiexcp & UECC_EXCP_DETECTED) { + cpc925_mc_printk(mci, KERN_INFO, "DRAM UECC Fault\n"); +- edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, ++ edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, + pfn, offset, 0, + csrow, -1, -1, + mci->ctl_name, ""); +diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c +index 3cda79bc8b00..ece3aef16bb1 100644 +--- a/drivers/edac/e7xxx_edac.c ++++ b/drivers/edac/e7xxx_edac.c +@@ -226,7 +226,7 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) + static void process_ce_no_info(struct mem_ctl_info *mci) + { + edac_dbg(3, "\n"); +- edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, ++ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, + "e7xxx CE log register overflow", ""); + } + +diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c +index fa1326e5a4b0..ad76f10865c6 100644 +--- a/drivers/edac/i3200_edac.c ++++ b/drivers/edac/i3200_edac.c +@@ -242,11 +242,11 @@ static void i3200_process_error_info(struct mem_ctl_info *mci, + -1, -1, + "i3000 UE", ""); + } else if (log & I3200_ECCERRLOG_CE) { +- edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, ++ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, + 0, 0, eccerrlog_syndrome(log), + eccerrlog_row(channel, log), + -1, -1, +- "i3000 UE", ""); ++ "i3000 CE", ""); + } + } + } +diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c +index 3382f6344e42..4382343a7c60 100644 +--- a/drivers/edac/i82860_edac.c ++++ b/drivers/edac/i82860_edac.c +@@ -124,7 +124,7 @@ static int i82860_process_error_info(struct mem_ctl_info *mci, + dimm->location[0], dimm->location[1], -1, + "i82860 UE", ""); + else +- edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, ++ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, + info->eap, 0, info->derrsyn, + dimm->location[0], dimm->location[1], -1, + "i82860 CE", ""); +diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c +index cca063b11083..d2e56e95d886 100644 +--- a/drivers/gpu/drm/ast/ast_mode.c ++++ b/drivers/gpu/drm/ast/ast_mode.c +@@ -1012,8 +1012,8 @@ static u32 copy_cursor_image(u8 *src, u8 *dst, int width, int height) + srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0; + data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4); + data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); +- data32.b[2] = srcdata32[0].b[1] | (srcdata32[1].b[0] >> 4); +- data32.b[3] = srcdata32[0].b[3] | (srcdata32[1].b[2] >> 4); ++ data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4); ++ data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4); + + writel(data32.ul, dstxor); + csum += data32.ul; +diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c +index 08ce520f61a5..faa1f421f1b8 100644 +--- a/drivers/gpu/drm/cirrus/cirrus_drv.c ++++ b/drivers/gpu/drm/cirrus/cirrus_drv.c +@@ -32,6 +32,8 @@ static struct drm_driver driver; + static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { + { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, 0x1af4, 0x1100, 0, + 0, 0 }, ++ { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, PCI_VENDOR_ID_XEN, ++ 0x0001, 0, 0, 0 }, + {0,} + }; + +diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c +index fd98bec78816..c6d9777bdb45 100644 +--- a/drivers/gpu/drm/i915/intel_panel.c ++++ b/drivers/gpu/drm/i915/intel_panel.c +@@ -645,7 +645,7 @@ static void pch_enable_backlight(struct intel_connector *connector) + + cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); + if (cpu_ctl2 & BLM_PWM_ENABLE) { +- WARN(1, "cpu backlight already enabled\n"); ++ DRM_DEBUG_KMS("cpu backlight already enabled\n"); + cpu_ctl2 &= ~BLM_PWM_ENABLE; + I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); + } +@@ -693,7 +693,7 @@ static void i9xx_enable_backlight(struct intel_connector *connector) + + ctl = I915_READ(BLC_PWM_CTL); + if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) { +- WARN(1, "backlight already enabled\n"); ++ DRM_DEBUG_KMS("backlight already enabled\n"); + I915_WRITE(BLC_PWM_CTL, 0); + } + +@@ -724,7 +724,7 @@ static void i965_enable_backlight(struct intel_connector *connector) + + ctl2 = I915_READ(BLC_PWM_CTL2); + if (ctl2 & BLM_PWM_ENABLE) { +- WARN(1, "backlight already enabled\n"); ++ DRM_DEBUG_KMS("backlight already enabled\n"); + ctl2 &= ~BLM_PWM_ENABLE; + I915_WRITE(BLC_PWM_CTL2, ctl2); + } +@@ -758,7 +758,7 @@ static void vlv_enable_backlight(struct intel_connector *connector) + + ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe)); + if (ctl2 & BLM_PWM_ENABLE) { +- WARN(1, "backlight already enabled\n"); ++ DRM_DEBUG_KMS("backlight already enabled\n"); + ctl2 &= ~BLM_PWM_ENABLE; + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); + } +diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c +index 2d9b9d7a7992..f3edd2841f2d 100644 +--- a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c ++++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c +@@ -124,6 +124,7 @@ dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len, + struct dcb_output *outp) + { + u16 dcb = dcb_outp(bios, idx, ver, len); ++ memset(outp, 0x00, sizeof(*outp)); + if (dcb) { + if (*ver >= 0x20) { + u32 conn = nv_ro32(bios, dcb + 0x00); +diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c +index 798bde2e5881..c39c414c7751 100644 +--- a/drivers/gpu/drm/qxl/qxl_display.c ++++ b/drivers/gpu/drm/qxl/qxl_display.c +@@ -523,7 +523,6 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc, + struct qxl_framebuffer *qfb; + struct qxl_bo *bo, *old_bo = NULL; + struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); +- uint32_t width, height, base_offset; + bool recreate_primary = false; + int ret; + int surf_id; +@@ -553,9 +552,10 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc, + if (qcrtc->index == 0) + recreate_primary = true; + +- width = mode->hdisplay; +- height = mode->vdisplay; +- base_offset = 0; ++ if (bo->surf.stride * bo->surf.height > qdev->vram_size) { ++ DRM_ERROR("Mode doesn't fit in vram size (vgamem)"); ++ return -EINVAL; ++ } + + ret = qxl_bo_reserve(bo, false); + if (ret != 0) +@@ -569,10 +569,10 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc, + if (recreate_primary) { + qxl_io_destroy_primary(qdev); + qxl_io_log(qdev, +- "recreate primary: %dx%d (was %dx%d,%d,%d)\n", +- width, height, bo->surf.width, +- bo->surf.height, bo->surf.stride, bo->surf.format); +- qxl_io_create_primary(qdev, base_offset, bo); ++ "recreate primary: %dx%d,%d,%d\n", ++ bo->surf.width, bo->surf.height, ++ bo->surf.stride, bo->surf.format); ++ qxl_io_create_primary(qdev, 0, bo); + bo->is_primary = true; + surf_id = 0; + } else { +diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c +index 0a2f5b4bca43..879e62844b2b 100644 +--- a/drivers/gpu/drm/radeon/si_dpm.c ++++ b/drivers/gpu/drm/radeon/si_dpm.c +@@ -6200,7 +6200,7 @@ static void si_parse_pplib_clock_info(struct radeon_device *rdev, + if ((rps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) && + index == 0) { + /* XXX disable for A0 tahiti */ +- si_pi->ulv.supported = true; ++ si_pi->ulv.supported = false; + si_pi->ulv.pl = *pl; + si_pi->ulv.one_pcie_lane_in_ulv = false; + si_pi->ulv.volt_change_delay = SISLANDS_ULVVOLTAGECHANGEDELAY_DFLT; +diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c +index 0644429f8559..52b47115b5cb 100644 +--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c ++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c +@@ -84,6 +84,7 @@ static int modeset_init(struct drm_device *dev) + if ((priv->num_encoders == 0) || (priv->num_connectors == 0)) { + /* oh nos! */ + dev_err(dev->dev, "no encoders/connectors found\n"); ++ drm_mode_config_cleanup(dev); + return -ENXIO; + } + +@@ -178,33 +179,37 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) + dev->dev_private = priv; + + priv->wq = alloc_ordered_workqueue("tilcdc", 0); ++ if (!priv->wq) { ++ ret = -ENOMEM; ++ goto fail_free_priv; ++ } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev->dev, "failed to get memory resource\n"); + ret = -EINVAL; +- goto fail; ++ goto fail_free_wq; + } + + priv->mmio = ioremap_nocache(res->start, resource_size(res)); + if (!priv->mmio) { + dev_err(dev->dev, "failed to ioremap\n"); + ret = -ENOMEM; +- goto fail; ++ goto fail_free_wq; + } + + priv->clk = clk_get(dev->dev, "fck"); + if (IS_ERR(priv->clk)) { + dev_err(dev->dev, "failed to get functional clock\n"); + ret = -ENODEV; +- goto fail; ++ goto fail_iounmap; + } + + priv->disp_clk = clk_get(dev->dev, "dpll_disp_ck"); + if (IS_ERR(priv->clk)) { + dev_err(dev->dev, "failed to get display clock\n"); + ret = -ENODEV; +- goto fail; ++ goto fail_put_clk; + } + + #ifdef CONFIG_CPU_FREQ +@@ -214,7 +219,7 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) + CPUFREQ_TRANSITION_NOTIFIER); + if (ret) { + dev_err(dev->dev, "failed to register cpufreq notifier\n"); +- goto fail; ++ goto fail_put_disp_clk; + } + #endif + +@@ -259,13 +264,13 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) + ret = modeset_init(dev); + if (ret < 0) { + dev_err(dev->dev, "failed to initialize mode setting\n"); +- goto fail; ++ goto fail_cpufreq_unregister; + } + + ret = drm_vblank_init(dev, 1); + if (ret < 0) { + dev_err(dev->dev, "failed to initialize vblank\n"); +- goto fail; ++ goto fail_mode_config_cleanup; + } + + pm_runtime_get_sync(dev->dev); +@@ -273,7 +278,7 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) + pm_runtime_put_sync(dev->dev); + if (ret < 0) { + dev_err(dev->dev, "failed to install IRQ handler\n"); +- goto fail; ++ goto fail_vblank_cleanup; + } + + platform_set_drvdata(pdev, dev); +@@ -289,13 +294,48 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) + priv->fbdev = drm_fbdev_cma_init(dev, bpp, + dev->mode_config.num_crtc, + dev->mode_config.num_connector); ++ if (IS_ERR(priv->fbdev)) { ++ ret = PTR_ERR(priv->fbdev); ++ goto fail_irq_uninstall; ++ } + + drm_kms_helper_poll_init(dev); + + return 0; + +-fail: +- tilcdc_unload(dev); ++fail_irq_uninstall: ++ pm_runtime_get_sync(dev->dev); ++ drm_irq_uninstall(dev); ++ pm_runtime_put_sync(dev->dev); ++ ++fail_vblank_cleanup: ++ drm_vblank_cleanup(dev); ++ ++fail_mode_config_cleanup: ++ drm_mode_config_cleanup(dev); ++ ++fail_cpufreq_unregister: ++ pm_runtime_disable(dev->dev); ++#ifdef CONFIG_CPU_FREQ ++ cpufreq_unregister_notifier(&priv->freq_transition, ++ CPUFREQ_TRANSITION_NOTIFIER); ++fail_put_disp_clk: ++ clk_put(priv->disp_clk); ++#endif ++ ++fail_put_clk: ++ clk_put(priv->clk); ++ ++fail_iounmap: ++ iounmap(priv->mmio); ++ ++fail_free_wq: ++ flush_workqueue(priv->wq); ++ destroy_workqueue(priv->wq); ++ ++fail_free_priv: ++ dev->dev_private = NULL; ++ kfree(priv); + return ret; + } + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +index 0083cbf99edf..fb7c36e93fd4 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +@@ -688,7 +688,11 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) + goto out_err0; + } + +- if (unlikely(dev_priv->prim_bb_mem < dev_priv->vram_size)) ++ /* ++ * Limit back buffer size to VRAM size. Remove this once ++ * screen targets are implemented. ++ */ ++ if (dev_priv->prim_bb_mem > dev_priv->vram_size) + dev_priv->prim_bb_mem = dev_priv->vram_size; + + mutex_unlock(&dev_priv->hw_mutex); +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +index 8a650413dea5..c8f8ecf7b282 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +@@ -1954,6 +1954,14 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) + }; + int i; ++ u32 assumed_bpp = 2; ++ ++ /* ++ * If using screen objects, then assume 32-bpp because that's what the ++ * SVGA device is assuming ++ */ ++ if (dev_priv->sou_priv) ++ assumed_bpp = 4; + + /* Add preferred mode */ + { +@@ -1964,8 +1972,9 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector, + mode->vdisplay = du->pref_height; + vmw_guess_mode_timing(mode); + +- if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2, +- mode->vdisplay)) { ++ if (vmw_kms_validate_mode_vram(dev_priv, ++ mode->hdisplay * assumed_bpp, ++ mode->vdisplay)) { + drm_mode_probed_add(connector, mode); + } else { + drm_mode_destroy(dev, mode); +@@ -1987,7 +1996,8 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector, + bmode->vdisplay > max_height) + continue; + +- if (!vmw_kms_validate_mode_vram(dev_priv, bmode->hdisplay * 2, ++ if (!vmw_kms_validate_mode_vram(dev_priv, ++ bmode->hdisplay * assumed_bpp, + bmode->vdisplay)) + continue; + +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 6e12cd0317f6..91bc66b4b151 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -292,6 +292,11 @@ + #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7 0x73f7 + #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001 + ++#define USB_VENDOR_ID_ELAN 0x04f3 ++#define USB_DEVICE_ID_ELAN_TOUCHSCREEN 0x0089 ++#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B 0x009b ++#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F 0x016f ++ + #define USB_VENDOR_ID_ELECOM 0x056e + #define USB_DEVICE_ID_ELECOM_BM084 0x0061 + +diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c +index 44df131d390a..617c47f9ebe6 100644 +--- a/drivers/hid/usbhid/hid-core.c ++++ b/drivers/hid/usbhid/hid-core.c +@@ -82,7 +82,7 @@ static int hid_start_in(struct hid_device *hid) + struct usbhid_device *usbhid = hid->driver_data; + + spin_lock_irqsave(&usbhid->lock, flags); +- if (hid->open > 0 && ++ if ((hid->open > 0 || hid->quirks & HID_QUIRK_ALWAYS_POLL) && + !test_bit(HID_DISCONNECTED, &usbhid->iofl) && + !test_bit(HID_SUSPENDED, &usbhid->iofl) && + !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { +@@ -292,6 +292,8 @@ static void hid_irq_in(struct urb *urb) + case 0: /* success */ + usbhid_mark_busy(usbhid); + usbhid->retry_delay = 0; ++ if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open) ++ break; + hid_input_report(urb->context, HID_INPUT_REPORT, + urb->transfer_buffer, + urb->actual_length, 1); +@@ -734,8 +736,10 @@ void usbhid_close(struct hid_device *hid) + if (!--hid->open) { + spin_unlock_irq(&usbhid->lock); + hid_cancel_delayed_stuff(usbhid); +- usb_kill_urb(usbhid->urbin); +- usbhid->intf->needs_remote_wakeup = 0; ++ if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) { ++ usb_kill_urb(usbhid->urbin); ++ usbhid->intf->needs_remote_wakeup = 0; ++ } + } else { + spin_unlock_irq(&usbhid->lock); + } +@@ -1119,6 +1123,19 @@ static int usbhid_start(struct hid_device *hid) + + set_bit(HID_STARTED, &usbhid->iofl); + ++ if (hid->quirks & HID_QUIRK_ALWAYS_POLL) { ++ ret = usb_autopm_get_interface(usbhid->intf); ++ if (ret) ++ goto fail; ++ usbhid->intf->needs_remote_wakeup = 1; ++ ret = hid_start_in(hid); ++ if (ret) { ++ dev_err(&hid->dev, ++ "failed to start in urb: %d\n", ret); ++ } ++ usb_autopm_put_interface(usbhid->intf); ++ } ++ + /* Some keyboards don't work until their LEDs have been set. + * Since BIOSes do set the LEDs, it must be safe for any device + * that supports the keyboard boot protocol. +@@ -1151,6 +1168,9 @@ static void usbhid_stop(struct hid_device *hid) + if (WARN_ON(!usbhid)) + return; + ++ if (hid->quirks & HID_QUIRK_ALWAYS_POLL) ++ usbhid->intf->needs_remote_wakeup = 0; ++ + clear_bit(HID_STARTED, &usbhid->iofl); + spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */ + set_bit(HID_DISCONNECTED, &usbhid->iofl); +diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c +index 8e4ddb369883..deb364306636 100644 +--- a/drivers/hid/usbhid/hid-quirks.c ++++ b/drivers/hid/usbhid/hid-quirks.c +@@ -69,6 +69,9 @@ static const struct hid_blacklist { + { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, ++ { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN, HID_QUIRK_ALWAYS_POLL }, ++ { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B, HID_QUIRK_ALWAYS_POLL }, ++ { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F, HID_QUIRK_ALWAYS_POLL }, + { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, +diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c +index 11e9c7f9bf9b..8873d84e1d4f 100644 +--- a/drivers/i2c/busses/i2c-at91.c ++++ b/drivers/i2c/busses/i2c-at91.c +@@ -434,7 +434,7 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) + } + } + +- ret = wait_for_completion_io_timeout(&dev->cmd_complete, ++ ret = wait_for_completion_timeout(&dev->cmd_complete, + dev->adapter.timeout); + if (ret == 0) { + dev_err(dev->dev, "controller timed out\n"); +diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c +index 1665c8e4b62b..e18bc6782256 100644 +--- a/drivers/iio/common/st_sensors/st_sensors_buffer.c ++++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c +@@ -71,7 +71,7 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) + goto st_sensors_free_memory; + } + +- for (i = 0; i < n * num_data_channels; i++) { ++ for (i = 0; i < n * byte_for_channel; i++) { + if (i < n) + buf[i] = rx_array[i]; + else +diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h +index f1da362c3e65..8fca488fdc15 100644 +--- a/drivers/input/serio/i8042-x86ia64io.h ++++ b/drivers/input/serio/i8042-x86ia64io.h +@@ -101,6 +101,12 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { + }, + { + .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "X750LN"), ++ }, ++ }, ++ { ++ .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), + DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"), + DMI_MATCH(DMI_PRODUCT_VERSION, "8500"), +@@ -609,6 +615,22 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = { + }, + }, + { ++ /* Fujitsu A544 laptop */ ++ /* https://bugzilla.redhat.com/show_bug.cgi?id=1111138 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK A544"), ++ }, ++ }, ++ { ++ /* Fujitsu AH544 laptop */ ++ /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK AH544"), ++ }, ++ }, ++ { + /* Fujitsu U574 laptop */ + /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */ + .matches = { +diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c +index 0e722c103562..ca1621b49453 100644 +--- a/drivers/md/dm-bufio.c ++++ b/drivers/md/dm-bufio.c +@@ -465,6 +465,7 @@ static void __relink_lru(struct dm_buffer *b, int dirty) + c->n_buffers[dirty]++; + b->list_mode = dirty; + list_move(&b->lru_list, &c->lru[dirty]); ++ b->last_accessed = jiffies; + } + + /*---------------------------------------------------------------- +@@ -1485,9 +1486,9 @@ static long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan, + list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list) { + freed += __cleanup_old_buffer(b, gfp_mask, 0); + if (!--nr_to_scan) +- break; ++ return freed; ++ dm_bufio_cond_resched(); + } +- dm_bufio_cond_resched(); + } + return freed; + } +diff --git a/drivers/md/dm-log-userspace-transfer.c b/drivers/md/dm-log-userspace-transfer.c +index 08d9a207259a..c69d0b787746 100644 +--- a/drivers/md/dm-log-userspace-transfer.c ++++ b/drivers/md/dm-log-userspace-transfer.c +@@ -272,7 +272,7 @@ int dm_ulog_tfr_init(void) + + r = cn_add_callback(&ulog_cn_id, "dmlogusr", cn_ulog_callback); + if (r) { +- cn_del_callback(&ulog_cn_id); ++ kfree(prealloced_cn_msg); + return r; + } + +diff --git a/drivers/media/dvb-frontends/ds3000.c b/drivers/media/dvb-frontends/ds3000.c +index 1e344b033277..22e8c2032f6d 100644 +--- a/drivers/media/dvb-frontends/ds3000.c ++++ b/drivers/media/dvb-frontends/ds3000.c +@@ -864,6 +864,13 @@ struct dvb_frontend *ds3000_attach(const struct ds3000_config *config, + memcpy(&state->frontend.ops, &ds3000_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; ++ ++ /* ++ * Some devices like T480 starts with voltage on. Be sure ++ * to turn voltage off during init, as this can otherwise ++ * interfere with Unicable SCR systems. ++ */ ++ ds3000_set_voltage(&state->frontend, SEC_VOLTAGE_OFF); + return &state->frontend; + + error3: +diff --git a/drivers/media/i2c/tda7432.c b/drivers/media/i2c/tda7432.c +index 72af644fa051..cf93021a6500 100644 +--- a/drivers/media/i2c/tda7432.c ++++ b/drivers/media/i2c/tda7432.c +@@ -293,7 +293,7 @@ static int tda7432_s_ctrl(struct v4l2_ctrl *ctrl) + if (t->mute->val) { + lf |= TDA7432_MUTE; + lr |= TDA7432_MUTE; +- lf |= TDA7432_MUTE; ++ rf |= TDA7432_MUTE; + rr |= TDA7432_MUTE; + } + /* Mute & update balance*/ +diff --git a/drivers/media/tuners/m88ts2022.c b/drivers/media/tuners/m88ts2022.c +index 40c42dec721b..7a62097aa9ea 100644 +--- a/drivers/media/tuners/m88ts2022.c ++++ b/drivers/media/tuners/m88ts2022.c +@@ -314,7 +314,7 @@ static int m88ts2022_set_params(struct dvb_frontend *fe) + div_min = gdiv28 * 78 / 100; + div_max = clamp_val(div_max, 0U, 63U); + +- f_3db_hz = c->symbol_rate * 135UL / 200UL; ++ f_3db_hz = mult_frac(c->symbol_rate, 135, 200); + f_3db_hz += 2000000U + (frequency_offset_khz * 1000U); + f_3db_hz = clamp(f_3db_hz, 7000000U, 40000000U); + +diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c +index 4d97a76cc3b0..c1a3f8f95750 100644 +--- a/drivers/media/usb/em28xx/em28xx-cards.c ++++ b/drivers/media/usb/em28xx/em28xx-cards.c +@@ -2993,16 +2993,6 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, + } + } + +- if (dev->chip_id == CHIP_ID_EM2870 || +- dev->chip_id == CHIP_ID_EM2874 || +- dev->chip_id == CHIP_ID_EM28174 || +- dev->chip_id == CHIP_ID_EM28178) { +- /* Digital only device - don't load any alsa module */ +- dev->audio_mode.has_audio = false; +- dev->has_audio_class = false; +- dev->has_alsa_audio = false; +- } +- + if (chip_name != default_chip_name) + printk(KERN_INFO DRIVER_NAME + ": chip ID is %s\n", chip_name); +@@ -3272,7 +3262,6 @@ static int em28xx_usb_probe(struct usb_interface *interface, + dev->alt = -1; + dev->is_audio_only = has_audio && !(has_video || has_dvb); + dev->has_alsa_audio = has_audio; +- dev->audio_mode.has_audio = has_audio; + dev->has_video = has_video; + dev->ifnum = ifnum; + +diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c +index 898fb9bd88a2..97fd881a4e7b 100644 +--- a/drivers/media/usb/em28xx/em28xx-core.c ++++ b/drivers/media/usb/em28xx/em28xx-core.c +@@ -506,8 +506,18 @@ int em28xx_audio_setup(struct em28xx *dev) + int vid1, vid2, feat, cfg; + u32 vid; + +- if (!dev->audio_mode.has_audio) ++ if (dev->chip_id == CHIP_ID_EM2870 || ++ dev->chip_id == CHIP_ID_EM2874 || ++ dev->chip_id == CHIP_ID_EM28174 || ++ dev->chip_id == CHIP_ID_EM28178) { ++ /* Digital only device - don't load any alsa module */ ++ dev->audio_mode.has_audio = false; ++ dev->has_audio_class = false; ++ dev->has_alsa_audio = false; + return 0; ++ } ++ ++ dev->audio_mode.has_audio = true; + + /* See how this device is configured */ + cfg = em28xx_read_reg(dev, EM28XX_R00_CHIPCFG); +diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c +index c3c928937dcd..e24ee08e634e 100644 +--- a/drivers/media/usb/em28xx/em28xx-video.c ++++ b/drivers/media/usb/em28xx/em28xx-video.c +@@ -953,13 +953,16 @@ static int em28xx_stop_streaming(struct vb2_queue *vq) + } + + spin_lock_irqsave(&dev->slock, flags); ++ if (dev->usb_ctl.vid_buf != NULL) { ++ vb2_buffer_done(&dev->usb_ctl.vid_buf->vb, VB2_BUF_STATE_ERROR); ++ dev->usb_ctl.vid_buf = NULL; ++ } + while (!list_empty(&vidq->active)) { + struct em28xx_buffer *buf; + buf = list_entry(vidq->active.next, struct em28xx_buffer, list); + list_del(&buf->list); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + } +- dev->usb_ctl.vid_buf = NULL; + spin_unlock_irqrestore(&dev->slock, flags); + + return 0; +@@ -981,13 +984,16 @@ int em28xx_stop_vbi_streaming(struct vb2_queue *vq) + } + + spin_lock_irqsave(&dev->slock, flags); ++ if (dev->usb_ctl.vbi_buf != NULL) { ++ vb2_buffer_done(&dev->usb_ctl.vbi_buf->vb, VB2_BUF_STATE_ERROR); ++ dev->usb_ctl.vbi_buf = NULL; ++ } + while (!list_empty(&vbiq->active)) { + struct em28xx_buffer *buf; + buf = list_entry(vbiq->active.next, struct em28xx_buffer, list); + list_del(&buf->list); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + } +- dev->usb_ctl.vbi_buf = NULL; + spin_unlock_irqrestore(&dev->slock, flags); + + return 0; +diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c +index c3bb2502225b..753ad4cfc118 100644 +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -2210,6 +2210,15 @@ static struct usb_device_id uvc_ids[] = { + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_DEF }, ++ /* Dell XPS M1330 (OmniVision OV7670 webcam) */ ++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE ++ | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x05a9, ++ .idProduct = 0x7670, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = 1, ++ .bInterfaceProtocol = 0, ++ .driver_info = UVC_QUIRK_PROBE_DEF }, + /* Apple Built-In iSight */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, +diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c +index 433d6d77942e..c5521cec933b 100644 +--- a/drivers/media/v4l2-core/v4l2-common.c ++++ b/drivers/media/v4l2-core/v4l2-common.c +@@ -431,16 +431,13 @@ static unsigned int clamp_align(unsigned int x, unsigned int min, + /* Bits that must be zero to be aligned */ + unsigned int mask = ~((1 << align) - 1); + ++ /* Clamp to aligned min and max */ ++ x = clamp(x, (min + ~mask) & mask, max & mask); ++ + /* Round to nearest aligned value */ + if (align) + x = (x + (1 << (align - 1))) & mask; + +- /* Clamp to aligned value of min and max */ +- if (x < min) +- x = (min + ~mask) & mask; +- else if (x > max) +- x = max & mask; +- + return x; + } + +diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c +index 1d15735f9ef9..89b4c4216d0c 100644 +--- a/drivers/mfd/rtsx_pcr.c ++++ b/drivers/mfd/rtsx_pcr.c +@@ -1177,7 +1177,7 @@ static int rtsx_pci_probe(struct pci_dev *pcidev, + pcr->msi_en = msi_en; + if (pcr->msi_en) { + ret = pci_enable_msi(pcidev); +- if (ret < 0) ++ if (ret) + pcr->msi_en = false; + } + +diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c +index d4e860413bb5..e87a2485468f 100644 +--- a/drivers/mfd/ti_am335x_tscadc.c ++++ b/drivers/mfd/ti_am335x_tscadc.c +@@ -54,11 +54,11 @@ void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val) + unsigned long flags; + + spin_lock_irqsave(&tsadc->reg_lock, flags); +- tsadc->reg_se_cache = val; ++ tsadc->reg_se_cache |= val; + if (tsadc->adc_waiting) + wake_up(&tsadc->reg_se_wait); + else if (!tsadc->adc_in_use) +- tscadc_writel(tsadc, REG_SE, val); ++ tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); + + spin_unlock_irqrestore(&tsadc->reg_lock, flags); + } +@@ -97,6 +97,7 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc) + void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val) + { + spin_lock_irq(&tsadc->reg_lock); ++ tsadc->reg_se_cache |= val; + am335x_tscadc_need_adc(tsadc); + + tscadc_writel(tsadc, REG_SE, val); +diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c +index 7e1866175e7b..ca297d741207 100644 +--- a/drivers/mmc/host/rtsx_pci_sdmmc.c ++++ b/drivers/mmc/host/rtsx_pci_sdmmc.c +@@ -342,6 +342,13 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, + } + + if (rsp_type == SD_RSP_TYPE_R2) { ++ /* ++ * The controller offloads the last byte {CRC-7, end bit 1'b1} ++ * of response type R2. Assign dummy CRC, 0, and end bit to the ++ * byte(ptr[16], goes into the LSB of resp[3] later). ++ */ ++ ptr[16] = 1; ++ + for (i = 0; i < 4; i++) { + cmd->resp[i] = get_unaligned_be32(ptr + 1 + i * 4); + dev_dbg(sdmmc_dev(host), "cmd->resp[%d] = 0x%08x\n", +diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c +index 0955777b6c7e..19bfa0ad70c4 100644 +--- a/drivers/mmc/host/sdhci-pci.c ++++ b/drivers/mmc/host/sdhci-pci.c +@@ -103,6 +103,10 @@ static const struct sdhci_pci_fixes sdhci_cafe = { + SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, + }; + ++static const struct sdhci_pci_fixes sdhci_intel_qrk = { ++ .quirks = SDHCI_QUIRK_NO_HISPD_BIT, ++}; ++ + static int mrst_hc_probe_slot(struct sdhci_pci_slot *slot) + { + slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA; +@@ -733,6 +737,14 @@ static const struct pci_device_id pci_ids[] = { + + { + .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_QRK_SD, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_intel_qrk, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_MRST_SD0, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, +diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h +index 6d718719659e..c101477ef3be 100644 +--- a/drivers/mmc/host/sdhci-pci.h ++++ b/drivers/mmc/host/sdhci-pci.h +@@ -17,6 +17,7 @@ + #define PCI_DEVICE_ID_INTEL_CLV_SDIO2 0x08fb + #define PCI_DEVICE_ID_INTEL_CLV_EMMC0 0x08e5 + #define PCI_DEVICE_ID_INTEL_CLV_EMMC1 0x08e6 ++#define PCI_DEVICE_ID_INTEL_QRK_SD 0x08A7 + + /* + * PCI registers +diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c +index c5dad652614d..904b4517fc1e 100644 +--- a/drivers/mtd/ubi/fastmap.c ++++ b/drivers/mtd/ubi/fastmap.c +@@ -330,6 +330,7 @@ static int process_pool_aeb(struct ubi_device *ubi, struct ubi_attach_info *ai, + av = tmp_av; + else { + ubi_err("orphaned volume in fastmap pool!"); ++ kmem_cache_free(ai->aeb_slab_cache, new_aeb); + return UBI_BAD_FASTMAP; + } + +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index 494b888a6568..7e5c6a8b89e7 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -135,6 +135,7 @@ config MACVLAN + config MACVTAP + tristate "MAC-VLAN based tap driver" + depends on MACVLAN ++ depends on INET + help + This adds a specialized tap character device driver that is based + on the MAC-VLAN network interface, called macvtap. A macvtap device +@@ -205,6 +206,7 @@ config RIONET_RX_SIZE + + config TUN + tristate "Universal TUN/TAP device driver support" ++ depends on INET + select CRC32 + ---help--- + TUN/TAP provides packet reception and transmission for user space +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index 0c6adaaf898c..f30ceb17d5fc 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -16,6 +16,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -65,7 +66,7 @@ static struct cdev macvtap_cdev; + static const struct proto_ops macvtap_socket_ops; + + #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ +- NETIF_F_TSO6 | NETIF_F_UFO) ++ NETIF_F_TSO6) + #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO) + #define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG) + +@@ -569,7 +570,11 @@ static int macvtap_skb_from_vnet_hdr(struct sk_buff *skb, + gso_type = SKB_GSO_TCPV6; + break; + case VIRTIO_NET_HDR_GSO_UDP: ++ pr_warn_once("macvtap: %s: using disabled UFO feature; please fix this program\n", ++ current->comm); + gso_type = SKB_GSO_UDP; ++ if (skb->protocol == htons(ETH_P_IPV6)) ++ ipv6_proxy_select_ident(skb); + break; + default: + return -EINVAL; +@@ -614,8 +619,6 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, + vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; + else if (sinfo->gso_type & SKB_GSO_TCPV6) + vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; +- else if (sinfo->gso_type & SKB_GSO_UDP) +- vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP; + else + BUG(); + if (sinfo->gso_type & SKB_GSO_TCP_ECN) +@@ -950,9 +953,6 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg) + if (arg & TUN_F_TSO6) + feature_mask |= NETIF_F_TSO6; + } +- +- if (arg & TUN_F_UFO) +- feature_mask |= NETIF_F_UFO; + } + + /* tun/tap driver inverts the usage for TSO offloads, where +@@ -963,7 +963,7 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg) + * When user space turns off TSO, we turn off GSO/LRO so that + * user-space will not receive TSO frames. + */ +- if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO)) ++ if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6)) + features |= RX_OFFLOADS; + else + features &= ~RX_OFFLOADS; +@@ -1064,7 +1064,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, + case TUNSETOFFLOAD: + /* let the user check for future flags */ + if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | +- TUN_F_TSO_ECN | TUN_F_UFO)) ++ TUN_F_TSO_ECN)) + return -EINVAL; + + rtnl_lock(); +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 72ff14b811c6..5a1897d86e94 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -601,7 +601,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + if (file == ppp->owner) + ppp_shutdown_interface(ppp); + } +- if (atomic_long_read(&file->f_count) <= 2) { ++ if (atomic_long_read(&file->f_count) < 2) { + ppp_release(NULL, file); + err = 0; + } else +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index 26f8635b027d..2c8b1c21c452 100644 +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -65,6 +65,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -174,7 +175,7 @@ struct tun_struct { + struct net_device *dev; + netdev_features_t set_features; + #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ +- NETIF_F_TSO6|NETIF_F_UFO) ++ NETIF_F_TSO6) + + int vnet_hdr_sz; + int sndbuf; +@@ -1140,6 +1141,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + break; + } + ++ skb_reset_network_header(skb); ++ + if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) { + pr_debug("GSO!\n"); + switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { +@@ -1150,8 +1153,20 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; + break; + case VIRTIO_NET_HDR_GSO_UDP: ++ { ++ static bool warned; ++ ++ if (!warned) { ++ warned = true; ++ netdev_warn(tun->dev, ++ "%s: using disabled UFO feature; please fix this program\n", ++ current->comm); ++ } + skb_shinfo(skb)->gso_type = SKB_GSO_UDP; ++ if (skb->protocol == htons(ETH_P_IPV6)) ++ ipv6_proxy_select_ident(skb); + break; ++ } + default: + tun->dev->stats.rx_frame_errors++; + kfree_skb(skb); +@@ -1180,7 +1195,6 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; + } + +- skb_reset_network_header(skb); + skb_probe_transport_header(skb, 0); + + rxhash = skb_get_hash(skb); +@@ -1252,8 +1266,6 @@ static ssize_t tun_put_user(struct tun_struct *tun, + gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; + else if (sinfo->gso_type & SKB_GSO_TCPV6) + gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; +- else if (sinfo->gso_type & SKB_GSO_UDP) +- gso.gso_type = VIRTIO_NET_HDR_GSO_UDP; + else { + pr_err("unexpected GSO type: " + "0x%x, gso_size %d, hdr_len %d\n", +@@ -1783,11 +1795,6 @@ static int set_offload(struct tun_struct *tun, unsigned long arg) + features |= NETIF_F_TSO6; + arg &= ~(TUN_F_TSO4|TUN_F_TSO6); + } +- +- if (arg & TUN_F_UFO) { +- features |= NETIF_F_UFO; +- arg &= ~TUN_F_UFO; +- } + } + + /* This gives the user a way to test for new features in future by +diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c +index 054e59ca6946..8cee173eefb2 100644 +--- a/drivers/net/usb/ax88179_178a.c ++++ b/drivers/net/usb/ax88179_178a.c +@@ -696,6 +696,7 @@ static int ax88179_set_mac_addr(struct net_device *net, void *p) + { + struct usbnet *dev = netdev_priv(net); + struct sockaddr *addr = p; ++ int ret; + + if (netif_running(net)) + return -EBUSY; +@@ -705,8 +706,12 @@ static int ax88179_set_mac_addr(struct net_device *net, void *p) + memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); + + /* Set the MAC address */ +- return ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, ++ ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, + ETH_ALEN, net->dev_addr); ++ if (ret < 0) ++ return ret; ++ ++ return 0; + } + + static const struct net_device_ops ax88179_netdev_ops = { +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index 841b60831df1..07a3255fd3cc 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -496,8 +496,17 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; + break; + case VIRTIO_NET_HDR_GSO_UDP: ++ { ++ static bool warned; ++ ++ if (!warned) { ++ warned = true; ++ netdev_warn(dev, ++ "host using disabled UFO feature; please fix it\n"); ++ } + skb_shinfo(skb)->gso_type = SKB_GSO_UDP; + break; ++ } + case VIRTIO_NET_HDR_GSO_TCPV6: + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; + break; +@@ -836,8 +845,6 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) + hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; + else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) + hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; +- else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) +- hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_UDP; + else + BUG(); + if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN) +@@ -1657,7 +1664,7 @@ static int virtnet_probe(struct virtio_device *vdev) + dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; + + if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) { +- dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO ++ dev->hw_features |= NETIF_F_TSO + | NETIF_F_TSO_ECN | NETIF_F_TSO6; + } + /* Individual feature bits: what can host handle? */ +@@ -1667,11 +1674,9 @@ static int virtnet_probe(struct virtio_device *vdev) + dev->hw_features |= NETIF_F_TSO6; + if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN)) + dev->hw_features |= NETIF_F_TSO_ECN; +- if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO)) +- dev->hw_features |= NETIF_F_UFO; + + if (gso) +- dev->features |= dev->hw_features & (NETIF_F_ALL_TSO|NETIF_F_UFO); ++ dev->features |= dev->hw_features & NETIF_F_ALL_TSO; + /* (!csum && gso) case will be fixed by register_netdev() */ + } + if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM)) +@@ -1711,8 +1716,7 @@ static int virtnet_probe(struct virtio_device *vdev) + /* If we can receive ANY GSO packets, we must allocate large ones. */ + if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) || + virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) || +- virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN) || +- virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UFO)) ++ virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN)) + vi->big_packets = true; + + if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) +@@ -1903,9 +1907,9 @@ static struct virtio_device_id id_table[] = { + static unsigned int features[] = { + VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, + VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC, +- VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, ++ VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_TSO6, + VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, +- VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO, ++ VIRTIO_NET_F_GUEST_ECN, + VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, + VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, + VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, +diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c +index 9b40532041cb..0704a0402897 100644 +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -1447,9 +1447,6 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb) + if (!in6_dev) + goto out; + +- if (!pskb_may_pull(skb, skb->len)) +- goto out; +- + iphdr = ipv6_hdr(skb); + saddr = &iphdr->saddr; + daddr = &iphdr->daddr; +@@ -1770,6 +1767,8 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, + struct pcpu_sw_netstats *tx_stats, *rx_stats; + union vxlan_addr loopback; + union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip; ++ struct net_device *dev = skb->dev; ++ int len = skb->len; + + tx_stats = this_cpu_ptr(src_vxlan->dev->tstats); + rx_stats = this_cpu_ptr(dst_vxlan->dev->tstats); +@@ -1793,16 +1792,16 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, + + u64_stats_update_begin(&tx_stats->syncp); + tx_stats->tx_packets++; +- tx_stats->tx_bytes += skb->len; ++ tx_stats->tx_bytes += len; + u64_stats_update_end(&tx_stats->syncp); + + if (netif_rx(skb) == NET_RX_SUCCESS) { + u64_stats_update_begin(&rx_stats->syncp); + rx_stats->rx_packets++; +- rx_stats->rx_bytes += skb->len; ++ rx_stats->rx_bytes += len; + u64_stats_update_end(&rx_stats->syncp); + } else { +- skb->dev->stats.rx_dropped++; ++ dev->stats.rx_dropped++; + } + } + +@@ -1977,7 +1976,8 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) + return arp_reduce(dev, skb); + #if IS_ENABLED(CONFIG_IPV6) + else if (ntohs(eth->h_proto) == ETH_P_IPV6 && +- skb->len >= sizeof(struct ipv6hdr) + sizeof(struct nd_msg) && ++ pskb_may_pull(skb, sizeof(struct ipv6hdr) ++ + sizeof(struct nd_msg)) && + ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) { + struct nd_msg *msg; + +@@ -1986,6 +1986,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) + msg->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) + return neigh_reduce(dev, skb); + } ++ eth = eth_hdr(skb); + #endif + } + +diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c +index 2ca62af3f81b..76ee486039d7 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/tx.c ++++ b/drivers/net/wireless/iwlwifi/mvm/tx.c +@@ -173,14 +173,10 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, + + /* + * for data packets, rate info comes from the table inside the fw. This +- * table is controlled by LINK_QUALITY commands. Exclude ctrl port +- * frames like EAPOLs which should be treated as mgmt frames. This +- * avoids them being sent initially in high rates which increases the +- * chances for completion of the 4-Way handshake. ++ * table is controlled by LINK_QUALITY commands + */ + +- if (ieee80211_is_data(fc) && sta && +- !(info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) { ++ if (ieee80211_is_data(fc) && sta) { + tx_cmd->initial_rate_index = 0; + tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE); + return; +diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h +index 7cf6081a05a1..ebd5625d13f1 100644 +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -52,6 +52,7 @@ + * RF5592 2.4G/5G 2T2R + * RF3070 2.4G 1T1R + * RF5360 2.4G 1T1R ++ * RF5362 2.4G 1T1R + * RF5370 2.4G 1T1R + * RF5390 2.4G 1T1R + */ +@@ -72,6 +73,7 @@ + #define RF3070 0x3070 + #define RF3290 0x3290 + #define RF5360 0x5360 ++#define RF5362 0x5362 + #define RF5370 0x5370 + #define RF5372 0x5372 + #define RF5390 0x5390 +@@ -2145,7 +2147,7 @@ struct mac_iveiv_entry { + /* Bits [7-4] for RF3320 (RT3370/RT3390), on other chipsets reserved */ + #define RFCSR3_PA1_BIAS_CCK FIELD8(0x70) + #define RFCSR3_PA2_CASCODE_BIAS_CCKK FIELD8(0x80) +-/* Bits for RF3290/RF5360/RF5370/RF5372/RF5390/RF5392 */ ++/* Bits for RF3290/RF5360/RF5362/RF5370/RF5372/RF5390/RF5392 */ + #define RFCSR3_VCOCAL_EN FIELD8(0x80) + /* Bits for RF3050 */ + #define RFCSR3_BIT1 FIELD8(0x02) +diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c +index 41d4a8167dc3..4e16d4da9d82 100644 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -3142,6 +3142,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, + break; + case RF3070: + case RF5360: ++ case RF5362: + case RF5370: + case RF5372: + case RF5390: +@@ -3159,6 +3160,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, + rt2x00_rf(rt2x00dev, RF3290) || + rt2x00_rf(rt2x00dev, RF3322) || + rt2x00_rf(rt2x00dev, RF5360) || ++ rt2x00_rf(rt2x00dev, RF5362) || + rt2x00_rf(rt2x00dev, RF5370) || + rt2x00_rf(rt2x00dev, RF5372) || + rt2x00_rf(rt2x00dev, RF5390) || +@@ -4273,6 +4275,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev) + case RF3070: + case RF3290: + case RF5360: ++ case RF5362: + case RF5370: + case RF5372: + case RF5390: +@@ -7073,6 +7076,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) + case RF3320: + case RF3322: + case RF5360: ++ case RF5362: + case RF5370: + case RF5372: + case RF5390: +@@ -7529,6 +7533,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) + case RF3320: + case RF3322: + case RF5360: ++ case RF5362: + case RF5370: + case RF5372: + case RF5390: +@@ -7658,6 +7663,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) + case RF3070: + case RF3290: + case RF5360: ++ case RF5362: + case RF5370: + case RF5372: + case RF5390: +diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c +index caddc1b427a9..57d3967de32f 100644 +--- a/drivers/net/wireless/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/rt2x00/rt2800usb.c +@@ -1062,6 +1062,7 @@ static struct usb_device_id rt2800usb_device_table[] = { + /* Ovislink */ + { USB_DEVICE(0x1b75, 0x3071) }, + { USB_DEVICE(0x1b75, 0x3072) }, ++ { USB_DEVICE(0x1b75, 0xa200) }, + /* Para */ + { USB_DEVICE(0x20b8, 0x8888) }, + /* Pegatron */ +@@ -1235,6 +1236,8 @@ static struct usb_device_id rt2800usb_device_table[] = { + /* Arcadyan */ + { USB_DEVICE(0x043e, 0x7a12) }, + { USB_DEVICE(0x043e, 0x7a32) }, ++ /* ASUS */ ++ { USB_DEVICE(0x0b05, 0x17e8) }, + /* Azurewave */ + { USB_DEVICE(0x13d3, 0x3329) }, + { USB_DEVICE(0x13d3, 0x3365) }, +@@ -1271,6 +1274,7 @@ static struct usb_device_id rt2800usb_device_table[] = { + { USB_DEVICE(0x057c, 0x8501) }, + /* Buffalo */ + { USB_DEVICE(0x0411, 0x0241) }, ++ { USB_DEVICE(0x0411, 0x0253) }, + /* D-Link */ + { USB_DEVICE(0x2001, 0x3c1a) }, + { USB_DEVICE(0x2001, 0x3c21) }, +@@ -1361,6 +1365,7 @@ static struct usb_device_id rt2800usb_device_table[] = { + { USB_DEVICE(0x0df6, 0x0053) }, + { USB_DEVICE(0x0df6, 0x0069) }, + { USB_DEVICE(0x0df6, 0x006f) }, ++ { USB_DEVICE(0x0df6, 0x0078) }, + /* SMC */ + { USB_DEVICE(0x083a, 0xa512) }, + { USB_DEVICE(0x083a, 0xc522) }, +diff --git a/drivers/of/base.c b/drivers/of/base.c +index 89e888a78899..3935614274eb 100644 +--- a/drivers/of/base.c ++++ b/drivers/of/base.c +@@ -1117,52 +1117,6 @@ int of_property_read_string(struct device_node *np, const char *propname, + EXPORT_SYMBOL_GPL(of_property_read_string); + + /** +- * of_property_read_string_index - Find and read a string from a multiple +- * strings property. +- * @np: device node from which the property value is to be read. +- * @propname: name of the property to be searched. +- * @index: index of the string in the list of strings +- * @out_string: pointer to null terminated return string, modified only if +- * return value is 0. +- * +- * Search for a property in a device tree node and retrieve a null +- * terminated string value (pointer to data, not a copy) in the list of strings +- * contained in that property. +- * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if +- * property does not have a value, and -EILSEQ if the string is not +- * null-terminated within the length of the property data. +- * +- * The out_string pointer is modified only if a valid string can be decoded. +- */ +-int of_property_read_string_index(struct device_node *np, const char *propname, +- int index, const char **output) +-{ +- struct property *prop = of_find_property(np, propname, NULL); +- int i = 0; +- size_t l = 0, total = 0; +- const char *p; +- +- if (!prop) +- return -EINVAL; +- if (!prop->value) +- return -ENODATA; +- if (strnlen(prop->value, prop->length) >= prop->length) +- return -EILSEQ; +- +- p = prop->value; +- +- for (i = 0; total < prop->length; total += l, p += l) { +- l = strlen(p) + 1; +- if (i++ == index) { +- *output = p; +- return 0; +- } +- } +- return -ENODATA; +-} +-EXPORT_SYMBOL_GPL(of_property_read_string_index); +- +-/** + * of_property_match_string() - Find string in a list and return index + * @np: pointer to node containing string list property + * @propname: string list property name +@@ -1188,7 +1142,7 @@ int of_property_match_string(struct device_node *np, const char *propname, + end = p + prop->length; + + for (i = 0; p < end; i++, p += l) { +- l = strlen(p) + 1; ++ l = strnlen(p, end - p) + 1; + if (p + l > end) + return -EILSEQ; + pr_debug("comparing %s with %s\n", string, p); +@@ -1200,39 +1154,41 @@ int of_property_match_string(struct device_node *np, const char *propname, + EXPORT_SYMBOL_GPL(of_property_match_string); + + /** +- * of_property_count_strings - Find and return the number of strings from a +- * multiple strings property. ++ * of_property_read_string_util() - Utility helper for parsing string properties + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. ++ * @out_strs: output array of string pointers. ++ * @sz: number of array elements to read. ++ * @skip: Number of strings to skip over at beginning of list. + * +- * Search for a property in a device tree node and retrieve the number of null +- * terminated string contain in it. Returns the number of strings on +- * success, -EINVAL if the property does not exist, -ENODATA if property +- * does not have a value, and -EILSEQ if the string is not null-terminated +- * within the length of the property data. ++ * Don't call this function directly. It is a utility helper for the ++ * of_property_read_string*() family of functions. + */ +-int of_property_count_strings(struct device_node *np, const char *propname) ++int of_property_read_string_helper(struct device_node *np, const char *propname, ++ const char **out_strs, size_t sz, int skip) + { + struct property *prop = of_find_property(np, propname, NULL); +- int i = 0; +- size_t l = 0, total = 0; +- const char *p; ++ int l = 0, i = 0; ++ const char *p, *end; + + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; +- if (strnlen(prop->value, prop->length) >= prop->length) +- return -EILSEQ; +- + p = prop->value; ++ end = p + prop->length; + +- for (i = 0; total < prop->length; total += l, p += l, i++) +- l = strlen(p) + 1; +- +- return i; ++ for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) { ++ l = strnlen(p, end - p) + 1; ++ if (p + l > end) ++ return -EILSEQ; ++ if (out_strs && i >= skip) ++ *out_strs++ = p; ++ } ++ i -= skip; ++ return i <= 0 ? -ENODATA : i; + } +-EXPORT_SYMBOL_GPL(of_property_count_strings); ++EXPORT_SYMBOL_GPL(of_property_read_string_helper); + + void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) + { +diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c +index 6643d1920985..70c61d75b75e 100644 +--- a/drivers/of/selftest.c ++++ b/drivers/of/selftest.c +@@ -132,8 +132,9 @@ static void __init of_selftest_parse_phandle_with_args(void) + selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + } + +-static void __init of_selftest_property_match_string(void) ++static void __init of_selftest_property_string(void) + { ++ const char *strings[4]; + struct device_node *np; + int rc; + +@@ -150,13 +151,66 @@ static void __init of_selftest_property_match_string(void) + rc = of_property_match_string(np, "phandle-list-names", "third"); + selftest(rc == 2, "third expected:0 got:%i\n", rc); + rc = of_property_match_string(np, "phandle-list-names", "fourth"); +- selftest(rc == -ENODATA, "unmatched string; rc=%i", rc); ++ selftest(rc == -ENODATA, "unmatched string; rc=%i\n", rc); + rc = of_property_match_string(np, "missing-property", "blah"); +- selftest(rc == -EINVAL, "missing property; rc=%i", rc); ++ selftest(rc == -EINVAL, "missing property; rc=%i\n", rc); + rc = of_property_match_string(np, "empty-property", "blah"); +- selftest(rc == -ENODATA, "empty property; rc=%i", rc); ++ selftest(rc == -ENODATA, "empty property; rc=%i\n", rc); + rc = of_property_match_string(np, "unterminated-string", "blah"); +- selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc); ++ selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc); ++ ++ /* of_property_count_strings() tests */ ++ rc = of_property_count_strings(np, "string-property"); ++ selftest(rc == 1, "Incorrect string count; rc=%i\n", rc); ++ rc = of_property_count_strings(np, "phandle-list-names"); ++ selftest(rc == 3, "Incorrect string count; rc=%i\n", rc); ++ rc = of_property_count_strings(np, "unterminated-string"); ++ selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc); ++ rc = of_property_count_strings(np, "unterminated-string-list"); ++ selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc); ++ ++ /* of_property_read_string_index() tests */ ++ rc = of_property_read_string_index(np, "string-property", 0, strings); ++ selftest(rc == 0 && !strcmp(strings[0], "foobar"), "of_property_read_string_index() failure; rc=%i\n", rc); ++ strings[0] = NULL; ++ rc = of_property_read_string_index(np, "string-property", 1, strings); ++ selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); ++ rc = of_property_read_string_index(np, "phandle-list-names", 0, strings); ++ selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc); ++ rc = of_property_read_string_index(np, "phandle-list-names", 1, strings); ++ selftest(rc == 0 && !strcmp(strings[0], "second"), "of_property_read_string_index() failure; rc=%i\n", rc); ++ rc = of_property_read_string_index(np, "phandle-list-names", 2, strings); ++ selftest(rc == 0 && !strcmp(strings[0], "third"), "of_property_read_string_index() failure; rc=%i\n", rc); ++ strings[0] = NULL; ++ rc = of_property_read_string_index(np, "phandle-list-names", 3, strings); ++ selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); ++ strings[0] = NULL; ++ rc = of_property_read_string_index(np, "unterminated-string", 0, strings); ++ selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); ++ rc = of_property_read_string_index(np, "unterminated-string-list", 0, strings); ++ selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc); ++ strings[0] = NULL; ++ rc = of_property_read_string_index(np, "unterminated-string-list", 2, strings); /* should fail */ ++ selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); ++ strings[1] = NULL; ++ ++ /* of_property_read_string_array() tests */ ++ rc = of_property_read_string_array(np, "string-property", strings, 4); ++ selftest(rc == 1, "Incorrect string count; rc=%i\n", rc); ++ rc = of_property_read_string_array(np, "phandle-list-names", strings, 4); ++ selftest(rc == 3, "Incorrect string count; rc=%i\n", rc); ++ rc = of_property_read_string_array(np, "unterminated-string", strings, 4); ++ selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc); ++ /* -- An incorrectly formed string should cause a failure */ ++ rc = of_property_read_string_array(np, "unterminated-string-list", strings, 4); ++ selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc); ++ /* -- parsing the correctly formed strings should still work: */ ++ strings[2] = NULL; ++ rc = of_property_read_string_array(np, "unterminated-string-list", strings, 2); ++ selftest(rc == 2 && strings[2] == NULL, "of_property_read_string_array() failure; rc=%i\n", rc); ++ strings[1] = NULL; ++ rc = of_property_read_string_array(np, "phandle-list-names", strings, 1); ++ selftest(rc == 1 && strings[1] == NULL, "Overwrote end of string array; rc=%i, str='%s'\n", rc, strings[1]); + } + + static void __init of_selftest_parse_interrupts(void) +@@ -379,7 +433,7 @@ static int __init of_selftest(void) + + pr_info("start of selftest - you will see error messages\n"); + of_selftest_parse_phandle_with_args(); +- of_selftest_property_match_string(); ++ of_selftest_property_string(); + of_selftest_parse_interrupts(); + of_selftest_parse_interrupts_extended(); + of_selftest_match_node(); +diff --git a/drivers/of/testcase-data/tests-phandle.dtsi b/drivers/of/testcase-data/tests-phandle.dtsi +index 0007d3cd7dc2..eedee37d70d7 100644 +--- a/drivers/of/testcase-data/tests-phandle.dtsi ++++ b/drivers/of/testcase-data/tests-phandle.dtsi +@@ -32,7 +32,9 @@ + phandle-list-bad-args = <&provider2 1 0>, + <&provider3 0>; + empty-property; ++ string-property = "foobar"; + unterminated-string = [40 41 42 43]; ++ unterminated-string-list = "first", "second", [40 41 42 43]; + }; + }; + }; +diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c +index 39a207abaa10..a943c6c0f206 100644 +--- a/drivers/pci/pci-sysfs.c ++++ b/drivers/pci/pci-sysfs.c +@@ -186,9 +186,9 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + } + static DEVICE_ATTR_RO(modalias); + +-static ssize_t enabled_store(struct device *dev, +- struct device_attribute *attr, const char *buf, +- size_t count) ++static ssize_t enable_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, ++ size_t count) + { + struct pci_dev *pdev = to_pci_dev(dev); + unsigned long val; +@@ -212,15 +212,15 @@ static ssize_t enabled_store(struct device *dev, + return result < 0 ? result : count; + } + +-static ssize_t enabled_show(struct device *dev, +- struct device_attribute *attr, char *buf) ++static ssize_t enable_show(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + struct pci_dev *pdev; + + pdev = to_pci_dev (dev); + return sprintf (buf, "%u\n", atomic_read(&pdev->enable_cnt)); + } +-static DEVICE_ATTR_RW(enabled); ++static DEVICE_ATTR_RW(enable); + + #ifdef CONFIG_NUMA + static ssize_t +@@ -526,7 +526,7 @@ static struct attribute *pci_dev_attrs[] = { + #endif + &dev_attr_dma_mask_bits.attr, + &dev_attr_consistent_dma_mask_bits.attr, +- &dev_attr_enabled.attr, ++ &dev_attr_enable.attr, + &dev_attr_broken_parity_status.attr, + &dev_attr_msi_bus.attr, + #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI) +diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c +index 665b96bc0c3a..eb9f1906952a 100644 +--- a/drivers/pinctrl/pinctrl-baytrail.c ++++ b/drivers/pinctrl/pinctrl-baytrail.c +@@ -263,7 +263,7 @@ static int byt_gpio_direction_output(struct gpio_chip *chip, + spin_lock_irqsave(&vg->lock, flags); + + reg_val = readl(reg) | BYT_DIR_MASK; +- reg_val &= ~BYT_OUTPUT_EN; ++ reg_val &= ~(BYT_OUTPUT_EN | BYT_INPUT_EN); + + if (value) + writel(reg_val | BYT_LEVEL, reg); +diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c +index c91f69b39db4..dcfcaea76048 100644 +--- a/drivers/platform/x86/acer-wmi.c ++++ b/drivers/platform/x86/acer-wmi.c +@@ -570,6 +570,17 @@ static const struct dmi_system_id video_vendor_dmi_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"), + }, + }, ++ { ++ /* ++ * Note no video_set_backlight_video_vendor, we must use the ++ * acer interface, as there is no native backlight interface. ++ */ ++ .ident = "Acer KAV80", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Acer"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "KAV80"), ++ }, ++ }, + {} + }; + +diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c +index 9e4dab46eefd..ef1f4c928431 100644 +--- a/drivers/power/charger-manager.c ++++ b/drivers/power/charger-manager.c +@@ -1720,6 +1720,11 @@ static int charger_manager_probe(struct platform_device *pdev) + return -EINVAL; + } + ++ if (!desc->psy_fuel_gauge) { ++ dev_err(&pdev->dev, "No fuel gauge power supply defined\n"); ++ return -EINVAL; ++ } ++ + /* Counting index only */ + while (desc->psy_charger_stat[i]) + i++; +diff --git a/drivers/regulator/max77693.c b/drivers/regulator/max77693.c +index 5fb899f461d0..24c926bfe6d4 100644 +--- a/drivers/regulator/max77693.c ++++ b/drivers/regulator/max77693.c +@@ -232,7 +232,7 @@ static int max77693_pmic_probe(struct platform_device *pdev) + struct max77693_pmic_dev *max77693_pmic; + struct max77693_regulator_data *rdata = NULL; + int num_rdata, i; +- struct regulator_config config; ++ struct regulator_config config = { }; + + num_rdata = max77693_pmic_init_rdata(&pdev->dev, &rdata); + if (!rdata || num_rdata <= 0) { +diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c +index 788c4fe2b0c9..9d81f7693f99 100644 +--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c ++++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c +@@ -707,7 +707,16 @@ static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess) + pr_debug("fc_rport domain: port_id 0x%06x\n", nacl->nport_id); + + node = btree_remove32(&lport->lport_fcport_map, nacl->nport_id); +- WARN_ON(node && (node != se_nacl)); ++ if (WARN_ON(node && (node != se_nacl))) { ++ /* ++ * The nacl no longer matches what we think it should be. ++ * Most likely a new dynamic acl has been added while ++ * someone dropped the hardware lock. It clearly is a ++ * bug elsewhere, but this bit can't make things worse. ++ */ ++ btree_insert32(&lport->lport_fcport_map, nacl->nport_id, ++ node, GFP_ATOMIC); ++ } + + pr_debug("Removed from fcport_map: %p for WWNN: 0x%016LX, port_id: 0x%06x\n", + se_nacl, nacl->nport_wwnn, nacl->nport_id); +diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c +index a25392065d9b..a5db6f930fa3 100644 +--- a/drivers/spi/spi-fsl-dspi.c ++++ b/drivers/spi/spi-fsl-dspi.c +@@ -45,7 +45,7 @@ + + #define SPI_TCR 0x08 + +-#define SPI_CTAR(x) (0x0c + (x * 4)) ++#define SPI_CTAR(x) (0x0c + (((x) & 0x3) * 4)) + #define SPI_CTAR_FMSZ(x) (((x) & 0x0000000f) << 27) + #define SPI_CTAR_CPOL(x) ((x) << 26) + #define SPI_CTAR_CPHA(x) ((x) << 25) +@@ -69,7 +69,7 @@ + + #define SPI_PUSHR 0x34 + #define SPI_PUSHR_CONT (1 << 31) +-#define SPI_PUSHR_CTAS(x) (((x) & 0x00000007) << 28) ++#define SPI_PUSHR_CTAS(x) (((x) & 0x00000003) << 28) + #define SPI_PUSHR_EOQ (1 << 27) + #define SPI_PUSHR_CTCNT (1 << 26) + #define SPI_PUSHR_PCS(x) (((1 << x) & 0x0000003f) << 16) +diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c +index 2789b452e711..971855e859c7 100644 +--- a/drivers/spi/spi-pl022.c ++++ b/drivers/spi/spi-pl022.c +@@ -1075,7 +1075,7 @@ err_rxdesc: + pl022->sgt_tx.nents, DMA_TO_DEVICE); + err_tx_sgmap: + dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl, +- pl022->sgt_tx.nents, DMA_FROM_DEVICE); ++ pl022->sgt_rx.nents, DMA_FROM_DEVICE); + err_rx_sgmap: + sg_free_table(&pl022->sgt_tx); + err_alloc_tx_sg: +diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c +index ced9ecffa163..7ab3ccb592eb 100644 +--- a/drivers/spi/spi-pxa2xx.c ++++ b/drivers/spi/spi-pxa2xx.c +@@ -1280,7 +1280,9 @@ static int pxa2xx_spi_suspend(struct device *dev) + if (status != 0) + return status; + write_SSCR0(0, drv_data->ioaddr); +- clk_disable_unprepare(ssp->clk); ++ ++ if (!pm_runtime_suspended(dev)) ++ clk_disable_unprepare(ssp->clk); + + return 0; + } +@@ -1294,7 +1296,8 @@ static int pxa2xx_spi_resume(struct device *dev) + pxa2xx_spi_dma_resume(drv_data); + + /* Enable the SSP clock */ +- clk_prepare_enable(ssp->clk); ++ if (!pm_runtime_suspended(dev)) ++ clk_prepare_enable(ssp->clk); + + /* Restore LPSS private register bits */ + lpss_ssp_setup(drv_data); +diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c +index 2b96665da8a2..97d4b3fb7e95 100644 +--- a/drivers/staging/iio/impedance-analyzer/ad5933.c ++++ b/drivers/staging/iio/impedance-analyzer/ad5933.c +@@ -115,6 +115,7 @@ static const struct iio_chan_spec ad5933_channels[] = { + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .address = AD5933_REG_TEMP_DATA, ++ .scan_index = -1, + .scan_type = { + .sign = 's', + .realbits = 14, +@@ -124,9 +125,7 @@ static const struct iio_chan_spec ad5933_channels[] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, +- .extend_name = "real_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | +- BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "real", + .address = AD5933_REG_REAL_DATA, + .scan_index = 0, + .scan_type = { +@@ -138,9 +137,7 @@ static const struct iio_chan_spec ad5933_channels[] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, +- .extend_name = "imag_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | +- BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "imag", + .address = AD5933_REG_IMAG_DATA, + .scan_index = 1, + .scan_type = { +@@ -748,14 +745,14 @@ static int ad5933_probe(struct i2c_client *client, + indio_dev->name = id->name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ad5933_channels; +- indio_dev->num_channels = 1; /* only register temp0_input */ ++ indio_dev->num_channels = ARRAY_SIZE(ad5933_channels); + + ret = ad5933_register_ring_funcs_and_init(indio_dev); + if (ret) + goto error_disable_reg; + +- /* skip temp0_input, register in0_(real|imag)_raw */ +- ret = iio_buffer_register(indio_dev, &ad5933_channels[1], 2); ++ ret = iio_buffer_register(indio_dev, ad5933_channels, ++ ARRAY_SIZE(ad5933_channels)); + if (ret) + goto error_unreg_ring; + +diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h +index 07318203a836..e8c98cf57070 100644 +--- a/drivers/staging/iio/meter/ade7758.h ++++ b/drivers/staging/iio/meter/ade7758.h +@@ -119,7 +119,6 @@ struct ade7758_state { + u8 *tx; + u8 *rx; + struct mutex buf_lock; +- const struct iio_chan_spec *ade7758_ring_channels; + struct spi_transfer ring_xfer[4]; + struct spi_message ring_msg; + /* +diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c +index cba183e24838..94d9914a602c 100644 +--- a/drivers/staging/iio/meter/ade7758_core.c ++++ b/drivers/staging/iio/meter/ade7758_core.c +@@ -630,9 +630,6 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, +- .extend_name = "raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_A, AD7758_VOLTAGE), + .scan_index = 0, + .scan_type = { +@@ -644,9 +641,6 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_CURRENT, + .indexed = 1, + .channel = 0, +- .extend_name = "raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_A, AD7758_CURRENT), + .scan_index = 1, + .scan_type = { +@@ -658,9 +652,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 0, +- .extend_name = "apparent_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "apparent", + .address = AD7758_WT(AD7758_PHASE_A, AD7758_APP_PWR), + .scan_index = 2, + .scan_type = { +@@ -672,9 +664,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 0, +- .extend_name = "active_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "active", + .address = AD7758_WT(AD7758_PHASE_A, AD7758_ACT_PWR), + .scan_index = 3, + .scan_type = { +@@ -686,9 +676,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 0, +- .extend_name = "reactive_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "reactive", + .address = AD7758_WT(AD7758_PHASE_A, AD7758_REACT_PWR), + .scan_index = 4, + .scan_type = { +@@ -700,9 +688,6 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 1, +- .extend_name = "raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_B, AD7758_VOLTAGE), + .scan_index = 5, + .scan_type = { +@@ -714,9 +699,6 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_CURRENT, + .indexed = 1, + .channel = 1, +- .extend_name = "raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_B, AD7758_CURRENT), + .scan_index = 6, + .scan_type = { +@@ -728,9 +710,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 1, +- .extend_name = "apparent_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "apparent", + .address = AD7758_WT(AD7758_PHASE_B, AD7758_APP_PWR), + .scan_index = 7, + .scan_type = { +@@ -742,9 +722,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 1, +- .extend_name = "active_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "active", + .address = AD7758_WT(AD7758_PHASE_B, AD7758_ACT_PWR), + .scan_index = 8, + .scan_type = { +@@ -756,9 +734,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 1, +- .extend_name = "reactive_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "reactive", + .address = AD7758_WT(AD7758_PHASE_B, AD7758_REACT_PWR), + .scan_index = 9, + .scan_type = { +@@ -770,9 +746,6 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 2, +- .extend_name = "raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_C, AD7758_VOLTAGE), + .scan_index = 10, + .scan_type = { +@@ -784,9 +757,6 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_CURRENT, + .indexed = 1, + .channel = 2, +- .extend_name = "raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_C, AD7758_CURRENT), + .scan_index = 11, + .scan_type = { +@@ -798,9 +768,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 2, +- .extend_name = "apparent_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "apparent", + .address = AD7758_WT(AD7758_PHASE_C, AD7758_APP_PWR), + .scan_index = 12, + .scan_type = { +@@ -812,9 +780,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 2, +- .extend_name = "active_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "active", + .address = AD7758_WT(AD7758_PHASE_C, AD7758_ACT_PWR), + .scan_index = 13, + .scan_type = { +@@ -826,9 +792,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 2, +- .extend_name = "reactive_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "reactive", + .address = AD7758_WT(AD7758_PHASE_C, AD7758_REACT_PWR), + .scan_index = 14, + .scan_type = { +@@ -869,13 +833,14 @@ static int ade7758_probe(struct spi_device *spi) + goto error_free_rx; + } + st->us = spi; +- st->ade7758_ring_channels = &ade7758_channels[0]; + mutex_init(&st->buf_lock); + + indio_dev->name = spi->dev.driver->name; + indio_dev->dev.parent = &spi->dev; + indio_dev->info = &ade7758_info; + indio_dev->modes = INDIO_DIRECT_MODE; ++ indio_dev->channels = ade7758_channels; ++ indio_dev->num_channels = ARRAY_SIZE(ade7758_channels); + + ret = ade7758_configure_ring(indio_dev); + if (ret) +diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c +index c0accf8cce93..6e9006490742 100644 +--- a/drivers/staging/iio/meter/ade7758_ring.c ++++ b/drivers/staging/iio/meter/ade7758_ring.c +@@ -85,17 +85,16 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p) + **/ + static int ade7758_ring_preenable(struct iio_dev *indio_dev) + { +- struct ade7758_state *st = iio_priv(indio_dev); + unsigned channel; + +- if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) ++ if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) + return -EINVAL; + + channel = find_first_bit(indio_dev->active_scan_mask, + indio_dev->masklength); + + ade7758_write_waveform_type(&indio_dev->dev, +- st->ade7758_ring_channels[channel].address); ++ indio_dev->channels[channel].address); + + return 0; + } +diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c +index 6ea95d216eb8..38b4be24d13f 100644 +--- a/drivers/target/target_core_device.c ++++ b/drivers/target/target_core_device.c +@@ -1409,7 +1409,8 @@ int core_dev_add_initiator_node_lun_acl( + * Check to see if there are any existing persistent reservation APTPL + * pre-registrations that need to be enabled for this LUN ACL.. + */ +- core_scsi3_check_aptpl_registration(lun->lun_se_dev, tpg, lun, lacl); ++ core_scsi3_check_aptpl_registration(lun->lun_se_dev, tpg, lun, nacl, ++ lacl->mapped_lun); + return 0; + } + +diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c +index 3013287a2aaa..1205dbd4f83d 100644 +--- a/drivers/target/target_core_pr.c ++++ b/drivers/target/target_core_pr.c +@@ -944,10 +944,10 @@ int core_scsi3_check_aptpl_registration( + struct se_device *dev, + struct se_portal_group *tpg, + struct se_lun *lun, +- struct se_lun_acl *lun_acl) ++ struct se_node_acl *nacl, ++ u32 mapped_lun) + { +- struct se_node_acl *nacl = lun_acl->se_lun_nacl; +- struct se_dev_entry *deve = nacl->device_list[lun_acl->mapped_lun]; ++ struct se_dev_entry *deve = nacl->device_list[mapped_lun]; + + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) + return 0; +diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h +index 2ee2936fa0bd..749fd7bb7510 100644 +--- a/drivers/target/target_core_pr.h ++++ b/drivers/target/target_core_pr.h +@@ -60,7 +60,7 @@ extern int core_scsi3_alloc_aptpl_registration( + unsigned char *, u16, u32, int, int, u8); + extern int core_scsi3_check_aptpl_registration(struct se_device *, + struct se_portal_group *, struct se_lun *, +- struct se_lun_acl *); ++ struct se_node_acl *, u32); + extern void core_scsi3_free_pr_reg_from_nacl(struct se_device *, + struct se_node_acl *); + extern void core_scsi3_free_all_registrations(struct se_device *); +diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c +index c036595b17cf..fb8a1a12dda9 100644 +--- a/drivers/target/target_core_tpg.c ++++ b/drivers/target/target_core_tpg.c +@@ -40,6 +40,7 @@ + #include + + #include "target_core_internal.h" ++#include "target_core_pr.h" + + extern struct se_device *g_lun0_dev; + +@@ -166,6 +167,13 @@ void core_tpg_add_node_to_devs( + + core_enable_device_list_for_node(lun, NULL, lun->unpacked_lun, + lun_access, acl, tpg); ++ /* ++ * Check to see if there are any existing persistent reservation ++ * APTPL pre-registrations that need to be enabled for this dynamic ++ * LUN ACL now.. ++ */ ++ core_scsi3_check_aptpl_registration(dev, tpg, lun, acl, ++ lun->unpacked_lun); + spin_lock(&tpg->tpg_lun_lock); + } + spin_unlock(&tpg->tpg_lun_lock); +diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c +index 24f527977ddb..9232c7738ed1 100644 +--- a/drivers/target/target_core_transport.c ++++ b/drivers/target/target_core_transport.c +@@ -1855,8 +1855,7 @@ static void transport_complete_qf(struct se_cmd *cmd) + if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { + trace_target_cmd_complete(cmd); + ret = cmd->se_tfo->queue_status(cmd); +- if (ret) +- goto out; ++ goto out; + } + + switch (cmd->data_direction) { +diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c +index 25b8f6868788..27b5554e20d9 100644 +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -353,7 +353,7 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, + * The spd_hi, spd_vhi, spd_shi, spd_warp kludge... + * Die! Die! Die! + */ +- if (baud == 38400) ++ if (try == 0 && baud == 38400) + baud = altbaud; + + /* +diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c +index d3448a90f0f9..25d07412e08e 100644 +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -1701,6 +1701,7 @@ int tty_release(struct inode *inode, struct file *filp) + int pty_master, tty_closing, o_tty_closing, do_sleep; + int idx; + char buf[64]; ++ long timeout = 0; + + if (tty_paranoia_check(tty, inode, __func__)) + return 0; +@@ -1785,7 +1786,11 @@ int tty_release(struct inode *inode, struct file *filp) + __func__, tty_name(tty, buf)); + tty_unlock_pair(tty, o_tty); + mutex_unlock(&tty_mutex); +- schedule(); ++ schedule_timeout_killable(timeout); ++ if (timeout < 120 * HZ) ++ timeout = 2 * timeout + 1; ++ else ++ timeout = MAX_SCHEDULE_TIMEOUT; + } + + /* +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index eabccd45f4e8..331f06a91cc3 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -965,11 +965,12 @@ static void acm_tty_set_termios(struct tty_struct *tty, + /* FIXME: Needs to clear unsupported bits in the termios */ + acm->clocal = ((termios->c_cflag & CLOCAL) != 0); + +- if (!newline.dwDTERate) { ++ if (C_BAUD(tty) == B0) { + newline.dwDTERate = acm->line.dwDTERate; + newctrl &= ~ACM_CTRL_DTR; +- } else ++ } else if (termios_old && (termios_old->c_cflag & CBAUD) == B0) { + newctrl |= ACM_CTRL_DTR; ++ } + + if (newctrl != acm->ctrlout) + acm_set_control(acm, acm->ctrlout = newctrl); +@@ -1672,6 +1673,7 @@ static const struct usb_device_id acm_ids[] = { + { USB_DEVICE(0x0572, 0x1328), /* Shiro / Aztech USB MODEM UM-3100 */ + .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ + }, ++ { USB_DEVICE(0x2184, 0x001c) }, /* GW Instek AFG-2225 */ + { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */ + }, + /* Motorola H24 HSPA module: */ +diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c +index 2518c3250750..ef6ec13b6ae5 100644 +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -2057,6 +2057,8 @@ int usb_alloc_streams(struct usb_interface *interface, + return -EINVAL; + if (dev->speed != USB_SPEED_SUPER) + return -EINVAL; ++ if (dev->state < USB_STATE_CONFIGURED) ++ return -ENODEV; + + /* Streams only apply to bulk endpoints. */ + for (i = 0; i < num_eps; i++) +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 445d62a4316a..d2bd9d7c8f4b 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -4378,6 +4378,9 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1) + struct usb_qualifier_descriptor *qual; + int status; + ++ if (udev->quirks & USB_QUIRK_DEVICE_QUALIFIER) ++ return; ++ + qual = kmalloc (sizeof *qual, GFP_KERNEL); + if (qual == NULL) + return; +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index 5144d11d032c..c85459338991 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -93,6 +93,16 @@ static const struct usb_device_id usb_quirk_list[] = { + { USB_DEVICE(0x04e8, 0x6601), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + ++ /* Elan Touchscreen */ ++ { USB_DEVICE(0x04f3, 0x0089), .driver_info = ++ USB_QUIRK_DEVICE_QUALIFIER }, ++ ++ { USB_DEVICE(0x04f3, 0x009b), .driver_info = ++ USB_QUIRK_DEVICE_QUALIFIER }, ++ ++ { USB_DEVICE(0x04f3, 0x016f), .driver_info = ++ USB_QUIRK_DEVICE_QUALIFIER }, ++ + /* Roland SC-8820 */ + { USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME }, + +diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c +index 21a352079bc2..0985ff715c0c 100644 +--- a/drivers/usb/dwc3/ep0.c ++++ b/drivers/usb/dwc3/ep0.c +@@ -251,7 +251,7 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) + + /* stall is always issued on EP0 */ + dep = dwc->eps[0]; +- __dwc3_gadget_ep_set_halt(dep, 1); ++ __dwc3_gadget_ep_set_halt(dep, 1, false); + dep->flags = DWC3_EP_ENABLED; + dwc->delayed_status = false; + +@@ -461,7 +461,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, + return -EINVAL; + if (set == 0 && (dep->flags & DWC3_EP_WEDGE)) + break; +- ret = __dwc3_gadget_ep_set_halt(dep, set); ++ ret = __dwc3_gadget_ep_set_halt(dep, set, true); + if (ret) + return -EINVAL; + break; +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 09e9619ae381..d90c70c23adb 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -532,12 +532,11 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, + if (!usb_endpoint_xfer_isoc(desc)) + return 0; + +- memset(&trb_link, 0, sizeof(trb_link)); +- + /* Link TRB for ISOC. The HWO bit is never reset */ + trb_st_hw = &dep->trb_pool[0]; + + trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1]; ++ memset(trb_link, 0, sizeof(*trb_link)); + + trb_link->bpl = lower_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw)); + trb_link->bph = upper_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw)); +@@ -588,7 +587,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) + + /* make sure HW endpoint isn't stalled */ + if (dep->flags & DWC3_EP_STALL) +- __dwc3_gadget_ep_set_halt(dep, 0); ++ __dwc3_gadget_ep_set_halt(dep, 0, false); + + reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); + reg &= ~DWC3_DALEPENA_EP(dep->number); +@@ -1186,7 +1185,7 @@ out0: + return ret; + } + +-int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value) ++int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) + { + struct dwc3_gadget_ep_cmd_params params; + struct dwc3 *dwc = dep->dwc; +@@ -1195,6 +1194,14 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value) + memset(¶ms, 0x00, sizeof(params)); + + if (value) { ++ if (!protocol && ((dep->direction && dep->flags & DWC3_EP_BUSY) || ++ (!list_empty(&dep->req_queued) || ++ !list_empty(&dep->request_list)))) { ++ dev_dbg(dwc->dev, "%s: pending request, cannot halt\n", ++ dep->name); ++ return -EAGAIN; ++ } ++ + ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, + DWC3_DEPCMD_SETSTALL, ¶ms); + if (ret) +@@ -1234,7 +1241,7 @@ static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value) + goto out; + } + +- ret = __dwc3_gadget_ep_set_halt(dep, value); ++ ret = __dwc3_gadget_ep_set_halt(dep, value, false); + out: + spin_unlock_irqrestore(&dwc->lock, flags); + +@@ -1254,7 +1261,7 @@ static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep) + if (dep->number == 0 || dep->number == 1) + return dwc3_gadget_ep0_set_halt(ep, 1); + else +- return dwc3_gadget_ep_set_halt(ep, 1); ++ return __dwc3_gadget_ep_set_halt(dep, 1, false); + } + + /* -------------------------------------------------------------------------- */ +diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h +index a0ee75b68a80..ac62558231be 100644 +--- a/drivers/usb/dwc3/gadget.h ++++ b/drivers/usb/dwc3/gadget.h +@@ -85,7 +85,7 @@ void dwc3_ep0_out_start(struct dwc3 *dwc); + int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value); + int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, + gfp_t gfp_flags); +-int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value); ++int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol); + + /** + * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW +diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c +index ab1065afbbd0..3384486c2884 100644 +--- a/drivers/usb/gadget/f_acm.c ++++ b/drivers/usb/gadget/f_acm.c +@@ -430,11 +430,12 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) + if (acm->notify->driver_data) { + VDBG(cdev, "reset acm control interface %d\n", intf); + usb_ep_disable(acm->notify); +- } else { +- VDBG(cdev, "init acm ctrl interface %d\n", intf); ++ } ++ ++ if (!acm->notify->desc) + if (config_ep_by_speed(cdev->gadget, f, acm->notify)) + return -EINVAL; +- } ++ + usb_ep_enable(acm->notify); + acm->notify->driver_data = acm; + +diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c +index 5bcf7d001259..afd0a159fe61 100644 +--- a/drivers/usb/gadget/f_fs.c ++++ b/drivers/usb/gadget/f_fs.c +@@ -1995,8 +1995,6 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, + func->conf = c; + func->gadget = c->cdev->gadget; + +- ffs_data_get(func->ffs); +- + /* + * in drivers/usb/gadget/configfs.c:configfs_composite_bind() + * configurations are bound in sequence with list_for_each_entry, +diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c +index 27768a7d986a..9ce0b135c8c8 100644 +--- a/drivers/usb/gadget/udc-core.c ++++ b/drivers/usb/gadget/udc-core.c +@@ -456,6 +456,11 @@ static ssize_t usb_udc_softconn_store(struct device *dev, + { + struct usb_udc *udc = container_of(dev, struct usb_udc, dev); + ++ if (!udc->driver) { ++ dev_err(dev, "soft-connect without a gadget driver\n"); ++ return -EOPNOTSUPP; ++ } ++ + if (sysfs_streq(buf, "connect")) { + usb_gadget_udc_start(udc->gadget, udc->driver); + usb_gadget_connect(udc->gadget); +diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c +index c2d5afc57e22..1d29bbfeb9d5 100644 +--- a/drivers/usb/musb/musb_cppi41.c ++++ b/drivers/usb/musb/musb_cppi41.c +@@ -190,7 +190,8 @@ static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer) + } + } + +- if (!list_empty(&controller->early_tx_list)) { ++ if (!list_empty(&controller->early_tx_list) && ++ !hrtimer_is_queued(&controller->early_tx)) { + ret = HRTIMER_RESTART; + hrtimer_forward_now(&controller->early_tx, + ktime_set(0, 150 * NSEC_PER_USEC)); +diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c +index 85f5215871de..865243e818b7 100644 +--- a/drivers/usb/musb/musb_dsps.c ++++ b/drivers/usb/musb/musb_dsps.c +@@ -733,7 +733,9 @@ static int dsps_resume(struct device *dev) + dsps_writel(mbase, wrp->mode, glue->context.mode); + dsps_writel(mbase, wrp->tx_mode, glue->context.tx_mode); + dsps_writel(mbase, wrp->rx_mode, glue->context.rx_mode); +- setup_timer(&glue->timer, otg_timer, (unsigned long) musb); ++ if (musb->xceiv->state == OTG_STATE_B_IDLE && ++ musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) ++ mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ); + + return 0; + } +diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c +index 8afa813d690b..0180eef05656 100644 +--- a/drivers/usb/phy/phy.c ++++ b/drivers/usb/phy/phy.c +@@ -229,6 +229,9 @@ struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index) + phy = __usb_find_phy_dev(dev, &phy_bind_list, index); + if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { + dev_dbg(dev, "unable to find transceiver\n"); ++ if (!IS_ERR(phy)) ++ phy = ERR_PTR(-ENODEV); ++ + goto err0; + } + +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 63b2af2a87c0..3beae723ad3a 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -155,6 +155,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ + { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ + { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ ++ { USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */ + { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ + { USB_DEVICE(0x1D6F, 0x0010) }, /* Seluxit ApS RF Dongle */ + { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */ +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index 3614620e09e1..a523adad6380 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -145,6 +145,7 @@ static struct ftdi_sio_quirk ftdi_8u2232c_quirk = { + * /sys/bus/usb-serial/drivers/ftdi_sio/new_id and send a patch or report. + */ + static const struct usb_device_id id_table_combined[] = { ++ { USB_DEVICE(FTDI_VID, FTDI_BRICK_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) }, +@@ -674,6 +675,8 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) }, + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) }, + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, ++ { USB_DEVICE(XSENS_VID, XSENS_AWINDA_DONGLE_PID) }, ++ { USB_DEVICE(XSENS_VID, XSENS_AWINDA_STATION_PID) }, + { USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) }, + { USB_DEVICE(XSENS_VID, XSENS_MTW_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) }, +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index 5937b2d242f2..6786b705ccf6 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -30,6 +30,12 @@ + + /*** third-party PIDs (using FTDI_VID) ***/ + ++/* ++ * Certain versions of the official Windows FTDI driver reprogrammed ++ * counterfeit FTDI devices to PID 0. Support these devices anyway. ++ */ ++#define FTDI_BRICK_PID 0x0000 ++ + #define FTDI_LUMEL_PD12_PID 0x6002 + + /* +@@ -143,8 +149,12 @@ + * Xsens Technologies BV products (http://www.xsens.com). + */ + #define XSENS_VID 0x2639 +-#define XSENS_CONVERTER_PID 0xD00D /* Xsens USB-serial converter */ ++#define XSENS_AWINDA_STATION_PID 0x0101 ++#define XSENS_AWINDA_DONGLE_PID 0x0102 + #define XSENS_MTW_PID 0x0200 /* Xsens MTw */ ++#define XSENS_CONVERTER_PID 0xD00D /* Xsens USB-serial converter */ ++ ++/* Xsens devices using FTDI VID */ + #define XSENS_CONVERTER_0_PID 0xD388 /* Xsens USB converter */ + #define XSENS_CONVERTER_1_PID 0xD389 /* Xsens Wireless Receiver */ + #define XSENS_CONVERTER_2_PID 0xD38A +diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c +index 618c1c1f227e..5cdb32b37e85 100644 +--- a/drivers/usb/serial/kobil_sct.c ++++ b/drivers/usb/serial/kobil_sct.c +@@ -335,7 +335,8 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, + port->interrupt_out_urb->transfer_buffer_length = length; + + priv->cur_pos = priv->cur_pos + length; +- result = usb_submit_urb(port->interrupt_out_urb, GFP_NOIO); ++ result = usb_submit_urb(port->interrupt_out_urb, ++ GFP_ATOMIC); + dev_dbg(&port->dev, "%s - Send write URB returns: %i\n", __func__, result); + todo = priv->filled - priv->cur_pos; + +@@ -350,7 +351,7 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, + if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || + priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) { + result = usb_submit_urb(port->interrupt_in_urb, +- GFP_NOIO); ++ GFP_ATOMIC); + dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result); + } + } +diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c +index 4856fb7e637e..4b7bfb394a32 100644 +--- a/drivers/usb/serial/opticon.c ++++ b/drivers/usb/serial/opticon.c +@@ -215,7 +215,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, + + /* The connected devices do not have a bulk write endpoint, + * to transmit data to de barcode device the control endpoint is used */ +- dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO); ++ dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); + if (!dr) { + count = -ENOMEM; + goto error_no_dr; +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index e47aabe0c760..8b3484134ab0 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -269,6 +269,7 @@ static void option_instat_callback(struct urb *urb); + #define TELIT_PRODUCT_DE910_DUAL 0x1010 + #define TELIT_PRODUCT_UE910_V2 0x1012 + #define TELIT_PRODUCT_LE920 0x1200 ++#define TELIT_PRODUCT_LE910 0x1201 + + /* ZTE PRODUCTS */ + #define ZTE_VENDOR_ID 0x19d2 +@@ -361,6 +362,7 @@ static void option_instat_callback(struct urb *urb); + + /* Haier products */ + #define HAIER_VENDOR_ID 0x201e ++#define HAIER_PRODUCT_CE81B 0x10f8 + #define HAIER_PRODUCT_CE100 0x2009 + + /* Cinterion (formerly Siemens) products */ +@@ -588,6 +590,11 @@ static const struct option_blacklist_info zte_1255_blacklist = { + .reserved = BIT(3) | BIT(4), + }; + ++static const struct option_blacklist_info telit_le910_blacklist = { ++ .sendsetup = BIT(0), ++ .reserved = BIT(1) | BIT(2), ++}; ++ + static const struct option_blacklist_info telit_le920_blacklist = { + .sendsetup = BIT(0), + .reserved = BIT(1) | BIT(5), +@@ -1137,6 +1144,8 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) }, ++ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910), ++ .driver_info = (kernel_ulong_t)&telit_le910_blacklist }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), + .driver_info = (kernel_ulong_t)&telit_le920_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ +@@ -1612,6 +1621,7 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) }, + { USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) }, + { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(HAIER_VENDOR_ID, HAIER_PRODUCT_CE81B, 0xff, 0xff, 0xff) }, + /* Pirelli */ + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2, 0xff) }, +diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c +index 22c7d4360fa2..b1d815eb6d0b 100644 +--- a/drivers/usb/storage/transport.c ++++ b/drivers/usb/storage/transport.c +@@ -1118,6 +1118,31 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) + */ + if (result == USB_STOR_XFER_LONG) + fake_sense = 1; ++ ++ /* ++ * Sometimes a device will mistakenly skip the data phase ++ * and go directly to the status phase without sending a ++ * zero-length packet. If we get a 13-byte response here, ++ * check whether it really is a CSW. ++ */ ++ if (result == USB_STOR_XFER_SHORT && ++ srb->sc_data_direction == DMA_FROM_DEVICE && ++ transfer_length - scsi_get_resid(srb) == ++ US_BULK_CS_WRAP_LEN) { ++ struct scatterlist *sg = NULL; ++ unsigned int offset = 0; ++ ++ if (usb_stor_access_xfer_buf((unsigned char *) bcs, ++ US_BULK_CS_WRAP_LEN, srb, &sg, ++ &offset, FROM_XFER_BUF) == ++ US_BULK_CS_WRAP_LEN && ++ bcs->Signature == ++ cpu_to_le32(US_BULK_CS_SIGN)) { ++ usb_stor_dbg(us, "Device skipped data phase\n"); ++ scsi_set_resid(srb, transfer_length); ++ goto skipped_data_phase; ++ } ++ } + } + + /* See flow chart on pg 15 of the Bulk Only Transport spec for +@@ -1153,6 +1178,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) + if (result != USB_STOR_XFER_GOOD) + return USB_STOR_TRANSPORT_ERROR; + ++ skipped_data_phase: + /* check bulk status */ + residue = le32_to_cpu(bcs->Residue); + usb_stor_dbg(us, "Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n", +diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c +index 61b182bf32a2..dbfe4eecf12e 100644 +--- a/drivers/video/console/bitblit.c ++++ b/drivers/video/console/bitblit.c +@@ -205,7 +205,6 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info, + static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, + int bottom_only) + { +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + unsigned int cw = vc->vc_font.width; + unsigned int ch = vc->vc_font.height; + unsigned int rw = info->var.xres - (vc->vc_cols*cw); +@@ -214,7 +213,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, + unsigned int bs = info->var.yres - bh; + struct fb_fillrect region; + +- region.color = attr_bgcol_ec(bgshift, vc, info); ++ region.color = 0; + region.rop = ROP_COPY; + + if (rw && !bottom_only) { +diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c +index 41b32ae23dac..5a3cbf6dff4d 100644 +--- a/drivers/video/console/fbcon_ccw.c ++++ b/drivers/video/console/fbcon_ccw.c +@@ -197,9 +197,8 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info, + unsigned int bh = info->var.xres - (vc->vc_rows*ch); + unsigned int bs = vc->vc_rows*ch; + struct fb_fillrect region; +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + +- region.color = attr_bgcol_ec(bgshift,vc,info); ++ region.color = 0; + region.rop = ROP_COPY; + + if (rw && !bottom_only) { +diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c +index a93670ef7f89..e7ee44db4e98 100644 +--- a/drivers/video/console/fbcon_cw.c ++++ b/drivers/video/console/fbcon_cw.c +@@ -180,9 +180,8 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info, + unsigned int bh = info->var.xres - (vc->vc_rows*ch); + unsigned int rs = info->var.yres - rw; + struct fb_fillrect region; +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + +- region.color = attr_bgcol_ec(bgshift,vc,info); ++ region.color = 0; + region.rop = ROP_COPY; + + if (rw && !bottom_only) { +diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c +index ff0872c0498b..19e3714abfe8 100644 +--- a/drivers/video/console/fbcon_ud.c ++++ b/drivers/video/console/fbcon_ud.c +@@ -227,9 +227,8 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info, + unsigned int rw = info->var.xres - (vc->vc_cols*cw); + unsigned int bh = info->var.yres - (vc->vc_rows*ch); + struct fb_fillrect region; +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + +- region.color = attr_bgcol_ec(bgshift,vc,info); ++ region.color = 0; + region.rop = ROP_COPY; + + if (rw && !bottom_only) { +diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c +index a416f9b2a7f6..827b5f8e6297 100644 +--- a/drivers/virtio/virtio_pci.c ++++ b/drivers/virtio/virtio_pci.c +@@ -791,6 +791,7 @@ static int virtio_pci_restore(struct device *dev) + struct pci_dev *pci_dev = to_pci_dev(dev); + struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); + struct virtio_driver *drv; ++ unsigned status = 0; + int ret; + + drv = container_of(vp_dev->vdev.dev.driver, +@@ -801,14 +802,40 @@ static int virtio_pci_restore(struct device *dev) + return ret; + + pci_set_master(pci_dev); ++ /* We always start by resetting the device, in case a previous ++ * driver messed it up. */ ++ vp_reset(&vp_dev->vdev); ++ ++ /* Acknowledge that we've seen the device. */ ++ status |= VIRTIO_CONFIG_S_ACKNOWLEDGE; ++ vp_set_status(&vp_dev->vdev, status); ++ ++ /* Maybe driver failed before freeze. ++ * Restore the failed status, for debugging. */ ++ status |= vp_dev->saved_status & VIRTIO_CONFIG_S_FAILED; ++ vp_set_status(&vp_dev->vdev, status); ++ ++ if (!drv) ++ return 0; ++ ++ /* We have a driver! */ ++ status |= VIRTIO_CONFIG_S_DRIVER; ++ vp_set_status(&vp_dev->vdev, status); ++ + vp_finalize_features(&vp_dev->vdev); + +- if (drv && drv->restore) ++ if (drv->restore) { + ret = drv->restore(&vp_dev->vdev); ++ if (ret) { ++ status |= VIRTIO_CONFIG_S_FAILED; ++ vp_set_status(&vp_dev->vdev, status); ++ return ret; ++ } ++ } + + /* Finally, tell the device we're all set */ +- if (!ret) +- vp_set_status(&vp_dev->vdev, vp_dev->saved_status); ++ status |= VIRTIO_CONFIG_S_DRIVER_OK; ++ vp_set_status(&vp_dev->vdev, status); + + return ret; + } +diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c +index ca248b0687f4..196b089b0052 100644 +--- a/fs/btrfs/file-item.c ++++ b/fs/btrfs/file-item.c +@@ -423,7 +423,7 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, + ret = 0; + fail: + while (ret < 0 && !list_empty(&tmplist)) { +- sums = list_entry(&tmplist, struct btrfs_ordered_sum, list); ++ sums = list_entry(tmplist.next, struct btrfs_ordered_sum, list); + list_del(&sums->list); + kfree(sums); + } +diff --git a/fs/buffer.c b/fs/buffer.c +index 71e2d0ed8530..4d06a573d199 100644 +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -2077,6 +2077,7 @@ int generic_write_end(struct file *file, struct address_space *mapping, + struct page *page, void *fsdata) + { + struct inode *inode = mapping->host; ++ loff_t old_size = inode->i_size; + int i_size_changed = 0; + + copied = block_write_end(file, mapping, pos, len, copied, page, fsdata); +@@ -2096,6 +2097,8 @@ int generic_write_end(struct file *file, struct address_space *mapping, + unlock_page(page); + page_cache_release(page); + ++ if (old_size < pos) ++ pagecache_isize_extended(inode, old_size, pos); + /* + * Don't mark the inode dirty under page lock. First, it unnecessarily + * makes the holding time of page lock longer. Second, it forces lock +@@ -2313,6 +2316,11 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping, + err = 0; + + balance_dirty_pages_ratelimited(mapping); ++ ++ if (unlikely(fatal_signal_pending(current))) { ++ err = -EINTR; ++ goto out; ++ } + } + + /* page covers the boundary, find the boundary offset */ +diff --git a/fs/dcache.c b/fs/dcache.c +index 58d57da91d2a..436612777203 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -2824,6 +2824,9 @@ static int prepend(char **buffer, int *buflen, const char *str, int namelen) + * the beginning of the name. The sequence number check at the caller will + * retry it again when a d_move() does happen. So any garbage in the buffer + * due to mismatched pointer and length will be discarded. ++ * ++ * Data dependency barrier is needed to make sure that we see that terminating ++ * NUL. Alpha strikes again, film at 11... + */ + static int prepend_name(char **buffer, int *buflen, struct qstr *name) + { +@@ -2831,6 +2834,8 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name) + u32 dlen = ACCESS_ONCE(name->len); + char *p; + ++ smp_read_barrier_depends(); ++ + *buflen -= dlen + 1; + if (*buflen < 0) + return -ENAMETOOLONG; +diff --git a/fs/ext3/super.c b/fs/ext3/super.c +index 37fd31ed16e7..0498390f309e 100644 +--- a/fs/ext3/super.c ++++ b/fs/ext3/super.c +@@ -1354,13 +1354,6 @@ set_qf_format: + "not specified."); + return 0; + } +- } else { +- if (sbi->s_jquota_fmt) { +- ext3_msg(sb, KERN_ERR, "error: journaled quota format " +- "specified with no journaling " +- "enabled."); +- return 0; +- } + } + #endif + return 1; +diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c +index 3285aa5a706a..b610779a958c 100644 +--- a/fs/ext4/bitmap.c ++++ b/fs/ext4/bitmap.c +@@ -24,8 +24,7 @@ int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, + __u32 provided, calculated; + struct ext4_sb_info *sbi = EXT4_SB(sb); + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return 1; + + provided = le16_to_cpu(gdp->bg_inode_bitmap_csum_lo); +@@ -46,8 +45,7 @@ void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group, + __u32 csum; + struct ext4_sb_info *sbi = EXT4_SB(sb); + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return; + + csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz); +@@ -65,8 +63,7 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, + struct ext4_sb_info *sbi = EXT4_SB(sb); + int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return 1; + + provided = le16_to_cpu(gdp->bg_block_bitmap_csum_lo); +@@ -91,8 +88,7 @@ void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group, + __u32 csum; + struct ext4_sb_info *sbi = EXT4_SB(sb); + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return; + + csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz); +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 62f024c051ce..2a6830a7af33 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -2110,6 +2110,7 @@ int do_journal_get_write_access(handle_t *handle, + #define CONVERT_INLINE_DATA 2 + + extern struct inode *ext4_iget(struct super_block *, unsigned long); ++extern struct inode *ext4_iget_normal(struct super_block *, unsigned long); + extern int ext4_write_inode(struct inode *, struct writeback_control *); + extern int ext4_setattr(struct dentry *, struct iattr *); + extern int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, +@@ -2340,10 +2341,18 @@ extern int ext4_register_li_request(struct super_block *sb, + static inline int ext4_has_group_desc_csum(struct super_block *sb) + { + return EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_GDT_CSUM | +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM); ++ EXT4_FEATURE_RO_COMPAT_GDT_CSUM) || ++ (EXT4_SB(sb)->s_chksum_driver != NULL); + } + ++static inline int ext4_has_metadata_csum(struct super_block *sb) ++{ ++ WARN_ON_ONCE(EXT4_HAS_RO_COMPAT_FEATURE(sb, ++ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) && ++ !EXT4_SB(sb)->s_chksum_driver); ++ ++ return (EXT4_SB(sb)->s_chksum_driver != NULL); ++} + static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es) + { + return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) | +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 47188916dd8d..96a1ce159f51 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -74,8 +74,7 @@ static int ext4_extent_block_csum_verify(struct inode *inode, + { + struct ext4_extent_tail *et; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(inode->i_sb)) + return 1; + + et = find_ext4_extent_tail(eh); +@@ -89,8 +88,7 @@ static void ext4_extent_block_csum_set(struct inode *inode, + { + struct ext4_extent_tail *et; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(inode->i_sb)) + return; + + et = find_ext4_extent_tail(eh); +diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c +index 64bb32f17903..a8d1a64d8cb0 100644 +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -864,6 +864,10 @@ got: + struct buffer_head *block_bitmap_bh; + + block_bitmap_bh = ext4_read_block_bitmap(sb, group); ++ if (!block_bitmap_bh) { ++ err = -EIO; ++ goto out; ++ } + BUFFER_TRACE(block_bitmap_bh, "get block bitmap access"); + err = ext4_journal_get_write_access(handle, block_bitmap_bh); + if (err) { +@@ -988,8 +992,7 @@ got: + spin_unlock(&sbi->s_next_gen_lock); + + /* Precompute checksum seed for inode metadata */ +- if (EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { ++ if (ext4_has_metadata_csum(sb)) { + __u32 csum; + __le32 inum = cpu_to_le32(inode->i_ino); + __le32 gen = cpu_to_le32(inode->i_generation); +diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c +index 82edf5b93352..8c03b747021b 100644 +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -1128,8 +1128,7 @@ static int ext4_finish_convert_inline_dir(handle_t *handle, + memcpy((void *)de, buf + EXT4_INLINE_DOTDOT_SIZE, + inline_size - EXT4_INLINE_DOTDOT_SIZE); + +- if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(inode->i_sb)) + csum_size = sizeof(struct ext4_dir_entry_tail); + + inode->i_size = inode->i_sb->s_blocksize; +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index b56062dc8b62..3a7e0341447f 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -83,8 +83,7 @@ static int ext4_inode_csum_verify(struct inode *inode, struct ext4_inode *raw, + + if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != + cpu_to_le32(EXT4_OS_LINUX) || +- !EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ !ext4_has_metadata_csum(inode->i_sb)) + return 1; + + provided = le16_to_cpu(raw->i_checksum_lo); +@@ -105,8 +104,7 @@ static void ext4_inode_csum_set(struct inode *inode, struct ext4_inode *raw, + + if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != + cpu_to_le32(EXT4_OS_LINUX) || +- !EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ !ext4_has_metadata_csum(inode->i_sb)) + return; + + csum = ext4_inode_csum(inode, raw, ei); +@@ -2633,6 +2631,20 @@ static int ext4_nonda_switch(struct super_block *sb) + return 0; + } + ++/* We always reserve for an inode update; the superblock could be there too */ ++static int ext4_da_write_credits(struct inode *inode, loff_t pos, unsigned len) ++{ ++ if (likely(EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, ++ EXT4_FEATURE_RO_COMPAT_LARGE_FILE))) ++ return 1; ++ ++ if (pos + len <= 0x7fffffffULL) ++ return 1; ++ ++ /* We might need to update the superblock to set LARGE_FILE */ ++ return 2; ++} ++ + static int ext4_da_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned flags, + struct page **pagep, void **fsdata) +@@ -2683,7 +2695,8 @@ retry_grab: + * of file which has an already mapped buffer. + */ + retry_journal: +- handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, 1); ++ handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, ++ ext4_da_write_credits(inode, pos, len)); + if (IS_ERR(handle)) { + page_cache_release(page); + return PTR_ERR(handle); +@@ -4061,8 +4074,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) + ei->i_extra_isize = 0; + + /* Precompute checksum seed for inode metadata */ +- if (EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { ++ if (ext4_has_metadata_csum(sb)) { + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + __u32 csum; + __le32 inum = cpu_to_le32(inode->i_ino); +@@ -4250,6 +4262,13 @@ bad_inode: + return ERR_PTR(ret); + } + ++struct inode *ext4_iget_normal(struct super_block *sb, unsigned long ino) ++{ ++ if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO) ++ return ERR_PTR(-EIO); ++ return ext4_iget(sb, ino); ++} ++ + static int ext4_inode_blocks_set(handle_t *handle, + struct ext4_inode *raw_inode, + struct ext4_inode_info *ei) +@@ -4645,8 +4664,12 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) + ext4_orphan_del(NULL, inode); + goto err_out; + } +- } else ++ } else { ++ loff_t oldsize = inode->i_size; ++ + i_size_write(inode, attr->ia_size); ++ pagecache_isize_extended(inode, oldsize, inode->i_size); ++ } + + /* + * Blocks are going to be removed from the inode. Wait +diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c +index a2a837f00407..dfe982dee0b3 100644 +--- a/fs/ext4/ioctl.c ++++ b/fs/ext4/ioctl.c +@@ -343,8 +343,7 @@ flags_out: + if (!inode_owner_or_capable(inode)) + return -EPERM; + +- if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { ++ if (ext4_has_metadata_csum(inode->i_sb)) { + ext4_warning(sb, "Setting inode version is not " + "supported with metadata_csum enabled."); + return -ENOTTY; +@@ -544,9 +543,17 @@ group_add_out: + } + + case EXT4_IOC_SWAP_BOOT: ++ { ++ int err; + if (!(filp->f_mode & FMODE_WRITE)) + return -EBADF; +- return swap_inode_boot_loader(sb, inode); ++ err = mnt_want_write_file(filp); ++ if (err) ++ return err; ++ err = swap_inode_boot_loader(sb, inode); ++ mnt_drop_write_file(filp); ++ return err; ++ } + + case EXT4_IOC_RESIZE_FS: { + ext4_fsblk_t n_blocks_count; +diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c +index 04434ad3e8e0..1268a1b5afa9 100644 +--- a/fs/ext4/mmp.c ++++ b/fs/ext4/mmp.c +@@ -20,8 +20,7 @@ static __le32 ext4_mmp_csum(struct super_block *sb, struct mmp_struct *mmp) + + int ext4_mmp_csum_verify(struct super_block *sb, struct mmp_struct *mmp) + { +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return 1; + + return mmp->mmp_checksum == ext4_mmp_csum(sb, mmp); +@@ -29,8 +28,7 @@ int ext4_mmp_csum_verify(struct super_block *sb, struct mmp_struct *mmp) + + void ext4_mmp_csum_set(struct super_block *sb, struct mmp_struct *mmp) + { +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return; + + mmp->mmp_checksum = ext4_mmp_csum(sb, mmp); +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index d050e043e884..2dcbfb6245d8 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -123,8 +123,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode, + "directory leaf block found instead of index block"); + return ERR_PTR(-EIO); + } +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) || ++ if (!ext4_has_metadata_csum(inode->i_sb) || + buffer_verified(bh)) + return bh; + +@@ -339,8 +338,7 @@ int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent) + { + struct ext4_dir_entry_tail *t; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(inode->i_sb)) + return 1; + + t = get_dirent_tail(inode, dirent); +@@ -361,8 +359,7 @@ static void ext4_dirent_csum_set(struct inode *inode, + { + struct ext4_dir_entry_tail *t; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(inode->i_sb)) + return; + + t = get_dirent_tail(inode, dirent); +@@ -437,8 +434,7 @@ static int ext4_dx_csum_verify(struct inode *inode, + struct dx_tail *t; + int count_offset, limit, count; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(inode->i_sb)) + return 1; + + c = get_dx_countlimit(inode, dirent, &count_offset); +@@ -467,8 +463,7 @@ static void ext4_dx_csum_set(struct inode *inode, struct ext4_dir_entry *dirent) + struct dx_tail *t; + int count_offset, limit, count; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(inode->i_sb)) + return; + + c = get_dx_countlimit(inode, dirent, &count_offset); +@@ -556,8 +551,7 @@ static inline unsigned dx_root_limit(struct inode *dir, unsigned infosize) + unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(1) - + EXT4_DIR_REC_LEN(2) - infosize; + +- if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(dir->i_sb)) + entry_space -= sizeof(struct dx_tail); + return entry_space / sizeof(struct dx_entry); + } +@@ -566,8 +560,7 @@ static inline unsigned dx_node_limit(struct inode *dir) + { + unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(0); + +- if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(dir->i_sb)) + entry_space -= sizeof(struct dx_tail); + return entry_space / sizeof(struct dx_entry); + } +@@ -1429,7 +1422,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi + dentry); + return ERR_PTR(-EIO); + } +- inode = ext4_iget(dir->i_sb, ino); ++ inode = ext4_iget_normal(dir->i_sb, ino); + if (inode == ERR_PTR(-ESTALE)) { + EXT4_ERROR_INODE(dir, + "deleted inode referenced: %u", +@@ -1460,7 +1453,7 @@ struct dentry *ext4_get_parent(struct dentry *child) + return ERR_PTR(-EIO); + } + +- return d_obtain_alias(ext4_iget(child->d_inode->i_sb, ino)); ++ return d_obtain_alias(ext4_iget_normal(child->d_inode->i_sb, ino)); + } + + /* +@@ -1534,8 +1527,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, + int csum_size = 0; + int err = 0, i; + +- if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(dir->i_sb)) + csum_size = sizeof(struct ext4_dir_entry_tail); + + bh2 = ext4_append(handle, dir, &newblock); +@@ -1704,8 +1696,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, + int csum_size = 0; + int err; + +- if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(inode->i_sb)) + csum_size = sizeof(struct ext4_dir_entry_tail); + + if (!de) { +@@ -1772,8 +1763,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, + struct fake_dirent *fde; + int csum_size = 0; + +- if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(inode->i_sb)) + csum_size = sizeof(struct ext4_dir_entry_tail); + + blocksize = dir->i_sb->s_blocksize; +@@ -1889,8 +1879,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, + ext4_lblk_t block, blocks; + int csum_size = 0; + +- if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(inode->i_sb)) + csum_size = sizeof(struct ext4_dir_entry_tail); + + sb = dir->i_sb; +@@ -2152,8 +2141,7 @@ static int ext4_delete_entry(handle_t *handle, + return err; + } + +- if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(dir->i_sb)) + csum_size = sizeof(struct ext4_dir_entry_tail); + + BUFFER_TRACE(bh, "get_write_access"); +@@ -2372,8 +2360,7 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir, + int csum_size = 0; + int err; + +- if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(dir->i_sb)) + csum_size = sizeof(struct ext4_dir_entry_tail); + + if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) { +diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c +index f3b84cd9de56..2400ad1c3d12 100644 +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -1071,7 +1071,7 @@ static void update_backups(struct super_block *sb, int blk_off, char *data, + break; + + if (meta_bg == 0) +- backup_block = group * bpg + blk_off; ++ backup_block = ((ext4_fsblk_t)group) * bpg + blk_off; + else + backup_block = (ext4_group_first_block_no(sb, group) + + ext4_bg_has_super(sb, group)); +@@ -1200,8 +1200,7 @@ static int ext4_set_bitmap_checksums(struct super_block *sb, + { + struct buffer_head *bh; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return 0; + + bh = ext4_get_bitmap(sb, group_data->inode_bitmap); +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index a46030d6b4af..9fb3e6c0c578 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -140,8 +140,7 @@ static __le32 ext4_superblock_csum(struct super_block *sb, + int ext4_superblock_csum_verify(struct super_block *sb, + struct ext4_super_block *es) + { +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return 1; + + return es->s_checksum == ext4_superblock_csum(sb, es); +@@ -151,8 +150,7 @@ void ext4_superblock_csum_set(struct super_block *sb) + { + struct ext4_super_block *es = EXT4_SB(sb)->s_es; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return; + + es->s_checksum = ext4_superblock_csum(sb, es); +@@ -996,7 +994,7 @@ static struct inode *ext4_nfs_get_inode(struct super_block *sb, + * Currently we don't know the generation for parent directory, so + * a generation of 0 means "accept any" + */ +- inode = ext4_iget(sb, ino); ++ inode = ext4_iget_normal(sb, ino); + if (IS_ERR(inode)) + return ERR_CAST(inode); + if (generation && inode->i_generation != generation) { +@@ -1706,13 +1704,6 @@ static int parse_options(char *options, struct super_block *sb, + "not specified"); + return 0; + } +- } else { +- if (sbi->s_jquota_fmt) { +- ext4_msg(sb, KERN_ERR, "journaled quota format " +- "specified with no journaling " +- "enabled"); +- return 0; +- } + } + #endif + if (test_opt(sb, DIOREAD_NOLOCK)) { +@@ -2010,8 +2001,7 @@ static __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group, + __u16 crc = 0; + __le32 le_group = cpu_to_le32(block_group); + +- if ((sbi->s_es->s_feature_ro_compat & +- cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))) { ++ if (ext4_has_metadata_csum(sbi->s_sb)) { + /* Use new metadata_csum algorithm */ + __le16 save_csum; + __u32 csum32; +@@ -2029,6 +2019,10 @@ static __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group, + } + + /* old crc16 code */ ++ if (!(sbi->s_es->s_feature_ro_compat & ++ cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM))) ++ return 0; ++ + offset = offsetof(struct ext4_group_desc, bg_checksum); + + crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid)); +@@ -3167,8 +3161,7 @@ static int set_journal_csum_feature_set(struct super_block *sb) + int compat, incompat; + struct ext4_sb_info *sbi = EXT4_SB(sb); + +- if (EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { ++ if (ext4_has_metadata_csum(sb)) { + /* journal checksum v3 */ + compat = 0; + incompat = JBD2_FEATURE_INCOMPAT_CSUM_V3; +@@ -3475,8 +3468,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) + } + + /* Precompute checksum seed for all metadata */ +- if (EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(sb)) + sbi->s_csum_seed = ext4_chksum(sbi, ~0, es->s_uuid, + sizeof(es->s_uuid)); + +@@ -3494,6 +3486,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) + #ifdef CONFIG_EXT4_FS_POSIX_ACL + set_opt(sb, POSIX_ACL); + #endif ++ /* don't forget to enable journal_csum when metadata_csum is enabled. */ ++ if (ext4_has_metadata_csum(sb)) ++ set_opt(sb, JOURNAL_CHECKSUM); ++ + if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA) + set_opt(sb, JOURNAL_DATA); + else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED) +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index 55e611c1513c..8825154b20b6 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -141,8 +141,7 @@ static int ext4_xattr_block_csum_verify(struct inode *inode, + sector_t block_nr, + struct ext4_xattr_header *hdr) + { +- if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) && ++ if (ext4_has_metadata_csum(inode->i_sb) && + (hdr->h_checksum != ext4_xattr_block_csum(inode, block_nr, hdr))) + return 0; + return 1; +@@ -152,8 +151,7 @@ static void ext4_xattr_block_csum_set(struct inode *inode, + sector_t block_nr, + struct ext4_xattr_header *hdr) + { +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(inode->i_sb)) + return; + + hdr->h_checksum = ext4_xattr_block_csum(inode, block_nr, hdr); +@@ -189,14 +187,28 @@ ext4_listxattr(struct dentry *dentry, char *buffer, size_t size) + } + + static int +-ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end) ++ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end, ++ void *value_start) + { +- while (!IS_LAST_ENTRY(entry)) { +- struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(entry); ++ struct ext4_xattr_entry *e = entry; ++ ++ while (!IS_LAST_ENTRY(e)) { ++ struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(e); + if ((void *)next >= end) + return -EIO; +- entry = next; ++ e = next; + } ++ ++ while (!IS_LAST_ENTRY(entry)) { ++ if (entry->e_value_size != 0 && ++ (value_start + le16_to_cpu(entry->e_value_offs) < ++ (void *)e + sizeof(__u32) || ++ value_start + le16_to_cpu(entry->e_value_offs) + ++ le32_to_cpu(entry->e_value_size) > end)) ++ return -EIO; ++ entry = EXT4_XATTR_NEXT(entry); ++ } ++ + return 0; + } + +@@ -213,7 +225,8 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh) + return -EIO; + if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh))) + return -EIO; +- error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size); ++ error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size, ++ bh->b_data); + if (!error) + set_buffer_verified(bh); + return error; +@@ -329,7 +342,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name, + header = IHDR(inode, raw_inode); + entry = IFIRST(header); + end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; +- error = ext4_xattr_check_names(entry, end); ++ error = ext4_xattr_check_names(entry, end, entry); + if (error) + goto cleanup; + error = ext4_xattr_find_entry(&entry, name_index, name, +@@ -457,7 +470,7 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size) + raw_inode = ext4_raw_inode(&iloc); + header = IHDR(inode, raw_inode); + end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; +- error = ext4_xattr_check_names(IFIRST(header), end); ++ error = ext4_xattr_check_names(IFIRST(header), end, IFIRST(header)); + if (error) + goto cleanup; + error = ext4_xattr_list_entries(dentry, IFIRST(header), +@@ -972,7 +985,8 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, + is->s.here = is->s.first; + is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; + if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) { +- error = ext4_xattr_check_names(IFIRST(header), is->s.end); ++ error = ext4_xattr_check_names(IFIRST(header), is->s.end, ++ IFIRST(header)); + if (error) + return error; + /* Find the named attribute. */ +diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c +index 9b329b55ffe3..bcbef08a4d8f 100644 +--- a/fs/jbd2/recovery.c ++++ b/fs/jbd2/recovery.c +@@ -525,6 +525,7 @@ static int do_one_pass(journal_t *journal, + !jbd2_descr_block_csum_verify(journal, + bh->b_data)) { + err = -EIO; ++ brelse(bh); + goto failed; + } + +diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h +index 413ef89c2d1b..046fee8b6e9b 100644 +--- a/fs/jffs2/jffs2_fs_sb.h ++++ b/fs/jffs2/jffs2_fs_sb.h +@@ -134,8 +134,6 @@ struct jffs2_sb_info { + struct rw_semaphore wbuf_sem; /* Protects the write buffer */ + + struct delayed_work wbuf_dwork; /* write-buffer write-out work */ +- int wbuf_queued; /* non-zero delayed work is queued */ +- spinlock_t wbuf_dwork_lock; /* protects wbuf_dwork and and wbuf_queued */ + + unsigned char *oobbuf; + int oobavail; /* How many bytes are available for JFFS2 in OOB */ +diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c +index a6597d60d76d..09ed55190ee2 100644 +--- a/fs/jffs2/wbuf.c ++++ b/fs/jffs2/wbuf.c +@@ -1162,10 +1162,6 @@ static void delayed_wbuf_sync(struct work_struct *work) + struct jffs2_sb_info *c = work_to_sb(work); + struct super_block *sb = OFNI_BS_2SFFJ(c); + +- spin_lock(&c->wbuf_dwork_lock); +- c->wbuf_queued = 0; +- spin_unlock(&c->wbuf_dwork_lock); +- + if (!(sb->s_flags & MS_RDONLY)) { + jffs2_dbg(1, "%s()\n", __func__); + jffs2_flush_wbuf_gc(c, 0); +@@ -1180,14 +1176,9 @@ void jffs2_dirty_trigger(struct jffs2_sb_info *c) + if (sb->s_flags & MS_RDONLY) + return; + +- spin_lock(&c->wbuf_dwork_lock); +- if (!c->wbuf_queued) { ++ delay = msecs_to_jiffies(dirty_writeback_interval * 10); ++ if (queue_delayed_work(system_long_wq, &c->wbuf_dwork, delay)) + jffs2_dbg(1, "%s()\n", __func__); +- delay = msecs_to_jiffies(dirty_writeback_interval * 10); +- queue_delayed_work(system_long_wq, &c->wbuf_dwork, delay); +- c->wbuf_queued = 1; +- } +- spin_unlock(&c->wbuf_dwork_lock); + } + + int jffs2_nand_flash_setup(struct jffs2_sb_info *c) +@@ -1211,7 +1202,6 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c) + + /* Initialise write buffer */ + init_rwsem(&c->wbuf_sem); +- spin_lock_init(&c->wbuf_dwork_lock); + INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync); + c->wbuf_pagesize = c->mtd->writesize; + c->wbuf_ofs = 0xFFFFFFFF; +@@ -1251,7 +1241,6 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) { + + /* Initialize write buffer */ + init_rwsem(&c->wbuf_sem); +- spin_lock_init(&c->wbuf_dwork_lock); + INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync); + c->wbuf_pagesize = c->mtd->erasesize; + +@@ -1311,7 +1300,6 @@ int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) { + + /* Initialize write buffer */ + init_rwsem(&c->wbuf_sem); +- spin_lock_init(&c->wbuf_dwork_lock); + INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync); + + c->wbuf_pagesize = c->mtd->writesize; +@@ -1346,7 +1334,6 @@ int jffs2_ubivol_setup(struct jffs2_sb_info *c) { + return 0; + + init_rwsem(&c->wbuf_sem); +- spin_lock_init(&c->wbuf_dwork_lock); + INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync); + + c->wbuf_pagesize = c->mtd->writesize; +diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c +index 1812f026960c..6ae664b489af 100644 +--- a/fs/lockd/mon.c ++++ b/fs/lockd/mon.c +@@ -159,6 +159,12 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, + + msg.rpc_proc = &clnt->cl_procinfo[proc]; + status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN); ++ if (status == -ECONNREFUSED) { ++ dprintk("lockd: NSM upcall RPC failed, status=%d, forcing rebind\n", ++ status); ++ rpc_force_rebind(clnt); ++ status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN); ++ } + if (status < 0) + dprintk("lockd: NSM upcall RPC failed, status=%d\n", + status); +diff --git a/fs/namei.c b/fs/namei.c +index dd2f2c5bda55..0dd72c8e65fd 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -3128,7 +3128,8 @@ static int do_tmpfile(int dfd, struct filename *pathname, + if (error) + goto out2; + audit_inode(pathname, nd->path.dentry, 0); +- error = may_open(&nd->path, op->acc_mode, op->open_flag); ++ /* Don't check for other permissions, the inode was just created */ ++ error = may_open(&nd->path, MAY_OPEN, op->open_flag); + if (error) + goto out2; + file->f_path.mnt = nd->path.mnt; +diff --git a/fs/namespace.c b/fs/namespace.c +index c7d4a0ae2c65..d9bf3efbf040 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -2831,6 +2831,9 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, + /* make sure we can reach put_old from new_root */ + if (!is_path_reachable(old_mnt, old.dentry, &new)) + goto out4; ++ /* make certain new is below the root */ ++ if (!is_path_reachable(new_mnt, new.dentry, &root)) ++ goto out4; + root_mp->m_count++; /* pin it so it won't go away */ + lock_mount_hash(); + detach_mnt(new_mnt, &parent_path); +diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c +index f23a6ca37504..86f5d3e474bf 100644 +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -1243,7 +1243,8 @@ static bool need_wrongsec_check(struct svc_rqst *rqstp) + */ + if (argp->opcnt == resp->opcnt) + return false; +- ++ if (next->opnum == OP_ILLEGAL) ++ return false; + nextd = OPDESC(next); + /* + * Rest of 2.6.3.1.1: certain operations will return WRONGSEC +diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c +index 12823845d324..14120a3c6195 100644 +--- a/fs/pstore/inode.c ++++ b/fs/pstore/inode.c +@@ -319,10 +319,10 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count, + compressed ? ".enc.z" : ""); + break; + case PSTORE_TYPE_CONSOLE: +- sprintf(name, "console-%s", psname); ++ sprintf(name, "console-%s-%lld", psname, id); + break; + case PSTORE_TYPE_FTRACE: +- sprintf(name, "ftrace-%s", psname); ++ sprintf(name, "ftrace-%s-%lld", psname, id); + break; + case PSTORE_TYPE_MCE: + sprintf(name, "mce-%s-%lld", psname, id); +diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c +index ce87c9007b0f..89da95700c69 100644 +--- a/fs/quota/dquot.c ++++ b/fs/quota/dquot.c +@@ -637,7 +637,7 @@ int dquot_writeback_dquots(struct super_block *sb, int type) + dqstats_inc(DQST_LOOKUPS); + err = sb->dq_op->write_dquot(dquot); + if (!ret && err) +- err = ret; ++ ret = err; + dqput(dquot); + spin_lock(&dq_list_lock); + } +diff --git a/fs/super.c b/fs/super.c +index 7624267b2043..88a6bc6e3cc9 100644 +--- a/fs/super.c ++++ b/fs/super.c +@@ -81,6 +81,8 @@ static unsigned long super_cache_scan(struct shrinker *shrink, + inodes = list_lru_count_node(&sb->s_inode_lru, sc->nid); + dentries = list_lru_count_node(&sb->s_dentry_lru, sc->nid); + total_objects = dentries + inodes + fs_objects + 1; ++ if (!total_objects) ++ total_objects = 1; + + /* proportion the scan between the caches */ + dentries = mult_frac(sc->nr_to_scan, dentries, total_objects); +diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c +index ff8229340cd5..26b69b2d4a45 100644 +--- a/fs/ubifs/commit.c ++++ b/fs/ubifs/commit.c +@@ -166,15 +166,10 @@ static int do_commit(struct ubifs_info *c) + err = ubifs_orphan_end_commit(c); + if (err) + goto out; +- old_ltail_lnum = c->ltail_lnum; +- err = ubifs_log_end_commit(c, new_ltail_lnum); +- if (err) +- goto out; + err = dbg_check_old_index(c, &zroot); + if (err) + goto out; + +- mutex_lock(&c->mst_mutex); + c->mst_node->cmt_no = cpu_to_le64(c->cmt_no); + c->mst_node->log_lnum = cpu_to_le32(new_ltail_lnum); + c->mst_node->root_lnum = cpu_to_le32(zroot.lnum); +@@ -203,8 +198,9 @@ static int do_commit(struct ubifs_info *c) + c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); + else + c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_NO_ORPHS); +- err = ubifs_write_master(c); +- mutex_unlock(&c->mst_mutex); ++ ++ old_ltail_lnum = c->ltail_lnum; ++ err = ubifs_log_end_commit(c, new_ltail_lnum); + if (err) + goto out; + +diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c +index a902c5919e42..8d59de86dc9a 100644 +--- a/fs/ubifs/log.c ++++ b/fs/ubifs/log.c +@@ -106,10 +106,14 @@ static inline long long empty_log_bytes(const struct ubifs_info *c) + h = (long long)c->lhead_lnum * c->leb_size + c->lhead_offs; + t = (long long)c->ltail_lnum * c->leb_size; + +- if (h >= t) ++ if (h > t) + return c->log_bytes - h + t; +- else ++ else if (h != t) + return t - h; ++ else if (c->lhead_lnum != c->ltail_lnum) ++ return 0; ++ else ++ return c->log_bytes; + } + + /** +@@ -447,9 +451,9 @@ out: + * @ltail_lnum: new log tail LEB number + * + * This function is called on when the commit operation was finished. It +- * moves log tail to new position and unmaps LEBs which contain obsolete data. +- * Returns zero in case of success and a negative error code in case of +- * failure. ++ * moves log tail to new position and updates the master node so that it stores ++ * the new log tail LEB number. Returns zero in case of success and a negative ++ * error code in case of failure. + */ + int ubifs_log_end_commit(struct ubifs_info *c, int ltail_lnum) + { +@@ -477,7 +481,12 @@ int ubifs_log_end_commit(struct ubifs_info *c, int ltail_lnum) + spin_unlock(&c->buds_lock); + + err = dbg_check_bud_bytes(c); ++ if (err) ++ goto out; + ++ err = ubifs_write_master(c); ++ ++out: + mutex_unlock(&c->log_mutex); + return err; + } +diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c +index ab83ace9910a..1a4bb9e8b3b8 100644 +--- a/fs/ubifs/master.c ++++ b/fs/ubifs/master.c +@@ -352,10 +352,9 @@ int ubifs_read_master(struct ubifs_info *c) + * ubifs_write_master - write master node. + * @c: UBIFS file-system description object + * +- * This function writes the master node. The caller has to take the +- * @c->mst_mutex lock before calling this function. Returns zero in case of +- * success and a negative error code in case of failure. The master node is +- * written twice to enable recovery. ++ * This function writes the master node. Returns zero in case of success and a ++ * negative error code in case of failure. The master node is written twice to ++ * enable recovery. + */ + int ubifs_write_master(struct ubifs_info *c) + { +diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c +index 5ded8490c0c6..94d9a64287b7 100644 +--- a/fs/ubifs/super.c ++++ b/fs/ubifs/super.c +@@ -1957,7 +1957,6 @@ static struct ubifs_info *alloc_ubifs_info(struct ubi_volume_desc *ubi) + mutex_init(&c->lp_mutex); + mutex_init(&c->tnc_mutex); + mutex_init(&c->log_mutex); +- mutex_init(&c->mst_mutex); + mutex_init(&c->umount_mutex); + mutex_init(&c->bu_mutex); + mutex_init(&c->write_reserve_mutex); +diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h +index e8c8cfe1435c..7ab9c710c749 100644 +--- a/fs/ubifs/ubifs.h ++++ b/fs/ubifs/ubifs.h +@@ -1042,7 +1042,6 @@ struct ubifs_debug_info; + * + * @mst_node: master node + * @mst_offs: offset of valid master node +- * @mst_mutex: protects the master node area, @mst_node, and @mst_offs + * + * @max_bu_buf_len: maximum bulk-read buffer length + * @bu_mutex: protects the pre-allocated bulk-read buffer and @c->bu +@@ -1282,7 +1281,6 @@ struct ubifs_info { + + struct ubifs_mst_node *mst_node; + int mst_offs; +- struct mutex mst_mutex; + + int max_bu_buf_len; + struct mutex bu_mutex; +diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c +index c6ff3cf5a5bb..0eaaa2d296f0 100644 +--- a/fs/xfs/xfs_mount.c ++++ b/fs/xfs/xfs_mount.c +@@ -321,7 +321,6 @@ reread: + * Initialize the mount structure from the superblock. + */ + xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp)); +- xfs_sb_quota_from_disk(sbp); + + /* + * If we haven't validated the superblock, do so now before we try +diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c +index 1e116794bb66..4afd393846d3 100644 +--- a/fs/xfs/xfs_sb.c ++++ b/fs/xfs/xfs_sb.c +@@ -397,10 +397,11 @@ xfs_sb_quota_from_disk(struct xfs_sb *sbp) + } + } + +-void +-xfs_sb_from_disk( ++static void ++__xfs_sb_from_disk( + struct xfs_sb *to, +- xfs_dsb_t *from) ++ xfs_dsb_t *from, ++ bool convert_xquota) + { + to->sb_magicnum = be32_to_cpu(from->sb_magicnum); + to->sb_blocksize = be32_to_cpu(from->sb_blocksize); +@@ -456,6 +457,17 @@ xfs_sb_from_disk( + to->sb_pad = 0; + to->sb_pquotino = be64_to_cpu(from->sb_pquotino); + to->sb_lsn = be64_to_cpu(from->sb_lsn); ++ /* Convert on-disk flags to in-memory flags? */ ++ if (convert_xquota) ++ xfs_sb_quota_from_disk(to); ++} ++ ++void ++xfs_sb_from_disk( ++ struct xfs_sb *to, ++ xfs_dsb_t *from) ++{ ++ __xfs_sb_from_disk(to, from, true); + } + + static inline void +@@ -571,7 +583,11 @@ xfs_sb_verify( + struct xfs_mount *mp = bp->b_target->bt_mount; + struct xfs_sb sb; + +- xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp)); ++ /* ++ * Use call variant which doesn't convert quota flags from disk ++ * format, because xfs_mount_validate_sb checks the on-disk flags. ++ */ ++ __xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp), false); + + /* + * Only check the in progress field for the primary superblock as +diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h +index bcec4c46cc2e..ca52de5a5c97 100644 +--- a/include/drm/drm_pciids.h ++++ b/include/drm/drm_pciids.h +@@ -74,7 +74,6 @@ + {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \ + {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \ + {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \ +- {0x1002, 0x4C6E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \ + {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ + {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ + {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index 4afa4f8f6090..a693c6d29328 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -1232,10 +1232,9 @@ static inline int queue_alignment_offset(struct request_queue *q) + static inline int queue_limit_alignment_offset(struct queue_limits *lim, sector_t sector) + { + unsigned int granularity = max(lim->physical_block_size, lim->io_min); +- unsigned int alignment = (sector << 9) & (granularity - 1); ++ unsigned int alignment = sector_div(sector, granularity >> 9) << 9; + +- return (granularity + lim->alignment_offset - alignment) +- & (granularity - 1); ++ return (granularity + lim->alignment_offset - alignment) % granularity; + } + + static inline int bdev_alignment_offset(struct block_device *bdev) +diff --git a/include/linux/hid.h b/include/linux/hid.h +index 31b9d299ef6c..00c88fccd162 100644 +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -286,6 +286,7 @@ struct hid_item { + #define HID_QUIRK_HIDINPUT_FORCE 0x00000080 + #define HID_QUIRK_NO_EMPTY_INPUT 0x00000100 + #define HID_QUIRK_NO_INIT_INPUT_REPORTS 0x00000200 ++#define HID_QUIRK_ALWAYS_POLL 0x00000400 + #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 + #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 + #define HID_QUIRK_NO_INIT_REPORTS 0x20000000 +diff --git a/include/linux/mm.h b/include/linux/mm.h +index c1b7414c7bef..0a0b024ec7e8 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1123,6 +1123,7 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping, + + extern void truncate_pagecache(struct inode *inode, loff_t new); + extern void truncate_setsize(struct inode *inode, loff_t newsize); ++void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to); + void truncate_pagecache_range(struct inode *inode, loff_t offset, loff_t end); + int truncate_inode_page(struct address_space *mapping, struct page *page); + int generic_error_remove_page(struct address_space *mapping, struct page *page); +diff --git a/include/linux/of.h b/include/linux/of.h +index 435cb995904d..3f8144dadaef 100644 +--- a/include/linux/of.h ++++ b/include/linux/of.h +@@ -215,14 +215,12 @@ extern int of_property_read_u64(const struct device_node *np, + extern int of_property_read_string(struct device_node *np, + const char *propname, + const char **out_string); +-extern int of_property_read_string_index(struct device_node *np, +- const char *propname, +- int index, const char **output); + extern int of_property_match_string(struct device_node *np, + const char *propname, + const char *string); +-extern int of_property_count_strings(struct device_node *np, +- const char *propname); ++extern int of_property_read_string_helper(struct device_node *np, ++ const char *propname, ++ const char **out_strs, size_t sz, int index); + extern int of_device_is_compatible(const struct device_node *device, + const char *); + extern int of_device_is_available(const struct device_node *device); +@@ -422,15 +420,9 @@ static inline int of_property_read_string(struct device_node *np, + return -ENOSYS; + } + +-static inline int of_property_read_string_index(struct device_node *np, +- const char *propname, int index, +- const char **out_string) +-{ +- return -ENOSYS; +-} +- +-static inline int of_property_count_strings(struct device_node *np, +- const char *propname) ++static inline int of_property_read_string_helper(struct device_node *np, ++ const char *propname, ++ const char **out_strs, size_t sz, int index) + { + return -ENOSYS; + } +@@ -536,6 +528,70 @@ static inline struct device_node *of_find_matching_node( + } + + /** ++ * of_property_read_string_array() - Read an array of strings from a multiple ++ * strings property. ++ * @np: device node from which the property value is to be read. ++ * @propname: name of the property to be searched. ++ * @out_strs: output array of string pointers. ++ * @sz: number of array elements to read. ++ * ++ * Search for a property in a device tree node and retrieve a list of ++ * terminated string values (pointer to data, not a copy) in that property. ++ * ++ * If @out_strs is NULL, the number of strings in the property is returned. ++ */ ++static inline int of_property_read_string_array(struct device_node *np, ++ const char *propname, const char **out_strs, ++ size_t sz) ++{ ++ return of_property_read_string_helper(np, propname, out_strs, sz, 0); ++} ++ ++/** ++ * of_property_count_strings() - Find and return the number of strings from a ++ * multiple strings property. ++ * @np: device node from which the property value is to be read. ++ * @propname: name of the property to be searched. ++ * ++ * Search for a property in a device tree node and retrieve the number of null ++ * terminated string contain in it. Returns the number of strings on ++ * success, -EINVAL if the property does not exist, -ENODATA if property ++ * does not have a value, and -EILSEQ if the string is not null-terminated ++ * within the length of the property data. ++ */ ++static inline int of_property_count_strings(struct device_node *np, ++ const char *propname) ++{ ++ return of_property_read_string_helper(np, propname, NULL, 0, 0); ++} ++ ++/** ++ * of_property_read_string_index() - Find and read a string from a multiple ++ * strings property. ++ * @np: device node from which the property value is to be read. ++ * @propname: name of the property to be searched. ++ * @index: index of the string in the list of strings ++ * @out_string: pointer to null terminated return string, modified only if ++ * return value is 0. ++ * ++ * Search for a property in a device tree node and retrieve a null ++ * terminated string value (pointer to data, not a copy) in the list of strings ++ * contained in that property. ++ * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if ++ * property does not have a value, and -EILSEQ if the string is not ++ * null-terminated within the length of the property data. ++ * ++ * The out_string pointer is modified only if a valid string can be decoded. ++ */ ++static inline int of_property_read_string_index(struct device_node *np, ++ const char *propname, ++ int index, const char **output) ++{ ++ int rc = of_property_read_string_helper(np, propname, output, 1, index); ++ return rc < 0 ? rc : 0; ++} ++ ++/** + * of_property_read_bool - Findfrom a property + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. +diff --git a/include/linux/oom.h b/include/linux/oom.h +index 4cd62677feb9..17f0949bd822 100644 +--- a/include/linux/oom.h ++++ b/include/linux/oom.h +@@ -50,6 +50,9 @@ static inline bool oom_task_origin(const struct task_struct *p) + extern unsigned long oom_badness(struct task_struct *p, + struct mem_cgroup *memcg, const nodemask_t *nodemask, + unsigned long totalpages); ++ ++extern int oom_kills_count(void); ++extern void note_oom_kill(void); + extern void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, + unsigned int points, unsigned long totalpages, + struct mem_cgroup *memcg, nodemask_t *nodemask, +diff --git a/include/linux/string.h b/include/linux/string.h +index ac889c5ea11b..0ed878d0465c 100644 +--- a/include/linux/string.h ++++ b/include/linux/string.h +@@ -129,7 +129,7 @@ int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...) __printf(3, 4); + #endif + + extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos, +- const void *from, size_t available); ++ const void *from, size_t available); + + /** + * strstarts - does @str start with @prefix? +@@ -141,7 +141,8 @@ static inline bool strstarts(const char *str, const char *prefix) + return strncmp(str, prefix, strlen(prefix)) == 0; + } + +-extern size_t memweight(const void *ptr, size_t bytes); ++size_t memweight(const void *ptr, size_t bytes); ++void memzero_explicit(void *s, size_t count); + + /** + * kbasename - return the last part of a pathname. +diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h +index 8097b9df6773..51009d280ac7 100644 +--- a/include/linux/sunrpc/xprt.h ++++ b/include/linux/sunrpc/xprt.h +@@ -340,6 +340,7 @@ int xs_swapper(struct rpc_xprt *xprt, int enable); + #define XPRT_CONNECTION_ABORT (7) + #define XPRT_CONNECTION_CLOSE (8) + #define XPRT_CONGESTED (9) ++#define XPRT_CONNECTION_REUSE (10) + + static inline void xprt_set_connected(struct rpc_xprt *xprt) + { +diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h +index 49587dc22f5d..8b96ae2a38fe 100644 +--- a/include/linux/usb/quirks.h ++++ b/include/linux/usb/quirks.h +@@ -33,4 +33,7 @@ + /* device generates spurious wakeup, ignore remote wakeup capability */ + #define USB_QUIRK_IGNORE_REMOTE_WAKEUP 0x00000200 + ++/* device can't handle device_qualifier descriptor requests */ ++#define USB_QUIRK_DEVICE_QUALIFIER 0x00000100 ++ + #endif /* __LINUX_USB_QUIRKS_H */ +diff --git a/include/net/ipv6.h b/include/net/ipv6.h +index 9ac65781d44b..a60948d7bcea 100644 +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -660,6 +660,8 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add + return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr)); + } + ++void ipv6_proxy_select_ident(struct sk_buff *skb); ++ + int ip6_dst_hoplimit(struct dst_entry *dst); + + /* +diff --git a/include/uapi/drm/vmwgfx_drm.h b/include/uapi/drm/vmwgfx_drm.h +index 87792a5fee3b..33b739522840 100644 +--- a/include/uapi/drm/vmwgfx_drm.h ++++ b/include/uapi/drm/vmwgfx_drm.h +@@ -29,7 +29,7 @@ + #define __VMWGFX_DRM_H__ + + #ifndef __KERNEL__ +-#include ++#include + #endif + + #define DRM_VMW_MAX_SURFACE_FACES 6 +diff --git a/kernel/freezer.c b/kernel/freezer.c +index aa6a8aadb911..8f9279b9c6d7 100644 +--- a/kernel/freezer.c ++++ b/kernel/freezer.c +@@ -42,6 +42,9 @@ bool freezing_slow_path(struct task_struct *p) + if (p->flags & (PF_NOFREEZE | PF_SUSPEND_TASK)) + return false; + ++ if (test_thread_flag(TIF_MEMDIE)) ++ return false; ++ + if (pm_nosig_freezing || cgroup_freezing(p)) + return true; + +diff --git a/kernel/module.c b/kernel/module.c +index 6716a1fa618b..1d679a6c942f 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -1841,7 +1841,9 @@ static void free_module(struct module *mod) + + /* We leave it in list to prevent duplicate loads, but make sure + * that noone uses it while it's being deconstructed. */ ++ mutex_lock(&module_mutex); + mod->state = MODULE_STATE_UNFORMED; ++ mutex_unlock(&module_mutex); + + /* Remove dynamic debug info */ + ddebug_remove_module(mod->name); +diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c +index 424c2d4265c9..77e6b83c0431 100644 +--- a/kernel/posix-timers.c ++++ b/kernel/posix-timers.c +@@ -634,6 +634,7 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock, + goto out; + } + } else { ++ memset(&event.sigev_value, 0, sizeof(event.sigev_value)); + event.sigev_notify = SIGEV_SIGNAL; + event.sigev_signo = SIGALRM; + event.sigev_value.sival_int = new_timer->it_id; +diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c +index 37170d4dd9a6..126586a31408 100644 +--- a/kernel/power/hibernate.c ++++ b/kernel/power/hibernate.c +@@ -492,8 +492,14 @@ int hibernation_restore(int platform_mode) + error = dpm_suspend_start(PMSG_QUIESCE); + if (!error) { + error = resume_target_kernel(platform_mode); +- dpm_resume_end(PMSG_RECOVER); ++ /* ++ * The above should either succeed and jump to the new kernel, ++ * or return with an error. Otherwise things are just ++ * undefined, so let's be paranoid. ++ */ ++ BUG_ON(!error); + } ++ dpm_resume_end(PMSG_RECOVER); + pm_restore_gfp_mask(); + ftrace_start(); + resume_console(); +diff --git a/kernel/power/process.c b/kernel/power/process.c +index 14f9a8d4725d..f1fe7ec110bb 100644 +--- a/kernel/power/process.c ++++ b/kernel/power/process.c +@@ -107,6 +107,28 @@ static int try_to_freeze_tasks(bool user_only) + return todo ? -EBUSY : 0; + } + ++/* ++ * Returns true if all freezable tasks (except for current) are frozen already ++ */ ++static bool check_frozen_processes(void) ++{ ++ struct task_struct *g, *p; ++ bool ret = true; ++ ++ read_lock(&tasklist_lock); ++ for_each_process_thread(g, p) { ++ if (p != current && !freezer_should_skip(p) && ++ !frozen(p)) { ++ ret = false; ++ goto done; ++ } ++ } ++done: ++ read_unlock(&tasklist_lock); ++ ++ return ret; ++} ++ + /** + * freeze_processes - Signal user space processes to enter the refrigerator. + * The current thread will not be frozen. The same process that calls +@@ -117,6 +139,7 @@ static int try_to_freeze_tasks(bool user_only) + int freeze_processes(void) + { + int error; ++ int oom_kills_saved; + + error = __usermodehelper_disable(UMH_FREEZING); + if (error) +@@ -130,12 +153,27 @@ int freeze_processes(void) + + printk("Freezing user space processes ... "); + pm_freezing = true; ++ oom_kills_saved = oom_kills_count(); + error = try_to_freeze_tasks(true); + if (!error) { +- printk("done."); + __usermodehelper_set_disable_depth(UMH_DISABLED); + oom_killer_disable(); ++ ++ /* ++ * There might have been an OOM kill while we were ++ * freezing tasks and the killed task might be still ++ * on the way out so we have to double check for race. ++ */ ++ if (oom_kills_count() != oom_kills_saved && ++ !check_frozen_processes()) { ++ __usermodehelper_set_disable_depth(UMH_ENABLED); ++ printk("OOM in progress."); ++ error = -EBUSY; ++ goto done; ++ } ++ printk("done."); + } ++done: + printk("\n"); + BUG_ON(in_atomic()); + +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 677ebad70ce1..9a3f3c4e1f5a 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -1895,6 +1895,8 @@ unsigned long to_ratio(u64 period, u64 runtime) + #ifdef CONFIG_SMP + inline struct dl_bw *dl_bw_of(int i) + { ++ rcu_lockdep_assert(rcu_read_lock_sched_held(), ++ "sched RCU must be held"); + return &cpu_rq(i)->rd->dl_bw; + } + +@@ -1903,6 +1905,8 @@ static inline int dl_bw_cpus(int i) + struct root_domain *rd = cpu_rq(i)->rd; + int cpus = 0; + ++ rcu_lockdep_assert(rcu_read_lock_sched_held(), ++ "sched RCU must be held"); + for_each_cpu_and(i, rd->span, cpu_active_mask) + cpus++; + +@@ -3937,13 +3941,14 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask) + * root_domain. + */ + #ifdef CONFIG_SMP +- if (task_has_dl_policy(p)) { +- const struct cpumask *span = task_rq(p)->rd->span; +- +- if (dl_bandwidth_enabled() && !cpumask_subset(span, new_mask)) { ++ if (task_has_dl_policy(p) && dl_bandwidth_enabled()) { ++ rcu_read_lock(); ++ if (!cpumask_subset(task_rq(p)->rd->span, new_mask)) { + retval = -EBUSY; ++ rcu_read_unlock(); + goto out_unlock; + } ++ rcu_read_unlock(); + } + #endif + again: +@@ -7458,6 +7463,8 @@ static int sched_dl_global_constraints(void) + int cpu, ret = 0; + unsigned long flags; + ++ rcu_read_lock(); ++ + /* + * Here we want to check the bandwidth not being set to some + * value smaller than the currently allocated bandwidth in +@@ -7479,6 +7486,8 @@ static int sched_dl_global_constraints(void) + break; + } + ++ rcu_read_unlock(); ++ + return ret; + } + +@@ -7494,6 +7503,7 @@ static void sched_dl_do_global(void) + if (global_rt_runtime() != RUNTIME_INF) + new_bw = to_ratio(global_rt_period(), global_rt_runtime()); + ++ rcu_read_lock(); + /* + * FIXME: As above... + */ +@@ -7504,6 +7514,7 @@ static void sched_dl_do_global(void) + dl_b->bw = new_bw; + raw_spin_unlock_irqrestore(&dl_b->lock, flags); + } ++ rcu_read_unlock(); + } + + static int sched_rt_global_validate(void) +diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c +index 759d5e004517..7e3cd7aaec83 100644 +--- a/kernel/trace/trace_syscalls.c ++++ b/kernel/trace/trace_syscalls.c +@@ -313,7 +313,7 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id) + int size; + + syscall_nr = trace_get_syscall_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + + /* Here we're inside tp handler's rcu_read_lock_sched (__DO_TRACE) */ +@@ -360,7 +360,7 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret) + int syscall_nr; + + syscall_nr = trace_get_syscall_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + + /* Here we're inside tp handler's rcu_read_lock_sched (__DO_TRACE()) */ +@@ -567,7 +567,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) + int size; + + syscall_nr = trace_get_syscall_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + if (!test_bit(syscall_nr, enabled_perf_enter_syscalls)) + return; +@@ -641,7 +641,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) + int size; + + syscall_nr = trace_get_syscall_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + if (!test_bit(syscall_nr, enabled_perf_exit_syscalls)) + return; +diff --git a/lib/bitmap.c b/lib/bitmap.c +index 06f7e4fe8d2d..e5c4ebe586ba 100644 +--- a/lib/bitmap.c ++++ b/lib/bitmap.c +@@ -131,7 +131,9 @@ void __bitmap_shift_right(unsigned long *dst, + lower = src[off + k]; + if (left && off + k == lim - 1) + lower &= mask; +- dst[k] = upper << (BITS_PER_LONG - rem) | lower >> rem; ++ dst[k] = lower >> rem; ++ if (rem) ++ dst[k] |= upper << (BITS_PER_LONG - rem); + if (left && k == lim - 1) + dst[k] &= mask; + } +@@ -172,7 +174,9 @@ void __bitmap_shift_left(unsigned long *dst, + upper = src[k]; + if (left && k == lim - 1) + upper &= (1UL << left) - 1; +- dst[k + off] = lower >> (BITS_PER_LONG - rem) | upper << rem; ++ dst[k + off] = upper << rem; ++ if (rem) ++ dst[k + off] |= lower >> (BITS_PER_LONG - rem); + if (left && k + off == lim - 1) + dst[k + off] &= (1UL << left) - 1; + } +diff --git a/lib/string.c b/lib/string.c +index e5878de4f101..43d0781daf47 100644 +--- a/lib/string.c ++++ b/lib/string.c +@@ -586,6 +586,22 @@ void *memset(void *s, int c, size_t count) + EXPORT_SYMBOL(memset); + #endif + ++/** ++ * memzero_explicit - Fill a region of memory (e.g. sensitive ++ * keying data) with 0s. ++ * @s: Pointer to the start of the area. ++ * @count: The size of the area. ++ * ++ * memzero_explicit() doesn't need an arch-specific version as ++ * it just invokes the one of memset() implicitly. ++ */ ++void memzero_explicit(void *s, size_t count) ++{ ++ memset(s, 0, count); ++ OPTIMIZER_HIDE_VAR(s); ++} ++EXPORT_SYMBOL(memzero_explicit); ++ + #ifndef __HAVE_ARCH_MEMCPY + /** + * memcpy - Copy one area of memory to another +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index 718bfa16a36f..331faa5c0d5e 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -199,7 +199,7 @@ retry: + preempt_disable(); + if (cmpxchg(&huge_zero_page, NULL, zero_page)) { + preempt_enable(); +- __free_page(zero_page); ++ __free_pages(zero_page, compound_order(zero_page)); + goto retry; + } + +@@ -231,7 +231,7 @@ static unsigned long shrink_huge_zero_page_scan(struct shrinker *shrink, + if (atomic_cmpxchg(&huge_zero_refcount, 1, 0) == 1) { + struct page *zero_page = xchg(&huge_zero_page, NULL); + BUG_ON(zero_page == NULL); +- __free_page(zero_page); ++ __free_pages(zero_page, compound_order(zero_page)); + return HPAGE_PMD_NR; + } + +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index 9b35da28b587..b58d4fbe6c48 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -292,6 +292,9 @@ struct mem_cgroup { + /* vmpressure notifications */ + struct vmpressure vmpressure; + ++ /* css_online() has been completed */ ++ int initialized; ++ + /* + * the counter to account for mem+swap usage. + */ +@@ -1127,9 +1130,21 @@ skip_node: + * skipping css reference should be safe. + */ + if (next_css) { +- if ((next_css == &root->css) || +- ((next_css->flags & CSS_ONLINE) && css_tryget(next_css))) +- return mem_cgroup_from_css(next_css); ++ struct mem_cgroup *memcg = mem_cgroup_from_css(next_css); ++ ++ if (next_css == &root->css) ++ return memcg; ++ ++ if (css_tryget(next_css)) { ++ /* ++ * Make sure the memcg is initialized: ++ * mem_cgroup_css_online() orders the the ++ * initialization against setting the flag. ++ */ ++ if (smp_load_acquire(&memcg->initialized)) ++ return memcg; ++ css_put(next_css); ++ } + + prev_css = next_css; + goto skip_node; +@@ -6538,6 +6553,7 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css) + { + struct mem_cgroup *memcg = mem_cgroup_from_css(css); + struct mem_cgroup *parent = mem_cgroup_from_css(css_parent(css)); ++ int ret; + + if (css->cgroup->id > MEM_CGROUP_ID_MAX) + return -ENOSPC; +@@ -6574,7 +6590,18 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css) + } + mutex_unlock(&memcg_create_mutex); + +- return memcg_init_kmem(memcg, &mem_cgroup_subsys); ++ ret = memcg_init_kmem(memcg, &mem_cgroup_subsys); ++ if (ret) ++ return ret; ++ ++ /* ++ * Make sure the memcg is initialized: mem_cgroup_iter() ++ * orders reading memcg->initialized against its callers ++ * reading the memcg members. ++ */ ++ smp_store_release(&memcg->initialized, 1); ++ ++ return 0; + } + + /* +diff --git a/mm/oom_kill.c b/mm/oom_kill.c +index 3291e82d4352..171c00f2e495 100644 +--- a/mm/oom_kill.c ++++ b/mm/oom_kill.c +@@ -406,6 +406,23 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order, + dump_tasks(memcg, nodemask); + } + ++/* ++ * Number of OOM killer invocations (including memcg OOM killer). ++ * Primarily used by PM freezer to check for potential races with ++ * OOM killed frozen task. ++ */ ++static atomic_t oom_kills = ATOMIC_INIT(0); ++ ++int oom_kills_count(void) ++{ ++ return atomic_read(&oom_kills); ++} ++ ++void note_oom_kill(void) ++{ ++ atomic_inc(&oom_kills); ++} ++ + #define K(x) ((x) << (PAGE_SHIFT-10)) + /* + * Must be called while holding a reference to p, which will be released upon +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index ff0f6b13f32f..7b2611a055a7 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -1957,7 +1957,7 @@ zonelist_scan: + if (alloc_flags & ALLOC_FAIR) { + if (!zone_local(preferred_zone, zone)) + continue; +- if (zone_page_state(zone, NR_ALLOC_BATCH) <= 0) ++ if (atomic_long_read(&zone->vm_stat[NR_ALLOC_BATCH]) <= 0) + continue; + } + /* +@@ -2196,6 +2196,14 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order, + } + + /* ++ * PM-freezer should be notified that there might be an OOM killer on ++ * its way to kill and wake somebody up. This is too early and we might ++ * end up not killing anything but false positives are acceptable. ++ * See freeze_processes. ++ */ ++ note_oom_kill(); ++ ++ /* + * Go through the zonelist yet one more time, keep very high watermark + * here, this is only to catch a parallel oom killing, we must fail if + * we're still under heavy pressure. +@@ -5662,9 +5670,8 @@ static void __setup_per_zone_wmarks(void) + zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) + (tmp >> 1); + + __mod_zone_page_state(zone, NR_ALLOC_BATCH, +- high_wmark_pages(zone) - +- low_wmark_pages(zone) - +- zone_page_state(zone, NR_ALLOC_BATCH)); ++ high_wmark_pages(zone) - low_wmark_pages(zone) - ++ atomic_long_read(&zone->vm_stat[NR_ALLOC_BATCH])); + + setup_zone_migrate_reserve(zone); + spin_unlock_irqrestore(&zone->lock, flags); +diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c +index cfd162882c00..0e9a319d5f8d 100644 +--- a/mm/page_cgroup.c ++++ b/mm/page_cgroup.c +@@ -171,6 +171,7 @@ static void free_page_cgroup(void *addr) + sizeof(struct page_cgroup) * PAGES_PER_SECTION; + + BUG_ON(PageReserved(page)); ++ kmemleak_free(addr); + free_pages_exact(addr, table_size); + } + } +diff --git a/mm/percpu.c b/mm/percpu.c +index 8cd4308471c3..a2a54a85f691 100644 +--- a/mm/percpu.c ++++ b/mm/percpu.c +@@ -1917,8 +1917,6 @@ void __init setup_per_cpu_areas(void) + + if (pcpu_setup_first_chunk(ai, fc) < 0) + panic("Failed to initialize percpu areas."); +- +- pcpu_free_alloc_info(ai); + } + + #endif /* CONFIG_SMP */ +diff --git a/mm/truncate.c b/mm/truncate.c +index 353b683afd6e..ac18edc30649 100644 +--- a/mm/truncate.c ++++ b/mm/truncate.c +@@ -20,6 +20,7 @@ + #include /* grr. try_to_release_page, + do_invalidatepage */ + #include ++#include + #include "internal.h" + + +@@ -613,12 +614,67 @@ EXPORT_SYMBOL(truncate_pagecache); + */ + void truncate_setsize(struct inode *inode, loff_t newsize) + { ++ loff_t oldsize = inode->i_size; ++ + i_size_write(inode, newsize); ++ if (newsize > oldsize) ++ pagecache_isize_extended(inode, oldsize, newsize); + truncate_pagecache(inode, newsize); + } + EXPORT_SYMBOL(truncate_setsize); + + /** ++ * pagecache_isize_extended - update pagecache after extension of i_size ++ * @inode: inode for which i_size was extended ++ * @from: original inode size ++ * @to: new inode size ++ * ++ * Handle extension of inode size either caused by extending truncate or by ++ * write starting after current i_size. We mark the page straddling current ++ * i_size RO so that page_mkwrite() is called on the nearest write access to ++ * the page. This way filesystem can be sure that page_mkwrite() is called on ++ * the page before user writes to the page via mmap after the i_size has been ++ * changed. ++ * ++ * The function must be called after i_size is updated so that page fault ++ * coming after we unlock the page will already see the new i_size. ++ * The function must be called while we still hold i_mutex - this not only ++ * makes sure i_size is stable but also that userspace cannot observe new ++ * i_size value before we are prepared to store mmap writes at new inode size. ++ */ ++void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to) ++{ ++ int bsize = 1 << inode->i_blkbits; ++ loff_t rounded_from; ++ struct page *page; ++ pgoff_t index; ++ ++ WARN_ON(to > inode->i_size); ++ ++ if (from >= to || bsize == PAGE_CACHE_SIZE) ++ return; ++ /* Page straddling @from will not have any hole block created? */ ++ rounded_from = round_up(from, bsize); ++ if (to <= rounded_from || !(rounded_from & (PAGE_CACHE_SIZE - 1))) ++ return; ++ ++ index = from >> PAGE_CACHE_SHIFT; ++ page = find_lock_page(inode->i_mapping, index); ++ /* Page not cached? Nothing to do */ ++ if (!page) ++ return; ++ /* ++ * See clear_page_dirty_for_io() for details why set_page_dirty() ++ * is needed. ++ */ ++ if (page_mkclean(page)) ++ set_page_dirty(page); ++ unlock_page(page); ++ page_cache_release(page); ++} ++EXPORT_SYMBOL(pagecache_isize_extended); ++ ++/** + * truncate_pagecache_range - unmap and remove pagecache that is hole-punched + * @inode: inode + * @lstart: offset of beginning of hole +diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c +index 0a31298737ac..2e87eecec8f6 100644 +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -291,7 +291,11 @@ int ceph_msgr_init(void) + if (ceph_msgr_slab_init()) + return -ENOMEM; + +- ceph_msgr_wq = alloc_workqueue("ceph-msgr", 0, 0); ++ /* ++ * The number of active work items is limited by the number of ++ * connections, so leave @max_active at default. ++ */ ++ ceph_msgr_wq = alloc_workqueue("ceph-msgr", WQ_MEM_RECLAIM, 0); + if (ceph_msgr_wq) + return 0; + +diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c +index 9d43468722ed..017fa5e17594 100644 +--- a/net/ipv4/fib_semantics.c ++++ b/net/ipv4/fib_semantics.c +@@ -535,7 +535,7 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi) + return 1; + + attrlen = rtnh_attrlen(rtnh); +- if (attrlen < 0) { ++ if (attrlen > 0) { + struct nlattr *nla, *attrs = rtnh_attrs(rtnh); + + nla = nla_find(attrs, attrlen, RTA_GATEWAY); +diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c +index 2d24f293f977..8c8493ea6b1c 100644 +--- a/net/ipv4/gre_offload.c ++++ b/net/ipv4/gre_offload.c +@@ -50,7 +50,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, + + greh = (struct gre_base_hdr *)skb_transport_header(skb); + +- ghl = skb_inner_network_header(skb) - skb_transport_header(skb); ++ ghl = skb_inner_mac_header(skb) - skb_transport_header(skb); + if (unlikely(ghl < sizeof(*greh))) + goto out; + +diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +index ed88d781248f..844323b6cfb9 100644 +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -1487,6 +1487,7 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, + struct sk_buff *nskb; + struct sock *sk; + struct inet_sock *inet; ++ int err; + + if (ip_options_echo(&replyopts.opt.opt, skb)) + return; +@@ -1525,8 +1526,13 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, + sock_net_set(sk, net); + __skb_queue_head_init(&sk->sk_write_queue); + sk->sk_sndbuf = sysctl_wmem_default; +- ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, len, 0, +- &ipc, &rt, MSG_DONTWAIT); ++ err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, ++ len, 0, &ipc, &rt, MSG_DONTWAIT); ++ if (unlikely(err)) { ++ ip_flush_pending_frames(sk); ++ goto out; ++ } ++ + nskb = skb_peek(&sk->sk_write_queue); + if (nskb) { + if (arg->csumoffset >= 0) +@@ -1538,7 +1544,7 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, + skb_set_queue_mapping(nskb, skb_get_queue_mapping(skb)); + ip_push_pending_frames(sk, &fl4); + } +- ++out: + put_cpu_var(unicast_sock); + + ip_rt_put(rt); +diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c +index 65b664d30fa1..791a419f0699 100644 +--- a/net/ipv4/ip_tunnel_core.c ++++ b/net/ipv4/ip_tunnel_core.c +@@ -91,11 +91,12 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto) + skb_pull_rcsum(skb, hdr_len); + + if (inner_proto == htons(ETH_P_TEB)) { +- struct ethhdr *eh = (struct ethhdr *)skb->data; ++ struct ethhdr *eh; + + if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) + return -ENOMEM; + ++ eh = (struct ethhdr *)skb->data; + if (likely(ntohs(eh->h_proto) >= ETH_P_802_3_MIN)) + skb->protocol = eh->h_proto; + else +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index f7d71ec72a47..29d240b87af1 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -2954,61 +2954,42 @@ EXPORT_SYMBOL(compat_tcp_getsockopt); + #endif + + #ifdef CONFIG_TCP_MD5SIG +-static struct tcp_md5sig_pool __percpu *tcp_md5sig_pool __read_mostly; ++static DEFINE_PER_CPU(struct tcp_md5sig_pool, tcp_md5sig_pool); + static DEFINE_MUTEX(tcp_md5sig_mutex); +- +-static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool __percpu *pool) +-{ +- int cpu; +- +- for_each_possible_cpu(cpu) { +- struct tcp_md5sig_pool *p = per_cpu_ptr(pool, cpu); +- +- if (p->md5_desc.tfm) +- crypto_free_hash(p->md5_desc.tfm); +- } +- free_percpu(pool); +-} ++static bool tcp_md5sig_pool_populated = false; + + static void __tcp_alloc_md5sig_pool(void) + { + int cpu; +- struct tcp_md5sig_pool __percpu *pool; +- +- pool = alloc_percpu(struct tcp_md5sig_pool); +- if (!pool) +- return; + + for_each_possible_cpu(cpu) { +- struct crypto_hash *hash; +- +- hash = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); +- if (IS_ERR_OR_NULL(hash)) +- goto out_free; ++ if (!per_cpu(tcp_md5sig_pool, cpu).md5_desc.tfm) { ++ struct crypto_hash *hash; + +- per_cpu_ptr(pool, cpu)->md5_desc.tfm = hash; ++ hash = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR_OR_NULL(hash)) ++ return; ++ per_cpu(tcp_md5sig_pool, cpu).md5_desc.tfm = hash; ++ } + } +- /* before setting tcp_md5sig_pool, we must commit all writes +- * to memory. See ACCESS_ONCE() in tcp_get_md5sig_pool() ++ /* before setting tcp_md5sig_pool_populated, we must commit all writes ++ * to memory. See smp_rmb() in tcp_get_md5sig_pool() + */ + smp_wmb(); +- tcp_md5sig_pool = pool; +- return; +-out_free: +- __tcp_free_md5sig_pool(pool); ++ tcp_md5sig_pool_populated = true; + } + + bool tcp_alloc_md5sig_pool(void) + { +- if (unlikely(!tcp_md5sig_pool)) { ++ if (unlikely(!tcp_md5sig_pool_populated)) { + mutex_lock(&tcp_md5sig_mutex); + +- if (!tcp_md5sig_pool) ++ if (!tcp_md5sig_pool_populated) + __tcp_alloc_md5sig_pool(); + + mutex_unlock(&tcp_md5sig_mutex); + } +- return tcp_md5sig_pool != NULL; ++ return tcp_md5sig_pool_populated; + } + EXPORT_SYMBOL(tcp_alloc_md5sig_pool); + +@@ -3022,13 +3003,13 @@ EXPORT_SYMBOL(tcp_alloc_md5sig_pool); + */ + struct tcp_md5sig_pool *tcp_get_md5sig_pool(void) + { +- struct tcp_md5sig_pool __percpu *p; +- + local_bh_disable(); +- p = ACCESS_ONCE(tcp_md5sig_pool); +- if (p) +- return __this_cpu_ptr(p); + ++ if (tcp_md5sig_pool_populated) { ++ /* coupled with smp_wmb() in __tcp_alloc_md5sig_pool() */ ++ smp_rmb(); ++ return this_cpu_ptr(&tcp_md5sig_pool); ++ } + local_bh_enable(); + return NULL; + } +diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c +index 798eb0f79078..ae4a06be14df 100644 +--- a/net/ipv6/output_core.c ++++ b/net/ipv6/output_core.c +@@ -3,10 +3,43 @@ + * not configured or static. These functions are needed by GSO/GRO implementation. + */ + #include ++#include + #include + #include + #include + ++/* This function exists only for tap drivers that must support broken ++ * clients requesting UFO without specifying an IPv6 fragment ID. ++ * ++ * This is similar to ipv6_select_ident() but we use an independent hash ++ * seed to limit information leakage. ++ * ++ * The network header must be set before calling this. ++ */ ++void ipv6_proxy_select_ident(struct sk_buff *skb) ++{ ++ static u32 ip6_proxy_idents_hashrnd __read_mostly; ++ struct in6_addr buf[2]; ++ struct in6_addr *addrs; ++ u32 hash, id; ++ ++ addrs = skb_header_pointer(skb, ++ skb_network_offset(skb) + ++ offsetof(struct ipv6hdr, saddr), ++ sizeof(buf), buf); ++ if (!addrs) ++ return; ++ ++ net_get_random_once(&ip6_proxy_idents_hashrnd, ++ sizeof(ip6_proxy_idents_hashrnd)); ++ ++ hash = __ipv6_addr_jhash(&addrs[1], ip6_proxy_idents_hashrnd); ++ hash = __ipv6_addr_jhash(&addrs[0], hash); ++ ++ id = ip_idents_reserve(hash, 1); ++ skb_shinfo(skb)->ip6_frag_id = htonl(id); ++} ++EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); + + int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) + { +diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c +index 22b223f13c9f..74350c3863b8 100644 +--- a/net/mac80211/rate.c ++++ b/net/mac80211/rate.c +@@ -462,7 +462,7 @@ static void rate_fixup_ratelist(struct ieee80211_vif *vif, + */ + if (!(rates[0].flags & IEEE80211_TX_RC_MCS)) { + u32 basic_rates = vif->bss_conf.basic_rates; +- s8 baserate = basic_rates ? ffs(basic_rates - 1) : 0; ++ s8 baserate = basic_rates ? ffs(basic_rates) - 1 : 0; + + rate = &sband->bitrates[rates[0].idx]; + +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index c375d731587f..7c177bc43806 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -707,7 +707,7 @@ static int netlink_mmap_sendmsg(struct sock *sk, struct msghdr *msg, + * after validation, the socket and the ring may only be used by a + * single process, otherwise we fall back to copying. + */ +- if (atomic_long_read(&sk->sk_socket->file->f_count) > 2 || ++ if (atomic_long_read(&sk->sk_socket->file->f_count) > 1 || + atomic_read(&nlk->mapped) > 1) + excl = false; + +diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c +index 3ea5cda787c7..5ff8b87c3d04 100644 +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -533,6 +533,8 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) + + if (args->flags & RPC_CLNT_CREATE_AUTOBIND) + clnt->cl_autobind = 1; ++ if (args->flags & RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT) ++ clnt->cl_noretranstimeo = 1; + if (args->flags & RPC_CLNT_CREATE_DISCRTRY) + clnt->cl_discrtry = 1; + if (!(args->flags & RPC_CLNT_CREATE_QUIET)) +@@ -571,6 +573,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, + /* Turn off autobind on clones */ + new->cl_autobind = 0; + new->cl_softrtry = clnt->cl_softrtry; ++ new->cl_noretranstimeo = clnt->cl_noretranstimeo; + new->cl_discrtry = clnt->cl_discrtry; + new->cl_chatty = clnt->cl_chatty; + return new; +diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c +index 0addefca8e77..41c2f9d7a148 100644 +--- a/net/sunrpc/xprtsock.c ++++ b/net/sunrpc/xprtsock.c +@@ -842,6 +842,8 @@ static void xs_error_report(struct sock *sk) + dprintk("RPC: xs_error_report client %p, error=%d...\n", + xprt, -err); + trace_rpc_socket_error(xprt, sk->sk_socket, err); ++ if (test_bit(XPRT_CONNECTION_REUSE, &xprt->state)) ++ goto out; + xprt_wake_pending_tasks(xprt, err); + out: + read_unlock_bh(&sk->sk_callback_lock); +@@ -2251,7 +2253,9 @@ static void xs_tcp_setup_socket(struct work_struct *work) + abort_and_exit = test_and_clear_bit(XPRT_CONNECTION_ABORT, + &xprt->state); + /* "close" the socket, preserving the local port */ ++ set_bit(XPRT_CONNECTION_REUSE, &xprt->state); + xs_tcp_reuse_connection(transport); ++ clear_bit(XPRT_CONNECTION_REUSE, &xprt->state); + + if (abort_and_exit) + goto out_eagain; +diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c +index 3c5cbb977254..7e71e066198f 100644 +--- a/security/integrity/evm/evm_main.c ++++ b/security/integrity/evm/evm_main.c +@@ -269,6 +269,13 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, + goto out; + } + evm_status = evm_verify_current_integrity(dentry); ++ if (evm_status == INTEGRITY_NOXATTRS) { ++ struct integrity_iint_cache *iint; ++ ++ iint = integrity_iint_find(dentry->d_inode); ++ if (iint && (iint->flags & IMA_NEW_FILE)) ++ return 0; ++ } + out: + if (evm_status != INTEGRITY_PASS) + integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode, +@@ -296,9 +303,12 @@ int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name, + { + const struct evm_ima_xattr_data *xattr_data = xattr_value; + +- if ((strcmp(xattr_name, XATTR_NAME_EVM) == 0) +- && (xattr_data->type == EVM_XATTR_HMAC)) +- return -EPERM; ++ if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { ++ if (!xattr_value_len) ++ return -EINVAL; ++ if (xattr_data->type != EVM_IMA_XATTR_DIGSIG) ++ return -EPERM; ++ } + return evm_protect_xattr(dentry, xattr_name, xattr_value, + xattr_value_len); + } +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index e294b86c8d88..47b5c69e4605 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -470,6 +470,7 @@ next_inode: + list_entry(sbsec->isec_head.next, + struct inode_security_struct, list); + struct inode *inode = isec->inode; ++ list_del_init(&isec->list); + spin_unlock(&sbsec->isec_lock); + inode = igrab(inode); + if (inode) { +@@ -478,7 +479,6 @@ next_inode: + iput(inode); + } + spin_lock(&sbsec->isec_lock); +- list_del_init(&isec->list); + goto next_inode; + } + spin_unlock(&sbsec->isec_lock); +diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c +index af49721ba0e3..c4ac3c1e19af 100644 +--- a/sound/core/pcm_compat.c ++++ b/sound/core/pcm_compat.c +@@ -206,6 +206,8 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, + if (err < 0) + return err; + ++ if (clear_user(src, sizeof(*src))) ++ return -EFAULT; + if (put_user(status.state, &src->state) || + compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) || + compat_put_timespec(&status.tstamp, &src->tstamp) || +diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c +index 7ec91424ba22..103e85a13f35 100644 +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -4027,6 +4027,9 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { + /* BayTrail */ + { PCI_DEVICE(0x8086, 0x0f04), + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, ++ /* Braswell */ ++ { PCI_DEVICE(0x8086, 0x2284), ++ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, + /* ICH */ + { PCI_DEVICE(0x8086, 0x2668), + .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index 8253b48a435b..611110a3f1a4 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -3317,6 +3317,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { + { .id = 0x80862808, .name = "Broadwell HDMI", .patch = patch_generic_hdmi }, + { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, + { .id = 0x80862882, .name = "Valleyview2 HDMI", .patch = patch_generic_hdmi }, ++{ .id = 0x80862883, .name = "Braswell HDMI", .patch = patch_generic_hdmi }, + { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, + {} /* terminator */ + }; +@@ -3373,6 +3374,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862807"); + MODULE_ALIAS("snd-hda-codec-id:80862808"); + MODULE_ALIAS("snd-hda-codec-id:80862880"); + MODULE_ALIAS("snd-hda-codec-id:80862882"); ++MODULE_ALIAS("snd-hda-codec-id:80862883"); + MODULE_ALIAS("snd-hda-codec-id:808629fb"); + + MODULE_LICENSE("GPL"); +diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c +index eb241c6571a9..fd53d37e1181 100644 +--- a/sound/soc/codecs/tlv320aic3x.c ++++ b/sound/soc/codecs/tlv320aic3x.c +@@ -1121,6 +1121,7 @@ static int aic3x_regulator_event(struct notifier_block *nb, + static int aic3x_set_power(struct snd_soc_codec *codec, int power) + { + struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); ++ unsigned int pll_c, pll_d; + int ret; + + if (power) { +@@ -1138,6 +1139,18 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power) + /* Sync reg_cache with the hardware */ + regcache_cache_only(aic3x->regmap, false); + regcache_sync(aic3x->regmap); ++ ++ /* Rewrite paired PLL D registers in case cached sync skipped ++ * writing one of them and thus caused other one also not ++ * being written ++ */ ++ pll_c = snd_soc_read(codec, AIC3X_PLL_PROGC_REG); ++ pll_d = snd_soc_read(codec, AIC3X_PLL_PROGD_REG); ++ if (pll_c == aic3x_reg[AIC3X_PLL_PROGC_REG].def || ++ pll_d == aic3x_reg[AIC3X_PLL_PROGD_REG].def) { ++ snd_soc_write(codec, AIC3X_PLL_PROGC_REG, pll_c); ++ snd_soc_write(codec, AIC3X_PLL_PROGD_REG, pll_d); ++ } + } else { + /* + * Do soft reset to this codec instance in order to clear +diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c +index 731d47b64daa..e4da224d7253 100644 +--- a/sound/soc/soc-dapm.c ++++ b/sound/soc/soc-dapm.c +@@ -689,9 +689,9 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, + int shared; + struct snd_kcontrol *kcontrol; + bool wname_in_long_name, kcname_in_long_name; +- char *long_name; ++ char *long_name = NULL; + const char *name; +- int ret; ++ int ret = 0; + + if (dapm->codec) + prefix = dapm->codec->name_prefix; +@@ -756,15 +756,17 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, + + kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], NULL, name, + prefix); +- kfree(long_name); +- if (!kcontrol) +- return -ENOMEM; ++ if (!kcontrol) { ++ ret = -ENOMEM; ++ goto exit_free; ++ } ++ + kcontrol->private_free = dapm_kcontrol_free; + + ret = dapm_kcontrol_data_alloc(w, kcontrol); + if (ret) { + snd_ctl_free_one(kcontrol); +- return ret; ++ goto exit_free; + } + + ret = snd_ctl_add(card, kcontrol); +@@ -772,17 +774,18 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, + dev_err(dapm->dev, + "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", + w->name, name, ret); +- return ret; ++ goto exit_free; + } + } + + ret = dapm_kcontrol_add_widget(kcontrol, w); +- if (ret) +- return ret; ++ if (ret == 0) ++ w->kcontrols[kci] = kcontrol; + +- w->kcontrols[kci] = kcontrol; ++exit_free: ++ kfree(long_name); + +- return 0; ++ return ret; + } + + /* create new dapm mixer control */ +diff --git a/sound/usb/card.c b/sound/usb/card.c +index af1956042c9e..ab433a02dbf1 100644 +--- a/sound/usb/card.c ++++ b/sound/usb/card.c +@@ -586,18 +586,19 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, + { + struct snd_card *card; + struct list_head *p; ++ bool was_shutdown; + + if (chip == (void *)-1L) + return; + + card = chip->card; + down_write(&chip->shutdown_rwsem); ++ was_shutdown = chip->shutdown; + chip->shutdown = 1; + up_write(&chip->shutdown_rwsem); + + mutex_lock(®ister_mutex); +- chip->num_interfaces--; +- if (chip->num_interfaces <= 0) { ++ if (!was_shutdown) { + struct snd_usb_endpoint *ep; + + snd_card_disconnect(card); +@@ -617,6 +618,10 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, + list_for_each(p, &chip->mixer_list) { + snd_usb_mixer_disconnect(p); + } ++ } ++ ++ chip->num_interfaces--; ++ if (chip->num_interfaces <= 0) { + usb_chip[chip->index] = NULL; + mutex_unlock(®ister_mutex); + snd_card_free_when_closed(card); +diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c +index 714b94932312..1f0dc1e5f1f0 100644 +--- a/virt/kvm/iommu.c ++++ b/virt/kvm/iommu.c +@@ -43,13 +43,13 @@ static void kvm_iommu_put_pages(struct kvm *kvm, + gfn_t base_gfn, unsigned long npages); + + static pfn_t kvm_pin_pages(struct kvm_memory_slot *slot, gfn_t gfn, +- unsigned long size) ++ unsigned long npages) + { + gfn_t end_gfn; + pfn_t pfn; + + pfn = gfn_to_pfn_memslot(slot, gfn); +- end_gfn = gfn + (size >> PAGE_SHIFT); ++ end_gfn = gfn + npages; + gfn += 1; + + if (is_error_noslot_pfn(pfn)) +@@ -119,7 +119,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) + * Pin all pages we are about to map in memory. This is + * important because we unmap and unpin in 4kb steps later. + */ +- pfn = kvm_pin_pages(slot, gfn, page_size); ++ pfn = kvm_pin_pages(slot, gfn, page_size >> PAGE_SHIFT); + if (is_error_noslot_pfn(pfn)) { + gfn += 1; + continue; +@@ -131,7 +131,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) + if (r) { + printk(KERN_ERR "kvm_iommu_map_address:" + "iommu failed to map pfn=%llx\n", pfn); +- kvm_unpin_pages(kvm, pfn, page_size); ++ kvm_unpin_pages(kvm, pfn, page_size >> PAGE_SHIFT); + goto unmap_pages; + } + diff --git a/patch/kernel/cubox-default/patch-3.14.24-25.patch b/patch/kernel/cubox-default/patch-3.14.24-25.patch new file mode 100644 index 000000000..03df3d2b2 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.24-25.patch @@ -0,0 +1,7549 @@ +diff --git a/Documentation/devicetree/bindings/ata/sata_rcar.txt b/Documentation/devicetree/bindings/ata/sata_rcar.txt +index 1e6111333fa8..7dd32d321a34 100644 +--- a/Documentation/devicetree/bindings/ata/sata_rcar.txt ++++ b/Documentation/devicetree/bindings/ata/sata_rcar.txt +@@ -3,7 +3,8 @@ + Required properties: + - compatible : should contain one of the following: + - "renesas,sata-r8a7779" for R-Car H1 +- - "renesas,sata-r8a7790" for R-Car H2 ++ - "renesas,sata-r8a7790-es1" for R-Car H2 ES1 ++ - "renesas,sata-r8a7790" for R-Car H2 other than ES1 + - "renesas,sata-r8a7791" for R-Car M2 + - reg : address and length of the SATA registers; + - interrupts : must consist of one interrupt specifier. +diff --git a/Makefile b/Makefile +index 8fd06101c482..eb96e40238f7 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 24 ++SUBLEVEL = 25 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S +index 066b03480b63..8017cde13648 100644 +--- a/arch/arm/boot/compressed/head.S ++++ b/arch/arm/boot/compressed/head.S +@@ -400,8 +400,7 @@ dtb_check_done: + add sp, sp, r6 + #endif + +- tst r4, #1 +- bleq cache_clean_flush ++ bl cache_clean_flush + + adr r0, BSYM(restart) + add r0, r0, r6 +@@ -1050,6 +1049,8 @@ cache_clean_flush: + b call_cache_fn + + __armv4_mpu_cache_flush: ++ tst r4, #1 ++ movne pc, lr + mov r2, #1 + mov r3, #0 + mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache +@@ -1067,6 +1068,8 @@ __armv4_mpu_cache_flush: + mov pc, lr + + __fa526_cache_flush: ++ tst r4, #1 ++ movne pc, lr + mov r1, #0 + mcr p15, 0, r1, c7, c14, 0 @ clean and invalidate D cache + mcr p15, 0, r1, c7, c5, 0 @ flush I cache +@@ -1075,13 +1078,16 @@ __fa526_cache_flush: + + __armv6_mmu_cache_flush: + mov r1, #0 +- mcr p15, 0, r1, c7, c14, 0 @ clean+invalidate D ++ tst r4, #1 ++ mcreq p15, 0, r1, c7, c14, 0 @ clean+invalidate D + mcr p15, 0, r1, c7, c5, 0 @ invalidate I+BTB +- mcr p15, 0, r1, c7, c15, 0 @ clean+invalidate unified ++ mcreq p15, 0, r1, c7, c15, 0 @ clean+invalidate unified + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + + __armv7_mmu_cache_flush: ++ tst r4, #1 ++ bne iflush + mrc p15, 0, r10, c0, c1, 5 @ read ID_MMFR1 + tst r10, #0xf << 16 @ hierarchical cache (ARMv7) + mov r10, #0 +@@ -1142,6 +1148,8 @@ iflush: + mov pc, lr + + __armv5tej_mmu_cache_flush: ++ tst r4, #1 ++ movne pc, lr + 1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate D cache + bne 1b + mcr p15, 0, r0, c7, c5, 0 @ flush I cache +@@ -1149,6 +1157,8 @@ __armv5tej_mmu_cache_flush: + mov pc, lr + + __armv4_mmu_cache_flush: ++ tst r4, #1 ++ movne pc, lr + mov r2, #64*1024 @ default: 32K dcache size (*2) + mov r11, #32 @ default: 32 byte line size + mrc p15, 0, r3, c0, c0, 1 @ read cache type +@@ -1182,6 +1192,8 @@ no_cache_id: + + __armv3_mmu_cache_flush: + __armv3_mpu_cache_flush: ++ tst r4, #1 ++ movne pc, lr + mov r1, #0 + mcr p15, 0, r1, c7, c0, 0 @ invalidate whole cache v3 + mov pc, lr +diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c +index 18a76282970e..380c20fb9c85 100644 +--- a/arch/arm/kernel/kprobes-common.c ++++ b/arch/arm/kernel/kprobes-common.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + #include "kprobes.h" + +@@ -305,7 +306,8 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) + + if (handler) { + /* We can emulate the instruction in (possibly) modified form */ +- asi->insn[0] = (insn & 0xfff00000) | (rn << 16) | reglist; ++ asi->insn[0] = __opcode_to_mem_arm((insn & 0xfff00000) | ++ (rn << 16) | reglist); + asi->insn_handler = handler; + return INSN_GOOD; + } +@@ -334,13 +336,14 @@ prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, + #ifdef CONFIG_THUMB2_KERNEL + if (thumb) { + u16 *thumb_insn = (u16 *)asi->insn; +- thumb_insn[1] = 0x4770; /* Thumb bx lr */ +- thumb_insn[2] = 0x4770; /* Thumb bx lr */ ++ /* Thumb bx lr */ ++ thumb_insn[1] = __opcode_to_mem_thumb16(0x4770); ++ thumb_insn[2] = __opcode_to_mem_thumb16(0x4770); + return insn; + } +- asi->insn[1] = 0xe12fff1e; /* ARM bx lr */ ++ asi->insn[1] = __opcode_to_mem_arm(0xe12fff1e); /* ARM bx lr */ + #else +- asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */ ++ asi->insn[1] = __opcode_to_mem_arm(0xe1a0f00e); /* mov pc, lr */ + #endif + /* Make an ARM instruction unconditional */ + if (insn < 0xe0000000) +@@ -360,12 +363,12 @@ set_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, + if (thumb) { + u16 *ip = (u16 *)asi->insn; + if (is_wide_instruction(insn)) +- *ip++ = insn >> 16; +- *ip++ = insn; ++ *ip++ = __opcode_to_mem_thumb16(insn >> 16); ++ *ip++ = __opcode_to_mem_thumb16(insn); + return; + } + #endif +- asi->insn[0] = insn; ++ asi->insn[0] = __opcode_to_mem_arm(insn); + } + + /* +diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c +index 6123daf397a7..241222c66a13 100644 +--- a/arch/arm/kernel/kprobes-thumb.c ++++ b/arch/arm/kernel/kprobes-thumb.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + #include "kprobes.h" + +@@ -163,9 +164,9 @@ t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) + enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi); + + /* Fixup modified instruction to have halfwords in correct order...*/ +- insn = asi->insn[0]; +- ((u16 *)asi->insn)[0] = insn >> 16; +- ((u16 *)asi->insn)[1] = insn & 0xffff; ++ insn = __mem_to_opcode_arm(asi->insn[0]); ++ ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn >> 16); ++ ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0xffff); + + return ret; + } +@@ -1153,7 +1154,7 @@ t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi) + { + insn &= ~0x00ff; + insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */ +- ((u16 *)asi->insn)[0] = insn; ++ ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn); + asi->insn_handler = t16_emulate_hiregs; + return INSN_GOOD; + } +@@ -1182,8 +1183,10 @@ t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi) + * and call it with R9=SP and LR in the register list represented + * by R8. + */ +- ((u16 *)asi->insn)[0] = 0xe929; /* 1st half STMDB R9!,{} */ +- ((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */ ++ /* 1st half STMDB R9!,{} */ ++ ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe929); ++ /* 2nd half (register list) */ ++ ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff); + asi->insn_handler = t16_emulate_push; + return INSN_GOOD; + } +@@ -1232,8 +1235,10 @@ t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi) + * and call it with R9=SP and PC in the register list represented + * by R8. + */ +- ((u16 *)asi->insn)[0] = 0xe8b9; /* 1st half LDMIA R9!,{} */ +- ((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */ ++ /* 1st half LDMIA R9!,{} */ ++ ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe8b9); ++ /* 2nd half (register list) */ ++ ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff); + asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc + : t16_emulate_pop_nopc; + return INSN_GOOD; +diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c +index a7b621ece23d..49a87b6d0bf3 100644 +--- a/arch/arm/kernel/kprobes.c ++++ b/arch/arm/kernel/kprobes.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + + #include "kprobes.h" +@@ -62,10 +63,10 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) + #ifdef CONFIG_THUMB2_KERNEL + thumb = true; + addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */ +- insn = ((u16 *)addr)[0]; ++ insn = __mem_to_opcode_thumb16(((u16 *)addr)[0]); + if (is_wide_instruction(insn)) { +- insn <<= 16; +- insn |= ((u16 *)addr)[1]; ++ u16 inst2 = __mem_to_opcode_thumb16(((u16 *)addr)[1]); ++ insn = __opcode_thumb32_compose(insn, inst2); + decode_insn = thumb32_kprobe_decode_insn; + } else + decode_insn = thumb16_kprobe_decode_insn; +@@ -73,7 +74,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) + thumb = false; + if (addr & 0x3) + return -EINVAL; +- insn = *p->addr; ++ insn = __mem_to_opcode_arm(*p->addr); + decode_insn = arm_kprobe_decode_insn; + #endif + +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index ca8ecdee47d8..e9c290c21744 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -798,6 +798,7 @@ config NEED_KUSER_HELPERS + + config KUSER_HELPERS + bool "Enable kuser helpers in vector page" if !NEED_KUSER_HELPERS ++ depends on MMU + default y + help + Warning: disabling this option may break user programs. +diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c +index 92f36835486b..565e26f23f31 100644 +--- a/arch/arm64/kernel/insn.c ++++ b/arch/arm64/kernel/insn.c +@@ -156,9 +156,10 @@ static int __kprobes aarch64_insn_patch_text_cb(void *arg) + * which ends with "dsb; isb" pair guaranteeing global + * visibility. + */ +- atomic_set(&pp->cpu_count, -1); ++ /* Notify other processors with an additional increment. */ ++ atomic_inc(&pp->cpu_count); + } else { +- while (atomic_read(&pp->cpu_count) != -1) ++ while (atomic_read(&pp->cpu_count) <= num_online_cpus()) + cpu_relax(); + isb(); + } +diff --git a/arch/arm64/lib/clear_user.S b/arch/arm64/lib/clear_user.S +index 6e0ed93d51fe..c17967fdf5f6 100644 +--- a/arch/arm64/lib/clear_user.S ++++ b/arch/arm64/lib/clear_user.S +@@ -46,7 +46,7 @@ USER(9f, strh wzr, [x0], #2 ) + sub x1, x1, #2 + 4: adds x1, x1, #1 + b.mi 5f +- strb wzr, [x0] ++USER(9f, strb wzr, [x0] ) + 5: mov x0, #0 + ret + ENDPROC(__clear_user) +diff --git a/arch/parisc/include/uapi/asm/shmbuf.h b/arch/parisc/include/uapi/asm/shmbuf.h +index 0a3eada1863b..f395cde7b593 100644 +--- a/arch/parisc/include/uapi/asm/shmbuf.h ++++ b/arch/parisc/include/uapi/asm/shmbuf.h +@@ -36,23 +36,16 @@ struct shmid64_ds { + unsigned int __unused2; + }; + +-#ifdef CONFIG_64BIT +-/* The 'unsigned int' (formerly 'unsigned long') data types below will +- * ensure that a 32-bit app calling shmctl(*,IPC_INFO,*) will work on +- * a wide kernel, but if some of these values are meant to contain pointers +- * they may need to be 'long long' instead. -PB XXX FIXME +- */ +-#endif + struct shminfo64 { +- unsigned int shmmax; +- unsigned int shmmin; +- unsigned int shmmni; +- unsigned int shmseg; +- unsigned int shmall; +- unsigned int __unused1; +- unsigned int __unused2; +- unsigned int __unused3; +- unsigned int __unused4; ++ unsigned long shmmax; ++ unsigned long shmmin; ++ unsigned long shmmni; ++ unsigned long shmseg; ++ unsigned long shmall; ++ unsigned long __unused1; ++ unsigned long __unused2; ++ unsigned long __unused3; ++ unsigned long __unused4; + }; + + #endif /* _PARISC_SHMBUF_H */ +diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S +index 7dd8a3b22147..fc77d53e2ca5 100644 +--- a/arch/parisc/kernel/syscall_table.S ++++ b/arch/parisc/kernel/syscall_table.S +@@ -286,11 +286,11 @@ + ENTRY_COMP(msgsnd) + ENTRY_COMP(msgrcv) + ENTRY_SAME(msgget) /* 190 */ +- ENTRY_SAME(msgctl) +- ENTRY_SAME(shmat) ++ ENTRY_COMP(msgctl) ++ ENTRY_COMP(shmat) + ENTRY_SAME(shmdt) + ENTRY_SAME(shmget) +- ENTRY_SAME(shmctl) /* 195 */ ++ ENTRY_COMP(shmctl) /* 195 */ + ENTRY_SAME(ni_syscall) /* streams1 */ + ENTRY_SAME(ni_syscall) /* streams2 */ + ENTRY_SAME(lstat64) +@@ -323,7 +323,7 @@ + ENTRY_SAME(epoll_ctl) /* 225 */ + ENTRY_SAME(epoll_wait) + ENTRY_SAME(remap_file_pages) +- ENTRY_SAME(semtimedop) ++ ENTRY_COMP(semtimedop) + ENTRY_COMP(mq_open) + ENTRY_SAME(mq_unlink) /* 230 */ + ENTRY_COMP(mq_timedsend) +diff --git a/arch/sparc/include/asm/atomic_32.h b/arch/sparc/include/asm/atomic_32.h +index 905832aa9e9e..a0ed182ae73c 100644 +--- a/arch/sparc/include/asm/atomic_32.h ++++ b/arch/sparc/include/asm/atomic_32.h +@@ -21,7 +21,7 @@ + + extern int __atomic_add_return(int, atomic_t *); + extern int atomic_cmpxchg(atomic_t *, int, int); +-#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) ++extern int atomic_xchg(atomic_t *, int); + extern int __atomic_add_unless(atomic_t *, int, int); + extern void atomic_set(atomic_t *, int); + +diff --git a/arch/sparc/include/asm/cmpxchg_32.h b/arch/sparc/include/asm/cmpxchg_32.h +index 1fae1a02e3c2..ae0f9a7a314d 100644 +--- a/arch/sparc/include/asm/cmpxchg_32.h ++++ b/arch/sparc/include/asm/cmpxchg_32.h +@@ -11,22 +11,14 @@ + #ifndef __ARCH_SPARC_CMPXCHG__ + #define __ARCH_SPARC_CMPXCHG__ + +-static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val) +-{ +- __asm__ __volatile__("swap [%2], %0" +- : "=&r" (val) +- : "0" (val), "r" (m) +- : "memory"); +- return val; +-} +- ++extern unsigned long __xchg_u32(volatile u32 *m, u32 new); + extern void __xchg_called_with_bad_pointer(void); + + static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size) + { + switch (size) { + case 4: +- return xchg_u32(ptr, x); ++ return __xchg_u32(ptr, x); + } + __xchg_called_with_bad_pointer(); + return x; +diff --git a/arch/sparc/include/asm/vio.h b/arch/sparc/include/asm/vio.h +index 432afa838861..55841c184e6d 100644 +--- a/arch/sparc/include/asm/vio.h ++++ b/arch/sparc/include/asm/vio.h +@@ -118,12 +118,18 @@ struct vio_disk_attr_info { + u8 vdisk_type; + #define VD_DISK_TYPE_SLICE 0x01 /* Slice in block device */ + #define VD_DISK_TYPE_DISK 0x02 /* Entire block device */ +- u16 resv1; ++ u8 vdisk_mtype; /* v1.1 */ ++#define VD_MEDIA_TYPE_FIXED 0x01 /* Fixed device */ ++#define VD_MEDIA_TYPE_CD 0x02 /* CD Device */ ++#define VD_MEDIA_TYPE_DVD 0x03 /* DVD Device */ ++ u8 resv1; + u32 vdisk_block_size; + u64 operations; +- u64 vdisk_size; ++ u64 vdisk_size; /* v1.1 */ + u64 max_xfer_size; +- u64 resv2[2]; ++ u32 phys_block_size; /* v1.2 */ ++ u32 resv2; ++ u64 resv3[1]; + }; + + struct vio_disk_desc { +@@ -259,7 +265,7 @@ static inline u32 vio_dring_avail(struct vio_dring_state *dr, + unsigned int ring_size) + { + return (dr->pending - +- ((dr->prod - dr->cons) & (ring_size - 1))); ++ ((dr->prod - dr->cons) & (ring_size - 1)) - 1); + } + + #define VIO_MAX_TYPE_LEN 32 +diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c +index 8f76f23dac38..f9c6813c132d 100644 +--- a/arch/sparc/kernel/pci_schizo.c ++++ b/arch/sparc/kernel/pci_schizo.c +@@ -581,7 +581,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) + { + unsigned long csr_reg, csr, csr_error_bits; + irqreturn_t ret = IRQ_NONE; +- u16 stat; ++ u32 stat; + + csr_reg = pbm->pbm_regs + SCHIZO_PCI_CTRL; + csr = upa_readq(csr_reg); +@@ -617,7 +617,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) + pbm->name); + ret = IRQ_HANDLED; + } +- pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat); ++ pbm->pci_ops->read(pbm->pci_bus, 0, PCI_STATUS, 2, &stat); + if (stat & (PCI_STATUS_PARITY | + PCI_STATUS_SIG_TARGET_ABORT | + PCI_STATUS_REC_TARGET_ABORT | +@@ -625,7 +625,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) + PCI_STATUS_SIG_SYSTEM_ERROR)) { + printk("%s: PCI bus error, PCI_STATUS[%04x]\n", + pbm->name, stat); +- pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff); ++ pbm->pci_ops->write(pbm->pci_bus, 0, PCI_STATUS, 2, 0xffff); + ret = IRQ_HANDLED; + } + return ret; +diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c +index 50c3dd03be31..9af0a5dbb36d 100644 +--- a/arch/sparc/kernel/smp_64.c ++++ b/arch/sparc/kernel/smp_64.c +@@ -823,13 +823,17 @@ void arch_send_call_function_single_ipi(int cpu) + void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs) + { + clear_softint(1 << irq); ++ irq_enter(); + generic_smp_call_function_interrupt(); ++ irq_exit(); + } + + void __irq_entry smp_call_function_single_client(int irq, struct pt_regs *regs) + { + clear_softint(1 << irq); ++ irq_enter(); + generic_smp_call_function_single_interrupt(); ++ irq_exit(); + } + + static void tsb_sync(void *info) +diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c +index 1d32b54089aa..8f2f94d53434 100644 +--- a/arch/sparc/lib/atomic32.c ++++ b/arch/sparc/lib/atomic32.c +@@ -40,6 +40,19 @@ int __atomic_add_return(int i, atomic_t *v) + } + EXPORT_SYMBOL(__atomic_add_return); + ++int atomic_xchg(atomic_t *v, int new) ++{ ++ int ret; ++ unsigned long flags; ++ ++ spin_lock_irqsave(ATOMIC_HASH(v), flags); ++ ret = v->counter; ++ v->counter = new; ++ spin_unlock_irqrestore(ATOMIC_HASH(v), flags); ++ return ret; ++} ++EXPORT_SYMBOL(atomic_xchg); ++ + int atomic_cmpxchg(atomic_t *v, int old, int new) + { + int ret; +@@ -132,3 +145,17 @@ unsigned long __cmpxchg_u32(volatile u32 *ptr, u32 old, u32 new) + return (unsigned long)prev; + } + EXPORT_SYMBOL(__cmpxchg_u32); ++ ++unsigned long __xchg_u32(volatile u32 *ptr, u32 new) ++{ ++ unsigned long flags; ++ u32 prev; ++ ++ spin_lock_irqsave(ATOMIC_HASH(ptr), flags); ++ prev = *ptr; ++ *ptr = new; ++ spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags); ++ ++ return (unsigned long)prev; ++} ++EXPORT_SYMBOL(__xchg_u32); +diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile +index 0fcd9133790c..14fe7cba21d1 100644 +--- a/arch/x86/boot/compressed/Makefile ++++ b/arch/x86/boot/compressed/Makefile +@@ -75,8 +75,10 @@ suffix-$(CONFIG_KERNEL_XZ) := xz + suffix-$(CONFIG_KERNEL_LZO) := lzo + suffix-$(CONFIG_KERNEL_LZ4) := lz4 + ++RUN_SIZE = $(shell objdump -h vmlinux | \ ++ perl $(srctree)/arch/x86/tools/calc_run_size.pl) + quiet_cmd_mkpiggy = MKPIGGY $@ +- cmd_mkpiggy = $(obj)/mkpiggy $< > $@ || ( rm -f $@ ; false ) ++ cmd_mkpiggy = $(obj)/mkpiggy $< $(RUN_SIZE) > $@ || ( rm -f $@ ; false ) + + targets += piggy.S + $(obj)/piggy.S: $(obj)/vmlinux.bin.$(suffix-y) $(obj)/mkpiggy FORCE +diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S +index f45ab7a36fb6..c5b56ed10aff 100644 +--- a/arch/x86/boot/compressed/head_32.S ++++ b/arch/x86/boot/compressed/head_32.S +@@ -186,7 +186,8 @@ relocated: + * Do the decompression, and jump to the new kernel.. + */ + /* push arguments for decompress_kernel: */ +- pushl $z_output_len /* decompressed length */ ++ pushl $z_run_size /* size of kernel with .bss and .brk */ ++ pushl $z_output_len /* decompressed length, end of relocs */ + leal z_extract_offset_negative(%ebx), %ebp + pushl %ebp /* output address */ + pushl $z_input_len /* input_len */ +@@ -196,7 +197,7 @@ relocated: + pushl %eax /* heap area */ + pushl %esi /* real mode pointer */ + call decompress_kernel /* returns kernel location in %eax */ +- addl $24, %esp ++ addl $28, %esp + + /* + * Jump to the decompressed kernel. +diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S +index b10fa66a2540..34bbc0911b7c 100644 +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -334,13 +334,16 @@ relocated: + * Do the decompression, and jump to the new kernel.. + */ + pushq %rsi /* Save the real mode argument */ ++ movq $z_run_size, %r9 /* size of kernel with .bss and .brk */ ++ pushq %r9 + movq %rsi, %rdi /* real mode address */ + leaq boot_heap(%rip), %rsi /* malloc area for uncompression */ + leaq input_data(%rip), %rdx /* input_data */ + movl $z_input_len, %ecx /* input_len */ + movq %rbp, %r8 /* output target address */ +- movq $z_output_len, %r9 /* decompressed length */ ++ movq $z_output_len, %r9 /* decompressed length, end of relocs */ + call decompress_kernel /* returns kernel location in %rax */ ++ popq %r9 + popq %rsi + + /* +diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c +index 196eaf373a06..eb25ca1eb6da 100644 +--- a/arch/x86/boot/compressed/misc.c ++++ b/arch/x86/boot/compressed/misc.c +@@ -393,7 +393,8 @@ asmlinkage void *decompress_kernel(void *rmode, memptr heap, + unsigned char *input_data, + unsigned long input_len, + unsigned char *output, +- unsigned long output_len) ++ unsigned long output_len, ++ unsigned long run_size) + { + real_mode = rmode; + +@@ -416,8 +417,14 @@ asmlinkage void *decompress_kernel(void *rmode, memptr heap, + free_mem_ptr = heap; /* Heap */ + free_mem_end_ptr = heap + BOOT_HEAP_SIZE; + +- output = choose_kernel_location(input_data, input_len, +- output, output_len); ++ /* ++ * The memory hole needed for the kernel is the larger of either ++ * the entire decompressed kernel plus relocation table, or the ++ * entire decompressed kernel plus .bss and .brk sections. ++ */ ++ output = choose_kernel_location(input_data, input_len, output, ++ output_len > run_size ? output_len ++ : run_size); + + /* Validate memory location choices. */ + if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1)) +diff --git a/arch/x86/boot/compressed/mkpiggy.c b/arch/x86/boot/compressed/mkpiggy.c +index b669ab65bf6c..d8222f213182 100644 +--- a/arch/x86/boot/compressed/mkpiggy.c ++++ b/arch/x86/boot/compressed/mkpiggy.c +@@ -36,11 +36,13 @@ int main(int argc, char *argv[]) + uint32_t olen; + long ilen; + unsigned long offs; ++ unsigned long run_size; + FILE *f = NULL; + int retval = 1; + +- if (argc < 2) { +- fprintf(stderr, "Usage: %s compressed_file\n", argv[0]); ++ if (argc < 3) { ++ fprintf(stderr, "Usage: %s compressed_file run_size\n", ++ argv[0]); + goto bail; + } + +@@ -74,6 +76,7 @@ int main(int argc, char *argv[]) + offs += olen >> 12; /* Add 8 bytes for each 32K block */ + offs += 64*1024 + 128; /* Add 64K + 128 bytes slack */ + offs = (offs+4095) & ~4095; /* Round to a 4K boundary */ ++ run_size = atoi(argv[2]); + + printf(".section \".rodata..compressed\",\"a\",@progbits\n"); + printf(".globl z_input_len\n"); +@@ -85,6 +88,8 @@ int main(int argc, char *argv[]) + /* z_extract_offset_negative allows simplification of head_32.S */ + printf(".globl z_extract_offset_negative\n"); + printf("z_extract_offset_negative = -0x%lx\n", offs); ++ printf(".globl z_run_size\n"); ++ printf("z_run_size = %lu\n", run_size); + + printf(".globl input_data, input_data_end\n"); + printf("input_data:\n"); +diff --git a/arch/x86/kernel/cpu/microcode/amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c +index 617a9e284245..b63773ba1646 100644 +--- a/arch/x86/kernel/cpu/microcode/amd_early.c ++++ b/arch/x86/kernel/cpu/microcode/amd_early.c +@@ -108,12 +108,13 @@ static size_t compute_container_size(u8 *data, u32 total_size) + * load_microcode_amd() to save equivalent cpu table and microcode patches in + * kernel heap memory. + */ +-static void apply_ucode_in_initrd(void *ucode, size_t size) ++static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch) + { + struct equiv_cpu_entry *eq; + size_t *cont_sz; + u32 *header; + u8 *data, **cont; ++ u8 (*patch)[PATCH_MAX_SIZE]; + u16 eq_id = 0; + int offset, left; + u32 rev, eax, ebx, ecx, edx; +@@ -123,10 +124,12 @@ static void apply_ucode_in_initrd(void *ucode, size_t size) + new_rev = (u32 *)__pa_nodebug(&ucode_new_rev); + cont_sz = (size_t *)__pa_nodebug(&container_size); + cont = (u8 **)__pa_nodebug(&container); ++ patch = (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch); + #else + new_rev = &ucode_new_rev; + cont_sz = &container_size; + cont = &container; ++ patch = &amd_ucode_patch; + #endif + + data = ucode; +@@ -213,9 +216,9 @@ static void apply_ucode_in_initrd(void *ucode, size_t size) + rev = mc->hdr.patch_id; + *new_rev = rev; + +- /* save ucode patch */ +- memcpy(amd_ucode_patch, mc, +- min_t(u32, header[1], PATCH_MAX_SIZE)); ++ if (save_patch) ++ memcpy(patch, mc, ++ min_t(u32, header[1], PATCH_MAX_SIZE)); + } + } + +@@ -246,7 +249,7 @@ void __init load_ucode_amd_bsp(void) + *data = cp.data; + *size = cp.size; + +- apply_ucode_in_initrd(cp.data, cp.size); ++ apply_ucode_in_initrd(cp.data, cp.size, true); + } + + #ifdef CONFIG_X86_32 +@@ -263,7 +266,7 @@ void load_ucode_amd_ap(void) + size_t *usize; + void **ucode; + +- mc = (struct microcode_amd *)__pa(amd_ucode_patch); ++ mc = (struct microcode_amd *)__pa_nodebug(amd_ucode_patch); + if (mc->hdr.patch_id && mc->hdr.processor_rev_id) { + __apply_microcode_amd(mc); + return; +@@ -275,7 +278,7 @@ void load_ucode_amd_ap(void) + if (!*ucode || !*usize) + return; + +- apply_ucode_in_initrd(*ucode, *usize); ++ apply_ucode_in_initrd(*ucode, *usize, false); + } + + static void __init collect_cpu_sig_on_bsp(void *arg) +@@ -339,7 +342,7 @@ void load_ucode_amd_ap(void) + * AP has a different equivalence ID than BSP, looks like + * mixed-steppings silicon so go through the ucode blob anew. + */ +- apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size); ++ apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size, false); + } + } + #endif +@@ -347,7 +350,9 @@ void load_ucode_amd_ap(void) + int __init save_microcode_in_initrd_amd(void) + { + unsigned long cont; ++ int retval = 0; + enum ucode_state ret; ++ u8 *cont_va; + u32 eax; + + if (!container) +@@ -355,13 +360,15 @@ int __init save_microcode_in_initrd_amd(void) + + #ifdef CONFIG_X86_32 + get_bsp_sig(); +- cont = (unsigned long)container; ++ cont = (unsigned long)container; ++ cont_va = __va(container); + #else + /* + * We need the physical address of the container for both bitness since + * boot_params.hdr.ramdisk_image is a physical address. + */ +- cont = __pa(container); ++ cont = __pa(container); ++ cont_va = container; + #endif + + /* +@@ -372,6 +379,8 @@ int __init save_microcode_in_initrd_amd(void) + if (relocated_ramdisk) + container = (u8 *)(__va(relocated_ramdisk) + + (cont - boot_params.hdr.ramdisk_image)); ++ else ++ container = cont_va; + + if (ucode_new_rev) + pr_info("microcode: updated early to new patch_level=0x%08x\n", +@@ -382,7 +391,7 @@ int __init save_microcode_in_initrd_amd(void) + + ret = load_microcode_amd(eax, container, container_size); + if (ret != UCODE_OK) +- return -EINVAL; ++ retval = -EINVAL; + + /* + * This will be freed any msec now, stash patches for the current +@@ -391,5 +400,5 @@ int __init save_microcode_in_initrd_amd(void) + container = NULL; + container_size = 0; + +- return 0; ++ return retval; + } +diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c +index 1340ebfcb467..5ee8064bd1d2 100644 +--- a/arch/x86/kernel/cpu/perf_event_intel.c ++++ b/arch/x86/kernel/cpu/perf_event_intel.c +@@ -2475,6 +2475,9 @@ __init int intel_pmu_init(void) + case 62: /* IvyBridge EP */ + memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, + sizeof(hw_cache_event_ids)); ++ /* dTLB-load-misses on IVB is different than SNB */ ++ hw_cache_event_ids[C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = 0x8108; /* DTLB_LOAD_MISSES.DEMAND_LD_MISS_CAUSES_A_WALK */ ++ + memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, + sizeof(hw_cache_extra_regs)); + +diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c +index 7461f50d5bb1..0686fe313b3b 100644 +--- a/arch/x86/kernel/ptrace.c ++++ b/arch/x86/kernel/ptrace.c +@@ -1441,15 +1441,6 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, + force_sig_info(SIGTRAP, &info, tsk); + } + +- +-#ifdef CONFIG_X86_32 +-# define IS_IA32 1 +-#elif defined CONFIG_IA32_EMULATION +-# define IS_IA32 is_compat_task() +-#else +-# define IS_IA32 0 +-#endif +- + /* + * We must return the syscall number to actually look up in the table. + * This can be -1L to skip running any syscall at all. +@@ -1487,7 +1478,7 @@ long syscall_trace_enter(struct pt_regs *regs) + if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) + trace_sys_enter(regs, regs->orig_ax); + +- if (IS_IA32) ++ if (is_ia32_task()) + audit_syscall_entry(AUDIT_ARCH_I386, + regs->orig_ax, + regs->bx, regs->cx, +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 51c2851ca243..fab97ade0fc8 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -4911,7 +4911,7 @@ static int handle_emulation_failure(struct kvm_vcpu *vcpu) + + ++vcpu->stat.insn_emulation_fail; + trace_kvm_emulate_insn_failed(vcpu); +- if (!is_guest_mode(vcpu)) { ++ if (!is_guest_mode(vcpu) && kvm_x86_ops->get_cpl(vcpu) == 0) { + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION; + vcpu->run->internal.ndata = 0; +diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c +index c96314abd144..0004ac72dbdd 100644 +--- a/arch/x86/mm/pgtable.c ++++ b/arch/x86/mm/pgtable.c +@@ -399,13 +399,20 @@ int pmdp_test_and_clear_young(struct vm_area_struct *vma, + int ptep_clear_flush_young(struct vm_area_struct *vma, + unsigned long address, pte_t *ptep) + { +- int young; +- +- young = ptep_test_and_clear_young(vma, address, ptep); +- if (young) +- flush_tlb_page(vma, address); +- +- return young; ++ /* ++ * On x86 CPUs, clearing the accessed bit without a TLB flush ++ * doesn't cause data corruption. [ It could cause incorrect ++ * page aging and the (mistaken) reclaim of hot pages, but the ++ * chance of that should be relatively low. ] ++ * ++ * So as a performance optimization don't flush the TLB when ++ * clearing the accessed bit, it will eventually be flushed by ++ * a context switch or a VM operation anyway. [ In the rare ++ * event of it not getting flushed for a long time the delay ++ * shouldn't really matter because there's no real memory ++ * pressure for swapout to react to. ] ++ */ ++ return ptep_test_and_clear_young(vma, address, ptep); + } + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE +diff --git a/arch/x86/tools/calc_run_size.pl b/arch/x86/tools/calc_run_size.pl +new file mode 100644 +index 000000000000..0b0b124d3ece +--- /dev/null ++++ b/arch/x86/tools/calc_run_size.pl +@@ -0,0 +1,30 @@ ++#!/usr/bin/perl ++# ++# Calculate the amount of space needed to run the kernel, including room for ++# the .bss and .brk sections. ++# ++# Usage: ++# objdump -h a.out | perl calc_run_size.pl ++use strict; ++ ++my $mem_size = 0; ++my $file_offset = 0; ++ ++my $sections=" *[0-9]+ \.(?:bss|brk) +"; ++while (<>) { ++ if (/^$sections([0-9a-f]+) +(?:[0-9a-f]+ +){2}([0-9a-f]+)/) { ++ my $size = hex($1); ++ my $offset = hex($2); ++ $mem_size += $size; ++ if ($file_offset == 0) { ++ $file_offset = $offset; ++ } elsif ($file_offset != $offset) { ++ die ".bss and .brk lack common file offset\n"; ++ } ++ } ++} ++ ++if ($file_offset == 0) { ++ die "Never found .bss or .brk file offset\n"; ++} ++printf("%d\n", $mem_size + $file_offset); +diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h +index b9395529f02d..50084f7c01c8 100644 +--- a/arch/xtensa/include/uapi/asm/unistd.h ++++ b/arch/xtensa/include/uapi/asm/unistd.h +@@ -384,7 +384,8 @@ __SYSCALL(174, sys_chroot, 1) + #define __NR_pivot_root 175 + __SYSCALL(175, sys_pivot_root, 2) + #define __NR_umount 176 +-__SYSCALL(176, sys_umount, 2) ++__SYSCALL(176, sys_oldumount, 1) ++#define __ARCH_WANT_SYS_OLDUMOUNT + #define __NR_swapoff 177 + __SYSCALL(177, sys_swapoff, 1) + #define __NR_sync 178 +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index 00663d60f6d4..e662f147d436 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -61,6 +61,7 @@ enum board_ids { + /* board IDs by feature in alphabetical order */ + board_ahci, + board_ahci_ign_iferr, ++ board_ahci_nomsi, + board_ahci_noncq, + board_ahci_nosntf, + board_ahci_yes_fbs, +@@ -122,6 +123,13 @@ static const struct ata_port_info ahci_port_info[] = { + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_ops, + }, ++ [board_ahci_nomsi] = { ++ AHCI_HFLAGS (AHCI_HFLAG_NO_MSI), ++ .flags = AHCI_FLAG_COMMON, ++ .pio_mask = ATA_PIO4, ++ .udma_mask = ATA_UDMA6, ++ .port_ops = &ahci_ops, ++ }, + [board_ahci_noncq] = { + AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), + .flags = AHCI_FLAG_COMMON, +@@ -314,6 +322,11 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */ + { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ + { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */ ++ { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H RAID */ ++ { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */ ++ { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */ ++ { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */ + + /* JMicron 360/1/3/5/6, match class to avoid IDE function */ + { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, +@@ -476,10 +489,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ + + /* +- * Samsung SSDs found on some macbooks. NCQ times out. +- * https://bugzilla.kernel.org/show_bug.cgi?id=60731 ++ * Samsung SSDs found on some macbooks. NCQ times out if MSI is ++ * enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731 + */ +- { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_noncq }, ++ { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi }, + + /* Enmotus */ + { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, +diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c +index 2b25bd83fc9d..c1ea780fca07 100644 +--- a/drivers/ata/sata_rcar.c ++++ b/drivers/ata/sata_rcar.c +@@ -146,6 +146,7 @@ + enum sata_rcar_type { + RCAR_GEN1_SATA, + RCAR_GEN2_SATA, ++ RCAR_R8A7790_ES1_SATA, + }; + + struct sata_rcar_priv { +@@ -763,6 +764,9 @@ static void sata_rcar_setup_port(struct ata_host *host) + ap->udma_mask = ATA_UDMA6; + ap->flags |= ATA_FLAG_SATA; + ++ if (priv->type == RCAR_R8A7790_ES1_SATA) ++ ap->flags |= ATA_FLAG_NO_DIPM; ++ + ioaddr->cmd_addr = base + SDATA_REG; + ioaddr->ctl_addr = base + SSDEVCON_REG; + ioaddr->scr_addr = base + SCRSSTS_REG; +@@ -792,6 +796,7 @@ static void sata_rcar_init_controller(struct ata_host *host) + sata_rcar_gen1_phy_init(priv); + break; + case RCAR_GEN2_SATA: ++ case RCAR_R8A7790_ES1_SATA: + sata_rcar_gen2_phy_init(priv); + break; + default: +@@ -838,6 +843,10 @@ static struct of_device_id sata_rcar_match[] = { + .data = (void *)RCAR_GEN2_SATA + }, + { ++ .compatible = "renesas,sata-r8a7790-es1", ++ .data = (void *)RCAR_R8A7790_ES1_SATA ++ }, ++ { + .compatible = "renesas,sata-r8a7791", + .data = (void *)RCAR_GEN2_SATA + }, +@@ -849,6 +858,7 @@ static const struct platform_device_id sata_rcar_id_table[] = { + { "sata_rcar", RCAR_GEN1_SATA }, /* Deprecated by "sata-r8a7779" */ + { "sata-r8a7779", RCAR_GEN1_SATA }, + { "sata-r8a7790", RCAR_GEN2_SATA }, ++ { "sata-r8a7790-es1", RCAR_R8A7790_ES1_SATA }, + { "sata-r8a7791", RCAR_GEN2_SATA }, + { }, + }; +diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c +index f6cff3be0ed7..2f9a3d8ecbbf 100644 +--- a/drivers/base/regmap/regmap.c ++++ b/drivers/base/regmap/regmap.c +@@ -1557,8 +1557,10 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, + } else { + void *wval; + +- if (!val_count) +- return -EINVAL; ++ if (!val_count) { ++ ret = -EINVAL; ++ goto out; ++ } + + wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL); + if (!wval) { +diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c +index 5814deb6963d..0ebadf93b6c5 100644 +--- a/drivers/block/sunvdc.c ++++ b/drivers/block/sunvdc.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -22,8 +23,8 @@ + + #define DRV_MODULE_NAME "sunvdc" + #define PFX DRV_MODULE_NAME ": " +-#define DRV_MODULE_VERSION "1.0" +-#define DRV_MODULE_RELDATE "June 25, 2007" ++#define DRV_MODULE_VERSION "1.1" ++#define DRV_MODULE_RELDATE "February 13, 2013" + + static char version[] = + DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; +@@ -32,7 +33,7 @@ MODULE_DESCRIPTION("Sun LDOM virtual disk client driver"); + MODULE_LICENSE("GPL"); + MODULE_VERSION(DRV_MODULE_VERSION); + +-#define VDC_TX_RING_SIZE 256 ++#define VDC_TX_RING_SIZE 512 + + #define WAITING_FOR_LINK_UP 0x01 + #define WAITING_FOR_TX_SPACE 0x02 +@@ -65,11 +66,9 @@ struct vdc_port { + u64 operations; + u32 vdisk_size; + u8 vdisk_type; ++ u8 vdisk_mtype; + + char disk_name[32]; +- +- struct vio_disk_geom geom; +- struct vio_disk_vtoc label; + }; + + static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio) +@@ -79,9 +78,16 @@ static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio) + + /* Ordered from largest major to lowest */ + static struct vio_version vdc_versions[] = { ++ { .major = 1, .minor = 1 }, + { .major = 1, .minor = 0 }, + }; + ++static inline int vdc_version_supported(struct vdc_port *port, ++ u16 major, u16 minor) ++{ ++ return port->vio.ver.major == major && port->vio.ver.minor >= minor; ++} ++ + #define VDCBLK_NAME "vdisk" + static int vdc_major; + #define PARTITION_SHIFT 3 +@@ -94,18 +100,54 @@ static inline u32 vdc_tx_dring_avail(struct vio_dring_state *dr) + static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo) + { + struct gendisk *disk = bdev->bd_disk; +- struct vdc_port *port = disk->private_data; ++ sector_t nsect = get_capacity(disk); ++ sector_t cylinders = nsect; + +- geo->heads = (u8) port->geom.num_hd; +- geo->sectors = (u8) port->geom.num_sec; +- geo->cylinders = port->geom.num_cyl; ++ geo->heads = 0xff; ++ geo->sectors = 0x3f; ++ sector_div(cylinders, geo->heads * geo->sectors); ++ geo->cylinders = cylinders; ++ if ((sector_t)(geo->cylinders + 1) * geo->heads * geo->sectors < nsect) ++ geo->cylinders = 0xffff; + + return 0; + } + ++/* Add ioctl/CDROM_GET_CAPABILITY to support cdrom_id in udev ++ * when vdisk_mtype is VD_MEDIA_TYPE_CD or VD_MEDIA_TYPE_DVD. ++ * Needed to be able to install inside an ldom from an iso image. ++ */ ++static int vdc_ioctl(struct block_device *bdev, fmode_t mode, ++ unsigned command, unsigned long argument) ++{ ++ int i; ++ struct gendisk *disk; ++ ++ switch (command) { ++ case CDROMMULTISESSION: ++ pr_debug(PFX "Multisession CDs not supported\n"); ++ for (i = 0; i < sizeof(struct cdrom_multisession); i++) ++ if (put_user(0, (char __user *)(argument + i))) ++ return -EFAULT; ++ return 0; ++ ++ case CDROM_GET_CAPABILITY: ++ disk = bdev->bd_disk; ++ ++ if (bdev->bd_disk && (disk->flags & GENHD_FL_CD)) ++ return 0; ++ return -EINVAL; ++ ++ default: ++ pr_debug(PFX "ioctl %08x not supported\n", command); ++ return -EINVAL; ++ } ++} ++ + static const struct block_device_operations vdc_fops = { + .owner = THIS_MODULE, + .getgeo = vdc_getgeo, ++ .ioctl = vdc_ioctl, + }; + + static void vdc_finish(struct vio_driver_state *vio, int err, int waiting_for) +@@ -165,9 +207,9 @@ static int vdc_handle_attr(struct vio_driver_state *vio, void *arg) + struct vio_disk_attr_info *pkt = arg; + + viodbg(HS, "GOT ATTR stype[0x%x] ops[%llx] disk_size[%llu] disk_type[%x] " +- "xfer_mode[0x%x] blksz[%u] max_xfer[%llu]\n", ++ "mtype[0x%x] xfer_mode[0x%x] blksz[%u] max_xfer[%llu]\n", + pkt->tag.stype, pkt->operations, +- pkt->vdisk_size, pkt->vdisk_type, ++ pkt->vdisk_size, pkt->vdisk_type, pkt->vdisk_mtype, + pkt->xfer_mode, pkt->vdisk_block_size, + pkt->max_xfer_size); + +@@ -192,8 +234,11 @@ static int vdc_handle_attr(struct vio_driver_state *vio, void *arg) + } + + port->operations = pkt->operations; +- port->vdisk_size = pkt->vdisk_size; + port->vdisk_type = pkt->vdisk_type; ++ if (vdc_version_supported(port, 1, 1)) { ++ port->vdisk_size = pkt->vdisk_size; ++ port->vdisk_mtype = pkt->vdisk_mtype; ++ } + if (pkt->max_xfer_size < port->max_xfer_size) + port->max_xfer_size = pkt->max_xfer_size; + port->vdisk_block_size = pkt->vdisk_block_size; +@@ -236,7 +281,9 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr, + + __blk_end_request(req, (desc->status ? -EIO : 0), desc->size); + +- if (blk_queue_stopped(port->disk->queue)) ++ /* restart blk queue when ring is half emptied */ ++ if (blk_queue_stopped(port->disk->queue) && ++ vdc_tx_dring_avail(dr) * 100 / VDC_TX_RING_SIZE >= 50) + blk_start_queue(port->disk->queue); + } + +@@ -388,12 +435,6 @@ static int __send_request(struct request *req) + for (i = 0; i < nsg; i++) + len += sg[i].length; + +- if (unlikely(vdc_tx_dring_avail(dr) < 1)) { +- blk_stop_queue(port->disk->queue); +- err = -ENOMEM; +- goto out; +- } +- + desc = vio_dring_cur(dr); + + err = ldc_map_sg(port->vio.lp, sg, nsg, +@@ -433,21 +474,32 @@ static int __send_request(struct request *req) + port->req_id++; + dr->prod = (dr->prod + 1) & (VDC_TX_RING_SIZE - 1); + } +-out: + + return err; + } + +-static void do_vdc_request(struct request_queue *q) ++static void do_vdc_request(struct request_queue *rq) + { +- while (1) { +- struct request *req = blk_fetch_request(q); ++ struct request *req; + +- if (!req) +- break; ++ while ((req = blk_peek_request(rq)) != NULL) { ++ struct vdc_port *port; ++ struct vio_dring_state *dr; + +- if (__send_request(req) < 0) +- __blk_end_request_all(req, -EIO); ++ port = req->rq_disk->private_data; ++ dr = &port->vio.drings[VIO_DRIVER_TX_RING]; ++ if (unlikely(vdc_tx_dring_avail(dr) < 1)) ++ goto wait; ++ ++ blk_start_request(req); ++ ++ if (__send_request(req) < 0) { ++ blk_requeue_request(rq, req); ++wait: ++ /* Avoid pointless unplugs. */ ++ blk_stop_queue(rq); ++ break; ++ } + } + } + +@@ -656,25 +708,27 @@ static int probe_disk(struct vdc_port *port) + if (comp.err) + return comp.err; + +- err = generic_request(port, VD_OP_GET_VTOC, +- &port->label, sizeof(port->label)); +- if (err < 0) { +- printk(KERN_ERR PFX "VD_OP_GET_VTOC returns error %d\n", err); +- return err; +- } +- +- err = generic_request(port, VD_OP_GET_DISKGEOM, +- &port->geom, sizeof(port->geom)); +- if (err < 0) { +- printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns " +- "error %d\n", err); +- return err; ++ if (vdc_version_supported(port, 1, 1)) { ++ /* vdisk_size should be set during the handshake, if it wasn't ++ * then the underlying disk is reserved by another system ++ */ ++ if (port->vdisk_size == -1) ++ return -ENODEV; ++ } else { ++ struct vio_disk_geom geom; ++ ++ err = generic_request(port, VD_OP_GET_DISKGEOM, ++ &geom, sizeof(geom)); ++ if (err < 0) { ++ printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns " ++ "error %d\n", err); ++ return err; ++ } ++ port->vdisk_size = ((u64)geom.num_cyl * ++ (u64)geom.num_hd * ++ (u64)geom.num_sec); + } + +- port->vdisk_size = ((u64)port->geom.num_cyl * +- (u64)port->geom.num_hd * +- (u64)port->geom.num_sec); +- + q = blk_init_queue(do_vdc_request, &port->vio.lock); + if (!q) { + printk(KERN_ERR PFX "%s: Could not allocate queue.\n", +@@ -691,6 +745,10 @@ static int probe_disk(struct vdc_port *port) + + port->disk = g; + ++ /* Each segment in a request is up to an aligned page in size. */ ++ blk_queue_segment_boundary(q, PAGE_SIZE - 1); ++ blk_queue_max_segment_size(q, PAGE_SIZE); ++ + blk_queue_max_segments(q, port->ring_cookies); + blk_queue_max_hw_sectors(q, port->max_xfer_size); + g->major = vdc_major; +@@ -704,9 +762,32 @@ static int probe_disk(struct vdc_port *port) + + set_capacity(g, port->vdisk_size); + +- printk(KERN_INFO PFX "%s: %u sectors (%u MB)\n", ++ if (vdc_version_supported(port, 1, 1)) { ++ switch (port->vdisk_mtype) { ++ case VD_MEDIA_TYPE_CD: ++ pr_info(PFX "Virtual CDROM %s\n", port->disk_name); ++ g->flags |= GENHD_FL_CD; ++ g->flags |= GENHD_FL_REMOVABLE; ++ set_disk_ro(g, 1); ++ break; ++ ++ case VD_MEDIA_TYPE_DVD: ++ pr_info(PFX "Virtual DVD %s\n", port->disk_name); ++ g->flags |= GENHD_FL_CD; ++ g->flags |= GENHD_FL_REMOVABLE; ++ set_disk_ro(g, 1); ++ break; ++ ++ case VD_MEDIA_TYPE_FIXED: ++ pr_info(PFX "Virtual Hard disk %s\n", port->disk_name); ++ break; ++ } ++ } ++ ++ pr_info(PFX "%s: %u sectors (%u MB) protocol %d.%d\n", + g->disk_name, +- port->vdisk_size, (port->vdisk_size >> (20 - 9))); ++ port->vdisk_size, (port->vdisk_size >> (20 - 9)), ++ port->vio.ver.major, port->vio.ver.minor); + + add_disk(g); + +@@ -765,6 +846,7 @@ static int vdc_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) + else + snprintf(port->disk_name, sizeof(port->disk_name), + VDCBLK_NAME "%c", 'a' + ((int)vdev->dev_no % 26)); ++ port->vdisk_size = -1; + + err = vio_driver_init(&port->vio, vdev, VDEV_DISK, + vdc_versions, ARRAY_SIZE(vdc_versions), +diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c +index 51c557cfd92b..d8ddb8e2adc1 100644 +--- a/drivers/block/zram/zram_drv.c ++++ b/drivers/block/zram/zram_drv.c +@@ -447,7 +447,8 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, + } + + if (page_zero_filled(uncmem)) { +- kunmap_atomic(user_mem); ++ if (user_mem) ++ kunmap_atomic(user_mem); + /* Free memory associated with this sector now. */ + write_lock(&zram->meta->tb_lock); + zram_free_page(zram, index); +diff --git a/drivers/char/hw_random/pseries-rng.c b/drivers/char/hw_random/pseries-rng.c +index ab7ffdec0ec3..f38f2c13e79c 100644 +--- a/drivers/char/hw_random/pseries-rng.c ++++ b/drivers/char/hw_random/pseries-rng.c +@@ -25,18 +25,21 @@ + #include + + +-static int pseries_rng_data_read(struct hwrng *rng, u32 *data) ++static int pseries_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) + { ++ u64 buffer[PLPAR_HCALL_BUFSIZE]; ++ size_t size = max < 8 ? max : 8; + int rc; + +- rc = plpar_hcall(H_RANDOM, (unsigned long *)data); ++ rc = plpar_hcall(H_RANDOM, (unsigned long *)buffer); + if (rc != H_SUCCESS) { + pr_err_ratelimited("H_RANDOM call failed %d\n", rc); + return -EIO; + } ++ memcpy(data, buffer, size); + + /* The hypervisor interface returns 64 bits */ +- return 8; ++ return size; + } + + /** +@@ -55,7 +58,7 @@ static unsigned long pseries_rng_get_desired_dma(struct vio_dev *vdev) + + static struct hwrng pseries_rng = { + .name = KBUILD_MODNAME, +- .data_read = pseries_rng_data_read, ++ .read = pseries_rng_read, + }; + + static int __init pseries_rng_probe(struct vio_dev *dev, +diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c +index a4127453baae..d97a03dbf42c 100644 +--- a/drivers/crypto/caam/caamhash.c ++++ b/drivers/crypto/caam/caamhash.c +@@ -835,8 +835,9 @@ static int ahash_update_ctx(struct ahash_request *req) + edesc->sec4_sg + sec4_sg_src_index, + chained); + if (*next_buflen) { +- sg_copy_part(next_buf, req->src, to_hash - +- *buflen, req->nbytes); ++ scatterwalk_map_and_copy(next_buf, req->src, ++ to_hash - *buflen, ++ *next_buflen, 0); + state->current_buf = !state->current_buf; + } + } else { +@@ -869,7 +870,8 @@ static int ahash_update_ctx(struct ahash_request *req) + kfree(edesc); + } + } else if (*next_buflen) { +- sg_copy(buf + *buflen, req->src, req->nbytes); ++ scatterwalk_map_and_copy(buf + *buflen, req->src, 0, ++ req->nbytes, 0); + *buflen = *next_buflen; + *next_buflen = last_buflen; + } +@@ -1216,8 +1218,9 @@ static int ahash_update_no_ctx(struct ahash_request *req) + src_map_to_sec4_sg(jrdev, req->src, src_nents, + edesc->sec4_sg + 1, chained); + if (*next_buflen) { +- sg_copy_part(next_buf, req->src, to_hash - *buflen, +- req->nbytes); ++ scatterwalk_map_and_copy(next_buf, req->src, ++ to_hash - *buflen, ++ *next_buflen, 0); + state->current_buf = !state->current_buf; + } + +@@ -1248,7 +1251,8 @@ static int ahash_update_no_ctx(struct ahash_request *req) + kfree(edesc); + } + } else if (*next_buflen) { +- sg_copy(buf + *buflen, req->src, req->nbytes); ++ scatterwalk_map_and_copy(buf + *buflen, req->src, 0, ++ req->nbytes, 0); + *buflen = *next_buflen; + *next_buflen = 0; + } +@@ -1405,7 +1409,8 @@ static int ahash_update_first(struct ahash_request *req) + } + + if (*next_buflen) +- sg_copy_part(next_buf, req->src, to_hash, req->nbytes); ++ scatterwalk_map_and_copy(next_buf, req->src, to_hash, ++ *next_buflen, 0); + + sh_len = desc_len(sh_desc); + desc = edesc->hw_desc; +@@ -1438,7 +1443,8 @@ static int ahash_update_first(struct ahash_request *req) + state->update = ahash_update_no_ctx; + state->finup = ahash_finup_no_ctx; + state->final = ahash_final_no_ctx; +- sg_copy(next_buf, req->src, req->nbytes); ++ scatterwalk_map_and_copy(next_buf, req->src, 0, ++ req->nbytes, 0); + } + #ifdef DEBUG + print_hex_dump(KERN_ERR, "next buf@"__stringify(__LINE__)": ", +diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c +index ea2e406610eb..b872eed2957b 100644 +--- a/drivers/crypto/caam/key_gen.c ++++ b/drivers/crypto/caam/key_gen.c +@@ -51,23 +51,29 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len, + u32 *desc; + struct split_key_result result; + dma_addr_t dma_addr_in, dma_addr_out; +- int ret = 0; ++ int ret = -ENOMEM; + + desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA); + if (!desc) { + dev_err(jrdev, "unable to allocate key input memory\n"); +- return -ENOMEM; ++ return ret; + } + +- init_job_desc(desc, 0); +- + dma_addr_in = dma_map_single(jrdev, (void *)key_in, keylen, + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, dma_addr_in)) { + dev_err(jrdev, "unable to map key input memory\n"); +- kfree(desc); +- return -ENOMEM; ++ goto out_free; + } ++ ++ dma_addr_out = dma_map_single(jrdev, key_out, split_key_pad_len, ++ DMA_FROM_DEVICE); ++ if (dma_mapping_error(jrdev, dma_addr_out)) { ++ dev_err(jrdev, "unable to map key output memory\n"); ++ goto out_unmap_in; ++ } ++ ++ init_job_desc(desc, 0); + append_key(desc, dma_addr_in, keylen, CLASS_2 | KEY_DEST_CLASS_REG); + + /* Sets MDHA up into an HMAC-INIT */ +@@ -84,13 +90,6 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len, + * FIFO_STORE with the explicit split-key content store + * (0x26 output type) + */ +- dma_addr_out = dma_map_single(jrdev, key_out, split_key_pad_len, +- DMA_FROM_DEVICE); +- if (dma_mapping_error(jrdev, dma_addr_out)) { +- dev_err(jrdev, "unable to map key output memory\n"); +- kfree(desc); +- return -ENOMEM; +- } + append_fifo_store(desc, dma_addr_out, split_key_len, + LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK); + +@@ -118,10 +117,10 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len, + + dma_unmap_single(jrdev, dma_addr_out, split_key_pad_len, + DMA_FROM_DEVICE); ++out_unmap_in: + dma_unmap_single(jrdev, dma_addr_in, keylen, DMA_TO_DEVICE); +- ++out_free: + kfree(desc); +- + return ret; + } + EXPORT_SYMBOL(gen_split_key); +diff --git a/drivers/crypto/caam/sg_sw_sec4.h b/drivers/crypto/caam/sg_sw_sec4.h +index b12ff85f4241..ce28a563effc 100644 +--- a/drivers/crypto/caam/sg_sw_sec4.h ++++ b/drivers/crypto/caam/sg_sw_sec4.h +@@ -116,57 +116,3 @@ static int dma_unmap_sg_chained(struct device *dev, struct scatterlist *sg, + } + return nents; + } +- +-/* Map SG page in kernel virtual address space and copy */ +-static inline void sg_map_copy(u8 *dest, struct scatterlist *sg, +- int len, int offset) +-{ +- u8 *mapped_addr; +- +- /* +- * Page here can be user-space pinned using get_user_pages +- * Same must be kmapped before use and kunmapped subsequently +- */ +- mapped_addr = kmap_atomic(sg_page(sg)); +- memcpy(dest, mapped_addr + offset, len); +- kunmap_atomic(mapped_addr); +-} +- +-/* Copy from len bytes of sg to dest, starting from beginning */ +-static inline void sg_copy(u8 *dest, struct scatterlist *sg, unsigned int len) +-{ +- struct scatterlist *current_sg = sg; +- int cpy_index = 0, next_cpy_index = current_sg->length; +- +- while (next_cpy_index < len) { +- sg_map_copy(dest + cpy_index, current_sg, current_sg->length, +- current_sg->offset); +- current_sg = scatterwalk_sg_next(current_sg); +- cpy_index = next_cpy_index; +- next_cpy_index += current_sg->length; +- } +- if (cpy_index < len) +- sg_map_copy(dest + cpy_index, current_sg, len-cpy_index, +- current_sg->offset); +-} +- +-/* Copy sg data, from to_skip to end, to dest */ +-static inline void sg_copy_part(u8 *dest, struct scatterlist *sg, +- int to_skip, unsigned int end) +-{ +- struct scatterlist *current_sg = sg; +- int sg_index, cpy_index, offset; +- +- sg_index = current_sg->length; +- while (sg_index <= to_skip) { +- current_sg = scatterwalk_sg_next(current_sg); +- sg_index += current_sg->length; +- } +- cpy_index = sg_index - to_skip; +- offset = current_sg->offset + current_sg->length - cpy_index; +- sg_map_copy(dest, current_sg, cpy_index, offset); +- if (end - sg_index) { +- current_sg = scatterwalk_sg_next(current_sg); +- sg_copy(dest + cpy_index, current_sg, end - sg_index); +- } +-} +diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c +index d7d5c8af92b9..6d4456898007 100644 +--- a/drivers/firewire/core-cdev.c ++++ b/drivers/firewire/core-cdev.c +@@ -1637,8 +1637,7 @@ static int dispatch_ioctl(struct client *client, + _IOC_SIZE(cmd) > sizeof(buffer)) + return -ENOTTY; + +- if (_IOC_DIR(cmd) == _IOC_READ) +- memset(&buffer, 0, _IOC_SIZE(cmd)); ++ memset(&buffer, 0, sizeof(buffer)); + + if (_IOC_DIR(cmd) & _IOC_WRITE) + if (copy_from_user(&buffer, arg, _IOC_SIZE(cmd))) +diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c +index ab5c26575622..ddf70d6c0270 100644 +--- a/drivers/gpu/drm/radeon/cik.c ++++ b/drivers/gpu/drm/radeon/cik.c +@@ -3936,8 +3936,8 @@ static int cik_cp_gfx_start(struct radeon_device *rdev) + /* init the CE partitions. CE only used for gfx on CIK */ + radeon_ring_write(ring, PACKET3(PACKET3_SET_BASE, 2)); + radeon_ring_write(ring, PACKET3_BASE_INDEX(CE_PARTITION_BASE)); +- radeon_ring_write(ring, 0xc000); +- radeon_ring_write(ring, 0xc000); ++ radeon_ring_write(ring, 0x8000); ++ radeon_ring_write(ring, 0x8000); + + /* setup clear context state */ + radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); +@@ -8893,6 +8893,9 @@ void dce8_bandwidth_update(struct radeon_device *rdev) + u32 num_heads = 0, lb_size; + int i; + ++ if (!rdev->mode_info.mode_config_initialized) ++ return; ++ + radeon_update_display_priority(rdev); + + for (i = 0; i < rdev->num_crtc; i++) { +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index 4b3c5f7ae63b..7138f3e31b7c 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -2362,6 +2362,9 @@ void evergreen_bandwidth_update(struct radeon_device *rdev) + u32 num_heads = 0, lb_size; + int i; + ++ if (!rdev->mode_info.mode_config_initialized) ++ return; ++ + radeon_update_display_priority(rdev); + + for (i = 0; i < rdev->num_crtc; i++) { +@@ -2570,6 +2573,7 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; + WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); ++ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); + } + } else { + tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); +diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c +index 3cc78bb66042..07620e198a6d 100644 +--- a/drivers/gpu/drm/radeon/r100.c ++++ b/drivers/gpu/drm/radeon/r100.c +@@ -3219,6 +3219,9 @@ void r100_bandwidth_update(struct radeon_device *rdev) + uint32_t pixel_bytes1 = 0; + uint32_t pixel_bytes2 = 0; + ++ if (!rdev->mode_info.mode_config_initialized) ++ return; ++ + radeon_update_display_priority(rdev); + + if (rdev->mode_info.crtcs[0]->base.enabled) { +diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c +index 95b693c11640..e5619d5e2a30 100644 +--- a/drivers/gpu/drm/radeon/rs600.c ++++ b/drivers/gpu/drm/radeon/rs600.c +@@ -890,6 +890,9 @@ void rs600_bandwidth_update(struct radeon_device *rdev) + u32 d1mode_priority_a_cnt, d2mode_priority_a_cnt; + /* FIXME: implement full support */ + ++ if (!rdev->mode_info.mode_config_initialized) ++ return; ++ + radeon_update_display_priority(rdev); + + if (rdev->mode_info.crtcs[0]->base.enabled) +diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c +index 3462b64369bf..0a2d36e81108 100644 +--- a/drivers/gpu/drm/radeon/rs690.c ++++ b/drivers/gpu/drm/radeon/rs690.c +@@ -579,6 +579,9 @@ void rs690_bandwidth_update(struct radeon_device *rdev) + u32 d1mode_priority_a_cnt, d1mode_priority_b_cnt; + u32 d2mode_priority_a_cnt, d2mode_priority_b_cnt; + ++ if (!rdev->mode_info.mode_config_initialized) ++ return; ++ + radeon_update_display_priority(rdev); + + if (rdev->mode_info.crtcs[0]->base.enabled) +diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c +index 237dd29d9f1c..b49965a21a2d 100644 +--- a/drivers/gpu/drm/radeon/rv515.c ++++ b/drivers/gpu/drm/radeon/rv515.c +@@ -1276,6 +1276,9 @@ void rv515_bandwidth_update(struct radeon_device *rdev) + struct drm_display_mode *mode0 = NULL; + struct drm_display_mode *mode1 = NULL; + ++ if (!rdev->mode_info.mode_config_initialized) ++ return; ++ + radeon_update_display_priority(rdev); + + if (rdev->mode_info.crtcs[0]->base.enabled) +diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c +index 559564c1dc97..52b64ad285d6 100644 +--- a/drivers/gpu/drm/radeon/si.c ++++ b/drivers/gpu/drm/radeon/si.c +@@ -2227,6 +2227,9 @@ void dce6_bandwidth_update(struct radeon_device *rdev) + u32 num_heads = 0, lb_size; + int i; + ++ if (!rdev->mode_info.mode_config_initialized) ++ return; ++ + radeon_update_display_priority(rdev); + + for (i = 0; i < rdev->num_crtc; i++) { +diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c +index ea6203ee7bcc..23467a2abd62 100644 +--- a/drivers/infiniband/core/uverbs_cmd.c ++++ b/drivers/infiniband/core/uverbs_cmd.c +@@ -2425,6 +2425,8 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, + attr.grh.sgid_index = cmd.attr.grh.sgid_index; + attr.grh.hop_limit = cmd.attr.grh.hop_limit; + attr.grh.traffic_class = cmd.attr.grh.traffic_class; ++ attr.vlan_id = 0; ++ memset(&attr.dmac, 0, sizeof(attr.dmac)); + memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16); + + ah = ib_create_ah(pd, &attr); +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index fb15c64ffb95..4979b00fbf04 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -1047,7 +1047,13 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; + +- if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ ++ /* ++ * Check if we are dealing with a bare PS/2 packet, presumably from ++ * a device connected to the external PS/2 port. Because bare PS/2 ++ * protocol does not have enough constant bits to self-synchronize ++ * properly we only do this if the device is fully synchronized. ++ */ ++ if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) { + if (psmouse->pktcnt == 3) { + alps_report_bare_ps2_packet(psmouse, psmouse->packet, + true); +@@ -1071,12 +1077,27 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + } + + /* Bytes 2 - pktsize should have 0 in the highest bit */ +- if ((priv->proto_version < ALPS_PROTO_V5) && ++ if (priv->proto_version < ALPS_PROTO_V5 && + psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && + (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { + psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", + psmouse->pktcnt - 1, + psmouse->packet[psmouse->pktcnt - 1]); ++ ++ if (priv->proto_version == ALPS_PROTO_V3 && ++ psmouse->pktcnt == psmouse->pktsize) { ++ /* ++ * Some Dell boxes, such as Latitude E6440 or E7440 ++ * with closed lid, quite often smash last byte of ++ * otherwise valid packet with 0xff. Given that the ++ * next packet is very likely to be valid let's ++ * report PSMOUSE_FULL_PACKET but not process data, ++ * rather than reporting PSMOUSE_BAD_DATA and ++ * filling the logs. ++ */ ++ return PSMOUSE_FULL_PACKET; ++ } ++ + return PSMOUSE_BAD_DATA; + } + +@@ -2148,6 +2169,9 @@ int alps_init(struct psmouse *psmouse) + /* We are having trouble resyncing ALPS touchpads so disable it for now */ + psmouse->resync_time = 0; + ++ /* Allow 2 invalid packets without resetting device */ ++ psmouse->resetafter = psmouse->pktsize * 2; ++ + return 0; + + init_fail: +diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c +index a50a2a7a43f7..1e76eb8f06c7 100644 +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -132,8 +132,8 @@ static const struct min_max_quirk min_max_pnpid_table[] = { + 1232, 5710, 1156, 4696 + }, + { +- (const char * const []){"LEN0034", "LEN0036", "LEN2002", +- "LEN2004", NULL}, ++ (const char * const []){"LEN0034", "LEN0036", "LEN0039", ++ "LEN2002", "LEN2004", NULL}, + 1024, 5112, 2024, 4832 + }, + { +@@ -160,6 +160,7 @@ static const char * const topbuttonpad_pnp_ids[] = { + "LEN0036", /* T440 */ + "LEN0037", + "LEN0038", ++ "LEN0039", /* T440s */ + "LEN0041", + "LEN0042", /* Yoga */ + "LEN0045", +diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c +index ca1621b49453..a1cebf745b22 100644 +--- a/drivers/md/dm-bufio.c ++++ b/drivers/md/dm-bufio.c +@@ -1448,9 +1448,9 @@ static void drop_buffers(struct dm_bufio_client *c) + + /* + * Test if the buffer is unused and too old, and commit it. +- * At if noio is set, we must not do any I/O because we hold +- * dm_bufio_clients_lock and we would risk deadlock if the I/O gets rerouted to +- * different bufio client. ++ * And if GFP_NOFS is used, we must not do any I/O because we hold ++ * dm_bufio_clients_lock and we would risk deadlock if the I/O gets ++ * rerouted to different bufio client. + */ + static int __cleanup_old_buffer(struct dm_buffer *b, gfp_t gfp, + unsigned long max_jiffies) +@@ -1458,7 +1458,7 @@ static int __cleanup_old_buffer(struct dm_buffer *b, gfp_t gfp, + if (jiffies - b->last_accessed < max_jiffies) + return 0; + +- if (!(gfp & __GFP_IO)) { ++ if (!(gfp & __GFP_FS)) { + if (test_bit(B_READING, &b->state) || + test_bit(B_WRITING, &b->state) || + test_bit(B_DIRTY, &b->state)) +@@ -1500,7 +1500,7 @@ dm_bufio_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) + unsigned long freed; + + c = container_of(shrink, struct dm_bufio_client, shrinker); +- if (sc->gfp_mask & __GFP_IO) ++ if (sc->gfp_mask & __GFP_FS) + dm_bufio_lock(c); + else if (!dm_bufio_trylock(c)) + return SHRINK_STOP; +@@ -1517,7 +1517,7 @@ dm_bufio_shrink_count(struct shrinker *shrink, struct shrink_control *sc) + unsigned long count; + + c = container_of(shrink, struct dm_bufio_client, shrinker); +- if (sc->gfp_mask & __GFP_IO) ++ if (sc->gfp_mask & __GFP_FS) + dm_bufio_lock(c); + else if (!dm_bufio_trylock(c)) + return 0; +diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c +index 4880b69e2e9e..59715389b3cf 100644 +--- a/drivers/md/dm-raid.c ++++ b/drivers/md/dm-raid.c +@@ -785,8 +785,7 @@ struct dm_raid_superblock { + __le32 layout; + __le32 stripe_sectors; + +- __u8 pad[452]; /* Round struct to 512 bytes. */ +- /* Always set to 0 when writing. */ ++ /* Remainder of a logical block is zero-filled when writing (see super_sync()). */ + } __packed; + + static int read_disk_sb(struct md_rdev *rdev, int size) +@@ -823,7 +822,7 @@ static void super_sync(struct mddev *mddev, struct md_rdev *rdev) + test_bit(Faulty, &(rs->dev[i].rdev.flags))) + failed_devices |= (1ULL << i); + +- memset(sb, 0, sizeof(*sb)); ++ memset(sb + 1, 0, rdev->sb_size - sizeof(*sb)); + + sb->magic = cpu_to_le32(DM_RAID_MAGIC); + sb->features = cpu_to_le32(0); /* No features yet */ +@@ -858,7 +857,11 @@ static int super_load(struct md_rdev *rdev, struct md_rdev *refdev) + uint64_t events_sb, events_refsb; + + rdev->sb_start = 0; +- rdev->sb_size = sizeof(*sb); ++ rdev->sb_size = bdev_logical_block_size(rdev->meta_bdev); ++ if (rdev->sb_size < sizeof(*sb) || rdev->sb_size > PAGE_SIZE) { ++ DMERR("superblock size of a logical block is no longer valid"); ++ return -EINVAL; ++ } + + ret = read_disk_sb(rdev, rdev->sb_size); + if (ret) +diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c +index 359af3a519b5..37f2648c112b 100644 +--- a/drivers/md/dm-thin.c ++++ b/drivers/md/dm-thin.c +@@ -1704,6 +1704,14 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) + return DM_MAPIO_SUBMITTED; + } + ++ /* ++ * We must hold the virtual cell before doing the lookup, otherwise ++ * there's a race with discard. ++ */ ++ build_virtual_key(tc->td, block, &key); ++ if (dm_bio_detain(tc->pool->prison, &key, bio, &cell1, &cell_result)) ++ return DM_MAPIO_SUBMITTED; ++ + r = dm_thin_find_block(td, block, 0, &result); + + /* +@@ -1727,13 +1735,10 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) + * shared flag will be set in their case. + */ + thin_defer_bio(tc, bio); ++ cell_defer_no_holder_no_free(tc, &cell1); + return DM_MAPIO_SUBMITTED; + } + +- build_virtual_key(tc->td, block, &key); +- if (dm_bio_detain(tc->pool->prison, &key, bio, &cell1, &cell_result)) +- return DM_MAPIO_SUBMITTED; +- + build_data_key(tc->td, result.block, &key); + if (dm_bio_detain(tc->pool->prison, &key, bio, &cell2, &cell_result)) { + cell_defer_no_holder_no_free(tc, &cell1); +@@ -1754,6 +1759,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) + * of doing so. + */ + handle_unserviceable_bio(tc->pool, bio); ++ cell_defer_no_holder_no_free(tc, &cell1); + return DM_MAPIO_SUBMITTED; + } + /* fall through */ +@@ -1764,6 +1770,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) + * provide the hint to load the metadata into cache. + */ + thin_defer_bio(tc, bio); ++ cell_defer_no_holder_no_free(tc, &cell1); + return DM_MAPIO_SUBMITTED; + + default: +@@ -1773,6 +1780,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) + * pool is switched to fail-io mode. + */ + bio_io_error(bio); ++ cell_defer_no_holder_no_free(tc, &cell1); + return DM_MAPIO_SUBMITTED; + } + } +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 73aedcb639c0..40959ee73583 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -5333,6 +5333,7 @@ static int md_set_readonly(struct mddev *mddev, struct block_device *bdev) + printk("md: %s still in use.\n",mdname(mddev)); + if (did_freeze) { + clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); ++ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); + } + err = -EBUSY; +@@ -5347,6 +5348,8 @@ static int md_set_readonly(struct mddev *mddev, struct block_device *bdev) + mddev->ro = 1; + set_disk_ro(mddev->gendisk, 1); + clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); ++ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); ++ md_wakeup_thread(mddev->thread); + sysfs_notify_dirent_safe(mddev->sysfs_state); + err = 0; + } +@@ -5390,6 +5393,7 @@ static int do_md_stop(struct mddev * mddev, int mode, + mutex_unlock(&mddev->open_mutex); + if (did_freeze) { + clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); ++ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); + } + return -EBUSY; +diff --git a/drivers/md/persistent-data/dm-btree-internal.h b/drivers/md/persistent-data/dm-btree-internal.h +index 37d367bb9aa8..bf2b80d5c470 100644 +--- a/drivers/md/persistent-data/dm-btree-internal.h ++++ b/drivers/md/persistent-data/dm-btree-internal.h +@@ -42,6 +42,12 @@ struct btree_node { + } __packed; + + ++/* ++ * Locks a block using the btree node validator. ++ */ ++int bn_read_lock(struct dm_btree_info *info, dm_block_t b, ++ struct dm_block **result); ++ + void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, + struct dm_btree_value_type *vt); + +diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c +index cf9fd676ae44..1b5e13ec7f96 100644 +--- a/drivers/md/persistent-data/dm-btree-spine.c ++++ b/drivers/md/persistent-data/dm-btree-spine.c +@@ -92,7 +92,7 @@ struct dm_block_validator btree_node_validator = { + + /*----------------------------------------------------------------*/ + +-static int bn_read_lock(struct dm_btree_info *info, dm_block_t b, ++int bn_read_lock(struct dm_btree_info *info, dm_block_t b, + struct dm_block **result) + { + return dm_tm_read_lock(info->tm, b, &btree_node_validator, result); +diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c +index 416060c25709..200ac12a1d40 100644 +--- a/drivers/md/persistent-data/dm-btree.c ++++ b/drivers/md/persistent-data/dm-btree.c +@@ -847,22 +847,26 @@ EXPORT_SYMBOL_GPL(dm_btree_find_lowest_key); + * FIXME: We shouldn't use a recursive algorithm when we have limited stack + * space. Also this only works for single level trees. + */ +-static int walk_node(struct ro_spine *s, dm_block_t block, ++static int walk_node(struct dm_btree_info *info, dm_block_t block, + int (*fn)(void *context, uint64_t *keys, void *leaf), + void *context) + { + int r; + unsigned i, nr; ++ struct dm_block *node; + struct btree_node *n; + uint64_t keys; + +- r = ro_step(s, block); +- n = ro_node(s); ++ r = bn_read_lock(info, block, &node); ++ if (r) ++ return r; ++ ++ n = dm_block_data(node); + + nr = le32_to_cpu(n->header.nr_entries); + for (i = 0; i < nr; i++) { + if (le32_to_cpu(n->header.flags) & INTERNAL_NODE) { +- r = walk_node(s, value64(n, i), fn, context); ++ r = walk_node(info, value64(n, i), fn, context); + if (r) + goto out; + } else { +@@ -874,7 +878,7 @@ static int walk_node(struct ro_spine *s, dm_block_t block, + } + + out: +- ro_pop(s); ++ dm_tm_unlock(info->tm, node); + return r; + } + +@@ -882,15 +886,7 @@ int dm_btree_walk(struct dm_btree_info *info, dm_block_t root, + int (*fn)(void *context, uint64_t *keys, void *leaf), + void *context) + { +- int r; +- struct ro_spine spine; +- + BUG_ON(info->levels > 1); +- +- init_ro_spine(&spine, info); +- r = walk_node(&spine, root, fn, context); +- exit_ro_spine(&spine); +- +- return r; ++ return walk_node(info, root, fn, context); + } + EXPORT_SYMBOL_GPL(dm_btree_walk); +diff --git a/drivers/media/usb/ttusb-dec/ttusbdecfe.c b/drivers/media/usb/ttusb-dec/ttusbdecfe.c +index 5c45c9d0712d..9c29552aedec 100644 +--- a/drivers/media/usb/ttusb-dec/ttusbdecfe.c ++++ b/drivers/media/usb/ttusb-dec/ttusbdecfe.c +@@ -156,6 +156,9 @@ static int ttusbdecfe_dvbs_diseqc_send_master_cmd(struct dvb_frontend* fe, struc + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 }; + ++ if (cmd->msg_len > sizeof(b) - 4) ++ return -EINVAL; ++ + memcpy(&b[4], cmd->msg, cmd->msg_len); + + state->config->send_command(fe, 0x72, +diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c +index 6382b7c416f4..e10f5ed26181 100644 +--- a/drivers/net/ethernet/smsc/smsc911x.c ++++ b/drivers/net/ethernet/smsc/smsc911x.c +@@ -1341,6 +1341,42 @@ static void smsc911x_rx_multicast_update_workaround(struct smsc911x_data *pdata) + spin_unlock(&pdata->mac_lock); + } + ++static int smsc911x_phy_general_power_up(struct smsc911x_data *pdata) ++{ ++ int rc = 0; ++ ++ if (!pdata->phy_dev) ++ return rc; ++ ++ /* If the internal PHY is in General Power-Down mode, all, except the ++ * management interface, is powered-down and stays in that condition as ++ * long as Phy register bit 0.11 is HIGH. ++ * ++ * In that case, clear the bit 0.11, so the PHY powers up and we can ++ * access to the phy registers. ++ */ ++ rc = phy_read(pdata->phy_dev, MII_BMCR); ++ if (rc < 0) { ++ SMSC_WARN(pdata, drv, "Failed reading PHY control reg"); ++ return rc; ++ } ++ ++ /* If the PHY general power-down bit is not set is not necessary to ++ * disable the general power down-mode. ++ */ ++ if (rc & BMCR_PDOWN) { ++ rc = phy_write(pdata->phy_dev, MII_BMCR, rc & ~BMCR_PDOWN); ++ if (rc < 0) { ++ SMSC_WARN(pdata, drv, "Failed writing PHY control reg"); ++ return rc; ++ } ++ ++ usleep_range(1000, 1500); ++ } ++ ++ return 0; ++} ++ + static int smsc911x_phy_disable_energy_detect(struct smsc911x_data *pdata) + { + int rc = 0; +@@ -1414,6 +1450,16 @@ static int smsc911x_soft_reset(struct smsc911x_data *pdata) + int ret; + + /* ++ * Make sure to power-up the PHY chip before doing a reset, otherwise ++ * the reset fails. ++ */ ++ ret = smsc911x_phy_general_power_up(pdata); ++ if (ret) { ++ SMSC_WARN(pdata, drv, "Failed to power-up the PHY chip"); ++ return ret; ++ } ++ ++ /* + * LAN9210/LAN9211/LAN9220/LAN9221 chips have an internal PHY that + * are initialized in a Energy Detect Power-Down mode that prevents + * the MAC chip to be software reseted. So we have to wakeup the PHY +diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c +index fd411d6e19a2..03ae9def0e0c 100644 +--- a/drivers/net/ethernet/sun/sunvnet.c ++++ b/drivers/net/ethernet/sun/sunvnet.c +@@ -656,7 +656,7 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) + spin_lock_irqsave(&port->vio.lock, flags); + + dr = &port->vio.drings[VIO_DRIVER_TX_RING]; +- if (unlikely(vnet_tx_dring_avail(dr) < 2)) { ++ if (unlikely(vnet_tx_dring_avail(dr) < 1)) { + if (!netif_queue_stopped(dev)) { + netif_stop_queue(dev); + +@@ -704,7 +704,7 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) + dev->stats.tx_bytes += skb->len; + + dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1); +- if (unlikely(vnet_tx_dring_avail(dr) < 2)) { ++ if (unlikely(vnet_tx_dring_avail(dr) < 1)) { + netif_stop_queue(dev); + if (vnet_tx_dring_avail(dr) > VNET_TX_WAKEUP_THRESH(dr)) + netif_wake_queue(dev); +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index f30ceb17d5fc..07c942b6ae01 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -66,7 +66,7 @@ static struct cdev macvtap_cdev; + static const struct proto_ops macvtap_socket_ops; + + #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ +- NETIF_F_TSO6) ++ NETIF_F_TSO6 | NETIF_F_UFO) + #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO) + #define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG) + +@@ -570,8 +570,6 @@ static int macvtap_skb_from_vnet_hdr(struct sk_buff *skb, + gso_type = SKB_GSO_TCPV6; + break; + case VIRTIO_NET_HDR_GSO_UDP: +- pr_warn_once("macvtap: %s: using disabled UFO feature; please fix this program\n", +- current->comm); + gso_type = SKB_GSO_UDP; + if (skb->protocol == htons(ETH_P_IPV6)) + ipv6_proxy_select_ident(skb); +@@ -619,6 +617,8 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, + vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; + else if (sinfo->gso_type & SKB_GSO_TCPV6) + vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; ++ else if (sinfo->gso_type & SKB_GSO_UDP) ++ vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP; + else + BUG(); + if (sinfo->gso_type & SKB_GSO_TCP_ECN) +@@ -629,6 +629,8 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, + if (skb->ip_summed == CHECKSUM_PARTIAL) { + vnet_hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; + vnet_hdr->csum_start = skb_checksum_start_offset(skb); ++ if (vlan_tx_tag_present(skb)) ++ vnet_hdr->csum_start += VLAN_HLEN; + vnet_hdr->csum_offset = skb->csum_offset; + } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + vnet_hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID; +@@ -953,6 +955,9 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg) + if (arg & TUN_F_TSO6) + feature_mask |= NETIF_F_TSO6; + } ++ ++ if (arg & TUN_F_UFO) ++ feature_mask |= NETIF_F_UFO; + } + + /* tun/tap driver inverts the usage for TSO offloads, where +@@ -963,7 +968,7 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg) + * When user space turns off TSO, we turn off GSO/LRO so that + * user-space will not receive TSO frames. + */ +- if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6)) ++ if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO)) + features |= RX_OFFLOADS; + else + features &= ~RX_OFFLOADS; +@@ -1064,7 +1069,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, + case TUNSETOFFLOAD: + /* let the user check for future flags */ + if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | +- TUN_F_TSO_ECN)) ++ TUN_F_TSO_ECN | TUN_F_UFO)) + return -EINVAL; + + rtnl_lock(); +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index 2c8b1c21c452..ec63314d6480 100644 +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -175,7 +175,7 @@ struct tun_struct { + struct net_device *dev; + netdev_features_t set_features; + #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ +- NETIF_F_TSO6) ++ NETIF_F_TSO6|NETIF_F_UFO) + + int vnet_hdr_sz; + int sndbuf; +@@ -1153,20 +1153,10 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; + break; + case VIRTIO_NET_HDR_GSO_UDP: +- { +- static bool warned; +- +- if (!warned) { +- warned = true; +- netdev_warn(tun->dev, +- "%s: using disabled UFO feature; please fix this program\n", +- current->comm); +- } + skb_shinfo(skb)->gso_type = SKB_GSO_UDP; + if (skb->protocol == htons(ETH_P_IPV6)) + ipv6_proxy_select_ident(skb); + break; +- } + default: + tun->dev->stats.rx_frame_errors++; + kfree_skb(skb); +@@ -1236,6 +1226,10 @@ static ssize_t tun_put_user(struct tun_struct *tun, + struct tun_pi pi = { 0, skb->protocol }; + ssize_t total = 0; + int vlan_offset = 0, copied; ++ int vlan_hlen = 0; ++ ++ if (vlan_tx_tag_present(skb)) ++ vlan_hlen = VLAN_HLEN; + + if (!(tun->flags & TUN_NO_PI)) { + if ((len -= sizeof(pi)) < 0) +@@ -1266,6 +1260,8 @@ static ssize_t tun_put_user(struct tun_struct *tun, + gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; + else if (sinfo->gso_type & SKB_GSO_TCPV6) + gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; ++ else if (sinfo->gso_type & SKB_GSO_UDP) ++ gso.gso_type = VIRTIO_NET_HDR_GSO_UDP; + else { + pr_err("unexpected GSO type: " + "0x%x, gso_size %d, hdr_len %d\n", +@@ -1285,7 +1281,8 @@ static ssize_t tun_put_user(struct tun_struct *tun, + + if (skb->ip_summed == CHECKSUM_PARTIAL) { + gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; +- gso.csum_start = skb_checksum_start_offset(skb); ++ gso.csum_start = skb_checksum_start_offset(skb) + ++ vlan_hlen; + gso.csum_offset = skb->csum_offset; + } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + gso.flags = VIRTIO_NET_HDR_F_DATA_VALID; +@@ -1298,10 +1295,9 @@ static ssize_t tun_put_user(struct tun_struct *tun, + } + + copied = total; +- total += skb->len; +- if (!vlan_tx_tag_present(skb)) { +- len = min_t(int, skb->len, len); +- } else { ++ len = min_t(int, skb->len + vlan_hlen, len); ++ total += skb->len + vlan_hlen; ++ if (vlan_hlen) { + int copy, ret; + struct { + __be16 h_vlan_proto; +@@ -1312,8 +1308,6 @@ static ssize_t tun_put_user(struct tun_struct *tun, + veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb)); + + vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); +- len = min_t(int, skb->len + VLAN_HLEN, len); +- total += VLAN_HLEN; + + copy = min_t(int, vlan_offset, len); + ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy); +@@ -1795,6 +1789,11 @@ static int set_offload(struct tun_struct *tun, unsigned long arg) + features |= NETIF_F_TSO6; + arg &= ~(TUN_F_TSO4|TUN_F_TSO6); + } ++ ++ if (arg & TUN_F_UFO) { ++ features |= NETIF_F_UFO; ++ arg &= ~TUN_F_UFO; ++ } + } + + /* This gives the user a way to test for new features in future by +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index 07a3255fd3cc..841b60831df1 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -496,17 +496,8 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; + break; + case VIRTIO_NET_HDR_GSO_UDP: +- { +- static bool warned; +- +- if (!warned) { +- warned = true; +- netdev_warn(dev, +- "host using disabled UFO feature; please fix it\n"); +- } + skb_shinfo(skb)->gso_type = SKB_GSO_UDP; + break; +- } + case VIRTIO_NET_HDR_GSO_TCPV6: + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; + break; +@@ -845,6 +836,8 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) + hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; + else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) + hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; ++ else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) ++ hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_UDP; + else + BUG(); + if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN) +@@ -1664,7 +1657,7 @@ static int virtnet_probe(struct virtio_device *vdev) + dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; + + if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) { +- dev->hw_features |= NETIF_F_TSO ++ dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO + | NETIF_F_TSO_ECN | NETIF_F_TSO6; + } + /* Individual feature bits: what can host handle? */ +@@ -1674,9 +1667,11 @@ static int virtnet_probe(struct virtio_device *vdev) + dev->hw_features |= NETIF_F_TSO6; + if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN)) + dev->hw_features |= NETIF_F_TSO_ECN; ++ if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO)) ++ dev->hw_features |= NETIF_F_UFO; + + if (gso) +- dev->features |= dev->hw_features & NETIF_F_ALL_TSO; ++ dev->features |= dev->hw_features & (NETIF_F_ALL_TSO|NETIF_F_UFO); + /* (!csum && gso) case will be fixed by register_netdev() */ + } + if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM)) +@@ -1716,7 +1711,8 @@ static int virtnet_probe(struct virtio_device *vdev) + /* If we can receive ANY GSO packets, we must allocate large ones. */ + if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) || + virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) || +- virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN)) ++ virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN) || ++ virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UFO)) + vi->big_packets = true; + + if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) +@@ -1907,9 +1903,9 @@ static struct virtio_device_id id_table[] = { + static unsigned int features[] = { + VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, + VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC, +- VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_TSO6, ++ VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, + VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, +- VIRTIO_NET_F_GUEST_ECN, ++ VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO, + VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, + VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, + VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, +diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c +index 0704a0402897..5441b49ef89d 100644 +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -279,13 +279,15 @@ static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb) + return list_first_entry(&fdb->remotes, struct vxlan_rdst, list); + } + +-/* Find VXLAN socket based on network namespace and UDP port */ +-static struct vxlan_sock *vxlan_find_sock(struct net *net, __be16 port) ++/* Find VXLAN socket based on network namespace, address family and UDP port */ ++static struct vxlan_sock *vxlan_find_sock(struct net *net, ++ sa_family_t family, __be16 port) + { + struct vxlan_sock *vs; + + hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) { +- if (inet_sk(vs->sock->sk)->inet_sport == port) ++ if (inet_sk(vs->sock->sk)->inet_sport == port && ++ inet_sk(vs->sock->sk)->sk.sk_family == family) + return vs; + } + return NULL; +@@ -304,11 +306,12 @@ static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, u32 id) + } + + /* Look up VNI in a per net namespace table */ +-static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id, __be16 port) ++static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id, ++ sa_family_t family, __be16 port) + { + struct vxlan_sock *vs; + +- vs = vxlan_find_sock(net, port); ++ vs = vxlan_find_sock(net, family, port); + if (!vs) + return NULL; + +@@ -1872,7 +1875,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, + struct vxlan_dev *dst_vxlan; + + ip_rt_put(rt); +- dst_vxlan = vxlan_find_vni(dev_net(dev), vni, dst_port); ++ dst_vxlan = vxlan_find_vni(dev_net(dev), vni, ++ dst->sa.sa_family, dst_port); + if (!dst_vxlan) + goto tx_error; + vxlan_encap_bypass(skb, vxlan, dst_vxlan); +@@ -1925,7 +1929,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, + struct vxlan_dev *dst_vxlan; + + dst_release(ndst); +- dst_vxlan = vxlan_find_vni(dev_net(dev), vni, dst_port); ++ dst_vxlan = vxlan_find_vni(dev_net(dev), vni, ++ dst->sa.sa_family, dst_port); + if (!dst_vxlan) + goto tx_error; + vxlan_encap_bypass(skb, vxlan, dst_vxlan); +@@ -2083,6 +2088,7 @@ static int vxlan_init(struct net_device *dev) + { + struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); ++ bool ipv6 = vxlan->flags & VXLAN_F_IPV6; + struct vxlan_sock *vs; + int i; + +@@ -2098,7 +2104,8 @@ static int vxlan_init(struct net_device *dev) + + + spin_lock(&vn->sock_lock); +- vs = vxlan_find_sock(dev_net(dev), vxlan->dst_port); ++ vs = vxlan_find_sock(dev_net(dev), ipv6 ? AF_INET6 : AF_INET, ++ vxlan->dst_port); + if (vs) { + /* If we have a socket with same port already, reuse it */ + atomic_inc(&vs->refcnt); +@@ -2566,7 +2573,7 @@ struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, + return vs; + + spin_lock(&vn->sock_lock); +- vs = vxlan_find_sock(net, port); ++ vs = vxlan_find_sock(net, ipv6 ? AF_INET6 : AF_INET, port); + if (vs) { + if (vs->rcv == rcv) + atomic_inc(&vs->refcnt); +@@ -2712,7 +2719,8 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, + if (data[IFLA_VXLAN_PORT]) + vxlan->dst_port = nla_get_be16(data[IFLA_VXLAN_PORT]); + +- if (vxlan_find_vni(net, vni, vxlan->dst_port)) { ++ if (vxlan_find_vni(net, vni, use_ipv6 ? AF_INET6 : AF_INET, ++ vxlan->dst_port)) { + pr_info("duplicate VNI %u\n", vni); + return -EEXIST; + } +diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h +index 1f065cf4a4ba..d090ed79ada0 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-trans.h ++++ b/drivers/net/wireless/iwlwifi/iwl-trans.h +@@ -514,6 +514,7 @@ enum iwl_trans_state { + * Set during transport allocation. + * @hw_id_str: a string with info about HW ID. Set during transport allocation. + * @pm_support: set to true in start_hw if link pm is supported ++ * @ltr_enabled: set to true if the LTR is enabled + * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only. + * The user should use iwl_trans_{alloc,free}_tx_cmd. + * @dev_cmd_headroom: room needed for the transport's private use before the +@@ -539,6 +540,7 @@ struct iwl_trans { + u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size; + + bool pm_support; ++ bool ltr_enabled; + + /* The following fields are internal only */ + struct kmem_cache *dev_cmd_pool; +diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +index 884c08725308..fa66471283d9 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h ++++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +@@ -66,13 +66,46 @@ + + /* Power Management Commands, Responses, Notifications */ + ++/** ++ * enum iwl_ltr_config_flags - masks for LTR config command flags ++ * @LTR_CFG_FLAG_FEATURE_ENABLE: Feature operational status ++ * @LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS: allow LTR change on shadow ++ * memory access ++ * @LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH: allow LTR msg send on ANY LTR ++ * reg change ++ * @LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3: allow LTR msg send on transition from ++ * D0 to D3 ++ * @LTR_CFG_FLAG_SW_SET_SHORT: fixed static short LTR register ++ * @LTR_CFG_FLAG_SW_SET_LONG: fixed static short LONG register ++ * @LTR_CFG_FLAG_DENIE_C10_ON_PD: allow going into C10 on PD ++ */ ++enum iwl_ltr_config_flags { ++ LTR_CFG_FLAG_FEATURE_ENABLE = BIT(0), ++ LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS = BIT(1), ++ LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH = BIT(2), ++ LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3 = BIT(3), ++ LTR_CFG_FLAG_SW_SET_SHORT = BIT(4), ++ LTR_CFG_FLAG_SW_SET_LONG = BIT(5), ++ LTR_CFG_FLAG_DENIE_C10_ON_PD = BIT(6), ++}; ++ ++/** ++ * struct iwl_ltr_config_cmd - configures the LTR ++ * @flags: See %enum iwl_ltr_config_flags ++ */ ++struct iwl_ltr_config_cmd { ++ __le32 flags; ++ __le32 static_long; ++ __le32 static_short; ++} __packed; ++ + /* Radio LP RX Energy Threshold measured in dBm */ + #define POWER_LPRX_RSSI_THRESHOLD 75 + #define POWER_LPRX_RSSI_THRESHOLD_MAX 94 + #define POWER_LPRX_RSSI_THRESHOLD_MIN 30 + + /** +- * enum iwl_scan_flags - masks for power table command flags ++ * enum iwl_power_flags - masks for power table command flags + * @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off + * receiver and transmitter. '0' - does not allow. + * @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management, +diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h +index d0a04779d734..d8948aa9c2d2 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h ++++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h +@@ -142,6 +142,7 @@ enum { + /* Power - legacy power table command */ + POWER_TABLE_CMD = 0x77, + PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78, ++ LTR_CONFIG = 0xee, + + /* Thermal Throttling*/ + REPLY_THERMAL_MNG_BACKOFF = 0x7e, +diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c +index c03d39541f9e..2ef344fc0acb 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/fw.c ++++ b/drivers/net/wireless/iwlwifi/mvm/fw.c +@@ -439,6 +439,15 @@ int iwl_mvm_up(struct iwl_mvm *mvm) + goto error; + } + ++ if (mvm->trans->ltr_enabled) { ++ struct iwl_ltr_config_cmd cmd = { ++ .flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE), ++ }; ++ ++ WARN_ON(iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, ++ sizeof(cmd), &cmd)); ++ } ++ + ret = iwl_mvm_power_update_device_mode(mvm); + if (ret) + goto error; +diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c +index a3d43de342d7..dbff7f0bc6a8 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/ops.c ++++ b/drivers/net/wireless/iwlwifi/mvm/ops.c +@@ -313,6 +313,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { + CMD(REPLY_BEACON_FILTERING_CMD), + CMD(REPLY_THERMAL_MNG_BACKOFF), + CMD(MAC_PM_POWER_TABLE), ++ CMD(LTR_CONFIG), + CMD(BT_COEX_CI), + CMD(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION), + }; +diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c +index 16be0c07c64a..fb62927ca44d 100644 +--- a/drivers/net/wireless/iwlwifi/pcie/trans.c ++++ b/drivers/net/wireless/iwlwifi/pcie/trans.c +@@ -94,6 +94,7 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans) + { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + u16 lctl; ++ u16 cap; + + /* + * HW bug W/A for instability in PCIe bus L0S->L1 transition. +@@ -104,16 +105,17 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans) + * power savings, even without L1. + */ + pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl); +- if (lctl & PCI_EXP_LNKCTL_ASPM_L1) { +- /* L1-ASPM enabled; disable(!) L0S */ ++ if (lctl & PCI_EXP_LNKCTL_ASPM_L1) + iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); +- dev_info(trans->dev, "L1 Enabled; Disabling L0S\n"); +- } else { +- /* L1-ASPM disabled; enable(!) L0S */ ++ else + iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); +- dev_info(trans->dev, "L1 Disabled; Enabling L0S\n"); +- } + trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S); ++ ++ pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_DEVCTL2, &cap); ++ trans->ltr_enabled = cap & PCI_EXP_DEVCTL2_LTR_EN; ++ dev_info(trans->dev, "L1 %sabled - LTR %sabled\n", ++ (lctl & PCI_EXP_LNKCTL_ASPM_L1) ? "En" : "Dis", ++ trans->ltr_enabled ? "En" : "Dis"); + } + + /* +diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c +index 69d4c3179d04..505ff601d9f4 100644 +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -1974,7 +1974,7 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, + if (err != 0) { + printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n", + err); +- goto failed_hw; ++ goto failed_bind; + } + + skb_queue_head_init(&data->pending); +@@ -2157,6 +2157,8 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, + return idx; + + failed_hw: ++ device_release_driver(data->dev); ++failed_bind: + device_unregister(data->dev); + failed_drvdata: + ieee80211_free_hw(hw); +diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c +index 390e8e33d5e3..25721bf20092 100644 +--- a/drivers/platform/x86/dell-wmi.c ++++ b/drivers/platform/x86/dell-wmi.c +@@ -163,18 +163,24 @@ static void dell_wmi_notify(u32 value, void *context) + const struct key_entry *key; + int reported_key; + u16 *buffer_entry = (u16 *)obj->buffer.pointer; ++ int buffer_size = obj->buffer.length/2; + +- if (dell_new_hk_type && (buffer_entry[1] != 0x10)) { ++ if (buffer_size >= 2 && dell_new_hk_type && buffer_entry[1] != 0x10) { + pr_info("Received unknown WMI event (0x%x)\n", + buffer_entry[1]); + kfree(obj); + return; + } + +- if (dell_new_hk_type || buffer_entry[1] == 0x0) ++ if (buffer_size >= 3 && (dell_new_hk_type || buffer_entry[1] == 0x0)) + reported_key = (int)buffer_entry[2]; +- else ++ else if (buffer_size >= 2) + reported_key = (int)buffer_entry[1] & 0xffff; ++ else { ++ pr_info("Received unknown WMI event\n"); ++ kfree(obj); ++ return; ++ } + + key = sparse_keymap_entry_from_scancode(dell_wmi_input_dev, + reported_key); +diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c +index e384844a1ae1..1f49986fc605 100644 +--- a/drivers/power/bq2415x_charger.c ++++ b/drivers/power/bq2415x_charger.c +@@ -1579,8 +1579,15 @@ static int bq2415x_probe(struct i2c_client *client, + if (np) { + bq->notify_psy = power_supply_get_by_phandle(np, "ti,usb-charger-detection"); + +- if (!bq->notify_psy) +- return -EPROBE_DEFER; ++ if (IS_ERR(bq->notify_psy)) { ++ dev_info(&client->dev, ++ "no 'ti,usb-charger-detection' property (err=%ld)\n", ++ PTR_ERR(bq->notify_psy)); ++ bq->notify_psy = NULL; ++ } else if (!bq->notify_psy) { ++ ret = -EPROBE_DEFER; ++ goto error_2; ++ } + } + else if (pdata->notify_device) + bq->notify_psy = power_supply_get_by_name(pdata->notify_device); +@@ -1602,27 +1609,27 @@ static int bq2415x_probe(struct i2c_client *client, + ret = of_property_read_u32(np, "ti,current-limit", + &bq->init_data.current_limit); + if (ret) +- return ret; ++ goto error_2; + ret = of_property_read_u32(np, "ti,weak-battery-voltage", + &bq->init_data.weak_battery_voltage); + if (ret) +- return ret; ++ goto error_2; + ret = of_property_read_u32(np, "ti,battery-regulation-voltage", + &bq->init_data.battery_regulation_voltage); + if (ret) +- return ret; ++ goto error_2; + ret = of_property_read_u32(np, "ti,charge-current", + &bq->init_data.charge_current); + if (ret) +- return ret; ++ goto error_2; + ret = of_property_read_u32(np, "ti,termination-current", + &bq->init_data.termination_current); + if (ret) +- return ret; ++ goto error_2; + ret = of_property_read_u32(np, "ti,resistor-sense", + &bq->init_data.resistor_sense); + if (ret) +- return ret; ++ goto error_2; + } else { + memcpy(&bq->init_data, pdata, sizeof(bq->init_data)); + } +diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c +index ef1f4c928431..03bfac3655ef 100644 +--- a/drivers/power/charger-manager.c ++++ b/drivers/power/charger-manager.c +@@ -97,6 +97,7 @@ static struct charger_global_desc *g_desc; /* init with setup_charger_manager */ + static bool is_batt_present(struct charger_manager *cm) + { + union power_supply_propval val; ++ struct power_supply *psy; + bool present = false; + int i, ret; + +@@ -107,16 +108,27 @@ static bool is_batt_present(struct charger_manager *cm) + case CM_NO_BATTERY: + break; + case CM_FUEL_GAUGE: +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ psy = power_supply_get_by_name(cm->desc->psy_fuel_gauge); ++ if (!psy) ++ break; ++ ++ ret = psy->get_property(psy, + POWER_SUPPLY_PROP_PRESENT, &val); + if (ret == 0 && val.intval) + present = true; + break; + case CM_CHARGER_STAT: +- for (i = 0; cm->charger_stat[i]; i++) { +- ret = cm->charger_stat[i]->get_property( +- cm->charger_stat[i], +- POWER_SUPPLY_PROP_PRESENT, &val); ++ for (i = 0; cm->desc->psy_charger_stat[i]; i++) { ++ psy = power_supply_get_by_name( ++ cm->desc->psy_charger_stat[i]); ++ if (!psy) { ++ dev_err(cm->dev, "Cannot find power supply \"%s\"\n", ++ cm->desc->psy_charger_stat[i]); ++ continue; ++ } ++ ++ ret = psy->get_property(psy, POWER_SUPPLY_PROP_PRESENT, ++ &val); + if (ret == 0 && val.intval) { + present = true; + break; +@@ -139,14 +151,20 @@ static bool is_batt_present(struct charger_manager *cm) + static bool is_ext_pwr_online(struct charger_manager *cm) + { + union power_supply_propval val; ++ struct power_supply *psy; + bool online = false; + int i, ret; + + /* If at least one of them has one, it's yes. */ +- for (i = 0; cm->charger_stat[i]; i++) { +- ret = cm->charger_stat[i]->get_property( +- cm->charger_stat[i], +- POWER_SUPPLY_PROP_ONLINE, &val); ++ for (i = 0; cm->desc->psy_charger_stat[i]; i++) { ++ psy = power_supply_get_by_name(cm->desc->psy_charger_stat[i]); ++ if (!psy) { ++ dev_err(cm->dev, "Cannot find power supply \"%s\"\n", ++ cm->desc->psy_charger_stat[i]); ++ continue; ++ } ++ ++ ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val); + if (ret == 0 && val.intval) { + online = true; + break; +@@ -167,12 +185,14 @@ static bool is_ext_pwr_online(struct charger_manager *cm) + static int get_batt_uV(struct charger_manager *cm, int *uV) + { + union power_supply_propval val; ++ struct power_supply *fuel_gauge; + int ret; + +- if (!cm->fuel_gauge) ++ fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge); ++ if (!fuel_gauge) + return -ENODEV; + +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ ret = fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_VOLTAGE_NOW, &val); + if (ret) + return ret; +@@ -189,6 +209,7 @@ static bool is_charging(struct charger_manager *cm) + { + int i, ret; + bool charging = false; ++ struct power_supply *psy; + union power_supply_propval val; + + /* If there is no battery, it cannot be charged */ +@@ -196,17 +217,22 @@ static bool is_charging(struct charger_manager *cm) + return false; + + /* If at least one of the charger is charging, return yes */ +- for (i = 0; cm->charger_stat[i]; i++) { ++ for (i = 0; cm->desc->psy_charger_stat[i]; i++) { + /* 1. The charger sholuld not be DISABLED */ + if (cm->emergency_stop) + continue; + if (!cm->charger_enabled) + continue; + ++ psy = power_supply_get_by_name(cm->desc->psy_charger_stat[i]); ++ if (!psy) { ++ dev_err(cm->dev, "Cannot find power supply \"%s\"\n", ++ cm->desc->psy_charger_stat[i]); ++ continue; ++ } ++ + /* 2. The charger should be online (ext-power) */ +- ret = cm->charger_stat[i]->get_property( +- cm->charger_stat[i], +- POWER_SUPPLY_PROP_ONLINE, &val); ++ ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val); + if (ret) { + dev_warn(cm->dev, "Cannot read ONLINE value from %s\n", + cm->desc->psy_charger_stat[i]); +@@ -219,9 +245,7 @@ static bool is_charging(struct charger_manager *cm) + * 3. The charger should not be FULL, DISCHARGING, + * or NOT_CHARGING. + */ +- ret = cm->charger_stat[i]->get_property( +- cm->charger_stat[i], +- POWER_SUPPLY_PROP_STATUS, &val); ++ ret = psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &val); + if (ret) { + dev_warn(cm->dev, "Cannot read STATUS value from %s\n", + cm->desc->psy_charger_stat[i]); +@@ -248,6 +272,7 @@ static bool is_full_charged(struct charger_manager *cm) + { + struct charger_desc *desc = cm->desc; + union power_supply_propval val; ++ struct power_supply *fuel_gauge; + int ret = 0; + int uV; + +@@ -255,11 +280,15 @@ static bool is_full_charged(struct charger_manager *cm) + if (!is_batt_present(cm)) + return false; + +- if (cm->fuel_gauge && desc->fullbatt_full_capacity > 0) { ++ fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge); ++ if (!fuel_gauge) ++ return false; ++ ++ if (desc->fullbatt_full_capacity > 0) { + val.intval = 0; + + /* Not full if capacity of fuel gauge isn't full */ +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ ret = fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_CHARGE_FULL, &val); + if (!ret && val.intval > desc->fullbatt_full_capacity) + return true; +@@ -273,10 +302,10 @@ static bool is_full_charged(struct charger_manager *cm) + } + + /* Full, if the capacity is more than fullbatt_soc */ +- if (cm->fuel_gauge && desc->fullbatt_soc > 0) { ++ if (desc->fullbatt_soc > 0) { + val.intval = 0; + +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ ret = fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_CAPACITY, &val); + if (!ret && val.intval >= desc->fullbatt_soc) + return true; +@@ -551,6 +580,20 @@ static int check_charging_duration(struct charger_manager *cm) + return ret; + } + ++static int cm_get_battery_temperature_by_psy(struct charger_manager *cm, ++ int *temp) ++{ ++ struct power_supply *fuel_gauge; ++ ++ fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge); ++ if (!fuel_gauge) ++ return -ENODEV; ++ ++ return fuel_gauge->get_property(fuel_gauge, ++ POWER_SUPPLY_PROP_TEMP, ++ (union power_supply_propval *)temp); ++} ++ + static int cm_get_battery_temperature(struct charger_manager *cm, + int *temp) + { +@@ -560,15 +603,18 @@ static int cm_get_battery_temperature(struct charger_manager *cm, + return -ENODEV; + + #ifdef CONFIG_THERMAL +- ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp); +- if (!ret) +- /* Calibrate temperature unit */ +- *temp /= 100; +-#else +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, +- POWER_SUPPLY_PROP_TEMP, +- (union power_supply_propval *)temp); ++ if (cm->tzd_batt) { ++ ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp); ++ if (!ret) ++ /* Calibrate temperature unit */ ++ *temp /= 100; ++ } else + #endif ++ { ++ /* if-else continued from CONFIG_THERMAL */ ++ ret = cm_get_battery_temperature_by_psy(cm, temp); ++ } ++ + return ret; + } + +@@ -827,6 +873,7 @@ static int charger_get_property(struct power_supply *psy, + struct charger_manager *cm = container_of(psy, + struct charger_manager, charger_psy); + struct charger_desc *desc = cm->desc; ++ struct power_supply *fuel_gauge; + int ret = 0; + int uV; + +@@ -857,14 +904,20 @@ static int charger_get_property(struct power_supply *psy, + ret = get_batt_uV(cm, &val->intval); + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge); ++ if (!fuel_gauge) { ++ ret = -ENODEV; ++ break; ++ } ++ ret = fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_CURRENT_NOW, val); + break; + case POWER_SUPPLY_PROP_TEMP: + case POWER_SUPPLY_PROP_TEMP_AMBIENT: + return cm_get_battery_temperature(cm, &val->intval); + case POWER_SUPPLY_PROP_CAPACITY: +- if (!cm->fuel_gauge) { ++ fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge); ++ if (!fuel_gauge) { + ret = -ENODEV; + break; + } +@@ -875,7 +928,7 @@ static int charger_get_property(struct power_supply *psy, + break; + } + +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ ret = fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_CAPACITY, val); + if (ret) + break; +@@ -924,7 +977,14 @@ static int charger_get_property(struct power_supply *psy, + break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + if (is_charging(cm)) { +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ fuel_gauge = power_supply_get_by_name( ++ cm->desc->psy_fuel_gauge); ++ if (!fuel_gauge) { ++ ret = -ENODEV; ++ break; ++ } ++ ++ ret = fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_CHARGE_NOW, + val); + if (ret) { +@@ -1485,14 +1545,15 @@ err: + return ret; + } + +-static int cm_init_thermal_data(struct charger_manager *cm) ++static int cm_init_thermal_data(struct charger_manager *cm, ++ struct power_supply *fuel_gauge) + { + struct charger_desc *desc = cm->desc; + union power_supply_propval val; + int ret; + + /* Verify whether fuel gauge provides battery temperature */ +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ ret = fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_TEMP, &val); + + if (!ret) { +@@ -1502,8 +1563,6 @@ static int cm_init_thermal_data(struct charger_manager *cm) + cm->desc->measure_battery_temp = true; + } + #ifdef CONFIG_THERMAL +- cm->tzd_batt = cm->fuel_gauge->tzd; +- + if (ret && desc->thermal_zone) { + cm->tzd_batt = + thermal_zone_get_zone_by_name(desc->thermal_zone); +@@ -1666,6 +1725,7 @@ static int charger_manager_probe(struct platform_device *pdev) + int ret = 0, i = 0; + int j = 0; + union power_supply_propval val; ++ struct power_supply *fuel_gauge; + + if (g_desc && !rtc_dev && g_desc->rtc_name) { + rtc_dev = rtc_class_open(g_desc->rtc_name); +@@ -1729,23 +1789,20 @@ static int charger_manager_probe(struct platform_device *pdev) + while (desc->psy_charger_stat[i]) + i++; + +- cm->charger_stat = devm_kzalloc(&pdev->dev, +- sizeof(struct power_supply *) * i, GFP_KERNEL); +- if (!cm->charger_stat) +- return -ENOMEM; +- ++ /* Check if charger's supplies are present at probe */ + for (i = 0; desc->psy_charger_stat[i]; i++) { +- cm->charger_stat[i] = power_supply_get_by_name( +- desc->psy_charger_stat[i]); +- if (!cm->charger_stat[i]) { ++ struct power_supply *psy; ++ ++ psy = power_supply_get_by_name(desc->psy_charger_stat[i]); ++ if (!psy) { + dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n", + desc->psy_charger_stat[i]); + return -ENODEV; + } + } + +- cm->fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge); +- if (!cm->fuel_gauge) { ++ fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge); ++ if (!fuel_gauge) { + dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n", + desc->psy_fuel_gauge); + return -ENODEV; +@@ -1788,13 +1845,13 @@ static int charger_manager_probe(struct platform_device *pdev) + cm->charger_psy.num_properties = psy_default.num_properties; + + /* Find which optional psy-properties are available */ +- if (!cm->fuel_gauge->get_property(cm->fuel_gauge, ++ if (!fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_CHARGE_NOW, &val)) { + cm->charger_psy.properties[cm->charger_psy.num_properties] = + POWER_SUPPLY_PROP_CHARGE_NOW; + cm->charger_psy.num_properties++; + } +- if (!cm->fuel_gauge->get_property(cm->fuel_gauge, ++ if (!fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_CURRENT_NOW, + &val)) { + cm->charger_psy.properties[cm->charger_psy.num_properties] = +@@ -1802,7 +1859,7 @@ static int charger_manager_probe(struct platform_device *pdev) + cm->charger_psy.num_properties++; + } + +- ret = cm_init_thermal_data(cm); ++ ret = cm_init_thermal_data(cm, fuel_gauge); + if (ret) { + dev_err(&pdev->dev, "Failed to initialize thermal data\n"); + cm->desc->measure_battery_temp = false; +@@ -2059,8 +2116,8 @@ static bool find_power_supply(struct charger_manager *cm, + int i; + bool found = false; + +- for (i = 0; cm->charger_stat[i]; i++) { +- if (psy == cm->charger_stat[i]) { ++ for (i = 0; cm->desc->psy_charger_stat[i]; i++) { ++ if (!strcmp(psy->name, cm->desc->psy_charger_stat[i])) { + found = true; + break; + } +diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c +index edb4d46fa874..96b6664bb1cf 100644 +--- a/drivers/scsi/scsi_error.c ++++ b/drivers/scsi/scsi_error.c +@@ -1984,8 +1984,10 @@ static void scsi_restart_operations(struct Scsi_Host *shost) + * is no point trying to lock the door of an off-line device. + */ + shost_for_each_device(sdev, shost) { +- if (scsi_device_online(sdev) && sdev->locked) ++ if (scsi_device_online(sdev) && sdev->was_reset && sdev->locked) { + scsi_eh_lock_door(sdev); ++ sdev->was_reset = 0; ++ } + } + + /* +diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c +index b01fb6c527e3..d43c544d3b68 100644 +--- a/fs/btrfs/compression.c ++++ b/fs/btrfs/compression.c +@@ -472,7 +472,7 @@ static noinline int add_ra_bio_pages(struct inode *inode, + rcu_read_lock(); + page = radix_tree_lookup(&mapping->page_tree, pg_index); + rcu_read_unlock(); +- if (page) { ++ if (page && !radix_tree_exceptional_entry(page)) { + misses++; + if (misses > 4) + break; +diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c +index a9a881ed8cbe..f6d00df99a8c 100644 +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -425,13 +425,8 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, + struct page *page = prepared_pages[pg]; + /* + * Copy data from userspace to the current page +- * +- * Disable pagefault to avoid recursive lock since +- * the pages are already locked + */ +- pagefault_disable(); + copied = iov_iter_copy_from_user_atomic(page, i, offset, count); +- pagefault_enable(); + + /* Flush processor's dcache for this page */ + flush_dcache_page(page); +diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c +index 06610cf94d57..a1f801c14fbc 100644 +--- a/fs/cramfs/inode.c ++++ b/fs/cramfs/inode.c +@@ -195,8 +195,7 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i + struct page *page = NULL; + + if (blocknr + i < devsize) { +- page = read_mapping_page_async(mapping, blocknr + i, +- NULL); ++ page = read_mapping_page(mapping, blocknr + i, NULL); + /* synchronous error? */ + if (IS_ERR(page)) + page = NULL; +diff --git a/fs/fuse/file.c b/fs/fuse/file.c +index 77bcc303c3ae..a91d3b4d32f3 100644 +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -1003,9 +1003,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, + if (mapping_writably_mapped(mapping)) + flush_dcache_page(page); + +- pagefault_disable(); + tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes); +- pagefault_enable(); + flush_dcache_page(page); + + mark_page_accessed(page); +diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c +index c7f24690ed05..b82a9c99e18b 100644 +--- a/fs/gfs2/meta_io.c ++++ b/fs/gfs2/meta_io.c +@@ -97,6 +97,11 @@ const struct address_space_operations gfs2_meta_aops = { + .releasepage = gfs2_releasepage, + }; + ++const struct address_space_operations gfs2_rgrp_aops = { ++ .writepage = gfs2_aspace_writepage, ++ .releasepage = gfs2_releasepage, ++}; ++ + /** + * gfs2_getbuf - Get a buffer with a given address space + * @gl: the glock +diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h +index 4823b934208a..ac5d8027d335 100644 +--- a/fs/gfs2/meta_io.h ++++ b/fs/gfs2/meta_io.h +@@ -38,12 +38,15 @@ static inline void gfs2_buffer_copy_tail(struct buffer_head *to_bh, + } + + extern const struct address_space_operations gfs2_meta_aops; ++extern const struct address_space_operations gfs2_rgrp_aops; + + static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping) + { + struct inode *inode = mapping->host; + if (mapping->a_ops == &gfs2_meta_aops) + return (((struct gfs2_glock *)mapping) - 1)->gl_sbd; ++ else if (mapping->a_ops == &gfs2_rgrp_aops) ++ return container_of(mapping, struct gfs2_sbd, sd_aspace); + else + return inode->i_sb->s_fs_info; + } +diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c +index c6872d09561a..f6c9d83aa39b 100644 +--- a/fs/gfs2/ops_fstype.c ++++ b/fs/gfs2/ops_fstype.c +@@ -104,7 +104,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) + mapping = &sdp->sd_aspace; + + address_space_init_once(mapping); +- mapping->a_ops = &gfs2_meta_aops; ++ mapping->a_ops = &gfs2_rgrp_aops; + mapping->host = sb->s_bdev->bd_inode; + mapping->flags = 0; + mapping_set_gfp_mask(mapping, GFP_NOFS); +diff --git a/fs/ioprio.c b/fs/ioprio.c +index e50170ca7c33..31666c92b46a 100644 +--- a/fs/ioprio.c ++++ b/fs/ioprio.c +@@ -157,14 +157,16 @@ out: + + int ioprio_best(unsigned short aprio, unsigned short bprio) + { +- unsigned short aclass = IOPRIO_PRIO_CLASS(aprio); +- unsigned short bclass = IOPRIO_PRIO_CLASS(bprio); ++ unsigned short aclass; ++ unsigned short bclass; + +- if (aclass == IOPRIO_CLASS_NONE) +- aclass = IOPRIO_CLASS_BE; +- if (bclass == IOPRIO_CLASS_NONE) +- bclass = IOPRIO_CLASS_BE; ++ if (!ioprio_valid(aprio)) ++ aprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, IOPRIO_NORM); ++ if (!ioprio_valid(bprio)) ++ bprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, IOPRIO_NORM); + ++ aclass = IOPRIO_PRIO_CLASS(aprio); ++ bclass = IOPRIO_PRIO_CLASS(bprio); + if (aclass == bclass) + return min(aprio, bprio); + if (aclass > bclass) +diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c +index a69e426435dd..5b234db85854 100644 +--- a/fs/jffs2/fs.c ++++ b/fs/jffs2/fs.c +@@ -687,7 +687,7 @@ unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, + struct inode *inode = OFNI_EDONI_2SFFJ(f); + struct page *pg; + +- pg = read_cache_page_async(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, ++ pg = read_cache_page(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, + (void *)jffs2_do_readpage_unlock, inode); + if (IS_ERR(pg)) + return (void *)pg; +diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c +index 56ff823ca82e..65d849bdf77a 100644 +--- a/fs/nfs/blocklayout/blocklayout.c ++++ b/fs/nfs/blocklayout/blocklayout.c +@@ -1213,7 +1213,7 @@ static u64 pnfs_num_cont_bytes(struct inode *inode, pgoff_t idx) + end = DIV_ROUND_UP(i_size_read(inode), PAGE_CACHE_SIZE); + if (end != NFS_I(inode)->npages) { + rcu_read_lock(); +- end = radix_tree_next_hole(&mapping->page_tree, idx + 1, ULONG_MAX); ++ end = page_cache_next_hole(mapping, idx + 1, ULONG_MAX); + rcu_read_unlock(); + } + +diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c +index 5d8ccecf5f5c..3ed1be9aade3 100644 +--- a/fs/nfs/delegation.c ++++ b/fs/nfs/delegation.c +@@ -109,6 +109,8 @@ again: + continue; + if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) + continue; ++ if (!nfs4_valid_open_stateid(state)) ++ continue; + if (!nfs4_stateid_match(&state->stateid, stateid)) + continue; + get_nfs_open_context(ctx); +@@ -177,7 +179,11 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation * + { + int res = 0; + +- res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync); ++ if (!test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) ++ res = nfs4_proc_delegreturn(inode, ++ delegation->cred, ++ &delegation->stateid, ++ issync); + nfs_free_delegation(delegation); + return res; + } +@@ -364,11 +370,13 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation + { + struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; + struct nfs_inode *nfsi = NFS_I(inode); +- int err; ++ int err = 0; + + if (delegation == NULL) + return 0; + do { ++ if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) ++ break; + err = nfs_delegation_claim_opens(inode, &delegation->stateid); + if (!issync || err != -EAGAIN) + break; +@@ -589,10 +597,23 @@ static void nfs_client_mark_return_unused_delegation_types(struct nfs_client *cl + rcu_read_unlock(); + } + ++static void nfs_revoke_delegation(struct inode *inode) ++{ ++ struct nfs_delegation *delegation; ++ rcu_read_lock(); ++ delegation = rcu_dereference(NFS_I(inode)->delegation); ++ if (delegation != NULL) { ++ set_bit(NFS_DELEGATION_REVOKED, &delegation->flags); ++ nfs_mark_return_delegation(NFS_SERVER(inode), delegation); ++ } ++ rcu_read_unlock(); ++} ++ + void nfs_remove_bad_delegation(struct inode *inode) + { + struct nfs_delegation *delegation; + ++ nfs_revoke_delegation(inode); + delegation = nfs_inode_detach_delegation(inode); + if (delegation) { + nfs_inode_find_state_and_recover(inode, &delegation->stateid); +diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h +index 9a79c7a99d6d..e02b090ab9da 100644 +--- a/fs/nfs/delegation.h ++++ b/fs/nfs/delegation.h +@@ -31,6 +31,7 @@ enum { + NFS_DELEGATION_RETURN_IF_CLOSED, + NFS_DELEGATION_REFERENCED, + NFS_DELEGATION_RETURNING, ++ NFS_DELEGATION_REVOKED, + }; + + int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); +diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c +index b8797ae6831f..de2543d3c283 100644 +--- a/fs/nfs/direct.c ++++ b/fs/nfs/direct.c +@@ -178,6 +178,7 @@ static void nfs_direct_req_free(struct kref *kref) + { + struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref); + ++ nfs_free_pnfs_ds_cinfo(&dreq->ds_cinfo); + if (dreq->l_ctx != NULL) + nfs_put_lock_context(dreq->l_ctx); + if (dreq->ctx != NULL) +diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c +index 15f9d98627a4..6659ce545f15 100644 +--- a/fs/nfs/inode.c ++++ b/fs/nfs/inode.c +@@ -592,7 +592,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) + { + struct inode *inode = dentry->d_inode; + int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; +- int err; ++ int err = 0; + + trace_nfs_getattr_enter(inode); + /* Flush out writes to the server in order to update c/mtime. */ +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index da657b7804a5..bd01803d0656 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -1587,7 +1587,7 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct + nfs_inode_find_state_and_recover(state->inode, + stateid); + nfs4_schedule_stateid_recovery(server, state); +- return 0; ++ return -EAGAIN; + case -NFS4ERR_DELAY: + case -NFS4ERR_GRACE: + set_bit(NFS_DELEGATED_STATE, &state->flags); +@@ -2034,46 +2034,60 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta + return ret; + } + ++static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state) ++{ ++ nfs_remove_bad_delegation(state->inode); ++ write_seqlock(&state->seqlock); ++ nfs4_stateid_copy(&state->stateid, &state->open_stateid); ++ write_sequnlock(&state->seqlock); ++ clear_bit(NFS_DELEGATED_STATE, &state->flags); ++} ++ ++static void nfs40_clear_delegation_stateid(struct nfs4_state *state) ++{ ++ if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL) ++ nfs_finish_clear_delegation_stateid(state); ++} ++ ++static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) ++{ ++ /* NFSv4.0 doesn't allow for delegation recovery on open expire */ ++ nfs40_clear_delegation_stateid(state); ++ return nfs4_open_expired(sp, state); ++} ++ + #if defined(CONFIG_NFS_V4_1) +-static void nfs41_clear_delegation_stateid(struct nfs4_state *state) ++static void nfs41_check_delegation_stateid(struct nfs4_state *state) + { + struct nfs_server *server = NFS_SERVER(state->inode); +- nfs4_stateid *stateid = &state->stateid; ++ nfs4_stateid stateid; + struct nfs_delegation *delegation; +- struct rpc_cred *cred = NULL; +- int status = -NFS4ERR_BAD_STATEID; +- +- /* If a state reset has been done, test_stateid is unneeded */ +- if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) +- return; ++ struct rpc_cred *cred; ++ int status; + + /* Get the delegation credential for use by test/free_stateid */ + rcu_read_lock(); + delegation = rcu_dereference(NFS_I(state->inode)->delegation); +- if (delegation != NULL && +- nfs4_stateid_match(&delegation->stateid, stateid)) { +- cred = get_rpccred(delegation->cred); +- rcu_read_unlock(); +- status = nfs41_test_stateid(server, stateid, cred); +- trace_nfs4_test_delegation_stateid(state, NULL, status); +- } else ++ if (delegation == NULL) { + rcu_read_unlock(); ++ return; ++ } ++ ++ nfs4_stateid_copy(&stateid, &delegation->stateid); ++ cred = get_rpccred(delegation->cred); ++ rcu_read_unlock(); ++ status = nfs41_test_stateid(server, &stateid, cred); ++ trace_nfs4_test_delegation_stateid(state, NULL, status); + + if (status != NFS_OK) { + /* Free the stateid unless the server explicitly + * informs us the stateid is unrecognized. */ + if (status != -NFS4ERR_BAD_STATEID) +- nfs41_free_stateid(server, stateid, cred); +- nfs_remove_bad_delegation(state->inode); +- +- write_seqlock(&state->seqlock); +- nfs4_stateid_copy(&state->stateid, &state->open_stateid); +- write_sequnlock(&state->seqlock); +- clear_bit(NFS_DELEGATED_STATE, &state->flags); ++ nfs41_free_stateid(server, &stateid, cred); ++ nfs_finish_clear_delegation_stateid(state); + } + +- if (cred != NULL) +- put_rpccred(cred); ++ put_rpccred(cred); + } + + /** +@@ -2117,7 +2131,7 @@ static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st + { + int status; + +- nfs41_clear_delegation_stateid(state); ++ nfs41_check_delegation_stateid(state); + status = nfs41_check_open_stateid(state); + if (status != NFS_OK) + status = nfs4_open_expired(sp, state); +@@ -8255,7 +8269,7 @@ static const struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = { + static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = { + .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE, + .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE, +- .recover_open = nfs4_open_expired, ++ .recover_open = nfs40_open_expired, + .recover_lock = nfs4_lock_expired, + .establish_clid = nfs4_init_clientid, + }; +diff --git a/fs/super.c b/fs/super.c +index 88a6bc6e3cc9..440ef51cd696 100644 +--- a/fs/super.c ++++ b/fs/super.c +@@ -114,9 +114,14 @@ static unsigned long super_cache_count(struct shrinker *shrink, + + sb = container_of(shrink, struct super_block, s_shrink); + +- if (!grab_super_passive(sb)) +- return 0; +- ++ /* ++ * Don't call grab_super_passive as it is a potential ++ * scalability bottleneck. The counts could get updated ++ * between super_cache_count and super_cache_scan anyway. ++ * Call to super_cache_count with shrinker_rwsem held ++ * ensures the safety of call to list_lru_count_node() and ++ * s_op->nr_cached_objects(). ++ */ + if (sb->s_op && sb->s_op->nr_cached_objects) + total_objects = sb->s_op->nr_cached_objects(sb, + sc->nid); +@@ -127,7 +132,6 @@ static unsigned long super_cache_count(struct shrinker *shrink, + sc->nid); + + total_objects = vfs_pressure_ratio(total_objects); +- drop_super(sb); + return total_objects; + } + +@@ -278,10 +282,8 @@ void deactivate_locked_super(struct super_block *s) + struct file_system_type *fs = s->s_type; + if (atomic_dec_and_test(&s->s_active)) { + cleancache_invalidate_fs(s); +- fs->kill_sb(s); +- +- /* caches are now gone, we can safely kill the shrinker now */ + unregister_shrinker(&s->s_shrink); ++ fs->kill_sb(s); + + put_filesystem(fs); + put_super(s); +diff --git a/include/dt-bindings/pinctrl/dra.h b/include/dt-bindings/pinctrl/dra.h +index 3d33794e4f3e..7448edff4723 100644 +--- a/include/dt-bindings/pinctrl/dra.h ++++ b/include/dt-bindings/pinctrl/dra.h +@@ -40,8 +40,8 @@ + + /* Active pin states */ + #define PIN_OUTPUT (0 | PULL_DIS) +-#define PIN_OUTPUT_PULLUP (PIN_OUTPUT | PULL_ENA | PULL_UP) +-#define PIN_OUTPUT_PULLDOWN (PIN_OUTPUT | PULL_ENA) ++#define PIN_OUTPUT_PULLUP (PULL_UP) ++#define PIN_OUTPUT_PULLDOWN (0) + #define PIN_INPUT (INPUT_EN | PULL_DIS) + #define PIN_INPUT_SLEW (INPUT_EN | SLEWCONTROL) + #define PIN_INPUT_PULLUP (PULL_ENA | INPUT_EN | PULL_UP) +diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h +index 67301a405712..879065d8d208 100644 +--- a/include/linux/clocksource.h ++++ b/include/linux/clocksource.h +@@ -289,7 +289,7 @@ extern struct clocksource* clocksource_get_next(void); + extern void clocksource_change_rating(struct clocksource *cs, int rating); + extern void clocksource_suspend(void); + extern void clocksource_resume(void); +-extern struct clocksource * __init __weak clocksource_default_clock(void); ++extern struct clocksource * __init clocksource_default_clock(void); + extern void clocksource_mark_unstable(struct clocksource *cs); + + extern u64 +diff --git a/include/linux/compaction.h b/include/linux/compaction.h +index 7e1c76e3cd68..01e3132820da 100644 +--- a/include/linux/compaction.h ++++ b/include/linux/compaction.h +@@ -22,7 +22,7 @@ extern int sysctl_extfrag_handler(struct ctl_table *table, int write, + extern int fragmentation_index(struct zone *zone, unsigned int order); + extern unsigned long try_to_compact_pages(struct zonelist *zonelist, + int order, gfp_t gfp_mask, nodemask_t *mask, +- bool sync, bool *contended); ++ enum migrate_mode mode, bool *contended); + extern void compact_pgdat(pg_data_t *pgdat, int order); + extern void reset_isolation_suitable(pg_data_t *pgdat); + extern unsigned long compaction_suitable(struct zone *zone, int order); +@@ -91,7 +91,7 @@ static inline bool compaction_restarting(struct zone *zone, int order) + #else + static inline unsigned long try_to_compact_pages(struct zonelist *zonelist, + int order, gfp_t gfp_mask, nodemask_t *nodemask, +- bool sync, bool *contended) ++ enum migrate_mode mode, bool *contended) + { + return COMPACT_CONTINUE; + } +diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h +index 7032518f8542..60023e5d3169 100644 +--- a/include/linux/crash_dump.h ++++ b/include/linux/crash_dump.h +@@ -14,14 +14,13 @@ + extern unsigned long long elfcorehdr_addr; + extern unsigned long long elfcorehdr_size; + +-extern int __weak elfcorehdr_alloc(unsigned long long *addr, +- unsigned long long *size); +-extern void __weak elfcorehdr_free(unsigned long long addr); +-extern ssize_t __weak elfcorehdr_read(char *buf, size_t count, u64 *ppos); +-extern ssize_t __weak elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos); +-extern int __weak remap_oldmem_pfn_range(struct vm_area_struct *vma, +- unsigned long from, unsigned long pfn, +- unsigned long size, pgprot_t prot); ++extern int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size); ++extern void elfcorehdr_free(unsigned long long addr); ++extern ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos); ++extern ssize_t elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos); ++extern int remap_oldmem_pfn_range(struct vm_area_struct *vma, ++ unsigned long from, unsigned long pfn, ++ unsigned long size, pgprot_t prot); + + extern ssize_t copy_oldmem_page(unsigned long, char *, size_t, + unsigned long, int); +diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h +index 6b06d378f3df..e465bb15912d 100644 +--- a/include/linux/kgdb.h ++++ b/include/linux/kgdb.h +@@ -283,7 +283,7 @@ struct kgdb_io { + + extern struct kgdb_arch arch_kgdb_ops; + +-extern unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs); ++extern unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs); + + #ifdef CONFIG_SERIAL_KGDB_NMI + extern int kgdb_register_nmi_console(void); +diff --git a/include/linux/memory.h b/include/linux/memory.h +index bb7384e3c3d8..8b8d8d12348e 100644 +--- a/include/linux/memory.h ++++ b/include/linux/memory.h +@@ -35,7 +35,7 @@ struct memory_block { + }; + + int arch_get_memory_phys_device(unsigned long start_pfn); +-unsigned long __weak memory_block_size_bytes(void); ++unsigned long memory_block_size_bytes(void); + + /* These states are exposed to userspace as text strings in sysfs */ + #define MEM_ONLINE (1<<0) /* exposed to userspace */ +diff --git a/include/linux/migrate.h b/include/linux/migrate.h +index 84a31ad0b791..a2901c414664 100644 +--- a/include/linux/migrate.h ++++ b/include/linux/migrate.h +@@ -5,7 +5,9 @@ + #include + #include + +-typedef struct page *new_page_t(struct page *, unsigned long private, int **); ++typedef struct page *new_page_t(struct page *page, unsigned long private, ++ int **reason); ++typedef void free_page_t(struct page *page, unsigned long private); + + /* + * Return values from addresss_space_operations.migratepage(): +@@ -38,7 +40,7 @@ enum migrate_reason { + extern void putback_movable_pages(struct list_head *l); + extern int migrate_page(struct address_space *, + struct page *, struct page *, enum migrate_mode); +-extern int migrate_pages(struct list_head *l, new_page_t x, ++extern int migrate_pages(struct list_head *l, new_page_t new, free_page_t free, + unsigned long private, enum migrate_mode mode, int reason); + + extern int migrate_prep(void); +@@ -56,8 +58,9 @@ extern int migrate_page_move_mapping(struct address_space *mapping, + #else + + static inline void putback_movable_pages(struct list_head *l) {} +-static inline int migrate_pages(struct list_head *l, new_page_t x, +- unsigned long private, enum migrate_mode mode, int reason) ++static inline int migrate_pages(struct list_head *l, new_page_t new, ++ free_page_t free, unsigned long private, enum migrate_mode mode, ++ int reason) + { return -ENOSYS; } + + static inline int migrate_prep(void) { return -ENOSYS; } +diff --git a/include/linux/mm.h b/include/linux/mm.h +index 0a0b024ec7e8..d5039daf1e1c 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1041,6 +1041,14 @@ extern void show_free_areas(unsigned int flags); + extern bool skip_free_areas_node(unsigned int flags, int nid); + + int shmem_zero_setup(struct vm_area_struct *); ++#ifdef CONFIG_SHMEM ++bool shmem_mapping(struct address_space *mapping); ++#else ++static inline bool shmem_mapping(struct address_space *mapping) ++{ ++ return false; ++} ++#endif + + extern int can_do_mlock(void); + extern int user_shm_lock(size_t, struct user_struct *); +@@ -1848,9 +1856,6 @@ void page_cache_async_readahead(struct address_space *mapping, + unsigned long size); + + unsigned long max_sane_readahead(unsigned long nr); +-unsigned long ra_submit(struct file_ra_state *ra, +- struct address_space *mapping, +- struct file *filp); + + /* Generic expand stack which grows the stack according to GROWS{UP,DOWN} */ + extern int expand_stack(struct vm_area_struct *vma, unsigned long address); +diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h +index e6800f0c0d7b..18843532a0c9 100644 +--- a/include/linux/mmzone.h ++++ b/include/linux/mmzone.h +@@ -361,9 +361,10 @@ struct zone { + /* Set to true when the PG_migrate_skip bits should be cleared */ + bool compact_blockskip_flush; + +- /* pfns where compaction scanners should start */ ++ /* pfn where compaction free scanner should start */ + unsigned long compact_cached_free_pfn; +- unsigned long compact_cached_migrate_pfn; ++ /* pfn where async and sync compaction migration scanner should start */ ++ unsigned long compact_cached_migrate_pfn[2]; + #endif + #ifdef CONFIG_MEMORY_HOTPLUG + /* see spanned/present_pages for more description */ +diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h +index 5624e4e2763c..53988cb3c05a 100644 +--- a/include/linux/nfs_xdr.h ++++ b/include/linux/nfs_xdr.h +@@ -1247,11 +1247,22 @@ struct nfs41_free_stateid_res { + unsigned int status; + }; + ++static inline void ++nfs_free_pnfs_ds_cinfo(struct pnfs_ds_commit_info *cinfo) ++{ ++ kfree(cinfo->buckets); ++} ++ + #else + + struct pnfs_ds_commit_info { + }; + ++static inline void ++nfs_free_pnfs_ds_cinfo(struct pnfs_ds_commit_info *cinfo) ++{ ++} ++ + #endif /* CONFIG_NFS_V4_1 */ + + struct nfs_page; +diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h +index 1710d1b060ba..09c1b03867d9 100644 +--- a/include/linux/pagemap.h ++++ b/include/linux/pagemap.h +@@ -243,12 +243,20 @@ static inline struct page *page_cache_alloc_readahead(struct address_space *x) + + typedef int filler_t(void *, struct page *); + +-extern struct page * find_get_page(struct address_space *mapping, +- pgoff_t index); +-extern struct page * find_lock_page(struct address_space *mapping, +- pgoff_t index); +-extern struct page * find_or_create_page(struct address_space *mapping, +- pgoff_t index, gfp_t gfp_mask); ++pgoff_t page_cache_next_hole(struct address_space *mapping, ++ pgoff_t index, unsigned long max_scan); ++pgoff_t page_cache_prev_hole(struct address_space *mapping, ++ pgoff_t index, unsigned long max_scan); ++ ++struct page *find_get_entry(struct address_space *mapping, pgoff_t offset); ++struct page *find_get_page(struct address_space *mapping, pgoff_t offset); ++struct page *find_lock_entry(struct address_space *mapping, pgoff_t offset); ++struct page *find_lock_page(struct address_space *mapping, pgoff_t offset); ++struct page *find_or_create_page(struct address_space *mapping, pgoff_t index, ++ gfp_t gfp_mask); ++unsigned find_get_entries(struct address_space *mapping, pgoff_t start, ++ unsigned int nr_entries, struct page **entries, ++ pgoff_t *indices); + unsigned find_get_pages(struct address_space *mapping, pgoff_t start, + unsigned int nr_pages, struct page **pages); + unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start, +@@ -270,8 +278,6 @@ static inline struct page *grab_cache_page(struct address_space *mapping, + + extern struct page * grab_cache_page_nowait(struct address_space *mapping, + pgoff_t index); +-extern struct page * read_cache_page_async(struct address_space *mapping, +- pgoff_t index, filler_t *filler, void *data); + extern struct page * read_cache_page(struct address_space *mapping, + pgoff_t index, filler_t *filler, void *data); + extern struct page * read_cache_page_gfp(struct address_space *mapping, +@@ -279,14 +285,6 @@ extern struct page * read_cache_page_gfp(struct address_space *mapping, + extern int read_cache_pages(struct address_space *mapping, + struct list_head *pages, filler_t *filler, void *data); + +-static inline struct page *read_mapping_page_async( +- struct address_space *mapping, +- pgoff_t index, void *data) +-{ +- filler_t *filler = (filler_t *)mapping->a_ops->readpage; +- return read_cache_page_async(mapping, index, filler, data); +-} +- + static inline struct page *read_mapping_page(struct address_space *mapping, + pgoff_t index, void *data) + { +diff --git a/include/linux/pagevec.h b/include/linux/pagevec.h +index e4dbfab37729..b45d391b4540 100644 +--- a/include/linux/pagevec.h ++++ b/include/linux/pagevec.h +@@ -22,6 +22,11 @@ struct pagevec { + + void __pagevec_release(struct pagevec *pvec); + void __pagevec_lru_add(struct pagevec *pvec); ++unsigned pagevec_lookup_entries(struct pagevec *pvec, ++ struct address_space *mapping, ++ pgoff_t start, unsigned nr_entries, ++ pgoff_t *indices); ++void pagevec_remove_exceptionals(struct pagevec *pvec); + unsigned pagevec_lookup(struct pagevec *pvec, struct address_space *mapping, + pgoff_t start, unsigned nr_pages); + unsigned pagevec_lookup_tag(struct pagevec *pvec, +diff --git a/include/linux/power/charger-manager.h b/include/linux/power/charger-manager.h +index 07e7945a1ff2..e97fc656a058 100644 +--- a/include/linux/power/charger-manager.h ++++ b/include/linux/power/charger-manager.h +@@ -253,9 +253,6 @@ struct charger_manager { + struct device *dev; + struct charger_desc *desc; + +- struct power_supply *fuel_gauge; +- struct power_supply **charger_stat; +- + #ifdef CONFIG_THERMAL + struct thermal_zone_device *tzd_batt; + #endif +diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h +index 403940787be1..e8be53ecfc45 100644 +--- a/include/linux/radix-tree.h ++++ b/include/linux/radix-tree.h +@@ -219,6 +219,7 @@ static inline void radix_tree_replace_slot(void **pslot, void *item) + int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); + void *radix_tree_lookup(struct radix_tree_root *, unsigned long); + void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long); ++void *radix_tree_delete_item(struct radix_tree_root *, unsigned long, void *); + void *radix_tree_delete(struct radix_tree_root *, unsigned long); + unsigned int + radix_tree_gang_lookup(struct radix_tree_root *root, void **results, +@@ -226,10 +227,6 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results, + unsigned int radix_tree_gang_lookup_slot(struct radix_tree_root *root, + void ***results, unsigned long *indices, + unsigned long first_index, unsigned int max_items); +-unsigned long radix_tree_next_hole(struct radix_tree_root *root, +- unsigned long index, unsigned long max_scan); +-unsigned long radix_tree_prev_hole(struct radix_tree_root *root, +- unsigned long index, unsigned long max_scan); + int radix_tree_preload(gfp_t gfp_mask); + int radix_tree_maybe_preload(gfp_t gfp_mask); + void radix_tree_init(void); +diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h +index 9d55438bc4ad..4d1771c2d29f 100644 +--- a/include/linux/shmem_fs.h ++++ b/include/linux/shmem_fs.h +@@ -51,6 +51,7 @@ extern struct file *shmem_kernel_file_setup(const char *name, loff_t size, + unsigned long flags); + extern int shmem_zero_setup(struct vm_area_struct *); + extern int shmem_lock(struct file *file, int lock, struct user_struct *user); ++extern bool shmem_mapping(struct address_space *mapping); + extern void shmem_unlock_mapping(struct address_space *mapping); + extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping, + pgoff_t index, gfp_t gfp_mask); +diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h +index a3353f45ef94..ba41e01ebc54 100644 +--- a/include/net/sctp/sctp.h ++++ b/include/net/sctp/sctp.h +@@ -433,6 +433,11 @@ static inline void sctp_assoc_pending_pmtu(struct sock *sk, struct sctp_associat + asoc->pmtu_pending = 0; + } + ++static inline bool sctp_chunk_pending(const struct sctp_chunk *chunk) ++{ ++ return !list_empty(&chunk->list); ++} ++ + /* Walk through a list of TLV parameters. Don't trust the + * individual parameter lengths and instead depend on + * the chunk length to indicate when to stop. Make sure +diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h +index 7f4eeb340a54..72a31db47ded 100644 +--- a/include/net/sctp/sm.h ++++ b/include/net/sctp/sm.h +@@ -248,9 +248,9 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *, + int, __be16); + struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc, + union sctp_addr *addr); +-int sctp_verify_asconf(const struct sctp_association *asoc, +- struct sctp_paramhdr *param_hdr, void *chunk_end, +- struct sctp_paramhdr **errp); ++bool sctp_verify_asconf(const struct sctp_association *asoc, ++ struct sctp_chunk *chunk, bool addr_param_needed, ++ struct sctp_paramhdr **errp); + struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, + struct sctp_chunk *asconf); + int sctp_process_asconf_ack(struct sctp_association *asoc, +diff --git a/include/trace/events/compaction.h b/include/trace/events/compaction.h +index 06f544ef2f6f..c6814b917bdf 100644 +--- a/include/trace/events/compaction.h ++++ b/include/trace/events/compaction.h +@@ -5,6 +5,7 @@ + #define _TRACE_COMPACTION_H + + #include ++#include + #include + #include + +@@ -47,10 +48,11 @@ DEFINE_EVENT(mm_compaction_isolate_template, mm_compaction_isolate_freepages, + + TRACE_EVENT(mm_compaction_migratepages, + +- TP_PROTO(unsigned long nr_migrated, +- unsigned long nr_failed), ++ TP_PROTO(unsigned long nr_all, ++ int migrate_rc, ++ struct list_head *migratepages), + +- TP_ARGS(nr_migrated, nr_failed), ++ TP_ARGS(nr_all, migrate_rc, migratepages), + + TP_STRUCT__entry( + __field(unsigned long, nr_migrated) +@@ -58,7 +60,22 @@ TRACE_EVENT(mm_compaction_migratepages, + ), + + TP_fast_assign( +- __entry->nr_migrated = nr_migrated; ++ unsigned long nr_failed = 0; ++ struct list_head *page_lru; ++ ++ /* ++ * migrate_pages() returns either a non-negative number ++ * with the number of pages that failed migration, or an ++ * error code, in which case we need to count the remaining ++ * pages manually ++ */ ++ if (migrate_rc >= 0) ++ nr_failed = migrate_rc; ++ else ++ list_for_each(page_lru, migratepages) ++ nr_failed++; ++ ++ __entry->nr_migrated = nr_all - nr_failed; + __entry->nr_failed = nr_failed; + ), + +diff --git a/include/uapi/linux/netfilter/xt_bpf.h b/include/uapi/linux/netfilter/xt_bpf.h +index 5dda450eb55b..2ec9fbcd06f9 100644 +--- a/include/uapi/linux/netfilter/xt_bpf.h ++++ b/include/uapi/linux/netfilter/xt_bpf.h +@@ -6,6 +6,8 @@ + + #define XT_BPF_MAX_NUM_INSTR 64 + ++struct sk_filter; ++ + struct xt_bpf_info { + __u16 bpf_program_num_elem; + struct sock_filter bpf_program[XT_BPF_MAX_NUM_INSTR]; +diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c +index 17028648cfeb..cadddc8388f3 100644 +--- a/ipc/ipc_sysctl.c ++++ b/ipc/ipc_sysctl.c +@@ -123,7 +123,6 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) + { + struct ctl_table ipc_table; +- size_t lenp_bef = *lenp; + int oldval; + int rc; + +@@ -133,7 +132,7 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, + + rc = proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); + +- if (write && !rc && lenp_bef == *lenp) { ++ if (write && !rc) { + int newval = *((int *)(ipc_table.data)); + /* + * The file "auto_msgmni" has correctly been set. +diff --git a/kernel/audit.c b/kernel/audit.c +index 2c0ecd1753de..b45b2daa9f92 100644 +--- a/kernel/audit.c ++++ b/kernel/audit.c +@@ -687,7 +687,7 @@ static int audit_get_feature(struct sk_buff *skb) + + seq = nlmsg_hdr(skb)->nlmsg_seq; + +- audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &af, sizeof(af)); ++ audit_send_reply(skb, seq, AUDIT_GET_FEATURE, 0, 0, &af, sizeof(af)); + + return 0; + } +@@ -702,7 +702,7 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature + + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE); + audit_log_task_info(ab, current); +- audit_log_format(ab, "feature=%s old=%u new=%u old_lock=%u new_lock=%u res=%d", ++ audit_log_format(ab, " feature=%s old=%u new=%u old_lock=%u new_lock=%u res=%d", + audit_feature_names[which], !!old_feature, !!new_feature, + !!old_lock, !!new_lock, res); + audit_log_end(ab); +diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c +index 135944a7b28a..a79db03990db 100644 +--- a/kernel/audit_tree.c ++++ b/kernel/audit_tree.c +@@ -154,6 +154,7 @@ static struct audit_chunk *alloc_chunk(int count) + chunk->owners[i].index = i; + } + fsnotify_init_mark(&chunk->mark, audit_tree_destroy_watch); ++ chunk->mark.mask = FS_IN_IGNORED; + return chunk; + } + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 4ced342f1ba9..4bbb27adf23d 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + + #include "internal.h" + +@@ -3693,6 +3694,26 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + return 0; + } + ++#ifdef CONFIG_COMPAT ++static long perf_compat_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ switch (_IOC_NR(cmd)) { ++ case _IOC_NR(PERF_EVENT_IOC_SET_FILTER): ++ case _IOC_NR(PERF_EVENT_IOC_ID): ++ /* Fix up pointer size (usually 4 -> 8 in 32-on-64-bit case */ ++ if (_IOC_SIZE(cmd) == sizeof(compat_uptr_t)) { ++ cmd &= ~IOCSIZE_MASK; ++ cmd |= sizeof(void *) << IOCSIZE_SHIFT; ++ } ++ break; ++ } ++ return perf_ioctl(file, cmd, arg); ++} ++#else ++# define perf_compat_ioctl NULL ++#endif ++ + int perf_event_task_enable(void) + { + struct perf_event *event; +@@ -4185,7 +4206,7 @@ static const struct file_operations perf_fops = { + .read = perf_read, + .poll = perf_poll, + .unlocked_ioctl = perf_ioctl, +- .compat_ioctl = perf_ioctl, ++ .compat_ioctl = perf_compat_ioctl, + .mmap = perf_mmap, + .fasync = perf_fasync, + }; +diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c +index b3d116cd072d..6705d947ef14 100644 +--- a/kernel/rcu/tree.c ++++ b/kernel/rcu/tree.c +@@ -1228,6 +1228,22 @@ static int rcu_future_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp) + } + + /* ++ * Awaken the grace-period kthread for the specified flavor of RCU. ++ * Don't do a self-awaken, and don't bother awakening when there is ++ * nothing for the grace-period kthread to do (as in several CPUs ++ * raced to awaken, and we lost), and finally don't try to awaken ++ * a kthread that has not yet been created. ++ */ ++static void rcu_gp_kthread_wake(struct rcu_state *rsp) ++{ ++ if (current == rsp->gp_kthread || ++ !ACCESS_ONCE(rsp->gp_flags) || ++ !rsp->gp_kthread) ++ return; ++ wake_up(&rsp->gp_wq); ++} ++ ++/* + * If there is room, assign a ->completed number to any callbacks on + * this CPU that have not already been assigned. Also accelerate any + * callbacks that were previously assigned a ->completed number that has +@@ -1670,7 +1686,7 @@ static void rsp_wakeup(struct irq_work *work) + struct rcu_state *rsp = container_of(work, struct rcu_state, wakeup_work); + + /* Wake up rcu_gp_kthread() to start the grace period. */ +- wake_up(&rsp->gp_wq); ++ rcu_gp_kthread_wake(rsp); + } + + /* +@@ -1746,7 +1762,7 @@ static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags) + { + WARN_ON_ONCE(!rcu_gp_in_progress(rsp)); + raw_spin_unlock_irqrestore(&rcu_get_root(rsp)->lock, flags); +- wake_up(&rsp->gp_wq); /* Memory barrier implied by wake_up() path. */ ++ rcu_gp_kthread_wake(rsp); + } + + /* +@@ -2322,7 +2338,7 @@ static void force_quiescent_state(struct rcu_state *rsp) + } + rsp->gp_flags |= RCU_GP_FLAG_FQS; + raw_spin_unlock_irqrestore(&rnp_old->lock, flags); +- wake_up(&rsp->gp_wq); /* Memory barrier implied by wake_up() path. */ ++ rcu_gp_kthread_wake(rsp); + } + + /* +diff --git a/lib/radix-tree.c b/lib/radix-tree.c +index bd4a8dfdf0b8..7e30d2a7f346 100644 +--- a/lib/radix-tree.c ++++ b/lib/radix-tree.c +@@ -946,81 +946,6 @@ next: + } + EXPORT_SYMBOL(radix_tree_range_tag_if_tagged); + +- +-/** +- * radix_tree_next_hole - find the next hole (not-present entry) +- * @root: tree root +- * @index: index key +- * @max_scan: maximum range to search +- * +- * Search the set [index, min(index+max_scan-1, MAX_INDEX)] for the lowest +- * indexed hole. +- * +- * Returns: the index of the hole if found, otherwise returns an index +- * outside of the set specified (in which case 'return - index >= max_scan' +- * will be true). In rare cases of index wrap-around, 0 will be returned. +- * +- * radix_tree_next_hole may be called under rcu_read_lock. However, like +- * radix_tree_gang_lookup, this will not atomically search a snapshot of +- * the tree at a single point in time. For example, if a hole is created +- * at index 5, then subsequently a hole is created at index 10, +- * radix_tree_next_hole covering both indexes may return 10 if called +- * under rcu_read_lock. +- */ +-unsigned long radix_tree_next_hole(struct radix_tree_root *root, +- unsigned long index, unsigned long max_scan) +-{ +- unsigned long i; +- +- for (i = 0; i < max_scan; i++) { +- if (!radix_tree_lookup(root, index)) +- break; +- index++; +- if (index == 0) +- break; +- } +- +- return index; +-} +-EXPORT_SYMBOL(radix_tree_next_hole); +- +-/** +- * radix_tree_prev_hole - find the prev hole (not-present entry) +- * @root: tree root +- * @index: index key +- * @max_scan: maximum range to search +- * +- * Search backwards in the range [max(index-max_scan+1, 0), index] +- * for the first hole. +- * +- * Returns: the index of the hole if found, otherwise returns an index +- * outside of the set specified (in which case 'index - return >= max_scan' +- * will be true). In rare cases of wrap-around, ULONG_MAX will be returned. +- * +- * radix_tree_next_hole may be called under rcu_read_lock. However, like +- * radix_tree_gang_lookup, this will not atomically search a snapshot of +- * the tree at a single point in time. For example, if a hole is created +- * at index 10, then subsequently a hole is created at index 5, +- * radix_tree_prev_hole covering both indexes may return 5 if called under +- * rcu_read_lock. +- */ +-unsigned long radix_tree_prev_hole(struct radix_tree_root *root, +- unsigned long index, unsigned long max_scan) +-{ +- unsigned long i; +- +- for (i = 0; i < max_scan; i++) { +- if (!radix_tree_lookup(root, index)) +- break; +- index--; +- if (index == ULONG_MAX) +- break; +- } +- +- return index; +-} +-EXPORT_SYMBOL(radix_tree_prev_hole); +- + /** + * radix_tree_gang_lookup - perform multiple lookup on a radix tree + * @root: radix tree root +@@ -1337,15 +1262,18 @@ static inline void radix_tree_shrink(struct radix_tree_root *root) + } + + /** +- * radix_tree_delete - delete an item from a radix tree ++ * radix_tree_delete_item - delete an item from a radix tree + * @root: radix tree root + * @index: index key ++ * @item: expected item + * +- * Remove the item at @index from the radix tree rooted at @root. ++ * Remove @item at @index from the radix tree rooted at @root. + * +- * Returns the address of the deleted item, or NULL if it was not present. ++ * Returns the address of the deleted item, or NULL if it was not present ++ * or the entry at the given @index was not @item. + */ +-void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) ++void *radix_tree_delete_item(struct radix_tree_root *root, ++ unsigned long index, void *item) + { + struct radix_tree_node *node = NULL; + struct radix_tree_node *slot = NULL; +@@ -1380,6 +1308,11 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) + if (slot == NULL) + goto out; + ++ if (item && slot != item) { ++ slot = NULL; ++ goto out; ++ } ++ + /* + * Clear all tags associated with the item to be deleted. + * This way of doing it would be inefficient, but seldom is any set. +@@ -1424,6 +1357,21 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) + out: + return slot; + } ++EXPORT_SYMBOL(radix_tree_delete_item); ++ ++/** ++ * radix_tree_delete - delete an item from a radix tree ++ * @root: radix tree root ++ * @index: index key ++ * ++ * Remove the item at @index from the radix tree rooted at @root. ++ * ++ * Returns the address of the deleted item, or NULL if it was not present. ++ */ ++void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) ++{ ++ return radix_tree_delete_item(root, index, NULL); ++} + EXPORT_SYMBOL(radix_tree_delete); + + /** +diff --git a/mm/compaction.c b/mm/compaction.c +index 5e38e5706f62..4229fc22a477 100644 +--- a/mm/compaction.c ++++ b/mm/compaction.c +@@ -89,7 +89,8 @@ static void __reset_isolation_suitable(struct zone *zone) + unsigned long end_pfn = zone_end_pfn(zone); + unsigned long pfn; + +- zone->compact_cached_migrate_pfn = start_pfn; ++ zone->compact_cached_migrate_pfn[0] = start_pfn; ++ zone->compact_cached_migrate_pfn[1] = start_pfn; + zone->compact_cached_free_pfn = end_pfn; + zone->compact_blockskip_flush = false; + +@@ -131,9 +132,10 @@ void reset_isolation_suitable(pg_data_t *pgdat) + */ + static void update_pageblock_skip(struct compact_control *cc, + struct page *page, unsigned long nr_isolated, +- bool migrate_scanner) ++ bool set_unsuitable, bool migrate_scanner) + { + struct zone *zone = cc->zone; ++ unsigned long pfn; + + if (cc->ignore_skip_hint) + return; +@@ -141,20 +143,32 @@ static void update_pageblock_skip(struct compact_control *cc, + if (!page) + return; + +- if (!nr_isolated) { +- unsigned long pfn = page_to_pfn(page); ++ if (nr_isolated) ++ return; ++ ++ /* ++ * Only skip pageblocks when all forms of compaction will be known to ++ * fail in the near future. ++ */ ++ if (set_unsuitable) + set_pageblock_skip(page); + +- /* Update where compaction should restart */ +- if (migrate_scanner) { +- if (!cc->finished_update_migrate && +- pfn > zone->compact_cached_migrate_pfn) +- zone->compact_cached_migrate_pfn = pfn; +- } else { +- if (!cc->finished_update_free && +- pfn < zone->compact_cached_free_pfn) +- zone->compact_cached_free_pfn = pfn; +- } ++ pfn = page_to_pfn(page); ++ ++ /* Update where async and sync compaction should restart */ ++ if (migrate_scanner) { ++ if (cc->finished_update_migrate) ++ return; ++ if (pfn > zone->compact_cached_migrate_pfn[0]) ++ zone->compact_cached_migrate_pfn[0] = pfn; ++ if (cc->mode != MIGRATE_ASYNC && ++ pfn > zone->compact_cached_migrate_pfn[1]) ++ zone->compact_cached_migrate_pfn[1] = pfn; ++ } else { ++ if (cc->finished_update_free) ++ return; ++ if (pfn < zone->compact_cached_free_pfn) ++ zone->compact_cached_free_pfn = pfn; + } + } + #else +@@ -166,7 +180,7 @@ static inline bool isolation_suitable(struct compact_control *cc, + + static void update_pageblock_skip(struct compact_control *cc, + struct page *page, unsigned long nr_isolated, +- bool migrate_scanner) ++ bool set_unsuitable, bool migrate_scanner) + { + } + #endif /* CONFIG_COMPACTION */ +@@ -195,7 +209,7 @@ static bool compact_checklock_irqsave(spinlock_t *lock, unsigned long *flags, + } + + /* async aborts if taking too long or contended */ +- if (!cc->sync) { ++ if (cc->mode == MIGRATE_ASYNC) { + cc->contended = true; + return false; + } +@@ -208,10 +222,28 @@ static bool compact_checklock_irqsave(spinlock_t *lock, unsigned long *flags, + return true; + } + +-static inline bool compact_trylock_irqsave(spinlock_t *lock, +- unsigned long *flags, struct compact_control *cc) ++/* ++ * Aside from avoiding lock contention, compaction also periodically checks ++ * need_resched() and either schedules in sync compaction or aborts async ++ * compaction. This is similar to what compact_checklock_irqsave() does, but ++ * is used where no lock is concerned. ++ * ++ * Returns false when no scheduling was needed, or sync compaction scheduled. ++ * Returns true when async compaction should abort. ++ */ ++static inline bool compact_should_abort(struct compact_control *cc) + { +- return compact_checklock_irqsave(lock, flags, false, cc); ++ /* async compaction aborts if contended */ ++ if (need_resched()) { ++ if (cc->mode == MIGRATE_ASYNC) { ++ cc->contended = true; ++ return true; ++ } ++ ++ cond_resched(); ++ } ++ ++ return false; + } + + /* Returns true if the page is within a block suitable for migration to */ +@@ -329,7 +361,8 @@ isolate_fail: + + /* Update the pageblock-skip if the whole pageblock was scanned */ + if (blockpfn == end_pfn) +- update_pageblock_skip(cc, valid_page, total_isolated, false); ++ update_pageblock_skip(cc, valid_page, total_isolated, true, ++ false); + + count_compact_events(COMPACTFREE_SCANNED, nr_scanned); + if (total_isolated) +@@ -464,8 +497,9 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + unsigned long flags; + bool locked = false; + struct page *page = NULL, *valid_page = NULL; +- bool skipped_async_unsuitable = false; +- const isolate_mode_t mode = (!cc->sync ? ISOLATE_ASYNC_MIGRATE : 0) | ++ bool set_unsuitable = true; ++ const isolate_mode_t mode = (cc->mode == MIGRATE_ASYNC ? ++ ISOLATE_ASYNC_MIGRATE : 0) | + (unevictable ? ISOLATE_UNEVICTABLE : 0); + + /* +@@ -475,7 +509,7 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + */ + while (unlikely(too_many_isolated(zone))) { + /* async migration should just abort */ +- if (!cc->sync) ++ if (cc->mode == MIGRATE_ASYNC) + return 0; + + congestion_wait(BLK_RW_ASYNC, HZ/10); +@@ -484,8 +518,10 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + return 0; + } + ++ if (compact_should_abort(cc)) ++ return 0; ++ + /* Time to isolate some pages for migration */ +- cond_resched(); + for (; low_pfn < end_pfn; low_pfn++) { + /* give a chance to irqs before checking need_resched() */ + if (locked && !(low_pfn % SWAP_CLUSTER_MAX)) { +@@ -540,9 +576,9 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + * the minimum amount of work satisfies the allocation + */ + mt = get_pageblock_migratetype(page); +- if (!cc->sync && !migrate_async_suitable(mt)) { +- cc->finished_update_migrate = true; +- skipped_async_unsuitable = true; ++ if (cc->mode == MIGRATE_ASYNC && ++ !migrate_async_suitable(mt)) { ++ set_unsuitable = false; + goto next_pageblock; + } + } +@@ -646,11 +682,10 @@ next_pageblock: + /* + * Update the pageblock-skip information and cached scanner pfn, + * if the whole pageblock was scanned without isolating any page. +- * This is not done when pageblock was skipped due to being unsuitable +- * for async compaction, so that eventual sync compaction can try. + */ +- if (low_pfn == end_pfn && !skipped_async_unsuitable) +- update_pageblock_skip(cc, valid_page, nr_isolated, true); ++ if (low_pfn == end_pfn) ++ update_pageblock_skip(cc, valid_page, nr_isolated, ++ set_unsuitable, true); + + trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated); + +@@ -671,7 +706,9 @@ static void isolate_freepages(struct zone *zone, + struct compact_control *cc) + { + struct page *page; +- unsigned long high_pfn, low_pfn, pfn, z_end_pfn; ++ unsigned long block_start_pfn; /* start of current pageblock */ ++ unsigned long block_end_pfn; /* end of current pageblock */ ++ unsigned long low_pfn; /* lowest pfn scanner is able to scan */ + int nr_freepages = cc->nr_freepages; + struct list_head *freelist = &cc->freepages; + +@@ -679,41 +716,38 @@ static void isolate_freepages(struct zone *zone, + * Initialise the free scanner. The starting point is where we last + * successfully isolated from, zone-cached value, or the end of the + * zone when isolating for the first time. We need this aligned to +- * the pageblock boundary, because we do pfn -= pageblock_nr_pages +- * in the for loop. ++ * the pageblock boundary, because we do ++ * block_start_pfn -= pageblock_nr_pages in the for loop. ++ * For ending point, take care when isolating in last pageblock of a ++ * a zone which ends in the middle of a pageblock. + * The low boundary is the end of the pageblock the migration scanner + * is using. + */ +- pfn = cc->free_pfn & ~(pageblock_nr_pages-1); ++ block_start_pfn = cc->free_pfn & ~(pageblock_nr_pages-1); ++ block_end_pfn = min(block_start_pfn + pageblock_nr_pages, ++ zone_end_pfn(zone)); + low_pfn = ALIGN(cc->migrate_pfn + 1, pageblock_nr_pages); + + /* +- * Take care that if the migration scanner is at the end of the zone +- * that the free scanner does not accidentally move to the next zone +- * in the next isolation cycle. +- */ +- high_pfn = min(low_pfn, pfn); +- +- z_end_pfn = zone_end_pfn(zone); +- +- /* + * Isolate free pages until enough are available to migrate the + * pages on cc->migratepages. We stop searching if the migrate + * and free page scanners meet or enough free pages are isolated. + */ +- for (; pfn >= low_pfn && cc->nr_migratepages > nr_freepages; +- pfn -= pageblock_nr_pages) { ++ for (; block_start_pfn >= low_pfn && cc->nr_migratepages > nr_freepages; ++ block_end_pfn = block_start_pfn, ++ block_start_pfn -= pageblock_nr_pages) { + unsigned long isolated; +- unsigned long end_pfn; + + /* + * This can iterate a massively long zone without finding any + * suitable migration targets, so periodically check if we need +- * to schedule. ++ * to schedule, or even abort async compaction. + */ +- cond_resched(); ++ if (!(block_start_pfn % (SWAP_CLUSTER_MAX * pageblock_nr_pages)) ++ && compact_should_abort(cc)) ++ break; + +- if (!pfn_valid(pfn)) ++ if (!pfn_valid(block_start_pfn)) + continue; + + /* +@@ -723,7 +757,7 @@ static void isolate_freepages(struct zone *zone, + * i.e. it's possible that all pages within a zones range of + * pages do not belong to a single zone. + */ +- page = pfn_to_page(pfn); ++ page = pfn_to_page(block_start_pfn); + if (page_zone(page) != zone) + continue; + +@@ -736,26 +770,26 @@ static void isolate_freepages(struct zone *zone, + continue; + + /* Found a block suitable for isolating free pages from */ +- isolated = 0; ++ cc->free_pfn = block_start_pfn; ++ isolated = isolate_freepages_block(cc, block_start_pfn, ++ block_end_pfn, freelist, false); ++ nr_freepages += isolated; + + /* +- * Take care when isolating in last pageblock of a zone which +- * ends in the middle of a pageblock. ++ * Set a flag that we successfully isolated in this pageblock. ++ * In the next loop iteration, zone->compact_cached_free_pfn ++ * will not be updated and thus it will effectively contain the ++ * highest pageblock we isolated pages from. + */ +- end_pfn = min(pfn + pageblock_nr_pages, z_end_pfn); +- isolated = isolate_freepages_block(cc, pfn, end_pfn, +- freelist, false); +- nr_freepages += isolated; ++ if (isolated) ++ cc->finished_update_free = true; + + /* +- * Record the highest PFN we isolated pages from. When next +- * looking for free pages, the search will restart here as +- * page migration may have returned some pages to the allocator ++ * isolate_freepages_block() might have aborted due to async ++ * compaction being contended + */ +- if (isolated) { +- cc->finished_update_free = true; +- high_pfn = max(high_pfn, pfn); +- } ++ if (cc->contended) ++ break; + } + + /* split_free_page does not map the pages */ +@@ -765,10 +799,9 @@ static void isolate_freepages(struct zone *zone, + * If we crossed the migrate scanner, we want to keep it that way + * so that compact_finished() may detect this + */ +- if (pfn < low_pfn) +- cc->free_pfn = max(pfn, zone->zone_start_pfn); +- else +- cc->free_pfn = high_pfn; ++ if (block_start_pfn < low_pfn) ++ cc->free_pfn = cc->migrate_pfn; ++ + cc->nr_freepages = nr_freepages; + } + +@@ -783,9 +816,13 @@ static struct page *compaction_alloc(struct page *migratepage, + struct compact_control *cc = (struct compact_control *)data; + struct page *freepage; + +- /* Isolate free pages if necessary */ ++ /* ++ * Isolate free pages if necessary, and if we are not aborting due to ++ * contention. ++ */ + if (list_empty(&cc->freepages)) { +- isolate_freepages(cc->zone, cc); ++ if (!cc->contended) ++ isolate_freepages(cc->zone, cc); + + if (list_empty(&cc->freepages)) + return NULL; +@@ -799,23 +836,16 @@ static struct page *compaction_alloc(struct page *migratepage, + } + + /* +- * We cannot control nr_migratepages and nr_freepages fully when migration is +- * running as migrate_pages() has no knowledge of compact_control. When +- * migration is complete, we count the number of pages on the lists by hand. ++ * This is a migrate-callback that "frees" freepages back to the isolated ++ * freelist. All pages on the freelist are from the same zone, so there is no ++ * special handling needed for NUMA. + */ +-static void update_nr_listpages(struct compact_control *cc) ++static void compaction_free(struct page *page, unsigned long data) + { +- int nr_migratepages = 0; +- int nr_freepages = 0; +- struct page *page; +- +- list_for_each_entry(page, &cc->migratepages, lru) +- nr_migratepages++; +- list_for_each_entry(page, &cc->freepages, lru) +- nr_freepages++; ++ struct compact_control *cc = (struct compact_control *)data; + +- cc->nr_migratepages = nr_migratepages; +- cc->nr_freepages = nr_freepages; ++ list_add(&page->lru, &cc->freepages); ++ cc->nr_freepages++; + } + + /* possible outcome of isolate_migratepages */ +@@ -862,13 +892,14 @@ static int compact_finished(struct zone *zone, + unsigned int order; + unsigned long watermark; + +- if (fatal_signal_pending(current)) ++ if (cc->contended || fatal_signal_pending(current)) + return COMPACT_PARTIAL; + + /* Compaction run completes if the migrate and free scanner meet */ + if (cc->free_pfn <= cc->migrate_pfn) { + /* Let the next compaction start anew. */ +- zone->compact_cached_migrate_pfn = zone->zone_start_pfn; ++ zone->compact_cached_migrate_pfn[0] = zone->zone_start_pfn; ++ zone->compact_cached_migrate_pfn[1] = zone->zone_start_pfn; + zone->compact_cached_free_pfn = zone_end_pfn(zone); + + /* +@@ -968,6 +999,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) + int ret; + unsigned long start_pfn = zone->zone_start_pfn; + unsigned long end_pfn = zone_end_pfn(zone); ++ const bool sync = cc->mode != MIGRATE_ASYNC; + + ret = compaction_suitable(zone, cc->order); + switch (ret) { +@@ -993,7 +1025,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) + * information on where the scanners should start but check that it + * is initialised by ensuring the values are within zone boundaries. + */ +- cc->migrate_pfn = zone->compact_cached_migrate_pfn; ++ cc->migrate_pfn = zone->compact_cached_migrate_pfn[sync]; + cc->free_pfn = zone->compact_cached_free_pfn; + if (cc->free_pfn < start_pfn || cc->free_pfn > end_pfn) { + cc->free_pfn = end_pfn & ~(pageblock_nr_pages-1); +@@ -1001,7 +1033,8 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) + } + if (cc->migrate_pfn < start_pfn || cc->migrate_pfn > end_pfn) { + cc->migrate_pfn = start_pfn; +- zone->compact_cached_migrate_pfn = cc->migrate_pfn; ++ zone->compact_cached_migrate_pfn[0] = cc->migrate_pfn; ++ zone->compact_cached_migrate_pfn[1] = cc->migrate_pfn; + } + + trace_mm_compaction_begin(start_pfn, cc->migrate_pfn, cc->free_pfn, end_pfn); +@@ -1009,7 +1042,6 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) + migrate_prep_local(); + + while ((ret = compact_finished(zone, cc)) == COMPACT_CONTINUE) { +- unsigned long nr_migrate, nr_remaining; + int err; + + switch (isolate_migratepages(zone, cc)) { +@@ -1024,21 +1056,20 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) + ; + } + +- nr_migrate = cc->nr_migratepages; ++ if (!cc->nr_migratepages) ++ continue; ++ + err = migrate_pages(&cc->migratepages, compaction_alloc, +- (unsigned long)cc, +- cc->sync ? MIGRATE_SYNC_LIGHT : MIGRATE_ASYNC, ++ compaction_free, (unsigned long)cc, cc->mode, + MR_COMPACTION); +- update_nr_listpages(cc); +- nr_remaining = cc->nr_migratepages; + +- trace_mm_compaction_migratepages(nr_migrate - nr_remaining, +- nr_remaining); ++ trace_mm_compaction_migratepages(cc->nr_migratepages, err, ++ &cc->migratepages); + +- /* Release isolated pages not migrated */ ++ /* All pages were either migrated or will be released */ ++ cc->nr_migratepages = 0; + if (err) { + putback_movable_pages(&cc->migratepages); +- cc->nr_migratepages = 0; + /* + * migrate_pages() may return -ENOMEM when scanners meet + * and we want compact_finished() to detect it +@@ -1060,9 +1091,8 @@ out: + return ret; + } + +-static unsigned long compact_zone_order(struct zone *zone, +- int order, gfp_t gfp_mask, +- bool sync, bool *contended) ++static unsigned long compact_zone_order(struct zone *zone, int order, ++ gfp_t gfp_mask, enum migrate_mode mode, bool *contended) + { + unsigned long ret; + struct compact_control cc = { +@@ -1071,7 +1101,7 @@ static unsigned long compact_zone_order(struct zone *zone, + .order = order, + .migratetype = allocflags_to_migratetype(gfp_mask), + .zone = zone, +- .sync = sync, ++ .mode = mode, + }; + INIT_LIST_HEAD(&cc.freepages); + INIT_LIST_HEAD(&cc.migratepages); +@@ -1093,7 +1123,7 @@ int sysctl_extfrag_threshold = 500; + * @order: The order of the current allocation + * @gfp_mask: The GFP mask of the current allocation + * @nodemask: The allowed nodes to allocate from +- * @sync: Whether migration is synchronous or not ++ * @mode: The migration mode for async, sync light, or sync migration + * @contended: Return value that is true if compaction was aborted due to lock contention + * @page: Optionally capture a free page of the requested order during compaction + * +@@ -1101,7 +1131,7 @@ int sysctl_extfrag_threshold = 500; + */ + unsigned long try_to_compact_pages(struct zonelist *zonelist, + int order, gfp_t gfp_mask, nodemask_t *nodemask, +- bool sync, bool *contended) ++ enum migrate_mode mode, bool *contended) + { + enum zone_type high_zoneidx = gfp_zone(gfp_mask); + int may_enter_fs = gfp_mask & __GFP_FS; +@@ -1126,7 +1156,7 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist, + nodemask) { + int status; + +- status = compact_zone_order(zone, order, gfp_mask, sync, ++ status = compact_zone_order(zone, order, gfp_mask, mode, + contended); + rc = max(status, rc); + +@@ -1165,9 +1195,6 @@ static void __compact_pgdat(pg_data_t *pgdat, struct compact_control *cc) + if (zone_watermark_ok(zone, cc->order, + low_wmark_pages(zone), 0, 0)) + compaction_defer_reset(zone, cc->order, false); +- /* Currently async compaction is never deferred. */ +- else if (cc->sync) +- defer_compaction(zone, cc->order); + } + + VM_BUG_ON(!list_empty(&cc->freepages)); +@@ -1179,7 +1206,7 @@ void compact_pgdat(pg_data_t *pgdat, int order) + { + struct compact_control cc = { + .order = order, +- .sync = false, ++ .mode = MIGRATE_ASYNC, + }; + + if (!order) +@@ -1192,7 +1219,7 @@ static void compact_node(int nid) + { + struct compact_control cc = { + .order = -1, +- .sync = true, ++ .mode = MIGRATE_SYNC, + .ignore_skip_hint = true, + }; + +diff --git a/mm/filemap.c b/mm/filemap.c +index c2cc7c95eff1..bdaa21555abe 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -448,6 +448,29 @@ int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask) + } + EXPORT_SYMBOL_GPL(replace_page_cache_page); + ++static int page_cache_tree_insert(struct address_space *mapping, ++ struct page *page) ++{ ++ void **slot; ++ int error; ++ ++ slot = radix_tree_lookup_slot(&mapping->page_tree, page->index); ++ if (slot) { ++ void *p; ++ ++ p = radix_tree_deref_slot_protected(slot, &mapping->tree_lock); ++ if (!radix_tree_exceptional_entry(p)) ++ return -EEXIST; ++ radix_tree_replace_slot(slot, page); ++ mapping->nrpages++; ++ return 0; ++ } ++ error = radix_tree_insert(&mapping->page_tree, page->index, page); ++ if (!error) ++ mapping->nrpages++; ++ return error; ++} ++ + /** + * add_to_page_cache_locked - add a locked page to the pagecache + * @page: page to add +@@ -482,11 +505,10 @@ int add_to_page_cache_locked(struct page *page, struct address_space *mapping, + page->index = offset; + + spin_lock_irq(&mapping->tree_lock); +- error = radix_tree_insert(&mapping->page_tree, offset, page); ++ error = page_cache_tree_insert(mapping, page); + radix_tree_preload_end(); + if (unlikely(error)) + goto err_insert; +- mapping->nrpages++; + __inc_zone_page_state(page, NR_FILE_PAGES); + spin_unlock_irq(&mapping->tree_lock); + trace_mm_filemap_add_to_page_cache(page); +@@ -688,14 +710,101 @@ int __lock_page_or_retry(struct page *page, struct mm_struct *mm, + } + + /** +- * find_get_page - find and get a page reference ++ * page_cache_next_hole - find the next hole (not-present entry) ++ * @mapping: mapping ++ * @index: index ++ * @max_scan: maximum range to search ++ * ++ * Search the set [index, min(index+max_scan-1, MAX_INDEX)] for the ++ * lowest indexed hole. ++ * ++ * Returns: the index of the hole if found, otherwise returns an index ++ * outside of the set specified (in which case 'return - index >= ++ * max_scan' will be true). In rare cases of index wrap-around, 0 will ++ * be returned. ++ * ++ * page_cache_next_hole may be called under rcu_read_lock. However, ++ * like radix_tree_gang_lookup, this will not atomically search a ++ * snapshot of the tree at a single point in time. For example, if a ++ * hole is created at index 5, then subsequently a hole is created at ++ * index 10, page_cache_next_hole covering both indexes may return 10 ++ * if called under rcu_read_lock. ++ */ ++pgoff_t page_cache_next_hole(struct address_space *mapping, ++ pgoff_t index, unsigned long max_scan) ++{ ++ unsigned long i; ++ ++ for (i = 0; i < max_scan; i++) { ++ struct page *page; ++ ++ page = radix_tree_lookup(&mapping->page_tree, index); ++ if (!page || radix_tree_exceptional_entry(page)) ++ break; ++ index++; ++ if (index == 0) ++ break; ++ } ++ ++ return index; ++} ++EXPORT_SYMBOL(page_cache_next_hole); ++ ++/** ++ * page_cache_prev_hole - find the prev hole (not-present entry) ++ * @mapping: mapping ++ * @index: index ++ * @max_scan: maximum range to search ++ * ++ * Search backwards in the range [max(index-max_scan+1, 0), index] for ++ * the first hole. ++ * ++ * Returns: the index of the hole if found, otherwise returns an index ++ * outside of the set specified (in which case 'index - return >= ++ * max_scan' will be true). In rare cases of wrap-around, ULONG_MAX ++ * will be returned. ++ * ++ * page_cache_prev_hole may be called under rcu_read_lock. However, ++ * like radix_tree_gang_lookup, this will not atomically search a ++ * snapshot of the tree at a single point in time. For example, if a ++ * hole is created at index 10, then subsequently a hole is created at ++ * index 5, page_cache_prev_hole covering both indexes may return 5 if ++ * called under rcu_read_lock. ++ */ ++pgoff_t page_cache_prev_hole(struct address_space *mapping, ++ pgoff_t index, unsigned long max_scan) ++{ ++ unsigned long i; ++ ++ for (i = 0; i < max_scan; i++) { ++ struct page *page; ++ ++ page = radix_tree_lookup(&mapping->page_tree, index); ++ if (!page || radix_tree_exceptional_entry(page)) ++ break; ++ index--; ++ if (index == ULONG_MAX) ++ break; ++ } ++ ++ return index; ++} ++EXPORT_SYMBOL(page_cache_prev_hole); ++ ++/** ++ * find_get_entry - find and get a page cache entry + * @mapping: the address_space to search +- * @offset: the page index ++ * @offset: the page cache index + * +- * Is there a pagecache struct page at the given (mapping, offset) tuple? +- * If yes, increment its refcount and return it; if no, return NULL. ++ * Looks up the page cache slot at @mapping & @offset. If there is a ++ * page cache page, it is returned with an increased refcount. ++ * ++ * If the slot holds a shadow entry of a previously evicted page, it ++ * is returned. ++ * ++ * Otherwise, %NULL is returned. + */ +-struct page *find_get_page(struct address_space *mapping, pgoff_t offset) ++struct page *find_get_entry(struct address_space *mapping, pgoff_t offset) + { + void **pagep; + struct page *page; +@@ -736,24 +845,50 @@ out: + + return page; + } +-EXPORT_SYMBOL(find_get_page); ++EXPORT_SYMBOL(find_get_entry); + + /** +- * find_lock_page - locate, pin and lock a pagecache page ++ * find_get_page - find and get a page reference + * @mapping: the address_space to search + * @offset: the page index + * +- * Locates the desired pagecache page, locks it, increments its reference +- * count and returns its address. ++ * Looks up the page cache slot at @mapping & @offset. If there is a ++ * page cache page, it is returned with an increased refcount. + * +- * Returns zero if the page was not present. find_lock_page() may sleep. ++ * Otherwise, %NULL is returned. + */ +-struct page *find_lock_page(struct address_space *mapping, pgoff_t offset) ++struct page *find_get_page(struct address_space *mapping, pgoff_t offset) ++{ ++ struct page *page = find_get_entry(mapping, offset); ++ ++ if (radix_tree_exceptional_entry(page)) ++ page = NULL; ++ return page; ++} ++EXPORT_SYMBOL(find_get_page); ++ ++/** ++ * find_lock_entry - locate, pin and lock a page cache entry ++ * @mapping: the address_space to search ++ * @offset: the page cache index ++ * ++ * Looks up the page cache slot at @mapping & @offset. If there is a ++ * page cache page, it is returned locked and with an increased ++ * refcount. ++ * ++ * If the slot holds a shadow entry of a previously evicted page, it ++ * is returned. ++ * ++ * Otherwise, %NULL is returned. ++ * ++ * find_lock_entry() may sleep. ++ */ ++struct page *find_lock_entry(struct address_space *mapping, pgoff_t offset) + { + struct page *page; + + repeat: +- page = find_get_page(mapping, offset); ++ page = find_get_entry(mapping, offset); + if (page && !radix_tree_exception(page)) { + lock_page(page); + /* Has the page been truncated? */ +@@ -766,6 +901,29 @@ repeat: + } + return page; + } ++EXPORT_SYMBOL(find_lock_entry); ++ ++/** ++ * find_lock_page - locate, pin and lock a pagecache page ++ * @mapping: the address_space to search ++ * @offset: the page index ++ * ++ * Looks up the page cache slot at @mapping & @offset. If there is a ++ * page cache page, it is returned locked and with an increased ++ * refcount. ++ * ++ * Otherwise, %NULL is returned. ++ * ++ * find_lock_page() may sleep. ++ */ ++struct page *find_lock_page(struct address_space *mapping, pgoff_t offset) ++{ ++ struct page *page = find_lock_entry(mapping, offset); ++ ++ if (radix_tree_exceptional_entry(page)) ++ page = NULL; ++ return page; ++} + EXPORT_SYMBOL(find_lock_page); + + /** +@@ -774,16 +932,18 @@ EXPORT_SYMBOL(find_lock_page); + * @index: the page's index into the mapping + * @gfp_mask: page allocation mode + * +- * Locates a page in the pagecache. If the page is not present, a new page +- * is allocated using @gfp_mask and is added to the pagecache and to the VM's +- * LRU list. The returned page is locked and has its reference count +- * incremented. ++ * Looks up the page cache slot at @mapping & @offset. If there is a ++ * page cache page, it is returned locked and with an increased ++ * refcount. ++ * ++ * If the page is not present, a new page is allocated using @gfp_mask ++ * and added to the page cache and the VM's LRU list. The page is ++ * returned locked and with an increased refcount. + * +- * find_or_create_page() may sleep, even if @gfp_flags specifies an atomic +- * allocation! ++ * On memory exhaustion, %NULL is returned. + * +- * find_or_create_page() returns the desired page's address, or zero on +- * memory exhaustion. ++ * find_or_create_page() may sleep, even if @gfp_flags specifies an ++ * atomic allocation! + */ + struct page *find_or_create_page(struct address_space *mapping, + pgoff_t index, gfp_t gfp_mask) +@@ -816,6 +976,76 @@ repeat: + EXPORT_SYMBOL(find_or_create_page); + + /** ++ * find_get_entries - gang pagecache lookup ++ * @mapping: The address_space to search ++ * @start: The starting page cache index ++ * @nr_entries: The maximum number of entries ++ * @entries: Where the resulting entries are placed ++ * @indices: The cache indices corresponding to the entries in @entries ++ * ++ * find_get_entries() will search for and return a group of up to ++ * @nr_entries entries in the mapping. The entries are placed at ++ * @entries. find_get_entries() takes a reference against any actual ++ * pages it returns. ++ * ++ * The search returns a group of mapping-contiguous page cache entries ++ * with ascending indexes. There may be holes in the indices due to ++ * not-present pages. ++ * ++ * Any shadow entries of evicted pages are included in the returned ++ * array. ++ * ++ * find_get_entries() returns the number of pages and shadow entries ++ * which were found. ++ */ ++unsigned find_get_entries(struct address_space *mapping, ++ pgoff_t start, unsigned int nr_entries, ++ struct page **entries, pgoff_t *indices) ++{ ++ void **slot; ++ unsigned int ret = 0; ++ struct radix_tree_iter iter; ++ ++ if (!nr_entries) ++ return 0; ++ ++ rcu_read_lock(); ++restart: ++ radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) { ++ struct page *page; ++repeat: ++ page = radix_tree_deref_slot(slot); ++ if (unlikely(!page)) ++ continue; ++ if (radix_tree_exception(page)) { ++ if (radix_tree_deref_retry(page)) ++ goto restart; ++ /* ++ * Otherwise, we must be storing a swap entry ++ * here as an exceptional entry: so return it ++ * without attempting to raise page count. ++ */ ++ goto export; ++ } ++ if (!page_cache_get_speculative(page)) ++ goto repeat; ++ ++ /* Has the page moved? */ ++ if (unlikely(page != *slot)) { ++ page_cache_release(page); ++ goto repeat; ++ } ++export: ++ indices[ret] = iter.index; ++ entries[ret] = page; ++ if (++ret == nr_entries) ++ break; ++ } ++ rcu_read_unlock(); ++ return ret; ++} ++ ++/** + * find_get_pages - gang pagecache lookup + * @mapping: The address_space to search + * @start: The starting page index +@@ -1797,6 +2027,18 @@ int generic_file_readonly_mmap(struct file * file, struct vm_area_struct * vma) + EXPORT_SYMBOL(generic_file_mmap); + EXPORT_SYMBOL(generic_file_readonly_mmap); + ++static struct page *wait_on_page_read(struct page *page) ++{ ++ if (!IS_ERR(page)) { ++ wait_on_page_locked(page); ++ if (!PageUptodate(page)) { ++ page_cache_release(page); ++ page = ERR_PTR(-EIO); ++ } ++ } ++ return page; ++} ++ + static struct page *__read_cache_page(struct address_space *mapping, + pgoff_t index, + int (*filler)(void *, struct page *), +@@ -1823,6 +2065,8 @@ repeat: + if (err < 0) { + page_cache_release(page); + page = ERR_PTR(err); ++ } else { ++ page = wait_on_page_read(page); + } + } + return page; +@@ -1859,6 +2103,10 @@ retry: + if (err < 0) { + page_cache_release(page); + return ERR_PTR(err); ++ } else { ++ page = wait_on_page_read(page); ++ if (IS_ERR(page)) ++ return page; + } + out: + mark_page_accessed(page); +@@ -1866,40 +2114,25 @@ out: + } + + /** +- * read_cache_page_async - read into page cache, fill it if needed ++ * read_cache_page - read into page cache, fill it if needed + * @mapping: the page's address_space + * @index: the page index + * @filler: function to perform the read + * @data: first arg to filler(data, page) function, often left as NULL + * +- * Same as read_cache_page, but don't wait for page to become unlocked +- * after submitting it to the filler. +- * + * Read into the page cache. If a page already exists, and PageUptodate() is +- * not set, try to fill the page but don't wait for it to become unlocked. ++ * not set, try to fill the page and wait for it to become unlocked. + * + * If the page does not get brought uptodate, return -EIO. + */ +-struct page *read_cache_page_async(struct address_space *mapping, ++struct page *read_cache_page(struct address_space *mapping, + pgoff_t index, + int (*filler)(void *, struct page *), + void *data) + { + return do_read_cache_page(mapping, index, filler, data, mapping_gfp_mask(mapping)); + } +-EXPORT_SYMBOL(read_cache_page_async); +- +-static struct page *wait_on_page_read(struct page *page) +-{ +- if (!IS_ERR(page)) { +- wait_on_page_locked(page); +- if (!PageUptodate(page)) { +- page_cache_release(page); +- page = ERR_PTR(-EIO); +- } +- } +- return page; +-} ++EXPORT_SYMBOL(read_cache_page); + + /** + * read_cache_page_gfp - read into page cache, using specified page allocation flags. +@@ -1918,31 +2151,10 @@ struct page *read_cache_page_gfp(struct address_space *mapping, + { + filler_t *filler = (filler_t *)mapping->a_ops->readpage; + +- return wait_on_page_read(do_read_cache_page(mapping, index, filler, NULL, gfp)); ++ return do_read_cache_page(mapping, index, filler, NULL, gfp); + } + EXPORT_SYMBOL(read_cache_page_gfp); + +-/** +- * read_cache_page - read into page cache, fill it if needed +- * @mapping: the page's address_space +- * @index: the page index +- * @filler: function to perform the read +- * @data: first arg to filler(data, page) function, often left as NULL +- * +- * Read into the page cache. If a page already exists, and PageUptodate() is +- * not set, try to fill the page then wait for it to become unlocked. +- * +- * If the page does not get brought uptodate, return -EIO. +- */ +-struct page *read_cache_page(struct address_space *mapping, +- pgoff_t index, +- int (*filler)(void *, struct page *), +- void *data) +-{ +- return wait_on_page_read(read_cache_page_async(mapping, index, filler, data)); +-} +-EXPORT_SYMBOL(read_cache_page); +- + static size_t __iovec_copy_from_user_inatomic(char *vaddr, + const struct iovec *iov, size_t base, size_t bytes) + { +@@ -1976,7 +2188,6 @@ size_t iov_iter_copy_from_user_atomic(struct page *page, + char *kaddr; + size_t copied; + +- BUG_ON(!in_atomic()); + kaddr = kmap_atomic(page); + if (likely(i->nr_segs == 1)) { + int left; +@@ -2350,9 +2561,7 @@ again: + if (mapping_writably_mapped(mapping)) + flush_dcache_page(page); + +- pagefault_disable(); + copied = iov_iter_copy_from_user_atomic(page, i, offset, bytes); +- pagefault_enable(); + flush_dcache_page(page); + + mark_page_accessed(page); +diff --git a/mm/internal.h b/mm/internal.h +index 3e910000fda4..1a8a0d4b687a 100644 +--- a/mm/internal.h ++++ b/mm/internal.h +@@ -11,6 +11,7 @@ + #ifndef __MM_INTERNAL_H + #define __MM_INTERNAL_H + ++#include + #include + + void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma, +@@ -21,6 +22,20 @@ static inline void set_page_count(struct page *page, int v) + atomic_set(&page->_count, v); + } + ++extern int __do_page_cache_readahead(struct address_space *mapping, ++ struct file *filp, pgoff_t offset, unsigned long nr_to_read, ++ unsigned long lookahead_size); ++ ++/* ++ * Submit IO for the read-ahead request in file_ra_state. ++ */ ++static inline unsigned long ra_submit(struct file_ra_state *ra, ++ struct address_space *mapping, struct file *filp) ++{ ++ return __do_page_cache_readahead(mapping, filp, ++ ra->start, ra->size, ra->async_size); ++} ++ + /* + * Turn a non-refcounted page (->_count == 0) into refcounted with + * a count of one. +@@ -119,7 +134,7 @@ struct compact_control { + unsigned long nr_migratepages; /* Number of pages to migrate */ + unsigned long free_pfn; /* isolate_freepages search base */ + unsigned long migrate_pfn; /* isolate_migratepages search base */ +- bool sync; /* Synchronous migration */ ++ enum migrate_mode mode; /* Async or sync migration mode */ + bool ignore_skip_hint; /* Scan blocks even if marked skip */ + bool finished_update_free; /* True when the zone cached pfns are + * no longer being updated +@@ -129,7 +144,10 @@ struct compact_control { + int order; /* order a direct compactor needs */ + int migratetype; /* MOVABLE, RECLAIMABLE etc */ + struct zone *zone; +- bool contended; /* True if a lock was contended */ ++ bool contended; /* True if a lock was contended, or ++ * need_resched() true during async ++ * compaction ++ */ + }; + + unsigned long +diff --git a/mm/madvise.c b/mm/madvise.c +index 539eeb96b323..a402f8fdc68e 100644 +--- a/mm/madvise.c ++++ b/mm/madvise.c +@@ -195,7 +195,7 @@ static void force_shm_swapin_readahead(struct vm_area_struct *vma, + for (; start < end; start += PAGE_SIZE) { + index = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; + +- page = find_get_page(mapping, index); ++ page = find_get_entry(mapping, index); + if (!radix_tree_exceptional_entry(page)) { + if (page) + page_cache_release(page); +diff --git a/mm/memory-failure.c b/mm/memory-failure.c +index 33365e9ce6a7..a98c7fce470a 100644 +--- a/mm/memory-failure.c ++++ b/mm/memory-failure.c +@@ -1540,7 +1540,7 @@ static int soft_offline_huge_page(struct page *page, int flags) + + /* Keep page count to indicate a given hugepage is isolated. */ + list_move(&hpage->lru, &pagelist); +- ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, ++ ret = migrate_pages(&pagelist, new_page, NULL, MPOL_MF_MOVE_ALL, + MIGRATE_SYNC, MR_MEMORY_FAILURE); + if (ret) { + pr_info("soft offline: %#lx: migration failed %d, type %lx\n", +@@ -1621,7 +1621,7 @@ static int __soft_offline_page(struct page *page, int flags) + inc_zone_page_state(page, NR_ISOLATED_ANON + + page_is_file_cache(page)); + list_add(&page->lru, &pagelist); +- ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, ++ ret = migrate_pages(&pagelist, new_page, NULL, MPOL_MF_MOVE_ALL, + MIGRATE_SYNC, MR_MEMORY_FAILURE); + if (ret) { + if (!list_empty(&pagelist)) { +diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c +index a650db29606f..f6f23833de44 100644 +--- a/mm/memory_hotplug.c ++++ b/mm/memory_hotplug.c +@@ -1332,7 +1332,7 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) + * alloc_migrate_target should be improooooved!! + * migrate_pages returns # of failed pages. + */ +- ret = migrate_pages(&source, alloc_migrate_target, 0, ++ ret = migrate_pages(&source, alloc_migrate_target, NULL, 0, + MIGRATE_SYNC, MR_MEMORY_HOTPLUG); + if (ret) + putback_movable_pages(&source); +diff --git a/mm/mempolicy.c b/mm/mempolicy.c +index 796c7e6cf93b..e8fff0fa1202 100644 +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -1060,7 +1060,7 @@ static int migrate_to_node(struct mm_struct *mm, int source, int dest, + flags | MPOL_MF_DISCONTIG_OK, &pagelist); + + if (!list_empty(&pagelist)) { +- err = migrate_pages(&pagelist, new_node_page, dest, ++ err = migrate_pages(&pagelist, new_node_page, NULL, dest, + MIGRATE_SYNC, MR_SYSCALL); + if (err) + putback_movable_pages(&pagelist); +@@ -1306,7 +1306,7 @@ static long do_mbind(unsigned long start, unsigned long len, + + if (!list_empty(&pagelist)) { + WARN_ON_ONCE(flags & MPOL_MF_LAZY); +- nr_failed = migrate_pages(&pagelist, new_page, ++ nr_failed = migrate_pages(&pagelist, new_page, NULL, + start, MIGRATE_SYNC, MR_MEMPOLICY_MBIND); + if (nr_failed) + putback_movable_pages(&pagelist); +diff --git a/mm/migrate.c b/mm/migrate.c +index 13f47fbe3550..3acac4a62c4b 100644 +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -941,8 +941,9 @@ out: + * Obtain the lock on page, remove all ptes and migrate the page + * to the newly allocated page in newpage. + */ +-static int unmap_and_move(new_page_t get_new_page, unsigned long private, +- struct page *page, int force, enum migrate_mode mode) ++static int unmap_and_move(new_page_t get_new_page, free_page_t put_new_page, ++ unsigned long private, struct page *page, int force, ++ enum migrate_mode mode) + { + int rc = 0; + int *result = NULL; +@@ -986,11 +987,18 @@ out: + page_is_file_cache(page)); + putback_lru_page(page); + } ++ + /* +- * Move the new page to the LRU. If migration was not successful +- * then this will free the page. ++ * If migration was not successful and there's a freeing callback, use ++ * it. Otherwise, putback_lru_page() will drop the reference grabbed ++ * during isolation. + */ +- putback_lru_page(newpage); ++ if (rc != MIGRATEPAGE_SUCCESS && put_new_page) { ++ ClearPageSwapBacked(newpage); ++ put_new_page(newpage, private); ++ } else ++ putback_lru_page(newpage); ++ + if (result) { + if (rc) + *result = rc; +@@ -1019,8 +1027,9 @@ out: + * will wait in the page fault for migration to complete. + */ + static int unmap_and_move_huge_page(new_page_t get_new_page, +- unsigned long private, struct page *hpage, +- int force, enum migrate_mode mode) ++ free_page_t put_new_page, unsigned long private, ++ struct page *hpage, int force, ++ enum migrate_mode mode) + { + int rc = 0; + int *result = NULL; +@@ -1059,20 +1068,30 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, + if (!page_mapped(hpage)) + rc = move_to_new_page(new_hpage, hpage, 1, mode); + +- if (rc) ++ if (rc != MIGRATEPAGE_SUCCESS) + remove_migration_ptes(hpage, hpage); + + if (anon_vma) + put_anon_vma(anon_vma); + +- if (!rc) ++ if (rc == MIGRATEPAGE_SUCCESS) + hugetlb_cgroup_migrate(hpage, new_hpage); + + unlock_page(hpage); + out: + if (rc != -EAGAIN) + putback_active_hugepage(hpage); +- put_page(new_hpage); ++ ++ /* ++ * If migration was not successful and there's a freeing callback, use ++ * it. Otherwise, put_page() will drop the reference grabbed during ++ * isolation. ++ */ ++ if (rc != MIGRATEPAGE_SUCCESS && put_new_page) ++ put_new_page(new_hpage, private); ++ else ++ put_page(new_hpage); ++ + if (result) { + if (rc) + *result = rc; +@@ -1089,6 +1108,8 @@ out: + * @from: The list of pages to be migrated. + * @get_new_page: The function used to allocate free pages to be used + * as the target of the page migration. ++ * @put_new_page: The function used to free target pages if migration ++ * fails, or NULL if no special handling is necessary. + * @private: Private data to be passed on to get_new_page() + * @mode: The migration mode that specifies the constraints for + * page migration, if any. +@@ -1102,7 +1123,8 @@ out: + * Returns the number of pages that were not migrated, or an error code. + */ + int migrate_pages(struct list_head *from, new_page_t get_new_page, +- unsigned long private, enum migrate_mode mode, int reason) ++ free_page_t put_new_page, unsigned long private, ++ enum migrate_mode mode, int reason) + { + int retry = 1; + int nr_failed = 0; +@@ -1124,10 +1146,11 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, + + if (PageHuge(page)) + rc = unmap_and_move_huge_page(get_new_page, +- private, page, pass > 2, mode); ++ put_new_page, private, page, ++ pass > 2, mode); + else +- rc = unmap_and_move(get_new_page, private, +- page, pass > 2, mode); ++ rc = unmap_and_move(get_new_page, put_new_page, ++ private, page, pass > 2, mode); + + switch(rc) { + case -ENOMEM: +@@ -1276,7 +1299,7 @@ set_status: + + err = 0; + if (!list_empty(&pagelist)) { +- err = migrate_pages(&pagelist, new_page_node, ++ err = migrate_pages(&pagelist, new_page_node, NULL, + (unsigned long)pm, MIGRATE_SYNC, MR_SYSCALL); + if (err) + putback_movable_pages(&pagelist); +@@ -1732,7 +1755,8 @@ int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma, + + list_add(&page->lru, &migratepages); + nr_remaining = migrate_pages(&migratepages, alloc_misplaced_dst_page, +- node, MIGRATE_ASYNC, MR_NUMA_MISPLACED); ++ NULL, node, MIGRATE_ASYNC, ++ MR_NUMA_MISPLACED); + if (nr_remaining) { + if (!list_empty(&migratepages)) { + list_del(&page->lru); +diff --git a/mm/mincore.c b/mm/mincore.c +index 101623378fbf..725c80961048 100644 +--- a/mm/mincore.c ++++ b/mm/mincore.c +@@ -70,13 +70,21 @@ static unsigned char mincore_page(struct address_space *mapping, pgoff_t pgoff) + * any other file mapping (ie. marked !present and faulted in with + * tmpfs's .fault). So swapped out tmpfs mappings are tested here. + */ +- page = find_get_page(mapping, pgoff); + #ifdef CONFIG_SWAP +- /* shmem/tmpfs may return swap: account for swapcache page too. */ +- if (radix_tree_exceptional_entry(page)) { +- swp_entry_t swap = radix_to_swp_entry(page); +- page = find_get_page(swap_address_space(swap), swap.val); +- } ++ if (shmem_mapping(mapping)) { ++ page = find_get_entry(mapping, pgoff); ++ /* ++ * shmem/tmpfs may return swap: account for swapcache ++ * page too. ++ */ ++ if (radix_tree_exceptional_entry(page)) { ++ swp_entry_t swp = radix_to_swp_entry(page); ++ page = find_get_page(swap_address_space(swp), swp.val); ++ } ++ } else ++ page = find_get_page(mapping, pgoff); ++#else ++ page = find_get_page(mapping, pgoff); + #endif + if (page) { + present = PageUptodate(page); +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 7b2611a055a7..4b258297cc7c 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -943,6 +943,7 @@ struct page *__rmqueue_smallest(struct zone *zone, unsigned int order, + rmv_page_order(page); + area->nr_free--; + expand(zone, page, order, current_order, area, migratetype); ++ set_freepage_migratetype(page, migratetype); + return page; + } + +@@ -1069,7 +1070,9 @@ static int try_to_steal_freepages(struct zone *zone, struct page *page, + + /* + * When borrowing from MIGRATE_CMA, we need to release the excess +- * buddy pages to CMA itself. ++ * buddy pages to CMA itself. We also ensure the freepage_migratetype ++ * is set to CMA so it is returned to the correct freelist in case ++ * the page ends up being not actually allocated from the pcp lists. + */ + if (is_migrate_cma(fallback_type)) + return fallback_type; +@@ -1137,6 +1140,12 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype) + + expand(zone, page, order, current_order, area, + new_type); ++ /* The freepage_migratetype may differ from pageblock's ++ * migratetype depending on the decisions in ++ * try_to_steal_freepages. This is OK as long as it does ++ * not differ for MIGRATE_CMA type. ++ */ ++ set_freepage_migratetype(page, new_type); + + trace_mm_page_alloc_extfrag(page, order, current_order, + start_migratetype, migratetype, new_type); +@@ -1187,7 +1196,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, + unsigned long count, struct list_head *list, + int migratetype, int cold) + { +- int mt = migratetype, i; ++ int i; + + spin_lock(&zone->lock); + for (i = 0; i < count; ++i) { +@@ -1208,14 +1217,8 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, + list_add(&page->lru, list); + else + list_add_tail(&page->lru, list); +- if (IS_ENABLED(CONFIG_CMA)) { +- mt = get_pageblock_migratetype(page); +- if (!is_migrate_cma(mt) && !is_migrate_isolate(mt)) +- mt = migratetype; +- } +- set_freepage_migratetype(page, mt); + list = &page->lru; +- if (is_migrate_cma(mt)) ++ if (is_migrate_cma(get_freepage_migratetype(page))) + __mod_zone_page_state(zone, NR_FREE_CMA_PAGES, + -(1 << order)); + } +@@ -1584,7 +1587,7 @@ again: + if (!page) + goto failed; + __mod_zone_freepage_state(zone, -(1 << order), +- get_pageblock_migratetype(page)); ++ get_freepage_migratetype(page)); + } + + __mod_zone_page_state(zone, NR_ALLOC_BATCH, -(1 << order)); +@@ -2246,7 +2249,7 @@ static struct page * + __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, enum zone_type high_zoneidx, + nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone, +- int migratetype, bool sync_migration, ++ int migratetype, enum migrate_mode mode, + bool *contended_compaction, bool *deferred_compaction, + unsigned long *did_some_progress) + { +@@ -2260,7 +2263,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, + + current->flags |= PF_MEMALLOC; + *did_some_progress = try_to_compact_pages(zonelist, order, gfp_mask, +- nodemask, sync_migration, ++ nodemask, mode, + contended_compaction); + current->flags &= ~PF_MEMALLOC; + +@@ -2293,7 +2296,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, + * As async compaction considers a subset of pageblocks, only + * defer if the failure was a sync compaction failure. + */ +- if (sync_migration) ++ if (mode != MIGRATE_ASYNC) + defer_compaction(preferred_zone, order); + + cond_resched(); +@@ -2306,9 +2309,8 @@ static inline struct page * + __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, enum zone_type high_zoneidx, + nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone, +- int migratetype, bool sync_migration, +- bool *contended_compaction, bool *deferred_compaction, +- unsigned long *did_some_progress) ++ int migratetype, enum migrate_mode mode, bool *contended_compaction, ++ bool *deferred_compaction, unsigned long *did_some_progress) + { + return NULL; + } +@@ -2503,7 +2505,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, + int alloc_flags; + unsigned long pages_reclaimed = 0; + unsigned long did_some_progress; +- bool sync_migration = false; ++ enum migrate_mode migration_mode = MIGRATE_ASYNC; + bool deferred_compaction = false; + bool contended_compaction = false; + +@@ -2597,17 +2599,15 @@ rebalance: + * Try direct compaction. The first pass is asynchronous. Subsequent + * attempts after direct reclaim are synchronous + */ +- page = __alloc_pages_direct_compact(gfp_mask, order, +- zonelist, high_zoneidx, +- nodemask, +- alloc_flags, preferred_zone, +- migratetype, sync_migration, +- &contended_compaction, ++ page = __alloc_pages_direct_compact(gfp_mask, order, zonelist, ++ high_zoneidx, nodemask, alloc_flags, ++ preferred_zone, migratetype, ++ migration_mode, &contended_compaction, + &deferred_compaction, + &did_some_progress); + if (page) + goto got_pg; +- sync_migration = true; ++ migration_mode = MIGRATE_SYNC_LIGHT; + + /* + * If compaction is deferred for high-order allocations, it is because +@@ -2682,12 +2682,10 @@ rebalance: + * direct reclaim and reclaim/compaction depends on compaction + * being called after reclaim so call directly if necessary + */ +- page = __alloc_pages_direct_compact(gfp_mask, order, +- zonelist, high_zoneidx, +- nodemask, +- alloc_flags, preferred_zone, +- migratetype, sync_migration, +- &contended_compaction, ++ page = __alloc_pages_direct_compact(gfp_mask, order, zonelist, ++ high_zoneidx, nodemask, alloc_flags, ++ preferred_zone, migratetype, ++ migration_mode, &contended_compaction, + &deferred_compaction, + &did_some_progress); + if (page) +@@ -6261,7 +6259,7 @@ static int __alloc_contig_migrate_range(struct compact_control *cc, + cc->nr_migratepages -= nr_reclaimed; + + ret = migrate_pages(&cc->migratepages, alloc_migrate_target, +- 0, MIGRATE_SYNC, MR_CMA); ++ NULL, 0, cc->mode, MR_CMA); + } + if (ret < 0) { + putback_movable_pages(&cc->migratepages); +@@ -6300,7 +6298,7 @@ int alloc_contig_range(unsigned long start, unsigned long end, + .nr_migratepages = 0, + .order = -1, + .zone = page_zone(pfn_to_page(start)), +- .sync = true, ++ .mode = MIGRATE_SYNC, + .ignore_skip_hint = true, + }; + INIT_LIST_HEAD(&cc.migratepages); +diff --git a/mm/readahead.c b/mm/readahead.c +index 1fa0d6fca556..0ca36a7770b1 100644 +--- a/mm/readahead.c ++++ b/mm/readahead.c +@@ -8,9 +8,7 @@ + */ + + #include +-#include + #include +-#include + #include + #include + #include +@@ -20,6 +18,8 @@ + #include + #include + ++#include "internal.h" ++ + /* + * Initialise a struct file's readahead state. Assumes that the caller has + * memset *ra to zero. +@@ -149,8 +149,7 @@ out: + * + * Returns the number of pages requested, or the maximum amount of I/O allowed. + */ +-static int +-__do_page_cache_readahead(struct address_space *mapping, struct file *filp, ++int __do_page_cache_readahead(struct address_space *mapping, struct file *filp, + pgoff_t offset, unsigned long nr_to_read, + unsigned long lookahead_size) + { +@@ -179,7 +178,7 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp, + rcu_read_lock(); + page = radix_tree_lookup(&mapping->page_tree, page_offset); + rcu_read_unlock(); +- if (page) ++ if (page && !radix_tree_exceptional_entry(page)) + continue; + + page = page_cache_alloc_readahead(mapping); +@@ -244,20 +243,6 @@ unsigned long max_sane_readahead(unsigned long nr) + } + + /* +- * Submit IO for the read-ahead request in file_ra_state. +- */ +-unsigned long ra_submit(struct file_ra_state *ra, +- struct address_space *mapping, struct file *filp) +-{ +- int actual; +- +- actual = __do_page_cache_readahead(mapping, filp, +- ra->start, ra->size, ra->async_size); +- +- return actual; +-} +- +-/* + * Set the initial window size, round to next power of 2 and square + * for small size, x 4 for medium, and x 2 for large + * for 128k (32 page) max ra +@@ -347,7 +332,7 @@ static pgoff_t count_history_pages(struct address_space *mapping, + pgoff_t head; + + rcu_read_lock(); +- head = radix_tree_prev_hole(&mapping->page_tree, offset - 1, max); ++ head = page_cache_prev_hole(mapping, offset - 1, max); + rcu_read_unlock(); + + return offset - 1 - head; +@@ -427,7 +412,7 @@ ondemand_readahead(struct address_space *mapping, + pgoff_t start; + + rcu_read_lock(); +- start = radix_tree_next_hole(&mapping->page_tree, offset+1,max); ++ start = page_cache_next_hole(mapping, offset + 1, max); + rcu_read_unlock(); + + if (!start || start - offset > max) +diff --git a/mm/shmem.c b/mm/shmem.c +index f0d698ba7d0f..0f1447563f17 100644 +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -243,19 +243,17 @@ static int shmem_radix_tree_replace(struct address_space *mapping, + pgoff_t index, void *expected, void *replacement) + { + void **pslot; +- void *item = NULL; ++ void *item; + + VM_BUG_ON(!expected); ++ VM_BUG_ON(!replacement); + pslot = radix_tree_lookup_slot(&mapping->page_tree, index); +- if (pslot) +- item = radix_tree_deref_slot_protected(pslot, +- &mapping->tree_lock); ++ if (!pslot) ++ return -ENOENT; ++ item = radix_tree_deref_slot_protected(pslot, &mapping->tree_lock); + if (item != expected) + return -ENOENT; +- if (replacement) +- radix_tree_replace_slot(pslot, replacement); +- else +- radix_tree_delete(&mapping->page_tree, index); ++ radix_tree_replace_slot(pslot, replacement); + return 0; + } + +@@ -332,84 +330,20 @@ static void shmem_delete_from_page_cache(struct page *page, void *radswap) + } + + /* +- * Like find_get_pages, but collecting swap entries as well as pages. +- */ +-static unsigned shmem_find_get_pages_and_swap(struct address_space *mapping, +- pgoff_t start, unsigned int nr_pages, +- struct page **pages, pgoff_t *indices) +-{ +- void **slot; +- unsigned int ret = 0; +- struct radix_tree_iter iter; +- +- if (!nr_pages) +- return 0; +- +- rcu_read_lock(); +-restart: +- radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) { +- struct page *page; +-repeat: +- page = radix_tree_deref_slot(slot); +- if (unlikely(!page)) +- continue; +- if (radix_tree_exception(page)) { +- if (radix_tree_deref_retry(page)) +- goto restart; +- /* +- * Otherwise, we must be storing a swap entry +- * here as an exceptional entry: so return it +- * without attempting to raise page count. +- */ +- goto export; +- } +- if (!page_cache_get_speculative(page)) +- goto repeat; +- +- /* Has the page moved? */ +- if (unlikely(page != *slot)) { +- page_cache_release(page); +- goto repeat; +- } +-export: +- indices[ret] = iter.index; +- pages[ret] = page; +- if (++ret == nr_pages) +- break; +- } +- rcu_read_unlock(); +- return ret; +-} +- +-/* + * Remove swap entry from radix tree, free the swap and its page cache. + */ + static int shmem_free_swap(struct address_space *mapping, + pgoff_t index, void *radswap) + { +- int error; ++ void *old; + + spin_lock_irq(&mapping->tree_lock); +- error = shmem_radix_tree_replace(mapping, index, radswap, NULL); ++ old = radix_tree_delete_item(&mapping->page_tree, index, radswap); + spin_unlock_irq(&mapping->tree_lock); +- if (!error) +- free_swap_and_cache(radix_to_swp_entry(radswap)); +- return error; +-} +- +-/* +- * Pagevec may contain swap entries, so shuffle up pages before releasing. +- */ +-static void shmem_deswap_pagevec(struct pagevec *pvec) +-{ +- int i, j; +- +- for (i = 0, j = 0; i < pagevec_count(pvec); i++) { +- struct page *page = pvec->pages[i]; +- if (!radix_tree_exceptional_entry(page)) +- pvec->pages[j++] = page; +- } +- pvec->nr = j; ++ if (old != radswap) ++ return -ENOENT; ++ free_swap_and_cache(radix_to_swp_entry(radswap)); ++ return 0; + } + + /* +@@ -430,12 +364,12 @@ void shmem_unlock_mapping(struct address_space *mapping) + * Avoid pagevec_lookup(): find_get_pages() returns 0 as if it + * has finished, if it hits a row of PAGEVEC_SIZE swap entries. + */ +- pvec.nr = shmem_find_get_pages_and_swap(mapping, index, +- PAGEVEC_SIZE, pvec.pages, indices); ++ pvec.nr = find_get_entries(mapping, index, ++ PAGEVEC_SIZE, pvec.pages, indices); + if (!pvec.nr) + break; + index = indices[pvec.nr - 1] + 1; +- shmem_deswap_pagevec(&pvec); ++ pagevec_remove_exceptionals(&pvec); + check_move_unevictable_pages(pvec.pages, pvec.nr); + pagevec_release(&pvec); + cond_resched(); +@@ -467,9 +401,9 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, + pagevec_init(&pvec, 0); + index = start; + while (index < end) { +- pvec.nr = shmem_find_get_pages_and_swap(mapping, index, +- min(end - index, (pgoff_t)PAGEVEC_SIZE), +- pvec.pages, indices); ++ pvec.nr = find_get_entries(mapping, index, ++ min(end - index, (pgoff_t)PAGEVEC_SIZE), ++ pvec.pages, indices); + if (!pvec.nr) + break; + mem_cgroup_uncharge_start(); +@@ -498,7 +432,7 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, + } + unlock_page(page); + } +- shmem_deswap_pagevec(&pvec); ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + mem_cgroup_uncharge_end(); + cond_resched(); +@@ -536,9 +470,10 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, + index = start; + while (index < end) { + cond_resched(); +- pvec.nr = shmem_find_get_pages_and_swap(mapping, index, ++ ++ pvec.nr = find_get_entries(mapping, index, + min(end - index, (pgoff_t)PAGEVEC_SIZE), +- pvec.pages, indices); ++ pvec.pages, indices); + if (!pvec.nr) { + /* If all gone or hole-punch or unfalloc, we're done */ + if (index == start || end != -1) +@@ -581,7 +516,7 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, + } + unlock_page(page); + } +- shmem_deswap_pagevec(&pvec); ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + mem_cgroup_uncharge_end(); + index++; +@@ -1088,7 +1023,7 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index, + return -EFBIG; + repeat: + swap.val = 0; +- page = find_lock_page(mapping, index); ++ page = find_lock_entry(mapping, index); + if (radix_tree_exceptional_entry(page)) { + swap = radix_to_swp_entry(page); + page = NULL; +@@ -1483,6 +1418,11 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode + return inode; + } + ++bool shmem_mapping(struct address_space *mapping) ++{ ++ return mapping->backing_dev_info == &shmem_backing_dev_info; ++} ++ + #ifdef CONFIG_TMPFS + static const struct inode_operations shmem_symlink_inode_operations; + static const struct inode_operations shmem_short_symlink_operations; +@@ -1795,7 +1735,7 @@ static pgoff_t shmem_seek_hole_data(struct address_space *mapping, + pagevec_init(&pvec, 0); + pvec.nr = 1; /* start small: we may be there already */ + while (!done) { +- pvec.nr = shmem_find_get_pages_and_swap(mapping, index, ++ pvec.nr = find_get_entries(mapping, index, + pvec.nr, pvec.pages, indices); + if (!pvec.nr) { + if (whence == SEEK_DATA) +@@ -1822,7 +1762,7 @@ static pgoff_t shmem_seek_hole_data(struct address_space *mapping, + break; + } + } +- shmem_deswap_pagevec(&pvec); ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + pvec.nr = PAGEVEC_SIZE; + cond_resched(); +diff --git a/mm/swap.c b/mm/swap.c +index 0092097b3f4c..c8048d71c642 100644 +--- a/mm/swap.c ++++ b/mm/swap.c +@@ -948,6 +948,57 @@ void __pagevec_lru_add(struct pagevec *pvec) + EXPORT_SYMBOL(__pagevec_lru_add); + + /** ++ * pagevec_lookup_entries - gang pagecache lookup ++ * @pvec: Where the resulting entries are placed ++ * @mapping: The address_space to search ++ * @start: The starting entry index ++ * @nr_entries: The maximum number of entries ++ * @indices: The cache indices corresponding to the entries in @pvec ++ * ++ * pagevec_lookup_entries() will search for and return a group of up ++ * to @nr_entries pages and shadow entries in the mapping. All ++ * entries are placed in @pvec. pagevec_lookup_entries() takes a ++ * reference against actual pages in @pvec. ++ * ++ * The search returns a group of mapping-contiguous entries with ++ * ascending indexes. There may be holes in the indices due to ++ * not-present entries. ++ * ++ * pagevec_lookup_entries() returns the number of entries which were ++ * found. ++ */ ++unsigned pagevec_lookup_entries(struct pagevec *pvec, ++ struct address_space *mapping, ++ pgoff_t start, unsigned nr_pages, ++ pgoff_t *indices) ++{ ++ pvec->nr = find_get_entries(mapping, start, nr_pages, ++ pvec->pages, indices); ++ return pagevec_count(pvec); ++} ++ ++/** ++ * pagevec_remove_exceptionals - pagevec exceptionals pruning ++ * @pvec: The pagevec to prune ++ * ++ * pagevec_lookup_entries() fills both pages and exceptional radix ++ * tree entries into the pagevec. This function prunes all ++ * exceptionals from @pvec without leaving holes, so that it can be ++ * passed on to page-only pagevec operations. ++ */ ++void pagevec_remove_exceptionals(struct pagevec *pvec) ++{ ++ int i, j; ++ ++ for (i = 0, j = 0; i < pagevec_count(pvec); i++) { ++ struct page *page = pvec->pages[i]; ++ if (!radix_tree_exceptional_entry(page)) ++ pvec->pages[j++] = page; ++ } ++ pvec->nr = j; ++} ++ ++/** + * pagevec_lookup - gang pagecache lookup + * @pvec: Where the resulting pages are placed + * @mapping: The address_space to search +diff --git a/mm/truncate.c b/mm/truncate.c +index ac18edc30649..827ad8d2b5cd 100644 +--- a/mm/truncate.c ++++ b/mm/truncate.c +@@ -23,6 +23,22 @@ + #include + #include "internal.h" + ++static void clear_exceptional_entry(struct address_space *mapping, ++ pgoff_t index, void *entry) ++{ ++ /* Handled by shmem itself */ ++ if (shmem_mapping(mapping)) ++ return; ++ ++ spin_lock_irq(&mapping->tree_lock); ++ /* ++ * Regular page slots are stabilized by the page lock even ++ * without the tree itself locked. These unlocked entries ++ * need verification under the tree lock. ++ */ ++ radix_tree_delete_item(&mapping->page_tree, index, entry); ++ spin_unlock_irq(&mapping->tree_lock); ++} + + /** + * do_invalidatepage - invalidate part or all of a page +@@ -209,6 +225,7 @@ void truncate_inode_pages_range(struct address_space *mapping, + unsigned int partial_start; /* inclusive */ + unsigned int partial_end; /* exclusive */ + struct pagevec pvec; ++ pgoff_t indices[PAGEVEC_SIZE]; + pgoff_t index; + int i; + +@@ -239,17 +256,23 @@ void truncate_inode_pages_range(struct address_space *mapping, + + pagevec_init(&pvec, 0); + index = start; +- while (index < end && pagevec_lookup(&pvec, mapping, index, +- min(end - index, (pgoff_t)PAGEVEC_SIZE))) { ++ while (index < end && pagevec_lookup_entries(&pvec, mapping, index, ++ min(end - index, (pgoff_t)PAGEVEC_SIZE), ++ indices)) { + mem_cgroup_uncharge_start(); + for (i = 0; i < pagevec_count(&pvec); i++) { + struct page *page = pvec.pages[i]; + + /* We rely upon deletion not changing page->index */ +- index = page->index; ++ index = indices[i]; + if (index >= end) + break; + ++ if (radix_tree_exceptional_entry(page)) { ++ clear_exceptional_entry(mapping, index, page); ++ continue; ++ } ++ + if (!trylock_page(page)) + continue; + WARN_ON(page->index != index); +@@ -260,6 +283,7 @@ void truncate_inode_pages_range(struct address_space *mapping, + truncate_inode_page(mapping, page); + unlock_page(page); + } ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + mem_cgroup_uncharge_end(); + cond_resched(); +@@ -308,14 +332,16 @@ void truncate_inode_pages_range(struct address_space *mapping, + index = start; + for ( ; ; ) { + cond_resched(); +- if (!pagevec_lookup(&pvec, mapping, index, +- min(end - index, (pgoff_t)PAGEVEC_SIZE))) { ++ if (!pagevec_lookup_entries(&pvec, mapping, index, ++ min(end - index, (pgoff_t)PAGEVEC_SIZE), ++ indices)) { + if (index == start) + break; + index = start; + continue; + } +- if (index == start && pvec.pages[0]->index >= end) { ++ if (index == start && indices[0] >= end) { ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + break; + } +@@ -324,16 +350,22 @@ void truncate_inode_pages_range(struct address_space *mapping, + struct page *page = pvec.pages[i]; + + /* We rely upon deletion not changing page->index */ +- index = page->index; ++ index = indices[i]; + if (index >= end) + break; + ++ if (radix_tree_exceptional_entry(page)) { ++ clear_exceptional_entry(mapping, index, page); ++ continue; ++ } ++ + lock_page(page); + WARN_ON(page->index != index); + wait_on_page_writeback(page); + truncate_inode_page(mapping, page); + unlock_page(page); + } ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + mem_cgroup_uncharge_end(); + index++; +@@ -376,6 +408,7 @@ EXPORT_SYMBOL(truncate_inode_pages); + unsigned long invalidate_mapping_pages(struct address_space *mapping, + pgoff_t start, pgoff_t end) + { ++ pgoff_t indices[PAGEVEC_SIZE]; + struct pagevec pvec; + pgoff_t index = start; + unsigned long ret; +@@ -391,17 +424,23 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping, + */ + + pagevec_init(&pvec, 0); +- while (index <= end && pagevec_lookup(&pvec, mapping, index, +- min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) { ++ while (index <= end && pagevec_lookup_entries(&pvec, mapping, index, ++ min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1, ++ indices)) { + mem_cgroup_uncharge_start(); + for (i = 0; i < pagevec_count(&pvec); i++) { + struct page *page = pvec.pages[i]; + + /* We rely upon deletion not changing page->index */ +- index = page->index; ++ index = indices[i]; + if (index > end) + break; + ++ if (radix_tree_exceptional_entry(page)) { ++ clear_exceptional_entry(mapping, index, page); ++ continue; ++ } ++ + if (!trylock_page(page)) + continue; + WARN_ON(page->index != index); +@@ -415,6 +454,7 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping, + deactivate_page(page); + count += ret; + } ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + mem_cgroup_uncharge_end(); + cond_resched(); +@@ -482,6 +522,7 @@ static int do_launder_page(struct address_space *mapping, struct page *page) + int invalidate_inode_pages2_range(struct address_space *mapping, + pgoff_t start, pgoff_t end) + { ++ pgoff_t indices[PAGEVEC_SIZE]; + struct pagevec pvec; + pgoff_t index; + int i; +@@ -492,17 +533,23 @@ int invalidate_inode_pages2_range(struct address_space *mapping, + cleancache_invalidate_inode(mapping); + pagevec_init(&pvec, 0); + index = start; +- while (index <= end && pagevec_lookup(&pvec, mapping, index, +- min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) { ++ while (index <= end && pagevec_lookup_entries(&pvec, mapping, index, ++ min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1, ++ indices)) { + mem_cgroup_uncharge_start(); + for (i = 0; i < pagevec_count(&pvec); i++) { + struct page *page = pvec.pages[i]; + + /* We rely upon deletion not changing page->index */ +- index = page->index; ++ index = indices[i]; + if (index > end) + break; + ++ if (radix_tree_exceptional_entry(page)) { ++ clear_exceptional_entry(mapping, index, page); ++ continue; ++ } ++ + lock_page(page); + WARN_ON(page->index != index); + if (page->mapping != mapping) { +@@ -540,6 +587,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping, + ret = ret2; + unlock_page(page); + } ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + mem_cgroup_uncharge_end(); + cond_resched(); +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 0c0b36e5b4f8..deb139e6b8ed 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -2018,13 +2018,27 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) + unsigned long nr_reclaimed = 0; + unsigned long nr_to_reclaim = sc->nr_to_reclaim; + struct blk_plug plug; +- bool scan_adjusted = false; ++ bool scan_adjusted; + + get_scan_count(lruvec, sc, nr); + + /* Record the original scan target for proportional adjustments later */ + memcpy(targets, nr, sizeof(nr)); + ++ /* ++ * Global reclaiming within direct reclaim at DEF_PRIORITY is a normal ++ * event that can occur when there is little memory pressure e.g. ++ * multiple streaming readers/writers. Hence, we do not abort scanning ++ * when the requested number of pages are reclaimed when scanning at ++ * DEF_PRIORITY on the assumption that the fact we are direct ++ * reclaiming implies that kswapd is not keeping up and it is best to ++ * do a batch of work at once. For memcg reclaim one check is made to ++ * abort proportional reclaim if either the file or anon lru has already ++ * dropped to zero at the first pass. ++ */ ++ scan_adjusted = (global_reclaim(sc) && !current_is_kswapd() && ++ sc->priority == DEF_PRIORITY); ++ + blk_start_plug(&plug); + while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] || + nr[LRU_INACTIVE_FILE]) { +@@ -2045,17 +2059,8 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) + continue; + + /* +- * For global direct reclaim, reclaim only the number of pages +- * requested. Less care is taken to scan proportionally as it +- * is more important to minimise direct reclaim stall latency +- * than it is to properly age the LRU lists. +- */ +- if (global_reclaim(sc) && !current_is_kswapd()) +- break; +- +- /* + * For kswapd and memcg, reclaim at least the number of pages +- * requested. Ensure that the anon and file LRUs shrink ++ * requested. Ensure that the anon and file LRUs are scanned + * proportionally what was requested by get_scan_count(). We + * stop reclaiming one LRU and reduce the amount scanning + * proportional to the original scan target. +@@ -2063,6 +2068,15 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) + nr_file = nr[LRU_INACTIVE_FILE] + nr[LRU_ACTIVE_FILE]; + nr_anon = nr[LRU_INACTIVE_ANON] + nr[LRU_ACTIVE_ANON]; + ++ /* ++ * It's just vindictive to attack the larger once the smaller ++ * has gone to zero. And given the way we stop scanning the ++ * smaller below, this makes sure that we only make one nudge ++ * towards proportionality once we've got nr_to_reclaim. ++ */ ++ if (!nr_file || !nr_anon) ++ break; ++ + if (nr_file > nr_anon) { + unsigned long scan_target = targets[LRU_INACTIVE_ANON] + + targets[LRU_ACTIVE_ANON] + 1; +diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c +index 6e7a236525b6..06f19b9e159a 100644 +--- a/net/ceph/crypto.c ++++ b/net/ceph/crypto.c +@@ -89,11 +89,82 @@ static struct crypto_blkcipher *ceph_crypto_alloc_cipher(void) + + static const u8 *aes_iv = (u8 *)CEPH_AES_IV; + ++/* ++ * Should be used for buffers allocated with ceph_kvmalloc(). ++ * Currently these are encrypt out-buffer (ceph_buffer) and decrypt ++ * in-buffer (msg front). ++ * ++ * Dispose of @sgt with teardown_sgtable(). ++ * ++ * @prealloc_sg is to avoid memory allocation inside sg_alloc_table() ++ * in cases where a single sg is sufficient. No attempt to reduce the ++ * number of sgs by squeezing physically contiguous pages together is ++ * made though, for simplicity. ++ */ ++static int setup_sgtable(struct sg_table *sgt, struct scatterlist *prealloc_sg, ++ const void *buf, unsigned int buf_len) ++{ ++ struct scatterlist *sg; ++ const bool is_vmalloc = is_vmalloc_addr(buf); ++ unsigned int off = offset_in_page(buf); ++ unsigned int chunk_cnt = 1; ++ unsigned int chunk_len = PAGE_ALIGN(off + buf_len); ++ int i; ++ int ret; ++ ++ if (buf_len == 0) { ++ memset(sgt, 0, sizeof(*sgt)); ++ return -EINVAL; ++ } ++ ++ if (is_vmalloc) { ++ chunk_cnt = chunk_len >> PAGE_SHIFT; ++ chunk_len = PAGE_SIZE; ++ } ++ ++ if (chunk_cnt > 1) { ++ ret = sg_alloc_table(sgt, chunk_cnt, GFP_NOFS); ++ if (ret) ++ return ret; ++ } else { ++ WARN_ON(chunk_cnt != 1); ++ sg_init_table(prealloc_sg, 1); ++ sgt->sgl = prealloc_sg; ++ sgt->nents = sgt->orig_nents = 1; ++ } ++ ++ for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) { ++ struct page *page; ++ unsigned int len = min(chunk_len - off, buf_len); ++ ++ if (is_vmalloc) ++ page = vmalloc_to_page(buf); ++ else ++ page = virt_to_page(buf); ++ ++ sg_set_page(sg, page, len, off); ++ ++ off = 0; ++ buf += len; ++ buf_len -= len; ++ } ++ WARN_ON(buf_len != 0); ++ ++ return 0; ++} ++ ++static void teardown_sgtable(struct sg_table *sgt) ++{ ++ if (sgt->orig_nents > 1) ++ sg_free_table(sgt); ++} ++ + static int ceph_aes_encrypt(const void *key, int key_len, + void *dst, size_t *dst_len, + const void *src, size_t src_len) + { +- struct scatterlist sg_in[2], sg_out[1]; ++ struct scatterlist sg_in[2], prealloc_sg; ++ struct sg_table sg_out; + struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); + struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 }; + int ret; +@@ -109,16 +180,18 @@ static int ceph_aes_encrypt(const void *key, int key_len, + + *dst_len = src_len + zero_padding; + +- crypto_blkcipher_setkey((void *)tfm, key, key_len); + sg_init_table(sg_in, 2); + sg_set_buf(&sg_in[0], src, src_len); + sg_set_buf(&sg_in[1], pad, zero_padding); +- sg_init_table(sg_out, 1); +- sg_set_buf(sg_out, dst, *dst_len); ++ ret = setup_sgtable(&sg_out, &prealloc_sg, dst, *dst_len); ++ if (ret) ++ goto out_tfm; ++ ++ crypto_blkcipher_setkey((void *)tfm, key, key_len); + iv = crypto_blkcipher_crt(tfm)->iv; + ivsize = crypto_blkcipher_ivsize(tfm); +- + memcpy(iv, aes_iv, ivsize); ++ + /* + print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1, + key, key_len, 1); +@@ -127,16 +200,22 @@ static int ceph_aes_encrypt(const void *key, int key_len, + print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1, + pad, zero_padding, 1); + */ +- ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in, ++ ret = crypto_blkcipher_encrypt(&desc, sg_out.sgl, sg_in, + src_len + zero_padding); +- crypto_free_blkcipher(tfm); +- if (ret < 0) ++ if (ret < 0) { + pr_err("ceph_aes_crypt failed %d\n", ret); ++ goto out_sg; ++ } + /* + print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1, + dst, *dst_len, 1); + */ +- return 0; ++ ++out_sg: ++ teardown_sgtable(&sg_out); ++out_tfm: ++ crypto_free_blkcipher(tfm); ++ return ret; + } + + static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, +@@ -144,7 +223,8 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, + const void *src1, size_t src1_len, + const void *src2, size_t src2_len) + { +- struct scatterlist sg_in[3], sg_out[1]; ++ struct scatterlist sg_in[3], prealloc_sg; ++ struct sg_table sg_out; + struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); + struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 }; + int ret; +@@ -160,17 +240,19 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, + + *dst_len = src1_len + src2_len + zero_padding; + +- crypto_blkcipher_setkey((void *)tfm, key, key_len); + sg_init_table(sg_in, 3); + sg_set_buf(&sg_in[0], src1, src1_len); + sg_set_buf(&sg_in[1], src2, src2_len); + sg_set_buf(&sg_in[2], pad, zero_padding); +- sg_init_table(sg_out, 1); +- sg_set_buf(sg_out, dst, *dst_len); ++ ret = setup_sgtable(&sg_out, &prealloc_sg, dst, *dst_len); ++ if (ret) ++ goto out_tfm; ++ ++ crypto_blkcipher_setkey((void *)tfm, key, key_len); + iv = crypto_blkcipher_crt(tfm)->iv; + ivsize = crypto_blkcipher_ivsize(tfm); +- + memcpy(iv, aes_iv, ivsize); ++ + /* + print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1, + key, key_len, 1); +@@ -181,23 +263,30 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, + print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1, + pad, zero_padding, 1); + */ +- ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in, ++ ret = crypto_blkcipher_encrypt(&desc, sg_out.sgl, sg_in, + src1_len + src2_len + zero_padding); +- crypto_free_blkcipher(tfm); +- if (ret < 0) ++ if (ret < 0) { + pr_err("ceph_aes_crypt2 failed %d\n", ret); ++ goto out_sg; ++ } + /* + print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1, + dst, *dst_len, 1); + */ +- return 0; ++ ++out_sg: ++ teardown_sgtable(&sg_out); ++out_tfm: ++ crypto_free_blkcipher(tfm); ++ return ret; + } + + static int ceph_aes_decrypt(const void *key, int key_len, + void *dst, size_t *dst_len, + const void *src, size_t src_len) + { +- struct scatterlist sg_in[1], sg_out[2]; ++ struct sg_table sg_in; ++ struct scatterlist sg_out[2], prealloc_sg; + struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); + struct blkcipher_desc desc = { .tfm = tfm }; + char pad[16]; +@@ -209,16 +298,16 @@ static int ceph_aes_decrypt(const void *key, int key_len, + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + +- crypto_blkcipher_setkey((void *)tfm, key, key_len); +- sg_init_table(sg_in, 1); + sg_init_table(sg_out, 2); +- sg_set_buf(sg_in, src, src_len); + sg_set_buf(&sg_out[0], dst, *dst_len); + sg_set_buf(&sg_out[1], pad, sizeof(pad)); ++ ret = setup_sgtable(&sg_in, &prealloc_sg, src, src_len); ++ if (ret) ++ goto out_tfm; + ++ crypto_blkcipher_setkey((void *)tfm, key, key_len); + iv = crypto_blkcipher_crt(tfm)->iv; + ivsize = crypto_blkcipher_ivsize(tfm); +- + memcpy(iv, aes_iv, ivsize); + + /* +@@ -227,12 +316,10 @@ static int ceph_aes_decrypt(const void *key, int key_len, + print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1, + src, src_len, 1); + */ +- +- ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len); +- crypto_free_blkcipher(tfm); ++ ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in.sgl, src_len); + if (ret < 0) { + pr_err("ceph_aes_decrypt failed %d\n", ret); +- return ret; ++ goto out_sg; + } + + if (src_len <= *dst_len) +@@ -250,7 +337,12 @@ static int ceph_aes_decrypt(const void *key, int key_len, + print_hex_dump(KERN_ERR, "dec out: ", DUMP_PREFIX_NONE, 16, 1, + dst, *dst_len, 1); + */ +- return 0; ++ ++out_sg: ++ teardown_sgtable(&sg_in); ++out_tfm: ++ crypto_free_blkcipher(tfm); ++ return ret; + } + + static int ceph_aes_decrypt2(const void *key, int key_len, +@@ -258,7 +350,8 @@ static int ceph_aes_decrypt2(const void *key, int key_len, + void *dst2, size_t *dst2_len, + const void *src, size_t src_len) + { +- struct scatterlist sg_in[1], sg_out[3]; ++ struct sg_table sg_in; ++ struct scatterlist sg_out[3], prealloc_sg; + struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); + struct blkcipher_desc desc = { .tfm = tfm }; + char pad[16]; +@@ -270,17 +363,17 @@ static int ceph_aes_decrypt2(const void *key, int key_len, + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + +- sg_init_table(sg_in, 1); +- sg_set_buf(sg_in, src, src_len); + sg_init_table(sg_out, 3); + sg_set_buf(&sg_out[0], dst1, *dst1_len); + sg_set_buf(&sg_out[1], dst2, *dst2_len); + sg_set_buf(&sg_out[2], pad, sizeof(pad)); ++ ret = setup_sgtable(&sg_in, &prealloc_sg, src, src_len); ++ if (ret) ++ goto out_tfm; + + crypto_blkcipher_setkey((void *)tfm, key, key_len); + iv = crypto_blkcipher_crt(tfm)->iv; + ivsize = crypto_blkcipher_ivsize(tfm); +- + memcpy(iv, aes_iv, ivsize); + + /* +@@ -289,12 +382,10 @@ static int ceph_aes_decrypt2(const void *key, int key_len, + print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1, + src, src_len, 1); + */ +- +- ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len); +- crypto_free_blkcipher(tfm); ++ ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in.sgl, src_len); + if (ret < 0) { + pr_err("ceph_aes_decrypt failed %d\n", ret); +- return ret; ++ goto out_sg; + } + + if (src_len <= *dst1_len) +@@ -324,7 +415,11 @@ static int ceph_aes_decrypt2(const void *key, int key_len, + dst2, *dst2_len, 1); + */ + +- return 0; ++out_sg: ++ teardown_sgtable(&sg_in); ++out_tfm: ++ crypto_free_blkcipher(tfm); ++ return ret; + } + + +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index cb57aa862177..b27f6d34762b 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -962,8 +962,6 @@ static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu) + else + dev->flags &= ~IFF_POINTOPOINT; + +- dev->iflink = p->link; +- + /* Precalculate GRE options length */ + if (t->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) { + if (t->parms.o_flags&GRE_CSUM) +@@ -1273,6 +1271,7 @@ static int ip6gre_tunnel_init(struct net_device *dev) + u64_stats_init(&ip6gre_tunnel_stats->syncp); + } + ++ dev->iflink = tunnel->parms.link; + + return 0; + } +@@ -1474,6 +1473,8 @@ static int ip6gre_tap_init(struct net_device *dev) + u64_stats_init(&ip6gre_tap_stats->syncp); + } + ++ dev->iflink = tunnel->parms.link; ++ + return 0; + } + +diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c +index 912033957ad3..657639d39f70 100644 +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -272,9 +272,6 @@ static int ip6_tnl_create2(struct net_device *dev) + int err; + + t = netdev_priv(dev); +- err = ip6_tnl_dev_init(dev); +- if (err < 0) +- goto out; + + err = register_netdevice(dev); + if (err < 0) +@@ -1456,6 +1453,7 @@ ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) + + + static const struct net_device_ops ip6_tnl_netdev_ops = { ++ .ndo_init = ip6_tnl_dev_init, + .ndo_uninit = ip6_tnl_dev_uninit, + .ndo_start_xmit = ip6_tnl_xmit, + .ndo_do_ioctl = ip6_tnl_ioctl, +@@ -1547,16 +1545,10 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev) + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = dev_net(dev); + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); +- int err = ip6_tnl_dev_init_gen(dev); +- +- if (err) +- return err; + + t->parms.proto = IPPROTO_IPV6; + dev_hold(dev); + +- ip6_tnl_link_config(t); +- + rcu_assign_pointer(ip6n->tnls_wc[0], t); + return 0; + } +diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c +index 2d19272b8cee..9a5339fcb450 100644 +--- a/net/ipv6/ip6_vti.c ++++ b/net/ipv6/ip6_vti.c +@@ -172,10 +172,6 @@ static int vti6_tnl_create2(struct net_device *dev) + struct vti6_net *ip6n = net_generic(net, vti6_net_id); + int err; + +- err = vti6_dev_init(dev); +- if (err < 0) +- goto out; +- + err = register_netdevice(dev); + if (err < 0) + goto out; +@@ -693,6 +689,7 @@ static int vti6_change_mtu(struct net_device *dev, int new_mtu) + } + + static const struct net_device_ops vti6_netdev_ops = { ++ .ndo_init = vti6_dev_init, + .ndo_uninit = vti6_dev_uninit, + .ndo_start_xmit = vti6_tnl_xmit, + .ndo_do_ioctl = vti6_ioctl, +@@ -772,16 +769,10 @@ static int __net_init vti6_fb_tnl_dev_init(struct net_device *dev) + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = dev_net(dev); + struct vti6_net *ip6n = net_generic(net, vti6_net_id); +- int err = vti6_dev_init_gen(dev); +- +- if (err) +- return err; + + t->parms.proto = IPPROTO_IPV6; + dev_hold(dev); + +- vti6_link_config(t); +- + rcu_assign_pointer(ip6n->tnls_wc[0], t); + return 0; + } +diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c +index b12b11b123ff..317b6dbf3190 100644 +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -195,10 +195,8 @@ static int ipip6_tunnel_create(struct net_device *dev) + struct sit_net *sitn = net_generic(net, sit_net_id); + int err; + +- err = ipip6_tunnel_init(dev); +- if (err < 0) +- goto out; +- ipip6_tunnel_clone_6rd(dev, sitn); ++ memcpy(dev->dev_addr, &t->parms.iph.saddr, 4); ++ memcpy(dev->broadcast, &t->parms.iph.daddr, 4); + + if ((__force u16)t->parms.i_flags & SIT_ISATAP) + dev->priv_flags |= IFF_ISATAP; +@@ -207,7 +205,8 @@ static int ipip6_tunnel_create(struct net_device *dev) + if (err < 0) + goto out; + +- strcpy(t->parms.name, dev->name); ++ ipip6_tunnel_clone_6rd(dev, sitn); ++ + dev->rtnl_link_ops = &sit_link_ops; + + dev_hold(dev); +@@ -1321,6 +1320,7 @@ static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) + } + + static const struct net_device_ops ipip6_netdev_ops = { ++ .ndo_init = ipip6_tunnel_init, + .ndo_uninit = ipip6_tunnel_uninit, + .ndo_start_xmit = sit_tunnel_xmit, + .ndo_do_ioctl = ipip6_tunnel_ioctl, +@@ -1367,9 +1367,7 @@ static int ipip6_tunnel_init(struct net_device *dev) + + tunnel->dev = dev; + tunnel->net = dev_net(dev); +- +- memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); +- memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); ++ strcpy(tunnel->parms.name, dev->name); + + ipip6_tunnel_bind_dev(dev); + dev->tstats = alloc_percpu(struct pcpu_sw_netstats); +@@ -1401,7 +1399,6 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) + + tunnel->dev = dev; + tunnel->net = dev_net(dev); +- strcpy(tunnel->parms.name, dev->name); + + iph->version = 4; + iph->protocol = IPPROTO_IPV6; +diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c +index ea7013cb7e52..3f076b9c9308 100644 +--- a/net/mac80211/ibss.c ++++ b/net/mac80211/ibss.c +@@ -815,7 +815,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, + + memset(¶ms, 0, sizeof(params)); + memset(&csa_ie, 0, sizeof(csa_ie)); +- err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, ++ err = ieee80211_parse_ch_switch_ie(sdata, elems, + ifibss->chandef.chan->band, + sta_flags, ifibss->bssid, &csa_ie); + /* can't switch to destination channel, fail */ +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index b127902361f4..bf7a1bbb975f 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1569,7 +1569,6 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, + * ieee80211_parse_ch_switch_ie - parses channel switch IEs + * @sdata: the sdata of the interface which has received the frame + * @elems: parsed 802.11 elements received with the frame +- * @beacon: indicates if the frame was a beacon or probe response + * @current_band: indicates the current band + * @sta_flags: contains information about own capabilities and restrictions + * to decide which channel switch announcements can be accepted. Only the +@@ -1583,7 +1582,7 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, + * Return: 0 on success, <0 on error and >0 if there is nothing to parse. + */ + int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, +- struct ieee802_11_elems *elems, bool beacon, ++ struct ieee802_11_elems *elems, + enum ieee80211_band current_band, + u32 sta_flags, u8 *bssid, + struct ieee80211_csa_ie *csa_ie); +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 8f7fabc46c97..06f5de4e4fbb 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -760,10 +760,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, + int i, flushed; + struct ps_data *ps; + struct cfg80211_chan_def chandef; ++ bool cancel_scan; + + clear_bit(SDATA_STATE_RUNNING, &sdata->state); + +- if (rcu_access_pointer(local->scan_sdata) == sdata) ++ cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata; ++ if (cancel_scan) + ieee80211_scan_cancel(local); + + /* +@@ -973,6 +975,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, + + ieee80211_recalc_ps(local, -1); + ++ if (cancel_scan) ++ flush_delayed_work(&local->scan_work); ++ + if (local->open_count == 0) { + ieee80211_stop_device(local); + +diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c +index 5b919cab1de0..3d52d1d68431 100644 +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -885,7 +885,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, + + memset(¶ms, 0, sizeof(params)); + memset(&csa_ie, 0, sizeof(csa_ie)); +- err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, band, ++ err = ieee80211_parse_ch_switch_ie(sdata, elems, band, + sta_flags, sdata->vif.addr, + &csa_ie); + if (err < 0) +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 189eef014c4f..c9535a976b56 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -1001,7 +1001,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, + + current_band = cbss->channel->band; + memset(&csa_ie, 0, sizeof(csa_ie)); +- res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band, ++ res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band, + ifmgd->flags, + ifmgd->associated->bssid, &csa_ie); + if (res < 0) +@@ -1086,7 +1086,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, + ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work); + else + mod_timer(&ifmgd->chswitch_timer, +- TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval)); ++ TU_TO_EXP_TIME((csa_ie.count - 1) * ++ cbss->beacon_interval)); + } + + static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 3e57f96c9666..095c16037bc5 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1679,11 +1679,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + sc = le16_to_cpu(hdr->seq_ctrl); + frag = sc & IEEE80211_SCTL_FRAG; + +- if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || +- is_multicast_ether_addr(hdr->addr1))) { +- /* not fragmented */ ++ if (likely(!ieee80211_has_morefrags(fc) && frag == 0)) ++ goto out; ++ ++ if (is_multicast_ether_addr(hdr->addr1)) { ++ rx->local->dot11MulticastReceivedFrameCount++; + goto out; + } ++ + I802_DEBUG_INC(rx->local->rx_handlers_fragments); + + if (skb_linearize(rx->skb)) +@@ -1776,10 +1779,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + out: + if (rx->sta) + rx->sta->rx_packets++; +- if (is_multicast_ether_addr(hdr->addr1)) +- rx->local->dot11MulticastReceivedFrameCount++; +- else +- ieee80211_led_rx(rx->local); ++ ieee80211_led_rx(rx->local); + return RX_CONTINUE; + } + +diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c +index 6ab009070084..efeba56c913b 100644 +--- a/net/mac80211/spectmgmt.c ++++ b/net/mac80211/spectmgmt.c +@@ -22,7 +22,7 @@ + #include "wme.h" + + int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, +- struct ieee802_11_elems *elems, bool beacon, ++ struct ieee802_11_elems *elems, + enum ieee80211_band current_band, + u32 sta_flags, u8 *bssid, + struct ieee80211_csa_ie *csa_ie) +@@ -91,19 +91,13 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, + return -EINVAL; + } + +- if (!beacon && sec_chan_offs) { ++ if (sec_chan_offs) { + secondary_channel_offset = sec_chan_offs->sec_chan_offs; +- } else if (beacon && ht_oper) { +- secondary_channel_offset = +- ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; + } else if (!(sta_flags & IEEE80211_STA_DISABLE_HT)) { +- /* If it's not a beacon, HT is enabled and the IE not present, +- * it's 20 MHz, 802.11-2012 8.5.2.6: +- * This element [the Secondary Channel Offset Element] is +- * present when switching to a 40 MHz channel. It may be +- * present when switching to a 20 MHz channel (in which +- * case the secondary channel offset is set to SCN). +- */ ++ /* If the secondary channel offset IE is not present, ++ * we can't know what's the post-CSA offset, so the ++ * best we can do is use 20MHz. ++ */ + secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; + } + +diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c +index de770ec39e51..cf9937743abb 100644 +--- a/net/netfilter/ipset/ip_set_core.c ++++ b/net/netfilter/ipset/ip_set_core.c +@@ -636,7 +636,7 @@ ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index) + struct ip_set *set; + struct ip_set_net *inst = ip_set_pernet(net); + +- if (index > inst->ip_set_max) ++ if (index >= inst->ip_set_max) + return IPSET_INVALID_ID; + + nfnl_lock(NFNL_SUBSYS_IPSET); +diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c +index a155d19a225e..6ff12a191400 100644 +--- a/net/netfilter/nfnetlink_log.c ++++ b/net/netfilter/nfnetlink_log.c +@@ -45,7 +45,8 @@ + #define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE + #define NFULNL_TIMEOUT_DEFAULT 100 /* every second */ + #define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */ +-#define NFULNL_COPY_RANGE_MAX 0xFFFF /* max packet size is limited by 16-bit struct nfattr nfa_len field */ ++/* max packet size is limited by 16-bit struct nfattr nfa_len field */ ++#define NFULNL_COPY_RANGE_MAX (0xFFFF - NLA_HDRLEN) + + #define PRINTR(x, args...) do { if (net_ratelimit()) \ + printk(x, ## args); } while (0); +@@ -255,6 +256,8 @@ nfulnl_set_mode(struct nfulnl_instance *inst, u_int8_t mode, + + case NFULNL_COPY_PACKET: + inst->copy_mode = mode; ++ if (range == 0) ++ range = NFULNL_COPY_RANGE_MAX; + inst->copy_range = min_t(unsigned int, + range, NFULNL_COPY_RANGE_MAX); + break; +@@ -346,26 +349,25 @@ nfulnl_alloc_skb(struct net *net, u32 peer_portid, unsigned int inst_size, + return skb; + } + +-static int ++static void + __nfulnl_send(struct nfulnl_instance *inst) + { +- int status = -1; +- + if (inst->qlen > 1) { + struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0, + NLMSG_DONE, + sizeof(struct nfgenmsg), + 0); +- if (!nlh) ++ if (WARN_ONCE(!nlh, "bad nlskb size: %u, tailroom %d\n", ++ inst->skb->len, skb_tailroom(inst->skb))) { ++ kfree_skb(inst->skb); + goto out; ++ } + } +- status = nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid, +- MSG_DONTWAIT); +- ++ nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid, ++ MSG_DONTWAIT); ++out: + inst->qlen = 0; + inst->skb = NULL; +-out: +- return status; + } + + static void +@@ -652,7 +654,8 @@ nfulnl_log_packet(struct net *net, + + nla_total_size(sizeof(u_int32_t)) /* gid */ + + nla_total_size(plen) /* prefix */ + + nla_total_size(sizeof(struct nfulnl_msg_packet_hw)) +- + nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp)); ++ + nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp)) ++ + nla_total_size(sizeof(struct nfgenmsg)); /* NLMSG_DONE */ + + if (in && skb_mac_header_was_set(skb)) { + size += nla_total_size(skb->dev->hard_header_len) +@@ -681,8 +684,7 @@ nfulnl_log_packet(struct net *net, + break; + + case NFULNL_COPY_PACKET: +- if (inst->copy_range == 0 +- || inst->copy_range > skb->len) ++ if (inst->copy_range > skb->len) + data_len = skb->len; + else + data_len = inst->copy_range; +@@ -695,8 +697,7 @@ nfulnl_log_packet(struct net *net, + goto unlock_and_release; + } + +- if (inst->skb && +- size > skb_tailroom(inst->skb) - sizeof(struct nfgenmsg)) { ++ if (inst->skb && size > skb_tailroom(inst->skb)) { + /* either the queue len is too high or we don't have + * enough room in the skb left. flush to userspace. */ + __nfulnl_flush(inst); +diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c +index 82cb8236f8a1..ad979612238a 100644 +--- a/net/netfilter/nft_compat.c ++++ b/net/netfilter/nft_compat.c +@@ -678,7 +678,7 @@ nft_target_select_ops(const struct nft_ctx *ctx, + family = ctx->afi->family; + + /* Re-use the existing target if it's already loaded. */ +- list_for_each_entry(nft_target, &nft_match_list, head) { ++ list_for_each_entry(nft_target, &nft_target_list, head) { + struct xt_target *target = nft_target->ops.data; + + if (strcmp(target->name, tg_name) == 0 && +diff --git a/net/sctp/associola.c b/net/sctp/associola.c +index 5d97d8fe4be7..d477d476714d 100644 +--- a/net/sctp/associola.c ++++ b/net/sctp/associola.c +@@ -1627,6 +1627,8 @@ struct sctp_chunk *sctp_assoc_lookup_asconf_ack( + * ack chunk whose serial number matches that of the request. + */ + list_for_each_entry(ack, &asoc->asconf_ack_list, transmitted_list) { ++ if (sctp_chunk_pending(ack)) ++ continue; + if (ack->subh.addip_hdr->serial == serial) { + sctp_chunk_hold(ack); + return ack; +diff --git a/net/sctp/auth.c b/net/sctp/auth.c +index 0e8529113dc5..fb7976aee61c 100644 +--- a/net/sctp/auth.c ++++ b/net/sctp/auth.c +@@ -862,8 +862,6 @@ int sctp_auth_set_key(struct sctp_endpoint *ep, + list_add(&cur_key->key_list, sh_keys); + + cur_key->key = key; +- sctp_auth_key_hold(key); +- + return 0; + nomem: + if (!replace) +diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c +index 4de12afa13d4..7e8a16c77039 100644 +--- a/net/sctp/inqueue.c ++++ b/net/sctp/inqueue.c +@@ -140,18 +140,9 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) + } else { + /* Nothing to do. Next chunk in the packet, please. */ + ch = (sctp_chunkhdr_t *) chunk->chunk_end; +- + /* Force chunk->skb->data to chunk->chunk_end. */ +- skb_pull(chunk->skb, +- chunk->chunk_end - chunk->skb->data); +- +- /* Verify that we have at least chunk headers +- * worth of buffer left. +- */ +- if (skb_headlen(chunk->skb) < sizeof(sctp_chunkhdr_t)) { +- sctp_chunk_free(chunk); +- chunk = queue->in_progress = NULL; +- } ++ skb_pull(chunk->skb, chunk->chunk_end - chunk->skb->data); ++ /* We are guaranteed to pull a SCTP header. */ + } + } + +@@ -187,24 +178,14 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) + skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t)); + chunk->subh.v = NULL; /* Subheader is no longer valid. */ + +- if (chunk->chunk_end < skb_tail_pointer(chunk->skb)) { ++ if (chunk->chunk_end + sizeof(sctp_chunkhdr_t) < ++ skb_tail_pointer(chunk->skb)) { + /* This is not a singleton */ + chunk->singleton = 0; + } else if (chunk->chunk_end > skb_tail_pointer(chunk->skb)) { +- /* RFC 2960, Section 6.10 Bundling +- * +- * Partial chunks MUST NOT be placed in an SCTP packet. +- * If the receiver detects a partial chunk, it MUST drop +- * the chunk. +- * +- * Since the end of the chunk is past the end of our buffer +- * (which contains the whole packet, we can freely discard +- * the whole packet. +- */ +- sctp_chunk_free(chunk); +- chunk = queue->in_progress = NULL; +- +- return NULL; ++ /* Discard inside state machine. */ ++ chunk->pdiscard = 1; ++ chunk->chunk_end = skb_tail_pointer(chunk->skb); + } else { + /* We are at the end of the packet, so mark the chunk + * in case we need to send a SACK. +diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c +index fee5552ddf92..43abb643f3a1 100644 +--- a/net/sctp/sm_make_chunk.c ++++ b/net/sctp/sm_make_chunk.c +@@ -2609,6 +2609,9 @@ do_addr_param: + addr_param = param.v + sizeof(sctp_addip_param_t); + + af = sctp_get_af_specific(param_type2af(param.p->type)); ++ if (af == NULL) ++ break; ++ + af->from_addr_param(&addr, addr_param, + htons(asoc->peer.port), 0); + +@@ -3110,50 +3113,63 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, + return SCTP_ERROR_NO_ERROR; + } + +-/* Verify the ASCONF packet before we process it. */ +-int sctp_verify_asconf(const struct sctp_association *asoc, +- struct sctp_paramhdr *param_hdr, void *chunk_end, +- struct sctp_paramhdr **errp) { +- sctp_addip_param_t *asconf_param; ++/* Verify the ASCONF packet before we process it. */ ++bool sctp_verify_asconf(const struct sctp_association *asoc, ++ struct sctp_chunk *chunk, bool addr_param_needed, ++ struct sctp_paramhdr **errp) ++{ ++ sctp_addip_chunk_t *addip = (sctp_addip_chunk_t *) chunk->chunk_hdr; + union sctp_params param; +- int length, plen; ++ bool addr_param_seen = false; + +- param.v = (sctp_paramhdr_t *) param_hdr; +- while (param.v <= chunk_end - sizeof(sctp_paramhdr_t)) { +- length = ntohs(param.p->length); +- *errp = param.p; +- +- if (param.v > chunk_end - length || +- length < sizeof(sctp_paramhdr_t)) +- return 0; ++ sctp_walk_params(param, addip, addip_hdr.params) { ++ size_t length = ntohs(param.p->length); + ++ *errp = param.p; + switch (param.p->type) { ++ case SCTP_PARAM_ERR_CAUSE: ++ break; ++ case SCTP_PARAM_IPV4_ADDRESS: ++ if (length != sizeof(sctp_ipv4addr_param_t)) ++ return false; ++ addr_param_seen = true; ++ break; ++ case SCTP_PARAM_IPV6_ADDRESS: ++ if (length != sizeof(sctp_ipv6addr_param_t)) ++ return false; ++ addr_param_seen = true; ++ break; + case SCTP_PARAM_ADD_IP: + case SCTP_PARAM_DEL_IP: + case SCTP_PARAM_SET_PRIMARY: +- asconf_param = (sctp_addip_param_t *)param.v; +- plen = ntohs(asconf_param->param_hdr.length); +- if (plen < sizeof(sctp_addip_param_t) + +- sizeof(sctp_paramhdr_t)) +- return 0; ++ /* In ASCONF chunks, these need to be first. */ ++ if (addr_param_needed && !addr_param_seen) ++ return false; ++ length = ntohs(param.addip->param_hdr.length); ++ if (length < sizeof(sctp_addip_param_t) + ++ sizeof(sctp_paramhdr_t)) ++ return false; + break; + case SCTP_PARAM_SUCCESS_REPORT: + case SCTP_PARAM_ADAPTATION_LAYER_IND: + if (length != sizeof(sctp_addip_param_t)) +- return 0; +- ++ return false; + break; + default: +- break; ++ /* This is unkown to us, reject! */ ++ return false; + } +- +- param.v += WORD_ROUND(length); + } + +- if (param.v != chunk_end) +- return 0; ++ /* Remaining sanity checks. */ ++ if (addr_param_needed && !addr_param_seen) ++ return false; ++ if (!addr_param_needed && addr_param_seen) ++ return false; ++ if (param.v != chunk->chunk_end) ++ return false; + +- return 1; ++ return true; + } + + /* Process an incoming ASCONF chunk with the next expected serial no. and +@@ -3162,16 +3178,17 @@ int sctp_verify_asconf(const struct sctp_association *asoc, + struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, + struct sctp_chunk *asconf) + { ++ sctp_addip_chunk_t *addip = (sctp_addip_chunk_t *) asconf->chunk_hdr; ++ bool all_param_pass = true; ++ union sctp_params param; + sctp_addiphdr_t *hdr; + union sctp_addr_param *addr_param; + sctp_addip_param_t *asconf_param; + struct sctp_chunk *asconf_ack; +- + __be16 err_code; + int length = 0; + int chunk_len; + __u32 serial; +- int all_param_pass = 1; + + chunk_len = ntohs(asconf->chunk_hdr->length) - sizeof(sctp_chunkhdr_t); + hdr = (sctp_addiphdr_t *)asconf->skb->data; +@@ -3199,9 +3216,14 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, + goto done; + + /* Process the TLVs contained within the ASCONF chunk. */ +- while (chunk_len > 0) { ++ sctp_walk_params(param, addip, addip_hdr.params) { ++ /* Skip preceeding address parameters. */ ++ if (param.p->type == SCTP_PARAM_IPV4_ADDRESS || ++ param.p->type == SCTP_PARAM_IPV6_ADDRESS) ++ continue; ++ + err_code = sctp_process_asconf_param(asoc, asconf, +- asconf_param); ++ param.addip); + /* ADDIP 4.1 A7) + * If an error response is received for a TLV parameter, + * all TLVs with no response before the failed TLV are +@@ -3209,28 +3231,20 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, + * the failed response are considered unsuccessful unless + * a specific success indication is present for the parameter. + */ +- if (SCTP_ERROR_NO_ERROR != err_code) +- all_param_pass = 0; +- ++ if (err_code != SCTP_ERROR_NO_ERROR) ++ all_param_pass = false; + if (!all_param_pass) +- sctp_add_asconf_response(asconf_ack, +- asconf_param->crr_id, err_code, +- asconf_param); ++ sctp_add_asconf_response(asconf_ack, param.addip->crr_id, ++ err_code, param.addip); + + /* ADDIP 4.3 D11) When an endpoint receiving an ASCONF to add + * an IP address sends an 'Out of Resource' in its response, it + * MUST also fail any subsequent add or delete requests bundled + * in the ASCONF. + */ +- if (SCTP_ERROR_RSRC_LOW == err_code) ++ if (err_code == SCTP_ERROR_RSRC_LOW) + goto done; +- +- /* Move to the next ASCONF param. */ +- length = ntohs(asconf_param->param_hdr.length); +- asconf_param = (void *)asconf_param + length; +- chunk_len -= length; + } +- + done: + asoc->peer.addip_serial++; + +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index 7194fe8589b0..3e287a3fa03b 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -170,6 +170,9 @@ sctp_chunk_length_valid(struct sctp_chunk *chunk, + { + __u16 chunk_length = ntohs(chunk->chunk_hdr->length); + ++ /* Previously already marked? */ ++ if (unlikely(chunk->pdiscard)) ++ return 0; + if (unlikely(chunk_length < required_length)) + return 0; + +@@ -3591,9 +3594,7 @@ sctp_disposition_t sctp_sf_do_asconf(struct net *net, + struct sctp_chunk *asconf_ack = NULL; + struct sctp_paramhdr *err_param = NULL; + sctp_addiphdr_t *hdr; +- union sctp_addr_param *addr_param; + __u32 serial; +- int length; + + if (!sctp_vtag_verify(chunk, asoc)) { + sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, +@@ -3618,17 +3619,8 @@ sctp_disposition_t sctp_sf_do_asconf(struct net *net, + hdr = (sctp_addiphdr_t *)chunk->skb->data; + serial = ntohl(hdr->serial); + +- addr_param = (union sctp_addr_param *)hdr->params; +- length = ntohs(addr_param->p.length); +- if (length < sizeof(sctp_paramhdr_t)) +- return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, +- (void *)addr_param, commands); +- + /* Verify the ASCONF chunk before processing it. */ +- if (!sctp_verify_asconf(asoc, +- (sctp_paramhdr_t *)((void *)addr_param + length), +- (void *)chunk->chunk_end, +- &err_param)) ++ if (!sctp_verify_asconf(asoc, chunk, true, &err_param)) + return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, + (void *)err_param, commands); + +@@ -3745,10 +3737,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(struct net *net, + rcvd_serial = ntohl(addip_hdr->serial); + + /* Verify the ASCONF-ACK chunk before processing it. */ +- if (!sctp_verify_asconf(asoc, +- (sctp_paramhdr_t *)addip_hdr->params, +- (void *)asconf_ack->chunk_end, +- &err_param)) ++ if (!sctp_verify_asconf(asoc, asconf_ack, false, &err_param)) + return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, + (void *)err_param, commands); + +diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c +index f4b12c216f1c..5a723df670b4 100644 +--- a/sound/usb/mixer_quirks.c ++++ b/sound/usb/mixer_quirks.c +@@ -885,6 +885,11 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, + return changed; + } + ++static void kctl_private_value_free(struct snd_kcontrol *kctl) ++{ ++ kfree((void *)kctl->private_value); ++} ++ + static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer, + int validx, int bUnitID) + { +@@ -919,6 +924,7 @@ static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer, + return -ENOMEM; + } + ++ kctl->private_free = kctl_private_value_free; + err = snd_ctl_add(mixer->chip->card, kctl); + if (err < 0) + return err; diff --git a/patch/kernel/cubox-default/patch-3.14.25-26.patch b/patch/kernel/cubox-default/patch-3.14.25-26.patch new file mode 100644 index 000000000..5d79376e1 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.25-26.patch @@ -0,0 +1,2603 @@ +diff --git a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +index ce6a1a072028..8a3c40829899 100644 +--- a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt ++++ b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +@@ -30,10 +30,6 @@ should only be used when a device has multiple interrupt parents. + Example: + interrupts-extended = <&intc1 5 1>, <&intc2 1 0>; + +-A device node may contain either "interrupts" or "interrupts-extended", but not +-both. If both properties are present, then the operating system should log an +-error and use only the data in "interrupts". +- + 2) Interrupt controller nodes + ----------------------------- + +diff --git a/Makefile b/Makefile +index eb96e40238f7..63a5ee858cc3 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 25 ++SUBLEVEL = 26 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h +index 71a06b293489..3e635eed9c6c 100644 +--- a/arch/arm/include/asm/thread_info.h ++++ b/arch/arm/include/asm/thread_info.h +@@ -43,16 +43,6 @@ struct cpu_context_save { + __u32 extra[2]; /* Xscale 'acc' register, etc */ + }; + +-struct arm_restart_block { +- union { +- /* For user cache flushing */ +- struct { +- unsigned long start; +- unsigned long end; +- } cache; +- }; +-}; +- + /* + * low level task data that entry.S needs immediate access to. + * __switch_to() assumes cpu_context follows immediately after cpu_domain. +@@ -78,7 +68,6 @@ struct thread_info { + unsigned long thumbee_state; /* ThumbEE Handler Base register */ + #endif + struct restart_block restart_block; +- struct arm_restart_block arm_restart_block; + }; + + #define INIT_THREAD_INFO(tsk) \ +diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c +index 9265b8bb529a..3f314433d653 100644 +--- a/arch/arm/kernel/traps.c ++++ b/arch/arm/kernel/traps.c +@@ -510,8 +510,6 @@ static int bad_syscall(int n, struct pt_regs *regs) + return regs->ARM_r0; + } + +-static long do_cache_op_restart(struct restart_block *); +- + static inline int + __do_cache_op(unsigned long start, unsigned long end) + { +@@ -520,24 +518,8 @@ __do_cache_op(unsigned long start, unsigned long end) + do { + unsigned long chunk = min(PAGE_SIZE, end - start); + +- if (signal_pending(current)) { +- struct thread_info *ti = current_thread_info(); +- +- ti->restart_block = (struct restart_block) { +- .fn = do_cache_op_restart, +- }; +- +- ti->arm_restart_block = (struct arm_restart_block) { +- { +- .cache = { +- .start = start, +- .end = end, +- }, +- }, +- }; +- +- return -ERESTART_RESTARTBLOCK; +- } ++ if (fatal_signal_pending(current)) ++ return 0; + + ret = flush_cache_user_range(start, start + chunk); + if (ret) +@@ -550,15 +532,6 @@ __do_cache_op(unsigned long start, unsigned long end) + return 0; + } + +-static long do_cache_op_restart(struct restart_block *unused) +-{ +- struct arm_restart_block *restart_block; +- +- restart_block = ¤t_thread_info()->arm_restart_block; +- return __do_cache_op(restart_block->cache.start, +- restart_block->cache.end); +-} +- + static inline int + do_cache_op(unsigned long start, unsigned long end, int flags) + { +diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S +index 74f6033e76dd..fdedc31e0f40 100644 +--- a/arch/arm/mm/proc-v7.S ++++ b/arch/arm/mm/proc-v7.S +@@ -211,7 +211,6 @@ __v7_pj4b_setup: + /* Auxiliary Debug Modes Control 1 Register */ + #define PJ4B_STATIC_BP (1 << 2) /* Enable Static BP */ + #define PJ4B_INTER_PARITY (1 << 8) /* Disable Internal Parity Handling */ +-#define PJ4B_BCK_OFF_STREX (1 << 5) /* Enable the back off of STREX instr */ + #define PJ4B_CLEAN_LINE (1 << 16) /* Disable data transfer for clean line */ + + /* Auxiliary Debug Modes Control 2 Register */ +@@ -234,7 +233,6 @@ __v7_pj4b_setup: + /* Auxiliary Debug Modes Control 1 Register */ + mrc p15, 1, r0, c15, c1, 1 + orr r0, r0, #PJ4B_CLEAN_LINE +- orr r0, r0, #PJ4B_BCK_OFF_STREX + orr r0, r0, #PJ4B_INTER_PARITY + bic r0, r0, #PJ4B_STATIC_BP + mcr p15, 1, r0, c15, c1, 1 +diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S +index d19b1cfcad91..b34b95f45cb3 100644 +--- a/arch/arm/mm/proc-xscale.S ++++ b/arch/arm/mm/proc-xscale.S +@@ -535,7 +535,7 @@ ENTRY(cpu_xscale_do_suspend) + mrc p15, 0, r5, c15, c1, 0 @ CP access reg + mrc p15, 0, r6, c13, c0, 0 @ PID + mrc p15, 0, r7, c3, c0, 0 @ domain ID +- mrc p15, 0, r8, c1, c1, 0 @ auxiliary control reg ++ mrc p15, 0, r8, c1, c0, 1 @ auxiliary control reg + mrc p15, 0, r9, c1, c0, 0 @ control reg + bic r4, r4, #2 @ clear frequency change bit + stmia r0, {r4 - r9} @ store cp regs +@@ -552,7 +552,7 @@ ENTRY(cpu_xscale_do_resume) + mcr p15, 0, r6, c13, c0, 0 @ PID + mcr p15, 0, r7, c3, c0, 0 @ domain ID + mcr p15, 0, r1, c2, c0, 0 @ translation table base addr +- mcr p15, 0, r8, c1, c1, 0 @ auxiliary control reg ++ mcr p15, 0, r8, c1, c0, 1 @ auxiliary control reg + mov r0, r9 @ control register + b cpu_resume_mmu + ENDPROC(cpu_xscale_do_resume) +diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile +index 9e4484ccbb03..9005a8d60969 100644 +--- a/arch/mips/loongson/common/Makefile ++++ b/arch/mips/loongson/common/Makefile +@@ -11,7 +11,8 @@ obj-$(CONFIG_PCI) += pci.o + # Serial port support + # + obj-$(CONFIG_EARLY_PRINTK) += early_printk.o +-obj-$(CONFIG_SERIAL_8250) += serial.o ++loongson-serial-$(CONFIG_SERIAL_8250) := serial.o ++obj-y += $(loongson-serial-m) $(loongson-serial-y) + obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o + obj-$(CONFIG_LOONGSON_MC146818) += rtc.o + +diff --git a/arch/mips/oprofile/backtrace.c b/arch/mips/oprofile/backtrace.c +index 6854ed5097d2..83a1dfd8f0e3 100644 +--- a/arch/mips/oprofile/backtrace.c ++++ b/arch/mips/oprofile/backtrace.c +@@ -92,7 +92,7 @@ static inline int unwind_user_frame(struct stackframe *old_frame, + /* This marks the end of the previous function, + which means we overran. */ + break; +- stack_size = (unsigned) stack_adjustment; ++ stack_size = (unsigned long) stack_adjustment; + } else if (is_ra_save_ins(&ip)) { + int ra_slot = ip.i_format.simmediate; + if (ra_slot < 0) +diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c +index beedaf0c5e75..d558b8595e6f 100644 +--- a/arch/powerpc/platforms/powernv/pci-ioda.c ++++ b/arch/powerpc/platforms/powernv/pci-ioda.c +@@ -902,7 +902,6 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, + unsigned int is_64, struct msi_msg *msg) + { + struct pnv_ioda_pe *pe = pnv_ioda_get_pe(dev); +- struct pci_dn *pdn = pci_get_pdn(dev); + struct irq_data *idata; + struct irq_chip *ichip; + unsigned int xive_num = hwirq - phb->msi_base; +@@ -918,7 +917,7 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, + return -ENXIO; + + /* Force 32-bit MSI on some broken devices */ +- if (pdn && pdn->force_32bit_msi) ++ if (dev->no_64bit_msi) + is_64 = 0; + + /* Assign XIVE to PE */ +diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c +index 8518817dcdfd..52c1162bcee3 100644 +--- a/arch/powerpc/platforms/powernv/pci.c ++++ b/arch/powerpc/platforms/powernv/pci.c +@@ -1,3 +1,4 @@ ++ + /* + * Support PCI/PCIe on PowerNV platforms + * +@@ -50,9 +51,8 @@ static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type) + { + struct pci_controller *hose = pci_bus_to_host(pdev->bus); + struct pnv_phb *phb = hose->private_data; +- struct pci_dn *pdn = pci_get_pdn(pdev); + +- if (pdn && pdn->force_32bit_msi && !phb->msi32_support) ++ if (pdev->no_64bit_msi && !phb->msi32_support) + return -ENODEV; + + return (phb && phb->msi_bmp.bitmap) ? 0 : -ENODEV; +diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c +index 0c882e83c4ce..6849d85ea0d5 100644 +--- a/arch/powerpc/platforms/pseries/msi.c ++++ b/arch/powerpc/platforms/pseries/msi.c +@@ -428,7 +428,7 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type) + */ + again: + if (type == PCI_CAP_ID_MSI) { +- if (pdn->force_32bit_msi) { ++ if (pdev->no_64bit_msi) { + rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSI_FN, nvec); + if (rc < 0) { + /* +diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c +index b07909850f77..bc5fbc201bcb 100644 +--- a/arch/powerpc/xmon/xmon.c ++++ b/arch/powerpc/xmon/xmon.c +@@ -288,10 +288,10 @@ static inline void disable_surveillance(void) + args.token = rtas_token("set-indicator"); + if (args.token == RTAS_UNKNOWN_SERVICE) + return; +- args.nargs = 3; +- args.nret = 1; ++ args.nargs = cpu_to_be32(3); ++ args.nret = cpu_to_be32(1); + args.rets = &args.args[3]; +- args.args[0] = SURVEILLANCE_TOKEN; ++ args.args[0] = cpu_to_be32(SURVEILLANCE_TOKEN); + args.args[1] = 0; + args.args[2] = 0; + enter_rtas(__pa(&args)); +diff --git a/arch/sparc/include/uapi/asm/swab.h b/arch/sparc/include/uapi/asm/swab.h +index a34ad079487e..4c7c12d69bea 100644 +--- a/arch/sparc/include/uapi/asm/swab.h ++++ b/arch/sparc/include/uapi/asm/swab.h +@@ -9,9 +9,9 @@ static inline __u16 __arch_swab16p(const __u16 *addr) + { + __u16 ret; + +- __asm__ __volatile__ ("lduha [%1] %2, %0" ++ __asm__ __volatile__ ("lduha [%2] %3, %0" + : "=r" (ret) +- : "r" (addr), "i" (ASI_PL)); ++ : "m" (*addr), "r" (addr), "i" (ASI_PL)); + return ret; + } + #define __arch_swab16p __arch_swab16p +@@ -20,9 +20,9 @@ static inline __u32 __arch_swab32p(const __u32 *addr) + { + __u32 ret; + +- __asm__ __volatile__ ("lduwa [%1] %2, %0" ++ __asm__ __volatile__ ("lduwa [%2] %3, %0" + : "=r" (ret) +- : "r" (addr), "i" (ASI_PL)); ++ : "m" (*addr), "r" (addr), "i" (ASI_PL)); + return ret; + } + #define __arch_swab32p __arch_swab32p +@@ -31,9 +31,9 @@ static inline __u64 __arch_swab64p(const __u64 *addr) + { + __u64 ret; + +- __asm__ __volatile__ ("ldxa [%1] %2, %0" ++ __asm__ __volatile__ ("ldxa [%2] %3, %0" + : "=r" (ret) +- : "r" (addr), "i" (ASI_PL)); ++ : "m" (*addr), "r" (addr), "i" (ASI_PL)); + return ret; + } + #define __arch_swab64p __arch_swab64p +diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h +index 5f1296872aed..1717156f4dd1 100644 +--- a/arch/x86/include/asm/cpufeature.h ++++ b/arch/x86/include/asm/cpufeature.h +@@ -203,6 +203,7 @@ + #define X86_FEATURE_DECODEASSISTS (8*32+12) /* AMD Decode Assists support */ + #define X86_FEATURE_PAUSEFILTER (8*32+13) /* AMD filtered pause intercept */ + #define X86_FEATURE_PFTHRESHOLD (8*32+14) /* AMD pause filter threshold */ ++#define X86_FEATURE_VMMCALL (8*32+15) /* Prefer vmmcall to vmcall */ + + + /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ +diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h +index c7678e43465b..e62cf897f781 100644 +--- a/arch/x86/include/asm/kvm_para.h ++++ b/arch/x86/include/asm/kvm_para.h +@@ -2,6 +2,7 @@ + #define _ASM_X86_KVM_PARA_H + + #include ++#include + #include + + extern void kvmclock_init(void); +@@ -16,10 +17,15 @@ static inline bool kvm_check_and_clear_guest_paused(void) + } + #endif /* CONFIG_KVM_GUEST */ + +-/* This instruction is vmcall. On non-VT architectures, it will generate a +- * trap that we will then rewrite to the appropriate instruction. ++#ifdef CONFIG_DEBUG_RODATA ++#define KVM_HYPERCALL \ ++ ALTERNATIVE(".byte 0x0f,0x01,0xc1", ".byte 0x0f,0x01,0xd9", X86_FEATURE_VMMCALL) ++#else ++/* On AMD processors, vmcall will generate a trap that we will ++ * then rewrite to the appropriate instruction. + */ + #define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1" ++#endif + + /* For KVM hypercalls, a three-byte sequence of either the vmcall or the vmmcall + * instruction. The hypervisor may replace it with something else but only the +diff --git a/arch/x86/include/asm/page_32_types.h b/arch/x86/include/asm/page_32_types.h +index f48b17df4224..3a52ee0e726d 100644 +--- a/arch/x86/include/asm/page_32_types.h ++++ b/arch/x86/include/asm/page_32_types.h +@@ -20,7 +20,6 @@ + #define THREAD_SIZE_ORDER 1 + #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) + +-#define STACKFAULT_STACK 0 + #define DOUBLEFAULT_STACK 1 + #define NMI_STACK 0 + #define DEBUG_STACK 0 +diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h +index 8de6d9cf3b95..d54d1eebeffe 100644 +--- a/arch/x86/include/asm/page_64_types.h ++++ b/arch/x86/include/asm/page_64_types.h +@@ -14,12 +14,11 @@ + #define IRQ_STACK_ORDER 2 + #define IRQ_STACK_SIZE (PAGE_SIZE << IRQ_STACK_ORDER) + +-#define STACKFAULT_STACK 1 +-#define DOUBLEFAULT_STACK 2 +-#define NMI_STACK 3 +-#define DEBUG_STACK 4 +-#define MCE_STACK 5 +-#define N_EXCEPTION_STACKS 5 /* hw limit: 7 */ ++#define DOUBLEFAULT_STACK 1 ++#define NMI_STACK 2 ++#define DEBUG_STACK 3 ++#define MCE_STACK 4 ++#define N_EXCEPTION_STACKS 4 /* hw limit: 7 */ + + #define PUD_PAGE_SIZE (_AC(1, UL) << PUD_SHIFT) + #define PUD_PAGE_MASK (~(PUD_PAGE_SIZE-1)) +diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h +index e1940c06ed02..e870ea9232c3 100644 +--- a/arch/x86/include/asm/thread_info.h ++++ b/arch/x86/include/asm/thread_info.h +@@ -144,7 +144,7 @@ struct thread_info { + /* Only used for 64 bit */ + #define _TIF_DO_NOTIFY_MASK \ + (_TIF_SIGPENDING | _TIF_MCE_NOTIFY | _TIF_NOTIFY_RESUME | \ +- _TIF_USER_RETURN_NOTIFY) ++ _TIF_USER_RETURN_NOTIFY | _TIF_UPROBE) + + /* flags to check in __switch_to() */ + #define _TIF_WORK_CTXSW \ +diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h +index 58d66fe06b61..b409b17efb48 100644 +--- a/arch/x86/include/asm/traps.h ++++ b/arch/x86/include/asm/traps.h +@@ -39,6 +39,7 @@ asmlinkage void simd_coprocessor_error(void); + + #ifdef CONFIG_TRACING + asmlinkage void trace_page_fault(void); ++#define trace_stack_segment stack_segment + #define trace_divide_error divide_error + #define trace_bounds bounds + #define trace_invalid_op invalid_op +diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c +index c67ffa686064..c005fdd52529 100644 +--- a/arch/x86/kernel/cpu/amd.c ++++ b/arch/x86/kernel/cpu/amd.c +@@ -508,6 +508,13 @@ static void early_init_amd(struct cpuinfo_x86 *c) + } + #endif + ++ /* ++ * This is only needed to tell the kernel whether to use VMCALL ++ * and VMMCALL. VMMCALL is never executed except under virt, so ++ * we can set it unconditionally. ++ */ ++ set_cpu_cap(c, X86_FEATURE_VMMCALL); ++ + /* F16h erratum 793, CVE-2013-6885 */ + if (c->x86 == 0x16 && c->x86_model <= 0xf) { + u64 val; +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +index 3f27f5fd0847..e6bddd5b9da3 100644 +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -144,6 +144,8 @@ EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); + + static int __init x86_xsave_setup(char *s) + { ++ if (strlen(s)) ++ return 0; + setup_clear_cpu_cap(X86_FEATURE_XSAVE); + setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT); + setup_clear_cpu_cap(X86_FEATURE_AVX); +diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c +index addb207dab92..66e274a3d968 100644 +--- a/arch/x86/kernel/dumpstack_64.c ++++ b/arch/x86/kernel/dumpstack_64.c +@@ -24,7 +24,6 @@ static char x86_stack_ids[][8] = { + [ DEBUG_STACK-1 ] = "#DB", + [ NMI_STACK-1 ] = "NMI", + [ DOUBLEFAULT_STACK-1 ] = "#DF", +- [ STACKFAULT_STACK-1 ] = "#SS", + [ MCE_STACK-1 ] = "#MC", + #if DEBUG_STKSZ > EXCEPTION_STKSZ + [ N_EXCEPTION_STACKS ... +diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S +index 03cd2a8f6009..02553d6d183d 100644 +--- a/arch/x86/kernel/entry_64.S ++++ b/arch/x86/kernel/entry_64.S +@@ -1053,9 +1053,15 @@ ENTRY(native_iret) + jnz native_irq_return_ldt + #endif + ++.global native_irq_return_iret + native_irq_return_iret: ++ /* ++ * This may fault. Non-paranoid faults on return to userspace are ++ * handled by fixup_bad_iret. These include #SS, #GP, and #NP. ++ * Double-faults due to espfix64 are handled in do_double_fault. ++ * Other faults here are fatal. ++ */ + iretq +- _ASM_EXTABLE(native_irq_return_iret, bad_iret) + + #ifdef CONFIG_X86_ESPFIX64 + native_irq_return_ldt: +@@ -1083,25 +1089,6 @@ native_irq_return_ldt: + jmp native_irq_return_iret + #endif + +- .section .fixup,"ax" +-bad_iret: +- /* +- * The iret traps when the %cs or %ss being restored is bogus. +- * We've lost the original trap vector and error code. +- * #GPF is the most likely one to get for an invalid selector. +- * So pretend we completed the iret and took the #GPF in user mode. +- * +- * We are now running with the kernel GS after exception recovery. +- * But error_entry expects us to have user GS to match the user %cs, +- * so swap back. +- */ +- pushq $0 +- +- SWAPGS +- jmp general_protection +- +- .previous +- + /* edi: workmask, edx: work */ + retint_careful: + CFI_RESTORE_STATE +@@ -1147,37 +1134,6 @@ ENTRY(retint_kernel) + CFI_ENDPROC + END(common_interrupt) + +- /* +- * If IRET takes a fault on the espfix stack, then we +- * end up promoting it to a doublefault. In that case, +- * modify the stack to make it look like we just entered +- * the #GP handler from user space, similar to bad_iret. +- */ +-#ifdef CONFIG_X86_ESPFIX64 +- ALIGN +-__do_double_fault: +- XCPT_FRAME 1 RDI+8 +- movq RSP(%rdi),%rax /* Trap on the espfix stack? */ +- sarq $PGDIR_SHIFT,%rax +- cmpl $ESPFIX_PGD_ENTRY,%eax +- jne do_double_fault /* No, just deliver the fault */ +- cmpl $__KERNEL_CS,CS(%rdi) +- jne do_double_fault +- movq RIP(%rdi),%rax +- cmpq $native_irq_return_iret,%rax +- jne do_double_fault /* This shouldn't happen... */ +- movq PER_CPU_VAR(kernel_stack),%rax +- subq $(6*8-KERNEL_STACK_OFFSET),%rax /* Reset to original stack */ +- movq %rax,RSP(%rdi) +- movq $0,(%rax) /* Missing (lost) #GP error code */ +- movq $general_protection,RIP(%rdi) +- retq +- CFI_ENDPROC +-END(__do_double_fault) +-#else +-# define __do_double_fault do_double_fault +-#endif +- + /* + * End of kprobes section + */ +@@ -1379,7 +1335,7 @@ zeroentry overflow do_overflow + zeroentry bounds do_bounds + zeroentry invalid_op do_invalid_op + zeroentry device_not_available do_device_not_available +-paranoiderrorentry double_fault __do_double_fault ++paranoiderrorentry double_fault do_double_fault + zeroentry coprocessor_segment_overrun do_coprocessor_segment_overrun + errorentry invalid_TSS do_invalid_TSS + errorentry segment_not_present do_segment_not_present +@@ -1549,7 +1505,7 @@ apicinterrupt3 HYPERVISOR_CALLBACK_VECTOR \ + + paranoidzeroentry_ist debug do_debug DEBUG_STACK + paranoidzeroentry_ist int3 do_int3 DEBUG_STACK +-paranoiderrorentry stack_segment do_stack_segment ++errorentry stack_segment do_stack_segment + #ifdef CONFIG_XEN + zeroentry xen_debug do_debug + zeroentry xen_int3 do_int3 +@@ -1659,16 +1615,15 @@ error_sti: + + /* + * There are two places in the kernel that can potentially fault with +- * usergs. Handle them here. The exception handlers after iret run with +- * kernel gs again, so don't set the user space flag. B stepping K8s +- * sometimes report an truncated RIP for IRET exceptions returning to +- * compat mode. Check for these here too. ++ * usergs. Handle them here. B stepping K8s sometimes report a ++ * truncated RIP for IRET exceptions returning to compat mode. Check ++ * for these here too. + */ + error_kernelspace: + incl %ebx + leaq native_irq_return_iret(%rip),%rcx + cmpq %rcx,RIP+8(%rsp) +- je error_swapgs ++ je error_bad_iret + movl %ecx,%eax /* zero extend */ + cmpq %rax,RIP+8(%rsp) + je bstep_iret +@@ -1679,7 +1634,15 @@ error_kernelspace: + bstep_iret: + /* Fix truncated RIP */ + movq %rcx,RIP+8(%rsp) +- jmp error_swapgs ++ /* fall through */ ++ ++error_bad_iret: ++ SWAPGS ++ mov %rsp,%rdi ++ call fixup_bad_iret ++ mov %rax,%rsp ++ decl %ebx /* Return to usergs */ ++ jmp error_sti + CFI_ENDPROC + END(error_entry) + +diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c +index 57409f6b8c62..f9d976e0ae67 100644 +--- a/arch/x86/kernel/traps.c ++++ b/arch/x86/kernel/traps.c +@@ -218,32 +218,40 @@ DO_ERROR_INFO(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op, ILL + DO_ERROR (X86_TRAP_OLD_MF, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun ) + DO_ERROR (X86_TRAP_TS, SIGSEGV, "invalid TSS", invalid_TSS ) + DO_ERROR (X86_TRAP_NP, SIGBUS, "segment not present", segment_not_present ) +-#ifdef CONFIG_X86_32 + DO_ERROR (X86_TRAP_SS, SIGBUS, "stack segment", stack_segment ) +-#endif + DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0 ) + + #ifdef CONFIG_X86_64 + /* Runs on IST stack */ +-dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code) +-{ +- enum ctx_state prev_state; +- +- prev_state = exception_enter(); +- if (notify_die(DIE_TRAP, "stack segment", regs, error_code, +- X86_TRAP_SS, SIGBUS) != NOTIFY_STOP) { +- preempt_conditional_sti(regs); +- do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL); +- preempt_conditional_cli(regs); +- } +- exception_exit(prev_state); +-} +- + dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) + { + static const char str[] = "double fault"; + struct task_struct *tsk = current; + ++#ifdef CONFIG_X86_ESPFIX64 ++ extern unsigned char native_irq_return_iret[]; ++ ++ /* ++ * If IRET takes a non-IST fault on the espfix64 stack, then we ++ * end up promoting it to a doublefault. In that case, modify ++ * the stack to make it look like we just entered the #GP ++ * handler from user space, similar to bad_iret. ++ */ ++ if (((long)regs->sp >> PGDIR_SHIFT) == ESPFIX_PGD_ENTRY && ++ regs->cs == __KERNEL_CS && ++ regs->ip == (unsigned long)native_irq_return_iret) ++ { ++ struct pt_regs *normal_regs = task_pt_regs(current); ++ ++ /* Fake a #GP(0) from userspace. */ ++ memmove(&normal_regs->ip, (void *)regs->sp, 5*8); ++ normal_regs->orig_ax = 0; /* Missing (lost) #GP error code */ ++ regs->ip = (unsigned long)general_protection; ++ regs->sp = (unsigned long)&normal_regs->orig_ax; ++ return; ++ } ++#endif ++ + exception_enter(); + /* Return not checked because double check cannot be ignored */ + notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV); +@@ -376,6 +384,35 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) + *regs = *eregs; + return regs; + } ++ ++struct bad_iret_stack { ++ void *error_entry_ret; ++ struct pt_regs regs; ++}; ++ ++asmlinkage __visible ++struct bad_iret_stack *fixup_bad_iret(struct bad_iret_stack *s) ++{ ++ /* ++ * This is called from entry_64.S early in handling a fault ++ * caused by a bad iret to user mode. To handle the fault ++ * correctly, we want move our stack frame to task_pt_regs ++ * and we want to pretend that the exception came from the ++ * iret target. ++ */ ++ struct bad_iret_stack *new_stack = ++ container_of(task_pt_regs(current), ++ struct bad_iret_stack, regs); ++ ++ /* Copy the IRET target to the new stack. */ ++ memmove(&new_stack->regs.ip, (void *)s->regs.sp, 5*8); ++ ++ /* Copy the remainder of the stack from the current stack. */ ++ memmove(new_stack, s, offsetof(struct bad_iret_stack, regs.ip)); ++ ++ BUG_ON(!user_mode_vm(&new_stack->regs)); ++ return new_stack; ++} + #endif + + /* +@@ -748,7 +785,7 @@ void __init trap_init(void) + set_intr_gate(X86_TRAP_OLD_MF, coprocessor_segment_overrun); + set_intr_gate(X86_TRAP_TS, invalid_TSS); + set_intr_gate(X86_TRAP_NP, segment_not_present); +- set_intr_gate_ist(X86_TRAP_SS, &stack_segment, STACKFAULT_STACK); ++ set_intr_gate(X86_TRAP_SS, stack_segment); + set_intr_gate(X86_TRAP_GP, general_protection); + set_intr_gate(X86_TRAP_SPURIOUS, spurious_interrupt_bug); + set_intr_gate(X86_TRAP_MF, coprocessor_error); +diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c +index f35c66c5959a..2308a401a1c5 100644 +--- a/arch/x86/mm/init_64.c ++++ b/arch/x86/mm/init_64.c +@@ -1110,7 +1110,7 @@ void mark_rodata_ro(void) + unsigned long end = (unsigned long) &__end_rodata_hpage_align; + unsigned long text_end = PFN_ALIGN(&__stop___ex_table); + unsigned long rodata_end = PFN_ALIGN(&__end_rodata); +- unsigned long all_end = PFN_ALIGN(&_end); ++ unsigned long all_end; + + printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", + (end - start) >> 10); +@@ -1121,7 +1121,16 @@ void mark_rodata_ro(void) + /* + * The rodata/data/bss/brk section (but not the kernel text!) + * should also be not-executable. ++ * ++ * We align all_end to PMD_SIZE because the existing mapping ++ * is a full PMD. If we would align _brk_end to PAGE_SIZE we ++ * split the PMD and the reminder between _brk_end and the end ++ * of the PMD will remain mapped executable. ++ * ++ * Any PMD which was setup after the one which covers _brk_end ++ * has been zapped already via cleanup_highmem(). + */ ++ all_end = roundup((unsigned long)_brk_end, PMD_SIZE); + set_memory_nx(rodata_start, (all_end - rodata_start) >> PAGE_SHIFT); + + rodata_test(); +diff --git a/arch/x86/tools/calc_run_size.pl b/arch/x86/tools/calc_run_size.pl +index 0b0b124d3ece..23210baade2d 100644 +--- a/arch/x86/tools/calc_run_size.pl ++++ b/arch/x86/tools/calc_run_size.pl +@@ -19,7 +19,16 @@ while (<>) { + if ($file_offset == 0) { + $file_offset = $offset; + } elsif ($file_offset != $offset) { +- die ".bss and .brk lack common file offset\n"; ++ # BFD linker shows the same file offset in ELF. ++ # Gold linker shows them as consecutive. ++ next if ($file_offset + $mem_size == $offset + $size); ++ ++ printf STDERR "file_offset: 0x%lx\n", $file_offset; ++ printf STDERR "mem_size: 0x%lx\n", $mem_size; ++ printf STDERR "offset: 0x%lx\n", $offset; ++ printf STDERR "size: 0x%lx\n", $size; ++ ++ die ".bss and .brk are non-contiguous\n"; + } + } + } +diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c +index bf497afba9ad..7d19f86012f2 100644 +--- a/drivers/clocksource/sun4i_timer.c ++++ b/drivers/clocksource/sun4i_timer.c +@@ -182,6 +182,12 @@ static void __init sun4i_timer_init(struct device_node *node) + /* Make sure timer is stopped before playing with interrupts */ + sun4i_clkevt_time_stop(0); + ++ sun4i_clockevent.cpumask = cpu_possible_mask; ++ sun4i_clockevent.irq = irq; ++ ++ clockevents_config_and_register(&sun4i_clockevent, rate, ++ TIMER_SYNC_TICKS, 0xffffffff); ++ + ret = setup_irq(irq, &sun4i_timer_irq); + if (ret) + pr_warn("failed to setup irq %d\n", irq); +@@ -189,12 +195,6 @@ static void __init sun4i_timer_init(struct device_node *node) + /* Enable timer0 interrupt */ + val = readl(timer_base + TIMER_IRQ_EN_REG); + writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); +- +- sun4i_clockevent.cpumask = cpu_possible_mask; +- sun4i_clockevent.irq = irq; +- +- clockevents_config_and_register(&sun4i_clockevent, rate, +- TIMER_SYNC_TICKS, 0xffffffff); + } + CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-timer", + sun4i_timer_init); +diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c +index 813db8de52b7..3334f916945b 100644 +--- a/drivers/gpu/drm/radeon/r600_dpm.c ++++ b/drivers/gpu/drm/radeon/r600_dpm.c +@@ -1209,7 +1209,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); + rdev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = +- ppt->usMaximumPowerDeliveryLimit; ++ le16_to_cpu(ppt->usMaximumPowerDeliveryLimit); + pt = &ppt->power_tune_table; + } else { + ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *) +diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c +index 089c9ffb0aa9..b3f0293ba0d8 100644 +--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c ++++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c +@@ -202,6 +202,16 @@ static bool radeon_msi_ok(struct radeon_device *rdev) + if (rdev->flags & RADEON_IS_AGP) + return false; + ++ /* ++ * Older chips have a HW limitation, they can only generate 40 bits ++ * of address for "64-bit" MSIs which breaks on some platforms, notably ++ * IBM POWER servers, so we limit them ++ */ ++ if (rdev->family < CHIP_BONAIRE) { ++ dev_info(rdev->dev, "radeon: MSI limited to 32-bit\n"); ++ rdev->pdev->no_64bit_msi = 1; ++ } ++ + /* force MSI on */ + if (radeon_msi == 1) + return true; +diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c +index c5c194c2e0b6..a96cfc31372e 100644 +--- a/drivers/infiniband/ulp/isert/ib_isert.c ++++ b/drivers/infiniband/ulp/isert/ib_isert.c +@@ -112,9 +112,12 @@ isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id) + attr.cap.max_recv_wr = ISERT_QP_MAX_RECV_DTOS; + /* + * FIXME: Use devattr.max_sge - 2 for max_send_sge as +- * work-around for RDMA_READ.. ++ * work-around for RDMA_READs with ConnectX-2. ++ * ++ * Also, still make sure to have at least two SGEs for ++ * outgoing control PDU responses. + */ +- attr.cap.max_send_sge = device->dev_attr.max_sge - 2; ++ attr.cap.max_send_sge = max(2, device->dev_attr.max_sge - 2); + isert_conn->max_sge = attr.cap.max_send_sge; + + attr.cap.max_recv_sge = 1; +@@ -220,12 +223,16 @@ isert_create_device_ib_res(struct isert_device *device) + struct isert_cq_desc *cq_desc; + struct ib_device_attr *dev_attr; + int ret = 0, i, j; ++ int max_rx_cqe, max_tx_cqe; + + dev_attr = &device->dev_attr; + ret = isert_query_device(ib_dev, dev_attr); + if (ret) + return ret; + ++ max_rx_cqe = min(ISER_MAX_RX_CQ_LEN, dev_attr->max_cqe); ++ max_tx_cqe = min(ISER_MAX_TX_CQ_LEN, dev_attr->max_cqe); ++ + /* asign function handlers */ + if (dev_attr->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS) { + device->use_fastreg = 1; +@@ -261,7 +268,7 @@ isert_create_device_ib_res(struct isert_device *device) + isert_cq_rx_callback, + isert_cq_event_callback, + (void *)&cq_desc[i], +- ISER_MAX_RX_CQ_LEN, i); ++ max_rx_cqe, i); + if (IS_ERR(device->dev_rx_cq[i])) { + ret = PTR_ERR(device->dev_rx_cq[i]); + device->dev_rx_cq[i] = NULL; +@@ -273,7 +280,7 @@ isert_create_device_ib_res(struct isert_device *device) + isert_cq_tx_callback, + isert_cq_event_callback, + (void *)&cq_desc[i], +- ISER_MAX_TX_CQ_LEN, i); ++ max_tx_cqe, i); + if (IS_ERR(device->dev_tx_cq[i])) { + ret = PTR_ERR(device->dev_tx_cq[i]); + device->dev_tx_cq[i] = NULL; +@@ -718,14 +725,25 @@ wake_up: + complete(&isert_conn->conn_wait); + } + +-static void ++static int + isert_disconnected_handler(struct rdma_cm_id *cma_id, bool disconnect) + { +- struct isert_conn *isert_conn = (struct isert_conn *)cma_id->context; ++ struct isert_conn *isert_conn; ++ ++ if (!cma_id->qp) { ++ struct isert_np *isert_np = cma_id->context; ++ ++ isert_np->np_cm_id = NULL; ++ return -1; ++ } ++ ++ isert_conn = (struct isert_conn *)cma_id->context; + + isert_conn->disconnect = disconnect; + INIT_WORK(&isert_conn->conn_logout_work, isert_disconnect_work); + schedule_work(&isert_conn->conn_logout_work); ++ ++ return 0; + } + + static int +@@ -740,6 +758,9 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + switch (event->event) { + case RDMA_CM_EVENT_CONNECT_REQUEST: + ret = isert_connect_request(cma_id, event); ++ if (ret) ++ pr_err("isert_cma_handler failed RDMA_CM_EVENT: 0x%08x %d\n", ++ event->event, ret); + break; + case RDMA_CM_EVENT_ESTABLISHED: + isert_connected_handler(cma_id); +@@ -749,7 +770,7 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + case RDMA_CM_EVENT_DEVICE_REMOVAL: /* FALLTHRU */ + disconnect = true; + case RDMA_CM_EVENT_TIMEWAIT_EXIT: /* FALLTHRU */ +- isert_disconnected_handler(cma_id, disconnect); ++ ret = isert_disconnected_handler(cma_id, disconnect); + break; + case RDMA_CM_EVENT_CONNECT_ERROR: + default: +@@ -757,12 +778,6 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + break; + } + +- if (ret != 0) { +- pr_err("isert_cma_handler failed RDMA_CM_EVENT: 0x%08x %d\n", +- event->event, ret); +- dump_stack(); +- } +- + return ret; + } + +@@ -970,7 +985,8 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login, + } + if (!login->login_failed) { + if (login->login_complete) { +- if (isert_conn->conn_device->use_fastreg) { ++ if (!conn->sess->sess_ops->SessionType && ++ isert_conn->conn_device->use_fastreg) { + ret = isert_conn_create_fastreg_pool(isert_conn); + if (ret) { + pr_err("Conn: %p failed to create" +@@ -1937,7 +1953,7 @@ isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd) + isert_cmd->tx_desc.num_sge = 2; + } + +- isert_init_send_wr(isert_conn, isert_cmd, send_wr, true); ++ isert_init_send_wr(isert_conn, isert_cmd, send_wr, false); + + pr_debug("Posting SCSI Response IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n"); + +@@ -2456,7 +2472,7 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd) + &isert_cmd->tx_desc.iscsi_header); + isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); + isert_init_send_wr(isert_conn, isert_cmd, +- &isert_cmd->tx_desc.send_wr, true); ++ &isert_cmd->tx_desc.send_wr, false); + + atomic_add(wr->send_wr_num + 1, &isert_conn->post_send_buf_count); + +@@ -2768,7 +2784,8 @@ isert_free_np(struct iscsi_np *np) + { + struct isert_np *isert_np = (struct isert_np *)np->np_context; + +- rdma_destroy_id(isert_np->np_cm_id); ++ if (isert_np->np_cm_id) ++ rdma_destroy_id(isert_np->np_cm_id); + + np->np_context = NULL; + kfree(isert_np); +diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c +index d1078ce73095..0097b8dae5bc 100644 +--- a/drivers/infiniband/ulp/srpt/ib_srpt.c ++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c +@@ -2091,6 +2091,7 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch) + if (!qp_init) + goto out; + ++retry: + ch->cq = ib_create_cq(sdev->device, srpt_completion, NULL, ch, + ch->rq_size + srp_sq_size, 0); + if (IS_ERR(ch->cq)) { +@@ -2114,6 +2115,13 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch) + ch->qp = ib_create_qp(sdev->pd, qp_init); + if (IS_ERR(ch->qp)) { + ret = PTR_ERR(ch->qp); ++ if (ret == -ENOMEM) { ++ srp_sq_size /= 2; ++ if (srp_sq_size >= MIN_SRPT_SQ_SIZE) { ++ ib_destroy_cq(ch->cq); ++ goto retry; ++ } ++ } + printk(KERN_ERR "failed to create_qp ret= %d\n", ret); + goto err_destroy_cq; + } +diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c +index 603fe0dd3682..517829f6a58b 100644 +--- a/drivers/input/joystick/xpad.c ++++ b/drivers/input/joystick/xpad.c +@@ -1003,9 +1003,19 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id + } + + ep_irq_in = &intf->cur_altsetting->endpoint[1].desc; +- usb_fill_bulk_urb(xpad->bulk_out, udev, +- usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress), +- xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad); ++ if (usb_endpoint_is_bulk_out(ep_irq_in)) { ++ usb_fill_bulk_urb(xpad->bulk_out, udev, ++ usb_sndbulkpipe(udev, ++ ep_irq_in->bEndpointAddress), ++ xpad->bdata, XPAD_PKT_LEN, ++ xpad_bulk_out, xpad); ++ } else { ++ usb_fill_int_urb(xpad->bulk_out, udev, ++ usb_sndintpipe(udev, ++ ep_irq_in->bEndpointAddress), ++ xpad->bdata, XPAD_PKT_LEN, ++ xpad_bulk_out, xpad, 0); ++ } + + /* + * Submit the int URB immediately rather than waiting for open +diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c +index 1e76eb8f06c7..a3769cf84381 100644 +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -140,6 +140,10 @@ static const struct min_max_quirk min_max_pnpid_table[] = { + (const char * const []){"LEN2001", NULL}, + 1024, 5022, 2508, 4832 + }, ++ { ++ (const char * const []){"LEN2006", NULL}, ++ 1264, 5675, 1171, 4688 ++ }, + { } + }; + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index cc38948cf65d..15379824d77d 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -2450,9 +2450,9 @@ static void bond_loadbalance_arp_mon(struct work_struct *work) + if (!rtnl_trylock()) + goto re_arm; + +- if (slave_state_changed) { ++ if (slave_state_changed) + bond_slave_state_change(bond); +- } else if (do_failover) { ++ if (do_failover) { + /* the bond_select_active_slave must hold RTNL + * and curr_slave_lock for write. + */ +diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c +index fc59bc6f040b..cc11f7f5e91d 100644 +--- a/drivers/net/can/dev.c ++++ b/drivers/net/can/dev.c +@@ -384,7 +384,7 @@ void can_free_echo_skb(struct net_device *dev, unsigned int idx) + BUG_ON(idx >= priv->echo_skb_max); + + if (priv->echo_skb[idx]) { +- kfree_skb(priv->echo_skb[idx]); ++ dev_kfree_skb_any(priv->echo_skb[idx]); + priv->echo_skb[idx] = NULL; + } + } +diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c +index 7fbe85935f1d..f34f7fa1f901 100644 +--- a/drivers/net/can/usb/esd_usb2.c ++++ b/drivers/net/can/usb/esd_usb2.c +@@ -1141,6 +1141,7 @@ static void esd_usb2_disconnect(struct usb_interface *intf) + } + } + unlink_all_urbs(dev); ++ kfree(dev); + } + } + +diff --git a/drivers/net/ieee802154/fakehard.c b/drivers/net/ieee802154/fakehard.c +index bf0d55e2dd63..6adbef89c4b0 100644 +--- a/drivers/net/ieee802154/fakehard.c ++++ b/drivers/net/ieee802154/fakehard.c +@@ -376,17 +376,20 @@ static int ieee802154fake_probe(struct platform_device *pdev) + + err = wpan_phy_register(phy); + if (err) +- goto out; ++ goto err_phy_reg; + + err = register_netdev(dev); +- if (err < 0) +- goto out; ++ if (err) ++ goto err_netdev_reg; + + dev_info(&pdev->dev, "Added ieee802154 HardMAC hardware\n"); + return 0; + +-out: +- unregister_netdev(dev); ++err_netdev_reg: ++ wpan_phy_unregister(phy); ++err_phy_reg: ++ free_netdev(dev); ++ wpan_phy_free(phy); + return err; + } + +diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c +index 1aff970be33e..1dc628ffce2b 100644 +--- a/drivers/net/ppp/pptp.c ++++ b/drivers/net/ppp/pptp.c +@@ -506,7 +506,9 @@ static int pptp_getname(struct socket *sock, struct sockaddr *uaddr, + int len = sizeof(struct sockaddr_pppox); + struct sockaddr_pppox sp; + +- sp.sa_family = AF_PPPOX; ++ memset(&sp.sa_addr, 0, sizeof(sp.sa_addr)); ++ ++ sp.sa_family = AF_PPPOX; + sp.sa_protocol = PX_PROTO_PPTP; + sp.sa_addr.pptp = pppox_sk(sock->sk)->proto.pptp.src_addr; + +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index d510f1d41bae..db21af8de9f6 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -769,6 +769,7 @@ static const struct usb_device_id products[] = { + {QMI_FIXED_INTF(0x413c, 0x81a4, 8)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ + {QMI_FIXED_INTF(0x413c, 0x81a8, 8)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */ + {QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */ ++ {QMI_FIXED_INTF(0x03f0, 0x581d, 4)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */ + + /* 4. Gobi 1000 devices */ + {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ +diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +index 09facba1dc6d..390c2de5a73e 100644 +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -647,6 +647,19 @@ static void ar9003_hw_override_ini(struct ath_hw *ah) + ah->enabled_cals |= TX_CL_CAL; + else + ah->enabled_cals &= ~TX_CL_CAL; ++ ++ if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) { ++ if (ah->is_clk_25mhz) { ++ REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); ++ REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); ++ REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae); ++ } else { ++ REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1); ++ REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400); ++ REG_WRITE(ah, AR_SLP32_INC, 0x0001e800); ++ } ++ udelay(100); ++ } + } + + static void ar9003_hw_prog_ini(struct ath_hw *ah, +diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c +index 9078a6c5a74e..dcc14940c9df 100644 +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -858,19 +858,6 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, + udelay(RTC_PLL_SETTLE_DELAY); + + REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); +- +- if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) { +- if (ah->is_clk_25mhz) { +- REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); +- REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); +- REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae); +- } else { +- REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1); +- REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400); +- REG_WRITE(ah, AR_SLP32_INC, 0x0001e800); +- } +- udelay(100); +- } + } + + static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, +diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c +index 5642ccceca7c..22d49d575d3f 100644 +--- a/drivers/net/wireless/rt2x00/rt2x00queue.c ++++ b/drivers/net/wireless/rt2x00/rt2x00queue.c +@@ -158,55 +158,29 @@ void rt2x00queue_align_frame(struct sk_buff *skb) + skb_trim(skb, frame_length); + } + +-void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) ++/* ++ * H/W needs L2 padding between the header and the paylod if header size ++ * is not 4 bytes aligned. ++ */ ++void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int hdr_len) + { +- unsigned int payload_length = skb->len - header_length; +- unsigned int header_align = ALIGN_SIZE(skb, 0); +- unsigned int payload_align = ALIGN_SIZE(skb, header_length); +- unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0; ++ unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0; + +- /* +- * Adjust the header alignment if the payload needs to be moved more +- * than the header. +- */ +- if (payload_align > header_align) +- header_align += 4; +- +- /* There is nothing to do if no alignment is needed */ +- if (!header_align) ++ if (!l2pad) + return; + +- /* Reserve the amount of space needed in front of the frame */ +- skb_push(skb, header_align); +- +- /* +- * Move the header. +- */ +- memmove(skb->data, skb->data + header_align, header_length); +- +- /* Move the payload, if present and if required */ +- if (payload_length && payload_align) +- memmove(skb->data + header_length + l2pad, +- skb->data + header_length + l2pad + payload_align, +- payload_length); +- +- /* Trim the skb to the correct size */ +- skb_trim(skb, header_length + l2pad + payload_length); ++ skb_push(skb, l2pad); ++ memmove(skb->data, skb->data + l2pad, hdr_len); + } + +-void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) ++void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int hdr_len) + { +- /* +- * L2 padding is only present if the skb contains more than just the +- * IEEE 802.11 header. +- */ +- unsigned int l2pad = (skb->len > header_length) ? +- L2PAD_SIZE(header_length) : 0; ++ unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0; + + if (!l2pad) + return; + +- memmove(skb->data + l2pad, skb->data, header_length); ++ memmove(skb->data + l2pad, skb->data, hdr_len); + skb_pull(skb, l2pad); + } + +diff --git a/drivers/of/address.c b/drivers/of/address.c +index 1a54f1ffaadb..005c65715846 100644 +--- a/drivers/of/address.c ++++ b/drivers/of/address.c +@@ -401,6 +401,21 @@ static struct of_bus *of_match_bus(struct device_node *np) + return NULL; + } + ++static int of_empty_ranges_quirk(void) ++{ ++ if (IS_ENABLED(CONFIG_PPC)) { ++ /* To save cycles, we cache the result */ ++ static int quirk_state = -1; ++ ++ if (quirk_state < 0) ++ quirk_state = ++ of_machine_is_compatible("Power Macintosh") || ++ of_machine_is_compatible("MacRISC"); ++ return quirk_state; ++ } ++ return false; ++} ++ + static int of_translate_one(struct device_node *parent, struct of_bus *bus, + struct of_bus *pbus, __be32 *addr, + int na, int ns, int pna, const char *rprop) +@@ -426,12 +441,10 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, + * This code is only enabled on powerpc. --gcl + */ + ranges = of_get_property(parent, rprop, &rlen); +-#if !defined(CONFIG_PPC) +- if (ranges == NULL) { ++ if (ranges == NULL && !of_empty_ranges_quirk()) { + pr_err("OF: no ranges; cannot translate\n"); + return 1; + } +-#endif /* !defined(CONFIG_PPC) */ + if (ranges == NULL || rlen == 0) { + offset = of_read_number(addr, na); + memset(addr, 0, pna * 4); +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index fb02fc2fb034..ced17f2ac782 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -599,6 +599,20 @@ error_attrs: + return ret; + } + ++static int msi_verify_entries(struct pci_dev *dev) ++{ ++ struct msi_desc *entry; ++ ++ list_for_each_entry(entry, &dev->msi_list, list) { ++ if (!dev->no_64bit_msi || !entry->msg.address_hi) ++ continue; ++ dev_err(&dev->dev, "Device has broken 64-bit MSI but arch" ++ " tried to assign one above 4G\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ + /** + * msi_capability_init - configure device's MSI capability structure + * @dev: pointer to the pci_dev data structure of MSI device function +@@ -652,6 +666,13 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) + return ret; + } + ++ ret = msi_verify_entries(dev); ++ if (ret) { ++ msi_mask_irq(entry, mask, ~mask); ++ free_msi_irqs(dev); ++ return ret; ++ } ++ + ret = populate_msi_sysfs(dev); + if (ret) { + msi_mask_irq(entry, mask, ~mask); +@@ -767,6 +788,11 @@ static int msix_capability_init(struct pci_dev *dev, + if (ret) + goto out_avail; + ++ /* Check if all MSI entries honor device restrictions */ ++ ret = msi_verify_entries(dev); ++ if (ret) ++ goto out_free; ++ + /* + * Some devices require MSI-X to be enabled before we can touch the + * MSI-X registers. We need to mask all the vectors to prevent +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index 6e34498ec9f0..34dff3a09b98 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -395,15 +395,16 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child) + { + struct pci_dev *dev = child->self; + u16 mem_base_lo, mem_limit_lo; +- unsigned long base, limit; ++ u64 base64, limit64; ++ dma_addr_t base, limit; + struct pci_bus_region region; + struct resource *res; + + res = child->resource[2]; + pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); + pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); +- base = ((unsigned long) mem_base_lo & PCI_PREF_RANGE_MASK) << 16; +- limit = ((unsigned long) mem_limit_lo & PCI_PREF_RANGE_MASK) << 16; ++ base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16; ++ limit64 = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16; + + if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { + u32 mem_base_hi, mem_limit_hi; +@@ -417,18 +418,20 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child) + * this, just assume they are not being used. + */ + if (mem_base_hi <= mem_limit_hi) { +-#if BITS_PER_LONG == 64 +- base |= ((unsigned long) mem_base_hi) << 32; +- limit |= ((unsigned long) mem_limit_hi) << 32; +-#else +- if (mem_base_hi || mem_limit_hi) { +- dev_err(&dev->dev, "can't handle 64-bit " +- "address space for bridge\n"); +- return; +- } +-#endif ++ base64 |= (u64) mem_base_hi << 32; ++ limit64 |= (u64) mem_limit_hi << 32; + } + } ++ ++ base = (dma_addr_t) base64; ++ limit = (dma_addr_t) limit64; ++ ++ if (base != base64) { ++ dev_err(&dev->dev, "can't handle bridge window above 4GB (bus address %#010llx)\n", ++ (unsigned long long) base64); ++ return; ++ } ++ + if (base <= limit) { + res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) | + IORESOURCE_MEM | IORESOURCE_PREFETCH; +diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +index 9b948505d118..cc6b13b81c53 100644 +--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c ++++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +@@ -411,6 +411,7 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev, + struct fc_frame_header *fh; + struct fcoe_rcv_info *fr; + struct fcoe_percpu_s *bg; ++ struct sk_buff *tmp_skb; + unsigned short oxid; + + interface = container_of(ptype, struct bnx2fc_interface, +@@ -423,6 +424,12 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev, + goto err; + } + ++ tmp_skb = skb_share_check(skb, GFP_ATOMIC); ++ if (!tmp_skb) ++ goto err; ++ ++ skb = tmp_skb; ++ + if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) { + printk(KERN_ERR PFX "bnx2fc_rcv: Wrong FC type frame\n"); + goto err; +diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c +index 49014a143c6a..c1d04d4d3c6c 100644 +--- a/drivers/scsi/scsi_devinfo.c ++++ b/drivers/scsi/scsi_devinfo.c +@@ -202,6 +202,7 @@ static struct { + {"IOMEGA", "Io20S *F", NULL, BLIST_KEY}, + {"INSITE", "Floptical F*8I", NULL, BLIST_KEY}, + {"INSITE", "I325VM", NULL, BLIST_KEY}, ++ {"Intel", "Multi-Flex", NULL, BLIST_NO_RSOC}, + {"iRiver", "iFP Mass Driver", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36}, + {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN}, + {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, +diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c +index e63d27013142..e543b80d610e 100644 +--- a/drivers/spi/spi-dw.c ++++ b/drivers/spi/spi-dw.c +@@ -394,9 +394,6 @@ static void pump_transfers(unsigned long data) + chip = dws->cur_chip; + spi = message->spi; + +- if (unlikely(!chip->clk_div)) +- chip->clk_div = dws->max_freq / chip->speed_hz; +- + if (message->state == ERROR_STATE) { + message->status = -EIO; + goto early_exit; +@@ -437,7 +434,7 @@ static void pump_transfers(unsigned long data) + if (transfer->speed_hz) { + speed = chip->speed_hz; + +- if (transfer->speed_hz != speed) { ++ if ((transfer->speed_hz != speed) || (!chip->clk_div)) { + speed = transfer->speed_hz; + if (speed > dws->max_freq) { + printk(KERN_ERR "MRST SPI0: unsupported" +@@ -659,7 +656,6 @@ static int dw_spi_setup(struct spi_device *spi) + dev_err(&spi->dev, "No max speed HZ parameter\n"); + return -EINVAL; + } +- chip->speed_hz = spi->max_speed_hz; + + chip->tmode = 0; /* Tx & Rx */ + /* Default SPI mode is SCPOL = 0, SCPH = 0 */ +diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c +index fed699fc5918..2185a71055f2 100644 +--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c ++++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c +@@ -57,6 +57,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = { + {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */ + {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(0x0df6, 0x0076)}, /* Sitecom N150 v2 */ + {} /* Terminating entry */ + }; +diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c +index 9232c7738ed1..e6463ef33cd2 100644 +--- a/drivers/target/target_core_transport.c ++++ b/drivers/target/target_core_transport.c +@@ -2230,7 +2230,7 @@ transport_generic_new_cmd(struct se_cmd *cmd) + * and let it call back once the write buffers are ready. + */ + target_add_to_state_list(cmd); +- if (cmd->data_direction != DMA_TO_DEVICE) { ++ if (cmd->data_direction != DMA_TO_DEVICE || cmd->data_length == 0) { + target_execute_cmd(cmd); + return 0; + } +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index c85459338991..b195fdb1effc 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -44,6 +44,9 @@ static const struct usb_device_id usb_quirk_list[] = { + /* Creative SB Audigy 2 NX */ + { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* Microsoft Wireless Laser Mouse 6000 Receiver */ ++ { USB_DEVICE(0x045e, 0x00e1), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* Microsoft LifeCam-VX700 v2.0 */ + { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, + +diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c +index 75cb1ff9d26b..73c43e5e231b 100644 +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -281,7 +281,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) + if (xhci_compliance_mode_recovery_timer_quirk_check()) + pdev->no_d3cold = true; + +- return xhci_suspend(xhci); ++ return xhci_suspend(xhci, do_wakeup); + } + + static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index 8abda5c73ca1..1d5ba3c299cc 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -205,7 +205,15 @@ static int xhci_plat_suspend(struct device *dev) + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + +- return xhci_suspend(xhci); ++ /* ++ * xhci_suspend() needs `do_wakeup` to know whether host is allowed ++ * to do wakeup during suspend. Since xhci_plat_suspend is currently ++ * only designed for system suspend, device_may_wakeup() is enough ++ * to dertermine whether host is allowed to do wakeup. Need to ++ * reconsider this when xhci_plat_suspend enlarges its scope, e.g., ++ * also applies to runtime suspend. ++ */ ++ return xhci_suspend(xhci, device_may_wakeup(dev)); + } + + static int xhci_plat_resume(struct device *dev) +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index 0e6665a82e88..1710a8678bcb 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1180,9 +1180,8 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id, + false); + xhci_ring_cmd_db(xhci); + } else { +- /* Clear our internal halted state and restart the ring(s) */ ++ /* Clear our internal halted state */ + xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_HALTED; +- ring_doorbell_for_active_rings(xhci, slot_id, ep_index); + } + } + +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 82b563fc4fd6..17e398748a2d 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -35,6 +35,8 @@ + #define DRIVER_AUTHOR "Sarah Sharp" + #define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver" + ++#define PORT_WAKE_BITS (PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E) ++ + /* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */ + static int link_quirk; + module_param(link_quirk, int, S_IRUGO | S_IWUSR); +@@ -842,13 +844,47 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci) + xhci_set_cmd_ring_deq(xhci); + } + ++static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci) ++{ ++ int port_index; ++ __le32 __iomem **port_array; ++ unsigned long flags; ++ u32 t1, t2; ++ ++ spin_lock_irqsave(&xhci->lock, flags); ++ ++ /* disble usb3 ports Wake bits*/ ++ port_index = xhci->num_usb3_ports; ++ port_array = xhci->usb3_ports; ++ while (port_index--) { ++ t1 = readl(port_array[port_index]); ++ t1 = xhci_port_state_to_neutral(t1); ++ t2 = t1 & ~PORT_WAKE_BITS; ++ if (t1 != t2) ++ writel(t2, port_array[port_index]); ++ } ++ ++ /* disble usb2 ports Wake bits*/ ++ port_index = xhci->num_usb2_ports; ++ port_array = xhci->usb2_ports; ++ while (port_index--) { ++ t1 = readl(port_array[port_index]); ++ t1 = xhci_port_state_to_neutral(t1); ++ t2 = t1 & ~PORT_WAKE_BITS; ++ if (t1 != t2) ++ writel(t2, port_array[port_index]); ++ } ++ ++ spin_unlock_irqrestore(&xhci->lock, flags); ++} ++ + /* + * Stop HC (not bus-specific) + * + * This is called when the machine transition into S3/S4 mode. + * + */ +-int xhci_suspend(struct xhci_hcd *xhci) ++int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) + { + int rc = 0; + unsigned int delay = XHCI_MAX_HALT_USEC; +@@ -859,6 +895,10 @@ int xhci_suspend(struct xhci_hcd *xhci) + xhci->shared_hcd->state != HC_STATE_SUSPENDED) + return -EINVAL; + ++ /* Clear root port wake on bits if wakeup not allowed. */ ++ if (!do_wakeup) ++ xhci_disable_port_wake_on_bits(xhci); ++ + /* Don't poll the roothubs on bus suspend. */ + xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 8faef64371c6..96e9e780ccae 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1760,7 +1760,7 @@ void xhci_shutdown(struct usb_hcd *hcd); + int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks); + + #ifdef CONFIG_PM +-int xhci_suspend(struct xhci_hcd *xhci); ++int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup); + int xhci_resume(struct xhci_hcd *xhci, bool hibernated); + #else + #define xhci_suspend NULL +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 3beae723ad3a..5741e9405069 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -120,6 +120,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */ + { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */ + { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ ++ { USB_DEVICE(0x10C4, 0x8875) }, /* CEL MeshConnect USB Stick */ + { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */ +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index a523adad6380..debcdef4cbf0 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -483,6 +483,39 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FD_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FE_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FF_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_4701_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9300_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9301_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9302_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9303_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9304_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9305_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9306_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9307_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9308_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9309_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930A_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930B_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930C_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930D_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930E_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930F_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9310_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9311_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9312_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9313_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9314_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9315_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9316_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9317_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9318_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9319_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931A_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931B_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931C_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931D_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931E_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931F_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) }, +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index 6786b705ccf6..e52409c9be99 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -926,8 +926,8 @@ + #define BAYER_CONTOUR_CABLE_PID 0x6001 + + /* +- * The following are the values for the Matrix Orbital FTDI Range +- * Anything in this range will use an FT232RL. ++ * Matrix Orbital Intelligent USB displays. ++ * http://www.matrixorbital.com + */ + #define MTXORB_VID 0x1B3D + #define MTXORB_FTDI_RANGE_0100_PID 0x0100 +@@ -1186,8 +1186,39 @@ + #define MTXORB_FTDI_RANGE_01FD_PID 0x01FD + #define MTXORB_FTDI_RANGE_01FE_PID 0x01FE + #define MTXORB_FTDI_RANGE_01FF_PID 0x01FF +- +- ++#define MTXORB_FTDI_RANGE_4701_PID 0x4701 ++#define MTXORB_FTDI_RANGE_9300_PID 0x9300 ++#define MTXORB_FTDI_RANGE_9301_PID 0x9301 ++#define MTXORB_FTDI_RANGE_9302_PID 0x9302 ++#define MTXORB_FTDI_RANGE_9303_PID 0x9303 ++#define MTXORB_FTDI_RANGE_9304_PID 0x9304 ++#define MTXORB_FTDI_RANGE_9305_PID 0x9305 ++#define MTXORB_FTDI_RANGE_9306_PID 0x9306 ++#define MTXORB_FTDI_RANGE_9307_PID 0x9307 ++#define MTXORB_FTDI_RANGE_9308_PID 0x9308 ++#define MTXORB_FTDI_RANGE_9309_PID 0x9309 ++#define MTXORB_FTDI_RANGE_930A_PID 0x930A ++#define MTXORB_FTDI_RANGE_930B_PID 0x930B ++#define MTXORB_FTDI_RANGE_930C_PID 0x930C ++#define MTXORB_FTDI_RANGE_930D_PID 0x930D ++#define MTXORB_FTDI_RANGE_930E_PID 0x930E ++#define MTXORB_FTDI_RANGE_930F_PID 0x930F ++#define MTXORB_FTDI_RANGE_9310_PID 0x9310 ++#define MTXORB_FTDI_RANGE_9311_PID 0x9311 ++#define MTXORB_FTDI_RANGE_9312_PID 0x9312 ++#define MTXORB_FTDI_RANGE_9313_PID 0x9313 ++#define MTXORB_FTDI_RANGE_9314_PID 0x9314 ++#define MTXORB_FTDI_RANGE_9315_PID 0x9315 ++#define MTXORB_FTDI_RANGE_9316_PID 0x9316 ++#define MTXORB_FTDI_RANGE_9317_PID 0x9317 ++#define MTXORB_FTDI_RANGE_9318_PID 0x9318 ++#define MTXORB_FTDI_RANGE_9319_PID 0x9319 ++#define MTXORB_FTDI_RANGE_931A_PID 0x931A ++#define MTXORB_FTDI_RANGE_931B_PID 0x931B ++#define MTXORB_FTDI_RANGE_931C_PID 0x931C ++#define MTXORB_FTDI_RANGE_931D_PID 0x931D ++#define MTXORB_FTDI_RANGE_931E_PID 0x931E ++#define MTXORB_FTDI_RANGE_931F_PID 0x931F + + /* + * The Mobility Lab (TML) +diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c +index 265c6776b081..49101fe45d38 100644 +--- a/drivers/usb/serial/keyspan.c ++++ b/drivers/usb/serial/keyspan.c +@@ -311,24 +311,30 @@ static void usa26_indat_callback(struct urb *urb) + if ((data[0] & 0x80) == 0) { + /* no errors on individual bytes, only + possible overrun err */ +- if (data[0] & RXERROR_OVERRUN) +- err = TTY_OVERRUN; +- else +- err = 0; ++ if (data[0] & RXERROR_OVERRUN) { ++ tty_insert_flip_char(&port->port, 0, ++ TTY_OVERRUN); ++ } + for (i = 1; i < urb->actual_length ; ++i) +- tty_insert_flip_char(&port->port, data[i], err); ++ tty_insert_flip_char(&port->port, data[i], ++ TTY_NORMAL); + } else { + /* some bytes had errors, every byte has status */ + dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__); + for (i = 0; i + 1 < urb->actual_length; i += 2) { +- int stat = data[i], flag = 0; +- if (stat & RXERROR_OVERRUN) +- flag |= TTY_OVERRUN; +- if (stat & RXERROR_FRAMING) +- flag |= TTY_FRAME; +- if (stat & RXERROR_PARITY) +- flag |= TTY_PARITY; ++ int stat = data[i]; ++ int flag = TTY_NORMAL; ++ ++ if (stat & RXERROR_OVERRUN) { ++ tty_insert_flip_char(&port->port, 0, ++ TTY_OVERRUN); ++ } + /* XXX should handle break (0x10) */ ++ if (stat & RXERROR_PARITY) ++ flag = TTY_PARITY; ++ else if (stat & RXERROR_FRAMING) ++ flag = TTY_FRAME; ++ + tty_insert_flip_char(&port->port, data[i+1], + flag); + } +@@ -666,14 +672,19 @@ static void usa49_indat_callback(struct urb *urb) + } else { + /* some bytes had errors, every byte has status */ + for (i = 0; i + 1 < urb->actual_length; i += 2) { +- int stat = data[i], flag = 0; +- if (stat & RXERROR_OVERRUN) +- flag |= TTY_OVERRUN; +- if (stat & RXERROR_FRAMING) +- flag |= TTY_FRAME; +- if (stat & RXERROR_PARITY) +- flag |= TTY_PARITY; ++ int stat = data[i]; ++ int flag = TTY_NORMAL; ++ ++ if (stat & RXERROR_OVERRUN) { ++ tty_insert_flip_char(&port->port, 0, ++ TTY_OVERRUN); ++ } + /* XXX should handle break (0x10) */ ++ if (stat & RXERROR_PARITY) ++ flag = TTY_PARITY; ++ else if (stat & RXERROR_FRAMING) ++ flag = TTY_FRAME; ++ + tty_insert_flip_char(&port->port, data[i+1], + flag); + } +@@ -730,15 +741,19 @@ static void usa49wg_indat_callback(struct urb *urb) + */ + for (x = 0; x + 1 < len && + i + 1 < urb->actual_length; x += 2) { +- int stat = data[i], flag = 0; ++ int stat = data[i]; ++ int flag = TTY_NORMAL; + +- if (stat & RXERROR_OVERRUN) +- flag |= TTY_OVERRUN; +- if (stat & RXERROR_FRAMING) +- flag |= TTY_FRAME; +- if (stat & RXERROR_PARITY) +- flag |= TTY_PARITY; ++ if (stat & RXERROR_OVERRUN) { ++ tty_insert_flip_char(&port->port, 0, ++ TTY_OVERRUN); ++ } + /* XXX should handle break (0x10) */ ++ if (stat & RXERROR_PARITY) ++ flag = TTY_PARITY; ++ else if (stat & RXERROR_FRAMING) ++ flag = TTY_FRAME; ++ + tty_insert_flip_char(&port->port, data[i+1], + flag); + i += 2; +@@ -790,25 +805,31 @@ static void usa90_indat_callback(struct urb *urb) + if ((data[0] & 0x80) == 0) { + /* no errors on individual bytes, only + possible overrun err*/ +- if (data[0] & RXERROR_OVERRUN) +- err = TTY_OVERRUN; +- else +- err = 0; ++ if (data[0] & RXERROR_OVERRUN) { ++ tty_insert_flip_char(&port->port, 0, ++ TTY_OVERRUN); ++ } + for (i = 1; i < urb->actual_length ; ++i) + tty_insert_flip_char(&port->port, +- data[i], err); ++ data[i], TTY_NORMAL); + } else { + /* some bytes had errors, every byte has status */ + dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__); + for (i = 0; i + 1 < urb->actual_length; i += 2) { +- int stat = data[i], flag = 0; +- if (stat & RXERROR_OVERRUN) +- flag |= TTY_OVERRUN; +- if (stat & RXERROR_FRAMING) +- flag |= TTY_FRAME; +- if (stat & RXERROR_PARITY) +- flag |= TTY_PARITY; ++ int stat = data[i]; ++ int flag = TTY_NORMAL; ++ ++ if (stat & RXERROR_OVERRUN) { ++ tty_insert_flip_char( ++ &port->port, 0, ++ TTY_OVERRUN); ++ } + /* XXX should handle break (0x10) */ ++ if (stat & RXERROR_PARITY) ++ flag = TTY_PARITY; ++ else if (stat & RXERROR_FRAMING) ++ flag = TTY_FRAME; ++ + tty_insert_flip_char(&port->port, + data[i+1], flag); + } +diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c +index a7fe664b6b7d..70a098de429f 100644 +--- a/drivers/usb/serial/ssu100.c ++++ b/drivers/usb/serial/ssu100.c +@@ -490,10 +490,9 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr, + if (*tty_flag == TTY_NORMAL) + *tty_flag = TTY_FRAME; + } +- if (lsr & UART_LSR_OE){ ++ if (lsr & UART_LSR_OE) { + port->icount.overrun++; +- if (*tty_flag == TTY_NORMAL) +- *tty_flag = TTY_OVERRUN; ++ tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); + } + } + +@@ -511,12 +510,8 @@ static void ssu100_process_read_urb(struct urb *urb) + if ((len >= 4) && + (packet[0] == 0x1b) && (packet[1] == 0x1b) && + ((packet[2] == 0x00) || (packet[2] == 0x01))) { +- if (packet[2] == 0x00) { ++ if (packet[2] == 0x00) + ssu100_update_lsr(port, packet[3], &flag); +- if (flag == TTY_OVERRUN) +- tty_insert_flip_char(&port->port, 0, +- TTY_OVERRUN); +- } + if (packet[2] == 0x01) + ssu100_update_msr(port, packet[3]); + +diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c +index e48d4a672580..5d0b7b846440 100644 +--- a/drivers/vhost/scsi.c ++++ b/drivers/vhost/scsi.c +@@ -1200,6 +1200,7 @@ static int + vhost_scsi_set_endpoint(struct vhost_scsi *vs, + struct vhost_scsi_target *t) + { ++ struct se_portal_group *se_tpg; + struct tcm_vhost_tport *tv_tport; + struct tcm_vhost_tpg *tpg; + struct tcm_vhost_tpg **vs_tpg; +@@ -1247,6 +1248,21 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs, + ret = -EEXIST; + goto out; + } ++ /* ++ * In order to ensure individual vhost-scsi configfs ++ * groups cannot be removed while in use by vhost ioctl, ++ * go ahead and take an explicit se_tpg->tpg_group.cg_item ++ * dependency now. ++ */ ++ se_tpg = &tpg->se_tpg; ++ ret = configfs_depend_item(se_tpg->se_tpg_tfo->tf_subsys, ++ &se_tpg->tpg_group.cg_item); ++ if (ret) { ++ pr_warn("configfs_depend_item() failed: %d\n", ret); ++ kfree(vs_tpg); ++ mutex_unlock(&tpg->tv_tpg_mutex); ++ goto out; ++ } + tpg->tv_tpg_vhost_count++; + tpg->vhost_scsi = vs; + vs_tpg[tpg->tport_tpgt] = tpg; +@@ -1289,6 +1305,7 @@ static int + vhost_scsi_clear_endpoint(struct vhost_scsi *vs, + struct vhost_scsi_target *t) + { ++ struct se_portal_group *se_tpg; + struct tcm_vhost_tport *tv_tport; + struct tcm_vhost_tpg *tpg; + struct vhost_virtqueue *vq; +@@ -1337,6 +1354,13 @@ vhost_scsi_clear_endpoint(struct vhost_scsi *vs, + vs->vs_tpg[target] = NULL; + match = true; + mutex_unlock(&tpg->tv_tpg_mutex); ++ /* ++ * Release se_tpg->tpg_group.cg_item configfs dependency now ++ * to allow vhost-scsi WWPN se_tpg->tpg_group shutdown to occur. ++ */ ++ se_tpg = &tpg->se_tpg; ++ configfs_undepend_item(se_tpg->se_tpg_tfo->tf_subsys, ++ &se_tpg->tpg_group.cg_item); + } + if (match) { + for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) { +diff --git a/fs/aio.c b/fs/aio.c +index f45ddaa4fffa..2f7e8c2e3e76 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -165,6 +165,15 @@ static struct vfsmount *aio_mnt; + static const struct file_operations aio_ring_fops; + static const struct address_space_operations aio_ctx_aops; + ++/* Backing dev info for aio fs. ++ * -no dirty page accounting or writeback happens ++ */ ++static struct backing_dev_info aio_fs_backing_dev_info = { ++ .name = "aiofs", ++ .state = 0, ++ .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK | BDI_CAP_MAP_COPY, ++}; ++ + static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) + { + struct qstr this = QSTR_INIT("[aio]", 5); +@@ -176,6 +185,7 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) + + inode->i_mapping->a_ops = &aio_ctx_aops; + inode->i_mapping->private_data = ctx; ++ inode->i_mapping->backing_dev_info = &aio_fs_backing_dev_info; + inode->i_size = PAGE_SIZE * nr_pages; + + path.dentry = d_alloc_pseudo(aio_mnt->mnt_sb, &this); +@@ -221,6 +231,9 @@ static int __init aio_setup(void) + if (IS_ERR(aio_mnt)) + panic("Failed to create aio fs mount."); + ++ if (bdi_init(&aio_fs_backing_dev_info)) ++ panic("Failed to init aio fs backing dev info."); ++ + kiocb_cachep = KMEM_CACHE(kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC); + kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC); + +@@ -282,11 +295,6 @@ static const struct file_operations aio_ring_fops = { + .mmap = aio_ring_mmap, + }; + +-static int aio_set_page_dirty(struct page *page) +-{ +- return 0; +-} +- + #if IS_ENABLED(CONFIG_MIGRATION) + static int aio_migratepage(struct address_space *mapping, struct page *new, + struct page *old, enum migrate_mode mode) +@@ -358,7 +366,7 @@ out: + #endif + + static const struct address_space_operations aio_ctx_aops = { +- .set_page_dirty = aio_set_page_dirty, ++ .set_page_dirty = __set_page_dirty_no_writeback, + #if IS_ENABLED(CONFIG_MIGRATION) + .migratepage = aio_migratepage, + #endif +@@ -413,7 +421,6 @@ static int aio_setup_ring(struct kioctx *ctx) + pr_debug("pid(%d) page[%d]->count=%d\n", + current->pid, i, page_count(page)); + SetPageUptodate(page); +- SetPageDirty(page); + unlock_page(page); + + ctx->ring_pages[i] = page; +diff --git a/fs/locks.c b/fs/locks.c +index 4dd39b98a6a3..2c61c4e9368c 100644 +--- a/fs/locks.c ++++ b/fs/locks.c +@@ -2235,16 +2235,28 @@ void locks_remove_flock(struct file *filp) + + while ((fl = *before) != NULL) { + if (fl->fl_file == filp) { +- if (IS_FLOCK(fl)) { +- locks_delete_lock(before); +- continue; +- } + if (IS_LEASE(fl)) { + lease_modify(before, F_UNLCK); + continue; + } +- /* What? */ +- BUG(); ++ ++ /* ++ * There's a leftover lock on the list of a type that ++ * we didn't expect to see. Most likely a classic ++ * POSIX lock that ended up not getting released ++ * properly, or that raced onto the list somehow. Log ++ * some info about it and then just remove it from ++ * the list. ++ */ ++ WARN(!IS_FLOCK(fl), ++ "leftover lock: dev=%u:%u ino=%lu type=%hhd flags=0x%x start=%lld end=%lld\n", ++ MAJOR(inode->i_sb->s_dev), ++ MINOR(inode->i_sb->s_dev), inode->i_ino, ++ fl->fl_type, fl->fl_flags, ++ fl->fl_start, fl->fl_end); ++ ++ locks_delete_lock(before); ++ continue; + } + before = &fl->fl_next; + } +diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c +index 2ffebf2081ce..27d7f2742592 100644 +--- a/fs/nfs/pagelist.c ++++ b/fs/nfs/pagelist.c +@@ -113,7 +113,7 @@ __nfs_iocounter_wait(struct nfs_io_counter *c) + if (atomic_read(&c->io_count) == 0) + break; + ret = nfs_wait_bit_killable(&c->flags); +- } while (atomic_read(&c->io_count) != 0); ++ } while (atomic_read(&c->io_count) != 0 && !ret); + finish_wait(wq, &q.wait); + return ret; + } +diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c +index cc8c5b32043c..f42bbe5fbc0a 100644 +--- a/fs/nfsd/nfs4callback.c ++++ b/fs/nfsd/nfs4callback.c +@@ -784,8 +784,12 @@ static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task) + { + if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { + rpc_sleep_on(&clp->cl_cb_waitq, task, NULL); +- dprintk("%s slot is busy\n", __func__); +- return false; ++ /* Race breaker */ ++ if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { ++ dprintk("%s slot is busy\n", __func__); ++ return false; ++ } ++ rpc_wake_up_queued_task(&clp->cl_cb_waitq, task); + } + return true; + } +diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c +index f8f060ffbf4f..6040da8830ff 100644 +--- a/fs/nfsd/nfscache.c ++++ b/fs/nfsd/nfscache.c +@@ -224,13 +224,6 @@ hash_refile(struct svc_cacherep *rp) + hlist_add_head(&rp->c_hash, cache_hash + hash_32(rp->c_xid, maskbits)); + } + +-static inline bool +-nfsd_cache_entry_expired(struct svc_cacherep *rp) +-{ +- return rp->c_state != RC_INPROG && +- time_after(jiffies, rp->c_timestamp + RC_EXPIRE); +-} +- + /* + * Walk the LRU list and prune off entries that are older than RC_EXPIRE. + * Also prune the oldest ones when the total exceeds the max number of entries. +@@ -242,8 +235,14 @@ prune_cache_entries(void) + long freed = 0; + + list_for_each_entry_safe(rp, tmp, &lru_head, c_lru) { +- if (!nfsd_cache_entry_expired(rp) && +- num_drc_entries <= max_drc_entries) ++ /* ++ * Don't free entries attached to calls that are still ++ * in-progress, but do keep scanning the list. ++ */ ++ if (rp->c_state == RC_INPROG) ++ continue; ++ if (num_drc_entries <= max_drc_entries && ++ time_before(jiffies, rp->c_timestamp + RC_EXPIRE)) + break; + nfsd_reply_cache_free_locked(rp); + freed++; +diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h +index 479eb681c27c..f417fef17118 100644 +--- a/fs/nfsd/nfsd.h ++++ b/fs/nfsd/nfsd.h +@@ -328,12 +328,15 @@ void nfsd_lockd_shutdown(void); + (NFSD4_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SUPPATTR_EXCLCREAT) + + #ifdef CONFIG_NFSD_V4_SECURITY_LABEL +-#define NFSD4_2_SUPPORTED_ATTRS_WORD2 \ +- (NFSD4_1_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SECURITY_LABEL) ++#define NFSD4_2_SECURITY_ATTRS FATTR4_WORD2_SECURITY_LABEL + #else +-#define NFSD4_2_SUPPORTED_ATTRS_WORD2 0 ++#define NFSD4_2_SECURITY_ATTRS 0 + #endif + ++#define NFSD4_2_SUPPORTED_ATTRS_WORD2 \ ++ (NFSD4_1_SUPPORTED_ATTRS_WORD2 | \ ++ NFSD4_2_SECURITY_ATTRS) ++ + static inline u32 nfsd_suppattrs0(u32 minorversion) + { + return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0 +diff --git a/include/linux/bitops.h b/include/linux/bitops.h +index be5fd38bd5a0..5d858e02997f 100644 +--- a/include/linux/bitops.h ++++ b/include/linux/bitops.h +@@ -18,8 +18,11 @@ + * position @h. For example + * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000. + */ +-#define GENMASK(h, l) (((U32_C(1) << ((h) - (l) + 1)) - 1) << (l)) +-#define GENMASK_ULL(h, l) (((U64_C(1) << ((h) - (l) + 1)) - 1) << (l)) ++#define GENMASK(h, l) \ ++ (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) ++ ++#define GENMASK_ULL(h, l) \ ++ (((~0ULL) << (l)) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h)))) + + extern unsigned int __sw_hweight8(unsigned int w); + extern unsigned int __sw_hweight16(unsigned int w); +diff --git a/include/linux/iio/events.h b/include/linux/iio/events.h +index 8bbd7bc1043d..03fa332ad2a8 100644 +--- a/include/linux/iio/events.h ++++ b/include/linux/iio/events.h +@@ -72,7 +72,7 @@ struct iio_event_data { + + #define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF) + +-#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0xCF) ++#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0x7F) + + #define IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(mask) ((mask >> 32) & 0xFF) + +diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h +index 0068708161ff..0a21fbefdfbe 100644 +--- a/include/linux/inetdevice.h ++++ b/include/linux/inetdevice.h +@@ -242,7 +242,7 @@ static inline void in_dev_put(struct in_device *idev) + static __inline__ __be32 inet_make_mask(int logmask) + { + if (logmask) +- return htonl(~((1<<(32-logmask))-1)); ++ return htonl(~((1U<<(32-logmask))-1)); + return 0; + } + +diff --git a/include/linux/pci.h b/include/linux/pci.h +index 33aa2caf0f0c..0e5e16c6f7f1 100644 +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -324,6 +324,7 @@ struct pci_dev { + unsigned int is_added:1; + unsigned int is_busmaster:1; /* device is busmaster */ + unsigned int no_msi:1; /* device may not use msi */ ++ unsigned int no_64bit_msi:1; /* device may only use 32-bit MSIs */ + unsigned int block_cfg_access:1; /* config space access is blocked */ + unsigned int broken_parity_status:1; /* Device generates false positive parity */ + unsigned int irq_reroute_variant:2; /* device needs IRQ rerouting variant */ +diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h +index 2883a7a6f9f3..98f2ade0266e 100644 +--- a/include/sound/soc-dpcm.h ++++ b/include/sound/soc-dpcm.h +@@ -102,6 +102,8 @@ struct snd_soc_dpcm_runtime { + /* state and update */ + enum snd_soc_dpcm_update runtime_update; + enum snd_soc_dpcm_state state; ++ ++ int trigger_pending; /* trigger cmd + 1 if pending, 0 if not */ + }; + + /* can this BE stop and free */ +diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c +index 307d87c0991a..1139b228befc 100644 +--- a/kernel/events/uprobes.c ++++ b/kernel/events/uprobes.c +@@ -1621,7 +1621,6 @@ bool uprobe_deny_signal(void) + if (__fatal_signal_pending(t) || arch_uprobe_xol_was_trapped(t)) { + utask->state = UTASK_SSTEP_TRAPPED; + set_tsk_thread_flag(t, TIF_UPROBE); +- set_tsk_thread_flag(t, TIF_NOTIFY_RESUME); + } + } + +diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c +index b851cc580853..fbda6b54baff 100644 +--- a/net/batman-adv/hard-interface.c ++++ b/net/batman-adv/hard-interface.c +@@ -83,7 +83,7 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev) + return true; + + /* no more parents..stop recursion */ +- if (net_dev->iflink == net_dev->ifindex) ++ if (net_dev->iflink == 0 || net_dev->iflink == net_dev->ifindex) + return false; + + /* recurse over the parent device */ +diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c +index f2e15738534d..8f7bd56955b0 100644 +--- a/net/ipv4/fib_rules.c ++++ b/net/ipv4/fib_rules.c +@@ -62,6 +62,10 @@ int __fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res) + else + res->tclassid = 0; + #endif ++ ++ if (err == -ESRCH) ++ err = -ENETUNREACH; ++ + return err; + } + EXPORT_SYMBOL_GPL(__fib_lookup); +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index e21934b06d4c..0d33f947a87f 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -217,6 +217,8 @@ static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident) + &ipv6_hdr(skb)->daddr)) + continue; + #endif ++ } else { ++ continue; + } + + if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) +diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c +index 00b2a6d1c009..d65aea21ce81 100644 +--- a/net/ipx/af_ipx.c ++++ b/net/ipx/af_ipx.c +@@ -1763,6 +1763,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, + struct ipxhdr *ipx = NULL; + struct sk_buff *skb; + int copied, rc; ++ bool locked = true; + + lock_sock(sk); + /* put the autobinding in */ +@@ -1789,6 +1790,8 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, + if (sock_flag(sk, SOCK_ZAPPED)) + goto out; + ++ release_sock(sk); ++ locked = false; + skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, + flags & MSG_DONTWAIT, &rc); + if (!skb) +@@ -1822,7 +1825,8 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, + out_free: + skb_free_datagram(sk, skb); + out: +- release_sock(sk); ++ if (locked) ++ release_sock(sk); + return rc; + } + +diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c +index 0fcbe90f3ef2..12528e9ac4c2 100644 +--- a/sound/soc/codecs/sgtl5000.c ++++ b/sound/soc/codecs/sgtl5000.c +@@ -1369,8 +1369,7 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) + + /* enable small pop, introduce 400ms delay in turning off */ + snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL, +- SGTL5000_SMALL_POP, +- SGTL5000_SMALL_POP); ++ SGTL5000_SMALL_POP, 1); + + /* disable short cut detector */ + snd_soc_write(codec, SGTL5000_CHIP_SHORT_CTRL, 0); +diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h +index 2f8c88931f69..bd7a344bf8c5 100644 +--- a/sound/soc/codecs/sgtl5000.h ++++ b/sound/soc/codecs/sgtl5000.h +@@ -275,7 +275,7 @@ + #define SGTL5000_BIAS_CTRL_MASK 0x000e + #define SGTL5000_BIAS_CTRL_SHIFT 1 + #define SGTL5000_BIAS_CTRL_WIDTH 3 +-#define SGTL5000_SMALL_POP 0x0001 ++#define SGTL5000_SMALL_POP 0 + + /* + * SGTL5000_CHIP_MIC_CTRL +diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c +index 53c03aff762e..0502e3f17412 100644 +--- a/sound/soc/codecs/wm_adsp.c ++++ b/sound/soc/codecs/wm_adsp.c +@@ -1341,6 +1341,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) + file, blocks, pos - firmware->size); + + out_fw: ++ regmap_async_complete(regmap); + release_firmware(firmware); + wm_adsp_buf_free(&buf_list); + out: +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 1967f44e7cd4..9d0c59ce6de8 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1785,8 +1785,7 @@ static const struct snd_soc_dai_ops fsi_dai_ops = { + static struct snd_pcm_hardware fsi_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | +- SNDRV_PCM_INFO_MMAP_VALID | +- SNDRV_PCM_INFO_PAUSE, ++ SNDRV_PCM_INFO_MMAP_VALID, + .buffer_bytes_max = 64 * 1024, + .period_bytes_min = 32, + .period_bytes_max = 8192, +diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c +index 743de5e3b1e1..37fcd93ed1fd 100644 +--- a/sound/soc/sh/rcar/core.c ++++ b/sound/soc/sh/rcar/core.c +@@ -626,8 +626,7 @@ static void rsnd_dai_remove(struct platform_device *pdev, + static struct snd_pcm_hardware rsnd_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | +- SNDRV_PCM_INFO_MMAP_VALID | +- SNDRV_PCM_INFO_PAUSE, ++ SNDRV_PCM_INFO_MMAP_VALID, + .buffer_bytes_max = 64 * 1024, + .period_bytes_min = 32, + .period_bytes_max = 8192, +diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c +index 02733ded2cb1..e28704e1274a 100644 +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -1258,13 +1258,36 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) + dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture); + } + ++static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd); ++ ++/* Set FE's runtime_update state; the state is protected via PCM stream lock ++ * for avoiding the race with trigger callback. ++ * If the state is unset and a trigger is pending while the previous operation, ++ * process the pending trigger action here. ++ */ ++static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe, ++ int stream, enum snd_soc_dpcm_update state) ++{ ++ struct snd_pcm_substream *substream = ++ snd_soc_dpcm_get_substream(fe, stream); ++ ++ snd_pcm_stream_lock_irq(substream); ++ if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) { ++ dpcm_fe_dai_do_trigger(substream, ++ fe->dpcm[stream].trigger_pending - 1); ++ fe->dpcm[stream].trigger_pending = 0; ++ } ++ fe->dpcm[stream].runtime_update = state; ++ snd_pcm_stream_unlock_irq(substream); ++} ++ + static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) + { + struct snd_soc_pcm_runtime *fe = fe_substream->private_data; + struct snd_pcm_runtime *runtime = fe_substream->runtime; + int stream = fe_substream->stream, ret = 0; + +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); + + ret = dpcm_be_dai_startup(fe, fe_substream->stream); + if (ret < 0) { +@@ -1286,13 +1309,13 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) + dpcm_set_fe_runtime(fe_substream); + snd_pcm_limit_hw_rates(runtime); + +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + return 0; + + unwind: + dpcm_be_dai_startup_unwind(fe, fe_substream->stream); + be_err: +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + return ret; + } + +@@ -1339,7 +1362,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream) + struct snd_soc_pcm_runtime *fe = substream->private_data; + int stream = substream->stream; + +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); + + /* shutdown the BEs */ + dpcm_be_dai_shutdown(fe, substream->stream); +@@ -1353,7 +1376,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream) + dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); + + fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + return 0; + } + +@@ -1401,7 +1424,7 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) + int err, stream = substream->stream; + + mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); + + dev_dbg(fe->dev, "ASoC: hw_free FE %s\n", fe->dai_link->name); + +@@ -1416,7 +1439,7 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) + err = dpcm_be_dai_hw_free(fe, stream); + + fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE; +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + + mutex_unlock(&fe->card->mutex); + return 0; +@@ -1509,7 +1532,7 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream, + int ret, stream = substream->stream; + + mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); + + memcpy(&fe->dpcm[substream->stream].hw_params, params, + sizeof(struct snd_pcm_hw_params)); +@@ -1532,7 +1555,7 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream, + fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS; + + out: +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + mutex_unlock(&fe->card->mutex); + return ret; + } +@@ -1646,7 +1669,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, + } + EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger); + +-static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd) ++static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) + { + struct snd_soc_pcm_runtime *fe = substream->private_data; + int stream = substream->stream, ret; +@@ -1720,6 +1743,23 @@ out: + return ret; + } + ++static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd) ++{ ++ struct snd_soc_pcm_runtime *fe = substream->private_data; ++ int stream = substream->stream; ++ ++ /* if FE's runtime_update is already set, we're in race; ++ * process this trigger later at exit ++ */ ++ if (fe->dpcm[stream].runtime_update != SND_SOC_DPCM_UPDATE_NO) { ++ fe->dpcm[stream].trigger_pending = cmd + 1; ++ return 0; /* delayed, assuming it's successful */ ++ } ++ ++ /* we're alone, let's trigger */ ++ return dpcm_fe_dai_do_trigger(substream, cmd); ++} ++ + int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) + { + struct snd_soc_dpcm *dpcm; +@@ -1763,7 +1803,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) + + dev_dbg(fe->dev, "ASoC: prepare FE %s\n", fe->dai_link->name); + +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); + + /* there is no point preparing this FE if there are no BEs */ + if (list_empty(&fe->dpcm[stream].be_clients)) { +@@ -1790,7 +1830,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) + fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; + + out: +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + mutex_unlock(&fe->card->mutex); + + return ret; +@@ -1937,11 +1977,11 @@ static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream) + { + int ret; + +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE); + ret = dpcm_run_update_startup(fe, stream); + if (ret < 0) + dev_err(fe->dev, "ASoC: failed to startup some BEs\n"); +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + + return ret; + } +@@ -1950,11 +1990,11 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream) + { + int ret; + +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE); + ret = dpcm_run_update_shutdown(fe, stream); + if (ret < 0) + dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n"); +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + + return ret; + } +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index c64a3d96db22..827d40441ec7 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1142,6 +1142,20 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, + if ((le16_to_cpu(dev->descriptor.idVendor) == 0x23ba) && + (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) + mdelay(20); ++ ++ /* Marantz/Denon devices with USB DAC functionality need a delay ++ * after each class compliant request ++ */ ++ if ((le16_to_cpu(dev->descriptor.idVendor) == 0x154e) && ++ (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) { ++ ++ switch (le16_to_cpu(dev->descriptor.idProduct)) { ++ case 0x3005: /* Marantz HD-DAC1 */ ++ case 0x3006: /* Marantz SA-14S1 */ ++ mdelay(20); ++ break; ++ } ++ } + } + + /* diff --git a/patch/kernel/cubox-default/patch-3.14.26-27.patch b/patch/kernel/cubox-default/patch-3.14.26-27.patch new file mode 100644 index 000000000..9c8913120 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.26-27.patch @@ -0,0 +1,914 @@ +diff --git a/Makefile b/Makefile +index 63a5ee858cc3..944db2356a7c 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 26 ++SUBLEVEL = 27 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/powerpc/kernel/vdso32/getcpu.S b/arch/powerpc/kernel/vdso32/getcpu.S +index 47afd08c90f7..fe7e97a1aad9 100644 +--- a/arch/powerpc/kernel/vdso32/getcpu.S ++++ b/arch/powerpc/kernel/vdso32/getcpu.S +@@ -30,8 +30,8 @@ + V_FUNCTION_BEGIN(__kernel_getcpu) + .cfi_startproc + mfspr r5,SPRN_USPRG3 +- cmpdi cr0,r3,0 +- cmpdi cr1,r4,0 ++ cmpwi cr0,r3,0 ++ cmpwi cr1,r4,0 + clrlwi r6,r5,16 + rlwinm r7,r5,16,31-15,31-0 + beq cr0,1f +diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile +index 14fe7cba21d1..b5bb49866bcc 100644 +--- a/arch/x86/boot/compressed/Makefile ++++ b/arch/x86/boot/compressed/Makefile +@@ -75,7 +75,7 @@ suffix-$(CONFIG_KERNEL_XZ) := xz + suffix-$(CONFIG_KERNEL_LZO) := lzo + suffix-$(CONFIG_KERNEL_LZ4) := lz4 + +-RUN_SIZE = $(shell objdump -h vmlinux | \ ++RUN_SIZE = $(shell $(OBJDUMP) -h vmlinux | \ + perl $(srctree)/arch/x86/tools/calc_run_size.pl) + quiet_cmd_mkpiggy = MKPIGGY $@ + cmd_mkpiggy = $(obj)/mkpiggy $< $(RUN_SIZE) > $@ || ( rm -f $@ ; false ) +diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c +index 79f9f848bee4..fb345c43815f 100644 +--- a/arch/x86/kernel/cpu/perf_event.c ++++ b/arch/x86/kernel/cpu/perf_event.c +@@ -118,6 +118,9 @@ static int x86_pmu_extra_regs(u64 config, struct perf_event *event) + continue; + if (event->attr.config1 & ~er->valid_mask) + return -EINVAL; ++ /* Check if the extra msrs can be safely accessed*/ ++ if (!er->extra_msr_access) ++ return -ENXIO; + + reg->idx = er->idx; + reg->config = event->attr.config1; +diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h +index 4972c244d0bc..7876c346ed1a 100644 +--- a/arch/x86/kernel/cpu/perf_event.h ++++ b/arch/x86/kernel/cpu/perf_event.h +@@ -293,14 +293,16 @@ struct extra_reg { + u64 config_mask; + u64 valid_mask; + int idx; /* per_xxx->regs[] reg index */ ++ bool extra_msr_access; + }; + + #define EVENT_EXTRA_REG(e, ms, m, vm, i) { \ +- .event = (e), \ +- .msr = (ms), \ +- .config_mask = (m), \ +- .valid_mask = (vm), \ +- .idx = EXTRA_REG_##i, \ ++ .event = (e), \ ++ .msr = (ms), \ ++ .config_mask = (m), \ ++ .valid_mask = (vm), \ ++ .idx = EXTRA_REG_##i, \ ++ .extra_msr_access = true, \ + } + + #define INTEL_EVENT_EXTRA_REG(event, msr, vm, idx) \ +diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c +index 5ee8064bd1d2..d4c0a0e46040 100644 +--- a/arch/x86/kernel/cpu/perf_event_intel.c ++++ b/arch/x86/kernel/cpu/perf_event_intel.c +@@ -2183,6 +2183,41 @@ static void intel_snb_check_microcode(void) + } + } + ++/* ++ * Under certain circumstances, access certain MSR may cause #GP. ++ * The function tests if the input MSR can be safely accessed. ++ */ ++static bool check_msr(unsigned long msr, u64 mask) ++{ ++ u64 val_old, val_new, val_tmp; ++ ++ /* ++ * Read the current value, change it and read it back to see if it ++ * matches, this is needed to detect certain hardware emulators ++ * (qemu/kvm) that don't trap on the MSR access and always return 0s. ++ */ ++ if (rdmsrl_safe(msr, &val_old)) ++ return false; ++ ++ /* ++ * Only change the bits which can be updated by wrmsrl. ++ */ ++ val_tmp = val_old ^ mask; ++ if (wrmsrl_safe(msr, val_tmp) || ++ rdmsrl_safe(msr, &val_new)) ++ return false; ++ ++ if (val_new != val_tmp) ++ return false; ++ ++ /* Here it's sure that the MSR can be safely accessed. ++ * Restore the old value and return. ++ */ ++ wrmsrl(msr, val_old); ++ ++ return true; ++} ++ + static __init void intel_sandybridge_quirk(void) + { + x86_pmu.check_microcode = intel_snb_check_microcode; +@@ -2272,7 +2307,8 @@ __init int intel_pmu_init(void) + union cpuid10_ebx ebx; + struct event_constraint *c; + unsigned int unused; +- int version; ++ struct extra_reg *er; ++ int version, i; + + if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { + switch (boot_cpu_data.x86) { +@@ -2578,6 +2614,34 @@ __init int intel_pmu_init(void) + } + } + ++ /* ++ * Access LBR MSR may cause #GP under certain circumstances. ++ * E.g. KVM doesn't support LBR MSR ++ * Check all LBT MSR here. ++ * Disable LBR access if any LBR MSRs can not be accessed. ++ */ ++ if (x86_pmu.lbr_nr && !check_msr(x86_pmu.lbr_tos, 0x3UL)) ++ x86_pmu.lbr_nr = 0; ++ for (i = 0; i < x86_pmu.lbr_nr; i++) { ++ if (!(check_msr(x86_pmu.lbr_from + i, 0xffffUL) && ++ check_msr(x86_pmu.lbr_to + i, 0xffffUL))) ++ x86_pmu.lbr_nr = 0; ++ } ++ ++ /* ++ * Access extra MSR may cause #GP under certain circumstances. ++ * E.g. KVM doesn't support offcore event ++ * Check all extra_regs here. ++ */ ++ if (x86_pmu.extra_regs) { ++ for (er = x86_pmu.extra_regs; er->msr; er++) { ++ er->extra_msr_access = check_msr(er->msr, 0x1ffUL); ++ /* Disable LBR select mapping */ ++ if ((er->idx == EXTRA_REG_LBR) && !er->extra_msr_access) ++ x86_pmu.lbr_sel_map = NULL; ++ } ++ } ++ + /* Support full width counters using alternative MSR range */ + if (x86_pmu.intel_cap.full_width_write) { + x86_pmu.max_period = x86_pmu.cntval_mask; +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index e662f147d436..cc5f102bebf3 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -322,6 +322,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */ + { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ + { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */ ++ { PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */ ++ { PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */ + { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H RAID */ + { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */ +@@ -493,6 +496,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { + * enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731 + */ + { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi }, ++ { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi }, + + /* Enmotus */ + { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, +diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c +index fb0b40a191c2..ee2780dd90a8 100644 +--- a/drivers/ata/sata_fsl.c ++++ b/drivers/ata/sata_fsl.c +@@ -1503,7 +1503,7 @@ static int sata_fsl_probe(struct platform_device *ofdev) + host_priv->csr_base = csr_base; + + irq = irq_of_parse_and_map(ofdev->dev.of_node, 0); +- if (irq < 0) { ++ if (!irq) { + dev_err(&ofdev->dev, "invalid irq from platform\n"); + goto error_exit_with_cleanup; + } +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index b6fb3ebe553a..c51469051e41 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -3817,7 +3817,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) + ironlake_fdi_disable(crtc); + + ironlake_disable_pch_transcoder(dev_priv, pipe); +- intel_set_pch_fifo_underrun_reporting(dev, pipe, true); + + if (HAS_PCH_CPT(dev)) { + /* disable TRANS_DP_CTL */ +@@ -3883,7 +3882,6 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) + + if (intel_crtc->config.has_pch_encoder) { + lpt_disable_pch_transcoder(dev_priv); +- intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true); + intel_ddi_fdi_disable(crtc); + } + +diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c +index 67c9ff389989..af49b24d14cb 100644 +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -905,6 +905,17 @@ void intel_lvds_init(struct drm_device *dev) + int pipe; + u8 pin; + ++ /* ++ * Unlock registers and just leave them unlocked. Do this before ++ * checking quirk lists to avoid bogus WARNINGs. ++ */ ++ if (HAS_PCH_SPLIT(dev)) { ++ I915_WRITE(PCH_PP_CONTROL, ++ I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); ++ } else { ++ I915_WRITE(PP_CONTROL, ++ I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); ++ } + if (!intel_lvds_supported(dev)) + return; + +@@ -1099,17 +1110,6 @@ out: + DRM_DEBUG_KMS("detected %s-link lvds configuration\n", + lvds_encoder->is_dual_link ? "dual" : "single"); + +- /* +- * Unlock registers and just +- * leave them unlocked +- */ +- if (HAS_PCH_SPLIT(dev)) { +- I915_WRITE(PCH_PP_CONTROL, +- I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); +- } else { +- I915_WRITE(PP_CONTROL, +- I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); +- } + lvds_connector->lid_notifier.notifier_call = intel_lid_notify; + if (acpi_lid_notifier_register(&lvds_connector->lid_notifier)) { + DRM_DEBUG_KMS("lid notifier registration failed\n"); +diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c +index 0bc9106ef435..6bffe82f241c 100644 +--- a/drivers/gpu/drm/radeon/radeon_kms.c ++++ b/drivers/gpu/drm/radeon/radeon_kms.c +@@ -740,6 +740,8 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, + + /* Get associated drm_crtc: */ + drmcrtc = &rdev->mode_info.crtcs[crtc]->base; ++ if (!drmcrtc) ++ return -EINVAL; + + /* Helper routine in DRM core does all the work: */ + return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error, +diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c +index af0b5830303d..e3c6a96717fc 100644 +--- a/drivers/i2c/busses/i2c-davinci.c ++++ b/drivers/i2c/busses/i2c-davinci.c +@@ -411,11 +411,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) + if (dev->cmd_err & DAVINCI_I2C_STR_NACK) { + if (msg->flags & I2C_M_IGNORE_NAK) + return msg->len; +- if (stop) { +- w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); +- w |= DAVINCI_I2C_MDR_STP; +- davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); +- } ++ w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); ++ w |= DAVINCI_I2C_MDR_STP; ++ davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); + return -EREMOTEIO; + } + return -EIO; +diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c +index 90dcc2eaac5f..a6860570391f 100644 +--- a/drivers/i2c/busses/i2c-omap.c ++++ b/drivers/i2c/busses/i2c-omap.c +@@ -926,14 +926,12 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) + if (stat & OMAP_I2C_STAT_NACK) { + err |= OMAP_I2C_STAT_NACK; + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK); +- break; + } + + if (stat & OMAP_I2C_STAT_AL) { + dev_err(dev->dev, "Arbitration lost\n"); + err |= OMAP_I2C_STAT_AL; + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL); +- break; + } + + /* +@@ -958,11 +956,13 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) + if (dev->fifo_size) + num_bytes = dev->buf_len; + +- omap_i2c_receive_data(dev, num_bytes, true); +- +- if (dev->errata & I2C_OMAP_ERRATA_I207) ++ if (dev->errata & I2C_OMAP_ERRATA_I207) { + i2c_omap_errata_i207(dev, stat); ++ num_bytes = (omap_i2c_read_reg(dev, ++ OMAP_I2C_BUFSTAT_REG) >> 8) & 0x3F; ++ } + ++ omap_i2c_receive_data(dev, num_bytes, true); + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); + continue; + } +diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c +index 8741cae9c9f2..7026ab08ec91 100644 +--- a/drivers/media/i2c/smiapp/smiapp-core.c ++++ b/drivers/media/i2c/smiapp/smiapp-core.c +@@ -2138,7 +2138,7 @@ static int smiapp_set_selection(struct v4l2_subdev *subdev, + ret = smiapp_set_compose(subdev, fh, sel); + break; + default: +- BUG(); ++ ret = -EINVAL; + } + + mutex_unlock(&sensor->mutex); +diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c +index 9373f1f59605..086eac5af5c2 100644 +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -8548,7 +8548,8 @@ static int tg3_init_rings(struct tg3 *tp) + if (tnapi->rx_rcb) + memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); + +- if (tg3_rx_prodring_alloc(tp, &tnapi->prodring)) { ++ if (tnapi->prodring.rx_std && ++ tg3_rx_prodring_alloc(tp, &tnapi->prodring)) { + tg3_free_rings(tp); + return -ENOMEM; + } +diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c +index 5ca8c479666e..206e79d29c79 100644 +--- a/drivers/net/ethernet/intel/igb/igb_main.c ++++ b/drivers/net/ethernet/intel/igb/igb_main.c +@@ -1613,6 +1613,8 @@ void igb_power_up_link(struct igb_adapter *adapter) + igb_power_up_phy_copper(&adapter->hw); + else + igb_power_up_serdes_link_82575(&adapter->hw); ++ ++ igb_setup_link(&adapter->hw); + } + + /** +diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c +index c4c00d9f2c04..96fc7fe8519f 100644 +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -213,7 +213,7 @@ + /* Various constants */ + + /* Coalescing */ +-#define MVNETA_TXDONE_COAL_PKTS 16 ++#define MVNETA_TXDONE_COAL_PKTS 1 + #define MVNETA_RX_COAL_PKTS 32 + #define MVNETA_RX_COAL_USEC 100 + +@@ -1612,6 +1612,7 @@ static int mvneta_tx(struct sk_buff *skb, struct net_device *dev) + u16 txq_id = skb_get_queue_mapping(skb); + struct mvneta_tx_queue *txq = &pp->txqs[txq_id]; + struct mvneta_tx_desc *tx_desc; ++ int len = skb->len; + struct netdev_queue *nq; + int frags = 0; + u32 tx_cmd; +@@ -1675,7 +1676,7 @@ out: + + u64_stats_update_begin(&stats->syncp); + stats->tx_packets++; +- stats->tx_bytes += skb->len; ++ stats->tx_bytes += len; + u64_stats_update_end(&stats->syncp); + } else { + dev->stats.tx_dropped++; +diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +index 57428a0cb9dd..1e8a4b411dc6 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c ++++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +@@ -1456,7 +1456,7 @@ static int qp_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, + + switch (op) { + case RES_OP_RESERVE: +- count = get_param_l(&in_param); ++ count = get_param_l(&in_param) & 0xffffff; + align = get_param_h(&in_param); + err = mlx4_grant_resource(dev, slave, RES_QP, count, 0); + if (err) +diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c +index 5441b49ef89d..5988910db23e 100644 +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -2106,9 +2106,8 @@ static int vxlan_init(struct net_device *dev) + spin_lock(&vn->sock_lock); + vs = vxlan_find_sock(dev_net(dev), ipv6 ? AF_INET6 : AF_INET, + vxlan->dst_port); +- if (vs) { ++ if (vs && atomic_add_unless(&vs->refcnt, 1, 0)) { + /* If we have a socket with same port already, reuse it */ +- atomic_inc(&vs->refcnt); + vxlan_vs_add_dev(vs, vxlan); + } else { + /* otherwise make new socket outside of RTNL */ +@@ -2574,12 +2573,9 @@ struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, + + spin_lock(&vn->sock_lock); + vs = vxlan_find_sock(net, ipv6 ? AF_INET6 : AF_INET, port); +- if (vs) { +- if (vs->rcv == rcv) +- atomic_inc(&vs->refcnt); +- else ++ if (vs && ((vs->rcv != rcv) || ++ !atomic_add_unless(&vs->refcnt, 1, 0))) + vs = ERR_PTR(-EBUSY); +- } + spin_unlock(&vn->sock_lock); + + if (!vs) +diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c +index e30d80033cbc..19db057658c5 100644 +--- a/drivers/net/xen-netfront.c ++++ b/drivers/net/xen-netfront.c +@@ -469,9 +469,6 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, + len = skb_frag_size(frag); + offset = frag->page_offset; + +- /* Data must not cross a page boundary. */ +- BUG_ON(len + offset > PAGE_SIZE<> PAGE_SHIFT; + offset &= ~PAGE_MASK; +@@ -479,8 +476,6 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, + while (len > 0) { + unsigned long bytes; + +- BUG_ON(offset >= PAGE_SIZE); +- + bytes = PAGE_SIZE - offset; + if (bytes > len) + bytes = len; +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index 1710a8678bcb..faa8b98954d9 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1998,22 +1998,13 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td, + ep->stopped_td = td; + return 0; + } else { +- if (trb_comp_code == COMP_STALL) { +- /* The transfer is completed from the driver's +- * perspective, but we need to issue a set dequeue +- * command for this stalled endpoint to move the dequeue +- * pointer past the TD. We can't do that here because +- * the halt condition must be cleared first. Let the +- * USB class driver clear the stall later. +- */ +- ep->stopped_td = td; +- ep->stopped_stream = ep_ring->stream_id; +- } else if (xhci_requires_manual_halt_cleanup(xhci, +- ep_ctx, trb_comp_code)) { +- /* Other types of errors halt the endpoint, but the +- * class driver doesn't call usb_reset_endpoint() unless +- * the error is -EPIPE. Clear the halted status in the +- * xHCI hardware manually. ++ if (trb_comp_code == COMP_STALL || ++ xhci_requires_manual_halt_cleanup(xhci, ep_ctx, ++ trb_comp_code)) { ++ /* Issue a reset endpoint command to clear the host side ++ * halt, followed by a set dequeue command to move the ++ * dequeue pointer past the TD. ++ * The class driver clears the device side halt later. + */ + xhci_cleanup_halted_endpoint(xhci, + slot_id, ep_index, ep_ring->stream_id, +@@ -2133,9 +2124,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, + else + td->urb->actual_length = 0; + +- xhci_cleanup_halted_endpoint(xhci, +- slot_id, ep_index, 0, td, event_trb); +- return finish_td(xhci, td, event_trb, event, ep, status, true); ++ return finish_td(xhci, td, event_trb, event, ep, status, false); + } + /* + * Did we transfer any data, despite the errors that might have +@@ -2689,17 +2678,8 @@ cleanup: + if (ret) { + urb = td->urb; + urb_priv = urb->hcpriv; +- /* Leave the TD around for the reset endpoint function +- * to use(but only if it's not a control endpoint, +- * since we already queued the Set TR dequeue pointer +- * command for stalled control endpoints). +- */ +- if (usb_endpoint_xfer_control(&urb->ep->desc) || +- (trb_comp_code != COMP_STALL && +- trb_comp_code != COMP_BABBLE)) +- xhci_urb_free_priv(xhci, urb_priv); +- else +- kfree(urb_priv); ++ ++ xhci_urb_free_priv(xhci, urb_priv); + + usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb); + if ((urb->actual_length != urb->transfer_buffer_length && +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 17e398748a2d..16f4f8dc1ae9 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -2925,63 +2925,33 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, + } + } + +-/* Deal with stalled endpoints. The core should have sent the control message +- * to clear the halt condition. However, we need to make the xHCI hardware +- * reset its sequence number, since a device will expect a sequence number of +- * zero after the halt condition is cleared. ++/* Called when clearing halted device. The core should have sent the control ++ * message to clear the device halt condition. The host side of the halt should ++ * already be cleared with a reset endpoint command issued when the STALL tx ++ * event was received. ++ * + * Context: in_interrupt + */ ++ + void xhci_endpoint_reset(struct usb_hcd *hcd, + struct usb_host_endpoint *ep) + { + struct xhci_hcd *xhci; +- struct usb_device *udev; +- unsigned int ep_index; +- unsigned long flags; +- int ret; +- struct xhci_virt_ep *virt_ep; + + xhci = hcd_to_xhci(hcd); +- udev = (struct usb_device *) ep->hcpriv; +- /* Called with a root hub endpoint (or an endpoint that wasn't added +- * with xhci_add_endpoint() +- */ +- if (!ep->hcpriv) +- return; +- ep_index = xhci_get_endpoint_index(&ep->desc); +- virt_ep = &xhci->devs[udev->slot_id]->eps[ep_index]; +- if (!virt_ep->stopped_td) { +- xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep, +- "Endpoint 0x%x not halted, refusing to reset.", +- ep->desc.bEndpointAddress); +- return; +- } +- if (usb_endpoint_xfer_control(&ep->desc)) { +- xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep, +- "Control endpoint stall already handled."); +- return; +- } + +- xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep, +- "Queueing reset endpoint command"); +- spin_lock_irqsave(&xhci->lock, flags); +- ret = xhci_queue_reset_ep(xhci, udev->slot_id, ep_index); + /* +- * Can't change the ring dequeue pointer until it's transitioned to the +- * stopped state, which is only upon a successful reset endpoint +- * command. Better hope that last command worked! ++ * We might need to implement the config ep cmd in xhci 4.8.1 note: ++ * The Reset Endpoint Command may only be issued to endpoints in the ++ * Halted state. If software wishes reset the Data Toggle or Sequence ++ * Number of an endpoint that isn't in the Halted state, then software ++ * may issue a Configure Endpoint Command with the Drop and Add bits set ++ * for the target endpoint. that is in the Stopped state. + */ +- if (!ret) { +- xhci_cleanup_stalled_ring(xhci, udev, ep_index); +- kfree(virt_ep->stopped_td); +- xhci_ring_cmd_db(xhci); +- } +- virt_ep->stopped_td = NULL; +- virt_ep->stopped_stream = 0; +- spin_unlock_irqrestore(&xhci->lock, flags); + +- if (ret) +- xhci_warn(xhci, "FIXME allocate a new ring segment\n"); ++ /* For now just print debug to follow the situation */ ++ xhci_dbg(xhci, "Endpoint 0x%x ep reset callback called\n", ++ ep->desc.bEndpointAddress); + } + + static int xhci_check_streams_endpoint(struct xhci_hcd *xhci, +diff --git a/mm/frontswap.c b/mm/frontswap.c +index c30eec536f03..f2a3571c6e22 100644 +--- a/mm/frontswap.c ++++ b/mm/frontswap.c +@@ -244,8 +244,10 @@ int __frontswap_store(struct page *page) + the (older) page from frontswap + */ + inc_frontswap_failed_stores(); +- if (dup) ++ if (dup) { + __frontswap_clear(sis, offset); ++ frontswap_ops->invalidate_page(type, offset); ++ } + } + if (frontswap_writethrough_enabled) + /* report failure so swap also writes to swap device */ +diff --git a/mm/memory.c b/mm/memory.c +index 492e36f27f43..48d7365ba4e4 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -808,20 +808,20 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, + if (!pte_file(pte)) { + swp_entry_t entry = pte_to_swp_entry(pte); + +- if (swap_duplicate(entry) < 0) +- return entry.val; +- +- /* make sure dst_mm is on swapoff's mmlist. */ +- if (unlikely(list_empty(&dst_mm->mmlist))) { +- spin_lock(&mmlist_lock); +- if (list_empty(&dst_mm->mmlist)) +- list_add(&dst_mm->mmlist, +- &src_mm->mmlist); +- spin_unlock(&mmlist_lock); +- } +- if (likely(!non_swap_entry(entry))) ++ if (likely(!non_swap_entry(entry))) { ++ if (swap_duplicate(entry) < 0) ++ return entry.val; ++ ++ /* make sure dst_mm is on swapoff's mmlist. */ ++ if (unlikely(list_empty(&dst_mm->mmlist))) { ++ spin_lock(&mmlist_lock); ++ if (list_empty(&dst_mm->mmlist)) ++ list_add(&dst_mm->mmlist, ++ &src_mm->mmlist); ++ spin_unlock(&mmlist_lock); ++ } + rss[MM_SWAPENTS]++; +- else if (is_migration_entry(entry)) { ++ } else if (is_migration_entry(entry)) { + page = migration_entry_to_page(entry); + + if (PageAnon(page)) +diff --git a/mm/mmap.c b/mm/mmap.c +index dfe90657a6db..b91ac800d7b7 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -745,8 +745,11 @@ again: remove_next = 1 + (end > next->vm_end); + * shrinking vma had, to cover any anon pages imported. + */ + if (exporter && exporter->anon_vma && !importer->anon_vma) { +- if (anon_vma_clone(importer, exporter)) +- return -ENOMEM; ++ int error; ++ ++ error = anon_vma_clone(importer, exporter); ++ if (error) ++ return error; + importer->anon_vma = exporter->anon_vma; + } + } +@@ -2428,7 +2431,8 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, + if (err) + goto out_free_vma; + +- if (anon_vma_clone(new, vma)) ++ err = anon_vma_clone(new, vma); ++ if (err) + goto out_free_mpol; + + if (new->vm_file) +diff --git a/mm/rmap.c b/mm/rmap.c +index cdbd31285cf6..cab982084e2b 100644 +--- a/mm/rmap.c ++++ b/mm/rmap.c +@@ -274,6 +274,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma) + { + struct anon_vma_chain *avc; + struct anon_vma *anon_vma; ++ int error; + + /* Don't bother if the parent process has no anon_vma here. */ + if (!pvma->anon_vma) +@@ -283,8 +284,9 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma) + * First, attach the new VMA to the parent VMA's anon_vmas, + * so rmap can find non-COWed pages in child processes. + */ +- if (anon_vma_clone(vma, pvma)) +- return -ENOMEM; ++ error = anon_vma_clone(vma, pvma); ++ if (error) ++ return error; + + /* Then add our own anon_vma. */ + anon_vma = anon_vma_alloc(); +diff --git a/mm/vmpressure.c b/mm/vmpressure.c +index d4042e75f7c7..c5afd573d7da 100644 +--- a/mm/vmpressure.c ++++ b/mm/vmpressure.c +@@ -165,6 +165,7 @@ static void vmpressure_work_fn(struct work_struct *work) + unsigned long scanned; + unsigned long reclaimed; + ++ spin_lock(&vmpr->sr_lock); + /* + * Several contexts might be calling vmpressure(), so it is + * possible that the work was rescheduled again before the old +@@ -173,11 +174,12 @@ static void vmpressure_work_fn(struct work_struct *work) + * here. No need for any locks here since we don't care if + * vmpr->reclaimed is in sync. + */ +- if (!vmpr->scanned) ++ scanned = vmpr->scanned; ++ if (!scanned) { ++ spin_unlock(&vmpr->sr_lock); + return; ++ } + +- spin_lock(&vmpr->sr_lock); +- scanned = vmpr->scanned; + reclaimed = vmpr->reclaimed; + vmpr->scanned = 0; + vmpr->reclaimed = 0; +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index b0db904f083d..46175866851e 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -1453,6 +1453,7 @@ static int do_setlink(const struct sk_buff *skb, + goto errout; + } + if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) { ++ put_net(net); + err = -EPERM; + goto errout; + } +diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c +index 8c8493ea6b1c..278836f1a5ad 100644 +--- a/net/ipv4/gre_offload.c ++++ b/net/ipv4/gre_offload.c +@@ -271,6 +271,9 @@ static int gre_gro_complete(struct sk_buff *skb, int nhoff) + err = ptype->callbacks.gro_complete(skb, nhoff + grehlen); + + rcu_read_unlock(); ++ ++ skb_set_inner_mac_header(skb, nhoff + grehlen); ++ + return err; + } + +diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c +index e4a8f76c8995..b0a9cb4bbfdb 100644 +--- a/net/ipv4/ip_vti.c ++++ b/net/ipv4/ip_vti.c +@@ -369,6 +369,7 @@ static struct rtnl_link_ops vti_link_ops __read_mostly = { + .validate = vti_tunnel_validate, + .newlink = vti_newlink, + .changelink = vti_changelink, ++ .dellink = ip_tunnel_dellink, + .get_size = vti_get_size, + .fill_info = vti_fill_info, + }; +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index b27f6d34762b..4a230b18dfe3 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -508,11 +508,11 @@ static int ip6gre_rcv(struct sk_buff *skb) + + skb->protocol = gre_proto; + /* WCCP version 1 and 2 protocol decoding. +- * - Change protocol to IP ++ * - Change protocol to IPv6 + * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header + */ + if (flags == 0 && gre_proto == htons(ETH_P_WCCP)) { +- skb->protocol = htons(ETH_P_IP); ++ skb->protocol = htons(ETH_P_IPV6); + if ((*(h + offset) & 0xF0) != 0x40) + offset += 4; + } +diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c +index 9a5339fcb450..28456c9a1847 100644 +--- a/net/ipv6/ip6_vti.c ++++ b/net/ipv6/ip6_vti.c +@@ -825,6 +825,15 @@ static int vti6_newlink(struct net *src_net, struct net_device *dev, + return vti6_tnl_create2(dev); + } + ++static void vti6_dellink(struct net_device *dev, struct list_head *head) ++{ ++ struct net *net = dev_net(dev); ++ struct vti6_net *ip6n = net_generic(net, vti6_net_id); ++ ++ if (dev != ip6n->fb_tnl_dev) ++ unregister_netdevice_queue(dev, head); ++} ++ + static int vti6_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[]) + { +@@ -900,6 +909,7 @@ static struct rtnl_link_ops vti6_link_ops __read_mostly = { + .setup = vti6_dev_setup, + .validate = vti6_validate, + .newlink = vti6_newlink, ++ .dellink = vti6_dellink, + .changelink = vti6_changelink, + .get_size = vti6_get_size, + .fill_info = vti6_fill_info, +@@ -945,6 +955,7 @@ static int __net_init vti6_init_net(struct net *net) + if (!ip6n->fb_tnl_dev) + goto err_alloc_dev; + dev_net_set(ip6n->fb_tnl_dev, net); ++ ip6n->fb_tnl_dev->rtnl_link_ops = &vti6_link_ops; + + err = vti6_fb_tnl_dev_init(ip6n->fb_tnl_dev); + if (err < 0) +diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c +index 7c7df475a401..f056f9ed97fb 100644 +--- a/net/mac80211/aes_ccm.c ++++ b/net/mac80211/aes_ccm.c +@@ -54,6 +54,9 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, + + memset(&aead_req, 0, sizeof(aead_req)); + ++ if (data_len == 0) ++ return -EINVAL; ++ + sg_init_one(&pt, data, data_len); + sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); + sg_init_table(ct, 2); +diff --git a/net/sctp/output.c b/net/sctp/output.c +index 8267b06c3646..740ca5f7add0 100644 +--- a/net/sctp/output.c ++++ b/net/sctp/output.c +@@ -401,12 +401,12 @@ int sctp_packet_transmit(struct sctp_packet *packet) + sk = chunk->skb->sk; + + /* Allocate the new skb. */ +- nskb = alloc_skb(packet->size + LL_MAX_HEADER, GFP_ATOMIC); ++ nskb = alloc_skb(packet->size + MAX_HEADER, GFP_ATOMIC); + if (!nskb) + goto nomem; + + /* Make sure the outbound skb has enough header room reserved. */ +- skb_reserve(nskb, packet->overhead + LL_MAX_HEADER); ++ skb_reserve(nskb, packet->overhead + MAX_HEADER); + + /* Set the owning socket so that we know where to get the + * destination IP address. +diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c +index eaf64ea2e1c1..1a05efa08d96 100644 +--- a/sound/pci/hda/patch_analog.c ++++ b/sound/pci/hda/patch_analog.c +@@ -333,6 +333,7 @@ static const struct hda_fixup ad1986a_fixups[] = { + + static const struct snd_pci_quirk ad1986a_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_FIXUP_LAPTOP_IMIC), ++ SND_PCI_QUIRK(0x1043, 0x1443, "ASUS Z99He", AD1986A_FIXUP_EAPD), + SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8JN", AD1986A_FIXUP_EAPD), + SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8100, "ASUS P5", AD1986A_FIXUP_3STACK), + SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8200, "ASUS M2", AD1986A_FIXUP_3STACK), +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 4c826a40705c..910f2dbe1b24 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -4554,6 +4554,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), ++ SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), + SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP), + SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC), +diff --git a/sound/usb/midi.c b/sound/usb/midi.c +index b901f468b67a..c7aa71ee775b 100644 +--- a/sound/usb/midi.c ++++ b/sound/usb/midi.c +@@ -364,6 +364,8 @@ static void snd_usbmidi_error_timer(unsigned long data) + if (in && in->error_resubmit) { + in->error_resubmit = 0; + for (j = 0; j < INPUT_URBS; ++j) { ++ if (atomic_read(&in->urbs[j]->use_count)) ++ continue; + in->urbs[j]->dev = umidi->dev; + snd_usbmidi_submit_urb(in->urbs[j], GFP_ATOMIC); + } diff --git a/patch/kernel/cubox-default/patch-3.14.27-28.patch b/patch/kernel/cubox-default/patch-3.14.27-28.patch new file mode 100644 index 000000000..ac6bcbc26 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.27-28.patch @@ -0,0 +1,1961 @@ +diff --git a/Makefile b/Makefile +index 944db2356a7c..a2e572bfff7d 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 27 ++SUBLEVEL = 28 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi +index 0d8530c98cf5..34841fc1a977 100644 +--- a/arch/arm/boot/dts/armada-370.dtsi ++++ b/arch/arm/boot/dts/armada-370.dtsi +@@ -106,11 +106,6 @@ + reg = <0x11100 0x20>; + }; + +- system-controller@18200 { +- compatible = "marvell,armada-370-xp-system-controller"; +- reg = <0x18200 0x100>; +- }; +- + pinctrl { + compatible = "marvell,mv88f6710-pinctrl"; + reg = <0x18000 0x38>; +@@ -167,6 +162,11 @@ + interrupts = <91>; + }; + ++ system-controller@18200 { ++ compatible = "marvell,armada-370-xp-system-controller"; ++ reg = <0x18200 0x100>; ++ }; ++ + gateclk: clock-gating-control@18220 { + compatible = "marvell,armada-370-gating-clock"; + reg = <0x18220 0x4>; +diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S +index 8c1ba4fea384..350579961e78 100644 +--- a/arch/arm/mach-tegra/reset-handler.S ++++ b/arch/arm/mach-tegra/reset-handler.S +@@ -51,6 +51,7 @@ ENTRY(tegra_resume) + THUMB( it ne ) + bne cpu_resume @ no + ++ tegra_get_soc_id TEGRA_APB_MISC_BASE, r6 + /* Are we on Tegra20? */ + cmp r6, #TEGRA20 + beq 1f @ Yes +diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h +index 6cddbb0c9f54..e0ec201eaf56 100644 +--- a/arch/arm64/include/asm/hwcap.h ++++ b/arch/arm64/include/asm/hwcap.h +@@ -30,6 +30,7 @@ + #define COMPAT_HWCAP_IDIVA (1 << 17) + #define COMPAT_HWCAP_IDIVT (1 << 18) + #define COMPAT_HWCAP_IDIV (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT) ++#define COMPAT_HWCAP_LPAE (1 << 20) + #define COMPAT_HWCAP_EVTSTRM (1 << 21) + + #ifndef __ASSEMBLY__ +diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c +index c8e9effe52e1..071c3822442b 100644 +--- a/arch/arm64/kernel/setup.c ++++ b/arch/arm64/kernel/setup.c +@@ -67,7 +67,8 @@ EXPORT_SYMBOL_GPL(elf_hwcap); + COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\ + COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\ + COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\ +- COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV) ++ COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV|\ ++ COMPAT_HWCAP_LPAE) + unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT; + #endif + +diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c +index db02052bd137..5426c9eb5114 100644 +--- a/arch/s390/kernel/compat_linux.c ++++ b/arch/s390/kernel/compat_linux.c +@@ -245,7 +245,7 @@ asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist) + struct group_info *group_info; + int retval; + +- if (!capable(CAP_SETGID)) ++ if (!may_setgroups()) + return -EPERM; + if ((unsigned)gidsetsize > NGROUPS_MAX) + return -EINVAL; +diff --git a/arch/x86/include/uapi/asm/ldt.h b/arch/x86/include/uapi/asm/ldt.h +index 46727eb37bfe..6e1aaf73852a 100644 +--- a/arch/x86/include/uapi/asm/ldt.h ++++ b/arch/x86/include/uapi/asm/ldt.h +@@ -28,6 +28,13 @@ struct user_desc { + unsigned int seg_not_present:1; + unsigned int useable:1; + #ifdef __x86_64__ ++ /* ++ * Because this bit is not present in 32-bit user code, user ++ * programs can pass uninitialized values here. Therefore, in ++ * any context in which a user_desc comes from a 32-bit program, ++ * the kernel must act as though lm == 0, regardless of the ++ * actual value. ++ */ + unsigned int lm:1; + #endif + }; +diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c +index 713f1b3bad52..0b1e1d5dbc5b 100644 +--- a/arch/x86/kernel/kvm.c ++++ b/arch/x86/kernel/kvm.c +@@ -280,7 +280,14 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code) + static void __init paravirt_ops_setup(void) + { + pv_info.name = "KVM"; +- pv_info.paravirt_enabled = 1; ++ ++ /* ++ * KVM isn't paravirt in the sense of paravirt_enabled. A KVM ++ * guest kernel works like a bare metal kernel with additional ++ * features, and paravirt_enabled is about features that are ++ * missing. ++ */ ++ pv_info.paravirt_enabled = 0; + + if (kvm_para_has_feature(KVM_FEATURE_NOP_IO_DELAY)) + pv_cpu_ops.io_delay = kvm_io_delay; +diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c +index e6041094ff26..c8e98cdc84c2 100644 +--- a/arch/x86/kernel/kvmclock.c ++++ b/arch/x86/kernel/kvmclock.c +@@ -263,7 +263,6 @@ void __init kvmclock_init(void) + #endif + kvm_get_preset_lpj(); + clocksource_register_hz(&kvm_clock, NSEC_PER_SEC); +- pv_info.paravirt_enabled = 1; + pv_info.name = "KVM"; + + if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE_STABLE_BIT)) +diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c +index 9c0280f93d05..e2d26ce9b854 100644 +--- a/arch/x86/kernel/process_64.c ++++ b/arch/x86/kernel/process_64.c +@@ -286,24 +286,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) + + fpu = switch_fpu_prepare(prev_p, next_p, cpu); + +- /* +- * Reload esp0, LDT and the page table pointer: +- */ ++ /* Reload esp0 and ss1. */ + load_sp0(tss, next); + +- /* +- * Switch DS and ES. +- * This won't pick up thread selector changes, but I guess that is ok. +- */ +- savesegment(es, prev->es); +- if (unlikely(next->es | prev->es)) +- loadsegment(es, next->es); +- +- savesegment(ds, prev->ds); +- if (unlikely(next->ds | prev->ds)) +- loadsegment(ds, next->ds); +- +- + /* We must save %fs and %gs before load_TLS() because + * %fs and %gs may be cleared by load_TLS(). + * +@@ -312,41 +297,101 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) + savesegment(fs, fsindex); + savesegment(gs, gsindex); + ++ /* ++ * Load TLS before restoring any segments so that segment loads ++ * reference the correct GDT entries. ++ */ + load_TLS(next, cpu); + + /* +- * Leave lazy mode, flushing any hypercalls made here. +- * This must be done before restoring TLS segments so +- * the GDT and LDT are properly updated, and must be +- * done before math_state_restore, so the TS bit is up +- * to date. ++ * Leave lazy mode, flushing any hypercalls made here. This ++ * must be done after loading TLS entries in the GDT but before ++ * loading segments that might reference them, and and it must ++ * be done before math_state_restore, so the TS bit is up to ++ * date. + */ + arch_end_context_switch(next_p); + ++ /* Switch DS and ES. ++ * ++ * Reading them only returns the selectors, but writing them (if ++ * nonzero) loads the full descriptor from the GDT or LDT. The ++ * LDT for next is loaded in switch_mm, and the GDT is loaded ++ * above. ++ * ++ * We therefore need to write new values to the segment ++ * registers on every context switch unless both the new and old ++ * values are zero. ++ * ++ * Note that we don't need to do anything for CS and SS, as ++ * those are saved and restored as part of pt_regs. ++ */ ++ savesegment(es, prev->es); ++ if (unlikely(next->es | prev->es)) ++ loadsegment(es, next->es); ++ ++ savesegment(ds, prev->ds); ++ if (unlikely(next->ds | prev->ds)) ++ loadsegment(ds, next->ds); ++ + /* + * Switch FS and GS. + * +- * Segment register != 0 always requires a reload. Also +- * reload when it has changed. When prev process used 64bit +- * base always reload to avoid an information leak. ++ * These are even more complicated than FS and GS: they have ++ * 64-bit bases are that controlled by arch_prctl. Those bases ++ * only differ from the values in the GDT or LDT if the selector ++ * is 0. ++ * ++ * Loading the segment register resets the hidden base part of ++ * the register to 0 or the value from the GDT / LDT. If the ++ * next base address zero, writing 0 to the segment register is ++ * much faster than using wrmsr to explicitly zero the base. ++ * ++ * The thread_struct.fs and thread_struct.gs values are 0 ++ * if the fs and gs bases respectively are not overridden ++ * from the values implied by fsindex and gsindex. They ++ * are nonzero, and store the nonzero base addresses, if ++ * the bases are overridden. ++ * ++ * (fs != 0 && fsindex != 0) || (gs != 0 && gsindex != 0) should ++ * be impossible. ++ * ++ * Therefore we need to reload the segment registers if either ++ * the old or new selector is nonzero, and we need to override ++ * the base address if next thread expects it to be overridden. ++ * ++ * This code is unnecessarily slow in the case where the old and ++ * new indexes are zero and the new base is nonzero -- it will ++ * unnecessarily write 0 to the selector before writing the new ++ * base address. ++ * ++ * Note: This all depends on arch_prctl being the only way that ++ * user code can override the segment base. Once wrfsbase and ++ * wrgsbase are enabled, most of this code will need to change. + */ + if (unlikely(fsindex | next->fsindex | prev->fs)) { + loadsegment(fs, next->fsindex); ++ + /* +- * Check if the user used a selector != 0; if yes +- * clear 64bit base, since overloaded base is always +- * mapped to the Null selector ++ * If user code wrote a nonzero value to FS, then it also ++ * cleared the overridden base address. ++ * ++ * XXX: if user code wrote 0 to FS and cleared the base ++ * address itself, we won't notice and we'll incorrectly ++ * restore the prior base address next time we reschdule ++ * the process. + */ + if (fsindex) + prev->fs = 0; + } +- /* when next process has a 64bit base use it */ + if (next->fs) + wrmsrl(MSR_FS_BASE, next->fs); + prev->fsindex = fsindex; + + if (unlikely(gsindex | next->gsindex | prev->gs)) { + load_gs_index(next->gsindex); ++ ++ /* This works (and fails) the same way as fsindex above. */ + if (gsindex) + prev->gs = 0; + } +diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c +index f7fec09e3e3a..4e942f31b1a7 100644 +--- a/arch/x86/kernel/tls.c ++++ b/arch/x86/kernel/tls.c +@@ -27,6 +27,37 @@ static int get_free_idx(void) + return -ESRCH; + } + ++static bool tls_desc_okay(const struct user_desc *info) ++{ ++ if (LDT_empty(info)) ++ return true; ++ ++ /* ++ * espfix is required for 16-bit data segments, but espfix ++ * only works for LDT segments. ++ */ ++ if (!info->seg_32bit) ++ return false; ++ ++ /* Only allow data segments in the TLS array. */ ++ if (info->contents > 1) ++ return false; ++ ++ /* ++ * Non-present segments with DPL 3 present an interesting attack ++ * surface. The kernel should handle such segments correctly, ++ * but TLS is very difficult to protect in a sandbox, so prevent ++ * such segments from being created. ++ * ++ * If userspace needs to remove a TLS entry, it can still delete ++ * it outright. ++ */ ++ if (info->seg_not_present) ++ return false; ++ ++ return true; ++} ++ + static void set_tls_desc(struct task_struct *p, int idx, + const struct user_desc *info, int n) + { +@@ -66,6 +97,9 @@ int do_set_thread_area(struct task_struct *p, int idx, + if (copy_from_user(&info, u_info, sizeof(info))) + return -EFAULT; + ++ if (!tls_desc_okay(&info)) ++ return -EINVAL; ++ + if (idx == -1) + idx = info.entry_number; + +@@ -192,6 +226,7 @@ int regset_tls_set(struct task_struct *target, const struct user_regset *regset, + { + struct user_desc infobuf[GDT_ENTRY_TLS_ENTRIES]; + const struct user_desc *info; ++ int i; + + if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) || + (pos % sizeof(struct user_desc)) != 0 || +@@ -205,6 +240,10 @@ int regset_tls_set(struct task_struct *target, const struct user_regset *regset, + else + info = infobuf; + ++ for (i = 0; i < count / sizeof(struct user_desc); i++) ++ if (!tls_desc_okay(info + i)) ++ return -EINVAL; ++ + set_tls_desc(target, + GDT_ENTRY_TLS_MIN + (pos / sizeof(struct user_desc)), + info, count / sizeof(struct user_desc)); +diff --git a/crypto/af_alg.c b/crypto/af_alg.c +index 6a3ad8011585..1de4beeb25f8 100644 +--- a/crypto/af_alg.c ++++ b/crypto/af_alg.c +@@ -449,6 +449,9 @@ void af_alg_complete(struct crypto_async_request *req, int err) + { + struct af_alg_completion *completion = req->data; + ++ if (err == -EINPROGRESS) ++ return; ++ + completion->err = err; + complete(&completion->completion); + } +diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c +index 4195a01b1535..8e51b3a3e7b9 100644 +--- a/drivers/md/bitmap.c ++++ b/drivers/md/bitmap.c +@@ -883,7 +883,6 @@ void bitmap_unplug(struct bitmap *bitmap) + { + unsigned long i; + int dirty, need_write; +- int wait = 0; + + if (!bitmap || !bitmap->storage.filemap || + test_bit(BITMAP_STALE, &bitmap->flags)) +@@ -901,16 +900,13 @@ void bitmap_unplug(struct bitmap *bitmap) + clear_page_attr(bitmap, i, BITMAP_PAGE_PENDING); + write_page(bitmap, bitmap->storage.filemap[i], 0); + } +- if (dirty) +- wait = 1; +- } +- if (wait) { /* if any writes were performed, we need to wait on them */ +- if (bitmap->storage.file) +- wait_event(bitmap->write_wait, +- atomic_read(&bitmap->pending_writes)==0); +- else +- md_super_wait(bitmap->mddev); + } ++ if (bitmap->storage.file) ++ wait_event(bitmap->write_wait, ++ atomic_read(&bitmap->pending_writes)==0); ++ else ++ md_super_wait(bitmap->mddev); ++ + if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) + bitmap_file_kick(bitmap); + } +diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c +index a1cebf745b22..03c872fd5d5c 100644 +--- a/drivers/md/dm-bufio.c ++++ b/drivers/md/dm-bufio.c +@@ -532,6 +532,19 @@ static void use_dmio(struct dm_buffer *b, int rw, sector_t block, + end_io(&b->bio, r); + } + ++static void inline_endio(struct bio *bio, int error) ++{ ++ bio_end_io_t *end_fn = bio->bi_private; ++ ++ /* ++ * Reset the bio to free any attached resources ++ * (e.g. bio integrity profiles). ++ */ ++ bio_reset(bio); ++ ++ end_fn(bio, error); ++} ++ + static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block, + bio_end_io_t *end_io) + { +@@ -543,7 +556,12 @@ static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block, + b->bio.bi_max_vecs = DM_BUFIO_INLINE_VECS; + b->bio.bi_iter.bi_sector = block << b->c->sectors_per_block_bits; + b->bio.bi_bdev = b->c->bdev; +- b->bio.bi_end_io = end_io; ++ b->bio.bi_end_io = inline_endio; ++ /* ++ * Use of .bi_private isn't a problem here because ++ * the dm_buffer's inline bio is local to bufio. ++ */ ++ b->bio.bi_private = end_io; + + /* + * We assume that if len >= PAGE_SIZE ptr is page-aligned. +diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c +index 2331543005b2..ff284b7a17bd 100644 +--- a/drivers/md/dm-cache-target.c ++++ b/drivers/md/dm-cache-target.c +@@ -946,10 +946,14 @@ static void migration_success_post_commit(struct dm_cache_migration *mg) + } + + } else { +- clear_dirty(cache, mg->new_oblock, mg->cblock); +- if (mg->requeue_holder) ++ if (mg->requeue_holder) { ++ clear_dirty(cache, mg->new_oblock, mg->cblock); + cell_defer(cache, mg->new_ocell, true); +- else { ++ } else { ++ /* ++ * The block was promoted via an overwrite, so it's dirty. ++ */ ++ set_dirty(cache, mg->new_oblock, mg->cblock); + bio_endio(mg->new_ocell->holder, 0); + cell_defer(cache, mg->new_ocell, false); + } +@@ -1060,7 +1064,8 @@ static void issue_copy(struct dm_cache_migration *mg) + + avoid = is_discarded_oblock(cache, mg->new_oblock); + +- if (!avoid && bio_writes_complete_block(cache, bio)) { ++ if (writeback_mode(&cache->features) && ++ !avoid && bio_writes_complete_block(cache, bio)) { + issue_overwrite(mg, bio); + return; + } +diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c +index 9533f835ce07..4a8d19d0a5a4 100644 +--- a/drivers/md/dm-crypt.c ++++ b/drivers/md/dm-crypt.c +@@ -709,7 +709,7 @@ static int crypt_iv_tcw_whitening(struct crypt_config *cc, + for (i = 0; i < ((1 << SECTOR_SHIFT) / 8); i++) + crypto_xor(data + i * 8, buf, 8); + out: +- memset(buf, 0, sizeof(buf)); ++ memzero_explicit(buf, sizeof(buf)); + return r; + } + +diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c +index 37f2648c112b..f7e052c7ab5f 100644 +--- a/drivers/md/dm-thin.c ++++ b/drivers/md/dm-thin.c +@@ -916,6 +916,24 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block, + } + } + ++static void set_pool_mode(struct pool *pool, enum pool_mode new_mode); ++ ++static void check_for_space(struct pool *pool) ++{ ++ int r; ++ dm_block_t nr_free; ++ ++ if (get_pool_mode(pool) != PM_OUT_OF_DATA_SPACE) ++ return; ++ ++ r = dm_pool_get_free_block_count(pool->pmd, &nr_free); ++ if (r) ++ return; ++ ++ if (nr_free) ++ set_pool_mode(pool, PM_WRITE); ++} ++ + /* + * A non-zero return indicates read_only or fail_io mode. + * Many callers don't care about the return value. +@@ -930,6 +948,8 @@ static int commit(struct pool *pool) + r = dm_pool_commit_metadata(pool->pmd); + if (r) + metadata_operation_failed(pool, "dm_pool_commit_metadata", r); ++ else ++ check_for_space(pool); + + return r; + } +@@ -948,8 +968,6 @@ static void check_low_water_mark(struct pool *pool, dm_block_t free_blocks) + } + } + +-static void set_pool_mode(struct pool *pool, enum pool_mode new_mode); +- + static int alloc_data_block(struct thin_c *tc, dm_block_t *result) + { + int r; +@@ -1592,7 +1610,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) + pool->process_bio = process_bio_read_only; + pool->process_discard = process_discard; + pool->process_prepared_mapping = process_prepared_mapping; +- pool->process_prepared_discard = process_prepared_discard_passdown; ++ pool->process_prepared_discard = process_prepared_discard; + + if (!pool->pf.error_if_no_space && no_space_timeout) + queue_delayed_work(pool->wq, &pool->no_space_timeout, no_space_timeout); +diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c +index 786b689bdfc7..f4e22bcc7fb8 100644 +--- a/drivers/md/persistent-data/dm-space-map-metadata.c ++++ b/drivers/md/persistent-data/dm-space-map-metadata.c +@@ -564,7 +564,9 @@ static int sm_bootstrap_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count + { + struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); + +- return smm->ll.nr_blocks; ++ *count = smm->ll.nr_blocks; ++ ++ return 0; + } + + static int sm_bootstrap_get_nr_free(struct dm_space_map *sm, dm_block_t *count) +diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c +index 11c19e538551..48579e5ef02c 100644 +--- a/drivers/mfd/tc6393xb.c ++++ b/drivers/mfd/tc6393xb.c +@@ -263,6 +263,17 @@ static int tc6393xb_ohci_disable(struct platform_device *dev) + return 0; + } + ++static int tc6393xb_ohci_suspend(struct platform_device *dev) ++{ ++ struct tc6393xb_platform_data *tcpd = dev_get_platdata(dev->dev.parent); ++ ++ /* We can't properly store/restore OHCI state, so fail here */ ++ if (tcpd->resume_restore) ++ return -EBUSY; ++ ++ return tc6393xb_ohci_disable(dev); ++} ++ + static int tc6393xb_fb_enable(struct platform_device *dev) + { + struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent); +@@ -403,7 +414,7 @@ static struct mfd_cell tc6393xb_cells[] = { + .num_resources = ARRAY_SIZE(tc6393xb_ohci_resources), + .resources = tc6393xb_ohci_resources, + .enable = tc6393xb_ohci_enable, +- .suspend = tc6393xb_ohci_disable, ++ .suspend = tc6393xb_ohci_suspend, + .resume = tc6393xb_ohci_enable, + .disable = tc6393xb_ohci_disable, + }, +diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c +index 7b5424f398ac..df72c478c5a2 100644 +--- a/drivers/mmc/card/block.c ++++ b/drivers/mmc/card/block.c +@@ -260,7 +260,7 @@ static ssize_t force_ro_show(struct device *dev, struct device_attribute *attr, + int ret; + struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev)); + +- ret = snprintf(buf, PAGE_SIZE, "%d", ++ ret = snprintf(buf, PAGE_SIZE, "%d\n", + get_disk_ro(dev_to_disk(dev)) ^ + md->read_only); + mmc_blk_put(md); +diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c +index 55cd110a49c4..caed9d53e8fa 100644 +--- a/drivers/mmc/host/dw_mmc.c ++++ b/drivers/mmc/host/dw_mmc.c +@@ -632,6 +632,13 @@ static void dw_mci_ctrl_rd_thld(struct dw_mci *host, struct mmc_data *data) + + WARN_ON(!(data->flags & MMC_DATA_READ)); + ++ /* ++ * CDTHRCTL doesn't exist prior to 240A (in fact that register offset is ++ * in the FIFO region, so we really shouldn't access it). ++ */ ++ if (host->verid < DW_MMC_240A) ++ return; ++ + if (host->timing != MMC_TIMING_MMC_HS200 && + host->timing != MMC_TIMING_UHS_SDR104) + goto disable; +diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c +index f49666bcc52a..257e9ca30166 100644 +--- a/drivers/mmc/host/sdhci-pci-o2micro.c ++++ b/drivers/mmc/host/sdhci-pci-o2micro.c +@@ -88,8 +88,6 @@ void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip) + return; + scratch_32 &= ~((1 << 21) | (1 << 30)); + +- /* Set RTD3 function disabled */ +- scratch_32 |= ((1 << 29) | (1 << 28)); + pci_write_config_dword(chip->pdev, O2_SD_FUNC_REG3, scratch_32); + + /* Set L1 Entrance Timer */ +diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c +index 1e9d6ad9302b..7563b3d9cc76 100644 +--- a/drivers/scsi/NCR5380.c ++++ b/drivers/scsi/NCR5380.c +@@ -2655,14 +2655,14 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) { + * + * Purpose : abort a command + * +- * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the +- * host byte of the result field to, if zero DID_ABORTED is ++ * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the ++ * host byte of the result field to, if zero DID_ABORTED is + * used. + * +- * Returns : 0 - success, -1 on failure. ++ * Returns : SUCCESS - success, FAILED on failure. + * +- * XXX - there is no way to abort the command that is currently +- * connected, you have to wait for it to complete. If this is ++ * XXX - there is no way to abort the command that is currently ++ * connected, you have to wait for it to complete. If this is + * a problem, we could implement longjmp() / setjmp(), setjmp() + * called where the loop started in NCR5380_main(). + * +@@ -2712,7 +2712,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) { + * aborted flag and get back into our main loop. + */ + +- return 0; ++ return SUCCESS; + } + #endif + +diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c +index 5f3101797c93..31ace4bef8fe 100644 +--- a/drivers/scsi/aha1740.c ++++ b/drivers/scsi/aha1740.c +@@ -531,7 +531,7 @@ static int aha1740_eh_abort_handler (Scsi_Cmnd *dummy) + * quiet as possible... + */ + +- return 0; ++ return SUCCESS; + } + + static struct scsi_host_template aha1740_template = { +diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c +index 0f3cdbc80ba6..30073d43d87b 100644 +--- a/drivers/scsi/atari_NCR5380.c ++++ b/drivers/scsi/atari_NCR5380.c +@@ -2613,7 +2613,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) + * host byte of the result field to, if zero DID_ABORTED is + * used. + * +- * Returns : 0 - success, -1 on failure. ++ * Returns : SUCCESS - success, FAILED on failure. + * + * XXX - there is no way to abort the command that is currently + * connected, you have to wait for it to complete. If this is +diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c +index f37f3e3dd5d5..28fe6feae44c 100644 +--- a/drivers/scsi/esas2r/esas2r_main.c ++++ b/drivers/scsi/esas2r/esas2r_main.c +@@ -1057,7 +1057,7 @@ int esas2r_eh_abort(struct scsi_cmnd *cmd) + + cmd->scsi_done(cmd); + +- return 0; ++ return SUCCESS; + } + + spin_lock_irqsave(&a->queue_lock, flags); +diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c +index 816db12ef5d5..52587ceac099 100644 +--- a/drivers/scsi/megaraid.c ++++ b/drivers/scsi/megaraid.c +@@ -1967,7 +1967,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor) + cmd->device->id, cmd->device->lun); + + if(list_empty(&adapter->pending_list)) +- return FALSE; ++ return FAILED; + + list_for_each_safe(pos, next, &adapter->pending_list) { + +@@ -1990,7 +1990,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor) + (aor==SCB_ABORT) ? "ABORTING":"RESET", + scb->idx); + +- return FALSE; ++ return FAILED; + } + else { + +@@ -2015,12 +2015,12 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor) + list_add_tail(SCSI_LIST(cmd), + &adapter->completed_list); + +- return TRUE; ++ return SUCCESS; + } + } + } + +- return FALSE; ++ return FAILED; + } + + static inline int +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index 3b7ad10497fe..c80afde97e96 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -953,7 +953,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, + cpu_to_le32(upper_32_bits(cmd_to_abort->frame_phys_addr)); + + cmd->sync_cmd = 1; +- cmd->cmd_status = 0xFF; ++ cmd->cmd_status = ENODATA; + + instance->instancet->issue_dcmd(instance, cmd); + +diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c +index 636bbe0ea84c..fc57c8aec2b3 100644 +--- a/drivers/scsi/sun3_NCR5380.c ++++ b/drivers/scsi/sun3_NCR5380.c +@@ -2597,15 +2597,15 @@ static void NCR5380_reselect (struct Scsi_Host *instance) + * Purpose : abort a command + * + * Inputs : cmd - the struct scsi_cmnd to abort, code - code to set the +- * host byte of the result field to, if zero DID_ABORTED is ++ * host byte of the result field to, if zero DID_ABORTED is + * used. + * +- * Returns : 0 - success, -1 on failure. ++ * Returns : SUCCESS - success, FAILED on failure. + * +- * XXX - there is no way to abort the command that is currently +- * connected, you have to wait for it to complete. If this is ++ * XXX - there is no way to abort the command that is currently ++ * connected, you have to wait for it to complete. If this is + * a problem, we could implement longjmp() / setjmp(), setjmp() +- * called where the loop started in NCR5380_main(). ++ * called where the loop started in NCR5380_main(). + */ + + static int NCR5380_abort(struct scsi_cmnd *cmd) +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index 71b0ec0c370d..284733e1fb6f 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -1824,10 +1824,10 @@ static int __init thermal_init(void) + + exit_netlink: + genetlink_exit(); +-unregister_governors: +- thermal_unregister_governors(); + unregister_class: + class_unregister(&thermal_class); ++unregister_governors: ++ thermal_unregister_governors(); + error: + idr_destroy(&thermal_tz_idr); + idr_destroy(&thermal_cdev_idr); +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index 370ef7450157..0db8ded65923 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -3978,12 +3978,6 @@ again: + if (ret) + break; + +- /* opt_discard */ +- if (btrfs_test_opt(root, DISCARD)) +- ret = btrfs_error_discard_extent(root, start, +- end + 1 - start, +- NULL); +- + clear_extent_dirty(unpin, start, end, GFP_NOFS); + btrfs_error_unpin_extent_range(root, start, end); + cond_resched(); +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 3ff98e23f651..d2f1c011d73a 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -5503,7 +5503,8 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans, + update_global_block_rsv(fs_info); + } + +-static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) ++static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end, ++ const bool return_free_space) + { + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_block_group_cache *cache = NULL; +@@ -5527,7 +5528,8 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) + + if (start < cache->last_byte_to_unpin) { + len = min(len, cache->last_byte_to_unpin - start); +- btrfs_add_free_space(cache, start, len); ++ if (return_free_space) ++ btrfs_add_free_space(cache, start, len); + } + + start += len; +@@ -5590,7 +5592,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, + end + 1 - start, NULL); + + clear_extent_dirty(unpin, start, end, GFP_NOFS); +- unpin_extent_range(root, start, end); ++ unpin_extent_range(root, start, end, true); + cond_resched(); + } + +@@ -8886,7 +8888,7 @@ out: + + int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) + { +- return unpin_extent_range(root, start, end); ++ return unpin_extent_range(root, start, end, false); + } + + int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr, +diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c +index 996ad56b57db..82845a6c63c2 100644 +--- a/fs/btrfs/extent_map.c ++++ b/fs/btrfs/extent_map.c +@@ -290,8 +290,6 @@ int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, + if (!em) + goto out; + +- if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags)) +- list_move(&em->list, &tree->modified_extents); + em->generation = gen; + clear_bit(EXTENT_FLAG_PINNED, &em->flags); + em->mod_start = em->start; +diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c +index 2f6735dbf1a9..31b148f3e772 100644 +--- a/fs/ecryptfs/crypto.c ++++ b/fs/ecryptfs/crypto.c +@@ -1917,7 +1917,6 @@ ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size, + break; + case 2: + dst[dst_byte_offset++] |= (src_byte); +- dst[dst_byte_offset] = 0; + current_bit_offset = 0; + break; + } +diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c +index b1eaa7a1f82c..03df50211c48 100644 +--- a/fs/ecryptfs/file.c ++++ b/fs/ecryptfs/file.c +@@ -191,23 +191,11 @@ static int ecryptfs_open(struct inode *inode, struct file *file) + { + int rc = 0; + struct ecryptfs_crypt_stat *crypt_stat = NULL; +- struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + struct dentry *ecryptfs_dentry = file->f_path.dentry; + /* Private value of ecryptfs_dentry allocated in + * ecryptfs_lookup() */ + struct ecryptfs_file_info *file_info; + +- mount_crypt_stat = &ecryptfs_superblock_to_private( +- ecryptfs_dentry->d_sb)->mount_crypt_stat; +- if ((mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) +- && ((file->f_flags & O_WRONLY) || (file->f_flags & O_RDWR) +- || (file->f_flags & O_CREAT) || (file->f_flags & O_TRUNC) +- || (file->f_flags & O_APPEND))) { +- printk(KERN_WARNING "Mount has encrypted view enabled; " +- "files may only be read\n"); +- rc = -EPERM; +- goto out; +- } + /* Released in ecryptfs_release or end of function if failure */ + file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL); + ecryptfs_set_file_private(file, file_info); +diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c +index 1b119d3bf924..34eb8433d93f 100644 +--- a/fs/ecryptfs/main.c ++++ b/fs/ecryptfs/main.c +@@ -493,6 +493,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags + { + struct super_block *s; + struct ecryptfs_sb_info *sbi; ++ struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + struct ecryptfs_dentry_info *root_info; + const char *err = "Getting sb failed"; + struct inode *inode; +@@ -511,6 +512,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags + err = "Error parsing options"; + goto out; + } ++ mount_crypt_stat = &sbi->mount_crypt_stat; + + s = sget(fs_type, NULL, set_anon_super, flags, NULL); + if (IS_ERR(s)) { +@@ -557,11 +559,19 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags + + /** + * Set the POSIX ACL flag based on whether they're enabled in the lower +- * mount. Force a read-only eCryptfs mount if the lower mount is ro. +- * Allow a ro eCryptfs mount even when the lower mount is rw. ++ * mount. + */ + s->s_flags = flags & ~MS_POSIXACL; +- s->s_flags |= path.dentry->d_sb->s_flags & (MS_RDONLY | MS_POSIXACL); ++ s->s_flags |= path.dentry->d_sb->s_flags & MS_POSIXACL; ++ ++ /** ++ * Force a read-only eCryptfs mount when: ++ * 1) The lower mount is ro ++ * 2) The ecryptfs_encrypted_view mount option is specified ++ */ ++ if (path.dentry->d_sb->s_flags & MS_RDONLY || ++ mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) ++ s->s_flags |= MS_RDONLY; + + s->s_maxbytes = path.dentry->d_sb->s_maxbytes; + s->s_blocksize = path.dentry->d_sb->s_blocksize; +diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c +index f488bbae541a..735d7522a3a9 100644 +--- a/fs/isofs/rock.c ++++ b/fs/isofs/rock.c +@@ -30,6 +30,7 @@ struct rock_state { + int cont_size; + int cont_extent; + int cont_offset; ++ int cont_loops; + struct inode *inode; + }; + +@@ -73,6 +74,9 @@ static void init_rock_state(struct rock_state *rs, struct inode *inode) + rs->inode = inode; + } + ++/* Maximum number of Rock Ridge continuation entries */ ++#define RR_MAX_CE_ENTRIES 32 ++ + /* + * Returns 0 if the caller should continue scanning, 1 if the scan must end + * and -ve on error. +@@ -105,6 +109,8 @@ static int rock_continue(struct rock_state *rs) + goto out; + } + ret = -EIO; ++ if (++rs->cont_loops >= RR_MAX_CE_ENTRIES) ++ goto out; + bh = sb_bread(rs->inode->i_sb, rs->cont_extent); + if (bh) { + memcpy(rs->buffer, bh->b_data + rs->cont_offset, +@@ -356,6 +362,9 @@ repeat: + rs.cont_size = isonum_733(rr->u.CE.size); + break; + case SIG('E', 'R'): ++ /* Invalid length of ER tag id? */ ++ if (rr->u.ER.len_id + offsetof(struct rock_ridge, u.ER.data) > rr->len) ++ goto out; + ISOFS_SB(inode->i_sb)->s_rock = 1; + printk(KERN_DEBUG "ISO 9660 Extensions: "); + { +diff --git a/fs/namespace.c b/fs/namespace.c +index d9bf3efbf040..039f3802d70e 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1295,6 +1295,8 @@ void umount_tree(struct mount *mnt, int how) + } + if (last) { + last->mnt_hash.next = unmounted.first; ++ if (unmounted.first) ++ unmounted.first->pprev = &last->mnt_hash.next; + unmounted.first = tmp_list.first; + unmounted.first->pprev = &unmounted.first; + } +@@ -1439,6 +1441,9 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags) + goto dput_and_out; + if (mnt->mnt.mnt_flags & MNT_LOCKED) + goto dput_and_out; ++ retval = -EPERM; ++ if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN)) ++ goto dput_and_out; + + retval = do_umount(mnt, flags); + dput_and_out: +@@ -1964,7 +1969,13 @@ static int do_remount(struct path *path, int flags, int mnt_flags, + } + if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) && + !(mnt_flags & MNT_NODEV)) { +- return -EPERM; ++ /* Was the nodev implicitly added in mount? */ ++ if ((mnt->mnt_ns->user_ns != &init_user_ns) && ++ !(sb->s_type->fs_flags & FS_USERNS_DEV_MOUNT)) { ++ mnt_flags |= MNT_NODEV; ++ } else { ++ return -EPERM; ++ } + } + if ((mnt->mnt.mnt_flags & MNT_LOCK_NOSUID) && + !(mnt_flags & MNT_NOSUID)) { +diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c +index 60426ccb3b65..2f970de02b16 100644 +--- a/fs/ncpfs/ioctl.c ++++ b/fs/ncpfs/ioctl.c +@@ -448,7 +448,6 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg + result = -EIO; + } + } +- result = 0; + } + mutex_unlock(&server->root_setup_lock); + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index bd01803d0656..58258ad50d5f 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -7589,6 +7589,9 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) + + dprintk("--> %s\n", __func__); + ++ /* nfs4_layoutget_release calls pnfs_put_layout_hdr */ ++ pnfs_get_layout_hdr(NFS_I(inode)->layout); ++ + lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); + if (!lgp->args.layout.pages) { + nfs4_layoutget_release(lgp); +@@ -7601,9 +7604,6 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) + lgp->res.seq_res.sr_slot = NULL; + nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); + +- /* nfs4_layoutget_release calls pnfs_put_layout_hdr */ +- pnfs_get_layout_hdr(NFS_I(inode)->layout); +- + task = rpc_run_task(&task_setup_data); + if (IS_ERR(task)) + return ERR_CAST(task); +diff --git a/fs/proc/base.c b/fs/proc/base.c +index b9760628e1fd..489ba8caafc0 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -2555,6 +2555,57 @@ static const struct file_operations proc_projid_map_operations = { + .llseek = seq_lseek, + .release = proc_id_map_release, + }; ++ ++static int proc_setgroups_open(struct inode *inode, struct file *file) ++{ ++ struct user_namespace *ns = NULL; ++ struct task_struct *task; ++ int ret; ++ ++ ret = -ESRCH; ++ task = get_proc_task(inode); ++ if (task) { ++ rcu_read_lock(); ++ ns = get_user_ns(task_cred_xxx(task, user_ns)); ++ rcu_read_unlock(); ++ put_task_struct(task); ++ } ++ if (!ns) ++ goto err; ++ ++ if (file->f_mode & FMODE_WRITE) { ++ ret = -EACCES; ++ if (!ns_capable(ns, CAP_SYS_ADMIN)) ++ goto err_put_ns; ++ } ++ ++ ret = single_open(file, &proc_setgroups_show, ns); ++ if (ret) ++ goto err_put_ns; ++ ++ return 0; ++err_put_ns: ++ put_user_ns(ns); ++err: ++ return ret; ++} ++ ++static int proc_setgroups_release(struct inode *inode, struct file *file) ++{ ++ struct seq_file *seq = file->private_data; ++ struct user_namespace *ns = seq->private; ++ int ret = single_release(inode, file); ++ put_user_ns(ns); ++ return ret; ++} ++ ++static const struct file_operations proc_setgroups_operations = { ++ .open = proc_setgroups_open, ++ .write = proc_setgroups_write, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = proc_setgroups_release, ++}; + #endif /* CONFIG_USER_NS */ + + static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns, +@@ -2663,6 +2714,7 @@ static const struct pid_entry tgid_base_stuff[] = { + REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations), + REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations), + REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations), ++ REG("setgroups", S_IRUGO|S_IWUSR, proc_setgroups_operations), + #endif + #ifdef CONFIG_CHECKPOINT_RESTORE + REG("timers", S_IRUGO, proc_timers_operations), +@@ -2998,6 +3050,7 @@ static const struct pid_entry tid_base_stuff[] = { + REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations), + REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations), + REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations), ++ REG("setgroups", S_IRUGO|S_IWUSR, proc_setgroups_operations), + #endif + }; + +diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c +index d7c6dbe4194b..d89f324bc387 100644 +--- a/fs/udf/symlink.c ++++ b/fs/udf/symlink.c +@@ -80,11 +80,17 @@ static int udf_symlink_filler(struct file *file, struct page *page) + struct inode *inode = page->mapping->host; + struct buffer_head *bh = NULL; + unsigned char *symlink; +- int err = -EIO; ++ int err; + unsigned char *p = kmap(page); + struct udf_inode_info *iinfo; + uint32_t pos; + ++ /* We don't support symlinks longer than one block */ ++ if (inode->i_size > inode->i_sb->s_blocksize) { ++ err = -ENAMETOOLONG; ++ goto out_unmap; ++ } ++ + iinfo = UDF_I(inode); + pos = udf_block_map(inode, 0); + +@@ -94,8 +100,10 @@ static int udf_symlink_filler(struct file *file, struct page *page) + } else { + bh = sb_bread(inode->i_sb, pos); + +- if (!bh) +- goto out; ++ if (!bh) { ++ err = -EIO; ++ goto out_unlock_inode; ++ } + + symlink = bh->b_data; + } +@@ -109,9 +117,10 @@ static int udf_symlink_filler(struct file *file, struct page *page) + unlock_page(page); + return 0; + +-out: ++out_unlock_inode: + up_read(&iinfo->i_data_sem); + SetPageError(page); ++out_unmap: + kunmap(page); + unlock_page(page); + return err; +diff --git a/include/linux/audit.h b/include/linux/audit.h +index ec1464df4c60..419b7d7d7a7f 100644 +--- a/include/linux/audit.h ++++ b/include/linux/audit.h +@@ -47,6 +47,7 @@ struct sk_buff; + + struct audit_krule { + int vers_ops; ++ u32 pflags; + u32 flags; + u32 listnr; + u32 action; +@@ -64,6 +65,9 @@ struct audit_krule { + u64 prio; + }; + ++/* Flag to indicate legacy AUDIT_LOGINUID unset usage */ ++#define AUDIT_LOGINUID_LEGACY 0x1 ++ + struct audit_field { + u32 type; + u32 val; +diff --git a/include/linux/cred.h b/include/linux/cred.h +index 04421e825365..6c58dd7cb9ac 100644 +--- a/include/linux/cred.h ++++ b/include/linux/cred.h +@@ -68,6 +68,7 @@ extern void groups_free(struct group_info *); + extern int set_current_groups(struct group_info *); + extern int set_groups(struct cred *, struct group_info *); + extern int groups_search(const struct group_info *, kgid_t); ++extern bool may_setgroups(void); + + /* access the groups "array" with this macro */ + #define GROUP_AT(gi, i) \ +diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h +index 4836ba3c1cd8..e92abf9e796f 100644 +--- a/include/linux/user_namespace.h ++++ b/include/linux/user_namespace.h +@@ -17,6 +17,10 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */ + } extent[UID_GID_MAP_MAX_EXTENTS]; + }; + ++#define USERNS_SETGROUPS_ALLOWED 1UL ++ ++#define USERNS_INIT_FLAGS USERNS_SETGROUPS_ALLOWED ++ + struct user_namespace { + struct uid_gid_map uid_map; + struct uid_gid_map gid_map; +@@ -27,6 +31,7 @@ struct user_namespace { + kuid_t owner; + kgid_t group; + unsigned int proc_inum; ++ unsigned long flags; + + /* Register of per-UID persistent keyrings for this namespace */ + #ifdef CONFIG_PERSISTENT_KEYRINGS +@@ -63,6 +68,9 @@ extern struct seq_operations proc_projid_seq_operations; + extern ssize_t proc_uid_map_write(struct file *, const char __user *, size_t, loff_t *); + extern ssize_t proc_gid_map_write(struct file *, const char __user *, size_t, loff_t *); + extern ssize_t proc_projid_map_write(struct file *, const char __user *, size_t, loff_t *); ++extern ssize_t proc_setgroups_write(struct file *, const char __user *, size_t, loff_t *); ++extern int proc_setgroups_show(struct seq_file *m, void *v); ++extern bool userns_may_setgroups(const struct user_namespace *ns); + #else + + static inline struct user_namespace *get_user_ns(struct user_namespace *ns) +@@ -87,6 +95,10 @@ static inline void put_user_ns(struct user_namespace *ns) + { + } + ++static inline bool userns_may_setgroups(const struct user_namespace *ns) ++{ ++ return true; ++} + #endif + + #endif /* _LINUX_USER_H */ +diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c +index 92062fd6cc8c..598c1dcf26dd 100644 +--- a/kernel/auditfilter.c ++++ b/kernel/auditfilter.c +@@ -429,6 +429,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, + if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) { + f->type = AUDIT_LOGINUID_SET; + f->val = 0; ++ entry->rule.pflags |= AUDIT_LOGINUID_LEGACY; + } + + err = audit_field_valid(entry, f); +@@ -604,6 +605,13 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) + data->buflen += data->values[i] = + audit_pack_string(&bufp, krule->filterkey); + break; ++ case AUDIT_LOGINUID_SET: ++ if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) { ++ data->fields[i] = AUDIT_LOGINUID; ++ data->values[i] = AUDIT_UID_UNSET; ++ break; ++ } ++ /* fallthrough if set */ + default: + data->values[i] = f->val; + } +@@ -620,6 +628,7 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b) + int i; + + if (a->flags != b->flags || ++ a->pflags != b->pflags || + a->listnr != b->listnr || + a->action != b->action || + a->field_count != b->field_count) +@@ -738,6 +747,7 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old) + new = &entry->rule; + new->vers_ops = old->vers_ops; + new->flags = old->flags; ++ new->pflags = old->pflags; + new->listnr = old->listnr; + new->action = old->action; + for (i = 0; i < AUDIT_BITMASK_SIZE; i++) +diff --git a/kernel/groups.c b/kernel/groups.c +index 90cf1c38c8ea..67b4ba30475f 100644 +--- a/kernel/groups.c ++++ b/kernel/groups.c +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + #include + + /* init to 2 - one for init_task, one to ensure it is never freed */ +@@ -223,6 +224,14 @@ out: + return i; + } + ++bool may_setgroups(void) ++{ ++ struct user_namespace *user_ns = current_user_ns(); ++ ++ return ns_capable(user_ns, CAP_SETGID) && ++ userns_may_setgroups(user_ns); ++} ++ + /* + * SMP: Our groups are copy-on-write. We can set them safely + * without another task interfering. +@@ -233,7 +242,7 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist) + struct group_info *group_info; + int retval; + +- if (!ns_capable(current_user_ns(), CAP_SETGID)) ++ if (!may_setgroups()) + return -EPERM; + if ((unsigned)gidsetsize > NGROUPS_MAX) + return -EINVAL; +diff --git a/kernel/pid.c b/kernel/pid.c +index 9b9a26698144..82430c858d69 100644 +--- a/kernel/pid.c ++++ b/kernel/pid.c +@@ -341,6 +341,8 @@ out: + + out_unlock: + spin_unlock_irq(&pidmap_lock); ++ put_pid_ns(ns); ++ + out_free: + while (++i <= ns->level) + free_pidmap(pid->numbers + i); +diff --git a/kernel/uid16.c b/kernel/uid16.c +index 602e5bbbceff..d58cc4d8f0d1 100644 +--- a/kernel/uid16.c ++++ b/kernel/uid16.c +@@ -176,7 +176,7 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist) + struct group_info *group_info; + int retval; + +- if (!ns_capable(current_user_ns(), CAP_SETGID)) ++ if (!may_setgroups()) + return -EPERM; + if ((unsigned)gidsetsize > NGROUPS_MAX) + return -EINVAL; +diff --git a/kernel/user.c b/kernel/user.c +index c006131beb77..c2bbb50f5a90 100644 +--- a/kernel/user.c ++++ b/kernel/user.c +@@ -51,6 +51,7 @@ struct user_namespace init_user_ns = { + .owner = GLOBAL_ROOT_UID, + .group = GLOBAL_ROOT_GID, + .proc_inum = PROC_USER_INIT_INO, ++ .flags = USERNS_INIT_FLAGS, + #ifdef CONFIG_PERSISTENT_KEYRINGS + .persistent_keyring_register_sem = + __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem), +diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c +index 80a57afd8647..153971e4798a 100644 +--- a/kernel/user_namespace.c ++++ b/kernel/user_namespace.c +@@ -24,6 +24,7 @@ + #include + + static struct kmem_cache *user_ns_cachep __read_mostly; ++static DEFINE_MUTEX(userns_state_mutex); + + static bool new_idmap_permitted(const struct file *file, + struct user_namespace *ns, int cap_setid, +@@ -99,6 +100,11 @@ int create_user_ns(struct cred *new) + ns->owner = owner; + ns->group = group; + ++ /* Inherit USERNS_SETGROUPS_ALLOWED from our parent */ ++ mutex_lock(&userns_state_mutex); ++ ns->flags = parent_ns->flags; ++ mutex_unlock(&userns_state_mutex); ++ + set_cred_user_ns(new, ns); + + #ifdef CONFIG_PERSISTENT_KEYRINGS +@@ -581,9 +587,6 @@ static bool mappings_overlap(struct uid_gid_map *new_map, struct uid_gid_extent + return false; + } + +- +-static DEFINE_MUTEX(id_map_mutex); +- + static ssize_t map_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos, + int cap_setid, +@@ -600,7 +603,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, + ssize_t ret = -EINVAL; + + /* +- * The id_map_mutex serializes all writes to any given map. ++ * The userns_state_mutex serializes all writes to any given map. + * + * Any map is only ever written once. + * +@@ -618,7 +621,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, + * order and smp_rmb() is guaranteed that we don't have crazy + * architectures returning stale data. + */ +- mutex_lock(&id_map_mutex); ++ mutex_lock(&userns_state_mutex); + + ret = -EPERM; + /* Only allow one successful write to the map */ +@@ -745,7 +748,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, + *ppos = count; + ret = count; + out: +- mutex_unlock(&id_map_mutex); ++ mutex_unlock(&userns_state_mutex); + if (page) + free_page(page); + return ret; +@@ -804,17 +807,21 @@ static bool new_idmap_permitted(const struct file *file, + struct user_namespace *ns, int cap_setid, + struct uid_gid_map *new_map) + { +- /* Allow mapping to your own filesystem ids */ +- if ((new_map->nr_extents == 1) && (new_map->extent[0].count == 1)) { ++ const struct cred *cred = file->f_cred; ++ /* Don't allow mappings that would allow anything that wouldn't ++ * be allowed without the establishment of unprivileged mappings. ++ */ ++ if ((new_map->nr_extents == 1) && (new_map->extent[0].count == 1) && ++ uid_eq(ns->owner, cred->euid)) { + u32 id = new_map->extent[0].lower_first; + if (cap_setid == CAP_SETUID) { + kuid_t uid = make_kuid(ns->parent, id); +- if (uid_eq(uid, file->f_cred->fsuid)) ++ if (uid_eq(uid, cred->euid)) + return true; +- } +- else if (cap_setid == CAP_SETGID) { ++ } else if (cap_setid == CAP_SETGID) { + kgid_t gid = make_kgid(ns->parent, id); +- if (gid_eq(gid, file->f_cred->fsgid)) ++ if (!(ns->flags & USERNS_SETGROUPS_ALLOWED) && ++ gid_eq(gid, cred->egid)) + return true; + } + } +@@ -834,6 +841,100 @@ static bool new_idmap_permitted(const struct file *file, + return false; + } + ++int proc_setgroups_show(struct seq_file *seq, void *v) ++{ ++ struct user_namespace *ns = seq->private; ++ unsigned long userns_flags = ACCESS_ONCE(ns->flags); ++ ++ seq_printf(seq, "%s\n", ++ (userns_flags & USERNS_SETGROUPS_ALLOWED) ? ++ "allow" : "deny"); ++ return 0; ++} ++ ++ssize_t proc_setgroups_write(struct file *file, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct seq_file *seq = file->private_data; ++ struct user_namespace *ns = seq->private; ++ char kbuf[8], *pos; ++ bool setgroups_allowed; ++ ssize_t ret; ++ ++ /* Only allow a very narrow range of strings to be written */ ++ ret = -EINVAL; ++ if ((*ppos != 0) || (count >= sizeof(kbuf))) ++ goto out; ++ ++ /* What was written? */ ++ ret = -EFAULT; ++ if (copy_from_user(kbuf, buf, count)) ++ goto out; ++ kbuf[count] = '\0'; ++ pos = kbuf; ++ ++ /* What is being requested? */ ++ ret = -EINVAL; ++ if (strncmp(pos, "allow", 5) == 0) { ++ pos += 5; ++ setgroups_allowed = true; ++ } ++ else if (strncmp(pos, "deny", 4) == 0) { ++ pos += 4; ++ setgroups_allowed = false; ++ } ++ else ++ goto out; ++ ++ /* Verify there is not trailing junk on the line */ ++ pos = skip_spaces(pos); ++ if (*pos != '\0') ++ goto out; ++ ++ ret = -EPERM; ++ mutex_lock(&userns_state_mutex); ++ if (setgroups_allowed) { ++ /* Enabling setgroups after setgroups has been disabled ++ * is not allowed. ++ */ ++ if (!(ns->flags & USERNS_SETGROUPS_ALLOWED)) ++ goto out_unlock; ++ } else { ++ /* Permanently disabling setgroups after setgroups has ++ * been enabled by writing the gid_map is not allowed. ++ */ ++ if (ns->gid_map.nr_extents != 0) ++ goto out_unlock; ++ ns->flags &= ~USERNS_SETGROUPS_ALLOWED; ++ } ++ mutex_unlock(&userns_state_mutex); ++ ++ /* Report a successful write */ ++ *ppos = count; ++ ret = count; ++out: ++ return ret; ++out_unlock: ++ mutex_unlock(&userns_state_mutex); ++ goto out; ++} ++ ++bool userns_may_setgroups(const struct user_namespace *ns) ++{ ++ bool allowed; ++ ++ mutex_lock(&userns_state_mutex); ++ /* It is not safe to use setgroups until a gid mapping in ++ * the user namespace has been established. ++ */ ++ allowed = ns->gid_map.nr_extents != 0; ++ /* Is setgroups allowed? */ ++ allowed = allowed && (ns->flags & USERNS_SETGROUPS_ALLOWED); ++ mutex_unlock(&userns_state_mutex); ++ ++ return allowed; ++} ++ + static void *userns_get(struct task_struct *task) + { + struct user_namespace *user_ns; +diff --git a/net/mac80211/key.c b/net/mac80211/key.c +index 6ff65a1ebaa9..d78b37a5d951 100644 +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -652,7 +652,7 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local, + int i; + + mutex_lock(&local->key_mtx); +- for (i = 0; i < NUM_DEFAULT_KEYS; i++) { ++ for (i = 0; i < ARRAY_SIZE(sta->gtk); i++) { + key = key_mtx_dereference(local, sta->gtk[i]); + if (!key) + continue; +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 095c16037bc5..1e4dc4ed5e0d 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1679,14 +1679,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + sc = le16_to_cpu(hdr->seq_ctrl); + frag = sc & IEEE80211_SCTL_FRAG; + +- if (likely(!ieee80211_has_morefrags(fc) && frag == 0)) +- goto out; +- + if (is_multicast_ether_addr(hdr->addr1)) { + rx->local->dot11MulticastReceivedFrameCount++; +- goto out; ++ goto out_no_led; + } + ++ if (likely(!ieee80211_has_morefrags(fc) && frag == 0)) ++ goto out; ++ + I802_DEBUG_INC(rx->local->rx_handlers_fragments); + + if (skb_linearize(rx->skb)) +@@ -1777,9 +1777,10 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + status->rx_flags |= IEEE80211_RX_FRAGMENTED; + + out: ++ ieee80211_led_rx(rx->local); ++ out_no_led: + if (rx->sta) + rx->sta->rx_packets++; +- ieee80211_led_rx(rx->local); + return RX_CONTINUE; + } + +diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c +index 9e1e005c7596..c4c8df4b214d 100644 +--- a/security/keys/encrypted-keys/encrypted.c ++++ b/security/keys/encrypted-keys/encrypted.c +@@ -1018,10 +1018,13 @@ static int __init init_encrypted(void) + ret = encrypted_shash_alloc(); + if (ret < 0) + return ret; ++ ret = aes_get_sizes(); ++ if (ret < 0) ++ goto out; + ret = register_key_type(&key_type_encrypted); + if (ret < 0) + goto out; +- return aes_get_sizes(); ++ return 0; + out: + encrypted_shash_release(); + return ret; +diff --git a/tools/testing/selftests/mount/unprivileged-remount-test.c b/tools/testing/selftests/mount/unprivileged-remount-test.c +index 1b3ff2fda4d0..517785052f1c 100644 +--- a/tools/testing/selftests/mount/unprivileged-remount-test.c ++++ b/tools/testing/selftests/mount/unprivileged-remount-test.c +@@ -6,6 +6,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -32,11 +34,14 @@ + # define CLONE_NEWPID 0x20000000 + #endif + ++#ifndef MS_REC ++# define MS_REC 16384 ++#endif + #ifndef MS_RELATIME +-#define MS_RELATIME (1 << 21) ++# define MS_RELATIME (1 << 21) + #endif + #ifndef MS_STRICTATIME +-#define MS_STRICTATIME (1 << 24) ++# define MS_STRICTATIME (1 << 24) + #endif + + static void die(char *fmt, ...) +@@ -48,17 +53,14 @@ static void die(char *fmt, ...) + exit(EXIT_FAILURE); + } + +-static void write_file(char *filename, char *fmt, ...) ++static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list ap) + { + char buf[4096]; + int fd; + ssize_t written; + int buf_len; +- va_list ap; + +- va_start(ap, fmt); + buf_len = vsnprintf(buf, sizeof(buf), fmt, ap); +- va_end(ap); + if (buf_len < 0) { + die("vsnprintf failed: %s\n", + strerror(errno)); +@@ -69,6 +71,8 @@ static void write_file(char *filename, char *fmt, ...) + + fd = open(filename, O_WRONLY); + if (fd < 0) { ++ if ((errno == ENOENT) && enoent_ok) ++ return; + die("open of %s failed: %s\n", + filename, strerror(errno)); + } +@@ -87,6 +91,65 @@ static void write_file(char *filename, char *fmt, ...) + } + } + ++static void maybe_write_file(char *filename, char *fmt, ...) ++{ ++ va_list ap; ++ ++ va_start(ap, fmt); ++ vmaybe_write_file(true, filename, fmt, ap); ++ va_end(ap); ++ ++} ++ ++static void write_file(char *filename, char *fmt, ...) ++{ ++ va_list ap; ++ ++ va_start(ap, fmt); ++ vmaybe_write_file(false, filename, fmt, ap); ++ va_end(ap); ++ ++} ++ ++static int read_mnt_flags(const char *path) ++{ ++ int ret; ++ struct statvfs stat; ++ int mnt_flags; ++ ++ ret = statvfs(path, &stat); ++ if (ret != 0) { ++ die("statvfs of %s failed: %s\n", ++ path, strerror(errno)); ++ } ++ if (stat.f_flag & ~(ST_RDONLY | ST_NOSUID | ST_NODEV | \ ++ ST_NOEXEC | ST_NOATIME | ST_NODIRATIME | ST_RELATIME | \ ++ ST_SYNCHRONOUS | ST_MANDLOCK)) { ++ die("Unrecognized mount flags\n"); ++ } ++ mnt_flags = 0; ++ if (stat.f_flag & ST_RDONLY) ++ mnt_flags |= MS_RDONLY; ++ if (stat.f_flag & ST_NOSUID) ++ mnt_flags |= MS_NOSUID; ++ if (stat.f_flag & ST_NODEV) ++ mnt_flags |= MS_NODEV; ++ if (stat.f_flag & ST_NOEXEC) ++ mnt_flags |= MS_NOEXEC; ++ if (stat.f_flag & ST_NOATIME) ++ mnt_flags |= MS_NOATIME; ++ if (stat.f_flag & ST_NODIRATIME) ++ mnt_flags |= MS_NODIRATIME; ++ if (stat.f_flag & ST_RELATIME) ++ mnt_flags |= MS_RELATIME; ++ if (stat.f_flag & ST_SYNCHRONOUS) ++ mnt_flags |= MS_SYNCHRONOUS; ++ if (stat.f_flag & ST_MANDLOCK) ++ mnt_flags |= ST_MANDLOCK; ++ ++ return mnt_flags; ++} ++ + static void create_and_enter_userns(void) + { + uid_t uid; +@@ -100,13 +163,10 @@ static void create_and_enter_userns(void) + strerror(errno)); + } + ++ maybe_write_file("/proc/self/setgroups", "deny"); + write_file("/proc/self/uid_map", "0 %d 1", uid); + write_file("/proc/self/gid_map", "0 %d 1", gid); + +- if (setgroups(0, NULL) != 0) { +- die("setgroups failed: %s\n", +- strerror(errno)); +- } + if (setgid(0) != 0) { + die ("setgid(0) failed %s\n", + strerror(errno)); +@@ -118,7 +178,8 @@ static void create_and_enter_userns(void) + } + + static +-bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags) ++bool test_unpriv_remount(const char *fstype, const char *mount_options, ++ int mount_flags, int remount_flags, int invalid_flags) + { + pid_t child; + +@@ -151,9 +212,11 @@ bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags) + strerror(errno)); + } + +- if (mount("testing", "/tmp", "ramfs", mount_flags, NULL) != 0) { +- die("mount of /tmp failed: %s\n", +- strerror(errno)); ++ if (mount("testing", "/tmp", fstype, mount_flags, mount_options) != 0) { ++ die("mount of %s with options '%s' on /tmp failed: %s\n", ++ fstype, ++ mount_options? mount_options : "", ++ strerror(errno)); + } + + create_and_enter_userns(); +@@ -181,62 +244,127 @@ bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags) + + static bool test_unpriv_remount_simple(int mount_flags) + { +- return test_unpriv_remount(mount_flags, mount_flags, 0); ++ return test_unpriv_remount("ramfs", NULL, mount_flags, mount_flags, 0); + } + + static bool test_unpriv_remount_atime(int mount_flags, int invalid_flags) + { +- return test_unpriv_remount(mount_flags, mount_flags, invalid_flags); ++ return test_unpriv_remount("ramfs", NULL, mount_flags, mount_flags, ++ invalid_flags); ++} ++ ++static bool test_priv_mount_unpriv_remount(void) ++{ ++ pid_t child; ++ int ret; ++ const char *orig_path = "/dev"; ++ const char *dest_path = "/tmp"; ++ int orig_mnt_flags, remount_mnt_flags; ++ ++ child = fork(); ++ if (child == -1) { ++ die("fork failed: %s\n", ++ strerror(errno)); ++ } ++ if (child != 0) { /* parent */ ++ pid_t pid; ++ int status; ++ pid = waitpid(child, &status, 0); ++ if (pid == -1) { ++ die("waitpid failed: %s\n", ++ strerror(errno)); ++ } ++ if (pid != child) { ++ die("waited for %d got %d\n", ++ child, pid); ++ } ++ if (!WIFEXITED(status)) { ++ die("child did not terminate cleanly\n"); ++ } ++ return WEXITSTATUS(status) == EXIT_SUCCESS ? true : false; ++ } ++ ++ orig_mnt_flags = read_mnt_flags(orig_path); ++ ++ create_and_enter_userns(); ++ ret = unshare(CLONE_NEWNS); ++ if (ret != 0) { ++ die("unshare(CLONE_NEWNS) failed: %s\n", ++ strerror(errno)); ++ } ++ ++ ret = mount(orig_path, dest_path, "bind", MS_BIND | MS_REC, NULL); ++ if (ret != 0) { ++ die("recursive bind mount of %s onto %s failed: %s\n", ++ orig_path, dest_path, strerror(errno)); ++ } ++ ++ ret = mount(dest_path, dest_path, "none", ++ MS_REMOUNT | MS_BIND | orig_mnt_flags , NULL); ++ if (ret != 0) { ++ /* system("cat /proc/self/mounts"); */ ++ die("remount of /tmp failed: %s\n", ++ strerror(errno)); ++ } ++ ++ remount_mnt_flags = read_mnt_flags(dest_path); ++ if (orig_mnt_flags != remount_mnt_flags) { ++ die("Mount flags unexpectedly changed during remount of %s originally mounted on %s\n", ++ dest_path, orig_path); ++ } ++ exit(EXIT_SUCCESS); + } + + int main(int argc, char **argv) + { +- if (!test_unpriv_remount_simple(MS_RDONLY|MS_NODEV)) { ++ if (!test_unpriv_remount_simple(MS_RDONLY)) { + die("MS_RDONLY malfunctions\n"); + } +- if (!test_unpriv_remount_simple(MS_NODEV)) { ++ if (!test_unpriv_remount("devpts", "newinstance", MS_NODEV, MS_NODEV, 0)) { + die("MS_NODEV malfunctions\n"); + } +- if (!test_unpriv_remount_simple(MS_NOSUID|MS_NODEV)) { ++ if (!test_unpriv_remount_simple(MS_NOSUID)) { + die("MS_NOSUID malfunctions\n"); + } +- if (!test_unpriv_remount_simple(MS_NOEXEC|MS_NODEV)) { ++ if (!test_unpriv_remount_simple(MS_NOEXEC)) { + die("MS_NOEXEC malfunctions\n"); + } +- if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODEV, +- MS_NOATIME|MS_NODEV)) ++ if (!test_unpriv_remount_atime(MS_RELATIME, ++ MS_NOATIME)) + { + die("MS_RELATIME malfunctions\n"); + } +- if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODEV, +- MS_NOATIME|MS_NODEV)) ++ if (!test_unpriv_remount_atime(MS_STRICTATIME, ++ MS_NOATIME)) + { + die("MS_STRICTATIME malfunctions\n"); + } +- if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODEV, +- MS_STRICTATIME|MS_NODEV)) ++ if (!test_unpriv_remount_atime(MS_NOATIME, ++ MS_STRICTATIME)) + { +- die("MS_RELATIME malfunctions\n"); ++ die("MS_NOATIME malfunctions\n"); + } +- if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME|MS_NODEV, +- MS_NOATIME|MS_NODEV)) ++ if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME, ++ MS_NOATIME)) + { +- die("MS_RELATIME malfunctions\n"); ++ die("MS_RELATIME|MS_NODIRATIME malfunctions\n"); + } +- if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME|MS_NODEV, +- MS_NOATIME|MS_NODEV)) ++ if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME, ++ MS_NOATIME)) + { +- die("MS_RELATIME malfunctions\n"); ++ die("MS_STRICTATIME|MS_NODIRATIME malfunctions\n"); + } +- if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME|MS_NODEV, +- MS_STRICTATIME|MS_NODEV)) ++ if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME, ++ MS_STRICTATIME)) + { +- die("MS_RELATIME malfunctions\n"); ++ die("MS_NOATIME|MS_DIRATIME malfunctions\n"); + } +- if (!test_unpriv_remount(MS_STRICTATIME|MS_NODEV, MS_NODEV, +- MS_NOATIME|MS_NODEV)) ++ if (!test_unpriv_remount("ramfs", NULL, MS_STRICTATIME, 0, MS_NOATIME)) + { + die("Default atime malfunctions\n"); + } ++ if (!test_priv_mount_unpriv_remount()) { ++ die("Mount flags unexpectedly changed after remount\n"); ++ } + return EXIT_SUCCESS; + } diff --git a/patch/kernel/cubox-default/patch-3.14.28-29.patch b/patch/kernel/cubox-default/patch-3.14.28-29.patch new file mode 100644 index 000000000..7f5e3248b --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.28-29.patch @@ -0,0 +1,2545 @@ +diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt +index 69b3cac4749d..5d8675615e59 100644 +--- a/Documentation/ramoops.txt ++++ b/Documentation/ramoops.txt +@@ -14,11 +14,19 @@ survive after a restart. + + 1. Ramoops concepts + +-Ramoops uses a predefined memory area to store the dump. The start and size of +-the memory area are set using two variables: ++Ramoops uses a predefined memory area to store the dump. The start and size ++and type of the memory area are set using three variables: + * "mem_address" for the start + * "mem_size" for the size. The memory size will be rounded down to a + power of two. ++ * "mem_type" to specifiy if the memory type (default is pgprot_writecombine). ++ ++Typically the default value of mem_type=0 should be used as that sets the pstore ++mapping to pgprot_writecombine. Setting mem_type=1 attempts to use ++pgprot_noncached, which only works on some platforms. This is because pstore ++depends on atomic operations. At least on ARM, pgprot_noncached causes the ++memory to be mapped strongly ordered, and atomic operations on strongly ordered ++memory are implementation defined, and won't work on many ARMs such as omaps. + + The memory area is divided into "record_size" chunks (also rounded down to + power of two) and each oops/panic writes a "record_size" chunk of +@@ -55,6 +63,7 @@ Setting the ramoops parameters can be done in 2 different manners: + static struct ramoops_platform_data ramoops_data = { + .mem_size = <...>, + .mem_address = <...>, ++ .mem_type = <...>, + .record_size = <...>, + .dump_oops = <...>, + .ecc = <...>, +diff --git a/Makefile b/Makefile +index a2e572bfff7d..7aff64ee4fb6 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 28 ++SUBLEVEL = 29 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi +index 767f0e376f4d..f60aeee2fc9e 100644 +--- a/arch/arm/boot/dts/dra7.dtsi ++++ b/arch/arm/boot/dts/dra7.dtsi +@@ -458,7 +458,7 @@ + }; + + wdt2: wdt@4ae14000 { +- compatible = "ti,omap4-wdt"; ++ compatible = "ti,omap3-wdt"; + reg = <0x4ae14000 0x80>; + interrupts = ; + ti,hwmods = "wd_timer2"; +diff --git a/arch/arm/boot/dts/s3c6410-mini6410.dts b/arch/arm/boot/dts/s3c6410-mini6410.dts +index 57e00f9bce99..a25debb50401 100644 +--- a/arch/arm/boot/dts/s3c6410-mini6410.dts ++++ b/arch/arm/boot/dts/s3c6410-mini6410.dts +@@ -198,10 +198,6 @@ + status = "okay"; + }; + +-&pwm { +- status = "okay"; +-}; +- + &pinctrl0 { + gpio_leds: gpio-leds { + samsung,pins = "gpk-4", "gpk-5", "gpk-6", "gpk-7"; +diff --git a/arch/arm/boot/dts/s3c64xx.dtsi b/arch/arm/boot/dts/s3c64xx.dtsi +index 4e3be4d3493d..4f1eff3420f6 100644 +--- a/arch/arm/boot/dts/s3c64xx.dtsi ++++ b/arch/arm/boot/dts/s3c64xx.dtsi +@@ -168,7 +168,6 @@ + clocks = <&clocks PCLK_PWM>; + samsung,pwm-outputs = <0>, <1>; + #pwm-cells = <3>; +- status = "disabled"; + }; + + pinctrl0: pinctrl@7f008000 { +diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig +index ee6982976d66..cf4823bc111d 100644 +--- a/arch/arm/configs/multi_v7_defconfig ++++ b/arch/arm/configs/multi_v7_defconfig +@@ -235,6 +235,7 @@ CONFIG_SND_SOC_TEGRA_MAX98090=y + CONFIG_USB=y + CONFIG_USB_XHCI_HCD=y + CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_EXYNOS=y + CONFIG_USB_EHCI_TEGRA=y + CONFIG_USB_EHCI_HCD_PLATFORM=y + CONFIG_USB_ISP1760_HCD=y +diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c +index 1e8b030dbefd..aab70f657cd2 100644 +--- a/arch/arm/kernel/setup.c ++++ b/arch/arm/kernel/setup.c +@@ -1021,6 +1021,15 @@ static int c_show(struct seq_file *m, void *v) + seq_printf(m, "model name\t: %s rev %d (%s)\n", + cpu_name, cpuid & 15, elf_platform); + ++#if defined(CONFIG_SMP) ++ seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", ++ per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ), ++ (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100); ++#else ++ seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", ++ loops_per_jiffy / (500000/HZ), ++ (loops_per_jiffy / (5000/HZ)) % 100); ++#endif + /* dump out the processor features */ + seq_puts(m, "Features\t: "); + +diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c +index b7b4c86e338b..8cd3724714fe 100644 +--- a/arch/arm/kernel/smp.c ++++ b/arch/arm/kernel/smp.c +@@ -388,8 +388,17 @@ asmlinkage void secondary_start_kernel(void) + + void __init smp_cpus_done(unsigned int max_cpus) + { +- printk(KERN_INFO "SMP: Total of %d processors activated.\n", +- num_online_cpus()); ++ int cpu; ++ unsigned long bogosum = 0; ++ ++ for_each_online_cpu(cpu) ++ bogosum += per_cpu(cpu_data, cpu).loops_per_jiffy; ++ ++ printk(KERN_INFO "SMP: Total of %d processors activated " ++ "(%lu.%02lu BogoMIPS).\n", ++ num_online_cpus(), ++ bogosum / (500000/HZ), ++ (bogosum / (5000/HZ)) % 100); + + hyp_mode_check(); + } +diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c +index 4e9d58148ca7..c295c10f9217 100644 +--- a/arch/arm/mach-mvebu/coherency.c ++++ b/arch/arm/mach-mvebu/coherency.c +@@ -125,6 +125,29 @@ int __init coherency_init(void) + { + struct device_node *np; + ++ /* ++ * The coherency fabric is needed: ++ * - For coherency between processors on Armada XP, so only ++ * when SMP is enabled. ++ * - For coherency between the processor and I/O devices, but ++ * this coherency requires many pre-requisites (write ++ * allocate cache policy, shareable pages, SMP bit set) that ++ * are only meant in SMP situations. ++ * ++ * Note that this means that on Armada 370, there is currently ++ * no way to use hardware I/O coherency, because even when ++ * CONFIG_SMP is enabled, is_smp() returns false due to the ++ * Armada 370 being a single-core processor. To lift this ++ * limitation, we would have to find a way to make the cache ++ * policy set to write-allocate (on all Armada SoCs), and to ++ * set the shareable attribute in page tables (on all Armada ++ * SoCs except the Armada 370). Unfortunately, such decisions ++ * are taken very early in the kernel boot process, at a point ++ * where we don't know yet on which SoC we are running. ++ */ ++ if (!is_smp()) ++ return 0; ++ + np = of_find_matching_node(NULL, of_coherency_table); + if (np) { + struct resource res; +@@ -151,6 +174,9 @@ static int __init coherency_late_init(void) + { + struct device_node *np; + ++ if (!is_smp()) ++ return 0; ++ + np = of_find_matching_node(NULL, of_coherency_table); + if (np) { + bus_register_notifier(&platform_bus_type, +diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c +index eefb30cfcabd..2b9cff960af2 100644 +--- a/arch/arm/mach-omap2/pm44xx.c ++++ b/arch/arm/mach-omap2/pm44xx.c +@@ -148,26 +148,6 @@ static inline int omap4_init_static_deps(void) + struct clockdomain *ducati_clkdm, *l3_2_clkdm; + int ret = 0; + +- if (omap_rev() == OMAP4430_REV_ES1_0) { +- WARN(1, "Power Management not supported on OMAP4430 ES1.0\n"); +- return -ENODEV; +- } +- +- pr_err("Power Management for TI OMAP4.\n"); +- /* +- * OMAP4 chip PM currently works only with certain (newer) +- * versions of bootloaders. This is due to missing code in the +- * kernel to properly reset and initialize some devices. +- * http://www.spinics.net/lists/arm-kernel/msg218641.html +- */ +- pr_warn("OMAP4 PM: u-boot >= v2012.07 is required for full PM support\n"); +- +- ret = pwrdm_for_each(pwrdms_setup, NULL); +- if (ret) { +- pr_err("Failed to setup powerdomains\n"); +- return ret; +- } +- + /* + * The dynamic dependency between MPUSS -> MEMIF and + * MPUSS -> L4_PER/L3_* and DUCATI -> L3_* doesn't work as +@@ -231,6 +211,15 @@ int __init omap4_pm_init(void) + + pr_info("Power Management for TI OMAP4+ devices.\n"); + ++ /* ++ * OMAP4 chip PM currently works only with certain (newer) ++ * versions of bootloaders. This is due to missing code in the ++ * kernel to properly reset and initialize some devices. ++ * http://www.spinics.net/lists/arm-kernel/msg218641.html ++ */ ++ if (cpu_is_omap44xx()) ++ pr_warn("OMAP4 PM: u-boot >= v2012.07 is required for full PM support\n"); ++ + ret = pwrdm_for_each(pwrdms_setup, NULL); + if (ret) { + pr_err("Failed to setup powerdomains.\n"); +diff --git a/arch/arm64/include/asm/suspend.h b/arch/arm64/include/asm/suspend.h +index e9c149c042e0..456d67c1f0fa 100644 +--- a/arch/arm64/include/asm/suspend.h ++++ b/arch/arm64/include/asm/suspend.h +@@ -21,6 +21,7 @@ struct sleep_save_sp { + phys_addr_t save_ptr_stash_phys; + }; + ++extern int __cpu_suspend(unsigned long arg, int (*fn)(unsigned long)); + extern void cpu_resume(void); + extern int cpu_suspend(unsigned long); + +diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S +index b1925729c692..ede186cdd452 100644 +--- a/arch/arm64/kernel/sleep.S ++++ b/arch/arm64/kernel/sleep.S +@@ -49,28 +49,39 @@ + orr \dst, \dst, \mask // dst|=(aff3>>rs3) + .endm + /* +- * Save CPU state for a suspend. This saves callee registers, and allocates +- * space on the kernel stack to save the CPU specific registers + some +- * other data for resume. ++ * Save CPU state for a suspend and execute the suspend finisher. ++ * On success it will return 0 through cpu_resume - ie through a CPU ++ * soft/hard reboot from the reset vector. ++ * On failure it returns the suspend finisher return value or force ++ * -EOPNOTSUPP if the finisher erroneously returns 0 (the suspend finisher ++ * is not allowed to return, if it does this must be considered failure). ++ * It saves callee registers, and allocates space on the kernel stack ++ * to save the CPU specific registers + some other data for resume. + * + * x0 = suspend finisher argument ++ * x1 = suspend finisher function pointer + */ +-ENTRY(__cpu_suspend) ++ENTRY(__cpu_suspend_enter) + stp x29, lr, [sp, #-96]! + stp x19, x20, [sp,#16] + stp x21, x22, [sp,#32] + stp x23, x24, [sp,#48] + stp x25, x26, [sp,#64] + stp x27, x28, [sp,#80] ++ /* ++ * Stash suspend finisher and its argument in x20 and x19 ++ */ ++ mov x19, x0 ++ mov x20, x1 + mov x2, sp + sub sp, sp, #CPU_SUSPEND_SZ // allocate cpu_suspend_ctx +- mov x1, sp ++ mov x0, sp + /* +- * x1 now points to struct cpu_suspend_ctx allocated on the stack ++ * x0 now points to struct cpu_suspend_ctx allocated on the stack + */ +- str x2, [x1, #CPU_CTX_SP] +- ldr x2, =sleep_save_sp +- ldr x2, [x2, #SLEEP_SAVE_SP_VIRT] ++ str x2, [x0, #CPU_CTX_SP] ++ ldr x1, =sleep_save_sp ++ ldr x1, [x1, #SLEEP_SAVE_SP_VIRT] + #ifdef CONFIG_SMP + mrs x7, mpidr_el1 + ldr x9, =mpidr_hash +@@ -82,11 +93,21 @@ ENTRY(__cpu_suspend) + ldp w3, w4, [x9, #MPIDR_HASH_SHIFTS] + ldp w5, w6, [x9, #(MPIDR_HASH_SHIFTS + 8)] + compute_mpidr_hash x8, x3, x4, x5, x6, x7, x10 +- add x2, x2, x8, lsl #3 ++ add x1, x1, x8, lsl #3 + #endif +- bl __cpu_suspend_finisher ++ bl __cpu_suspend_save ++ /* ++ * Grab suspend finisher in x20 and its argument in x19 ++ */ ++ mov x0, x19 ++ mov x1, x20 ++ /* ++ * We are ready for power down, fire off the suspend finisher ++ * in x1, with argument in x0 ++ */ ++ blr x1 + /* +- * Never gets here, unless suspend fails. ++ * Never gets here, unless suspend finisher fails. + * Successful cpu_suspend should return from cpu_resume, returning + * through this code path is considered an error + * If the return value is set to 0 force x0 = -EOPNOTSUPP +@@ -103,7 +124,7 @@ ENTRY(__cpu_suspend) + ldp x27, x28, [sp, #80] + ldp x29, lr, [sp], #96 + ret +-ENDPROC(__cpu_suspend) ++ENDPROC(__cpu_suspend_enter) + .ltorg + + /* +@@ -126,14 +147,12 @@ cpu_resume_after_mmu: + ret + ENDPROC(cpu_resume_after_mmu) + +- .data + ENTRY(cpu_resume) + bl el2_setup // if in EL2 drop to EL1 cleanly + #ifdef CONFIG_SMP + mrs x1, mpidr_el1 +- adr x4, mpidr_hash_ptr +- ldr x5, [x4] +- add x8, x4, x5 // x8 = struct mpidr_hash phys address ++ adrp x8, mpidr_hash ++ add x8, x8, #:lo12:mpidr_hash // x8 = struct mpidr_hash phys address + /* retrieve mpidr_hash members to compute the hash */ + ldr x2, [x8, #MPIDR_HASH_MASK] + ldp w3, w4, [x8, #MPIDR_HASH_SHIFTS] +@@ -143,14 +162,15 @@ ENTRY(cpu_resume) + #else + mov x7, xzr + #endif +- adr x0, sleep_save_sp ++ adrp x0, sleep_save_sp ++ add x0, x0, #:lo12:sleep_save_sp + ldr x0, [x0, #SLEEP_SAVE_SP_PHYS] + ldr x0, [x0, x7, lsl #3] + /* load sp from context */ + ldr x2, [x0, #CPU_CTX_SP] +- adr x1, sleep_idmap_phys ++ adrp x1, sleep_idmap_phys + /* load physical address of identity map page table in x1 */ +- ldr x1, [x1] ++ ldr x1, [x1, #:lo12:sleep_idmap_phys] + mov sp, x2 + /* + * cpu_do_resume expects x0 to contain context physical address +@@ -159,26 +179,3 @@ ENTRY(cpu_resume) + bl cpu_do_resume // PC relative jump, MMU off + b cpu_resume_mmu // Resume MMU, never returns + ENDPROC(cpu_resume) +- +- .align 3 +-mpidr_hash_ptr: +- /* +- * offset of mpidr_hash symbol from current location +- * used to obtain run-time mpidr_hash address with MMU off +- */ +- .quad mpidr_hash - . +-/* +- * physical address of identity mapped page tables +- */ +- .type sleep_idmap_phys, #object +-ENTRY(sleep_idmap_phys) +- .quad 0 +-/* +- * struct sleep_save_sp { +- * phys_addr_t *save_ptr_stash; +- * phys_addr_t save_ptr_stash_phys; +- * }; +- */ +- .type sleep_save_sp, #object +-ENTRY(sleep_save_sp) +- .space SLEEP_SAVE_SP_SZ // struct sleep_save_sp +diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c +index 1fa9ce4afd8f..2d6b6065fe7f 100644 +--- a/arch/arm64/kernel/suspend.c ++++ b/arch/arm64/kernel/suspend.c +@@ -5,26 +5,24 @@ + #include + #include + #include ++#include + #include + #include + #include + +-extern int __cpu_suspend(unsigned long); ++extern int __cpu_suspend_enter(unsigned long arg, int (*fn)(unsigned long)); + /* +- * This is called by __cpu_suspend() to save the state, and do whatever ++ * This is called by __cpu_suspend_enter() to save the state, and do whatever + * flushing is required to ensure that when the CPU goes to sleep we have + * the necessary data available when the caches are not searched. + * +- * @arg: Argument to pass to suspend operations +- * @ptr: CPU context virtual address +- * @save_ptr: address of the location where the context physical address +- * must be saved ++ * ptr: CPU context virtual address ++ * save_ptr: address of the location where the context physical address ++ * must be saved + */ +-int __cpu_suspend_finisher(unsigned long arg, struct cpu_suspend_ctx *ptr, +- phys_addr_t *save_ptr) ++void notrace __cpu_suspend_save(struct cpu_suspend_ctx *ptr, ++ phys_addr_t *save_ptr) + { +- int cpu = smp_processor_id(); +- + *save_ptr = virt_to_phys(ptr); + + cpu_do_suspend(ptr); +@@ -35,8 +33,6 @@ int __cpu_suspend_finisher(unsigned long arg, struct cpu_suspend_ctx *ptr, + */ + __flush_dcache_area(ptr, sizeof(*ptr)); + __flush_dcache_area(save_ptr, sizeof(*save_ptr)); +- +- return cpu_ops[cpu]->cpu_suspend(arg); + } + + /* +@@ -56,15 +52,15 @@ void __init cpu_suspend_set_dbg_restorer(void (*hw_bp_restore)(void *)) + } + + /** +- * cpu_suspend ++ * cpu_suspend() - function to enter a low-power state ++ * @arg: argument to pass to CPU suspend operations + * +- * @arg: argument to pass to the finisher function ++ * Return: 0 on success, -EOPNOTSUPP if CPU suspend hook not initialized, CPU ++ * operations back-end error code otherwise. + */ + int cpu_suspend(unsigned long arg) + { +- struct mm_struct *mm = current->active_mm; +- int ret, cpu = smp_processor_id(); +- unsigned long flags; ++ int cpu = smp_processor_id(); + + /* + * If cpu_ops have not been registered or suspend +@@ -72,6 +68,21 @@ int cpu_suspend(unsigned long arg) + */ + if (!cpu_ops[cpu] || !cpu_ops[cpu]->cpu_suspend) + return -EOPNOTSUPP; ++ return cpu_ops[cpu]->cpu_suspend(arg); ++} ++ ++/* ++ * __cpu_suspend ++ * ++ * arg: argument to pass to the finisher function ++ * fn: finisher function pointer ++ * ++ */ ++int __cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) ++{ ++ struct mm_struct *mm = current->active_mm; ++ int ret; ++ unsigned long flags; + + /* + * From this point debug exceptions are disabled to prevent +@@ -86,16 +97,27 @@ int cpu_suspend(unsigned long arg) + * page tables, so that the thread address space is properly + * set-up on function return. + */ +- ret = __cpu_suspend(arg); ++ ret = __cpu_suspend_enter(arg, fn); + if (ret == 0) { +- cpu_switch_mm(mm->pgd, mm); ++ /* ++ * We are resuming from reset with TTBR0_EL1 set to the ++ * idmap to enable the MMU; restore the active_mm mappings in ++ * TTBR0_EL1 unless the active_mm == &init_mm, in which case ++ * the thread entered __cpu_suspend with TTBR0_EL1 set to ++ * reserved TTBR0 page tables and should be restored as such. ++ */ ++ if (mm == &init_mm) ++ cpu_set_reserved_ttbr0(); ++ else ++ cpu_switch_mm(mm->pgd, mm); ++ + flush_tlb_all(); + + /* + * Restore per-cpu offset before any kernel + * subsystem relying on it has a chance to run. + */ +- set_my_cpu_offset(per_cpu_offset(cpu)); ++ set_my_cpu_offset(per_cpu_offset(smp_processor_id())); + + /* + * Restore HW breakpoint registers to sane values +@@ -116,10 +138,10 @@ int cpu_suspend(unsigned long arg) + return ret; + } + +-extern struct sleep_save_sp sleep_save_sp; +-extern phys_addr_t sleep_idmap_phys; ++struct sleep_save_sp sleep_save_sp; ++phys_addr_t sleep_idmap_phys; + +-static int cpu_suspend_init(void) ++static int __init cpu_suspend_init(void) + { + void *ctx_ptr; + +diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c +index 27c93f41166f..fc0927a162ff 100644 +--- a/arch/powerpc/kernel/mce_power.c ++++ b/arch/powerpc/kernel/mce_power.c +@@ -78,7 +78,7 @@ static long mce_handle_derror(uint64_t dsisr, uint64_t slb_error_bits) + } + if (dsisr & P7_DSISR_MC_TLB_MULTIHIT_MFTLB) { + if (cur_cpu_spec && cur_cpu_spec->flush_tlb) +- cur_cpu_spec->flush_tlb(TLBIEL_INVAL_PAGE); ++ cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET); + /* reset error bits */ + dsisr &= ~P7_DSISR_MC_TLB_MULTIHIT_MFTLB; + } +@@ -109,7 +109,7 @@ static long mce_handle_common_ierror(uint64_t srr1) + break; + case P7_SRR1_MC_IFETCH_TLB_MULTIHIT: + if (cur_cpu_spec && cur_cpu_spec->flush_tlb) { +- cur_cpu_spec->flush_tlb(TLBIEL_INVAL_PAGE); ++ cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET); + handled = 1; + } + break; +diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c +index 75702e207b29..f7089fcfaa5d 100644 +--- a/arch/powerpc/kernel/udbg_16550.c ++++ b/arch/powerpc/kernel/udbg_16550.c +@@ -69,8 +69,12 @@ static void udbg_uart_putc(char c) + + static int udbg_uart_getc_poll(void) + { +- if (!udbg_uart_in || !(udbg_uart_in(UART_LSR) & LSR_DR)) ++ if (!udbg_uart_in) ++ return -1; ++ ++ if (!(udbg_uart_in(UART_LSR) & LSR_DR)) + return udbg_uart_in(UART_RBR); ++ + return -1; + } + +diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h +index 2a46ca720afc..2874be9aef0a 100644 +--- a/arch/x86/include/asm/vsyscall.h ++++ b/arch/x86/include/asm/vsyscall.h +@@ -34,7 +34,7 @@ static inline unsigned int __getcpu(void) + native_read_tscp(&p); + } else { + /* Load per CPU data from GDT */ +- asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG)); ++ asm volatile ("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG)); + } + + return p; +diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c +index 047f540cf3f7..2f9858894d5a 100644 +--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c ++++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c +@@ -2886,6 +2886,17 @@ static struct intel_uncore_box *uncore_event_to_box(struct perf_event *event) + return uncore_pmu_to_box(uncore_event_to_pmu(event), smp_processor_id()); + } + ++/* ++ * Using uncore_pmu_event_init pmu event_init callback ++ * as a detection point for uncore events. ++ */ ++static int uncore_pmu_event_init(struct perf_event *event); ++ ++static bool is_uncore_event(struct perf_event *event) ++{ ++ return event->pmu->event_init == uncore_pmu_event_init; ++} ++ + static int + uncore_collect_events(struct intel_uncore_box *box, struct perf_event *leader, bool dogrp) + { +@@ -2900,13 +2911,18 @@ uncore_collect_events(struct intel_uncore_box *box, struct perf_event *leader, b + return -EINVAL; + + n = box->n_events; +- box->event_list[n] = leader; +- n++; ++ ++ if (is_uncore_event(leader)) { ++ box->event_list[n] = leader; ++ n++; ++ } ++ + if (!dogrp) + return n; + + list_for_each_entry(event, &leader->sibling_list, group_entry) { +- if (event->state <= PERF_EVENT_STATE_OFF) ++ if (!is_uncore_event(event) || ++ event->state <= PERF_EVENT_STATE_OFF) + continue; + + if (n >= max_count) +diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c +index 49088b8a3ee3..dcae8fa2bf04 100644 +--- a/arch/x86/kvm/mmu.c ++++ b/arch/x86/kvm/mmu.c +@@ -4384,7 +4384,7 @@ void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm) + * zap all shadow pages. + */ + if (unlikely(kvm_current_mmio_generation(kvm) == 0)) { +- printk_ratelimited(KERN_INFO "kvm: zapping shadow pages for mmio generation wraparound\n"); ++ printk_ratelimited(KERN_DEBUG "kvm: zapping shadow pages for mmio generation wraparound\n"); + kvm_mmu_invalidate_zap_all_pages(kvm); + } + } +diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c +index 431e87544411..ab6ba35a9357 100644 +--- a/arch/x86/vdso/vma.c ++++ b/arch/x86/vdso/vma.c +@@ -117,30 +117,45 @@ subsys_initcall(init_vdso); + + struct linux_binprm; + +-/* Put the vdso above the (randomized) stack with another randomized offset. +- This way there is no hole in the middle of address space. +- To save memory make sure it is still in the same PTE as the stack top. +- This doesn't give that many random bits */ ++/* ++ * Put the vdso above the (randomized) stack with another randomized ++ * offset. This way there is no hole in the middle of address space. ++ * To save memory make sure it is still in the same PTE as the stack ++ * top. This doesn't give that many random bits. ++ * ++ * Note that this algorithm is imperfect: the distribution of the vdso ++ * start address within a PMD is biased toward the end. ++ * ++ * Only used for the 64-bit and x32 vdsos. ++ */ + static unsigned long vdso_addr(unsigned long start, unsigned len) + { + unsigned long addr, end; + unsigned offset; +- end = (start + PMD_SIZE - 1) & PMD_MASK; ++ ++ /* ++ * Round up the start address. It can start out unaligned as a result ++ * of stack start randomization. ++ */ ++ start = PAGE_ALIGN(start); ++ ++ /* Round the lowest possible end address up to a PMD boundary. */ ++ end = (start + len + PMD_SIZE - 1) & PMD_MASK; + if (end >= TASK_SIZE_MAX) + end = TASK_SIZE_MAX; + end -= len; +- /* This loses some more bits than a modulo, but is cheaper */ +- offset = get_random_int() & (PTRS_PER_PTE - 1); +- addr = start + (offset << PAGE_SHIFT); +- if (addr >= end) +- addr = end; ++ ++ if (end > start) { ++ offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1); ++ addr = start + (offset << PAGE_SHIFT); ++ } else { ++ addr = start; ++ } + + /* +- * page-align it here so that get_unmapped_area doesn't +- * align it wrongfully again to the next page. addr can come in 4K +- * unaligned here as a result of stack start randomization. ++ * Forcibly align the final address in case we have a hardware ++ * issue that requires alignment for performance reasons. + */ +- addr = PAGE_ALIGN(addr); + addr = align_vdso_addr(addr); + + return addr; +diff --git a/block/blk-mq-cpumap.c b/block/blk-mq-cpumap.c +index f8721278601c..78d38352bf8d 100644 +--- a/block/blk-mq-cpumap.c ++++ b/block/blk-mq-cpumap.c +@@ -95,7 +95,7 @@ unsigned int *blk_mq_make_queue_map(struct blk_mq_reg *reg) + unsigned int *map; + + /* If cpus are offline, map them to first hctx */ +- map = kzalloc_node(sizeof(*map) * num_possible_cpus(), GFP_KERNEL, ++ map = kzalloc_node(sizeof(*map) * nr_cpu_ids, GFP_KERNEL, + reg->numa_node); + if (!map) + return NULL; +diff --git a/block/genhd.c b/block/genhd.c +index e6723bd4d7a1..a8d586a729bb 100644 +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -1070,9 +1070,16 @@ int disk_expand_part_tbl(struct gendisk *disk, int partno) + struct disk_part_tbl *old_ptbl = disk->part_tbl; + struct disk_part_tbl *new_ptbl; + int len = old_ptbl ? old_ptbl->len : 0; +- int target = partno + 1; ++ int i, target; + size_t size; +- int i; ++ ++ /* ++ * check for int overflow, since we can get here from blkpg_ioctl() ++ * with a user passed 'partno'. ++ */ ++ target = partno + 1; ++ if (target < 0) ++ return -EINVAL; + + /* disk_max_parts() is zero during initialization, ignore if so */ + if (disk_max_parts(disk) && target > disk_max_parts(disk)) +diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c +index c14a00d3dca6..19f650556e2e 100644 +--- a/drivers/acpi/device_pm.c ++++ b/drivers/acpi/device_pm.c +@@ -257,7 +257,7 @@ int acpi_bus_init_power(struct acpi_device *device) + + device->power.state = ACPI_STATE_UNKNOWN; + if (!acpi_device_is_present(device)) +- return 0; ++ return -ENXIO; + + result = acpi_device_get_power(device, &state); + if (result) +diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c +index 493a342efa44..666beea3bf1c 100644 +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -865,7 +865,7 @@ static void acpi_free_power_resources_lists(struct acpi_device *device) + if (device->wakeup.flags.valid) + acpi_power_resources_list_free(&device->wakeup.resources); + +- if (!device->flags.power_manageable) ++ if (!device->power.flags.power_resources) + return; + + for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) { +@@ -1554,10 +1554,8 @@ static void acpi_bus_get_power_flags(struct acpi_device *device) + device->power.flags.power_resources) + device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible = 1; + +- if (acpi_bus_init_power(device)) { +- acpi_free_power_resources_lists(device); ++ if (acpi_bus_init_power(device)) + device->flags.power_manageable = 0; +- } + } + + static void acpi_bus_get_flags(struct acpi_device *device) +@@ -2043,13 +2041,18 @@ static void acpi_bus_attach(struct acpi_device *device) + /* Skip devices that are not present. */ + if (!acpi_device_is_present(device)) { + device->flags.visited = false; ++ device->flags.power_manageable = 0; + return; + } + if (device->handler) + goto ok; + + if (!device->flags.initialized) { +- acpi_bus_update_power(device, NULL); ++ device->flags.power_manageable = ++ device->power.states[ACPI_STATE_D0].flags.valid; ++ if (acpi_bus_init_power(device)) ++ device->flags.power_manageable = 0; ++ + device->flags.initialized = true; + } + device->flags.visited = false; +diff --git a/drivers/base/bus.c b/drivers/base/bus.c +index 59dc8086e4fa..45d0fa78981c 100644 +--- a/drivers/base/bus.c ++++ b/drivers/base/bus.c +@@ -254,13 +254,15 @@ static ssize_t store_drivers_probe(struct bus_type *bus, + const char *buf, size_t count) + { + struct device *dev; ++ int err = -EINVAL; + + dev = bus_find_device_by_name(bus, NULL, buf); + if (!dev) + return -ENODEV; +- if (bus_rescan_devices_helper(dev, NULL) != 0) +- return -EINVAL; +- return count; ++ if (bus_rescan_devices_helper(dev, NULL) == 0) ++ err = count; ++ put_device(dev); ++ return err; + } + + static struct device *next_device(struct klist_iter *i) +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 7cd42ea30d6d..d92c7d9b959a 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1743,6 +1743,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) }, +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 91bc66b4b151..4850da34d3ef 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -511,6 +511,7 @@ + #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 + #define USB_DEVICE_ID_KYE_EASYPEN_I405X 0x5010 + #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X 0x5011 ++#define USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2 0x501a + #define USB_DEVICE_ID_KYE_EASYPEN_M610X 0x5013 + + #define USB_VENDOR_ID_LABTEC 0x1020 +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index a713e6211419..4b87bb164f30 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -312,6 +312,9 @@ static const struct hid_device_id hid_battery_quirks[] = { + USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI), + HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, ++ USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO), ++ HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE }, ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI), + HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE }, + {} +diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c +index b92bf01a1ae8..158fcf577fae 100644 +--- a/drivers/hid/hid-kye.c ++++ b/drivers/hid/hid-kye.c +@@ -323,6 +323,7 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, + } + break; + case USB_DEVICE_ID_KYE_MOUSEPEN_I608X: ++ case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2: + if (*rsize == MOUSEPEN_I608X_RDESC_ORIG_SIZE) { + rdesc = mousepen_i608x_rdesc_fixed; + *rsize = sizeof(mousepen_i608x_rdesc_fixed); +@@ -415,6 +416,7 @@ static int kye_probe(struct hid_device *hdev, const struct hid_device_id *id) + switch (id->product) { + case USB_DEVICE_ID_KYE_EASYPEN_I405X: + case USB_DEVICE_ID_KYE_MOUSEPEN_I608X: ++ case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2: + case USB_DEVICE_ID_KYE_EASYPEN_M610X: + ret = kye_tablet_enable(hdev); + if (ret) { +@@ -446,6 +448,8 @@ static const struct hid_device_id kye_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, + USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, ++ USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, + USB_DEVICE_ID_KYE_EASYPEN_M610X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, + USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, +diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c +index 1a07e07d99a0..47d7e74231e5 100644 +--- a/drivers/hid/hid-roccat-pyra.c ++++ b/drivers/hid/hid-roccat-pyra.c +@@ -35,6 +35,8 @@ static struct class *pyra_class; + static void profile_activated(struct pyra_device *pyra, + unsigned int new_profile) + { ++ if (new_profile >= ARRAY_SIZE(pyra->profile_settings)) ++ return; + pyra->actual_profile = new_profile; + pyra->actual_cpi = pyra->profile_settings[pyra->actual_profile].y_cpi; + } +@@ -257,9 +259,11 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp, + if (off != 0 || count != PYRA_SIZE_SETTINGS) + return -EINVAL; + +- mutex_lock(&pyra->pyra_lock); +- + settings = (struct pyra_settings const *)buf; ++ if (settings->startup_profile >= ARRAY_SIZE(pyra->profile_settings)) ++ return -EINVAL; ++ ++ mutex_lock(&pyra->pyra_lock); + + retval = pyra_set_settings(usb_dev, settings); + if (retval) { +diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c +index 42eebd14de1f..6e5d8fe0ce8f 100644 +--- a/drivers/hid/i2c-hid/i2c-hid.c ++++ b/drivers/hid/i2c-hid/i2c-hid.c +@@ -136,6 +136,7 @@ struct i2c_hid { + * descriptor. */ + unsigned int bufsize; /* i2c buffer size */ + char *inbuf; /* Input buffer */ ++ char *rawbuf; /* Raw Input buffer */ + char *cmdbuf; /* Command buffer */ + char *argsbuf; /* Command arguments buffer */ + +@@ -355,7 +356,7 @@ static int i2c_hid_hwreset(struct i2c_client *client) + static void i2c_hid_get_input(struct i2c_hid *ihid) + { + int ret, ret_size; +- int size = le16_to_cpu(ihid->hdesc.wMaxInputLength); ++ int size = ihid->bufsize; + + ret = i2c_master_recv(ihid->client, ihid->inbuf, size); + if (ret != size) { +@@ -482,9 +483,11 @@ static void i2c_hid_find_max_report(struct hid_device *hid, unsigned int type, + static void i2c_hid_free_buffers(struct i2c_hid *ihid) + { + kfree(ihid->inbuf); ++ kfree(ihid->rawbuf); + kfree(ihid->argsbuf); + kfree(ihid->cmdbuf); + ihid->inbuf = NULL; ++ ihid->rawbuf = NULL; + ihid->cmdbuf = NULL; + ihid->argsbuf = NULL; + ihid->bufsize = 0; +@@ -500,10 +503,11 @@ static int i2c_hid_alloc_buffers(struct i2c_hid *ihid, size_t report_size) + report_size; /* report */ + + ihid->inbuf = kzalloc(report_size, GFP_KERNEL); ++ ihid->rawbuf = kzalloc(report_size, GFP_KERNEL); + ihid->argsbuf = kzalloc(args_len, GFP_KERNEL); + ihid->cmdbuf = kzalloc(sizeof(union command) + args_len, GFP_KERNEL); + +- if (!ihid->inbuf || !ihid->argsbuf || !ihid->cmdbuf) { ++ if (!ihid->inbuf || !ihid->rawbuf || !ihid->argsbuf || !ihid->cmdbuf) { + i2c_hid_free_buffers(ihid); + return -ENOMEM; + } +@@ -530,12 +534,12 @@ static int i2c_hid_get_raw_report(struct hid_device *hid, + + ret = i2c_hid_get_report(client, + report_type == HID_FEATURE_REPORT ? 0x03 : 0x01, +- report_number, ihid->inbuf, ask_count); ++ report_number, ihid->rawbuf, ask_count); + + if (ret < 0) + return ret; + +- ret_count = ihid->inbuf[0] | (ihid->inbuf[1] << 8); ++ ret_count = ihid->rawbuf[0] | (ihid->rawbuf[1] << 8); + + if (ret_count <= 2) + return 0; +@@ -544,7 +548,7 @@ static int i2c_hid_get_raw_report(struct hid_device *hid, + + /* The query buffer contains the size, dropping it in the reply */ + count = min(count, ret_count - 2); +- memcpy(buf, ihid->inbuf + 2, count); ++ memcpy(buf, ihid->rawbuf + 2, count); + + return count; + } +diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c +index deb364306636..473c0c43af52 100644 +--- a/drivers/hid/usbhid/hid-quirks.c ++++ b/drivers/hid/usbhid/hid-quirks.c +@@ -116,6 +116,7 @@ static const struct hid_blacklist { + { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT }, ++ { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS }, +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index fa920469bf10..505fe29c75b0 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -202,9 +202,16 @@ static void vmbus_process_rescind_offer(struct work_struct *work) + unsigned long flags; + struct vmbus_channel *primary_channel; + struct vmbus_channel_relid_released msg; ++ struct device *dev; ++ ++ if (channel->device_obj) { ++ dev = get_device(&channel->device_obj->device); ++ if (dev) { ++ vmbus_device_unregister(channel->device_obj); ++ put_device(dev); ++ } ++ } + +- if (channel->device_obj) +- vmbus_device_unregister(channel->device_obj); + memset(&msg, 0, sizeof(struct vmbus_channel_relid_released)); + msg.child_relid = channel->offermsg.child_relid; + msg.header.msgtype = CHANNELMSG_RELID_RELEASED; +diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c +index 40f6b47c28f6..8855ecbc36be 100644 +--- a/drivers/iommu/intel-iommu.c ++++ b/drivers/iommu/intel-iommu.c +@@ -1768,7 +1768,7 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, + struct dma_pte *first_pte = NULL, *pte = NULL; + phys_addr_t uninitialized_var(pteval); + int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; +- unsigned long sg_res; ++ unsigned long sg_res = 0; + unsigned int largepage_lvl = 0; + unsigned long lvl_pages = 0; + +@@ -1779,10 +1779,8 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, + + prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP; + +- if (sg) +- sg_res = 0; +- else { +- sg_res = nr_pages + 1; ++ if (!sg) { ++ sg_res = nr_pages; + pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot; + } + +diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c +index 6b1a6ef9f1a8..0c3a64708409 100644 +--- a/drivers/misc/genwqe/card_utils.c ++++ b/drivers/misc/genwqe/card_utils.c +@@ -490,6 +490,8 @@ int genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m, void *uaddr, + m->nr_pages, + 1, /* write by caller */ + m->page_list); /* ptrs to pages */ ++ if (rc < 0) ++ goto fail_get_user_pages; + + /* assumption: get_user_pages can be killed by signals. */ + if (rc < m->nr_pages) { +diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c +index 9ddef4763541..7e0176321aff 100644 +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -1343,6 +1343,8 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) + + sdhci_runtime_pm_get(host); + ++ present = mmc_gpio_get_cd(host->mmc); ++ + spin_lock_irqsave(&host->lock, flags); + + WARN_ON(host->mrq != NULL); +@@ -1371,7 +1373,6 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) + * zero: cd-gpio is used, and card is removed + * one: cd-gpio is used, and card is present + */ +- present = mmc_gpio_get_cd(host->mmc); + if (present < 0) { + /* If polling, assume that the card is always present. */ + if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) +@@ -2082,15 +2083,18 @@ static void sdhci_card_event(struct mmc_host *mmc) + { + struct sdhci_host *host = mmc_priv(mmc); + unsigned long flags; ++ int present; + + /* First check if client has provided their own card event */ + if (host->ops->card_event) + host->ops->card_event(host); + ++ present = sdhci_do_get_cd(host); ++ + spin_lock_irqsave(&host->lock, flags); + + /* Check host->mrq first in case we are runtime suspended */ +- if (host->mrq && !sdhci_do_get_cd(host)) { ++ if (host->mrq && !present) { + pr_err("%s: Card removed during transfer!\n", + mmc_hostname(host->mmc)); + pr_err("%s: Resetting controller.\n", +diff --git a/drivers/mtd/tests/torturetest.c b/drivers/mtd/tests/torturetest.c +index eeab96973cf0..b55bc52a1340 100644 +--- a/drivers/mtd/tests/torturetest.c ++++ b/drivers/mtd/tests/torturetest.c +@@ -264,7 +264,9 @@ static int __init tort_init(void) + int i; + void *patt; + +- mtdtest_erase_good_eraseblocks(mtd, bad_ebs, eb, ebcnt); ++ err = mtdtest_erase_good_eraseblocks(mtd, bad_ebs, eb, ebcnt); ++ if (err) ++ goto out; + + /* Check if the eraseblocks contain only 0xFF bytes */ + if (check) { +diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c +index ec2c2dc1c1ca..2a1b6e037e1a 100644 +--- a/drivers/mtd/ubi/upd.c ++++ b/drivers/mtd/ubi/upd.c +@@ -133,6 +133,10 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, + ubi_assert(!vol->updating && !vol->changing_leb); + vol->updating = 1; + ++ vol->upd_buf = vmalloc(ubi->leb_size); ++ if (!vol->upd_buf) ++ return -ENOMEM; ++ + err = set_update_marker(ubi, vol); + if (err) + return err; +@@ -152,14 +156,12 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, + err = clear_update_marker(ubi, vol, 0); + if (err) + return err; ++ ++ vfree(vol->upd_buf); + vol->updating = 0; + return 0; + } + +- vol->upd_buf = vmalloc(ubi->leb_size); +- if (!vol->upd_buf) +- return -ENOMEM; +- + vol->upd_ebs = div_u64(bytes + vol->usable_leb_size - 1, + vol->usable_leb_size); + vol->upd_bytes = bytes; +diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c +index 02317c1c0238..68b924ec222e 100644 +--- a/drivers/mtd/ubi/wl.c ++++ b/drivers/mtd/ubi/wl.c +@@ -1205,7 +1205,6 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, + + err = do_sync_erase(ubi, e1, vol_id, lnum, 0); + if (err) { +- kmem_cache_free(ubi_wl_entry_slab, e1); + if (e2) + kmem_cache_free(ubi_wl_entry_slab, e2); + goto out_ro; +@@ -1219,10 +1218,8 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, + dbg_wl("PEB %d (LEB %d:%d) was put meanwhile, erase", + e2->pnum, vol_id, lnum); + err = do_sync_erase(ubi, e2, vol_id, lnum, 0); +- if (err) { +- kmem_cache_free(ubi_wl_entry_slab, e2); ++ if (err) + goto out_ro; +- } + } + + dbg_wl("done"); +@@ -1258,10 +1255,9 @@ out_not_moved: + + ubi_free_vid_hdr(ubi, vid_hdr); + err = do_sync_erase(ubi, e2, vol_id, lnum, torture); +- if (err) { +- kmem_cache_free(ubi_wl_entry_slab, e2); ++ if (err) + goto out_ro; +- } ++ + mutex_unlock(&ubi->move_mutex); + return 0; + +diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c +index 0b7a4c3b01a2..03e7f0cbda8c 100644 +--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c ++++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c +@@ -734,7 +734,7 @@ static int peak_usb_create_dev(struct peak_usb_adapter *peak_usb_adapter, + dev->cmd_buf = kmalloc(PCAN_USB_MAX_CMD_LEN, GFP_KERNEL); + if (!dev->cmd_buf) { + err = -ENOMEM; +- goto lbl_set_intf_data; ++ goto lbl_free_candev; + } + + dev->udev = usb_dev; +@@ -773,7 +773,7 @@ static int peak_usb_create_dev(struct peak_usb_adapter *peak_usb_adapter, + err = register_candev(netdev); + if (err) { + dev_err(&intf->dev, "couldn't register CAN device: %d\n", err); +- goto lbl_free_cmd_buf; ++ goto lbl_restore_intf_data; + } + + if (dev->prev_siblings) +@@ -786,14 +786,14 @@ static int peak_usb_create_dev(struct peak_usb_adapter *peak_usb_adapter, + if (dev->adapter->dev_init) { + err = dev->adapter->dev_init(dev); + if (err) +- goto lbl_free_cmd_buf; ++ goto lbl_unregister_candev; + } + + /* set bus off */ + if (dev->adapter->dev_set_bus) { + err = dev->adapter->dev_set_bus(dev, 0); + if (err) +- goto lbl_free_cmd_buf; ++ goto lbl_unregister_candev; + } + + /* get device number early */ +@@ -805,11 +805,14 @@ static int peak_usb_create_dev(struct peak_usb_adapter *peak_usb_adapter, + + return 0; + +-lbl_free_cmd_buf: +- kfree(dev->cmd_buf); ++lbl_unregister_candev: ++ unregister_candev(netdev); + +-lbl_set_intf_data: ++lbl_restore_intf_data: + usb_set_intfdata(intf, dev->prev_siblings); ++ kfree(dev->cmd_buf); ++ ++lbl_free_candev: + free_candev(netdev); + + return err; +diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +index 263dd921edc4..f7f796a2c50b 100644 +--- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c ++++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +@@ -333,8 +333,6 @@ static int pcan_usb_pro_send_req(struct peak_usb_device *dev, int req_id, + if (!(dev->state & PCAN_USB_STATE_CONNECTED)) + return 0; + +- memset(req_addr, '\0', req_size); +- + req_type = USB_TYPE_VENDOR | USB_RECIP_OTHER; + + switch (req_id) { +@@ -345,6 +343,7 @@ static int pcan_usb_pro_send_req(struct peak_usb_device *dev, int req_id, + default: + p = usb_rcvctrlpipe(dev->udev, 0); + req_type |= USB_DIR_IN; ++ memset(req_addr, '\0', req_size); + break; + } + +diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c +index 0583c69d26db..ddaad712c59a 100644 +--- a/drivers/net/wireless/ath/ath5k/qcu.c ++++ b/drivers/net/wireless/ath/ath5k/qcu.c +@@ -225,13 +225,7 @@ ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, + } else { + switch (queue_type) { + case AR5K_TX_QUEUE_DATA: +- for (queue = AR5K_TX_QUEUE_ID_DATA_MIN; +- ah->ah_txq[queue].tqi_type != +- AR5K_TX_QUEUE_INACTIVE; queue++) { +- +- if (queue > AR5K_TX_QUEUE_ID_DATA_MAX) +- return -EINVAL; +- } ++ queue = queue_info->tqi_subtype; + break; + case AR5K_TX_QUEUE_UAPSD: + queue = AR5K_TX_QUEUE_ID_UAPSD; +diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h +index 0acd4b5a4892..32ae0a47fed0 100644 +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -216,8 +216,8 @@ + #define AH_WOW_BEACON_MISS BIT(3) + + enum ath_hw_txq_subtype { +- ATH_TXQ_AC_BE = 0, +- ATH_TXQ_AC_BK = 1, ++ ATH_TXQ_AC_BK = 0, ++ ATH_TXQ_AC_BE = 1, + ATH_TXQ_AC_VI = 2, + ATH_TXQ_AC_VO = 3, + }; +diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c +index 5f727588ca27..8f93ed373fb5 100644 +--- a/drivers/net/wireless/ath/ath9k/mac.c ++++ b/drivers/net/wireless/ath/ath9k/mac.c +@@ -311,14 +311,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, + q = ATH9K_NUM_TX_QUEUES - 3; + break; + case ATH9K_TX_QUEUE_DATA: +- for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++) +- if (ah->txq[q].tqi_type == +- ATH9K_TX_QUEUE_INACTIVE) +- break; +- if (q == ATH9K_NUM_TX_QUEUES) { +- ath_err(common, "No available TX queue\n"); +- return -1; +- } ++ q = qinfo->tqi_subtype; + break; + default: + ath_err(common, "Invalid TX queue type: %u\n", type); +diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h +index d8948aa9c2d2..60dc387cc554 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h ++++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h +@@ -1394,7 +1394,7 @@ enum iwl_sf_scenario { + #define SF_NUM_TIMEOUT_TYPES 2 /* Aging timer and Idle timer */ + + /* smart FIFO default values */ +-#define SF_W_MARK_SISO 4096 ++#define SF_W_MARK_SISO 6144 + #define SF_W_MARK_MIMO2 8192 + #define SF_W_MARK_MIMO3 6144 + #define SF_W_MARK_LEGACY 4096 +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index 34dff3a09b98..5b428db6a150 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -214,14 +214,17 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, + res->flags |= IORESOURCE_SIZEALIGN; + if (res->flags & IORESOURCE_IO) { + l &= PCI_BASE_ADDRESS_IO_MASK; ++ sz &= PCI_BASE_ADDRESS_IO_MASK; + mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT; + } else { + l &= PCI_BASE_ADDRESS_MEM_MASK; ++ sz &= PCI_BASE_ADDRESS_MEM_MASK; + mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; + } + } else { + res->flags |= (l & IORESOURCE_ROM_ENABLE); + l &= PCI_ROM_ADDRESS_MASK; ++ sz &= PCI_ROM_ADDRESS_MASK; + mask = (u32)PCI_ROM_ADDRESS_MASK; + } + +diff --git a/drivers/rtc/rtc-isl12057.c b/drivers/rtc/rtc-isl12057.c +index 7854a656628f..110eab817a4f 100644 +--- a/drivers/rtc/rtc-isl12057.c ++++ b/drivers/rtc/rtc-isl12057.c +@@ -89,7 +89,7 @@ static void isl12057_rtc_regs_to_tm(struct rtc_time *tm, u8 *regs) + tm->tm_min = bcd2bin(regs[ISL12057_REG_RTC_MN]); + + if (regs[ISL12057_REG_RTC_HR] & ISL12057_REG_RTC_HR_MIL) { /* AM/PM */ +- tm->tm_hour = bcd2bin(regs[ISL12057_REG_RTC_HR] & 0x0f); ++ tm->tm_hour = bcd2bin(regs[ISL12057_REG_RTC_HR] & 0x1f); + if (regs[ISL12057_REG_RTC_HR] & ISL12057_REG_RTC_HR_PM) + tm->tm_hour += 12; + } else { /* 24 hour mode */ +@@ -98,7 +98,7 @@ static void isl12057_rtc_regs_to_tm(struct rtc_time *tm, u8 *regs) + + tm->tm_mday = bcd2bin(regs[ISL12057_REG_RTC_DT]); + tm->tm_wday = bcd2bin(regs[ISL12057_REG_RTC_DW]) - 1; /* starts at 1 */ +- tm->tm_mon = bcd2bin(regs[ISL12057_REG_RTC_MO]) - 1; /* starts at 1 */ ++ tm->tm_mon = bcd2bin(regs[ISL12057_REG_RTC_MO] & 0x1f) - 1; /* ditto */ + tm->tm_year = bcd2bin(regs[ISL12057_REG_RTC_YR]) + 100; + } + +diff --git a/drivers/rtc/rtc-sirfsoc.c b/drivers/rtc/rtc-sirfsoc.c +index 3eb3642ae299..d2b1ab3162c2 100644 +--- a/drivers/rtc/rtc-sirfsoc.c ++++ b/drivers/rtc/rtc-sirfsoc.c +@@ -290,14 +290,6 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev) + rtc_div = ((32768 / RTC_HZ) / 2) - 1; + sirfsoc_rtc_iobrg_writel(rtc_div, rtcdrv->rtc_base + RTC_DIV); + +- rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, +- &sirfsoc_rtc_ops, THIS_MODULE); +- if (IS_ERR(rtcdrv->rtc)) { +- err = PTR_ERR(rtcdrv->rtc); +- dev_err(&pdev->dev, "can't register RTC device\n"); +- return err; +- } +- + /* 0x3 -> RTC_CLK */ + sirfsoc_rtc_iobrg_writel(SIRFSOC_RTC_CLK, + rtcdrv->rtc_base + RTC_CLOCK_SWITCH); +@@ -312,6 +304,14 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev) + rtcdrv->overflow_rtc = + sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_SW_VALUE); + ++ rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, ++ &sirfsoc_rtc_ops, THIS_MODULE); ++ if (IS_ERR(rtcdrv->rtc)) { ++ err = PTR_ERR(rtcdrv->rtc); ++ dev_err(&pdev->dev, "can't register RTC device\n"); ++ return err; ++ } ++ + rtcdrv->irq = platform_get_irq(pdev, 0); + err = devm_request_irq( + &pdev->dev, +diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c +index 119f7af94537..4dcb2929c01f 100644 +--- a/drivers/spi/spi-fsl-spi.c ++++ b/drivers/spi/spi-fsl-spi.c +@@ -362,18 +362,28 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t, + static void fsl_spi_do_one_msg(struct spi_message *m) + { + struct spi_device *spi = m->spi; +- struct spi_transfer *t; ++ struct spi_transfer *t, *first; + unsigned int cs_change; + const int nsecs = 50; + int status; + +- cs_change = 1; +- status = 0; ++ /* Don't allow changes if CS is active */ ++ first = list_first_entry(&m->transfers, struct spi_transfer, ++ transfer_list); + list_for_each_entry(t, &m->transfers, transfer_list) { +- if (t->bits_per_word || t->speed_hz) { +- /* Don't allow changes if CS is active */ ++ if ((first->bits_per_word != t->bits_per_word) || ++ (first->speed_hz != t->speed_hz)) { + status = -EINVAL; ++ dev_err(&spi->dev, ++ "bits_per_word/speed_hz should be same for the same SPI transfer\n"); ++ return; ++ } ++ } + ++ cs_change = 1; ++ status = -EINVAL; ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ if (t->bits_per_word || t->speed_hz) { + if (cs_change) + status = fsl_spi_setup_transfer(spi, t); + if (status < 0) +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index 28ac3f3b7ec3..d46b4ccec8cd 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -321,7 +321,8 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) + + static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata) + { +- *read_buf_addr(ldata, ldata->read_head++) = c; ++ *read_buf_addr(ldata, ldata->read_head) = c; ++ ldata->read_head++; + } + + /** +diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c +index 9cd706df3b33..7d3a3f5cb5ba 100644 +--- a/drivers/tty/serial/samsung.c ++++ b/drivers/tty/serial/samsung.c +@@ -544,11 +544,15 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, + unsigned int old) + { + struct s3c24xx_uart_port *ourport = to_ourport(port); ++ int timeout = 10000; + + ourport->pm_level = level; + + switch (level) { + case 3: ++ while (--timeout && !s3c24xx_serial_txempty_nofifo(port)) ++ udelay(100); ++ + if (!IS_ERR(ourport->baudclk)) + clk_disable_unprepare(ourport->baudclk); + +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index 331f06a91cc3..d7049c393a33 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1169,10 +1169,11 @@ next_desc: + } else { + control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0); + data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0)); +- if (!control_interface || !data_interface) { +- dev_dbg(&intf->dev, "no interfaces\n"); +- return -ENODEV; +- } ++ } ++ ++ if (!control_interface || !data_interface) { ++ dev_dbg(&intf->dev, "no interfaces\n"); ++ return -ENODEV; + } + + if (data_interface_num != call_interface_num) +@@ -1448,6 +1449,7 @@ alloc_fail8: + &dev_attr_wCountryCodes); + device_remove_file(&acm->control->dev, + &dev_attr_iCountryCodeRelDate); ++ kfree(acm->country_codes); + } + device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); + alloc_fail7: +diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c +index ebd8f218a788..9df5d6ec7eec 100644 +--- a/drivers/xen/swiotlb-xen.c ++++ b/drivers/xen/swiotlb-xen.c +@@ -96,8 +96,6 @@ static inline phys_addr_t xen_bus_to_phys(dma_addr_t baddr) + dma_addr_t dma = (dma_addr_t)pfn << PAGE_SHIFT; + phys_addr_t paddr = dma; + +- BUG_ON(paddr != dma); /* truncation has occurred, should never happen */ +- + paddr |= baddr & ~PAGE_MASK; + + return paddr; +@@ -447,11 +445,11 @@ static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr, + + BUG_ON(dir == DMA_NONE); + +- xen_dma_unmap_page(hwdev, paddr, size, dir, attrs); ++ xen_dma_unmap_page(hwdev, dev_addr, size, dir, attrs); + + /* NOTE: We use dev_addr here, not paddr! */ + if (is_xen_swiotlb_buffer(dev_addr)) { +- swiotlb_tbl_unmap_single(hwdev, paddr, size, dir); ++ swiotlb_tbl_unmap_single(hwdev, dev_addr, size, dir); + return; + } + +@@ -495,14 +493,14 @@ xen_swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr, + BUG_ON(dir == DMA_NONE); + + if (target == SYNC_FOR_CPU) +- xen_dma_sync_single_for_cpu(hwdev, paddr, size, dir); ++ xen_dma_sync_single_for_cpu(hwdev, dev_addr, size, dir); + + /* NOTE: We use dev_addr here, not paddr! */ + if (is_xen_swiotlb_buffer(dev_addr)) + swiotlb_tbl_sync_single(hwdev, paddr, size, dir, target); + + if (target == SYNC_FOR_DEVICE) +- xen_dma_sync_single_for_cpu(hwdev, paddr, size, dir); ++ xen_dma_sync_single_for_device(hwdev, dev_addr, size, dir); + + if (dir != DMA_FROM_DEVICE) + return; +diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c +index 451b00c86f6c..12e35566d2fc 100644 +--- a/fs/btrfs/delayed-inode.c ++++ b/fs/btrfs/delayed-inode.c +@@ -1854,6 +1854,14 @@ int btrfs_delayed_delete_inode_ref(struct inode *inode) + { + struct btrfs_delayed_node *delayed_node; + ++ /* ++ * we don't do delayed inode updates during log recovery because it ++ * leads to enospc problems. This means we also can't do ++ * delayed inode refs ++ */ ++ if (BTRFS_I(inode)->root->fs_info->log_root_recovering) ++ return -EAGAIN; ++ + delayed_node = btrfs_get_or_create_delayed_node(inode); + if (IS_ERR(delayed_node)) + return PTR_ERR(delayed_node); +diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c +index b53278c9fd97..94a85ee5b990 100644 +--- a/fs/ceph/addr.c ++++ b/fs/ceph/addr.c +@@ -676,7 +676,7 @@ static int ceph_writepages_start(struct address_space *mapping, + int rc = 0; + unsigned wsize = 1 << inode->i_blkbits; + struct ceph_osd_request *req = NULL; +- int do_sync; ++ int do_sync = 0; + u64 truncate_size, snap_size; + u32 truncate_seq; + +diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c +index f4f050a69a48..339c41216d14 100644 +--- a/fs/ceph/mds_client.c ++++ b/fs/ceph/mds_client.c +@@ -1461,15 +1461,18 @@ static void discard_cap_releases(struct ceph_mds_client *mdsc, + + dout("discard_cap_releases mds%d\n", session->s_mds); + +- /* zero out the in-progress message */ +- msg = list_first_entry(&session->s_cap_releases, +- struct ceph_msg, list_head); +- head = msg->front.iov_base; +- num = le32_to_cpu(head->num); +- dout("discard_cap_releases mds%d %p %u\n", session->s_mds, msg, num); +- head->num = cpu_to_le32(0); +- msg->front.iov_len = sizeof(*head); +- session->s_num_cap_releases += num; ++ if (!list_empty(&session->s_cap_releases)) { ++ /* zero out the in-progress message */ ++ msg = list_first_entry(&session->s_cap_releases, ++ struct ceph_msg, list_head); ++ head = msg->front.iov_base; ++ num = le32_to_cpu(head->num); ++ dout("discard_cap_releases mds%d %p %u\n", ++ session->s_mds, msg, num); ++ head->num = cpu_to_le32(0); ++ msg->front.iov_len = sizeof(*head); ++ session->s_num_cap_releases += num; ++ } + + /* requeue completed messages */ + while (!list_empty(&session->s_cap_releases_done)) { +diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c +index a16315957ef3..23a51f08e3b5 100644 +--- a/fs/fs-writeback.c ++++ b/fs/fs-writeback.c +@@ -476,12 +476,28 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) + * write_inode() + */ + spin_lock(&inode->i_lock); +- /* Clear I_DIRTY_PAGES if we've written out all dirty pages */ +- if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) +- inode->i_state &= ~I_DIRTY_PAGES; ++ + dirty = inode->i_state & I_DIRTY; +- inode->i_state &= ~(I_DIRTY_SYNC | I_DIRTY_DATASYNC); ++ inode->i_state &= ~I_DIRTY; ++ ++ /* ++ * Paired with smp_mb() in __mark_inode_dirty(). This allows ++ * __mark_inode_dirty() to test i_state without grabbing i_lock - ++ * either they see the I_DIRTY bits cleared or we see the dirtied ++ * inode. ++ * ++ * I_DIRTY_PAGES is always cleared together above even if @mapping ++ * still has dirty pages. The flag is reinstated after smp_mb() if ++ * necessary. This guarantees that either __mark_inode_dirty() ++ * sees clear I_DIRTY_PAGES or we see PAGECACHE_TAG_DIRTY. ++ */ ++ smp_mb(); ++ ++ if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) ++ inode->i_state |= I_DIRTY_PAGES; ++ + spin_unlock(&inode->i_lock); ++ + /* Don't write the inode if only I_DIRTY_PAGES was set */ + if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { + int err = write_inode(inode, wbc); +@@ -1145,12 +1161,11 @@ void __mark_inode_dirty(struct inode *inode, int flags) + } + + /* +- * make sure that changes are seen by all cpus before we test i_state +- * -- mikulas ++ * Paired with smp_mb() in __writeback_single_inode() for the ++ * following lockless i_state test. See there for details. + */ + smp_mb(); + +- /* avoid the locking if we can */ + if ((inode->i_state & flags) == flags) + return; + +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index 34d2a1f2f400..daa53da1d286 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -1209,15 +1209,14 @@ static int copy_cred(struct svc_cred *target, struct svc_cred *source) + return 0; + } + +-static long long ++static int + compare_blob(const struct xdr_netobj *o1, const struct xdr_netobj *o2) + { +- long long res; +- +- res = o1->len - o2->len; +- if (res) +- return res; +- return (long long)memcmp(o1->data, o2->data, o1->len); ++ if (o1->len < o2->len) ++ return -1; ++ if (o1->len > o2->len) ++ return 1; ++ return memcmp(o1->data, o2->data, o1->len); + } + + static int same_name(const char *n1, const char *n2) +@@ -1401,7 +1400,7 @@ add_clp_to_name_tree(struct nfs4_client *new_clp, struct rb_root *root) + static struct nfs4_client * + find_clp_in_name_tree(struct xdr_netobj *name, struct rb_root *root) + { +- long long cmp; ++ int cmp; + struct rb_node *node = root->rb_node; + struct nfs4_client *clp; + +diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c +index 86573350350e..dd1afa38f2ae 100644 +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -1809,6 +1809,9 @@ static __be32 nfsd4_encode_components_esc(char sep, char *components, + } + else + end++; ++ if (found_esc) ++ end = next; ++ + str = end; + } + *pp = p; +diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c +index 1e0bbae06ee7..09480c53fd74 100644 +--- a/fs/nilfs2/inode.c ++++ b/fs/nilfs2/inode.c +@@ -49,6 +49,8 @@ struct nilfs_iget_args { + int for_gc; + }; + ++static int nilfs_iget_test(struct inode *inode, void *opaque); ++ + void nilfs_inode_add_blocks(struct inode *inode, int n) + { + struct nilfs_root *root = NILFS_I(inode)->i_root; +@@ -347,6 +349,17 @@ const struct address_space_operations nilfs_aops = { + .is_partially_uptodate = block_is_partially_uptodate, + }; + ++static int nilfs_insert_inode_locked(struct inode *inode, ++ struct nilfs_root *root, ++ unsigned long ino) ++{ ++ struct nilfs_iget_args args = { ++ .ino = ino, .root = root, .cno = 0, .for_gc = 0 ++ }; ++ ++ return insert_inode_locked4(inode, ino, nilfs_iget_test, &args); ++} ++ + struct inode *nilfs_new_inode(struct inode *dir, umode_t mode) + { + struct super_block *sb = dir->i_sb; +@@ -382,7 +395,7 @@ struct inode *nilfs_new_inode(struct inode *dir, umode_t mode) + if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { + err = nilfs_bmap_read(ii->i_bmap, NULL); + if (err < 0) +- goto failed_bmap; ++ goto failed_after_creation; + + set_bit(NILFS_I_BMAP, &ii->i_state); + /* No lock is needed; iget() ensures it. */ +@@ -398,21 +411,24 @@ struct inode *nilfs_new_inode(struct inode *dir, umode_t mode) + spin_lock(&nilfs->ns_next_gen_lock); + inode->i_generation = nilfs->ns_next_generation++; + spin_unlock(&nilfs->ns_next_gen_lock); +- insert_inode_hash(inode); ++ if (nilfs_insert_inode_locked(inode, root, ino) < 0) { ++ err = -EIO; ++ goto failed_after_creation; ++ } + + err = nilfs_init_acl(inode, dir); + if (unlikely(err)) +- goto failed_acl; /* never occur. When supporting ++ goto failed_after_creation; /* never occur. When supporting + nilfs_init_acl(), proper cancellation of + above jobs should be considered */ + + return inode; + +- failed_acl: +- failed_bmap: ++ failed_after_creation: + clear_nlink(inode); ++ unlock_new_inode(inode); + iput(inode); /* raw_inode will be deleted through +- generic_delete_inode() */ ++ nilfs_evict_inode() */ + goto failed; + + failed_ifile_create_inode: +@@ -460,8 +476,8 @@ int nilfs_read_inode_common(struct inode *inode, + inode->i_atime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec); + inode->i_ctime.tv_nsec = le32_to_cpu(raw_inode->i_ctime_nsec); + inode->i_mtime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec); +- if (inode->i_nlink == 0 && inode->i_mode == 0) +- return -EINVAL; /* this inode is deleted */ ++ if (inode->i_nlink == 0) ++ return -ESTALE; /* this inode is deleted */ + + inode->i_blocks = le64_to_cpu(raw_inode->i_blocks); + ii->i_flags = le32_to_cpu(raw_inode->i_flags); +diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c +index 9de78f08989e..0f84b257932c 100644 +--- a/fs/nilfs2/namei.c ++++ b/fs/nilfs2/namei.c +@@ -51,9 +51,11 @@ static inline int nilfs_add_nondir(struct dentry *dentry, struct inode *inode) + int err = nilfs_add_link(dentry, inode); + if (!err) { + d_instantiate(dentry, inode); ++ unlock_new_inode(inode); + return 0; + } + inode_dec_link_count(inode); ++ unlock_new_inode(inode); + iput(inode); + return err; + } +@@ -182,6 +184,7 @@ out: + out_fail: + drop_nlink(inode); + nilfs_mark_inode_dirty(inode); ++ unlock_new_inode(inode); + iput(inode); + goto out; + } +@@ -201,11 +204,15 @@ static int nilfs_link(struct dentry *old_dentry, struct inode *dir, + inode_inc_link_count(inode); + ihold(inode); + +- err = nilfs_add_nondir(dentry, inode); +- if (!err) ++ err = nilfs_add_link(dentry, inode); ++ if (!err) { ++ d_instantiate(dentry, inode); + err = nilfs_transaction_commit(dir->i_sb); +- else ++ } else { ++ inode_dec_link_count(inode); ++ iput(inode); + nilfs_transaction_abort(dir->i_sb); ++ } + + return err; + } +@@ -243,6 +250,7 @@ static int nilfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) + + nilfs_mark_inode_dirty(inode); + d_instantiate(dentry, inode); ++ unlock_new_inode(inode); + out: + if (!err) + err = nilfs_transaction_commit(dir->i_sb); +@@ -255,6 +263,7 @@ out_fail: + drop_nlink(inode); + drop_nlink(inode); + nilfs_mark_inode_dirty(inode); ++ unlock_new_inode(inode); + iput(inode); + out_dir: + drop_nlink(dir); +diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c +index aeb44e879c51..bb6ee06118ca 100644 +--- a/fs/ocfs2/aops.c ++++ b/fs/ocfs2/aops.c +@@ -899,7 +899,7 @@ void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages) + } + } + +-static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) ++static void ocfs2_unlock_pages(struct ocfs2_write_ctxt *wc) + { + int i; + +@@ -920,7 +920,11 @@ static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) + page_cache_release(wc->w_target_page); + } + ocfs2_unlock_and_free_pages(wc->w_pages, wc->w_num_pages); ++} + ++static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) ++{ ++ ocfs2_unlock_pages(wc); + brelse(wc->w_di_bh); + kfree(wc); + } +@@ -2045,11 +2049,19 @@ out_write_size: + di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); + ocfs2_journal_dirty(handle, wc->w_di_bh); + ++ /* unlock pages before dealloc since it needs acquiring j_trans_barrier ++ * lock, or it will cause a deadlock since journal commit threads holds ++ * this lock and will ask for the page lock when flushing the data. ++ * put it here to preserve the unlock order. ++ */ ++ ocfs2_unlock_pages(wc); ++ + ocfs2_commit_trans(osb, handle); + + ocfs2_run_deallocs(osb, &wc->w_dealloc); + +- ocfs2_free_write_ctxt(wc); ++ brelse(wc->w_di_bh); ++ kfree(wc); + + return copied; + } +diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c +index feed025fe064..b2427623dd6c 100644 +--- a/fs/ocfs2/namei.c ++++ b/fs/ocfs2/namei.c +@@ -94,6 +94,14 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb, + struct inode *inode, + const char *symname); + ++static int ocfs2_double_lock(struct ocfs2_super *osb, ++ struct buffer_head **bh1, ++ struct inode *inode1, ++ struct buffer_head **bh2, ++ struct inode *inode2, ++ int rename); ++ ++static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2); + /* An orphan dir name is an 8 byte value, printed as a hex string */ + #define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64))) + +@@ -656,8 +664,10 @@ static int ocfs2_link(struct dentry *old_dentry, + { + handle_t *handle; + struct inode *inode = old_dentry->d_inode; ++ struct inode *old_dir = old_dentry->d_parent->d_inode; + int err; + struct buffer_head *fe_bh = NULL; ++ struct buffer_head *old_dir_bh = NULL; + struct buffer_head *parent_fe_bh = NULL; + struct ocfs2_dinode *fe = NULL; + struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); +@@ -674,19 +684,33 @@ static int ocfs2_link(struct dentry *old_dentry, + + dquot_initialize(dir); + +- err = ocfs2_inode_lock_nested(dir, &parent_fe_bh, 1, OI_LS_PARENT); ++ err = ocfs2_double_lock(osb, &old_dir_bh, old_dir, ++ &parent_fe_bh, dir, 0); + if (err < 0) { + if (err != -ENOENT) + mlog_errno(err); + return err; + } + ++ /* make sure both dirs have bhs ++ * get an extra ref on old_dir_bh if old==new */ ++ if (!parent_fe_bh) { ++ if (old_dir_bh) { ++ parent_fe_bh = old_dir_bh; ++ get_bh(parent_fe_bh); ++ } else { ++ mlog(ML_ERROR, "%s: no old_dir_bh!\n", osb->uuid_str); ++ err = -EIO; ++ goto out; ++ } ++ } ++ + if (!dir->i_nlink) { + err = -ENOENT; + goto out; + } + +- err = ocfs2_lookup_ino_from_name(dir, old_dentry->d_name.name, ++ err = ocfs2_lookup_ino_from_name(old_dir, old_dentry->d_name.name, + old_dentry->d_name.len, &old_de_ino); + if (err) { + err = -ENOENT; +@@ -779,10 +803,11 @@ out_unlock_inode: + ocfs2_inode_unlock(inode, 1); + + out: +- ocfs2_inode_unlock(dir, 1); ++ ocfs2_double_unlock(old_dir, dir); + + brelse(fe_bh); + brelse(parent_fe_bh); ++ brelse(old_dir_bh); + + ocfs2_free_dir_lookup_result(&lookup); + +@@ -991,14 +1016,15 @@ leave: + } + + /* +- * The only place this should be used is rename! ++ * The only place this should be used is rename and link! + * if they have the same id, then the 1st one is the only one locked. + */ + static int ocfs2_double_lock(struct ocfs2_super *osb, + struct buffer_head **bh1, + struct inode *inode1, + struct buffer_head **bh2, +- struct inode *inode2) ++ struct inode *inode2, ++ int rename) + { + int status; + struct ocfs2_inode_info *oi1 = OCFS2_I(inode1); +@@ -1028,7 +1054,7 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, + } + /* lock id2 */ + status = ocfs2_inode_lock_nested(inode2, bh2, 1, +- OI_LS_RENAME1); ++ rename == 1 ? OI_LS_RENAME1 : OI_LS_PARENT); + if (status < 0) { + if (status != -ENOENT) + mlog_errno(status); +@@ -1037,7 +1063,8 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, + } + + /* lock id1 */ +- status = ocfs2_inode_lock_nested(inode1, bh1, 1, OI_LS_RENAME2); ++ status = ocfs2_inode_lock_nested(inode1, bh1, 1, ++ rename == 1 ? OI_LS_RENAME2 : OI_LS_PARENT); + if (status < 0) { + /* + * An error return must mean that no cluster locks +@@ -1137,7 +1164,7 @@ static int ocfs2_rename(struct inode *old_dir, + + /* if old and new are the same, this'll just do one lock. */ + status = ocfs2_double_lock(osb, &old_dir_bh, old_dir, +- &new_dir_bh, new_dir); ++ &new_dir_bh, new_dir, 1); + if (status < 0) { + mlog_errno(status); + goto bail; +diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c +index fa8cef2cca3a..e7d95f959333 100644 +--- a/fs/pstore/ram.c ++++ b/fs/pstore/ram.c +@@ -61,6 +61,11 @@ module_param(mem_size, ulong, 0400); + MODULE_PARM_DESC(mem_size, + "size of reserved RAM used to store oops/panic logs"); + ++static unsigned int mem_type; ++module_param(mem_type, uint, 0600); ++MODULE_PARM_DESC(mem_type, ++ "set to 1 to try to use unbuffered memory (default 0)"); ++ + static int dump_oops = 1; + module_param(dump_oops, int, 0600); + MODULE_PARM_DESC(dump_oops, +@@ -79,6 +84,7 @@ struct ramoops_context { + struct persistent_ram_zone *fprz; + phys_addr_t phys_addr; + unsigned long size; ++ unsigned int memtype; + size_t record_size; + size_t console_size; + size_t ftrace_size; +@@ -353,7 +359,8 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt, + size_t sz = cxt->record_size; + + cxt->przs[i] = persistent_ram_new(*paddr, sz, 0, +- &cxt->ecc_info); ++ &cxt->ecc_info, ++ cxt->memtype); + if (IS_ERR(cxt->przs[i])) { + err = PTR_ERR(cxt->przs[i]); + dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", +@@ -383,7 +390,7 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt, + return -ENOMEM; + } + +- *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info); ++ *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info, cxt->memtype); + if (IS_ERR(*prz)) { + int err = PTR_ERR(*prz); + +@@ -431,6 +438,7 @@ static int ramoops_probe(struct platform_device *pdev) + cxt->dump_read_cnt = 0; + cxt->size = pdata->mem_size; + cxt->phys_addr = pdata->mem_address; ++ cxt->memtype = pdata->mem_type; + cxt->record_size = pdata->record_size; + cxt->console_size = pdata->console_size; + cxt->ftrace_size = pdata->ftrace_size; +@@ -561,6 +569,7 @@ static void ramoops_register_dummy(void) + + dummy_data->mem_size = mem_size; + dummy_data->mem_address = mem_address; ++ dummy_data->mem_type = 0; + dummy_data->record_size = record_size; + dummy_data->console_size = ramoops_console_size; + dummy_data->ftrace_size = ramoops_ftrace_size; +diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c +index de272d426763..bda61a759b68 100644 +--- a/fs/pstore/ram_core.c ++++ b/fs/pstore/ram_core.c +@@ -380,7 +380,8 @@ void persistent_ram_zap(struct persistent_ram_zone *prz) + persistent_ram_update_header_ecc(prz); + } + +-static void *persistent_ram_vmap(phys_addr_t start, size_t size) ++static void *persistent_ram_vmap(phys_addr_t start, size_t size, ++ unsigned int memtype) + { + struct page **pages; + phys_addr_t page_start; +@@ -392,7 +393,10 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size) + page_start = start - offset_in_page(start); + page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE); + +- prot = pgprot_noncached(PAGE_KERNEL); ++ if (memtype) ++ prot = pgprot_noncached(PAGE_KERNEL); ++ else ++ prot = pgprot_writecombine(PAGE_KERNEL); + + pages = kmalloc(sizeof(struct page *) * page_count, GFP_KERNEL); + if (!pages) { +@@ -411,8 +415,11 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size) + return vaddr; + } + +-static void *persistent_ram_iomap(phys_addr_t start, size_t size) ++static void *persistent_ram_iomap(phys_addr_t start, size_t size, ++ unsigned int memtype) + { ++ void *va; ++ + if (!request_mem_region(start, size, "persistent_ram")) { + pr_err("request mem region (0x%llx@0x%llx) failed\n", + (unsigned long long)size, (unsigned long long)start); +@@ -422,19 +429,24 @@ static void *persistent_ram_iomap(phys_addr_t start, size_t size) + buffer_start_add = buffer_start_add_locked; + buffer_size_add = buffer_size_add_locked; + +- return ioremap(start, size); ++ if (memtype) ++ va = ioremap(start, size); ++ else ++ va = ioremap_wc(start, size); ++ ++ return va; + } + + static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size, +- struct persistent_ram_zone *prz) ++ struct persistent_ram_zone *prz, int memtype) + { + prz->paddr = start; + prz->size = size; + + if (pfn_valid(start >> PAGE_SHIFT)) +- prz->vaddr = persistent_ram_vmap(start, size); ++ prz->vaddr = persistent_ram_vmap(start, size, memtype); + else +- prz->vaddr = persistent_ram_iomap(start, size); ++ prz->vaddr = persistent_ram_iomap(start, size, memtype); + + if (!prz->vaddr) { + pr_err("%s: Failed to map 0x%llx pages at 0x%llx\n", __func__, +@@ -502,7 +514,8 @@ void persistent_ram_free(struct persistent_ram_zone *prz) + } + + struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, +- u32 sig, struct persistent_ram_ecc_info *ecc_info) ++ u32 sig, struct persistent_ram_ecc_info *ecc_info, ++ unsigned int memtype) + { + struct persistent_ram_zone *prz; + int ret = -ENOMEM; +@@ -513,7 +526,7 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, + goto err; + } + +- ret = persistent_ram_buffer_map(start, size, prz); ++ ret = persistent_ram_buffer_map(start, size, prz, memtype); + if (ret) + goto err; + +diff --git a/include/linux/mm.h b/include/linux/mm.h +index d5039daf1e1c..46b8ab56b9db 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1866,7 +1866,7 @@ extern int expand_downwards(struct vm_area_struct *vma, + #if VM_GROWSUP + extern int expand_upwards(struct vm_area_struct *vma, unsigned long address); + #else +- #define expand_upwards(vma, address) do { } while (0) ++ #define expand_upwards(vma, address) (0) + #endif + + /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ +diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h +index 9974975d40db..4af3fdc85b01 100644 +--- a/include/linux/pstore_ram.h ++++ b/include/linux/pstore_ram.h +@@ -53,7 +53,8 @@ struct persistent_ram_zone { + }; + + struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, +- u32 sig, struct persistent_ram_ecc_info *ecc_info); ++ u32 sig, struct persistent_ram_ecc_info *ecc_info, ++ unsigned int memtype); + void persistent_ram_free(struct persistent_ram_zone *prz); + void persistent_ram_zap(struct persistent_ram_zone *prz); + +@@ -76,6 +77,7 @@ ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz, + struct ramoops_platform_data { + unsigned long mem_size; + unsigned long mem_address; ++ unsigned int mem_type; + unsigned long record_size; + unsigned long console_size; + unsigned long ftrace_size; +diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h +index 67e1bbf83695..dc7bb01f580f 100644 +--- a/include/trace/events/sched.h ++++ b/include/trace/events/sched.h +@@ -100,7 +100,7 @@ static inline long __trace_sched_switch_state(struct task_struct *p) + /* + * For all intents and purposes a preempted task is a running task. + */ +- if (task_preempt_count(p) & PREEMPT_ACTIVE) ++ if (preempt_count() & PREEMPT_ACTIVE) + state = TASK_RUNNING | TASK_STATE_MAX; + #endif + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 4bbb27adf23d..69cffb46db17 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -7240,11 +7240,11 @@ SYSCALL_DEFINE5(perf_event_open, + + if (move_group) { + synchronize_rcu(); +- perf_install_in_context(ctx, group_leader, event->cpu); ++ perf_install_in_context(ctx, group_leader, group_leader->cpu); + get_ctx(ctx); + list_for_each_entry(sibling, &group_leader->sibling_list, + group_entry) { +- perf_install_in_context(ctx, sibling, event->cpu); ++ perf_install_in_context(ctx, sibling, sibling->cpu); + get_ctx(ctx); + } + } +diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c +index 37dac98c0749..8d3c5ddfdfdd 100644 +--- a/kernel/sched/deadline.c ++++ b/kernel/sched/deadline.c +@@ -550,24 +550,7 @@ void init_dl_task_timer(struct sched_dl_entity *dl_se) + static + int dl_runtime_exceeded(struct rq *rq, struct sched_dl_entity *dl_se) + { +- int dmiss = dl_time_before(dl_se->deadline, rq_clock(rq)); +- int rorun = dl_se->runtime <= 0; +- +- if (!rorun && !dmiss) +- return 0; +- +- /* +- * If we are beyond our current deadline and we are still +- * executing, then we have already used some of the runtime of +- * the next instance. Thus, if we do not account that, we are +- * stealing bandwidth from the system at each deadline miss! +- */ +- if (dmiss) { +- dl_se->runtime = rorun ? dl_se->runtime : 0; +- dl_se->runtime -= rq_clock(rq) - dl_se->deadline; +- } +- +- return 1; ++ return (dl_se->runtime <= 0); + } + + extern bool sched_rt_bandwidth_account(struct rt_rq *rt_rq); +@@ -806,10 +789,10 @@ enqueue_dl_entity(struct sched_dl_entity *dl_se, + * parameters of the task might need updating. Otherwise, + * we want a replenishment of its runtime. + */ +- if (!dl_se->dl_new && flags & ENQUEUE_REPLENISH) +- replenish_dl_entity(dl_se, pi_se); +- else ++ if (dl_se->dl_new || flags & ENQUEUE_WAKEUP) + update_dl_entity(dl_se, pi_se); ++ else if (flags & ENQUEUE_REPLENISH) ++ replenish_dl_entity(dl_se, pi_se); + + __enqueue_dl_entity(dl_se); + } +diff --git a/mm/memory.c b/mm/memory.c +index 48d7365ba4e4..924429e5ef4d 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -3204,7 +3204,7 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo + if (prev && prev->vm_end == address) + return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM; + +- expand_downwards(vma, address - PAGE_SIZE); ++ return expand_downwards(vma, address - PAGE_SIZE); + } + if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) { + struct vm_area_struct *next = vma->vm_next; +@@ -3213,7 +3213,7 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo + if (next && next->vm_start == address + PAGE_SIZE) + return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM; + +- expand_upwards(vma, address + PAGE_SIZE); ++ return expand_upwards(vma, address + PAGE_SIZE); + } + return 0; + } +diff --git a/mm/mmap.c b/mm/mmap.c +index b91ac800d7b7..085bcd890ad2 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -2058,14 +2058,17 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns + { + struct mm_struct *mm = vma->vm_mm; + struct rlimit *rlim = current->signal->rlim; +- unsigned long new_start; ++ unsigned long new_start, actual_size; + + /* address space limit tests */ + if (!may_expand_vm(mm, grow)) + return -ENOMEM; + + /* Stack limit test */ +- if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur)) ++ actual_size = size; ++ if (size && (vma->vm_flags & (VM_GROWSUP | VM_GROWSDOWN))) ++ actual_size -= PAGE_SIZE; ++ if (actual_size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur)) + return -ENOMEM; + + /* mlock limit tests */ +diff --git a/mm/vmscan.c b/mm/vmscan.c +index deb139e6b8ed..be6a689a71a6 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -2860,18 +2860,20 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining, + return false; + + /* +- * There is a potential race between when kswapd checks its watermarks +- * and a process gets throttled. There is also a potential race if +- * processes get throttled, kswapd wakes, a large process exits therby +- * balancing the zones that causes kswapd to miss a wakeup. If kswapd +- * is going to sleep, no process should be sleeping on pfmemalloc_wait +- * so wake them now if necessary. If necessary, processes will wake +- * kswapd and get throttled again ++ * The throttled processes are normally woken up in balance_pgdat() as ++ * soon as pfmemalloc_watermark_ok() is true. But there is a potential ++ * race between when kswapd checks the watermarks and a process gets ++ * throttled. There is also a potential race if processes get ++ * throttled, kswapd wakes, a large process exits thereby balancing the ++ * zones, which causes kswapd to exit balance_pgdat() before reaching ++ * the wake up checks. If kswapd is going to sleep, no process should ++ * be sleeping on pfmemalloc_wait, so wake them now if necessary. If ++ * the wake up is premature, processes will wake kswapd and get ++ * throttled again. The difference from wake ups in balance_pgdat() is ++ * that here we are under prepare_to_wait(). + */ +- if (waitqueue_active(&pgdat->pfmemalloc_wait)) { +- wake_up(&pgdat->pfmemalloc_wait); +- return false; +- } ++ if (waitqueue_active(&pgdat->pfmemalloc_wait)) ++ wake_up_all(&pgdat->pfmemalloc_wait); + + return pgdat_balanced(pgdat, order, classzone_idx); + } +diff --git a/scripts/kernel-doc b/scripts/kernel-doc +index da058da413e7..2438cc351952 100755 +--- a/scripts/kernel-doc ++++ b/scripts/kernel-doc +@@ -1753,7 +1753,7 @@ sub dump_struct($$) { + # strip kmemcheck_bitfield_{begin,end}.*; + $members =~ s/kmemcheck_bitfield_.*?;//gos; + # strip attributes +- $members =~ s/__aligned\s*\(.+\)//gos; ++ $members =~ s/__aligned\s*\([^;]*\)//gos; + + create_parameterlist($members, ';', $file); + check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested); +diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c +index dafcf82139e2..f6e5c4ed03ed 100644 +--- a/sound/pci/hda/hda_codec.c ++++ b/sound/pci/hda/hda_codec.c +@@ -338,8 +338,10 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, + unsigned int parm; + + parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT); +- if (parm == -1) ++ if (parm == -1) { ++ *start_id = 0; + return 0; ++ } + *start_id = (parm >> 16) & 0x7fff; + return (int)(parm & 0x7fff); + } +diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c +index 15270a2e71cc..12f28d7e0fdc 100644 +--- a/sound/pci/hda/patch_sigmatel.c ++++ b/sound/pci/hda/patch_sigmatel.c +@@ -593,9 +593,9 @@ static void stac_store_hints(struct hda_codec *codec) + spec->gpio_mask; + } + if (get_int_hint(codec, "gpio_dir", &spec->gpio_dir)) +- spec->gpio_mask &= spec->gpio_mask; +- if (get_int_hint(codec, "gpio_data", &spec->gpio_data)) + spec->gpio_dir &= spec->gpio_mask; ++ if (get_int_hint(codec, "gpio_data", &spec->gpio_data)) ++ spec->gpio_data &= spec->gpio_mask; + if (get_int_hint(codec, "eapd_mask", &spec->eapd_mask)) + spec->eapd_mask &= spec->gpio_mask; + if (get_int_hint(codec, "gpio_mute", &spec->gpio_mute)) +diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c +index ddfb0fddd030..9dd260f9dd06 100644 +--- a/sound/soc/codecs/max98090.c ++++ b/sound/soc/codecs/max98090.c +@@ -1378,8 +1378,8 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = { + {"STENL Mux", "Sidetone Left", "DMICL"}, + {"STENR Mux", "Sidetone Right", "ADCR"}, + {"STENR Mux", "Sidetone Right", "DMICR"}, +- {"DACL", "NULL", "STENL Mux"}, +- {"DACR", "NULL", "STENL Mux"}, ++ {"DACL", NULL, "STENL Mux"}, ++ {"DACR", NULL, "STENL Mux"}, + + {"AIFINL", NULL, "SHDN"}, + {"AIFINR", NULL, "SHDN"}, +diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c +index 4068f2491232..bb3878c9625f 100644 +--- a/sound/soc/codecs/sigmadsp.c ++++ b/sound/soc/codecs/sigmadsp.c +@@ -176,6 +176,13 @@ static int _process_sigma_firmware(struct device *dev, + goto done; + } + ++ if (ssfw_head->version != 1) { ++ dev_err(dev, ++ "Failed to load firmware: Invalid version %d. Supported firmware versions: 1\n", ++ ssfw_head->version); ++ goto done; ++ } ++ + crc = crc32(0, fw->data + sizeof(*ssfw_head), + fw->size - sizeof(*ssfw_head)); + pr_debug("%s: crc=%x\n", __func__, crc); +diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c +index 25c31f1655f6..2f6357578616 100644 +--- a/sound/soc/dwc/designware_i2s.c ++++ b/sound/soc/dwc/designware_i2s.c +@@ -263,6 +263,19 @@ static void dw_i2s_shutdown(struct snd_pcm_substream *substream, + snd_soc_dai_set_dma_data(dai, substream, NULL); + } + ++static int dw_i2s_prepare(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ i2s_write_reg(dev->i2s_base, TXFFR, 1); ++ else ++ i2s_write_reg(dev->i2s_base, RXFFR, 1); ++ ++ return 0; ++} ++ + static int dw_i2s_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) + { +@@ -294,6 +307,7 @@ static struct snd_soc_dai_ops dw_i2s_dai_ops = { + .startup = dw_i2s_startup, + .shutdown = dw_i2s_shutdown, + .hw_params = dw_i2s_hw_params, ++ .prepare = dw_i2s_prepare, + .trigger = dw_i2s_trigger, + }; + +diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c +index d1d72ff50347..621bc9ebb55e 100644 +--- a/sound/usb/mixer_maps.c ++++ b/sound/usb/mixer_maps.c +@@ -328,8 +328,11 @@ static struct usbmix_name_map gamecom780_map[] = { + {} + }; + +-static const struct usbmix_name_map kef_x300a_map[] = { +- { 10, NULL }, /* firmware locks up (?) when we try to access this FU */ ++/* some (all?) SCMS USB3318 devices are affected by a firmware lock up ++ * when anything attempts to access FU 10 (control) ++ */ ++static const struct usbmix_name_map scms_usb3318_map[] = { ++ { 10, NULL }, + { 0 } + }; + +@@ -425,8 +428,14 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { + .map = ebox44_map, + }, + { ++ /* KEF X300A */ + .id = USB_ID(0x27ac, 0x1000), +- .map = kef_x300a_map, ++ .map = scms_usb3318_map, ++ }, ++ { ++ /* Arcam rPAC */ ++ .id = USB_ID(0x25c4, 0x0003), ++ .map = scms_usb3318_map, + }, + { 0 } /* terminator */ + }; +diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h +index a59743fa3ef7..0001c9aa8b71 100644 +--- a/tools/perf/util/hist.h ++++ b/tools/perf/util/hist.h +@@ -36,6 +36,7 @@ struct events_stats { + u32 nr_invalid_chains; + u32 nr_unknown_id; + u32 nr_unprocessable_samples; ++ u32 nr_unordered_events; + }; + + enum hist_column { +diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c +index 5da6ce74c676..c1f20e91f968 100644 +--- a/tools/perf/util/session.c ++++ b/tools/perf/util/session.c +@@ -638,8 +638,7 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event, + return -ETIME; + + if (timestamp < s->ordered_samples.last_flush) { +- printf("Warning: Timestamp below last timeslice flush\n"); +- return -EINVAL; ++ s->stats.nr_unordered_events++; + } + + if (!list_empty(sc)) { +@@ -1135,6 +1134,8 @@ static void perf_session__warn_about_errors(const struct perf_session *session, + "Do you have a KVM guest running and not using 'perf kvm'?\n", + session->stats.nr_unprocessable_samples); + } ++ if (session->stats.nr_unordered_events != 0) ++ ui__warning("%u out of order events recorded.\n", session->stats.nr_unordered_events); + } + + volatile int session_done; diff --git a/patch/kernel/cubox-default/patch-3.14.29-30.patch b/patch/kernel/cubox-default/patch-3.14.29-30.patch new file mode 100644 index 000000000..c5db3c797 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.29-30.patch @@ -0,0 +1,4387 @@ +diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index 7116fda7077f..5d91ba1606bb 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -1172,6 +1172,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + i8042.notimeout [HW] Ignore timeout condition signalled by controller + i8042.reset [HW] Reset the controller during init and cleanup + i8042.unlock [HW] Unlock (ignore) the keylock ++ i8042.kbdreset [HW] Reset device connected to KBD port + + i810= [HW,DRM] + +diff --git a/Makefile b/Makefile +index 7aff64ee4fb6..5b94752a85e3 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 29 ++SUBLEVEL = 30 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arc/boot/dts/nsimosci.dts b/arch/arc/boot/dts/nsimosci.dts +index 398064cef746..4c169d825415 100644 +--- a/arch/arc/boot/dts/nsimosci.dts ++++ b/arch/arc/boot/dts/nsimosci.dts +@@ -20,7 +20,7 @@ + /* this is for console on PGU */ + /* bootargs = "console=tty0 consoleblank=0"; */ + /* this is for console on serial */ +- bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug"; ++ bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug"; + }; + + aliases { +@@ -46,9 +46,9 @@ + #interrupt-cells = <1>; + }; + +- uart0: serial@c0000000 { ++ uart0: serial@f0000000 { + compatible = "ns8250"; +- reg = <0xc0000000 0x2000>; ++ reg = <0xf0000000 0x2000>; + interrupts = <11>; + clock-frequency = <3686400>; + baud = <115200>; +@@ -57,21 +57,21 @@ + no-loopback-test = <1>; + }; + +- pgu0: pgu@c9000000 { ++ pgu0: pgu@f9000000 { + compatible = "snps,arcpgufb"; +- reg = <0xc9000000 0x400>; ++ reg = <0xf9000000 0x400>; + }; + +- ps2: ps2@c9001000 { ++ ps2: ps2@f9001000 { + compatible = "snps,arc_ps2"; +- reg = <0xc9000400 0x14>; ++ reg = <0xf9000400 0x14>; + interrupts = <13>; + interrupt-names = "arc_ps2_irq"; + }; + +- eth0: ethernet@c0003000 { ++ eth0: ethernet@f0003000 { + compatible = "snps,oscilan"; +- reg = <0xc0003000 0x44>; ++ reg = <0xf0003000 0x44>; + interrupts = <7>, <8>; + interrupt-names = "rx", "tx"; + }; +diff --git a/arch/arc/include/asm/linkage.h b/arch/arc/include/asm/linkage.h +index 66ee5527aefc..5faad17118b4 100644 +--- a/arch/arc/include/asm/linkage.h ++++ b/arch/arc/include/asm/linkage.h +@@ -13,20 +13,6 @@ + + #define ASM_NL ` /* use '`' to mark new line in macro */ + +-/* Can't use the ENTRY macro in linux/linkage.h +- * gas considers ';' as comment vs. newline +- */ +-.macro ARC_ENTRY name +- .global \name +- .align 4 +- \name: +-.endm +- +-.macro ARC_EXIT name +-#define ASM_PREV_SYM_ADDR(name) .-##name +- .size \ name, ASM_PREV_SYM_ADDR(\name) +-.endm +- + /* annotation for data we want in DCCM - if enabled in .config */ + .macro ARCFP_DATA nm + #ifdef CONFIG_ARC_HAS_DCCM +diff --git a/arch/arc/kernel/ctx_sw_asm.S b/arch/arc/kernel/ctx_sw_asm.S +index 65690e7fcc8c..2ff0347a2fd7 100644 +--- a/arch/arc/kernel/ctx_sw_asm.S ++++ b/arch/arc/kernel/ctx_sw_asm.S +@@ -62,4 +62,4 @@ __switch_to: + ld.ab blink, [sp, 4] + j [blink] + +-ARC_EXIT __switch_to ++END(__switch_to) +diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S +index 6e8f83a32522..29b82adbf0b4 100644 +--- a/arch/arc/kernel/entry.S ++++ b/arch/arc/kernel/entry.S +@@ -141,7 +141,7 @@ VECTOR EV_Extension ; 0x130, Extn Intruction Excp (0x26) + VECTOR reserved ; Reserved Exceptions + .endr + +-#include /* ARC_{EXTRY,EXIT} */ ++#include /* {EXTRY,EXIT} */ + #include /* SAVE_ALL_{INT1,INT2,SYS...} */ + #include + #include +@@ -184,7 +184,7 @@ reserved: ; processor restart + ; --------------------------------------------- + ; Level 2 ISR: Can interrupt a Level 1 ISR + ; --------------------------------------------- +-ARC_ENTRY handle_interrupt_level2 ++ENTRY(handle_interrupt_level2) + + ; TODO-vineetg for SMP this wont work + ; free up r9 as scratchpad +@@ -225,14 +225,14 @@ ARC_ENTRY handle_interrupt_level2 + + b ret_from_exception + +-ARC_EXIT handle_interrupt_level2 ++END(handle_interrupt_level2) + + #endif + + ; --------------------------------------------- + ; Level 1 ISR + ; --------------------------------------------- +-ARC_ENTRY handle_interrupt_level1 ++ENTRY(handle_interrupt_level1) + + /* free up r9 as scratchpad */ + #ifdef CONFIG_SMP +@@ -265,7 +265,7 @@ ARC_ENTRY handle_interrupt_level1 + sr r8, [AUX_IRQ_LV12] ; clear bit in Sticky Status Reg + + b ret_from_exception +-ARC_EXIT handle_interrupt_level1 ++END(handle_interrupt_level1) + + ;################### Non TLB Exception Handling ############################# + +@@ -273,7 +273,7 @@ ARC_EXIT handle_interrupt_level1 + ; Instruction Error Exception Handler + ; --------------------------------------------- + +-ARC_ENTRY instr_service ++ENTRY(instr_service) + + EXCEPTION_PROLOGUE + +@@ -284,13 +284,13 @@ ARC_ENTRY instr_service + + bl do_insterror_or_kprobe + b ret_from_exception +-ARC_EXIT instr_service ++END(instr_service) + + ; --------------------------------------------- + ; Memory Error Exception Handler + ; --------------------------------------------- + +-ARC_ENTRY mem_service ++ENTRY(mem_service) + + EXCEPTION_PROLOGUE + +@@ -301,13 +301,13 @@ ARC_ENTRY mem_service + + bl do_memory_error + b ret_from_exception +-ARC_EXIT mem_service ++END(mem_service) + + ; --------------------------------------------- + ; Machine Check Exception Handler + ; --------------------------------------------- + +-ARC_ENTRY EV_MachineCheck ++ENTRY(EV_MachineCheck) + + EXCEPTION_PROLOGUE + +@@ -331,13 +331,13 @@ ARC_ENTRY EV_MachineCheck + + j do_machine_check_fault + +-ARC_EXIT EV_MachineCheck ++END(EV_MachineCheck) + + ; --------------------------------------------- + ; Protection Violation Exception Handler + ; --------------------------------------------- + +-ARC_ENTRY EV_TLBProtV ++ENTRY(EV_TLBProtV) + + EXCEPTION_PROLOGUE + +@@ -385,12 +385,12 @@ ARC_ENTRY EV_TLBProtV + + b ret_from_exception + +-ARC_EXIT EV_TLBProtV ++END(EV_TLBProtV) + + ; --------------------------------------------- + ; Privilege Violation Exception Handler + ; --------------------------------------------- +-ARC_ENTRY EV_PrivilegeV ++ENTRY(EV_PrivilegeV) + + EXCEPTION_PROLOGUE + +@@ -401,12 +401,12 @@ ARC_ENTRY EV_PrivilegeV + + bl do_privilege_fault + b ret_from_exception +-ARC_EXIT EV_PrivilegeV ++END(EV_PrivilegeV) + + ; --------------------------------------------- + ; Extension Instruction Exception Handler + ; --------------------------------------------- +-ARC_ENTRY EV_Extension ++ENTRY(EV_Extension) + + EXCEPTION_PROLOGUE + +@@ -417,7 +417,7 @@ ARC_ENTRY EV_Extension + + bl do_extension_fault + b ret_from_exception +-ARC_EXIT EV_Extension ++END(EV_Extension) + + ;######################### System Call Tracing ######################### + +@@ -504,7 +504,7 @@ trap_with_param: + ; (2) Break Points + ;------------------------------------------------------------------ + +-ARC_ENTRY EV_Trap ++ENTRY(EV_Trap) + + EXCEPTION_PROLOGUE + +@@ -534,9 +534,9 @@ ARC_ENTRY EV_Trap + jl [r9] ; Entry into Sys Call Handler + + ; fall through to ret_from_system_call +-ARC_EXIT EV_Trap ++END(EV_Trap) + +-ARC_ENTRY ret_from_system_call ++ENTRY(ret_from_system_call) + + st r0, [sp, PT_r0] ; sys call return value in pt_regs + +@@ -546,7 +546,7 @@ ARC_ENTRY ret_from_system_call + ; + ; If ret to user mode do we need to handle signals, schedule() et al. + +-ARC_ENTRY ret_from_exception ++ENTRY(ret_from_exception) + + ; Pre-{IRQ,Trap,Exception} K/U mode from pt_regs->status32 + ld r8, [sp, PT_status32] ; returning to User/Kernel Mode +@@ -728,9 +728,9 @@ not_level1_interrupt: + debug_marker_syscall: + rtie + +-ARC_EXIT ret_from_exception ++END(ret_from_exception) + +-ARC_ENTRY ret_from_fork ++ENTRY(ret_from_fork) + ; when the forked child comes here from the __switch_to function + ; r0 has the last task pointer. + ; put last task in scheduler queue +@@ -747,11 +747,11 @@ ARC_ENTRY ret_from_fork + ; special case of kernel_thread entry point returning back due to + ; kernel_execve() - pretend return from syscall to ret to userland + b ret_from_exception +-ARC_EXIT ret_from_fork ++END(ret_from_fork) + + ;################### Special Sys Call Wrappers ########################## + +-ARC_ENTRY sys_clone_wrapper ++ENTRY(sys_clone_wrapper) + SAVE_CALLEE_SAVED_USER + bl @sys_clone + DISCARD_CALLEE_SAVED_USER +@@ -761,7 +761,7 @@ ARC_ENTRY sys_clone_wrapper + bnz tracesys_exit + + b ret_from_system_call +-ARC_EXIT sys_clone_wrapper ++END(sys_clone_wrapper) + + #ifdef CONFIG_ARC_DW2_UNWIND + ; Workaround for bug 94179 (STAR ): +diff --git a/arch/arc/lib/memcmp.S b/arch/arc/lib/memcmp.S +index bc813d55b6c3..978bf8314dfb 100644 +--- a/arch/arc/lib/memcmp.S ++++ b/arch/arc/lib/memcmp.S +@@ -6,7 +6,7 @@ + * published by the Free Software Foundation. + */ + +-#include ++#include + + #ifdef __LITTLE_ENDIAN__ + #define WORD2 r2 +@@ -16,7 +16,7 @@ + #define SHIFT r2 + #endif + +-ARC_ENTRY memcmp ++ENTRY(memcmp) + or r12,r0,r1 + asl_s r12,r12,30 + sub r3,r2,1 +@@ -121,4 +121,4 @@ ARC_ENTRY memcmp + .Lnil: + j_s.d [blink] + mov r0,0 +-ARC_EXIT memcmp ++END(memcmp) +diff --git a/arch/arc/lib/memcpy-700.S b/arch/arc/lib/memcpy-700.S +index b64cc10ac918..3222573e50de 100644 +--- a/arch/arc/lib/memcpy-700.S ++++ b/arch/arc/lib/memcpy-700.S +@@ -6,9 +6,9 @@ + * published by the Free Software Foundation. + */ + +-#include ++#include + +-ARC_ENTRY memcpy ++ENTRY(memcpy) + or r3,r0,r1 + asl_s r3,r3,30 + mov_s r5,r0 +@@ -63,4 +63,4 @@ ARC_ENTRY memcpy + .Lendbloop: + j_s.d [blink] + stb r12,[r5,0] +-ARC_EXIT memcpy ++END(memcpy) +diff --git a/arch/arc/lib/memset.S b/arch/arc/lib/memset.S +index 9b2d88d2e141..d36bd43fc98d 100644 +--- a/arch/arc/lib/memset.S ++++ b/arch/arc/lib/memset.S +@@ -6,11 +6,11 @@ + * published by the Free Software Foundation. + */ + +-#include ++#include + + #define SMALL 7 /* Must be at least 6 to deal with alignment/loop issues. */ + +-ARC_ENTRY memset ++ENTRY(memset) + mov_s r4,r0 + or r12,r0,r2 + bmsk.f r12,r12,1 +@@ -46,14 +46,14 @@ ARC_ENTRY memset + stb.ab r1,[r4,1] + .Ltiny_end: + j_s [blink] +-ARC_EXIT memset ++END(memset) + + ; memzero: @r0 = mem, @r1 = size_t + ; memset: @r0 = mem, @r1 = char, @r2 = size_t + +-ARC_ENTRY memzero ++ENTRY(memzero) + ; adjust bzero args to memset args + mov r2, r1 + mov r1, 0 + b memset ;tail call so need to tinker with blink +-ARC_EXIT memzero ++END(memzero) +diff --git a/arch/arc/lib/strchr-700.S b/arch/arc/lib/strchr-700.S +index 9c548c7cf001..b725d5862107 100644 +--- a/arch/arc/lib/strchr-700.S ++++ b/arch/arc/lib/strchr-700.S +@@ -11,9 +11,9 @@ + presence of the norm instruction makes it easier to operate on whole + words branch-free. */ + +-#include ++#include + +-ARC_ENTRY strchr ++ENTRY(strchr) + extb_s r1,r1 + asl r5,r1,8 + bmsk r2,r0,1 +@@ -130,4 +130,4 @@ ARC_ENTRY strchr + j_s.d [blink] + mov.mi r0,0 + #endif /* ENDIAN */ +-ARC_EXIT strchr ++END(strchr) +diff --git a/arch/arc/lib/strcmp.S b/arch/arc/lib/strcmp.S +index 5dc802b45cf3..3544600fefe6 100644 +--- a/arch/arc/lib/strcmp.S ++++ b/arch/arc/lib/strcmp.S +@@ -13,9 +13,9 @@ + source 1; however, that would increase the overhead for loop setup / finish, + and strcmp might often terminate early. */ + +-#include ++#include + +-ARC_ENTRY strcmp ++ENTRY(strcmp) + or r2,r0,r1 + bmsk_s r2,r2,1 + brne r2,0,.Lcharloop +@@ -93,4 +93,4 @@ ARC_ENTRY strcmp + .Lcmpend: + j_s.d [blink] + sub r0,r2,r3 +-ARC_EXIT strcmp ++END(strcmp) +diff --git a/arch/arc/lib/strcpy-700.S b/arch/arc/lib/strcpy-700.S +index b7ca4ae81d88..8422f38e1218 100644 +--- a/arch/arc/lib/strcpy-700.S ++++ b/arch/arc/lib/strcpy-700.S +@@ -16,9 +16,9 @@ + there, but the it is not likely to be taken often, and it + would also be likey to cost an unaligned mispredict at the next call. */ + +-#include ++#include + +-ARC_ENTRY strcpy ++ENTRY(strcpy) + or r2,r0,r1 + bmsk_s r2,r2,1 + brne.d r2,0,charloop +@@ -67,4 +67,4 @@ charloop: + brne.d r3,0,charloop + stb.ab r3,[r10,1] + j [blink] +-ARC_EXIT strcpy ++END(strcpy) +diff --git a/arch/arc/lib/strlen.S b/arch/arc/lib/strlen.S +index 39759e099696..53cfd5685a5f 100644 +--- a/arch/arc/lib/strlen.S ++++ b/arch/arc/lib/strlen.S +@@ -6,9 +6,9 @@ + * published by the Free Software Foundation. + */ + +-#include ++#include + +-ARC_ENTRY strlen ++ENTRY(strlen) + or r3,r0,7 + ld r2,[r3,-7] + ld.a r6,[r3,-3] +@@ -80,4 +80,4 @@ ARC_ENTRY strlen + .Learly_end: + b.d .Lend + sub_s.ne r1,r1,r1 +-ARC_EXIT strlen ++END(strlen) +diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S +index 3fcfdb38d242..79bfc81358c9 100644 +--- a/arch/arc/mm/tlbex.S ++++ b/arch/arc/mm/tlbex.S +@@ -260,7 +260,7 @@ ARCFP_CODE ;Fast Path Code, candidate for ICCM + ; I-TLB Miss Exception Handler + ;----------------------------------------------------------------------------- + +-ARC_ENTRY EV_TLBMissI ++ENTRY(EV_TLBMissI) + + TLBMISS_FREEUP_REGS + +@@ -293,13 +293,13 @@ ARC_ENTRY EV_TLBMissI + TLBMISS_RESTORE_REGS + rtie + +-ARC_EXIT EV_TLBMissI ++END(EV_TLBMissI) + + ;----------------------------------------------------------------------------- + ; D-TLB Miss Exception Handler + ;----------------------------------------------------------------------------- + +-ARC_ENTRY EV_TLBMissD ++ENTRY(EV_TLBMissD) + + TLBMISS_FREEUP_REGS + +@@ -381,6 +381,4 @@ do_slow_path_pf: + bl do_page_fault + b ret_from_exception + +-ARC_EXIT EV_TLBMissD +- +-ARC_ENTRY EV_TLBMissB ; Bogus entry to measure sz of DTLBMiss hdlr ++END(EV_TLBMissD) +diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi +index de1611966d8b..6a26e79f0ef4 100644 +--- a/arch/arm/boot/dts/imx25.dtsi ++++ b/arch/arm/boot/dts/imx25.dtsi +@@ -158,7 +158,7 @@ + #size-cells = <0>; + compatible = "fsl,imx25-cspi", "fsl,imx35-cspi"; + reg = <0x43fa4000 0x4000>; +- clocks = <&clks 62>, <&clks 62>; ++ clocks = <&clks 78>, <&clks 78>; + clock-names = "ipg", "per"; + interrupts = <14>; + status = "disabled"; +diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c +index 4d677f442539..01a5765a8b26 100644 +--- a/arch/arm/mach-imx/clk-imx6q.c ++++ b/arch/arm/mach-imx/clk-imx6q.c +@@ -161,8 +161,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) + post_div_table[1].div = 1; + post_div_table[2].div = 1; + video_div_table[1].div = 1; +- video_div_table[2].div = 1; +- }; ++ video_div_table[3].div = 1; ++ } + + /* type name parent_name base div_mask */ + clk[pll1_sys] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f); +diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c +index 74044aaf438b..73d80b8576c3 100644 +--- a/arch/arm/mach-omap2/timer.c ++++ b/arch/arm/mach-omap2/timer.c +@@ -513,11 +513,11 @@ static void __init realtime_counter_init(void) + rate = clk_get_rate(sys_clk); + /* Numerator/denumerator values refer TRM Realtime Counter section */ + switch (rate) { +- case 1200000: ++ case 12000000: + num = 64; + den = 125; + break; +- case 1300000: ++ case 13000000: + num = 768; + den = 1625; + break; +@@ -529,11 +529,11 @@ static void __init realtime_counter_init(void) + num = 192; + den = 625; + break; +- case 2600000: ++ case 26000000: + num = 384; + den = 1625; + break; +- case 2700000: ++ case 27000000: + num = 256; + den = 1125; + break; +diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c +index f74ab530c71d..2b73c8a0c244 100644 +--- a/arch/arm/mach-shmobile/setup-sh73a0.c ++++ b/arch/arm/mach-shmobile/setup-sh73a0.c +@@ -617,6 +617,7 @@ static struct platform_device ipmmu_device = { + + static struct renesas_intc_irqpin_config irqpin0_platform_data = { + .irq_base = irq_pin(0), /* IRQ0 -> IRQ7 */ ++ .control_parent = true, + }; + + static struct resource irqpin0_resources[] = { +@@ -678,6 +679,7 @@ static struct platform_device irqpin1_device = { + + static struct renesas_intc_irqpin_config irqpin2_platform_data = { + .irq_base = irq_pin(16), /* IRQ16 -> IRQ23 */ ++ .control_parent = true, + }; + + static struct resource irqpin2_resources[] = { +@@ -708,6 +710,7 @@ static struct platform_device irqpin2_device = { + + static struct renesas_intc_irqpin_config irqpin3_platform_data = { + .irq_base = irq_pin(24), /* IRQ24 -> IRQ31 */ ++ .control_parent = true, + }; + + static struct resource irqpin3_resources[] = { +diff --git a/arch/parisc/include/asm/ldcw.h b/arch/parisc/include/asm/ldcw.h +index d2d11b7055ba..8121aa6db2ff 100644 +--- a/arch/parisc/include/asm/ldcw.h ++++ b/arch/parisc/include/asm/ldcw.h +@@ -33,11 +33,18 @@ + + #endif /*!CONFIG_PA20*/ + +-/* LDCW, the only atomic read-write operation PA-RISC has. *sigh*. */ ++/* LDCW, the only atomic read-write operation PA-RISC has. *sigh*. ++ We don't explicitly expose that "*a" may be written as reload ++ fails to find a register in class R1_REGS when "a" needs to be ++ reloaded when generating 64-bit PIC code. Instead, we clobber ++ memory to indicate to the compiler that the assembly code reads ++ or writes to items other than those listed in the input and output ++ operands. This may pessimize the code somewhat but __ldcw is ++ usually used within code blocks surrounded by memory barriors. */ + #define __ldcw(a) ({ \ + unsigned __ret; \ +- __asm__ __volatile__(__LDCW " 0(%2),%0" \ +- : "=r" (__ret), "+m" (*(a)) : "r" (a)); \ ++ __asm__ __volatile__(__LDCW " 0(%1),%0" \ ++ : "=r" (__ret) : "r" (a) : "memory"); \ + __ret; \ + }) + +diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common +index 21ca44c4f6d5..1f0ea5537e8a 100644 +--- a/arch/um/Kconfig.common ++++ b/arch/um/Kconfig.common +@@ -2,6 +2,7 @@ config UML + bool + default y + select HAVE_UID16 ++ select HAVE_FUTEX_CMPXCHG if FUTEX + select GENERIC_IRQ_SHOW + select GENERIC_CPU_DEVICES + select GENERIC_IO +diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c +index 79a3f9682871..a1f5b1866cbe 100644 +--- a/arch/x86/kernel/kprobes/core.c ++++ b/arch/x86/kernel/kprobes/core.c +@@ -1017,6 +1017,15 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) + regs->flags &= ~X86_EFLAGS_IF; + trace_hardirqs_off(); + regs->ip = (unsigned long)(jp->entry); ++ ++ /* ++ * jprobes use jprobe_return() which skips the normal return ++ * path of the function, and this messes up the accounting of the ++ * function graph tracer to get messed up. ++ * ++ * Pause function graph tracing while performing the jprobe function. ++ */ ++ pause_graph_tracing(); + return 1; + } + +@@ -1042,24 +1051,25 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + u8 *addr = (u8 *) (regs->ip - 1); + struct jprobe *jp = container_of(p, struct jprobe, kp); ++ void *saved_sp = kcb->jprobe_saved_sp; + + if ((addr > (u8 *) jprobe_return) && + (addr < (u8 *) jprobe_return_end)) { +- if (stack_addr(regs) != kcb->jprobe_saved_sp) { ++ if (stack_addr(regs) != saved_sp) { + struct pt_regs *saved_regs = &kcb->jprobe_saved_regs; + printk(KERN_ERR + "current sp %p does not match saved sp %p\n", +- stack_addr(regs), kcb->jprobe_saved_sp); ++ stack_addr(regs), saved_sp); + printk(KERN_ERR "Saved registers for jprobe %p\n", jp); + show_regs(saved_regs); + printk(KERN_ERR "Current registers\n"); + show_regs(regs); + BUG(); + } ++ /* It's OK to start function graph tracing again */ ++ unpause_graph_tracing(); + *regs = kcb->jprobe_saved_regs; +- memcpy((kprobe_opcode_t *)(kcb->jprobe_saved_sp), +- kcb->jprobes_stack, +- MIN_STACK_SIZE(kcb->jprobe_saved_sp)); ++ memcpy(saved_sp, kcb->jprobes_stack, MIN_STACK_SIZE(saved_sp)); + preempt_enable_no_resched(); + return 1; + } +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 0c90f4b3f835..de426887b359 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -2320,12 +2320,12 @@ static __init void nested_vmx_setup_ctls_msrs(void) + nested_vmx_secondary_ctls_low = 0; + nested_vmx_secondary_ctls_high &= + SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | +- SECONDARY_EXEC_UNRESTRICTED_GUEST | + SECONDARY_EXEC_WBINVD_EXITING; + + if (enable_ept) { + /* nested EPT: emulate EPT also to L1 */ +- nested_vmx_secondary_ctls_high |= SECONDARY_EXEC_ENABLE_EPT; ++ nested_vmx_secondary_ctls_high |= SECONDARY_EXEC_ENABLE_EPT | ++ SECONDARY_EXEC_UNRESTRICTED_GUEST; + nested_vmx_ept_caps = VMX_EPT_PAGE_WALK_4_BIT | + VMX_EPTP_WB_BIT | VMX_EPT_2MB_PAGE_BIT | + VMX_EPT_INVEPT_BIT; +diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c +index 531d4269e2e3..bd16d6c370ec 100644 +--- a/arch/x86/um/sys_call_table_32.c ++++ b/arch/x86/um/sys_call_table_32.c +@@ -34,7 +34,7 @@ typedef asmlinkage void (*sys_call_ptr_t)(void); + + extern asmlinkage void sys_ni_syscall(void); + +-const sys_call_ptr_t sys_call_table[] __cacheline_aligned = { ++const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = { + /* + * Smells like a compiler bug -- it doesn't work + * when the & below is removed. +diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c +index f2f0723070ca..95783087f0d3 100644 +--- a/arch/x86/um/sys_call_table_64.c ++++ b/arch/x86/um/sys_call_table_64.c +@@ -46,7 +46,7 @@ typedef void (*sys_call_ptr_t)(void); + + extern void sys_ni_syscall(void); + +-const sys_call_ptr_t sys_call_table[] __cacheline_aligned = { ++const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = { + /* + * Smells like a compiler bug -- it doesn't work + * when the & below is removed. +diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c +index f9c4632d4dd3..7145f6d93567 100644 +--- a/drivers/clk/clk.c ++++ b/drivers/clk/clk.c +@@ -2232,14 +2232,17 @@ int __clk_get(struct clk *clk) + + void __clk_put(struct clk *clk) + { ++ struct module *owner; ++ + if (!clk || WARN_ON_ONCE(IS_ERR(clk))) + return; + + clk_prepare_lock(); ++ owner = clk->owner; + kref_put(&clk->ref, __clk_release); + clk_prepare_unlock(); + +- module_put(clk->owner); ++ module_put(owner); + } + + /*** clk rate change notifiers ***/ +diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c +index 884187fbfe00..7f30b94c00a5 100644 +--- a/drivers/clk/samsung/clk-exynos-audss.c ++++ b/drivers/clk/samsung/clk-exynos-audss.c +@@ -210,6 +210,10 @@ static int exynos_audss_clk_remove(struct platform_device *pdev) + { + int i; + ++#ifdef CONFIG_PM_SLEEP ++ unregister_syscore_ops(&exynos_audss_clk_syscore_ops); ++#endif ++ + of_clk_del_provider(pdev->dev.of_node); + + for (i = 0; i < clk_data.clk_num; i++) { +diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c +index e0a98f581f58..74ed17d6cfa1 100644 +--- a/drivers/gpio/gpiolib-of.c ++++ b/drivers/gpio/gpiolib-of.c +@@ -44,8 +44,14 @@ static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data) + return false; + + ret = gc->of_xlate(gc, &gg_data->gpiospec, gg_data->flags); +- if (ret < 0) +- return false; ++ if (ret < 0) { ++ /* We've found the gpio chip, but the translation failed. ++ * Return true to stop looking and return the translation ++ * error via out_gpio ++ */ ++ gg_data->out_gpio = ERR_PTR(ret); ++ return true; ++ } + + gg_data->out_gpio = gpio_to_desc(ret + gc->base); + return true; +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index 50c4922fe53a..5b88c83888d1 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -1222,6 +1222,9 @@ int gpiochip_add(struct gpio_chip *chip) + + spin_unlock_irqrestore(&gpio_lock, flags); + ++ if (status) ++ goto fail; ++ + #ifdef CONFIG_PINCTRL + INIT_LIST_HEAD(&chip->pin_ranges); + #endif +@@ -1229,12 +1232,12 @@ int gpiochip_add(struct gpio_chip *chip) + of_gpiochip_add(chip); + acpi_gpiochip_add(chip); + +- if (status) +- goto fail; +- + status = gpiochip_export(chip); +- if (status) ++ if (status) { ++ acpi_gpiochip_remove(chip); ++ of_gpiochip_remove(chip); + goto fail; ++ } + + pr_debug("%s: registered GPIOs %d to %d on device: %s\n", __func__, + chip->base, chip->base + chip->ngpio - 1, +diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c +index 3c78b2268209..800e06c28018 100644 +--- a/drivers/gpu/drm/i915/i915_gem_stolen.c ++++ b/drivers/gpu/drm/i915/i915_gem_stolen.c +@@ -137,7 +137,11 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) + r = devm_request_mem_region(dev->dev, base + 1, + dev_priv->gtt.stolen_size - 1, + "Graphics Stolen Memory"); +- if (r == NULL) { ++ /* ++ * GEN3 firmware likes to smash pci bridges into the stolen ++ * range. Apparently this works. ++ */ ++ if (r == NULL && !IS_GEN3(dev)) { + DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n", + base, base + (uint32_t)dev_priv->gtt.stolen_size); + base = 0; +diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h +index 0a3b9386eb43..0c83b3dab58c 100644 +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -320,6 +320,7 @@ + #define PIPE_CONTROL_GLOBAL_GTT_IVB (1<<24) /* gen7+ */ + #define PIPE_CONTROL_CS_STALL (1<<20) + #define PIPE_CONTROL_TLB_INVALIDATE (1<<18) ++#define PIPE_CONTROL_MEDIA_STATE_CLEAR (1<<16) + #define PIPE_CONTROL_QW_WRITE (1<<14) + #define PIPE_CONTROL_DEPTH_STALL (1<<13) + #define PIPE_CONTROL_WRITE_FLUSH (1<<12) +diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c +index d488fc71ef49..d2af1e138c91 100644 +--- a/drivers/gpu/drm/i915/intel_ringbuffer.c ++++ b/drivers/gpu/drm/i915/intel_ringbuffer.c +@@ -334,12 +334,15 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring, + flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; ++ flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR; + /* + * TLB invalidate requires a post-sync write. + */ + flags |= PIPE_CONTROL_QW_WRITE; + flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; + ++ flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; ++ + /* Workaround: we must issue a pipe_control with CS-stall bit + * set before a pipe_control command that has the state cache + * invalidate bit set. */ +diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c +index c8796316d242..b6c063cad59b 100644 +--- a/drivers/gpu/drm/i915/intel_uncore.c ++++ b/drivers/gpu/drm/i915/intel_uncore.c +@@ -451,8 +451,8 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg) + static void + assert_device_not_suspended(struct drm_i915_private *dev_priv) + { +- WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended, +- "Device suspended\n"); ++ WARN_ONCE(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended, ++ "Device suspended\n"); + } + + #define REG_READ_HEADER(x) \ +diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c +index a75c35ccf25c..165401c4045c 100644 +--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c ++++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c +@@ -24,13 +24,6 @@ + + #include "nv04.h" + +-static void +-nv4c_mc_msi_rearm(struct nouveau_mc *pmc) +-{ +- struct nv04_mc_priv *priv = (void *)pmc; +- nv_wr08(priv, 0x088050, 0xff); +-} +- + struct nouveau_oclass * + nv4c_mc_oclass = &(struct nouveau_mc_oclass) { + .base.handle = NV_SUBDEV(MC, 0x4c), +@@ -41,5 +34,4 @@ nv4c_mc_oclass = &(struct nouveau_mc_oclass) { + .fini = _nouveau_mc_fini, + }, + .intr = nv04_mc_intr, +- .msi_rearm = nv4c_mc_msi_rearm, + }.base; +diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c +index 5727dbdeda7f..b4dbaded2caf 100644 +--- a/drivers/gpu/drm/radeon/atombios_dp.c ++++ b/drivers/gpu/drm/radeon/atombios_dp.c +@@ -576,6 +576,10 @@ int radeon_dp_mode_valid_helper(struct drm_connector *connector, + struct radeon_connector_atom_dig *dig_connector; + int dp_clock; + ++ if ((mode->clock > 340000) && ++ (!radeon_connector_is_dp12_capable(connector))) ++ return MODE_CLOCK_HIGH; ++ + if (!radeon_connector->con_priv) + return MODE_CLOCK_HIGH; + dig_connector = radeon_connector->con_priv; +diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c +index 543ba2d4a659..c7c285646857 100644 +--- a/drivers/gpu/drm/radeon/ci_dpm.c ++++ b/drivers/gpu/drm/radeon/ci_dpm.c +@@ -4733,7 +4733,7 @@ void ci_dpm_disable(struct radeon_device *rdev) + ci_enable_spread_spectrum(rdev, false); + ci_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, false); + ci_stop_dpm(rdev); +- ci_enable_ds_master_switch(rdev, true); ++ ci_enable_ds_master_switch(rdev, false); + ci_enable_ulv(rdev, false); + ci_clear_vc(rdev); + ci_reset_to_default(rdev); +diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c +index ddf70d6c0270..8ef67cb4ef1e 100644 +--- a/drivers/gpu/drm/radeon/cik.c ++++ b/drivers/gpu/drm/radeon/cik.c +@@ -5879,6 +5879,7 @@ static void cik_enable_mgcg(struct radeon_device *rdev, bool enable) + } + + orig = data = RREG32(RLC_CGTT_MGCG_OVERRIDE); ++ data |= 0x00000001; + data &= 0xfffffffd; + if (orig != data) + WREG32(RLC_CGTT_MGCG_OVERRIDE, data); +@@ -5910,7 +5911,7 @@ static void cik_enable_mgcg(struct radeon_device *rdev, bool enable) + } + } else { + orig = data = RREG32(RLC_CGTT_MGCG_OVERRIDE); +- data |= 0x00000002; ++ data |= 0x00000003; + if (orig != data) + WREG32(RLC_CGTT_MGCG_OVERRIDE, data); + +diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c +index 040a2a10ea17..45a9a03efc06 100644 +--- a/drivers/gpu/drm/radeon/radeon_ttm.c ++++ b/drivers/gpu/drm/radeon/radeon_ttm.c +@@ -191,7 +191,7 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo, + rbo = container_of(bo, struct radeon_bo, tbo); + switch (bo->mem.mem_type) { + case TTM_PL_VRAM: +- if (rbo->rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready == false) ++ if (rbo->rdev->ring[radeon_copy_ring_index(rbo->rdev)].ready == false) + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU); + else + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); +diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c +index cf4bad2c1d59..76329d27385b 100644 +--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c ++++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c +@@ -297,11 +297,12 @@ static void ttm_pool_update_free_locked(struct ttm_page_pool *pool, + * + * @pool: to free the pages from + * @free_all: If set to true will free all pages in pool +- * @gfp: GFP flags. ++ * @use_static: Safe to use static buffer + **/ + static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free, +- gfp_t gfp) ++ bool use_static) + { ++ static struct page *static_buf[NUM_PAGES_TO_ALLOC]; + unsigned long irq_flags; + struct page *p; + struct page **pages_to_free; +@@ -311,7 +312,11 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free, + if (NUM_PAGES_TO_ALLOC < nr_free) + npages_to_free = NUM_PAGES_TO_ALLOC; + +- pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp); ++ if (use_static) ++ pages_to_free = static_buf; ++ else ++ pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), ++ GFP_KERNEL); + if (!pages_to_free) { + pr_err("Failed to allocate memory for pool free operation\n"); + return 0; +@@ -374,7 +379,8 @@ restart: + if (freed_pages) + ttm_pages_put(pages_to_free, freed_pages); + out: +- kfree(pages_to_free); ++ if (pages_to_free != static_buf) ++ kfree(pages_to_free); + return nr_free; + } + +@@ -383,8 +389,6 @@ out: + * + * XXX: (dchinner) Deadlock warning! + * +- * We need to pass sc->gfp_mask to ttm_page_pool_free(). +- * + * This code is crying out for a shrinker per pool.... + */ + static unsigned long +@@ -407,8 +411,8 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) + if (shrink_pages == 0) + break; + pool = &_manager->pools[(i + pool_offset)%NUM_POOLS]; +- shrink_pages = ttm_page_pool_free(pool, nr_free, +- sc->gfp_mask); ++ /* OK to use static buffer since global mutex is held. */ ++ shrink_pages = ttm_page_pool_free(pool, nr_free, true); + freed += nr_free - shrink_pages; + } + mutex_unlock(&lock); +@@ -710,7 +714,7 @@ static void ttm_put_pages(struct page **pages, unsigned npages, int flags, + } + spin_unlock_irqrestore(&pool->lock, irq_flags); + if (npages) +- ttm_page_pool_free(pool, npages, GFP_KERNEL); ++ ttm_page_pool_free(pool, npages, false); + } + + /* +@@ -849,9 +853,9 @@ void ttm_page_alloc_fini(void) + pr_info("Finalizing pool allocator\n"); + ttm_pool_mm_shrink_fini(_manager); + ++ /* OK to use static buffer since global mutex is no longer used. */ + for (i = 0; i < NUM_POOLS; ++i) +- ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES, +- GFP_KERNEL); ++ ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES, true); + + kobject_put(&_manager->kobj); + _manager = NULL; +diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +index ca65df144765..3dfa97d04e51 100644 +--- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c ++++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +@@ -411,11 +411,12 @@ static void ttm_dma_page_put(struct dma_pool *pool, struct dma_page *d_page) + * + * @pool: to free the pages from + * @nr_free: If set to true will free all pages in pool +- * @gfp: GFP flags. ++ * @use_static: Safe to use static buffer + **/ + static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free, +- gfp_t gfp) ++ bool use_static) + { ++ static struct page *static_buf[NUM_PAGES_TO_ALLOC]; + unsigned long irq_flags; + struct dma_page *dma_p, *tmp; + struct page **pages_to_free; +@@ -432,7 +433,11 @@ static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free, + npages_to_free, nr_free); + } + #endif +- pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp); ++ if (use_static) ++ pages_to_free = static_buf; ++ else ++ pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), ++ GFP_KERNEL); + + if (!pages_to_free) { + pr_err("%s: Failed to allocate memory for pool free operation\n", +@@ -502,7 +507,8 @@ restart: + if (freed_pages) + ttm_dma_pages_put(pool, &d_pages, pages_to_free, freed_pages); + out: +- kfree(pages_to_free); ++ if (pages_to_free != static_buf) ++ kfree(pages_to_free); + return nr_free; + } + +@@ -531,7 +537,8 @@ static void ttm_dma_free_pool(struct device *dev, enum pool_type type) + if (pool->type != type) + continue; + /* Takes a spinlock.. */ +- ttm_dma_page_pool_free(pool, FREE_ALL_PAGES, GFP_KERNEL); ++ /* OK to use static buffer since global mutex is held. */ ++ ttm_dma_page_pool_free(pool, FREE_ALL_PAGES, true); + WARN_ON(((pool->npages_in_use + pool->npages_free) != 0)); + /* This code path is called after _all_ references to the + * struct device has been dropped - so nobody should be +@@ -984,7 +991,7 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev) + + /* shrink pool if necessary (only on !is_cached pools)*/ + if (npages) +- ttm_dma_page_pool_free(pool, npages, GFP_KERNEL); ++ ttm_dma_page_pool_free(pool, npages, false); + ttm->state = tt_unpopulated; + } + EXPORT_SYMBOL_GPL(ttm_dma_unpopulate); +@@ -994,8 +1001,6 @@ EXPORT_SYMBOL_GPL(ttm_dma_unpopulate); + * + * XXX: (dchinner) Deadlock warning! + * +- * We need to pass sc->gfp_mask to ttm_dma_page_pool_free(). +- * + * I'm getting sadder as I hear more pathetical whimpers about needing per-pool + * shrinkers + */ +@@ -1028,8 +1033,8 @@ ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) + if (++idx < pool_offset) + continue; + nr_free = shrink_pages; +- shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free, +- sc->gfp_mask); ++ /* OK to use static buffer since global mutex is held. */ ++ shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free, true); + freed += nr_free - shrink_pages; + + pr_debug("%s: (%s:%d) Asked to shrink %d, have %d more to go\n", +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +index 436b013b4231..b65272d7ea56 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +@@ -1049,6 +1049,8 @@ static int vmw_event_fence_action_create(struct drm_file *file_priv, + if (ret != 0) + goto out_no_queue; + ++ return 0; ++ + out_no_queue: + event->base.destroy(&event->base); + out_no_event: +@@ -1124,17 +1126,10 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data, + + BUG_ON(fence == NULL); + +- if (arg->flags & DRM_VMW_FE_FLAG_REQ_TIME) +- ret = vmw_event_fence_action_create(file_priv, fence, +- arg->flags, +- arg->user_data, +- true); +- else +- ret = vmw_event_fence_action_create(file_priv, fence, +- arg->flags, +- arg->user_data, +- true); +- ++ ret = vmw_event_fence_action_create(file_priv, fence, ++ arg->flags, ++ arg->user_data, ++ true); + if (unlikely(ret != 0)) { + if (ret != -ERESTARTSYS) + DRM_ERROR("Failed to attach event to fence.\n"); +diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c +index a96cfc31372e..60142274fe4b 100644 +--- a/drivers/infiniband/ulp/isert/ib_isert.c ++++ b/drivers/infiniband/ulp/isert/ib_isert.c +@@ -41,6 +41,7 @@ static DEFINE_MUTEX(device_list_mutex); + static LIST_HEAD(device_list); + static struct workqueue_struct *isert_rx_wq; + static struct workqueue_struct *isert_comp_wq; ++static struct workqueue_struct *isert_release_wq; + + static void + isert_unmap_cmd(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn); +@@ -52,6 +53,11 @@ isert_unreg_rdma(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn); + static int + isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd, + struct isert_rdma_wr *wr); ++static int ++isert_rdma_post_recvl(struct isert_conn *isert_conn); ++static int ++isert_rdma_accept(struct isert_conn *isert_conn); ++struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np); + + static void + isert_qp_event_callback(struct ib_event *e, void *context) +@@ -132,12 +138,18 @@ isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id) + ret = rdma_create_qp(cma_id, isert_conn->conn_pd, &attr); + if (ret) { + pr_err("rdma_create_qp failed for cma_id %d\n", ret); +- return ret; ++ goto err; + } + isert_conn->conn_qp = cma_id->qp; + pr_debug("rdma_create_qp() returned success >>>>>>>>>>>>>>>>>>>>>>>>>.\n"); + + return 0; ++err: ++ mutex_lock(&device_list_mutex); ++ device->cq_active_qps[min_index]--; ++ mutex_unlock(&device_list_mutex); ++ ++ return ret; + } + + static void +@@ -489,8 +501,8 @@ err: + static int + isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + { +- struct iscsi_np *np = cma_id->context; +- struct isert_np *isert_np = np->np_context; ++ struct isert_np *isert_np = cma_id->context; ++ struct iscsi_np *np = isert_np->np; + struct isert_conn *isert_conn; + struct isert_device *device; + struct ib_device *ib_dev = cma_id->device; +@@ -515,6 +527,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + isert_conn->state = ISER_CONN_INIT; + INIT_LIST_HEAD(&isert_conn->conn_accept_node); + init_completion(&isert_conn->conn_login_comp); ++ init_completion(&isert_conn->login_req_comp); + init_completion(&isert_conn->conn_wait); + init_completion(&isert_conn->conn_wait_comp_err); + kref_init(&isert_conn->conn_kref); +@@ -522,7 +535,6 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + spin_lock_init(&isert_conn->conn_lock); + INIT_LIST_HEAD(&isert_conn->conn_fr_pool); + +- cma_id->context = isert_conn; + isert_conn->conn_cm_id = cma_id; + isert_conn->responder_resources = event->param.conn.responder_resources; + isert_conn->initiator_depth = event->param.conn.initiator_depth; +@@ -596,6 +608,14 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + if (ret) + goto out_conn_dev; + ++ ret = isert_rdma_post_recvl(isert_conn); ++ if (ret) ++ goto out_conn_dev; ++ ++ ret = isert_rdma_accept(isert_conn); ++ if (ret) ++ goto out_conn_dev; ++ + mutex_lock(&isert_np->np_accept_mutex); + list_add_tail(&isert_conn->conn_accept_node, &isert_np->np_accept_list); + mutex_unlock(&isert_np->np_accept_mutex); +@@ -620,6 +640,7 @@ out_login_buf: + kfree(isert_conn->login_buf); + out: + kfree(isert_conn); ++ rdma_reject(cma_id, NULL, 0); + return ret; + } + +@@ -635,18 +656,20 @@ isert_connect_release(struct isert_conn *isert_conn) + if (device && device->use_fastreg) + isert_conn_free_fastreg_pool(isert_conn); + ++ isert_free_rx_descriptors(isert_conn); ++ rdma_destroy_id(isert_conn->conn_cm_id); ++ + if (isert_conn->conn_qp) { + cq_index = ((struct isert_cq_desc *) + isert_conn->conn_qp->recv_cq->cq_context)->cq_index; + pr_debug("isert_connect_release: cq_index: %d\n", cq_index); ++ mutex_lock(&device_list_mutex); + isert_conn->conn_device->cq_active_qps[cq_index]--; ++ mutex_unlock(&device_list_mutex); + +- rdma_destroy_qp(isert_conn->conn_cm_id); ++ ib_destroy_qp(isert_conn->conn_qp); + } + +- isert_free_rx_descriptors(isert_conn); +- rdma_destroy_id(isert_conn->conn_cm_id); +- + ib_dereg_mr(isert_conn->conn_mr); + ib_dealloc_pd(isert_conn->conn_pd); + +@@ -669,9 +692,19 @@ isert_connect_release(struct isert_conn *isert_conn) + static void + isert_connected_handler(struct rdma_cm_id *cma_id) + { +- struct isert_conn *isert_conn = cma_id->context; ++ struct isert_conn *isert_conn = cma_id->qp->qp_context; ++ ++ pr_info("conn %p\n", isert_conn); + +- kref_get(&isert_conn->conn_kref); ++ if (!kref_get_unless_zero(&isert_conn->conn_kref)) { ++ pr_warn("conn %p connect_release is running\n", isert_conn); ++ return; ++ } ++ ++ mutex_lock(&isert_conn->conn_mutex); ++ if (isert_conn->state != ISER_CONN_FULL_FEATURE) ++ isert_conn->state = ISER_CONN_UP; ++ mutex_unlock(&isert_conn->conn_mutex); + } + + static void +@@ -692,65 +725,108 @@ isert_put_conn(struct isert_conn *isert_conn) + kref_put(&isert_conn->conn_kref, isert_release_conn_kref); + } + ++/** ++ * isert_conn_terminate() - Initiate connection termination ++ * @isert_conn: isert connection struct ++ * ++ * Notes: ++ * In case the connection state is FULL_FEATURE, move state ++ * to TEMINATING and start teardown sequence (rdma_disconnect). ++ * In case the connection state is UP, complete flush as well. ++ * ++ * This routine must be called with conn_mutex held. Thus it is ++ * safe to call multiple times. ++ */ + static void +-isert_disconnect_work(struct work_struct *work) ++isert_conn_terminate(struct isert_conn *isert_conn) + { +- struct isert_conn *isert_conn = container_of(work, +- struct isert_conn, conn_logout_work); ++ int err; + +- pr_debug("isert_disconnect_work(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); +- mutex_lock(&isert_conn->conn_mutex); +- if (isert_conn->state == ISER_CONN_UP) ++ switch (isert_conn->state) { ++ case ISER_CONN_TERMINATING: ++ break; ++ case ISER_CONN_UP: ++ /* ++ * No flush completions will occur as we didn't ++ * get to ISER_CONN_FULL_FEATURE yet, complete ++ * to allow teardown progress. ++ */ ++ complete(&isert_conn->conn_wait_comp_err); ++ case ISER_CONN_FULL_FEATURE: /* FALLTHRU */ ++ pr_info("Terminating conn %p state %d\n", ++ isert_conn, isert_conn->state); + isert_conn->state = ISER_CONN_TERMINATING; +- +- if (isert_conn->post_recv_buf_count == 0 && +- atomic_read(&isert_conn->post_send_buf_count) == 0) { +- mutex_unlock(&isert_conn->conn_mutex); +- goto wake_up; +- } +- if (!isert_conn->conn_cm_id) { +- mutex_unlock(&isert_conn->conn_mutex); +- isert_put_conn(isert_conn); +- return; ++ err = rdma_disconnect(isert_conn->conn_cm_id); ++ if (err) ++ pr_warn("Failed rdma_disconnect isert_conn %p\n", ++ isert_conn); ++ break; ++ default: ++ pr_warn("conn %p teminating in state %d\n", ++ isert_conn, isert_conn->state); + } ++} + +- if (isert_conn->disconnect) { +- /* Send DREQ/DREP towards our initiator */ +- rdma_disconnect(isert_conn->conn_cm_id); +- } ++static int ++isert_np_cma_handler(struct isert_np *isert_np, ++ enum rdma_cm_event_type event) ++{ ++ pr_debug("isert np %p, handling event %d\n", isert_np, event); + +- mutex_unlock(&isert_conn->conn_mutex); ++ switch (event) { ++ case RDMA_CM_EVENT_DEVICE_REMOVAL: ++ isert_np->np_cm_id = NULL; ++ break; ++ case RDMA_CM_EVENT_ADDR_CHANGE: ++ isert_np->np_cm_id = isert_setup_id(isert_np); ++ if (IS_ERR(isert_np->np_cm_id)) { ++ pr_err("isert np %p setup id failed: %ld\n", ++ isert_np, PTR_ERR(isert_np->np_cm_id)); ++ isert_np->np_cm_id = NULL; ++ } ++ break; ++ default: ++ pr_err("isert np %p Unexpected event %d\n", ++ isert_np, event); ++ } + +-wake_up: +- complete(&isert_conn->conn_wait); ++ return -1; + } + + static int +-isert_disconnected_handler(struct rdma_cm_id *cma_id, bool disconnect) ++isert_disconnected_handler(struct rdma_cm_id *cma_id, ++ enum rdma_cm_event_type event) + { ++ struct isert_np *isert_np = cma_id->context; + struct isert_conn *isert_conn; + +- if (!cma_id->qp) { +- struct isert_np *isert_np = cma_id->context; ++ if (isert_np->np_cm_id == cma_id) ++ return isert_np_cma_handler(cma_id->context, event); + +- isert_np->np_cm_id = NULL; +- return -1; +- } ++ isert_conn = cma_id->qp->qp_context; + +- isert_conn = (struct isert_conn *)cma_id->context; ++ mutex_lock(&isert_conn->conn_mutex); ++ isert_conn_terminate(isert_conn); ++ mutex_unlock(&isert_conn->conn_mutex); + +- isert_conn->disconnect = disconnect; +- INIT_WORK(&isert_conn->conn_logout_work, isert_disconnect_work); +- schedule_work(&isert_conn->conn_logout_work); ++ pr_info("conn %p completing conn_wait\n", isert_conn); ++ complete(&isert_conn->conn_wait); + + return 0; + } + ++static void ++isert_connect_error(struct rdma_cm_id *cma_id) ++{ ++ struct isert_conn *isert_conn = cma_id->qp->qp_context; ++ ++ isert_put_conn(isert_conn); ++} ++ + static int + isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + { + int ret = 0; +- bool disconnect = false; + + pr_debug("isert_cma_handler: event %d status %d conn %p id %p\n", + event->event, event->status, cma_id->context, cma_id); +@@ -768,11 +844,14 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + case RDMA_CM_EVENT_ADDR_CHANGE: /* FALLTHRU */ + case RDMA_CM_EVENT_DISCONNECTED: /* FALLTHRU */ + case RDMA_CM_EVENT_DEVICE_REMOVAL: /* FALLTHRU */ +- disconnect = true; + case RDMA_CM_EVENT_TIMEWAIT_EXIT: /* FALLTHRU */ +- ret = isert_disconnected_handler(cma_id, disconnect); ++ ret = isert_disconnected_handler(cma_id, event->event); + break; ++ case RDMA_CM_EVENT_REJECTED: /* FALLTHRU */ ++ case RDMA_CM_EVENT_UNREACHABLE: /* FALLTHRU */ + case RDMA_CM_EVENT_CONNECT_ERROR: ++ isert_connect_error(cma_id); ++ break; + default: + pr_err("Unhandled RDMA CMA event: %d\n", event->event); + break; +@@ -906,7 +985,7 @@ isert_init_send_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, + * bit for every ISERT_COMP_BATCH_COUNT number of ib_post_send() calls. + */ + mutex_lock(&isert_conn->conn_mutex); +- if (coalesce && isert_conn->state == ISER_CONN_UP && ++ if (coalesce && isert_conn->state == ISER_CONN_FULL_FEATURE && + ++isert_conn->conn_comp_batch < ISERT_COMP_BATCH_COUNT) { + tx_desc->llnode_active = true; + llist_add(&tx_desc->comp_llnode, &isert_conn->conn_comp_llist); +@@ -1003,7 +1082,10 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login, + if (ret) + return ret; + +- isert_conn->state = ISER_CONN_UP; ++ /* Now we are in FULL_FEATURE phase */ ++ mutex_lock(&isert_conn->conn_mutex); ++ isert_conn->state = ISER_CONN_FULL_FEATURE; ++ mutex_unlock(&isert_conn->conn_mutex); + goto post_send; + } + +@@ -1020,18 +1102,17 @@ post_send: + } + + static void +-isert_rx_login_req(struct iser_rx_desc *rx_desc, int rx_buflen, +- struct isert_conn *isert_conn) ++isert_rx_login_req(struct isert_conn *isert_conn) + { ++ struct iser_rx_desc *rx_desc = (void *)isert_conn->login_req_buf; ++ int rx_buflen = isert_conn->login_req_len; + struct iscsi_conn *conn = isert_conn->conn; + struct iscsi_login *login = conn->conn_login; + int size; + +- if (!login) { +- pr_err("conn->conn_login is NULL\n"); +- dump_stack(); +- return; +- } ++ pr_info("conn %p\n", isert_conn); ++ ++ WARN_ON_ONCE(!login); + + if (login->first_request) { + struct iscsi_login_req *login_req = +@@ -1394,11 +1475,20 @@ isert_rx_completion(struct iser_rx_desc *desc, struct isert_conn *isert_conn, + hdr->opcode, hdr->itt, hdr->flags, + (int)(xfer_len - ISER_HEADERS_LEN)); + +- if ((char *)desc == isert_conn->login_req_buf) +- isert_rx_login_req(desc, xfer_len - ISER_HEADERS_LEN, +- isert_conn); +- else ++ if ((char *)desc == isert_conn->login_req_buf) { ++ isert_conn->login_req_len = xfer_len - ISER_HEADERS_LEN; ++ if (isert_conn->conn) { ++ struct iscsi_login *login = isert_conn->conn->conn_login; ++ ++ if (login && !login->first_request) ++ isert_rx_login_req(isert_conn); ++ } ++ mutex_lock(&isert_conn->conn_mutex); ++ complete(&isert_conn->login_req_comp); ++ mutex_unlock(&isert_conn->conn_mutex); ++ } else { + isert_rx_do_work(desc, isert_conn); ++ } + + ib_dma_sync_single_for_device(ib_dev, rx_dma, rx_buflen, + DMA_FROM_DEVICE); +@@ -1799,7 +1889,7 @@ isert_cq_rx_comp_err(struct isert_conn *isert_conn) + msleep(3000); + + mutex_lock(&isert_conn->conn_mutex); +- isert_conn->state = ISER_CONN_DOWN; ++ isert_conn_terminate(isert_conn); + mutex_unlock(&isert_conn->conn_mutex); + + iscsit_cause_connection_reinstatement(isert_conn->conn, 0); +@@ -2579,13 +2669,51 @@ isert_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state) + return ret; + } + ++struct rdma_cm_id * ++isert_setup_id(struct isert_np *isert_np) ++{ ++ struct iscsi_np *np = isert_np->np; ++ struct rdma_cm_id *id; ++ struct sockaddr *sa; ++ int ret; ++ ++ sa = (struct sockaddr *)&np->np_sockaddr; ++ pr_debug("ksockaddr: %p, sa: %p\n", &np->np_sockaddr, sa); ++ ++ id = rdma_create_id(isert_cma_handler, isert_np, ++ RDMA_PS_TCP, IB_QPT_RC); ++ if (IS_ERR(id)) { ++ pr_err("rdma_create_id() failed: %ld\n", PTR_ERR(id)); ++ ret = PTR_ERR(id); ++ goto out; ++ } ++ pr_debug("id %p context %p\n", id, id->context); ++ ++ ret = rdma_bind_addr(id, sa); ++ if (ret) { ++ pr_err("rdma_bind_addr() failed: %d\n", ret); ++ goto out_id; ++ } ++ ++ ret = rdma_listen(id, ISERT_RDMA_LISTEN_BACKLOG); ++ if (ret) { ++ pr_err("rdma_listen() failed: %d\n", ret); ++ goto out_id; ++ } ++ ++ return id; ++out_id: ++ rdma_destroy_id(id); ++out: ++ return ERR_PTR(ret); ++} ++ + static int + isert_setup_np(struct iscsi_np *np, + struct __kernel_sockaddr_storage *ksockaddr) + { + struct isert_np *isert_np; + struct rdma_cm_id *isert_lid; +- struct sockaddr *sa; + int ret; + + isert_np = kzalloc(sizeof(struct isert_np), GFP_KERNEL); +@@ -2597,9 +2725,8 @@ isert_setup_np(struct iscsi_np *np, + mutex_init(&isert_np->np_accept_mutex); + INIT_LIST_HEAD(&isert_np->np_accept_list); + init_completion(&isert_np->np_login_comp); ++ isert_np->np = np; + +- sa = (struct sockaddr *)ksockaddr; +- pr_debug("ksockaddr: %p, sa: %p\n", ksockaddr, sa); + /* + * Setup the np->np_sockaddr from the passed sockaddr setup + * in iscsi_target_configfs.c code.. +@@ -2607,37 +2734,20 @@ isert_setup_np(struct iscsi_np *np, + memcpy(&np->np_sockaddr, ksockaddr, + sizeof(struct __kernel_sockaddr_storage)); + +- isert_lid = rdma_create_id(isert_cma_handler, np, RDMA_PS_TCP, +- IB_QPT_RC); ++ isert_lid = isert_setup_id(isert_np); + if (IS_ERR(isert_lid)) { +- pr_err("rdma_create_id() for isert_listen_handler failed: %ld\n", +- PTR_ERR(isert_lid)); + ret = PTR_ERR(isert_lid); + goto out; + } + +- ret = rdma_bind_addr(isert_lid, sa); +- if (ret) { +- pr_err("rdma_bind_addr() for isert_lid failed: %d\n", ret); +- goto out_lid; +- } +- +- ret = rdma_listen(isert_lid, ISERT_RDMA_LISTEN_BACKLOG); +- if (ret) { +- pr_err("rdma_listen() for isert_lid failed: %d\n", ret); +- goto out_lid; +- } +- + isert_np->np_cm_id = isert_lid; + np->np_context = isert_np; +- pr_debug("Setup isert_lid->context: %p\n", isert_lid->context); + + return 0; + +-out_lid: +- rdma_destroy_id(isert_lid); + out: + kfree(isert_np); ++ + return ret; + } + +@@ -2673,7 +2783,15 @@ isert_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login) + struct isert_conn *isert_conn = (struct isert_conn *)conn->context; + int ret; + +- pr_debug("isert_get_login_rx before conn_login_comp conn: %p\n", conn); ++ pr_info("before login_req comp conn: %p\n", isert_conn); ++ ret = wait_for_completion_interruptible(&isert_conn->login_req_comp); ++ if (ret) { ++ pr_err("isert_conn %p interrupted before got login req\n", ++ isert_conn); ++ return ret; ++ } ++ reinit_completion(&isert_conn->login_req_comp); ++ + /* + * For login requests after the first PDU, isert_rx_login_req() will + * kick schedule_delayed_work(&conn->login_work) as the packet is +@@ -2683,11 +2801,15 @@ isert_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login) + if (!login->first_request) + return 0; + ++ isert_rx_login_req(isert_conn); ++ ++ pr_info("before conn_login_comp conn: %p\n", conn); + ret = wait_for_completion_interruptible(&isert_conn->conn_login_comp); + if (ret) + return ret; + +- pr_debug("isert_get_login_rx processing login->req: %p\n", login->req); ++ pr_info("processing login->req: %p\n", login->req); ++ + return 0; + } + +@@ -2765,17 +2887,10 @@ accept_wait: + isert_conn->conn = conn; + max_accept = 0; + +- ret = isert_rdma_post_recvl(isert_conn); +- if (ret) +- return ret; +- +- ret = isert_rdma_accept(isert_conn); +- if (ret) +- return ret; +- + isert_set_conn_info(np, conn, isert_conn); + +- pr_debug("Processing isert_accept_np: isert_conn: %p\n", isert_conn); ++ pr_debug("Processing isert_conn: %p\n", isert_conn); ++ + return 0; + } + +@@ -2791,6 +2906,24 @@ isert_free_np(struct iscsi_np *np) + kfree(isert_np); + } + ++static void isert_release_work(struct work_struct *work) ++{ ++ struct isert_conn *isert_conn = container_of(work, ++ struct isert_conn, ++ release_work); ++ ++ pr_info("Starting release conn %p\n", isert_conn); ++ ++ wait_for_completion(&isert_conn->conn_wait); ++ ++ mutex_lock(&isert_conn->conn_mutex); ++ isert_conn->state = ISER_CONN_DOWN; ++ mutex_unlock(&isert_conn->conn_mutex); ++ ++ pr_info("Destroying conn %p\n", isert_conn); ++ isert_put_conn(isert_conn); ++} ++ + static void isert_wait_conn(struct iscsi_conn *conn) + { + struct isert_conn *isert_conn = conn->context; +@@ -2798,10 +2931,6 @@ static void isert_wait_conn(struct iscsi_conn *conn) + pr_debug("isert_wait_conn: Starting \n"); + + mutex_lock(&isert_conn->conn_mutex); +- if (isert_conn->conn_cm_id) { +- pr_debug("Calling rdma_disconnect from isert_wait_conn\n"); +- rdma_disconnect(isert_conn->conn_cm_id); +- } + /* + * Only wait for conn_wait_comp_err if the isert_conn made it + * into full feature phase.. +@@ -2810,14 +2939,13 @@ static void isert_wait_conn(struct iscsi_conn *conn) + mutex_unlock(&isert_conn->conn_mutex); + return; + } +- if (isert_conn->state == ISER_CONN_UP) +- isert_conn->state = ISER_CONN_TERMINATING; ++ isert_conn_terminate(isert_conn); + mutex_unlock(&isert_conn->conn_mutex); + + wait_for_completion(&isert_conn->conn_wait_comp_err); + +- wait_for_completion(&isert_conn->conn_wait); +- isert_put_conn(isert_conn); ++ INIT_WORK(&isert_conn->release_work, isert_release_work); ++ queue_work(isert_release_wq, &isert_conn->release_work); + } + + static void isert_free_conn(struct iscsi_conn *conn) +@@ -2863,10 +2991,21 @@ static int __init isert_init(void) + goto destroy_rx_wq; + } + ++ isert_release_wq = alloc_workqueue("isert_release_wq", WQ_UNBOUND, ++ WQ_UNBOUND_MAX_ACTIVE); ++ if (!isert_release_wq) { ++ pr_err("Unable to allocate isert_release_wq\n"); ++ ret = -ENOMEM; ++ goto destroy_comp_wq; ++ } ++ + iscsit_register_transport(&iser_target_transport); +- pr_debug("iSER_TARGET[0] - Loaded iser_target_transport\n"); ++ pr_info("iSER_TARGET[0] - Loaded iser_target_transport\n"); ++ + return 0; + ++destroy_comp_wq: ++ destroy_workqueue(isert_comp_wq); + destroy_rx_wq: + destroy_workqueue(isert_rx_wq); + return ret; +@@ -2875,6 +3014,7 @@ destroy_rx_wq: + static void __exit isert_exit(void) + { + flush_scheduled_work(); ++ destroy_workqueue(isert_release_wq); + destroy_workqueue(isert_comp_wq); + destroy_workqueue(isert_rx_wq); + iscsit_unregister_transport(&iser_target_transport); +diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h +index cbecaabe90b9..1178c5b6800c 100644 +--- a/drivers/infiniband/ulp/isert/ib_isert.h ++++ b/drivers/infiniband/ulp/isert/ib_isert.h +@@ -23,6 +23,7 @@ enum iser_ib_op_code { + enum iser_conn_state { + ISER_CONN_INIT, + ISER_CONN_UP, ++ ISER_CONN_FULL_FEATURE, + ISER_CONN_TERMINATING, + ISER_CONN_DOWN, + }; +@@ -102,6 +103,7 @@ struct isert_conn { + char *login_req_buf; + char *login_rsp_buf; + u64 login_req_dma; ++ int login_req_len; + u64 login_rsp_dma; + unsigned int conn_rx_desc_head; + struct iser_rx_desc *conn_rx_descs; +@@ -109,13 +111,13 @@ struct isert_conn { + struct iscsi_conn *conn; + struct list_head conn_accept_node; + struct completion conn_login_comp; ++ struct completion login_req_comp; + struct iser_tx_desc conn_login_tx_desc; + struct rdma_cm_id *conn_cm_id; + struct ib_pd *conn_pd; + struct ib_mr *conn_mr; + struct ib_qp *conn_qp; + struct isert_device *conn_device; +- struct work_struct conn_logout_work; + struct mutex conn_mutex; + struct completion conn_wait; + struct completion conn_wait_comp_err; +@@ -124,10 +126,10 @@ struct isert_conn { + int conn_fr_pool_size; + /* lock to protect fastreg pool */ + spinlock_t conn_lock; ++ struct work_struct release_work; + #define ISERT_COMP_BATCH_COUNT 8 + int conn_comp_batch; + struct llist_head conn_comp_llist; +- bool disconnect; + }; + + #define ISERT_MAX_CQ 64 +@@ -158,6 +160,7 @@ struct isert_device { + }; + + struct isert_np { ++ struct iscsi_np *np; + struct semaphore np_sem; + struct rdma_cm_id *np_cm_id; + struct mutex np_accept_mutex; +diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h +index 8fca488fdc15..c43c46f7dcd0 100644 +--- a/drivers/input/serio/i8042-x86ia64io.h ++++ b/drivers/input/serio/i8042-x86ia64io.h +@@ -408,6 +408,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { + }, + }, + { ++ /* Acer Aspire 7738 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Acer"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7738"), ++ }, ++ }, ++ { + /* Gericom Bellagio */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Gericom"), +@@ -721,6 +728,35 @@ static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = { + { } + }; + ++/* ++ * Some laptops need keyboard reset before probing for the trackpad to get ++ * it detected, initialised & finally work. ++ */ ++static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = { ++ { ++ /* Gigabyte P35 v2 - Elantech touchpad */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "P35V2"), ++ }, ++ }, ++ { ++ /* Aorus branded Gigabyte X3 Plus - Elantech touchpad */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "X3"), ++ }, ++ }, ++ { ++ /* Gigabyte P34 - Elantech touchpad */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "P34"), ++ }, ++ }, ++ { } ++}; ++ + #endif /* CONFIG_X86 */ + + #ifdef CONFIG_PNP +@@ -1016,6 +1052,9 @@ static int __init i8042_platform_init(void) + if (dmi_check_system(i8042_dmi_dritek_table)) + i8042_dritek = true; + ++ if (dmi_check_system(i8042_dmi_kbdreset_table)) ++ i8042_kbdreset = true; ++ + /* + * A20 was already enabled during early kernel init. But some buggy + * BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to +diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c +index 3807c3e971cc..eb796fff9e62 100644 +--- a/drivers/input/serio/i8042.c ++++ b/drivers/input/serio/i8042.c +@@ -67,6 +67,10 @@ static bool i8042_notimeout; + module_param_named(notimeout, i8042_notimeout, bool, 0); + MODULE_PARM_DESC(notimeout, "Ignore timeouts signalled by i8042"); + ++static bool i8042_kbdreset; ++module_param_named(kbdreset, i8042_kbdreset, bool, 0); ++MODULE_PARM_DESC(kbdreset, "Reset device connected to KBD port"); ++ + #ifdef CONFIG_X86 + static bool i8042_dritek; + module_param_named(dritek, i8042_dritek, bool, 0); +@@ -790,6 +794,16 @@ static int __init i8042_check_aux(void) + return -1; + + /* ++ * Reset keyboard (needed on some laptops to successfully detect ++ * touchpad, e.g., some Gigabyte laptop models with Elantech ++ * touchpads). ++ */ ++ if (i8042_kbdreset) { ++ pr_warn("Attempting to reset device connected to KBD port\n"); ++ i8042_kbd_write(NULL, (unsigned char) 0xff); ++ } ++ ++/* + * Test AUX IRQ delivery to make sure BIOS did not grab the IRQ and + * used it for a PCI card or somethig else. + */ +diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c +index 5f9c2a665ca5..fbcb6225f794 100644 +--- a/drivers/md/bcache/btree.c ++++ b/drivers/md/bcache/btree.c +@@ -199,7 +199,7 @@ void bch_btree_node_read_done(struct btree *b) + struct bset *i = btree_bset_first(b); + struct btree_iter *iter; + +- iter = mempool_alloc(b->c->fill_iter, GFP_NOWAIT); ++ iter = mempool_alloc(b->c->fill_iter, GFP_NOIO); + iter->size = b->c->sb.bucket_size / b->c->sb.block_size; + iter->used = 0; + +diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c +index 2335529b195c..ab5d9a3adebf 100644 +--- a/drivers/media/i2c/smiapp-pll.c ++++ b/drivers/media/i2c/smiapp-pll.c +@@ -67,7 +67,7 @@ static void print_pll(struct device *dev, struct smiapp_pll *pll) + { + dev_dbg(dev, "pre_pll_clk_div\t%d\n", pll->pre_pll_clk_div); + dev_dbg(dev, "pll_multiplier \t%d\n", pll->pll_multiplier); +- if (pll->flags != SMIAPP_PLL_FLAG_NO_OP_CLOCKS) { ++ if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) { + dev_dbg(dev, "op_sys_clk_div \t%d\n", pll->op_sys_clk_div); + dev_dbg(dev, "op_pix_clk_div \t%d\n", pll->op_pix_clk_div); + } +@@ -77,7 +77,7 @@ static void print_pll(struct device *dev, struct smiapp_pll *pll) + dev_dbg(dev, "ext_clk_freq_hz \t%d\n", pll->ext_clk_freq_hz); + dev_dbg(dev, "pll_ip_clk_freq_hz \t%d\n", pll->pll_ip_clk_freq_hz); + dev_dbg(dev, "pll_op_clk_freq_hz \t%d\n", pll->pll_op_clk_freq_hz); +- if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) { ++ if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) { + dev_dbg(dev, "op_sys_clk_freq_hz \t%d\n", + pll->op_sys_clk_freq_hz); + dev_dbg(dev, "op_pix_clk_freq_hz \t%d\n", +diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c +index 7026ab08ec91..873d0627a75b 100644 +--- a/drivers/media/i2c/smiapp/smiapp-core.c ++++ b/drivers/media/i2c/smiapp/smiapp-core.c +@@ -2624,7 +2624,9 @@ static int smiapp_registered(struct v4l2_subdev *subdev) + pll->flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE; + pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN]; + ++ mutex_lock(&sensor->mutex); + rval = smiapp_update_mode(sensor); ++ mutex_unlock(&sensor->mutex); + if (rval) { + dev_err(&client->dev, "update mode failed\n"); + goto out_nvm_release; +diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c +index dd32decb237d..1d4b11038958 100644 +--- a/drivers/media/usb/au0828/au0828-cards.c ++++ b/drivers/media/usb/au0828/au0828-cards.c +@@ -36,6 +36,11 @@ static void hvr950q_cs5340_audio(void *priv, int enable) + au0828_clear(dev, REG_000, 0x10); + } + ++/* ++ * WARNING: There's a quirks table at sound/usb/quirks-table.h ++ * that should also be updated every time a new device with V4L2 support ++ * is added here. ++ */ + struct au0828_board au0828_boards[] = { + [AU0828_BOARD_UNKNOWN] = { + .name = "Unknown board", +diff --git a/drivers/media/usb/dvb-usb/af9005.c b/drivers/media/usb/dvb-usb/af9005.c +index af176b6ce738..e6d3561eea47 100644 +--- a/drivers/media/usb/dvb-usb/af9005.c ++++ b/drivers/media/usb/dvb-usb/af9005.c +@@ -1081,9 +1081,12 @@ static int __init af9005_usb_module_init(void) + err("usb_register failed. (%d)", result); + return result; + } ++#if IS_MODULE(CONFIG_DVB_USB_AF9005) || defined(CONFIG_DVB_USB_AF9005_REMOTE) ++ /* FIXME: convert to todays kernel IR infrastructure */ + rc_decode = symbol_request(af9005_rc_decode); + rc_keys = symbol_request(rc_map_af9005_table); + rc_keys_size = symbol_request(rc_map_af9005_table_size); ++#endif + if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) { + err("af9005_rc_decode function not found, disabling remote"); + af9005_properties.rc.legacy.rc_query = NULL; +diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c +index 753ad4cfc118..45314412b4a3 100644 +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -1603,12 +1603,12 @@ static void uvc_delete(struct uvc_device *dev) + { + struct list_head *p, *n; + +- usb_put_intf(dev->intf); +- usb_put_dev(dev->udev); +- + uvc_status_cleanup(dev); + uvc_ctrl_cleanup_device(dev); + ++ usb_put_intf(dev->intf); ++ usb_put_dev(dev->udev); ++ + if (dev->vdev.dev) + v4l2_device_unregister(&dev->vdev); + #ifdef CONFIG_MEDIA_CONTROLLER +diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c +index e77d11049747..4e65b35bebc0 100644 +--- a/drivers/net/can/usb/kvaser_usb.c ++++ b/drivers/net/can/usb/kvaser_usb.c +@@ -1237,6 +1237,9 @@ static int kvaser_usb_close(struct net_device *netdev) + if (err) + netdev_warn(netdev, "Cannot stop device, error %d\n", err); + ++ /* reset tx contexts */ ++ kvaser_usb_unlink_tx_urbs(priv); ++ + priv->can.state = CAN_STATE_STOPPED; + close_candev(priv->netdev); + +@@ -1285,12 +1288,14 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, + if (!urb) { + netdev_err(netdev, "No memory left for URBs\n"); + stats->tx_dropped++; +- goto nourbmem; ++ dev_kfree_skb(skb); ++ return NETDEV_TX_OK; + } + + buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC); + if (!buf) { + stats->tx_dropped++; ++ dev_kfree_skb(skb); + goto nobufmem; + } + +@@ -1325,6 +1330,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, + } + } + ++ /* This should never happen; it implies a flow control bug */ + if (!context) { + netdev_warn(netdev, "cannot find free context\n"); + ret = NETDEV_TX_BUSY; +@@ -1355,9 +1361,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, + if (unlikely(err)) { + can_free_echo_skb(netdev, context->echo_index); + +- skb = NULL; /* set to NULL to avoid double free in +- * dev_kfree_skb(skb) */ +- + atomic_dec(&priv->active_tx_urbs); + usb_unanchor_urb(urb); + +@@ -1379,8 +1382,6 @@ releasebuf: + kfree(buf); + nobufmem: + usb_free_urb(urb); +-nourbmem: +- dev_kfree_skb(skb); + return ret; + } + +@@ -1492,6 +1493,10 @@ static int kvaser_usb_init_one(struct usb_interface *intf, + struct kvaser_usb_net_priv *priv; + int i, err; + ++ err = kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, channel); ++ if (err) ++ return err; ++ + netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS); + if (!netdev) { + dev_err(&intf->dev, "Cannot alloc candev\n"); +@@ -1595,9 +1600,6 @@ static int kvaser_usb_probe(struct usb_interface *intf, + + usb_set_intfdata(intf, dev); + +- for (i = 0; i < MAX_NET_DEVICES; i++) +- kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, i); +- + err = kvaser_usb_get_software_info(dev); + if (err) { + dev_err(&intf->dev, +diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c +index 380d24922049..3e1d7d29b4ec 100644 +--- a/drivers/net/ethernet/atheros/alx/main.c ++++ b/drivers/net/ethernet/atheros/alx/main.c +@@ -184,15 +184,16 @@ static void alx_schedule_reset(struct alx_priv *alx) + schedule_work(&alx->reset_wk); + } + +-static bool alx_clean_rx_irq(struct alx_priv *alx, int budget) ++static int alx_clean_rx_irq(struct alx_priv *alx, int budget) + { + struct alx_rx_queue *rxq = &alx->rxq; + struct alx_rrd *rrd; + struct alx_buffer *rxb; + struct sk_buff *skb; + u16 length, rfd_cleaned = 0; ++ int work = 0; + +- while (budget > 0) { ++ while (work < budget) { + rrd = &rxq->rrd[rxq->rrd_read_idx]; + if (!(rrd->word3 & cpu_to_le32(1 << RRD_UPDATED_SHIFT))) + break; +@@ -203,7 +204,7 @@ static bool alx_clean_rx_irq(struct alx_priv *alx, int budget) + ALX_GET_FIELD(le32_to_cpu(rrd->word0), + RRD_NOR) != 1) { + alx_schedule_reset(alx); +- return 0; ++ return work; + } + + rxb = &rxq->bufs[rxq->read_idx]; +@@ -243,7 +244,7 @@ static bool alx_clean_rx_irq(struct alx_priv *alx, int budget) + } + + napi_gro_receive(&alx->napi, skb); +- budget--; ++ work++; + + next_pkt: + if (++rxq->read_idx == alx->rx_ringsz) +@@ -258,21 +259,22 @@ next_pkt: + if (rfd_cleaned) + alx_refill_rx_ring(alx, GFP_ATOMIC); + +- return budget > 0; ++ return work; + } + + static int alx_poll(struct napi_struct *napi, int budget) + { + struct alx_priv *alx = container_of(napi, struct alx_priv, napi); + struct alx_hw *hw = &alx->hw; +- bool complete = true; + unsigned long flags; ++ bool tx_complete; ++ int work; + +- complete = alx_clean_tx_irq(alx) && +- alx_clean_rx_irq(alx, budget); ++ tx_complete = alx_clean_tx_irq(alx); ++ work = alx_clean_rx_irq(alx, budget); + +- if (!complete) +- return 1; ++ if (!tx_complete || work == budget) ++ return budget; + + napi_complete(&alx->napi); + +@@ -284,7 +286,7 @@ static int alx_poll(struct napi_struct *napi, int budget) + + alx_post_write(hw); + +- return 0; ++ return work; + } + + static irqreturn_t alx_intr_handle(struct alx_priv *alx, u32 intr) +diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c +index 086eac5af5c2..82061139b215 100644 +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -17731,23 +17731,6 @@ static int tg3_init_one(struct pci_dev *pdev, + goto err_out_apeunmap; + } + +- /* +- * Reset chip in case UNDI or EFI driver did not shutdown +- * DMA self test will enable WDMAC and we'll see (spurious) +- * pending DMA on the PCI bus at that point. +- */ +- if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || +- (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { +- tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); +- tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); +- } +- +- err = tg3_test_dma(tp); +- if (err) { +- dev_err(&pdev->dev, "DMA engine test failed, aborting\n"); +- goto err_out_apeunmap; +- } +- + intmbx = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW; + rcvmbx = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW; + sndmbx = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW; +@@ -17792,6 +17775,23 @@ static int tg3_init_one(struct pci_dev *pdev, + sndmbx += 0xc; + } + ++ /* ++ * Reset chip in case UNDI or EFI driver did not shutdown ++ * DMA self test will enable WDMAC and we'll see (spurious) ++ * pending DMA on the PCI bus at that point. ++ */ ++ if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || ++ (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { ++ tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); ++ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); ++ } ++ ++ err = tg3_test_dma(tp); ++ if (err) { ++ dev_err(&pdev->dev, "DMA engine test failed, aborting\n"); ++ goto err_out_apeunmap; ++ } ++ + tg3_init_coal(tp); + + pci_set_drvdata(pdev, dev); +diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c +index b740bfce72ef..ff9b423805a0 100644 +--- a/drivers/net/ethernet/cisco/enic/enic_main.c ++++ b/drivers/net/ethernet/cisco/enic/enic_main.c +@@ -1044,10 +1044,14 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, + PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); + } + +- if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc) { +- skb->csum = htons(checksum); +- skb->ip_summed = CHECKSUM_COMPLETE; +- } ++ /* Hardware does not provide whole packet checksum. It only ++ * provides pseudo checksum. Since hw validates the packet ++ * checksum but not provide us the checksum value. use ++ * CHECSUM_UNNECESSARY. ++ */ ++ if ((netdev->features & NETIF_F_RXCSUM) && tcp_udp_csum_ok && ++ ipv4_csum_ok) ++ skb->ip_summed = CHECKSUM_UNNECESSARY; + + if (vlan_stripped) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci); +diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c +index 921b9df2faca..316650c3b5d7 100644 +--- a/drivers/net/ethernet/ti/cpsw.c ++++ b/drivers/net/ethernet/ti/cpsw.c +@@ -596,7 +596,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) + + /* Clear all mcast from ALE */ + cpsw_ale_flush_multicast(ale, ALE_ALL_PORTS << +- priv->host_port); ++ priv->host_port, -1); + + /* Flood All Unicast Packets to Host port */ + cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 1); +@@ -620,6 +620,12 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) + static void cpsw_ndo_set_rx_mode(struct net_device *ndev) + { + struct cpsw_priv *priv = netdev_priv(ndev); ++ int vid; ++ ++ if (priv->data.dual_emac) ++ vid = priv->slaves[priv->emac_port].port_vlan; ++ else ++ vid = priv->data.default_vlan; + + if (ndev->flags & IFF_PROMISC) { + /* Enable promiscuous mode */ +@@ -631,7 +637,8 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev) + } + + /* Clear all mcast from ALE */ +- cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port); ++ cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port, ++ vid); + + if (!netdev_mc_empty(ndev)) { + struct netdev_hw_addr *ha; +@@ -716,6 +723,14 @@ static void cpsw_rx_handler(void *token, int len, int status) + static irqreturn_t cpsw_interrupt(int irq, void *dev_id) + { + struct cpsw_priv *priv = dev_id; ++ int value = irq - priv->irqs_table[0]; ++ ++ /* NOTICE: Ending IRQ here. The trick with the 'value' variable above ++ * is to make sure we will always write the correct value to the EOI ++ * register. Namely 0 for RX_THRESH Interrupt, 1 for RX Interrupt, 2 ++ * for TX Interrupt and 3 for MISC Interrupt. ++ */ ++ cpdma_ctlr_eoi(priv->dma, value); + + cpsw_intr_disable(priv); + if (priv->irq_enabled == true) { +@@ -745,8 +760,6 @@ static int cpsw_poll(struct napi_struct *napi, int budget) + int num_tx, num_rx; + + num_tx = cpdma_chan_process(priv->txch, 128); +- if (num_tx) +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX); + + num_rx = cpdma_chan_process(priv->rxch, budget); + if (num_rx < budget) { +@@ -754,7 +767,6 @@ static int cpsw_poll(struct napi_struct *napi, int budget) + + napi_complete(napi); + cpsw_intr_enable(priv); +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX); + prim_cpsw = cpsw_get_slave_priv(priv, 0); + if (prim_cpsw->irq_enabled == false) { + prim_cpsw->irq_enabled = true; +@@ -1265,8 +1277,6 @@ static int cpsw_ndo_open(struct net_device *ndev) + napi_enable(&priv->napi); + cpdma_ctlr_start(priv->dma); + cpsw_intr_enable(priv); +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX); +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX); + + if (priv->data.dual_emac) + priv->slaves[priv->emac_port].open_stat = true; +@@ -1512,9 +1522,6 @@ static void cpsw_ndo_tx_timeout(struct net_device *ndev) + cpdma_chan_start(priv->txch); + cpdma_ctlr_int_ctrl(priv->dma, true); + cpsw_intr_enable(priv); +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX); +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX); +- + } + + static int cpsw_ndo_set_mac_address(struct net_device *ndev, void *p) +@@ -1560,9 +1567,6 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev) + cpsw_interrupt(ndev->irq, priv); + cpdma_ctlr_int_ctrl(priv->dma, true); + cpsw_intr_enable(priv); +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX); +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX); +- + } + #endif + +diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c +index 7f893069c418..4eceb7e42c80 100644 +--- a/drivers/net/ethernet/ti/cpsw_ale.c ++++ b/drivers/net/ethernet/ti/cpsw_ale.c +@@ -236,7 +236,7 @@ static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry, + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); + } + +-int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask) ++int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid) + { + u32 ale_entry[ALE_ENTRY_WORDS]; + int ret, idx; +@@ -247,6 +247,14 @@ int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask) + if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR) + continue; + ++ /* if vid passed is -1 then remove all multicast entry from ++ * the table irrespective of vlan id, if a valid vlan id is ++ * passed then remove only multicast added to that vlan id. ++ * if vlan id doesn't match then move on to next entry. ++ */ ++ if (vid != -1 && cpsw_ale_get_vlan_id(ale_entry) != vid) ++ continue; ++ + if (cpsw_ale_get_mcast(ale_entry)) { + u8 addr[6]; + +diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h +index de409c33b250..e701358fd00b 100644 +--- a/drivers/net/ethernet/ti/cpsw_ale.h ++++ b/drivers/net/ethernet/ti/cpsw_ale.h +@@ -88,7 +88,7 @@ void cpsw_ale_stop(struct cpsw_ale *ale); + + int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout); + int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask); +-int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask); ++int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid); + int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, + int flags, u16 vid); + int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port, +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 979fe433278c..32efe8371ff8 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -629,6 +629,7 @@ static int team_change_mode(struct team *team, const char *kind) + static void team_notify_peers_work(struct work_struct *work) + { + struct team *team; ++ int val; + + team = container_of(work, struct team, notify_peers.dw.work); + +@@ -636,9 +637,14 @@ static void team_notify_peers_work(struct work_struct *work) + schedule_delayed_work(&team->notify_peers.dw, 0); + return; + } ++ val = atomic_dec_if_positive(&team->notify_peers.count_pending); ++ if (val < 0) { ++ rtnl_unlock(); ++ return; ++ } + call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, team->dev); + rtnl_unlock(); +- if (!atomic_dec_and_test(&team->notify_peers.count_pending)) ++ if (val) + schedule_delayed_work(&team->notify_peers.dw, + msecs_to_jiffies(team->notify_peers.interval)); + } +@@ -669,6 +675,7 @@ static void team_notify_peers_fini(struct team *team) + static void team_mcast_rejoin_work(struct work_struct *work) + { + struct team *team; ++ int val; + + team = container_of(work, struct team, mcast_rejoin.dw.work); + +@@ -676,9 +683,14 @@ static void team_mcast_rejoin_work(struct work_struct *work) + schedule_delayed_work(&team->mcast_rejoin.dw, 0); + return; + } ++ val = atomic_dec_if_positive(&team->mcast_rejoin.count_pending); ++ if (val < 0) { ++ rtnl_unlock(); ++ return; ++ } + call_netdevice_notifiers(NETDEV_RESEND_IGMP, team->dev); + rtnl_unlock(); +- if (!atomic_dec_and_test(&team->mcast_rejoin.count_pending)) ++ if (val) + schedule_delayed_work(&team->mcast_rejoin.dw, + msecs_to_jiffies(team->mcast_rejoin.interval)); + } +diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c +index 3dc934438c28..07fbcb0fb646 100644 +--- a/drivers/platform/x86/hp_accel.c ++++ b/drivers/platform/x86/hp_accel.c +@@ -237,6 +237,7 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { + AXIS_DMI_MATCH("HPB64xx", "HP ProBook 64", xy_swap), + AXIS_DMI_MATCH("HPB64xx", "HP EliteBook 84", xy_swap), + AXIS_DMI_MATCH("HPB65xx", "HP ProBook 65", x_inverted), ++ AXIS_DMI_MATCH("HPZBook15", "HP ZBook 15", x_inverted), + { NULL, } + /* Laptop models without axis info (yet): + * "NC6910" "HP Compaq 6910" +diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c +index bb86494e2b7b..19915c5b256f 100644 +--- a/drivers/s390/char/con3215.c ++++ b/drivers/s390/char/con3215.c +@@ -288,12 +288,16 @@ static void raw3215_timeout(unsigned long __data) + unsigned long flags; + + spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); +- if (raw->flags & RAW3215_TIMER_RUNS) { +- del_timer(&raw->timer); +- raw->flags &= ~RAW3215_TIMER_RUNS; +- if (!(raw->port.flags & ASYNC_SUSPENDED)) { +- raw3215_mk_write_req(raw); +- raw3215_start_io(raw); ++ raw->flags &= ~RAW3215_TIMER_RUNS; ++ if (!(raw->port.flags & ASYNC_SUSPENDED)) { ++ raw3215_mk_write_req(raw); ++ raw3215_start_io(raw); ++ if ((raw->queued_read || raw->queued_write) && ++ !(raw->flags & RAW3215_WORKING) && ++ !(raw->flags & RAW3215_TIMER_RUNS)) { ++ raw->timer.expires = RAW3215_TIMEOUT + jiffies; ++ add_timer(&raw->timer); ++ raw->flags |= RAW3215_TIMER_RUNS; + } + } + spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); +@@ -317,17 +321,15 @@ static inline void raw3215_try_io(struct raw3215_info *raw) + (raw->flags & RAW3215_FLUSHING)) { + /* execute write requests bigger than minimum size */ + raw3215_start_io(raw); +- if (raw->flags & RAW3215_TIMER_RUNS) { +- del_timer(&raw->timer); +- raw->flags &= ~RAW3215_TIMER_RUNS; +- } +- } else if (!(raw->flags & RAW3215_TIMER_RUNS)) { +- /* delay small writes */ +- raw->timer.expires = RAW3215_TIMEOUT + jiffies; +- add_timer(&raw->timer); +- raw->flags |= RAW3215_TIMER_RUNS; + } + } ++ if ((raw->queued_read || raw->queued_write) && ++ !(raw->flags & RAW3215_WORKING) && ++ !(raw->flags & RAW3215_TIMER_RUNS)) { ++ raw->timer.expires = RAW3215_TIMEOUT + jiffies; ++ add_timer(&raw->timer); ++ raw->flags |= RAW3215_TIMER_RUNS; ++ } + } + + /* +@@ -1027,12 +1029,26 @@ static int tty3215_write(struct tty_struct * tty, + const unsigned char *buf, int count) + { + struct raw3215_info *raw; ++ int i, written; + + if (!tty) + return 0; + raw = (struct raw3215_info *) tty->driver_data; +- raw3215_write(raw, buf, count); +- return count; ++ written = count; ++ while (count > 0) { ++ for (i = 0; i < count; i++) ++ if (buf[i] == '\t' || buf[i] == '\n') ++ break; ++ raw3215_write(raw, buf, i); ++ count -= i; ++ buf += i; ++ if (count > 0) { ++ raw3215_putchar(raw, *buf); ++ count--; ++ buf++; ++ } ++ } ++ return written; + } + + /* +@@ -1180,7 +1196,7 @@ static int __init tty3215_init(void) + driver->subtype = SYSTEM_TYPE_TTY; + driver->init_termios = tty_std_termios; + driver->init_termios.c_iflag = IGNBRK | IGNPAR; +- driver->init_termios.c_oflag = ONLCR | XTABS; ++ driver->init_termios.c_oflag = ONLCR; + driver->init_termios.c_lflag = ISIG; + driver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(driver, &tty3215_ops); +diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c +index 410f4a3e8888..72f9c55d0e00 100644 +--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c ++++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c +@@ -1006,12 +1006,9 @@ mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc, + &mpt2sas_phy->remote_identify); + _transport_add_phy_to_an_existing_port(ioc, sas_node, + mpt2sas_phy, mpt2sas_phy->remote_identify.sas_address); +- } else { ++ } else + memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct + sas_identify)); +- _transport_del_phy_from_an_existing_port(ioc, sas_node, +- mpt2sas_phy); +- } + + if (mpt2sas_phy->phy) + mpt2sas_phy->phy->negotiated_linkrate = +diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c +index 65170cb1a00f..55aa597eb229 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c +@@ -1003,12 +1003,9 @@ mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc, + &mpt3sas_phy->remote_identify); + _transport_add_phy_to_an_existing_port(ioc, sas_node, + mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address); +- } else { ++ } else + memset(&mpt3sas_phy->remote_identify, 0 , sizeof(struct + sas_identify)); +- _transport_del_phy_from_an_existing_port(ioc, sas_node, +- mpt3sas_phy); +- } + + if (mpt3sas_phy->phy) + mpt3sas_phy->phy->negotiated_linkrate = +diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c +index c1d04d4d3c6c..262ab837a704 100644 +--- a/drivers/scsi/scsi_devinfo.c ++++ b/drivers/scsi/scsi_devinfo.c +@@ -211,6 +211,7 @@ static struct { + {"Medion", "Flash XL MMC/SD", "2.6D", BLIST_FORCELUN}, + {"MegaRAID", "LD", NULL, BLIST_FORCELUN}, + {"MICROP", "4110", NULL, BLIST_NOTQ}, ++ {"MSFT", "Virtual HD", NULL, BLIST_NO_RSOC}, + {"MYLEX", "DACARMRB", "*", BLIST_REPORTLUN2}, + {"nCipher", "Fastness Crypto", NULL, BLIST_FORCELUN}, + {"NAKAMICH", "MJ-4.8S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, +diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c +index ed0f899e8aa5..86b05151fdab 100644 +--- a/drivers/scsi/storvsc_drv.c ++++ b/drivers/scsi/storvsc_drv.c +@@ -1690,13 +1690,12 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) + if (ret == -EAGAIN) { + /* no more space */ + +- if (cmd_request->bounce_sgl_count) { ++ if (cmd_request->bounce_sgl_count) + destroy_bounce_buffer(cmd_request->bounce_sgl, + cmd_request->bounce_sgl_count); + +- ret = SCSI_MLQUEUE_DEVICE_BUSY; +- goto queue_error; +- } ++ ret = SCSI_MLQUEUE_DEVICE_BUSY; ++ goto queue_error; + } + + return 0; +diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c +index d509aa74cfa1..c5d3811a7b8c 100644 +--- a/drivers/target/iscsi/iscsi_target_login.c ++++ b/drivers/target/iscsi/iscsi_target_login.c +@@ -1186,6 +1186,9 @@ old_sess_out: + conn->sock = NULL; + } + ++ if (conn->conn_transport->iscsit_wait_conn) ++ conn->conn_transport->iscsit_wait_conn(conn); ++ + if (conn->conn_transport->iscsit_free_conn) + conn->conn_transport->iscsit_free_conn(conn); + +diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c +index ab77f80ead2b..1e406af4ee47 100644 +--- a/drivers/target/iscsi/iscsi_target_util.c ++++ b/drivers/target/iscsi/iscsi_target_util.c +@@ -1356,15 +1356,15 @@ static int iscsit_do_tx_data( + struct iscsi_conn *conn, + struct iscsi_data_count *count) + { +- int data = count->data_length, total_tx = 0, tx_loop = 0, iov_len; ++ int ret, iov_len; + struct kvec *iov_p; + struct msghdr msg; + + if (!conn || !conn->sock || !conn->conn_ops) + return -1; + +- if (data <= 0) { +- pr_err("Data length is: %d\n", data); ++ if (count->data_length <= 0) { ++ pr_err("Data length is: %d\n", count->data_length); + return -1; + } + +@@ -1373,20 +1373,16 @@ static int iscsit_do_tx_data( + iov_p = count->iov; + iov_len = count->iov_count; + +- while (total_tx < data) { +- tx_loop = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len, +- (data - total_tx)); +- if (tx_loop <= 0) { +- pr_debug("tx_loop: %d total_tx %d\n", +- tx_loop, total_tx); +- return tx_loop; +- } +- total_tx += tx_loop; +- pr_debug("tx_loop: %d, total_tx: %d, data: %d\n", +- tx_loop, total_tx, data); ++ ret = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len, ++ count->data_length); ++ if (ret != count->data_length) { ++ pr_err("Unexpected ret: %d send data %d\n", ++ ret, count->data_length); ++ return -EPIPE; + } ++ pr_debug("ret: %d, sent data: %d\n", ret, count->data_length); + +- return total_tx; ++ return ret; + } + + int rx_data( +diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c +index fadad7c5f635..67c802c93ef3 100644 +--- a/drivers/target/loopback/tcm_loop.c ++++ b/drivers/target/loopback/tcm_loop.c +@@ -153,18 +153,11 @@ static int tcm_loop_change_queue_type(struct scsi_device *sdev, int tag) + /* + * Locate the SAM Task Attr from struct scsi_cmnd * + */ +-static int tcm_loop_sam_attr(struct scsi_cmnd *sc) +-{ +- if (sc->device->tagged_supported) { +- switch (sc->tag) { +- case HEAD_OF_QUEUE_TAG: +- return MSG_HEAD_TAG; +- case ORDERED_QUEUE_TAG: +- return MSG_ORDERED_TAG; +- default: +- break; +- } +- } ++static int tcm_loop_sam_attr(struct scsi_cmnd *sc, int tag) ++{ ++ if (sc->device->tagged_supported && ++ sc->device->ordered_tags && tag >= 0) ++ return MSG_ORDERED_TAG; + + return MSG_SIMPLE_TAG; + } +@@ -197,7 +190,7 @@ static void tcm_loop_submission_work(struct work_struct *work) + set_host_byte(sc, DID_TRANSPORT_DISRUPTED); + goto out_done; + } +- tl_nexus = tl_hba->tl_nexus; ++ tl_nexus = tl_tpg->tl_nexus; + if (!tl_nexus) { + scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus" + " does not exist\n"); +@@ -214,7 +207,7 @@ static void tcm_loop_submission_work(struct work_struct *work) + } + rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus->se_sess, sc->cmnd, + &tl_cmd->tl_sense_buf[0], tl_cmd->sc->device->lun, +- scsi_bufflen(sc), tcm_loop_sam_attr(sc), ++ scsi_bufflen(sc), tcm_loop_sam_attr(sc, tl_cmd->sc_cmd_tag), + sc->sc_data_direction, 0, + scsi_sglist(sc), scsi_sg_count(sc), + sgl_bidi, sgl_bidi_count, +@@ -252,7 +245,7 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc) + } + + tl_cmd->sc = sc; +- tl_cmd->sc_cmd_tag = sc->tag; ++ tl_cmd->sc_cmd_tag = sc->request->tag; + INIT_WORK(&tl_cmd->work, tcm_loop_submission_work); + queue_work(tcm_loop_workqueue, &tl_cmd->work); + return 0; +@@ -263,16 +256,26 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc) + * to struct scsi_device + */ + static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg, +- struct tcm_loop_nexus *tl_nexus, + int lun, int task, enum tcm_tmreq_table tmr) + { + struct se_cmd *se_cmd = NULL; + struct se_session *se_sess; + struct se_portal_group *se_tpg; ++ struct tcm_loop_nexus *tl_nexus; + struct tcm_loop_cmd *tl_cmd = NULL; + struct tcm_loop_tmr *tl_tmr = NULL; + int ret = TMR_FUNCTION_FAILED, rc; + ++ /* ++ * Locate the tl_nexus and se_sess pointers ++ */ ++ tl_nexus = tl_tpg->tl_nexus; ++ if (!tl_nexus) { ++ pr_err("Unable to perform device reset without" ++ " active I_T Nexus\n"); ++ return ret; ++ } ++ + tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_KERNEL); + if (!tl_cmd) { + pr_err("Unable to allocate memory for tl_cmd\n"); +@@ -288,7 +291,7 @@ static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg, + + se_cmd = &tl_cmd->tl_se_cmd; + se_tpg = &tl_tpg->tl_se_tpg; +- se_sess = tl_nexus->se_sess; ++ se_sess = tl_tpg->tl_nexus->se_sess; + /* + * Initialize struct se_cmd descriptor from target_core_mod infrastructure + */ +@@ -333,7 +336,6 @@ release: + static int tcm_loop_abort_task(struct scsi_cmnd *sc) + { + struct tcm_loop_hba *tl_hba; +- struct tcm_loop_nexus *tl_nexus; + struct tcm_loop_tpg *tl_tpg; + int ret = FAILED; + +@@ -341,22 +343,9 @@ static int tcm_loop_abort_task(struct scsi_cmnd *sc) + * Locate the tcm_loop_hba_t pointer + */ + tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); +- /* +- * Locate the tl_nexus and se_sess pointers +- */ +- tl_nexus = tl_hba->tl_nexus; +- if (!tl_nexus) { +- pr_err("Unable to perform device reset without" +- " active I_T Nexus\n"); +- return FAILED; +- } +- +- /* +- * Locate the tl_tpg pointer from TargetID in sc->device->id +- */ + tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; +- ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun, +- sc->tag, TMR_ABORT_TASK); ++ ret = tcm_loop_issue_tmr(tl_tpg, sc->device->lun, ++ sc->request->tag, TMR_ABORT_TASK); + return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED; + } + +@@ -367,7 +356,6 @@ static int tcm_loop_abort_task(struct scsi_cmnd *sc) + static int tcm_loop_device_reset(struct scsi_cmnd *sc) + { + struct tcm_loop_hba *tl_hba; +- struct tcm_loop_nexus *tl_nexus; + struct tcm_loop_tpg *tl_tpg; + int ret = FAILED; + +@@ -375,20 +363,9 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc) + * Locate the tcm_loop_hba_t pointer + */ + tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); +- /* +- * Locate the tl_nexus and se_sess pointers +- */ +- tl_nexus = tl_hba->tl_nexus; +- if (!tl_nexus) { +- pr_err("Unable to perform device reset without" +- " active I_T Nexus\n"); +- return FAILED; +- } +- /* +- * Locate the tl_tpg pointer from TargetID in sc->device->id +- */ + tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; +- ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun, ++ ++ ret = tcm_loop_issue_tmr(tl_tpg, sc->device->lun, + 0, TMR_LUN_RESET); + return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED; + } +@@ -995,8 +972,8 @@ static int tcm_loop_make_nexus( + struct tcm_loop_nexus *tl_nexus; + int ret = -ENOMEM; + +- if (tl_tpg->tl_hba->tl_nexus) { +- pr_debug("tl_tpg->tl_hba->tl_nexus already exists\n"); ++ if (tl_tpg->tl_nexus) { ++ pr_debug("tl_tpg->tl_nexus already exists\n"); + return -EEXIST; + } + se_tpg = &tl_tpg->tl_se_tpg; +@@ -1031,7 +1008,7 @@ static int tcm_loop_make_nexus( + */ + __transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl, + tl_nexus->se_sess, tl_nexus); +- tl_tpg->tl_hba->tl_nexus = tl_nexus; ++ tl_tpg->tl_nexus = tl_nexus; + pr_debug("TCM_Loop_ConfigFS: Established I_T Nexus to emulated" + " %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba), + name); +@@ -1047,12 +1024,8 @@ static int tcm_loop_drop_nexus( + { + struct se_session *se_sess; + struct tcm_loop_nexus *tl_nexus; +- struct tcm_loop_hba *tl_hba = tpg->tl_hba; + +- if (!tl_hba) +- return -ENODEV; +- +- tl_nexus = tl_hba->tl_nexus; ++ tl_nexus = tpg->tl_nexus; + if (!tl_nexus) + return -ENODEV; + +@@ -1068,13 +1041,13 @@ static int tcm_loop_drop_nexus( + } + + pr_debug("TCM_Loop_ConfigFS: Removing I_T Nexus to emulated" +- " %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba), ++ " %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tpg->tl_hba), + tl_nexus->se_sess->se_node_acl->initiatorname); + /* + * Release the SCSI I_T Nexus to the emulated SAS Target Port + */ + transport_deregister_session(tl_nexus->se_sess); +- tpg->tl_hba->tl_nexus = NULL; ++ tpg->tl_nexus = NULL; + kfree(tl_nexus); + return 0; + } +@@ -1090,7 +1063,7 @@ static ssize_t tcm_loop_tpg_show_nexus( + struct tcm_loop_nexus *tl_nexus; + ssize_t ret; + +- tl_nexus = tl_tpg->tl_hba->tl_nexus; ++ tl_nexus = tl_tpg->tl_nexus; + if (!tl_nexus) + return -ENODEV; + +diff --git a/drivers/target/loopback/tcm_loop.h b/drivers/target/loopback/tcm_loop.h +index 54c59d0b6608..6ae49f272ba6 100644 +--- a/drivers/target/loopback/tcm_loop.h ++++ b/drivers/target/loopback/tcm_loop.h +@@ -27,11 +27,6 @@ struct tcm_loop_tmr { + }; + + struct tcm_loop_nexus { +- int it_nexus_active; +- /* +- * Pointer to Linux/SCSI HBA from linux/include/scsi_host.h +- */ +- struct scsi_host *sh; + /* + * Pointer to TCM session for I_T Nexus + */ +@@ -51,6 +46,7 @@ struct tcm_loop_tpg { + atomic_t tl_tpg_port_count; + struct se_portal_group tl_se_tpg; + struct tcm_loop_hba *tl_hba; ++ struct tcm_loop_nexus *tl_nexus; + }; + + struct tcm_loop_hba { +@@ -59,7 +55,6 @@ struct tcm_loop_hba { + struct se_hba_s *se_hba; + struct se_lun *tl_hba_lun; + struct se_port *tl_hba_lun_sep; +- struct tcm_loop_nexus *tl_nexus; + struct device dev; + struct Scsi_Host *sh; + struct tcm_loop_tpg tl_hba_tpgs[TL_TPGS_PER_HBA]; +diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c +index a084325f1386..6e75177915fa 100644 +--- a/drivers/thermal/intel_powerclamp.c ++++ b/drivers/thermal/intel_powerclamp.c +@@ -435,7 +435,6 @@ static int clamp_thread(void *arg) + * allowed. thus jiffies are updated properly. + */ + preempt_disable(); +- tick_nohz_idle_enter(); + /* mwait until target jiffies is reached */ + while (time_before(jiffies, target_jiffies)) { + unsigned long ecx = 1; +@@ -451,7 +450,6 @@ static int clamp_thread(void *arg) + start_critical_timings(); + atomic_inc(&idle_wakeup_counter); + } +- tick_nohz_idle_exit(); + preempt_enable(); + } + del_timer_sync(&wakeup_timer); +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index d90c70c23adb..8f6738d46b14 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -887,8 +887,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) + + if (i == (request->num_mapped_sgs - 1) || + sg_is_last(s)) { +- if (list_is_last(&req->list, +- &dep->request_list)) ++ if (list_empty(&dep->request_list)) + last_one = true; + chain = false; + } +@@ -906,6 +905,9 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) + if (last_one) + break; + } ++ ++ if (last_one) ++ break; + } else { + dma = req->request.dma; + length = req->request.length; +diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c +index e113fd73aeae..c399606f154e 100644 +--- a/drivers/usb/host/ehci-sched.c ++++ b/drivers/usb/host/ehci-sched.c +@@ -1581,6 +1581,10 @@ iso_stream_schedule ( + else + next = (now + 2 + 7) & ~0x07; /* full frame cache */ + ++ /* If needed, initialize last_iso_frame so that this URB will be seen */ ++ if (ehci->isoc_count == 0) ++ ehci->last_iso_frame = now >> 3; ++ + /* + * Use ehci->last_iso_frame as the base. There can't be any + * TDs scheduled for earlier than that. +@@ -1671,10 +1675,6 @@ iso_stream_schedule ( + urb->start_frame = start & (mod - 1); + if (!stream->highspeed) + urb->start_frame >>= 3; +- +- /* Make sure scan_isoc() sees these */ +- if (ehci->isoc_count == 0) +- ehci->last_iso_frame = now >> 3; + return status; + + fail: +diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c +index 2f3acebb577a..f4e6b945136c 100644 +--- a/drivers/usb/host/pci-quirks.c ++++ b/drivers/usb/host/pci-quirks.c +@@ -571,7 +571,8 @@ static void quirk_usb_handoff_ohci(struct pci_dev *pdev) + { + void __iomem *base; + u32 control; +- u32 fminterval; ++ u32 fminterval = 0; ++ bool no_fminterval = false; + int cnt; + + if (!mmio_resource_enabled(pdev, 0)) +@@ -581,6 +582,13 @@ static void quirk_usb_handoff_ohci(struct pci_dev *pdev) + if (base == NULL) + return; + ++ /* ++ * ULi M5237 OHCI controller locks the whole system when accessing ++ * the OHCI_FMINTERVAL offset. ++ */ ++ if (pdev->vendor == PCI_VENDOR_ID_AL && pdev->device == 0x5237) ++ no_fminterval = true; ++ + control = readl(base + OHCI_CONTROL); + + /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ +@@ -619,7 +627,9 @@ static void quirk_usb_handoff_ohci(struct pci_dev *pdev) + } + + /* software reset of the controller, preserving HcFmInterval */ +- fminterval = readl(base + OHCI_FMINTERVAL); ++ if (!no_fminterval) ++ fminterval = readl(base + OHCI_FMINTERVAL); ++ + writel(OHCI_HCR, base + OHCI_CMDSTATUS); + + /* reset requires max 10 us delay */ +@@ -628,7 +638,9 @@ static void quirk_usb_handoff_ohci(struct pci_dev *pdev) + break; + udelay(1); + } +- writel(fminterval, base + OHCI_FMINTERVAL); ++ ++ if (!no_fminterval) ++ writel(fminterval, base + OHCI_FMINTERVAL); + + /* Now the controller is safely in SUSPEND and nothing can wake it up */ + iounmap(base); +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index abb38c3833ef..6b0fb6af6815 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -2640,7 +2640,6 @@ void musb_host_cleanup(struct musb *musb) + if (musb->port_mode == MUSB_PORT_MODE_GADGET) + return; + usb_remove_hcd(musb->hcd); +- musb->hcd = NULL; + } + + void musb_host_free(struct musb *musb) +diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c +index 8d7fc48b1f30..29fa1c3d0089 100644 +--- a/drivers/usb/serial/console.c ++++ b/drivers/usb/serial/console.c +@@ -46,6 +46,8 @@ static struct console usbcons; + * ------------------------------------------------------------ + */ + ++static const struct tty_operations usb_console_fake_tty_ops = { ++}; + + /* + * The parsing of the command line works exactly like the +@@ -137,13 +139,17 @@ static int usb_console_setup(struct console *co, char *options) + goto reset_open_count; + } + kref_init(&tty->kref); +- tty_port_tty_set(&port->port, tty); + tty->driver = usb_serial_tty_driver; + tty->index = co->index; ++ init_ldsem(&tty->ldisc_sem); ++ INIT_LIST_HEAD(&tty->tty_files); ++ kref_get(&tty->driver->kref); ++ tty->ops = &usb_console_fake_tty_ops; + if (tty_init_termios(tty)) { + retval = -ENOMEM; +- goto free_tty; ++ goto put_tty; + } ++ tty_port_tty_set(&port->port, tty); + } + + /* only call the device specific open if this +@@ -161,7 +167,7 @@ static int usb_console_setup(struct console *co, char *options) + serial->type->set_termios(tty, port, &dummy); + + tty_port_tty_set(&port->port, NULL); +- kfree(tty); ++ tty_kref_put(tty); + } + set_bit(ASYNCB_INITIALIZED, &port->port.flags); + } +@@ -177,8 +183,8 @@ static int usb_console_setup(struct console *co, char *options) + + fail: + tty_port_tty_set(&port->port, NULL); +- free_tty: +- kfree(tty); ++ put_tty: ++ tty_kref_put(tty); + reset_open_count: + port->port.count = 0; + usb_autopm_put_interface(serial->interface); +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 5741e9405069..9e8708c5cbfa 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -120,10 +120,12 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */ + { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */ + { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ +- { USB_DEVICE(0x10C4, 0x8875) }, /* CEL MeshConnect USB Stick */ ++ { USB_DEVICE(0x10C4, 0x8856) }, /* CEL EM357 ZigBee USB Stick - LR */ ++ { USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */ + { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */ ++ { USB_DEVICE(0x10C4, 0x8977) }, /* CEL MeshWorks DevKit Device */ + { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ +diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c +index 49101fe45d38..35297a845a63 100644 +--- a/drivers/usb/serial/keyspan.c ++++ b/drivers/usb/serial/keyspan.c +@@ -421,6 +421,8 @@ static void usa26_instat_callback(struct urb *urb) + } + port = serial->port[msg->port]; + p_priv = usb_get_serial_port_data(port); ++ if (!p_priv) ++ goto resubmit; + + /* Update handshaking pin state information */ + old_dcd_state = p_priv->dcd_state; +@@ -431,7 +433,7 @@ static void usa26_instat_callback(struct urb *urb) + + if (old_dcd_state != p_priv->dcd_state) + tty_port_tty_hangup(&port->port, true); +- ++resubmit: + /* Resubmit urb so we continue receiving */ + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) +@@ -541,6 +543,8 @@ static void usa28_instat_callback(struct urb *urb) + } + port = serial->port[msg->port]; + p_priv = usb_get_serial_port_data(port); ++ if (!p_priv) ++ goto resubmit; + + /* Update handshaking pin state information */ + old_dcd_state = p_priv->dcd_state; +@@ -551,7 +555,7 @@ static void usa28_instat_callback(struct urb *urb) + + if (old_dcd_state != p_priv->dcd_state && old_dcd_state) + tty_port_tty_hangup(&port->port, true); +- ++resubmit: + /* Resubmit urb so we continue receiving */ + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) +@@ -624,6 +628,8 @@ static void usa49_instat_callback(struct urb *urb) + } + port = serial->port[msg->portNumber]; + p_priv = usb_get_serial_port_data(port); ++ if (!p_priv) ++ goto resubmit; + + /* Update handshaking pin state information */ + old_dcd_state = p_priv->dcd_state; +@@ -634,7 +640,7 @@ static void usa49_instat_callback(struct urb *urb) + + if (old_dcd_state != p_priv->dcd_state && old_dcd_state) + tty_port_tty_hangup(&port->port, true); +- ++resubmit: + /* Resubmit urb so we continue receiving */ + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) +@@ -872,6 +878,8 @@ static void usa90_instat_callback(struct urb *urb) + + port = serial->port[0]; + p_priv = usb_get_serial_port_data(port); ++ if (!p_priv) ++ goto resubmit; + + /* Update handshaking pin state information */ + old_dcd_state = p_priv->dcd_state; +@@ -882,7 +890,7 @@ static void usa90_instat_callback(struct urb *urb) + + if (old_dcd_state != p_priv->dcd_state && old_dcd_state) + tty_port_tty_hangup(&port->port, true); +- ++resubmit: + /* Resubmit urb so we continue receiving */ + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) +@@ -943,6 +951,8 @@ static void usa67_instat_callback(struct urb *urb) + + port = serial->port[msg->port]; + p_priv = usb_get_serial_port_data(port); ++ if (!p_priv) ++ goto resubmit; + + /* Update handshaking pin state information */ + old_dcd_state = p_priv->dcd_state; +@@ -951,7 +961,7 @@ static void usa67_instat_callback(struct urb *urb) + + if (old_dcd_state != p_priv->dcd_state && old_dcd_state) + tty_port_tty_hangup(&port->port, true); +- ++resubmit: + /* Resubmit urb so we continue receiving */ + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) +diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c +index 7ba042498857..75e1d03b8da3 100644 +--- a/drivers/vfio/pci/vfio_pci.c ++++ b/drivers/vfio/pci/vfio_pci.c +@@ -810,13 +810,11 @@ static const struct vfio_device_ops vfio_pci_ops = { + + static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + { +- u8 type; + struct vfio_pci_device *vdev; + struct iommu_group *group; + int ret; + +- pci_read_config_byte(pdev, PCI_HEADER_TYPE, &type); +- if ((type & PCI_HEADER_TYPE) != PCI_HEADER_TYPE_NORMAL) ++ if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL) + return -EINVAL; + + group = iommu_group_get(&pdev->dev); +diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c +index 5d0b7b846440..486d710a5293 100644 +--- a/drivers/vhost/scsi.c ++++ b/drivers/vhost/scsi.c +@@ -861,6 +861,23 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd, + return 0; + } + ++static int vhost_scsi_to_tcm_attr(int attr) ++{ ++ switch (attr) { ++ case VIRTIO_SCSI_S_SIMPLE: ++ return MSG_SIMPLE_TAG; ++ case VIRTIO_SCSI_S_ORDERED: ++ return MSG_ORDERED_TAG; ++ case VIRTIO_SCSI_S_HEAD: ++ return MSG_HEAD_TAG; ++ case VIRTIO_SCSI_S_ACA: ++ return MSG_ACA_TAG; ++ default: ++ break; ++ } ++ return MSG_SIMPLE_TAG; ++} ++ + static void tcm_vhost_submission_work(struct work_struct *work) + { + struct tcm_vhost_cmd *cmd = +@@ -887,9 +904,10 @@ static void tcm_vhost_submission_work(struct work_struct *work) + rc = target_submit_cmd_map_sgls(se_cmd, tv_nexus->tvn_se_sess, + cmd->tvc_cdb, &cmd->tvc_sense_buf[0], + cmd->tvc_lun, cmd->tvc_exp_data_len, +- cmd->tvc_task_attr, cmd->tvc_data_direction, +- TARGET_SCF_ACK_KREF, sg_ptr, cmd->tvc_sgl_count, +- sg_bidi_ptr, sg_no_bidi, NULL, 0); ++ vhost_scsi_to_tcm_attr(cmd->tvc_task_attr), ++ cmd->tvc_data_direction, TARGET_SCF_ACK_KREF, ++ sg_ptr, cmd->tvc_sgl_count, sg_bidi_ptr, sg_no_bidi, ++ NULL, 0); + if (rc < 0) { + transport_send_check_condition_and_sense(se_cmd, + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0); +diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c +index b670cbda38e3..ffe024b830fc 100644 +--- a/drivers/video/logo/logo.c ++++ b/drivers/video/logo/logo.c +@@ -21,6 +21,21 @@ static bool nologo; + module_param(nologo, bool, 0); + MODULE_PARM_DESC(nologo, "Disables startup logo"); + ++/* ++ * Logos are located in the initdata, and will be freed in kernel_init. ++ * Use late_init to mark the logos as freed to prevent any further use. ++ */ ++ ++static bool logos_freed; ++ ++static int __init fb_logo_late_init(void) ++{ ++ logos_freed = true; ++ return 0; ++} ++ ++late_initcall(fb_logo_late_init); ++ + /* logo's are marked __initdata. Use __init_refok to tell + * modpost that it is intended that this function uses data + * marked __initdata. +@@ -29,7 +44,7 @@ const struct linux_logo * __init_refok fb_find_logo(int depth) + { + const struct linux_logo *logo = NULL; + +- if (nologo) ++ if (nologo || logos_freed) + return NULL; + + if (depth >= 1) { +diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c +index 223e1cb14345..59a53f664005 100644 +--- a/fs/lockd/svc.c ++++ b/fs/lockd/svc.c +@@ -137,10 +137,6 @@ lockd(void *vrqstp) + + dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n"); + +- if (!nlm_timeout) +- nlm_timeout = LOCKD_DFLT_TIMEO; +- nlmsvc_timeout = nlm_timeout * HZ; +- + /* + * The main request loop. We don't terminate until the last + * NFS mount or NFS daemon has gone away. +@@ -346,6 +342,10 @@ static struct svc_serv *lockd_create_svc(void) + printk(KERN_WARNING + "lockd_up: no pid, %d users??\n", nlmsvc_users); + ++ if (!nlm_timeout) ++ nlm_timeout = LOCKD_DFLT_TIMEO; ++ nlmsvc_timeout = nlm_timeout * HZ; ++ + serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL); + if (!serv) { + printk(KERN_WARNING "lockd_up: create service failed\n"); +diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c +index 1abe4f55dea2..037f9572b94c 100644 +--- a/fs/nfs/nfs4client.c ++++ b/fs/nfs/nfs4client.c +@@ -565,20 +565,14 @@ static bool nfs4_match_clientids(struct nfs_client *a, struct nfs_client *b) + } + + /* +- * Returns true if the server owners match ++ * Returns true if the server major ids match + */ + static bool +-nfs4_match_serverowners(struct nfs_client *a, struct nfs_client *b) ++nfs4_check_clientid_trunking(struct nfs_client *a, struct nfs_client *b) + { + struct nfs41_server_owner *o1 = a->cl_serverowner; + struct nfs41_server_owner *o2 = b->cl_serverowner; + +- if (o1->minor_id != o2->minor_id) { +- dprintk("NFS: --> %s server owner minor IDs do not match\n", +- __func__); +- return false; +- } +- + if (o1->major_id_sz != o2->major_id_sz) + goto out_major_mismatch; + if (memcmp(o1->major_id, o2->major_id, o1->major_id_sz) != 0) +@@ -654,7 +648,12 @@ int nfs41_walk_client_list(struct nfs_client *new, + if (!nfs4_match_clientids(pos, new)) + continue; + +- if (!nfs4_match_serverowners(pos, new)) ++ /* ++ * Note that session trunking is just a special subcase of ++ * client id trunking. In either case, we want to fall back ++ * to using the existing nfs_client. ++ */ ++ if (!nfs4_check_clientid_trunking(pos, new)) + continue; + + atomic_inc(&pos->cl_count); +diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c +index 74825be65b7b..fbb9dfb7b1d2 100644 +--- a/fs/notify/inode_mark.c ++++ b/fs/notify/inode_mark.c +@@ -288,20 +288,25 @@ void fsnotify_unmount_inodes(struct list_head *list) + spin_unlock(&inode->i_lock); + + /* In case the dropping of a reference would nuke next_i. */ +- if ((&next_i->i_sb_list != list) && +- atomic_read(&next_i->i_count)) { ++ while (&next_i->i_sb_list != list) { + spin_lock(&next_i->i_lock); +- if (!(next_i->i_state & (I_FREEING | I_WILL_FREE))) { ++ if (!(next_i->i_state & (I_FREEING | I_WILL_FREE)) && ++ atomic_read(&next_i->i_count)) { + __iget(next_i); + need_iput = next_i; ++ spin_unlock(&next_i->i_lock); ++ break; + } + spin_unlock(&next_i->i_lock); ++ next_i = list_entry(next_i->i_sb_list.next, ++ struct inode, i_sb_list); + } + + /* +- * We can safely drop inode_sb_list_lock here because we hold +- * references on both inode and next_i. Also no new inodes +- * will be added since the umount has begun. ++ * We can safely drop inode_sb_list_lock here because either ++ * we actually hold references on both inode and next_i or ++ * end of list. Also no new inodes will be added since the ++ * umount has begun. + */ + spin_unlock(&inode_sb_list_lock); + +diff --git a/fs/proc/stat.c b/fs/proc/stat.c +index 6f599c62f0cc..dbd027235440 100644 +--- a/fs/proc/stat.c ++++ b/fs/proc/stat.c +@@ -159,7 +159,7 @@ static int show_stat(struct seq_file *p, void *v) + + /* sum again ? it could be updated? */ + for_each_irq_nr(j) +- seq_put_decimal_ull(p, ' ', kstat_irqs(j)); ++ seq_put_decimal_ull(p, ' ', kstat_irqs_usr(j)); + + seq_printf(p, + "\nctxt %llu\n" +diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h +index 51c72be4a7c3..4b2053a232c9 100644 +--- a/include/linux/kernel_stat.h ++++ b/include/linux/kernel_stat.h +@@ -74,6 +74,7 @@ static inline unsigned int kstat_softirqs_cpu(unsigned int irq, int cpu) + * Number of interrupts per specific IRQ source, since bootup + */ + extern unsigned int kstat_irqs(unsigned int irq); ++extern unsigned int kstat_irqs_usr(unsigned int irq); + + /* + * Number of interrupts per cpu, since bootup +diff --git a/include/uapi/linux/in6.h b/include/uapi/linux/in6.h +index e9a1d2d973b6..4c399ae04677 100644 +--- a/include/uapi/linux/in6.h ++++ b/include/uapi/linux/in6.h +@@ -149,7 +149,7 @@ struct in6_flowlabel_req { + /* + * IPV6 socket options + */ +- ++#if __UAPI_DEF_IPV6_OPTIONS + #define IPV6_ADDRFORM 1 + #define IPV6_2292PKTINFO 2 + #define IPV6_2292HOPOPTS 3 +@@ -192,6 +192,7 @@ struct in6_flowlabel_req { + + #define IPV6_IPSEC_POLICY 34 + #define IPV6_XFRM_POLICY 35 ++#endif + + /* + * Multicast: +diff --git a/include/uapi/linux/libc-compat.h b/include/uapi/linux/libc-compat.h +index c140620dad92..e28807ad17fa 100644 +--- a/include/uapi/linux/libc-compat.h ++++ b/include/uapi/linux/libc-compat.h +@@ -69,6 +69,7 @@ + #define __UAPI_DEF_SOCKADDR_IN6 0 + #define __UAPI_DEF_IPV6_MREQ 0 + #define __UAPI_DEF_IPPROTO_V6 0 ++#define __UAPI_DEF_IPV6_OPTIONS 0 + + #else + +@@ -82,6 +83,7 @@ + #define __UAPI_DEF_SOCKADDR_IN6 1 + #define __UAPI_DEF_IPV6_MREQ 1 + #define __UAPI_DEF_IPPROTO_V6 1 ++#define __UAPI_DEF_IPV6_OPTIONS 1 + + #endif /* _NETINET_IN_H */ + +@@ -103,6 +105,7 @@ + #define __UAPI_DEF_SOCKADDR_IN6 1 + #define __UAPI_DEF_IPV6_MREQ 1 + #define __UAPI_DEF_IPPROTO_V6 1 ++#define __UAPI_DEF_IPV6_OPTIONS 1 + + /* Definitions for xattr.h */ + #define __UAPI_DEF_XATTR 1 +diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h +index 001fa5bab490..8a160e8a44e8 100644 +--- a/kernel/irq/internals.h ++++ b/kernel/irq/internals.h +@@ -74,6 +74,14 @@ extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu); + extern void mask_irq(struct irq_desc *desc); + extern void unmask_irq(struct irq_desc *desc); + ++#ifdef CONFIG_SPARSE_IRQ ++extern void irq_lock_sparse(void); ++extern void irq_unlock_sparse(void); ++#else ++static inline void irq_lock_sparse(void) { } ++static inline void irq_unlock_sparse(void) { } ++#endif ++ + extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr); + + irqreturn_t handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action); +diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c +index 8ab8e9390297..07d45516b540 100644 +--- a/kernel/irq/irqdesc.c ++++ b/kernel/irq/irqdesc.c +@@ -131,6 +131,16 @@ static void free_masks(struct irq_desc *desc) + static inline void free_masks(struct irq_desc *desc) { } + #endif + ++void irq_lock_sparse(void) ++{ ++ mutex_lock(&sparse_irq_lock); ++} ++ ++void irq_unlock_sparse(void) ++{ ++ mutex_unlock(&sparse_irq_lock); ++} ++ + static struct irq_desc *alloc_desc(int irq, int node, struct module *owner) + { + struct irq_desc *desc; +@@ -167,6 +177,12 @@ static void free_desc(unsigned int irq) + + unregister_irq_proc(irq, desc); + ++ /* ++ * sparse_irq_lock protects also show_interrupts() and ++ * kstat_irq_usr(). Once we deleted the descriptor from the ++ * sparse tree we can free it. Access in proc will fail to ++ * lookup the descriptor. ++ */ + mutex_lock(&sparse_irq_lock); + delete_irq_desc(irq); + mutex_unlock(&sparse_irq_lock); +@@ -489,6 +505,15 @@ void dynamic_irq_cleanup(unsigned int irq) + raw_spin_unlock_irqrestore(&desc->lock, flags); + } + ++/** ++ * kstat_irqs_cpu - Get the statistics for an interrupt on a cpu ++ * @irq: The interrupt number ++ * @cpu: The cpu number ++ * ++ * Returns the sum of interrupt counts on @cpu since boot for ++ * @irq. The caller must ensure that the interrupt is not removed ++ * concurrently. ++ */ + unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) + { + struct irq_desc *desc = irq_to_desc(irq); +@@ -497,6 +522,14 @@ unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) + *per_cpu_ptr(desc->kstat_irqs, cpu) : 0; + } + ++/** ++ * kstat_irqs - Get the statistics for an interrupt ++ * @irq: The interrupt number ++ * ++ * Returns the sum of interrupt counts on all cpus since boot for ++ * @irq. The caller must ensure that the interrupt is not removed ++ * concurrently. ++ */ + unsigned int kstat_irqs(unsigned int irq) + { + struct irq_desc *desc = irq_to_desc(irq); +@@ -509,3 +542,22 @@ unsigned int kstat_irqs(unsigned int irq) + sum += *per_cpu_ptr(desc->kstat_irqs, cpu); + return sum; + } ++ ++/** ++ * kstat_irqs_usr - Get the statistics for an interrupt ++ * @irq: The interrupt number ++ * ++ * Returns the sum of interrupt counts on all cpus since boot for ++ * @irq. Contrary to kstat_irqs() this can be called from any ++ * preemptible context. It's protected against concurrent removal of ++ * an interrupt descriptor when sparse irqs are enabled. ++ */ ++unsigned int kstat_irqs_usr(unsigned int irq) ++{ ++ int sum; ++ ++ irq_lock_sparse(); ++ sum = kstat_irqs(irq); ++ irq_unlock_sparse(); ++ return sum; ++} +diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c +index 36f6ee181b0c..095cd7230aef 100644 +--- a/kernel/irq/proc.c ++++ b/kernel/irq/proc.c +@@ -15,6 +15,23 @@ + + #include "internals.h" + ++/* ++ * Access rules: ++ * ++ * procfs protects read/write of /proc/irq/N/ files against a ++ * concurrent free of the interrupt descriptor. remove_proc_entry() ++ * immediately prevents new read/writes to happen and waits for ++ * already running read/write functions to complete. ++ * ++ * We remove the proc entries first and then delete the interrupt ++ * descriptor from the radix tree and free it. So it is guaranteed ++ * that irq_to_desc(N) is valid as long as the read/writes are ++ * permitted by procfs. ++ * ++ * The read from /proc/interrupts is a different problem because there ++ * is no protection. So the lookup and the access to irqdesc ++ * information must be protected by sparse_irq_lock. ++ */ + static struct proc_dir_entry *root_irq_dir; + + #ifdef CONFIG_SMP +@@ -437,9 +454,10 @@ int show_interrupts(struct seq_file *p, void *v) + seq_putc(p, '\n'); + } + ++ irq_lock_sparse(); + desc = irq_to_desc(i); + if (!desc) +- return 0; ++ goto outsparse; + + raw_spin_lock_irqsave(&desc->lock, flags); + for_each_online_cpu(j) +@@ -479,6 +497,8 @@ int show_interrupts(struct seq_file *p, void *v) + seq_putc(p, '\n'); + out: + raw_spin_unlock_irqrestore(&desc->lock, flags); ++outsparse: ++ irq_unlock_sparse(); + return 0; + } + #endif +diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c +index 6558b7ac112d..8c08a6f9cca0 100644 +--- a/kernel/time/tick-sched.c ++++ b/kernel/time/tick-sched.c +@@ -807,7 +807,6 @@ void tick_nohz_idle_enter(void) + + local_irq_enable(); + } +-EXPORT_SYMBOL_GPL(tick_nohz_idle_enter); + + /** + * tick_nohz_irq_exit - update next tick event from interrupt exit +@@ -934,7 +933,6 @@ void tick_nohz_idle_exit(void) + + local_irq_enable(); + } +-EXPORT_SYMBOL_GPL(tick_nohz_idle_exit); + + static int tick_nohz_reprogram(struct tick_sched *ts, ktime_t now) + { +diff --git a/lib/decompress_bunzip2.c b/lib/decompress_bunzip2.c +index 31c5f7675fbf..f504027d66a8 100644 +--- a/lib/decompress_bunzip2.c ++++ b/lib/decompress_bunzip2.c +@@ -184,7 +184,7 @@ static int INIT get_next_block(struct bunzip_data *bd) + if (get_bits(bd, 1)) + return RETVAL_OBSOLETE_INPUT; + origPtr = get_bits(bd, 24); +- if (origPtr > dbufSize) ++ if (origPtr >= dbufSize) + return RETVAL_DATA_ERROR; + /* mapping table: if some byte values are never used (encoding things + like ascii text), the compression code removes the gaps to have fewer +diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c +index c46387a46535..e5c5f573c0d4 100644 +--- a/net/batman-adv/fragmentation.c ++++ b/net/batman-adv/fragmentation.c +@@ -251,7 +251,7 @@ batadv_frag_merge_packets(struct hlist_head *chain, struct sk_buff *skb) + kfree(entry); + + /* Make room for the rest of the fragments. */ +- if (pskb_expand_head(skb_out, 0, size - skb->len, GFP_ATOMIC) < 0) { ++ if (pskb_expand_head(skb_out, 0, size - skb_out->len, GFP_ATOMIC) < 0) { + kfree_skb(skb_out); + skb_out = NULL; + goto free; +@@ -434,7 +434,7 @@ bool batadv_frag_send_packet(struct sk_buff *skb, + * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE + */ + mtu = min_t(unsigned, mtu, BATADV_FRAG_MAX_FRAG_SIZE); +- max_fragment_size = (mtu - header_size - ETH_HLEN); ++ max_fragment_size = mtu - header_size; + max_packet_size = max_fragment_size * BATADV_FRAG_MAX_FRAGMENTS; + + /* Don't even try to fragment, if we need more than 16 fragments */ +diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c +index 36b9ae61f5e8..2393ea72d65f 100644 +--- a/net/batman-adv/gateway_client.c ++++ b/net/batman-adv/gateway_client.c +@@ -812,7 +812,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, + goto out; + + gw_node = batadv_gw_node_get(bat_priv, orig_dst_node); +- if (!gw_node->bandwidth_down == 0) ++ if (!gw_node) + goto out; + + switch (atomic_read(&bat_priv->gw_mode)) { +diff --git a/net/core/dev.c b/net/core/dev.c +index 3ed11a555834..86bb9cc81f02 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1709,6 +1709,7 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) + + skb_scrub_packet(skb, true); + skb->protocol = eth_type_trans(skb, dev); ++ skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); + + return netif_rx_internal(skb); + } +@@ -2529,11 +2530,14 @@ netdev_features_t netif_skb_dev_features(struct sk_buff *skb, + if (skb_shinfo(skb)->gso_segs > dev->gso_max_segs) + features &= ~NETIF_F_GSO_MASK; + +- if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) { +- struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; +- protocol = veh->h_vlan_encapsulated_proto; +- } else if (!vlan_tx_tag_present(skb)) { +- return harmonize_features(skb, dev, features); ++ if (!vlan_tx_tag_present(skb)) { ++ if (unlikely(protocol == htons(ETH_P_8021Q) || ++ protocol == htons(ETH_P_8021AD))) { ++ struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; ++ protocol = veh->h_vlan_encapsulated_proto; ++ } else { ++ return harmonize_features(skb, dev, features); ++ } + } + + features &= (dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX | +@@ -4701,9 +4705,14 @@ static void netdev_adjacent_sysfs_del(struct net_device *dev, + sysfs_remove_link(&(dev->dev.kobj), linkname); + } + +-#define netdev_adjacent_is_neigh_list(dev, dev_list) \ +- (dev_list == &dev->adj_list.upper || \ +- dev_list == &dev->adj_list.lower) ++static inline bool netdev_adjacent_is_neigh_list(struct net_device *dev, ++ struct net_device *adj_dev, ++ struct list_head *dev_list) ++{ ++ return (dev_list == &dev->adj_list.upper || ++ dev_list == &dev->adj_list.lower) && ++ net_eq(dev_net(dev), dev_net(adj_dev)); ++} + + static int __netdev_adjacent_dev_insert(struct net_device *dev, + struct net_device *adj_dev, +@@ -4733,7 +4742,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, + pr_debug("dev_hold for %s, because of link added from %s to %s\n", + adj_dev->name, dev->name, adj_dev->name); + +- if (netdev_adjacent_is_neigh_list(dev, dev_list)) { ++ if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) { + ret = netdev_adjacent_sysfs_add(dev, adj_dev, dev_list); + if (ret) + goto free_adj; +@@ -4754,7 +4763,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, + return 0; + + remove_symlinks: +- if (netdev_adjacent_is_neigh_list(dev, dev_list)) ++ if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) + netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); + free_adj: + kfree(adj); +@@ -4787,7 +4796,7 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev, + if (adj->master) + sysfs_remove_link(&(dev->dev.kobj), "master"); + +- if (netdev_adjacent_is_neigh_list(dev, dev_list)) ++ if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) + netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); + + list_del_rcu(&adj->list); +@@ -5057,11 +5066,65 @@ void netdev_upper_dev_unlink(struct net_device *dev, + } + EXPORT_SYMBOL(netdev_upper_dev_unlink); + ++void netdev_adjacent_add_links(struct net_device *dev) ++{ ++ struct netdev_adjacent *iter; ++ ++ struct net *net = dev_net(dev); ++ ++ list_for_each_entry(iter, &dev->adj_list.upper, list) { ++ if (!net_eq(net,dev_net(iter->dev))) ++ continue; ++ netdev_adjacent_sysfs_add(iter->dev, dev, ++ &iter->dev->adj_list.lower); ++ netdev_adjacent_sysfs_add(dev, iter->dev, ++ &dev->adj_list.upper); ++ } ++ ++ list_for_each_entry(iter, &dev->adj_list.lower, list) { ++ if (!net_eq(net,dev_net(iter->dev))) ++ continue; ++ netdev_adjacent_sysfs_add(iter->dev, dev, ++ &iter->dev->adj_list.upper); ++ netdev_adjacent_sysfs_add(dev, iter->dev, ++ &dev->adj_list.lower); ++ } ++} ++ ++void netdev_adjacent_del_links(struct net_device *dev) ++{ ++ struct netdev_adjacent *iter; ++ ++ struct net *net = dev_net(dev); ++ ++ list_for_each_entry(iter, &dev->adj_list.upper, list) { ++ if (!net_eq(net,dev_net(iter->dev))) ++ continue; ++ netdev_adjacent_sysfs_del(iter->dev, dev->name, ++ &iter->dev->adj_list.lower); ++ netdev_adjacent_sysfs_del(dev, iter->dev->name, ++ &dev->adj_list.upper); ++ } ++ ++ list_for_each_entry(iter, &dev->adj_list.lower, list) { ++ if (!net_eq(net,dev_net(iter->dev))) ++ continue; ++ netdev_adjacent_sysfs_del(iter->dev, dev->name, ++ &iter->dev->adj_list.upper); ++ netdev_adjacent_sysfs_del(dev, iter->dev->name, ++ &dev->adj_list.lower); ++ } ++} ++ + void netdev_adjacent_rename_links(struct net_device *dev, char *oldname) + { + struct netdev_adjacent *iter; + ++ struct net *net = dev_net(dev); ++ + list_for_each_entry(iter, &dev->adj_list.upper, list) { ++ if (!net_eq(net,dev_net(iter->dev))) ++ continue; + netdev_adjacent_sysfs_del(iter->dev, oldname, + &iter->dev->adj_list.lower); + netdev_adjacent_sysfs_add(iter->dev, dev, +@@ -5069,6 +5132,8 @@ void netdev_adjacent_rename_links(struct net_device *dev, char *oldname) + } + + list_for_each_entry(iter, &dev->adj_list.lower, list) { ++ if (!net_eq(net,dev_net(iter->dev))) ++ continue; + netdev_adjacent_sysfs_del(iter->dev, oldname, + &iter->dev->adj_list.upper); + netdev_adjacent_sysfs_add(iter->dev, dev, +@@ -6675,6 +6740,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char + + /* Send a netdev-removed uevent to the old namespace */ + kobject_uevent(&dev->dev.kobj, KOBJ_REMOVE); ++ netdev_adjacent_del_links(dev); + + /* Actually switch the network namespace */ + dev_net_set(dev, net); +@@ -6689,6 +6755,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char + + /* Send a netdev-add uevent to the new namespace */ + kobject_uevent(&dev->dev.kobj, KOBJ_ADD); ++ netdev_adjacent_add_links(dev); + + /* Fixup kobjects */ + err = device_rename(&dev->dev, dev->name); +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index baf6fc457df9..e2b1bba69882 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -3937,6 +3937,7 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet) + skb->local_df = 0; + skb_dst_drop(skb); + skb->mark = 0; ++ skb_init_secmark(skb); + secpath_reset(skb); + nf_reset(skb); + nf_reset_trace(skb); +diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c +index 94213c891565..b40b90d3bd2b 100644 +--- a/net/ipv4/ip_gre.c ++++ b/net/ipv4/ip_gre.c +@@ -250,10 +250,6 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb, + struct ip_tunnel *tunnel = netdev_priv(dev); + const struct iphdr *tnl_params; + +- skb = gre_handle_offloads(skb, !!(tunnel->parms.o_flags&TUNNEL_CSUM)); +- if (IS_ERR(skb)) +- goto out; +- + if (dev->header_ops) { + /* Need space for new headers */ + if (skb_cow_head(skb, dev->needed_headroom - +@@ -266,6 +262,7 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb, + * to gre header. + */ + skb_pull(skb, tunnel->hlen + sizeof(struct iphdr)); ++ skb_reset_mac_header(skb); + } else { + if (skb_cow_head(skb, dev->needed_headroom)) + goto free_skb; +@@ -273,6 +270,10 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb, + tnl_params = &tunnel->parms.iph; + } + ++ skb = gre_handle_offloads(skb, !!(tunnel->parms.o_flags&TUNNEL_CSUM)); ++ if (IS_ERR(skb)) ++ goto out; ++ + __gre_xmit(skb, dev, tnl_params, skb->protocol); + + return NETDEV_TX_OK; +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 91b98e5a17aa..7efa26bb872c 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -1894,7 +1894,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, + if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now))) + break; + +- if (tso_segs == 1) { ++ if (tso_segs == 1 || !sk->sk_gso_max_segs) { + if (unlikely(!tcp_nagle_test(tp, skb, mss_now, + (tcp_skb_is_last(sk, skb) ? + nonagle : TCP_NAGLE_PUSH)))) +@@ -1931,7 +1931,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, + } + + limit = mss_now; +- if (tso_segs > 1 && !tcp_urg_mode(tp)) ++ if (tso_segs > 1 && sk->sk_gso_max_segs && !tcp_urg_mode(tp)) + limit = tcp_mss_split_point(sk, skb, mss_now, + min_t(unsigned int, + cwnd_quota, +diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c +index cf9937743abb..53ea1644a297 100644 +--- a/net/netfilter/ipset/ip_set_core.c ++++ b/net/netfilter/ipset/ip_set_core.c +@@ -1839,6 +1839,12 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len) + if (*op < IP_SET_OP_VERSION) { + /* Check the version at the beginning of operations */ + struct ip_set_req_version *req_version = data; ++ ++ if (*len < sizeof(struct ip_set_req_version)) { ++ ret = -EINVAL; ++ goto done; ++ } ++ + if (req_version->version != IPSET_PROTOCOL) { + ret = -EPROTO; + goto done; +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 7c177bc43806..1d52506bda14 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -510,14 +510,14 @@ out: + return err; + } + +-static void netlink_frame_flush_dcache(const struct nl_mmap_hdr *hdr) ++static void netlink_frame_flush_dcache(const struct nl_mmap_hdr *hdr, unsigned int nm_len) + { + #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE == 1 + struct page *p_start, *p_end; + + /* First page is flushed through netlink_{get,set}_status */ + p_start = pgvec_to_page(hdr + PAGE_SIZE); +- p_end = pgvec_to_page((void *)hdr + NL_MMAP_HDRLEN + hdr->nm_len - 1); ++ p_end = pgvec_to_page((void *)hdr + NL_MMAP_HDRLEN + nm_len - 1); + while (p_start <= p_end) { + flush_dcache_page(p_start); + p_start++; +@@ -535,9 +535,9 @@ static enum nl_mmap_status netlink_get_status(const struct nl_mmap_hdr *hdr) + static void netlink_set_status(struct nl_mmap_hdr *hdr, + enum nl_mmap_status status) + { ++ smp_mb(); + hdr->nm_status = status; + flush_dcache_page(pgvec_to_page(hdr)); +- smp_wmb(); + } + + static struct nl_mmap_hdr * +@@ -699,24 +699,16 @@ static int netlink_mmap_sendmsg(struct sock *sk, struct msghdr *msg, + struct nl_mmap_hdr *hdr; + struct sk_buff *skb; + unsigned int maxlen; +- bool excl = true; + int err = 0, len = 0; + +- /* Netlink messages are validated by the receiver before processing. +- * In order to avoid userspace changing the contents of the message +- * after validation, the socket and the ring may only be used by a +- * single process, otherwise we fall back to copying. +- */ +- if (atomic_long_read(&sk->sk_socket->file->f_count) > 1 || +- atomic_read(&nlk->mapped) > 1) +- excl = false; +- + mutex_lock(&nlk->pg_vec_lock); + + ring = &nlk->tx_ring; + maxlen = ring->frame_size - NL_MMAP_HDRLEN; + + do { ++ unsigned int nm_len; ++ + hdr = netlink_current_frame(ring, NL_MMAP_STATUS_VALID); + if (hdr == NULL) { + if (!(msg->msg_flags & MSG_DONTWAIT) && +@@ -724,35 +716,23 @@ static int netlink_mmap_sendmsg(struct sock *sk, struct msghdr *msg, + schedule(); + continue; + } +- if (hdr->nm_len > maxlen) { ++ ++ nm_len = ACCESS_ONCE(hdr->nm_len); ++ if (nm_len > maxlen) { + err = -EINVAL; + goto out; + } + +- netlink_frame_flush_dcache(hdr); ++ netlink_frame_flush_dcache(hdr, nm_len); + +- if (likely(dst_portid == 0 && dst_group == 0 && excl)) { +- skb = alloc_skb_head(GFP_KERNEL); +- if (skb == NULL) { +- err = -ENOBUFS; +- goto out; +- } +- sock_hold(sk); +- netlink_ring_setup_skb(skb, sk, ring, hdr); +- NETLINK_CB(skb).flags |= NETLINK_SKB_TX; +- __skb_put(skb, hdr->nm_len); +- netlink_set_status(hdr, NL_MMAP_STATUS_RESERVED); +- atomic_inc(&ring->pending); +- } else { +- skb = alloc_skb(hdr->nm_len, GFP_KERNEL); +- if (skb == NULL) { +- err = -ENOBUFS; +- goto out; +- } +- __skb_put(skb, hdr->nm_len); +- memcpy(skb->data, (void *)hdr + NL_MMAP_HDRLEN, hdr->nm_len); +- netlink_set_status(hdr, NL_MMAP_STATUS_UNUSED); ++ skb = alloc_skb(nm_len, GFP_KERNEL); ++ if (skb == NULL) { ++ err = -ENOBUFS; ++ goto out; + } ++ __skb_put(skb, nm_len); ++ memcpy(skb->data, (void *)hdr + NL_MMAP_HDRLEN, nm_len); ++ netlink_set_status(hdr, NL_MMAP_STATUS_UNUSED); + + netlink_increment_head(ring); + +@@ -798,7 +778,7 @@ static void netlink_queue_mmaped_skb(struct sock *sk, struct sk_buff *skb) + hdr->nm_pid = NETLINK_CB(skb).creds.pid; + hdr->nm_uid = from_kuid(sk_user_ns(sk), NETLINK_CB(skb).creds.uid); + hdr->nm_gid = from_kgid(sk_user_ns(sk), NETLINK_CB(skb).creds.gid); +- netlink_frame_flush_dcache(hdr); ++ netlink_frame_flush_dcache(hdr, hdr->nm_len); + netlink_set_status(hdr, NL_MMAP_STATUS_VALID); + + NETLINK_CB(skb).flags |= NETLINK_SKB_DELIVERED; +diff --git a/net/wireless/chan.c b/net/wireless/chan.c +index 78559b5bbd1f..27157a7801e8 100644 +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -516,7 +516,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, + { + struct ieee80211_sta_ht_cap *ht_cap; + struct ieee80211_sta_vht_cap *vht_cap; +- u32 width, control_freq; ++ u32 width, control_freq, cap; + + if (WARN_ON(!cfg80211_chandef_valid(chandef))) + return false; +@@ -554,7 +554,8 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, + return false; + break; + case NL80211_CHAN_WIDTH_80P80: +- if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) ++ cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; ++ if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) + return false; + case NL80211_CHAN_WIDTH_80: + if (!vht_cap->vht_supported) +@@ -565,7 +566,9 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, + case NL80211_CHAN_WIDTH_160: + if (!vht_cap->vht_supported) + return false; +- if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)) ++ cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; ++ if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ && ++ cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) + return false; + prohibited_flags |= IEEE80211_CHAN_NO_160MHZ; + width = 160; +diff --git a/net/wireless/reg.c b/net/wireless/reg.c +index 338794ea44d1..04d530560ec8 100644 +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -1547,7 +1547,7 @@ static enum reg_request_treatment + reg_process_hint_driver(struct wiphy *wiphy, + struct regulatory_request *driver_request) + { +- const struct ieee80211_regdomain *regd; ++ const struct ieee80211_regdomain *regd, *tmp; + enum reg_request_treatment treatment; + + treatment = __reg_process_hint_driver(driver_request); +@@ -1566,7 +1566,10 @@ reg_process_hint_driver(struct wiphy *wiphy, + kfree(driver_request); + return REG_REQ_IGNORE; + } ++ ++ tmp = get_wiphy_regdom(wiphy); + rcu_assign_pointer(wiphy->regd, regd); ++ rcu_free_regdom(tmp); + } + + +@@ -1625,11 +1628,8 @@ __reg_process_hint_country_ie(struct wiphy *wiphy, + return REG_REQ_IGNORE; + return REG_REQ_ALREADY_SET; + } +- /* +- * Two consecutive Country IE hints on the same wiphy. +- * This should be picked up early by the driver/stack +- */ +- if (WARN_ON(regdom_changes(country_ie_request->alpha2))) ++ ++ if (regdom_changes(country_ie_request->alpha2)) + return REG_REQ_OK; + return REG_REQ_ALREADY_SET; + } +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index c657752a420c..83bddbdb90e9 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -2804,133 +2804,45 @@ YAMAHA_DEVICE(0x7010, "UB99"), + } + }, + +-/* Hauppauge HVR-950Q and HVR-850 */ +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x7200), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x7210), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x7217), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x721b), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x721e), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x721f), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x7240), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-850", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x7280), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x0fd9, 0x0008), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, ++/* ++ * Auvitek au0828 devices with audio interface. ++ * This should be kept in sync with drivers/media/usb/au0828/au0828-cards.c ++ * Please notice that some drivers are DVB only, and don't need to be ++ * here. That's the case, for example, of DVICO_FUSIONHDTV7. ++ */ ++ ++#define AU0828_DEVICE(vid, pid, vname, pname) { \ ++ USB_DEVICE_VENDOR_SPEC(vid, pid), \ ++ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ ++ USB_DEVICE_ID_MATCH_INT_CLASS | \ ++ USB_DEVICE_ID_MATCH_INT_SUBCLASS, \ ++ .bInterfaceClass = USB_CLASS_AUDIO, \ ++ .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, \ ++ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { \ ++ .vendor_name = vname, \ ++ .product_name = pname, \ ++ .ifnum = QUIRK_ANY_INTERFACE, \ ++ .type = QUIRK_AUDIO_ALIGN_TRANSFER, \ ++ } \ ++} ++ ++AU0828_DEVICE(0x2040, 0x7200, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x7240, "Hauppauge", "HVR-850"), ++AU0828_DEVICE(0x2040, 0x7210, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x7217, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x721b, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x721e, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x721f, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x7280, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x0fd9, 0x0008, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x7201, "Hauppauge", "HVR-950Q-MXL"), ++AU0828_DEVICE(0x2040, 0x7211, "Hauppauge", "HVR-950Q-MXL"), ++AU0828_DEVICE(0x2040, 0x7281, "Hauppauge", "HVR-950Q-MXL"), ++AU0828_DEVICE(0x05e1, 0x0480, "Hauppauge", "Woodbury"), ++AU0828_DEVICE(0x2040, 0x8200, "Hauppauge", "Woodbury"), ++AU0828_DEVICE(0x2040, 0x7260, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x7213, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), + + /* Digidesign Mbox */ + { diff --git a/patch/kernel/cubox-default/patch-3.14.30-31.patch b/patch/kernel/cubox-default/patch-3.14.30-31.patch new file mode 100644 index 000000000..c557e2164 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.30-31.patch @@ -0,0 +1,5744 @@ +diff --git a/Makefile b/Makefile +index 5b94752a85e3..5abf670c6651 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 30 ++SUBLEVEL = 31 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arc/include/asm/barrier.h b/arch/arc/include/asm/barrier.h +deleted file mode 100644 +index c32245c3d1e9..000000000000 +--- a/arch/arc/include/asm/barrier.h ++++ /dev/null +@@ -1,37 +0,0 @@ +-/* +- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +- */ +- +-#ifndef __ASM_BARRIER_H +-#define __ASM_BARRIER_H +- +-#ifndef __ASSEMBLY__ +- +-/* TODO-vineetg: Need to see what this does, don't we need sync anywhere */ +-#define mb() __asm__ __volatile__ ("" : : : "memory") +-#define rmb() mb() +-#define wmb() mb() +-#define set_mb(var, value) do { var = value; mb(); } while (0) +-#define set_wmb(var, value) do { var = value; wmb(); } while (0) +-#define read_barrier_depends() mb() +- +-/* TODO-vineetg verify the correctness of macros here */ +-#ifdef CONFIG_SMP +-#define smp_mb() mb() +-#define smp_rmb() rmb() +-#define smp_wmb() wmb() +-#else +-#define smp_mb() barrier() +-#define smp_rmb() barrier() +-#define smp_wmb() barrier() +-#endif +- +-#define smp_read_barrier_depends() do { } while (0) +- +-#endif +- +-#endif +diff --git a/arch/arc/kernel/ctx_sw_asm.S b/arch/arc/kernel/ctx_sw_asm.S +index 2ff0347a2fd7..e248594097e7 100644 +--- a/arch/arc/kernel/ctx_sw_asm.S ++++ b/arch/arc/kernel/ctx_sw_asm.S +@@ -10,9 +10,9 @@ + * -This is the more "natural" hand written assembler + */ + ++#include + #include /* For the SAVE_* macros */ + #include +-#include + + #define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) + +diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi +index 6a26e79f0ef4..cf3300a3071d 100644 +--- a/arch/arm/boot/dts/imx25.dtsi ++++ b/arch/arm/boot/dts/imx25.dtsi +@@ -352,7 +352,7 @@ + compatible = "fsl,imx25-pwm", "fsl,imx27-pwm"; + #pwm-cells = <2>; + reg = <0x53fa0000 0x4000>; +- clocks = <&clks 106>, <&clks 36>; ++ clocks = <&clks 106>, <&clks 52>; + clock-names = "ipg", "per"; + interrupts = <36>; + }; +@@ -371,7 +371,7 @@ + compatible = "fsl,imx25-pwm", "fsl,imx27-pwm"; + #pwm-cells = <2>; + reg = <0x53fa8000 0x4000>; +- clocks = <&clks 107>, <&clks 36>; ++ clocks = <&clks 107>, <&clks 52>; + clock-names = "ipg", "per"; + interrupts = <41>; + }; +@@ -412,7 +412,7 @@ + pwm4: pwm@53fc8000 { + compatible = "fsl,imx25-pwm", "fsl,imx27-pwm"; + reg = <0x53fc8000 0x4000>; +- clocks = <&clks 108>, <&clks 36>; ++ clocks = <&clks 108>, <&clks 52>; + clock-names = "ipg", "per"; + interrupts = <42>; + }; +@@ -458,7 +458,7 @@ + compatible = "fsl,imx25-pwm", "fsl,imx27-pwm"; + #pwm-cells = <2>; + reg = <0x53fe0000 0x4000>; +- clocks = <&clks 105>, <&clks 36>; ++ clocks = <&clks 105>, <&clks 52>; + clock-names = "ipg", "per"; + interrupts = <26>; + }; +diff --git a/arch/arm/crypto/aes_glue.c b/arch/arm/crypto/aes_glue.c +index 3003fa1f6fb4..0409b8f89782 100644 +--- a/arch/arm/crypto/aes_glue.c ++++ b/arch/arm/crypto/aes_glue.c +@@ -93,6 +93,6 @@ module_exit(aes_fini); + + MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm (ASM)"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("aes"); +-MODULE_ALIAS("aes-asm"); ++MODULE_ALIAS_CRYPTO("aes"); ++MODULE_ALIAS_CRYPTO("aes-asm"); + MODULE_AUTHOR("David McCullough "); +diff --git a/arch/arm/crypto/sha1_glue.c b/arch/arm/crypto/sha1_glue.c +index 76cd976230bc..ace4cd67464c 100644 +--- a/arch/arm/crypto/sha1_glue.c ++++ b/arch/arm/crypto/sha1_glue.c +@@ -175,5 +175,5 @@ module_exit(sha1_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm (ARM)"); +-MODULE_ALIAS("sha1"); ++MODULE_ALIAS_CRYPTO("sha1"); + MODULE_AUTHOR("David McCullough "); +diff --git a/arch/powerpc/crypto/sha1.c b/arch/powerpc/crypto/sha1.c +index f9e8b9491efc..b51da9132744 100644 +--- a/arch/powerpc/crypto/sha1.c ++++ b/arch/powerpc/crypto/sha1.c +@@ -154,4 +154,5 @@ module_exit(sha1_powerpc_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); + +-MODULE_ALIAS("sha1-powerpc"); ++MODULE_ALIAS_CRYPTO("sha1"); ++MODULE_ALIAS_CRYPTO("sha1-powerpc"); +diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c +index 23223cd63e54..1f272b24fc0b 100644 +--- a/arch/s390/crypto/aes_s390.c ++++ b/arch/s390/crypto/aes_s390.c +@@ -979,7 +979,7 @@ static void __exit aes_s390_fini(void) + module_init(aes_s390_init); + module_exit(aes_s390_fini); + +-MODULE_ALIAS("aes-all"); ++MODULE_ALIAS_CRYPTO("aes-all"); + + MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); + MODULE_LICENSE("GPL"); +diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c +index 7acb77f7ef1a..9e05cc453a40 100644 +--- a/arch/s390/crypto/des_s390.c ++++ b/arch/s390/crypto/des_s390.c +@@ -619,8 +619,8 @@ static void __exit des_s390_exit(void) + module_init(des_s390_init); + module_exit(des_s390_exit); + +-MODULE_ALIAS("des"); +-MODULE_ALIAS("des3_ede"); ++MODULE_ALIAS_CRYPTO("des"); ++MODULE_ALIAS_CRYPTO("des3_ede"); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); +diff --git a/arch/s390/crypto/ghash_s390.c b/arch/s390/crypto/ghash_s390.c +index d43485d142e9..7940dc90e80b 100644 +--- a/arch/s390/crypto/ghash_s390.c ++++ b/arch/s390/crypto/ghash_s390.c +@@ -160,7 +160,7 @@ static void __exit ghash_mod_exit(void) + module_init(ghash_mod_init); + module_exit(ghash_mod_exit); + +-MODULE_ALIAS("ghash"); ++MODULE_ALIAS_CRYPTO("ghash"); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("GHASH Message Digest Algorithm, s390 implementation"); +diff --git a/arch/s390/crypto/sha1_s390.c b/arch/s390/crypto/sha1_s390.c +index a1b3a9dc9d8a..5b2bee323694 100644 +--- a/arch/s390/crypto/sha1_s390.c ++++ b/arch/s390/crypto/sha1_s390.c +@@ -103,6 +103,6 @@ static void __exit sha1_s390_fini(void) + module_init(sha1_s390_init); + module_exit(sha1_s390_fini); + +-MODULE_ALIAS("sha1"); ++MODULE_ALIAS_CRYPTO("sha1"); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); +diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c +index 9b853809a492..b74ff158108c 100644 +--- a/arch/s390/crypto/sha256_s390.c ++++ b/arch/s390/crypto/sha256_s390.c +@@ -143,7 +143,7 @@ static void __exit sha256_s390_fini(void) + module_init(sha256_s390_init); + module_exit(sha256_s390_fini); + +-MODULE_ALIAS("sha256"); +-MODULE_ALIAS("sha224"); ++MODULE_ALIAS_CRYPTO("sha256"); ++MODULE_ALIAS_CRYPTO("sha224"); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA256 and SHA224 Secure Hash Algorithm"); +diff --git a/arch/s390/crypto/sha512_s390.c b/arch/s390/crypto/sha512_s390.c +index 32a81383b69c..0c36989ba182 100644 +--- a/arch/s390/crypto/sha512_s390.c ++++ b/arch/s390/crypto/sha512_s390.c +@@ -86,7 +86,7 @@ static struct shash_alg sha512_alg = { + } + }; + +-MODULE_ALIAS("sha512"); ++MODULE_ALIAS_CRYPTO("sha512"); + + static int sha384_init(struct shash_desc *desc) + { +@@ -126,7 +126,7 @@ static struct shash_alg sha384_alg = { + } + }; + +-MODULE_ALIAS("sha384"); ++MODULE_ALIAS_CRYPTO("sha384"); + + static int __init init(void) + { +diff --git a/arch/sparc/crypto/aes_glue.c b/arch/sparc/crypto/aes_glue.c +index 503e6d96ad4e..ded4cee35318 100644 +--- a/arch/sparc/crypto/aes_glue.c ++++ b/arch/sparc/crypto/aes_glue.c +@@ -499,6 +499,6 @@ module_exit(aes_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("AES Secure Hash Algorithm, sparc64 aes opcode accelerated"); + +-MODULE_ALIAS("aes"); ++MODULE_ALIAS_CRYPTO("aes"); + + #include "crop_devid.c" +diff --git a/arch/sparc/crypto/camellia_glue.c b/arch/sparc/crypto/camellia_glue.c +index 888f6260b4ec..641f55cb61c3 100644 +--- a/arch/sparc/crypto/camellia_glue.c ++++ b/arch/sparc/crypto/camellia_glue.c +@@ -322,6 +322,6 @@ module_exit(camellia_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated"); + +-MODULE_ALIAS("aes"); ++MODULE_ALIAS_CRYPTO("aes"); + + #include "crop_devid.c" +diff --git a/arch/sparc/crypto/crc32c_glue.c b/arch/sparc/crypto/crc32c_glue.c +index 5162fad912ce..d1064e46efe8 100644 +--- a/arch/sparc/crypto/crc32c_glue.c ++++ b/arch/sparc/crypto/crc32c_glue.c +@@ -176,6 +176,6 @@ module_exit(crc32c_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("CRC32c (Castagnoli), sparc64 crc32c opcode accelerated"); + +-MODULE_ALIAS("crc32c"); ++MODULE_ALIAS_CRYPTO("crc32c"); + + #include "crop_devid.c" +diff --git a/arch/sparc/crypto/des_glue.c b/arch/sparc/crypto/des_glue.c +index 3065bc61f9d3..d11500972994 100644 +--- a/arch/sparc/crypto/des_glue.c ++++ b/arch/sparc/crypto/des_glue.c +@@ -532,6 +532,6 @@ module_exit(des_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated"); + +-MODULE_ALIAS("des"); ++MODULE_ALIAS_CRYPTO("des"); + + #include "crop_devid.c" +diff --git a/arch/sparc/crypto/md5_glue.c b/arch/sparc/crypto/md5_glue.c +index 09a9ea1dfb69..64c7ff5f72a9 100644 +--- a/arch/sparc/crypto/md5_glue.c ++++ b/arch/sparc/crypto/md5_glue.c +@@ -185,6 +185,6 @@ module_exit(md5_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, sparc64 md5 opcode accelerated"); + +-MODULE_ALIAS("md5"); ++MODULE_ALIAS_CRYPTO("md5"); + + #include "crop_devid.c" +diff --git a/arch/sparc/crypto/sha1_glue.c b/arch/sparc/crypto/sha1_glue.c +index 6cd5f29e1e0d..1b3e47accc74 100644 +--- a/arch/sparc/crypto/sha1_glue.c ++++ b/arch/sparc/crypto/sha1_glue.c +@@ -180,6 +180,6 @@ module_exit(sha1_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, sparc64 sha1 opcode accelerated"); + +-MODULE_ALIAS("sha1"); ++MODULE_ALIAS_CRYPTO("sha1"); + + #include "crop_devid.c" +diff --git a/arch/sparc/crypto/sha256_glue.c b/arch/sparc/crypto/sha256_glue.c +index 04f555ab2680..41f27cca2a22 100644 +--- a/arch/sparc/crypto/sha256_glue.c ++++ b/arch/sparc/crypto/sha256_glue.c +@@ -237,7 +237,7 @@ module_exit(sha256_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm, sparc64 sha256 opcode accelerated"); + +-MODULE_ALIAS("sha224"); +-MODULE_ALIAS("sha256"); ++MODULE_ALIAS_CRYPTO("sha224"); ++MODULE_ALIAS_CRYPTO("sha256"); + + #include "crop_devid.c" +diff --git a/arch/sparc/crypto/sha512_glue.c b/arch/sparc/crypto/sha512_glue.c +index f04d1994d19a..9fff88541b8c 100644 +--- a/arch/sparc/crypto/sha512_glue.c ++++ b/arch/sparc/crypto/sha512_glue.c +@@ -222,7 +222,7 @@ module_exit(sha512_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA-384 and SHA-512 Secure Hash Algorithm, sparc64 sha512 opcode accelerated"); + +-MODULE_ALIAS("sha384"); +-MODULE_ALIAS("sha512"); ++MODULE_ALIAS_CRYPTO("sha384"); ++MODULE_ALIAS_CRYPTO("sha512"); + + #include "crop_devid.c" +diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c +index 004ba568d93f..33294fdc402e 100644 +--- a/arch/tile/mm/homecache.c ++++ b/arch/tile/mm/homecache.c +@@ -417,7 +417,7 @@ void __homecache_free_pages(struct page *page, unsigned int order) + if (put_page_testzero(page)) { + homecache_change_page_home(page, order, PAGE_HOME_HASH); + if (order == 0) { +- free_hot_cold_page(page, 0); ++ free_hot_cold_page(page, false); + } else { + init_page_count(page); + __free_pages(page, order); +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index 98aa930230ec..2f645c90e4d8 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -854,7 +854,7 @@ source "kernel/Kconfig.preempt" + + config X86_UP_APIC + bool "Local APIC support on uniprocessors" +- depends on X86_32 && !SMP && !X86_32_NON_STANDARD && !PCI_MSI ++ depends on X86_32 && !SMP && !X86_32_NON_STANDARD + ---help--- + A local APIC (Advanced Programmable Interrupt Controller) is an + integrated interrupt controller in the CPU. If you have a single-CPU +@@ -865,6 +865,10 @@ config X86_UP_APIC + performance counters), and the NMI watchdog which detects hard + lockups. + ++config X86_UP_APIC_MSI ++ def_bool y ++ select X86_UP_APIC if X86_32 && !SMP && !X86_32_NON_STANDARD && PCI_MSI ++ + config X86_UP_IOAPIC + bool "IO-APIC support on uniprocessors" + depends on X86_UP_APIC +diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c +index eb25ca1eb6da..8f45c855f84c 100644 +--- a/arch/x86/boot/compressed/misc.c ++++ b/arch/x86/boot/compressed/misc.c +@@ -396,6 +396,8 @@ asmlinkage void *decompress_kernel(void *rmode, memptr heap, + unsigned long output_len, + unsigned long run_size) + { ++ unsigned char *output_orig = output; ++ + real_mode = rmode; + + sanitize_boot_params(real_mode); +@@ -444,7 +446,12 @@ asmlinkage void *decompress_kernel(void *rmode, memptr heap, + debug_putstr("\nDecompressing Linux... "); + decompress(input_data, input_len, NULL, NULL, output, NULL, error); + parse_elf(output); +- handle_relocations(output, output_len); ++ /* ++ * 32-bit always performs relocations. 64-bit relocations are only ++ * needed if kASLR has chosen a different load address. ++ */ ++ if (!IS_ENABLED(CONFIG_X86_64) || output != output_orig) ++ handle_relocations(output, output_len); + debug_putstr("done.\nBooting the kernel.\n"); + return output; + } +diff --git a/arch/x86/crypto/aes_glue.c b/arch/x86/crypto/aes_glue.c +index aafe8ce0d65d..e26984f7ab8d 100644 +--- a/arch/x86/crypto/aes_glue.c ++++ b/arch/x86/crypto/aes_glue.c +@@ -66,5 +66,5 @@ module_exit(aes_fini); + + MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, asm optimized"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("aes"); +-MODULE_ALIAS("aes-asm"); ++MODULE_ALIAS_CRYPTO("aes"); ++MODULE_ALIAS_CRYPTO("aes-asm"); +diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c +index 948ad0e77741..6dfb7d0b139a 100644 +--- a/arch/x86/crypto/aesni-intel_glue.c ++++ b/arch/x86/crypto/aesni-intel_glue.c +@@ -1514,4 +1514,4 @@ module_exit(aesni_exit); + + MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, Intel AES-NI instructions optimized"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("aes"); ++MODULE_ALIAS_CRYPTO("aes"); +diff --git a/arch/x86/crypto/blowfish_glue.c b/arch/x86/crypto/blowfish_glue.c +index 50ec333b70e6..1477cfcdbf6b 100644 +--- a/arch/x86/crypto/blowfish_glue.c ++++ b/arch/x86/crypto/blowfish_glue.c +@@ -481,5 +481,5 @@ module_exit(fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Blowfish Cipher Algorithm, asm optimized"); +-MODULE_ALIAS("blowfish"); +-MODULE_ALIAS("blowfish-asm"); ++MODULE_ALIAS_CRYPTO("blowfish"); ++MODULE_ALIAS_CRYPTO("blowfish-asm"); +diff --git a/arch/x86/crypto/camellia_aesni_avx2_glue.c b/arch/x86/crypto/camellia_aesni_avx2_glue.c +index 4209a76fcdaa..9a07fafe3831 100644 +--- a/arch/x86/crypto/camellia_aesni_avx2_glue.c ++++ b/arch/x86/crypto/camellia_aesni_avx2_glue.c +@@ -582,5 +582,5 @@ module_exit(camellia_aesni_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Camellia Cipher Algorithm, AES-NI/AVX2 optimized"); +-MODULE_ALIAS("camellia"); +-MODULE_ALIAS("camellia-asm"); ++MODULE_ALIAS_CRYPTO("camellia"); ++MODULE_ALIAS_CRYPTO("camellia-asm"); +diff --git a/arch/x86/crypto/camellia_aesni_avx_glue.c b/arch/x86/crypto/camellia_aesni_avx_glue.c +index 87a041a10f4a..ed38d959add6 100644 +--- a/arch/x86/crypto/camellia_aesni_avx_glue.c ++++ b/arch/x86/crypto/camellia_aesni_avx_glue.c +@@ -574,5 +574,5 @@ module_exit(camellia_aesni_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Camellia Cipher Algorithm, AES-NI/AVX optimized"); +-MODULE_ALIAS("camellia"); +-MODULE_ALIAS("camellia-asm"); ++MODULE_ALIAS_CRYPTO("camellia"); ++MODULE_ALIAS_CRYPTO("camellia-asm"); +diff --git a/arch/x86/crypto/camellia_glue.c b/arch/x86/crypto/camellia_glue.c +index c171dcbf192d..5c8b6266a394 100644 +--- a/arch/x86/crypto/camellia_glue.c ++++ b/arch/x86/crypto/camellia_glue.c +@@ -1725,5 +1725,5 @@ module_exit(fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Camellia Cipher Algorithm, asm optimized"); +-MODULE_ALIAS("camellia"); +-MODULE_ALIAS("camellia-asm"); ++MODULE_ALIAS_CRYPTO("camellia"); ++MODULE_ALIAS_CRYPTO("camellia-asm"); +diff --git a/arch/x86/crypto/cast5_avx_glue.c b/arch/x86/crypto/cast5_avx_glue.c +index e6a3700489b9..f62e9db5a462 100644 +--- a/arch/x86/crypto/cast5_avx_glue.c ++++ b/arch/x86/crypto/cast5_avx_glue.c +@@ -494,4 +494,4 @@ module_exit(cast5_exit); + + MODULE_DESCRIPTION("Cast5 Cipher Algorithm, AVX optimized"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("cast5"); ++MODULE_ALIAS_CRYPTO("cast5"); +diff --git a/arch/x86/crypto/cast6_avx_glue.c b/arch/x86/crypto/cast6_avx_glue.c +index 09f3677393e4..0160f68a57ff 100644 +--- a/arch/x86/crypto/cast6_avx_glue.c ++++ b/arch/x86/crypto/cast6_avx_glue.c +@@ -611,4 +611,4 @@ module_exit(cast6_exit); + + MODULE_DESCRIPTION("Cast6 Cipher Algorithm, AVX optimized"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("cast6"); ++MODULE_ALIAS_CRYPTO("cast6"); +diff --git a/arch/x86/crypto/crc32-pclmul_glue.c b/arch/x86/crypto/crc32-pclmul_glue.c +index 9d014a74ef96..1937fc1d8763 100644 +--- a/arch/x86/crypto/crc32-pclmul_glue.c ++++ b/arch/x86/crypto/crc32-pclmul_glue.c +@@ -197,5 +197,5 @@ module_exit(crc32_pclmul_mod_fini); + MODULE_AUTHOR("Alexander Boyko "); + MODULE_LICENSE("GPL"); + +-MODULE_ALIAS("crc32"); +-MODULE_ALIAS("crc32-pclmul"); ++MODULE_ALIAS_CRYPTO("crc32"); ++MODULE_ALIAS_CRYPTO("crc32-pclmul"); +diff --git a/arch/x86/crypto/crc32c-intel_glue.c b/arch/x86/crypto/crc32c-intel_glue.c +index 6812ad98355c..28640c3d6af7 100644 +--- a/arch/x86/crypto/crc32c-intel_glue.c ++++ b/arch/x86/crypto/crc32c-intel_glue.c +@@ -280,5 +280,5 @@ MODULE_AUTHOR("Austin Zhang , Kent Liu "); + MODULE_DESCRIPTION("T10 DIF CRC calculation accelerated with PCLMULQDQ."); + MODULE_LICENSE("GPL"); + +-MODULE_ALIAS("crct10dif"); +-MODULE_ALIAS("crct10dif-pclmul"); ++MODULE_ALIAS_CRYPTO("crct10dif"); ++MODULE_ALIAS_CRYPTO("crct10dif-pclmul"); +diff --git a/arch/x86/crypto/fpu.c b/arch/x86/crypto/fpu.c +index 98d7a188f46b..f368ba261739 100644 +--- a/arch/x86/crypto/fpu.c ++++ b/arch/x86/crypto/fpu.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + + struct crypto_fpu_ctx { +@@ -159,3 +160,5 @@ void __exit crypto_fpu_exit(void) + { + crypto_unregister_template(&crypto_fpu_tmpl); + } ++ ++MODULE_ALIAS_CRYPTO("fpu"); +diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c +index d785cf2c529c..a8d6f69f92a3 100644 +--- a/arch/x86/crypto/ghash-clmulni-intel_glue.c ++++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c +@@ -341,4 +341,4 @@ module_exit(ghash_pclmulqdqni_mod_exit); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("GHASH Message Digest Algorithm, " + "acclerated by PCLMULQDQ-NI"); +-MODULE_ALIAS("ghash"); ++MODULE_ALIAS_CRYPTO("ghash"); +diff --git a/arch/x86/crypto/salsa20_glue.c b/arch/x86/crypto/salsa20_glue.c +index 5e8e67739bb5..399a29d067d6 100644 +--- a/arch/x86/crypto/salsa20_glue.c ++++ b/arch/x86/crypto/salsa20_glue.c +@@ -119,5 +119,5 @@ module_exit(fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION ("Salsa20 stream cipher algorithm (optimized assembly version)"); +-MODULE_ALIAS("salsa20"); +-MODULE_ALIAS("salsa20-asm"); ++MODULE_ALIAS_CRYPTO("salsa20"); ++MODULE_ALIAS_CRYPTO("salsa20-asm"); +diff --git a/arch/x86/crypto/serpent_avx2_glue.c b/arch/x86/crypto/serpent_avx2_glue.c +index 2fae489b1524..437e47a4d302 100644 +--- a/arch/x86/crypto/serpent_avx2_glue.c ++++ b/arch/x86/crypto/serpent_avx2_glue.c +@@ -558,5 +558,5 @@ module_exit(fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Serpent Cipher Algorithm, AVX2 optimized"); +-MODULE_ALIAS("serpent"); +-MODULE_ALIAS("serpent-asm"); ++MODULE_ALIAS_CRYPTO("serpent"); ++MODULE_ALIAS_CRYPTO("serpent-asm"); +diff --git a/arch/x86/crypto/serpent_avx_glue.c b/arch/x86/crypto/serpent_avx_glue.c +index ff4870870972..7e217398b4eb 100644 +--- a/arch/x86/crypto/serpent_avx_glue.c ++++ b/arch/x86/crypto/serpent_avx_glue.c +@@ -617,4 +617,4 @@ module_exit(serpent_exit); + + MODULE_DESCRIPTION("Serpent Cipher Algorithm, AVX optimized"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("serpent"); ++MODULE_ALIAS_CRYPTO("serpent"); +diff --git a/arch/x86/crypto/serpent_sse2_glue.c b/arch/x86/crypto/serpent_sse2_glue.c +index 8c95f8637306..bf025adaea01 100644 +--- a/arch/x86/crypto/serpent_sse2_glue.c ++++ b/arch/x86/crypto/serpent_sse2_glue.c +@@ -618,4 +618,4 @@ module_exit(serpent_sse2_exit); + + MODULE_DESCRIPTION("Serpent Cipher Algorithm, SSE2 optimized"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("serpent"); ++MODULE_ALIAS_CRYPTO("serpent"); +diff --git a/arch/x86/crypto/sha1_ssse3_glue.c b/arch/x86/crypto/sha1_ssse3_glue.c +index 4a11a9d72451..29e1060e9001 100644 +--- a/arch/x86/crypto/sha1_ssse3_glue.c ++++ b/arch/x86/crypto/sha1_ssse3_glue.c +@@ -237,4 +237,4 @@ module_exit(sha1_ssse3_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, Supplemental SSE3 accelerated"); + +-MODULE_ALIAS("sha1"); ++MODULE_ALIAS_CRYPTO("sha1"); +diff --git a/arch/x86/crypto/sha256_ssse3_glue.c b/arch/x86/crypto/sha256_ssse3_glue.c +index f248546da1ca..4dc100d82902 100644 +--- a/arch/x86/crypto/sha256_ssse3_glue.c ++++ b/arch/x86/crypto/sha256_ssse3_glue.c +@@ -318,5 +318,5 @@ module_exit(sha256_ssse3_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm, Supplemental SSE3 accelerated"); + +-MODULE_ALIAS("sha256"); +-MODULE_ALIAS("sha224"); ++MODULE_ALIAS_CRYPTO("sha256"); ++MODULE_ALIAS_CRYPTO("sha224"); +diff --git a/arch/x86/crypto/sha512_ssse3_glue.c b/arch/x86/crypto/sha512_ssse3_glue.c +index 8626b03e83b7..26a5898a6f26 100644 +--- a/arch/x86/crypto/sha512_ssse3_glue.c ++++ b/arch/x86/crypto/sha512_ssse3_glue.c +@@ -326,5 +326,5 @@ module_exit(sha512_ssse3_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA512 Secure Hash Algorithm, Supplemental SSE3 accelerated"); + +-MODULE_ALIAS("sha512"); +-MODULE_ALIAS("sha384"); ++MODULE_ALIAS_CRYPTO("sha512"); ++MODULE_ALIAS_CRYPTO("sha384"); +diff --git a/arch/x86/crypto/twofish_avx_glue.c b/arch/x86/crypto/twofish_avx_glue.c +index 4e3c665be129..1ac531ea9bcc 100644 +--- a/arch/x86/crypto/twofish_avx_glue.c ++++ b/arch/x86/crypto/twofish_avx_glue.c +@@ -579,4 +579,4 @@ module_exit(twofish_exit); + + MODULE_DESCRIPTION("Twofish Cipher Algorithm, AVX optimized"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("twofish"); ++MODULE_ALIAS_CRYPTO("twofish"); +diff --git a/arch/x86/crypto/twofish_glue.c b/arch/x86/crypto/twofish_glue.c +index 0a5202303501..77e06c2da83d 100644 +--- a/arch/x86/crypto/twofish_glue.c ++++ b/arch/x86/crypto/twofish_glue.c +@@ -96,5 +96,5 @@ module_exit(fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION ("Twofish Cipher Algorithm, asm optimized"); +-MODULE_ALIAS("twofish"); +-MODULE_ALIAS("twofish-asm"); ++MODULE_ALIAS_CRYPTO("twofish"); ++MODULE_ALIAS_CRYPTO("twofish-asm"); +diff --git a/arch/x86/crypto/twofish_glue_3way.c b/arch/x86/crypto/twofish_glue_3way.c +index 13e63b3e1dfb..56d8a08ee479 100644 +--- a/arch/x86/crypto/twofish_glue_3way.c ++++ b/arch/x86/crypto/twofish_glue_3way.c +@@ -495,5 +495,5 @@ module_exit(fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Twofish Cipher Algorithm, 3-way parallel asm optimized"); +-MODULE_ALIAS("twofish"); +-MODULE_ALIAS("twofish-asm"); ++MODULE_ALIAS_CRYPTO("twofish"); ++MODULE_ALIAS_CRYPTO("twofish-asm"); +diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h +index 50d033a8947d..a94b82e8f156 100644 +--- a/arch/x86/include/asm/desc.h ++++ b/arch/x86/include/asm/desc.h +@@ -251,7 +251,8 @@ static inline void native_load_tls(struct thread_struct *t, unsigned int cpu) + gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]; + } + +-#define _LDT_empty(info) \ ++/* This intentionally ignores lm, since 32-bit apps don't have that field. */ ++#define LDT_empty(info) \ + ((info)->base_addr == 0 && \ + (info)->limit == 0 && \ + (info)->contents == 0 && \ +@@ -261,11 +262,18 @@ static inline void native_load_tls(struct thread_struct *t, unsigned int cpu) + (info)->seg_not_present == 1 && \ + (info)->useable == 0) + +-#ifdef CONFIG_X86_64 +-#define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0)) +-#else +-#define LDT_empty(info) (_LDT_empty(info)) +-#endif ++/* Lots of programs expect an all-zero user_desc to mean "no segment at all". */ ++static inline bool LDT_zero(const struct user_desc *info) ++{ ++ return (info->base_addr == 0 && ++ info->limit == 0 && ++ info->contents == 0 && ++ info->read_exec_only == 0 && ++ info->seg_32bit == 0 && ++ info->limit_in_pages == 0 && ++ info->seg_not_present == 0 && ++ info->useable == 0); ++} + + static inline void clear_LDT(void) + { +diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c +index 832d05a914ba..317c81172c18 100644 +--- a/arch/x86/kernel/cpu/mshyperv.c ++++ b/arch/x86/kernel/cpu/mshyperv.c +@@ -67,6 +67,7 @@ static struct clocksource hyperv_cs = { + .rating = 400, /* use this when running on Hyperv*/ + .read = read_hv_clock, + .mask = CLOCKSOURCE_MASK(64), ++ .flags = CLOCK_SOURCE_IS_CONTINUOUS, + }; + + static void __init ms_hyperv_init_platform(void) +diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c +index 4e942f31b1a7..7fc5e843f247 100644 +--- a/arch/x86/kernel/tls.c ++++ b/arch/x86/kernel/tls.c +@@ -29,7 +29,28 @@ static int get_free_idx(void) + + static bool tls_desc_okay(const struct user_desc *info) + { +- if (LDT_empty(info)) ++ /* ++ * For historical reasons (i.e. no one ever documented how any ++ * of the segmentation APIs work), user programs can and do ++ * assume that a struct user_desc that's all zeros except for ++ * entry_number means "no segment at all". This never actually ++ * worked. In fact, up to Linux 3.19, a struct user_desc like ++ * this would create a 16-bit read-write segment with base and ++ * limit both equal to zero. ++ * ++ * That was close enough to "no segment at all" until we ++ * hardened this function to disallow 16-bit TLS segments. Fix ++ * it up by interpreting these zeroed segments the way that they ++ * were almost certainly intended to be interpreted. ++ * ++ * The correct way to ask for "no segment at all" is to specify ++ * a user_desc that satisfies LDT_empty. To keep everything ++ * working, we accept both. ++ * ++ * Note that there's a similar kludge in modify_ldt -- look at ++ * the distinction between modes 1 and 0x11. ++ */ ++ if (LDT_empty(info) || LDT_zero(info)) + return true; + + /* +@@ -71,7 +92,7 @@ static void set_tls_desc(struct task_struct *p, int idx, + cpu = get_cpu(); + + while (n-- > 0) { +- if (LDT_empty(info)) ++ if (LDT_empty(info) || LDT_zero(info)) + desc->a = desc->b = 0; + else + fill_ldt(desc, info); +diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c +index f9d976e0ae67..b1d9002af7db 100644 +--- a/arch/x86/kernel/traps.c ++++ b/arch/x86/kernel/traps.c +@@ -365,7 +365,7 @@ exit: + * for scheduling or signal handling. The actual stack switch is done in + * entry.S + */ +-asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) ++asmlinkage notrace __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) + { + struct pt_regs *regs = eregs; + /* Did already sync */ +@@ -390,7 +390,7 @@ struct bad_iret_stack { + struct pt_regs regs; + }; + +-asmlinkage __visible ++asmlinkage __visible notrace __kprobes + struct bad_iret_stack *fixup_bad_iret(struct bad_iret_stack *s) + { + /* +diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c +index de0290605903..b20bced0090f 100644 +--- a/arch/x86/kernel/tsc.c ++++ b/arch/x86/kernel/tsc.c +@@ -618,7 +618,7 @@ static unsigned long quick_pit_calibrate(void) + goto success; + } + } +- pr_err("Fast TSC calibration failed\n"); ++ pr_info("Fast TSC calibration failed\n"); + return 0; + + success: +diff --git a/crypto/842.c b/crypto/842.c +index 65c7a89cfa09..b48f4f108c47 100644 +--- a/crypto/842.c ++++ b/crypto/842.c +@@ -180,3 +180,4 @@ module_exit(nx842_mod_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("842 Compression Algorithm"); ++MODULE_ALIAS_CRYPTO("842"); +diff --git a/crypto/aes_generic.c b/crypto/aes_generic.c +index fd0d6b454975..3dd101144a58 100644 +--- a/crypto/aes_generic.c ++++ b/crypto/aes_generic.c +@@ -1474,4 +1474,5 @@ module_exit(aes_fini); + + MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); + MODULE_LICENSE("Dual BSD/GPL"); +-MODULE_ALIAS("aes"); ++MODULE_ALIAS_CRYPTO("aes"); ++MODULE_ALIAS_CRYPTO("aes-generic"); +diff --git a/crypto/algapi.c b/crypto/algapi.c +index 7a1ae87f1683..00d8d939733b 100644 +--- a/crypto/algapi.c ++++ b/crypto/algapi.c +@@ -495,8 +495,8 @@ static struct crypto_template *__crypto_lookup_template(const char *name) + + struct crypto_template *crypto_lookup_template(const char *name) + { +- return try_then_request_module(__crypto_lookup_template(name), "%s", +- name); ++ return try_then_request_module(__crypto_lookup_template(name), ++ "crypto-%s", name); + } + EXPORT_SYMBOL_GPL(crypto_lookup_template); + +diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c +index 666f1962a160..6f5bebc9bf01 100644 +--- a/crypto/ansi_cprng.c ++++ b/crypto/ansi_cprng.c +@@ -476,4 +476,5 @@ module_param(dbg, int, 0); + MODULE_PARM_DESC(dbg, "Boolean to enable debugging (0/1 == off/on)"); + module_init(prng_mod_init); + module_exit(prng_mod_fini); +-MODULE_ALIAS("stdrng"); ++MODULE_ALIAS_CRYPTO("stdrng"); ++MODULE_ALIAS_CRYPTO("ansi_cprng"); +diff --git a/crypto/anubis.c b/crypto/anubis.c +index 008c8a4fb67c..4bb187c2a902 100644 +--- a/crypto/anubis.c ++++ b/crypto/anubis.c +@@ -704,3 +704,4 @@ module_exit(anubis_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Anubis Cryptographic Algorithm"); ++MODULE_ALIAS_CRYPTO("anubis"); +diff --git a/crypto/api.c b/crypto/api.c +index a2b39c5f3649..2a81e98a0021 100644 +--- a/crypto/api.c ++++ b/crypto/api.c +@@ -216,11 +216,11 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask) + + alg = crypto_alg_lookup(name, type, mask); + if (!alg) { +- request_module("%s", name); ++ request_module("crypto-%s", name); + + if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask & + CRYPTO_ALG_NEED_FALLBACK)) +- request_module("%s-all", name); ++ request_module("crypto-%s-all", name); + + alg = crypto_alg_lookup(name, type, mask); + } +diff --git a/crypto/arc4.c b/crypto/arc4.c +index 5a772c3657d5..f1a81925558f 100644 +--- a/crypto/arc4.c ++++ b/crypto/arc4.c +@@ -166,3 +166,4 @@ module_exit(arc4_exit); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("ARC4 Cipher Algorithm"); + MODULE_AUTHOR("Jon Oberheide "); ++MODULE_ALIAS_CRYPTO("arc4"); +diff --git a/crypto/authenc.c b/crypto/authenc.c +index e1223559d5df..78fb16cab13f 100644 +--- a/crypto/authenc.c ++++ b/crypto/authenc.c +@@ -721,3 +721,4 @@ module_exit(crypto_authenc_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Simple AEAD wrapper for IPsec"); ++MODULE_ALIAS_CRYPTO("authenc"); +diff --git a/crypto/authencesn.c b/crypto/authencesn.c +index 4be0dd4373a9..024bff2344fc 100644 +--- a/crypto/authencesn.c ++++ b/crypto/authencesn.c +@@ -814,3 +814,4 @@ module_exit(crypto_authenc_esn_module_exit); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Steffen Klassert "); + MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers"); ++MODULE_ALIAS_CRYPTO("authencesn"); +diff --git a/crypto/blowfish_generic.c b/crypto/blowfish_generic.c +index 8baf5447d35b..87b392a77a93 100644 +--- a/crypto/blowfish_generic.c ++++ b/crypto/blowfish_generic.c +@@ -138,4 +138,5 @@ module_exit(blowfish_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Blowfish Cipher Algorithm"); +-MODULE_ALIAS("blowfish"); ++MODULE_ALIAS_CRYPTO("blowfish"); ++MODULE_ALIAS_CRYPTO("blowfish-generic"); +diff --git a/crypto/camellia_generic.c b/crypto/camellia_generic.c +index 26bcd7a2d6b4..a02286bf319e 100644 +--- a/crypto/camellia_generic.c ++++ b/crypto/camellia_generic.c +@@ -1098,4 +1098,5 @@ module_exit(camellia_fini); + + MODULE_DESCRIPTION("Camellia Cipher Algorithm"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("camellia"); ++MODULE_ALIAS_CRYPTO("camellia"); ++MODULE_ALIAS_CRYPTO("camellia-generic"); +diff --git a/crypto/cast5_generic.c b/crypto/cast5_generic.c +index 5558f630a0eb..df5c72629383 100644 +--- a/crypto/cast5_generic.c ++++ b/crypto/cast5_generic.c +@@ -549,4 +549,5 @@ module_exit(cast5_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Cast5 Cipher Algorithm"); +-MODULE_ALIAS("cast5"); ++MODULE_ALIAS_CRYPTO("cast5"); ++MODULE_ALIAS_CRYPTO("cast5-generic"); +diff --git a/crypto/cast6_generic.c b/crypto/cast6_generic.c +index de732528a430..058c8d755d03 100644 +--- a/crypto/cast6_generic.c ++++ b/crypto/cast6_generic.c +@@ -291,4 +291,5 @@ module_exit(cast6_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Cast6 Cipher Algorithm"); +-MODULE_ALIAS("cast6"); ++MODULE_ALIAS_CRYPTO("cast6"); ++MODULE_ALIAS_CRYPTO("cast6-generic"); +diff --git a/crypto/cbc.c b/crypto/cbc.c +index 61ac42e1e32b..780ee27b2d43 100644 +--- a/crypto/cbc.c ++++ b/crypto/cbc.c +@@ -289,3 +289,4 @@ module_exit(crypto_cbc_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("CBC block cipher algorithm"); ++MODULE_ALIAS_CRYPTO("cbc"); +diff --git a/crypto/ccm.c b/crypto/ccm.c +index 1df84217f7c9..003bbbd21a2b 100644 +--- a/crypto/ccm.c ++++ b/crypto/ccm.c +@@ -879,5 +879,6 @@ module_exit(crypto_ccm_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Counter with CBC MAC"); +-MODULE_ALIAS("ccm_base"); +-MODULE_ALIAS("rfc4309"); ++MODULE_ALIAS_CRYPTO("ccm_base"); ++MODULE_ALIAS_CRYPTO("rfc4309"); ++MODULE_ALIAS_CRYPTO("ccm"); +diff --git a/crypto/chainiv.c b/crypto/chainiv.c +index 834d8dd3d4fc..22b7e55b0e1b 100644 +--- a/crypto/chainiv.c ++++ b/crypto/chainiv.c +@@ -359,3 +359,4 @@ module_exit(chainiv_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Chain IV Generator"); ++MODULE_ALIAS_CRYPTO("chainiv"); +diff --git a/crypto/cmac.c b/crypto/cmac.c +index 50880cf17fad..7a8bfbd548f6 100644 +--- a/crypto/cmac.c ++++ b/crypto/cmac.c +@@ -313,3 +313,4 @@ module_exit(crypto_cmac_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("CMAC keyed hash algorithm"); ++MODULE_ALIAS_CRYPTO("cmac"); +diff --git a/crypto/crc32.c b/crypto/crc32.c +index 9d1c41569898..187ded28cb0b 100644 +--- a/crypto/crc32.c ++++ b/crypto/crc32.c +@@ -156,3 +156,4 @@ module_exit(crc32_mod_fini); + MODULE_AUTHOR("Alexander Boyko "); + MODULE_DESCRIPTION("CRC32 calculations wrapper for lib/crc32"); + MODULE_LICENSE("GPL"); ++MODULE_ALIAS_CRYPTO("crc32"); +diff --git a/crypto/crct10dif_generic.c b/crypto/crct10dif_generic.c +index 877e7114ec5c..c1229614c7e3 100644 +--- a/crypto/crct10dif_generic.c ++++ b/crypto/crct10dif_generic.c +@@ -124,4 +124,5 @@ module_exit(crct10dif_mod_fini); + MODULE_AUTHOR("Tim Chen "); + MODULE_DESCRIPTION("T10 DIF CRC calculation."); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("crct10dif"); ++MODULE_ALIAS_CRYPTO("crct10dif"); ++MODULE_ALIAS_CRYPTO("crct10dif-generic"); +diff --git a/crypto/cryptd.c b/crypto/cryptd.c +index 7bdd61b867c8..75c415d37086 100644 +--- a/crypto/cryptd.c ++++ b/crypto/cryptd.c +@@ -955,3 +955,4 @@ module_exit(cryptd_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Software async crypto daemon"); ++MODULE_ALIAS_CRYPTO("cryptd"); +diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c +index fee7265cd35d..7b39fa3deac2 100644 +--- a/crypto/crypto_null.c ++++ b/crypto/crypto_null.c +@@ -149,9 +149,9 @@ static struct crypto_alg null_algs[3] = { { + .coa_decompress = null_compress } } + } }; + +-MODULE_ALIAS("compress_null"); +-MODULE_ALIAS("digest_null"); +-MODULE_ALIAS("cipher_null"); ++MODULE_ALIAS_CRYPTO("compress_null"); ++MODULE_ALIAS_CRYPTO("digest_null"); ++MODULE_ALIAS_CRYPTO("cipher_null"); + + static int __init crypto_null_mod_init(void) + { +diff --git a/crypto/ctr.c b/crypto/ctr.c +index f2b94f27bb2c..2386f7313952 100644 +--- a/crypto/ctr.c ++++ b/crypto/ctr.c +@@ -466,4 +466,5 @@ module_exit(crypto_ctr_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("CTR Counter block mode"); +-MODULE_ALIAS("rfc3686"); ++MODULE_ALIAS_CRYPTO("rfc3686"); ++MODULE_ALIAS_CRYPTO("ctr"); +diff --git a/crypto/cts.c b/crypto/cts.c +index 042223f8e733..60b9da3fa7c1 100644 +--- a/crypto/cts.c ++++ b/crypto/cts.c +@@ -350,3 +350,4 @@ module_exit(crypto_cts_module_exit); + + MODULE_LICENSE("Dual BSD/GPL"); + MODULE_DESCRIPTION("CTS-CBC CipherText Stealing for CBC"); ++MODULE_ALIAS_CRYPTO("cts"); +diff --git a/crypto/deflate.c b/crypto/deflate.c +index b57d70eb156b..95d8d37c5021 100644 +--- a/crypto/deflate.c ++++ b/crypto/deflate.c +@@ -222,4 +222,4 @@ module_exit(deflate_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP"); + MODULE_AUTHOR("James Morris "); +- ++MODULE_ALIAS_CRYPTO("deflate"); +diff --git a/crypto/des_generic.c b/crypto/des_generic.c +index f6cf63f88468..3ec6071309d9 100644 +--- a/crypto/des_generic.c ++++ b/crypto/des_generic.c +@@ -971,8 +971,6 @@ static struct crypto_alg des_algs[2] = { { + .cia_decrypt = des3_ede_decrypt } } + } }; + +-MODULE_ALIAS("des3_ede"); +- + static int __init des_generic_mod_init(void) + { + return crypto_register_algs(des_algs, ARRAY_SIZE(des_algs)); +@@ -989,4 +987,7 @@ module_exit(des_generic_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); + MODULE_AUTHOR("Dag Arne Osvik "); +-MODULE_ALIAS("des"); ++MODULE_ALIAS_CRYPTO("des"); ++MODULE_ALIAS_CRYPTO("des-generic"); ++MODULE_ALIAS_CRYPTO("des3_ede"); ++MODULE_ALIAS_CRYPTO("des3_ede-generic"); +diff --git a/crypto/ecb.c b/crypto/ecb.c +index 935cfef4aa84..12011aff0971 100644 +--- a/crypto/ecb.c ++++ b/crypto/ecb.c +@@ -185,3 +185,4 @@ module_exit(crypto_ecb_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("ECB block cipher algorithm"); ++MODULE_ALIAS_CRYPTO("ecb"); +diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c +index 42ce9f570aec..388f582ab0b9 100644 +--- a/crypto/eseqiv.c ++++ b/crypto/eseqiv.c +@@ -267,3 +267,4 @@ module_exit(eseqiv_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Encrypted Sequence Number IV Generator"); ++MODULE_ALIAS_CRYPTO("eseqiv"); +diff --git a/crypto/fcrypt.c b/crypto/fcrypt.c +index 021d7fec6bc8..77286ea28865 100644 +--- a/crypto/fcrypt.c ++++ b/crypto/fcrypt.c +@@ -420,3 +420,4 @@ module_exit(fcrypt_mod_fini); + MODULE_LICENSE("Dual BSD/GPL"); + MODULE_DESCRIPTION("FCrypt Cipher Algorithm"); + MODULE_AUTHOR("David Howells "); ++MODULE_ALIAS_CRYPTO("fcrypt"); +diff --git a/crypto/gcm.c b/crypto/gcm.c +index b4f017939004..9cea4d0b6904 100644 +--- a/crypto/gcm.c ++++ b/crypto/gcm.c +@@ -1441,6 +1441,7 @@ module_exit(crypto_gcm_module_exit); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Galois/Counter Mode"); + MODULE_AUTHOR("Mikko Herranen "); +-MODULE_ALIAS("gcm_base"); +-MODULE_ALIAS("rfc4106"); +-MODULE_ALIAS("rfc4543"); ++MODULE_ALIAS_CRYPTO("gcm_base"); ++MODULE_ALIAS_CRYPTO("rfc4106"); ++MODULE_ALIAS_CRYPTO("rfc4543"); ++MODULE_ALIAS_CRYPTO("gcm"); +diff --git a/crypto/ghash-generic.c b/crypto/ghash-generic.c +index 9d3f0c69a86f..bac70995e064 100644 +--- a/crypto/ghash-generic.c ++++ b/crypto/ghash-generic.c +@@ -172,4 +172,5 @@ module_exit(ghash_mod_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("GHASH Message Digest Algorithm"); +-MODULE_ALIAS("ghash"); ++MODULE_ALIAS_CRYPTO("ghash"); ++MODULE_ALIAS_CRYPTO("ghash-generic"); +diff --git a/crypto/hmac.c b/crypto/hmac.c +index 8d9544cf8169..ade790b454e9 100644 +--- a/crypto/hmac.c ++++ b/crypto/hmac.c +@@ -271,3 +271,4 @@ module_exit(hmac_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("HMAC hash algorithm"); ++MODULE_ALIAS_CRYPTO("hmac"); +diff --git a/crypto/khazad.c b/crypto/khazad.c +index 60e7cd66facc..873eb5ded6d7 100644 +--- a/crypto/khazad.c ++++ b/crypto/khazad.c +@@ -880,3 +880,4 @@ module_exit(khazad_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Khazad Cryptographic Algorithm"); ++MODULE_ALIAS_CRYPTO("khazad"); +diff --git a/crypto/krng.c b/crypto/krng.c +index a2d2b72fc135..0224841b6579 100644 +--- a/crypto/krng.c ++++ b/crypto/krng.c +@@ -62,4 +62,5 @@ module_exit(krng_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Kernel Random Number Generator"); +-MODULE_ALIAS("stdrng"); ++MODULE_ALIAS_CRYPTO("stdrng"); ++MODULE_ALIAS_CRYPTO("krng"); +diff --git a/crypto/lrw.c b/crypto/lrw.c +index ba42acc4deba..6f9908a7ebcb 100644 +--- a/crypto/lrw.c ++++ b/crypto/lrw.c +@@ -400,3 +400,4 @@ module_exit(crypto_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("LRW block cipher mode"); ++MODULE_ALIAS_CRYPTO("lrw"); +diff --git a/crypto/lz4.c b/crypto/lz4.c +index 4586dd15b0d8..53279ab8c3a6 100644 +--- a/crypto/lz4.c ++++ b/crypto/lz4.c +@@ -104,3 +104,4 @@ module_exit(lz4_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("LZ4 Compression Algorithm"); ++MODULE_ALIAS_CRYPTO("lz4"); +diff --git a/crypto/lz4hc.c b/crypto/lz4hc.c +index 151ba31d34e3..eaec5fa3debf 100644 +--- a/crypto/lz4hc.c ++++ b/crypto/lz4hc.c +@@ -104,3 +104,4 @@ module_exit(lz4hc_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("LZ4HC Compression Algorithm"); ++MODULE_ALIAS_CRYPTO("lz4hc"); +diff --git a/crypto/lzo.c b/crypto/lzo.c +index 1c2aa69c54b8..d1ff69404353 100644 +--- a/crypto/lzo.c ++++ b/crypto/lzo.c +@@ -103,3 +103,4 @@ module_exit(lzo_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("LZO Compression Algorithm"); ++MODULE_ALIAS_CRYPTO("lzo"); +diff --git a/crypto/md4.c b/crypto/md4.c +index 0477a6a01d58..3515af425cc9 100644 +--- a/crypto/md4.c ++++ b/crypto/md4.c +@@ -255,4 +255,4 @@ module_exit(md4_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("MD4 Message Digest Algorithm"); +- ++MODULE_ALIAS_CRYPTO("md4"); +diff --git a/crypto/md5.c b/crypto/md5.c +index 7febeaab923b..36f5e5b103f3 100644 +--- a/crypto/md5.c ++++ b/crypto/md5.c +@@ -168,3 +168,4 @@ module_exit(md5_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("MD5 Message Digest Algorithm"); ++MODULE_ALIAS_CRYPTO("md5"); +diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c +index 079b761bc70d..46195e0d0f4d 100644 +--- a/crypto/michael_mic.c ++++ b/crypto/michael_mic.c +@@ -184,3 +184,4 @@ module_exit(michael_mic_exit); + MODULE_LICENSE("GPL v2"); + MODULE_DESCRIPTION("Michael MIC"); + MODULE_AUTHOR("Jouni Malinen "); ++MODULE_ALIAS_CRYPTO("michael_mic"); +diff --git a/crypto/pcbc.c b/crypto/pcbc.c +index d1b8bdfb5855..f654965f0933 100644 +--- a/crypto/pcbc.c ++++ b/crypto/pcbc.c +@@ -295,3 +295,4 @@ module_exit(crypto_pcbc_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("PCBC block cipher algorithm"); ++MODULE_ALIAS_CRYPTO("pcbc"); +diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c +index 309d345ead95..c305d4112735 100644 +--- a/crypto/pcrypt.c ++++ b/crypto/pcrypt.c +@@ -565,3 +565,4 @@ module_exit(pcrypt_exit); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Steffen Klassert "); + MODULE_DESCRIPTION("Parallel crypto wrapper"); ++MODULE_ALIAS_CRYPTO("pcrypt"); +diff --git a/crypto/rmd128.c b/crypto/rmd128.c +index 8a0f68b7f257..049486ede938 100644 +--- a/crypto/rmd128.c ++++ b/crypto/rmd128.c +@@ -327,3 +327,4 @@ module_exit(rmd128_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Adrian-Ken Rueegsegger "); + MODULE_DESCRIPTION("RIPEMD-128 Message Digest"); ++MODULE_ALIAS_CRYPTO("rmd128"); +diff --git a/crypto/rmd160.c b/crypto/rmd160.c +index 525d7bb752cf..de585e51d455 100644 +--- a/crypto/rmd160.c ++++ b/crypto/rmd160.c +@@ -371,3 +371,4 @@ module_exit(rmd160_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Adrian-Ken Rueegsegger "); + MODULE_DESCRIPTION("RIPEMD-160 Message Digest"); ++MODULE_ALIAS_CRYPTO("rmd160"); +diff --git a/crypto/rmd256.c b/crypto/rmd256.c +index 69293d9b56e0..4ec02a754e09 100644 +--- a/crypto/rmd256.c ++++ b/crypto/rmd256.c +@@ -346,3 +346,4 @@ module_exit(rmd256_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Adrian-Ken Rueegsegger "); + MODULE_DESCRIPTION("RIPEMD-256 Message Digest"); ++MODULE_ALIAS_CRYPTO("rmd256"); +diff --git a/crypto/rmd320.c b/crypto/rmd320.c +index 09f97dfdfbba..770f2cb369f8 100644 +--- a/crypto/rmd320.c ++++ b/crypto/rmd320.c +@@ -395,3 +395,4 @@ module_exit(rmd320_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Adrian-Ken Rueegsegger "); + MODULE_DESCRIPTION("RIPEMD-320 Message Digest"); ++MODULE_ALIAS_CRYPTO("rmd320"); +diff --git a/crypto/salsa20_generic.c b/crypto/salsa20_generic.c +index 9a4770c02284..f550b5d94630 100644 +--- a/crypto/salsa20_generic.c ++++ b/crypto/salsa20_generic.c +@@ -248,4 +248,5 @@ module_exit(salsa20_generic_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION ("Salsa20 stream cipher algorithm"); +-MODULE_ALIAS("salsa20"); ++MODULE_ALIAS_CRYPTO("salsa20"); ++MODULE_ALIAS_CRYPTO("salsa20-generic"); +diff --git a/crypto/seed.c b/crypto/seed.c +index 9c904d6d2151..c6ba8438be43 100644 +--- a/crypto/seed.c ++++ b/crypto/seed.c +@@ -476,3 +476,4 @@ module_exit(seed_fini); + MODULE_DESCRIPTION("SEED Cipher Algorithm"); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Hye-Shik Chang , Kim Hyun "); ++MODULE_ALIAS_CRYPTO("seed"); +diff --git a/crypto/seqiv.c b/crypto/seqiv.c +index f2cba4ed6f25..49a4069ff453 100644 +--- a/crypto/seqiv.c ++++ b/crypto/seqiv.c +@@ -362,3 +362,4 @@ module_exit(seqiv_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Sequence Number IV Generator"); ++MODULE_ALIAS_CRYPTO("seqiv"); +diff --git a/crypto/serpent_generic.c b/crypto/serpent_generic.c +index 7ddbd7e88859..94970a794975 100644 +--- a/crypto/serpent_generic.c ++++ b/crypto/serpent_generic.c +@@ -665,5 +665,6 @@ module_exit(serpent_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Serpent and tnepres (kerneli compatible serpent reversed) Cipher Algorithm"); + MODULE_AUTHOR("Dag Arne Osvik "); +-MODULE_ALIAS("tnepres"); +-MODULE_ALIAS("serpent"); ++MODULE_ALIAS_CRYPTO("tnepres"); ++MODULE_ALIAS_CRYPTO("serpent"); ++MODULE_ALIAS_CRYPTO("serpent-generic"); +diff --git a/crypto/sha1_generic.c b/crypto/sha1_generic.c +index 42794803c480..fdf7c00de4b0 100644 +--- a/crypto/sha1_generic.c ++++ b/crypto/sha1_generic.c +@@ -153,4 +153,5 @@ module_exit(sha1_generic_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); + +-MODULE_ALIAS("sha1"); ++MODULE_ALIAS_CRYPTO("sha1"); ++MODULE_ALIAS_CRYPTO("sha1-generic"); +diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c +index 543366779524..136381bdd48d 100644 +--- a/crypto/sha256_generic.c ++++ b/crypto/sha256_generic.c +@@ -384,5 +384,7 @@ module_exit(sha256_generic_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm"); + +-MODULE_ALIAS("sha224"); +-MODULE_ALIAS("sha256"); ++MODULE_ALIAS_CRYPTO("sha224"); ++MODULE_ALIAS_CRYPTO("sha224-generic"); ++MODULE_ALIAS_CRYPTO("sha256"); ++MODULE_ALIAS_CRYPTO("sha256-generic"); +diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c +index 6ed124f3ea0f..6c6d901a7cc1 100644 +--- a/crypto/sha512_generic.c ++++ b/crypto/sha512_generic.c +@@ -287,5 +287,7 @@ module_exit(sha512_generic_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms"); + +-MODULE_ALIAS("sha384"); +-MODULE_ALIAS("sha512"); ++MODULE_ALIAS_CRYPTO("sha384"); ++MODULE_ALIAS_CRYPTO("sha384-generic"); ++MODULE_ALIAS_CRYPTO("sha512"); ++MODULE_ALIAS_CRYPTO("sha512-generic"); +diff --git a/crypto/tea.c b/crypto/tea.c +index 0a572323ee4a..b70b441c7d1e 100644 +--- a/crypto/tea.c ++++ b/crypto/tea.c +@@ -270,8 +270,9 @@ static void __exit tea_mod_fini(void) + crypto_unregister_algs(tea_algs, ARRAY_SIZE(tea_algs)); + } + +-MODULE_ALIAS("xtea"); +-MODULE_ALIAS("xeta"); ++MODULE_ALIAS_CRYPTO("tea"); ++MODULE_ALIAS_CRYPTO("xtea"); ++MODULE_ALIAS_CRYPTO("xeta"); + + module_init(tea_mod_init); + module_exit(tea_mod_fini); +diff --git a/crypto/tgr192.c b/crypto/tgr192.c +index 87403556fd0b..f7ed2fba396c 100644 +--- a/crypto/tgr192.c ++++ b/crypto/tgr192.c +@@ -676,8 +676,9 @@ static void __exit tgr192_mod_fini(void) + crypto_unregister_shashes(tgr_algs, ARRAY_SIZE(tgr_algs)); + } + +-MODULE_ALIAS("tgr160"); +-MODULE_ALIAS("tgr128"); ++MODULE_ALIAS_CRYPTO("tgr192"); ++MODULE_ALIAS_CRYPTO("tgr160"); ++MODULE_ALIAS_CRYPTO("tgr128"); + + module_init(tgr192_mod_init); + module_exit(tgr192_mod_fini); +diff --git a/crypto/twofish_generic.c b/crypto/twofish_generic.c +index 2d5000552d0f..ebf7a3efb572 100644 +--- a/crypto/twofish_generic.c ++++ b/crypto/twofish_generic.c +@@ -211,4 +211,5 @@ module_exit(twofish_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION ("Twofish Cipher Algorithm"); +-MODULE_ALIAS("twofish"); ++MODULE_ALIAS_CRYPTO("twofish"); ++MODULE_ALIAS_CRYPTO("twofish-generic"); +diff --git a/crypto/vmac.c b/crypto/vmac.c +index 2eb11a30c29c..bf2d3a89845f 100644 +--- a/crypto/vmac.c ++++ b/crypto/vmac.c +@@ -713,3 +713,4 @@ module_exit(vmac_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("VMAC hash algorithm"); ++MODULE_ALIAS_CRYPTO("vmac"); +diff --git a/crypto/wp512.c b/crypto/wp512.c +index 180f1d6e03f4..253db94b5479 100644 +--- a/crypto/wp512.c ++++ b/crypto/wp512.c +@@ -1167,8 +1167,9 @@ static void __exit wp512_mod_fini(void) + crypto_unregister_shashes(wp_algs, ARRAY_SIZE(wp_algs)); + } + +-MODULE_ALIAS("wp384"); +-MODULE_ALIAS("wp256"); ++MODULE_ALIAS_CRYPTO("wp512"); ++MODULE_ALIAS_CRYPTO("wp384"); ++MODULE_ALIAS_CRYPTO("wp256"); + + module_init(wp512_mod_init); + module_exit(wp512_mod_fini); +diff --git a/crypto/xcbc.c b/crypto/xcbc.c +index a5fbdf3738cf..df90b332554c 100644 +--- a/crypto/xcbc.c ++++ b/crypto/xcbc.c +@@ -286,3 +286,4 @@ module_exit(crypto_xcbc_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("XCBC keyed hash algorithm"); ++MODULE_ALIAS_CRYPTO("xcbc"); +diff --git a/crypto/xts.c b/crypto/xts.c +index ca1608f44cb5..f6fd43f100c8 100644 +--- a/crypto/xts.c ++++ b/crypto/xts.c +@@ -362,3 +362,4 @@ module_exit(crypto_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("XTS block cipher mode"); ++MODULE_ALIAS_CRYPTO("xts"); +diff --git a/crypto/zlib.c b/crypto/zlib.c +index 06b62e5cdcc7..d98078835281 100644 +--- a/crypto/zlib.c ++++ b/crypto/zlib.c +@@ -378,3 +378,4 @@ module_exit(zlib_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Zlib Compression Algorithm"); + MODULE_AUTHOR("Sony Corporation"); ++MODULE_ALIAS_CRYPTO("zlib"); +diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c +index 37acda6fa7e4..136803c47cdb 100644 +--- a/drivers/ata/libata-sff.c ++++ b/drivers/ata/libata-sff.c +@@ -1333,7 +1333,19 @@ void ata_sff_flush_pio_task(struct ata_port *ap) + DPRINTK("ENTER\n"); + + cancel_delayed_work_sync(&ap->sff_pio_task); ++ ++ /* ++ * We wanna reset the HSM state to IDLE. If we do so without ++ * grabbing the port lock, critical sections protected by it which ++ * expect the HSM state to stay stable may get surprised. For ++ * example, we may set IDLE in between the time ++ * __ata_sff_port_intr() checks for HSM_ST_IDLE and before it calls ++ * ata_sff_hsm_move() causing ata_sff_hsm_move() to BUG(). ++ */ ++ spin_lock_irq(ap->lock); + ap->hsm_task_state = HSM_ST_IDLE; ++ spin_unlock_irq(ap->lock); ++ + ap->sff_pio_task_link = NULL; + + if (ata_msg_ctl(ap)) +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 523524b68022..f71e09d6cfe6 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -799,7 +799,7 @@ static int dma_dwc_init(struct sata_dwc_device *hsdev, int irq) + if (err) { + dev_err(host_pvt.dwc_dev, "%s: dma_request_interrupts returns" + " %d\n", __func__, err); +- goto error_out; ++ return err; + } + + /* Enabe DMA */ +@@ -810,11 +810,6 @@ static int dma_dwc_init(struct sata_dwc_device *hsdev, int irq) + sata_dma_regs); + + return 0; +- +-error_out: +- dma_dwc_exit(hsdev); +- +- return err; + } + + static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val) +@@ -1664,7 +1659,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) + char *ver = (char *)&versionr; + u8 *base = NULL; + int err = 0; +- int irq, rc; ++ int irq; + struct ata_host *host; + struct ata_port_info pi = sata_dwc_port_info[0]; + const struct ata_port_info *ppi[] = { &pi, NULL }; +@@ -1727,7 +1722,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) + if (irq == NO_IRQ) { + dev_err(&ofdev->dev, "no SATA DMA irq\n"); + err = -ENODEV; +- goto error_out; ++ goto error_iomap; + } + + /* Get physical SATA DMA register base address */ +@@ -1736,14 +1731,16 @@ static int sata_dwc_probe(struct platform_device *ofdev) + dev_err(&ofdev->dev, "ioremap failed for AHBDMA register" + " address\n"); + err = -ENODEV; +- goto error_out; ++ goto error_iomap; + } + + /* Save dev for later use in dev_xxx() routines */ + host_pvt.dwc_dev = &ofdev->dev; + + /* Initialize AHB DMAC */ +- dma_dwc_init(hsdev, irq); ++ err = dma_dwc_init(hsdev, irq); ++ if (err) ++ goto error_dma_iomap; + + /* Enable SATA Interrupts */ + sata_dwc_enable_interrupts(hsdev); +@@ -1761,9 +1758,8 @@ static int sata_dwc_probe(struct platform_device *ofdev) + * device discovery process, invoking our port_start() handler & + * error_handler() to execute a dummy Softreset EH session + */ +- rc = ata_host_activate(host, irq, sata_dwc_isr, 0, &sata_dwc_sht); +- +- if (rc != 0) ++ err = ata_host_activate(host, irq, sata_dwc_isr, 0, &sata_dwc_sht); ++ if (err) + dev_err(&ofdev->dev, "failed to activate host"); + + dev_set_drvdata(&ofdev->dev, host); +@@ -1772,7 +1768,8 @@ static int sata_dwc_probe(struct platform_device *ofdev) + error_out: + /* Free SATA DMA resources */ + dma_dwc_exit(hsdev); +- ++error_dma_iomap: ++ iounmap((void __iomem *)host_pvt.sata_dma_regs); + error_iomap: + iounmap(base); + error_kmalloc: +@@ -1793,6 +1790,7 @@ static int sata_dwc_remove(struct platform_device *ofdev) + /* Free SATA DMA resources */ + dma_dwc_exit(hsdev); + ++ iounmap((void __iomem *)host_pvt.sata_dma_regs); + iounmap(hsdev->reg_base); + kfree(hsdev); + kfree(host); +diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c +index 104a040f24de..6efdbeafa33c 100644 +--- a/drivers/block/drbd/drbd_req.c ++++ b/drivers/block/drbd/drbd_req.c +@@ -1310,6 +1310,7 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct + struct request_queue * const b = + mdev->ldev->backing_bdev->bd_disk->queue; + if (b->merge_bvec_fn) { ++ bvm->bi_bdev = mdev->ldev->backing_bdev; + backing_limit = b->merge_bvec_fn(b, bvm, bvec); + limit = min(limit, backing_limit); + } +diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c +index 372ae72cce34..e990deed2d33 100644 +--- a/drivers/bus/mvebu-mbus.c ++++ b/drivers/bus/mvebu-mbus.c +@@ -181,12 +181,25 @@ static void mvebu_mbus_disable_window(struct mvebu_mbus_state *mbus, + } + + /* Checks whether the given window number is available */ ++ ++/* On Armada XP, 375 and 38x the MBus window 13 has the remap ++ * capability, like windows 0 to 7. However, the mvebu-mbus driver ++ * isn't currently taking into account this special case, which means ++ * that when window 13 is actually used, the remap registers are left ++ * to 0, making the device using this MBus window unavailable. The ++ * quick fix for stable is to not use window 13. A follow up patch ++ * will correctly handle this window. ++*/ + static int mvebu_mbus_window_is_free(struct mvebu_mbus_state *mbus, + const int win) + { + void __iomem *addr = mbus->mbuswins_base + + mbus->soc->win_cfg_offset(win); + u32 ctrl = readl(addr + WIN_CTRL_OFF); ++ ++ if (win == 13) ++ return false; ++ + return !(ctrl & WIN_CTRL_ENABLE); + } + +diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c +index e252939b9ee1..831b48287a22 100644 +--- a/drivers/clocksource/exynos_mct.c ++++ b/drivers/clocksource/exynos_mct.c +@@ -98,8 +98,8 @@ static void exynos4_mct_write(unsigned int value, unsigned long offset) + __raw_writel(value, reg_base + offset); + + if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) { +- stat_addr = (offset & ~EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET; +- switch (offset & EXYNOS4_MCT_L_MASK) { ++ stat_addr = (offset & EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET; ++ switch (offset & ~EXYNOS4_MCT_L_MASK) { + case MCT_L_TCON_OFFSET: + mask = 1 << 3; /* L_TCON write status */ + break; +diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c +index 633ba945e153..c178ed8c3908 100644 +--- a/drivers/crypto/padlock-aes.c ++++ b/drivers/crypto/padlock-aes.c +@@ -563,4 +563,4 @@ MODULE_DESCRIPTION("VIA PadLock AES algorithm support"); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Michal Ludvig"); + +-MODULE_ALIAS("aes"); ++MODULE_ALIAS_CRYPTO("aes"); +diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c +index 9266c0e25492..93d7753ab38a 100644 +--- a/drivers/crypto/padlock-sha.c ++++ b/drivers/crypto/padlock-sha.c +@@ -593,7 +593,7 @@ MODULE_DESCRIPTION("VIA PadLock SHA1/SHA256 algorithms support."); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Michal Ludvig"); + +-MODULE_ALIAS("sha1-all"); +-MODULE_ALIAS("sha256-all"); +-MODULE_ALIAS("sha1-padlock"); +-MODULE_ALIAS("sha256-padlock"); ++MODULE_ALIAS_CRYPTO("sha1-all"); ++MODULE_ALIAS_CRYPTO("sha256-all"); ++MODULE_ALIAS_CRYPTO("sha1-padlock"); ++MODULE_ALIAS_CRYPTO("sha256-padlock"); +diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c +index 92105f3dc8e0..e4cea7c45142 100644 +--- a/drivers/crypto/ux500/cryp/cryp_core.c ++++ b/drivers/crypto/ux500/cryp/cryp_core.c +@@ -1810,7 +1810,7 @@ module_exit(ux500_cryp_mod_fini); + module_param(cryp_mode, int, 0); + + MODULE_DESCRIPTION("Driver for ST-Ericsson UX500 CRYP crypto engine."); +-MODULE_ALIAS("aes-all"); +-MODULE_ALIAS("des-all"); ++MODULE_ALIAS_CRYPTO("aes-all"); ++MODULE_ALIAS_CRYPTO("des-all"); + + MODULE_LICENSE("GPL"); +diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c +index 1c73f4fbc252..8e5e0187506f 100644 +--- a/drivers/crypto/ux500/hash/hash_core.c ++++ b/drivers/crypto/ux500/hash/hash_core.c +@@ -1995,7 +1995,7 @@ module_exit(ux500_hash_mod_fini); + MODULE_DESCRIPTION("Driver for ST-Ericsson UX500 HASH engine."); + MODULE_LICENSE("GPL"); + +-MODULE_ALIAS("sha1-all"); +-MODULE_ALIAS("sha256-all"); +-MODULE_ALIAS("hmac-sha1-all"); +-MODULE_ALIAS("hmac-sha256-all"); ++MODULE_ALIAS_CRYPTO("sha1-all"); ++MODULE_ALIAS_CRYPTO("sha256-all"); ++MODULE_ALIAS_CRYPTO("hmac-sha1-all"); ++MODULE_ALIAS_CRYPTO("hmac-sha256-all"); +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index 5b88c83888d1..ccbffd0d7a02 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -408,7 +408,7 @@ static ssize_t gpio_value_store(struct device *dev, + return status; + } + +-static const DEVICE_ATTR(value, 0644, ++static DEVICE_ATTR(value, 0644, + gpio_value_show, gpio_value_store); + + static irqreturn_t gpio_sysfs_irq(int irq, void *priv) +@@ -633,18 +633,16 @@ static ssize_t gpio_active_low_store(struct device *dev, + return status ? : size; + } + +-static const DEVICE_ATTR(active_low, 0644, ++static DEVICE_ATTR(active_low, 0644, + gpio_active_low_show, gpio_active_low_store); + +-static const struct attribute *gpio_attrs[] = { ++static struct attribute *gpio_attrs[] = { + &dev_attr_value.attr, + &dev_attr_active_low.attr, + NULL, + }; + +-static const struct attribute_group gpio_attr_group = { +- .attrs = (struct attribute **) gpio_attrs, +-}; ++ATTRIBUTE_GROUPS(gpio); + + /* + * /sys/class/gpio/gpiochipN/ +@@ -680,16 +678,13 @@ static ssize_t chip_ngpio_show(struct device *dev, + } + static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL); + +-static const struct attribute *gpiochip_attrs[] = { ++static struct attribute *gpiochip_attrs[] = { + &dev_attr_base.attr, + &dev_attr_label.attr, + &dev_attr_ngpio.attr, + NULL, + }; +- +-static const struct attribute_group gpiochip_attr_group = { +- .attrs = (struct attribute **) gpiochip_attrs, +-}; ++ATTRIBUTE_GROUPS(gpiochip); + + /* + * /sys/class/gpio/export ... write-only +@@ -844,18 +839,15 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) + if (desc->chip->names && desc->chip->names[offset]) + ioname = desc->chip->names[offset]; + +- dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), +- desc, ioname ? ioname : "gpio%u", +- desc_to_gpio(desc)); ++ dev = device_create_with_groups(&gpio_class, desc->chip->dev, ++ MKDEV(0, 0), desc, gpio_groups, ++ ioname ? ioname : "gpio%u", ++ desc_to_gpio(desc)); + if (IS_ERR(dev)) { + status = PTR_ERR(dev); + goto fail_unlock; + } + +- status = sysfs_create_group(&dev->kobj, &gpio_attr_group); +- if (status) +- goto fail_unregister_device; +- + if (direction_may_change) { + status = device_create_file(dev, &dev_attr_direction); + if (status) +@@ -866,13 +858,15 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) + !test_bit(FLAG_IS_OUT, &desc->flags))) { + status = device_create_file(dev, &dev_attr_edge); + if (status) +- goto fail_unregister_device; ++ goto fail_remove_attr_direction; + } + + set_bit(FLAG_EXPORT, &desc->flags); + mutex_unlock(&sysfs_lock); + return 0; + ++fail_remove_attr_direction: ++ device_remove_file(dev, &dev_attr_direction); + fail_unregister_device: + device_unregister(dev); + fail_unlock: +@@ -1006,6 +1000,8 @@ void gpiod_unexport(struct gpio_desc *desc) + mutex_unlock(&sysfs_lock); + + if (dev) { ++ device_remove_file(dev, &dev_attr_edge); ++ device_remove_file(dev, &dev_attr_direction); + device_unregister(dev); + put_device(dev); + } +@@ -1030,13 +1026,13 @@ static int gpiochip_export(struct gpio_chip *chip) + + /* use chip->base for the ID; it's already known to be unique */ + mutex_lock(&sysfs_lock); +- dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip, +- "gpiochip%d", chip->base); +- if (!IS_ERR(dev)) { +- status = sysfs_create_group(&dev->kobj, +- &gpiochip_attr_group); +- } else ++ dev = device_create_with_groups(&gpio_class, chip->dev, MKDEV(0, 0), ++ chip, gpiochip_groups, ++ "gpiochip%d", chip->base); ++ if (IS_ERR(dev)) + status = PTR_ERR(dev); ++ else ++ status = 0; + chip->exported = (status == 0); + mutex_unlock(&sysfs_lock); + +diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c +index 7410a507eacc..3153eabde39b 100644 +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -4978,7 +4978,7 @@ static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task) + if (!mutex_is_locked(mutex)) + return false; + +-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES) ++#if defined(CONFIG_SMP) && !defined(CONFIG_DEBUG_MUTEXES) + return mutex->owner == task; + #else + /* Since UP may be pre-empted, we cannot assume that we own the lock */ +diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c +index 5600d4c5f981..64d6cfba9952 100644 +--- a/drivers/gpu/drm/radeon/radeon_asic.c ++++ b/drivers/gpu/drm/radeon/radeon_asic.c +@@ -335,6 +335,20 @@ static struct radeon_asic_ring r300_gfx_ring = { + .set_wptr = &r100_gfx_set_wptr, + }; + ++static struct radeon_asic_ring rv515_gfx_ring = { ++ .ib_execute = &r100_ring_ib_execute, ++ .emit_fence = &r300_fence_ring_emit, ++ .emit_semaphore = &r100_semaphore_ring_emit, ++ .cs_parse = &r300_cs_parse, ++ .ring_start = &rv515_ring_start, ++ .ring_test = &r100_ring_test, ++ .ib_test = &r100_ib_test, ++ .is_lockup = &r100_gpu_is_lockup, ++ .get_rptr = &r100_gfx_get_rptr, ++ .get_wptr = &r100_gfx_get_wptr, ++ .set_wptr = &r100_gfx_set_wptr, ++}; ++ + static struct radeon_asic r300_asic = { + .init = &r300_init, + .fini = &r300_fini, +@@ -756,7 +770,7 @@ static struct radeon_asic rv515_asic = { + .set_page = &rv370_pcie_gart_set_page, + }, + .ring = { +- [RADEON_RING_TYPE_GFX_INDEX] = &r300_gfx_ring ++ [RADEON_RING_TYPE_GFX_INDEX] = &rv515_gfx_ring + }, + .irq = { + .set = &rs600_irq_set, +@@ -823,7 +837,7 @@ static struct radeon_asic r520_asic = { + .set_page = &rv370_pcie_gart_set_page, + }, + .ring = { +- [RADEON_RING_TYPE_GFX_INDEX] = &r300_gfx_ring ++ [RADEON_RING_TYPE_GFX_INDEX] = &rv515_gfx_ring + }, + .irq = { + .set = &rs600_irq_set, +diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c +index cfb513f933d5..0095ee7fce34 100644 +--- a/drivers/gpu/drm/radeon/radeon_pm.c ++++ b/drivers/gpu/drm/radeon/radeon_pm.c +@@ -1260,8 +1260,39 @@ dpm_failed: + return ret; + } + ++struct radeon_dpm_quirk { ++ u32 chip_vendor; ++ u32 chip_device; ++ u32 subsys_vendor; ++ u32 subsys_device; ++}; ++ ++/* cards with dpm stability problems */ ++static struct radeon_dpm_quirk radeon_dpm_quirk_list[] = { ++ /* TURKS - https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1386534 */ ++ { PCI_VENDOR_ID_ATI, 0x6759, 0x1682, 0x3195 }, ++ /* TURKS - https://bugzilla.kernel.org/show_bug.cgi?id=83731 */ ++ { PCI_VENDOR_ID_ATI, 0x6840, 0x1179, 0xfb81 }, ++ { 0, 0, 0, 0 }, ++}; ++ + int radeon_pm_init(struct radeon_device *rdev) + { ++ struct radeon_dpm_quirk *p = radeon_dpm_quirk_list; ++ bool disable_dpm = false; ++ ++ /* Apply dpm quirks */ ++ while (p && p->chip_device != 0) { ++ if (rdev->pdev->vendor == p->chip_vendor && ++ rdev->pdev->device == p->chip_device && ++ rdev->pdev->subsystem_vendor == p->subsys_vendor && ++ rdev->pdev->subsystem_device == p->subsys_device) { ++ disable_dpm = true; ++ break; ++ } ++ ++p; ++ } ++ + /* enable dpm on rv6xx+ */ + switch (rdev->family) { + case CHIP_RV610: +@@ -1316,6 +1347,8 @@ int radeon_pm_init(struct radeon_device *rdev) + (!(rdev->flags & RADEON_IS_IGP)) && + (!rdev->smc_fw)) + rdev->pm.pm_method = PM_METHOD_PROFILE; ++ else if (disable_dpm && (radeon_dpm == -1)) ++ rdev->pm.pm_method = PM_METHOD_PROFILE; + else if (radeon_dpm == 0) + rdev->pm.pm_method = PM_METHOD_PROFILE; + else +diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c +index 879e62844b2b..35bf2bba69bf 100644 +--- a/drivers/gpu/drm/radeon/si_dpm.c ++++ b/drivers/gpu/drm/radeon/si_dpm.c +@@ -2900,6 +2900,22 @@ static int si_init_smc_spll_table(struct radeon_device *rdev) + return ret; + } + ++struct si_dpm_quirk { ++ u32 chip_vendor; ++ u32 chip_device; ++ u32 subsys_vendor; ++ u32 subsys_device; ++ u32 max_sclk; ++ u32 max_mclk; ++}; ++ ++/* cards with dpm stability problems */ ++static struct si_dpm_quirk si_dpm_quirk_list[] = { ++ /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */ ++ { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 }, ++ { 0, 0, 0, 0 }, ++}; ++ + static void si_apply_state_adjust_rules(struct radeon_device *rdev, + struct radeon_ps *rps) + { +@@ -2910,7 +2926,22 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, + u32 mclk, sclk; + u16 vddc, vddci; + u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; ++ u32 max_sclk = 0, max_mclk = 0; + int i; ++ struct si_dpm_quirk *p = si_dpm_quirk_list; ++ ++ /* Apply dpm quirks */ ++ while (p && p->chip_device != 0) { ++ if (rdev->pdev->vendor == p->chip_vendor && ++ rdev->pdev->device == p->chip_device && ++ rdev->pdev->subsystem_vendor == p->subsys_vendor && ++ rdev->pdev->subsystem_device == p->subsys_device) { ++ max_sclk = p->max_sclk; ++ max_mclk = p->max_mclk; ++ break; ++ } ++ ++p; ++ } + + if ((rdev->pm.dpm.new_active_crtc_count > 1) || + ni_dpm_vblank_too_short(rdev)) +@@ -2964,6 +2995,14 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, + if (ps->performance_levels[i].mclk > max_mclk_vddc) + ps->performance_levels[i].mclk = max_mclk_vddc; + } ++ if (max_mclk) { ++ if (ps->performance_levels[i].mclk > max_mclk) ++ ps->performance_levels[i].mclk = max_mclk; ++ } ++ if (max_sclk) { ++ if (ps->performance_levels[i].sclk > max_sclk) ++ ps->performance_levels[i].sclk = max_sclk; ++ } + } + + /* XXX validate the min clocks required for display */ +diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c +index ce953d895f5b..fb787c3e88d9 100644 +--- a/drivers/input/evdev.c ++++ b/drivers/input/evdev.c +@@ -757,20 +757,23 @@ static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) + */ + static int evdev_handle_get_val(struct evdev_client *client, + struct input_dev *dev, unsigned int type, +- unsigned long *bits, unsigned int max, +- unsigned int size, void __user *p, int compat) ++ unsigned long *bits, unsigned int maxbit, ++ unsigned int maxlen, void __user *p, ++ int compat) + { + int ret; + unsigned long *mem; ++ size_t len; + +- mem = kmalloc(sizeof(unsigned long) * max, GFP_KERNEL); ++ len = BITS_TO_LONGS(maxbit) * sizeof(unsigned long); ++ mem = kmalloc(len, GFP_KERNEL); + if (!mem) + return -ENOMEM; + + spin_lock_irq(&dev->event_lock); + spin_lock(&client->buffer_lock); + +- memcpy(mem, bits, sizeof(unsigned long) * max); ++ memcpy(mem, bits, len); + + spin_unlock(&dev->event_lock); + +@@ -778,7 +781,7 @@ static int evdev_handle_get_val(struct evdev_client *client, + + spin_unlock_irq(&client->buffer_lock); + +- ret = bits_to_user(mem, max, size, p, compat); ++ ret = bits_to_user(mem, maxbit, maxlen, p, compat); + if (ret < 0) + evdev_queue_syn_dropped(client); + +diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c +index a87d3fab0271..d290e8396116 100644 +--- a/drivers/md/dm-cache-metadata.c ++++ b/drivers/md/dm-cache-metadata.c +@@ -94,6 +94,9 @@ struct cache_disk_superblock { + } __packed; + + struct dm_cache_metadata { ++ atomic_t ref_count; ++ struct list_head list; ++ + struct block_device *bdev; + struct dm_block_manager *bm; + struct dm_space_map *metadata_sm; +@@ -669,10 +672,10 @@ static void unpack_value(__le64 value_le, dm_oblock_t *block, unsigned *flags) + + /*----------------------------------------------------------------*/ + +-struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, +- sector_t data_block_size, +- bool may_format_device, +- size_t policy_hint_size) ++static struct dm_cache_metadata *metadata_open(struct block_device *bdev, ++ sector_t data_block_size, ++ bool may_format_device, ++ size_t policy_hint_size) + { + int r; + struct dm_cache_metadata *cmd; +@@ -683,6 +686,7 @@ struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, + return NULL; + } + ++ atomic_set(&cmd->ref_count, 1); + init_rwsem(&cmd->root_lock); + cmd->bdev = bdev; + cmd->data_block_size = data_block_size; +@@ -705,10 +709,95 @@ struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, + return cmd; + } + ++/* ++ * We keep a little list of ref counted metadata objects to prevent two ++ * different target instances creating separate bufio instances. This is ++ * an issue if a table is reloaded before the suspend. ++ */ ++static DEFINE_MUTEX(table_lock); ++static LIST_HEAD(table); ++ ++static struct dm_cache_metadata *lookup(struct block_device *bdev) ++{ ++ struct dm_cache_metadata *cmd; ++ ++ list_for_each_entry(cmd, &table, list) ++ if (cmd->bdev == bdev) { ++ atomic_inc(&cmd->ref_count); ++ return cmd; ++ } ++ ++ return NULL; ++} ++ ++static struct dm_cache_metadata *lookup_or_open(struct block_device *bdev, ++ sector_t data_block_size, ++ bool may_format_device, ++ size_t policy_hint_size) ++{ ++ struct dm_cache_metadata *cmd, *cmd2; ++ ++ mutex_lock(&table_lock); ++ cmd = lookup(bdev); ++ mutex_unlock(&table_lock); ++ ++ if (cmd) ++ return cmd; ++ ++ cmd = metadata_open(bdev, data_block_size, may_format_device, policy_hint_size); ++ if (cmd) { ++ mutex_lock(&table_lock); ++ cmd2 = lookup(bdev); ++ if (cmd2) { ++ mutex_unlock(&table_lock); ++ __destroy_persistent_data_objects(cmd); ++ kfree(cmd); ++ return cmd2; ++ } ++ list_add(&cmd->list, &table); ++ mutex_unlock(&table_lock); ++ } ++ ++ return cmd; ++} ++ ++static bool same_params(struct dm_cache_metadata *cmd, sector_t data_block_size) ++{ ++ if (cmd->data_block_size != data_block_size) { ++ DMERR("data_block_size (%llu) different from that in metadata (%llu)\n", ++ (unsigned long long) data_block_size, ++ (unsigned long long) cmd->data_block_size); ++ return false; ++ } ++ ++ return true; ++} ++ ++struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, ++ sector_t data_block_size, ++ bool may_format_device, ++ size_t policy_hint_size) ++{ ++ struct dm_cache_metadata *cmd = lookup_or_open(bdev, data_block_size, ++ may_format_device, policy_hint_size); ++ if (cmd && !same_params(cmd, data_block_size)) { ++ dm_cache_metadata_close(cmd); ++ return NULL; ++ } ++ ++ return cmd; ++} ++ + void dm_cache_metadata_close(struct dm_cache_metadata *cmd) + { +- __destroy_persistent_data_objects(cmd); +- kfree(cmd); ++ if (atomic_dec_and_test(&cmd->ref_count)) { ++ mutex_lock(&table_lock); ++ list_del(&cmd->list); ++ mutex_unlock(&table_lock); ++ ++ __destroy_persistent_data_objects(cmd); ++ kfree(cmd); ++ } + } + + /* +diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c +index ff284b7a17bd..c10dec0f6e9d 100644 +--- a/drivers/md/dm-cache-target.c ++++ b/drivers/md/dm-cache-target.c +@@ -222,7 +222,13 @@ struct cache { + struct list_head need_commit_migrations; + sector_t migration_threshold; + wait_queue_head_t migration_wait; +- atomic_t nr_migrations; ++ atomic_t nr_allocated_migrations; ++ ++ /* ++ * The number of in flight migrations that are performing ++ * background io. eg, promotion, writeback. ++ */ ++ atomic_t nr_io_migrations; + + wait_queue_head_t quiescing_wait; + atomic_t quiescing; +@@ -259,7 +265,6 @@ struct cache { + struct dm_deferred_set *all_io_ds; + + mempool_t *migration_pool; +- struct dm_cache_migration *next_migration; + + struct dm_cache_policy *policy; + unsigned policy_nr_args; +@@ -350,10 +355,31 @@ static void free_prison_cell(struct cache *cache, struct dm_bio_prison_cell *cel + dm_bio_prison_free_cell(cache->prison, cell); + } + ++static struct dm_cache_migration *alloc_migration(struct cache *cache) ++{ ++ struct dm_cache_migration *mg; ++ ++ mg = mempool_alloc(cache->migration_pool, GFP_NOWAIT); ++ if (mg) { ++ mg->cache = cache; ++ atomic_inc(&mg->cache->nr_allocated_migrations); ++ } ++ ++ return mg; ++} ++ ++static void free_migration(struct dm_cache_migration *mg) ++{ ++ if (atomic_dec_and_test(&mg->cache->nr_allocated_migrations)) ++ wake_up(&mg->cache->migration_wait); ++ ++ mempool_free(mg, mg->cache->migration_pool); ++} ++ + static int prealloc_data_structs(struct cache *cache, struct prealloc *p) + { + if (!p->mg) { +- p->mg = mempool_alloc(cache->migration_pool, GFP_NOWAIT); ++ p->mg = alloc_migration(cache); + if (!p->mg) + return -ENOMEM; + } +@@ -382,7 +408,7 @@ static void prealloc_free_structs(struct cache *cache, struct prealloc *p) + free_prison_cell(cache, p->cell1); + + if (p->mg) +- mempool_free(p->mg, cache->migration_pool); ++ free_migration(p->mg); + } + + static struct dm_cache_migration *prealloc_get_migration(struct prealloc *p) +@@ -812,24 +838,14 @@ static void remap_to_origin_then_cache(struct cache *cache, struct bio *bio, + * Migration covers moving data from the origin device to the cache, or + * vice versa. + *--------------------------------------------------------------*/ +-static void free_migration(struct dm_cache_migration *mg) +-{ +- mempool_free(mg, mg->cache->migration_pool); +-} +- +-static void inc_nr_migrations(struct cache *cache) ++static void inc_io_migrations(struct cache *cache) + { +- atomic_inc(&cache->nr_migrations); ++ atomic_inc(&cache->nr_io_migrations); + } + +-static void dec_nr_migrations(struct cache *cache) ++static void dec_io_migrations(struct cache *cache) + { +- atomic_dec(&cache->nr_migrations); +- +- /* +- * Wake the worker in case we're suspending the target. +- */ +- wake_up(&cache->migration_wait); ++ atomic_dec(&cache->nr_io_migrations); + } + + static void __cell_defer(struct cache *cache, struct dm_bio_prison_cell *cell, +@@ -852,11 +868,10 @@ static void cell_defer(struct cache *cache, struct dm_bio_prison_cell *cell, + wake_worker(cache); + } + +-static void cleanup_migration(struct dm_cache_migration *mg) ++static void free_io_migration(struct dm_cache_migration *mg) + { +- struct cache *cache = mg->cache; ++ dec_io_migrations(mg->cache); + free_migration(mg); +- dec_nr_migrations(cache); + } + + static void migration_failure(struct dm_cache_migration *mg) +@@ -881,7 +896,7 @@ static void migration_failure(struct dm_cache_migration *mg) + cell_defer(cache, mg->new_ocell, true); + } + +- cleanup_migration(mg); ++ free_io_migration(mg); + } + + static void migration_success_pre_commit(struct dm_cache_migration *mg) +@@ -892,7 +907,7 @@ static void migration_success_pre_commit(struct dm_cache_migration *mg) + if (mg->writeback) { + clear_dirty(cache, mg->old_oblock, mg->cblock); + cell_defer(cache, mg->old_ocell, false); +- cleanup_migration(mg); ++ free_io_migration(mg); + return; + + } else if (mg->demote) { +@@ -902,14 +917,14 @@ static void migration_success_pre_commit(struct dm_cache_migration *mg) + mg->old_oblock); + if (mg->promote) + cell_defer(cache, mg->new_ocell, true); +- cleanup_migration(mg); ++ free_io_migration(mg); + return; + } + } else { + if (dm_cache_insert_mapping(cache->cmd, mg->cblock, mg->new_oblock)) { + DMWARN_LIMIT("promotion failed; couldn't update on disk metadata"); + policy_remove_mapping(cache->policy, mg->new_oblock); +- cleanup_migration(mg); ++ free_io_migration(mg); + return; + } + } +@@ -942,7 +957,7 @@ static void migration_success_post_commit(struct dm_cache_migration *mg) + } else { + if (mg->invalidate) + policy_remove_mapping(cache->policy, mg->old_oblock); +- cleanup_migration(mg); ++ free_io_migration(mg); + } + + } else { +@@ -957,7 +972,7 @@ static void migration_success_post_commit(struct dm_cache_migration *mg) + bio_endio(mg->new_ocell->holder, 0); + cell_defer(cache, mg->new_ocell, false); + } +- cleanup_migration(mg); ++ free_io_migration(mg); + } + } + +@@ -1169,7 +1184,7 @@ static void promote(struct cache *cache, struct prealloc *structs, + mg->new_ocell = cell; + mg->start_jiffies = jiffies; + +- inc_nr_migrations(cache); ++ inc_io_migrations(cache); + quiesce_migration(mg); + } + +@@ -1192,7 +1207,7 @@ static void writeback(struct cache *cache, struct prealloc *structs, + mg->new_ocell = NULL; + mg->start_jiffies = jiffies; + +- inc_nr_migrations(cache); ++ inc_io_migrations(cache); + quiesce_migration(mg); + } + +@@ -1218,7 +1233,7 @@ static void demote_then_promote(struct cache *cache, struct prealloc *structs, + mg->new_ocell = new_ocell; + mg->start_jiffies = jiffies; + +- inc_nr_migrations(cache); ++ inc_io_migrations(cache); + quiesce_migration(mg); + } + +@@ -1245,7 +1260,7 @@ static void invalidate(struct cache *cache, struct prealloc *structs, + mg->new_ocell = NULL; + mg->start_jiffies = jiffies; + +- inc_nr_migrations(cache); ++ inc_io_migrations(cache); + quiesce_migration(mg); + } + +@@ -1306,7 +1321,7 @@ static void process_discard_bio(struct cache *cache, struct bio *bio) + + static bool spare_migration_bandwidth(struct cache *cache) + { +- sector_t current_volume = (atomic_read(&cache->nr_migrations) + 1) * ++ sector_t current_volume = (atomic_read(&cache->nr_io_migrations) + 1) * + cache->sectors_per_block; + return current_volume < cache->migration_threshold; + } +@@ -1661,7 +1676,7 @@ static void stop_quiescing(struct cache *cache) + + static void wait_for_migrations(struct cache *cache) + { +- wait_event(cache->migration_wait, !atomic_read(&cache->nr_migrations)); ++ wait_event(cache->migration_wait, !atomic_read(&cache->nr_allocated_migrations)); + } + + static void stop_worker(struct cache *cache) +@@ -1772,9 +1787,6 @@ static void destroy(struct cache *cache) + { + unsigned i; + +- if (cache->next_migration) +- mempool_free(cache->next_migration, cache->migration_pool); +- + if (cache->migration_pool) + mempool_destroy(cache->migration_pool); + +@@ -2282,7 +2294,8 @@ static int cache_create(struct cache_args *ca, struct cache **result) + INIT_LIST_HEAD(&cache->quiesced_migrations); + INIT_LIST_HEAD(&cache->completed_migrations); + INIT_LIST_HEAD(&cache->need_commit_migrations); +- atomic_set(&cache->nr_migrations, 0); ++ atomic_set(&cache->nr_allocated_migrations, 0); ++ atomic_set(&cache->nr_io_migrations, 0); + init_waitqueue_head(&cache->migration_wait); + + init_waitqueue_head(&cache->quiescing_wait); +@@ -2342,8 +2355,6 @@ static int cache_create(struct cache_args *ca, struct cache **result) + goto bad; + } + +- cache->next_migration = NULL; +- + cache->need_tick_bio = true; + cache->sized = false; + cache->invalidate = false; +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 4913c0690872..175584ad643f 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -2896,7 +2896,8 @@ static int fetch_block(struct stripe_head *sh, struct stripe_head_state *s, + (s->failed >= 2 && fdev[1]->toread) || + (sh->raid_conf->level <= 5 && s->failed && fdev[0]->towrite && + !test_bit(R5_OVERWRITE, &fdev[0]->flags)) || +- (sh->raid_conf->level == 6 && s->failed && s->to_write))) { ++ ((sh->raid_conf->level == 6 || sh->sector >= sh->raid_conf->mddev->recovery_cp) ++ && s->failed && s->to_write))) { + /* we would like to get this block, possibly by computing it, + * otherwise read it if the backing disk is insync + */ +diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c +index 7e0176321aff..881bf89acfcc 100644 +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -2537,7 +2537,7 @@ out: + /* + * We have to delay this as it calls back into the driver. + */ +- if (cardint) ++ if (cardint && host->mmc->sdio_irqs) + mmc_signal_sdio_irq(host->mmc); + + return result; +diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c +index cc11f7f5e91d..1468c4658804 100644 +--- a/drivers/net/can/dev.c ++++ b/drivers/net/can/dev.c +@@ -664,10 +664,14 @@ static int can_changelink(struct net_device *dev, + if (dev->flags & IFF_UP) + return -EBUSY; + cm = nla_data(data[IFLA_CAN_CTRLMODE]); +- if (cm->flags & ~priv->ctrlmode_supported) ++ ++ /* check whether changed bits are allowed to be modified */ ++ if (cm->mask & ~priv->ctrlmode_supported) + return -EOPNOTSUPP; ++ ++ /* clear bits to be modified and copy the flag values */ + priv->ctrlmode &= ~cm->mask; +- priv->ctrlmode |= cm->flags; ++ priv->ctrlmode |= (cm->flags & cm->mask); + } + + if (data[IFLA_CAN_RESTART_MS]) { +diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c +index dae70d216762..78c65d327e33 100644 +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -3187,7 +3187,8 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe) + { + struct pci_dev *pdev; + +- if (pci_is_root_bus(dev->bus) || dev->subordinate || !dev->bus->self) ++ if (pci_is_root_bus(dev->bus) || dev->subordinate || ++ !dev->bus->self || dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET) + return -ENOTTY; + + list_for_each_entry(pdev, &dev->bus->devices, bus_list) +@@ -3221,7 +3222,8 @@ static int pci_dev_reset_slot_function(struct pci_dev *dev, int probe) + { + struct pci_dev *pdev; + +- if (dev->subordinate || !dev->slot) ++ if (dev->subordinate || !dev->slot || ++ dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET) + return -ENOTTY; + + list_for_each_entry(pdev, &dev->bus->devices, bus_list) +@@ -3452,6 +3454,20 @@ int pci_try_reset_function(struct pci_dev *dev) + } + EXPORT_SYMBOL_GPL(pci_try_reset_function); + ++/* Do any devices on or below this bus prevent a bus reset? */ ++static bool pci_bus_resetable(struct pci_bus *bus) ++{ ++ struct pci_dev *dev; ++ ++ list_for_each_entry(dev, &bus->devices, bus_list) { ++ if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || ++ (dev->subordinate && !pci_bus_resetable(dev->subordinate))) ++ return false; ++ } ++ ++ return true; ++} ++ + /* Lock devices from the top of the tree down */ + static void pci_bus_lock(struct pci_bus *bus) + { +@@ -3502,6 +3518,22 @@ unlock: + return 0; + } + ++/* Do any devices on or below this slot prevent a bus reset? */ ++static bool pci_slot_resetable(struct pci_slot *slot) ++{ ++ struct pci_dev *dev; ++ ++ list_for_each_entry(dev, &slot->bus->devices, bus_list) { ++ if (!dev->slot || dev->slot != slot) ++ continue; ++ if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || ++ (dev->subordinate && !pci_bus_resetable(dev->subordinate))) ++ return false; ++ } ++ ++ return true; ++} ++ + /* Lock devices from the top of the tree down */ + static void pci_slot_lock(struct pci_slot *slot) + { +@@ -3623,7 +3655,7 @@ static int pci_slot_reset(struct pci_slot *slot, int probe) + { + int rc; + +- if (!slot) ++ if (!slot || !pci_slot_resetable(slot)) + return -ENOTTY; + + if (!probe) +@@ -3715,7 +3747,7 @@ EXPORT_SYMBOL_GPL(pci_try_reset_slot); + + static int pci_bus_reset(struct pci_bus *bus, int probe) + { +- if (!bus->self) ++ if (!bus->self || !pci_bus_resetable(bus)) + return -ENOTTY; + + if (probe) +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 6e8776b59a2c..27abeb40dfab 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -3008,6 +3008,20 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CHELSIO, 0x0030, + DECLARE_PCI_FIXUP_HEADER(0x1814, 0x0601, /* Ralink RT2800 802.11n PCI */ + quirk_broken_intx_masking); + ++static void quirk_no_bus_reset(struct pci_dev *dev) ++{ ++ dev->dev_flags |= PCI_DEV_FLAGS_NO_BUS_RESET; ++} ++ ++/* ++ * Atheros AR93xx chips do not behave after a bus reset. The device will ++ * throw a Link Down error on AER-capable systems and regardless of AER, ++ * config space of the device is never accessible again and typically ++ * causes the system to hang or reset when access is attempted. ++ * http://www.spinics.net/lists/linux-pci/msg34797.html ++ */ ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, quirk_no_bus_reset); ++ + static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, + struct pci_fixup *end) + { +diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c +index c0fe6091566a..988f5e18763a 100644 +--- a/drivers/pinctrl/core.c ++++ b/drivers/pinctrl/core.c +@@ -1812,14 +1812,15 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev) + if (pctldev == NULL) + return; + +- mutex_lock(&pinctrldev_list_mutex); + mutex_lock(&pctldev->mutex); +- + pinctrl_remove_device_debugfs(pctldev); ++ mutex_unlock(&pctldev->mutex); + + if (!IS_ERR(pctldev->p)) + pinctrl_put(pctldev->p); + ++ mutex_lock(&pinctrldev_list_mutex); ++ mutex_lock(&pctldev->mutex); + /* TODO: check that no pinmuxes are still active? */ + list_del(&pctldev->node); + /* Destroy descriptor tree */ +diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c +index ab3baa7f9508..86ade85481bd 100644 +--- a/drivers/s390/crypto/ap_bus.c ++++ b/drivers/s390/crypto/ap_bus.c +@@ -44,6 +44,7 @@ + #include + #include + #include ++#include + + #include "ap_bus.h" + +@@ -71,7 +72,7 @@ MODULE_AUTHOR("IBM Corporation"); + MODULE_DESCRIPTION("Adjunct Processor Bus driver, " \ + "Copyright IBM Corp. 2006, 2012"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("z90crypt"); ++MODULE_ALIAS_CRYPTO("z90crypt"); + + /* + * Module parameter +diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c +index 3f5b56a99892..b4ddb7310e36 100644 +--- a/drivers/scsi/ipr.c ++++ b/drivers/scsi/ipr.c +@@ -683,6 +683,7 @@ static void ipr_init_ipr_cmnd(struct ipr_cmnd *ipr_cmd, + ipr_reinit_ipr_cmnd(ipr_cmd); + ipr_cmd->u.scratch = 0; + ipr_cmd->sibling = NULL; ++ ipr_cmd->eh_comp = NULL; + ipr_cmd->fast_done = fast_done; + init_timer(&ipr_cmd->timer); + } +@@ -848,6 +849,8 @@ static void ipr_scsi_eh_done(struct ipr_cmnd *ipr_cmd) + + scsi_dma_unmap(ipr_cmd->scsi_cmd); + scsi_cmd->scsi_done(scsi_cmd); ++ if (ipr_cmd->eh_comp) ++ complete(ipr_cmd->eh_comp); + list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); + } + +@@ -4805,6 +4808,84 @@ static int ipr_slave_alloc(struct scsi_device *sdev) + return rc; + } + ++/** ++ * ipr_match_lun - Match function for specified LUN ++ * @ipr_cmd: ipr command struct ++ * @device: device to match (sdev) ++ * ++ * Returns: ++ * 1 if command matches sdev / 0 if command does not match sdev ++ **/ ++static int ipr_match_lun(struct ipr_cmnd *ipr_cmd, void *device) ++{ ++ if (ipr_cmd->scsi_cmd && ipr_cmd->scsi_cmd->device == device) ++ return 1; ++ return 0; ++} ++ ++/** ++ * ipr_wait_for_ops - Wait for matching commands to complete ++ * @ipr_cmd: ipr command struct ++ * @device: device to match (sdev) ++ * @match: match function to use ++ * ++ * Returns: ++ * SUCCESS / FAILED ++ **/ ++static int ipr_wait_for_ops(struct ipr_ioa_cfg *ioa_cfg, void *device, ++ int (*match)(struct ipr_cmnd *, void *)) ++{ ++ struct ipr_cmnd *ipr_cmd; ++ int wait; ++ unsigned long flags; ++ struct ipr_hrr_queue *hrrq; ++ signed long timeout = IPR_ABORT_TASK_TIMEOUT; ++ DECLARE_COMPLETION_ONSTACK(comp); ++ ++ ENTER; ++ do { ++ wait = 0; ++ ++ for_each_hrrq(hrrq, ioa_cfg) { ++ spin_lock_irqsave(hrrq->lock, flags); ++ list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) { ++ if (match(ipr_cmd, device)) { ++ ipr_cmd->eh_comp = ∁ ++ wait++; ++ } ++ } ++ spin_unlock_irqrestore(hrrq->lock, flags); ++ } ++ ++ if (wait) { ++ timeout = wait_for_completion_timeout(&comp, timeout); ++ ++ if (!timeout) { ++ wait = 0; ++ ++ for_each_hrrq(hrrq, ioa_cfg) { ++ spin_lock_irqsave(hrrq->lock, flags); ++ list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) { ++ if (match(ipr_cmd, device)) { ++ ipr_cmd->eh_comp = NULL; ++ wait++; ++ } ++ } ++ spin_unlock_irqrestore(hrrq->lock, flags); ++ } ++ ++ if (wait) ++ dev_err(&ioa_cfg->pdev->dev, "Timed out waiting for aborted commands\n"); ++ LEAVE; ++ return wait ? FAILED : SUCCESS; ++ } ++ } ++ } while (wait); ++ ++ LEAVE; ++ return SUCCESS; ++} ++ + static int ipr_eh_host_reset(struct scsi_cmnd *cmd) + { + struct ipr_ioa_cfg *ioa_cfg; +@@ -5023,11 +5104,17 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd *scsi_cmd) + static int ipr_eh_dev_reset(struct scsi_cmnd *cmd) + { + int rc; ++ struct ipr_ioa_cfg *ioa_cfg; ++ ++ ioa_cfg = (struct ipr_ioa_cfg *) cmd->device->host->hostdata; + + spin_lock_irq(cmd->device->host->host_lock); + rc = __ipr_eh_dev_reset(cmd); + spin_unlock_irq(cmd->device->host->host_lock); + ++ if (rc == SUCCESS) ++ rc = ipr_wait_for_ops(ioa_cfg, cmd->device, ipr_match_lun); ++ + return rc; + } + +@@ -5205,13 +5292,18 @@ static int ipr_eh_abort(struct scsi_cmnd *scsi_cmd) + { + unsigned long flags; + int rc; ++ struct ipr_ioa_cfg *ioa_cfg; + + ENTER; + ++ ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata; ++ + spin_lock_irqsave(scsi_cmd->device->host->host_lock, flags); + rc = ipr_cancel_op(scsi_cmd); + spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, flags); + ++ if (rc == SUCCESS) ++ rc = ipr_wait_for_ops(ioa_cfg, scsi_cmd->device, ipr_match_lun); + LEAVE; + return rc; + } +diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h +index 9ce38a22647e..0801f3df4b27 100644 +--- a/drivers/scsi/ipr.h ++++ b/drivers/scsi/ipr.h +@@ -1585,6 +1585,7 @@ struct ipr_cmnd { + struct scsi_device *sdev; + } u; + ++ struct completion *eh_comp; + struct ipr_hrr_queue *hrrq; + struct ipr_ioa_cfg *ioa_cfg; + }; +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index d46b4ccec8cd..850e232d086e 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -2417,12 +2417,17 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, + + poll_wait(file, &tty->read_wait, wait); + poll_wait(file, &tty->write_wait, wait); ++ if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) ++ mask |= POLLHUP; + if (input_available_p(tty, 1)) + mask |= POLLIN | POLLRDNORM; ++ else if (mask & POLLHUP) { ++ tty_flush_to_ldisc(tty); ++ if (input_available_p(tty, 1)) ++ mask |= POLLIN | POLLRDNORM; ++ } + if (tty->packet && tty->link->ctrl_status) + mask |= POLLPRI | POLLIN | POLLRDNORM; +- if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) +- mask |= POLLHUP; + if (tty_hung_up_p(file)) + mask |= POLLHUP; + if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) { +diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c +index 9df5d6ec7eec..f3a9d831d0f9 100644 +--- a/drivers/xen/swiotlb-xen.c ++++ b/drivers/xen/swiotlb-xen.c +@@ -449,7 +449,7 @@ static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr, + + /* NOTE: We use dev_addr here, not paddr! */ + if (is_xen_swiotlb_buffer(dev_addr)) { +- swiotlb_tbl_unmap_single(hwdev, dev_addr, size, dir); ++ swiotlb_tbl_unmap_single(hwdev, paddr, size, dir); + return; + } + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 1a858947006e..fa9f90049099 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -4507,7 +4507,8 @@ static void check_buffer_tree_ref(struct extent_buffer *eb) + spin_unlock(&eb->refs_lock); + } + +-static void mark_extent_buffer_accessed(struct extent_buffer *eb) ++static void mark_extent_buffer_accessed(struct extent_buffer *eb, ++ struct page *accessed) + { + unsigned long num_pages, i; + +@@ -4516,7 +4517,8 @@ static void mark_extent_buffer_accessed(struct extent_buffer *eb) + num_pages = num_extent_pages(eb->start, eb->len); + for (i = 0; i < num_pages; i++) { + struct page *p = extent_buffer_page(eb, i); +- mark_page_accessed(p); ++ if (p != accessed) ++ mark_page_accessed(p); + } + } + +@@ -4530,7 +4532,7 @@ struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info, + start >> PAGE_CACHE_SHIFT); + if (eb && atomic_inc_not_zero(&eb->refs)) { + rcu_read_unlock(); +- mark_extent_buffer_accessed(eb); ++ mark_extent_buffer_accessed(eb, NULL); + return eb; + } + rcu_read_unlock(); +@@ -4578,7 +4580,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, + spin_unlock(&mapping->private_lock); + unlock_page(p); + page_cache_release(p); +- mark_extent_buffer_accessed(exists); ++ mark_extent_buffer_accessed(exists, p); + goto free_eb; + } + +@@ -4593,7 +4595,6 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, + attach_extent_buffer_page(eb, p); + spin_unlock(&mapping->private_lock); + WARN_ON(PageDirty(p)); +- mark_page_accessed(p); + eb->pages[i] = p; + if (!PageUptodate(p)) + uptodate = 0; +diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c +index f6d00df99a8c..279b06ef5522 100644 +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -470,11 +470,12 @@ static void btrfs_drop_pages(struct page **pages, size_t num_pages) + for (i = 0; i < num_pages; i++) { + /* page checked is some magic around finding pages that + * have been modified without going through btrfs_set_page_dirty +- * clear it here ++ * clear it here. There should be no need to mark the pages ++ * accessed as prepare_pages should have marked them accessed ++ * in prepare_pages via find_or_create_page() + */ + ClearPageChecked(pages[i]); + unlock_page(pages[i]); +- mark_page_accessed(pages[i]); + page_cache_release(pages[i]); + } + } +diff --git a/fs/buffer.c b/fs/buffer.c +index 4d06a573d199..eef21c69f2d7 100644 +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -227,7 +227,7 @@ __find_get_block_slow(struct block_device *bdev, sector_t block) + int all_mapped = 1; + + index = block >> (PAGE_CACHE_SHIFT - bd_inode->i_blkbits); +- page = find_get_page(bd_mapping, index); ++ page = find_get_page_flags(bd_mapping, index, FGP_ACCESSED); + if (!page) + goto out; + +@@ -1368,12 +1368,13 @@ __find_get_block(struct block_device *bdev, sector_t block, unsigned size) + struct buffer_head *bh = lookup_bh_lru(bdev, block, size); + + if (bh == NULL) { ++ /* __find_get_block_slow will mark the page accessed */ + bh = __find_get_block_slow(bdev, block); + if (bh) + bh_lru_install(bh); +- } +- if (bh) ++ } else + touch_buffer(bh); ++ + return bh; + } + EXPORT_SYMBOL(__find_get_block); +@@ -1485,16 +1486,27 @@ EXPORT_SYMBOL(set_bh_page); + /* + * Called when truncating a buffer on a page completely. + */ ++ ++/* Bits that are cleared during an invalidate */ ++#define BUFFER_FLAGS_DISCARD \ ++ (1 << BH_Mapped | 1 << BH_New | 1 << BH_Req | \ ++ 1 << BH_Delay | 1 << BH_Unwritten) ++ + static void discard_buffer(struct buffer_head * bh) + { ++ unsigned long b_state, b_state_old; ++ + lock_buffer(bh); + clear_buffer_dirty(bh); + bh->b_bdev = NULL; +- clear_buffer_mapped(bh); +- clear_buffer_req(bh); +- clear_buffer_new(bh); +- clear_buffer_delay(bh); +- clear_buffer_unwritten(bh); ++ b_state = bh->b_state; ++ for (;;) { ++ b_state_old = cmpxchg(&bh->b_state, b_state, ++ (b_state & ~BUFFER_FLAGS_DISCARD)); ++ if (b_state_old == b_state) ++ break; ++ b_state = b_state_old; ++ } + unlock_buffer(bh); + } + +diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c +index 77492301cc2b..dfc95646b88c 100644 +--- a/fs/cifs/ioctl.c ++++ b/fs/cifs/ioctl.c +@@ -86,21 +86,16 @@ static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file, + } + + src_inode = src_file.file->f_dentry->d_inode; ++ rc = -EINVAL; ++ if (S_ISDIR(src_inode->i_mode)) ++ goto out_fput; + + /* + * Note: cifs case is easier than btrfs since server responsible for + * checks for proper open modes and file type and if it wants + * server could even support copy of range where source = target + */ +- +- /* so we do not deadlock racing two ioctls on same files */ +- if (target_inode < src_inode) { +- mutex_lock_nested(&target_inode->i_mutex, I_MUTEX_PARENT); +- mutex_lock_nested(&src_inode->i_mutex, I_MUTEX_CHILD); +- } else { +- mutex_lock_nested(&src_inode->i_mutex, I_MUTEX_PARENT); +- mutex_lock_nested(&target_inode->i_mutex, I_MUTEX_CHILD); +- } ++ lock_two_nondirectories(target_inode, src_inode); + + /* determine range to clone */ + rc = -EINVAL; +@@ -124,13 +119,7 @@ static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file, + out_unlock: + /* although unlocking in the reverse order from locking is not + strictly necessary here it is a little cleaner to be consistent */ +- if (target_inode < src_inode) { +- mutex_unlock(&src_inode->i_mutex); +- mutex_unlock(&target_inode->i_mutex); +- } else { +- mutex_unlock(&target_inode->i_mutex); +- mutex_unlock(&src_inode->i_mutex); +- } ++ unlock_two_nondirectories(src_inode, target_inode); + out_fput: + fdput(src_file); + out_drop_write: +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 242226a87be7..7620133f78bf 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -1044,6 +1044,8 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group) + * allocating. If we are looking at the buddy cache we would + * have taken a reference using ext4_mb_load_buddy and that + * would have pinned buddy page to page cache. ++ * The call to ext4_mb_get_buddy_page_lock will mark the ++ * page accessed. + */ + ret = ext4_mb_get_buddy_page_lock(sb, group, &e4b); + if (ret || !EXT4_MB_GRP_NEED_INIT(this_grp)) { +@@ -1062,7 +1064,6 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group) + ret = -EIO; + goto err; + } +- mark_page_accessed(page); + + if (e4b.bd_buddy_page == NULL) { + /* +@@ -1082,7 +1083,6 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group) + ret = -EIO; + goto err; + } +- mark_page_accessed(page); + err: + ext4_mb_put_buddy_page_lock(&e4b); + return ret; +@@ -1141,7 +1141,7 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group, + + /* we could use find_or_create_page(), but it locks page + * what we'd like to avoid in fast path ... */ +- page = find_get_page(inode->i_mapping, pnum); ++ page = find_get_page_flags(inode->i_mapping, pnum, FGP_ACCESSED); + if (page == NULL || !PageUptodate(page)) { + if (page) + /* +@@ -1172,15 +1172,16 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group, + ret = -EIO; + goto err; + } ++ ++ /* Pages marked accessed already */ + e4b->bd_bitmap_page = page; + e4b->bd_bitmap = page_address(page) + (poff * sb->s_blocksize); +- mark_page_accessed(page); + + block++; + pnum = block / blocks_per_page; + poff = block % blocks_per_page; + +- page = find_get_page(inode->i_mapping, pnum); ++ page = find_get_page_flags(inode->i_mapping, pnum, FGP_ACCESSED); + if (page == NULL || !PageUptodate(page)) { + if (page) + page_cache_release(page); +@@ -1201,9 +1202,10 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group, + ret = -EIO; + goto err; + } ++ ++ /* Pages marked accessed already */ + e4b->bd_buddy_page = page; + e4b->bd_buddy = page_address(page) + (poff * sb->s_blocksize); +- mark_page_accessed(page); + + BUG_ON(e4b->bd_bitmap_page == NULL); + BUG_ON(e4b->bd_buddy_page == NULL); +diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c +index 293d0486a40f..5c6fe278fb63 100644 +--- a/fs/f2fs/checkpoint.c ++++ b/fs/f2fs/checkpoint.c +@@ -71,7 +71,6 @@ repeat: + goto repeat; + } + out: +- mark_page_accessed(page); + return page; + } + +diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c +index b0649b76eb4f..bb6478acb369 100644 +--- a/fs/f2fs/node.c ++++ b/fs/f2fs/node.c +@@ -969,7 +969,6 @@ repeat: + } + got_it: + f2fs_bug_on(nid != nid_of_node(page)); +- mark_page_accessed(page); + return page; + } + +@@ -1024,7 +1023,6 @@ page_hit: + f2fs_put_page(page, 1); + return ERR_PTR(-EIO); + } +- mark_page_accessed(page); + return page; + } + +diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c +index 0a648bb455ae..6eb13c621a14 100644 +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -1614,7 +1614,7 @@ out_finish: + + static void fuse_retrieve_end(struct fuse_conn *fc, struct fuse_req *req) + { +- release_pages(req->pages, req->num_pages, 0); ++ release_pages(req->pages, req->num_pages, false); + } + + static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, +diff --git a/fs/fuse/file.c b/fs/fuse/file.c +index a91d3b4d32f3..d8a60270581c 100644 +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -1006,8 +1006,6 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, + tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes); + flush_dcache_page(page); + +- mark_page_accessed(page); +- + if (!tmp) { + unlock_page(page); + page_cache_release(page); +diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c +index 49436fa7cd4f..4ccb60d943bb 100644 +--- a/fs/gfs2/aops.c ++++ b/fs/gfs2/aops.c +@@ -517,7 +517,6 @@ int gfs2_internal_read(struct gfs2_inode *ip, char *buf, loff_t *pos, + p = kmap_atomic(page); + memcpy(buf + copied, p + offset, amt); + kunmap_atomic(p); +- mark_page_accessed(page); + page_cache_release(page); + copied += amt; + index++; +diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c +index b82a9c99e18b..e7b149614f5e 100644 +--- a/fs/gfs2/meta_io.c ++++ b/fs/gfs2/meta_io.c +@@ -136,7 +136,8 @@ struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create) + yield(); + } + } else { +- page = find_lock_page(mapping, index); ++ page = find_get_page_flags(mapping, index, ++ FGP_LOCK|FGP_ACCESSED); + if (!page) + return NULL; + } +@@ -153,7 +154,6 @@ struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create) + map_bh(bh, sdp->sd_vfs, blkno); + + unlock_page(page); +- mark_page_accessed(page); + page_cache_release(page); + + return bh; +diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c +index a27e3fecefaf..250ed5b20c8f 100644 +--- a/fs/ntfs/attrib.c ++++ b/fs/ntfs/attrib.c +@@ -1748,7 +1748,6 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size) + if (page) { + set_page_dirty(page); + unlock_page(page); +- mark_page_accessed(page); + page_cache_release(page); + } + ntfs_debug("Done."); +diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c +index db9bd8a31725..86ddab916b66 100644 +--- a/fs/ntfs/file.c ++++ b/fs/ntfs/file.c +@@ -2060,7 +2060,6 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb, + } + do { + unlock_page(pages[--do_pages]); +- mark_page_accessed(pages[do_pages]); + page_cache_release(pages[do_pages]); + } while (do_pages); + if (unlikely(status)) +diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h +index b19d3dc2e651..ade2390ffe92 100644 +--- a/include/linux/cpuset.h ++++ b/include/linux/cpuset.h +@@ -12,10 +12,31 @@ + #include + #include + #include ++#include + + #ifdef CONFIG_CPUSETS + +-extern int number_of_cpusets; /* How many cpusets are defined in system? */ ++extern struct static_key cpusets_enabled_key; ++static inline bool cpusets_enabled(void) ++{ ++ return static_key_false(&cpusets_enabled_key); ++} ++ ++static inline int nr_cpusets(void) ++{ ++ /* jump label reference count + the top-level cpuset */ ++ return static_key_count(&cpusets_enabled_key) + 1; ++} ++ ++static inline void cpuset_inc(void) ++{ ++ static_key_slow_inc(&cpusets_enabled_key); ++} ++ ++static inline void cpuset_dec(void) ++{ ++ static_key_slow_dec(&cpusets_enabled_key); ++} + + extern int cpuset_init(void); + extern void cpuset_init_smp(void); +@@ -32,13 +53,13 @@ extern int __cpuset_node_allowed_hardwall(int node, gfp_t gfp_mask); + + static inline int cpuset_node_allowed_softwall(int node, gfp_t gfp_mask) + { +- return number_of_cpusets <= 1 || ++ return nr_cpusets() <= 1 || + __cpuset_node_allowed_softwall(node, gfp_mask); + } + + static inline int cpuset_node_allowed_hardwall(int node, gfp_t gfp_mask) + { +- return number_of_cpusets <= 1 || ++ return nr_cpusets() <= 1 || + __cpuset_node_allowed_hardwall(node, gfp_mask); + } + +@@ -124,6 +145,8 @@ static inline void set_mems_allowed(nodemask_t nodemask) + + #else /* !CONFIG_CPUSETS */ + ++static inline bool cpusets_enabled(void) { return false; } ++ + static inline int cpuset_init(void) { return 0; } + static inline void cpuset_init_smp(void) {} + +diff --git a/include/linux/crypto.h b/include/linux/crypto.h +index b92eadf92d72..2b00d92a6e6f 100644 +--- a/include/linux/crypto.h ++++ b/include/linux/crypto.h +@@ -26,6 +26,19 @@ + #include + + /* ++ * Autoloaded crypto modules should only use a prefixed name to avoid allowing ++ * arbitrary modules to be loaded. Loading from userspace may still need the ++ * unprefixed names, so retains those aliases as well. ++ * This uses __MODULE_INFO directly instead of MODULE_ALIAS because pre-4.3 ++ * gcc (e.g. avr32 toolchain) uses __LINE__ for uniqueness, and this macro ++ * expands twice on the same line. Instead, use a separate base name for the ++ * alias. ++ */ ++#define MODULE_ALIAS_CRYPTO(name) \ ++ __MODULE_INFO(alias, alias_userspace, name); \ ++ __MODULE_INFO(alias, alias_crypto, "crypto-" name) ++ ++/* + * Algorithm masks and types. + */ + #define CRYPTO_ALG_TYPE_MASK 0x0000000f +diff --git a/include/linux/gfp.h b/include/linux/gfp.h +index 39b81dc7d01a..3824ac62f395 100644 +--- a/include/linux/gfp.h ++++ b/include/linux/gfp.h +@@ -369,8 +369,8 @@ void *alloc_pages_exact_nid(int nid, size_t size, gfp_t gfp_mask); + + extern void __free_pages(struct page *page, unsigned int order); + extern void free_pages(unsigned long addr, unsigned int order); +-extern void free_hot_cold_page(struct page *page, int cold); +-extern void free_hot_cold_page_list(struct list_head *list, int cold); ++extern void free_hot_cold_page(struct page *page, bool cold); ++extern void free_hot_cold_page_list(struct list_head *list, bool cold); + + extern void __free_memcg_kmem_pages(struct page *page, unsigned int order); + extern void free_memcg_kmem_pages(unsigned long addr, unsigned int order); +diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h +index b826239bdce0..63579cb8d3dc 100644 +--- a/include/linux/huge_mm.h ++++ b/include/linux/huge_mm.h +@@ -93,10 +93,6 @@ extern bool is_vma_temporary_stack(struct vm_area_struct *vma); + #endif /* CONFIG_DEBUG_VM */ + + extern unsigned long transparent_hugepage_flags; +-extern int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, +- pmd_t *dst_pmd, pmd_t *src_pmd, +- struct vm_area_struct *vma, +- unsigned long addr, unsigned long end); + extern int split_huge_page_to_list(struct page *page, struct list_head *list); + static inline int split_huge_page(struct page *page) + { +diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h +index 5c1dfb2a9e73..784304b222b3 100644 +--- a/include/linux/jump_label.h ++++ b/include/linux/jump_label.h +@@ -69,6 +69,10 @@ struct static_key { + + # include + # define HAVE_JUMP_LABEL ++#else ++struct static_key { ++ atomic_t enabled; ++}; + #endif /* CC_HAVE_ASM_GOTO && CONFIG_JUMP_LABEL */ + + enum jump_label_type { +@@ -79,6 +83,12 @@ enum jump_label_type { + struct module; + + #include ++ ++static inline int static_key_count(struct static_key *key) ++{ ++ return atomic_read(&key->enabled); ++} ++ + #ifdef HAVE_JUMP_LABEL + + #define JUMP_LABEL_TYPE_FALSE_BRANCH 0UL +@@ -134,10 +144,6 @@ extern void jump_label_apply_nops(struct module *mod); + + #else /* !HAVE_JUMP_LABEL */ + +-struct static_key { +- atomic_t enabled; +-}; +- + static __always_inline void jump_label_init(void) + { + static_key_initialized = true; +@@ -145,14 +151,14 @@ static __always_inline void jump_label_init(void) + + static __always_inline bool static_key_false(struct static_key *key) + { +- if (unlikely(atomic_read(&key->enabled) > 0)) ++ if (unlikely(static_key_count(key) > 0)) + return true; + return false; + } + + static __always_inline bool static_key_true(struct static_key *key) + { +- if (likely(atomic_read(&key->enabled) > 0)) ++ if (likely(static_key_count(key) > 0)) + return true; + return false; + } +@@ -194,7 +200,7 @@ static inline int jump_label_apply_nops(struct module *mod) + + static inline bool static_key_enabled(struct static_key *key) + { +- return (atomic_read(&key->enabled) > 0); ++ return static_key_count(key) > 0; + } + + #endif /* _LINUX_JUMP_LABEL_H */ +diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h +index 18843532a0c9..ac819bf9522c 100644 +--- a/include/linux/mmzone.h ++++ b/include/linux/mmzone.h +@@ -78,10 +78,15 @@ extern int page_group_by_mobility_disabled; + #define NR_MIGRATETYPE_BITS (PB_migrate_end - PB_migrate + 1) + #define MIGRATETYPE_MASK ((1UL << NR_MIGRATETYPE_BITS) - 1) + +-static inline int get_pageblock_migratetype(struct page *page) ++#define get_pageblock_migratetype(page) \ ++ get_pfnblock_flags_mask(page, page_to_pfn(page), \ ++ PB_migrate_end, MIGRATETYPE_MASK) ++ ++static inline int get_pfnblock_migratetype(struct page *page, unsigned long pfn) + { + BUILD_BUG_ON(PB_migrate_end - PB_migrate != 2); +- return get_pageblock_flags_mask(page, PB_migrate_end, MIGRATETYPE_MASK); ++ return get_pfnblock_flags_mask(page, pfn, PB_migrate_end, ++ MIGRATETYPE_MASK); + } + + struct free_area { +@@ -138,6 +143,7 @@ enum zone_stat_item { + NR_SHMEM, /* shmem pages (included tmpfs/GEM pages) */ + NR_DIRTIED, /* page dirtyings since bootup */ + NR_WRITTEN, /* page writings since bootup */ ++ NR_PAGES_SCANNED, /* pages scanned since last reclaim */ + #ifdef CONFIG_NUMA + NUMA_HIT, /* allocated in intended node */ + NUMA_MISS, /* allocated in non intended node */ +@@ -316,19 +322,12 @@ enum zone_type { + #ifndef __GENERATING_BOUNDS_H + + struct zone { +- /* Fields commonly accessed by the page allocator */ ++ /* Read-mostly fields */ + + /* zone watermarks, access with *_wmark_pages(zone) macros */ + unsigned long watermark[NR_WMARK]; + + /* +- * When free pages are below this point, additional steps are taken +- * when reading the number of free pages to avoid per-cpu counter +- * drift allowing watermarks to be breached +- */ +- unsigned long percpu_drift_mark; +- +- /* + * We don't know if the memory that we're going to allocate will be freeable + * or/and it will be released eventually, so to avoid totally wasting several + * GB of ram we must reserve some of the lower zone memory (otherwise we risk +@@ -336,41 +335,26 @@ struct zone { + * on the higher zones). This array is recalculated at runtime if the + * sysctl_lowmem_reserve_ratio sysctl changes. + */ +- unsigned long lowmem_reserve[MAX_NR_ZONES]; +- +- /* +- * This is a per-zone reserve of pages that should not be +- * considered dirtyable memory. +- */ +- unsigned long dirty_balance_reserve; ++ long lowmem_reserve[MAX_NR_ZONES]; + + #ifdef CONFIG_NUMA + int node; ++#endif ++ + /* +- * zone reclaim becomes active if more unmapped pages exist. ++ * The target ratio of ACTIVE_ANON to INACTIVE_ANON pages on ++ * this zone's LRU. Maintained by the pageout code. + */ +- unsigned long min_unmapped_pages; +- unsigned long min_slab_pages; +-#endif ++ unsigned int inactive_ratio; ++ ++ struct pglist_data *zone_pgdat; + struct per_cpu_pageset __percpu *pageset; ++ + /* +- * free areas of different sizes ++ * This is a per-zone reserve of pages that should not be ++ * considered dirtyable memory. + */ +- spinlock_t lock; +-#if defined CONFIG_COMPACTION || defined CONFIG_CMA +- /* Set to true when the PG_migrate_skip bits should be cleared */ +- bool compact_blockskip_flush; +- +- /* pfn where compaction free scanner should start */ +- unsigned long compact_cached_free_pfn; +- /* pfn where async and sync compaction migration scanner should start */ +- unsigned long compact_cached_migrate_pfn[2]; +-#endif +-#ifdef CONFIG_MEMORY_HOTPLUG +- /* see spanned/present_pages for more description */ +- seqlock_t span_seqlock; +-#endif +- struct free_area free_area[MAX_ORDER]; ++ unsigned long dirty_balance_reserve; + + #ifndef CONFIG_SPARSEMEM + /* +@@ -380,71 +364,14 @@ struct zone { + unsigned long *pageblock_flags; + #endif /* CONFIG_SPARSEMEM */ + +-#ifdef CONFIG_COMPACTION +- /* +- * On compaction failure, 1<> PAGE_SHIFT */ + unsigned long zone_start_pfn; + +@@ -490,9 +417,11 @@ struct zone { + * adjust_managed_page_count() should be used instead of directly + * touching zone->managed_pages and totalram_pages. + */ ++ unsigned long managed_pages; + unsigned long spanned_pages; + unsigned long present_pages; +- unsigned long managed_pages; ++ ++ const char *name; + + /* + * Number of MIGRATE_RESEVE page block. To maintain for just +@@ -500,10 +429,91 @@ struct zone { + */ + int nr_migrate_reserve_block; + ++#ifdef CONFIG_MEMORY_HOTPLUG ++ /* see spanned/present_pages for more description */ ++ seqlock_t span_seqlock; ++#endif ++ + /* +- * rarely used fields: ++ * wait_table -- the array holding the hash table ++ * wait_table_hash_nr_entries -- the size of the hash table array ++ * wait_table_bits -- wait_table_size == (1 << wait_table_bits) ++ * ++ * The purpose of all these is to keep track of the people ++ * waiting for a page to become available and make them ++ * runnable again when possible. The trouble is that this ++ * consumes a lot of space, especially when so few things ++ * wait on pages at a given time. So instead of using ++ * per-page waitqueues, we use a waitqueue hash table. ++ * ++ * The bucket discipline is to sleep on the same queue when ++ * colliding and wake all in that wait queue when removing. ++ * When something wakes, it must check to be sure its page is ++ * truly available, a la thundering herd. The cost of a ++ * collision is great, but given the expected load of the ++ * table, they should be so rare as to be outweighed by the ++ * benefits from the saved space. ++ * ++ * __wait_on_page_locked() and unlock_page() in mm/filemap.c, are the ++ * primary users of these fields, and in mm/page_alloc.c ++ * free_area_init_core() performs the initialization of them. + */ +- const char *name; ++ wait_queue_head_t *wait_table; ++ unsigned long wait_table_hash_nr_entries; ++ unsigned long wait_table_bits; ++ ++ ZONE_PADDING(_pad1_) ++ ++ /* Write-intensive fields used from the page allocator */ ++ spinlock_t lock; ++ ++ /* free areas of different sizes */ ++ struct free_area free_area[MAX_ORDER]; ++ ++ /* zone flags, see below */ ++ unsigned long flags; ++ ++ ZONE_PADDING(_pad2_) ++ ++ /* Write-intensive fields used by page reclaim */ ++ ++ /* Fields commonly accessed by the page reclaim scanner */ ++ spinlock_t lru_lock; ++ struct lruvec lruvec; ++ ++ /* ++ * When free pages are below this point, additional steps are taken ++ * when reading the number of free pages to avoid per-cpu counter ++ * drift allowing watermarks to be breached ++ */ ++ unsigned long percpu_drift_mark; ++ ++#if defined CONFIG_COMPACTION || defined CONFIG_CMA ++ /* pfn where compaction free scanner should start */ ++ unsigned long compact_cached_free_pfn; ++ /* pfn where async and sync compaction migration scanner should start */ ++ unsigned long compact_cached_migrate_pfn[2]; ++#endif ++ ++#ifdef CONFIG_COMPACTION ++ /* ++ * On compaction failure, 1<flags); + } + ++static inline int zone_is_fair_depleted(const struct zone *zone) ++{ ++ return test_bit(ZONE_FAIR_DEPLETED, &zone->flags); ++} ++ + static inline int zone_is_oom_locked(const struct zone *zone) + { + return test_bit(ZONE_OOM_LOCKED, &zone->flags); +@@ -807,10 +823,10 @@ static inline bool pgdat_is_empty(pg_data_t *pgdat) + extern struct mutex zonelists_mutex; + void build_all_zonelists(pg_data_t *pgdat, struct zone *zone); + void wakeup_kswapd(struct zone *zone, int order, enum zone_type classzone_idx); +-bool zone_watermark_ok(struct zone *z, int order, unsigned long mark, +- int classzone_idx, int alloc_flags); +-bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark, +- int classzone_idx, int alloc_flags); ++bool zone_watermark_ok(struct zone *z, unsigned int order, ++ unsigned long mark, int classzone_idx, int alloc_flags); ++bool zone_watermark_ok_safe(struct zone *z, unsigned int order, ++ unsigned long mark, int classzone_idx, int alloc_flags); + enum memmap_context { + MEMMAP_EARLY, + MEMMAP_HOTPLUG, +diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h +index ca71a1d347a0..3c545b48aeab 100644 +--- a/include/linux/page-flags.h ++++ b/include/linux/page-flags.h +@@ -198,6 +198,7 @@ struct page; /* forward declaration */ + TESTPAGEFLAG(Locked, locked) + PAGEFLAG(Error, error) TESTCLEARFLAG(Error, error) + PAGEFLAG(Referenced, referenced) TESTCLEARFLAG(Referenced, referenced) ++ __SETPAGEFLAG(Referenced, referenced) + PAGEFLAG(Dirty, dirty) TESTSCFLAG(Dirty, dirty) __CLEARPAGEFLAG(Dirty, dirty) + PAGEFLAG(LRU, lru) __CLEARPAGEFLAG(LRU, lru) + PAGEFLAG(Active, active) __CLEARPAGEFLAG(Active, active) +@@ -208,6 +209,7 @@ PAGEFLAG(Pinned, pinned) TESTSCFLAG(Pinned, pinned) /* Xen */ + PAGEFLAG(SavePinned, savepinned); /* Xen */ + PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved) + PAGEFLAG(SwapBacked, swapbacked) __CLEARPAGEFLAG(SwapBacked, swapbacked) ++ __SETPAGEFLAG(SwapBacked, swapbacked) + + __PAGEFLAG(SlobFree, slob_free) + +diff --git a/include/linux/pageblock-flags.h b/include/linux/pageblock-flags.h +index c08730c10c7a..2baeee12f48e 100644 +--- a/include/linux/pageblock-flags.h ++++ b/include/linux/pageblock-flags.h +@@ -65,33 +65,26 @@ extern int pageblock_order; + /* Forward declaration */ + struct page; + +-unsigned long get_pageblock_flags_mask(struct page *page, ++unsigned long get_pfnblock_flags_mask(struct page *page, ++ unsigned long pfn, + unsigned long end_bitidx, + unsigned long mask); +-void set_pageblock_flags_mask(struct page *page, ++ ++void set_pfnblock_flags_mask(struct page *page, + unsigned long flags, ++ unsigned long pfn, + unsigned long end_bitidx, + unsigned long mask); + + /* Declarations for getting and setting flags. See mm/page_alloc.c */ +-static inline unsigned long get_pageblock_flags_group(struct page *page, +- int start_bitidx, int end_bitidx) +-{ +- unsigned long nr_flag_bits = end_bitidx - start_bitidx + 1; +- unsigned long mask = (1 << nr_flag_bits) - 1; +- +- return get_pageblock_flags_mask(page, end_bitidx, mask); +-} +- +-static inline void set_pageblock_flags_group(struct page *page, +- unsigned long flags, +- int start_bitidx, int end_bitidx) +-{ +- unsigned long nr_flag_bits = end_bitidx - start_bitidx + 1; +- unsigned long mask = (1 << nr_flag_bits) - 1; +- +- set_pageblock_flags_mask(page, flags, end_bitidx, mask); +-} ++#define get_pageblock_flags_group(page, start_bitidx, end_bitidx) \ ++ get_pfnblock_flags_mask(page, page_to_pfn(page), \ ++ end_bitidx, \ ++ (1 << (end_bitidx - start_bitidx + 1)) - 1) ++#define set_pageblock_flags_group(page, flags, start_bitidx, end_bitidx) \ ++ set_pfnblock_flags_mask(page, flags, page_to_pfn(page), \ ++ end_bitidx, \ ++ (1 << (end_bitidx - start_bitidx + 1)) - 1) + + #ifdef CONFIG_COMPACTION + #define get_pageblock_skip(page) \ +diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h +index 09c1b03867d9..fcebdda3651c 100644 +--- a/include/linux/pagemap.h ++++ b/include/linux/pagemap.h +@@ -99,7 +99,7 @@ static inline void mapping_set_gfp_mask(struct address_space *m, gfp_t mask) + + #define page_cache_get(page) get_page(page) + #define page_cache_release(page) put_page(page) +-void release_pages(struct page **pages, int nr, int cold); ++void release_pages(struct page **pages, int nr, bool cold); + + /* + * speculatively take a reference to a page. +@@ -248,12 +248,108 @@ pgoff_t page_cache_next_hole(struct address_space *mapping, + pgoff_t page_cache_prev_hole(struct address_space *mapping, + pgoff_t index, unsigned long max_scan); + ++#define FGP_ACCESSED 0x00000001 ++#define FGP_LOCK 0x00000002 ++#define FGP_CREAT 0x00000004 ++#define FGP_WRITE 0x00000008 ++#define FGP_NOFS 0x00000010 ++#define FGP_NOWAIT 0x00000020 ++ ++struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset, ++ int fgp_flags, gfp_t cache_gfp_mask); ++ ++/** ++ * find_get_page - find and get a page reference ++ * @mapping: the address_space to search ++ * @offset: the page index ++ * ++ * Looks up the page cache slot at @mapping & @offset. If there is a ++ * page cache page, it is returned with an increased refcount. ++ * ++ * Otherwise, %NULL is returned. ++ */ ++static inline struct page *find_get_page(struct address_space *mapping, ++ pgoff_t offset) ++{ ++ return pagecache_get_page(mapping, offset, 0, 0); ++} ++ ++static inline struct page *find_get_page_flags(struct address_space *mapping, ++ pgoff_t offset, int fgp_flags) ++{ ++ return pagecache_get_page(mapping, offset, fgp_flags, 0); ++} ++ ++/** ++ * find_lock_page - locate, pin and lock a pagecache page ++ * pagecache_get_page - find and get a page reference ++ * @mapping: the address_space to search ++ * @offset: the page index ++ * ++ * Looks up the page cache slot at @mapping & @offset. If there is a ++ * page cache page, it is returned locked and with an increased ++ * refcount. ++ * ++ * Otherwise, %NULL is returned. ++ * ++ * find_lock_page() may sleep. ++ */ ++static inline struct page *find_lock_page(struct address_space *mapping, ++ pgoff_t offset) ++{ ++ return pagecache_get_page(mapping, offset, FGP_LOCK, 0); ++} ++ ++/** ++ * find_or_create_page - locate or add a pagecache page ++ * @mapping: the page's address_space ++ * @index: the page's index into the mapping ++ * @gfp_mask: page allocation mode ++ * ++ * Looks up the page cache slot at @mapping & @offset. If there is a ++ * page cache page, it is returned locked and with an increased ++ * refcount. ++ * ++ * If the page is not present, a new page is allocated using @gfp_mask ++ * and added to the page cache and the VM's LRU list. The page is ++ * returned locked and with an increased refcount. ++ * ++ * On memory exhaustion, %NULL is returned. ++ * ++ * find_or_create_page() may sleep, even if @gfp_flags specifies an ++ * atomic allocation! ++ */ ++static inline struct page *find_or_create_page(struct address_space *mapping, ++ pgoff_t offset, gfp_t gfp_mask) ++{ ++ return pagecache_get_page(mapping, offset, ++ FGP_LOCK|FGP_ACCESSED|FGP_CREAT, ++ gfp_mask); ++} ++ ++/** ++ * grab_cache_page_nowait - returns locked page at given index in given cache ++ * @mapping: target address_space ++ * @index: the page index ++ * ++ * Same as grab_cache_page(), but do not wait if the page is unavailable. ++ * This is intended for speculative data generators, where the data can ++ * be regenerated if the page couldn't be grabbed. This routine should ++ * be safe to call while holding the lock for another page. ++ * ++ * Clear __GFP_FS when allocating the page to avoid recursion into the fs ++ * and deadlock against the caller's locked page. ++ */ ++static inline struct page *grab_cache_page_nowait(struct address_space *mapping, ++ pgoff_t index) ++{ ++ return pagecache_get_page(mapping, index, ++ FGP_LOCK|FGP_CREAT|FGP_NOFS|FGP_NOWAIT, ++ mapping_gfp_mask(mapping)); ++} ++ + struct page *find_get_entry(struct address_space *mapping, pgoff_t offset); +-struct page *find_get_page(struct address_space *mapping, pgoff_t offset); + struct page *find_lock_entry(struct address_space *mapping, pgoff_t offset); +-struct page *find_lock_page(struct address_space *mapping, pgoff_t offset); +-struct page *find_or_create_page(struct address_space *mapping, pgoff_t index, +- gfp_t gfp_mask); + unsigned find_get_entries(struct address_space *mapping, pgoff_t start, + unsigned int nr_entries, struct page **entries, + pgoff_t *indices); +@@ -276,8 +372,6 @@ static inline struct page *grab_cache_page(struct address_space *mapping, + return find_or_create_page(mapping, index, mapping_gfp_mask(mapping)); + } + +-extern struct page * grab_cache_page_nowait(struct address_space *mapping, +- pgoff_t index); + extern struct page * read_cache_page(struct address_space *mapping, + pgoff_t index, filler_t *filler, void *data); + extern struct page * read_cache_page_gfp(struct address_space *mapping, +diff --git a/include/linux/pci.h b/include/linux/pci.h +index 0e5e16c6f7f1..d662546f77d8 100644 +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -170,6 +170,8 @@ enum pci_dev_flags { + PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2, + /* Provide indication device is assigned by a Virtual Machine Manager */ + PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4, ++ /* Do not use bus resets for device */ ++ PCI_DEV_FLAGS_NO_BUS_RESET = (__force pci_dev_flags_t) (1 << 6), + }; + + enum pci_irq_reroute_variant { +diff --git a/include/linux/swap.h b/include/linux/swap.h +index 789324976801..241bf0922770 100644 +--- a/include/linux/swap.h ++++ b/include/linux/swap.h +@@ -268,12 +268,14 @@ extern unsigned long nr_free_pagecache_pages(void); + + + /* linux/mm/swap.c */ +-extern void __lru_cache_add(struct page *); + extern void lru_cache_add(struct page *); ++extern void lru_cache_add_anon(struct page *page); ++extern void lru_cache_add_file(struct page *page); + extern void lru_add_page_tail(struct page *page, struct page *page_tail, + struct lruvec *lruvec, struct list_head *head); + extern void activate_page(struct page *); + extern void mark_page_accessed(struct page *); ++extern void init_page_accessed(struct page *page); + extern void lru_add_drain(void); + extern void lru_add_drain_cpu(int cpu); + extern void lru_add_drain_all(void); +@@ -283,22 +285,6 @@ extern void swap_setup(void); + + extern void add_page_to_unevictable_list(struct page *page); + +-/** +- * lru_cache_add: add a page to the page lists +- * @page: the page to add +- */ +-static inline void lru_cache_add_anon(struct page *page) +-{ +- ClearPageActive(page); +- __lru_cache_add(page); +-} +- +-static inline void lru_cache_add_file(struct page *page) +-{ +- ClearPageActive(page); +- __lru_cache_add(page); +-} +- + /* linux/mm/vmscan.c */ + extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order, + gfp_t gfp_mask, nodemask_t *mask); +@@ -456,7 +442,7 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) + #define free_page_and_swap_cache(page) \ + page_cache_release(page) + #define free_pages_and_swap_cache(pages, nr) \ +- release_pages((pages), (nr), 0); ++ release_pages((pages), (nr), false); + + static inline void show_swap_cache_info(void) + { +diff --git a/include/linux/time.h b/include/linux/time.h +index d5d229b2e5af..7d532a32ff3a 100644 +--- a/include/linux/time.h ++++ b/include/linux/time.h +@@ -173,6 +173,19 @@ extern void getboottime(struct timespec *ts); + extern void monotonic_to_bootbased(struct timespec *ts); + extern void get_monotonic_boottime(struct timespec *ts); + ++static inline bool timeval_valid(const struct timeval *tv) ++{ ++ /* Dates before 1970 are bogus */ ++ if (tv->tv_sec < 0) ++ return false; ++ ++ /* Can't have more microseconds then a second */ ++ if (tv->tv_usec < 0 || tv->tv_usec >= USEC_PER_SEC) ++ return false; ++ ++ return true; ++} ++ + extern struct timespec timespec_trunc(struct timespec t, unsigned gran); + extern int timekeeping_valid_for_hres(void); + extern u64 timekeeping_max_deferment(void); +diff --git a/include/trace/events/pagemap.h b/include/trace/events/pagemap.h +index 1c9fabde69e4..ce0803b8d05f 100644 +--- a/include/trace/events/pagemap.h ++++ b/include/trace/events/pagemap.h +@@ -28,12 +28,10 @@ TRACE_EVENT(mm_lru_insertion, + + TP_PROTO( + struct page *page, +- unsigned long pfn, +- int lru, +- unsigned long flags ++ int lru + ), + +- TP_ARGS(page, pfn, lru, flags), ++ TP_ARGS(page, lru), + + TP_STRUCT__entry( + __field(struct page *, page ) +@@ -44,9 +42,9 @@ TRACE_EVENT(mm_lru_insertion, + + TP_fast_assign( + __entry->page = page; +- __entry->pfn = pfn; ++ __entry->pfn = page_to_pfn(page); + __entry->lru = lru; +- __entry->flags = flags; ++ __entry->flags = trace_pagemap_flags(page); + ), + + /* Flag format is based on page-types.c formatting for pagemap */ +@@ -64,9 +62,9 @@ TRACE_EVENT(mm_lru_insertion, + + TRACE_EVENT(mm_lru_activate, + +- TP_PROTO(struct page *page, unsigned long pfn), ++ TP_PROTO(struct page *page), + +- TP_ARGS(page, pfn), ++ TP_ARGS(page), + + TP_STRUCT__entry( + __field(struct page *, page ) +@@ -75,7 +73,7 @@ TRACE_EVENT(mm_lru_activate, + + TP_fast_assign( + __entry->page = page; +- __entry->pfn = pfn; ++ __entry->pfn = page_to_pfn(page); + ), + + /* Flag format is based on page-types.c formatting for pagemap */ +diff --git a/kernel/cpuset.c b/kernel/cpuset.c +index 15b3ea693225..2fb2877e6961 100644 +--- a/kernel/cpuset.c ++++ b/kernel/cpuset.c +@@ -61,12 +61,7 @@ + #include + #include + +-/* +- * Tracks how many cpusets are currently defined in system. +- * When there is only one cpuset (the root cpuset) we can +- * short circuit some hooks. +- */ +-int number_of_cpusets __read_mostly; ++struct static_key cpusets_enabled_key __read_mostly = STATIC_KEY_INIT_FALSE; + + /* See "Frequency meter" comments, below. */ + +@@ -611,7 +606,7 @@ static int generate_sched_domains(cpumask_var_t **domains, + goto done; + } + +- csa = kmalloc(number_of_cpusets * sizeof(cp), GFP_KERNEL); ++ csa = kmalloc(nr_cpusets() * sizeof(cp), GFP_KERNEL); + if (!csa) + goto done; + csn = 0; +@@ -1961,7 +1956,7 @@ static int cpuset_css_online(struct cgroup_subsys_state *css) + if (is_spread_slab(parent)) + set_bit(CS_SPREAD_SLAB, &cs->flags); + +- number_of_cpusets++; ++ cpuset_inc(); + + if (!test_bit(CGRP_CPUSET_CLONE_CHILDREN, &css->cgroup->flags)) + goto out_unlock; +@@ -2012,7 +2007,7 @@ static void cpuset_css_offline(struct cgroup_subsys_state *css) + if (is_sched_load_balance(cs)) + update_flag(CS_SCHED_LOAD_BALANCE, cs, 0); + +- number_of_cpusets--; ++ cpuset_dec(); + clear_bit(CS_ONLINE, &cs->flags); + + mutex_unlock(&cpuset_mutex); +@@ -2067,7 +2062,6 @@ int __init cpuset_init(void) + if (!alloc_cpumask_var(&cpus_attach, GFP_KERNEL)) + BUG(); + +- number_of_cpusets = 1; + return 0; + } + +diff --git a/kernel/time.c b/kernel/time.c +index 3c49ab45f822..3eb322e518a3 100644 +--- a/kernel/time.c ++++ b/kernel/time.c +@@ -195,6 +195,10 @@ SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv, + if (tv) { + if (copy_from_user(&user_tv, tv, sizeof(*tv))) + return -EFAULT; ++ ++ if (!timeval_valid(&user_tv)) ++ return -EINVAL; ++ + new_ts.tv_sec = user_tv.tv_sec; + new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC; + } +diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c +index af8d1d4f3d55..28db9bedc857 100644 +--- a/kernel/time/ntp.c ++++ b/kernel/time/ntp.c +@@ -631,6 +631,13 @@ int ntp_validate_timex(struct timex *txc) + if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME))) + return -EPERM; + ++ if (txc->modes & ADJ_FREQUENCY) { ++ if (LONG_MIN / PPM_SCALE > txc->freq) ++ return -EINVAL; ++ if (LONG_MAX / PPM_SCALE < txc->freq) ++ return -EINVAL; ++ } ++ + return 0; + } + +diff --git a/mm/filemap.c b/mm/filemap.c +index bdaa21555abe..217cfd3b3264 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -644,8 +644,17 @@ EXPORT_SYMBOL(unlock_page); + */ + void end_page_writeback(struct page *page) + { +- if (TestClearPageReclaim(page)) ++ /* ++ * TestClearPageReclaim could be used here but it is an atomic ++ * operation and overkill in this particular case. Failing to ++ * shuffle a page marked for immediate reclaim is too mild to ++ * justify taking an atomic operation penalty at the end of ++ * ever page writeback. ++ */ ++ if (PageReclaim(page)) { ++ ClearPageReclaim(page); + rotate_reclaimable_page(page); ++ } + + if (!test_clear_page_writeback(page)) + BUG(); +@@ -848,26 +857,6 @@ out: + EXPORT_SYMBOL(find_get_entry); + + /** +- * find_get_page - find and get a page reference +- * @mapping: the address_space to search +- * @offset: the page index +- * +- * Looks up the page cache slot at @mapping & @offset. If there is a +- * page cache page, it is returned with an increased refcount. +- * +- * Otherwise, %NULL is returned. +- */ +-struct page *find_get_page(struct address_space *mapping, pgoff_t offset) +-{ +- struct page *page = find_get_entry(mapping, offset); +- +- if (radix_tree_exceptional_entry(page)) +- page = NULL; +- return page; +-} +-EXPORT_SYMBOL(find_get_page); +- +-/** + * find_lock_entry - locate, pin and lock a page cache entry + * @mapping: the address_space to search + * @offset: the page cache index +@@ -904,66 +893,83 @@ repeat: + EXPORT_SYMBOL(find_lock_entry); + + /** +- * find_lock_page - locate, pin and lock a pagecache page ++ * pagecache_get_page - find and get a page reference + * @mapping: the address_space to search + * @offset: the page index ++ * @fgp_flags: PCG flags ++ * @gfp_mask: gfp mask to use for the page cache data page allocation + * +- * Looks up the page cache slot at @mapping & @offset. If there is a +- * page cache page, it is returned locked and with an increased +- * refcount. +- * +- * Otherwise, %NULL is returned. ++ * Looks up the page cache slot at @mapping & @offset. + * +- * find_lock_page() may sleep. +- */ +-struct page *find_lock_page(struct address_space *mapping, pgoff_t offset) +-{ +- struct page *page = find_lock_entry(mapping, offset); +- +- if (radix_tree_exceptional_entry(page)) +- page = NULL; +- return page; +-} +-EXPORT_SYMBOL(find_lock_page); +- +-/** +- * find_or_create_page - locate or add a pagecache page +- * @mapping: the page's address_space +- * @index: the page's index into the mapping +- * @gfp_mask: page allocation mode ++ * PCG flags modify how the page is returned + * +- * Looks up the page cache slot at @mapping & @offset. If there is a +- * page cache page, it is returned locked and with an increased +- * refcount. +- * +- * If the page is not present, a new page is allocated using @gfp_mask +- * and added to the page cache and the VM's LRU list. The page is +- * returned locked and with an increased refcount. ++ * FGP_ACCESSED: the page will be marked accessed ++ * FGP_LOCK: Page is return locked ++ * FGP_CREAT: If page is not present then a new page is allocated using ++ * @gfp_mask and added to the page cache and the VM's LRU ++ * list. The page is returned locked and with an increased ++ * refcount. Otherwise, %NULL is returned. + * +- * On memory exhaustion, %NULL is returned. ++ * If FGP_LOCK or FGP_CREAT are specified then the function may sleep even ++ * if the GFP flags specified for FGP_CREAT are atomic. + * +- * find_or_create_page() may sleep, even if @gfp_flags specifies an +- * atomic allocation! ++ * If there is a page cache page, it is returned with an increased refcount. + */ +-struct page *find_or_create_page(struct address_space *mapping, +- pgoff_t index, gfp_t gfp_mask) ++struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset, ++ int fgp_flags, gfp_t gfp_mask) + { + struct page *page; +- int err; ++ + repeat: +- page = find_lock_page(mapping, index); +- if (!page) { ++ page = find_get_entry(mapping, offset); ++ if (radix_tree_exceptional_entry(page)) ++ page = NULL; ++ if (!page) ++ goto no_page; ++ ++ if (fgp_flags & FGP_LOCK) { ++ if (fgp_flags & FGP_NOWAIT) { ++ if (!trylock_page(page)) { ++ page_cache_release(page); ++ return NULL; ++ } ++ } else { ++ lock_page(page); ++ } ++ ++ /* Has the page been truncated? */ ++ if (unlikely(page->mapping != mapping)) { ++ unlock_page(page); ++ page_cache_release(page); ++ goto repeat; ++ } ++ VM_BUG_ON(page->index != offset); ++ } ++ ++ if (page && (fgp_flags & FGP_ACCESSED)) ++ mark_page_accessed(page); ++ ++no_page: ++ if (!page && (fgp_flags & FGP_CREAT)) { ++ int err; ++ if ((fgp_flags & FGP_WRITE) && mapping_cap_account_dirty(mapping)) ++ gfp_mask |= __GFP_WRITE; ++ if (fgp_flags & FGP_NOFS) ++ gfp_mask &= ~__GFP_FS; ++ + page = __page_cache_alloc(gfp_mask); + if (!page) + return NULL; +- /* +- * We want a regular kernel memory (not highmem or DMA etc) +- * allocation for the radix tree nodes, but we need to honour +- * the context-specific requirements the caller has asked for. +- * GFP_RECLAIM_MASK collects those requirements. +- */ +- err = add_to_page_cache_lru(page, mapping, index, +- (gfp_mask & GFP_RECLAIM_MASK)); ++ ++ if (WARN_ON_ONCE(!(fgp_flags & FGP_LOCK))) ++ fgp_flags |= FGP_LOCK; ++ ++ /* Init accessed so avoit atomic mark_page_accessed later */ ++ if (fgp_flags & FGP_ACCESSED) ++ init_page_accessed(page); ++ ++ err = add_to_page_cache_lru(page, mapping, offset, ++ gfp_mask & GFP_RECLAIM_MASK); + if (unlikely(err)) { + page_cache_release(page); + page = NULL; +@@ -971,9 +977,10 @@ repeat: + goto repeat; + } + } ++ + return page; + } +-EXPORT_SYMBOL(find_or_create_page); ++EXPORT_SYMBOL(pagecache_get_page); + + /** + * find_get_entries - gang pagecache lookup +@@ -1263,39 +1270,6 @@ repeat: + } + EXPORT_SYMBOL(find_get_pages_tag); + +-/** +- * grab_cache_page_nowait - returns locked page at given index in given cache +- * @mapping: target address_space +- * @index: the page index +- * +- * Same as grab_cache_page(), but do not wait if the page is unavailable. +- * This is intended for speculative data generators, where the data can +- * be regenerated if the page couldn't be grabbed. This routine should +- * be safe to call while holding the lock for another page. +- * +- * Clear __GFP_FS when allocating the page to avoid recursion into the fs +- * and deadlock against the caller's locked page. +- */ +-struct page * +-grab_cache_page_nowait(struct address_space *mapping, pgoff_t index) +-{ +- struct page *page = find_get_page(mapping, index); +- +- if (page) { +- if (trylock_page(page)) +- return page; +- page_cache_release(page); +- return NULL; +- } +- page = __page_cache_alloc(mapping_gfp_mask(mapping) & ~__GFP_FS); +- if (page && add_to_page_cache_lru(page, mapping, index, GFP_NOFS)) { +- page_cache_release(page); +- page = NULL; +- } +- return page; +-} +-EXPORT_SYMBOL(grab_cache_page_nowait); +- + /* + * CD/DVDs are error prone. When a medium error occurs, the driver may fail + * a _large_ part of the i/o request. Imagine the worst scenario: +@@ -2397,7 +2371,6 @@ int pagecache_write_end(struct file *file, struct address_space *mapping, + { + const struct address_space_operations *aops = mapping->a_ops; + +- mark_page_accessed(page); + return aops->write_end(file, mapping, pos, len, copied, page, fsdata); + } + EXPORT_SYMBOL(pagecache_write_end); +@@ -2479,34 +2452,17 @@ EXPORT_SYMBOL(generic_file_direct_write); + struct page *grab_cache_page_write_begin(struct address_space *mapping, + pgoff_t index, unsigned flags) + { +- int status; +- gfp_t gfp_mask; + struct page *page; +- gfp_t gfp_notmask = 0; ++ int fgp_flags = FGP_LOCK|FGP_ACCESSED|FGP_WRITE|FGP_CREAT; + +- gfp_mask = mapping_gfp_mask(mapping); +- if (mapping_cap_account_dirty(mapping)) +- gfp_mask |= __GFP_WRITE; + if (flags & AOP_FLAG_NOFS) +- gfp_notmask = __GFP_FS; +-repeat: +- page = find_lock_page(mapping, index); ++ fgp_flags |= FGP_NOFS; ++ ++ page = pagecache_get_page(mapping, index, fgp_flags, ++ mapping_gfp_mask(mapping)); + if (page) +- goto found; ++ wait_for_stable_page(page); + +- page = __page_cache_alloc(gfp_mask & ~gfp_notmask); +- if (!page) +- return NULL; +- status = add_to_page_cache_lru(page, mapping, index, +- GFP_KERNEL & ~gfp_notmask); +- if (unlikely(status)) { +- page_cache_release(page); +- if (status == -EEXIST) +- goto repeat; +- return NULL; +- } +-found: +- wait_for_stable_page(page); + return page; + } + EXPORT_SYMBOL(grab_cache_page_write_begin); +@@ -2555,7 +2511,7 @@ again: + + status = a_ops->write_begin(file, mapping, pos, bytes, flags, + &page, &fsdata); +- if (unlikely(status)) ++ if (unlikely(status < 0)) + break; + + if (mapping_writably_mapped(mapping)) +@@ -2564,7 +2520,6 @@ again: + copied = iov_iter_copy_from_user_atomic(page, i, offset, bytes); + flush_dcache_page(page); + +- mark_page_accessed(page); + status = a_ops->write_end(file, mapping, pos, bytes, copied, + page, fsdata); + if (unlikely(status < 0)) +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index 331faa5c0d5e..adce656d2e9c 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -2273,6 +2273,30 @@ static void khugepaged_alloc_sleep(void) + + static int khugepaged_node_load[MAX_NUMNODES]; + ++static bool khugepaged_scan_abort(int nid) ++{ ++ int i; ++ ++ /* ++ * If zone_reclaim_mode is disabled, then no extra effort is made to ++ * allocate memory locally. ++ */ ++ if (!zone_reclaim_mode) ++ return false; ++ ++ /* If there is a count for this node already, it must be acceptable */ ++ if (khugepaged_node_load[nid]) ++ return false; ++ ++ for (i = 0; i < MAX_NUMNODES; i++) { ++ if (!khugepaged_node_load[i]) ++ continue; ++ if (node_distance(nid, i) > RECLAIM_DISTANCE) ++ return true; ++ } ++ return false; ++} ++ + #ifdef CONFIG_NUMA + static int khugepaged_find_target_node(void) + { +@@ -2589,6 +2613,8 @@ static int khugepaged_scan_pmd(struct mm_struct *mm, + * hit record. + */ + node = page_to_nid(page); ++ if (khugepaged_scan_abort(node)) ++ goto out_unmap; + khugepaged_node_load[node]++; + VM_BUG_ON_PAGE(PageCompound(page), page); + if (!PageLRU(page) || PageLocked(page) || !PageAnon(page)) +diff --git a/mm/memory.c b/mm/memory.c +index 924429e5ef4d..7f30beaba74f 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -878,7 +878,7 @@ out_set_pte: + return 0; + } + +-int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, ++static int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, + pmd_t *dst_pmd, pmd_t *src_pmd, struct vm_area_struct *vma, + unsigned long addr, unsigned long end) + { +@@ -3646,7 +3646,7 @@ static int handle_pte_fault(struct mm_struct *mm, + pte_t entry; + spinlock_t *ptl; + +- entry = *pte; ++ entry = ACCESS_ONCE(*pte); + if (!pte_present(entry)) { + if (pte_none(entry)) { + if (vma->vm_ops) { +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 4b258297cc7c..ea419137f845 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -408,7 +408,8 @@ static int destroy_compound_page(struct page *page, unsigned long order) + return bad; + } + +-static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags) ++static inline void prep_zero_page(struct page *page, unsigned int order, ++ gfp_t gfp_flags) + { + int i; + +@@ -452,7 +453,7 @@ static inline void set_page_guard_flag(struct page *page) { } + static inline void clear_page_guard_flag(struct page *page) { } + #endif + +-static inline void set_page_order(struct page *page, int order) ++static inline void set_page_order(struct page *page, unsigned int order) + { + set_page_private(page, order); + __SetPageBuddy(page); +@@ -503,21 +504,31 @@ __find_buddy_index(unsigned long page_idx, unsigned int order) + * For recording page's order, we use page_private(page). + */ + static inline int page_is_buddy(struct page *page, struct page *buddy, +- int order) ++ unsigned int order) + { + if (!pfn_valid_within(page_to_pfn(buddy))) + return 0; + +- if (page_zone_id(page) != page_zone_id(buddy)) +- return 0; +- + if (page_is_guard(buddy) && page_order(buddy) == order) { + VM_BUG_ON_PAGE(page_count(buddy) != 0, buddy); ++ ++ if (page_zone_id(page) != page_zone_id(buddy)) ++ return 0; ++ + return 1; + } + + if (PageBuddy(buddy) && page_order(buddy) == order) { + VM_BUG_ON_PAGE(page_count(buddy) != 0, buddy); ++ ++ /* ++ * zone check is done late to avoid uselessly ++ * calculating zone/node ids for pages that could ++ * never merge. ++ */ ++ if (page_zone_id(page) != page_zone_id(buddy)) ++ return 0; ++ + return 1; + } + return 0; +@@ -549,6 +560,7 @@ static inline int page_is_buddy(struct page *page, struct page *buddy, + */ + + static inline void __free_one_page(struct page *page, ++ unsigned long pfn, + struct zone *zone, unsigned int order, + int migratetype) + { +@@ -565,7 +577,7 @@ static inline void __free_one_page(struct page *page, + + VM_BUG_ON(migratetype == -1); + +- page_idx = page_to_pfn(page) & ((1 << MAX_ORDER) - 1); ++ page_idx = pfn & ((1 << MAX_ORDER) - 1); + + VM_BUG_ON_PAGE(page_idx & ((1 << order) - 1), page); + VM_BUG_ON_PAGE(bad_range(zone, page), page); +@@ -666,9 +678,12 @@ static void free_pcppages_bulk(struct zone *zone, int count, + int migratetype = 0; + int batch_free = 0; + int to_free = count; ++ unsigned long nr_scanned; + + spin_lock(&zone->lock); +- zone->pages_scanned = 0; ++ nr_scanned = zone_page_state(zone, NR_PAGES_SCANNED); ++ if (nr_scanned) ++ __mod_zone_page_state(zone, NR_PAGES_SCANNED, -nr_scanned); + + while (to_free) { + struct page *page; +@@ -700,7 +715,7 @@ static void free_pcppages_bulk(struct zone *zone, int count, + list_del(&page->lru); + mt = get_freepage_migratetype(page); + /* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */ +- __free_one_page(page, zone, 0, mt); ++ __free_one_page(page, page_to_pfn(page), zone, 0, mt); + trace_mm_page_pcpu_drain(page, 0, mt); + if (likely(!is_migrate_isolate_page(page))) { + __mod_zone_page_state(zone, NR_FREE_PAGES, 1); +@@ -712,13 +727,18 @@ static void free_pcppages_bulk(struct zone *zone, int count, + spin_unlock(&zone->lock); + } + +-static void free_one_page(struct zone *zone, struct page *page, int order, ++static void free_one_page(struct zone *zone, ++ struct page *page, unsigned long pfn, ++ unsigned int order, + int migratetype) + { ++ unsigned long nr_scanned; + spin_lock(&zone->lock); +- zone->pages_scanned = 0; ++ nr_scanned = zone_page_state(zone, NR_PAGES_SCANNED); ++ if (nr_scanned) ++ __mod_zone_page_state(zone, NR_PAGES_SCANNED, -nr_scanned); + +- __free_one_page(page, zone, order, migratetype); ++ __free_one_page(page, pfn, zone, order, migratetype); + if (unlikely(!is_migrate_isolate(migratetype))) + __mod_zone_freepage_state(zone, 1 << order, migratetype); + spin_unlock(&zone->lock); +@@ -755,15 +775,16 @@ static void __free_pages_ok(struct page *page, unsigned int order) + { + unsigned long flags; + int migratetype; ++ unsigned long pfn = page_to_pfn(page); + + if (!free_pages_prepare(page, order)) + return; + ++ migratetype = get_pfnblock_migratetype(page, pfn); + local_irq_save(flags); + __count_vm_events(PGFREE, 1 << order); +- migratetype = get_pageblock_migratetype(page); + set_freepage_migratetype(page, migratetype); +- free_one_page(page_zone(page), page, order, migratetype); ++ free_one_page(page_zone(page), page, pfn, order, migratetype); + local_irq_restore(flags); + } + +@@ -894,7 +915,7 @@ static inline int check_new_page(struct page *page) + return 0; + } + +-static int prep_new_page(struct page *page, int order, gfp_t gfp_flags) ++static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags) + { + int i; + +@@ -1105,16 +1126,17 @@ static int try_to_steal_freepages(struct zone *zone, struct page *page, + + /* Remove an element from the buddy allocator from the fallback list */ + static inline struct page * +-__rmqueue_fallback(struct zone *zone, int order, int start_migratetype) ++__rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype) + { + struct free_area *area; +- int current_order; ++ unsigned int current_order; + struct page *page; + int migratetype, new_type, i; + + /* Find the largest possible block of pages in the other list */ +- for (current_order = MAX_ORDER-1; current_order >= order; +- --current_order) { ++ for (current_order = MAX_ORDER-1; ++ current_order >= order && current_order <= MAX_ORDER-1; ++ --current_order) { + for (i = 0;; i++) { + migratetype = fallbacks[start_migratetype][i]; + +@@ -1194,7 +1216,7 @@ retry_reserve: + */ + static int rmqueue_bulk(struct zone *zone, unsigned int order, + unsigned long count, struct list_head *list, +- int migratetype, int cold) ++ int migratetype, bool cold) + { + int i; + +@@ -1213,7 +1235,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, + * merge IO requests if the physical pages are ordered + * properly. + */ +- if (likely(cold == 0)) ++ if (likely(!cold)) + list_add(&page->lru, list); + else + list_add_tail(&page->lru, list); +@@ -1342,7 +1364,7 @@ void mark_free_pages(struct zone *zone) + { + unsigned long pfn, max_zone_pfn; + unsigned long flags; +- int order, t; ++ unsigned int order, t; + struct list_head *curr; + + if (zone_is_empty(zone)) +@@ -1374,19 +1396,20 @@ void mark_free_pages(struct zone *zone) + + /* + * Free a 0-order page +- * cold == 1 ? free a cold page : free a hot page ++ * cold == true ? free a cold page : free a hot page + */ +-void free_hot_cold_page(struct page *page, int cold) ++void free_hot_cold_page(struct page *page, bool cold) + { + struct zone *zone = page_zone(page); + struct per_cpu_pages *pcp; + unsigned long flags; ++ unsigned long pfn = page_to_pfn(page); + int migratetype; + + if (!free_pages_prepare(page, 0)) + return; + +- migratetype = get_pageblock_migratetype(page); ++ migratetype = get_pfnblock_migratetype(page, pfn); + set_freepage_migratetype(page, migratetype); + local_irq_save(flags); + __count_vm_event(PGFREE); +@@ -1400,17 +1423,17 @@ void free_hot_cold_page(struct page *page, int cold) + */ + if (migratetype >= MIGRATE_PCPTYPES) { + if (unlikely(is_migrate_isolate(migratetype))) { +- free_one_page(zone, page, 0, migratetype); ++ free_one_page(zone, page, pfn, 0, migratetype); + goto out; + } + migratetype = MIGRATE_MOVABLE; + } + + pcp = &this_cpu_ptr(zone->pageset)->pcp; +- if (cold) +- list_add_tail(&page->lru, &pcp->lists[migratetype]); +- else ++ if (!cold) + list_add(&page->lru, &pcp->lists[migratetype]); ++ else ++ list_add_tail(&page->lru, &pcp->lists[migratetype]); + pcp->count++; + if (pcp->count >= pcp->high) { + unsigned long batch = ACCESS_ONCE(pcp->batch); +@@ -1425,7 +1448,7 @@ out: + /* + * Free a list of 0-order pages + */ +-void free_hot_cold_page_list(struct list_head *list, int cold) ++void free_hot_cold_page_list(struct list_head *list, bool cold) + { + struct page *page, *next; + +@@ -1537,12 +1560,12 @@ int split_free_page(struct page *page) + */ + static inline + struct page *buffered_rmqueue(struct zone *preferred_zone, +- struct zone *zone, int order, gfp_t gfp_flags, +- int migratetype) ++ struct zone *zone, unsigned int order, ++ gfp_t gfp_flags, int migratetype) + { + unsigned long flags; + struct page *page; +- int cold = !!(gfp_flags & __GFP_COLD); ++ bool cold = ((gfp_flags & __GFP_COLD) != 0); + + again: + if (likely(order == 0)) { +@@ -1591,6 +1614,9 @@ again: + } + + __mod_zone_page_state(zone, NR_ALLOC_BATCH, -(1 << order)); ++ if (zone_page_state(zone, NR_ALLOC_BATCH) == 0 && ++ !zone_is_fair_depleted(zone)) ++ zone_set_flag(zone, ZONE_FAIR_DEPLETED); + + __count_zone_vm_events(PGALLOC, zone, 1 << order); + zone_statistics(preferred_zone, zone, gfp_flags); +@@ -1687,12 +1713,12 @@ static inline bool should_fail_alloc_page(gfp_t gfp_mask, unsigned int order) + * Return true if free pages are above 'mark'. This takes into account the order + * of the allocation. + */ +-static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark, +- int classzone_idx, int alloc_flags, long free_pages) ++static bool __zone_watermark_ok(struct zone *z, unsigned int order, ++ unsigned long mark, int classzone_idx, int alloc_flags, ++ long free_pages) + { + /* free_pages my go negative - that's OK */ + long min = mark; +- long lowmem_reserve = z->lowmem_reserve[classzone_idx]; + int o; + long free_cma = 0; + +@@ -1707,7 +1733,7 @@ static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark, + free_cma = zone_page_state(z, NR_FREE_CMA_PAGES); + #endif + +- if (free_pages - free_cma <= min + lowmem_reserve) ++ if (free_pages - free_cma <= min + z->lowmem_reserve[classzone_idx]) + return false; + for (o = 0; o < order; o++) { + /* At the next order, this order's pages become unavailable */ +@@ -1722,15 +1748,15 @@ static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark, + return true; + } + +-bool zone_watermark_ok(struct zone *z, int order, unsigned long mark, ++bool zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark, + int classzone_idx, int alloc_flags) + { + return __zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags, + zone_page_state(z, NR_FREE_PAGES)); + } + +-bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark, +- int classzone_idx, int alloc_flags) ++bool zone_watermark_ok_safe(struct zone *z, unsigned int order, ++ unsigned long mark, int classzone_idx, int alloc_flags) + { + long free_pages = zone_page_state(z, NR_FREE_PAGES); + +@@ -1915,6 +1941,18 @@ static inline void init_zone_allows_reclaim(int nid) + } + #endif /* CONFIG_NUMA */ + ++static void reset_alloc_batches(struct zone *preferred_zone) ++{ ++ struct zone *zone = preferred_zone->zone_pgdat->node_zones; ++ ++ do { ++ mod_zone_page_state(zone, NR_ALLOC_BATCH, ++ high_wmark_pages(zone) - low_wmark_pages(zone) - ++ atomic_long_read(&zone->vm_stat[NR_ALLOC_BATCH])); ++ zone_clear_flag(zone, ZONE_FAIR_DEPLETED); ++ } while (zone++ != preferred_zone); ++} ++ + /* + * get_page_from_freelist goes through the zonelist trying to allocate + * a page. +@@ -1922,18 +1960,22 @@ static inline void init_zone_allows_reclaim(int nid) + static struct page * + get_page_from_freelist(gfp_t gfp_mask, nodemask_t *nodemask, unsigned int order, + struct zonelist *zonelist, int high_zoneidx, int alloc_flags, +- struct zone *preferred_zone, int migratetype) ++ struct zone *preferred_zone, int classzone_idx, int migratetype) + { + struct zoneref *z; + struct page *page = NULL; +- int classzone_idx; + struct zone *zone; + nodemask_t *allowednodes = NULL;/* zonelist_cache approximation */ + int zlc_active = 0; /* set if using zonelist_cache */ + int did_zlc_setup = 0; /* just call zlc_setup() one time */ ++ bool consider_zone_dirty = (alloc_flags & ALLOC_WMARK_LOW) && ++ (gfp_mask & __GFP_WRITE); ++ int nr_fair_skipped = 0; ++ bool zonelist_rescan; + +- classzone_idx = zone_idx(preferred_zone); + zonelist_scan: ++ zonelist_rescan = false; ++ + /* + * Scan zonelist, looking for a zone with enough free. + * See also __cpuset_node_allowed_softwall() comment in kernel/cpuset.c. +@@ -1945,12 +1987,10 @@ zonelist_scan: + if (IS_ENABLED(CONFIG_NUMA) && zlc_active && + !zlc_zone_worth_trying(zonelist, z, allowednodes)) + continue; +- if ((alloc_flags & ALLOC_CPUSET) && ++ if (cpusets_enabled() && ++ (alloc_flags & ALLOC_CPUSET) && + !cpuset_zone_allowed_softwall(zone, gfp_mask)) + continue; +- BUILD_BUG_ON(ALLOC_NO_WATERMARKS < NR_WMARK); +- if (unlikely(alloc_flags & ALLOC_NO_WATERMARKS)) +- goto try_this_zone; + /* + * Distribute pages in proportion to the individual + * zone size to ensure fair page aging. The zone a +@@ -1959,9 +1999,11 @@ zonelist_scan: + */ + if (alloc_flags & ALLOC_FAIR) { + if (!zone_local(preferred_zone, zone)) ++ break; ++ if (zone_is_fair_depleted(zone)) { ++ nr_fair_skipped++; + continue; +- if (atomic_long_read(&zone->vm_stat[NR_ALLOC_BATCH]) <= 0) +- continue; ++ } + } + /* + * When allocating a page cache page for writing, we +@@ -1989,15 +2031,19 @@ zonelist_scan: + * will require awareness of zones in the + * dirty-throttling and the flusher threads. + */ +- if ((alloc_flags & ALLOC_WMARK_LOW) && +- (gfp_mask & __GFP_WRITE) && !zone_dirty_ok(zone)) +- goto this_zone_full; ++ if (consider_zone_dirty && !zone_dirty_ok(zone)) ++ continue; + + mark = zone->watermark[alloc_flags & ALLOC_WMARK_MASK]; + if (!zone_watermark_ok(zone, order, mark, + classzone_idx, alloc_flags)) { + int ret; + ++ /* Checked here to keep the fast path fast */ ++ BUILD_BUG_ON(ALLOC_NO_WATERMARKS < NR_WMARK); ++ if (alloc_flags & ALLOC_NO_WATERMARKS) ++ goto try_this_zone; ++ + if (IS_ENABLED(CONFIG_NUMA) && + !did_zlc_setup && nr_online_nodes > 1) { + /* +@@ -2059,17 +2105,11 @@ try_this_zone: + if (page) + break; + this_zone_full: +- if (IS_ENABLED(CONFIG_NUMA)) ++ if (IS_ENABLED(CONFIG_NUMA) && zlc_active) + zlc_mark_zone_full(zonelist, z); + } + +- if (unlikely(IS_ENABLED(CONFIG_NUMA) && page == NULL && zlc_active)) { +- /* Disable zlc cache for second zonelist scan */ +- zlc_active = 0; +- goto zonelist_scan; +- } +- +- if (page) ++ if (page) { + /* + * page->pfmemalloc is set when ALLOC_NO_WATERMARKS was + * necessary to allocate the page. The expectation is +@@ -2078,8 +2118,37 @@ this_zone_full: + * for !PFMEMALLOC purposes. + */ + page->pfmemalloc = !!(alloc_flags & ALLOC_NO_WATERMARKS); ++ return page; ++ } + +- return page; ++ /* ++ * The first pass makes sure allocations are spread fairly within the ++ * local node. However, the local node might have free pages left ++ * after the fairness batches are exhausted, and remote zones haven't ++ * even been considered yet. Try once more without fairness, and ++ * include remote zones now, before entering the slowpath and waking ++ * kswapd: prefer spilling to a remote zone over swapping locally. ++ */ ++ if (alloc_flags & ALLOC_FAIR) { ++ alloc_flags &= ~ALLOC_FAIR; ++ if (nr_fair_skipped) { ++ zonelist_rescan = true; ++ reset_alloc_batches(preferred_zone); ++ } ++ if (nr_online_nodes > 1) ++ zonelist_rescan = true; ++ } ++ ++ if (unlikely(IS_ENABLED(CONFIG_NUMA) && zlc_active)) { ++ /* Disable zlc cache for second zonelist scan */ ++ zlc_active = 0; ++ zonelist_rescan = true; ++ } ++ ++ if (zonelist_rescan) ++ goto zonelist_scan; ++ ++ return NULL; + } + + /* +@@ -2188,7 +2257,7 @@ static inline struct page * + __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, enum zone_type high_zoneidx, + nodemask_t *nodemask, struct zone *preferred_zone, +- int migratetype) ++ int classzone_idx, int migratetype) + { + struct page *page; + +@@ -2214,7 +2283,7 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order, + page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, + order, zonelist, high_zoneidx, + ALLOC_WMARK_HIGH|ALLOC_CPUSET, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, migratetype); + if (page) + goto out; + +@@ -2249,7 +2318,7 @@ static struct page * + __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, enum zone_type high_zoneidx, + nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone, +- int migratetype, enum migrate_mode mode, ++ int classzone_idx, int migratetype, enum migrate_mode mode, + bool *contended_compaction, bool *deferred_compaction, + unsigned long *did_some_progress) + { +@@ -2277,7 +2346,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, + page = get_page_from_freelist(gfp_mask, nodemask, + order, zonelist, high_zoneidx, + alloc_flags & ~ALLOC_NO_WATERMARKS, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, migratetype); + if (page) { + preferred_zone->compact_blockskip_flush = false; + compaction_defer_reset(preferred_zone, order, true); +@@ -2309,7 +2378,8 @@ static inline struct page * + __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, enum zone_type high_zoneidx, + nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone, +- int migratetype, enum migrate_mode mode, bool *contended_compaction, ++ int classzone_idx, int migratetype, ++ enum migrate_mode mode, bool *contended_compaction, + bool *deferred_compaction, unsigned long *did_some_progress) + { + return NULL; +@@ -2349,7 +2419,7 @@ static inline struct page * + __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, enum zone_type high_zoneidx, + nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone, +- int migratetype, unsigned long *did_some_progress) ++ int classzone_idx, int migratetype, unsigned long *did_some_progress) + { + struct page *page = NULL; + bool drained = false; +@@ -2367,7 +2437,8 @@ retry: + page = get_page_from_freelist(gfp_mask, nodemask, order, + zonelist, high_zoneidx, + alloc_flags & ~ALLOC_NO_WATERMARKS, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, ++ migratetype); + + /* + * If an allocation failed after direct reclaim, it could be because +@@ -2390,14 +2461,14 @@ static inline struct page * + __alloc_pages_high_priority(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, enum zone_type high_zoneidx, + nodemask_t *nodemask, struct zone *preferred_zone, +- int migratetype) ++ int classzone_idx, int migratetype) + { + struct page *page; + + do { + page = get_page_from_freelist(gfp_mask, nodemask, order, + zonelist, high_zoneidx, ALLOC_NO_WATERMARKS, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, migratetype); + + if (!page && gfp_mask & __GFP_NOFAIL) + wait_iff_congested(preferred_zone, BLK_RW_ASYNC, HZ/50); +@@ -2406,28 +2477,6 @@ __alloc_pages_high_priority(gfp_t gfp_mask, unsigned int order, + return page; + } + +-static void reset_alloc_batches(struct zonelist *zonelist, +- enum zone_type high_zoneidx, +- struct zone *preferred_zone) +-{ +- struct zoneref *z; +- struct zone *zone; +- +- for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) { +- /* +- * Only reset the batches of zones that were actually +- * considered in the fairness pass, we don't want to +- * trash fairness information for zones that are not +- * actually part of this zonelist's round-robin cycle. +- */ +- if (!zone_local(preferred_zone, zone)) +- continue; +- mod_zone_page_state(zone, NR_ALLOC_BATCH, +- high_wmark_pages(zone) - low_wmark_pages(zone) - +- atomic_long_read(&zone->vm_stat[NR_ALLOC_BATCH])); +- } +-} +- + static void wake_all_kswapds(unsigned int order, + struct zonelist *zonelist, + enum zone_type high_zoneidx, +@@ -2498,7 +2547,7 @@ static inline struct page * + __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, enum zone_type high_zoneidx, + nodemask_t *nodemask, struct zone *preferred_zone, +- int migratetype) ++ int classzone_idx, int migratetype) + { + const gfp_t wait = gfp_mask & __GFP_WAIT; + struct page *page = NULL; +@@ -2547,15 +2596,19 @@ restart: + * Find the true preferred zone if the allocation is unconstrained by + * cpusets. + */ +- if (!(alloc_flags & ALLOC_CPUSET) && !nodemask) +- first_zones_zonelist(zonelist, high_zoneidx, NULL, +- &preferred_zone); ++ if (!(alloc_flags & ALLOC_CPUSET) && !nodemask) { ++ struct zoneref *preferred_zoneref; ++ preferred_zoneref = first_zones_zonelist(zonelist, high_zoneidx, ++ NULL, ++ &preferred_zone); ++ classzone_idx = zonelist_zone_idx(preferred_zoneref); ++ } + + rebalance: + /* This is the last chance, in general, before the goto nopage. */ + page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist, + high_zoneidx, alloc_flags & ~ALLOC_NO_WATERMARKS, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, migratetype); + if (page) + goto got_pg; + +@@ -2570,7 +2623,7 @@ rebalance: + + page = __alloc_pages_high_priority(gfp_mask, order, + zonelist, high_zoneidx, nodemask, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, migratetype); + if (page) { + goto got_pg; + } +@@ -2601,7 +2654,8 @@ rebalance: + */ + page = __alloc_pages_direct_compact(gfp_mask, order, zonelist, + high_zoneidx, nodemask, alloc_flags, +- preferred_zone, migratetype, ++ preferred_zone, ++ classzone_idx, migratetype, + migration_mode, &contended_compaction, + &deferred_compaction, + &did_some_progress); +@@ -2624,7 +2678,8 @@ rebalance: + zonelist, high_zoneidx, + nodemask, + alloc_flags, preferred_zone, +- migratetype, &did_some_progress); ++ classzone_idx, migratetype, ++ &did_some_progress); + if (page) + goto got_pg; + +@@ -2643,7 +2698,7 @@ rebalance: + page = __alloc_pages_may_oom(gfp_mask, order, + zonelist, high_zoneidx, + nodemask, preferred_zone, +- migratetype); ++ classzone_idx, migratetype); + if (page) + goto got_pg; + +@@ -2684,7 +2739,8 @@ rebalance: + */ + page = __alloc_pages_direct_compact(gfp_mask, order, zonelist, + high_zoneidx, nodemask, alloc_flags, +- preferred_zone, migratetype, ++ preferred_zone, ++ classzone_idx, migratetype, + migration_mode, &contended_compaction, + &deferred_compaction, + &did_some_progress); +@@ -2711,11 +2767,13 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, + { + enum zone_type high_zoneidx = gfp_zone(gfp_mask); + struct zone *preferred_zone; ++ struct zoneref *preferred_zoneref; + struct page *page = NULL; + int migratetype = allocflags_to_migratetype(gfp_mask); + unsigned int cpuset_mems_cookie; + int alloc_flags = ALLOC_WMARK_LOW|ALLOC_CPUSET|ALLOC_FAIR; + struct mem_cgroup *memcg = NULL; ++ int classzone_idx; + + gfp_mask &= gfp_allowed_mask; + +@@ -2745,39 +2803,23 @@ retry_cpuset: + cpuset_mems_cookie = read_mems_allowed_begin(); + + /* The preferred zone is used for statistics later */ +- first_zones_zonelist(zonelist, high_zoneidx, ++ preferred_zoneref = first_zones_zonelist(zonelist, high_zoneidx, + nodemask ? : &cpuset_current_mems_allowed, + &preferred_zone); + if (!preferred_zone) + goto out; ++ classzone_idx = zonelist_zone_idx(preferred_zoneref); + + #ifdef CONFIG_CMA + if (allocflags_to_migratetype(gfp_mask) == MIGRATE_MOVABLE) + alloc_flags |= ALLOC_CMA; + #endif +-retry: + /* First allocation attempt */ + page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, order, + zonelist, high_zoneidx, alloc_flags, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, migratetype); + if (unlikely(!page)) { + /* +- * The first pass makes sure allocations are spread +- * fairly within the local node. However, the local +- * node might have free pages left after the fairness +- * batches are exhausted, and remote zones haven't +- * even been considered yet. Try once more without +- * fairness, and include remote zones now, before +- * entering the slowpath and waking kswapd: prefer +- * spilling to a remote zone over swapping locally. +- */ +- if (alloc_flags & ALLOC_FAIR) { +- reset_alloc_batches(zonelist, high_zoneidx, +- preferred_zone); +- alloc_flags &= ~ALLOC_FAIR; +- goto retry; +- } +- /* + * Runtime PM, block IO and its error handling path + * can deadlock because I/O on the device might not + * complete. +@@ -2785,7 +2827,7 @@ retry: + gfp_mask = memalloc_noio_flags(gfp_mask); + page = __alloc_pages_slowpath(gfp_mask, order, + zonelist, high_zoneidx, nodemask, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, migratetype); + } + + trace_mm_page_alloc(page, order, gfp_mask, migratetype); +@@ -2836,7 +2878,7 @@ void __free_pages(struct page *page, unsigned int order) + { + if (put_page_testzero(page)) { + if (order == 0) +- free_hot_cold_page(page, 0); ++ free_hot_cold_page(page, false); + else + __free_pages_ok(page, order); + } +@@ -3220,12 +3262,12 @@ void show_free_areas(unsigned int filter) + K(zone_page_state(zone, NR_BOUNCE)), + K(zone_page_state(zone, NR_FREE_CMA_PAGES)), + K(zone_page_state(zone, NR_WRITEBACK_TEMP)), +- zone->pages_scanned, ++ K(zone_page_state(zone, NR_PAGES_SCANNED)), + (!zone_reclaimable(zone) ? "yes" : "no") + ); + printk("lowmem_reserve[]:"); + for (i = 0; i < MAX_NR_ZONES; i++) +- printk(" %lu", zone->lowmem_reserve[i]); ++ printk(" %ld", zone->lowmem_reserve[i]); + printk("\n"); + } + +@@ -4113,7 +4155,7 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, + + static void __meminit zone_init_free_lists(struct zone *zone) + { +- int order, t; ++ unsigned int order, t; + for_each_migratetype_order(order, t) { + INIT_LIST_HEAD(&zone->free_area[order].free_list[t]); + zone->free_area[order].nr_free = 0; +@@ -5553,7 +5595,7 @@ static void calculate_totalreserve_pages(void) + for_each_online_pgdat(pgdat) { + for (i = 0; i < MAX_NR_ZONES; i++) { + struct zone *zone = pgdat->node_zones + i; +- unsigned long max = 0; ++ long max = 0; + + /* Find valid and maximum lowmem_reserve in the zone */ + for (j = i; j < MAX_NR_ZONES; j++) { +@@ -6041,17 +6083,16 @@ static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn) + * @end_bitidx: The last bit of interest + * returns pageblock_bits flags + */ +-unsigned long get_pageblock_flags_mask(struct page *page, ++unsigned long get_pfnblock_flags_mask(struct page *page, unsigned long pfn, + unsigned long end_bitidx, + unsigned long mask) + { + struct zone *zone; + unsigned long *bitmap; +- unsigned long pfn, bitidx, word_bitidx; ++ unsigned long bitidx, word_bitidx; + unsigned long word; + + zone = page_zone(page); +- pfn = page_to_pfn(page); + bitmap = get_pageblock_bitmap(zone, pfn); + bitidx = pfn_to_bitidx(zone, pfn); + word_bitidx = bitidx / BITS_PER_LONG; +@@ -6063,25 +6104,25 @@ unsigned long get_pageblock_flags_mask(struct page *page, + } + + /** +- * set_pageblock_flags_mask - Set the requested group of flags for a pageblock_nr_pages block of pages ++ * set_pfnblock_flags_mask - Set the requested group of flags for a pageblock_nr_pages block of pages + * @page: The page within the block of interest + * @start_bitidx: The first bit of interest + * @end_bitidx: The last bit of interest + * @flags: The flags to set + */ +-void set_pageblock_flags_mask(struct page *page, unsigned long flags, ++void set_pfnblock_flags_mask(struct page *page, unsigned long flags, ++ unsigned long pfn, + unsigned long end_bitidx, + unsigned long mask) + { + struct zone *zone; + unsigned long *bitmap; +- unsigned long pfn, bitidx, word_bitidx; ++ unsigned long bitidx, word_bitidx; + unsigned long old_word, word; + + BUILD_BUG_ON(NR_PAGEBLOCK_BITS != 4); + + zone = page_zone(page); +- pfn = page_to_pfn(page); + bitmap = get_pageblock_bitmap(zone, pfn); + bitidx = pfn_to_bitidx(zone, pfn); + word_bitidx = bitidx / BITS_PER_LONG; +@@ -6453,7 +6494,7 @@ __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn) + { + struct page *page; + struct zone *zone; +- int order, i; ++ unsigned int order, i; + unsigned long pfn; + unsigned long flags; + /* find the first valid pfn */ +@@ -6505,7 +6546,7 @@ bool is_free_buddy_page(struct page *page) + struct zone *zone = page_zone(page); + unsigned long pfn = page_to_pfn(page); + unsigned long flags; +- int order; ++ unsigned int order; + + spin_lock_irqsave(&zone->lock, flags); + for (order = 0; order < MAX_ORDER; order++) { +diff --git a/mm/shmem.c b/mm/shmem.c +index 0f1447563f17..85d8a1a3626c 100644 +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -1035,6 +1035,9 @@ repeat: + goto failed; + } + ++ if (page && sgp == SGP_WRITE) ++ mark_page_accessed(page); ++ + /* fallocated page? */ + if (page && !PageUptodate(page)) { + if (sgp != SGP_READ) +@@ -1116,6 +1119,9 @@ repeat: + shmem_recalc_inode(inode); + spin_unlock(&info->lock); + ++ if (sgp == SGP_WRITE) ++ mark_page_accessed(page); ++ + delete_from_swap_cache(page); + set_page_dirty(page); + swap_free(swap); +@@ -1140,8 +1146,11 @@ repeat: + goto decused; + } + +- SetPageSwapBacked(page); ++ __SetPageSwapBacked(page); + __set_page_locked(page); ++ if (sgp == SGP_WRITE) ++ init_page_accessed(page); ++ + error = mem_cgroup_cache_charge(page, current->mm, + gfp & GFP_RECLAIM_MASK); + if (error) +diff --git a/mm/swap.c b/mm/swap.c +index c8048d71c642..d2ceddf70d42 100644 +--- a/mm/swap.c ++++ b/mm/swap.c +@@ -67,7 +67,7 @@ static void __page_cache_release(struct page *page) + static void __put_single_page(struct page *page) + { + __page_cache_release(page); +- free_hot_cold_page(page, 0); ++ free_hot_cold_page(page, false); + } + + static void __put_compound_page(struct page *page) +@@ -469,7 +469,7 @@ static void __activate_page(struct page *page, struct lruvec *lruvec, + SetPageActive(page); + lru += LRU_ACTIVE; + add_page_to_lru_list(page, lruvec, lru); +- trace_mm_lru_activate(page, page_to_pfn(page)); ++ trace_mm_lru_activate(page); + + __count_vm_event(PGACTIVATE); + update_page_reclaim_stat(lruvec, file, 1); +@@ -581,12 +581,17 @@ void mark_page_accessed(struct page *page) + EXPORT_SYMBOL(mark_page_accessed); + + /* +- * Queue the page for addition to the LRU via pagevec. The decision on whether +- * to add the page to the [in]active [file|anon] list is deferred until the +- * pagevec is drained. This gives a chance for the caller of __lru_cache_add() +- * have the page added to the active list using mark_page_accessed(). ++ * Used to mark_page_accessed(page) that is not visible yet and when it is ++ * still safe to use non-atomic ops + */ +-void __lru_cache_add(struct page *page) ++void init_page_accessed(struct page *page) ++{ ++ if (!PageReferenced(page)) ++ __SetPageReferenced(page); ++} ++EXPORT_SYMBOL(init_page_accessed); ++ ++static void __lru_cache_add(struct page *page) + { + struct pagevec *pvec = &get_cpu_var(lru_add_pvec); + +@@ -596,11 +601,34 @@ void __lru_cache_add(struct page *page) + pagevec_add(pvec, page); + put_cpu_var(lru_add_pvec); + } +-EXPORT_SYMBOL(__lru_cache_add); ++ ++/** ++ * lru_cache_add: add a page to the page lists ++ * @page: the page to add ++ */ ++void lru_cache_add_anon(struct page *page) ++{ ++ if (PageActive(page)) ++ ClearPageActive(page); ++ __lru_cache_add(page); ++} ++ ++void lru_cache_add_file(struct page *page) ++{ ++ if (PageActive(page)) ++ ClearPageActive(page); ++ __lru_cache_add(page); ++} ++EXPORT_SYMBOL(lru_cache_add_file); + + /** + * lru_cache_add - add a page to a page list + * @page: the page to be added to the LRU. ++ * ++ * Queue the page for addition to the LRU via pagevec. The decision on whether ++ * to add the page to the [in]active [file|anon] list is deferred until the ++ * pagevec is drained. This gives a chance for the caller of lru_cache_add() ++ * have the page added to the active list using mark_page_accessed(). + */ + void lru_cache_add(struct page *page) + { +@@ -811,7 +839,7 @@ void lru_add_drain_all(void) + * grabbed the page via the LRU. If it did, give up: shrink_inactive_list() + * will free it. + */ +-void release_pages(struct page **pages, int nr, int cold) ++void release_pages(struct page **pages, int nr, bool cold) + { + int i; + LIST_HEAD(pages_to_free); +@@ -852,7 +880,7 @@ void release_pages(struct page **pages, int nr, int cold) + } + + /* Clear Active bit in case of parallel mark_page_accessed */ +- ClearPageActive(page); ++ __ClearPageActive(page); + + list_add(&page->lru, &pages_to_free); + } +@@ -934,7 +962,7 @@ static void __pagevec_lru_add_fn(struct page *page, struct lruvec *lruvec, + SetPageLRU(page); + add_page_to_lru_list(page, lruvec, lru); + update_page_reclaim_stat(lruvec, file, active); +- trace_mm_lru_insertion(page, page_to_pfn(page), lru, trace_pagemap_flags(page)); ++ trace_mm_lru_insertion(page, lru); + } + + /* +diff --git a/mm/swap_state.c b/mm/swap_state.c +index e76ace30d436..2972eee184a4 100644 +--- a/mm/swap_state.c ++++ b/mm/swap_state.c +@@ -270,7 +270,7 @@ void free_pages_and_swap_cache(struct page **pages, int nr) + + for (i = 0; i < todo; i++) + free_swap_cache(pagep[i]); +- release_pages(pagep, todo, 0); ++ release_pages(pagep, todo, false); + pagep += todo; + nr -= todo; + } +diff --git a/mm/vmalloc.c b/mm/vmalloc.c +index 0fdf96803c5b..aa3891e8e388 100644 +--- a/mm/vmalloc.c ++++ b/mm/vmalloc.c +@@ -2681,14 +2681,14 @@ void get_vmalloc_info(struct vmalloc_info *vmi) + + prev_end = VMALLOC_START; + +- spin_lock(&vmap_area_lock); ++ rcu_read_lock(); + + if (list_empty(&vmap_area_list)) { + vmi->largest_chunk = VMALLOC_TOTAL; + goto out; + } + +- list_for_each_entry(va, &vmap_area_list, list) { ++ list_for_each_entry_rcu(va, &vmap_area_list, list) { + unsigned long addr = va->va_start; + + /* +@@ -2715,7 +2715,7 @@ void get_vmalloc_info(struct vmalloc_info *vmi) + vmi->largest_chunk = VMALLOC_END - prev_end; + + out: +- spin_unlock(&vmap_area_lock); ++ rcu_read_unlock(); + } + #endif + +diff --git a/mm/vmscan.c b/mm/vmscan.c +index be6a689a71a6..b850ced69ed6 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -163,7 +163,8 @@ static unsigned long zone_reclaimable_pages(struct zone *zone) + + bool zone_reclaimable(struct zone *zone) + { +- return zone->pages_scanned < zone_reclaimable_pages(zone) * 6; ++ return zone_page_state(zone, NR_PAGES_SCANNED) < ++ zone_reclaimable_pages(zone) * 6; + } + + static unsigned long get_lru_size(struct lruvec *lruvec, enum lru_list lru) +@@ -1107,7 +1108,7 @@ keep: + VM_BUG_ON_PAGE(PageLRU(page) || PageUnevictable(page), page); + } + +- free_hot_cold_page_list(&free_pages, 1); ++ free_hot_cold_page_list(&free_pages, true); + + list_splice(&ret_pages, page_list); + count_vm_events(PGACTIVATE, pgactivate); +@@ -1470,7 +1471,7 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec, + __mod_zone_page_state(zone, NR_ISOLATED_ANON + file, nr_taken); + + if (global_reclaim(sc)) { +- zone->pages_scanned += nr_scanned; ++ __mod_zone_page_state(zone, NR_PAGES_SCANNED, nr_scanned); + if (current_is_kswapd()) + __count_zone_vm_events(PGSCAN_KSWAPD, zone, nr_scanned); + else +@@ -1505,7 +1506,7 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec, + + spin_unlock_irq(&zone->lru_lock); + +- free_hot_cold_page_list(&page_list, 1); ++ free_hot_cold_page_list(&page_list, true); + + /* + * If reclaim is isolating dirty pages under writeback, it implies +@@ -1659,7 +1660,7 @@ static void shrink_active_list(unsigned long nr_to_scan, + nr_taken = isolate_lru_pages(nr_to_scan, lruvec, &l_hold, + &nr_scanned, sc, isolate_mode, lru); + if (global_reclaim(sc)) +- zone->pages_scanned += nr_scanned; ++ __mod_zone_page_state(zone, NR_PAGES_SCANNED, nr_scanned); + + reclaim_stat->recent_scanned[file] += nr_taken; + +@@ -1725,7 +1726,7 @@ static void shrink_active_list(unsigned long nr_to_scan, + __mod_zone_page_state(zone, NR_ISOLATED_ANON + file, -nr_taken); + spin_unlock_irq(&zone->lru_lock); + +- free_hot_cold_page_list(&l_hold, 1); ++ free_hot_cold_page_list(&l_hold, true); + } + + #ifdef CONFIG_SWAP +@@ -1847,7 +1848,7 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, + struct zone *zone = lruvec_zone(lruvec); + unsigned long anon_prio, file_prio; + enum scan_balance scan_balance; +- unsigned long anon, file, free; ++ unsigned long anon, file; + bool force_scan = false; + unsigned long ap, fp; + enum lru_list lru; +@@ -1895,11 +1896,6 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, + goto out; + } + +- anon = get_lru_size(lruvec, LRU_ACTIVE_ANON) + +- get_lru_size(lruvec, LRU_INACTIVE_ANON); +- file = get_lru_size(lruvec, LRU_ACTIVE_FILE) + +- get_lru_size(lruvec, LRU_INACTIVE_FILE); +- + /* + * If it's foreseeable that reclaiming the file cache won't be + * enough to get the zone back into a desirable shape, we have +@@ -1907,8 +1903,14 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, + * thrashing - remaining file pages alone. + */ + if (global_reclaim(sc)) { +- free = zone_page_state(zone, NR_FREE_PAGES); +- if (unlikely(file + free <= high_wmark_pages(zone))) { ++ unsigned long zonefile; ++ unsigned long zonefree; ++ ++ zonefree = zone_page_state(zone, NR_FREE_PAGES); ++ zonefile = zone_page_state(zone, NR_ACTIVE_FILE) + ++ zone_page_state(zone, NR_INACTIVE_FILE); ++ ++ if (unlikely(zonefile + zonefree <= high_wmark_pages(zone))) { + scan_balance = SCAN_ANON; + goto out; + } +@@ -1943,6 +1945,12 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, + * + * anon in [0], file in [1] + */ ++ ++ anon = get_lru_size(lruvec, LRU_ACTIVE_ANON) + ++ get_lru_size(lruvec, LRU_INACTIVE_ANON); ++ file = get_lru_size(lruvec, LRU_ACTIVE_FILE) + ++ get_lru_size(lruvec, LRU_INACTIVE_FILE); ++ + spin_lock_irq(&zone->lru_lock); + if (unlikely(reclaim_stat->recent_scanned[0] > anon / 4)) { + reclaim_stat->recent_scanned[0] /= 2; +diff --git a/mm/vmstat.c b/mm/vmstat.c +index def5dd2fbe61..eded1909a690 100644 +--- a/mm/vmstat.c ++++ b/mm/vmstat.c +@@ -200,7 +200,7 @@ void set_pgdat_percpu_threshold(pg_data_t *pgdat, + continue; + + threshold = (*calculate_pressure)(zone); +- for_each_possible_cpu(cpu) ++ for_each_online_cpu(cpu) + per_cpu_ptr(zone->pageset, cpu)->stat_threshold + = threshold; + } +@@ -761,6 +761,7 @@ const char * const vmstat_text[] = { + "nr_shmem", + "nr_dirtied", + "nr_written", ++ "nr_pages_scanned", + + #ifdef CONFIG_NUMA + "numa_hit", +@@ -1055,7 +1056,7 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat, + min_wmark_pages(zone), + low_wmark_pages(zone), + high_wmark_pages(zone), +- zone->pages_scanned, ++ zone_page_state(zone, NR_PAGES_SCANNED), + zone->spanned_pages, + zone->present_pages, + zone->managed_pages); +@@ -1065,10 +1066,10 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat, + zone_page_state(zone, i)); + + seq_printf(m, +- "\n protection: (%lu", ++ "\n protection: (%ld", + zone->lowmem_reserve[0]); + for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++) +- seq_printf(m, ", %lu", zone->lowmem_reserve[i]); ++ seq_printf(m, ", %ld", zone->lowmem_reserve[i]); + seq_printf(m, + ")" + "\n pagesets"); +diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c +index 77c173282f38..4a662f15eaee 100644 +--- a/net/netfilter/ipvs/ip_vs_ftp.c ++++ b/net/netfilter/ipvs/ip_vs_ftp.c +@@ -183,6 +183,8 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, + struct nf_conn *ct; + struct net *net; + ++ *diff = 0; ++ + #ifdef CONFIG_IP_VS_IPV6 + /* This application helper doesn't work with IPv6 yet, + * so turn this into a no-op for IPv6 packets +@@ -191,8 +193,6 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, + return 1; + #endif + +- *diff = 0; +- + /* Only useful for established sessions */ + if (cp->state != IP_VS_TCP_S_ESTABLISHED) + return 1; +@@ -321,6 +321,9 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, + struct ip_vs_conn *n_cp; + struct net *net; + ++ /* no diff required for incoming packets */ ++ *diff = 0; ++ + #ifdef CONFIG_IP_VS_IPV6 + /* This application helper doesn't work with IPv6 yet, + * so turn this into a no-op for IPv6 packets +@@ -329,9 +332,6 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, + return 1; + #endif + +- /* no diff required for incoming packets */ +- *diff = 0; +- + /* Only useful for established sessions */ + if (cp->state != IP_VS_TCP_S_ESTABLISHED) + return 1; +diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c +index bf8a108b46e2..6cf2f077e09c 100644 +--- a/net/netfilter/nfnetlink.c ++++ b/net/netfilter/nfnetlink.c +@@ -265,7 +265,8 @@ replay: + nlh = nlmsg_hdr(skb); + err = 0; + +- if (nlh->nlmsg_len < NLMSG_HDRLEN) { ++ if (nlmsg_len(nlh) < sizeof(struct nfgenmsg) || ++ skb->len < nlh->nlmsg_len) { + err = -EINVAL; + goto ack; + } +diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl +index 91280b82da08..513f7bd85cb7 100755 +--- a/scripts/recordmcount.pl ++++ b/scripts/recordmcount.pl +@@ -262,7 +262,6 @@ if ($arch eq "x86_64") { + # force flags for this arch + $ld .= " -m shlelf_linux"; + $objcopy .= " -O elf32-sh-linux"; +- $cc .= " -m32"; + + } elsif ($arch eq "powerpc") { + $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)"; +diff --git a/security/keys/gc.c b/security/keys/gc.c +index d3222b6d7d59..009d9370c8fd 100644 +--- a/security/keys/gc.c ++++ b/security/keys/gc.c +@@ -157,12 +157,12 @@ static noinline void key_gc_unused_keys(struct list_head *keys) + if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) + atomic_dec(&key->user->nikeys); + +- key_user_put(key->user); +- + /* now throw away the key memory */ + if (key->type->destroy) + key->type->destroy(key); + ++ key_user_put(key->user); ++ + kfree(key->description); + + #ifdef KEY_DEBUGGING +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index 1bed780e21d9..2d37b3fc3a21 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -886,6 +886,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, + case USB_ID(0x046d, 0x0807): /* Logitech Webcam C500 */ + case USB_ID(0x046d, 0x0808): + case USB_ID(0x046d, 0x0809): ++ case USB_ID(0x046d, 0x0819): /* Logitech Webcam C210 */ + case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */ + case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ + case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */ diff --git a/patch/kernel/cubox-default/patch-3.14.31-32.patch b/patch/kernel/cubox-default/patch-3.14.31-32.patch new file mode 100644 index 000000000..cca57f39a --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.31-32.patch @@ -0,0 +1,1098 @@ +diff --git a/Makefile b/Makefile +index 5abf670c6651..00fffa3f2310 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 31 ++SUBLEVEL = 32 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c +index 11b3914660d2..42f2fb8c5a00 100644 +--- a/arch/arm/mm/dma-mapping.c ++++ b/arch/arm/mm/dma-mapping.c +@@ -464,12 +464,21 @@ void __init dma_contiguous_remap(void) + map.type = MT_MEMORY_DMA_READY; + + /* +- * Clear previous low-memory mapping ++ * Clear previous low-memory mapping to ensure that the ++ * TLB does not see any conflicting entries, then flush ++ * the TLB of the old entries before creating new mappings. ++ * ++ * This ensures that any speculatively loaded TLB entries ++ * (even though they may be rare) can not cause any problems, ++ * and ensures that this code is architecturally compliant. + */ + for (addr = __phys_to_virt(start); addr < __phys_to_virt(end); + addr += PMD_SIZE) + pmd_clear(pmd_off_k(addr)); + ++ flush_tlb_kernel_range(__phys_to_virt(start), ++ __phys_to_virt(end)); ++ + iotable_init(&map, 1); + } + } +diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c +index bc5fbc201bcb..f89389f634d7 100644 +--- a/arch/powerpc/xmon/xmon.c ++++ b/arch/powerpc/xmon/xmon.c +@@ -288,6 +288,7 @@ static inline void disable_surveillance(void) + args.token = rtas_token("set-indicator"); + if (args.token == RTAS_UNKNOWN_SERVICE) + return; ++ args.token = cpu_to_be32(args.token); + args.nargs = cpu_to_be32(3); + args.nret = cpu_to_be32(1); + args.rets = &args.args[3]; +diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile +index b5bb49866bcc..67e9f5cc91ed 100644 +--- a/arch/x86/boot/compressed/Makefile ++++ b/arch/x86/boot/compressed/Makefile +@@ -76,7 +76,7 @@ suffix-$(CONFIG_KERNEL_LZO) := lzo + suffix-$(CONFIG_KERNEL_LZ4) := lz4 + + RUN_SIZE = $(shell $(OBJDUMP) -h vmlinux | \ +- perl $(srctree)/arch/x86/tools/calc_run_size.pl) ++ $(CONFIG_SHELL) $(srctree)/arch/x86/tools/calc_run_size.sh) + quiet_cmd_mkpiggy = MKPIGGY $@ + cmd_mkpiggy = $(obj)/mkpiggy $< $(RUN_SIZE) > $@ || ( rm -f $@ ; false ) + +diff --git a/arch/x86/tools/calc_run_size.pl b/arch/x86/tools/calc_run_size.pl +deleted file mode 100644 +index 23210baade2d..000000000000 +--- a/arch/x86/tools/calc_run_size.pl ++++ /dev/null +@@ -1,39 +0,0 @@ +-#!/usr/bin/perl +-# +-# Calculate the amount of space needed to run the kernel, including room for +-# the .bss and .brk sections. +-# +-# Usage: +-# objdump -h a.out | perl calc_run_size.pl +-use strict; +- +-my $mem_size = 0; +-my $file_offset = 0; +- +-my $sections=" *[0-9]+ \.(?:bss|brk) +"; +-while (<>) { +- if (/^$sections([0-9a-f]+) +(?:[0-9a-f]+ +){2}([0-9a-f]+)/) { +- my $size = hex($1); +- my $offset = hex($2); +- $mem_size += $size; +- if ($file_offset == 0) { +- $file_offset = $offset; +- } elsif ($file_offset != $offset) { +- # BFD linker shows the same file offset in ELF. +- # Gold linker shows them as consecutive. +- next if ($file_offset + $mem_size == $offset + $size); +- +- printf STDERR "file_offset: 0x%lx\n", $file_offset; +- printf STDERR "mem_size: 0x%lx\n", $mem_size; +- printf STDERR "offset: 0x%lx\n", $offset; +- printf STDERR "size: 0x%lx\n", $size; +- +- die ".bss and .brk are non-contiguous\n"; +- } +- } +-} +- +-if ($file_offset == 0) { +- die "Never found .bss or .brk file offset\n"; +-} +-printf("%d\n", $mem_size + $file_offset); +diff --git a/arch/x86/tools/calc_run_size.sh b/arch/x86/tools/calc_run_size.sh +new file mode 100644 +index 000000000000..1a4c17bb3910 +--- /dev/null ++++ b/arch/x86/tools/calc_run_size.sh +@@ -0,0 +1,42 @@ ++#!/bin/sh ++# ++# Calculate the amount of space needed to run the kernel, including room for ++# the .bss and .brk sections. ++# ++# Usage: ++# objdump -h a.out | sh calc_run_size.sh ++ ++NUM='\([0-9a-fA-F]*[ \t]*\)' ++OUT=$(sed -n 's/^[ \t0-9]*.b[sr][sk][ \t]*'"$NUM$NUM$NUM$NUM"'.*/\1\4/p') ++if [ -z "$OUT" ] ; then ++ echo "Never found .bss or .brk file offset" >&2 ++ exit 1 ++fi ++ ++OUT=$(echo ${OUT# }) ++sizeA=$(printf "%d" 0x${OUT%% *}) ++OUT=${OUT#* } ++offsetA=$(printf "%d" 0x${OUT%% *}) ++OUT=${OUT#* } ++sizeB=$(printf "%d" 0x${OUT%% *}) ++OUT=${OUT#* } ++offsetB=$(printf "%d" 0x${OUT%% *}) ++ ++run_size=$(( $offsetA + $sizeA + $sizeB )) ++ ++# BFD linker shows the same file offset in ELF. ++if [ "$offsetA" -ne "$offsetB" ] ; then ++ # Gold linker shows them as consecutive. ++ endB=$(( $offsetB + $sizeB )) ++ if [ "$endB" != "$run_size" ] ; then ++ printf "sizeA: 0x%x\n" $sizeA >&2 ++ printf "offsetA: 0x%x\n" $offsetA >&2 ++ printf "sizeB: 0x%x\n" $sizeB >&2 ++ printf "offsetB: 0x%x\n" $offsetB >&2 ++ echo ".bss and .brk are non-contiguous" >&2 ++ exit 1 ++ fi ++fi ++ ++printf "%d\n" $run_size ++exit 0 +diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c +index 255ca232ecc7..275a7dc2b06c 100644 +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -1926,32 +1926,26 @@ static void rbd_dev_parent_put(struct rbd_device *rbd_dev) + * If an image has a non-zero parent overlap, get a reference to its + * parent. + * +- * We must get the reference before checking for the overlap to +- * coordinate properly with zeroing the parent overlap in +- * rbd_dev_v2_parent_info() when an image gets flattened. We +- * drop it again if there is no overlap. +- * + * Returns true if the rbd device has a parent with a non-zero + * overlap and a reference for it was successfully taken, or + * false otherwise. + */ + static bool rbd_dev_parent_get(struct rbd_device *rbd_dev) + { +- int counter; ++ int counter = 0; + + if (!rbd_dev->parent_spec) + return false; + +- counter = atomic_inc_return_safe(&rbd_dev->parent_ref); +- if (counter > 0 && rbd_dev->parent_overlap) +- return true; +- +- /* Image was flattened, but parent is not yet torn down */ ++ down_read(&rbd_dev->header_rwsem); ++ if (rbd_dev->parent_overlap) ++ counter = atomic_inc_return_safe(&rbd_dev->parent_ref); ++ up_read(&rbd_dev->header_rwsem); + + if (counter < 0) + rbd_warn(rbd_dev, "parent reference overflow\n"); + +- return false; ++ return counter > 0; + } + + /* +@@ -3904,7 +3898,6 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev) + */ + if (rbd_dev->parent_overlap) { + rbd_dev->parent_overlap = 0; +- smp_mb(); + rbd_dev_parent_put(rbd_dev); + pr_info("%s: clone image has been flattened\n", + rbd_dev->disk->disk_name); +@@ -3948,7 +3941,6 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev) + * treat it specially. + */ + rbd_dev->parent_overlap = overlap; +- smp_mb(); + if (!overlap) { + + /* A null parent_spec indicates it's the initial probe */ +@@ -4764,10 +4756,7 @@ static void rbd_dev_unprobe(struct rbd_device *rbd_dev) + { + struct rbd_image_header *header; + +- /* Drop parent reference unless it's already been done (or none) */ +- +- if (rbd_dev->parent_overlap) +- rbd_dev_parent_put(rbd_dev); ++ rbd_dev_parent_put(rbd_dev); + + /* Free dynamic fields from the header, then zero it out */ + +diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c +index 3153eabde39b..de5ab4876a89 100644 +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -2893,6 +2893,13 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg, + u32 size = i915_gem_obj_ggtt_size(obj); + uint64_t val; + ++ /* Adjust fence size to match tiled area */ ++ if (obj->tiling_mode != I915_TILING_NONE) { ++ uint32_t row_size = obj->stride * ++ (obj->tiling_mode == I915_TILING_Y ? 32 : 8); ++ size = (size / row_size) * row_size; ++ } ++ + val = (uint64_t)((i915_gem_obj_ggtt_offset(obj) + size - 4096) & + 0xfffff000) << 32; + val |= i915_gem_obj_ggtt_offset(obj) & 0xfffff000; +diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c +index 93ec37649346..79a211782766 100644 +--- a/drivers/i2c/busses/i2c-s3c2410.c ++++ b/drivers/i2c/busses/i2c-s3c2410.c +@@ -753,14 +753,16 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, + int ret; + + pm_runtime_get_sync(&adap->dev); +- clk_prepare_enable(i2c->clk); ++ ret = clk_enable(i2c->clk); ++ if (ret) ++ return ret; + + for (retry = 0; retry < adap->retries; retry++) { + + ret = s3c24xx_i2c_doxfer(i2c, msgs, num); + + if (ret != -EAGAIN) { +- clk_disable_unprepare(i2c->clk); ++ clk_disable(i2c->clk); + pm_runtime_put(&adap->dev); + return ret; + } +@@ -770,7 +772,7 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, + udelay(100); + } + +- clk_disable_unprepare(i2c->clk); ++ clk_disable(i2c->clk); + pm_runtime_put(&adap->dev); + return -EREMOTEIO; + } +@@ -1153,7 +1155,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + + clk_prepare_enable(i2c->clk); + ret = s3c24xx_i2c_init(i2c); +- clk_disable_unprepare(i2c->clk); ++ clk_disable(i2c->clk); + if (ret != 0) { + dev_err(&pdev->dev, "I2C controller init failed\n"); + return ret; +@@ -1166,6 +1168,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + i2c->irq = ret = platform_get_irq(pdev, 0); + if (ret <= 0) { + dev_err(&pdev->dev, "cannot find IRQ\n"); ++ clk_unprepare(i2c->clk); + return ret; + } + +@@ -1174,6 +1177,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + + if (ret != 0) { + dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); ++ clk_unprepare(i2c->clk); + return ret; + } + } +@@ -1181,6 +1185,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + ret = s3c24xx_i2c_register_cpufreq(i2c); + if (ret < 0) { + dev_err(&pdev->dev, "failed to register cpufreq notifier\n"); ++ clk_unprepare(i2c->clk); + return ret; + } + +@@ -1197,6 +1202,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + if (ret < 0) { + dev_err(&pdev->dev, "failed to add bus to i2c core\n"); + s3c24xx_i2c_deregister_cpufreq(i2c); ++ clk_unprepare(i2c->clk); + return ret; + } + +@@ -1218,6 +1224,8 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) + { + struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); + ++ clk_unprepare(i2c->clk); ++ + pm_runtime_disable(&i2c->adap.dev); + pm_runtime_disable(&pdev->dev); + +@@ -1246,10 +1254,13 @@ static int s3c24xx_i2c_resume(struct device *dev) + { + struct platform_device *pdev = to_platform_device(dev); + struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); ++ int ret; + +- clk_prepare_enable(i2c->clk); ++ ret = clk_enable(i2c->clk); ++ if (ret) ++ return ret; + s3c24xx_i2c_init(i2c); +- clk_disable_unprepare(i2c->clk); ++ clk_disable(i2c->clk); + i2c->suspended = 0; + + return 0; +diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c +index a3769cf84381..b00e282ef166 100644 +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -132,8 +132,9 @@ static const struct min_max_quirk min_max_pnpid_table[] = { + 1232, 5710, 1156, 4696 + }, + { +- (const char * const []){"LEN0034", "LEN0036", "LEN0039", +- "LEN2002", "LEN2004", NULL}, ++ (const char * const []){"LEN0034", "LEN0036", "LEN0037", ++ "LEN0039", "LEN2002", "LEN2004", ++ NULL}, + 1024, 5112, 2024, 4832 + }, + { +@@ -162,7 +163,7 @@ static const char * const topbuttonpad_pnp_ids[] = { + "LEN0034", /* T431s, L440, L540, T540, W540, X1 Carbon 2nd */ + "LEN0035", /* X240 */ + "LEN0036", /* T440 */ +- "LEN0037", ++ "LEN0037", /* X1 Carbon 2nd */ + "LEN0038", + "LEN0039", /* T440s */ + "LEN0041", +diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h +index c43c46f7dcd0..dd6d14d2337f 100644 +--- a/drivers/input/serio/i8042-x86ia64io.h ++++ b/drivers/input/serio/i8042-x86ia64io.h +@@ -152,6 +152,14 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { + }, + }, + { ++ /* Medion Akoya E7225 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Medion"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Akoya E7225"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"), ++ }, ++ }, ++ { + /* Blue FB5601 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "blue"), +diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c +index d290e8396116..b950a803bae8 100644 +--- a/drivers/md/dm-cache-metadata.c ++++ b/drivers/md/dm-cache-metadata.c +@@ -683,7 +683,7 @@ static struct dm_cache_metadata *metadata_open(struct block_device *bdev, + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + DMERR("could not allocate metadata struct"); +- return NULL; ++ return ERR_PTR(-ENOMEM); + } + + atomic_set(&cmd->ref_count, 1); +@@ -745,7 +745,7 @@ static struct dm_cache_metadata *lookup_or_open(struct block_device *bdev, + return cmd; + + cmd = metadata_open(bdev, data_block_size, may_format_device, policy_hint_size); +- if (cmd) { ++ if (!IS_ERR(cmd)) { + mutex_lock(&table_lock); + cmd2 = lookup(bdev); + if (cmd2) { +@@ -780,9 +780,10 @@ struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, + { + struct dm_cache_metadata *cmd = lookup_or_open(bdev, data_block_size, + may_format_device, policy_hint_size); +- if (cmd && !same_params(cmd, data_block_size)) { ++ ++ if (!IS_ERR(cmd) && !same_params(cmd, data_block_size)) { + dm_cache_metadata_close(cmd); +- return NULL; ++ return ERR_PTR(-EINVAL); + } + + return cmd; +diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c +index f7e052c7ab5f..c1120eb96d86 100644 +--- a/drivers/md/dm-thin.c ++++ b/drivers/md/dm-thin.c +@@ -2744,6 +2744,12 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv) + struct pool_c *pt = ti->private; + struct pool *pool = pt->pool; + ++ if (get_pool_mode(pool) >= PM_READ_ONLY) { ++ DMERR("%s: unable to service pool target messages in READ_ONLY or FAIL mode", ++ dm_device_name(pool->pool_md)); ++ return -EINVAL; ++ } ++ + if (!strcasecmp(argv[0], "create_thin")) + r = process_create_thin_mesg(argc, argv, pool); + +diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c +index 4e65b35bebc0..3d198679510b 100644 +--- a/drivers/net/can/usb/kvaser_usb.c ++++ b/drivers/net/can/usb/kvaser_usb.c +@@ -578,7 +578,7 @@ static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv, + usb_sndbulkpipe(dev->udev, + dev->bulk_out->bEndpointAddress), + buf, msg->len, +- kvaser_usb_simple_msg_callback, priv); ++ kvaser_usb_simple_msg_callback, netdev); + usb_anchor_urb(urb, &priv->tx_submitted); + + err = usb_submit_urb(urb, GFP_ATOMIC); +@@ -653,11 +653,6 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev, + priv = dev->nets[channel]; + stats = &priv->netdev->stats; + +- if (status & M16C_STATE_BUS_RESET) { +- kvaser_usb_unlink_tx_urbs(priv); +- return; +- } +- + skb = alloc_can_err_skb(priv->netdev, &cf); + if (!skb) { + stats->rx_dropped++; +@@ -668,7 +663,7 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev, + + netdev_dbg(priv->netdev, "Error status: 0x%02x\n", status); + +- if (status & M16C_STATE_BUS_OFF) { ++ if (status & (M16C_STATE_BUS_OFF | M16C_STATE_BUS_RESET)) { + cf->can_id |= CAN_ERR_BUSOFF; + + priv->can.can_stats.bus_off++; +@@ -694,9 +689,7 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev, + } + + new_state = CAN_STATE_ERROR_PASSIVE; +- } +- +- if (status == M16C_STATE_BUS_ERROR) { ++ } else if (status & M16C_STATE_BUS_ERROR) { + if ((priv->can.state < CAN_STATE_ERROR_WARNING) && + ((txerr >= 96) || (rxerr >= 96))) { + cf->can_id |= CAN_ERR_CRTL; +@@ -706,7 +699,8 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev, + + priv->can.can_stats.error_warning++; + new_state = CAN_STATE_ERROR_WARNING; +- } else if (priv->can.state > CAN_STATE_ERROR_ACTIVE) { ++ } else if ((priv->can.state > CAN_STATE_ERROR_ACTIVE) && ++ ((txerr < 96) && (rxerr < 96))) { + cf->can_id |= CAN_ERR_PROT; + cf->data[2] = CAN_ERR_PROT_ACTIVE; + +@@ -1582,7 +1576,7 @@ static int kvaser_usb_probe(struct usb_interface *intf, + { + struct kvaser_usb *dev; + int err = -ENOMEM; +- int i; ++ int i, retry = 3; + + dev = devm_kzalloc(&intf->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) +@@ -1600,7 +1594,15 @@ static int kvaser_usb_probe(struct usb_interface *intf, + + usb_set_intfdata(intf, dev); + +- err = kvaser_usb_get_software_info(dev); ++ /* On some x86 laptops, plugging a Kvaser device again after ++ * an unplug makes the firmware always ignore the very first ++ * command. For such a case, provide some room for retries ++ * instead of completely exiting the driver. ++ */ ++ do { ++ err = kvaser_usb_get_software_info(dev); ++ } while (--retry && err == -ETIMEDOUT); ++ + if (err) { + dev_err(&intf->dev, + "Cannot get software infos, error %d\n", err); +diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c +index 316650c3b5d7..4eb091da7fb6 100644 +--- a/drivers/net/ethernet/ti/cpsw.c ++++ b/drivers/net/ethernet/ti/cpsw.c +@@ -1610,6 +1610,19 @@ static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev, + if (vid == priv->data.default_vlan) + return 0; + ++ if (priv->data.dual_emac) { ++ /* In dual EMAC, reserved VLAN id should not be used for ++ * creating VLAN interfaces as this can break the dual ++ * EMAC port separation ++ */ ++ int i; ++ ++ for (i = 0; i < priv->data.slaves; i++) { ++ if (vid == priv->slaves[i].port_vlan) ++ return -EINVAL; ++ } ++ } ++ + dev_info(priv->dev, "Adding vlanid %d to vlan filter\n", vid); + return cpsw_add_vlan_ale_entry(priv, vid); + } +@@ -1623,6 +1636,15 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev, + if (vid == priv->data.default_vlan) + return 0; + ++ if (priv->data.dual_emac) { ++ int i; ++ ++ for (i = 0; i < priv->data.slaves; i++) { ++ if (vid == priv->slaves[i].port_vlan) ++ return -EINVAL; ++ } ++ } ++ + dev_info(priv->dev, "removing vlanid %d from vlan filter\n", vid); + ret = cpsw_ale_del_vlan(priv->ale, vid, 0); + if (ret != 0) +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index afca1bc24f26..b7984044232d 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1479,7 +1479,7 @@ struct regulator *regulator_get_optional(struct device *dev, const char *id) + } + EXPORT_SYMBOL_GPL(regulator_get_optional); + +-/* Locks held by regulator_put() */ ++/* regulator_list_mutex lock held by regulator_put() */ + static void _regulator_put(struct regulator *regulator) + { + struct regulator_dev *rdev; +@@ -1494,12 +1494,14 @@ static void _regulator_put(struct regulator *regulator) + /* remove any sysfs entries */ + if (regulator->dev) + sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); ++ mutex_lock(&rdev->mutex); + kfree(regulator->supply_name); + list_del(®ulator->list); + kfree(regulator); + + rdev->open_count--; + rdev->exclusive = 0; ++ mutex_unlock(&rdev->mutex); + + module_put(rdev->owner); + } +diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c +index a4c45ea8f688..996e16d12cd4 100644 +--- a/drivers/spi/spi-dw-mid.c ++++ b/drivers/spi/spi-dw-mid.c +@@ -222,7 +222,6 @@ int dw_spi_mid_init(struct dw_spi *dws) + iounmap(clk_reg); + + dws->num_cs = 16; +- dws->fifo_len = 40; /* FIFO has 40 words buffer */ + + #ifdef CONFIG_SPI_DW_MID_DMA + dws->dma_priv = kzalloc(sizeof(struct mid_dma), GFP_KERNEL); +diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c +index 7ab3ccb592eb..458a1480dc07 100644 +--- a/drivers/spi/spi-pxa2xx.c ++++ b/drivers/spi/spi-pxa2xx.c +@@ -400,8 +400,8 @@ static void giveback(struct driver_data *drv_data) + cs_deassert(drv_data); + } + +- spi_finalize_current_message(drv_data->master); + drv_data->cur_chip = NULL; ++ spi_finalize_current_message(drv_data->master); + } + + static void reset_sccr1(struct driver_data *drv_data) +diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c +index 38b4be24d13f..26ae6886ac59 100644 +--- a/drivers/target/target_core_device.c ++++ b/drivers/target/target_core_device.c +@@ -1153,10 +1153,10 @@ int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors) + " changed for TCM/pSCSI\n", dev); + return -EINVAL; + } +- if (optimal_sectors > dev->dev_attrib.fabric_max_sectors) { ++ if (optimal_sectors > dev->dev_attrib.hw_max_sectors) { + pr_err("dev[%p]: Passed optimal_sectors %u cannot be" +- " greater than fabric_max_sectors: %u\n", dev, +- optimal_sectors, dev->dev_attrib.fabric_max_sectors); ++ " greater than hw_max_sectors: %u\n", dev, ++ optimal_sectors, dev->dev_attrib.hw_max_sectors); + return -EINVAL; + } + +@@ -1565,7 +1565,6 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) + DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT; + dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN; + dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS; +- dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS; + + xcopy_lun = &dev->xcopy_lun; + xcopy_lun->lun_se_dev = dev; +@@ -1606,6 +1605,7 @@ int target_configure_device(struct se_device *dev) + dev->dev_attrib.hw_max_sectors = + se_dev_align_max_sectors(dev->dev_attrib.hw_max_sectors, + dev->dev_attrib.hw_block_size); ++ dev->dev_attrib.optimal_sectors = dev->dev_attrib.hw_max_sectors; + + dev->dev_index = scsi_get_new_index(SCSI_DEVICE_INDEX); + dev->creation_time = get_jiffies_64(); +diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c +index cf991a91a8a9..41eff7d64cb8 100644 +--- a/drivers/target/target_core_file.c ++++ b/drivers/target/target_core_file.c +@@ -620,7 +620,16 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, + struct fd_prot fd_prot; + sense_reason_t rc; + int ret = 0; +- ++ /* ++ * We are currently limited by the number of iovecs (2048) per ++ * single vfs_[writev,readv] call. ++ */ ++ if (cmd->data_length > FD_MAX_BYTES) { ++ pr_err("FILEIO: Not able to process I/O of %u bytes due to" ++ "FD_MAX_BYTES: %u iovec count limitiation\n", ++ cmd->data_length, FD_MAX_BYTES); ++ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; ++ } + /* + * Call vectorized fileio functions to map struct scatterlist + * physical memory addresses to struct iovec virtual memory. +diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c +index 9e0232cca92e..feefe24a88f7 100644 +--- a/drivers/target/target_core_iblock.c ++++ b/drivers/target/target_core_iblock.c +@@ -123,7 +123,7 @@ static int iblock_configure_device(struct se_device *dev) + q = bdev_get_queue(bd); + + dev->dev_attrib.hw_block_size = bdev_logical_block_size(bd); +- dev->dev_attrib.hw_max_sectors = UINT_MAX; ++ dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q); + dev->dev_attrib.hw_queue_depth = q->nr_requests; + + /* +diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c +index 379033f5903b..5216acd68b4b 100644 +--- a/drivers/target/target_core_sbc.c ++++ b/drivers/target/target_core_sbc.c +@@ -910,21 +910,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) + if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { + unsigned long long end_lba; + +- if (sectors > dev->dev_attrib.fabric_max_sectors) { +- printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" +- " big sectors %u exceeds fabric_max_sectors:" +- " %u\n", cdb[0], sectors, +- dev->dev_attrib.fabric_max_sectors); +- return TCM_INVALID_CDB_FIELD; +- } +- if (sectors > dev->dev_attrib.hw_max_sectors) { +- printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" +- " big sectors %u exceeds backend hw_max_sectors:" +- " %u\n", cdb[0], sectors, +- dev->dev_attrib.hw_max_sectors); +- return TCM_INVALID_CDB_FIELD; +- } +- + end_lba = dev->transport->get_blocks(dev) + 1; + if (cmd->t_task_lba + sectors > end_lba) { + pr_err("cmd exceeds last lba %llu " +diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c +index fcdf98fc947c..12a74f646d38 100644 +--- a/drivers/target/target_core_spc.c ++++ b/drivers/target/target_core_spc.c +@@ -503,7 +503,6 @@ static sense_reason_t + spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) + { + struct se_device *dev = cmd->se_dev; +- u32 max_sectors; + int have_tp = 0; + int opt, min; + +@@ -537,9 +536,7 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) + /* + * Set MAXIMUM TRANSFER LENGTH + */ +- max_sectors = min(dev->dev_attrib.fabric_max_sectors, +- dev->dev_attrib.hw_max_sectors); +- put_unaligned_be32(max_sectors, &buf[8]); ++ put_unaligned_be32(dev->dev_attrib.hw_max_sectors, &buf[8]); + + /* + * Set OPTIMAL TRANSFER LENGTH +diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c +index de2543d3c283..7ececa1c6c4f 100644 +--- a/fs/nfs/direct.c ++++ b/fs/nfs/direct.c +@@ -123,6 +123,12 @@ static inline int put_dreq(struct nfs_direct_req *dreq) + */ + ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs) + { ++ struct inode *inode = iocb->ki_filp->f_mapping->host; ++ ++ /* we only support swap file calling nfs_direct_IO */ ++ if (!IS_SWAPFILE(inode)) ++ return 0; ++ + #ifndef CONFIG_NFS_SWAP + dprintk("NFS: nfs_direct_IO (%pD) off/no(%Ld/%lu) EINVAL\n", + iocb->ki_filp, (long long) pos, nr_segs); +diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c +index 037f9572b94c..d3f606255b99 100644 +--- a/fs/nfs/nfs4client.c ++++ b/fs/nfs/nfs4client.c +@@ -633,7 +633,7 @@ int nfs41_walk_client_list(struct nfs_client *new, + prev = pos; + + status = nfs_wait_client_init_complete(pos); +- if (status == 0) { ++ if (pos->cl_cons_state == NFS_CS_SESSION_INITING) { + nfs4_schedule_lease_recovery(pos); + status = nfs4_wait_clnt_recover(pos); + } +diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c +index e7d95f959333..fe68d8ac4d3d 100644 +--- a/fs/pstore/ram.c ++++ b/fs/pstore/ram.c +@@ -92,6 +92,7 @@ struct ramoops_context { + struct persistent_ram_ecc_info ecc_info; + unsigned int max_dump_cnt; + unsigned int dump_write_cnt; ++ /* _read_cnt need clear on ramoops_pstore_open */ + unsigned int dump_read_cnt; + unsigned int console_read_cnt; + unsigned int ftrace_read_cnt; +@@ -107,6 +108,7 @@ static int ramoops_pstore_open(struct pstore_info *psi) + + cxt->dump_read_cnt = 0; + cxt->console_read_cnt = 0; ++ cxt->ftrace_read_cnt = 0; + return 0; + } + +@@ -123,13 +125,15 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], uint *c, uint max, + return NULL; + + prz = przs[i]; ++ if (!prz) ++ return NULL; + +- if (update) { +- /* Update old/shadowed buffer. */ ++ /* Update old/shadowed buffer. */ ++ if (update) + persistent_ram_save_old(prz); +- if (!persistent_ram_old_size(prz)) +- return NULL; +- } ++ ++ if (!persistent_ram_old_size(prz)) ++ return NULL; + + *typep = type; + *id = i; +@@ -435,7 +439,6 @@ static int ramoops_probe(struct platform_device *pdev) + if (pdata->ftrace_size && !is_power_of_2(pdata->ftrace_size)) + pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); + +- cxt->dump_read_cnt = 0; + cxt->size = pdata->mem_size; + cxt->phys_addr = pdata->mem_address; + cxt->memtype = pdata->mem_type; +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index b4defdecec8a..f6f31d823e8e 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -1962,17 +1962,13 @@ static void pool_mayday_timeout(unsigned long __pool) + * spin_lock_irq(pool->lock) which may be released and regrabbed + * multiple times. Does GFP_KERNEL allocations. Called only from + * manager. +- * +- * Return: +- * %false if no action was taken and pool->lock stayed locked, %true +- * otherwise. + */ +-static bool maybe_create_worker(struct worker_pool *pool) ++static void maybe_create_worker(struct worker_pool *pool) + __releases(&pool->lock) + __acquires(&pool->lock) + { + if (!need_to_create_worker(pool)) +- return false; ++ return; + restart: + spin_unlock_irq(&pool->lock); + +@@ -1989,7 +1985,7 @@ restart: + start_worker(worker); + if (WARN_ON_ONCE(need_to_create_worker(pool))) + goto restart; +- return true; ++ return; + } + + if (!need_to_create_worker(pool)) +@@ -2006,7 +2002,7 @@ restart: + spin_lock_irq(&pool->lock); + if (need_to_create_worker(pool)) + goto restart; +- return true; ++ return; + } + + /** +@@ -2019,15 +2015,9 @@ restart: + * LOCKING: + * spin_lock_irq(pool->lock) which may be released and regrabbed + * multiple times. Called only from manager. +- * +- * Return: +- * %false if no action was taken and pool->lock stayed locked, %true +- * otherwise. + */ +-static bool maybe_destroy_workers(struct worker_pool *pool) ++static void maybe_destroy_workers(struct worker_pool *pool) + { +- bool ret = false; +- + while (too_many_workers(pool)) { + struct worker *worker; + unsigned long expires; +@@ -2041,10 +2031,7 @@ static bool maybe_destroy_workers(struct worker_pool *pool) + } + + destroy_worker(worker); +- ret = true; + } +- +- return ret; + } + + /** +@@ -2064,16 +2051,14 @@ static bool maybe_destroy_workers(struct worker_pool *pool) + * multiple times. Does GFP_KERNEL allocations. + * + * Return: +- * %false if the pool don't need management and the caller can safely start +- * processing works, %true indicates that the function released pool->lock +- * and reacquired it to perform some management function and that the +- * conditions that the caller verified while holding the lock before +- * calling the function might no longer be true. ++ * %false if the pool doesn't need management and the caller can safely ++ * start processing works, %true if management function was performed and ++ * the conditions that the caller verified before calling the function may ++ * no longer be true. + */ + static bool manage_workers(struct worker *worker) + { + struct worker_pool *pool = worker->pool; +- bool ret = false; + + /* + * Managership is governed by two mutexes - manager_arb and +@@ -2097,7 +2082,7 @@ static bool manage_workers(struct worker *worker) + * manager_mutex. + */ + if (!mutex_trylock(&pool->manager_arb)) +- return ret; ++ return false; + + /* + * With manager arbitration won, manager_mutex would be free in +@@ -2107,7 +2092,6 @@ static bool manage_workers(struct worker *worker) + spin_unlock_irq(&pool->lock); + mutex_lock(&pool->manager_mutex); + spin_lock_irq(&pool->lock); +- ret = true; + } + + pool->flags &= ~POOL_MANAGE_WORKERS; +@@ -2116,12 +2100,12 @@ static bool manage_workers(struct worker *worker) + * Destroy and then create so that may_start_working() is true + * on return. + */ +- ret |= maybe_destroy_workers(pool); +- ret |= maybe_create_worker(pool); ++ maybe_destroy_workers(pool); ++ maybe_create_worker(pool); + + mutex_unlock(&pool->manager_mutex); + mutex_unlock(&pool->manager_arb); +- return ret; ++ return true; + } + + /** +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 1e4dc4ed5e0d..815ca56b39e7 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -261,7 +261,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, + else if (rate && rate->flags & IEEE80211_RATE_ERP_G) + channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; + else if (rate) +- channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; ++ channel_flags |= IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ; + else + channel_flags |= IEEE80211_CHAN_2GHZ; + put_unaligned_le16(channel_flags, pos); +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index df33156ecd2d..18d73df72531 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -2697,6 +2697,9 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) + if (!rdev->ops->get_key) + return -EOPNOTSUPP; + ++ if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) ++ return -ENOENT; ++ + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; +@@ -2716,10 +2719,6 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr)) + goto nla_put_failure; + +- if (pairwise && mac_addr && +- !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) +- return -ENOENT; +- + err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie, + get_key_callback); + +@@ -2890,7 +2889,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) + wdev_lock(dev->ieee80211_ptr); + err = nl80211_key_allowed(dev->ieee80211_ptr); + +- if (key.type == NL80211_KEYTYPE_PAIRWISE && mac_addr && ++ if (key.type == NL80211_KEYTYPE_GROUP && mac_addr && + !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) + err = -ENOENT; + +diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c +index dbc550716790..f60d81497f28 100644 +--- a/sound/core/seq/seq_dummy.c ++++ b/sound/core/seq/seq_dummy.c +@@ -82,36 +82,6 @@ struct snd_seq_dummy_port { + static int my_client = -1; + + /* +- * unuse callback - send ALL_SOUNDS_OFF and RESET_CONTROLLERS events +- * to subscribers. +- * Note: this callback is called only after all subscribers are removed. +- */ +-static int +-dummy_unuse(void *private_data, struct snd_seq_port_subscribe *info) +-{ +- struct snd_seq_dummy_port *p; +- int i; +- struct snd_seq_event ev; +- +- p = private_data; +- memset(&ev, 0, sizeof(ev)); +- if (p->duplex) +- ev.source.port = p->connect; +- else +- ev.source.port = p->port; +- ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; +- ev.type = SNDRV_SEQ_EVENT_CONTROLLER; +- for (i = 0; i < 16; i++) { +- ev.data.control.channel = i; +- ev.data.control.param = MIDI_CTL_ALL_SOUNDS_OFF; +- snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0); +- ev.data.control.param = MIDI_CTL_RESET_CONTROLLERS; +- snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0); +- } +- return 0; +-} +- +-/* + * event input callback - just redirect events to subscribers + */ + static int +@@ -175,7 +145,6 @@ create_port(int idx, int type) + | SNDRV_SEQ_PORT_TYPE_PORT; + memset(&pcb, 0, sizeof(pcb)); + pcb.owner = THIS_MODULE; +- pcb.unuse = dummy_unuse; + pcb.event_input = dummy_input; + pcb.private_free = dummy_free; + pcb.private_data = rec; +diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c +index f156010e52bc..942ef8427347 100644 +--- a/sound/soc/codecs/wm8960.c ++++ b/sound/soc/codecs/wm8960.c +@@ -555,7 +555,7 @@ static struct { + { 22050, 2 }, + { 24000, 2 }, + { 16000, 3 }, +- { 11250, 4 }, ++ { 11025, 4 }, + { 12000, 4 }, + { 8000, 5 }, + }; +diff --git a/sound/soc/fsl/fsl_esai.h b/sound/soc/fsl/fsl_esai.h +index 75e14033e8d8..dfdbaa014561 100644 +--- a/sound/soc/fsl/fsl_esai.h ++++ b/sound/soc/fsl/fsl_esai.h +@@ -302,7 +302,7 @@ + #define ESAI_xCCR_xFP_MASK (((1 << ESAI_xCCR_xFP_WIDTH) - 1) << ESAI_xCCR_xFP_SHIFT) + #define ESAI_xCCR_xFP(v) ((((v) - 1) << ESAI_xCCR_xFP_SHIFT) & ESAI_xCCR_xFP_MASK) + #define ESAI_xCCR_xDC_SHIFT 9 +-#define ESAI_xCCR_xDC_WIDTH 4 ++#define ESAI_xCCR_xDC_WIDTH 5 + #define ESAI_xCCR_xDC_MASK (((1 << ESAI_xCCR_xDC_WIDTH) - 1) << ESAI_xCCR_xDC_SHIFT) + #define ESAI_xCCR_xDC(v) ((((v) - 1) << ESAI_xCCR_xDC_SHIFT) & ESAI_xCCR_xDC_MASK) + #define ESAI_xCCR_xPSR_SHIFT 8 +diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c +index 6c19bba23570..6a339fb55479 100644 +--- a/sound/soc/omap/omap-mcbsp.c ++++ b/sound/soc/omap/omap-mcbsp.c +@@ -436,7 +436,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, + case SND_SOC_DAIFMT_CBM_CFS: + /* McBSP slave. FS clock as output */ + regs->srgr2 |= FSGM; +- regs->pcr0 |= FSXM; ++ regs->pcr0 |= FSXM | FSRM; + break; + case SND_SOC_DAIFMT_CBM_CFM: + /* McBSP slave */ +diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c +index 5e9690c85d8f..4f98ff14cf12 100644 +--- a/sound/soc/soc-compress.c ++++ b/sound/soc/soc-compress.c +@@ -696,7 +696,8 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) + rtd->dai_link->stream_name); + + ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, +- 1, 0, &be_pcm); ++ rtd->dai_link->dpcm_playback, ++ rtd->dai_link->dpcm_capture, &be_pcm); + if (ret < 0) { + dev_err(rtd->card->dev, "ASoC: can't create compressed for %s\n", + rtd->dai_link->name); +@@ -705,8 +706,10 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) + + rtd->pcm = be_pcm; + rtd->fe_compr = 1; +- be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; +- be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; ++ if (rtd->dai_link->dpcm_playback) ++ be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; ++ else if (rtd->dai_link->dpcm_capture) ++ be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; + memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops)); + } else + memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); diff --git a/patch/kernel/cubox-default/patch-3.14.32-33.patch b/patch/kernel/cubox-default/patch-3.14.32-33.patch new file mode 100644 index 000000000..6d2d1f2f4 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.32-33.patch @@ -0,0 +1,942 @@ +diff --git a/Makefile b/Makefile +index 00fffa3f2310..b0963ca2895d 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 32 ++SUBLEVEL = 33 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c +index 6eb97b3a7481..4370933f16cd 100644 +--- a/arch/arm/mm/context.c ++++ b/arch/arm/mm/context.c +@@ -144,21 +144,17 @@ static void flush_context(unsigned int cpu) + /* Update the list of reserved ASIDs and the ASID bitmap. */ + bitmap_clear(asid_map, 0, NUM_USER_ASIDS); + for_each_possible_cpu(i) { +- if (i == cpu) { +- asid = 0; +- } else { +- asid = atomic64_xchg(&per_cpu(active_asids, i), 0); +- /* +- * If this CPU has already been through a +- * rollover, but hasn't run another task in +- * the meantime, we must preserve its reserved +- * ASID, as this is the only trace we have of +- * the process it is still running. +- */ +- if (asid == 0) +- asid = per_cpu(reserved_asids, i); +- __set_bit(asid & ~ASID_MASK, asid_map); +- } ++ asid = atomic64_xchg(&per_cpu(active_asids, i), 0); ++ /* ++ * If this CPU has already been through a ++ * rollover, but hasn't run another task in ++ * the meantime, we must preserve its reserved ++ * ASID, as this is the only trace we have of ++ * the process it is still running. ++ */ ++ if (asid == 0) ++ asid = per_cpu(reserved_asids, i); ++ __set_bit(asid & ~ASID_MASK, asid_map); + per_cpu(reserved_asids, i) = asid; + } + +diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h +index c404fb0df3a6..64bc6c6efc6f 100644 +--- a/arch/arm64/include/asm/cputype.h ++++ b/arch/arm64/include/asm/cputype.h +@@ -77,6 +77,8 @@ static inline u32 __attribute_const__ read_cpuid_cachetype(void) + return read_cpuid(CTR_EL0); + } + ++void cpuinfo_store_cpu(void); ++ + #endif /* __ASSEMBLY__ */ + + #endif +diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c +index 071c3822442b..1e01d80a1165 100644 +--- a/arch/arm64/kernel/setup.c ++++ b/arch/arm64/kernel/setup.c +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -73,7 +74,6 @@ unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT; + #endif + + static const char *cpu_name; +-static const char *machine_name; + phys_addr_t __fdt_pointer __initdata; + + /* +@@ -193,6 +193,19 @@ static void __init smp_build_mpidr_hash(void) + } + #endif + ++struct cpuinfo_arm64 { ++ struct cpu cpu; ++ u32 reg_midr; ++}; ++ ++static DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data); ++ ++void cpuinfo_store_cpu(void) ++{ ++ struct cpuinfo_arm64 *info = this_cpu_ptr(&cpu_data); ++ info->reg_midr = read_cpuid_id(); ++} ++ + static void __init setup_processor(void) + { + struct cpu_info *cpu_info; +@@ -213,6 +226,8 @@ static void __init setup_processor(void) + sprintf(init_utsname()->machine, ELF_PLATFORM); + elf_hwcap = 0; + ++ cpuinfo_store_cpu(); ++ + /* + * ID_AA64ISAR0_EL1 contains 4-bit wide signed feature blocks. + * The blocks we test below represent incremental functionality +@@ -257,8 +272,6 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys) + while (true) + cpu_relax(); + } +- +- machine_name = of_flat_dt_get_machine_name(); + } + + /* +@@ -363,14 +376,12 @@ static int __init arm64_device_init(void) + } + arch_initcall(arm64_device_init); + +-static DEFINE_PER_CPU(struct cpu, cpu_data); +- + static int __init topology_init(void) + { + int i; + + for_each_possible_cpu(i) { +- struct cpu *cpu = &per_cpu(cpu_data, i); ++ struct cpu *cpu = &per_cpu(cpu_data.cpu, i); + cpu->hotpluggable = 1; + register_cpu(cpu, i); + } +@@ -391,14 +402,41 @@ static const char *hwcap_str[] = { + NULL + }; + ++#ifdef CONFIG_COMPAT ++static const char *compat_hwcap_str[] = { ++ "swp", ++ "half", ++ "thumb", ++ "26bit", ++ "fastmult", ++ "fpa", ++ "vfp", ++ "edsp", ++ "java", ++ "iwmmxt", ++ "crunch", ++ "thumbee", ++ "neon", ++ "vfpv3", ++ "vfpv3d16", ++ "tls", ++ "vfpv4", ++ "idiva", ++ "idivt", ++ "vfpd32", ++ "lpae", ++ "evtstrm" ++}; ++#endif /* CONFIG_COMPAT */ ++ + static int c_show(struct seq_file *m, void *v) + { +- int i; +- +- seq_printf(m, "Processor\t: %s rev %d (%s)\n", +- cpu_name, read_cpuid_id() & 15, ELF_PLATFORM); ++ int i, j; + + for_each_online_cpu(i) { ++ struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i); ++ u32 midr = cpuinfo->reg_midr; ++ + /* + * glibc reads /proc/cpuinfo to determine the number of + * online processors, looking for lines beginning with +@@ -407,24 +445,33 @@ static int c_show(struct seq_file *m, void *v) + #ifdef CONFIG_SMP + seq_printf(m, "processor\t: %d\n", i); + #endif +- } +- +- /* dump out the processor features */ +- seq_puts(m, "Features\t: "); +- +- for (i = 0; hwcap_str[i]; i++) +- if (elf_hwcap & (1 << i)) +- seq_printf(m, "%s ", hwcap_str[i]); + +- seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24); +- seq_printf(m, "CPU architecture: AArch64\n"); +- seq_printf(m, "CPU variant\t: 0x%x\n", (read_cpuid_id() >> 20) & 15); +- seq_printf(m, "CPU part\t: 0x%03x\n", (read_cpuid_id() >> 4) & 0xfff); +- seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15); +- +- seq_puts(m, "\n"); ++ /* ++ * Dump out the common processor features in a single line. ++ * Userspace should read the hwcaps with getauxval(AT_HWCAP) ++ * rather than attempting to parse this, but there's a body of ++ * software which does already (at least for 32-bit). ++ */ ++ seq_puts(m, "Features\t:"); ++ if (personality(current->personality) == PER_LINUX32) { ++#ifdef CONFIG_COMPAT ++ for (j = 0; compat_hwcap_str[j]; j++) ++ if (compat_elf_hwcap & (1 << j)) ++ seq_printf(m, " %s", compat_hwcap_str[j]); ++#endif /* CONFIG_COMPAT */ ++ } else { ++ for (j = 0; hwcap_str[j]; j++) ++ if (elf_hwcap & (1 << j)) ++ seq_printf(m, " %s", hwcap_str[j]); ++ } ++ seq_puts(m, "\n"); + +- seq_printf(m, "Hardware\t: %s\n", machine_name); ++ seq_printf(m, "CPU implementer\t: 0x%02x\n", (midr >> 24)); ++ seq_printf(m, "CPU architecture: 8\n"); ++ seq_printf(m, "CPU variant\t: 0x%x\n", ((midr >> 20) & 0xf)); ++ seq_printf(m, "CPU part\t: 0x%03x\n", ((midr >> 4) & 0xfff)); ++ seq_printf(m, "CPU revision\t: %d\n\n", (midr & 0xf)); ++ } + + return 0; + } +diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c +index 7cfb92a4ab66..7b9542b7bac2 100644 +--- a/arch/arm64/kernel/smp.c ++++ b/arch/arm64/kernel/smp.c +@@ -148,6 +148,11 @@ asmlinkage void secondary_start_kernel(void) + cpu_ops[cpu]->cpu_postboot(); + + /* ++ * Log the CPU info before it is marked online and might get read. ++ */ ++ cpuinfo_store_cpu(); ++ ++ /* + * Enable GIC and timers. + */ + notify_cpu_starting(cpu); +diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c +index 67a078ffc464..34467ac8220c 100644 +--- a/arch/mips/cavium-octeon/smp.c ++++ b/arch/mips/cavium-octeon/smp.c +@@ -263,9 +263,7 @@ static int octeon_cpu_disable(void) + + set_cpu_online(cpu, false); + cpu_clear(cpu, cpu_callin_map); +- local_irq_disable(); + octeon_fixup_irqs(); +- local_irq_enable(); + + flush_cache_all(); + local_flush_tlb_all(); +diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c +index e498f2b3646a..f5598e25e906 100644 +--- a/arch/mips/kernel/irq_cpu.c ++++ b/arch/mips/kernel/irq_cpu.c +@@ -56,6 +56,8 @@ static struct irq_chip mips_cpu_irq_controller = { + .irq_mask_ack = mask_mips_irq, + .irq_unmask = unmask_mips_irq, + .irq_eoi = unmask_mips_irq, ++ .irq_disable = mask_mips_irq, ++ .irq_enable = unmask_mips_irq, + }; + + /* +@@ -92,6 +94,8 @@ static struct irq_chip mips_mt_cpu_irq_controller = { + .irq_mask_ack = mips_mt_cpu_irq_ack, + .irq_unmask = unmask_mips_irq, + .irq_eoi = unmask_mips_irq, ++ .irq_disable = mask_mips_irq, ++ .irq_enable = unmask_mips_irq, + }; + + void __init mips_cpu_irq_init(void) +diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c +index 0a022ee33b2a..18ed11275052 100644 +--- a/arch/mips/kernel/smp.c ++++ b/arch/mips/kernel/smp.c +@@ -109,10 +109,10 @@ asmlinkage void start_secondary(void) + else + #endif /* CONFIG_MIPS_MT_SMTC */ + cpu_probe(); +- cpu_report(); + per_cpu_trap_init(false); + mips_clockevent_init(); + mp_ops->init_secondary(); ++ cpu_report(); + + /* + * XXX parity protection should be folded in here when it's converted +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index de426887b359..80c22a3ca688 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -441,6 +441,7 @@ struct vcpu_vmx { + #endif + int gs_ldt_reload_needed; + int fs_reload_needed; ++ unsigned long vmcs_host_cr4; /* May not match real cr4 */ + } host_state; + struct { + int vm86_active; +@@ -4165,11 +4166,16 @@ static void vmx_set_constant_host_state(struct vcpu_vmx *vmx) + u32 low32, high32; + unsigned long tmpl; + struct desc_ptr dt; ++ unsigned long cr4; + + vmcs_writel(HOST_CR0, read_cr0() & ~X86_CR0_TS); /* 22.2.3 */ +- vmcs_writel(HOST_CR4, read_cr4()); /* 22.2.3, 22.2.5 */ + vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */ + ++ /* Save the most likely value for this task's CR4 in the VMCS. */ ++ cr4 = read_cr4(); ++ vmcs_writel(HOST_CR4, cr4); /* 22.2.3, 22.2.5 */ ++ vmx->host_state.vmcs_host_cr4 = cr4; ++ + vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */ + #ifdef CONFIG_X86_64 + /* +@@ -7196,7 +7202,7 @@ static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx) + static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) + { + struct vcpu_vmx *vmx = to_vmx(vcpu); +- unsigned long debugctlmsr; ++ unsigned long debugctlmsr, cr4; + + /* Record the guest's net vcpu time for enforced NMI injections. */ + if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked)) +@@ -7217,6 +7223,12 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) + if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty)) + vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]); + ++ cr4 = read_cr4(); ++ if (unlikely(cr4 != vmx->host_state.vmcs_host_cr4)) { ++ vmcs_writel(HOST_CR4, cr4); ++ vmx->host_state.vmcs_host_cr4 = cr4; ++ } ++ + /* When single-stepping over STI and MOV SS, we must clear the + * corresponding interruptibility bits in the guest state. Otherwise + * vmentry fails as it then expects bit 14 (BS) in pending debug +diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c +index 981c2dbd72cc..88f143d9754e 100644 +--- a/arch/x86/pci/common.c ++++ b/arch/x86/pci/common.c +@@ -448,6 +448,22 @@ static const struct dmi_system_id pciprobe_dmi_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "ftServer"), + }, + }, ++ { ++ .callback = set_scan_all, ++ .ident = "Stratus/NEC ftServer", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "NEC"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Express5800/R32"), ++ }, ++ }, ++ { ++ .callback = set_scan_all, ++ .ident = "Stratus/NEC ftServer", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "NEC"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Express5800/R31"), ++ }, ++ }, + {} + }; + +diff --git a/crypto/crc32c.c b/crypto/crc32c.c +index 06f7018c9d95..238f0e627ef3 100644 +--- a/crypto/crc32c.c ++++ b/crypto/crc32c.c +@@ -170,3 +170,4 @@ module_exit(crc32c_mod_fini); + MODULE_AUTHOR("Clay Haapala "); + MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c"); + MODULE_LICENSE("GPL"); ++MODULE_ALIAS_CRYPTO("crc32c"); +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index ccbffd0d7a02..8f42bd724682 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -911,6 +911,7 @@ int gpiod_export_link(struct device *dev, const char *name, + if (tdev != NULL) { + status = sysfs_create_link(&dev->kobj, &tdev->kobj, + name); ++ put_device(tdev); + } else { + status = -ENODEV; + } +@@ -958,7 +959,7 @@ int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value) + } + + status = sysfs_set_active_low(desc, dev, value); +- ++ put_device(dev); + unlock: + mutex_unlock(&sysfs_lock); + +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index d375322b6cec..0218a9b23b38 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -366,6 +366,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) + struct cifsLockInfo *li, *tmp; + struct cifs_fid fid; + struct cifs_pending_open open; ++ bool oplock_break_cancelled; + + spin_lock(&cifs_file_list_lock); + if (--cifs_file->count > 0) { +@@ -397,7 +398,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) + } + spin_unlock(&cifs_file_list_lock); + +- cancel_work_sync(&cifs_file->oplock_break); ++ oplock_break_cancelled = cancel_work_sync(&cifs_file->oplock_break); + + if (!tcon->need_reconnect && !cifs_file->invalidHandle) { + struct TCP_Server_Info *server = tcon->ses->server; +@@ -409,6 +410,9 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) + _free_xid(xid); + } + ++ if (oplock_break_cancelled) ++ cifs_done_oplock_break(cifsi); ++ + cifs_del_pending_open(&open); + + /* +diff --git a/fs/ext4/file.c b/fs/ext4/file.c +index 2a8b2e15dcc4..589117e9e9be 100644 +--- a/fs/ext4/file.c ++++ b/fs/ext4/file.c +@@ -100,7 +100,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, + struct blk_plug plug; + int unaligned_aio = 0; + ssize_t ret; +- int overwrite = 0; ++ int *overwrite = iocb->private; + size_t length = iov_length(iov, nr_segs); + + if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) && +@@ -118,8 +118,6 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, + mutex_lock(&inode->i_mutex); + blk_start_plug(&plug); + +- iocb->private = &overwrite; +- + /* check whether we do a DIO overwrite or not */ + if (ext4_should_dioread_nolock(inode) && !unaligned_aio && + !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) { +@@ -143,7 +141,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, + * So we should check these two conditions. + */ + if (err == len && (map.m_flags & EXT4_MAP_MAPPED)) +- overwrite = 1; ++ *overwrite = 1; + } + + ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); +@@ -170,6 +168,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, + { + struct inode *inode = file_inode(iocb->ki_filp); + ssize_t ret; ++ int overwrite = 0; + + /* + * If we have encountered a bitmap-format file, the size limit +@@ -190,6 +189,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, + } + } + ++ iocb->private = &overwrite; + if (unlikely(iocb->ki_filp->f_flags & O_DIRECT)) + ret = ext4_file_dio_write(iocb, iov, nr_segs, pos); + else +diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h +index 9bc72dec3fa6..b02c202223a6 100644 +--- a/fs/nilfs2/nilfs.h ++++ b/fs/nilfs2/nilfs.h +@@ -141,7 +141,6 @@ enum { + * @ti_save: Backup of journal_info field of task_struct + * @ti_flags: Flags + * @ti_count: Nest level +- * @ti_garbage: List of inode to be put when releasing semaphore + */ + struct nilfs_transaction_info { + u32 ti_magic; +@@ -150,7 +149,6 @@ struct nilfs_transaction_info { + one of other filesystems has a bug. */ + unsigned short ti_flags; + unsigned short ti_count; +- struct list_head ti_garbage; + }; + + /* ti_magic */ +diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c +index a1a191634abc..5bee81674d53 100644 +--- a/fs/nilfs2/segment.c ++++ b/fs/nilfs2/segment.c +@@ -305,7 +305,6 @@ static void nilfs_transaction_lock(struct super_block *sb, + ti->ti_count = 0; + ti->ti_save = cur_ti; + ti->ti_magic = NILFS_TI_MAGIC; +- INIT_LIST_HEAD(&ti->ti_garbage); + current->journal_info = ti; + + for (;;) { +@@ -332,8 +331,6 @@ static void nilfs_transaction_unlock(struct super_block *sb) + + up_write(&nilfs->ns_segctor_sem); + current->journal_info = ti->ti_save; +- if (!list_empty(&ti->ti_garbage)) +- nilfs_dispose_list(nilfs, &ti->ti_garbage, 0); + } + + static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci, +@@ -746,6 +743,15 @@ static void nilfs_dispose_list(struct the_nilfs *nilfs, + } + } + ++static void nilfs_iput_work_func(struct work_struct *work) ++{ ++ struct nilfs_sc_info *sci = container_of(work, struct nilfs_sc_info, ++ sc_iput_work); ++ struct the_nilfs *nilfs = sci->sc_super->s_fs_info; ++ ++ nilfs_dispose_list(nilfs, &sci->sc_iput_queue, 0); ++} ++ + static int nilfs_test_metadata_dirty(struct the_nilfs *nilfs, + struct nilfs_root *root) + { +@@ -1899,8 +1905,8 @@ static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci, + static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, + struct the_nilfs *nilfs) + { +- struct nilfs_transaction_info *ti = current->journal_info; + struct nilfs_inode_info *ii, *n; ++ int defer_iput = false; + + spin_lock(&nilfs->ns_inode_lock); + list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) { +@@ -1911,9 +1917,24 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, + clear_bit(NILFS_I_BUSY, &ii->i_state); + brelse(ii->i_bh); + ii->i_bh = NULL; +- list_move_tail(&ii->i_dirty, &ti->ti_garbage); ++ list_del_init(&ii->i_dirty); ++ if (!ii->vfs_inode.i_nlink) { ++ /* ++ * Defer calling iput() to avoid a deadlock ++ * over I_SYNC flag for inodes with i_nlink == 0 ++ */ ++ list_add_tail(&ii->i_dirty, &sci->sc_iput_queue); ++ defer_iput = true; ++ } else { ++ spin_unlock(&nilfs->ns_inode_lock); ++ iput(&ii->vfs_inode); ++ spin_lock(&nilfs->ns_inode_lock); ++ } + } + spin_unlock(&nilfs->ns_inode_lock); ++ ++ if (defer_iput) ++ schedule_work(&sci->sc_iput_work); + } + + /* +@@ -2580,6 +2601,8 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb, + INIT_LIST_HEAD(&sci->sc_segbufs); + INIT_LIST_HEAD(&sci->sc_write_logs); + INIT_LIST_HEAD(&sci->sc_gc_inodes); ++ INIT_LIST_HEAD(&sci->sc_iput_queue); ++ INIT_WORK(&sci->sc_iput_work, nilfs_iput_work_func); + init_timer(&sci->sc_timer); + + sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT; +@@ -2606,6 +2629,8 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) + ret = nilfs_segctor_construct(sci, SC_LSEG_SR); + nilfs_transaction_unlock(sci->sc_super); + ++ flush_work(&sci->sc_iput_work); ++ + } while (ret && retrycount-- > 0); + } + +@@ -2630,6 +2655,9 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) + || sci->sc_seq_request != sci->sc_seq_done); + spin_unlock(&sci->sc_state_lock); + ++ if (flush_work(&sci->sc_iput_work)) ++ flag = true; ++ + if (flag || !nilfs_segctor_confirm(sci)) + nilfs_segctor_write_out(sci); + +@@ -2639,6 +2667,12 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) + nilfs_dispose_list(nilfs, &sci->sc_dirty_files, 1); + } + ++ if (!list_empty(&sci->sc_iput_queue)) { ++ nilfs_warning(sci->sc_super, __func__, ++ "iput queue is not empty\n"); ++ nilfs_dispose_list(nilfs, &sci->sc_iput_queue, 1); ++ } ++ + WARN_ON(!list_empty(&sci->sc_segbufs)); + WARN_ON(!list_empty(&sci->sc_write_logs)); + +diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h +index 38a1d0013314..a48d6de1e02c 100644 +--- a/fs/nilfs2/segment.h ++++ b/fs/nilfs2/segment.h +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include "nilfs.h" + +@@ -92,6 +93,8 @@ struct nilfs_segsum_pointer { + * @sc_nblk_inc: Block count of current generation + * @sc_dirty_files: List of files to be written + * @sc_gc_inodes: List of GC inodes having blocks to be written ++ * @sc_iput_queue: list of inodes for which iput should be done ++ * @sc_iput_work: work struct to defer iput call + * @sc_freesegs: array of segment numbers to be freed + * @sc_nfreesegs: number of segments on @sc_freesegs + * @sc_dsync_inode: inode whose data pages are written for a sync operation +@@ -135,6 +138,8 @@ struct nilfs_sc_info { + + struct list_head sc_dirty_files; + struct list_head sc_gc_inodes; ++ struct list_head sc_iput_queue; ++ struct work_struct sc_iput_work; + + __u64 *sc_freesegs; + size_t sc_nfreesegs; +diff --git a/include/sound/ak4113.h b/include/sound/ak4113.h +index 2609048c1d44..3a34f6edc2d1 100644 +--- a/include/sound/ak4113.h ++++ b/include/sound/ak4113.h +@@ -286,7 +286,7 @@ struct ak4113 { + ak4113_write_t *write; + ak4113_read_t *read; + void *private_data; +- unsigned int init:1; ++ atomic_t wq_processing; + spinlock_t lock; + unsigned char regmap[AK4113_WRITABLE_REGS]; + struct snd_kcontrol *kctls[AK4113_CONTROLS]; +diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h +index 52f02a60dba7..069299a88915 100644 +--- a/include/sound/ak4114.h ++++ b/include/sound/ak4114.h +@@ -168,7 +168,7 @@ struct ak4114 { + ak4114_write_t * write; + ak4114_read_t * read; + void * private_data; +- unsigned int init: 1; ++ atomic_t wq_processing; + spinlock_t lock; + unsigned char regmap[6]; + unsigned char txcsb[5]; +diff --git a/kernel/smpboot.c b/kernel/smpboot.c +index eb89e1807408..60d35ac5d3f1 100644 +--- a/kernel/smpboot.c ++++ b/kernel/smpboot.c +@@ -279,6 +279,7 @@ int smpboot_register_percpu_thread(struct smp_hotplug_thread *plug_thread) + unsigned int cpu; + int ret = 0; + ++ get_online_cpus(); + mutex_lock(&smpboot_threads_lock); + for_each_online_cpu(cpu) { + ret = __smpboot_create_thread(plug_thread, cpu); +@@ -291,6 +292,7 @@ int smpboot_register_percpu_thread(struct smp_hotplug_thread *plug_thread) + list_add(&plug_thread->list, &hotplug_threads); + out: + mutex_unlock(&smpboot_threads_lock); ++ put_online_cpus(); + return ret; + } + EXPORT_SYMBOL_GPL(smpboot_register_percpu_thread); +diff --git a/lib/checksum.c b/lib/checksum.c +index 129775eb6de6..8b39e86dbab5 100644 +--- a/lib/checksum.c ++++ b/lib/checksum.c +@@ -181,6 +181,15 @@ csum_partial_copy(const void *src, void *dst, int len, __wsum sum) + EXPORT_SYMBOL(csum_partial_copy); + + #ifndef csum_tcpudp_nofold ++static inline u32 from64to32(u64 x) ++{ ++ /* add up 32-bit and 32-bit for 32+c bit */ ++ x = (x & 0xffffffff) + (x >> 32); ++ /* add up carry.. */ ++ x = (x & 0xffffffff) + (x >> 32); ++ return (u32)x; ++} ++ + __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, + unsigned short len, + unsigned short proto, +@@ -195,8 +204,7 @@ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, + #else + s += (proto + len) << 8; + #endif +- s += (s >> 32); +- return (__force __wsum)s; ++ return (__force __wsum)from64to32(s); + } + EXPORT_SYMBOL(csum_tcpudp_nofold); + #endif +diff --git a/mm/pagewalk.c b/mm/pagewalk.c +index 2beeabf502c5..9056d22d2880 100644 +--- a/mm/pagewalk.c ++++ b/mm/pagewalk.c +@@ -199,7 +199,10 @@ int walk_page_range(unsigned long addr, unsigned long end, + */ + if ((vma->vm_start <= addr) && + (vma->vm_flags & VM_PFNMAP)) { +- next = vma->vm_end; ++ if (walk->pte_hole) ++ err = walk->pte_hole(addr, next, walk); ++ if (err) ++ break; + pgd = pgd_offset(walk->mm, next); + continue; + } +diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c +index db1512ae30cc..f53542b55de6 100644 +--- a/scripts/kconfig/menu.c ++++ b/scripts/kconfig/menu.c +@@ -545,7 +545,7 @@ static void get_prompt_str(struct gstr *r, struct property *prop, + { + int i, j; + struct menu *submenu[8], *menu, *location = NULL; +- struct jump_key *jump; ++ struct jump_key *jump = NULL; + + str_printf(r, _("Prompt: %s\n"), _(prop->text)); + menu = prop->menu->parent; +@@ -583,7 +583,7 @@ static void get_prompt_str(struct gstr *r, struct property *prop, + str_printf(r, _(" Location:\n")); + for (j = 4; --i >= 0; j += 2) { + menu = submenu[i]; +- if (head && location && menu == location) ++ if (jump && menu == location) + jump->offset = strlen(r->s); + str_printf(r, "%*c-> %s", j, ' ', + _(menu_get_prompt(menu))); +diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c +index e04e750a77ed..7a9149bb2a38 100644 +--- a/sound/i2c/other/ak4113.c ++++ b/sound/i2c/other/ak4113.c +@@ -56,8 +56,7 @@ static inline unsigned char reg_read(struct ak4113 *ak4113, unsigned char reg) + + static void snd_ak4113_free(struct ak4113 *chip) + { +- chip->init = 1; /* don't schedule new work */ +- mb(); ++ atomic_inc(&chip->wq_processing); /* don't schedule new work */ + cancel_delayed_work_sync(&chip->work); + kfree(chip); + } +@@ -89,6 +88,7 @@ int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read, + chip->write = write; + chip->private_data = private_data; + INIT_DELAYED_WORK(&chip->work, ak4113_stats); ++ atomic_set(&chip->wq_processing, 0); + + for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++) + chip->regmap[reg] = pgm[reg]; +@@ -139,13 +139,11 @@ static void ak4113_init_regs(struct ak4113 *chip) + + void snd_ak4113_reinit(struct ak4113 *chip) + { +- chip->init = 1; +- mb(); +- flush_delayed_work(&chip->work); ++ if (atomic_inc_return(&chip->wq_processing) == 1) ++ cancel_delayed_work_sync(&chip->work); + ak4113_init_regs(chip); + /* bring up statistics / event queing */ +- chip->init = 0; +- if (chip->kctls[0]) ++ if (atomic_dec_and_test(&chip->wq_processing)) + schedule_delayed_work(&chip->work, HZ / 10); + } + EXPORT_SYMBOL_GPL(snd_ak4113_reinit); +@@ -632,8 +630,9 @@ static void ak4113_stats(struct work_struct *work) + { + struct ak4113 *chip = container_of(work, struct ak4113, work.work); + +- if (!chip->init) ++ if (atomic_inc_return(&chip->wq_processing) == 1) + snd_ak4113_check_rate_and_errors(chip, chip->check_flags); + +- schedule_delayed_work(&chip->work, HZ / 10); ++ if (atomic_dec_and_test(&chip->wq_processing)) ++ schedule_delayed_work(&chip->work, HZ / 10); + } +diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c +index 15ae0250eace..bf515db7c2e1 100644 +--- a/sound/i2c/other/ak4114.c ++++ b/sound/i2c/other/ak4114.c +@@ -66,8 +66,7 @@ static void reg_dump(struct ak4114 *ak4114) + + static void snd_ak4114_free(struct ak4114 *chip) + { +- chip->init = 1; /* don't schedule new work */ +- mb(); ++ atomic_inc(&chip->wq_processing); /* don't schedule new work */ + cancel_delayed_work_sync(&chip->work); + kfree(chip); + } +@@ -100,6 +99,7 @@ int snd_ak4114_create(struct snd_card *card, + chip->write = write; + chip->private_data = private_data; + INIT_DELAYED_WORK(&chip->work, ak4114_stats); ++ atomic_set(&chip->wq_processing, 0); + + for (reg = 0; reg < 6; reg++) + chip->regmap[reg] = pgm[reg]; +@@ -152,13 +152,11 @@ static void ak4114_init_regs(struct ak4114 *chip) + + void snd_ak4114_reinit(struct ak4114 *chip) + { +- chip->init = 1; +- mb(); +- flush_delayed_work(&chip->work); ++ if (atomic_inc_return(&chip->wq_processing) == 1) ++ cancel_delayed_work_sync(&chip->work); + ak4114_init_regs(chip); + /* bring up statistics / event queing */ +- chip->init = 0; +- if (chip->kctls[0]) ++ if (atomic_dec_and_test(&chip->wq_processing)) + schedule_delayed_work(&chip->work, HZ / 10); + } + +@@ -612,10 +610,10 @@ static void ak4114_stats(struct work_struct *work) + { + struct ak4114 *chip = container_of(work, struct ak4114, work.work); + +- if (!chip->init) ++ if (atomic_inc_return(&chip->wq_processing) == 1) + snd_ak4114_check_rate_and_errors(chip, chip->check_flags); +- +- schedule_delayed_work(&chip->work, HZ / 10); ++ if (atomic_dec_and_test(&chip->wq_processing)) ++ schedule_delayed_work(&chip->work, HZ / 10); + } + + EXPORT_SYMBOL(snd_ak4114_create); +diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c +index 1ead3c977a51..f20e703b2a35 100644 +--- a/sound/soc/atmel/atmel_ssc_dai.c ++++ b/sound/soc/atmel/atmel_ssc_dai.c +@@ -344,7 +344,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, + struct atmel_pcm_dma_params *dma_params; + int dir, channels, bits; + u32 tfmr, rfmr, tcmr, rcmr; +- int start_event; + int ret; + + /* +@@ -451,19 +450,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, + * The SSC transmit clock is obtained from the BCLK signal on + * on the TK line, and the SSC receive clock is + * generated from the transmit clock. +- * +- * For single channel data, one sample is transferred +- * on the falling edge of the LRC clock. +- * For two channel data, one sample is +- * transferred on both edges of the LRC clock. + */ +- start_event = ((channels == 1) +- ? SSC_START_FALLING_RF +- : SSC_START_EDGE_RF); +- + rcmr = SSC_BF(RCMR_PERIOD, 0) + | SSC_BF(RCMR_STTDLY, START_DELAY) +- | SSC_BF(RCMR_START, start_event) ++ | SSC_BF(RCMR_START, SSC_START_FALLING_RF) + | SSC_BF(RCMR_CKI, SSC_CKI_RISING) + | SSC_BF(RCMR_CKO, SSC_CKO_NONE) + | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK); +@@ -471,14 +461,14 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, + rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) + | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) + | SSC_BF(RFMR_FSLEN, 0) +- | SSC_BF(RFMR_DATNB, 0) ++ | SSC_BF(RFMR_DATNB, (channels - 1)) + | SSC_BIT(RFMR_MSBF) + | SSC_BF(RFMR_LOOP, 0) + | SSC_BF(RFMR_DATLEN, (bits - 1)); + + tcmr = SSC_BF(TCMR_PERIOD, 0) + | SSC_BF(TCMR_STTDLY, START_DELAY) +- | SSC_BF(TCMR_START, start_event) ++ | SSC_BF(TCMR_START, SSC_START_FALLING_RF) + | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) + | SSC_BF(TCMR_CKO, SSC_CKO_NONE) + | SSC_BF(TCMR_CKS, SSC_CKS_PIN); +@@ -487,7 +477,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, + | SSC_BF(TFMR_FSDEN, 0) + | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) + | SSC_BF(TFMR_FSLEN, 0) +- | SSC_BF(TFMR_DATNB, 0) ++ | SSC_BF(TFMR_DATNB, (channels - 1)) + | SSC_BIT(TFMR_MSBF) + | SSC_BF(TFMR_DATDEF, 0) + | SSC_BF(TFMR_DATLEN, (bits - 1)); +diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c +index 12528e9ac4c2..715589ff0eda 100644 +--- a/sound/soc/codecs/sgtl5000.c ++++ b/sound/soc/codecs/sgtl5000.c +@@ -1521,6 +1521,9 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, + if (ret) + return ret; + ++ /* Need 8 clocks before I2C accesses */ ++ udelay(1); ++ + /* read chip information */ + ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, ®); + if (ret) diff --git a/patch/kernel/cubox-default/patch-3.14.33-34.patch b/patch/kernel/cubox-default/patch-3.14.33-34.patch new file mode 100644 index 000000000..6db62b2fc --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.33-34.patch @@ -0,0 +1,584 @@ +diff --git a/Makefile b/Makefile +index b0963ca2895d..54434817f2a4 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 33 ++SUBLEVEL = 34 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c +index ed2c8a1ed8ca..98893a8332c7 100644 +--- a/drivers/media/rc/ir-lirc-codec.c ++++ b/drivers/media/rc/ir-lirc-codec.c +@@ -42,11 +42,17 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) + return -EINVAL; + + /* Packet start */ +- if (ev.reset) +- return 0; ++ if (ev.reset) { ++ /* Userspace expects a long space event before the start of ++ * the signal to use as a sync. This may be done with repeat ++ * packets and normal samples. But if a reset has been sent ++ * then we assume that a long time has passed, so we send a ++ * space with the maximum time value. */ ++ sample = LIRC_SPACE(LIRC_VALUE_MASK); ++ IR_dprintk(2, "delivering reset sync space to lirc_dev\n"); + + /* Carrier reports */ +- if (ev.carrier_report) { ++ } else if (ev.carrier_report) { + sample = LIRC_FREQUENCY(ev.carrier); + IR_dprintk(2, "carrier report (freq: %d)\n", sample); + +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +index afa4a1f63270..a830d42e3d9b 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +@@ -3131,7 +3131,7 @@ static int bnx2x_poll(struct napi_struct *napi, int budget) + } + #endif + if (!bnx2x_fp_lock_napi(fp)) +- return work_done; ++ return budget; + + for_each_cos_in_tx_queue(fp, cos) + if (bnx2x_tx_queue_has_work(fp->txdata_ptr[cos])) +diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +index 70849dea32b1..5fa076fd439e 100644 +--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c ++++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +@@ -2390,7 +2390,10 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget) + + work_done = netxen_process_rcv_ring(sds_ring, budget); + +- if ((work_done < budget) && tx_complete) { ++ if (!tx_complete) ++ work_done = budget; ++ ++ if (work_done < budget) { + napi_complete(&sds_ring->napi); + if (test_bit(__NX_DEV_UP, &adapter->state)) + netxen_nic_enable_int(sds_ring); +diff --git a/drivers/net/ppp/ppp_deflate.c b/drivers/net/ppp/ppp_deflate.c +index 602c625d95d5..b5edc7f96a39 100644 +--- a/drivers/net/ppp/ppp_deflate.c ++++ b/drivers/net/ppp/ppp_deflate.c +@@ -246,7 +246,7 @@ static int z_compress(void *arg, unsigned char *rptr, unsigned char *obuf, + /* + * See if we managed to reduce the size of the packet. + */ +- if (olen < isize) { ++ if (olen < isize && olen <= osize) { + state->stats.comp_bytes += olen; + state->stats.comp_packets++; + } else { +diff --git a/include/net/ip.h b/include/net/ip.h +index 937f19681426..3446cdd29608 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -38,11 +38,12 @@ struct inet_skb_parm { + struct ip_options opt; /* Compiled IP options */ + unsigned char flags; + +-#define IPSKB_FORWARDED 1 +-#define IPSKB_XFRM_TUNNEL_SIZE 2 +-#define IPSKB_XFRM_TRANSFORMED 4 +-#define IPSKB_FRAG_COMPLETE 8 +-#define IPSKB_REROUTED 16 ++#define IPSKB_FORWARDED BIT(0) ++#define IPSKB_XFRM_TUNNEL_SIZE BIT(1) ++#define IPSKB_XFRM_TRANSFORMED BIT(2) ++#define IPSKB_FRAG_COMPLETE BIT(3) ++#define IPSKB_REROUTED BIT(4) ++#define IPSKB_DOREDIRECT BIT(5) + + u16 frag_max_size; + }; +@@ -174,7 +175,7 @@ static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg) + return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0; + } + +-void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, ++void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, + __be32 saddr, const struct ip_reply_arg *arg, + unsigned int len); + +diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h +index 80f500a29498..57c2da922952 100644 +--- a/include/net/netns/ipv4.h ++++ b/include/net/netns/ipv4.h +@@ -47,6 +47,7 @@ struct netns_ipv4 { + struct inet_peer_base *peers; + struct tcpm_hash_bucket *tcp_metrics_hash; + unsigned int tcp_metrics_hash_log; ++ struct sock * __percpu *tcp_sk; + struct netns_frags frags; + #ifdef CONFIG_NETFILTER + struct xt_table *iptable_filter; +diff --git a/net/core/dev.c b/net/core/dev.c +index 86bb9cc81f02..4ed77d7245c0 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -6812,10 +6812,20 @@ static int dev_cpu_callback(struct notifier_block *nfb, + oldsd->output_queue = NULL; + oldsd->output_queue_tailp = &oldsd->output_queue; + } +- /* Append NAPI poll list from offline CPU. */ +- if (!list_empty(&oldsd->poll_list)) { +- list_splice_init(&oldsd->poll_list, &sd->poll_list); +- raise_softirq_irqoff(NET_RX_SOFTIRQ); ++ /* Append NAPI poll list from offline CPU, with one exception : ++ * process_backlog() must be called by cpu owning percpu backlog. ++ * We properly handle process_queue & input_pkt_queue later. ++ */ ++ while (!list_empty(&oldsd->poll_list)) { ++ struct napi_struct *napi = list_first_entry(&oldsd->poll_list, ++ struct napi_struct, ++ poll_list); ++ ++ list_del_init(&napi->poll_list); ++ if (napi->poll == process_backlog) ++ napi->state = 0; ++ else ++ ____napi_schedule(sd, napi); + } + + raise_softirq_irqoff(NET_TX_SOFTIRQ); +@@ -6826,7 +6836,7 @@ static int dev_cpu_callback(struct notifier_block *nfb, + netif_rx_internal(skb); + input_queue_head_incr(oldsd); + } +- while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) { ++ while ((skb = skb_dequeue(&oldsd->input_pkt_queue))) { + netif_rx_internal(skb); + input_queue_head_incr(oldsd); + } +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 46175866851e..a6613ff972c1 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -2649,12 +2649,16 @@ static int rtnl_bridge_notify(struct net_device *dev, u16 flags) + goto errout; + } + ++ if (!skb->len) ++ goto errout; ++ + rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); + return 0; + errout: + WARN_ON(err == -EMSGSIZE); + kfree_skb(skb); +- rtnl_set_sk_err(net, RTNLGRP_LINK, err); ++ if (err) ++ rtnl_set_sk_err(net, RTNLGRP_LINK, err); + return err; + } + +diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c +index 1c6bd4359cbd..ecb34b5ea42f 100644 +--- a/net/ipv4/ip_forward.c ++++ b/net/ipv4/ip_forward.c +@@ -178,7 +178,8 @@ int ip_forward(struct sk_buff *skb) + * We now generate an ICMP HOST REDIRECT giving the route + * we calculated. + */ +- if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr && !skb_sec_path(skb)) ++ if (IPCB(skb)->flags & IPSKB_DOREDIRECT && !opt->srr && ++ !skb_sec_path(skb)) + ip_rt_send_redirect(skb); + + skb->priority = rt_tos2priority(iph->tos); +diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +index 844323b6cfb9..dd637fc4b553 100644 +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -1460,23 +1460,8 @@ static int ip_reply_glue_bits(void *dptr, char *to, int offset, + /* + * Generic function to send a packet as reply to another packet. + * Used to send some TCP resets/acks so far. +- * +- * Use a fake percpu inet socket to avoid false sharing and contention. + */ +-static DEFINE_PER_CPU(struct inet_sock, unicast_sock) = { +- .sk = { +- .__sk_common = { +- .skc_refcnt = ATOMIC_INIT(1), +- }, +- .sk_wmem_alloc = ATOMIC_INIT(1), +- .sk_allocation = GFP_ATOMIC, +- .sk_flags = (1UL << SOCK_USE_WRITE_QUEUE), +- }, +- .pmtudisc = IP_PMTUDISC_WANT, +- .uc_ttl = -1, +-}; +- +-void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, ++void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, + __be32 saddr, const struct ip_reply_arg *arg, + unsigned int len) + { +@@ -1484,9 +1469,8 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, + struct ipcm_cookie ipc; + struct flowi4 fl4; + struct rtable *rt = skb_rtable(skb); ++ struct net *net = sock_net(sk); + struct sk_buff *nskb; +- struct sock *sk; +- struct inet_sock *inet; + int err; + + if (ip_options_echo(&replyopts.opt.opt, skb)) +@@ -1516,15 +1500,11 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, + if (IS_ERR(rt)) + return; + +- inet = &get_cpu_var(unicast_sock); ++ inet_sk(sk)->tos = arg->tos; + +- inet->tos = arg->tos; +- sk = &inet->sk; + sk->sk_priority = skb->priority; + sk->sk_protocol = ip_hdr(skb)->protocol; + sk->sk_bound_dev_if = arg->bound_dev_if; +- sock_net_set(sk, net); +- __skb_queue_head_init(&sk->sk_write_queue); + sk->sk_sndbuf = sysctl_wmem_default; + err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, + len, 0, &ipc, &rt, MSG_DONTWAIT); +@@ -1540,13 +1520,10 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, + arg->csumoffset) = csum_fold(csum_add(nskb->csum, + arg->csum)); + nskb->ip_summed = CHECKSUM_NONE; +- skb_orphan(nskb); + skb_set_queue_mapping(nskb, skb_get_queue_mapping(skb)); + ip_push_pending_frames(sk, &fl4); + } + out: +- put_cpu_var(unicast_sock); +- + ip_rt_put(rt); + } + +diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c +index 580dd96666e0..135045e0e125 100644 +--- a/net/ipv4/ip_sockglue.c ++++ b/net/ipv4/ip_sockglue.c +@@ -426,15 +426,11 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) + + memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); + sin = &errhdr.offender; +- sin->sin_family = AF_UNSPEC; ++ memset(sin, 0, sizeof(*sin)); + if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP) { +- struct inet_sock *inet = inet_sk(sk); +- + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = ip_hdr(skb)->saddr; +- sin->sin_port = 0; +- memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); +- if (inet->cmsg_flags) ++ if (inet_sk(sk)->cmsg_flags) + ip_cmsg_recv(msg, skb); + } + +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index 0d33f947a87f..04ce671430cb 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -973,8 +973,11 @@ void ping_rcv(struct sk_buff *skb) + + sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); + if (sk != NULL) { ++ struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); ++ + pr_debug("rcv on socket %p\n", sk); +- ping_queue_rcv_skb(sk, skb_get(skb)); ++ if (skb2) ++ ping_queue_rcv_skb(sk, skb2); + sock_put(sk); + return; + } +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 487bb6252520..b64330f25fbe 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -1554,11 +1554,10 @@ static int __mkroute_input(struct sk_buff *skb, + + do_cache = res->fi && !itag; + if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) && ++ skb->protocol == htons(ETH_P_IP) && + (IN_DEV_SHARED_MEDIA(out_dev) || +- inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) { +- flags |= RTCF_DOREDIRECT; +- do_cache = false; +- } ++ inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) ++ IPCB(skb)->flags |= IPSKB_DOREDIRECT; + + if (skb->protocol != htons(ETH_P_IP)) { + /* Not IP (i.e. ARP). Do not create route, if it is +@@ -2305,6 +2304,8 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, + r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; + if (rt->rt_flags & RTCF_NOTIFY) + r->rtm_flags |= RTM_F_NOTIFY; ++ if (IPCB(skb)->flags & IPSKB_DOREDIRECT) ++ r->rtm_flags |= RTCF_DOREDIRECT; + + if (nla_put_be32(skb, RTA_DST, dst)) + goto nla_put_failure; +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index a782d5be132e..b7effad5a58c 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -691,7 +691,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) + + net = dev_net(skb_dst(skb)->dev); + arg.tos = ip_hdr(skb)->tos; +- ip_send_unicast_reply(net, skb, ip_hdr(skb)->saddr, ++ ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), ++ skb, ip_hdr(skb)->saddr, + ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len); + + TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); +@@ -774,7 +775,8 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, + if (oif) + arg.bound_dev_if = oif; + arg.tos = tos; +- ip_send_unicast_reply(net, skb, ip_hdr(skb)->saddr, ++ ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), ++ skb, ip_hdr(skb)->saddr, + ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len); + + TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); +@@ -2769,14 +2771,39 @@ struct proto tcp_prot = { + }; + EXPORT_SYMBOL(tcp_prot); + ++static void __net_exit tcp_sk_exit(struct net *net) ++{ ++ int cpu; ++ ++ for_each_possible_cpu(cpu) ++ inet_ctl_sock_destroy(*per_cpu_ptr(net->ipv4.tcp_sk, cpu)); ++ free_percpu(net->ipv4.tcp_sk); ++} ++ + static int __net_init tcp_sk_init(struct net *net) + { ++ int res, cpu; ++ ++ net->ipv4.tcp_sk = alloc_percpu(struct sock *); ++ if (!net->ipv4.tcp_sk) ++ return -ENOMEM; ++ ++ for_each_possible_cpu(cpu) { ++ struct sock *sk; ++ ++ res = inet_ctl_sock_create(&sk, PF_INET, SOCK_RAW, ++ IPPROTO_TCP, net); ++ if (res) ++ goto fail; ++ *per_cpu_ptr(net->ipv4.tcp_sk, cpu) = sk; ++ } + net->ipv4.sysctl_tcp_ecn = 2; + return 0; +-} + +-static void __net_exit tcp_sk_exit(struct net *net) +-{ ++fail: ++ tcp_sk_exit(net); ++ ++ return res; + } + + static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list) +diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c +index 7927db0a9279..4a000f1dd757 100644 +--- a/net/ipv4/udp_diag.c ++++ b/net/ipv4/udp_diag.c +@@ -99,11 +99,13 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlin + s_slot = cb->args[0]; + num = s_num = cb->args[1]; + +- for (slot = s_slot; slot <= table->mask; num = s_num = 0, slot++) { ++ for (slot = s_slot; slot <= table->mask; s_num = 0, slot++) { + struct sock *sk; + struct hlist_nulls_node *node; + struct udp_hslot *hslot = &table->hash[slot]; + ++ num = 0; ++ + if (hlist_nulls_empty(&hslot->head)) + continue; + +diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c +index c3bf2d2e519e..841cfa2c4600 100644 +--- a/net/ipv6/datagram.c ++++ b/net/ipv6/datagram.c +@@ -382,11 +382,10 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) + + memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); + sin = &errhdr.offender; +- sin->sin6_family = AF_UNSPEC; ++ memset(sin, 0, sizeof(*sin)); ++ + if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { + sin->sin6_family = AF_INET6; +- sin->sin6_flowinfo = 0; +- sin->sin6_port = 0; + if (np->rxopt.all) + ip6_datagram_recv_common_ctl(sk, msg, skb); + if (skb->protocol == htons(ETH_P_IPV6)) { +@@ -397,12 +396,9 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) + ipv6_iface_scope_id(&sin->sin6_addr, + IP6CB(skb)->iif); + } else { +- struct inet_sock *inet = inet_sk(sk); +- + ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, + &sin->sin6_addr); +- sin->sin6_scope_id = 0; +- if (inet->cmsg_flags) ++ if (inet_sk(sk)->cmsg_flags) + ip_cmsg_recv(msg, skb); + } + } +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index 1e55f5eba185..7daaeaf1bc1a 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -638,6 +638,29 @@ static inline bool rt6_qualify_for_ecmp(struct rt6_info *rt) + RTF_GATEWAY; + } + ++static void fib6_purge_rt(struct rt6_info *rt, struct fib6_node *fn, ++ struct net *net) ++{ ++ if (atomic_read(&rt->rt6i_ref) != 1) { ++ /* This route is used as dummy address holder in some split ++ * nodes. It is not leaked, but it still holds other resources, ++ * which must be released in time. So, scan ascendant nodes ++ * and replace dummy references to this route with references ++ * to still alive ones. ++ */ ++ while (fn) { ++ if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) { ++ fn->leaf = fib6_find_prefix(net, fn); ++ atomic_inc(&fn->leaf->rt6i_ref); ++ rt6_release(rt); ++ } ++ fn = fn->parent; ++ } ++ /* No more references are possible at this point. */ ++ BUG_ON(atomic_read(&rt->rt6i_ref) != 1); ++ } ++} ++ + /* + * Insert routing information in a node. + */ +@@ -775,11 +798,12 @@ add: + rt->dst.rt6_next = iter->dst.rt6_next; + atomic_inc(&rt->rt6i_ref); + inet6_rt_notify(RTM_NEWROUTE, rt, info); +- rt6_release(iter); + if (!(fn->fn_flags & RTN_RTINFO)) { + info->nl_net->ipv6.rt6_stats->fib_route_nodes++; + fn->fn_flags |= RTN_RTINFO; + } ++ fib6_purge_rt(iter, fn, info->nl_net); ++ rt6_release(iter); + } + + return 0; +@@ -1284,24 +1308,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, + fn = fib6_repair_tree(net, fn); + } + +- if (atomic_read(&rt->rt6i_ref) != 1) { +- /* This route is used as dummy address holder in some split +- * nodes. It is not leaked, but it still holds other resources, +- * which must be released in time. So, scan ascendant nodes +- * and replace dummy references to this route with references +- * to still alive ones. +- */ +- while (fn) { +- if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) { +- fn->leaf = fib6_find_prefix(net, fn); +- atomic_inc(&fn->leaf->rt6i_ref); +- rt6_release(rt); +- } +- fn = fn->parent; +- } +- /* No more references are possible at this point. */ +- BUG_ON(atomic_read(&rt->rt6i_ref) != 1); +- } ++ fib6_purge_rt(rt, fn, net); + + inet6_rt_notify(RTM_DELROUTE, rt, info); + rt6_release(rt); +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 7cc1102e298c..6f1b8503a431 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -1160,12 +1160,9 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, + struct net *net = dev_net(dst->dev); + + rt6->rt6i_flags |= RTF_MODIFIED; +- if (mtu < IPV6_MIN_MTU) { +- u32 features = dst_metric(dst, RTAX_FEATURES); ++ if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; +- features |= RTAX_FEATURE_ALLFRAG; +- dst_metric_set(dst, RTAX_FEATURES, features); +- } ++ + dst_metric_set(dst, RTAX_MTU, mtu); + rt6_update_expires(rt6, net->ipv6.sysctl.ip6_rt_mtu_expires); + } +diff --git a/net/sctp/associola.c b/net/sctp/associola.c +index d477d476714d..abc0922d0e31 100644 +--- a/net/sctp/associola.c ++++ b/net/sctp/associola.c +@@ -1235,7 +1235,6 @@ void sctp_assoc_update(struct sctp_association *asoc, + asoc->peer.peer_hmacs = new->peer.peer_hmacs; + new->peer.peer_hmacs = NULL; + +- sctp_auth_key_put(asoc->asoc_shared_key); + sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC); + } + +diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c +index 43abb643f3a1..df06b13a50f6 100644 +--- a/net/sctp/sm_make_chunk.c ++++ b/net/sctp/sm_make_chunk.c +@@ -2608,7 +2608,7 @@ do_addr_param: + + addr_param = param.v + sizeof(sctp_addip_param_t); + +- af = sctp_get_af_specific(param_type2af(param.p->type)); ++ af = sctp_get_af_specific(param_type2af(addr_param->p.type)); + if (af == NULL) + break; + +diff --git a/net/socket.c b/net/socket.c +index a19ae1968d37..1b2c2d62ff20 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -886,9 +886,6 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos, + static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, + struct sock_iocb *siocb) + { +- if (!is_sync_kiocb(iocb)) +- BUG(); +- + siocb->kiocb = iocb; + iocb->private = siocb; + return siocb; diff --git a/patch/kernel/cubox-default/patch-3.14.34-35.patch b/patch/kernel/cubox-default/patch-3.14.34-35.patch new file mode 100644 index 000000000..e8a6189a6 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.34-35.patch @@ -0,0 +1,2036 @@ +diff --git a/Makefile b/Makefile +index 54434817f2a4..9720e863c06f 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 34 ++SUBLEVEL = 35 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h +index 6b0b7f7ef783..7670f33b9ce2 100644 +--- a/arch/arc/include/asm/pgtable.h ++++ b/arch/arc/include/asm/pgtable.h +@@ -259,7 +259,8 @@ static inline void pmd_set(pmd_t *pmdp, pte_t *ptep) + #define pmd_clear(xp) do { pmd_val(*(xp)) = 0; } while (0) + + #define pte_page(x) (mem_map + \ +- (unsigned long)(((pte_val(x) - PAGE_OFFSET) >> PAGE_SHIFT))) ++ (unsigned long)(((pte_val(x) - CONFIG_LINUX_LINK_BASE) >> \ ++ PAGE_SHIFT))) + + #define mk_pte(page, pgprot) \ + ({ \ +diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi +index 2e7d932887b5..b3eff40188c6 100644 +--- a/arch/arm/boot/dts/am335x-bone-common.dtsi ++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi +@@ -197,6 +197,7 @@ + + usb@47401000 { + status = "okay"; ++ dr_mode = "peripheral"; + }; + + usb@47401800 { +diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi +index 48d2a7f4d0c0..ce978bc5b6d4 100644 +--- a/arch/arm/boot/dts/tegra20.dtsi ++++ b/arch/arm/boot/dts/tegra20.dtsi +@@ -76,9 +76,9 @@ + reset-names = "2d"; + }; + +- gr3d@54140000 { ++ gr3d@54180000 { + compatible = "nvidia,tegra20-gr3d"; +- reg = <0x54140000 0x00040000>; ++ reg = <0x54180000 0x00040000>; + clocks = <&tegra_car TEGRA20_CLK_GR3D>; + resets = <&tegra_car 24>; + reset-names = "3d"; +@@ -138,9 +138,9 @@ + status = "disabled"; + }; + +- dsi@542c0000 { ++ dsi@54300000 { + compatible = "nvidia,tegra20-dsi"; +- reg = <0x542c0000 0x00040000>; ++ reg = <0x54300000 0x00040000>; + clocks = <&tegra_car TEGRA20_CLK_DSI>; + resets = <&tegra_car 48>; + reset-names = "dsi"; +diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +index 2e35ff99f60e..d3ac4c634624 100644 +--- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c ++++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +@@ -1669,7 +1669,7 @@ static struct omap_hwmod dra7xx_uart3_hwmod = { + .class = &dra7xx_uart_hwmod_class, + .clkdm_name = "l4per_clkdm", + .main_clk = "uart3_gfclk_mux", +- .flags = HWMOD_SWSUP_SIDLE_ACT, ++ .flags = HWMOD_SWSUP_SIDLE_ACT | DEBUG_OMAP4UART3_FLAGS, + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_UART3_CLKCTRL_OFFSET, +diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c +index f162f1b77cd2..82fd9dd17ed1 100644 +--- a/arch/arm/mach-pxa/corgi.c ++++ b/arch/arm/mach-pxa/corgi.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -711,6 +712,8 @@ static void __init corgi_init(void) + sharpsl_nand_partitions[1].size = 53 * 1024 * 1024; + + platform_add_devices(devices, ARRAY_SIZE(devices)); ++ ++ regulator_has_full_constraints(); + } + + static void __init fixup_corgi(struct tag *tags, char **cmdline, +diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c +index a7c30eb0c8db..007fd8a237d9 100644 +--- a/arch/arm/mach-pxa/hx4700.c ++++ b/arch/arm/mach-pxa/hx4700.c +@@ -892,6 +892,8 @@ static void __init hx4700_init(void) + mdelay(10); + gpio_set_value(GPIO71_HX4700_ASIC3_nRESET, 1); + mdelay(10); ++ ++ regulator_has_full_constraints(); + } + + MACHINE_START(H4700, "HP iPAQ HX4700") +diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c +index aedf053a1de5..b4fff2998b8a 100644 +--- a/arch/arm/mach-pxa/poodle.c ++++ b/arch/arm/mach-pxa/poodle.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -454,6 +455,7 @@ static void __init poodle_init(void) + pxa_set_i2c_info(NULL); + i2c_register_board_info(0, ARRAY_AND_SIZE(poodle_i2c_devices)); + poodle_init_spi(); ++ regulator_has_full_constraints(); + } + + static void __init fixup_poodle(struct tag *tags, char **cmdline, +diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c +index 6645d1e31f14..34853d5dfda2 100644 +--- a/arch/arm/mach-sa1100/pm.c ++++ b/arch/arm/mach-sa1100/pm.c +@@ -81,6 +81,7 @@ static int sa11x0_pm_enter(suspend_state_t state) + /* + * Ensure not to come back here if it wasn't intended + */ ++ RCSR = RCSR_SMR; + PSPR = 0; + + /* +diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c +index b3fc9f5ec6d3..7ed72dc0fb0e 100644 +--- a/arch/arm64/kernel/signal32.c ++++ b/arch/arm64/kernel/signal32.c +@@ -151,8 +151,7 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) + case __SI_TIMER: + err |= __put_user(from->si_tid, &to->si_tid); + err |= __put_user(from->si_overrun, &to->si_overrun); +- err |= __put_user((compat_uptr_t)(unsigned long)from->si_ptr, +- &to->si_ptr); ++ err |= __put_user(from->si_int, &to->si_int); + break; + case __SI_POLL: + err |= __put_user(from->si_band, &to->si_band); +@@ -181,7 +180,7 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) + case __SI_MESGQ: /* But this is */ + err |= __put_user(from->si_pid, &to->si_pid); + err |= __put_user(from->si_uid, &to->si_uid); +- err |= __put_user((compat_uptr_t)(unsigned long)from->si_ptr, &to->si_ptr); ++ err |= __put_user(from->si_int, &to->si_int); + break; + default: /* this is just in case for now ... */ + err |= __put_user(from->si_pid, &to->si_pid); +diff --git a/arch/metag/include/asm/processor.h b/arch/metag/include/asm/processor.h +index a8a37477c66e..eb2005bd3c79 100644 +--- a/arch/metag/include/asm/processor.h ++++ b/arch/metag/include/asm/processor.h +@@ -149,8 +149,8 @@ extern void exit_thread(void); + + unsigned long get_wchan(struct task_struct *p); + +-#define KSTK_EIP(tsk) ((tsk)->thread.kernel_context->CurrPC) +-#define KSTK_ESP(tsk) ((tsk)->thread.kernel_context->AX[0].U0) ++#define KSTK_EIP(tsk) (task_pt_regs(tsk)->ctx.CurrPC) ++#define KSTK_ESP(tsk) (task_pt_regs(tsk)->ctx.AX[0].U0) + + #define user_stack_pointer(regs) ((regs)->ctx.AX[0].U0) + +diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c +index 6e58e97fcd39..cedeb5686eb5 100644 +--- a/arch/mips/kernel/mips_ksyms.c ++++ b/arch/mips/kernel/mips_ksyms.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + extern void *__bzero(void *__s, size_t __count); + extern long __strncpy_from_user_nocheck_asm(char *__to, +@@ -26,6 +27,13 @@ extern long __strnlen_user_nocheck_asm(const char *s); + extern long __strnlen_user_asm(const char *s); + + /* ++ * Core architecture code ++ */ ++#ifdef CONFIG_CPU_R4K_FPU ++EXPORT_SYMBOL_GPL(_save_fp); ++#endif ++ ++/* + * String functions + */ + EXPORT_SYMBOL(memset); +diff --git a/arch/mips/kvm/kvm_locore.S b/arch/mips/kvm/kvm_locore.S +index bbace092ad0a..03a2db58b22d 100644 +--- a/arch/mips/kvm/kvm_locore.S ++++ b/arch/mips/kvm/kvm_locore.S +@@ -428,7 +428,7 @@ __kvm_mips_return_to_guest: + /* Setup status register for running guest in UM */ + .set at + or v1, v1, (ST0_EXL | KSU_USER | ST0_IE) +- and v1, v1, ~ST0_CU0 ++ and v1, v1, ~(ST0_CU0 | ST0_MX) + .set noat + mtc0 v1, CP0_STATUS + ehb +diff --git a/arch/mips/kvm/kvm_mips.c b/arch/mips/kvm/kvm_mips.c +index 3e0ff8d0fbf9..897c605263f2 100644 +--- a/arch/mips/kvm/kvm_mips.c ++++ b/arch/mips/kvm/kvm_mips.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -418,11 +419,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) + vcpu->mmio_needed = 0; + } + ++ lose_fpu(1); ++ ++ local_irq_disable(); + /* Check if we have any exceptions/interrupts pending */ + kvm_mips_deliver_interrupts(vcpu, + kvm_read_c0_guest_cause(vcpu->arch.cop0)); + +- local_irq_disable(); + kvm_guest_enter(); + + r = __kvm_mips_vcpu_run(run, vcpu); +@@ -1021,9 +1024,6 @@ void kvm_mips_set_c0_status(void) + { + uint32_t status = read_c0_status(); + +- if (cpu_has_fpu) +- status |= (ST0_CU1); +- + if (cpu_has_dsp) + status |= (ST0_MX); + +diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c +index 47b6b9f81d43..830edc83c12a 100644 +--- a/arch/powerpc/sysdev/axonram.c ++++ b/arch/powerpc/sysdev/axonram.c +@@ -156,7 +156,7 @@ axon_ram_direct_access(struct block_device *device, sector_t sector, + } + + *kaddr = (void *)(bank->ph_addr + offset); +- *pfn = virt_to_phys(kaddr) >> PAGE_SHIFT; ++ *pfn = virt_to_phys(*kaddr) >> PAGE_SHIFT; + + return 0; + } +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index fab97ade0fc8..1777f89875fb 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -1207,21 +1207,22 @@ void kvm_track_tsc_matching(struct kvm_vcpu *vcpu) + { + #ifdef CONFIG_X86_64 + bool vcpus_matched; +- bool do_request = false; + struct kvm_arch *ka = &vcpu->kvm->arch; + struct pvclock_gtod_data *gtod = &pvclock_gtod_data; + + vcpus_matched = (ka->nr_vcpus_matched_tsc + 1 == + atomic_read(&vcpu->kvm->online_vcpus)); + +- if (vcpus_matched && gtod->clock.vclock_mode == VCLOCK_TSC) +- if (!ka->use_master_clock) +- do_request = 1; +- +- if (!vcpus_matched && ka->use_master_clock) +- do_request = 1; +- +- if (do_request) ++ /* ++ * Once the masterclock is enabled, always perform request in ++ * order to update it. ++ * ++ * In order to enable masterclock, the host clocksource must be TSC ++ * and the vcpus need to have matched TSCs. When that happens, ++ * perform request to enable masterclock. ++ */ ++ if (ka->use_master_clock || ++ (gtod->clock.vclock_mode == VCLOCK_TSC && vcpus_matched)) + kvm_make_request(KVM_REQ_MASTERCLOCK_UPDATE, vcpu); + + trace_kvm_track_tsc(vcpu->vcpu_id, ka->nr_vcpus_matched_tsc, +diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c +index 207d9aef662d..448ee8912d9b 100644 +--- a/arch/x86/mm/gup.c ++++ b/arch/x86/mm/gup.c +@@ -172,7 +172,7 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end, + */ + if (pmd_none(pmd) || pmd_trans_splitting(pmd)) + return 0; +- if (unlikely(pmd_large(pmd))) { ++ if (unlikely(pmd_large(pmd) || !pmd_present(pmd))) { + /* + * NUMA hinting faults need to be handled in the GUP + * slowpath for accounting purposes and so that they +diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c +index 8b977ebf9388..006cc914994b 100644 +--- a/arch/x86/mm/hugetlbpage.c ++++ b/arch/x86/mm/hugetlbpage.c +@@ -66,9 +66,15 @@ follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) + return ERR_PTR(-EINVAL); + } + ++/* ++ * pmd_huge() returns 1 if @pmd is hugetlb related entry, that is normal ++ * hugetlb entry or non-present (migration or hwpoisoned) hugetlb entry. ++ * Otherwise, returns 0. ++ */ + int pmd_huge(pmd_t pmd) + { +- return !!(pmd_val(pmd) & _PAGE_PSE); ++ return !pmd_none(pmd) && ++ (pmd_val(pmd) & (_PAGE_PRESENT|_PAGE_PSE)) != _PAGE_PRESENT; + } + + int pud_huge(pud_t pud) +diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c +index 25e7e1372bb2..3601ff284b92 100644 +--- a/arch/x86/mm/mmap.c ++++ b/arch/x86/mm/mmap.c +@@ -35,12 +35,12 @@ struct __read_mostly va_alignment va_align = { + .flags = -1, + }; + +-static unsigned int stack_maxrandom_size(void) ++static unsigned long stack_maxrandom_size(void) + { +- unsigned int max = 0; ++ unsigned long max = 0; + if ((current->flags & PF_RANDOMIZE) && + !(current->personality & ADDR_NO_RANDOMIZE)) { +- max = ((-1U) & STACK_RND_MASK) << PAGE_SHIFT; ++ max = ((-1UL) & STACK_RND_MASK) << PAGE_SHIFT; + } + + return max; +diff --git a/block/blk-throttle.c b/block/blk-throttle.c +index 1474c3ab7e72..15998784c00e 100644 +--- a/block/blk-throttle.c ++++ b/block/blk-throttle.c +@@ -1292,6 +1292,9 @@ static u64 tg_prfill_cpu_rwstat(struct seq_file *sf, + struct blkg_rwstat rwstat = { }, tmp; + int i, cpu; + ++ if (tg->stats_cpu == NULL) ++ return 0; ++ + for_each_possible_cpu(cpu) { + struct tg_stats_cpu *sc = per_cpu_ptr(tg->stats_cpu, cpu); + +diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c +index 91c25f261c91..d9bba9915420 100644 +--- a/block/cfq-iosched.c ++++ b/block/cfq-iosched.c +@@ -3585,6 +3585,11 @@ retry: + + blkcg = bio_blkcg(bio); + cfqg = cfq_lookup_create_cfqg(cfqd, blkcg); ++ if (!cfqg) { ++ cfqq = &cfqd->oom_cfqq; ++ goto out; ++ } ++ + cfqq = cic_to_cfqq(cic, is_sync); + + /* +@@ -3621,7 +3626,7 @@ retry: + } else + cfqq = &cfqd->oom_cfqq; + } +- ++out: + if (new_cfqq) + kmem_cache_free(cfq_pool, new_cfqq); + +@@ -3651,12 +3656,17 @@ static struct cfq_queue * + cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct cfq_io_cq *cic, + struct bio *bio, gfp_t gfp_mask) + { +- const int ioprio_class = IOPRIO_PRIO_CLASS(cic->ioprio); +- const int ioprio = IOPRIO_PRIO_DATA(cic->ioprio); ++ int ioprio_class = IOPRIO_PRIO_CLASS(cic->ioprio); ++ int ioprio = IOPRIO_PRIO_DATA(cic->ioprio); + struct cfq_queue **async_cfqq = NULL; + struct cfq_queue *cfqq = NULL; + + if (!is_sync) { ++ if (!ioprio_valid(cic->ioprio)) { ++ struct task_struct *tsk = current; ++ ioprio = task_nice_ioprio(tsk); ++ ioprio_class = task_nice_ioclass(tsk); ++ } + async_cfqq = cfq_async_queue_prio(cfqd, ioprio_class, ioprio); + cfqq = *async_cfqq; + } +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index b11949c5b029..f667e37394da 100644 +--- a/drivers/bluetooth/ath3k.c ++++ b/drivers/bluetooth/ath3k.c +@@ -157,6 +157,8 @@ static const struct usb_device_id ath3k_blist_tbl[] = { + #define USB_REQ_DFU_DNLOAD 1 + #define BULK_SIZE 4096 + #define FW_HDR_SIZE 20 ++#define TIMEGAP_USEC_MIN 50 ++#define TIMEGAP_USEC_MAX 100 + + static int ath3k_load_firmware(struct usb_device *udev, + const struct firmware *firmware) +@@ -187,6 +189,9 @@ static int ath3k_load_firmware(struct usb_device *udev, + count -= 20; + + while (count) { ++ /* workaround the compatibility issue with xHCI controller*/ ++ usleep_range(TIMEGAP_USEC_MIN, TIMEGAP_USEC_MAX); ++ + size = min_t(uint, count, BULK_SIZE); + pipe = usb_sndbulkpipe(udev, 0x02); + memcpy(send_buf, firmware->data + sent, size); +@@ -283,6 +288,9 @@ static int ath3k_load_fwfile(struct usb_device *udev, + count -= size; + + while (count) { ++ /* workaround the compatibility issue with xHCI controller*/ ++ usleep_range(TIMEGAP_USEC_MIN, TIMEGAP_USEC_MAX); ++ + size = min_t(uint, count, BULK_SIZE); + pipe = usb_sndbulkpipe(udev, 0x02); + +diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c +index 6af17002a115..cfb9089887bd 100644 +--- a/drivers/char/tpm/tpm-interface.c ++++ b/drivers/char/tpm/tpm-interface.c +@@ -1122,7 +1122,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, + + /* Make chip available */ + spin_lock(&driver_lock); +- list_add_rcu(&chip->list, &tpm_chip_list); ++ list_add_tail_rcu(&chip->list, &tpm_chip_list); + spin_unlock(&driver_lock); + + return chip; +diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c +index 77272925dee6..503a85ae176c 100644 +--- a/drivers/char/tpm/tpm_i2c_atmel.c ++++ b/drivers/char/tpm/tpm_i2c_atmel.c +@@ -168,6 +168,10 @@ static int i2c_atmel_probe(struct i2c_client *client, + + chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), + GFP_KERNEL); ++ if (!chip->vendor.priv) { ++ rc = -ENOMEM; ++ goto out_err; ++ } + + /* Default timeouts */ + chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); +diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c +index 7b158efd49f7..23c7b137a7fd 100644 +--- a/drivers/char/tpm/tpm_i2c_nuvoton.c ++++ b/drivers/char/tpm/tpm_i2c_nuvoton.c +@@ -538,6 +538,11 @@ static int i2c_nuvoton_probe(struct i2c_client *client, + + chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), + GFP_KERNEL); ++ if (!chip->vendor.priv) { ++ rc = -ENOMEM; ++ goto out_err; ++ } ++ + init_waitqueue_head(&chip->vendor.read_queue); + init_waitqueue_head(&chip->vendor.int_queue); + +diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c +index be9af2e6ca5a..576d1112ac57 100644 +--- a/drivers/char/tpm/tpm_i2c_stm_st33.c ++++ b/drivers/char/tpm/tpm_i2c_stm_st33.c +@@ -488,7 +488,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf, + if (burstcnt < 0) + return burstcnt; + size = min_t(int, len - i - 1, burstcnt); +- ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf, size); ++ ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf + i, size); + if (ret < 0) + goto out_err; + +diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c +index af74c57e5090..eff9d5870034 100644 +--- a/drivers/char/tpm/tpm_ibmvtpm.c ++++ b/drivers/char/tpm/tpm_ibmvtpm.c +@@ -148,7 +148,8 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) + crq.len = (u16)count; + crq.data = ibmvtpm->rtce_dma_handle; + +- rc = ibmvtpm_send_crq(ibmvtpm->vdev, word[0], word[1]); ++ rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(word[0]), ++ cpu_to_be64(word[1])); + if (rc != H_SUCCESS) { + dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc); + rc = 0; +@@ -186,7 +187,8 @@ static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm) + crq.valid = (u8)IBMVTPM_VALID_CMD; + crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE; + +- rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); ++ rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]), ++ cpu_to_be64(buf[1])); + if (rc != H_SUCCESS) + dev_err(ibmvtpm->dev, + "ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc); +@@ -212,7 +214,8 @@ static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm) + crq.valid = (u8)IBMVTPM_VALID_CMD; + crq.msg = (u8)VTPM_GET_VERSION; + +- rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); ++ rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]), ++ cpu_to_be64(buf[1])); + if (rc != H_SUCCESS) + dev_err(ibmvtpm->dev, + "ibmvtpm_crq_get_version failed rc=%d\n", rc); +@@ -307,6 +310,14 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev) + static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev) + { + struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev); ++ ++ /* ibmvtpm initializes at probe time, so the data we are ++ * asking for may not be set yet. Estimate that 4K required ++ * for TCE-mapped buffer in addition to CRQ. ++ */ ++ if (!ibmvtpm) ++ return CRQ_RES_BUF_SIZE + PAGE_SIZE; ++ + return CRQ_RES_BUF_SIZE + ibmvtpm->rtce_size; + } + +@@ -327,7 +338,8 @@ static int tpm_ibmvtpm_suspend(struct device *dev) + crq.valid = (u8)IBMVTPM_VALID_CMD; + crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND; + +- rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); ++ rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]), ++ cpu_to_be64(buf[1])); + if (rc != H_SUCCESS) + dev_err(ibmvtpm->dev, + "tpm_ibmvtpm_suspend failed rc=%d\n", rc); +@@ -472,11 +484,11 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, + case IBMVTPM_VALID_CMD: + switch (crq->msg) { + case VTPM_GET_RTCE_BUFFER_SIZE_RES: +- if (crq->len <= 0) { ++ if (be16_to_cpu(crq->len) <= 0) { + dev_err(ibmvtpm->dev, "Invalid rtce size\n"); + return; + } +- ibmvtpm->rtce_size = crq->len; ++ ibmvtpm->rtce_size = be16_to_cpu(crq->len); + ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size, + GFP_KERNEL); + if (!ibmvtpm->rtce_buf) { +@@ -497,11 +509,11 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, + + return; + case VTPM_GET_VERSION_RES: +- ibmvtpm->vtpm_version = crq->data; ++ ibmvtpm->vtpm_version = be32_to_cpu(crq->data); + return; + case VTPM_TPM_COMMAND_RES: + /* len of the data in rtce buffer */ +- ibmvtpm->res_len = crq->len; ++ ibmvtpm->res_len = be16_to_cpu(crq->len); + wake_up_interruptible(&ibmvtpm->wq); + return; + default: +diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c +index 2c46734b266d..51350cd0847e 100644 +--- a/drivers/char/tpm/tpm_tis.c ++++ b/drivers/char/tpm/tpm_tis.c +@@ -75,6 +75,10 @@ enum tis_defaults { + #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) + #define TPM_RID(l) (0x0F04 | ((l) << 12)) + ++struct priv_data { ++ bool irq_tested; ++}; ++ + static LIST_HEAD(tis_chips); + static DEFINE_MUTEX(tis_lock); + +@@ -338,12 +342,27 @@ out_err: + return rc; + } + ++static void disable_interrupts(struct tpm_chip *chip) ++{ ++ u32 intmask; ++ ++ intmask = ++ ioread32(chip->vendor.iobase + ++ TPM_INT_ENABLE(chip->vendor.locality)); ++ intmask &= ~TPM_GLOBAL_INT_ENABLE; ++ iowrite32(intmask, ++ chip->vendor.iobase + ++ TPM_INT_ENABLE(chip->vendor.locality)); ++ free_irq(chip->vendor.irq, chip); ++ chip->vendor.irq = 0; ++} ++ + /* + * If interrupts are used (signaled by an irq set in the vendor structure) + * tpm.c can skip polling for the data to be available as the interrupt is + * waited for here + */ +-static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) ++static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) + { + int rc; + u32 ordinal; +@@ -373,6 +392,30 @@ out_err: + return rc; + } + ++static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) ++{ ++ int rc, irq; ++ struct priv_data *priv = chip->vendor.priv; ++ ++ if (!chip->vendor.irq || priv->irq_tested) ++ return tpm_tis_send_main(chip, buf, len); ++ ++ /* Verify receipt of the expected IRQ */ ++ irq = chip->vendor.irq; ++ chip->vendor.irq = 0; ++ rc = tpm_tis_send_main(chip, buf, len); ++ chip->vendor.irq = irq; ++ if (!priv->irq_tested) ++ msleep(1); ++ if (!priv->irq_tested) { ++ disable_interrupts(chip); ++ dev_err(chip->dev, ++ FW_BUG "TPM interrupt not working, polling instead\n"); ++ } ++ priv->irq_tested = true; ++ return rc; ++} ++ + struct tis_vendor_timeout_override { + u32 did_vid; + unsigned long timeout_us[4]; +@@ -505,6 +548,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id) + if (interrupt == 0) + return IRQ_NONE; + ++ ((struct priv_data *)chip->vendor.priv)->irq_tested = true; + if (interrupt & TPM_INTF_DATA_AVAIL_INT) + wake_up_interruptible(&chip->vendor.read_queue); + if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) +@@ -534,9 +578,14 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, + u32 vendor, intfcaps, intmask; + int rc, i, irq_s, irq_e, probe; + struct tpm_chip *chip; ++ struct priv_data *priv; + ++ priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL); ++ if (priv == NULL) ++ return -ENOMEM; + if (!(chip = tpm_register_hardware(dev, &tpm_tis))) + return -ENODEV; ++ chip->vendor.priv = priv; + + chip->vendor.iobase = ioremap(start, len); + if (!chip->vendor.iobase) { +@@ -605,19 +654,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, + if (intfcaps & TPM_INTF_DATA_AVAIL_INT) + dev_dbg(dev, "\tData Avail Int Support\n"); + +- /* get the timeouts before testing for irqs */ +- if (tpm_get_timeouts(chip)) { +- dev_err(dev, "Could not get TPM timeouts and durations\n"); +- rc = -ENODEV; +- goto out_err; +- } +- +- if (tpm_do_selftest(chip)) { +- dev_err(dev, "TPM self test failed\n"); +- rc = -ENODEV; +- goto out_err; +- } +- + /* INTERRUPT Setup */ + init_waitqueue_head(&chip->vendor.read_queue); + init_waitqueue_head(&chip->vendor.int_queue); +@@ -719,6 +755,18 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, + } + } + ++ if (tpm_get_timeouts(chip)) { ++ dev_err(dev, "Could not get TPM timeouts and durations\n"); ++ rc = -ENODEV; ++ goto out_err; ++ } ++ ++ if (tpm_do_selftest(chip)) { ++ dev_err(dev, "TPM self test failed\n"); ++ rc = -ENODEV; ++ goto out_err; ++ } ++ + INIT_LIST_HEAD(&chip->vendor.list); + mutex_lock(&tis_lock); + list_add(&chip->vendor.list, &tis_chips); +diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c +index 4854f81d038b..ef3b8adb9d47 100644 +--- a/drivers/cpufreq/cpufreq.c ++++ b/drivers/cpufreq/cpufreq.c +@@ -1365,9 +1365,10 @@ static int __cpufreq_remove_dev_finish(struct device *dev, + unsigned long flags; + struct cpufreq_policy *policy; + +- read_lock_irqsave(&cpufreq_driver_lock, flags); ++ write_lock_irqsave(&cpufreq_driver_lock, flags); + policy = per_cpu(cpufreq_cpu_data, cpu); +- read_unlock_irqrestore(&cpufreq_driver_lock, flags); ++ per_cpu(cpufreq_cpu_data, cpu) = NULL; ++ write_unlock_irqrestore(&cpufreq_driver_lock, flags); + + if (!policy) { + pr_debug("%s: No cpu_data found\n", __func__); +@@ -1422,7 +1423,6 @@ static int __cpufreq_remove_dev_finish(struct device *dev, + } + } + +- per_cpu(cpufreq_cpu_data, cpu) = NULL; + return 0; + } + +diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c +index 826b8be23099..82cef00a27d9 100644 +--- a/drivers/cpufreq/s3c2416-cpufreq.c ++++ b/drivers/cpufreq/s3c2416-cpufreq.c +@@ -263,7 +263,7 @@ out: + } + + #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE +-static void __init s3c2416_cpufreq_cfg_regulator(struct s3c2416_data *s3c_freq) ++static void s3c2416_cpufreq_cfg_regulator(struct s3c2416_data *s3c_freq) + { + int count, v, i, found; + struct cpufreq_frequency_table *freq; +@@ -335,7 +335,7 @@ static struct notifier_block s3c2416_cpufreq_reboot_notifier = { + .notifier_call = s3c2416_cpufreq_reboot_notifier_evt, + }; + +-static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) ++static int s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) + { + struct s3c2416_data *s3c_freq = &s3c2416_cpufreq; + struct cpufreq_frequency_table *freq; +diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c +index 25069741b507..0eb5b405c2f0 100644 +--- a/drivers/cpufreq/s3c24xx-cpufreq.c ++++ b/drivers/cpufreq/s3c24xx-cpufreq.c +@@ -454,7 +454,7 @@ static struct cpufreq_driver s3c24xx_driver = { + }; + + +-int __init s3c_cpufreq_register(struct s3c_cpufreq_info *info) ++int s3c_cpufreq_register(struct s3c_cpufreq_info *info) + { + if (!info || !info->name) { + printk(KERN_ERR "%s: failed to pass valid information\n", +diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-lib.c +index 7047821a7f8a..4ab7a2156672 100644 +--- a/drivers/cpufreq/speedstep-lib.c ++++ b/drivers/cpufreq/speedstep-lib.c +@@ -400,6 +400,7 @@ unsigned int speedstep_get_freqs(enum speedstep_processor processor, + + pr_debug("previous speed is %u\n", prev_speed); + ++ preempt_disable(); + local_irq_save(flags); + + /* switch to low state */ +@@ -464,6 +465,8 @@ unsigned int speedstep_get_freqs(enum speedstep_processor processor, + + out: + local_irq_restore(flags); ++ preempt_enable(); ++ + return ret; + } + EXPORT_SYMBOL_GPL(speedstep_get_freqs); +diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c +index 998c17b42200..b52d8af1ab3c 100644 +--- a/drivers/cpufreq/speedstep-smi.c ++++ b/drivers/cpufreq/speedstep-smi.c +@@ -156,6 +156,7 @@ static void speedstep_set_state(unsigned int state) + return; + + /* Disable IRQs */ ++ preempt_disable(); + local_irq_save(flags); + + command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); +@@ -166,9 +167,19 @@ static void speedstep_set_state(unsigned int state) + + do { + if (retry) { ++ /* ++ * We need to enable interrupts, otherwise the blockage ++ * won't resolve. ++ * ++ * We disable preemption so that other processes don't ++ * run. If other processes were running, they could ++ * submit more DMA requests, making the blockage worse. ++ */ + pr_debug("retry %u, previous result %u, waiting...\n", + retry, result); ++ local_irq_enable(); + mdelay(retry * 50); ++ local_irq_disable(); + } + retry++; + __asm__ __volatile__( +@@ -185,6 +196,7 @@ static void speedstep_set_state(unsigned int state) + + /* enable IRQs */ + local_irq_restore(flags); ++ preempt_enable(); + + if (new_state == state) + pr_debug("change to %u MHz succeeded after %u tries " +diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c +index 98e14ee4833c..278603c373ca 100644 +--- a/drivers/edac/amd64_edac.c ++++ b/drivers/edac/amd64_edac.c +@@ -2006,14 +2006,20 @@ static void __log_bus_error(struct mem_ctl_info *mci, struct err_info *err, + + static inline void decode_bus_error(int node_id, struct mce *m) + { +- struct mem_ctl_info *mci = mcis[node_id]; +- struct amd64_pvt *pvt = mci->pvt_info; ++ struct mem_ctl_info *mci; ++ struct amd64_pvt *pvt; + u8 ecc_type = (m->status >> 45) & 0x3; + u8 xec = XEC(m->status, 0x1f); + u16 ec = EC(m->status); + u64 sys_addr; + struct err_info err; + ++ mci = edac_mc_find(node_id); ++ if (!mci) ++ return; ++ ++ pvt = mci->pvt_info; ++ + /* Bail out early if this was an 'observed' error */ + if (PP(ec) == NBSL_PP_OBS) + return; +diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c +index 59ee486cb8b9..6005d260457d 100644 +--- a/drivers/gpio/gpio-tps65912.c ++++ b/drivers/gpio/gpio-tps65912.c +@@ -26,9 +26,12 @@ struct tps65912_gpio_data { + struct gpio_chip gpio_chip; + }; + ++#define to_tgd(gc) container_of(gc, struct tps65912_gpio_data, gpio_chip) ++ + static int tps65912_gpio_get(struct gpio_chip *gc, unsigned offset) + { +- struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio); ++ struct tps65912_gpio_data *tps65912_gpio = to_tgd(gc); ++ struct tps65912 *tps65912 = tps65912_gpio->tps65912; + int val; + + val = tps65912_reg_read(tps65912, TPS65912_GPIO1 + offset); +@@ -42,7 +45,8 @@ static int tps65912_gpio_get(struct gpio_chip *gc, unsigned offset) + static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset, + int value) + { +- struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio); ++ struct tps65912_gpio_data *tps65912_gpio = to_tgd(gc); ++ struct tps65912 *tps65912 = tps65912_gpio->tps65912; + + if (value) + tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset, +@@ -55,7 +59,8 @@ static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset, + static int tps65912_gpio_output(struct gpio_chip *gc, unsigned offset, + int value) + { +- struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio); ++ struct tps65912_gpio_data *tps65912_gpio = to_tgd(gc); ++ struct tps65912 *tps65912 = tps65912_gpio->tps65912; + + /* Set the initial value */ + tps65912_gpio_set(gc, offset, value); +@@ -66,7 +71,8 @@ static int tps65912_gpio_output(struct gpio_chip *gc, unsigned offset, + + static int tps65912_gpio_input(struct gpio_chip *gc, unsigned offset) + { +- struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio); ++ struct tps65912_gpio_data *tps65912_gpio = to_tgd(gc); ++ struct tps65912 *tps65912 = tps65912_gpio->tps65912; + + return tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset, + GPIO_CFG_MASK); +diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c +index 74ed17d6cfa1..d26028cb9eac 100644 +--- a/drivers/gpio/gpiolib-of.c ++++ b/drivers/gpio/gpiolib-of.c +@@ -45,12 +45,13 @@ static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data) + + ret = gc->of_xlate(gc, &gg_data->gpiospec, gg_data->flags); + if (ret < 0) { +- /* We've found the gpio chip, but the translation failed. +- * Return true to stop looking and return the translation +- * error via out_gpio ++ /* We've found a gpio chip, but the translation failed. ++ * Store translation error in out_gpio. ++ * Return false to keep looking, as more than one gpio chip ++ * could be registered per of-node. + */ + gg_data->out_gpio = ERR_PTR(ret); +- return true; ++ return false; + } + + gg_data->out_gpio = gpio_to_desc(ret + gc->base); +diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c +index 6e5d8fe0ce8f..17be889d8a83 100644 +--- a/drivers/hid/i2c-hid/i2c-hid.c ++++ b/drivers/hid/i2c-hid/i2c-hid.c +@@ -356,7 +356,10 @@ static int i2c_hid_hwreset(struct i2c_client *client) + static void i2c_hid_get_input(struct i2c_hid *ihid) + { + int ret, ret_size; +- int size = ihid->bufsize; ++ int size = le16_to_cpu(ihid->hdesc.wMaxInputLength); ++ ++ if (size > ihid->bufsize) ++ size = ihid->bufsize; + + ret = i2c_master_recv(ihid->client, ihid->inbuf, size); + if (ret != size) { +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 55de4f6f7eaf..b96ee9d78aa3 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -561,7 +561,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect + if (test_bit(WriteMostly, &rdev->flags)) { + /* Don't balance among write-mostly, just + * use the first as a last resort */ +- if (best_disk < 0) { ++ if (best_dist_disk < 0) { + if (is_badblock(rdev, this_sector, sectors, + &first_bad, &bad_sectors)) { + if (first_bad < this_sector) +@@ -570,7 +570,8 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect + best_good_sectors = first_bad - this_sector; + } else + best_good_sectors = sectors; +- best_disk = disk; ++ best_dist_disk = disk; ++ best_pending_disk = disk; + } + continue; + } +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 175584ad643f..3545fafe2027 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -3071,7 +3071,8 @@ static void handle_stripe_dirtying(struct r5conf *conf, + * generate correct data from the parity. + */ + if (conf->max_degraded == 2 || +- (recovery_cp < MaxSector && sh->sector >= recovery_cp)) { ++ (recovery_cp < MaxSector && sh->sector >= recovery_cp && ++ s->failed == 0)) { + /* Calculate the real rcw later - for now make it + * look like rcw is cheaper + */ +diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c +index f674dc024d06..d2a4e6d40bf0 100644 +--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c ++++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c +@@ -350,6 +350,7 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap) + { + struct dvb_usb_device *d = adap_to_d(adap); + struct lme2510_state *lme_int = adap_to_priv(adap); ++ struct usb_host_endpoint *ep; + + lme_int->lme_urb = usb_alloc_urb(0, GFP_ATOMIC); + +@@ -371,6 +372,12 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap) + adap, + 8); + ++ /* Quirk of pipe reporting PIPE_BULK but behaves as interrupt */ ++ ep = usb_pipe_endpoint(d->udev, lme_int->lme_urb->pipe); ++ ++ if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK) ++ lme_int->lme_urb->pipe = usb_rcvbulkpipe(d->udev, 0xa), ++ + lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + usb_submit_urb(lme_int->lme_urb, GFP_ATOMIC); +diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c +index dfdfa772eb1e..c39f7d329ee2 100644 +--- a/drivers/media/usb/em28xx/em28xx-audio.c ++++ b/drivers/media/usb/em28xx/em28xx-audio.c +@@ -814,7 +814,7 @@ static int em28xx_audio_urb_init(struct em28xx *dev) + if (urb_size > ep_size * npackets) + npackets = DIV_ROUND_UP(urb_size, ep_size); + +- em28xx_info("Number of URBs: %d, with %d packets and %d size", ++ em28xx_info("Number of URBs: %d, with %d packets and %d size\n", + num_urb, npackets, urb_size); + + /* Estimate the bytes per period */ +@@ -974,7 +974,7 @@ static int em28xx_audio_fini(struct em28xx *dev) + return 0; + } + +- em28xx_info("Closing audio extension"); ++ em28xx_info("Closing audio extension\n"); + + if (dev->adev.sndcard) { + snd_card_disconnect(dev->adev.sndcard); +diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c +index 1373cfa4e974..ec2ebe9b89fb 100644 +--- a/drivers/media/usb/em28xx/em28xx-dvb.c ++++ b/drivers/media/usb/em28xx/em28xx-dvb.c +@@ -1468,7 +1468,7 @@ static int em28xx_dvb_fini(struct em28xx *dev) + return 0; + } + +- em28xx_info("Closing DVB extension"); ++ em28xx_info("Closing DVB extension\n"); + + if (dev->dvb) { + struct em28xx_dvb *dvb = dev->dvb; +diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c +index 18f65d89d4bc..dd59c005cbcc 100644 +--- a/drivers/media/usb/em28xx/em28xx-input.c ++++ b/drivers/media/usb/em28xx/em28xx-input.c +@@ -810,7 +810,7 @@ static int em28xx_ir_fini(struct em28xx *dev) + return 0; + } + +- em28xx_info("Closing input extension"); ++ em28xx_info("Closing input extension\n"); + + em28xx_shutdown_buttons(dev); + +diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c +index e24ee08e634e..0e8d0856b89a 100644 +--- a/drivers/media/usb/em28xx/em28xx-video.c ++++ b/drivers/media/usb/em28xx/em28xx-video.c +@@ -1900,7 +1900,7 @@ static int em28xx_v4l2_fini(struct em28xx *dev) + return 0; + } + +- em28xx_info("Closing video extension"); ++ em28xx_info("Closing video extension\n"); + + mutex_lock(&dev->lock); + +diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c +index 793dacd3b841..561c6b4907a1 100644 +--- a/drivers/mmc/host/sdhci-pxav3.c ++++ b/drivers/mmc/host/sdhci-pxav3.c +@@ -201,8 +201,8 @@ static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev) + if (!pdata) + return NULL; + +- of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles); +- if (clk_delay_cycles > 0) ++ if (!of_property_read_u32(np, "mrvl,clk-delay-cycles", ++ &clk_delay_cycles)) + pdata->clk_delay_cycles = clk_delay_cycles; + + return pdata; +diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c +index d06414ef15c5..a04174607e97 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c +@@ -410,9 +410,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, + mvmvif->uploaded = false; + mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; + +- /* does this make sense at all? */ +- mvmvif->color++; +- + spin_lock_bh(&mvm->time_event_lock); + iwl_mvm_te_clear_data(mvm, &mvmvif->time_event_data); + spin_unlock_bh(&mvm->time_event_lock); +@@ -597,7 +594,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, + + ret = iwl_mvm_mac_ctxt_add(mvm, vif); + if (ret) +- goto out_release; ++ goto out_remove_mac; + + iwl_mvm_power_disable(mvm, vif); + +diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c +index 76ee486039d7..4efcb2869379 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/tx.c ++++ b/drivers/net/wireless/iwlwifi/mvm/tx.c +@@ -835,6 +835,11 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, + sta_id = ba_notif->sta_id; + tid = ba_notif->tid; + ++ if (WARN_ONCE(sta_id >= IWL_MVM_STATION_COUNT || ++ tid >= IWL_MAX_TID_COUNT, ++ "sta_id %d tid %d", sta_id, tid)) ++ return 0; ++ + rcu_read_lock(); + + sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); +diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c +index 3d549008b3e2..52427fba22cd 100644 +--- a/drivers/net/wireless/iwlwifi/pcie/tx.c ++++ b/drivers/net/wireless/iwlwifi/pcie/tx.c +@@ -729,7 +729,12 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans) + iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, + trans_pcie->kw.dma >> 4); + +- iwl_pcie_tx_start(trans, trans_pcie->scd_base_addr); ++ /* ++ * Send 0 as the scd_base_addr since the device may have be reset ++ * while we were in WoWLAN in which case SCD_SRAM_BASE_ADDR will ++ * contain garbage. ++ */ ++ iwl_pcie_tx_start(trans, 0); + } + + /* +diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c +index 25f0bc659164..7f4155116cc9 100644 +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -1324,7 +1324,7 @@ static int pci_uevent(struct device *dev, struct kobj_uevent_env *env) + if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev))) + return -ENOMEM; + +- if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x", ++ if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02X", + pdev->vendor, pdev->device, + pdev->subsystem_vendor, pdev->subsystem_device, + (u8)(pdev->class >> 16), (u8)(pdev->class >> 8), +diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c +index 5d595724e5f4..5510c88b5044 100644 +--- a/drivers/pci/rom.c ++++ b/drivers/pci/rom.c +@@ -69,6 +69,7 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size) + { + void __iomem *image; + int last_image; ++ unsigned length; + + image = rom; + do { +@@ -91,9 +92,9 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size) + if (readb(pds + 3) != 'R') + break; + last_image = readb(pds + 21) & 0x80; +- /* this length is reliable */ +- image += readw(pds + 16) * 512; +- } while (!last_image); ++ length = readw(pds + 16); ++ image += length * 512; ++ } while (length && !last_image); + + /* never return a size larger than the PCI resource window */ + /* there are known ROMs that get the size wrong */ +diff --git a/drivers/power/88pm860x_charger.c b/drivers/power/88pm860x_charger.c +index de029bbc1cc1..5ccca8743ce6 100644 +--- a/drivers/power/88pm860x_charger.c ++++ b/drivers/power/88pm860x_charger.c +@@ -711,6 +711,7 @@ static int pm860x_charger_probe(struct platform_device *pdev) + return 0; + + out_irq: ++ power_supply_unregister(&info->usb); + while (--i >= 0) + free_irq(info->irq[i], info); + out: +diff --git a/drivers/power/bq24190_charger.c b/drivers/power/bq24190_charger.c +index ad3ff8fbfbbb..e4c95e1a6733 100644 +--- a/drivers/power/bq24190_charger.c ++++ b/drivers/power/bq24190_charger.c +@@ -929,7 +929,7 @@ static void bq24190_charger_init(struct power_supply *charger) + charger->properties = bq24190_charger_properties; + charger->num_properties = ARRAY_SIZE(bq24190_charger_properties); + charger->supplied_to = bq24190_charger_supplied_to; +- charger->num_supplies = ARRAY_SIZE(bq24190_charger_supplied_to); ++ charger->num_supplicants = ARRAY_SIZE(bq24190_charger_supplied_to); + charger->get_property = bq24190_charger_get_property; + charger->set_property = bq24190_charger_set_property; + charger->property_is_writeable = bq24190_charger_property_is_writeable; +diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c +index a0024b252197..86e03c6d28f3 100644 +--- a/drivers/power/gpio-charger.c ++++ b/drivers/power/gpio-charger.c +@@ -168,7 +168,7 @@ static int gpio_charger_suspend(struct device *dev) + + if (device_may_wakeup(dev)) + gpio_charger->wakeup_enabled = +- enable_irq_wake(gpio_charger->irq); ++ !enable_irq_wake(gpio_charger->irq); + + return 0; + } +@@ -178,7 +178,7 @@ static int gpio_charger_resume(struct device *dev) + struct platform_device *pdev = to_platform_device(dev); + struct gpio_charger *gpio_charger = platform_get_drvdata(pdev); + +- if (gpio_charger->wakeup_enabled) ++ if (device_may_wakeup(dev) && gpio_charger->wakeup_enabled) + disable_irq_wake(gpio_charger->irq); + power_supply_changed(&gpio_charger->charger); + +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c +index f6555921fd7a..a1f04e3b2a8f 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c +@@ -92,6 +92,8 @@ megasas_enable_intr_fusion(struct megasas_instance *instance) + { + struct megasas_register_set __iomem *regs; + regs = instance->reg_set; ++ ++ instance->mask_interrupts = 0; + /* For Thunderbolt/Invader also clear intr on enable */ + writel(~0, ®s->outbound_intr_status); + readl(®s->outbound_intr_status); +@@ -100,7 +102,6 @@ megasas_enable_intr_fusion(struct megasas_instance *instance) + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +- instance->mask_interrupts = 0; + } + + /** +diff --git a/drivers/target/iscsi/iscsi_target_tq.c b/drivers/target/iscsi/iscsi_target_tq.c +index 601e9cc61e98..bb2890e79ca0 100644 +--- a/drivers/target/iscsi/iscsi_target_tq.c ++++ b/drivers/target/iscsi/iscsi_target_tq.c +@@ -24,36 +24,22 @@ + #include "iscsi_target_tq.h" + #include "iscsi_target.h" + +-static LIST_HEAD(active_ts_list); + static LIST_HEAD(inactive_ts_list); +-static DEFINE_SPINLOCK(active_ts_lock); + static DEFINE_SPINLOCK(inactive_ts_lock); + static DEFINE_SPINLOCK(ts_bitmap_lock); + +-static void iscsi_add_ts_to_active_list(struct iscsi_thread_set *ts) +-{ +- spin_lock(&active_ts_lock); +- list_add_tail(&ts->ts_list, &active_ts_list); +- iscsit_global->active_ts++; +- spin_unlock(&active_ts_lock); +-} +- + static void iscsi_add_ts_to_inactive_list(struct iscsi_thread_set *ts) + { ++ if (!list_empty(&ts->ts_list)) { ++ WARN_ON(1); ++ return; ++ } + spin_lock(&inactive_ts_lock); + list_add_tail(&ts->ts_list, &inactive_ts_list); + iscsit_global->inactive_ts++; + spin_unlock(&inactive_ts_lock); + } + +-static void iscsi_del_ts_from_active_list(struct iscsi_thread_set *ts) +-{ +- spin_lock(&active_ts_lock); +- list_del(&ts->ts_list); +- iscsit_global->active_ts--; +- spin_unlock(&active_ts_lock); +-} +- + static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void) + { + struct iscsi_thread_set *ts; +@@ -66,7 +52,7 @@ static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void) + + ts = list_first_entry(&inactive_ts_list, struct iscsi_thread_set, ts_list); + +- list_del(&ts->ts_list); ++ list_del_init(&ts->ts_list); + iscsit_global->inactive_ts--; + spin_unlock(&inactive_ts_lock); + +@@ -204,8 +190,6 @@ static void iscsi_deallocate_extra_thread_sets(void) + + void iscsi_activate_thread_set(struct iscsi_conn *conn, struct iscsi_thread_set *ts) + { +- iscsi_add_ts_to_active_list(ts); +- + spin_lock_bh(&ts->ts_state_lock); + conn->thread_set = ts; + ts->conn = conn; +@@ -397,7 +381,6 @@ struct iscsi_conn *iscsi_rx_thread_pre_handler(struct iscsi_thread_set *ts) + + if (ts->delay_inactive && (--ts->thread_count == 0)) { + spin_unlock_bh(&ts->ts_state_lock); +- iscsi_del_ts_from_active_list(ts); + + if (!iscsit_global->in_shutdown) + iscsi_deallocate_extra_thread_sets(); +@@ -452,7 +435,6 @@ struct iscsi_conn *iscsi_tx_thread_pre_handler(struct iscsi_thread_set *ts) + + if (ts->delay_inactive && (--ts->thread_count == 0)) { + spin_unlock_bh(&ts->ts_state_lock); +- iscsi_del_ts_from_active_list(ts); + + if (!iscsit_global->in_shutdown) + iscsi_deallocate_extra_thread_sets(); +diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c +index 25c9bc783722..e49616eeb1cc 100644 +--- a/drivers/tty/pty.c ++++ b/drivers/tty/pty.c +@@ -209,6 +209,9 @@ static int pty_signal(struct tty_struct *tty, int sig) + unsigned long flags; + struct pid *pgrp; + ++ if (sig != SIGINT && sig != SIGQUIT && sig != SIGTSTP) ++ return -EINVAL; ++ + if (tty->link) { + spin_lock_irqsave(&tty->link->ctrl_lock, flags); + pgrp = get_pid(tty->link->pgrp); +diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c +index ce352b81e230..0d3e6cb36748 100644 +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -2392,7 +2392,7 @@ static int atmel_serial_probe(struct platform_device *pdev) + + ret = atmel_init_port(port, pdev); + if (ret) +- goto err; ++ goto err_clear_bit; + + if (!atmel_use_pdc_rx(&port->uart)) { + ret = -ENOMEM; +@@ -2441,6 +2441,8 @@ err_alloc_ring: + clk_put(port->clk); + port->clk = NULL; + } ++err_clear_bit: ++ clear_bit(port->uart.line, atmel_ports_in_use); + err: + return ret; + } +diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c +index 23b5d32954bf..693091ab726b 100644 +--- a/drivers/tty/vt/vt.c ++++ b/drivers/tty/vt/vt.c +@@ -498,6 +498,7 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed) + #endif + if (DO_UPDATE(vc)) + do_update_region(vc, (unsigned long) p, count); ++ notify_update(vc); + } + + /* used by selection: complement pointer position */ +@@ -514,6 +515,7 @@ void complement_pos(struct vc_data *vc, int offset) + scr_writew(old, screenpos(vc, old_offset, 1)); + if (DO_UPDATE(vc)) + vc->vc_sw->con_putc(vc, old, oldy, oldx); ++ notify_update(vc); + } + + old_offset = offset; +@@ -531,8 +533,8 @@ void complement_pos(struct vc_data *vc, int offset) + oldy = (offset >> 1) / vc->vc_cols; + vc->vc_sw->con_putc(vc, new, oldy, oldx); + } ++ notify_update(vc); + } +- + } + + static void insert_char(struct vc_data *vc, unsigned int nr) +diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c +index 684ef70dc09d..506b969ea7fd 100644 +--- a/drivers/usb/core/buffer.c ++++ b/drivers/usb/core/buffer.c +@@ -22,17 +22,25 @@ + */ + + /* FIXME tune these based on pool statistics ... */ +-static const size_t pool_max[HCD_BUFFER_POOLS] = { +- /* platforms without dma-friendly caches might need to +- * prevent cacheline sharing... +- */ +- 32, +- 128, +- 512, +- PAGE_SIZE / 2 +- /* bigger --> allocate pages */ ++static size_t pool_max[HCD_BUFFER_POOLS] = { ++ 32, 128, 512, 2048, + }; + ++void __init usb_init_pool_max(void) ++{ ++ /* ++ * The pool_max values must never be smaller than ++ * ARCH_KMALLOC_MINALIGN. ++ */ ++ if (ARCH_KMALLOC_MINALIGN <= 32) ++ ; /* Original value is okay */ ++ else if (ARCH_KMALLOC_MINALIGN <= 64) ++ pool_max[0] = 64; ++ else if (ARCH_KMALLOC_MINALIGN <= 128) ++ pool_max[0] = 0; /* Don't use this pool */ ++ else ++ BUILD_BUG(); /* We don't allow this */ ++} + + /* SETUP primitives */ + +diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c +index ef6ec13b6ae5..ee6c5562d296 100644 +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -1617,6 +1617,7 @@ static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status) + int usb_hcd_unlink_urb (struct urb *urb, int status) + { + struct usb_hcd *hcd; ++ struct usb_device *udev = urb->dev; + int retval = -EIDRM; + unsigned long flags; + +@@ -1628,20 +1629,19 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) + spin_lock_irqsave(&hcd_urb_unlink_lock, flags); + if (atomic_read(&urb->use_count) > 0) { + retval = 0; +- usb_get_dev(urb->dev); ++ usb_get_dev(udev); + } + spin_unlock_irqrestore(&hcd_urb_unlink_lock, flags); + if (retval == 0) { + hcd = bus_to_hcd(urb->dev->bus); + retval = unlink1(hcd, urb, status); +- usb_put_dev(urb->dev); ++ if (retval == 0) ++ retval = -EINPROGRESS; ++ else if (retval != -EIDRM && retval != -EBUSY) ++ dev_dbg(&udev->dev, "hcd_unlink_urb %p fail %d\n", ++ urb, retval); ++ usb_put_dev(udev); + } +- +- if (retval == 0) +- retval = -EINPROGRESS; +- else if (retval != -EIDRM && retval != -EBUSY) +- dev_dbg(&urb->dev->dev, "hcd_unlink_urb %p fail %d\n", +- urb, retval); + return retval; + } + +diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c +index 4d1144990d4c..a92273026ecc 100644 +--- a/drivers/usb/core/usb.c ++++ b/drivers/usb/core/usb.c +@@ -1050,6 +1050,7 @@ static int __init usb_init(void) + pr_info("%s: USB support disabled\n", usbcore_name); + return 0; + } ++ usb_init_pool_max(); + + retval = usb_debugfs_init(); + if (retval) +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 9e8708c5cbfa..a2d040971afe 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -56,6 +56,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x0846, 0x1100) }, /* NetGear Managed Switch M4100 series, M5300 series, M7100 series */ + { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ + { USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */ ++ { USB_DEVICE(0x0908, 0x01FF) }, /* Siemens RUGGEDCOM USB Serial Console */ + { USB_DEVICE(0x0BED, 0x1100) }, /* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */ + { USB_DEVICE(0x0BED, 0x1101) }, /* MEI series 2000 Combo Acceptor */ + { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ +diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c +index 602913d7ae03..edfd797db341 100644 +--- a/drivers/xen/manage.c ++++ b/drivers/xen/manage.c +@@ -113,10 +113,16 @@ static void do_suspend(void) + + err = freeze_processes(); + if (err) { +- pr_err("%s: freeze failed %d\n", __func__, err); ++ pr_err("%s: freeze processes failed %d\n", __func__, err); + goto out; + } + ++ err = freeze_kernel_threads(); ++ if (err) { ++ pr_err("%s: freeze kernel threads failed %d\n", __func__, err); ++ goto out_thaw; ++ } ++ + err = dpm_suspend_start(PMSG_FREEZE); + if (err) { + pr_err("%s: dpm_suspend_start %d\n", __func__, err); +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index 67be2951b98a..f4d7b2fc9ffb 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -549,11 +549,12 @@ out: + + static unsigned long randomize_stack_top(unsigned long stack_top) + { +- unsigned int random_variable = 0; ++ unsigned long random_variable = 0; + + if ((current->flags & PF_RANDOMIZE) && + !(current->personality & ADDR_NO_RANDOMIZE)) { +- random_variable = get_random_int() & STACK_RND_MASK; ++ random_variable = (unsigned long) get_random_int(); ++ random_variable &= STACK_RND_MASK; + random_variable <<= PAGE_SHIFT; + } + #ifdef CONFIG_STACK_GROWSUP +diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c +index cbd3a7d6fa68..93de3ba994e7 100644 +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -2655,32 +2655,23 @@ static int key_search(struct extent_buffer *b, struct btrfs_key *key, + return 0; + } + +-int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *found_path, ++int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *path, + u64 iobjectid, u64 ioff, u8 key_type, + struct btrfs_key *found_key) + { + int ret; + struct btrfs_key key; + struct extent_buffer *eb; +- struct btrfs_path *path; ++ ++ ASSERT(path); + + key.type = key_type; + key.objectid = iobjectid; + key.offset = ioff; + +- if (found_path == NULL) { +- path = btrfs_alloc_path(); +- if (!path) +- return -ENOMEM; +- } else +- path = found_path; +- + ret = btrfs_search_slot(NULL, fs_root, &key, path, 0, 0); +- if ((ret < 0) || (found_key == NULL)) { +- if (path != found_path) +- btrfs_free_path(path); ++ if ((ret < 0) || (found_key == NULL)) + return ret; +- } + + eb = path->nodes[0]; + if (ret && path->slots[0] >= btrfs_header_nritems(eb)) { +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index 0db8ded65923..f48d5fc352a9 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -1560,6 +1560,7 @@ struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info, + bool check_ref) + { + struct btrfs_root *root; ++ struct btrfs_path *path; + int ret; + + if (location->objectid == BTRFS_ROOT_TREE_OBJECTID) +@@ -1599,8 +1600,14 @@ again: + if (ret) + goto fail; + +- ret = btrfs_find_item(fs_info->tree_root, NULL, BTRFS_ORPHAN_OBJECTID, ++ path = btrfs_alloc_path(); ++ if (!path) { ++ ret = -ENOMEM; ++ goto fail; ++ } ++ ret = btrfs_find_item(fs_info->tree_root, path, BTRFS_ORPHAN_OBJECTID, + location->objectid, BTRFS_ORPHAN_ITEM_KEY, NULL); ++ btrfs_free_path(path); + if (ret < 0) + goto fail; + if (ret == 0) +@@ -2411,7 +2418,7 @@ int open_ctree(struct super_block *sb, + features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO; + + if (features & BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA) +- printk(KERN_ERR "BTRFS: has skinny extents\n"); ++ printk(KERN_INFO "BTRFS: has skinny extents\n"); + + /* + * flag our filesystem as having big metadata blocks if +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index 39d83da03e03..aeb57b98c53f 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -1238,10 +1238,19 @@ static int insert_orphan_item(struct btrfs_trans_handle *trans, + struct btrfs_root *root, u64 offset) + { + int ret; +- ret = btrfs_find_item(root, NULL, BTRFS_ORPHAN_OBJECTID, ++ struct btrfs_path *path; ++ ++ path = btrfs_alloc_path(); ++ if (!path) ++ return -ENOMEM; ++ ++ ret = btrfs_find_item(root, path, BTRFS_ORPHAN_OBJECTID, + offset, BTRFS_ORPHAN_ITEM_KEY, NULL); + if (ret > 0) + ret = btrfs_insert_orphan_item(trans, root, offset); ++ ++ btrfs_free_path(path); ++ + return ret; + } + +diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c +index 7654e87b0428..9ad5ba4b299b 100644 +--- a/fs/jffs2/scan.c ++++ b/fs/jffs2/scan.c +@@ -510,6 +510,10 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo + sumlen = c->sector_size - je32_to_cpu(sm->offset); + sumptr = buf + buf_size - sumlen; + ++ /* sm->offset maybe wrong but MAGIC maybe right */ ++ if (sumlen > c->sector_size) ++ goto full_scan; ++ + /* Now, make sure the summary itself is available */ + if (sumlen > buf_size) { + /* Need to kmalloc for this. */ +@@ -544,6 +548,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo + } + } + ++full_scan: + buf_ofs = jeb->offset; + + if (!buf_size) { +diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c +index 073b4cf67ed9..0a2016bd6e58 100644 +--- a/fs/nfs/callback.c ++++ b/fs/nfs/callback.c +@@ -128,22 +128,24 @@ nfs41_callback_svc(void *vrqstp) + if (try_to_freeze()) + continue; + +- prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE); ++ prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_UNINTERRUPTIBLE); + spin_lock_bh(&serv->sv_cb_lock); + if (!list_empty(&serv->sv_cb_list)) { + req = list_first_entry(&serv->sv_cb_list, + struct rpc_rqst, rq_bc_list); + list_del(&req->rq_bc_list); + spin_unlock_bh(&serv->sv_cb_lock); ++ finish_wait(&serv->sv_cb_waitq, &wq); + dprintk("Invoking bc_svc_process()\n"); + error = bc_svc_process(serv, req, rqstp); + dprintk("bc_svc_process() returned w/ error code= %d\n", + error); + } else { + spin_unlock_bh(&serv->sv_cb_lock); +- schedule(); ++ /* schedule_timeout to game the hung task watchdog */ ++ schedule_timeout(60 * HZ); ++ finish_wait(&serv->sv_cb_waitq, &wq); + } +- finish_wait(&serv->sv_cb_waitq, &wq); + } + return 0; + } +diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c +index f4ccfe6521ec..02f8d09e119f 100644 +--- a/fs/nfs/callback_xdr.c ++++ b/fs/nfs/callback_xdr.c +@@ -464,8 +464,10 @@ static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp, + + for (i = 0; i < args->csa_nrclists; i++) { + status = decode_rc_list(xdr, &args->csa_rclists[i]); +- if (status) ++ if (status) { ++ args->csa_nrclists = i; + goto out_free; ++ } + } + } + status = 0; +diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c +index 33149113e333..645f180f5960 100644 +--- a/fs/xfs/xfs_buf_item.c ++++ b/fs/xfs/xfs_buf_item.c +@@ -319,6 +319,10 @@ xfs_buf_item_format( + ASSERT(atomic_read(&bip->bli_refcount) > 0); + ASSERT((bip->bli_flags & XFS_BLI_LOGGED) || + (bip->bli_flags & XFS_BLI_STALE)); ++ ASSERT((bip->bli_flags & XFS_BLI_STALE) || ++ (xfs_blft_from_flags(&bip->__bli_format) > XFS_BLFT_UNKNOWN_BUF ++ && xfs_blft_from_flags(&bip->__bli_format) < XFS_BLFT_MAX_BUF)); ++ + + /* + * If it is an inode buffer, transfer the in-memory state to the +diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c +index 3a137e9f9a7d..5d90b8db0ac7 100644 +--- a/fs/xfs/xfs_inode.c ++++ b/fs/xfs/xfs_inode.c +@@ -1946,6 +1946,7 @@ xfs_iunlink( + agi->agi_unlinked[bucket_index] = cpu_to_be32(agino); + offset = offsetof(xfs_agi_t, agi_unlinked) + + (sizeof(xfs_agino_t) * bucket_index); ++ xfs_trans_buf_set_type(tp, agibp, XFS_BLFT_AGI_BUF); + xfs_trans_log_buf(tp, agibp, offset, + (offset + sizeof(xfs_agino_t) - 1)); + return 0; +@@ -2037,6 +2038,7 @@ xfs_iunlink_remove( + agi->agi_unlinked[bucket_index] = cpu_to_be32(next_agino); + offset = offsetof(xfs_agi_t, agi_unlinked) + + (sizeof(xfs_agino_t) * bucket_index); ++ xfs_trans_buf_set_type(tp, agibp, XFS_BLFT_AGI_BUF); + xfs_trans_log_buf(tp, agibp, offset, + (offset + sizeof(xfs_agino_t) - 1)); + } else { +diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c +index 6d7d1de13403..1b271f59d518 100644 +--- a/fs/xfs/xfs_qm.c ++++ b/fs/xfs/xfs_qm.c +@@ -1108,6 +1108,11 @@ xfs_qm_reset_dqcounts( + */ + xfs_dqcheck(mp, ddq, id+j, type, XFS_QMOPT_DQREPAIR, + "xfs_quotacheck"); ++ /* ++ * Reset type in case we are reusing group quota file for ++ * project quotas or vice versa ++ */ ++ ddq->d_flags = type; + ddq->d_bcount = 0; + ddq->d_icount = 0; + ddq->d_rtbcount = 0; +diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c +index c812c5c060de..b626f3db67cb 100644 +--- a/fs/xfs/xfs_trans.c ++++ b/fs/xfs/xfs_trans.c +@@ -474,6 +474,7 @@ xfs_trans_apply_sb_deltas( + whole = 1; + } + ++ xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); + if (whole) + /* + * Log the whole thing, the fields are noncontiguous. +diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h +index 1c804b057fb1..7ee1774edee5 100644 +--- a/include/linux/fsnotify.h ++++ b/include/linux/fsnotify.h +@@ -101,8 +101,10 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, + new_dir_mask |= FS_ISDIR; + } + +- fsnotify(old_dir, old_dir_mask, old_dir, FSNOTIFY_EVENT_INODE, old_name, fs_cookie); +- fsnotify(new_dir, new_dir_mask, new_dir, FSNOTIFY_EVENT_INODE, new_name, fs_cookie); ++ fsnotify(old_dir, old_dir_mask, source, FSNOTIFY_EVENT_INODE, old_name, ++ fs_cookie); ++ fsnotify(new_dir, new_dir_mask, source, FSNOTIFY_EVENT_INODE, new_name, ++ fs_cookie); + + if (target) + fsnotify_link_count(target); +diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h +index efe8d8a7c7ad..e34bce3781ee 100644 +--- a/include/linux/usb/hcd.h ++++ b/include/linux/usb/hcd.h +@@ -447,6 +447,7 @@ extern const struct dev_pm_ops usb_hcd_pci_pm_ops; + #endif /* CONFIG_PCI */ + + /* pci-ish (pdev null is ok) buffer alloc/mapping support */ ++void usb_init_pool_max(void); + int hcd_buffer_create(struct usb_hcd *hcd); + void hcd_buffer_destroy(struct usb_hcd *hcd); + +diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c +index 0b097c8a1e50..449518eb85ce 100644 +--- a/kernel/debug/kdb/kdb_main.c ++++ b/kernel/debug/kdb/kdb_main.c +@@ -2535,7 +2535,7 @@ static int kdb_summary(int argc, const char **argv) + #define K(x) ((x) << (PAGE_SHIFT - 10)) + kdb_printf("\nMemTotal: %8lu kB\nMemFree: %8lu kB\n" + "Buffers: %8lu kB\n", +- val.totalram, val.freeram, val.bufferram); ++ K(val.totalram), K(val.freeram), K(val.bufferram)); + return 0; + } + +diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c +index 28db9bedc857..6211d5d6d465 100644 +--- a/kernel/time/ntp.c ++++ b/kernel/time/ntp.c +@@ -631,10 +631,14 @@ int ntp_validate_timex(struct timex *txc) + if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME))) + return -EPERM; + +- if (txc->modes & ADJ_FREQUENCY) { +- if (LONG_MIN / PPM_SCALE > txc->freq) ++ /* ++ * Check for potential multiplication overflows that can ++ * only happen on 64-bit systems: ++ */ ++ if ((txc->modes & ADJ_FREQUENCY) && (BITS_PER_LONG == 64)) { ++ if (LLONG_MIN / PPM_SCALE > txc->freq) + return -EINVAL; +- if (LONG_MAX / PPM_SCALE < txc->freq) ++ if (LLONG_MAX / PPM_SCALE < txc->freq) + return -EINVAL; + } + +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index 71136720ffa1..813b021379f5 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -4694,7 +4694,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, + *fpos += written; + + out_unlock: +- for (i = 0; i < nr_pages; i++){ ++ for (i = nr_pages - 1; i >= 0; i--) { + kunmap_atomic(map_page[i]); + put_page(pages[i]); + } +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 67d0c175efcf..472259b00618 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -3456,6 +3456,8 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address, + { + struct page *page; + ++ if (!pmd_present(*pmd)) ++ return NULL; + page = pte_page(*(pte_t *)pmd); + if (page) + page += ((address & ~PMD_MASK) >> PAGE_SHIFT); +diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c +index 0676f2b199d6..45f077c60348 100644 +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -977,12 +977,24 @@ static void put_osd(struct ceph_osd *osd) + */ + static void __remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) + { +- dout("__remove_osd %p\n", osd); +- BUG_ON(!list_empty(&osd->o_requests)); +- rb_erase(&osd->o_node, &osdc->osds); ++ dout("%s %p osd%d\n", __func__, osd, osd->o_osd); ++ WARN_ON(!list_empty(&osd->o_requests)); ++ WARN_ON(!list_empty(&osd->o_linger_requests)); ++ + list_del_init(&osd->o_osd_lru); +- ceph_con_close(&osd->o_con); +- put_osd(osd); ++ rb_erase(&osd->o_node, &osdc->osds); ++ RB_CLEAR_NODE(&osd->o_node); ++} ++ ++static void remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) ++{ ++ dout("%s %p osd%d\n", __func__, osd, osd->o_osd); ++ ++ if (!RB_EMPTY_NODE(&osd->o_node)) { ++ ceph_con_close(&osd->o_con); ++ __remove_osd(osdc, osd); ++ put_osd(osd); ++ } + } + + static void remove_all_osds(struct ceph_osd_client *osdc) +@@ -992,7 +1004,7 @@ static void remove_all_osds(struct ceph_osd_client *osdc) + while (!RB_EMPTY_ROOT(&osdc->osds)) { + struct ceph_osd *osd = rb_entry(rb_first(&osdc->osds), + struct ceph_osd, o_node); +- __remove_osd(osdc, osd); ++ remove_osd(osdc, osd); + } + mutex_unlock(&osdc->request_mutex); + } +@@ -1022,7 +1034,7 @@ static void remove_old_osds(struct ceph_osd_client *osdc) + list_for_each_entry_safe(osd, nosd, &osdc->osd_lru, o_osd_lru) { + if (time_before(jiffies, osd->lru_ttl)) + break; +- __remove_osd(osdc, osd); ++ remove_osd(osdc, osd); + } + mutex_unlock(&osdc->request_mutex); + } +@@ -1037,8 +1049,7 @@ static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) + dout("__reset_osd %p osd%d\n", osd, osd->o_osd); + if (list_empty(&osd->o_requests) && + list_empty(&osd->o_linger_requests)) { +- __remove_osd(osdc, osd); +- ++ remove_osd(osdc, osd); + return -ENODEV; + } + +@@ -1840,6 +1851,7 @@ static void reset_changed_osds(struct ceph_osd_client *osdc) + { + struct rb_node *p, *n; + ++ dout("%s %p\n", __func__, osdc); + for (p = rb_first(&osdc->osds); p; p = n) { + struct ceph_osd *osd = rb_entry(p, struct ceph_osd, o_node); + +diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c +index 56cc891e395e..d99c8d341e50 100644 +--- a/sound/pci/riptide/riptide.c ++++ b/sound/pci/riptide/riptide.c +@@ -2032,32 +2032,43 @@ snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id) + { + static int dev; + struct gameport *gameport; ++ int ret; + + if (dev >= SNDRV_CARDS) + return -ENODEV; ++ + if (!enable[dev]) { +- dev++; +- return -ENOENT; ++ ret = -ENOENT; ++ goto inc_dev; + } + +- if (!joystick_port[dev++]) +- return 0; ++ if (!joystick_port[dev]) { ++ ret = 0; ++ goto inc_dev; ++ } + + gameport = gameport_allocate_port(); +- if (!gameport) +- return -ENOMEM; ++ if (!gameport) { ++ ret = -ENOMEM; ++ goto inc_dev; ++ } + if (!request_region(joystick_port[dev], 8, "Riptide gameport")) { + snd_printk(KERN_WARNING + "Riptide: cannot grab gameport 0x%x\n", + joystick_port[dev]); + gameport_free_port(gameport); +- return -EBUSY; ++ ret = -EBUSY; ++ goto inc_dev; + } + + gameport->io = joystick_port[dev]; + gameport_register_port(gameport); + pci_set_drvdata(pci, gameport); +- return 0; ++ ++ ret = 0; ++inc_dev: ++ dev++; ++ return ret; + } + + static void snd_riptide_joystick_remove(struct pci_dev *pci) +diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c +index e98dc008de0b..21167503a3f9 100644 +--- a/sound/pci/rme9652/hdspm.c ++++ b/sound/pci/rme9652/hdspm.c +@@ -6102,6 +6102,9 @@ static int snd_hdspm_playback_open(struct snd_pcm_substream *substream) + snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + 64, 8192); ++ snd_pcm_hw_constraint_minmax(runtime, ++ SNDRV_PCM_HW_PARAM_PERIODS, ++ 2, 2); + break; + } + +@@ -6176,6 +6179,9 @@ static int snd_hdspm_capture_open(struct snd_pcm_substream *substream) + snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + 64, 8192); ++ snd_pcm_hw_constraint_minmax(runtime, ++ SNDRV_PCM_HW_PARAM_PERIODS, ++ 2, 2); + break; + } + diff --git a/patch/kernel/cubox-default/patch-3.14.35-36.patch b/patch/kernel/cubox-default/patch-3.14.35-36.patch new file mode 100644 index 000000000..ea99fa6f0 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.35-36.patch @@ -0,0 +1,3477 @@ +diff --git a/Makefile b/Makefile +index 9720e863c06f..4e6537bd8aa0 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 35 ++SUBLEVEL = 36 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h +index 15334ab66b56..fb95aa807215 100644 +--- a/arch/arc/include/asm/processor.h ++++ b/arch/arc/include/asm/processor.h +@@ -69,18 +69,19 @@ unsigned long thread_saved_pc(struct task_struct *t); + #define release_segments(mm) do { } while (0) + + #define KSTK_EIP(tsk) (task_pt_regs(tsk)->ret) ++#define KSTK_ESP(tsk) (task_pt_regs(tsk)->sp) + + /* + * Where abouts of Task's sp, fp, blink when it was last seen in kernel mode. + * Look in process.c for details of kernel stack layout + */ +-#define KSTK_ESP(tsk) (tsk->thread.ksp) ++#define TSK_K_ESP(tsk) (tsk->thread.ksp) + +-#define KSTK_REG(tsk, off) (*((unsigned int *)(KSTK_ESP(tsk) + \ ++#define TSK_K_REG(tsk, off) (*((unsigned int *)(TSK_K_ESP(tsk) + \ + sizeof(struct callee_regs) + off))) + +-#define KSTK_BLINK(tsk) KSTK_REG(tsk, 4) +-#define KSTK_FP(tsk) KSTK_REG(tsk, 0) ++#define TSK_K_BLINK(tsk) TSK_K_REG(tsk, 4) ++#define TSK_K_FP(tsk) TSK_K_REG(tsk, 0) + + /* + * Do necessary setup to start up a newly executed thread. +diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c +index 9ce47cfe2303..fb98769b6a98 100644 +--- a/arch/arc/kernel/stacktrace.c ++++ b/arch/arc/kernel/stacktrace.c +@@ -64,9 +64,9 @@ static void seed_unwind_frame_info(struct task_struct *tsk, + + frame_info->task = tsk; + +- frame_info->regs.r27 = KSTK_FP(tsk); +- frame_info->regs.r28 = KSTK_ESP(tsk); +- frame_info->regs.r31 = KSTK_BLINK(tsk); ++ frame_info->regs.r27 = TSK_K_FP(tsk); ++ frame_info->regs.r28 = TSK_K_ESP(tsk); ++ frame_info->regs.r31 = TSK_K_BLINK(tsk); + frame_info->regs.r63 = (unsigned int)__switch_to; + + /* In the prologue of __switch_to, first FP is saved on stack +diff --git a/arch/mips/kvm/trace.h b/arch/mips/kvm/trace.h +index bc9e0f406c08..e51621e36152 100644 +--- a/arch/mips/kvm/trace.h ++++ b/arch/mips/kvm/trace.h +@@ -26,18 +26,18 @@ TRACE_EVENT(kvm_exit, + TP_PROTO(struct kvm_vcpu *vcpu, unsigned int reason), + TP_ARGS(vcpu, reason), + TP_STRUCT__entry( +- __field(struct kvm_vcpu *, vcpu) ++ __field(unsigned long, pc) + __field(unsigned int, reason) + ), + + TP_fast_assign( +- __entry->vcpu = vcpu; ++ __entry->pc = vcpu->arch.pc; + __entry->reason = reason; + ), + + TP_printk("[%s]PC: 0x%08lx", + kvm_mips_exit_types_str[__entry->reason], +- __entry->vcpu->arch.pc) ++ __entry->pc) + ); + + #endif /* _TRACE_KVM_H */ +diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S +index 02553d6d183d..06469ee0f26e 100644 +--- a/arch/x86/kernel/entry_64.S ++++ b/arch/x86/kernel/entry_64.S +@@ -542,11 +542,14 @@ ENTRY(ret_from_fork) + testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread? + jz 1f + +- testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET +- jnz int_ret_from_sys_call +- +- RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET +- jmp ret_from_sys_call # go to the SYSRET fastpath ++ /* ++ * By the time we get here, we have no idea whether our pt_regs, ++ * ti flags, and ti status came from the 64-bit SYSCALL fast path, ++ * the slow path, or one of the ia32entry paths. ++ * Use int_ret_from_sys_call to return, since it can safely handle ++ * all of the above. ++ */ ++ jmp int_ret_from_sys_call + + 1: + subq $REST_SKIP, %rsp # leave space for volatiles +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index 38d3751472e4..09651d4a9038 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -4646,7 +4646,8 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) + if (rc != X86EMUL_CONTINUE) + goto done; + } +- ctxt->dst.orig_val = ctxt->dst.val; ++ /* Copy full 64-bit value for CMPXCHG8B. */ ++ ctxt->dst.orig_val64 = ctxt->dst.val64; + + special_insn: + +diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c +index bb0b90461a6b..997540dc8250 100644 +--- a/drivers/acpi/video.c ++++ b/drivers/acpi/video.c +@@ -2064,6 +2064,17 @@ EXPORT_SYMBOL(acpi_video_unregister); + + static int __init acpi_video_init(void) + { ++ /* ++ * Let the module load even if ACPI is disabled (e.g. due to ++ * a broken BIOS) so that i915.ko can still be loaded on such ++ * old systems without an AcpiOpRegion. ++ * ++ * acpi_video_register() will report -ENODEV later as well due ++ * to acpi_disabled when i915.ko tries to register itself afterwards. ++ */ ++ if (acpi_disabled) ++ return 0; ++ + dmi_check_system(video_dmi_table); + + if (intel_opregion_present()) +diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c +index 4a58c55255bd..797bab97cea6 100644 +--- a/drivers/clk/clk-gate.c ++++ b/drivers/clk/clk-gate.c +@@ -128,7 +128,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name, + struct clk_init_data init; + + if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { +- if (bit_idx > 16) { ++ if (bit_idx > 15) { + pr_err("gate bit exceeds LOWORD field\n"); + return ERR_PTR(-EINVAL); + } +diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c +index 9e232644f07e..ea4db844aee3 100644 +--- a/drivers/clk/sunxi/clk-factors.c ++++ b/drivers/clk/sunxi/clk-factors.c +@@ -62,7 +62,7 @@ static unsigned long clk_factors_recalc_rate(struct clk_hw *hw, + p = FACTOR_GET(config->pshift, config->pwidth, reg); + + /* Calculate the rate */ +- rate = (parent_rate * n * (k + 1) >> p) / (m + 1); ++ rate = (parent_rate * (n + config->n_start) * (k + 1) >> p) / (m + 1); + + return rate; + } +diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h +index 02e1a43ebac7..d2d0efa39379 100644 +--- a/drivers/clk/sunxi/clk-factors.h ++++ b/drivers/clk/sunxi/clk-factors.h +@@ -15,6 +15,7 @@ struct clk_factors_config { + u8 mwidth; + u8 pshift; + u8 pwidth; ++ u8 n_start; + }; + + struct clk_factors { +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index abb6c5ac8a10..06a14b808683 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -407,6 +407,7 @@ static struct clk_factors_config sun6i_a31_pll1_config = { + .kwidth = 2, + .mshift = 0, + .mwidth = 2, ++ .n_start = 1, + }; + + static struct clk_factors_config sun4i_pll5_config = { +diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c +index 09dd0173ea0a..5f52f3f62644 100644 +--- a/drivers/clk/zynq/clkc.c ++++ b/drivers/clk/zynq/clkc.c +@@ -300,6 +300,7 @@ static void __init zynq_clk_setup(struct device_node *np) + clks[cpu_2x] = clk_register_gate(NULL, clk_output_name[cpu_2x], + "cpu_2x_div", CLK_IGNORE_UNUSED, SLCR_ARM_CLK_CTRL, + 26, 0, &armclk_lock); ++ clk_prepare_enable(clks[cpu_2x]); + + clk = clk_register_fixed_factor(NULL, "cpu_1x_div", "cpu_div", 0, 1, + 4 + 2 * tmp); +diff --git a/drivers/firmware/efi/runtime-map.c b/drivers/firmware/efi/runtime-map.c +index 97cdd16a2169..c98b101a73ae 100644 +--- a/drivers/firmware/efi/runtime-map.c ++++ b/drivers/firmware/efi/runtime-map.c +@@ -170,7 +170,7 @@ int __init efi_runtime_map_init(struct kobject *efi_kobj) + + return 0; + out_add_entry: +- for (j = i - 1; j > 0; j--) { ++ for (j = i - 1; j >= 0; j--) { + entry = *(map_entries + j); + kobject_put(&entry->kobj); + } +diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c +index 8ef67cb4ef1e..f0ed0baddf70 100644 +--- a/drivers/gpu/drm/radeon/cik.c ++++ b/drivers/gpu/drm/radeon/cik.c +@@ -3558,7 +3558,21 @@ void cik_fence_gfx_ring_emit(struct radeon_device *rdev, + struct radeon_ring *ring = &rdev->ring[fence->ring]; + u64 addr = rdev->fence_drv[fence->ring].gpu_addr; + +- /* EVENT_WRITE_EOP - flush caches, send int */ ++ /* Workaround for cache flush problems. First send a dummy EOP ++ * event down the pipe with seq one below. ++ */ ++ radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); ++ radeon_ring_write(ring, (EOP_TCL1_ACTION_EN | ++ EOP_TC_ACTION_EN | ++ EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) | ++ EVENT_INDEX(5))); ++ radeon_ring_write(ring, addr & 0xfffffffc); ++ radeon_ring_write(ring, (upper_32_bits(addr) & 0xffff) | ++ DATA_SEL(1) | INT_SEL(0)); ++ radeon_ring_write(ring, fence->seq - 1); ++ radeon_ring_write(ring, 0); ++ ++ /* Then send the real EOP event down the pipe. */ + radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); + radeon_ring_write(ring, (EOP_TCL1_ACTION_EN | + EOP_TC_ACTION_EN | +@@ -6809,7 +6823,6 @@ int cik_irq_set(struct radeon_device *rdev) + u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; + u32 grbm_int_cntl = 0; + u32 dma_cntl, dma_cntl1; +- u32 thermal_int; + + if (!rdev->irq.installed) { + WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); +@@ -6846,13 +6859,6 @@ int cik_irq_set(struct radeon_device *rdev) + cp_m2p2 = RREG32(CP_ME2_PIPE2_INT_CNTL) & ~TIME_STAMP_INT_ENABLE; + cp_m2p3 = RREG32(CP_ME2_PIPE3_INT_CNTL) & ~TIME_STAMP_INT_ENABLE; + +- if (rdev->flags & RADEON_IS_IGP) +- thermal_int = RREG32_SMC(CG_THERMAL_INT_CTRL) & +- ~(THERM_INTH_MASK | THERM_INTL_MASK); +- else +- thermal_int = RREG32_SMC(CG_THERMAL_INT) & +- ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); +- + /* enable CP interrupts on all rings */ + if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { + DRM_DEBUG("cik_irq_set: sw int gfx\n"); +@@ -7010,14 +7016,6 @@ int cik_irq_set(struct radeon_device *rdev) + hpd6 |= DC_HPDx_INT_EN; + } + +- if (rdev->irq.dpm_thermal) { +- DRM_DEBUG("dpm thermal\n"); +- if (rdev->flags & RADEON_IS_IGP) +- thermal_int |= THERM_INTH_MASK | THERM_INTL_MASK; +- else +- thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW; +- } +- + WREG32(CP_INT_CNTL_RING0, cp_int_cntl); + + WREG32(SDMA0_CNTL + SDMA0_REGISTER_OFFSET, dma_cntl); +@@ -7071,11 +7069,6 @@ int cik_irq_set(struct radeon_device *rdev) + WREG32(DC_HPD5_INT_CONTROL, hpd5); + WREG32(DC_HPD6_INT_CONTROL, hpd6); + +- if (rdev->flags & RADEON_IS_IGP) +- WREG32_SMC(CG_THERMAL_INT_CTRL, thermal_int); +- else +- WREG32_SMC(CG_THERMAL_INT, thermal_int); +- + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c +index 351db361239d..c7c7bc5d573f 100644 +--- a/drivers/gpu/drm/radeon/kv_dpm.c ++++ b/drivers/gpu/drm/radeon/kv_dpm.c +@@ -1121,6 +1121,19 @@ void kv_dpm_enable_bapm(struct radeon_device *rdev, bool enable) + } + } + ++static void kv_enable_thermal_int(struct radeon_device *rdev, bool enable) ++{ ++ u32 thermal_int; ++ ++ thermal_int = RREG32_SMC(CG_THERMAL_INT_CTRL); ++ if (enable) ++ thermal_int |= THERM_INTH_MASK | THERM_INTL_MASK; ++ else ++ thermal_int &= ~(THERM_INTH_MASK | THERM_INTL_MASK); ++ WREG32_SMC(CG_THERMAL_INT_CTRL, thermal_int); ++ ++} ++ + int kv_dpm_enable(struct radeon_device *rdev) + { + struct kv_power_info *pi = kv_get_pi(rdev); +@@ -1232,8 +1245,7 @@ int kv_dpm_late_enable(struct radeon_device *rdev) + DRM_ERROR("kv_set_thermal_temperature_range failed\n"); + return ret; + } +- rdev->irq.dpm_thermal = true; +- radeon_irq_set(rdev); ++ kv_enable_thermal_int(rdev, true); + } + + /* powerdown unused blocks for now */ +@@ -1261,6 +1273,7 @@ void kv_dpm_disable(struct radeon_device *rdev) + kv_stop_dpm(rdev); + kv_enable_ulv(rdev, false); + kv_reset_am(rdev); ++ kv_enable_thermal_int(rdev, false); + + kv_update_current_ps(rdev, rdev->pm.dpm.boot_ps); + } +diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c +index bf6300cfd62d..f8c01b8d1594 100644 +--- a/drivers/gpu/drm/radeon/ni.c ++++ b/drivers/gpu/drm/radeon/ni.c +@@ -1073,12 +1073,12 @@ static void cayman_gpu_init(struct radeon_device *rdev) + + if ((rdev->config.cayman.max_backends_per_se == 1) && + (rdev->flags & RADEON_IS_IGP)) { +- if ((disabled_rb_mask & 3) == 1) { +- /* RB0 disabled, RB1 enabled */ +- tmp = 0x11111111; +- } else { ++ if ((disabled_rb_mask & 3) == 2) { + /* RB1 disabled, RB0 enabled */ + tmp = 0x00000000; ++ } else { ++ /* RB0 disabled, RB1 enabled */ ++ tmp = 0x11111111; + } + } else { + tmp = gb_addr_config & NUM_PIPES_MASK; +diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c +index 3334f916945b..e98108236e04 100644 +--- a/drivers/gpu/drm/radeon/r600_dpm.c ++++ b/drivers/gpu/drm/radeon/r600_dpm.c +@@ -187,7 +187,7 @@ u32 r600_dpm_get_vrefresh(struct radeon_device *rdev) + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + radeon_crtc = to_radeon_crtc(crtc); + if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) { +- vrefresh = radeon_crtc->hw_mode.vrefresh; ++ vrefresh = drm_mode_vrefresh(&radeon_crtc->hw_mode); + break; + } + } +diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c +index e2de749327ad..2fa3cf615a67 100644 +--- a/drivers/gpu/drm/radeon/radeon_atombios.c ++++ b/drivers/gpu/drm/radeon/radeon_atombios.c +@@ -3272,6 +3272,7 @@ int radeon_atom_get_voltage_evv(struct radeon_device *rdev, + + args.in.ucVoltageType = VOLTAGE_TYPE_VDDC; + args.in.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE; ++ args.in.usVoltageLevel = cpu_to_le16(virtual_voltage_id); + args.in.ulSCLKFreq = + cpu_to_le32(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[entry_id].clk); + +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index 4b87bb164f30..a413f76e84d4 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -1066,6 +1066,23 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct + return; + } + ++ /* ++ * Ignore reports for absolute data if the data didn't change. This is ++ * not only an optimization but also fixes 'dead' key reports. Some ++ * RollOver implementations for localized keys (like BACKSLASH/PIPE; HID ++ * 0x31 and 0x32) report multiple keys, even though a localized keyboard ++ * can only have one of them physically available. The 'dead' keys ++ * report constant 0. As all map to the same keycode, they'd confuse ++ * the input layer. If we filter the 'dead' keys on the HID level, we ++ * skip the keycode translation and only forward real events. ++ */ ++ if (!(field->flags & (HID_MAIN_ITEM_RELATIVE | ++ HID_MAIN_ITEM_BUFFERED_BYTE)) && ++ (field->flags & HID_MAIN_ITEM_VARIABLE) && ++ usage->usage_index < field->maxusage && ++ value == field->value[usage->usage_index]) ++ return; ++ + /* report the usage code as scancode if the key status has changed */ + if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value) + input_event(input, EV_MSC, MSC_SCAN, usage->hid); +diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c +index 47dcb34ff44c..3a615f3b5d80 100644 +--- a/drivers/iio/adc/mcp3422.c ++++ b/drivers/iio/adc/mcp3422.c +@@ -57,20 +57,11 @@ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + } + +-/* LSB is in nV to eliminate floating point */ +-static const u32 rates_to_lsb[] = {1000000, 250000, 62500, 15625}; +- +-/* +- * scales calculated as: +- * rates_to_lsb[sample_rate] / (1 << pga); +- * pga is 1 for 0, 2 +- */ +- + static const int mcp3422_scales[4][4] = { +- { 1000000, 250000, 62500, 15625 }, +- { 500000 , 125000, 31250, 7812 }, +- { 250000 , 62500 , 15625, 3906 }, +- { 125000 , 31250 , 7812 , 1953 } }; ++ { 1000000, 500000, 250000, 125000 }, ++ { 250000 , 125000, 62500 , 31250 }, ++ { 62500 , 31250 , 15625 , 7812 }, ++ { 15625 , 7812 , 3906 , 1953 } }; + + /* Constant msleep times for data acquisitions */ + static const int mcp3422_read_times[4] = { +diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c +index 17aca4d9bd06..861ba3d60163 100644 +--- a/drivers/iio/dac/ad5686.c ++++ b/drivers/iio/dac/ad5686.c +@@ -322,7 +322,7 @@ static int ad5686_probe(struct spi_device *spi) + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + +- st->reg = devm_regulator_get(&spi->dev, "vcc"); ++ st->reg = devm_regulator_get_optional(&spi->dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) +diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c +index 7c582f7ae34e..70753bf23a86 100644 +--- a/drivers/iio/imu/adis16400_core.c ++++ b/drivers/iio/imu/adis16400_core.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -447,7 +448,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, + mutex_unlock(&indio_dev->mlock); + if (ret) + return ret; +- val16 = ((val16 & 0xFFF) << 4) >> 4; ++ val16 = sign_extend32(val16, 11); + *val = val16; + return IIO_VAL_INT; + case IIO_CHAN_INFO_OFFSET: +diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c +index 56a4b7ca7ee3..45d67e9228d7 100644 +--- a/drivers/infiniband/core/ucma.c ++++ b/drivers/infiniband/core/ucma.c +@@ -1124,6 +1124,9 @@ static int ucma_set_ib_path(struct ucma_context *ctx, + if (!optlen) + return -EINVAL; + ++ memset(&sa_path, 0, sizeof(sa_path)); ++ sa_path.vlan_id = 0xffff; ++ + ib_sa_unpack_path(path_data->path_rec, &sa_path); + ret = rdma_set_ib_paths(ctx->cm_id, &sa_path, 1); + if (ret) +diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c +index 23467a2abd62..2adc14372b94 100644 +--- a/drivers/infiniband/core/uverbs_cmd.c ++++ b/drivers/infiniband/core/uverbs_cmd.c +@@ -1964,20 +1964,21 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, + if (qp->real_qp == qp) { + ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd.attr_mask); + if (ret) +- goto out; ++ goto release_qp; + ret = qp->device->modify_qp(qp, attr, + modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata); + } else { + ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask)); + } + +- put_qp_read(qp); +- + if (ret) +- goto out; ++ goto release_qp; + + ret = in_len; + ++release_qp: ++ put_qp_read(qp); ++ + out: + kfree(attr); + +diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c +index 11f0606792bb..1a3d924744cc 100644 +--- a/drivers/infiniband/hw/mlx4/main.c ++++ b/drivers/infiniband/hw/mlx4/main.c +@@ -1161,8 +1161,7 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) + struct mlx4_ib_qp *mqp = to_mqp(ibqp); + u64 reg_id; + struct mlx4_ib_steering *ib_steering = NULL; +- enum mlx4_protocol prot = (gid->raw[1] == 0x0e) ? +- MLX4_PROT_IB_IPV4 : MLX4_PROT_IB_IPV6; ++ enum mlx4_protocol prot = MLX4_PROT_IB_IPV6; + + if (mdev->dev->caps.steering_mode == + MLX4_STEERING_MODE_DEVICE_MANAGED) { +@@ -1175,8 +1174,10 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) + !!(mqp->flags & + MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK), + prot, ®_id); +- if (err) ++ if (err) { ++ pr_err("multicast attach op failed, err %d\n", err); + goto err_malloc; ++ } + + err = add_gid_entry(ibqp, gid); + if (err) +@@ -1224,8 +1225,7 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) + struct net_device *ndev; + struct mlx4_ib_gid_entry *ge; + u64 reg_id = 0; +- enum mlx4_protocol prot = (gid->raw[1] == 0x0e) ? +- MLX4_PROT_IB_IPV4 : MLX4_PROT_IB_IPV6; ++ enum mlx4_protocol prot = MLX4_PROT_IB_IPV6; + + if (mdev->dev->caps.steering_mode == + MLX4_STEERING_MODE_DEVICE_MANAGED) { +diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h +index 1946101419a3..675d3c796b9f 100644 +--- a/drivers/infiniband/hw/qib/qib.h ++++ b/drivers/infiniband/hw/qib/qib.h +@@ -1080,12 +1080,6 @@ struct qib_devdata { + /* control high-level access to EEPROM */ + struct mutex eep_lock; + uint64_t traffic_wds; +- /* active time is kept in seconds, but logged in hours */ +- atomic_t active_time; +- /* Below are nominal shadow of EEPROM, new since last EEPROM update */ +- uint8_t eep_st_errs[QIB_EEP_LOG_CNT]; +- uint8_t eep_st_new_errs[QIB_EEP_LOG_CNT]; +- uint16_t eep_hrs; + /* + * masks for which bits of errs, hwerrs that cause + * each of the counters to increment. +@@ -1307,8 +1301,7 @@ int qib_twsi_blk_rd(struct qib_devdata *dd, int dev, int addr, void *buffer, + int qib_twsi_blk_wr(struct qib_devdata *dd, int dev, int addr, + const void *buffer, int len); + void qib_get_eeprom_info(struct qib_devdata *); +-int qib_update_eeprom_log(struct qib_devdata *dd); +-void qib_inc_eeprom_err(struct qib_devdata *dd, u32 eidx, u32 incr); ++#define qib_inc_eeprom_err(dd, eidx, incr) + void qib_dump_lookup_output_queue(struct qib_devdata *); + void qib_force_pio_avail_update(struct qib_devdata *); + void qib_clear_symerror_on_linkup(unsigned long opaque); +diff --git a/drivers/infiniband/hw/qib/qib_eeprom.c b/drivers/infiniband/hw/qib/qib_eeprom.c +index 4d5d71aaa2b4..e2280b07df02 100644 +--- a/drivers/infiniband/hw/qib/qib_eeprom.c ++++ b/drivers/infiniband/hw/qib/qib_eeprom.c +@@ -267,190 +267,9 @@ void qib_get_eeprom_info(struct qib_devdata *dd) + "Board SN %s did not pass functional test: %s\n", + dd->serial, ifp->if_comment); + +- memcpy(&dd->eep_st_errs, &ifp->if_errcntp, QIB_EEP_LOG_CNT); +- /* +- * Power-on (actually "active") hours are kept as little-endian value +- * in EEPROM, but as seconds in a (possibly as small as 24-bit) +- * atomic_t while running. +- */ +- atomic_set(&dd->active_time, 0); +- dd->eep_hrs = ifp->if_powerhour[0] | (ifp->if_powerhour[1] << 8); +- + done: + vfree(buf); + + bail:; + } + +-/** +- * qib_update_eeprom_log - copy active-time and error counters to eeprom +- * @dd: the qlogic_ib device +- * +- * Although the time is kept as seconds in the qib_devdata struct, it is +- * rounded to hours for re-write, as we have only 16 bits in EEPROM. +- * First-cut code reads whole (expected) struct qib_flash, modifies, +- * re-writes. Future direction: read/write only what we need, assuming +- * that the EEPROM had to have been "good enough" for driver init, and +- * if not, we aren't making it worse. +- * +- */ +-int qib_update_eeprom_log(struct qib_devdata *dd) +-{ +- void *buf; +- struct qib_flash *ifp; +- int len, hi_water; +- uint32_t new_time, new_hrs; +- u8 csum; +- int ret, idx; +- unsigned long flags; +- +- /* first, check if we actually need to do anything. */ +- ret = 0; +- for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) { +- if (dd->eep_st_new_errs[idx]) { +- ret = 1; +- break; +- } +- } +- new_time = atomic_read(&dd->active_time); +- +- if (ret == 0 && new_time < 3600) +- goto bail; +- +- /* +- * The quick-check above determined that there is something worthy +- * of logging, so get current contents and do a more detailed idea. +- * read full flash, not just currently used part, since it may have +- * been written with a newer definition +- */ +- len = sizeof(struct qib_flash); +- buf = vmalloc(len); +- ret = 1; +- if (!buf) { +- qib_dev_err(dd, +- "Couldn't allocate memory to read %u bytes from eeprom for logging\n", +- len); +- goto bail; +- } +- +- /* Grab semaphore and read current EEPROM. If we get an +- * error, let go, but if not, keep it until we finish write. +- */ +- ret = mutex_lock_interruptible(&dd->eep_lock); +- if (ret) { +- qib_dev_err(dd, "Unable to acquire EEPROM for logging\n"); +- goto free_bail; +- } +- ret = qib_twsi_blk_rd(dd, dd->twsi_eeprom_dev, 0, buf, len); +- if (ret) { +- mutex_unlock(&dd->eep_lock); +- qib_dev_err(dd, "Unable read EEPROM for logging\n"); +- goto free_bail; +- } +- ifp = (struct qib_flash *)buf; +- +- csum = flash_csum(ifp, 0); +- if (csum != ifp->if_csum) { +- mutex_unlock(&dd->eep_lock); +- qib_dev_err(dd, "EEPROM cks err (0x%02X, S/B 0x%02X)\n", +- csum, ifp->if_csum); +- ret = 1; +- goto free_bail; +- } +- hi_water = 0; +- spin_lock_irqsave(&dd->eep_st_lock, flags); +- for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) { +- int new_val = dd->eep_st_new_errs[idx]; +- if (new_val) { +- /* +- * If we have seen any errors, add to EEPROM values +- * We need to saturate at 0xFF (255) and we also +- * would need to adjust the checksum if we were +- * trying to minimize EEPROM traffic +- * Note that we add to actual current count in EEPROM, +- * in case it was altered while we were running. +- */ +- new_val += ifp->if_errcntp[idx]; +- if (new_val > 0xFF) +- new_val = 0xFF; +- if (ifp->if_errcntp[idx] != new_val) { +- ifp->if_errcntp[idx] = new_val; +- hi_water = offsetof(struct qib_flash, +- if_errcntp) + idx; +- } +- /* +- * update our shadow (used to minimize EEPROM +- * traffic), to match what we are about to write. +- */ +- dd->eep_st_errs[idx] = new_val; +- dd->eep_st_new_errs[idx] = 0; +- } +- } +- /* +- * Now update active-time. We would like to round to the nearest hour +- * but unless atomic_t are sure to be proper signed ints we cannot, +- * because we need to account for what we "transfer" to EEPROM and +- * if we log an hour at 31 minutes, then we would need to set +- * active_time to -29 to accurately count the _next_ hour. +- */ +- if (new_time >= 3600) { +- new_hrs = new_time / 3600; +- atomic_sub((new_hrs * 3600), &dd->active_time); +- new_hrs += dd->eep_hrs; +- if (new_hrs > 0xFFFF) +- new_hrs = 0xFFFF; +- dd->eep_hrs = new_hrs; +- if ((new_hrs & 0xFF) != ifp->if_powerhour[0]) { +- ifp->if_powerhour[0] = new_hrs & 0xFF; +- hi_water = offsetof(struct qib_flash, if_powerhour); +- } +- if ((new_hrs >> 8) != ifp->if_powerhour[1]) { +- ifp->if_powerhour[1] = new_hrs >> 8; +- hi_water = offsetof(struct qib_flash, if_powerhour) + 1; +- } +- } +- /* +- * There is a tiny possibility that we could somehow fail to write +- * the EEPROM after updating our shadows, but problems from holding +- * the spinlock too long are a much bigger issue. +- */ +- spin_unlock_irqrestore(&dd->eep_st_lock, flags); +- if (hi_water) { +- /* we made some change to the data, uopdate cksum and write */ +- csum = flash_csum(ifp, 1); +- ret = eeprom_write_with_enable(dd, 0, buf, hi_water + 1); +- } +- mutex_unlock(&dd->eep_lock); +- if (ret) +- qib_dev_err(dd, "Failed updating EEPROM\n"); +- +-free_bail: +- vfree(buf); +-bail: +- return ret; +-} +- +-/** +- * qib_inc_eeprom_err - increment one of the four error counters +- * that are logged to EEPROM. +- * @dd: the qlogic_ib device +- * @eidx: 0..3, the counter to increment +- * @incr: how much to add +- * +- * Each counter is 8-bits, and saturates at 255 (0xFF). They +- * are copied to the EEPROM (aka flash) whenever qib_update_eeprom_log() +- * is called, but it can only be called in a context that allows sleep. +- * This function can be called even at interrupt level. +- */ +-void qib_inc_eeprom_err(struct qib_devdata *dd, u32 eidx, u32 incr) +-{ +- uint new_val; +- unsigned long flags; +- +- spin_lock_irqsave(&dd->eep_st_lock, flags); +- new_val = dd->eep_st_new_errs[eidx] + incr; +- if (new_val > 255) +- new_val = 255; +- dd->eep_st_new_errs[eidx] = new_val; +- spin_unlock_irqrestore(&dd->eep_st_lock, flags); +-} +diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c +index 84e593d6007b..295f6312e6a9 100644 +--- a/drivers/infiniband/hw/qib/qib_iba6120.c ++++ b/drivers/infiniband/hw/qib/qib_iba6120.c +@@ -2682,8 +2682,6 @@ static void qib_get_6120_faststats(unsigned long opaque) + spin_lock_irqsave(&dd->eep_st_lock, flags); + traffic_wds -= dd->traffic_wds; + dd->traffic_wds += traffic_wds; +- if (traffic_wds >= QIB_TRAFFIC_ACTIVE_THRESHOLD) +- atomic_add(5, &dd->active_time); /* S/B #define */ + spin_unlock_irqrestore(&dd->eep_st_lock, flags); + + qib_chk_6120_errormask(dd); +diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c +index 454c2e7668fe..c86e71b9e160 100644 +--- a/drivers/infiniband/hw/qib/qib_iba7220.c ++++ b/drivers/infiniband/hw/qib/qib_iba7220.c +@@ -3299,8 +3299,6 @@ static void qib_get_7220_faststats(unsigned long opaque) + spin_lock_irqsave(&dd->eep_st_lock, flags); + traffic_wds -= dd->traffic_wds; + dd->traffic_wds += traffic_wds; +- if (traffic_wds >= QIB_TRAFFIC_ACTIVE_THRESHOLD) +- atomic_add(5, &dd->active_time); /* S/B #define */ + spin_unlock_irqrestore(&dd->eep_st_lock, flags); + done: + mod_timer(&dd->stats_timer, jiffies + HZ * ACTIVITY_TIMER); +diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c +index d1bd21319d7d..0f8d1f0bd929 100644 +--- a/drivers/infiniband/hw/qib/qib_iba7322.c ++++ b/drivers/infiniband/hw/qib/qib_iba7322.c +@@ -5191,8 +5191,6 @@ static void qib_get_7322_faststats(unsigned long opaque) + spin_lock_irqsave(&ppd->dd->eep_st_lock, flags); + traffic_wds -= ppd->dd->traffic_wds; + ppd->dd->traffic_wds += traffic_wds; +- if (traffic_wds >= QIB_TRAFFIC_ACTIVE_THRESHOLD) +- atomic_add(ACTIVITY_TIMER, &ppd->dd->active_time); + spin_unlock_irqrestore(&ppd->dd->eep_st_lock, flags); + if (ppd->cpspec->qdr_dfe_on && (ppd->link_speed_active & + QIB_IB_QDR) && +diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c +index 76c3e177164d..8c9bb6c35838 100644 +--- a/drivers/infiniband/hw/qib/qib_init.c ++++ b/drivers/infiniband/hw/qib/qib_init.c +@@ -922,7 +922,6 @@ static void qib_shutdown_device(struct qib_devdata *dd) + } + } + +- qib_update_eeprom_log(dd); + } + + /** +diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c +index 3c8e4e3caca6..b9ccbda7817d 100644 +--- a/drivers/infiniband/hw/qib/qib_sysfs.c ++++ b/drivers/infiniband/hw/qib/qib_sysfs.c +@@ -611,28 +611,6 @@ bail: + return ret < 0 ? ret : count; + } + +-static ssize_t show_logged_errs(struct device *device, +- struct device_attribute *attr, char *buf) +-{ +- struct qib_ibdev *dev = +- container_of(device, struct qib_ibdev, ibdev.dev); +- struct qib_devdata *dd = dd_from_dev(dev); +- int idx, count; +- +- /* force consistency with actual EEPROM */ +- if (qib_update_eeprom_log(dd) != 0) +- return -ENXIO; +- +- count = 0; +- for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) { +- count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c", +- dd->eep_st_errs[idx], +- idx == (QIB_EEP_LOG_CNT - 1) ? '\n' : ' '); +- } +- +- return count; +-} +- + /* + * Dump tempsense regs. in decimal, to ease shell-scripts. + */ +@@ -679,7 +657,6 @@ static DEVICE_ATTR(nctxts, S_IRUGO, show_nctxts, NULL); + static DEVICE_ATTR(nfreectxts, S_IRUGO, show_nfreectxts, NULL); + static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL); + static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL); +-static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL); + static DEVICE_ATTR(tempsense, S_IRUGO, show_tempsense, NULL); + static DEVICE_ATTR(localbus_info, S_IRUGO, show_localbus_info, NULL); + static DEVICE_ATTR(chip_reset, S_IWUSR, NULL, store_chip_reset); +@@ -693,7 +670,6 @@ static struct device_attribute *qib_attributes[] = { + &dev_attr_nfreectxts, + &dev_attr_serial, + &dev_attr_boardversion, +- &dev_attr_logged_errors, + &dev_attr_tempsense, + &dev_attr_localbus_info, + &dev_attr_chip_reset, +diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c +index 05f371df6c40..d4b0a31ab66b 100644 +--- a/drivers/input/tablet/wacom_wac.c ++++ b/drivers/input/tablet/wacom_wac.c +@@ -700,6 +700,12 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) + input_report_key(input, BTN_7, (data[4] & 0x40)); /* Left */ + input_report_key(input, BTN_8, (data[4] & 0x80)); /* Down */ + input_report_key(input, BTN_0, (data[3] & 0x01)); /* Center */ ++ ++ if (data[4] | (data[3] & 0x01)) { ++ input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); ++ } else { ++ input_report_abs(input, ABS_MISC, 0); ++ } + } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) { + int i; + +diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c +index db404a0f7e2c..d2a8d64f8526 100644 +--- a/drivers/md/dm-io.c ++++ b/drivers/md/dm-io.c +@@ -292,6 +292,12 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, + unsigned short logical_block_size = queue_logical_block_size(q); + sector_t num_sectors; + ++ /* Reject unsupported discard requests */ ++ if ((rw & REQ_DISCARD) && !blk_queue_discard(q)) { ++ dec_count(io, region, -EOPNOTSUPP); ++ return; ++ } ++ + /* + * where->count may be zero if rw holds a flush and we need to + * send a zero-sized flush. +diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c +index 7dfdb5c746d6..089d62751f7f 100644 +--- a/drivers/md/dm-raid1.c ++++ b/drivers/md/dm-raid1.c +@@ -604,6 +604,15 @@ static void write_callback(unsigned long error, void *context) + return; + } + ++ /* ++ * If the bio is discard, return an error, but do not ++ * degrade the array. ++ */ ++ if (bio->bi_rw & REQ_DISCARD) { ++ bio_endio(bio, -EOPNOTSUPP); ++ return; ++ } ++ + for (i = 0; i < ms->nr_mirrors; i++) + if (test_bit(i, &error)) + fail_mirror(ms->mirror + i, DM_RAID1_WRITE_ERROR); +diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c +index ebddef5237e4..c356a10b9ba5 100644 +--- a/drivers/md/dm-snap.c ++++ b/drivers/md/dm-snap.c +@@ -1440,8 +1440,6 @@ out: + full_bio->bi_private = pe->full_bio_private; + atomic_inc(&full_bio->bi_remaining); + } +- free_pending_exception(pe); +- + increment_pending_exceptions_done_count(); + + up_write(&s->lock); +@@ -1458,6 +1456,8 @@ out: + } + + retry_origin_bios(s, origin_bios); ++ ++ free_pending_exception(pe); + } + + static void commit_callback(void *context, int success) +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index 65ee3a0d4683..1582c3dac3ac 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -2288,7 +2288,7 @@ int dm_setup_md_queue(struct mapped_device *md) + return 0; + } + +-static struct mapped_device *dm_find_md(dev_t dev) ++struct mapped_device *dm_get_md(dev_t dev) + { + struct mapped_device *md; + unsigned minor = MINOR(dev); +@@ -2299,12 +2299,15 @@ static struct mapped_device *dm_find_md(dev_t dev) + spin_lock(&_minor_lock); + + md = idr_find(&_minor_idr, minor); +- if (md && (md == MINOR_ALLOCED || +- (MINOR(disk_devt(dm_disk(md))) != minor) || +- dm_deleting_md(md) || +- test_bit(DMF_FREEING, &md->flags))) { +- md = NULL; +- goto out; ++ if (md) { ++ if ((md == MINOR_ALLOCED || ++ (MINOR(disk_devt(dm_disk(md))) != minor) || ++ dm_deleting_md(md) || ++ test_bit(DMF_FREEING, &md->flags))) { ++ md = NULL; ++ goto out; ++ } ++ dm_get(md); + } + + out: +@@ -2312,16 +2315,6 @@ out: + + return md; + } +- +-struct mapped_device *dm_get_md(dev_t dev) +-{ +- struct mapped_device *md = dm_find_md(dev); +- +- if (md) +- dm_get(md); +- +- return md; +-} + EXPORT_SYMBOL_GPL(dm_get_md); + + void *dm_get_mdptr(struct mapped_device *md) +diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c +index cdd31c2a2a2b..b2965382d0ec 100644 +--- a/drivers/misc/mei/init.c ++++ b/drivers/misc/mei/init.c +@@ -275,6 +275,8 @@ void mei_stop(struct mei_device *dev) + + dev->dev_state = MEI_DEV_POWER_DOWN; + mei_reset(dev); ++ /* move device to disabled state unconditionally */ ++ dev->dev_state = MEI_DEV_DISABLED; + + mutex_unlock(&dev->device_lock); + +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index 07c942b6ae01..e8c21f911b6f 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -637,12 +637,15 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, + } /* else everything is zero */ + } + ++/* Neighbour code has some assumptions on HH_DATA_MOD alignment */ ++#define MACVTAP_RESERVE HH_DATA_OFF(ETH_HLEN) ++ + /* Get packet from user space buffer */ + static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, + const struct iovec *iv, unsigned long total_len, + size_t count, int noblock) + { +- int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN); ++ int good_linear = SKB_MAX_HEAD(MACVTAP_RESERVE); + struct sk_buff *skb; + struct macvlan_dev *vlan; + unsigned long len = total_len; +@@ -701,7 +704,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, + linear = vnet_hdr.hdr_len; + } + +- skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen, ++ skb = macvtap_alloc_skb(&q->sk, MACVTAP_RESERVE, copylen, + linear, noblock, &err); + if (!skb) + goto err; +diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c +index 76d96b9ebcdb..1d568788c3e3 100644 +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -194,6 +194,25 @@ static inline unsigned int phy_find_valid(unsigned int idx, u32 features) + } + + /** ++ * phy_check_valid - check if there is a valid PHY setting which matches ++ * speed, duplex, and feature mask ++ * @speed: speed to match ++ * @duplex: duplex to match ++ * @features: A mask of the valid settings ++ * ++ * Description: Returns true if there is a valid setting, false otherwise. ++ */ ++static inline bool phy_check_valid(int speed, int duplex, u32 features) ++{ ++ unsigned int idx; ++ ++ idx = phy_find_valid(phy_find_setting(speed, duplex), features); ++ ++ return settings[idx].speed == speed && settings[idx].duplex == duplex && ++ (settings[idx].setting & features); ++} ++ ++/** + * phy_sanitize_settings - make sure the PHY is set to supported speed and duplex + * @phydev: the target phy_device struct + * +@@ -955,7 +974,6 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable) + int eee_lp, eee_cap, eee_adv; + u32 lp, cap, adv; + int status; +- unsigned int idx; + + /* Read phy status to properly get the right settings */ + status = phy_read_status(phydev); +@@ -987,8 +1005,7 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable) + + adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv); + lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp); +- idx = phy_find_setting(phydev->speed, phydev->duplex); +- if (!(lp & adv & settings[idx].setting)) ++ if (!phy_check_valid(phydev->speed, phydev->duplex, lp & adv)) + return -EPROTONOSUPPORT; + + if (clk_stop_enable) { +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 32efe8371ff8..c28e2dafb3f0 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -42,9 +42,7 @@ + + static struct team_port *team_port_get_rcu(const struct net_device *dev) + { +- struct team_port *port = rcu_dereference(dev->rx_handler_data); +- +- return team_port_exists(dev) ? port : NULL; ++ return rcu_dereference(dev->rx_handler_data); + } + + static struct team_port *team_port_get_rtnl(const struct net_device *dev) +@@ -1725,11 +1723,11 @@ static int team_set_mac_address(struct net_device *dev, void *p) + if (dev->type == ARPHRD_ETHER && !is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); +- rcu_read_lock(); +- list_for_each_entry_rcu(port, &team->port_list, list) ++ mutex_lock(&team->lock); ++ list_for_each_entry(port, &team->port_list, list) + if (team->ops.port_change_dev_addr) + team->ops.port_change_dev_addr(team, port); +- rcu_read_unlock(); ++ mutex_unlock(&team->lock); + return 0; + } + +diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c +index 3d18bb0eee85..1bfe0fcaccf5 100644 +--- a/drivers/net/usb/plusb.c ++++ b/drivers/net/usb/plusb.c +@@ -134,6 +134,11 @@ static const struct usb_device_id products [] = { + }, { + USB_DEVICE(0x050d, 0x258a), /* Belkin F5U258/F5U279 (PL-25A1) */ + .driver_info = (unsigned long) &prolific_info, ++}, { ++ USB_DEVICE(0x3923, 0x7825), /* National Instruments USB ++ * Host-to-Host Cable ++ */ ++ .driver_info = (unsigned long) &prolific_info, + }, + + { }, // END +diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c +index a3399c4f13a9..b9b651ea9851 100644 +--- a/drivers/net/wireless/ath/ath5k/reset.c ++++ b/drivers/net/wireless/ath/ath5k/reset.c +@@ -478,7 +478,7 @@ ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) + regval = ioread32(reg); + iowrite32(regval | val, reg); + regval = ioread32(reg); +- usleep_range(100, 150); ++ udelay(100); /* NB: should be atomic */ + + /* Bring BB/MAC out of reset */ + iowrite32(regval & ~val, reg); +diff --git a/drivers/net/wireless/ath/ath6kl/hif.h b/drivers/net/wireless/ath/ath6kl/hif.h +index 61f6b21fb0ae..dc6bd8cd9b83 100644 +--- a/drivers/net/wireless/ath/ath6kl/hif.h ++++ b/drivers/net/wireless/ath/ath6kl/hif.h +@@ -197,9 +197,9 @@ struct hif_scatter_req { + /* bounce buffer for upper layers to copy to/from */ + u8 *virt_dma_buf; + +- struct hif_scatter_item scat_list[1]; +- + u32 scat_q_depth; ++ ++ struct hif_scatter_item scat_list[0]; + }; + + struct ath6kl_irq_proc_registers { +diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c +index 7126bdd4236c..6bf15a331714 100644 +--- a/drivers/net/wireless/ath/ath6kl/sdio.c ++++ b/drivers/net/wireless/ath/ath6kl/sdio.c +@@ -348,7 +348,7 @@ static int ath6kl_sdio_alloc_prep_scat_req(struct ath6kl_sdio *ar_sdio, + int i, scat_req_sz, scat_list_sz, size; + u8 *virt_buf; + +- scat_list_sz = (n_scat_entry - 1) * sizeof(struct hif_scatter_item); ++ scat_list_sz = n_scat_entry * sizeof(struct hif_scatter_item); + scat_req_sz = sizeof(*s_req) + scat_list_sz; + + if (!virt_scat) +diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c +index 5642a9b250c2..953bd0bfdf0d 100644 +--- a/drivers/scsi/be2iscsi/be_main.c ++++ b/drivers/scsi/be2iscsi/be_main.c +@@ -581,7 +581,6 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) + "beiscsi_hba_alloc - iscsi_host_alloc failed\n"); + return NULL; + } +- shost->dma_boundary = pcidev->dma_mask; + shost->max_id = BE2_MAX_SESSIONS; + shost->max_channel = 0; + shost->max_cmd_len = BEISCSI_MAX_CMD_LEN; +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index df5e961484e1..eb81c98386b9 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -522,7 +522,7 @@ static ssize_t + sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp) + { + sg_io_hdr_t *hp = &srp->header; +- int err = 0; ++ int err = 0, err2; + int len; + + if (count < SZ_SG_IO_HDR) { +@@ -551,8 +551,8 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp) + goto err_out; + } + err_out: +- err = sg_finish_rem_req(srp); +- return (0 == err) ? count : err; ++ err2 = sg_finish_rem_req(srp); ++ return err ? : err2 ? : count; + } + + static ssize_t +diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c +index 1e9da405d833..528781049ad5 100644 +--- a/drivers/staging/comedi/comedi_compat32.c ++++ b/drivers/staging/comedi/comedi_compat32.c +@@ -262,7 +262,7 @@ static int compat_cmd(struct file *file, unsigned long arg) + { + struct comedi_cmd __user *cmd; + struct comedi32_cmd_struct __user *cmd32; +- int rc; ++ int rc, err; + + cmd32 = compat_ptr(arg); + cmd = compat_alloc_user_space(sizeof(*cmd)); +@@ -271,7 +271,15 @@ static int compat_cmd(struct file *file, unsigned long arg) + if (rc) + return rc; + +- return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd); ++ rc = translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd); ++ if (rc == -EAGAIN) { ++ /* Special case: copy cmd back to user. */ ++ err = put_compat_cmd(cmd32, cmd); ++ if (err) ++ rc = err; ++ } ++ ++ return rc; + } + + /* Handle 32-bit COMEDI_CMDTEST ioctl. */ +diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c +index 4fff1738e3f8..3d1cb5b0a956 100644 +--- a/drivers/staging/comedi/drivers/cb_pcidas64.c ++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c +@@ -441,6 +441,29 @@ static const struct comedi_lrange ai_ranges_64xx = { + } + }; + ++static const uint8_t ai_range_code_64xx[8] = { ++ 0x0, 0x1, 0x2, 0x3, /* bipolar 10, 5, 2,5, 1.25 */ ++ 0x8, 0x9, 0xa, 0xb /* unipolar 10, 5, 2.5, 1.25 */ ++}; ++ ++/* analog input ranges for 64-Mx boards */ ++static const struct comedi_lrange ai_ranges_64_mx = { ++ 7, { ++ BIP_RANGE(5), ++ BIP_RANGE(2.5), ++ BIP_RANGE(1.25), ++ BIP_RANGE(0.625), ++ UNI_RANGE(5), ++ UNI_RANGE(2.5), ++ UNI_RANGE(1.25) ++ } ++}; ++ ++static const uint8_t ai_range_code_64_mx[7] = { ++ 0x0, 0x1, 0x2, 0x3, /* bipolar 5, 2.5, 1.25, 0.625 */ ++ 0x9, 0xa, 0xb /* unipolar 5, 2.5, 1.25 */ ++}; ++ + /* analog input ranges for 60xx boards */ + static const struct comedi_lrange ai_ranges_60xx = { + 4, { +@@ -451,6 +474,10 @@ static const struct comedi_lrange ai_ranges_60xx = { + } + }; + ++static const uint8_t ai_range_code_60xx[4] = { ++ 0x0, 0x1, 0x4, 0x7 /* bipolar 10, 5, 0.5, 0.05 */ ++}; ++ + /* analog input ranges for 6030, etc boards */ + static const struct comedi_lrange ai_ranges_6030 = { + 14, { +@@ -471,6 +498,11 @@ static const struct comedi_lrange ai_ranges_6030 = { + } + }; + ++static const uint8_t ai_range_code_6030[14] = { ++ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, /* bip 10, 5, 2, 1, 0.5, 0.2, 0.1 */ ++ 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* uni 10, 5, 2, 1, 0.5, 0.2, 0.1 */ ++}; ++ + /* analog input ranges for 6052, etc boards */ + static const struct comedi_lrange ai_ranges_6052 = { + 15, { +@@ -492,6 +524,11 @@ static const struct comedi_lrange ai_ranges_6052 = { + } + }; + ++static const uint8_t ai_range_code_6052[15] = { ++ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, /* bipolar 10 ... 0.05 */ ++ 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* unipolar 10 ... 0.1 */ ++}; ++ + /* analog input ranges for 4020 board */ + static const struct comedi_lrange ai_ranges_4020 = { + 2, { +@@ -595,6 +632,7 @@ struct pcidas64_board { + int ai_bits; /* analog input resolution */ + int ai_speed; /* fastest conversion period in ns */ + const struct comedi_lrange *ai_range_table; ++ const uint8_t *ai_range_code; + int ao_nchan; /* number of analog out channels */ + int ao_bits; /* analog output resolution */ + int ao_scan_speed; /* analog output scan speed */ +@@ -653,6 +691,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, ++ .ai_range_code = ai_range_code_64xx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, +@@ -668,6 +707,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, ++ .ai_range_code = ai_range_code_64xx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, +@@ -682,7 +722,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_bits = 16, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, +@@ -697,7 +738,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_bits = 16, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, +@@ -712,7 +754,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_bits = 16, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, +@@ -727,6 +770,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_bits = 16, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -742,6 +786,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -756,6 +801,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -771,6 +817,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -786,6 +833,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 10000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, ++ .ai_range_code = ai_range_code_6030, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -801,6 +849,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 10000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, ++ .ai_range_code = ai_range_code_6030, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -814,6 +863,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 0, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, ++ .ai_range_code = ai_range_code_6030, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, +@@ -825,6 +875,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 0, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, ++ .ai_range_code = ai_range_code_6030, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, +@@ -837,6 +888,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 0, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, +@@ -850,6 +902,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -865,6 +918,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -880,6 +934,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 1000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, ++ .ai_range_code = ai_range_code_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -895,6 +950,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 3333, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, ++ .ai_range_code = ai_range_code_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -910,6 +966,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 1000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, ++ .ai_range_code = ai_range_code_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -925,6 +982,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 1000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, ++ .ai_range_code = ai_range_code_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -959,6 +1017,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, ++ .ai_range_code = ai_range_code_64xx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -970,7 +1029,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 0, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -982,7 +1042,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 0, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -994,7 +1055,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 0, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -1006,7 +1068,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 2, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -1018,7 +1081,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 2, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -1030,7 +1094,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 2, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -1127,45 +1192,8 @@ static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev, + unsigned int range_index) + { + const struct pcidas64_board *thisboard = comedi_board(dev); +- const struct comedi_krange *range = +- &thisboard->ai_range_table->range[range_index]; +- unsigned int bits = 0; + +- switch (range->max) { +- case 10000000: +- bits = 0x000; +- break; +- case 5000000: +- bits = 0x100; +- break; +- case 2000000: +- case 2500000: +- bits = 0x200; +- break; +- case 1000000: +- case 1250000: +- bits = 0x300; +- break; +- case 500000: +- bits = 0x400; +- break; +- case 200000: +- case 250000: +- bits = 0x500; +- break; +- case 100000: +- bits = 0x600; +- break; +- case 50000: +- bits = 0x700; +- break; +- default: +- comedi_error(dev, "bug! in ai_range_bits_6xxx"); +- break; +- } +- if (range->min == 0) +- bits += 0x900; +- return bits; ++ return thisboard->ai_range_code[range_index] << 8; + } + + static unsigned int hw_revision(const struct comedi_device *dev, +diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c +index 9ec1df9cff95..be89260c23a6 100644 +--- a/drivers/staging/iio/adc/mxs-lradc.c ++++ b/drivers/staging/iio/adc/mxs-lradc.c +@@ -214,11 +214,17 @@ struct mxs_lradc { + unsigned long is_divided; + + /* +- * Touchscreen LRADC channels receives a private slot in the CTRL4 +- * register, the slot #7. Therefore only 7 slots instead of 8 in the +- * CTRL4 register can be mapped to LRADC channels when using the +- * touchscreen. +- * ++ * When the touchscreen is enabled, we give it two private virtual ++ * channels: #6 and #7. This means that only 6 virtual channels (instead ++ * of 8) will be available for buffered capture. ++ */ ++#define TOUCHSCREEN_VCHANNEL1 7 ++#define TOUCHSCREEN_VCHANNEL2 6 ++#define BUFFER_VCHANS_LIMITED 0x3f ++#define BUFFER_VCHANS_ALL 0xff ++ u8 buffer_vchans; ++ ++ /* + * Furthermore, certain LRADC channels are shared between touchscreen + * and/or touch-buttons and generic LRADC block. Therefore when using + * either of these, these channels are not available for the regular +@@ -342,6 +348,9 @@ struct mxs_lradc { + #define LRADC_CTRL4 0x140 + #define LRADC_CTRL4_LRADCSELECT_MASK(n) (0xf << ((n) * 4)) + #define LRADC_CTRL4_LRADCSELECT_OFFSET(n) ((n) * 4) ++#define LRADC_CTRL4_LRADCSELECT(n, x) \ ++ (((x) << LRADC_CTRL4_LRADCSELECT_OFFSET(n)) & \ ++ LRADC_CTRL4_LRADCSELECT_MASK(n)) + + #define LRADC_RESOLUTION 12 + #define LRADC_SINGLE_SAMPLE_MASK ((1 << LRADC_RESOLUTION) - 1) +@@ -423,6 +432,14 @@ static bool mxs_lradc_check_touch_event(struct mxs_lradc *lradc) + LRADC_STATUS_TOUCH_DETECT_RAW); + } + ++static void mxs_lradc_map_channel(struct mxs_lradc *lradc, unsigned vch, ++ unsigned ch) ++{ ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(vch), ++ LRADC_CTRL4); ++ mxs_lradc_reg_set(lradc, LRADC_CTRL4_LRADCSELECT(vch, ch), LRADC_CTRL4); ++} ++ + static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) + { + /* +@@ -450,12 +467,8 @@ static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) + LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), + LRADC_DELAY(3)); + +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) | +- LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) | +- LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch), LRADC_CTRL1); + +- /* wake us again, when the complete conversion is done */ +- mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1); + /* + * after changing the touchscreen plates setting + * the signals need some initial time to settle. Start the +@@ -508,12 +521,8 @@ static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1, + LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), + LRADC_DELAY(3)); + +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) | +- LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) | +- LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch2), LRADC_CTRL1); + +- /* wake us again, when the conversions are done */ +- mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1); + /* + * after changing the touchscreen plates setting + * the signals need some initial time to settle. Start the +@@ -578,36 +587,6 @@ static unsigned mxs_lradc_read_ts_pressure(struct mxs_lradc *lradc, + #define TS_CH_XM 4 + #define TS_CH_YM 5 + +-static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc) +-{ +- u32 reg; +- int val; +- +- reg = readl(lradc->base + LRADC_CTRL1); +- +- /* only channels 3 to 5 are of interest here */ +- if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YP)) { +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YP) | +- LRADC_CTRL1_LRADC_IRQ(TS_CH_YP), LRADC_CTRL1); +- val = mxs_lradc_read_raw_channel(lradc, TS_CH_YP); +- } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_XM)) { +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_XM) | +- LRADC_CTRL1_LRADC_IRQ(TS_CH_XM), LRADC_CTRL1); +- val = mxs_lradc_read_raw_channel(lradc, TS_CH_XM); +- } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YM)) { +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YM) | +- LRADC_CTRL1_LRADC_IRQ(TS_CH_YM), LRADC_CTRL1); +- val = mxs_lradc_read_raw_channel(lradc, TS_CH_YM); +- } else { +- return -EIO; +- } +- +- mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); +- mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); +- +- return val; +-} +- + /* + * YP(open)--+-------------+ + * | |--+ +@@ -651,7 +630,8 @@ static void mxs_lradc_prepare_x_pos(struct mxs_lradc *lradc) + mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0); + + lradc->cur_plate = LRADC_SAMPLE_X; +- mxs_lradc_setup_ts_channel(lradc, TS_CH_YP); ++ mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YP); ++ mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1); + } + + /* +@@ -672,7 +652,8 @@ static void mxs_lradc_prepare_y_pos(struct mxs_lradc *lradc) + mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0); + + lradc->cur_plate = LRADC_SAMPLE_Y; +- mxs_lradc_setup_ts_channel(lradc, TS_CH_XM); ++ mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_XM); ++ mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1); + } + + /* +@@ -693,7 +674,10 @@ static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc) + mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0); + + lradc->cur_plate = LRADC_SAMPLE_PRESSURE; +- mxs_lradc_setup_ts_pressure(lradc, TS_CH_XP, TS_CH_YM); ++ mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YM); ++ mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL2, TS_CH_XP); ++ mxs_lradc_setup_ts_pressure(lradc, TOUCHSCREEN_VCHANNEL2, ++ TOUCHSCREEN_VCHANNEL1); + } + + static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) +@@ -706,6 +690,19 @@ static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) + mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); + } + ++static void mxs_lradc_start_touch_event(struct mxs_lradc *lradc) ++{ ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, ++ LRADC_CTRL1); ++ mxs_lradc_reg_set(lradc, ++ LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1); ++ /* ++ * start with the Y-pos, because it uses nearly the same plate ++ * settings like the touch detection ++ */ ++ mxs_lradc_prepare_y_pos(lradc); ++} ++ + static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc) + { + input_report_abs(lradc->ts_input, ABS_X, lradc->ts_x_pos); +@@ -723,10 +720,12 @@ static void mxs_lradc_complete_touch_event(struct mxs_lradc *lradc) + * start a dummy conversion to burn time to settle the signals + * note: we are not interested in the conversion's value + */ +- mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(5)); +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); +- mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(5), LRADC_CTRL1); +- mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << 5) | ++ mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(TOUCHSCREEN_VCHANNEL1)); ++ mxs_lradc_reg_clear(lradc, ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) | ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1); ++ mxs_lradc_reg_wrt(lradc, ++ LRADC_DELAY_TRIGGER(1 << TOUCHSCREEN_VCHANNEL1) | + LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10), /* waste 5 ms */ + LRADC_DELAY(2)); + } +@@ -758,59 +757,45 @@ static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid) + + /* if it is released, wait for the next touch via IRQ */ + lradc->cur_plate = LRADC_TOUCH; +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1); ++ mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); ++ mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ | ++ LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) | ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1); + mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); + } + + /* touchscreen's state machine */ + static void mxs_lradc_handle_touch(struct mxs_lradc *lradc) + { +- int val; +- + switch (lradc->cur_plate) { + case LRADC_TOUCH: +- /* +- * start with the Y-pos, because it uses nearly the same plate +- * settings like the touch detection +- */ +- if (mxs_lradc_check_touch_event(lradc)) { +- mxs_lradc_reg_clear(lradc, +- LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, +- LRADC_CTRL1); +- mxs_lradc_prepare_y_pos(lradc); +- } ++ if (mxs_lradc_check_touch_event(lradc)) ++ mxs_lradc_start_touch_event(lradc); + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, + LRADC_CTRL1); + return; + + case LRADC_SAMPLE_Y: +- val = mxs_lradc_read_ts_channel(lradc); +- if (val < 0) { +- mxs_lradc_enable_touch_detection(lradc); /* re-start */ +- return; +- } +- lradc->ts_y_pos = val; ++ lradc->ts_y_pos = mxs_lradc_read_raw_channel(lradc, ++ TOUCHSCREEN_VCHANNEL1); + mxs_lradc_prepare_x_pos(lradc); + return; + + case LRADC_SAMPLE_X: +- val = mxs_lradc_read_ts_channel(lradc); +- if (val < 0) { +- mxs_lradc_enable_touch_detection(lradc); /* re-start */ +- return; +- } +- lradc->ts_x_pos = val; ++ lradc->ts_x_pos = mxs_lradc_read_raw_channel(lradc, ++ TOUCHSCREEN_VCHANNEL1); + mxs_lradc_prepare_pressure(lradc); + return; + + case LRADC_SAMPLE_PRESSURE: +- lradc->ts_pressure = +- mxs_lradc_read_ts_pressure(lradc, TS_CH_XP, TS_CH_YM); ++ lradc->ts_pressure = mxs_lradc_read_ts_pressure(lradc, ++ TOUCHSCREEN_VCHANNEL2, ++ TOUCHSCREEN_VCHANNEL1); + mxs_lradc_complete_touch_event(lradc); + return; + + case LRADC_SAMPLE_VALID: +- val = mxs_lradc_read_ts_channel(lradc); /* ignore the value */ + mxs_lradc_finish_touch_event(lradc, 1); + break; + } +@@ -842,9 +827,9 @@ static int mxs_lradc_read_single(struct iio_dev *iio_dev, int chan, int *val) + * used if doing raw sampling. + */ + if (lradc->soc == IMX28_LRADC) +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), + LRADC_CTRL1); +- mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); ++ mxs_lradc_reg_clear(lradc, 0x1, LRADC_CTRL0); + + /* Enable / disable the divider per requirement */ + if (test_bit(chan, &lradc->is_divided)) +@@ -1091,9 +1076,8 @@ static void mxs_lradc_disable_ts(struct mxs_lradc *lradc) + { + /* stop all interrupts from firing */ + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN | +- LRADC_CTRL1_LRADC_IRQ_EN(2) | LRADC_CTRL1_LRADC_IRQ_EN(3) | +- LRADC_CTRL1_LRADC_IRQ_EN(4) | LRADC_CTRL1_LRADC_IRQ_EN(5), +- LRADC_CTRL1); ++ LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) | ++ LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1); + + /* Power-down touchscreen touch-detect circuitry. */ + mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); +@@ -1159,25 +1143,31 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) + struct iio_dev *iio = data; + struct mxs_lradc *lradc = iio_priv(iio); + unsigned long reg = readl(lradc->base + LRADC_CTRL1); ++ uint32_t clr_irq = mxs_lradc_irq_mask(lradc); + const uint32_t ts_irq_mask = + LRADC_CTRL1_TOUCH_DETECT_IRQ | +- LRADC_CTRL1_LRADC_IRQ(2) | +- LRADC_CTRL1_LRADC_IRQ(3) | +- LRADC_CTRL1_LRADC_IRQ(4) | +- LRADC_CTRL1_LRADC_IRQ(5); ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) | ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2); + + if (!(reg & mxs_lradc_irq_mask(lradc))) + return IRQ_NONE; + +- if (lradc->use_touchscreen && (reg & ts_irq_mask)) ++ if (lradc->use_touchscreen && (reg & ts_irq_mask)) { + mxs_lradc_handle_touch(lradc); ++ /* Make sure we don't clear the next conversion's interrupt. */ ++ clr_irq &= ~(LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) | ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2)); ++ } + + if (iio_buffer_enabled(iio)) +- iio_trigger_poll(iio->trig, iio_get_time_ns()); +- else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) ++ if (iio_buffer_enabled(iio)) { ++ if (reg & lradc->buffer_vchans) ++ iio_trigger_poll(iio->trig, iio_get_time_ns()); ++ } else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) { + complete(&lradc->completion); ++ } + +- mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc), LRADC_CTRL1); ++ mxs_lradc_reg_clear(lradc, reg & clr_irq, LRADC_CTRL1); + + return IRQ_HANDLED; + } +@@ -1288,9 +1278,10 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio) + } + + if (lradc->soc == IMX28_LRADC) +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, +- LRADC_CTRL1); +- mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); ++ mxs_lradc_reg_clear(lradc, ++ lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET, ++ LRADC_CTRL1); ++ mxs_lradc_reg_clear(lradc, lradc->buffer_vchans, LRADC_CTRL0); + + for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) { + ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs); +@@ -1323,10 +1314,11 @@ static int mxs_lradc_buffer_postdisable(struct iio_dev *iio) + mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK | + LRADC_DELAY_KICK, LRADC_DELAY(0)); + +- mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); ++ mxs_lradc_reg_clear(lradc, lradc->buffer_vchans, LRADC_CTRL0); + if (lradc->soc == IMX28_LRADC) +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, +- LRADC_CTRL1); ++ mxs_lradc_reg_clear(lradc, ++ lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET, ++ LRADC_CTRL1); + + kfree(lradc->buffer); + mutex_unlock(&lradc->lock); +@@ -1352,7 +1344,7 @@ static bool mxs_lradc_validate_scan_mask(struct iio_dev *iio, + if (lradc->use_touchbutton) + rsvd_chans++; + if (lradc->use_touchscreen) +- rsvd_chans++; ++ rsvd_chans += 2; + + /* Test for attempts to map channels with special mode of operation. */ + if (bitmap_intersects(mask, &rsvd_mask, LRADC_MAX_TOTAL_CHANS)) +@@ -1412,6 +1404,13 @@ static const struct iio_chan_spec mxs_lradc_chan_spec[] = { + .channel = 8, + .scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,}, + }, ++ /* Hidden channel to keep indexes */ ++ { ++ .type = IIO_TEMP, ++ .indexed = 1, ++ .scan_index = -1, ++ .channel = 9, ++ }, + MXS_ADC_CHAN(10, IIO_VOLTAGE), /* VDDIO */ + MXS_ADC_CHAN(11, IIO_VOLTAGE), /* VTH */ + MXS_ADC_CHAN(12, IIO_VOLTAGE), /* VDDA */ +@@ -1563,6 +1562,11 @@ static int mxs_lradc_probe(struct platform_device *pdev) + + touch_ret = mxs_lradc_probe_touchscreen(lradc, node); + ++ if (touch_ret == 0) ++ lradc->buffer_vchans = BUFFER_VCHANS_LIMITED; ++ else ++ lradc->buffer_vchans = BUFFER_VCHANS_ALL; ++ + /* Grab all IRQ sources */ + for (i = 0; i < of_cfg->irq_count; i++) { + lradc->irq[i] = platform_get_irq(pdev, i); +diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c +index 1205dbd4f83d..0fccdcfd1015 100644 +--- a/drivers/target/target_core_pr.c ++++ b/drivers/target/target_core_pr.c +@@ -1877,8 +1877,8 @@ static int core_scsi3_update_aptpl_buf( + } + + if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { +- pr_err("Unable to update renaming" +- " APTPL metadata\n"); ++ pr_err("Unable to update renaming APTPL metadata," ++ " reallocating larger buffer\n"); + ret = -EMSGSIZE; + goto out; + } +@@ -1895,8 +1895,8 @@ static int core_scsi3_update_aptpl_buf( + lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count); + + if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { +- pr_err("Unable to update renaming" +- " APTPL metadata\n"); ++ pr_err("Unable to update renaming APTPL metadata," ++ " reallocating larger buffer\n"); + ret = -EMSGSIZE; + goto out; + } +@@ -1959,7 +1959,7 @@ static int __core_scsi3_write_aptpl_to_file( + static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, bool aptpl) + { + unsigned char *buf; +- int rc; ++ int rc, len = PR_APTPL_BUF_LEN; + + if (!aptpl) { + char *null_buf = "No Registrations or Reservations\n"; +@@ -1973,25 +1973,26 @@ static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, b + + return 0; + } +- +- buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL); ++retry: ++ buf = vzalloc(len); + if (!buf) + return TCM_OUT_OF_RESOURCES; + +- rc = core_scsi3_update_aptpl_buf(dev, buf, PR_APTPL_BUF_LEN); ++ rc = core_scsi3_update_aptpl_buf(dev, buf, len); + if (rc < 0) { +- kfree(buf); +- return TCM_OUT_OF_RESOURCES; ++ vfree(buf); ++ len *= 2; ++ goto retry; + } + + rc = __core_scsi3_write_aptpl_to_file(dev, buf); + if (rc != 0) { + pr_err("SPC-3 PR: Could not update APTPL\n"); +- kfree(buf); ++ vfree(buf); + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + dev->t10_pr.pr_aptpl_active = 1; +- kfree(buf); ++ vfree(buf); + pr_debug("SPC-3 PR: Set APTPL Bit Activated\n"); + return 0; + } +diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c +index 5216acd68b4b..68511e83486b 100644 +--- a/drivers/target/target_core_sbc.c ++++ b/drivers/target/target_core_sbc.c +@@ -266,6 +266,8 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb) + static sense_reason_t + sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops) + { ++ struct se_device *dev = cmd->se_dev; ++ sector_t end_lba = dev->transport->get_blocks(dev) + 1; + unsigned int sectors = sbc_get_write_same_sectors(cmd); + + if ((flags[0] & 0x04) || (flags[0] & 0x02)) { +@@ -279,6 +281,16 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o + sectors, cmd->se_dev->dev_attrib.max_write_same_len); + return TCM_INVALID_CDB_FIELD; + } ++ /* ++ * Sanity check for LBA wrap and request past end of device. ++ */ ++ if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) || ++ ((cmd->t_task_lba + sectors) > end_lba)) { ++ pr_err("WRITE_SAME exceeds last lba %llu (lba %llu, sectors %u)\n", ++ (unsigned long long)end_lba, cmd->t_task_lba, sectors); ++ return TCM_ADDRESS_OUT_OF_RANGE; ++ } ++ + /* We always have ANC_SUP == 0 so setting ANCHOR is always an error */ + if (flags[0] & 0x10) { + pr_warn("WRITE SAME with ANCHOR not supported\n"); +@@ -911,7 +923,8 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) + unsigned long long end_lba; + + end_lba = dev->transport->get_blocks(dev) + 1; +- if (cmd->t_task_lba + sectors > end_lba) { ++ if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) || ++ ((cmd->t_task_lba + sectors) > end_lba)) { + pr_err("cmd exceeds last lba %llu " + "(lba %llu, sectors %u)\n", + end_lba, cmd->t_task_lba, sectors); +diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c +index 25d07412e08e..39988fa91294 100644 +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -996,8 +996,8 @@ EXPORT_SYMBOL(start_tty); + /* We limit tty time update visibility to every 8 seconds or so. */ + static void tty_update_time(struct timespec *time) + { +- unsigned long sec = get_seconds() & ~7; +- if ((long)(sec - time->tv_sec) > 0) ++ unsigned long sec = get_seconds(); ++ if (abs(sec - time->tv_sec) & ~7) + time->tv_sec = sec; + } + +diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c +index 6fd60fece6b4..22da05d27009 100644 +--- a/drivers/tty/tty_ioctl.c ++++ b/drivers/tty/tty_ioctl.c +@@ -217,11 +217,17 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout) + #endif + if (!timeout) + timeout = MAX_SCHEDULE_TIMEOUT; ++ + if (wait_event_interruptible_timeout(tty->write_wait, +- !tty_chars_in_buffer(tty), timeout) >= 0) { +- if (tty->ops->wait_until_sent) +- tty->ops->wait_until_sent(tty, timeout); ++ !tty_chars_in_buffer(tty), timeout) < 0) { ++ return; + } ++ ++ if (timeout == MAX_SCHEDULE_TIMEOUT) ++ timeout = 0; ++ ++ if (tty->ops->wait_until_sent) ++ tty->ops->wait_until_sent(tty, timeout); + } + EXPORT_SYMBOL(tty_wait_until_sent); + +diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c +index 9ca77166d37e..45b7b96f9ed3 100644 +--- a/drivers/usb/core/devio.c ++++ b/drivers/usb/core/devio.c +@@ -501,6 +501,7 @@ static void async_completed(struct urb *urb) + as->status = urb->status; + signr = as->signr; + if (signr) { ++ memset(&sinfo, 0, sizeof(sinfo)); + sinfo.si_signo = as->signr; + sinfo.si_errno = as->status; + sinfo.si_code = SI_ASYNCIO; +@@ -2227,6 +2228,7 @@ static void usbdev_remove(struct usb_device *udev) + wake_up_all(&ps->wait); + list_del_init(&ps->list); + if (ps->discsignr) { ++ memset(&sinfo, 0, sizeof(sinfo)); + sinfo.si_signo = ps->discsignr; + sinfo.si_errno = EPIPE; + sinfo.si_code = SI_ASYNCIO; +diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c +index 2a6841c95b64..cfca302d3d88 100644 +--- a/drivers/usb/dwc3/dwc3-omap.c ++++ b/drivers/usb/dwc3/dwc3-omap.c +@@ -211,6 +211,18 @@ static void dwc3_omap_write_irq0_set(struct dwc3_omap *omap, u32 value) + omap->irq0_offset, value); + } + ++static void dwc3_omap_write_irqmisc_clr(struct dwc3_omap *omap, u32 value) ++{ ++ dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_CLR_MISC + ++ omap->irqmisc_offset, value); ++} ++ ++static void dwc3_omap_write_irq0_clr(struct dwc3_omap *omap, u32 value) ++{ ++ dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_CLR_0 - ++ omap->irq0_offset, value); ++} ++ + static void dwc3_omap_set_mailbox(struct dwc3_omap *omap, + enum omap_dwc3_vbus_id_status status) + { +@@ -351,9 +363,23 @@ static void dwc3_omap_enable_irqs(struct dwc3_omap *omap) + + static void dwc3_omap_disable_irqs(struct dwc3_omap *omap) + { ++ u32 reg; ++ + /* disable all IRQs */ +- dwc3_omap_write_irqmisc_set(omap, 0x00); +- dwc3_omap_write_irq0_set(omap, 0x00); ++ reg = USBOTGSS_IRQO_COREIRQ_ST; ++ dwc3_omap_write_irq0_clr(omap, reg); ++ ++ reg = (USBOTGSS_IRQMISC_OEVT | ++ USBOTGSS_IRQMISC_DRVVBUS_RISE | ++ USBOTGSS_IRQMISC_CHRGVBUS_RISE | ++ USBOTGSS_IRQMISC_DISCHRGVBUS_RISE | ++ USBOTGSS_IRQMISC_IDPULLUP_RISE | ++ USBOTGSS_IRQMISC_DRVVBUS_FALL | ++ USBOTGSS_IRQMISC_CHRGVBUS_FALL | ++ USBOTGSS_IRQMISC_DISCHRGVBUS_FALL | ++ USBOTGSS_IRQMISC_IDPULLUP_FALL); ++ ++ dwc3_omap_write_irqmisc_clr(omap, reg); + } + + static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32); +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index faa8b98954d9..a95eee8ddc38 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -2133,7 +2133,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, + if (event_trb != ep_ring->dequeue) { + /* The event was for the status stage */ + if (event_trb == td->last_trb) { +- if (td->urb->actual_length != 0) { ++ if (td->urb_length_set) { + /* Don't overwrite a previously set error code + */ + if ((*status == -EINPROGRESS || *status == 0) && +@@ -2147,7 +2147,13 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, + td->urb->transfer_buffer_length; + } + } else { +- /* Maybe the event was for the data stage? */ ++ /* ++ * Maybe the event was for the data stage? If so, update ++ * already the actual_length of the URB and flag it as ++ * set, so that it is not overwritten in the event for ++ * the last TRB. ++ */ ++ td->urb_length_set = true; + td->urb->actual_length = + td->urb->transfer_buffer_length - + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 96e9e780ccae..7225dd242bfa 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1,3 +1,4 @@ ++ + /* + * xHCI host controller driver + * +@@ -88,9 +89,10 @@ struct xhci_cap_regs { + #define HCS_IST(p) (((p) >> 0) & 0xf) + /* bits 4:7, max number of Event Ring segments */ + #define HCS_ERST_MAX(p) (((p) >> 4) & 0xf) ++/* bits 21:25 Hi 5 bits of Scratchpad buffers SW must allocate for the HW */ + /* bit 26 Scratchpad restore - for save/restore HW state - not used yet */ +-/* bits 27:31 number of Scratchpad buffers SW must allocate for the HW */ +-#define HCS_MAX_SCRATCHPAD(p) (((p) >> 27) & 0x1f) ++/* bits 27:31 Lo 5 bits of Scratchpad buffers SW must allocate for the HW */ ++#define HCS_MAX_SCRATCHPAD(p) ((((p) >> 16) & 0x3e0) | (((p) >> 27) & 0x1f)) + + /* HCSPARAMS3 - hcs_params3 - bitmasks */ + /* bits 0:7, Max U1 to U0 latency for the roothub ports */ +@@ -1289,6 +1291,8 @@ struct xhci_td { + struct xhci_segment *start_seg; + union xhci_trb *first_trb; + union xhci_trb *last_trb; ++ /* actual_length of the URB has already been set */ ++ bool urb_length_set; + }; + + /* xHCI command default timeout value */ +diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c +index 9374bd2aba20..6f91eb9ae81a 100644 +--- a/drivers/usb/serial/bus.c ++++ b/drivers/usb/serial/bus.c +@@ -51,6 +51,7 @@ static int usb_serial_device_probe(struct device *dev) + { + struct usb_serial_driver *driver; + struct usb_serial_port *port; ++ struct device *tty_dev; + int retval = 0; + int minor; + +@@ -75,12 +76,20 @@ static int usb_serial_device_probe(struct device *dev) + retval = device_create_file(dev, &dev_attr_port_number); + if (retval) { + if (driver->port_remove) +- retval = driver->port_remove(port); ++ driver->port_remove(port); + goto exit_with_autopm; + } + + minor = port->minor; +- tty_register_device(usb_serial_tty_driver, minor, dev); ++ tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev); ++ if (IS_ERR(tty_dev)) { ++ retval = PTR_ERR(tty_dev); ++ device_remove_file(dev, &dev_attr_port_number); ++ if (driver->port_remove) ++ driver->port_remove(port); ++ goto exit_with_autopm; ++ } ++ + dev_info(&port->serial->dev->dev, + "%s converter now attached to ttyUSB%d\n", + driver->description, minor); +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index a2d040971afe..8d114b9733ed 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -147,6 +147,8 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x166A, 0x0305) }, /* Clipsal C-5000CT2 C-Bus Spectrum Colour Touchscreen */ + { USB_DEVICE(0x166A, 0x0401) }, /* Clipsal L51xx C-Bus Architectural Dimmer */ + { USB_DEVICE(0x166A, 0x0101) }, /* Clipsal 5560884 C-Bus Multi-room Audio Matrix Switcher */ ++ { USB_DEVICE(0x16C0, 0x09B0) }, /* Lunatico Seletek */ ++ { USB_DEVICE(0x16C0, 0x09B1) }, /* Lunatico Seletek */ + { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ + { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */ + { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index debcdef4cbf0..923500595357 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -812,6 +812,8 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) }, ++ { USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID), ++ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID), +@@ -991,6 +993,23 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) }, + /* GE Healthcare devices */ + { USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) }, ++ /* Active Research (Actisense) devices */ ++ { USB_DEVICE(FTDI_VID, ACTISENSE_NDC_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_USG_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_NGT_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_NGW_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_D9AC_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_D9AD_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_D9AE_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_D9AF_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEAGAUGE_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASWITCH_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_NMEA2000_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ETHERNET_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_WIFI_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) }, + { } /* Terminating entry */ + }; + +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index e52409c9be99..56b1b55c4751 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -38,6 +38,9 @@ + + #define FTDI_LUMEL_PD12_PID 0x6002 + ++/* Cyber Cortex AV by Fabulous Silicon (http://fabuloussilicon.com) */ ++#define CYBER_CORTEX_AV_PID 0x8698 ++ + /* + * Marvell OpenRD Base, Client + * http://www.open-rd.org +@@ -1438,3 +1441,23 @@ + */ + #define GE_HEALTHCARE_VID 0x1901 + #define GE_HEALTHCARE_NEMO_TRACKER_PID 0x0015 ++ ++/* ++ * Active Research (Actisense) devices ++ */ ++#define ACTISENSE_NDC_PID 0xD9A8 /* NDC USB Serial Adapter */ ++#define ACTISENSE_USG_PID 0xD9A9 /* USG USB Serial Adapter */ ++#define ACTISENSE_NGT_PID 0xD9AA /* NGT NMEA2000 Interface */ ++#define ACTISENSE_NGW_PID 0xD9AB /* NGW NMEA2000 Gateway */ ++#define ACTISENSE_D9AC_PID 0xD9AC /* Actisense Reserved */ ++#define ACTISENSE_D9AD_PID 0xD9AD /* Actisense Reserved */ ++#define ACTISENSE_D9AE_PID 0xD9AE /* Actisense Reserved */ ++#define ACTISENSE_D9AF_PID 0xD9AF /* Actisense Reserved */ ++#define CHETCO_SEAGAUGE_PID 0xA548 /* SeaGauge USB Adapter */ ++#define CHETCO_SEASWITCH_PID 0xA549 /* SeaSwitch USB Adapter */ ++#define CHETCO_SEASMART_NMEA2000_PID 0xA54A /* SeaSmart NMEA2000 Gateway */ ++#define CHETCO_SEASMART_ETHERNET_PID 0xA54B /* SeaSmart Ethernet Gateway */ ++#define CHETCO_SEASMART_WIFI_PID 0xA5AC /* SeaSmart Wifi Gateway */ ++#define CHETCO_SEASMART_DISPLAY_PID 0xA5AD /* SeaSmart NMEA2000 Display */ ++#define CHETCO_SEASMART_LITE_PID 0xA5AE /* SeaSmart Lite USB Adapter */ ++#define CHETCO_SEASMART_ANALOG_PID 0xA5AF /* SeaSmart Analog Adapter */ +diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c +index b63ce023f96f..d6a197917ebd 100644 +--- a/drivers/usb/serial/generic.c ++++ b/drivers/usb/serial/generic.c +@@ -258,7 +258,8 @@ void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout) + * character or at least one jiffy. + */ + period = max_t(unsigned long, (10 * HZ / bps), 1); +- period = min_t(unsigned long, period, timeout); ++ if (timeout) ++ period = min_t(unsigned long, period, timeout); + + dev_dbg(&port->dev, "%s - timeout = %u ms, period = %u ms\n", + __func__, jiffies_to_msecs(timeout), +@@ -268,7 +269,7 @@ void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout) + schedule_timeout_interruptible(period); + if (signal_pending(current)) + break; +- if (time_after(jiffies, expire)) ++ if (timeout && time_after(jiffies, expire)) + break; + } + } +diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c +index ab1d690274ae..460a40669967 100644 +--- a/drivers/usb/serial/mxuport.c ++++ b/drivers/usb/serial/mxuport.c +@@ -1284,7 +1284,8 @@ static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port) + } + + /* Initial port termios */ +- mxuport_set_termios(tty, port, NULL); ++ if (tty) ++ mxuport_set_termios(tty, port, NULL); + + /* + * TODO: use RQ_VENDOR_GET_MSR, once we know what it +diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c +index 3182c0e68b42..e3399dc2453b 100644 +--- a/fs/autofs4/dev-ioctl.c ++++ b/fs/autofs4/dev-ioctl.c +@@ -95,7 +95,7 @@ static int check_dev_ioctl_version(int cmd, struct autofs_dev_ioctl *param) + */ + static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *in) + { +- struct autofs_dev_ioctl tmp; ++ struct autofs_dev_ioctl tmp, *res; + + if (copy_from_user(&tmp, in, sizeof(tmp))) + return ERR_PTR(-EFAULT); +@@ -103,7 +103,11 @@ static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *i + if (tmp.size < sizeof(tmp)) + return ERR_PTR(-EINVAL); + +- return memdup_user(in, tmp.size); ++ res = memdup_user(in, tmp.size); ++ if (!IS_ERR(res)) ++ res->size = tmp.size; ++ ++ return res; + } + + static inline void free_dev_ioctl(struct autofs_dev_ioctl *param) +diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c +index 279b06ef5522..0a841ddd6843 100644 +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -1774,22 +1774,10 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, + mutex_unlock(&inode->i_mutex); + + /* +- * we want to make sure fsync finds this change +- * but we haven't joined a transaction running right now. +- * +- * Later on, someone is sure to update the inode and get the +- * real transid recorded. +- * +- * We set last_trans now to the fs_info generation + 1, +- * this will either be one more than the running transaction +- * or the generation used for the next transaction if there isn't +- * one running right now. +- * + * We also have to set last_sub_trans to the current log transid, + * otherwise subsequent syncs to a file that's been synced in this + * transaction will appear to have already occured. + */ +- BTRFS_I(inode)->last_trans = root->fs_info->generation + 1; + BTRFS_I(inode)->last_sub_trans = root->log_transid; + if (num_written > 0) { + err = generic_write_sync(file, pos, num_written); +@@ -1892,25 +1880,37 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + atomic_inc(&root->log_batch); + + /* +- * check the transaction that last modified this inode +- * and see if its already been committed +- */ +- if (!BTRFS_I(inode)->last_trans) { +- mutex_unlock(&inode->i_mutex); +- goto out; +- } +- +- /* +- * if the last transaction that changed this file was before +- * the current transaction, we can bail out now without any +- * syncing ++ * If the last transaction that changed this file was before the current ++ * transaction and we have the full sync flag set in our inode, we can ++ * bail out now without any syncing. ++ * ++ * Note that we can't bail out if the full sync flag isn't set. This is ++ * because when the full sync flag is set we start all ordered extents ++ * and wait for them to fully complete - when they complete they update ++ * the inode's last_trans field through: ++ * ++ * btrfs_finish_ordered_io() -> ++ * btrfs_update_inode_fallback() -> ++ * btrfs_update_inode() -> ++ * btrfs_set_inode_last_trans() ++ * ++ * So we are sure that last_trans is up to date and can do this check to ++ * bail out safely. For the fast path, when the full sync flag is not ++ * set in our inode, we can not do it because we start only our ordered ++ * extents and don't wait for them to complete (that is when ++ * btrfs_finish_ordered_io runs), so here at this point their last_trans ++ * value might be less than or equals to fs_info->last_trans_committed, ++ * and setting a speculative last_trans for an inode when a buffered ++ * write is made (such as fs_info->generation + 1 for example) would not ++ * be reliable since after setting the value and before fsync is called ++ * any number of transactions can start and commit (transaction kthread ++ * commits the current transaction periodically), and a transaction ++ * commit does not start nor waits for ordered extents to complete. + */ + smp_mb(); + if (btrfs_inode_in_log(inode, root->fs_info->generation) || +- BTRFS_I(inode)->last_trans <= +- root->fs_info->last_trans_committed) { +- BTRFS_I(inode)->last_trans = 0; +- ++ (full_sync && BTRFS_I(inode)->last_trans <= ++ root->fs_info->last_trans_committed)) { + /* + * We'v had everything committed since the last time we were + * modified so clear this flag in case it was set for whatever +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index d68a7250f00b..653cdd85e0f2 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -6870,7 +6870,6 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, + ((BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) && + em->block_start != EXTENT_MAP_HOLE)) { + int type; +- int ret; + u64 block_start, orig_start, orig_block_len, ram_bytes; + + if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index aeb57b98c53f..a7f32bfdd5e7 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -979,7 +979,7 @@ again: + base = btrfs_item_ptr_offset(leaf, path->slots[0]); + + while (cur_offset < item_size) { +- extref = (struct btrfs_inode_extref *)base + cur_offset; ++ extref = (struct btrfs_inode_extref *)(base + cur_offset); + + victim_name_len = btrfs_inode_extref_name_len(leaf, extref); + +diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c +index 15761957cc3f..1ff8fe5dab0d 100644 +--- a/fs/debugfs/inode.c ++++ b/fs/debugfs/inode.c +@@ -245,10 +245,19 @@ static int debugfs_show_options(struct seq_file *m, struct dentry *root) + return 0; + } + ++static void debugfs_evict_inode(struct inode *inode) ++{ ++ truncate_inode_pages(&inode->i_data, 0); ++ clear_inode(inode); ++ if (S_ISLNK(inode->i_mode)) ++ kfree(inode->i_private); ++} ++ + static const struct super_operations debugfs_super_operations = { + .statfs = simple_statfs, + .remount_fs = debugfs_remount, + .show_options = debugfs_show_options, ++ .evict_inode = debugfs_evict_inode, + }; + + static int debug_fill_super(struct super_block *sb, void *data, int silent) +@@ -465,23 +474,14 @@ static int __debugfs_remove(struct dentry *dentry, struct dentry *parent) + int ret = 0; + + if (debugfs_positive(dentry)) { +- if (dentry->d_inode) { +- dget(dentry); +- switch (dentry->d_inode->i_mode & S_IFMT) { +- case S_IFDIR: +- ret = simple_rmdir(parent->d_inode, dentry); +- break; +- case S_IFLNK: +- kfree(dentry->d_inode->i_private); +- /* fall through */ +- default: +- simple_unlink(parent->d_inode, dentry); +- break; +- } +- if (!ret) +- d_delete(dentry); +- dput(dentry); +- } ++ dget(dentry); ++ if (S_ISDIR(dentry->d_inode->i_mode)) ++ ret = simple_rmdir(parent->d_inode, dentry); ++ else ++ simple_unlink(parent->d_inode, dentry); ++ if (!ret) ++ d_delete(dentry); ++ dput(dentry); + } + return ret; + } +diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c +index 3ed1be9aade3..2ea3537b8bde 100644 +--- a/fs/nfs/delegation.c ++++ b/fs/nfs/delegation.c +@@ -161,8 +161,8 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, + &delegation->flags); + NFS_I(inode)->delegation_state = delegation->type; + spin_unlock(&delegation->lock); +- put_rpccred(oldcred); + rcu_read_unlock(); ++ put_rpccred(oldcred); + trace_nfs4_reclaim_delegation(inode, res->delegation_type); + } else { + /* We appear to have raced with a delegation return. */ +diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c +index b2e3ff347620..ecdbae19a766 100644 +--- a/fs/nilfs2/btree.c ++++ b/fs/nilfs2/btree.c +@@ -31,6 +31,8 @@ + #include "alloc.h" + #include "dat.h" + ++static void __nilfs_btree_init(struct nilfs_bmap *bmap); ++ + static struct nilfs_btree_path *nilfs_btree_alloc_path(void) + { + struct nilfs_btree_path *path; +@@ -368,6 +370,34 @@ static int nilfs_btree_node_broken(const struct nilfs_btree_node *node, + return ret; + } + ++/** ++ * nilfs_btree_root_broken - verify consistency of btree root node ++ * @node: btree root node to be examined ++ * @ino: inode number ++ * ++ * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned. ++ */ ++static int nilfs_btree_root_broken(const struct nilfs_btree_node *node, ++ unsigned long ino) ++{ ++ int level, flags, nchildren; ++ int ret = 0; ++ ++ level = nilfs_btree_node_get_level(node); ++ flags = nilfs_btree_node_get_flags(node); ++ nchildren = nilfs_btree_node_get_nchildren(node); ++ ++ if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN || ++ level > NILFS_BTREE_LEVEL_MAX || ++ nchildren < 0 || ++ nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) { ++ pr_crit("NILFS: bad btree root (inode number=%lu): level = %d, flags = 0x%x, nchildren = %d\n", ++ ino, level, flags, nchildren); ++ ret = 1; ++ } ++ return ret; ++} ++ + int nilfs_btree_broken_node_block(struct buffer_head *bh) + { + int ret; +@@ -1713,7 +1743,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *btree, + + /* convert and insert */ + dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL; +- nilfs_btree_init(btree); ++ __nilfs_btree_init(btree); + if (nreq != NULL) { + nilfs_bmap_commit_alloc_ptr(btree, dreq, dat); + nilfs_bmap_commit_alloc_ptr(btree, nreq, dat); +@@ -2294,12 +2324,23 @@ static const struct nilfs_bmap_operations nilfs_btree_ops_gc = { + .bop_gather_data = NULL, + }; + +-int nilfs_btree_init(struct nilfs_bmap *bmap) ++static void __nilfs_btree_init(struct nilfs_bmap *bmap) + { + bmap->b_ops = &nilfs_btree_ops; + bmap->b_nchildren_per_block = + NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap)); +- return 0; ++} ++ ++int nilfs_btree_init(struct nilfs_bmap *bmap) ++{ ++ int ret = 0; ++ ++ __nilfs_btree_init(bmap); ++ ++ if (nilfs_btree_root_broken(nilfs_btree_get_root(bmap), ++ bmap->b_inode->i_ino)) ++ ret = -EIO; ++ return ret; + } + + void nilfs_btree_init_gc(struct nilfs_bmap *bmap) +diff --git a/fs/proc/generic.c b/fs/proc/generic.c +index b7f268eb5f45..2e2d9d5d78d9 100644 +--- a/fs/proc/generic.c ++++ b/fs/proc/generic.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -162,17 +161,6 @@ void proc_free_inum(unsigned int inum) + spin_unlock_irqrestore(&proc_inum_lock, flags); + } + +-static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd) +-{ +- nd_set_link(nd, __PDE_DATA(dentry->d_inode)); +- return NULL; +-} +- +-static const struct inode_operations proc_link_inode_operations = { +- .readlink = generic_readlink, +- .follow_link = proc_follow_link, +-}; +- + /* + * Don't create negative dentries here, return -ENOENT by hand + * instead. +diff --git a/fs/proc/inode.c b/fs/proc/inode.c +index 124fc43c7090..2f2815f3176e 100644 +--- a/fs/proc/inode.c ++++ b/fs/proc/inode.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + #include + +@@ -401,6 +402,26 @@ static const struct file_operations proc_reg_file_ops_no_compat = { + }; + #endif + ++static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd) ++{ ++ struct proc_dir_entry *pde = PDE(dentry->d_inode); ++ if (unlikely(!use_pde(pde))) ++ return ERR_PTR(-EINVAL); ++ nd_set_link(nd, pde->data); ++ return pde; ++} ++ ++static void proc_put_link(struct dentry *dentry, struct nameidata *nd, void *p) ++{ ++ unuse_pde(p); ++} ++ ++const struct inode_operations proc_link_inode_operations = { ++ .readlink = generic_readlink, ++ .follow_link = proc_follow_link, ++ .put_link = proc_put_link, ++}; ++ + struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) + { + struct inode *inode = new_inode_pseudo(sb); +diff --git a/fs/proc/internal.h b/fs/proc/internal.h +index 651d09a11dde..8b8ca1db6316 100644 +--- a/fs/proc/internal.h ++++ b/fs/proc/internal.h +@@ -202,6 +202,7 @@ struct pde_opener { + int closing; + struct completion *c; + }; ++extern const struct inode_operations proc_link_inode_operations; + + extern const struct inode_operations proc_pid_link_inode_operations; + +diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h +index 1772fadcff62..349325404add 100644 +--- a/include/target/target_core_base.h ++++ b/include/target/target_core_base.h +@@ -407,7 +407,7 @@ struct t10_reservation { + /* Activate Persistence across Target Power Loss enabled + * for SCSI device */ + int pr_aptpl_active; +-#define PR_APTPL_BUF_LEN 8192 ++#define PR_APTPL_BUF_LEN 262144 + u32 pr_generation; + spinlock_t registration_lock; + spinlock_t aptpl_reg_lock; +diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h +index aece1346ceb7..4ad10baecd4d 100644 +--- a/include/trace/events/kmem.h ++++ b/include/trace/events/kmem.h +@@ -268,11 +268,11 @@ TRACE_EVENT(mm_page_alloc_extfrag, + + TP_PROTO(struct page *page, + int alloc_order, int fallback_order, +- int alloc_migratetype, int fallback_migratetype, int new_migratetype), ++ int alloc_migratetype, int fallback_migratetype), + + TP_ARGS(page, + alloc_order, fallback_order, +- alloc_migratetype, fallback_migratetype, new_migratetype), ++ alloc_migratetype, fallback_migratetype), + + TP_STRUCT__entry( + __field( struct page *, page ) +@@ -289,7 +289,8 @@ TRACE_EVENT(mm_page_alloc_extfrag, + __entry->fallback_order = fallback_order; + __entry->alloc_migratetype = alloc_migratetype; + __entry->fallback_migratetype = fallback_migratetype; +- __entry->change_ownership = (new_migratetype == alloc_migratetype); ++ __entry->change_ownership = (alloc_migratetype == ++ get_pageblock_migratetype(page)); + ), + + TP_printk("page=%p pfn=%lu alloc_order=%d fallback_order=%d pageblock_order=%d alloc_migratetype=%d fallback_migratetype=%d fragmenting=%d change_ownership=%d", +diff --git a/mm/compaction.c b/mm/compaction.c +index 4229fc22a477..a522208bb8ea 100644 +--- a/mm/compaction.c ++++ b/mm/compaction.c +@@ -937,7 +937,7 @@ static int compact_finished(struct zone *zone, + return COMPACT_PARTIAL; + + /* Job done if allocation would set block type */ +- if (cc->order >= pageblock_order && area->nr_free) ++ if (order >= pageblock_order && area->nr_free) + return COMPACT_PARTIAL; + } + +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 472259b00618..c3e8660cb616 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -2488,9 +2488,10 @@ again: + goto unlock; + + /* +- * HWPoisoned hugepage is already unmapped and dropped reference ++ * Migrating hugepage or HWPoisoned hugepage is already ++ * unmapped and its refcount is dropped, so just clear pte here. + */ +- if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) { ++ if (unlikely(!pte_present(pte))) { + huge_pte_clear(mm, address, ptep); + goto unlock; + } +@@ -3163,7 +3164,26 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma, + spin_unlock(ptl); + continue; + } +- if (!huge_pte_none(huge_ptep_get(ptep))) { ++ pte = huge_ptep_get(ptep); ++ if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) { ++ spin_unlock(ptl); ++ continue; ++ } ++ if (unlikely(is_hugetlb_entry_migration(pte))) { ++ swp_entry_t entry = pte_to_swp_entry(pte); ++ ++ if (is_write_migration_entry(entry)) { ++ pte_t newpte; ++ ++ make_migration_entry_read(&entry); ++ newpte = swp_entry_to_pte(entry); ++ set_huge_pte_at(mm, address, ptep, newpte); ++ pages++; ++ } ++ spin_unlock(ptl); ++ continue; ++ } ++ if (!huge_pte_none(pte)) { + pte = huge_ptep_get_and_clear(mm, address, ptep); + pte = pte_mkhuge(huge_pte_modify(pte, newprot)); + pte = arch_make_huge_pte(pte, vma, NULL, 0); +diff --git a/mm/memory.c b/mm/memory.c +index 7f30beaba74f..102af096cbc5 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -4024,7 +4024,7 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr, + if (follow_phys(vma, addr, write, &prot, &phys_addr)) + return -EINVAL; + +- maddr = ioremap_prot(phys_addr, PAGE_SIZE, prot); ++ maddr = ioremap_prot(phys_addr, PAGE_ALIGN(len + offset), prot); + if (write) + memcpy_toio(maddr + offset, buf, len); + else +diff --git a/mm/mmap.c b/mm/mmap.c +index 085bcd890ad2..d4c97ba6843b 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -129,7 +129,7 @@ EXPORT_SYMBOL_GPL(vm_memory_committed); + */ + int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) + { +- unsigned long free, allowed, reserve; ++ long free, allowed, reserve; + + vm_acct_memory(pages); + +@@ -193,7 +193,7 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) + */ + if (mm) { + reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10); +- allowed -= min(mm->total_vm / 32, reserve); ++ allowed -= min_t(long, mm->total_vm / 32, reserve); + } + + if (percpu_counter_read_positive(&vm_committed_as) < allowed) +diff --git a/mm/nommu.c b/mm/nommu.c +index 3ee4f74fbfbe..76b3f90ada7b 100644 +--- a/mm/nommu.c ++++ b/mm/nommu.c +@@ -1905,7 +1905,7 @@ EXPORT_SYMBOL(unmap_mapping_range); + */ + int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) + { +- unsigned long free, allowed, reserve; ++ long free, allowed, reserve; + + vm_acct_memory(pages); + +@@ -1969,7 +1969,7 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) + */ + if (mm) { + reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10); +- allowed -= min(mm->total_vm / 32, reserve); ++ allowed -= min_t(long, mm->total_vm / 32, reserve); + } + + if (percpu_counter_read_positive(&vm_committed_as) < allowed) +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index ea419137f845..0479732f6b02 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -1081,8 +1081,8 @@ static void change_pageblock_range(struct page *pageblock_page, + * nor move CMA pages to different free lists. We don't want unmovable pages + * to be allocated from MIGRATE_CMA areas. + * +- * Returns the new migratetype of the pageblock (or the same old migratetype +- * if it was unchanged). ++ * Returns the allocation migratetype if free pages were stolen, or the ++ * fallback migratetype if it was decided not to steal. + */ + static int try_to_steal_freepages(struct zone *zone, struct page *page, + int start_type, int fallback_type) +@@ -1113,12 +1113,10 @@ static int try_to_steal_freepages(struct zone *zone, struct page *page, + + /* Claim the whole block if over half of it is free */ + if (pages >= (1 << (pageblock_order-1)) || +- page_group_by_mobility_disabled) { +- ++ page_group_by_mobility_disabled) + set_pageblock_migratetype(page, start_type); +- return start_type; +- } + ++ return start_type; + } + + return fallback_type; +@@ -1170,7 +1168,7 @@ __rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype) + set_freepage_migratetype(page, new_type); + + trace_mm_page_alloc_extfrag(page, order, current_order, +- start_migratetype, migratetype, new_type); ++ start_migratetype, migratetype); + + return page; + } +diff --git a/net/compat.c b/net/compat.c +index cbc1a2a26587..275af79c131b 100644 +--- a/net/compat.c ++++ b/net/compat.c +@@ -738,24 +738,18 @@ static unsigned char nas[21] = { + + asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) + { +- if (flags & MSG_CMSG_COMPAT) +- return -EINVAL; + return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); + } + + asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, + unsigned int vlen, unsigned int flags) + { +- if (flags & MSG_CMSG_COMPAT) +- return -EINVAL; + return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, + flags | MSG_CMSG_COMPAT); + } + + asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) + { +- if (flags & MSG_CMSG_COMPAT) +- return -EINVAL; + return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); + } + +@@ -778,9 +772,6 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, + int datagrams; + struct timespec ktspec; + +- if (flags & MSG_CMSG_COMPAT) +- return -EINVAL; +- + if (timeout == NULL) + return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, + flags | MSG_CMSG_COMPAT, NULL); +diff --git a/net/core/dev.c b/net/core/dev.c +index 4ed77d7245c0..f6d8d7fe29ab 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -940,7 +940,7 @@ bool dev_valid_name(const char *name) + return false; + + while (*name) { +- if (*name == '/' || isspace(*name)) ++ if (*name == '/' || *name == ':' || isspace(*name)) + return false; + name++; + } +diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c +index 9d3d9e78397b..372ac662adf9 100644 +--- a/net/core/gen_stats.c ++++ b/net/core/gen_stats.c +@@ -32,6 +32,9 @@ gnet_stats_copy(struct gnet_dump *d, int type, void *buf, int size) + return 0; + + nla_put_failure: ++ kfree(d->xstats); ++ d->xstats = NULL; ++ d->xstats_len = 0; + spin_unlock_bh(d->lock); + return -1; + } +@@ -217,7 +220,9 @@ int + gnet_stats_copy_app(struct gnet_dump *d, void *st, int len) + { + if (d->compat_xstats) { +- d->xstats = st; ++ d->xstats = kmemdup(st, len, GFP_ATOMIC); ++ if (!d->xstats) ++ goto err_out; + d->xstats_len = len; + } + +@@ -225,6 +230,11 @@ gnet_stats_copy_app(struct gnet_dump *d, void *st, int len) + return gnet_stats_copy(d, TCA_STATS_APP, st, len); + + return 0; ++ ++err_out: ++ d->xstats_len = 0; ++ spin_unlock_bh(d->lock); ++ return -1; + } + EXPORT_SYMBOL(gnet_stats_copy_app); + +@@ -257,6 +267,9 @@ gnet_stats_finish_copy(struct gnet_dump *d) + return -1; + } + ++ kfree(d->xstats); ++ d->xstats = NULL; ++ d->xstats_len = 0; + spin_unlock_bh(d->lock); + return 0; + } +diff --git a/net/core/pktgen.c b/net/core/pktgen.c +index fdac61cac1bd..ca68d32b49ba 100644 +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -2812,25 +2812,25 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, + skb->dev = odev; + skb->pkt_type = PACKET_HOST; + ++ pktgen_finalize_skb(pkt_dev, skb, datalen); ++ + if (!(pkt_dev->flags & F_UDPCSUM)) { + skb->ip_summed = CHECKSUM_NONE; + } else if (odev->features & NETIF_F_V4_CSUM) { + skb->ip_summed = CHECKSUM_PARTIAL; + skb->csum = 0; +- udp4_hwcsum(skb, udph->source, udph->dest); ++ udp4_hwcsum(skb, iph->saddr, iph->daddr); + } else { +- __wsum csum = udp_csum(skb); ++ __wsum csum = skb_checksum(skb, skb_transport_offset(skb), datalen + 8, 0); + + /* add protocol-dependent pseudo-header */ +- udph->check = csum_tcpudp_magic(udph->source, udph->dest, ++ udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, + datalen + 8, IPPROTO_UDP, csum); + + if (udph->check == 0) + udph->check = CSUM_MANGLED_0; + } + +- pktgen_finalize_skb(pkt_dev, skb, datalen); +- + #ifdef CONFIG_XFRM + if (!process_ipsec(pkt_dev, skb, protocol)) + return NULL; +@@ -2946,6 +2946,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, + skb->dev = odev; + skb->pkt_type = PACKET_HOST; + ++ pktgen_finalize_skb(pkt_dev, skb, datalen); ++ + if (!(pkt_dev->flags & F_UDPCSUM)) { + skb->ip_summed = CHECKSUM_NONE; + } else if (odev->features & NETIF_F_V6_CSUM) { +@@ -2954,7 +2956,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, + skb->csum_offset = offsetof(struct udphdr, check); + udph->check = ~csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, 0); + } else { +- __wsum csum = udp_csum(skb); ++ __wsum csum = skb_checksum(skb, skb_transport_offset(skb), udplen, 0); + + /* add protocol-dependent pseudo-header */ + udph->check = csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, csum); +@@ -2963,8 +2965,6 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, + udph->check = CSUM_MANGLED_0; + } + +- pktgen_finalize_skb(pkt_dev, skb, datalen); +- + return skb; + } + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index a6613ff972c1..8aadd6a072a4 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -1264,14 +1264,10 @@ static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = { + }; + + static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { +- [IFLA_VF_MAC] = { .type = NLA_BINARY, +- .len = sizeof(struct ifla_vf_mac) }, +- [IFLA_VF_VLAN] = { .type = NLA_BINARY, +- .len = sizeof(struct ifla_vf_vlan) }, +- [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, +- .len = sizeof(struct ifla_vf_tx_rate) }, +- [IFLA_VF_SPOOFCHK] = { .type = NLA_BINARY, +- .len = sizeof(struct ifla_vf_spoofchk) }, ++ [IFLA_VF_MAC] = { .len = sizeof(struct ifla_vf_mac) }, ++ [IFLA_VF_VLAN] = { .len = sizeof(struct ifla_vf_vlan) }, ++ [IFLA_VF_TX_RATE] = { .len = sizeof(struct ifla_vf_tx_rate) }, ++ [IFLA_VF_SPOOFCHK] = { .len = sizeof(struct ifla_vf_spoofchk) }, + }; + + static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = { +@@ -2034,8 +2030,16 @@ replay: + } + } + err = rtnl_configure_link(dev, ifm); +- if (err < 0) +- unregister_netdevice(dev); ++ if (err < 0) { ++ if (ops->newlink) { ++ LIST_HEAD(list_kill); ++ ++ ops->dellink(dev, &list_kill); ++ unregister_netdevice_many(&list_kill); ++ } else { ++ unregister_netdevice(dev); ++ } ++ } + out: + put_net(dest_net); + return err; +diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c +index c10a3ce5cbff..9ff497d17545 100644 +--- a/net/ipv4/ip_fragment.c ++++ b/net/ipv4/ip_fragment.c +@@ -679,27 +679,30 @@ EXPORT_SYMBOL(ip_defrag); + struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user) + { + struct iphdr iph; ++ int netoff; + u32 len; + + if (skb->protocol != htons(ETH_P_IP)) + return skb; + +- if (!skb_copy_bits(skb, 0, &iph, sizeof(iph))) ++ netoff = skb_network_offset(skb); ++ ++ if (skb_copy_bits(skb, netoff, &iph, sizeof(iph)) < 0) + return skb; + + if (iph.ihl < 5 || iph.version != 4) + return skb; + + len = ntohs(iph.tot_len); +- if (skb->len < len || len < (iph.ihl * 4)) ++ if (skb->len < netoff + len || len < (iph.ihl * 4)) + return skb; + + if (ip_is_fragment(&iph)) { + skb = skb_share_check(skb, GFP_ATOMIC); + if (skb) { +- if (!pskb_may_pull(skb, iph.ihl*4)) ++ if (!pskb_may_pull(skb, netoff + iph.ihl * 4)) + return skb; +- if (pskb_trim_rcsum(skb, len)) ++ if (pskb_trim_rcsum(skb, netoff + len)) + return skb; + memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); + if (ip_defrag(skb, user)) +diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +index dd637fc4b553..05686c47a289 100644 +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -843,7 +843,8 @@ static int __ip_append_data(struct sock *sk, + cork->length += length; + if (((length > mtu) || (skb && skb_is_gso(skb))) && + (sk->sk_protocol == IPPROTO_UDP) && +- (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) { ++ (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len && ++ (sk->sk_type == SOCK_DGRAM)) { + err = ip_ufo_append_data(sk, queue, getfrag, from, length, + hh_len, fragheaderlen, transhdrlen, + maxfraglen, flags); +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index 04ce671430cb..b94002ab8052 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -259,6 +259,10 @@ int ping_init_sock(struct sock *sk) + kgid_t low, high; + int ret = 0; + ++#if IS_ENABLED(CONFIG_IPV6) ++ if (sk->sk_family == AF_INET6) ++ inet6_sk(sk)->ipv6only = 1; ++#endif + inet_get_ping_group_range_net(net, &low, &high); + if (gid_lte(low, group) && gid_lte(group, high)) + return 0; +@@ -305,6 +309,11 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, + if (addr_len < sizeof(*addr)) + return -EINVAL; + ++ if (addr->sin_family != AF_INET && ++ !(addr->sin_family == AF_UNSPEC && ++ addr->sin_addr.s_addr == htonl(INADDR_ANY))) ++ return -EAFNOSUPPORT; ++ + pr_debug("ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)\n", + sk, &addr->sin_addr.s_addr, ntohs(addr->sin_port)); + +@@ -330,7 +339,7 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, + return -EINVAL; + + if (addr->sin6_family != AF_INET6) +- return -EINVAL; ++ return -EAFNOSUPPORT; + + pr_debug("ping_check_bind_addr(sk=%p,addr=%pI6c,port=%d)\n", + sk, addr->sin6_addr.s6_addr, ntohs(addr->sin6_port)); +@@ -716,7 +725,7 @@ static int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m + if (msg->msg_namelen < sizeof(*usin)) + return -EINVAL; + if (usin->sin_family != AF_INET) +- return -EINVAL; ++ return -EAFNOSUPPORT; + daddr = usin->sin_addr.s_addr; + /* no remote port */ + } else { +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 12f7ef0f243a..d7907ecf0b75 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1294,7 +1294,8 @@ emsgsize: + if (((length > mtu) || + (skb && skb_is_gso(skb))) && + (sk->sk_protocol == IPPROTO_UDP) && +- (rt->dst.dev->features & NETIF_F_UFO)) { ++ (rt->dst.dev->features & NETIF_F_UFO) && ++ (sk->sk_type == SOCK_DGRAM)) { + err = ip6_ufo_append_data(sk, getfrag, from, length, + hh_len, fragheaderlen, + transhdrlen, mtu, flags, rt); +diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c +index bda74291c3e0..461199533fe4 100644 +--- a/net/ipv6/ping.c ++++ b/net/ipv6/ping.c +@@ -103,9 +103,10 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + + if (msg->msg_name) { + DECLARE_SOCKADDR(struct sockaddr_in6 *, u, msg->msg_name); +- if (msg->msg_namelen < sizeof(struct sockaddr_in6) || +- u->sin6_family != AF_INET6) { ++ if (msg->msg_namelen < sizeof(*u)) + return -EINVAL; ++ if (u->sin6_family != AF_INET6) { ++ return -EAFNOSUPPORT; + } + if (sk->sk_bound_dev_if && + sk->sk_bound_dev_if != u->sin6_scope_id) { +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 6f1b8503a431..3809ca234c69 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -141,7 +141,7 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) + u32 *p = NULL; + + if (!(rt->dst.flags & DST_HOST)) +- return NULL; ++ return dst_cow_metrics_generic(dst, old); + + peer = rt6_get_peer_create(rt); + if (peer) { +diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c +index 2ba8b9705bb7..fdcb9688b5d3 100644 +--- a/net/irda/ircomm/ircomm_tty.c ++++ b/net/irda/ircomm/ircomm_tty.c +@@ -818,7 +818,9 @@ static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout) + orig_jiffies = jiffies; + + /* Set poll time to 200 ms */ +- poll_time = IRDA_MIN(timeout, msecs_to_jiffies(200)); ++ poll_time = msecs_to_jiffies(200); ++ if (timeout) ++ poll_time = min_t(unsigned long, timeout, poll_time); + + spin_lock_irqsave(&self->spinlock, flags); + while (self->tx_skb && self->tx_skb->len) { +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index e5a7ac2f3687..dca076f6252c 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -562,6 +562,7 @@ ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx) + if (tx->sdata->control_port_no_encrypt) + info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; + info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO; ++ info->flags |= IEEE80211_TX_CTL_USE_MINRATE; + } + + return TX_CONTINUE; +diff --git a/net/sched/ematch.c b/net/sched/ematch.c +index 3a633debb6df..a2abc449ce8f 100644 +--- a/net/sched/ematch.c ++++ b/net/sched/ematch.c +@@ -227,6 +227,7 @@ static int tcf_em_validate(struct tcf_proto *tp, + * to replay the request. + */ + module_put(em->ops->owner); ++ em->ops = NULL; + err = -EAGAIN; + } + #endif +diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c +index ae333c1845bb..0adc66caae2f 100644 +--- a/net/sunrpc/cache.c ++++ b/net/sunrpc/cache.c +@@ -920,7 +920,7 @@ static unsigned int cache_poll(struct file *filp, poll_table *wait, + poll_wait(filp, &queue_wait, wait); + + /* alway allow write */ +- mask = POLL_OUT | POLLWRNORM; ++ mask = POLLOUT | POLLWRNORM; + + if (!rp) + return mask; +diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c +index 566b0f69d628..ee2405723188 100644 +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -1404,6 +1404,8 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state) + if (! snd_pcm_playback_empty(substream)) { + snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING); + snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING); ++ } else { ++ runtime->status->state = SNDRV_PCM_STATE_SETUP; + } + break; + case SNDRV_PCM_STATE_RUNNING: +diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c +index 103e85a13f35..2f3059b50ffa 100644 +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -3984,7 +3984,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, + /* Panther Point */ + { PCI_DEVICE(0x8086, 0x1e20), +- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, ++ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, + /* Lynx Point */ + { PCI_DEVICE(0x8086, 0x8c20), + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, +diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c +index 12f28d7e0fdc..231b26471a63 100644 +--- a/sound/pci/hda/patch_sigmatel.c ++++ b/sound/pci/hda/patch_sigmatel.c +@@ -85,6 +85,7 @@ enum { + STAC_ALIENWARE_M17X, + STAC_92HD89XX_HP_FRONT_JACK, + STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK, ++ STAC_92HD73XX_ASUS_MOBO, + STAC_92HD73XX_MODELS + }; + +@@ -1935,7 +1936,18 @@ static const struct hda_fixup stac92hd73xx_fixups[] = { + [STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK] = { + .type = HDA_FIXUP_PINS, + .v.pins = stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs, +- } ++ }, ++ [STAC_92HD73XX_ASUS_MOBO] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ /* enable 5.1 and SPDIF out */ ++ { 0x0c, 0x01014411 }, ++ { 0x0d, 0x01014410 }, ++ { 0x0e, 0x01014412 }, ++ { 0x22, 0x014b1180 }, ++ { } ++ } ++ }, + }; + + static const struct hda_model_fixup stac92hd73xx_models[] = { +@@ -1947,6 +1959,7 @@ static const struct hda_model_fixup stac92hd73xx_models[] = { + { .id = STAC_DELL_M6_BOTH, .name = "dell-m6" }, + { .id = STAC_DELL_EQ, .name = "dell-eq" }, + { .id = STAC_ALIENWARE_M17X, .name = "alienware" }, ++ { .id = STAC_92HD73XX_ASUS_MOBO, .name = "asus-mobo" }, + {} + }; + +@@ -1999,6 +2012,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = { + "HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17, + "unknown HP", STAC_92HD89XX_HP_FRONT_JACK), ++ SND_PCI_QUIRK(PCI_VENDOR_ID_ASUSTEK, 0x83f8, "ASUS AT4NM10", ++ STAC_92HD73XX_ASUS_MOBO), + {} /* terminator */ + }; + +diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c +index 07b8b7bc9d20..81f6a7545ef5 100644 +--- a/sound/soc/omap/omap-pcm.c ++++ b/sound/soc/omap/omap-pcm.c +@@ -200,7 +200,7 @@ static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd) + struct snd_pcm *pcm = rtd->pcm; + int ret; + +- ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(64)); ++ ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + diff --git a/patch/kernel/cubox-default/patch-3.14.36-37.patch b/patch/kernel/cubox-default/patch-3.14.36-37.patch new file mode 100644 index 000000000..6b928d9ec --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.36-37.patch @@ -0,0 +1,2861 @@ +diff --git a/Makefile b/Makefile +index 4e6537bd8aa0..c24acc0d34a1 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 36 ++SUBLEVEL = 37 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/dra7xx-clocks.dtsi +index e96da9a898ad..f2512e1d28c7 100644 +--- a/arch/arm/boot/dts/dra7xx-clocks.dtsi ++++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi +@@ -243,10 +243,18 @@ + ti,invert-autoidle-bit; + }; + ++ dpll_core_byp_mux: dpll_core_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ ti,bit-shift = <23>; ++ reg = <0x012c>; ++ }; ++ + dpll_core_ck: dpll_core_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-core-clock"; +- clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ clocks = <&sys_clkin1>, <&dpll_core_byp_mux>; + reg = <0x0120>, <0x0124>, <0x012c>, <0x0128>; + }; + +@@ -309,10 +317,18 @@ + clock-div = <1>; + }; + ++ dpll_dsp_byp_mux: dpll_dsp_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&dsp_dpll_hs_clk_div>; ++ ti,bit-shift = <23>; ++ reg = <0x0240>; ++ }; ++ + dpll_dsp_ck: dpll_dsp_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&dsp_dpll_hs_clk_div>; ++ clocks = <&sys_clkin1>, <&dpll_dsp_byp_mux>; + reg = <0x0234>, <0x0238>, <0x0240>, <0x023c>; + }; + +@@ -335,10 +351,18 @@ + clock-div = <1>; + }; + ++ dpll_iva_byp_mux: dpll_iva_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&iva_dpll_hs_clk_div>; ++ ti,bit-shift = <23>; ++ reg = <0x01ac>; ++ }; ++ + dpll_iva_ck: dpll_iva_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&iva_dpll_hs_clk_div>; ++ clocks = <&sys_clkin1>, <&dpll_iva_byp_mux>; + reg = <0x01a0>, <0x01a4>, <0x01ac>, <0x01a8>; + }; + +@@ -361,10 +385,18 @@ + clock-div = <1>; + }; + ++ dpll_gpu_byp_mux: dpll_gpu_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ ti,bit-shift = <23>; ++ reg = <0x02e4>; ++ }; ++ + dpll_gpu_ck: dpll_gpu_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ clocks = <&sys_clkin1>, <&dpll_gpu_byp_mux>; + reg = <0x02d8>, <0x02dc>, <0x02e4>, <0x02e0>; + }; + +@@ -398,10 +430,18 @@ + clock-div = <1>; + }; + ++ dpll_ddr_byp_mux: dpll_ddr_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ ti,bit-shift = <23>; ++ reg = <0x021c>; ++ }; ++ + dpll_ddr_ck: dpll_ddr_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ clocks = <&sys_clkin1>, <&dpll_ddr_byp_mux>; + reg = <0x0210>, <0x0214>, <0x021c>, <0x0218>; + }; + +@@ -416,10 +456,18 @@ + ti,invert-autoidle-bit; + }; + ++ dpll_gmac_byp_mux: dpll_gmac_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ ti,bit-shift = <23>; ++ reg = <0x02b4>; ++ }; ++ + dpll_gmac_ck: dpll_gmac_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ clocks = <&sys_clkin1>, <&dpll_gmac_byp_mux>; + reg = <0x02a8>, <0x02ac>, <0x02b4>, <0x02b0>; + }; + +@@ -482,10 +530,18 @@ + clock-div = <1>; + }; + ++ dpll_eve_byp_mux: dpll_eve_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&eve_dpll_hs_clk_div>; ++ ti,bit-shift = <23>; ++ reg = <0x0290>; ++ }; ++ + dpll_eve_ck: dpll_eve_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&eve_dpll_hs_clk_div>; ++ clocks = <&sys_clkin1>, <&dpll_eve_byp_mux>; + reg = <0x0284>, <0x0288>, <0x0290>, <0x028c>; + }; + +@@ -1214,10 +1270,18 @@ + clock-div = <1>; + }; + ++ dpll_per_byp_mux: dpll_per_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&per_dpll_hs_clk_div>; ++ ti,bit-shift = <23>; ++ reg = <0x014c>; ++ }; ++ + dpll_per_ck: dpll_per_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&per_dpll_hs_clk_div>; ++ clocks = <&sys_clkin1>, <&dpll_per_byp_mux>; + reg = <0x0140>, <0x0144>, <0x014c>, <0x0148>; + }; + +@@ -1240,10 +1304,18 @@ + clock-div = <1>; + }; + ++ dpll_usb_byp_mux: dpll_usb_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&usb_dpll_hs_clk_div>; ++ ti,bit-shift = <23>; ++ reg = <0x018c>; ++ }; ++ + dpll_usb_ck: dpll_usb_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-j-type-clock"; +- clocks = <&sys_clkin1>, <&usb_dpll_hs_clk_div>; ++ clocks = <&sys_clkin1>, <&dpll_usb_byp_mux>; + reg = <0x0180>, <0x0184>, <0x018c>, <0x0188>; + }; + +diff --git a/arch/arm/crypto/aesbs-core.S_shipped b/arch/arm/crypto/aesbs-core.S_shipped +index 71e5fc7cfb18..1d1800f71c5b 100644 +--- a/arch/arm/crypto/aesbs-core.S_shipped ++++ b/arch/arm/crypto/aesbs-core.S_shipped +@@ -58,14 +58,18 @@ + # define VFP_ABI_FRAME 0 + # define BSAES_ASM_EXTENDED_KEY + # define XTS_CHAIN_TWEAK +-# define __ARM_ARCH__ 7 ++# define __ARM_ARCH__ __LINUX_ARM_ARCH__ ++# define __ARM_MAX_ARCH__ 7 + #endif + + #ifdef __thumb__ + # define adrl adr + #endif + +-#if __ARM_ARCH__>=7 ++#if __ARM_MAX_ARCH__>=7 ++.arch armv7-a ++.fpu neon ++ + .text + .syntax unified @ ARMv7-capable assembler is expected to handle this + #ifdef __thumb2__ +@@ -74,8 +78,6 @@ + .code 32 + #endif + +-.fpu neon +- + .type _bsaes_decrypt8,%function + .align 4 + _bsaes_decrypt8: +@@ -2095,9 +2097,11 @@ bsaes_xts_decrypt: + vld1.8 {q8}, [r0] @ initial tweak + adr r2, .Lxts_magic + ++#ifndef XTS_CHAIN_TWEAK + tst r9, #0xf @ if not multiple of 16 + it ne @ Thumb2 thing, sanity check in ARM + subne r9, #0x10 @ subtract another 16 bytes ++#endif + subs r9, #0x80 + + blo .Lxts_dec_short +diff --git a/arch/arm/crypto/bsaes-armv7.pl b/arch/arm/crypto/bsaes-armv7.pl +index be068db960ee..a4d3856e7d24 100644 +--- a/arch/arm/crypto/bsaes-armv7.pl ++++ b/arch/arm/crypto/bsaes-armv7.pl +@@ -701,14 +701,18 @@ $code.=<<___; + # define VFP_ABI_FRAME 0 + # define BSAES_ASM_EXTENDED_KEY + # define XTS_CHAIN_TWEAK +-# define __ARM_ARCH__ 7 ++# define __ARM_ARCH__ __LINUX_ARM_ARCH__ ++# define __ARM_MAX_ARCH__ 7 + #endif + + #ifdef __thumb__ + # define adrl adr + #endif + +-#if __ARM_ARCH__>=7 ++#if __ARM_MAX_ARCH__>=7 ++.arch armv7-a ++.fpu neon ++ + .text + .syntax unified @ ARMv7-capable assembler is expected to handle this + #ifdef __thumb2__ +@@ -717,8 +721,6 @@ $code.=<<___; + .code 32 + #endif + +-.fpu neon +- + .type _bsaes_decrypt8,%function + .align 4 + _bsaes_decrypt8: +@@ -2076,9 +2078,11 @@ bsaes_xts_decrypt: + vld1.8 {@XMM[8]}, [r0] @ initial tweak + adr $magic, .Lxts_magic + ++#ifndef XTS_CHAIN_TWEAK + tst $len, #0xf @ if not multiple of 16 + it ne @ Thumb2 thing, sanity check in ARM + subne $len, #0x10 @ subtract another 16 bytes ++#endif + subs $len, #0x80 + + blo .Lxts_dec_short +diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h +index c5101dcb4fb0..1d4df3b70ebc 100644 +--- a/arch/arm/mach-at91/pm.h ++++ b/arch/arm/mach-at91/pm.h +@@ -45,7 +45,7 @@ static inline void at91rm9200_standby(void) + " mcr p15, 0, %0, c7, c0, 4\n\t" + " str %5, [%1, %2]" + : +- : "r" (0), "r" (AT91_BASE_SYS), "r" (AT91RM9200_SDRAMC_LPR), ++ : "r" (0), "r" (at91_ramc_base[0]), "r" (AT91RM9200_SDRAMC_LPR), + "r" (1), "r" (AT91RM9200_SDRAMC_SRR), + "r" (lpr)); + } +diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c +index fbd76785c5db..3974881388bb 100644 +--- a/arch/arm64/mm/dma-mapping.c ++++ b/arch/arm64/mm/dma-mapping.c +@@ -44,6 +44,7 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size, + flags |= GFP_DMA32; + if (IS_ENABLED(CONFIG_DMA_CMA)) { + struct page *page; ++ void *addr; + + size = PAGE_ALIGN(size); + page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT, +@@ -52,7 +53,10 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size, + return NULL; + + *dma_handle = phys_to_dma(dev, page_to_phys(page)); +- return page_address(page); ++ addr = page_address(page); ++ if (flags & __GFP_ZERO) ++ memset(addr, 0, size); ++ return addr; + } else { + return swiotlb_alloc_coherent(dev, size, dma_handle, flags); + } +diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c +index 617b9fe33771..3ccb6777a7e1 100644 +--- a/arch/sparc/kernel/perf_event.c ++++ b/arch/sparc/kernel/perf_event.c +@@ -960,6 +960,8 @@ out: + cpuc->pcr[0] |= cpuc->event[0]->hw.config_base; + } + ++static void sparc_pmu_start(struct perf_event *event, int flags); ++ + /* On this PMU each PIC has it's own PCR control register. */ + static void calculate_multiple_pcrs(struct cpu_hw_events *cpuc) + { +@@ -972,20 +974,13 @@ static void calculate_multiple_pcrs(struct cpu_hw_events *cpuc) + struct perf_event *cp = cpuc->event[i]; + struct hw_perf_event *hwc = &cp->hw; + int idx = hwc->idx; +- u64 enc; + + if (cpuc->current_idx[i] != PIC_NO_INDEX) + continue; + +- sparc_perf_event_set_period(cp, hwc, idx); + cpuc->current_idx[i] = idx; + +- enc = perf_event_get_enc(cpuc->events[i]); +- cpuc->pcr[idx] &= ~mask_for_index(idx); +- if (hwc->state & PERF_HES_STOPPED) +- cpuc->pcr[idx] |= nop_for_index(idx); +- else +- cpuc->pcr[idx] |= event_encoding(enc, idx); ++ sparc_pmu_start(cp, PERF_EF_RELOAD); + } + out: + for (i = 0; i < cpuc->n_events; i++) { +@@ -1101,7 +1096,6 @@ static void sparc_pmu_del(struct perf_event *event, int _flags) + int i; + + local_irq_save(flags); +- perf_pmu_disable(event->pmu); + + for (i = 0; i < cpuc->n_events; i++) { + if (event == cpuc->event[i]) { +@@ -1127,7 +1121,6 @@ static void sparc_pmu_del(struct perf_event *event, int _flags) + } + } + +- perf_pmu_enable(event->pmu); + local_irq_restore(flags); + } + +@@ -1361,7 +1354,6 @@ static int sparc_pmu_add(struct perf_event *event, int ef_flags) + unsigned long flags; + + local_irq_save(flags); +- perf_pmu_disable(event->pmu); + + n0 = cpuc->n_events; + if (n0 >= sparc_pmu->max_hw_events) +@@ -1394,7 +1386,6 @@ nocheck: + + ret = 0; + out: +- perf_pmu_enable(event->pmu); + local_irq_restore(flags); + return ret; + } +diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c +index c6f7113b6e2f..1a79d6877981 100644 +--- a/arch/sparc/kernel/process_64.c ++++ b/arch/sparc/kernel/process_64.c +@@ -281,6 +281,8 @@ void arch_trigger_all_cpu_backtrace(void) + printk(" TPC[%lx] O7[%lx] I7[%lx] RPC[%lx]\n", + gp->tpc, gp->o7, gp->i7, gp->rpc); + } ++ ++ touch_nmi_watchdog(); + } + + memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot)); +@@ -356,6 +358,8 @@ static void pmu_snapshot_all_cpus(void) + (cpu == this_cpu ? '*' : ' '), cpu, + pp->pcr[0], pp->pcr[1], pp->pcr[2], pp->pcr[3], + pp->pic[0], pp->pic[1], pp->pic[2], pp->pic[3]); ++ ++ touch_nmi_watchdog(); + } + + memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot)); +diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c +index beb0b5a5f21f..25db14a33d03 100644 +--- a/arch/sparc/kernel/sys_sparc_64.c ++++ b/arch/sparc/kernel/sys_sparc_64.c +@@ -332,7 +332,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second + long err; + + /* No need for backward compatibility. We can start fresh... */ +- if (call <= SEMCTL) { ++ if (call <= SEMTIMEDOP) { + switch (call) { + case SEMOP: + err = sys_semtimedop(first, ptr, +diff --git a/arch/sparc/lib/memmove.S b/arch/sparc/lib/memmove.S +index b7f6334e159f..857ad4f8905f 100644 +--- a/arch/sparc/lib/memmove.S ++++ b/arch/sparc/lib/memmove.S +@@ -8,9 +8,11 @@ + + .text + ENTRY(memmove) /* o0=dst o1=src o2=len */ +- mov %o0, %g1 ++ brz,pn %o2, 99f ++ mov %o0, %g1 ++ + cmp %o0, %o1 +- bleu,pt %xcc, memcpy ++ bleu,pt %xcc, 2f + add %o1, %o2, %g7 + cmp %g7, %o0 + bleu,pt %xcc, memcpy +@@ -24,7 +26,34 @@ ENTRY(memmove) /* o0=dst o1=src o2=len */ + stb %g7, [%o0] + bne,pt %icc, 1b + sub %o0, 1, %o0 +- ++99: + retl + mov %g1, %o0 ++ ++ /* We can't just call memcpy for these memmove cases. On some ++ * chips the memcpy uses cache initializing stores and when dst ++ * and src are close enough, those can clobber the source data ++ * before we've loaded it in. ++ */ ++2: or %o0, %o1, %g7 ++ or %o2, %g7, %g7 ++ andcc %g7, 0x7, %g0 ++ bne,pn %xcc, 4f ++ nop ++ ++3: ldx [%o1], %g7 ++ add %o1, 8, %o1 ++ subcc %o2, 8, %o2 ++ add %o0, 8, %o0 ++ bne,pt %icc, 3b ++ stx %g7, [%o0 - 0x8] ++ ba,a,pt %xcc, 99b ++ ++4: ldub [%o1], %g7 ++ add %o1, 1, %o1 ++ subcc %o2, 1, %o2 ++ add %o0, 1, %o0 ++ bne,pt %icc, 4b ++ stb %g7, [%o0 - 0x1] ++ ba,a,pt %xcc, 99b + ENDPROC(memmove) +diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c +index cfbe53c17b0d..09daebdee552 100644 +--- a/arch/sparc/mm/srmmu.c ++++ b/arch/sparc/mm/srmmu.c +@@ -460,10 +460,12 @@ static void __init sparc_context_init(int numctx) + void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, + struct task_struct *tsk) + { ++ unsigned long flags; ++ + if (mm->context == NO_CONTEXT) { +- spin_lock(&srmmu_context_spinlock); ++ spin_lock_irqsave(&srmmu_context_spinlock, flags); + alloc_context(old_mm, mm); +- spin_unlock(&srmmu_context_spinlock); ++ spin_unlock_irqrestore(&srmmu_context_spinlock, flags); + srmmu_ctxd_set(&srmmu_context_table[mm->context], mm->pgd); + } + +@@ -988,14 +990,15 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) + + void destroy_context(struct mm_struct *mm) + { ++ unsigned long flags; + + if (mm->context != NO_CONTEXT) { + flush_cache_mm(mm); + srmmu_ctxd_set(&srmmu_context_table[mm->context], srmmu_swapper_pg_dir); + flush_tlb_mm(mm); +- spin_lock(&srmmu_context_spinlock); ++ spin_lock_irqsave(&srmmu_context_spinlock, flags); + free_context(mm->context); +- spin_unlock(&srmmu_context_spinlock); ++ spin_unlock_irqrestore(&srmmu_context_spinlock, flags); + mm->context = NO_CONTEXT; + } + } +diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c +index 6dfb7d0b139a..6d4fabac779c 100644 +--- a/arch/x86/crypto/aesni-intel_glue.c ++++ b/arch/x86/crypto/aesni-intel_glue.c +@@ -1109,7 +1109,7 @@ static int __driver_rfc4106_decrypt(struct aead_request *req) + src = kmalloc(req->cryptlen + req->assoclen, GFP_ATOMIC); + if (!src) + return -ENOMEM; +- assoc = (src + req->cryptlen + auth_tag_len); ++ assoc = (src + req->cryptlen); + scatterwalk_map_and_copy(src, req->src, 0, req->cryptlen, 0); + scatterwalk_map_and_copy(assoc, req->assoc, 0, + req->assoclen, 0); +@@ -1134,7 +1134,7 @@ static int __driver_rfc4106_decrypt(struct aead_request *req) + scatterwalk_done(&src_sg_walk, 0, 0); + scatterwalk_done(&assoc_sg_walk, 0, 0); + } else { +- scatterwalk_map_and_copy(dst, req->dst, 0, req->cryptlen, 1); ++ scatterwalk_map_and_copy(dst, req->dst, 0, tempCipherLen, 1); + kfree(src); + } + return retval; +diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h +index cea1c76d49bf..1ac1c009090d 100644 +--- a/arch/x86/include/asm/fpu-internal.h ++++ b/arch/x86/include/asm/fpu-internal.h +@@ -368,7 +368,7 @@ static inline void drop_fpu(struct task_struct *tsk) + preempt_disable(); + tsk->thread.fpu_counter = 0; + __drop_fpu(tsk); +- clear_used_math(); ++ clear_stopped_child_used_math(tsk); + preempt_enable(); + } + +diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c +index dd50e26c58f6..7a09aca4b33a 100644 +--- a/arch/x86/kernel/xsave.c ++++ b/arch/x86/kernel/xsave.c +@@ -375,7 +375,7 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size) + * thread's fpu state, reconstruct fxstate from the fsave + * header. Sanitize the copied state etc. + */ +- struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave; ++ struct fpu *fpu = &tsk->thread.fpu; + struct user_i387_ia32_struct env; + int err = 0; + +@@ -389,14 +389,15 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size) + */ + drop_fpu(tsk); + +- if (__copy_from_user(xsave, buf_fx, state_size) || ++ if (__copy_from_user(&fpu->state->xsave, buf_fx, state_size) || + __copy_from_user(&env, buf, sizeof(env))) { ++ fpu_finit(fpu); + err = -1; + } else { + sanitize_restored_xstate(tsk, &env, xstate_bv, fx_only); +- set_used_math(); + } + ++ set_used_math(); + if (use_eager_fpu()) { + preempt_disable(); + math_state_restore(); +diff --git a/arch/x86/vdso/vdso32/sigreturn.S b/arch/x86/vdso/vdso32/sigreturn.S +index 31776d0efc8c..d7ec4e251c0a 100644 +--- a/arch/x86/vdso/vdso32/sigreturn.S ++++ b/arch/x86/vdso/vdso32/sigreturn.S +@@ -17,6 +17,7 @@ + .text + .globl __kernel_sigreturn + .type __kernel_sigreturn,@function ++ nop /* this guy is needed for .LSTARTFDEDLSI1 below (watch for HACK) */ + ALIGN + __kernel_sigreturn: + .LSTART_sigreturn: +diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c +index eff9d5870034..102463ba745d 100644 +--- a/drivers/char/tpm/tpm_ibmvtpm.c ++++ b/drivers/char/tpm/tpm_ibmvtpm.c +@@ -124,7 +124,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) + { + struct ibmvtpm_dev *ibmvtpm; + struct ibmvtpm_crq crq; +- u64 *word = (u64 *) &crq; ++ __be64 *word = (__be64 *)&crq; + int rc; + + ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip); +@@ -145,11 +145,11 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) + memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count); + crq.valid = (u8)IBMVTPM_VALID_CMD; + crq.msg = (u8)VTPM_TPM_COMMAND; +- crq.len = (u16)count; +- crq.data = ibmvtpm->rtce_dma_handle; ++ crq.len = cpu_to_be16(count); ++ crq.data = cpu_to_be32(ibmvtpm->rtce_dma_handle); + +- rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(word[0]), +- cpu_to_be64(word[1])); ++ rc = ibmvtpm_send_crq(ibmvtpm->vdev, be64_to_cpu(word[0]), ++ be64_to_cpu(word[1])); + if (rc != H_SUCCESS) { + dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc); + rc = 0; +diff --git a/drivers/char/tpm/tpm_ibmvtpm.h b/drivers/char/tpm/tpm_ibmvtpm.h +index bd82a791f995..b2c231b1beec 100644 +--- a/drivers/char/tpm/tpm_ibmvtpm.h ++++ b/drivers/char/tpm/tpm_ibmvtpm.h +@@ -22,9 +22,9 @@ + struct ibmvtpm_crq { + u8 valid; + u8 msg; +- u16 len; +- u32 data; +- u64 reserved; ++ __be16 len; ++ __be32 data; ++ __be64 reserved; + } __attribute__((packed, aligned(8))); + + struct ibmvtpm_crq_queue { +diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c +index 6928d094451d..b08eadb4b1d2 100644 +--- a/drivers/char/virtio_console.c ++++ b/drivers/char/virtio_console.c +@@ -142,6 +142,7 @@ struct ports_device { + * notification + */ + struct work_struct control_work; ++ struct work_struct config_work; + + struct list_head ports; + +@@ -1832,10 +1833,21 @@ static void config_intr(struct virtio_device *vdev) + + portdev = vdev->priv; + ++ if (!use_multiport(portdev)) ++ schedule_work(&portdev->config_work); ++} ++ ++static void config_work_handler(struct work_struct *work) ++{ ++ struct ports_device *portdev; ++ ++ portdev = container_of(work, struct ports_device, control_work); + if (!use_multiport(portdev)) { ++ struct virtio_device *vdev; + struct port *port; + u16 rows, cols; + ++ vdev = portdev->vdev; + virtio_cread(vdev, struct virtio_console_config, cols, &cols); + virtio_cread(vdev, struct virtio_console_config, rows, &rows); + +@@ -2024,12 +2036,14 @@ static int virtcons_probe(struct virtio_device *vdev) + spin_lock_init(&portdev->ports_lock); + INIT_LIST_HEAD(&portdev->ports); + ++ INIT_WORK(&portdev->config_work, &config_work_handler); ++ INIT_WORK(&portdev->control_work, &control_work_handler); ++ + if (multiport) { + unsigned int nr_added_bufs; + + spin_lock_init(&portdev->c_ivq_lock); + spin_lock_init(&portdev->c_ovq_lock); +- INIT_WORK(&portdev->control_work, &control_work_handler); + + nr_added_bufs = fill_queue(portdev->c_ivq, + &portdev->c_ivq_lock); +@@ -2097,6 +2111,8 @@ static void virtcons_remove(struct virtio_device *vdev) + /* Finish up work that's lined up */ + if (use_multiport(portdev)) + cancel_work_sync(&portdev->control_work); ++ else ++ cancel_work_sync(&portdev->config_work); + + list_for_each_entry_safe(port, port2, &portdev->ports, list) + unplug_port(port); +@@ -2148,6 +2164,7 @@ static int virtcons_freeze(struct virtio_device *vdev) + + virtqueue_disable_cb(portdev->c_ivq); + cancel_work_sync(&portdev->control_work); ++ cancel_work_sync(&portdev->config_work); + /* + * Once more: if control_work_handler() was running, it would + * enable the cb as the last step. +diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c +index 0cca5f24196a..663394f0c166 100644 +--- a/drivers/gpu/drm/radeon/atombios_crtc.c ++++ b/drivers/gpu/drm/radeon/atombios_crtc.c +@@ -1306,6 +1306,9 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, + (x << 16) | y); + viewport_w = crtc->mode.hdisplay; + viewport_h = (crtc->mode.vdisplay + 1) & ~1; ++ if ((rdev->family >= CHIP_BONAIRE) && ++ (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)) ++ viewport_h *= 2; + WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, + (viewport_w << 16) | viewport_h); + +diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c +index f0ed0baddf70..c3664bc05acf 100644 +--- a/drivers/gpu/drm/radeon/cik.c ++++ b/drivers/gpu/drm/radeon/cik.c +@@ -7069,6 +7069,9 @@ int cik_irq_set(struct radeon_device *rdev) + WREG32(DC_HPD5_INT_CONTROL, hpd5); + WREG32(DC_HPD6_INT_CONTROL, hpd6); + ++ /* posting read */ ++ RREG32(SRBM_STATUS); ++ + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index 7138f3e31b7c..ee9f0b4e90d6 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -4596,6 +4596,9 @@ int evergreen_irq_set(struct radeon_device *rdev) + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, afmt5); + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, afmt6); + ++ /* posting read */ ++ RREG32(SRBM_STATUS); ++ + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c +index 07620e198a6d..e28de20d469a 100644 +--- a/drivers/gpu/drm/radeon/r100.c ++++ b/drivers/gpu/drm/radeon/r100.c +@@ -742,6 +742,10 @@ int r100_irq_set(struct radeon_device *rdev) + tmp |= RADEON_FP2_DETECT_MASK; + } + WREG32(RADEON_GEN_INT_CNTL, tmp); ++ ++ /* read back to post the write */ ++ RREG32(RADEON_GEN_INT_CNTL); ++ + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c +index 788f602e8989..74a8a38db4d5 100644 +--- a/drivers/gpu/drm/radeon/r600.c ++++ b/drivers/gpu/drm/radeon/r600.c +@@ -3647,6 +3647,9 @@ int r600_irq_set(struct radeon_device *rdev) + WREG32(RV770_CG_THERMAL_INT, thermal_int); + } + ++ /* posting read */ ++ RREG32(R_000E50_SRBM_STATUS); ++ + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c +index 7f2d6c0d11c1..2f2d2ce34709 100644 +--- a/drivers/gpu/drm/radeon/radeon_cs.c ++++ b/drivers/gpu/drm/radeon/radeon_cs.c +@@ -179,11 +179,13 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) + u32 ring = RADEON_CS_RING_GFX; + s32 priority = 0; + ++ INIT_LIST_HEAD(&p->validated); ++ + if (!cs->num_chunks) { + return 0; + } ++ + /* get chunks */ +- INIT_LIST_HEAD(&p->validated); + p->idx = 0; + p->ib.sa_bo = NULL; + p->ib.semaphore = NULL; +diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c +index e5619d5e2a30..4261b3865cb0 100644 +--- a/drivers/gpu/drm/radeon/rs600.c ++++ b/drivers/gpu/drm/radeon/rs600.c +@@ -700,6 +700,10 @@ int rs600_irq_set(struct radeon_device *rdev) + WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); + if (ASIC_IS_DCE2(rdev)) + WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0); ++ ++ /* posting read */ ++ RREG32(R_000040_GEN_INT_CNTL); ++ + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c +index 52b64ad285d6..2f2deccb3b78 100644 +--- a/drivers/gpu/drm/radeon/si.c ++++ b/drivers/gpu/drm/radeon/si.c +@@ -5958,6 +5958,9 @@ int si_irq_set(struct radeon_device *rdev) + + WREG32(CG_THERMAL_INT, thermal_int); + ++ /* posting read */ ++ RREG32(SRBM_STATUS); ++ + return 0; + } + +@@ -6875,8 +6878,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) + WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK); + + if (!vclk || !dclk) { +- /* keep the Bypass mode, put PLL to sleep */ +- WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); ++ /* keep the Bypass mode */ + return 0; + } + +@@ -6892,8 +6894,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) + /* set VCO_MODE to 1 */ + WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_VCO_MODE_MASK, ~UPLL_VCO_MODE_MASK); + +- /* toggle UPLL_SLEEP to 1 then back to 0 */ +- WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); ++ /* disable sleep mode */ + WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_SLEEP_MASK); + + /* deassert UPLL_RESET */ +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +index fb7c36e93fd4..0771dcbf9ed0 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +@@ -733,32 +733,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) + goto out_err1; + } + +- ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM, +- (dev_priv->vram_size >> PAGE_SHIFT)); +- if (unlikely(ret != 0)) { +- DRM_ERROR("Failed initializing memory manager for VRAM.\n"); +- goto out_err2; +- } +- +- dev_priv->has_gmr = true; +- if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) || +- refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR, +- VMW_PL_GMR) != 0) { +- DRM_INFO("No GMR memory available. " +- "Graphics memory resources are very limited.\n"); +- dev_priv->has_gmr = false; +- } +- +- if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) { +- dev_priv->has_mob = true; +- if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB, +- VMW_PL_MOB) != 0) { +- DRM_INFO("No MOB memory available. " +- "3D will be disabled.\n"); +- dev_priv->has_mob = false; +- } +- } +- + dev_priv->mmio_mtrr = arch_phys_wc_add(dev_priv->mmio_start, + dev_priv->mmio_size); + +@@ -821,6 +795,33 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) + goto out_no_fman; + } + ++ ++ ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM, ++ (dev_priv->vram_size >> PAGE_SHIFT)); ++ if (unlikely(ret != 0)) { ++ DRM_ERROR("Failed initializing memory manager for VRAM.\n"); ++ goto out_no_vram; ++ } ++ ++ dev_priv->has_gmr = true; ++ if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) || ++ refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR, ++ VMW_PL_GMR) != 0) { ++ DRM_INFO("No GMR memory available. " ++ "Graphics memory resources are very limited.\n"); ++ dev_priv->has_gmr = false; ++ } ++ ++ if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) { ++ dev_priv->has_mob = true; ++ if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB, ++ VMW_PL_MOB) != 0) { ++ DRM_INFO("No MOB memory available. " ++ "3D will be disabled.\n"); ++ dev_priv->has_mob = false; ++ } ++ } ++ + vmw_kms_save_vga(dev_priv); + + /* Start kms and overlay systems, needs fifo. */ +@@ -846,6 +847,12 @@ out_no_fifo: + vmw_kms_close(dev_priv); + out_no_kms: + vmw_kms_restore_vga(dev_priv); ++ if (dev_priv->has_mob) ++ (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); ++ if (dev_priv->has_gmr) ++ (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); ++ (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); ++out_no_vram: + vmw_fence_manager_takedown(dev_priv->fman); + out_no_fman: + if (dev_priv->capabilities & SVGA_CAP_IRQMASK) +@@ -861,12 +868,6 @@ out_err4: + iounmap(dev_priv->mmio_virt); + out_err3: + arch_phys_wc_del(dev_priv->mmio_mtrr); +- if (dev_priv->has_mob) +- (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); +- if (dev_priv->has_gmr) +- (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); +- (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); +-out_err2: + (void)ttm_bo_device_release(&dev_priv->bdev); + out_err1: + vmw_ttm_global_release(dev_priv); +@@ -896,6 +897,13 @@ static int vmw_driver_unload(struct drm_device *dev) + } + vmw_kms_close(dev_priv); + vmw_overlay_close(dev_priv); ++ ++ if (dev_priv->has_mob) ++ (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); ++ if (dev_priv->has_gmr) ++ (void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); ++ (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); ++ + vmw_fence_manager_takedown(dev_priv->fman); + if (dev_priv->capabilities & SVGA_CAP_IRQMASK) + drm_irq_uninstall(dev_priv->dev); +@@ -907,11 +915,6 @@ static int vmw_driver_unload(struct drm_device *dev) + ttm_object_device_release(&dev_priv->tdev); + iounmap(dev_priv->mmio_virt); + arch_phys_wc_del(dev_priv->mmio_mtrr); +- if (dev_priv->has_mob) +- (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); +- if (dev_priv->has_gmr) +- (void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); +- (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); + (void)ttm_bo_device_release(&dev_priv->bdev); + vmw_ttm_global_release(dev_priv); + +diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c +index 51e15fd53108..d058b00ba218 100644 +--- a/drivers/mtd/nand/pxa3xx_nand.c ++++ b/drivers/mtd/nand/pxa3xx_nand.c +@@ -481,6 +481,42 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) + nand_writel(info, NDCR, ndcr | int_mask); + } + ++static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len) ++{ ++ if (info->ecc_bch) { ++ int timeout; ++ ++ /* ++ * According to the datasheet, when reading from NDDB ++ * with BCH enabled, after each 32 bytes reads, we ++ * have to make sure that the NDSR.RDDREQ bit is set. ++ * ++ * Drain the FIFO 8 32 bits reads at a time, and skip ++ * the polling on the last read. ++ */ ++ while (len > 8) { ++ __raw_readsl(info->mmio_base + NDDB, data, 8); ++ ++ for (timeout = 0; ++ !(nand_readl(info, NDSR) & NDSR_RDDREQ); ++ timeout++) { ++ if (timeout >= 5) { ++ dev_err(&info->pdev->dev, ++ "Timeout on RDDREQ while draining the FIFO\n"); ++ return; ++ } ++ ++ mdelay(1); ++ } ++ ++ data += 32; ++ len -= 8; ++ } ++ } ++ ++ __raw_readsl(info->mmio_base + NDDB, data, len); ++} ++ + static void handle_data_pio(struct pxa3xx_nand_info *info) + { + unsigned int do_bytes = min(info->data_size, info->chunk_size); +@@ -497,14 +533,14 @@ static void handle_data_pio(struct pxa3xx_nand_info *info) + DIV_ROUND_UP(info->oob_size, 4)); + break; + case STATE_PIO_READING: +- __raw_readsl(info->mmio_base + NDDB, +- info->data_buff + info->data_buff_pos, +- DIV_ROUND_UP(do_bytes, 4)); ++ drain_fifo(info, ++ info->data_buff + info->data_buff_pos, ++ DIV_ROUND_UP(do_bytes, 4)); + + if (info->oob_size > 0) +- __raw_readsl(info->mmio_base + NDDB, +- info->oob_buff + info->oob_buff_pos, +- DIV_ROUND_UP(info->oob_size, 4)); ++ drain_fifo(info, ++ info->oob_buff + info->oob_buff_pos, ++ DIV_ROUND_UP(info->oob_size, 4)); + break; + default: + dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__, +diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c +index 1468c4658804..84ad2b44377c 100644 +--- a/drivers/net/can/dev.c ++++ b/drivers/net/can/dev.c +@@ -502,6 +502,14 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf) + skb->pkt_type = PACKET_BROADCAST; + skb->ip_summed = CHECKSUM_UNNECESSARY; + ++ skb_reset_mac_header(skb); ++ skb_reset_network_header(skb); ++ skb_reset_transport_header(skb); ++ ++ skb_reset_mac_header(skb); ++ skb_reset_network_header(skb); ++ skb_reset_transport_header(skb); ++ + can_skb_reserve(skb); + can_skb_prv(skb)->ifindex = dev->ifindex; + +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +index 7d4382286457..242874041ba4 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +@@ -12395,6 +12395,9 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev, + pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS, + PCICFG_VENDOR_ID_OFFSET); + ++ /* Set PCIe reset type to fundamental for EEH recovery */ ++ pdev->needs_freset = 1; ++ + /* AER (Advanced Error reporting) configuration */ + rc = pci_enable_pcie_error_reporting(pdev); + if (!rc) +diff --git a/drivers/net/usb/cx82310_eth.c b/drivers/net/usb/cx82310_eth.c +index 3eed708a6182..fe48f4c51373 100644 +--- a/drivers/net/usb/cx82310_eth.c ++++ b/drivers/net/usb/cx82310_eth.c +@@ -300,9 +300,18 @@ static const struct driver_info cx82310_info = { + .tx_fixup = cx82310_tx_fixup, + }; + ++#define USB_DEVICE_CLASS(vend, prod, cl, sc, pr) \ ++ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ ++ USB_DEVICE_ID_MATCH_DEV_INFO, \ ++ .idVendor = (vend), \ ++ .idProduct = (prod), \ ++ .bDeviceClass = (cl), \ ++ .bDeviceSubClass = (sc), \ ++ .bDeviceProtocol = (pr) ++ + static const struct usb_device_id products[] = { + { +- USB_DEVICE_AND_INTERFACE_INFO(0x0572, 0xcb01, 0xff, 0, 0), ++ USB_DEVICE_CLASS(0x0572, 0xcb01, 0xff, 0, 0), + .driver_info = (unsigned long) &cx82310_info + }, + { }, +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index b7984044232d..5d8d2dcd975e 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1764,10 +1764,12 @@ static int _regulator_do_enable(struct regulator_dev *rdev) + trace_regulator_enable(rdev_get_name(rdev)); + + if (rdev->ena_pin) { +- ret = regulator_ena_gpio_ctrl(rdev, true); +- if (ret < 0) +- return ret; +- rdev->ena_gpio_state = 1; ++ if (!rdev->ena_gpio_state) { ++ ret = regulator_ena_gpio_ctrl(rdev, true); ++ if (ret < 0) ++ return ret; ++ rdev->ena_gpio_state = 1; ++ } + } else if (rdev->desc->ops->enable) { + ret = rdev->desc->ops->enable(rdev); + if (ret < 0) +@@ -1897,10 +1899,12 @@ static int _regulator_do_disable(struct regulator_dev *rdev) + trace_regulator_disable(rdev_get_name(rdev)); + + if (rdev->ena_pin) { +- ret = regulator_ena_gpio_ctrl(rdev, false); +- if (ret < 0) +- return ret; +- rdev->ena_gpio_state = 0; ++ if (rdev->ena_gpio_state) { ++ ret = regulator_ena_gpio_ctrl(rdev, false); ++ if (ret < 0) ++ return ret; ++ rdev->ena_gpio_state = 0; ++ } + + } else if (rdev->desc->ops->disable) { + ret = rdev->desc->ops->disable(rdev); +@@ -3454,12 +3458,6 @@ regulator_register(const struct regulator_desc *regulator_desc, + config->ena_gpio, ret); + goto wash; + } +- +- if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH) +- rdev->ena_gpio_state = 1; +- +- if (config->ena_gpio_invert) +- rdev->ena_gpio_state = !rdev->ena_gpio_state; + } + + /* set regulator constraints */ +@@ -3631,9 +3629,11 @@ int regulator_suspend_finish(void) + list_for_each_entry(rdev, ®ulator_list, list) { + mutex_lock(&rdev->mutex); + if (rdev->use_count > 0 || rdev->constraints->always_on) { +- error = _regulator_do_enable(rdev); +- if (error) +- ret = error; ++ if (!_regulator_is_enabled(rdev)) { ++ error = _regulator_do_enable(rdev); ++ if (error) ++ ret = error; ++ } + } else { + if (!have_full_constraints()) + goto unlock; +diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c +index 62b58d38ce2e..60de66252fa2 100644 +--- a/drivers/scsi/libsas/sas_discover.c ++++ b/drivers/scsi/libsas/sas_discover.c +@@ -500,6 +500,7 @@ static void sas_revalidate_domain(struct work_struct *work) + struct sas_discovery_event *ev = to_sas_discovery_event(work); + struct asd_sas_port *port = ev->port; + struct sas_ha_struct *ha = port->ha; ++ struct domain_device *ddev = port->port_dev; + + /* prevent revalidation from finding sata links in recovery */ + mutex_lock(&ha->disco_mutex); +@@ -514,8 +515,9 @@ static void sas_revalidate_domain(struct work_struct *work) + SAS_DPRINTK("REVALIDATING DOMAIN on port %d, pid:%d\n", port->id, + task_pid_nr(current)); + +- if (port->port_dev) +- res = sas_ex_revalidate_domain(port->port_dev); ++ if (ddev && (ddev->dev_type == SAS_FANOUT_EXPANDER_DEVICE || ++ ddev->dev_type == SAS_EDGE_EXPANDER_DEVICE)) ++ res = sas_ex_revalidate_domain(ddev); + + SAS_DPRINTK("done REVALIDATING DOMAIN on port %d, pid:%d, res 0x%x\n", + port->id, task_pid_nr(current), res); +diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c +index 5d7b07f08326..5f8c6d2f4df7 100644 +--- a/drivers/spi/spi-atmel.c ++++ b/drivers/spi/spi-atmel.c +@@ -781,17 +781,17 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master, + (unsigned long long)xfer->rx_dma); + } + +- /* REVISIT: We're waiting for ENDRX before we start the next ++ /* REVISIT: We're waiting for RXBUFF before we start the next + * transfer because we need to handle some difficult timing +- * issues otherwise. If we wait for ENDTX in one transfer and +- * then starts waiting for ENDRX in the next, it's difficult +- * to tell the difference between the ENDRX interrupt we're +- * actually waiting for and the ENDRX interrupt of the ++ * issues otherwise. If we wait for TXBUFE in one transfer and ++ * then starts waiting for RXBUFF in the next, it's difficult ++ * to tell the difference between the RXBUFF interrupt we're ++ * actually waiting for and the RXBUFF interrupt of the + * previous transfer. + * + * It should be doable, though. Just not now... + */ +- spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES)); ++ spi_writel(as, IER, SPI_BIT(RXBUFF) | SPI_BIT(OVRES)); + spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN)); + } + +diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c +index 971855e859c7..fe091a87fd6d 100644 +--- a/drivers/spi/spi-pl022.c ++++ b/drivers/spi/spi-pl022.c +@@ -503,12 +503,12 @@ static void giveback(struct pl022 *pl022) + pl022->cur_msg = NULL; + pl022->cur_transfer = NULL; + pl022->cur_chip = NULL; +- spi_finalize_current_message(pl022->master); + + /* disable the SPI/SSP operation */ + writew((readw(SSP_CR1(pl022->virtbase)) & + (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); + ++ spi_finalize_current_message(pl022->master); + } + + /** +diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c +index be89260c23a6..27e1a6e62d06 100644 +--- a/drivers/staging/iio/adc/mxs-lradc.c ++++ b/drivers/staging/iio/adc/mxs-lradc.c +@@ -1159,7 +1159,6 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) + LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2)); + } + +- if (iio_buffer_enabled(iio)) + if (iio_buffer_enabled(iio)) { + if (reg & lradc->buffer_vchans) + iio_trigger_poll(iio->trig, iio_get_time_ns()); +diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c +index 104f29e6b290..e168a63e77ea 100644 +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -4196,11 +4196,17 @@ int iscsit_close_connection( + pr_debug("Closing iSCSI connection CID %hu on SID:" + " %u\n", conn->cid, sess->sid); + /* +- * Always up conn_logout_comp just in case the RX Thread is sleeping +- * and the logout response never got sent because the connection +- * failed. ++ * Always up conn_logout_comp for the traditional TCP case just in case ++ * the RX Thread in iscsi_target_rx_opcode() is sleeping and the logout ++ * response never got sent because the connection failed. ++ * ++ * However for iser-target, isert_wait4logout() is using conn_logout_comp ++ * to signal logout response TX interrupt completion. Go ahead and skip ++ * this for iser since isert_rx_opcode() does not wait on logout failure, ++ * and to avoid iscsi_conn pointer dereference in iser-target code. + */ +- complete(&conn->conn_logout_comp); ++ if (conn->conn_transport->transport_type == ISCSI_TCP) ++ complete(&conn->conn_logout_comp); + + iscsi_release_thread_set(conn); + +diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c +index 26ae6886ac59..093b8cb85de7 100644 +--- a/drivers/target/target_core_device.c ++++ b/drivers/target/target_core_device.c +@@ -1591,8 +1591,6 @@ int target_configure_device(struct se_device *dev) + ret = dev->transport->configure_device(dev); + if (ret) + goto out; +- dev->dev_flags |= DF_CONFIGURED; +- + /* + * XXX: there is not much point to have two different values here.. + */ +@@ -1654,6 +1652,8 @@ int target_configure_device(struct se_device *dev) + list_add_tail(&dev->g_dev_node, &g_device_list); + mutex_unlock(&g_device_mutex); + ++ dev->dev_flags |= DF_CONFIGURED; ++ + return 0; + + out_free_alua: +diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c +index 0fccdcfd1015..70cb37516d40 100644 +--- a/drivers/target/target_core_pr.c ++++ b/drivers/target/target_core_pr.c +@@ -76,7 +76,7 @@ enum preempt_type { + }; + + static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, +- struct t10_pr_registration *, int); ++ struct t10_pr_registration *, int, int); + + static sense_reason_t + target_scsi2_reservation_check(struct se_cmd *cmd) +@@ -528,6 +528,18 @@ static int core_scsi3_pr_seq_non_holder( + + return 0; + } ++ } else if (we && registered_nexus) { ++ /* ++ * Reads are allowed for Write Exclusive locks ++ * from all registrants. ++ */ ++ if (cmd->data_direction == DMA_FROM_DEVICE) { ++ pr_debug("Allowing READ CDB: 0x%02x for %s" ++ " reservation\n", cdb[0], ++ core_scsi3_pr_dump_type(pr_reg_type)); ++ ++ return 0; ++ } + } + pr_debug("%s Conflict for %sregistered nexus %s CDB: 0x%2x" + " for %s reservation\n", transport_dump_cmd_direction(cmd), +@@ -1186,7 +1198,7 @@ static int core_scsi3_check_implicit_release( + * service action with the SERVICE ACTION RESERVATION KEY + * field set to zero (see 5.7.11.3). + */ +- __core_scsi3_complete_pro_release(dev, nacl, pr_reg, 0); ++ __core_scsi3_complete_pro_release(dev, nacl, pr_reg, 0, 1); + ret = 1; + /* + * For 'All Registrants' reservation types, all existing +@@ -1228,7 +1240,8 @@ static void __core_scsi3_free_registration( + + pr_reg->pr_reg_deve->def_pr_registered = 0; + pr_reg->pr_reg_deve->pr_res_key = 0; +- list_del(&pr_reg->pr_reg_list); ++ if (!list_empty(&pr_reg->pr_reg_list)) ++ list_del(&pr_reg->pr_reg_list); + /* + * Caller accessing *pr_reg using core_scsi3_locate_pr_reg(), + * so call core_scsi3_put_pr_reg() to decrement our reference. +@@ -1280,6 +1293,7 @@ void core_scsi3_free_pr_reg_from_nacl( + { + struct t10_reservation *pr_tmpl = &dev->t10_pr; + struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder; ++ bool free_reg = false; + /* + * If the passed se_node_acl matches the reservation holder, + * release the reservation. +@@ -1287,13 +1301,18 @@ void core_scsi3_free_pr_reg_from_nacl( + spin_lock(&dev->dev_reservation_lock); + pr_res_holder = dev->dev_pr_res_holder; + if ((pr_res_holder != NULL) && +- (pr_res_holder->pr_reg_nacl == nacl)) +- __core_scsi3_complete_pro_release(dev, nacl, pr_res_holder, 0); ++ (pr_res_holder->pr_reg_nacl == nacl)) { ++ __core_scsi3_complete_pro_release(dev, nacl, pr_res_holder, 0, 1); ++ free_reg = true; ++ } + spin_unlock(&dev->dev_reservation_lock); + /* + * Release any registration associated with the struct se_node_acl. + */ + spin_lock(&pr_tmpl->registration_lock); ++ if (pr_res_holder && free_reg) ++ __core_scsi3_free_registration(dev, pr_res_holder, NULL, 0); ++ + list_for_each_entry_safe(pr_reg, pr_reg_tmp, + &pr_tmpl->registration_list, pr_reg_list) { + +@@ -1316,7 +1335,7 @@ void core_scsi3_free_all_registrations( + if (pr_res_holder != NULL) { + struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl; + __core_scsi3_complete_pro_release(dev, pr_res_nacl, +- pr_res_holder, 0); ++ pr_res_holder, 0, 0); + } + spin_unlock(&dev->dev_reservation_lock); + +@@ -2126,13 +2145,13 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, + /* + * sa_res_key=0 Unregister Reservation Key for registered I_T Nexus. + */ +- pr_holder = core_scsi3_check_implicit_release( +- cmd->se_dev, pr_reg); ++ type = pr_reg->pr_res_type; ++ pr_holder = core_scsi3_check_implicit_release(cmd->se_dev, ++ pr_reg); + if (pr_holder < 0) { + ret = TCM_RESERVATION_CONFLICT; + goto out; + } +- type = pr_reg->pr_res_type; + + spin_lock(&pr_tmpl->registration_lock); + /* +@@ -2290,6 +2309,7 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) + spin_lock(&dev->dev_reservation_lock); + pr_res_holder = dev->dev_pr_res_holder; + if (pr_res_holder) { ++ int pr_res_type = pr_res_holder->pr_res_type; + /* + * From spc4r17 Section 5.7.9: Reserving: + * +@@ -2300,7 +2320,9 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) + * the logical unit, then the command shall be completed with + * RESERVATION CONFLICT status. + */ +- if (pr_res_holder != pr_reg) { ++ if ((pr_res_holder != pr_reg) && ++ (pr_res_type != PR_TYPE_WRITE_EXCLUSIVE_ALLREG) && ++ (pr_res_type != PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) { + struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl; + pr_err("SPC-3 PR: Attempted RESERVE from" + " [%s]: %s while reservation already held by" +@@ -2406,23 +2428,59 @@ static void __core_scsi3_complete_pro_release( + struct se_device *dev, + struct se_node_acl *se_nacl, + struct t10_pr_registration *pr_reg, +- int explicit) ++ int explicit, ++ int unreg) + { + struct target_core_fabric_ops *tfo = se_nacl->se_tpg->se_tpg_tfo; + char i_buf[PR_REG_ISID_ID_LEN]; ++ int pr_res_type = 0, pr_res_scope = 0; + + memset(i_buf, 0, PR_REG_ISID_ID_LEN); + core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); + /* + * Go ahead and release the current PR reservation holder. ++ * If an All Registrants reservation is currently active and ++ * a unregister operation is requested, replace the current ++ * dev_pr_res_holder with another active registration. + */ +- dev->dev_pr_res_holder = NULL; ++ if (dev->dev_pr_res_holder) { ++ pr_res_type = dev->dev_pr_res_holder->pr_res_type; ++ pr_res_scope = dev->dev_pr_res_holder->pr_res_scope; ++ dev->dev_pr_res_holder->pr_res_type = 0; ++ dev->dev_pr_res_holder->pr_res_scope = 0; ++ dev->dev_pr_res_holder->pr_res_holder = 0; ++ dev->dev_pr_res_holder = NULL; ++ } ++ if (!unreg) ++ goto out; + +- pr_debug("SPC-3 PR [%s] Service Action: %s RELEASE cleared" +- " reservation holder TYPE: %s ALL_TG_PT: %d\n", +- tfo->get_fabric_name(), (explicit) ? "explicit" : "implicit", +- core_scsi3_pr_dump_type(pr_reg->pr_res_type), +- (pr_reg->pr_reg_all_tg_pt) ? 1 : 0); ++ spin_lock(&dev->t10_pr.registration_lock); ++ list_del_init(&pr_reg->pr_reg_list); ++ /* ++ * If the I_T nexus is a reservation holder, the persistent reservation ++ * is of an all registrants type, and the I_T nexus is the last remaining ++ * registered I_T nexus, then the device server shall also release the ++ * persistent reservation. ++ */ ++ if (!list_empty(&dev->t10_pr.registration_list) && ++ ((pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) || ++ (pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG))) { ++ dev->dev_pr_res_holder = ++ list_entry(dev->t10_pr.registration_list.next, ++ struct t10_pr_registration, pr_reg_list); ++ dev->dev_pr_res_holder->pr_res_type = pr_res_type; ++ dev->dev_pr_res_holder->pr_res_scope = pr_res_scope; ++ dev->dev_pr_res_holder->pr_res_holder = 1; ++ } ++ spin_unlock(&dev->t10_pr.registration_lock); ++out: ++ if (!dev->dev_pr_res_holder) { ++ pr_debug("SPC-3 PR [%s] Service Action: %s RELEASE cleared" ++ " reservation holder TYPE: %s ALL_TG_PT: %d\n", ++ tfo->get_fabric_name(), (explicit) ? "explicit" : ++ "implicit", core_scsi3_pr_dump_type(pr_res_type), ++ (pr_reg->pr_reg_all_tg_pt) ? 1 : 0); ++ } + pr_debug("SPC-3 PR [%s] RELEASE Node: %s%s\n", + tfo->get_fabric_name(), se_nacl->initiatorname, + i_buf); +@@ -2553,7 +2611,7 @@ core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope, + * server shall not establish a unit attention condition. + */ + __core_scsi3_complete_pro_release(dev, se_sess->se_node_acl, +- pr_reg, 1); ++ pr_reg, 1, 0); + + spin_unlock(&dev->dev_reservation_lock); + +@@ -2641,7 +2699,7 @@ core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key) + if (pr_res_holder) { + struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl; + __core_scsi3_complete_pro_release(dev, pr_res_nacl, +- pr_res_holder, 0); ++ pr_res_holder, 0, 0); + } + spin_unlock(&dev->dev_reservation_lock); + /* +@@ -2700,7 +2758,7 @@ static void __core_scsi3_complete_pro_preempt( + */ + if (dev->dev_pr_res_holder) + __core_scsi3_complete_pro_release(dev, nacl, +- dev->dev_pr_res_holder, 0); ++ dev->dev_pr_res_holder, 0, 0); + + dev->dev_pr_res_holder = pr_reg; + pr_reg->pr_res_holder = 1; +@@ -2944,8 +3002,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, + */ + if (pr_reg_n != pr_res_holder) + __core_scsi3_complete_pro_release(dev, +- pr_res_holder->pr_reg_nacl, +- dev->dev_pr_res_holder, 0); ++ pr_res_holder->pr_reg_nacl, ++ dev->dev_pr_res_holder, 0, 0); + /* + * b) Remove the registrations for all I_T nexuses identified + * by the SERVICE ACTION RESERVATION KEY field, except the +@@ -3415,7 +3473,7 @@ after_iport_check: + * holder (i.e., the I_T nexus on which the + */ + __core_scsi3_complete_pro_release(dev, pr_res_nacl, +- dev->dev_pr_res_holder, 0); ++ dev->dev_pr_res_holder, 0, 0); + /* + * g) Move the persistent reservation to the specified I_T nexus using + * the same scope and type as the persistent reservation released in +@@ -3855,7 +3913,8 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) + unsigned char *buf; + u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len; + u32 off = 8; /* off into first Full Status descriptor */ +- int format_code = 0; ++ int format_code = 0, pr_res_type = 0, pr_res_scope = 0; ++ bool all_reg = false; + + if (cmd->data_length < 8) { + pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u" +@@ -3872,6 +3931,19 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) + buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); + buf[3] = (dev->t10_pr.pr_generation & 0xff); + ++ spin_lock(&dev->dev_reservation_lock); ++ if (dev->dev_pr_res_holder) { ++ struct t10_pr_registration *pr_holder = dev->dev_pr_res_holder; ++ ++ if (pr_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG || ++ pr_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG) { ++ all_reg = true; ++ pr_res_type = pr_holder->pr_res_type; ++ pr_res_scope = pr_holder->pr_res_scope; ++ } ++ } ++ spin_unlock(&dev->dev_reservation_lock); ++ + spin_lock(&pr_tmpl->registration_lock); + list_for_each_entry_safe(pr_reg, pr_reg_tmp, + &pr_tmpl->registration_list, pr_reg_list) { +@@ -3921,14 +3993,20 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) + * reservation holder for PR_HOLDER bit. + * + * Also, if this registration is the reservation +- * holder, fill in SCOPE and TYPE in the next byte. ++ * holder or there is an All Registrants reservation ++ * active, fill in SCOPE and TYPE in the next byte. + */ + if (pr_reg->pr_res_holder) { + buf[off++] |= 0x01; + buf[off++] = (pr_reg->pr_res_scope & 0xf0) | + (pr_reg->pr_res_type & 0x0f); +- } else ++ } else if (all_reg) { ++ buf[off++] |= 0x01; ++ buf[off++] = (pr_res_scope & 0xf0) | ++ (pr_res_type & 0x0f); ++ } else { + off += 2; ++ } + + off += 4; /* Skip over reserved area */ + /* +diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c +index 0f199f6a0738..29f28808fc03 100644 +--- a/drivers/target/target_core_pscsi.c ++++ b/drivers/target/target_core_pscsi.c +@@ -1111,7 +1111,7 @@ static u32 pscsi_get_device_type(struct se_device *dev) + struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); + struct scsi_device *sd = pdv->pdv_sd; + +- return sd->type; ++ return (sd) ? sd->type : TYPE_NO_LUN; + } + + static sector_t pscsi_get_blocks(struct se_device *dev) +diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c +index e6463ef33cd2..9e54c0fe718d 100644 +--- a/drivers/target/target_core_transport.c ++++ b/drivers/target/target_core_transport.c +@@ -2327,6 +2327,10 @@ int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd, + list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list); + out: + spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); ++ ++ if (ret && ack_kref) ++ target_put_sess_cmd(se_sess, se_cmd); ++ + return ret; + } + EXPORT_SYMBOL(target_get_sess_cmd); +diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c +index feda34404ed0..5892eab03874 100644 +--- a/drivers/tty/serial/8250/8250_pci.c ++++ b/drivers/tty/serial/8250/8250_pci.c +@@ -66,7 +66,7 @@ static void moan_device(const char *str, struct pci_dev *dev) + "Please send the output of lspci -vv, this\n" + "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n" + "manufacturer and name of serial board or\n" +- "modem board to rmk+serial@arm.linux.org.uk.\n", ++ "modem board to .\n", + pci_name(dev), str, dev->vendor, dev->device, + dev->subsystem_vendor, dev->subsystem_device); + } +diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c +index f4a9e3311297..c8860a8757ac 100644 +--- a/drivers/xen/events/events_base.c ++++ b/drivers/xen/events/events_base.c +@@ -547,20 +547,26 @@ static unsigned int __startup_pirq(unsigned int irq) + pirq_query_unmask(irq); + + rc = set_evtchn_to_irq(evtchn, irq); +- if (rc != 0) { +- pr_err("irq%d: Failed to set port to irq mapping (%d)\n", +- irq, rc); +- xen_evtchn_close(evtchn); +- return 0; +- } ++ if (rc) ++ goto err; ++ + bind_evtchn_to_cpu(evtchn, 0); + info->evtchn = evtchn; + ++ rc = xen_evtchn_port_setup(info); ++ if (rc) ++ goto err; ++ + out: + unmask_evtchn(evtchn); + eoi_pirq(irq_get_irq_data(irq)); + + return 0; ++ ++err: ++ pr_err("irq%d: Failed to set port to irq mapping (%d)\n", irq, rc); ++ xen_evtchn_close(evtchn); ++ return 0; + } + + static unsigned int startup_pirq(struct irq_data *data) +diff --git a/drivers/xen/xen-pciback/conf_space.c b/drivers/xen/xen-pciback/conf_space.c +index 46ae0f9f02ad..75fe3d466515 100644 +--- a/drivers/xen/xen-pciback/conf_space.c ++++ b/drivers/xen/xen-pciback/conf_space.c +@@ -16,7 +16,7 @@ + #include "conf_space.h" + #include "conf_space_quirks.h" + +-static bool permissive; ++bool permissive; + module_param(permissive, bool, 0644); + + /* This is where xen_pcibk_read_config_byte, xen_pcibk_read_config_word, +diff --git a/drivers/xen/xen-pciback/conf_space.h b/drivers/xen/xen-pciback/conf_space.h +index e56c934ad137..2e1d73d1d5d0 100644 +--- a/drivers/xen/xen-pciback/conf_space.h ++++ b/drivers/xen/xen-pciback/conf_space.h +@@ -64,6 +64,8 @@ struct config_field_entry { + void *data; + }; + ++extern bool permissive; ++ + #define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset) + + /* Add fields to a device - the add_fields macro expects to get a pointer to +diff --git a/drivers/xen/xen-pciback/conf_space_header.c b/drivers/xen/xen-pciback/conf_space_header.c +index c5ee82587e8c..2d7369391472 100644 +--- a/drivers/xen/xen-pciback/conf_space_header.c ++++ b/drivers/xen/xen-pciback/conf_space_header.c +@@ -11,6 +11,10 @@ + #include "pciback.h" + #include "conf_space.h" + ++struct pci_cmd_info { ++ u16 val; ++}; ++ + struct pci_bar_info { + u32 val; + u32 len_val; +@@ -20,22 +24,36 @@ struct pci_bar_info { + #define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO)) + #define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER) + +-static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data) ++/* Bits guests are allowed to control in permissive mode. */ ++#define PCI_COMMAND_GUEST (PCI_COMMAND_MASTER|PCI_COMMAND_SPECIAL| \ ++ PCI_COMMAND_INVALIDATE|PCI_COMMAND_VGA_PALETTE| \ ++ PCI_COMMAND_WAIT|PCI_COMMAND_FAST_BACK) ++ ++static void *command_init(struct pci_dev *dev, int offset) + { +- int i; +- int ret; +- +- ret = xen_pcibk_read_config_word(dev, offset, value, data); +- if (!pci_is_enabled(dev)) +- return ret; +- +- for (i = 0; i < PCI_ROM_RESOURCE; i++) { +- if (dev->resource[i].flags & IORESOURCE_IO) +- *value |= PCI_COMMAND_IO; +- if (dev->resource[i].flags & IORESOURCE_MEM) +- *value |= PCI_COMMAND_MEMORY; ++ struct pci_cmd_info *cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); ++ int err; ++ ++ if (!cmd) ++ return ERR_PTR(-ENOMEM); ++ ++ err = pci_read_config_word(dev, PCI_COMMAND, &cmd->val); ++ if (err) { ++ kfree(cmd); ++ return ERR_PTR(err); + } + ++ return cmd; ++} ++ ++static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data) ++{ ++ int ret = pci_read_config_word(dev, offset, value); ++ const struct pci_cmd_info *cmd = data; ++ ++ *value &= PCI_COMMAND_GUEST; ++ *value |= cmd->val & ~PCI_COMMAND_GUEST; ++ + return ret; + } + +@@ -43,6 +61,8 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) + { + struct xen_pcibk_dev_data *dev_data; + int err; ++ u16 val; ++ struct pci_cmd_info *cmd = data; + + dev_data = pci_get_drvdata(dev); + if (!pci_is_enabled(dev) && is_enable_cmd(value)) { +@@ -83,6 +103,19 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) + } + } + ++ cmd->val = value; ++ ++ if (!permissive && (!dev_data || !dev_data->permissive)) ++ return 0; ++ ++ /* Only allow the guest to control certain bits. */ ++ err = pci_read_config_word(dev, offset, &val); ++ if (err || val == value) ++ return err; ++ ++ value &= PCI_COMMAND_GUEST; ++ value |= val & ~PCI_COMMAND_GUEST; ++ + return pci_write_config_word(dev, offset, value); + } + +@@ -282,6 +315,8 @@ static const struct config_field header_common[] = { + { + .offset = PCI_COMMAND, + .size = 2, ++ .init = command_init, ++ .release = bar_release, + .u.w.read = command_read, + .u.w.write = command_write, + }, +diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c +index 6eb13c621a14..499155ca3e84 100644 +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -819,8 +819,8 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) + + newpage = buf->page; + +- if (WARN_ON(!PageUptodate(newpage))) +- return -EIO; ++ if (!PageUptodate(newpage)) ++ SetPageUptodate(newpage); + + ClearPageMappedToDisk(newpage); + +@@ -1726,6 +1726,9 @@ copy_finish: + static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, + unsigned int size, struct fuse_copy_state *cs) + { ++ /* Don't try to move pages (yet) */ ++ cs->move_pages = 0; ++ + switch (code) { + case FUSE_NOTIFY_POLL: + return fuse_notify_poll(fc, size, cs); +diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c +index 5bee81674d53..14538a865102 100644 +--- a/fs/nilfs2/segment.c ++++ b/fs/nilfs2/segment.c +@@ -1906,6 +1906,7 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, + struct the_nilfs *nilfs) + { + struct nilfs_inode_info *ii, *n; ++ int during_mount = !(sci->sc_super->s_flags & MS_ACTIVE); + int defer_iput = false; + + spin_lock(&nilfs->ns_inode_lock); +@@ -1918,10 +1919,10 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, + brelse(ii->i_bh); + ii->i_bh = NULL; + list_del_init(&ii->i_dirty); +- if (!ii->vfs_inode.i_nlink) { ++ if (!ii->vfs_inode.i_nlink || during_mount) { + /* +- * Defer calling iput() to avoid a deadlock +- * over I_SYNC flag for inodes with i_nlink == 0 ++ * Defer calling iput() to avoid deadlocks if ++ * i_nlink == 0 or mount is not yet finished. + */ + list_add_tail(&ii->i_dirty, &sci->sc_iput_queue); + defer_iput = true; +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index c4b2646b6d7c..c2546717fc2b 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -1227,6 +1227,9 @@ out: + + static int pagemap_open(struct inode *inode, struct file *file) + { ++ /* do not disclose physical addresses: attack vector */ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; + pr_warn_once("Bits 55-60 of /proc/PID/pagemap entries are about " + "to stop being page-shift some time soon. See the " + "linux/Documentation/vm/pagemap.txt for details.\n"); +diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h +index 6c62cfa25f1a..bc9d2c2ddf87 100644 +--- a/include/linux/workqueue.h ++++ b/include/linux/workqueue.h +@@ -71,7 +71,8 @@ enum { + /* data contains off-queue information when !WORK_STRUCT_PWQ */ + WORK_OFFQ_FLAG_BASE = WORK_STRUCT_COLOR_SHIFT, + +- WORK_OFFQ_CANCELING = (1 << WORK_OFFQ_FLAG_BASE), ++ __WORK_OFFQ_CANCELING = WORK_OFFQ_FLAG_BASE, ++ WORK_OFFQ_CANCELING = (1 << __WORK_OFFQ_CANCELING), + + /* + * When a work item is off queue, its high bits point to the last +diff --git a/kernel/cpuset.c b/kernel/cpuset.c +index 2fb2877e6961..7b4530b0b16b 100644 +--- a/kernel/cpuset.c ++++ b/kernel/cpuset.c +@@ -503,9 +503,6 @@ static void update_domain_attr_tree(struct sched_domain_attr *dattr, + + rcu_read_lock(); + cpuset_for_each_descendant_pre(cp, pos_css, root_cs) { +- if (cp == root_cs) +- continue; +- + /* skip the whole subtree if @cp doesn't have any CPU */ + if (cpumask_empty(cp->cpus_allowed)) { + pos_css = css_rightmost_descendant(pos_css); +diff --git a/kernel/printk/console_cmdline.h b/kernel/printk/console_cmdline.h +index cbd69d842341..2ca4a8b5fe57 100644 +--- a/kernel/printk/console_cmdline.h ++++ b/kernel/printk/console_cmdline.h +@@ -3,7 +3,7 @@ + + struct console_cmdline + { +- char name[8]; /* Name of the driver */ ++ char name[16]; /* Name of the driver */ + int index; /* Minor dev. to use */ + char *options; /* Options for the driver */ + #ifdef CONFIG_A11Y_BRAILLE_CONSOLE +diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c +index 8c086e6049b9..a755ad70fe8f 100644 +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -2280,6 +2280,7 @@ void register_console(struct console *newcon) + for (i = 0, c = console_cmdline; + i < MAX_CMDLINECONSOLES && c->name[0]; + i++, c++) { ++ BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name)); + if (strcmp(c->name, newcon->name) != 0) + continue; + if (newcon->index >= 0 && +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index f6f31d823e8e..423c9e37a9e7 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -2893,19 +2893,57 @@ bool flush_work(struct work_struct *work) + } + EXPORT_SYMBOL_GPL(flush_work); + ++struct cwt_wait { ++ wait_queue_t wait; ++ struct work_struct *work; ++}; ++ ++static int cwt_wakefn(wait_queue_t *wait, unsigned mode, int sync, void *key) ++{ ++ struct cwt_wait *cwait = container_of(wait, struct cwt_wait, wait); ++ ++ if (cwait->work != key) ++ return 0; ++ return autoremove_wake_function(wait, mode, sync, key); ++} ++ + static bool __cancel_work_timer(struct work_struct *work, bool is_dwork) + { ++ static DECLARE_WAIT_QUEUE_HEAD(cancel_waitq); + unsigned long flags; + int ret; + + do { + ret = try_to_grab_pending(work, is_dwork, &flags); + /* +- * If someone else is canceling, wait for the same event it +- * would be waiting for before retrying. ++ * If someone else is already canceling, wait for it to ++ * finish. flush_work() doesn't work for PREEMPT_NONE ++ * because we may get scheduled between @work's completion ++ * and the other canceling task resuming and clearing ++ * CANCELING - flush_work() will return false immediately ++ * as @work is no longer busy, try_to_grab_pending() will ++ * return -ENOENT as @work is still being canceled and the ++ * other canceling task won't be able to clear CANCELING as ++ * we're hogging the CPU. ++ * ++ * Let's wait for completion using a waitqueue. As this ++ * may lead to the thundering herd problem, use a custom ++ * wake function which matches @work along with exclusive ++ * wait and wakeup. + */ +- if (unlikely(ret == -ENOENT)) +- flush_work(work); ++ if (unlikely(ret == -ENOENT)) { ++ struct cwt_wait cwait; ++ ++ init_wait(&cwait.wait); ++ cwait.wait.func = cwt_wakefn; ++ cwait.work = work; ++ ++ prepare_to_wait_exclusive(&cancel_waitq, &cwait.wait, ++ TASK_UNINTERRUPTIBLE); ++ if (work_is_canceling(work)) ++ schedule(); ++ finish_wait(&cancel_waitq, &cwait.wait); ++ } + } while (unlikely(ret < 0)); + + /* tell other tasks trying to grab @work to back off */ +@@ -2914,6 +2952,16 @@ static bool __cancel_work_timer(struct work_struct *work, bool is_dwork) + + flush_work(work); + clear_work_data(work); ++ ++ /* ++ * Paired with prepare_to_wait() above so that either ++ * waitqueue_active() is visible here or !work_is_canceling() is ++ * visible there. ++ */ ++ smp_mb(); ++ if (waitqueue_active(&cancel_waitq)) ++ __wake_up(&cancel_waitq, TASK_NORMAL, 1, work); ++ + return ret; + } + +diff --git a/lib/lz4/lz4_decompress.c b/lib/lz4/lz4_decompress.c +index 7a85967060a5..f0f5c5c3de12 100644 +--- a/lib/lz4/lz4_decompress.c ++++ b/lib/lz4/lz4_decompress.c +@@ -139,6 +139,9 @@ static int lz4_uncompress(const char *source, char *dest, int osize) + /* Error: request to write beyond destination buffer */ + if (cpy > oend) + goto _output_error; ++ if ((ref + COPYLENGTH) > oend || ++ (op + COPYLENGTH) > oend) ++ goto _output_error; + LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH)); + while (op < cpy) + *op++ = *ref++; +diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c +index d6be3edb7a43..526bf56f4d31 100644 +--- a/net/caif/caif_socket.c ++++ b/net/caif/caif_socket.c +@@ -283,7 +283,7 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock, + int copylen; + + ret = -EOPNOTSUPP; +- if (m->msg_flags&MSG_OOB) ++ if (flags & MSG_OOB) + goto read_error; + + skb = skb_recv_datagram(sk, flags, 0 , &ret); +diff --git a/net/can/af_can.c b/net/can/af_can.c +index a27f8aad9e99..5e9a2272b7a7 100644 +--- a/net/can/af_can.c ++++ b/net/can/af_can.c +@@ -262,6 +262,9 @@ int can_send(struct sk_buff *skb, int loop) + goto inval_skb; + } + ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ ++ skb_reset_mac_header(skb); + skb_reset_network_header(skb); + skb_reset_transport_header(skb); + +diff --git a/net/compat.c b/net/compat.c +index 275af79c131b..d12529050b29 100644 +--- a/net/compat.c ++++ b/net/compat.c +@@ -71,6 +71,13 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg) + __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || + __get_user(kmsg->msg_flags, &umsg->msg_flags)) + return -EFAULT; ++ ++ if (!tmp1) ++ kmsg->msg_namelen = 0; ++ ++ if (kmsg->msg_namelen < 0) ++ return -EINVAL; ++ + if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) + kmsg->msg_namelen = sizeof(struct sockaddr_storage); + kmsg->msg_name = compat_ptr(tmp1); +diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c +index cf9cd13509a7..e731c96eac4b 100644 +--- a/net/core/sysctl_net_core.c ++++ b/net/core/sysctl_net_core.c +@@ -25,6 +25,8 @@ + static int zero = 0; + static int one = 1; + static int ushort_max = USHRT_MAX; ++static int min_sndbuf = SOCK_MIN_SNDBUF; ++static int min_rcvbuf = SOCK_MIN_RCVBUF; + + #ifdef CONFIG_RPS + static int rps_sock_flow_sysctl(struct ctl_table *table, int write, +@@ -223,7 +225,7 @@ static struct ctl_table net_core_table[] = { + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_sndbuf, + }, + { + .procname = "rmem_max", +@@ -231,7 +233,7 @@ static struct ctl_table net_core_table[] = { + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_rcvbuf, + }, + { + .procname = "wmem_default", +@@ -239,7 +241,7 @@ static struct ctl_table net_core_table[] = { + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_sndbuf, + }, + { + .procname = "rmem_default", +@@ -247,7 +249,7 @@ static struct ctl_table net_core_table[] = { + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_rcvbuf, + }, + { + .procname = "dev_weight", +diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c +index e34dccbc4d70..4eeba4e497a0 100644 +--- a/net/ipv4/inet_diag.c ++++ b/net/ipv4/inet_diag.c +@@ -71,6 +71,20 @@ static inline void inet_diag_unlock_handler( + mutex_unlock(&inet_diag_table_mutex); + } + ++static size_t inet_sk_attr_size(void) ++{ ++ 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(sizeof(struct inet_diag_meminfo)) ++ + nla_total_size(sizeof(struct inet_diag_msg)) ++ + nla_total_size(SK_MEMINFO_VARS * sizeof(u32)) ++ + nla_total_size(TCP_CA_NAME_MAX) ++ + nla_total_size(sizeof(struct tcpvegas_info)) ++ + 64; ++} ++ + int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, + struct sk_buff *skb, struct inet_diag_req_v2 *req, + struct user_namespace *user_ns, +@@ -324,9 +338,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s + if (err) + goto out; + +- rep = nlmsg_new(sizeof(struct inet_diag_msg) + +- sizeof(struct inet_diag_meminfo) + +- sizeof(struct tcp_info) + 64, GFP_KERNEL); ++ rep = nlmsg_new(inet_sk_attr_size(), GFP_KERNEL); + if (!rep) { + err = -ENOMEM; + goto out; +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 7efa26bb872c..d0c310801479 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -2617,15 +2617,11 @@ void tcp_send_fin(struct sock *sk) + } else { + /* Socket is locked, keep trying until memory is available. */ + for (;;) { +- skb = alloc_skb_fclone(MAX_TCP_HEADER, +- sk->sk_allocation); ++ skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation); + if (skb) + break; + yield(); + } +- +- /* Reserve space for headers and prepare control bits. */ +- skb_reserve(skb, MAX_TCP_HEADER); + /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */ + tcp_init_nondata_skb(skb, tp->write_seq, + TCPHDR_ACK | TCPHDR_FIN); +@@ -2899,9 +2895,9 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) + { + struct tcp_sock *tp = tcp_sk(sk); + struct tcp_fastopen_request *fo = tp->fastopen_req; +- int syn_loss = 0, space, i, err = 0, iovlen = fo->data->msg_iovlen; +- struct sk_buff *syn_data = NULL, *data; ++ int syn_loss = 0, space, err = 0; + unsigned long last_syn_loss = 0; ++ struct sk_buff *syn_data; + + tp->rx_opt.mss_clamp = tp->advmss; /* If MSS is not cached */ + tcp_fastopen_cache_get(sk, &tp->rx_opt.mss_clamp, &fo->cookie, +@@ -2932,42 +2928,38 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) + /* limit to order-0 allocations */ + space = min_t(size_t, space, SKB_MAX_HEAD(MAX_TCP_HEADER)); + +- syn_data = skb_copy_expand(syn, MAX_TCP_HEADER, space, +- sk->sk_allocation); +- if (syn_data == NULL) ++ syn_data = sk_stream_alloc_skb(sk, space, sk->sk_allocation); ++ if (!syn_data) + goto fallback; ++ syn_data->ip_summed = CHECKSUM_PARTIAL; ++ memcpy(syn_data->cb, syn->cb, sizeof(syn->cb)); ++ if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space), ++ fo->data->msg_iov, 0, space))) { ++ kfree_skb(syn_data); ++ goto fallback; ++ } + +- for (i = 0; i < iovlen && syn_data->len < space; ++i) { +- struct iovec *iov = &fo->data->msg_iov[i]; +- unsigned char __user *from = iov->iov_base; +- int len = iov->iov_len; +- +- if (syn_data->len + len > space) +- len = space - syn_data->len; +- else if (i + 1 == iovlen) +- /* No more data pending in inet_wait_for_connect() */ +- fo->data = NULL; ++ /* No more data pending in inet_wait_for_connect() */ ++ if (space == fo->size) ++ fo->data = NULL; ++ fo->copied = space; + +- if (skb_add_data(syn_data, from, len)) +- goto fallback; +- } ++ tcp_connect_queue_skb(sk, syn_data); + +- /* Queue a data-only packet after the regular SYN for retransmission */ +- data = pskb_copy(syn_data, sk->sk_allocation); +- if (data == NULL) +- goto fallback; +- TCP_SKB_CB(data)->seq++; +- TCP_SKB_CB(data)->tcp_flags &= ~TCPHDR_SYN; +- TCP_SKB_CB(data)->tcp_flags = (TCPHDR_ACK|TCPHDR_PSH); +- tcp_connect_queue_skb(sk, data); +- fo->copied = data->len; ++ err = tcp_transmit_skb(sk, syn_data, 1, sk->sk_allocation); + +- if (tcp_transmit_skb(sk, syn_data, 0, sk->sk_allocation) == 0) { ++ /* Now full SYN+DATA was cloned and sent (or not), ++ * remove the SYN from the original skb (syn_data) ++ * we keep in write queue in case of a retransmit, as we ++ * also have the SYN packet (with no data) in the same queue. ++ */ ++ TCP_SKB_CB(syn_data)->seq++; ++ TCP_SKB_CB(syn_data)->tcp_flags = TCPHDR_ACK | TCPHDR_PSH; ++ if (!err) { + tp->syn_data = (fo->copied > 0); + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE); + goto done; + } +- syn_data = NULL; + + fallback: + /* Send a regular SYN with Fast Open cookie request option */ +@@ -2976,7 +2968,6 @@ fallback: + err = tcp_transmit_skb(sk, syn, 1, sk->sk_allocation); + if (err) + tp->syn_fastopen = 0; +- kfree_skb(syn_data); + done: + fo->cookie.len = -1; /* Exclude Fast Open option for SYN retries */ + return err; +@@ -2996,13 +2987,10 @@ int tcp_connect(struct sock *sk) + return 0; + } + +- buff = alloc_skb_fclone(MAX_TCP_HEADER + 15, sk->sk_allocation); +- if (unlikely(buff == NULL)) ++ buff = sk_stream_alloc_skb(sk, 0, sk->sk_allocation); ++ if (unlikely(!buff)) + return -ENOBUFS; + +- /* Reserve space for headers. */ +- skb_reserve(buff, MAX_TCP_HEADER); +- + tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN); + tp->retrans_stamp = TCP_SKB_CB(buff)->when = tcp_time_stamp; + tcp_connect_queue_skb(sk, buff); +diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c +index b4d5e1d97c1b..27ca79682efb 100644 +--- a/net/ipv6/fib6_rules.c ++++ b/net/ipv6/fib6_rules.c +@@ -104,6 +104,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, + goto again; + flp6->saddr = saddr; + } ++ err = rt->dst.error; + goto out; + } + again: +diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c +index 27d3f40de3cd..847d2a2c5d05 100644 +--- a/net/netfilter/ipvs/ip_vs_core.c ++++ b/net/netfilter/ipvs/ip_vs_core.c +@@ -658,16 +658,24 @@ static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user) + return err; + } + +-static int ip_vs_route_me_harder(int af, struct sk_buff *skb) ++static int ip_vs_route_me_harder(int af, struct sk_buff *skb, ++ unsigned int hooknum) + { ++ if (!sysctl_snat_reroute(skb)) ++ return 0; ++ /* Reroute replies only to remote clients (FORWARD and LOCAL_OUT) */ ++ if (NF_INET_LOCAL_IN == hooknum) ++ return 0; + #ifdef CONFIG_IP_VS_IPV6 + if (af == AF_INET6) { +- if (sysctl_snat_reroute(skb) && ip6_route_me_harder(skb) != 0) ++ struct dst_entry *dst = skb_dst(skb); ++ ++ if (dst->dev && !(dst->dev->flags & IFF_LOOPBACK) && ++ ip6_route_me_harder(skb) != 0) + return 1; + } else + #endif +- if ((sysctl_snat_reroute(skb) || +- skb_rtable(skb)->rt_flags & RTCF_LOCAL) && ++ if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL) && + ip_route_me_harder(skb, RTN_LOCAL) != 0) + return 1; + +@@ -790,7 +798,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb, + union nf_inet_addr *snet, + __u8 protocol, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, +- unsigned int offset, unsigned int ihl) ++ unsigned int offset, unsigned int ihl, ++ unsigned int hooknum) + { + unsigned int verdict = NF_DROP; + +@@ -820,7 +829,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb, + #endif + ip_vs_nat_icmp(skb, pp, cp, 1); + +- if (ip_vs_route_me_harder(af, skb)) ++ if (ip_vs_route_me_harder(af, skb, hooknum)) + goto out; + + /* do the statistics and put it back */ +@@ -915,7 +924,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related, + + snet.ip = iph->saddr; + return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp, +- pp, ciph.len, ihl); ++ pp, ciph.len, ihl, hooknum); + } + + #ifdef CONFIG_IP_VS_IPV6 +@@ -980,7 +989,8 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related, + snet.in6 = ciph.saddr.in6; + writable = ciph.len; + return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp, +- pp, writable, sizeof(struct ipv6hdr)); ++ pp, writable, sizeof(struct ipv6hdr), ++ hooknum); + } + #endif + +@@ -1039,7 +1049,8 @@ static inline bool is_new_conn(const struct sk_buff *skb, + */ + static unsigned int + handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, +- struct ip_vs_conn *cp, struct ip_vs_iphdr *iph) ++ struct ip_vs_conn *cp, struct ip_vs_iphdr *iph, ++ unsigned int hooknum) + { + struct ip_vs_protocol *pp = pd->pp; + +@@ -1077,7 +1088,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, + * if it came from this machine itself. So re-compute + * the routing information. + */ +- if (ip_vs_route_me_harder(af, skb)) ++ if (ip_vs_route_me_harder(af, skb, hooknum)) + goto drop; + + IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT"); +@@ -1180,7 +1191,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) + cp = pp->conn_out_get(af, skb, &iph, 0); + + if (likely(cp)) +- return handle_response(af, skb, pd, cp, &iph); ++ return handle_response(af, skb, pd, cp, &iph, hooknum); + if (sysctl_nat_icmp_send(net) && + (pp->protocol == IPPROTO_TCP || + pp->protocol == IPPROTO_UDP || +diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c +index db801263ee9f..a8027e73b6a2 100644 +--- a/net/netfilter/ipvs/ip_vs_sync.c ++++ b/net/netfilter/ipvs/ip_vs_sync.c +@@ -891,6 +891,8 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param, + IP_VS_DBG(2, "BACKUP, add new conn. failed\n"); + return; + } ++ if (!(flags & IP_VS_CONN_F_TEMPLATE)) ++ kfree(param->pe_data); + } + + if (opt) +@@ -1164,6 +1166,7 @@ static inline int ip_vs_proc_sync_conn(struct net *net, __u8 *p, __u8 *msg_end) + (opt_flags & IPVS_OPT_F_SEQ_DATA ? &opt : NULL) + ); + #endif ++ ip_vs_pe_put(param.pe); + return 0; + /* Error exit */ + out: +diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c +index ad979612238a..7350723aeb15 100644 +--- a/net/netfilter/nft_compat.c ++++ b/net/netfilter/nft_compat.c +@@ -611,8 +611,12 @@ nft_match_select_ops(const struct nft_ctx *ctx, + struct xt_match *match = nft_match->ops.data; + + if (strcmp(match->name, mt_name) == 0 && +- match->revision == rev && match->family == family) ++ match->revision == rev && match->family == family) { ++ if (!try_module_get(match->me)) ++ return ERR_PTR(-ENOENT); ++ + return &nft_match->ops; ++ } + } + + match = xt_request_find_match(family, mt_name, rev); +@@ -682,8 +686,12 @@ nft_target_select_ops(const struct nft_ctx *ctx, + struct xt_target *target = nft_target->ops.data; + + if (strcmp(target->name, tg_name) == 0 && +- target->revision == rev && target->family == family) ++ target->revision == rev && target->family == family) { ++ if (!try_module_get(target->me)) ++ return ERR_PTR(-ENOENT); ++ + return &nft_target->ops; ++ } + } + + target = xt_request_find_target(family, tg_name, rev); +diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c +index 1ba67931eb1b..13332dbf291d 100644 +--- a/net/netfilter/xt_socket.c ++++ b/net/netfilter/xt_socket.c +@@ -243,12 +243,13 @@ static int + extract_icmp6_fields(const struct sk_buff *skb, + unsigned int outside_hdrlen, + int *protocol, +- struct in6_addr **raddr, +- struct in6_addr **laddr, ++ const struct in6_addr **raddr, ++ const struct in6_addr **laddr, + __be16 *rport, +- __be16 *lport) ++ __be16 *lport, ++ struct ipv6hdr *ipv6_var) + { +- struct ipv6hdr *inside_iph, _inside_iph; ++ const struct ipv6hdr *inside_iph; + struct icmp6hdr *icmph, _icmph; + __be16 *ports, _ports[2]; + u8 inside_nexthdr; +@@ -263,12 +264,14 @@ extract_icmp6_fields(const struct sk_buff *skb, + if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK) + return 1; + +- inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph), sizeof(_inside_iph), &_inside_iph); ++ inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph), ++ sizeof(*ipv6_var), ipv6_var); + if (inside_iph == NULL) + return 1; + inside_nexthdr = inside_iph->nexthdr; + +- inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + sizeof(_inside_iph), ++ inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + ++ sizeof(*ipv6_var), + &inside_nexthdr, &inside_fragoff); + if (inside_hdrlen < 0) + return 1; /* hjm: Packet has no/incomplete transport layer headers. */ +@@ -315,10 +318,10 @@ xt_socket_get_sock_v6(struct net *net, const u8 protocol, + static bool + socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) + { +- struct ipv6hdr *iph = ipv6_hdr(skb); ++ struct ipv6hdr ipv6_var, *iph = ipv6_hdr(skb); + struct udphdr _hdr, *hp = NULL; + struct sock *sk = skb->sk; +- struct in6_addr *daddr = NULL, *saddr = NULL; ++ const struct in6_addr *daddr = NULL, *saddr = NULL; + __be16 uninitialized_var(dport), uninitialized_var(sport); + int thoff = 0, uninitialized_var(tproto); + const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; +@@ -342,7 +345,7 @@ socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) + + } else if (tproto == IPPROTO_ICMPV6) { + if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr, +- &sport, &dport)) ++ &sport, &dport, &ipv6_var)) + return false; + } else { + return false; +diff --git a/net/rds/iw_rdma.c b/net/rds/iw_rdma.c +index a817705ce2d0..dba8d0864f18 100644 +--- a/net/rds/iw_rdma.c ++++ b/net/rds/iw_rdma.c +@@ -88,7 +88,9 @@ static unsigned int rds_iw_unmap_fastreg_list(struct rds_iw_mr_pool *pool, + int *unpinned); + static void rds_iw_destroy_fastreg(struct rds_iw_mr_pool *pool, struct rds_iw_mr *ibmr); + +-static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwdev, struct rdma_cm_id **cm_id) ++static int rds_iw_get_device(struct sockaddr_in *src, struct sockaddr_in *dst, ++ struct rds_iw_device **rds_iwdev, ++ struct rdma_cm_id **cm_id) + { + struct rds_iw_device *iwdev; + struct rds_iw_cm_id *i_cm_id; +@@ -112,15 +114,15 @@ static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwd + src_addr->sin_port, + dst_addr->sin_addr.s_addr, + dst_addr->sin_port, +- rs->rs_bound_addr, +- rs->rs_bound_port, +- rs->rs_conn_addr, +- rs->rs_conn_port); ++ src->sin_addr.s_addr, ++ src->sin_port, ++ dst->sin_addr.s_addr, ++ dst->sin_port); + #ifdef WORKING_TUPLE_DETECTION +- if (src_addr->sin_addr.s_addr == rs->rs_bound_addr && +- src_addr->sin_port == rs->rs_bound_port && +- dst_addr->sin_addr.s_addr == rs->rs_conn_addr && +- dst_addr->sin_port == rs->rs_conn_port) { ++ if (src_addr->sin_addr.s_addr == src->sin_addr.s_addr && ++ src_addr->sin_port == src->sin_port && ++ dst_addr->sin_addr.s_addr == dst->sin_addr.s_addr && ++ dst_addr->sin_port == dst->sin_port) { + #else + /* FIXME - needs to compare the local and remote + * ipaddr/port tuple, but the ipaddr is the only +@@ -128,7 +130,7 @@ static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwd + * zero'ed. It doesn't appear to be properly populated + * during connection setup... + */ +- if (src_addr->sin_addr.s_addr == rs->rs_bound_addr) { ++ if (src_addr->sin_addr.s_addr == src->sin_addr.s_addr) { + #endif + spin_unlock_irq(&iwdev->spinlock); + *rds_iwdev = iwdev; +@@ -180,19 +182,13 @@ int rds_iw_update_cm_id(struct rds_iw_device *rds_iwdev, struct rdma_cm_id *cm_i + { + struct sockaddr_in *src_addr, *dst_addr; + struct rds_iw_device *rds_iwdev_old; +- struct rds_sock rs; + struct rdma_cm_id *pcm_id; + int rc; + + src_addr = (struct sockaddr_in *)&cm_id->route.addr.src_addr; + dst_addr = (struct sockaddr_in *)&cm_id->route.addr.dst_addr; + +- rs.rs_bound_addr = src_addr->sin_addr.s_addr; +- rs.rs_bound_port = src_addr->sin_port; +- rs.rs_conn_addr = dst_addr->sin_addr.s_addr; +- rs.rs_conn_port = dst_addr->sin_port; +- +- rc = rds_iw_get_device(&rs, &rds_iwdev_old, &pcm_id); ++ rc = rds_iw_get_device(src_addr, dst_addr, &rds_iwdev_old, &pcm_id); + if (rc) + rds_iw_remove_cm_id(rds_iwdev, cm_id); + +@@ -598,9 +594,17 @@ void *rds_iw_get_mr(struct scatterlist *sg, unsigned long nents, + struct rds_iw_device *rds_iwdev; + struct rds_iw_mr *ibmr = NULL; + struct rdma_cm_id *cm_id; ++ struct sockaddr_in src = { ++ .sin_addr.s_addr = rs->rs_bound_addr, ++ .sin_port = rs->rs_bound_port, ++ }; ++ struct sockaddr_in dst = { ++ .sin_addr.s_addr = rs->rs_conn_addr, ++ .sin_port = rs->rs_conn_port, ++ }; + int ret; + +- ret = rds_iw_get_device(rs, &rds_iwdev, &cm_id); ++ ret = rds_iw_get_device(&src, &dst, &rds_iwdev, &cm_id); + if (ret || !cm_id) { + ret = -ENODEV; + goto out; +diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c +index 34b5490dde65..4949f753686c 100644 +--- a/net/rxrpc/ar-recvmsg.c ++++ b/net/rxrpc/ar-recvmsg.c +@@ -87,7 +87,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, + if (!skb) { + /* nothing remains on the queue */ + if (copied && +- (msg->msg_flags & MSG_PEEK || timeo == 0)) ++ (flags & MSG_PEEK || timeo == 0)) + goto out; + + /* wait for a message to turn up */ +diff --git a/sound/core/control.c b/sound/core/control.c +index 98a29b26c5f4..f2082a35b890 100644 +--- a/sound/core/control.c ++++ b/sound/core/control.c +@@ -1168,6 +1168,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, + + if (info->count < 1) + return -EINVAL; ++ if (!*info->id.name) ++ return -EINVAL; ++ if (strnlen(info->id.name, sizeof(info->id.name)) >= sizeof(info->id.name)) ++ return -EINVAL; + access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : + (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| + SNDRV_CTL_ELEM_ACCESS_INACTIVE| +diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c +index d9a09bdd09db..9a23bdea97d8 100644 +--- a/sound/pci/hda/hda_generic.c ++++ b/sound/pci/hda/hda_generic.c +@@ -653,12 +653,45 @@ static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid, + return val; + } + ++/* is this a stereo widget or a stereo-to-mono mix? */ ++static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, int dir) ++{ ++ unsigned int wcaps = get_wcaps(codec, nid); ++ hda_nid_t conn; ++ ++ if (wcaps & AC_WCAP_STEREO) ++ return true; ++ if (dir != HDA_INPUT || get_wcaps_type(wcaps) != AC_WID_AUD_MIX) ++ return false; ++ if (snd_hda_get_num_conns(codec, nid) != 1) ++ return false; ++ if (snd_hda_get_connections(codec, nid, &conn, 1) < 0) ++ return false; ++ return !!(get_wcaps(codec, conn) & AC_WCAP_STEREO); ++} ++ + /* initialize the amp value (only at the first time) */ + static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx) + { + unsigned int caps = query_amp_caps(codec, nid, dir); + int val = get_amp_val_to_activate(codec, nid, dir, caps, false); +- snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val); ++ ++ if (is_stereo_amps(codec, nid, dir)) ++ snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val); ++ else ++ snd_hda_codec_amp_init(codec, nid, 0, dir, idx, 0xff, val); ++} ++ ++/* update the amp, doing in stereo or mono depending on NID */ ++static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx, ++ unsigned int mask, unsigned int val) ++{ ++ if (is_stereo_amps(codec, nid, dir)) ++ return snd_hda_codec_amp_stereo(codec, nid, dir, idx, ++ mask, val); ++ else ++ return snd_hda_codec_amp_update(codec, nid, 0, dir, idx, ++ mask, val); + } + + /* calculate amp value mask we can modify; +@@ -698,7 +731,7 @@ static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir, + return; + + val &= mask; +- snd_hda_codec_amp_stereo(codec, nid, dir, idx, mask, val); ++ update_amp(codec, nid, dir, idx, mask, val); + } + + static void activate_amp_out(struct hda_codec *codec, struct nid_path *path, +@@ -4337,13 +4370,11 @@ static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix) + has_amp = nid_has_mute(codec, mix, HDA_INPUT); + for (i = 0; i < nums; i++) { + if (has_amp) +- snd_hda_codec_amp_stereo(codec, mix, +- HDA_INPUT, i, +- 0xff, HDA_AMP_MUTE); ++ update_amp(codec, mix, HDA_INPUT, i, ++ 0xff, HDA_AMP_MUTE); + else if (nid_has_volume(codec, conn[i], HDA_OUTPUT)) +- snd_hda_codec_amp_stereo(codec, conn[i], +- HDA_OUTPUT, 0, +- 0xff, HDA_AMP_MUTE); ++ update_amp(codec, conn[i], HDA_OUTPUT, 0, ++ 0xff, HDA_AMP_MUTE); + } + } + +diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c +index 2f3059b50ffa..84e8879cc372 100644 +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -959,7 +959,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, + } + } + +- if (!bus->no_response_fallback) ++ if (bus->no_response_fallback) + return -1; + + if (!chip->polling_mode && chip->poll_count < 2) { +diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c +index ce5a6da83419..05e19f78b4cb 100644 +--- a/sound/pci/hda/hda_proc.c ++++ b/sound/pci/hda/hda_proc.c +@@ -134,13 +134,38 @@ static void print_amp_caps(struct snd_info_buffer *buffer, + (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT); + } + ++/* is this a stereo widget or a stereo-to-mono mix? */ ++static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, ++ int dir, unsigned int wcaps, int indices) ++{ ++ hda_nid_t conn; ++ ++ if (wcaps & AC_WCAP_STEREO) ++ return true; ++ /* check for a stereo-to-mono mix; it must be: ++ * only a single connection, only for input, and only a mixer widget ++ */ ++ if (indices != 1 || dir != HDA_INPUT || ++ get_wcaps_type(wcaps) != AC_WID_AUD_MIX) ++ return false; ++ ++ if (snd_hda_get_raw_connections(codec, nid, &conn, 1) < 0) ++ return false; ++ /* the connection source is a stereo? */ ++ wcaps = snd_hda_param_read(codec, conn, AC_PAR_AUDIO_WIDGET_CAP); ++ return !!(wcaps & AC_WCAP_STEREO); ++} ++ + static void print_amp_vals(struct snd_info_buffer *buffer, + struct hda_codec *codec, hda_nid_t nid, +- int dir, int stereo, int indices) ++ int dir, unsigned int wcaps, int indices) + { + unsigned int val; ++ bool stereo; + int i; + ++ stereo = is_stereo_amps(codec, nid, dir, wcaps, indices); ++ + dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT; + for (i = 0; i < indices; i++) { + snd_iprintf(buffer, " ["); +@@ -757,12 +782,10 @@ static void print_codec_info(struct snd_info_entry *entry, + (codec->single_adc_amp && + wid_type == AC_WID_AUD_IN)) + print_amp_vals(buffer, codec, nid, HDA_INPUT, +- wid_caps & AC_WCAP_STEREO, +- 1); ++ wid_caps, 1); + else + print_amp_vals(buffer, codec, nid, HDA_INPUT, +- wid_caps & AC_WCAP_STEREO, +- conn_len); ++ wid_caps, conn_len); + } + if (wid_caps & AC_WCAP_OUT_AMP) { + snd_iprintf(buffer, " Amp-Out caps: "); +@@ -771,11 +794,10 @@ static void print_codec_info(struct snd_info_entry *entry, + if (wid_type == AC_WID_PIN && + codec->pin_amp_workaround) + print_amp_vals(buffer, codec, nid, HDA_OUTPUT, +- wid_caps & AC_WCAP_STEREO, +- conn_len); ++ wid_caps, conn_len); + else + print_amp_vals(buffer, codec, nid, HDA_OUTPUT, +- wid_caps & AC_WCAP_STEREO, 1); ++ wid_caps, 1); + } + + switch (wid_type) { +diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c +index fc492ac24caa..51e208022cc8 100644 +--- a/sound/pci/hda/patch_cirrus.c ++++ b/sound/pci/hda/patch_cirrus.c +@@ -396,6 +396,7 @@ static const struct snd_pci_quirk cs420x_fixup_tbl[] = { + SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81), + SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122), + SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101), ++ SND_PCI_QUIRK(0x106b, 0x5600, "MacBookAir 5,2", CS420X_MBP81), + SND_PCI_QUIRK(0x106b, 0x5b00, "MacBookAir 4,2", CS420X_MBA42), + SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE), + {} /* terminator */ +@@ -587,6 +588,7 @@ static int patch_cs420x(struct hda_codec *codec) + return -ENOMEM; + + spec->gen.automute_hook = cs_automute; ++ codec->single_adc_amp = 1; + + snd_hda_pick_fixup(codec, cs420x_models, cs420x_fixup_tbl, + cs420x_fixups); +diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c +index ffc19464b978..976493c4a695 100644 +--- a/sound/pci/hda/patch_conexant.c ++++ b/sound/pci/hda/patch_conexant.c +@@ -3232,6 +3232,7 @@ enum { + CXT_PINCFG_LENOVO_TP410, + CXT_PINCFG_LEMOTE_A1004, + CXT_PINCFG_LEMOTE_A1205, ++ CXT_PINCFG_COMPAQ_CQ60, + CXT_FIXUP_STEREO_DMIC, + CXT_FIXUP_INC_MIC_BOOST, + CXT_FIXUP_HEADPHONE_MIC_PIN, +@@ -3368,6 +3369,15 @@ static const struct hda_fixup cxt_fixups[] = { + .type = HDA_FIXUP_PINS, + .v.pins = cxt_pincfg_lemote, + }, ++ [CXT_PINCFG_COMPAQ_CQ60] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ /* 0x17 was falsely set up as a mic, it should 0x1d */ ++ { 0x17, 0x400001f0 }, ++ { 0x1d, 0x97a70120 }, ++ { } ++ } ++ }, + [CXT_FIXUP_STEREO_DMIC] = { + .type = HDA_FIXUP_FUNC, + .v.func = cxt_fixup_stereo_dmic, +@@ -3411,6 +3421,7 @@ static const struct hda_fixup cxt_fixups[] = { + }; + + static const struct snd_pci_quirk cxt5051_fixups[] = { ++ SND_PCI_QUIRK(0x103c, 0x360b, "Compaq CQ60", CXT_PINCFG_COMPAQ_CQ60), + SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200), + {} + }; +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index 83bddbdb90e9..5293b5ac8b9d 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -1773,6 +1773,36 @@ YAMAHA_DEVICE(0x7010, "UB99"), + } + } + }, ++{ ++ USB_DEVICE(0x0582, 0x0159), ++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { ++ /* .vendor_name = "Roland", */ ++ /* .product_name = "UA-22", */ ++ .ifnum = QUIRK_ANY_INTERFACE, ++ .type = QUIRK_COMPOSITE, ++ .data = (const struct snd_usb_audio_quirk[]) { ++ { ++ .ifnum = 0, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 1, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 2, ++ .type = QUIRK_MIDI_FIXED_ENDPOINT, ++ .data = & (const struct snd_usb_midi_endpoint_info) { ++ .out_cables = 0x0001, ++ .in_cables = 0x0001 ++ } ++ }, ++ { ++ .ifnum = -1 ++ } ++ } ++ } ++}, + /* this catches most recent vendor-specific Roland devices */ + { + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | diff --git a/patch/kernel/cubox-default/patch-3.14.37-38.patch b/patch/kernel/cubox-default/patch-3.14.37-38.patch new file mode 100644 index 000000000..a7c872544 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.37-38.patch @@ -0,0 +1,1029 @@ +diff --git a/Makefile b/Makefile +index c24acc0d34a1..f09e19d2cc4f 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 37 ++SUBLEVEL = 38 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h +index a9eee33dfa62..101a42bde728 100644 +--- a/arch/arm64/include/asm/mmu_context.h ++++ b/arch/arm64/include/asm/mmu_context.h +@@ -151,6 +151,15 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, + { + unsigned int cpu = smp_processor_id(); + ++ /* ++ * init_mm.pgd does not contain any user mappings and it is always ++ * active for kernel addresses in TTBR1. Just set the reserved TTBR0. ++ */ ++ if (next == &init_mm) { ++ cpu_set_reserved_ttbr0(); ++ return; ++ } ++ + if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) + check_and_switch_context(next, tsk); + } +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi +index 1382fec9e8c5..7fcb1ac0f232 100644 +--- a/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi +@@ -50,6 +50,7 @@ ethernet@b0000 { + fsl,num_tx_queues = <0x8>; + fsl,magic-packet; + local-mac-address = [ 00 00 00 00 00 00 ]; ++ ranges; + + queue-group@b0000 { + #address-cells = <1>; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi +index 221cd2ea5b31..9f25427c1527 100644 +--- a/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi +@@ -50,6 +50,7 @@ ethernet@b1000 { + fsl,num_tx_queues = <0x8>; + fsl,magic-packet; + local-mac-address = [ 00 00 00 00 00 00 ]; ++ ranges; + + queue-group@b1000 { + #address-cells = <1>; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi +index 61456c317609..cd7c318ab131 100644 +--- a/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi +@@ -49,6 +49,7 @@ ethernet@b2000 { + fsl,num_tx_queues = <0x8>; + fsl,magic-packet; + local-mac-address = [ 00 00 00 00 00 00 ]; ++ ranges; + + queue-group@b2000 { + #address-cells = <1>; +diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S +index 38d507306a11..5193116eadc0 100644 +--- a/arch/powerpc/kernel/exceptions-64s.S ++++ b/arch/powerpc/kernel/exceptions-64s.S +@@ -1422,7 +1422,7 @@ machine_check_handle_early: + bne 9f /* continue in V mode if we are. */ + + 5: +-#ifdef CONFIG_KVM_BOOK3S_64_HV ++#ifdef CONFIG_KVM_BOOK3S_64_HANDLER + /* + * We are coming from kernel context. Check if we are coming from + * guest. if yes, then we can continue. We will fall through +diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c +index cde4e0a095ae..bf3829242aff 100644 +--- a/arch/powerpc/platforms/pseries/mobility.c ++++ b/arch/powerpc/platforms/pseries/mobility.c +@@ -24,10 +24,10 @@ + static struct kobject *mobility_kobj; + + struct update_props_workarea { +- u32 phandle; +- u32 state; +- u64 reserved; +- u32 nprops; ++ __be32 phandle; ++ __be32 state; ++ __be64 reserved; ++ __be32 nprops; + } __packed; + + #define NODE_ACTION_MASK 0xff000000 +@@ -53,11 +53,11 @@ static int mobility_rtas_call(int token, char *buf, s32 scope) + return rc; + } + +-static int delete_dt_node(u32 phandle) ++static int delete_dt_node(__be32 phandle) + { + struct device_node *dn; + +- dn = of_find_node_by_phandle(phandle); ++ dn = of_find_node_by_phandle(be32_to_cpu(phandle)); + if (!dn) + return -ENOENT; + +@@ -126,7 +126,7 @@ static int update_dt_property(struct device_node *dn, struct property **prop, + return 0; + } + +-static int update_dt_node(u32 phandle, s32 scope) ++static int update_dt_node(__be32 phandle, s32 scope) + { + struct update_props_workarea *upwa; + struct device_node *dn; +@@ -135,6 +135,7 @@ static int update_dt_node(u32 phandle, s32 scope) + char *prop_data; + char *rtas_buf; + int update_properties_token; ++ u32 nprops; + u32 vd; + + update_properties_token = rtas_token("ibm,update-properties"); +@@ -145,7 +146,7 @@ static int update_dt_node(u32 phandle, s32 scope) + if (!rtas_buf) + return -ENOMEM; + +- dn = of_find_node_by_phandle(phandle); ++ dn = of_find_node_by_phandle(be32_to_cpu(phandle)); + if (!dn) { + kfree(rtas_buf); + return -ENOENT; +@@ -161,6 +162,7 @@ static int update_dt_node(u32 phandle, s32 scope) + break; + + prop_data = rtas_buf + sizeof(*upwa); ++ nprops = be32_to_cpu(upwa->nprops); + + /* On the first call to ibm,update-properties for a node the + * the first property value descriptor contains an empty +@@ -169,17 +171,17 @@ static int update_dt_node(u32 phandle, s32 scope) + */ + if (*prop_data == 0) { + prop_data++; +- vd = *(u32 *)prop_data; ++ vd = be32_to_cpu(*(__be32 *)prop_data); + prop_data += vd + sizeof(vd); +- upwa->nprops--; ++ nprops--; + } + +- for (i = 0; i < upwa->nprops; i++) { ++ for (i = 0; i < nprops; i++) { + char *prop_name; + + prop_name = prop_data; + prop_data += strlen(prop_name) + 1; +- vd = *(u32 *)prop_data; ++ vd = be32_to_cpu(*(__be32 *)prop_data); + prop_data += sizeof(vd); + + switch (vd) { +@@ -211,13 +213,13 @@ static int update_dt_node(u32 phandle, s32 scope) + return 0; + } + +-static int add_dt_node(u32 parent_phandle, u32 drc_index) ++static int add_dt_node(__be32 parent_phandle, __be32 drc_index) + { + struct device_node *dn; + struct device_node *parent_dn; + int rc; + +- parent_dn = of_find_node_by_phandle(parent_phandle); ++ parent_dn = of_find_node_by_phandle(be32_to_cpu(parent_phandle)); + if (!parent_dn) + return -ENOENT; + +@@ -236,7 +238,7 @@ static int add_dt_node(u32 parent_phandle, u32 drc_index) + int pseries_devicetree_update(s32 scope) + { + char *rtas_buf; +- u32 *data; ++ __be32 *data; + int update_nodes_token; + int rc; + +@@ -253,17 +255,17 @@ int pseries_devicetree_update(s32 scope) + if (rc && rc != 1) + break; + +- data = (u32 *)rtas_buf + 4; +- while (*data & NODE_ACTION_MASK) { ++ data = (__be32 *)rtas_buf + 4; ++ while (be32_to_cpu(*data) & NODE_ACTION_MASK) { + int i; +- u32 action = *data & NODE_ACTION_MASK; +- int node_count = *data & NODE_COUNT_MASK; ++ u32 action = be32_to_cpu(*data) & NODE_ACTION_MASK; ++ u32 node_count = be32_to_cpu(*data) & NODE_COUNT_MASK; + + data++; + + for (i = 0; i < node_count; i++) { +- u32 phandle = *data++; +- u32 drc_index; ++ __be32 phandle = *data++; ++ __be32 drc_index; + + switch (action) { + case DELETE_DT_NODE: +diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c +index 930cad4e5df8..2b946bc4212d 100644 +--- a/drivers/base/regmap/regcache-rbtree.c ++++ b/drivers/base/regmap/regcache-rbtree.c +@@ -313,7 +313,7 @@ static int regcache_rbtree_insert_to_block(struct regmap *map, + if (pos == 0) { + memmove(blk + offset * map->cache_word_size, + blk, rbnode->blklen * map->cache_word_size); +- bitmap_shift_right(present, present, offset, blklen); ++ bitmap_shift_left(present, present, offset, blklen); + } + + /* update the rbnode block, its size and the base register */ +diff --git a/drivers/clocksource/time-efm32.c b/drivers/clocksource/time-efm32.c +index 1a6205b7bed3..35b016100673 100644 +--- a/drivers/clocksource/time-efm32.c ++++ b/drivers/clocksource/time-efm32.c +@@ -225,12 +225,12 @@ static int __init efm32_clockevent_init(struct device_node *np) + clock_event_ddata.base = base; + clock_event_ddata.periodic_top = DIV_ROUND_CLOSEST(rate, 1024 * HZ); + +- setup_irq(irq, &efm32_clock_event_irq); +- + clockevents_config_and_register(&clock_event_ddata.evtdev, + DIV_ROUND_CLOSEST(rate, 1024), + 0xf, 0xffff); + ++ setup_irq(irq, &efm32_clock_event_irq); ++ + return 0; + + err_get_irq: +diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c +index deebcd6469fc..4f0f3610371a 100644 +--- a/drivers/clocksource/timer-sun5i.c ++++ b/drivers/clocksource/timer-sun5i.c +@@ -172,10 +172,6 @@ static void __init sun5i_timer_init(struct device_node *node) + + ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); + +- ret = setup_irq(irq, &sun5i_timer_irq); +- if (ret) +- pr_warn("failed to setup irq %d\n", irq); +- + /* Enable timer0 interrupt */ + val = readl(timer_base + TIMER_IRQ_EN_REG); + writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); +@@ -185,6 +181,10 @@ static void __init sun5i_timer_init(struct device_node *node) + + clockevents_config_and_register(&sun5i_clockevent, rate, + TIMER_SYNC_TICKS, 0xffffffff); ++ ++ ret = setup_irq(irq, &sun5i_timer_irq); ++ if (ret) ++ pr_warn("failed to setup irq %d\n", irq); + } + CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer", + sun5i_timer_init); +diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c +index 453822cc4f9d..fe8b0c991518 100644 +--- a/drivers/dma/dw/platform.c ++++ b/drivers/dma/dw/platform.c +@@ -48,6 +48,8 @@ static bool dw_dma_of_filter(struct dma_chan *chan, void *param) + return true; + } + ++#define DRV_NAME "dw_dmac" ++ + static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) + { +@@ -293,7 +295,7 @@ static struct platform_driver dw_driver = { + .remove = dw_remove, + .shutdown = dw_shutdown, + .driver = { +- .name = "dw_dmac", ++ .name = DRV_NAME, + .pm = &dw_dev_pm_ops, + .of_match_table = of_match_ptr(dw_dma_of_id_table), + .acpi_match_table = ACPI_PTR(dw_dma_acpi_id_table), +@@ -314,3 +316,4 @@ module_exit(dw_exit); + + MODULE_LICENSE("GPL v2"); + MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller platform driver"); ++MODULE_ALIAS("platform:" DRV_NAME); +diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c +index d2a8d64f8526..080e767250d3 100644 +--- a/drivers/md/dm-io.c ++++ b/drivers/md/dm-io.c +@@ -291,9 +291,16 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, + struct request_queue *q = bdev_get_queue(where->bdev); + unsigned short logical_block_size = queue_logical_block_size(q); + sector_t num_sectors; ++ unsigned int uninitialized_var(special_cmd_max_sectors); + +- /* Reject unsupported discard requests */ +- if ((rw & REQ_DISCARD) && !blk_queue_discard(q)) { ++ /* ++ * Reject unsupported discard and write same requests. ++ */ ++ if (rw & REQ_DISCARD) ++ special_cmd_max_sectors = q->limits.max_discard_sectors; ++ else if (rw & REQ_WRITE_SAME) ++ special_cmd_max_sectors = q->limits.max_write_same_sectors; ++ if ((rw & (REQ_DISCARD | REQ_WRITE_SAME)) && special_cmd_max_sectors == 0) { + dec_count(io, region, -EOPNOTSUPP); + return; + } +@@ -319,7 +326,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, + store_io_and_region_in_bio(bio, io, region); + + if (rw & REQ_DISCARD) { +- num_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining); ++ num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining); + bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT; + remaining -= num_sectors; + } else if (rw & REQ_WRITE_SAME) { +@@ -328,7 +335,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, + */ + dp->get_page(dp, &page, &len, &offset); + bio_add_page(bio, page, logical_block_size, offset); +- num_sectors = min_t(sector_t, q->limits.max_write_same_sectors, remaining); ++ num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining); + bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT; + + offset = 0; +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index 1582c3dac3ac..e40059143272 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -2352,10 +2352,16 @@ static void __dm_destroy(struct mapped_device *md, bool wait) + set_bit(DMF_FREEING, &md->flags); + spin_unlock(&_minor_lock); + ++ /* ++ * Take suspend_lock so that presuspend and postsuspend methods ++ * do not race with internal suspend. ++ */ ++ mutex_lock(&md->suspend_lock); + if (!dm_suspended_md(md)) { + dm_table_presuspend_targets(map); + dm_table_postsuspend_targets(map); + } ++ mutex_unlock(&md->suspend_lock); + + /* dm_put_live_table must be before msleep, otherwise deadlock is possible */ + dm_put_live_table(md, srcu_idx); +diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c +index 38917a822335..2df3cbc968d1 100644 +--- a/drivers/mfd/kempld-core.c ++++ b/drivers/mfd/kempld-core.c +@@ -629,7 +629,7 @@ static int __init kempld_init(void) + if (force_device_id[0]) { + for (id = kempld_dmi_table; id->matches[0].slot != DMI_NONE; id++) + if (strstr(id->ident, force_device_id)) +- if (id->callback && id->callback(id)) ++ if (id->callback && !id->callback(id)) + break; + if (id->matches[0].slot == DMI_NONE) + return -ENODEV; +diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c +index 9339cccfe05a..ad0e71c7a607 100644 +--- a/drivers/net/ethernet/amd/pcnet32.c ++++ b/drivers/net/ethernet/amd/pcnet32.c +@@ -1516,7 +1516,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) + { + struct pcnet32_private *lp; + int i, media; +- int fdx, mii, fset, dxsuflo; ++ int fdx, mii, fset, dxsuflo, sram; + int chip_version; + char *chipname; + struct net_device *dev; +@@ -1553,7 +1553,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) + } + + /* initialize variables */ +- fdx = mii = fset = dxsuflo = 0; ++ fdx = mii = fset = dxsuflo = sram = 0; + chip_version = (chip_version >> 12) & 0xffff; + + switch (chip_version) { +@@ -1586,6 +1586,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) + chipname = "PCnet/FAST III 79C973"; /* PCI */ + fdx = 1; + mii = 1; ++ sram = 1; + break; + case 0x2626: + chipname = "PCnet/Home 79C978"; /* PCI */ +@@ -1609,6 +1610,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) + chipname = "PCnet/FAST III 79C975"; /* PCI */ + fdx = 1; + mii = 1; ++ sram = 1; + break; + case 0x2628: + chipname = "PCnet/PRO 79C976"; +@@ -1637,6 +1639,31 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) + dxsuflo = 1; + } + ++ /* ++ * The Am79C973/Am79C975 controllers come with 12K of SRAM ++ * which we can use for the Tx/Rx buffers but most importantly, ++ * the use of SRAM allow us to use the BCR18:NOUFLO bit to avoid ++ * Tx fifo underflows. ++ */ ++ if (sram) { ++ /* ++ * The SRAM is being configured in two steps. First we ++ * set the SRAM size in the BCR25:SRAM_SIZE bits. According ++ * to the datasheet, each bit corresponds to a 512-byte ++ * page so we can have at most 24 pages. The SRAM_SIZE ++ * holds the value of the upper 8 bits of the 16-bit SRAM size. ++ * The low 8-bits start at 0x00 and end at 0xff. So the ++ * address range is from 0x0000 up to 0x17ff. Therefore, ++ * the SRAM_SIZE is set to 0x17. The next step is to set ++ * the BCR26:SRAM_BND midway through so the Tx and Rx ++ * buffers can share the SRAM equally. ++ */ ++ a->write_bcr(ioaddr, 25, 0x17); ++ a->write_bcr(ioaddr, 26, 0xc); ++ /* And finally enable the NOUFLO bit */ ++ a->write_bcr(ioaddr, 18, a->read_bcr(ioaddr, 18) | (1 << 11)); ++ } ++ + dev = alloc_etherdev(sizeof(*lp)); + if (!dev) { + ret = -ENOMEM; +diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c +index a04174607e97..4a3b8b72c8af 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c +@@ -594,7 +594,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, + + ret = iwl_mvm_mac_ctxt_add(mvm, vif); + if (ret) +- goto out_remove_mac; ++ goto out_release; + + iwl_mvm_power_disable(mvm, vif); + +diff --git a/drivers/of/irq.c b/drivers/of/irq.c +index 48f20ff1add9..bbff99dcbaea 100644 +--- a/drivers/of/irq.c ++++ b/drivers/of/irq.c +@@ -290,7 +290,7 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar + struct device_node *p; + const __be32 *intspec, *tmp, *addr; + u32 intsize, intlen; +- int i, res = -EINVAL; ++ int i, res; + + pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index); + +@@ -323,15 +323,19 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar + + /* Get size of interrupt specifier */ + tmp = of_get_property(p, "#interrupt-cells", NULL); +- if (tmp == NULL) ++ if (tmp == NULL) { ++ res = -EINVAL; + goto out; ++ } + intsize = be32_to_cpu(*tmp); + + pr_debug(" intsize=%d intlen=%d\n", intsize, intlen); + + /* Check index */ +- if ((index + 1) * intsize > intlen) ++ if ((index + 1) * intsize > intlen) { ++ res = -EINVAL; + goto out; ++ } + + /* Copy intspec into irq structure */ + intspec += index * intsize; +diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c +index 34d56f7864d6..86592dd24da5 100644 +--- a/drivers/phy/phy-core.c ++++ b/drivers/phy/phy-core.c +@@ -50,7 +50,9 @@ static void devm_phy_consume(struct device *dev, void *res) + + static int devm_phy_match(struct device *dev, void *res, void *match_data) + { +- return res == match_data; ++ struct phy **phy = res; ++ ++ return *phy == match_data; + } + + static struct phy *phy_lookup(struct device *device, const char *port) +diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c +index 9d81f7693f99..1817f3f2b02d 100644 +--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c ++++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c +@@ -1515,7 +1515,7 @@ static int tcm_qla2xxx_check_initiator_node_acl( + /* + * Finally register the new FC Nexus with TCM + */ +- __transport_register_session(se_nacl->se_tpg, se_nacl, se_sess, sess); ++ transport_register_session(se_nacl->se_tpg, se_nacl, se_sess, sess); + + return 0; + } +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index fbf3b22efe5a..d6563ec700d4 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -846,13 +846,14 @@ void spi_finalize_current_message(struct spi_master *master) + "failed to unprepare message: %d\n", ret); + } + } ++ ++ trace_spi_message_done(mesg); ++ + master->cur_msg_prepared = false; + + mesg->state = NULL; + if (mesg->complete) + mesg->complete(mesg->context); +- +- trace_spi_message_done(mesg); + } + EXPORT_SYMBOL_GPL(spi_finalize_current_message); + +diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c +index edb1b2768b17..dbd9d44919ac 100644 +--- a/drivers/staging/vt6655/rf.c ++++ b/drivers/staging/vt6655/rf.c +@@ -936,6 +936,7 @@ bool RFbSetPower( + break; + case RATE_6M: + case RATE_9M: ++ case RATE_12M: + case RATE_18M: + byPwr = pDevice->abyOFDMPwrTbl[uCH]; + if (pDevice->byRFType == RF_UW2452) { +diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c +index 1e8f64bff03c..2dc48d4ff433 100644 +--- a/drivers/staging/vt6656/rf.c ++++ b/drivers/staging/vt6656/rf.c +@@ -752,6 +752,7 @@ int RFbSetPower(struct vnt_private *priv, u32 rate, u32 channel) + break; + case RATE_6M: + case RATE_9M: ++ case RATE_12M: + case RATE_18M: + case RATE_24M: + case RATE_36M: +diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c +index e415af32115a..c67d3795db4a 100644 +--- a/drivers/target/tcm_fc/tfc_io.c ++++ b/drivers/target/tcm_fc/tfc_io.c +@@ -346,7 +346,7 @@ void ft_invl_hw_context(struct ft_cmd *cmd) + ep = fc_seq_exch(seq); + if (ep) { + lport = ep->lp; +- if (lport && (ep->xid <= lport->lro_xid)) ++ if (lport && (ep->xid <= lport->lro_xid)) { + /* + * "ddp_done" trigger invalidation of HW + * specific DDP context +@@ -361,6 +361,7 @@ void ft_invl_hw_context(struct ft_cmd *cmd) + * identified using ep->xid) + */ + cmd->was_ddp_setup = 0; ++ } + } + } + } +diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c +index 6e560d56094b..754fdf8c6356 100644 +--- a/fs/hfsplus/brec.c ++++ b/fs/hfsplus/brec.c +@@ -131,13 +131,16 @@ skip: + hfs_bnode_write(node, entry, data_off + key_len, entry_len); + hfs_bnode_dump(node); + +- if (new_node) { +- /* update parent key if we inserted a key +- * at the start of the first node +- */ +- if (!rec && new_node != node) +- hfs_brec_update_parent(fd); ++ /* ++ * update parent key if we inserted a key ++ * at the start of the node and it is not the new node ++ */ ++ if (!rec && new_node != node) { ++ hfs_bnode_read_key(node, fd->search_key, data_off + size); ++ hfs_brec_update_parent(fd); ++ } + ++ if (new_node) { + hfs_bnode_put(fd->bnode); + if (!new_node->parent) { + hfs_btree_inc_height(tree); +@@ -168,9 +171,6 @@ skip: + goto again; + } + +- if (!rec) +- hfs_brec_update_parent(fd); +- + return 0; + } + +@@ -370,6 +370,8 @@ again: + if (IS_ERR(parent)) + return PTR_ERR(parent); + __hfs_brec_find(parent, fd, hfs_find_rec_by_key); ++ if (fd->record < 0) ++ return -ENOENT; + hfs_bnode_dump(parent); + rec = fd->record; + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 69cffb46db17..60146febb9b3 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -4232,6 +4232,13 @@ static void perf_pending_event(struct irq_work *entry) + { + struct perf_event *event = container_of(entry, + struct perf_event, pending); ++ int rctx; ++ ++ rctx = perf_swevent_get_recursion_context(); ++ /* ++ * If we 'fail' here, that's OK, it means recursion is already disabled ++ * and we won't recurse 'further'. ++ */ + + if (event->pending_disable) { + event->pending_disable = 0; +@@ -4242,6 +4249,9 @@ static void perf_pending_event(struct irq_work *entry) + event->pending_wakeup = 0; + perf_event_wakeup(event); + } ++ ++ if (rctx >= 0) ++ perf_swevent_put_recursion_context(rctx); + } + + /* +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index bf7a1bbb975f..e278c64572de 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -57,13 +57,24 @@ struct ieee80211_local; + #define IEEE80211_UNSET_POWER_LEVEL INT_MIN + + /* +- * Some APs experience problems when working with U-APSD. Decrease the +- * probability of that happening by using legacy mode for all ACs but VO. +- * The AP that caused us trouble was a Cisco 4410N. It ignores our +- * setting, and always treats non-VO ACs as legacy. ++ * Some APs experience problems when working with U-APSD. Decreasing the ++ * probability of that happening by using legacy mode for all ACs but VO isn't ++ * enough. ++ * ++ * Cisco 4410N originally forced us to enable VO by default only because it ++ * treated non-VO ACs as legacy. ++ * ++ * However some APs (notably Netgear R7000) silently reclassify packets to ++ * different ACs. Since u-APSD ACs require trigger frames for frame retrieval ++ * clients would never see some frames (e.g. ARP responses) or would fetch them ++ * accidentally after a long time. ++ * ++ * It makes little sense to enable u-APSD queues by default because it needs ++ * userspace applications to be aware of it to actually take advantage of the ++ * possible additional powersavings. Implicitly depending on driver autotrigger ++ * frame support doesn't make much sense. + */ +-#define IEEE80211_DEFAULT_UAPSD_QUEUES \ +- IEEE80211_WMM_IE_STA_QOSINFO_AC_VO ++#define IEEE80211_DEFAULT_UAPSD_QUEUES 0 + + #define IEEE80211_DEFAULT_MAX_SP_LEN \ + IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 815ca56b39e7..9abb445ea261 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2107,6 +2107,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) + hdr = (struct ieee80211_hdr *) skb->data; + mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); + ++ if (ieee80211_drop_unencrypted(rx, hdr->frame_control)) ++ return RX_DROP_MONITOR; ++ + /* frame is in RMC, don't forward */ + if (ieee80211_is_data(hdr->frame_control) && + is_multicast_ether_addr(hdr->addr1) && +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 18d73df72531..c260243dbe07 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -4190,6 +4190,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) + if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) + return -EINVAL; + ++ /* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT ++ * as userspace might just pass through the capabilities from the IEs ++ * directly, rather than enforcing this restriction and returning an ++ * error in this case. ++ */ ++ if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) { ++ params.ht_capa = NULL; ++ params.vht_capa = NULL; ++ } ++ + /* When you run into this, adjust the code below for the new flag */ + BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7); + +diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c +index f78b27a7c461..23454e9a5d3a 100644 +--- a/sound/soc/codecs/adav80x.c ++++ b/sound/soc/codecs/adav80x.c +@@ -319,7 +319,7 @@ static int adav80x_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); +- unsigned int deemph = ucontrol->value.enumerated.item[0]; ++ unsigned int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; +@@ -335,7 +335,7 @@ static int adav80x_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = adav80x->deemph; ++ ucontrol->value.integer.value[0] = adav80x->deemph; + return 0; + }; + +diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c +index 94cbe508dd37..d7184726f8a0 100644 +--- a/sound/soc/codecs/ak4641.c ++++ b/sound/soc/codecs/ak4641.c +@@ -76,7 +76,7 @@ static int ak4641_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; +@@ -92,7 +92,7 @@ static int ak4641_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = ak4641->deemph; ++ ucontrol->value.integer.value[0] = ak4641->deemph; + return 0; + }; + +diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c +index ce05fd93dc74..a0ad41ac5574 100644 +--- a/sound/soc/codecs/cs4271.c ++++ b/sound/soc/codecs/cs4271.c +@@ -288,7 +288,7 @@ static int cs4271_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = cs4271->deemph; ++ ucontrol->value.integer.value[0] = cs4271->deemph; + return 0; + } + +@@ -298,7 +298,7 @@ static int cs4271_put_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); + +- cs4271->deemph = ucontrol->value.enumerated.item[0]; ++ cs4271->deemph = ucontrol->value.integer.value[0]; + return cs4271_set_deemph(codec); + } + +diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c +index 73f9c3630e2c..651e2fe2c31f 100644 +--- a/sound/soc/codecs/pcm1681.c ++++ b/sound/soc/codecs/pcm1681.c +@@ -118,7 +118,7 @@ static int pcm1681_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = priv->deemph; ++ ucontrol->value.integer.value[0] = priv->deemph; + + return 0; + } +@@ -129,7 +129,7 @@ static int pcm1681_put_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); + +- priv->deemph = ucontrol->value.enumerated.item[0]; ++ priv->deemph = ucontrol->value.integer.value[0]; + + return pcm1681_set_deemph(codec); + } +diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c +index 715589ff0eda..e93c36fd3073 100644 +--- a/sound/soc/codecs/sgtl5000.c ++++ b/sound/soc/codecs/sgtl5000.c +@@ -1198,13 +1198,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec) + /* Enable VDDC charge pump */ + ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP; + } else if (vddio >= 3100 && vdda >= 3100) { +- /* +- * if vddio and vddd > 3.1v, +- * charge pump should be clean before set ana_pwr +- */ +- snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, +- SGTL5000_VDDC_CHRGPMP_POWERUP, 0); +- ++ ana_pwr &= ~SGTL5000_VDDC_CHRGPMP_POWERUP; + /* VDDC use VDDIO rail */ + lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD; + lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO << +diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c +index a895a5e4bdf2..c6c65001457d 100644 +--- a/sound/soc/codecs/tas5086.c ++++ b/sound/soc/codecs/tas5086.c +@@ -275,7 +275,7 @@ static int tas5086_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = priv->deemph; ++ ucontrol->value.integer.value[0] = priv->deemph; + + return 0; + } +@@ -286,7 +286,7 @@ static int tas5086_put_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); + +- priv->deemph = ucontrol->value.enumerated.item[0]; ++ priv->deemph = ucontrol->value.integer.value[0]; + + return tas5086_set_deemph(codec); + } +diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c +index 8ae50274ea8f..1a9f4574b65b 100644 +--- a/sound/soc/codecs/wm2000.c ++++ b/sound/soc/codecs/wm2000.c +@@ -610,7 +610,7 @@ static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); + +- ucontrol->value.enumerated.item[0] = wm2000->anc_active; ++ ucontrol->value.integer.value[0] = wm2000->anc_active; + + return 0; + } +@@ -620,7 +620,7 @@ static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); +- int anc_active = ucontrol->value.enumerated.item[0]; ++ int anc_active = ucontrol->value.integer.value[0]; + int ret; + + if (anc_active > 1) +@@ -643,7 +643,7 @@ static int wm2000_speaker_get(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); + +- ucontrol->value.enumerated.item[0] = wm2000->spk_ena; ++ ucontrol->value.integer.value[0] = wm2000->spk_ena; + + return 0; + } +@@ -653,7 +653,7 @@ static int wm2000_speaker_put(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); +- int val = ucontrol->value.enumerated.item[0]; ++ int val = ucontrol->value.integer.value[0]; + int ret; + + if (val > 1) +diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c +index 029720366ff8..e593722574de 100644 +--- a/sound/soc/codecs/wm8731.c ++++ b/sound/soc/codecs/wm8731.c +@@ -122,7 +122,7 @@ static int wm8731_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = wm8731->deemph; ++ ucontrol->value.integer.value[0] = wm8731->deemph; + + return 0; + } +@@ -132,7 +132,7 @@ static int wm8731_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + int ret = 0; + + if (deemph > 1) +diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c +index eebcb1da3b7b..ae7d76efe063 100644 +--- a/sound/soc/codecs/wm8903.c ++++ b/sound/soc/codecs/wm8903.c +@@ -442,7 +442,7 @@ static int wm8903_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = wm8903->deemph; ++ ucontrol->value.integer.value[0] = wm8903->deemph; + + return 0; + } +@@ -452,7 +452,7 @@ static int wm8903_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + int ret = 0; + + if (deemph > 1) +diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c +index 53bbfac6a83a..66cb9e95b5eb 100644 +--- a/sound/soc/codecs/wm8904.c ++++ b/sound/soc/codecs/wm8904.c +@@ -523,7 +523,7 @@ static int wm8904_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = wm8904->deemph; ++ ucontrol->value.integer.value[0] = wm8904->deemph; + return 0; + } + +@@ -532,7 +532,7 @@ static int wm8904_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; +diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c +index 82c8ba975720..1c1fc6119758 100644 +--- a/sound/soc/codecs/wm8955.c ++++ b/sound/soc/codecs/wm8955.c +@@ -393,7 +393,7 @@ static int wm8955_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = wm8955->deemph; ++ ucontrol->value.integer.value[0] = wm8955->deemph; + return 0; + } + +@@ -402,7 +402,7 @@ static int wm8955_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; +diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c +index 942ef8427347..2a0bfb848512 100644 +--- a/sound/soc/codecs/wm8960.c ++++ b/sound/soc/codecs/wm8960.c +@@ -181,7 +181,7 @@ static int wm8960_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = wm8960->deemph; ++ ucontrol->value.integer.value[0] = wm8960->deemph; + return 0; + } + +@@ -190,7 +190,7 @@ static int wm8960_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; +diff --git a/sound/soc/jz4740/Makefile b/sound/soc/jz4740/Makefile +index be873c1b0c20..d32c540555c4 100644 +--- a/sound/soc/jz4740/Makefile ++++ b/sound/soc/jz4740/Makefile +@@ -1,10 +1,8 @@ + # + # Jz4740 Platform Support + # +-snd-soc-jz4740-objs := jz4740-pcm.o + snd-soc-jz4740-i2s-objs := jz4740-i2s.o + +-obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o + obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o + + # Jz4740 Machine Support diff --git a/patch/kernel/cubox-default/patch-3.14.38-39.patch b/patch/kernel/cubox-default/patch-3.14.38-39.patch new file mode 100644 index 000000000..ea2030ba3 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.38-39.patch @@ -0,0 +1,1100 @@ +diff --git a/Makefile b/Makefile +index f09e19d2cc4f..b40845e11b84 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 38 ++SUBLEVEL = 39 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c +index 7e95e1a86510..d68b410595c8 100644 +--- a/arch/arc/kernel/signal.c ++++ b/arch/arc/kernel/signal.c +@@ -67,7 +67,7 @@ stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs, + sigset_t *set) + { + int err; +- err = __copy_to_user(&(sf->uc.uc_mcontext.regs), regs, ++ err = __copy_to_user(&(sf->uc.uc_mcontext.regs.scratch), regs, + sizeof(sf->uc.uc_mcontext.regs.scratch)); + err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t)); + +@@ -83,7 +83,7 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf) + if (!err) + set_current_blocked(&set); + +- err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs), ++ err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs.scratch), + sizeof(sf->uc.uc_mcontext.regs.scratch)); + + return err; +diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c +index c752cb43e52f..a6aa91f77654 100644 +--- a/arch/x86/kernel/reboot.c ++++ b/arch/x86/kernel/reboot.c +@@ -181,6 +181,16 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { + }, + }, + ++ /* ASRock */ ++ { /* Handle problems with rebooting on ASRock Q1900DC-ITX */ ++ .callback = set_pci_reboot, ++ .ident = "ASRock Q1900DC-ITX", ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASRock"), ++ DMI_MATCH(DMI_BOARD_NAME, "Q1900DC-ITX"), ++ }, ++ }, ++ + /* ASUS */ + { /* Handle problems with rebooting on ASUS P4S800 */ + .callback = set_bios_reboot, +diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c +index 17f9ec501972..fd8496a92b45 100644 +--- a/drivers/acpi/processor_idle.c ++++ b/drivers/acpi/processor_idle.c +@@ -962,7 +962,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) + return -EINVAL; + + drv->safe_state_index = -1; +- for (i = 0; i < CPUIDLE_STATE_MAX; i++) { ++ for (i = CPUIDLE_DRIVER_STATE_START; i < CPUIDLE_STATE_MAX; i++) { + drv->states[i].name[0] = '\0'; + drv->states[i].desc[0] = '\0'; + } +diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c +index 55298db36b2d..d18093681af2 100644 +--- a/drivers/block/nbd.c ++++ b/drivers/block/nbd.c +@@ -814,10 +814,6 @@ static int __init nbd_init(void) + return -EINVAL; + } + +- nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL); +- if (!nbd_dev) +- return -ENOMEM; +- + part_shift = 0; + if (max_part > 0) { + part_shift = fls(max_part); +@@ -839,6 +835,10 @@ static int __init nbd_init(void) + if (nbds_max > 1UL << (MINORBITS - part_shift)) + return -EINVAL; + ++ nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL); ++ if (!nbd_dev) ++ return -ENOMEM; ++ + for (i = 0; i < nbds_max; i++) { + struct gendisk *disk = alloc_disk(1 << part_shift); + if (!disk) +diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c +index a55e68f2cfc8..e3d2052e7552 100644 +--- a/drivers/cpuidle/cpuidle.c ++++ b/drivers/cpuidle/cpuidle.c +@@ -252,9 +252,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev) + if (!dev->registered) + return -EINVAL; + +- if (!dev->state_count) +- dev->state_count = drv->state_count; +- + ret = cpuidle_add_device_sysfs(dev); + if (ret) + return ret; +diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c +index e918b6d0caf7..dcaae4c8bc08 100644 +--- a/drivers/cpuidle/sysfs.c ++++ b/drivers/cpuidle/sysfs.c +@@ -398,7 +398,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) + struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); + + /* state statistics */ +- for (i = 0; i < device->state_count; i++) { ++ for (i = 0; i < drv->state_count; i++) { + kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL); + if (!kobj) + goto error_state; +@@ -430,9 +430,10 @@ error_state: + */ + static void cpuidle_remove_state_sysfs(struct cpuidle_device *device) + { ++ struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); + int i; + +- for (i = 0; i < device->state_count; i++) ++ for (i = 0; i < drv->state_count; i++) + cpuidle_free_state_kobj(device, i); + } + +diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c +index 362e7c49f2e1..12f82942e347 100644 +--- a/drivers/dma/omap-dma.c ++++ b/drivers/dma/omap-dma.c +@@ -487,6 +487,7 @@ static int omap_dma_terminate_all(struct omap_chan *c) + * c->desc is NULL and exit.) + */ + if (c->desc) { ++ omap_dma_desc_free(&c->desc->vd); + c->desc = NULL; + /* Avoid stopping the dma twice */ + if (!c->paused) +diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c +index 9ab30976287d..c43335ce8778 100644 +--- a/drivers/gpu/drm/radeon/radeon_bios.c ++++ b/drivers/gpu/drm/radeon/radeon_bios.c +@@ -76,7 +76,7 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev) + + static bool radeon_read_bios(struct radeon_device *rdev) + { +- uint8_t __iomem *bios; ++ uint8_t __iomem *bios, val1, val2; + size_t size; + + rdev->bios = NULL; +@@ -86,15 +86,19 @@ static bool radeon_read_bios(struct radeon_device *rdev) + return false; + } + +- if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { ++ val1 = readb(&bios[0]); ++ val2 = readb(&bios[1]); ++ ++ if (size == 0 || val1 != 0x55 || val2 != 0xaa) { + pci_unmap_rom(rdev->pdev, bios); + return false; + } +- rdev->bios = kmemdup(bios, size, GFP_KERNEL); ++ rdev->bios = kzalloc(size, GFP_KERNEL); + if (rdev->bios == NULL) { + pci_unmap_rom(rdev->pdev, bios); + return false; + } ++ memcpy_fromio(rdev->bios, bios, size); + pci_unmap_rom(rdev->pdev, bios); + return true; + } +diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c +index e0017c22bb9c..f53e9a803a0e 100644 +--- a/drivers/iio/imu/adis_trigger.c ++++ b/drivers/iio/imu/adis_trigger.c +@@ -60,7 +60,7 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) + iio_trigger_set_drvdata(adis->trig, adis); + ret = iio_trigger_register(adis->trig); + +- indio_dev->trig = adis->trig; ++ indio_dev->trig = iio_trigger_get(adis->trig); + if (ret) + goto error_free_irq; + +diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +index 429517117eff..30fce6723e61 100644 +--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c ++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +@@ -25,6 +25,16 @@ + #include + #include "inv_mpu_iio.h" + ++static void inv_clear_kfifo(struct inv_mpu6050_state *st) ++{ ++ unsigned long flags; ++ ++ /* take the spin lock sem to avoid interrupt kick in */ ++ spin_lock_irqsave(&st->time_stamp_lock, flags); ++ kfifo_reset(&st->timestamps); ++ spin_unlock_irqrestore(&st->time_stamp_lock, flags); ++} ++ + int inv_reset_fifo(struct iio_dev *indio_dev) + { + int result; +@@ -51,6 +61,10 @@ int inv_reset_fifo(struct iio_dev *indio_dev) + INV_MPU6050_BIT_FIFO_RST); + if (result) + goto reset_fifo_fail; ++ ++ /* clear timestamps fifo */ ++ inv_clear_kfifo(st); ++ + /* enable interrupt */ + if (st->chip_config.accl_fifo_enable || + st->chip_config.gyro_fifo_enable) { +@@ -84,16 +98,6 @@ reset_fifo_fail: + return result; + } + +-static void inv_clear_kfifo(struct inv_mpu6050_state *st) +-{ +- unsigned long flags; +- +- /* take the spin lock sem to avoid interrupt kick in */ +- spin_lock_irqsave(&st->time_stamp_lock, flags); +- kfifo_reset(&st->timestamps); +- spin_unlock_irqrestore(&st->time_stamp_lock, flags); +-} +- + /** + * inv_mpu6050_irq_handler() - Cache a timestamp at each data ready interrupt. + */ +@@ -185,7 +189,6 @@ end_session: + flush_fifo: + /* Flush HW and SW FIFOs. */ + inv_reset_fifo(indio_dev); +- inv_clear_kfifo(st); + mutex_unlock(&indio_dev->mlock); + iio_trigger_notify_done(indio_dev->trig); + +diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c +index a84112322071..055ebebc07dd 100644 +--- a/drivers/infiniband/core/umem.c ++++ b/drivers/infiniband/core/umem.c +@@ -94,6 +94,14 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, + if (dmasync) + dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs); + ++ /* ++ * If the combination of the addr and size requested for this memory ++ * region causes an integer overflow, return error. ++ */ ++ if ((PAGE_ALIGN(addr + size) <= size) || ++ (PAGE_ALIGN(addr + size) <= addr)) ++ return ERR_PTR(-EINVAL); ++ + if (!can_do_mlock()) + return ERR_PTR(-EPERM); + +diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c +index 08219fb3338b..7a515c867674 100644 +--- a/drivers/infiniband/core/uverbs_main.c ++++ b/drivers/infiniband/core/uverbs_main.c +@@ -476,6 +476,7 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file, + + entry->desc.async.element = element; + entry->desc.async.event_type = event; ++ entry->desc.async.reserved = 0; + entry->counter = counter; + + list_add_tail(&entry->list, &file->async_file->event_list); +diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c +index f2a3f48107e7..2592ab5f21b1 100644 +--- a/drivers/infiniband/hw/mlx4/mad.c ++++ b/drivers/infiniband/hw/mlx4/mad.c +@@ -64,6 +64,14 @@ enum { + #define GUID_TBL_BLK_NUM_ENTRIES 8 + #define GUID_TBL_BLK_SIZE (GUID_TBL_ENTRY_SIZE * GUID_TBL_BLK_NUM_ENTRIES) + ++/* Counters should be saturate once they reach their maximum value */ ++#define ASSIGN_32BIT_COUNTER(counter, value) do {\ ++ if ((value) > U32_MAX) \ ++ counter = cpu_to_be32(U32_MAX); \ ++ else \ ++ counter = cpu_to_be32(value); \ ++} while (0) ++ + struct mlx4_mad_rcv_buf { + struct ib_grh grh; + u8 payload[256]; +@@ -730,10 +738,14 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, + static void edit_counter(struct mlx4_counter *cnt, + struct ib_pma_portcounters *pma_cnt) + { +- pma_cnt->port_xmit_data = cpu_to_be32((be64_to_cpu(cnt->tx_bytes)>>2)); +- pma_cnt->port_rcv_data = cpu_to_be32((be64_to_cpu(cnt->rx_bytes)>>2)); +- pma_cnt->port_xmit_packets = cpu_to_be32(be64_to_cpu(cnt->tx_frames)); +- pma_cnt->port_rcv_packets = cpu_to_be32(be64_to_cpu(cnt->rx_frames)); ++ ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_data, ++ (be64_to_cpu(cnt->tx_bytes) >> 2)); ++ ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_data, ++ (be64_to_cpu(cnt->rx_bytes) >> 2)); ++ ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_packets, ++ be64_to_cpu(cnt->tx_frames)); ++ ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_packets, ++ be64_to_cpu(cnt->rx_frames)); + } + + static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, +diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +index f723f1f2f578..ab851278d9d0 100644 +--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h ++++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +@@ -30,7 +30,7 @@ + + /* Offset base used to differentiate between CAPTURE and OUTPUT + * while mmaping */ +-#define DST_QUEUE_OFF_BASE (TASK_SIZE / 2) ++#define DST_QUEUE_OFF_BASE (1 << 30) + + #define MFC_BANK1_ALLOC_CTX 0 + #define MFC_BANK2_ALLOC_CTX 1 +diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c +index 744e43b480bc..f698e322a1cd 100644 +--- a/drivers/media/platform/sh_veu.c ++++ b/drivers/media/platform/sh_veu.c +@@ -1183,6 +1183,7 @@ static int sh_veu_probe(struct platform_device *pdev) + } + + *vdev = sh_veu_videodev; ++ vdev->v4l2_dev = &veu->v4l2_dev; + spin_lock_init(&veu->lock); + mutex_init(&veu->fop_lock); + vdev->lock = &veu->fop_lock; +diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c +index 61376abdab39..dbd8d21a8f10 100644 +--- a/drivers/net/can/flexcan.c ++++ b/drivers/net/can/flexcan.c +@@ -1095,12 +1095,19 @@ static int flexcan_probe(struct platform_device *pdev) + const struct flexcan_devtype_data *devtype_data; + struct net_device *dev; + struct flexcan_priv *priv; ++ struct regulator *reg_xceiver; + struct resource *mem; + struct clk *clk_ipg = NULL, *clk_per = NULL; + void __iomem *base; + int err, irq; + u32 clock_freq = 0; + ++ reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver"); ++ if (PTR_ERR(reg_xceiver) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ else if (IS_ERR(reg_xceiver)) ++ reg_xceiver = NULL; ++ + if (pdev->dev.of_node) + of_property_read_u32(pdev->dev.of_node, + "clock-frequency", &clock_freq); +@@ -1162,9 +1169,7 @@ static int flexcan_probe(struct platform_device *pdev) + priv->pdata = dev_get_platdata(&pdev->dev); + priv->devtype_data = devtype_data; + +- priv->reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver"); +- if (IS_ERR(priv->reg_xceiver)) +- priv->reg_xceiver = NULL; ++ priv->reg_xceiver = reg_xceiver; + + netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT); + +diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h +index 3441f70d0ff9..6e8cdb8a0cc5 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/dev.h ++++ b/drivers/net/wireless/iwlwifi/dvm/dev.h +@@ -708,7 +708,6 @@ struct iwl_priv { + unsigned long reload_jiffies; + int reload_count; + bool ucode_loaded; +- bool init_ucode_run; /* Don't run init uCode again */ + + u8 plcp_delta_threshold; + +diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c +index cf03ef5619d9..8b2dedc30159 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/ucode.c ++++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c +@@ -418,9 +418,6 @@ int iwl_run_init_ucode(struct iwl_priv *priv) + if (!priv->fw->img[IWL_UCODE_INIT].sec[0].len) + return 0; + +- if (priv->init_ucode_run) +- return 0; +- + iwl_init_notification_wait(&priv->notif_wait, &calib_wait, + calib_complete, ARRAY_SIZE(calib_complete), + iwlagn_wait_calib, priv); +@@ -440,8 +437,6 @@ int iwl_run_init_ucode(struct iwl_priv *priv) + */ + ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, + UCODE_CALIB_TIMEOUT); +- if (!ret) +- priv->init_ucode_run = true; + + goto out; + +diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c +index 34ff7026440c..5d3b45640181 100644 +--- a/drivers/pci/pcie/aer/aerdrv_errprint.c ++++ b/drivers/pci/pcie/aer/aerdrv_errprint.c +@@ -127,16 +127,8 @@ static const char *aer_agent_string[] = { + static void __print_tlp_header(struct pci_dev *dev, + struct aer_header_log_regs *t) + { +- unsigned char *tlp = (unsigned char *)&t; +- +- dev_err(&dev->dev, " TLP Header:" +- " %02x%02x%02x%02x %02x%02x%02x%02x" +- " %02x%02x%02x%02x %02x%02x%02x%02x\n", +- *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, +- *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), +- *(tlp + 11), *(tlp + 10), *(tlp + 9), +- *(tlp + 8), *(tlp + 15), *(tlp + 14), +- *(tlp + 13), *(tlp + 12)); ++ dev_err(&dev->dev, " TLP Header: %08x %08x %08x %08x\n", ++ t->dw0, t->dw1, t->dw2, t->dw3); + } + + static void __aer_print_error(struct pci_dev *dev, +diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c +index 953bd0bfdf0d..19ddd43a00cf 100644 +--- a/drivers/scsi/be2iscsi/be_main.c ++++ b/drivers/scsi/be2iscsi/be_main.c +@@ -5684,9 +5684,9 @@ free_port: + hba_free: + if (phba->msix_enabled) + pci_disable_msix(phba->pcidev); +- iscsi_host_remove(phba->shost); + pci_dev_put(phba->pcidev); + iscsi_host_free(phba->shost); ++ pci_set_drvdata(pcidev, NULL); + disable_pci: + pci_disable_device(pcidev); + return ret; +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index 64e487a8bf59..719bd8257520 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -1258,9 +1258,11 @@ int scsi_prep_state_check(struct scsi_device *sdev, struct request *req) + "rejecting I/O to dead device\n"); + ret = BLKPREP_KILL; + break; +- case SDEV_QUIESCE: + case SDEV_BLOCK: + case SDEV_CREATED_BLOCK: ++ ret = BLKPREP_DEFER; ++ break; ++ case SDEV_QUIESCE: + /* + * If the devices is blocked we defer normal commands. + */ +diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c +index e168a63e77ea..b61c555a5a8f 100644 +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -1165,7 +1165,7 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, + * traditional iSCSI block I/O. + */ + if (iscsit_allocate_iovecs(cmd) < 0) { +- return iscsit_add_reject_cmd(cmd, ++ return iscsit_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); + } + immed_data = cmd->immediate_data; +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index 850e232d086e..8ab46ad40f28 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -247,8 +247,6 @@ static void n_tty_write_wakeup(struct tty_struct *tty) + + static void n_tty_check_throttle(struct tty_struct *tty) + { +- if (tty->driver->type == TTY_DRIVER_TYPE_PTY) +- return; + /* + * Check the remaining room for the input canonicalization + * mode. We don't want to throttle the driver if we're in +@@ -1512,23 +1510,6 @@ n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag) + n_tty_receive_char_flagged(tty, c, flag); + } + +-/** +- * n_tty_receive_buf - data receive +- * @tty: terminal device +- * @cp: buffer +- * @fp: flag buffer +- * @count: characters +- * +- * Called by the terminal driver when a block of characters has +- * been received. This function must be called from soft contexts +- * not from interrupt context. The driver is responsible for making +- * calls one at a time and in order (or using flush_to_ldisc) +- * +- * n_tty_receive_buf()/producer path: +- * claims non-exclusive termios_rwsem +- * publishes read_head and canon_head +- */ +- + static void + n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count) +@@ -1684,24 +1665,85 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, + } + } + ++/** ++ * n_tty_receive_buf_common - process input ++ * @tty: device to receive input ++ * @cp: input chars ++ * @fp: flags for each char (if NULL, all chars are TTY_NORMAL) ++ * @count: number of input chars in @cp ++ * ++ * Called by the terminal driver when a block of characters has ++ * been received. This function must be called from soft contexts ++ * not from interrupt context. The driver is responsible for making ++ * calls one at a time and in order (or using flush_to_ldisc) ++ * ++ * Returns the # of input chars from @cp which were processed. ++ * ++ * In canonical mode, the maximum line length is 4096 chars (including ++ * the line termination char); lines longer than 4096 chars are ++ * truncated. After 4095 chars, input data is still processed but ++ * not stored. Overflow processing ensures the tty can always ++ * receive more input until at least one line can be read. ++ * ++ * In non-canonical mode, the read buffer will only accept 4095 chars; ++ * this provides the necessary space for a newline char if the input ++ * mode is switched to canonical. ++ * ++ * Note it is possible for the read buffer to _contain_ 4096 chars ++ * in non-canonical mode: the read buffer could already contain the ++ * maximum canon line of 4096 chars when the mode is switched to ++ * non-canonical. ++ * ++ * n_tty_receive_buf()/producer path: ++ * claims non-exclusive termios_rwsem ++ * publishes commit_head or canon_head ++ */ + static int + n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count, int flow) + { + struct n_tty_data *ldata = tty->disc_data; +- int room, n, rcvd = 0; ++ int room, n, rcvd = 0, overflow; + + down_read(&tty->termios_rwsem); + + while (1) { +- room = receive_room(tty); ++ /* ++ * When PARMRK is set, each input char may take up to 3 chars ++ * in the read buf; reduce the buffer space avail by 3x ++ * ++ * If we are doing input canonicalization, and there are no ++ * pending newlines, let characters through without limit, so ++ * that erase characters will be handled. Other excess ++ * characters will be beeped. ++ * ++ * paired with store in *_copy_from_read_buf() -- guarantees ++ * the consumer has loaded the data in read_buf up to the new ++ * read_tail (so this producer will not overwrite unread data) ++ */ ++ size_t tail = ldata->read_tail; ++ ++ room = N_TTY_BUF_SIZE - (ldata->read_head - tail); ++ if (I_PARMRK(tty)) ++ room = (room + 2) / 3; ++ room--; ++ if (room <= 0) { ++ overflow = ldata->icanon && ldata->canon_head == tail; ++ if (overflow && room < 0) ++ ldata->read_head--; ++ room = overflow; ++ ldata->no_room = flow && !room; ++ } else ++ overflow = 0; ++ + n = min(count, room); +- if (!n) { +- if (flow && !room) +- ldata->no_room = 1; ++ if (!n) + break; +- } +- __receive_buf(tty, cp, fp, n); ++ ++ /* ignore parity errors if handling overflow */ ++ if (!overflow || !fp || *fp != TTY_PARITY) ++ __receive_buf(tty, cp, fp, n); ++ + cp += n; + if (fp) + fp += n; +@@ -1710,7 +1752,17 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, + } + + tty->receive_room = room; +- n_tty_check_throttle(tty); ++ ++ /* Unthrottle if handling overflow on pty */ ++ if (tty->driver->type == TTY_DRIVER_TYPE_PTY) { ++ if (overflow) { ++ tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE); ++ tty_unthrottle_safe(tty); ++ __tty_set_flow_change(tty, 0); ++ } ++ } else ++ n_tty_check_throttle(tty); ++ + up_read(&tty->termios_rwsem); + + return rcvd; +diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c +index 175f123f4f09..501c465feb59 100644 +--- a/drivers/tty/serial/fsl_lpuart.c ++++ b/drivers/tty/serial/fsl_lpuart.c +@@ -362,6 +362,9 @@ static void lpuart_setup_watermark(struct lpuart_port *sport) + writeb(val | UARTPFIFO_TXFE | UARTPFIFO_RXFE, + sport->port.membase + UARTPFIFO); + ++ /* explicitly clear RDRF */ ++ readb(sport->port.membase + UARTSR1); ++ + /* flush Tx and Rx FIFO */ + writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH, + sport->port.membase + UARTCFIFO); +diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c +index 93fe089cd51a..b9e16abb0fab 100644 +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -383,6 +383,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, + status = PORT_PLC; + port_change_bit = "link state"; + break; ++ case USB_PORT_FEAT_C_PORT_CONFIG_ERROR: ++ status = PORT_CEC; ++ port_change_bit = "config error"; ++ break; + default: + /* Should never happen */ + return; +@@ -584,6 +588,8 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, + status |= USB_PORT_STAT_C_LINK_STATE << 16; + if ((raw_port_status & PORT_WRC)) + status |= USB_PORT_STAT_C_BH_RESET << 16; ++ if ((raw_port_status & PORT_CEC)) ++ status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; + } + + if (hcd->speed != HCD_USB3) { +@@ -999,6 +1005,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + case USB_PORT_FEAT_C_OVER_CURRENT: + case USB_PORT_FEAT_C_ENABLE: + case USB_PORT_FEAT_C_PORT_LINK_STATE: ++ case USB_PORT_FEAT_C_PORT_CONFIG_ERROR: + xhci_clear_port_change_bit(xhci, wValue, wIndex, + port_array[wIndex], temp); + break; +@@ -1063,7 +1070,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) + */ + status = bus_state->resuming_ports; + +- mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC; ++ mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC | PORT_CEC; + + spin_lock_irqsave(&xhci->lock, flags); + /* For each port, did anything change? If so, set that bit in buf. */ +diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c +index 73c43e5e231b..eb3399f4c1ed 100644 +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -108,6 +108,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + if (pdev->vendor == PCI_VENDOR_ID_INTEL) { + xhci->quirks |= XHCI_LPM_SUPPORT; + xhci->quirks |= XHCI_INTEL_HOST; ++ xhci->quirks |= XHCI_AVOID_BEI; + } + if (pdev->vendor == PCI_VENDOR_ID_INTEL && + pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) { +@@ -123,7 +124,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + * PPT chipsets. + */ + xhci->quirks |= XHCI_SPURIOUS_REBOOT; +- xhci->quirks |= XHCI_AVOID_BEI; + } + if (pdev->vendor == PCI_VENDOR_ID_INTEL && + (pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI || +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index 923500595357..2d858f81ab33 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -617,6 +617,7 @@ static const struct usb_device_id id_table_combined[] = { + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, ++ { USB_DEVICE(FTDI_VID, FTDI_SYNAPSE_SS200_PID) }, + /* + * ELV devices: + */ +@@ -1901,8 +1902,12 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial) + { + struct usb_device *udev = serial->dev; + +- if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) || +- (udev->product && !strcmp(udev->product, "BeagleBone/XDS100V2"))) ++ if (udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ++ return ftdi_jtag_probe(serial); ++ ++ if (udev->product && ++ (!strcmp(udev->product, "BeagleBone/XDS100V2") || ++ !strcmp(udev->product, "SNAP Connect E10"))) + return ftdi_jtag_probe(serial); + + return 0; +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index 56b1b55c4751..4e4f46f3c89c 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -561,6 +561,12 @@ + */ + #define FTDI_NT_ORIONLXM_PID 0x7c90 /* OrionLXm Substation Automation Platform */ + ++/* ++ * Synapse Wireless product ids (FTDI_VID) ++ * http://www.synapse-wireless.com ++ */ ++#define FTDI_SYNAPSE_SS200_PID 0x9090 /* SS200 - SNAP Stick 200 */ ++ + + /********************************/ + /** third-party VID/PID combos **/ +diff --git a/fs/aio.c b/fs/aio.c +index 2f7e8c2e3e76..3241659491b1 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -719,6 +719,9 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) + err_cleanup: + aio_nr_sub(ctx->max_reqs); + err_ctx: ++ atomic_set(&ctx->dead, 1); ++ if (ctx->mmap_size) ++ vm_munmap(ctx->mmap_base, ctx->mmap_size); + aio_free_ring(ctx); + err: + mutex_unlock(&ctx->ring_lock); +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index a7f32bfdd5e7..ec8b6542c8bd 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -1235,21 +1235,13 @@ out: + } + + static int insert_orphan_item(struct btrfs_trans_handle *trans, +- struct btrfs_root *root, u64 offset) ++ struct btrfs_root *root, u64 ino) + { + int ret; +- struct btrfs_path *path; +- +- path = btrfs_alloc_path(); +- if (!path) +- return -ENOMEM; + +- ret = btrfs_find_item(root, path, BTRFS_ORPHAN_OBJECTID, +- offset, BTRFS_ORPHAN_ITEM_KEY, NULL); +- if (ret > 0) +- ret = btrfs_insert_orphan_item(trans, root, offset); +- +- btrfs_free_path(path); ++ ret = btrfs_insert_orphan_item(trans, root, ino); ++ if (ret == -EEXIST) ++ ret = 0; + + return ret; + } +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index 0218a9b23b38..40ddb6e93912 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -1821,6 +1821,7 @@ refind_writable: + cifsFileInfo_put(inv_file); + spin_lock(&cifs_file_list_lock); + ++refind; ++ inv_file = NULL; + goto refind_writable; + } + } +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 34a17d425be6..30f3eb5bc022 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -630,7 +630,8 @@ smb2_clone_range(const unsigned int xid, + + /* No need to change MaxChunks since already set to 1 */ + chunk_sizes_updated = true; +- } ++ } else ++ goto cchunk_out; + } + + cchunk_out: +diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c +index 51632c40e896..7fe30f655aa5 100644 +--- a/fs/ocfs2/file.c ++++ b/fs/ocfs2/file.c +@@ -2391,10 +2391,14 @@ out_dio: + /* buffered aio wouldn't have proper lock coverage today */ + BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); + ++ if (unlikely(written <= 0)) ++ goto no_sync; ++ + if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) || + ((file->f_flags & O_DIRECT) && !direct_io)) { +- ret = filemap_fdatawrite_range(file->f_mapping, *ppos, +- *ppos + count - 1); ++ ret = filemap_fdatawrite_range(file->f_mapping, ++ iocb->ki_pos - written, ++ iocb->ki_pos - 1); + if (ret < 0) + written = ret; + +@@ -2407,10 +2411,12 @@ out_dio: + } + + if (!ret) +- ret = filemap_fdatawait_range(file->f_mapping, *ppos, +- *ppos + count - 1); ++ ret = filemap_fdatawait_range(file->f_mapping, ++ iocb->ki_pos - written, ++ iocb->ki_pos - 1); + } + ++no_sync: + /* + * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io + * function pointer which is called when o_direct io completes so that +diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h +index bbc3a6c88fce..33fd7ff53a77 100644 +--- a/include/linux/blk_types.h ++++ b/include/linux/blk_types.h +@@ -180,7 +180,9 @@ enum rq_flag_bits { + __REQ_ELVPRIV, /* elevator private data attached */ + __REQ_FAILED, /* set if the request failed */ + __REQ_QUIET, /* don't worry about errors */ +- __REQ_PREEMPT, /* set for "ide_preempt" requests */ ++ __REQ_PREEMPT, /* set for "ide_preempt" requests and also ++ for requests for which the SCSI "quiesce" ++ state must be ignored. */ + __REQ_ALLOCED, /* request came from our alloc pool */ + __REQ_COPY_USER, /* contains copies of user pages */ + __REQ_FLUSH_SEQ, /* request for flush sequence */ +diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h +index 50fcbb0ac4e7..d1338170b6b9 100644 +--- a/include/linux/cpuidle.h ++++ b/include/linux/cpuidle.h +@@ -69,7 +69,6 @@ struct cpuidle_device { + unsigned int cpu; + + int last_residency; +- int state_count; + struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX]; + struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX]; + struct cpuidle_driver_kobj *kobj_driver; +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 9a3f3c4e1f5a..5e973efc036e 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -2980,6 +2980,8 @@ void rt_mutex_setprio(struct task_struct *p, int prio) + } else { + if (dl_prio(oldprio)) + p->dl.dl_boosted = 0; ++ if (rt_prio(oldprio)) ++ p->rt.timeout = 0; + p->sched_class = &fair_sched_class; + } + +diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c +index f6f23833de44..c8e450132813 100644 +--- a/mm/memory_hotplug.c ++++ b/mm/memory_hotplug.c +@@ -1016,6 +1016,10 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start) + return NULL; + + arch_refresh_nodedata(nid, pgdat); ++ } else { ++ /* Reset the nr_zones and classzone_idx to 0 before reuse */ ++ pgdat->nr_zones = 0; ++ pgdat->classzone_idx = 0; + } + + /* we can use NODE_DATA(nid) from here */ +@@ -1863,15 +1867,6 @@ void try_offline_node(int nid) + if (is_vmalloc_addr(zone->wait_table)) + vfree(zone->wait_table); + } +- +- /* +- * Since there is no way to guarentee the address of pgdat/zone is not +- * on stack of any kernel threads or used by other kernel objects +- * without reference counting or other symchronizing method, do not +- * reset node_data and free pgdat here. Just reset it to 0 and reuse +- * the memory when the node is online again. +- */ +- memset(pgdat, 0, sizeof(*pgdat)); + } + EXPORT_SYMBOL(try_offline_node); + +diff --git a/mm/page-writeback.c b/mm/page-writeback.c +index 9f45f87a5859..51d8d15f48d7 100644 +--- a/mm/page-writeback.c ++++ b/mm/page-writeback.c +@@ -878,8 +878,11 @@ static void bdi_update_write_bandwidth(struct backing_dev_info *bdi, + * bw * elapsed + write_bandwidth * (period - elapsed) + * write_bandwidth = --------------------------------------------------- + * period ++ * ++ * @written may have decreased due to account_page_redirty(). ++ * Avoid underflowing @bw calculation. + */ +- bw = written - bdi->written_stamp; ++ bw = written - min(written, bdi->written_stamp); + bw *= HZ; + if (unlikely(elapsed > period)) { + do_div(bw, elapsed); +@@ -943,7 +946,7 @@ static void global_update_bandwidth(unsigned long thresh, + unsigned long now) + { + static DEFINE_SPINLOCK(dirty_lock); +- static unsigned long update_time; ++ static unsigned long update_time = INITIAL_JIFFIES; + + /* + * check locklessly first to optimize away locking for the most time +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index d0c310801479..96f64e59d70c 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -2933,6 +2933,7 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) + goto fallback; + syn_data->ip_summed = CHECKSUM_PARTIAL; + memcpy(syn_data->cb, syn->cb, sizeof(syn->cb)); ++ skb_shinfo(syn_data)->gso_segs = 1; + if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space), + fo->data->msg_iov, 0, space))) { + kfree_skb(syn_data); +diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c +index 612a5ddaf93b..799bafc2af39 100644 +--- a/net/llc/sysctl_net_llc.c ++++ b/net/llc/sysctl_net_llc.c +@@ -18,28 +18,28 @@ static struct ctl_table llc2_timeout_table[] = { + { + .procname = "ack", + .data = &sysctl_llc2_ack_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_ack_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "busy", + .data = &sysctl_llc2_busy_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_busy_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "p", + .data = &sysctl_llc2_p_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_p_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "rej", + .data = &sysctl_llc2_rej_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_rej_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, +diff --git a/net/rds/sysctl.c b/net/rds/sysctl.c +index b5cb2aa08f33..35773ad6d23d 100644 +--- a/net/rds/sysctl.c ++++ b/net/rds/sysctl.c +@@ -71,14 +71,14 @@ static struct ctl_table rds_sysctl_rds_table[] = { + { + .procname = "max_unacked_packets", + .data = &rds_sysctl_max_unacked_packets, +- .maxlen = sizeof(unsigned long), ++ .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "max_unacked_bytes", + .data = &rds_sysctl_max_unacked_bytes, +- .maxlen = sizeof(unsigned long), ++ .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, +diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c +index d60c0ee66387..6c4cbd97a673 100644 +--- a/security/selinux/selinuxfs.c ++++ b/security/selinux/selinuxfs.c +@@ -152,7 +152,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, + goto out; + + /* No partial writes. */ +- length = EINVAL; ++ length = -EINVAL; + if (*ppos != 0) + goto out; + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 910f2dbe1b24..ca26373ebe70 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -271,7 +271,7 @@ static void alc_auto_setup_eapd(struct hda_codec *codec, bool on) + { + /* We currently only handle front, HP */ + static hda_nid_t pins[] = { +- 0x0f, 0x10, 0x14, 0x15, 0 ++ 0x0f, 0x10, 0x14, 0x15, 0x17, 0 + }; + hda_nid_t *p; + for (p = pins; *p; p++) +@@ -2885,6 +2885,8 @@ static void alc283_init(struct hda_codec *codec) + + if (!hp_pin) + return; ++ ++ msleep(30); + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + + /* Index 0x43 Direct Drive HP AMP LPM Control 1 */ +@@ -3951,6 +3953,7 @@ enum { + ALC269_FIXUP_QUANTA_MUTE, + ALC269_FIXUP_LIFEBOOK, + ALC269_FIXUP_LIFEBOOK_EXTMIC, ++ ALC269_FIXUP_LIFEBOOK_HP_PIN, + ALC269_FIXUP_AMIC, + ALC269_FIXUP_DMIC, + ALC269VB_FIXUP_AMIC, +@@ -4085,6 +4088,13 @@ static const struct hda_fixup alc269_fixups[] = { + { } + }, + }, ++ [ALC269_FIXUP_LIFEBOOK_HP_PIN] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x21, 0x0221102f }, /* HP out */ ++ { } ++ }, ++ }, + [ALC269_FIXUP_AMIC] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { +@@ -4538,6 +4548,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), + SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), + SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), ++ SND_PCI_QUIRK(0x10cf, 0x15dc, "Lifebook T731", ALC269_FIXUP_LIFEBOOK_HP_PIN), + SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), + SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), +diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c +index 5a723df670b4..a82ec53b8fb3 100644 +--- a/sound/usb/mixer_quirks.c ++++ b/sound/usb/mixer_quirks.c +@@ -178,6 +178,7 @@ static const struct rc_config { + { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ + { USB_ID(0x041e, 0x3042), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 */ + { USB_ID(0x041e, 0x30df), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */ ++ { USB_ID(0x041e, 0x3237), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */ + { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ + }; + diff --git a/patch/kernel/cubox-default/patch-3.14.39-40.patch b/patch/kernel/cubox-default/patch-3.14.39-40.patch new file mode 100644 index 000000000..550549b51 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.39-40.patch @@ -0,0 +1,2462 @@ +diff --git a/Makefile b/Makefile +index b40845e11b84..070e0ebb9231 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 39 ++SUBLEVEL = 40 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c +index 98838a05ba6d..9d0ac091a52a 100644 +--- a/arch/alpha/mm/fault.c ++++ b/arch/alpha/mm/fault.c +@@ -156,6 +156,8 @@ retry: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c +index 9c69552350c4..01e18b58dfa4 100644 +--- a/arch/arc/mm/fault.c ++++ b/arch/arc/mm/fault.c +@@ -162,6 +162,8 @@ good_area: + /* TBD: switch to pagefault_out_of_memory() */ + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + +diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h +index 626989fec4d3..9fd61c72a33a 100644 +--- a/arch/arm/include/asm/pgtable-3level-hwdef.h ++++ b/arch/arm/include/asm/pgtable-3level-hwdef.h +@@ -43,7 +43,7 @@ + #define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) + #define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) + #define PMD_SECT_USER (_AT(pmdval_t, 1) << 6) /* AP[1] */ +-#define PMD_SECT_RDONLY (_AT(pmdval_t, 1) << 7) /* AP[2] */ ++#define PMD_SECT_AP2 (_AT(pmdval_t, 1) << 7) /* read only */ + #define PMD_SECT_S (_AT(pmdval_t, 3) << 8) + #define PMD_SECT_AF (_AT(pmdval_t, 1) << 10) + #define PMD_SECT_nG (_AT(pmdval_t, 1) << 11) +@@ -72,6 +72,7 @@ + #define PTE_TABLE_BIT (_AT(pteval_t, 1) << 1) + #define PTE_BUFFERABLE (_AT(pteval_t, 1) << 2) /* AttrIndx[0] */ + #define PTE_CACHEABLE (_AT(pteval_t, 1) << 3) /* AttrIndx[1] */ ++#define PTE_AP2 (_AT(pteval_t, 1) << 7) /* AP[2] */ + #define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ + #define PTE_EXT_AF (_AT(pteval_t, 1) << 10) /* Access Flag */ + #define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* nG */ +diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h +index 85c60adc8b60..06e0bc0f8b00 100644 +--- a/arch/arm/include/asm/pgtable-3level.h ++++ b/arch/arm/include/asm/pgtable-3level.h +@@ -79,18 +79,19 @@ + #define L_PTE_PRESENT (_AT(pteval_t, 3) << 0) /* Present */ + #define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */ + #define L_PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */ +-#define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) /* AP[2] */ + #define L_PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ + #define L_PTE_YOUNG (_AT(pteval_t, 1) << 10) /* AF */ + #define L_PTE_XN (_AT(pteval_t, 1) << 54) /* XN */ +-#define L_PTE_DIRTY (_AT(pteval_t, 1) << 55) /* unused */ +-#define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) /* unused */ ++#define L_PTE_DIRTY (_AT(pteval_t, 1) << 55) ++#define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) + #define L_PTE_NONE (_AT(pteval_t, 1) << 57) /* PROT_NONE */ ++#define L_PTE_RDONLY (_AT(pteval_t, 1) << 58) /* READ ONLY */ + +-#define PMD_SECT_VALID (_AT(pmdval_t, 1) << 0) +-#define PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55) +-#define PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 56) +-#define PMD_SECT_NONE (_AT(pmdval_t, 1) << 57) ++#define L_PMD_SECT_VALID (_AT(pmdval_t, 1) << 0) ++#define L_PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55) ++#define L_PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 56) ++#define L_PMD_SECT_NONE (_AT(pmdval_t, 1) << 57) ++#define L_PMD_SECT_RDONLY (_AT(pteval_t, 1) << 58) + + /* + * To be used in assembly code with the upper page attributes. +@@ -207,27 +208,32 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) + #define pte_huge(pte) (pte_val(pte) && !(pte_val(pte) & PTE_TABLE_BIT)) + #define pte_mkhuge(pte) (__pte(pte_val(pte) & ~PTE_TABLE_BIT)) + +-#define pmd_young(pmd) (pmd_val(pmd) & PMD_SECT_AF) ++#define pmd_isset(pmd, val) ((u32)(val) == (val) ? pmd_val(pmd) & (val) \ ++ : !!(pmd_val(pmd) & (val))) ++#define pmd_isclear(pmd, val) (!(pmd_val(pmd) & (val))) ++ ++#define pmd_young(pmd) (pmd_isset((pmd), PMD_SECT_AF)) + + #define __HAVE_ARCH_PMD_WRITE +-#define pmd_write(pmd) (!(pmd_val(pmd) & PMD_SECT_RDONLY)) ++#define pmd_write(pmd) (pmd_isclear((pmd), L_PMD_SECT_RDONLY)) ++#define pmd_dirty(pmd) (pmd_isset((pmd), L_PMD_SECT_DIRTY)) + + #define pmd_hugewillfault(pmd) (!pmd_young(pmd) || !pmd_write(pmd)) + #define pmd_thp_or_huge(pmd) (pmd_huge(pmd) || pmd_trans_huge(pmd)) + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE +-#define pmd_trans_huge(pmd) (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT)) +-#define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING) ++#define pmd_trans_huge(pmd) (pmd_val(pmd) && !pmd_table(pmd)) ++#define pmd_trans_splitting(pmd) (pmd_isset((pmd), L_PMD_SECT_SPLITTING)) + #endif + + #define PMD_BIT_FUNC(fn,op) \ + static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; } + +-PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY); ++PMD_BIT_FUNC(wrprotect, |= L_PMD_SECT_RDONLY); + PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF); +-PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING); +-PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY); +-PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY); ++PMD_BIT_FUNC(mksplitting, |= L_PMD_SECT_SPLITTING); ++PMD_BIT_FUNC(mkwrite, &= ~L_PMD_SECT_RDONLY); ++PMD_BIT_FUNC(mkdirty, |= L_PMD_SECT_DIRTY); + PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF); + + #define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT)) +@@ -241,8 +247,8 @@ PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF); + + static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) + { +- const pmdval_t mask = PMD_SECT_USER | PMD_SECT_XN | PMD_SECT_RDONLY | +- PMD_SECT_VALID | PMD_SECT_NONE; ++ const pmdval_t mask = PMD_SECT_USER | PMD_SECT_XN | L_PMD_SECT_RDONLY | ++ L_PMD_SECT_VALID | L_PMD_SECT_NONE; + pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask); + return pmd; + } +@@ -253,8 +259,13 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, + BUG_ON(addr >= TASK_SIZE); + + /* create a faulting entry if PROT_NONE protected */ +- if (pmd_val(pmd) & PMD_SECT_NONE) +- pmd_val(pmd) &= ~PMD_SECT_VALID; ++ if (pmd_val(pmd) & L_PMD_SECT_NONE) ++ pmd_val(pmd) &= ~L_PMD_SECT_VALID; ++ ++ if (pmd_write(pmd) && pmd_dirty(pmd)) ++ pmd_val(pmd) &= ~PMD_SECT_AP2; ++ else ++ pmd_val(pmd) |= PMD_SECT_AP2; + + *pmdp = __pmd(pmd_val(pmd) | PMD_SECT_nG); + flush_pmd_entry(pmdp); +diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h +index 7d59b524f2af..89dba131703b 100644 +--- a/arch/arm/include/asm/pgtable.h ++++ b/arch/arm/include/asm/pgtable.h +@@ -214,12 +214,16 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) + + #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) + ++#define pte_isset(pte, val) ((u32)(val) == (val) ? pte_val(pte) & (val) \ ++ : !!(pte_val(pte) & (val))) ++#define pte_isclear(pte, val) (!(pte_val(pte) & (val))) ++ + #define pte_none(pte) (!pte_val(pte)) +-#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) +-#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY)) +-#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) +-#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) +-#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) ++#define pte_present(pte) (pte_isset((pte), L_PTE_PRESENT)) ++#define pte_write(pte) (pte_isclear((pte), L_PTE_RDONLY)) ++#define pte_dirty(pte) (pte_isset((pte), L_PTE_DIRTY)) ++#define pte_young(pte) (pte_isset((pte), L_PTE_YOUNG)) ++#define pte_exec(pte) (pte_isclear((pte), L_PTE_XN)) + #define pte_special(pte) (0) + + #define pte_present_user(pte) (pte_present(pte) && (pte_val(pte) & L_PTE_USER)) +diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S +index 22e3ad63500c..eb81123a845d 100644 +--- a/arch/arm/mm/proc-v7-3level.S ++++ b/arch/arm/mm/proc-v7-3level.S +@@ -86,8 +86,13 @@ ENTRY(cpu_v7_set_pte_ext) + tst rh, #1 << (57 - 32) @ L_PTE_NONE + bicne rl, #L_PTE_VALID + bne 1f +- tst rh, #1 << (55 - 32) @ L_PTE_DIRTY +- orreq rl, #L_PTE_RDONLY ++ ++ eor ip, rh, #1 << (55 - 32) @ toggle L_PTE_DIRTY in temp reg to ++ @ test for !L_PTE_DIRTY || L_PTE_RDONLY ++ tst ip, #1 << (55 - 32) | 1 << (58 - 32) ++ orrne rl, #PTE_AP2 ++ biceq rl, #PTE_AP2 ++ + 1: strd r2, r3, [r0] + ALT_SMP(W(nop)) + ALT_UP (mcr p15, 0, r0, c7, c10, 1) @ flush_pte +diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c +index 0eca93327195..d223a8b57c1e 100644 +--- a/arch/avr32/mm/fault.c ++++ b/arch/avr32/mm/fault.c +@@ -142,6 +142,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c +index 1790f22e71a2..2686a7aa8ec8 100644 +--- a/arch/cris/mm/fault.c ++++ b/arch/cris/mm/fault.c +@@ -176,6 +176,8 @@ retry: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/frv/mm/fault.c b/arch/frv/mm/fault.c +index 9a66372fc7c7..ec4917ddf678 100644 +--- a/arch/frv/mm/fault.c ++++ b/arch/frv/mm/fault.c +@@ -168,6 +168,8 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c +index 7225dad87094..ba5ba7accd0d 100644 +--- a/arch/ia64/mm/fault.c ++++ b/arch/ia64/mm/fault.c +@@ -172,6 +172,8 @@ retry: + */ + if (fault & VM_FAULT_OOM) { + goto out_of_memory; ++ } else if (fault & VM_FAULT_SIGSEGV) { ++ goto bad_area; + } else if (fault & VM_FAULT_SIGBUS) { + signal = SIGBUS; + goto bad_area; +diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c +index e9c6a8014bd6..e3d4d4890104 100644 +--- a/arch/m32r/mm/fault.c ++++ b/arch/m32r/mm/fault.c +@@ -200,6 +200,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c +index 2bd7487440c4..b2f04aee46ec 100644 +--- a/arch/m68k/mm/fault.c ++++ b/arch/m68k/mm/fault.c +@@ -145,6 +145,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto map_err; + else if (fault & VM_FAULT_SIGBUS) + goto bus_err; + BUG(); +diff --git a/arch/metag/mm/fault.c b/arch/metag/mm/fault.c +index 332680e5ebf2..2de5dc695a87 100644 +--- a/arch/metag/mm/fault.c ++++ b/arch/metag/mm/fault.c +@@ -141,6 +141,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/microblaze/mm/fault.c b/arch/microblaze/mm/fault.c +index fa4cf52aa7a6..d46a5ebb7570 100644 +--- a/arch/microblaze/mm/fault.c ++++ b/arch/microblaze/mm/fault.c +@@ -224,6 +224,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c +index becc42bb1849..70ab5d664332 100644 +--- a/arch/mips/mm/fault.c ++++ b/arch/mips/mm/fault.c +@@ -158,6 +158,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c +index 3516cbdf1ee9..0c2cc5d39c8e 100644 +--- a/arch/mn10300/mm/fault.c ++++ b/arch/mn10300/mm/fault.c +@@ -262,6 +262,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c +index 0703acf7d327..230ac20ae794 100644 +--- a/arch/openrisc/mm/fault.c ++++ b/arch/openrisc/mm/fault.c +@@ -171,6 +171,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c +index d72197f0ddb8..d27e38874e81 100644 +--- a/arch/parisc/mm/fault.c ++++ b/arch/parisc/mm/fault.c +@@ -256,6 +256,8 @@ good_area: + */ + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto bad_area; + BUG(); +diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c +index 51ab9e7e6c39..010fabf3828c 100644 +--- a/arch/powerpc/mm/fault.c ++++ b/arch/powerpc/mm/fault.c +@@ -432,6 +432,8 @@ good_area: + */ + fault = handle_mm_fault(mm, vma, address, flags); + if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) { ++ if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + rc = mm_fault_error(regs, address, fault); + if (rc >= MM_FAULT_RETURN) + goto bail; +diff --git a/arch/powerpc/platforms/cell/spu_fault.c b/arch/powerpc/platforms/cell/spu_fault.c +index 641e7273d75a..62f3e4e48a0b 100644 +--- a/arch/powerpc/platforms/cell/spu_fault.c ++++ b/arch/powerpc/platforms/cell/spu_fault.c +@@ -75,7 +75,7 @@ int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, + if (*flt & VM_FAULT_OOM) { + ret = -ENOMEM; + goto out_unlock; +- } else if (*flt & VM_FAULT_SIGBUS) { ++ } else if (*flt & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) { + ret = -EFAULT; + goto out_unlock; + } +diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c +index 87ba7cf99cd7..65d633f20d37 100644 +--- a/arch/powerpc/platforms/cell/spufs/inode.c ++++ b/arch/powerpc/platforms/cell/spufs/inode.c +@@ -164,7 +164,7 @@ static void spufs_prune_dir(struct dentry *dir) + struct dentry *dentry, *tmp; + + mutex_lock(&dir->d_inode->i_mutex); +- list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) { ++ list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) { + spin_lock(&dentry->d_lock); + if (!(d_unhashed(dentry)) && dentry->d_inode) { + dget_dlock(dentry); +diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c +index d95265b2719f..8e95432cc3b2 100644 +--- a/arch/s390/mm/fault.c ++++ b/arch/s390/mm/fault.c +@@ -239,6 +239,12 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault) + do_no_context(regs); + else + pagefault_out_of_memory(); ++ } else if (fault & VM_FAULT_SIGSEGV) { ++ /* Kernel mode? Handle exceptions or die */ ++ if (!user_mode(regs)) ++ do_no_context(regs); ++ else ++ do_sigsegv(regs, SEGV_MAPERR); + } else if (fault & VM_FAULT_SIGBUS) { + /* Kernel mode? Handle exceptions or die */ + if (!user_mode(regs)) +diff --git a/arch/score/mm/fault.c b/arch/score/mm/fault.c +index 52238983527d..6860beb2a280 100644 +--- a/arch/score/mm/fault.c ++++ b/arch/score/mm/fault.c +@@ -114,6 +114,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c +index 541dc6101508..a58fec9b55e0 100644 +--- a/arch/sh/mm/fault.c ++++ b/arch/sh/mm/fault.c +@@ -353,6 +353,8 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, + } else { + if (fault & VM_FAULT_SIGBUS) + do_sigbus(regs, error_code, address); ++ else if (fault & VM_FAULT_SIGSEGV) ++ bad_area(regs, error_code, address); + else + BUG(); + } +diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c +index 59dbd4645725..163c78712110 100644 +--- a/arch/sparc/mm/fault_32.c ++++ b/arch/sparc/mm/fault_32.c +@@ -252,6 +252,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c +index 45a413e4380a..0d6de79105b6 100644 +--- a/arch/sparc/mm/fault_64.c ++++ b/arch/sparc/mm/fault_64.c +@@ -448,6 +448,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c +index 6c0571216a9d..c6d2a76d91a8 100644 +--- a/arch/tile/mm/fault.c ++++ b/arch/tile/mm/fault.c +@@ -444,6 +444,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c +index 974b87474a99..53b832033d9b 100644 +--- a/arch/um/kernel/trap.c ++++ b/arch/um/kernel/trap.c +@@ -80,6 +80,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) { + goto out_of_memory; ++ } else if (fault & VM_FAULT_SIGSEGV) { ++ goto out; + } else if (fault & VM_FAULT_SIGBUS) { + err = -EACCES; + goto out; +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index 09651d4a9038..cf1eeeafdfa3 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -2258,7 +2258,7 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt) + * Not recognized on AMD in compat mode (but is recognized in legacy + * mode). + */ +- if ((ctxt->mode == X86EMUL_MODE_PROT32) && (efer & EFER_LMA) ++ if ((ctxt->mode != X86EMUL_MODE_PROT64) && (efer & EFER_LMA) + && !vendor_intel(ctxt)) + return emulate_ud(ctxt); + +@@ -2271,25 +2271,13 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt) + setup_syscalls_segments(ctxt, &cs, &ss); + + ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data); +- switch (ctxt->mode) { +- case X86EMUL_MODE_PROT32: +- if ((msr_data & 0xfffc) == 0x0) +- return emulate_gp(ctxt, 0); +- break; +- case X86EMUL_MODE_PROT64: +- if (msr_data == 0x0) +- return emulate_gp(ctxt, 0); +- break; +- default: +- break; +- } ++ if ((msr_data & 0xfffc) == 0x0) ++ return emulate_gp(ctxt, 0); + + ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF); +- cs_sel = (u16)msr_data; +- cs_sel &= ~SELECTOR_RPL_MASK; ++ cs_sel = (u16)msr_data & ~SELECTOR_RPL_MASK; + ss_sel = cs_sel + 8; +- ss_sel &= ~SELECTOR_RPL_MASK; +- if (ctxt->mode == X86EMUL_MODE_PROT64 || (efer & EFER_LMA)) { ++ if (efer & EFER_LMA) { + cs.d = 0; + cs.l = 1; + } +@@ -2298,10 +2286,11 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt) + ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS); + + ops->get_msr(ctxt, MSR_IA32_SYSENTER_EIP, &msr_data); +- ctxt->_eip = msr_data; ++ ctxt->_eip = (efer & EFER_LMA) ? msr_data : (u32)msr_data; + + ops->get_msr(ctxt, MSR_IA32_SYSENTER_ESP, &msr_data); +- *reg_write(ctxt, VCPU_REGS_RSP) = msr_data; ++ *reg_write(ctxt, VCPU_REGS_RSP) = (efer & EFER_LMA) ? msr_data : ++ (u32)msr_data; + + return X86EMUL_CONTINUE; + } +diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c +index a10c8c792161..ebc551c82605 100644 +--- a/arch/x86/mm/fault.c ++++ b/arch/x86/mm/fault.c +@@ -833,11 +833,8 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, + unsigned int fault) + { + struct task_struct *tsk = current; +- struct mm_struct *mm = tsk->mm; + int code = BUS_ADRERR; + +- up_read(&mm->mmap_sem); +- + /* Kernel mode? Handle exceptions or die: */ + if (!(error_code & PF_USER)) { + no_context(regs, error_code, address, SIGBUS, BUS_ADRERR); +@@ -868,7 +865,6 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, + unsigned long address, unsigned int fault) + { + if (fatal_signal_pending(current) && !(error_code & PF_USER)) { +- up_read(¤t->mm->mmap_sem); + no_context(regs, error_code, address, 0, 0); + return; + } +@@ -876,14 +872,11 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, + if (fault & VM_FAULT_OOM) { + /* Kernel mode? Handle exceptions or die: */ + if (!(error_code & PF_USER)) { +- up_read(¤t->mm->mmap_sem); + no_context(regs, error_code, address, + SIGSEGV, SEGV_MAPERR); + return; + } + +- up_read(¤t->mm->mmap_sem); +- + /* + * We ran out of memory, call the OOM killer, and return the + * userspace (which will retry the fault, or kill us if we got +@@ -894,6 +887,8 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, + if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON| + VM_FAULT_HWPOISON_LARGE)) + do_sigbus(regs, error_code, address, fault); ++ else if (fault & VM_FAULT_SIGSEGV) ++ bad_area_nosemaphore(regs, error_code, address); + else + BUG(); + } +@@ -1216,6 +1211,7 @@ good_area: + return; + + if (unlikely(fault & VM_FAULT_ERROR)) { ++ up_read(&mm->mmap_sem); + mm_fault_error(regs, error_code, address, fault); + return; + } +diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c +index b57c4f91f487..9e3571a6535c 100644 +--- a/arch/xtensa/mm/fault.c ++++ b/arch/xtensa/mm/fault.c +@@ -117,6 +117,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index f667e37394da..5afe556a70f8 100644 +--- a/drivers/bluetooth/ath3k.c ++++ b/drivers/bluetooth/ath3k.c +@@ -62,51 +62,59 @@ static const struct usb_device_id ath3k_table[] = { + { USB_DEVICE(0x0CF3, 0x3000) }, + + /* Atheros AR3011 with sflash firmware*/ ++ { USB_DEVICE(0x0489, 0xE027) }, ++ { USB_DEVICE(0x0489, 0xE03D) }, ++ { USB_DEVICE(0x0930, 0x0215) }, + { USB_DEVICE(0x0CF3, 0x3002) }, + { USB_DEVICE(0x0CF3, 0xE019) }, + { USB_DEVICE(0x13d3, 0x3304) }, +- { USB_DEVICE(0x0930, 0x0215) }, +- { USB_DEVICE(0x0489, 0xE03D) }, +- { USB_DEVICE(0x0489, 0xE027) }, + + /* Atheros AR9285 Malbec with sflash firmware */ + { USB_DEVICE(0x03F0, 0x311D) }, + + /* Atheros AR3012 with sflash firmware*/ +- { USB_DEVICE(0x0CF3, 0x0036) }, +- { USB_DEVICE(0x0CF3, 0x3004) }, +- { USB_DEVICE(0x0CF3, 0x3008) }, +- { USB_DEVICE(0x0CF3, 0x311D) }, +- { USB_DEVICE(0x0CF3, 0x817a) }, +- { USB_DEVICE(0x13d3, 0x3375) }, ++ { USB_DEVICE(0x0489, 0xe04d) }, ++ { USB_DEVICE(0x0489, 0xe04e) }, ++ { USB_DEVICE(0x0489, 0xe057) }, ++ { USB_DEVICE(0x0489, 0xe056) }, ++ { USB_DEVICE(0x0489, 0xe05f) }, ++ { USB_DEVICE(0x0489, 0xe078) }, ++ { USB_DEVICE(0x04c5, 0x1330) }, + { USB_DEVICE(0x04CA, 0x3004) }, + { USB_DEVICE(0x04CA, 0x3005) }, + { USB_DEVICE(0x04CA, 0x3006) }, + { USB_DEVICE(0x04CA, 0x3007) }, + { USB_DEVICE(0x04CA, 0x3008) }, + { USB_DEVICE(0x04CA, 0x300b) }, +- { USB_DEVICE(0x13d3, 0x3362) }, +- { USB_DEVICE(0x0CF3, 0xE004) }, +- { USB_DEVICE(0x0CF3, 0xE005) }, ++ { USB_DEVICE(0x04CA, 0x3010) }, + { USB_DEVICE(0x0930, 0x0219) }, + { USB_DEVICE(0x0930, 0x0220) }, +- { USB_DEVICE(0x0489, 0xe057) }, +- { USB_DEVICE(0x13d3, 0x3393) }, +- { USB_DEVICE(0x0489, 0xe04e) }, +- { USB_DEVICE(0x0489, 0xe056) }, +- { USB_DEVICE(0x0489, 0xe04d) }, +- { USB_DEVICE(0x04c5, 0x1330) }, +- { USB_DEVICE(0x13d3, 0x3402) }, ++ { USB_DEVICE(0x0930, 0x0227) }, ++ { USB_DEVICE(0x0b05, 0x17d0) }, ++ { USB_DEVICE(0x0CF3, 0x0036) }, ++ { USB_DEVICE(0x0CF3, 0x3004) }, ++ { USB_DEVICE(0x0CF3, 0x3008) }, ++ { USB_DEVICE(0x0CF3, 0x311D) }, ++ { USB_DEVICE(0x0CF3, 0x311E) }, ++ { USB_DEVICE(0x0CF3, 0x311F) }, + { USB_DEVICE(0x0cf3, 0x3121) }, ++ { USB_DEVICE(0x0CF3, 0x817a) }, + { USB_DEVICE(0x0cf3, 0xe003) }, +- { USB_DEVICE(0x0489, 0xe05f) }, ++ { USB_DEVICE(0x0CF3, 0xE004) }, ++ { USB_DEVICE(0x0CF3, 0xE005) }, ++ { USB_DEVICE(0x13d3, 0x3362) }, ++ { USB_DEVICE(0x13d3, 0x3375) }, ++ { USB_DEVICE(0x13d3, 0x3393) }, ++ { USB_DEVICE(0x13d3, 0x3402) }, ++ { USB_DEVICE(0x13d3, 0x3408) }, ++ { USB_DEVICE(0x13d3, 0x3432) }, + + /* Atheros AR5BBU12 with sflash firmware */ + { USB_DEVICE(0x0489, 0xE02C) }, + + /* Atheros AR5BBU22 with sflash firmware */ +- { USB_DEVICE(0x0489, 0xE03C) }, + { USB_DEVICE(0x0489, 0xE036) }, ++ { USB_DEVICE(0x0489, 0xE03C) }, + + { } /* Terminating entry */ + }; +@@ -119,37 +127,45 @@ MODULE_DEVICE_TABLE(usb, ath3k_table); + static const struct usb_device_id ath3k_blist_tbl[] = { + + /* Atheros AR3012 with sflash firmware*/ +- { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x311F), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, + + /* Atheros AR5BBU22 with sflash firmware */ +- { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, + + { } /* Terminating entry */ + }; +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index e00c3f84a4cf..03b331798e16 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -49,6 +49,7 @@ static struct usb_driver btusb_driver; + #define BTUSB_WRONG_SCO_MTU 0x40 + #define BTUSB_ATH3012 0x80 + #define BTUSB_INTEL 0x100 ++#define BTUSB_INTEL_BOOT 0x200 + + static const struct usb_device_id btusb_table[] = { + /* Generic Bluetooth USB device */ +@@ -101,21 +102,31 @@ static const struct usb_device_id btusb_table[] = { + { USB_DEVICE(0x0c10, 0x0000) }, + + /* Broadcom BCM20702A0 */ ++ { USB_DEVICE(0x0489, 0xe042) }, ++ { USB_DEVICE(0x04ca, 0x2003) }, + { USB_DEVICE(0x0b05, 0x17b5) }, + { USB_DEVICE(0x0b05, 0x17cb) }, +- { USB_DEVICE(0x04ca, 0x2003) }, +- { USB_DEVICE(0x0489, 0xe042) }, + { USB_DEVICE(0x413c, 0x8197) }, + + /* Foxconn - Hon Hai */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) }, + +- /*Broadcom devices with vendor specific id */ ++ /* Broadcom devices with vendor specific id */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) }, + ++ /* ASUSTek Computer - Broadcom based */ ++ { USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01) }, ++ + /* Belkin F8065bf - Broadcom based */ + { USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) }, + ++ /* IMC Networks - Broadcom based */ ++ { USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) }, ++ ++ /* Intel Bluetooth USB Bootloader (RAM module) */ ++ { USB_DEVICE(0x8087, 0x0a5a), ++ .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC }, ++ + { } /* Terminating entry */ + }; + +@@ -129,56 +140,64 @@ static const struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE }, + + /* Atheros 3011 with sflash firmware */ ++ { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE }, ++ { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE }, ++ { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE }, +- { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE }, +- { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE }, +- { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE }, + + /* Atheros AR9285 Malbec with sflash firmware */ + { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, + + /* Atheros 3012 with sflash firmware */ +- { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, + + /* Atheros AR5BBU12 with sflash firmware */ + { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, + + /* Atheros AR5BBU12 with sflash firmware */ +- { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, + + /* Broadcom BCM2035 */ +- { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, +- { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, + { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 }, ++ { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, ++ { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, + + /* Broadcom BCM2045 */ + { USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU }, +@@ -1491,6 +1510,9 @@ static int btusb_probe(struct usb_interface *intf, + if (id->driver_info & BTUSB_INTEL) + hdev->setup = btusb_setup_intel; + ++ if (id->driver_info & BTUSB_INTEL_BOOT) ++ set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); ++ + /* Interface numbers are hardcoded in the specification */ + data->isoc = usb_ifnum_to_if(data->udev, 1); + +diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c +index 54e2abe671f7..c611bcc01f7e 100644 +--- a/drivers/edac/sb_edac.c ++++ b/drivers/edac/sb_edac.c +@@ -285,8 +285,9 @@ static const u32 correrrthrsld[] = { + * sbridge structs + */ + +-#define NUM_CHANNELS 4 +-#define MAX_DIMMS 3 /* Max DIMMS per channel */ ++#define NUM_CHANNELS 4 ++#define MAX_DIMMS 3 /* Max DIMMS per channel */ ++#define CHANNEL_UNSPECIFIED 0xf /* Intel IA32 SDM 15-14 */ + + enum type { + SANDY_BRIDGE, +@@ -1750,6 +1751,9 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, + + /* FIXME: need support for channel mask */ + ++ if (channel == CHANNEL_UNSPECIFIED) ++ channel = -1; ++ + /* Call the helper to output message */ + edac_mc_handle_error(tp_event, mci, core_err_cnt, + m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0, +diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c +index dcde56057fe1..3177498f3eab 100644 +--- a/drivers/net/bonding/bond_3ad.c ++++ b/drivers/net/bonding/bond_3ad.c +@@ -2479,7 +2479,7 @@ out: + return NETDEV_TX_OK; + err_free: + /* no suitable interface, frame not sent */ +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + goto out; + } + +diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c +index e8f133e926aa..c67bbc9c36dc 100644 +--- a/drivers/net/bonding/bond_alb.c ++++ b/drivers/net/bonding/bond_alb.c +@@ -1479,7 +1479,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) + } + + /* no suitable interface, frame not sent */ +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + out: + return NETDEV_TX_OK; + } +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 15379824d77d..32b0e7055b1e 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -3568,7 +3568,7 @@ static void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int sl + } + } + /* no slave that can tx has been found */ +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + } + + /** +@@ -3650,7 +3650,7 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d + if (slave) + bond_dev_queue_xmit(bond, skb, slave->dev); + else +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + + return NETDEV_TX_OK; + } +@@ -3698,7 +3698,7 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev) + if (slave && IS_UP(slave->dev) && slave->link == BOND_LINK_UP) + bond_dev_queue_xmit(bond, skb, slave->dev); + else +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + + return NETDEV_TX_OK; + } +@@ -3785,7 +3785,7 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev + pr_err("%s: Error: Unknown bonding mode %d\n", + dev->name, bond->params.mode); + WARN_ON_ONCE(1); +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + } +@@ -3806,7 +3806,7 @@ static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev) + if (bond_has_slaves(bond)) + ret = __bond_start_xmit(skb, dev); + else +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + rcu_read_unlock(); + + return ret; +diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c +index 6c9e1c9bdeb8..0c8a16866603 100644 +--- a/drivers/net/ethernet/broadcom/bnx2.c ++++ b/drivers/net/ethernet/broadcom/bnx2.c +@@ -2886,7 +2886,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) + sw_cons = BNX2_NEXT_TX_BD(sw_cons); + + tx_bytes += skb->len; +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + tx_pkt++; + if (tx_pkt == budget) + break; +@@ -6640,7 +6640,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) + + mapping = dma_map_single(&bp->pdev->dev, skb->data, len, PCI_DMA_TODEVICE); + if (dma_mapping_error(&bp->pdev->dev, mapping)) { +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +@@ -6733,7 +6733,7 @@ dma_error: + PCI_DMA_TODEVICE); + } + +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c +index 82061139b215..bc65dc85a622 100644 +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -6593,7 +6593,7 @@ static void tg3_tx(struct tg3_napi *tnapi) + pkts_compl++; + bytes_compl += skb->len; + +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + + if (unlikely(tx_bug)) { + tg3_tx_recover(tp); +@@ -6925,7 +6925,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) + if (len > (tp->dev->mtu + ETH_HLEN) && + skb->protocol != htons(ETH_P_8021Q) && + skb->protocol != htons(ETH_P_8021AD)) { +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + goto drop_it_no_recycle; + } + +@@ -7808,7 +7808,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, + PCI_DMA_TODEVICE); + /* Make sure the mapping succeeded */ + if (pci_dma_mapping_error(tp->pdev, new_addr)) { +- dev_kfree_skb(new_skb); ++ dev_kfree_skb_any(new_skb); + ret = -1; + } else { + u32 save_entry = *entry; +@@ -7823,13 +7823,13 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, + new_skb->len, base_flags, + mss, vlan)) { + tg3_tx_skb_unmap(tnapi, save_entry, -1); +- dev_kfree_skb(new_skb); ++ dev_kfree_skb_any(new_skb); + ret = -1; + } + } + } + +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + *pskb = new_skb; + return ret; + } +@@ -7872,7 +7872,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb) + } while (segs); + + tg3_tso_bug_end: +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + + return NETDEV_TX_OK; + } +@@ -8110,7 +8110,7 @@ dma_error: + tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, --i); + tnapi->tx_buffers[tnapi->tx_prod].skb = NULL; + drop: +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + drop_nofree: + tp->tx_dropped++; + return NETDEV_TX_OK; +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 80bfa0391913..075e7e7abea9 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -1883,7 +1883,7 @@ static u16 be_tx_compl_process(struct be_adapter *adapter, + queue_tail_inc(txq); + } while (cur_index != last_index); + +- kfree_skb(sent_skb); ++ dev_kfree_skb_any(sent_skb); + return num_wrbs; + } + +diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c +index ad5a5aadc7e1..70eb4d27b4fa 100644 +--- a/drivers/net/ethernet/freescale/gianfar.c ++++ b/drivers/net/ethernet/freescale/gianfar.c +@@ -2152,13 +2152,13 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) + skb_new = skb_realloc_headroom(skb, fcb_len); + if (!skb_new) { + dev->stats.tx_errors++; +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + if (skb->sk) + skb_set_owner_w(skb_new, skb->sk); +- consume_skb(skb); ++ dev_consume_skb_any(skb); + skb = skb_new; + } + +diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c +index 57e390cbe6d0..f42c201f727f 100644 +--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c ++++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c +@@ -1521,12 +1521,12 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) + int tso; + + if (test_bit(__IXGB_DOWN, &adapter->flags)) { +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + if (skb->len <= 0) { +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +@@ -1543,7 +1543,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) + + tso = ixgb_tso(adapter, skb); + if (tso < 0) { +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +index 2f83f3489fdb..8be0f3e1e8e9 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +@@ -2497,13 +2497,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, + netif_carrier_off(dev); + mlx4_en_set_default_moderation(priv); + +- err = register_netdev(dev); +- if (err) { +- en_err(priv, "Netdev registration failed for port %d\n", port); +- goto out; +- } +- priv->registered = 1; +- + en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num); + en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num); + +@@ -2543,6 +2536,14 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, + queue_delayed_work(mdev->workqueue, &priv->service_task, + SERVICE_TASK_DELAY); + ++ err = register_netdev(dev); ++ if (err) { ++ en_err(priv, "Netdev registration failed for port %d\n", port); ++ goto out; ++ } ++ ++ priv->registered = 1; ++ + return 0; + + out: +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c +index 13457032d15f..019a04a31384 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c +@@ -325,7 +325,7 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv, + } + } + } +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return tx_info->nr_txbb; + } + +diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c +index 737c1a881f78..a3c1daa7ad5c 100644 +--- a/drivers/net/ethernet/realtek/8139cp.c ++++ b/drivers/net/ethernet/realtek/8139cp.c +@@ -899,7 +899,7 @@ out_unlock: + + return NETDEV_TX_OK; + out_dma_error: +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + cp->dev->stats.tx_dropped++; + goto out_unlock; + } +diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c +index da5972eefdd2..8cb2f357026e 100644 +--- a/drivers/net/ethernet/realtek/8139too.c ++++ b/drivers/net/ethernet/realtek/8139too.c +@@ -1717,9 +1717,9 @@ static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, + if (len < ETH_ZLEN) + memset(tp->tx_buf[entry], 0, ETH_ZLEN); + skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + } else { +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } +diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c +index 3ff7bc3e7a23..90c14d16f261 100644 +--- a/drivers/net/ethernet/realtek/r8169.c ++++ b/drivers/net/ethernet/realtek/r8169.c +@@ -5834,7 +5834,7 @@ static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start, + tp->TxDescArray + entry); + if (skb) { + tp->dev->stats.tx_dropped++; +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + tx_skb->skb = NULL; + } + } +@@ -6059,7 +6059,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, + err_dma_1: + rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd); + err_dma_0: +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + err_update_stats: + dev->stats.tx_dropped++; + return NETDEV_TX_OK; +@@ -6142,7 +6142,7 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) + tp->tx_stats.packets++; + tp->tx_stats.bytes += tx_skb->skb->len; + u64_stats_update_end(&tp->tx_stats.syncp); +- dev_kfree_skb(tx_skb->skb); ++ dev_kfree_skb_any(tx_skb->skb); + tx_skb->skb = NULL; + } + dirty_tx++; +diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c +index cbd663ed030c..19405ed56cab 100644 +--- a/drivers/staging/lustre/lustre/llite/dcache.c ++++ b/drivers/staging/lustre/lustre/llite/dcache.c +@@ -278,7 +278,7 @@ void ll_invalidate_aliases(struct inode *inode) + inode->i_ino, inode->i_generation, inode); + + ll_lock_dcache(inode); +- ll_d_hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) { ++ ll_d_hlist_for_each_entry(dentry, p, &inode->i_dentry, d_u.d_alias) { + CDEBUG(D_DENTRY, "dentry in drop %.*s (%p) parent %p " + "inode %p flags %d\n", dentry->d_name.len, + dentry->d_name.name, dentry, dentry->d_parent, +diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c +index 6cfdb9e4b74b..5ae562ea95f7 100644 +--- a/drivers/staging/lustre/lustre/llite/llite_lib.c ++++ b/drivers/staging/lustre/lustre/llite/llite_lib.c +@@ -678,7 +678,7 @@ void lustre_dump_dentry(struct dentry *dentry, int recur) + return; + + list_for_each(tmp, &dentry->d_subdirs) { +- struct dentry *d = list_entry(tmp, struct dentry, d_u.d_child); ++ struct dentry *d = list_entry(tmp, struct dentry, d_child); + lustre_dump_dentry(d, recur - 1); + } + } +diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c +index fc8d264f6c9a..8e9a9e95b5cc 100644 +--- a/drivers/staging/lustre/lustre/llite/namei.c ++++ b/drivers/staging/lustre/lustre/llite/namei.c +@@ -175,14 +175,14 @@ static void ll_invalidate_negative_children(struct inode *dir) + struct ll_d_hlist_node *p; + + ll_lock_dcache(dir); +- ll_d_hlist_for_each_entry(dentry, p, &dir->i_dentry, d_alias) { ++ ll_d_hlist_for_each_entry(dentry, p, &dir->i_dentry, d_u.d_alias) { + spin_lock(&dentry->d_lock); + if (!list_empty(&dentry->d_subdirs)) { + struct dentry *child; + + list_for_each_entry_safe(child, tmp_subdir, + &dentry->d_subdirs, +- d_u.d_child) { ++ d_child) { + if (child->d_inode == NULL) + d_lustre_invalidate(child, 1); + } +@@ -364,7 +364,7 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *dentry) + discon_alias = invalid_alias = NULL; + + ll_lock_dcache(inode); +- ll_d_hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) { ++ ll_d_hlist_for_each_entry(alias, p, &inode->i_dentry, d_u.d_alias) { + LASSERT(alias != dentry); + + spin_lock(&alias->d_lock); +@@ -953,7 +953,7 @@ static void ll_get_child_fid(struct inode * dir, struct qstr *name, + { + struct dentry *parent, *child; + +- parent = ll_d_hlist_entry(dir->i_dentry, struct dentry, d_alias); ++ parent = ll_d_hlist_entry(dir->i_dentry, struct dentry, d_u.d_alias); + child = d_lookup(parent, name); + if (child) { + if (child->d_inode) +diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c +index 93cbfbb7e7f7..6096771e2400 100644 +--- a/drivers/staging/lustre/lustre/llite/vvp_io.c ++++ b/drivers/staging/lustre/lustre/llite/vvp_io.c +@@ -642,7 +642,7 @@ static int vvp_io_kernel_fault(struct vvp_fault_io *cfio) + return 0; + } + +- if (cfio->fault.ft_flags & VM_FAULT_SIGBUS) { ++ if (cfio->fault.ft_flags & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) { + CDEBUG(D_PAGE, "got addr %p - SIGBUS\n", vmf->virtual_address); + return -EFAULT; + } +diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c +index d9a43674cb94..9cca0ea4e479 100644 +--- a/fs/affs/amigaffs.c ++++ b/fs/affs/amigaffs.c +@@ -126,7 +126,7 @@ affs_fix_dcache(struct inode *inode, u32 entry_ino) + { + struct dentry *dentry; + spin_lock(&inode->i_lock); +- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) { + if (entry_ino == (u32)(long)dentry->d_fsdata) { + dentry->d_fsdata = (void *)inode->i_ino; + break; +diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c +index 394e90b02c5e..edb46e67d5ca 100644 +--- a/fs/autofs4/expire.c ++++ b/fs/autofs4/expire.c +@@ -91,7 +91,7 @@ static struct dentry *get_next_positive_subdir(struct dentry *prev, + spin_lock(&root->d_lock); + + if (prev) +- next = prev->d_u.d_child.next; ++ next = prev->d_child.next; + else { + prev = dget_dlock(root); + next = prev->d_subdirs.next; +@@ -105,13 +105,13 @@ cont: + return NULL; + } + +- q = list_entry(next, struct dentry, d_u.d_child); ++ q = list_entry(next, struct dentry, d_child); + + spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED); + /* Already gone or negative dentry (under construction) - try next */ + if (!d_count(q) || !simple_positive(q)) { + spin_unlock(&q->d_lock); +- next = q->d_u.d_child.next; ++ next = q->d_child.next; + goto cont; + } + dget_dlock(q); +@@ -161,13 +161,13 @@ again: + goto relock; + } + spin_unlock(&p->d_lock); +- next = p->d_u.d_child.next; ++ next = p->d_child.next; + p = parent; + if (next != &parent->d_subdirs) + break; + } + } +- ret = list_entry(next, struct dentry, d_u.d_child); ++ ret = list_entry(next, struct dentry, d_child); + + spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED); + /* Negative dentry - try next */ +@@ -461,7 +461,7 @@ found: + spin_lock(&sbi->lookup_lock); + spin_lock(&expired->d_parent->d_lock); + spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED); +- list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child); ++ list_move(&expired->d_parent->d_subdirs, &expired->d_child); + spin_unlock(&expired->d_lock); + spin_unlock(&expired->d_parent->d_lock); + spin_unlock(&sbi->lookup_lock); +diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c +index cc87c1abac97..9e016e6fb582 100644 +--- a/fs/autofs4/root.c ++++ b/fs/autofs4/root.c +@@ -655,7 +655,7 @@ static void autofs_clear_leaf_automount_flags(struct dentry *dentry) + /* only consider parents below dentrys in the root */ + if (IS_ROOT(parent->d_parent)) + return; +- d_child = &dentry->d_u.d_child; ++ d_child = &dentry->d_child; + /* Set parent managed if it's becoming empty */ + if (d_child->next == &parent->d_subdirs && + d_child->prev == &parent->d_subdirs) +diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c +index 5e0982aa7000..18e14cf8f223 100644 +--- a/fs/ceph/dir.c ++++ b/fs/ceph/dir.c +@@ -111,7 +111,7 @@ static int fpos_cmp(loff_t l, loff_t r) + /* + * When possible, we try to satisfy a readdir by peeking at the + * dcache. We make this work by carefully ordering dentries on +- * d_u.d_child when we initially get results back from the MDS, and ++ * d_child when we initially get results back from the MDS, and + * falling back to a "normal" sync readdir if any dentries in the dir + * are dropped. + * +@@ -146,11 +146,11 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx) + p = parent->d_subdirs.prev; + dout(" initial p %p/%p\n", p->prev, p->next); + } else { +- p = last->d_u.d_child.prev; ++ p = last->d_child.prev; + } + + more: +- dentry = list_entry(p, struct dentry, d_u.d_child); ++ dentry = list_entry(p, struct dentry, d_child); + di = ceph_dentry(dentry); + while (1) { + dout(" p %p/%p %s d_subdirs %p/%p\n", p->prev, p->next, +@@ -172,7 +172,7 @@ more: + !dentry->d_inode ? " null" : ""); + spin_unlock(&dentry->d_lock); + p = p->prev; +- dentry = list_entry(p, struct dentry, d_u.d_child); ++ dentry = list_entry(p, struct dentry, d_child); + di = ceph_dentry(dentry); + } + +diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c +index 6471f9c83428..ee24490ee925 100644 +--- a/fs/ceph/inode.c ++++ b/fs/ceph/inode.c +@@ -1289,7 +1289,7 @@ retry_lookup: + /* reorder parent's d_subdirs */ + spin_lock(&parent->d_lock); + spin_lock_nested(&dn->d_lock, DENTRY_D_LOCK_NESTED); +- list_move(&dn->d_u.d_child, &parent->d_subdirs); ++ list_move(&dn->d_child, &parent->d_subdirs); + spin_unlock(&dn->d_lock); + spin_unlock(&parent->d_lock); + } +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index f2ddcf7ac9c3..7ee427e16f3b 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -883,7 +883,7 @@ inode_has_hashed_dentries(struct inode *inode) + struct dentry *dentry; + + spin_lock(&inode->i_lock); +- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) { + if (!d_unhashed(dentry) || IS_ROOT(dentry)) { + spin_unlock(&inode->i_lock); + return true; +diff --git a/fs/coda/cache.c b/fs/coda/cache.c +index 1da168c61d35..9bc1147a6c5d 100644 +--- a/fs/coda/cache.c ++++ b/fs/coda/cache.c +@@ -92,7 +92,7 @@ static void coda_flag_children(struct dentry *parent, int flag) + struct dentry *de; + + spin_lock(&parent->d_lock); +- list_for_each_entry(de, &parent->d_subdirs, d_u.d_child) { ++ list_for_each_entry(de, &parent->d_subdirs, d_child) { + /* don't know what to do with negative dentries */ + if (de->d_inode ) + coda_flag_inode(de->d_inode, flag); +diff --git a/fs/dcache.c b/fs/dcache.c +index 436612777203..c345f5f2b508 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -44,7 +44,7 @@ + /* + * Usage: + * dcache->d_inode->i_lock protects: +- * - i_dentry, d_alias, d_inode of aliases ++ * - i_dentry, d_u.d_alias, d_inode of aliases + * dcache_hash_bucket lock protects: + * - the dcache hash table + * s_anon bl list spinlock protects: +@@ -59,7 +59,7 @@ + * - d_unhashed() + * - d_parent and d_subdirs + * - childrens' d_child and d_parent +- * - d_alias, d_inode ++ * - d_u.d_alias, d_inode + * + * Ordering: + * dentry->d_inode->i_lock +@@ -239,7 +239,6 @@ static void __d_free(struct rcu_head *head) + { + struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu); + +- WARN_ON(!hlist_unhashed(&dentry->d_alias)); + if (dname_external(dentry)) + kfree(dentry->d_name.name); + kmem_cache_free(dentry_cache, dentry); +@@ -250,6 +249,7 @@ static void __d_free(struct rcu_head *head) + */ + static void d_free(struct dentry *dentry) + { ++ WARN_ON(!hlist_unhashed(&dentry->d_u.d_alias)); + BUG_ON((int)dentry->d_lockref.count > 0); + this_cpu_dec(nr_dentry); + if (dentry->d_op && dentry->d_op->d_release) +@@ -288,7 +288,7 @@ static void dentry_iput(struct dentry * dentry) + struct inode *inode = dentry->d_inode; + if (inode) { + dentry->d_inode = NULL; +- hlist_del_init(&dentry->d_alias); ++ hlist_del_init(&dentry->d_u.d_alias); + spin_unlock(&dentry->d_lock); + spin_unlock(&inode->i_lock); + if (!inode->i_nlink) +@@ -313,7 +313,7 @@ static void dentry_unlink_inode(struct dentry * dentry) + struct inode *inode = dentry->d_inode; + __d_clear_type(dentry); + dentry->d_inode = NULL; +- hlist_del_init(&dentry->d_alias); ++ hlist_del_init(&dentry->d_u.d_alias); + dentry_rcuwalk_barrier(dentry); + spin_unlock(&dentry->d_lock); + spin_unlock(&inode->i_lock); +@@ -435,7 +435,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) + __releases(parent->d_lock) + __releases(dentry->d_inode->i_lock) + { +- list_del(&dentry->d_u.d_child); ++ list_del(&dentry->d_child); + /* + * Inform d_walk() that we are no longer attached to the + * dentry tree +@@ -737,7 +737,7 @@ static struct dentry *__d_find_alias(struct inode *inode, int want_discon) + + again: + discon_alias = NULL; +- hlist_for_each_entry(alias, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) { + spin_lock(&alias->d_lock); + if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) { + if (IS_ROOT(alias) && +@@ -790,7 +790,7 @@ void d_prune_aliases(struct inode *inode) + struct dentry *dentry; + restart: + spin_lock(&inode->i_lock); +- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) { + spin_lock(&dentry->d_lock); + if (!dentry->d_lockref.count) { + /* +@@ -1091,7 +1091,7 @@ repeat: + resume: + while (next != &this_parent->d_subdirs) { + struct list_head *tmp = next; +- struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child); ++ struct dentry *dentry = list_entry(tmp, struct dentry, d_child); + next = tmp->next; + + spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); +@@ -1143,7 +1143,7 @@ resume: + goto rename_retry; + } + rcu_read_unlock(); +- next = child->d_u.d_child.next; ++ next = child->d_child.next; + goto resume; + } + if (need_seqretry(&rename_lock, seq)) { +@@ -1524,8 +1524,8 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name) + INIT_HLIST_BL_NODE(&dentry->d_hash); + INIT_LIST_HEAD(&dentry->d_lru); + INIT_LIST_HEAD(&dentry->d_subdirs); +- INIT_HLIST_NODE(&dentry->d_alias); +- INIT_LIST_HEAD(&dentry->d_u.d_child); ++ INIT_HLIST_NODE(&dentry->d_u.d_alias); ++ INIT_LIST_HEAD(&dentry->d_child); + d_set_d_op(dentry, dentry->d_sb->s_d_op); + + this_cpu_inc(nr_dentry); +@@ -1555,7 +1555,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) + */ + __dget_dlock(parent); + dentry->d_parent = parent; +- list_add(&dentry->d_u.d_child, &parent->d_subdirs); ++ list_add(&dentry->d_child, &parent->d_subdirs); + spin_unlock(&parent->d_lock); + + return dentry; +@@ -1648,7 +1648,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode) + spin_lock(&dentry->d_lock); + __d_set_type(dentry, add_flags); + if (inode) +- hlist_add_head(&dentry->d_alias, &inode->i_dentry); ++ hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry); + dentry->d_inode = inode; + dentry_rcuwalk_barrier(dentry); + spin_unlock(&dentry->d_lock); +@@ -1672,7 +1672,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode) + + void d_instantiate(struct dentry *entry, struct inode * inode) + { +- BUG_ON(!hlist_unhashed(&entry->d_alias)); ++ BUG_ON(!hlist_unhashed(&entry->d_u.d_alias)); + if (inode) + spin_lock(&inode->i_lock); + __d_instantiate(entry, inode); +@@ -1711,7 +1711,7 @@ static struct dentry *__d_instantiate_unique(struct dentry *entry, + return NULL; + } + +- hlist_for_each_entry(alias, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) { + /* + * Don't need alias->d_lock here, because aliases with + * d_parent == entry->d_parent are not subject to name or +@@ -1737,7 +1737,7 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode) + { + struct dentry *result; + +- BUG_ON(!hlist_unhashed(&entry->d_alias)); ++ BUG_ON(!hlist_unhashed(&entry->d_u.d_alias)); + + if (inode) + spin_lock(&inode->i_lock); +@@ -1768,7 +1768,7 @@ EXPORT_SYMBOL(d_instantiate_unique); + */ + int d_instantiate_no_diralias(struct dentry *entry, struct inode *inode) + { +- BUG_ON(!hlist_unhashed(&entry->d_alias)); ++ BUG_ON(!hlist_unhashed(&entry->d_u.d_alias)); + + spin_lock(&inode->i_lock); + if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry)) { +@@ -1807,7 +1807,7 @@ static struct dentry * __d_find_any_alias(struct inode *inode) + + if (hlist_empty(&inode->i_dentry)) + return NULL; +- alias = hlist_entry(inode->i_dentry.first, struct dentry, d_alias); ++ alias = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias); + __dget(alias); + return alias; + } +@@ -1884,7 +1884,7 @@ struct dentry *d_obtain_alias(struct inode *inode) + spin_lock(&tmp->d_lock); + tmp->d_inode = inode; + tmp->d_flags |= add_flags; +- hlist_add_head(&tmp->d_alias, &inode->i_dentry); ++ hlist_add_head(&tmp->d_u.d_alias, &inode->i_dentry); + hlist_bl_lock(&tmp->d_sb->s_anon); + hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); + hlist_bl_unlock(&tmp->d_sb->s_anon); +@@ -2327,7 +2327,7 @@ int d_validate(struct dentry *dentry, struct dentry *dparent) + struct dentry *child; + + spin_lock(&dparent->d_lock); +- list_for_each_entry(child, &dparent->d_subdirs, d_u.d_child) { ++ list_for_each_entry(child, &dparent->d_subdirs, d_child) { + if (dentry == child) { + spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); + __dget_dlock(dentry); +@@ -2574,8 +2574,8 @@ static void __d_move(struct dentry * dentry, struct dentry * target) + /* Unhash the target: dput() will then get rid of it */ + __d_drop(target); + +- list_del(&dentry->d_u.d_child); +- list_del(&target->d_u.d_child); ++ list_del(&dentry->d_child); ++ list_del(&target->d_child); + + /* Switch the names.. */ + switch_names(dentry, target); +@@ -2585,15 +2585,15 @@ static void __d_move(struct dentry * dentry, struct dentry * target) + if (IS_ROOT(dentry)) { + dentry->d_parent = target->d_parent; + target->d_parent = target; +- INIT_LIST_HEAD(&target->d_u.d_child); ++ INIT_LIST_HEAD(&target->d_child); + } else { + swap(dentry->d_parent, target->d_parent); + + /* And add them back to the (new) parent lists */ +- list_add(&target->d_u.d_child, &target->d_parent->d_subdirs); ++ list_add(&target->d_child, &target->d_parent->d_subdirs); + } + +- list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs); ++ list_add(&dentry->d_child, &dentry->d_parent->d_subdirs); + + write_seqcount_end(&target->d_seq); + write_seqcount_end(&dentry->d_seq); +@@ -2700,9 +2700,9 @@ static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon) + swap(dentry->d_name.hash, anon->d_name.hash); + + dentry->d_parent = dentry; +- list_del_init(&dentry->d_u.d_child); ++ list_del_init(&dentry->d_child); + anon->d_parent = dparent; +- list_move(&anon->d_u.d_child, &dparent->d_subdirs); ++ list_move(&anon->d_child, &dparent->d_subdirs); + + write_seqcount_end(&dentry->d_seq); + write_seqcount_end(&anon->d_seq); +@@ -3333,7 +3333,7 @@ void d_tmpfile(struct dentry *dentry, struct inode *inode) + { + inode_dec_link_count(inode); + BUG_ON(dentry->d_name.name != dentry->d_iname || +- !hlist_unhashed(&dentry->d_alias) || ++ !hlist_unhashed(&dentry->d_u.d_alias) || + !d_unlinked(dentry)); + spin_lock(&dentry->d_parent->d_lock); + spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); +diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c +index 1ff8fe5dab0d..4a9f0e0c6644 100644 +--- a/fs/debugfs/inode.c ++++ b/fs/debugfs/inode.c +@@ -552,7 +552,7 @@ void debugfs_remove_recursive(struct dentry *dentry) + * use the d_u.d_child as the rcu head and corrupt this list. + */ + spin_lock(&parent->d_lock); +- list_for_each_entry(child, &parent->d_subdirs, d_u.d_child) { ++ list_for_each_entry(child, &parent->d_subdirs, d_child) { + if (!debugfs_positive(child)) + continue; + +diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c +index 48a359dd286e..831d4f057e15 100644 +--- a/fs/exportfs/expfs.c ++++ b/fs/exportfs/expfs.c +@@ -50,7 +50,7 @@ find_acceptable_alias(struct dentry *result, + + inode = result->d_inode; + spin_lock(&inode->i_lock); +- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) { + dget(dentry); + spin_unlock(&inode->i_lock); + if (toput) +diff --git a/fs/libfs.c b/fs/libfs.c +index a1844244246f..868c0b70a30e 100644 +--- a/fs/libfs.c ++++ b/fs/libfs.c +@@ -113,18 +113,18 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence) + + spin_lock(&dentry->d_lock); + /* d_lock not required for cursor */ +- list_del(&cursor->d_u.d_child); ++ list_del(&cursor->d_child); + p = dentry->d_subdirs.next; + while (n && p != &dentry->d_subdirs) { + struct dentry *next; +- next = list_entry(p, struct dentry, d_u.d_child); ++ next = list_entry(p, struct dentry, d_child); + spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED); + if (simple_positive(next)) + n--; + spin_unlock(&next->d_lock); + p = p->next; + } +- list_add_tail(&cursor->d_u.d_child, p); ++ list_add_tail(&cursor->d_child, p); + spin_unlock(&dentry->d_lock); + } + } +@@ -149,7 +149,7 @@ int dcache_readdir(struct file *file, struct dir_context *ctx) + { + struct dentry *dentry = file->f_path.dentry; + struct dentry *cursor = file->private_data; +- struct list_head *p, *q = &cursor->d_u.d_child; ++ struct list_head *p, *q = &cursor->d_child; + + if (!dir_emit_dots(file, ctx)) + return 0; +@@ -158,7 +158,7 @@ int dcache_readdir(struct file *file, struct dir_context *ctx) + list_move(q, &dentry->d_subdirs); + + for (p = q->next; p != &dentry->d_subdirs; p = p->next) { +- struct dentry *next = list_entry(p, struct dentry, d_u.d_child); ++ struct dentry *next = list_entry(p, struct dentry, d_child); + spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED); + if (!simple_positive(next)) { + spin_unlock(&next->d_lock); +@@ -286,7 +286,7 @@ int simple_empty(struct dentry *dentry) + int ret = 0; + + spin_lock(&dentry->d_lock); +- list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) { ++ list_for_each_entry(child, &dentry->d_subdirs, d_child) { + spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED); + if (simple_positive(child)) { + spin_unlock(&child->d_lock); +diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c +index c320ac52353e..dc9747d6a4d0 100644 +--- a/fs/ncpfs/dir.c ++++ b/fs/ncpfs/dir.c +@@ -406,7 +406,7 @@ ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos) + spin_lock(&parent->d_lock); + next = parent->d_subdirs.next; + while (next != &parent->d_subdirs) { +- dent = list_entry(next, struct dentry, d_u.d_child); ++ dent = list_entry(next, struct dentry, d_child); + if ((unsigned long)dent->d_fsdata == fpos) { + if (dent->d_inode) + dget(dent); +diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h +index 32c06587351a..6d5e7c56c79d 100644 +--- a/fs/ncpfs/ncplib_kernel.h ++++ b/fs/ncpfs/ncplib_kernel.h +@@ -194,7 +194,7 @@ ncp_renew_dentries(struct dentry *parent) + spin_lock(&parent->d_lock); + next = parent->d_subdirs.next; + while (next != &parent->d_subdirs) { +- dentry = list_entry(next, struct dentry, d_u.d_child); ++ dentry = list_entry(next, struct dentry, d_child); + + if (dentry->d_fsdata == NULL) + ncp_age_dentry(server, dentry); +@@ -216,7 +216,7 @@ ncp_invalidate_dircache_entries(struct dentry *parent) + spin_lock(&parent->d_lock); + next = parent->d_subdirs.next; + while (next != &parent->d_subdirs) { +- dentry = list_entry(next, struct dentry, d_u.d_child); ++ dentry = list_entry(next, struct dentry, d_child); + dentry->d_fsdata = NULL; + ncp_age_dentry(server, dentry); + next = next->next; +diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c +index 66984a9aafaa..5b8ab0e444f9 100644 +--- a/fs/nfs/getroot.c ++++ b/fs/nfs/getroot.c +@@ -58,7 +58,7 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i + */ + spin_lock(&sb->s_root->d_inode->i_lock); + spin_lock(&sb->s_root->d_lock); +- hlist_del_init(&sb->s_root->d_alias); ++ hlist_del_init(&sb->s_root->d_u.d_alias); + spin_unlock(&sb->s_root->d_lock); + spin_unlock(&sb->s_root->d_inode->i_lock); + } +diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c +index 9d3e9c50066a..700129940c6e 100644 +--- a/fs/notify/fsnotify.c ++++ b/fs/notify/fsnotify.c +@@ -63,14 +63,14 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) + spin_lock(&inode->i_lock); + /* run all of the dentries associated with this inode. Since this is a + * directory, there damn well better only be one item on this list */ +- hlist_for_each_entry(alias, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) { + struct dentry *child; + + /* run all of the children of the original inode and fix their + * d_flags to indicate parental interest (their parent is the + * original inode) */ + spin_lock(&alias->d_lock); +- list_for_each_entry(child, &alias->d_subdirs, d_u.d_child) { ++ list_for_each_entry(child, &alias->d_subdirs, d_child) { + if (!child->d_inode) + continue; + +diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c +index 0d3a97d2d5f6..116748502bae 100644 +--- a/fs/ocfs2/dcache.c ++++ b/fs/ocfs2/dcache.c +@@ -173,7 +173,7 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode, + struct dentry *dentry; + + spin_lock(&inode->i_lock); +- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) { + spin_lock(&dentry->d_lock); + if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) { + trace_ocfs2_find_local_alias(dentry->d_name.len, +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index c2546717fc2b..eaa7374305a3 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -993,9 +993,8 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, + struct vm_area_struct *vma; + struct pagemapread *pm = walk->private; + spinlock_t *ptl; +- pte_t *pte; ++ pte_t *pte, *orig_pte; + int err = 0; +- pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2)); + + /* find the first VMA at or above 'addr' */ + vma = find_vma(walk->mm, addr); +@@ -1009,6 +1008,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, + + for (; addr != end; addr += PAGE_SIZE) { + unsigned long offset; ++ pagemap_entry_t pme; + + offset = (addr & ~PAGEMAP_WALK_MASK) >> + PAGE_SHIFT; +@@ -1023,32 +1023,55 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, + + if (pmd_trans_unstable(pmd)) + return 0; +- for (; addr != end; addr += PAGE_SIZE) { +- int flags2; +- +- /* check to see if we've left 'vma' behind +- * and need a new, higher one */ +- if (vma && (addr >= vma->vm_end)) { +- vma = find_vma(walk->mm, addr); +- if (vma && (vma->vm_flags & VM_SOFTDIRTY)) +- flags2 = __PM_SOFT_DIRTY; +- else +- flags2 = 0; +- pme = make_pme(PM_NOT_PRESENT(pm->v2) | PM_STATUS2(pm->v2, flags2)); ++ ++ while (1) { ++ /* End of address space hole, which we mark as non-present. */ ++ unsigned long hole_end; ++ ++ if (vma) ++ hole_end = min(end, vma->vm_start); ++ else ++ hole_end = end; ++ ++ for (; addr < hole_end; addr += PAGE_SIZE) { ++ pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2)); ++ ++ err = add_to_pagemap(addr, &pme, pm); ++ if (err) ++ return err; + } + +- /* check that 'vma' actually covers this address, +- * and that it isn't a huge page vma */ +- if (vma && (vma->vm_start <= addr) && +- !is_vm_hugetlb_page(vma)) { +- pte = pte_offset_map(pmd, addr); ++ if (!vma || vma->vm_start >= end) ++ break; ++ /* ++ * We can't possibly be in a hugetlb VMA. In general, ++ * for a mm_walk with a pmd_entry and a hugetlb_entry, ++ * the pmd_entry can only be called on addresses in a ++ * hugetlb if the walk starts in a non-hugetlb VMA and ++ * spans a hugepage VMA. Since pagemap_read walks are ++ * PMD-sized and PMD-aligned, this will never be true. ++ */ ++ BUG_ON(is_vm_hugetlb_page(vma)); ++ ++ /* Addresses in the VMA. */ ++ orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); ++ for (; addr < min(end, vma->vm_end); pte++, addr += PAGE_SIZE) { ++ pagemap_entry_t pme; ++ + pte_to_pagemap_entry(&pme, pm, vma, addr, *pte); +- /* unmap before userspace copy */ +- pte_unmap(pte); ++ err = add_to_pagemap(addr, &pme, pm); ++ if (err) ++ break; + } +- err = add_to_pagemap(addr, &pme, pm); ++ pte_unmap_unlock(orig_pte, ptl); ++ + if (err) + return err; ++ ++ if (addr == end) ++ break; ++ ++ vma = find_vma(walk->mm, addr); + } + + cond_resched(); +diff --git a/include/linux/dcache.h b/include/linux/dcache.h +index 3b50cac7ccb3..0f0eb1c1e676 100644 +--- a/include/linux/dcache.h ++++ b/include/linux/dcache.h +@@ -124,15 +124,15 @@ struct dentry { + void *d_fsdata; /* fs-specific data */ + + struct list_head d_lru; /* LRU list */ ++ struct list_head d_child; /* child of parent list */ ++ struct list_head d_subdirs; /* our children */ + /* +- * d_child and d_rcu can share memory ++ * d_alias and d_rcu can share memory + */ + union { +- struct list_head d_child; /* child of parent list */ ++ struct hlist_node d_alias; /* inode alias list */ + struct rcu_head d_rcu; + } d_u; +- struct list_head d_subdirs; /* our children */ +- struct hlist_node d_alias; /* inode alias list */ + }; + + /* +diff --git a/include/linux/mm.h b/include/linux/mm.h +index 46b8ab56b9db..a7b311dfa742 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1009,6 +1009,7 @@ static inline int page_mapped(struct page *page) + #define VM_FAULT_WRITE 0x0008 /* Special case for get_user_pages */ + #define VM_FAULT_HWPOISON 0x0010 /* Hit poisoned small page */ + #define VM_FAULT_HWPOISON_LARGE 0x0020 /* Hit poisoned large page. Index encoded in upper bits */ ++#define VM_FAULT_SIGSEGV 0x0040 + + #define VM_FAULT_NOPAGE 0x0100 /* ->fault installed the pte, not return page */ + #define VM_FAULT_LOCKED 0x0200 /* ->fault locked the returned page */ +@@ -1017,8 +1018,9 @@ static inline int page_mapped(struct page *page) + + #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */ + +-#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | \ +- VM_FAULT_FALLBACK | VM_FAULT_HWPOISON_LARGE) ++#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \ ++ VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \ ++ VM_FAULT_FALLBACK) + + /* Encode hstate index for a hwpoisoned large page */ + #define VM_FAULT_SET_HINDEX(x) ((x) << 12) +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index 911718fa92ed..bf46cc813451 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1880,6 +1880,12 @@ void netdev_freemem(struct net_device *dev); + void synchronize_net(void); + int init_dummy_netdev(struct net_device *dev); + ++DECLARE_PER_CPU(int, xmit_recursion); ++static inline int dev_recursion_level(void) ++{ ++ return this_cpu_read(xmit_recursion); ++} ++ + struct net_device *dev_get_by_index(struct net *net, int ifindex); + struct net_device *__dev_get_by_index(struct net *net, int ifindex); + struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex); +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 218b058060f1..91fe6a38b307 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -1695,7 +1695,7 @@ static inline pid_t task_tgid_vnr(struct task_struct *tsk) + } + + +-static int pid_alive(const struct task_struct *p); ++static inline int pid_alive(const struct task_struct *p); + static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns) + { + pid_t pid = 0; +diff --git a/include/net/ip.h b/include/net/ip.h +index 3446cdd29608..5128fa7a8302 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -407,22 +407,6 @@ static __inline__ void inet_reset_saddr(struct sock *sk) + + #endif + +-static inline int sk_mc_loop(struct sock *sk) +-{ +- if (!sk) +- return 1; +- switch (sk->sk_family) { +- case AF_INET: +- return inet_sk(sk)->mc_loop; +-#if IS_ENABLED(CONFIG_IPV6) +- case AF_INET6: +- return inet6_sk(sk)->mc_loop; +-#endif +- } +- WARN_ON(1); +- return 1; +-} +- + bool ip_call_ra_chain(struct sk_buff *skb); + + /* +diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h +index 2e74c6cfa612..ee2d53ae62fe 100644 +--- a/include/net/ip6_route.h ++++ b/include/net/ip6_route.h +@@ -168,7 +168,8 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); + + static inline int ip6_skb_dst_mtu(struct sk_buff *skb) + { +- struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; ++ struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ? ++ inet6_sk(skb->sk) : NULL; + + return (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) ? + skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); +diff --git a/include/net/sock.h b/include/net/sock.h +index f66b2b19a6e4..0c79a740e97d 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -1815,6 +1815,8 @@ struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie); + + struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie); + ++bool sk_mc_loop(struct sock *sk); ++ + static inline bool sk_can_gso(const struct sock *sk) + { + return net_gso_ok(sk->sk_route_caps, sk->sk_gso_type); +diff --git a/kernel/cgroup.c b/kernel/cgroup.c +index 550e2050d778..18711f326260 100644 +--- a/kernel/cgroup.c ++++ b/kernel/cgroup.c +@@ -971,7 +971,7 @@ static void cgroup_d_remove_dir(struct dentry *dentry) + parent = dentry->d_parent; + spin_lock(&parent->d_lock); + spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); +- list_del_init(&dentry->d_u.d_child); ++ list_del_init(&dentry->d_child); + spin_unlock(&dentry->d_lock); + spin_unlock(&parent->d_lock); + remove_dir(dentry); +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index 813b021379f5..a2d62b3b90c7 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -6158,7 +6158,7 @@ static int instance_mkdir (struct inode *inode, struct dentry *dentry, umode_t m + int ret; + + /* Paranoid: Make sure the parent is the "instances" directory */ +- parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias); ++ parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias); + if (WARN_ON_ONCE(parent != trace_instance_dir)) + return -ENOENT; + +@@ -6185,7 +6185,7 @@ static int instance_rmdir(struct inode *inode, struct dentry *dentry) + int ret; + + /* Paranoid: Make sure the parent is the "instances" directory */ +- parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias); ++ parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias); + if (WARN_ON_ONCE(parent != trace_instance_dir)) + return -ENOENT; + +diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c +index e4c4efc4ba0d..c6646a58d23e 100644 +--- a/kernel/trace/trace_events.c ++++ b/kernel/trace/trace_events.c +@@ -428,7 +428,7 @@ static void remove_event_file_dir(struct ftrace_event_file *file) + + if (dir) { + spin_lock(&dir->d_lock); /* probably unneeded */ +- list_for_each_entry(child, &dir->d_subdirs, d_u.d_child) { ++ list_for_each_entry(child, &dir->d_subdirs, d_child) { + if (child->d_inode) /* probably unneeded */ + child->d_inode->i_private = NULL; + } +diff --git a/mm/ksm.c b/mm/ksm.c +index 68710e80994a..5e706e391a02 100644 +--- a/mm/ksm.c ++++ b/mm/ksm.c +@@ -376,7 +376,7 @@ static int break_ksm(struct vm_area_struct *vma, unsigned long addr) + else + ret = VM_FAULT_WRITE; + put_page(page); +- } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_OOM))); ++ } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | VM_FAULT_OOM))); + /* + * We must loop because handle_mm_fault() may back out if there's + * any difficulty e.g. if pte accessed bit gets updated concurrently. +diff --git a/mm/memory-failure.c b/mm/memory-failure.c +index a98c7fce470a..ffc7bf0458fb 100644 +--- a/mm/memory-failure.c ++++ b/mm/memory-failure.c +@@ -1645,8 +1645,6 @@ static int __soft_offline_page(struct page *page, int flags) + * setting PG_hwpoison. + */ + if (!is_free_buddy_page(page)) +- lru_add_drain_all(); +- if (!is_free_buddy_page(page)) + drain_all_pages(); + SetPageHWPoison(page); + if (!is_free_buddy_page(page)) +diff --git a/mm/memory.c b/mm/memory.c +index 102af096cbc5..749e1c68d490 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -1836,7 +1836,8 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, + else + return -EFAULT; + } +- if (ret & VM_FAULT_SIGBUS) ++ if (ret & (VM_FAULT_SIGBUS | ++ VM_FAULT_SIGSEGV)) + return i ? i : -EFAULT; + BUG(); + } +@@ -1946,7 +1947,7 @@ int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm, + return -ENOMEM; + if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE)) + return -EHWPOISON; +- if (ret & VM_FAULT_SIGBUS) ++ if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) + return -EFAULT; + BUG(); + } +@@ -3235,7 +3236,7 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, + + /* Check if we need to add a guard page to the stack */ + if (check_stack_guard_page(vma, address) < 0) +- return VM_FAULT_SIGBUS; ++ return VM_FAULT_SIGSEGV; + + /* Use the zero-page for reads */ + if (!(flags & FAULT_FLAG_WRITE)) { +diff --git a/net/core/dev.c b/net/core/dev.c +index f6d8d7fe29ab..73abbd77d72c 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -2775,7 +2775,9 @@ static void skb_update_prio(struct sk_buff *skb) + #define skb_update_prio(skb) + #endif + +-static DEFINE_PER_CPU(int, xmit_recursion); ++DEFINE_PER_CPU(int, xmit_recursion); ++EXPORT_SYMBOL(xmit_recursion); ++ + #define RECURSION_LIMIT 10 + + /** +diff --git a/net/core/sock.c b/net/core/sock.c +index c8069561bdb7..650dd58ebd05 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -659,6 +659,25 @@ static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool) + sock_reset_flag(sk, bit); + } + ++bool sk_mc_loop(struct sock *sk) ++{ ++ if (dev_recursion_level()) ++ return false; ++ if (!sk) ++ return true; ++ switch (sk->sk_family) { ++ case AF_INET: ++ return inet_sk(sk)->mc_loop; ++#if IS_ENABLED(CONFIG_IPV6) ++ case AF_INET6: ++ return inet6_sk(sk)->mc_loop; ++#endif ++ } ++ WARN_ON(1); ++ return true; ++} ++EXPORT_SYMBOL(sk_mc_loop); ++ + /* + * This is meant for all protocols to use and covers goings on + * at the socket level. Everything here is generic. +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 22917918fa80..9fbd69efa999 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -3064,10 +3064,11 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, + if (seq_rtt < 0) { + seq_rtt = ca_seq_rtt; + } +- if (!(sacked & TCPCB_SACKED_ACKED)) ++ if (!(sacked & TCPCB_SACKED_ACKED)) { + reord = min(pkts_acked, reord); +- if (!after(scb->end_seq, tp->high_seq)) +- flag |= FLAG_ORIG_SACK_ACKED; ++ if (!after(scb->end_seq, tp->high_seq)) ++ flag |= FLAG_ORIG_SACK_ACKED; ++ } + } + + if (sacked & TCPCB_SACKED_ACKED) +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index b7effad5a58c..e2f8bd0d35ed 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -1875,7 +1875,7 @@ void tcp_v4_early_demux(struct sk_buff *skb) + skb->sk = sk; + skb->destructor = sock_edemux; + if (sk->sk_state != TCP_TIME_WAIT) { +- struct dst_entry *dst = sk->sk_rx_dst; ++ struct dst_entry *dst = ACCESS_ONCE(sk->sk_rx_dst); + + if (dst) + dst = dst_check(dst, 0); +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 96f64e59d70c..8c70c73da347 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -2796,6 +2796,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, + } + #endif + ++ /* Do not fool tcpdump (if any), clean our debris */ ++ skb->tstamp.tv64 = 0; + return skb; + } + EXPORT_SYMBOL(tcp_make_synack); +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index d7907ecf0b75..066d0b03f2b8 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -555,7 +555,8 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) + { + struct sk_buff *frag; + struct rt6_info *rt = (struct rt6_info*)skb_dst(skb); +- struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; ++ struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ? ++ inet6_sk(skb->sk) : NULL; + struct ipv6hdr *tmp_hdr; + struct frag_hdr *fh; + unsigned int mtu, hlen, left, len; +diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c +index 09a22f4f36c9..bcd65186b497 100644 +--- a/net/ipv6/ndisc.c ++++ b/net/ipv6/ndisc.c +@@ -1193,7 +1193,14 @@ static void ndisc_router_discovery(struct sk_buff *skb) + if (rt) + rt6_set_expires(rt, jiffies + (HZ * lifetime)); + if (ra_msg->icmph.icmp6_hop_limit) { +- in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; ++ /* Only set hop_limit on the interface if it is higher than ++ * the current hop_limit. ++ */ ++ if (in6_dev->cnf.hop_limit < ra_msg->icmph.icmp6_hop_limit) { ++ in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; ++ } else { ++ ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than current\n"); ++ } + if (rt) + dst_metric_set(&rt->dst, RTAX_HOPLIMIT, + ra_msg->icmph.icmp6_hop_limit); +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index a4f890dd223a..9d4332dba8ea 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1633,7 +1633,7 @@ static void tcp_v6_early_demux(struct sk_buff *skb) + skb->sk = sk; + skb->destructor = sock_edemux; + if (sk->sk_state != TCP_TIME_WAIT) { +- struct dst_entry *dst = sk->sk_rx_dst; ++ struct dst_entry *dst = ACCESS_ONCE(sk->sk_rx_dst); + + if (dst) + dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie); +diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c +index d25f29377648..957c1db66652 100644 +--- a/net/netfilter/nf_conntrack_proto_generic.c ++++ b/net/netfilter/nf_conntrack_proto_generic.c +@@ -14,6 +14,30 @@ + + static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ; + ++static bool nf_generic_should_process(u8 proto) ++{ ++ switch (proto) { ++#ifdef CONFIG_NF_CT_PROTO_SCTP_MODULE ++ case IPPROTO_SCTP: ++ return false; ++#endif ++#ifdef CONFIG_NF_CT_PROTO_DCCP_MODULE ++ case IPPROTO_DCCP: ++ return false; ++#endif ++#ifdef CONFIG_NF_CT_PROTO_GRE_MODULE ++ case IPPROTO_GRE: ++ return false; ++#endif ++#ifdef CONFIG_NF_CT_PROTO_UDPLITE_MODULE ++ case IPPROTO_UDPLITE: ++ return false; ++#endif ++ default: ++ return true; ++ } ++} ++ + static inline struct nf_generic_net *generic_pernet(struct net *net) + { + return &net->ct.nf_ct_proto.generic; +@@ -67,7 +91,7 @@ static int generic_packet(struct nf_conn *ct, + static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb, + unsigned int dataoff, unsigned int *timeouts) + { +- return true; ++ return nf_generic_should_process(nf_ct_protonum(ct)); + } + + #if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT) +diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c +index 6c4cbd97a673..fc68bf6e4889 100644 +--- a/security/selinux/selinuxfs.c ++++ b/security/selinux/selinuxfs.c +@@ -1200,7 +1200,7 @@ static void sel_remove_entries(struct dentry *de) + spin_lock(&de->d_lock); + node = de->d_subdirs.next; + while (node != &de->d_subdirs) { +- struct dentry *d = list_entry(node, struct dentry, d_u.d_child); ++ struct dentry *d = list_entry(node, struct dentry, d_child); + + spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED); + list_del_init(node); +@@ -1674,12 +1674,12 @@ static void sel_remove_classes(void) + + list_for_each(class_node, &class_dir->d_subdirs) { + struct dentry *class_subdir = list_entry(class_node, +- struct dentry, d_u.d_child); ++ struct dentry, d_child); + struct list_head *class_subdir_node; + + list_for_each(class_subdir_node, &class_subdir->d_subdirs) { + struct dentry *d = list_entry(class_subdir_node, +- struct dentry, d_u.d_child); ++ struct dentry, d_child); + + if (d->d_inode) + if (d->d_inode->i_mode & S_IFDIR) diff --git a/patch/kernel/cubox-default/patch-3.14.40-41.patch b/patch/kernel/cubox-default/patch-3.14.40-41.patch new file mode 100644 index 000000000..5638effc9 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.40-41.patch @@ -0,0 +1,3586 @@ +diff --git a/Makefile b/Makefile +index 070e0ebb9231..7a60d4a1301c 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 40 ++SUBLEVEL = 41 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi +index 187fd46b7b5e..355117cbbf4a 100644 +--- a/arch/arm/boot/dts/dove.dtsi ++++ b/arch/arm/boot/dts/dove.dtsi +@@ -154,7 +154,7 @@ + + uart2: serial@12200 { + compatible = "ns16550a"; +- reg = <0x12000 0x100>; ++ reg = <0x12200 0x100>; + reg-shift = <2>; + interrupts = <9>; + clocks = <&core_clk 0>; +@@ -163,7 +163,7 @@ + + uart3: serial@12300 { + compatible = "ns16550a"; +- reg = <0x12100 0x100>; ++ reg = <0x12300 0x100>; + reg-shift = <2>; + interrupts = <10>; + clocks = <&core_clk 0>; +diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h +index f4b46d39b9cf..051b7269e639 100644 +--- a/arch/arm/include/asm/elf.h ++++ b/arch/arm/include/asm/elf.h +@@ -114,7 +114,7 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs); + the loader. We need to make sure that it is out of the way of the program + that it will "exec", and that there is sufficient room for the brk. */ + +-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) ++#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) + + /* When the program starts, a1 contains a pointer to a function to be + registered with atexit, as per the SVR4 ABI. A value of 0 means we +diff --git a/arch/arm/mach-s3c64xx/crag6410.h b/arch/arm/mach-s3c64xx/crag6410.h +index 7bc66682687e..dcbe17f5e5f8 100644 +--- a/arch/arm/mach-s3c64xx/crag6410.h ++++ b/arch/arm/mach-s3c64xx/crag6410.h +@@ -14,6 +14,7 @@ + #include + + #define GLENFARCLAS_PMIC_IRQ_BASE IRQ_BOARD_START ++#define BANFF_PMIC_IRQ_BASE (IRQ_BOARD_START + 64) + + #define PCA935X_GPIO_BASE GPIO_BOARD_START + #define CODEC_GPIO_BASE (GPIO_BOARD_START + 8) +diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c +index 3df3c372ee1f..66b95c466497 100644 +--- a/arch/arm/mach-s3c64xx/mach-crag6410.c ++++ b/arch/arm/mach-s3c64xx/mach-crag6410.c +@@ -555,6 +555,7 @@ static struct wm831x_touch_pdata touch_pdata = { + + static struct wm831x_pdata crag_pmic_pdata = { + .wm831x_num = 1, ++ .irq_base = BANFF_PMIC_IRQ_BASE, + .gpio_base = BANFF_PMIC_GPIO_BASE, + .soft_shutdown = true, + +diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile +index 6d20b7d162d8..a268a9af0c2d 100644 +--- a/arch/arm64/kernel/vdso/Makefile ++++ b/arch/arm64/kernel/vdso/Makefile +@@ -43,7 +43,7 @@ $(obj)/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE + $(call if_changed,vdsosym) + + # Assembly rules for the .S files +-$(obj-vdso): %.o: %.S ++$(obj-vdso): %.o: %.S FORCE + $(call if_changed_dep,vdsoas) + + # Actual build commands +diff --git a/arch/c6x/kernel/time.c b/arch/c6x/kernel/time.c +index 356ee84cad95..04845aaf5985 100644 +--- a/arch/c6x/kernel/time.c ++++ b/arch/c6x/kernel/time.c +@@ -49,7 +49,7 @@ u64 sched_clock(void) + return (tsc * sched_clock_multiplier) >> SCHED_CLOCK_SHIFT; + } + +-void time_init(void) ++void __init time_init(void) + { + u64 tmp = (u64)NSEC_PER_SEC << SCHED_CLOCK_SHIFT; + +diff --git a/arch/mips/include/asm/suspend.h b/arch/mips/include/asm/suspend.h +deleted file mode 100644 +index 3adac3b53d19..000000000000 +--- a/arch/mips/include/asm/suspend.h ++++ /dev/null +@@ -1,7 +0,0 @@ +-#ifndef __ASM_SUSPEND_H +-#define __ASM_SUSPEND_H +- +-/* References to section boundaries */ +-extern const void __nosave_begin, __nosave_end; +- +-#endif /* __ASM_SUSPEND_H */ +diff --git a/arch/mips/power/cpu.c b/arch/mips/power/cpu.c +index 521e5963df05..2129e67723ff 100644 +--- a/arch/mips/power/cpu.c ++++ b/arch/mips/power/cpu.c +@@ -7,7 +7,7 @@ + * Author: Hu Hongbing + * Wu Zhangjin + */ +-#include ++#include + #include + #include + +diff --git a/arch/mips/power/hibernate.S b/arch/mips/power/hibernate.S +index 32a7c828f073..e7567c8a9e79 100644 +--- a/arch/mips/power/hibernate.S ++++ b/arch/mips/power/hibernate.S +@@ -30,6 +30,8 @@ LEAF(swsusp_arch_suspend) + END(swsusp_arch_suspend) + + LEAF(swsusp_arch_resume) ++ /* Avoid TLB mismatch during and after kernel resume */ ++ jal local_flush_tlb_all + PTR_L t0, restore_pblist + 0: + PTR_L t1, PBE_ADDRESS(t0) /* source */ +@@ -43,7 +45,6 @@ LEAF(swsusp_arch_resume) + bne t1, t3, 1b + PTR_L t0, PBE_NEXT(t0) + bnez t0, 0b +- jal local_flush_tlb_all /* Avoid TLB mismatch after kernel resume */ + PTR_LA t0, saved_regs + PTR_L ra, PT_R31(t0) + PTR_L sp, PT_R29(t0) +diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c +index 2912b8787aa4..3eb36cea324c 100644 +--- a/arch/powerpc/kernel/cacheinfo.c ++++ b/arch/powerpc/kernel/cacheinfo.c +@@ -61,12 +61,22 @@ struct cache_type_info { + }; + + /* These are used to index the cache_type_info array. */ +-#define CACHE_TYPE_UNIFIED 0 +-#define CACHE_TYPE_INSTRUCTION 1 +-#define CACHE_TYPE_DATA 2 ++#define CACHE_TYPE_UNIFIED 0 /* cache-size, cache-block-size, etc. */ ++#define CACHE_TYPE_UNIFIED_D 1 /* d-cache-size, d-cache-block-size, etc */ ++#define CACHE_TYPE_INSTRUCTION 2 ++#define CACHE_TYPE_DATA 3 + + static const struct cache_type_info cache_type_info[] = { + { ++ /* Embedded systems that use cache-size, cache-block-size, ++ * etc. for the Unified (typically L2) cache. */ ++ .name = "Unified", ++ .size_prop = "cache-size", ++ .line_size_props = { "cache-line-size", ++ "cache-block-size", }, ++ .nr_sets_prop = "cache-sets", ++ }, ++ { + /* PowerPC Processor binding says the [di]-cache-* + * must be equal on unified caches, so just use + * d-cache properties. */ +@@ -293,7 +303,8 @@ static struct cache *cache_find_first_sibling(struct cache *cache) + { + struct cache *iter; + +- if (cache->type == CACHE_TYPE_UNIFIED) ++ if (cache->type == CACHE_TYPE_UNIFIED || ++ cache->type == CACHE_TYPE_UNIFIED_D) + return cache; + + list_for_each_entry(iter, &cache_list, list) +@@ -324,16 +335,29 @@ static bool cache_node_is_unified(const struct device_node *np) + return of_get_property(np, "cache-unified", NULL); + } + +-static struct cache *cache_do_one_devnode_unified(struct device_node *node, +- int level) ++/* ++ * Unified caches can have two different sets of tags. Most embedded ++ * use cache-size, etc. for the unified cache size, but open firmware systems ++ * use d-cache-size, etc. Check on initialization for which type we have, and ++ * return the appropriate structure type. Assume it's embedded if it isn't ++ * open firmware. If it's yet a 3rd type, then there will be missing entries ++ * in /sys/devices/system/cpu/cpu0/cache/index2/, and this code will need ++ * to be extended further. ++ */ ++static int cache_is_unified_d(const struct device_node *np) + { +- struct cache *cache; ++ return of_get_property(np, ++ cache_type_info[CACHE_TYPE_UNIFIED_D].size_prop, NULL) ? ++ CACHE_TYPE_UNIFIED_D : CACHE_TYPE_UNIFIED; ++} + ++/* ++ */ ++static struct cache *cache_do_one_devnode_unified(struct device_node *node, int level) ++{ + pr_debug("creating L%d ucache for %s\n", level, node->full_name); + +- cache = new_cache(CACHE_TYPE_UNIFIED, level, node); +- +- return cache; ++ return new_cache(cache_is_unified_d(node), level, node); + } + + static struct cache *cache_do_one_devnode_split(struct device_node *node, +diff --git a/arch/powerpc/kernel/suspend.c b/arch/powerpc/kernel/suspend.c +index 0167d53da30c..a531154cc0f3 100644 +--- a/arch/powerpc/kernel/suspend.c ++++ b/arch/powerpc/kernel/suspend.c +@@ -9,9 +9,7 @@ + + #include + #include +- +-/* References to section boundaries */ +-extern const void __nosave_begin, __nosave_end; ++#include + + /* + * pfn_is_nosave - check if given pfn is in the 'nosave' section +diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c +index 2396dda282cd..ead55351b254 100644 +--- a/arch/powerpc/perf/callchain.c ++++ b/arch/powerpc/perf/callchain.c +@@ -243,7 +243,7 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry, + sp = regs->gpr[1]; + perf_callchain_store(entry, next_ip); + +- for (;;) { ++ while (entry->nr < PERF_MAX_STACK_DEPTH) { + fp = (unsigned long __user *) sp; + if (!valid_user_sp(sp, 1) || read_user_stack_64(fp, &next_sp)) + return; +diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c +index 2b90ff8a93be..59ef76c5f4f4 100644 +--- a/arch/powerpc/platforms/cell/iommu.c ++++ b/arch/powerpc/platforms/cell/iommu.c +@@ -197,7 +197,7 @@ static int tce_build_cell(struct iommu_table *tbl, long index, long npages, + + io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset); + +- for (i = 0; i < npages; i++, uaddr += tbl->it_page_shift) ++ for (i = 0; i < npages; i++, uaddr += (1 << tbl->it_page_shift)) + io_pte[i] = base_pte | (__pa(uaddr) & CBE_IOPTE_RPN_Mask); + + mb(); +diff --git a/arch/s390/kernel/suspend.c b/arch/s390/kernel/suspend.c +index a7a7537ce1e7..d3236c9e226b 100644 +--- a/arch/s390/kernel/suspend.c ++++ b/arch/s390/kernel/suspend.c +@@ -13,14 +13,10 @@ + #include + #include + #include ++#include + #include "entry.h" + + /* +- * References to section boundaries +- */ +-extern const void __nosave_begin, __nosave_end; +- +-/* + * The restore of the saved pages in an hibernation image will set + * the change and referenced bits in the storage key for each page. + * Overindication of the referenced bits after an hibernation cycle +@@ -142,6 +138,8 @@ int pfn_is_nosave(unsigned long pfn) + { + unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin)); + unsigned long nosave_end_pfn = PFN_DOWN(__pa(&__nosave_end)); ++ unsigned long eshared_pfn = PFN_DOWN(__pa(&_eshared)) - 1; ++ unsigned long stext_pfn = PFN_DOWN(__pa(&_stext)); + + /* Always save lowcore pages (LC protection might be enabled). */ + if (pfn <= LC_PAGES) +@@ -149,6 +147,8 @@ int pfn_is_nosave(unsigned long pfn) + if (pfn >= nosave_begin_pfn && pfn < nosave_end_pfn) + return 1; + /* Skip memory holes and read-only pages (NSS, DCSS, ...). */ ++ if (pfn >= stext_pfn && pfn <= eshared_pfn) ++ return ipl_info.type == IPL_TYPE_NSS ? 1 : 0; + if (tprot(PFN_PHYS(pfn))) + return 1; + return 0; +diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c +index 75beea632a10..3588f2f37986 100644 +--- a/arch/s390/kvm/priv.c ++++ b/arch/s390/kvm/priv.c +@@ -414,6 +414,7 @@ static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem) + for (n = mem->count - 1; n > 0 ; n--) + memcpy(&mem->vm[n], &mem->vm[n - 1], sizeof(mem->vm[0])); + ++ memset(&mem->vm[0], 0, sizeof(mem->vm[0])); + mem->vm[0].cpus_total = cpus; + mem->vm[0].cpus_configured = cpus; + mem->vm[0].cpus_standby = 0; +diff --git a/arch/sh/include/asm/sections.h b/arch/sh/include/asm/sections.h +index 1b6199740e98..7a99e6af6372 100644 +--- a/arch/sh/include/asm/sections.h ++++ b/arch/sh/include/asm/sections.h +@@ -3,7 +3,6 @@ + + #include + +-extern long __nosave_begin, __nosave_end; + extern long __machvec_start, __machvec_end; + extern char __uncached_start, __uncached_end; + extern char __start_eh_frame[], __stop_eh_frame[]; +diff --git a/arch/sparc/power/hibernate.c b/arch/sparc/power/hibernate.c +index 42b0b8ce699a..17bd2e167e07 100644 +--- a/arch/sparc/power/hibernate.c ++++ b/arch/sparc/power/hibernate.c +@@ -9,11 +9,9 @@ + #include + #include + #include ++#include + #include + +-/* References to section boundaries */ +-extern const void __nosave_begin, __nosave_end; +- + struct saved_context saved_context; + + /* +diff --git a/arch/unicore32/include/mach/pm.h b/arch/unicore32/include/mach/pm.h +index 4dcd34ae194c..77b522694e74 100644 +--- a/arch/unicore32/include/mach/pm.h ++++ b/arch/unicore32/include/mach/pm.h +@@ -36,8 +36,5 @@ extern int puv3_pm_enter(suspend_state_t state); + /* Defined in hibernate_asm.S */ + extern int restore_image(pgd_t *resume_pg_dir, struct pbe *restore_pblist); + +-/* References to section boundaries */ +-extern const void __nosave_begin, __nosave_end; +- + extern struct pbe *restore_pblist; + #endif +diff --git a/arch/unicore32/kernel/hibernate.c b/arch/unicore32/kernel/hibernate.c +index d75ef8b6cb56..9969ec374abb 100644 +--- a/arch/unicore32/kernel/hibernate.c ++++ b/arch/unicore32/kernel/hibernate.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + + #include "mach/pm.h" +diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h +index 1da25a5f96f9..3ba047cbcf5b 100644 +--- a/arch/x86/include/asm/mwait.h ++++ b/arch/x86/include/asm/mwait.h +@@ -30,6 +30,14 @@ static inline void __mwait(unsigned long eax, unsigned long ecx) + :: "a" (eax), "c" (ecx)); + } + ++static inline void __sti_mwait(unsigned long eax, unsigned long ecx) ++{ ++ trace_hardirqs_on(); ++ /* "mwait %eax, %ecx;" */ ++ asm volatile("sti; .byte 0x0f, 0x01, 0xc9;" ++ :: "a" (eax), "c" (ecx)); ++} ++ + /* + * This uses new MONITOR/MWAIT instructions on P4 processors with PNI, + * which can obviate IPI to trigger checking of need_resched. +diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c +index 3fb8d95ab8b5..1a1ff42094a7 100644 +--- a/arch/x86/kernel/process.c ++++ b/arch/x86/kernel/process.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + /* + * per-CPU TSS segments. Threads are completely 'soft' on Linux, +@@ -398,6 +399,52 @@ static void amd_e400_idle(void) + default_idle(); + } + ++/* ++ * Intel Core2 and older machines prefer MWAIT over HALT for C1. ++ * We can't rely on cpuidle installing MWAIT, because it will not load ++ * on systems that support only C1 -- so the boot default must be MWAIT. ++ * ++ * Some AMD machines are the opposite, they depend on using HALT. ++ * ++ * So for default C1, which is used during boot until cpuidle loads, ++ * use MWAIT-C1 on Intel HW that has it, else use HALT. ++ */ ++static int prefer_mwait_c1_over_halt(const struct cpuinfo_x86 *c) ++{ ++ if (c->x86_vendor != X86_VENDOR_INTEL) ++ return 0; ++ ++ if (!cpu_has(c, X86_FEATURE_MWAIT)) ++ return 0; ++ ++ return 1; ++} ++ ++/* ++ * MONITOR/MWAIT with no hints, used for default default C1 state. ++ * This invokes MWAIT with interrutps enabled and no flags, ++ * which is backwards compatible with the original MWAIT implementation. ++ */ ++ ++static void mwait_idle(void) ++{ ++ if (!current_set_polling_and_test()) { ++ if (static_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) { ++ mb(); ++ clflush((void *)¤t_thread_info()->flags); ++ mb(); ++ } ++ ++ __monitor((void *)¤t_thread_info()->flags, 0, 0); ++ if (!need_resched()) ++ __sti_mwait(0, 0); ++ else ++ local_irq_enable(); ++ } else ++ local_irq_enable(); ++ current_clr_polling(); ++} ++ + void select_idle_routine(const struct cpuinfo_x86 *c) + { + #ifdef CONFIG_SMP +@@ -411,6 +458,9 @@ void select_idle_routine(const struct cpuinfo_x86 *c) + /* E400: APIC timer interrupt does not wake up CPU from C1e */ + pr_info("using AMD E400 aware idle routine\n"); + x86_idle = amd_e400_idle; ++ } else if (prefer_mwait_c1_over_halt(c)) { ++ pr_info("using mwait in idle threads\n"); ++ x86_idle = mwait_idle; + } else + x86_idle = default_idle; + } +diff --git a/arch/x86/power/hibernate_32.c b/arch/x86/power/hibernate_32.c +index 7d28c885d238..291226b952a9 100644 +--- a/arch/x86/power/hibernate_32.c ++++ b/arch/x86/power/hibernate_32.c +@@ -13,13 +13,11 @@ + #include + #include + #include ++#include + + /* Defined in hibernate_asm_32.S */ + extern int restore_image(void); + +-/* References to section boundaries */ +-extern const void __nosave_begin, __nosave_end; +- + /* Pointer to the temporary resume page tables */ + pgd_t *resume_pg_dir; + +diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c +index 304fca20d96e..2276238fde6f 100644 +--- a/arch/x86/power/hibernate_64.c ++++ b/arch/x86/power/hibernate_64.c +@@ -17,11 +17,9 @@ + #include + #include + #include ++#include + #include + +-/* References to section boundaries */ +-extern __visible const void __nosave_begin, __nosave_end; +- + /* Defined in hibernate_asm_64.S */ + extern asmlinkage int restore_image(void); + +diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig +index c87ae7c6e5f9..8879361e477e 100644 +--- a/arch/xtensa/Kconfig ++++ b/arch/xtensa/Kconfig +@@ -336,6 +336,36 @@ menu "Executable file formats" + + source "fs/Kconfig.binfmt" + ++config XTFPGA_LCD ++ bool "Enable XTFPGA LCD driver" ++ depends on XTENSA_PLATFORM_XTFPGA ++ default n ++ help ++ There's a 2x16 LCD on most of XTFPGA boards, kernel may output ++ progress messages there during bootup/shutdown. It may be useful ++ during board bringup. ++ ++ If unsure, say N. ++ ++config XTFPGA_LCD_BASE_ADDR ++ hex "XTFPGA LCD base address" ++ depends on XTFPGA_LCD ++ default "0x0d0c0000" ++ help ++ Base address of the LCD controller inside KIO region. ++ Different boards from XTFPGA family have LCD controller at different ++ addresses. Please consult prototyping user guide for your board for ++ the correct address. Wrong address here may lead to hardware lockup. ++ ++config XTFPGA_LCD_8BIT_ACCESS ++ bool "Use 8-bit access to XTFPGA LCD" ++ depends on XTFPGA_LCD ++ default n ++ help ++ LCD may be connected with 4- or 8-bit interface, 8-bit access may ++ only be used with 8-bit interface. Please consult prototyping user ++ guide for your board for the correct interface width. ++ + endmenu + + source "net/Kconfig" +diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h +index 50084f7c01c8..b54fa1bd7f7e 100644 +--- a/arch/xtensa/include/uapi/asm/unistd.h ++++ b/arch/xtensa/include/uapi/asm/unistd.h +@@ -715,7 +715,7 @@ __SYSCALL(323, sys_process_vm_writev, 6) + __SYSCALL(324, sys_name_to_handle_at, 5) + #define __NR_open_by_handle_at 325 + __SYSCALL(325, sys_open_by_handle_at, 3) +-#define __NR_sync_file_range 326 ++#define __NR_sync_file_range2 326 + __SYSCALL(326, sys_sync_file_range2, 6) + #define __NR_perf_event_open 327 + __SYSCALL(327, sys_perf_event_open, 5) +diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c +index d05f8feeb8d7..17b1ef3232e4 100644 +--- a/arch/xtensa/platforms/iss/network.c ++++ b/arch/xtensa/platforms/iss/network.c +@@ -349,8 +349,8 @@ static void iss_net_timer(unsigned long priv) + { + struct iss_net_private *lp = (struct iss_net_private *)priv; + +- spin_lock(&lp->lock); + iss_net_poll(); ++ spin_lock(&lp->lock); + mod_timer(&lp->timer, jiffies + lp->timer_val); + spin_unlock(&lp->lock); + } +@@ -361,7 +361,7 @@ static int iss_net_open(struct net_device *dev) + struct iss_net_private *lp = netdev_priv(dev); + int err; + +- spin_lock(&lp->lock); ++ spin_lock_bh(&lp->lock); + + err = lp->tp.open(lp); + if (err < 0) +@@ -376,9 +376,11 @@ static int iss_net_open(struct net_device *dev) + while ((err = iss_net_rx(dev)) > 0) + ; + +- spin_lock(&opened_lock); ++ spin_unlock_bh(&lp->lock); ++ spin_lock_bh(&opened_lock); + list_add(&lp->opened_list, &opened); +- spin_unlock(&opened_lock); ++ spin_unlock_bh(&opened_lock); ++ spin_lock_bh(&lp->lock); + + init_timer(&lp->timer); + lp->timer_val = ISS_NET_TIMER_VALUE; +@@ -387,7 +389,7 @@ static int iss_net_open(struct net_device *dev) + mod_timer(&lp->timer, jiffies + lp->timer_val); + + out: +- spin_unlock(&lp->lock); ++ spin_unlock_bh(&lp->lock); + return err; + } + +@@ -395,7 +397,7 @@ static int iss_net_close(struct net_device *dev) + { + struct iss_net_private *lp = netdev_priv(dev); + netif_stop_queue(dev); +- spin_lock(&lp->lock); ++ spin_lock_bh(&lp->lock); + + spin_lock(&opened_lock); + list_del(&opened); +@@ -405,18 +407,17 @@ static int iss_net_close(struct net_device *dev) + + lp->tp.close(lp); + +- spin_unlock(&lp->lock); ++ spin_unlock_bh(&lp->lock); + return 0; + } + + static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct iss_net_private *lp = netdev_priv(dev); +- unsigned long flags; + int len; + + netif_stop_queue(dev); +- spin_lock_irqsave(&lp->lock, flags); ++ spin_lock_bh(&lp->lock); + + len = lp->tp.write(lp, &skb); + +@@ -438,7 +439,7 @@ static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev) + pr_err("%s: %s failed(%d)\n", dev->name, __func__, len); + } + +- spin_unlock_irqrestore(&lp->lock, flags); ++ spin_unlock_bh(&lp->lock); + + dev_kfree_skb(skb); + return NETDEV_TX_OK; +@@ -466,9 +467,9 @@ static int iss_net_set_mac(struct net_device *dev, void *addr) + + if (!is_valid_ether_addr(hwaddr->sa_data)) + return -EADDRNOTAVAIL; +- spin_lock(&lp->lock); ++ spin_lock_bh(&lp->lock); + memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN); +- spin_unlock(&lp->lock); ++ spin_unlock_bh(&lp->lock); + return 0; + } + +@@ -520,11 +521,11 @@ static int iss_net_configure(int index, char *init) + *lp = (struct iss_net_private) { + .device_list = LIST_HEAD_INIT(lp->device_list), + .opened_list = LIST_HEAD_INIT(lp->opened_list), +- .lock = __SPIN_LOCK_UNLOCKED(lp.lock), + .dev = dev, + .index = index, +- }; ++ }; + ++ spin_lock_init(&lp->lock); + /* + * If this name ends up conflicting with an existing registered + * netdevice, that is OK, register_netdev{,ice}() will notice this +diff --git a/arch/xtensa/platforms/xtfpga/Makefile b/arch/xtensa/platforms/xtfpga/Makefile +index b9ae206340cd..7839d38b2337 100644 +--- a/arch/xtensa/platforms/xtfpga/Makefile ++++ b/arch/xtensa/platforms/xtfpga/Makefile +@@ -6,4 +6,5 @@ + # + # Note 2! The CFLAGS definitions are in the main makefile... + +-obj-y = setup.o lcd.o ++obj-y += setup.o ++obj-$(CONFIG_XTFPGA_LCD) += lcd.o +diff --git a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h +index aeb316b7ff88..e8cc86fbba09 100644 +--- a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h ++++ b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h +@@ -40,9 +40,6 @@ + + /* UART */ + #define DUART16552_PADDR (XCHAL_KIO_PADDR + 0x0D050020) +-/* LCD instruction and data addresses. */ +-#define LCD_INSTR_ADDR ((char *)IOADDR(0x0D040000)) +-#define LCD_DATA_ADDR ((char *)IOADDR(0x0D040004)) + + /* Misc. */ + #define XTFPGA_FPGAREGS_VADDR IOADDR(0x0D020000) +diff --git a/arch/xtensa/platforms/xtfpga/include/platform/lcd.h b/arch/xtensa/platforms/xtfpga/include/platform/lcd.h +index 0e435645af5a..4c8541ed1139 100644 +--- a/arch/xtensa/platforms/xtfpga/include/platform/lcd.h ++++ b/arch/xtensa/platforms/xtfpga/include/platform/lcd.h +@@ -11,10 +11,25 @@ + #ifndef __XTENSA_XTAVNET_LCD_H + #define __XTENSA_XTAVNET_LCD_H + ++#ifdef CONFIG_XTFPGA_LCD + /* Display string STR at position POS on the LCD. */ + void lcd_disp_at_pos(char *str, unsigned char pos); + + /* Shift the contents of the LCD display left or right. */ + void lcd_shiftleft(void); + void lcd_shiftright(void); ++#else ++static inline void lcd_disp_at_pos(char *str, unsigned char pos) ++{ ++} ++ ++static inline void lcd_shiftleft(void) ++{ ++} ++ ++static inline void lcd_shiftright(void) ++{ ++} ++#endif ++ + #endif +diff --git a/arch/xtensa/platforms/xtfpga/lcd.c b/arch/xtensa/platforms/xtfpga/lcd.c +index 2872301598df..4dc0c1b43f4b 100644 +--- a/arch/xtensa/platforms/xtfpga/lcd.c ++++ b/arch/xtensa/platforms/xtfpga/lcd.c +@@ -1,50 +1,63 @@ + /* +- * Driver for the LCD display on the Tensilica LX60 Board. ++ * Driver for the LCD display on the Tensilica XTFPGA board family. ++ * http://www.mytechcorp.com/cfdata/productFile/File1/MOC-16216B-B-A0A04.pdf + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2001, 2006 Tensilica Inc. ++ * Copyright (C) 2015 Cadence Design Systems Inc. + */ + +-/* +- * +- * FIXME: this code is from the examples from the LX60 user guide. +- * +- * The lcd_pause function does busy waiting, which is probably not +- * great. Maybe the code could be changed to use kernel timers, or +- * change the hardware to not need to wait. +- */ +- ++#include + #include + #include + + #include + #include +-#include + +-#define LCD_PAUSE_ITERATIONS 4000 ++/* LCD instruction and data addresses. */ ++#define LCD_INSTR_ADDR ((char *)IOADDR(CONFIG_XTFPGA_LCD_BASE_ADDR)) ++#define LCD_DATA_ADDR (LCD_INSTR_ADDR + 4) ++ + #define LCD_CLEAR 0x1 + #define LCD_DISPLAY_ON 0xc + + /* 8bit and 2 lines display */ + #define LCD_DISPLAY_MODE8BIT 0x38 ++#define LCD_DISPLAY_MODE4BIT 0x28 + #define LCD_DISPLAY_POS 0x80 + #define LCD_SHIFT_LEFT 0x18 + #define LCD_SHIFT_RIGHT 0x1c + ++static void lcd_put_byte(u8 *addr, u8 data) ++{ ++#ifdef CONFIG_XTFPGA_LCD_8BIT_ACCESS ++ ACCESS_ONCE(*addr) = data; ++#else ++ ACCESS_ONCE(*addr) = data & 0xf0; ++ ACCESS_ONCE(*addr) = (data << 4) & 0xf0; ++#endif ++} ++ + static int __init lcd_init(void) + { +- *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; ++ ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT; + mdelay(5); +- *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; ++ ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT; + udelay(200); +- *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; ++ ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT; ++ udelay(50); ++#ifndef CONFIG_XTFPGA_LCD_8BIT_ACCESS ++ ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE4BIT; ++ udelay(50); ++ lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_MODE4BIT); + udelay(50); +- *LCD_INSTR_ADDR = LCD_DISPLAY_ON; ++#endif ++ lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_ON); + udelay(50); +- *LCD_INSTR_ADDR = LCD_CLEAR; ++ lcd_put_byte(LCD_INSTR_ADDR, LCD_CLEAR); + mdelay(10); + lcd_disp_at_pos("XTENSA LINUX", 0); + return 0; +@@ -52,10 +65,10 @@ static int __init lcd_init(void) + + void lcd_disp_at_pos(char *str, unsigned char pos) + { +- *LCD_INSTR_ADDR = LCD_DISPLAY_POS | pos; ++ lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_POS | pos); + udelay(100); + while (*str != 0) { +- *LCD_DATA_ADDR = *str; ++ lcd_put_byte(LCD_DATA_ADDR, *str); + udelay(200); + str++; + } +@@ -63,13 +76,13 @@ void lcd_disp_at_pos(char *str, unsigned char pos) + + void lcd_shiftleft(void) + { +- *LCD_INSTR_ADDR = LCD_SHIFT_LEFT; ++ lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_LEFT); + udelay(50); + } + + void lcd_shiftright(void) + { +- *LCD_INSTR_ADDR = LCD_SHIFT_RIGHT; ++ lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_RIGHT); + udelay(50); + } + +diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c +index 666beea3bf1c..9498c3d575d4 100644 +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -192,7 +192,11 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent) + struct acpi_device_physical_node *pn; + bool offline = true; + +- mutex_lock(&adev->physical_node_lock); ++ /* ++ * acpi_container_offline() calls this for all of the container's ++ * children under the container's physical_node_lock lock. ++ */ ++ mutex_lock_nested(&adev->physical_node_lock, SINGLE_DEPTH_NESTING); + + list_for_each_entry(pn, &adev->physical_node_list, node) + if (device_supports_offline(pn->dev) && !pn->dev->offline) { +diff --git a/drivers/base/bus.c b/drivers/base/bus.c +index 45d0fa78981c..12b39dc2ad5c 100644 +--- a/drivers/base/bus.c ++++ b/drivers/base/bus.c +@@ -515,11 +515,11 @@ int bus_add_device(struct device *dev) + goto out_put; + error = device_add_groups(dev, bus->dev_groups); + if (error) +- goto out_groups; ++ goto out_id; + error = sysfs_create_link(&bus->p->devices_kset->kobj, + &dev->kobj, dev_name(dev)); + if (error) +- goto out_id; ++ goto out_groups; + error = sysfs_create_link(&dev->kobj, + &dev->bus->p->subsys.kobj, "subsystem"); + if (error) +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index 5afe556a70f8..26b03e1254ef 100644 +--- a/drivers/bluetooth/ath3k.c ++++ b/drivers/bluetooth/ath3k.c +@@ -64,6 +64,7 @@ static const struct usb_device_id ath3k_table[] = { + /* Atheros AR3011 with sflash firmware*/ + { USB_DEVICE(0x0489, 0xE027) }, + { USB_DEVICE(0x0489, 0xE03D) }, ++ { USB_DEVICE(0x04F2, 0xAFF1) }, + { USB_DEVICE(0x0930, 0x0215) }, + { USB_DEVICE(0x0CF3, 0x3002) }, + { USB_DEVICE(0x0CF3, 0xE019) }, +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 03b331798e16..9eb1669962ef 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -142,6 +142,7 @@ static const struct usb_device_id blacklist_table[] = { + /* Atheros 3011 with sflash firmware */ + { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE }, ++ { USB_DEVICE(0x04f2, 0xaff1), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE }, +diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c +index 0996a3a39855..a9dd21aff6bb 100644 +--- a/drivers/clk/qcom/clk-rcg2.c ++++ b/drivers/clk/qcom/clk-rcg2.c +@@ -257,7 +257,7 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate) + mask |= CFG_SRC_SEL_MASK | CFG_MODE_MASK; + cfg = f->pre_div << CFG_SRC_DIV_SHIFT; + cfg |= rcg->parent_map[f->src] << CFG_SRC_SEL_SHIFT; +- if (rcg->mnd_width && f->n) ++ if (rcg->mnd_width && f->n && (f->m != f->n)) + cfg |= CFG_MODE_DUAL_EDGE; + ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, mask, + cfg); +diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c +index c0a7d7723510..a90af1780cf2 100644 +--- a/drivers/clk/tegra/clk.c ++++ b/drivers/clk/tegra/clk.c +@@ -266,7 +266,7 @@ void __init tegra_add_of_provider(struct device_node *np) + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + + rst_ctlr.of_node = np; +- rst_ctlr.nr_resets = clk_num * 32; ++ rst_ctlr.nr_resets = periph_banks * 32; + reset_controller_register(&rst_ctlr); + } + +diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c +index dde41f1df608..d522396174c3 100644 +--- a/drivers/crypto/omap-aes.c ++++ b/drivers/crypto/omap-aes.c +@@ -554,15 +554,23 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd) + return err; + } + +-static int omap_aes_check_aligned(struct scatterlist *sg) ++static int omap_aes_check_aligned(struct scatterlist *sg, int total) + { ++ int len = 0; ++ + while (sg) { + if (!IS_ALIGNED(sg->offset, 4)) + return -1; + if (!IS_ALIGNED(sg->length, AES_BLOCK_SIZE)) + return -1; ++ ++ len += sg->length; + sg = sg_next(sg); + } ++ ++ if (len != total) ++ return -1; ++ + return 0; + } + +@@ -633,8 +641,8 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd, + dd->in_sg = req->src; + dd->out_sg = req->dst; + +- if (omap_aes_check_aligned(dd->in_sg) || +- omap_aes_check_aligned(dd->out_sg)) { ++ if (omap_aes_check_aligned(dd->in_sg, dd->total) || ++ omap_aes_check_aligned(dd->out_sg, dd->total)) { + if (omap_aes_copy_sgs(dd)) + pr_err("Failed to copy SGs for unaligned cases\n"); + dd->sgs_copied = 1; +diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c +index 3b1fd1ce460f..e9d8cf6c2f79 100644 +--- a/drivers/gpio/gpio-mvebu.c ++++ b/drivers/gpio/gpio-mvebu.c +@@ -304,11 +304,13 @@ static void mvebu_gpio_edge_irq_mask(struct irq_data *d) + { + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mvebu_gpio_chip *mvchip = gc->private; ++ struct irq_chip_type *ct = irq_data_get_chip_type(d); + u32 mask = 1 << (d->irq - gc->irq_base); + + irq_gc_lock(gc); +- gc->mask_cache &= ~mask; +- writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip)); ++ ct->mask_cache_priv &= ~mask; ++ ++ writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip)); + irq_gc_unlock(gc); + } + +@@ -316,11 +318,13 @@ static void mvebu_gpio_edge_irq_unmask(struct irq_data *d) + { + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mvebu_gpio_chip *mvchip = gc->private; ++ struct irq_chip_type *ct = irq_data_get_chip_type(d); ++ + u32 mask = 1 << (d->irq - gc->irq_base); + + irq_gc_lock(gc); +- gc->mask_cache |= mask; +- writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip)); ++ ct->mask_cache_priv |= mask; ++ writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip)); + irq_gc_unlock(gc); + } + +@@ -328,11 +332,13 @@ static void mvebu_gpio_level_irq_mask(struct irq_data *d) + { + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mvebu_gpio_chip *mvchip = gc->private; ++ struct irq_chip_type *ct = irq_data_get_chip_type(d); ++ + u32 mask = 1 << (d->irq - gc->irq_base); + + irq_gc_lock(gc); +- gc->mask_cache &= ~mask; +- writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip)); ++ ct->mask_cache_priv &= ~mask; ++ writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip)); + irq_gc_unlock(gc); + } + +@@ -340,11 +346,13 @@ static void mvebu_gpio_level_irq_unmask(struct irq_data *d) + { + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mvebu_gpio_chip *mvchip = gc->private; ++ struct irq_chip_type *ct = irq_data_get_chip_type(d); ++ + u32 mask = 1 << (d->irq - gc->irq_base); + + irq_gc_lock(gc); +- gc->mask_cache |= mask; +- writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip)); ++ ct->mask_cache_priv |= mask; ++ writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip)); + irq_gc_unlock(gc); + } + +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index 8f42bd724682..f1fc14c33be5 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -1928,15 +1928,15 @@ EXPORT_SYMBOL_GPL(gpiod_is_active_low); + * that the GPIO was actually requested. + */ + +-static int _gpiod_get_raw_value(const struct gpio_desc *desc) ++static bool _gpiod_get_raw_value(const struct gpio_desc *desc) + { + struct gpio_chip *chip; +- int value; ++ bool value; + int offset; + + chip = desc->chip; + offset = gpio_chip_hwgpio(desc); +- value = chip->get ? chip->get(chip, offset) : 0; ++ value = chip->get ? chip->get(chip, offset) : false; + trace_gpio_value(desc_to_gpio(desc), 1, value); + return value; + } +@@ -1992,7 +1992,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_value); + * @desc: gpio descriptor whose state need to be set. + * @value: Non-zero for setting it HIGH otherise it will set to LOW. + */ +-static void _gpio_set_open_drain_value(struct gpio_desc *desc, int value) ++static void _gpio_set_open_drain_value(struct gpio_desc *desc, bool value) + { + int err = 0; + struct gpio_chip *chip = desc->chip; +@@ -2019,7 +2019,7 @@ static void _gpio_set_open_drain_value(struct gpio_desc *desc, int value) + * @desc: gpio descriptor whose state need to be set. + * @value: Non-zero for setting it HIGH otherise it will set to LOW. + */ +-static void _gpio_set_open_source_value(struct gpio_desc *desc, int value) ++static void _gpio_set_open_source_value(struct gpio_desc *desc, bool value) + { + int err = 0; + struct gpio_chip *chip = desc->chip; +@@ -2041,7 +2041,7 @@ static void _gpio_set_open_source_value(struct gpio_desc *desc, int value) + __func__, err); + } + +-static void _gpiod_set_raw_value(struct gpio_desc *desc, int value) ++static void _gpiod_set_raw_value(struct gpio_desc *desc, bool value) + { + struct gpio_chip *chip; + +diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h +index 0c83b3dab58c..5b38bf819b7b 100644 +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -1181,6 +1181,7 @@ + #define GMBUS_CYCLE_INDEX (2<<25) + #define GMBUS_CYCLE_STOP (4<<25) + #define GMBUS_BYTE_COUNT_SHIFT 16 ++#define GMBUS_BYTE_COUNT_MAX 256U + #define GMBUS_SLAVE_INDEX_SHIFT 8 + #define GMBUS_SLAVE_ADDR_SHIFT 1 + #define GMBUS_SLAVE_READ (1<<0) +diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c +index d33b61d0dd33..1d02970ed395 100644 +--- a/drivers/gpu/drm/i915/intel_i2c.c ++++ b/drivers/gpu/drm/i915/intel_i2c.c +@@ -324,18 +324,17 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv) + } + + static int +-gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, +- u32 gmbus1_index) ++gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv, ++ unsigned short addr, u8 *buf, unsigned int len, ++ u32 gmbus1_index) + { + int reg_offset = dev_priv->gpio_mmio_base; +- u16 len = msg->len; +- u8 *buf = msg->buf; + + I915_WRITE(GMBUS1 + reg_offset, + gmbus1_index | + GMBUS_CYCLE_WAIT | + (len << GMBUS_BYTE_COUNT_SHIFT) | +- (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) | ++ (addr << GMBUS_SLAVE_ADDR_SHIFT) | + GMBUS_SLAVE_READ | GMBUS_SW_RDY); + while (len) { + int ret; +@@ -357,11 +356,35 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, + } + + static int +-gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) ++gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, ++ u32 gmbus1_index) + { +- int reg_offset = dev_priv->gpio_mmio_base; +- u16 len = msg->len; + u8 *buf = msg->buf; ++ unsigned int rx_size = msg->len; ++ unsigned int len; ++ int ret; ++ ++ do { ++ len = min(rx_size, GMBUS_BYTE_COUNT_MAX); ++ ++ ret = gmbus_xfer_read_chunk(dev_priv, msg->addr, ++ buf, len, gmbus1_index); ++ if (ret) ++ return ret; ++ ++ rx_size -= len; ++ buf += len; ++ } while (rx_size != 0); ++ ++ return 0; ++} ++ ++static int ++gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv, ++ unsigned short addr, u8 *buf, unsigned int len) ++{ ++ int reg_offset = dev_priv->gpio_mmio_base; ++ unsigned int chunk_size = len; + u32 val, loop; + + val = loop = 0; +@@ -373,8 +396,8 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) + I915_WRITE(GMBUS3 + reg_offset, val); + I915_WRITE(GMBUS1 + reg_offset, + GMBUS_CYCLE_WAIT | +- (msg->len << GMBUS_BYTE_COUNT_SHIFT) | +- (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) | ++ (chunk_size << GMBUS_BYTE_COUNT_SHIFT) | ++ (addr << GMBUS_SLAVE_ADDR_SHIFT) | + GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); + while (len) { + int ret; +@@ -391,6 +414,29 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) + if (ret) + return ret; + } ++ ++ return 0; ++} ++ ++static int ++gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) ++{ ++ u8 *buf = msg->buf; ++ unsigned int tx_size = msg->len; ++ unsigned int len; ++ int ret; ++ ++ do { ++ len = min(tx_size, GMBUS_BYTE_COUNT_MAX); ++ ++ ret = gmbus_xfer_write_chunk(dev_priv, msg->addr, buf, len); ++ if (ret) ++ return ret; ++ ++ buf += len; ++ tx_size -= len; ++ } while (tx_size != 0); ++ + return 0; + } + +diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +index 461df93e825e..4f32b34f48d4 100644 +--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c ++++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +@@ -35,8 +35,6 @@ + A3XX_INT0_CP_AHB_ERROR_HALT | \ + A3XX_INT0_UCHE_OOB_ACCESS) + +-static struct platform_device *a3xx_pdev; +- + static void a3xx_me_init(struct msm_gpu *gpu) + { + struct msm_ringbuffer *ring = gpu->rb; +@@ -311,7 +309,6 @@ static void a3xx_destroy(struct msm_gpu *gpu) + ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl); + #endif + +- put_device(&a3xx_gpu->pdev->dev); + kfree(a3xx_gpu); + } + +@@ -439,7 +436,8 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) + struct a3xx_gpu *a3xx_gpu = NULL; + struct adreno_gpu *adreno_gpu; + struct msm_gpu *gpu; +- struct platform_device *pdev = a3xx_pdev; ++ struct msm_drm_private *priv = dev->dev_private; ++ struct platform_device *pdev = priv->gpu_pdev; + struct adreno_platform_config *config; + int ret; + +@@ -460,7 +458,6 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) + adreno_gpu = &a3xx_gpu->base; + gpu = &adreno_gpu->base; + +- get_device(&pdev->dev); + a3xx_gpu->pdev = pdev; + + gpu->fast_rate = config->fast_rate; +@@ -522,17 +519,24 @@ fail: + # include + #endif + +-static int a3xx_probe(struct platform_device *pdev) ++static void set_gpu_pdev(struct drm_device *dev, ++ struct platform_device *pdev) ++{ ++ struct msm_drm_private *priv = dev->dev_private; ++ priv->gpu_pdev = pdev; ++} ++ ++static int a3xx_bind(struct device *dev, struct device *master, void *data) + { + static struct adreno_platform_config config = {}; + #ifdef CONFIG_OF +- struct device_node *child, *node = pdev->dev.of_node; ++ struct device_node *child, *node = dev->of_node; + u32 val; + int ret; + + ret = of_property_read_u32(node, "qcom,chipid", &val); + if (ret) { +- dev_err(&pdev->dev, "could not find chipid: %d\n", ret); ++ dev_err(dev, "could not find chipid: %d\n", ret); + return ret; + } + +@@ -548,7 +552,7 @@ static int a3xx_probe(struct platform_device *pdev) + for_each_child_of_node(child, pwrlvl) { + ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val); + if (ret) { +- dev_err(&pdev->dev, "could not find gpu-freq: %d\n", ret); ++ dev_err(dev, "could not find gpu-freq: %d\n", ret); + return ret; + } + config.fast_rate = max(config.fast_rate, val); +@@ -558,12 +562,12 @@ static int a3xx_probe(struct platform_device *pdev) + } + + if (!config.fast_rate) { +- dev_err(&pdev->dev, "could not find clk rates\n"); ++ dev_err(dev, "could not find clk rates\n"); + return -ENXIO; + } + + #else +- struct kgsl_device_platform_data *pdata = pdev->dev.platform_data; ++ struct kgsl_device_platform_data *pdata = dev->platform_data; + uint32_t version = socinfo_get_version(); + if (cpu_is_apq8064ab()) { + config.fast_rate = 450000000; +@@ -609,14 +613,30 @@ static int a3xx_probe(struct platform_device *pdev) + config.bus_scale_table = pdata->bus_scale_table; + # endif + #endif +- pdev->dev.platform_data = &config; +- a3xx_pdev = pdev; ++ dev->platform_data = &config; ++ set_gpu_pdev(dev_get_drvdata(master), to_platform_device(dev)); + return 0; + } + ++static void a3xx_unbind(struct device *dev, struct device *master, ++ void *data) ++{ ++ set_gpu_pdev(dev_get_drvdata(master), NULL); ++} ++ ++static const struct component_ops a3xx_ops = { ++ .bind = a3xx_bind, ++ .unbind = a3xx_unbind, ++}; ++ ++static int a3xx_probe(struct platform_device *pdev) ++{ ++ return component_add(&pdev->dev, &a3xx_ops); ++} ++ + static int a3xx_remove(struct platform_device *pdev) + { +- a3xx_pdev = NULL; ++ component_del(&pdev->dev, &a3xx_ops); + return 0; + } + +@@ -624,7 +644,6 @@ static const struct of_device_id dt_match[] = { + { .compatible = "qcom,kgsl-3d0" }, + {} + }; +-MODULE_DEVICE_TABLE(of, dt_match); + + static struct platform_driver a3xx_driver = { + .probe = a3xx_probe, +diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c +index 6f1588aa9071..8a04a1d206cd 100644 +--- a/drivers/gpu/drm/msm/hdmi/hdmi.c ++++ b/drivers/gpu/drm/msm/hdmi/hdmi.c +@@ -17,8 +17,6 @@ + + #include "hdmi.h" + +-static struct platform_device *hdmi_pdev; +- + void hdmi_set_mode(struct hdmi *hdmi, bool power_on) + { + uint32_t ctrl = 0; +@@ -75,7 +73,7 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder) + { + struct hdmi *hdmi = NULL; + struct msm_drm_private *priv = dev->dev_private; +- struct platform_device *pdev = hdmi_pdev; ++ struct platform_device *pdev = priv->hdmi_pdev; + struct hdmi_platform_config *config; + int i, ret; + +@@ -95,8 +93,6 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder) + + kref_init(&hdmi->refcount); + +- get_device(&pdev->dev); +- + hdmi->dev = dev; + hdmi->pdev = pdev; + hdmi->config = config; +@@ -249,17 +245,24 @@ fail: + + #include + +-static int hdmi_dev_probe(struct platform_device *pdev) ++static void set_hdmi_pdev(struct drm_device *dev, ++ struct platform_device *pdev) ++{ ++ struct msm_drm_private *priv = dev->dev_private; ++ priv->hdmi_pdev = pdev; ++} ++ ++static int hdmi_bind(struct device *dev, struct device *master, void *data) + { + static struct hdmi_platform_config config = {}; + #ifdef CONFIG_OF +- struct device_node *of_node = pdev->dev.of_node; ++ struct device_node *of_node = dev->of_node; + + int get_gpio(const char *name) + { + int gpio = of_get_named_gpio(of_node, name, 0); + if (gpio < 0) { +- dev_err(&pdev->dev, "failed to get gpio: %s (%d)\n", ++ dev_err(dev, "failed to get gpio: %s (%d)\n", + name, gpio); + gpio = -1; + } +@@ -336,14 +339,30 @@ static int hdmi_dev_probe(struct platform_device *pdev) + config.mux_sel_gpio = -1; + } + #endif +- pdev->dev.platform_data = &config; +- hdmi_pdev = pdev; ++ dev->platform_data = &config; ++ set_hdmi_pdev(dev_get_drvdata(master), to_platform_device(dev)); + return 0; + } + ++static void hdmi_unbind(struct device *dev, struct device *master, ++ void *data) ++{ ++ set_hdmi_pdev(dev_get_drvdata(master), NULL); ++} ++ ++static const struct component_ops hdmi_ops = { ++ .bind = hdmi_bind, ++ .unbind = hdmi_unbind, ++}; ++ ++static int hdmi_dev_probe(struct platform_device *pdev) ++{ ++ return component_add(&pdev->dev, &hdmi_ops); ++} ++ + static int hdmi_dev_remove(struct platform_device *pdev) + { +- hdmi_pdev = NULL; ++ component_del(&pdev->dev, &hdmi_ops); + return 0; + } + +@@ -351,7 +370,6 @@ static const struct of_device_id dt_match[] = { + { .compatible = "qcom,hdmi-tx" }, + {} + }; +-MODULE_DEVICE_TABLE(of, dt_match); + + static struct platform_driver hdmi_driver = { + .probe = hdmi_dev_probe, +diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c +index e6adafc7eff3..e79cfd0b2b04 100644 +--- a/drivers/gpu/drm/msm/msm_drv.c ++++ b/drivers/gpu/drm/msm/msm_drv.c +@@ -56,6 +56,10 @@ static char *vram; + MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU"); + module_param(vram, charp, 0); + ++/* ++ * Util/helpers: ++ */ ++ + void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, + const char *dbgname) + { +@@ -143,6 +147,8 @@ static int msm_unload(struct drm_device *dev) + priv->vram.paddr, &attrs); + } + ++ component_unbind_all(dev->dev, dev); ++ + dev->dev_private = NULL; + + kfree(priv); +@@ -175,6 +181,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags) + struct msm_kms *kms; + int ret; + ++ + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + dev_err(dev->dev, "failed to allocate private data\n"); +@@ -226,6 +233,13 @@ static int msm_load(struct drm_device *dev, unsigned long flags) + (uint32_t)(priv->vram.paddr + size)); + } + ++ platform_set_drvdata(pdev, dev); ++ ++ /* Bind all our sub-components: */ ++ ret = component_bind_all(dev->dev, dev); ++ if (ret) ++ return ret; ++ + switch (get_mdp_ver(pdev)) { + case 4: + kms = mdp4_kms_init(dev); +@@ -281,8 +295,6 @@ static int msm_load(struct drm_device *dev, unsigned long flags) + goto fail; + } + +- platform_set_drvdata(pdev, dev); +- + #ifdef CONFIG_DRM_MSM_FBDEV + priv->fbdev = msm_fbdev_init(dev); + #endif +@@ -819,18 +831,110 @@ static const struct dev_pm_ops msm_pm_ops = { + }; + + /* ++ * Componentized driver support: ++ */ ++ ++#ifdef CONFIG_OF ++/* NOTE: the CONFIG_OF case duplicates the same code as exynos or imx ++ * (or probably any other).. so probably some room for some helpers ++ */ ++static int compare_of(struct device *dev, void *data) ++{ ++ return dev->of_node == data; ++} ++ ++static int msm_drm_add_components(struct device *master, struct master *m) ++{ ++ struct device_node *np = master->of_node; ++ unsigned i; ++ int ret; ++ ++ for (i = 0; ; i++) { ++ struct device_node *node; ++ ++ node = of_parse_phandle(np, "connectors", i); ++ if (!node) ++ break; ++ ++ ret = component_master_add_child(m, compare_of, node); ++ of_node_put(node); ++ ++ if (ret) ++ return ret; ++ } ++ return 0; ++} ++#else ++static int compare_dev(struct device *dev, void *data) ++{ ++ return dev == data; ++} ++ ++static int msm_drm_add_components(struct device *master, struct master *m) ++{ ++ /* For non-DT case, it kinda sucks. We don't actually have a way ++ * to know whether or not we are waiting for certain devices (or if ++ * they are simply not present). But for non-DT we only need to ++ * care about apq8064/apq8060/etc (all mdp4/a3xx): ++ */ ++ static const char *devnames[] = { ++ "hdmi_msm.0", "kgsl-3d0.0", ++ }; ++ int i; ++ ++ DBG("Adding components.."); ++ ++ for (i = 0; i < ARRAY_SIZE(devnames); i++) { ++ struct device *dev; ++ int ret; ++ ++ dev = bus_find_device_by_name(&platform_bus_type, ++ NULL, devnames[i]); ++ if (!dev) { ++ dev_info(master, "still waiting for %s\n", devnames[i]); ++ return -EPROBE_DEFER; ++ } ++ ++ ret = component_master_add_child(m, compare_dev, dev); ++ if (ret) { ++ DBG("could not add child: %d", ret); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++#endif ++ ++static int msm_drm_bind(struct device *dev) ++{ ++ return drm_platform_init(&msm_driver, to_platform_device(dev)); ++} ++ ++static void msm_drm_unbind(struct device *dev) ++{ ++ drm_put_dev(platform_get_drvdata(to_platform_device(dev))); ++} ++ ++static const struct component_master_ops msm_drm_ops = { ++ .add_components = msm_drm_add_components, ++ .bind = msm_drm_bind, ++ .unbind = msm_drm_unbind, ++}; ++ ++/* + * Platform driver: + */ + + static int msm_pdev_probe(struct platform_device *pdev) + { + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); +- return drm_platform_init(&msm_driver, pdev); ++ return component_master_add(&pdev->dev, &msm_drm_ops); + } + + static int msm_pdev_remove(struct platform_device *pdev) + { +- drm_put_dev(platform_get_drvdata(pdev)); ++ component_master_del(&pdev->dev, &msm_drm_ops); + + return 0; + } +diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h +index 3d63269c5b29..9d10ee0b5aac 100644 +--- a/drivers/gpu/drm/msm/msm_drv.h ++++ b/drivers/gpu/drm/msm/msm_drv.h +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -69,6 +70,9 @@ struct msm_drm_private { + + struct msm_kms *kms; + ++ /* subordinate devices, if present: */ ++ struct platform_device *hdmi_pdev, *gpu_pdev; ++ + /* when we have more than one 'msm_gpu' these need to be an array: */ + struct msm_gpu *gpu; + struct msm_file_private *lastctx; +diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c +index 663394f0c166..0db3e208f02a 100644 +--- a/drivers/gpu/drm/radeon/atombios_crtc.c ++++ b/drivers/gpu/drm/radeon/atombios_crtc.c +@@ -330,8 +330,10 @@ atombios_set_crtc_dtd_timing(struct drm_crtc *crtc, + misc |= ATOM_COMPOSITESYNC; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + misc |= ATOM_INTERLACE; +- if (mode->flags & DRM_MODE_FLAG_DBLSCAN) ++ if (mode->flags & DRM_MODE_FLAG_DBLCLK) + misc |= ATOM_DOUBLE_CLOCK_MODE; ++ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) ++ misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2; + + args.susModeMiscInfo.usAccess = cpu_to_le16(misc); + args.ucCRTC = radeon_crtc->crtc_id; +@@ -374,8 +376,10 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc, + misc |= ATOM_COMPOSITESYNC; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + misc |= ATOM_INTERLACE; +- if (mode->flags & DRM_MODE_FLAG_DBLSCAN) ++ if (mode->flags & DRM_MODE_FLAG_DBLCLK) + misc |= ATOM_DOUBLE_CLOCK_MODE; ++ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) ++ misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2; + + args.susModeMiscInfo.usAccess = cpu_to_le16(misc); + args.ucCRTC = radeon_crtc->crtc_id; +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +index e99e71a6ea59..356f22f90a05 100644 +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -134,7 +134,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, + GFP_KERNEL); + if (!open_info) { + err = -ENOMEM; +- goto error0; ++ goto error_gpadl; + } + + init_completion(&open_info->waitevent); +@@ -150,7 +150,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, + + if (userdatalen > MAX_USER_DEFINED_BYTES) { + err = -EINVAL; +- goto error0; ++ goto error_gpadl; + } + + if (userdatalen) +@@ -194,6 +194,9 @@ error1: + list_del(&open_info->msglistentry); + spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); + ++error_gpadl: ++ vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle); ++ + error0: + free_pages((unsigned long)out, + get_order(send_ringbuffer_size + recv_ringbuffer_size)); +diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c +index 5fb80b8962a2..43fe15a0e5cc 100644 +--- a/drivers/i2c/i2c-core.c ++++ b/drivers/i2c/i2c-core.c +@@ -217,6 +217,7 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap) + adap->bus_recovery_info->set_scl(adap, 1); + return i2c_generic_recovery(adap); + } ++EXPORT_SYMBOL_GPL(i2c_generic_scl_recovery); + + int i2c_generic_gpio_recovery(struct i2c_adapter *adap) + { +@@ -231,6 +232,7 @@ int i2c_generic_gpio_recovery(struct i2c_adapter *adap) + + return ret; + } ++EXPORT_SYMBOL_GPL(i2c_generic_gpio_recovery); + + int i2c_recover_bus(struct i2c_adapter *adap) + { +@@ -240,6 +242,7 @@ int i2c_recover_bus(struct i2c_adapter *adap) + dev_dbg(&adap->dev, "Trying i2c bus recovery\n"); + return adap->bus_recovery_info->recover_bus(adap); + } ++EXPORT_SYMBOL_GPL(i2c_recover_bus); + + static int i2c_device_probe(struct device *dev) + { +diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c +index 055ebebc07dd..c1fef27010d4 100644 +--- a/drivers/infiniband/core/umem.c ++++ b/drivers/infiniband/core/umem.c +@@ -94,12 +94,15 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, + if (dmasync) + dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs); + ++ if (!size) ++ return ERR_PTR(-EINVAL); ++ + /* + * If the combination of the addr and size requested for this memory + * region causes an integer overflow, return error. + */ +- if ((PAGE_ALIGN(addr + size) <= size) || +- (PAGE_ALIGN(addr + size) <= addr)) ++ if (((addr + size) < addr) || ++ PAGE_ALIGN(addr + size) < (addr + size)) + return ERR_PTR(-EINVAL); + + if (!can_do_mlock()) +diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c +index d8f4d1fe8494..8d7cd98c9671 100644 +--- a/drivers/infiniband/hw/mlx4/qp.c ++++ b/drivers/infiniband/hw/mlx4/qp.c +@@ -2274,8 +2274,7 @@ static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr, + + memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen); + +- *lso_hdr_sz = cpu_to_be32((wr->wr.ud.mss - wr->wr.ud.hlen) << 16 | +- wr->wr.ud.hlen); ++ *lso_hdr_sz = cpu_to_be32(wr->wr.ud.mss << 16 | wr->wr.ud.hlen); + *lso_seg_len = halign; + return 0; + } +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 0b75b5764f31..cfc5a2e6dcce 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -814,6 +814,21 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) + } + + /* ++ * This writes the reg_07 value again to the hardware at the end of every ++ * set_rate call because the register loses its value. reg_07 allows setting ++ * absolute mode on v4 hardware ++ */ ++static void elantech_set_rate_restore_reg_07(struct psmouse *psmouse, ++ unsigned int rate) ++{ ++ struct elantech_data *etd = psmouse->private; ++ ++ etd->original_set_rate(psmouse, rate); ++ if (elantech_write_reg(psmouse, 0x07, etd->reg_07)) ++ psmouse_err(psmouse, "restoring reg_07 failed\n"); ++} ++ ++/* + * Put the touchpad into absolute mode + */ + static int elantech_set_absolute_mode(struct psmouse *psmouse) +@@ -1015,6 +1030,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse, + * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons + * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons + * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons ++ * Asus TP500LN 0x381f17 10, 14, 0e clickpad ++ * Asus X750JN 0x381f17 10, 14, 0e clickpad + * Asus UX31 0x361f00 20, 15, 0e clickpad + * Asus UX32VD 0x361f02 00, 15, 0e clickpad + * Avatar AVIU-145A2 0x361f00 ? clickpad +@@ -1490,6 +1507,11 @@ int elantech_init(struct psmouse *psmouse) + goto init_fail; + } + ++ if (etd->fw_version == 0x381f17) { ++ etd->original_set_rate = psmouse->set_rate; ++ psmouse->set_rate = elantech_set_rate_restore_reg_07; ++ } ++ + if (elantech_set_input_params(psmouse)) { + psmouse_err(psmouse, "failed to query touchpad range.\n"); + goto init_fail; +diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h +index 9e0e2a1f340d..59263a3a8667 100644 +--- a/drivers/input/mouse/elantech.h ++++ b/drivers/input/mouse/elantech.h +@@ -139,6 +139,7 @@ struct elantech_data { + struct finger_pos mt[ETP_MAX_FINGERS]; + unsigned char parity[256]; + int (*send_cmd)(struct psmouse *psmouse, unsigned char c, unsigned char *param); ++ void (*original_set_rate)(struct psmouse *psmouse, unsigned int rate); + }; + + #ifdef CONFIG_MOUSE_PS2_ELANTECH +diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c +index 4a8d19d0a5a4..5a4cda24e302 100644 +--- a/drivers/md/dm-crypt.c ++++ b/drivers/md/dm-crypt.c +@@ -915,11 +915,10 @@ static int crypt_convert(struct crypt_config *cc, + + switch (r) { + /* async */ ++ case -EINPROGRESS: + case -EBUSY: + wait_for_completion(&ctx->restart); + reinit_completion(&ctx->restart); +- /* fall through*/ +- case -EINPROGRESS: + ctx->req = NULL; + ctx->cc_sector++; + continue; +@@ -1314,10 +1313,8 @@ static void kcryptd_async_done(struct crypto_async_request *async_req, + struct dm_crypt_io *io = container_of(ctx, struct dm_crypt_io, ctx); + struct crypt_config *cc = io->cc; + +- if (error == -EINPROGRESS) { +- complete(&ctx->restart); ++ if (error == -EINPROGRESS) + return; +- } + + if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post) + error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq); +@@ -1328,12 +1325,15 @@ static void kcryptd_async_done(struct crypto_async_request *async_req, + mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool); + + if (!atomic_dec_and_test(&ctx->cc_pending)) +- return; ++ goto done; + + if (bio_data_dir(io->base_bio) == READ) + kcryptd_crypt_read_done(io); + else + kcryptd_crypt_write_io_submit(io, 1); ++done: ++ if (!completion_done(&ctx->restart)) ++ complete(&ctx->restart); + } + + static void kcryptd_crypt(struct work_struct *work) +diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c +index 407a99e46f69..683e685ed697 100644 +--- a/drivers/md/raid0.c ++++ b/drivers/md/raid0.c +@@ -320,7 +320,7 @@ static struct strip_zone *find_zone(struct r0conf *conf, + + /* + * remaps the bio to the target device. we separate two flows. +- * power 2 flow and a general flow for the sake of perfromance ++ * power 2 flow and a general flow for the sake of performance + */ + static struct md_rdev *map_sector(struct mddev *mddev, struct strip_zone *zone, + sector_t sector, sector_t *sector_offset) +@@ -538,6 +538,7 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio) + split = bio; + } + ++ sector = bio->bi_iter.bi_sector; + zone = find_zone(mddev->private, §or); + tmp_dev = map_sector(mddev, zone, sector, §or); + split->bi_bdev = tmp_dev->bdev; +diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c +index c45c9881bb5f..4572530346fb 100644 +--- a/drivers/media/usb/stk1160/stk1160-v4l.c ++++ b/drivers/media/usb/stk1160/stk1160-v4l.c +@@ -244,6 +244,11 @@ static int stk1160_stop_streaming(struct stk1160 *dev) + if (mutex_lock_interruptible(&dev->v4l_lock)) + return -ERESTARTSYS; + ++ /* ++ * Once URBs are cancelled, the URB complete handler ++ * won't be running. This is required to safely release the ++ * current buffer (dev->isoc_ctl.buf). ++ */ + stk1160_cancel_isoc(dev); + + /* +@@ -624,8 +629,16 @@ void stk1160_clear_queue(struct stk1160 *dev) + stk1160_info("buffer [%p/%d] aborted\n", + buf, buf->vb.v4l2_buf.index); + } +- /* It's important to clear current buffer */ +- dev->isoc_ctl.buf = NULL; ++ ++ /* It's important to release the current buffer */ ++ if (dev->isoc_ctl.buf) { ++ buf = dev->isoc_ctl.buf; ++ dev->isoc_ctl.buf = NULL; ++ ++ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); ++ stk1160_info("buffer [%p/%d] aborted\n", ++ buf, buf->vb.v4l2_buf.index); ++ } + spin_unlock_irqrestore(&dev->buf_lock, flags); + } + +diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c +index fc145d202c46..922a750640e8 100644 +--- a/drivers/memstick/core/mspro_block.c ++++ b/drivers/memstick/core/mspro_block.c +@@ -758,7 +758,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error) + + if (error || (card->current_mrq.tpc == MSPRO_CMD_STOP)) { + if (msb->data_dir == READ) { +- for (cnt = 0; cnt < msb->current_seg; cnt++) ++ for (cnt = 0; cnt < msb->current_seg; cnt++) { + t_len += msb->req_sg[cnt].length + / msb->page_size; + +@@ -766,6 +766,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error) + t_len += msb->current_page - 1; + + t_len *= msb->page_size; ++ } + } + } else + t_len = blk_rq_bytes(msb->block_req); +diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c +index 6f27d9a1be3b..21841fe25ad3 100644 +--- a/drivers/mtd/ubi/attach.c ++++ b/drivers/mtd/ubi/attach.c +@@ -408,7 +408,7 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, + second_is_newer = !second_is_newer; + } else { + dbg_bld("PEB %d CRC is OK", pnum); +- bitflips = !!err; ++ bitflips |= !!err; + } + mutex_unlock(&ubi->buf_mutex); + +diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c +index 8ca49f2043e4..4cbbd5531133 100644 +--- a/drivers/mtd/ubi/cdev.c ++++ b/drivers/mtd/ubi/cdev.c +@@ -451,7 +451,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd, + /* Validate the request */ + err = -EINVAL; + if (req.lnum < 0 || req.lnum >= vol->reserved_pebs || +- req.bytes < 0 || req.lnum >= vol->usable_leb_size) ++ req.bytes < 0 || req.bytes > vol->usable_leb_size) + break; + + err = get_exclusive(desc); +diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c +index 0e11671dadc4..930cf2c77abb 100644 +--- a/drivers/mtd/ubi/eba.c ++++ b/drivers/mtd/ubi/eba.c +@@ -1362,7 +1362,8 @@ int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai) + * during re-size. + */ + ubi_move_aeb_to_list(av, aeb, &ai->erase); +- vol->eba_tbl[aeb->lnum] = aeb->pnum; ++ else ++ vol->eba_tbl[aeb->lnum] = aeb->pnum; + } + } + +diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c +index 68b924ec222e..c6b0b078ab99 100644 +--- a/drivers/mtd/ubi/wl.c ++++ b/drivers/mtd/ubi/wl.c +@@ -995,7 +995,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, + int cancel) + { + int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0; +- int vol_id = -1, uninitialized_var(lnum); ++ int vol_id = -1, lnum = -1; + #ifdef CONFIG_MTD_UBI_FASTMAP + int anchor = wrk->anchor; + #endif +diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c +index 46e6544ed1b7..b655fe4f4c2e 100644 +--- a/drivers/net/ethernet/intel/e1000/e1000_main.c ++++ b/drivers/net/ethernet/intel/e1000/e1000_main.c +@@ -144,6 +144,11 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, + static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, + struct e1000_rx_ring *rx_ring, + int *work_done, int work_to_do); ++static void e1000_alloc_dummy_rx_buffers(struct e1000_adapter *adapter, ++ struct e1000_rx_ring *rx_ring, ++ int cleaned_count) ++{ ++} + static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, + struct e1000_rx_ring *rx_ring, + int cleaned_count); +@@ -3531,8 +3536,11 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) + msleep(1); + /* e1000_down has a dependency on max_frame_size */ + hw->max_frame_size = max_frame; +- if (netif_running(netdev)) ++ if (netif_running(netdev)) { ++ /* prevent buffers from being reallocated */ ++ adapter->alloc_rx_buf = e1000_alloc_dummy_rx_buffers; + e1000_down(adapter); ++ } + + /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN + * means we reserve 2 more, this pushes us to allocate from the next +diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +index f58316769159..66c92a16da29 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +@@ -314,6 +314,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { + {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ + {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ + {RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/ ++ {RTL_USB_DEVICE(0x0b05, 0x17ba, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/ + {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/ + {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ + {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ +@@ -370,6 +371,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { + {RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/ + {RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/ + {RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/ ++ {RTL_USB_DEVICE(0x2001, 0x330d, rtl92cu_hal_cfg)}, /*D-Link DWA-131 */ + {RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/ + {RTL_USB_DEVICE(0x20f4, 0x624d, rtl92cu_hal_cfg)}, /*TRENDNet*/ + {RTL_USB_DEVICE(0x2357, 0x0100, rtl92cu_hal_cfg)}, /*TP-Link WN8200ND*/ +diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.c b/drivers/net/wireless/ti/wl18xx/debugfs.c +index 7f1669cdea09..779dc2b2ca75 100644 +--- a/drivers/net/wireless/ti/wl18xx/debugfs.c ++++ b/drivers/net/wireless/ti/wl18xx/debugfs.c +@@ -136,7 +136,7 @@ WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, protection_filter, "%u"); + WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, accum_arp_pend_requests, "%u"); + WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, max_arp_queue_dep, "%u"); + +-WL18XX_DEBUGFS_FWSTATS_FILE(rx_rate, rx_frames_per_rates, "%u"); ++WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(rx_rate, rx_frames_per_rates, 50); + + WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(aggr_size, tx_agg_vs_rate, + AGGR_STATS_TX_AGG*AGGR_STATS_TX_RATE); +diff --git a/drivers/net/wireless/ti/wlcore/debugfs.h b/drivers/net/wireless/ti/wlcore/debugfs.h +index f7381dd69009..1bce4325e86b 100644 +--- a/drivers/net/wireless/ti/wlcore/debugfs.h ++++ b/drivers/net/wireless/ti/wlcore/debugfs.h +@@ -26,8 +26,8 @@ + + #include "wlcore.h" + +-int wl1271_format_buffer(char __user *userbuf, size_t count, +- loff_t *ppos, char *fmt, ...); ++__printf(4, 5) int wl1271_format_buffer(char __user *userbuf, size_t count, ++ loff_t *ppos, char *fmt, ...); + + int wl1271_debugfs_init(struct wl1271 *wl); + void wl1271_debugfs_exit(struct wl1271 *wl); +diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c +index 7297df2ebf50..2d9d1985adc1 100644 +--- a/drivers/platform/x86/compal-laptop.c ++++ b/drivers/platform/x86/compal-laptop.c +@@ -1037,7 +1037,9 @@ static int compal_probe(struct platform_device *pdev) + + /* Power supply */ + initialize_power_supply_data(data); +- power_supply_register(&compal_device->dev, &data->psy); ++ err = power_supply_register(&compal_device->dev, &data->psy); ++ if (err < 0) ++ goto remove; + + platform_set_drvdata(pdev, data); + +diff --git a/drivers/power/lp8788-charger.c b/drivers/power/lp8788-charger.c +index ed49b50b220b..72da2a6c22db 100644 +--- a/drivers/power/lp8788-charger.c ++++ b/drivers/power/lp8788-charger.c +@@ -417,8 +417,10 @@ static int lp8788_psy_register(struct platform_device *pdev, + pchg->battery.num_properties = ARRAY_SIZE(lp8788_battery_prop); + pchg->battery.get_property = lp8788_battery_get_property; + +- if (power_supply_register(&pdev->dev, &pchg->battery)) ++ if (power_supply_register(&pdev->dev, &pchg->battery)) { ++ power_supply_unregister(&pchg->charger); + return -EPERM; ++ } + + return 0; + } +diff --git a/drivers/power/twl4030_madc_battery.c b/drivers/power/twl4030_madc_battery.c +index 7ef445a6cfa6..cf907609ec49 100644 +--- a/drivers/power/twl4030_madc_battery.c ++++ b/drivers/power/twl4030_madc_battery.c +@@ -192,6 +192,7 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev) + { + struct twl4030_madc_battery *twl4030_madc_bat; + struct twl4030_madc_bat_platform_data *pdata = pdev->dev.platform_data; ++ int ret = 0; + + twl4030_madc_bat = kzalloc(sizeof(*twl4030_madc_bat), GFP_KERNEL); + if (!twl4030_madc_bat) +@@ -216,9 +217,11 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev) + + twl4030_madc_bat->pdata = pdata; + platform_set_drvdata(pdev, twl4030_madc_bat); +- power_supply_register(&pdev->dev, &twl4030_madc_bat->psy); ++ ret = power_supply_register(&pdev->dev, &twl4030_madc_bat->psy); ++ if (ret < 0) ++ kfree(twl4030_madc_bat); + +- return 0; ++ return ret; + } + + static int twl4030_madc_battery_remove(struct platform_device *pdev) +diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c +index 65180e15de6e..50c75e1fbf8a 100644 +--- a/drivers/scsi/bfa/bfa_ioc.c ++++ b/drivers/scsi/bfa/bfa_ioc.c +@@ -7006,7 +7006,7 @@ bfa_flash_sem_get(void __iomem *bar) + while (!bfa_raw_sem_get(bar)) { + if (--n <= 0) + return BFA_STATUS_BADFLASH; +- udelay(10000); ++ mdelay(10); + } + return BFA_STATUS_OK; + } +diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c +index 6c1f223a8e1d..4c0b8b4e1d40 100644 +--- a/drivers/scsi/mvsas/mv_sas.c ++++ b/drivers/scsi/mvsas/mv_sas.c +@@ -441,14 +441,11 @@ static u32 mvs_get_ncq_tag(struct sas_task *task, u32 *tag) + static int mvs_task_prep_ata(struct mvs_info *mvi, + struct mvs_task_exec_info *tei) + { +- struct sas_ha_struct *sha = mvi->sas; + struct sas_task *task = tei->task; + struct domain_device *dev = task->dev; + struct mvs_device *mvi_dev = dev->lldd_dev; + struct mvs_cmd_hdr *hdr = tei->hdr; + struct asd_sas_port *sas_port = dev->port; +- struct sas_phy *sphy = dev->phy; +- struct asd_sas_phy *sas_phy = sha->sas_phy[sphy->number]; + struct mvs_slot_info *slot; + void *buf_prd; + u32 tag = tei->tag, hdr_tag; +@@ -468,7 +465,7 @@ static int mvs_task_prep_ata(struct mvs_info *mvi, + slot->tx = mvi->tx_prod; + del_q = TXQ_MODE_I | tag | + (TXQ_CMD_STP << TXQ_CMD_SHIFT) | +- (MVS_PHY_ID << TXQ_PHY_SHIFT) | ++ ((sas_port->phy_mask & TXQ_PHY_MASK) << TXQ_PHY_SHIFT) | + (mvi_dev->taskfileset << TXQ_SRS_SHIFT); + mvi->tx[mvi->tx_prod] = cpu_to_le32(del_q); + +diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c +index 86b05151fdab..97892f258043 100644 +--- a/drivers/scsi/storvsc_drv.c ++++ b/drivers/scsi/storvsc_drv.c +@@ -739,21 +739,22 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, + if (bounce_sgl[j].length == PAGE_SIZE) { + /* full..move to next entry */ + sg_kunmap_atomic(bounce_addr); ++ bounce_addr = 0; + j++; ++ } + +- /* if we need to use another bounce buffer */ +- if (srclen || i != orig_sgl_count - 1) +- bounce_addr = sg_kmap_atomic(bounce_sgl,j); ++ /* if we need to use another bounce buffer */ ++ if (srclen && bounce_addr == 0) ++ bounce_addr = sg_kmap_atomic(bounce_sgl, j); + +- } else if (srclen == 0 && i == orig_sgl_count - 1) { +- /* unmap the last bounce that is < PAGE_SIZE */ +- sg_kunmap_atomic(bounce_addr); +- } + } + + sg_kunmap_atomic(src_addr - orig_sgl[i].offset); + } + ++ if (bounce_addr) ++ sg_kunmap_atomic(bounce_addr); ++ + local_irq_restore(flags); + + return total_copied; +diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c +index d7c6e36021e8..2fe5b61d886a 100644 +--- a/drivers/spi/spidev.c ++++ b/drivers/spi/spidev.c +@@ -243,7 +243,10 @@ static int spidev_message(struct spidev_data *spidev, + k_tmp->len = u_tmp->len; + + total += k_tmp->len; +- if (total > bufsiz) { ++ /* Check total length of transfers. Also check each ++ * transfer length to avoid arithmetic overflow. ++ */ ++ if (total > bufsiz || k_tmp->len > bufsiz) { + status = -EMSGSIZE; + goto done; + } +diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c +index 41eff7d64cb8..b199f1e21d0e 100644 +--- a/drivers/target/target_core_file.c ++++ b/drivers/target/target_core_file.c +@@ -263,40 +263,32 @@ static int fd_do_prot_rw(struct se_cmd *cmd, struct fd_prot *fd_prot, + struct se_device *se_dev = cmd->se_dev; + struct fd_dev *dev = FD_DEV(se_dev); + struct file *prot_fd = dev->fd_prot_file; +- struct scatterlist *sg; + loff_t pos = (cmd->t_task_lba * se_dev->prot_length); + unsigned char *buf; +- u32 prot_size, len, size; +- int rc, ret = 1, i; ++ u32 prot_size; ++ int rc, ret = 1; + + prot_size = (cmd->data_length / se_dev->dev_attrib.block_size) * + se_dev->prot_length; + + if (!is_write) { +- fd_prot->prot_buf = vzalloc(prot_size); ++ fd_prot->prot_buf = kzalloc(prot_size, GFP_KERNEL); + if (!fd_prot->prot_buf) { + pr_err("Unable to allocate fd_prot->prot_buf\n"); + return -ENOMEM; + } + buf = fd_prot->prot_buf; + +- fd_prot->prot_sg_nents = cmd->t_prot_nents; +- fd_prot->prot_sg = kzalloc(sizeof(struct scatterlist) * +- fd_prot->prot_sg_nents, GFP_KERNEL); ++ fd_prot->prot_sg_nents = 1; ++ fd_prot->prot_sg = kzalloc(sizeof(struct scatterlist), ++ GFP_KERNEL); + if (!fd_prot->prot_sg) { + pr_err("Unable to allocate fd_prot->prot_sg\n"); +- vfree(fd_prot->prot_buf); ++ kfree(fd_prot->prot_buf); + return -ENOMEM; + } +- size = prot_size; +- +- for_each_sg(fd_prot->prot_sg, sg, fd_prot->prot_sg_nents, i) { +- +- len = min_t(u32, PAGE_SIZE, size); +- sg_set_buf(sg, buf, len); +- size -= len; +- buf += len; +- } ++ sg_init_table(fd_prot->prot_sg, fd_prot->prot_sg_nents); ++ sg_set_buf(fd_prot->prot_sg, buf, prot_size); + } + + if (is_write) { +@@ -317,7 +309,7 @@ static int fd_do_prot_rw(struct se_cmd *cmd, struct fd_prot *fd_prot, + + if (is_write || ret < 0) { + kfree(fd_prot->prot_sg); +- vfree(fd_prot->prot_buf); ++ kfree(fd_prot->prot_buf); + } + + return ret; +@@ -652,11 +644,11 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, + 0, fd_prot.prot_sg, 0); + if (rc) { + kfree(fd_prot.prot_sg); +- vfree(fd_prot.prot_buf); ++ kfree(fd_prot.prot_buf); + return rc; + } + kfree(fd_prot.prot_sg); +- vfree(fd_prot.prot_buf); ++ kfree(fd_prot.prot_buf); + } + } else { + memset(&fd_prot, 0, sizeof(struct fd_prot)); +@@ -672,7 +664,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, + 0, fd_prot.prot_sg, 0); + if (rc) { + kfree(fd_prot.prot_sg); +- vfree(fd_prot.prot_buf); ++ kfree(fd_prot.prot_buf); + return rc; + } + } +@@ -703,7 +695,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, + + if (ret < 0) { + kfree(fd_prot.prot_sg); +- vfree(fd_prot.prot_buf); ++ kfree(fd_prot.prot_buf); + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + +diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c +index 68511e83486b..f89b24a09b19 100644 +--- a/drivers/target/target_core_sbc.c ++++ b/drivers/target/target_core_sbc.c +@@ -314,7 +314,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o + return 0; + } + +-static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd) ++static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd, bool success) + { + unsigned char *buf, *addr; + struct scatterlist *sg; +@@ -378,7 +378,7 @@ sbc_execute_rw(struct se_cmd *cmd) + cmd->data_direction); + } + +-static sense_reason_t compare_and_write_post(struct se_cmd *cmd) ++static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success) + { + struct se_device *dev = cmd->se_dev; + +@@ -401,7 +401,7 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd) + return TCM_NO_SENSE; + } + +-static sense_reason_t compare_and_write_callback(struct se_cmd *cmd) ++static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool success) + { + struct se_device *dev = cmd->se_dev; + struct scatterlist *write_sg = NULL, *sg; +@@ -416,11 +416,16 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd) + + /* + * Handle early failure in transport_generic_request_failure(), +- * which will not have taken ->caw_mutex yet.. ++ * which will not have taken ->caw_sem yet.. + */ +- if (!cmd->t_data_sg || !cmd->t_bidi_data_sg) ++ if (!success && (!cmd->t_data_sg || !cmd->t_bidi_data_sg)) + return TCM_NO_SENSE; + /* ++ * Handle special case for zero-length COMPARE_AND_WRITE ++ */ ++ if (!cmd->data_length) ++ goto out; ++ /* + * Immediately exit + release dev->caw_sem if command has already + * been failed with a non-zero SCSI status. + */ +diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c +index 9e54c0fe718d..6fc38903046c 100644 +--- a/drivers/target/target_core_transport.c ++++ b/drivers/target/target_core_transport.c +@@ -1600,11 +1600,11 @@ void transport_generic_request_failure(struct se_cmd *cmd, + transport_complete_task_attr(cmd); + /* + * Handle special case for COMPARE_AND_WRITE failure, where the +- * callback is expected to drop the per device ->caw_mutex. ++ * callback is expected to drop the per device ->caw_sem. + */ + if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) && + cmd->transport_complete_callback) +- cmd->transport_complete_callback(cmd); ++ cmd->transport_complete_callback(cmd, false); + + switch (sense_reason) { + case TCM_NON_EXISTENT_LUN: +@@ -1941,8 +1941,12 @@ static void target_complete_ok_work(struct work_struct *work) + if (cmd->transport_complete_callback) { + sense_reason_t rc; + +- rc = cmd->transport_complete_callback(cmd); ++ rc = cmd->transport_complete_callback(cmd, true); + if (!rc && !(cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE_POST)) { ++ if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) && ++ !cmd->data_length) ++ goto queue_rsp; ++ + return; + } else if (rc) { + ret = transport_send_check_condition_and_sense(cmd, +@@ -1956,6 +1960,7 @@ static void target_complete_ok_work(struct work_struct *work) + } + } + ++queue_rsp: + switch (cmd->data_direction) { + case DMA_FROM_DEVICE: + spin_lock(&cmd->se_lun->lun_sep_lock); +@@ -2044,6 +2049,16 @@ static inline void transport_reset_sgl_orig(struct se_cmd *cmd) + static inline void transport_free_pages(struct se_cmd *cmd) + { + if (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) { ++ /* ++ * Release special case READ buffer payload required for ++ * SG_TO_MEM_NOALLOC to function with COMPARE_AND_WRITE ++ */ ++ if (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) { ++ transport_free_sgl(cmd->t_bidi_data_sg, ++ cmd->t_bidi_data_nents); ++ cmd->t_bidi_data_sg = NULL; ++ cmd->t_bidi_data_nents = 0; ++ } + transport_reset_sgl_orig(cmd); + return; + } +@@ -2192,6 +2207,7 @@ sense_reason_t + transport_generic_new_cmd(struct se_cmd *cmd) + { + int ret = 0; ++ bool zero_flag = !(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB); + + /* + * Determine is the TCM fabric module has already allocated physical +@@ -2200,7 +2216,6 @@ transport_generic_new_cmd(struct se_cmd *cmd) + */ + if (!(cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) && + cmd->data_length) { +- bool zero_flag = !(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB); + + if ((cmd->se_cmd_flags & SCF_BIDI) || + (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE)) { +@@ -2223,6 +2238,20 @@ transport_generic_new_cmd(struct se_cmd *cmd) + cmd->data_length, zero_flag); + if (ret < 0) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; ++ } else if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) && ++ cmd->data_length) { ++ /* ++ * Special case for COMPARE_AND_WRITE with fabrics ++ * using SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC. ++ */ ++ u32 caw_length = cmd->t_task_nolb * ++ cmd->se_dev->dev_attrib.block_size; ++ ++ ret = target_alloc_sgl(&cmd->t_bidi_data_sg, ++ &cmd->t_bidi_data_nents, ++ caw_length, zero_flag); ++ if (ret < 0) ++ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + /* + * If this command is not a write we can execute it right here, +diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c +index a051a7a2b1bd..a81f9dd7ee97 100644 +--- a/drivers/usb/class/cdc-wdm.c ++++ b/drivers/usb/class/cdc-wdm.c +@@ -245,7 +245,7 @@ static void wdm_int_callback(struct urb *urb) + case USB_CDC_NOTIFY_RESPONSE_AVAILABLE: + dev_dbg(&desc->intf->dev, + "NOTIFY_RESPONSE_AVAILABLE received: index %d len %d", +- dr->wIndex, dr->wLength); ++ le16_to_cpu(dr->wIndex), le16_to_cpu(dr->wLength)); + break; + + case USB_CDC_NOTIFY_NETWORK_CONNECTION: +@@ -262,7 +262,9 @@ static void wdm_int_callback(struct urb *urb) + clear_bit(WDM_POLL_RUNNING, &desc->flags); + dev_err(&desc->intf->dev, + "unknown notification %d received: index %d len %d\n", +- dr->bNotificationType, dr->wIndex, dr->wLength); ++ dr->bNotificationType, ++ le16_to_cpu(dr->wIndex), ++ le16_to_cpu(dr->wLength)); + goto exit; + } + +@@ -408,7 +410,7 @@ static ssize_t wdm_write + USB_RECIP_INTERFACE); + req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND; + req->wValue = 0; +- req->wIndex = desc->inum; ++ req->wIndex = desc->inum; /* already converted */ + req->wLength = cpu_to_le16(count); + set_bit(WDM_IN_USE, &desc->flags); + desc->outbuf = buf; +@@ -422,7 +424,7 @@ static ssize_t wdm_write + rv = usb_translate_errors(rv); + } else { + dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d", +- req->wIndex); ++ le16_to_cpu(req->wIndex)); + } + out: + usb_autopm_put_interface(desc->intf); +@@ -820,7 +822,7 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor + desc->irq->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE); + desc->irq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE; + desc->irq->wValue = 0; +- desc->irq->wIndex = desc->inum; ++ desc->irq->wIndex = desc->inum; /* already converted */ + desc->irq->wLength = cpu_to_le16(desc->wMaxCommand); + + usb_fill_control_urb( +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index d2bd9d7c8f4b..1847a7d38026 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -3289,10 +3289,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) + dev_dbg(hub->intfdev, "can't resume port %d, status %d\n", + port1, status); + } else { +- /* drive resume for at least 20 msec */ ++ /* drive resume for USB_RESUME_TIMEOUT msec */ + dev_dbg(&udev->dev, "usb %sresume\n", + (PMSG_IS_AUTO(msg) ? "auto-" : "")); +- msleep(25); ++ msleep(USB_RESUME_TIMEOUT); + + /* Virtual root hubs can trigger on GET_PORT_STATUS to + * stop resume signaling. Then finish the resume +diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c +index 4d918ed8d343..0f9980088c08 100644 +--- a/drivers/usb/dwc2/hcd.c ++++ b/drivers/usb/dwc2/hcd.c +@@ -1501,7 +1501,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, + dev_dbg(hsotg->dev, + "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); + writel(0, hsotg->regs + PCGCTL); +- usleep_range(20000, 40000); ++ msleep(USB_RESUME_TIMEOUT); + + hprt0 = dwc2_read_hprt0(hsotg); + hprt0 |= HPRT0_RES; +diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c +index d742bed7a5fa..82df926c765d 100644 +--- a/drivers/usb/gadget/composite.c ++++ b/drivers/usb/gadget/composite.c +@@ -528,7 +528,7 @@ static int bos_desc(struct usb_composite_dev *cdev) + usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE; + usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY; + usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT; +- usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT); ++ usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT | USB_BESL_SUPPORT); + + /* + * The Superspeed USB Capability descriptor shall be implemented by all +diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c +index 98a89d16cc3e..8aa4ba0a0c69 100644 +--- a/drivers/usb/host/fotg210-hcd.c ++++ b/drivers/usb/host/fotg210-hcd.c +@@ -1595,7 +1595,7 @@ static int fotg210_hub_control( + /* resume signaling for 20 msec */ + fotg210_writel(fotg210, temp | PORT_RESUME, status_reg); + fotg210->reset_done[wIndex] = jiffies +- + msecs_to_jiffies(20); ++ + msecs_to_jiffies(USB_RESUME_TIMEOUT); + break; + case USB_PORT_FEAT_C_SUSPEND: + clear_bit(wIndex, &fotg210->port_c_suspend); +diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c +index ba9499060f63..3e3926aa584e 100644 +--- a/drivers/usb/host/fusbh200-hcd.c ++++ b/drivers/usb/host/fusbh200-hcd.c +@@ -1550,10 +1550,9 @@ static int fusbh200_hub_control ( + if ((temp & PORT_PE) == 0) + goto error; + +- /* resume signaling for 20 msec */ + fusbh200_writel(fusbh200, temp | PORT_RESUME, status_reg); + fusbh200->reset_done[wIndex] = jiffies +- + msecs_to_jiffies(20); ++ + msecs_to_jiffies(USB_RESUME_TIMEOUT); + break; + case USB_PORT_FEAT_C_SUSPEND: + clear_bit(wIndex, &fusbh200->port_c_suspend); +diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c +index 240e792c81a7..b62298fe0be8 100644 +--- a/drivers/usb/host/isp116x-hcd.c ++++ b/drivers/usb/host/isp116x-hcd.c +@@ -1487,7 +1487,7 @@ static int isp116x_bus_resume(struct usb_hcd *hcd) + spin_unlock_irq(&isp116x->lock); + + hcd->state = HC_STATE_RESUMING; +- msleep(20); ++ msleep(USB_RESUME_TIMEOUT); + + /* Go operational */ + spin_lock_irq(&isp116x->lock); +diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c +index 110b4b9ebeaa..f130bb2f7bbe 100644 +--- a/drivers/usb/host/r8a66597-hcd.c ++++ b/drivers/usb/host/r8a66597-hcd.c +@@ -2300,7 +2300,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd) + rh->port &= ~USB_PORT_STAT_SUSPEND; + rh->port |= USB_PORT_STAT_C_SUSPEND << 16; + r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg); +- msleep(50); ++ msleep(USB_RESUME_TIMEOUT); + r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg); + } + +diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c +index a517151867af..0f53cc8c8ecf 100644 +--- a/drivers/usb/host/sl811-hcd.c ++++ b/drivers/usb/host/sl811-hcd.c +@@ -1259,7 +1259,7 @@ sl811h_hub_control( + sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); + + mod_timer(&sl811->timer, jiffies +- + msecs_to_jiffies(20)); ++ + msecs_to_jiffies(USB_RESUME_TIMEOUT)); + break; + case USB_PORT_FEAT_POWER: + port_power(sl811, 0); +diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c +index 93e17b12fb33..98c66d88ebde 100644 +--- a/drivers/usb/host/uhci-hub.c ++++ b/drivers/usb/host/uhci-hub.c +@@ -165,7 +165,7 @@ static void uhci_check_ports(struct uhci_hcd *uhci) + /* Port received a wakeup request */ + set_bit(port, &uhci->resuming_ports); + uhci->ports_timeout = jiffies + +- msecs_to_jiffies(25); ++ msecs_to_jiffies(USB_RESUME_TIMEOUT); + usb_hcd_start_port_resume( + &uhci_to_hcd(uhci)->self, port); + +@@ -337,7 +337,8 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + uhci_finish_suspend(uhci, port, port_addr); + + /* USB v2.0 7.1.7.5 */ +- uhci->ports_timeout = jiffies + msecs_to_jiffies(50); ++ uhci->ports_timeout = jiffies + ++ msecs_to_jiffies(USB_RESUME_TIMEOUT); + break; + case USB_PORT_FEAT_POWER: + /* UHCI has no power switching */ +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index a95eee8ddc38..05185b9d4495 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1768,7 +1768,7 @@ static void handle_port_status(struct xhci_hcd *xhci, + } else { + xhci_dbg(xhci, "resume HS port %d\n", port_id); + bus_state->resume_done[faked_port_index] = jiffies + +- msecs_to_jiffies(20); ++ msecs_to_jiffies(USB_RESUME_TIMEOUT); + set_bit(faked_port_index, &bus_state->resuming_ports); + mod_timer(&hcd->rh_timer, + bus_state->resume_done[faked_port_index]); +diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c +index 0180eef05656..964ebafe8b44 100644 +--- a/drivers/usb/phy/phy.c ++++ b/drivers/usb/phy/phy.c +@@ -78,7 +78,9 @@ static void devm_usb_phy_release(struct device *dev, void *res) + + static int devm_usb_phy_match(struct device *dev, void *res, void *match_data) + { +- return res == match_data; ++ struct usb_phy **phy = res; ++ ++ return *phy == match_data; + } + + /** +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index f4d7b2fc9ffb..78f46089a077 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -751,6 +751,7 @@ static int load_elf_binary(struct linux_binprm *bprm) + i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { + int elf_prot = 0, elf_flags; + unsigned long k, vaddr; ++ unsigned long total_size = 0; + + if (elf_ppnt->p_type != PT_LOAD) + continue; +@@ -815,10 +816,16 @@ static int load_elf_binary(struct linux_binprm *bprm) + #else + load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); + #endif ++ total_size = total_mapping_size(elf_phdata, ++ loc->elf_ex.e_phnum); ++ if (!total_size) { ++ error = -EINVAL; ++ goto out_free_dentry; ++ } + } + + error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, +- elf_prot, elf_flags, 0); ++ elf_prot, elf_flags, total_size); + if (BAD_ADDR(error)) { + send_sig(SIGKILL, current, 0); + retval = IS_ERR((void *)error) ? +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index d2f1c011d73a..794d7c6ea9ee 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -6645,12 +6645,11 @@ static int __btrfs_free_reserved_extent(struct btrfs_root *root, + return -ENOSPC; + } + +- if (btrfs_test_opt(root, DISCARD)) +- ret = btrfs_discard_extent(root, start, len, NULL); +- + if (pin) + pin_down_extent(root, cache, start, len, 1); + else { ++ if (btrfs_test_opt(root, DISCARD)) ++ ret = btrfs_discard_extent(root, start, len, NULL); + btrfs_add_free_space(cache, start, len); + btrfs_update_reserved_bytes(cache, len, RESERVE_FREE); + } +diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c +index 0b72006aecbe..3e16042338e4 100644 +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -2708,6 +2708,9 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 len, + if (src == dst) + return -EINVAL; + ++ if (len == 0) ++ return 0; ++ + btrfs_double_lock(src, loff, dst, dst_loff, len); + + ret = extent_same_check_offsets(src, loff, len); +@@ -3226,6 +3229,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, + if (off + len == src->i_size) + len = ALIGN(src->i_size, bs) - off; + ++ if (len == 0) { ++ ret = 0; ++ goto out_unlock; ++ } ++ + /* verify the end result is block aligned */ + if (!IS_ALIGNED(off, bs) || !IS_ALIGNED(off + len, bs) || + !IS_ALIGNED(destoff, bs)) +diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c +index ad8328d797ea..488e987c3374 100644 +--- a/fs/btrfs/xattr.c ++++ b/fs/btrfs/xattr.c +@@ -324,22 +324,42 @@ const struct xattr_handler *btrfs_xattr_handlers[] = { + /* + * Check if the attribute is in a supported namespace. + * +- * This applied after the check for the synthetic attributes in the system ++ * This is applied after the check for the synthetic attributes in the system + * namespace. + */ +-static bool btrfs_is_valid_xattr(const char *name) ++static int btrfs_is_valid_xattr(const char *name) + { +- return !strncmp(name, XATTR_SECURITY_PREFIX, +- XATTR_SECURITY_PREFIX_LEN) || +- !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) || +- !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) || +- !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) || +- !strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN); ++ int len = strlen(name); ++ int prefixlen = 0; ++ ++ if (!strncmp(name, XATTR_SECURITY_PREFIX, ++ XATTR_SECURITY_PREFIX_LEN)) ++ prefixlen = XATTR_SECURITY_PREFIX_LEN; ++ else if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) ++ prefixlen = XATTR_SYSTEM_PREFIX_LEN; ++ else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) ++ prefixlen = XATTR_TRUSTED_PREFIX_LEN; ++ else if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) ++ prefixlen = XATTR_USER_PREFIX_LEN; ++ else if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN)) ++ prefixlen = XATTR_BTRFS_PREFIX_LEN; ++ else ++ return -EOPNOTSUPP; ++ ++ /* ++ * The name cannot consist of just prefix ++ */ ++ if (len <= prefixlen) ++ return -EINVAL; ++ ++ return 0; + } + + ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, + void *buffer, size_t size) + { ++ int ret; ++ + /* + * If this is a request for a synthetic attribute in the system.* + * namespace use the generic infrastructure to resolve a handler +@@ -348,8 +368,9 @@ ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, + if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) + return generic_getxattr(dentry, name, buffer, size); + +- if (!btrfs_is_valid_xattr(name)) +- return -EOPNOTSUPP; ++ ret = btrfs_is_valid_xattr(name); ++ if (ret) ++ return ret; + return __btrfs_getxattr(dentry->d_inode, name, buffer, size); + } + +@@ -357,6 +378,7 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, + size_t size, int flags) + { + struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root; ++ int ret; + + /* + * The permission on security.* and system.* is not checked +@@ -373,8 +395,9 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, + if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) + return generic_setxattr(dentry, name, value, size, flags); + +- if (!btrfs_is_valid_xattr(name)) +- return -EOPNOTSUPP; ++ ret = btrfs_is_valid_xattr(name); ++ if (ret) ++ return ret; + + if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN)) + return btrfs_set_prop(dentry->d_inode, name, +@@ -390,6 +413,7 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, + int btrfs_removexattr(struct dentry *dentry, const char *name) + { + struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root; ++ int ret; + + /* + * The permission on security.* and system.* is not checked +@@ -406,8 +430,9 @@ int btrfs_removexattr(struct dentry *dentry, const char *name) + if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) + return generic_removexattr(dentry, name); + +- if (!btrfs_is_valid_xattr(name)) +- return -EOPNOTSUPP; ++ ret = btrfs_is_valid_xattr(name); ++ if (ret) ++ return ret; + + if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN)) + return btrfs_set_prop(dentry->d_inode, name, +diff --git a/fs/exec.c b/fs/exec.c +index ea4449d0536a..05f1942d7edb 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1268,6 +1268,53 @@ static void check_unsafe_exec(struct linux_binprm *bprm) + spin_unlock(&p->fs->lock); + } + ++static void bprm_fill_uid(struct linux_binprm *bprm) ++{ ++ struct inode *inode; ++ unsigned int mode; ++ kuid_t uid; ++ kgid_t gid; ++ ++ /* clear any previous set[ug]id data from a previous binary */ ++ bprm->cred->euid = current_euid(); ++ bprm->cred->egid = current_egid(); ++ ++ if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ++ return; ++ ++ if (current->no_new_privs) ++ return; ++ ++ inode = file_inode(bprm->file); ++ mode = ACCESS_ONCE(inode->i_mode); ++ if (!(mode & (S_ISUID|S_ISGID))) ++ return; ++ ++ /* Be careful if suid/sgid is set */ ++ mutex_lock(&inode->i_mutex); ++ ++ /* reload atomically mode/uid/gid now that lock held */ ++ mode = inode->i_mode; ++ uid = inode->i_uid; ++ gid = inode->i_gid; ++ mutex_unlock(&inode->i_mutex); ++ ++ /* We ignore suid/sgid if there are no mappings for them in the ns */ ++ if (!kuid_has_mapping(bprm->cred->user_ns, uid) || ++ !kgid_has_mapping(bprm->cred->user_ns, gid)) ++ return; ++ ++ if (mode & S_ISUID) { ++ bprm->per_clear |= PER_CLEAR_ON_SETID; ++ bprm->cred->euid = uid; ++ } ++ ++ if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { ++ bprm->per_clear |= PER_CLEAR_ON_SETID; ++ bprm->cred->egid = gid; ++ } ++} ++ + /* + * Fill the binprm structure from the inode. + * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes +@@ -1276,36 +1323,9 @@ static void check_unsafe_exec(struct linux_binprm *bprm) + */ + int prepare_binprm(struct linux_binprm *bprm) + { +- struct inode *inode = file_inode(bprm->file); +- umode_t mode = inode->i_mode; + int retval; + +- +- /* clear any previous set[ug]id data from a previous binary */ +- bprm->cred->euid = current_euid(); +- bprm->cred->egid = current_egid(); +- +- if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) && +- !current->no_new_privs && +- kuid_has_mapping(bprm->cred->user_ns, inode->i_uid) && +- kgid_has_mapping(bprm->cred->user_ns, inode->i_gid)) { +- /* Set-uid? */ +- if (mode & S_ISUID) { +- bprm->per_clear |= PER_CLEAR_ON_SETID; +- bprm->cred->euid = inode->i_uid; +- } +- +- /* Set-gid? */ +- /* +- * If setgid is set but no group execute bit then this +- * is a candidate for mandatory locking, not a setgid +- * executable. +- */ +- if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { +- bprm->per_clear |= PER_CLEAR_ON_SETID; +- bprm->cred->egid = inode->i_gid; +- } +- } ++ bprm_fill_uid(bprm); + + /* fill in binprm security blob */ + retval = security_bprm_set_creds(bprm); +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index 2dcbfb6245d8..bc7e37bc0c5b 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -1869,7 +1869,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, + struct inode *inode) + { + struct inode *dir = dentry->d_parent->d_inode; +- struct buffer_head *bh; ++ struct buffer_head *bh = NULL; + struct ext4_dir_entry_2 *de; + struct ext4_dir_entry_tail *t; + struct super_block *sb; +@@ -1893,14 +1893,14 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, + return retval; + if (retval == 1) { + retval = 0; +- return retval; ++ goto out; + } + } + + if (is_dx(dir)) { + retval = ext4_dx_add_entry(handle, dentry, inode); + if (!retval || (retval != ERR_BAD_DX_DIR)) +- return retval; ++ goto out; + ext4_clear_inode_flag(dir, EXT4_INODE_INDEX); + dx_fallback++; + ext4_mark_inode_dirty(handle, dir); +@@ -1912,14 +1912,15 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, + return PTR_ERR(bh); + + retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh); +- if (retval != -ENOSPC) { +- brelse(bh); +- return retval; +- } ++ if (retval != -ENOSPC) ++ goto out; + + if (blocks == 1 && !dx_fallback && +- EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) +- return make_indexed_dir(handle, dentry, inode, bh); ++ EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) { ++ retval = make_indexed_dir(handle, dentry, inode, bh); ++ bh = NULL; /* make_indexed_dir releases bh */ ++ goto out; ++ } + brelse(bh); + } + bh = ext4_append(handle, dir, &block); +@@ -1935,6 +1936,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, + } + + retval = add_dirent_to_buf(handle, dentry, inode, de, bh); ++out: + brelse(bh); + if (retval == 0) + ext4_set_inode_state(inode, EXT4_STATE_NEWENTRY); +diff --git a/fs/namei.c b/fs/namei.c +index 0dd72c8e65fd..ccb8000f3459 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -1545,7 +1545,8 @@ static inline int walk_component(struct nameidata *nd, struct path *path, + + if (should_follow_link(path->dentry, follow)) { + if (nd->flags & LOOKUP_RCU) { +- if (unlikely(unlazy_walk(nd, path->dentry))) { ++ if (unlikely(nd->path.mnt != path->mnt || ++ unlazy_walk(nd, path->dentry))) { + err = -ECHILD; + goto out_err; + } +@@ -2992,7 +2993,8 @@ finish_lookup: + + if (should_follow_link(path->dentry, !symlink_ok)) { + if (nd->flags & LOOKUP_RCU) { +- if (unlikely(unlazy_walk(nd, path->dentry))) { ++ if (unlikely(nd->path.mnt != path->mnt || ++ unlazy_walk(nd, path->dentry))) { + error = -ECHILD; + goto out; + } +diff --git a/fs/open.c b/fs/open.c +index 2ed7325f713e..17679f2b2f1c 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -539,6 +539,7 @@ static int chown_common(struct path *path, uid_t user, gid_t group) + uid = make_kuid(current_user_ns(), user); + gid = make_kgid(current_user_ns(), group); + ++retry_deleg: + newattrs.ia_valid = ATTR_CTIME; + if (user != (uid_t) -1) { + if (!uid_valid(uid)) +@@ -555,7 +556,6 @@ static int chown_common(struct path *path, uid_t user, gid_t group) + if (!S_ISDIR(inode->i_mode)) + newattrs.ia_valid |= + ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; +-retry_deleg: + mutex_lock(&inode->i_mutex); + error = security_path_chown(path, uid, gid); + if (!error) +diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h +index 68a3ada689c9..8fc12f80b616 100644 +--- a/include/acpi/actypes.h ++++ b/include/acpi/actypes.h +@@ -198,9 +198,29 @@ typedef int INT32; + typedef s32 acpi_native_int; + + typedef u32 acpi_size; ++ ++#ifdef ACPI_32BIT_PHYSICAL_ADDRESS ++ ++/* ++ * OSPMs can define this to shrink the size of the structures for 32-bit ++ * none PAE environment. ASL compiler may always define this to generate ++ * 32-bit OSPM compliant tables. ++ */ + typedef u32 acpi_io_address; + typedef u32 acpi_physical_address; + ++#else /* ACPI_32BIT_PHYSICAL_ADDRESS */ ++ ++/* ++ * It is reported that, after some calculations, the physical addresses can ++ * wrap over the 32-bit boundary on 32-bit PAE environment. ++ * https://bugzilla.kernel.org/show_bug.cgi?id=87971 ++ */ ++typedef u64 acpi_io_address; ++typedef u64 acpi_physical_address; ++ ++#endif /* ACPI_32BIT_PHYSICAL_ADDRESS */ ++ + #define ACPI_MAX_PTR ACPI_UINT32_MAX + #define ACPI_SIZE_MAX ACPI_UINT32_MAX + +diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h +index b402eb67af83..579912c7156c 100644 +--- a/include/acpi/platform/acenv.h ++++ b/include/acpi/platform/acenv.h +@@ -76,6 +76,7 @@ + #define ACPI_LARGE_NAMESPACE_NODE + #define ACPI_DATA_TABLE_DISASSEMBLY + #define ACPI_SINGLE_THREADED ++#define ACPI_32BIT_PHYSICAL_ADDRESS + #endif + + /* acpi_exec configuration. Multithreaded with full AML debugger */ +diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h +index f1a24b5c3b90..b58fd667f87b 100644 +--- a/include/asm-generic/sections.h ++++ b/include/asm-generic/sections.h +@@ -3,6 +3,8 @@ + + /* References to section boundaries */ + ++#include ++ + /* + * Usage guidelines: + * _text, _data: architecture specific, don't use them in arch-independent code +@@ -37,6 +39,8 @@ extern char __start_rodata[], __end_rodata[]; + /* Start and end of .ctors section - used for constructor calls. */ + extern char __ctors_start[], __ctors_end[]; + ++extern __visible const void __nosave_begin, __nosave_end; ++ + /* function descriptor handling (if any). Override + * in asm/sections.h */ + #ifndef dereference_function_descriptor +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index ad8f85908a56..ab3133797ff7 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -661,6 +661,7 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, + + struct sk_buff *__alloc_skb(unsigned int size, gfp_t priority, int flags, + int node); ++struct sk_buff *__build_skb(void *data, unsigned int frag_size); + struct sk_buff *build_skb(void *data, unsigned int frag_size); + static inline struct sk_buff *alloc_skb(unsigned int size, + gfp_t priority) +diff --git a/include/linux/usb.h b/include/linux/usb.h +index 7f6eb859873e..49466beab90d 100644 +--- a/include/linux/usb.h ++++ b/include/linux/usb.h +@@ -206,6 +206,32 @@ void usb_put_intf(struct usb_interface *intf); + #define USB_MAXINTERFACES 32 + #define USB_MAXIADS (USB_MAXINTERFACES/2) + ++/* ++ * USB Resume Timer: Every Host controller driver should drive the resume ++ * signalling on the bus for the amount of time defined by this macro. ++ * ++ * That way we will have a 'stable' behavior among all HCDs supported by Linux. ++ * ++ * Note that the USB Specification states we should drive resume for *at least* ++ * 20 ms, but it doesn't give an upper bound. This creates two possible ++ * situations which we want to avoid: ++ * ++ * (a) sometimes an msleep(20) might expire slightly before 20 ms, which causes ++ * us to fail USB Electrical Tests, thus failing Certification ++ * ++ * (b) Some (many) devices actually need more than 20 ms of resume signalling, ++ * and while we can argue that's against the USB Specification, we don't have ++ * control over which devices a certification laboratory will be using for ++ * certification. If CertLab uses a device which was tested against Windows and ++ * that happens to have relaxed resume signalling rules, we might fall into ++ * situations where we fail interoperability and electrical tests. ++ * ++ * In order to avoid both conditions, we're using a 40 ms resume timeout, which ++ * should cope with both LPJ calibration errors and devices not following every ++ * detail of the USB Specification. ++ */ ++#define USB_RESUME_TIMEOUT 40 /* ms */ ++ + /** + * struct usb_interface_cache - long-term representation of a device interface + * @num_altsetting: number of altsettings defined. +diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h +index 349325404add..e4b9e011d2a1 100644 +--- a/include/target/target_core_base.h ++++ b/include/target/target_core_base.h +@@ -513,7 +513,7 @@ struct se_cmd { + sense_reason_t (*execute_cmd)(struct se_cmd *); + sense_reason_t (*execute_rw)(struct se_cmd *, struct scatterlist *, + u32, enum dma_data_direction); +- sense_reason_t (*transport_complete_callback)(struct se_cmd *); ++ sense_reason_t (*transport_complete_callback)(struct se_cmd *, bool); + + unsigned char *t_task_cdb; + unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE]; +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index 1f4bcb3cc21c..be9760f8284a 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -720,6 +720,8 @@ static int ptrace_peek_siginfo(struct task_struct *child, + static int ptrace_resume(struct task_struct *child, long request, + unsigned long data) + { ++ bool need_siglock; ++ + if (!valid_signal(data)) + return -EIO; + +@@ -747,8 +749,26 @@ static int ptrace_resume(struct task_struct *child, long request, + user_disable_single_step(child); + } + ++ /* ++ * Change ->exit_code and ->state under siglock to avoid the race ++ * with wait_task_stopped() in between; a non-zero ->exit_code will ++ * wrongly look like another report from tracee. ++ * ++ * Note that we need siglock even if ->exit_code == data and/or this ++ * status was not reported yet, the new status must not be cleared by ++ * wait_task_stopped() after resume. ++ * ++ * If data == 0 we do not care if wait_task_stopped() reports the old ++ * status and clears the code too; this can't race with the tracee, it ++ * takes siglock after resume. ++ */ ++ need_siglock = data && !thread_group_empty(current); ++ if (need_siglock) ++ spin_lock_irq(&child->sighand->siglock); + child->exit_code = data; + wake_up_state(child, __TASK_TRACED); ++ if (need_siglock) ++ spin_unlock_irq(&child->sighand->siglock); + + return 0; + } +diff --git a/kernel/softirq.c b/kernel/softirq.c +index 490fcbb1dc5b..93be750348c8 100644 +--- a/kernel/softirq.c ++++ b/kernel/softirq.c +@@ -657,9 +657,13 @@ static void run_ksoftirqd(unsigned int cpu) + * in the task stack here. + */ + __do_softirq(); +- rcu_note_context_switch(cpu); + local_irq_enable(); + cond_resched(); ++ ++ preempt_disable(); ++ rcu_note_context_switch(cpu); ++ preempt_enable(); ++ + return; + } + local_irq_enable(); +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index 774a0807fe81..da41de9dc319 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -2651,7 +2651,7 @@ static DEFINE_PER_CPU(unsigned int, current_context); + + static __always_inline int trace_recursive_lock(void) + { +- unsigned int val = this_cpu_read(current_context); ++ unsigned int val = __this_cpu_read(current_context); + int bit; + + if (in_interrupt()) { +@@ -2668,18 +2668,17 @@ static __always_inline int trace_recursive_lock(void) + return 1; + + val |= (1 << bit); +- this_cpu_write(current_context, val); ++ __this_cpu_write(current_context, val); + + return 0; + } + + static __always_inline void trace_recursive_unlock(void) + { +- unsigned int val = this_cpu_read(current_context); ++ unsigned int val = __this_cpu_read(current_context); + +- val--; +- val &= this_cpu_read(current_context); +- this_cpu_write(current_context, val); ++ val &= val & (val - 1); ++ __this_cpu_write(current_context, val); + } + + #else +diff --git a/lib/string.c b/lib/string.c +index 43d0781daf47..cb9ea2181557 100644 +--- a/lib/string.c ++++ b/lib/string.c +@@ -598,7 +598,7 @@ EXPORT_SYMBOL(memset); + void memzero_explicit(void *s, size_t count) + { + memset(s, 0, count); +- OPTIMIZER_HIDE_VAR(s); ++ barrier(); + } + EXPORT_SYMBOL(memzero_explicit); + +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index e2b1bba69882..69ec61abfb37 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -278,13 +278,14 @@ nodata: + EXPORT_SYMBOL(__alloc_skb); + + /** +- * build_skb - build a network buffer ++ * __build_skb - build a network buffer + * @data: data buffer provided by caller +- * @frag_size: size of fragment, or 0 if head was kmalloced ++ * @frag_size: size of data, or 0 if head was kmalloced + * + * Allocate a new &sk_buff. Caller provides space holding head and + * skb_shared_info. @data must have been allocated by kmalloc() only if +- * @frag_size is 0, otherwise data should come from the page allocator. ++ * @frag_size is 0, otherwise data should come from the page allocator ++ * or vmalloc() + * The return is the new skb buffer. + * On a failure the return is %NULL, and @data is not freed. + * Notes : +@@ -295,7 +296,7 @@ EXPORT_SYMBOL(__alloc_skb); + * before giving packet to stack. + * RX rings only contains data buffers, not full skbs. + */ +-struct sk_buff *build_skb(void *data, unsigned int frag_size) ++struct sk_buff *__build_skb(void *data, unsigned int frag_size) + { + struct skb_shared_info *shinfo; + struct sk_buff *skb; +@@ -309,7 +310,6 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size) + + memset(skb, 0, offsetof(struct sk_buff, tail)); + skb->truesize = SKB_TRUESIZE(size); +- skb->head_frag = frag_size != 0; + atomic_set(&skb->users, 1); + skb->head = data; + skb->data = data; +@@ -326,6 +326,23 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size) + + return skb; + } ++ ++/* build_skb() is wrapper over __build_skb(), that specifically ++ * takes care of skb->head and skb->pfmemalloc ++ * This means that if @frag_size is not zero, then @data must be backed ++ * by a page fragment, not kmalloc() or vmalloc() ++ */ ++struct sk_buff *build_skb(void *data, unsigned int frag_size) ++{ ++ struct sk_buff *skb = __build_skb(data, frag_size); ++ ++ if (skb && frag_size) { ++ skb->head_frag = 1; ++ if (virt_to_head_page(data)->pfmemalloc) ++ skb->pfmemalloc = 1; ++ } ++ return skb; ++} + EXPORT_SYMBOL(build_skb); + + struct netdev_alloc_cache { +@@ -352,7 +369,8 @@ refill: + gfp_t gfp = gfp_mask; + + if (order) +- gfp |= __GFP_COMP | __GFP_NOWARN; ++ gfp |= __GFP_COMP | __GFP_NOWARN | ++ __GFP_NOMEMALLOC; + nc->frag.page = alloc_pages(gfp, order); + if (likely(nc->frag.page)) + break; +diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c +index ecb34b5ea42f..57075c4508f7 100644 +--- a/net/ipv4/ip_forward.c ++++ b/net/ipv4/ip_forward.c +@@ -127,6 +127,9 @@ int ip_forward(struct sk_buff *skb) + struct rtable *rt; /* Route we use */ + struct ip_options *opt = &(IPCB(skb)->opt); + ++ if (unlikely(skb->sk)) ++ goto drop; ++ + if (skb_warn_if_lro(skb)) + goto drop; + +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 8c70c73da347..a68cd7100349 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -2595,39 +2595,65 @@ begin_fwd: + } + } + +-/* Send a fin. The caller locks the socket for us. This cannot be +- * allowed to fail queueing a FIN frame under any circumstances. ++/* We allow to exceed memory limits for FIN packets to expedite ++ * connection tear down and (memory) recovery. ++ * Otherwise tcp_send_fin() could be tempted to either delay FIN ++ * or even be forced to close flow without any FIN. ++ */ ++static void sk_forced_wmem_schedule(struct sock *sk, int size) ++{ ++ int amt, status; ++ ++ if (size <= sk->sk_forward_alloc) ++ return; ++ amt = sk_mem_pages(size); ++ sk->sk_forward_alloc += amt * SK_MEM_QUANTUM; ++ sk_memory_allocated_add(sk, amt, &status); ++} ++ ++/* Send a FIN. The caller locks the socket for us. ++ * We should try to send a FIN packet really hard, but eventually give up. + */ + void tcp_send_fin(struct sock *sk) + { ++ struct sk_buff *skb, *tskb = tcp_write_queue_tail(sk); + struct tcp_sock *tp = tcp_sk(sk); +- struct sk_buff *skb = tcp_write_queue_tail(sk); +- int mss_now; + +- /* Optimization, tack on the FIN if we have a queue of +- * unsent frames. But be careful about outgoing SACKS +- * and IP options. ++ /* Optimization, tack on the FIN if we have one skb in write queue and ++ * this skb was not yet sent, or we are under memory pressure. ++ * Note: in the latter case, FIN packet will be sent after a timeout, ++ * as TCP stack thinks it has already been transmitted. + */ +- mss_now = tcp_current_mss(sk); +- +- if (tcp_send_head(sk) != NULL) { +- TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_FIN; +- TCP_SKB_CB(skb)->end_seq++; ++ if (tskb && (tcp_send_head(sk) || sk_under_memory_pressure(sk))) { ++coalesce: ++ TCP_SKB_CB(tskb)->tcp_flags |= TCPHDR_FIN; ++ TCP_SKB_CB(tskb)->end_seq++; + tp->write_seq++; ++ if (!tcp_send_head(sk)) { ++ /* This means tskb was already sent. ++ * Pretend we included the FIN on previous transmit. ++ * We need to set tp->snd_nxt to the value it would have ++ * if FIN had been sent. This is because retransmit path ++ * does not change tp->snd_nxt. ++ */ ++ tp->snd_nxt++; ++ return; ++ } + } else { +- /* Socket is locked, keep trying until memory is available. */ +- for (;;) { +- skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation); +- if (skb) +- break; +- yield(); ++ skb = alloc_skb_fclone(MAX_TCP_HEADER, sk->sk_allocation); ++ if (unlikely(!skb)) { ++ if (tskb) ++ goto coalesce; ++ return; + } ++ skb_reserve(skb, MAX_TCP_HEADER); ++ sk_forced_wmem_schedule(sk, skb->truesize); + /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */ + tcp_init_nondata_skb(skb, tp->write_seq, + TCPHDR_ACK | TCPHDR_FIN); + tcp_queue_skb(sk, skb); + } +- __tcp_push_pending_frames(sk, mss_now, TCP_NAGLE_OFF); ++ __tcp_push_pending_frames(sk, tcp_current_mss(sk), TCP_NAGLE_OFF); + } + + /* We get here when a process closes a file descriptor (either due to +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 1d52506bda14..a0b0ea949192 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -1624,13 +1624,11 @@ static struct sk_buff *netlink_alloc_large_skb(unsigned int size, + if (data == NULL) + return NULL; + +- skb = build_skb(data, size); ++ skb = __build_skb(data, size); + if (skb == NULL) + vfree(data); +- else { +- skb->head_frag = 0; ++ else + skb->destructor = netlink_skb_destructor; +- } + + return skb; + } +diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c +index 2ca9f2e93139..53745f4c2bf5 100644 +--- a/sound/pci/emu10k1/emuproc.c ++++ b/sound/pci/emu10k1/emuproc.c +@@ -241,31 +241,22 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry, + struct snd_emu10k1 *emu = entry->private_data; + u32 value; + u32 value2; +- unsigned long flags; + u32 rate; + + if (emu->card_capabilities->emu_model) { +- spin_lock_irqsave(&emu->emu_lock, flags); + snd_emu1010_fpga_read(emu, 0x38, &value); +- spin_unlock_irqrestore(&emu->emu_lock, flags); + if ((value & 0x1) == 0) { +- spin_lock_irqsave(&emu->emu_lock, flags); + snd_emu1010_fpga_read(emu, 0x2a, &value); + snd_emu1010_fpga_read(emu, 0x2b, &value2); +- spin_unlock_irqrestore(&emu->emu_lock, flags); + rate = 0x1770000 / (((value << 5) | value2)+1); + snd_iprintf(buffer, "ADAT Locked : %u\n", rate); + } else { + snd_iprintf(buffer, "ADAT Unlocked\n"); + } +- spin_lock_irqsave(&emu->emu_lock, flags); + snd_emu1010_fpga_read(emu, 0x20, &value); +- spin_unlock_irqrestore(&emu->emu_lock, flags); + if ((value & 0x4) == 0) { +- spin_lock_irqsave(&emu->emu_lock, flags); + snd_emu1010_fpga_read(emu, 0x28, &value); + snd_emu1010_fpga_read(emu, 0x29, &value2); +- spin_unlock_irqrestore(&emu->emu_lock, flags); + rate = 0x1770000 / (((value << 5) | value2)+1); + snd_iprintf(buffer, "SPDIF Locked : %d\n", rate); + } else { +@@ -410,14 +401,11 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry, + { + struct snd_emu10k1 *emu = entry->private_data; + u32 value; +- unsigned long flags; + int i; + snd_iprintf(buffer, "EMU1010 Registers:\n\n"); + + for(i = 0; i < 0x40; i+=1) { +- spin_lock_irqsave(&emu->emu_lock, flags); + snd_emu1010_fpga_read(emu, i, &value); +- spin_unlock_irqrestore(&emu->emu_lock, flags); + snd_iprintf(buffer, "%02X: %08X, %02X\n", i, value, (value >> 8) & 0x7f); + } + } +diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c +index 5e3bc3c6801a..f40a7a4b6591 100644 +--- a/sound/soc/davinci/davinci-evm.c ++++ b/sound/soc/davinci/davinci-evm.c +@@ -384,18 +384,8 @@ static int davinci_evm_probe(struct platform_device *pdev) + return ret; + } + +-static int davinci_evm_remove(struct platform_device *pdev) +-{ +- struct snd_soc_card *card = platform_get_drvdata(pdev); +- +- snd_soc_unregister_card(card); +- +- return 0; +-} +- + static struct platform_driver davinci_evm_driver = { + .probe = davinci_evm_probe, +- .remove = davinci_evm_remove, + .driver = { + .name = "davinci_evm", + .owner = THIS_MODULE, +diff --git a/tools/lib/traceevent/kbuffer-parse.c b/tools/lib/traceevent/kbuffer-parse.c +index dcc665228c71..deb3569ab004 100644 +--- a/tools/lib/traceevent/kbuffer-parse.c ++++ b/tools/lib/traceevent/kbuffer-parse.c +@@ -372,7 +372,6 @@ translate_data(struct kbuffer *kbuf, void *data, void **rptr, + switch (type_len) { + case KBUFFER_TYPE_PADDING: + *length = read_4(kbuf, data); +- data += *length; + break; + + case KBUFFER_TYPE_TIME_EXTEND: +diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile +index d1b3a361e526..4039854560d0 100644 +--- a/tools/power/x86/turbostat/Makefile ++++ b/tools/power/x86/turbostat/Makefile +@@ -1,8 +1,12 @@ + CC = $(CROSS_COMPILE)gcc +-BUILD_OUTPUT := $(PWD) ++BUILD_OUTPUT := $(CURDIR) + PREFIX := /usr + DESTDIR := + ++ifeq ("$(origin O)", "command line") ++ BUILD_OUTPUT := $(O) ++endif ++ + turbostat : turbostat.c + CFLAGS += -Wall + CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/uapi/asm/msr-index.h"' +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 66112533b1e9..eed250e9c218 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -1549,8 +1549,8 @@ int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc, + ghc->generation = slots->generation; + ghc->len = len; + ghc->memslot = gfn_to_memslot(kvm, start_gfn); +- ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, &nr_pages_avail); +- if (!kvm_is_error_hva(ghc->hva) && nr_pages_avail >= nr_pages_needed) { ++ ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, NULL); ++ if (!kvm_is_error_hva(ghc->hva) && nr_pages_needed <= 1) { + ghc->hva += offset; + } else { + /* diff --git a/patch/kernel/cubox-default/patch-3.14.41-42.patch b/patch/kernel/cubox-default/patch-3.14.41-42.patch new file mode 100644 index 000000000..69f3d5e0d --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.41-42.patch @@ -0,0 +1,1174 @@ +diff --git a/Makefile b/Makefile +index 7a60d4a1301c..b9d850d86366 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 41 ++SUBLEVEL = 42 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c +index d68b410595c8..a0c63fc48457 100644 +--- a/arch/arc/kernel/signal.c ++++ b/arch/arc/kernel/signal.c +@@ -131,6 +131,15 @@ SYSCALL_DEFINE0(rt_sigreturn) + /* Don't restart from sigreturn */ + syscall_wont_restart(regs); + ++ /* ++ * Ensure that sigreturn always returns to user mode (in case the ++ * regs saved on user stack got fudged between save and sigreturn) ++ * Otherwise it is easy to panic the kernel with a custom ++ * signal handler and/or restorer which clobberes the status32/ret ++ * to return to a bogus location in kernel mode. ++ */ ++ regs->status32 |= STATUS_U_MASK; ++ + return regs->r0; + + badframe: +@@ -234,8 +243,11 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info, + + /* + * handler returns using sigreturn stub provided already by userpsace ++ * If not, nuke the process right away + */ +- BUG_ON(!(ka->sa.sa_flags & SA_RESTORER)); ++ if(!(ka->sa.sa_flags & SA_RESTORER)) ++ return 1; ++ + regs->blink = (unsigned long)ka->sa.sa_restorer; + + /* User Stack for signal handler will be above the frame just carved */ +@@ -302,12 +314,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, + struct pt_regs *regs) + { + sigset_t *oldset = sigmask_to_save(); +- int ret; ++ int failed; + + /* Set up the stack frame */ +- ret = setup_rt_frame(sig, ka, info, oldset, regs); ++ failed = setup_rt_frame(sig, ka, info, oldset, regs); + +- if (ret) ++ if (failed) + force_sigsegv(sig, current); + else + signal_delivered(sig, info, ka, regs, 0); +diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c +index 275a7dc2b06c..63688d3a6ea0 100644 +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -2084,6 +2084,11 @@ static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request) + result, xferred); + if (!img_request->result) + img_request->result = result; ++ /* ++ * Need to end I/O on the entire obj_request worth of ++ * bytes in case of error. ++ */ ++ xferred = obj_request->length; + } + + /* Image object requests don't own their page array */ +diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c +index 35bf2bba69bf..11804cc1e11f 100644 +--- a/drivers/gpu/drm/radeon/si_dpm.c ++++ b/drivers/gpu/drm/radeon/si_dpm.c +@@ -2913,6 +2913,7 @@ struct si_dpm_quirk { + static struct si_dpm_quirk si_dpm_quirk_list[] = { + /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */ + { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 }, ++ { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 }, + { 0, 0, 0, 0 }, + }; + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index 505fe29c75b0..8c248818592e 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -716,7 +716,7 @@ int vmbus_request_offers(void) + { + struct vmbus_channel_message_header *msg; + struct vmbus_channel_msginfo *msginfo; +- int ret, t; ++ int ret; + + msginfo = kmalloc(sizeof(*msginfo) + + sizeof(struct vmbus_channel_message_header), +@@ -724,8 +724,6 @@ int vmbus_request_offers(void) + if (!msginfo) + return -ENOMEM; + +- init_completion(&msginfo->waitevent); +- + msg = (struct vmbus_channel_message_header *)msginfo->msg; + + msg->msgtype = CHANNELMSG_REQUESTOFFERS; +@@ -739,14 +737,6 @@ int vmbus_request_offers(void) + goto cleanup; + } + +- t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ); +- if (t == 0) { +- ret = -ETIMEDOUT; +- goto cleanup; +- } +- +- +- + cleanup: + kfree(msginfo); + +diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c +index f913d701a5b3..c4b1af07a121 100644 +--- a/drivers/mtd/ubi/misc.c ++++ b/drivers/mtd/ubi/misc.c +@@ -74,6 +74,8 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id) + for (i = 0; i < vol->used_ebs; i++) { + int size; + ++ cond_resched(); ++ + if (i == vol->used_ebs - 1) + size = vol->last_eb_bytes; + else +diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c +index 2d9d1985adc1..54407a8209b5 100644 +--- a/drivers/platform/x86/compal-laptop.c ++++ b/drivers/platform/x86/compal-laptop.c +@@ -1027,9 +1027,9 @@ static int compal_probe(struct platform_device *pdev) + if (err) + return err; + +- hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, +- DRIVER_NAME, data, +- compal_hwmon_groups); ++ hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, ++ DRIVER_NAME, data, ++ compal_hwmon_groups); + if (IS_ERR(hwmon_dev)) { + err = PTR_ERR(hwmon_dev); + goto remove; +diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c +index 0a7325361d29..5f57e3d35e26 100644 +--- a/drivers/scsi/3w-9xxx.c ++++ b/drivers/scsi/3w-9xxx.c +@@ -149,7 +149,6 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset); + static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg); + static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); + static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code); +-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id); + + /* Functions */ + +@@ -1352,11 +1351,11 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) + } + + /* Now complete the io */ ++ scsi_dma_unmap(cmd); ++ cmd->scsi_done(cmd); + tw_dev->state[request_id] = TW_S_COMPLETED; + twa_free_request_id(tw_dev, request_id); + tw_dev->posted_request_count--; +- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); +- twa_unmap_scsi_data(tw_dev, request_id); + } + + /* Check for valid status after each drain */ +@@ -1414,26 +1413,6 @@ static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_comm + } + } /* End twa_load_sgl() */ + +-/* This function will perform a pci-dma mapping for a scatter gather list */ +-static int twa_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id) +-{ +- int use_sg; +- struct scsi_cmnd *cmd = tw_dev->srb[request_id]; +- +- use_sg = scsi_dma_map(cmd); +- if (!use_sg) +- return 0; +- else if (use_sg < 0) { +- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list"); +- return 0; +- } +- +- cmd->SCp.phase = TW_PHASE_SGLIST; +- cmd->SCp.have_data_in = use_sg; +- +- return use_sg; +-} /* End twa_map_scsi_sg_data() */ +- + /* This function will poll for a response interrupt of a request */ + static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds) + { +@@ -1612,9 +1591,11 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev) + (tw_dev->state[i] != TW_S_INITIAL) && + (tw_dev->state[i] != TW_S_COMPLETED)) { + if (tw_dev->srb[i]) { +- tw_dev->srb[i]->result = (DID_RESET << 16); +- tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); +- twa_unmap_scsi_data(tw_dev, i); ++ struct scsi_cmnd *cmd = tw_dev->srb[i]; ++ ++ cmd->result = (DID_RESET << 16); ++ scsi_dma_unmap(cmd); ++ cmd->scsi_done(cmd); + } + } + } +@@ -1793,21 +1774,18 @@ static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_ + /* Save the scsi command for use by the ISR */ + tw_dev->srb[request_id] = SCpnt; + +- /* Initialize phase to zero */ +- SCpnt->SCp.phase = TW_PHASE_INITIAL; +- + retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL); + switch (retval) { + case SCSI_MLQUEUE_HOST_BUSY: ++ scsi_dma_unmap(SCpnt); + twa_free_request_id(tw_dev, request_id); +- twa_unmap_scsi_data(tw_dev, request_id); + break; + case 1: +- tw_dev->state[request_id] = TW_S_COMPLETED; +- twa_free_request_id(tw_dev, request_id); +- twa_unmap_scsi_data(tw_dev, request_id); + SCpnt->result = (DID_ERROR << 16); ++ scsi_dma_unmap(SCpnt); + done(SCpnt); ++ tw_dev->state[request_id] = TW_S_COMPLETED; ++ twa_free_request_id(tw_dev, request_id); + retval = 0; + } + out: +@@ -1875,8 +1853,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, + command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]); + command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH); + } else { +- sg_count = twa_map_scsi_sg_data(tw_dev, request_id); +- if (sg_count == 0) ++ sg_count = scsi_dma_map(srb); ++ if (sg_count < 0) + goto out; + + scsi_for_each_sg(srb, sg, sg_count, i) { +@@ -1991,15 +1969,6 @@ static char *twa_string_lookup(twa_message_type *table, unsigned int code) + return(table[index].text); + } /* End twa_string_lookup() */ + +-/* This function will perform a pci-dma unmap */ +-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id) +-{ +- struct scsi_cmnd *cmd = tw_dev->srb[request_id]; +- +- if (cmd->SCp.phase == TW_PHASE_SGLIST) +- scsi_dma_unmap(cmd); +-} /* End twa_unmap_scsi_data() */ +- + /* This function gets called when a disk is coming on-line */ + static int twa_slave_configure(struct scsi_device *sdev) + { +diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h +index 040f7214e5b7..0fdc83cfa0e1 100644 +--- a/drivers/scsi/3w-9xxx.h ++++ b/drivers/scsi/3w-9xxx.h +@@ -324,11 +324,6 @@ static twa_message_type twa_error_table[] = { + #define TW_CURRENT_DRIVER_BUILD 0 + #define TW_CURRENT_DRIVER_BRANCH 0 + +-/* Phase defines */ +-#define TW_PHASE_INITIAL 0 +-#define TW_PHASE_SINGLE 1 +-#define TW_PHASE_SGLIST 2 +- + /* Misc defines */ + #define TW_9550SX_DRAIN_COMPLETED 0xFFFF + #define TW_SECTOR_SIZE 512 +diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c +index 4de346017e9f..61702ac00d42 100644 +--- a/drivers/scsi/3w-sas.c ++++ b/drivers/scsi/3w-sas.c +@@ -303,26 +303,6 @@ static int twl_post_command_packet(TW_Device_Extension *tw_dev, int request_id) + return 0; + } /* End twl_post_command_packet() */ + +-/* This function will perform a pci-dma mapping for a scatter gather list */ +-static int twl_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id) +-{ +- int use_sg; +- struct scsi_cmnd *cmd = tw_dev->srb[request_id]; +- +- use_sg = scsi_dma_map(cmd); +- if (!use_sg) +- return 0; +- else if (use_sg < 0) { +- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1, "Failed to map scatter gather list"); +- return 0; +- } +- +- cmd->SCp.phase = TW_PHASE_SGLIST; +- cmd->SCp.have_data_in = use_sg; +- +- return use_sg; +-} /* End twl_map_scsi_sg_data() */ +- + /* This function hands scsi cdb's to the firmware */ + static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry_ISO *sglistarg) + { +@@ -370,8 +350,8 @@ static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, + if (!sglistarg) { + /* Map sglist from scsi layer to cmd packet */ + if (scsi_sg_count(srb)) { +- sg_count = twl_map_scsi_sg_data(tw_dev, request_id); +- if (sg_count == 0) ++ sg_count = scsi_dma_map(srb); ++ if (sg_count <= 0) + goto out; + + scsi_for_each_sg(srb, sg, sg_count, i) { +@@ -1116,15 +1096,6 @@ out: + return retval; + } /* End twl_initialize_device_extension() */ + +-/* This function will perform a pci-dma unmap */ +-static void twl_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id) +-{ +- struct scsi_cmnd *cmd = tw_dev->srb[request_id]; +- +- if (cmd->SCp.phase == TW_PHASE_SGLIST) +- scsi_dma_unmap(cmd); +-} /* End twl_unmap_scsi_data() */ +- + /* This function will handle attention interrupts */ + static int twl_handle_attention_interrupt(TW_Device_Extension *tw_dev) + { +@@ -1265,11 +1236,11 @@ static irqreturn_t twl_interrupt(int irq, void *dev_instance) + } + + /* Now complete the io */ ++ scsi_dma_unmap(cmd); ++ cmd->scsi_done(cmd); + tw_dev->state[request_id] = TW_S_COMPLETED; + twl_free_request_id(tw_dev, request_id); + tw_dev->posted_request_count--; +- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); +- twl_unmap_scsi_data(tw_dev, request_id); + } + + /* Check for another response interrupt */ +@@ -1414,10 +1385,12 @@ static int twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_res + if ((tw_dev->state[i] != TW_S_FINISHED) && + (tw_dev->state[i] != TW_S_INITIAL) && + (tw_dev->state[i] != TW_S_COMPLETED)) { +- if (tw_dev->srb[i]) { +- tw_dev->srb[i]->result = (DID_RESET << 16); +- tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); +- twl_unmap_scsi_data(tw_dev, i); ++ struct scsi_cmnd *cmd = tw_dev->srb[i]; ++ ++ if (cmd) { ++ cmd->result = (DID_RESET << 16); ++ scsi_dma_unmap(cmd); ++ cmd->scsi_done(cmd); + } + } + } +@@ -1521,9 +1494,6 @@ static int twl_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_ + /* Save the scsi command for use by the ISR */ + tw_dev->srb[request_id] = SCpnt; + +- /* Initialize phase to zero */ +- SCpnt->SCp.phase = TW_PHASE_INITIAL; +- + retval = twl_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL); + if (retval) { + tw_dev->state[request_id] = TW_S_COMPLETED; +diff --git a/drivers/scsi/3w-sas.h b/drivers/scsi/3w-sas.h +index d474892701d4..fec6449c7595 100644 +--- a/drivers/scsi/3w-sas.h ++++ b/drivers/scsi/3w-sas.h +@@ -103,10 +103,6 @@ static char *twl_aen_severity_table[] = + #define TW_CURRENT_DRIVER_BUILD 0 + #define TW_CURRENT_DRIVER_BRANCH 0 + +-/* Phase defines */ +-#define TW_PHASE_INITIAL 0 +-#define TW_PHASE_SGLIST 2 +- + /* Misc defines */ + #define TW_SECTOR_SIZE 512 + #define TW_MAX_UNITS 32 +diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c +index 752624e6bc00..b327742b95ef 100644 +--- a/drivers/scsi/3w-xxxx.c ++++ b/drivers/scsi/3w-xxxx.c +@@ -1284,32 +1284,6 @@ static int tw_initialize_device_extension(TW_Device_Extension *tw_dev) + return 0; + } /* End tw_initialize_device_extension() */ + +-static int tw_map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) +-{ +- int use_sg; +- +- dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n"); +- +- use_sg = scsi_dma_map(cmd); +- if (use_sg < 0) { +- printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n"); +- return 0; +- } +- +- cmd->SCp.phase = TW_PHASE_SGLIST; +- cmd->SCp.have_data_in = use_sg; +- +- return use_sg; +-} /* End tw_map_scsi_sg_data() */ +- +-static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) +-{ +- dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n"); +- +- if (cmd->SCp.phase == TW_PHASE_SGLIST) +- scsi_dma_unmap(cmd); +-} /* End tw_unmap_scsi_data() */ +- + /* This function will reset a device extension */ + static int tw_reset_device_extension(TW_Device_Extension *tw_dev) + { +@@ -1332,8 +1306,8 @@ static int tw_reset_device_extension(TW_Device_Extension *tw_dev) + srb = tw_dev->srb[i]; + if (srb != NULL) { + srb->result = (DID_RESET << 16); +- tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); +- tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]); ++ scsi_dma_unmap(srb); ++ srb->scsi_done(srb); + } + } + } +@@ -1780,8 +1754,8 @@ static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id) + command_packet->byte8.io.lba = lba; + command_packet->byte6.block_count = num_sectors; + +- use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); +- if (!use_sg) ++ use_sg = scsi_dma_map(srb); ++ if (use_sg <= 0) + return 1; + + scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) { +@@ -1968,9 +1942,6 @@ static int tw_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_c + /* Save the scsi command for use by the ISR */ + tw_dev->srb[request_id] = SCpnt; + +- /* Initialize phase to zero */ +- SCpnt->SCp.phase = TW_PHASE_INITIAL; +- + switch (*command) { + case READ_10: + case READ_6: +@@ -2198,12 +2169,11 @@ static irqreturn_t tw_interrupt(int irq, void *dev_instance) + + /* Now complete the io */ + if ((error != TW_ISR_DONT_COMPLETE)) { ++ scsi_dma_unmap(tw_dev->srb[request_id]); ++ tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); + tw_dev->state[request_id] = TW_S_COMPLETED; + tw_state_request_finish(tw_dev, request_id); + tw_dev->posted_request_count--; +- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); +- +- tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); + } + } + +diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h +index 49dcf03c631a..1d31858766ce 100644 +--- a/drivers/scsi/3w-xxxx.h ++++ b/drivers/scsi/3w-xxxx.h +@@ -195,11 +195,6 @@ static unsigned char tw_sense_table[][4] = + #define TW_AEN_SMART_FAIL 0x000F + #define TW_AEN_SBUF_FAIL 0x0024 + +-/* Phase defines */ +-#define TW_PHASE_INITIAL 0 +-#define TW_PHASE_SINGLE 1 +-#define TW_PHASE_SGLIST 2 +- + /* Misc defines */ + #define TW_ALIGNMENT_6000 64 /* 64 bytes */ + #define TW_ALIGNMENT_7000 4 /* 4 bytes */ +diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c +index ec4b1fd14021..790e12e0f524 100644 +--- a/drivers/staging/panel/panel.c ++++ b/drivers/staging/panel/panel.c +@@ -275,11 +275,11 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES]; + * LCD types + */ + #define LCD_TYPE_NONE 0 +-#define LCD_TYPE_OLD 1 +-#define LCD_TYPE_KS0074 2 +-#define LCD_TYPE_HANTRONIX 3 +-#define LCD_TYPE_NEXCOM 4 +-#define LCD_TYPE_CUSTOM 5 ++#define LCD_TYPE_CUSTOM 1 ++#define LCD_TYPE_OLD 2 ++#define LCD_TYPE_KS0074 3 ++#define LCD_TYPE_HANTRONIX 4 ++#define LCD_TYPE_NEXCOM 5 + + /* + * keypad types +@@ -457,8 +457,7 @@ MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead"); + static int lcd_type = -1; + module_param(lcd_type, int, 0000); + MODULE_PARM_DESC(lcd_type, +- "LCD type: 0=none, 1=old //, 2=serial ks0074, " +- "3=hantronix //, 4=nexcom //, 5=compiled-in"); ++ "LCD type: 0=none, 1=compiled-in, 2=old, 3=serial ks0074, 4=hantronix, 5=nexcom"); + + static int lcd_proto = -1; + module_param(lcd_proto, int, 0000); +diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c +index 0d3e6cb36748..9d162ef79af6 100644 +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -757,6 +757,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port) + config.direction = DMA_MEM_TO_DEV; + config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + config.dst_addr = port->mapbase + ATMEL_US_THR; ++ config.dst_maxburst = 1; + + ret = dmaengine_device_control(atmel_port->chan_tx, + DMA_SLAVE_CONFIG, +@@ -921,6 +922,7 @@ static int atmel_prepare_rx_dma(struct uart_port *port) + config.direction = DMA_DEV_TO_MEM; + config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + config.src_addr = port->mapbase + ATMEL_US_RHR; ++ config.src_maxburst = 1; + + ret = dmaengine_device_control(atmel_port->chan_rx, + DMA_SLAVE_CONFIG, +diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c +index 99246606a256..9dd8a71fff9e 100644 +--- a/drivers/tty/serial/of_serial.c ++++ b/drivers/tty/serial/of_serial.c +@@ -261,7 +261,6 @@ static struct of_device_id of_platform_serial_table[] = { + { .compatible = "ibm,qpace-nwp-serial", + .data = (void *)PORT_NWPSERIAL, }, + #endif +- { .type = "serial", .data = (void *)PORT_UNKNOWN, }, + { /* end of list */ }, + }; + +diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c +index 69b76efd11e9..44e698cd5246 100644 +--- a/drivers/usb/gadget/printer.c ++++ b/drivers/usb/gadget/printer.c +@@ -975,6 +975,15 @@ unknown: + break; + } + /* host either stalls (value < 0) or reports success */ ++ if (value >= 0) { ++ req->length = value; ++ req->zero = value < wLength; ++ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); ++ if (value < 0) { ++ ERROR(dev, "%s:%d Error!\n", __func__, __LINE__); ++ req->status = 0; ++ } ++ } + return value; + } + +diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c +index 488a30836c36..3df32fa8c8ae 100644 +--- a/drivers/usb/host/ehci-hcd.c ++++ b/drivers/usb/host/ehci-hcd.c +@@ -787,12 +787,12 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) + ehci->reset_done[i] == 0)) + continue; + +- /* start 20 msec resume signaling from this port, +- * and make khubd collect PORT_STAT_C_SUSPEND to +- * stop that signaling. Use 5 ms extra for safety, +- * like usb_port_resume() does. ++ /* start USB_RESUME_TIMEOUT msec resume signaling from ++ * this port, and make hub_wq collect ++ * PORT_STAT_C_SUSPEND to stop that signaling. + */ +- ehci->reset_done[i] = jiffies + msecs_to_jiffies(25); ++ ehci->reset_done[i] = jiffies + ++ msecs_to_jiffies(USB_RESUME_TIMEOUT); + set_bit(i, &ehci->resuming_ports); + ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); + usb_hcd_start_port_resume(&hcd->self, i); +diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c +index 7d6f64c447bf..323c5faf7a2f 100644 +--- a/drivers/usb/host/ehci-hub.c ++++ b/drivers/usb/host/ehci-hub.c +@@ -482,10 +482,13 @@ static int ehci_bus_resume (struct usb_hcd *hcd) + ehci_writel(ehci, temp, &ehci->regs->port_status [i]); + } + +- /* msleep for 20ms only if code is trying to resume port */ ++ /* ++ * msleep for USB_RESUME_TIMEOUT ms only if code is trying to resume ++ * port ++ */ + if (resume_needed) { + spin_unlock_irq(&ehci->lock); +- msleep(20); ++ msleep(USB_RESUME_TIMEOUT); + spin_lock_irq(&ehci->lock); + if (ehci->shutdown) + goto shutdown; +@@ -953,7 +956,7 @@ static int ehci_hub_control ( + temp &= ~PORT_WAKE_BITS; + ehci_writel(ehci, temp | PORT_RESUME, status_reg); + ehci->reset_done[wIndex] = jiffies +- + msecs_to_jiffies(20); ++ + msecs_to_jiffies(USB_RESUME_TIMEOUT); + set_bit(wIndex, &ehci->resuming_ports); + usb_hcd_start_port_resume(&hcd->self, wIndex); + break; +diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c +index e07248b6ab67..1b1e6e0d9270 100644 +--- a/drivers/usb/host/oxu210hp-hcd.c ++++ b/drivers/usb/host/oxu210hp-hcd.c +@@ -2500,11 +2500,12 @@ static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd) + || oxu->reset_done[i] != 0) + continue; + +- /* start 20 msec resume signaling from this port, +- * and make khubd collect PORT_STAT_C_SUSPEND to ++ /* start USB_RESUME_TIMEOUT resume signaling from this ++ * port, and make hub_wq collect PORT_STAT_C_SUSPEND to + * stop that signaling. + */ +- oxu->reset_done[i] = jiffies + msecs_to_jiffies(20); ++ oxu->reset_done[i] = jiffies + ++ msecs_to_jiffies(USB_RESUME_TIMEOUT); + oxu_dbg(oxu, "port %d remote wakeup\n", i + 1); + mod_timer(&hcd->rh_timer, oxu->reset_done[i]); + } +diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c +index 07576907e2c6..ec69b90475c7 100644 +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -99,6 +99,7 @@ + #include + #include + #include ++#include + + #include "musb_core.h" + +@@ -477,10 +478,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + (USB_PORT_STAT_C_SUSPEND << 16) + | MUSB_PORT_STAT_RESUME; + musb->rh_timer = jiffies +- + msecs_to_jiffies(20); ++ + msecs_to_jiffies(USB_RESUME_TIMEOUT); ++ + schedule_delayed_work( + &musb->finish_resume_work, +- msecs_to_jiffies(20)); ++ msecs_to_jiffies(USB_RESUME_TIMEOUT)); + + musb->xceiv->state = OTG_STATE_A_HOST; + musb->is_active = 1; +diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c +index e2d2d8c9891b..0241a3a0d63e 100644 +--- a/drivers/usb/musb/musb_virthub.c ++++ b/drivers/usb/musb/musb_virthub.c +@@ -136,7 +136,7 @@ void musb_port_suspend(struct musb *musb, bool do_suspend) + /* later, GetPortStatus will stop RESUME signaling */ + musb->port1_status |= MUSB_PORT_STAT_RESUME; + schedule_delayed_work(&musb->finish_resume_work, +- msecs_to_jiffies(20)); ++ msecs_to_jiffies(USB_RESUME_TIMEOUT)); + } + } + +diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c +index 171b9fa0f27a..4e8b79def9c7 100644 +--- a/fs/ext4/extents_status.c ++++ b/fs/ext4/extents_status.c +@@ -656,6 +656,14 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk, + + BUG_ON(end < lblk); + ++ if ((status & EXTENT_STATUS_DELAYED) && ++ (status & EXTENT_STATUS_WRITTEN)) { ++ ext4_warning(inode->i_sb, "Inserting extent [%u/%u] as " ++ " delayed and written which can potentially " ++ " cause data loss.\n", lblk, len); ++ WARN_ON(1); ++ } ++ + newes.es_lblk = lblk; + newes.es_len = len; + ext4_es_store_pblock(&newes, pblk); +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 3a7e0341447f..da03340fdb17 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -569,6 +569,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, + status = map->m_flags & EXT4_MAP_UNWRITTEN ? + EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; + if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && ++ !(status & EXTENT_STATUS_WRITTEN) && + ext4_find_delalloc_range(inode, map->m_lblk, + map->m_lblk + map->m_len - 1)) + status |= EXTENT_STATUS_DELAYED; +@@ -678,6 +679,7 @@ found: + status = map->m_flags & EXT4_MAP_UNWRITTEN ? + EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; + if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && ++ !(status & EXTENT_STATUS_WRITTEN) && + ext4_find_delalloc_range(inode, map->m_lblk, + map->m_lblk + map->m_len - 1)) + status |= EXTENT_STATUS_DELAYED; +diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h +index dfb42ca6d043..8898cdeb42a4 100644 +--- a/include/sound/emu10k1.h ++++ b/include/sound/emu10k1.h +@@ -41,7 +41,8 @@ + + #define EMUPAGESIZE 4096 + #define MAXREQVOICES 8 +-#define MAXPAGES 8192 ++#define MAXPAGES0 4096 /* 32 bit mode */ ++#define MAXPAGES1 8192 /* 31 bit mode */ + #define RESERVED 0 + #define NUM_MIDI 16 + #define NUM_G 64 /* use all channels */ +@@ -50,8 +51,7 @@ + + /* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */ + #define EMU10K1_DMA_MASK 0x7fffffffUL /* 31bit */ +-#define AUDIGY_DMA_MASK 0x7fffffffUL /* 31bit FIXME - 32 should work? */ +- /* See ALSA bug #1276 - rlrevell */ ++#define AUDIGY_DMA_MASK 0xffffffffUL /* 32bit mode */ + + #define TMEMSIZE 256*1024 + #define TMEMSIZEREG 4 +@@ -468,8 +468,11 @@ + + #define MAPB 0x0d /* Cache map B */ + +-#define MAP_PTE_MASK 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */ +-#define MAP_PTI_MASK 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */ ++#define MAP_PTE_MASK0 0xfffff000 /* The 20 MSBs of the PTE indexed by the PTI */ ++#define MAP_PTI_MASK0 0x00000fff /* The 12 bit index to one of the 4096 PTE dwords */ ++ ++#define MAP_PTE_MASK1 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */ ++#define MAP_PTI_MASK1 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */ + + /* 0x0e, 0x0f: Not used */ + +@@ -1706,6 +1709,7 @@ struct snd_emu10k1 { + unsigned short model; /* subsystem id */ + unsigned int card_type; /* EMU10K1_CARD_* */ + unsigned int ecard_ctrl; /* ecard control bits */ ++ unsigned int address_mode; /* address mode */ + unsigned long dma_mask; /* PCI DMA mask */ + unsigned int delay_pcm_irq; /* in samples */ + int max_cache_pages; /* max memory size / PAGE_SIZE */ +diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h +index 6e89ef6c11c1..13412ab158ee 100644 +--- a/include/sound/soc-dapm.h ++++ b/include/sound/soc-dapm.h +@@ -302,7 +302,7 @@ struct device; + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ + .tlv.p = (tlv_array), \ + .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ +- .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } ++ .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) } + #define SOC_DAPM_SINGLE_TLV_VIRT(xname, max, tlv_array) \ + SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0, tlv_array) + #define SOC_DAPM_ENUM(xname, xenum) \ +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index b94002ab8052..1e2e9bf62f1a 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -158,6 +158,7 @@ void ping_unhash(struct sock *sk) + if (sk_hashed(sk)) { + write_lock_bh(&ping_table.lock); + hlist_nulls_del(&sk->sk_nulls_node); ++ sk_nulls_node_init(&sk->sk_nulls_node); + sock_put(sk); + isk->inet_num = 0; + isk->inet_sport = 0; +diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c +index 9e1bd0c39a8c..6757458e8db6 100644 +--- a/sound/pci/emu10k1/emu10k1.c ++++ b/sound/pci/emu10k1/emu10k1.c +@@ -181,8 +181,10 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, + } + #endif + +- strcpy(card->driver, emu->card_capabilities->driver); +- strcpy(card->shortname, emu->card_capabilities->name); ++ strlcpy(card->driver, emu->card_capabilities->driver, ++ sizeof(card->driver)); ++ strlcpy(card->shortname, emu->card_capabilities->name, ++ sizeof(card->shortname)); + snprintf(card->longname, sizeof(card->longname), + "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i", + card->shortname, emu->revision, emu->serial, emu->port, emu->irq); +diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c +index 0a34b5f1c475..f8a6549f00e5 100644 +--- a/sound/pci/emu10k1/emu10k1_callback.c ++++ b/sound/pci/emu10k1/emu10k1_callback.c +@@ -415,7 +415,7 @@ start_voice(struct snd_emux_voice *vp) + snd_emu10k1_ptr_write(hw, Z2, ch, 0); + + /* invalidate maps */ +- temp = (hw->silent_page.addr << 1) | MAP_PTI_MASK; ++ temp = (hw->silent_page.addr << hw->address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); + snd_emu10k1_ptr_write(hw, MAPA, ch, temp); + snd_emu10k1_ptr_write(hw, MAPB, ch, temp); + #if 0 +@@ -436,7 +436,7 @@ start_voice(struct snd_emux_voice *vp) + snd_emu10k1_ptr_write(hw, CDF, ch, sample); + + /* invalidate maps */ +- temp = ((unsigned int)hw->silent_page.addr << 1) | MAP_PTI_MASK; ++ temp = ((unsigned int)hw->silent_page.addr << hw_address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); + snd_emu10k1_ptr_write(hw, MAPA, ch, temp); + snd_emu10k1_ptr_write(hw, MAPB, ch, temp); + +diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c +index bdd888ec9a84..a131092572e6 100644 +--- a/sound/pci/emu10k1/emu10k1_main.c ++++ b/sound/pci/emu10k1/emu10k1_main.c +@@ -282,7 +282,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) + snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */ + snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */ + +- silent_page = (emu->silent_page.addr << 1) | MAP_PTI_MASK; ++ silent_page = (emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); + for (ch = 0; ch < NUM_G; ch++) { + snd_emu10k1_ptr_write(emu, MAPA, ch, silent_page); + snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page); +@@ -348,6 +348,11 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) + outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); + } + ++ if (emu->address_mode == 0) { ++ /* use 16M in 4G */ ++ outl(inl(emu->port + HCFG) | HCFG_EXPANDED_MEM, emu->port + HCFG); ++ } ++ + return 0; + } + +@@ -1411,7 +1416,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { + * + */ + {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102, +- .driver = "Audigy2", .name = "SB Audigy 2 ZS Notebook [SB0530]", ++ .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]", + .id = "Audigy2", + .emu10k2_chip = 1, + .ca0108_chip = 1, +@@ -1561,7 +1566,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { + .adc_1361t = 1, /* 24 bit capture instead of 16bit */ + .ac97_chip = 1} , + {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, +- .driver = "Audigy2", .name = "SB Audigy 2 Platinum EX [SB0280]", ++ .driver = "Audigy2", .name = "Audigy 2 Platinum EX [SB0280]", + .id = "Audigy2", + .emu10k2_chip = 1, + .ca0102_chip = 1, +@@ -1865,8 +1870,10 @@ int snd_emu10k1_create(struct snd_card *card, + + is_audigy = emu->audigy = c->emu10k2_chip; + ++ /* set addressing mode */ ++ emu->address_mode = is_audigy ? 0 : 1; + /* set the DMA transfer mask */ +- emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK; ++ emu->dma_mask = emu->address_mode ? EMU10K1_DMA_MASK : AUDIGY_DMA_MASK; + if (pci_set_dma_mask(pci, emu->dma_mask) < 0 || + pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) { + snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask); +@@ -1889,7 +1896,7 @@ int snd_emu10k1_create(struct snd_card *card, + + emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT; + if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), +- 32 * 1024, &emu->ptb_pages) < 0) { ++ (emu->address_mode ? 32 : 16) * 1024, &emu->ptb_pages) < 0) { + err = -ENOMEM; + goto error; + } +@@ -1988,8 +1995,8 @@ int snd_emu10k1_create(struct snd_card *card, + + /* Clear silent pages and set up pointers */ + memset(emu->silent_page.area, 0, PAGE_SIZE); +- silent_page = emu->silent_page.addr << 1; +- for (idx = 0; idx < MAXPAGES; idx++) ++ silent_page = emu->silent_page.addr << emu->address_mode; ++ for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++) + ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx); + + /* set up voice indices */ +diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c +index 5ae1d045bdcb..7581019d7c84 100644 +--- a/sound/pci/emu10k1/emupcm.c ++++ b/sound/pci/emu10k1/emupcm.c +@@ -379,7 +379,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, + snd_emu10k1_ptr_write(emu, Z1, voice, 0); + snd_emu10k1_ptr_write(emu, Z2, voice, 0); + /* invalidate maps */ +- silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK; ++ silent_page = ((unsigned int)emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); + snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page); + snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page); + /* modulation envelope */ +diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c +index ae709c1ab3a8..d514458efe3d 100644 +--- a/sound/pci/emu10k1/memory.c ++++ b/sound/pci/emu10k1/memory.c +@@ -34,10 +34,11 @@ + * aligned pages in others + */ + #define __set_ptb_entry(emu,page,addr) \ +- (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << 1) | (page))) ++ (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << (emu->address_mode)) | (page))) + + #define UNIT_PAGES (PAGE_SIZE / EMUPAGESIZE) +-#define MAX_ALIGN_PAGES (MAXPAGES / UNIT_PAGES) ++#define MAX_ALIGN_PAGES0 (MAXPAGES0 / UNIT_PAGES) ++#define MAX_ALIGN_PAGES1 (MAXPAGES1 / UNIT_PAGES) + /* get aligned page from offset address */ + #define get_aligned_page(offset) ((offset) >> PAGE_SHIFT) + /* get offset address from aligned page */ +@@ -124,7 +125,7 @@ static int search_empty_map_area(struct snd_emu10k1 *emu, int npages, struct lis + } + page = blk->mapped_page + blk->pages; + } +- size = MAX_ALIGN_PAGES - page; ++ size = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0) - page; + if (size >= max_size) { + *nextp = pos; + return page; +@@ -181,7 +182,7 @@ static int unmap_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) + q = get_emu10k1_memblk(p, mapped_link); + end_page = q->mapped_page; + } else +- end_page = MAX_ALIGN_PAGES; ++ end_page = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0); + + /* remove links */ + list_del(&blk->mapped_link); +@@ -305,7 +306,7 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst + if (snd_BUG_ON(!emu)) + return NULL; + if (snd_BUG_ON(runtime->dma_bytes <= 0 || +- runtime->dma_bytes >= MAXPAGES * EMUPAGESIZE)) ++ runtime->dma_bytes >= (emu->address_mode ? MAXPAGES1 : MAXPAGES0) * EMUPAGESIZE)) + return NULL; + hdr = emu->memhdr; + if (snd_BUG_ON(!hdr)) +diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c +index f6e5c4ed03ed..97ebc105cf3c 100644 +--- a/sound/pci/hda/hda_codec.c ++++ b/sound/pci/hda/hda_codec.c +@@ -2082,6 +2082,16 @@ static void put_vol_mute(struct hda_codec *codec, unsigned int amp_caps, + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm); + } + ++/* meta hook to call each driver's vmaster hook */ ++static void vmaster_hook(void *private_data, int enabled) ++{ ++ struct hda_vmaster_mute_hook *hook = private_data; ++ ++ if (hook->mute_mode != HDA_VMUTE_FOLLOW_MASTER) ++ enabled = hook->mute_mode; ++ hook->hook(hook->codec, enabled); ++} ++ + /** + * snd_hda_codec_amp_read - Read AMP value + * @codec: HD-audio codec +@@ -2917,9 +2927,9 @@ int snd_hda_add_vmaster_hook(struct hda_codec *codec, + + if (!hook->hook || !hook->sw_kctl) + return 0; +- snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec); + hook->codec = codec; + hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER; ++ snd_ctl_add_vmaster_hook(hook->sw_kctl, vmaster_hook, hook); + if (!expose_enum_ctl) + return 0; + kctl = snd_ctl_new1(&vmaster_mute_mode, hook); +@@ -2942,14 +2952,7 @@ void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook) + */ + if (hook->codec->bus->shutdown) + return; +- switch (hook->mute_mode) { +- case HDA_VMUTE_FOLLOW_MASTER: +- snd_ctl_sync_vmaster_hook(hook->sw_kctl); +- break; +- default: +- hook->hook(hook->codec, hook->mute_mode); +- break; +- } ++ snd_ctl_sync_vmaster_hook(hook->sw_kctl); + } + EXPORT_SYMBOL_GPL(snd_hda_sync_vmaster_hook); + +diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c +index 8fe3b8c18ed4..1eafc1a28193 100644 +--- a/sound/pci/hda/thinkpad_helper.c ++++ b/sound/pci/hda/thinkpad_helper.c +@@ -71,6 +71,7 @@ static void hda_fixup_thinkpad_acpi(struct hda_codec *codec, + if (led_set_func(TPACPI_LED_MUTE, false) >= 0) { + old_vmaster_hook = spec->vmaster_mute.hook; + spec->vmaster_mute.hook = update_tpacpi_mute_led; ++ spec->vmaster_mute_enum = 1; + removefunc = false; + } + if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) { +diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c +index 319754cf6208..daf61abc3670 100644 +--- a/sound/synth/emux/emux_oss.c ++++ b/sound/synth/emux/emux_oss.c +@@ -118,12 +118,8 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) + if (snd_BUG_ON(!arg || !emu)) + return -ENXIO; + +- mutex_lock(&emu->register_mutex); +- +- if (!snd_emux_inc_count(emu)) { +- mutex_unlock(&emu->register_mutex); ++ if (!snd_emux_inc_count(emu)) + return -EFAULT; +- } + + memset(&callback, 0, sizeof(callback)); + callback.owner = THIS_MODULE; +@@ -135,7 +131,6 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) + if (p == NULL) { + snd_printk(KERN_ERR "can't create port\n"); + snd_emux_dec_count(emu); +- mutex_unlock(&emu->register_mutex); + return -ENOMEM; + } + +@@ -148,8 +143,6 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) + reset_port_mode(p, arg->seq_mode); + + snd_emux_reset_port(p); +- +- mutex_unlock(&emu->register_mutex); + return 0; + } + +@@ -195,13 +188,11 @@ snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg) + if (snd_BUG_ON(!emu)) + return -ENXIO; + +- mutex_lock(&emu->register_mutex); + snd_emux_sounds_off_all(p); + snd_soundfont_close_check(emu->sflist, SF_CLIENT_NO(p->chset.port)); + snd_seq_event_port_detach(p->chset.client, p->chset.port); + snd_emux_dec_count(emu); + +- mutex_unlock(&emu->register_mutex); + return 0; + } + +diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c +index 7778b8e19782..a0209204ae48 100644 +--- a/sound/synth/emux/emux_seq.c ++++ b/sound/synth/emux/emux_seq.c +@@ -124,12 +124,10 @@ snd_emux_detach_seq(struct snd_emux *emu) + if (emu->voices) + snd_emux_terminate_all(emu); + +- mutex_lock(&emu->register_mutex); + if (emu->client >= 0) { + snd_seq_delete_kernel_client(emu->client); + emu->client = -1; + } +- mutex_unlock(&emu->register_mutex); + } + + +@@ -269,8 +267,8 @@ snd_emux_event_input(struct snd_seq_event *ev, int direct, void *private_data, + /* + * increment usage count + */ +-int +-snd_emux_inc_count(struct snd_emux *emu) ++static int ++__snd_emux_inc_count(struct snd_emux *emu) + { + emu->used++; + if (!try_module_get(emu->ops.owner)) +@@ -284,12 +282,21 @@ snd_emux_inc_count(struct snd_emux *emu) + return 1; + } + ++int snd_emux_inc_count(struct snd_emux *emu) ++{ ++ int ret; ++ ++ mutex_lock(&emu->register_mutex); ++ ret = __snd_emux_inc_count(emu); ++ mutex_unlock(&emu->register_mutex); ++ return ret; ++} + + /* + * decrease usage count + */ +-void +-snd_emux_dec_count(struct snd_emux *emu) ++static void ++__snd_emux_dec_count(struct snd_emux *emu) + { + module_put(emu->card->module); + emu->used--; +@@ -298,6 +305,12 @@ snd_emux_dec_count(struct snd_emux *emu) + module_put(emu->ops.owner); + } + ++void snd_emux_dec_count(struct snd_emux *emu) ++{ ++ mutex_lock(&emu->register_mutex); ++ __snd_emux_dec_count(emu); ++ mutex_unlock(&emu->register_mutex); ++} + + /* + * Routine that is called upon a first use of a particular port +@@ -317,7 +330,7 @@ snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info) + + mutex_lock(&emu->register_mutex); + snd_emux_init_port(p); +- snd_emux_inc_count(emu); ++ __snd_emux_inc_count(emu); + mutex_unlock(&emu->register_mutex); + return 0; + } +@@ -340,7 +353,7 @@ snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info) + + mutex_lock(&emu->register_mutex); + snd_emux_sounds_off_all(p); +- snd_emux_dec_count(emu); ++ __snd_emux_dec_count(emu); + mutex_unlock(&emu->register_mutex); + return 0; + } diff --git a/patch/kernel/cubox-default/patch-3.14.42-43.patch b/patch/kernel/cubox-default/patch-3.14.42-43.patch new file mode 100644 index 000000000..7eda7cd36 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.42-43.patch @@ -0,0 +1,2548 @@ +diff --git a/Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt b/Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt +index a4873e5e3e36..e30e184f50c7 100644 +--- a/Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt ++++ b/Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt +@@ -38,7 +38,7 @@ dma_apbx: dma-apbx@80024000 { + 80 81 68 69 + 70 71 72 73 + 74 75 76 77>; +- interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty", ++ interrupt-names = "auart4-rx", "auart4-tx", "spdif-tx", "empty", + "saif0", "saif1", "i2c0", "i2c1", + "auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx", + "auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx"; +diff --git a/Makefile b/Makefile +index b9d850d86366..ae5f1e62812f 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 42 ++SUBLEVEL = 43 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts +index 1c6bd83bde5e..2ade35703d72 100644 +--- a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts ++++ b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts +@@ -69,6 +69,10 @@ + }; + + internal-regs { ++ rtc@10300 { ++ /* No crystal connected to the internal RTC */ ++ status = "disabled"; ++ }; + serial@12000 { + clock-frequency = <250000000>; + status = "okay"; +diff --git a/arch/arm/boot/dts/imx23-olinuxino.dts b/arch/arm/boot/dts/imx23-olinuxino.dts +index 526bfdbd87f9..f8922fb9bf50 100644 +--- a/arch/arm/boot/dts/imx23-olinuxino.dts ++++ b/arch/arm/boot/dts/imx23-olinuxino.dts +@@ -12,6 +12,7 @@ + */ + + /dts-v1/; ++#include + #include "imx23.dtsi" + + / { +@@ -93,6 +94,7 @@ + + ahb@80080000 { + usb0: usb@80080000 { ++ dr_mode = "host"; + vbus-supply = <®_usb0_vbus>; + status = "okay"; + }; +@@ -119,7 +121,7 @@ + + user { + label = "green"; +- gpios = <&gpio2 1 1>; ++ gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>; + }; + }; + }; +diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi +index cf3300a3071d..bfc327ff70af 100644 +--- a/arch/arm/boot/dts/imx25.dtsi ++++ b/arch/arm/boot/dts/imx25.dtsi +@@ -411,6 +411,7 @@ + + pwm4: pwm@53fc8000 { + compatible = "fsl,imx25-pwm", "fsl,imx27-pwm"; ++ #pwm-cells = <2>; + reg = <0x53fc8000 0x4000>; + clocks = <&clks 108>, <&clks 52>; + clock-names = "ipg", "per"; +diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi +index f8e9b20f6982..ee1a4da35cc4 100644 +--- a/arch/arm/boot/dts/imx28.dtsi ++++ b/arch/arm/boot/dts/imx28.dtsi +@@ -803,7 +803,7 @@ + 80 81 68 69 + 70 71 72 73 + 74 75 76 77>; +- interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty", ++ interrupt-names = "auart4-rx", "auart4-tx", "spdif-tx", "empty", + "saif0", "saif1", "i2c0", "i2c1", + "auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx", + "auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx"; +diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi +index e0853ea02df2..75e748efa9c2 100644 +--- a/arch/arm/boot/dts/ste-dbx5x0.dtsi ++++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi +@@ -985,23 +985,6 @@ + status = "disabled"; + }; + +- vmmci: regulator-gpio { +- compatible = "regulator-gpio"; +- +- regulator-min-microvolt = <1800000>; +- regulator-max-microvolt = <2900000>; +- regulator-name = "mmci-reg"; +- regulator-type = "voltage"; +- +- startup-delay-us = <100>; +- enable-active-high; +- +- states = <1800000 0x1 +- 2900000 0x0>; +- +- status = "disabled"; +- }; +- + mcde@a0350000 { + compatible = "stericsson,mcde"; + reg = <0xa0350000 0x1000>, /* MCDE */ +diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi +index 6cb9b68e2188..0b668f87dd40 100644 +--- a/arch/arm/boot/dts/ste-href.dtsi ++++ b/arch/arm/boot/dts/ste-href.dtsi +@@ -111,6 +111,21 @@ + pinctrl-1 = <&i2c3_sleep_mode>; + }; + ++ vmmci: regulator-gpio { ++ compatible = "regulator-gpio"; ++ ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <2900000>; ++ regulator-name = "mmci-reg"; ++ regulator-type = "voltage"; ++ ++ startup-delay-us = <100>; ++ enable-active-high; ++ ++ states = <1800000 0x1 ++ 2900000 0x0>; ++ }; ++ + // External Micro SD slot + sdi0_per1@80126000 { + arm,primecell-periphid = <0x10480180>; +diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts +index 97d5d21b7db7..5deaf3c1292f 100644 +--- a/arch/arm/boot/dts/ste-snowball.dts ++++ b/arch/arm/boot/dts/ste-snowball.dts +@@ -146,8 +146,21 @@ + }; + + vmmci: regulator-gpio { ++ compatible = "regulator-gpio"; ++ + gpios = <&gpio7 4 0x4>; + enable-gpio = <&gpio6 25 0x4>; ++ ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <2900000>; ++ regulator-name = "mmci-reg"; ++ regulator-type = "voltage"; ++ ++ startup-delay-us = <100>; ++ enable-active-high; ++ ++ states = <1800000 0x1 ++ 2900000 0x0>; + }; + + // External Micro SD slot +diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h +index 1d3153c7eb41..816db0bf2dd8 100644 +--- a/arch/arm/include/asm/kvm_arm.h ++++ b/arch/arm/include/asm/kvm_arm.h +@@ -55,6 +55,7 @@ + * The bits we set in HCR: + * TAC: Trap ACTLR + * TSC: Trap SMC ++ * TVM: Trap VM ops (until MMU and caches are on) + * TSW: Trap cache operations by set/way + * TWI: Trap WFI + * TWE: Trap WFE +@@ -68,8 +69,7 @@ + */ + #define HCR_GUEST_MASK (HCR_TSC | HCR_TSW | HCR_TWI | HCR_VM | HCR_BSU_IS | \ + HCR_FB | HCR_TAC | HCR_AMO | HCR_IMO | HCR_FMO | \ +- HCR_TWE | HCR_SWIO | HCR_TIDCP) +-#define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF) ++ HCR_TVM | HCR_TWE | HCR_SWIO | HCR_TIDCP) + + /* System Control Register (SCTLR) bits */ + #define SCTLR_TE (1 << 30) +diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h +index 661da11f76f4..53b3c4a50d5c 100644 +--- a/arch/arm/include/asm/kvm_asm.h ++++ b/arch/arm/include/asm/kvm_asm.h +@@ -48,7 +48,9 @@ + #define c13_TID_URO 26 /* Thread ID, User R/O */ + #define c13_TID_PRIV 27 /* Thread ID, Privileged */ + #define c14_CNTKCTL 28 /* Timer Control Register (PL1) */ +-#define NR_CP15_REGS 29 /* Number of regs (incl. invalid) */ ++#define c10_AMAIR0 29 /* Auxilary Memory Attribute Indirection Reg0 */ ++#define c10_AMAIR1 30 /* Auxilary Memory Attribute Indirection Reg1 */ ++#define NR_CP15_REGS 31 /* Number of regs (incl. invalid) */ + + #define ARM_EXCEPTION_RESET 0 + #define ARM_EXCEPTION_UNDEFINED 1 +diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h +index 098f7dd6d564..09af14999c9b 100644 +--- a/arch/arm/include/asm/kvm_host.h ++++ b/arch/arm/include/asm/kvm_host.h +@@ -101,6 +101,12 @@ struct kvm_vcpu_arch { + /* The CPU type we expose to the VM */ + u32 midr; + ++ /* HYP trapping configuration */ ++ u32 hcr; ++ ++ /* Interrupt related fields */ ++ u32 irq_lines; /* IRQ and FIQ levels */ ++ + /* Exception Information */ + struct kvm_vcpu_fault_info fault; + +@@ -128,9 +134,6 @@ struct kvm_vcpu_arch { + /* IO related fields */ + struct kvm_decode mmio_decode; + +- /* Interrupt related fields */ +- u32 irq_lines; /* IRQ and FIQ levels */ +- + /* Cache some mmu pages needed inside spinlock regions */ + struct kvm_mmu_memory_cache mmu_page_cache; + +diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h +index 2d122adcdb22..7b362bc9c09a 100644 +--- a/arch/arm/include/asm/kvm_mmu.h ++++ b/arch/arm/include/asm/kvm_mmu.h +@@ -114,11 +114,34 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd) + pmd_val(*pmd) |= L_PMD_S2_RDWR; + } + ++/* Open coded p*d_addr_end that can deal with 64bit addresses */ ++#define kvm_pgd_addr_end(addr, end) \ ++({ u64 __boundary = ((addr) + PGDIR_SIZE) & PGDIR_MASK; \ ++ (__boundary - 1 < (end) - 1)? __boundary: (end); \ ++}) ++ ++#define kvm_pud_addr_end(addr,end) (end) ++ ++#define kvm_pmd_addr_end(addr, end) \ ++({ u64 __boundary = ((addr) + PMD_SIZE) & PMD_MASK; \ ++ (__boundary - 1 < (end) - 1)? __boundary: (end); \ ++}) ++ + struct kvm; + +-static inline void coherent_icache_guest_page(struct kvm *kvm, hva_t hva, +- unsigned long size) ++#define kvm_flush_dcache_to_poc(a,l) __cpuc_flush_dcache_area((a), (l)) ++ ++static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu) + { ++ return (vcpu->arch.cp15[c1_SCTLR] & 0b101) == 0b101; ++} ++ ++static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva, ++ unsigned long size) ++{ ++ if (!vcpu_has_cache_enabled(vcpu)) ++ kvm_flush_dcache_to_poc((void *)hva, size); ++ + /* + * If we are going to insert an instruction page and the icache is + * either VIPT or PIPT, there is a potential problem where the host +@@ -139,9 +162,10 @@ static inline void coherent_icache_guest_page(struct kvm *kvm, hva_t hva, + } + } + +-#define kvm_flush_dcache_to_poc(a,l) __cpuc_flush_dcache_area((a), (l)) + #define kvm_virt_to_phys(x) virt_to_idmap((unsigned long)(x)) + ++void stage2_flush_vm(struct kvm *kvm); ++ + #endif /* !__ASSEMBLY__ */ + + #endif /* __ARM_KVM_MMU_H__ */ +diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c +index ded041711beb..85598b5d1efd 100644 +--- a/arch/arm/kernel/asm-offsets.c ++++ b/arch/arm/kernel/asm-offsets.c +@@ -174,6 +174,7 @@ int main(void) + DEFINE(VCPU_FIQ_REGS, offsetof(struct kvm_vcpu, arch.regs.fiq_regs)); + DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_pc)); + DEFINE(VCPU_CPSR, offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_cpsr)); ++ DEFINE(VCPU_HCR, offsetof(struct kvm_vcpu, arch.hcr)); + DEFINE(VCPU_IRQ_LINES, offsetof(struct kvm_vcpu, arch.irq_lines)); + DEFINE(VCPU_HSR, offsetof(struct kvm_vcpu, arch.fault.hsr)); + DEFINE(VCPU_HxFAR, offsetof(struct kvm_vcpu, arch.fault.hxfar)); +diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c +index 78c0885d6501..c58a35116f63 100644 +--- a/arch/arm/kvm/coproc.c ++++ b/arch/arm/kvm/coproc.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -205,6 +206,44 @@ done: + } + + /* ++ * Generic accessor for VM registers. Only called as long as HCR_TVM ++ * is set. ++ */ ++static bool access_vm_reg(struct kvm_vcpu *vcpu, ++ const struct coproc_params *p, ++ const struct coproc_reg *r) ++{ ++ BUG_ON(!p->is_write); ++ ++ vcpu->arch.cp15[r->reg] = *vcpu_reg(vcpu, p->Rt1); ++ if (p->is_64bit) ++ vcpu->arch.cp15[r->reg + 1] = *vcpu_reg(vcpu, p->Rt2); ++ ++ return true; ++} ++ ++/* ++ * SCTLR accessor. Only called as long as HCR_TVM is set. If the ++ * guest enables the MMU, we stop trapping the VM sys_regs and leave ++ * it in complete control of the caches. ++ * ++ * Used by the cpu-specific code. ++ */ ++bool access_sctlr(struct kvm_vcpu *vcpu, ++ const struct coproc_params *p, ++ const struct coproc_reg *r) ++{ ++ access_vm_reg(vcpu, p, r); ++ ++ if (vcpu_has_cache_enabled(vcpu)) { /* MMU+Caches enabled? */ ++ vcpu->arch.hcr &= ~HCR_TVM; ++ stage2_flush_vm(vcpu->kvm); ++ } ++ ++ return true; ++} ++ ++/* + * We could trap ID_DFR0 and tell the guest we don't support performance + * monitoring. Unfortunately the patch to make the kernel check ID_DFR0 was + * NAKed, so it will read the PMCR anyway. +@@ -261,33 +300,36 @@ static const struct coproc_reg cp15_regs[] = { + { CRn( 1), CRm( 0), Op1( 0), Op2( 2), is32, + NULL, reset_val, c1_CPACR, 0x00000000 }, + +- /* TTBR0/TTBR1: swapped by interrupt.S. */ +- { CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 }, +- { CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 }, +- +- /* TTBCR: swapped by interrupt.S. */ ++ /* TTBR0/TTBR1/TTBCR: swapped by interrupt.S. */ ++ { CRm64( 2), Op1( 0), is64, access_vm_reg, reset_unknown64, c2_TTBR0 }, ++ { CRn(2), CRm( 0), Op1( 0), Op2( 0), is32, ++ access_vm_reg, reset_unknown, c2_TTBR0 }, ++ { CRn(2), CRm( 0), Op1( 0), Op2( 1), is32, ++ access_vm_reg, reset_unknown, c2_TTBR1 }, + { CRn( 2), CRm( 0), Op1( 0), Op2( 2), is32, +- NULL, reset_val, c2_TTBCR, 0x00000000 }, ++ access_vm_reg, reset_val, c2_TTBCR, 0x00000000 }, ++ { CRm64( 2), Op1( 1), is64, access_vm_reg, reset_unknown64, c2_TTBR1 }, ++ + + /* DACR: swapped by interrupt.S. */ + { CRn( 3), CRm( 0), Op1( 0), Op2( 0), is32, +- NULL, reset_unknown, c3_DACR }, ++ access_vm_reg, reset_unknown, c3_DACR }, + + /* DFSR/IFSR/ADFSR/AIFSR: swapped by interrupt.S. */ + { CRn( 5), CRm( 0), Op1( 0), Op2( 0), is32, +- NULL, reset_unknown, c5_DFSR }, ++ access_vm_reg, reset_unknown, c5_DFSR }, + { CRn( 5), CRm( 0), Op1( 0), Op2( 1), is32, +- NULL, reset_unknown, c5_IFSR }, ++ access_vm_reg, reset_unknown, c5_IFSR }, + { CRn( 5), CRm( 1), Op1( 0), Op2( 0), is32, +- NULL, reset_unknown, c5_ADFSR }, ++ access_vm_reg, reset_unknown, c5_ADFSR }, + { CRn( 5), CRm( 1), Op1( 0), Op2( 1), is32, +- NULL, reset_unknown, c5_AIFSR }, ++ access_vm_reg, reset_unknown, c5_AIFSR }, + + /* DFAR/IFAR: swapped by interrupt.S. */ + { CRn( 6), CRm( 0), Op1( 0), Op2( 0), is32, +- NULL, reset_unknown, c6_DFAR }, ++ access_vm_reg, reset_unknown, c6_DFAR }, + { CRn( 6), CRm( 0), Op1( 0), Op2( 2), is32, +- NULL, reset_unknown, c6_IFAR }, ++ access_vm_reg, reset_unknown, c6_IFAR }, + + /* PAR swapped by interrupt.S */ + { CRm64( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR }, +@@ -324,9 +366,15 @@ static const struct coproc_reg cp15_regs[] = { + + /* PRRR/NMRR (aka MAIR0/MAIR1): swapped by interrupt.S. */ + { CRn(10), CRm( 2), Op1( 0), Op2( 0), is32, +- NULL, reset_unknown, c10_PRRR}, ++ access_vm_reg, reset_unknown, c10_PRRR}, + { CRn(10), CRm( 2), Op1( 0), Op2( 1), is32, +- NULL, reset_unknown, c10_NMRR}, ++ access_vm_reg, reset_unknown, c10_NMRR}, ++ ++ /* AMAIR0/AMAIR1: swapped by interrupt.S. */ ++ { CRn(10), CRm( 3), Op1( 0), Op2( 0), is32, ++ access_vm_reg, reset_unknown, c10_AMAIR0}, ++ { CRn(10), CRm( 3), Op1( 0), Op2( 1), is32, ++ access_vm_reg, reset_unknown, c10_AMAIR1}, + + /* VBAR: swapped by interrupt.S. */ + { CRn(12), CRm( 0), Op1( 0), Op2( 0), is32, +@@ -334,7 +382,7 @@ static const struct coproc_reg cp15_regs[] = { + + /* CONTEXTIDR/TPIDRURW/TPIDRURO/TPIDRPRW: swapped by interrupt.S. */ + { CRn(13), CRm( 0), Op1( 0), Op2( 1), is32, +- NULL, reset_val, c13_CID, 0x00000000 }, ++ access_vm_reg, reset_val, c13_CID, 0x00000000 }, + { CRn(13), CRm( 0), Op1( 0), Op2( 2), is32, + NULL, reset_unknown, c13_TID_URW }, + { CRn(13), CRm( 0), Op1( 0), Op2( 3), is32, +@@ -443,7 +491,7 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) + { + struct coproc_params params; + +- params.CRm = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf; ++ params.CRn = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf; + params.Rt1 = (kvm_vcpu_get_hsr(vcpu) >> 5) & 0xf; + params.is_write = ((kvm_vcpu_get_hsr(vcpu) & 1) == 0); + params.is_64bit = true; +@@ -451,7 +499,7 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) + params.Op1 = (kvm_vcpu_get_hsr(vcpu) >> 16) & 0xf; + params.Op2 = 0; + params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf; +- params.CRn = 0; ++ params.CRm = 0; + + return emulate_cp15(vcpu, ¶ms); + } +diff --git a/arch/arm/kvm/coproc.h b/arch/arm/kvm/coproc.h +index 0461d5c8d3de..1a44bbe39643 100644 +--- a/arch/arm/kvm/coproc.h ++++ b/arch/arm/kvm/coproc.h +@@ -58,8 +58,8 @@ static inline void print_cp_instr(const struct coproc_params *p) + { + /* Look, we even formatted it for you to paste into the table! */ + if (p->is_64bit) { +- kvm_pr_unimpl(" { CRm(%2lu), Op1(%2lu), is64, func_%s },\n", +- p->CRm, p->Op1, p->is_write ? "write" : "read"); ++ kvm_pr_unimpl(" { CRm64(%2lu), Op1(%2lu), is64, func_%s },\n", ++ p->CRn, p->Op1, p->is_write ? "write" : "read"); + } else { + kvm_pr_unimpl(" { CRn(%2lu), CRm(%2lu), Op1(%2lu), Op2(%2lu), is32," + " func_%s },\n", +@@ -135,13 +135,13 @@ static inline int cmp_reg(const struct coproc_reg *i1, + return -1; + if (i1->CRn != i2->CRn) + return i1->CRn - i2->CRn; +- if (i1->is_64 != i2->is_64) +- return i2->is_64 - i1->is_64; + if (i1->CRm != i2->CRm) + return i1->CRm - i2->CRm; + if (i1->Op1 != i2->Op1) + return i1->Op1 - i2->Op1; +- return i1->Op2 - i2->Op2; ++ if (i1->Op2 != i2->Op2) ++ return i1->Op2 - i2->Op2; ++ return i2->is_64 - i1->is_64; + } + + +@@ -153,4 +153,8 @@ static inline int cmp_reg(const struct coproc_reg *i1, + #define is64 .is_64 = true + #define is32 .is_64 = false + ++bool access_sctlr(struct kvm_vcpu *vcpu, ++ const struct coproc_params *p, ++ const struct coproc_reg *r); ++ + #endif /* __ARM_KVM_COPROC_LOCAL_H__ */ +diff --git a/arch/arm/kvm/coproc_a15.c b/arch/arm/kvm/coproc_a15.c +index bb0cac1410cc..e6f4ae48bda9 100644 +--- a/arch/arm/kvm/coproc_a15.c ++++ b/arch/arm/kvm/coproc_a15.c +@@ -34,7 +34,7 @@ + static const struct coproc_reg a15_regs[] = { + /* SCTLR: swapped by interrupt.S. */ + { CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32, +- NULL, reset_val, c1_SCTLR, 0x00C50078 }, ++ access_sctlr, reset_val, c1_SCTLR, 0x00C50078 }, + }; + + static struct kvm_coproc_target_table a15_target_table = { +diff --git a/arch/arm/kvm/coproc_a7.c b/arch/arm/kvm/coproc_a7.c +index 1df767331588..17fc7cd479d3 100644 +--- a/arch/arm/kvm/coproc_a7.c ++++ b/arch/arm/kvm/coproc_a7.c +@@ -37,7 +37,7 @@ + static const struct coproc_reg a7_regs[] = { + /* SCTLR: swapped by interrupt.S. */ + { CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32, +- NULL, reset_val, c1_SCTLR, 0x00C50878 }, ++ access_sctlr, reset_val, c1_SCTLR, 0x00C50878 }, + }; + + static struct kvm_coproc_target_table a7_target_table = { +diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c +index 2786eae10c0d..b23a59c1c522 100644 +--- a/arch/arm/kvm/guest.c ++++ b/arch/arm/kvm/guest.c +@@ -38,6 +38,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { + + int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) + { ++ vcpu->arch.hcr = HCR_GUEST_MASK; + return 0; + } + +diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S +index 6f18695a09cb..76af93025574 100644 +--- a/arch/arm/kvm/interrupts_head.S ++++ b/arch/arm/kvm/interrupts_head.S +@@ -303,13 +303,17 @@ vcpu .req r0 @ vcpu pointer always in r0 + + mrc p15, 0, r2, c14, c1, 0 @ CNTKCTL + mrrc p15, 0, r4, r5, c7 @ PAR ++ mrc p15, 0, r6, c10, c3, 0 @ AMAIR0 ++ mrc p15, 0, r7, c10, c3, 1 @ AMAIR1 + + .if \store_to_vcpu == 0 +- push {r2,r4-r5} ++ push {r2,r4-r7} + .else + str r2, [vcpu, #CP15_OFFSET(c14_CNTKCTL)] + add r12, vcpu, #CP15_OFFSET(c7_PAR) + strd r4, r5, [r12] ++ str r6, [vcpu, #CP15_OFFSET(c10_AMAIR0)] ++ str r7, [vcpu, #CP15_OFFSET(c10_AMAIR1)] + .endif + .endm + +@@ -322,15 +326,19 @@ vcpu .req r0 @ vcpu pointer always in r0 + */ + .macro write_cp15_state read_from_vcpu + .if \read_from_vcpu == 0 +- pop {r2,r4-r5} ++ pop {r2,r4-r7} + .else + ldr r2, [vcpu, #CP15_OFFSET(c14_CNTKCTL)] + add r12, vcpu, #CP15_OFFSET(c7_PAR) + ldrd r4, r5, [r12] ++ ldr r6, [vcpu, #CP15_OFFSET(c10_AMAIR0)] ++ ldr r7, [vcpu, #CP15_OFFSET(c10_AMAIR1)] + .endif + + mcr p15, 0, r2, c14, c1, 0 @ CNTKCTL + mcrr p15, 0, r4, r5, c7 @ PAR ++ mcr p15, 0, r6, c10, c3, 0 @ AMAIR0 ++ mcr p15, 0, r7, c10, c3, 1 @ AMAIR1 + + .if \read_from_vcpu == 0 + pop {r2-r12} +@@ -597,17 +605,14 @@ vcpu .req r0 @ vcpu pointer always in r0 + + /* Enable/Disable: stage-2 trans., trap interrupts, trap wfi, trap smc */ + .macro configure_hyp_role operation +- mrc p15, 4, r2, c1, c1, 0 @ HCR +- bic r2, r2, #HCR_VIRT_EXCP_MASK +- ldr r3, =HCR_GUEST_MASK + .if \operation == vmentry +- orr r2, r2, r3 ++ ldr r2, [vcpu, #VCPU_HCR] + ldr r3, [vcpu, #VCPU_IRQ_LINES] + orr r2, r2, r3 + .else +- bic r2, r2, r3 ++ mov r2, #0 + .endif +- mcr p15, 4, r2, c1, c1, 0 ++ mcr p15, 4, r2, c1, c1, 0 @ HCR + .endm + + .macro load_vcpu +diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c +index 575d7904305b..c93ef38f9cb0 100644 +--- a/arch/arm/kvm/mmu.c ++++ b/arch/arm/kvm/mmu.c +@@ -147,7 +147,7 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp, + pgd = pgdp + pgd_index(addr); + pud = pud_offset(pgd, addr); + if (pud_none(*pud)) { +- addr = pud_addr_end(addr, end); ++ addr = kvm_pud_addr_end(addr, end); + continue; + } + +@@ -157,13 +157,13 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp, + * move on. + */ + clear_pud_entry(kvm, pud, addr); +- addr = pud_addr_end(addr, end); ++ addr = kvm_pud_addr_end(addr, end); + continue; + } + + pmd = pmd_offset(pud, addr); + if (pmd_none(*pmd)) { +- addr = pmd_addr_end(addr, end); ++ addr = kvm_pmd_addr_end(addr, end); + continue; + } + +@@ -178,10 +178,10 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp, + */ + if (kvm_pmd_huge(*pmd) || page_empty(pte)) { + clear_pmd_entry(kvm, pmd, addr); +- next = pmd_addr_end(addr, end); ++ next = kvm_pmd_addr_end(addr, end); + if (page_empty(pmd) && !page_empty(pud)) { + clear_pud_entry(kvm, pud, addr); +- next = pud_addr_end(addr, end); ++ next = kvm_pud_addr_end(addr, end); + } + } + +@@ -189,6 +189,99 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp, + } + } + ++static void stage2_flush_ptes(struct kvm *kvm, pmd_t *pmd, ++ phys_addr_t addr, phys_addr_t end) ++{ ++ pte_t *pte; ++ ++ pte = pte_offset_kernel(pmd, addr); ++ do { ++ if (!pte_none(*pte)) { ++ hva_t hva = gfn_to_hva(kvm, addr >> PAGE_SHIFT); ++ kvm_flush_dcache_to_poc((void*)hva, PAGE_SIZE); ++ } ++ } while (pte++, addr += PAGE_SIZE, addr != end); ++} ++ ++static void stage2_flush_pmds(struct kvm *kvm, pud_t *pud, ++ phys_addr_t addr, phys_addr_t end) ++{ ++ pmd_t *pmd; ++ phys_addr_t next; ++ ++ pmd = pmd_offset(pud, addr); ++ do { ++ next = kvm_pmd_addr_end(addr, end); ++ if (!pmd_none(*pmd)) { ++ if (kvm_pmd_huge(*pmd)) { ++ hva_t hva = gfn_to_hva(kvm, addr >> PAGE_SHIFT); ++ kvm_flush_dcache_to_poc((void*)hva, PMD_SIZE); ++ } else { ++ stage2_flush_ptes(kvm, pmd, addr, next); ++ } ++ } ++ } while (pmd++, addr = next, addr != end); ++} ++ ++static void stage2_flush_puds(struct kvm *kvm, pgd_t *pgd, ++ phys_addr_t addr, phys_addr_t end) ++{ ++ pud_t *pud; ++ phys_addr_t next; ++ ++ pud = pud_offset(pgd, addr); ++ do { ++ next = kvm_pud_addr_end(addr, end); ++ if (!pud_none(*pud)) { ++ if (pud_huge(*pud)) { ++ hva_t hva = gfn_to_hva(kvm, addr >> PAGE_SHIFT); ++ kvm_flush_dcache_to_poc((void*)hva, PUD_SIZE); ++ } else { ++ stage2_flush_pmds(kvm, pud, addr, next); ++ } ++ } ++ } while (pud++, addr = next, addr != end); ++} ++ ++static void stage2_flush_memslot(struct kvm *kvm, ++ struct kvm_memory_slot *memslot) ++{ ++ phys_addr_t addr = memslot->base_gfn << PAGE_SHIFT; ++ phys_addr_t end = addr + PAGE_SIZE * memslot->npages; ++ phys_addr_t next; ++ pgd_t *pgd; ++ ++ pgd = kvm->arch.pgd + pgd_index(addr); ++ do { ++ next = kvm_pgd_addr_end(addr, end); ++ stage2_flush_puds(kvm, pgd, addr, next); ++ } while (pgd++, addr = next, addr != end); ++} ++ ++/** ++ * stage2_flush_vm - Invalidate cache for pages mapped in stage 2 ++ * @kvm: The struct kvm pointer ++ * ++ * Go through the stage 2 page tables and invalidate any cache lines ++ * backing memory already mapped to the VM. ++ */ ++void stage2_flush_vm(struct kvm *kvm) ++{ ++ struct kvm_memslots *slots; ++ struct kvm_memory_slot *memslot; ++ int idx; ++ ++ idx = srcu_read_lock(&kvm->srcu); ++ spin_lock(&kvm->mmu_lock); ++ ++ slots = kvm_memslots(kvm); ++ kvm_for_each_memslot(memslot, slots) ++ stage2_flush_memslot(kvm, memslot); ++ ++ spin_unlock(&kvm->mmu_lock); ++ srcu_read_unlock(&kvm->srcu, idx); ++} ++ + /** + * free_boot_hyp_pgd - free HYP boot page tables + * +@@ -717,7 +810,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + kvm_set_s2pmd_writable(&new_pmd); + kvm_set_pfn_dirty(pfn); + } +- coherent_icache_guest_page(kvm, hva & PMD_MASK, PMD_SIZE); ++ coherent_cache_guest_page(vcpu, hva & PMD_MASK, PMD_SIZE); + ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd); + } else { + pte_t new_pte = pfn_pte(pfn, PAGE_S2); +@@ -725,7 +818,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + kvm_set_s2pte_writable(&new_pte); + kvm_set_pfn_dirty(pfn); + } +- coherent_icache_guest_page(kvm, hva, PAGE_SIZE); ++ coherent_cache_guest_page(vcpu, hva, PAGE_SIZE); + ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, false); + } + +diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c +index 271b5e971568..6adf5913a7ac 100644 +--- a/arch/arm/net/bpf_jit_32.c ++++ b/arch/arm/net/bpf_jit_32.c +@@ -449,10 +449,21 @@ static inline void emit_udiv(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx) + return; + } + #endif +- if (rm != ARM_R0) +- emit(ARM_MOV_R(ARM_R0, rm), ctx); ++ ++ /* ++ * For BPF_ALU | BPF_DIV | BPF_K instructions, rm is ARM_R4 ++ * (r_A) and rn is ARM_R0 (r_scratch) so load rn first into ++ * ARM_R1 to avoid accidentally overwriting ARM_R0 with rm ++ * before using it as a source for ARM_R1. ++ * ++ * For BPF_ALU | BPF_DIV | BPF_X rm is ARM_R4 (r_A) and rn is ++ * ARM_R5 (r_X) so there is no particular register overlap ++ * issues. ++ */ + if (rn != ARM_R1) + emit(ARM_MOV_R(ARM_R1, rn), ctx); ++ if (rm != ARM_R0) ++ emit(ARM_MOV_R(ARM_R0, rm), ctx); + + ctx->seen |= SEEN_CALL; + emit_mov_i(ARM_R3, (u32)jit_udiv, ctx); +diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h +index 0eb398655378..00fbaa75dc7b 100644 +--- a/arch/arm64/include/asm/kvm_arm.h ++++ b/arch/arm64/include/asm/kvm_arm.h +@@ -62,6 +62,7 @@ + * RW: 64bit by default, can be overriden for 32bit VMs + * TAC: Trap ACTLR + * TSC: Trap SMC ++ * TVM: Trap VM ops (until M+C set in SCTLR_EL1) + * TSW: Trap cache operations by set/way + * TWE: Trap WFE + * TWI: Trap WFI +@@ -74,7 +75,7 @@ + * SWIO: Turn set/way invalidates into set/way clean+invalidate + */ + #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \ +- HCR_BSU_IS | HCR_FB | HCR_TAC | \ ++ HCR_TVM | HCR_BSU_IS | HCR_FB | HCR_TAC | \ + HCR_AMO | HCR_IMO | HCR_FMO | \ + HCR_SWIO | HCR_TIDCP | HCR_RW) + #define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF) +diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h +index b25763bc0ec4..9fcd54b1e16d 100644 +--- a/arch/arm64/include/asm/kvm_asm.h ++++ b/arch/arm64/include/asm/kvm_asm.h +@@ -79,7 +79,8 @@ + #define c13_TID_URW (TPIDR_EL0 * 2) /* Thread ID, User R/W */ + #define c13_TID_URO (TPIDRRO_EL0 * 2)/* Thread ID, User R/O */ + #define c13_TID_PRIV (TPIDR_EL1 * 2) /* Thread ID, Privileged */ +-#define c10_AMAIR (AMAIR_EL1 * 2) /* Aux Memory Attr Indirection Reg */ ++#define c10_AMAIR0 (AMAIR_EL1 * 2) /* Aux Memory Attr Indirection Reg */ ++#define c10_AMAIR1 (c10_AMAIR0 + 1)/* Aux Memory Attr Indirection Reg */ + #define c14_CNTKCTL (CNTKCTL_EL1 * 2) /* Timer Control Register (PL1) */ + #define NR_CP15_REGS (NR_SYS_REGS * 2) + +diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h +index 7f1f9408ff66..7d29847a893b 100644 +--- a/arch/arm64/include/asm/kvm_mmu.h ++++ b/arch/arm64/include/asm/kvm_mmu.h +@@ -106,7 +106,6 @@ static inline bool kvm_is_write_fault(unsigned long esr) + return true; + } + +-static inline void kvm_clean_dcache_area(void *addr, size_t size) {} + static inline void kvm_clean_pgd(pgd_t *pgd) {} + static inline void kvm_clean_pmd_entry(pmd_t *pmd) {} + static inline void kvm_clean_pte(pte_t *pte) {} +@@ -122,11 +121,25 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd) + pmd_val(*pmd) |= PMD_S2_RDWR; + } + ++#define kvm_pgd_addr_end(addr, end) pgd_addr_end(addr, end) ++#define kvm_pud_addr_end(addr, end) pud_addr_end(addr, end) ++#define kvm_pmd_addr_end(addr, end) pmd_addr_end(addr, end) ++ + struct kvm; + +-static inline void coherent_icache_guest_page(struct kvm *kvm, hva_t hva, +- unsigned long size) ++#define kvm_flush_dcache_to_poc(a,l) __flush_dcache_area((a), (l)) ++ ++static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu) + { ++ return (vcpu_sys_reg(vcpu, SCTLR_EL1) & 0b101) == 0b101; ++} ++ ++static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva, ++ unsigned long size) ++{ ++ if (!vcpu_has_cache_enabled(vcpu)) ++ kvm_flush_dcache_to_poc((void *)hva, size); ++ + if (!icache_is_aliasing()) { /* PIPT */ + flush_icache_range(hva, hva + size); + } else if (!icache_is_aivivt()) { /* non ASID-tagged VIVT */ +@@ -135,8 +148,9 @@ static inline void coherent_icache_guest_page(struct kvm *kvm, hva_t hva, + } + } + +-#define kvm_flush_dcache_to_poc(a,l) __flush_dcache_area((a), (l)) + #define kvm_virt_to_phys(x) __virt_to_phys((unsigned long)(x)) + ++void stage2_flush_vm(struct kvm *kvm); ++ + #endif /* __ASSEMBLY__ */ + #endif /* __ARM64_KVM_MMU_H__ */ +diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S +index 2c56012cb2d2..b0d1512acf08 100644 +--- a/arch/arm64/kvm/hyp.S ++++ b/arch/arm64/kvm/hyp.S +@@ -630,9 +630,15 @@ ENTRY(__kvm_tlb_flush_vmid_ipa) + * whole of Stage-1. Weep... + */ + tlbi ipas2e1is, x1 +- dsb sy ++ /* ++ * We have to ensure completion of the invalidation at Stage-2, ++ * since a table walk on another CPU could refill a TLB with a ++ * complete (S1 + S2) walk based on the old Stage-2 mapping if ++ * the Stage-1 invalidation happened first. ++ */ ++ dsb ish + tlbi vmalle1is +- dsb sy ++ dsb ish + isb + + msr vttbr_el2, xzr +@@ -643,7 +649,7 @@ ENTRY(__kvm_flush_vm_context) + dsb ishst + tlbi alle1is + ic ialluis +- dsb sy ++ dsb ish + ret + ENDPROC(__kvm_flush_vm_context) + +diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c +index 02e9d09e1d80..03244582bc55 100644 +--- a/arch/arm64/kvm/sys_regs.c ++++ b/arch/arm64/kvm/sys_regs.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -121,6 +122,48 @@ done: + } + + /* ++ * Generic accessor for VM registers. Only called as long as HCR_TVM ++ * is set. ++ */ ++static bool access_vm_reg(struct kvm_vcpu *vcpu, ++ const struct sys_reg_params *p, ++ const struct sys_reg_desc *r) ++{ ++ unsigned long val; ++ ++ BUG_ON(!p->is_write); ++ ++ val = *vcpu_reg(vcpu, p->Rt); ++ if (!p->is_aarch32) { ++ vcpu_sys_reg(vcpu, r->reg) = val; ++ } else { ++ vcpu_cp15(vcpu, r->reg) = val & 0xffffffffUL; ++ if (!p->is_32bit) ++ vcpu_cp15(vcpu, r->reg + 1) = val >> 32; ++ } ++ return true; ++} ++ ++/* ++ * SCTLR_EL1 accessor. Only called as long as HCR_TVM is set. If the ++ * guest enables the MMU, we stop trapping the VM sys_regs and leave ++ * it in complete control of the caches. ++ */ ++static bool access_sctlr(struct kvm_vcpu *vcpu, ++ const struct sys_reg_params *p, ++ const struct sys_reg_desc *r) ++{ ++ access_vm_reg(vcpu, p, r); ++ ++ if (vcpu_has_cache_enabled(vcpu)) { /* MMU+Caches enabled? */ ++ vcpu->arch.hcr_el2 &= ~HCR_TVM; ++ stage2_flush_vm(vcpu->kvm); ++ } ++ ++ return true; ++} ++ ++/* + * We could trap ID_DFR0 and tell the guest we don't support performance + * monitoring. Unfortunately the patch to make the kernel check ID_DFR0 was + * NAKed, so it will read the PMCR anyway. +@@ -185,32 +228,32 @@ static const struct sys_reg_desc sys_reg_descs[] = { + NULL, reset_mpidr, MPIDR_EL1 }, + /* SCTLR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0001), CRm(0b0000), Op2(0b000), +- NULL, reset_val, SCTLR_EL1, 0x00C50078 }, ++ access_sctlr, reset_val, SCTLR_EL1, 0x00C50078 }, + /* CPACR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0001), CRm(0b0000), Op2(0b010), + NULL, reset_val, CPACR_EL1, 0 }, + /* TTBR0_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0010), CRm(0b0000), Op2(0b000), +- NULL, reset_unknown, TTBR0_EL1 }, ++ access_vm_reg, reset_unknown, TTBR0_EL1 }, + /* TTBR1_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0010), CRm(0b0000), Op2(0b001), +- NULL, reset_unknown, TTBR1_EL1 }, ++ access_vm_reg, reset_unknown, TTBR1_EL1 }, + /* TCR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0010), CRm(0b0000), Op2(0b010), +- NULL, reset_val, TCR_EL1, 0 }, ++ access_vm_reg, reset_val, TCR_EL1, 0 }, + + /* AFSR0_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0101), CRm(0b0001), Op2(0b000), +- NULL, reset_unknown, AFSR0_EL1 }, ++ access_vm_reg, reset_unknown, AFSR0_EL1 }, + /* AFSR1_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0101), CRm(0b0001), Op2(0b001), +- NULL, reset_unknown, AFSR1_EL1 }, ++ access_vm_reg, reset_unknown, AFSR1_EL1 }, + /* ESR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0101), CRm(0b0010), Op2(0b000), +- NULL, reset_unknown, ESR_EL1 }, ++ access_vm_reg, reset_unknown, ESR_EL1 }, + /* FAR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0110), CRm(0b0000), Op2(0b000), +- NULL, reset_unknown, FAR_EL1 }, ++ access_vm_reg, reset_unknown, FAR_EL1 }, + /* PAR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0111), CRm(0b0100), Op2(0b000), + NULL, reset_unknown, PAR_EL1 }, +@@ -224,17 +267,17 @@ static const struct sys_reg_desc sys_reg_descs[] = { + + /* MAIR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b1010), CRm(0b0010), Op2(0b000), +- NULL, reset_unknown, MAIR_EL1 }, ++ access_vm_reg, reset_unknown, MAIR_EL1 }, + /* AMAIR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b1010), CRm(0b0011), Op2(0b000), +- NULL, reset_amair_el1, AMAIR_EL1 }, ++ access_vm_reg, reset_amair_el1, AMAIR_EL1 }, + + /* VBAR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b0000), Op2(0b000), + NULL, reset_val, VBAR_EL1, 0 }, + /* CONTEXTIDR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b0000), Op2(0b001), +- NULL, reset_val, CONTEXTIDR_EL1, 0 }, ++ access_vm_reg, reset_val, CONTEXTIDR_EL1, 0 }, + /* TPIDR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b0000), Op2(0b100), + NULL, reset_unknown, TPIDR_EL1 }, +@@ -305,14 +348,32 @@ static const struct sys_reg_desc sys_reg_descs[] = { + NULL, reset_val, FPEXC32_EL2, 0x70 }, + }; + +-/* Trapped cp15 registers */ ++/* ++ * Trapped cp15 registers. TTBR0/TTBR1 get a double encoding, ++ * depending on the way they are accessed (as a 32bit or a 64bit ++ * register). ++ */ + static const struct sys_reg_desc cp15_regs[] = { ++ { Op1( 0), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR0 }, ++ { Op1( 0), CRn( 1), CRm( 0), Op2( 0), access_sctlr, NULL, c1_SCTLR }, ++ { Op1( 0), CRn( 2), CRm( 0), Op2( 0), access_vm_reg, NULL, c2_TTBR0 }, ++ { Op1( 0), CRn( 2), CRm( 0), Op2( 1), access_vm_reg, NULL, c2_TTBR1 }, ++ { Op1( 0), CRn( 2), CRm( 0), Op2( 2), access_vm_reg, NULL, c2_TTBCR }, ++ { Op1( 0), CRn( 3), CRm( 0), Op2( 0), access_vm_reg, NULL, c3_DACR }, ++ { Op1( 0), CRn( 5), CRm( 0), Op2( 0), access_vm_reg, NULL, c5_DFSR }, ++ { Op1( 0), CRn( 5), CRm( 0), Op2( 1), access_vm_reg, NULL, c5_IFSR }, ++ { Op1( 0), CRn( 5), CRm( 1), Op2( 0), access_vm_reg, NULL, c5_ADFSR }, ++ { Op1( 0), CRn( 5), CRm( 1), Op2( 1), access_vm_reg, NULL, c5_AIFSR }, ++ { Op1( 0), CRn( 6), CRm( 0), Op2( 0), access_vm_reg, NULL, c6_DFAR }, ++ { Op1( 0), CRn( 6), CRm( 0), Op2( 2), access_vm_reg, NULL, c6_IFAR }, ++ + /* + * DC{C,I,CI}SW operations: + */ + { Op1( 0), CRn( 7), CRm( 6), Op2( 2), access_dcsw }, + { Op1( 0), CRn( 7), CRm(10), Op2( 2), access_dcsw }, + { Op1( 0), CRn( 7), CRm(14), Op2( 2), access_dcsw }, ++ + { Op1( 0), CRn( 9), CRm(12), Op2( 0), pm_fake }, + { Op1( 0), CRn( 9), CRm(12), Op2( 1), pm_fake }, + { Op1( 0), CRn( 9), CRm(12), Op2( 2), pm_fake }, +@@ -326,6 +387,14 @@ static const struct sys_reg_desc cp15_regs[] = { + { Op1( 0), CRn( 9), CRm(14), Op2( 0), pm_fake }, + { Op1( 0), CRn( 9), CRm(14), Op2( 1), pm_fake }, + { Op1( 0), CRn( 9), CRm(14), Op2( 2), pm_fake }, ++ ++ { Op1( 0), CRn(10), CRm( 2), Op2( 0), access_vm_reg, NULL, c10_PRRR }, ++ { Op1( 0), CRn(10), CRm( 2), Op2( 1), access_vm_reg, NULL, c10_NMRR }, ++ { Op1( 0), CRn(10), CRm( 3), Op2( 0), access_vm_reg, NULL, c10_AMAIR0 }, ++ { Op1( 0), CRn(10), CRm( 3), Op2( 1), access_vm_reg, NULL, c10_AMAIR1 }, ++ { Op1( 0), CRn(13), CRm( 0), Op2( 1), access_vm_reg, NULL, c13_CID }, ++ ++ { Op1( 1), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR1 }, + }; + + /* Target specific emulation tables */ +@@ -437,6 +506,8 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) + u32 hsr = kvm_vcpu_get_hsr(vcpu); + int Rt2 = (hsr >> 10) & 0xf; + ++ params.is_aarch32 = true; ++ params.is_32bit = false; + params.CRm = (hsr >> 1) & 0xf; + params.Rt = (hsr >> 5) & 0xf; + params.is_write = ((hsr & 1) == 0); +@@ -480,6 +551,8 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) + struct sys_reg_params params; + u32 hsr = kvm_vcpu_get_hsr(vcpu); + ++ params.is_aarch32 = true; ++ params.is_32bit = true; + params.CRm = (hsr >> 1) & 0xf; + params.Rt = (hsr >> 5) & 0xf; + params.is_write = ((hsr & 1) == 0); +@@ -549,6 +622,8 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run) + struct sys_reg_params params; + unsigned long esr = kvm_vcpu_get_hsr(vcpu); + ++ params.is_aarch32 = false; ++ params.is_32bit = false; + params.Op0 = (esr >> 20) & 3; + params.Op1 = (esr >> 14) & 0x7; + params.CRn = (esr >> 10) & 0xf; +diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h +index d50d3722998e..d411e251412c 100644 +--- a/arch/arm64/kvm/sys_regs.h ++++ b/arch/arm64/kvm/sys_regs.h +@@ -30,6 +30,8 @@ struct sys_reg_params { + u8 Op2; + u8 Rt; + bool is_write; ++ bool is_aarch32; ++ bool is_32bit; /* Only valid if is_aarch32 is true */ + }; + + struct sys_reg_desc { +diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h +index 2a86c65d873b..97c7a52dfb4a 100644 +--- a/drivers/acpi/acpica/acmacros.h ++++ b/drivers/acpi/acpica/acmacros.h +@@ -63,19 +63,15 @@ + #define ACPI_SET64(ptr, val) (*ACPI_CAST64 (ptr) = (u64) (val)) + + /* +- * printf() format helpers ++ * printf() format helper. This macros is a workaround for the difficulties ++ * with emitting 64-bit integers and 64-bit pointers with the same code ++ * for both 32-bit and 64-bit hosts. + */ + + /* Split 64-bit integer into two 32-bit values. Use with %8.8X%8.8X */ + + #define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i), ACPI_LODWORD(i) + +-#if ACPI_MACHINE_WIDTH == 64 +-#define ACPI_FORMAT_NATIVE_UINT(i) ACPI_FORMAT_UINT64(i) +-#else +-#define ACPI_FORMAT_NATIVE_UINT(i) 0, (i) +-#endif +- + /* + * Macros for moving data around to/from buffers that are possibly unaligned. + * If the hardware supports the transfer of unaligned data, just do the store. +diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c +index 5205edcf2c01..fe79296fdd9e 100644 +--- a/drivers/acpi/acpica/dsopcode.c ++++ b/drivers/acpi/acpica/dsopcode.c +@@ -446,7 +446,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", + obj_desc, +- ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), ++ ACPI_FORMAT_UINT64(obj_desc->region.address), + obj_desc->region.length)); + + /* Now the address and length are valid for this opregion */ +@@ -539,13 +539,12 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, + return_ACPI_STATUS(AE_NOT_EXIST); + } + +- obj_desc->region.address = +- (acpi_physical_address) ACPI_TO_INTEGER(table); ++ obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table); + obj_desc->region.length = table->length; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", + obj_desc, +- ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), ++ ACPI_FORMAT_UINT64(obj_desc->region.address), + obj_desc->region.length)); + + /* Now the address and length are valid for this opregion */ +diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c +index cd4b231ae760..ee8ec4bf0611 100644 +--- a/drivers/acpi/acpica/evregion.c ++++ b/drivers/acpi/acpica/evregion.c +@@ -272,7 +272,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", + ®ion_obj->region.handler->address_space, handler, +- ACPI_FORMAT_NATIVE_UINT(address), ++ ACPI_FORMAT_UINT64(address), + acpi_ut_get_region_name(region_obj->region. + space_id))); + +diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c +index 4d046faac48c..b64fb68aa5d3 100644 +--- a/drivers/acpi/acpica/exdump.c ++++ b/drivers/acpi/acpica/exdump.c +@@ -622,8 +622,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) + acpi_os_printf("\n"); + } else { + acpi_os_printf(" base %8.8X%8.8X Length %X\n", +- ACPI_FORMAT_NATIVE_UINT(obj_desc->region. +- address), ++ ACPI_FORMAT_UINT64(obj_desc->region. ++ address), + obj_desc->region.length); + } + break; +diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c +index 49fb742d61b9..98af39f0d677 100644 +--- a/drivers/acpi/acpica/exfldio.c ++++ b/drivers/acpi/acpica/exfldio.c +@@ -263,17 +263,15 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD, +- " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n", ++ " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n", + acpi_ut_get_region_name(rgn_desc->region. + space_id), + rgn_desc->region.space_id, + obj_desc->common_field.access_byte_width, + obj_desc->common_field.base_byte_offset, +- field_datum_byte_offset, ACPI_CAST_PTR(void, +- (rgn_desc-> +- region. +- address + +- region_offset)))); ++ field_datum_byte_offset, ++ ACPI_FORMAT_UINT64(rgn_desc->region.address + ++ region_offset))); + + /* Invoke the appropriate address_space/op_region handler */ + +diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c +index 9d28867e60dc..cf4022359dc7 100644 +--- a/drivers/acpi/acpica/exregion.c ++++ b/drivers/acpi/acpica/exregion.c +@@ -181,7 +181,7 @@ acpi_ex_system_memory_space_handler(u32 function, + if (!mem_info->mapped_logical_address) { + ACPI_ERROR((AE_INFO, + "Could not map memory at 0x%8.8X%8.8X, size %u", +- ACPI_FORMAT_NATIVE_UINT(address), ++ ACPI_FORMAT_UINT64(address), + (u32) map_length)); + mem_info->mapped_length = 0; + return_ACPI_STATUS(AE_NO_MEMORY); +@@ -202,8 +202,7 @@ acpi_ex_system_memory_space_handler(u32 function, + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n", +- bit_width, function, +- ACPI_FORMAT_NATIVE_UINT(address))); ++ bit_width, function, ACPI_FORMAT_UINT64(address))); + + /* + * Perform the memory read or write +@@ -318,8 +317,7 @@ acpi_ex_system_io_space_handler(u32 function, + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n", +- bit_width, function, +- ACPI_FORMAT_NATIVE_UINT(address))); ++ bit_width, function, ACPI_FORMAT_UINT64(address))); + + /* Decode the function parameter */ + +diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c +index eab70d58852a..fae57584a182 100644 +--- a/drivers/acpi/acpica/hwvalid.c ++++ b/drivers/acpi/acpica/hwvalid.c +@@ -142,17 +142,17 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width) + byte_width = ACPI_DIV_8(bit_width); + last_address = address + byte_width - 1; + +- ACPI_DEBUG_PRINT((ACPI_DB_IO, "Address %p LastAddress %p Length %X", +- ACPI_CAST_PTR(void, address), ACPI_CAST_PTR(void, +- last_address), +- byte_width)); ++ ACPI_DEBUG_PRINT((ACPI_DB_IO, ++ "Address %8.8X%8.8X LastAddress %8.8X%8.8X Length %X", ++ ACPI_FORMAT_UINT64(address), ++ ACPI_FORMAT_UINT64(last_address), byte_width)); + + /* Maximum 16-bit address in I/O space */ + + if (last_address > ACPI_UINT16_MAX) { + ACPI_ERROR((AE_INFO, +- "Illegal I/O port address/length above 64K: %p/0x%X", +- ACPI_CAST_PTR(void, address), byte_width)); ++ "Illegal I/O port address/length above 64K: %8.8X%8.8X/0x%X", ++ ACPI_FORMAT_UINT64(address), byte_width)); + return_ACPI_STATUS(AE_LIMIT); + } + +@@ -181,8 +181,8 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width) + + if (acpi_gbl_osi_data >= port_info->osi_dependency) { + ACPI_DEBUG_PRINT((ACPI_DB_IO, +- "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)", +- ACPI_CAST_PTR(void, address), ++ "Denied AML access to port 0x%8.8X%8.8X/%X (%s 0x%.4X-0x%.4X)", ++ ACPI_FORMAT_UINT64(address), + byte_width, port_info->name, + port_info->start, + port_info->end)); +diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c +index 48b9c6f12643..fc82c532090f 100644 +--- a/drivers/acpi/acpica/nsdump.c ++++ b/drivers/acpi/acpica/nsdump.c +@@ -271,12 +271,11 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, + switch (type) { + case ACPI_TYPE_PROCESSOR: + +- acpi_os_printf("ID %02X Len %02X Addr %p\n", ++ acpi_os_printf("ID %02X Len %02X Addr %8.8X%8.8X\n", + obj_desc->processor.proc_id, + obj_desc->processor.length, +- ACPI_CAST_PTR(void, +- obj_desc->processor. +- address)); ++ ACPI_FORMAT_UINT64(obj_desc->processor. ++ address)); + break; + + case ACPI_TYPE_DEVICE: +@@ -347,8 +346,9 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, + space_id)); + if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { + acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n", +- ACPI_FORMAT_NATIVE_UINT +- (obj_desc->region.address), ++ ACPI_FORMAT_UINT64(obj_desc-> ++ region. ++ address), + obj_desc->region.length); + } else { + acpi_os_printf +diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c +index 634357d51fe9..c4d097700a86 100644 +--- a/drivers/acpi/acpica/tbinstal.c ++++ b/drivers/acpi/acpica/tbinstal.c +@@ -294,8 +294,7 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header + ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, + "%4.4s %p Attempted physical table override failed", + table_header->signature, +- ACPI_CAST_PTR(void, +- table_desc->address))); ++ ACPI_PHYSADDR_TO_PTR(table_desc->address))); + return (NULL); + } + +@@ -311,7 +310,7 @@ finish_override: + ACPI_INFO((AE_INFO, + "%4.4s %p %s table override, new table: %p", + table_header->signature, +- ACPI_CAST_PTR(void, table_desc->address), ++ ACPI_PHYSADDR_TO_PTR(table_desc->address), + override_type, new_table)); + + /* We can now unmap/delete the original table (if fully mapped) */ +diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c +index 6866e767ba90..2957ed50b552 100644 +--- a/drivers/acpi/acpica/tbprint.c ++++ b/drivers/acpi/acpica/tbprint.c +@@ -127,16 +127,12 @@ acpi_tb_print_table_header(acpi_physical_address address, + { + struct acpi_table_header local_header; + +- /* +- * The reason that the Address is cast to a void pointer is so that we +- * can use %p which will work properly on both 32-bit and 64-bit hosts. +- */ + if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { + + /* FACS only has signature and length fields */ + +- ACPI_INFO((AE_INFO, "%4.4s %p %06X", +- header->signature, ACPI_CAST_PTR(void, address), ++ ACPI_INFO((AE_INFO, "%-4.4s 0x%8.8X%8.8X %06X", ++ header->signature, ACPI_FORMAT_UINT64(address), + header->length)); + } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) { + +@@ -147,8 +143,8 @@ acpi_tb_print_table_header(acpi_physical_address address, + header)->oem_id, ACPI_OEM_ID_SIZE); + acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); + +- ACPI_INFO((AE_INFO, "RSDP %p %06X (v%.2d %6.6s)", +- ACPI_CAST_PTR(void, address), ++ ACPI_INFO((AE_INFO, "RSDP 0x%8.8X%8.8X %06X (v%.2d %-6.6s)", ++ ACPI_FORMAT_UINT64(address), + (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> + revision > + 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, +@@ -162,8 +158,9 @@ acpi_tb_print_table_header(acpi_physical_address address, + acpi_tb_cleanup_table_header(&local_header, header); + + ACPI_INFO((AE_INFO, +- "%4.4s %p %06X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", +- local_header.signature, ACPI_CAST_PTR(void, address), ++ "%-4.4s 0x%8.8X%8.8X" ++ " %06X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)", ++ local_header.signature, ACPI_FORMAT_UINT64(address), + local_header.length, local_header.revision, + local_header.oem_id, local_header.oem_table_id, + local_header.oem_revision, +diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c +index 1bc879ec83d4..4cca6b797808 100644 +--- a/drivers/acpi/acpica/tbutils.c ++++ b/drivers/acpi/acpica/tbutils.c +@@ -227,8 +227,8 @@ acpi_tb_install_table(acpi_physical_address address, + table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); + if (!table) { + ACPI_ERROR((AE_INFO, +- "Could not map memory for table [%s] at %p", +- signature, ACPI_CAST_PTR(void, address))); ++ "Could not map memory for table [%s] at %8.8X%8.8X", ++ signature, ACPI_FORMAT_UINT64(address))); + return; + } + +diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c +index 60b5a871833c..daad59d76e67 100644 +--- a/drivers/acpi/acpica/tbxfload.c ++++ b/drivers/acpi/acpica/tbxfload.c +@@ -184,11 +184,10 @@ static acpi_status acpi_tb_load_namespace(void) + * be useful for debugging ACPI problems on some machines. + */ + if (acpi_gbl_disable_ssdt_table_load) { +- ACPI_INFO((AE_INFO, "Ignoring %4.4s at %p", ++ ACPI_INFO((AE_INFO, "Ignoring %4.4s at %8.8X%8.8X", + acpi_gbl_root_table_list.tables[i].signature. +- ascii, ACPI_CAST_PTR(void, +- acpi_gbl_root_table_list. +- tables[i].address))); ++ ascii, ACPI_FORMAT_UINT64(acpi_gbl_root_table_list. ++ tables[i].address))); + continue; + } + +diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c +index e4e1468877c3..01bf7ebef7a4 100644 +--- a/drivers/acpi/acpica/tbxfroot.c ++++ b/drivers/acpi/acpica/tbxfroot.c +@@ -111,7 +111,7 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) + * + ******************************************************************************/ + +-acpi_status __init acpi_find_root_pointer(acpi_size *table_address) ++acpi_status __init acpi_find_root_pointer(acpi_physical_address * table_address) + { + u8 *table_ptr; + u8 *mem_rover; +@@ -169,7 +169,8 @@ acpi_status __init acpi_find_root_pointer(acpi_size *table_address) + physical_address += + (u32) ACPI_PTR_DIFF(mem_rover, table_ptr); + +- *table_address = physical_address; ++ *table_address = ++ (acpi_physical_address) physical_address; + return_ACPI_STATUS(AE_OK); + } + } +@@ -202,7 +203,7 @@ acpi_status __init acpi_find_root_pointer(acpi_size *table_address) + (ACPI_HI_RSDP_WINDOW_BASE + + ACPI_PTR_DIFF(mem_rover, table_ptr)); + +- *table_address = physical_address; ++ *table_address = (acpi_physical_address) physical_address; + return_ACPI_STATUS(AE_OK); + } + +diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c +index 2c2b6ae5dfc4..3a02b65a1d9e 100644 +--- a/drivers/acpi/acpica/utaddress.c ++++ b/drivers/acpi/acpica/utaddress.c +@@ -107,10 +107,10 @@ acpi_ut_add_address_range(acpi_adr_space_type space_id, + acpi_gbl_address_range_list[space_id] = range_info; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, +- "\nAdded [%4.4s] address range: 0x%p-0x%p\n", ++ "\nAdded [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n", + acpi_ut_get_node_name(range_info->region_node), +- ACPI_CAST_PTR(void, address), +- ACPI_CAST_PTR(void, range_info->end_address))); ++ ACPI_FORMAT_UINT64(address), ++ ACPI_FORMAT_UINT64(range_info->end_address))); + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(AE_OK); +@@ -160,15 +160,13 @@ acpi_ut_remove_address_range(acpi_adr_space_type space_id, + } + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, +- "\nRemoved [%4.4s] address range: 0x%p-0x%p\n", ++ "\nRemoved [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n", + acpi_ut_get_node_name(range_info-> + region_node), +- ACPI_CAST_PTR(void, +- range_info-> +- start_address), +- ACPI_CAST_PTR(void, +- range_info-> +- end_address))); ++ ACPI_FORMAT_UINT64(range_info-> ++ start_address), ++ ACPI_FORMAT_UINT64(range_info-> ++ end_address))); + + ACPI_FREE(range_info); + return_VOID; +@@ -245,16 +243,14 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id, + region_node); + + ACPI_WARNING((AE_INFO, +- "%s range 0x%p-0x%p conflicts with OpRegion 0x%p-0x%p (%s)", ++ "%s range 0x%8.8X%8.8X-0x%8.8X%8.8X conflicts with OpRegion 0x%8.8X%8.8X-0x%8.8X%8.8X (%s)", + acpi_ut_get_region_name(space_id), +- ACPI_CAST_PTR(void, address), +- ACPI_CAST_PTR(void, end_address), +- ACPI_CAST_PTR(void, +- range_info-> +- start_address), +- ACPI_CAST_PTR(void, +- range_info-> +- end_address), ++ ACPI_FORMAT_UINT64(address), ++ ACPI_FORMAT_UINT64(end_address), ++ ACPI_FORMAT_UINT64(range_info-> ++ start_address), ++ ACPI_FORMAT_UINT64(range_info-> ++ end_address), + pathname)); + ACPI_FREE(pathname); + } +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index f1fc14c33be5..a03e18f5e562 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -800,6 +800,7 @@ static struct class gpio_class = { + */ + int gpiod_export(struct gpio_desc *desc, bool direction_may_change) + { ++ struct gpio_chip *chip; + unsigned long flags; + int status; + const char *ioname = NULL; +@@ -817,8 +818,16 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) + return -EINVAL; + } + ++ chip = desc->chip; ++ + mutex_lock(&sysfs_lock); + ++ /* check if chip is being removed */ ++ if (!chip || !chip->exported) { ++ status = -ENODEV; ++ goto fail_unlock; ++ } ++ + spin_lock_irqsave(&gpio_lock, flags); + if (!test_bit(FLAG_REQUESTED, &desc->flags) || + test_bit(FLAG_EXPORT, &desc->flags)) { +@@ -1057,12 +1066,15 @@ static void gpiochip_unexport(struct gpio_chip *chip) + { + int status; + struct device *dev; ++ struct gpio_desc *desc; ++ unsigned int i; + + mutex_lock(&sysfs_lock); + dev = class_find_device(&gpio_class, NULL, chip, match_export); + if (dev) { + put_device(dev); + device_unregister(dev); ++ /* prevent further gpiod exports */ + chip->exported = false; + status = 0; + } else +@@ -1071,6 +1083,13 @@ static void gpiochip_unexport(struct gpio_chip *chip) + + if (status) + chip_dbg(chip, "%s: status %d\n", __func__, status); ++ ++ /* unregister gpiod class devices owned by sysfs */ ++ for (i = 0; i < chip->ngpio; i++) { ++ desc = &chip->desc[i]; ++ if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) ++ gpiod_free(desc); ++ } + } + + static int __init gpiolib_sysfs_init(void) +@@ -1265,6 +1284,8 @@ int gpiochip_remove(struct gpio_chip *chip) + int status = 0; + unsigned id; + ++ gpiochip_unexport(chip); ++ + spin_lock_irqsave(&gpio_lock, flags); + + gpiochip_remove_pin_ranges(chip); +@@ -1286,9 +1307,6 @@ int gpiochip_remove(struct gpio_chip *chip) + + spin_unlock_irqrestore(&gpio_lock, flags); + +- if (status == 0) +- gpiochip_unexport(chip); +- + return status; + } + EXPORT_SYMBOL_GPL(gpiochip_remove); +diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c +index af49b24d14cb..1eb49941faff 100644 +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -815,12 +815,28 @@ static int intel_dual_link_lvds_callback(const struct dmi_system_id *id) + static const struct dmi_system_id intel_dual_link_lvds[] = { + { + .callback = intel_dual_link_lvds_callback, +- .ident = "Apple MacBook Pro (Core i5/i7 Series)", ++ .ident = "Apple MacBook Pro 15\" (2010)", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6,2"), ++ }, ++ }, ++ { ++ .callback = intel_dual_link_lvds_callback, ++ .ident = "Apple MacBook Pro 15\" (2011)", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"), + }, + }, ++ { ++ .callback = intel_dual_link_lvds_callback, ++ .ident = "Apple MacBook Pro 15\" (2012)", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro9,1"), ++ }, ++ }, + { } /* terminating entry */ + }; + +diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c +index 64d6cfba9952..d625a14ec038 100644 +--- a/drivers/gpu/drm/radeon/radeon_asic.c ++++ b/drivers/gpu/drm/radeon/radeon_asic.c +@@ -1173,7 +1173,7 @@ static struct radeon_asic rs780_asic = { + static struct radeon_asic_ring rv770_uvd_ring = { + .ib_execute = &uvd_v1_0_ib_execute, + .emit_fence = &uvd_v2_2_fence_emit, +- .emit_semaphore = &uvd_v1_0_semaphore_emit, ++ .emit_semaphore = &uvd_v2_2_semaphore_emit, + .cs_parse = &radeon_uvd_cs_parse, + .ring_test = &uvd_v1_0_ring_test, + .ib_test = &uvd_v1_0_ib_test, +diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h +index ae637cfda783..f6e19edb1166 100644 +--- a/drivers/gpu/drm/radeon/radeon_asic.h ++++ b/drivers/gpu/drm/radeon/radeon_asic.h +@@ -853,6 +853,10 @@ void uvd_v1_0_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); + int uvd_v2_2_resume(struct radeon_device *rdev); + void uvd_v2_2_fence_emit(struct radeon_device *rdev, + struct radeon_fence *fence); ++bool uvd_v2_2_semaphore_emit(struct radeon_device *rdev, ++ struct radeon_ring *ring, ++ struct radeon_semaphore *semaphore, ++ bool emit_wait); + + /* uvd v3.1 */ + bool uvd_v3_1_semaphore_emit(struct radeon_device *rdev, +diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c +index 414e07928693..bcfac7624550 100644 +--- a/drivers/gpu/drm/radeon/radeon_uvd.c ++++ b/drivers/gpu/drm/radeon/radeon_uvd.c +@@ -350,6 +350,29 @@ static int radeon_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[]) + return 0; + } + ++static int radeon_uvd_validate_codec(struct radeon_cs_parser *p, ++ unsigned stream_type) ++{ ++ switch (stream_type) { ++ case 0: /* H264 */ ++ case 1: /* VC1 */ ++ /* always supported */ ++ return 0; ++ ++ case 3: /* MPEG2 */ ++ case 4: /* MPEG4 */ ++ /* only since UVD 3 */ ++ if (p->rdev->family >= CHIP_PALM) ++ return 0; ++ ++ /* fall through */ ++ default: ++ DRM_ERROR("UVD codec not supported by hardware %d!\n", ++ stream_type); ++ return -EINVAL; ++ } ++} ++ + static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, + unsigned offset, unsigned buf_sizes[]) + { +@@ -388,50 +411,70 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, + return -EINVAL; + } + +- if (msg_type == 1) { +- /* it's a decode msg, calc buffer sizes */ +- r = radeon_uvd_cs_msg_decode(msg, buf_sizes); +- /* calc image size (width * height) */ +- img_size = msg[6] * msg[7]; ++ switch (msg_type) { ++ case 0: ++ /* it's a create msg, calc image size (width * height) */ ++ img_size = msg[7] * msg[8]; ++ ++ r = radeon_uvd_validate_codec(p, msg[4]); ++ radeon_bo_kunmap(bo); ++ if (r) ++ return r; ++ ++ /* try to alloc a new handle */ ++ for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { ++ if (atomic_read(&p->rdev->uvd.handles[i]) == handle) { ++ DRM_ERROR("Handle 0x%x already in use!\n", handle); ++ return -EINVAL; ++ } ++ ++ if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) { ++ p->rdev->uvd.filp[i] = p->filp; ++ p->rdev->uvd.img_size[i] = img_size; ++ return 0; ++ } ++ } ++ ++ DRM_ERROR("No more free UVD handles!\n"); ++ return -EINVAL; ++ ++ case 1: ++ /* it's a decode msg, validate codec and calc buffer sizes */ ++ r = radeon_uvd_validate_codec(p, msg[4]); ++ if (!r) ++ r = radeon_uvd_cs_msg_decode(msg, buf_sizes); + radeon_bo_kunmap(bo); + if (r) + return r; + +- } else if (msg_type == 2) { ++ /* validate the handle */ ++ for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { ++ if (atomic_read(&p->rdev->uvd.handles[i]) == handle) { ++ if (p->rdev->uvd.filp[i] != p->filp) { ++ DRM_ERROR("UVD handle collision detected!\n"); ++ return -EINVAL; ++ } ++ return 0; ++ } ++ } ++ ++ DRM_ERROR("Invalid UVD handle 0x%x!\n", handle); ++ return -ENOENT; ++ ++ case 2: + /* it's a destroy msg, free the handle */ + for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) + atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0); + radeon_bo_kunmap(bo); + return 0; +- } else { +- /* it's a create msg, calc image size (width * height) */ +- img_size = msg[7] * msg[8]; +- radeon_bo_kunmap(bo); + +- if (msg_type != 0) { +- DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type); +- return -EINVAL; +- } +- +- /* it's a create msg, no special handling needed */ +- } +- +- /* create or decode, validate the handle */ +- for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { +- if (atomic_read(&p->rdev->uvd.handles[i]) == handle) +- return 0; +- } ++ default: + +- /* handle not found try to alloc a new one */ +- for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { +- if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) { +- p->rdev->uvd.filp[i] = p->filp; +- p->rdev->uvd.img_size[i] = img_size; +- return 0; +- } ++ DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type); ++ return -EINVAL; + } + +- DRM_ERROR("No more free UVD handles!\n"); ++ BUG(); + return -EINVAL; + } + +diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h +index 3cf1e2921545..9ef2064b1c9c 100644 +--- a/drivers/gpu/drm/radeon/rv770d.h ++++ b/drivers/gpu/drm/radeon/rv770d.h +@@ -989,6 +989,9 @@ + ((n) & 0x3FFF) << 16) + + /* UVD */ ++#define UVD_SEMA_ADDR_LOW 0xef00 ++#define UVD_SEMA_ADDR_HIGH 0xef04 ++#define UVD_SEMA_CMD 0xef08 + #define UVD_GPCOM_VCPU_CMD 0xef0c + #define UVD_GPCOM_VCPU_DATA0 0xef10 + #define UVD_GPCOM_VCPU_DATA1 0xef14 +diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c +index c310a0aeebb9..0fa9009fef64 100644 +--- a/drivers/gpu/drm/radeon/uvd_v1_0.c ++++ b/drivers/gpu/drm/radeon/uvd_v1_0.c +@@ -365,18 +365,8 @@ bool uvd_v1_0_semaphore_emit(struct radeon_device *rdev, + struct radeon_semaphore *semaphore, + bool emit_wait) + { +- uint64_t addr = semaphore->gpu_addr; +- +- radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0)); +- radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF); +- +- radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0)); +- radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF); +- +- radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0)); +- radeon_ring_write(ring, emit_wait ? 1 : 0); +- +- return true; ++ /* disable semaphores for UVD V1 hardware */ ++ return false; + } + + /** +diff --git a/drivers/gpu/drm/radeon/uvd_v2_2.c b/drivers/gpu/drm/radeon/uvd_v2_2.c +index d1771004cb52..19ccb2ae7a5d 100644 +--- a/drivers/gpu/drm/radeon/uvd_v2_2.c ++++ b/drivers/gpu/drm/radeon/uvd_v2_2.c +@@ -60,6 +60,35 @@ void uvd_v2_2_fence_emit(struct radeon_device *rdev, + } + + /** ++ * uvd_v2_2_semaphore_emit - emit semaphore command ++ * ++ * @rdev: radeon_device pointer ++ * @ring: radeon_ring pointer ++ * @semaphore: semaphore to emit commands for ++ * @emit_wait: true if we should emit a wait command ++ * ++ * Emit a semaphore command (either wait or signal) to the UVD ring. ++ */ ++bool uvd_v2_2_semaphore_emit(struct radeon_device *rdev, ++ struct radeon_ring *ring, ++ struct radeon_semaphore *semaphore, ++ bool emit_wait) ++{ ++ uint64_t addr = semaphore->gpu_addr; ++ ++ radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0)); ++ radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF); ++ ++ radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0)); ++ radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF); ++ ++ radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0)); ++ radeon_ring_write(ring, emit_wait ? 1 : 0); ++ ++ return true; ++} ++ ++/** + * uvd_v2_2_resume - memory controller programming + * + * @rdev: radeon_device pointer +diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c +index 42c3058e6e9c..dbd7d66977c9 100644 +--- a/drivers/infiniband/core/cma.c ++++ b/drivers/infiniband/core/cma.c +@@ -859,19 +859,27 @@ static void cma_save_ib_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id + memcpy(&ib->sib_addr, &path->dgid, 16); + } + ++static __be16 ss_get_port(const struct sockaddr_storage *ss) ++{ ++ if (ss->ss_family == AF_INET) ++ return ((struct sockaddr_in *)ss)->sin_port; ++ else if (ss->ss_family == AF_INET6) ++ return ((struct sockaddr_in6 *)ss)->sin6_port; ++ BUG(); ++} ++ + static void cma_save_ip4_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id, + struct cma_hdr *hdr) + { +- struct sockaddr_in *listen4, *ip4; ++ struct sockaddr_in *ip4; + +- listen4 = (struct sockaddr_in *) &listen_id->route.addr.src_addr; + ip4 = (struct sockaddr_in *) &id->route.addr.src_addr; +- ip4->sin_family = listen4->sin_family; ++ ip4->sin_family = AF_INET; + ip4->sin_addr.s_addr = hdr->dst_addr.ip4.addr; +- ip4->sin_port = listen4->sin_port; ++ ip4->sin_port = ss_get_port(&listen_id->route.addr.src_addr); + + ip4 = (struct sockaddr_in *) &id->route.addr.dst_addr; +- ip4->sin_family = listen4->sin_family; ++ ip4->sin_family = AF_INET; + ip4->sin_addr.s_addr = hdr->src_addr.ip4.addr; + ip4->sin_port = hdr->port; + } +@@ -879,16 +887,15 @@ static void cma_save_ip4_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_i + static void cma_save_ip6_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id, + struct cma_hdr *hdr) + { +- struct sockaddr_in6 *listen6, *ip6; ++ struct sockaddr_in6 *ip6; + +- listen6 = (struct sockaddr_in6 *) &listen_id->route.addr.src_addr; + ip6 = (struct sockaddr_in6 *) &id->route.addr.src_addr; +- ip6->sin6_family = listen6->sin6_family; ++ ip6->sin6_family = AF_INET6; + ip6->sin6_addr = hdr->dst_addr.ip6; +- ip6->sin6_port = listen6->sin6_port; ++ ip6->sin6_port = ss_get_port(&listen_id->route.addr.src_addr); + + ip6 = (struct sockaddr_in6 *) &id->route.addr.dst_addr; +- ip6->sin6_family = listen6->sin6_family; ++ ip6->sin6_family = AF_INET6; + ip6->sin6_addr = hdr->src_addr.ip6; + ip6->sin6_port = hdr->port; + } +diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c +index 5a4cda24e302..4a8d19d0a5a4 100644 +--- a/drivers/md/dm-crypt.c ++++ b/drivers/md/dm-crypt.c +@@ -915,10 +915,11 @@ static int crypt_convert(struct crypt_config *cc, + + switch (r) { + /* async */ +- case -EINPROGRESS: + case -EBUSY: + wait_for_completion(&ctx->restart); + reinit_completion(&ctx->restart); ++ /* fall through*/ ++ case -EINPROGRESS: + ctx->req = NULL; + ctx->cc_sector++; + continue; +@@ -1313,8 +1314,10 @@ static void kcryptd_async_done(struct crypto_async_request *async_req, + struct dm_crypt_io *io = container_of(ctx, struct dm_crypt_io, ctx); + struct crypt_config *cc = io->cc; + +- if (error == -EINPROGRESS) ++ if (error == -EINPROGRESS) { ++ complete(&ctx->restart); + return; ++ } + + if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post) + error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq); +@@ -1325,15 +1328,12 @@ static void kcryptd_async_done(struct crypto_async_request *async_req, + mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool); + + if (!atomic_dec_and_test(&ctx->cc_pending)) +- goto done; ++ return; + + if (bio_data_dir(io->base_bio) == READ) + kcryptd_crypt_read_done(io); + else + kcryptd_crypt_write_io_submit(io, 1); +-done: +- if (!completion_done(&ctx->restart)) +- complete(&ctx->restart); + } + + static void kcryptd_crypt(struct work_struct *work) +diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c +index df72c478c5a2..b1e21fc869c3 100644 +--- a/drivers/mmc/card/block.c ++++ b/drivers/mmc/card/block.c +@@ -951,6 +951,18 @@ static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type) + md->reset_done &= ~type; + } + ++int mmc_access_rpmb(struct mmc_queue *mq) ++{ ++ struct mmc_blk_data *md = mq->data; ++ /* ++ * If this is a RPMB partition access, return ture ++ */ ++ if (md && md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB) ++ return true; ++ ++ return false; ++} ++ + static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) + { + struct mmc_blk_data *md = mq->data; +diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c +index 3e049c13429c..6ceede0a0bf7 100644 +--- a/drivers/mmc/card/queue.c ++++ b/drivers/mmc/card/queue.c +@@ -38,7 +38,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req) + return BLKPREP_KILL; + } + +- if (mq && mmc_card_removed(mq->card)) ++ if (mq && (mmc_card_removed(mq->card) || mmc_access_rpmb(mq))) + return BLKPREP_KILL; + + req->cmd_flags |= REQ_DONTPREP; +diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h +index 5752d50049a3..99e6521e6169 100644 +--- a/drivers/mmc/card/queue.h ++++ b/drivers/mmc/card/queue.h +@@ -73,4 +73,6 @@ extern void mmc_queue_bounce_post(struct mmc_queue_req *); + extern int mmc_packed_init(struct mmc_queue *, struct mmc_card *); + extern void mmc_packed_clean(struct mmc_queue *); + ++extern int mmc_access_rpmb(struct mmc_queue *); ++ + #endif +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index 098374b1ab2b..6a881ebe5b02 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -2657,6 +2657,7 @@ int mmc_pm_notify(struct notifier_block *notify_block, + switch (mode) { + case PM_HIBERNATION_PREPARE: + case PM_SUSPEND_PREPARE: ++ case PM_RESTORE_PREPARE: + spin_lock_irqsave(&host->lock, flags); + host->rescan_disable = 1; + spin_unlock_irqrestore(&host->lock, flags); +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index 54730f4aac87..9c208fdf43ab 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -1401,7 +1401,7 @@ static int sh_mmcif_probe(struct platform_device *pdev) + host = mmc_priv(mmc); + host->mmc = mmc; + host->addr = reg; +- host->timeout = msecs_to_jiffies(1000); ++ host->timeout = msecs_to_jiffies(10000); + host->ccs_enable = !pd || !pd->ccs_unsupported; + host->clk_ctrl2_enable = pd && pd->clk_ctrl2_present; + +diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c +index 988f5e18763a..a2a79c737b1b 100644 +--- a/drivers/pinctrl/core.c ++++ b/drivers/pinctrl/core.c +@@ -1121,7 +1121,7 @@ void devm_pinctrl_put(struct pinctrl *p) + EXPORT_SYMBOL_GPL(devm_pinctrl_put); + + int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps, +- bool dup, bool locked) ++ bool dup) + { + int i, ret; + struct pinctrl_maps *maps_node; +@@ -1189,11 +1189,9 @@ int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps, + maps_node->maps = maps; + } + +- if (!locked) +- mutex_lock(&pinctrl_maps_mutex); ++ mutex_lock(&pinctrl_maps_mutex); + list_add_tail(&maps_node->node, &pinctrl_maps); +- if (!locked) +- mutex_unlock(&pinctrl_maps_mutex); ++ mutex_unlock(&pinctrl_maps_mutex); + + return 0; + } +@@ -1208,7 +1206,7 @@ int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps, + int pinctrl_register_mappings(struct pinctrl_map const *maps, + unsigned num_maps) + { +- return pinctrl_register_map(maps, num_maps, true, false); ++ return pinctrl_register_map(maps, num_maps, true); + } + + void pinctrl_unregister_map(struct pinctrl_map const *map) +diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h +index 75476b3d87da..b24ea846c867 100644 +--- a/drivers/pinctrl/core.h ++++ b/drivers/pinctrl/core.h +@@ -183,7 +183,7 @@ static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, + } + + int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps, +- bool dup, bool locked); ++ bool dup); + void pinctrl_unregister_map(struct pinctrl_map const *map); + + extern int pinctrl_force_sleep(struct pinctrl_dev *pctldev); +diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c +index 340fb4e6c600..fd91c4c31f6b 100644 +--- a/drivers/pinctrl/devicetree.c ++++ b/drivers/pinctrl/devicetree.c +@@ -92,7 +92,7 @@ static int dt_remember_or_free_map(struct pinctrl *p, const char *statename, + dt_map->num_maps = num_maps; + list_add_tail(&dt_map->node, &p->dt_maps); + +- return pinctrl_register_map(map, num_maps, false, true); ++ return pinctrl_register_map(map, num_maps, false); + } + + struct pinctrl_dev *of_pinctrl_get(struct device_node *np) +diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c +index 2dc2831840ca..8eb65f26fcae 100644 +--- a/drivers/tty/hvc/hvc_xen.c ++++ b/drivers/tty/hvc/hvc_xen.c +@@ -299,11 +299,27 @@ static int xen_initial_domain_console_init(void) + return 0; + } + ++static void xen_console_update_evtchn(struct xencons_info *info) ++{ ++ if (xen_hvm_domain()) { ++ uint64_t v; ++ int err; ++ ++ err = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v); ++ if (!err && v) ++ info->evtchn = v; ++ } else ++ info->evtchn = xen_start_info->console.domU.evtchn; ++} ++ + void xen_console_resume(void) + { + struct xencons_info *info = vtermno_to_xencons(HVC_COOKIE); +- if (info != NULL && info->irq) ++ if (info != NULL && info->irq) { ++ if (!xen_initial_domain()) ++ xen_console_update_evtchn(info); + rebind_evtchn_irq(info->evtchn, info->irq); ++ } + } + + static void xencons_disconnect_backend(struct xencons_info *info) +diff --git a/drivers/xen/events/events_2l.c b/drivers/xen/events/events_2l.c +index d7ff91757307..843e5d8538bd 100644 +--- a/drivers/xen/events/events_2l.c ++++ b/drivers/xen/events/events_2l.c +@@ -352,6 +352,15 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id) + return IRQ_HANDLED; + } + ++static void evtchn_2l_resume(void) ++{ ++ int i; ++ ++ for_each_online_cpu(i) ++ memset(per_cpu(cpu_evtchn_mask, i), 0, sizeof(xen_ulong_t) * ++ EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD); ++} ++ + static const struct evtchn_ops evtchn_ops_2l = { + .max_channels = evtchn_2l_max_channels, + .nr_channels = evtchn_2l_max_channels, +@@ -363,6 +372,7 @@ static const struct evtchn_ops evtchn_ops_2l = { + .mask = evtchn_2l_mask, + .unmask = evtchn_2l_unmask, + .handle_events = evtchn_2l_handle_events, ++ .resume = evtchn_2l_resume, + }; + + void __init xen_evtchn_2l_init(void) +diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c +index c8860a8757ac..a5cc476256f1 100644 +--- a/drivers/xen/events/events_base.c ++++ b/drivers/xen/events/events_base.c +@@ -550,8 +550,8 @@ static unsigned int __startup_pirq(unsigned int irq) + if (rc) + goto err; + +- bind_evtchn_to_cpu(evtchn, 0); + info->evtchn = evtchn; ++ bind_evtchn_to_cpu(evtchn, 0); + + rc = xen_evtchn_port_setup(info); + if (rc) +@@ -1294,8 +1294,9 @@ void rebind_evtchn_irq(int evtchn, int irq) + + mutex_unlock(&irq_mapping_update_lock); + +- /* new event channels are always bound to cpu 0 */ +- irq_set_affinity(irq, cpumask_of(0)); ++ bind_evtchn_to_cpu(evtchn, info->cpu); ++ /* This will be deferred until interrupt is processed */ ++ irq_set_affinity(irq, cpumask_of(info->cpu)); + + /* Unmask the event channel. */ + enable_irq(irq); +diff --git a/fs/dcache.c b/fs/dcache.c +index c345f5f2b508..a9231c872342 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -435,7 +435,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) + __releases(parent->d_lock) + __releases(dentry->d_inode->i_lock) + { +- list_del(&dentry->d_child); ++ __list_del_entry(&dentry->d_child); + /* + * Inform d_walk() that we are no longer attached to the + * dentry tree +@@ -1123,33 +1123,31 @@ resume: + /* + * All done at this level ... ascend and resume the search. + */ ++ rcu_read_lock(); ++ascend: + if (this_parent != parent) { + struct dentry *child = this_parent; + this_parent = child->d_parent; + +- rcu_read_lock(); + spin_unlock(&child->d_lock); + spin_lock(&this_parent->d_lock); + +- /* +- * might go back up the wrong parent if we have had a rename +- * or deletion +- */ +- if (this_parent != child->d_parent || +- (child->d_flags & DCACHE_DENTRY_KILLED) || +- need_seqretry(&rename_lock, seq)) { +- spin_unlock(&this_parent->d_lock); +- rcu_read_unlock(); ++ /* might go back up the wrong parent if we have had a rename. */ ++ if (need_seqretry(&rename_lock, seq)) + goto rename_retry; ++ next = child->d_child.next; ++ while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) { ++ if (next == &this_parent->d_subdirs) ++ goto ascend; ++ child = list_entry(next, struct dentry, d_child); ++ next = next->next; + } + rcu_read_unlock(); +- next = child->d_child.next; + goto resume; + } +- if (need_seqretry(&rename_lock, seq)) { +- spin_unlock(&this_parent->d_lock); ++ if (need_seqretry(&rename_lock, seq)) + goto rename_retry; +- } ++ rcu_read_unlock(); + if (finish) + finish(data); + +@@ -1159,6 +1157,9 @@ out_unlock: + return; + + rename_retry: ++ spin_unlock(&this_parent->d_lock); ++ rcu_read_unlock(); ++ BUG_ON(seq & 1); + if (!retry) + return; + seq = 1; +diff --git a/fs/namespace.c b/fs/namespace.c +index 039f3802d70e..2faa7eacb62b 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -3025,6 +3025,12 @@ bool fs_fully_visible(struct file_system_type *type) + if (mnt->mnt.mnt_sb->s_type != type) + continue; + ++ /* This mount is not fully visible if it's root directory ++ * is not the root directory of the filesystem. ++ */ ++ if (mnt->mnt.mnt_root != mnt->mnt.mnt_sb->s_root) ++ continue; ++ + /* This mount is not fully visible if there are any child mounts + * that cover anything except for empty directories. + */ +diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c +index ecdbae19a766..090d8ce25bd1 100644 +--- a/fs/nilfs2/btree.c ++++ b/fs/nilfs2/btree.c +@@ -388,7 +388,7 @@ static int nilfs_btree_root_broken(const struct nilfs_btree_node *node, + nchildren = nilfs_btree_node_get_nchildren(node); + + if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN || +- level > NILFS_BTREE_LEVEL_MAX || ++ level >= NILFS_BTREE_LEVEL_MAX || + nchildren < 0 || + nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) { + pr_crit("NILFS: bad btree root (inode number=%lu): level = %d, flags = 0x%x, nchildren = %d\n", +diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c +index 1be3398c96f6..1dd0bcc75536 100644 +--- a/fs/ocfs2/dlm/dlmmaster.c ++++ b/fs/ocfs2/dlm/dlmmaster.c +@@ -726,6 +726,19 @@ lookup: + if (tmpres) { + spin_unlock(&dlm->spinlock); + spin_lock(&tmpres->spinlock); ++ ++ /* ++ * Right after dlm spinlock was released, dlm_thread could have ++ * purged the lockres. Check if lockres got unhashed. If so ++ * start over. ++ */ ++ if (hlist_unhashed(&tmpres->hash_node)) { ++ spin_unlock(&tmpres->spinlock); ++ dlm_lockres_put(tmpres); ++ tmpres = NULL; ++ goto lookup; ++ } ++ + /* Wait on the thread that is mastering the resource */ + if (tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN) { + __dlm_wait_on_lockres(tmpres); +diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h +index fea6773f87fc..5d51f27549cc 100644 +--- a/include/acpi/acpixf.h ++++ b/include/acpi/acpixf.h +@@ -175,7 +175,7 @@ acpi_status __init acpi_load_tables(void); + */ + acpi_status __init acpi_reallocate_root_table(void); + +-acpi_status __init acpi_find_root_pointer(acpi_size *rsdp_address); ++acpi_status __init acpi_find_root_pointer(acpi_physical_address * rsdp_address); + + acpi_status acpi_unload_table_id(acpi_owner_id id); + +diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h +index 98755767c7b0..1108acaacfc6 100644 +--- a/include/linux/nilfs2_fs.h ++++ b/include/linux/nilfs2_fs.h +@@ -458,7 +458,7 @@ struct nilfs_btree_node { + /* level */ + #define NILFS_BTREE_LEVEL_DATA 0 + #define NILFS_BTREE_LEVEL_NODE_MIN (NILFS_BTREE_LEVEL_DATA + 1) +-#define NILFS_BTREE_LEVEL_MAX 14 ++#define NILFS_BTREE_LEVEL_MAX 14 /* Max level (exclusive) */ + + /** + * struct nilfs_palloc_group_desc - block group descriptor +diff --git a/mm/memory-failure.c b/mm/memory-failure.c +index ffc7bf0458fb..9502057c3c54 100644 +--- a/mm/memory-failure.c ++++ b/mm/memory-failure.c +@@ -1149,10 +1149,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags) + * The check (unnecessarily) ignores LRU pages being isolated and + * walked by the page reclaim code, however that's not a big loss. + */ +- if (!PageHuge(p) && !PageTransTail(p)) { +- if (!PageLRU(p)) +- shake_page(p, 0); +- if (!PageLRU(p)) { ++ if (!PageHuge(p)) { ++ if (!PageLRU(hpage)) ++ shake_page(hpage, 0); ++ if (!PageLRU(hpage)) { + /* + * shake_page could have turned it free. + */ +@@ -1723,12 +1723,12 @@ int soft_offline_page(struct page *page, int flags) + } else if (ret == 0) { /* for free pages */ + if (PageHuge(page)) { + set_page_hwpoison_huge_page(hpage); +- dequeue_hwpoisoned_huge_page(hpage); +- atomic_long_add(1 << compound_order(hpage), ++ if (!dequeue_hwpoisoned_huge_page(hpage)) ++ atomic_long_add(1 << compound_order(hpage), + &num_poisoned_pages); + } else { +- SetPageHWPoison(page); +- atomic_long_inc(&num_poisoned_pages); ++ if (!TestSetPageHWPoison(page)) ++ atomic_long_inc(&num_poisoned_pages); + } + } + unset_migratetype_isolate(page, MIGRATE_MOVABLE); +diff --git a/mm/page-writeback.c b/mm/page-writeback.c +index 51d8d15f48d7..656a5490f693 100644 +--- a/mm/page-writeback.c ++++ b/mm/page-writeback.c +@@ -601,7 +601,7 @@ static long long pos_ratio_polynom(unsigned long setpoint, + long x; + + x = div64_s64(((s64)setpoint - (s64)dirty) << RATELIMIT_CALC_SHIFT, +- limit - setpoint + 1); ++ (limit - setpoint) | 1); + pos_ratio = x; + pos_ratio = pos_ratio * x >> RATELIMIT_CALC_SHIFT; + pos_ratio = pos_ratio * x >> RATELIMIT_CALC_SHIFT; +@@ -828,7 +828,7 @@ static unsigned long bdi_position_ratio(struct backing_dev_info *bdi, + * scale global setpoint to bdi's: + * bdi_setpoint = setpoint * bdi_thresh / thresh + */ +- x = div_u64((u64)bdi_thresh << 16, thresh + 1); ++ x = div_u64((u64)bdi_thresh << 16, thresh | 1); + bdi_setpoint = setpoint * (u64)x >> 16; + /* + * Use span=(8*write_bw) in single bdi case as indicated by +@@ -843,7 +843,7 @@ static unsigned long bdi_position_ratio(struct backing_dev_info *bdi, + + if (bdi_dirty < x_intercept - span / 4) { + pos_ratio = div64_u64(pos_ratio * (x_intercept - bdi_dirty), +- x_intercept - bdi_setpoint + 1); ++ (x_intercept - bdi_setpoint) | 1); + } else + pos_ratio /= 4; + +diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c +index 9b9f7d385134..1010ca1c9994 100644 +--- a/sound/oss/sequencer.c ++++ b/sound/oss/sequencer.c +@@ -683,13 +683,8 @@ static int seq_timing_event(unsigned char *event_rec) + break; + + case TMR_ECHO: +- if (seq_mode == SEQ_2) +- seq_copy_to_input(event_rec, 8); +- else +- { +- parm = (parm << 8 | SEQ_ECHO); +- seq_copy_to_input((unsigned char *) &parm, 4); +- } ++ parm = (parm << 8 | SEQ_ECHO); ++ seq_copy_to_input((unsigned char *) &parm, 4); + break; + + default:; +@@ -1330,7 +1325,6 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, void __user *a + int mode = translate_mode(file); + struct synth_info inf; + struct seq_event_rec event_rec; +- unsigned long flags; + int __user *p = arg; + + orig_dev = dev = dev >> 4; +@@ -1485,9 +1479,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, void __user *a + case SNDCTL_SEQ_OUTOFBAND: + if (copy_from_user(&event_rec, arg, sizeof(event_rec))) + return -EFAULT; +- spin_lock_irqsave(&lock,flags); + play_event(event_rec.arr); +- spin_unlock_irqrestore(&lock,flags); + return 0; + + case SNDCTL_MIDI_INFO: +diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c +index 26954a7d9b03..4eec2d436109 100644 +--- a/virt/kvm/arm/vgic.c ++++ b/virt/kvm/arm/vgic.c +@@ -548,11 +548,10 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu, + u32 val; + u32 *reg; + +- offset >>= 1; + reg = vgic_bitmap_get_reg(&vcpu->kvm->arch.vgic.irq_cfg, +- vcpu->vcpu_id, offset); ++ vcpu->vcpu_id, offset >> 1); + +- if (offset & 2) ++ if (offset & 4) + val = *reg >> 16; + else + val = *reg & 0xffff; +@@ -561,13 +560,13 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu, + vgic_reg_access(mmio, &val, offset, + ACCESS_READ_VALUE | ACCESS_WRITE_VALUE); + if (mmio->is_write) { +- if (offset < 4) { ++ if (offset < 8) { + *reg = ~0U; /* Force PPIs/SGIs to 1 */ + return false; + } + + val = vgic_cfg_compress(val); +- if (offset & 2) { ++ if (offset & 4) { + *reg &= 0xffff; + *reg |= val << 16; + } else { +@@ -1527,17 +1526,33 @@ int kvm_vgic_hyp_init(void) + goto out_unmap; + } + +- kvm_info("%s@%llx IRQ%d\n", vgic_node->name, +- vctrl_res.start, vgic_maint_irq); +- on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1); +- + if (of_address_to_resource(vgic_node, 3, &vcpu_res)) { + kvm_err("Cannot obtain VCPU resource\n"); + ret = -ENXIO; + goto out_unmap; + } ++ ++ if (!PAGE_ALIGNED(vcpu_res.start)) { ++ kvm_err("GICV physical address 0x%llx not page aligned\n", ++ (unsigned long long)vcpu_res.start); ++ ret = -ENXIO; ++ goto out_unmap; ++ } ++ ++ if (!PAGE_ALIGNED(resource_size(&vcpu_res))) { ++ kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n", ++ (unsigned long long)resource_size(&vcpu_res), ++ PAGE_SIZE); ++ ret = -ENXIO; ++ goto out_unmap; ++ } ++ + vgic_vcpu_base = vcpu_res.start; + ++ kvm_info("%s@%llx IRQ%d\n", vgic_node->name, ++ vctrl_res.start, vgic_maint_irq); ++ on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1); ++ + goto out; + + out_unmap: +@@ -1668,10 +1683,11 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr, + if (addr + size < addr) + return -EINVAL; + ++ *ioaddr = addr; + ret = vgic_ioaddr_overlap(kvm); + if (ret) +- return ret; +- *ioaddr = addr; ++ *ioaddr = VGIC_ADDR_UNDEF; ++ + return ret; + } + diff --git a/patch/kernel/cubox-default/patch-3.14.43-44.patch b/patch/kernel/cubox-default/patch-3.14.43-44.patch new file mode 100644 index 000000000..4ee694057 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.43-44.patch @@ -0,0 +1,1714 @@ +diff --git a/Makefile b/Makefile +index ae5f1e62812f..9f2471c6fbbe 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 43 ++SUBLEVEL = 44 + EXTRAVERSION = + NAME = Remembering Coco + +@@ -244,7 +244,7 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ + + HOSTCC = gcc + HOSTCXX = g++ +-HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer ++HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu89 + HOSTCXXFLAGS = -O2 + + # Decide whether to build built-in, modular, or both. +@@ -382,7 +382,9 @@ KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ + -fno-strict-aliasing -fno-common \ + -Werror-implicit-function-declaration \ + -Wno-format-security \ +- -fno-delete-null-pointer-checks ++ -fno-delete-null-pointer-checks \ ++ -std=gnu89 ++ + KBUILD_AFLAGS_KERNEL := + KBUILD_CFLAGS_KERNEL := + KBUILD_AFLAGS := -D__ASSEMBLY__ +diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi +index da2eb7f6a5b2..6899990be272 100644 +--- a/arch/arm/boot/dts/imx27.dtsi ++++ b/arch/arm/boot/dts/imx27.dtsi +@@ -428,7 +428,7 @@ + + fec: ethernet@1002b000 { + compatible = "fsl,imx27-fec"; +- reg = <0x1002b000 0x4000>; ++ reg = <0x1002b000 0x1000>; + interrupts = <50>; + clocks = <&clks 48>, <&clks 67>; + clock-names = "ipg", "ahb"; +diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S +index a2dcafdf1bc8..98dd389e3b3c 100644 +--- a/arch/arm/kernel/entry-common.S ++++ b/arch/arm/kernel/entry-common.S +@@ -32,7 +32,9 @@ ret_fast_syscall: + UNWIND(.fnstart ) + UNWIND(.cantunwind ) + disable_irq @ disable interrupts +- ldr r1, [tsk, #TI_FLAGS] ++ ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing ++ tst r1, #_TIF_SYSCALL_WORK ++ bne __sys_trace_return + tst r1, #_TIF_WORK_MASK + bne fast_work_pending + asm_trace_hardirqs_on +diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S +index f096e72262f4..1db685104ffc 100644 +--- a/arch/powerpc/kernel/vmlinux.lds.S ++++ b/arch/powerpc/kernel/vmlinux.lds.S +@@ -213,6 +213,7 @@ SECTIONS + *(.opd) + } + ++ . = ALIGN(256); + .got : AT(ADDR(.got) - LOAD_OFFSET) { + __toc_start = .; + #ifndef CONFIG_RELOCATABLE +diff --git a/arch/s390/crypto/ghash_s390.c b/arch/s390/crypto/ghash_s390.c +index 7940dc90e80b..b258110da952 100644 +--- a/arch/s390/crypto/ghash_s390.c ++++ b/arch/s390/crypto/ghash_s390.c +@@ -16,11 +16,12 @@ + #define GHASH_DIGEST_SIZE 16 + + struct ghash_ctx { +- u8 icv[16]; +- u8 key[16]; ++ u8 key[GHASH_BLOCK_SIZE]; + }; + + struct ghash_desc_ctx { ++ u8 icv[GHASH_BLOCK_SIZE]; ++ u8 key[GHASH_BLOCK_SIZE]; + u8 buffer[GHASH_BLOCK_SIZE]; + u32 bytes; + }; +@@ -28,8 +29,10 @@ struct ghash_desc_ctx { + static int ghash_init(struct shash_desc *desc) + { + struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); ++ struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); + + memset(dctx, 0, sizeof(*dctx)); ++ memcpy(dctx->key, ctx->key, GHASH_BLOCK_SIZE); + + return 0; + } +@@ -45,7 +48,6 @@ static int ghash_setkey(struct crypto_shash *tfm, + } + + memcpy(ctx->key, key, GHASH_BLOCK_SIZE); +- memset(ctx->icv, 0, GHASH_BLOCK_SIZE); + + return 0; + } +@@ -54,7 +56,6 @@ static int ghash_update(struct shash_desc *desc, + const u8 *src, unsigned int srclen) + { + struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); +- struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); + unsigned int n; + u8 *buf = dctx->buffer; + int ret; +@@ -70,7 +71,7 @@ static int ghash_update(struct shash_desc *desc, + src += n; + + if (!dctx->bytes) { +- ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, ++ ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf, + GHASH_BLOCK_SIZE); + if (ret != GHASH_BLOCK_SIZE) + return -EIO; +@@ -79,7 +80,7 @@ static int ghash_update(struct shash_desc *desc, + + n = srclen & ~(GHASH_BLOCK_SIZE - 1); + if (n) { +- ret = crypt_s390_kimd(KIMD_GHASH, ctx, src, n); ++ ret = crypt_s390_kimd(KIMD_GHASH, dctx, src, n); + if (ret != n) + return -EIO; + src += n; +@@ -94,7 +95,7 @@ static int ghash_update(struct shash_desc *desc, + return 0; + } + +-static int ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx) ++static int ghash_flush(struct ghash_desc_ctx *dctx) + { + u8 *buf = dctx->buffer; + int ret; +@@ -104,24 +105,24 @@ static int ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx) + + memset(pos, 0, dctx->bytes); + +- ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, GHASH_BLOCK_SIZE); ++ ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf, GHASH_BLOCK_SIZE); + if (ret != GHASH_BLOCK_SIZE) + return -EIO; ++ ++ dctx->bytes = 0; + } + +- dctx->bytes = 0; + return 0; + } + + static int ghash_final(struct shash_desc *desc, u8 *dst) + { + struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); +- struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); + int ret; + +- ret = ghash_flush(ctx, dctx); ++ ret = ghash_flush(dctx); + if (!ret) +- memcpy(dst, ctx->icv, GHASH_BLOCK_SIZE); ++ memcpy(dst, dctx->icv, GHASH_BLOCK_SIZE); + return ret; + } + +diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c +index dcae8fa2bf04..aa0779372e3d 100644 +--- a/arch/x86/kvm/mmu.c ++++ b/arch/x86/kvm/mmu.c +@@ -4078,7 +4078,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, + ++vcpu->kvm->stat.mmu_pte_write; + kvm_mmu_audit(vcpu, AUDIT_PRE_PTE_WRITE); + +- mask.cr0_wp = mask.cr4_pae = mask.nxe = 1; ++ mask.cr0_wp = mask.cr4_pae = mask.nxe = mask.smep_andnot_wp = 1; + for_each_gfn_indirect_valid_sp(vcpu->kvm, sp, gfn) { + if (detect_write_misaligned(sp, gpa, bytes) || + detect_write_flooding(sp)) { +diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c +index fc1aa7909690..726c969b8a81 100644 +--- a/drivers/acpi/osl.c ++++ b/drivers/acpi/osl.c +@@ -172,7 +172,7 @@ static void __init acpi_request_region (struct acpi_generic_address *gas, + request_mem_region(addr, length, desc); + } + +-static int __init acpi_reserve_resources(void) ++static void __init acpi_reserve_resources(void) + { + acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length, + "ACPI PM1a_EVT_BLK"); +@@ -201,10 +201,7 @@ static int __init acpi_reserve_resources(void) + if (!(acpi_gbl_FADT.gpe1_block_length & 0x1)) + acpi_request_region(&acpi_gbl_FADT.xgpe1_block, + acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK"); +- +- return 0; + } +-device_initcall(acpi_reserve_resources); + + void acpi_os_printf(const char *fmt, ...) + { +@@ -1792,6 +1789,7 @@ acpi_status __init acpi_os_initialize(void) + + acpi_status __init acpi_os_initialize1(void) + { ++ acpi_reserve_resources(); + kacpid_wq = alloc_workqueue("kacpid", 0, 1); + kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1); + kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0); +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index 36605abe5a67..b65d79cd43d5 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -1693,8 +1693,7 @@ static void ahci_handle_port_interrupt(struct ata_port *ap, + if (unlikely(resetting)) + status &= ~PORT_IRQ_BAD_PMP; + +- /* if LPM is enabled, PHYRDY doesn't mean anything */ +- if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) { ++ if (sata_lpm_ignore_phy_events(&ap->link)) { + status &= ~PORT_IRQ_PHYRDY; + ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG); + } +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index 538574f98e22..b1c0fcdf46fc 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -6825,6 +6825,38 @@ u32 ata_wait_register(struct ata_port *ap, void __iomem *reg, u32 mask, u32 val, + return tmp; + } + ++/** ++ * sata_lpm_ignore_phy_events - test if PHY event should be ignored ++ * @link: Link receiving the event ++ * ++ * Test whether the received PHY event has to be ignored or not. ++ * ++ * LOCKING: ++ * None: ++ * ++ * RETURNS: ++ * True if the event has to be ignored. ++ */ ++bool sata_lpm_ignore_phy_events(struct ata_link *link) ++{ ++ unsigned long lpm_timeout = link->last_lpm_change + ++ msecs_to_jiffies(ATA_TMOUT_SPURIOUS_PHY); ++ ++ /* if LPM is enabled, PHYRDY doesn't mean anything */ ++ if (link->lpm_policy > ATA_LPM_MAX_POWER) ++ return true; ++ ++ /* ignore the first PHY event after the LPM policy changed ++ * as it is might be spurious ++ */ ++ if ((link->flags & ATA_LFLAG_CHANGED) && ++ time_before(jiffies, lpm_timeout)) ++ return true; ++ ++ return false; ++} ++EXPORT_SYMBOL_GPL(sata_lpm_ignore_phy_events); ++ + /* + * Dummy port_ops + */ +diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c +index 6d8757008318..c6c77b767a8d 100644 +--- a/drivers/ata/libata-eh.c ++++ b/drivers/ata/libata-eh.c +@@ -3488,6 +3488,9 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, + } + } + ++ link->last_lpm_change = jiffies; ++ link->flags |= ATA_LFLAG_CHANGED; ++ + return 0; + + fail: +diff --git a/drivers/gpio/gpio-kempld.c b/drivers/gpio/gpio-kempld.c +index c6d88173f5a2..fe6d4a135cab 100644 +--- a/drivers/gpio/gpio-kempld.c ++++ b/drivers/gpio/gpio-kempld.c +@@ -117,7 +117,7 @@ static int kempld_gpio_get_direction(struct gpio_chip *chip, unsigned offset) + = container_of(chip, struct kempld_gpio_data, chip); + struct kempld_device_data *pld = gpio->pld; + +- return kempld_gpio_get_bit(pld, KEMPLD_GPIO_DIR_NUM(offset), offset); ++ return !kempld_gpio_get_bit(pld, KEMPLD_GPIO_DIR_NUM(offset), offset); + } + + static int kempld_gpio_pincount(struct kempld_device_data *pld) +diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c +index c3664bc05acf..c4558bdb0584 100644 +--- a/drivers/gpu/drm/radeon/cik.c ++++ b/drivers/gpu/drm/radeon/cik.c +@@ -5360,7 +5360,7 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev) + */ + /* set vm size, must be a multiple of 4 */ + WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0); +- WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn); ++ WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn - 1); + for (i = 1; i < 16; i++) { + if (i < 8) + WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), +diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c +index f8c01b8d1594..392d94b94905 100644 +--- a/drivers/gpu/drm/radeon/ni.c ++++ b/drivers/gpu/drm/radeon/ni.c +@@ -1256,7 +1256,8 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev) + */ + for (i = 1; i < 8; i++) { + WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0); +- WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), rdev->vm_manager.max_pfn); ++ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), ++ rdev->vm_manager.max_pfn - 1); + WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), + rdev->gart.table_addr >> 12); + } +diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c +index 2f2deccb3b78..49da9fc6b742 100644 +--- a/drivers/gpu/drm/radeon/si.c ++++ b/drivers/gpu/drm/radeon/si.c +@@ -4084,7 +4084,7 @@ static int si_pcie_gart_enable(struct radeon_device *rdev) + /* empty context1-15 */ + /* set vm size, must be a multiple of 4 */ + WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0); +- WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn); ++ WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn - 1); + /* Assign the pt base to something valid for now; the pts used for + * the VMs are determined by the application and setup and assigned + * on the fly in the vm part of radeon_gart.c +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index 38d5a6334053..20b69bff5b34 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -986,6 +986,7 @@ nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg, + (*t)->dev_attr.attr.name, tg->base + i); + if ((*t)->s2) { + a2 = &su->u.a2; ++ sysfs_attr_init(&a2->dev_attr.attr); + a2->dev_attr.attr.name = su->name; + a2->nr = (*t)->u.s.nr + i; + a2->index = (*t)->u.s.index; +@@ -996,6 +997,7 @@ nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg, + *attrs = &a2->dev_attr.attr; + } else { + a = &su->u.a1; ++ sysfs_attr_init(&a->dev_attr.attr); + a->dev_attr.attr.name = su->name; + a->index = (*t)->u.index + i; + a->dev_attr.attr.mode = +diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c +index e76feb86a1d4..3660cb6fc68a 100644 +--- a/drivers/hwmon/ntc_thermistor.c ++++ b/drivers/hwmon/ntc_thermistor.c +@@ -181,8 +181,10 @@ static struct ntc_thermistor_platform_data * + ntc_thermistor_parse_dt(struct platform_device *pdev) + { + struct iio_channel *chan; ++ enum iio_chan_type type; + struct device_node *np = pdev->dev.of_node; + struct ntc_thermistor_platform_data *pdata; ++ int ret; + + if (!np) + return NULL; +@@ -195,6 +197,13 @@ ntc_thermistor_parse_dt(struct platform_device *pdev) + if (IS_ERR(chan)) + return ERR_CAST(chan); + ++ ret = iio_get_channel_type(chan, &type); ++ if (ret < 0) ++ return ERR_PTR(ret); ++ ++ if (type != IIO_VOLTAGE) ++ return ERR_PTR(-EINVAL); ++ + if (of_property_read_u32(np, "pullup-uv", &pdata->pullup_uv)) + return ERR_PTR(-ENODEV); + if (of_property_read_u32(np, "pullup-ohm", &pdata->pullup_ohm)) +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index cfc5a2e6dcce..e824651a5a11 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -314,7 +314,7 @@ static void elantech_report_semi_mt_data(struct input_dev *dev, + unsigned int x2, unsigned int y2) + { + elantech_set_slot(dev, 0, num_fingers != 0, x1, y1); +- elantech_set_slot(dev, 1, num_fingers == 2, x2, y2); ++ elantech_set_slot(dev, 1, num_fingers >= 2, x2, y2); + } + + /* +diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c +index 0bf1e4edf04d..19da22249bd8 100644 +--- a/drivers/lguest/core.c ++++ b/drivers/lguest/core.c +@@ -176,7 +176,7 @@ static void unmap_switcher(void) + bool lguest_address_ok(const struct lguest *lg, + unsigned long addr, unsigned long len) + { +- return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr); ++ return addr+len <= lg->pfn_limit * PAGE_SIZE && (addr+len >= addr); + } + + /* +diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c +index 683e685ed697..9afd00b45f83 100644 +--- a/drivers/md/raid0.c ++++ b/drivers/md/raid0.c +@@ -531,6 +531,9 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio) + ? (sector & (chunk_sects-1)) + : sector_div(sector, chunk_sects)); + ++ /* Restore due to sector_div */ ++ sector = bio->bi_iter.bi_sector; ++ + if (sectors < bio_sectors(bio)) { + split = bio_split(bio, sectors, GFP_NOIO, fs_bio_set); + bio_chain(split, bio); +@@ -538,7 +541,6 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio) + split = bio; + } + +- sector = bio->bi_iter.bi_sector; + zone = find_zone(mddev->private, §or); + tmp_dev = map_sector(mddev, zone, sector, §or); + split->bi_bdev = tmp_dev->bdev; +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 3545fafe2027..b98c70e1f1a9 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -1914,7 +1914,8 @@ static int resize_stripes(struct r5conf *conf, int newsize) + + conf->slab_cache = sc; + conf->active_name = 1-conf->active_name; +- conf->pool_size = newsize; ++ if (!err) ++ conf->pool_size = newsize; + return err; + } + +diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c +index 42706ea0ba85..201ce37426ab 100644 +--- a/drivers/mmc/host/atmel-mci.c ++++ b/drivers/mmc/host/atmel-mci.c +@@ -1300,7 +1300,7 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + + if (ios->clock) { + unsigned int clock_min = ~0U; +- u32 clkdiv; ++ int clkdiv; + + clk_prepare(host->mck); + unprepare_clk = true; +@@ -1329,7 +1329,12 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + /* Calculate clock divider */ + if (host->caps.has_odd_clk_div) { + clkdiv = DIV_ROUND_UP(host->bus_hz, clock_min) - 2; +- if (clkdiv > 511) { ++ if (clkdiv < 0) { ++ dev_warn(&mmc->class_dev, ++ "clock %u too fast; using %lu\n", ++ clock_min, host->bus_hz / 2); ++ clkdiv = 0; ++ } else if (clkdiv > 511) { + dev_warn(&mmc->class_dev, + "clock %u too slow; using %lu\n", + clock_min, host->bus_hz / (511 + 2)); +diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c +index 57d3967de32f..e8abd0f3a06c 100644 +--- a/drivers/net/wireless/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/rt2x00/rt2800usb.c +@@ -991,6 +991,7 @@ static struct usb_device_id rt2800usb_device_table[] = { + { USB_DEVICE(0x07d1, 0x3c17) }, + { USB_DEVICE(0x2001, 0x3317) }, + { USB_DEVICE(0x2001, 0x3c1b) }, ++ { USB_DEVICE(0x2001, 0x3c25) }, + /* Draytek */ + { USB_DEVICE(0x07fa, 0x7712) }, + /* DVICO */ +diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c +index 4933f02ce1d5..bc409ec43563 100644 +--- a/drivers/net/wireless/rtlwifi/usb.c ++++ b/drivers/net/wireless/rtlwifi/usb.c +@@ -126,7 +126,7 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request, + + do { + status = usb_control_msg(udev, pipe, request, reqtype, value, +- index, pdata, len, 0); /*max. timeout*/ ++ index, pdata, len, 1000); + if (status < 0) { + /* firmware download is checksumed, don't retry */ + if ((value >= FW_8192C_START_ADDRESS && +diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h +index 1f426628a0a5..b5f22a9088e5 100644 +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -728,8 +728,6 @@ extern void qla8044_set_idc_dontreset(struct scsi_qla_host *ha); + extern int qla8044_rd_direct(struct scsi_qla_host *vha, const uint32_t crb_reg); + extern void qla8044_wr_direct(struct scsi_qla_host *vha, + const uint32_t crb_reg, const uint32_t value); +-extern inline void qla8044_set_qsnt_ready(struct scsi_qla_host *vha); +-extern inline void qla8044_need_reset_handler(struct scsi_qla_host *vha); + extern int qla8044_device_state_handler(struct scsi_qla_host *vha); + extern void qla8044_clear_qsnt_ready(struct scsi_qla_host *vha); + extern void qla8044_clear_drv_active(struct qla_hw_data *); +diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c +index f60989d729a8..24f69acdcd58 100644 +--- a/drivers/scsi/qla2xxx/qla_nx2.c ++++ b/drivers/scsi/qla2xxx/qla_nx2.c +@@ -146,7 +146,7 @@ qla8044_rmw_crb_reg(struct scsi_qla_host *vha, + return; + } + +-inline void ++static inline void + qla8044_set_qsnt_ready(struct scsi_qla_host *vha) + { + uint32_t qsnt_state; +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index e8abb731c7ec..a10706409927 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -1599,6 +1599,7 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) + { + u64 start_lba = blk_rq_pos(scmd->request); + u64 end_lba = blk_rq_pos(scmd->request) + (scsi_bufflen(scmd) / 512); ++ u64 factor = scmd->device->sector_size / 512; + u64 bad_lba; + int info_valid; + /* +@@ -1620,16 +1621,9 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) + if (scsi_bufflen(scmd) <= scmd->device->sector_size) + return 0; + +- if (scmd->device->sector_size < 512) { +- /* only legitimate sector_size here is 256 */ +- start_lba <<= 1; +- end_lba <<= 1; +- } else { +- /* be careful ... don't want any overflows */ +- unsigned int factor = scmd->device->sector_size / 512; +- do_div(start_lba, factor); +- do_div(end_lba, factor); +- } ++ /* be careful ... don't want any overflows */ ++ do_div(start_lba, factor); ++ do_div(end_lba, factor); + + /* The bad lba was reported incorrectly, we have no idea where + * the error is. +@@ -2196,8 +2190,7 @@ got_data: + if (sector_size != 512 && + sector_size != 1024 && + sector_size != 2048 && +- sector_size != 4096 && +- sector_size != 256) { ++ sector_size != 4096) { + sd_printk(KERN_NOTICE, sdkp, "Unsupported sector size %d.\n", + sector_size); + /* +@@ -2248,8 +2241,6 @@ got_data: + sdkp->capacity <<= 2; + else if (sector_size == 1024) + sdkp->capacity <<= 1; +- else if (sector_size == 256) +- sdkp->capacity >>= 1; + + blk_queue_physical_block_size(sdp->request_queue, + sdkp->physical_block_size); +diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c +index 97892f258043..3bb6646bb406 100644 +--- a/drivers/scsi/storvsc_drv.c ++++ b/drivers/scsi/storvsc_drv.c +@@ -1625,8 +1625,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) + break; + default: + vm_srb->data_in = UNKNOWN_TYPE; +- vm_srb->win8_extension.srb_flags |= (SRB_FLAGS_DATA_IN | +- SRB_FLAGS_DATA_OUT); ++ vm_srb->win8_extension.srb_flags |= SRB_FLAGS_NO_DATA_TRANSFER; + break; + } + +diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c +index 2fa3a5a6580f..f2e6599eef33 100644 +--- a/drivers/staging/gdm724x/gdm_mux.c ++++ b/drivers/staging/gdm724x/gdm_mux.c +@@ -158,7 +158,7 @@ static int up_to_host(struct mux_rx *r) + unsigned int start_flag; + unsigned int payload_size; + unsigned short packet_type; +- int dummy_cnt; ++ int total_len; + u32 packet_size_sum = r->offset; + int index; + int ret = TO_HOST_INVALID_PACKET; +@@ -175,10 +175,10 @@ static int up_to_host(struct mux_rx *r) + break; + } + +- dummy_cnt = ALIGN(MUX_HEADER_SIZE + payload_size, 4); ++ total_len = ALIGN(MUX_HEADER_SIZE + payload_size, 4); + + if (len - packet_size_sum < +- MUX_HEADER_SIZE + payload_size + dummy_cnt) { ++ total_len) { + pr_err("invalid payload : %d %d %04x\n", + payload_size, len, packet_type); + break; +@@ -201,7 +201,7 @@ static int up_to_host(struct mux_rx *r) + break; + } + +- packet_size_sum += MUX_HEADER_SIZE + payload_size + dummy_cnt; ++ packet_size_sum += total_len; + if (len - packet_size_sum <= MUX_HEADER_SIZE + 2) { + ret = r->callback(NULL, + 0, +@@ -359,7 +359,6 @@ static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index, + struct mux_pkt_header *mux_header; + struct mux_tx *t = NULL; + static u32 seq_num = 1; +- int dummy_cnt; + int total_len; + int ret; + unsigned long flags; +@@ -372,9 +371,7 @@ static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index, + + spin_lock_irqsave(&mux_dev->write_lock, flags); + +- dummy_cnt = ALIGN(MUX_HEADER_SIZE + len, 4); +- +- total_len = len + MUX_HEADER_SIZE + dummy_cnt; ++ total_len = ALIGN(MUX_HEADER_SIZE + len, 4); + + t = alloc_mux_tx(total_len); + if (!t) { +@@ -390,7 +387,8 @@ static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index, + mux_header->packet_type = __cpu_to_le16(packet_type[tty_index]); + + memcpy(t->buf+MUX_HEADER_SIZE, data, len); +- memset(t->buf+MUX_HEADER_SIZE+len, 0, dummy_cnt); ++ memset(t->buf+MUX_HEADER_SIZE+len, 0, total_len - MUX_HEADER_SIZE - ++ len); + + t->len = total_len; + t->callback = cb; +diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h +index 09ffd9bc8991..6ebdd3f35dd6 100644 +--- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h ++++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h +@@ -1460,12 +1460,12 @@ extern void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, + + extern const long ieee80211_wlan_frequencies[]; + +-extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee) ++static inline void ieee80211_increment_scans(struct ieee80211_device *ieee) + { + ieee->scans++; + } + +-extern inline int ieee80211_get_scans(struct ieee80211_device *ieee) ++static inline int ieee80211_get_scans(struct ieee80211_device *ieee) + { + return ieee->scans; + } +diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h +index 83f5f57373a6..59dc0782df44 100644 +--- a/drivers/staging/rtl8192e/rtllib.h ++++ b/drivers/staging/rtl8192e/rtllib.h +@@ -2761,7 +2761,6 @@ extern void rtllib_stop_scan(struct rtllib_device *ieee); + extern bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan); + extern void rtllib_stop_scan_syncro(struct rtllib_device *ieee); + extern void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh); +-extern inline struct sk_buff *rtllib_probe_req(struct rtllib_device *ieee); + extern u8 MgntQuery_MgntFrameTxRate(struct rtllib_device *ieee); + extern void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, + short pwr); +@@ -2943,12 +2942,12 @@ void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh); + + extern const long rtllib_wlan_frequencies[]; + +-extern inline void rtllib_increment_scans(struct rtllib_device *ieee) ++static inline void rtllib_increment_scans(struct rtllib_device *ieee) + { + ieee->scans++; + } + +-extern inline int rtllib_get_scans(struct rtllib_device *ieee) ++static inline int rtllib_get_scans(struct rtllib_device *ieee) + { + return ieee->scans; + } +diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c +index 4bf72bc1ba7b..7b5093aa8683 100644 +--- a/drivers/staging/rtl8192e/rtllib_softmac.c ++++ b/drivers/staging/rtl8192e/rtllib_softmac.c +@@ -341,7 +341,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, + } + } + +-inline struct sk_buff *rtllib_probe_req(struct rtllib_device *ieee) ++static inline struct sk_buff *rtllib_probe_req(struct rtllib_device *ieee) + { + unsigned int len, rate_len; + u8 *tag; +diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h +index bc64f05a7e6a..b1a0380ee596 100644 +--- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h ++++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h +@@ -2250,7 +2250,7 @@ static inline void *ieee80211_priv(struct net_device *dev) + return ((struct ieee80211_device *)netdev_priv(dev))->priv; + } + +-extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len) ++static inline int ieee80211_is_empty_essid(const char *essid, int essid_len) + { + /* Single white space is for Linksys APs */ + if (essid_len == 1 && essid[0] == ' ') +@@ -2266,7 +2266,7 @@ extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len) + return 1; + } + +-extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode) ++static inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode) + { + /* + * It is possible for both access points and our device to support +@@ -2292,7 +2292,7 @@ extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mod + return 0; + } + +-extern inline int ieee80211_get_hdrlen(u16 fc) ++static inline int ieee80211_get_hdrlen(u16 fc) + { + int hdrlen = IEEE80211_3ADDR_LEN; + +@@ -2578,12 +2578,12 @@ void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee); + + extern const long ieee80211_wlan_frequencies[]; + +-extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee) ++static inline void ieee80211_increment_scans(struct ieee80211_device *ieee) + { + ieee->scans++; + } + +-extern inline int ieee80211_get_scans(struct ieee80211_device *ieee) ++static inline int ieee80211_get_scans(struct ieee80211_device *ieee) + { + return ieee->scans; + } +diff --git a/drivers/staging/rtl8712/ieee80211.h b/drivers/staging/rtl8712/ieee80211.h +index da4000e49da6..8269be80437a 100644 +--- a/drivers/staging/rtl8712/ieee80211.h ++++ b/drivers/staging/rtl8712/ieee80211.h +@@ -734,7 +734,7 @@ enum ieee80211_state { + #define IEEE_G (1<<2) + #define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G) + +-extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len) ++static inline int ieee80211_is_empty_essid(const char *essid, int essid_len) + { + /* Single white space is for Linksys APs */ + if (essid_len == 1 && essid[0] == ' ') +@@ -748,7 +748,7 @@ extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len) + return 1; + } + +-extern inline int ieee80211_get_hdrlen(u16 fc) ++static inline int ieee80211_get_hdrlen(u16 fc) + { + int hdrlen = 24; + +diff --git a/drivers/staging/wlags49_h2/wl_internal.h b/drivers/staging/wlags49_h2/wl_internal.h +index 78129e93920f..1ecb5cb44bd5 100644 +--- a/drivers/staging/wlags49_h2/wl_internal.h ++++ b/drivers/staging/wlags49_h2/wl_internal.h +@@ -1013,7 +1013,7 @@ static inline void wl_unlock(struct wl_private *lp, + /* Interrupt enable disable functions */ + /********************************************************************/ + +-extern inline void wl_act_int_on(struct wl_private *lp) ++static inline void wl_act_int_on(struct wl_private *lp) + { + /* + * Only do something when the driver is handling +@@ -1025,7 +1025,7 @@ extern inline void wl_act_int_on(struct wl_private *lp) + } + } + +-extern inline void wl_act_int_off(struct wl_private *lp) ++static inline void wl_act_int_off(struct wl_private *lp) + { + /* + * Only do something when the driver is handling +diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c +index 29f28808fc03..9b90cfacf75c 100644 +--- a/drivers/target/target_core_pscsi.c ++++ b/drivers/target/target_core_pscsi.c +@@ -520,6 +520,7 @@ static int pscsi_configure_device(struct se_device *dev) + " pdv_host_id: %d\n", pdv->pdv_host_id); + return -EINVAL; + } ++ pdv->pdv_lld_host = sh; + } + } else { + if (phv->phv_mode == PHV_VIRTUAL_HOST_ID) { +@@ -602,6 +603,8 @@ static void pscsi_free_device(struct se_device *dev) + if ((phv->phv_mode == PHV_LLD_SCSI_HOST_NO) && + (phv->phv_lld_host != NULL)) + scsi_host_put(phv->phv_lld_host); ++ else if (pdv->pdv_lld_host) ++ scsi_host_put(pdv->pdv_lld_host); + + if ((sd->type == TYPE_DISK) || (sd->type == TYPE_ROM)) + scsi_device_put(sd); +diff --git a/drivers/target/target_core_pscsi.h b/drivers/target/target_core_pscsi.h +index 1bd757dff8ee..820d3052b775 100644 +--- a/drivers/target/target_core_pscsi.h ++++ b/drivers/target/target_core_pscsi.h +@@ -45,6 +45,7 @@ struct pscsi_dev_virt { + int pdv_lun_id; + struct block_device *pdv_bd; + struct scsi_device *pdv_sd; ++ struct Scsi_Host *pdv_lld_host; + } ____cacheline_aligned; + + typedef enum phv_modes { +diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c +index f251521baaa2..ee52ab7d3730 100644 +--- a/drivers/thermal/step_wise.c ++++ b/drivers/thermal/step_wise.c +@@ -146,9 +146,6 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) + dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n", + old_target, (int)instance->target); + +- if (old_target == instance->target) +- continue; +- + /* Activate a passive thermal instance */ + if (old_target == THERMAL_NO_TARGET && + instance->target != THERMAL_NO_TARGET) +diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c +index 8eb65f26fcae..59a7da7c6c5e 100644 +--- a/drivers/tty/hvc/hvc_xen.c ++++ b/drivers/tty/hvc/hvc_xen.c +@@ -289,7 +289,7 @@ static int xen_initial_domain_console_init(void) + return -ENOMEM; + } + +- info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0); ++ info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false); + info->vtermno = HVC_COOKIE; + + spin_lock(&xencons_lock); +diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c +index 2ebe47b78a3e..5bfd8076b21f 100644 +--- a/drivers/tty/n_gsm.c ++++ b/drivers/tty/n_gsm.c +@@ -3166,7 +3166,7 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state) + return gsmtty_modem_update(dlci, encode); + } + +-static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty) ++static void gsmtty_cleanup(struct tty_struct *tty) + { + struct gsm_dlci *dlci = tty->driver_data; + struct gsm_mux *gsm = dlci->gsm; +@@ -3174,7 +3174,6 @@ static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty) + dlci_put(dlci); + dlci_put(gsm->dlci[0]); + mux_put(gsm); +- driver->ttys[tty->index] = NULL; + } + + /* Virtual ttys for the demux */ +@@ -3195,7 +3194,7 @@ static const struct tty_operations gsmtty_ops = { + .tiocmget = gsmtty_tiocmget, + .tiocmset = gsmtty_tiocmset, + .break_ctl = gsmtty_break_ctl, +- .remove = gsmtty_remove, ++ .cleanup = gsmtty_cleanup, + }; + + +diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c +index 7d1cc01796b6..3740a3fd545b 100644 +--- a/drivers/usb/gadget/configfs.c ++++ b/drivers/usb/gadget/configfs.c +@@ -765,6 +765,7 @@ static void purge_configs_funcs(struct gadget_info *gi) + } + } + c->next_interface_id = 0; ++ memset(c->interface, 0, sizeof(c->interface)); + c->superspeed = 0; + c->highspeed = 0; + c->fullspeed = 0; +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index 05185b9d4495..f615712e8251 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -2213,8 +2213,13 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, + break; + case COMP_DEV_ERR: + case COMP_STALL: ++ frame->status = -EPROTO; ++ skip_td = true; ++ break; + case COMP_TX_ERR: + frame->status = -EPROTO; ++ if (event_trb != td->last_trb) ++ return 0; + skip_td = true; + break; + case COMP_STOP: +@@ -2822,7 +2827,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) + xhci_halt(xhci); + hw_died: + spin_unlock(&xhci->lock); +- return -ESHUTDOWN; ++ return IRQ_HANDLED; + } + + /* +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 7225dd242bfa..70facb725105 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1268,7 +1268,7 @@ union xhci_trb { + * since the command ring is 64-byte aligned. + * It must also be greater than 16. + */ +-#define TRBS_PER_SEGMENT 64 ++#define TRBS_PER_SEGMENT 256 + /* Allow two commands + a link TRB, along with any reserved command TRBs */ + #define MAX_RSVD_CMD_TRBS (TRBS_PER_SEGMENT - 3) + #define TRB_SEGMENT_SIZE (TRBS_PER_SEGMENT*16) +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 8d114b9733ed..02de4cf48a5b 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -127,6 +127,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */ + { USB_DEVICE(0x10C4, 0x8977) }, /* CEL MeshWorks DevKit Device */ ++ { USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */ + { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ +diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c +index e9bad928039f..521959370b66 100644 +--- a/drivers/usb/serial/pl2303.c ++++ b/drivers/usb/serial/pl2303.c +@@ -61,7 +61,6 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) }, + { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) }, +- { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1), + .driver_info = PL2303_QUIRK_UART_STATE_IDX0 }, + { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65), +diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h +index 71fd9da1d6e7..e3b7af8adfb7 100644 +--- a/drivers/usb/serial/pl2303.h ++++ b/drivers/usb/serial/pl2303.h +@@ -62,10 +62,6 @@ + #define ALCATEL_VENDOR_ID 0x11f7 + #define ALCATEL_PRODUCT_ID 0x02df + +-/* Samsung I330 phone cradle */ +-#define SAMSUNG_VENDOR_ID 0x04e8 +-#define SAMSUNG_PRODUCT_ID 0x8001 +- + #define SIEMENS_VENDOR_ID 0x11f5 + #define SIEMENS_PRODUCT_ID_SX1 0x0001 + #define SIEMENS_PRODUCT_ID_X65 0x0003 +diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c +index bf2bd40e5f2a..60afb39eb73c 100644 +--- a/drivers/usb/serial/visor.c ++++ b/drivers/usb/serial/visor.c +@@ -95,7 +95,7 @@ static const struct usb_device_id id_table[] = { + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, + { USB_DEVICE(ACER_VENDOR_ID, ACER_S10_ID), + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, +- { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID), ++ { USB_DEVICE_INTERFACE_CLASS(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID, 0xff), + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, + { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID), + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, +diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h +index 7f625306ea80..821e1e2f70f6 100644 +--- a/drivers/usb/storage/unusual_devs.h ++++ b/drivers/usb/storage/unusual_devs.h +@@ -760,6 +760,13 @@ UNUSUAL_DEV( 0x059f, 0x0643, 0x0000, 0x0000, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_GO_SLOW ), + ++/* Reported by Christian Schaller */ ++UNUSUAL_DEV( 0x059f, 0x0651, 0x0000, 0x0000, ++ "LaCie", ++ "External HDD", ++ USB_SC_DEVICE, USB_PR_DEVICE, NULL, ++ US_FL_NO_WP_DETECT ), ++ + /* Submitted by Joel Bourquard + * Some versions of this device need the SubClass and Protocol overrides + * while others don't. +diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c +index a5cc476256f1..5af64e966ed6 100644 +--- a/drivers/xen/events/events_base.c ++++ b/drivers/xen/events/events_base.c +@@ -973,7 +973,7 @@ unsigned xen_evtchn_nr_channels(void) + } + EXPORT_SYMBOL_GPL(xen_evtchn_nr_channels); + +-int bind_virq_to_irq(unsigned int virq, unsigned int cpu) ++int bind_virq_to_irq(unsigned int virq, unsigned int cpu, bool percpu) + { + struct evtchn_bind_virq bind_virq; + int evtchn, irq, ret; +@@ -987,8 +987,12 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu) + if (irq < 0) + goto out; + +- irq_set_chip_and_handler_name(irq, &xen_percpu_chip, +- handle_percpu_irq, "virq"); ++ if (percpu) ++ irq_set_chip_and_handler_name(irq, &xen_percpu_chip, ++ handle_percpu_irq, "virq"); ++ else ++ irq_set_chip_and_handler_name(irq, &xen_dynamic_chip, ++ handle_edge_irq, "virq"); + + bind_virq.virq = virq; + bind_virq.vcpu = cpu; +@@ -1078,7 +1082,7 @@ int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, + { + int irq, retval; + +- irq = bind_virq_to_irq(virq, cpu); ++ irq = bind_virq_to_irq(virq, cpu, irqflags & IRQF_PERCPU); + if (irq < 0) + return irq; + retval = request_irq(irq, handler, irqflags, devname, dev_id); +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index 78f46089a077..35240a704413 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -819,7 +819,7 @@ static int load_elf_binary(struct linux_binprm *bprm) + total_size = total_mapping_size(elf_phdata, + loc->elf_ex.e_phnum); + if (!total_size) { +- error = -EINVAL; ++ retval = -EINVAL; + goto out_free_dentry; + } + } +diff --git a/fs/dcache.c b/fs/dcache.c +index a9231c872342..1d7e8a3fb6cd 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -1135,13 +1135,13 @@ ascend: + /* might go back up the wrong parent if we have had a rename. */ + if (need_seqretry(&rename_lock, seq)) + goto rename_retry; +- next = child->d_child.next; +- while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) { ++ /* go into the first sibling still alive */ ++ do { ++ next = child->d_child.next; + if (next == &this_parent->d_subdirs) + goto ascend; + child = list_entry(next, struct dentry, d_child); +- next = next->next; +- } ++ } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)); + rcu_read_unlock(); + goto resume; + } +diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c +index 3fe29de832c8..ff42208417b9 100644 +--- a/fs/ext4/ext4_jbd2.c ++++ b/fs/ext4/ext4_jbd2.c +@@ -87,6 +87,12 @@ int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) + ext4_put_nojournal(handle); + return 0; + } ++ ++ if (!handle->h_transaction) { ++ err = jbd2_journal_stop(handle); ++ return handle->h_err ? handle->h_err : err; ++ } ++ + sb = handle->h_transaction->t_journal->j_private; + err = handle->h_err; + rc = jbd2_journal_stop(handle); +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 96a1ce159f51..4e237a6b4b33 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -361,7 +361,7 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext) + ext4_lblk_t lblock = le32_to_cpu(ext->ee_block); + ext4_lblk_t last = lblock + len - 1; + +- if (lblock > last) ++ if (len == 0 || lblock > last) + return 0; + return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len); + } +diff --git a/fs/fhandle.c b/fs/fhandle.c +index 999ff5c3cab0..d59712dfa3e7 100644 +--- a/fs/fhandle.c ++++ b/fs/fhandle.c +@@ -195,8 +195,9 @@ static int handle_to_path(int mountdirfd, struct file_handle __user *ufh, + goto out_err; + } + /* copy the full handle */ +- if (copy_from_user(handle, ufh, +- sizeof(struct file_handle) + ++ *handle = f_handle; ++ if (copy_from_user(&handle->f_handle, ++ &ufh->f_handle, + f_handle.handle_bytes)) { + retval = -EFAULT; + goto out_handle; +diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c +index bcbef08a4d8f..a5f72a36c6c8 100644 +--- a/fs/jbd2/recovery.c ++++ b/fs/jbd2/recovery.c +@@ -839,15 +839,23 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh, + { + jbd2_journal_revoke_header_t *header; + int offset, max; ++ int csum_size = 0; ++ __u32 rcount; + int record_len = 4; + + header = (jbd2_journal_revoke_header_t *) bh->b_data; + offset = sizeof(jbd2_journal_revoke_header_t); +- max = be32_to_cpu(header->r_count); ++ rcount = be32_to_cpu(header->r_count); + + if (!jbd2_revoke_block_csum_verify(journal, header)) + return -EINVAL; + ++ if (jbd2_journal_has_csum_v2or3(journal)) ++ csum_size = sizeof(struct jbd2_journal_revoke_tail); ++ if (rcount > journal->j_blocksize - csum_size) ++ return -EINVAL; ++ max = rcount; ++ + if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) + record_len = 8; + +diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c +index d5e95a175c92..8ecf9b92f163 100644 +--- a/fs/jbd2/revoke.c ++++ b/fs/jbd2/revoke.c +@@ -583,7 +583,7 @@ static void write_one_revoke_record(journal_t *journal, + { + int csum_size = 0; + struct buffer_head *descriptor; +- int offset; ++ int sz, offset; + journal_header_t *header; + + /* If we are already aborting, this all becomes a noop. We +@@ -600,9 +600,14 @@ static void write_one_revoke_record(journal_t *journal, + if (jbd2_journal_has_csum_v2or3(journal)) + csum_size = sizeof(struct jbd2_journal_revoke_tail); + ++ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) ++ sz = 8; ++ else ++ sz = 4; ++ + /* Make sure we have a descriptor with space left for the record */ + if (descriptor) { +- if (offset >= journal->j_blocksize - csum_size) { ++ if (offset + sz > journal->j_blocksize - csum_size) { + flush_descriptor(journal, descriptor, offset, write_op); + descriptor = NULL; + } +@@ -625,16 +630,13 @@ static void write_one_revoke_record(journal_t *journal, + *descriptorp = descriptor; + } + +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) { ++ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) + * ((__be64 *)(&descriptor->b_data[offset])) = + cpu_to_be64(record->blocknr); +- offset += 8; +- +- } else { ++ else + * ((__be32 *)(&descriptor->b_data[offset])) = + cpu_to_be32(record->blocknr); +- offset += 4; +- } ++ offset += sz; + + *offsetp = offset; + } +diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c +index f8a5d6a166fb..ecc57071a1a9 100644 +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -551,7 +551,6 @@ int jbd2_journal_extend(handle_t *handle, int nblocks) + int result; + int wanted; + +- WARN_ON(!transaction); + if (is_handle_aborted(handle)) + return -EROFS; + journal = transaction->t_journal; +@@ -627,7 +626,6 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask) + tid_t tid; + int need_to_start, ret; + +- WARN_ON(!transaction); + /* If we've had an abort of any type, don't even think about + * actually doing the restart! */ + if (is_handle_aborted(handle)) +@@ -791,7 +789,6 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, + int need_copy = 0; + unsigned long start_lock, time_lock; + +- WARN_ON(!transaction); + if (is_handle_aborted(handle)) + return -EROFS; + journal = transaction->t_journal; +@@ -1057,7 +1054,6 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh) + int err; + + jbd_debug(5, "journal_head %p\n", jh); +- WARN_ON(!transaction); + err = -EROFS; + if (is_handle_aborted(handle)) + goto out; +@@ -1271,7 +1267,6 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) + struct journal_head *jh; + int ret = 0; + +- WARN_ON(!transaction); + if (is_handle_aborted(handle)) + return -EROFS; + journal = transaction->t_journal; +@@ -1407,7 +1402,6 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh) + int err = 0; + int was_modified = 0; + +- WARN_ON(!transaction); + if (is_handle_aborted(handle)) + return -EROFS; + journal = transaction->t_journal; +@@ -1538,8 +1532,22 @@ int jbd2_journal_stop(handle_t *handle) + tid_t tid; + pid_t pid; + +- if (!transaction) +- goto free_and_exit; ++ if (!transaction) { ++ /* ++ * Handle is already detached from the transaction so ++ * there is nothing to do other than decrease a refcount, ++ * or free the handle if refcount drops to zero ++ */ ++ if (--handle->h_ref > 0) { ++ jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1, ++ handle->h_ref); ++ return err; ++ } else { ++ if (handle->h_rsv_handle) ++ jbd2_free_handle(handle->h_rsv_handle); ++ goto free_and_exit; ++ } ++ } + journal = transaction->t_journal; + + J_ASSERT(journal_current_handle() == handle); +@@ -2381,7 +2389,6 @@ int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode) + transaction_t *transaction = handle->h_transaction; + journal_t *journal; + +- WARN_ON(!transaction); + if (is_handle_aborted(handle)) + return -EROFS; + journal = transaction->t_journal; +diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c +index d8b0afde2179..2dba0caf1f4a 100644 +--- a/fs/omfs/inode.c ++++ b/fs/omfs/inode.c +@@ -361,7 +361,7 @@ nomem: + } + + enum { +- Opt_uid, Opt_gid, Opt_umask, Opt_dmask, Opt_fmask ++ Opt_uid, Opt_gid, Opt_umask, Opt_dmask, Opt_fmask, Opt_err + }; + + static const match_table_t tokens = { +@@ -370,6 +370,7 @@ static const match_table_t tokens = { + {Opt_umask, "umask=%o"}, + {Opt_dmask, "dmask=%o"}, + {Opt_fmask, "fmask=%o"}, ++ {Opt_err, NULL}, + }; + + static int parse_options(char *options, struct omfs_sb_info *sbi) +diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h +index ca52de5a5c97..bb5367d288fb 100644 +--- a/include/drm/drm_pciids.h ++++ b/include/drm/drm_pciids.h +@@ -186,6 +186,7 @@ + {0x1002, 0x6658, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x665c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x665d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x665f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6663, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6664, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ +diff --git a/include/linux/libata.h b/include/linux/libata.h +index e13b3aef0b0c..b84e786ff990 100644 +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -204,6 +204,7 @@ enum { + ATA_LFLAG_SW_ACTIVITY = (1 << 7), /* keep activity stats */ + ATA_LFLAG_NO_LPM = (1 << 8), /* disable LPM on this link */ + ATA_LFLAG_RST_ONCE = (1 << 9), /* limit recovery to one reset */ ++ ATA_LFLAG_CHANGED = (1 << 10), /* LPM state changed on this link */ + + /* struct ata_port flags */ + ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ +@@ -307,6 +308,12 @@ enum { + */ + ATA_TMOUT_PMP_SRST_WAIT = 5000, + ++ /* When the LPM policy is set to ATA_LPM_MAX_POWER, there might ++ * be a spurious PHY event, so ignore the first PHY event that ++ * occurs within 10s after the policy change. ++ */ ++ ATA_TMOUT_SPURIOUS_PHY = 10000, ++ + /* ATA bus states */ + BUS_UNKNOWN = 0, + BUS_DMA = 1, +@@ -785,6 +792,8 @@ struct ata_link { + struct ata_eh_context eh_context; + + struct ata_device device[ATA_MAX_DEVICES]; ++ ++ unsigned long last_lpm_change; /* when last LPM change happened */ + }; + #define ATA_LINK_CLEAR_BEGIN offsetof(struct ata_link, active_tag) + #define ATA_LINK_CLEAR_END offsetof(struct ata_link, device[0]) +@@ -1201,6 +1210,7 @@ extern struct ata_device *ata_dev_pair(struct ata_device *adev); + extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev); + extern void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap); + extern void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, struct list_head *eh_q); ++extern bool sata_lpm_ignore_phy_events(struct ata_link *link); + + extern int ata_cable_40wire(struct ata_port *ap); + extern int ata_cable_80wire(struct ata_port *ap); +diff --git a/include/xen/events.h b/include/xen/events.h +index c9c85cf84895..5d84cd0a51b7 100644 +--- a/include/xen/events.h ++++ b/include/xen/events.h +@@ -14,7 +14,7 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn, + irq_handler_t handler, + unsigned long irqflags, const char *devname, + void *dev_id); +-int bind_virq_to_irq(unsigned int virq, unsigned int cpu); ++int bind_virq_to_irq(unsigned int virq, unsigned int cpu, bool percpu); + int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, + irq_handler_t handler, + unsigned long irqflags, const char *devname, +diff --git a/lib/strnlen_user.c b/lib/strnlen_user.c +index a28df5206d95..11649615c505 100644 +--- a/lib/strnlen_user.c ++++ b/lib/strnlen_user.c +@@ -57,7 +57,8 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count, + return res + find_zero(data) + 1 - align; + } + res += sizeof(unsigned long); +- if (unlikely(max < sizeof(unsigned long))) ++ /* We already handled 'unsigned long' bytes. Did we do it all ? */ ++ if (unlikely(max <= sizeof(unsigned long))) + break; + max -= sizeof(unsigned long); + if (unlikely(__get_user(c,(unsigned long __user *)(src+res)))) +diff --git a/mm/mempolicy.c b/mm/mempolicy.c +index e8fff0fa1202..936866e72b1d 100644 +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -2663,7 +2663,7 @@ static void __init check_numabalancing_enable(void) + if (numabalancing_override) + set_numabalancing_state(numabalancing_override == 1); + +- if (nr_node_ids > 1 && !numabalancing_override) { ++ if (num_online_nodes() > 1 && !numabalancing_override) { + pr_info("%s automatic NUMA balancing. " + "Configure with numa_balancing= or the " + "kernel.numa_balancing sysctl", +diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c +index 45f077c60348..5b7ef5bb90ed 100644 +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -1932,20 +1932,29 @@ static void kick_requests(struct ceph_osd_client *osdc, bool force_resend, + err = __map_request(osdc, req, + force_resend || force_resend_writes); + dout("__map_request returned %d\n", err); +- if (err == 0) +- continue; /* no change and no osd was specified */ + if (err < 0) + continue; /* hrm! */ +- if (req->r_osd == NULL) { +- dout("tid %llu maps to no valid osd\n", req->r_tid); +- needmap++; /* request a newer map */ +- continue; +- } ++ if (req->r_osd == NULL || err > 0) { ++ if (req->r_osd == NULL) { ++ dout("lingering %p tid %llu maps to no osd\n", ++ req, req->r_tid); ++ /* ++ * A homeless lingering request makes ++ * no sense, as it's job is to keep ++ * a particular OSD connection open. ++ * Request a newer map and kick the ++ * request, knowing that it won't be ++ * resent until we actually get a map ++ * that can tell us where to send it. ++ */ ++ needmap++; ++ } + +- dout("kicking lingering %p tid %llu osd%d\n", req, req->r_tid, +- req->r_osd ? req->r_osd->o_osd : -1); +- __register_request(osdc, req); +- __unregister_linger_request(osdc, req); ++ dout("kicking lingering %p tid %llu osd%d\n", req, ++ req->r_tid, req->r_osd ? req->r_osd->o_osd : -1); ++ __register_request(osdc, req); ++ __unregister_linger_request(osdc, req); ++ } + } + reset_changed_osds(osdc); + mutex_unlock(&osdc->request_mutex); +diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c +index 6ee2b5863572..f21b142dee1f 100644 +--- a/net/mac80211/wep.c ++++ b/net/mac80211/wep.c +@@ -98,8 +98,7 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local, + + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); + +- if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN || +- skb_headroom(skb) < IEEE80211_WEP_IV_LEN)) ++ if (WARN_ON(skb_headroom(skb) < IEEE80211_WEP_IV_LEN)) + return NULL; + + hdrlen = ieee80211_hdrlen(hdr->frame_control); +@@ -169,6 +168,9 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, + size_t len; + u8 rc4key[3 + WLAN_KEY_LEN_WEP104]; + ++ if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN)) ++ return -1; ++ + iv = ieee80211_wep_add_iv(local, skb, keylen, keyidx); + if (!iv) + return -1; +diff --git a/net/socket.c b/net/socket.c +index 1b2c2d62ff20..b72fc137e1a6 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -2007,14 +2007,12 @@ static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, + int err, ctl_len, total_len; + + err = -EFAULT; +- if (MSG_CMSG_COMPAT & flags) { +- if (get_compat_msghdr(msg_sys, msg_compat)) +- return -EFAULT; +- } else { ++ if (MSG_CMSG_COMPAT & flags) ++ err = get_compat_msghdr(msg_sys, msg_compat); ++ else + err = copy_msghdr_from_user(msg_sys, msg); +- if (err) +- return err; +- } ++ if (err) ++ return err; + + if (msg_sys->msg_iovlen > UIO_FASTIOV) { + err = -EMSGSIZE; +@@ -2219,14 +2217,12 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, + struct sockaddr __user *uaddr; + int __user *uaddr_len; + +- if (MSG_CMSG_COMPAT & flags) { +- if (get_compat_msghdr(msg_sys, msg_compat)) +- return -EFAULT; +- } else { ++ if (MSG_CMSG_COMPAT & flags) ++ err = get_compat_msghdr(msg_sys, msg_compat); ++ else + err = copy_msghdr_from_user(msg_sys, msg); +- if (err) +- return err; +- } ++ if (err) ++ return err; + + if (msg_sys->msg_iovlen > UIO_FASTIOV) { + err = -EMSGSIZE; +diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c +index 1ec19f6f0c2b..eeeba5adee6d 100644 +--- a/net/sunrpc/auth_gss/gss_rpc_xdr.c ++++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c +@@ -793,20 +793,26 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, + { + u32 value_follows; + int err; ++ struct page *scratch; ++ ++ scratch = alloc_page(GFP_KERNEL); ++ if (!scratch) ++ return -ENOMEM; ++ xdr_set_scratch_buffer(xdr, page_address(scratch), PAGE_SIZE); + + /* res->status */ + err = gssx_dec_status(xdr, &res->status); + if (err) +- return err; ++ goto out_free; + + /* res->context_handle */ + err = gssx_dec_bool(xdr, &value_follows); + if (err) +- return err; ++ goto out_free; + if (value_follows) { + err = gssx_dec_ctx(xdr, res->context_handle); + if (err) +- return err; ++ goto out_free; + } else { + res->context_handle = NULL; + } +@@ -814,11 +820,11 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, + /* res->output_token */ + err = gssx_dec_bool(xdr, &value_follows); + if (err) +- return err; ++ goto out_free; + if (value_follows) { + err = gssx_dec_buffer(xdr, res->output_token); + if (err) +- return err; ++ goto out_free; + } else { + res->output_token = NULL; + } +@@ -826,14 +832,17 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, + /* res->delegated_cred_handle */ + err = gssx_dec_bool(xdr, &value_follows); + if (err) +- return err; ++ goto out_free; + if (value_follows) { + /* we do not support upcall servers sending this data. */ +- return -EINVAL; ++ err = -EINVAL; ++ goto out_free; + } + + /* res->options */ + err = gssx_dec_option_array(xdr, &res->options); + ++out_free: ++ __free_page(scratch); + return err; + } +diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c +index 976493c4a695..50981b148121 100644 +--- a/sound/pci/hda/patch_conexant.c ++++ b/sound/pci/hda/patch_conexant.c +@@ -3591,6 +3591,14 @@ static const struct hda_codec_preset snd_hda_preset_conexant[] = { + .patch = patch_conexant_auto }, + { .id = 0x14f150b9, .name = "CX20665", + .patch = patch_conexant_auto }, ++ { .id = 0x14f150f1, .name = "CX20721", ++ .patch = patch_conexant_auto }, ++ { .id = 0x14f150f2, .name = "CX20722", ++ .patch = patch_conexant_auto }, ++ { .id = 0x14f150f3, .name = "CX20723", ++ .patch = patch_conexant_auto }, ++ { .id = 0x14f150f4, .name = "CX20724", ++ .patch = patch_conexant_auto }, + { .id = 0x14f1510f, .name = "CX20751/2", + .patch = patch_conexant_auto }, + { .id = 0x14f15110, .name = "CX20751/2", +@@ -3625,6 +3633,10 @@ MODULE_ALIAS("snd-hda-codec-id:14f150ab"); + MODULE_ALIAS("snd-hda-codec-id:14f150ac"); + MODULE_ALIAS("snd-hda-codec-id:14f150b8"); + MODULE_ALIAS("snd-hda-codec-id:14f150b9"); ++MODULE_ALIAS("snd-hda-codec-id:14f150f1"); ++MODULE_ALIAS("snd-hda-codec-id:14f150f2"); ++MODULE_ALIAS("snd-hda-codec-id:14f150f3"); ++MODULE_ALIAS("snd-hda-codec-id:14f150f4"); + MODULE_ALIAS("snd-hda-codec-id:14f1510f"); + MODULE_ALIAS("snd-hda-codec-id:14f15110"); + MODULE_ALIAS("snd-hda-codec-id:14f15111"); +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index ca26373ebe70..e2b567706297 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -4549,6 +4549,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), + SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), + SND_PCI_QUIRK(0x10cf, 0x15dc, "Lifebook T731", ALC269_FIXUP_LIFEBOOK_HP_PIN), ++ SND_PCI_QUIRK(0x10cf, 0x1757, "Lifebook E752", ALC269_FIXUP_LIFEBOOK_HP_PIN), + SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), + SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), +diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c +index 1eafc1a28193..8fe3b8c18ed4 100644 +--- a/sound/pci/hda/thinkpad_helper.c ++++ b/sound/pci/hda/thinkpad_helper.c +@@ -71,7 +71,6 @@ static void hda_fixup_thinkpad_acpi(struct hda_codec *codec, + if (led_set_func(TPACPI_LED_MUTE, false) >= 0) { + old_vmaster_hook = spec->vmaster_mute.hook; + spec->vmaster_mute.hook = update_tpacpi_mute_led; +- spec->vmaster_mute_enum = 1; + removefunc = false; + } + if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) { +diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c +index 582c2bbd42cb..b85229345969 100644 +--- a/sound/soc/codecs/mc13783.c ++++ b/sound/soc/codecs/mc13783.c +@@ -634,14 +634,14 @@ static int mc13783_probe(struct snd_soc_codec *codec) + AUDIO_SSI_SEL, 0); + else + mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_CODEC, +- 0, AUDIO_SSI_SEL); ++ AUDIO_SSI_SEL, AUDIO_SSI_SEL); + + if (priv->dac_ssi_port == MC13783_SSI1_PORT) + mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC, + AUDIO_SSI_SEL, 0); + else + mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC, +- 0, AUDIO_SSI_SEL); ++ AUDIO_SSI_SEL, AUDIO_SSI_SEL); + + return 0; + } +diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c +index 2a0bfb848512..edfd4edaa864 100644 +--- a/sound/soc/codecs/wm8960.c ++++ b/sound/soc/codecs/wm8960.c +@@ -392,7 +392,7 @@ static const struct snd_soc_dapm_route audio_paths[] = { + { "Right Input Mixer", "Boost Switch", "Right Boost Mixer", }, + { "Right Input Mixer", NULL, "RINPUT1", }, /* Really Boost Switch */ + { "Right Input Mixer", NULL, "RINPUT2" }, +- { "Right Input Mixer", NULL, "LINPUT3" }, ++ { "Right Input Mixer", NULL, "RINPUT3" }, + + { "Left ADC", NULL, "Left Input Mixer" }, + { "Right ADC", NULL, "Right Input Mixer" }, +diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c +index d98e52f647d2..66aec0c3b7bb 100644 +--- a/sound/soc/codecs/wm8994.c ++++ b/sound/soc/codecs/wm8994.c +@@ -2745,7 +2745,7 @@ static struct { + }; + + static int fs_ratios[] = { +- 64, 128, 192, 256, 348, 512, 768, 1024, 1408, 1536 ++ 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536 + }; + + static int bclk_divs[] = { +diff --git a/tools/vm/Makefile b/tools/vm/Makefile +index 3d907dacf2ac..c604f3ec628a 100644 +--- a/tools/vm/Makefile ++++ b/tools/vm/Makefile +@@ -3,7 +3,7 @@ + TARGETS=page-types slabinfo + + LIB_DIR = ../lib/api +-LIBS = $(LIB_DIR)/libapikfs.a ++LIBS = $(LIB_DIR)/libapi.a + + CC = $(CROSS_COMPILE)gcc + CFLAGS = -Wall -Wextra -I../lib/ diff --git a/patch/kernel/cubox-default/patch-3.14.44-45.patch b/patch/kernel/cubox-default/patch-3.14.44-45.patch new file mode 100644 index 000000000..4f7aa254e --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.44-45.patch @@ -0,0 +1,1273 @@ +diff --git a/Makefile b/Makefile +index 9f2471c6fbbe..c92186c3efd7 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 44 ++SUBLEVEL = 45 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c +index d1fea7a054be..7479d8d847a6 100644 +--- a/arch/mips/kernel/irq.c ++++ b/arch/mips/kernel/irq.c +@@ -110,7 +110,7 @@ void __init init_IRQ(void) + #endif + } + +-#ifdef DEBUG_STACKOVERFLOW ++#ifdef CONFIG_DEBUG_STACKOVERFLOW + static inline void check_stack_overflow(void) + { + unsigned long sp; +diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h +index 6f1c3a8a33ab..bcc9a2f46c62 100644 +--- a/arch/x86/include/asm/segment.h ++++ b/arch/x86/include/asm/segment.h +@@ -212,10 +212,21 @@ + #define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8) + + #ifdef __KERNEL__ ++ ++/* ++ * early_idt_handler_array is an array of entry points referenced in the ++ * early IDT. For simplicity, it's a real array with one entry point ++ * every nine bytes. That leaves room for an optional 'push $0' if the ++ * vector has no error code (two bytes), a 'push $vector_number' (two ++ * bytes), and a jump to the common entry code (up to five bytes). ++ */ ++#define EARLY_IDT_HANDLER_SIZE 9 ++ + #ifndef __ASSEMBLY__ +-extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][2+2+5]; ++ ++extern const char early_idt_handler_array[NUM_EXCEPTION_VECTORS][EARLY_IDT_HANDLER_SIZE]; + #ifdef CONFIG_TRACING +-#define trace_early_idt_handlers early_idt_handlers ++# define trace_early_idt_handler_array early_idt_handler_array + #endif + + /* +diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c +index 85126ccbdf6b..5fc4ac7c6582 100644 +--- a/arch/x86/kernel/head64.c ++++ b/arch/x86/kernel/head64.c +@@ -162,7 +162,7 @@ asmlinkage void __init x86_64_start_kernel(char * real_mode_data) + clear_bss(); + + for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) +- set_intr_gate(i, early_idt_handlers[i]); ++ set_intr_gate(i, early_idt_handler_array[i]); + load_idt((const struct desc_ptr *)&idt_descr); + + copy_bootdata(__va(real_mode_data)); +diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S +index f36bd42d6f0c..30a2aa3782fa 100644 +--- a/arch/x86/kernel/head_32.S ++++ b/arch/x86/kernel/head_32.S +@@ -477,21 +477,22 @@ is486: + __INIT + setup_once: + /* +- * Set up a idt with 256 entries pointing to ignore_int, +- * interrupt gates. It doesn't actually load idt - that needs +- * to be done on each CPU. Interrupts are enabled elsewhere, +- * when we can be relatively sure everything is ok. ++ * Set up a idt with 256 interrupt gates that push zero if there ++ * is no error code and then jump to early_idt_handler_common. ++ * It doesn't actually load the idt - that needs to be done on ++ * each CPU. Interrupts are enabled elsewhere, when we can be ++ * relatively sure everything is ok. + */ + + movl $idt_table,%edi +- movl $early_idt_handlers,%eax ++ movl $early_idt_handler_array,%eax + movl $NUM_EXCEPTION_VECTORS,%ecx + 1: + movl %eax,(%edi) + movl %eax,4(%edi) + /* interrupt gate, dpl=0, present */ + movl $(0x8E000000 + __KERNEL_CS),2(%edi) +- addl $9,%eax ++ addl $EARLY_IDT_HANDLER_SIZE,%eax + addl $8,%edi + loop 1b + +@@ -523,26 +524,28 @@ setup_once: + andl $0,setup_once_ref /* Once is enough, thanks */ + ret + +-ENTRY(early_idt_handlers) ++ENTRY(early_idt_handler_array) + # 36(%esp) %eflags + # 32(%esp) %cs + # 28(%esp) %eip + # 24(%rsp) error code + i = 0 + .rept NUM_EXCEPTION_VECTORS +- .if (EXCEPTION_ERRCODE_MASK >> i) & 1 +- ASM_NOP2 +- .else ++ .ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1 + pushl $0 # Dummy error code, to make stack frame uniform + .endif + pushl $i # 20(%esp) Vector number +- jmp early_idt_handler ++ jmp early_idt_handler_common + i = i + 1 ++ .fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc + .endr +-ENDPROC(early_idt_handlers) ++ENDPROC(early_idt_handler_array) + +- /* This is global to keep gas from relaxing the jumps */ +-ENTRY(early_idt_handler) ++early_idt_handler_common: ++ /* ++ * The stack is the hardware frame, an error code or zero, and the ++ * vector number. ++ */ + cld + + cmpl $2,(%esp) # X86_TRAP_NMI +@@ -602,7 +605,7 @@ ex_entry: + is_nmi: + addl $8,%esp /* drop vector number and error code */ + iret +-ENDPROC(early_idt_handler) ++ENDPROC(early_idt_handler_common) + + /* This is the default interrupt "handler" :-) */ + ALIGN +diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S +index a468c0a65c42..a2dc0add72ed 100644 +--- a/arch/x86/kernel/head_64.S ++++ b/arch/x86/kernel/head_64.S +@@ -321,26 +321,28 @@ bad_address: + jmp bad_address + + __INIT +- .globl early_idt_handlers +-early_idt_handlers: ++ENTRY(early_idt_handler_array) + # 104(%rsp) %rflags + # 96(%rsp) %cs + # 88(%rsp) %rip + # 80(%rsp) error code + i = 0 + .rept NUM_EXCEPTION_VECTORS +- .if (EXCEPTION_ERRCODE_MASK >> i) & 1 +- ASM_NOP2 +- .else ++ .ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1 + pushq $0 # Dummy error code, to make stack frame uniform + .endif + pushq $i # 72(%rsp) Vector number +- jmp early_idt_handler ++ jmp early_idt_handler_common + i = i + 1 ++ .fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc + .endr ++ENDPROC(early_idt_handler_array) + +-/* This is global to keep gas from relaxing the jumps */ +-ENTRY(early_idt_handler) ++early_idt_handler_common: ++ /* ++ * The stack is the hardware frame, an error code or zero, and the ++ * vector number. ++ */ + cld + + cmpl $2,(%rsp) # X86_TRAP_NMI +@@ -412,7 +414,7 @@ ENTRY(early_idt_handler) + is_nmi: + addq $16,%rsp # drop vector number and error code + INTERRUPT_RETURN +-ENDPROC(early_idt_handler) ++ENDPROC(early_idt_handler_common) + + __INITDATA + +diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c +index af2d4317b218..1fed139f8eae 100644 +--- a/arch/x86/net/bpf_jit_comp.c ++++ b/arch/x86/net/bpf_jit_comp.c +@@ -211,7 +211,12 @@ void bpf_jit_compile(struct sk_filter *fp) + } + cleanup_addr = proglen; /* epilogue address */ + +- for (pass = 0; pass < 10; pass++) { ++ /* JITed image shrinks with every pass and the loop iterates ++ * until the image stops shrinking. Very large bpf programs ++ * may converge on the last pass. In such case do one more ++ * pass to emit the final image ++ */ ++ for (pass = 0; pass < 10 || image; pass++) { + u8 seen_or_pass0 = (pass == 0) ? (SEEN_XREG | SEEN_DATAREF | SEEN_MEM) : seen; + /* no prologue/epilogue for trivial filters (RET something) */ + proglen = 0; +diff --git a/block/genhd.c b/block/genhd.c +index a8d586a729bb..9316f5fd416f 100644 +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -422,9 +422,9 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt) + /* allocate ext devt */ + idr_preload(GFP_KERNEL); + +- spin_lock(&ext_devt_lock); ++ spin_lock_bh(&ext_devt_lock); + idx = idr_alloc(&ext_devt_idr, part, 0, NR_EXT_DEVT, GFP_NOWAIT); +- spin_unlock(&ext_devt_lock); ++ spin_unlock_bh(&ext_devt_lock); + + idr_preload_end(); + if (idx < 0) +@@ -449,9 +449,9 @@ void blk_free_devt(dev_t devt) + return; + + if (MAJOR(devt) == BLOCK_EXT_MAJOR) { +- spin_lock(&ext_devt_lock); ++ spin_lock_bh(&ext_devt_lock); + idr_remove(&ext_devt_idr, blk_mangle_minor(MINOR(devt))); +- spin_unlock(&ext_devt_lock); ++ spin_unlock_bh(&ext_devt_lock); + } + } + +@@ -691,13 +691,13 @@ struct gendisk *get_gendisk(dev_t devt, int *partno) + } else { + struct hd_struct *part; + +- spin_lock(&ext_devt_lock); ++ spin_lock_bh(&ext_devt_lock); + part = idr_find(&ext_devt_idr, blk_mangle_minor(MINOR(devt))); + if (part && get_disk(part_to_disk(part))) { + *partno = part->partno; + disk = part_to_disk(part); + } +- spin_unlock(&ext_devt_lock); ++ spin_unlock_bh(&ext_devt_lock); + } + + return disk; +diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c +index 83c4ddb1bc7f..08223cc980b0 100644 +--- a/drivers/ata/pata_octeon_cf.c ++++ b/drivers/ata/pata_octeon_cf.c +@@ -1069,7 +1069,7 @@ static struct of_device_id octeon_cf_match[] = { + }, + {}, + }; +-MODULE_DEVICE_TABLE(of, octeon_i2c_match); ++MODULE_DEVICE_TABLE(of, octeon_cf_match); + + static struct platform_driver octeon_cf_driver = { + .probe = octeon_cf_probe, +diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c +index b2d0887b3d12..462307c36d65 100644 +--- a/drivers/gpu/drm/i915/intel_dp.c ++++ b/drivers/gpu/drm/i915/intel_dp.c +@@ -481,10 +481,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, + DP_AUX_CH_CTL_RECEIVE_ERROR)) + continue; + if (status & DP_AUX_CH_CTL_DONE) +- break; ++ goto done; + } +- if (status & DP_AUX_CH_CTL_DONE) +- break; + } + + if ((status & DP_AUX_CH_CTL_DONE) == 0) { +@@ -493,6 +491,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, + goto out; + } + ++done: + /* Check for timeout or receive error. + * Timeouts occur when the sink is not connected + */ +diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c +index 1d02970ed395..81f8ec85a48a 100644 +--- a/drivers/gpu/drm/i915/intel_i2c.c ++++ b/drivers/gpu/drm/i915/intel_i2c.c +@@ -489,7 +489,7 @@ gmbus_xfer(struct i2c_adapter *adapter, + struct intel_gmbus, + adapter); + struct drm_i915_private *dev_priv = bus->dev_priv; +- int i, reg_offset; ++ int i = 0, inc, try = 0, reg_offset; + int ret = 0; + + intel_aux_display_runtime_get(dev_priv); +@@ -502,12 +502,14 @@ gmbus_xfer(struct i2c_adapter *adapter, + + reg_offset = dev_priv->gpio_mmio_base; + ++retry: + I915_WRITE(GMBUS0 + reg_offset, bus->reg0); + +- for (i = 0; i < num; i++) { ++ for (; i < num; i += inc) { ++ inc = 1; + if (gmbus_is_index_read(msgs, i, num)) { + ret = gmbus_xfer_index_read(dev_priv, &msgs[i]); +- i += 1; /* set i to the index of the read xfer */ ++ inc = 2; /* an index read is two msgs */ + } else if (msgs[i].flags & I2C_M_RD) { + ret = gmbus_xfer_read(dev_priv, &msgs[i], 0); + } else { +@@ -579,6 +581,18 @@ clear_err: + adapter->name, msgs[i].addr, + (msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len); + ++ /* ++ * Passive adapters sometimes NAK the first probe. Retry the first ++ * message once on -ENXIO for GMBUS transfers; the bit banging algorithm ++ * has retries internally. See also the retry loop in ++ * drm_do_probe_ddc_edid, which bails out on the first -ENXIO. ++ */ ++ if (ret == -ENXIO && i == 0 && try++ == 0) { ++ DRM_DEBUG_KMS("GMBUS [%s] NAK on first message, retry\n", ++ adapter->name); ++ goto retry; ++ } ++ + goto out; + + timeout: +diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c +index e39026cc7d07..129915eca07b 100644 +--- a/drivers/gpu/drm/radeon/radeon_device.c ++++ b/drivers/gpu/drm/radeon/radeon_device.c +@@ -1337,6 +1337,21 @@ int radeon_device_init(struct radeon_device *rdev, + goto failed; + } + ++ /* ++ * Turks/Thames GPU will freeze whole laptop if DPM is not restarted ++ * after the CP ring have chew one packet at least. Hence here we stop ++ * and restart DPM after the radeon_ib_ring_tests(). ++ */ ++ if (rdev->pm.dpm_enabled && ++ (rdev->pm.pm_method == PM_METHOD_DPM) && ++ (rdev->family == CHIP_TURKS) && ++ (rdev->flags & RADEON_IS_MOBILITY)) { ++ mutex_lock(&rdev->pm.mutex); ++ radeon_dpm_disable(rdev); ++ radeon_dpm_enable(rdev); ++ mutex_unlock(&rdev->pm.mutex); ++ } ++ + if ((radeon_testing & 1)) { + if (rdev->accel_working) + radeon_test_moves(rdev); +diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c +index 53a24ebb92c3..779dac5676d9 100644 +--- a/drivers/iio/adc/twl6030-gpadc.c ++++ b/drivers/iio/adc/twl6030-gpadc.c +@@ -1003,7 +1003,7 @@ static struct platform_driver twl6030_gpadc_driver = { + + module_platform_driver(twl6030_gpadc_driver); + +-MODULE_ALIAS("platform: " DRIVER_NAME); ++MODULE_ALIAS("platform:" DRIVER_NAME); + MODULE_AUTHOR("Balaji T K "); + MODULE_AUTHOR("Graeme Gregory "); + MODULE_AUTHOR("Oleksandr Kozaruk variant->temp_scale_nano / 1000000; + *val2 = (st->variant->temp_scale_nano % 1000000); + return IIO_VAL_INT_PLUS_MICRO; ++ case IIO_PRESSURE: ++ /* 20 uBar = 0.002kPascal */ ++ *val = 0; ++ *val2 = 2000; ++ return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +@@ -480,10 +485,10 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, + } + } + +-#define ADIS16400_VOLTAGE_CHAN(addr, bits, name, si) { \ ++#define ADIS16400_VOLTAGE_CHAN(addr, bits, name, si, chn) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ +- .channel = 0, \ ++ .channel = chn, \ + .extend_name = name, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ +@@ -499,10 +504,10 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, + } + + #define ADIS16400_SUPPLY_CHAN(addr, bits) \ +- ADIS16400_VOLTAGE_CHAN(addr, bits, "supply", ADIS16400_SCAN_SUPPLY) ++ ADIS16400_VOLTAGE_CHAN(addr, bits, "supply", ADIS16400_SCAN_SUPPLY, 0) + + #define ADIS16400_AUX_ADC_CHAN(addr, bits) \ +- ADIS16400_VOLTAGE_CHAN(addr, bits, NULL, ADIS16400_SCAN_ADC) ++ ADIS16400_VOLTAGE_CHAN(addr, bits, NULL, ADIS16400_SCAN_ADC, 1) + + #define ADIS16400_GYRO_CHAN(mod, addr, bits) { \ + .type = IIO_ANGL_VEL, \ +@@ -819,11 +824,6 @@ static const struct iio_info adis16400_info = { + .debugfs_reg_access = adis_debugfs_reg_access, + }; + +-static const unsigned long adis16400_burst_scan_mask[] = { +- ~0UL, +- 0, +-}; +- + static const char * const adis16400_status_error_msgs[] = { + [ADIS16400_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure", + [ADIS16400_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure", +@@ -871,6 +871,20 @@ static const struct adis_data adis16400_data = { + BIT(ADIS16400_DIAG_STAT_POWER_LOW), + }; + ++static void adis16400_setup_chan_mask(struct adis16400_state *st) ++{ ++ const struct adis16400_chip_info *chip_info = st->variant; ++ unsigned i; ++ ++ for (i = 0; i < chip_info->num_channels; i++) { ++ const struct iio_chan_spec *ch = &chip_info->channels[i]; ++ ++ if (ch->scan_index >= 0 && ++ ch->scan_index != ADIS16400_SCAN_TIMESTAMP) ++ st->avail_scan_mask[0] |= BIT(ch->scan_index); ++ } ++} ++ + static int adis16400_probe(struct spi_device *spi) + { + struct adis16400_state *st; +@@ -894,8 +908,10 @@ static int adis16400_probe(struct spi_device *spi) + indio_dev->info = &adis16400_info; + indio_dev->modes = INDIO_DIRECT_MODE; + +- if (!(st->variant->flags & ADIS16400_NO_BURST)) +- indio_dev->available_scan_masks = adis16400_burst_scan_mask; ++ if (!(st->variant->flags & ADIS16400_NO_BURST)) { ++ adis16400_setup_chan_mask(st); ++ indio_dev->available_scan_masks = st->avail_scan_mask; ++ } + + ret = adis_init(&st->adis, indio_dev, spi, &adis16400_data); + if (ret) +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index e824651a5a11..94eaaf0c49b3 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -1271,10 +1271,11 @@ static bool elantech_is_signature_valid(const unsigned char *param) + return true; + + /* +- * Some models have a revision higher then 20. Meaning param[2] may +- * be 10 or 20, skip the rates check for these. ++ * Some hw_version >= 4 models have a revision higher then 20. Meaning ++ * that param[2] may be 10 or 20, skip the rates check for these. + */ +- if (param[0] == 0x46 && (param[1] & 0xef) == 0x0f && param[2] < 40) ++ if ((param[0] & 0x0f) >= 0x06 && (param[1] & 0xaf) == 0x0f && ++ param[2] < 40) + return true; + + for (i = 0; i < ARRAY_SIZE(rates); i++) +diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c +index b00e282ef166..53f09a8b0b72 100644 +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -138,6 +138,10 @@ static const struct min_max_quirk min_max_pnpid_table[] = { + 1024, 5112, 2024, 4832 + }, + { ++ (const char * const []){"LEN2000", NULL}, ++ 1024, 5113, 2021, 4832 ++ }, ++ { + (const char * const []){"LEN2001", NULL}, + 1024, 5022, 2508, 4832 + }, +@@ -173,7 +177,7 @@ static const char * const topbuttonpad_pnp_ids[] = { + "LEN0047", + "LEN0048", + "LEN0049", +- "LEN2000", ++ "LEN2000", /* S540 */ + "LEN2001", /* Edge E431 */ + "LEN2002", /* Edge E531 */ + "LEN2003", +diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c +index 98e7cbf720a5..0be3f9d94322 100644 +--- a/drivers/net/phy/dp83640.c ++++ b/drivers/net/phy/dp83640.c +@@ -45,7 +45,7 @@ + #define PSF_TX 0x1000 + #define EXT_EVENT 1 + #define CAL_EVENT 7 +-#define CAL_TRIGGER 7 ++#define CAL_TRIGGER 1 + #define PER_TRIGGER 6 + + #define MII_DP83640_MICR 0x11 +@@ -442,7 +442,9 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp, + else + evnt |= EVNT_RISE; + } ++ mutex_lock(&clock->extreg_lock); + ext_write(0, phydev, PAGE5, PTP_EVNT, evnt); ++ mutex_unlock(&clock->extreg_lock); + return 0; + + case PTP_CLK_REQ_PEROUT: +@@ -463,6 +465,8 @@ static u8 status_frame_src[6] = { 0x08, 0x00, 0x17, 0x0B, 0x6B, 0x0F }; + + static void enable_status_frames(struct phy_device *phydev, bool on) + { ++ struct dp83640_private *dp83640 = phydev->priv; ++ struct dp83640_clock *clock = dp83640->clock; + u16 cfg0 = 0, ver; + + if (on) +@@ -470,9 +474,13 @@ static void enable_status_frames(struct phy_device *phydev, bool on) + + ver = (PSF_PTPVER & VERSIONPTP_MASK) << VERSIONPTP_SHIFT; + ++ mutex_lock(&clock->extreg_lock); ++ + ext_write(0, phydev, PAGE5, PSF_CFG0, cfg0); + ext_write(0, phydev, PAGE6, PSF_CFG1, ver); + ++ mutex_unlock(&clock->extreg_lock); ++ + if (!phydev->attached_dev) { + pr_warn("expected to find an attached netdevice\n"); + return; +@@ -1063,11 +1071,18 @@ static int dp83640_config_init(struct phy_device *phydev) + + if (clock->chosen && !list_empty(&clock->phylist)) + recalibrate(clock); +- else ++ else { ++ mutex_lock(&clock->extreg_lock); + enable_broadcast(phydev, clock->page, 1); ++ mutex_unlock(&clock->extreg_lock); ++ } + + enable_status_frames(phydev, true); ++ ++ mutex_lock(&clock->extreg_lock); + ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE); ++ mutex_unlock(&clock->extreg_lock); ++ + return 0; + } + +diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c +index 1d568788c3e3..65cfc5a436c7 100644 +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -965,12 +965,14 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable) + { + /* According to 802.3az,the EEE is supported only in full duplex-mode. + * Also EEE feature is active when core is operating with MII, GMII +- * or RGMII. ++ * or RGMII (all kinds). Internal PHYs are also allowed to proceed and ++ * should return an error if they do not support EEE. + */ + if ((phydev->duplex == DUPLEX_FULL) && + ((phydev->interface == PHY_INTERFACE_MODE_MII) || + (phydev->interface == PHY_INTERFACE_MODE_GMII) || +- (phydev->interface == PHY_INTERFACE_MODE_RGMII))) { ++ (phydev->interface >= PHY_INTERFACE_MODE_RGMII && ++ phydev->interface <= PHY_INTERFACE_MODE_RGMII_TXID))) { + int eee_lp, eee_cap, eee_adv; + u32 lp, cap, adv; + int status; +diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c +index 7a206cffb062..d18e65398edc 100644 +--- a/drivers/net/xen-netback/xenbus.c ++++ b/drivers/net/xen-netback/xenbus.c +@@ -32,6 +32,8 @@ struct backend_info { + enum xenbus_state frontend_state; + struct xenbus_watch hotplug_status_watch; + u8 have_hotplug_status_watch:1; ++ ++ const char *hotplug_script; + }; + + static int connect_rings(struct backend_info *); +@@ -54,6 +56,7 @@ static int netback_remove(struct xenbus_device *dev) + xenvif_free(be->vif); + be->vif = NULL; + } ++ kfree(be->hotplug_script); + kfree(be); + dev_set_drvdata(&dev->dev, NULL); + return 0; +@@ -71,6 +74,7 @@ static int netback_probe(struct xenbus_device *dev, + struct xenbus_transaction xbt; + int err; + int sg; ++ const char *script; + struct backend_info *be = kzalloc(sizeof(struct backend_info), + GFP_KERNEL); + if (!be) { +@@ -157,6 +161,15 @@ static int netback_probe(struct xenbus_device *dev, + if (err) + pr_debug("Error writing feature-split-event-channels\n"); + ++ script = xenbus_read(XBT_NIL, dev->nodename, "script", NULL); ++ if (IS_ERR(script)) { ++ err = PTR_ERR(script); ++ xenbus_dev_fatal(dev, err, "reading script"); ++ goto fail; ++ } ++ ++ be->hotplug_script = script; ++ + err = xenbus_switch_state(dev, XenbusStateInitWait); + if (err) + goto fail; +@@ -187,22 +200,14 @@ static int netback_uevent(struct xenbus_device *xdev, + struct kobj_uevent_env *env) + { + struct backend_info *be = dev_get_drvdata(&xdev->dev); +- char *val; + +- val = xenbus_read(XBT_NIL, xdev->nodename, "script", NULL); +- if (IS_ERR(val)) { +- int err = PTR_ERR(val); +- xenbus_dev_fatal(xdev, err, "reading script"); +- return err; +- } else { +- if (add_uevent_var(env, "script=%s", val)) { +- kfree(val); +- return -ENOMEM; +- } +- kfree(val); +- } ++ if (!be) ++ return 0; ++ ++ if (add_uevent_var(env, "script=%s", be->hotplug_script)) ++ return -ENOMEM; + +- if (!be || !be->vif) ++ if (!be->vif) + return 0; + + return add_uevent_var(env, "vif=%s", be->vif->dev->name); +diff --git a/drivers/staging/ozwpan/ozusbsvc1.c b/drivers/staging/ozwpan/ozusbsvc1.c +index 617f51cdaea7..b58e87e951e7 100644 +--- a/drivers/staging/ozwpan/ozusbsvc1.c ++++ b/drivers/staging/ozwpan/ozusbsvc1.c +@@ -323,7 +323,11 @@ static void oz_usb_handle_ep_data(struct oz_usb_ctx *usb_ctx, + struct oz_multiple_fixed *body = + (struct oz_multiple_fixed *)data_hdr; + u8 *data = body->data; +- int n = (len - sizeof(struct oz_multiple_fixed)+1) ++ unsigned int n; ++ if (!body->unit_size || ++ len < sizeof(struct oz_multiple_fixed) - 1) ++ break; ++ n = (len - (sizeof(struct oz_multiple_fixed) - 1)) + / body->unit_size; + while (n--) { + oz_hcd_data_ind(usb_ctx->hport, body->endpoint, +@@ -386,10 +390,15 @@ void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt) + case OZ_GET_DESC_RSP: { + struct oz_get_desc_rsp *body = + (struct oz_get_desc_rsp *)usb_hdr; +- int data_len = elt->length - +- sizeof(struct oz_get_desc_rsp) + 1; +- u16 offs = le16_to_cpu(get_unaligned(&body->offset)); +- u16 total_size = ++ u16 offs, total_size; ++ u8 data_len; ++ ++ if (elt->length < sizeof(struct oz_get_desc_rsp) - 1) ++ break; ++ data_len = elt->length - ++ (sizeof(struct oz_get_desc_rsp) - 1); ++ offs = le16_to_cpu(get_unaligned(&body->offset)); ++ total_size = + le16_to_cpu(get_unaligned(&body->total_size)); + oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - cnf\n"); + oz_hcd_get_desc_cnf(usb_ctx->hport, body->req_id, +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index 8ab46ad40f28..81951904186c 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -186,6 +186,17 @@ static int receive_room(struct tty_struct *tty) + return left; + } + ++static inline int tty_copy_to_user(struct tty_struct *tty, ++ void __user *to, ++ const void *from, ++ unsigned long n) ++{ ++ struct n_tty_data *ldata = tty->disc_data; ++ ++ tty_audit_add_data(tty, to, n, ldata->icanon); ++ return copy_to_user(to, from, n); ++} ++ + /** + * n_tty_set_room - receive space + * @tty: terminal +@@ -2084,12 +2095,12 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, + __func__, eol, found, n, c, size, more); + + if (n > size) { +- ret = copy_to_user(*b, read_buf_addr(ldata, tail), size); ++ ret = tty_copy_to_user(tty, *b, read_buf_addr(ldata, tail), size); + if (ret) + return -EFAULT; +- ret = copy_to_user(*b + size, ldata->read_buf, n - size); ++ ret = tty_copy_to_user(tty, *b + size, ldata->read_buf, n - size); + } else +- ret = copy_to_user(*b, read_buf_addr(ldata, tail), n); ++ ret = tty_copy_to_user(tty, *b, read_buf_addr(ldata, tail), n); + + if (ret) + return -EFAULT; +diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c +index d799140e53b6..1fd9bc695ab7 100644 +--- a/drivers/tty/serial/imx.c ++++ b/drivers/tty/serial/imx.c +@@ -907,6 +907,14 @@ static void dma_rx_callback(void *data) + + status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state); + count = RX_BUF_SIZE - state.residue; ++ ++ if (readl(sport->port.membase + USR2) & USR2_IDLE) { ++ /* In condition [3] the SDMA counted up too early */ ++ count--; ++ ++ writel(USR2_IDLE, sport->port.membase + USR2); ++ } ++ + dev_dbg(sport->port.dev, "We get %d bytes.\n", count); + + if (count) { +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 02de4cf48a5b..73c7292f48e5 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -128,6 +128,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */ + { USB_DEVICE(0x10C4, 0x8977) }, /* CEL MeshWorks DevKit Device */ + { USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */ ++ { USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */ + { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index 2d858f81ab33..bc77ea7cde48 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -712,6 +712,7 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(XSENS_VID, XSENS_AWINDA_DONGLE_PID) }, + { USB_DEVICE(XSENS_VID, XSENS_AWINDA_STATION_PID) }, + { USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) }, ++ { USB_DEVICE(XSENS_VID, XSENS_MTDEVBOARD_PID) }, + { USB_DEVICE(XSENS_VID, XSENS_MTW_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) }, + { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index 4e4f46f3c89c..792e054126de 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -155,6 +155,7 @@ + #define XSENS_AWINDA_STATION_PID 0x0101 + #define XSENS_AWINDA_DONGLE_PID 0x0102 + #define XSENS_MTW_PID 0x0200 /* Xsens MTw */ ++#define XSENS_MTDEVBOARD_PID 0x0300 /* Motion Tracker Development Board */ + #define XSENS_CONVERTER_PID 0xD00D /* Xsens USB-serial converter */ + + /* Xsens devices using FTDI VID */ +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index fa9f90049099..8adfc65b37dd 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -4289,8 +4289,11 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + } + ret = fiemap_fill_next_extent(fieinfo, em_start, disko, + em_len, flags); +- if (ret) ++ if (ret) { ++ if (ret == 1) ++ ret = 0; + goto out_free; ++ } + } + out_free: + free_extent_map(em); +diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c +index d04db817be5c..92cbfbf2599e 100644 +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -906,6 +906,15 @@ find_root: + if (IS_ERR(new_root)) + return ERR_CAST(new_root); + ++ if (!(sb->s_flags & MS_RDONLY)) { ++ int ret; ++ down_read(&fs_info->cleanup_work_sem); ++ ret = btrfs_orphan_cleanup(new_root); ++ up_read(&fs_info->cleanup_work_sem); ++ if (ret) ++ return ERR_PTR(ret); ++ } ++ + dir_id = btrfs_root_dirid(&new_root->root_item); + setup_root: + location.objectid = dir_id; +diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c +index a5457d577b98..6ad2e2d320fe 100644 +--- a/kernel/trace/ring_buffer_benchmark.c ++++ b/kernel/trace/ring_buffer_benchmark.c +@@ -455,7 +455,7 @@ static int __init ring_buffer_benchmark_init(void) + + if (producer_fifo >= 0) { + struct sched_param param = { +- .sched_priority = consumer_fifo ++ .sched_priority = producer_fifo + }; + sched_setscheduler(producer, SCHED_FIFO, ¶m); + } else +diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c +index c8e450132813..5bba3b35bec8 100644 +--- a/mm/memory_hotplug.c ++++ b/mm/memory_hotplug.c +@@ -1864,8 +1864,10 @@ void try_offline_node(int nid) + * wait_table may be allocated from boot memory, + * here only free if it's allocated by vmalloc. + */ +- if (is_vmalloc_addr(zone->wait_table)) ++ if (is_vmalloc_addr(zone->wait_table)) { + vfree(zone->wait_table); ++ zone->wait_table = NULL; ++ } + } + } + EXPORT_SYMBOL(try_offline_node); +diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c +index 9203d5a1943f..09152d11eb29 100644 +--- a/net/bridge/br_fdb.c ++++ b/net/bridge/br_fdb.c +@@ -705,9 +705,11 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge_port *p, + int err = 0; + + if (ndm->ndm_flags & NTF_USE) { ++ local_bh_disable(); + rcu_read_lock(); + br_fdb_update(p->br, p, addr, vid, true); + rcu_read_unlock(); ++ local_bh_enable(); + } else { + spin_lock_bh(&p->br->hash_lock); + err = fdb_add_entry(p, addr, ndm->ndm_state, +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index 93067ecdb9a2..11a2e6c8538f 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -1056,7 +1056,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, + + err = br_ip6_multicast_add_group(br, port, &grec->grec_mca, + vid); +- if (!err) ++ if (err) + break; + } + +diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c +index 526bf56f4d31..afeb8e07ee41 100644 +--- a/net/caif/caif_socket.c ++++ b/net/caif/caif_socket.c +@@ -332,6 +332,10 @@ static long caif_stream_data_wait(struct sock *sk, long timeo) + release_sock(sk); + timeo = schedule_timeout(timeo); + lock_sock(sk); ++ ++ if (sock_flag(sk, SOCK_DEAD)) ++ break; ++ + clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); + } + +@@ -376,6 +380,10 @@ static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock, + struct sk_buff *skb; + + lock_sock(sk); ++ if (sock_flag(sk, SOCK_DEAD)) { ++ err = -ECONNRESET; ++ goto unlock; ++ } + skb = skb_dequeue(&sk->sk_receive_queue); + caif_check_flow_release(sk); + +diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c +index 074bb2a5e675..0a08902c539e 100644 +--- a/net/ceph/crush/mapper.c ++++ b/net/ceph/crush/mapper.c +@@ -290,6 +290,7 @@ static int is_out(const struct crush_map *map, + * @type: the type of item to choose + * @out: pointer to output vector + * @outpos: our position in that vector ++ * @out_size: size of the out vector + * @tries: number of attempts to make + * @recurse_tries: number of attempts to have recursive chooseleaf make + * @local_retries: localized retries +@@ -302,6 +303,7 @@ static int crush_choose_firstn(const struct crush_map *map, + const __u32 *weight, int weight_max, + int x, int numrep, int type, + int *out, int outpos, ++ int out_size, + unsigned int tries, + unsigned int recurse_tries, + unsigned int local_retries, +@@ -318,11 +320,12 @@ static int crush_choose_firstn(const struct crush_map *map, + int item = 0; + int itemtype; + int collide, reject; ++ int count = out_size; + + dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d\n", recurse_to_leaf ? "_LEAF" : "", + bucket->id, x, outpos, numrep); + +- for (rep = outpos; rep < numrep; rep++) { ++ for (rep = outpos; rep < numrep && count > 0 ; rep++) { + /* keep trying until we get a non-out, non-colliding item */ + ftotal = 0; + skip_rep = 0; +@@ -391,7 +394,7 @@ static int crush_choose_firstn(const struct crush_map *map, + map->buckets[-1-item], + weight, weight_max, + x, outpos+1, 0, +- out2, outpos, ++ out2, outpos, count, + recurse_tries, 0, + local_retries, + local_fallback_retries, +@@ -449,6 +452,7 @@ reject: + dprintk("CHOOSE got %d\n", item); + out[outpos] = item; + outpos++; ++ count--; + } + + dprintk("CHOOSE returns %d\n", outpos); +@@ -640,6 +644,7 @@ int crush_do_rule(const struct crush_map *map, + __u32 step; + int i, j; + int numrep; ++ int out_size; + /* + * the original choose_total_tries value was off by one (it + * counted "retries" and not "tries"). add one. +@@ -740,6 +745,7 @@ int crush_do_rule(const struct crush_map *map, + x, numrep, + curstep->arg2, + o+osize, j, ++ result_max-osize, + choose_tries, + recurse_tries, + choose_local_retries, +@@ -747,11 +753,13 @@ int crush_do_rule(const struct crush_map *map, + recurse_to_leaf, + c+osize); + } else { ++ out_size = ((numrep < (result_max-osize)) ? ++ numrep : (result_max-osize)); + crush_choose_indep( + map, + map->buckets[-1-w[i]], + weight, weight_max, +- x, numrep, numrep, ++ x, out_size, numrep, + curstep->arg2, + o+osize, j, + choose_tries, +@@ -760,7 +768,7 @@ int crush_do_rule(const struct crush_map *map, + recurse_to_leaf, + c+osize, + 0); +- osize += numrep; ++ osize += out_size; + } + } + +diff --git a/net/core/dev.c b/net/core/dev.c +index 73abbd77d72c..1b9e700c85b6 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4903,7 +4903,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, + if (__netdev_find_adj(upper_dev, dev, &upper_dev->all_adj_list.upper)) + return -EBUSY; + +- if (__netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper)) ++ if (__netdev_find_adj(dev, upper_dev, &dev->adj_list.upper)) + return -EEXIST; + + if (master && netdev_master_upper_dev_get(dev)) +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index b64330f25fbe..625615cdac86 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -910,6 +910,10 @@ static int ip_error(struct sk_buff *skb) + bool send; + int code; + ++ /* IP on this device is disabled. */ ++ if (!in_dev) ++ goto out; ++ + net = dev_net(rt->dst.dev); + if (!IN_DEV_FORWARD(in_dev)) { + switch (rt->dst.error) { +diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c +index 7a436c517e44..9128d0aa4643 100644 +--- a/net/ipv4/tcp_minisocks.c ++++ b/net/ipv4/tcp_minisocks.c +@@ -297,7 +297,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) + tw->tw_v6_daddr = sk->sk_v6_daddr; + tw->tw_v6_rcv_saddr = sk->sk_v6_rcv_saddr; + tw->tw_tclass = np->tclass; +- tw->tw_flowlabel = np->flow_label >> 12; ++ tw->tw_flowlabel = be32_to_cpu(np->flow_label & IPV6_FLOWLABEL_MASK); + tw->tw_ipv6only = np->ipv6only; + } + #endif +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index b25e852625d8..21a3a9e90b10 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -90,6 +90,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1317,10 +1318,8 @@ csum_copy_err: + } + unlock_sock_fast(sk, slow); + +- if (noblock) +- return -EAGAIN; +- +- /* starting over for a new packet */ ++ /* starting over for a new packet, but check if we need to yield */ ++ cond_resched(); + msg->msg_flags &= ~MSG_TRUNC; + goto try_again; + } +@@ -1924,6 +1923,7 @@ void udp_v4_early_demux(struct sk_buff *skb) + struct sock *sk; + struct dst_entry *dst; + int dif = skb->dev->ifindex; ++ int ours; + + /* validate the packet */ + if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr))) +@@ -1933,14 +1933,24 @@ void udp_v4_early_demux(struct sk_buff *skb) + uh = udp_hdr(skb); + + if (skb->pkt_type == PACKET_BROADCAST || +- skb->pkt_type == PACKET_MULTICAST) ++ skb->pkt_type == PACKET_MULTICAST) { ++ struct in_device *in_dev = __in_dev_get_rcu(skb->dev); ++ ++ if (!in_dev) ++ return; ++ ++ ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr, ++ iph->protocol); ++ if (!ours) ++ return; + sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr, + uh->source, iph->saddr, dif); +- else if (skb->pkt_type == PACKET_HOST) ++ } else if (skb->pkt_type == PACKET_HOST) { + sk = __udp4_lib_demux_lookup(net, uh->dest, iph->daddr, + uh->source, iph->saddr, dif); +- else ++ } else { + return; ++ } + + if (!sk) + return; +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 9d4332dba8ea..b50ae296537d 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -905,7 +905,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) + tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, + tcp_time_stamp + tcptw->tw_ts_offset, + tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw), +- tw->tw_tclass, (tw->tw_flowlabel << 12)); ++ tw->tw_tclass, cpu_to_be32(tw->tw_flowlabel)); + + inet_twsk_put(tw); + } +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 20b63d2ab70f..38625a91ec94 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -515,10 +515,8 @@ csum_copy_err: + } + unlock_sock_fast(sk, slow); + +- if (noblock) +- return -EAGAIN; +- +- /* starting over for a new packet */ ++ /* starting over for a new packet, but check if we need to yield */ ++ cond_resched(); + msg->msg_flags &= ~MSG_TRUNC; + goto try_again; + } +diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c +index 98532cfa7823..bdaed3130029 100644 +--- a/net/sched/sch_api.c ++++ b/net/sched/sch_api.c +@@ -812,10 +812,8 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, + if (dev->flags & IFF_UP) + dev_deactivate(dev); + +- if (new && new->ops->attach) { +- new->ops->attach(new); +- num_q = 0; +- } ++ if (new && new->ops->attach) ++ goto skip; + + for (i = 0; i < num_q; i++) { + struct netdev_queue *dev_queue = dev_ingress_queue(dev); +@@ -831,12 +829,16 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, + qdisc_destroy(old); + } + ++skip: + if (!ingress) { + notify_and_destroy(net, skb, n, classid, + dev->qdisc, new); + if (new && !new->ops->attach) + atomic_inc(&new->refcnt); + dev->qdisc = new ? : &noop_qdisc; ++ ++ if (new && new->ops->attach) ++ new->ops->attach(new); + } else { + notify_and_destroy(net, skb, n, classid, old, new); + } +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 94404f19f9de..4757f1cf6237 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1893,6 +1893,10 @@ static long unix_stream_data_wait(struct sock *sk, long timeo, + unix_state_unlock(sk); + timeo = freezable_schedule_timeout(timeo); + unix_state_lock(sk); ++ ++ if (sock_flag(sk, SOCK_DEAD)) ++ break; ++ + clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); + } + +@@ -1957,6 +1961,10 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, + struct sk_buff *skb, *last; + + unix_state_lock(sk); ++ if (sock_flag(sk, SOCK_DEAD)) { ++ err = -ECONNRESET; ++ goto unlock; ++ } + last = skb = skb_peek(&sk->sk_receive_queue); + again: + if (skb == NULL) { +diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c +index 5661a54ac7ee..ae1fe6fd4ab6 100644 +--- a/net/wireless/wext-compat.c ++++ b/net/wireless/wext-compat.c +@@ -1331,6 +1331,8 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) + memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN); + wdev_unlock(wdev); + ++ memset(&sinfo, 0, sizeof(sinfo)); ++ + if (rdev_get_station(rdev, dev, bssid, &sinfo)) + return NULL; + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index e2b567706297..ba175226da78 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -2226,6 +2226,7 @@ static const struct hda_fixup alc882_fixups[] = { + static const struct snd_pci_quirk alc882_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD), + SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD), ++ SND_PCI_QUIRK(0x1025, 0x0107, "Acer Aspire", ALC883_FIXUP_ACER_EAPD), + SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_FIXUP_ACER_EAPD), + SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_FIXUP_ACER_EAPD), + SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_FIXUP_ACER_EAPD), +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index 2d37b3fc3a21..c60103306b18 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -891,6 +891,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, + case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ + case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */ + case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */ ++ case USB_ID(0x046d, 0x08ca): /* Logitech Quickcam Fusion */ + case USB_ID(0x046d, 0x0991): + /* Most audio usb devices lie about volume resolution. + * Most Logitech webcams have res = 384. +diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c +index 621bc9ebb55e..b16be3944213 100644 +--- a/sound/usb/mixer_maps.c ++++ b/sound/usb/mixer_maps.c +@@ -428,6 +428,11 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { + .map = ebox44_map, + }, + { ++ /* MAYA44 USB+ */ ++ .id = USB_ID(0x2573, 0x0008), ++ .map = maya44_map, ++ }, ++ { + /* KEF X300A */ + .id = USB_ID(0x27ac, 0x1000), + .map = scms_usb3318_map, diff --git a/patch/kernel/cubox-default/patch-3.14.45-46.patch b/patch/kernel/cubox-default/patch-3.14.45-46.patch new file mode 100644 index 000000000..11a3c895d --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.45-46.patch @@ -0,0 +1,829 @@ +diff --git a/Makefile b/Makefile +index c92186c3efd7..def39fdd9df4 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 45 ++SUBLEVEL = 46 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h +index 09af14999c9b..530f56e19931 100644 +--- a/arch/arm/include/asm/kvm_host.h ++++ b/arch/arm/include/asm/kvm_host.h +@@ -42,7 +42,7 @@ + + struct kvm_vcpu; + u32 *kvm_vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num, u32 mode); +-int kvm_target_cpu(void); ++int __attribute_const__ kvm_target_cpu(void); + int kvm_reset_vcpu(struct kvm_vcpu *vcpu); + void kvm_reset_coprocs(struct kvm_vcpu *vcpu); + +diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h +index 7b362bc9c09a..0cbdb8ed71cf 100644 +--- a/arch/arm/include/asm/kvm_mmu.h ++++ b/arch/arm/include/asm/kvm_mmu.h +@@ -127,6 +127,18 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd) + (__boundary - 1 < (end) - 1)? __boundary: (end); \ + }) + ++static inline bool kvm_page_empty(void *ptr) ++{ ++ struct page *ptr_page = virt_to_page(ptr); ++ return page_count(ptr_page) == 1; ++} ++ ++ ++#define kvm_pte_table_empty(ptep) kvm_page_empty(ptep) ++#define kvm_pmd_table_empty(pmdp) kvm_page_empty(pmdp) ++#define kvm_pud_table_empty(pudp) (0) ++ ++ + struct kvm; + + #define kvm_flush_dcache_to_poc(a,l) __cpuc_flush_dcache_area((a), (l)) +diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S +index 797b1a6a4906..7e666cfda634 100644 +--- a/arch/arm/kernel/hyp-stub.S ++++ b/arch/arm/kernel/hyp-stub.S +@@ -134,9 +134,7 @@ ENTRY(__hyp_stub_install_secondary) + mcr p15, 4, r7, c1, c1, 3 @ HSTR + + THUMB( orr r7, #(1 << 30) ) @ HSCTLR.TE +-#ifdef CONFIG_CPU_BIG_ENDIAN +- orr r7, #(1 << 9) @ HSCTLR.EE +-#endif ++ARM_BE8(orr r7, r7, #(1 << 25)) @ HSCTLR.EE + mcr p15, 4, r7, c1, c0, 0 @ HSCTLR + + mrc p15, 4, r7, c1, c1, 1 @ HDCR +diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c +index bd18bb8b2770..df6e75e47ae0 100644 +--- a/arch/arm/kvm/arm.c ++++ b/arch/arm/kvm/arm.c +@@ -82,7 +82,7 @@ struct kvm_vcpu *kvm_arm_get_running_vcpu(void) + /** + * kvm_arm_get_running_vcpus - get the per-CPU array of currently running vcpus. + */ +-struct kvm_vcpu __percpu **kvm_get_running_vcpus(void) ++struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void) + { + return &kvm_arm_running_vcpu; + } +@@ -155,16 +155,6 @@ int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf) + return VM_FAULT_SIGBUS; + } + +-void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free, +- struct kvm_memory_slot *dont) +-{ +-} +- +-int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, +- unsigned long npages) +-{ +- return 0; +-} + + /** + * kvm_arch_destroy_vm - destroy the VM data structure +@@ -224,33 +214,6 @@ long kvm_arch_dev_ioctl(struct file *filp, + return -EINVAL; + } + +-void kvm_arch_memslots_updated(struct kvm *kvm) +-{ +-} +- +-int kvm_arch_prepare_memory_region(struct kvm *kvm, +- struct kvm_memory_slot *memslot, +- struct kvm_userspace_memory_region *mem, +- enum kvm_mr_change change) +-{ +- return 0; +-} +- +-void kvm_arch_commit_memory_region(struct kvm *kvm, +- struct kvm_userspace_memory_region *mem, +- const struct kvm_memory_slot *old, +- enum kvm_mr_change change) +-{ +-} +- +-void kvm_arch_flush_shadow_all(struct kvm *kvm) +-{ +-} +- +-void kvm_arch_flush_shadow_memslot(struct kvm *kvm, +- struct kvm_memory_slot *slot) +-{ +-} + + struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) + { +diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c +index c58a35116f63..7c732908f1df 100644 +--- a/arch/arm/kvm/coproc.c ++++ b/arch/arm/kvm/coproc.c +@@ -742,7 +742,7 @@ static bool is_valid_cache(u32 val) + u32 level, ctype; + + if (val >= CSSELR_MAX) +- return -ENOENT; ++ return false; + + /* Bottom bit is Instruction or Data bit. Next 3 bits are level. */ + level = (val >> 1); +diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c +index c93ef38f9cb0..70ed2c1f57b0 100644 +--- a/arch/arm/kvm/mmu.c ++++ b/arch/arm/kvm/mmu.c +@@ -90,103 +90,115 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc) + return p; + } + +-static bool page_empty(void *ptr) ++static void clear_pgd_entry(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr) + { +- struct page *ptr_page = virt_to_page(ptr); +- return page_count(ptr_page) == 1; ++ pud_t *pud_table __maybe_unused = pud_offset(pgd, 0); ++ pgd_clear(pgd); ++ kvm_tlb_flush_vmid_ipa(kvm, addr); ++ pud_free(NULL, pud_table); ++ put_page(virt_to_page(pgd)); + } + + static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr) + { +- if (pud_huge(*pud)) { +- pud_clear(pud); +- kvm_tlb_flush_vmid_ipa(kvm, addr); +- } else { +- pmd_t *pmd_table = pmd_offset(pud, 0); +- pud_clear(pud); +- kvm_tlb_flush_vmid_ipa(kvm, addr); +- pmd_free(NULL, pmd_table); +- } ++ pmd_t *pmd_table = pmd_offset(pud, 0); ++ VM_BUG_ON(pud_huge(*pud)); ++ pud_clear(pud); ++ kvm_tlb_flush_vmid_ipa(kvm, addr); ++ pmd_free(NULL, pmd_table); + put_page(virt_to_page(pud)); + } + + static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr) + { +- if (kvm_pmd_huge(*pmd)) { +- pmd_clear(pmd); +- kvm_tlb_flush_vmid_ipa(kvm, addr); +- } else { +- pte_t *pte_table = pte_offset_kernel(pmd, 0); +- pmd_clear(pmd); +- kvm_tlb_flush_vmid_ipa(kvm, addr); +- pte_free_kernel(NULL, pte_table); +- } ++ pte_t *pte_table = pte_offset_kernel(pmd, 0); ++ VM_BUG_ON(kvm_pmd_huge(*pmd)); ++ pmd_clear(pmd); ++ kvm_tlb_flush_vmid_ipa(kvm, addr); ++ pte_free_kernel(NULL, pte_table); + put_page(virt_to_page(pmd)); + } + +-static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr) ++static void unmap_ptes(struct kvm *kvm, pmd_t *pmd, ++ phys_addr_t addr, phys_addr_t end) + { +- if (pte_present(*pte)) { +- kvm_set_pte(pte, __pte(0)); +- put_page(virt_to_page(pte)); +- kvm_tlb_flush_vmid_ipa(kvm, addr); ++ phys_addr_t start_addr = addr; ++ pte_t *pte, *start_pte; ++ ++ start_pte = pte = pte_offset_kernel(pmd, addr); ++ do { ++ if (!pte_none(*pte)) { ++ kvm_set_pte(pte, __pte(0)); ++ put_page(virt_to_page(pte)); ++ kvm_tlb_flush_vmid_ipa(kvm, addr); ++ } ++ } while (pte++, addr += PAGE_SIZE, addr != end); ++ ++ if (kvm_pte_table_empty(start_pte)) ++ clear_pmd_entry(kvm, pmd, start_addr); + } +-} + +-static void unmap_range(struct kvm *kvm, pgd_t *pgdp, +- unsigned long long start, u64 size) ++static void unmap_pmds(struct kvm *kvm, pud_t *pud, ++ phys_addr_t addr, phys_addr_t end) + { +- pgd_t *pgd; +- pud_t *pud; +- pmd_t *pmd; +- pte_t *pte; +- unsigned long long addr = start, end = start + size; +- u64 next; +- +- while (addr < end) { +- pgd = pgdp + pgd_index(addr); +- pud = pud_offset(pgd, addr); +- if (pud_none(*pud)) { +- addr = kvm_pud_addr_end(addr, end); +- continue; +- } ++ phys_addr_t next, start_addr = addr; ++ pmd_t *pmd, *start_pmd; + +- if (pud_huge(*pud)) { +- /* +- * If we are dealing with a huge pud, just clear it and +- * move on. +- */ +- clear_pud_entry(kvm, pud, addr); +- addr = kvm_pud_addr_end(addr, end); +- continue; ++ start_pmd = pmd = pmd_offset(pud, addr); ++ do { ++ next = kvm_pmd_addr_end(addr, end); ++ if (!pmd_none(*pmd)) { ++ if (kvm_pmd_huge(*pmd)) { ++ pmd_clear(pmd); ++ kvm_tlb_flush_vmid_ipa(kvm, addr); ++ put_page(virt_to_page(pmd)); ++ } else { ++ unmap_ptes(kvm, pmd, addr, next); ++ } + } ++ } while (pmd++, addr = next, addr != end); + +- pmd = pmd_offset(pud, addr); +- if (pmd_none(*pmd)) { +- addr = kvm_pmd_addr_end(addr, end); +- continue; +- } ++ if (kvm_pmd_table_empty(start_pmd)) ++ clear_pud_entry(kvm, pud, start_addr); ++} + +- if (!kvm_pmd_huge(*pmd)) { +- pte = pte_offset_kernel(pmd, addr); +- clear_pte_entry(kvm, pte, addr); +- next = addr + PAGE_SIZE; +- } ++static void unmap_puds(struct kvm *kvm, pgd_t *pgd, ++ phys_addr_t addr, phys_addr_t end) ++{ ++ phys_addr_t next, start_addr = addr; ++ pud_t *pud, *start_pud; + +- /* +- * If the pmd entry is to be cleared, walk back up the ladder +- */ +- if (kvm_pmd_huge(*pmd) || page_empty(pte)) { +- clear_pmd_entry(kvm, pmd, addr); +- next = kvm_pmd_addr_end(addr, end); +- if (page_empty(pmd) && !page_empty(pud)) { +- clear_pud_entry(kvm, pud, addr); +- next = kvm_pud_addr_end(addr, end); ++ start_pud = pud = pud_offset(pgd, addr); ++ do { ++ next = kvm_pud_addr_end(addr, end); ++ if (!pud_none(*pud)) { ++ if (pud_huge(*pud)) { ++ pud_clear(pud); ++ kvm_tlb_flush_vmid_ipa(kvm, addr); ++ put_page(virt_to_page(pud)); ++ } else { ++ unmap_pmds(kvm, pud, addr, next); + } + } ++ } while (pud++, addr = next, addr != end); + +- addr = next; +- } ++ if (kvm_pud_table_empty(start_pud)) ++ clear_pgd_entry(kvm, pgd, start_addr); ++} ++ ++ ++static void unmap_range(struct kvm *kvm, pgd_t *pgdp, ++ phys_addr_t start, u64 size) ++{ ++ pgd_t *pgd; ++ phys_addr_t addr = start, end = start + size; ++ phys_addr_t next; ++ ++ pgd = pgdp + pgd_index(addr); ++ do { ++ next = kvm_pgd_addr_end(addr, end); ++ unmap_puds(kvm, pgd, addr, next); ++ } while (pgd++, addr = next, addr != end); + } + + static void stage2_flush_ptes(struct kvm *kvm, pmd_t *pmd, +@@ -747,6 +759,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache; + struct vm_area_struct *vma; + pfn_t pfn; ++ pgprot_t mem_type = PAGE_S2; + + write_fault = kvm_is_write_fault(kvm_vcpu_get_hsr(vcpu)); + if (fault_status == FSC_PERM && !write_fault) { +@@ -797,6 +810,9 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + if (is_error_pfn(pfn)) + return -EFAULT; + ++ if (kvm_is_mmio_pfn(pfn)) ++ mem_type = PAGE_S2_DEVICE; ++ + spin_lock(&kvm->mmu_lock); + if (mmu_notifier_retry(kvm, mmu_seq)) + goto out_unlock; +@@ -804,7 +820,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + hugetlb = transparent_hugepage_adjust(&pfn, &fault_ipa); + + if (hugetlb) { +- pmd_t new_pmd = pfn_pmd(pfn, PAGE_S2); ++ pmd_t new_pmd = pfn_pmd(pfn, mem_type); + new_pmd = pmd_mkhuge(new_pmd); + if (writable) { + kvm_set_s2pmd_writable(&new_pmd); +@@ -813,13 +829,14 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + coherent_cache_guest_page(vcpu, hva & PMD_MASK, PMD_SIZE); + ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd); + } else { +- pte_t new_pte = pfn_pte(pfn, PAGE_S2); ++ pte_t new_pte = pfn_pte(pfn, mem_type); + if (writable) { + kvm_set_s2pte_writable(&new_pte); + kvm_set_pfn_dirty(pfn); + } + coherent_cache_guest_page(vcpu, hva, PAGE_SIZE); +- ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, false); ++ ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, ++ mem_type == PAGE_S2_DEVICE); + } + + +@@ -1099,3 +1116,49 @@ out: + free_hyp_pgds(); + return err; + } ++ ++void kvm_arch_commit_memory_region(struct kvm *kvm, ++ struct kvm_userspace_memory_region *mem, ++ const struct kvm_memory_slot *old, ++ enum kvm_mr_change change) ++{ ++ gpa_t gpa = old->base_gfn << PAGE_SHIFT; ++ phys_addr_t size = old->npages << PAGE_SHIFT; ++ if (change == KVM_MR_DELETE || change == KVM_MR_MOVE) { ++ spin_lock(&kvm->mmu_lock); ++ unmap_stage2_range(kvm, gpa, size); ++ spin_unlock(&kvm->mmu_lock); ++ } ++} ++ ++int kvm_arch_prepare_memory_region(struct kvm *kvm, ++ struct kvm_memory_slot *memslot, ++ struct kvm_userspace_memory_region *mem, ++ enum kvm_mr_change change) ++{ ++ return 0; ++} ++ ++void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free, ++ struct kvm_memory_slot *dont) ++{ ++} ++ ++int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, ++ unsigned long npages) ++{ ++ return 0; ++} ++ ++void kvm_arch_memslots_updated(struct kvm *kvm) ++{ ++} ++ ++void kvm_arch_flush_shadow_all(struct kvm *kvm) ++{ ++} ++ ++void kvm_arch_flush_shadow_memslot(struct kvm *kvm, ++ struct kvm_memory_slot *slot) ++{ ++} +diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h +index 0a1d69751562..3fb0946d963a 100644 +--- a/arch/arm64/include/asm/kvm_host.h ++++ b/arch/arm64/include/asm/kvm_host.h +@@ -42,7 +42,7 @@ + #define KVM_VCPU_MAX_FEATURES 2 + + struct kvm_vcpu; +-int kvm_target_cpu(void); ++int __attribute_const__ kvm_target_cpu(void); + int kvm_reset_vcpu(struct kvm_vcpu *vcpu); + int kvm_arch_dev_ioctl_check_extension(long ext); + +@@ -177,7 +177,7 @@ static inline int kvm_test_age_hva(struct kvm *kvm, unsigned long hva) + } + + struct kvm_vcpu *kvm_arm_get_running_vcpu(void); +-struct kvm_vcpu __percpu **kvm_get_running_vcpus(void); ++struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void); + + u64 kvm_call_hyp(void *hypfn, ...); + +diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h +index 7d29847a893b..8e138c7c53ac 100644 +--- a/arch/arm64/include/asm/kvm_mmu.h ++++ b/arch/arm64/include/asm/kvm_mmu.h +@@ -125,6 +125,21 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd) + #define kvm_pud_addr_end(addr, end) pud_addr_end(addr, end) + #define kvm_pmd_addr_end(addr, end) pmd_addr_end(addr, end) + ++static inline bool kvm_page_empty(void *ptr) ++{ ++ struct page *ptr_page = virt_to_page(ptr); ++ return page_count(ptr_page) == 1; ++} ++ ++#define kvm_pte_table_empty(ptep) kvm_page_empty(ptep) ++#ifndef CONFIG_ARM64_64K_PAGES ++#define kvm_pmd_table_empty(pmdp) kvm_page_empty(pmdp) ++#else ++#define kvm_pmd_table_empty(pmdp) (0) ++#endif ++#define kvm_pud_table_empty(pudp) (0) ++ ++ + struct kvm; + + #define kvm_flush_dcache_to_poc(a,l) __flush_dcache_area((a), (l)) +diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S +index b0d1512acf08..5dfc8331c385 100644 +--- a/arch/arm64/kvm/hyp.S ++++ b/arch/arm64/kvm/hyp.S +@@ -830,7 +830,7 @@ el1_trap: + mrs x2, far_el2 + + 2: mrs x0, tpidr_el2 +- str x1, [x0, #VCPU_ESR_EL2] ++ str w1, [x0, #VCPU_ESR_EL2] + str x2, [x0, #VCPU_FAR_EL2] + str x3, [x0, #VCPU_HPFAR_EL2] + +diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c +index 03244582bc55..7691b2563d27 100644 +--- a/arch/arm64/kvm/sys_regs.c ++++ b/arch/arm64/kvm/sys_regs.c +@@ -836,7 +836,7 @@ static bool is_valid_cache(u32 val) + u32 level, ctype; + + if (val >= CSSELR_MAX) +- return -ENOENT; ++ return false; + + /* Bottom bit is Instruction or Data bit. Next 3 bits are level. */ + level = (val >> 1); +@@ -962,7 +962,7 @@ static unsigned int num_demux_regs(void) + + static int write_demux_regids(u64 __user *uindices) + { +- u64 val = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX; ++ u64 val = KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX; + unsigned int i; + + val |= KVM_REG_ARM_DEMUX_ID_CCSIDR; +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index 26b03e1254ef..8ff2b3ca7ee9 100644 +--- a/drivers/bluetooth/ath3k.c ++++ b/drivers/bluetooth/ath3k.c +@@ -79,6 +79,7 @@ static const struct usb_device_id ath3k_table[] = { + { USB_DEVICE(0x0489, 0xe057) }, + { USB_DEVICE(0x0489, 0xe056) }, + { USB_DEVICE(0x0489, 0xe05f) }, ++ { USB_DEVICE(0x0489, 0xe076) }, + { USB_DEVICE(0x0489, 0xe078) }, + { USB_DEVICE(0x04c5, 0x1330) }, + { USB_DEVICE(0x04CA, 0x3004) }, +@@ -109,6 +110,7 @@ static const struct usb_device_id ath3k_table[] = { + { USB_DEVICE(0x13d3, 0x3402) }, + { USB_DEVICE(0x13d3, 0x3408) }, + { USB_DEVICE(0x13d3, 0x3432) }, ++ { USB_DEVICE(0x13d3, 0x3474) }, + + /* Atheros AR5BBU12 with sflash firmware */ + { USB_DEVICE(0x0489, 0xE02C) }, +@@ -133,6 +135,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { + { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, +@@ -163,6 +166,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { + { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 }, + + /* Atheros AR5BBU22 with sflash firmware */ + { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 }, +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 9eb1669962ef..c0e7a9aa97a4 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -157,6 +157,7 @@ static const struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, +@@ -187,6 +188,7 @@ static const struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 }, + + /* Atheros AR5BBU12 with sflash firmware */ + { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, +diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c +index 28486b19fc36..ae6dae8ef7ab 100644 +--- a/drivers/crypto/caam/caamrng.c ++++ b/drivers/crypto/caam/caamrng.c +@@ -56,7 +56,7 @@ + + /* Buffer, its dma address and lock */ + struct buf_data { +- u8 buf[RN_BUF_SIZE]; ++ u8 buf[RN_BUF_SIZE] ____cacheline_aligned; + dma_addr_t addr; + struct completion filled; + u32 hw_desc[DESC_JOB_O_LEN]; +diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c +index 968374776db9..f2511a03e3e9 100644 +--- a/drivers/gpu/drm/mgag200/mgag200_mode.c ++++ b/drivers/gpu/drm/mgag200/mgag200_mode.c +@@ -1529,6 +1529,11 @@ static int mga_vga_mode_valid(struct drm_connector *connector, + return MODE_BANDWIDTH; + } + ++ if ((mode->hdisplay % 8) != 0 || (mode->hsync_start % 8) != 0 || ++ (mode->hsync_end % 8) != 0 || (mode->htotal % 8) != 0) { ++ return MODE_H_ILLEGAL; ++ } ++ + if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 || + mode->crtc_hsync_end > 4096 || mode->crtc_htotal > 4096 || + mode->crtc_vdisplay > 2048 || mode->crtc_vsync_start > 4096 || +diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c +index 8f580fda443f..ce211328bc1c 100644 +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -265,6 +265,16 @@ lpfc_sli4_eq_get(struct lpfc_queue *q) + return NULL; + + q->hba_index = idx; ++ ++ /* ++ * insert barrier for instruction interlock : data from the hardware ++ * must have the valid bit checked before it can be copied and acted ++ * upon. Given what was seen in lpfc_sli4_cq_get() of speculative ++ * instructions allowing action on content before valid bit checked, ++ * add barrier here as well. May not be needed as "content" is a ++ * single 32-bit entity here (vs multi word structure for cq's). ++ */ ++ mb(); + return eqe; + } + +@@ -370,6 +380,17 @@ lpfc_sli4_cq_get(struct lpfc_queue *q) + + cqe = q->qe[q->hba_index].cqe; + q->hba_index = idx; ++ ++ /* ++ * insert barrier for instruction interlock : data from the hardware ++ * must have the valid bit checked before it can be copied and acted ++ * upon. Speculative instructions were allowing a bcopy at the start ++ * of lpfc_sli4_fp_handle_wcqe(), which is called immediately ++ * after our return, to copy data before the valid bit check above ++ * was done. As such, some of the copied data was stale. The barrier ++ * ensures the check is before any data is copied. ++ */ ++ mb(); + return cqe; + } + +diff --git a/fs/pipe.c b/fs/pipe.c +index 78fd0d0788db..46f1ab264a4c 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -117,25 +117,27 @@ void pipe_wait(struct pipe_inode_info *pipe) + } + + static int +-pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len, +- int atomic) ++pipe_iov_copy_from_user(void *addr, int *offset, struct iovec *iov, ++ size_t *remaining, int atomic) + { + unsigned long copy; + +- while (len > 0) { ++ while (*remaining > 0) { + while (!iov->iov_len) + iov++; +- copy = min_t(unsigned long, len, iov->iov_len); ++ copy = min_t(unsigned long, *remaining, iov->iov_len); + + if (atomic) { +- if (__copy_from_user_inatomic(to, iov->iov_base, copy)) ++ if (__copy_from_user_inatomic(addr + *offset, ++ iov->iov_base, copy)) + return -EFAULT; + } else { +- if (copy_from_user(to, iov->iov_base, copy)) ++ if (copy_from_user(addr + *offset, ++ iov->iov_base, copy)) + return -EFAULT; + } +- to += copy; +- len -= copy; ++ *offset += copy; ++ *remaining -= copy; + iov->iov_base += copy; + iov->iov_len -= copy; + } +@@ -143,25 +145,27 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len, + } + + static int +-pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len, +- int atomic) ++pipe_iov_copy_to_user(struct iovec *iov, void *addr, int *offset, ++ size_t *remaining, int atomic) + { + unsigned long copy; + +- while (len > 0) { ++ while (*remaining > 0) { + while (!iov->iov_len) + iov++; +- copy = min_t(unsigned long, len, iov->iov_len); ++ copy = min_t(unsigned long, *remaining, iov->iov_len); + + if (atomic) { +- if (__copy_to_user_inatomic(iov->iov_base, from, copy)) ++ if (__copy_to_user_inatomic(iov->iov_base, ++ addr + *offset, copy)) + return -EFAULT; + } else { +- if (copy_to_user(iov->iov_base, from, copy)) ++ if (copy_to_user(iov->iov_base, ++ addr + *offset, copy)) + return -EFAULT; + } +- from += copy; +- len -= copy; ++ *offset += copy; ++ *remaining -= copy; + iov->iov_base += copy; + iov->iov_len -= copy; + } +@@ -395,7 +399,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, + struct pipe_buffer *buf = pipe->bufs + curbuf; + const struct pipe_buf_operations *ops = buf->ops; + void *addr; +- size_t chars = buf->len; ++ size_t chars = buf->len, remaining; + int error, atomic; + + if (chars > total_len) +@@ -409,9 +413,11 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, + } + + atomic = !iov_fault_in_pages_write(iov, chars); ++ remaining = chars; + redo: + addr = ops->map(pipe, buf, atomic); +- error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars, atomic); ++ error = pipe_iov_copy_to_user(iov, addr, &buf->offset, ++ &remaining, atomic); + ops->unmap(pipe, buf, addr); + if (unlikely(error)) { + /* +@@ -426,7 +432,6 @@ redo: + break; + } + ret += chars; +- buf->offset += chars; + buf->len -= chars; + + /* Was it a packet buffer? Clean up and exit */ +@@ -531,6 +536,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov, + if (ops->can_merge && offset + chars <= PAGE_SIZE) { + int error, atomic = 1; + void *addr; ++ size_t remaining = chars; + + error = ops->confirm(pipe, buf); + if (error) +@@ -539,8 +545,8 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov, + iov_fault_in_pages_read(iov, chars); + redo1: + addr = ops->map(pipe, buf, atomic); +- error = pipe_iov_copy_from_user(offset + addr, iov, +- chars, atomic); ++ error = pipe_iov_copy_from_user(addr, &offset, iov, ++ &remaining, atomic); + ops->unmap(pipe, buf, addr); + ret = error; + do_wakeup = 1; +@@ -575,6 +581,8 @@ redo1: + struct page *page = pipe->tmp_page; + char *src; + int error, atomic = 1; ++ int offset = 0; ++ size_t remaining; + + if (!page) { + page = alloc_page(GFP_HIGHUSER); +@@ -595,14 +603,15 @@ redo1: + chars = total_len; + + iov_fault_in_pages_read(iov, chars); ++ remaining = chars; + redo2: + if (atomic) + src = kmap_atomic(page); + else + src = kmap(page); + +- error = pipe_iov_copy_from_user(src, iov, chars, +- atomic); ++ error = pipe_iov_copy_from_user(src, &offset, iov, ++ &remaining, atomic); + if (atomic) + kunmap_atomic(src); + else +diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c +index 8a8631926a07..cb347e85f75e 100644 +--- a/kernel/trace/trace_events_filter.c ++++ b/kernel/trace/trace_events_filter.c +@@ -1399,19 +1399,24 @@ static int check_preds(struct filter_parse_state *ps) + { + int n_normal_preds = 0, n_logical_preds = 0; + struct postfix_elt *elt; ++ int cnt = 0; + + list_for_each_entry(elt, &ps->postfix, list) { +- if (elt->op == OP_NONE) ++ if (elt->op == OP_NONE) { ++ cnt++; + continue; ++ } + ++ cnt--; + if (elt->op == OP_AND || elt->op == OP_OR) { + n_logical_preds++; + continue; + } + n_normal_preds++; ++ WARN_ON_ONCE(cnt < 0); + } + +- if (!n_normal_preds || n_logical_preds >= n_normal_preds) { ++ if (cnt != 1 || !n_normal_preds || n_logical_preds >= n_normal_preds) { + parse_error(ps, FILT_ERR_INVALID_FILTER, 0); + return -EINVAL; + } +diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c +index 4eec2d436109..1316e558db64 100644 +--- a/virt/kvm/arm/vgic.c ++++ b/virt/kvm/arm/vgic.c +@@ -1654,7 +1654,7 @@ out: + return ret; + } + +-static bool vgic_ioaddr_overlap(struct kvm *kvm) ++static int vgic_ioaddr_overlap(struct kvm *kvm) + { + phys_addr_t dist = kvm->arch.vgic.vgic_dist_base; + phys_addr_t cpu = kvm->arch.vgic.vgic_cpu_base; diff --git a/patch/kernel/cubox-default/patch-3.14.46-47.patch b/patch/kernel/cubox-default/patch-3.14.46-47.patch new file mode 100644 index 000000000..862f253cd --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.46-47.patch @@ -0,0 +1,1395 @@ +diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt +index 6cd63a9010fb..bc6d61773ee2 100644 +--- a/Documentation/virtual/kvm/api.txt ++++ b/Documentation/virtual/kvm/api.txt +@@ -2344,7 +2344,8 @@ should be created before this ioctl is invoked. + + Possible features: + - KVM_ARM_VCPU_POWER_OFF: Starts the CPU in a power-off state. +- Depends on KVM_CAP_ARM_PSCI. ++ Depends on KVM_CAP_ARM_PSCI. If not set, the CPU will be powered on ++ and execute guest code when KVM_RUN is called. + - KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode. + Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only). + +diff --git a/Makefile b/Makefile +index def39fdd9df4..f9041e6d4d19 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 46 ++SUBLEVEL = 47 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h +index 0fa90c962ac8..853e2becad18 100644 +--- a/arch/arm/include/asm/kvm_emulate.h ++++ b/arch/arm/include/asm/kvm_emulate.h +@@ -33,6 +33,11 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu); + void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr); + void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr); + ++static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) ++{ ++ vcpu->arch.hcr = HCR_GUEST_MASK; ++} ++ + static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu) + { + return 1; +diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h +index 0cbdb8ed71cf..9f7923193cda 100644 +--- a/arch/arm/include/asm/kvm_mmu.h ++++ b/arch/arm/include/asm/kvm_mmu.h +@@ -47,6 +47,7 @@ int create_hyp_io_mappings(void *from, void *to, phys_addr_t); + void free_boot_hyp_pgd(void); + void free_hyp_pgds(void); + ++void stage2_unmap_vm(struct kvm *kvm); + int kvm_alloc_stage2_pgd(struct kvm *kvm); + void kvm_free_stage2_pgd(struct kvm *kvm); + int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, +@@ -78,17 +79,6 @@ static inline void kvm_set_pte(pte_t *pte, pte_t new_pte) + flush_pmd_entry(pte); + } + +-static inline bool kvm_is_write_fault(unsigned long hsr) +-{ +- unsigned long hsr_ec = hsr >> HSR_EC_SHIFT; +- if (hsr_ec == HSR_EC_IABT) +- return false; +- else if ((hsr & HSR_ISV) && !(hsr & HSR_WNR)) +- return false; +- else +- return true; +-} +- + static inline void kvm_clean_pgd(pgd_t *pgd) + { + clean_dcache_area(pgd, PTRS_PER_S2_PGD * sizeof(pgd_t)); +diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c +index df6e75e47ae0..2e74a617147d 100644 +--- a/arch/arm/kvm/arm.c ++++ b/arch/arm/kvm/arm.c +@@ -220,6 +220,11 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) + int err; + struct kvm_vcpu *vcpu; + ++ if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) { ++ err = -EBUSY; ++ goto out; ++ } ++ + vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); + if (!vcpu) { + err = -ENOMEM; +@@ -427,9 +432,9 @@ static void update_vttbr(struct kvm *kvm) + + /* update vttbr to be used with the new vmid */ + pgd_phys = virt_to_phys(kvm->arch.pgd); ++ BUG_ON(pgd_phys & ~VTTBR_BADDR_MASK); + vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK; +- kvm->arch.vttbr = pgd_phys & VTTBR_BADDR_MASK; +- kvm->arch.vttbr |= vmid; ++ kvm->arch.vttbr = pgd_phys | vmid; + + spin_unlock(&kvm_vmid_lock); + } +@@ -676,10 +681,21 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu, + return ret; + + /* ++ * Ensure a rebooted VM will fault in RAM pages and detect if the ++ * guest MMU is turned off and flush the caches as needed. ++ */ ++ if (vcpu->arch.has_run_once) ++ stage2_unmap_vm(vcpu->kvm); ++ ++ vcpu_reset_hcr(vcpu); ++ ++ /* + * Handle the "start in power-off" case by marking the VCPU as paused. + */ +- if (__test_and_clear_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features)) ++ if (test_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features)) + vcpu->arch.pause = true; ++ else ++ vcpu->arch.pause = false; + + return 0; + } +@@ -825,7 +841,8 @@ static int hyp_init_cpu_notify(struct notifier_block *self, + switch (action) { + case CPU_STARTING: + case CPU_STARTING_FROZEN: +- cpu_init_hyp_mode(NULL); ++ if (__hyp_get_vectors() == hyp_default_vectors) ++ cpu_init_hyp_mode(NULL); + break; + } + +diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c +index b23a59c1c522..2786eae10c0d 100644 +--- a/arch/arm/kvm/guest.c ++++ b/arch/arm/kvm/guest.c +@@ -38,7 +38,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { + + int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) + { +- vcpu->arch.hcr = HCR_GUEST_MASK; + return 0; + } + +diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c +index 70ed2c1f57b0..524b4b57f650 100644 +--- a/arch/arm/kvm/mmu.c ++++ b/arch/arm/kvm/mmu.c +@@ -197,7 +197,8 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp, + pgd = pgdp + pgd_index(addr); + do { + next = kvm_pgd_addr_end(addr, end); +- unmap_puds(kvm, pgd, addr, next); ++ if (!pgd_none(*pgd)) ++ unmap_puds(kvm, pgd, addr, next); + } while (pgd++, addr = next, addr != end); + } + +@@ -555,6 +556,71 @@ static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size) + unmap_range(kvm, kvm->arch.pgd, start, size); + } + ++static void stage2_unmap_memslot(struct kvm *kvm, ++ struct kvm_memory_slot *memslot) ++{ ++ hva_t hva = memslot->userspace_addr; ++ phys_addr_t addr = memslot->base_gfn << PAGE_SHIFT; ++ phys_addr_t size = PAGE_SIZE * memslot->npages; ++ hva_t reg_end = hva + size; ++ ++ /* ++ * A memory region could potentially cover multiple VMAs, and any holes ++ * between them, so iterate over all of them to find out if we should ++ * unmap any of them. ++ * ++ * +--------------------------------------------+ ++ * +---------------+----------------+ +----------------+ ++ * | : VMA 1 | VMA 2 | | VMA 3 : | ++ * +---------------+----------------+ +----------------+ ++ * | memory region | ++ * +--------------------------------------------+ ++ */ ++ do { ++ struct vm_area_struct *vma = find_vma(current->mm, hva); ++ hva_t vm_start, vm_end; ++ ++ if (!vma || vma->vm_start >= reg_end) ++ break; ++ ++ /* ++ * Take the intersection of this VMA with the memory region ++ */ ++ vm_start = max(hva, vma->vm_start); ++ vm_end = min(reg_end, vma->vm_end); ++ ++ if (!(vma->vm_flags & VM_PFNMAP)) { ++ gpa_t gpa = addr + (vm_start - memslot->userspace_addr); ++ unmap_stage2_range(kvm, gpa, vm_end - vm_start); ++ } ++ hva = vm_end; ++ } while (hva < reg_end); ++} ++ ++/** ++ * stage2_unmap_vm - Unmap Stage-2 RAM mappings ++ * @kvm: The struct kvm pointer ++ * ++ * Go through the memregions and unmap any reguler RAM ++ * backing memory already mapped to the VM. ++ */ ++void stage2_unmap_vm(struct kvm *kvm) ++{ ++ struct kvm_memslots *slots; ++ struct kvm_memory_slot *memslot; ++ int idx; ++ ++ idx = srcu_read_lock(&kvm->srcu); ++ spin_lock(&kvm->mmu_lock); ++ ++ slots = kvm_memslots(kvm); ++ kvm_for_each_memslot(memslot, slots) ++ stage2_unmap_memslot(kvm, memslot); ++ ++ spin_unlock(&kvm->mmu_lock); ++ srcu_read_unlock(&kvm->srcu, idx); ++} ++ + /** + * kvm_free_stage2_pgd - free all stage-2 tables + * @kvm: The KVM struct pointer for the VM. +@@ -746,6 +812,19 @@ static bool transparent_hugepage_adjust(pfn_t *pfnp, phys_addr_t *ipap) + return false; + } + ++static bool kvm_is_write_fault(struct kvm_vcpu *vcpu) ++{ ++ if (kvm_vcpu_trap_is_iabt(vcpu)) ++ return false; ++ ++ return kvm_vcpu_dabt_iswrite(vcpu); ++} ++ ++static bool kvm_is_device_pfn(unsigned long pfn) ++{ ++ return !pfn_valid(pfn); ++} ++ + static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + struct kvm_memory_slot *memslot, + unsigned long fault_status) +@@ -761,7 +840,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + pfn_t pfn; + pgprot_t mem_type = PAGE_S2; + +- write_fault = kvm_is_write_fault(kvm_vcpu_get_hsr(vcpu)); ++ write_fault = kvm_is_write_fault(vcpu); + if (fault_status == FSC_PERM && !write_fault) { + kvm_err("Unexpected L2 read permission error\n"); + return -EFAULT; +@@ -770,6 +849,12 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + /* Let's check if we will get back a huge page backed by hugetlbfs */ + down_read(¤t->mm->mmap_sem); + vma = find_vma_intersection(current->mm, hva, hva + 1); ++ if (unlikely(!vma)) { ++ kvm_err("Failed to find VMA for hva 0x%lx\n", hva); ++ up_read(¤t->mm->mmap_sem); ++ return -EFAULT; ++ } ++ + if (is_vm_hugetlb_page(vma)) { + hugetlb = true; + gfn = (fault_ipa & PMD_MASK) >> PAGE_SHIFT; +@@ -810,7 +895,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + if (is_error_pfn(pfn)) + return -EFAULT; + +- if (kvm_is_mmio_pfn(pfn)) ++ if (kvm_is_device_pfn(pfn)) + mem_type = PAGE_S2_DEVICE; + + spin_lock(&kvm->mmu_lock); +@@ -836,7 +921,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + } + coherent_cache_guest_page(vcpu, hva, PAGE_SIZE); + ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, +- mem_type == PAGE_S2_DEVICE); ++ pgprot_val(mem_type) == pgprot_val(PAGE_S2_DEVICE)); + } + + +@@ -912,6 +997,9 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) + + memslot = gfn_to_memslot(vcpu->kvm, gfn); + ++ /* Userspace should not be able to register out-of-bounds IPAs */ ++ VM_BUG_ON(fault_ipa >= KVM_PHYS_SIZE); ++ + ret = user_mem_abort(vcpu, fault_ipa, memslot, fault_status); + if (ret == 0) + ret = 1; +@@ -1136,6 +1224,14 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, + struct kvm_userspace_memory_region *mem, + enum kvm_mr_change change) + { ++ /* ++ * Prevent userspace from creating a memory region outside of the IPA ++ * space addressable by the KVM guest IPA space. ++ */ ++ if (memslot->base_gfn + memslot->npages >= ++ (KVM_PHYS_SIZE >> PAGE_SHIFT)) ++ return -EFAULT; ++ + return 0; + } + +diff --git a/arch/arm/mach-dove/board-dt.c b/arch/arm/mach-dove/board-dt.c +index 49fa9abd09da..7a7a09a5d5ff 100644 +--- a/arch/arm/mach-dove/board-dt.c ++++ b/arch/arm/mach-dove/board-dt.c +@@ -26,7 +26,7 @@ static void __init dove_dt_init(void) + #ifdef CONFIG_CACHE_TAUROS2 + tauros2_init(0); + #endif +- BUG_ON(mvebu_mbus_dt_init()); ++ BUG_ON(mvebu_mbus_dt_init(false)); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + } + +diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c +index 01a5765a8b26..b509556f6cfd 100644 +--- a/arch/arm/mach-imx/clk-imx6q.c ++++ b/arch/arm/mach-imx/clk-imx6q.c +@@ -406,7 +406,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) + clk[gpmi_io] = imx_clk_gate2("gpmi_io", "enfc", base + 0x78, 28); + clk[gpmi_apb] = imx_clk_gate2("gpmi_apb", "usdhc3", base + 0x78, 30); + clk[rom] = imx_clk_gate2("rom", "ahb", base + 0x7c, 0); +- clk[sata] = imx_clk_gate2("sata", "ipg", base + 0x7c, 4); ++ clk[sata] = imx_clk_gate2("sata", "ahb", base + 0x7c, 4); + clk[sdma] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6); + clk[spba] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12); + clk[spdif] = imx_clk_gate2("spdif", "spdif_podf", base + 0x7c, 14); +diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c +index 78188159484d..79e629da1c92 100644 +--- a/arch/arm/mach-kirkwood/board-dt.c ++++ b/arch/arm/mach-kirkwood/board-dt.c +@@ -116,7 +116,7 @@ static void __init kirkwood_dt_init(void) + */ + writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG); + +- BUG_ON(mvebu_mbus_dt_init()); ++ BUG_ON(mvebu_mbus_dt_init(false)); + + kirkwood_l2_init(); + +diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c +index f6c9d1d85c14..79c3766a56fd 100644 +--- a/arch/arm/mach-mvebu/armada-370-xp.c ++++ b/arch/arm/mach-mvebu/armada-370-xp.c +@@ -41,7 +41,7 @@ static void __init armada_370_xp_timer_and_clk_init(void) + of_clk_init(NULL); + clocksource_of_init(); + coherency_init(); +- BUG_ON(mvebu_mbus_dt_init()); ++ BUG_ON(mvebu_mbus_dt_init(coherency_available())); + #ifdef CONFIG_CACHE_L2X0 + l2x0_of_init(0, ~0UL); + #endif +diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c +index c295c10f9217..49bad4d66fa2 100644 +--- a/arch/arm/mach-mvebu/coherency.c ++++ b/arch/arm/mach-mvebu/coherency.c +@@ -121,6 +121,20 @@ static struct notifier_block mvebu_hwcc_platform_nb = { + .notifier_call = mvebu_hwcc_platform_notifier, + }; + ++/* ++ * Keep track of whether we have IO hardware coherency enabled or not. ++ * On Armada 370's we will not be using it for example. We need to make ++ * that available [through coherency_available()] so the mbus controller ++ * doesn't enable the IO coherency bit in the attribute bits of the ++ * chip selects. ++ */ ++static int coherency_enabled; ++ ++int coherency_available(void) ++{ ++ return coherency_enabled; ++} ++ + int __init coherency_init(void) + { + struct device_node *np; +@@ -164,6 +178,7 @@ int __init coherency_init(void) + coherency_base = of_iomap(np, 0); + coherency_cpu_base = of_iomap(np, 1); + set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0); ++ coherency_enabled = 1; + of_node_put(np); + } + +diff --git a/arch/arm/mach-mvebu/coherency.h b/arch/arm/mach-mvebu/coherency.h +index 760226c41353..63e18c64a8e3 100644 +--- a/arch/arm/mach-mvebu/coherency.h ++++ b/arch/arm/mach-mvebu/coherency.h +@@ -17,6 +17,7 @@ + extern unsigned long coherency_phys_base; + + int set_cpu_coherent(unsigned int cpu_id, int smp_group_id); ++int coherency_available(void); + int coherency_init(void); + + #endif /* __MACH_370_XP_COHERENCY_H */ +diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h +index 00fbaa75dc7b..ea68925a4480 100644 +--- a/arch/arm64/include/asm/kvm_arm.h ++++ b/arch/arm64/include/asm/kvm_arm.h +@@ -18,6 +18,7 @@ + #ifndef __ARM64_KVM_ARM_H__ + #define __ARM64_KVM_ARM_H__ + ++#include + #include + + /* Hyp Configuration Register (HCR) bits */ +@@ -122,6 +123,17 @@ + #define VTCR_EL2_T0SZ_MASK 0x3f + #define VTCR_EL2_T0SZ_40B 24 + ++/* ++ * We configure the Stage-2 page tables to always restrict the IPA space to be ++ * 40 bits wide (T0SZ = 24). Systems with a PARange smaller than 40 bits are ++ * not known to exist and will break with this configuration. ++ * ++ * Note that when using 4K pages, we concatenate two first level page tables ++ * together. ++ * ++ * The magic numbers used for VTTBR_X in this patch can be found in Tables ++ * D4-23 and D4-25 in ARM DDI 0487A.b. ++ */ + #ifdef CONFIG_ARM64_64K_PAGES + /* + * Stage2 translation configuration: +@@ -151,9 +163,9 @@ + #endif + + #define VTTBR_BADDR_SHIFT (VTTBR_X - 1) +-#define VTTBR_BADDR_MASK (((1LLU << (40 - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT) +-#define VTTBR_VMID_SHIFT (48LLU) +-#define VTTBR_VMID_MASK (0xffLLU << VTTBR_VMID_SHIFT) ++#define VTTBR_BADDR_MASK (((UL(1) << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT) ++#define VTTBR_VMID_SHIFT (UL(48)) ++#define VTTBR_VMID_MASK (UL(0xFF) << VTTBR_VMID_SHIFT) + + /* Hyp System Trap Register */ + #define HSTR_EL2_TTEE (1 << 16) +@@ -176,13 +188,13 @@ + + /* Exception Syndrome Register (ESR) bits */ + #define ESR_EL2_EC_SHIFT (26) +-#define ESR_EL2_EC (0x3fU << ESR_EL2_EC_SHIFT) +-#define ESR_EL2_IL (1U << 25) ++#define ESR_EL2_EC (UL(0x3f) << ESR_EL2_EC_SHIFT) ++#define ESR_EL2_IL (UL(1) << 25) + #define ESR_EL2_ISS (ESR_EL2_IL - 1) + #define ESR_EL2_ISV_SHIFT (24) +-#define ESR_EL2_ISV (1U << ESR_EL2_ISV_SHIFT) ++#define ESR_EL2_ISV (UL(1) << ESR_EL2_ISV_SHIFT) + #define ESR_EL2_SAS_SHIFT (22) +-#define ESR_EL2_SAS (3U << ESR_EL2_SAS_SHIFT) ++#define ESR_EL2_SAS (UL(3) << ESR_EL2_SAS_SHIFT) + #define ESR_EL2_SSE (1 << 21) + #define ESR_EL2_SRT_SHIFT (16) + #define ESR_EL2_SRT_MASK (0x1f << ESR_EL2_SRT_SHIFT) +@@ -196,16 +208,16 @@ + #define ESR_EL2_FSC_TYPE (0x3c) + + #define ESR_EL2_CV_SHIFT (24) +-#define ESR_EL2_CV (1U << ESR_EL2_CV_SHIFT) ++#define ESR_EL2_CV (UL(1) << ESR_EL2_CV_SHIFT) + #define ESR_EL2_COND_SHIFT (20) +-#define ESR_EL2_COND (0xfU << ESR_EL2_COND_SHIFT) ++#define ESR_EL2_COND (UL(0xf) << ESR_EL2_COND_SHIFT) + + + #define FSC_FAULT (0x04) + #define FSC_PERM (0x0c) + + /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */ +-#define HPFAR_MASK (~0xFUL) ++#define HPFAR_MASK (~UL(0xf)) + + #define ESR_EL2_EC_UNKNOWN (0x00) + #define ESR_EL2_EC_WFI (0x01) +diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h +index dd8ecfc3f995..681cb9080100 100644 +--- a/arch/arm64/include/asm/kvm_emulate.h ++++ b/arch/arm64/include/asm/kvm_emulate.h +@@ -38,6 +38,11 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu); + void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr); + void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr); + ++static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) ++{ ++ vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; ++} ++ + static inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu) + { + return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pc; +diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h +index 8e138c7c53ac..0d51874c838f 100644 +--- a/arch/arm64/include/asm/kvm_mmu.h ++++ b/arch/arm64/include/asm/kvm_mmu.h +@@ -59,10 +59,9 @@ + #define KERN_TO_HYP(kva) ((unsigned long)kva - PAGE_OFFSET + HYP_PAGE_OFFSET) + + /* +- * Align KVM with the kernel's view of physical memory. Should be +- * 40bit IPA, with PGD being 8kB aligned in the 4KB page configuration. ++ * We currently only support a 40bit IPA. + */ +-#define KVM_PHYS_SHIFT PHYS_MASK_SHIFT ++#define KVM_PHYS_SHIFT (40) + #define KVM_PHYS_SIZE (1UL << KVM_PHYS_SHIFT) + #define KVM_PHYS_MASK (KVM_PHYS_SIZE - 1UL) + +@@ -75,6 +74,7 @@ int create_hyp_io_mappings(void *from, void *to, phys_addr_t); + void free_boot_hyp_pgd(void); + void free_hyp_pgds(void); + ++void stage2_unmap_vm(struct kvm *kvm); + int kvm_alloc_stage2_pgd(struct kvm *kvm); + void kvm_free_stage2_pgd(struct kvm *kvm); + int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, +@@ -93,19 +93,6 @@ void kvm_clear_hyp_idmap(void); + #define kvm_set_pte(ptep, pte) set_pte(ptep, pte) + #define kvm_set_pmd(pmdp, pmd) set_pmd(pmdp, pmd) + +-static inline bool kvm_is_write_fault(unsigned long esr) +-{ +- unsigned long esr_ec = esr >> ESR_EL2_EC_SHIFT; +- +- if (esr_ec == ESR_EL2_EC_IABT) +- return false; +- +- if ((esr & ESR_EL2_ISV) && !(esr & ESR_EL2_WNR)) +- return false; +- +- return true; +-} +- + static inline void kvm_clean_pgd(pgd_t *pgd) {} + static inline void kvm_clean_pmd_entry(pmd_t *pmd) {} + static inline void kvm_clean_pte(pte_t *pte) {} +diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c +index 08745578d54d..a8d81fa8c527 100644 +--- a/arch/arm64/kvm/guest.c ++++ b/arch/arm64/kvm/guest.c +@@ -38,7 +38,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { + + int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) + { +- vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; + return 0; + } + +diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c +index 3974881388bb..b76159a153a5 100644 +--- a/arch/arm64/mm/dma-mapping.c ++++ b/arch/arm64/mm/dma-mapping.c +@@ -54,8 +54,7 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size, + + *dma_handle = phys_to_dma(dev, page_to_phys(page)); + addr = page_address(page); +- if (flags & __GFP_ZERO) +- memset(addr, 0, size); ++ memset(addr, 0, size); + return addr; + } else { + return swiotlb_alloc_coherent(dev, size, dma_handle, flags); +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index 2f645c90e4d8..5dab54accc56 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -160,7 +160,7 @@ config SBUS + + config NEED_DMA_MAP_STATE + def_bool y +- depends on X86_64 || INTEL_IOMMU || DMA_API_DEBUG ++ depends on X86_64 || INTEL_IOMMU || DMA_API_DEBUG || SWIOTLB + + config NEED_SG_DMA_LENGTH + def_bool y +diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c +index 18f739129e72..43a07bf48dea 100644 +--- a/arch/x86/kernel/cpu/microcode/intel_early.c ++++ b/arch/x86/kernel/cpu/microcode/intel_early.c +@@ -321,7 +321,7 @@ get_matching_model_microcode(int cpu, unsigned long start, + unsigned int mc_saved_count = mc_saved_data->mc_saved_count; + int i; + +- while (leftover) { ++ while (leftover && mc_saved_count < ARRAY_SIZE(mc_saved_tmp)) { + mc_header = (struct microcode_header_intel *)ucode_ptr; + + mc_size = get_totalsize(mc_header); +diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c +index a1f5b1866cbe..490fee15fea5 100644 +--- a/arch/x86/kernel/kprobes/core.c ++++ b/arch/x86/kernel/kprobes/core.c +@@ -326,13 +326,16 @@ int __kprobes __copy_instruction(u8 *dest, u8 *src) + { + struct insn insn; + kprobe_opcode_t buf[MAX_INSN_SIZE]; ++ int length; + + kernel_insn_init(&insn, (void *)recover_probed_instruction(buf, (unsigned long)src)); + insn_get_length(&insn); ++ length = insn.length; ++ + /* Another subsystem puts a breakpoint, failed to recover */ + if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION) + return 0; +- memcpy(dest, insn.kaddr, insn.length); ++ memcpy(dest, insn.kaddr, length); + + #ifdef CONFIG_X86_64 + if (insn_rip_relative(&insn)) { +@@ -362,7 +365,7 @@ int __kprobes __copy_instruction(u8 *dest, u8 *src) + *(s32 *) disp = (s32) newdisp; + } + #endif +- return insn.length; ++ return length; + } + + static int __kprobes arch_copy_kprobe(struct kprobe *p) +diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c +index 9643eda60a52..074633411ea8 100644 +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -495,8 +495,10 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu) + { + struct vcpu_svm *svm = to_svm(vcpu); + +- if (svm->vmcb->control.next_rip != 0) ++ if (svm->vmcb->control.next_rip != 0) { ++ WARN_ON(!static_cpu_has(X86_FEATURE_NRIPS)); + svm->next_rip = svm->vmcb->control.next_rip; ++ } + + if (!svm->next_rip) { + if (emulate_instruction(vcpu, EMULTYPE_SKIP) != +@@ -4246,7 +4248,9 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu, + break; + } + +- vmcb->control.next_rip = info->next_rip; ++ /* TODO: Advertise NRIPS to guest hypervisor unconditionally */ ++ if (static_cpu_has(X86_FEATURE_NRIPS)) ++ vmcb->control.next_rip = info->next_rip; + vmcb->control.exit_code = icpt_info.exit_code; + vmexit = nested_svm_exit_handled(svm); + +diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c +index e990deed2d33..1aa0130a63d5 100644 +--- a/drivers/bus/mvebu-mbus.c ++++ b/drivers/bus/mvebu-mbus.c +@@ -701,7 +701,6 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus, + phys_addr_t sdramwins_phys_base, + size_t sdramwins_size) + { +- struct device_node *np; + int win; + + mbus->mbuswins_base = ioremap(mbuswins_phys_base, mbuswins_size); +@@ -714,12 +713,6 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus, + return -ENOMEM; + } + +- np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"); +- if (np) { +- mbus->hw_io_coherency = 1; +- of_node_put(np); +- } +- + for (win = 0; win < mbus->soc->num_wins; win++) + mvebu_mbus_disable_window(mbus, win); + +@@ -889,7 +882,7 @@ static void __init mvebu_mbus_get_pcie_resources(struct device_node *np, + } + } + +-int __init mvebu_mbus_dt_init(void) ++int __init mvebu_mbus_dt_init(bool is_coherent) + { + struct resource mbuswins_res, sdramwins_res; + struct device_node *np, *controller; +@@ -928,6 +921,8 @@ int __init mvebu_mbus_dt_init(void) + return -EINVAL; + } + ++ mbus_state.hw_io_coherency = is_coherent; ++ + /* Get optional pcie-{mem,io}-aperture properties */ + mvebu_mbus_get_pcie_resources(np, &mbus_state.pcie_mem_aperture, + &mbus_state.pcie_io_aperture); +diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c +index c611bcc01f7e..3e623ab5e315 100644 +--- a/drivers/edac/sb_edac.c ++++ b/drivers/edac/sb_edac.c +@@ -765,7 +765,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + u32 reg; + u64 limit, prv = 0; + u64 tmp_mb; +- u32 mb, kb; ++ u32 gb, mb; + u32 rir_way; + + /* +@@ -775,15 +775,17 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + pvt->tolm = pvt->info.get_tolm(pvt); + tmp_mb = (1 + pvt->tolm) >> 20; + +- mb = div_u64_rem(tmp_mb, 1000, &kb); +- edac_dbg(0, "TOLM: %u.%03u GB (0x%016Lx)\n", mb, kb, (u64)pvt->tolm); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); ++ edac_dbg(0, "TOLM: %u.%03u GB (0x%016Lx)\n", ++ gb, (mb*1000)/1024, (u64)pvt->tolm); + + /* Address range is already 45:25 */ + pvt->tohm = pvt->info.get_tohm(pvt); + tmp_mb = (1 + pvt->tohm) >> 20; + +- mb = div_u64_rem(tmp_mb, 1000, &kb); +- edac_dbg(0, "TOHM: %u.%03u GB (0x%016Lx)\n", mb, kb, (u64)pvt->tohm); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); ++ edac_dbg(0, "TOHM: %u.%03u GB (0x%016Lx)\n", ++ gb, (mb*1000)/1024, (u64)pvt->tohm); + + /* + * Step 2) Get SAD range and SAD Interleave list +@@ -805,11 +807,11 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + break; + + tmp_mb = (limit + 1) >> 20; +- mb = div_u64_rem(tmp_mb, 1000, &kb); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); + edac_dbg(0, "SAD#%d %s up to %u.%03u GB (0x%016Lx) Interleave: %s reg=0x%08x\n", + n_sads, + get_dram_attr(reg), +- mb, kb, ++ gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, + INTERLEAVE_MODE(reg) ? "8:6" : "[8:6]XOR[18:16]", + reg); +@@ -840,9 +842,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + break; + tmp_mb = (limit + 1) >> 20; + +- mb = div_u64_rem(tmp_mb, 1000, &kb); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); + edac_dbg(0, "TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n", +- n_tads, mb, kb, ++ n_tads, gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, + (u32)TAD_SOCK(reg), + (u32)TAD_CH(reg), +@@ -865,10 +867,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + tad_ch_nilv_offset[j], + ®); + tmp_mb = TAD_OFFSET(reg) >> 20; +- mb = div_u64_rem(tmp_mb, 1000, &kb); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); + edac_dbg(0, "TAD CH#%d, offset #%d: %u.%03u GB (0x%016Lx), reg=0x%08x\n", + i, j, +- mb, kb, ++ gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, + reg); + } +@@ -890,10 +892,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + + tmp_mb = RIR_LIMIT(reg) >> 20; + rir_way = 1 << RIR_WAY(reg); +- mb = div_u64_rem(tmp_mb, 1000, &kb); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); + edac_dbg(0, "CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n", + i, j, +- mb, kb, ++ gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, + rir_way, + reg); +@@ -904,10 +906,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + ®); + tmp_mb = RIR_OFFSET(reg) << 6; + +- mb = div_u64_rem(tmp_mb, 1000, &kb); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); + edac_dbg(0, "CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n", + i, j, k, +- mb, kb, ++ gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, + (u32)RIR_RNK_TGT(reg), + reg); +@@ -945,7 +947,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, + u8 ch_way, sck_way, pkg, sad_ha = 0; + u32 tad_offset; + u32 rir_way; +- u32 mb, kb; ++ u32 mb, gb; + u64 ch_addr, offset, limit = 0, prv = 0; + + +@@ -1183,10 +1185,10 @@ static int get_memory_error_data(struct mem_ctl_info *mci, + continue; + + limit = RIR_LIMIT(reg); +- mb = div_u64_rem(limit >> 20, 1000, &kb); ++ gb = div_u64_rem(limit >> 20, 1024, &mb); + edac_dbg(0, "RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n", + n_rir, +- mb, kb, ++ gb, (mb*1000)/1024, + limit, + 1 << RIR_WAY(reg)); + if (ch_addr <= limit) +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c +index 019a04a31384..a467261b10b9 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c +@@ -810,8 +810,11 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) + tx_desc->ctrl.fence_size = (real_size / 16) & 0x3f; + tx_desc->ctrl.srcrb_flags = priv->ctrl_flags; + if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { +- tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM | +- MLX4_WQE_CTRL_TCP_UDP_CSUM); ++ if (!skb->encapsulation) ++ tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM | ++ MLX4_WQE_CTRL_TCP_UDP_CSUM); ++ else ++ tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM); + ring->tx_csum++; + } + +diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c +index 528bff5ec91f..85d370e1ca79 100644 +--- a/drivers/scsi/hpsa.c ++++ b/drivers/scsi/hpsa.c +@@ -3984,10 +3984,6 @@ static int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev) + + /* Save the PCI command register */ + pci_read_config_word(pdev, 4, &command_register); +- /* Turn the board off. This is so that later pci_restore_state() +- * won't turn the board on before the rest of config space is ready. +- */ +- pci_disable_device(pdev); + pci_save_state(pdev); + + /* find the first memory BAR, so we can find the cfg table */ +@@ -4035,11 +4031,6 @@ static int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev) + goto unmap_cfgtable; + + pci_restore_state(pdev); +- rc = pci_enable_device(pdev); +- if (rc) { +- dev_warn(&pdev->dev, "failed to enable device.\n"); +- goto unmap_cfgtable; +- } + pci_write_config_word(pdev, 4, command_register); + + /* Some devices (notably the HP Smart Array 5i Controller) +@@ -4525,6 +4516,23 @@ static int hpsa_init_reset_devices(struct pci_dev *pdev) + if (!reset_devices) + return 0; + ++ /* kdump kernel is loading, we don't know in which state is ++ * the pci interface. The dev->enable_cnt is equal zero ++ * so we call enable+disable, wait a while and switch it on. ++ */ ++ rc = pci_enable_device(pdev); ++ if (rc) { ++ dev_warn(&pdev->dev, "Failed to enable PCI device\n"); ++ return -ENODEV; ++ } ++ pci_disable_device(pdev); ++ msleep(260); /* a randomly chosen number */ ++ rc = pci_enable_device(pdev); ++ if (rc) { ++ dev_warn(&pdev->dev, "failed to enable device.\n"); ++ return -ENODEV; ++ } ++ pci_set_master(pdev); + /* Reset the controller with a PCI power-cycle or via doorbell */ + rc = hpsa_kdump_hard_reset_controller(pdev); + +@@ -4533,10 +4541,11 @@ static int hpsa_init_reset_devices(struct pci_dev *pdev) + * "performant mode". Or, it might be 640x, which can't reset + * due to concerns about shared bbwc between 6402/6404 pair. + */ +- if (rc == -ENOTSUPP) +- return rc; /* just try to do the kdump anyhow. */ +- if (rc) +- return -ENODEV; ++ if (rc) { ++ if (rc != -ENOTSUPP) /* just try to do the kdump anyhow. */ ++ rc = -ENODEV; ++ goto out_disable; ++ } + + /* Now try to get the controller to respond to a no-op */ + dev_warn(&pdev->dev, "Waiting for controller to respond to no-op\n"); +@@ -4547,7 +4556,11 @@ static int hpsa_init_reset_devices(struct pci_dev *pdev) + dev_warn(&pdev->dev, "no-op failed%s\n", + (i < 11 ? "; re-trying" : "")); + } +- return 0; ++ ++out_disable: ++ ++ pci_disable_device(pdev); ++ return rc; + } + + static int hpsa_allocate_cmd_pool(struct ctlr_info *h) +@@ -4690,6 +4703,7 @@ static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h) + iounmap(h->transtable); + if (h->cfgtable) + iounmap(h->cfgtable); ++ pci_disable_device(h->pdev); + pci_release_regions(h->pdev); + kfree(h); + } +diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c +index 93de3ba994e7..f8ffee4562d3 100644 +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -2963,7 +2963,7 @@ done: + */ + if (!p->leave_spinning) + btrfs_set_path_blocking(p); +- if (ret < 0) ++ if (ret < 0 && !p->skip_release_on_error) + btrfs_release_path(p); + return ret; + } +diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h +index d3511cc17091..3b39eb4cb309 100644 +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -608,6 +608,7 @@ struct btrfs_path { + unsigned int skip_locking:1; + unsigned int leave_spinning:1; + unsigned int search_commit_root:1; ++ unsigned int skip_release_on_error:1; + }; + + /* +@@ -3609,6 +3610,10 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, + int verify_dir_item(struct btrfs_root *root, + struct extent_buffer *leaf, + struct btrfs_dir_item *dir_item); ++struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, ++ struct btrfs_path *path, ++ const char *name, ++ int name_len); + + /* orphan.c */ + int btrfs_insert_orphan_item(struct btrfs_trans_handle *trans, +diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c +index a0691df5dcea..9521a93b5303 100644 +--- a/fs/btrfs/dir-item.c ++++ b/fs/btrfs/dir-item.c +@@ -21,10 +21,6 @@ + #include "hash.h" + #include "transaction.h" + +-static struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, +- struct btrfs_path *path, +- const char *name, int name_len); +- + /* + * insert a name into a directory, doing overflow properly if there is a hash + * collision. data_size indicates how big the item inserted should be. On +@@ -383,9 +379,9 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, + * this walks through all the entries in a dir item and finds one + * for a specific name. + */ +-static struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, +- struct btrfs_path *path, +- const char *name, int name_len) ++struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, ++ struct btrfs_path *path, ++ const char *name, int name_len) + { + struct btrfs_dir_item *dir_item; + unsigned long name_ptr; +diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c +index 488e987c3374..618e86ceede7 100644 +--- a/fs/btrfs/xattr.c ++++ b/fs/btrfs/xattr.c +@@ -29,6 +29,7 @@ + #include "xattr.h" + #include "disk-io.h" + #include "props.h" ++#include "locking.h" + + + ssize_t __btrfs_getxattr(struct inode *inode, const char *name, +@@ -91,7 +92,7 @@ static int do_setxattr(struct btrfs_trans_handle *trans, + struct inode *inode, const char *name, + const void *value, size_t size, int flags) + { +- struct btrfs_dir_item *di; ++ struct btrfs_dir_item *di = NULL; + struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_path *path; + size_t name_len = strlen(name); +@@ -103,84 +104,119 @@ static int do_setxattr(struct btrfs_trans_handle *trans, + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; ++ path->skip_release_on_error = 1; ++ ++ if (!value) { ++ di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), ++ name, name_len, -1); ++ if (!di && (flags & XATTR_REPLACE)) ++ ret = -ENODATA; ++ else if (di) ++ ret = btrfs_delete_one_dir_name(trans, root, path, di); ++ goto out; ++ } + ++ /* ++ * For a replace we can't just do the insert blindly. ++ * Do a lookup first (read-only btrfs_search_slot), and return if xattr ++ * doesn't exist. If it exists, fall down below to the insert/replace ++ * path - we can't race with a concurrent xattr delete, because the VFS ++ * locks the inode's i_mutex before calling setxattr or removexattr. ++ */ + if (flags & XATTR_REPLACE) { +- di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), name, +- name_len, -1); +- if (IS_ERR(di)) { +- ret = PTR_ERR(di); +- goto out; +- } else if (!di) { ++ ASSERT(mutex_is_locked(&inode->i_mutex)); ++ di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode), ++ name, name_len, 0); ++ if (!di) { + ret = -ENODATA; + goto out; + } +- ret = btrfs_delete_one_dir_name(trans, root, path, di); +- if (ret) +- goto out; + btrfs_release_path(path); ++ di = NULL; ++ } + ++ ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode), ++ name, name_len, value, size); ++ if (ret == -EOVERFLOW) { + /* +- * remove the attribute ++ * We have an existing item in a leaf, split_leaf couldn't ++ * expand it. That item might have or not a dir_item that ++ * matches our target xattr, so lets check. + */ +- if (!value) +- goto out; +- } else { +- di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode), +- name, name_len, 0); +- if (IS_ERR(di)) { +- ret = PTR_ERR(di); ++ ret = 0; ++ btrfs_assert_tree_locked(path->nodes[0]); ++ di = btrfs_match_dir_item_name(root, path, name, name_len); ++ if (!di && !(flags & XATTR_REPLACE)) { ++ ret = -ENOSPC; + goto out; + } +- if (!di && !value) +- goto out; +- btrfs_release_path(path); ++ } else if (ret == -EEXIST) { ++ ret = 0; ++ di = btrfs_match_dir_item_name(root, path, name, name_len); ++ ASSERT(di); /* logic error */ ++ } else if (ret) { ++ goto out; + } + +-again: +- ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode), +- name, name_len, value, size); +- /* +- * If we're setting an xattr to a new value but the new value is say +- * exactly BTRFS_MAX_XATTR_SIZE, we could end up with EOVERFLOW getting +- * back from split_leaf. This is because it thinks we'll be extending +- * the existing item size, but we're asking for enough space to add the +- * item itself. So if we get EOVERFLOW just set ret to EEXIST and let +- * the rest of the function figure it out. +- */ +- if (ret == -EOVERFLOW) ++ if (di && (flags & XATTR_CREATE)) { + ret = -EEXIST; ++ goto out; ++ } + +- if (ret == -EEXIST) { +- if (flags & XATTR_CREATE) +- goto out; ++ if (di) { + /* +- * We can't use the path we already have since we won't have the +- * proper locking for a delete, so release the path and +- * re-lookup to delete the thing. ++ * We're doing a replace, and it must be atomic, that is, at ++ * any point in time we have either the old or the new xattr ++ * value in the tree. We don't want readers (getxattr and ++ * listxattrs) to miss a value, this is specially important ++ * for ACLs. + */ +- btrfs_release_path(path); +- di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), +- name, name_len, -1); +- if (IS_ERR(di)) { +- ret = PTR_ERR(di); +- goto out; +- } else if (!di) { +- /* Shouldn't happen but just in case... */ +- btrfs_release_path(path); +- goto again; ++ const int slot = path->slots[0]; ++ struct extent_buffer *leaf = path->nodes[0]; ++ const u16 old_data_len = btrfs_dir_data_len(leaf, di); ++ const u32 item_size = btrfs_item_size_nr(leaf, slot); ++ const u32 data_size = sizeof(*di) + name_len + size; ++ struct btrfs_item *item; ++ unsigned long data_ptr; ++ char *ptr; ++ ++ if (size > old_data_len) { ++ if (btrfs_leaf_free_space(root, leaf) < ++ (size - old_data_len)) { ++ ret = -ENOSPC; ++ goto out; ++ } + } + +- ret = btrfs_delete_one_dir_name(trans, root, path, di); +- if (ret) +- goto out; ++ if (old_data_len + name_len + sizeof(*di) == item_size) { ++ /* No other xattrs packed in the same leaf item. */ ++ if (size > old_data_len) ++ btrfs_extend_item(root, path, ++ size - old_data_len); ++ else if (size < old_data_len) ++ btrfs_truncate_item(root, path, data_size, 1); ++ } else { ++ /* There are other xattrs packed in the same item. */ ++ ret = btrfs_delete_one_dir_name(trans, root, path, di); ++ if (ret) ++ goto out; ++ btrfs_extend_item(root, path, data_size); ++ } + ++ item = btrfs_item_nr(slot); ++ ptr = btrfs_item_ptr(leaf, slot, char); ++ ptr += btrfs_item_size(leaf, item) - data_size; ++ di = (struct btrfs_dir_item *)ptr; ++ btrfs_set_dir_data_len(leaf, di, size); ++ data_ptr = ((unsigned long)(di + 1)) + name_len; ++ write_extent_buffer(leaf, value, data_ptr, size); ++ btrfs_mark_buffer_dirty(leaf); ++ } else { + /* +- * We have a value to set, so go back and try to insert it now. ++ * Insert, and we had space for the xattr, so path->slots[0] is ++ * where our xattr dir_item is and btrfs_insert_xattr_item() ++ * filled it. + */ +- if (value) { +- btrfs_release_path(path); +- goto again; +- } + } + out: + btrfs_free_path(path); +diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c +index 7fe30f655aa5..35f54bc96519 100644 +--- a/fs/ocfs2/file.c ++++ b/fs/ocfs2/file.c +@@ -2478,9 +2478,7 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, + struct address_space *mapping = out->f_mapping; + struct inode *inode = mapping->host; + struct splice_desc sd = { +- .total_len = len, + .flags = flags, +- .pos = *ppos, + .u.file = out, + }; + +@@ -2490,6 +2488,12 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, + out->f_path.dentry->d_name.len, + out->f_path.dentry->d_name.name, len); + ++ ret = generic_write_checks(out, ppos, &len, 0); ++ if (ret) ++ return ret; ++ sd.total_len = len; ++ sd.pos = *ppos; ++ + pipe_lock(pipe); + + splice_from_pipe_begin(&sd); +diff --git a/fs/splice.c b/fs/splice.c +index 12028fa41def..f345d53f94da 100644 +--- a/fs/splice.c ++++ b/fs/splice.c +@@ -1012,13 +1012,17 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, + struct address_space *mapping = out->f_mapping; + struct inode *inode = mapping->host; + struct splice_desc sd = { +- .total_len = len, + .flags = flags, +- .pos = *ppos, + .u.file = out, + }; + ssize_t ret; + ++ ret = generic_write_checks(out, ppos, &len, S_ISBLK(inode->i_mode)); ++ if (ret) ++ return ret; ++ sd.total_len = len; ++ sd.pos = *ppos; ++ + pipe_lock(pipe); + + splice_from_pipe_begin(&sd); +diff --git a/include/linux/mbus.h b/include/linux/mbus.h +index 345b8c53b897..550c88fb0267 100644 +--- a/include/linux/mbus.h ++++ b/include/linux/mbus.h +@@ -73,6 +73,6 @@ int mvebu_mbus_del_window(phys_addr_t base, size_t size); + int mvebu_mbus_init(const char *soc, phys_addr_t mbus_phys_base, + size_t mbus_size, phys_addr_t sdram_phys_base, + size_t sdram_size); +-int mvebu_mbus_dt_init(void); ++int mvebu_mbus_dt_init(bool is_coherent); + + #endif /* __LINUX_MBUS_H */ +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index c68e5e0628df..99de2409f731 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -855,7 +855,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, + + if (nla[NFTA_CHAIN_POLICY]) { + if ((chain != NULL && +- !(chain->flags & NFT_BASE_CHAIN)) || ++ !(chain->flags & NFT_BASE_CHAIN))) ++ return -EOPNOTSUPP; ++ ++ if (chain == NULL && + nla[NFTA_CHAIN_HOOK] == NULL) + return -EOPNOTSUPP; + +diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c +index 9e287cb56a04..54330fb5efaf 100644 +--- a/net/netfilter/nfnetlink_cthelper.c ++++ b/net/netfilter/nfnetlink_cthelper.c +@@ -77,6 +77,9 @@ nfnl_cthelper_parse_tuple(struct nf_conntrack_tuple *tuple, + if (!tb[NFCTH_TUPLE_L3PROTONUM] || !tb[NFCTH_TUPLE_L4PROTONUM]) + return -EINVAL; + ++ /* Not all fields are initialized so first zero the tuple */ ++ memset(tuple, 0, sizeof(struct nf_conntrack_tuple)); ++ + tuple->src.l3num = ntohs(nla_get_be16(tb[NFCTH_TUPLE_L3PROTONUM])); + tuple->dst.protonum = nla_get_u8(tb[NFCTH_TUPLE_L4PROTONUM]); + +@@ -86,7 +89,7 @@ nfnl_cthelper_parse_tuple(struct nf_conntrack_tuple *tuple, + static int + nfnl_cthelper_from_nlattr(struct nlattr *attr, struct nf_conn *ct) + { +- const struct nf_conn_help *help = nfct_help(ct); ++ struct nf_conn_help *help = nfct_help(ct); + + if (attr == NULL) + return -EINVAL; +@@ -94,7 +97,7 @@ nfnl_cthelper_from_nlattr(struct nlattr *attr, struct nf_conn *ct) + if (help->helper->data_len == 0) + return -EINVAL; + +- memcpy(&help->data, nla_data(attr), help->helper->data_len); ++ memcpy(help->data, nla_data(attr), help->helper->data_len); + return 0; + } + +diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c +index 7350723aeb15..969589590814 100644 +--- a/net/netfilter/nft_compat.c ++++ b/net/netfilter/nft_compat.c +@@ -82,6 +82,9 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par, + entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0; + break; + case AF_INET6: ++ if (proto) ++ entry->e6.ipv6.flags |= IP6T_F_PROTO; ++ + entry->e6.ipv6.proto = proto; + entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; + break; +@@ -313,6 +316,9 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx, + entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0; + break; + case AF_INET6: ++ if (proto) ++ entry->e6.ipv6.flags |= IP6T_F_PROTO; ++ + entry->e6.ipv6.proto = proto; + entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; + break; +diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c +index 1316e558db64..c324a52bb407 100644 +--- a/virt/kvm/arm/vgic.c ++++ b/virt/kvm/arm/vgic.c +@@ -674,7 +674,7 @@ static bool read_set_clear_sgi_pend_reg(struct kvm_vcpu *vcpu, + { + struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + int sgi; +- int min_sgi = (offset & ~0x3) * 4; ++ int min_sgi = (offset & ~0x3); + int max_sgi = min_sgi + 3; + int vcpu_id = vcpu->vcpu_id; + u32 reg = 0; +@@ -695,7 +695,7 @@ static bool write_set_clear_sgi_pend_reg(struct kvm_vcpu *vcpu, + { + struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + int sgi; +- int min_sgi = (offset & ~0x3) * 4; ++ int min_sgi = (offset & ~0x3); + int max_sgi = min_sgi + 3; + int vcpu_id = vcpu->vcpu_id; + u32 reg; +@@ -1387,7 +1387,8 @@ out: + int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num, + bool level) + { +- if (vgic_update_irq_state(kvm, cpuid, irq_num, level)) ++ if (likely(vgic_initialized(kvm)) && ++ vgic_update_irq_state(kvm, cpuid, irq_num, level)) + vgic_kick_vcpus(kvm); + + return 0; +@@ -1610,7 +1611,7 @@ out: + + int kvm_vgic_create(struct kvm *kvm) + { +- int i, vcpu_lock_idx = -1, ret = 0; ++ int i, vcpu_lock_idx = -1, ret; + struct kvm_vcpu *vcpu; + + mutex_lock(&kvm->lock); +@@ -1625,6 +1626,7 @@ int kvm_vgic_create(struct kvm *kvm) + * vcpu->mutex. By grabbing the vcpu->mutex of all VCPUs we ensure + * that no other VCPUs are run while we create the vgic. + */ ++ ret = -EBUSY; + kvm_for_each_vcpu(i, vcpu, kvm) { + if (!mutex_trylock(&vcpu->mutex)) + goto out_unlock; +@@ -1632,11 +1634,10 @@ int kvm_vgic_create(struct kvm *kvm) + } + + kvm_for_each_vcpu(i, vcpu, kvm) { +- if (vcpu->arch.has_run_once) { +- ret = -EBUSY; ++ if (vcpu->arch.has_run_once) + goto out_unlock; +- } + } ++ ret = 0; + + spin_lock_init(&kvm->arch.vgic.lock); + kvm->arch.vgic.vctrl_base = vgic_vctrl_base; diff --git a/patch/kernel/cubox-default/patch-3.14.47-48.patch b/patch/kernel/cubox-default/patch-3.14.47-48.patch new file mode 100644 index 000000000..b3cd94d1a --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.47-48.patch @@ -0,0 +1,1019 @@ +diff --git a/Makefile b/Makefile +index f9041e6d4d19..25393e89051c 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 47 ++SUBLEVEL = 48 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h +index 9f7923193cda..7d35af3f3752 100644 +--- a/arch/arm/include/asm/kvm_mmu.h ++++ b/arch/arm/include/asm/kvm_mmu.h +@@ -117,13 +117,14 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd) + (__boundary - 1 < (end) - 1)? __boundary: (end); \ + }) + ++#define kvm_pgd_index(addr) pgd_index(addr) ++ + static inline bool kvm_page_empty(void *ptr) + { + struct page *ptr_page = virt_to_page(ptr); + return page_count(ptr_page) == 1; + } + +- + #define kvm_pte_table_empty(ptep) kvm_page_empty(ptep) + #define kvm_pmd_table_empty(pmdp) kvm_page_empty(pmdp) + #define kvm_pud_table_empty(pudp) (0) +diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c +index 2e74a617147d..f6a52a2a3724 100644 +--- a/arch/arm/kvm/arm.c ++++ b/arch/arm/kvm/arm.c +@@ -441,6 +441,7 @@ static void update_vttbr(struct kvm *kvm) + + static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) + { ++ struct kvm *kvm = vcpu->kvm; + int ret; + + if (likely(vcpu->arch.has_run_once)) +@@ -452,12 +453,20 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) + * Initialize the VGIC before running a vcpu the first time on + * this VM. + */ +- if (unlikely(!vgic_initialized(vcpu->kvm))) { +- ret = kvm_vgic_init(vcpu->kvm); ++ if (unlikely(!vgic_initialized(kvm))) { ++ ret = kvm_vgic_init(kvm); + if (ret) + return ret; + } + ++ /* ++ * Enable the arch timers only if we have an in-kernel VGIC ++ * and it has been properly initialized, since we cannot handle ++ * interrupts from the virtual timer with a userspace gic. ++ */ ++ if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) ++ kvm_timer_enable(kvm); ++ + return 0; + } + +diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S +index 0d68d4073068..a1467e7689f5 100644 +--- a/arch/arm/kvm/interrupts.S ++++ b/arch/arm/kvm/interrupts.S +@@ -159,13 +159,9 @@ __kvm_vcpu_return: + @ Don't trap coprocessor accesses for host kernel + set_hstr vmexit + set_hdcr vmexit +- set_hcptr vmexit, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11)) ++ set_hcptr vmexit, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11)), after_vfp_restore + + #ifdef CONFIG_VFPv3 +- @ Save floating point registers we if let guest use them. +- tst r2, #(HCPTR_TCP(10) | HCPTR_TCP(11)) +- bne after_vfp_restore +- + @ Switch VFP/NEON hardware state to the host's + add r7, vcpu, #VCPU_VFP_GUEST + store_vfp_state r7 +@@ -177,6 +173,8 @@ after_vfp_restore: + @ Restore FPEXC_EN which we clobbered on entry + pop {r2} + VFPFMXR FPEXC, r2 ++#else ++after_vfp_restore: + #endif + + @ Reset Hyp-role +@@ -467,7 +465,7 @@ switch_to_guest_vfp: + push {r3-r7} + + @ NEON/VFP used. Turn on VFP access. +- set_hcptr vmexit, (HCPTR_TCP(10) | HCPTR_TCP(11)) ++ set_hcptr vmtrap, (HCPTR_TCP(10) | HCPTR_TCP(11)) + + @ Switch VFP/NEON hardware state to the guest's + add r7, r0, #VCPU_VFP_HOST +diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S +index 76af93025574..2973b2d342fa 100644 +--- a/arch/arm/kvm/interrupts_head.S ++++ b/arch/arm/kvm/interrupts_head.S +@@ -578,8 +578,13 @@ vcpu .req r0 @ vcpu pointer always in r0 + .endm + + /* Configures the HCPTR (Hyp Coprocessor Trap Register) on entry/return +- * (hardware reset value is 0). Keep previous value in r2. */ +-.macro set_hcptr operation, mask ++ * (hardware reset value is 0). Keep previous value in r2. ++ * An ISB is emited on vmexit/vmtrap, but executed on vmexit only if ++ * VFP wasn't already enabled (always executed on vmtrap). ++ * If a label is specified with vmexit, it is branched to if VFP wasn't ++ * enabled. ++ */ ++.macro set_hcptr operation, mask, label = none + mrc p15, 4, r2, c1, c1, 2 + ldr r3, =\mask + .if \operation == vmentry +@@ -588,6 +593,17 @@ vcpu .req r0 @ vcpu pointer always in r0 + bic r3, r2, r3 @ Don't trap defined coproc-accesses + .endif + mcr p15, 4, r3, c1, c1, 2 ++ .if \operation != vmentry ++ .if \operation == vmexit ++ tst r2, #(HCPTR_TCP(10) | HCPTR_TCP(11)) ++ beq 1f ++ .endif ++ isb ++ .if \label != none ++ b \label ++ .endif ++1: ++ .endif + .endm + + /* Configures the HDCR (Hyp Debug Configuration Register) on entry/return +diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c +index 524b4b57f650..c612e37166ad 100644 +--- a/arch/arm/kvm/mmu.c ++++ b/arch/arm/kvm/mmu.c +@@ -194,7 +194,7 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp, + phys_addr_t addr = start, end = start + size; + phys_addr_t next; + +- pgd = pgdp + pgd_index(addr); ++ pgd = pgdp + kvm_pgd_index(addr); + do { + next = kvm_pgd_addr_end(addr, end); + if (!pgd_none(*pgd)) +@@ -264,7 +264,7 @@ static void stage2_flush_memslot(struct kvm *kvm, + phys_addr_t next; + pgd_t *pgd; + +- pgd = kvm->arch.pgd + pgd_index(addr); ++ pgd = kvm->arch.pgd + kvm_pgd_index(addr); + do { + next = kvm_pgd_addr_end(addr, end); + stage2_flush_puds(kvm, pgd, addr, next); +@@ -649,7 +649,7 @@ static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache + pud_t *pud; + pmd_t *pmd; + +- pgd = kvm->arch.pgd + pgd_index(addr); ++ pgd = kvm->arch.pgd + kvm_pgd_index(addr); + pud = pud_offset(pgd, addr); + if (pud_none(*pud)) { + if (!cache) +diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h +index 681cb9080100..91f33c2051f2 100644 +--- a/arch/arm64/include/asm/kvm_emulate.h ++++ b/arch/arm64/include/asm/kvm_emulate.h +@@ -41,6 +41,8 @@ void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr); + static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) + { + vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; ++ if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) ++ vcpu->arch.hcr_el2 &= ~HCR_RW; + } + + static inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu) +diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h +index 0d51874c838f..15a8a861264a 100644 +--- a/arch/arm64/include/asm/kvm_mmu.h ++++ b/arch/arm64/include/asm/kvm_mmu.h +@@ -69,6 +69,8 @@ + #define PTRS_PER_S2_PGD (1 << (KVM_PHYS_SHIFT - PGDIR_SHIFT)) + #define S2_PGD_ORDER get_order(PTRS_PER_S2_PGD * sizeof(pgd_t)) + ++#define kvm_pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1)) ++ + int create_hyp_mappings(void *from, void *to); + int create_hyp_io_mappings(void *from, void *to, phys_addr_t); + void free_boot_hyp_pgd(void); +diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S +index 5dfc8331c385..3aaf3bc4ad8a 100644 +--- a/arch/arm64/kvm/hyp.S ++++ b/arch/arm64/kvm/hyp.S +@@ -629,6 +629,7 @@ ENTRY(__kvm_tlb_flush_vmid_ipa) + * Instead, we invalidate Stage-2 for this IPA, and the + * whole of Stage-1. Weep... + */ ++ lsr x1, x1, #12 + tlbi ipas2e1is, x1 + /* + * We have to ensure completion of the invalidation at Stage-2, +diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c +index 70a7816535cd..0b4326578985 100644 +--- a/arch/arm64/kvm/reset.c ++++ b/arch/arm64/kvm/reset.c +@@ -90,7 +90,6 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) + if (!cpu_has_32bit_el1()) + return -EINVAL; + cpu_reset = &default_regs_reset32; +- vcpu->arch.hcr_el2 &= ~HCR_RW; + } else { + cpu_reset = &default_regs_reset; + } +diff --git a/arch/mips/include/asm/mach-generic/spaces.h b/arch/mips/include/asm/mach-generic/spaces.h +index 9488fa5f8866..afc96ecb9004 100644 +--- a/arch/mips/include/asm/mach-generic/spaces.h ++++ b/arch/mips/include/asm/mach-generic/spaces.h +@@ -94,7 +94,11 @@ + #endif + + #ifndef FIXADDR_TOP ++#ifdef CONFIG_KVM_GUEST ++#define FIXADDR_TOP ((unsigned long)(long)(int)0x7ffe0000) ++#else + #define FIXADDR_TOP ((unsigned long)(long)(int)0xfffe0000) + #endif ++#endif + + #endif /* __ASM_MACH_GENERIC_SPACES_H */ +diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c +index 38265dc85318..65dfbd0c196d 100644 +--- a/arch/powerpc/perf/core-book3s.c ++++ b/arch/powerpc/perf/core-book3s.c +@@ -124,7 +124,16 @@ static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {} + + static bool regs_use_siar(struct pt_regs *regs) + { +- return !!regs->result; ++ /* ++ * When we take a performance monitor exception the regs are setup ++ * using perf_read_regs() which overloads some fields, in particular ++ * regs->result to tell us whether to use SIAR. ++ * ++ * However if the regs are from another exception, eg. a syscall, then ++ * they have not been setup using perf_read_regs() and so regs->result ++ * is something random. ++ */ ++ return ((TRAP(regs) == 0xf00) && regs->result); + } + + /* +diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c +index 27bb55485472..7ef28625c199 100644 +--- a/arch/sparc/kernel/ldc.c ++++ b/arch/sparc/kernel/ldc.c +@@ -2307,7 +2307,7 @@ void *ldc_alloc_exp_dring(struct ldc_channel *lp, unsigned int len, + if (len & (8UL - 1)) + return ERR_PTR(-EINVAL); + +- buf = kzalloc(len, GFP_KERNEL); ++ buf = kzalloc(len, GFP_ATOMIC); + if (!buf) + return ERR_PTR(-ENOMEM); + +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index 5dab54accc56..96e743ac28f3 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -2440,9 +2440,19 @@ config X86_DMA_REMAP + depends on STA2X11 + + config IOSF_MBI +- tristate +- default m ++ tristate "Intel System On Chip IOSF Sideband support" + depends on PCI ++ ---help--- ++ Enables sideband access to mailbox registers on SoC's. The sideband is ++ available on the following platforms. This list is not meant to be ++ exclusive. ++ - BayTrail ++ - Cherryview ++ - Braswell ++ - Quark ++ ++ You should say Y if you are running a kernel on one of these ++ platforms. + + source "net/Kconfig" + +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index e9dc02968cf8..ac03bd7c8978 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -571,7 +571,7 @@ struct kvm_arch { + struct kvm_pic *vpic; + struct kvm_ioapic *vioapic; + struct kvm_pit *vpit; +- int vapics_in_nmi_mode; ++ atomic_t vapics_in_nmi_mode; + struct mutex apic_map_lock; + struct kvm_apic_map *apic_map; + +diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c +index 298781d4cfb4..1406ffde3e35 100644 +--- a/arch/x86/kvm/i8254.c ++++ b/arch/x86/kvm/i8254.c +@@ -305,7 +305,7 @@ static void pit_do_work(struct kthread_work *work) + * LVT0 to NMI delivery. Other PIC interrupts are just sent to + * VCPU0, and only if its LVT0 is in EXTINT mode. + */ +- if (kvm->arch.vapics_in_nmi_mode > 0) ++ if (atomic_read(&kvm->arch.vapics_in_nmi_mode) > 0) + kvm_for_each_vcpu(i, vcpu, kvm) + kvm_apic_nmi_wd_deliver(vcpu); + } +diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c +index 453e5fbbb7ae..6456734a4ca6 100644 +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -1109,10 +1109,10 @@ static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val) + if (!nmi_wd_enabled) { + apic_debug("Receive NMI setting on APIC_LVT0 " + "for cpu %d\n", apic->vcpu->vcpu_id); +- apic->vcpu->kvm->arch.vapics_in_nmi_mode++; ++ atomic_inc(&apic->vcpu->kvm->arch.vapics_in_nmi_mode); + } + } else if (nmi_wd_enabled) +- apic->vcpu->kvm->arch.vapics_in_nmi_mode--; ++ atomic_dec(&apic->vcpu->kvm->arch.vapics_in_nmi_mode); + } + + static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) +diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c +index 4f25ec077552..bf001382d170 100644 +--- a/arch/x86/pci/acpi.c ++++ b/arch/x86/pci/acpi.c +@@ -84,6 +84,17 @@ static const struct dmi_system_id pci_crs_quirks[] __initconst = { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"), + }, + }, ++ /* https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/931368 */ ++ /* https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/1033299 */ ++ { ++ .callback = set_use_crs, ++ .ident = "Foxconn K8M890-8237A", ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Foxconn"), ++ DMI_MATCH(DMI_BOARD_NAME, "K8M890-8237A"), ++ DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"), ++ }, ++ }, + + /* Now for the blacklist.. */ + +@@ -124,8 +135,10 @@ void __init pci_acpi_crs_quirks(void) + { + int year; + +- if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008) +- pci_use_crs = false; ++ if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008) { ++ if (iomem_resource.end <= 0xffffffff) ++ pci_use_crs = false; ++ } + + dmi_check_system(pci_crs_quirks); + +diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c +index 533a509439ca..fbc693b7d24f 100644 +--- a/drivers/cpufreq/intel_pstate.c ++++ b/drivers/cpufreq/intel_pstate.c +@@ -417,7 +417,7 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate) + + val |= vid; + +- wrmsrl(MSR_IA32_PERF_CTL, val); ++ wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val); + } + + #define BYT_BCLK_FREQS 5 +diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c +index 5967667e1a8f..1f354879bd06 100644 +--- a/drivers/crypto/talitos.c ++++ b/drivers/crypto/talitos.c +@@ -927,7 +927,8 @@ static int sg_to_link_tbl(struct scatterlist *sg, int sg_count, + sg_count--; + link_tbl_ptr--; + } +- be16_add_cpu(&link_tbl_ptr->len, cryptlen); ++ link_tbl_ptr->len = cpu_to_be16(be16_to_cpu(link_tbl_ptr->len) ++ + cryptlen); + + /* tag end of link table */ + link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN; +@@ -2563,6 +2564,7 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, + break; + default: + dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type); ++ kfree(t_alg); + return ERR_PTR(-EINVAL); + } + +diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c +index 9cbef59d404a..935974090aa0 100644 +--- a/drivers/iommu/amd_iommu.c ++++ b/drivers/iommu/amd_iommu.c +@@ -1922,9 +1922,15 @@ static void free_pt_##LVL (unsigned long __pt) \ + pt = (u64 *)__pt; \ + \ + for (i = 0; i < 512; ++i) { \ ++ /* PTE present? */ \ + if (!IOMMU_PTE_PRESENT(pt[i])) \ + continue; \ + \ ++ /* Large PTE? */ \ ++ if (PM_PTE_LEVEL(pt[i]) == 0 || \ ++ PM_PTE_LEVEL(pt[i]) == 7) \ ++ continue; \ ++ \ + p = (unsigned long)IOMMU_PTE_PAGE(pt[i]); \ + FN(p); \ + } \ +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index 25f74191a788..62c3fb91e76f 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -765,10 +765,11 @@ static int genphy_config_advert(struct phy_device *phydev) + if (phydev->supported & (SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full)) { + adv |= ethtool_adv_to_mii_ctrl1000_t(advertise); +- if (adv != oldadv) +- changed = 1; + } + ++ if (adv != oldadv) ++ changed = 1; ++ + err = phy_write(phydev, MII_CTRL1000, adv); + if (err < 0) + return err; +diff --git a/fs/dcache.c b/fs/dcache.c +index 1d7e8a3fb6cd..aa24f7de1b92 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -2905,17 +2905,6 @@ restart: + vfsmnt = &mnt->mnt; + continue; + } +- /* +- * Filesystems needing to implement special "root names" +- * should do so with ->d_dname() +- */ +- if (IS_ROOT(dentry) && +- (dentry->d_name.len != 1 || +- dentry->d_name.name[0] != '/')) { +- WARN(1, "Root dentry has weird name <%.*s>\n", +- (int) dentry->d_name.len, +- dentry->d_name.name); +- } + if (!error) + error = is_mounted(vfsmnt) ? 1 : 2; + break; +diff --git a/fs/inode.c b/fs/inode.c +index e846a32e8d6e..644875bcc846 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -1631,8 +1631,8 @@ int file_remove_suid(struct file *file) + error = security_inode_killpriv(dentry); + if (!error && killsuid) + error = __remove_suid(dentry, killsuid); +- if (!error && (inode->i_sb->s_flags & MS_NOSEC)) +- inode->i_flags |= S_NOSEC; ++ if (!error) ++ inode_has_no_xattr(inode); + + return error; + } +diff --git a/fs/namespace.c b/fs/namespace.c +index 2faa7eacb62b..fc99d185a477 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -3031,11 +3031,15 @@ bool fs_fully_visible(struct file_system_type *type) + if (mnt->mnt.mnt_root != mnt->mnt.mnt_sb->s_root) + continue; + +- /* This mount is not fully visible if there are any child mounts +- * that cover anything except for empty directories. ++ /* This mount is not fully visible if there are any ++ * locked child mounts that cover anything except for ++ * empty directories. + */ + list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) { + struct inode *inode = child->mnt_mountpoint->d_inode; ++ /* Only worry about locked mounts */ ++ if (!(mnt->mnt.mnt_flags & MNT_LOCKED)) ++ continue; + if (!S_ISDIR(inode->i_mode)) + goto next; + if (inode->i_nlink > 2) +diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h +index 6d9aeddc09bf..327b155e7cc9 100644 +--- a/include/kvm/arm_arch_timer.h ++++ b/include/kvm/arm_arch_timer.h +@@ -60,7 +60,8 @@ struct arch_timer_cpu { + + #ifdef CONFIG_KVM_ARM_TIMER + int kvm_timer_hyp_init(void); +-int kvm_timer_init(struct kvm *kvm); ++void kvm_timer_enable(struct kvm *kvm); ++void kvm_timer_init(struct kvm *kvm); + void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu, + const struct kvm_irq_level *irq); + void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu); +@@ -73,11 +74,8 @@ static inline int kvm_timer_hyp_init(void) + return 0; + }; + +-static inline int kvm_timer_init(struct kvm *kvm) +-{ +- return 0; +-} +- ++static inline void kvm_timer_enable(struct kvm *kvm) {} ++static inline void kvm_timer_init(struct kvm *kvm) {} + static inline void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu, + const struct kvm_irq_level *irq) {} + static inline void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) {} +diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h +index 3573a81815ad..8ba379f9e467 100644 +--- a/include/net/netns/sctp.h ++++ b/include/net/netns/sctp.h +@@ -31,6 +31,7 @@ struct netns_sctp { + struct list_head addr_waitq; + struct timer_list addr_wq_timer; + struct list_head auto_asconf_splist; ++ /* Lock that protects both addr_waitq and auto_asconf_splist */ + spinlock_t addr_wq_lock; + + /* Lock that protects the local_addr_list writers */ +diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h +index 0dfcc92600e8..2c2d388f884f 100644 +--- a/include/net/sctp/structs.h ++++ b/include/net/sctp/structs.h +@@ -219,6 +219,10 @@ struct sctp_sock { + atomic_t pd_mode; + /* Receive to here while partial delivery is in effect. */ + struct sk_buff_head pd_lobby; ++ ++ /* These must be the last fields, as they will skipped on copies, ++ * like on accept and peeloff operations ++ */ + struct list_head auto_asconf_list; + int do_auto_asconf; + }; +diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c +index a9a4a1b7863d..8d423bc649b9 100644 +--- a/net/bridge/br_ioctl.c ++++ b/net/bridge/br_ioctl.c +@@ -247,9 +247,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) + if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) + return -EPERM; + +- spin_lock_bh(&br->lock); + br_stp_set_bridge_priority(br, args[1]); +- spin_unlock_bh(&br->lock); + return 0; + + case BRCTL_SET_PORT_PRIORITY: +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index 11a2e6c8538f..7bbc8fe25261 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -1086,6 +1086,9 @@ static void br_multicast_add_router(struct net_bridge *br, + struct net_bridge_port *p; + struct hlist_node *slot = NULL; + ++ if (!hlist_unhashed(&port->rlist)) ++ return; ++ + hlist_for_each_entry(p, &br->router_list, rlist) { + if ((unsigned long) port >= (unsigned long) p) + break; +@@ -1113,12 +1116,8 @@ static void br_multicast_mark_router(struct net_bridge *br, + if (port->multicast_router != 1) + return; + +- if (!hlist_unhashed(&port->rlist)) +- goto timer; +- + br_multicast_add_router(br, port); + +-timer: + mod_timer(&port->multicast_router_timer, + now + br->multicast_querier_interval); + } +diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c +index 189ba1e7d851..9a0005aee9ad 100644 +--- a/net/bridge/br_stp_if.c ++++ b/net/bridge/br_stp_if.c +@@ -243,12 +243,13 @@ bool br_stp_recalculate_bridge_id(struct net_bridge *br) + return true; + } + +-/* called under bridge lock */ ++/* Acquires and releases bridge lock */ + void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio) + { + struct net_bridge_port *p; + int wasroot; + ++ spin_lock_bh(&br->lock); + wasroot = br_is_root_bridge(br); + + list_for_each_entry(p, &br->port_list, list) { +@@ -266,6 +267,7 @@ void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio) + br_port_state_selection(br); + if (br_is_root_bridge(br) && !wasroot) + br_become_root_bridge(br); ++ spin_unlock_bh(&br->lock); + } + + /* called under bridge lock */ +diff --git a/net/core/neighbour.c b/net/core/neighbour.c +index 7d95f69635c6..0f062c671da9 100644 +--- a/net/core/neighbour.c ++++ b/net/core/neighbour.c +@@ -976,6 +976,8 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) + rc = 0; + if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE)) + goto out_unlock_bh; ++ if (neigh->dead) ++ goto out_dead; + + if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) { + if (NEIGH_VAR(neigh->parms, MCAST_PROBES) + +@@ -1032,6 +1034,13 @@ out_unlock_bh: + write_unlock(&neigh->lock); + local_bh_enable(); + return rc; ++ ++out_dead: ++ if (neigh->nud_state & NUD_STALE) ++ goto out_unlock_bh; ++ write_unlock_bh(&neigh->lock); ++ kfree_skb(skb); ++ return 1; + } + EXPORT_SYMBOL(__neigh_event_send); + +@@ -1095,6 +1104,8 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, + if (!(flags & NEIGH_UPDATE_F_ADMIN) && + (old & (NUD_NOARP | NUD_PERMANENT))) + goto out; ++ if (neigh->dead) ++ goto out; + + if (!(new & NUD_VALID)) { + neigh_del_timer(neigh); +@@ -1244,6 +1255,8 @@ EXPORT_SYMBOL(neigh_update); + */ + void __neigh_set_probe_once(struct neighbour *neigh) + { ++ if (neigh->dead) ++ return; + neigh->updated = jiffies; + if (!(neigh->nud_state & NUD_FAILED)) + return; +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index 69ec61abfb37..8207f8d7f665 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -368,9 +368,11 @@ refill: + for (order = NETDEV_FRAG_PAGE_MAX_ORDER; ;) { + gfp_t gfp = gfp_mask; + +- if (order) ++ if (order) { + gfp |= __GFP_COMP | __GFP_NOWARN | + __GFP_NOMEMALLOC; ++ gfp &= ~__GFP_WAIT; ++ } + nc->frag.page = alloc_pages(gfp, order); + if (likely(nc->frag.page)) + break; +diff --git a/net/core/sock.c b/net/core/sock.c +index 650dd58ebd05..8ebfa52e5d70 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -1914,8 +1914,10 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio) + do { + gfp_t gfp = prio; + +- if (order) ++ if (order) { + gfp |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY; ++ gfp &= ~__GFP_WAIT; ++ } + pfrag->page = alloc_pages(gfp, order); + if (likely(pfrag->page)) { + pfrag->offset = 0; +diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c +index 07bd8edef417..951fe55b1671 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -228,6 +228,8 @@ int inet_listen(struct socket *sock, int backlog) + err = 0; + if (err) + goto out; ++ ++ tcp_fastopen_init_key_once(true); + } + err = inet_csk_listen_start(sk, backlog); + if (err) +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 29d240b87af1..dc45221dc692 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -2684,10 +2684,13 @@ static int do_tcp_setsockopt(struct sock *sk, int level, + + case TCP_FASTOPEN: + if (val >= 0 && ((1 << sk->sk_state) & (TCPF_CLOSE | +- TCPF_LISTEN))) ++ TCPF_LISTEN))) { ++ tcp_fastopen_init_key_once(true); ++ + err = fastopen_init_queue(sk, val); +- else ++ } else { + err = -EINVAL; ++ } + break; + case TCP_TIMESTAMP: + if (!tp->repair) +diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c +index f195d9316e55..ee6518d1afe5 100644 +--- a/net/ipv4/tcp_fastopen.c ++++ b/net/ipv4/tcp_fastopen.c +@@ -84,8 +84,6 @@ void tcp_fastopen_cookie_gen(__be32 src, __be32 dst, + __be32 path[4] = { src, dst, 0, 0 }; + struct tcp_fastopen_context *ctx; + +- tcp_fastopen_init_key_once(true); +- + rcu_read_lock(); + ctx = rcu_dereference(tcp_fastopen_ctx); + if (ctx) { +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 48b181797d7b..84a60b82e235 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -1264,16 +1264,6 @@ static void packet_sock_destruct(struct sock *sk) + sk_refcnt_debug_dec(sk); + } + +-static int fanout_rr_next(struct packet_fanout *f, unsigned int num) +-{ +- int x = atomic_read(&f->rr_cur) + 1; +- +- if (x >= num) +- x = 0; +- +- return x; +-} +- + static unsigned int fanout_demux_hash(struct packet_fanout *f, + struct sk_buff *skb, + unsigned int num) +@@ -1285,13 +1275,9 @@ static unsigned int fanout_demux_lb(struct packet_fanout *f, + struct sk_buff *skb, + unsigned int num) + { +- int cur, old; ++ unsigned int val = atomic_inc_return(&f->rr_cur); + +- cur = atomic_read(&f->rr_cur); +- while ((old = atomic_cmpxchg(&f->rr_cur, cur, +- fanout_rr_next(f, num))) != cur) +- cur = old; +- return cur; ++ return val % num; + } + + static unsigned int fanout_demux_cpu(struct packet_fanout *f, +@@ -1345,7 +1331,7 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *orig_dev) + { + struct packet_fanout *f = pt->af_packet_priv; +- unsigned int num = f->num_members; ++ unsigned int num = ACCESS_ONCE(f->num_members); + struct packet_sock *po; + unsigned int idx; + +diff --git a/net/sctp/output.c b/net/sctp/output.c +index 740ca5f7add0..e39e6d561592 100644 +--- a/net/sctp/output.c ++++ b/net/sctp/output.c +@@ -599,7 +599,9 @@ out: + return err; + no_route: + kfree_skb(nskb); +- IP_INC_STATS(sock_net(asoc->base.sk), IPSTATS_MIB_OUTNOROUTES); ++ ++ if (asoc) ++ IP_INC_STATS(sock_net(asoc->base.sk), IPSTATS_MIB_OUTNOROUTES); + + /* FIXME: Returning the 'err' will effect all the associations + * associated with a socket, although only one of the paths of the +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index 604a6acdf92e..f940fdc540f5 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -1532,8 +1532,10 @@ static void sctp_close(struct sock *sk, long timeout) + + /* Supposedly, no process has access to the socket, but + * the net layers still may. ++ * Also, sctp_destroy_sock() needs to be called with addr_wq_lock ++ * held and that should be grabbed before socket lock. + */ +- local_bh_disable(); ++ spin_lock_bh(&net->sctp.addr_wq_lock); + bh_lock_sock(sk); + + /* Hold the sock, since sk_common_release() will put sock_put() +@@ -1543,7 +1545,7 @@ static void sctp_close(struct sock *sk, long timeout) + sk_common_release(sk); + + bh_unlock_sock(sk); +- local_bh_enable(); ++ spin_unlock_bh(&net->sctp.addr_wq_lock); + + sock_put(sk); + +@@ -3511,6 +3513,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval, + if ((val && sp->do_auto_asconf) || (!val && !sp->do_auto_asconf)) + return 0; + ++ spin_lock_bh(&sock_net(sk)->sctp.addr_wq_lock); + if (val == 0 && sp->do_auto_asconf) { + list_del(&sp->auto_asconf_list); + sp->do_auto_asconf = 0; +@@ -3519,6 +3522,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval, + &sock_net(sk)->sctp.auto_asconf_splist); + sp->do_auto_asconf = 1; + } ++ spin_unlock_bh(&sock_net(sk)->sctp.addr_wq_lock); + return 0; + } + +@@ -4009,18 +4013,28 @@ static int sctp_init_sock(struct sock *sk) + local_bh_disable(); + percpu_counter_inc(&sctp_sockets_allocated); + sock_prot_inuse_add(net, sk->sk_prot, 1); ++ ++ /* Nothing can fail after this block, otherwise ++ * sctp_destroy_sock() will be called without addr_wq_lock held ++ */ + if (net->sctp.default_auto_asconf) { ++ spin_lock(&sock_net(sk)->sctp.addr_wq_lock); + list_add_tail(&sp->auto_asconf_list, + &net->sctp.auto_asconf_splist); + sp->do_auto_asconf = 1; +- } else ++ spin_unlock(&sock_net(sk)->sctp.addr_wq_lock); ++ } else { + sp->do_auto_asconf = 0; ++ } ++ + local_bh_enable(); + + return 0; + } + +-/* Cleanup any SCTP per socket resources. */ ++/* Cleanup any SCTP per socket resources. Must be called with ++ * sock_net(sk)->sctp.addr_wq_lock held if sp->do_auto_asconf is true ++ */ + static void sctp_destroy_sock(struct sock *sk) + { + struct sctp_sock *sp; +@@ -6973,6 +6987,19 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, + newinet->mc_list = NULL; + } + ++static inline void sctp_copy_descendant(struct sock *sk_to, ++ const struct sock *sk_from) ++{ ++ int ancestor_size = sizeof(struct inet_sock) + ++ sizeof(struct sctp_sock) - ++ offsetof(struct sctp_sock, auto_asconf_list); ++ ++ if (sk_from->sk_family == PF_INET6) ++ ancestor_size += sizeof(struct ipv6_pinfo); ++ ++ __inet_sk_copy_descendant(sk_to, sk_from, ancestor_size); ++} ++ + /* Populate the fields of the newsk from the oldsk and migrate the assoc + * and its messages to the newsk. + */ +@@ -6987,7 +7014,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, + struct sk_buff *skb, *tmp; + struct sctp_ulpevent *event; + struct sctp_bind_hashbucket *head; +- struct list_head tmplist; + + /* Migrate socket buffer sizes and all the socket level options to the + * new socket. +@@ -6995,12 +7021,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, + newsk->sk_sndbuf = oldsk->sk_sndbuf; + newsk->sk_rcvbuf = oldsk->sk_rcvbuf; + /* Brute force copy old sctp opt. */ +- if (oldsp->do_auto_asconf) { +- memcpy(&tmplist, &newsp->auto_asconf_list, sizeof(tmplist)); +- inet_sk_copy_descendant(newsk, oldsk); +- memcpy(&newsp->auto_asconf_list, &tmplist, sizeof(tmplist)); +- } else +- inet_sk_copy_descendant(newsk, oldsk); ++ sctp_copy_descendant(newsk, oldsk); + + /* Restore the ep value that was overwritten with the above structure + * copy. +diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c +index 5081e809821f..c6fe40568690 100644 +--- a/virt/kvm/arm/arch_timer.c ++++ b/virt/kvm/arm/arch_timer.c +@@ -61,12 +61,14 @@ static void timer_disarm(struct arch_timer_cpu *timer) + + static void kvm_timer_inject_irq(struct kvm_vcpu *vcpu) + { ++ int ret; + struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; + + timer->cntv_ctl |= ARCH_TIMER_CTRL_IT_MASK; +- kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id, +- timer->irq->irq, +- timer->irq->level); ++ ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id, ++ timer->irq->irq, ++ timer->irq->level); ++ WARN_ON(ret); + } + + static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id) +@@ -307,12 +309,24 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu) + timer_disarm(timer); + } + +-int kvm_timer_init(struct kvm *kvm) ++void kvm_timer_enable(struct kvm *kvm) + { +- if (timecounter && wqueue) { +- kvm->arch.timer.cntvoff = kvm_phys_timer_read(); ++ if (kvm->arch.timer.enabled) ++ return; ++ ++ /* ++ * There is a potential race here between VCPUs starting for the first ++ * time, which may be enabling the timer multiple times. That doesn't ++ * hurt though, because we're just setting a variable to the same ++ * variable that it already was. The important thing is that all ++ * VCPUs have the enabled variable set, before entering the guest, if ++ * the arch timers are enabled. ++ */ ++ if (timecounter && wqueue) + kvm->arch.timer.enabled = 1; +- } ++} + +- return 0; ++void kvm_timer_init(struct kvm *kvm) ++{ ++ kvm->arch.timer.cntvoff = kvm_phys_timer_read(); + } +diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c +index c324a52bb407..152ec76ccb42 100644 +--- a/virt/kvm/arm/vgic.c ++++ b/virt/kvm/arm/vgic.c +@@ -1042,6 +1042,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq) + lr, irq, vgic_cpu->vgic_lr[lr]); + BUG_ON(!test_bit(lr, vgic_cpu->lr_used)); + vgic_cpu->vgic_lr[lr] |= GICH_LR_PENDING_BIT; ++ __clear_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr); + return true; + } + +@@ -1055,6 +1056,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq) + vgic_cpu->vgic_lr[lr] = MK_LR_PEND(sgi_source_id, irq); + vgic_cpu->vgic_irq_lr_map[irq] = lr; + set_bit(lr, vgic_cpu->lr_used); ++ __clear_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr); + + if (!vgic_irq_is_edge(vcpu, irq)) + vgic_cpu->vgic_lr[lr] |= GICH_LR_EOI; +@@ -1209,6 +1211,14 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) + if (vgic_cpu->vgic_misr & GICH_MISR_U) + vgic_cpu->vgic_hcr &= ~GICH_HCR_UIE; + ++ /* ++ * In the next iterations of the vcpu loop, if we sync the vgic state ++ * after flushing it, but before entering the guest (this happens for ++ * pending signals and vmid rollovers), then make sure we don't pick ++ * up any old maintenance interrupts here. ++ */ ++ memset(vgic_cpu->vgic_eisr, 0, sizeof(vgic_cpu->vgic_eisr[0]) * 2); ++ + return level_pending; + } + diff --git a/patch/kernel/cubox-default/patch-3.14.48-49.patch b/patch/kernel/cubox-default/patch-3.14.48-49.patch new file mode 100644 index 000000000..dfa4b2739 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.48-49.patch @@ -0,0 +1,4039 @@ +diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt +index 01ef408e205f..8faff12e7014 100644 +--- a/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt ++++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt +@@ -91,5 +91,5 @@ mpp61 61 gpo, dev(wen1), uart1(txd), audio(rclk) + mpp62 62 gpio, dev(a2), uart1(cts), tdm(drx), pcie(clkreq0), + audio(mclk), uart0(cts) + mpp63 63 gpo, spi0(sck), tclk +-mpp64 64 gpio, spi0(miso), spi0-1(cs1) +-mpp65 65 gpio, spi0(mosi), spi0-1(cs2) ++mpp64 64 gpio, spi0(miso), spi0(cs1) ++mpp65 65 gpio, spi0(mosi), spi0(cs2) +diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt +index bfa0a2e5e0cb..86dec67e5450 100644 +--- a/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt ++++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt +@@ -41,15 +41,15 @@ mpp20 20 gpio, ge0(rxd4), ge1(rxd2), lcd(d20), ptp(clk) + mpp21 21 gpio, ge0(rxd5), ge1(rxd3), lcd(d21), mem(bat) + mpp22 22 gpio, ge0(rxd6), ge1(rxctl), lcd(d22), sata0(prsnt) + mpp23 23 gpio, ge0(rxd7), ge1(rxclk), lcd(d23), sata1(prsnt) +-mpp24 24 gpio, lcd(hsync), sata1(prsnt), nf(bootcs-re), tdm(rst) +-mpp25 25 gpio, lcd(vsync), sata0(prsnt), nf(bootcs-we), tdm(pclk) +-mpp26 26 gpio, lcd(clk), tdm(fsync), vdd(cpu1-pd) ++mpp24 24 gpio, lcd(hsync), sata1(prsnt), tdm(rst) ++mpp25 25 gpio, lcd(vsync), sata0(prsnt), tdm(pclk) ++mpp26 26 gpio, lcd(clk), tdm(fsync) + mpp27 27 gpio, lcd(e), tdm(dtx), ptp(trig) + mpp28 28 gpio, lcd(pwm), tdm(drx), ptp(evreq) +-mpp29 29 gpio, lcd(ref-clk), tdm(int0), ptp(clk), vdd(cpu0-pd) ++mpp29 29 gpio, lcd(ref-clk), tdm(int0), ptp(clk) + mpp30 30 gpio, tdm(int1), sd0(clk) +-mpp31 31 gpio, tdm(int2), sd0(cmd), vdd(cpu0-pd) +-mpp32 32 gpio, tdm(int3), sd0(d0), vdd(cpu1-pd) ++mpp31 31 gpio, tdm(int2), sd0(cmd) ++mpp32 32 gpio, tdm(int3), sd0(d0) + mpp33 33 gpio, tdm(int4), sd0(d1), mem(bat) + mpp34 34 gpio, tdm(int5), sd0(d2), sata0(prsnt) + mpp35 35 gpio, tdm(int6), sd0(d3), sata1(prsnt) +@@ -57,21 +57,18 @@ mpp36 36 gpio, spi(mosi) + mpp37 37 gpio, spi(miso) + mpp38 38 gpio, spi(sck) + mpp39 39 gpio, spi(cs0) +-mpp40 40 gpio, spi(cs1), uart2(cts), lcd(vga-hsync), vdd(cpu1-pd), +- pcie(clkreq0) ++mpp40 40 gpio, spi(cs1), uart2(cts), lcd(vga-hsync), pcie(clkreq0) + mpp41 41 gpio, spi(cs2), uart2(rts), lcd(vga-vsync), sata1(prsnt), + pcie(clkreq1) +-mpp42 42 gpio, uart2(rxd), uart0(cts), tdm(int7), tdm-1(timer), +- vdd(cpu0-pd) +-mpp43 43 gpio, uart2(txd), uart0(rts), spi(cs3), pcie(rstout), +- vdd(cpu2-3-pd){1} ++mpp42 42 gpio, uart2(rxd), uart0(cts), tdm(int7), tdm-1(timer) ++mpp43 43 gpio, uart2(txd), uart0(rts), spi(cs3), pcie(rstout) + mpp44 44 gpio, uart2(cts), uart3(rxd), spi(cs4), pcie(clkreq2), + mem(bat) + mpp45 45 gpio, uart2(rts), uart3(txd), spi(cs5), sata1(prsnt) + mpp46 46 gpio, uart3(rts), uart1(rts), spi(cs6), sata0(prsnt) + mpp47 47 gpio, uart3(cts), uart1(cts), spi(cs7), pcie(clkreq3), + ref(clkout) +-mpp48 48 gpio, tclk, dev(burst/last) ++mpp48 48 gpio, dev(clkout), dev(burst/last) + + * Marvell Armada XP (mv78260 and mv78460 only) + +@@ -83,9 +80,9 @@ mpp51 51 gpio, dev(ad16) + mpp52 52 gpio, dev(ad17) + mpp53 53 gpio, dev(ad18) + mpp54 54 gpio, dev(ad19) +-mpp55 55 gpio, dev(ad20), vdd(cpu0-pd) +-mpp56 56 gpio, dev(ad21), vdd(cpu1-pd) +-mpp57 57 gpio, dev(ad22), vdd(cpu2-3-pd){1} ++mpp55 55 gpio, dev(ad20) ++mpp56 56 gpio, dev(ad21) ++mpp57 57 gpio, dev(ad22) + mpp58 58 gpio, dev(ad23) + mpp59 59 gpio, dev(ad24) + mpp60 60 gpio, dev(ad25) +@@ -95,6 +92,3 @@ mpp63 63 gpio, dev(ad28) + mpp64 64 gpio, dev(ad29) + mpp65 65 gpio, dev(ad30) + mpp66 66 gpio, dev(ad31) +- +-Notes: +-* {1} vdd(cpu2-3-pd) only available on mv78460. +diff --git a/Documentation/devicetree/bindings/spi/spi_pl022.txt b/Documentation/devicetree/bindings/spi/spi_pl022.txt +index 22ed6797216d..4d1673ca8cf8 100644 +--- a/Documentation/devicetree/bindings/spi/spi_pl022.txt ++++ b/Documentation/devicetree/bindings/spi/spi_pl022.txt +@@ -4,9 +4,9 @@ Required properties: + - compatible : "arm,pl022", "arm,primecell" + - reg : Offset and length of the register set for the device + - interrupts : Should contain SPI controller interrupt ++- num-cs : total number of chipselects + + Optional properties: +-- num-cs : total number of chipselects + - cs-gpios : should specify GPIOs used for chipselects. + The gpios will be referred to as reg = in the SPI child nodes. + If unspecified, a single SPI device without a chip select can be used. +diff --git a/Makefile b/Makefile +index 25393e89051c..fee84602e999 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 48 ++SUBLEVEL = 49 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arc/include/asm/cmpxchg.h b/arch/arc/include/asm/cmpxchg.h +index 03cd6894855d..90de5c528da2 100644 +--- a/arch/arc/include/asm/cmpxchg.h ++++ b/arch/arc/include/asm/cmpxchg.h +@@ -25,10 +25,11 @@ __cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new) + " scond %3, [%1] \n" + " bnz 1b \n" + "2: \n" +- : "=&r"(prev) +- : "r"(ptr), "ir"(expected), +- "r"(new) /* can't be "ir". scond can't take limm for "b" */ +- : "cc"); ++ : "=&r"(prev) /* Early clobber, to prevent reg reuse */ ++ : "r"(ptr), /* Not "m": llock only supports reg direct addr mode */ ++ "ir"(expected), ++ "r"(new) /* can't be "ir". scond can't take LIMM for "b" */ ++ : "cc", "memory"); /* so that gcc knows memory is being written here */ + + return prev; + } +diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile +index a268a9af0c2d..a622dd0be9c4 100644 +--- a/arch/arm64/kernel/vdso/Makefile ++++ b/arch/arm64/kernel/vdso/Makefile +@@ -15,6 +15,10 @@ ccflags-y := -shared -fno-common -fno-builtin + ccflags-y += -nostdlib -Wl,-soname=linux-vdso.so.1 \ + $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) + ++# Workaround for bare-metal (ELF) toolchains that neglect to pass -shared ++# down to collect2, resulting in silent corruption of the vDSO image. ++ccflags-y += -Wl,-shared ++ + obj-y += vdso.o + extra-y += vdso.lds vdso-offsets.h + CPPFLAGS_vdso.lds += -P -C -U$(ARCH) +diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c +index baa758d37021..76c1e6cd36fc 100644 +--- a/arch/arm64/mm/context.c ++++ b/arch/arm64/mm/context.c +@@ -92,6 +92,14 @@ static void reset_context(void *info) + unsigned int cpu = smp_processor_id(); + struct mm_struct *mm = current->active_mm; + ++ /* ++ * current->active_mm could be init_mm for the idle thread immediately ++ * after secondary CPU boot or hotplug. TTBR0_EL1 is already set to ++ * the reserved value, so no need to reset any context. ++ */ ++ if (mm == &init_mm) ++ return; ++ + smp_rmb(); + asid = cpu_last_asid + cpu; + +diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c +index 023747bf4dd7..e3a24b75e53c 100644 +--- a/arch/arm64/mm/hugetlbpage.c ++++ b/arch/arm64/mm/hugetlbpage.c +@@ -46,13 +46,13 @@ struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address, + + int pmd_huge(pmd_t pmd) + { +- return !(pmd_val(pmd) & PMD_TABLE_BIT); ++ return pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT); + } + + int pud_huge(pud_t pud) + { + #ifndef __PAGETABLE_PMD_FOLDED +- return !(pud_val(pud) & PUD_TABLE_BIT); ++ return pud_val(pud) && !(pud_val(pud) & PUD_TABLE_BIT); + #else + return 0; + #endif +diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c +index d0b4c2efda90..aeb95a15cc9a 100644 +--- a/arch/arm64/mm/init.c ++++ b/arch/arm64/mm/init.c +@@ -243,7 +243,7 @@ static void __init free_unused_memmap(void) + * memmap entries are valid from the bank end aligned to + * MAX_ORDER_NR_PAGES. + */ +- prev_end = ALIGN(start + __phys_to_pfn(reg->size), ++ prev_end = ALIGN(__phys_to_pfn(reg->base + reg->size), + MAX_ORDER_NR_PAGES); + } + +diff --git a/arch/mips/kvm/kvm_mips_emul.c b/arch/mips/kvm/kvm_mips_emul.c +index e75ef8219caf..c76f297b7149 100644 +--- a/arch/mips/kvm/kvm_mips_emul.c ++++ b/arch/mips/kvm/kvm_mips_emul.c +@@ -1626,7 +1626,7 @@ kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run) + if (vcpu->mmio_needed == 2) + *gpr = *(int16_t *) run->mmio.data; + else +- *gpr = *(int16_t *) run->mmio.data; ++ *gpr = *(uint16_t *)run->mmio.data; + + break; + case 1: +diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c +index 246ef68681f4..2c3c578faa0a 100644 +--- a/drivers/acpi/acpica/utxfinit.c ++++ b/drivers/acpi/acpica/utxfinit.c +@@ -175,10 +175,12 @@ acpi_status __init acpi_enable_subsystem(u32 flags) + * Obtain a permanent mapping for the FACS. This is required for the + * Global Lock and the Firmware Waking Vector + */ +- status = acpi_tb_initialize_facs(); +- if (ACPI_FAILURE(status)) { +- ACPI_WARNING((AE_INFO, "Could not map the FACS table")); +- return_ACPI_STATUS(status); ++ if (!(flags & ACPI_NO_FACS_INIT)) { ++ status = acpi_tb_initialize_facs(); ++ if (ACPI_FAILURE(status)) { ++ ACPI_WARNING((AE_INFO, "Could not map the FACS table")); ++ return_ACPI_STATUS(status); ++ } + } + #endif /* !ACPI_REDUCED_HARDWARE */ + +diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c +index b48aefab57e8..60be8d0ef100 100644 +--- a/drivers/acpi/bus.c ++++ b/drivers/acpi/bus.c +@@ -450,6 +450,16 @@ static int __init acpi_bus_init_irq(void) + u8 acpi_gbl_permanent_mmap; + + ++/** ++ * acpi_early_init - Initialize ACPICA and populate the ACPI namespace. ++ * ++ * The ACPI tables are accessible after this, but the handling of events has not ++ * been initialized and the global lock is not available yet, so AML should not ++ * be executed at this point. ++ * ++ * Doing this before switching the EFI runtime services to virtual mode allows ++ * the EfiBootServices memory to be freed slightly earlier on boot. ++ */ + void __init acpi_early_init(void) + { + acpi_status status; +@@ -510,26 +520,42 @@ void __init acpi_early_init(void) + acpi_gbl_FADT.sci_interrupt = acpi_sci_override_gsi; + } + #endif ++ return; ++ ++ error0: ++ disable_acpi(); ++} ++ ++/** ++ * acpi_subsystem_init - Finalize the early initialization of ACPI. ++ * ++ * Switch over the platform to the ACPI mode (if possible), initialize the ++ * handling of ACPI events, install the interrupt and global lock handlers. ++ * ++ * Doing this too early is generally unsafe, but at the same time it needs to be ++ * done before all things that really depend on ACPI. The right spot appears to ++ * be before finalizing the EFI initialization. ++ */ ++void __init acpi_subsystem_init(void) ++{ ++ acpi_status status; ++ ++ if (acpi_disabled) ++ return; + + status = acpi_enable_subsystem(~ACPI_NO_ACPI_ENABLE); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Unable to enable ACPI\n"); +- goto error0; ++ disable_acpi(); ++ } else { ++ /* ++ * If the system is using ACPI then we can be reasonably ++ * confident that any regulators are managed by the firmware ++ * so tell the regulator core it has everything it needs to ++ * know. ++ */ ++ regulator_has_full_constraints(); + } +- +- /* +- * If the system is using ACPI then we can be reasonably +- * confident that any regulators are managed by the firmware +- * so tell the regulator core it has everything it needs to +- * know. +- */ +- regulator_has_full_constraints(); +- +- return; +- +- error0: +- disable_acpi(); +- return; + } + + static int __init acpi_bus_init(void) +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index b1c0fcdf46fc..b0e6691faf18 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -4173,9 +4173,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { + { "ST3320[68]13AS", "SD1[5-9]", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + +- /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */ ++ /* drives which fail FPDMA_AA activation (some may freeze afterwards) */ + { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA }, + { "ST1000LM024 HN-M101MBB", "2BA30001", ATA_HORKAGE_BROKEN_FPDMA_AA }, ++ { "VB0250EAVER", "HPG7", ATA_HORKAGE_BROKEN_FPDMA_AA }, + + /* Blacklist entries taken from Silicon Image 3124/3132 + Windows driver .inf file - also several Linux problem reports */ +@@ -4229,6 +4230,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { + { "Micron_M550*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Crucial_CT*M550SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + ++ /* devices that don't properly handle TRIM commands */ ++ { "SuperSSpeed S238*", NULL, ATA_HORKAGE_NOTRIM, }, ++ + /* + * Some WD SATA-I drives spin up and down erratically when the link + * is put into the slumber mode. We don't have full list of the +@@ -4533,7 +4537,8 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev) + else /* In the ancient relic department - skip all of this */ + return 0; + +- err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); ++ /* On some disks, this command causes spin-up, so we need longer timeout */ ++ err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 15000); + + DPRINTK("EXIT, err_mask=%x\n", err_mask); + return err_mask; +diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c +index ef8567de6a75..6fecf0bde105 100644 +--- a/drivers/ata/libata-scsi.c ++++ b/drivers/ata/libata-scsi.c +@@ -2510,7 +2510,8 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf) + rbuf[14] = (lowest_aligned >> 8) & 0x3f; + rbuf[15] = lowest_aligned; + +- if (ata_id_has_trim(args->id)) { ++ if (ata_id_has_trim(args->id) && ++ !(dev->horkage & ATA_HORKAGE_NOTRIM)) { + rbuf[14] |= 0x80; /* TPE */ + + if (ata_id_has_zero_after_trim(args->id)) +diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c +index 2495ee577a64..f0c15f9c2b2f 100644 +--- a/drivers/base/firmware_class.c ++++ b/drivers/base/firmware_class.c +@@ -544,10 +544,8 @@ static void fw_dev_release(struct device *dev) + kfree(fw_priv); + } + +-static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) ++static int do_firmware_uevent(struct firmware_priv *fw_priv, struct kobj_uevent_env *env) + { +- struct firmware_priv *fw_priv = to_firmware_priv(dev); +- + if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->buf->fw_id)) + return -ENOMEM; + if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout)) +@@ -558,6 +556,18 @@ static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) + return 0; + } + ++static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) ++{ ++ struct firmware_priv *fw_priv = to_firmware_priv(dev); ++ int err = 0; ++ ++ mutex_lock(&fw_lock); ++ if (fw_priv->buf) ++ err = do_firmware_uevent(fw_priv, env); ++ mutex_unlock(&fw_lock); ++ return err; ++} ++ + static struct class firmware_class = { + .name = "firmware", + .class_attrs = firmware_class_attrs, +diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c +index 2f9a3d8ecbbf..58559d75d02c 100644 +--- a/drivers/base/regmap/regmap.c ++++ b/drivers/base/regmap/regmap.c +@@ -808,11 +808,10 @@ EXPORT_SYMBOL_GPL(devm_regmap_init); + static void regmap_field_init(struct regmap_field *rm_field, + struct regmap *regmap, struct reg_field reg_field) + { +- int field_bits = reg_field.msb - reg_field.lsb + 1; + rm_field->regmap = regmap; + rm_field->reg = reg_field.reg; + rm_field->shift = reg_field.lsb; +- rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb); ++ rm_field->mask = GENMASK(reg_field.msb, reg_field.lsb); + rm_field->id_size = reg_field.id_size; + rm_field->id_offset = reg_field.id_offset; + } +@@ -1947,7 +1946,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, + &ival); + if (ret != 0) + return ret; +- memcpy(val + (i * val_bytes), &ival, val_bytes); ++ map->format.format_val(val + (i * val_bytes), ival, 0); + } + } + +diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c +index 63688d3a6ea0..12be7cbfba4f 100644 +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -1826,11 +1826,11 @@ static struct rbd_obj_request *rbd_obj_request_create(const char *object_name, + rbd_assert(obj_request_type_valid(type)); + + size = strlen(object_name) + 1; +- name = kmalloc(size, GFP_KERNEL); ++ name = kmalloc(size, GFP_NOIO); + if (!name) + return NULL; + +- obj_request = kmem_cache_zalloc(rbd_obj_request_cache, GFP_KERNEL); ++ obj_request = kmem_cache_zalloc(rbd_obj_request_cache, GFP_NOIO); + if (!obj_request) { + kfree(name); + return NULL; +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index c0e7a9aa97a4..c23658e42fc3 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -1293,6 +1293,8 @@ static int btusb_setup_intel(struct hci_dev *hdev) + } + fw_ptr = fw->data; + ++ kfree_skb(skb); ++ + /* This Intel specific command enables the manufacturer mode of the + * controller. + * +diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c +index 5c85350f4c3d..19e301f9d549 100644 +--- a/drivers/char/agp/intel-gtt.c ++++ b/drivers/char/agp/intel-gtt.c +@@ -586,7 +586,7 @@ static inline int needs_ilk_vtd_wa(void) + /* Query intel_iommu to see if we need the workaround. Presumably that + * was loaded first. + */ +- if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || ++ if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG || + gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) && + intel_iommu_gfx_mapped) + return 1; +diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c +index 102463ba745d..643bba7d6f81 100644 +--- a/drivers/char/tpm/tpm_ibmvtpm.c ++++ b/drivers/char/tpm/tpm_ibmvtpm.c +@@ -579,6 +579,9 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, + goto cleanup; + } + ++ ibmvtpm->dev = dev; ++ ibmvtpm->vdev = vio_dev; ++ + crq_q = &ibmvtpm->crq_queue; + crq_q->crq_addr = (struct ibmvtpm_crq *)get_zeroed_page(GFP_KERNEL); + if (!crq_q->crq_addr) { +@@ -623,8 +626,6 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, + + crq_q->index = 0; + +- ibmvtpm->dev = dev; +- ibmvtpm->vdev = vio_dev; + TPM_VPRIV(chip) = (void *)ibmvtpm; + + spin_lock_init(&ibmvtpm->rtce_lock); +diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c +index 831b48287a22..ddd03f8037a7 100644 +--- a/drivers/clocksource/exynos_mct.c ++++ b/drivers/clocksource/exynos_mct.c +@@ -422,15 +422,12 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) + exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET); + + if (mct_int_type == MCT_INT_SPI) { +- evt->irq = mct_irqs[MCT_L0_IRQ + cpu]; +- if (request_irq(evt->irq, exynos4_mct_tick_isr, +- IRQF_TIMER | IRQF_NOBALANCING, +- evt->name, mevt)) { +- pr_err("exynos-mct: cannot register IRQ %d\n", +- evt->irq); ++ ++ if (evt->irq == -1) + return -EIO; +- } +- irq_force_affinity(mct_irqs[MCT_L0_IRQ + cpu], cpumask_of(cpu)); ++ ++ irq_force_affinity(evt->irq, cpumask_of(cpu)); ++ enable_irq(evt->irq); + } else { + enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0); + } +@@ -443,10 +440,12 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) + static void exynos4_local_timer_stop(struct clock_event_device *evt) + { + evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); +- if (mct_int_type == MCT_INT_SPI) +- free_irq(evt->irq, this_cpu_ptr(&percpu_mct_tick)); +- else ++ if (mct_int_type == MCT_INT_SPI) { ++ if (evt->irq != -1) ++ disable_irq_nosync(evt->irq); ++ } else { + disable_percpu_irq(mct_irqs[MCT_L0_IRQ]); ++ } + } + + static int exynos4_mct_cpu_notify(struct notifier_block *self, +@@ -478,7 +477,7 @@ static struct notifier_block exynos4_mct_cpu_nb = { + + static void __init exynos4_timer_resources(struct device_node *np, void __iomem *base) + { +- int err; ++ int err, cpu; + struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); + struct clk *mct_clk, *tick_clk; + +@@ -505,7 +504,25 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomem + WARN(err, "MCT: can't request IRQ %d (%d)\n", + mct_irqs[MCT_L0_IRQ], err); + } else { +- irq_set_affinity(mct_irqs[MCT_L0_IRQ], cpumask_of(0)); ++ for_each_possible_cpu(cpu) { ++ int mct_irq = mct_irqs[MCT_L0_IRQ + cpu]; ++ struct mct_clock_event_device *pcpu_mevt = ++ per_cpu_ptr(&percpu_mct_tick, cpu); ++ ++ pcpu_mevt->evt.irq = -1; ++ ++ irq_set_status_flags(mct_irq, IRQ_NOAUTOEN); ++ if (request_irq(mct_irq, ++ exynos4_mct_tick_isr, ++ IRQF_TIMER | IRQF_NOBALANCING, ++ pcpu_mevt->name, pcpu_mevt)) { ++ pr_err("exynos-mct: cannot register IRQ (cpu%d)\n", ++ cpu); ++ ++ continue; ++ } ++ pcpu_mevt->evt.irq = mct_irq; ++ } + } + + err = register_cpu_notifier(&exynos4_mct_cpu_nb); +diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c +index e3d2052e7552..1adc039fe74d 100644 +--- a/drivers/cpuidle/cpuidle.c ++++ b/drivers/cpuidle/cpuidle.c +@@ -131,6 +131,9 @@ int cpuidle_idle_call(void) + + /* ask the governor for the next state */ + next_state = cpuidle_curr_governor->select(drv, dev); ++ if (next_state < 0) ++ return -EBUSY; ++ + if (need_resched()) { + dev->last_residency = 0; + /* give the governor an opportunity to reflect on the outcome */ +diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c +index cf7f2f0e4ef5..027c484e1ec9 100644 +--- a/drivers/cpuidle/governors/menu.c ++++ b/drivers/cpuidle/governors/menu.c +@@ -297,7 +297,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) + data->needs_update = 0; + } + +- data->last_state_idx = 0; ++ data->last_state_idx = CPUIDLE_DRIVER_STATE_START - 1; + data->exit_us = 0; + + /* Special case when user has set very strict latency requirement */ +diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c +index 394cbc5c93e3..6b2f01d60527 100644 +--- a/drivers/dma/mv_xor.c ++++ b/drivers/dma/mv_xor.c +@@ -316,7 +316,8 @@ static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan) + dma_cookie_t cookie = 0; + int busy = mv_chan_is_busy(mv_chan); + u32 current_desc = mv_chan_get_current_desc(mv_chan); +- int seen_current = 0; ++ int current_cleaned = 0; ++ struct mv_xor_desc *hw_desc; + + dev_dbg(mv_chan_to_devp(mv_chan), "%s %d\n", __func__, __LINE__); + dev_dbg(mv_chan_to_devp(mv_chan), "current_desc %x\n", current_desc); +@@ -328,38 +329,57 @@ static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan) + + list_for_each_entry_safe(iter, _iter, &mv_chan->chain, + chain_node) { +- prefetch(_iter); +- prefetch(&_iter->async_tx); + +- /* do not advance past the current descriptor loaded into the +- * hardware channel, subsequent descriptors are either in +- * process or have not been submitted +- */ +- if (seen_current) +- break; ++ /* clean finished descriptors */ ++ hw_desc = iter->hw_desc; ++ if (hw_desc->status & XOR_DESC_SUCCESS) { ++ cookie = mv_xor_run_tx_complete_actions(iter, mv_chan, ++ cookie); + +- /* stop the search if we reach the current descriptor and the +- * channel is busy +- */ +- if (iter->async_tx.phys == current_desc) { +- seen_current = 1; +- if (busy) ++ /* done processing desc, clean slot */ ++ mv_xor_clean_slot(iter, mv_chan); ++ ++ /* break if we did cleaned the current */ ++ if (iter->async_tx.phys == current_desc) { ++ current_cleaned = 1; ++ break; ++ } ++ } else { ++ if (iter->async_tx.phys == current_desc) { ++ current_cleaned = 0; + break; ++ } + } +- +- cookie = mv_xor_run_tx_complete_actions(iter, mv_chan, cookie); +- +- if (mv_xor_clean_slot(iter, mv_chan)) +- break; + } + + if ((busy == 0) && !list_empty(&mv_chan->chain)) { +- struct mv_xor_desc_slot *chain_head; +- chain_head = list_entry(mv_chan->chain.next, +- struct mv_xor_desc_slot, +- chain_node); +- +- mv_xor_start_new_chain(mv_chan, chain_head); ++ if (current_cleaned) { ++ /* ++ * current descriptor cleaned and removed, run ++ * from list head ++ */ ++ iter = list_entry(mv_chan->chain.next, ++ struct mv_xor_desc_slot, ++ chain_node); ++ mv_xor_start_new_chain(mv_chan, iter); ++ } else { ++ if (!list_is_last(&iter->chain_node, &mv_chan->chain)) { ++ /* ++ * descriptors are still waiting after ++ * current, trigger them ++ */ ++ iter = list_entry(iter->chain_node.next, ++ struct mv_xor_desc_slot, ++ chain_node); ++ mv_xor_start_new_chain(mv_chan, iter); ++ } else { ++ /* ++ * some descriptors are still waiting ++ * to be cleaned ++ */ ++ tasklet_schedule(&mv_chan->irq_tasklet); ++ } ++ } + } + + if (cookie > 0) +diff --git a/drivers/dma/mv_xor.h b/drivers/dma/mv_xor.h +index d0749229c875..5d14e4b21692 100644 +--- a/drivers/dma/mv_xor.h ++++ b/drivers/dma/mv_xor.h +@@ -33,6 +33,7 @@ + #define XOR_OPERATION_MODE_XOR 0 + #define XOR_OPERATION_MODE_MEMCPY 2 + #define XOR_DESCRIPTOR_SWAP BIT(14) ++#define XOR_DESC_SUCCESS 0x40000000 + + #define XOR_CURR_DESC(chan) (chan->mmr_high_base + 0x10 + (chan->idx * 4)) + #define XOR_NEXT_DESC(chan) (chan->mmr_high_base + 0x00 + (chan->idx * 4)) +diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c +index 3b7d32da1604..903db3cf288a 100644 +--- a/drivers/gpu/drm/drm_crtc.c ++++ b/drivers/gpu/drm/drm_crtc.c +@@ -2155,8 +2155,11 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + +- /* For some reason crtc x/y offsets are signed internally. */ +- if (crtc_req->x > INT_MAX || crtc_req->y > INT_MAX) ++ /* ++ * Universal plane src offsets are only 16.16, prevent havoc for ++ * drivers using universal plane code internally. ++ */ ++ if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000) + return -ERANGE; + + drm_modeset_lock_all(dev); +diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c +index eb89653a7a17..c5e96a38f859 100644 +--- a/drivers/gpu/drm/qxl/qxl_cmd.c ++++ b/drivers/gpu/drm/qxl/qxl_cmd.c +@@ -505,6 +505,7 @@ int qxl_hw_surface_alloc(struct qxl_device *qdev, + + cmd = (struct qxl_surface_cmd *)qxl_release_map(qdev, release); + cmd->type = QXL_SURFACE_CMD_CREATE; ++ cmd->flags = QXL_SURF_FLAG_KEEP_DATA; + cmd->u.surface_create.format = surf->surf.format; + cmd->u.surface_create.width = surf->surf.width; + cmd->u.surface_create.height = surf->surf.height; +diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c +index 0bb86e6d41b4..56a13a915155 100644 +--- a/drivers/gpu/drm/qxl/qxl_ioctl.c ++++ b/drivers/gpu/drm/qxl/qxl_ioctl.c +@@ -122,8 +122,10 @@ static struct qxl_bo *qxlhw_handle_to_bo(struct qxl_device *qdev, + qobj = gem_to_qxl_bo(gobj); + + ret = qxl_release_list_add(release, qobj); +- if (ret) ++ if (ret) { ++ drm_gem_object_unreference_unlocked(gobj); + return NULL; ++ } + + return qobj; + } +diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c +index c4558bdb0584..2fd2fb3f735f 100644 +--- a/drivers/gpu/drm/radeon/cik.c ++++ b/drivers/gpu/drm/radeon/cik.c +@@ -4148,6 +4148,31 @@ void cik_compute_set_wptr(struct radeon_device *rdev, + WDOORBELL32(ring->doorbell_index, ring->wptr); + } + ++static void cik_compute_stop(struct radeon_device *rdev, ++ struct radeon_ring *ring) ++{ ++ u32 j, tmp; ++ ++ cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0); ++ /* Disable wptr polling. */ ++ tmp = RREG32(CP_PQ_WPTR_POLL_CNTL); ++ tmp &= ~WPTR_POLL_EN; ++ WREG32(CP_PQ_WPTR_POLL_CNTL, tmp); ++ /* Disable HQD. */ ++ if (RREG32(CP_HQD_ACTIVE) & 1) { ++ WREG32(CP_HQD_DEQUEUE_REQUEST, 1); ++ for (j = 0; j < rdev->usec_timeout; j++) { ++ if (!(RREG32(CP_HQD_ACTIVE) & 1)) ++ break; ++ udelay(1); ++ } ++ WREG32(CP_HQD_DEQUEUE_REQUEST, 0); ++ WREG32(CP_HQD_PQ_RPTR, 0); ++ WREG32(CP_HQD_PQ_WPTR, 0); ++ } ++ cik_srbm_select(rdev, 0, 0, 0, 0); ++} ++ + /** + * cik_cp_compute_enable - enable/disable the compute CP MEs + * +@@ -4161,6 +4186,15 @@ static void cik_cp_compute_enable(struct radeon_device *rdev, bool enable) + if (enable) + WREG32(CP_MEC_CNTL, 0); + else { ++ /* ++ * To make hibernation reliable we need to clear compute ring ++ * configuration before halting the compute ring. ++ */ ++ mutex_lock(&rdev->srbm_mutex); ++ cik_compute_stop(rdev,&rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]); ++ cik_compute_stop(rdev,&rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]); ++ mutex_unlock(&rdev->srbm_mutex); ++ + WREG32(CP_MEC_CNTL, (MEC_ME1_HALT | MEC_ME2_HALT)); + rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; + rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; +diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c +index 66ba713ba7d7..e590aec50c7d 100644 +--- a/drivers/gpu/drm/radeon/cik_sdma.c ++++ b/drivers/gpu/drm/radeon/cik_sdma.c +@@ -266,6 +266,17 @@ static void cik_sdma_gfx_stop(struct radeon_device *rdev) + } + rdev->ring[R600_RING_TYPE_DMA_INDEX].ready = false; + rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready = false; ++ ++ /* FIXME use something else than big hammer but after few days can not ++ * seem to find good combination so reset SDMA blocks as it seems we ++ * do not shut them down properly. This fix hibernation and does not ++ * affect suspend to ram. ++ */ ++ WREG32(SRBM_SOFT_RESET, SOFT_RESET_SDMA | SOFT_RESET_SDMA1); ++ (void)RREG32(SRBM_SOFT_RESET); ++ udelay(50); ++ WREG32(SRBM_SOFT_RESET, 0); ++ (void)RREG32(SRBM_SOFT_RESET); + } + + /** +diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c +index a8f9b463bf2a..e60972290be6 100644 +--- a/drivers/gpu/drm/radeon/radeon_gart.c ++++ b/drivers/gpu/drm/radeon/radeon_gart.c +@@ -251,8 +251,10 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, + } + } + } +- mb(); +- radeon_gart_tlb_flush(rdev); ++ if (rdev->gart.ptr) { ++ mb(); ++ radeon_gart_tlb_flush(rdev); ++ } + } + + /** +@@ -294,8 +296,10 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, + } + } + } +- mb(); +- radeon_gart_tlb_flush(rdev); ++ if (rdev->gart.ptr) { ++ mb(); ++ radeon_gart_tlb_flush(rdev); ++ } + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c +index b3f0293ba0d8..f8b20e1c0820 100644 +--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c ++++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c +@@ -79,10 +79,12 @@ static void radeon_hotplug_work_func(struct work_struct *work) + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_connector *connector; + ++ mutex_lock(&mode_config->mutex); + if (mode_config->num_connector) { + list_for_each_entry(connector, &mode_config->connector_list, head) + radeon_connector_hotplug(connector); + } ++ mutex_unlock(&mode_config->mutex); + /* Just fire off a uevent and let userspace tell us what to do */ + drm_helper_hpd_irq_event(dev); + } +diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c +index 11804cc1e11f..c9053f799abe 100644 +--- a/drivers/gpu/drm/radeon/si_dpm.c ++++ b/drivers/gpu/drm/radeon/si_dpm.c +@@ -2914,6 +2914,7 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = { + /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */ + { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 }, + { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 }, ++ { PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 }, + { 0, 0, 0, 0 }, + }; + +diff --git a/drivers/hwmon/mcp3021.c b/drivers/hwmon/mcp3021.c +index d219c06a857b..972444a14cca 100644 +--- a/drivers/hwmon/mcp3021.c ++++ b/drivers/hwmon/mcp3021.c +@@ -31,14 +31,11 @@ + /* output format */ + #define MCP3021_SAR_SHIFT 2 + #define MCP3021_SAR_MASK 0x3ff +- + #define MCP3021_OUTPUT_RES 10 /* 10-bit resolution */ +-#define MCP3021_OUTPUT_SCALE 4 + + #define MCP3221_SAR_SHIFT 0 + #define MCP3221_SAR_MASK 0xfff + #define MCP3221_OUTPUT_RES 12 /* 12-bit resolution */ +-#define MCP3221_OUTPUT_SCALE 1 + + enum chips { + mcp3021, +@@ -54,7 +51,6 @@ struct mcp3021_data { + u16 sar_shift; + u16 sar_mask; + u8 output_res; +- u8 output_scale; + }; + + static int mcp3021_read16(struct i2c_client *client) +@@ -84,13 +80,7 @@ static int mcp3021_read16(struct i2c_client *client) + + static inline u16 volts_from_reg(struct mcp3021_data *data, u16 val) + { +- if (val == 0) +- return 0; +- +- val = val * data->output_scale - data->output_scale / 2; +- +- return val * DIV_ROUND_CLOSEST(data->vdd, +- (1 << data->output_res) * data->output_scale); ++ return DIV_ROUND_CLOSEST(data->vdd * val, 1 << data->output_res); + } + + static ssize_t show_in_input(struct device *dev, struct device_attribute *attr, +@@ -132,14 +122,12 @@ static int mcp3021_probe(struct i2c_client *client, + data->sar_shift = MCP3021_SAR_SHIFT; + data->sar_mask = MCP3021_SAR_MASK; + data->output_res = MCP3021_OUTPUT_RES; +- data->output_scale = MCP3021_OUTPUT_SCALE; + break; + + case mcp3221: + data->sar_shift = MCP3221_SAR_SHIFT; + data->sar_mask = MCP3221_SAR_MASK; + data->output_res = MCP3221_OUTPUT_RES; +- data->output_scale = MCP3221_OUTPUT_SCALE; + break; + } + +diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c +index 8873d84e1d4f..50862c948217 100644 +--- a/drivers/i2c/busses/i2c-at91.c ++++ b/drivers/i2c/busses/i2c-at91.c +@@ -62,6 +62,9 @@ + #define AT91_TWI_UNRE 0x0080 /* Underrun Error */ + #define AT91_TWI_NACK 0x0100 /* Not Acknowledged */ + ++#define AT91_TWI_INT_MASK \ ++ (AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY | AT91_TWI_NACK) ++ + #define AT91_TWI_IER 0x0024 /* Interrupt Enable Register */ + #define AT91_TWI_IDR 0x0028 /* Interrupt Disable Register */ + #define AT91_TWI_IMR 0x002c /* Interrupt Mask Register */ +@@ -117,13 +120,12 @@ static void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, unsigned val) + + static void at91_disable_twi_interrupts(struct at91_twi_dev *dev) + { +- at91_twi_write(dev, AT91_TWI_IDR, +- AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY); ++ at91_twi_write(dev, AT91_TWI_IDR, AT91_TWI_INT_MASK); + } + + static void at91_twi_irq_save(struct at91_twi_dev *dev) + { +- dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & 0x7; ++ dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & AT91_TWI_INT_MASK; + at91_disable_twi_interrupts(dev); + } + +@@ -213,6 +215,14 @@ static void at91_twi_write_data_dma_callback(void *data) + dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg), + dev->buf_len, DMA_TO_DEVICE); + ++ /* ++ * When this callback is called, THR/TX FIFO is likely not to be empty ++ * yet. So we have to wait for TXCOMP or NACK bits to be set into the ++ * Status Register to be sure that the STOP bit has been sent and the ++ * transfer is completed. The NACK interrupt has already been enabled, ++ * we just have to enable TXCOMP one. ++ */ ++ at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP); + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP); + } + +@@ -307,7 +317,7 @@ static void at91_twi_read_data_dma_callback(void *data) + /* The last two bytes have to be read without using dma */ + dev->buf += dev->buf_len - 2; + dev->buf_len = 2; +- at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_RXRDY); ++ at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_RXRDY | AT91_TWI_TXCOMP); + } + + static void at91_twi_read_data_dma(struct at91_twi_dev *dev) +@@ -368,7 +378,7 @@ static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id) + /* catch error flags */ + dev->transfer_status |= status; + +- if (irqstatus & AT91_TWI_TXCOMP) { ++ if (irqstatus & (AT91_TWI_TXCOMP | AT91_TWI_NACK)) { + at91_disable_twi_interrupts(dev); + complete(&dev->cmd_complete); + } +@@ -381,6 +391,34 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) + int ret; + bool has_unre_flag = dev->pdata->has_unre_flag; + ++ /* ++ * WARNING: the TXCOMP bit in the Status Register is NOT a clear on ++ * read flag but shows the state of the transmission at the time the ++ * Status Register is read. According to the programmer datasheet, ++ * TXCOMP is set when both holding register and internal shifter are ++ * empty and STOP condition has been sent. ++ * Consequently, we should enable NACK interrupt rather than TXCOMP to ++ * detect transmission failure. ++ * ++ * Besides, the TXCOMP bit is already set before the i2c transaction ++ * has been started. For read transactions, this bit is cleared when ++ * writing the START bit into the Control Register. So the ++ * corresponding interrupt can safely be enabled just after. ++ * However for write transactions managed by the CPU, we first write ++ * into THR, so TXCOMP is cleared. Then we can safely enable TXCOMP ++ * interrupt. If TXCOMP interrupt were enabled before writing into THR, ++ * the interrupt handler would be called immediately and the i2c command ++ * would be reported as completed. ++ * Also when a write transaction is managed by the DMA controller, ++ * enabling the TXCOMP interrupt in this function may lead to a race ++ * condition since we don't know whether the TXCOMP interrupt is enabled ++ * before or after the DMA has started to write into THR. So the TXCOMP ++ * interrupt is enabled later by at91_twi_write_data_dma_callback(). ++ * Immediately after in that DMA callback, we still need to send the ++ * STOP condition manually writing the corresponding bit into the ++ * Control Register. ++ */ ++ + dev_dbg(dev->dev, "transfer: %s %d bytes.\n", + (dev->msg->flags & I2C_M_RD) ? "read" : "write", dev->buf_len); + +@@ -411,26 +449,24 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) + * seems to be the best solution. + */ + if (dev->use_dma && (dev->buf_len > AT91_I2C_DMA_THRESHOLD)) { ++ at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_NACK); + at91_twi_read_data_dma(dev); +- /* +- * It is important to enable TXCOMP irq here because +- * doing it only when transferring the last two bytes +- * will mask NACK errors since TXCOMP is set when a +- * NACK occurs. +- */ +- at91_twi_write(dev, AT91_TWI_IER, +- AT91_TWI_TXCOMP); +- } else ++ } else { + at91_twi_write(dev, AT91_TWI_IER, +- AT91_TWI_TXCOMP | AT91_TWI_RXRDY); ++ AT91_TWI_TXCOMP | ++ AT91_TWI_NACK | ++ AT91_TWI_RXRDY); ++ } + } else { + if (dev->use_dma && (dev->buf_len > AT91_I2C_DMA_THRESHOLD)) { ++ at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_NACK); + at91_twi_write_data_dma(dev); +- at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP); + } else { + at91_twi_write_next_byte(dev); + at91_twi_write(dev, AT91_TWI_IER, +- AT91_TWI_TXCOMP | AT91_TWI_TXRDY); ++ AT91_TWI_TXCOMP | ++ AT91_TWI_NACK | ++ AT91_TWI_TXRDY); + } + } + +diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c +index e6bf77d1ec08..ed4e45f53e20 100644 +--- a/drivers/iio/adc/at91_adc.c ++++ b/drivers/iio/adc/at91_adc.c +@@ -58,7 +58,7 @@ struct at91_adc_caps { + u8 ts_pen_detect_sensitivity; + + /* startup time calculate function */ +- u32 (*calc_startup_ticks)(u8 startup_time, u32 adc_clk_khz); ++ u32 (*calc_startup_ticks)(u32 startup_time, u32 adc_clk_khz); + + u8 num_channels; + struct at91_adc_reg_desc registers; +@@ -82,7 +82,7 @@ struct at91_adc_state { + u8 num_channels; + void __iomem *reg_base; + struct at91_adc_reg_desc *registers; +- u8 startup_time; ++ u32 startup_time; + u8 sample_hold_time; + bool sleep_mode; + struct iio_trigger **trig; +@@ -590,7 +590,7 @@ ret: + return ret; + } + +-static u32 calc_startup_ticks_9260(u8 startup_time, u32 adc_clk_khz) ++static u32 calc_startup_ticks_9260(u32 startup_time, u32 adc_clk_khz) + { + /* + * Number of ticks needed to cover the startup time of the ADC +@@ -601,7 +601,7 @@ static u32 calc_startup_ticks_9260(u8 startup_time, u32 adc_clk_khz) + return round_up((startup_time * adc_clk_khz / 1000) - 1, 8) / 8; + } + +-static u32 calc_startup_ticks_9x5(u8 startup_time, u32 adc_clk_khz) ++static u32 calc_startup_ticks_9x5(u32 startup_time, u32 adc_clk_khz) + { + /* + * For sama5d3x and at91sam9x5, the formula changes to: +diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c +index e8199cce2aea..1e666510c672 100644 +--- a/drivers/iio/dac/ad5624r_spi.c ++++ b/drivers/iio/dac/ad5624r_spi.c +@@ -22,7 +22,7 @@ + #include "ad5624r.h" + + static int ad5624r_spi_write(struct spi_device *spi, +- u8 cmd, u8 addr, u16 val, u8 len) ++ u8 cmd, u8 addr, u16 val, u8 shift) + { + u32 data; + u8 msg[3]; +@@ -35,7 +35,7 @@ static int ad5624r_spi_write(struct spi_device *spi, + * 14-, 12-bit input code followed by 0, 2, or 4 don't care bits, + * for the AD5664R, AD5644R, and AD5624R, respectively. + */ +- data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << (16 - len)); ++ data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << shift); + msg[0] = data >> 16; + msg[1] = data >> 8; + msg[2] = data; +diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c +index 84a0789c3d96..7a8050996b4e 100644 +--- a/drivers/iio/temperature/tmp006.c ++++ b/drivers/iio/temperature/tmp006.c +@@ -132,6 +132,9 @@ static int tmp006_write_raw(struct iio_dev *indio_dev, + struct tmp006_data *data = iio_priv(indio_dev); + int i; + ++ if (mask != IIO_CHAN_INFO_SAMP_FREQ) ++ return -EINVAL; ++ + for (i = 0; i < ARRAY_SIZE(tmp006_freqs); i++) + if ((val == tmp006_freqs[i][0]) && + (val2 == tmp006_freqs[i][1])) { +diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c +index 60142274fe4b..dd2b610552d5 100644 +--- a/drivers/infiniband/ulp/isert/ib_isert.c ++++ b/drivers/infiniband/ulp/isert/ib_isert.c +@@ -59,6 +59,8 @@ static int + isert_rdma_accept(struct isert_conn *isert_conn); + struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np); + ++static void isert_release_work(struct work_struct *work); ++ + static void + isert_qp_event_callback(struct ib_event *e, void *context) + { +@@ -206,7 +208,7 @@ fail: + static void + isert_free_rx_descriptors(struct isert_conn *isert_conn) + { +- struct ib_device *ib_dev = isert_conn->conn_cm_id->device; ++ struct ib_device *ib_dev = isert_conn->conn_device->ib_device; + struct iser_rx_desc *rx_desc; + int i; + +@@ -534,6 +536,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + mutex_init(&isert_conn->conn_mutex); + spin_lock_init(&isert_conn->conn_lock); + INIT_LIST_HEAD(&isert_conn->conn_fr_pool); ++ INIT_WORK(&isert_conn->release_work, isert_release_work); + + isert_conn->conn_cm_id = cma_id; + isert_conn->responder_resources = event->param.conn.responder_resources; +@@ -647,9 +650,9 @@ out: + static void + isert_connect_release(struct isert_conn *isert_conn) + { +- struct ib_device *ib_dev = isert_conn->conn_cm_id->device; + struct isert_device *device = isert_conn->conn_device; + int cq_index; ++ struct ib_device *ib_dev = device->ib_device; + + pr_debug("Entering isert_connect_release(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); + +@@ -657,7 +660,8 @@ isert_connect_release(struct isert_conn *isert_conn) + isert_conn_free_fastreg_pool(isert_conn); + + isert_free_rx_descriptors(isert_conn); +- rdma_destroy_id(isert_conn->conn_cm_id); ++ if (isert_conn->conn_cm_id) ++ rdma_destroy_id(isert_conn->conn_cm_id); + + if (isert_conn->conn_qp) { + cq_index = ((struct isert_cq_desc *) +@@ -799,6 +803,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id, + { + struct isert_np *isert_np = cma_id->context; + struct isert_conn *isert_conn; ++ bool terminating = false; + + if (isert_np->np_cm_id == cma_id) + return isert_np_cma_handler(cma_id->context, event); +@@ -806,21 +811,37 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id, + isert_conn = cma_id->qp->qp_context; + + mutex_lock(&isert_conn->conn_mutex); ++ terminating = (isert_conn->state == ISER_CONN_TERMINATING); + isert_conn_terminate(isert_conn); + mutex_unlock(&isert_conn->conn_mutex); + + pr_info("conn %p completing conn_wait\n", isert_conn); + complete(&isert_conn->conn_wait); + ++ if (terminating) ++ goto out; ++ ++ mutex_lock(&isert_np->np_accept_mutex); ++ if (!list_empty(&isert_conn->conn_accept_node)) { ++ list_del_init(&isert_conn->conn_accept_node); ++ isert_put_conn(isert_conn); ++ queue_work(isert_release_wq, &isert_conn->release_work); ++ } ++ mutex_unlock(&isert_np->np_accept_mutex); ++ ++out: + return 0; + } + +-static void ++static int + isert_connect_error(struct rdma_cm_id *cma_id) + { + struct isert_conn *isert_conn = cma_id->qp->qp_context; + ++ isert_conn->conn_cm_id = NULL; + isert_put_conn(isert_conn); ++ ++ return -1; + } + + static int +@@ -850,7 +871,7 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + case RDMA_CM_EVENT_REJECTED: /* FALLTHRU */ + case RDMA_CM_EVENT_UNREACHABLE: /* FALLTHRU */ + case RDMA_CM_EVENT_CONNECT_ERROR: +- isert_connect_error(cma_id); ++ ret = isert_connect_error(cma_id); + break; + default: + pr_err("Unhandled RDMA CMA event: %d\n", event->event); +@@ -2944,7 +2965,6 @@ static void isert_wait_conn(struct iscsi_conn *conn) + + wait_for_completion(&isert_conn->conn_wait_comp_err); + +- INIT_WORK(&isert_conn->release_work, isert_release_work); + queue_work(isert_release_wq, &isert_conn->release_work); + } + +diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c +index f37d63cf726b..825545cdfb10 100644 +--- a/drivers/leds/led-class.c ++++ b/drivers/leds/led-class.c +@@ -178,6 +178,7 @@ void led_classdev_resume(struct led_classdev *led_cdev) + } + EXPORT_SYMBOL_GPL(led_classdev_resume); + ++#ifdef CONFIG_PM_SLEEP + static int led_suspend(struct device *dev) + { + struct led_classdev *led_cdev = dev_get_drvdata(dev); +@@ -197,11 +198,9 @@ static int led_resume(struct device *dev) + + return 0; + } ++#endif + +-static const struct dev_pm_ops leds_class_dev_pm_ops = { +- .suspend = led_suspend, +- .resume = led_resume, +-}; ++static SIMPLE_DEV_PM_OPS(leds_class_dev_pm_ops, led_suspend, led_resume); + + /** + * led_classdev_register - register a new object of led_classdev class. +diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c +index 28a90122a5a8..b3b0697a9fd7 100644 +--- a/drivers/md/dm-stats.c ++++ b/drivers/md/dm-stats.c +@@ -795,6 +795,8 @@ static int message_stats_create(struct mapped_device *md, + return -EINVAL; + + if (sscanf(argv[2], "/%u%c", &divisor, &dummy) == 1) { ++ if (!divisor) ++ return -EINVAL; + step = end - start; + if (do_div(step, divisor)) + step++; +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 40959ee73583..b4067b9afd38 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -6232,7 +6232,7 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info) + mddev->ctime != info->ctime || + mddev->level != info->level || + /* mddev->layout != info->layout || */ +- !mddev->persistent != info->not_persistent|| ++ mddev->persistent != !info->not_persistent || + mddev->chunk_sectors != info->chunk_size >> 9 || + /* ignore bottom 8 bits of state, and allow SB_BITMAP_PRESENT to change */ + ((state^info->state) & 0xfffffe00) +diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c +index b88757cd0d1d..a03178e91a79 100644 +--- a/drivers/md/persistent-data/dm-btree-remove.c ++++ b/drivers/md/persistent-data/dm-btree-remove.c +@@ -309,8 +309,8 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, + + if (s < 0 && nr_center < -s) { + /* not enough in central node */ +- shift(left, center, nr_center); +- s = nr_center - target; ++ shift(left, center, -nr_center); ++ s += nr_center; + shift(left, right, s); + nr_right += s; + } else +@@ -323,7 +323,7 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, + if (s > 0 && nr_center < s) { + /* not enough in central node */ + shift(center, right, nr_center); +- s = target - nr_center; ++ s -= nr_center; + shift(left, right, s); + nr_left -= s; + } else +diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c +index 200ac12a1d40..fdd3793e22f9 100644 +--- a/drivers/md/persistent-data/dm-btree.c ++++ b/drivers/md/persistent-data/dm-btree.c +@@ -255,7 +255,7 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root) + int r; + struct del_stack *s; + +- s = kmalloc(sizeof(*s), GFP_KERNEL); ++ s = kmalloc(sizeof(*s), GFP_NOIO); + if (!s) + return -ENOMEM; + s->info = info; +diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c +index f4e22bcc7fb8..199c9ccd1f5d 100644 +--- a/drivers/md/persistent-data/dm-space-map-metadata.c ++++ b/drivers/md/persistent-data/dm-space-map-metadata.c +@@ -204,6 +204,27 @@ static void in(struct sm_metadata *smm) + smm->recursion_count++; + } + ++static int apply_bops(struct sm_metadata *smm) ++{ ++ int r = 0; ++ ++ while (!brb_empty(&smm->uncommitted)) { ++ struct block_op bop; ++ ++ r = brb_pop(&smm->uncommitted, &bop); ++ if (r) { ++ DMERR("bug in bop ring buffer"); ++ break; ++ } ++ ++ r = commit_bop(smm, &bop); ++ if (r) ++ break; ++ } ++ ++ return r; ++} ++ + static int out(struct sm_metadata *smm) + { + int r = 0; +@@ -216,21 +237,8 @@ static int out(struct sm_metadata *smm) + return -ENOMEM; + } + +- if (smm->recursion_count == 1) { +- while (!brb_empty(&smm->uncommitted)) { +- struct block_op bop; +- +- r = brb_pop(&smm->uncommitted, &bop); +- if (r) { +- DMERR("bug in bop ring buffer"); +- break; +- } +- +- r = commit_bop(smm, &bop); +- if (r) +- break; +- } +- } ++ if (smm->recursion_count == 1) ++ apply_bops(smm); + + smm->recursion_count--; + +@@ -702,6 +710,12 @@ static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks) + } + old_len = smm->begin; + ++ r = apply_bops(smm); ++ if (r) { ++ DMERR("%s: apply_bops failed", __func__); ++ goto out; ++ } ++ + r = sm_ll_commit(&smm->ll); + if (r) + goto out; +@@ -771,6 +785,12 @@ int dm_sm_metadata_create(struct dm_space_map *sm, + if (r) + return r; + ++ r = apply_bops(smm); ++ if (r) { ++ DMERR("%s: apply_bops failed", __func__); ++ return r; ++ } ++ + return sm_metadata_commit(sm); + } + +diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c +index fb504f1e9125..5930aee6b5d0 100644 +--- a/drivers/media/dvb-frontends/af9013.c ++++ b/drivers/media/dvb-frontends/af9013.c +@@ -606,6 +606,10 @@ static int af9013_set_frontend(struct dvb_frontend *fe) + } + } + ++ /* Return an error if can't find bandwidth or the right clock */ ++ if (i == ARRAY_SIZE(coeff_lut)) ++ return -EINVAL; ++ + ret = af9013_wr_regs(state, 0xae00, coeff_lut[i].val, + sizeof(coeff_lut[i].val)); + } +diff --git a/drivers/media/dvb-frontends/cx24116.c b/drivers/media/dvb-frontends/cx24116.c +index 2916d7c74a1d..7bc68b355c0b 100644 +--- a/drivers/media/dvb-frontends/cx24116.c ++++ b/drivers/media/dvb-frontends/cx24116.c +@@ -963,6 +963,10 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend *fe, + struct cx24116_state *state = fe->demodulator_priv; + int i, ret; + ++ /* Validate length */ ++ if (d->msg_len > sizeof(d->msg)) ++ return -EINVAL; ++ + /* Dump DiSEqC message */ + if (debug) { + printk(KERN_INFO "cx24116: %s(", __func__); +@@ -974,10 +978,6 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend *fe, + printk(") toneburst=%d\n", toneburst); + } + +- /* Validate length */ +- if (d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS)) +- return -EINVAL; +- + /* DiSEqC message */ + for (i = 0; i < d->msg_len; i++) + state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i]; +diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c +index a6c3c9e2e897..d2eab0676d30 100644 +--- a/drivers/media/dvb-frontends/cx24117.c ++++ b/drivers/media/dvb-frontends/cx24117.c +@@ -1043,7 +1043,7 @@ static int cx24117_send_diseqc_msg(struct dvb_frontend *fe, + dev_dbg(&state->priv->i2c->dev, ")\n"); + + /* Validate length */ +- if (d->msg_len > 15) ++ if (d->msg_len > sizeof(d->msg)) + return -EINVAL; + + /* DiSEqC message */ +diff --git a/drivers/media/dvb-frontends/s5h1420.c b/drivers/media/dvb-frontends/s5h1420.c +index 93eeaf7118fd..0b4f8fe6bf99 100644 +--- a/drivers/media/dvb-frontends/s5h1420.c ++++ b/drivers/media/dvb-frontends/s5h1420.c +@@ -180,7 +180,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, + int result = 0; + + dprintk("enter %s\n", __func__); +- if (cmd->msg_len > 8) ++ if (cmd->msg_len > sizeof(cmd->msg)) + return -EINVAL; + + /* setup for DISEQC */ +diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c +index b1e21fc869c3..d71f5ef036e0 100644 +--- a/drivers/mmc/card/block.c ++++ b/drivers/mmc/card/block.c +@@ -205,6 +205,8 @@ static ssize_t power_ro_lock_show(struct device *dev, + + ret = snprintf(buf, PAGE_SIZE, "%d\n", locked); + ++ mmc_blk_put(md); ++ + return ret; + } + +@@ -1861,9 +1863,11 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) + break; + case MMC_BLK_CMD_ERR: + ret = mmc_blk_cmd_err(md, card, brq, req, ret); +- if (!mmc_blk_reset(md, card->host, type)) +- break; +- goto cmd_abort; ++ if (mmc_blk_reset(md, card->host, type)) ++ goto cmd_abort; ++ if (!ret) ++ goto start_new_req; ++ break; + case MMC_BLK_RETRY: + if (retry++ < 5) + break; +diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c +index f8a7dd14cee0..70a3db3ab856 100644 +--- a/drivers/mtd/maps/dc21285.c ++++ b/drivers/mtd/maps/dc21285.c +@@ -38,9 +38,9 @@ static void nw_en_write(void) + * we want to write a bit pattern XXX1 to Xilinx to enable + * the write gate, which will be open for about the next 2ms. + */ +- spin_lock_irqsave(&nw_gpio_lock, flags); ++ raw_spin_lock_irqsave(&nw_gpio_lock, flags); + nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE); +- spin_unlock_irqrestore(&nw_gpio_lock, flags); ++ raw_spin_unlock_irqrestore(&nw_gpio_lock, flags); + + /* + * let the ISA bus to catch on... +diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c +index 5073cbc796d8..32d5e40c6863 100644 +--- a/drivers/mtd/mtd_blkdevs.c ++++ b/drivers/mtd/mtd_blkdevs.c +@@ -199,6 +199,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode) + return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ + + mutex_lock(&dev->lock); ++ mutex_lock(&mtd_table_mutex); + + if (dev->open) + goto unlock; +@@ -222,6 +223,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode) + + unlock: + dev->open++; ++ mutex_unlock(&mtd_table_mutex); + mutex_unlock(&dev->lock); + blktrans_dev_put(dev); + return ret; +@@ -232,6 +234,7 @@ error_release: + error_put: + module_put(dev->tr->owner); + kref_put(&dev->ref, blktrans_dev_release); ++ mutex_unlock(&mtd_table_mutex); + mutex_unlock(&dev->lock); + blktrans_dev_put(dev); + return ret; +@@ -245,6 +248,7 @@ static void blktrans_release(struct gendisk *disk, fmode_t mode) + return; + + mutex_lock(&dev->lock); ++ mutex_lock(&mtd_table_mutex); + + if (--dev->open) + goto unlock; +@@ -258,6 +262,7 @@ static void blktrans_release(struct gendisk *disk, fmode_t mode) + __put_mtd_device(dev->mtd); + } + unlock: ++ mutex_unlock(&mtd_table_mutex); + mutex_unlock(&dev->lock); + blktrans_dev_put(dev); + } +diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c +index 9715a7ba164a..efc542d00c84 100644 +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -2000,7 +2000,7 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd, + oob += chip->ecc.prepad; + } + +- chip->read_buf(mtd, oob, eccbytes); ++ chip->write_buf(mtd, oob, eccbytes); + oob += eccbytes; + + if (chip->ecc.postpad) { +@@ -3063,7 +3063,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, + int *busw) + { + struct nand_onfi_params *p = &chip->onfi_params; +- int i; ++ int i, j; + int val; + + /* Try ONFI for unknown chip or LP */ +@@ -3072,18 +3072,10 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, + chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I') + return 0; + +- /* +- * ONFI must be probed in 8-bit mode or with NAND_BUSWIDTH_AUTO, not +- * with NAND_BUSWIDTH_16 +- */ +- if (chip->options & NAND_BUSWIDTH_16) { +- pr_err("ONFI cannot be probed in 16-bit mode; aborting\n"); +- return 0; +- } +- + chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); + for (i = 0; i < 3; i++) { +- chip->read_buf(mtd, (uint8_t *)p, sizeof(*p)); ++ for (j = 0; j < sizeof(*p); j++) ++ ((uint8_t *)p)[j] = chip->read_byte(mtd); + if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) == + le16_to_cpu(p->crc)) { + break; +diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c +index 5924f72dd493..f35ce8e50e65 100644 +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -205,11 +205,13 @@ static bool ath_prepare_reset(struct ath_softc *sc) + ath_stop_ani(sc); + ath9k_hw_disable_interrupts(ah); + +- if (!ath_drain_all_txq(sc)) +- ret = false; +- +- if (!ath_stoprecv(sc)) +- ret = false; ++ if (AR_SREV_9300_20_OR_LATER(ah)) { ++ ret &= ath_stoprecv(sc); ++ ret &= ath_drain_all_txq(sc); ++ } else { ++ ret &= ath_drain_all_txq(sc); ++ ret &= ath_stoprecv(sc); ++ } + + return ret; + } +diff --git a/drivers/of/base.c b/drivers/of/base.c +index 3935614274eb..e99f329c905e 100644 +--- a/drivers/of/base.c ++++ b/drivers/of/base.c +@@ -77,7 +77,7 @@ EXPORT_SYMBOL(of_n_size_cells); + #ifdef CONFIG_NUMA + int __weak of_node_to_nid(struct device_node *np) + { +- return numa_node_id(); ++ return NUMA_NO_NODE; + } + #endif + +diff --git a/drivers/pcmcia/topic.h b/drivers/pcmcia/topic.h +index 615a45a8fe86..582688fe7505 100644 +--- a/drivers/pcmcia/topic.h ++++ b/drivers/pcmcia/topic.h +@@ -104,6 +104,9 @@ + #define TOPIC_EXCA_IF_CONTROL 0x3e /* 8 bit */ + #define TOPIC_EXCA_IFC_33V_ENA 0x01 + ++#define TOPIC_PCI_CFG_PPBCN 0x3e /* 16-bit */ ++#define TOPIC_PCI_CFG_PPBCN_WBEN 0x0400 ++ + static void topic97_zoom_video(struct pcmcia_socket *sock, int onoff) + { + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); +@@ -138,6 +141,7 @@ static int topic97_override(struct yenta_socket *socket) + static int topic95_override(struct yenta_socket *socket) + { + u8 fctrl; ++ u16 ppbcn; + + /* enable 3.3V support for 16bit cards */ + fctrl = exca_readb(socket, TOPIC_EXCA_IF_CONTROL); +@@ -146,6 +150,18 @@ static int topic95_override(struct yenta_socket *socket) + /* tell yenta to use exca registers to power 16bit cards */ + socket->flags |= YENTA_16BIT_POWER_EXCA | YENTA_16BIT_POWER_DF; + ++ /* Disable write buffers to prevent lockups under load with numerous ++ Cardbus cards, observed on Tecra 500CDT and reported elsewhere on the ++ net. This is not a power-on default according to the datasheet ++ but some BIOSes seem to set it. */ ++ if (pci_read_config_word(socket->dev, TOPIC_PCI_CFG_PPBCN, &ppbcn) == 0 ++ && socket->dev->revision <= 7 ++ && (ppbcn & TOPIC_PCI_CFG_PPBCN_WBEN)) { ++ ppbcn &= ~TOPIC_PCI_CFG_PPBCN_WBEN; ++ pci_write_config_word(socket->dev, TOPIC_PCI_CFG_PPBCN, ppbcn); ++ dev_info(&socket->dev->dev, "Disabled ToPIC95 Cardbus write buffers.\n"); ++ } ++ + return 0; + } + +diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-370.c b/drivers/pinctrl/mvebu/pinctrl-armada-370.c +index ae1f760cbdd2..bb525b19be77 100644 +--- a/drivers/pinctrl/mvebu/pinctrl-armada-370.c ++++ b/drivers/pinctrl/mvebu/pinctrl-armada-370.c +@@ -358,11 +358,11 @@ static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = { + MPP_MODE(64, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "spi0", "miso"), +- MPP_FUNCTION(0x2, "spi0-1", "cs1")), ++ MPP_FUNCTION(0x2, "spi0", "cs1")), + MPP_MODE(65, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "spi0", "mosi"), +- MPP_FUNCTION(0x2, "spi0-1", "cs2")), ++ MPP_FUNCTION(0x2, "spi0", "cs2")), + }; + + static struct mvebu_pinctrl_soc_info armada_370_pinctrl_info; +diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c +index 843a51f9d129..d918c5186061 100644 +--- a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c ++++ b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c +@@ -14,10 +14,7 @@ + * available: mv78230, mv78260 and mv78460. From a pin muxing + * perspective, the mv78230 has 49 MPP pins. The mv78260 and mv78460 + * both have 67 MPP pins (more GPIOs and address lines for the memory +- * bus mainly). The only difference between the mv78260 and the +- * mv78460 in terms of pin muxing is the addition of two functions on +- * pins 43 and 56 to access the VDD of the CPU2 and 3 (mv78260 has two +- * cores, mv78460 has four cores). ++ * bus mainly). + */ + + #include +@@ -159,20 +156,17 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { + MPP_MODE(24, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sata1", "prsnt", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x2, "nf", "bootcs-re", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "rst", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "hsync", V_MV78230_PLUS)), + MPP_MODE(25, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sata0", "prsnt", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x2, "nf", "bootcs-we", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "pclk", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "vsync", V_MV78230_PLUS)), + MPP_MODE(26, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "fsync", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x4, "lcd", "clk", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd", V_MV78230_PLUS)), ++ MPP_VAR_FUNCTION(0x4, "lcd", "clk", V_MV78230_PLUS)), + MPP_MODE(27, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ptp", "trig", V_MV78230_PLUS), +@@ -187,8 +181,7 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ptp", "clk", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "int0", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x4, "lcd", "ref-clk", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)), ++ MPP_VAR_FUNCTION(0x4, "lcd", "ref-clk", V_MV78230_PLUS)), + MPP_MODE(30, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sd0", "clk", V_MV78230_PLUS), +@@ -196,13 +189,11 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { + MPP_MODE(31, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sd0", "cmd", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x3, "tdm", "int2", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)), ++ MPP_VAR_FUNCTION(0x3, "tdm", "int2", V_MV78230_PLUS)), + MPP_MODE(32, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sd0", "d0", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x3, "tdm", "int3", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd", V_MV78230_PLUS)), ++ MPP_VAR_FUNCTION(0x3, "tdm", "int3", V_MV78230_PLUS)), + MPP_MODE(33, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sd0", "d1", V_MV78230_PLUS), +@@ -234,7 +225,6 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "spi", "cs1", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "uart2", "cts", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x3, "vdd", "cpu1-pd", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "vga-hsync", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x5, "pcie", "clkreq0", V_MV78230_PLUS)), + MPP_MODE(41, +@@ -249,15 +239,13 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { + MPP_VAR_FUNCTION(0x1, "uart2", "rxd", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "uart0", "cts", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "int7", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x4, "tdm-1", "timer", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)), ++ MPP_VAR_FUNCTION(0x4, "tdm-1", "timer", V_MV78230_PLUS)), + MPP_MODE(43, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "uart2", "txd", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "uart0", "rts", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "spi", "cs3", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x4, "pcie", "rstout", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x5, "vdd", "cpu2-3-pd", V_MV78460)), ++ MPP_VAR_FUNCTION(0x4, "pcie", "rstout", V_MV78230_PLUS)), + MPP_MODE(44, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "uart2", "cts", V_MV78230_PLUS), +@@ -286,7 +274,7 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { + MPP_VAR_FUNCTION(0x5, "pcie", "clkreq3", V_MV78230_PLUS)), + MPP_MODE(48, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x1, "tclk", NULL, V_MV78230_PLUS), ++ MPP_VAR_FUNCTION(0x1, "dev", "clkout", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "dev", "burst/last", V_MV78230_PLUS)), + MPP_MODE(49, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), +@@ -308,16 +296,13 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { + MPP_VAR_FUNCTION(0x1, "dev", "ad19", V_MV78260_PLUS)), + MPP_MODE(55, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), +- MPP_VAR_FUNCTION(0x1, "dev", "ad20", V_MV78260_PLUS), +- MPP_VAR_FUNCTION(0x2, "vdd", "cpu0-pd", V_MV78260_PLUS)), ++ MPP_VAR_FUNCTION(0x1, "dev", "ad20", V_MV78260_PLUS)), + MPP_MODE(56, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), +- MPP_VAR_FUNCTION(0x1, "dev", "ad21", V_MV78260_PLUS), +- MPP_VAR_FUNCTION(0x2, "vdd", "cpu1-pd", V_MV78260_PLUS)), ++ MPP_VAR_FUNCTION(0x1, "dev", "ad21", V_MV78260_PLUS)), + MPP_MODE(57, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), +- MPP_VAR_FUNCTION(0x1, "dev", "ad22", V_MV78260_PLUS), +- MPP_VAR_FUNCTION(0x2, "vdd", "cpu2-3-pd", V_MV78460)), ++ MPP_VAR_FUNCTION(0x1, "dev", "ad22", V_MV78260_PLUS)), + MPP_MODE(58, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad23", V_MV78260_PLUS)), +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index fed4111ac31a..1beb232ef03b 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -272,7 +272,6 @@ static struct dmi_system_id dell_quirks[] = { + }; + + static struct calling_interface_buffer *buffer; +-static struct page *bufferpage; + static DEFINE_MUTEX(buffer_mutex); + + static int hwswitch_state; +@@ -825,12 +824,11 @@ static int __init dell_init(void) + * Allocate buffer below 4GB for SMI data--only 32-bit physical addr + * is passed to SMI handler. + */ +- bufferpage = alloc_page(GFP_KERNEL | GFP_DMA32); +- if (!bufferpage) { ++ buffer = (void *)__get_free_page(GFP_KERNEL | GFP_DMA32); ++ if (!buffer) { + ret = -ENOMEM; + goto fail_buffer; + } +- buffer = page_address(bufferpage); + + ret = dell_setup_rfkill(); + +@@ -892,7 +890,7 @@ fail_backlight: + cancel_delayed_work_sync(&dell_rfkill_work); + dell_cleanup_rfkill(); + fail_rfkill: +- free_page((unsigned long)bufferpage); ++ free_page((unsigned long)buffer); + fail_buffer: + platform_device_del(platform_device); + fail_platform_device2: +diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c +index 6dd060a0bb65..0d1a5d497ce0 100644 +--- a/drivers/platform/x86/ideapad-laptop.c ++++ b/drivers/platform/x86/ideapad-laptop.c +@@ -461,8 +461,9 @@ const struct ideapad_rfk_data ideapad_rfk_data[] = { + static int ideapad_rfk_set(void *data, bool blocked) + { + struct ideapad_rfk_priv *priv = data; ++ int opcode = ideapad_rfk_data[priv->dev].opcode; + +- return write_ec_cmd(priv->priv->adev->handle, priv->dev, !blocked); ++ return write_ec_cmd(priv->priv->adev->handle, opcode, !blocked); + } + + static struct rfkill_ops ideapad_rfk_ops = { +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index 5d8d2dcd975e..427cb625af0a 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -773,7 +773,7 @@ static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) + static void print_constraints(struct regulator_dev *rdev) + { + struct regulation_constraints *constraints = rdev->constraints; +- char buf[80] = ""; ++ char buf[160] = ""; + int count = 0; + int ret; + +diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h +index 0801f3df4b27..02edae714b0e 100644 +--- a/drivers/scsi/ipr.h ++++ b/drivers/scsi/ipr.h +@@ -264,7 +264,7 @@ + #define IPR_RUNTIME_RESET 0x40000000 + + #define IPR_IPL_INIT_MIN_STAGE_TIME 5 +-#define IPR_IPL_INIT_DEFAULT_STAGE_TIME 15 ++#define IPR_IPL_INIT_DEFAULT_STAGE_TIME 30 + #define IPR_IPL_INIT_STAGE_UNKNOWN 0x0 + #define IPR_IPL_INIT_STAGE_TRANSOP 0xB0000000 + #define IPR_IPL_INIT_STAGE_MASK 0xff000000 +diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c +index 0a1dcb43d18b..13f4bef214dc 100644 +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -572,8 +572,9 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24; + struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82; +- uint32_t rscn_entry, host_pid; ++ uint32_t rscn_entry, host_pid, tmp_pid; + unsigned long flags; ++ fc_port_t *fcport = NULL; + + /* Setup to process RIO completion. */ + handle_cnt = 0; +@@ -968,6 +969,20 @@ skip_rio: + if (qla2x00_is_a_vp_did(vha, rscn_entry)) + break; + ++ /* ++ * Search for the rport related to this RSCN entry and mark it ++ * as lost. ++ */ ++ list_for_each_entry(fcport, &vha->vp_fcports, list) { ++ if (atomic_read(&fcport->state) != FCS_ONLINE) ++ continue; ++ tmp_pid = fcport->d_id.b24; ++ if (fcport->d_id.b24 == rscn_entry) { ++ qla2x00_mark_device_lost(vha, fcport, 0, 0); ++ break; ++ } ++ } ++ + atomic_set(&vha->loop_down_timer, 0); + vha->flags.management_server_logged_in = 0; + +diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c +index e3e794ee7ddd..b85eaa0d75c2 100644 +--- a/drivers/scsi/scsi_transport_srp.c ++++ b/drivers/scsi/scsi_transport_srp.c +@@ -397,6 +397,36 @@ static void srp_reconnect_work(struct work_struct *work) + } + } + ++/** ++ * scsi_request_fn_active() - number of kernel threads inside scsi_request_fn() ++ * @shost: SCSI host for which to count the number of scsi_request_fn() callers. ++ * ++ * To do: add support for scsi-mq in this function. ++ */ ++static int scsi_request_fn_active(struct Scsi_Host *shost) ++{ ++ struct scsi_device *sdev; ++ struct request_queue *q; ++ int request_fn_active = 0; ++ ++ shost_for_each_device(sdev, shost) { ++ q = sdev->request_queue; ++ ++ spin_lock_irq(q->queue_lock); ++ request_fn_active += q->request_fn_active; ++ spin_unlock_irq(q->queue_lock); ++ } ++ ++ return request_fn_active; ++} ++ ++/* Wait until ongoing shost->hostt->queuecommand() calls have finished. */ ++static void srp_wait_for_queuecommand(struct Scsi_Host *shost) ++{ ++ while (scsi_request_fn_active(shost)) ++ msleep(20); ++} ++ + static void __rport_fail_io_fast(struct srp_rport *rport) + { + struct Scsi_Host *shost = rport_to_shost(rport); +@@ -410,8 +440,10 @@ static void __rport_fail_io_fast(struct srp_rport *rport) + + /* Involve the LLD if possible to terminate all I/O on the rport. */ + i = to_srp_internal(shost->transportt); +- if (i->f->terminate_rport_io) ++ if (i->f->terminate_rport_io) { ++ srp_wait_for_queuecommand(shost); + i->f->terminate_rport_io(rport); ++ } + } + + /** +@@ -505,27 +537,6 @@ void srp_start_tl_fail_timers(struct srp_rport *rport) + EXPORT_SYMBOL(srp_start_tl_fail_timers); + + /** +- * scsi_request_fn_active() - number of kernel threads inside scsi_request_fn() +- * @shost: SCSI host for which to count the number of scsi_request_fn() callers. +- */ +-static int scsi_request_fn_active(struct Scsi_Host *shost) +-{ +- struct scsi_device *sdev; +- struct request_queue *q; +- int request_fn_active = 0; +- +- shost_for_each_device(sdev, shost) { +- q = sdev->request_queue; +- +- spin_lock_irq(q->queue_lock); +- request_fn_active += q->request_fn_active; +- spin_unlock_irq(q->queue_lock); +- } +- +- return request_fn_active; +-} +- +-/** + * srp_reconnect_rport() - reconnect to an SRP target port + * @rport: SRP target port. + * +@@ -560,8 +571,7 @@ int srp_reconnect_rport(struct srp_rport *rport) + if (res) + goto out; + scsi_target_block(&shost->shost_gendev); +- while (scsi_request_fn_active(shost)) +- msleep(20); ++ srp_wait_for_queuecommand(shost); + res = rport->state != SRP_RPORT_LOST ? i->f->reconnect(rport) : -ENODEV; + pr_debug("%s (state %d): transport.reconnect() returned %d\n", + dev_name(&shost->shost_gendev), rport->state, res); +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index d6563ec700d4..f3e3ae8af709 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -834,9 +834,6 @@ void spi_finalize_current_message(struct spi_master *master) + + spin_lock_irqsave(&master->queue_lock, flags); + mesg = master->cur_msg; +- master->cur_msg = NULL; +- +- queue_kthread_work(&master->kworker, &master->pump_messages); + spin_unlock_irqrestore(&master->queue_lock, flags); + + if (master->cur_msg_prepared && master->unprepare_message) { +@@ -847,9 +844,13 @@ void spi_finalize_current_message(struct spi_master *master) + } + } + +- trace_spi_message_done(mesg); +- ++ spin_lock_irqsave(&master->queue_lock, flags); ++ master->cur_msg = NULL; + master->cur_msg_prepared = false; ++ queue_kthread_work(&master->kworker, &master->pump_messages); ++ spin_unlock_irqrestore(&master->queue_lock, flags); ++ ++ trace_spi_message_done(mesg); + + mesg->state = NULL; + if (mesg->complete) +diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c +index ea965370d1ac..d060b1f4f092 100644 +--- a/drivers/staging/rtl8712/rtl8712_recv.c ++++ b/drivers/staging/rtl8712/rtl8712_recv.c +@@ -1075,7 +1075,8 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) + /* for first fragment packet, driver need allocate 1536 + + * drvinfo_sz + RXDESC_SIZE to defrag packet. */ + if ((mf == 1) && (frag == 0)) +- alloc_sz = 1658;/*1658+6=1664, 1664 is 128 alignment.*/ ++ /*1658+6=1664, 1664 is 128 alignment.*/ ++ alloc_sz = max_t(u16, tmp_len, 1658); + else + alloc_sz = tmp_len; + /* 2 is for IP header 4 bytes alignment in QoS packet case. +diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c +index b61c555a5a8f..c8d7b3009c7e 100644 +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -518,7 +518,7 @@ static struct iscsit_transport iscsi_target_transport = { + + static int __init iscsi_target_init_module(void) + { +- int ret = 0; ++ int ret = 0, size; + + pr_debug("iSCSI-Target "ISCSIT_VERSION"\n"); + +@@ -527,6 +527,7 @@ static int __init iscsi_target_init_module(void) + pr_err("Unable to allocate memory for iscsit_global\n"); + return -1; + } ++ spin_lock_init(&iscsit_global->ts_bitmap_lock); + mutex_init(&auth_id_lock); + spin_lock_init(&sess_idr_lock); + idr_init(&tiqn_idr); +@@ -536,15 +537,11 @@ static int __init iscsi_target_init_module(void) + if (ret < 0) + goto out; + +- ret = iscsi_thread_set_init(); +- if (ret < 0) ++ size = BITS_TO_LONGS(ISCSIT_BITMAP_BITS) * sizeof(long); ++ iscsit_global->ts_bitmap = vzalloc(size); ++ if (!iscsit_global->ts_bitmap) { ++ pr_err("Unable to allocate iscsit_global->ts_bitmap\n"); + goto configfs_out; +- +- if (iscsi_allocate_thread_sets(TARGET_THREAD_SET_COUNT) != +- TARGET_THREAD_SET_COUNT) { +- pr_err("iscsi_allocate_thread_sets() returned" +- " unexpected value!\n"); +- goto ts_out1; + } + + lio_qr_cache = kmem_cache_create("lio_qr_cache", +@@ -553,7 +550,7 @@ static int __init iscsi_target_init_module(void) + if (!lio_qr_cache) { + pr_err("nable to kmem_cache_create() for" + " lio_qr_cache\n"); +- goto ts_out2; ++ goto bitmap_out; + } + + lio_dr_cache = kmem_cache_create("lio_dr_cache", +@@ -597,10 +594,8 @@ dr_out: + kmem_cache_destroy(lio_dr_cache); + qr_out: + kmem_cache_destroy(lio_qr_cache); +-ts_out2: +- iscsi_deallocate_thread_sets(); +-ts_out1: +- iscsi_thread_set_free(); ++bitmap_out: ++ vfree(iscsit_global->ts_bitmap); + configfs_out: + iscsi_target_deregister_configfs(); + out: +@@ -610,8 +605,6 @@ out: + + static void __exit iscsi_target_cleanup_module(void) + { +- iscsi_deallocate_thread_sets(); +- iscsi_thread_set_free(); + iscsit_release_discovery_tpg(); + iscsit_unregister_transport(&iscsi_target_transport); + kmem_cache_destroy(lio_qr_cache); +@@ -621,6 +614,7 @@ static void __exit iscsi_target_cleanup_module(void) + + iscsi_target_deregister_configfs(); + ++ vfree(iscsit_global->ts_bitmap); + kfree(iscsit_global); + } + +@@ -3653,17 +3647,16 @@ static int iscsit_send_reject( + + void iscsit_thread_get_cpumask(struct iscsi_conn *conn) + { +- struct iscsi_thread_set *ts = conn->thread_set; + int ord, cpu; + /* +- * thread_id is assigned from iscsit_global->ts_bitmap from +- * within iscsi_thread_set.c:iscsi_allocate_thread_sets() ++ * bitmap_id is assigned from iscsit_global->ts_bitmap from ++ * within iscsit_start_kthreads() + * +- * Here we use thread_id to determine which CPU that this +- * iSCSI connection's iscsi_thread_set will be scheduled to ++ * Here we use bitmap_id to determine which CPU that this ++ * iSCSI connection's RX/TX threads will be scheduled to + * execute upon. + */ +- ord = ts->thread_id % cpumask_weight(cpu_online_mask); ++ ord = conn->bitmap_id % cpumask_weight(cpu_online_mask); + for_each_online_cpu(cpu) { + if (ord-- == 0) { + cpumask_set_cpu(cpu, conn->conn_cpumask); +@@ -3855,7 +3848,7 @@ check_rsp_state: + switch (state) { + case ISTATE_SEND_LOGOUTRSP: + if (!iscsit_logout_post_handler(cmd, conn)) +- goto restart; ++ return -ECONNRESET; + /* fall through */ + case ISTATE_SEND_STATUS: + case ISTATE_SEND_ASYNCMSG: +@@ -3883,8 +3876,6 @@ check_rsp_state: + + err: + return -1; +-restart: +- return -EAGAIN; + } + + static int iscsit_handle_response_queue(struct iscsi_conn *conn) +@@ -3911,21 +3902,13 @@ static int iscsit_handle_response_queue(struct iscsi_conn *conn) + int iscsi_target_tx_thread(void *arg) + { + int ret = 0; +- struct iscsi_conn *conn; +- struct iscsi_thread_set *ts = arg; ++ struct iscsi_conn *conn = arg; + /* + * Allow ourselves to be interrupted by SIGINT so that a + * connection recovery / failure event can be triggered externally. + */ + allow_signal(SIGINT); + +-restart: +- conn = iscsi_tx_thread_pre_handler(ts); +- if (!conn) +- goto out; +- +- ret = 0; +- + while (!kthread_should_stop()) { + /* + * Ensure that both TX and RX per connection kthreads +@@ -3934,11 +3917,9 @@ restart: + iscsit_thread_check_cpumask(conn, current, 1); + + wait_event_interruptible(conn->queues_wq, +- !iscsit_conn_all_queues_empty(conn) || +- ts->status == ISCSI_THREAD_SET_RESET); ++ !iscsit_conn_all_queues_empty(conn)); + +- if ((ts->status == ISCSI_THREAD_SET_RESET) || +- signal_pending(current)) ++ if (signal_pending(current)) + goto transport_err; + + get_immediate: +@@ -3949,15 +3930,14 @@ get_immediate: + ret = iscsit_handle_response_queue(conn); + if (ret == 1) + goto get_immediate; +- else if (ret == -EAGAIN) +- goto restart; ++ else if (ret == -ECONNRESET) ++ goto out; + else if (ret < 0) + goto transport_err; + } + + transport_err: + iscsit_take_action_for_connection_exit(conn); +- goto restart; + out: + return 0; + } +@@ -4046,8 +4026,7 @@ int iscsi_target_rx_thread(void *arg) + int ret; + u8 buffer[ISCSI_HDR_LEN], opcode; + u32 checksum = 0, digest = 0; +- struct iscsi_conn *conn = NULL; +- struct iscsi_thread_set *ts = arg; ++ struct iscsi_conn *conn = arg; + struct kvec iov; + /* + * Allow ourselves to be interrupted by SIGINT so that a +@@ -4055,11 +4034,6 @@ int iscsi_target_rx_thread(void *arg) + */ + allow_signal(SIGINT); + +-restart: +- conn = iscsi_rx_thread_pre_handler(ts); +- if (!conn) +- goto out; +- + if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) { + struct completion comp; + int rc; +@@ -4069,7 +4043,7 @@ restart: + if (rc < 0) + goto transport_err; + +- goto out; ++ goto transport_err; + } + + while (!kthread_should_stop()) { +@@ -4145,8 +4119,6 @@ transport_err: + if (!signal_pending(current)) + atomic_set(&conn->transport_failed, 1); + iscsit_take_action_for_connection_exit(conn); +- goto restart; +-out: + return 0; + } + +@@ -4208,7 +4180,24 @@ int iscsit_close_connection( + if (conn->conn_transport->transport_type == ISCSI_TCP) + complete(&conn->conn_logout_comp); + +- iscsi_release_thread_set(conn); ++ if (!strcmp(current->comm, ISCSI_RX_THREAD_NAME)) { ++ if (conn->tx_thread && ++ cmpxchg(&conn->tx_thread_active, true, false)) { ++ send_sig(SIGINT, conn->tx_thread, 1); ++ kthread_stop(conn->tx_thread); ++ } ++ } else if (!strcmp(current->comm, ISCSI_TX_THREAD_NAME)) { ++ if (conn->rx_thread && ++ cmpxchg(&conn->rx_thread_active, true, false)) { ++ send_sig(SIGINT, conn->rx_thread, 1); ++ kthread_stop(conn->rx_thread); ++ } ++ } ++ ++ spin_lock(&iscsit_global->ts_bitmap_lock); ++ bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id, ++ get_order(1)); ++ spin_unlock(&iscsit_global->ts_bitmap_lock); + + iscsit_stop_timers_for_cmds(conn); + iscsit_stop_nopin_response_timer(conn); +@@ -4487,15 +4476,13 @@ static void iscsit_logout_post_handler_closesession( + struct iscsi_conn *conn) + { + struct iscsi_session *sess = conn->sess; +- +- iscsi_set_thread_clear(conn, ISCSI_CLEAR_TX_THREAD); +- iscsi_set_thread_set_signal(conn, ISCSI_SIGNAL_TX_THREAD); ++ int sleep = cmpxchg(&conn->tx_thread_active, true, false); + + atomic_set(&conn->conn_logout_remove, 0); + complete(&conn->conn_logout_comp); + + iscsit_dec_conn_usage_count(conn); +- iscsit_stop_session(sess, 1, 1); ++ iscsit_stop_session(sess, sleep, sleep); + iscsit_dec_session_usage_count(sess); + target_put_session(sess->se_sess); + } +@@ -4503,13 +4490,12 @@ static void iscsit_logout_post_handler_closesession( + static void iscsit_logout_post_handler_samecid( + struct iscsi_conn *conn) + { +- iscsi_set_thread_clear(conn, ISCSI_CLEAR_TX_THREAD); +- iscsi_set_thread_set_signal(conn, ISCSI_SIGNAL_TX_THREAD); ++ int sleep = cmpxchg(&conn->tx_thread_active, true, false); + + atomic_set(&conn->conn_logout_remove, 0); + complete(&conn->conn_logout_comp); + +- iscsit_cause_connection_reinstatement(conn, 1); ++ iscsit_cause_connection_reinstatement(conn, sleep); + iscsit_dec_conn_usage_count(conn); + } + +diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h +index 1d4a8c86551f..825b579ebca8 100644 +--- a/drivers/target/iscsi/iscsi_target_core.h ++++ b/drivers/target/iscsi/iscsi_target_core.h +@@ -601,6 +601,11 @@ struct iscsi_conn { + struct iscsi_session *sess; + /* Pointer to thread_set in use for this conn's threads */ + struct iscsi_thread_set *thread_set; ++ int bitmap_id; ++ int rx_thread_active; ++ struct task_struct *rx_thread; ++ int tx_thread_active; ++ struct task_struct *tx_thread; + /* list_head for session connection list */ + struct list_head conn_list; + } ____cacheline_aligned; +@@ -869,10 +874,12 @@ struct iscsit_global { + /* Unique identifier used for the authentication daemon */ + u32 auth_id; + u32 inactive_ts; ++#define ISCSIT_BITMAP_BITS 262144 + /* Thread Set bitmap count */ + int ts_bitmap_count; + /* Thread Set bitmap pointer */ + unsigned long *ts_bitmap; ++ spinlock_t ts_bitmap_lock; + /* Used for iSCSI discovery session authentication */ + struct iscsi_node_acl discovery_acl; + struct iscsi_portal_group *discovery_tpg; +diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c +index 0d1e6ee3e992..7396d90d96b2 100644 +--- a/drivers/target/iscsi/iscsi_target_erl0.c ++++ b/drivers/target/iscsi/iscsi_target_erl0.c +@@ -864,7 +864,10 @@ void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *conn) + } + spin_unlock_bh(&conn->state_lock); + +- iscsi_thread_set_force_reinstatement(conn); ++ if (conn->tx_thread && conn->tx_thread_active) ++ send_sig(SIGINT, conn->tx_thread, 1); ++ if (conn->rx_thread && conn->rx_thread_active) ++ send_sig(SIGINT, conn->rx_thread, 1); + + sleep: + wait_for_completion(&conn->conn_wait_rcfr_comp); +@@ -889,10 +892,10 @@ void iscsit_cause_connection_reinstatement(struct iscsi_conn *conn, int sleep) + return; + } + +- if (iscsi_thread_set_force_reinstatement(conn) < 0) { +- spin_unlock_bh(&conn->state_lock); +- return; +- } ++ if (conn->tx_thread && conn->tx_thread_active) ++ send_sig(SIGINT, conn->tx_thread, 1); ++ if (conn->rx_thread && conn->rx_thread_active) ++ send_sig(SIGINT, conn->rx_thread, 1); + + atomic_set(&conn->connection_reinstatement, 1); + if (!sleep) { +diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c +index c5d3811a7b8c..449df092bfa0 100644 +--- a/drivers/target/iscsi/iscsi_target_login.c ++++ b/drivers/target/iscsi/iscsi_target_login.c +@@ -681,6 +681,51 @@ static void iscsi_post_login_start_timers(struct iscsi_conn *conn) + iscsit_start_nopin_timer(conn); + } + ++int iscsit_start_kthreads(struct iscsi_conn *conn) ++{ ++ int ret = 0; ++ ++ spin_lock(&iscsit_global->ts_bitmap_lock); ++ conn->bitmap_id = bitmap_find_free_region(iscsit_global->ts_bitmap, ++ ISCSIT_BITMAP_BITS, get_order(1)); ++ spin_unlock(&iscsit_global->ts_bitmap_lock); ++ ++ if (conn->bitmap_id < 0) { ++ pr_err("bitmap_find_free_region() failed for" ++ " iscsit_start_kthreads()\n"); ++ return -ENOMEM; ++ } ++ ++ conn->tx_thread = kthread_run(iscsi_target_tx_thread, conn, ++ "%s", ISCSI_TX_THREAD_NAME); ++ if (IS_ERR(conn->tx_thread)) { ++ pr_err("Unable to start iscsi_target_tx_thread\n"); ++ ret = PTR_ERR(conn->tx_thread); ++ goto out_bitmap; ++ } ++ conn->tx_thread_active = true; ++ ++ conn->rx_thread = kthread_run(iscsi_target_rx_thread, conn, ++ "%s", ISCSI_RX_THREAD_NAME); ++ if (IS_ERR(conn->rx_thread)) { ++ pr_err("Unable to start iscsi_target_rx_thread\n"); ++ ret = PTR_ERR(conn->rx_thread); ++ goto out_tx; ++ } ++ conn->rx_thread_active = true; ++ ++ return 0; ++out_tx: ++ kthread_stop(conn->tx_thread); ++ conn->tx_thread_active = false; ++out_bitmap: ++ spin_lock(&iscsit_global->ts_bitmap_lock); ++ bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id, ++ get_order(1)); ++ spin_unlock(&iscsit_global->ts_bitmap_lock); ++ return ret; ++} ++ + int iscsi_post_login_handler( + struct iscsi_np *np, + struct iscsi_conn *conn, +@@ -691,7 +736,7 @@ int iscsi_post_login_handler( + struct se_session *se_sess = sess->se_sess; + struct iscsi_portal_group *tpg = sess->tpg; + struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; +- struct iscsi_thread_set *ts; ++ int rc; + + iscsit_inc_conn_usage_count(conn); + +@@ -706,7 +751,6 @@ int iscsi_post_login_handler( + /* + * SCSI Initiator -> SCSI Target Port Mapping + */ +- ts = iscsi_get_thread_set(); + if (!zero_tsih) { + iscsi_set_session_parameters(sess->sess_ops, + conn->param_list, 0); +@@ -733,9 +777,11 @@ int iscsi_post_login_handler( + sess->sess_ops->InitiatorName); + spin_unlock_bh(&sess->conn_lock); + +- iscsi_post_login_start_timers(conn); ++ rc = iscsit_start_kthreads(conn); ++ if (rc) ++ return rc; + +- iscsi_activate_thread_set(conn, ts); ++ iscsi_post_login_start_timers(conn); + /* + * Determine CPU mask to ensure connection's RX and TX kthreads + * are scheduled on the same CPU. +@@ -792,8 +838,11 @@ int iscsi_post_login_handler( + " iSCSI Target Portal Group: %hu\n", tpg->nsessions, tpg->tpgt); + spin_unlock_bh(&se_tpg->session_lock); + ++ rc = iscsit_start_kthreads(conn); ++ if (rc) ++ return rc; ++ + iscsi_post_login_start_timers(conn); +- iscsi_activate_thread_set(conn, ts); + /* + * Determine CPU mask to ensure connection's RX and TX kthreads + * are scheduled on the same CPU. +diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c +index ee52ab7d3730..c501eba601da 100644 +--- a/drivers/thermal/step_wise.c ++++ b/drivers/thermal/step_wise.c +@@ -76,7 +76,7 @@ static unsigned long get_target_state(struct thermal_instance *instance, + next_target = instance->upper; + break; + case THERMAL_TREND_DROPPING: +- if (cur_state == instance->lower) { ++ if (cur_state <= instance->lower) { + if (!throttle) + next_target = THERMAL_NO_TARGET; + } else { +diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c +index 45b7b96f9ed3..8016aaa158f2 100644 +--- a/drivers/usb/core/devio.c ++++ b/drivers/usb/core/devio.c +@@ -513,7 +513,7 @@ static void async_completed(struct urb *urb) + snoop(&urb->dev->dev, "urb complete\n"); + snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length, + as->status, COMPLETE, NULL, 0); +- if ((urb->transfer_flags & URB_DIR_MASK) == USB_DIR_IN) ++ if ((urb->transfer_flags & URB_DIR_MASK) == URB_DIR_IN) + snoop_urb_data(urb, urb->actual_length); + + if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET && +@@ -1591,7 +1591,7 @@ static struct async *reap_as(struct dev_state *ps) + for (;;) { + __set_current_state(TASK_INTERRUPTIBLE); + as = async_getcompleted(ps); +- if (as) ++ if (as || !connected(ps)) + break; + if (signal_pending(current)) + break; +@@ -1614,7 +1614,7 @@ static int proc_reapurb(struct dev_state *ps, void __user *arg) + } + if (signal_pending(current)) + return -EINTR; +- return -EIO; ++ return -ENODEV; + } + + static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg) +@@ -1623,10 +1623,11 @@ static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg) + struct async *as; + + as = async_getcompleted(ps); +- retval = -EAGAIN; + if (as) { + retval = processcompl(as, (void __user * __user *)arg); + free_async(as); ++ } else { ++ retval = (connected(ps) ? -EAGAIN : -ENODEV); + } + return retval; + } +@@ -1756,7 +1757,7 @@ static int proc_reapurb_compat(struct dev_state *ps, void __user *arg) + } + if (signal_pending(current)) + return -EINTR; +- return -EIO; ++ return -ENODEV; + } + + static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg) +@@ -1764,11 +1765,12 @@ static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg) + int retval; + struct async *as; + +- retval = -EAGAIN; + as = async_getcompleted(ps); + if (as) { + retval = processcompl_compat(as, (void __user * __user *)arg); + free_async(as); ++ } else { ++ retval = (connected(ps) ? -EAGAIN : -ENODEV); + } + return retval; + } +@@ -1940,7 +1942,8 @@ static int proc_get_capabilities(struct dev_state *ps, void __user *arg) + { + __u32 caps; + +- caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM; ++ caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM | ++ USBDEVFS_CAP_REAP_AFTER_DISCONNECT; + if (!ps->dev->bus->no_stop_on_short) + caps |= USBDEVFS_CAP_BULK_CONTINUATION; + if (ps->dev->bus->sg_tablesize) +@@ -2001,6 +2004,32 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, + return -EPERM; + + usb_lock_device(dev); ++ ++ /* Reap operations are allowed even after disconnection */ ++ switch (cmd) { ++ case USBDEVFS_REAPURB: ++ snoop(&dev->dev, "%s: REAPURB\n", __func__); ++ ret = proc_reapurb(ps, p); ++ goto done; ++ ++ case USBDEVFS_REAPURBNDELAY: ++ snoop(&dev->dev, "%s: REAPURBNDELAY\n", __func__); ++ ret = proc_reapurbnonblock(ps, p); ++ goto done; ++ ++#ifdef CONFIG_COMPAT ++ case USBDEVFS_REAPURB32: ++ snoop(&dev->dev, "%s: REAPURB32\n", __func__); ++ ret = proc_reapurb_compat(ps, p); ++ goto done; ++ ++ case USBDEVFS_REAPURBNDELAY32: ++ snoop(&dev->dev, "%s: REAPURBNDELAY32\n", __func__); ++ ret = proc_reapurbnonblock_compat(ps, p); ++ goto done; ++#endif ++ } ++ + if (!connected(ps)) { + usb_unlock_device(dev); + return -ENODEV; +@@ -2094,16 +2123,6 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, + inode->i_mtime = CURRENT_TIME; + break; + +- case USBDEVFS_REAPURB32: +- snoop(&dev->dev, "%s: REAPURB32\n", __func__); +- ret = proc_reapurb_compat(ps, p); +- break; +- +- case USBDEVFS_REAPURBNDELAY32: +- snoop(&dev->dev, "%s: REAPURBNDELAY32\n", __func__); +- ret = proc_reapurbnonblock_compat(ps, p); +- break; +- + case USBDEVFS_IOCTL32: + snoop(&dev->dev, "%s: IOCTL32\n", __func__); + ret = proc_ioctl_compat(ps, ptr_to_compat(p)); +@@ -2115,16 +2134,6 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, + ret = proc_unlinkurb(ps, p); + break; + +- case USBDEVFS_REAPURB: +- snoop(&dev->dev, "%s: REAPURB\n", __func__); +- ret = proc_reapurb(ps, p); +- break; +- +- case USBDEVFS_REAPURBNDELAY: +- snoop(&dev->dev, "%s: REAPURBNDELAY\n", __func__); +- ret = proc_reapurbnonblock(ps, p); +- break; +- + case USBDEVFS_DISCSIGNAL: + snoop(&dev->dev, "%s: DISCSIGNAL\n", __func__); + ret = proc_disconnectsignal(ps, p); +@@ -2161,6 +2170,8 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, + ret = proc_disconnect_claim(ps, p); + break; + } ++ ++ done: + usb_unlock_device(dev); + if (ret >= 0) + inode->i_atime = CURRENT_TIME; +diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c +index 0985ff715c0c..a05fc58d9b60 100644 +--- a/drivers/usb/dwc3/ep0.c ++++ b/drivers/usb/dwc3/ep0.c +@@ -707,6 +707,10 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) + dev_vdbg(dwc->dev, "USB_REQ_SET_ISOCH_DELAY\n"); + ret = dwc3_ep0_set_isoch_delay(dwc, ctrl); + break; ++ case USB_REQ_SET_INTERFACE: ++ dev_vdbg(dwc->dev, "USB_REQ_SET_INTERFACE\n"); ++ dwc->start_config_issued = false; ++ /* Fall through */ + default: + dev_vdbg(dwc->dev, "Forwarding to gadget driver\n"); + ret = dwc3_ep0_delegate_req(dwc, ctrl); +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 8f6738d46b14..a57ad1f52f79 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -299,6 +299,8 @@ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, int cmd, u32 param) + if (!(reg & DWC3_DGCMD_CMDACT)) { + dev_vdbg(dwc->dev, "Command Complete --> %d\n", + DWC3_DGCMD_STATUS(reg)); ++ if (DWC3_DGCMD_STATUS(reg)) ++ return -EINVAL; + return 0; + } + +@@ -335,6 +337,8 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, + if (!(reg & DWC3_DEPCMD_CMDACT)) { + dev_vdbg(dwc->dev, "Command Complete --> %d\n", + DWC3_DEPCMD_STATUS(reg)); ++ if (DWC3_DEPCMD_STATUS(reg)) ++ return -EINVAL; + return 0; + } + +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index 9bce4f0e99be..f8893b32bbb6 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -1331,10 +1331,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, + /* Attempt to use the ring cache */ + if (virt_dev->num_rings_cached == 0) + return -ENOMEM; ++ virt_dev->num_rings_cached--; + virt_dev->eps[ep_index].new_ring = + virt_dev->ring_cache[virt_dev->num_rings_cached]; + virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL; +- virt_dev->num_rings_cached--; + xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring, + 1, type); + } +diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c +index 0241a3a0d63e..1e9bde4fe785 100644 +--- a/drivers/usb/musb/musb_virthub.c ++++ b/drivers/usb/musb/musb_virthub.c +@@ -273,9 +273,7 @@ static int musb_has_gadget(struct musb *musb) + #ifdef CONFIG_USB_MUSB_HOST + return 1; + #else +- if (musb->port_mode == MUSB_PORT_MODE_HOST) +- return 1; +- return musb->g.dev.driver != NULL; ++ return musb->port_mode == MUSB_PORT_MODE_HOST; + #endif + } + +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 73c7292f48e5..d11335d4395d 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -187,6 +187,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x1FB9, 0x0602) }, /* Lake Shore Model 648 Magnet Power Supply */ + { USB_DEVICE(0x1FB9, 0x0700) }, /* Lake Shore Model 737 VSM Controller */ + { USB_DEVICE(0x1FB9, 0x0701) }, /* Lake Shore Model 776 Hall Matrix */ ++ { USB_DEVICE(0x2626, 0xEA60) }, /* Aruba Networks 7xxx USB Serial Console */ + { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */ + { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */ + { USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */ +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index 8b3484134ab0..096438e4fb0c 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -1755,6 +1755,7 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) }, + { 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_INTERFACE_CLASS(0x2020, 0x4000, 0xff) }, /* OLICARD300 - MT6225 */ + { USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) }, + { USB_DEVICE(VIATELECOM_VENDOR_ID, VIATELECOM_PRODUCT_CDS7) }, + { } /* Terminating entry */ +diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c +index 9a08e18e09b9..3d66e9c5a95d 100644 +--- a/drivers/usb/serial/usb-serial.c ++++ b/drivers/usb/serial/usb-serial.c +@@ -1300,6 +1300,7 @@ static void __exit usb_serial_exit(void) + tty_unregister_driver(usb_serial_tty_driver); + put_tty_driver(usb_serial_tty_driver); + bus_unregister(&usb_serial_bus_type); ++ idr_destroy(&serial_minors); + } + + +diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c +index 09cf0135e8ac..90a6406111f5 100644 +--- a/drivers/watchdog/omap_wdt.c ++++ b/drivers/watchdog/omap_wdt.c +@@ -134,6 +134,13 @@ static int omap_wdt_start(struct watchdog_device *wdog) + + pm_runtime_get_sync(wdev->dev); + ++ /* ++ * Make sure the watchdog is disabled. This is unfortunately required ++ * because writing to various registers with the watchdog running has no ++ * effect. ++ */ ++ omap_wdt_disable(wdev); ++ + /* initialize prescaler */ + while (readl_relaxed(base + OMAP_WATCHDOG_WPS) & 0x01) + cpu_relax(); +diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c +index bb7991c7e5c7..bfdeadb7c243 100644 +--- a/fs/9p/vfs_inode.c ++++ b/fs/9p/vfs_inode.c +@@ -540,8 +540,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb, + unlock_new_inode(inode); + return inode; + error: +- unlock_new_inode(inode); +- iput(inode); ++ iget_failed(inode); + return ERR_PTR(retval); + + } +diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c +index 59dc8e87647f..de8606c3a9da 100644 +--- a/fs/9p/vfs_inode_dotl.c ++++ b/fs/9p/vfs_inode_dotl.c +@@ -149,8 +149,7 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, + unlock_new_inode(inode); + return inode; + error: +- unlock_new_inode(inode); +- iput(inode); ++ iget_failed(inode); + return ERR_PTR(retval); + + } +diff --git a/fs/bio.c b/fs/bio.c +index 8754e7b6eb49..b2b1451912b5 100644 +--- a/fs/bio.c ++++ b/fs/bio.c +@@ -1806,8 +1806,9 @@ EXPORT_SYMBOL(bio_endio_nodec); + * Allocates and returns a new bio which represents @sectors from the start of + * @bio, and updates @bio to represent the remaining sectors. + * +- * The newly allocated bio will point to @bio's bi_io_vec; it is the caller's +- * responsibility to ensure that @bio is not freed before the split. ++ * Unless this is a discard request the newly allocated bio will point ++ * to @bio's bi_io_vec; it is the caller's responsibility to ensure that ++ * @bio is not freed before the split. + */ + struct bio *bio_split(struct bio *bio, int sectors, + gfp_t gfp, struct bio_set *bs) +@@ -1817,7 +1818,15 @@ struct bio *bio_split(struct bio *bio, int sectors, + BUG_ON(sectors <= 0); + BUG_ON(sectors >= bio_sectors(bio)); + +- split = bio_clone_fast(bio, gfp, bs); ++ /* ++ * Discards need a mutable bio_vec to accommodate the payload ++ * required by the DSM TRIM and UNMAP commands. ++ */ ++ if (bio->bi_rw & REQ_DISCARD) ++ split = bio_clone_bioset(bio, gfp, bs); ++ else ++ split = bio_clone_fast(bio, gfp, bs); ++ + if (!split) + return NULL; + +diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c +index ab485e57b6fe..644942aeaeda 100644 +--- a/fs/btrfs/inode-map.c ++++ b/fs/btrfs/inode-map.c +@@ -281,7 +281,7 @@ void btrfs_unpin_free_ino(struct btrfs_root *root) + __btrfs_add_free_space(ctl, info->offset, count); + free: + rb_erase(&info->offset_index, rbroot); +- kfree(info); ++ kmem_cache_free(btrfs_free_space_cachep, info); + } + } + +diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c +index 3e16042338e4..d40ae42ba6d4 100644 +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -2743,7 +2743,7 @@ out_unlock: + static long btrfs_ioctl_file_extent_same(struct file *file, + struct btrfs_ioctl_same_args __user *argp) + { +- struct btrfs_ioctl_same_args *same; ++ struct btrfs_ioctl_same_args *same = NULL; + struct btrfs_ioctl_same_extent_info *info; + struct inode *src = file_inode(file); + u64 off; +@@ -2773,6 +2773,7 @@ static long btrfs_ioctl_file_extent_same(struct file *file, + + if (IS_ERR(same)) { + ret = PTR_ERR(same); ++ same = NULL; + goto out; + } + +@@ -2843,6 +2844,7 @@ static long btrfs_ioctl_file_extent_same(struct file *file, + + out: + mnt_drop_write_file(file); ++ kfree(same); + return ret; + } + +diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c +index e6574d7b6642..a7c5277a728f 100644 +--- a/fs/ext4/indirect.c ++++ b/fs/ext4/indirect.c +@@ -576,7 +576,7 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, + EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { + EXT4_ERROR_INODE(inode, "Can't allocate blocks for " + "non-extent mapped inodes with bigalloc"); +- return -ENOSPC; ++ return -EUCLEAN; + } + + goal = ext4_find_goal(inode, map->m_lblk, partial); +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index da03340fdb17..f9c63ae7276a 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -1357,7 +1357,7 @@ static void ext4_da_page_release_reservation(struct page *page, + unsigned int offset, + unsigned int length) + { +- int to_release = 0; ++ int to_release = 0, contiguous_blks = 0; + struct buffer_head *head, *bh; + unsigned int curr_off = 0; + struct inode *inode = page->mapping->host; +@@ -1378,14 +1378,23 @@ static void ext4_da_page_release_reservation(struct page *page, + + if ((offset <= curr_off) && (buffer_delay(bh))) { + to_release++; ++ contiguous_blks++; + clear_buffer_delay(bh); ++ } else if (contiguous_blks) { ++ lblk = page->index << ++ (PAGE_CACHE_SHIFT - inode->i_blkbits); ++ lblk += (curr_off >> inode->i_blkbits) - ++ contiguous_blks; ++ ext4_es_remove_extent(inode, lblk, contiguous_blks); ++ contiguous_blks = 0; + } + curr_off = next_off; + } while ((bh = bh->b_this_page) != head); + +- if (to_release) { ++ if (contiguous_blks) { + lblk = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); +- ext4_es_remove_extent(inode, lblk, to_release); ++ lblk += (curr_off >> inode->i_blkbits) - contiguous_blks; ++ ext4_es_remove_extent(inode, lblk, contiguous_blks); + } + + /* If we have released all the blocks belonging to a cluster, then we +@@ -1744,19 +1753,32 @@ static int __ext4_journalled_writepage(struct page *page, + ext4_walk_page_buffers(handle, page_bufs, 0, len, + NULL, bget_one); + } +- /* As soon as we unlock the page, it can go away, but we have +- * references to buffers so we are safe */ ++ /* ++ * We need to release the page lock before we start the ++ * journal, so grab a reference so the page won't disappear ++ * out from under us. ++ */ ++ get_page(page); + unlock_page(page); + + handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, + ext4_writepage_trans_blocks(inode)); + if (IS_ERR(handle)) { + ret = PTR_ERR(handle); +- goto out; ++ put_page(page); ++ goto out_no_pagelock; + } +- + BUG_ON(!ext4_handle_valid(handle)); + ++ lock_page(page); ++ put_page(page); ++ if (page->mapping != mapping) { ++ /* The page got truncated from under us */ ++ ext4_journal_stop(handle); ++ ret = 0; ++ goto out; ++ } ++ + if (inline_data) { + ret = ext4_journal_get_write_access(handle, inode_bh); + +@@ -1781,6 +1803,8 @@ static int __ext4_journalled_writepage(struct page *page, + NULL, bput_one); + ext4_set_inode_state(inode, EXT4_STATE_JDATA); + out: ++ unlock_page(page); ++out_no_pagelock: + brelse(inode_bh); + return ret; + } +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 7620133f78bf..c4a5e4df8ca3 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -4793,18 +4793,12 @@ do_more: + /* + * blocks being freed are metadata. these blocks shouldn't + * be used until this transaction is committed ++ * ++ * We use __GFP_NOFAIL because ext4_free_blocks() is not allowed ++ * to fail. + */ +- retry: +- new_entry = kmem_cache_alloc(ext4_free_data_cachep, GFP_NOFS); +- if (!new_entry) { +- /* +- * We use a retry loop because +- * ext4_free_blocks() is not allowed to fail. +- */ +- cond_resched(); +- congestion_wait(BLK_RW_ASYNC, HZ/50); +- goto retry; +- } ++ new_entry = kmem_cache_alloc(ext4_free_data_cachep, ++ GFP_NOFS|__GFP_NOFAIL); + new_entry->efd_start_cluster = bit; + new_entry->efd_group = block_group; + new_entry->efd_count = count_clusters; +diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c +index 2ae73a80c19b..be92ed2609bc 100644 +--- a/fs/ext4/migrate.c ++++ b/fs/ext4/migrate.c +@@ -616,6 +616,7 @@ int ext4_ind_migrate(struct inode *inode) + struct ext4_inode_info *ei = EXT4_I(inode); + struct ext4_extent *ex; + unsigned int i, len; ++ ext4_lblk_t start, end; + ext4_fsblk_t blk; + handle_t *handle; + int ret; +@@ -629,6 +630,14 @@ int ext4_ind_migrate(struct inode *inode) + EXT4_FEATURE_RO_COMPAT_BIGALLOC)) + return -EOPNOTSUPP; + ++ /* ++ * In order to get correct extent info, force all delayed allocation ++ * blocks to be allocated, otherwise delayed allocation blocks may not ++ * be reflected and bypass the checks on extent header. ++ */ ++ if (test_opt(inode->i_sb, DELALLOC)) ++ ext4_alloc_da_blocks(inode); ++ + handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1); + if (IS_ERR(handle)) + return PTR_ERR(handle); +@@ -646,11 +655,13 @@ int ext4_ind_migrate(struct inode *inode) + goto errout; + } + if (eh->eh_entries == 0) +- blk = len = 0; ++ blk = len = start = end = 0; + else { + len = le16_to_cpu(ex->ee_len); + blk = ext4_ext_pblock(ex); +- if (len > EXT4_NDIR_BLOCKS) { ++ start = le32_to_cpu(ex->ee_block); ++ end = start + len - 1; ++ if (end >= EXT4_NDIR_BLOCKS) { + ret = -EOPNOTSUPP; + goto errout; + } +@@ -658,7 +669,7 @@ int ext4_ind_migrate(struct inode *inode) + + ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS); + memset(ei->i_data, 0, sizeof(ei->i_data)); +- for (i=0; i < len; i++) ++ for (i = start; i <= end; i++) + ei->i_data[i] = cpu_to_le32(blk++); + ext4_mark_inode_dirty(handle, inode); + errout: +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 9fb3e6c0c578..a07af5b7a575 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -832,6 +832,7 @@ static void ext4_put_super(struct super_block *sb) + dump_orphan_list(sb, sbi); + J_ASSERT(list_empty(&sbi->s_orphan)); + ++ sync_blockdev(sb->s_bdev); + invalidate_bdev(sb->s_bdev); + if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) { + /* +diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c +index 73f6bcb44ea8..faf00af7f3d7 100644 +--- a/fs/fuse/inode.c ++++ b/fs/fuse/inode.c +@@ -1026,6 +1026,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) + goto err_fput; + + fuse_conn_init(fc); ++ fc->release = fuse_free_conn; + + fc->dev = sb->s_dev; + fc->sb = sb; +@@ -1040,7 +1041,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) + fc->dont_mask = 1; + sb->s_flags |= MS_POSIXACL; + +- fc->release = fuse_free_conn; + fc->flags = d.flags; + fc->user_id = d.user_id; + fc->group_id = d.group_id; +diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c +index 4534ff688b76..77b583da187f 100644 +--- a/fs/hpfs/super.c ++++ b/fs/hpfs/super.c +@@ -52,17 +52,20 @@ static void unmark_dirty(struct super_block *s) + } + + /* Filesystem error... */ +-static char err_buf[1024]; +- + void hpfs_error(struct super_block *s, const char *fmt, ...) + { ++ struct va_format vaf; + va_list args; + + va_start(args, fmt); +- vsnprintf(err_buf, sizeof(err_buf), fmt, args); ++ ++ vaf.fmt = fmt; ++ vaf.va = &args; ++ ++ pr_err("filesystem error: %pV", &vaf); ++ + va_end(args); + +- printk("HPFS: filesystem error: %s", err_buf); + if (!hpfs_sb(s)->sb_was_error) { + if (hpfs_sb(s)->sb_err == 2) { + printk("; crashing the system because you wanted it\n"); +diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c +index 7f34f4716165..b892355f1944 100644 +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -448,7 +448,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal) + unsigned long blocknr; + + if (is_journal_aborted(journal)) +- return 1; ++ return -EIO; + + if (!jbd2_journal_get_log_tail(journal, &first_tid, &blocknr)) + return 1; +@@ -463,10 +463,9 @@ int jbd2_cleanup_journal_tail(journal_t *journal) + * jbd2_cleanup_journal_tail() doesn't get called all that often. + */ + if (journal->j_flags & JBD2_BARRIER) +- blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); ++ blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL); + +- __jbd2_update_log_tail(journal, first_tid, blocknr); +- return 0; ++ return __jbd2_update_log_tail(journal, first_tid, blocknr); + } + + +diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c +index f2d78a3dae43..e8d62d742435 100644 +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -885,9 +885,10 @@ int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid, + * + * Requires j_checkpoint_mutex + */ +-void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) ++int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) + { + unsigned long freed; ++ int ret; + + BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); + +@@ -897,7 +898,10 @@ void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) + * space and if we lose sb update during power failure we'd replay + * old transaction with possibly newly overwritten data. + */ +- jbd2_journal_update_sb_log_tail(journal, tid, block, WRITE_FUA); ++ ret = jbd2_journal_update_sb_log_tail(journal, tid, block, WRITE_FUA); ++ if (ret) ++ goto out; ++ + write_lock(&journal->j_state_lock); + freed = block - journal->j_tail; + if (block < journal->j_tail) +@@ -913,6 +917,9 @@ void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) + journal->j_tail_sequence = tid; + journal->j_tail = block; + write_unlock(&journal->j_state_lock); ++ ++out: ++ return ret; + } + + /* +@@ -1331,7 +1338,7 @@ static int journal_reset(journal_t *journal) + return jbd2_journal_start_thread(journal); + } + +-static void jbd2_write_superblock(journal_t *journal, int write_op) ++static int jbd2_write_superblock(journal_t *journal, int write_op) + { + struct buffer_head *bh = journal->j_sb_buffer; + journal_superblock_t *sb = journal->j_superblock; +@@ -1370,7 +1377,10 @@ static void jbd2_write_superblock(journal_t *journal, int write_op) + printk(KERN_ERR "JBD2: Error %d detected when updating " + "journal superblock for %s.\n", ret, + journal->j_devname); ++ jbd2_journal_abort(journal, ret); + } ++ ++ return ret; + } + + /** +@@ -1383,10 +1393,11 @@ static void jbd2_write_superblock(journal_t *journal, int write_op) + * Update a journal's superblock information about log tail and write it to + * disk, waiting for the IO to complete. + */ +-void jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid, ++int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid, + unsigned long tail_block, int write_op) + { + journal_superblock_t *sb = journal->j_superblock; ++ int ret; + + BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); + jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n", +@@ -1395,13 +1406,18 @@ void jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid, + sb->s_sequence = cpu_to_be32(tail_tid); + sb->s_start = cpu_to_be32(tail_block); + +- jbd2_write_superblock(journal, write_op); ++ ret = jbd2_write_superblock(journal, write_op); ++ if (ret) ++ goto out; + + /* Log is no longer empty */ + write_lock(&journal->j_state_lock); + WARN_ON(!sb->s_sequence); + journal->j_flags &= ~JBD2_FLUSHED; + write_unlock(&journal->j_state_lock); ++ ++out: ++ return ret; + } + + /** +@@ -1952,7 +1968,14 @@ int jbd2_journal_flush(journal_t *journal) + return -EIO; + + mutex_lock(&journal->j_checkpoint_mutex); +- jbd2_cleanup_journal_tail(journal); ++ if (!err) { ++ err = jbd2_cleanup_journal_tail(journal); ++ if (err < 0) { ++ mutex_unlock(&journal->j_checkpoint_mutex); ++ goto out; ++ } ++ err = 0; ++ } + + /* Finally, mark the journal as really needing no recovery. + * This sets s_start==0 in the underlying superblock, which is +@@ -1968,7 +1991,8 @@ int jbd2_journal_flush(journal_t *journal) + J_ASSERT(journal->j_head == journal->j_tail); + J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence); + write_unlock(&journal->j_state_lock); +- return 0; ++out: ++ return err; + } + + /** +diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c +index fa6d72131c19..4495cad189c3 100644 +--- a/fs/nfs/nfs3xdr.c ++++ b/fs/nfs/nfs3xdr.c +@@ -1342,7 +1342,7 @@ static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req, + if (args->npages != 0) + xdr_write_pages(xdr, args->pages, 0, args->len); + else +- xdr_reserve_space(xdr, NFS_ACL_INLINE_BUFSIZE); ++ xdr_reserve_space(xdr, args->len); + + error = nfsacl_encode(xdr->buf, base, args->inode, + (args->mask & NFS_ACL) ? +diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c +index b4f177f1d405..c402b672a474 100644 +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -1482,6 +1482,8 @@ restart: + spin_unlock(&state->state_lock); + } + nfs4_put_open_state(state); ++ clear_bit(NFS4CLNT_RECLAIM_NOGRACE, ++ &state->flags); + spin_lock(&sp->so_lock); + goto restart; + } +diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c +index 14e58f2c96bd..98d4948feba0 100644 +--- a/fs/xfs/xfs_symlink.c ++++ b/fs/xfs/xfs_symlink.c +@@ -102,7 +102,7 @@ xfs_readlink_bmap( + cur_chunk += sizeof(struct xfs_dsymlink_hdr); + } + +- memcpy(link + offset, bp->b_addr, byte_cnt); ++ memcpy(link + offset, cur_chunk, byte_cnt); + + pathlen -= byte_cnt; + offset += byte_cnt; +diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h +index 8fc12f80b616..69afb5780815 100644 +--- a/include/acpi/actypes.h ++++ b/include/acpi/actypes.h +@@ -561,6 +561,7 @@ typedef u64 acpi_integer; + #define ACPI_NO_ACPI_ENABLE 0x10 + #define ACPI_NO_DEVICE_INIT 0x20 + #define ACPI_NO_OBJECT_INIT 0x40 ++#define ACPI_NO_FACS_INIT 0x80 + + /* + * Initialization state +diff --git a/include/linux/acpi.h b/include/linux/acpi.h +index cd80aa80d03e..77af62187e7a 100644 +--- a/include/linux/acpi.h ++++ b/include/linux/acpi.h +@@ -402,6 +402,7 @@ extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, + #define ACPI_OST_SC_INSERT_NOT_SUPPORTED 0x82 + + extern void acpi_early_init(void); ++extern void acpi_subsystem_init(void); + + extern int acpi_nvs_register(__u64 start, __u64 size); + +@@ -436,6 +437,7 @@ static inline const char *acpi_dev_name(struct acpi_device *adev) + } + + static inline void acpi_early_init(void) { } ++static inline void acpi_subsystem_init(void) { } + + static inline int early_acpi_boot_init(void) + { +diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h +index 0dae71e9971c..e1fb0f613a99 100644 +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -1035,7 +1035,7 @@ struct buffer_head *jbd2_journal_get_descriptor_buffer(journal_t *journal); + int jbd2_journal_next_log_block(journal_t *, unsigned long long *); + int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid, + unsigned long *block); +-void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); ++int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); + void jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); + + /* Commit management */ +@@ -1157,7 +1157,7 @@ extern int jbd2_journal_recover (journal_t *journal); + extern int jbd2_journal_wipe (journal_t *, int); + extern int jbd2_journal_skip_recovery (journal_t *); + extern void jbd2_journal_update_sb_errno(journal_t *); +-extern void jbd2_journal_update_sb_log_tail (journal_t *, tid_t, ++extern int jbd2_journal_update_sb_log_tail (journal_t *, tid_t, + unsigned long, int); + extern void __jbd2_journal_abort_hard (journal_t *); + extern void jbd2_journal_abort (journal_t *, int); +diff --git a/include/linux/libata.h b/include/linux/libata.h +index b84e786ff990..189c9ff97b29 100644 +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -428,6 +428,7 @@ enum { + ATA_HORKAGE_NO_NCQ_TRIM = (1 << 19), /* don't use queued TRIM */ + ATA_HORKAGE_NOLPM = (1 << 20), /* don't use LPM */ + ATA_HORKAGE_WD_BROKEN_LPM = (1 << 21), /* some WDs have broken LPM */ ++ ATA_HORKAGE_NOTRIM = (1 << 24), /* don't use TRIM */ + + /* DMA mask for user DMA control: User visible values; DO NOT + renumber */ +diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h +index 53988cb3c05a..3a36a2c33aef 100644 +--- a/include/linux/nfs_xdr.h ++++ b/include/linux/nfs_xdr.h +@@ -1155,7 +1155,7 @@ struct nfs41_state_protection { + struct nfs4_op_map allow; + }; + +-#define NFS4_EXCHANGE_ID_LEN (48) ++#define NFS4_EXCHANGE_ID_LEN (127) + struct nfs41_exchange_id_args { + struct nfs_client *client; + nfs4_verifier *verifier; +diff --git a/include/linux/of.h b/include/linux/of.h +index 3f8144dadaef..9f2698de732b 100644 +--- a/include/linux/of.h ++++ b/include/linux/of.h +@@ -517,7 +517,10 @@ static inline const char *of_prop_next_string(struct property *prop, + #if defined(CONFIG_OF) && defined(CONFIG_NUMA) + extern int of_node_to_nid(struct device_node *np); + #else +-static inline int of_node_to_nid(struct device_node *device) { return 0; } ++static inline int of_node_to_nid(struct device_node *device) ++{ ++ return NUMA_NO_NODE; ++} + #endif + + static inline struct device_node *of_find_matching_node( +diff --git a/include/uapi/linux/usbdevice_fs.h b/include/uapi/linux/usbdevice_fs.h +index 0c65e4b12617..ef29266ef77a 100644 +--- a/include/uapi/linux/usbdevice_fs.h ++++ b/include/uapi/linux/usbdevice_fs.h +@@ -125,11 +125,12 @@ struct usbdevfs_hub_portinfo { + char port [127]; /* e.g. port 3 connects to device 27 */ + }; + +-/* Device capability flags */ ++/* System and bus capability flags */ + #define USBDEVFS_CAP_ZERO_PACKET 0x01 + #define USBDEVFS_CAP_BULK_CONTINUATION 0x02 + #define USBDEVFS_CAP_NO_PACKET_SIZE_LIM 0x04 + #define USBDEVFS_CAP_BULK_SCATTER_GATHER 0x08 ++#define USBDEVFS_CAP_REAP_AFTER_DISCONNECT 0x10 + + /* USBDEVFS_DISCONNECT_CLAIM flags & struct */ + +diff --git a/init/main.c b/init/main.c +index 58c132d7de4b..008edceecf03 100644 +--- a/init/main.c ++++ b/init/main.c +@@ -643,6 +643,7 @@ asmlinkage void __init start_kernel(void) + + check_bugs(); + ++ acpi_subsystem_init(); + sfi_init_late(); + + if (efi_enabled(EFI_RUNTIME_SERVICES)) { +diff --git a/kernel/irq/devres.c b/kernel/irq/devres.c +index 1ef0606797c9..0296d6fd7d4e 100644 +--- a/kernel/irq/devres.c ++++ b/kernel/irq/devres.c +@@ -104,7 +104,7 @@ int devm_request_any_context_irq(struct device *dev, unsigned int irq, + return -ENOMEM; + + rc = request_any_context_irq(irq, handler, irqflags, devname, dev_id); +- if (rc) { ++ if (rc < 0) { + devres_free(dr); + return rc; + } +@@ -113,7 +113,7 @@ int devm_request_any_context_irq(struct device *dev, unsigned int irq, + dr->dev_id = dev_id; + devres_add(dev, dr); + +- return 0; ++ return rc; + } + EXPORT_SYMBOL(devm_request_any_context_irq); + +diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig +index 2fac9cc79b3d..9d1862866786 100644 +--- a/kernel/power/Kconfig ++++ b/kernel/power/Kconfig +@@ -191,7 +191,7 @@ config DPM_WATCHDOG + config DPM_WATCHDOG_TIMEOUT + int "Watchdog timeout in seconds" + range 1 120 +- default 12 ++ default 60 + depends on DPM_WATCHDOG + + config PM_TRACE +diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c +index a755ad70fe8f..02e7fb4edb93 100644 +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -383,11 +383,11 @@ static int check_syslog_permissions(int type, bool from_file) + * already done the capabilities checks at open time. + */ + if (from_file && type != SYSLOG_ACTION_OPEN) +- return 0; ++ goto ok; + + if (syslog_action_restricted(type)) { + if (capable(CAP_SYSLOG)) +- return 0; ++ goto ok; + /* + * For historical reasons, accept CAP_SYS_ADMIN too, with + * a warning. +@@ -397,10 +397,11 @@ static int check_syslog_permissions(int type, bool from_file) + "CAP_SYS_ADMIN but no CAP_SYSLOG " + "(deprecated).\n", + current->comm, task_pid_nr(current)); +- return 0; ++ goto ok; + } + return -EPERM; + } ++ok: + return security_syslog(type); + } + +@@ -1126,10 +1127,6 @@ int do_syslog(int type, char __user *buf, int len, bool from_file) + if (error) + goto out; + +- error = security_syslog(type); +- if (error) +- return error; +- + switch (type) { + case SYSLOG_ACTION_CLOSE: /* Close log */ + break; +diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c +index 1254f312d024..ae359f0302c4 100644 +--- a/kernel/rcu/tiny.c ++++ b/kernel/rcu/tiny.c +@@ -284,6 +284,11 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp) + + /* Move the ready-to-invoke callbacks to a local list. */ + local_irq_save(flags); ++ if (rcp->donetail == &rcp->rcucblist) { ++ /* No callbacks ready, so just leave. */ ++ local_irq_restore(flags); ++ return; ++ } + RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, rcp->qlen, -1)); + list = rcp->rcucblist; + rcp->rcucblist = *rcp->donetail; +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index c8bd809cbd1c..c1be95c26046 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -422,6 +422,7 @@ enum { + + TRACE_CONTROL_BIT, + ++ TRACE_BRANCH_BIT, + /* + * Abuse of the trace_recursion. + * As we need a way to maintain state if we are tracing the function +diff --git a/kernel/trace/trace_branch.c b/kernel/trace/trace_branch.c +index 697fb9bac8f0..60850b4fcb04 100644 +--- a/kernel/trace/trace_branch.c ++++ b/kernel/trace/trace_branch.c +@@ -37,9 +37,12 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect) + struct trace_branch *entry; + struct ring_buffer *buffer; + unsigned long flags; +- int cpu, pc; ++ int pc; + const char *p; + ++ if (current->trace_recursion & TRACE_BRANCH_BIT) ++ return; ++ + /* + * I would love to save just the ftrace_likely_data pointer, but + * this code can also be used by modules. Ugly things can happen +@@ -50,10 +53,10 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect) + if (unlikely(!tr)) + return; + +- local_irq_save(flags); +- cpu = raw_smp_processor_id(); +- data = per_cpu_ptr(tr->trace_buffer.data, cpu); +- if (atomic_inc_return(&data->disabled) != 1) ++ raw_local_irq_save(flags); ++ current->trace_recursion |= TRACE_BRANCH_BIT; ++ data = this_cpu_ptr(tr->trace_buffer.data); ++ if (atomic_read(&data->disabled)) + goto out; + + pc = preempt_count(); +@@ -82,8 +85,8 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect) + __buffer_unlock_commit(buffer, event); + + out: +- atomic_dec(&data->disabled); +- local_irq_restore(flags); ++ current->trace_recursion &= ~TRACE_BRANCH_BIT; ++ raw_local_irq_restore(flags); + } + + static inline +diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c +index cb347e85f75e..7b244d004d68 100644 +--- a/kernel/trace/trace_events_filter.c ++++ b/kernel/trace/trace_events_filter.c +@@ -1086,6 +1086,9 @@ static void parse_init(struct filter_parse_state *ps, + + static char infix_next(struct filter_parse_state *ps) + { ++ if (!ps->infix.cnt) ++ return 0; ++ + ps->infix.cnt--; + + return ps->infix.string[ps->infix.tail++]; +@@ -1101,6 +1104,9 @@ static char infix_peek(struct filter_parse_state *ps) + + static void infix_advance(struct filter_parse_state *ps) + { ++ if (!ps->infix.cnt) ++ return; ++ + ps->infix.cnt--; + ps->infix.tail++; + } +@@ -1413,7 +1419,9 @@ static int check_preds(struct filter_parse_state *ps) + continue; + } + n_normal_preds++; +- WARN_ON_ONCE(cnt < 0); ++ /* all ops should have operands */ ++ if (cnt < 0) ++ break; + } + + if (cnt != 1 || !n_normal_preds || n_logical_preds >= n_normal_preds) { +diff --git a/lib/bitmap.c b/lib/bitmap.c +index e5c4ebe586ba..c0634aa923a6 100644 +--- a/lib/bitmap.c ++++ b/lib/bitmap.c +@@ -603,12 +603,12 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen, + unsigned a, b; + int c, old_c, totaldigits; + const char __user __force *ubuf = (const char __user __force *)buf; +- int exp_digit, in_range; ++ int at_start, in_range; + + totaldigits = c = 0; + bitmap_zero(maskp, nmaskbits); + do { +- exp_digit = 1; ++ at_start = 1; + in_range = 0; + a = b = 0; + +@@ -637,11 +637,10 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen, + break; + + if (c == '-') { +- if (exp_digit || in_range) ++ if (at_start || in_range) + return -EINVAL; + b = 0; + in_range = 1; +- exp_digit = 1; + continue; + } + +@@ -651,16 +650,18 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen, + b = b * 10 + (c - '0'); + if (!in_range) + a = b; +- exp_digit = 0; ++ at_start = 0; + totaldigits++; + } + if (!(a <= b)) + return -EINVAL; + if (b >= nmaskbits) + return -ERANGE; +- while (a <= b) { +- set_bit(a, maskp); +- a++; ++ if (!at_start) { ++ while (a <= b) { ++ set_bit(a, maskp); ++ a++; ++ } + } + } while (buflen && c == ','); + return 0; +diff --git a/net/9p/client.c b/net/9p/client.c +index 9186550d77a6..08046f39f09c 100644 +--- a/net/9p/client.c ++++ b/net/9p/client.c +@@ -839,7 +839,8 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, + if (err < 0) { + if (err == -EIO) + c->status = Disconnected; +- goto reterr; ++ if (err != -ERESTARTSYS) ++ goto reterr; + } + if (req->status == REQ_STATUS_ERROR) { + p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); +diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c +index aade4a5c1c07..bde94d853b2b 100644 +--- a/net/ceph/osdmap.c ++++ b/net/ceph/osdmap.c +@@ -89,7 +89,7 @@ static int crush_decode_tree_bucket(void **p, void *end, + { + int j; + dout("crush_decode_tree_bucket %p to %p\n", *p, end); +- ceph_decode_32_safe(p, end, b->num_nodes, bad); ++ ceph_decode_8_safe(p, end, b->num_nodes, bad); + b->node_weights = kcalloc(b->num_nodes, sizeof(u32), GFP_NOFS); + if (b->node_weights == NULL) + return -ENOMEM; +diff --git a/net/mac80211/main.c b/net/mac80211/main.c +index c7a7a86afdb8..9e58c99e3bdc 100644 +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -248,6 +248,7 @@ static void ieee80211_restart_work(struct work_struct *work) + { + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, restart_work); ++ struct ieee80211_sub_if_data *sdata; + + /* wait for scan work complete */ + flush_workqueue(local->workqueue); +@@ -256,6 +257,8 @@ static void ieee80211_restart_work(struct work_struct *work) + "%s called with hardware scan in progress\n", __func__); + + rtnl_lock(); ++ list_for_each_entry(sdata, &local->interfaces, list) ++ flush_delayed_work(&sdata->dec_tailroom_needed_wk); + ieee80211_scan_cancel(local); + ieee80211_reconfig(local); + rtnl_unlock(); +diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c +index e860d4f7ed2a..ab219685336c 100644 +--- a/net/sunrpc/backchannel_rqst.c ++++ b/net/sunrpc/backchannel_rqst.c +@@ -60,7 +60,7 @@ static void xprt_free_allocation(struct rpc_rqst *req) + + dprintk("RPC: free allocations for req= %p\n", req); + WARN_ON_ONCE(test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); +- xbufp = &req->rq_private_buf; ++ xbufp = &req->rq_rcv_buf; + free_page((unsigned long)xbufp->head[0].iov_base); + xbufp = &req->rq_snd_buf; + free_page((unsigned long)xbufp->head[0].iov_base); +diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c +index 7e71e066198f..048550aacffc 100644 +--- a/security/integrity/evm/evm_main.c ++++ b/security/integrity/evm/evm_main.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include "evm.h" + +@@ -275,6 +276,17 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, + iint = integrity_iint_find(dentry->d_inode); + if (iint && (iint->flags & IMA_NEW_FILE)) + return 0; ++ ++ /* exception for pseudo filesystems */ ++ if (dentry->d_inode->i_sb->s_magic == TMPFS_MAGIC ++ || dentry->d_inode->i_sb->s_magic == SYSFS_MAGIC) ++ return 0; ++ ++ integrity_audit_msg(AUDIT_INTEGRITY_METADATA, ++ dentry->d_inode, dentry->d_name.name, ++ "update_metadata", ++ integrity_status_msg[evm_status], ++ -EPERM, 0); + } + out: + if (evm_status != INTEGRITY_PASS) +diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h +index f79fa8be203c..5cb7de9046fa 100644 +--- a/security/integrity/ima/ima.h ++++ b/security/integrity/ima/ima.h +@@ -106,7 +106,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename, + const char *op, const char *cause); + int ima_init_crypto(void); + void ima_putc(struct seq_file *m, void *data, int datalen); +-void ima_print_digest(struct seq_file *m, u8 *digest, int size); ++void ima_print_digest(struct seq_file *m, u8 *digest, u32 size); + struct ima_template_desc *ima_template_desc_current(void); + int ima_init_template(void); + +diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c +index 468a3ba3c539..35f3c900f801 100644 +--- a/security/integrity/ima/ima_fs.c ++++ b/security/integrity/ima/ima_fs.c +@@ -186,9 +186,9 @@ static const struct file_operations ima_measurements_ops = { + .release = seq_release, + }; + +-void ima_print_digest(struct seq_file *m, u8 *digest, int size) ++void ima_print_digest(struct seq_file *m, u8 *digest, u32 size) + { +- int i; ++ u32 i; + + for (i = 0; i < size; i++) + seq_printf(m, "%02x", *(digest + i)); +diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c +index e8592e7bfc21..dcf77b77d2fc 100644 +--- a/security/integrity/ima/ima_template_lib.c ++++ b/security/integrity/ima/ima_template_lib.c +@@ -79,7 +79,8 @@ static void ima_show_template_data_ascii(struct seq_file *m, + enum data_formats datafmt, + struct ima_field_data *field_data) + { +- u8 *buf_ptr = field_data->data, buflen = field_data->len; ++ u8 *buf_ptr = field_data->data; ++ u32 buflen = field_data->len; + + switch (datafmt) { + case DATA_FMT_DIGEST_WITH_ALGO: +diff --git a/security/keys/keyring.c b/security/keys/keyring.c +index 2fb2576dc644..04d0d7c2ab0e 100644 +--- a/security/keys/keyring.c ++++ b/security/keys/keyring.c +@@ -1151,9 +1151,11 @@ void __key_link_end(struct key *keyring, + if (index_key->type == &key_type_keyring) + up_write(&keyring_serialise_link_sem); + +- if (edit && !edit->dead_leaf) { +- key_payload_reserve(keyring, +- keyring->datalen - KEYQUOTA_LINK_BYTES); ++ if (edit) { ++ if (!edit->dead_leaf) { ++ key_payload_reserve(keyring, ++ keyring->datalen - KEYQUOTA_LINK_BYTES); ++ } + assoc_array_cancel_edit(edit); + } + up_write(&keyring->sem); +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index ba175226da78..2f503c0836a9 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -3955,6 +3955,7 @@ enum { + ALC269_FIXUP_LIFEBOOK, + ALC269_FIXUP_LIFEBOOK_EXTMIC, + ALC269_FIXUP_LIFEBOOK_HP_PIN, ++ ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT, + ALC269_FIXUP_AMIC, + ALC269_FIXUP_DMIC, + ALC269VB_FIXUP_AMIC, +@@ -3973,6 +3974,7 @@ enum { + ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, + ALC269_FIXUP_HEADSET_MODE, + ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, ++ ALC269_FIXUP_ASPIRE_HEADSET_MIC, + ALC269_FIXUP_ASUS_X101_FUNC, + ALC269_FIXUP_ASUS_X101_VERB, + ALC269_FIXUP_ASUS_X101, +@@ -4096,6 +4098,10 @@ static const struct hda_fixup alc269_fixups[] = { + { } + }, + }, ++ [ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc269_fixup_pincfg_no_hp_to_lineout, ++ }, + [ALC269_FIXUP_AMIC] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { +@@ -4214,6 +4220,15 @@ static const struct hda_fixup alc269_fixups[] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_headset_mode_no_hp_mic, + }, ++ [ALC269_FIXUP_ASPIRE_HEADSET_MIC] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x19, 0x01a1913c }, /* headset mic w/o jack detect */ ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC269_FIXUP_HEADSET_MODE, ++ }, + [ALC286_FIXUP_SONY_MIC_NO_PRESENCE] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { +@@ -4397,6 +4412,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC), + SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), + SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700), ++ SND_PCI_QUIRK(0x1025, 0x072d, "Acer Aspire V5-571G", ALC269_FIXUP_ASPIRE_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC), + SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK), + SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK), + SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC), +@@ -4549,6 +4566,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), + SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), + SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), ++ SND_PCI_QUIRK(0x10cf, 0x159f, "Lifebook E780", ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT), + SND_PCI_QUIRK(0x10cf, 0x15dc, "Lifebook T731", ALC269_FIXUP_LIFEBOOK_HP_PIN), + SND_PCI_QUIRK(0x10cf, 0x1757, "Lifebook E752", ALC269_FIXUP_LIFEBOOK_HP_PIN), + SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), +diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c +index ce9c8e14d4bd..fbee45c82a44 100644 +--- a/sound/soc/codecs/wm5102.c ++++ b/sound/soc/codecs/wm5102.c +@@ -41,7 +41,7 @@ struct wm5102_priv { + static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); + static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); + static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); +-static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); ++static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0); + static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); + + static const struct wm_adsp_region wm5102_dsp1_regions[] = { +diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c +index 2c3c962d9a85..0fce853bda44 100644 +--- a/sound/soc/codecs/wm5110.c ++++ b/sound/soc/codecs/wm5110.c +@@ -167,7 +167,7 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, + static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); + static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); + static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); +-static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); ++static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0); + static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); + + #define WM5110_NG_SRC(name, base) \ +diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c +index 2f167a8ca01b..62bacb8536e6 100644 +--- a/sound/soc/codecs/wm8737.c ++++ b/sound/soc/codecs/wm8737.c +@@ -494,7 +494,8 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec, + + /* Fast VMID ramp at 2*2.5k */ + snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, +- WM8737_VMIDSEL_MASK, 0x4); ++ WM8737_VMIDSEL_MASK, ++ 2 << WM8737_VMIDSEL_SHIFT); + + /* Bring VMID up */ + snd_soc_update_bits(codec, WM8737_POWER_MANAGEMENT, +@@ -508,7 +509,8 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec, + + /* VMID at 2*300k */ + snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, +- WM8737_VMIDSEL_MASK, 2); ++ WM8737_VMIDSEL_MASK, ++ 1 << WM8737_VMIDSEL_SHIFT); + + break; + +diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h +index db949311c0f2..0bb4a647755d 100644 +--- a/sound/soc/codecs/wm8903.h ++++ b/sound/soc/codecs/wm8903.h +@@ -172,7 +172,7 @@ extern int wm8903_mic_detect(struct snd_soc_codec *codec, + #define WM8903_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */ + + #define WM8903_VMID_RES_50K 2 +-#define WM8903_VMID_RES_250K 3 ++#define WM8903_VMID_RES_250K 4 + #define WM8903_VMID_RES_5K 6 + + /* +diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c +index 1c1fc6119758..475fc24c8ff6 100644 +--- a/sound/soc/codecs/wm8955.c ++++ b/sound/soc/codecs/wm8955.c +@@ -298,7 +298,7 @@ static int wm8955_configure_clocking(struct snd_soc_codec *codec) + snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2, + WM8955_K_17_9_MASK, + (pll.k >> 9) & WM8955_K_17_9_MASK); +- snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2, ++ snd_soc_update_bits(codec, WM8955_PLL_CONTROL_3, + WM8955_K_8_0_MASK, + pll.k & WM8955_K_8_0_MASK); + if (pll.k) +diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c +index edfd4edaa864..e04dbaa1de8f 100644 +--- a/sound/soc/codecs/wm8960.c ++++ b/sound/soc/codecs/wm8960.c +@@ -242,7 +242,7 @@ SOC_SINGLE("PCM Playback -6dB Switch", WM8960_DACCTL1, 7, 1, 0), + SOC_ENUM("ADC Polarity", wm8960_enum[0]), + SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1, 0, 1, 0), + +-SOC_ENUM("DAC Polarity", wm8960_enum[2]), ++SOC_ENUM("DAC Polarity", wm8960_enum[1]), + SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0, + wm8960_get_deemph, wm8960_put_deemph), + +diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c +index 555115ee2159..1461ae611f31 100644 +--- a/sound/soc/codecs/wm8997.c ++++ b/sound/soc/codecs/wm8997.c +@@ -40,7 +40,7 @@ struct wm8997_priv { + static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); + static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); + static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); +-static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); ++static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0); + static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); + + static const struct reg_default wm8997_sysclk_reva_patch[] = { +diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c +index 3a3d17ce6ba4..664452599497 100644 +--- a/sound/soc/fsl/imx-wm8962.c ++++ b/sound/soc/fsl/imx-wm8962.c +@@ -190,7 +190,7 @@ static int imx_wm8962_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "audmux internal port setup failed\n"); + return ret; + } +- imx_audmux_v2_configure_port(ext_port, ++ ret = imx_audmux_v2_configure_port(ext_port, + IMX_AUDMUX_V2_PTCR_SYN, + IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); + if (ret) { diff --git a/patch/kernel/cubox-default/patch-3.14.49-50.patch b/patch/kernel/cubox-default/patch-3.14.49-50.patch new file mode 100644 index 000000000..41fc25a1c --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.49-50.patch @@ -0,0 +1,700 @@ +diff --git a/Makefile b/Makefile +index fee84602e999..d71c40a34b30 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 49 ++SUBLEVEL = 50 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h +index 1bfeec2c0558..2a58af7a2e3a 100644 +--- a/arch/arc/include/asm/ptrace.h ++++ b/arch/arc/include/asm/ptrace.h +@@ -63,7 +63,7 @@ struct callee_regs { + long r25, r24, r23, r22, r21, r20, r19, r18, r17, r16, r15, r14, r13; + }; + +-#define instruction_pointer(regs) ((regs)->ret) ++#define instruction_pointer(regs) (unsigned long)((regs)->ret) + #define profile_pc(regs) instruction_pointer(regs) + + /* return 1 if user mode or 0 if kernel mode */ +diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c +index 23b1a97fae7a..52c179bec0cc 100644 +--- a/arch/avr32/mach-at32ap/clock.c ++++ b/arch/avr32/mach-at32ap/clock.c +@@ -80,6 +80,9 @@ int clk_enable(struct clk *clk) + { + unsigned long flags; + ++ if (!clk) ++ return 0; ++ + spin_lock_irqsave(&clk_lock, flags); + __clk_enable(clk); + spin_unlock_irqrestore(&clk_lock, flags); +@@ -106,6 +109,9 @@ void clk_disable(struct clk *clk) + { + unsigned long flags; + ++ if (IS_ERR_OR_NULL(clk)) ++ return; ++ + spin_lock_irqsave(&clk_lock, flags); + __clk_disable(clk); + spin_unlock_irqrestore(&clk_lock, flags); +@@ -117,6 +123,9 @@ unsigned long clk_get_rate(struct clk *clk) + unsigned long flags; + unsigned long rate; + ++ if (!clk) ++ return 0; ++ + spin_lock_irqsave(&clk_lock, flags); + rate = clk->get_rate(clk); + spin_unlock_irqrestore(&clk_lock, flags); +@@ -129,6 +138,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate) + { + unsigned long flags, actual_rate; + ++ if (!clk) ++ return 0; ++ + if (!clk->set_rate) + return -ENOSYS; + +@@ -145,6 +157,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate) + unsigned long flags; + long ret; + ++ if (!clk) ++ return 0; ++ + if (!clk->set_rate) + return -ENOSYS; + +@@ -161,6 +176,9 @@ int clk_set_parent(struct clk *clk, struct clk *parent) + unsigned long flags; + int ret; + ++ if (!clk) ++ return 0; ++ + if (!clk->set_parent) + return -ENOSYS; + +@@ -174,7 +192,7 @@ EXPORT_SYMBOL(clk_set_parent); + + struct clk *clk_get_parent(struct clk *clk) + { +- return clk->parent; ++ return !clk ? NULL : clk->parent; + } + EXPORT_SYMBOL(clk_get_parent); + +diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S +index 29bd7bec4176..1ecd47b5e250 100644 +--- a/arch/s390/kernel/sclp.S ++++ b/arch/s390/kernel/sclp.S +@@ -276,6 +276,8 @@ ENTRY(_sclp_print_early) + jno .Lesa2 + ahi %r15,-80 + stmh %r6,%r15,96(%r15) # store upper register halves ++ basr %r13,0 ++ lmh %r0,%r15,.Lzeroes-.(%r13) # clear upper register halves + .Lesa2: + #endif + lr %r10,%r2 # save string pointer +@@ -299,6 +301,8 @@ ENTRY(_sclp_print_early) + #endif + lm %r6,%r15,120(%r15) # restore registers + br %r14 ++.Lzeroes: ++ .fill 64,4,0 + + .LwritedataS4: + .long 0x00760005 # SCLP command for write data +diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c +index 74c91729a62a..bdb3ecf8e168 100644 +--- a/arch/tile/kernel/setup.c ++++ b/arch/tile/kernel/setup.c +@@ -1146,7 +1146,7 @@ static void __init load_hv_initrd(void) + + void __init free_initrd_mem(unsigned long begin, unsigned long end) + { +- free_bootmem(__pa(begin), end - begin); ++ free_bootmem_late(__pa(begin), end - begin); + } + + static int __init setup_initrd(char *str) +diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c +index 78cbb2db5a85..ec5a3c7fac7a 100644 +--- a/arch/x86/boot/compressed/eboot.c ++++ b/arch/x86/boot/compressed/eboot.c +@@ -560,6 +560,10 @@ static efi_status_t setup_e820(struct boot_params *params, + unsigned int e820_type = 0; + unsigned long m = efi->efi_memmap; + ++#ifdef CONFIG_X86_64 ++ m |= (u64)efi->efi_memmap_hi << 32; ++#endif ++ + d = (efi_memory_desc_t *)(m + (i * efi->efi_memdesc_size)); + switch (d->type) { + case EFI_RESERVED_TYPE: +diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S +index c5b56ed10aff..a814c80eb580 100644 +--- a/arch/x86/boot/compressed/head_32.S ++++ b/arch/x86/boot/compressed/head_32.S +@@ -54,7 +54,7 @@ ENTRY(efi_pe_entry) + call reloc + reloc: + popl %ecx +- subl reloc, %ecx ++ subl $reloc, %ecx + movl %ecx, BP_code32_start(%eax) + + sub $0x4, %esp +diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c +index d8f80e733cf8..a7175855b6ed 100644 +--- a/block/blk-cgroup.c ++++ b/block/blk-cgroup.c +@@ -703,8 +703,12 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, + return -EINVAL; + + disk = get_gendisk(MKDEV(major, minor), &part); +- if (!disk || part) ++ if (!disk) + return -EINVAL; ++ if (part) { ++ put_disk(disk); ++ return -EINVAL; ++ } + + rcu_read_lock(); + spin_lock_irq(disk->queue->queue_lock); +diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c +index 7ccc084bf1df..85aa76116a30 100644 +--- a/drivers/ata/libata-pmp.c ++++ b/drivers/ata/libata-pmp.c +@@ -460,6 +460,13 @@ static void sata_pmp_quirks(struct ata_port *ap) + ATA_LFLAG_NO_SRST | + ATA_LFLAG_ASSUME_ATA; + } ++ } else if (vendor == 0x11ab && devid == 0x4140) { ++ /* Marvell 4140 quirks */ ++ ata_for_each_link(link, ap, EDGE) { ++ /* port 4 is for SEMB device and it doesn't like SRST */ ++ if (link->pmp == 4) ++ link->flags |= ATA_LFLAG_DISABLED; ++ } + } + } + +diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c +index a0966331a89b..c6f7e918b2b1 100644 +--- a/drivers/input/touchscreen/usbtouchscreen.c ++++ b/drivers/input/touchscreen/usbtouchscreen.c +@@ -625,6 +625,9 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) + goto err_out; + } + ++ /* TSC-25 data sheet specifies a delay after the RESET command */ ++ msleep(150); ++ + /* set coordinate output rate */ + buf[0] = buf[1] = 0xFF; + ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index b96ee9d78aa3..9be97e0bd149 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -336,7 +336,7 @@ static void raid1_end_read_request(struct bio *bio, int error) + spin_lock_irqsave(&conf->device_lock, flags); + if (r1_bio->mddev->degraded == conf->raid_disks || + (r1_bio->mddev->degraded == conf->raid_disks-1 && +- !test_bit(Faulty, &conf->mirrors[mirror].rdev->flags))) ++ test_bit(In_sync, &conf->mirrors[mirror].rdev->flags))) + uptodate = 1; + spin_unlock_irqrestore(&conf->device_lock, flags); + } +diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h +index a7d9f95a7b03..7fd86becfd1a 100644 +--- a/drivers/mmc/host/sdhci-esdhc.h ++++ b/drivers/mmc/host/sdhci-esdhc.h +@@ -47,6 +47,6 @@ + #define ESDHC_DMA_SYSCTL 0x40c + #define ESDHC_DMA_SNOOP 0x00000040 + +-#define ESDHC_HOST_CONTROL_RES 0x05 ++#define ESDHC_HOST_CONTROL_RES 0x01 + + #endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */ +diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c +index 561c6b4907a1..b80766699249 100644 +--- a/drivers/mmc/host/sdhci-pxav3.c ++++ b/drivers/mmc/host/sdhci-pxav3.c +@@ -257,6 +257,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) + goto err_of_parse; + sdhci_get_of_property(pdev); + pdata = pxav3_get_mmc_pdata(dev); ++ pdev->dev.platform_data = pdata; + } else if (pdata) { + /* on-chip device */ + if (pdata->flags & PXA_FLAG_CARD_PERMANENT) +diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c +index a1d6986261a3..f3109828c6df 100644 +--- a/drivers/scsi/st.c ++++ b/drivers/scsi/st.c +@@ -1262,9 +1262,9 @@ static int st_open(struct inode *inode, struct file *filp) + spin_lock(&st_use_lock); + STp->in_use = 0; + spin_unlock(&st_use_lock); +- scsi_tape_put(STp); + if (resumed) + scsi_autopm_put_device(STp->device); ++ scsi_tape_put(STp); + return retval; + + } +diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c +index c8d7b3009c7e..55ec9b4b97cc 100644 +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -4476,7 +4476,18 @@ static void iscsit_logout_post_handler_closesession( + struct iscsi_conn *conn) + { + struct iscsi_session *sess = conn->sess; +- int sleep = cmpxchg(&conn->tx_thread_active, true, false); ++ int sleep = 1; ++ /* ++ * Traditional iscsi/tcp will invoke this logic from TX thread ++ * context during session logout, so clear tx_thread_active and ++ * sleep if iscsit_close_connection() has not already occured. ++ * ++ * Since iser-target invokes this logic from it's own workqueue, ++ * always sleep waiting for RX/TX thread shutdown to complete ++ * within iscsit_close_connection(). ++ */ ++ if (conn->conn_transport->transport_type == ISCSI_TCP) ++ sleep = cmpxchg(&conn->tx_thread_active, true, false); + + atomic_set(&conn->conn_logout_remove, 0); + complete(&conn->conn_logout_comp); +@@ -4490,7 +4501,10 @@ static void iscsit_logout_post_handler_closesession( + static void iscsit_logout_post_handler_samecid( + struct iscsi_conn *conn) + { +- int sleep = cmpxchg(&conn->tx_thread_active, true, false); ++ int sleep = 1; ++ ++ if (conn->conn_transport->transport_type == ISCSI_TCP) ++ sleep = cmpxchg(&conn->tx_thread_active, true, false); + + atomic_set(&conn->conn_logout_remove, 0); + complete(&conn->conn_logout_comp); +@@ -4709,6 +4723,7 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force) + struct iscsi_session *sess; + struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; + struct se_session *se_sess, *se_sess_tmp; ++ LIST_HEAD(free_list); + int session_count = 0; + + spin_lock_bh(&se_tpg->session_lock); +@@ -4730,14 +4745,17 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force) + } + atomic_set(&sess->session_reinstatement, 1); + spin_unlock(&sess->conn_lock); +- spin_unlock_bh(&se_tpg->session_lock); + +- iscsit_free_session(sess); +- spin_lock_bh(&se_tpg->session_lock); ++ list_move_tail(&se_sess->sess_list, &free_list); ++ } ++ spin_unlock_bh(&se_tpg->session_lock); + ++ list_for_each_entry_safe(se_sess, se_sess_tmp, &free_list, sess_list) { ++ sess = (struct iscsi_session *)se_sess->fabric_sess_ptr; ++ ++ iscsit_free_session(sess); + session_count++; + } +- spin_unlock_bh(&se_tpg->session_lock); + + pr_debug("Released %d iSCSI Session(s) from Target Portal" + " Group: %hu\n", session_count, tpg->tpgt); +diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c +index b9e16abb0fab..5c957658a04a 100644 +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -480,10 +480,13 @@ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, + u32 pls = status_reg & PORT_PLS_MASK; + + /* resume state is a xHCI internal state. +- * Do not report it to usb core. ++ * Do not report it to usb core, instead, pretend to be U3, ++ * thus usb core knows it's not ready for transfer + */ +- if (pls == XDEV_RESUME) ++ if (pls == XDEV_RESUME) { ++ *status |= USB_SS_PORT_LS_U3; + return; ++ } + + /* When the CAS bit is set then warm reset + * should be performed on port +@@ -584,7 +587,14 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, + status |= USB_PORT_STAT_C_RESET << 16; + /* USB3.0 only */ + if (hcd->speed == HCD_USB3) { +- if ((raw_port_status & PORT_PLC)) ++ /* Port link change with port in resume state should not be ++ * reported to usbcore, as this is an internal state to be ++ * handled by xhci driver. Reporting PLC to usbcore may ++ * cause usbcore clearing PLC first and port change event ++ * irq won't be generated. ++ */ ++ if ((raw_port_status & PORT_PLC) && ++ (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) + status |= USB_PORT_STAT_C_LINK_STATE << 16; + if ((raw_port_status & PORT_WRC)) + status |= USB_PORT_STAT_C_BH_RESET << 16; +@@ -1114,10 +1124,10 @@ int xhci_bus_suspend(struct usb_hcd *hcd) + spin_lock_irqsave(&xhci->lock, flags); + + if (hcd->self.root_hub->do_remote_wakeup) { +- if (bus_state->resuming_ports) { ++ if (bus_state->resuming_ports || /* USB2 */ ++ bus_state->port_remote_wakeup) { /* USB3 */ + spin_unlock_irqrestore(&xhci->lock, flags); +- xhci_dbg(xhci, "suspend failed because " +- "a port is resuming\n"); ++ xhci_dbg(xhci, "suspend failed because a port is resuming\n"); + return -EBUSY; + } + } +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index f615712e8251..bcc43a21fd12 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1740,6 +1740,9 @@ static void handle_port_status(struct xhci_hcd *xhci, + usb_hcd_resume_root_hub(hcd); + } + ++ if (hcd->speed == HCD_USB3 && (temp & PORT_PLS_MASK) == XDEV_INACTIVE) ++ bus_state->port_remote_wakeup &= ~(1 << faked_port_index); ++ + if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) { + xhci_dbg(xhci, "port resume event for port %d\n", port_id); + +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 16f4f8dc1ae9..fc61e663b00a 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -3424,6 +3424,9 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) + return -EINVAL; + } + ++ if (virt_dev->tt_info) ++ old_active_eps = virt_dev->tt_info->active_eps; ++ + if (virt_dev->udev != udev) { + /* If the virt_dev and the udev does not match, this virt_dev + * may belong to another udev. +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 70facb725105..c167485e0653 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -285,6 +285,7 @@ struct xhci_op_regs { + #define XDEV_U0 (0x0 << 5) + #define XDEV_U2 (0x2 << 5) + #define XDEV_U3 (0x3 << 5) ++#define XDEV_INACTIVE (0x6 << 5) + #define XDEV_RESUME (0xf << 5) + /* true: port has power (see HCC_PPC) */ + #define PORT_POWER (1 << 9) +diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h +index 821e1e2f70f6..da380a99c6b8 100644 +--- a/drivers/usb/storage/unusual_devs.h ++++ b/drivers/usb/storage/unusual_devs.h +@@ -2032,6 +2032,18 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NO_READ_DISC_INFO ), + ++/* Reported by Oliver Neukum ++ * This device morphes spontaneously into another device if the access ++ * pattern of Windows isn't followed. Thus writable media would be dirty ++ * if the initial instance is used. So the device is limited to its ++ * virtual CD. ++ * And yes, the concept that BCD goes up to 9 is not heeded */ ++UNUSUAL_DEV( 0x19d2, 0x1225, 0x0000, 0xffff, ++ "ZTE,Incorporated", ++ "ZTE WCDMA Technologies MSM", ++ USB_SC_DEVICE, USB_PR_DEVICE, NULL, ++ US_FL_SINGLE_LUN ), ++ + /* Reported by Sven Geggus + * This encrypted pen drive returns bogus data for the initial READ(10). + */ +diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c +index 78987e481bc6..85095d7aa51c 100644 +--- a/drivers/vhost/vhost.c ++++ b/drivers/vhost/vhost.c +@@ -876,6 +876,7 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp) + } + if (eventfp != d->log_file) { + filep = d->log_file; ++ d->log_file = eventfp; + ctx = d->log_ctx; + d->log_ctx = eventfp ? + eventfd_ctx_fileget(eventfp) : NULL; +diff --git a/fs/dcache.c b/fs/dcache.c +index aa24f7de1b92..3d2f27b4cd38 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -587,6 +587,9 @@ repeat: + if (unlikely(d_unhashed(dentry))) + goto kill_it; + ++ if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) ++ goto kill_it; ++ + if (unlikely(dentry->d_flags & DCACHE_OP_DELETE)) { + if (dentry->d_op->d_delete(dentry)) + goto kill_it; +diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c +index 9065107f083e..7a5237a1bce5 100644 +--- a/kernel/irq/resend.c ++++ b/kernel/irq/resend.c +@@ -75,13 +75,21 @@ void check_irq_resend(struct irq_desc *desc, unsigned int irq) + !desc->irq_data.chip->irq_retrigger(&desc->irq_data)) { + #ifdef CONFIG_HARDIRQS_SW_RESEND + /* +- * If the interrupt has a parent irq and runs +- * in the thread context of the parent irq, +- * retrigger the parent. ++ * If the interrupt is running in the thread ++ * context of the parent irq we need to be ++ * careful, because we cannot trigger it ++ * directly. + */ +- if (desc->parent_irq && +- irq_settings_is_nested_thread(desc)) ++ if (irq_settings_is_nested_thread(desc)) { ++ /* ++ * If the parent_irq is valid, we ++ * retrigger the parent, otherwise we ++ * do nothing. ++ */ ++ if (!desc->parent_irq) ++ return; + irq = desc->parent_irq; ++ } + /* Set it pending and activate the softirq: */ + set_bit(irq, irqs_resend); + tasklet_schedule(&resend_tasklet); +diff --git a/mm/memory.c b/mm/memory.c +index 749e1c68d490..e9ddc7aceefa 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -3234,6 +3234,10 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, + + pte_unmap(page_table); + ++ /* File mapping without ->vm_ops ? */ ++ if (vma->vm_flags & VM_SHARED) ++ return VM_FAULT_SIGBUS; ++ + /* Check if we need to add a guard page to the stack */ + if (check_stack_guard_page(vma, address) < 0) + return VM_FAULT_SIGSEGV; +@@ -3502,6 +3506,9 @@ static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, + - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; + + pte_unmap(page_table); ++ /* The VMA was not fully populated on mmap() or missing VM_DONTEXPAND */ ++ if (!vma->vm_ops->fault) ++ return VM_FAULT_SIGBUS; + return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte); + } + +@@ -3650,11 +3657,9 @@ static int handle_pte_fault(struct mm_struct *mm, + entry = ACCESS_ONCE(*pte); + if (!pte_present(entry)) { + if (pte_none(entry)) { +- if (vma->vm_ops) { +- if (likely(vma->vm_ops->fault)) +- return do_linear_fault(mm, vma, address, ++ if (vma->vm_ops) ++ return do_linear_fault(mm, vma, address, + pte, pmd, flags, entry); +- } + return do_anonymous_page(mm, vma, address, + pte, pmd, flags); + } +diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c +index 653ce5d9e6e0..5d8bc1f6b5a1 100644 +--- a/net/mac80211/debugfs_netdev.c ++++ b/net/mac80211/debugfs_netdev.c +@@ -712,6 +712,7 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) + + debugfs_remove_recursive(sdata->vif.debugfs_dir); + sdata->vif.debugfs_dir = NULL; ++ sdata->debugfs.subdir_stations = NULL; + } + + void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) +diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c +index e8fdb172adbb..a985158d95d5 100644 +--- a/net/rds/ib_rdma.c ++++ b/net/rds/ib_rdma.c +@@ -759,8 +759,10 @@ void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents, + } + + ibmr = rds_ib_alloc_fmr(rds_ibdev); +- if (IS_ERR(ibmr)) ++ if (IS_ERR(ibmr)) { ++ rds_ib_dev_put(rds_ibdev); + return ibmr; ++ } + + ret = rds_ib_map_fmr(rds_ibdev, ibmr, sg, nents); + if (ret == 0) +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 2f503c0836a9..907371d87312 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -2282,7 +2282,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { + SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF), + SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF), + SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF), +- SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF), ++ SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF), + + SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), + SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD), +diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c +index b16be3944213..9a3e1076a5b1 100644 +--- a/sound/usb/mixer_maps.c ++++ b/sound/usb/mixer_maps.c +@@ -336,6 +336,20 @@ static const struct usbmix_name_map scms_usb3318_map[] = { + { 0 } + }; + ++/* Bose companion 5, the dB conversion factor is 16 instead of 256 */ ++static struct usbmix_dB_map bose_companion5_dB = {-5006, -6}; ++static struct usbmix_name_map bose_companion5_map[] = { ++ { 3, NULL, .dB = &bose_companion5_dB }, ++ { 0 } /* terminator */ ++}; ++ ++/* Dragonfly DAC 1.2, the dB conversion factor is 1 instead of 256 */ ++static struct usbmix_dB_map dragonfly_1_2_dB = {0, 5000}; ++static struct usbmix_name_map dragonfly_1_2_map[] = { ++ { 7, NULL, .dB = &dragonfly_1_2_dB }, ++ { 0 } /* terminator */ ++}; ++ + /* + * Control map entries + */ +@@ -442,6 +456,16 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { + .id = USB_ID(0x25c4, 0x0003), + .map = scms_usb3318_map, + }, ++ { ++ /* Bose Companion 5 */ ++ .id = USB_ID(0x05a7, 0x1020), ++ .map = bose_companion5_map, ++ }, ++ { ++ /* Dragonfly DAC 1.2 */ ++ .id = USB_ID(0x21b4, 0x0081), ++ .map = dragonfly_1_2_map, ++ }, + { 0 } /* terminator */ + }; + +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index 5293b5ac8b9d..7c24088bcaa4 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -2516,6 +2516,74 @@ YAMAHA_DEVICE(0x7010, "UB99"), + } + }, + ++/* Steinberg devices */ ++{ ++ /* Steinberg MI2 */ ++ USB_DEVICE_VENDOR_SPEC(0x0a4e, 0x2040), ++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { ++ .ifnum = QUIRK_ANY_INTERFACE, ++ .type = QUIRK_COMPOSITE, ++ .data = & (const struct snd_usb_audio_quirk[]) { ++ { ++ .ifnum = 0, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 1, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 2, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 3, ++ .type = QUIRK_MIDI_FIXED_ENDPOINT, ++ .data = &(const struct snd_usb_midi_endpoint_info) { ++ .out_cables = 0x0001, ++ .in_cables = 0x0001 ++ } ++ }, ++ { ++ .ifnum = -1 ++ } ++ } ++ } ++}, ++{ ++ /* Steinberg MI4 */ ++ USB_DEVICE_VENDOR_SPEC(0x0a4e, 0x4040), ++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { ++ .ifnum = QUIRK_ANY_INTERFACE, ++ .type = QUIRK_COMPOSITE, ++ .data = & (const struct snd_usb_audio_quirk[]) { ++ { ++ .ifnum = 0, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 1, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 2, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 3, ++ .type = QUIRK_MIDI_FIXED_ENDPOINT, ++ .data = &(const struct snd_usb_midi_endpoint_info) { ++ .out_cables = 0x0001, ++ .in_cables = 0x0001 ++ } ++ }, ++ { ++ .ifnum = -1 ++ } ++ } ++ } ++}, ++ + /* TerraTec devices */ + { + USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012), diff --git a/patch/kernel/cubox-default/patch-3.14.50-51.patch b/patch/kernel/cubox-default/patch-3.14.50-51.patch new file mode 100644 index 000000000..edca85e3d --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.50-51.patch @@ -0,0 +1,1929 @@ +diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy +index 4c3efe434806..750ab970fa95 100644 +--- a/Documentation/ABI/testing/ima_policy ++++ b/Documentation/ABI/testing/ima_policy +@@ -20,16 +20,18 @@ Description: + action: measure | dont_measure | appraise | dont_appraise | audit + condition:= base | lsm [option] + base: [[func=] [mask=] [fsmagic=] [fsuuid=] [uid=] +- [fowner]] ++ [euid=] [fowner=]] + lsm: [[subj_user=] [subj_role=] [subj_type=] + [obj_user=] [obj_role=] [obj_type=]] + option: [[appraise_type=]] [permit_directio] + + base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK] +- mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC] ++ mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND] ++ [[^]MAY_EXEC] + fsmagic:= hex value + fsuuid:= file system UUID (e.g 8bcbe394-4f13-4144-be8e-5aa9ea2ce2f6) + uid:= decimal value ++ euid:= decimal value + fowner:=decimal value + lsm: are LSM specific + option: appraise_type:= [imasig] +diff --git a/Makefile b/Makefile +index d71c40a34b30..83275d8ed880 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 50 ++SUBLEVEL = 51 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h +index 22a3b9b5d4a1..4157aec4e307 100644 +--- a/arch/arm/include/asm/smp.h ++++ b/arch/arm/include/asm/smp.h +@@ -74,6 +74,7 @@ struct secondary_data { + }; + extern struct secondary_data secondary_data; + extern volatile int pen_release; ++extern void secondary_startup(void); + + extern int __cpu_disable(void); + +diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c +index 4551efd28f8d..399af1e9f6e1 100644 +--- a/arch/arm/mach-omap2/omap_hwmod.c ++++ b/arch/arm/mach-omap2/omap_hwmod.c +@@ -2452,6 +2452,9 @@ static int of_dev_hwmod_lookup(struct device_node *np, + * registers. This address is needed early so the OCP registers that + * are part of the device's address space can be ioremapped properly. + * ++ * If SYSC access is not needed, the registers will not be remapped ++ * and non-availability of MPU access is not treated as an error. ++ * + * Returns 0 on success, -EINVAL if an invalid hwmod is passed, and + * -ENXIO on absent or invalid register target address space. + */ +@@ -2466,6 +2469,11 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data, + + _save_mpu_port_index(oh); + ++ /* if we don't need sysc access we don't need to ioremap */ ++ if (!oh->class->sysc) ++ return 0; ++ ++ /* we can't continue without MPU PORT if we need sysc access */ + if (oh->_int_flags & _HWMOD_NO_MPU_PORT) + return -ENXIO; + +@@ -2475,8 +2483,10 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data, + oh->name); + + /* Extract the IO space from device tree blob */ +- if (!np) ++ if (!np) { ++ pr_err("omap_hwmod: %s: no dt node\n", oh->name); + return -ENXIO; ++ } + + va_start = of_iomap(np, index + oh->mpu_rt_idx); + } else { +@@ -2535,13 +2545,11 @@ static int __init _init(struct omap_hwmod *oh, void *data) + oh->name, np->name); + } + +- if (oh->class->sysc) { +- r = _init_mpu_rt_base(oh, NULL, index, np); +- if (r < 0) { +- WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n", +- oh->name); +- return 0; +- } ++ r = _init_mpu_rt_base(oh, NULL, index, np); ++ if (r < 0) { ++ WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n", ++ oh->name); ++ return 0; + } + + r = _init_clocks(oh, NULL); +diff --git a/arch/arm/mach-realview/include/mach/memory.h b/arch/arm/mach-realview/include/mach/memory.h +index 2022e092f0ca..db09170e3832 100644 +--- a/arch/arm/mach-realview/include/mach/memory.h ++++ b/arch/arm/mach-realview/include/mach/memory.h +@@ -56,6 +56,8 @@ + #define PAGE_OFFSET1 (PAGE_OFFSET + 0x10000000) + #define PAGE_OFFSET2 (PAGE_OFFSET + 0x30000000) + ++#define PHYS_OFFSET PLAT_PHYS_OFFSET ++ + #define __phys_to_virt(phys) \ + ((phys) >= 0x80000000 ? (phys) - 0x80000000 + PAGE_OFFSET2 : \ + (phys) >= 0x20000000 ? (phys) - 0x20000000 + PAGE_OFFSET1 : \ +diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile +index d9397202d6ec..27b168f121a1 100644 +--- a/arch/arm/mach-sunxi/Makefile ++++ b/arch/arm/mach-sunxi/Makefile +@@ -1,2 +1,2 @@ + obj-$(CONFIG_ARCH_SUNXI) += sunxi.o +-obj-$(CONFIG_SMP) += platsmp.o headsmp.o ++obj-$(CONFIG_SMP) += platsmp.o +diff --git a/arch/arm/mach-sunxi/headsmp.S b/arch/arm/mach-sunxi/headsmp.S +deleted file mode 100644 +index a10d494fb37b..000000000000 +--- a/arch/arm/mach-sunxi/headsmp.S ++++ /dev/null +@@ -1,9 +0,0 @@ +-#include +-#include +- +- .section ".text.head", "ax" +- +-ENTRY(sun6i_secondary_startup) +- msr cpsr_fsxc, #0xd3 +- b secondary_startup +-ENDPROC(sun6i_secondary_startup) +diff --git a/arch/arm/mach-sunxi/platsmp.c b/arch/arm/mach-sunxi/platsmp.c +index 7b141d8342a1..0c7dbce033cc 100644 +--- a/arch/arm/mach-sunxi/platsmp.c ++++ b/arch/arm/mach-sunxi/platsmp.c +@@ -82,7 +82,7 @@ static int sun6i_smp_boot_secondary(unsigned int cpu, + spin_lock(&cpu_lock); + + /* Set CPU boot address */ +- writel(virt_to_phys(sun6i_secondary_startup), ++ writel(virt_to_phys(secondary_startup), + cpucfg_membase + CPUCFG_PRIVATE0_REG); + + /* Assert the CPU core in reset */ +diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c +index 7ed72dc0fb0e..a966baccf1c0 100644 +--- a/arch/arm64/kernel/signal32.c ++++ b/arch/arm64/kernel/signal32.c +@@ -165,7 +165,8 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) + * Other callers might not initialize the si_lsb field, + * so check explicitely for the right codes here. + */ +- if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO) ++ if (from->si_signo == SIGBUS && ++ (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)) + err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb); + #endif + break; +@@ -192,8 +193,6 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) + + int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) + { +- memset(to, 0, sizeof *to); +- + if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) || + copy_from_user(to->_sifields._pad, + from->_sifields._pad, SI_PAD_SIZE)) +diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h +index 008324d1c261..b15495367d5c 100644 +--- a/arch/mips/include/asm/pgtable.h ++++ b/arch/mips/include/asm/pgtable.h +@@ -150,8 +150,39 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) + * Make sure the buddy is global too (if it's !none, + * it better already be global) + */ ++#ifdef CONFIG_SMP ++ /* ++ * For SMP, multiple CPUs can race, so we need to do ++ * this atomically. ++ */ ++#ifdef CONFIG_64BIT ++#define LL_INSN "lld" ++#define SC_INSN "scd" ++#else /* CONFIG_32BIT */ ++#define LL_INSN "ll" ++#define SC_INSN "sc" ++#endif ++ unsigned long page_global = _PAGE_GLOBAL; ++ unsigned long tmp; ++ ++ __asm__ __volatile__ ( ++ " .set push\n" ++ " .set noreorder\n" ++ "1: " LL_INSN " %[tmp], %[buddy]\n" ++ " bnez %[tmp], 2f\n" ++ " or %[tmp], %[tmp], %[global]\n" ++ " " SC_INSN " %[tmp], %[buddy]\n" ++ " beqz %[tmp], 1b\n" ++ " nop\n" ++ "2:\n" ++ " .set pop" ++ : [buddy] "+m" (buddy->pte), ++ [tmp] "=&r" (tmp) ++ : [global] "r" (page_global)); ++#else /* !CONFIG_SMP */ + if (pte_none(*buddy)) + pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL; ++#endif /* CONFIG_SMP */ + } + #endif + } +diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c +index cb098628aee8..ca16964a2b5e 100644 +--- a/arch/mips/kernel/mips-mt-fpaff.c ++++ b/arch/mips/kernel/mips-mt-fpaff.c +@@ -154,7 +154,7 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len, + unsigned long __user *user_mask_ptr) + { + unsigned int real_len; +- cpumask_t mask; ++ cpumask_t allowed, mask; + int retval; + struct task_struct *p; + +@@ -173,7 +173,8 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len, + if (retval) + goto out_unlock; + +- cpumask_and(&mask, &p->thread.user_cpus_allowed, cpu_possible_mask); ++ cpumask_or(&allowed, &p->thread.user_cpus_allowed, &p->cpus_allowed); ++ cpumask_and(&mask, &allowed, cpu_active_mask); + + out_unlock: + read_unlock(&tasklist_lock); +diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c +index 3d60f7750fa8..ea585cf80eb2 100644 +--- a/arch/mips/kernel/signal32.c ++++ b/arch/mips/kernel/signal32.c +@@ -370,8 +370,6 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) + + int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) + { +- memset(to, 0, sizeof *to); +- + if (copy_from_user(to, from, 3*sizeof(int)) || + copy_from_user(to->_sifields._pad, + from->_sifields._pad, SI_PAD_SIZE32)) +diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c +index 319009912142..d4ab447f7850 100644 +--- a/arch/mips/mti-malta/malta-time.c ++++ b/arch/mips/mti-malta/malta-time.c +@@ -168,14 +168,17 @@ unsigned int get_c0_compare_int(void) + + static void __init init_rtc(void) + { +- /* stop the clock whilst setting it up */ +- CMOS_WRITE(RTC_SET | RTC_24H, RTC_CONTROL); ++ unsigned char freq, ctrl; + +- /* 32KHz time base */ +- CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_FREQ_SELECT); ++ /* Set 32KHz time base if not already set */ ++ freq = CMOS_READ(RTC_FREQ_SELECT); ++ if ((freq & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ) ++ CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_FREQ_SELECT); + +- /* start the clock */ +- CMOS_WRITE(RTC_24H, RTC_CONTROL); ++ /* Ensure SET bit is clear so RTC can run */ ++ ctrl = CMOS_READ(RTC_CONTROL); ++ if (ctrl & RTC_SET) ++ CMOS_WRITE(ctrl & ~RTC_SET, RTC_CONTROL); + } + + void __init plat_time_init(void) +diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c +index 4e47db686b5d..e881e3f5f0ec 100644 +--- a/arch/powerpc/kernel/signal_32.c ++++ b/arch/powerpc/kernel/signal_32.c +@@ -967,8 +967,6 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *d, const siginfo_t *s) + + int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from) + { +- memset(to, 0, sizeof *to); +- + if (copy_from_user(to, from, 3*sizeof(int)) || + copy_from_user(to->_sifields._pad, + from->_sifields._pad, SI_PAD_SIZE32)) +diff --git a/arch/sparc/include/asm/visasm.h b/arch/sparc/include/asm/visasm.h +index 11fdf0ef50bb..50d6f16a1513 100644 +--- a/arch/sparc/include/asm/visasm.h ++++ b/arch/sparc/include/asm/visasm.h +@@ -28,16 +28,10 @@ + * Must preserve %o5 between VISEntryHalf and VISExitHalf */ + + #define VISEntryHalf \ +- rd %fprs, %o5; \ +- andcc %o5, FPRS_FEF, %g0; \ +- be,pt %icc, 297f; \ +- sethi %hi(298f), %g7; \ +- sethi %hi(VISenterhalf), %g1; \ +- jmpl %g1 + %lo(VISenterhalf), %g0; \ +- or %g7, %lo(298f), %g7; \ +- clr %o5; \ +-297: wr %o5, FPRS_FEF, %fprs; \ +-298: ++ VISEntry ++ ++#define VISExitHalf \ ++ VISExit + + #define VISEntryHalfFast(fail_label) \ + rd %fprs, %o5; \ +@@ -47,7 +41,7 @@ + ba,a,pt %xcc, fail_label; \ + 297: wr %o5, FPRS_FEF, %fprs; + +-#define VISExitHalf \ ++#define VISExitHalfFast \ + wr %o5, 0, %fprs; + + #ifndef __ASSEMBLY__ +diff --git a/arch/sparc/lib/NG4memcpy.S b/arch/sparc/lib/NG4memcpy.S +index 140527a20e7d..83aeeb1dffdb 100644 +--- a/arch/sparc/lib/NG4memcpy.S ++++ b/arch/sparc/lib/NG4memcpy.S +@@ -240,8 +240,11 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ + add %o0, 0x40, %o0 + bne,pt %icc, 1b + LOAD(prefetch, %g1 + 0x200, #n_reads_strong) ++#ifdef NON_USER_COPY ++ VISExitHalfFast ++#else + VISExitHalf +- ++#endif + brz,pn %o2, .Lexit + cmp %o2, 19 + ble,pn %icc, .Lsmall_unaligned +diff --git a/arch/sparc/lib/VISsave.S b/arch/sparc/lib/VISsave.S +index b320ae9e2e2e..a063d84336d6 100644 +--- a/arch/sparc/lib/VISsave.S ++++ b/arch/sparc/lib/VISsave.S +@@ -44,9 +44,8 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3 + + stx %g3, [%g6 + TI_GSR] + 2: add %g6, %g1, %g3 +- cmp %o5, FPRS_DU +- be,pn %icc, 6f +- sll %g1, 3, %g1 ++ mov FPRS_DU | FPRS_DL | FPRS_FEF, %o5 ++ sll %g1, 3, %g1 + stb %o5, [%g3 + TI_FPSAVED] + rd %gsr, %g2 + add %g6, %g1, %g3 +@@ -80,65 +79,3 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3 + .align 32 + 80: jmpl %g7 + %g0, %g0 + nop +- +-6: ldub [%g3 + TI_FPSAVED], %o5 +- or %o5, FPRS_DU, %o5 +- add %g6, TI_FPREGS+0x80, %g2 +- stb %o5, [%g3 + TI_FPSAVED] +- +- sll %g1, 5, %g1 +- add %g6, TI_FPREGS+0xc0, %g3 +- wr %g0, FPRS_FEF, %fprs +- membar #Sync +- stda %f32, [%g2 + %g1] ASI_BLK_P +- stda %f48, [%g3 + %g1] ASI_BLK_P +- membar #Sync +- ba,pt %xcc, 80f +- nop +- +- .align 32 +-80: jmpl %g7 + %g0, %g0 +- nop +- +- .align 32 +-VISenterhalf: +- ldub [%g6 + TI_FPDEPTH], %g1 +- brnz,a,pn %g1, 1f +- cmp %g1, 1 +- stb %g0, [%g6 + TI_FPSAVED] +- stx %fsr, [%g6 + TI_XFSR] +- clr %o5 +- jmpl %g7 + %g0, %g0 +- wr %g0, FPRS_FEF, %fprs +- +-1: bne,pn %icc, 2f +- srl %g1, 1, %g1 +- ba,pt %xcc, vis1 +- sub %g7, 8, %g7 +-2: addcc %g6, %g1, %g3 +- sll %g1, 3, %g1 +- andn %o5, FPRS_DU, %g2 +- stb %g2, [%g3 + TI_FPSAVED] +- +- rd %gsr, %g2 +- add %g6, %g1, %g3 +- stx %g2, [%g3 + TI_GSR] +- add %g6, %g1, %g2 +- stx %fsr, [%g2 + TI_XFSR] +- sll %g1, 5, %g1 +-3: andcc %o5, FPRS_DL, %g0 +- be,pn %icc, 4f +- add %g6, TI_FPREGS, %g2 +- +- add %g6, TI_FPREGS+0x40, %g3 +- membar #Sync +- stda %f0, [%g2 + %g1] ASI_BLK_P +- stda %f16, [%g3 + %g1] ASI_BLK_P +- membar #Sync +- ba,pt %xcc, 4f +- nop +- +- .align 32 +-4: and %o5, FPRS_DU, %o5 +- jmpl %g7 + %g0, %g0 +- wr %o5, FPRS_FEF, %fprs +diff --git a/arch/sparc/lib/ksyms.c b/arch/sparc/lib/ksyms.c +index 323335b9cd2b..ac094de28ccf 100644 +--- a/arch/sparc/lib/ksyms.c ++++ b/arch/sparc/lib/ksyms.c +@@ -126,10 +126,6 @@ EXPORT_SYMBOL(copy_user_page); + void VISenter(void); + EXPORT_SYMBOL(VISenter); + +-/* CRYPTO code needs this */ +-void VISenterhalf(void); +-EXPORT_SYMBOL(VISenterhalf); +- + extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *); + extern void xor_vis_3(unsigned long, unsigned long *, unsigned long *, + unsigned long *); +diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h +index 6a11845fd8b9..72051730caf1 100644 +--- a/arch/x86/kvm/lapic.h ++++ b/arch/x86/kvm/lapic.h +@@ -165,7 +165,7 @@ static inline u16 apic_logical_id(struct kvm_apic_map *map, u32 ldr) + + static inline bool kvm_apic_has_events(struct kvm_vcpu *vcpu) + { +- return vcpu->arch.apic->pending_events; ++ return kvm_vcpu_has_lapic(vcpu) && vcpu->arch.apic->pending_events; + } + + bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector); +diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c +index 201d09a7c46b..2302f10b1be6 100644 +--- a/arch/x86/xen/enlighten.c ++++ b/arch/x86/xen/enlighten.c +@@ -481,6 +481,7 @@ static void set_aliased_prot(void *v, pgprot_t prot) + pte_t pte; + unsigned long pfn; + struct page *page; ++ unsigned char dummy; + + ptep = lookup_address((unsigned long)v, &level); + BUG_ON(ptep == NULL); +@@ -490,6 +491,32 @@ static void set_aliased_prot(void *v, pgprot_t prot) + + pte = pfn_pte(pfn, prot); + ++ /* ++ * Careful: update_va_mapping() will fail if the virtual address ++ * we're poking isn't populated in the page tables. We don't ++ * need to worry about the direct map (that's always in the page ++ * tables), but we need to be careful about vmap space. In ++ * particular, the top level page table can lazily propagate ++ * entries between processes, so if we've switched mms since we ++ * vmapped the target in the first place, we might not have the ++ * top-level page table entry populated. ++ * ++ * We disable preemption because we want the same mm active when ++ * we probe the target and when we issue the hypercall. We'll ++ * have the same nominal mm, but if we're a kernel thread, lazy ++ * mm dropping could change our pgd. ++ * ++ * Out of an abundance of caution, this uses __get_user() to fault ++ * in the target address just in case there's some obscure case ++ * in which the target address isn't readable. ++ */ ++ ++ preempt_disable(); ++ ++ pagefault_disable(); /* Avoid warnings due to being atomic. */ ++ __get_user(dummy, (unsigned char __user __force *)v); ++ pagefault_enable(); ++ + if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0)) + BUG(); + +@@ -501,6 +528,8 @@ static void set_aliased_prot(void *v, pgprot_t prot) + BUG(); + } else + kmap_flush_unused(); ++ ++ preempt_enable(); + } + + static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries) +@@ -508,6 +537,17 @@ static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries) + const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE; + int i; + ++ /* ++ * We need to mark the all aliases of the LDT pages RO. We ++ * don't need to call vm_flush_aliases(), though, since that's ++ * only responsible for flushing aliases out the TLBs, not the ++ * page tables, and Xen will flush the TLB for us if needed. ++ * ++ * To avoid confusing future readers: none of this is necessary ++ * to load the LDT. The hypervisor only checks this when the ++ * LDT is faulted in due to subsequent descriptor access. ++ */ ++ + for(i = 0; i < entries; i += entries_per_page) + set_aliased_prot(ldt + i, PAGE_KERNEL_RO); + } +diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c +index 12be7cbfba4f..b583773e4ecb 100644 +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -508,6 +508,7 @@ void rbd_warn(struct rbd_device *rbd_dev, const char *fmt, ...) + # define rbd_assert(expr) ((void) 0) + #endif /* !RBD_DEBUG */ + ++static void rbd_osd_copyup_callback(struct rbd_obj_request *obj_request); + static int rbd_img_obj_request_submit(struct rbd_obj_request *obj_request); + static void rbd_img_parent_read(struct rbd_obj_request *obj_request); + static void rbd_dev_remove_parent(struct rbd_device *rbd_dev); +@@ -1651,6 +1652,16 @@ static void rbd_osd_stat_callback(struct rbd_obj_request *obj_request) + obj_request_done_set(obj_request); + } + ++static void rbd_osd_call_callback(struct rbd_obj_request *obj_request) ++{ ++ dout("%s: obj %p\n", __func__, obj_request); ++ ++ if (obj_request_img_data_test(obj_request)) ++ rbd_osd_copyup_callback(obj_request); ++ else ++ obj_request_done_set(obj_request); ++} ++ + static void rbd_osd_req_callback(struct ceph_osd_request *osd_req, + struct ceph_msg *msg) + { +@@ -1689,6 +1700,8 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req, + rbd_osd_stat_callback(obj_request); + break; + case CEPH_OSD_OP_CALL: ++ rbd_osd_call_callback(obj_request); ++ break; + case CEPH_OSD_OP_NOTIFY_ACK: + case CEPH_OSD_OP_WATCH: + rbd_osd_trivial_callback(obj_request); +@@ -2275,13 +2288,15 @@ out_unwind: + } + + static void +-rbd_img_obj_copyup_callback(struct rbd_obj_request *obj_request) ++rbd_osd_copyup_callback(struct rbd_obj_request *obj_request) + { + struct rbd_img_request *img_request; + struct rbd_device *rbd_dev; + struct page **pages; + u32 page_count; + ++ dout("%s: obj %p\n", __func__, obj_request); ++ + rbd_assert(obj_request->type == OBJ_REQUEST_BIO); + rbd_assert(obj_request_img_data_test(obj_request)); + img_request = obj_request->img_request; +@@ -2307,9 +2322,7 @@ rbd_img_obj_copyup_callback(struct rbd_obj_request *obj_request) + if (!obj_request->result) + obj_request->xferred = obj_request->length; + +- /* Finish up with the normal image object callback */ +- +- rbd_img_obj_callback(obj_request); ++ obj_request_done_set(obj_request); + } + + static void +@@ -2406,7 +2419,6 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request) + + /* All set, send it off. */ + +- orig_request->callback = rbd_img_obj_copyup_callback; + osdc = &rbd_dev->rbd_client->client->osdc; + img_result = rbd_obj_request_submit(osdc, orig_request); + if (!img_result) +diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c +index f757a0f428bd..3beed38d306a 100644 +--- a/drivers/crypto/ixp4xx_crypto.c ++++ b/drivers/crypto/ixp4xx_crypto.c +@@ -904,7 +904,6 @@ static int ablk_perform(struct ablkcipher_request *req, int encrypt) + crypt->mode |= NPE_OP_NOT_IN_PLACE; + /* This was never tested by Intel + * for more than one dst buffer, I think. */ +- BUG_ON(req->dst->length < nbytes); + req_ctx->dst = NULL; + if (!chainup_buffers(dev, req->dst, nbytes, &dst_hook, + flags, DMA_FROM_DEVICE)) +diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c +index 6651177110f0..79a266934327 100644 +--- a/drivers/gpu/drm/radeon/radeon_combios.c ++++ b/drivers/gpu/drm/radeon/radeon_combios.c +@@ -1255,10 +1255,15 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder + + if ((RBIOS16(tmp) == lvds->native_mode.hdisplay) && + (RBIOS16(tmp + 2) == lvds->native_mode.vdisplay)) { ++ u32 hss = (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - 1) * 8; ++ ++ if (hss > lvds->native_mode.hdisplay) ++ hss = (10 - 1) * 8; ++ + lvds->native_mode.htotal = lvds->native_mode.hdisplay + + (RBIOS16(tmp + 17) - RBIOS16(tmp + 19)) * 8; + lvds->native_mode.hsync_start = lvds->native_mode.hdisplay + +- (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - 1) * 8; ++ hss; + lvds->native_mode.hsync_end = lvds->native_mode.hsync_start + + (RBIOS8(tmp + 23) * 8); + +diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c +index 8e51b3a3e7b9..cc3dc0cb4fe3 100644 +--- a/drivers/md/bitmap.c ++++ b/drivers/md/bitmap.c +@@ -564,6 +564,8 @@ static int bitmap_read_sb(struct bitmap *bitmap) + if (err) + return err; + ++ err = -EINVAL; ++ + sb = kmap_atomic(sb_page); + + chunksize = le32_to_cpu(sb->chunksize); +diff --git a/drivers/md/md.c b/drivers/md/md.c +index b4067b9afd38..2ffd277eb311 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -5645,8 +5645,7 @@ static int get_bitmap_file(struct mddev * mddev, void __user * arg) + char *ptr, *buf = NULL; + int err = -ENOMEM; + +- file = kmalloc(sizeof(*file), GFP_NOIO); +- ++ file = kzalloc(sizeof(*file), GFP_NOIO); + if (!file) + goto out; + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 9be97e0bd149..47b7c3136807 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -1477,6 +1477,7 @@ static void error(struct mddev *mddev, struct md_rdev *rdev) + { + char b[BDEVNAME_SIZE]; + struct r1conf *conf = mddev->private; ++ unsigned long flags; + + /* + * If it is not operational, then we have already marked it as dead +@@ -1496,14 +1497,13 @@ static void error(struct mddev *mddev, struct md_rdev *rdev) + return; + } + set_bit(Blocked, &rdev->flags); ++ spin_lock_irqsave(&conf->device_lock, flags); + if (test_and_clear_bit(In_sync, &rdev->flags)) { +- unsigned long flags; +- spin_lock_irqsave(&conf->device_lock, flags); + mddev->degraded++; + set_bit(Faulty, &rdev->flags); +- spin_unlock_irqrestore(&conf->device_lock, flags); + } else + set_bit(Faulty, &rdev->flags); ++ spin_unlock_irqrestore(&conf->device_lock, flags); + /* + * if recovery is running, make sure it aborts. + */ +@@ -1569,7 +1569,10 @@ static int raid1_spare_active(struct mddev *mddev) + * Find all failed disks within the RAID1 configuration + * and mark them readable. + * Called under mddev lock, so rcu protection not needed. ++ * device_lock used to avoid races with raid1_end_read_request ++ * which expects 'In_sync' flags and ->degraded to be consistent. + */ ++ spin_lock_irqsave(&conf->device_lock, flags); + for (i = 0; i < conf->raid_disks; i++) { + struct md_rdev *rdev = conf->mirrors[i].rdev; + struct md_rdev *repl = conf->mirrors[conf->raid_disks + i].rdev; +@@ -1599,7 +1602,6 @@ static int raid1_spare_active(struct mddev *mddev) + sysfs_notify_dirent_safe(rdev->sysfs_state); + } + } +- spin_lock_irqsave(&conf->device_lock, flags); + mddev->degraded -= count; + spin_unlock_irqrestore(&conf->device_lock, flags); + +diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c +index b4ddb7310e36..128dc2f75186 100644 +--- a/drivers/scsi/ipr.c ++++ b/drivers/scsi/ipr.c +@@ -592,9 +592,10 @@ static void ipr_trc_hook(struct ipr_cmnd *ipr_cmd, + { + struct ipr_trace_entry *trace_entry; + struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; ++ unsigned int trace_index; + +- trace_entry = &ioa_cfg->trace[atomic_add_return +- (1, &ioa_cfg->trace_index)%IPR_NUM_TRACE_ENTRIES]; ++ trace_index = atomic_add_return(1, &ioa_cfg->trace_index) & IPR_TRACE_INDEX_MASK; ++ trace_entry = &ioa_cfg->trace[trace_index]; + trace_entry->time = jiffies; + trace_entry->op_code = ipr_cmd->ioarcb.cmd_pkt.cdb[0]; + trace_entry->type = type; +@@ -1044,10 +1045,15 @@ static void ipr_send_blocking_cmd(struct ipr_cmnd *ipr_cmd, + + static int ipr_get_hrrq_index(struct ipr_ioa_cfg *ioa_cfg) + { ++ unsigned int hrrq; ++ + if (ioa_cfg->hrrq_num == 1) +- return 0; +- else +- return (atomic_add_return(1, &ioa_cfg->hrrq_index) % (ioa_cfg->hrrq_num - 1)) + 1; ++ hrrq = 0; ++ else { ++ hrrq = atomic_add_return(1, &ioa_cfg->hrrq_index); ++ hrrq = (hrrq % (ioa_cfg->hrrq_num - 1)) + 1; ++ } ++ return hrrq; + } + + /** +@@ -6179,21 +6185,23 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd) + struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; + struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; + u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); +- unsigned long hrrq_flags; ++ unsigned long lock_flags; + + scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->s.ioasa.hdr.residual_data_len)); + + if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) { + scsi_dma_unmap(scsi_cmd); + +- spin_lock_irqsave(ipr_cmd->hrrq->lock, hrrq_flags); ++ spin_lock_irqsave(ipr_cmd->hrrq->lock, lock_flags); + list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); + scsi_cmd->scsi_done(scsi_cmd); +- spin_unlock_irqrestore(ipr_cmd->hrrq->lock, hrrq_flags); ++ spin_unlock_irqrestore(ipr_cmd->hrrq->lock, lock_flags); + } else { +- spin_lock_irqsave(ipr_cmd->hrrq->lock, hrrq_flags); ++ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); ++ spin_lock(&ipr_cmd->hrrq->_lock); + ipr_erp_start(ioa_cfg, ipr_cmd); +- spin_unlock_irqrestore(ipr_cmd->hrrq->lock, hrrq_flags); ++ spin_unlock(&ipr_cmd->hrrq->_lock); ++ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + } + } + +diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h +index 02edae714b0e..694ec20de7c0 100644 +--- a/drivers/scsi/ipr.h ++++ b/drivers/scsi/ipr.h +@@ -1459,6 +1459,7 @@ struct ipr_ioa_cfg { + + #define IPR_NUM_TRACE_INDEX_BITS 8 + #define IPR_NUM_TRACE_ENTRIES (1 << IPR_NUM_TRACE_INDEX_BITS) ++#define IPR_TRACE_INDEX_MASK (IPR_NUM_TRACE_ENTRIES - 1) + #define IPR_TRACE_SIZE (sizeof(struct ipr_trace_entry) * IPR_NUM_TRACE_ENTRIES) + char trace_start[8]; + #define IPR_TRACE_START_LABEL "trace" +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index eb81c98386b9..721d839d6c54 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -1694,6 +1694,9 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) + md->from_user = 0; + } + ++ if (unlikely(iov_count > UIO_MAXIOV)) ++ return -EINVAL; ++ + if (iov_count) { + int len, size = sizeof(struct sg_iovec) * iov_count; + struct iovec *iov; +diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c +index 55ec9b4b97cc..9dbf17671439 100644 +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -3937,7 +3937,13 @@ get_immediate: + } + + transport_err: +- iscsit_take_action_for_connection_exit(conn); ++ /* ++ * Avoid the normal connection failure code-path if this connection ++ * is still within LOGIN mode, and iscsi_np process context is ++ * responsible for cleaning up the early connection failure. ++ */ ++ if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN) ++ iscsit_take_action_for_connection_exit(conn); + out: + return 0; + } +@@ -4023,7 +4029,7 @@ reject: + + int iscsi_target_rx_thread(void *arg) + { +- int ret; ++ int ret, rc; + u8 buffer[ISCSI_HDR_LEN], opcode; + u32 checksum = 0, digest = 0; + struct iscsi_conn *conn = arg; +@@ -4033,10 +4039,16 @@ int iscsi_target_rx_thread(void *arg) + * connection recovery / failure event can be triggered externally. + */ + allow_signal(SIGINT); ++ /* ++ * Wait for iscsi_post_login_handler() to complete before allowing ++ * incoming iscsi/tcp socket I/O, and/or failing the connection. ++ */ ++ rc = wait_for_completion_interruptible(&conn->rx_login_comp); ++ if (rc < 0) ++ return 0; + + if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) { + struct completion comp; +- int rc; + + init_completion(&comp); + rc = wait_for_completion_interruptible(&comp); +diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h +index 825b579ebca8..92abbe2f96ed 100644 +--- a/drivers/target/iscsi/iscsi_target_core.h ++++ b/drivers/target/iscsi/iscsi_target_core.h +@@ -604,6 +604,7 @@ struct iscsi_conn { + int bitmap_id; + int rx_thread_active; + struct task_struct *rx_thread; ++ struct completion rx_login_comp; + int tx_thread_active; + struct task_struct *tx_thread; + /* list_head for session connection list */ +diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c +index 449df092bfa0..01c27aac7bfb 100644 +--- a/drivers/target/iscsi/iscsi_target_login.c ++++ b/drivers/target/iscsi/iscsi_target_login.c +@@ -83,6 +83,7 @@ static struct iscsi_login *iscsi_login_init_conn(struct iscsi_conn *conn) + init_completion(&conn->conn_logout_comp); + init_completion(&conn->rx_half_close_comp); + init_completion(&conn->tx_half_close_comp); ++ init_completion(&conn->rx_login_comp); + spin_lock_init(&conn->cmd_lock); + spin_lock_init(&conn->conn_usage_lock); + spin_lock_init(&conn->immed_queue_lock); +@@ -716,6 +717,7 @@ int iscsit_start_kthreads(struct iscsi_conn *conn) + + return 0; + out_tx: ++ send_sig(SIGINT, conn->tx_thread, 1); + kthread_stop(conn->tx_thread); + conn->tx_thread_active = false; + out_bitmap: +@@ -726,7 +728,7 @@ out_bitmap: + return ret; + } + +-int iscsi_post_login_handler( ++void iscsi_post_login_handler( + struct iscsi_np *np, + struct iscsi_conn *conn, + u8 zero_tsih) +@@ -736,7 +738,6 @@ int iscsi_post_login_handler( + struct se_session *se_sess = sess->se_sess; + struct iscsi_portal_group *tpg = sess->tpg; + struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; +- int rc; + + iscsit_inc_conn_usage_count(conn); + +@@ -777,10 +778,6 @@ int iscsi_post_login_handler( + sess->sess_ops->InitiatorName); + spin_unlock_bh(&sess->conn_lock); + +- rc = iscsit_start_kthreads(conn); +- if (rc) +- return rc; +- + iscsi_post_login_start_timers(conn); + /* + * Determine CPU mask to ensure connection's RX and TX kthreads +@@ -789,15 +786,20 @@ int iscsi_post_login_handler( + iscsit_thread_get_cpumask(conn); + conn->conn_rx_reset_cpumask = 1; + conn->conn_tx_reset_cpumask = 1; +- ++ /* ++ * Wakeup the sleeping iscsi_target_rx_thread() now that ++ * iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state. ++ */ ++ complete(&conn->rx_login_comp); + iscsit_dec_conn_usage_count(conn); ++ + if (stop_timer) { + spin_lock_bh(&se_tpg->session_lock); + iscsit_stop_time2retain_timer(sess); + spin_unlock_bh(&se_tpg->session_lock); + } + iscsit_dec_session_usage_count(sess); +- return 0; ++ return; + } + + iscsi_set_session_parameters(sess->sess_ops, conn->param_list, 1); +@@ -838,10 +840,6 @@ int iscsi_post_login_handler( + " iSCSI Target Portal Group: %hu\n", tpg->nsessions, tpg->tpgt); + spin_unlock_bh(&se_tpg->session_lock); + +- rc = iscsit_start_kthreads(conn); +- if (rc) +- return rc; +- + iscsi_post_login_start_timers(conn); + /* + * Determine CPU mask to ensure connection's RX and TX kthreads +@@ -850,10 +848,12 @@ int iscsi_post_login_handler( + iscsit_thread_get_cpumask(conn); + conn->conn_rx_reset_cpumask = 1; + conn->conn_tx_reset_cpumask = 1; +- ++ /* ++ * Wakeup the sleeping iscsi_target_rx_thread() now that ++ * iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state. ++ */ ++ complete(&conn->rx_login_comp); + iscsit_dec_conn_usage_count(conn); +- +- return 0; + } + + static void iscsi_handle_login_thread_timeout(unsigned long data) +@@ -1418,23 +1418,12 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) + if (ret < 0) + goto new_sess_out; + +- if (!conn->sess) { +- pr_err("struct iscsi_conn session pointer is NULL!\n"); +- goto new_sess_out; +- } +- + iscsi_stop_login_thread_timer(np); + +- if (signal_pending(current)) +- goto new_sess_out; +- + if (ret == 1) { + tpg_np = conn->tpg_np; + +- ret = iscsi_post_login_handler(np, conn, zero_tsih); +- if (ret < 0) +- goto new_sess_out; +- ++ iscsi_post_login_handler(np, conn, zero_tsih); + iscsit_deaccess_np(np, tpg, tpg_np); + } + +diff --git a/drivers/target/iscsi/iscsi_target_login.h b/drivers/target/iscsi/iscsi_target_login.h +index 29d098324b7f..55cbf4533544 100644 +--- a/drivers/target/iscsi/iscsi_target_login.h ++++ b/drivers/target/iscsi/iscsi_target_login.h +@@ -12,7 +12,8 @@ extern int iscsit_accept_np(struct iscsi_np *, struct iscsi_conn *); + extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *); + extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32); + extern void iscsit_free_conn(struct iscsi_np *, struct iscsi_conn *); +-extern int iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8); ++extern int iscsit_start_kthreads(struct iscsi_conn *); ++extern void iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8); + extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *, + bool, bool); + extern int iscsi_target_login_thread(void *); +diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c +index 582ba84075ec..25ad113c5978 100644 +--- a/drivers/target/iscsi/iscsi_target_nego.c ++++ b/drivers/target/iscsi/iscsi_target_nego.c +@@ -17,6 +17,7 @@ + ******************************************************************************/ + + #include ++#include + #include + #include + #include +@@ -361,10 +362,24 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log + ntohl(login_rsp->statsn), login->rsp_length); + + padding = ((-login->rsp_length) & 3); ++ /* ++ * Before sending the last login response containing the transition ++ * bit for full-feature-phase, go ahead and start up TX/RX threads ++ * now to avoid potential resource allocation failures after the ++ * final login response has been sent. ++ */ ++ if (login->login_complete) { ++ int rc = iscsit_start_kthreads(conn); ++ if (rc) { ++ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, ++ ISCSI_LOGIN_STATUS_NO_RESOURCES); ++ return -1; ++ } ++ } + + if (conn->conn_transport->iscsit_put_login_tx(conn, login, + login->rsp_length + padding) < 0) +- return -1; ++ goto err; + + login->rsp_length = 0; + mutex_lock(&sess->cmdsn_mutex); +@@ -373,6 +388,23 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log + mutex_unlock(&sess->cmdsn_mutex); + + return 0; ++ ++err: ++ if (login->login_complete) { ++ if (conn->rx_thread && conn->rx_thread_active) { ++ send_sig(SIGINT, conn->rx_thread, 1); ++ kthread_stop(conn->rx_thread); ++ } ++ if (conn->tx_thread && conn->tx_thread_active) { ++ send_sig(SIGINT, conn->tx_thread, 1); ++ kthread_stop(conn->tx_thread); ++ } ++ spin_lock(&iscsit_global->ts_bitmap_lock); ++ bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id, ++ get_order(1)); ++ spin_unlock(&iscsit_global->ts_bitmap_lock); ++ } ++ return -1; + } + + static void iscsi_target_sk_data_ready(struct sock *sk, int count) +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index bcc43a21fd12..a365e9769fcc 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -86,7 +86,7 @@ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, + return 0; + /* offset in TRBs */ + segment_offset = trb - seg->trbs; +- if (segment_offset > TRBS_PER_SEGMENT) ++ if (segment_offset >= TRBS_PER_SEGMENT) + return 0; + return seg->dma + (segment_offset * sizeof(*trb)); + } +diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c +index 74a9375a9bb5..89c55d4d9e54 100644 +--- a/drivers/usb/serial/sierra.c ++++ b/drivers/usb/serial/sierra.c +@@ -289,6 +289,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68AA, 0xFF, 0xFF, 0xFF), + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, ++ { USB_DEVICE(0x1199, 0x68AB) }, /* Sierra Wireless AR8550 */ + /* AT&T Direct IP LTE modems */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF), + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist +diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c +index 073b4a19a8b0..ff3c98f1ea95 100644 +--- a/drivers/xen/gntdev.c ++++ b/drivers/xen/gntdev.c +@@ -529,12 +529,14 @@ static int gntdev_release(struct inode *inode, struct file *flip) + + pr_debug("priv %p\n", priv); + ++ mutex_lock(&priv->lock); + while (!list_empty(&priv->maps)) { + map = list_entry(priv->maps.next, struct grant_map, next); + list_del(&map->next); + gntdev_put_map(NULL /* already removed */, map); + } + WARN_ON(!list_empty(&priv->freeable_maps)); ++ mutex_unlock(&priv->lock); + + if (use_ptemod) + mmu_notifier_unregister(&priv->mn, priv->mm); +diff --git a/fs/dcache.c b/fs/dcache.c +index 3d2f27b4cd38..df323f809e03 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -244,17 +244,8 @@ static void __d_free(struct rcu_head *head) + kmem_cache_free(dentry_cache, dentry); + } + +-/* +- * no locks, please. +- */ +-static void d_free(struct dentry *dentry) ++static void dentry_free(struct dentry *dentry) + { +- WARN_ON(!hlist_unhashed(&dentry->d_u.d_alias)); +- BUG_ON((int)dentry->d_lockref.count > 0); +- this_cpu_dec(nr_dentry); +- if (dentry->d_op && dentry->d_op->d_release) +- dentry->d_op->d_release(dentry); +- + /* if dentry was never visible to RCU, immediate free is OK */ + if (!(dentry->d_flags & DCACHE_RCUACCESS)) + __d_free(&dentry->d_u.d_rcu); +@@ -402,56 +393,6 @@ static void dentry_lru_add(struct dentry *dentry) + d_lru_add(dentry); + } + +-/* +- * Remove a dentry with references from the LRU. +- * +- * If we are on the shrink list, then we can get to try_prune_one_dentry() and +- * lose our last reference through the parent walk. In this case, we need to +- * remove ourselves from the shrink list, not the LRU. +- */ +-static void dentry_lru_del(struct dentry *dentry) +-{ +- if (dentry->d_flags & DCACHE_LRU_LIST) { +- if (dentry->d_flags & DCACHE_SHRINK_LIST) +- return d_shrink_del(dentry); +- d_lru_del(dentry); +- } +-} +- +-/** +- * d_kill - kill dentry and return parent +- * @dentry: dentry to kill +- * @parent: parent dentry +- * +- * The dentry must already be unhashed and removed from the LRU. +- * +- * If this is the root of the dentry tree, return NULL. +- * +- * dentry->d_lock and parent->d_lock must be held by caller, and are dropped by +- * d_kill. +- */ +-static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) +- __releases(dentry->d_lock) +- __releases(parent->d_lock) +- __releases(dentry->d_inode->i_lock) +-{ +- __list_del_entry(&dentry->d_child); +- /* +- * Inform d_walk() that we are no longer attached to the +- * dentry tree +- */ +- dentry->d_flags |= DCACHE_DENTRY_KILLED; +- if (parent) +- spin_unlock(&parent->d_lock); +- dentry_iput(dentry); +- /* +- * dentry_iput drops the locks, at which point nobody (except +- * transient RCU lookups) can reach this dentry. +- */ +- d_free(dentry); +- return parent; +-} +- + /** + * d_drop - drop a dentry + * @dentry: dentry to drop +@@ -509,7 +450,14 @@ dentry_kill(struct dentry *dentry, int unlock_on_failure) + __releases(dentry->d_lock) + { + struct inode *inode; +- struct dentry *parent; ++ struct dentry *parent = NULL; ++ bool can_free = true; ++ ++ if (unlikely(dentry->d_flags & DCACHE_DENTRY_KILLED)) { ++ can_free = dentry->d_flags & DCACHE_MAY_FREE; ++ spin_unlock(&dentry->d_lock); ++ goto out; ++ } + + inode = dentry->d_inode; + if (inode && !spin_trylock(&inode->i_lock)) { +@@ -520,9 +468,7 @@ relock: + } + return dentry; /* try again with same dentry */ + } +- if (IS_ROOT(dentry)) +- parent = NULL; +- else ++ if (!IS_ROOT(dentry)) + parent = dentry->d_parent; + if (parent && !spin_trylock(&parent->d_lock)) { + if (inode) +@@ -542,10 +488,40 @@ relock: + if ((dentry->d_flags & DCACHE_OP_PRUNE) && !d_unhashed(dentry)) + dentry->d_op->d_prune(dentry); + +- dentry_lru_del(dentry); ++ if (dentry->d_flags & DCACHE_LRU_LIST) { ++ if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) ++ d_lru_del(dentry); ++ } + /* if it was on the hash then remove it */ + __d_drop(dentry); +- return d_kill(dentry, parent); ++ __list_del_entry(&dentry->d_child); ++ /* ++ * Inform d_walk() that we are no longer attached to the ++ * dentry tree ++ */ ++ dentry->d_flags |= DCACHE_DENTRY_KILLED; ++ if (parent) ++ spin_unlock(&parent->d_lock); ++ dentry_iput(dentry); ++ /* ++ * dentry_iput drops the locks, at which point nobody (except ++ * transient RCU lookups) can reach this dentry. ++ */ ++ BUG_ON((int)dentry->d_lockref.count > 0); ++ this_cpu_dec(nr_dentry); ++ if (dentry->d_op && dentry->d_op->d_release) ++ dentry->d_op->d_release(dentry); ++ ++ spin_lock(&dentry->d_lock); ++ if (dentry->d_flags & DCACHE_SHRINK_LIST) { ++ dentry->d_flags |= DCACHE_MAY_FREE; ++ can_free = false; ++ } ++ spin_unlock(&dentry->d_lock); ++out: ++ if (likely(can_free)) ++ dentry_free(dentry); ++ return parent; + } + + /* +@@ -817,65 +793,13 @@ restart: + } + EXPORT_SYMBOL(d_prune_aliases); + +-/* +- * Try to throw away a dentry - free the inode, dput the parent. +- * Requires dentry->d_lock is held, and dentry->d_count == 0. +- * Releases dentry->d_lock. +- * +- * This may fail if locks cannot be acquired no problem, just try again. +- */ +-static struct dentry * try_prune_one_dentry(struct dentry *dentry) +- __releases(dentry->d_lock) +-{ +- struct dentry *parent; +- +- parent = dentry_kill(dentry, 0); +- /* +- * If dentry_kill returns NULL, we have nothing more to do. +- * if it returns the same dentry, trylocks failed. In either +- * case, just loop again. +- * +- * Otherwise, we need to prune ancestors too. This is necessary +- * to prevent quadratic behavior of shrink_dcache_parent(), but +- * is also expected to be beneficial in reducing dentry cache +- * fragmentation. +- */ +- if (!parent) +- return NULL; +- if (parent == dentry) +- return dentry; +- +- /* Prune ancestors. */ +- dentry = parent; +- while (dentry) { +- if (lockref_put_or_lock(&dentry->d_lockref)) +- return NULL; +- dentry = dentry_kill(dentry, 1); +- } +- return NULL; +-} +- + static void shrink_dentry_list(struct list_head *list) + { +- struct dentry *dentry; ++ struct dentry *dentry, *parent; + +- rcu_read_lock(); +- for (;;) { +- dentry = list_entry_rcu(list->prev, struct dentry, d_lru); +- if (&dentry->d_lru == list) +- break; /* empty */ +- +- /* +- * Get the dentry lock, and re-verify that the dentry is +- * this on the shrinking list. If it is, we know that +- * DCACHE_SHRINK_LIST and DCACHE_LRU_LIST are set. +- */ ++ while (!list_empty(list)) { ++ dentry = list_entry(list->prev, struct dentry, d_lru); + spin_lock(&dentry->d_lock); +- if (dentry != list_entry(list->prev, struct dentry, d_lru)) { +- spin_unlock(&dentry->d_lock); +- continue; +- } +- + /* + * The dispose list is isolated and dentries are not accounted + * to the LRU here, so we can simply remove it from the list +@@ -887,30 +811,38 @@ static void shrink_dentry_list(struct list_head *list) + * We found an inuse dentry which was not removed from + * the LRU because of laziness during lookup. Do not free it. + */ +- if (dentry->d_lockref.count) { ++ if ((int)dentry->d_lockref.count > 0) { + spin_unlock(&dentry->d_lock); + continue; + } +- rcu_read_unlock(); + ++ parent = dentry_kill(dentry, 0); + /* +- * If 'try_to_prune()' returns a dentry, it will +- * be the same one we passed in, and d_lock will +- * have been held the whole time, so it will not +- * have been added to any other lists. We failed +- * to get the inode lock. +- * +- * We just add it back to the shrink list. ++ * If dentry_kill returns NULL, we have nothing more to do. + */ +- dentry = try_prune_one_dentry(dentry); ++ if (!parent) ++ continue; + +- rcu_read_lock(); +- if (dentry) { ++ if (unlikely(parent == dentry)) { ++ /* ++ * trylocks have failed and d_lock has been held the ++ * whole time, so it could not have been added to any ++ * other lists. Just add it back to the shrink list. ++ */ + d_shrink_add(dentry, list); + spin_unlock(&dentry->d_lock); ++ continue; + } ++ /* ++ * We need to prune ancestors too. This is necessary to prevent ++ * quadratic behavior of shrink_dcache_parent(), but is also ++ * expected to be beneficial in reducing dentry cache ++ * fragmentation. ++ */ ++ dentry = parent; ++ while (dentry && !lockref_put_or_lock(&dentry->d_lockref)) ++ dentry = dentry_kill(dentry, 1); + } +- rcu_read_unlock(); + } + + static enum lru_status +@@ -1264,34 +1196,23 @@ static enum d_walk_ret select_collect(void *_data, struct dentry *dentry) + if (data->start == dentry) + goto out; + +- /* +- * move only zero ref count dentries to the dispose list. +- * +- * Those which are presently on the shrink list, being processed +- * by shrink_dentry_list(), shouldn't be moved. Otherwise the +- * loop in shrink_dcache_parent() might not make any progress +- * and loop forever. +- */ +- if (dentry->d_lockref.count) { +- dentry_lru_del(dentry); +- } else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) { +- /* +- * We can't use d_lru_shrink_move() because we +- * need to get the global LRU lock and do the +- * LRU accounting. +- */ +- d_lru_del(dentry); +- d_shrink_add(dentry, &data->dispose); ++ if (dentry->d_flags & DCACHE_SHRINK_LIST) { + data->found++; +- ret = D_WALK_NORETRY; ++ } else { ++ if (dentry->d_flags & DCACHE_LRU_LIST) ++ d_lru_del(dentry); ++ if (!dentry->d_lockref.count) { ++ d_shrink_add(dentry, &data->dispose); ++ data->found++; ++ } + } + /* + * We can return to the caller if we have found some (this + * ensures forward progress). We'll be coming back to find + * the rest. + */ +- if (data->found && need_resched()) +- ret = D_WALK_QUIT; ++ if (!list_empty(&data->dispose)) ++ ret = need_resched() ? D_WALK_QUIT : D_WALK_NORETRY; + out: + return ret; + } +@@ -1321,45 +1242,35 @@ void shrink_dcache_parent(struct dentry *parent) + } + EXPORT_SYMBOL(shrink_dcache_parent); + +-static enum d_walk_ret umount_collect(void *_data, struct dentry *dentry) ++static enum d_walk_ret umount_check(void *_data, struct dentry *dentry) + { +- struct select_data *data = _data; +- enum d_walk_ret ret = D_WALK_CONTINUE; ++ /* it has busy descendents; complain about those instead */ ++ if (!list_empty(&dentry->d_subdirs)) ++ return D_WALK_CONTINUE; + +- if (dentry->d_lockref.count) { +- dentry_lru_del(dentry); +- if (likely(!list_empty(&dentry->d_subdirs))) +- goto out; +- if (dentry == data->start && dentry->d_lockref.count == 1) +- goto out; +- printk(KERN_ERR +- "BUG: Dentry %p{i=%lx,n=%s}" +- " still in use (%d)" +- " [unmount of %s %s]\n", ++ /* root with refcount 1 is fine */ ++ if (dentry == _data && dentry->d_lockref.count == 1) ++ return D_WALK_CONTINUE; ++ ++ printk(KERN_ERR "BUG: Dentry %p{i=%lx,n=%pd} " ++ " still in use (%d) [unmount of %s %s]\n", + dentry, + dentry->d_inode ? + dentry->d_inode->i_ino : 0UL, +- dentry->d_name.name, ++ dentry, + dentry->d_lockref.count, + dentry->d_sb->s_type->name, + dentry->d_sb->s_id); +- BUG(); +- } else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) { +- /* +- * We can't use d_lru_shrink_move() because we +- * need to get the global LRU lock and do the +- * LRU accounting. +- */ +- if (dentry->d_flags & DCACHE_LRU_LIST) +- d_lru_del(dentry); +- d_shrink_add(dentry, &data->dispose); +- data->found++; +- ret = D_WALK_NORETRY; +- } +-out: +- if (data->found && need_resched()) +- ret = D_WALK_QUIT; +- return ret; ++ WARN_ON(1); ++ return D_WALK_CONTINUE; ++} ++ ++static void do_one_tree(struct dentry *dentry) ++{ ++ shrink_dcache_parent(dentry); ++ d_walk(dentry, dentry, umount_check, NULL); ++ d_drop(dentry); ++ dput(dentry); + } + + /* +@@ -1369,40 +1280,15 @@ void shrink_dcache_for_umount(struct super_block *sb) + { + struct dentry *dentry; + +- if (down_read_trylock(&sb->s_umount)) +- BUG(); ++ WARN(down_read_trylock(&sb->s_umount), "s_umount should've been locked"); + + dentry = sb->s_root; + sb->s_root = NULL; +- for (;;) { +- struct select_data data; +- +- INIT_LIST_HEAD(&data.dispose); +- data.start = dentry; +- data.found = 0; +- +- d_walk(dentry, &data, umount_collect, NULL); +- if (!data.found) +- break; +- +- shrink_dentry_list(&data.dispose); +- cond_resched(); +- } +- d_drop(dentry); +- dput(dentry); ++ do_one_tree(dentry); + + while (!hlist_bl_empty(&sb->s_anon)) { +- struct select_data data; +- dentry = hlist_bl_entry(hlist_bl_first(&sb->s_anon), struct dentry, d_hash); +- +- INIT_LIST_HEAD(&data.dispose); +- data.start = NULL; +- data.found = 0; +- +- d_walk(dentry, &data, umount_collect, NULL); +- if (data.found) +- shrink_dentry_list(&data.dispose); +- cond_resched(); ++ dentry = dget(hlist_bl_entry(hlist_bl_first(&sb->s_anon), struct dentry, d_hash)); ++ do_one_tree(dentry); + } + } + +diff --git a/fs/namei.c b/fs/namei.c +index ccb8000f3459..c6fa07942b2a 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -3171,7 +3171,7 @@ static struct file *path_openat(int dfd, struct filename *pathname, + + if (unlikely(file->f_flags & __O_TMPFILE)) { + error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened); +- goto out; ++ goto out2; + } + + error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base); +@@ -3209,6 +3209,7 @@ out: + path_put(&nd->root); + if (base) + fput(base); ++out2: + if (!(opened & FILE_OPENED)) { + BUG_ON(!error); + put_filp(file); +diff --git a/fs/notify/mark.c b/fs/notify/mark.c +index 923fe4a5f503..6bffc3331df6 100644 +--- a/fs/notify/mark.c ++++ b/fs/notify/mark.c +@@ -293,16 +293,36 @@ void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group, + unsigned int flags) + { + struct fsnotify_mark *lmark, *mark; ++ LIST_HEAD(to_free); + ++ /* ++ * We have to be really careful here. Anytime we drop mark_mutex, e.g. ++ * fsnotify_clear_marks_by_inode() can come and free marks. Even in our ++ * to_free list so we have to use mark_mutex even when accessing that ++ * list. And freeing mark requires us to drop mark_mutex. So we can ++ * reliably free only the first mark in the list. That's why we first ++ * move marks to free to to_free list in one go and then free marks in ++ * to_free list one by one. ++ */ + mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); + list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) { +- if (mark->flags & flags) { +- fsnotify_get_mark(mark); +- fsnotify_destroy_mark_locked(mark, group); +- fsnotify_put_mark(mark); +- } ++ if (mark->flags & flags) ++ list_move(&mark->g_list, &to_free); + } + mutex_unlock(&group->mark_mutex); ++ ++ while (1) { ++ mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); ++ if (list_empty(&to_free)) { ++ mutex_unlock(&group->mark_mutex); ++ break; ++ } ++ mark = list_first_entry(&to_free, struct fsnotify_mark, g_list); ++ fsnotify_get_mark(mark); ++ fsnotify_destroy_mark_locked(mark, group); ++ mutex_unlock(&group->mark_mutex); ++ fsnotify_put_mark(mark); ++ } + } + + /* +diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c +index 19986959d149..fa742590bc3d 100644 +--- a/fs/ocfs2/dlmglue.c ++++ b/fs/ocfs2/dlmglue.c +@@ -3973,9 +3973,13 @@ static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb) + osb->dc_work_sequence = osb->dc_wake_sequence; + + processed = osb->blocked_lock_count; +- while (processed) { +- BUG_ON(list_empty(&osb->blocked_lock_list)); +- ++ /* ++ * blocked lock processing in this loop might call iput which can ++ * remove items off osb->blocked_lock_list. Downconvert up to ++ * 'processed' number of locks, but stop short if we had some ++ * removed in ocfs2_mark_lockres_freeing when downconverting. ++ */ ++ while (processed && !list_empty(&osb->blocked_lock_list)) { + lockres = list_entry(osb->blocked_lock_list.next, + struct ocfs2_lock_res, l_blocked_list); + list_del_init(&lockres->l_blocked_list); +diff --git a/fs/signalfd.c b/fs/signalfd.c +index 424b7b65321f..148f8e7af882 100644 +--- a/fs/signalfd.c ++++ b/fs/signalfd.c +@@ -121,8 +121,9 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, + * Other callers might not initialize the si_lsb field, + * so check explicitly for the right codes here. + */ +- if (kinfo->si_code == BUS_MCEERR_AR || +- kinfo->si_code == BUS_MCEERR_AO) ++ if (kinfo->si_signo == SIGBUS && ++ (kinfo->si_code == BUS_MCEERR_AR || ++ kinfo->si_code == BUS_MCEERR_AO)) + err |= __put_user((short) kinfo->si_addr_lsb, + &uinfo->ssi_addr_lsb); + #endif +diff --git a/include/linux/dcache.h b/include/linux/dcache.h +index 0f0eb1c1e676..2a23ecb4f71c 100644 +--- a/include/linux/dcache.h ++++ b/include/linux/dcache.h +@@ -221,6 +221,8 @@ struct dentry_operations { + #define DCACHE_SYMLINK_TYPE 0x00300000 /* Symlink */ + #define DCACHE_FILE_TYPE 0x00400000 /* Other file type */ + ++#define DCACHE_MAY_FREE 0x00800000 ++ + extern seqlock_t rename_lock; + + static inline int dname_external(const struct dentry *dentry) +diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h +index 30db069bce62..788c5aa055d7 100644 +--- a/include/uapi/linux/pci_regs.h ++++ b/include/uapi/linux/pci_regs.h +@@ -319,6 +319,7 @@ + #define PCI_MSIX_PBA 8 /* Pending Bit Array offset */ + #define PCI_MSIX_PBA_BIR 0x00000007 /* BAR index */ + #define PCI_MSIX_PBA_OFFSET 0xfffffff8 /* Offset into specified BAR */ ++#define PCI_MSIX_FLAGS_BIRMASK PCI_MSIX_PBA_BIR /* deprecated */ + #define PCI_CAP_MSIX_SIZEOF 12 /* size of MSIX registers */ + + /* MSI-X Table entry format */ +diff --git a/ipc/mqueue.c b/ipc/mqueue.c +index c3b31179122c..9699d3f7989c 100644 +--- a/ipc/mqueue.c ++++ b/ipc/mqueue.c +@@ -143,7 +143,6 @@ static int msg_insert(struct msg_msg *msg, struct mqueue_inode_info *info) + if (!leaf) + return -ENOMEM; + INIT_LIST_HEAD(&leaf->msg_list); +- info->qsize += sizeof(*leaf); + } + leaf->priority = msg->m_type; + rb_link_node(&leaf->rb_node, parent, p); +@@ -188,7 +187,6 @@ try_again: + "lazy leaf delete!\n"); + rb_erase(&leaf->rb_node, &info->msg_tree); + if (info->node_cache) { +- info->qsize -= sizeof(*leaf); + kfree(leaf); + } else { + info->node_cache = leaf; +@@ -201,7 +199,6 @@ try_again: + if (list_empty(&leaf->msg_list)) { + rb_erase(&leaf->rb_node, &info->msg_tree); + if (info->node_cache) { +- info->qsize -= sizeof(*leaf); + kfree(leaf); + } else { + info->node_cache = leaf; +@@ -1026,7 +1023,6 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr, + /* Save our speculative allocation into the cache */ + INIT_LIST_HEAD(&new_leaf->msg_list); + info->node_cache = new_leaf; +- info->qsize += sizeof(*new_leaf); + new_leaf = NULL; + } else { + kfree(new_leaf); +@@ -1133,7 +1129,6 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr, + /* Save our speculative allocation into the cache */ + INIT_LIST_HEAD(&new_leaf->msg_list); + info->node_cache = new_leaf; +- info->qsize += sizeof(*new_leaf); + } else { + kfree(new_leaf); + } +diff --git a/kernel/signal.c b/kernel/signal.c +index 52f881db1ca0..15c22ee11156 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -2768,7 +2768,8 @@ int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from) + * Other callers might not initialize the si_lsb field, + * so check explicitly for the right codes here. + */ +- if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO) ++ if (from->si_signo == SIGBUS && ++ (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)) + err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb); + #endif + break; +@@ -3035,7 +3036,7 @@ COMPAT_SYSCALL_DEFINE3(rt_sigqueueinfo, + int, sig, + struct compat_siginfo __user *, uinfo) + { +- siginfo_t info; ++ siginfo_t info = {}; + int ret = copy_siginfo_from_user32(&info, uinfo); + if (unlikely(ret)) + return ret; +@@ -3081,7 +3082,7 @@ COMPAT_SYSCALL_DEFINE4(rt_tgsigqueueinfo, + int, sig, + struct compat_siginfo __user *, uinfo) + { +- siginfo_t info; ++ siginfo_t info = {}; + + if (copy_siginfo_from_user32(&info, uinfo)) + return -EFAULT; +diff --git a/mm/vmscan.c b/mm/vmscan.c +index b850ced69ed6..88edf53748ee 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -871,21 +871,17 @@ static unsigned long shrink_page_list(struct list_head *page_list, + * + * 2) Global reclaim encounters a page, memcg encounters a + * page that is not marked for immediate reclaim or +- * the caller does not have __GFP_IO. In this case mark ++ * the caller does not have __GFP_FS (or __GFP_IO if it's ++ * simply going to swap, not to fs). In this case mark + * the page for immediate reclaim and continue scanning. + * +- * __GFP_IO is checked because a loop driver thread might ++ * Require may_enter_fs because we would wait on fs, which ++ * may not have submitted IO yet. And the loop driver might + * enter reclaim, and deadlock if it waits on a page for + * which it is needed to do the write (loop masks off + * __GFP_IO|__GFP_FS for this reason); but more thought + * would probably show more reasons. + * +- * Don't require __GFP_FS, since we're not going into the +- * FS, just waiting on its writeback completion. Worryingly, +- * ext4 gfs2 and xfs allocate pages with +- * grab_cache_page_write_begin(,,AOP_FLAG_NOFS), so testing +- * may_enter_fs here is liable to OOM on them. +- * + * 3) memcg encounters a page that is not already marked + * PageReclaim. memcg does not have any dirty pages + * throttling so we could easily OOM just because too many +@@ -902,7 +898,7 @@ static unsigned long shrink_page_list(struct list_head *page_list, + + /* Case 2 above */ + } else if (global_reclaim(sc) || +- !PageReclaim(page) || !(sc->gfp_mask & __GFP_IO)) { ++ !PageReclaim(page) || !may_enter_fs) { + /* + * This is slightly racy - end_page_writeback() + * might have just cleared PageReclaim, then +diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c +index 085c4964be99..9d8e420a80d9 100644 +--- a/security/integrity/ima/ima_policy.c ++++ b/security/integrity/ima/ima_policy.c +@@ -27,6 +27,8 @@ + #define IMA_UID 0x0008 + #define IMA_FOWNER 0x0010 + #define IMA_FSUUID 0x0020 ++#define IMA_INMASK 0x0040 ++#define IMA_EUID 0x0080 + + #define UNKNOWN 0 + #define MEASURE 0x0001 /* same as IMA_MEASURE */ +@@ -171,6 +173,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule, + return false; + if ((rule->flags & IMA_MASK) && rule->mask != mask) + return false; ++ if ((rule->flags & IMA_INMASK) && ++ (!(rule->mask & mask) && func != POST_SETATTR)) ++ return false; + if ((rule->flags & IMA_FSMAGIC) + && rule->fsmagic != inode->i_sb->s_magic) + return false; +@@ -179,6 +184,16 @@ static bool ima_match_rules(struct ima_rule_entry *rule, + return false; + if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid)) + return false; ++ if (rule->flags & IMA_EUID) { ++ if (has_capability_noaudit(current, CAP_SETUID)) { ++ if (!uid_eq(rule->uid, cred->euid) ++ && !uid_eq(rule->uid, cred->suid) ++ && !uid_eq(rule->uid, cred->uid)) ++ return false; ++ } else if (!uid_eq(rule->uid, cred->euid)) ++ return false; ++ } ++ + if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid)) + return false; + for (i = 0; i < MAX_LSM_RULES; i++) { +@@ -350,7 +365,8 @@ enum { + Opt_audit, + Opt_obj_user, Opt_obj_role, Opt_obj_type, + Opt_subj_user, Opt_subj_role, Opt_subj_type, +- Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner, ++ Opt_func, Opt_mask, Opt_fsmagic, ++ Opt_uid, Opt_euid, Opt_fowner, + Opt_appraise_type, Opt_fsuuid, Opt_permit_directio + }; + +@@ -371,6 +387,7 @@ static match_table_t policy_tokens = { + {Opt_fsmagic, "fsmagic=%s"}, + {Opt_fsuuid, "fsuuid=%s"}, + {Opt_uid, "uid=%s"}, ++ {Opt_euid, "euid=%s"}, + {Opt_fowner, "fowner=%s"}, + {Opt_appraise_type, "appraise_type=%s"}, + {Opt_permit_directio, "permit_directio"}, +@@ -412,6 +429,7 @@ static void ima_log_string(struct audit_buffer *ab, char *key, char *value) + static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) + { + struct audit_buffer *ab; ++ char *from; + char *p; + int result = 0; + +@@ -500,18 +518,23 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) + if (entry->mask) + result = -EINVAL; + +- if ((strcmp(args[0].from, "MAY_EXEC")) == 0) ++ from = args[0].from; ++ if (*from == '^') ++ from++; ++ ++ if ((strcmp(from, "MAY_EXEC")) == 0) + entry->mask = MAY_EXEC; +- else if (strcmp(args[0].from, "MAY_WRITE") == 0) ++ else if (strcmp(from, "MAY_WRITE") == 0) + entry->mask = MAY_WRITE; +- else if (strcmp(args[0].from, "MAY_READ") == 0) ++ else if (strcmp(from, "MAY_READ") == 0) + entry->mask = MAY_READ; +- else if (strcmp(args[0].from, "MAY_APPEND") == 0) ++ else if (strcmp(from, "MAY_APPEND") == 0) + entry->mask = MAY_APPEND; + else + result = -EINVAL; + if (!result) +- entry->flags |= IMA_MASK; ++ entry->flags |= (*args[0].from == '^') ++ ? IMA_INMASK : IMA_MASK; + break; + case Opt_fsmagic: + ima_log_string(ab, "fsmagic", args[0].from); +@@ -542,6 +565,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) + break; + case Opt_uid: + ima_log_string(ab, "uid", args[0].from); ++ case Opt_euid: ++ if (token == Opt_euid) ++ ima_log_string(ab, "euid", args[0].from); + + if (uid_valid(entry->uid)) { + result = -EINVAL; +@@ -550,11 +576,14 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) + + result = strict_strtoul(args[0].from, 10, &lnum); + if (!result) { +- entry->uid = make_kuid(current_user_ns(), (uid_t)lnum); +- if (!uid_valid(entry->uid) || (((uid_t)lnum) != lnum)) ++ entry->uid = make_kuid(current_user_ns(), ++ (uid_t) lnum); ++ if (!uid_valid(entry->uid) || ++ (uid_t)lnum != lnum) + result = -EINVAL; + else +- entry->flags |= IMA_UID; ++ entry->flags |= (token == Opt_uid) ++ ? IMA_UID : IMA_EUID; + } + break; + case Opt_fowner: +diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c +index 51e208022cc8..7b0aac9d27ca 100644 +--- a/sound/pci/hda/patch_cirrus.c ++++ b/sound/pci/hda/patch_cirrus.c +@@ -1002,9 +1002,7 @@ static void cs4210_spdif_automute(struct hda_codec *codec, + + spec->spdif_present = spdif_present; + /* SPDIF TX on/off */ +- if (spdif_present) +- snd_hda_set_pin_ctl(codec, spdif_pin, +- spdif_present ? PIN_OUT : 0); ++ snd_hda_set_pin_ctl(codec, spdif_pin, spdif_present ? PIN_OUT : 0); + + cs_automute(codec); + } +diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c +index 651e2fe2c31f..dfa9755da118 100644 +--- a/sound/soc/codecs/pcm1681.c ++++ b/sound/soc/codecs/pcm1681.c +@@ -102,7 +102,7 @@ static int pcm1681_set_deemph(struct snd_soc_codec *codec) + + if (val != -1) { + regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL, +- PCM1681_DEEMPH_RATE_MASK, val); ++ PCM1681_DEEMPH_RATE_MASK, val << 3); + enable = 1; + } else + enable = 0; diff --git a/patch/kernel/cubox-default/patch-3.14.51-52.patch b/patch/kernel/cubox-default/patch-3.14.51-52.patch new file mode 100644 index 000000000..1af148389 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.51-52.patch @@ -0,0 +1,568 @@ +diff --git a/Makefile b/Makefile +index 83275d8ed880..3a5d4316c4c7 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 51 ++SUBLEVEL = 52 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c +index 81a02a8762b0..86825f8883de 100644 +--- a/arch/arm64/kvm/inject_fault.c ++++ b/arch/arm64/kvm/inject_fault.c +@@ -168,8 +168,8 @@ void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr) + { + if (!(vcpu->arch.hcr_el2 & HCR_RW)) + inject_abt32(vcpu, false, addr); +- +- inject_abt64(vcpu, false, addr); ++ else ++ inject_abt64(vcpu, false, addr); + } + + /** +@@ -184,8 +184,8 @@ void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr) + { + if (!(vcpu->arch.hcr_el2 & HCR_RW)) + inject_abt32(vcpu, true, addr); +- +- inject_abt64(vcpu, true, addr); ++ else ++ inject_abt64(vcpu, true, addr); + } + + /** +@@ -198,6 +198,6 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu) + { + if (!(vcpu->arch.hcr_el2 & HCR_RW)) + inject_undef32(vcpu); +- +- inject_undef64(vcpu); ++ else ++ inject_undef64(vcpu); + } +diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c +index 8ed6cb1a900f..8f7ffffc63e9 100644 +--- a/arch/arm64/mm/mmap.c ++++ b/arch/arm64/mm/mmap.c +@@ -47,22 +47,14 @@ static int mmap_is_legacy(void) + return sysctl_legacy_va_layout; + } + +-/* +- * Since get_random_int() returns the same value within a 1 jiffy window, we +- * will almost always get the same randomisation for the stack and mmap +- * region. This will mean the relative distance between stack and mmap will be +- * the same. +- * +- * To avoid this we can shift the randomness by 1 bit. +- */ + static unsigned long mmap_rnd(void) + { + unsigned long rnd = 0; + + if (current->flags & PF_RANDOMIZE) +- rnd = (long)get_random_int() & (STACK_RND_MASK >> 1); ++ rnd = (long)get_random_int() & STACK_RND_MASK; + +- return rnd << (PAGE_SHIFT + 1); ++ return rnd << PAGE_SHIFT; + } + + static unsigned long mmap_base(void) +diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c +index 2b946bc4212d..f3f71369adc7 100644 +--- a/drivers/base/regmap/regcache-rbtree.c ++++ b/drivers/base/regmap/regcache-rbtree.c +@@ -302,11 +302,20 @@ static int regcache_rbtree_insert_to_block(struct regmap *map, + if (!blk) + return -ENOMEM; + +- present = krealloc(rbnode->cache_present, +- BITS_TO_LONGS(blklen) * sizeof(*present), GFP_KERNEL); +- if (!present) { +- kfree(blk); +- return -ENOMEM; ++ if (BITS_TO_LONGS(blklen) > BITS_TO_LONGS(rbnode->blklen)) { ++ present = krealloc(rbnode->cache_present, ++ BITS_TO_LONGS(blklen) * sizeof(*present), ++ GFP_KERNEL); ++ if (!present) { ++ kfree(blk); ++ return -ENOMEM; ++ } ++ ++ memset(present + BITS_TO_LONGS(rbnode->blklen), 0, ++ (BITS_TO_LONGS(blklen) - BITS_TO_LONGS(rbnode->blklen)) ++ * sizeof(*present)); ++ } else { ++ present = rbnode->cache_present; + } + + /* insert the register value in the correct place in the rbnode block */ +diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c +index efe1b4761735..e88556ac8318 100644 +--- a/drivers/block/xen-blkfront.c ++++ b/drivers/block/xen-blkfront.c +@@ -1093,8 +1093,10 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info, + * Add the used indirect page back to the list of + * available pages for indirect grefs. + */ +- indirect_page = pfn_to_page(s->indirect_grants[i]->pfn); +- list_add(&indirect_page->lru, &info->indirect_pages); ++ if (!info->feature_persistent) { ++ indirect_page = pfn_to_page(s->indirect_grants[i]->pfn); ++ list_add(&indirect_page->lru, &info->indirect_pages); ++ } + s->indirect_grants[i]->gref = GRANT_INVALID_REF; + list_add_tail(&s->indirect_grants[i]->node, &info->grants); + } +diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c +index d97a03dbf42c..1489927bdda1 100644 +--- a/drivers/crypto/caam/caamhash.c ++++ b/drivers/crypto/caam/caamhash.c +@@ -900,13 +900,14 @@ static int ahash_final_ctx(struct ahash_request *req) + state->buflen_1; + u32 *sh_desc = ctx->sh_desc_fin, *desc; + dma_addr_t ptr = ctx->sh_desc_fin_dma; +- int sec4_sg_bytes; ++ int sec4_sg_bytes, sec4_sg_src_index; + int digestsize = crypto_ahash_digestsize(ahash); + struct ahash_edesc *edesc; + int ret = 0; + int sh_len; + +- sec4_sg_bytes = (1 + (buflen ? 1 : 0)) * sizeof(struct sec4_sg_entry); ++ sec4_sg_src_index = 1 + (buflen ? 1 : 0); ++ sec4_sg_bytes = sec4_sg_src_index * sizeof(struct sec4_sg_entry); + + /* allocate space for base edesc and hw desc commands, link tables */ + edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN + +@@ -933,7 +934,7 @@ static int ahash_final_ctx(struct ahash_request *req) + state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, + buf, state->buf_dma, buflen, + last_buflen); +- (edesc->sec4_sg + sec4_sg_bytes - 1)->len |= SEC4_SG_LEN_FIN; ++ (edesc->sec4_sg + sec4_sg_src_index - 1)->len |= SEC4_SG_LEN_FIN; + + append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + buflen, + LDST_SGF); +diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c +index ef6b7e08f485..5c361f3c66aa 100644 +--- a/drivers/edac/ppc4xx_edac.c ++++ b/drivers/edac/ppc4xx_edac.c +@@ -921,7 +921,7 @@ static int ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) + */ + + for (row = 0; row < mci->nr_csrows; row++) { +- struct csrow_info *csi = &mci->csrows[row]; ++ struct csrow_info *csi = mci->csrows[row]; + + /* + * Get the configuration settings for this +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +index a3480c13eb1b..9fe10d1ad2e4 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +@@ -2475,7 +2475,7 @@ int vmw_execbuf_process(struct drm_file *file_priv, + + ret = vmw_resources_validate(sw_context); + if (unlikely(ret != 0)) +- goto out_err; ++ goto out_err_nores; + + if (throttle_us) { + ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue, +@@ -2511,6 +2511,7 @@ int vmw_execbuf_process(struct drm_file *file_priv, + vmw_resource_relocations_free(&sw_context->res_relocations); + + vmw_fifo_commit(dev_priv, command_size); ++ mutex_unlock(&dev_priv->binding_mutex); + + vmw_query_bo_switch_commit(dev_priv, sw_context); + ret = vmw_execbuf_fence_commands(file_priv, dev_priv, +@@ -2526,7 +2527,6 @@ int vmw_execbuf_process(struct drm_file *file_priv, + DRM_ERROR("Fence submission error. Syncing.\n"); + + vmw_resource_list_unreserve(&sw_context->resource_list, false); +- mutex_unlock(&dev_priv->binding_mutex); + + ttm_eu_fence_buffer_objects(&ticket, &sw_context->validate_nodes, + (void *) fence); +diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c +index e9d33ad59df5..3412b86e79fd 100644 +--- a/drivers/md/dm-thin-metadata.c ++++ b/drivers/md/dm-thin-metadata.c +@@ -1295,8 +1295,8 @@ static int __release_metadata_snap(struct dm_pool_metadata *pmd) + return r; + + disk_super = dm_block_data(copy); +- dm_sm_dec_block(pmd->metadata_sm, le64_to_cpu(disk_super->data_mapping_root)); +- dm_sm_dec_block(pmd->metadata_sm, le64_to_cpu(disk_super->device_details_root)); ++ dm_btree_del(&pmd->info, le64_to_cpu(disk_super->data_mapping_root)); ++ dm_btree_del(&pmd->details_info, le64_to_cpu(disk_super->device_details_root)); + dm_sm_dec_block(pmd->metadata_sm, held_root); + + return dm_tm_unlock(pmd->tm, copy); +diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c +index 1b3a09473452..30f9ef0c0d4f 100644 +--- a/drivers/scsi/libfc/fc_exch.c ++++ b/drivers/scsi/libfc/fc_exch.c +@@ -733,8 +733,6 @@ static bool fc_invoke_resp(struct fc_exch *ep, struct fc_seq *sp, + if (resp) { + resp(sp, fp, arg); + res = true; +- } else if (!IS_ERR(fp)) { +- fc_frame_free(fp); + } + + spin_lock_bh(&ep->ex_lock); +@@ -1596,7 +1594,8 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) + * If new exch resp handler is valid then call that + * first. + */ +- fc_invoke_resp(ep, sp, fp); ++ if (!fc_invoke_resp(ep, sp, fp)) ++ fc_frame_free(fp); + + fc_exch_release(ep); + return; +@@ -1695,7 +1694,8 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) + fc_exch_hold(ep); + if (!rc) + fc_exch_delete(ep); +- fc_invoke_resp(ep, sp, fp); ++ if (!fc_invoke_resp(ep, sp, fp)) ++ fc_frame_free(fp); + if (has_rec) + fc_exch_timer_set(ep, ep->r_a_tov); + fc_exch_release(ep); +diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c +index 1d7e76e8b447..ae6fc1a94568 100644 +--- a/drivers/scsi/libfc/fc_fcp.c ++++ b/drivers/scsi/libfc/fc_fcp.c +@@ -1039,11 +1039,26 @@ restart: + fc_fcp_pkt_hold(fsp); + spin_unlock_irqrestore(&si->scsi_queue_lock, flags); + +- if (!fc_fcp_lock_pkt(fsp)) { ++ spin_lock_bh(&fsp->scsi_pkt_lock); ++ if (!(fsp->state & FC_SRB_COMPL)) { ++ fsp->state |= FC_SRB_COMPL; ++ /* ++ * TODO: dropping scsi_pkt_lock and then reacquiring ++ * again around fc_fcp_cleanup_cmd() is required, ++ * since fc_fcp_cleanup_cmd() calls into ++ * fc_seq_set_resp() and that func preempts cpu using ++ * schedule. May be schedule and related code should be ++ * removed instead of unlocking here to avoid scheduling ++ * while atomic bug. ++ */ ++ spin_unlock_bh(&fsp->scsi_pkt_lock); ++ + fc_fcp_cleanup_cmd(fsp, error); ++ ++ spin_lock_bh(&fsp->scsi_pkt_lock); + fc_io_compl(fsp); +- fc_fcp_unlock_pkt(fsp); + } ++ spin_unlock_bh(&fsp->scsi_pkt_lock); + + fc_fcp_pkt_release(fsp); + spin_lock_irqsave(&si->scsi_queue_lock, flags); +diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c +index 001e9ceda4c3..a59be67b92d5 100644 +--- a/drivers/scsi/scsi_pm.c ++++ b/drivers/scsi/scsi_pm.c +@@ -149,15 +149,15 @@ static int sdev_runtime_suspend(struct device *dev) + { + const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; + struct scsi_device *sdev = to_scsi_device(dev); +- int err; ++ int err = 0; + +- err = blk_pre_runtime_suspend(sdev->request_queue); +- if (err) +- return err; +- if (pm && pm->runtime_suspend) ++ if (pm && pm->runtime_suspend) { ++ err = blk_pre_runtime_suspend(sdev->request_queue); ++ if (err) ++ return err; + err = pm->runtime_suspend(dev); +- blk_post_runtime_suspend(sdev->request_queue, err); +- ++ blk_post_runtime_suspend(sdev->request_queue, err); ++ } + return err; + } + +@@ -180,11 +180,11 @@ static int sdev_runtime_resume(struct device *dev) + const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; + int err = 0; + +- blk_pre_runtime_resume(sdev->request_queue); +- if (pm && pm->runtime_resume) ++ if (pm && pm->runtime_resume) { ++ blk_pre_runtime_resume(sdev->request_queue); + err = pm->runtime_resume(dev); +- blk_post_runtime_resume(sdev->request_queue, err); +- ++ blk_post_runtime_resume(sdev->request_queue, err); ++ } + return err; + } + +diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h +index bb5367d288fb..7e9a0a6c655b 100644 +--- a/include/drm/drm_pciids.h ++++ b/include/drm/drm_pciids.h +@@ -172,6 +172,7 @@ + {0x1002, 0x6610, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6611, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6613, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6617, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6620, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6623, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ +diff --git a/ipc/sem.c b/ipc/sem.c +index bee555417312..e53c96f7db42 100644 +--- a/ipc/sem.c ++++ b/ipc/sem.c +@@ -253,6 +253,16 @@ static void sem_rcu_free(struct rcu_head *head) + } + + /* ++ * spin_unlock_wait() and !spin_is_locked() are not memory barriers, they ++ * are only control barriers. ++ * The code must pair with spin_unlock(&sem->lock) or ++ * spin_unlock(&sem_perm.lock), thus just the control barrier is insufficient. ++ * ++ * smp_rmb() is sufficient, as writes cannot pass the control barrier. ++ */ ++#define ipc_smp_acquire__after_spin_is_unlocked() smp_rmb() ++ ++/* + * Wait until all currently ongoing simple ops have completed. + * Caller must own sem_perm.lock. + * New simple ops cannot start, because simple ops first check +@@ -275,6 +285,7 @@ static void sem_wait_array(struct sem_array *sma) + sem = sma->sem_base + i; + spin_unlock_wait(&sem->lock); + } ++ ipc_smp_acquire__after_spin_is_unlocked(); + } + + /* +@@ -326,8 +337,13 @@ static inline int sem_lock(struct sem_array *sma, struct sembuf *sops, + + /* Then check that the global lock is free */ + if (!spin_is_locked(&sma->sem_perm.lock)) { +- /* spin_is_locked() is not a memory barrier */ +- smp_mb(); ++ /* ++ * We need a memory barrier with acquire semantics, ++ * otherwise we can race with another thread that does: ++ * complex_count++; ++ * spin_unlock(sem_perm.lock); ++ */ ++ ipc_smp_acquire__after_spin_is_unlocked(); + + /* Now repeat the test of complex_count: + * It can't change anymore until we drop sem->lock. +@@ -2055,17 +2071,28 @@ void exit_sem(struct task_struct *tsk) + rcu_read_lock(); + un = list_entry_rcu(ulp->list_proc.next, + struct sem_undo, list_proc); +- if (&un->list_proc == &ulp->list_proc) +- semid = -1; +- else +- semid = un->semid; ++ if (&un->list_proc == &ulp->list_proc) { ++ /* ++ * We must wait for freeary() before freeing this ulp, ++ * in case we raced with last sem_undo. There is a small ++ * possibility where we exit while freeary() didn't ++ * finish unlocking sem_undo_list. ++ */ ++ spin_unlock_wait(&ulp->lock); ++ rcu_read_unlock(); ++ break; ++ } ++ spin_lock(&ulp->lock); ++ semid = un->semid; ++ spin_unlock(&ulp->lock); + ++ /* exit_sem raced with IPC_RMID, nothing to do */ + if (semid == -1) { + rcu_read_unlock(); +- break; ++ continue; + } + +- sma = sem_obtain_object_check(tsk->nsproxy->ipc_ns, un->semid); ++ sma = sem_obtain_object_check(tsk->nsproxy->ipc_ns, semid); + /* exit_sem raced with IPC_RMID, nothing to do */ + if (IS_ERR(sma)) { + rcu_read_unlock(); +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 60146febb9b3..3bf20e36a8e7 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -3562,28 +3562,21 @@ static void perf_event_for_each(struct perf_event *event, + mutex_unlock(&ctx->mutex); + } + +-static int perf_event_period(struct perf_event *event, u64 __user *arg) +-{ +- struct perf_event_context *ctx = event->ctx; +- int ret = 0, active; ++struct period_event { ++ struct perf_event *event; + u64 value; ++}; + +- if (!is_sampling_event(event)) +- return -EINVAL; +- +- if (copy_from_user(&value, arg, sizeof(value))) +- return -EFAULT; +- +- if (!value) +- return -EINVAL; ++static int __perf_event_period(void *info) ++{ ++ struct period_event *pe = info; ++ struct perf_event *event = pe->event; ++ struct perf_event_context *ctx = event->ctx; ++ u64 value = pe->value; ++ bool active; + +- raw_spin_lock_irq(&ctx->lock); ++ raw_spin_lock(&ctx->lock); + if (event->attr.freq) { +- if (value > sysctl_perf_event_sample_rate) { +- ret = -EINVAL; +- goto unlock; +- } +- + event->attr.sample_freq = value; + } else { + event->attr.sample_period = value; +@@ -3602,11 +3595,53 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg) + event->pmu->start(event, PERF_EF_RELOAD); + perf_pmu_enable(ctx->pmu); + } ++ raw_spin_unlock(&ctx->lock); + +-unlock: ++ return 0; ++} ++ ++static int perf_event_period(struct perf_event *event, u64 __user *arg) ++{ ++ struct period_event pe = { .event = event, }; ++ struct perf_event_context *ctx = event->ctx; ++ struct task_struct *task; ++ u64 value; ++ ++ if (!is_sampling_event(event)) ++ return -EINVAL; ++ ++ if (copy_from_user(&value, arg, sizeof(value))) ++ return -EFAULT; ++ ++ if (!value) ++ return -EINVAL; ++ ++ if (event->attr.freq && value > sysctl_perf_event_sample_rate) ++ return -EINVAL; ++ ++ task = ctx->task; ++ pe.value = value; ++ ++ if (!task) { ++ cpu_function_call(event->cpu, __perf_event_period, &pe); ++ return 0; ++ } ++ ++retry: ++ if (!task_function_call(task, __perf_event_period, &pe)) ++ return 0; ++ ++ raw_spin_lock_irq(&ctx->lock); ++ if (ctx->is_active) { ++ raw_spin_unlock_irq(&ctx->lock); ++ task = ctx->task; ++ goto retry; ++ } ++ ++ __perf_event_period(&pe); + raw_spin_unlock_irq(&ctx->lock); + +- return ret; ++ return 0; + } + + static const struct file_operations perf_fops; +@@ -4218,12 +4253,20 @@ static const struct file_operations perf_fops = { + * to user-space before waking everybody up. + */ + ++static inline struct fasync_struct **perf_event_fasync(struct perf_event *event) ++{ ++ /* only the parent has fasync state */ ++ if (event->parent) ++ event = event->parent; ++ return &event->fasync; ++} ++ + void perf_event_wakeup(struct perf_event *event) + { + ring_buffer_wakeup(event); + + if (event->pending_kill) { +- kill_fasync(&event->fasync, SIGIO, event->pending_kill); ++ kill_fasync(perf_event_fasync(event), SIGIO, event->pending_kill); + event->pending_kill = 0; + } + } +@@ -5432,7 +5475,7 @@ static int __perf_event_overflow(struct perf_event *event, + else + perf_event_output(event, data, regs); + +- if (event->fasync && event->pending_kill) { ++ if (*perf_event_fasync(event) && event->pending_kill) { + event->pending_wakeup = 1; + irq_work_queue(&event->pending); + } +diff --git a/mm/memory-failure.c b/mm/memory-failure.c +index 9502057c3c54..42aeb848b8e9 100644 +--- a/mm/memory-failure.c ++++ b/mm/memory-failure.c +@@ -1510,6 +1510,8 @@ static int get_any_page(struct page *page, unsigned long pfn, int flags) + */ + ret = __get_any_page(page, pfn, 0); + if (!PageLRU(page)) { ++ /* Drop page reference which is from __get_any_page() */ ++ put_page(page); + pr_info("soft_offline: %#lx: unknown non LRU page type %lx\n", + pfn, page->flags); + return -EIO; +diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl +index 31331723e810..9969feefb720 100644 +--- a/scripts/kconfig/streamline_config.pl ++++ b/scripts/kconfig/streamline_config.pl +@@ -137,7 +137,7 @@ my $ksource = ($ARGV[0] ? $ARGV[0] : '.'); + my $kconfig = $ARGV[1]; + my $lsmod_file = $ENV{'LSMOD'}; + +-my @makefiles = `find $ksource -name Makefile 2>/dev/null`; ++my @makefiles = `find $ksource -name Makefile -or -name Kbuild 2>/dev/null`; + chomp @makefiles; + + my %depends; diff --git a/patch/kernel/cubox-default/patch-3.14.52-53.patch b/patch/kernel/cubox-default/patch-3.14.52-53.patch new file mode 100644 index 000000000..857b37d07 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.52-53.patch @@ -0,0 +1,940 @@ +diff --git a/Documentation/ABI/testing/configfs-usb-gadget-loopback b/Documentation/ABI/testing/configfs-usb-gadget-loopback +index 9aae5bfb9908..06beefbcf061 100644 +--- a/Documentation/ABI/testing/configfs-usb-gadget-loopback ++++ b/Documentation/ABI/testing/configfs-usb-gadget-loopback +@@ -5,4 +5,4 @@ Description: + The attributes: + + qlen - depth of loopback queue +- bulk_buflen - buffer length ++ buflen - buffer length +diff --git a/Documentation/ABI/testing/configfs-usb-gadget-sourcesink b/Documentation/ABI/testing/configfs-usb-gadget-sourcesink +index 29477c319f61..bc7ff731aa0c 100644 +--- a/Documentation/ABI/testing/configfs-usb-gadget-sourcesink ++++ b/Documentation/ABI/testing/configfs-usb-gadget-sourcesink +@@ -9,4 +9,4 @@ Description: + isoc_maxpacket - 0 - 1023 (fs), 0 - 1024 (hs/ss) + isoc_mult - 0..2 (hs/ss only) + isoc_maxburst - 0..15 (ss only) +- qlen - buffer length ++ buflen - buffer length +diff --git a/Makefile b/Makefile +index 3a5d4316c4c7..86d227774ae6 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 52 ++SUBLEVEL = 53 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/mach-omap2/clockdomains7xx_data.c b/arch/arm/mach-omap2/clockdomains7xx_data.c +index 57d5df0c1fbd..7581e036bda6 100644 +--- a/arch/arm/mach-omap2/clockdomains7xx_data.c ++++ b/arch/arm/mach-omap2/clockdomains7xx_data.c +@@ -331,7 +331,7 @@ static struct clockdomain l4per2_7xx_clkdm = { + .dep_bit = DRA7XX_L4PER2_STATDEP_SHIFT, + .wkdep_srcs = l4per2_wkup_sleep_deps, + .sleepdep_srcs = l4per2_wkup_sleep_deps, +- .flags = CLKDM_CAN_HWSUP_SWSUP, ++ .flags = CLKDM_CAN_SWSUP, + }; + + static struct clockdomain mpu0_7xx_clkdm = { +diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c +index a8d6f69f92a3..4bcf841e4701 100644 +--- a/arch/x86/crypto/ghash-clmulni-intel_glue.c ++++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c +@@ -291,6 +291,7 @@ static struct ahash_alg ghash_async_alg = { + .cra_name = "ghash", + .cra_driver_name = "ghash-clmulni", + .cra_priority = 400, ++ .cra_ctxsize = sizeof(struct ghash_async_ctx), + .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC, + .cra_blocksize = GHASH_BLOCK_SIZE, + .cra_type = &crypto_ahash_type, +diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c +index aa0779372e3d..dba56fb5e383 100644 +--- a/arch/x86/kvm/mmu.c ++++ b/arch/x86/kvm/mmu.c +@@ -381,12 +381,6 @@ static u64 __get_spte_lockless(u64 *sptep) + { + return ACCESS_ONCE(*sptep); + } +- +-static bool __check_direct_spte_mmio_pf(u64 spte) +-{ +- /* It is valid if the spte is zapped. */ +- return spte == 0ull; +-} + #else + union split_spte { + struct { +@@ -502,23 +496,6 @@ retry: + + return spte.spte; + } +- +-static bool __check_direct_spte_mmio_pf(u64 spte) +-{ +- union split_spte sspte = (union split_spte)spte; +- u32 high_mmio_mask = shadow_mmio_mask >> 32; +- +- /* It is valid if the spte is zapped. */ +- if (spte == 0ull) +- return true; +- +- /* It is valid if the spte is being zapped. */ +- if (sspte.spte_low == 0ull && +- (sspte.spte_high & high_mmio_mask) == high_mmio_mask) +- return true; +- +- return false; +-} + #endif + + static bool spte_is_locklessly_modifiable(u64 spte) +@@ -3215,21 +3192,6 @@ static bool quickly_check_mmio_pf(struct kvm_vcpu *vcpu, u64 addr, bool direct) + return vcpu_match_mmio_gva(vcpu, addr); + } + +- +-/* +- * On direct hosts, the last spte is only allows two states +- * for mmio page fault: +- * - It is the mmio spte +- * - It is zapped or it is being zapped. +- * +- * This function completely checks the spte when the last spte +- * is not the mmio spte. +- */ +-static bool check_direct_spte_mmio_pf(u64 spte) +-{ +- return __check_direct_spte_mmio_pf(spte); +-} +- + static u64 walk_shadow_page_get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr) + { + struct kvm_shadow_walk_iterator iterator; +@@ -3272,13 +3234,6 @@ int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct) + } + + /* +- * It's ok if the gva is remapped by other cpus on shadow guest, +- * it's a BUG if the gfn is not a mmio page. +- */ +- if (direct && !check_direct_spte_mmio_pf(spte)) +- return RET_MMIO_PF_BUG; +- +- /* + * If the page table is zapped by other cpus, let CPU fault again on + * the address. + */ +diff --git a/arch/xtensa/include/asm/traps.h b/arch/xtensa/include/asm/traps.h +index 677bfcf4ee5d..28f33a8b7f5f 100644 +--- a/arch/xtensa/include/asm/traps.h ++++ b/arch/xtensa/include/asm/traps.h +@@ -25,30 +25,39 @@ static inline void spill_registers(void) + { + #if XCHAL_NUM_AREGS > 16 + __asm__ __volatile__ ( +- " call12 1f\n" ++ " call8 1f\n" + " _j 2f\n" + " retw\n" + " .align 4\n" + "1:\n" ++#if XCHAL_NUM_AREGS == 32 ++ " _entry a1, 32\n" ++ " addi a8, a0, 3\n" ++ " _entry a1, 16\n" ++ " mov a12, a12\n" ++ " retw\n" ++#else + " _entry a1, 48\n" +- " addi a12, a0, 3\n" +-#if XCHAL_NUM_AREGS > 32 +- " .rept (" __stringify(XCHAL_NUM_AREGS) " - 32) / 12\n" ++ " call12 1f\n" ++ " retw\n" ++ " .align 4\n" ++ "1:\n" ++ " .rept (" __stringify(XCHAL_NUM_AREGS) " - 16) / 12\n" + " _entry a1, 48\n" + " mov a12, a0\n" + " .endr\n" +-#endif +- " _entry a1, 48\n" ++ " _entry a1, 16\n" + #if XCHAL_NUM_AREGS % 12 == 0 +- " mov a8, a8\n" +-#elif XCHAL_NUM_AREGS % 12 == 4 + " mov a12, a12\n" +-#elif XCHAL_NUM_AREGS % 12 == 8 ++#elif XCHAL_NUM_AREGS % 12 == 4 + " mov a4, a4\n" ++#elif XCHAL_NUM_AREGS % 12 == 8 ++ " mov a8, a8\n" + #endif + " retw\n" ++#endif + "2:\n" +- : : : "a12", "a13", "memory"); ++ : : : "a8", "a9", "memory"); + #else + __asm__ __volatile__ ( + " mov a12, a12\n" +diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S +index a06b7efaae82..cf8a354fa628 100644 +--- a/arch/xtensa/kernel/entry.S ++++ b/arch/xtensa/kernel/entry.S +@@ -568,12 +568,13 @@ user_exception_exit: + * (if we have restored WSBITS-1 frames). + */ + ++2: + #if XCHAL_HAVE_THREADPTR + l32i a3, a1, PT_THREADPTR + wur a3, threadptr + #endif + +-2: j common_exception_exit ++ j common_exception_exit + + /* This is the kernel exception exit. + * We avoided to do a MOVSP when we entered the exception, but we +@@ -1792,7 +1793,7 @@ ENDPROC(system_call) + mov a12, a0 + .endr + #endif +- _entry a1, 48 ++ _entry a1, 16 + #if XCHAL_NUM_AREGS % 12 == 0 + mov a8, a8 + #elif XCHAL_NUM_AREGS % 12 == 4 +@@ -1816,7 +1817,7 @@ ENDPROC(system_call) + + ENTRY(_switch_to) + +- entry a1, 16 ++ entry a1, 48 + + mov a11, a3 # and 'next' (a3) + +diff --git a/drivers/auxdisplay/ks0108.c b/drivers/auxdisplay/ks0108.c +index 5b93852392b8..0d752851a1ee 100644 +--- a/drivers/auxdisplay/ks0108.c ++++ b/drivers/auxdisplay/ks0108.c +@@ -139,6 +139,7 @@ static int __init ks0108_init(void) + + ks0108_pardevice = parport_register_device(ks0108_parport, KS0108_NAME, + NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); ++ parport_put_port(ks0108_parport); + if (ks0108_pardevice == NULL) { + printk(KERN_ERR KS0108_NAME ": ERROR: " + "parport didn't register new device\n"); +diff --git a/drivers/base/devres.c b/drivers/base/devres.c +index 545c4de412c3..cbe0b58bab3c 100644 +--- a/drivers/base/devres.c ++++ b/drivers/base/devres.c +@@ -297,10 +297,10 @@ void * devres_get(struct device *dev, void *new_res, + if (!dr) { + add_dr(dev, &new_dr->node); + dr = new_dr; +- new_dr = NULL; ++ new_res = NULL; + } + spin_unlock_irqrestore(&dev->devres_lock, flags); +- devres_free(new_dr); ++ devres_free(new_res); + + return dr->data; + } +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index 9dbf4ef2b2a3..57d8f671d1f6 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -354,9 +354,7 @@ int platform_device_add(struct platform_device *pdev) + + while (--i >= 0) { + struct resource *r = &pdev->resource[i]; +- unsigned long type = resource_type(r); +- +- if (type == IORESOURCE_MEM || type == IORESOURCE_IO) ++ if (r->parent) + release_resource(r); + } + +@@ -387,9 +385,7 @@ void platform_device_del(struct platform_device *pdev) + + for (i = 0; i < pdev->num_resources; i++) { + struct resource *r = &pdev->resource[i]; +- unsigned long type = resource_type(r); +- +- if (type == IORESOURCE_MEM || type == IORESOURCE_IO) ++ if (r->parent) + release_resource(r); + } + } +diff --git a/drivers/clk/versatile/clk-sp810.c b/drivers/clk/versatile/clk-sp810.c +index c6e86a9a2aa3..5122ef25f595 100644 +--- a/drivers/clk/versatile/clk-sp810.c ++++ b/drivers/clk/versatile/clk-sp810.c +@@ -128,8 +128,8 @@ static struct clk *clk_sp810_timerclken_of_get(struct of_phandle_args *clkspec, + { + struct clk_sp810 *sp810 = data; + +- if (WARN_ON(clkspec->args_count != 1 || clkspec->args[0] > +- ARRAY_SIZE(sp810->timerclken))) ++ if (WARN_ON(clkspec->args_count != 1 || ++ clkspec->args[0] >= ARRAY_SIZE(sp810->timerclken))) + return NULL; + + return sp810->timerclken[clkspec->args[0]].clk; +diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c +index c39c414c7751..8e3267a8bd4f 100644 +--- a/drivers/gpu/drm/qxl/qxl_display.c ++++ b/drivers/gpu/drm/qxl/qxl_display.c +@@ -136,9 +136,35 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector, + *pwidth = head->width; + *pheight = head->height; + drm_mode_probed_add(connector, mode); ++ /* remember the last custom size for mode validation */ ++ qdev->monitors_config_width = mode->hdisplay; ++ qdev->monitors_config_height = mode->vdisplay; + return 1; + } + ++static struct mode_size { ++ int w; ++ int h; ++} common_modes[] = { ++ { 640, 480}, ++ { 720, 480}, ++ { 800, 600}, ++ { 848, 480}, ++ {1024, 768}, ++ {1152, 768}, ++ {1280, 720}, ++ {1280, 800}, ++ {1280, 854}, ++ {1280, 960}, ++ {1280, 1024}, ++ {1440, 900}, ++ {1400, 1050}, ++ {1680, 1050}, ++ {1600, 1200}, ++ {1920, 1080}, ++ {1920, 1200} ++}; ++ + static int qxl_add_common_modes(struct drm_connector *connector, + unsigned pwidth, + unsigned pheight) +@@ -146,29 +172,6 @@ static int qxl_add_common_modes(struct drm_connector *connector, + struct drm_device *dev = connector->dev; + struct drm_display_mode *mode = NULL; + int i; +- struct mode_size { +- int w; +- int h; +- } common_modes[] = { +- { 640, 480}, +- { 720, 480}, +- { 800, 600}, +- { 848, 480}, +- {1024, 768}, +- {1152, 768}, +- {1280, 720}, +- {1280, 800}, +- {1280, 854}, +- {1280, 960}, +- {1280, 1024}, +- {1440, 900}, +- {1400, 1050}, +- {1680, 1050}, +- {1600, 1200}, +- {1920, 1080}, +- {1920, 1200} +- }; +- + for (i = 0; i < ARRAY_SIZE(common_modes); i++) { + mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, + 60, false, false, false); +@@ -753,11 +756,22 @@ static int qxl_conn_get_modes(struct drm_connector *connector) + static int qxl_conn_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) + { ++ struct drm_device *ddev = connector->dev; ++ struct qxl_device *qdev = ddev->dev_private; ++ int i; ++ + /* TODO: is this called for user defined modes? (xrandr --add-mode) + * TODO: check that the mode fits in the framebuffer */ +- DRM_DEBUG("%s: %dx%d status=%d\n", mode->name, mode->hdisplay, +- mode->vdisplay, mode->status); +- return MODE_OK; ++ ++ if(qdev->monitors_config_width == mode->hdisplay && ++ qdev->monitors_config_height == mode->vdisplay) ++ return MODE_OK; ++ ++ for (i = 0; i < ARRAY_SIZE(common_modes); i++) { ++ if (common_modes[i].w == mode->hdisplay && common_modes[i].h == mode->vdisplay) ++ return MODE_OK; ++ } ++ return MODE_BAD; + } + + static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector) +diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h +index 36ed40ba773f..8aa077ca8244 100644 +--- a/drivers/gpu/drm/qxl/qxl_drv.h ++++ b/drivers/gpu/drm/qxl/qxl_drv.h +@@ -325,6 +325,8 @@ struct qxl_device { + struct work_struct fb_work; + + struct drm_property *hotplug_mode_update_property; ++ int monitors_config_width; ++ int monitors_config_height; + }; + + /* forward declaration for QXL_INFO_IO */ +diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c +index 4d36b9e86275..17ae621dbdab 100644 +--- a/drivers/gpu/drm/radeon/radeon_connectors.c ++++ b/drivers/gpu/drm/radeon/radeon_connectors.c +@@ -71,6 +71,11 @@ void radeon_connector_hotplug(struct drm_connector *connector) + if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + } else if (radeon_dp_needs_link_train(radeon_connector)) { ++ /* Don't try to start link training before we ++ * have the dpcd */ ++ if (!radeon_dp_getdpcd(radeon_connector)) ++ return; ++ + /* set it to OFF so that drm_helper_connector_dpms() + * won't return immediately since the current state + * is ON at this point. +diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c +index 617c47f9ebe6..deabd2c8772d 100644 +--- a/drivers/hid/usbhid/hid-core.c ++++ b/drivers/hid/usbhid/hid-core.c +@@ -180,7 +180,7 @@ static void hid_io_error(struct hid_device *hid) + if (time_after(jiffies, usbhid->stop_retry)) { + + /* Retries failed, so do a port reset unless we lack bandwidth*/ +- if (test_bit(HID_NO_BANDWIDTH, &usbhid->iofl) ++ if (!test_bit(HID_NO_BANDWIDTH, &usbhid->iofl) + && !test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) { + + schedule_work(&usbhid->reset_work); +diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig +index ac2d69e34c8c..6f64c5cc5387 100644 +--- a/drivers/iio/gyro/Kconfig ++++ b/drivers/iio/gyro/Kconfig +@@ -93,7 +93,8 @@ config IIO_ST_GYRO_SPI_3AXIS + config ITG3200 + tristate "InvenSense ITG3200 Digital 3-Axis Gyroscope I2C driver" + depends on I2C +- select IIO_TRIGGERED_BUFFER if IIO_BUFFER ++ select IIO_BUFFER ++ select IIO_TRIGGERED_BUFFER + help + Say yes here to add support for the InvenSense ITG3200 digital + 3-axis gyroscope sensor. +diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c +index dd4206cac62d..5e1b117d4e3b 100644 +--- a/drivers/iio/imu/adis16480.c ++++ b/drivers/iio/imu/adis16480.c +@@ -110,6 +110,10 @@ + struct adis16480_chip_info { + unsigned int num_channels; + const struct iio_chan_spec *channels; ++ unsigned int gyro_max_val; ++ unsigned int gyro_max_scale; ++ unsigned int accel_max_val; ++ unsigned int accel_max_scale; + }; + + struct adis16480 { +@@ -533,19 +537,21 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev, + static int adis16480_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *val, int *val2, long info) + { ++ struct adis16480 *st = iio_priv(indio_dev); ++ + switch (info) { + case IIO_CHAN_INFO_RAW: + return adis_single_conversion(indio_dev, chan, 0, val); + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: +- *val = 0; +- *val2 = IIO_DEGREE_TO_RAD(20000); /* 0.02 degree/sec */ +- return IIO_VAL_INT_PLUS_MICRO; ++ *val = st->chip_info->gyro_max_scale; ++ *val2 = st->chip_info->gyro_max_val; ++ return IIO_VAL_FRACTIONAL; + case IIO_ACCEL: +- *val = 0; +- *val2 = IIO_G_TO_M_S_2(800); /* 0.8 mg */ +- return IIO_VAL_INT_PLUS_MICRO; ++ *val = st->chip_info->accel_max_scale; ++ *val2 = st->chip_info->accel_max_val; ++ return IIO_VAL_FRACTIONAL; + case IIO_MAGN: + *val = 0; + *val2 = 100; /* 0.0001 gauss */ +@@ -702,18 +708,39 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { + [ADIS16375] = { + .channels = adis16485_channels, + .num_channels = ARRAY_SIZE(adis16485_channels), ++ /* ++ * storing the value in rad/degree and the scale in degree ++ * gives us the result in rad and better precession than ++ * storing the scale directly in rad. ++ */ ++ .gyro_max_val = IIO_RAD_TO_DEGREE(22887), ++ .gyro_max_scale = 300, ++ .accel_max_val = IIO_M_S_2_TO_G(21973), ++ .accel_max_scale = 18, + }, + [ADIS16480] = { + .channels = adis16480_channels, + .num_channels = ARRAY_SIZE(adis16480_channels), ++ .gyro_max_val = IIO_RAD_TO_DEGREE(22500), ++ .gyro_max_scale = 450, ++ .accel_max_val = IIO_M_S_2_TO_G(12500), ++ .accel_max_scale = 5, + }, + [ADIS16485] = { + .channels = adis16485_channels, + .num_channels = ARRAY_SIZE(adis16485_channels), ++ .gyro_max_val = IIO_RAD_TO_DEGREE(22500), ++ .gyro_max_scale = 450, ++ .accel_max_val = IIO_M_S_2_TO_G(20000), ++ .accel_max_scale = 5, + }, + [ADIS16488] = { + .channels = adis16480_channels, + .num_channels = ARRAY_SIZE(adis16480_channels), ++ .gyro_max_val = IIO_RAD_TO_DEGREE(22500), ++ .gyro_max_scale = 450, ++ .accel_max_val = IIO_M_S_2_TO_G(22500), ++ .accel_max_scale = 18, + }, + }; + +diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c +index 0f1d9b2ccdfa..37b52bd44f86 100644 +--- a/drivers/iio/industrialio-buffer.c ++++ b/drivers/iio/industrialio-buffer.c +@@ -96,7 +96,7 @@ unsigned int iio_buffer_poll(struct file *filp, + struct iio_buffer *rb = indio_dev->buffer; + + if (!indio_dev->info) +- return -ENODEV; ++ return 0; + + poll_wait(filp, &rb->pollq, wait); + if (iio_buffer_data_available(rb)) +diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c +index f9360f497ed4..05b59941c400 100644 +--- a/drivers/iio/industrialio-event.c ++++ b/drivers/iio/industrialio-event.c +@@ -83,7 +83,7 @@ static unsigned int iio_event_poll(struct file *filep, + unsigned int events = 0; + + if (!indio_dev->info) +- return -ENODEV; ++ return events; + + poll_wait(filep, &ev_int->wait, wait); + +diff --git a/drivers/of/address.c b/drivers/of/address.c +index 005c65715846..9eae613c2a52 100644 +--- a/drivers/of/address.c ++++ b/drivers/of/address.c +@@ -704,10 +704,10 @@ struct device_node *of_find_matching_node_by_address(struct device_node *from, + struct resource res; + + while (dn) { +- if (of_address_to_resource(dn, 0, &res)) +- continue; +- if (res.start == base_address) ++ if (!of_address_to_resource(dn, 0, &res) && ++ res.start == base_address) + return dn; ++ + dn = of_find_matching_node(dn, matches); + } + +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 27abeb40dfab..2afa4803280f 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -2790,12 +2790,15 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors); + + static void fixup_ti816x_class(struct pci_dev *dev) + { ++ u32 class = dev->class; ++ + /* TI 816x devices do not have class code set when in PCIe boot mode */ +- dev_info(&dev->dev, "Setting PCI class for 816x PCIe device\n"); +- dev->class = PCI_CLASS_MULTIMEDIA_VIDEO; ++ dev->class = PCI_CLASS_MULTIMEDIA_VIDEO << 8; ++ dev_info(&dev->dev, "PCI class overridden (%#08x -> %#08x)\n", ++ class, dev->class); + } + DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_TI, 0xb800, +- PCI_CLASS_NOT_DEFINED, 0, fixup_ti816x_class); ++ PCI_CLASS_NOT_DEFINED, 0, fixup_ti816x_class); + + /* Some PCIe devices do not work reliably with the claimed maximum + * payload size supported. +diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c +index 82f2c389b4d1..b334f68ebe46 100644 +--- a/drivers/s390/char/sclp_early.c ++++ b/drivers/s390/char/sclp_early.c +@@ -7,6 +7,7 @@ + #define KMSG_COMPONENT "sclp_early" + #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + ++#include + #include + #include + #include +diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c +index 6f622b4de698..927edd130ce9 100644 +--- a/drivers/staging/comedi/drivers/adl_pci7x3x.c ++++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c +@@ -113,8 +113,20 @@ static int adl_pci7x3x_do_insn_bits(struct comedi_device *dev, + { + unsigned long reg = (unsigned long)s->private; + +- if (comedi_dio_update_state(s, data)) +- outl(s->state, dev->iobase + reg); ++ if (comedi_dio_update_state(s, data)) { ++ unsigned int val = s->state; ++ ++ if (s->n_chan == 16) { ++ /* ++ * It seems the PCI-7230 needs the 16-bit DO state ++ * to be shifted left by 16 bits before being written ++ * to the 32-bit register. Set the value in both ++ * halves of the register to be sure. ++ */ ++ val |= val << 16; ++ } ++ outl(val, dev->iobase + reg); ++ } + + data[1] = s->state; + +diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c +index 682a2fbe5c06..2b22cc1e57a2 100644 +--- a/drivers/tty/serial/8250/8250_pnp.c ++++ b/drivers/tty/serial/8250/8250_pnp.c +@@ -364,6 +364,11 @@ static const struct pnp_device_id pnp_dev_table[] = { + /* Winbond CIR port, should not be probed. We should keep track + of it to prevent the legacy serial driver from probing it */ + { "WEC1022", CIR_PORT }, ++ /* ++ * SMSC IrCC SIR/FIR port, should not be probed by serial driver ++ * as well so its own driver can bind to it. ++ */ ++ { "SMCF010", CIR_PORT }, + { "", 0 } + }; + +diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c +index 2978ca596a7f..0e75d2a76511 100644 +--- a/drivers/tty/vt/consolemap.c ++++ b/drivers/tty/vt/consolemap.c +@@ -540,6 +540,12 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) + + /* Save original vc_unipagdir_loc in case we allocate a new one */ + p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; ++ ++ if (!p) { ++ err = -EINVAL; ++ ++ goto out_unlock; ++ } + if (p->readonly) { + console_unlock(); + return -EIO; +@@ -633,6 +639,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) + set_inverse_transl(vc, p, i); /* Update inverse translations */ + set_inverse_trans_unicode(vc, p); + ++out_unlock: + console_unlock(); + return err; + } +diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c +index a05fc58d9b60..965c9ac85d6f 100644 +--- a/drivers/usb/dwc3/ep0.c ++++ b/drivers/usb/dwc3/ep0.c +@@ -793,6 +793,11 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, + unsigned maxp = ep0->endpoint.maxpacket; + + transfer_size += (maxp - (transfer_size % maxp)); ++ ++ /* Maximum of DWC3_EP0_BOUNCE_SIZE can only be received */ ++ if (transfer_size > DWC3_EP0_BOUNCE_SIZE) ++ transfer_size = DWC3_EP0_BOUNCE_SIZE; ++ + transferred = min_t(u32, ur->length, + transfer_size - length); + memcpy(ur->buf, dwc->ep0_bounce, transferred); +@@ -905,11 +910,14 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, + return; + } + +- WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE); +- + maxpacket = dep->endpoint.maxpacket; + transfer_size = roundup(req->request.length, maxpacket); + ++ if (transfer_size > DWC3_EP0_BOUNCE_SIZE) { ++ dev_WARN(dwc->dev, "bounce buf can't handle req len\n"); ++ transfer_size = DWC3_EP0_BOUNCE_SIZE; ++ } ++ + dwc->ep0_bounced = true; + + /* +diff --git a/drivers/usb/host/ehci-sysfs.c b/drivers/usb/host/ehci-sysfs.c +index f6459dfb6f54..94054dad7710 100644 +--- a/drivers/usb/host/ehci-sysfs.c ++++ b/drivers/usb/host/ehci-sysfs.c +@@ -29,7 +29,7 @@ static ssize_t show_companion(struct device *dev, + int count = PAGE_SIZE; + char *ptr = buf; + +- ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); ++ ehci = hcd_to_ehci(dev_get_drvdata(dev)); + nports = HCS_N_PORTS(ehci->hcs_params); + + for (index = 0; index < nports; ++index) { +@@ -54,7 +54,7 @@ static ssize_t store_companion(struct device *dev, + struct ehci_hcd *ehci; + int portnum, new_owner; + +- ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); ++ ehci = hcd_to_ehci(dev_get_drvdata(dev)); + new_owner = PORT_OWNER; /* Owned by companion */ + if (sscanf(buf, "%d", &portnum) != 1) + return -EINVAL; +@@ -85,7 +85,7 @@ static ssize_t show_uframe_periodic_max(struct device *dev, + struct ehci_hcd *ehci; + int n; + +- ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); ++ ehci = hcd_to_ehci(dev_get_drvdata(dev)); + n = scnprintf(buf, PAGE_SIZE, "%d\n", ehci->uframe_periodic_max); + return n; + } +@@ -101,7 +101,7 @@ static ssize_t store_uframe_periodic_max(struct device *dev, + unsigned long flags; + ssize_t ret; + +- ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); ++ ehci = hcd_to_ehci(dev_get_drvdata(dev)); + if (kstrtouint(buf, 0, &uframe_periodic_max) < 0) + return -EINVAL; + +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index bc77ea7cde48..7fb81dbbdc8d 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -618,6 +618,10 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_SYNAPSE_SS200_PID) }, ++ { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX_PID) }, ++ { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2_PID) }, ++ { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2WI_PID) }, ++ { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX3_PID) }, + /* + * ELV devices: + */ +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index 792e054126de..2943b97b2a83 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -568,6 +568,14 @@ + */ + #define FTDI_SYNAPSE_SS200_PID 0x9090 /* SS200 - SNAP Stick 200 */ + ++/* ++ * CustomWare / ShipModul NMEA multiplexers product ids (FTDI_VID) ++ */ ++#define FTDI_CUSTOMWARE_MINIPLEX_PID 0xfd48 /* MiniPlex first generation NMEA Multiplexer */ ++#define FTDI_CUSTOMWARE_MINIPLEX2_PID 0xfd49 /* MiniPlex-USB and MiniPlex-2 series */ ++#define FTDI_CUSTOMWARE_MINIPLEX2WI_PID 0xfd4a /* MiniPlex-2Wi */ ++#define FTDI_CUSTOMWARE_MINIPLEX3_PID 0xfd4b /* MiniPlex-3 series */ ++ + + /********************************/ + /** third-party VID/PID combos **/ +diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c +index 9fa7dd413e83..5e5e88209eeb 100644 +--- a/drivers/usb/serial/symbolserial.c ++++ b/drivers/usb/serial/symbolserial.c +@@ -96,7 +96,7 @@ exit: + + static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port) + { +- struct symbol_private *priv = usb_get_serial_data(port->serial); ++ struct symbol_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + int result = 0; + +@@ -122,7 +122,7 @@ static void symbol_close(struct usb_serial_port *port) + static void symbol_throttle(struct tty_struct *tty) + { + struct usb_serial_port *port = tty->driver_data; +- struct symbol_private *priv = usb_get_serial_data(port->serial); ++ struct symbol_private *priv = usb_get_serial_port_data(port); + + spin_lock_irq(&priv->lock); + priv->throttled = true; +@@ -132,7 +132,7 @@ static void symbol_throttle(struct tty_struct *tty) + static void symbol_unthrottle(struct tty_struct *tty) + { + struct usb_serial_port *port = tty->driver_data; +- struct symbol_private *priv = usb_get_serial_data(port->serial); ++ struct symbol_private *priv = usb_get_serial_port_data(port); + int result; + bool was_throttled; + +diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c +index 1b39afdd86fd..5f60bb21905c 100644 +--- a/fs/hpfs/namei.c ++++ b/fs/hpfs/namei.c +@@ -8,6 +8,17 @@ + #include + #include "hpfs_fn.h" + ++static void hpfs_update_directory_times(struct inode *dir) ++{ ++ time_t t = get_seconds(); ++ if (t == dir->i_mtime.tv_sec && ++ t == dir->i_ctime.tv_sec) ++ return; ++ dir->i_mtime.tv_sec = dir->i_ctime.tv_sec = t; ++ dir->i_mtime.tv_nsec = dir->i_ctime.tv_nsec = 0; ++ hpfs_write_inode_nolock(dir); ++} ++ + static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) + { + const unsigned char *name = dentry->d_name.name; +@@ -99,6 +110,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) + result->i_mode = mode | S_IFDIR; + hpfs_write_inode_nolock(result); + } ++ hpfs_update_directory_times(dir); + d_instantiate(dentry, result); + hpfs_unlock(dir->i_sb); + return 0; +@@ -187,6 +199,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, b + result->i_mode = mode | S_IFREG; + hpfs_write_inode_nolock(result); + } ++ hpfs_update_directory_times(dir); + d_instantiate(dentry, result); + hpfs_unlock(dir->i_sb); + return 0; +@@ -262,6 +275,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, de + insert_inode_hash(result); + + hpfs_write_inode_nolock(result); ++ hpfs_update_directory_times(dir); + d_instantiate(dentry, result); + brelse(bh); + hpfs_unlock(dir->i_sb); +@@ -340,6 +354,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy + insert_inode_hash(result); + + hpfs_write_inode_nolock(result); ++ hpfs_update_directory_times(dir); + d_instantiate(dentry, result); + hpfs_unlock(dir->i_sb); + return 0; +@@ -423,6 +438,8 @@ again: + out1: + hpfs_brelse4(&qbh); + out: ++ if (!err) ++ hpfs_update_directory_times(dir); + hpfs_unlock(dir->i_sb); + return err; + } +@@ -477,6 +494,8 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry) + out1: + hpfs_brelse4(&qbh); + out: ++ if (!err) ++ hpfs_update_directory_times(dir); + hpfs_unlock(dir->i_sb); + return err; + } +@@ -595,7 +614,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, + goto end1; + } + +- end: ++end: + hpfs_i(i)->i_parent_dir = new_dir->i_ino; + if (S_ISDIR(i->i_mode)) { + inc_nlink(new_dir); +@@ -610,6 +629,10 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, + brelse(bh); + } + end1: ++ if (!err) { ++ hpfs_update_directory_times(old_dir); ++ hpfs_update_directory_times(new_dir); ++ } + hpfs_unlock(i->i_sb); + return err; + } +diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h +index 75a8a20c8179..c2fb6f3ff44b 100644 +--- a/include/linux/iio/iio.h ++++ b/include/linux/iio/iio.h +@@ -593,6 +593,15 @@ int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer, + #define IIO_DEGREE_TO_RAD(deg) (((deg) * 314159ULL + 9000000ULL) / 18000000ULL) + + /** ++ * IIO_RAD_TO_DEGREE() - Convert rad to degree ++ * @rad: A value in rad ++ * ++ * Returns the given value converted from rad to degree ++ */ ++#define IIO_RAD_TO_DEGREE(rad) \ ++ (((rad) * 18000000ULL + 314159ULL / 2) / 314159ULL) ++ ++/** + * IIO_G_TO_M_S_2() - Convert g to meter / second**2 + * @g: A value in g + * +@@ -600,4 +609,12 @@ int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer, + */ + #define IIO_G_TO_M_S_2(g) ((g) * 980665ULL / 100000ULL) + ++/** ++ * IIO_M_S_2_TO_G() - Convert meter / second**2 to g ++ * @ms2: A value in meter / second**2 ++ * ++ * Returns the given value converted from meter / second**2 to g ++ */ ++#define IIO_M_S_2_TO_G(ms2) (((ms2) * 100000ULL + 980665ULL / 2) / 980665ULL) ++ + #endif /* _INDUSTRIAL_IO_H_ */ diff --git a/patch/kernel/cubox-default/patch-3.14.53-54.patch b/patch/kernel/cubox-default/patch-3.14.53-54.patch new file mode 100644 index 000000000..836dcd881 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.53-54.patch @@ -0,0 +1,3609 @@ +diff --git a/Makefile b/Makefile +index 86d227774ae6..22c91fa0411e 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,8 +1,8 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 53 ++SUBLEVEL = 54 + EXTRAVERSION = +-NAME = Remembering Coco ++NAME = Kernel Recipes 2015 + + # *DOCUMENTATION* + # To see a list of typical targets execute "make help" +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index 65b788410bd9..9a406627b0ef 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -68,6 +68,10 @@ config NO_IOPORT + config STACKTRACE_SUPPORT + def_bool y + ++config ILLEGAL_POINTER_VALUE ++ hex ++ default 0xdead000000000000 ++ + config LOCKDEP_SUPPORT + def_bool y + +@@ -302,6 +306,22 @@ menu "CPU Power Management" + + source "drivers/cpuidle/Kconfig" + ++config ARM64_ERRATUM_843419 ++ bool "Cortex-A53: 843419: A load or store might access an incorrect address" ++ depends on MODULES ++ default y ++ help ++ This option builds kernel modules using the large memory model in ++ order to avoid the use of the ADRP instruction, which can cause ++ a subsequent memory access to use an incorrect address on Cortex-A53 ++ parts up to r0p4. ++ ++ Note that the kernel itself must be linked with a version of ld ++ which fixes potentially affected ADRP instructions through the ++ use of veneers. ++ ++ If unsure, say Y. ++ + endmenu + + source "net/Kconfig" +diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile +index 2fceb71ac3b7..0ab1a34dab58 100644 +--- a/arch/arm64/Makefile ++++ b/arch/arm64/Makefile +@@ -34,6 +34,10 @@ comma = , + + CHECKFLAGS += -D__aarch64__ + ++ifeq ($(CONFIG_ARM64_ERRATUM_843419), y) ++CFLAGS_MODULE += -mcmodel=large ++endif ++ + # Default value + head-y := arch/arm64/kernel/head.o + +diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S +index 0b281fffda51..150492b6cd02 100644 +--- a/arch/arm64/kernel/head.S ++++ b/arch/arm64/kernel/head.S +@@ -203,6 +203,11 @@ CPU_LE( movk x0, #0x30d0, lsl #16 ) // Clear EE and E0E on LE systems + msr hstr_el2, xzr // Disable CP15 traps to EL2 + #endif + ++ /* EL2 debug */ ++ mrs x0, pmcr_el0 // Disable debug access traps ++ ubfx x0, x0, #11, #5 // to EL2 and allow access to ++ msr mdcr_el2, x0 // all PMU counters from EL1 ++ + /* Stage-2 translation */ + msr vttbr_el2, xzr + +diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c +index 1eb1cc955139..e366329d96d8 100644 +--- a/arch/arm64/kernel/module.c ++++ b/arch/arm64/kernel/module.c +@@ -330,12 +330,14 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, + ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 0, 21, + AARCH64_INSN_IMM_ADR); + break; ++#ifndef CONFIG_ARM64_ERRATUM_843419 + case R_AARCH64_ADR_PREL_PG_HI21_NC: + overflow_check = false; + case R_AARCH64_ADR_PREL_PG_HI21: + ovf = reloc_insn_imm(RELOC_OP_PAGE, loc, val, 12, 21, + AARCH64_INSN_IMM_ADR); + break; ++#endif + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_LDST8_ABS_LO12_NC: + overflow_check = false; +diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c +index a966baccf1c0..cbe646fa340b 100644 +--- a/arch/arm64/kernel/signal32.c ++++ b/arch/arm64/kernel/signal32.c +@@ -203,14 +203,32 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) + + /* + * VFP save/restore code. ++ * ++ * We have to be careful with endianness, since the fpsimd context-switch ++ * code operates on 128-bit (Q) register values whereas the compat ABI ++ * uses an array of 64-bit (D) registers. Consequently, we need to swap ++ * the two halves of each Q register when running on a big-endian CPU. + */ ++union __fpsimd_vreg { ++ __uint128_t raw; ++ struct { ++#ifdef __AARCH64EB__ ++ u64 hi; ++ u64 lo; ++#else ++ u64 lo; ++ u64 hi; ++#endif ++ }; ++}; ++ + static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame) + { + struct fpsimd_state *fpsimd = ¤t->thread.fpsimd_state; + compat_ulong_t magic = VFP_MAGIC; + compat_ulong_t size = VFP_STORAGE_SIZE; + compat_ulong_t fpscr, fpexc; +- int err = 0; ++ int i, err = 0; + + /* + * Save the hardware registers to the fpsimd_state structure. +@@ -226,10 +244,15 @@ static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame) + /* + * Now copy the FP registers. Since the registers are packed, + * we can copy the prefix we want (V0-V15) as it is. +- * FIXME: Won't work if big endian. + */ +- err |= __copy_to_user(&frame->ufp.fpregs, fpsimd->vregs, +- sizeof(frame->ufp.fpregs)); ++ for (i = 0; i < ARRAY_SIZE(frame->ufp.fpregs); i += 2) { ++ union __fpsimd_vreg vreg = { ++ .raw = fpsimd->vregs[i >> 1], ++ }; ++ ++ __put_user_error(vreg.lo, &frame->ufp.fpregs[i], err); ++ __put_user_error(vreg.hi, &frame->ufp.fpregs[i + 1], err); ++ } + + /* Create an AArch32 fpscr from the fpsr and the fpcr. */ + fpscr = (fpsimd->fpsr & VFP_FPSCR_STAT_MASK) | +@@ -254,7 +277,7 @@ static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame) + compat_ulong_t magic = VFP_MAGIC; + compat_ulong_t size = VFP_STORAGE_SIZE; + compat_ulong_t fpscr; +- int err = 0; ++ int i, err = 0; + + __get_user_error(magic, &frame->magic, err); + __get_user_error(size, &frame->size, err); +@@ -264,12 +287,14 @@ static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame) + if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE) + return -EINVAL; + +- /* +- * Copy the FP registers into the start of the fpsimd_state. +- * FIXME: Won't work if big endian. +- */ +- err |= __copy_from_user(fpsimd.vregs, frame->ufp.fpregs, +- sizeof(frame->ufp.fpregs)); ++ /* Copy the FP registers into the start of the fpsimd_state. */ ++ for (i = 0; i < ARRAY_SIZE(frame->ufp.fpregs); i += 2) { ++ union __fpsimd_vreg vreg; ++ ++ __get_user_error(vreg.lo, &frame->ufp.fpregs[i], err); ++ __get_user_error(vreg.hi, &frame->ufp.fpregs[i + 1], err); ++ fpsimd.vregs[i >> 1] = vreg.raw; ++ } + + /* Extract the fpsr and the fpcr from the fpscr */ + __get_user_error(fpscr, &frame->ufp.fpscr, err); +diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S +index 3aaf3bc4ad8a..1343b2020891 100644 +--- a/arch/arm64/kvm/hyp.S ++++ b/arch/arm64/kvm/hyp.S +@@ -485,8 +485,6 @@ CPU_BE( rev w5, w5 ) + mrs x3, cntv_ctl_el0 + and x3, x3, #3 + str w3, [x0, #VCPU_TIMER_CNTV_CTL] +- bic x3, x3, #1 // Clear Enable +- msr cntv_ctl_el0, x3 + + isb + +@@ -494,6 +492,9 @@ CPU_BE( rev w5, w5 ) + str x3, [x0, #VCPU_TIMER_CNTV_CVAL] + + 1: ++ // Disable the virtual timer ++ msr cntv_ctl_el0, xzr ++ + // Allow physical timer/counter access for the host + mrs x2, cnthctl_el2 + orr x2, x2, #3 +diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c +index 8ceac4785609..1ce320e4d3d8 100644 +--- a/arch/parisc/kernel/irq.c ++++ b/arch/parisc/kernel/irq.c +@@ -507,8 +507,8 @@ void do_cpu_irq_mask(struct pt_regs *regs) + struct pt_regs *old_regs; + unsigned long eirr_val; + int irq, cpu = smp_processor_id(); +-#ifdef CONFIG_SMP + struct irq_desc *desc; ++#ifdef CONFIG_SMP + cpumask_t dest; + #endif + +@@ -521,8 +521,12 @@ void do_cpu_irq_mask(struct pt_regs *regs) + goto set_out; + irq = eirr_to_irq(eirr_val); + +-#ifdef CONFIG_SMP ++ /* Filter out spurious interrupts, mostly from serial port at bootup */ + desc = irq_to_desc(irq); ++ if (unlikely(!desc->action)) ++ goto set_out; ++ ++#ifdef CONFIG_SMP + cpumask_copy(&dest, desc->irq_data.affinity); + if (irqd_is_per_cpu(&desc->irq_data) && + !cpu_isset(smp_processor_id(), dest)) { +diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S +index 7ef22e3387e0..0b8d26d3ba43 100644 +--- a/arch/parisc/kernel/syscall.S ++++ b/arch/parisc/kernel/syscall.S +@@ -821,7 +821,7 @@ cas2_action: + /* 64bit CAS */ + #ifdef CONFIG_64BIT + 19: ldd,ma 0(%sr3,%r26), %r29 +- sub,= %r29, %r25, %r0 ++ sub,*= %r29, %r25, %r0 + b,n cas2_end + 20: std,ma %r24, 0(%sr3,%r26) + copy %r0, %r28 +diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h +index 7b3d54fae46f..7356053b1133 100644 +--- a/arch/powerpc/include/asm/pgtable-ppc64.h ++++ b/arch/powerpc/include/asm/pgtable-ppc64.h +@@ -135,7 +135,19 @@ + #define pte_iterate_hashed_end() } while(0) + + #ifdef CONFIG_PPC_HAS_HASH_64K +-#define pte_pagesize_index(mm, addr, pte) get_slice_psize(mm, addr) ++/* ++ * We expect this to be called only for user addresses or kernel virtual ++ * addresses other than the linear mapping. ++ */ ++#define pte_pagesize_index(mm, addr, pte) \ ++ ({ \ ++ unsigned int psize; \ ++ if (is_kernel_addr(addr)) \ ++ psize = MMU_PAGE_4K; \ ++ else \ ++ psize = get_slice_psize(mm, addr); \ ++ psize; \ ++ }) + #else + #define pte_pagesize_index(mm, addr, pte) MMU_PAGE_4K + #endif +diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h +index 9bd52c65e66f..14de1385dedb 100644 +--- a/arch/powerpc/include/asm/rtas.h ++++ b/arch/powerpc/include/asm/rtas.h +@@ -255,6 +255,7 @@ extern void rtas_power_off(void); + extern void rtas_halt(void); + extern void rtas_os_term(char *str); + extern int rtas_get_sensor(int sensor, int index, int *state); ++extern int rtas_get_sensor_fast(int sensor, int index, int *state); + extern int rtas_get_power_level(int powerdomain, int *level); + extern int rtas_set_power_level(int powerdomain, int level, int *setlevel); + extern bool rtas_indicator_present(int token, int *maxindex); +diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c +index 4cf674d7d5ae..c4bc8d6cfd79 100644 +--- a/arch/powerpc/kernel/rtas.c ++++ b/arch/powerpc/kernel/rtas.c +@@ -584,6 +584,23 @@ int rtas_get_sensor(int sensor, int index, int *state) + } + EXPORT_SYMBOL(rtas_get_sensor); + ++int rtas_get_sensor_fast(int sensor, int index, int *state) ++{ ++ int token = rtas_token("get-sensor-state"); ++ int rc; ++ ++ if (token == RTAS_UNKNOWN_SERVICE) ++ return -ENOENT; ++ ++ rc = rtas_call(token, 2, 2, state, sensor, index); ++ WARN_ON(rc == RTAS_BUSY || (rc >= RTAS_EXTENDED_DELAY_MIN && ++ rc <= RTAS_EXTENDED_DELAY_MAX)); ++ ++ if (rc < 0) ++ return rtas_error_rc(rc); ++ return rc; ++} ++ + bool rtas_indicator_present(int token, int *maxindex) + { + int proplen, count, i; +diff --git a/arch/powerpc/mm/hugepage-hash64.c b/arch/powerpc/mm/hugepage-hash64.c +index 5f5e6328c21c..5061c6f676da 100644 +--- a/arch/powerpc/mm/hugepage-hash64.c ++++ b/arch/powerpc/mm/hugepage-hash64.c +@@ -136,7 +136,6 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, + BUG_ON(index >= 4096); + + vpn = hpt_vpn(ea, vsid, ssize); +- hash = hpt_hash(vpn, shift, ssize); + hpte_slot_array = get_hpte_slot_array(pmdp); + if (psize == MMU_PAGE_4K) { + /* +@@ -151,6 +150,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, + valid = hpte_valid(hpte_slot_array, index); + if (valid) { + /* update the hpte bits */ ++ hash = hpt_hash(vpn, shift, ssize); + hidx = hpte_hash_index(hpte_slot_array, index); + if (hidx & _PTEIDX_SECONDARY) + hash = ~hash; +@@ -176,6 +176,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, + if (!valid) { + unsigned long hpte_group; + ++ hash = hpt_hash(vpn, shift, ssize); + /* insert new entry */ + pa = pmd_pfn(__pmd(old_pmd)) << PAGE_SHIFT; + new_pmd |= _PAGE_HASHPTE; +diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c +index 721c0586b284..50fd3ac7b7bf 100644 +--- a/arch/powerpc/platforms/pseries/ras.c ++++ b/arch/powerpc/platforms/pseries/ras.c +@@ -187,7 +187,8 @@ static irqreturn_t ras_epow_interrupt(int irq, void *dev_id) + int state; + int critical; + +- status = rtas_get_sensor(EPOW_SENSOR_TOKEN, EPOW_SENSOR_INDEX, &state); ++ status = rtas_get_sensor_fast(EPOW_SENSOR_TOKEN, EPOW_SENSOR_INDEX, ++ &state); + + if (state > 3) + critical = 1; /* Time Critical */ +diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S +index 06469ee0f26e..6d6ab2b0bdfa 100644 +--- a/arch/x86/kernel/entry_64.S ++++ b/arch/x86/kernel/entry_64.S +@@ -1702,11 +1702,12 @@ ENTRY(nmi) + * If the variable is not set and the stack is not the NMI + * stack then: + * o Set the special variable on the stack +- * o Copy the interrupt frame into a "saved" location on the stack +- * o Copy the interrupt frame into a "copy" location on the stack ++ * o Copy the interrupt frame into an "outermost" location on the ++ * stack ++ * o Copy the interrupt frame into an "iret" location on the stack + * o Continue processing the NMI + * If the variable is set or the previous stack is the NMI stack: +- * o Modify the "copy" location to jump to the repeate_nmi ++ * o Modify the "iret" location to jump to the repeat_nmi + * o return back to the first NMI + * + * Now on exit of the first NMI, we first clear the stack variable +@@ -1715,52 +1716,184 @@ ENTRY(nmi) + * a nested NMI that updated the copy interrupt stack frame, a + * jump will be made to the repeat_nmi code that will handle the second + * NMI. ++ * ++ * However, espfix prevents us from directly returning to userspace ++ * with a single IRET instruction. Similarly, IRET to user mode ++ * can fault. We therefore handle NMIs from user space like ++ * other IST entries. + */ + + /* Use %rdx as out temp variable throughout */ + pushq_cfi %rdx + CFI_REL_OFFSET rdx, 0 + ++ testb $3, CS-RIP+8(%rsp) ++ jz .Lnmi_from_kernel ++ ++ /* ++ * NMI from user mode. We need to run on the thread stack, but we ++ * can't go through the normal entry paths: NMIs are masked, and ++ * we don't want to enable interrupts, because then we'll end ++ * up in an awkward situation in which IRQs are on but NMIs ++ * are off. ++ */ ++ SWAPGS ++ cld ++ movq %rsp, %rdx ++ movq PER_CPU_VAR(kernel_stack), %rsp ++ addq $KERNEL_STACK_OFFSET, %rsp ++ pushq 5*8(%rdx) /* pt_regs->ss */ ++ pushq 4*8(%rdx) /* pt_regs->rsp */ ++ pushq 3*8(%rdx) /* pt_regs->flags */ ++ pushq 2*8(%rdx) /* pt_regs->cs */ ++ pushq 1*8(%rdx) /* pt_regs->rip */ ++ pushq $-1 /* pt_regs->orig_ax */ ++ pushq %rdi /* pt_regs->di */ ++ pushq %rsi /* pt_regs->si */ ++ pushq (%rdx) /* pt_regs->dx */ ++ pushq %rcx /* pt_regs->cx */ ++ pushq %rax /* pt_regs->ax */ ++ pushq %r8 /* pt_regs->r8 */ ++ pushq %r9 /* pt_regs->r9 */ ++ pushq %r10 /* pt_regs->r10 */ ++ pushq %r11 /* pt_regs->r11 */ ++ pushq %rbx /* pt_regs->rbx */ ++ pushq %rbp /* pt_regs->rbp */ ++ pushq %r12 /* pt_regs->r12 */ ++ pushq %r13 /* pt_regs->r13 */ ++ pushq %r14 /* pt_regs->r14 */ ++ pushq %r15 /* pt_regs->r15 */ ++ ++ /* ++ * At this point we no longer need to worry about stack damage ++ * due to nesting -- we're on the normal thread stack and we're ++ * done with the NMI stack. ++ */ ++ movq %rsp, %rdi ++ movq $-1, %rsi ++ call do_nmi ++ ++ /* ++ * Return back to user mode. We must *not* do the normal exit ++ * work, because we don't want to enable interrupts. Fortunately, ++ * do_nmi doesn't modify pt_regs. ++ */ ++ SWAPGS ++ ++ /* ++ * Open-code the entire return process for compatibility with varying ++ * register layouts across different kernel versions. ++ */ ++ addq $6*8, %rsp /* skip bx, bp, and r12-r15 */ ++ popq %r11 /* pt_regs->r11 */ ++ popq %r10 /* pt_regs->r10 */ ++ popq %r9 /* pt_regs->r9 */ ++ popq %r8 /* pt_regs->r8 */ ++ popq %rax /* pt_regs->ax */ ++ popq %rcx /* pt_regs->cx */ ++ popq %rdx /* pt_regs->dx */ ++ popq %rsi /* pt_regs->si */ ++ popq %rdi /* pt_regs->di */ ++ addq $8, %rsp /* skip orig_ax */ ++ INTERRUPT_RETURN ++ ++.Lnmi_from_kernel: + /* +- * If %cs was not the kernel segment, then the NMI triggered in user +- * space, which means it is definitely not nested. ++ * Here's what our stack frame will look like: ++ * +---------------------------------------------------------+ ++ * | original SS | ++ * | original Return RSP | ++ * | original RFLAGS | ++ * | original CS | ++ * | original RIP | ++ * +---------------------------------------------------------+ ++ * | temp storage for rdx | ++ * +---------------------------------------------------------+ ++ * | "NMI executing" variable | ++ * +---------------------------------------------------------+ ++ * | iret SS } Copied from "outermost" frame | ++ * | iret Return RSP } on each loop iteration; overwritten | ++ * | iret RFLAGS } by a nested NMI to force another | ++ * | iret CS } iteration if needed. | ++ * | iret RIP } | ++ * +---------------------------------------------------------+ ++ * | outermost SS } initialized in first_nmi; | ++ * | outermost Return RSP } will not be changed before | ++ * | outermost RFLAGS } NMI processing is done. | ++ * | outermost CS } Copied to "iret" frame on each | ++ * | outermost RIP } iteration. | ++ * +---------------------------------------------------------+ ++ * | pt_regs | ++ * +---------------------------------------------------------+ ++ * ++ * The "original" frame is used by hardware. Before re-enabling ++ * NMIs, we need to be done with it, and we need to leave enough ++ * space for the asm code here. ++ * ++ * We return by executing IRET while RSP points to the "iret" frame. ++ * That will either return for real or it will loop back into NMI ++ * processing. ++ * ++ * The "outermost" frame is copied to the "iret" frame on each ++ * iteration of the loop, so each iteration starts with the "iret" ++ * frame pointing to the final return target. + */ +- cmpl $__KERNEL_CS, 16(%rsp) +- jne first_nmi + + /* +- * Check the special variable on the stack to see if NMIs are +- * executing. ++ * Determine whether we're a nested NMI. ++ * ++ * If we interrupted kernel code between repeat_nmi and ++ * end_repeat_nmi, then we are a nested NMI. We must not ++ * modify the "iret" frame because it's being written by ++ * the outer NMI. That's okay; the outer NMI handler is ++ * about to about to call do_nmi anyway, so we can just ++ * resume the outer NMI. ++ */ ++ movq $repeat_nmi, %rdx ++ cmpq 8(%rsp), %rdx ++ ja 1f ++ movq $end_repeat_nmi, %rdx ++ cmpq 8(%rsp), %rdx ++ ja nested_nmi_out ++1: ++ ++ /* ++ * Now check "NMI executing". If it's set, then we're nested. ++ * This will not detect if we interrupted an outer NMI just ++ * before IRET. + */ + cmpl $1, -8(%rsp) + je nested_nmi + + /* +- * Now test if the previous stack was an NMI stack. +- * We need the double check. We check the NMI stack to satisfy the +- * race when the first NMI clears the variable before returning. +- * We check the variable because the first NMI could be in a +- * breakpoint routine using a breakpoint stack. ++ * Now test if the previous stack was an NMI stack. This covers ++ * the case where we interrupt an outer NMI after it clears ++ * "NMI executing" but before IRET. We need to be careful, though: ++ * there is one case in which RSP could point to the NMI stack ++ * despite there being no NMI active: naughty userspace controls ++ * RSP at the very beginning of the SYSCALL targets. We can ++ * pull a fast one on naughty userspace, though: we program ++ * SYSCALL to mask DF, so userspace cannot cause DF to be set ++ * if it controls the kernel's RSP. We set DF before we clear ++ * "NMI executing". + */ + lea 6*8(%rsp), %rdx + test_in_nmi rdx, 4*8(%rsp), nested_nmi, first_nmi ++ ++ /* Ah, it is within the NMI stack. */ ++ ++ testb $(X86_EFLAGS_DF >> 8), (3*8 + 1)(%rsp) ++ jz first_nmi /* RSP was user controlled. */ ++ ++ /* This is a nested NMI. */ ++ + CFI_REMEMBER_STATE + + nested_nmi: + /* +- * Do nothing if we interrupted the fixup in repeat_nmi. +- * It's about to repeat the NMI handler, so we are fine +- * with ignoring this one. ++ * Modify the "iret" frame to point to repeat_nmi, forcing another ++ * iteration of NMI handling. + */ +- movq $repeat_nmi, %rdx +- cmpq 8(%rsp), %rdx +- ja 1f +- movq $end_repeat_nmi, %rdx +- cmpq 8(%rsp), %rdx +- ja nested_nmi_out +- +-1: +- /* Set up the interrupted NMIs stack to jump to repeat_nmi */ + leaq -1*8(%rsp), %rdx + movq %rdx, %rsp + CFI_ADJUST_CFA_OFFSET 1*8 +@@ -1779,60 +1912,23 @@ nested_nmi_out: + popq_cfi %rdx + CFI_RESTORE rdx + +- /* No need to check faults here */ ++ /* We are returning to kernel mode, so this cannot result in a fault. */ + INTERRUPT_RETURN + + CFI_RESTORE_STATE + first_nmi: +- /* +- * Because nested NMIs will use the pushed location that we +- * stored in rdx, we must keep that space available. +- * Here's what our stack frame will look like: +- * +-------------------------+ +- * | original SS | +- * | original Return RSP | +- * | original RFLAGS | +- * | original CS | +- * | original RIP | +- * +-------------------------+ +- * | temp storage for rdx | +- * +-------------------------+ +- * | NMI executing variable | +- * +-------------------------+ +- * | copied SS | +- * | copied Return RSP | +- * | copied RFLAGS | +- * | copied CS | +- * | copied RIP | +- * +-------------------------+ +- * | Saved SS | +- * | Saved Return RSP | +- * | Saved RFLAGS | +- * | Saved CS | +- * | Saved RIP | +- * +-------------------------+ +- * | pt_regs | +- * +-------------------------+ +- * +- * The saved stack frame is used to fix up the copied stack frame +- * that a nested NMI may change to make the interrupted NMI iret jump +- * to the repeat_nmi. The original stack frame and the temp storage +- * is also used by nested NMIs and can not be trusted on exit. +- */ +- /* Do not pop rdx, nested NMIs will corrupt that part of the stack */ ++ /* Restore rdx. */ + movq (%rsp), %rdx + CFI_RESTORE rdx + +- /* Set the NMI executing variable on the stack. */ ++ /* Set "NMI executing" on the stack. */ + pushq_cfi $1 + +- /* +- * Leave room for the "copied" frame +- */ ++ /* Leave room for the "iret" frame */ + subq $(5*8), %rsp + CFI_ADJUST_CFA_OFFSET 5*8 + +- /* Copy the stack frame to the Saved frame */ ++ /* Copy the "original" frame to the "outermost" frame */ + .rept 5 + pushq_cfi 11*8(%rsp) + .endr +@@ -1840,6 +1936,7 @@ first_nmi: + + /* Everything up to here is safe from nested NMIs */ + ++repeat_nmi: + /* + * If there was a nested NMI, the first NMI's iret will return + * here. But NMIs are still enabled and we can take another +@@ -1848,16 +1945,21 @@ first_nmi: + * it will just return, as we are about to repeat an NMI anyway. + * This makes it safe to copy to the stack frame that a nested + * NMI will update. +- */ +-repeat_nmi: +- /* +- * Update the stack variable to say we are still in NMI (the update +- * is benign for the non-repeat case, where 1 was pushed just above +- * to this very stack slot). ++ * ++ * RSP is pointing to "outermost RIP". gsbase is unknown, but, if ++ * we're repeating an NMI, gsbase has the same value that it had on ++ * the first iteration. paranoid_entry will load the kernel ++ * gsbase if needed before we call do_nmi. ++ * ++ * Set "NMI executing" in case we came back here via IRET. + */ + movq $1, 10*8(%rsp) + +- /* Make another copy, this one may be modified by nested NMIs */ ++ /* ++ * Copy the "outermost" frame to the "iret" frame. NMIs that nest ++ * here must not modify the "iret" frame while we're writing to ++ * it or it will end up containing garbage. ++ */ + addq $(10*8), %rsp + CFI_ADJUST_CFA_OFFSET -10*8 + .rept 5 +@@ -1868,9 +1970,9 @@ repeat_nmi: + end_repeat_nmi: + + /* +- * Everything below this point can be preempted by a nested +- * NMI if the first NMI took an exception and reset our iret stack +- * so that we repeat another NMI. ++ * Everything below this point can be preempted by a nested NMI. ++ * If this happens, then the inner NMI will change the "iret" ++ * frame to point back to repeat_nmi. + */ + pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */ + subq $ORIG_RAX-R15, %rsp +@@ -1885,28 +1987,10 @@ end_repeat_nmi: + call save_paranoid + DEFAULT_FRAME 0 + +- /* +- * Save off the CR2 register. If we take a page fault in the NMI then +- * it could corrupt the CR2 value. If the NMI preempts a page fault +- * handler before it was able to read the CR2 register, and then the +- * NMI itself takes a page fault, the page fault that was preempted +- * will read the information from the NMI page fault and not the +- * origin fault. Save it off and restore it if it changes. +- * Use the r12 callee-saved register. +- */ +- movq %cr2, %r12 +- + /* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */ + movq %rsp,%rdi + movq $-1,%rsi + call do_nmi +- +- /* Did the NMI take a page fault? Restore cr2 if it did */ +- movq %cr2, %rcx +- cmpq %rcx, %r12 +- je 1f +- movq %r12, %cr2 +-1: + + testl %ebx,%ebx /* swapgs needed? */ + jnz nmi_restore +@@ -1916,9 +2000,23 @@ nmi_restore: + /* Pop the extra iret frame at once */ + RESTORE_ALL 6*8 + +- /* Clear the NMI executing stack variable */ +- movq $0, 5*8(%rsp) +- jmp irq_return ++ /* ++ * Clear "NMI executing". Set DF first so that we can easily ++ * distinguish the remaining code between here and IRET from ++ * the SYSCALL entry and exit paths. On a native kernel, we ++ * could just inspect RIP, but, on paravirt kernels, ++ * INTERRUPT_RETURN can translate into a jump into a ++ * hypercall page. ++ */ ++ std ++ movq $0, 5*8(%rsp) /* clear "NMI executing" */ ++ ++ /* ++ * INTERRUPT_RETURN reads the "iret" frame and exits the NMI ++ * stack in a single instruction. We are returning to kernel ++ * mode, so this cannot result in a fault. ++ */ ++ INTERRUPT_RETURN + CFI_ENDPROC + END(nmi) + +diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c +index 6fcb49ce50a1..8facfb318a97 100644 +--- a/arch/x86/kernel/nmi.c ++++ b/arch/x86/kernel/nmi.c +@@ -392,15 +392,15 @@ static __kprobes void default_do_nmi(struct pt_regs *regs) + } + + /* +- * NMIs can hit breakpoints which will cause it to lose its +- * NMI context with the CPU when the breakpoint does an iret. +- */ +-#ifdef CONFIG_X86_32 +-/* +- * For i386, NMIs use the same stack as the kernel, and we can +- * add a workaround to the iret problem in C (preventing nested +- * NMIs if an NMI takes a trap). Simply have 3 states the NMI +- * can be in: ++ * NMIs can page fault or hit breakpoints which will cause it to lose ++ * its NMI context with the CPU when the breakpoint or page fault does an IRET. ++ * ++ * As a result, NMIs can nest if NMIs get unmasked due an IRET during ++ * NMI processing. On x86_64, the asm glue protects us from nested NMIs ++ * if the outer NMI came from kernel mode, but we can still nest if the ++ * outer NMI came from user mode. ++ * ++ * To handle these nested NMIs, we have three states: + * + * 1) not running + * 2) executing +@@ -414,15 +414,14 @@ static __kprobes void default_do_nmi(struct pt_regs *regs) + * (Note, the latch is binary, thus multiple NMIs triggering, + * when one is running, are ignored. Only one NMI is restarted.) + * +- * If an NMI hits a breakpoint that executes an iret, another +- * NMI can preempt it. We do not want to allow this new NMI +- * to run, but we want to execute it when the first one finishes. +- * We set the state to "latched", and the exit of the first NMI will +- * perform a dec_return, if the result is zero (NOT_RUNNING), then +- * it will simply exit the NMI handler. If not, the dec_return +- * would have set the state to NMI_EXECUTING (what we want it to +- * be when we are running). In this case, we simply jump back +- * to rerun the NMI handler again, and restart the 'latched' NMI. ++ * If an NMI executes an iret, another NMI can preempt it. We do not ++ * want to allow this new NMI to run, but we want to execute it when the ++ * first one finishes. We set the state to "latched", and the exit of ++ * the first NMI will perform a dec_return, if the result is zero ++ * (NOT_RUNNING), then it will simply exit the NMI handler. If not, the ++ * dec_return would have set the state to NMI_EXECUTING (what we want it ++ * to be when we are running). In this case, we simply jump back to ++ * rerun the NMI handler again, and restart the 'latched' NMI. + * + * No trap (breakpoint or page fault) should be hit before nmi_restart, + * thus there is no race between the first check of state for NOT_RUNNING +@@ -445,49 +444,36 @@ enum nmi_states { + static DEFINE_PER_CPU(enum nmi_states, nmi_state); + static DEFINE_PER_CPU(unsigned long, nmi_cr2); + +-#define nmi_nesting_preprocess(regs) \ +- do { \ +- if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) { \ +- this_cpu_write(nmi_state, NMI_LATCHED); \ +- return; \ +- } \ +- this_cpu_write(nmi_state, NMI_EXECUTING); \ +- this_cpu_write(nmi_cr2, read_cr2()); \ +- } while (0); \ +- nmi_restart: +- +-#define nmi_nesting_postprocess() \ +- do { \ +- if (unlikely(this_cpu_read(nmi_cr2) != read_cr2())) \ +- write_cr2(this_cpu_read(nmi_cr2)); \ +- if (this_cpu_dec_return(nmi_state)) \ +- goto nmi_restart; \ +- } while (0) +-#else /* x86_64 */ ++#ifdef CONFIG_X86_64 + /* +- * In x86_64 things are a bit more difficult. This has the same problem +- * where an NMI hitting a breakpoint that calls iret will remove the +- * NMI context, allowing a nested NMI to enter. What makes this more +- * difficult is that both NMIs and breakpoints have their own stack. +- * When a new NMI or breakpoint is executed, the stack is set to a fixed +- * point. If an NMI is nested, it will have its stack set at that same +- * fixed address that the first NMI had, and will start corrupting the +- * stack. This is handled in entry_64.S, but the same problem exists with +- * the breakpoint stack. ++ * In x86_64, we need to handle breakpoint -> NMI -> breakpoint. Without ++ * some care, the inner breakpoint will clobber the outer breakpoint's ++ * stack. + * +- * If a breakpoint is being processed, and the debug stack is being used, +- * if an NMI comes in and also hits a breakpoint, the stack pointer +- * will be set to the same fixed address as the breakpoint that was +- * interrupted, causing that stack to be corrupted. To handle this case, +- * check if the stack that was interrupted is the debug stack, and if +- * so, change the IDT so that new breakpoints will use the current stack +- * and not switch to the fixed address. On return of the NMI, switch back +- * to the original IDT. ++ * If a breakpoint is being processed, and the debug stack is being ++ * used, if an NMI comes in and also hits a breakpoint, the stack ++ * pointer will be set to the same fixed address as the breakpoint that ++ * was interrupted, causing that stack to be corrupted. To handle this ++ * case, check if the stack that was interrupted is the debug stack, and ++ * if so, change the IDT so that new breakpoints will use the current ++ * stack and not switch to the fixed address. On return of the NMI, ++ * switch back to the original IDT. + */ + static DEFINE_PER_CPU(int, update_debug_stack); ++#endif + +-static inline void nmi_nesting_preprocess(struct pt_regs *regs) ++dotraplinkage notrace void ++do_nmi(struct pt_regs *regs, long error_code) + { ++ if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) { ++ this_cpu_write(nmi_state, NMI_LATCHED); ++ return; ++ } ++ this_cpu_write(nmi_state, NMI_EXECUTING); ++ this_cpu_write(nmi_cr2, read_cr2()); ++nmi_restart: ++ ++#ifdef CONFIG_X86_64 + /* + * If we interrupted a breakpoint, it is possible that + * the nmi handler will have breakpoints too. We need to +@@ -498,22 +484,8 @@ static inline void nmi_nesting_preprocess(struct pt_regs *regs) + debug_stack_set_zero(); + this_cpu_write(update_debug_stack, 1); + } +-} +- +-static inline void nmi_nesting_postprocess(void) +-{ +- if (unlikely(this_cpu_read(update_debug_stack))) { +- debug_stack_reset(); +- this_cpu_write(update_debug_stack, 0); +- } +-} + #endif + +-dotraplinkage notrace __kprobes void +-do_nmi(struct pt_regs *regs, long error_code) +-{ +- nmi_nesting_preprocess(regs); +- + nmi_enter(); + + inc_irq_stat(__nmi_count); +@@ -523,8 +495,17 @@ do_nmi(struct pt_regs *regs, long error_code) + + nmi_exit(); + +- /* On i386, may loop back to preprocess */ +- nmi_nesting_postprocess(); ++#ifdef CONFIG_X86_64 ++ if (unlikely(this_cpu_read(update_debug_stack))) { ++ debug_stack_reset(); ++ this_cpu_write(update_debug_stack, 0); ++ } ++#endif ++ ++ if (unlikely(this_cpu_read(nmi_cr2) != read_cr2())) ++ write_cr2(this_cpu_read(nmi_cr2)); ++ if (this_cpu_dec_return(nmi_state)) ++ goto nmi_restart; + } + + void stop_nmi(void) +diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c +index e39504878aec..a7b5b3071072 100644 +--- a/arch/x86/mm/init_32.c ++++ b/arch/x86/mm/init_32.c +@@ -137,6 +137,7 @@ page_table_range_init_count(unsigned long start, unsigned long end) + + vaddr = start; + pgd_idx = pgd_index(vaddr); ++ pmd_idx = pmd_index(vaddr); + + for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd_idx++) { + for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); +diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c +index b91ce75bd35d..d2102c4eefbf 100644 +--- a/block/blk-mq-sysfs.c ++++ b/block/blk-mq-sysfs.c +@@ -141,15 +141,26 @@ static ssize_t blk_mq_sysfs_completed_show(struct blk_mq_ctx *ctx, char *page) + + static ssize_t sysfs_list_show(char *page, struct list_head *list, char *msg) + { +- char *start_page = page; + struct request *rq; ++ int len = snprintf(page, PAGE_SIZE - 1, "%s:\n", msg); ++ ++ list_for_each_entry(rq, list, queuelist) { ++ const int rq_len = 2 * sizeof(rq) + 2; ++ ++ /* if the output will be truncated */ ++ if (PAGE_SIZE - 1 < len + rq_len) { ++ /* backspacing if it can't hold '\t...\n' */ ++ if (PAGE_SIZE - 1 < len + 5) ++ len -= rq_len; ++ len += snprintf(page + len, PAGE_SIZE - 1 - len, ++ "\t...\n"); ++ break; ++ } ++ len += snprintf(page + len, PAGE_SIZE - 1 - len, ++ "\t%p\n", rq); ++ } + +- page += sprintf(page, "%s:\n", msg); +- +- list_for_each_entry(rq, list, queuelist) +- page += sprintf(page, "\t%p\n", rq); +- +- return page - start_page; ++ return len; + } + + static ssize_t blk_mq_sysfs_rq_list_show(struct blk_mq_ctx *ctx, char *page) +diff --git a/drivers/base/node.c b/drivers/base/node.c +index bc9f43bf7e29..5f5160c9455f 100644 +--- a/drivers/base/node.c ++++ b/drivers/base/node.c +@@ -399,6 +399,16 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid) + for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { + int page_nid; + ++ /* ++ * memory block could have several absent sections from start. ++ * skip pfn range from absent section ++ */ ++ if (!pfn_present(pfn)) { ++ pfn = round_down(pfn + PAGES_PER_SECTION, ++ PAGES_PER_SECTION) - 1; ++ continue; ++ } ++ + page_nid = get_nid_for_pfn(pfn); + if (page_nid < 0) + continue; +diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c +index 51824d1f23ea..2d3385d3c6a9 100644 +--- a/drivers/block/nvme-core.c ++++ b/drivers/block/nvme-core.c +@@ -2464,6 +2464,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) + if (result) + goto release; + ++ kref_init(&dev->kref); + result = nvme_dev_start(dev); + if (result) { + if (result == -EBUSY) +@@ -2471,7 +2472,6 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) + goto release_pools; + } + +- kref_init(&dev->kref); + result = nvme_dev_add(dev); + if (result) + goto shutdown; +diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c +index 79a266934327..fd2820ff9e5b 100644 +--- a/drivers/gpu/drm/radeon/radeon_combios.c ++++ b/drivers/gpu/drm/radeon/radeon_combios.c +@@ -3387,6 +3387,14 @@ void radeon_combios_asic_init(struct drm_device *dev) + rdev->pdev->subsystem_device == 0x30ae) + return; + ++ /* quirk for rs4xx HP Compaq dc5750 Small Form Factor to make it resume ++ * - it hangs on resume inside the dynclk 1 table. ++ */ ++ if (rdev->family == CHIP_RS480 && ++ rdev->pdev->subsystem_vendor == 0x103c && ++ rdev->pdev->subsystem_device == 0x280a) ++ return; ++ + /* DYN CLK 1 */ + table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE); + if (table) +diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig +index 6f64c5cc5387..ac2d69e34c8c 100644 +--- a/drivers/iio/gyro/Kconfig ++++ b/drivers/iio/gyro/Kconfig +@@ -93,8 +93,7 @@ config IIO_ST_GYRO_SPI_3AXIS + config ITG3200 + tristate "InvenSense ITG3200 Digital 3-Axis Gyroscope I2C driver" + depends on I2C +- select IIO_BUFFER +- select IIO_TRIGGERED_BUFFER ++ select IIO_TRIGGERED_BUFFER if IIO_BUFFER + help + Say yes here to add support for the InvenSense ITG3200 digital + 3-axis gyroscope sensor. +diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h +index a283274a5a09..639557bdc0cd 100644 +--- a/drivers/infiniband/core/uverbs.h ++++ b/drivers/infiniband/core/uverbs.h +@@ -85,7 +85,7 @@ + */ + + struct ib_uverbs_device { +- struct kref ref; ++ atomic_t refcount; + int num_comp_vectors; + struct completion comp; + struct device *dev; +@@ -94,6 +94,7 @@ struct ib_uverbs_device { + struct cdev cdev; + struct rb_root xrcd_tree; + struct mutex xrcd_tree_mutex; ++ struct kobject kobj; + }; + + struct ib_uverbs_event_file { +diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c +index 2adc14372b94..5e66eab292d8 100644 +--- a/drivers/infiniband/core/uverbs_cmd.c ++++ b/drivers/infiniband/core/uverbs_cmd.c +@@ -2111,6 +2111,12 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, + next->send_flags = user_wr->send_flags; + + if (is_ud) { ++ if (next->opcode != IB_WR_SEND && ++ next->opcode != IB_WR_SEND_WITH_IMM) { ++ ret = -EINVAL; ++ goto out_put; ++ } ++ + next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah, + file->ucontext); + if (!next->wr.ud.ah) { +@@ -2150,9 +2156,11 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, + user_wr->wr.atomic.compare_add; + next->wr.atomic.swap = user_wr->wr.atomic.swap; + next->wr.atomic.rkey = user_wr->wr.atomic.rkey; ++ case IB_WR_SEND: + break; + default: +- break; ++ ret = -EINVAL; ++ goto out_put; + } + } + +diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c +index 7a515c867674..8802d5ccd93d 100644 +--- a/drivers/infiniband/core/uverbs_main.c ++++ b/drivers/infiniband/core/uverbs_main.c +@@ -127,14 +127,18 @@ static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file, + static void ib_uverbs_add_one(struct ib_device *device); + static void ib_uverbs_remove_one(struct ib_device *device); + +-static void ib_uverbs_release_dev(struct kref *ref) ++static void ib_uverbs_release_dev(struct kobject *kobj) + { + struct ib_uverbs_device *dev = +- container_of(ref, struct ib_uverbs_device, ref); ++ container_of(kobj, struct ib_uverbs_device, kobj); + +- complete(&dev->comp); ++ kfree(dev); + } + ++static struct kobj_type ib_uverbs_dev_ktype = { ++ .release = ib_uverbs_release_dev, ++}; ++ + static void ib_uverbs_release_event_file(struct kref *ref) + { + struct ib_uverbs_event_file *file = +@@ -298,13 +302,19 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, + return context->device->dealloc_ucontext(context); + } + ++static void ib_uverbs_comp_dev(struct ib_uverbs_device *dev) ++{ ++ complete(&dev->comp); ++} ++ + static void ib_uverbs_release_file(struct kref *ref) + { + struct ib_uverbs_file *file = + container_of(ref, struct ib_uverbs_file, ref); + + module_put(file->device->ib_dev->owner); +- kref_put(&file->device->ref, ib_uverbs_release_dev); ++ if (atomic_dec_and_test(&file->device->refcount)) ++ ib_uverbs_comp_dev(file->device); + + kfree(file); + } +@@ -734,9 +744,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) + int ret; + + dev = container_of(inode->i_cdev, struct ib_uverbs_device, cdev); +- if (dev) +- kref_get(&dev->ref); +- else ++ if (!atomic_inc_not_zero(&dev->refcount)) + return -ENXIO; + + if (!try_module_get(dev->ib_dev->owner)) { +@@ -757,6 +765,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) + mutex_init(&file->mutex); + + filp->private_data = file; ++ kobject_get(&dev->kobj); + + return nonseekable_open(inode, filp); + +@@ -764,13 +773,16 @@ err_module: + module_put(dev->ib_dev->owner); + + err: +- kref_put(&dev->ref, ib_uverbs_release_dev); ++ if (atomic_dec_and_test(&dev->refcount)) ++ ib_uverbs_comp_dev(dev); ++ + return ret; + } + + static int ib_uverbs_close(struct inode *inode, struct file *filp) + { + struct ib_uverbs_file *file = filp->private_data; ++ struct ib_uverbs_device *dev = file->device; + + ib_uverbs_cleanup_ucontext(file, file->ucontext); + +@@ -778,6 +790,7 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp) + kref_put(&file->async_file->ref, ib_uverbs_release_event_file); + + kref_put(&file->ref, ib_uverbs_release_file); ++ kobject_put(&dev->kobj); + + return 0; + } +@@ -873,10 +886,11 @@ static void ib_uverbs_add_one(struct ib_device *device) + if (!uverbs_dev) + return; + +- kref_init(&uverbs_dev->ref); ++ atomic_set(&uverbs_dev->refcount, 1); + init_completion(&uverbs_dev->comp); + uverbs_dev->xrcd_tree = RB_ROOT; + mutex_init(&uverbs_dev->xrcd_tree_mutex); ++ kobject_init(&uverbs_dev->kobj, &ib_uverbs_dev_ktype); + + spin_lock(&map_lock); + devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES); +@@ -903,6 +917,7 @@ static void ib_uverbs_add_one(struct ib_device *device) + cdev_init(&uverbs_dev->cdev, NULL); + uverbs_dev->cdev.owner = THIS_MODULE; + uverbs_dev->cdev.ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops; ++ uverbs_dev->cdev.kobj.parent = &uverbs_dev->kobj; + kobject_set_name(&uverbs_dev->cdev.kobj, "uverbs%d", uverbs_dev->devnum); + if (cdev_add(&uverbs_dev->cdev, base, 1)) + goto err_cdev; +@@ -933,9 +948,10 @@ err_cdev: + clear_bit(devnum, overflow_map); + + err: +- kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); ++ if (atomic_dec_and_test(&uverbs_dev->refcount)) ++ ib_uverbs_comp_dev(uverbs_dev); + wait_for_completion(&uverbs_dev->comp); +- kfree(uverbs_dev); ++ kobject_put(&uverbs_dev->kobj); + return; + } + +@@ -955,9 +971,10 @@ static void ib_uverbs_remove_one(struct ib_device *device) + else + clear_bit(uverbs_dev->devnum - IB_UVERBS_MAX_DEVICES, overflow_map); + +- kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); ++ if (atomic_dec_and_test(&uverbs_dev->refcount)) ++ ib_uverbs_comp_dev(uverbs_dev); + wait_for_completion(&uverbs_dev->comp); +- kfree(uverbs_dev); ++ kobject_put(&uverbs_dev->kobj); + } + + static char *uverbs_devnode(struct device *dev, umode_t *mode) +diff --git a/drivers/infiniband/hw/mlx4/ah.c b/drivers/infiniband/hw/mlx4/ah.c +index 170dca608042..1ddcebd84622 100644 +--- a/drivers/infiniband/hw/mlx4/ah.c ++++ b/drivers/infiniband/hw/mlx4/ah.c +@@ -147,9 +147,13 @@ int mlx4_ib_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr) + enum rdma_link_layer ll; + + memset(ah_attr, 0, sizeof *ah_attr); +- ah_attr->sl = be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 28; + ah_attr->port_num = be32_to_cpu(ah->av.ib.port_pd) >> 24; + ll = rdma_port_get_link_layer(ibah->device, ah_attr->port_num); ++ if (ll == IB_LINK_LAYER_ETHERNET) ++ ah_attr->sl = be32_to_cpu(ah->av.eth.sl_tclass_flowlabel) >> 29; ++ else ++ ah_attr->sl = be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 28; ++ + ah_attr->dlid = ll == IB_LINK_LAYER_INFINIBAND ? be16_to_cpu(ah->av.ib.dlid) : 0; + if (ah->av.ib.stat_rate) + ah_attr->static_rate = ah->av.ib.stat_rate - MLX4_STAT_RATE_OFFSET; +diff --git a/drivers/infiniband/hw/mlx4/sysfs.c b/drivers/infiniband/hw/mlx4/sysfs.c +index db2ea31df832..b5e50c605933 100644 +--- a/drivers/infiniband/hw/mlx4/sysfs.c ++++ b/drivers/infiniband/hw/mlx4/sysfs.c +@@ -563,6 +563,8 @@ static int add_port(struct mlx4_ib_dev *dev, int port_num, int slave) + struct mlx4_port *p; + int i; + int ret; ++ int is_eth = rdma_port_get_link_layer(&dev->ib_dev, port_num) == ++ IB_LINK_LAYER_ETHERNET; + + p = kzalloc(sizeof *p, GFP_KERNEL); + if (!p) +@@ -580,7 +582,8 @@ static int add_port(struct mlx4_ib_dev *dev, int port_num, int slave) + + p->pkey_group.name = "pkey_idx"; + p->pkey_group.attrs = +- alloc_group_attrs(show_port_pkey, store_port_pkey, ++ alloc_group_attrs(show_port_pkey, ++ is_eth ? NULL : store_port_pkey, + dev->dev->caps.pkey_table_len[port_num]); + if (!p->pkey_group.attrs) { + ret = -ENOMEM; +diff --git a/drivers/infiniband/hw/qib/qib_keys.c b/drivers/infiniband/hw/qib/qib_keys.c +index 3b9afccaaade..eabe54738be6 100644 +--- a/drivers/infiniband/hw/qib/qib_keys.c ++++ b/drivers/infiniband/hw/qib/qib_keys.c +@@ -86,6 +86,10 @@ int qib_alloc_lkey(struct qib_mregion *mr, int dma_region) + * unrestricted LKEY. + */ + rkt->gen++; ++ /* ++ * bits are capped in qib_verbs.c to insure enough bits ++ * for generation number ++ */ + mr->lkey = (r << (32 - ib_qib_lkey_table_size)) | + ((((1 << (24 - ib_qib_lkey_table_size)) - 1) & rkt->gen) + << 8); +diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c +index 092b0bb1bb78..c141b9b2493d 100644 +--- a/drivers/infiniband/hw/qib/qib_verbs.c ++++ b/drivers/infiniband/hw/qib/qib_verbs.c +@@ -40,6 +40,7 @@ + #include + #include + #include ++#include + + #include "qib.h" + #include "qib_common.h" +@@ -2086,10 +2087,16 @@ int qib_register_ib_device(struct qib_devdata *dd) + * the LKEY). The remaining bits act as a generation number or tag. + */ + spin_lock_init(&dev->lk_table.lock); ++ /* insure generation is at least 4 bits see keys.c */ ++ if (ib_qib_lkey_table_size > MAX_LKEY_TABLE_BITS) { ++ qib_dev_warn(dd, "lkey bits %u too large, reduced to %u\n", ++ ib_qib_lkey_table_size, MAX_LKEY_TABLE_BITS); ++ ib_qib_lkey_table_size = MAX_LKEY_TABLE_BITS; ++ } + dev->lk_table.max = 1 << ib_qib_lkey_table_size; + lk_tab_size = dev->lk_table.max * sizeof(*dev->lk_table.table); + dev->lk_table.table = (struct qib_mregion __rcu **) +- __get_free_pages(GFP_KERNEL, get_order(lk_tab_size)); ++ vmalloc(lk_tab_size); + if (dev->lk_table.table == NULL) { + ret = -ENOMEM; + goto err_lk; +@@ -2262,7 +2269,7 @@ err_tx: + sizeof(struct qib_pio_header), + dev->pio_hdrs, dev->pio_hdrs_phys); + err_hdrs: +- free_pages((unsigned long) dev->lk_table.table, get_order(lk_tab_size)); ++ vfree(dev->lk_table.table); + err_lk: + kfree(dev->qp_table); + err_qpt: +@@ -2316,8 +2323,7 @@ void qib_unregister_ib_device(struct qib_devdata *dd) + sizeof(struct qib_pio_header), + dev->pio_hdrs, dev->pio_hdrs_phys); + lk_tab_size = dev->lk_table.max * sizeof(*dev->lk_table.table); +- free_pages((unsigned long) dev->lk_table.table, +- get_order(lk_tab_size)); ++ vfree(dev->lk_table.table); + kfree(dev->qp_table); + } + +diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h +index a01c7d2cf541..d34bc69f1f17 100644 +--- a/drivers/infiniband/hw/qib/qib_verbs.h ++++ b/drivers/infiniband/hw/qib/qib_verbs.h +@@ -647,6 +647,8 @@ struct qib_qpn_table { + struct qpn_map map[QPNMAP_ENTRIES]; + }; + ++#define MAX_LKEY_TABLE_BITS 23 ++ + struct qib_lkey_table { + spinlock_t lock; /* protect changes in this struct */ + u32 next; /* next unused index (speeds search) */ +diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c +index fb787c3e88d9..bb9f073a4e13 100644 +--- a/drivers/input/evdev.c ++++ b/drivers/input/evdev.c +@@ -240,19 +240,14 @@ static int evdev_flush(struct file *file, fl_owner_t id) + { + struct evdev_client *client = file->private_data; + struct evdev *evdev = client->evdev; +- int retval; + +- retval = mutex_lock_interruptible(&evdev->mutex); +- if (retval) +- return retval; ++ mutex_lock(&evdev->mutex); + +- if (!evdev->exist || client->revoked) +- retval = -ENODEV; +- else +- retval = input_flush_device(&evdev->handle, file); ++ if (evdev->exist && !client->revoked) ++ input_flush_device(&evdev->handle, file); + + mutex_unlock(&evdev->mutex); +- return retval; ++ return 0; + } + + static void evdev_free(struct device *dev) +diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c +index 8c91fd5eb6fd..3ac9c4194814 100644 +--- a/drivers/isdn/gigaset/ser-gigaset.c ++++ b/drivers/isdn/gigaset/ser-gigaset.c +@@ -524,9 +524,18 @@ gigaset_tty_open(struct tty_struct *tty) + cs->hw.ser->tty = tty; + atomic_set(&cs->hw.ser->refcnt, 1); + init_completion(&cs->hw.ser->dead_cmp); +- + tty->disc_data = cs; + ++ /* Set the amount of data we're willing to receive per call ++ * from the hardware driver to half of the input buffer size ++ * to leave some reserve. ++ * Note: We don't do flow control towards the hardware driver. ++ * If more data is received than will fit into the input buffer, ++ * it will be dropped and an error will be logged. This should ++ * never happen as the device is slow and the buffer size ample. ++ */ ++ tty->receive_room = RBUFSIZE/2; ++ + /* OK.. Initialization of the datastructures and the HW is done.. Now + * startup system and notify the LL that we are ready to run + */ +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index a46124ecafc7..73c9f579b042 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -3585,6 +3585,7 @@ static struct r10conf *setup_conf(struct mddev *mddev) + /* far_copies must be 1 */ + conf->prev.stride = conf->dev_sectors; + } ++ conf->reshape_safe = conf->reshape_progress; + spin_lock_init(&conf->device_lock); + INIT_LIST_HEAD(&conf->retry_list); + +@@ -3793,7 +3794,6 @@ static int run(struct mddev *mddev) + } + conf->offset_diff = min_offset_diff; + +- conf->reshape_safe = conf->reshape_progress; + clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); + clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); + set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); +@@ -4138,6 +4138,7 @@ static int raid10_start_reshape(struct mddev *mddev) + conf->reshape_progress = size; + } else + conf->reshape_progress = 0; ++ conf->reshape_safe = conf->reshape_progress; + spin_unlock_irq(&conf->device_lock); + + if (mddev->delta_disks && mddev->bitmap) { +@@ -4204,6 +4205,7 @@ abort: + rdev->new_data_offset = rdev->data_offset; + smp_wmb(); + conf->reshape_progress = MaxSector; ++ conf->reshape_safe = MaxSector; + mddev->reshape_position = MaxSector; + spin_unlock_irq(&conf->device_lock); + return ret; +@@ -4556,6 +4558,7 @@ static void end_reshape(struct r10conf *conf) + md_finish_reshape(conf->mddev); + smp_wmb(); + conf->reshape_progress = MaxSector; ++ conf->reshape_safe = MaxSector; + spin_unlock_irq(&conf->device_lock); + + /* read-ahead size must cover two whole stripes, which is +diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c +index 5807185262fe..ee0015be1421 100644 +--- a/drivers/media/platform/omap3isp/isp.c ++++ b/drivers/media/platform/omap3isp/isp.c +@@ -824,14 +824,14 @@ static int isp_pipeline_link_notify(struct media_link *link, u32 flags, + int ret; + + if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && +- !(link->flags & MEDIA_LNK_FL_ENABLED)) { ++ !(flags & MEDIA_LNK_FL_ENABLED)) { + /* Powering off entities is assumed to never fail. */ + isp_pipeline_pm_power(source, -sink_use); + isp_pipeline_pm_power(sink, -source_use); + return 0; + } + +- if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && ++ if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH && + (flags & MEDIA_LNK_FL_ENABLED)) { + + ret = isp_pipeline_pm_power(source, sink_use); +diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c +index 02e2f38c9c85..bdd3609c7641 100644 +--- a/drivers/media/rc/rc-main.c ++++ b/drivers/media/rc/rc-main.c +@@ -982,9 +982,6 @@ static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) + { + struct rc_dev *dev = to_rc_dev(device); + +- if (!dev || !dev->input_dev) +- return -ENODEV; +- + if (dev->rc_map.name) + ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name); + if (dev->driver_name) +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index 6a881ebe5b02..4a50b5049c51 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -329,8 +329,10 @@ EXPORT_SYMBOL(mmc_start_bkops); + */ + static void mmc_wait_data_done(struct mmc_request *mrq) + { +- mrq->host->context_info.is_done_rcv = true; +- wake_up_interruptible(&mrq->host->context_info.wait); ++ struct mmc_context_info *context_info = &mrq->host->context_info; ++ ++ context_info->is_done_rcv = true; ++ wake_up_interruptible(&context_info->wait); + } + + static void mmc_wait_done(struct mmc_request *mrq) +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 32b0e7055b1e..0697d8f5f3cf 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -636,6 +636,23 @@ static void bond_set_dev_addr(struct net_device *bond_dev, + call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev); + } + ++static struct slave *bond_get_old_active(struct bonding *bond, ++ struct slave *new_active) ++{ ++ struct slave *slave; ++ struct list_head *iter; ++ ++ bond_for_each_slave(bond, slave, iter) { ++ if (slave == new_active) ++ continue; ++ ++ if (ether_addr_equal(bond->dev->dev_addr, slave->dev->dev_addr)) ++ return slave; ++ } ++ ++ return NULL; ++} ++ + /* + * bond_do_fail_over_mac + * +@@ -672,6 +689,9 @@ static void bond_do_fail_over_mac(struct bonding *bond, + + write_unlock_bh(&bond->curr_slave_lock); + ++ if (!old_active) ++ old_active = bond_get_old_active(bond, new_active); ++ + if (old_active) { + memcpy(tmp_mac, new_active->dev->dev_addr, ETH_ALEN); + memcpy(saddr.sa_data, old_active->dev->dev_addr, +@@ -1825,6 +1845,7 @@ static int bond_release_and_destroy(struct net_device *bond_dev, + bond_dev->priv_flags |= IFF_DISABLE_NETPOLL; + pr_info("%s: destroying bond %s.\n", + bond_dev->name, bond_dev->name); ++ bond_remove_proc_entry(bond); + unregister_netdevice(bond_dev); + } + return ret; +diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c +index bc65dc85a622..91e7286ab1e1 100644 +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -10737,7 +10737,7 @@ static ssize_t tg3_show_temp(struct device *dev, + tg3_ape_scratchpad_read(tp, &temperature, attr->index, + sizeof(temperature)); + spin_unlock_bh(&tp->lock); +- return sprintf(buf, "%u\n", temperature); ++ return sprintf(buf, "%u\n", temperature * 1000); + } + + +diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c +index 669eeb4eb247..f051783f5882 100644 +--- a/drivers/net/ethernet/brocade/bna/bnad.c ++++ b/drivers/net/ethernet/brocade/bna/bnad.c +@@ -674,6 +674,7 @@ bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget) + if (!next_cmpl->valid) + break; + } ++ packets++; + + /* TODO: BNA_CQ_EF_LOCAL ? */ + if (unlikely(flags & (BNA_CQ_EF_MAC_ERROR | +@@ -690,7 +691,6 @@ bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget) + else + bnad_cq_setup_skb_frags(rcb, skb, sop_ci, nvecs, len); + +- packets++; + rcb->rxq->rx_packets++; + rcb->rxq->rx_bytes += totlen; + ccb->bytes_per_intr += totlen; +diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c +index 8992b38578d5..e8a1baa87c95 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/eq.c ++++ b/drivers/net/ethernet/mellanox/mlx4/eq.c +@@ -557,7 +557,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) + mlx4_dbg(dev, "%s: Sending MLX4_PORT_CHANGE_SUBTYPE_DOWN" + " to slave: %d, port:%d\n", + __func__, i, port); +- s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state; ++ s_info = &priv->mfunc.master.vf_oper[i].vport[port].state; + if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state) + mlx4_slave_event(dev, i, eqe); + } else { /* IB port */ +@@ -583,7 +583,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) + for (i = 0; i < dev->num_slaves; i++) { + if (i == mlx4_master_func_num(dev)) + continue; +- s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state; ++ s_info = &priv->mfunc.master.vf_oper[i].vport[port].state; + if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state) + mlx4_slave_event(dev, i, eqe); + } +diff --git a/drivers/net/ethernet/stmicro/stmmac/descs.h b/drivers/net/ethernet/stmicro/stmmac/descs.h +index ad3996038018..799c2929c536 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/descs.h ++++ b/drivers/net/ethernet/stmicro/stmmac/descs.h +@@ -158,6 +158,8 @@ struct dma_desc { + u32 buffer2_size:13; + u32 reserved4:3; + } etx; /* -- enhanced -- */ ++ ++ u64 all_flags; + } des01; + unsigned int des2; + unsigned int des3; +diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c +index 7e6628a91514..59fb7f69841b 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c +@@ -240,6 +240,7 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x, + static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, + int mode, int end) + { ++ p->des01.all_flags = 0; + p->des01.erx.own = 1; + p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1; + +@@ -254,7 +255,7 @@ static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, + + static void enh_desc_init_tx_desc(struct dma_desc *p, int mode, int end) + { +- p->des01.etx.own = 0; ++ p->des01.all_flags = 0; + if (mode == STMMAC_CHAIN_MODE) + ehn_desc_tx_set_on_chain(p, end); + else +diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +index 35ad4f427ae2..48c3456445b2 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +@@ -123,6 +123,7 @@ static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x, + static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode, + int end) + { ++ p->des01.all_flags = 0; + p->des01.rx.own = 1; + p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1; + +@@ -137,7 +138,7 @@ static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode, + + static void ndesc_init_tx_desc(struct dma_desc *p, int mode, int end) + { +- p->des01.tx.own = 0; ++ p->des01.all_flags = 0; + if (mode == STMMAC_CHAIN_MODE) + ndesc_tx_set_on_chain(p, end); + else +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 8543e1cfd55e..582e0b3cf5ba 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -1142,41 +1142,41 @@ static int alloc_dma_desc_resources(struct stmmac_priv *priv) + goto err_tx_skbuff; + + if (priv->extend_desc) { +- priv->dma_erx = dma_alloc_coherent(priv->device, rxsize * +- sizeof(struct +- dma_extended_desc), +- &priv->dma_rx_phy, +- GFP_KERNEL); ++ priv->dma_erx = dma_zalloc_coherent(priv->device, rxsize * ++ sizeof(struct ++ dma_extended_desc), ++ &priv->dma_rx_phy, ++ GFP_KERNEL); + if (!priv->dma_erx) + goto err_dma; + +- priv->dma_etx = dma_alloc_coherent(priv->device, txsize * +- sizeof(struct +- dma_extended_desc), +- &priv->dma_tx_phy, +- GFP_KERNEL); ++ priv->dma_etx = dma_zalloc_coherent(priv->device, txsize * ++ sizeof(struct ++ dma_extended_desc), ++ &priv->dma_tx_phy, ++ GFP_KERNEL); + if (!priv->dma_etx) { + dma_free_coherent(priv->device, priv->dma_rx_size * +- sizeof(struct dma_extended_desc), +- priv->dma_erx, priv->dma_rx_phy); ++ sizeof(struct dma_extended_desc), ++ priv->dma_erx, priv->dma_rx_phy); + goto err_dma; + } + } else { +- priv->dma_rx = dma_alloc_coherent(priv->device, rxsize * +- sizeof(struct dma_desc), +- &priv->dma_rx_phy, +- GFP_KERNEL); ++ priv->dma_rx = dma_zalloc_coherent(priv->device, rxsize * ++ sizeof(struct dma_desc), ++ &priv->dma_rx_phy, ++ GFP_KERNEL); + if (!priv->dma_rx) + goto err_dma; + +- priv->dma_tx = dma_alloc_coherent(priv->device, txsize * +- sizeof(struct dma_desc), +- &priv->dma_tx_phy, +- GFP_KERNEL); ++ priv->dma_tx = dma_zalloc_coherent(priv->device, txsize * ++ sizeof(struct dma_desc), ++ &priv->dma_tx_phy, ++ GFP_KERNEL); + if (!priv->dma_tx) { + dma_free_coherent(priv->device, priv->dma_rx_size * +- sizeof(struct dma_desc), +- priv->dma_rx, priv->dma_rx_phy); ++ sizeof(struct dma_desc), ++ priv->dma_rx, priv->dma_rx_phy); + goto err_dma; + } + } +diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c +index f9e96c427558..23dc1316c1c2 100644 +--- a/drivers/net/usb/usbnet.c ++++ b/drivers/net/usb/usbnet.c +@@ -778,7 +778,7 @@ int usbnet_stop (struct net_device *net) + { + struct usbnet *dev = netdev_priv(net); + struct driver_info *info = dev->driver_info; +- int retval, pm; ++ int retval, pm, mpn; + + clear_bit(EVENT_DEV_OPEN, &dev->flags); + netif_stop_queue (net); +@@ -809,6 +809,8 @@ int usbnet_stop (struct net_device *net) + + usbnet_purge_paused_rxq(dev); + ++ mpn = !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags); ++ + /* deferred work (task, timer, softirq) must also stop. + * can't flush_scheduled_work() until we drop rtnl (later), + * else workers could deadlock; so make workers a NOP. +@@ -819,8 +821,7 @@ int usbnet_stop (struct net_device *net) + if (!pm) + usb_autopm_put_interface(dev->intf); + +- if (info->manage_power && +- !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags)) ++ if (info->manage_power && mpn) + info->manage_power(dev, 0); + else + usb_autopm_put_interface(dev->intf); +diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +index 66c92a16da29..a35d1dedeffb 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +@@ -314,6 +314,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { + {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ + {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ + {RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/ ++ {RTL_USB_DEVICE(0x0846, 0x9043, rtl92cu_hal_cfg)}, /*NG WNA1000Mv2*/ + {RTL_USB_DEVICE(0x0b05, 0x17ba, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/ + {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/ + {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ +diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c +index ff3c98f1ea95..91cc44611062 100644 +--- a/drivers/xen/gntdev.c ++++ b/drivers/xen/gntdev.c +@@ -67,7 +67,7 @@ struct gntdev_priv { + * Only populated if populate_freeable_maps == 1 */ + struct list_head freeable_maps; + /* lock protects maps and freeable_maps */ +- spinlock_t lock; ++ struct mutex lock; + struct mm_struct *mm; + struct mmu_notifier mn; + }; +@@ -216,9 +216,9 @@ static void gntdev_put_map(struct gntdev_priv *priv, struct grant_map *map) + } + + if (populate_freeable_maps && priv) { +- spin_lock(&priv->lock); ++ mutex_lock(&priv->lock); + list_del(&map->next); +- spin_unlock(&priv->lock); ++ mutex_unlock(&priv->lock); + } + + if (map->pages && !use_ptemod) +@@ -387,9 +387,9 @@ static void gntdev_vma_close(struct vm_area_struct *vma) + * not do any unmapping, since that has been done prior to + * closing the vma, but it may still iterate the unmap_ops list. + */ +- spin_lock(&priv->lock); ++ mutex_lock(&priv->lock); + map->vma = NULL; +- spin_unlock(&priv->lock); ++ mutex_unlock(&priv->lock); + } + vma->vm_private_data = NULL; + gntdev_put_map(priv, map); +@@ -433,14 +433,14 @@ static void mn_invl_range_start(struct mmu_notifier *mn, + struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); + struct grant_map *map; + +- spin_lock(&priv->lock); ++ mutex_lock(&priv->lock); + list_for_each_entry(map, &priv->maps, next) { + unmap_if_in_range(map, start, end); + } + list_for_each_entry(map, &priv->freeable_maps, next) { + unmap_if_in_range(map, start, end); + } +- spin_unlock(&priv->lock); ++ mutex_unlock(&priv->lock); + } + + static void mn_invl_page(struct mmu_notifier *mn, +@@ -457,7 +457,7 @@ static void mn_release(struct mmu_notifier *mn, + struct grant_map *map; + int err; + +- spin_lock(&priv->lock); ++ mutex_lock(&priv->lock); + list_for_each_entry(map, &priv->maps, next) { + if (!map->vma) + continue; +@@ -476,7 +476,7 @@ static void mn_release(struct mmu_notifier *mn, + err = unmap_grant_pages(map, /* offset */ 0, map->count); + WARN_ON(err); + } +- spin_unlock(&priv->lock); ++ mutex_unlock(&priv->lock); + } + + static struct mmu_notifier_ops gntdev_mmu_ops = { +@@ -498,7 +498,7 @@ static int gntdev_open(struct inode *inode, struct file *flip) + + INIT_LIST_HEAD(&priv->maps); + INIT_LIST_HEAD(&priv->freeable_maps); +- spin_lock_init(&priv->lock); ++ mutex_init(&priv->lock); + + if (use_ptemod) { + priv->mm = get_task_mm(current); +@@ -574,10 +574,10 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv, + return -EFAULT; + } + +- spin_lock(&priv->lock); ++ mutex_lock(&priv->lock); + gntdev_add_map(priv, map); + op.index = map->index << PAGE_SHIFT; +- spin_unlock(&priv->lock); ++ mutex_unlock(&priv->lock); + + if (copy_to_user(u, &op, sizeof(op)) != 0) + return -EFAULT; +@@ -596,7 +596,7 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv, + return -EFAULT; + pr_debug("priv %p, del %d+%d\n", priv, (int)op.index, (int)op.count); + +- spin_lock(&priv->lock); ++ mutex_lock(&priv->lock); + map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count); + if (map) { + list_del(&map->next); +@@ -604,7 +604,7 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv, + list_add_tail(&map->next, &priv->freeable_maps); + err = 0; + } +- spin_unlock(&priv->lock); ++ mutex_unlock(&priv->lock); + if (map) + gntdev_put_map(priv, map); + return err; +@@ -672,7 +672,7 @@ static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u) + out_flags = op.action; + out_event = op.event_channel_port; + +- spin_lock(&priv->lock); ++ mutex_lock(&priv->lock); + + list_for_each_entry(map, &priv->maps, next) { + uint64_t begin = map->index << PAGE_SHIFT; +@@ -700,7 +700,7 @@ static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u) + rc = 0; + + unlock_out: +- spin_unlock(&priv->lock); ++ mutex_unlock(&priv->lock); + + /* Drop the reference to the event channel we did not save in the map */ + if (out_flags & UNMAP_NOTIFY_SEND_EVENT) +@@ -750,7 +750,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma) + pr_debug("map %d+%d at %lx (pgoff %lx)\n", + index, count, vma->vm_start, vma->vm_pgoff); + +- spin_lock(&priv->lock); ++ mutex_lock(&priv->lock); + map = gntdev_find_map_index(priv, index, count); + if (!map) + goto unlock_out; +@@ -785,7 +785,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma) + map->flags |= GNTMAP_readonly; + } + +- spin_unlock(&priv->lock); ++ mutex_unlock(&priv->lock); + + if (use_ptemod) { + err = apply_to_page_range(vma->vm_mm, vma->vm_start, +@@ -813,11 +813,11 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma) + return 0; + + unlock_out: +- spin_unlock(&priv->lock); ++ mutex_unlock(&priv->lock); + return err; + + out_unlock_put: +- spin_unlock(&priv->lock); ++ mutex_unlock(&priv->lock); + out_put_map: + if (use_ptemod) + map->vma = NULL; +diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c +index a0b65a01fed7..86f86823a5f4 100644 +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -1710,8 +1710,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, + spin_unlock(&root->fs_info->trans_lock); + + wait_for_commit(root, prev_trans); ++ ret = prev_trans->aborted; + + btrfs_put_transaction(prev_trans); ++ if (ret) ++ goto cleanup_transaction; + } else { + spin_unlock(&root->fs_info->trans_lock); + } +diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c +index dfc95646b88c..31df9bceedca 100644 +--- a/fs/cifs/ioctl.c ++++ b/fs/cifs/ioctl.c +@@ -67,6 +67,12 @@ static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file, + goto out_drop_write; + } + ++ if (src_file.file->f_op->unlocked_ioctl != cifs_ioctl) { ++ rc = -EBADF; ++ cifs_dbg(VFS, "src file seems to be from a different filesystem type\n"); ++ goto out_fput; ++ } ++ + if ((!src_file.file->private_data) || (!dst_file->private_data)) { + rc = -EBADF; + cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n"); +diff --git a/fs/coredump.c b/fs/coredump.c +index a93f7e6ea4cf..72f97a56966f 100644 +--- a/fs/coredump.c ++++ b/fs/coredump.c +@@ -498,10 +498,10 @@ void do_coredump(const siginfo_t *siginfo) + const struct cred *old_cred; + struct cred *cred; + int retval = 0; +- int flag = 0; + int ispipe; + struct files_struct *displaced; +- bool need_nonrelative = false; ++ /* require nonrelative corefile path and be extra careful */ ++ bool need_suid_safe = false; + bool core_dumped = false; + static atomic_t core_dump_count = ATOMIC_INIT(0); + struct coredump_params cprm = { +@@ -535,9 +535,8 @@ void do_coredump(const siginfo_t *siginfo) + */ + if (__get_dumpable(cprm.mm_flags) == SUID_DUMP_ROOT) { + /* Setuid core dump mode */ +- flag = O_EXCL; /* Stop rewrite attacks */ + cred->fsuid = GLOBAL_ROOT_UID; /* Dump root private */ +- need_nonrelative = true; ++ need_suid_safe = true; + } + + retval = coredump_wait(siginfo->si_signo, &core_state); +@@ -618,7 +617,7 @@ void do_coredump(const siginfo_t *siginfo) + if (cprm.limit < binfmt->min_coredump) + goto fail_unlock; + +- if (need_nonrelative && cn.corename[0] != '/') { ++ if (need_suid_safe && cn.corename[0] != '/') { + printk(KERN_WARNING "Pid %d(%s) can only dump core "\ + "to fully qualified path!\n", + task_tgid_vnr(current), current->comm); +@@ -626,8 +625,35 @@ void do_coredump(const siginfo_t *siginfo) + goto fail_unlock; + } + ++ /* ++ * Unlink the file if it exists unless this is a SUID ++ * binary - in that case, we're running around with root ++ * privs and don't want to unlink another user's coredump. ++ */ ++ if (!need_suid_safe) { ++ mm_segment_t old_fs; ++ ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ /* ++ * If it doesn't exist, that's fine. If there's some ++ * other problem, we'll catch it at the filp_open(). ++ */ ++ (void) sys_unlink((const char __user *)cn.corename); ++ set_fs(old_fs); ++ } ++ ++ /* ++ * There is a race between unlinking and creating the ++ * file, but if that causes an EEXIST here, that's ++ * fine - another process raced with us while creating ++ * the corefile, and the other process won. To userspace, ++ * what matters is that at least one of the two processes ++ * writes its coredump successfully, not which one. ++ */ + cprm.file = filp_open(cn.corename, +- O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, ++ O_CREAT | 2 | O_NOFOLLOW | ++ O_LARGEFILE | O_EXCL, + 0600); + if (IS_ERR(cprm.file)) + goto fail_unlock; +diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c +index d3fa6bd9503e..221719eac5de 100644 +--- a/fs/hfs/bnode.c ++++ b/fs/hfs/bnode.c +@@ -288,7 +288,6 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid) + page_cache_release(page); + goto fail; + } +- page_cache_release(page); + node->page[i] = page; + } + +@@ -398,11 +397,11 @@ node_error: + + void hfs_bnode_free(struct hfs_bnode *node) + { +- //int i; ++ int i; + +- //for (i = 0; i < node->tree->pages_per_bnode; i++) +- // if (node->page[i]) +- // page_cache_release(node->page[i]); ++ for (i = 0; i < node->tree->pages_per_bnode; i++) ++ if (node->page[i]) ++ page_cache_release(node->page[i]); + kfree(node); + } + +diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c +index 9f4ee7f52026..6fc766df0461 100644 +--- a/fs/hfs/brec.c ++++ b/fs/hfs/brec.c +@@ -131,13 +131,16 @@ skip: + hfs_bnode_write(node, entry, data_off + key_len, entry_len); + hfs_bnode_dump(node); + +- if (new_node) { +- /* update parent key if we inserted a key +- * at the start of the first node +- */ +- if (!rec && new_node != node) +- hfs_brec_update_parent(fd); ++ /* ++ * update parent key if we inserted a key ++ * at the start of the node and it is not the new node ++ */ ++ if (!rec && new_node != node) { ++ hfs_bnode_read_key(node, fd->search_key, data_off + size); ++ hfs_brec_update_parent(fd); ++ } + ++ if (new_node) { + hfs_bnode_put(fd->bnode); + if (!new_node->parent) { + hfs_btree_inc_height(tree); +@@ -166,9 +169,6 @@ skip: + goto again; + } + +- if (!rec) +- hfs_brec_update_parent(fd); +- + return 0; + } + +@@ -366,6 +366,8 @@ again: + if (IS_ERR(parent)) + return PTR_ERR(parent); + __hfs_brec_find(parent, fd); ++ if (fd->record < 0) ++ return -ENOENT; + hfs_bnode_dump(parent); + rec = fd->record; + +diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c +index 11c860204520..bedfe5f7d332 100644 +--- a/fs/hfsplus/bnode.c ++++ b/fs/hfsplus/bnode.c +@@ -456,7 +456,6 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid) + page_cache_release(page); + goto fail; + } +- page_cache_release(page); + node->page[i] = page; + } + +@@ -568,13 +567,11 @@ node_error: + + void hfs_bnode_free(struct hfs_bnode *node) + { +-#if 0 + int i; + + for (i = 0; i < node->tree->pages_per_bnode; i++) + if (node->page[i]) + page_cache_release(node->page[i]); +-#endif + kfree(node); + } + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 58258ad50d5f..7b945957e230 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -2275,7 +2275,7 @@ static int _nfs4_do_open(struct inode *dir, + goto err_free_label; + state = ctx->state; + +- if ((opendata->o_arg.open_flags & O_EXCL) && ++ if ((opendata->o_arg.open_flags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) && + (opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) { + nfs4_exclusive_attrset(opendata, sattr); + +@@ -8368,6 +8368,7 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = { + .reboot_recovery_ops = &nfs41_reboot_recovery_ops, + .nograce_recovery_ops = &nfs41_nograce_recovery_ops, + .state_renewal_ops = &nfs41_state_renewal_ops, ++ .mig_recovery_ops = &nfs41_mig_recovery_ops, + }; + #endif + +diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c +index 27d7f2742592..11763ce73709 100644 +--- a/fs/nfs/pagelist.c ++++ b/fs/nfs/pagelist.c +@@ -60,8 +60,8 @@ EXPORT_SYMBOL_GPL(nfs_pgheader_init); + void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos) + { + spin_lock(&hdr->lock); +- if (pos < hdr->io_start + hdr->good_bytes) { +- set_bit(NFS_IOHDR_ERROR, &hdr->flags); ++ if (!test_and_set_bit(NFS_IOHDR_ERROR, &hdr->flags) ++ || pos < hdr->io_start + hdr->good_bytes) { + clear_bit(NFS_IOHDR_EOF, &hdr->flags); + hdr->good_bytes = pos - hdr->io_start; + hdr->error = error; +diff --git a/fs/udf/inode.c b/fs/udf/inode.c +index 287cd5f23421..142d29e3ccdf 100644 +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -1496,6 +1496,22 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) + iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint); + } + ++ /* ++ * Sanity check length of allocation descriptors and extended attrs to ++ * avoid integer overflows ++ */ ++ if (iinfo->i_lenEAttr > inode->i_sb->s_blocksize ++ || iinfo->i_lenAlloc > inode->i_sb->s_blocksize) { ++ make_bad_inode(inode); ++ return; ++ } ++ /* Now do exact checks */ ++ if (udf_file_entry_alloc_offset(inode) ++ + iinfo->i_lenAlloc > inode->i_sb->s_blocksize) { ++ make_bad_inode(inode); ++ return; ++ } ++ + switch (fe->icbTag.fileType) { + case ICBTAG_FILE_TYPE_DIRECTORY: + inode->i_op = &udf_dir_inode_operations; +diff --git a/include/net/ip.h b/include/net/ip.h +index 5128fa7a8302..476bab2d28b0 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -154,6 +154,7 @@ static inline __u8 get_rtconn_flags(struct ipcm_cookie* ipc, struct sock* sk) + } + + /* datagram.c */ ++int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); + int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); + + void ip4_datagram_release_cb(struct sock *sk); +diff --git a/kernel/fork.c b/kernel/fork.c +index e2c685396295..1394fb3476d0 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -1756,13 +1756,21 @@ static int check_unshare_flags(unsigned long unshare_flags) + CLONE_NEWUSER|CLONE_NEWPID)) + return -EINVAL; + /* +- * Not implemented, but pretend it works if there is nothing to +- * unshare. Note that unsharing CLONE_THREAD or CLONE_SIGHAND +- * needs to unshare vm. ++ * Not implemented, but pretend it works if there is nothing ++ * to unshare. Note that unsharing the address space or the ++ * signal handlers also need to unshare the signal queues (aka ++ * CLONE_THREAD). + */ + if (unshare_flags & (CLONE_THREAD | CLONE_SIGHAND | CLONE_VM)) { +- /* FIXME: get_task_mm() increments ->mm_users */ +- if (atomic_read(¤t->mm->mm_users) > 1) ++ if (!thread_group_empty(current)) ++ return -EINVAL; ++ } ++ if (unshare_flags & (CLONE_SIGHAND | CLONE_VM)) { ++ if (atomic_read(¤t->sighand->count) > 1) ++ return -EINVAL; ++ } ++ if (unshare_flags & CLONE_VM) { ++ if (!current_is_single_threaded()) + return -EINVAL; + } + +@@ -1831,16 +1839,16 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) + if (unshare_flags & CLONE_NEWUSER) + unshare_flags |= CLONE_THREAD | CLONE_FS; + /* +- * If unsharing a thread from a thread group, must also unshare vm. +- */ +- if (unshare_flags & CLONE_THREAD) +- unshare_flags |= CLONE_VM; +- /* + * If unsharing vm, must also unshare signal handlers. + */ + if (unshare_flags & CLONE_VM) + unshare_flags |= CLONE_SIGHAND; + /* ++ * If unsharing a signal handlers, must also unshare the signal queues. ++ */ ++ if (unshare_flags & CLONE_SIGHAND) ++ unshare_flags |= CLONE_THREAD; ++ /* + * If unsharing namespace, must also unshare filesystem information. + */ + if (unshare_flags & CLONE_NEWNS) +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 88edf53748ee..57af138d26a2 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -1087,7 +1087,7 @@ cull_mlocked: + if (PageSwapCache(page)) + try_to_free_swap(page); + unlock_page(page); +- putback_lru_page(page); ++ list_add(&page->lru, &ret_pages); + continue; + + activate_locked: +diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c +index b7b1914dfa25..27cf128ebc15 100644 +--- a/net/bridge/br_mdb.c ++++ b/net/bridge/br_mdb.c +@@ -347,7 +347,6 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, + return -ENOMEM; + rcu_assign_pointer(*pp, p); + +- br_mdb_notify(br->dev, port, group, RTM_NEWMDB); + return 0; + } + +@@ -370,6 +369,7 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br, + if (!p || p->br != br || p->state == BR_STATE_DISABLED) + return -EINVAL; + ++ memset(&ip, 0, sizeof(ip)); + ip.proto = entry->addr.proto; + if (ip.proto == htons(ETH_P_IP)) + ip.u.ip4 = entry->addr.u.ip4; +@@ -416,6 +416,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) + if (!netif_running(br->dev) || br->multicast_disabled) + return -EINVAL; + ++ memset(&ip, 0, sizeof(ip)); + ip.proto = entry->addr.proto; + if (ip.proto == htons(ETH_P_IP)) { + if (timer_pending(&br->ip4_querier.timer)) +diff --git a/net/core/datagram.c b/net/core/datagram.c +index a16ed7bbe376..13bc7dad7990 100644 +--- a/net/core/datagram.c ++++ b/net/core/datagram.c +@@ -130,6 +130,35 @@ out_noerr: + goto out; + } + ++static struct sk_buff *skb_set_peeked(struct sk_buff *skb) ++{ ++ struct sk_buff *nskb; ++ ++ if (skb->peeked) ++ return skb; ++ ++ /* We have to unshare an skb before modifying it. */ ++ if (!skb_shared(skb)) ++ goto done; ++ ++ nskb = skb_clone(skb, GFP_ATOMIC); ++ if (!nskb) ++ return ERR_PTR(-ENOMEM); ++ ++ skb->prev->next = nskb; ++ skb->next->prev = nskb; ++ nskb->prev = skb->prev; ++ nskb->next = skb->next; ++ ++ consume_skb(skb); ++ skb = nskb; ++ ++done: ++ skb->peeked = 1; ++ ++ return skb; ++} ++ + /** + * __skb_recv_datagram - Receive a datagram skbuff + * @sk: socket +@@ -164,7 +193,9 @@ out_noerr: + struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, + int *peeked, int *off, int *err) + { ++ struct sk_buff_head *queue = &sk->sk_receive_queue; + struct sk_buff *skb, *last; ++ unsigned long cpu_flags; + long timeo; + /* + * Caller is allowed not to check sk->sk_err before skb_recv_datagram() +@@ -183,8 +214,6 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, + * Look at current nfs client by the way... + * However, this function was correct in any case. 8) + */ +- unsigned long cpu_flags; +- struct sk_buff_head *queue = &sk->sk_receive_queue; + int _off = *off; + + last = (struct sk_buff *)queue; +@@ -198,7 +227,12 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, + _off -= skb->len; + continue; + } +- skb->peeked = 1; ++ ++ skb = skb_set_peeked(skb); ++ error = PTR_ERR(skb); ++ if (IS_ERR(skb)) ++ goto unlock_err; ++ + atomic_inc(&skb->users); + } else + __skb_unlink(skb, queue); +@@ -222,6 +256,8 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, + + return NULL; + ++unlock_err: ++ spin_unlock_irqrestore(&queue->lock, cpu_flags); + no_packet: + *err = error; + return NULL; +@@ -742,7 +778,8 @@ __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len) + if (likely(!sum)) { + if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) + netdev_rx_csum_fault(skb->dev); +- skb->ip_summed = CHECKSUM_UNNECESSARY; ++ if (!skb_shared(skb)) ++ skb->ip_summed = CHECKSUM_UNNECESSARY; + } + return sum; + } +diff --git a/net/core/dev.c b/net/core/dev.c +index 1b9e700c85b6..ae3260fc133d 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -3214,6 +3214,8 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu, + local_irq_save(flags); + + rps_lock(sd); ++ if (!netif_running(skb->dev)) ++ goto drop; + qlen = skb_queue_len(&sd->input_pkt_queue); + if (qlen <= netdev_max_backlog && !skb_flow_limit(skb, qlen)) { + if (skb_queue_len(&sd->input_pkt_queue)) { +@@ -3235,6 +3237,7 @@ enqueue: + goto enqueue; + } + ++drop: + sd->dropped++; + rps_unlock(sd); + +@@ -3551,8 +3554,6 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc) + + pt_prev = NULL; + +- rcu_read_lock(); +- + another_round: + skb->skb_iif = skb->dev->ifindex; + +@@ -3562,7 +3563,7 @@ another_round: + skb->protocol == cpu_to_be16(ETH_P_8021AD)) { + skb = skb_vlan_untag(skb); + if (unlikely(!skb)) +- goto unlock; ++ goto out; + } + + #ifdef CONFIG_NET_CLS_ACT +@@ -3587,7 +3588,7 @@ skip_taps: + #ifdef CONFIG_NET_CLS_ACT + skb = handle_ing(skb, &pt_prev, &ret, orig_dev); + if (!skb) +- goto unlock; ++ goto out; + ncls: + #endif + +@@ -3602,7 +3603,7 @@ ncls: + if (vlan_do_receive(&skb)) + goto another_round; + else if (unlikely(!skb)) +- goto unlock; ++ goto out; + } + + rx_handler = rcu_dereference(skb->dev->rx_handler); +@@ -3614,7 +3615,7 @@ ncls: + switch (rx_handler(&skb)) { + case RX_HANDLER_CONSUMED: + ret = NET_RX_SUCCESS; +- goto unlock; ++ goto out; + case RX_HANDLER_ANOTHER: + goto another_round; + case RX_HANDLER_EXACT: +@@ -3666,8 +3667,6 @@ drop: + ret = NET_RX_DROP; + } + +-unlock: +- rcu_read_unlock(); + out: + return ret; + } +@@ -3699,29 +3698,30 @@ static int __netif_receive_skb(struct sk_buff *skb) + + static int netif_receive_skb_internal(struct sk_buff *skb) + { ++ int ret; ++ + net_timestamp_check(netdev_tstamp_prequeue, skb); + + if (skb_defer_rx_timestamp(skb)) + return NET_RX_SUCCESS; + ++ rcu_read_lock(); ++ + #ifdef CONFIG_RPS + if (static_key_false(&rps_needed)) { + struct rps_dev_flow voidflow, *rflow = &voidflow; +- int cpu, ret; +- +- rcu_read_lock(); +- +- cpu = get_rps_cpu(skb->dev, skb, &rflow); ++ int cpu = get_rps_cpu(skb->dev, skb, &rflow); + + if (cpu >= 0) { + ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail); + rcu_read_unlock(); + return ret; + } +- rcu_read_unlock(); + } + #endif +- return __netif_receive_skb(skb); ++ ret = __netif_receive_skb(skb); ++ rcu_read_unlock(); ++ return ret; + } + + /** +@@ -4182,8 +4182,10 @@ static int process_backlog(struct napi_struct *napi, int quota) + unsigned int qlen; + + while ((skb = __skb_dequeue(&sd->process_queue))) { ++ rcu_read_lock(); + local_irq_enable(); + __netif_receive_skb(skb); ++ rcu_read_unlock(); + local_irq_disable(); + input_queue_head_incr(sd); + if (++work >= quota) { +@@ -5694,6 +5696,7 @@ static void rollback_registered_many(struct list_head *head) + unlist_netdevice(dev); + + dev->reg_state = NETREG_UNREGISTERING; ++ on_each_cpu(flush_backlog, dev, 1); + } + + synchronize_net(); +@@ -5951,7 +5954,8 @@ static int netif_alloc_netdev_queues(struct net_device *dev) + struct netdev_queue *tx; + size_t sz = count * sizeof(*tx); + +- BUG_ON(count < 1 || count > 0xffff); ++ if (count < 1 || count > 0xffff) ++ return -EINVAL; + + tx = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT); + if (!tx) { +@@ -6309,8 +6313,6 @@ void netdev_run_todo(void) + + dev->reg_state = NETREG_UNREGISTERED; + +- on_each_cpu(flush_backlog, dev, 1); +- + netdev_wait_allrefs(dev); + + /* paranoia */ +diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c +index 185c341fafbd..aeedc3a961a1 100644 +--- a/net/core/fib_rules.c ++++ b/net/core/fib_rules.c +@@ -621,15 +621,17 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb, + { + int idx = 0; + struct fib_rule *rule; ++ int err = 0; + + rcu_read_lock(); + list_for_each_entry_rcu(rule, &ops->rules_list, list) { + if (idx < cb->args[1]) + goto skip; + +- if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).portid, +- cb->nlh->nlmsg_seq, RTM_NEWRULE, +- NLM_F_MULTI, ops) < 0) ++ err = fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).portid, ++ cb->nlh->nlmsg_seq, RTM_NEWRULE, ++ NLM_F_MULTI, ops); ++ if (err) + break; + skip: + idx++; +@@ -638,7 +640,7 @@ skip: + cb->args[1] = idx; + rules_ops_put(ops); + +- return skb->len; ++ return err; + } + + static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb) +@@ -654,7 +656,9 @@ static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb) + if (ops == NULL) + return -EAFNOSUPPORT; + +- return dump_rules(skb, cb, ops); ++ dump_rules(skb, cb, ops); ++ ++ return skb->len; + } + + rcu_read_lock(); +diff --git a/net/core/pktgen.c b/net/core/pktgen.c +index ca68d32b49ba..dbd797a62b3a 100644 +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -3464,8 +3464,10 @@ static int pktgen_thread_worker(void *arg) + pktgen_rem_thread(t); + + /* Wait for kthread_stop */ +- while (!kthread_should_stop()) { ++ for (;;) { + set_current_state(TASK_INTERRUPTIBLE); ++ if (kthread_should_stop()) ++ break; + schedule(); + } + __set_current_state(TASK_RUNNING); +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 8aadd6a072a4..465092f8fb76 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -1259,10 +1259,6 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { + [IFLA_INFO_SLAVE_DATA] = { .type = NLA_NESTED }, + }; + +-static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = { +- [IFLA_VF_INFO] = { .type = NLA_NESTED }, +-}; +- + static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { + [IFLA_VF_MAC] = { .len = sizeof(struct ifla_vf_mac) }, + [IFLA_VF_VLAN] = { .len = sizeof(struct ifla_vf_vlan) }, +@@ -1336,67 +1332,66 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) + return 0; + } + +-static int do_setvfinfo(struct net_device *dev, struct nlattr *attr) ++static int do_setvfinfo(struct net_device *dev, struct nlattr **tb) + { +- int rem, err = -EINVAL; +- struct nlattr *vf; + const struct net_device_ops *ops = dev->netdev_ops; ++ int err = -EINVAL; + +- nla_for_each_nested(vf, attr, rem) { +- switch (nla_type(vf)) { +- case IFLA_VF_MAC: { +- struct ifla_vf_mac *ivm; +- ivm = nla_data(vf); +- err = -EOPNOTSUPP; +- if (ops->ndo_set_vf_mac) +- err = ops->ndo_set_vf_mac(dev, ivm->vf, +- ivm->mac); +- break; +- } +- case IFLA_VF_VLAN: { +- struct ifla_vf_vlan *ivv; +- ivv = nla_data(vf); +- err = -EOPNOTSUPP; +- if (ops->ndo_set_vf_vlan) +- err = ops->ndo_set_vf_vlan(dev, ivv->vf, +- ivv->vlan, +- ivv->qos); +- break; +- } +- case IFLA_VF_TX_RATE: { +- struct ifla_vf_tx_rate *ivt; +- ivt = nla_data(vf); +- err = -EOPNOTSUPP; +- if (ops->ndo_set_vf_tx_rate) +- err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, +- ivt->rate); +- break; +- } +- case IFLA_VF_SPOOFCHK: { +- struct ifla_vf_spoofchk *ivs; +- ivs = nla_data(vf); +- err = -EOPNOTSUPP; +- if (ops->ndo_set_vf_spoofchk) +- err = ops->ndo_set_vf_spoofchk(dev, ivs->vf, +- ivs->setting); +- break; +- } +- case IFLA_VF_LINK_STATE: { +- struct ifla_vf_link_state *ivl; +- ivl = nla_data(vf); +- err = -EOPNOTSUPP; +- if (ops->ndo_set_vf_link_state) +- err = ops->ndo_set_vf_link_state(dev, ivl->vf, +- ivl->link_state); +- break; +- } +- default: +- err = -EINVAL; +- break; +- } +- if (err) +- break; ++ if (tb[IFLA_VF_MAC]) { ++ struct ifla_vf_mac *ivm = nla_data(tb[IFLA_VF_MAC]); ++ ++ err = -EOPNOTSUPP; ++ if (ops->ndo_set_vf_mac) ++ err = ops->ndo_set_vf_mac(dev, ivm->vf, ++ ivm->mac); ++ if (err < 0) ++ return err; ++ } ++ ++ if (tb[IFLA_VF_VLAN]) { ++ struct ifla_vf_vlan *ivv = nla_data(tb[IFLA_VF_VLAN]); ++ ++ err = -EOPNOTSUPP; ++ if (ops->ndo_set_vf_vlan) ++ err = ops->ndo_set_vf_vlan(dev, ivv->vf, ivv->vlan, ++ ivv->qos); ++ if (err < 0) ++ return err; ++ } ++ ++ if (tb[IFLA_VF_TX_RATE]) { ++ struct ifla_vf_tx_rate *ivt = nla_data(tb[IFLA_VF_TX_RATE]); ++ ++ err = -EOPNOTSUPP; ++ if (ops->ndo_set_vf_tx_rate) ++ err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, ++ ivt->rate); ++ if (err < 0) ++ return err; + } ++ ++ if (tb[IFLA_VF_SPOOFCHK]) { ++ struct ifla_vf_spoofchk *ivs = nla_data(tb[IFLA_VF_SPOOFCHK]); ++ ++ err = -EOPNOTSUPP; ++ if (ops->ndo_set_vf_spoofchk) ++ err = ops->ndo_set_vf_spoofchk(dev, ivs->vf, ++ ivs->setting); ++ if (err < 0) ++ return err; ++ } ++ ++ if (tb[IFLA_VF_LINK_STATE]) { ++ struct ifla_vf_link_state *ivl = nla_data(tb[IFLA_VF_LINK_STATE]); ++ ++ err = -EOPNOTSUPP; ++ if (ops->ndo_set_vf_link_state) ++ err = ops->ndo_set_vf_link_state(dev, ivl->vf, ++ ivl->link_state); ++ if (err < 0) ++ return err; ++ } ++ + return err; + } + +@@ -1579,14 +1574,21 @@ static int do_setlink(const struct sk_buff *skb, + } + + if (tb[IFLA_VFINFO_LIST]) { ++ struct nlattr *vfinfo[IFLA_VF_MAX + 1]; + struct nlattr *attr; + int rem; ++ + nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) { +- if (nla_type(attr) != IFLA_VF_INFO) { ++ if (nla_type(attr) != IFLA_VF_INFO || ++ nla_len(attr) < NLA_HDRLEN) { + err = -EINVAL; + goto errout; + } +- err = do_setvfinfo(dev, attr); ++ err = nla_parse_nested(vfinfo, IFLA_VF_MAX, attr, ++ ifla_vf_policy); ++ if (err < 0) ++ goto errout; ++ err = do_setvfinfo(dev, vfinfo); + if (err < 0) + goto errout; + modified = 1; +diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c +index 951fe55b1671..f4c804dbd3b4 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -1291,7 +1291,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, + + encap = SKB_GSO_CB(skb)->encap_level > 0; + if (encap) +- features = skb->dev->hw_enc_features & netif_skb_features(skb); ++ features &= skb->dev->hw_enc_features; + SKB_GSO_CB(skb)->encap_level += ihl; + + skb_reset_transport_header(skb); +diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c +index a3095fdefbed..f0c307cb6196 100644 +--- a/net/ipv4/datagram.c ++++ b/net/ipv4/datagram.c +@@ -20,7 +20,7 @@ + #include + #include + +-int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ++int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) + { + struct inet_sock *inet = inet_sk(sk); + struct sockaddr_in *usin = (struct sockaddr_in *) uaddr; +@@ -39,8 +39,6 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) + + sk_dst_reset(sk); + +- lock_sock(sk); +- + oif = sk->sk_bound_dev_if; + saddr = inet->inet_saddr; + if (ipv4_is_multicast(usin->sin_addr.s_addr)) { +@@ -81,9 +79,19 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) + sk_dst_set(sk, &rt->dst); + err = 0; + out: +- release_sock(sk); + return err; + } ++EXPORT_SYMBOL(__ip4_datagram_connect); ++ ++int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ++{ ++ int res; ++ ++ lock_sock(sk); ++ res = __ip4_datagram_connect(sk, uaddr, addr_len); ++ release_sock(sk); ++ return res; ++} + EXPORT_SYMBOL(ip4_datagram_connect); + + /* Because UDP xmit path can manipulate sk_dst_cache without holding +diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c +index 278836f1a5ad..0da513e7730a 100644 +--- a/net/ipv4/gre_offload.c ++++ b/net/ipv4/gre_offload.c +@@ -69,7 +69,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, + skb->mac_len = skb_inner_network_offset(skb); + + /* segment inner packet. */ +- enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); ++ enc_features = skb->dev->hw_enc_features & features; + segs = skb_mac_gso_segment(skb, enc_features); + if (!segs || IS_ERR(segs)) { + skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len); +diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c +index 9ff497d17545..3f3a424ef0d5 100644 +--- a/net/ipv4/ip_fragment.c ++++ b/net/ipv4/ip_fragment.c +@@ -357,7 +357,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) + ihl = ip_hdrlen(skb); + + /* Determine the position of this fragment. */ +- end = offset + skb->len - ihl; ++ end = offset + skb->len - skb_network_offset(skb) - ihl; + err = -EINVAL; + + /* Is this the final fragment? */ +@@ -387,7 +387,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) + goto err; + + err = -ENOMEM; +- if (pskb_pull(skb, ihl) == NULL) ++ if (!pskb_pull(skb, skb_network_offset(skb) + ihl)) + goto err; + + err = pskb_trim_rcsum(skb, end - offset); +@@ -628,6 +628,9 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, + iph->frag_off = qp->q.max_size ? htons(IP_DF) : 0; + iph->tot_len = htons(len); + iph->tos |= ecn; ++ ++ ip_send_check(iph); ++ + IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS); + qp->q.fragments = NULL; + qp->q.fragments_tail = NULL; +diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c +index 0a4af0920af3..2d4be69c64f4 100644 +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -484,7 +484,8 @@ drop: + EXPORT_SYMBOL_GPL(ip_tunnel_rcv); + + static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, +- struct rtable *rt, __be16 df) ++ struct rtable *rt, __be16 df, ++ const struct iphdr *inner_iph) + { + struct ip_tunnel *tunnel = netdev_priv(dev); + int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len; +@@ -501,7 +502,8 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, + + if (skb->protocol == htons(ETH_P_IP)) { + if (!skb_is_gso(skb) && +- (df & htons(IP_DF)) && mtu < pkt_size) { ++ (inner_iph->frag_off & htons(IP_DF)) && ++ mtu < pkt_size) { + memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); + return -E2BIG; +@@ -632,7 +634,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, + goto tx_error; + } + +- if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off)) { ++ if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off, inner_iph)) { + ip_rt_put(rt); + goto tx_error; + } +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 21a3a9e90b10..6970e36ad7b8 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1957,12 +1957,19 @@ void udp_v4_early_demux(struct sk_buff *skb) + + skb->sk = sk; + skb->destructor = sock_edemux; +- dst = sk->sk_rx_dst; ++ dst = ACCESS_ONCE(sk->sk_rx_dst); + + if (dst) + dst = dst_check(dst, 0); +- if (dst) +- skb_dst_set_noref(skb, dst); ++ if (dst) { ++ /* DST_NOCACHE can not be used without taking a reference */ ++ if (dst->flags & DST_NOCACHE) { ++ if (likely(atomic_inc_not_zero(&dst->__refcnt))) ++ skb_dst_set(skb, dst); ++ } else { ++ skb_dst_set_noref(skb, dst); ++ } ++ } + } + + int udp_rcv(struct sk_buff *skb) +@@ -2510,7 +2517,7 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, + skb->protocol = htons(ETH_P_TEB); + + /* segment inner packet. */ +- enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); ++ enc_features = skb->dev->hw_enc_features & features; + segs = skb_mac_gso_segment(skb, enc_features); + if (!segs || IS_ERR(segs)) { + skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset, +diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c +index 841cfa2c4600..6b89b2a1ac74 100644 +--- a/net/ipv6/datagram.c ++++ b/net/ipv6/datagram.c +@@ -40,7 +40,7 @@ static bool ipv6_mapped_addr_any(const struct in6_addr *a) + return ipv6_addr_v4mapped(a) && (a->s6_addr32[3] == 0); + } + +-int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ++static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) + { + struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; + struct inet_sock *inet = inet_sk(sk); +@@ -56,7 +56,7 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) + if (usin->sin6_family == AF_INET) { + if (__ipv6_only_sock(sk)) + return -EAFNOSUPPORT; +- err = ip4_datagram_connect(sk, uaddr, addr_len); ++ err = __ip4_datagram_connect(sk, uaddr, addr_len); + goto ipv4_connected; + } + +@@ -98,9 +98,9 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) + sin.sin_addr.s_addr = daddr->s6_addr32[3]; + sin.sin_port = usin->sin6_port; + +- err = ip4_datagram_connect(sk, +- (struct sockaddr *) &sin, +- sizeof(sin)); ++ err = __ip4_datagram_connect(sk, ++ (struct sockaddr *) &sin, ++ sizeof(sin)); + + ipv4_connected: + if (err) +@@ -203,6 +203,16 @@ out: + fl6_sock_release(flowlabel); + return err; + } ++ ++int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ++{ ++ int res; ++ ++ lock_sock(sk); ++ res = __ip6_datagram_connect(sk, uaddr, addr_len); ++ release_sock(sk); ++ return res; ++} + EXPORT_SYMBOL_GPL(ip6_datagram_connect); + + int ip6_datagram_connect_v6_only(struct sock *sk, struct sockaddr *uaddr, +diff --git a/net/ipv6/exthdrs_offload.c b/net/ipv6/exthdrs_offload.c +index 447a7fbd1bb6..f5e2ba1c18bf 100644 +--- a/net/ipv6/exthdrs_offload.c ++++ b/net/ipv6/exthdrs_offload.c +@@ -36,6 +36,6 @@ out: + return ret; + + out_rt: +- inet_del_offload(&rthdr_offload, IPPROTO_ROUTING); ++ inet6_del_offload(&rthdr_offload, IPPROTO_ROUTING); + goto out; + } +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index 4a230b18dfe3..baffa3b7a328 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -357,6 +357,7 @@ static void ip6gre_tunnel_uninit(struct net_device *dev) + struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + + ip6gre_tunnel_unlink(ign, netdev_priv(dev)); ++ ip6_tnl_dst_reset(netdev_priv(dev)); + dev_put(dev); + } + +diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c +index 51d54dc376f3..05c94d9c3776 100644 +--- a/net/ipv6/ip6_input.c ++++ b/net/ipv6/ip6_input.c +@@ -329,10 +329,10 @@ int ip6_mc_input(struct sk_buff *skb) + if (offset < 0) + goto out; + +- if (!ipv6_is_mld(skb, nexthdr, offset)) +- goto out; ++ if (ipv6_is_mld(skb, nexthdr, offset)) ++ deliver = true; + +- deliver = true; ++ goto out; + } + /* unknown RA - process it normally */ + } +diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c +index b2f091566f88..dc46ebae1987 100644 +--- a/net/ipv6/ip6_offload.c ++++ b/net/ipv6/ip6_offload.c +@@ -112,7 +112,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, + + encap = SKB_GSO_CB(skb)->encap_level > 0; + if (encap) +- features = skb->dev->hw_enc_features & netif_skb_features(skb); ++ features &= skb->dev->hw_enc_features; + SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h); + + ipv6h = ipv6_hdr(skb); +diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c +index 8737400af0a0..821d8dfb2ddd 100644 +--- a/net/ipv6/ip6mr.c ++++ b/net/ipv6/ip6mr.c +@@ -552,7 +552,7 @@ static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) + + if (it->cache == &mrt->mfc6_unres_queue) + spin_unlock_bh(&mfc_unres_lock); +- else if (it->cache == mrt->mfc6_cache_array) ++ else if (it->cache == &mrt->mfc6_cache_array[it->ct]) + read_unlock(&mrt_lock); + } + +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index dca076f6252c..bc08a9ce3bd4 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -297,9 +297,6 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) + if (tx->sdata->vif.type == NL80211_IFTYPE_WDS) + return TX_CONTINUE; + +- if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT) +- return TX_CONTINUE; +- + if (tx->flags & IEEE80211_TX_PS_BUFFERED) + return TX_CONTINUE; + +diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c +index 851cd880b0c0..0c970cbe0405 100644 +--- a/net/mpls/mpls_gso.c ++++ b/net/mpls/mpls_gso.c +@@ -47,7 +47,7 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb, + __skb_push(skb, skb->mac_len); + + /* Segment inner packet. */ +- mpls_features = skb->dev->mpls_features & netif_skb_features(skb); ++ mpls_features = skb->dev->mpls_features & features; + segs = skb_mac_gso_segment(skb, mpls_features); + + +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index a0b0ea949192..fd9373c9f057 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -115,6 +115,24 @@ static inline struct hlist_head *nl_portid_hashfn(struct nl_portid_hash *hash, u + return &hash->table[jhash_1word(portid, hash->rnd) & hash->mask]; + } + ++static struct sk_buff *netlink_to_full_skb(const struct sk_buff *skb, ++ gfp_t gfp_mask) ++{ ++ unsigned int len = skb_end_offset(skb); ++ struct sk_buff *new; ++ ++ new = alloc_skb(len, gfp_mask); ++ if (new == NULL) ++ return NULL; ++ ++ NETLINK_CB(new).portid = NETLINK_CB(skb).portid; ++ NETLINK_CB(new).dst_group = NETLINK_CB(skb).dst_group; ++ NETLINK_CB(new).creds = NETLINK_CB(skb).creds; ++ ++ memcpy(skb_put(new, len), skb->data, len); ++ return new; ++} ++ + int netlink_add_tap(struct netlink_tap *nt) + { + if (unlikely(nt->dev->type != ARPHRD_NETLINK)) +@@ -199,7 +217,11 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb, + int ret = -ENOMEM; + + dev_hold(dev); +- nskb = skb_clone(skb, GFP_ATOMIC); ++ ++ if (netlink_skb_is_mmaped(skb) || is_vmalloc_addr(skb->head)) ++ nskb = netlink_to_full_skb(skb, GFP_ATOMIC); ++ else ++ nskb = skb_clone(skb, GFP_ATOMIC); + if (nskb) { + nskb->dev = dev; + nskb->protocol = htons((u16) sk->sk_protocol); +@@ -271,11 +293,6 @@ static void netlink_rcv_wake(struct sock *sk) + } + + #ifdef CONFIG_NETLINK_MMAP +-static bool netlink_skb_is_mmaped(const struct sk_buff *skb) +-{ +- return NETLINK_CB(skb).flags & NETLINK_SKB_MMAPED; +-} +- + static bool netlink_rx_is_mmaped(struct sock *sk) + { + return nlk_sk(sk)->rx_ring.pg_vec != NULL; +@@ -350,25 +367,52 @@ err1: + return NULL; + } + ++ ++static void ++__netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, bool tx_ring, void **pg_vec, ++ unsigned int order) ++{ ++ struct netlink_sock *nlk = nlk_sk(sk); ++ struct sk_buff_head *queue; ++ struct netlink_ring *ring; ++ ++ queue = tx_ring ? &sk->sk_write_queue : &sk->sk_receive_queue; ++ ring = tx_ring ? &nlk->tx_ring : &nlk->rx_ring; ++ ++ spin_lock_bh(&queue->lock); ++ ++ ring->frame_max = req->nm_frame_nr - 1; ++ ring->head = 0; ++ ring->frame_size = req->nm_frame_size; ++ ring->pg_vec_pages = req->nm_block_size / PAGE_SIZE; ++ ++ swap(ring->pg_vec_len, req->nm_block_nr); ++ swap(ring->pg_vec_order, order); ++ swap(ring->pg_vec, pg_vec); ++ ++ __skb_queue_purge(queue); ++ spin_unlock_bh(&queue->lock); ++ ++ WARN_ON(atomic_read(&nlk->mapped)); ++ ++ if (pg_vec) ++ free_pg_vec(pg_vec, order, req->nm_block_nr); ++} ++ + static int netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, +- bool closing, bool tx_ring) ++ bool tx_ring) + { + struct netlink_sock *nlk = nlk_sk(sk); + struct netlink_ring *ring; +- struct sk_buff_head *queue; + void **pg_vec = NULL; + unsigned int order = 0; +- int err; + + ring = tx_ring ? &nlk->tx_ring : &nlk->rx_ring; +- queue = tx_ring ? &sk->sk_write_queue : &sk->sk_receive_queue; + +- if (!closing) { +- if (atomic_read(&nlk->mapped)) +- return -EBUSY; +- if (atomic_read(&ring->pending)) +- return -EBUSY; +- } ++ if (atomic_read(&nlk->mapped)) ++ return -EBUSY; ++ if (atomic_read(&ring->pending)) ++ return -EBUSY; + + if (req->nm_block_nr) { + if (ring->pg_vec != NULL) +@@ -400,31 +444,19 @@ static int netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, + return -EINVAL; + } + +- err = -EBUSY; + mutex_lock(&nlk->pg_vec_lock); +- if (closing || atomic_read(&nlk->mapped) == 0) { +- err = 0; +- spin_lock_bh(&queue->lock); +- +- ring->frame_max = req->nm_frame_nr - 1; +- ring->head = 0; +- ring->frame_size = req->nm_frame_size; +- ring->pg_vec_pages = req->nm_block_size / PAGE_SIZE; +- +- swap(ring->pg_vec_len, req->nm_block_nr); +- swap(ring->pg_vec_order, order); +- swap(ring->pg_vec, pg_vec); +- +- __skb_queue_purge(queue); +- spin_unlock_bh(&queue->lock); +- +- WARN_ON(atomic_read(&nlk->mapped)); ++ if (atomic_read(&nlk->mapped) == 0) { ++ __netlink_set_ring(sk, req, tx_ring, pg_vec, order); ++ mutex_unlock(&nlk->pg_vec_lock); ++ return 0; + } ++ + mutex_unlock(&nlk->pg_vec_lock); + + if (pg_vec) + free_pg_vec(pg_vec, order, req->nm_block_nr); +- return err; ++ ++ return -EBUSY; + } + + static void netlink_mm_open(struct vm_area_struct *vma) +@@ -812,7 +844,6 @@ static void netlink_ring_set_copied(struct sock *sk, struct sk_buff *skb) + } + + #else /* CONFIG_NETLINK_MMAP */ +-#define netlink_skb_is_mmaped(skb) false + #define netlink_rx_is_mmaped(sk) false + #define netlink_tx_is_mmaped(sk) false + #define netlink_mmap sock_no_mmap +@@ -893,10 +924,10 @@ static void netlink_sock_destruct(struct sock *sk) + + memset(&req, 0, sizeof(req)); + if (nlk->rx_ring.pg_vec) +- netlink_set_ring(sk, &req, true, false); ++ __netlink_set_ring(sk, &req, false, NULL, 0); + memset(&req, 0, sizeof(req)); + if (nlk->tx_ring.pg_vec) +- netlink_set_ring(sk, &req, true, true); ++ __netlink_set_ring(sk, &req, true, NULL, 0); + } + #endif /* CONFIG_NETLINK_MMAP */ + +@@ -2190,7 +2221,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, + return -EINVAL; + if (copy_from_user(&req, optval, sizeof(req))) + return -EFAULT; +- err = netlink_set_ring(sk, &req, false, ++ err = netlink_set_ring(sk, &req, + optname == NETLINK_TX_RING); + break; + } +diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h +index acbd774eeb7c..dcc89c74b514 100644 +--- a/net/netlink/af_netlink.h ++++ b/net/netlink/af_netlink.h +@@ -65,6 +65,15 @@ struct nl_portid_hash { + u32 rnd; + }; + ++static inline bool netlink_skb_is_mmaped(const struct sk_buff *skb) ++{ ++#ifdef CONFIG_NETLINK_MMAP ++ return NETLINK_CB(skb).flags & NETLINK_SKB_MMAPED; ++#else ++ return false; ++#endif /* CONFIG_NETLINK_MMAP */ ++} ++ + struct netlink_table { + struct nl_portid_hash hash; + struct hlist_head mc_list; +diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c +index 270b77dfac30..8bb1a5a9b02e 100644 +--- a/net/openvswitch/datapath.c ++++ b/net/openvswitch/datapath.c +@@ -803,7 +803,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) + if (IS_ERR(acts)) + goto error; + +- ovs_flow_mask_key(&masked_key, &key, &mask); ++ ovs_flow_mask_key(&masked_key, &key, true, &mask); + error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], + &masked_key, 0, &acts); + if (error) { +diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c +index 3c268b3d71c3..4877d5a212a2 100644 +--- a/net/openvswitch/flow_table.c ++++ b/net/openvswitch/flow_table.c +@@ -55,18 +55,21 @@ static u16 range_n_bytes(const struct sw_flow_key_range *range) + } + + void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src, +- const struct sw_flow_mask *mask) ++ bool full, const struct sw_flow_mask *mask) + { +- const long *m = (long *)((u8 *)&mask->key + mask->range.start); +- const long *s = (long *)((u8 *)src + mask->range.start); +- long *d = (long *)((u8 *)dst + mask->range.start); ++ int start = full ? 0 : mask->range.start; ++ int len = full ? sizeof *dst : range_n_bytes(&mask->range); ++ const long *m = (const long *)((const u8 *)&mask->key + start); ++ const long *s = (const long *)((const u8 *)src + start); ++ long *d = (long *)((u8 *)dst + start); + int i; + +- /* The memory outside of the 'mask->range' are not set since +- * further operations on 'dst' only uses contents within +- * 'mask->range'. ++ /* If 'full' is true then all of 'dst' is fully initialized. Otherwise, ++ * if 'full' is false the memory outside of the 'mask->range' is left ++ * uninitialized. This can be used as an optimization when further ++ * operations on 'dst' only use contents within 'mask->range'. + */ +- for (i = 0; i < range_n_bytes(&mask->range); i += sizeof(long)) ++ for (i = 0; i < len; i += sizeof(long)) + *d++ = *s++ & *m++; + } + +@@ -436,7 +439,7 @@ static struct sw_flow *masked_flow_lookup(struct table_instance *ti, + u32 hash; + struct sw_flow_key masked_key; + +- ovs_flow_mask_key(&masked_key, unmasked, mask); ++ ovs_flow_mask_key(&masked_key, unmasked, false, mask); + hash = flow_hash(&masked_key, key_start, key_end); + head = find_bucket(ti, hash); + hlist_for_each_entry_rcu(flow, head, hash_node[ti->node_ver]) { +diff --git a/net/openvswitch/flow_table.h b/net/openvswitch/flow_table.h +index baaeb101924d..82e64a9b6416 100644 +--- a/net/openvswitch/flow_table.h ++++ b/net/openvswitch/flow_table.h +@@ -79,5 +79,5 @@ bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow, + struct sw_flow_match *match); + + void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src, +- const struct sw_flow_mask *mask); ++ bool full, const struct sw_flow_mask *mask); + #endif /* flow_table.h */ +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 84a60b82e235..fee7dcc28abd 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -2645,7 +2645,7 @@ static int packet_release(struct socket *sock) + static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 proto) + { + struct packet_sock *po = pkt_sk(sk); +- const struct net_device *dev_curr; ++ struct net_device *dev_curr; + __be16 proto_curr; + bool need_rehook; + +@@ -2669,15 +2669,13 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 proto) + + po->num = proto; + po->prot_hook.type = proto; +- +- if (po->prot_hook.dev) +- dev_put(po->prot_hook.dev); +- + po->prot_hook.dev = dev; + + po->ifindex = dev ? dev->ifindex : 0; + packet_cached_dev_assign(po, dev); + } ++ if (dev_curr) ++ dev_put(dev_curr); + + if (proto == 0 || !need_rehook) + goto out_unlock; +diff --git a/net/rds/info.c b/net/rds/info.c +index 9a6b4f66187c..140a44a5f7b7 100644 +--- a/net/rds/info.c ++++ b/net/rds/info.c +@@ -176,7 +176,7 @@ int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval, + + /* check for all kinds of wrapping and the like */ + start = (unsigned long)optval; +- if (len < 0 || len + PAGE_SIZE - 1 < len || start + len < start) { ++ if (len < 0 || len > INT_MAX - PAGE_SIZE + 1 || start + len < start) { + ret = -EINVAL; + goto out; + } +diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c +index a62a215dd22e..1237a237495b 100644 +--- a/net/sctp/protocol.c ++++ b/net/sctp/protocol.c +@@ -1167,7 +1167,7 @@ static void sctp_v4_del_protocol(void) + unregister_inetaddr_notifier(&sctp_inetaddr_notifier); + } + +-static int __net_init sctp_net_init(struct net *net) ++static int __net_init sctp_defaults_init(struct net *net) + { + int status; + +@@ -1260,12 +1260,6 @@ static int __net_init sctp_net_init(struct net *net) + + sctp_dbg_objcnt_init(net); + +- /* Initialize the control inode/socket for handling OOTB packets. */ +- if ((status = sctp_ctl_sock_init(net))) { +- pr_err("Failed to initialize the SCTP control sock\n"); +- goto err_ctl_sock_init; +- } +- + /* Initialize the local address list. */ + INIT_LIST_HEAD(&net->sctp.local_addr_list); + spin_lock_init(&net->sctp.local_addr_lock); +@@ -1281,9 +1275,6 @@ static int __net_init sctp_net_init(struct net *net) + + return 0; + +-err_ctl_sock_init: +- sctp_dbg_objcnt_exit(net); +- sctp_proc_exit(net); + err_init_proc: + cleanup_sctp_mibs(net); + err_init_mibs: +@@ -1292,15 +1283,12 @@ err_sysctl_register: + return status; + } + +-static void __net_exit sctp_net_exit(struct net *net) ++static void __net_exit sctp_defaults_exit(struct net *net) + { + /* Free the local address list */ + sctp_free_addr_wq(net); + sctp_free_local_addr_list(net); + +- /* Free the control endpoint. */ +- inet_ctl_sock_destroy(net->sctp.ctl_sock); +- + sctp_dbg_objcnt_exit(net); + + sctp_proc_exit(net); +@@ -1308,9 +1296,32 @@ static void __net_exit sctp_net_exit(struct net *net) + sctp_sysctl_net_unregister(net); + } + +-static struct pernet_operations sctp_net_ops = { +- .init = sctp_net_init, +- .exit = sctp_net_exit, ++static struct pernet_operations sctp_defaults_ops = { ++ .init = sctp_defaults_init, ++ .exit = sctp_defaults_exit, ++}; ++ ++static int __net_init sctp_ctrlsock_init(struct net *net) ++{ ++ int status; ++ ++ /* Initialize the control inode/socket for handling OOTB packets. */ ++ status = sctp_ctl_sock_init(net); ++ if (status) ++ pr_err("Failed to initialize the SCTP control sock\n"); ++ ++ return status; ++} ++ ++static void __net_init sctp_ctrlsock_exit(struct net *net) ++{ ++ /* Free the control endpoint. */ ++ inet_ctl_sock_destroy(net->sctp.ctl_sock); ++} ++ ++static struct pernet_operations sctp_ctrlsock_ops = { ++ .init = sctp_ctrlsock_init, ++ .exit = sctp_ctrlsock_exit, + }; + + /* Initialize the universe into something sensible. */ +@@ -1444,8 +1455,11 @@ static __init int sctp_init(void) + sctp_v4_pf_init(); + sctp_v6_pf_init(); + +- status = sctp_v4_protosw_init(); ++ status = register_pernet_subsys(&sctp_defaults_ops); ++ if (status) ++ goto err_register_defaults; + ++ status = sctp_v4_protosw_init(); + if (status) + goto err_protosw_init; + +@@ -1453,9 +1467,9 @@ static __init int sctp_init(void) + if (status) + goto err_v6_protosw_init; + +- status = register_pernet_subsys(&sctp_net_ops); ++ status = register_pernet_subsys(&sctp_ctrlsock_ops); + if (status) +- goto err_register_pernet_subsys; ++ goto err_register_ctrlsock; + + status = sctp_v4_add_protocol(); + if (status) +@@ -1471,12 +1485,14 @@ out: + err_v6_add_protocol: + sctp_v4_del_protocol(); + err_add_protocol: +- unregister_pernet_subsys(&sctp_net_ops); +-err_register_pernet_subsys: ++ unregister_pernet_subsys(&sctp_ctrlsock_ops); ++err_register_ctrlsock: + sctp_v6_protosw_exit(); + err_v6_protosw_init: + sctp_v4_protosw_exit(); + err_protosw_init: ++ unregister_pernet_subsys(&sctp_defaults_ops); ++err_register_defaults: + sctp_v4_pf_exit(); + sctp_v6_pf_exit(); + sctp_sysctl_unregister(); +@@ -1509,12 +1525,14 @@ static __exit void sctp_exit(void) + sctp_v6_del_protocol(); + sctp_v4_del_protocol(); + +- unregister_pernet_subsys(&sctp_net_ops); ++ unregister_pernet_subsys(&sctp_ctrlsock_ops); + + /* Free protosw registrations */ + sctp_v6_protosw_exit(); + sctp_v4_protosw_exit(); + ++ unregister_pernet_subsys(&sctp_defaults_ops); ++ + /* Unregister with socket layer. */ + sctp_v6_pf_exit(); + sctp_v4_pf_exit(); +diff --git a/net/tipc/socket.c b/net/tipc/socket.c +index 0ed0eaa62f29..830e40b329d6 100644 +--- a/net/tipc/socket.c ++++ b/net/tipc/socket.c +@@ -1681,6 +1681,7 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) + res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, 1); + if (res) + goto exit; ++ security_sk_clone(sock->sk, new_sock->sk); + + new_sk = new_sock->sk; + new_tsock = tipc_sk(new_sk); +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 907371d87312..08e29311e17d 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -1193,7 +1193,7 @@ static const struct hda_fixup alc880_fixups[] = { + /* override all pins as BIOS on old Amilo is broken */ + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { +- { 0x14, 0x0121411f }, /* HP */ ++ { 0x14, 0x0121401f }, /* HP */ + { 0x15, 0x99030120 }, /* speaker */ + { 0x16, 0x99030130 }, /* bass speaker */ + { 0x17, 0x411111f0 }, /* N/A */ +@@ -1213,7 +1213,7 @@ static const struct hda_fixup alc880_fixups[] = { + /* almost compatible with FUJITSU, but no bass and SPDIF */ + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { +- { 0x14, 0x0121411f }, /* HP */ ++ { 0x14, 0x0121401f }, /* HP */ + { 0x15, 0x99030120 }, /* speaker */ + { 0x16, 0x411111f0 }, /* N/A */ + { 0x17, 0x411111f0 }, /* N/A */ +@@ -1421,7 +1421,7 @@ static const struct snd_pci_quirk alc880_fixup_tbl[] = { + SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810), + SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), + SND_PCI_QUIRK(0x1631, 0xe011, "PB 13201056", ALC880_FIXUP_6ST_AUTOMUTE), +- SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734), ++ SND_PCI_QUIRK(0x1734, 0x107c, "FSC Amilo M1437", ALC880_FIXUP_FUJITSU), + SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU), + SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734), + SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU), diff --git a/patch/kernel/cubox-default/patch-3.14.54-55.patch b/patch/kernel/cubox-default/patch-3.14.54-55.patch new file mode 100644 index 000000000..f5b8d2d3d --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.54-55.patch @@ -0,0 +1,2917 @@ +diff --git a/Makefile b/Makefile +index 22c91fa0411e..97d18c1d27f2 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,8 +1,8 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 54 ++SUBLEVEL = 55 + EXTRAVERSION = +-NAME = Kernel Recipes 2015 ++NAME = Remembering Coco + + # *DOCUMENTATION* + # To see a list of typical targets execute "make help" +diff --git a/arch/arm/Makefile b/arch/arm/Makefile +index 08a9ef58d9c3..6ca3f2ebaa9c 100644 +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -52,6 +52,14 @@ endif + + comma = , + ++# ++# The Scalar Replacement of Aggregates (SRA) optimization pass in GCC 4.9 and ++# later may result in code being generated that handles signed short and signed ++# char struct members incorrectly. So disable it. ++# (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65932) ++# ++KBUILD_CFLAGS += $(call cc-option,-fno-ipa-sra) ++ + # This selects which instruction set is used. + # Note that GCC does not numerically define an architecture version + # macro, but instead defines a whole series of macros which makes +diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/omap5-uevm.dts +index 002fa70180a5..1186a50fc1de 100644 +--- a/arch/arm/boot/dts/omap5-uevm.dts ++++ b/arch/arm/boot/dts/omap5-uevm.dts +@@ -111,8 +111,8 @@ + + i2c5_pins: pinmux_i2c5_pins { + pinctrl-single,pins = < +- 0x184 (PIN_INPUT | MUX_MODE0) /* i2c5_scl */ +- 0x186 (PIN_INPUT | MUX_MODE0) /* i2c5_sda */ ++ 0x186 (PIN_INPUT | MUX_MODE0) /* i2c5_scl */ ++ 0x188 (PIN_INPUT | MUX_MODE0) /* i2c5_sda */ + >; + }; + +diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c +index 04d63880037f..1e5a4fd25a50 100644 +--- a/arch/arm/kernel/signal.c ++++ b/arch/arm/kernel/signal.c +@@ -353,12 +353,17 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig, + */ + thumb = handler & 1; + +-#if __LINUX_ARM_ARCH__ >= 7 ++#if __LINUX_ARM_ARCH__ >= 6 + /* +- * Clear the If-Then Thumb-2 execution state +- * ARM spec requires this to be all 000s in ARM mode +- * Snapdragon S4/Krait misbehaves on a Thumb=>ARM +- * signal transition without this. ++ * Clear the If-Then Thumb-2 execution state. ARM spec ++ * requires this to be all 000s in ARM mode. Snapdragon ++ * S4/Krait misbehaves on a Thumb=>ARM signal transition ++ * without this. ++ * ++ * We must do this whenever we are running on a Thumb-2 ++ * capable CPU, which includes ARMv6T2. However, we elect ++ * to do this whenever we're on an ARMv6 or later CPU for ++ * simplicity. + */ + cpsr &= ~PSR_IT_MASK; + #endif +diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c +index c23751b06120..cc083b6e4ce7 100644 +--- a/arch/arm64/mm/fault.c ++++ b/arch/arm64/mm/fault.c +@@ -278,6 +278,7 @@ retry: + * starvation. + */ + mm_flags &= ~FAULT_FLAG_ALLOW_RETRY; ++ mm_flags |= FAULT_FLAG_TRIED; + goto retry; + } + } +diff --git a/arch/hexagon/include/asm/barrier.h b/arch/hexagon/include/asm/barrier.h +deleted file mode 100644 +index 4e863daea25b..000000000000 +--- a/arch/hexagon/include/asm/barrier.h ++++ /dev/null +@@ -1,37 +0,0 @@ +-/* +- * Memory barrier definitions for the Hexagon architecture +- * +- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 and +- * only version 2 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +- * 02110-1301, USA. +- */ +- +-#ifndef _ASM_BARRIER_H +-#define _ASM_BARRIER_H +- +-#define rmb() barrier() +-#define read_barrier_depends() barrier() +-#define wmb() barrier() +-#define mb() barrier() +-#define smp_rmb() barrier() +-#define smp_read_barrier_depends() barrier() +-#define smp_wmb() barrier() +-#define smp_mb() barrier() +- +-/* Set a value and use a memory barrier. Used by the scheduler somewhere. */ +-#define set_mb(var, value) \ +- do { var = value; mb(); } while (0) +- +-#endif /* _ASM_BARRIER_H */ +diff --git a/arch/m68k/include/asm/linkage.h b/arch/m68k/include/asm/linkage.h +index 5a822bb790f7..066e74f666ae 100644 +--- a/arch/m68k/include/asm/linkage.h ++++ b/arch/m68k/include/asm/linkage.h +@@ -4,4 +4,34 @@ + #define __ALIGN .align 4 + #define __ALIGN_STR ".align 4" + ++/* ++ * Make sure the compiler doesn't do anything stupid with the ++ * arguments on the stack - they are owned by the *caller*, not ++ * the callee. This just fools gcc into not spilling into them, ++ * and keeps it from doing tailcall recursion and/or using the ++ * stack slots for temporaries, since they are live and "used" ++ * all the way to the end of the function. ++ */ ++#define asmlinkage_protect(n, ret, args...) \ ++ __asmlinkage_protect##n(ret, ##args) ++#define __asmlinkage_protect_n(ret, args...) \ ++ __asm__ __volatile__ ("" : "=r" (ret) : "0" (ret), ##args) ++#define __asmlinkage_protect0(ret) \ ++ __asmlinkage_protect_n(ret) ++#define __asmlinkage_protect1(ret, arg1) \ ++ __asmlinkage_protect_n(ret, "m" (arg1)) ++#define __asmlinkage_protect2(ret, arg1, arg2) \ ++ __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2)) ++#define __asmlinkage_protect3(ret, arg1, arg2, arg3) \ ++ __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3)) ++#define __asmlinkage_protect4(ret, arg1, arg2, arg3, arg4) \ ++ __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \ ++ "m" (arg4)) ++#define __asmlinkage_protect5(ret, arg1, arg2, arg3, arg4, arg5) \ ++ __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \ ++ "m" (arg4), "m" (arg5)) ++#define __asmlinkage_protect6(ret, arg1, arg2, arg3, arg4, arg5, arg6) \ ++ __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \ ++ "m" (arg4), "m" (arg5), "m" (arg6)) ++ + #endif +diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c +index 44b6dff5aba2..a1087593b3c2 100644 +--- a/arch/mips/mm/dma-default.c ++++ b/arch/mips/mm/dma-default.c +@@ -94,7 +94,7 @@ static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp) + else + #endif + #if defined(CONFIG_ZONE_DMA) && !defined(CONFIG_ZONE_DMA32) +- if (dev->coherent_dma_mask < DMA_BIT_MASK(64)) ++ if (dev->coherent_dma_mask < DMA_BIT_MASK(sizeof(phys_addr_t) * 8)) + dma_flag = __GFP_DMA; + else + #endif +diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c +index 52c1162bcee3..4ca00128ae34 100644 +--- a/arch/powerpc/platforms/powernv/pci.c ++++ b/arch/powerpc/platforms/powernv/pci.c +@@ -109,6 +109,7 @@ static void pnv_teardown_msi_irqs(struct pci_dev *pdev) + struct pci_controller *hose = pci_bus_to_host(pdev->bus); + struct pnv_phb *phb = hose->private_data; + struct msi_desc *entry; ++ irq_hw_number_t hwirq; + + if (WARN_ON(!phb)) + return; +@@ -116,10 +117,10 @@ static void pnv_teardown_msi_irqs(struct pci_dev *pdev) + list_for_each_entry(entry, &pdev->msi_list, list) { + if (entry->irq == NO_IRQ) + continue; ++ hwirq = virq_to_hw(entry->irq); + irq_set_msi_desc(entry->irq, NULL); +- msi_bitmap_free_hwirqs(&phb->msi_bmp, +- virq_to_hw(entry->irq) - phb->msi_base, 1); + irq_dispose_mapping(entry->irq); ++ msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq - phb->msi_base, 1); + } + } + #endif /* CONFIG_PCI_MSI */ +diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c +index 77efbaec7b9c..4a9b36777775 100644 +--- a/arch/powerpc/sysdev/fsl_msi.c ++++ b/arch/powerpc/sysdev/fsl_msi.c +@@ -121,15 +121,16 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev) + { + struct msi_desc *entry; + struct fsl_msi *msi_data; ++ irq_hw_number_t hwirq; + + list_for_each_entry(entry, &pdev->msi_list, list) { + if (entry->irq == NO_IRQ) + continue; ++ hwirq = virq_to_hw(entry->irq); + msi_data = irq_get_chip_data(entry->irq); + irq_set_msi_desc(entry->irq, NULL); +- msi_bitmap_free_hwirqs(&msi_data->bitmap, +- virq_to_hw(entry->irq), 1); + irq_dispose_mapping(entry->irq); ++ msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1); + } + + return; +diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c +index 38e62382070c..9e14d82287a1 100644 +--- a/arch/powerpc/sysdev/mpic_pasemi_msi.c ++++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c +@@ -74,6 +74,7 @@ static int pasemi_msi_check_device(struct pci_dev *pdev, int nvec, int type) + static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev) + { + struct msi_desc *entry; ++ irq_hw_number_t hwirq; + + pr_debug("pasemi_msi_teardown_msi_irqs, pdev %p\n", pdev); + +@@ -81,10 +82,11 @@ static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev) + if (entry->irq == NO_IRQ) + continue; + ++ hwirq = virq_to_hw(entry->irq); + irq_set_msi_desc(entry->irq, NULL); +- msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, +- virq_to_hw(entry->irq), ALLOC_CHUNK); + irq_dispose_mapping(entry->irq); ++ msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, ++ hwirq, ALLOC_CHUNK); + } + + return; +diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c +index 9a7aa0ed9c1c..dfc3486bf802 100644 +--- a/arch/powerpc/sysdev/mpic_u3msi.c ++++ b/arch/powerpc/sysdev/mpic_u3msi.c +@@ -124,15 +124,16 @@ static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type) + static void u3msi_teardown_msi_irqs(struct pci_dev *pdev) + { + struct msi_desc *entry; ++ irq_hw_number_t hwirq; + + list_for_each_entry(entry, &pdev->msi_list, list) { + if (entry->irq == NO_IRQ) + continue; + ++ hwirq = virq_to_hw(entry->irq); + irq_set_msi_desc(entry->irq, NULL); +- msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, +- virq_to_hw(entry->irq), 1); + irq_dispose_mapping(entry->irq); ++ msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, 1); + } + + return; +diff --git a/arch/powerpc/sysdev/ppc4xx_msi.c b/arch/powerpc/sysdev/ppc4xx_msi.c +index 43948da837a7..c3e65129940b 100644 +--- a/arch/powerpc/sysdev/ppc4xx_msi.c ++++ b/arch/powerpc/sysdev/ppc4xx_msi.c +@@ -121,16 +121,17 @@ void ppc4xx_teardown_msi_irqs(struct pci_dev *dev) + { + struct msi_desc *entry; + struct ppc4xx_msi *msi_data = &ppc4xx_msi; ++ irq_hw_number_t hwirq; + + dev_dbg(&dev->dev, "PCIE-MSI: tearing down msi irqs\n"); + + list_for_each_entry(entry, &dev->msi_list, list) { + if (entry->irq == NO_IRQ) + continue; ++ hwirq = virq_to_hw(entry->irq); + irq_set_msi_desc(entry->irq, NULL); +- msi_bitmap_free_hwirqs(&msi_data->bitmap, +- virq_to_hw(entry->irq), 1); + irq_dispose_mapping(entry->irq); ++ msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1); + } + } + +diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c +index 523f147b2470..b6ee63a69122 100644 +--- a/arch/x86/kernel/apic/apic.c ++++ b/arch/x86/kernel/apic/apic.c +@@ -359,6 +359,13 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) + apic_write(APIC_LVTT, lvtt_value); + + if (lvtt_value & APIC_LVT_TIMER_TSCDEADLINE) { ++ /* ++ * See Intel SDM: TSC-Deadline Mode chapter. In xAPIC mode, ++ * writing to the APIC LVTT and TSC_DEADLINE MSR isn't serialized. ++ * According to Intel, MFENCE can do the serialization here. ++ */ ++ asm volatile("mfence" : : : "memory"); ++ + printk_once(KERN_DEBUG "TSC deadline timer enabled\n"); + return; + } +diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S +index 6d6ab2b0bdfa..f2f2b97b7cc4 100644 +--- a/arch/x86/kernel/entry_64.S ++++ b/arch/x86/kernel/entry_64.S +@@ -1684,7 +1684,18 @@ END(error_exit) + /* runs on exception stack */ + ENTRY(nmi) + INTR_FRAME ++ /* ++ * Fix up the exception frame if we're on Xen. ++ * PARAVIRT_ADJUST_EXCEPTION_FRAME is guaranteed to push at most ++ * one value to the stack on native, so it may clobber the rdx ++ * scratch slot, but it won't clobber any of the important ++ * slots past it. ++ * ++ * Xen is a different story, because the Xen frame itself overlaps ++ * the "NMI executing" variable. ++ */ + PARAVIRT_ADJUST_EXCEPTION_FRAME ++ + /* + * We allow breakpoints in NMIs. If a breakpoint occurs, then + * the iretq it performs will take us out of NMI context. +@@ -1736,8 +1747,11 @@ ENTRY(nmi) + * we don't want to enable interrupts, because then we'll end + * up in an awkward situation in which IRQs are on but NMIs + * are off. ++ * ++ * We also must not push anything to the stack before switching ++ * stacks lest we corrupt the "NMI executing" variable. + */ +- SWAPGS ++ SWAPGS_UNSAFE_STACK + cld + movq %rsp, %rdx + movq PER_CPU_VAR(kernel_stack), %rsp +diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c +index 1b10af835c31..45c2045692bd 100644 +--- a/arch/x86/kernel/paravirt.c ++++ b/arch/x86/kernel/paravirt.c +@@ -40,10 +40,18 @@ + #include + #include + +-/* nop stub */ +-void _paravirt_nop(void) +-{ +-} ++/* ++ * nop stub, which must not clobber anything *including the stack* to ++ * avoid confusing the entry prologues. ++ */ ++extern void _paravirt_nop(void); ++asm (".pushsection .entry.text, \"ax\"\n" ++ ".global _paravirt_nop\n" ++ "_paravirt_nop:\n\t" ++ "ret\n\t" ++ ".size _paravirt_nop, . - _paravirt_nop\n\t" ++ ".type _paravirt_nop, @function\n\t" ++ ".popsection"); + + /* identity function, which can be inlined */ + u32 _paravirt_ident_32(u32 x) +diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c +index b20bced0090f..8bc924ff88ee 100644 +--- a/arch/x86/kernel/tsc.c ++++ b/arch/x86/kernel/tsc.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + unsigned int __read_mostly cpu_khz; /* TSC clocks / usec, not used here */ + EXPORT_SYMBOL(cpu_khz); +@@ -1011,15 +1012,17 @@ EXPORT_SYMBOL_GPL(mark_tsc_unstable); + + static void __init check_system_tsc_reliable(void) + { +-#ifdef CONFIG_MGEODE_LX +- /* RTSC counts during suspend */ ++#if defined(CONFIG_MGEODEGX1) || defined(CONFIG_MGEODE_LX) || defined(CONFIG_X86_GENERIC) ++ if (is_geode_lx()) { ++ /* RTSC counts during suspend */ + #define RTSC_SUSP 0x100 +- unsigned long res_low, res_high; ++ unsigned long res_low, res_high; + +- rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high); +- /* Geode_LX - the OLPC CPU has a very reliable TSC */ +- if (res_low & RTSC_SUSP) +- tsc_clocksource_reliable = 1; ++ rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high); ++ /* Geode_LX - the OLPC CPU has a very reliable TSC */ ++ if (res_low & RTSC_SUSP) ++ tsc_clocksource_reliable = 1; ++ } + #endif + if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) + tsc_clocksource_reliable = 1; +diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c +index 074633411ea8..e23a539e2077 100644 +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -496,7 +496,7 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu) + struct vcpu_svm *svm = to_svm(vcpu); + + if (svm->vmcb->control.next_rip != 0) { +- WARN_ON(!static_cpu_has(X86_FEATURE_NRIPS)); ++ WARN_ON_ONCE(!static_cpu_has(X86_FEATURE_NRIPS)); + svm->next_rip = svm->vmcb->control.next_rip; + } + +diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c +index 2308a401a1c5..0029f59588bd 100644 +--- a/arch/x86/mm/init_64.c ++++ b/arch/x86/mm/init_64.c +@@ -1131,7 +1131,7 @@ void mark_rodata_ro(void) + * has been zapped already via cleanup_highmem(). + */ + all_end = roundup((unsigned long)_brk_end, PMD_SIZE); +- set_memory_nx(rodata_start, (all_end - rodata_start) >> PAGE_SHIFT); ++ set_memory_nx(text_end, (all_end - text_end) >> PAGE_SHIFT); + + rodata_test(); + +diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c +index abb81b0ad83f..ae7d543f23ed 100644 +--- a/arch/x86/platform/efi/efi.c ++++ b/arch/x86/platform/efi/efi.c +@@ -961,6 +961,70 @@ out: + } + + /* ++ * Iterate the EFI memory map in reverse order because the regions ++ * will be mapped top-down. The end result is the same as if we had ++ * mapped things forward, but doesn't require us to change the ++ * existing implementation of efi_map_region(). ++ */ ++static inline void *efi_map_next_entry_reverse(void *entry) ++{ ++ /* Initial call */ ++ if (!entry) ++ return memmap.map_end - memmap.desc_size; ++ ++ entry -= memmap.desc_size; ++ if (entry < memmap.map) ++ return NULL; ++ ++ return entry; ++} ++ ++/* ++ * efi_map_next_entry - Return the next EFI memory map descriptor ++ * @entry: Previous EFI memory map descriptor ++ * ++ * This is a helper function to iterate over the EFI memory map, which ++ * we do in different orders depending on the current configuration. ++ * ++ * To begin traversing the memory map @entry must be %NULL. ++ * ++ * Returns %NULL when we reach the end of the memory map. ++ */ ++static void *efi_map_next_entry(void *entry) ++{ ++ if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) { ++ /* ++ * Starting in UEFI v2.5 the EFI_PROPERTIES_TABLE ++ * config table feature requires us to map all entries ++ * in the same order as they appear in the EFI memory ++ * map. That is to say, entry N must have a lower ++ * virtual address than entry N+1. This is because the ++ * firmware toolchain leaves relative references in ++ * the code/data sections, which are split and become ++ * separate EFI memory regions. Mapping things ++ * out-of-order leads to the firmware accessing ++ * unmapped addresses. ++ * ++ * Since we need to map things this way whether or not ++ * the kernel actually makes use of ++ * EFI_PROPERTIES_TABLE, let's just switch to this ++ * scheme by default for 64-bit. ++ */ ++ return efi_map_next_entry_reverse(entry); ++ } ++ ++ /* Initial call */ ++ if (!entry) ++ return memmap.map; ++ ++ entry += memmap.desc_size; ++ if (entry >= memmap.map_end) ++ return NULL; ++ ++ return entry; ++} ++ ++/* + * Map the efi memory ranges of the runtime services and update new_mmap with + * virtual addresses. + */ +@@ -970,7 +1034,8 @@ static void * __init efi_map_regions(int *count, int *pg_shift) + unsigned long left = 0; + efi_memory_desc_t *md; + +- for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { ++ p = NULL; ++ while ((p = efi_map_next_entry(p))) { + md = p; + if (!(md->attribute & EFI_MEMORY_RUNTIME)) { + #ifdef CONFIG_X86_64 +diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c +index 2302f10b1be6..4dca0d50762e 100644 +--- a/arch/x86/xen/enlighten.c ++++ b/arch/x86/xen/enlighten.c +@@ -33,6 +33,10 @@ + #include + #include + ++#ifdef CONFIG_KEXEC_CORE ++#include ++#endif ++ + #include + #include + #include +@@ -1844,6 +1848,21 @@ static struct notifier_block xen_hvm_cpu_notifier = { + .notifier_call = xen_hvm_cpu_notify, + }; + ++#ifdef CONFIG_KEXEC_CORE ++static void xen_hvm_shutdown(void) ++{ ++ native_machine_shutdown(); ++ if (kexec_in_progress) ++ xen_reboot(SHUTDOWN_soft_reset); ++} ++ ++static void xen_hvm_crash_shutdown(struct pt_regs *regs) ++{ ++ native_machine_crash_shutdown(regs); ++ xen_reboot(SHUTDOWN_soft_reset); ++} ++#endif ++ + static void __init xen_hvm_guest_init(void) + { + init_hvm_pv_info(); +@@ -1860,6 +1879,10 @@ static void __init xen_hvm_guest_init(void) + x86_init.irqs.intr_init = xen_init_IRQ; + xen_hvm_init_time_ops(); + xen_hvm_init_mmu_ops(); ++#ifdef CONFIG_KEXEC_CORE ++ machine_ops.shutdown = xen_hvm_shutdown; ++ machine_ops.crash_shutdown = xen_hvm_crash_shutdown; ++#endif + } + + static uint32_t __init xen_hvm_platform(void) +diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c +index d39fd610aa3b..1dca2a516bfd 100644 +--- a/drivers/base/regmap/regmap-debugfs.c ++++ b/drivers/base/regmap/regmap-debugfs.c +@@ -32,8 +32,7 @@ static DEFINE_MUTEX(regmap_debugfs_early_lock); + /* Calculate the length of a fixed format */ + static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size) + { +- snprintf(buf, buf_size, "%x", max_val); +- return strlen(buf); ++ return snprintf(NULL, 0, "%x", max_val); + } + + static ssize_t regmap_name_read_file(struct file *file, +@@ -432,7 +431,7 @@ static ssize_t regmap_access_read_file(struct file *file, + /* If we're in the region the user is trying to read */ + if (p >= *ppos) { + /* ...but not beyond it */ +- if (buf_pos >= count - 1 - tot_len) ++ if (buf_pos + tot_len + 1 >= count) + break; + + /* Format the register */ +diff --git a/drivers/clk/ti/clk-3xxx.c b/drivers/clk/ti/clk-3xxx.c +index d3230234f07b..8c7b048bd0ab 100644 +--- a/drivers/clk/ti/clk-3xxx.c ++++ b/drivers/clk/ti/clk-3xxx.c +@@ -174,7 +174,6 @@ static struct ti_dt_clk omap3xxx_clks[] = { + DT_CLK(NULL, "gpio2_ick", "gpio2_ick"), + DT_CLK(NULL, "wdt3_ick", "wdt3_ick"), + DT_CLK(NULL, "uart3_ick", "uart3_ick"), +- DT_CLK(NULL, "uart4_ick", "uart4_ick"), + DT_CLK(NULL, "gpt9_ick", "gpt9_ick"), + DT_CLK(NULL, "gpt8_ick", "gpt8_ick"), + DT_CLK(NULL, "gpt7_ick", "gpt7_ick"), +@@ -317,6 +316,7 @@ static struct ti_dt_clk am35xx_clks[] = { + static struct ti_dt_clk omap36xx_clks[] = { + DT_CLK(NULL, "omap_192m_alwon_fck", "omap_192m_alwon_fck"), + DT_CLK(NULL, "uart4_fck", "uart4_fck"), ++ DT_CLK(NULL, "uart4_ick", "uart4_ick"), + { .node_name = NULL }, + }; + +diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c +index b0972b3869c7..3ae48ee2f488 100644 +--- a/drivers/dma/dw/core.c ++++ b/drivers/dma/dw/core.c +@@ -1561,7 +1561,6 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) + INIT_LIST_HEAD(&dw->dma.channels); + for (i = 0; i < nr_channels; i++) { + struct dw_dma_chan *dwc = &dw->chan[i]; +- int r = nr_channels - i - 1; + + dwc->chan.device = &dw->dma; + dma_cookie_init(&dwc->chan); +@@ -1573,7 +1572,7 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) + + /* 7 is highest priority & 0 is lowest. */ + if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING) +- dwc->priority = r; ++ dwc->priority = nr_channels - i - 1; + else + dwc->priority = i; + +@@ -1593,6 +1592,7 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata) + /* Hardware configuration */ + if (autocfg) { + unsigned int dwc_params; ++ unsigned int r = DW_DMA_MAX_NR_CHANNELS - i - 1; + void __iomem *addr = chip->regs + r * sizeof(u32); + + dwc_params = dma_read_byaddr(addr, DWC_PARAMS); +diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c +index f6452682141b..8b8b0e3fc2a8 100644 +--- a/drivers/gpu/drm/drm_lock.c ++++ b/drivers/gpu/drm/drm_lock.c +@@ -58,6 +58,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) + struct drm_master *master = file_priv->master; + int ret = 0; + ++ if (drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + ++file_priv->lock_count; + + if (lock->context == DRM_KERNEL_CONTEXT) { +@@ -150,6 +153,9 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) + struct drm_lock *lock = data; + struct drm_master *master = file_priv->master; + ++ if (drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + if (lock->context == DRM_KERNEL_CONTEXT) { + DRM_ERROR("Process %d using kernel context %d\n", + task_pid_nr(current), lock->context); +diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c +index 8e3267a8bd4f..11f401ac6bdc 100644 +--- a/drivers/gpu/drm/qxl/qxl_display.c ++++ b/drivers/gpu/drm/qxl/qxl_display.c +@@ -552,7 +552,7 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc, + adjusted_mode->hdisplay, + adjusted_mode->vdisplay); + +- if (qcrtc->index == 0) ++ if (bo->is_primary == false) + recreate_primary = true; + + if (bo->surf.stride * bo->surf.height > qdev->vram_size) { +@@ -816,13 +816,15 @@ static enum drm_connector_status qxl_conn_detect( + drm_connector_to_qxl_output(connector); + struct drm_device *ddev = connector->dev; + struct qxl_device *qdev = ddev->dev_private; +- int connected; ++ bool connected = false; + + /* The first monitor is always connected */ +- connected = (output->index == 0) || +- (qdev->client_monitors_config && +- qdev->client_monitors_config->count > output->index && +- qxl_head_enabled(&qdev->client_monitors_config->heads[output->index])); ++ if (!qdev->client_monitors_config) { ++ if (output->index == 0) ++ connected = true; ++ } else ++ connected = qdev->client_monitors_config->count > output->index && ++ qxl_head_enabled(&qdev->client_monitors_config->heads[output->index]); + + DRM_DEBUG("#%d connected: %d\n", output->index, connected); + if (!connected) +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index 20b69bff5b34..7393b76b6b63 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -350,6 +350,10 @@ static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1] + + /* NCT6776 specific data */ + ++/* STEP_UP_TIME and STEP_DOWN_TIME regs are swapped for all chips but NCT6775 */ ++#define NCT6776_REG_FAN_STEP_UP_TIME NCT6775_REG_FAN_STEP_DOWN_TIME ++#define NCT6776_REG_FAN_STEP_DOWN_TIME NCT6775_REG_FAN_STEP_UP_TIME ++ + static const s8 NCT6776_ALARM_BITS[] = { + 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */ + 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */ +@@ -3476,8 +3480,8 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES; + data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT; + data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; +- data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; +- data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; ++ data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME; ++ data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME; + data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H; + data->REG_PWM[0] = NCT6775_REG_PWM; + data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; +@@ -3548,8 +3552,8 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES; + data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT; + data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; +- data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; +- data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; ++ data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME; ++ data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME; + data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H; + data->REG_PWM[0] = NCT6775_REG_PWM; + data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; +@@ -3624,8 +3628,8 @@ static int nct6775_probe(struct platform_device *pdev) + data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES; + data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT; + data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; +- data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME; +- data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME; ++ data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME; ++ data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME; + data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H; + data->REG_PWM[0] = NCT6775_REG_PWM; + data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; +diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c +index dd2b610552d5..a49ce4a6e72f 100644 +--- a/drivers/infiniband/ulp/isert/ib_isert.c ++++ b/drivers/infiniband/ulp/isert/ib_isert.c +@@ -2634,9 +2634,16 @@ isert_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, bool recovery) + static int + isert_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state) + { +- int ret; ++ struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd); ++ int ret = 0; + + switch (state) { ++ case ISTATE_REMOVE: ++ spin_lock_bh(&conn->cmd_lock); ++ list_del_init(&cmd->i_conn_node); ++ spin_unlock_bh(&conn->cmd_lock); ++ isert_put_cmd(isert_cmd, true); ++ break; + case ISTATE_SEND_NOPIN_WANT_RESPONSE: + ret = isert_put_nopin(cmd, conn, false); + break; +diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c +index 3ee198b65843..cc7ece1712b5 100644 +--- a/drivers/macintosh/windfarm_core.c ++++ b/drivers/macintosh/windfarm_core.c +@@ -435,7 +435,7 @@ int wf_unregister_client(struct notifier_block *nb) + { + mutex_lock(&wf_lock); + blocking_notifier_chain_unregister(&wf_client_list, nb); +- wf_client_count++; ++ wf_client_count--; + if (wf_client_count == 0) + wf_stop_thread(); + mutex_unlock(&wf_lock); +diff --git a/drivers/md/dm-cache-policy-cleaner.c b/drivers/md/dm-cache-policy-cleaner.c +index b04d1f904d07..2eca9084defe 100644 +--- a/drivers/md/dm-cache-policy-cleaner.c ++++ b/drivers/md/dm-cache-policy-cleaner.c +@@ -434,7 +434,7 @@ static struct dm_cache_policy *wb_create(dm_cblock_t cache_size, + static struct dm_cache_policy_type wb_policy_type = { + .name = "cleaner", + .version = {1, 0, 0}, +- .hint_size = 0, ++ .hint_size = 4, + .owner = THIS_MODULE, + .create = wb_create + }; +diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c +index 59715389b3cf..19cfd7affebe 100644 +--- a/drivers/md/dm-raid.c ++++ b/drivers/md/dm-raid.c +@@ -325,8 +325,7 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size) + */ + if (min_region_size > (1 << 13)) { + /* If not a power of 2, make it the next power of 2 */ +- if (min_region_size & (min_region_size - 1)) +- region_size = 1 << fls(region_size); ++ region_size = roundup_pow_of_two(min_region_size); + DMINFO("Choosing default region size of %lu sectors", + region_size); + } else { +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 2ffd277eb311..31d14d88205b 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -5285,6 +5285,8 @@ EXPORT_SYMBOL_GPL(md_stop_writes); + static void __md_stop(struct mddev *mddev) + { + mddev->ready = 0; ++ /* Ensure ->event_work is done */ ++ flush_workqueue(md_misc_wq); + mddev->pers->stop(mddev); + if (mddev->pers->sync_request && mddev->to_remove == NULL) + mddev->to_remove = &md_redundancy_group; +diff --git a/drivers/md/persistent-data/dm-btree-internal.h b/drivers/md/persistent-data/dm-btree-internal.h +index bf2b80d5c470..8731b6ea026b 100644 +--- a/drivers/md/persistent-data/dm-btree-internal.h ++++ b/drivers/md/persistent-data/dm-btree-internal.h +@@ -138,4 +138,10 @@ int lower_bound(struct btree_node *n, uint64_t key); + + extern struct dm_block_validator btree_node_validator; + ++/* ++ * Value type for upper levels of multi-level btrees. ++ */ ++extern void init_le64_type(struct dm_transaction_manager *tm, ++ struct dm_btree_value_type *vt); ++ + #endif /* DM_BTREE_INTERNAL_H */ +diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c +index a03178e91a79..7c0d75547ccf 100644 +--- a/drivers/md/persistent-data/dm-btree-remove.c ++++ b/drivers/md/persistent-data/dm-btree-remove.c +@@ -544,14 +544,6 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info, + return r; + } + +-static struct dm_btree_value_type le64_type = { +- .context = NULL, +- .size = sizeof(__le64), +- .inc = NULL, +- .dec = NULL, +- .equal = NULL +-}; +- + int dm_btree_remove(struct dm_btree_info *info, dm_block_t root, + uint64_t *keys, dm_block_t *new_root) + { +@@ -559,12 +551,14 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root, + int index = 0, r = 0; + struct shadow_spine spine; + struct btree_node *n; ++ struct dm_btree_value_type le64_vt; + ++ init_le64_type(info->tm, &le64_vt); + init_shadow_spine(&spine, info); + for (level = 0; level < info->levels; level++) { + r = remove_raw(&spine, info, + (level == last_level ? +- &info->value_type : &le64_type), ++ &info->value_type : &le64_vt), + root, keys[level], (unsigned *)&index); + if (r < 0) + break; +diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c +index 1b5e13ec7f96..0dee514ba4c5 100644 +--- a/drivers/md/persistent-data/dm-btree-spine.c ++++ b/drivers/md/persistent-data/dm-btree-spine.c +@@ -249,3 +249,40 @@ int shadow_root(struct shadow_spine *s) + { + return s->root; + } ++ ++static void le64_inc(void *context, const void *value_le) ++{ ++ struct dm_transaction_manager *tm = context; ++ __le64 v_le; ++ ++ memcpy(&v_le, value_le, sizeof(v_le)); ++ dm_tm_inc(tm, le64_to_cpu(v_le)); ++} ++ ++static void le64_dec(void *context, const void *value_le) ++{ ++ struct dm_transaction_manager *tm = context; ++ __le64 v_le; ++ ++ memcpy(&v_le, value_le, sizeof(v_le)); ++ dm_tm_dec(tm, le64_to_cpu(v_le)); ++} ++ ++static int le64_equal(void *context, const void *value1_le, const void *value2_le) ++{ ++ __le64 v1_le, v2_le; ++ ++ memcpy(&v1_le, value1_le, sizeof(v1_le)); ++ memcpy(&v2_le, value2_le, sizeof(v2_le)); ++ return v1_le == v2_le; ++} ++ ++void init_le64_type(struct dm_transaction_manager *tm, ++ struct dm_btree_value_type *vt) ++{ ++ vt->context = tm; ++ vt->size = sizeof(__le64); ++ vt->inc = le64_inc; ++ vt->dec = le64_dec; ++ vt->equal = le64_equal; ++} +diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c +index fdd3793e22f9..c7726cebc495 100644 +--- a/drivers/md/persistent-data/dm-btree.c ++++ b/drivers/md/persistent-data/dm-btree.c +@@ -667,12 +667,7 @@ static int insert(struct dm_btree_info *info, dm_block_t root, + struct btree_node *n; + struct dm_btree_value_type le64_type; + +- le64_type.context = NULL; +- le64_type.size = sizeof(__le64); +- le64_type.inc = NULL; +- le64_type.dec = NULL; +- le64_type.equal = NULL; +- ++ init_le64_type(info->tm, &le64_type); + init_shadow_spine(&spine, info); + + for (level = 0; level < (info->levels - 1); level++) { +diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c +index d058b00ba218..eb3823e25638 100644 +--- a/drivers/mtd/nand/pxa3xx_nand.c ++++ b/drivers/mtd/nand/pxa3xx_nand.c +@@ -1463,6 +1463,9 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) + if (pdata->keep_config && !pxa3xx_nand_detect_config(info)) + goto KEEP_CONFIG; + ++ /* Set a default chunk size */ ++ info->chunk_size = 512; ++ + ret = pxa3xx_nand_sensing(info); + if (ret) { + dev_info(&info->pdev->dev, "There is no chip on cs %d!\n", +diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c +index d36134925d31..db657f2168d7 100644 +--- a/drivers/mtd/ubi/io.c ++++ b/drivers/mtd/ubi/io.c +@@ -921,6 +921,11 @@ static int validate_vid_hdr(const struct ubi_device *ubi, + goto bad; + } + ++ if (data_size > ubi->leb_size) { ++ ubi_err("bad data_size"); ++ goto bad; ++ } ++ + if (vol_type == UBI_VID_STATIC) { + /* + * Although from high-level point of view static volumes may +diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c +index d77b1c1d7c72..bebf49e0dbe9 100644 +--- a/drivers/mtd/ubi/vtbl.c ++++ b/drivers/mtd/ubi/vtbl.c +@@ -651,6 +651,7 @@ static int init_volumes(struct ubi_device *ubi, + if (ubi->corr_peb_count) + ubi_err("%d PEBs are corrupted and not used", + ubi->corr_peb_count); ++ return -ENOSPC; + } + ubi->rsvd_pebs += reserved_pebs; + ubi->avail_pebs -= reserved_pebs; +diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c +index c6b0b078ab99..2060fef7f2d2 100644 +--- a/drivers/mtd/ubi/wl.c ++++ b/drivers/mtd/ubi/wl.c +@@ -1974,6 +1974,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) + if (ubi->corr_peb_count) + ubi_err("%d PEBs are corrupted and not used", + ubi->corr_peb_count); ++ err = -ENOSPC; + goto out_free; + } + ubi->avail_pebs -= reserved_pebs; +diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c +index 5f57e3d35e26..6adf9abdf955 100644 +--- a/drivers/scsi/3w-9xxx.c ++++ b/drivers/scsi/3w-9xxx.c +@@ -225,6 +225,17 @@ static const struct file_operations twa_fops = { + .llseek = noop_llseek, + }; + ++/* ++ * The controllers use an inline buffer instead of a mapped SGL for small, ++ * single entry buffers. Note that we treat a zero-length transfer like ++ * a mapped SGL. ++ */ ++static bool twa_command_mapped(struct scsi_cmnd *cmd) ++{ ++ return scsi_sg_count(cmd) != 1 || ++ scsi_bufflen(cmd) >= TW_MIN_SGL_LENGTH; ++} ++ + /* This function will complete an aen request from the isr */ + static int twa_aen_complete(TW_Device_Extension *tw_dev, int request_id) + { +@@ -1351,7 +1362,8 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) + } + + /* Now complete the io */ +- scsi_dma_unmap(cmd); ++ if (twa_command_mapped(cmd)) ++ scsi_dma_unmap(cmd); + cmd->scsi_done(cmd); + tw_dev->state[request_id] = TW_S_COMPLETED; + twa_free_request_id(tw_dev, request_id); +@@ -1594,7 +1606,8 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev) + struct scsi_cmnd *cmd = tw_dev->srb[i]; + + cmd->result = (DID_RESET << 16); +- scsi_dma_unmap(cmd); ++ if (twa_command_mapped(cmd)) ++ scsi_dma_unmap(cmd); + cmd->scsi_done(cmd); + } + } +@@ -1777,12 +1790,14 @@ static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_ + retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL); + switch (retval) { + case SCSI_MLQUEUE_HOST_BUSY: +- scsi_dma_unmap(SCpnt); ++ if (twa_command_mapped(SCpnt)) ++ scsi_dma_unmap(SCpnt); + twa_free_request_id(tw_dev, request_id); + break; + case 1: + SCpnt->result = (DID_ERROR << 16); +- scsi_dma_unmap(SCpnt); ++ if (twa_command_mapped(SCpnt)) ++ scsi_dma_unmap(SCpnt); + done(SCpnt); + tw_dev->state[request_id] = TW_S_COMPLETED; + twa_free_request_id(tw_dev, request_id); +@@ -1843,8 +1858,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, + /* Map sglist from scsi layer to cmd packet */ + + if (scsi_sg_count(srb)) { +- if ((scsi_sg_count(srb) == 1) && +- (scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) { ++ if (!twa_command_mapped(srb)) { + if (srb->sc_data_direction == DMA_TO_DEVICE || + srb->sc_data_direction == DMA_BIDIRECTIONAL) + scsi_sg_copy_to_buffer(srb, +@@ -1917,7 +1931,7 @@ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re + { + struct scsi_cmnd *cmd = tw_dev->srb[request_id]; + +- if (scsi_bufflen(cmd) < TW_MIN_SGL_LENGTH && ++ if (!twa_command_mapped(cmd) && + (cmd->sc_data_direction == DMA_FROM_DEVICE || + cmd->sc_data_direction == DMA_BIDIRECTIONAL)) { + if (scsi_sg_count(cmd) == 1) { +diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c +index 96b6664bb1cf..787c8a883c3c 100644 +--- a/drivers/scsi/scsi_error.c ++++ b/drivers/scsi/scsi_error.c +@@ -2149,8 +2149,17 @@ int scsi_error_handler(void *data) + * We never actually get interrupted because kthread_run + * disables signal delivery for the created thread. + */ +- while (!kthread_should_stop()) { ++ while (true) { ++ /* ++ * The sequence in kthread_stop() sets the stop flag first ++ * then wakes the process. To avoid missed wakeups, the task ++ * should always be in a non running state before the stop ++ * flag is checked ++ */ + set_current_state(TASK_INTERRUPTIBLE); ++ if (kthread_should_stop()) ++ break; ++ + if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) || + shost->host_failed != shost->host_busy) { + SCSI_LOG_ERROR_RECOVERY(1, +diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c +index 458a1480dc07..ebd32379b178 100644 +--- a/drivers/spi/spi-pxa2xx.c ++++ b/drivers/spi/spi-pxa2xx.c +@@ -562,6 +562,10 @@ static irqreturn_t ssp_int(int irq, void *dev_id) + if (!(sccr1_reg & SSCR1_TIE)) + mask &= ~SSSR_TFS; + ++ /* Ignore RX timeout interrupt if it is disabled */ ++ if (!(sccr1_reg & SSCR1_TINTE)) ++ mask &= ~SSSR_TINT; ++ + if (!(status & mask)) + return IRQ_NONE; + +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index f3e3ae8af709..d88492152be1 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -1251,8 +1251,7 @@ static struct class spi_master_class = { + * + * The caller is responsible for assigning the bus number and initializing + * the master's methods before calling spi_register_master(); and (after errors +- * adding the device) calling spi_master_put() and kfree() to prevent a memory +- * leak. ++ * adding the device) calling spi_master_put() to prevent a memory leak. + */ + struct spi_master *spi_alloc_master(struct device *dev, unsigned size) + { +diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c +index 574066ff73f8..c771b37967b2 100644 +--- a/drivers/staging/android/ion/ion.c ++++ b/drivers/staging/android/ion/ion.c +@@ -1119,13 +1119,13 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) + mutex_unlock(&client->lock); + goto end; + } +- mutex_unlock(&client->lock); + + handle = ion_handle_create(client, buffer); +- if (IS_ERR(handle)) ++ if (IS_ERR(handle)) { ++ mutex_unlock(&client->lock); + goto end; ++ } + +- mutex_lock(&client->lock); + ret = ion_handle_add(client, handle); + mutex_unlock(&client->lock); + if (ret) { +diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c +index 88c60b6020c4..c4ee9fa1dc91 100644 +--- a/drivers/staging/comedi/drivers/usbduxsigma.c ++++ b/drivers/staging/comedi/drivers/usbduxsigma.c +@@ -575,37 +575,6 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev, + if (err) + return 3; + +- /* Step 4: fix up any arguments */ +- +- if (high_speed) { +- /* +- * every 2 channels get a time window of 125us. Thus, if we +- * sample all 16 channels we need 1ms. If we sample only one +- * channel we need only 125us +- */ +- devpriv->ai_interval = interval; +- devpriv->ai_timer = cmd->scan_begin_arg / (125000 * interval); +- } else { +- /* interval always 1ms */ +- devpriv->ai_interval = 1; +- devpriv->ai_timer = cmd->scan_begin_arg / 1000000; +- } +- if (devpriv->ai_timer < 1) +- err |= -EINVAL; +- +- if (cmd->stop_src == TRIG_COUNT) { +- /* data arrives as one packet */ +- devpriv->ai_sample_count = cmd->stop_arg; +- devpriv->ai_continuous = 0; +- } else { +- /* continuous acquisition */ +- devpriv->ai_continuous = 1; +- devpriv->ai_sample_count = 0; +- } +- +- if (err) +- return 4; +- + return 0; + } + +@@ -704,6 +673,33 @@ static int usbduxsigma_ai_cmd(struct comedi_device *dev, + + /* set current channel of the running acquisition to zero */ + s->async->cur_chan = 0; ++ ++ if (devpriv->high_speed) { ++ /* ++ * every 2 channels get a time window of 125us. Thus, if we ++ * sample all 16 channels we need 1ms. If we sample only one ++ * channel we need only 125us ++ */ ++ unsigned int interval = usbduxsigma_chans_to_interval(len); ++ ++ devpriv->ai_interval = interval; ++ devpriv->ai_timer = cmd->scan_begin_arg / (125000 * interval); ++ } else { ++ /* interval always 1ms */ ++ devpriv->ai_interval = 1; ++ devpriv->ai_timer = cmd->scan_begin_arg / 1000000; ++ } ++ ++ if (cmd->stop_src == TRIG_COUNT) { ++ /* data arrives as one packet */ ++ devpriv->ai_sample_count = cmd->stop_arg; ++ devpriv->ai_continuous = 0; ++ } else { ++ /* continuous acquisition */ ++ devpriv->ai_continuous = 1; ++ devpriv->ai_sample_count = 0; ++ } ++ + for (i = 0; i < len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + +@@ -955,10 +951,24 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev, + if (err) + return 3; + +- /* Step 4: fix up any arguments */ ++ return 0; ++} ++ ++static int usbduxsigma_ao_cmd(struct comedi_device *dev, ++ struct comedi_subdevice *s) ++{ ++ struct usbduxsigma_private *devpriv = dev->private; ++ struct comedi_cmd *cmd = &s->async->cmd; ++ int ret; ++ int i; ++ ++ down(&devpriv->sem); ++ ++ /* set current channel of the running acquisition to zero */ ++ s->async->cur_chan = 0; + + /* we count in timer steps */ +- if (high_speed) { ++ if (cmd->convert_src == TRIG_TIMER) { + /* timing of the conversion itself: every 125 us */ + devpriv->ao_timer = cmd->convert_arg / 125000; + } else { +@@ -968,12 +978,9 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev, + */ + devpriv->ao_timer = cmd->scan_begin_arg / 1000000; + } +- if (devpriv->ao_timer < 1) +- err |= -EINVAL; +- + if (cmd->stop_src == TRIG_COUNT) { + /* not continuous, use counter */ +- if (high_speed) { ++ if (cmd->convert_src == TRIG_TIMER) { + /* high speed also scans everything at once */ + devpriv->ao_sample_count = cmd->stop_arg * + cmd->scan_end_arg; +@@ -992,24 +999,6 @@ static int usbduxsigma_ao_cmdtest(struct comedi_device *dev, + devpriv->ao_sample_count = 0; + } + +- if (err) +- return 4; +- +- return 0; +-} +- +-static int usbduxsigma_ao_cmd(struct comedi_device *dev, +- struct comedi_subdevice *s) +-{ +- struct usbduxsigma_private *devpriv = dev->private; +- struct comedi_cmd *cmd = &s->async->cmd; +- int ret; +- int i; +- +- down(&devpriv->sem); +- +- /* set current channel of the running acquisition to zero */ +- s->async->cur_chan = 0; + for (i = 0; i < cmd->chanlist_len; ++i) + devpriv->ao_chanlist[i] = CR_CHAN(cmd->chanlist[i]); + +diff --git a/drivers/staging/speakup/fakekey.c b/drivers/staging/speakup/fakekey.c +index 4299cf45f947..5e1f16c36b49 100644 +--- a/drivers/staging/speakup/fakekey.c ++++ b/drivers/staging/speakup/fakekey.c +@@ -81,6 +81,7 @@ void speakup_fake_down_arrow(void) + __this_cpu_write(reporting_keystroke, true); + input_report_key(virt_keyboard, KEY_DOWN, PRESSED); + input_report_key(virt_keyboard, KEY_DOWN, RELEASED); ++ input_sync(virt_keyboard); + __this_cpu_write(reporting_keystroke, false); + + /* reenable preemption */ +diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c +index 062967c90b2a..3ecc887eea27 100644 +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -113,7 +113,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, + cfgno, inum, asnum, ep->desc.bEndpointAddress); + ep->ss_ep_comp.bmAttributes = 16; + } else if (usb_endpoint_xfer_isoc(&ep->desc) && +- desc->bmAttributes > 2) { ++ USB_SS_MULT(desc->bmAttributes) > 3) { + dev_warn(ddev, "Isoc endpoint has Mult of %d in " + "config %d interface %d altsetting %d ep %d: " + "setting to 3\n", desc->bmAttributes + 1, +@@ -122,7 +122,8 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, + } + + if (usb_endpoint_xfer_isoc(&ep->desc)) +- max_tx = (desc->bMaxBurst + 1) * (desc->bmAttributes + 1) * ++ max_tx = (desc->bMaxBurst + 1) * ++ (USB_SS_MULT(desc->bmAttributes)) * + usb_endpoint_maxp(&ep->desc); + else if (usb_endpoint_xfer_int(&ep->desc)) + max_tx = usb_endpoint_maxp(&ep->desc) * +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index b195fdb1effc..804acc700327 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -54,6 +54,13 @@ static const struct usb_device_id usb_quirk_list[] = { + { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT }, + { USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT }, + ++ /* Logitech ConferenceCam CC3000e */ ++ { USB_DEVICE(0x046d, 0x0847), .driver_info = USB_QUIRK_DELAY_INIT }, ++ { USB_DEVICE(0x046d, 0x0848), .driver_info = USB_QUIRK_DELAY_INIT }, ++ ++ /* Logitech PTZ Pro Camera */ ++ { USB_DEVICE(0x046d, 0x0853), .driver_info = USB_QUIRK_DELAY_INIT }, ++ + /* Logitech Quickcam Fusion */ + { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, + +@@ -78,6 +85,12 @@ static const struct usb_device_id usb_quirk_list[] = { + /* Philips PSC805 audio device */ + { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* Plantronic Audio 655 DSP */ ++ { USB_DEVICE(0x047f, 0xc008), .driver_info = USB_QUIRK_RESET_RESUME }, ++ ++ /* Plantronic Audio 648 USB */ ++ { USB_DEVICE(0x047f, 0xc013), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* Artisman Watchdog Dongle */ + { USB_DEVICE(0x04b4, 0x0526), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index f8893b32bbb6..86bfaf904ab5 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -1402,10 +1402,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, + * use Event Data TRBs, and we don't chain in a link TRB on short + * transfers, we're basically dividing by 1. + * +- * xHCI 1.0 specification indicates that the Average TRB Length should +- * be set to 8 for control endpoints. ++ * xHCI 1.0 and 1.1 specification indicates that the Average TRB Length ++ * should be set to 8 for control endpoints. + */ +- if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version == 0x100) ++ if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100) + ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(8)); + else + ep_ctx->tx_info |= +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index a365e9769fcc..86a0ddd8efb7 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -3223,9 +3223,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, + struct xhci_td *td; + struct scatterlist *sg; + int num_sgs; +- int trb_buff_len, this_sg_len, running_total; ++ int trb_buff_len, this_sg_len, running_total, ret; + unsigned int total_packet_count; ++ bool zero_length_needed; + bool first_trb; ++ int last_trb_num; + u64 addr; + bool more_trbs_coming; + +@@ -3241,13 +3243,27 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, + total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length, + usb_endpoint_maxp(&urb->ep->desc)); + +- trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id], ++ ret = prepare_transfer(xhci, xhci->devs[slot_id], + ep_index, urb->stream_id, + num_trbs, urb, 0, mem_flags); +- if (trb_buff_len < 0) +- return trb_buff_len; ++ if (ret < 0) ++ return ret; + + urb_priv = urb->hcpriv; ++ ++ /* Deal with URB_ZERO_PACKET - need one more td/trb */ ++ zero_length_needed = urb->transfer_flags & URB_ZERO_PACKET && ++ urb_priv->length == 2; ++ if (zero_length_needed) { ++ num_trbs++; ++ xhci_dbg(xhci, "Creating zero length td.\n"); ++ ret = prepare_transfer(xhci, xhci->devs[slot_id], ++ ep_index, urb->stream_id, ++ 1, urb, 1, mem_flags); ++ if (ret < 0) ++ return ret; ++ } ++ + td = urb_priv->td[0]; + + /* +@@ -3277,6 +3293,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, + trb_buff_len = urb->transfer_buffer_length; + + first_trb = true; ++ last_trb_num = zero_length_needed ? 2 : 1; + /* Queue the first TRB, even if it's zero-length */ + do { + u32 field = 0; +@@ -3294,12 +3311,15 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, + /* Chain all the TRBs together; clear the chain bit in the last + * TRB to indicate it's the last TRB in the chain. + */ +- if (num_trbs > 1) { ++ if (num_trbs > last_trb_num) { + field |= TRB_CHAIN; +- } else { +- /* FIXME - add check for ZERO_PACKET flag before this */ ++ } else if (num_trbs == last_trb_num) { + td->last_trb = ep_ring->enqueue; + field |= TRB_IOC; ++ } else if (zero_length_needed && num_trbs == 1) { ++ trb_buff_len = 0; ++ urb_priv->td[1]->last_trb = ep_ring->enqueue; ++ field |= TRB_IOC; + } + + /* Only set interrupt on short packet for IN endpoints */ +@@ -3361,7 +3381,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, + if (running_total + trb_buff_len > urb->transfer_buffer_length) + trb_buff_len = + urb->transfer_buffer_length - running_total; +- } while (running_total < urb->transfer_buffer_length); ++ } while (num_trbs > 0); + + check_trb_math(urb, num_trbs, running_total); + giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, +@@ -3379,7 +3399,9 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, + int num_trbs; + struct xhci_generic_trb *start_trb; + bool first_trb; ++ int last_trb_num; + bool more_trbs_coming; ++ bool zero_length_needed; + int start_cycle; + u32 field, length_field; + +@@ -3410,7 +3432,6 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, + num_trbs++; + running_total += TRB_MAX_BUFF_SIZE; + } +- /* FIXME: this doesn't deal with URB_ZERO_PACKET - need one more */ + + ret = prepare_transfer(xhci, xhci->devs[slot_id], + ep_index, urb->stream_id, +@@ -3419,6 +3440,20 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, + return ret; + + urb_priv = urb->hcpriv; ++ ++ /* Deal with URB_ZERO_PACKET - need one more td/trb */ ++ zero_length_needed = urb->transfer_flags & URB_ZERO_PACKET && ++ urb_priv->length == 2; ++ if (zero_length_needed) { ++ num_trbs++; ++ xhci_dbg(xhci, "Creating zero length td.\n"); ++ ret = prepare_transfer(xhci, xhci->devs[slot_id], ++ ep_index, urb->stream_id, ++ 1, urb, 1, mem_flags); ++ if (ret < 0) ++ return ret; ++ } ++ + td = urb_priv->td[0]; + + /* +@@ -3440,7 +3475,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, + trb_buff_len = urb->transfer_buffer_length; + + first_trb = true; +- ++ last_trb_num = zero_length_needed ? 2 : 1; + /* Queue the first TRB, even if it's zero-length */ + do { + u32 remainder = 0; +@@ -3457,12 +3492,15 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, + /* Chain all the TRBs together; clear the chain bit in the last + * TRB to indicate it's the last TRB in the chain. + */ +- if (num_trbs > 1) { ++ if (num_trbs > last_trb_num) { + field |= TRB_CHAIN; +- } else { +- /* FIXME - add check for ZERO_PACKET flag before this */ ++ } else if (num_trbs == last_trb_num) { + td->last_trb = ep_ring->enqueue; + field |= TRB_IOC; ++ } else if (zero_length_needed && num_trbs == 1) { ++ trb_buff_len = 0; ++ urb_priv->td[1]->last_trb = ep_ring->enqueue; ++ field |= TRB_IOC; + } + + /* Only set interrupt on short packet for IN endpoints */ +@@ -3500,7 +3538,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, + trb_buff_len = urb->transfer_buffer_length - running_total; + if (trb_buff_len > TRB_MAX_BUFF_SIZE) + trb_buff_len = TRB_MAX_BUFF_SIZE; +- } while (running_total < urb->transfer_buffer_length); ++ } while (num_trbs > 0); + + check_trb_math(urb, num_trbs, running_total); + giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, +@@ -3567,8 +3605,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, + if (start_cycle == 0) + field |= 0x1; + +- /* xHCI 1.0 6.4.1.2.1: Transfer Type field */ +- if (xhci->hci_version == 0x100) { ++ /* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */ ++ if (xhci->hci_version >= 0x100) { + if (urb->transfer_buffer_length > 0) { + if (setup->bRequestType & USB_DIR_IN) + field |= TRB_TX_TYPE(TRB_DATA_IN); +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index fc61e663b00a..79c7b255e60a 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -147,7 +147,8 @@ static int xhci_start(struct xhci_hcd *xhci) + "waited %u microseconds.\n", + XHCI_MAX_HALT_USEC); + if (!ret) +- xhci->xhc_state &= ~XHCI_STATE_HALTED; ++ xhci->xhc_state &= ~(XHCI_STATE_HALTED | XHCI_STATE_DYING); ++ + return ret; + } + +@@ -1319,6 +1320,11 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) + + if (usb_endpoint_xfer_isoc(&urb->ep->desc)) + size = urb->number_of_packets; ++ else if (usb_endpoint_is_bulk_out(&urb->ep->desc) && ++ urb->transfer_buffer_length > 0 && ++ urb->transfer_flags & URB_ZERO_PACKET && ++ !(urb->transfer_buffer_length % usb_endpoint_maxp(&urb->ep->desc))) ++ size = 2; + else + size = 1; + +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index 096438e4fb0c..c918075e5eae 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -276,6 +276,10 @@ static void option_instat_callback(struct urb *urb); + #define ZTE_PRODUCT_MF622 0x0001 + #define ZTE_PRODUCT_MF628 0x0015 + #define ZTE_PRODUCT_MF626 0x0031 ++#define ZTE_PRODUCT_ZM8620_X 0x0396 ++#define ZTE_PRODUCT_ME3620_MBIM 0x0426 ++#define ZTE_PRODUCT_ME3620_X 0x1432 ++#define ZTE_PRODUCT_ME3620_L 0x1433 + #define ZTE_PRODUCT_AC2726 0xfff1 + #define ZTE_PRODUCT_CDMA_TECH 0xfffe + #define ZTE_PRODUCT_AC8710T 0xffff +@@ -549,6 +553,18 @@ static const struct option_blacklist_info zte_mc2716_z_blacklist = { + .sendsetup = BIT(1) | BIT(2) | BIT(3), + }; + ++static const struct option_blacklist_info zte_me3620_mbim_blacklist = { ++ .reserved = BIT(2) | BIT(3) | BIT(4), ++}; ++ ++static const struct option_blacklist_info zte_me3620_xl_blacklist = { ++ .reserved = BIT(3) | BIT(4) | BIT(5), ++}; ++ ++static const struct option_blacklist_info zte_zm8620_x_blacklist = { ++ .reserved = BIT(3) | BIT(4) | BIT(5), ++}; ++ + static const struct option_blacklist_info huawei_cdc12_blacklist = { + .reserved = BIT(1) | BIT(2), + }; +@@ -1579,6 +1595,14 @@ static const struct usb_device_id option_ids[] = { + .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist }, ++ { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_L), ++ .driver_info = (kernel_ulong_t)&zte_me3620_xl_blacklist }, ++ { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_MBIM), ++ .driver_info = (kernel_ulong_t)&zte_me3620_mbim_blacklist }, ++ { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_X), ++ .driver_info = (kernel_ulong_t)&zte_me3620_xl_blacklist }, ++ { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ZM8620_X), ++ .driver_info = (kernel_ulong_t)&zte_zm8620_x_blacklist }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) }, +diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c +index 6c3734d2b45a..d3ea90bef84d 100644 +--- a/drivers/usb/serial/whiteheat.c ++++ b/drivers/usb/serial/whiteheat.c +@@ -80,6 +80,8 @@ static int whiteheat_firmware_download(struct usb_serial *serial, + static int whiteheat_firmware_attach(struct usb_serial *serial); + + /* function prototypes for the Connect Tech WhiteHEAT serial converter */ ++static int whiteheat_probe(struct usb_serial *serial, ++ const struct usb_device_id *id); + static int whiteheat_attach(struct usb_serial *serial); + static void whiteheat_release(struct usb_serial *serial); + static int whiteheat_port_probe(struct usb_serial_port *port); +@@ -116,6 +118,7 @@ static struct usb_serial_driver whiteheat_device = { + .description = "Connect Tech - WhiteHEAT", + .id_table = id_table_std, + .num_ports = 4, ++ .probe = whiteheat_probe, + .attach = whiteheat_attach, + .release = whiteheat_release, + .port_probe = whiteheat_port_probe, +@@ -217,6 +220,34 @@ static int whiteheat_firmware_attach(struct usb_serial *serial) + /***************************************************************************** + * Connect Tech's White Heat serial driver functions + *****************************************************************************/ ++ ++static int whiteheat_probe(struct usb_serial *serial, ++ const struct usb_device_id *id) ++{ ++ struct usb_host_interface *iface_desc; ++ struct usb_endpoint_descriptor *endpoint; ++ size_t num_bulk_in = 0; ++ size_t num_bulk_out = 0; ++ size_t min_num_bulk; ++ unsigned int i; ++ ++ iface_desc = serial->interface->cur_altsetting; ++ ++ for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { ++ endpoint = &iface_desc->endpoint[i].desc; ++ if (usb_endpoint_is_bulk_in(endpoint)) ++ ++num_bulk_in; ++ if (usb_endpoint_is_bulk_out(endpoint)) ++ ++num_bulk_out; ++ } ++ ++ min_num_bulk = COMMAND_PORT + 1; ++ if (num_bulk_in < min_num_bulk || num_bulk_out < min_num_bulk) ++ return -ENODEV; ++ ++ return 0; ++} ++ + static int whiteheat_attach(struct usb_serial *serial) + { + struct usb_serial_port *command_port; +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 8adfc65b37dd..332999288b51 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -2681,7 +2681,8 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree, + bio_end_io_t end_io_func, + int mirror_num, + unsigned long prev_bio_flags, +- unsigned long bio_flags) ++ unsigned long bio_flags, ++ bool force_bio_submit) + { + int ret = 0; + struct bio *bio; +@@ -2699,6 +2700,7 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree, + contig = bio_end_sector(bio) == sector; + + if (prev_bio_flags != bio_flags || !contig || ++ force_bio_submit || + merge_bio(rw, tree, page, offset, page_size, bio, bio_flags) || + bio_add_page(bio, page, page_size, offset) < page_size) { + ret = submit_one_bio(rw, bio, mirror_num, +@@ -2790,7 +2792,8 @@ static int __do_readpage(struct extent_io_tree *tree, + get_extent_t *get_extent, + struct extent_map **em_cached, + struct bio **bio, int mirror_num, +- unsigned long *bio_flags, int rw) ++ unsigned long *bio_flags, int rw, ++ u64 *prev_em_start) + { + struct inode *inode = page->mapping->host; + u64 start = page_offset(page); +@@ -2838,6 +2841,7 @@ static int __do_readpage(struct extent_io_tree *tree, + } + while (cur <= end) { + unsigned long pnr = (last_byte >> PAGE_CACHE_SHIFT) + 1; ++ bool force_bio_submit = false; + + if (cur >= last_byte) { + char *userpage; +@@ -2888,6 +2892,49 @@ static int __do_readpage(struct extent_io_tree *tree, + block_start = em->block_start; + if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) + block_start = EXTENT_MAP_HOLE; ++ ++ /* ++ * If we have a file range that points to a compressed extent ++ * and it's followed by a consecutive file range that points to ++ * to the same compressed extent (possibly with a different ++ * offset and/or length, so it either points to the whole extent ++ * or only part of it), we must make sure we do not submit a ++ * single bio to populate the pages for the 2 ranges because ++ * this makes the compressed extent read zero out the pages ++ * belonging to the 2nd range. Imagine the following scenario: ++ * ++ * File layout ++ * [0 - 8K] [8K - 24K] ++ * | | ++ * | | ++ * points to extent X, points to extent X, ++ * offset 4K, length of 8K offset 0, length 16K ++ * ++ * [extent X, compressed length = 4K uncompressed length = 16K] ++ * ++ * If the bio to read the compressed extent covers both ranges, ++ * it will decompress extent X into the pages belonging to the ++ * first range and then it will stop, zeroing out the remaining ++ * pages that belong to the other range that points to extent X. ++ * So here we make sure we submit 2 bios, one for the first ++ * range and another one for the third range. Both will target ++ * the same physical extent from disk, but we can't currently ++ * make the compressed bio endio callback populate the pages ++ * for both ranges because each compressed bio is tightly ++ * coupled with a single extent map, and each range can have ++ * an extent map with a different offset value relative to the ++ * uncompressed data of our extent and different lengths. This ++ * is a corner case so we prioritize correctness over ++ * non-optimal behavior (submitting 2 bios for the same extent). ++ */ ++ if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags) && ++ prev_em_start && *prev_em_start != (u64)-1 && ++ *prev_em_start != em->orig_start) ++ force_bio_submit = true; ++ ++ if (prev_em_start) ++ *prev_em_start = em->orig_start; ++ + free_extent_map(em); + em = NULL; + +@@ -2937,7 +2984,8 @@ static int __do_readpage(struct extent_io_tree *tree, + bdev, bio, pnr, + end_bio_extent_readpage, mirror_num, + *bio_flags, +- this_bio_flag); ++ this_bio_flag, ++ force_bio_submit); + if (!ret) { + nr++; + *bio_flags = this_bio_flag; +@@ -2964,7 +3012,8 @@ static inline void __do_contiguous_readpages(struct extent_io_tree *tree, + get_extent_t *get_extent, + struct extent_map **em_cached, + struct bio **bio, int mirror_num, +- unsigned long *bio_flags, int rw) ++ unsigned long *bio_flags, int rw, ++ u64 *prev_em_start) + { + struct inode *inode; + struct btrfs_ordered_extent *ordered; +@@ -2984,7 +3033,7 @@ static inline void __do_contiguous_readpages(struct extent_io_tree *tree, + + for (index = 0; index < nr_pages; index++) { + __do_readpage(tree, pages[index], get_extent, em_cached, bio, +- mirror_num, bio_flags, rw); ++ mirror_num, bio_flags, rw, prev_em_start); + page_cache_release(pages[index]); + } + } +@@ -2994,7 +3043,8 @@ static void __extent_readpages(struct extent_io_tree *tree, + int nr_pages, get_extent_t *get_extent, + struct extent_map **em_cached, + struct bio **bio, int mirror_num, +- unsigned long *bio_flags, int rw) ++ unsigned long *bio_flags, int rw, ++ u64 *prev_em_start) + { + u64 start = 0; + u64 end = 0; +@@ -3015,7 +3065,7 @@ static void __extent_readpages(struct extent_io_tree *tree, + index - first_index, start, + end, get_extent, em_cached, + bio, mirror_num, bio_flags, +- rw); ++ rw, prev_em_start); + start = page_start; + end = start + PAGE_CACHE_SIZE - 1; + first_index = index; +@@ -3026,7 +3076,8 @@ static void __extent_readpages(struct extent_io_tree *tree, + __do_contiguous_readpages(tree, &pages[first_index], + index - first_index, start, + end, get_extent, em_cached, bio, +- mirror_num, bio_flags, rw); ++ mirror_num, bio_flags, rw, ++ prev_em_start); + } + + static int __extent_read_full_page(struct extent_io_tree *tree, +@@ -3052,7 +3103,7 @@ static int __extent_read_full_page(struct extent_io_tree *tree, + } + + ret = __do_readpage(tree, page, get_extent, NULL, bio, mirror_num, +- bio_flags, rw); ++ bio_flags, rw, NULL); + return ret; + } + +@@ -3078,7 +3129,7 @@ int extent_read_full_page_nolock(struct extent_io_tree *tree, struct page *page, + int ret; + + ret = __do_readpage(tree, page, get_extent, NULL, &bio, mirror_num, +- &bio_flags, READ); ++ &bio_flags, READ, NULL); + if (bio) + ret = submit_one_bio(READ, bio, mirror_num, bio_flags); + return ret; +@@ -3347,7 +3398,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, + sector, iosize, pg_offset, + bdev, &epd->bio, max_nr, + end_bio_extent_writepage, +- 0, 0, 0); ++ 0, 0, 0, false); + if (ret) + SetPageError(page); + } +@@ -3516,7 +3567,7 @@ static int write_one_eb(struct extent_buffer *eb, + ret = submit_extent_page(rw, tree, p, offset >> 9, + PAGE_CACHE_SIZE, 0, bdev, &epd->bio, + -1, end_bio_extent_buffer_writepage, +- 0, epd->bio_flags, bio_flags); ++ 0, epd->bio_flags, bio_flags, false); + epd->bio_flags = bio_flags; + if (ret) { + set_bit(EXTENT_BUFFER_IOERR, &eb->bflags); +@@ -3918,6 +3969,7 @@ int extent_readpages(struct extent_io_tree *tree, + struct page *page; + struct extent_map *em_cached = NULL; + int nr = 0; ++ u64 prev_em_start = (u64)-1; + + for (page_idx = 0; page_idx < nr_pages; page_idx++) { + page = list_entry(pages->prev, struct page, lru); +@@ -3934,12 +3986,12 @@ int extent_readpages(struct extent_io_tree *tree, + if (nr < ARRAY_SIZE(pagepool)) + continue; + __extent_readpages(tree, pagepool, nr, get_extent, &em_cached, +- &bio, 0, &bio_flags, READ); ++ &bio, 0, &bio_flags, READ, &prev_em_start); + nr = 0; + } + if (nr) + __extent_readpages(tree, pagepool, nr, get_extent, &em_cached, +- &bio, 0, &bio_flags, READ); ++ &bio, 0, &bio_flags, READ, &prev_em_start); + + if (em_cached) + free_extent_map(em_cached); +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 653cdd85e0f2..eaf8699ed559 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -4668,7 +4668,8 @@ void btrfs_evict_inode(struct inode *inode) + goto no_delete; + } + /* do we really want it for ->i_nlink > 0 and zero btrfs_root_refs? */ +- btrfs_wait_ordered_range(inode, 0, (u64)-1); ++ if (!special_file(inode->i_mode)) ++ btrfs_wait_ordered_range(inode, 0, (u64)-1); + + if (root->fs_info->log_root_recovering) { + BUG_ON(test_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, +diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c +index 4934347321d3..3299778391fd 100644 +--- a/fs/cifs/cifsencrypt.c ++++ b/fs/cifs/cifsencrypt.c +@@ -441,6 +441,48 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp) + return 0; + } + ++/* Server has provided av pairs/target info in the type 2 challenge ++ * packet and we have plucked it and stored within smb session. ++ * We parse that blob here to find the server given timestamp ++ * as part of ntlmv2 authentication (or local current time as ++ * default in case of failure) ++ */ ++static __le64 ++find_timestamp(struct cifs_ses *ses) ++{ ++ unsigned int attrsize; ++ unsigned int type; ++ unsigned int onesize = sizeof(struct ntlmssp2_name); ++ unsigned char *blobptr; ++ unsigned char *blobend; ++ struct ntlmssp2_name *attrptr; ++ ++ if (!ses->auth_key.len || !ses->auth_key.response) ++ return 0; ++ ++ blobptr = ses->auth_key.response; ++ blobend = blobptr + ses->auth_key.len; ++ ++ while (blobptr + onesize < blobend) { ++ attrptr = (struct ntlmssp2_name *) blobptr; ++ type = le16_to_cpu(attrptr->type); ++ if (type == NTLMSSP_AV_EOL) ++ break; ++ blobptr += 2; /* advance attr type */ ++ attrsize = le16_to_cpu(attrptr->length); ++ blobptr += 2; /* advance attr size */ ++ if (blobptr + attrsize > blobend) ++ break; ++ if (type == NTLMSSP_AV_TIMESTAMP) { ++ if (attrsize == sizeof(u64)) ++ return *((__le64 *)blobptr); ++ } ++ blobptr += attrsize; /* advance attr value */ ++ } ++ ++ return cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); ++} ++ + static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, + const struct nls_table *nls_cp) + { +@@ -637,6 +679,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) + struct ntlmv2_resp *ntlmv2; + char ntlmv2_hash[16]; + unsigned char *tiblob = NULL; /* target info blob */ ++ __le64 rsp_timestamp; + + if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) { + if (!ses->domainName) { +@@ -655,6 +698,12 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) + } + } + ++ /* Must be within 5 minutes of the server (or in range +/-2h ++ * in case of Mac OS X), so simply carry over server timestamp ++ * (as Windows 7 does) ++ */ ++ rsp_timestamp = find_timestamp(ses); ++ + baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp); + tilen = ses->auth_key.len; + tiblob = ses->auth_key.response; +@@ -671,8 +720,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) + (ses->auth_key.response + CIFS_SESS_KEY_SIZE); + ntlmv2->blob_signature = cpu_to_le32(0x00000101); + ntlmv2->reserved = 0; +- /* Must be within 5 minutes of the server */ +- ntlmv2->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); ++ ntlmv2->time = rsp_timestamp; ++ + get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal)); + ntlmv2->reserved2 = 0; + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 30f3eb5bc022..6aeb1de0fa23 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -49,9 +49,13 @@ change_conf(struct TCP_Server_Info *server) + break; + default: + server->echoes = true; +- server->oplocks = true; ++ if (enable_oplocks) { ++ server->oplocks = true; ++ server->oplock_credits = 1; ++ } else ++ server->oplocks = false; ++ + server->echo_credits = 1; +- server->oplock_credits = 1; + } + server->credits -= server->echo_credits + server->oplock_credits; + return 0; +diff --git a/fs/dcache.c b/fs/dcache.c +index df323f809e03..65ccdf0e2854 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -2787,6 +2787,13 @@ restart: + + if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) { + struct mount *parent = ACCESS_ONCE(mnt->mnt_parent); ++ /* Escaped? */ ++ if (dentry != vfsmnt->mnt_root) { ++ bptr = *buffer; ++ blen = *buflen; ++ error = 3; ++ break; ++ } + /* Global root? */ + if (mnt != parent) { + dentry = ACCESS_ONCE(mnt->mnt_mountpoint); +diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c +index b892355f1944..d4c7e470dec8 100644 +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -475,14 +475,15 @@ int jbd2_cleanup_journal_tail(journal_t *journal) + * journal_clean_one_cp_list + * + * Find all the written-back checkpoint buffers in the given list and +- * release them. ++ * release them. If 'destroy' is set, clean all buffers unconditionally. + * + * Called with the journal locked. + * Called with j_list_lock held. + * Returns number of buffers reaped (for debug) + */ + +-static int journal_clean_one_cp_list(struct journal_head *jh, int *released) ++static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy, ++ int *released) + { + struct journal_head *last_jh; + struct journal_head *next_jh = jh; +@@ -496,7 +497,10 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released) + do { + jh = next_jh; + next_jh = jh->b_cpnext; +- ret = __try_to_free_cp_buf(jh); ++ if (!destroy) ++ ret = __try_to_free_cp_buf(jh); ++ else ++ ret = __jbd2_journal_remove_checkpoint(jh) + 1; + if (ret) { + freed++; + if (ret == 2) { +@@ -521,13 +525,14 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released) + * journal_clean_checkpoint_list + * + * Find all the written-back checkpoint buffers in the journal and release them. ++ * If 'destroy' is set, release all buffers unconditionally. + * + * Called with the journal locked. + * Called with j_list_lock held. + * Returns number of buffers reaped (for debug) + */ + +-int __jbd2_journal_clean_checkpoint_list(journal_t *journal) ++int __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy) + { + transaction_t *transaction, *last_transaction, *next_transaction; + int ret = 0; +@@ -543,7 +548,7 @@ int __jbd2_journal_clean_checkpoint_list(journal_t *journal) + transaction = next_transaction; + next_transaction = transaction->t_cpnext; + ret += journal_clean_one_cp_list(transaction-> +- t_checkpoint_list, &released); ++ t_checkpoint_list, destroy, &released); + /* + * This function only frees up some memory if possible so we + * dont have an obligation to finish processing. Bail out if +@@ -559,7 +564,7 @@ int __jbd2_journal_clean_checkpoint_list(journal_t *journal) + * we can possibly see not yet submitted buffers on io_list + */ + ret += journal_clean_one_cp_list(transaction-> +- t_checkpoint_io_list, &released); ++ t_checkpoint_io_list, destroy, &released); + if (need_resched()) + goto out; + } while (transaction != last_transaction); +@@ -568,6 +573,28 @@ out: + } + + /* ++ * Remove buffers from all checkpoint lists as journal is aborted and we just ++ * need to free memory ++ */ ++void jbd2_journal_destroy_checkpoint(journal_t *journal) ++{ ++ /* ++ * We loop because __jbd2_journal_clean_checkpoint_list() may abort ++ * early due to a need of rescheduling. ++ */ ++ while (1) { ++ spin_lock(&journal->j_list_lock); ++ if (!journal->j_checkpoint_transactions) { ++ spin_unlock(&journal->j_list_lock); ++ break; ++ } ++ __jbd2_journal_clean_checkpoint_list(journal, true); ++ spin_unlock(&journal->j_list_lock); ++ cond_resched(); ++ } ++} ++ ++/* + * journal_remove_checkpoint: called after a buffer has been committed + * to disk (either by being write-back flushed to disk, or being + * committed to the log). +diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c +index 9181c2b22b3c..4207cf2caa87 100644 +--- a/fs/jbd2/commit.c ++++ b/fs/jbd2/commit.c +@@ -510,7 +510,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) + * frees some memory + */ + spin_lock(&journal->j_list_lock); +- __jbd2_journal_clean_checkpoint_list(journal); ++ __jbd2_journal_clean_checkpoint_list(journal, false); + spin_unlock(&journal->j_list_lock); + + jbd_debug(3, "JBD2: commit phase 1\n"); +diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c +index e8d62d742435..3b607a8609c4 100644 +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -1708,8 +1708,17 @@ int jbd2_journal_destroy(journal_t *journal) + while (journal->j_checkpoint_transactions != NULL) { + spin_unlock(&journal->j_list_lock); + mutex_lock(&journal->j_checkpoint_mutex); +- jbd2_log_do_checkpoint(journal); ++ err = jbd2_log_do_checkpoint(journal); + mutex_unlock(&journal->j_checkpoint_mutex); ++ /* ++ * If checkpointing failed, just free the buffers to avoid ++ * looping forever ++ */ ++ if (err) { ++ jbd2_journal_destroy_checkpoint(journal); ++ spin_lock(&journal->j_list_lock); ++ break; ++ } + spin_lock(&journal->j_list_lock); + } + +diff --git a/fs/namei.c b/fs/namei.c +index c6fa07942b2a..f4f6460b6958 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -484,6 +484,24 @@ void path_put(const struct path *path) + } + EXPORT_SYMBOL(path_put); + ++/** ++ * path_connected - Verify that a path->dentry is below path->mnt.mnt_root ++ * @path: nameidate to verify ++ * ++ * Rename can sometimes move a file or directory outside of a bind ++ * mount, path_connected allows those cases to be detected. ++ */ ++static bool path_connected(const struct path *path) ++{ ++ struct vfsmount *mnt = path->mnt; ++ ++ /* Only bind mounts can have disconnected paths */ ++ if (mnt->mnt_root == mnt->mnt_sb->s_root) ++ return true; ++ ++ return is_subdir(path->dentry, mnt->mnt_root); ++} ++ + /* + * Path walking has 2 modes, rcu-walk and ref-walk (see + * Documentation/filesystems/path-lookup.txt). In situations when we can't +@@ -1149,6 +1167,8 @@ static int follow_dotdot_rcu(struct nameidata *nd) + goto failed; + nd->path.dentry = parent; + nd->seq = seq; ++ if (unlikely(!path_connected(&nd->path))) ++ goto failed; + break; + } + if (!follow_up_rcu(&nd->path)) +@@ -1242,7 +1262,7 @@ static void follow_mount(struct path *path) + } + } + +-static void follow_dotdot(struct nameidata *nd) ++static int follow_dotdot(struct nameidata *nd) + { + if (!nd->root.mnt) + set_root(nd); +@@ -1258,6 +1278,10 @@ static void follow_dotdot(struct nameidata *nd) + /* rare case of legitimate dget_parent()... */ + nd->path.dentry = dget_parent(nd->path.dentry); + dput(old); ++ if (unlikely(!path_connected(&nd->path))) { ++ path_put(&nd->path); ++ return -ENOENT; ++ } + break; + } + if (!follow_up(&nd->path)) +@@ -1265,6 +1289,7 @@ static void follow_dotdot(struct nameidata *nd) + } + follow_mount(&nd->path); + nd->inode = nd->path.dentry->d_inode; ++ return 0; + } + + /* +@@ -1488,7 +1513,7 @@ static inline int handle_dots(struct nameidata *nd, int type) + if (follow_dotdot_rcu(nd)) + return -ECHILD; + } else +- follow_dotdot(nd); ++ return follow_dotdot(nd); + } + return 0; + } +@@ -2214,7 +2239,7 @@ mountpoint_last(struct nameidata *nd, struct path *path) + if (unlikely(nd->last_type != LAST_NORM)) { + error = handle_dots(nd, nd->last_type); + if (error) +- goto out; ++ return error; + dentry = dget(nd->path.dentry); + goto done; + } +diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h +index e1fb0f613a99..385593d748f6 100644 +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -1042,8 +1042,9 @@ void jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); + extern void jbd2_journal_commit_transaction(journal_t *); + + /* Checkpoint list management */ +-int __jbd2_journal_clean_checkpoint_list(journal_t *journal); ++int __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy); + int __jbd2_journal_remove_checkpoint(struct journal_head *); ++void jbd2_journal_destroy_checkpoint(journal_t *journal); + void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *); + + +diff --git a/include/linux/security.h b/include/linux/security.h +index 2fc42d191f79..2a8f853750c7 100644 +--- a/include/linux/security.h ++++ b/include/linux/security.h +@@ -2452,7 +2452,7 @@ static inline int security_task_prctl(int option, unsigned long arg2, + unsigned long arg4, + unsigned long arg5) + { +- return cap_task_prctl(option, arg2, arg3, arg3, arg5); ++ return cap_task_prctl(option, arg2, arg3, arg4, arg5); + } + + static inline void security_task_to_inode(struct task_struct *p, struct inode *inode) +diff --git a/include/xen/interface/sched.h b/include/xen/interface/sched.h +index 9ce083960a25..f18490985fc8 100644 +--- a/include/xen/interface/sched.h ++++ b/include/xen/interface/sched.h +@@ -107,5 +107,13 @@ struct sched_watchdog { + #define SHUTDOWN_suspend 2 /* Clean up, save suspend info, kill. */ + #define SHUTDOWN_crash 3 /* Tell controller we've crashed. */ + #define SHUTDOWN_watchdog 4 /* Restart because watchdog time expired. */ ++/* ++ * Domain asked to perform 'soft reset' for it. The expected behavior is to ++ * reset internal Xen state for the domain returning it to the point where it ++ * was created but leaving the domain's memory contents and vCPU contexts ++ * intact. This will allow the domain to start over and set up all Xen specific ++ * interfaces again. ++ */ ++#define SHUTDOWN_soft_reset 5 + + #endif /* __XEN_PUBLIC_SCHED_H__ */ +diff --git a/ipc/msg.c b/ipc/msg.c +index 649853105a5d..4a036c619607 100644 +--- a/ipc/msg.c ++++ b/ipc/msg.c +@@ -202,13 +202,6 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params) + return retval; + } + +- /* ipc_addid() locks msq upon success. */ +- id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni); +- if (id < 0) { +- ipc_rcu_putref(msq, msg_rcu_free); +- return id; +- } +- + msq->q_stime = msq->q_rtime = 0; + msq->q_ctime = get_seconds(); + msq->q_cbytes = msq->q_qnum = 0; +@@ -218,6 +211,13 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params) + INIT_LIST_HEAD(&msq->q_receivers); + INIT_LIST_HEAD(&msq->q_senders); + ++ /* ipc_addid() locks msq upon success. */ ++ id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni); ++ if (id < 0) { ++ ipc_rcu_putref(msq, msg_rcu_free); ++ return id; ++ } ++ + ipc_unlock_object(&msq->q_perm); + rcu_read_unlock(); + +diff --git a/ipc/shm.c b/ipc/shm.c +index 76459616a7fa..ada866d768a6 100644 +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -543,12 +543,6 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) + if (IS_ERR(file)) + goto no_file; + +- id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni); +- if (id < 0) { +- error = id; +- goto no_id; +- } +- + shp->shm_cprid = task_tgid_vnr(current); + shp->shm_lprid = 0; + shp->shm_atim = shp->shm_dtim = 0; +@@ -558,6 +552,12 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) + shp->shm_file = file; + shp->shm_creator = current; + ++ id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni); ++ if (id < 0) { ++ error = id; ++ goto no_id; ++ } ++ + /* + * shmid gets reported as "inode#" in /proc/pid/maps. + * proc-ps tools use this. Changing this will break them. +diff --git a/ipc/util.c b/ipc/util.c +index e1b4c6db8aa0..cdb19ce3f358 100644 +--- a/ipc/util.c ++++ b/ipc/util.c +@@ -277,6 +277,10 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int size) + rcu_read_lock(); + spin_lock(&new->lock); + ++ current_euid_egid(&euid, &egid); ++ new->cuid = new->uid = euid; ++ new->gid = new->cgid = egid; ++ + id = idr_alloc(&ids->ipcs_idr, new, + (next_id < 0) ? 0 : ipcid_to_idx(next_id), 0, + GFP_NOWAIT); +@@ -289,10 +293,6 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int size) + + ids->in_use++; + +- current_euid_egid(&euid, &egid); +- new->cuid = new->uid = euid; +- new->gid = new->cgid = egid; +- + if (next_id < 0) { + new->seq = ids->seq++; + if (ids->seq > IPCID_SEQ_MAX) +diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c +index 095cd7230aef..56d7272199ff 100644 +--- a/kernel/irq/proc.c ++++ b/kernel/irq/proc.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + + #include "internals.h" + +@@ -326,18 +327,29 @@ void register_handler_proc(unsigned int irq, struct irqaction *action) + + void register_irq_proc(unsigned int irq, struct irq_desc *desc) + { ++ static DEFINE_MUTEX(register_lock); + char name [MAX_NAMELEN]; + +- if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip) || desc->dir) ++ if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip)) + return; + ++ /* ++ * irq directories are registered only when a handler is ++ * added, not when the descriptor is created, so multiple ++ * tasks might try to register at the same time. ++ */ ++ mutex_lock(®ister_lock); ++ ++ if (desc->dir) ++ goto out_unlock; ++ + memset(name, 0, MAX_NAMELEN); + sprintf(name, "%d", irq); + + /* create /proc/irq/1234 */ + desc->dir = proc_mkdir(name, root_irq_dir); + if (!desc->dir) +- return; ++ goto out_unlock; + + #ifdef CONFIG_SMP + /* create /proc/irq//smp_affinity */ +@@ -358,6 +370,9 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc) + + proc_create_data("spurious", 0444, desc->dir, + &irq_spurious_proc_fops, (void *)(long)irq); ++ ++out_unlock: ++ mutex_unlock(®ister_lock); + } + + void unregister_irq_proc(unsigned int irq, struct irq_desc *desc) +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 5e973efc036e..a19262a7d70b 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -2136,11 +2136,11 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev) + * If a task dies, then it sets TASK_DEAD in tsk->state and calls + * schedule one last time. The schedule call will never return, and + * the scheduled task must drop that reference. +- * The test for TASK_DEAD must occur while the runqueue locks are +- * still held, otherwise prev could be scheduled on another cpu, die +- * there before we look at prev->state, and then the reference would +- * be dropped twice. +- * Manfred Spraul ++ * ++ * We must observe prev->state before clearing prev->on_cpu (in ++ * finish_lock_switch), otherwise a concurrent wakeup can get prev ++ * running on another CPU and we could rave with its RUNNING -> DEAD ++ * transition, resulting in a double drop. + */ + prev_state = prev->state; + vtime_task_switch(prev); +diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h +index f964add50f38..835b6efa8bd6 100644 +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -994,9 +994,10 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev) + * After ->on_cpu is cleared, the task can be moved to a different CPU. + * We must ensure this doesn't happen until the switch is completely + * finished. ++ * ++ * Pairs with the control dependency and rmb in try_to_wake_up(). + */ +- smp_wmb(); +- prev->on_cpu = 0; ++ smp_store_release(&prev->on_cpu, 0); + #endif + #ifdef CONFIG_DEBUG_SPINLOCK + /* this is a valid case when another task releases the spinlock */ +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index c3e8660cb616..86cbb2f13715 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -2615,6 +2615,14 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma, + continue; + + /* ++ * Shared VMAs have their own reserves and do not affect ++ * MAP_PRIVATE accounting but it is possible that a shared ++ * VMA is using the same page so check and skip such VMAs. ++ */ ++ if (iter_vma->vm_flags & VM_MAYSHARE) ++ continue; ++ ++ /* + * Unmap the page from other VMAs without their own reserves. + * They get marked to be SIGKILLed if they fault in these + * areas. This is because a future no-page fault on this VMA +diff --git a/mm/slab.c b/mm/slab.c +index 0b1c2a58559d..844ea1e89568 100644 +--- a/mm/slab.c ++++ b/mm/slab.c +@@ -2271,9 +2271,16 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) + size += BYTES_PER_WORD; + } + #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC) +- if (size >= kmalloc_size(INDEX_NODE + 1) +- && cachep->object_size > cache_line_size() +- && ALIGN(size, cachep->align) < PAGE_SIZE) { ++ /* ++ * To activate debug pagealloc, off-slab management is necessary ++ * requirement. In early phase of initialization, small sized slab ++ * doesn't get initialized so it would not be possible. So, we need ++ * to check size >= 256. It guarantees that all necessary small ++ * sized slab is initialized in current slab initialization sequence. ++ */ ++ if (!slab_early_init && size >= kmalloc_size(INDEX_NODE) && ++ size >= 256 && cachep->object_size > cache_line_size() && ++ ALIGN(size, cachep->align) < PAGE_SIZE) { + cachep->obj_offset += PAGE_SIZE - ALIGN(size, cachep->align); + size = PAGE_SIZE; + } +diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c +index aeedc3a961a1..99ae718b79be 100644 +--- a/net/core/fib_rules.c ++++ b/net/core/fib_rules.c +@@ -631,7 +631,7 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb, + err = fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, RTM_NEWRULE, + NLM_F_MULTI, ops); +- if (err) ++ if (err < 0) + break; + skip: + idx++; +diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c +index a8027e73b6a2..a108953a8c2c 100644 +--- a/net/netfilter/ipvs/ip_vs_sync.c ++++ b/net/netfilter/ipvs/ip_vs_sync.c +@@ -612,7 +612,7 @@ static void ip_vs_sync_conn_v0(struct net *net, struct ip_vs_conn *cp, + pkts = atomic_add_return(1, &cp->in_pkts); + else + pkts = sysctl_sync_threshold(ipvs); +- ip_vs_sync_conn(net, cp->control, pkts); ++ ip_vs_sync_conn(net, cp, pkts); + } + } + +diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c +index 1692e7534759..c3d204973dbc 100644 +--- a/net/netfilter/ipvs/ip_vs_xmit.c ++++ b/net/netfilter/ipvs/ip_vs_xmit.c +@@ -129,7 +129,6 @@ static struct rtable *do_output_route4(struct net *net, __be32 daddr, + + memset(&fl4, 0, sizeof(fl4)); + fl4.daddr = daddr; +- fl4.saddr = (rt_mode & IP_VS_RT_MODE_CONNECT) ? *saddr : 0; + fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ? + FLOWI_FLAG_KNOWN_NH : 0; + +diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c +index 4fd1ca94fd4a..71c46f463969 100644 +--- a/net/netfilter/nf_conntrack_expect.c ++++ b/net/netfilter/nf_conntrack_expect.c +@@ -202,7 +202,8 @@ static inline int expect_clash(const struct nf_conntrack_expect *a, + a->mask.src.u3.all[count] & b->mask.src.u3.all[count]; + } + +- return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask); ++ return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask) && ++ nf_ct_zone(a->master) == nf_ct_zone(b->master); + } + + static inline int expect_matches(const struct nf_conntrack_expect *a, +diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c +index b9f0e0374322..7d5dcd2a9092 100644 +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -2927,11 +2927,6 @@ ctnetlink_create_expect(struct net *net, u16 zone, + } + + err = nf_ct_expect_related_report(exp, portid, report); +- if (err < 0) +- goto err_exp; +- +- return 0; +-err_exp: + nf_ct_expect_put(exp); + err_ct: + nf_ct_put(ct); +diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c +index 969589590814..82273b83de8e 100644 +--- a/net/netfilter/nft_compat.c ++++ b/net/netfilter/nft_compat.c +@@ -594,6 +594,13 @@ struct nft_xt { + + static struct nft_expr_type nft_match_type; + ++static bool nft_match_cmp(const struct xt_match *match, ++ const char *name, u32 rev, u32 family) ++{ ++ return strcmp(match->name, name) == 0 && match->revision == rev && ++ (match->family == NFPROTO_UNSPEC || match->family == family); ++} ++ + static const struct nft_expr_ops * + nft_match_select_ops(const struct nft_ctx *ctx, + const struct nlattr * const tb[]) +@@ -601,7 +608,7 @@ nft_match_select_ops(const struct nft_ctx *ctx, + struct nft_xt *nft_match; + struct xt_match *match; + char *mt_name; +- __u32 rev, family; ++ u32 rev, family; + + if (tb[NFTA_MATCH_NAME] == NULL || + tb[NFTA_MATCH_REV] == NULL || +@@ -616,8 +623,7 @@ nft_match_select_ops(const struct nft_ctx *ctx, + list_for_each_entry(nft_match, &nft_match_list, head) { + struct xt_match *match = nft_match->ops.data; + +- if (strcmp(match->name, mt_name) == 0 && +- match->revision == rev && match->family == family) { ++ if (nft_match_cmp(match, mt_name, rev, family)) { + if (!try_module_get(match->me)) + return ERR_PTR(-ENOENT); + +@@ -669,6 +675,13 @@ static LIST_HEAD(nft_target_list); + + static struct nft_expr_type nft_target_type; + ++static bool nft_target_cmp(const struct xt_target *tg, ++ const char *name, u32 rev, u32 family) ++{ ++ return strcmp(tg->name, name) == 0 && tg->revision == rev && ++ (tg->family == NFPROTO_UNSPEC || tg->family == family); ++} ++ + static const struct nft_expr_ops * + nft_target_select_ops(const struct nft_ctx *ctx, + const struct nlattr * const tb[]) +@@ -676,7 +689,7 @@ nft_target_select_ops(const struct nft_ctx *ctx, + struct nft_xt *nft_target; + struct xt_target *target; + char *tg_name; +- __u32 rev, family; ++ u32 rev, family; + + if (tb[NFTA_TARGET_NAME] == NULL || + tb[NFTA_TARGET_REV] == NULL || +@@ -691,8 +704,7 @@ nft_target_select_ops(const struct nft_ctx *ctx, + list_for_each_entry(nft_target, &nft_target_list, head) { + struct xt_target *target = nft_target->ops.data; + +- if (strcmp(target->name, tg_name) == 0 && +- target->revision == rev && target->family == family) { ++ if (nft_target_cmp(target, tg_name, rev, family)) { + if (!try_module_get(target->me)) + return ERR_PTR(-ENOENT); + +diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig +index 885683a3b0bd..e0406211716b 100644 +--- a/sound/arm/Kconfig ++++ b/sound/arm/Kconfig +@@ -9,6 +9,14 @@ menuconfig SND_ARM + Drivers that are implemented on ASoC can be found in + "ALSA for SoC audio support" section. + ++config SND_PXA2XX_LIB ++ tristate ++ select SND_AC97_CODEC if SND_PXA2XX_LIB_AC97 ++ select SND_DMAENGINE_PCM ++ ++config SND_PXA2XX_LIB_AC97 ++ bool ++ + if SND_ARM + + config SND_ARMAACI +@@ -21,13 +29,6 @@ config SND_PXA2XX_PCM + tristate + select SND_PCM + +-config SND_PXA2XX_LIB +- tristate +- select SND_AC97_CODEC if SND_PXA2XX_LIB_AC97 +- +-config SND_PXA2XX_LIB_AC97 +- bool +- + config SND_PXA2XX_AC97 + tristate "AC97 driver for the Intel PXA2xx chip" + depends on ARCH_PXA +diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c +index 7b0aac9d27ca..3c90743fa50b 100644 +--- a/sound/pci/hda/patch_cirrus.c ++++ b/sound/pci/hda/patch_cirrus.c +@@ -637,6 +637,7 @@ static const struct snd_pci_quirk cs4208_mac_fixup_tbl[] = { + SND_PCI_QUIRK(0x106b, 0x5e00, "MacBookPro 11,2", CS4208_MBP11), + SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6), + SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6), ++ SND_PCI_QUIRK(0x106b, 0x7b00, "MacBookPro 12,1", CS4208_MBP11), + {} /* terminator */ + }; + +diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c +index 2f6357578616..1b6cbbc95456 100644 +--- a/sound/soc/dwc/designware_i2s.c ++++ b/sound/soc/dwc/designware_i2s.c +@@ -100,10 +100,10 @@ static inline void i2s_clear_irqs(struct dw_i2s_dev *dev, u32 stream) + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + for (i = 0; i < 4; i++) +- i2s_write_reg(dev->i2s_base, TOR(i), 0); ++ i2s_read_reg(dev->i2s_base, TOR(i)); + } else { + for (i = 0; i < 4; i++) +- i2s_write_reg(dev->i2s_base, ROR(i), 0); ++ i2s_read_reg(dev->i2s_base, ROR(i)); + } + } + +diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig +index 6473052b6899..9f4ea3f2bbb5 100644 +--- a/sound/soc/pxa/Kconfig ++++ b/sound/soc/pxa/Kconfig +@@ -1,7 +1,6 @@ + config SND_PXA2XX_SOC + tristate "SoC Audio for the Intel PXA2xx chip" + depends on ARCH_PXA +- select SND_ARM + select SND_PXA2XX_LIB + help + Say Y or M if you want to add support for codecs attached to +@@ -24,7 +23,6 @@ config SND_PXA2XX_AC97 + config SND_PXA2XX_SOC_AC97 + tristate + select AC97_BUS +- select SND_ARM + select SND_PXA2XX_LIB_AC97 + select SND_SOC_AC97_BUS + +diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c +index ae956e3f4b9d..593e3202fc35 100644 +--- a/sound/soc/pxa/pxa2xx-ac97.c ++++ b/sound/soc/pxa/pxa2xx-ac97.c +@@ -49,7 +49,7 @@ static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { + .reset = pxa2xx_ac97_cold_reset, + }; + +-static unsigned long pxa2xx_ac97_pcm_stereo_in_req = 12; ++static unsigned long pxa2xx_ac97_pcm_stereo_in_req = 11; + static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_in = { + .addr = __PREG(PCDR), + .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, +@@ -57,7 +57,7 @@ static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_in = { + .filter_data = &pxa2xx_ac97_pcm_stereo_in_req, + }; + +-static unsigned long pxa2xx_ac97_pcm_stereo_out_req = 11; ++static unsigned long pxa2xx_ac97_pcm_stereo_out_req = 12; + static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_out = { + .addr = __PREG(PCDR), + .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, +diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c +index daf61abc3670..646b66703bd8 100644 +--- a/sound/synth/emux/emux_oss.c ++++ b/sound/synth/emux/emux_oss.c +@@ -69,7 +69,8 @@ snd_emux_init_seq_oss(struct snd_emux *emu) + struct snd_seq_oss_reg *arg; + struct snd_seq_device *dev; + +- if (snd_seq_device_new(emu->card, 0, SNDRV_SEQ_DEV_ID_OSS, ++ /* using device#1 here for avoiding conflicts with OPL3 */ ++ if (snd_seq_device_new(emu->card, 1, SNDRV_SEQ_DEV_ID_OSS, + sizeof(struct snd_seq_oss_reg), &dev) < 0) + return; + +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index 8b0e1c9234d9..8801d5cdafae 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -1108,7 +1108,7 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) + static void print_aggr(char *prefix) + { + struct perf_evsel *counter; +- int cpu, cpu2, s, s2, id, nr; ++ int cpu, s, s2, id, nr; + double uval; + u64 ena, run, val; + +@@ -1121,8 +1121,7 @@ static void print_aggr(char *prefix) + val = ena = run = 0; + nr = 0; + for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { +- cpu2 = perf_evsel__cpus(counter)->map[cpu]; +- s2 = aggr_get_id(evsel_list->cpus, cpu2); ++ s2 = aggr_get_id(perf_evsel__cpus(counter), cpu); + if (s2 != id) + continue; + val += counter->counts->cpu[cpu].val; +diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c +index 893f8e2df928..96592f7bfa9f 100644 +--- a/tools/perf/util/header.c ++++ b/tools/perf/util/header.c +@@ -1715,7 +1715,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused, + if (ph->needs_swap) + nr = bswap_32(nr); + +- ph->env.nr_cpus_online = nr; ++ ph->env.nr_cpus_avail = nr; + + ret = readn(fd, &nr, sizeof(nr)); + if (ret != sizeof(nr)) +@@ -1724,7 +1724,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused, + if (ph->needs_swap) + nr = bswap_32(nr); + +- ph->env.nr_cpus_avail = nr; ++ ph->env.nr_cpus_online = nr; + return 0; + } + +diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c +index e4e6249b87d4..24a506974610 100644 +--- a/tools/perf/util/hist.c ++++ b/tools/perf/util/hist.c +@@ -160,6 +160,9 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) + hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12); + hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12); + ++ if (h->srcline) ++ hists__new_col_len(hists, HISTC_SRCLINE, strlen(h->srcline)); ++ + if (h->transaction) + hists__new_col_len(hists, HISTC_TRANSACTION, + hist_entry__transaction_len()); +diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c +index 516d19fb999b..8bd904bd9009 100644 +--- a/tools/perf/util/symbol-elf.c ++++ b/tools/perf/util/symbol-elf.c +@@ -1100,8 +1100,6 @@ out_close: + static int kcore__init(struct kcore *kcore, char *filename, int elfclass, + bool temp) + { +- GElf_Ehdr *ehdr; +- + kcore->elfclass = elfclass; + + if (temp) +@@ -1118,9 +1116,7 @@ static int kcore__init(struct kcore *kcore, char *filename, int elfclass, + if (!gelf_newehdr(kcore->elf, elfclass)) + goto out_end; + +- ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr); +- if (!ehdr) +- goto out_end; ++ memset(&kcore->ehdr, 0, sizeof(GElf_Ehdr)); + + return 0; + +@@ -1177,23 +1173,18 @@ static int kcore__copy_hdr(struct kcore *from, struct kcore *to, size_t count) + static int kcore__add_phdr(struct kcore *kcore, int idx, off_t offset, + u64 addr, u64 len) + { +- GElf_Phdr gphdr; +- GElf_Phdr *phdr; +- +- phdr = gelf_getphdr(kcore->elf, idx, &gphdr); +- if (!phdr) +- return -1; +- +- phdr->p_type = PT_LOAD; +- phdr->p_flags = PF_R | PF_W | PF_X; +- phdr->p_offset = offset; +- phdr->p_vaddr = addr; +- phdr->p_paddr = 0; +- phdr->p_filesz = len; +- phdr->p_memsz = len; +- phdr->p_align = page_size; +- +- if (!gelf_update_phdr(kcore->elf, idx, phdr)) ++ GElf_Phdr phdr = { ++ .p_type = PT_LOAD, ++ .p_flags = PF_R | PF_W | PF_X, ++ .p_offset = offset, ++ .p_vaddr = addr, ++ .p_paddr = 0, ++ .p_filesz = len, ++ .p_memsz = len, ++ .p_align = page_size, ++ }; ++ ++ if (!gelf_update_phdr(kcore->elf, idx, &phdr)) + return -1; + + return 0; +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index eed250e9c218..d7d950f51b55 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -2797,10 +2797,25 @@ static void kvm_io_bus_destroy(struct kvm_io_bus *bus) + static inline int kvm_io_bus_cmp(const struct kvm_io_range *r1, + const struct kvm_io_range *r2) + { +- if (r1->addr < r2->addr) ++ gpa_t addr1 = r1->addr; ++ gpa_t addr2 = r2->addr; ++ ++ if (addr1 < addr2) + return -1; +- if (r1->addr + r1->len > r2->addr + r2->len) ++ ++ /* If r2->len == 0, match the exact address. If r2->len != 0, ++ * accept any overlapping write. Any order is acceptable for ++ * overlapping ranges, because kvm_io_bus_get_first_dev ensures ++ * we process all of them. ++ */ ++ if (r2->len) { ++ addr1 += r1->len; ++ addr2 += r2->len; ++ } ++ ++ if (addr1 > addr2) + return 1; ++ + return 0; + } + diff --git a/patch/kernel/cubox-default/patch-3.14.55-56.patch b/patch/kernel/cubox-default/patch-3.14.55-56.patch new file mode 100644 index 000000000..83b202c46 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.55-56.patch @@ -0,0 +1,782 @@ +diff --git a/Makefile b/Makefile +index 97d18c1d27f2..2a13d9d63880 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 55 ++SUBLEVEL = 56 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile +index 0ab1a34dab58..dcc26850727d 100644 +--- a/arch/arm64/Makefile ++++ b/arch/arm64/Makefile +@@ -35,7 +35,7 @@ comma = , + CHECKFLAGS += -D__aarch64__ + + ifeq ($(CONFIG_ARM64_ERRATUM_843419), y) +-CFLAGS_MODULE += -mcmodel=large ++KBUILD_CFLAGS_MODULE += -mcmodel=large + endif + + # Default value +diff --git a/arch/sparc/crypto/aes_glue.c b/arch/sparc/crypto/aes_glue.c +index ded4cee35318..dc78cdd43e0a 100644 +--- a/arch/sparc/crypto/aes_glue.c ++++ b/arch/sparc/crypto/aes_glue.c +@@ -433,6 +433,7 @@ static struct crypto_alg algs[] = { { + .blkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, ++ .ivsize = AES_BLOCK_SIZE, + .setkey = aes_set_key, + .encrypt = cbc_encrypt, + .decrypt = cbc_decrypt, +@@ -452,6 +453,7 @@ static struct crypto_alg algs[] = { { + .blkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, ++ .ivsize = AES_BLOCK_SIZE, + .setkey = aes_set_key, + .encrypt = ctr_crypt, + .decrypt = ctr_crypt, +diff --git a/arch/sparc/crypto/camellia_glue.c b/arch/sparc/crypto/camellia_glue.c +index 641f55cb61c3..eb87d6dd86b1 100644 +--- a/arch/sparc/crypto/camellia_glue.c ++++ b/arch/sparc/crypto/camellia_glue.c +@@ -274,6 +274,7 @@ static struct crypto_alg algs[] = { { + .blkcipher = { + .min_keysize = CAMELLIA_MIN_KEY_SIZE, + .max_keysize = CAMELLIA_MAX_KEY_SIZE, ++ .ivsize = CAMELLIA_BLOCK_SIZE, + .setkey = camellia_set_key, + .encrypt = cbc_encrypt, + .decrypt = cbc_decrypt, +diff --git a/arch/sparc/crypto/des_glue.c b/arch/sparc/crypto/des_glue.c +index d11500972994..1359bfc544e4 100644 +--- a/arch/sparc/crypto/des_glue.c ++++ b/arch/sparc/crypto/des_glue.c +@@ -429,6 +429,7 @@ static struct crypto_alg algs[] = { { + .blkcipher = { + .min_keysize = DES_KEY_SIZE, + .max_keysize = DES_KEY_SIZE, ++ .ivsize = DES_BLOCK_SIZE, + .setkey = des_set_key, + .encrypt = cbc_encrypt, + .decrypt = cbc_decrypt, +@@ -485,6 +486,7 @@ static struct crypto_alg algs[] = { { + .blkcipher = { + .min_keysize = DES3_EDE_KEY_SIZE, + .max_keysize = DES3_EDE_KEY_SIZE, ++ .ivsize = DES3_EDE_BLOCK_SIZE, + .setkey = des3_ede_set_key, + .encrypt = cbc3_encrypt, + .decrypt = cbc3_decrypt, +diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h +index b39e194f6c8d..999b4a3e65f5 100644 +--- a/arch/x86/include/asm/preempt.h ++++ b/arch/x86/include/asm/preempt.h +@@ -105,9 +105,9 @@ static __always_inline bool __preempt_count_dec_and_test(void) + /* + * Returns true when we need to resched and can (barring IRQ state). + */ +-static __always_inline bool should_resched(void) ++static __always_inline bool should_resched(int preempt_offset) + { +- return unlikely(!__this_cpu_read_4(__preempt_count)); ++ return unlikely(__this_cpu_read_4(__preempt_count) == preempt_offset); + } + + #ifdef CONFIG_PREEMPT +diff --git a/crypto/ahash.c b/crypto/ahash.c +index a92dc382f781..865ef923eda6 100644 +--- a/crypto/ahash.c ++++ b/crypto/ahash.c +@@ -465,7 +465,8 @@ static int ahash_prepare_alg(struct ahash_alg *alg) + struct crypto_alg *base = &alg->halg.base; + + if (alg->halg.digestsize > PAGE_SIZE / 8 || +- alg->halg.statesize > PAGE_SIZE / 8) ++ alg->halg.statesize > PAGE_SIZE / 8 || ++ alg->halg.statesize == 0) + return -EINVAL; + + base->cra_type = &crypto_ahash_type; +diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c +index b583773e4ecb..2ea515509ca6 100644 +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -4851,7 +4851,6 @@ static int rbd_dev_probe_parent(struct rbd_device *rbd_dev) + out_err: + if (parent) { + rbd_dev_unparent(rbd_dev); +- kfree(rbd_dev->header_name); + rbd_dev_destroy(parent); + } else { + rbd_put_client(rbdc); +diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c +index 7903e0ed3c75..a5846b34fdd9 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c ++++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c +@@ -183,8 +183,30 @@ nouveau_fbcon_sync(struct fb_info *info) + return 0; + } + ++static int ++nouveau_fbcon_open(struct fb_info *info, int user) ++{ ++ struct nouveau_fbdev *fbcon = info->par; ++ struct nouveau_drm *drm = nouveau_drm(fbcon->dev); ++ int ret = pm_runtime_get_sync(drm->dev->dev); ++ if (ret < 0 && ret != -EACCES) ++ return ret; ++ return 0; ++} ++ ++static int ++nouveau_fbcon_release(struct fb_info *info, int user) ++{ ++ struct nouveau_fbdev *fbcon = info->par; ++ struct nouveau_drm *drm = nouveau_drm(fbcon->dev); ++ pm_runtime_put(drm->dev->dev); ++ return 0; ++} ++ + static struct fb_ops nouveau_fbcon_ops = { + .owner = THIS_MODULE, ++ .fb_open = nouveau_fbcon_open, ++ .fb_release = nouveau_fbcon_release, + .fb_check_var = drm_fb_helper_check_var, + .fb_set_par = drm_fb_helper_set_par, + .fb_fillrect = nouveau_fbcon_fillrect, +@@ -200,6 +222,8 @@ static struct fb_ops nouveau_fbcon_ops = { + + static struct fb_ops nouveau_fbcon_sw_ops = { + .owner = THIS_MODULE, ++ .fb_open = nouveau_fbcon_open, ++ .fb_release = nouveau_fbcon_release, + .fb_check_var = drm_fb_helper_check_var, + .fb_set_par = drm_fb_helper_set_par, + .fb_fillrect = cfb_fillrect, +diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c +index 11d06c7b5afa..1af604a4512a 100644 +--- a/drivers/gpu/drm/radeon/radeon_display.c ++++ b/drivers/gpu/drm/radeon/radeon_display.c +@@ -1479,18 +1479,8 @@ int radeon_modeset_init(struct radeon_device *rdev) + radeon_fbdev_init(rdev); + drm_kms_helper_poll_init(rdev->ddev); + +- if (rdev->pm.dpm_enabled) { +- /* do dpm late init */ +- ret = radeon_pm_late_init(rdev); +- if (ret) { +- rdev->pm.dpm_enabled = false; +- DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n"); +- } +- /* set the dpm state for PX since there won't be +- * a modeset to call this. +- */ +- radeon_pm_compute_clocks(rdev); +- } ++ /* do pm late init */ ++ ret = radeon_pm_late_init(rdev); + + return 0; + } +diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c +index 0095ee7fce34..214adc6d2a68 100644 +--- a/drivers/gpu/drm/radeon/radeon_pm.c ++++ b/drivers/gpu/drm/radeon/radeon_pm.c +@@ -1153,14 +1153,6 @@ static int radeon_pm_init_old(struct radeon_device *rdev) + INIT_DELAYED_WORK(&rdev->pm.dynpm_idle_work, radeon_dynpm_idle_work_handler); + + if (rdev->pm.num_power_states > 1) { +- /* where's the best place to put these? */ +- ret = device_create_file(rdev->dev, &dev_attr_power_profile); +- if (ret) +- DRM_ERROR("failed to create device file for power profile\n"); +- ret = device_create_file(rdev->dev, &dev_attr_power_method); +- if (ret) +- DRM_ERROR("failed to create device file for power method\n"); +- + if (radeon_debugfs_pm_init(rdev)) { + DRM_ERROR("Failed to register debugfs file for PM!\n"); + } +@@ -1218,20 +1210,6 @@ static int radeon_pm_init_dpm(struct radeon_device *rdev) + goto dpm_failed; + rdev->pm.dpm_enabled = true; + +- ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state); +- if (ret) +- DRM_ERROR("failed to create device file for dpm state\n"); +- ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level); +- if (ret) +- DRM_ERROR("failed to create device file for dpm state\n"); +- /* XXX: these are noops for dpm but are here for backwards compat */ +- ret = device_create_file(rdev->dev, &dev_attr_power_profile); +- if (ret) +- DRM_ERROR("failed to create device file for power profile\n"); +- ret = device_create_file(rdev->dev, &dev_attr_power_method); +- if (ret) +- DRM_ERROR("failed to create device file for power method\n"); +- + if (radeon_debugfs_pm_init(rdev)) { + DRM_ERROR("Failed to register debugfs file for dpm!\n"); + } +@@ -1371,9 +1349,44 @@ int radeon_pm_late_init(struct radeon_device *rdev) + int ret = 0; + + if (rdev->pm.pm_method == PM_METHOD_DPM) { +- mutex_lock(&rdev->pm.mutex); +- ret = radeon_dpm_late_enable(rdev); +- mutex_unlock(&rdev->pm.mutex); ++ if (rdev->pm.dpm_enabled) { ++ ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state); ++ if (ret) ++ DRM_ERROR("failed to create device file for dpm state\n"); ++ ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level); ++ if (ret) ++ DRM_ERROR("failed to create device file for dpm state\n"); ++ /* XXX: these are noops for dpm but are here for backwards compat */ ++ ret = device_create_file(rdev->dev, &dev_attr_power_profile); ++ if (ret) ++ DRM_ERROR("failed to create device file for power profile\n"); ++ ret = device_create_file(rdev->dev, &dev_attr_power_method); ++ if (ret) ++ DRM_ERROR("failed to create device file for power method\n"); ++ ++ mutex_lock(&rdev->pm.mutex); ++ ret = radeon_dpm_late_enable(rdev); ++ mutex_unlock(&rdev->pm.mutex); ++ if (ret) { ++ rdev->pm.dpm_enabled = false; ++ DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n"); ++ } else { ++ /* set the dpm state for PX since there won't be ++ * a modeset to call this. ++ */ ++ radeon_pm_compute_clocks(rdev); ++ } ++ } ++ } else { ++ if (rdev->pm.num_power_states > 1) { ++ /* where's the best place to put these? */ ++ ret = device_create_file(rdev->dev, &dev_attr_power_profile); ++ if (ret) ++ DRM_ERROR("failed to create device file for power profile\n"); ++ ret = device_create_file(rdev->dev, &dev_attr_power_method); ++ if (ret) ++ DRM_ERROR("failed to create device file for power method\n"); ++ } + } + return ret; + } +diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c +index d0bdac0498ce..f7439c556413 100644 +--- a/drivers/i2c/busses/i2c-designware-platdrv.c ++++ b/drivers/i2c/busses/i2c-designware-platdrv.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -53,6 +54,22 @@ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev) + } + + #ifdef CONFIG_ACPI ++/* ++ * The HCNT/LCNT information coming from ACPI should be the most accurate ++ * for given platform. However, some systems get it wrong. On such systems ++ * we get better results by calculating those based on the input clock. ++ */ ++static const struct dmi_system_id dw_i2c_no_acpi_params[] = { ++ { ++ .ident = "Dell Inspiron 7348", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7348"), ++ }, ++ }, ++ { } ++}; ++ + static void dw_i2c_acpi_params(struct platform_device *pdev, char method[], + u16 *hcnt, u16 *lcnt, u32 *sda_hold) + { +@@ -60,6 +77,9 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[], + acpi_handle handle = ACPI_HANDLE(&pdev->dev); + union acpi_object *obj; + ++ if (dmi_check_system(dw_i2c_no_acpi_params)) ++ return; ++ + if (ACPI_FAILURE(acpi_evaluate_object(handle, method, NULL, &buf))) + return; + +diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c +index d3c5d6216575..32812d3e5411 100644 +--- a/drivers/i2c/busses/i2c-rcar.c ++++ b/drivers/i2c/busses/i2c-rcar.c +@@ -712,15 +712,16 @@ static int rcar_i2c_probe(struct platform_device *pdev) + return ret; + } + ++ pm_runtime_enable(dev); ++ platform_set_drvdata(pdev, priv); ++ + ret = i2c_add_numbered_adapter(adap); + if (ret < 0) { + dev_err(dev, "reg adap failed: %d\n", ret); ++ pm_runtime_disable(dev); + return ret; + } + +- pm_runtime_enable(dev); +- platform_set_drvdata(pdev, priv); +- + dev_info(dev, "probed\n"); + + return 0; +diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c +index 79a211782766..a272988f8f10 100644 +--- a/drivers/i2c/busses/i2c-s3c2410.c ++++ b/drivers/i2c/busses/i2c-s3c2410.c +@@ -1198,17 +1198,19 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + i2c->adap.nr = i2c->pdata->bus_num; + i2c->adap.dev.of_node = pdev->dev.of_node; + ++ platform_set_drvdata(pdev, i2c); ++ ++ pm_runtime_enable(&pdev->dev); ++ + ret = i2c_add_numbered_adapter(&i2c->adap); + if (ret < 0) { + dev_err(&pdev->dev, "failed to add bus to i2c core\n"); ++ pm_runtime_disable(&pdev->dev); + s3c24xx_i2c_deregister_cpufreq(i2c); + clk_unprepare(i2c->clk); + return ret; + } + +- platform_set_drvdata(pdev, i2c); +- +- pm_runtime_enable(&pdev->dev); + pm_runtime_enable(&i2c->adap.dev); + + dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev)); +diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c +index c1120eb96d86..b94e4648c199 100644 +--- a/drivers/md/dm-thin.c ++++ b/drivers/md/dm-thin.c +@@ -2373,7 +2373,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv) + metadata_low_callback, + pool); + if (r) +- goto out_free_pt; ++ goto out_flags_changed; + + pt->callbacks.congested_fn = pool_is_congested; + dm_table_add_target_callbacks(ti->table, &pt->callbacks); +diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c +index 6c9c16d76935..f606b5ba611f 100644 +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -313,7 +313,6 @@ static void pppoe_flush_dev(struct net_device *dev) + if (po->pppoe_dev == dev && + sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) { + pppox_unbind_sock(sk); +- sk->sk_state = PPPOX_ZOMBIE; + sk->sk_state_change(sk); + po->pppoe_dev = NULL; + dev_put(dev); +diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c +index 5d194093f3e1..816d511e34d3 100644 +--- a/drivers/net/usb/asix_devices.c ++++ b/drivers/net/usb/asix_devices.c +@@ -465,19 +465,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) + return ret; + } + +- ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL); +- if (ret < 0) +- return ret; +- +- msleep(150); +- +- ret = asix_sw_reset(dev, AX_SWRESET_CLEAR); +- if (ret < 0) +- return ret; +- +- msleep(150); +- +- ret = asix_sw_reset(dev, embd_phy ? AX_SWRESET_IPRL : AX_SWRESET_PRTE); ++ ax88772_reset(dev); + + /* Read PHYID register *AFTER* the PHY was reset properly */ + phyid = asix_get_phyid(dev); +@@ -890,7 +878,7 @@ static const struct driver_info ax88772_info = { + .unbind = ax88772_unbind, + .status = asix_status, + .link_reset = ax88772_link_reset, +- .reset = ax88772_reset, ++ .reset = ax88772_link_reset, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET, + .rx_fixup = asix_rx_fixup_common, + .tx_fixup = asix_tx_fixup, +diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c +index 6244f9cf8ae3..0529defbdf73 100644 +--- a/fs/btrfs/backref.c ++++ b/fs/btrfs/backref.c +@@ -1692,7 +1692,6 @@ static int iterate_inode_extrefs(u64 inum, struct btrfs_root *fs_root, + int found = 0; + struct extent_buffer *eb; + struct btrfs_inode_extref *extref; +- struct extent_buffer *leaf; + u32 item_size; + u32 cur_offset; + unsigned long ptr; +@@ -1720,9 +1719,8 @@ static int iterate_inode_extrefs(u64 inum, struct btrfs_root *fs_root, + btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); + btrfs_release_path(path); + +- leaf = path->nodes[0]; +- item_size = btrfs_item_size_nr(leaf, slot); +- ptr = btrfs_item_ptr_offset(leaf, slot); ++ item_size = btrfs_item_size_nr(eb, slot); ++ ptr = btrfs_item_ptr_offset(eb, slot); + cur_offset = 0; + + while (cur_offset < item_size) { +@@ -1736,7 +1734,7 @@ static int iterate_inode_extrefs(u64 inum, struct btrfs_root *fs_root, + if (ret) + break; + +- cur_offset += btrfs_inode_extref_name_len(leaf, extref); ++ cur_offset += btrfs_inode_extref_name_len(eb, extref); + cur_offset += sizeof(*extref); + } + btrfs_tree_read_unlock_blocking(eb); +diff --git a/include/asm-generic/preempt.h b/include/asm-generic/preempt.h +index 1cd3f5d767a8..54352f4dde1a 100644 +--- a/include/asm-generic/preempt.h ++++ b/include/asm-generic/preempt.h +@@ -74,9 +74,10 @@ static __always_inline bool __preempt_count_dec_and_test(void) + /* + * Returns true when we need to resched and can (barring IRQ state). + */ +-static __always_inline bool should_resched(void) ++static __always_inline bool should_resched(int preempt_offset) + { +- return unlikely(!preempt_count() && tif_need_resched()); ++ return unlikely(preempt_count() == preempt_offset && ++ tif_need_resched()); + } + + #ifdef CONFIG_PREEMPT +diff --git a/include/linux/preempt.h b/include/linux/preempt.h +index 1841b58cf173..411a5c6371da 100644 +--- a/include/linux/preempt.h ++++ b/include/linux/preempt.h +@@ -22,7 +22,8 @@ + #if defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_PREEMPT_TRACER) + extern void preempt_count_add(int val); + extern void preempt_count_sub(int val); +-#define preempt_count_dec_and_test() ({ preempt_count_sub(1); should_resched(); }) ++#define preempt_count_dec_and_test() \ ++ ({ preempt_count_sub(1); should_resched(0); }) + #else + #define preempt_count_add(val) __preempt_count_add(val) + #define preempt_count_sub(val) __preempt_count_sub(val) +@@ -61,7 +62,7 @@ do { \ + + #define preempt_check_resched() \ + do { \ +- if (should_resched()) \ ++ if (should_resched(0)) \ + __preempt_schedule(); \ + } while (0) + +diff --git a/include/linux/preempt_mask.h b/include/linux/preempt_mask.h +index dbeec4d4a3be..5cb25f17331a 100644 +--- a/include/linux/preempt_mask.h ++++ b/include/linux/preempt_mask.h +@@ -71,13 +71,21 @@ + */ + #define in_nmi() (preempt_count() & NMI_MASK) + ++/* ++ * The preempt_count offset after preempt_disable(); ++ */ + #if defined(CONFIG_PREEMPT_COUNT) +-# define PREEMPT_CHECK_OFFSET 1 ++# define PREEMPT_DISABLE_OFFSET PREEMPT_OFFSET + #else +-# define PREEMPT_CHECK_OFFSET 0 ++# define PREEMPT_DISABLE_OFFSET 0 + #endif + + /* ++ * The preempt_count offset after spin_lock() ++ */ ++#define PREEMPT_LOCK_OFFSET PREEMPT_DISABLE_OFFSET ++ ++/* + * The preempt_count offset needed for things like: + * + * spin_lock_bh() +@@ -90,7 +98,7 @@ + * + * Work as expected. + */ +-#define SOFTIRQ_LOCK_OFFSET (SOFTIRQ_DISABLE_OFFSET + PREEMPT_CHECK_OFFSET) ++#define SOFTIRQ_LOCK_OFFSET (SOFTIRQ_DISABLE_OFFSET + PREEMPT_LOCK_OFFSET) + + /* + * Are we running in atomic context? WARNING: this macro cannot +@@ -106,7 +114,7 @@ + * (used by the scheduler, *after* releasing the kernel lock) + */ + #define in_atomic_preempt_off() \ +- ((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_CHECK_OFFSET) ++ ((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_DISABLE_OFFSET) + + #ifdef CONFIG_PREEMPT_COUNT + # define preemptible() (preempt_count() == 0 && !irqs_disabled()) +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 91fe6a38b307..ec6000f66e75 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -2647,12 +2647,6 @@ extern int _cond_resched(void); + + extern int __cond_resched_lock(spinlock_t *lock); + +-#ifdef CONFIG_PREEMPT_COUNT +-#define PREEMPT_LOCK_OFFSET PREEMPT_OFFSET +-#else +-#define PREEMPT_LOCK_OFFSET 0 +-#endif +- + #define cond_resched_lock(lock) ({ \ + __might_sleep(__FILE__, __LINE__, PREEMPT_LOCK_OFFSET); \ + __cond_resched_lock(lock); \ +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index ab3133797ff7..d8bec47b6edd 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -2347,6 +2347,9 @@ static inline void skb_postpull_rcsum(struct sk_buff *skb, + { + if (skb->ip_summed == CHECKSUM_COMPLETE) + skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0)); ++ else if (skb->ip_summed == CHECKSUM_PARTIAL && ++ skb_checksum_start_offset(skb) < 0) ++ skb->ip_summed = CHECKSUM_NONE; + } + + unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len); +diff --git a/include/net/af_unix.h b/include/net/af_unix.h +index a175ba4a7adb..dfe4ddfbb43c 100644 +--- a/include/net/af_unix.h ++++ b/include/net/af_unix.h +@@ -64,7 +64,11 @@ struct unix_sock { + #define UNIX_GC_MAYBE_CYCLE 1 + struct socket_wq peer_wq; + }; +-#define unix_sk(__sk) ((struct unix_sock *)__sk) ++ ++static inline struct unix_sock *unix_sk(struct sock *sk) ++{ ++ return (struct unix_sock *)sk; ++} + + #define peer_wait peer_wq.wait + +diff --git a/include/net/sock.h b/include/net/sock.h +index 0c79a740e97d..ff4f825647a5 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -805,6 +805,14 @@ static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *s + if (sk_rcvqueues_full(sk, skb, limit)) + return -ENOBUFS; + ++ /* ++ * If the skb was allocated from pfmemalloc reserves, only ++ * allow SOCK_MEMALLOC sockets to use it as this socket is ++ * helping free memory ++ */ ++ if (skb_pfmemalloc(skb) && !sock_flag(sk, SOCK_MEMALLOC)) ++ return -ENOMEM; ++ + __sk_add_backlog(sk, skb); + sk->sk_backlog.len += skb->truesize; + return 0; +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index a19262a7d70b..bbe957762ace 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -4113,7 +4113,7 @@ static void __cond_resched(void) + + int __sched _cond_resched(void) + { +- if (should_resched()) { ++ if (should_resched(0)) { + __cond_resched(); + return 1; + } +@@ -4131,7 +4131,7 @@ EXPORT_SYMBOL(_cond_resched); + */ + int __cond_resched_lock(spinlock_t *lock) + { +- int resched = should_resched(); ++ int resched = should_resched(PREEMPT_LOCK_OFFSET); + int ret = 0; + + lockdep_assert_held(lock); +@@ -4153,7 +4153,7 @@ int __sched __cond_resched_softirq(void) + { + BUG_ON(!in_softirq()); + +- if (should_resched()) { ++ if (should_resched(SOFTIRQ_DISABLE_OFFSET)) { + local_bh_enable(); + __cond_resched(); + local_bh_disable(); +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index 423c9e37a9e7..646a8b81bee1 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -1475,13 +1475,13 @@ static void __queue_delayed_work(int cpu, struct workqueue_struct *wq, + timer_stats_timer_set_start_info(&dwork->timer); + + dwork->wq = wq; ++ /* timer isn't guaranteed to run in this cpu, record earlier */ ++ if (cpu == WORK_CPU_UNBOUND) ++ cpu = raw_smp_processor_id(); + dwork->cpu = cpu; + timer->expires = jiffies + delay; + +- if (unlikely(cpu != WORK_CPU_UNBOUND)) +- add_timer_on(timer, cpu); +- else +- add_timer(timer); ++ add_timer_on(timer, cpu); + } + + /** +diff --git a/net/core/ethtool.c b/net/core/ethtool.c +index 30071dec287a..0b39ab6f7675 100644 +--- a/net/core/ethtool.c ++++ b/net/core/ethtool.c +@@ -1080,7 +1080,7 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr) + + gstrings.len = ret; + +- data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); ++ data = kcalloc(gstrings.len, ETH_GSTRING_LEN, GFP_USER); + if (!data) + return -ENOMEM; + +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index 8207f8d7f665..366f7ff741b7 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -2862,11 +2862,12 @@ EXPORT_SYMBOL(skb_append_datato_frags); + */ + unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) + { ++ unsigned char *data = skb->data; ++ + BUG_ON(len > skb->len); +- skb->len -= len; +- BUG_ON(skb->len < skb->data_len); +- skb_postpull_rcsum(skb, skb->data, len); +- return skb->data += len; ++ __skb_pull(skb, len); ++ skb_postpull_rcsum(skb, data, len); ++ return skb->data; + } + EXPORT_SYMBOL_GPL(skb_pull_rcsum); + +diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c +index 85d9d94c0a3c..3679bd6000d7 100644 +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -1435,7 +1435,7 @@ static void l2tp_tunnel_del_work(struct work_struct *work) + tunnel = container_of(work, struct l2tp_tunnel, del_work); + sk = l2tp_tunnel_sock_lookup(tunnel); + if (!sk) +- return; ++ goto out; + + sock = sk->sk_socket; + +@@ -1456,6 +1456,8 @@ static void l2tp_tunnel_del_work(struct work_struct *work) + } + + l2tp_tunnel_sock_put(sk); ++out: ++ l2tp_tunnel_dec_refcount(tunnel); + } + + /* Create a socket for the tunnel, if one isn't set up by +@@ -1785,8 +1787,13 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create); + */ + int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) + { ++ l2tp_tunnel_inc_refcount(tunnel); + l2tp_tunnel_closeall(tunnel); +- return (false == queue_work(l2tp_wq, &tunnel->del_work)); ++ if (false == queue_work(l2tp_wq, &tunnel->del_work)) { ++ l2tp_tunnel_dec_refcount(tunnel); ++ return 1; ++ } ++ return 0; + } + EXPORT_SYMBOL_GPL(l2tp_tunnel_delete); + +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 4757f1cf6237..4affedbe0206 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1956,6 +1956,11 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, + goto out; + } + ++ if (flags & MSG_PEEK) ++ skip = sk_peek_offset(sk, flags); ++ else ++ skip = 0; ++ + do { + int chunk; + struct sk_buff *skb, *last; +@@ -2002,7 +2007,6 @@ again: + break; + } + +- skip = sk_peek_offset(sk, flags); + while (skip >= unix_skb_len(skb)) { + skip -= unix_skb_len(skb); + last = skb; +@@ -2066,6 +2070,16 @@ again: + + sk_peek_offset_fwd(sk, chunk); + ++ if (UNIXCB(skb).fp) ++ break; ++ ++ skip = 0; ++ last = skb; ++ unix_state_lock(sk); ++ skb = skb_peek_next(skb, &sk->sk_receive_queue); ++ if (skb) ++ goto again; ++ unix_state_unlock(sk); + break; + } + } while (size); diff --git a/patch/kernel/cubox-default/patch-3.14.56-57.patch b/patch/kernel/cubox-default/patch-3.14.56-57.patch new file mode 100644 index 000000000..a5eaaf1f4 --- /dev/null +++ b/patch/kernel/cubox-default/patch-3.14.56-57.patch @@ -0,0 +1,988 @@ +diff --git a/Makefile b/Makefile +index 2a13d9d63880..51ee14329c47 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 56 ++SUBLEVEL = 57 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c +index 38f0558f0c0a..c3b6c63ea5fb 100644 +--- a/arch/arm64/kernel/stacktrace.c ++++ b/arch/arm64/kernel/stacktrace.c +@@ -48,11 +48,7 @@ int unwind_frame(struct stackframe *frame) + + frame->sp = fp + 0x10; + frame->fp = *(unsigned long *)(fp); +- /* +- * -4 here because we care about the PC at time of bl, +- * not where the return will go. +- */ +- frame->pc = *(unsigned long *)(fp + 8) - 4; ++ frame->pc = *(unsigned long *)(fp + 8); + + return 0; + } +diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c +index c4bc8d6cfd79..e6b028d3b1e7 100644 +--- a/arch/powerpc/kernel/rtas.c ++++ b/arch/powerpc/kernel/rtas.c +@@ -1041,6 +1041,9 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + ++ if (!rtas.entry) ++ return -EINVAL; ++ + if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0) + return -EFAULT; + +diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c +index 4dca0d50762e..a7fab60bdeeb 100644 +--- a/arch/x86/xen/enlighten.c ++++ b/arch/x86/xen/enlighten.c +@@ -33,7 +33,7 @@ + #include + #include + +-#ifdef CONFIG_KEXEC_CORE ++#ifdef CONFIG_KEXEC + #include + #endif + +@@ -1848,7 +1848,7 @@ static struct notifier_block xen_hvm_cpu_notifier = { + .notifier_call = xen_hvm_cpu_notify, + }; + +-#ifdef CONFIG_KEXEC_CORE ++#ifdef CONFIG_KEXEC + static void xen_hvm_shutdown(void) + { + native_machine_shutdown(); +@@ -1879,7 +1879,7 @@ static void __init xen_hvm_guest_init(void) + x86_init.irqs.intr_init = xen_init_IRQ; + xen_hvm_init_time_ops(); + xen_hvm_init_mmu_ops(); +-#ifdef CONFIG_KEXEC_CORE ++#ifdef CONFIG_KEXEC + machine_ops.shutdown = xen_hvm_shutdown; + machine_ops.crash_shutdown = xen_hvm_crash_shutdown; + #endif +diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c +index 40886c489903..520729d898fe 100644 +--- a/crypto/ablkcipher.c ++++ b/crypto/ablkcipher.c +@@ -695,7 +695,7 @@ struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name, + err: + if (err != -EAGAIN) + break; +- if (signal_pending(current)) { ++ if (fatal_signal_pending(current)) { + err = -EINTR; + break; + } +diff --git a/crypto/algapi.c b/crypto/algapi.c +index 00d8d939733b..daf2f653b131 100644 +--- a/crypto/algapi.c ++++ b/crypto/algapi.c +@@ -325,7 +325,7 @@ static void crypto_wait_for_test(struct crypto_larval *larval) + crypto_alg_tested(larval->alg.cra_driver_name, 0); + } + +- err = wait_for_completion_interruptible(&larval->completion); ++ err = wait_for_completion_killable(&larval->completion); + WARN_ON(err); + + out: +diff --git a/crypto/api.c b/crypto/api.c +index 2a81e98a0021..7db2e89a3114 100644 +--- a/crypto/api.c ++++ b/crypto/api.c +@@ -172,7 +172,7 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) + struct crypto_larval *larval = (void *)alg; + long timeout; + +- timeout = wait_for_completion_interruptible_timeout( ++ timeout = wait_for_completion_killable_timeout( + &larval->completion, 60 * HZ); + + alg = larval->adult; +@@ -435,7 +435,7 @@ struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask) + err: + if (err != -EAGAIN) + break; +- if (signal_pending(current)) { ++ if (fatal_signal_pending(current)) { + err = -EINTR; + break; + } +@@ -552,7 +552,7 @@ void *crypto_alloc_tfm(const char *alg_name, + err: + if (err != -EAGAIN) + break; +- if (signal_pending(current)) { ++ if (fatal_signal_pending(current)) { + err = -EINTR; + break; + } +diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c +index 43665d0d0905..c7666f401381 100644 +--- a/crypto/crypto_user.c ++++ b/crypto/crypto_user.c +@@ -361,7 +361,7 @@ static struct crypto_alg *crypto_user_aead_alg(const char *name, u32 type, + err = PTR_ERR(alg); + if (err != -EAGAIN) + break; +- if (signal_pending(current)) { ++ if (fatal_signal_pending(current)) { + err = -EINTR; + break; + } +diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c +index 2ea515509ca6..eb3dff3500c2 100644 +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -94,6 +94,8 @@ static int atomic_dec_return_safe(atomic_t *v) + #define RBD_MINORS_PER_MAJOR 256 + #define RBD_SINGLE_MAJOR_PART_SHIFT 4 + ++#define RBD_MAX_PARENT_CHAIN_LEN 16 ++ + #define RBD_SNAP_DEV_NAME_PREFIX "snap_" + #define RBD_MAX_SNAP_NAME_LEN \ + (NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1)) +@@ -411,7 +413,7 @@ static ssize_t rbd_add_single_major(struct bus_type *bus, const char *buf, + size_t count); + static ssize_t rbd_remove_single_major(struct bus_type *bus, const char *buf, + size_t count); +-static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping); ++static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth); + static void rbd_spec_put(struct rbd_spec *spec); + + static int rbd_dev_id_to_minor(int dev_id) +@@ -3443,6 +3445,9 @@ static int rbd_init_disk(struct rbd_device *rbd_dev) + blk_queue_io_opt(q, segment_size); + + blk_queue_merge_bvec(q, rbd_merge_bvec); ++ if (!ceph_test_opt(rbd_dev->rbd_client->client, NOCRC)) ++ q->backing_dev_info.capabilities |= BDI_CAP_STABLE_WRITES; ++ + disk->queue = q; + + q->queuedata = rbd_dev; +@@ -4819,44 +4824,50 @@ out_err: + return ret; + } + +-static int rbd_dev_probe_parent(struct rbd_device *rbd_dev) ++/* ++ * @depth is rbd_dev_image_probe() -> rbd_dev_probe_parent() -> ++ * rbd_dev_image_probe() recursion depth, which means it's also the ++ * length of the already discovered part of the parent chain. ++ */ ++static int rbd_dev_probe_parent(struct rbd_device *rbd_dev, int depth) + { + struct rbd_device *parent = NULL; +- struct rbd_spec *parent_spec; +- struct rbd_client *rbdc; + int ret; + + if (!rbd_dev->parent_spec) + return 0; +- /* +- * We need to pass a reference to the client and the parent +- * spec when creating the parent rbd_dev. Images related by +- * parent/child relationships always share both. +- */ +- parent_spec = rbd_spec_get(rbd_dev->parent_spec); +- rbdc = __rbd_get_client(rbd_dev->rbd_client); + +- ret = -ENOMEM; +- parent = rbd_dev_create(rbdc, parent_spec); +- if (!parent) ++ if (++depth > RBD_MAX_PARENT_CHAIN_LEN) { ++ pr_info("parent chain is too long (%d)\n", depth); ++ ret = -EINVAL; + goto out_err; ++ } + +- ret = rbd_dev_image_probe(parent, false); ++ parent = rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec); ++ if (!parent) { ++ ret = -ENOMEM; ++ goto out_err; ++ } ++ ++ /* ++ * Images related by parent/child relationships always share ++ * rbd_client and spec/parent_spec, so bump their refcounts. ++ */ ++ __rbd_get_client(rbd_dev->rbd_client); ++ rbd_spec_get(rbd_dev->parent_spec); ++ ++ ret = rbd_dev_image_probe(parent, depth); + if (ret < 0) + goto out_err; ++ + rbd_dev->parent = parent; + atomic_set(&rbd_dev->parent_ref, 1); +- + return 0; ++ + out_err: +- if (parent) { +- rbd_dev_unparent(rbd_dev); ++ rbd_dev_unparent(rbd_dev); ++ if (parent) + rbd_dev_destroy(parent); +- } else { +- rbd_put_client(rbdc); +- rbd_spec_put(parent_spec); +- } +- + return ret; + } + +@@ -4972,7 +4983,7 @@ static void rbd_dev_image_release(struct rbd_device *rbd_dev) + * parent), initiate a watch on its header object before using that + * object to get detailed information about the rbd image. + */ +-static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) ++static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth) + { + int ret; + +@@ -4992,7 +5003,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) + if (ret) + goto err_out_format; + +- if (mapping) { ++ if (!depth) { + ret = rbd_dev_header_watch_sync(rbd_dev); + if (ret) + goto out_header_name; +@@ -5009,7 +5020,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) + if (ret) + goto err_out_probe; + +- ret = rbd_dev_probe_parent(rbd_dev); ++ ret = rbd_dev_probe_parent(rbd_dev, depth); + if (ret) + goto err_out_probe; + +@@ -5020,7 +5031,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) + err_out_probe: + rbd_dev_unprobe(rbd_dev); + err_out_watch: +- if (mapping) ++ if (!depth) + rbd_dev_header_unwatch_sync(rbd_dev); + out_header_name: + kfree(rbd_dev->header_name); +@@ -5087,7 +5098,7 @@ static ssize_t do_rbd_add(struct bus_type *bus, + rbdc = NULL; /* rbd_dev now owns this */ + spec = NULL; /* rbd_dev now owns this */ + +- rc = rbd_dev_image_probe(rbd_dev, true); ++ rc = rbd_dev_image_probe(rbd_dev, 0); + if (rc < 0) + goto err_out_rbd_dev; + +diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c +index e88556ac8318..d4285270f20c 100644 +--- a/drivers/block/xen-blkfront.c ++++ b/drivers/block/xen-blkfront.c +@@ -1917,7 +1917,8 @@ static void blkback_changed(struct xenbus_device *dev, + break; + /* Missed the backend's Closing state -- fallthrough */ + case XenbusStateClosing: +- blkfront_closing(info); ++ if (info) ++ blkfront_closing(info); + break; + } + } +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index c51469051e41..958b26dcac8a 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -1451,6 +1451,8 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) + + I915_WRITE(reg, dpll); + ++ I915_WRITE(reg, dpll); ++ + /* Wait for the clocks to stabilize. */ + POSTING_READ(reg); + udelay(150); +diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c +index 27c3fd89e8ce..e85525427d9c 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_gem.c ++++ b/drivers/gpu/drm/nouveau/nouveau_gem.c +@@ -196,11 +196,12 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, + struct nouveau_bo *nvbo = nouveau_gem_object(gem); + struct nouveau_vma *vma; + +- if (nvbo->bo.mem.mem_type == TTM_PL_TT) ++ if (is_power_of_2(nvbo->valid_domains)) ++ rep->domain = nvbo->valid_domains; ++ else if (nvbo->bo.mem.mem_type == TTM_PL_TT) + rep->domain = NOUVEAU_GEM_DOMAIN_GART; + else + rep->domain = NOUVEAU_GEM_DOMAIN_VRAM; +- + rep->offset = nvbo->bo.offset; + if (cli->base.vm) { + vma = nouveau_bo_vma_find(nvbo, cli->base.vm); +diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h +index b837e9f9f8ce..1f14f32853ef 100644 +--- a/drivers/gpu/drm/radeon/radeon.h ++++ b/drivers/gpu/drm/radeon/radeon.h +@@ -1551,6 +1551,7 @@ struct radeon_pm { + struct device *int_hwmon_dev; + /* dpm */ + bool dpm_enabled; ++ bool sysfs_initialized; + struct radeon_dpm dpm; + }; + +diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c +index 214adc6d2a68..0b00de55b2a4 100644 +--- a/drivers/gpu/drm/radeon/radeon_pm.c ++++ b/drivers/gpu/drm/radeon/radeon_pm.c +@@ -1350,19 +1350,23 @@ int radeon_pm_late_init(struct radeon_device *rdev) + + if (rdev->pm.pm_method == PM_METHOD_DPM) { + if (rdev->pm.dpm_enabled) { +- ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state); +- if (ret) +- DRM_ERROR("failed to create device file for dpm state\n"); +- ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level); +- if (ret) +- DRM_ERROR("failed to create device file for dpm state\n"); +- /* XXX: these are noops for dpm but are here for backwards compat */ +- ret = device_create_file(rdev->dev, &dev_attr_power_profile); +- if (ret) +- DRM_ERROR("failed to create device file for power profile\n"); +- ret = device_create_file(rdev->dev, &dev_attr_power_method); +- if (ret) +- DRM_ERROR("failed to create device file for power method\n"); ++ if (!rdev->pm.sysfs_initialized) { ++ ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state); ++ if (ret) ++ DRM_ERROR("failed to create device file for dpm state\n"); ++ ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level); ++ if (ret) ++ DRM_ERROR("failed to create device file for dpm state\n"); ++ /* XXX: these are noops for dpm but are here for backwards compat */ ++ ret = device_create_file(rdev->dev, &dev_attr_power_profile); ++ if (ret) ++ DRM_ERROR("failed to create device file for power profile\n"); ++ ret = device_create_file(rdev->dev, &dev_attr_power_method); ++ if (ret) ++ DRM_ERROR("failed to create device file for power method\n"); ++ if (!ret) ++ rdev->pm.sysfs_initialized = true; ++ } + + mutex_lock(&rdev->pm.mutex); + ret = radeon_dpm_late_enable(rdev); +@@ -1378,7 +1382,8 @@ int radeon_pm_late_init(struct radeon_device *rdev) + } + } + } else { +- if (rdev->pm.num_power_states > 1) { ++ if ((rdev->pm.num_power_states > 1) && ++ (!rdev->pm.sysfs_initialized)) { + /* where's the best place to put these? */ + ret = device_create_file(rdev->dev, &dev_attr_power_profile); + if (ret) +@@ -1386,6 +1391,8 @@ int radeon_pm_late_init(struct radeon_device *rdev) + ret = device_create_file(rdev->dev, &dev_attr_power_method); + if (ret) + DRM_ERROR("failed to create device file for power method\n"); ++ if (!ret) ++ rdev->pm.sysfs_initialized = true; + } + } + return ret; +diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c +index c3239170d8b7..5311cac12132 100644 +--- a/drivers/infiniband/core/cm.c ++++ b/drivers/infiniband/core/cm.c +@@ -860,6 +860,11 @@ retest: + case IB_CM_SIDR_REQ_RCVD: + spin_unlock_irq(&cm_id_priv->lock); + cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT); ++ spin_lock_irq(&cm.lock); ++ if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node)) ++ rb_erase(&cm_id_priv->sidr_id_node, ++ &cm.remote_sidr_table); ++ spin_unlock_irq(&cm.lock); + break; + case IB_CM_REQ_SENT: + ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg); +@@ -3099,7 +3104,10 @@ int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id, + spin_unlock_irqrestore(&cm_id_priv->lock, flags); + + spin_lock_irqsave(&cm.lock, flags); +- rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table); ++ if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node)) { ++ rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table); ++ RB_CLEAR_NODE(&cm_id_priv->sidr_id_node); ++ } + spin_unlock_irqrestore(&cm.lock, flags); + return 0; + +diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c +index 935974090aa0..b0cb66208c8b 100644 +--- a/drivers/iommu/amd_iommu.c ++++ b/drivers/iommu/amd_iommu.c +@@ -2152,8 +2152,8 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats) + static void clear_dte_entry(u16 devid) + { + /* remove entry from the device table seen by the hardware */ +- amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV; +- amd_iommu_dev_table[devid].data[1] = 0; ++ amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV; ++ amd_iommu_dev_table[devid].data[1] &= DTE_FLAG_MASK; + + amd_iommu_apply_erratum_63(devid); + } +diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h +index e400fbe411de..e0c39940f659 100644 +--- a/drivers/iommu/amd_iommu_types.h ++++ b/drivers/iommu/amd_iommu_types.h +@@ -283,6 +283,7 @@ + #define IOMMU_PTE_IR (1ULL << 61) + #define IOMMU_PTE_IW (1ULL << 62) + ++#define DTE_FLAG_MASK (0x3ffULL << 32) + #define DTE_FLAG_IOTLB (0x01UL << 32) + #define DTE_FLAG_GV (0x01ULL << 55) + #define DTE_GLX_SHIFT (56) +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 31d14d88205b..af837313d431 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -7775,8 +7775,7 @@ static int remove_and_add_spares(struct mddev *mddev, + !test_bit(Bitmap_sync, &rdev->flags))) + continue; + +- if (rdev->saved_raid_disk < 0) +- rdev->recovery_offset = 0; ++ rdev->recovery_offset = 0; + if (mddev->pers-> + hot_add_disk(mddev, rdev) == 0) { + if (sysfs_link_rdev(mddev, rdev)) +diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c +index 7c0d75547ccf..92cd09f3c69b 100644 +--- a/drivers/md/persistent-data/dm-btree-remove.c ++++ b/drivers/md/persistent-data/dm-btree-remove.c +@@ -301,11 +301,16 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, + { + int s; + uint32_t max_entries = le32_to_cpu(left->header.max_entries); +- unsigned target = (nr_left + nr_center + nr_right) / 3; +- BUG_ON(target > max_entries); ++ unsigned total = nr_left + nr_center + nr_right; ++ unsigned target_right = total / 3; ++ unsigned remainder = (target_right * 3) != total; ++ unsigned target_left = target_right + remainder; ++ ++ BUG_ON(target_left > max_entries); ++ BUG_ON(target_right > max_entries); + + if (nr_left < nr_right) { +- s = nr_left - target; ++ s = nr_left - target_left; + + if (s < 0 && nr_center < -s) { + /* not enough in central node */ +@@ -316,10 +321,10 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, + } else + shift(left, center, s); + +- shift(center, right, target - nr_right); ++ shift(center, right, target_right - nr_right); + + } else { +- s = target - nr_right; ++ s = target_right - nr_right; + if (s > 0 && nr_center < s) { + /* not enough in central node */ + shift(center, right, nr_center); +@@ -329,7 +334,7 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, + } else + shift(center, right, s); + +- shift(left, center, nr_left - target); ++ shift(left, center, nr_left - target_left); + } + + *key_ptr(parent, c->index) = center->keys[0]; +diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c +index c7726cebc495..d6e47033b5e0 100644 +--- a/drivers/md/persistent-data/dm-btree.c ++++ b/drivers/md/persistent-data/dm-btree.c +@@ -523,7 +523,7 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key) + + r = new_block(s->info, &right); + if (r < 0) { +- /* FIXME: put left */ ++ unlock_block(s->info, left); + return r; + } + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 47b7c3136807..0d91644e80eb 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -2251,7 +2251,7 @@ static int narrow_write_error(struct r1bio *r1_bio, int i) + bio_trim(wbio, sector - r1_bio->sector, sectors); + wbio->bi_iter.bi_sector += rdev->data_offset; + wbio->bi_bdev = rdev->bdev; +- if (submit_bio_wait(WRITE, wbio) == 0) ++ if (submit_bio_wait(WRITE, wbio) < 0) + /* failure! */ + ok = rdev_set_badblocks(rdev, sector, + sectors, 0) +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index 73c9f579b042..19bc2e1aee26 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -2604,7 +2604,7 @@ static int narrow_write_error(struct r10bio *r10_bio, int i) + choose_data_offset(r10_bio, rdev) + + (sector - r10_bio->sector)); + wbio->bi_bdev = rdev->bdev; +- if (submit_bio_wait(WRITE, wbio) == 0) ++ if (submit_bio_wait(WRITE, wbio) < 0) + /* Failure! */ + ok = rdev_set_badblocks(rdev, sector, + sectors, 0) +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index b98c70e1f1a9..1c829a0b234b 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -3029,6 +3029,8 @@ static void handle_stripe_clean_event(struct r5conf *conf, + } + if (!discard_pending && + test_bit(R5_Discard, &sh->dev[sh->pd_idx].flags)) { ++ int hash = sh->hash_lock_index; ++ + clear_bit(R5_Discard, &sh->dev[sh->pd_idx].flags); + clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags); + if (sh->qd_idx >= 0) { +@@ -3042,9 +3044,9 @@ static void handle_stripe_clean_event(struct r5conf *conf, + * no updated data, so remove it from hash list and the stripe + * will be reinitialized + */ +- spin_lock_irq(&conf->device_lock); ++ spin_lock_irq(conf->hash_locks + hash); + remove_hash(sh); +- spin_unlock_irq(&conf->device_lock); ++ spin_unlock_irq(conf->hash_locks + hash); + if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state)) + set_bit(STRIPE_HANDLE, &sh->state); + +diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c +index 26641817a9c7..c9fcf6fa5479 100644 +--- a/drivers/net/ethernet/sfc/selftest.c ++++ b/drivers/net/ethernet/sfc/selftest.c +@@ -46,7 +46,7 @@ struct efx_loopback_payload { + struct iphdr ip; + struct udphdr udp; + __be16 iteration; +- const char msg[64]; ++ char msg[64]; + } __packed; + + /* Loopback test source MAC address */ +diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c +index 1fc2e5a26b52..a72cac46f699 100644 +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -956,6 +956,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) + hw->max_rate_tries = 10; + hw->sta_data_size = sizeof(struct ath_node); + hw->vif_data_size = sizeof(struct ath_vif); ++ hw->extra_tx_headroom = 4; + + hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1; + hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1; +diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c +index 576f7ee38ca5..78a155e11183 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/lib.c ++++ b/drivers/net/wireless/iwlwifi/dvm/lib.c +@@ -1022,7 +1022,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw, + u8 *pn = seq.ccmp.pn; + + ieee80211_get_key_rx_seq(key, i, &seq); +- aes_sc->pn = cpu_to_le64( ++ aes_sc[i].pn = cpu_to_le64( + (u64)pn[5] | + ((u64)pn[4] << 8) | + ((u64)pn[3] << 16) | +diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c +index e1d546665ae8..28e18de9f429 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-7000.c ++++ b/drivers/net/wireless/iwlwifi/iwl-7000.c +@@ -222,5 +222,5 @@ const struct iwl_cfg iwl7265_n_cfg = { + }; + + MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); +-MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); ++MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); + MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); +diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c +index f36a7ee0267f..8e844d580cc6 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/d3.c ++++ b/drivers/net/wireless/iwlwifi/mvm/d3.c +@@ -297,12 +297,12 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, + u8 *pn = seq.ccmp.pn; + + ieee80211_get_key_rx_seq(key, i, &seq); +- aes_sc->pn = cpu_to_le64((u64)pn[5] | +- ((u64)pn[4] << 8) | +- ((u64)pn[3] << 16) | +- ((u64)pn[2] << 24) | +- ((u64)pn[1] << 32) | +- ((u64)pn[0] << 40)); ++ aes_sc[i].pn = cpu_to_le64((u64)pn[5] | ++ ((u64)pn[4] << 8) | ++ ((u64)pn[3] << 16) | ++ ((u64)pn[2] << 24) | ++ ((u64)pn[1] << 32) | ++ ((u64)pn[0] << 40)); + } + data->use_rsc_tsc = true; + break; +diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c +index 1ac33d9cd396..988f9fec0bff 100644 +--- a/drivers/net/wireless/iwlwifi/pcie/drv.c ++++ b/drivers/net/wireless/iwlwifi/pcie/drv.c +@@ -396,6 +396,11 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { + {IWL_PCI_DEVICE(0x095A, 0x5590, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)}, ++ {IWL_PCI_DEVICE(0x095A, 0x5F10, iwl7265_2ac_cfg)}, ++ {IWL_PCI_DEVICE(0x095B, 0x5212, iwl7265_2ac_cfg)}, ++ {IWL_PCI_DEVICE(0x095B, 0x520A, iwl7265_2ac_cfg)}, ++ {IWL_PCI_DEVICE(0x095A, 0x9000, iwl7265_2ac_cfg)}, ++ {IWL_PCI_DEVICE(0x095A, 0x9400, iwl7265_2ac_cfg)}, + #endif /* CONFIG_IWLMVM */ + + {0} +diff --git a/drivers/power/bq24190_charger.c b/drivers/power/bq24190_charger.c +index e4c95e1a6733..d0e8236a6404 100644 +--- a/drivers/power/bq24190_charger.c ++++ b/drivers/power/bq24190_charger.c +@@ -1208,7 +1208,7 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) + { + struct bq24190_dev_info *bdi = data; + bool alert_userspace = false; +- u8 ss_reg, f_reg; ++ u8 ss_reg = 0, f_reg = 0; + int ret; + + pm_runtime_get_sync(bdi->dev); +diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c +index 4c0b8b4e1d40..42b1f3318e59 100644 +--- a/drivers/scsi/mvsas/mv_sas.c ++++ b/drivers/scsi/mvsas/mv_sas.c +@@ -988,6 +988,8 @@ static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc) + static void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task, + struct mvs_slot_info *slot, u32 slot_idx) + { ++ if (!slot) ++ return; + if (!slot->task) + return; + if (!sas_protocol_ata(task->task_proto)) +diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c +index 7beeb29472ac..dd4fe5036220 100644 +--- a/drivers/spi/spi-gpio.c ++++ b/drivers/spi/spi-gpio.c +@@ -250,7 +250,7 @@ static int spi_gpio_setup(struct spi_device *spi) + /* + * ... otherwise, take it from spi->controller_data + */ +- cs = (unsigned int) spi->controller_data; ++ cs = (unsigned int)(uintptr_t) spi->controller_data; + } + + if (!spi->controller_state) { +diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c +index 27e1a6e62d06..503846c3e620 100644 +--- a/drivers/staging/iio/adc/mxs-lradc.c ++++ b/drivers/staging/iio/adc/mxs-lradc.c +@@ -920,11 +920,12 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev, + case IIO_CHAN_INFO_OFFSET: + if (chan->type == IIO_TEMP) { + /* The calculated value from the ADC is in Kelvin, we +- * want Celsius for hwmon so the offset is +- * -272.15 * scale ++ * want Celsius for hwmon so the offset is -273.15 ++ * The offset is applied before scaling so it is ++ * actually -213.15 * 4 / 1.012 = -1079.644268 + */ +- *val = -1075; +- *val2 = 691699; ++ *val = -1079; ++ *val2 = 644268; + + return IIO_VAL_INT_PLUS_MICRO; + } +diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c +index 5892eab03874..996f8f3fd423 100644 +--- a/drivers/tty/serial/8250/8250_pci.c ++++ b/drivers/tty/serial/8250/8250_pci.c +@@ -1772,6 +1772,9 @@ pci_wch_ch353_setup(struct serial_private *priv, + #define PCI_DEVICE_ID_SUNIX_1999 0x1999 + + ++#define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358 ++#define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358 ++ + /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ + #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 + #define PCI_SUBDEVICE_ID_UNKNOWN_0x1588 0x1588 +@@ -2266,6 +2269,20 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { + .subdevice = PCI_ANY_ID, + .setup = pci_xr17v35x_setup, + }, ++ { ++ .vendor = PCI_VENDOR_ID_EXAR, ++ .device = PCI_DEVICE_ID_EXAR_XR17V4358, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .setup = pci_xr17v35x_setup, ++ }, ++ { ++ .vendor = PCI_VENDOR_ID_EXAR, ++ .device = PCI_DEVICE_ID_EXAR_XR17V8358, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .setup = pci_xr17v35x_setup, ++ }, + /* + * Xircom cards + */ +@@ -2706,6 +2723,8 @@ enum pci_board_num_t { + pbn_exar_XR17V352, + pbn_exar_XR17V354, + pbn_exar_XR17V358, ++ pbn_exar_XR17V4358, ++ pbn_exar_XR17V8358, + pbn_exar_ibm_saturn, + pbn_pasemi_1682M, + pbn_ni8430_2, +@@ -3375,6 +3394,22 @@ static struct pciserial_board pci_boards[] = { + .reg_shift = 0, + .first_offset = 0, + }, ++ [pbn_exar_XR17V4358] = { ++ .flags = FL_BASE0, ++ .num_ports = 12, ++ .base_baud = 7812500, ++ .uart_offset = 0x400, ++ .reg_shift = 0, ++ .first_offset = 0, ++ }, ++ [pbn_exar_XR17V8358] = { ++ .flags = FL_BASE0, ++ .num_ports = 16, ++ .base_baud = 7812500, ++ .uart_offset = 0x400, ++ .reg_shift = 0, ++ .first_offset = 0, ++ }, + [pbn_exar_ibm_saturn] = { + .flags = FL_BASE0, + .num_ports = 1, +@@ -4731,7 +4766,7 @@ static struct pci_device_id serial_pci_tbl[] = { + 0, + 0, pbn_exar_XR17C158 }, + /* +- * Exar Corp. XR17V35[248] Dual/Quad/Octal PCIe UARTs ++ * Exar Corp. XR17V[48]35[248] Dual/Quad/Octal/Hexa PCIe UARTs + */ + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V352, + PCI_ANY_ID, PCI_ANY_ID, +@@ -4745,7 +4780,14 @@ static struct pci_device_id serial_pci_tbl[] = { + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_exar_XR17V358 }, +- ++ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V4358, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, ++ 0, pbn_exar_XR17V4358 }, ++ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V8358, ++ PCI_ANY_ID, PCI_ANY_ID, ++ 0, ++ 0, pbn_exar_XR17V8358 }, + /* + * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke) + */ +diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c +index eb3399f4c1ed..44af2b02d701 100644 +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -140,6 +140,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + xhci->quirks |= XHCI_SPURIOUS_WAKEUP; + + xhci->quirks |= XHCI_SPURIOUS_REBOOT; ++ xhci->quirks |= XHCI_SPURIOUS_WAKEUP; + } + if (pdev->vendor == PCI_VENDOR_ID_ETRON && + pdev->device == PCI_DEVICE_ID_ASROCK_P67) { +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index 86a0ddd8efb7..bd993fe00e0c 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -2417,6 +2417,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, + u32 trb_comp_code; + int ret = 0; + int td_num = 0; ++ bool handling_skipped_tds = false; + + slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); + xdev = xhci->devs[slot_id]; +@@ -2550,6 +2551,10 @@ static int handle_tx_event(struct xhci_hcd *xhci, + ep->skip = true; + xhci_dbg(xhci, "Miss service interval error, set skip flag\n"); + goto cleanup; ++ case COMP_PING_ERR: ++ ep->skip = true; ++ xhci_dbg(xhci, "No Ping response error, Skip one Isoc TD\n"); ++ goto cleanup; + default: + if (xhci_is_vendor_info_code(xhci, trb_comp_code)) { + status = 0; +@@ -2681,13 +2686,18 @@ static int handle_tx_event(struct xhci_hcd *xhci, + ep, &status); + + cleanup: ++ ++ ++ handling_skipped_tds = ep->skip && ++ trb_comp_code != COMP_MISSED_INT && ++ trb_comp_code != COMP_PING_ERR; ++ + /* +- * Do not update event ring dequeue pointer if ep->skip is set. +- * Will roll back to continue process missed tds. ++ * Do not update event ring dequeue pointer if we're in a loop ++ * processing missed tds. + */ +- if (trb_comp_code == COMP_MISSED_INT || !ep->skip) { ++ if (!handling_skipped_tds) + inc_deq(xhci, xhci->event_ring); +- } + + if (ret) { + urb = td->urb; +@@ -2722,7 +2732,7 @@ cleanup: + * Process them as short transfer until reach the td pointed by + * the event. + */ +- } while (ep->skip && trb_comp_code != COMP_MISSED_INT); ++ } while (handling_skipped_tds); + + return 0; + } +diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c +index 486d710a5293..6aeea1936aea 100644 +--- a/drivers/vhost/scsi.c ++++ b/drivers/vhost/scsi.c +@@ -1139,7 +1139,7 @@ tcm_vhost_send_evt(struct vhost_scsi *vs, + * lun[4-7] need to be zero according to virtio-scsi spec. + */ + evt->event.lun[0] = 0x01; +- evt->event.lun[1] = tpg->tport_tpgt & 0xFF; ++ evt->event.lun[1] = tpg->tport_tpgt; + if (lun->unpacked_lun >= 256) + evt->event.lun[2] = lun->unpacked_lun >> 8 | 0x40 ; + evt->event.lun[3] = lun->unpacked_lun & 0xFF; +@@ -2004,12 +2004,12 @@ tcm_vhost_make_tpg(struct se_wwn *wwn, + struct tcm_vhost_tport, tport_wwn); + + struct tcm_vhost_tpg *tpg; +- unsigned long tpgt; ++ u16 tpgt; + int ret; + + if (strstr(name, "tpgt_") != name) + return ERR_PTR(-EINVAL); +- if (kstrtoul(name + 5, 10, &tpgt) || tpgt > UINT_MAX) ++ if (kstrtou16(name + 5, 10, &tpgt) || tpgt >= VHOST_SCSI_MAX_TARGET) + return ERR_PTR(-EINVAL); + + tpg = kzalloc(sizeof(struct tcm_vhost_tpg), GFP_KERNEL); +diff --git a/include/sound/wm8904.h b/include/sound/wm8904.h +index 898be3a8db9a..6d8f8fba3341 100644 +--- a/include/sound/wm8904.h ++++ b/include/sound/wm8904.h +@@ -119,7 +119,7 @@ + #define WM8904_MIC_REGS 2 + #define WM8904_GPIO_REGS 4 + #define WM8904_DRC_REGS 4 +-#define WM8904_EQ_REGS 25 ++#define WM8904_EQ_REGS 24 + + /** + * DRC configurations are specified with a label and a set of register +diff --git a/kernel/module.c b/kernel/module.c +index 1d679a6c942f..49f17c27bf11 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -915,11 +915,15 @@ void symbol_put_addr(void *addr) + if (core_kernel_text(a)) + return; + +- /* module_text_address is safe here: we're supposed to have reference +- * to module from symbol_get, so it can't go away. */ ++ /* ++ * Even though we hold a reference on the module; we still need to ++ * disable preemption in order to safely traverse the data structure. ++ */ ++ preempt_disable(); + modaddr = __module_text_address(a); + BUG_ON(!modaddr); + module_put(modaddr); ++ preempt_enable(); + } + EXPORT_SYMBOL_GPL(symbol_put_addr); + +diff --git a/mm/filemap.c b/mm/filemap.c +index 217cfd3b3264..ca9efc6fff3b 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -2509,6 +2509,11 @@ again: + break; + } + ++ if (fatal_signal_pending(current)) { ++ status = -EINTR; ++ break; ++ } ++ + status = a_ops->write_begin(file, mapping, pos, bytes, flags, + &page, &fsdata); + if (unlikely(status < 0)) +@@ -2546,10 +2551,6 @@ again: + written += copied; + + balance_dirty_pages_ratelimited(mapping); +- if (fatal_signal_pending(current)) { +- status = -EINTR; +- break; +- } + } while (iov_iter_count(i)); + + return written ? written : status; diff --git a/patch/kernel/cubox-patch-3.14.14-53.patch b/patch/kernel/cubox-patch-3.14.14-53.patch new file mode 100644 index 000000000..36e8c142b --- /dev/null +++ b/patch/kernel/cubox-patch-3.14.14-53.patch @@ -0,0 +1,92250 @@ +diff --git a/Documentation/ABI/testing/configfs-usb-gadget-loopback b/Documentation/ABI/testing/configfs-usb-gadget-loopback +index 9aae5bf..06beefb 100644 +--- a/Documentation/ABI/testing/configfs-usb-gadget-loopback ++++ b/Documentation/ABI/testing/configfs-usb-gadget-loopback +@@ -5,4 +5,4 @@ Description: + The attributes: + + qlen - depth of loopback queue +- bulk_buflen - buffer length ++ buflen - buffer length +diff --git a/Documentation/ABI/testing/configfs-usb-gadget-sourcesink b/Documentation/ABI/testing/configfs-usb-gadget-sourcesink +index 29477c3..bc7ff73 100644 +--- a/Documentation/ABI/testing/configfs-usb-gadget-sourcesink ++++ b/Documentation/ABI/testing/configfs-usb-gadget-sourcesink +@@ -9,4 +9,4 @@ Description: + isoc_maxpacket - 0 - 1023 (fs), 0 - 1024 (hs/ss) + isoc_mult - 0..2 (hs/ss only) + isoc_maxburst - 0..15 (ss only) +- qlen - buffer length ++ buflen - buffer length +diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy +index 4c3efe4..750ab97 100644 +--- a/Documentation/ABI/testing/ima_policy ++++ b/Documentation/ABI/testing/ima_policy +@@ -20,16 +20,18 @@ Description: + action: measure | dont_measure | appraise | dont_appraise | audit + condition:= base | lsm [option] + base: [[func=] [mask=] [fsmagic=] [fsuuid=] [uid=] +- [fowner]] ++ [euid=] [fowner=]] + lsm: [[subj_user=] [subj_role=] [subj_type=] + [obj_user=] [obj_role=] [obj_type=]] + option: [[appraise_type=]] [permit_directio] + + base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK] +- mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC] ++ mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND] ++ [[^]MAY_EXEC] + fsmagic:= hex value + fsuuid:= file system UUID (e.g 8bcbe394-4f13-4144-be8e-5aa9ea2ce2f6) + uid:= decimal value ++ euid:= decimal value + fowner:=decimal value + lsm: are LSM specific + option: appraise_type:= [imasig] +diff --git a/Documentation/devicetree/bindings/ata/sata_rcar.txt b/Documentation/devicetree/bindings/ata/sata_rcar.txt +index 1e61113..7dd32d3 100644 +--- a/Documentation/devicetree/bindings/ata/sata_rcar.txt ++++ b/Documentation/devicetree/bindings/ata/sata_rcar.txt +@@ -3,7 +3,8 @@ + Required properties: + - compatible : should contain one of the following: + - "renesas,sata-r8a7779" for R-Car H1 +- - "renesas,sata-r8a7790" for R-Car H2 ++ - "renesas,sata-r8a7790-es1" for R-Car H2 ES1 ++ - "renesas,sata-r8a7790" for R-Car H2 other than ES1 + - "renesas,sata-r8a7791" for R-Car M2 + - reg : address and length of the SATA registers; + - interrupts : must consist of one interrupt specifier. +diff --git a/Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt b/Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt +index a4873e5..e30e184 100644 +--- a/Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt ++++ b/Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt +@@ -38,7 +38,7 @@ dma_apbx: dma-apbx@80024000 { + 80 81 68 69 + 70 71 72 73 + 74 75 76 77>; +- interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty", ++ interrupt-names = "auart4-rx", "auart4-tx", "spdif-tx", "empty", + "saif0", "saif1", "i2c0", "i2c1", + "auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx", + "auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx"; +diff --git a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +index 1486497..8a3c408 100644 +--- a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt ++++ b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +@@ -4,11 +4,13 @@ Specifying interrupt information for devices + 1) Interrupt client nodes + ------------------------- + +-Nodes that describe devices which generate interrupts must contain an either an +-"interrupts" property or an "interrupts-extended" property. These properties +-contain a list of interrupt specifiers, one per output interrupt. The format of +-the interrupt specifier is determined by the interrupt controller to which the +-interrupts are routed; see section 2 below for details. ++Nodes that describe devices which generate interrupts must contain an ++"interrupts" property, an "interrupts-extended" property, or both. If both are ++present, the latter should take precedence; the former may be provided simply ++for compatibility with software that does not recognize the latter. These ++properties contain a list of interrupt specifiers, one per output interrupt. The ++format of the interrupt specifier is determined by the interrupt controller to ++which the interrupts are routed; see section 2 below for details. + + Example: + interrupt-parent = <&intc1>; +@@ -28,10 +30,6 @@ should only be used when a device has multiple interrupt parents. + Example: + interrupts-extended = <&intc1 5 1>, <&intc2 1 0>; + +-A device node may contain either "interrupts" or "interrupts-extended", but not +-both. If both properties are present, then the operating system should log an +-error and use only the data in "interrupts". +- + 2) Interrupt controller nodes + ----------------------------- + +diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt +index 01ef408..8faff12 100644 +--- a/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt ++++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt +@@ -91,5 +91,5 @@ mpp61 61 gpo, dev(wen1), uart1(txd), audio(rclk) + mpp62 62 gpio, dev(a2), uart1(cts), tdm(drx), pcie(clkreq0), + audio(mclk), uart0(cts) + mpp63 63 gpo, spi0(sck), tclk +-mpp64 64 gpio, spi0(miso), spi0-1(cs1) +-mpp65 65 gpio, spi0(mosi), spi0-1(cs2) ++mpp64 64 gpio, spi0(miso), spi0(cs1) ++mpp65 65 gpio, spi0(mosi), spi0(cs2) +diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt +index bfa0a2e..86dec67 100644 +--- a/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt ++++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt +@@ -41,15 +41,15 @@ mpp20 20 gpio, ge0(rxd4), ge1(rxd2), lcd(d20), ptp(clk) + mpp21 21 gpio, ge0(rxd5), ge1(rxd3), lcd(d21), mem(bat) + mpp22 22 gpio, ge0(rxd6), ge1(rxctl), lcd(d22), sata0(prsnt) + mpp23 23 gpio, ge0(rxd7), ge1(rxclk), lcd(d23), sata1(prsnt) +-mpp24 24 gpio, lcd(hsync), sata1(prsnt), nf(bootcs-re), tdm(rst) +-mpp25 25 gpio, lcd(vsync), sata0(prsnt), nf(bootcs-we), tdm(pclk) +-mpp26 26 gpio, lcd(clk), tdm(fsync), vdd(cpu1-pd) ++mpp24 24 gpio, lcd(hsync), sata1(prsnt), tdm(rst) ++mpp25 25 gpio, lcd(vsync), sata0(prsnt), tdm(pclk) ++mpp26 26 gpio, lcd(clk), tdm(fsync) + mpp27 27 gpio, lcd(e), tdm(dtx), ptp(trig) + mpp28 28 gpio, lcd(pwm), tdm(drx), ptp(evreq) +-mpp29 29 gpio, lcd(ref-clk), tdm(int0), ptp(clk), vdd(cpu0-pd) ++mpp29 29 gpio, lcd(ref-clk), tdm(int0), ptp(clk) + mpp30 30 gpio, tdm(int1), sd0(clk) +-mpp31 31 gpio, tdm(int2), sd0(cmd), vdd(cpu0-pd) +-mpp32 32 gpio, tdm(int3), sd0(d0), vdd(cpu1-pd) ++mpp31 31 gpio, tdm(int2), sd0(cmd) ++mpp32 32 gpio, tdm(int3), sd0(d0) + mpp33 33 gpio, tdm(int4), sd0(d1), mem(bat) + mpp34 34 gpio, tdm(int5), sd0(d2), sata0(prsnt) + mpp35 35 gpio, tdm(int6), sd0(d3), sata1(prsnt) +@@ -57,21 +57,18 @@ mpp36 36 gpio, spi(mosi) + mpp37 37 gpio, spi(miso) + mpp38 38 gpio, spi(sck) + mpp39 39 gpio, spi(cs0) +-mpp40 40 gpio, spi(cs1), uart2(cts), lcd(vga-hsync), vdd(cpu1-pd), +- pcie(clkreq0) ++mpp40 40 gpio, spi(cs1), uart2(cts), lcd(vga-hsync), pcie(clkreq0) + mpp41 41 gpio, spi(cs2), uart2(rts), lcd(vga-vsync), sata1(prsnt), + pcie(clkreq1) +-mpp42 42 gpio, uart2(rxd), uart0(cts), tdm(int7), tdm-1(timer), +- vdd(cpu0-pd) +-mpp43 43 gpio, uart2(txd), uart0(rts), spi(cs3), pcie(rstout), +- vdd(cpu2-3-pd){1} ++mpp42 42 gpio, uart2(rxd), uart0(cts), tdm(int7), tdm-1(timer) ++mpp43 43 gpio, uart2(txd), uart0(rts), spi(cs3), pcie(rstout) + mpp44 44 gpio, uart2(cts), uart3(rxd), spi(cs4), pcie(clkreq2), + mem(bat) + mpp45 45 gpio, uart2(rts), uart3(txd), spi(cs5), sata1(prsnt) + mpp46 46 gpio, uart3(rts), uart1(rts), spi(cs6), sata0(prsnt) + mpp47 47 gpio, uart3(cts), uart1(cts), spi(cs7), pcie(clkreq3), + ref(clkout) +-mpp48 48 gpio, tclk, dev(burst/last) ++mpp48 48 gpio, dev(clkout), dev(burst/last) + + * Marvell Armada XP (mv78260 and mv78460 only) + +@@ -83,9 +80,9 @@ mpp51 51 gpio, dev(ad16) + mpp52 52 gpio, dev(ad17) + mpp53 53 gpio, dev(ad18) + mpp54 54 gpio, dev(ad19) +-mpp55 55 gpio, dev(ad20), vdd(cpu0-pd) +-mpp56 56 gpio, dev(ad21), vdd(cpu1-pd) +-mpp57 57 gpio, dev(ad22), vdd(cpu2-3-pd){1} ++mpp55 55 gpio, dev(ad20) ++mpp56 56 gpio, dev(ad21) ++mpp57 57 gpio, dev(ad22) + mpp58 58 gpio, dev(ad23) + mpp59 59 gpio, dev(ad24) + mpp60 60 gpio, dev(ad25) +@@ -95,6 +92,3 @@ mpp63 63 gpio, dev(ad28) + mpp64 64 gpio, dev(ad29) + mpp65 65 gpio, dev(ad30) + mpp66 66 gpio, dev(ad31) +- +-Notes: +-* {1} vdd(cpu2-3-pd) only available on mv78460. +diff --git a/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt b/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt +index 46f3449..4eb7997 100644 +--- a/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt ++++ b/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt +@@ -1,7 +1,7 @@ + ADI AXI-SPDIF controller + + Required properties: +- - compatible : Must be "adi,axi-spdif-1.00.a" ++ - compatible : Must be "adi,axi-spdif-tx-1.00.a" + - reg : Must contain SPDIF core's registers location and length + - clocks : Pairs of phandle and specifier referencing the controller's clocks. + The controller expects two clocks, the clock used for the AXI interface and +diff --git a/Documentation/devicetree/bindings/spi/spi_pl022.txt b/Documentation/devicetree/bindings/spi/spi_pl022.txt +index 22ed679..4d1673c 100644 +--- a/Documentation/devicetree/bindings/spi/spi_pl022.txt ++++ b/Documentation/devicetree/bindings/spi/spi_pl022.txt +@@ -4,9 +4,9 @@ Required properties: + - compatible : "arm,pl022", "arm,primecell" + - reg : Offset and length of the register set for the device + - interrupts : Should contain SPI controller interrupt ++- num-cs : total number of chipselects + + Optional properties: +-- num-cs : total number of chipselects + - cs-gpios : should specify GPIOs used for chipselects. + The gpios will be referred to as reg = in the SPI child nodes. + If unspecified, a single SPI device without a chip select can be used. +diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index cef2e7d..a666fd8 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -1175,6 +1175,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + i8042.notimeout [HW] Ignore timeout condition signalled by controller + i8042.reset [HW] Reset the controller during init and cleanup + i8042.unlock [HW] Unlock (ignore) the keylock ++ i8042.kbdreset [HW] Reset device connected to KBD port + + i810= [HW,DRM] + +diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt +index 69b3cac..5d86756 100644 +--- a/Documentation/ramoops.txt ++++ b/Documentation/ramoops.txt +@@ -14,11 +14,19 @@ survive after a restart. + + 1. Ramoops concepts + +-Ramoops uses a predefined memory area to store the dump. The start and size of +-the memory area are set using two variables: ++Ramoops uses a predefined memory area to store the dump. The start and size ++and type of the memory area are set using three variables: + * "mem_address" for the start + * "mem_size" for the size. The memory size will be rounded down to a + power of two. ++ * "mem_type" to specifiy if the memory type (default is pgprot_writecombine). ++ ++Typically the default value of mem_type=0 should be used as that sets the pstore ++mapping to pgprot_writecombine. Setting mem_type=1 attempts to use ++pgprot_noncached, which only works on some platforms. This is because pstore ++depends on atomic operations. At least on ARM, pgprot_noncached causes the ++memory to be mapped strongly ordered, and atomic operations on strongly ordered ++memory are implementation defined, and won't work on many ARMs such as omaps. + + The memory area is divided into "record_size" chunks (also rounded down to + power of two) and each oops/panic writes a "record_size" chunk of +@@ -55,6 +63,7 @@ Setting the ramoops parameters can be done in 2 different manners: + static struct ramoops_platform_data ramoops_data = { + .mem_size = <...>, + .mem_address = <...>, ++ .mem_type = <...>, + .record_size = <...>, + .dump_oops = <...>, + .ecc = <...>, +diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt +index b8dd0df..0fd40b1 100644 +--- a/Documentation/sound/alsa/ALSA-Configuration.txt ++++ b/Documentation/sound/alsa/ALSA-Configuration.txt +@@ -2026,8 +2026,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. + ------------------- + + Module for sound cards based on the Asus AV66/AV100/AV200 chips, +- i.e., Xonar D1, DX, D2, D2X, DS, Essence ST (Deluxe), Essence STX, +- HDAV1.3 (Deluxe), and HDAV1.3 Slim. ++ i.e., Xonar D1, DX, D2, D2X, DS, DSX, Essence ST (Deluxe), ++ Essence STX (II), HDAV1.3 (Deluxe), and HDAV1.3 Slim. + + This module supports autoprobe and multiple cards. + +diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt +index b0714d8..8dfb6a5 100644 +--- a/Documentation/stable_kernel_rules.txt ++++ b/Documentation/stable_kernel_rules.txt +@@ -29,6 +29,9 @@ Rules on what kind of patches are accepted, and which ones are not, into the + + Procedure for submitting patches to the -stable tree: + ++ - If the patch covers files in net/ or drivers/net please follow netdev stable ++ submission guidelines as described in ++ Documentation/networking/netdev-FAQ.txt + - Send the patch, after verifying that it follows the above rules, to + stable@vger.kernel.org. You must note the upstream commit ID in the + changelog of your submission, as well as the kernel version you wish +diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt +index 6cd63a9..bc6d617 100644 +--- a/Documentation/virtual/kvm/api.txt ++++ b/Documentation/virtual/kvm/api.txt +@@ -2344,7 +2344,8 @@ should be created before this ioctl is invoked. + + Possible features: + - KVM_ARM_VCPU_POWER_OFF: Starts the CPU in a power-off state. +- Depends on KVM_CAP_ARM_PSCI. ++ Depends on KVM_CAP_ARM_PSCI. If not set, the CPU will be powered on ++ and execute guest code when KVM_RUN is called. + - KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode. + Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only). + +diff --git a/Documentation/virtual/kvm/mmu.txt b/Documentation/virtual/kvm/mmu.txt +index 2908941..53838d9 100644 +--- a/Documentation/virtual/kvm/mmu.txt ++++ b/Documentation/virtual/kvm/mmu.txt +@@ -425,6 +425,20 @@ fault through the slow path. + Since only 19 bits are used to store generation-number on mmio spte, all + pages are zapped when there is an overflow. + ++Unfortunately, a single memory access might access kvm_memslots(kvm) multiple ++times, the last one happening when the generation number is retrieved and ++stored into the MMIO spte. Thus, the MMIO spte might be created based on ++out-of-date information, but with an up-to-date generation number. ++ ++To avoid this, the generation number is incremented again after synchronize_srcu ++returns; thus, the low bit of kvm_memslots(kvm)->generation is only 1 during a ++memslot update, while some SRCU readers might be using the old copy. We do not ++want to use an MMIO sptes created with an odd generation number, and we can do ++this without losing a bit in the MMIO spte. The low bit of the generation ++is not stored in MMIO spte, and presumed zero when it is extracted out of the ++spte. If KVM is unlucky and creates an MMIO spte while the low bit is 1, ++the next access to the spte will always be a cache miss. ++ + + Further reading + =============== +diff --git a/Documentation/x86/x86_64/mm.txt b/Documentation/x86/x86_64/mm.txt +index c584a51..afe68dd 100644 +--- a/Documentation/x86/x86_64/mm.txt ++++ b/Documentation/x86/x86_64/mm.txt +@@ -12,6 +12,8 @@ ffffc90000000000 - ffffe8ffffffffff (=45 bits) vmalloc/ioremap space + ffffe90000000000 - ffffe9ffffffffff (=40 bits) hole + ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB) + ... unused hole ... ++ffffff0000000000 - ffffff7fffffffff (=39 bits) %esp fixup stacks ++... unused hole ... + ffffffff80000000 - ffffffffa0000000 (=512 MB) kernel text mapping, from phys 0 + ffffffffa0000000 - ffffffffff5fffff (=1525 MB) module mapping space + ffffffffff600000 - ffffffffffdfffff (=8 MB) vsyscalls +diff --git a/Makefile b/Makefile +index 230c7f6..86d2277 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 14 ++SUBLEVEL = 53 + EXTRAVERSION = + NAME = Remembering Coco + +@@ -244,7 +244,7 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ + + HOSTCC = gcc + HOSTCXX = g++ +-HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer ++HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu89 + HOSTCXXFLAGS = -O2 + + # Decide whether to build built-in, modular, or both. +@@ -382,7 +382,9 @@ KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ + -fno-strict-aliasing -fno-common \ + -Werror-implicit-function-declaration \ + -Wno-format-security \ +- -fno-delete-null-pointer-checks ++ -fno-delete-null-pointer-checks \ ++ -std=gnu89 ++ + KBUILD_AFLAGS_KERNEL := + KBUILD_CFLAGS_KERNEL := + KBUILD_AFLAGS := -D__ASSEMBLY__ +@@ -639,6 +641,8 @@ KBUILD_CFLAGS += -fomit-frame-pointer + endif + endif + ++KBUILD_CFLAGS += $(call cc-option, -fno-var-tracking-assignments) ++ + ifdef CONFIG_DEBUG_INFO + KBUILD_CFLAGS += -g + KBUILD_AFLAGS += -Wa,--gdwarf-2 +diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c +index 98838a0..9d0ac09 100644 +--- a/arch/alpha/mm/fault.c ++++ b/arch/alpha/mm/fault.c +@@ -156,6 +156,8 @@ retry: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/arc/boot/dts/nsimosci.dts b/arch/arc/boot/dts/nsimosci.dts +index 4f31b2e..4c169d8 100644 +--- a/arch/arc/boot/dts/nsimosci.dts ++++ b/arch/arc/boot/dts/nsimosci.dts +@@ -20,7 +20,7 @@ + /* this is for console on PGU */ + /* bootargs = "console=tty0 consoleblank=0"; */ + /* this is for console on serial */ +- bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=ttyS0,115200n8 consoleblank=0 debug"; ++ bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug"; + }; + + aliases { +@@ -46,9 +46,9 @@ + #interrupt-cells = <1>; + }; + +- uart0: serial@c0000000 { ++ uart0: serial@f0000000 { + compatible = "ns8250"; +- reg = <0xc0000000 0x2000>; ++ reg = <0xf0000000 0x2000>; + interrupts = <11>; + clock-frequency = <3686400>; + baud = <115200>; +@@ -57,21 +57,21 @@ + no-loopback-test = <1>; + }; + +- pgu0: pgu@c9000000 { ++ pgu0: pgu@f9000000 { + compatible = "snps,arcpgufb"; +- reg = <0xc9000000 0x400>; ++ reg = <0xf9000000 0x400>; + }; + +- ps2: ps2@c9001000 { ++ ps2: ps2@f9001000 { + compatible = "snps,arc_ps2"; +- reg = <0xc9000400 0x14>; ++ reg = <0xf9000400 0x14>; + interrupts = <13>; + interrupt-names = "arc_ps2_irq"; + }; + +- eth0: ethernet@c0003000 { ++ eth0: ethernet@f0003000 { + compatible = "snps,oscilan"; +- reg = <0xc0003000 0x44>; ++ reg = <0xf0003000 0x44>; + interrupts = <7>, <8>; + interrupt-names = "rx", "tx"; + }; +diff --git a/arch/arc/include/asm/barrier.h b/arch/arc/include/asm/barrier.h +deleted file mode 100644 +index c32245c..0000000 +--- a/arch/arc/include/asm/barrier.h ++++ /dev/null +@@ -1,37 +0,0 @@ +-/* +- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +- */ +- +-#ifndef __ASM_BARRIER_H +-#define __ASM_BARRIER_H +- +-#ifndef __ASSEMBLY__ +- +-/* TODO-vineetg: Need to see what this does, don't we need sync anywhere */ +-#define mb() __asm__ __volatile__ ("" : : : "memory") +-#define rmb() mb() +-#define wmb() mb() +-#define set_mb(var, value) do { var = value; mb(); } while (0) +-#define set_wmb(var, value) do { var = value; wmb(); } while (0) +-#define read_barrier_depends() mb() +- +-/* TODO-vineetg verify the correctness of macros here */ +-#ifdef CONFIG_SMP +-#define smp_mb() mb() +-#define smp_rmb() rmb() +-#define smp_wmb() wmb() +-#else +-#define smp_mb() barrier() +-#define smp_rmb() barrier() +-#define smp_wmb() barrier() +-#endif +- +-#define smp_read_barrier_depends() do { } while (0) +- +-#endif +- +-#endif +diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h +index 2fd3162..c1d3d2d 100644 +--- a/arch/arc/include/asm/cache.h ++++ b/arch/arc/include/asm/cache.h +@@ -55,4 +55,31 @@ extern void read_decode_cache_bcr(void); + + #endif /* !__ASSEMBLY__ */ + ++/* Instruction cache related Auxiliary registers */ ++#define ARC_REG_IC_BCR 0x77 /* Build Config reg */ ++#define ARC_REG_IC_IVIC 0x10 ++#define ARC_REG_IC_CTRL 0x11 ++#define ARC_REG_IC_IVIL 0x19 ++#if defined(CONFIG_ARC_MMU_V3) || defined (CONFIG_ARC_MMU_V4) ++#define ARC_REG_IC_PTAG 0x1E ++#endif ++ ++/* Bit val in IC_CTRL */ ++#define IC_CTRL_CACHE_DISABLE 0x1 ++ ++/* Data cache related Auxiliary registers */ ++#define ARC_REG_DC_BCR 0x72 /* Build Config reg */ ++#define ARC_REG_DC_IVDC 0x47 ++#define ARC_REG_DC_CTRL 0x48 ++#define ARC_REG_DC_IVDL 0x4A ++#define ARC_REG_DC_FLSH 0x4B ++#define ARC_REG_DC_FLDL 0x4C ++#if defined(CONFIG_ARC_MMU_V3) || defined (CONFIG_ARC_MMU_V4) ++#define ARC_REG_DC_PTAG 0x5C ++#endif ++ ++/* Bit val in DC_CTRL */ ++#define DC_CTRL_INV_MODE_FLUSH 0x40 ++#define DC_CTRL_FLUSH_STATUS 0x100 ++ + #endif /* _ASM_CACHE_H */ +diff --git a/arch/arc/include/asm/cmpxchg.h b/arch/arc/include/asm/cmpxchg.h +index 03cd689..90de5c5 100644 +--- a/arch/arc/include/asm/cmpxchg.h ++++ b/arch/arc/include/asm/cmpxchg.h +@@ -25,10 +25,11 @@ __cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new) + " scond %3, [%1] \n" + " bnz 1b \n" + "2: \n" +- : "=&r"(prev) +- : "r"(ptr), "ir"(expected), +- "r"(new) /* can't be "ir". scond can't take limm for "b" */ +- : "cc"); ++ : "=&r"(prev) /* Early clobber, to prevent reg reuse */ ++ : "r"(ptr), /* Not "m": llock only supports reg direct addr mode */ ++ "ir"(expected), ++ "r"(new) /* can't be "ir". scond can't take LIMM for "b" */ ++ : "cc", "memory"); /* so that gcc knows memory is being written here */ + + return prev; + } +diff --git a/arch/arc/include/asm/kgdb.h b/arch/arc/include/asm/kgdb.h +index b65fca7..fea9316 100644 +--- a/arch/arc/include/asm/kgdb.h ++++ b/arch/arc/include/asm/kgdb.h +@@ -19,7 +19,7 @@ + * register API yet */ + #undef DBG_MAX_REG_NUM + +-#define GDB_MAX_REGS 39 ++#define GDB_MAX_REGS 87 + + #define BREAK_INSTR_SIZE 2 + #define CACHE_FLUSH_IS_SAFE 1 +@@ -33,23 +33,27 @@ static inline void arch_kgdb_breakpoint(void) + + extern void kgdb_trap(struct pt_regs *regs); + +-enum arc700_linux_regnums { ++/* This is the numbering of registers according to the GDB. See GDB's ++ * arc-tdep.h for details. ++ * ++ * Registers are ordered for GDB 7.5. It is incompatible with GDB 6.8. */ ++enum arc_linux_regnums { + _R0 = 0, + _R1, _R2, _R3, _R4, _R5, _R6, _R7, _R8, _R9, _R10, _R11, _R12, _R13, + _R14, _R15, _R16, _R17, _R18, _R19, _R20, _R21, _R22, _R23, _R24, + _R25, _R26, +- _BTA = 27, +- _LP_START = 28, +- _LP_END = 29, +- _LP_COUNT = 30, +- _STATUS32 = 31, +- _BLINK = 32, +- _FP = 33, +- __SP = 34, +- _EFA = 35, +- _RET = 36, +- _ORIG_R8 = 37, +- _STOP_PC = 38 ++ _FP = 27, ++ __SP = 28, ++ _R30 = 30, ++ _BLINK = 31, ++ _LP_COUNT = 60, ++ _STOP_PC = 64, ++ _RET = 64, ++ _LP_START = 65, ++ _LP_END = 66, ++ _STATUS32 = 67, ++ _ECR = 76, ++ _BTA = 82, + }; + + #else +diff --git a/arch/arc/include/asm/linkage.h b/arch/arc/include/asm/linkage.h +index 66ee552..5faad17 100644 +--- a/arch/arc/include/asm/linkage.h ++++ b/arch/arc/include/asm/linkage.h +@@ -13,20 +13,6 @@ + + #define ASM_NL ` /* use '`' to mark new line in macro */ + +-/* Can't use the ENTRY macro in linux/linkage.h +- * gas considers ';' as comment vs. newline +- */ +-.macro ARC_ENTRY name +- .global \name +- .align 4 +- \name: +-.endm +- +-.macro ARC_EXIT name +-#define ASM_PREV_SYM_ADDR(name) .-##name +- .size \ name, ASM_PREV_SYM_ADDR(\name) +-.endm +- + /* annotation for data we want in DCCM - if enabled in .config */ + .macro ARCFP_DATA nm + #ifdef CONFIG_ARC_HAS_DCCM +diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h +index 6b0b7f7e..7670f33 100644 +--- a/arch/arc/include/asm/pgtable.h ++++ b/arch/arc/include/asm/pgtable.h +@@ -259,7 +259,8 @@ static inline void pmd_set(pmd_t *pmdp, pte_t *ptep) + #define pmd_clear(xp) do { pmd_val(*(xp)) = 0; } while (0) + + #define pte_page(x) (mem_map + \ +- (unsigned long)(((pte_val(x) - PAGE_OFFSET) >> PAGE_SHIFT))) ++ (unsigned long)(((pte_val(x) - CONFIG_LINUX_LINK_BASE) >> \ ++ PAGE_SHIFT))) + + #define mk_pte(page, pgprot) \ + ({ \ +diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h +index 15334ab..fb95aa8 100644 +--- a/arch/arc/include/asm/processor.h ++++ b/arch/arc/include/asm/processor.h +@@ -69,18 +69,19 @@ unsigned long thread_saved_pc(struct task_struct *t); + #define release_segments(mm) do { } while (0) + + #define KSTK_EIP(tsk) (task_pt_regs(tsk)->ret) ++#define KSTK_ESP(tsk) (task_pt_regs(tsk)->sp) + + /* + * Where abouts of Task's sp, fp, blink when it was last seen in kernel mode. + * Look in process.c for details of kernel stack layout + */ +-#define KSTK_ESP(tsk) (tsk->thread.ksp) ++#define TSK_K_ESP(tsk) (tsk->thread.ksp) + +-#define KSTK_REG(tsk, off) (*((unsigned int *)(KSTK_ESP(tsk) + \ ++#define TSK_K_REG(tsk, off) (*((unsigned int *)(TSK_K_ESP(tsk) + \ + sizeof(struct callee_regs) + off))) + +-#define KSTK_BLINK(tsk) KSTK_REG(tsk, 4) +-#define KSTK_FP(tsk) KSTK_REG(tsk, 0) ++#define TSK_K_BLINK(tsk) TSK_K_REG(tsk, 4) ++#define TSK_K_FP(tsk) TSK_K_REG(tsk, 0) + + /* + * Do necessary setup to start up a newly executed thread. +diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h +index 1bfeec2..2a58af7 100644 +--- a/arch/arc/include/asm/ptrace.h ++++ b/arch/arc/include/asm/ptrace.h +@@ -63,7 +63,7 @@ struct callee_regs { + long r25, r24, r23, r22, r21, r20, r19, r18, r17, r16, r15, r14, r13; + }; + +-#define instruction_pointer(regs) ((regs)->ret) ++#define instruction_pointer(regs) (unsigned long)((regs)->ret) + #define profile_pc(regs) instruction_pointer(regs) + + /* return 1 if user mode or 0 if kernel mode */ +diff --git a/arch/arc/kernel/ctx_sw_asm.S b/arch/arc/kernel/ctx_sw_asm.S +index 65690e7..e248594 100644 +--- a/arch/arc/kernel/ctx_sw_asm.S ++++ b/arch/arc/kernel/ctx_sw_asm.S +@@ -10,9 +10,9 @@ + * -This is the more "natural" hand written assembler + */ + ++#include + #include /* For the SAVE_* macros */ + #include +-#include + + #define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) + +@@ -62,4 +62,4 @@ __switch_to: + ld.ab blink, [sp, 4] + j [blink] + +-ARC_EXIT __switch_to ++END(__switch_to) +diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S +index 6e8f83a..29b82ad 100644 +--- a/arch/arc/kernel/entry.S ++++ b/arch/arc/kernel/entry.S +@@ -141,7 +141,7 @@ VECTOR EV_Extension ; 0x130, Extn Intruction Excp (0x26) + VECTOR reserved ; Reserved Exceptions + .endr + +-#include /* ARC_{EXTRY,EXIT} */ ++#include /* {EXTRY,EXIT} */ + #include /* SAVE_ALL_{INT1,INT2,SYS...} */ + #include + #include +@@ -184,7 +184,7 @@ reserved: ; processor restart + ; --------------------------------------------- + ; Level 2 ISR: Can interrupt a Level 1 ISR + ; --------------------------------------------- +-ARC_ENTRY handle_interrupt_level2 ++ENTRY(handle_interrupt_level2) + + ; TODO-vineetg for SMP this wont work + ; free up r9 as scratchpad +@@ -225,14 +225,14 @@ ARC_ENTRY handle_interrupt_level2 + + b ret_from_exception + +-ARC_EXIT handle_interrupt_level2 ++END(handle_interrupt_level2) + + #endif + + ; --------------------------------------------- + ; Level 1 ISR + ; --------------------------------------------- +-ARC_ENTRY handle_interrupt_level1 ++ENTRY(handle_interrupt_level1) + + /* free up r9 as scratchpad */ + #ifdef CONFIG_SMP +@@ -265,7 +265,7 @@ ARC_ENTRY handle_interrupt_level1 + sr r8, [AUX_IRQ_LV12] ; clear bit in Sticky Status Reg + + b ret_from_exception +-ARC_EXIT handle_interrupt_level1 ++END(handle_interrupt_level1) + + ;################### Non TLB Exception Handling ############################# + +@@ -273,7 +273,7 @@ ARC_EXIT handle_interrupt_level1 + ; Instruction Error Exception Handler + ; --------------------------------------------- + +-ARC_ENTRY instr_service ++ENTRY(instr_service) + + EXCEPTION_PROLOGUE + +@@ -284,13 +284,13 @@ ARC_ENTRY instr_service + + bl do_insterror_or_kprobe + b ret_from_exception +-ARC_EXIT instr_service ++END(instr_service) + + ; --------------------------------------------- + ; Memory Error Exception Handler + ; --------------------------------------------- + +-ARC_ENTRY mem_service ++ENTRY(mem_service) + + EXCEPTION_PROLOGUE + +@@ -301,13 +301,13 @@ ARC_ENTRY mem_service + + bl do_memory_error + b ret_from_exception +-ARC_EXIT mem_service ++END(mem_service) + + ; --------------------------------------------- + ; Machine Check Exception Handler + ; --------------------------------------------- + +-ARC_ENTRY EV_MachineCheck ++ENTRY(EV_MachineCheck) + + EXCEPTION_PROLOGUE + +@@ -331,13 +331,13 @@ ARC_ENTRY EV_MachineCheck + + j do_machine_check_fault + +-ARC_EXIT EV_MachineCheck ++END(EV_MachineCheck) + + ; --------------------------------------------- + ; Protection Violation Exception Handler + ; --------------------------------------------- + +-ARC_ENTRY EV_TLBProtV ++ENTRY(EV_TLBProtV) + + EXCEPTION_PROLOGUE + +@@ -385,12 +385,12 @@ ARC_ENTRY EV_TLBProtV + + b ret_from_exception + +-ARC_EXIT EV_TLBProtV ++END(EV_TLBProtV) + + ; --------------------------------------------- + ; Privilege Violation Exception Handler + ; --------------------------------------------- +-ARC_ENTRY EV_PrivilegeV ++ENTRY(EV_PrivilegeV) + + EXCEPTION_PROLOGUE + +@@ -401,12 +401,12 @@ ARC_ENTRY EV_PrivilegeV + + bl do_privilege_fault + b ret_from_exception +-ARC_EXIT EV_PrivilegeV ++END(EV_PrivilegeV) + + ; --------------------------------------------- + ; Extension Instruction Exception Handler + ; --------------------------------------------- +-ARC_ENTRY EV_Extension ++ENTRY(EV_Extension) + + EXCEPTION_PROLOGUE + +@@ -417,7 +417,7 @@ ARC_ENTRY EV_Extension + + bl do_extension_fault + b ret_from_exception +-ARC_EXIT EV_Extension ++END(EV_Extension) + + ;######################### System Call Tracing ######################### + +@@ -504,7 +504,7 @@ trap_with_param: + ; (2) Break Points + ;------------------------------------------------------------------ + +-ARC_ENTRY EV_Trap ++ENTRY(EV_Trap) + + EXCEPTION_PROLOGUE + +@@ -534,9 +534,9 @@ ARC_ENTRY EV_Trap + jl [r9] ; Entry into Sys Call Handler + + ; fall through to ret_from_system_call +-ARC_EXIT EV_Trap ++END(EV_Trap) + +-ARC_ENTRY ret_from_system_call ++ENTRY(ret_from_system_call) + + st r0, [sp, PT_r0] ; sys call return value in pt_regs + +@@ -546,7 +546,7 @@ ARC_ENTRY ret_from_system_call + ; + ; If ret to user mode do we need to handle signals, schedule() et al. + +-ARC_ENTRY ret_from_exception ++ENTRY(ret_from_exception) + + ; Pre-{IRQ,Trap,Exception} K/U mode from pt_regs->status32 + ld r8, [sp, PT_status32] ; returning to User/Kernel Mode +@@ -728,9 +728,9 @@ not_level1_interrupt: + debug_marker_syscall: + rtie + +-ARC_EXIT ret_from_exception ++END(ret_from_exception) + +-ARC_ENTRY ret_from_fork ++ENTRY(ret_from_fork) + ; when the forked child comes here from the __switch_to function + ; r0 has the last task pointer. + ; put last task in scheduler queue +@@ -747,11 +747,11 @@ ARC_ENTRY ret_from_fork + ; special case of kernel_thread entry point returning back due to + ; kernel_execve() - pretend return from syscall to ret to userland + b ret_from_exception +-ARC_EXIT ret_from_fork ++END(ret_from_fork) + + ;################### Special Sys Call Wrappers ########################## + +-ARC_ENTRY sys_clone_wrapper ++ENTRY(sys_clone_wrapper) + SAVE_CALLEE_SAVED_USER + bl @sys_clone + DISCARD_CALLEE_SAVED_USER +@@ -761,7 +761,7 @@ ARC_ENTRY sys_clone_wrapper + bnz tracesys_exit + + b ret_from_system_call +-ARC_EXIT sys_clone_wrapper ++END(sys_clone_wrapper) + + #ifdef CONFIG_ARC_DW2_UNWIND + ; Workaround for bug 94179 (STAR ): +diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S +index 9919972..07a58f2 100644 +--- a/arch/arc/kernel/head.S ++++ b/arch/arc/kernel/head.S +@@ -12,10 +12,42 @@ + * to skip certain things during boot on simulator + */ + ++#include + #include + #include +-#include + #include ++#include ++ ++.macro CPU_EARLY_SETUP ++ ++ ; Setting up Vectror Table (in case exception happens in early boot ++ sr @_int_vec_base_lds, [AUX_INTR_VEC_BASE] ++ ++ ; Disable I-cache/D-cache if kernel so configured ++ lr r5, [ARC_REG_IC_BCR] ++ breq r5, 0, 1f ; I$ doesn't exist ++ lr r5, [ARC_REG_IC_CTRL] ++#ifdef CONFIG_ARC_HAS_ICACHE ++ bclr r5, r5, 0 ; 0 - Enable, 1 is Disable ++#else ++ bset r5, r5, 0 ; I$ exists, but is not used ++#endif ++ sr r5, [ARC_REG_IC_CTRL] ++ ++1: ++ lr r5, [ARC_REG_DC_BCR] ++ breq r5, 0, 1f ; D$ doesn't exist ++ lr r5, [ARC_REG_DC_CTRL] ++ bclr r5, r5, 6 ; Invalidate (discard w/o wback) ++#ifdef CONFIG_ARC_HAS_DCACHE ++ bclr r5, r5, 0 ; Enable (+Inv) ++#else ++ bset r5, r5, 0 ; Disable (+Inv) ++#endif ++ sr r5, [ARC_REG_DC_CTRL] ++ ++1: ++.endm + + .cpu A7 + +@@ -24,13 +56,13 @@ + .globl stext + stext: + ;------------------------------------------------------------------- +- ; Don't clobber r0-r4 yet. It might have bootloader provided info ++ ; Don't clobber r0-r2 yet. It might have bootloader provided info + ;------------------------------------------------------------------- + +- sr @_int_vec_base_lds, [AUX_INTR_VEC_BASE] ++ CPU_EARLY_SETUP + + #ifdef CONFIG_SMP +- ; Only Boot (Master) proceeds. Others wait in platform dependent way ++ ; Ensure Boot (Master) proceeds. Others wait in platform dependent way + ; IDENTITY Reg [ 3 2 1 0 ] + ; (cpu-id) ^^^ => Zero for UP ARC700 + ; => #Core-ID if SMP (Master 0) +@@ -39,7 +71,8 @@ stext: + ; need to make sure only boot cpu takes this path. + GET_CPU_ID r5 + cmp r5, 0 +- jnz arc_platform_smp_wait_to_boot ++ mov.ne r0, r5 ++ jne arc_platform_smp_wait_to_boot + #endif + ; Clear BSS before updating any globals + ; XXX: use ZOL here +@@ -89,7 +122,7 @@ stext: + + first_lines_of_secondary: + +- sr @_int_vec_base_lds, [AUX_INTR_VEC_BASE] ++ CPU_EARLY_SETUP + + ; setup per-cpu idle task as "current" on this CPU + ld r0, [@secondary_idle_tsk] +diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c +index 7e95e1a..a0c63fc 100644 +--- a/arch/arc/kernel/signal.c ++++ b/arch/arc/kernel/signal.c +@@ -67,7 +67,7 @@ stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs, + sigset_t *set) + { + int err; +- err = __copy_to_user(&(sf->uc.uc_mcontext.regs), regs, ++ err = __copy_to_user(&(sf->uc.uc_mcontext.regs.scratch), regs, + sizeof(sf->uc.uc_mcontext.regs.scratch)); + err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t)); + +@@ -83,7 +83,7 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf) + if (!err) + set_current_blocked(&set); + +- err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs), ++ err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs.scratch), + sizeof(sf->uc.uc_mcontext.regs.scratch)); + + return err; +@@ -131,6 +131,15 @@ SYSCALL_DEFINE0(rt_sigreturn) + /* Don't restart from sigreturn */ + syscall_wont_restart(regs); + ++ /* ++ * Ensure that sigreturn always returns to user mode (in case the ++ * regs saved on user stack got fudged between save and sigreturn) ++ * Otherwise it is easy to panic the kernel with a custom ++ * signal handler and/or restorer which clobberes the status32/ret ++ * to return to a bogus location in kernel mode. ++ */ ++ regs->status32 |= STATUS_U_MASK; ++ + return regs->r0; + + badframe: +@@ -234,8 +243,11 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info, + + /* + * handler returns using sigreturn stub provided already by userpsace ++ * If not, nuke the process right away + */ +- BUG_ON(!(ka->sa.sa_flags & SA_RESTORER)); ++ if(!(ka->sa.sa_flags & SA_RESTORER)) ++ return 1; ++ + regs->blink = (unsigned long)ka->sa.sa_restorer; + + /* User Stack for signal handler will be above the frame just carved */ +@@ -302,12 +314,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, + struct pt_regs *regs) + { + sigset_t *oldset = sigmask_to_save(); +- int ret; ++ int failed; + + /* Set up the stack frame */ +- ret = setup_rt_frame(sig, ka, info, oldset, regs); ++ failed = setup_rt_frame(sig, ka, info, oldset, regs); + +- if (ret) ++ if (failed) + force_sigsegv(sig, current); + else + signal_delivered(sig, info, ka, regs, 0); +diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c +index 9ce47cf..fb98769 100644 +--- a/arch/arc/kernel/stacktrace.c ++++ b/arch/arc/kernel/stacktrace.c +@@ -64,9 +64,9 @@ static void seed_unwind_frame_info(struct task_struct *tsk, + + frame_info->task = tsk; + +- frame_info->regs.r27 = KSTK_FP(tsk); +- frame_info->regs.r28 = KSTK_ESP(tsk); +- frame_info->regs.r31 = KSTK_BLINK(tsk); ++ frame_info->regs.r27 = TSK_K_FP(tsk); ++ frame_info->regs.r28 = TSK_K_ESP(tsk); ++ frame_info->regs.r31 = TSK_K_BLINK(tsk); + frame_info->regs.r63 = (unsigned int)__switch_to; + + /* In the prologue of __switch_to, first FP is saved on stack +diff --git a/arch/arc/lib/memcmp.S b/arch/arc/lib/memcmp.S +index bc813d5..978bf83 100644 +--- a/arch/arc/lib/memcmp.S ++++ b/arch/arc/lib/memcmp.S +@@ -6,7 +6,7 @@ + * published by the Free Software Foundation. + */ + +-#include ++#include + + #ifdef __LITTLE_ENDIAN__ + #define WORD2 r2 +@@ -16,7 +16,7 @@ + #define SHIFT r2 + #endif + +-ARC_ENTRY memcmp ++ENTRY(memcmp) + or r12,r0,r1 + asl_s r12,r12,30 + sub r3,r2,1 +@@ -121,4 +121,4 @@ ARC_ENTRY memcmp + .Lnil: + j_s.d [blink] + mov r0,0 +-ARC_EXIT memcmp ++END(memcmp) +diff --git a/arch/arc/lib/memcpy-700.S b/arch/arc/lib/memcpy-700.S +index b64cc10..3222573 100644 +--- a/arch/arc/lib/memcpy-700.S ++++ b/arch/arc/lib/memcpy-700.S +@@ -6,9 +6,9 @@ + * published by the Free Software Foundation. + */ + +-#include ++#include + +-ARC_ENTRY memcpy ++ENTRY(memcpy) + or r3,r0,r1 + asl_s r3,r3,30 + mov_s r5,r0 +@@ -63,4 +63,4 @@ ARC_ENTRY memcpy + .Lendbloop: + j_s.d [blink] + stb r12,[r5,0] +-ARC_EXIT memcpy ++END(memcpy) +diff --git a/arch/arc/lib/memset.S b/arch/arc/lib/memset.S +index 9b2d88d..d36bd43 100644 +--- a/arch/arc/lib/memset.S ++++ b/arch/arc/lib/memset.S +@@ -6,11 +6,11 @@ + * published by the Free Software Foundation. + */ + +-#include ++#include + + #define SMALL 7 /* Must be at least 6 to deal with alignment/loop issues. */ + +-ARC_ENTRY memset ++ENTRY(memset) + mov_s r4,r0 + or r12,r0,r2 + bmsk.f r12,r12,1 +@@ -46,14 +46,14 @@ ARC_ENTRY memset + stb.ab r1,[r4,1] + .Ltiny_end: + j_s [blink] +-ARC_EXIT memset ++END(memset) + + ; memzero: @r0 = mem, @r1 = size_t + ; memset: @r0 = mem, @r1 = char, @r2 = size_t + +-ARC_ENTRY memzero ++ENTRY(memzero) + ; adjust bzero args to memset args + mov r2, r1 + mov r1, 0 + b memset ;tail call so need to tinker with blink +-ARC_EXIT memzero ++END(memzero) +diff --git a/arch/arc/lib/strchr-700.S b/arch/arc/lib/strchr-700.S +index 9c548c7..b725d58 100644 +--- a/arch/arc/lib/strchr-700.S ++++ b/arch/arc/lib/strchr-700.S +@@ -11,9 +11,9 @@ + presence of the norm instruction makes it easier to operate on whole + words branch-free. */ + +-#include ++#include + +-ARC_ENTRY strchr ++ENTRY(strchr) + extb_s r1,r1 + asl r5,r1,8 + bmsk r2,r0,1 +@@ -130,4 +130,4 @@ ARC_ENTRY strchr + j_s.d [blink] + mov.mi r0,0 + #endif /* ENDIAN */ +-ARC_EXIT strchr ++END(strchr) +diff --git a/arch/arc/lib/strcmp.S b/arch/arc/lib/strcmp.S +index 5dc802b..3544600 100644 +--- a/arch/arc/lib/strcmp.S ++++ b/arch/arc/lib/strcmp.S +@@ -13,9 +13,9 @@ + source 1; however, that would increase the overhead for loop setup / finish, + and strcmp might often terminate early. */ + +-#include ++#include + +-ARC_ENTRY strcmp ++ENTRY(strcmp) + or r2,r0,r1 + bmsk_s r2,r2,1 + brne r2,0,.Lcharloop +@@ -93,4 +93,4 @@ ARC_ENTRY strcmp + .Lcmpend: + j_s.d [blink] + sub r0,r2,r3 +-ARC_EXIT strcmp ++END(strcmp) +diff --git a/arch/arc/lib/strcpy-700.S b/arch/arc/lib/strcpy-700.S +index b7ca4ae..8422f38 100644 +--- a/arch/arc/lib/strcpy-700.S ++++ b/arch/arc/lib/strcpy-700.S +@@ -16,9 +16,9 @@ + there, but the it is not likely to be taken often, and it + would also be likey to cost an unaligned mispredict at the next call. */ + +-#include ++#include + +-ARC_ENTRY strcpy ++ENTRY(strcpy) + or r2,r0,r1 + bmsk_s r2,r2,1 + brne.d r2,0,charloop +@@ -67,4 +67,4 @@ charloop: + brne.d r3,0,charloop + stb.ab r3,[r10,1] + j [blink] +-ARC_EXIT strcpy ++END(strcpy) +diff --git a/arch/arc/lib/strlen.S b/arch/arc/lib/strlen.S +index 39759e0..53cfd56 100644 +--- a/arch/arc/lib/strlen.S ++++ b/arch/arc/lib/strlen.S +@@ -6,9 +6,9 @@ + * published by the Free Software Foundation. + */ + +-#include ++#include + +-ARC_ENTRY strlen ++ENTRY(strlen) + or r3,r0,7 + ld r2,[r3,-7] + ld.a r6,[r3,-3] +@@ -80,4 +80,4 @@ ARC_ENTRY strlen + .Learly_end: + b.d .Lend + sub_s.ne r1,r1,r1 +-ARC_EXIT strlen ++END(strlen) +diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c +index 400c663..1f676c4 100644 +--- a/arch/arc/mm/cache_arc700.c ++++ b/arch/arc/mm/cache_arc700.c +@@ -73,37 +73,9 @@ + #include + #include + +-/* Instruction cache related Auxiliary registers */ +-#define ARC_REG_IC_BCR 0x77 /* Build Config reg */ +-#define ARC_REG_IC_IVIC 0x10 +-#define ARC_REG_IC_CTRL 0x11 +-#define ARC_REG_IC_IVIL 0x19 +-#if (CONFIG_ARC_MMU_VER > 2) +-#define ARC_REG_IC_PTAG 0x1E +-#endif +- +-/* Bit val in IC_CTRL */ +-#define IC_CTRL_CACHE_DISABLE 0x1 +- +-/* Data cache related Auxiliary registers */ +-#define ARC_REG_DC_BCR 0x72 /* Build Config reg */ +-#define ARC_REG_DC_IVDC 0x47 +-#define ARC_REG_DC_CTRL 0x48 +-#define ARC_REG_DC_IVDL 0x4A +-#define ARC_REG_DC_FLSH 0x4B +-#define ARC_REG_DC_FLDL 0x4C +-#if (CONFIG_ARC_MMU_VER > 2) +-#define ARC_REG_DC_PTAG 0x5C +-#endif +- +-/* Bit val in DC_CTRL */ +-#define DC_CTRL_INV_MODE_FLUSH 0x40 +-#define DC_CTRL_FLUSH_STATUS 0x100 +- +-char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len) ++char *arc_cache_mumbojumbo(int c, char *buf, int len) + { + int n = 0; +- unsigned int c = smp_processor_id(); + + #define PR_CACHE(p, enb, str) \ + { \ +@@ -169,72 +141,43 @@ void read_decode_cache_bcr(void) + */ + void arc_cache_init(void) + { +- unsigned int cpu = smp_processor_id(); +- struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache; +- struct cpuinfo_arc_cache *dc = &cpuinfo_arc700[cpu].dcache; +- unsigned int dcache_does_alias, temp; ++ unsigned int __maybe_unused cpu = smp_processor_id(); ++ struct cpuinfo_arc_cache __maybe_unused *ic, __maybe_unused *dc; + char str[256]; + + printk(arc_cache_mumbojumbo(0, str, sizeof(str))); + +- if (!ic->ver) +- goto chk_dc; +- +-#ifdef CONFIG_ARC_HAS_ICACHE +- /* 1. Confirm some of I-cache params which Linux assumes */ +- if (ic->line_len != L1_CACHE_BYTES) +- panic("Cache H/W doesn't match kernel Config"); +- +- if (ic->ver != CONFIG_ARC_MMU_VER) +- panic("Cache ver doesn't match MMU ver\n"); +-#endif +- +- /* Enable/disable I-Cache */ +- temp = read_aux_reg(ARC_REG_IC_CTRL); +- + #ifdef CONFIG_ARC_HAS_ICACHE +- temp &= ~IC_CTRL_CACHE_DISABLE; +-#else +- temp |= IC_CTRL_CACHE_DISABLE; ++ ic = &cpuinfo_arc700[cpu].icache; ++ if (ic->ver) { ++ if (ic->line_len != L1_CACHE_BYTES) ++ panic("ICache line [%d] != kernel Config [%d]", ++ ic->line_len, L1_CACHE_BYTES); ++ ++ if (ic->ver != CONFIG_ARC_MMU_VER) ++ panic("Cache ver [%d] doesn't match MMU ver [%d]\n", ++ ic->ver, CONFIG_ARC_MMU_VER); ++ } + #endif + +- write_aux_reg(ARC_REG_IC_CTRL, temp); +- +-chk_dc: +- if (!dc->ver) +- return; +- + #ifdef CONFIG_ARC_HAS_DCACHE +- if (dc->line_len != L1_CACHE_BYTES) +- panic("Cache H/W doesn't match kernel Config"); ++ dc = &cpuinfo_arc700[cpu].dcache; ++ if (dc->ver) { ++ unsigned int dcache_does_alias; + +- /* check for D-Cache aliasing */ +- dcache_does_alias = (dc->sz / dc->assoc) > PAGE_SIZE; ++ if (dc->line_len != L1_CACHE_BYTES) ++ panic("DCache line [%d] != kernel Config [%d]", ++ dc->line_len, L1_CACHE_BYTES); + +- if (dcache_does_alias && !cache_is_vipt_aliasing()) +- panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n"); +- else if (!dcache_does_alias && cache_is_vipt_aliasing()) +- panic("Don't need CONFIG_ARC_CACHE_VIPT_ALIASING\n"); +-#endif +- +- /* Set the default Invalidate Mode to "simpy discard dirty lines" +- * as this is more frequent then flush before invalidate +- * Ofcourse we toggle this default behviour when desired +- */ +- temp = read_aux_reg(ARC_REG_DC_CTRL); +- temp &= ~DC_CTRL_INV_MODE_FLUSH; ++ /* check for D-Cache aliasing */ ++ dcache_does_alias = (dc->sz / dc->assoc) > PAGE_SIZE; + +-#ifdef CONFIG_ARC_HAS_DCACHE +- /* Enable D-Cache: Clear Bit 0 */ +- write_aux_reg(ARC_REG_DC_CTRL, temp & ~IC_CTRL_CACHE_DISABLE); +-#else +- /* Flush D cache */ +- write_aux_reg(ARC_REG_DC_FLSH, 0x1); +- /* Disable D cache */ +- write_aux_reg(ARC_REG_DC_CTRL, temp | IC_CTRL_CACHE_DISABLE); ++ if (dcache_does_alias && !cache_is_vipt_aliasing()) ++ panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n"); ++ else if (!dcache_does_alias && cache_is_vipt_aliasing()) ++ panic("Don't need CONFIG_ARC_CACHE_VIPT_ALIASING\n"); ++ } + #endif +- +- return; + } + + #define OP_INV 0x1 +@@ -254,12 +197,16 @@ static inline void __cache_line_loop(unsigned long paddr, unsigned long vaddr, + + if (cacheop == OP_INV_IC) { + aux_cmd = ARC_REG_IC_IVIL; ++#if (CONFIG_ARC_MMU_VER > 2) + aux_tag = ARC_REG_IC_PTAG; ++#endif + } + else { + /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ + aux_cmd = cacheop & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL; ++#if (CONFIG_ARC_MMU_VER > 2) + aux_tag = ARC_REG_DC_PTAG; ++#endif + } + + /* Ensure we properly floor/ceil the non-line aligned/sized requests +diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c +index 9c69552..01e18b5 100644 +--- a/arch/arc/mm/fault.c ++++ b/arch/arc/mm/fault.c +@@ -162,6 +162,8 @@ good_area: + /* TBD: switch to pagefault_out_of_memory() */ + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + +diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S +index 3fcfdb3..79bfc81 100644 +--- a/arch/arc/mm/tlbex.S ++++ b/arch/arc/mm/tlbex.S +@@ -260,7 +260,7 @@ ARCFP_CODE ;Fast Path Code, candidate for ICCM + ; I-TLB Miss Exception Handler + ;----------------------------------------------------------------------------- + +-ARC_ENTRY EV_TLBMissI ++ENTRY(EV_TLBMissI) + + TLBMISS_FREEUP_REGS + +@@ -293,13 +293,13 @@ ARC_ENTRY EV_TLBMissI + TLBMISS_RESTORE_REGS + rtie + +-ARC_EXIT EV_TLBMissI ++END(EV_TLBMissI) + + ;----------------------------------------------------------------------------- + ; D-TLB Miss Exception Handler + ;----------------------------------------------------------------------------- + +-ARC_ENTRY EV_TLBMissD ++ENTRY(EV_TLBMissD) + + TLBMISS_FREEUP_REGS + +@@ -381,6 +381,4 @@ do_slow_path_pf: + bl do_page_fault + b ret_from_exception + +-ARC_EXIT EV_TLBMissD +- +-ARC_ENTRY EV_TLBMissB ; Bogus entry to measure sz of DTLBMiss hdlr ++END(EV_TLBMissD) +diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S +index 066b034..8017cde 100644 +--- a/arch/arm/boot/compressed/head.S ++++ b/arch/arm/boot/compressed/head.S +@@ -400,8 +400,7 @@ dtb_check_done: + add sp, sp, r6 + #endif + +- tst r4, #1 +- bleq cache_clean_flush ++ bl cache_clean_flush + + adr r0, BSYM(restart) + add r0, r0, r6 +@@ -1050,6 +1049,8 @@ cache_clean_flush: + b call_cache_fn + + __armv4_mpu_cache_flush: ++ tst r4, #1 ++ movne pc, lr + mov r2, #1 + mov r3, #0 + mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache +@@ -1067,6 +1068,8 @@ __armv4_mpu_cache_flush: + mov pc, lr + + __fa526_cache_flush: ++ tst r4, #1 ++ movne pc, lr + mov r1, #0 + mcr p15, 0, r1, c7, c14, 0 @ clean and invalidate D cache + mcr p15, 0, r1, c7, c5, 0 @ flush I cache +@@ -1075,13 +1078,16 @@ __fa526_cache_flush: + + __armv6_mmu_cache_flush: + mov r1, #0 +- mcr p15, 0, r1, c7, c14, 0 @ clean+invalidate D ++ tst r4, #1 ++ mcreq p15, 0, r1, c7, c14, 0 @ clean+invalidate D + mcr p15, 0, r1, c7, c5, 0 @ invalidate I+BTB +- mcr p15, 0, r1, c7, c15, 0 @ clean+invalidate unified ++ mcreq p15, 0, r1, c7, c15, 0 @ clean+invalidate unified + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mov pc, lr + + __armv7_mmu_cache_flush: ++ tst r4, #1 ++ bne iflush + mrc p15, 0, r10, c0, c1, 5 @ read ID_MMFR1 + tst r10, #0xf << 16 @ hierarchical cache (ARMv7) + mov r10, #0 +@@ -1142,6 +1148,8 @@ iflush: + mov pc, lr + + __armv5tej_mmu_cache_flush: ++ tst r4, #1 ++ movne pc, lr + 1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate D cache + bne 1b + mcr p15, 0, r0, c7, c5, 0 @ flush I cache +@@ -1149,6 +1157,8 @@ __armv5tej_mmu_cache_flush: + mov pc, lr + + __armv4_mmu_cache_flush: ++ tst r4, #1 ++ movne pc, lr + mov r2, #64*1024 @ default: 32K dcache size (*2) + mov r11, #32 @ default: 32 byte line size + mrc p15, 0, r3, c0, c0, 1 @ read cache type +@@ -1182,6 +1192,8 @@ no_cache_id: + + __armv3_mmu_cache_flush: + __armv3_mpu_cache_flush: ++ tst r4, #1 ++ movne pc, lr + mov r1, #0 + mcr p15, 0, r1, c7, c0, 0 @ invalidate whole cache v3 + mov pc, lr +diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi +index 2e7d932..b3eff40 100644 +--- a/arch/arm/boot/dts/am335x-bone-common.dtsi ++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi +@@ -197,6 +197,7 @@ + + usb@47401000 { + status = "okay"; ++ dr_mode = "peripheral"; + }; + + usb@47401800 { +diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi +index c6bd4d9..8775681 100644 +--- a/arch/arm/boot/dts/am4372.dtsi ++++ b/arch/arm/boot/dts/am4372.dtsi +@@ -161,9 +161,6 @@ + ti,hwmods = "mailbox"; + ti,mbox-num-users = <4>; + ti,mbox-num-fifos = <8>; +- ti,mbox-names = "wkup_m3"; +- ti,mbox-data = <0 0 0 0>; +- status = "disabled"; + }; + + timer1: timer@44e31000 { +diff --git a/arch/arm/boot/dts/armada-370-netgear-rn102.dts b/arch/arm/boot/dts/armada-370-netgear-rn102.dts +index 651aeb5..f3188e9 100644 +--- a/arch/arm/boot/dts/armada-370-netgear-rn102.dts ++++ b/arch/arm/boot/dts/armada-370-netgear-rn102.dts +@@ -144,6 +144,10 @@ + marvell,nand-enable-arbiter; + nand-on-flash-bbt; + ++ /* Use Hardware BCH ECC */ ++ nand-ecc-strength = <4>; ++ nand-ecc-step-size = <512>; ++ + partition@0 { + label = "u-boot"; + reg = <0x0000000 0x180000>; /* 1.5MB */ +diff --git a/arch/arm/boot/dts/armada-370-netgear-rn104.dts b/arch/arm/boot/dts/armada-370-netgear-rn104.dts +index 4e27587..da406c1 100644 +--- a/arch/arm/boot/dts/armada-370-netgear-rn104.dts ++++ b/arch/arm/boot/dts/armada-370-netgear-rn104.dts +@@ -146,6 +146,10 @@ + marvell,nand-enable-arbiter; + nand-on-flash-bbt; + ++ /* Use Hardware BCH ECC */ ++ nand-ecc-strength = <4>; ++ nand-ecc-step-size = <512>; ++ + partition@0 { + label = "u-boot"; + reg = <0x0000000 0x180000>; /* 1.5MB */ +diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi +index 0d8530c..34841fc 100644 +--- a/arch/arm/boot/dts/armada-370.dtsi ++++ b/arch/arm/boot/dts/armada-370.dtsi +@@ -106,11 +106,6 @@ + reg = <0x11100 0x20>; + }; + +- system-controller@18200 { +- compatible = "marvell,armada-370-xp-system-controller"; +- reg = <0x18200 0x100>; +- }; +- + pinctrl { + compatible = "marvell,mv88f6710-pinctrl"; + reg = <0x18000 0x38>; +@@ -167,6 +162,11 @@ + interrupts = <91>; + }; + ++ system-controller@18200 { ++ compatible = "marvell,armada-370-xp-system-controller"; ++ reg = <0x18200 0x100>; ++ }; ++ + gateclk: clock-gating-control@18220 { + compatible = "marvell,armada-370-gating-clock"; + reg = <0x18220 0x4>; +diff --git a/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts b/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts +index ff049ee..b4aba09 100644 +--- a/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts ++++ b/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts +@@ -224,6 +224,10 @@ + marvell,nand-enable-arbiter; + nand-on-flash-bbt; + ++ /* Use Hardware BCH ECC */ ++ nand-ecc-strength = <4>; ++ nand-ecc-step-size = <512>; ++ + partition@0 { + label = "u-boot"; + reg = <0x0000000 0x180000>; /* 1.5MB */ +diff --git a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts +index 1c6bd83..2ade357 100644 +--- a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts ++++ b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts +@@ -69,6 +69,10 @@ + }; + + internal-regs { ++ rtc@10300 { ++ /* No crystal connected to the internal RTC */ ++ status = "disabled"; ++ }; + serial@12000 { + clock-frequency = <250000000>; + status = "okay"; +diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi +index fece866..b8f234b 100644 +--- a/arch/arm/boot/dts/at91sam9263.dtsi ++++ b/arch/arm/boot/dts/at91sam9263.dtsi +@@ -535,6 +535,7 @@ + compatible = "atmel,hsmci"; + reg = <0xfff80000 0x600>; + interrupts = <10 IRQ_TYPE_LEVEL_HIGH 0>; ++ pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +@@ -544,6 +545,7 @@ + compatible = "atmel,hsmci"; + reg = <0xfff84000 0x600>; + interrupts = <11 IRQ_TYPE_LEVEL_HIGH 0>; ++ pinctrl-names = "default"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; +diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi +index 187fd46..355117c 100644 +--- a/arch/arm/boot/dts/dove.dtsi ++++ b/arch/arm/boot/dts/dove.dtsi +@@ -154,7 +154,7 @@ + + uart2: serial@12200 { + compatible = "ns16550a"; +- reg = <0x12000 0x100>; ++ reg = <0x12200 0x100>; + reg-shift = <2>; + interrupts = <9>; + clocks = <&core_clk 0>; +@@ -163,7 +163,7 @@ + + uart3: serial@12300 { + compatible = "ns16550a"; +- reg = <0x12100 0x100>; ++ reg = <0x12300 0x100>; + reg-shift = <2>; + interrupts = <10>; + clocks = <&core_clk 0>; +diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts +index 5babba0..9381754 100644 +--- a/arch/arm/boot/dts/dra7-evm.dts ++++ b/arch/arm/boot/dts/dra7-evm.dts +@@ -50,13 +50,13 @@ + + mcspi1_pins: pinmux_mcspi1_pins { + pinctrl-single,pins = < +- 0x3a4 (PIN_INPUT | MUX_MODE0) /* spi2_clk */ +- 0x3a8 (PIN_INPUT | MUX_MODE0) /* spi2_d1 */ +- 0x3ac (PIN_INPUT | MUX_MODE0) /* spi2_d0 */ +- 0x3b0 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs0 */ +- 0x3b4 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs1 */ +- 0x3b8 (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs2 */ +- 0x3bc (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs3 */ ++ 0x3a4 (PIN_INPUT | MUX_MODE0) /* spi1_sclk */ ++ 0x3a8 (PIN_INPUT | MUX_MODE0) /* spi1_d1 */ ++ 0x3ac (PIN_INPUT | MUX_MODE0) /* spi1_d0 */ ++ 0x3b0 (PIN_INPUT_SLEW | MUX_MODE0) /* spi1_cs0 */ ++ 0x3b4 (PIN_INPUT_SLEW | MUX_MODE0) /* spi1_cs1 */ ++ 0x3b8 (PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs2.hdmi1_hpd */ ++ 0x3bc (PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs3.hdmi1_cec */ + >; + }; + +@@ -182,6 +182,7 @@ + regulator-name = "ldo3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; ++ regulator-always-on; + regulator-boot-on; + }; + +diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi +index 1fd75aa..f60aeee 100644 +--- a/arch/arm/boot/dts/dra7.dtsi ++++ b/arch/arm/boot/dts/dra7.dtsi +@@ -178,7 +178,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + gpio2: gpio@48055000 { +@@ -189,7 +189,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + gpio3: gpio@48057000 { +@@ -200,7 +200,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + gpio4: gpio@48059000 { +@@ -211,7 +211,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + gpio5: gpio@4805b000 { +@@ -222,7 +222,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + gpio6: gpio@4805d000 { +@@ -233,7 +233,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + gpio7: gpio@48051000 { +@@ -244,7 +244,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + gpio8: gpio@48053000 { +@@ -255,7 +255,7 @@ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +- #interrupt-cells = <1>; ++ #interrupt-cells = <2>; + }; + + uart1: serial@4806a000 { +@@ -458,7 +458,7 @@ + }; + + wdt2: wdt@4ae14000 { +- compatible = "ti,omap4-wdt"; ++ compatible = "ti,omap3-wdt"; + reg = <0x4ae14000 0x80>; + interrupts = ; + ti,hwmods = "wd_timer2"; +diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/dra7xx-clocks.dtsi +index e96da9a..f2512e1 100644 +--- a/arch/arm/boot/dts/dra7xx-clocks.dtsi ++++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi +@@ -243,10 +243,18 @@ + ti,invert-autoidle-bit; + }; + ++ dpll_core_byp_mux: dpll_core_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ ti,bit-shift = <23>; ++ reg = <0x012c>; ++ }; ++ + dpll_core_ck: dpll_core_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-core-clock"; +- clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ clocks = <&sys_clkin1>, <&dpll_core_byp_mux>; + reg = <0x0120>, <0x0124>, <0x012c>, <0x0128>; + }; + +@@ -309,10 +317,18 @@ + clock-div = <1>; + }; + ++ dpll_dsp_byp_mux: dpll_dsp_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&dsp_dpll_hs_clk_div>; ++ ti,bit-shift = <23>; ++ reg = <0x0240>; ++ }; ++ + dpll_dsp_ck: dpll_dsp_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&dsp_dpll_hs_clk_div>; ++ clocks = <&sys_clkin1>, <&dpll_dsp_byp_mux>; + reg = <0x0234>, <0x0238>, <0x0240>, <0x023c>; + }; + +@@ -335,10 +351,18 @@ + clock-div = <1>; + }; + ++ dpll_iva_byp_mux: dpll_iva_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&iva_dpll_hs_clk_div>; ++ ti,bit-shift = <23>; ++ reg = <0x01ac>; ++ }; ++ + dpll_iva_ck: dpll_iva_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&iva_dpll_hs_clk_div>; ++ clocks = <&sys_clkin1>, <&dpll_iva_byp_mux>; + reg = <0x01a0>, <0x01a4>, <0x01ac>, <0x01a8>; + }; + +@@ -361,10 +385,18 @@ + clock-div = <1>; + }; + ++ dpll_gpu_byp_mux: dpll_gpu_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ ti,bit-shift = <23>; ++ reg = <0x02e4>; ++ }; ++ + dpll_gpu_ck: dpll_gpu_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ clocks = <&sys_clkin1>, <&dpll_gpu_byp_mux>; + reg = <0x02d8>, <0x02dc>, <0x02e4>, <0x02e0>; + }; + +@@ -398,10 +430,18 @@ + clock-div = <1>; + }; + ++ dpll_ddr_byp_mux: dpll_ddr_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ ti,bit-shift = <23>; ++ reg = <0x021c>; ++ }; ++ + dpll_ddr_ck: dpll_ddr_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ clocks = <&sys_clkin1>, <&dpll_ddr_byp_mux>; + reg = <0x0210>, <0x0214>, <0x021c>, <0x0218>; + }; + +@@ -416,10 +456,18 @@ + ti,invert-autoidle-bit; + }; + ++ dpll_gmac_byp_mux: dpll_gmac_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ ti,bit-shift = <23>; ++ reg = <0x02b4>; ++ }; ++ + dpll_gmac_ck: dpll_gmac_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ clocks = <&sys_clkin1>, <&dpll_gmac_byp_mux>; + reg = <0x02a8>, <0x02ac>, <0x02b4>, <0x02b0>; + }; + +@@ -482,10 +530,18 @@ + clock-div = <1>; + }; + ++ dpll_eve_byp_mux: dpll_eve_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&eve_dpll_hs_clk_div>; ++ ti,bit-shift = <23>; ++ reg = <0x0290>; ++ }; ++ + dpll_eve_ck: dpll_eve_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&eve_dpll_hs_clk_div>; ++ clocks = <&sys_clkin1>, <&dpll_eve_byp_mux>; + reg = <0x0284>, <0x0288>, <0x0290>, <0x028c>; + }; + +@@ -1214,10 +1270,18 @@ + clock-div = <1>; + }; + ++ dpll_per_byp_mux: dpll_per_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&per_dpll_hs_clk_div>; ++ ti,bit-shift = <23>; ++ reg = <0x014c>; ++ }; ++ + dpll_per_ck: dpll_per_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&per_dpll_hs_clk_div>; ++ clocks = <&sys_clkin1>, <&dpll_per_byp_mux>; + reg = <0x0140>, <0x0144>, <0x014c>, <0x0148>; + }; + +@@ -1240,10 +1304,18 @@ + clock-div = <1>; + }; + ++ dpll_usb_byp_mux: dpll_usb_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&usb_dpll_hs_clk_div>; ++ ti,bit-shift = <23>; ++ reg = <0x018c>; ++ }; ++ + dpll_usb_ck: dpll_usb_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-j-type-clock"; +- clocks = <&sys_clkin1>, <&usb_dpll_hs_clk_div>; ++ clocks = <&sys_clkin1>, <&dpll_usb_byp_mux>; + reg = <0x0180>, <0x0184>, <0x018c>, <0x0188>; + }; + +diff --git a/arch/arm/boot/dts/hi3620.dtsi b/arch/arm/boot/dts/hi3620.dtsi +index ab1116d..83a5b86 100644 +--- a/arch/arm/boot/dts/hi3620.dtsi ++++ b/arch/arm/boot/dts/hi3620.dtsi +@@ -73,7 +73,7 @@ + + L2: l2-cache { + compatible = "arm,pl310-cache"; +- reg = <0xfc10000 0x100000>; ++ reg = <0x100000 0x100000>; + interrupts = <0 15 4>; + cache-unified; + cache-level = <2>; +diff --git a/arch/arm/boot/dts/imx23-olinuxino.dts b/arch/arm/boot/dts/imx23-olinuxino.dts +index 526bfdb..f8922fb 100644 +--- a/arch/arm/boot/dts/imx23-olinuxino.dts ++++ b/arch/arm/boot/dts/imx23-olinuxino.dts +@@ -12,6 +12,7 @@ + */ + + /dts-v1/; ++#include + #include "imx23.dtsi" + + / { +@@ -93,6 +94,7 @@ + + ahb@80080000 { + usb0: usb@80080000 { ++ dr_mode = "host"; + vbus-supply = <®_usb0_vbus>; + status = "okay"; + }; +@@ -119,7 +121,7 @@ + + user { + label = "green"; +- gpios = <&gpio2 1 1>; ++ gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>; + }; + }; + }; +diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi +index 904416e..3fd539b 100644 +--- a/arch/arm/boot/dts/imx25.dtsi ++++ b/arch/arm/boot/dts/imx25.dtsi +@@ -160,7 +160,7 @@ + #size-cells = <0>; + compatible = "fsl,imx25-cspi", "fsl,imx35-cspi"; + reg = <0x43fa4000 0x4000>; +- clocks = <&clks 62>, <&clks 62>; ++ clocks = <&clks 78>, <&clks 78>; + clock-names = "ipg", "per"; + interrupts = <14>; + status = "disabled"; +@@ -354,7 +354,7 @@ + compatible = "fsl,imx25-pwm", "fsl,imx27-pwm"; + #pwm-cells = <2>; + reg = <0x53fa0000 0x4000>; +- clocks = <&clks 106>, <&clks 36>; ++ clocks = <&clks 106>, <&clks 52>; + clock-names = "ipg", "per"; + interrupts = <36>; + }; +@@ -373,7 +373,7 @@ + compatible = "fsl,imx25-pwm", "fsl,imx27-pwm"; + #pwm-cells = <2>; + reg = <0x53fa8000 0x4000>; +- clocks = <&clks 107>, <&clks 36>; ++ clocks = <&clks 107>, <&clks 52>; + clock-names = "ipg", "per"; + interrupts = <41>; + }; +@@ -413,8 +413,9 @@ + + pwm4: pwm@53fc8000 { + compatible = "fsl,imx25-pwm", "fsl,imx27-pwm"; ++ #pwm-cells = <2>; + reg = <0x53fc8000 0x4000>; +- clocks = <&clks 108>, <&clks 36>; ++ clocks = <&clks 108>, <&clks 52>; + clock-names = "ipg", "per"; + interrupts = <42>; + }; +@@ -460,7 +461,7 @@ + compatible = "fsl,imx25-pwm", "fsl,imx27-pwm"; + #pwm-cells = <2>; + reg = <0x53fe0000 0x4000>; +- clocks = <&clks 105>, <&clks 36>; ++ clocks = <&clks 105>, <&clks 52>; + clock-names = "ipg", "per"; + interrupts = <26>; + }; +diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi +index 3f1f2c8..78be5c2 100644 +--- a/arch/arm/boot/dts/imx27.dtsi ++++ b/arch/arm/boot/dts/imx27.dtsi +@@ -430,7 +430,7 @@ + + fec: ethernet@1002b000 { + compatible = "fsl,imx27-fec"; +- reg = <0x1002b000 0x4000>; ++ reg = <0x1002b000 0x1000>; + interrupts = <50>; + clocks = <&clks 48>, <&clks 67>; + clock-names = "ipg", "ahb"; +diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi +index f34d469..6f776ab 100644 +--- a/arch/arm/boot/dts/imx28.dtsi ++++ b/arch/arm/boot/dts/imx28.dtsi +@@ -803,7 +803,7 @@ + 80 81 68 69 + 70 71 72 73 + 74 75 76 77>; +- interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty", ++ interrupt-names = "auart4-rx", "auart4-tx", "spdif-tx", "empty", + "saif0", "saif1", "i2c0", "i2c1", + "auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx", + "auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx"; +diff --git a/arch/arm/boot/dts/s3c6410-mini6410.dts b/arch/arm/boot/dts/s3c6410-mini6410.dts +index 57e00f9..a25debb 100644 +--- a/arch/arm/boot/dts/s3c6410-mini6410.dts ++++ b/arch/arm/boot/dts/s3c6410-mini6410.dts +@@ -198,10 +198,6 @@ + status = "okay"; + }; + +-&pwm { +- status = "okay"; +-}; +- + &pinctrl0 { + gpio_leds: gpio-leds { + samsung,pins = "gpk-4", "gpk-5", "gpk-6", "gpk-7"; +diff --git a/arch/arm/boot/dts/s3c64xx.dtsi b/arch/arm/boot/dts/s3c64xx.dtsi +index 4e3be4d..4f1eff3 100644 +--- a/arch/arm/boot/dts/s3c64xx.dtsi ++++ b/arch/arm/boot/dts/s3c64xx.dtsi +@@ -168,7 +168,6 @@ + clocks = <&clocks PCLK_PWM>; + samsung,pwm-outputs = <0>, <1>; + #pwm-cells = <3>; +- status = "disabled"; + }; + + pinctrl0: pinctrl@7f008000 { +diff --git a/arch/arm/boot/dts/sama5d3_can.dtsi b/arch/arm/boot/dts/sama5d3_can.dtsi +index a077585..eaf4145 100644 +--- a/arch/arm/boot/dts/sama5d3_can.dtsi ++++ b/arch/arm/boot/dts/sama5d3_can.dtsi +@@ -40,7 +40,7 @@ + atmel,clk-output-range = <0 66000000>; + }; + +- can1_clk: can0_clk { ++ can1_clk: can1_clk { + #clock-cells = <0>; + reg = <41>; + atmel,clk-output-range = <0 66000000>; +diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi +index e0853ea..75e748e 100644 +--- a/arch/arm/boot/dts/ste-dbx5x0.dtsi ++++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi +@@ -985,23 +985,6 @@ + status = "disabled"; + }; + +- vmmci: regulator-gpio { +- compatible = "regulator-gpio"; +- +- regulator-min-microvolt = <1800000>; +- regulator-max-microvolt = <2900000>; +- regulator-name = "mmci-reg"; +- regulator-type = "voltage"; +- +- startup-delay-us = <100>; +- enable-active-high; +- +- states = <1800000 0x1 +- 2900000 0x0>; +- +- status = "disabled"; +- }; +- + mcde@a0350000 { + compatible = "stericsson,mcde"; + reg = <0xa0350000 0x1000>, /* MCDE */ +diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi +index 6cb9b68..0b668f8 100644 +--- a/arch/arm/boot/dts/ste-href.dtsi ++++ b/arch/arm/boot/dts/ste-href.dtsi +@@ -111,6 +111,21 @@ + pinctrl-1 = <&i2c3_sleep_mode>; + }; + ++ vmmci: regulator-gpio { ++ compatible = "regulator-gpio"; ++ ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <2900000>; ++ regulator-name = "mmci-reg"; ++ regulator-type = "voltage"; ++ ++ startup-delay-us = <100>; ++ enable-active-high; ++ ++ states = <1800000 0x1 ++ 2900000 0x0>; ++ }; ++ + // External Micro SD slot + sdi0_per1@80126000 { + arm,primecell-periphid = <0x10480180>; +diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts +index 97d5d21..5deaf3c 100644 +--- a/arch/arm/boot/dts/ste-snowball.dts ++++ b/arch/arm/boot/dts/ste-snowball.dts +@@ -146,8 +146,21 @@ + }; + + vmmci: regulator-gpio { ++ compatible = "regulator-gpio"; ++ + gpios = <&gpio7 4 0x4>; + enable-gpio = <&gpio6 25 0x4>; ++ ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <2900000>; ++ regulator-name = "mmci-reg"; ++ regulator-type = "voltage"; ++ ++ startup-delay-us = <100>; ++ enable-active-high; ++ ++ states = <1800000 0x1 ++ 2900000 0x0>; + }; + + // External Micro SD slot +diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi +index 48d2a7f..ce978bc 100644 +--- a/arch/arm/boot/dts/tegra20.dtsi ++++ b/arch/arm/boot/dts/tegra20.dtsi +@@ -76,9 +76,9 @@ + reset-names = "2d"; + }; + +- gr3d@54140000 { ++ gr3d@54180000 { + compatible = "nvidia,tegra20-gr3d"; +- reg = <0x54140000 0x00040000>; ++ reg = <0x54180000 0x00040000>; + clocks = <&tegra_car TEGRA20_CLK_GR3D>; + resets = <&tegra_car 24>; + reset-names = "3d"; +@@ -138,9 +138,9 @@ + status = "disabled"; + }; + +- dsi@542c0000 { ++ dsi@54300000 { + compatible = "nvidia,tegra20-dsi"; +- reg = <0x542c0000 0x00040000>; ++ reg = <0x54300000 0x00040000>; + clocks = <&tegra_car TEGRA20_CLK_DSI>; + resets = <&tegra_car 48>; + reset-names = "dsi"; +diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig +index ee69829..cf4823b 100644 +--- a/arch/arm/configs/multi_v7_defconfig ++++ b/arch/arm/configs/multi_v7_defconfig +@@ -235,6 +235,7 @@ CONFIG_SND_SOC_TEGRA_MAX98090=y + CONFIG_USB=y + CONFIG_USB_XHCI_HCD=y + CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_EXYNOS=y + CONFIG_USB_EHCI_TEGRA=y + CONFIG_USB_EHCI_HCD_PLATFORM=y + CONFIG_USB_ISP1760_HCD=y +diff --git a/arch/arm/crypto/aes_glue.c b/arch/arm/crypto/aes_glue.c +index 3003fa1..0409b8f 100644 +--- a/arch/arm/crypto/aes_glue.c ++++ b/arch/arm/crypto/aes_glue.c +@@ -93,6 +93,6 @@ module_exit(aes_fini); + + MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm (ASM)"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("aes"); +-MODULE_ALIAS("aes-asm"); ++MODULE_ALIAS_CRYPTO("aes"); ++MODULE_ALIAS_CRYPTO("aes-asm"); + MODULE_AUTHOR("David McCullough "); +diff --git a/arch/arm/crypto/aesbs-core.S_shipped b/arch/arm/crypto/aesbs-core.S_shipped +index 71e5fc7..1d1800f 100644 +--- a/arch/arm/crypto/aesbs-core.S_shipped ++++ b/arch/arm/crypto/aesbs-core.S_shipped +@@ -58,14 +58,18 @@ + # define VFP_ABI_FRAME 0 + # define BSAES_ASM_EXTENDED_KEY + # define XTS_CHAIN_TWEAK +-# define __ARM_ARCH__ 7 ++# define __ARM_ARCH__ __LINUX_ARM_ARCH__ ++# define __ARM_MAX_ARCH__ 7 + #endif + + #ifdef __thumb__ + # define adrl adr + #endif + +-#if __ARM_ARCH__>=7 ++#if __ARM_MAX_ARCH__>=7 ++.arch armv7-a ++.fpu neon ++ + .text + .syntax unified @ ARMv7-capable assembler is expected to handle this + #ifdef __thumb2__ +@@ -74,8 +78,6 @@ + .code 32 + #endif + +-.fpu neon +- + .type _bsaes_decrypt8,%function + .align 4 + _bsaes_decrypt8: +@@ -2095,9 +2097,11 @@ bsaes_xts_decrypt: + vld1.8 {q8}, [r0] @ initial tweak + adr r2, .Lxts_magic + ++#ifndef XTS_CHAIN_TWEAK + tst r9, #0xf @ if not multiple of 16 + it ne @ Thumb2 thing, sanity check in ARM + subne r9, #0x10 @ subtract another 16 bytes ++#endif + subs r9, #0x80 + + blo .Lxts_dec_short +diff --git a/arch/arm/crypto/aesbs-glue.c b/arch/arm/crypto/aesbs-glue.c +index 4522366..15468fb 100644 +--- a/arch/arm/crypto/aesbs-glue.c ++++ b/arch/arm/crypto/aesbs-glue.c +@@ -137,7 +137,7 @@ static int aesbs_cbc_encrypt(struct blkcipher_desc *desc, + dst += AES_BLOCK_SIZE; + } while (--blocks); + } +- err = blkcipher_walk_done(desc, &walk, 0); ++ err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + } + return err; + } +@@ -158,7 +158,7 @@ static int aesbs_cbc_decrypt(struct blkcipher_desc *desc, + bsaes_cbc_encrypt(walk.src.virt.addr, walk.dst.virt.addr, + walk.nbytes, &ctx->dec, walk.iv); + kernel_neon_end(); +- err = blkcipher_walk_done(desc, &walk, 0); ++ err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + } + while (walk.nbytes) { + u32 blocks = walk.nbytes / AES_BLOCK_SIZE; +@@ -182,7 +182,7 @@ static int aesbs_cbc_decrypt(struct blkcipher_desc *desc, + dst += AES_BLOCK_SIZE; + src += AES_BLOCK_SIZE; + } while (--blocks); +- err = blkcipher_walk_done(desc, &walk, 0); ++ err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + } + return err; + } +@@ -268,7 +268,7 @@ static int aesbs_xts_encrypt(struct blkcipher_desc *desc, + bsaes_xts_encrypt(walk.src.virt.addr, walk.dst.virt.addr, + walk.nbytes, &ctx->enc, walk.iv); + kernel_neon_end(); +- err = blkcipher_walk_done(desc, &walk, 0); ++ err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + } + return err; + } +@@ -292,7 +292,7 @@ static int aesbs_xts_decrypt(struct blkcipher_desc *desc, + bsaes_xts_decrypt(walk.src.virt.addr, walk.dst.virt.addr, + walk.nbytes, &ctx->dec, walk.iv); + kernel_neon_end(); +- err = blkcipher_walk_done(desc, &walk, 0); ++ err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE); + } + return err; + } +diff --git a/arch/arm/crypto/bsaes-armv7.pl b/arch/arm/crypto/bsaes-armv7.pl +index be068db..a4d3856 100644 +--- a/arch/arm/crypto/bsaes-armv7.pl ++++ b/arch/arm/crypto/bsaes-armv7.pl +@@ -701,14 +701,18 @@ $code.=<<___; + # define VFP_ABI_FRAME 0 + # define BSAES_ASM_EXTENDED_KEY + # define XTS_CHAIN_TWEAK +-# define __ARM_ARCH__ 7 ++# define __ARM_ARCH__ __LINUX_ARM_ARCH__ ++# define __ARM_MAX_ARCH__ 7 + #endif + + #ifdef __thumb__ + # define adrl adr + #endif + +-#if __ARM_ARCH__>=7 ++#if __ARM_MAX_ARCH__>=7 ++.arch armv7-a ++.fpu neon ++ + .text + .syntax unified @ ARMv7-capable assembler is expected to handle this + #ifdef __thumb2__ +@@ -717,8 +721,6 @@ $code.=<<___; + .code 32 + #endif + +-.fpu neon +- + .type _bsaes_decrypt8,%function + .align 4 + _bsaes_decrypt8: +@@ -2076,9 +2078,11 @@ bsaes_xts_decrypt: + vld1.8 {@XMM[8]}, [r0] @ initial tweak + adr $magic, .Lxts_magic + ++#ifndef XTS_CHAIN_TWEAK + tst $len, #0xf @ if not multiple of 16 + it ne @ Thumb2 thing, sanity check in ARM + subne $len, #0x10 @ subtract another 16 bytes ++#endif + subs $len, #0x80 + + blo .Lxts_dec_short +diff --git a/arch/arm/crypto/sha1_glue.c b/arch/arm/crypto/sha1_glue.c +index 76cd976..ace4cd6 100644 +--- a/arch/arm/crypto/sha1_glue.c ++++ b/arch/arm/crypto/sha1_glue.c +@@ -175,5 +175,5 @@ module_exit(sha1_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm (ARM)"); +-MODULE_ALIAS("sha1"); ++MODULE_ALIAS_CRYPTO("sha1"); + MODULE_AUTHOR("David McCullough "); +diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h +index f4b46d3..051b726 100644 +--- a/arch/arm/include/asm/elf.h ++++ b/arch/arm/include/asm/elf.h +@@ -114,7 +114,7 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs); + the loader. We need to make sure that it is out of the way of the program + that it will "exec", and that there is sufficient room for the brk. */ + +-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) ++#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) + + /* When the program starts, a1 contains a pointer to a function to be + registered with atexit, as per the SVR4 ABI. A value of 0 means we +diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h +index 1d3153c..816db0b 100644 +--- a/arch/arm/include/asm/kvm_arm.h ++++ b/arch/arm/include/asm/kvm_arm.h +@@ -55,6 +55,7 @@ + * The bits we set in HCR: + * TAC: Trap ACTLR + * TSC: Trap SMC ++ * TVM: Trap VM ops (until MMU and caches are on) + * TSW: Trap cache operations by set/way + * TWI: Trap WFI + * TWE: Trap WFE +@@ -68,8 +69,7 @@ + */ + #define HCR_GUEST_MASK (HCR_TSC | HCR_TSW | HCR_TWI | HCR_VM | HCR_BSU_IS | \ + HCR_FB | HCR_TAC | HCR_AMO | HCR_IMO | HCR_FMO | \ +- HCR_TWE | HCR_SWIO | HCR_TIDCP) +-#define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF) ++ HCR_TVM | HCR_TWE | HCR_SWIO | HCR_TIDCP) + + /* System Control Register (SCTLR) bits */ + #define SCTLR_TE (1 << 30) +diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h +index 661da11..53b3c4a 100644 +--- a/arch/arm/include/asm/kvm_asm.h ++++ b/arch/arm/include/asm/kvm_asm.h +@@ -48,7 +48,9 @@ + #define c13_TID_URO 26 /* Thread ID, User R/O */ + #define c13_TID_PRIV 27 /* Thread ID, Privileged */ + #define c14_CNTKCTL 28 /* Timer Control Register (PL1) */ +-#define NR_CP15_REGS 29 /* Number of regs (incl. invalid) */ ++#define c10_AMAIR0 29 /* Auxilary Memory Attribute Indirection Reg0 */ ++#define c10_AMAIR1 30 /* Auxilary Memory Attribute Indirection Reg1 */ ++#define NR_CP15_REGS 31 /* Number of regs (incl. invalid) */ + + #define ARM_EXCEPTION_RESET 0 + #define ARM_EXCEPTION_UNDEFINED 1 +diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h +index 0fa90c9..853e2be 100644 +--- a/arch/arm/include/asm/kvm_emulate.h ++++ b/arch/arm/include/asm/kvm_emulate.h +@@ -33,6 +33,11 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu); + void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr); + void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr); + ++static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) ++{ ++ vcpu->arch.hcr = HCR_GUEST_MASK; ++} ++ + static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu) + { + return 1; +diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h +index 098f7dd..530f56e 100644 +--- a/arch/arm/include/asm/kvm_host.h ++++ b/arch/arm/include/asm/kvm_host.h +@@ -42,7 +42,7 @@ + + struct kvm_vcpu; + u32 *kvm_vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num, u32 mode); +-int kvm_target_cpu(void); ++int __attribute_const__ kvm_target_cpu(void); + int kvm_reset_vcpu(struct kvm_vcpu *vcpu); + void kvm_reset_coprocs(struct kvm_vcpu *vcpu); + +@@ -101,6 +101,12 @@ struct kvm_vcpu_arch { + /* The CPU type we expose to the VM */ + u32 midr; + ++ /* HYP trapping configuration */ ++ u32 hcr; ++ ++ /* Interrupt related fields */ ++ u32 irq_lines; /* IRQ and FIQ levels */ ++ + /* Exception Information */ + struct kvm_vcpu_fault_info fault; + +@@ -128,9 +134,6 @@ struct kvm_vcpu_arch { + /* IO related fields */ + struct kvm_decode mmio_decode; + +- /* Interrupt related fields */ +- u32 irq_lines; /* IRQ and FIQ levels */ +- + /* Cache some mmu pages needed inside spinlock regions */ + struct kvm_mmu_memory_cache mmu_page_cache; + +diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h +index 2d122ad..7d35af3 100644 +--- a/arch/arm/include/asm/kvm_mmu.h ++++ b/arch/arm/include/asm/kvm_mmu.h +@@ -47,6 +47,7 @@ int create_hyp_io_mappings(void *from, void *to, phys_addr_t); + void free_boot_hyp_pgd(void); + void free_hyp_pgds(void); + ++void stage2_unmap_vm(struct kvm *kvm); + int kvm_alloc_stage2_pgd(struct kvm *kvm); + void kvm_free_stage2_pgd(struct kvm *kvm); + int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, +@@ -78,17 +79,6 @@ static inline void kvm_set_pte(pte_t *pte, pte_t new_pte) + flush_pmd_entry(pte); + } + +-static inline bool kvm_is_write_fault(unsigned long hsr) +-{ +- unsigned long hsr_ec = hsr >> HSR_EC_SHIFT; +- if (hsr_ec == HSR_EC_IABT) +- return false; +- else if ((hsr & HSR_ISV) && !(hsr & HSR_WNR)) +- return false; +- else +- return true; +-} +- + static inline void kvm_clean_pgd(pgd_t *pgd) + { + clean_dcache_area(pgd, PTRS_PER_S2_PGD * sizeof(pgd_t)); +@@ -114,11 +104,47 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd) + pmd_val(*pmd) |= L_PMD_S2_RDWR; + } + ++/* Open coded p*d_addr_end that can deal with 64bit addresses */ ++#define kvm_pgd_addr_end(addr, end) \ ++({ u64 __boundary = ((addr) + PGDIR_SIZE) & PGDIR_MASK; \ ++ (__boundary - 1 < (end) - 1)? __boundary: (end); \ ++}) ++ ++#define kvm_pud_addr_end(addr,end) (end) ++ ++#define kvm_pmd_addr_end(addr, end) \ ++({ u64 __boundary = ((addr) + PMD_SIZE) & PMD_MASK; \ ++ (__boundary - 1 < (end) - 1)? __boundary: (end); \ ++}) ++ ++#define kvm_pgd_index(addr) pgd_index(addr) ++ ++static inline bool kvm_page_empty(void *ptr) ++{ ++ struct page *ptr_page = virt_to_page(ptr); ++ return page_count(ptr_page) == 1; ++} ++ ++#define kvm_pte_table_empty(ptep) kvm_page_empty(ptep) ++#define kvm_pmd_table_empty(pmdp) kvm_page_empty(pmdp) ++#define kvm_pud_table_empty(pudp) (0) ++ ++ + struct kvm; + +-static inline void coherent_icache_guest_page(struct kvm *kvm, hva_t hva, +- unsigned long size) ++#define kvm_flush_dcache_to_poc(a,l) __cpuc_flush_dcache_area((a), (l)) ++ ++static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu) ++{ ++ return (vcpu->arch.cp15[c1_SCTLR] & 0b101) == 0b101; ++} ++ ++static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva, ++ unsigned long size) + { ++ if (!vcpu_has_cache_enabled(vcpu)) ++ kvm_flush_dcache_to_poc((void *)hva, size); ++ + /* + * If we are going to insert an instruction page and the icache is + * either VIPT or PIPT, there is a potential problem where the host +@@ -139,9 +165,10 @@ static inline void coherent_icache_guest_page(struct kvm *kvm, hva_t hva, + } + } + +-#define kvm_flush_dcache_to_poc(a,l) __cpuc_flush_dcache_area((a), (l)) + #define kvm_virt_to_phys(x) virt_to_idmap((unsigned long)(x)) + ++void stage2_flush_vm(struct kvm *kvm); ++ + #endif /* !__ASSEMBLY__ */ + + #endif /* __ARM_KVM_MMU_H__ */ +diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h +index 626989f..9fd61c7 100644 +--- a/arch/arm/include/asm/pgtable-3level-hwdef.h ++++ b/arch/arm/include/asm/pgtable-3level-hwdef.h +@@ -43,7 +43,7 @@ + #define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) + #define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) + #define PMD_SECT_USER (_AT(pmdval_t, 1) << 6) /* AP[1] */ +-#define PMD_SECT_RDONLY (_AT(pmdval_t, 1) << 7) /* AP[2] */ ++#define PMD_SECT_AP2 (_AT(pmdval_t, 1) << 7) /* read only */ + #define PMD_SECT_S (_AT(pmdval_t, 3) << 8) + #define PMD_SECT_AF (_AT(pmdval_t, 1) << 10) + #define PMD_SECT_nG (_AT(pmdval_t, 1) << 11) +@@ -72,6 +72,7 @@ + #define PTE_TABLE_BIT (_AT(pteval_t, 1) << 1) + #define PTE_BUFFERABLE (_AT(pteval_t, 1) << 2) /* AttrIndx[0] */ + #define PTE_CACHEABLE (_AT(pteval_t, 1) << 3) /* AttrIndx[1] */ ++#define PTE_AP2 (_AT(pteval_t, 1) << 7) /* AP[2] */ + #define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ + #define PTE_EXT_AF (_AT(pteval_t, 1) << 10) /* Access Flag */ + #define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* nG */ +diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h +index 85c60ad..06e0bc0 100644 +--- a/arch/arm/include/asm/pgtable-3level.h ++++ b/arch/arm/include/asm/pgtable-3level.h +@@ -79,18 +79,19 @@ + #define L_PTE_PRESENT (_AT(pteval_t, 3) << 0) /* Present */ + #define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */ + #define L_PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */ +-#define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) /* AP[2] */ + #define L_PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ + #define L_PTE_YOUNG (_AT(pteval_t, 1) << 10) /* AF */ + #define L_PTE_XN (_AT(pteval_t, 1) << 54) /* XN */ +-#define L_PTE_DIRTY (_AT(pteval_t, 1) << 55) /* unused */ +-#define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) /* unused */ ++#define L_PTE_DIRTY (_AT(pteval_t, 1) << 55) ++#define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) + #define L_PTE_NONE (_AT(pteval_t, 1) << 57) /* PROT_NONE */ ++#define L_PTE_RDONLY (_AT(pteval_t, 1) << 58) /* READ ONLY */ + +-#define PMD_SECT_VALID (_AT(pmdval_t, 1) << 0) +-#define PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55) +-#define PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 56) +-#define PMD_SECT_NONE (_AT(pmdval_t, 1) << 57) ++#define L_PMD_SECT_VALID (_AT(pmdval_t, 1) << 0) ++#define L_PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55) ++#define L_PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 56) ++#define L_PMD_SECT_NONE (_AT(pmdval_t, 1) << 57) ++#define L_PMD_SECT_RDONLY (_AT(pteval_t, 1) << 58) + + /* + * To be used in assembly code with the upper page attributes. +@@ -207,27 +208,32 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) + #define pte_huge(pte) (pte_val(pte) && !(pte_val(pte) & PTE_TABLE_BIT)) + #define pte_mkhuge(pte) (__pte(pte_val(pte) & ~PTE_TABLE_BIT)) + +-#define pmd_young(pmd) (pmd_val(pmd) & PMD_SECT_AF) ++#define pmd_isset(pmd, val) ((u32)(val) == (val) ? pmd_val(pmd) & (val) \ ++ : !!(pmd_val(pmd) & (val))) ++#define pmd_isclear(pmd, val) (!(pmd_val(pmd) & (val))) ++ ++#define pmd_young(pmd) (pmd_isset((pmd), PMD_SECT_AF)) + + #define __HAVE_ARCH_PMD_WRITE +-#define pmd_write(pmd) (!(pmd_val(pmd) & PMD_SECT_RDONLY)) ++#define pmd_write(pmd) (pmd_isclear((pmd), L_PMD_SECT_RDONLY)) ++#define pmd_dirty(pmd) (pmd_isset((pmd), L_PMD_SECT_DIRTY)) + + #define pmd_hugewillfault(pmd) (!pmd_young(pmd) || !pmd_write(pmd)) + #define pmd_thp_or_huge(pmd) (pmd_huge(pmd) || pmd_trans_huge(pmd)) + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE +-#define pmd_trans_huge(pmd) (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT)) +-#define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING) ++#define pmd_trans_huge(pmd) (pmd_val(pmd) && !pmd_table(pmd)) ++#define pmd_trans_splitting(pmd) (pmd_isset((pmd), L_PMD_SECT_SPLITTING)) + #endif + + #define PMD_BIT_FUNC(fn,op) \ + static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; } + +-PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY); ++PMD_BIT_FUNC(wrprotect, |= L_PMD_SECT_RDONLY); + PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF); +-PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING); +-PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY); +-PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY); ++PMD_BIT_FUNC(mksplitting, |= L_PMD_SECT_SPLITTING); ++PMD_BIT_FUNC(mkwrite, &= ~L_PMD_SECT_RDONLY); ++PMD_BIT_FUNC(mkdirty, |= L_PMD_SECT_DIRTY); + PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF); + + #define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT)) +@@ -241,8 +247,8 @@ PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF); + + static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) + { +- const pmdval_t mask = PMD_SECT_USER | PMD_SECT_XN | PMD_SECT_RDONLY | +- PMD_SECT_VALID | PMD_SECT_NONE; ++ const pmdval_t mask = PMD_SECT_USER | PMD_SECT_XN | L_PMD_SECT_RDONLY | ++ L_PMD_SECT_VALID | L_PMD_SECT_NONE; + pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask); + return pmd; + } +@@ -253,8 +259,13 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, + BUG_ON(addr >= TASK_SIZE); + + /* create a faulting entry if PROT_NONE protected */ +- if (pmd_val(pmd) & PMD_SECT_NONE) +- pmd_val(pmd) &= ~PMD_SECT_VALID; ++ if (pmd_val(pmd) & L_PMD_SECT_NONE) ++ pmd_val(pmd) &= ~L_PMD_SECT_VALID; ++ ++ if (pmd_write(pmd) && pmd_dirty(pmd)) ++ pmd_val(pmd) &= ~PMD_SECT_AP2; ++ else ++ pmd_val(pmd) |= PMD_SECT_AP2; + + *pmdp = __pmd(pmd_val(pmd) | PMD_SECT_nG); + flush_pmd_entry(pmdp); +diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h +index 7d59b52..89dba13 100644 +--- a/arch/arm/include/asm/pgtable.h ++++ b/arch/arm/include/asm/pgtable.h +@@ -214,12 +214,16 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) + + #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) + ++#define pte_isset(pte, val) ((u32)(val) == (val) ? pte_val(pte) & (val) \ ++ : !!(pte_val(pte) & (val))) ++#define pte_isclear(pte, val) (!(pte_val(pte) & (val))) ++ + #define pte_none(pte) (!pte_val(pte)) +-#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) +-#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY)) +-#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) +-#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) +-#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) ++#define pte_present(pte) (pte_isset((pte), L_PTE_PRESENT)) ++#define pte_write(pte) (pte_isclear((pte), L_PTE_RDONLY)) ++#define pte_dirty(pte) (pte_isset((pte), L_PTE_DIRTY)) ++#define pte_young(pte) (pte_isset((pte), L_PTE_YOUNG)) ++#define pte_exec(pte) (pte_isclear((pte), L_PTE_XN)) + #define pte_special(pte) (0) + + #define pte_present_user(pte) (pte_present(pte) && (pte_val(pte) & L_PTE_USER)) +diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h +index 22a3b9b..4157aec 100644 +--- a/arch/arm/include/asm/smp.h ++++ b/arch/arm/include/asm/smp.h +@@ -74,6 +74,7 @@ struct secondary_data { + }; + extern struct secondary_data secondary_data; + extern volatile int pen_release; ++extern void secondary_startup(void); + + extern int __cpu_disable(void); + +diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h +index 71a06b2..3e635ee 100644 +--- a/arch/arm/include/asm/thread_info.h ++++ b/arch/arm/include/asm/thread_info.h +@@ -43,16 +43,6 @@ struct cpu_context_save { + __u32 extra[2]; /* Xscale 'acc' register, etc */ + }; + +-struct arm_restart_block { +- union { +- /* For user cache flushing */ +- struct { +- unsigned long start; +- unsigned long end; +- } cache; +- }; +-}; +- + /* + * low level task data that entry.S needs immediate access to. + * __switch_to() assumes cpu_context follows immediately after cpu_domain. +@@ -78,7 +68,6 @@ struct thread_info { + unsigned long thumbee_state; /* ThumbEE Handler Base register */ + #endif + struct restart_block restart_block; +- struct arm_restart_block arm_restart_block; + }; + + #define INIT_THREAD_INFO(tsk) \ +diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h +index 83259b8..5f833f7 100644 +--- a/arch/arm/include/asm/tls.h ++++ b/arch/arm/include/asm/tls.h +@@ -1,6 +1,9 @@ + #ifndef __ASMARM_TLS_H + #define __ASMARM_TLS_H + ++#include ++#include ++ + #ifdef __ASSEMBLY__ + #include + .macro switch_tls_none, base, tp, tpuser, tmp1, tmp2 +@@ -50,6 +53,49 @@ + #endif + + #ifndef __ASSEMBLY__ ++ ++static inline void set_tls(unsigned long val) ++{ ++ struct thread_info *thread; ++ ++ thread = current_thread_info(); ++ ++ thread->tp_value[0] = val; ++ ++ /* ++ * This code runs with preemption enabled and therefore must ++ * be reentrant with respect to switch_tls. ++ * ++ * We need to ensure ordering between the shadow state and the ++ * hardware state, so that we don't corrupt the hardware state ++ * with a stale shadow state during context switch. ++ * ++ * If we're preempted here, switch_tls will load TPIDRURO from ++ * thread_info upon resuming execution and the following mcr ++ * is merely redundant. ++ */ ++ barrier(); ++ ++ if (!tls_emu) { ++ if (has_tls_reg) { ++ asm("mcr p15, 0, %0, c13, c0, 3" ++ : : "r" (val)); ++ } else { ++#ifdef CONFIG_KUSER_HELPERS ++ /* ++ * User space must never try to access this ++ * directly. Expect your app to break ++ * eventually if you do so. The user helper ++ * at 0xffff0fe0 must be used instead. (see ++ * entry-armv.S for details) ++ */ ++ *((unsigned int *)0xffff0ff0) = val; ++#endif ++ } ++ ++ } ++} ++ + static inline unsigned long get_tpuser(void) + { + unsigned long reg = 0; +@@ -59,5 +105,23 @@ static inline unsigned long get_tpuser(void) + + return reg; + } ++ ++static inline void set_tpuser(unsigned long val) ++{ ++ /* Since TPIDRURW is fully context-switched (unlike TPIDRURO), ++ * we need not update thread_info. ++ */ ++ if (has_tls_reg && !tls_emu) { ++ asm("mcr p15, 0, %0, c13, c0, 2" ++ : : "r" (val)); ++ } ++} ++ ++static inline void flush_tls(void) ++{ ++ set_tls(0); ++ set_tpuser(0); ++} ++ + #endif + #endif /* __ASMARM_TLS_H */ +diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h +index 4387624..21ca0ce 100644 +--- a/arch/arm/include/asm/unistd.h ++++ b/arch/arm/include/asm/unistd.h +@@ -15,7 +15,17 @@ + + #include + ++/* ++ * This may need to be greater than __NR_last_syscall+1 in order to ++ * account for the padding in the syscall table ++ */ + #define __NR_syscalls (384) ++ ++/* ++ * *NOTE*: This is a ghost syscall private to the kernel. Only the ++ * __kuser_cmpxchg code in entry-armv.S should be aware of its ++ * existence. Don't ever use this from user code. ++ */ + #define __ARM_NR_cmpxchg (__ARM_NR_BASE+0x00fff0) + + #define __ARCH_WANT_STAT64 +diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h +index fb5584d..c377633 100644 +--- a/arch/arm/include/uapi/asm/unistd.h ++++ b/arch/arm/include/uapi/asm/unistd.h +@@ -410,11 +410,6 @@ + #define __NR_sched_getattr (__NR_SYSCALL_BASE+381) + + /* +- * This may need to be greater than __NR_last_syscall+1 in order to +- * account for the padding in the syscall table +- */ +- +-/* + * The following SWIs are ARM private. + */ + #define __ARM_NR_BASE (__NR_SYSCALL_BASE+0x0f0000) +@@ -425,12 +420,6 @@ + #define __ARM_NR_set_tls (__ARM_NR_BASE+5) + + /* +- * *NOTE*: This is a ghost syscall private to the kernel. Only the +- * __kuser_cmpxchg code in entry-armv.S should be aware of its +- * existence. Don't ever use this from user code. +- */ +- +-/* + * The following syscalls are obsolete and no longer available for EABI. + */ + #if !defined(__KERNEL__) +diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c +index ded0417..85598b5 100644 +--- a/arch/arm/kernel/asm-offsets.c ++++ b/arch/arm/kernel/asm-offsets.c +@@ -174,6 +174,7 @@ int main(void) + DEFINE(VCPU_FIQ_REGS, offsetof(struct kvm_vcpu, arch.regs.fiq_regs)); + DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_pc)); + DEFINE(VCPU_CPSR, offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_cpsr)); ++ DEFINE(VCPU_HCR, offsetof(struct kvm_vcpu, arch.hcr)); + DEFINE(VCPU_IRQ_LINES, offsetof(struct kvm_vcpu, arch.irq_lines)); + DEFINE(VCPU_HSR, offsetof(struct kvm_vcpu, arch.fault.hsr)); + DEFINE(VCPU_HxFAR, offsetof(struct kvm_vcpu, arch.fault.hxfar)); +diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S +index a2dcafd..98dd389 100644 +--- a/arch/arm/kernel/entry-common.S ++++ b/arch/arm/kernel/entry-common.S +@@ -32,7 +32,9 @@ ret_fast_syscall: + UNWIND(.fnstart ) + UNWIND(.cantunwind ) + disable_irq @ disable interrupts +- ldr r1, [tsk, #TI_FLAGS] ++ ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing ++ tst r1, #_TIF_SYSCALL_WORK ++ bne __sys_trace_return + tst r1, #_TIF_WORK_MASK + bne fast_work_pending + asm_trace_hardirqs_on +diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S +index 797b1a6..7e666cf 100644 +--- a/arch/arm/kernel/hyp-stub.S ++++ b/arch/arm/kernel/hyp-stub.S +@@ -134,9 +134,7 @@ ENTRY(__hyp_stub_install_secondary) + mcr p15, 4, r7, c1, c1, 3 @ HSTR + + THUMB( orr r7, #(1 << 30) ) @ HSCTLR.TE +-#ifdef CONFIG_CPU_BIG_ENDIAN +- orr r7, #(1 << 9) @ HSCTLR.EE +-#endif ++ARM_BE8(orr r7, r7, #(1 << 25)) @ HSCTLR.EE + mcr p15, 4, r7, c1, c0, 0 @ HSCTLR + + mrc p15, 4, r7, c1, c1, 1 @ HDCR +diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c +index 9723d17..1e782bd 100644 +--- a/arch/arm/kernel/irq.c ++++ b/arch/arm/kernel/irq.c +@@ -163,7 +163,7 @@ static bool migrate_one_irq(struct irq_desc *desc) + c = irq_data_get_irq_chip(d); + if (!c->irq_set_affinity) + pr_debug("IRQ%u: unable to set affinity\n", d->irq); +- else if (c->irq_set_affinity(d, affinity, true) == IRQ_SET_MASK_OK && ret) ++ else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret) + cpumask_copy(d->affinity, affinity); + + return ret; +diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c +index 18a7628..380c20f 100644 +--- a/arch/arm/kernel/kprobes-common.c ++++ b/arch/arm/kernel/kprobes-common.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + #include "kprobes.h" + +@@ -305,7 +306,8 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) + + if (handler) { + /* We can emulate the instruction in (possibly) modified form */ +- asi->insn[0] = (insn & 0xfff00000) | (rn << 16) | reglist; ++ asi->insn[0] = __opcode_to_mem_arm((insn & 0xfff00000) | ++ (rn << 16) | reglist); + asi->insn_handler = handler; + return INSN_GOOD; + } +@@ -334,13 +336,14 @@ prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, + #ifdef CONFIG_THUMB2_KERNEL + if (thumb) { + u16 *thumb_insn = (u16 *)asi->insn; +- thumb_insn[1] = 0x4770; /* Thumb bx lr */ +- thumb_insn[2] = 0x4770; /* Thumb bx lr */ ++ /* Thumb bx lr */ ++ thumb_insn[1] = __opcode_to_mem_thumb16(0x4770); ++ thumb_insn[2] = __opcode_to_mem_thumb16(0x4770); + return insn; + } +- asi->insn[1] = 0xe12fff1e; /* ARM bx lr */ ++ asi->insn[1] = __opcode_to_mem_arm(0xe12fff1e); /* ARM bx lr */ + #else +- asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */ ++ asi->insn[1] = __opcode_to_mem_arm(0xe1a0f00e); /* mov pc, lr */ + #endif + /* Make an ARM instruction unconditional */ + if (insn < 0xe0000000) +@@ -360,12 +363,12 @@ set_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, + if (thumb) { + u16 *ip = (u16 *)asi->insn; + if (is_wide_instruction(insn)) +- *ip++ = insn >> 16; +- *ip++ = insn; ++ *ip++ = __opcode_to_mem_thumb16(insn >> 16); ++ *ip++ = __opcode_to_mem_thumb16(insn); + return; + } + #endif +- asi->insn[0] = insn; ++ asi->insn[0] = __opcode_to_mem_arm(insn); + } + + /* +diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c +index 6123daf..241222c 100644 +--- a/arch/arm/kernel/kprobes-thumb.c ++++ b/arch/arm/kernel/kprobes-thumb.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + #include "kprobes.h" + +@@ -163,9 +164,9 @@ t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) + enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi); + + /* Fixup modified instruction to have halfwords in correct order...*/ +- insn = asi->insn[0]; +- ((u16 *)asi->insn)[0] = insn >> 16; +- ((u16 *)asi->insn)[1] = insn & 0xffff; ++ insn = __mem_to_opcode_arm(asi->insn[0]); ++ ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn >> 16); ++ ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0xffff); + + return ret; + } +@@ -1153,7 +1154,7 @@ t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi) + { + insn &= ~0x00ff; + insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */ +- ((u16 *)asi->insn)[0] = insn; ++ ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn); + asi->insn_handler = t16_emulate_hiregs; + return INSN_GOOD; + } +@@ -1182,8 +1183,10 @@ t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi) + * and call it with R9=SP and LR in the register list represented + * by R8. + */ +- ((u16 *)asi->insn)[0] = 0xe929; /* 1st half STMDB R9!,{} */ +- ((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */ ++ /* 1st half STMDB R9!,{} */ ++ ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe929); ++ /* 2nd half (register list) */ ++ ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff); + asi->insn_handler = t16_emulate_push; + return INSN_GOOD; + } +@@ -1232,8 +1235,10 @@ t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi) + * and call it with R9=SP and PC in the register list represented + * by R8. + */ +- ((u16 *)asi->insn)[0] = 0xe8b9; /* 1st half LDMIA R9!,{} */ +- ((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */ ++ /* 1st half LDMIA R9!,{} */ ++ ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe8b9); ++ /* 2nd half (register list) */ ++ ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff); + asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc + : t16_emulate_pop_nopc; + return INSN_GOOD; +diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c +index a7b621e..49a87b6 100644 +--- a/arch/arm/kernel/kprobes.c ++++ b/arch/arm/kernel/kprobes.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + + #include "kprobes.h" +@@ -62,10 +63,10 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) + #ifdef CONFIG_THUMB2_KERNEL + thumb = true; + addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */ +- insn = ((u16 *)addr)[0]; ++ insn = __mem_to_opcode_thumb16(((u16 *)addr)[0]); + if (is_wide_instruction(insn)) { +- insn <<= 16; +- insn |= ((u16 *)addr)[1]; ++ u16 inst2 = __mem_to_opcode_thumb16(((u16 *)addr)[1]); ++ insn = __opcode_thumb32_compose(insn, inst2); + decode_insn = thumb32_kprobe_decode_insn; + } else + decode_insn = thumb16_kprobe_decode_insn; +@@ -73,7 +74,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) + thumb = false; + if (addr & 0x3) + return -EINVAL; +- insn = *p->addr; ++ insn = __mem_to_opcode_arm(*p->addr); + decode_insn = arm_kprobe_decode_insn; + #endif + +diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c +index 1bdd78b..dd6553b 100644 +--- a/arch/arm/kernel/process.c ++++ b/arch/arm/kernel/process.c +@@ -336,6 +336,8 @@ void flush_thread(void) + memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); + memset(&thread->fpstate, 0, sizeof(union fp_state)); + ++ flush_tls(); ++ + thread_notify(THREAD_NOTIFY_FLUSH, thread); + } + +diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c +index 4a5e943..a4ef472 100644 +--- a/arch/arm/kernel/setup.c ++++ b/arch/arm/kernel/setup.c +@@ -1034,6 +1034,15 @@ static int c_show(struct seq_file *m, void *v) + seq_printf(m, "model name\t: %s rev %d (%s)\n", + cpu_name, cpuid & 15, elf_platform); + ++#if defined(CONFIG_SMP) ++ seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", ++ per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ), ++ (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100); ++#else ++ seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", ++ loops_per_jiffy / (500000/HZ), ++ (loops_per_jiffy / (5000/HZ)) % 100); ++#endif + /* dump out the processor features */ + seq_puts(m, "Features\t: "); + +diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c +index b7b4c86..8cd3724 100644 +--- a/arch/arm/kernel/smp.c ++++ b/arch/arm/kernel/smp.c +@@ -388,8 +388,17 @@ asmlinkage void secondary_start_kernel(void) + + void __init smp_cpus_done(unsigned int max_cpus) + { +- printk(KERN_INFO "SMP: Total of %d processors activated.\n", +- num_online_cpus()); ++ int cpu; ++ unsigned long bogosum = 0; ++ ++ for_each_online_cpu(cpu) ++ bogosum += per_cpu(cpu_data, cpu).loops_per_jiffy; ++ ++ printk(KERN_INFO "SMP: Total of %d processors activated " ++ "(%lu.%02lu BogoMIPS).\n", ++ num_online_cpus(), ++ bogosum / (500000/HZ), ++ (bogosum / (5000/HZ)) % 100); + + hyp_mode_check(); + } +diff --git a/arch/arm/kernel/thumbee.c b/arch/arm/kernel/thumbee.c +index 7b8403b..80f0d69 100644 +--- a/arch/arm/kernel/thumbee.c ++++ b/arch/arm/kernel/thumbee.c +@@ -45,7 +45,7 @@ static int thumbee_notifier(struct notifier_block *self, unsigned long cmd, void + + switch (cmd) { + case THREAD_NOTIFY_FLUSH: +- thread->thumbee_state = 0; ++ teehbr_write(0); + break; + case THREAD_NOTIFY_SWITCH: + current_thread_info()->thumbee_state = teehbr_read(); +diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c +index 172ee18..3f31443 100644 +--- a/arch/arm/kernel/traps.c ++++ b/arch/arm/kernel/traps.c +@@ -510,8 +510,6 @@ static int bad_syscall(int n, struct pt_regs *regs) + return regs->ARM_r0; + } + +-static long do_cache_op_restart(struct restart_block *); +- + static inline int + __do_cache_op(unsigned long start, unsigned long end) + { +@@ -520,24 +518,8 @@ __do_cache_op(unsigned long start, unsigned long end) + do { + unsigned long chunk = min(PAGE_SIZE, end - start); + +- if (signal_pending(current)) { +- struct thread_info *ti = current_thread_info(); +- +- ti->restart_block = (struct restart_block) { +- .fn = do_cache_op_restart, +- }; +- +- ti->arm_restart_block = (struct arm_restart_block) { +- { +- .cache = { +- .start = start, +- .end = end, +- }, +- }, +- }; +- +- return -ERESTART_RESTARTBLOCK; +- } ++ if (fatal_signal_pending(current)) ++ return 0; + + ret = flush_cache_user_range(start, start + chunk); + if (ret) +@@ -550,15 +532,6 @@ __do_cache_op(unsigned long start, unsigned long end) + return 0; + } + +-static long do_cache_op_restart(struct restart_block *unused) +-{ +- struct arm_restart_block *restart_block; +- +- restart_block = ¤t_thread_info()->arm_restart_block; +- return __do_cache_op(restart_block->cache.start, +- restart_block->cache.end); +-} +- + static inline int + do_cache_op(unsigned long start, unsigned long end, int flags) + { +@@ -578,7 +551,6 @@ do_cache_op(unsigned long start, unsigned long end, int flags) + #define NR(x) ((__ARM_NR_##x) - __ARM_NR_BASE) + asmlinkage int arm_syscall(int no, struct pt_regs *regs) + { +- struct thread_info *thread = current_thread_info(); + siginfo_t info; + + if ((no >> 16) != (__ARM_NR_BASE>> 16)) +@@ -629,21 +601,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) + return regs->ARM_r0; + + case NR(set_tls): +- thread->tp_value[0] = regs->ARM_r0; +- if (tls_emu) +- return 0; +- if (has_tls_reg) { +- asm ("mcr p15, 0, %0, c13, c0, 3" +- : : "r" (regs->ARM_r0)); +- } else { +- /* +- * User space must never try to access this directly. +- * Expect your app to break eventually if you do so. +- * The user helper at 0xffff0fe0 must be used instead. +- * (see entry-armv.S for details) +- */ +- *((unsigned int *)0xffff0ff0) = regs->ARM_r0; +- } ++ set_tls(regs->ARM_r0); + return 0; + + #ifdef CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG +diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c +index bd18bb8..f6a52a2 100644 +--- a/arch/arm/kvm/arm.c ++++ b/arch/arm/kvm/arm.c +@@ -82,7 +82,7 @@ struct kvm_vcpu *kvm_arm_get_running_vcpu(void) + /** + * kvm_arm_get_running_vcpus - get the per-CPU array of currently running vcpus. + */ +-struct kvm_vcpu __percpu **kvm_get_running_vcpus(void) ++struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void) + { + return &kvm_arm_running_vcpu; + } +@@ -155,16 +155,6 @@ int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf) + return VM_FAULT_SIGBUS; + } + +-void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free, +- struct kvm_memory_slot *dont) +-{ +-} +- +-int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, +- unsigned long npages) +-{ +- return 0; +-} + + /** + * kvm_arch_destroy_vm - destroy the VM data structure +@@ -224,39 +214,17 @@ long kvm_arch_dev_ioctl(struct file *filp, + return -EINVAL; + } + +-void kvm_arch_memslots_updated(struct kvm *kvm) +-{ +-} +- +-int kvm_arch_prepare_memory_region(struct kvm *kvm, +- struct kvm_memory_slot *memslot, +- struct kvm_userspace_memory_region *mem, +- enum kvm_mr_change change) +-{ +- return 0; +-} +- +-void kvm_arch_commit_memory_region(struct kvm *kvm, +- struct kvm_userspace_memory_region *mem, +- const struct kvm_memory_slot *old, +- enum kvm_mr_change change) +-{ +-} +- +-void kvm_arch_flush_shadow_all(struct kvm *kvm) +-{ +-} +- +-void kvm_arch_flush_shadow_memslot(struct kvm *kvm, +- struct kvm_memory_slot *slot) +-{ +-} + + struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) + { + int err; + struct kvm_vcpu *vcpu; + ++ if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) { ++ err = -EBUSY; ++ goto out; ++ } ++ + vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); + if (!vcpu) { + err = -ENOMEM; +@@ -464,15 +432,16 @@ static void update_vttbr(struct kvm *kvm) + + /* update vttbr to be used with the new vmid */ + pgd_phys = virt_to_phys(kvm->arch.pgd); ++ BUG_ON(pgd_phys & ~VTTBR_BADDR_MASK); + vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK; +- kvm->arch.vttbr = pgd_phys & VTTBR_BADDR_MASK; +- kvm->arch.vttbr |= vmid; ++ kvm->arch.vttbr = pgd_phys | vmid; + + spin_unlock(&kvm_vmid_lock); + } + + static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) + { ++ struct kvm *kvm = vcpu->kvm; + int ret; + + if (likely(vcpu->arch.has_run_once)) +@@ -484,12 +453,20 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) + * Initialize the VGIC before running a vcpu the first time on + * this VM. + */ +- if (unlikely(!vgic_initialized(vcpu->kvm))) { +- ret = kvm_vgic_init(vcpu->kvm); ++ if (unlikely(!vgic_initialized(kvm))) { ++ ret = kvm_vgic_init(kvm); + if (ret) + return ret; + } + ++ /* ++ * Enable the arch timers only if we have an in-kernel VGIC ++ * and it has been properly initialized, since we cannot handle ++ * interrupts from the virtual timer with a userspace gic. ++ */ ++ if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) ++ kvm_timer_enable(kvm); ++ + return 0; + } + +@@ -713,10 +690,21 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu, + return ret; + + /* ++ * Ensure a rebooted VM will fault in RAM pages and detect if the ++ * guest MMU is turned off and flush the caches as needed. ++ */ ++ if (vcpu->arch.has_run_once) ++ stage2_unmap_vm(vcpu->kvm); ++ ++ vcpu_reset_hcr(vcpu); ++ ++ /* + * Handle the "start in power-off" case by marking the VCPU as paused. + */ +- if (__test_and_clear_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features)) ++ if (test_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features)) + vcpu->arch.pause = true; ++ else ++ vcpu->arch.pause = false; + + return 0; + } +@@ -862,7 +850,8 @@ static int hyp_init_cpu_notify(struct notifier_block *self, + switch (action) { + case CPU_STARTING: + case CPU_STARTING_FROZEN: +- cpu_init_hyp_mode(NULL); ++ if (__hyp_get_vectors() == hyp_default_vectors) ++ cpu_init_hyp_mode(NULL); + break; + } + +diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c +index 78c0885..7c73290 100644 +--- a/arch/arm/kvm/coproc.c ++++ b/arch/arm/kvm/coproc.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -205,6 +206,44 @@ done: + } + + /* ++ * Generic accessor for VM registers. Only called as long as HCR_TVM ++ * is set. ++ */ ++static bool access_vm_reg(struct kvm_vcpu *vcpu, ++ const struct coproc_params *p, ++ const struct coproc_reg *r) ++{ ++ BUG_ON(!p->is_write); ++ ++ vcpu->arch.cp15[r->reg] = *vcpu_reg(vcpu, p->Rt1); ++ if (p->is_64bit) ++ vcpu->arch.cp15[r->reg + 1] = *vcpu_reg(vcpu, p->Rt2); ++ ++ return true; ++} ++ ++/* ++ * SCTLR accessor. Only called as long as HCR_TVM is set. If the ++ * guest enables the MMU, we stop trapping the VM sys_regs and leave ++ * it in complete control of the caches. ++ * ++ * Used by the cpu-specific code. ++ */ ++bool access_sctlr(struct kvm_vcpu *vcpu, ++ const struct coproc_params *p, ++ const struct coproc_reg *r) ++{ ++ access_vm_reg(vcpu, p, r); ++ ++ if (vcpu_has_cache_enabled(vcpu)) { /* MMU+Caches enabled? */ ++ vcpu->arch.hcr &= ~HCR_TVM; ++ stage2_flush_vm(vcpu->kvm); ++ } ++ ++ return true; ++} ++ ++/* + * We could trap ID_DFR0 and tell the guest we don't support performance + * monitoring. Unfortunately the patch to make the kernel check ID_DFR0 was + * NAKed, so it will read the PMCR anyway. +@@ -261,33 +300,36 @@ static const struct coproc_reg cp15_regs[] = { + { CRn( 1), CRm( 0), Op1( 0), Op2( 2), is32, + NULL, reset_val, c1_CPACR, 0x00000000 }, + +- /* TTBR0/TTBR1: swapped by interrupt.S. */ +- { CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 }, +- { CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 }, +- +- /* TTBCR: swapped by interrupt.S. */ ++ /* TTBR0/TTBR1/TTBCR: swapped by interrupt.S. */ ++ { CRm64( 2), Op1( 0), is64, access_vm_reg, reset_unknown64, c2_TTBR0 }, ++ { CRn(2), CRm( 0), Op1( 0), Op2( 0), is32, ++ access_vm_reg, reset_unknown, c2_TTBR0 }, ++ { CRn(2), CRm( 0), Op1( 0), Op2( 1), is32, ++ access_vm_reg, reset_unknown, c2_TTBR1 }, + { CRn( 2), CRm( 0), Op1( 0), Op2( 2), is32, +- NULL, reset_val, c2_TTBCR, 0x00000000 }, ++ access_vm_reg, reset_val, c2_TTBCR, 0x00000000 }, ++ { CRm64( 2), Op1( 1), is64, access_vm_reg, reset_unknown64, c2_TTBR1 }, ++ + + /* DACR: swapped by interrupt.S. */ + { CRn( 3), CRm( 0), Op1( 0), Op2( 0), is32, +- NULL, reset_unknown, c3_DACR }, ++ access_vm_reg, reset_unknown, c3_DACR }, + + /* DFSR/IFSR/ADFSR/AIFSR: swapped by interrupt.S. */ + { CRn( 5), CRm( 0), Op1( 0), Op2( 0), is32, +- NULL, reset_unknown, c5_DFSR }, ++ access_vm_reg, reset_unknown, c5_DFSR }, + { CRn( 5), CRm( 0), Op1( 0), Op2( 1), is32, +- NULL, reset_unknown, c5_IFSR }, ++ access_vm_reg, reset_unknown, c5_IFSR }, + { CRn( 5), CRm( 1), Op1( 0), Op2( 0), is32, +- NULL, reset_unknown, c5_ADFSR }, ++ access_vm_reg, reset_unknown, c5_ADFSR }, + { CRn( 5), CRm( 1), Op1( 0), Op2( 1), is32, +- NULL, reset_unknown, c5_AIFSR }, ++ access_vm_reg, reset_unknown, c5_AIFSR }, + + /* DFAR/IFAR: swapped by interrupt.S. */ + { CRn( 6), CRm( 0), Op1( 0), Op2( 0), is32, +- NULL, reset_unknown, c6_DFAR }, ++ access_vm_reg, reset_unknown, c6_DFAR }, + { CRn( 6), CRm( 0), Op1( 0), Op2( 2), is32, +- NULL, reset_unknown, c6_IFAR }, ++ access_vm_reg, reset_unknown, c6_IFAR }, + + /* PAR swapped by interrupt.S */ + { CRm64( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR }, +@@ -324,9 +366,15 @@ static const struct coproc_reg cp15_regs[] = { + + /* PRRR/NMRR (aka MAIR0/MAIR1): swapped by interrupt.S. */ + { CRn(10), CRm( 2), Op1( 0), Op2( 0), is32, +- NULL, reset_unknown, c10_PRRR}, ++ access_vm_reg, reset_unknown, c10_PRRR}, + { CRn(10), CRm( 2), Op1( 0), Op2( 1), is32, +- NULL, reset_unknown, c10_NMRR}, ++ access_vm_reg, reset_unknown, c10_NMRR}, ++ ++ /* AMAIR0/AMAIR1: swapped by interrupt.S. */ ++ { CRn(10), CRm( 3), Op1( 0), Op2( 0), is32, ++ access_vm_reg, reset_unknown, c10_AMAIR0}, ++ { CRn(10), CRm( 3), Op1( 0), Op2( 1), is32, ++ access_vm_reg, reset_unknown, c10_AMAIR1}, + + /* VBAR: swapped by interrupt.S. */ + { CRn(12), CRm( 0), Op1( 0), Op2( 0), is32, +@@ -334,7 +382,7 @@ static const struct coproc_reg cp15_regs[] = { + + /* CONTEXTIDR/TPIDRURW/TPIDRURO/TPIDRPRW: swapped by interrupt.S. */ + { CRn(13), CRm( 0), Op1( 0), Op2( 1), is32, +- NULL, reset_val, c13_CID, 0x00000000 }, ++ access_vm_reg, reset_val, c13_CID, 0x00000000 }, + { CRn(13), CRm( 0), Op1( 0), Op2( 2), is32, + NULL, reset_unknown, c13_TID_URW }, + { CRn(13), CRm( 0), Op1( 0), Op2( 3), is32, +@@ -443,7 +491,7 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) + { + struct coproc_params params; + +- params.CRm = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf; ++ params.CRn = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf; + params.Rt1 = (kvm_vcpu_get_hsr(vcpu) >> 5) & 0xf; + params.is_write = ((kvm_vcpu_get_hsr(vcpu) & 1) == 0); + params.is_64bit = true; +@@ -451,7 +499,7 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) + params.Op1 = (kvm_vcpu_get_hsr(vcpu) >> 16) & 0xf; + params.Op2 = 0; + params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf; +- params.CRn = 0; ++ params.CRm = 0; + + return emulate_cp15(vcpu, ¶ms); + } +@@ -694,7 +742,7 @@ static bool is_valid_cache(u32 val) + u32 level, ctype; + + if (val >= CSSELR_MAX) +- return -ENOENT; ++ return false; + + /* Bottom bit is Instruction or Data bit. Next 3 bits are level. */ + level = (val >> 1); +diff --git a/arch/arm/kvm/coproc.h b/arch/arm/kvm/coproc.h +index 0461d5c..1a44bbe 100644 +--- a/arch/arm/kvm/coproc.h ++++ b/arch/arm/kvm/coproc.h +@@ -58,8 +58,8 @@ static inline void print_cp_instr(const struct coproc_params *p) + { + /* Look, we even formatted it for you to paste into the table! */ + if (p->is_64bit) { +- kvm_pr_unimpl(" { CRm(%2lu), Op1(%2lu), is64, func_%s },\n", +- p->CRm, p->Op1, p->is_write ? "write" : "read"); ++ kvm_pr_unimpl(" { CRm64(%2lu), Op1(%2lu), is64, func_%s },\n", ++ p->CRn, p->Op1, p->is_write ? "write" : "read"); + } else { + kvm_pr_unimpl(" { CRn(%2lu), CRm(%2lu), Op1(%2lu), Op2(%2lu), is32," + " func_%s },\n", +@@ -135,13 +135,13 @@ static inline int cmp_reg(const struct coproc_reg *i1, + return -1; + if (i1->CRn != i2->CRn) + return i1->CRn - i2->CRn; +- if (i1->is_64 != i2->is_64) +- return i2->is_64 - i1->is_64; + if (i1->CRm != i2->CRm) + return i1->CRm - i2->CRm; + if (i1->Op1 != i2->Op1) + return i1->Op1 - i2->Op1; +- return i1->Op2 - i2->Op2; ++ if (i1->Op2 != i2->Op2) ++ return i1->Op2 - i2->Op2; ++ return i2->is_64 - i1->is_64; + } + + +@@ -153,4 +153,8 @@ static inline int cmp_reg(const struct coproc_reg *i1, + #define is64 .is_64 = true + #define is32 .is_64 = false + ++bool access_sctlr(struct kvm_vcpu *vcpu, ++ const struct coproc_params *p, ++ const struct coproc_reg *r); ++ + #endif /* __ARM_KVM_COPROC_LOCAL_H__ */ +diff --git a/arch/arm/kvm/coproc_a15.c b/arch/arm/kvm/coproc_a15.c +index bb0cac1..e6f4ae4 100644 +--- a/arch/arm/kvm/coproc_a15.c ++++ b/arch/arm/kvm/coproc_a15.c +@@ -34,7 +34,7 @@ + static const struct coproc_reg a15_regs[] = { + /* SCTLR: swapped by interrupt.S. */ + { CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32, +- NULL, reset_val, c1_SCTLR, 0x00C50078 }, ++ access_sctlr, reset_val, c1_SCTLR, 0x00C50078 }, + }; + + static struct kvm_coproc_target_table a15_target_table = { +diff --git a/arch/arm/kvm/coproc_a7.c b/arch/arm/kvm/coproc_a7.c +index 1df7673..17fc7cd 100644 +--- a/arch/arm/kvm/coproc_a7.c ++++ b/arch/arm/kvm/coproc_a7.c +@@ -37,7 +37,7 @@ + static const struct coproc_reg a7_regs[] = { + /* SCTLR: swapped by interrupt.S. */ + { CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32, +- NULL, reset_val, c1_SCTLR, 0x00C50878 }, ++ access_sctlr, reset_val, c1_SCTLR, 0x00C50878 }, + }; + + static struct kvm_coproc_target_table a7_target_table = { +diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c +index 0de91fc..ec4fa86 100644 +--- a/arch/arm/kvm/handle_exit.c ++++ b/arch/arm/kvm/handle_exit.c +@@ -89,6 +89,8 @@ static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run) + else + kvm_vcpu_block(vcpu); + ++ kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); ++ + return 1; + } + +diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S +index 1b9844d..ee4f744 100644 +--- a/arch/arm/kvm/init.S ++++ b/arch/arm/kvm/init.S +@@ -98,6 +98,10 @@ __do_hyp_init: + mrc p15, 0, r0, c10, c2, 1 + mcr p15, 4, r0, c10, c2, 1 + ++ @ Invalidate the stale TLBs from Bootloader ++ mcr p15, 4, r0, c8, c7, 0 @ TLBIALLH ++ dsb ish ++ + @ Set the HSCTLR to: + @ - ARM/THUMB exceptions: Kernel config (Thumb-2 kernel) + @ - Endianness: Kernel config +diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S +index 0d68d40..a1467e7 100644 +--- a/arch/arm/kvm/interrupts.S ++++ b/arch/arm/kvm/interrupts.S +@@ -159,13 +159,9 @@ __kvm_vcpu_return: + @ Don't trap coprocessor accesses for host kernel + set_hstr vmexit + set_hdcr vmexit +- set_hcptr vmexit, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11)) ++ set_hcptr vmexit, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11)), after_vfp_restore + + #ifdef CONFIG_VFPv3 +- @ Save floating point registers we if let guest use them. +- tst r2, #(HCPTR_TCP(10) | HCPTR_TCP(11)) +- bne after_vfp_restore +- + @ Switch VFP/NEON hardware state to the host's + add r7, vcpu, #VCPU_VFP_GUEST + store_vfp_state r7 +@@ -177,6 +173,8 @@ after_vfp_restore: + @ Restore FPEXC_EN which we clobbered on entry + pop {r2} + VFPFMXR FPEXC, r2 ++#else ++after_vfp_restore: + #endif + + @ Reset Hyp-role +@@ -467,7 +465,7 @@ switch_to_guest_vfp: + push {r3-r7} + + @ NEON/VFP used. Turn on VFP access. +- set_hcptr vmexit, (HCPTR_TCP(10) | HCPTR_TCP(11)) ++ set_hcptr vmtrap, (HCPTR_TCP(10) | HCPTR_TCP(11)) + + @ Switch VFP/NEON hardware state to the guest's + add r7, r0, #VCPU_VFP_HOST +diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S +index 6f18695..2973b2d 100644 +--- a/arch/arm/kvm/interrupts_head.S ++++ b/arch/arm/kvm/interrupts_head.S +@@ -303,13 +303,17 @@ vcpu .req r0 @ vcpu pointer always in r0 + + mrc p15, 0, r2, c14, c1, 0 @ CNTKCTL + mrrc p15, 0, r4, r5, c7 @ PAR ++ mrc p15, 0, r6, c10, c3, 0 @ AMAIR0 ++ mrc p15, 0, r7, c10, c3, 1 @ AMAIR1 + + .if \store_to_vcpu == 0 +- push {r2,r4-r5} ++ push {r2,r4-r7} + .else + str r2, [vcpu, #CP15_OFFSET(c14_CNTKCTL)] + add r12, vcpu, #CP15_OFFSET(c7_PAR) + strd r4, r5, [r12] ++ str r6, [vcpu, #CP15_OFFSET(c10_AMAIR0)] ++ str r7, [vcpu, #CP15_OFFSET(c10_AMAIR1)] + .endif + .endm + +@@ -322,15 +326,19 @@ vcpu .req r0 @ vcpu pointer always in r0 + */ + .macro write_cp15_state read_from_vcpu + .if \read_from_vcpu == 0 +- pop {r2,r4-r5} ++ pop {r2,r4-r7} + .else + ldr r2, [vcpu, #CP15_OFFSET(c14_CNTKCTL)] + add r12, vcpu, #CP15_OFFSET(c7_PAR) + ldrd r4, r5, [r12] ++ ldr r6, [vcpu, #CP15_OFFSET(c10_AMAIR0)] ++ ldr r7, [vcpu, #CP15_OFFSET(c10_AMAIR1)] + .endif + + mcr p15, 0, r2, c14, c1, 0 @ CNTKCTL + mcrr p15, 0, r4, r5, c7 @ PAR ++ mcr p15, 0, r6, c10, c3, 0 @ AMAIR0 ++ mcr p15, 0, r7, c10, c3, 1 @ AMAIR1 + + .if \read_from_vcpu == 0 + pop {r2-r12} +@@ -570,8 +578,13 @@ vcpu .req r0 @ vcpu pointer always in r0 + .endm + + /* Configures the HCPTR (Hyp Coprocessor Trap Register) on entry/return +- * (hardware reset value is 0). Keep previous value in r2. */ +-.macro set_hcptr operation, mask ++ * (hardware reset value is 0). Keep previous value in r2. ++ * An ISB is emited on vmexit/vmtrap, but executed on vmexit only if ++ * VFP wasn't already enabled (always executed on vmtrap). ++ * If a label is specified with vmexit, it is branched to if VFP wasn't ++ * enabled. ++ */ ++.macro set_hcptr operation, mask, label = none + mrc p15, 4, r2, c1, c1, 2 + ldr r3, =\mask + .if \operation == vmentry +@@ -580,6 +593,17 @@ vcpu .req r0 @ vcpu pointer always in r0 + bic r3, r2, r3 @ Don't trap defined coproc-accesses + .endif + mcr p15, 4, r3, c1, c1, 2 ++ .if \operation != vmentry ++ .if \operation == vmexit ++ tst r2, #(HCPTR_TCP(10) | HCPTR_TCP(11)) ++ beq 1f ++ .endif ++ isb ++ .if \label != none ++ b \label ++ .endif ++1: ++ .endif + .endm + + /* Configures the HDCR (Hyp Debug Configuration Register) on entry/return +@@ -597,17 +621,14 @@ vcpu .req r0 @ vcpu pointer always in r0 + + /* Enable/Disable: stage-2 trans., trap interrupts, trap wfi, trap smc */ + .macro configure_hyp_role operation +- mrc p15, 4, r2, c1, c1, 0 @ HCR +- bic r2, r2, #HCR_VIRT_EXCP_MASK +- ldr r3, =HCR_GUEST_MASK + .if \operation == vmentry +- orr r2, r2, r3 ++ ldr r2, [vcpu, #VCPU_HCR] + ldr r3, [vcpu, #VCPU_IRQ_LINES] + orr r2, r2, r3 + .else +- bic r2, r2, r3 ++ mov r2, #0 + .endif +- mcr p15, 4, r2, c1, c1, 0 ++ mcr p15, 4, r2, c1, c1, 0 @ HCR + .endm + + .macro load_vcpu +diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c +index 575d790..c612e37 100644 +--- a/arch/arm/kvm/mmu.c ++++ b/arch/arm/kvm/mmu.c +@@ -90,103 +90,209 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc) + return p; + } + +-static bool page_empty(void *ptr) ++static void clear_pgd_entry(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr) + { +- struct page *ptr_page = virt_to_page(ptr); +- return page_count(ptr_page) == 1; ++ pud_t *pud_table __maybe_unused = pud_offset(pgd, 0); ++ pgd_clear(pgd); ++ kvm_tlb_flush_vmid_ipa(kvm, addr); ++ pud_free(NULL, pud_table); ++ put_page(virt_to_page(pgd)); + } + + static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr) + { +- if (pud_huge(*pud)) { +- pud_clear(pud); +- kvm_tlb_flush_vmid_ipa(kvm, addr); +- } else { +- pmd_t *pmd_table = pmd_offset(pud, 0); +- pud_clear(pud); +- kvm_tlb_flush_vmid_ipa(kvm, addr); +- pmd_free(NULL, pmd_table); +- } ++ pmd_t *pmd_table = pmd_offset(pud, 0); ++ VM_BUG_ON(pud_huge(*pud)); ++ pud_clear(pud); ++ kvm_tlb_flush_vmid_ipa(kvm, addr); ++ pmd_free(NULL, pmd_table); + put_page(virt_to_page(pud)); + } + + static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr) + { +- if (kvm_pmd_huge(*pmd)) { +- pmd_clear(pmd); +- kvm_tlb_flush_vmid_ipa(kvm, addr); +- } else { +- pte_t *pte_table = pte_offset_kernel(pmd, 0); +- pmd_clear(pmd); +- kvm_tlb_flush_vmid_ipa(kvm, addr); +- pte_free_kernel(NULL, pte_table); +- } ++ pte_t *pte_table = pte_offset_kernel(pmd, 0); ++ VM_BUG_ON(kvm_pmd_huge(*pmd)); ++ pmd_clear(pmd); ++ kvm_tlb_flush_vmid_ipa(kvm, addr); ++ pte_free_kernel(NULL, pte_table); + put_page(virt_to_page(pmd)); + } + +-static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr) ++static void unmap_ptes(struct kvm *kvm, pmd_t *pmd, ++ phys_addr_t addr, phys_addr_t end) + { +- if (pte_present(*pte)) { +- kvm_set_pte(pte, __pte(0)); +- put_page(virt_to_page(pte)); +- kvm_tlb_flush_vmid_ipa(kvm, addr); ++ phys_addr_t start_addr = addr; ++ pte_t *pte, *start_pte; ++ ++ start_pte = pte = pte_offset_kernel(pmd, addr); ++ do { ++ if (!pte_none(*pte)) { ++ kvm_set_pte(pte, __pte(0)); ++ put_page(virt_to_page(pte)); ++ kvm_tlb_flush_vmid_ipa(kvm, addr); ++ } ++ } while (pte++, addr += PAGE_SIZE, addr != end); ++ ++ if (kvm_pte_table_empty(start_pte)) ++ clear_pmd_entry(kvm, pmd, start_addr); + } ++ ++static void unmap_pmds(struct kvm *kvm, pud_t *pud, ++ phys_addr_t addr, phys_addr_t end) ++{ ++ phys_addr_t next, start_addr = addr; ++ pmd_t *pmd, *start_pmd; ++ ++ start_pmd = pmd = pmd_offset(pud, addr); ++ do { ++ next = kvm_pmd_addr_end(addr, end); ++ if (!pmd_none(*pmd)) { ++ if (kvm_pmd_huge(*pmd)) { ++ pmd_clear(pmd); ++ kvm_tlb_flush_vmid_ipa(kvm, addr); ++ put_page(virt_to_page(pmd)); ++ } else { ++ unmap_ptes(kvm, pmd, addr, next); ++ } ++ } ++ } while (pmd++, addr = next, addr != end); ++ ++ if (kvm_pmd_table_empty(start_pmd)) ++ clear_pud_entry(kvm, pud, start_addr); ++} ++ ++static void unmap_puds(struct kvm *kvm, pgd_t *pgd, ++ phys_addr_t addr, phys_addr_t end) ++{ ++ phys_addr_t next, start_addr = addr; ++ pud_t *pud, *start_pud; ++ ++ start_pud = pud = pud_offset(pgd, addr); ++ do { ++ next = kvm_pud_addr_end(addr, end); ++ if (!pud_none(*pud)) { ++ if (pud_huge(*pud)) { ++ pud_clear(pud); ++ kvm_tlb_flush_vmid_ipa(kvm, addr); ++ put_page(virt_to_page(pud)); ++ } else { ++ unmap_pmds(kvm, pud, addr, next); ++ } ++ } ++ } while (pud++, addr = next, addr != end); ++ ++ if (kvm_pud_table_empty(start_pud)) ++ clear_pgd_entry(kvm, pgd, start_addr); + } + ++ + static void unmap_range(struct kvm *kvm, pgd_t *pgdp, +- unsigned long long start, u64 size) ++ phys_addr_t start, u64 size) + { + pgd_t *pgd; +- pud_t *pud; +- pmd_t *pmd; ++ phys_addr_t addr = start, end = start + size; ++ phys_addr_t next; ++ ++ pgd = pgdp + kvm_pgd_index(addr); ++ do { ++ next = kvm_pgd_addr_end(addr, end); ++ if (!pgd_none(*pgd)) ++ unmap_puds(kvm, pgd, addr, next); ++ } while (pgd++, addr = next, addr != end); ++} ++ ++static void stage2_flush_ptes(struct kvm *kvm, pmd_t *pmd, ++ phys_addr_t addr, phys_addr_t end) ++{ + pte_t *pte; +- unsigned long long addr = start, end = start + size; +- u64 next; + +- while (addr < end) { +- pgd = pgdp + pgd_index(addr); +- pud = pud_offset(pgd, addr); +- if (pud_none(*pud)) { +- addr = pud_addr_end(addr, end); +- continue; ++ pte = pte_offset_kernel(pmd, addr); ++ do { ++ if (!pte_none(*pte)) { ++ hva_t hva = gfn_to_hva(kvm, addr >> PAGE_SHIFT); ++ kvm_flush_dcache_to_poc((void*)hva, PAGE_SIZE); + } ++ } while (pte++, addr += PAGE_SIZE, addr != end); ++} + +- if (pud_huge(*pud)) { +- /* +- * If we are dealing with a huge pud, just clear it and +- * move on. +- */ +- clear_pud_entry(kvm, pud, addr); +- addr = pud_addr_end(addr, end); +- continue; +- } ++static void stage2_flush_pmds(struct kvm *kvm, pud_t *pud, ++ phys_addr_t addr, phys_addr_t end) ++{ ++ pmd_t *pmd; ++ phys_addr_t next; + +- pmd = pmd_offset(pud, addr); +- if (pmd_none(*pmd)) { +- addr = pmd_addr_end(addr, end); +- continue; ++ pmd = pmd_offset(pud, addr); ++ do { ++ next = kvm_pmd_addr_end(addr, end); ++ if (!pmd_none(*pmd)) { ++ if (kvm_pmd_huge(*pmd)) { ++ hva_t hva = gfn_to_hva(kvm, addr >> PAGE_SHIFT); ++ kvm_flush_dcache_to_poc((void*)hva, PMD_SIZE); ++ } else { ++ stage2_flush_ptes(kvm, pmd, addr, next); ++ } + } ++ } while (pmd++, addr = next, addr != end); ++} + +- if (!kvm_pmd_huge(*pmd)) { +- pte = pte_offset_kernel(pmd, addr); +- clear_pte_entry(kvm, pte, addr); +- next = addr + PAGE_SIZE; +- } ++static void stage2_flush_puds(struct kvm *kvm, pgd_t *pgd, ++ phys_addr_t addr, phys_addr_t end) ++{ ++ pud_t *pud; ++ phys_addr_t next; + +- /* +- * If the pmd entry is to be cleared, walk back up the ladder +- */ +- if (kvm_pmd_huge(*pmd) || page_empty(pte)) { +- clear_pmd_entry(kvm, pmd, addr); +- next = pmd_addr_end(addr, end); +- if (page_empty(pmd) && !page_empty(pud)) { +- clear_pud_entry(kvm, pud, addr); +- next = pud_addr_end(addr, end); ++ pud = pud_offset(pgd, addr); ++ do { ++ next = kvm_pud_addr_end(addr, end); ++ if (!pud_none(*pud)) { ++ if (pud_huge(*pud)) { ++ hva_t hva = gfn_to_hva(kvm, addr >> PAGE_SHIFT); ++ kvm_flush_dcache_to_poc((void*)hva, PUD_SIZE); ++ } else { ++ stage2_flush_pmds(kvm, pud, addr, next); + } + } ++ } while (pud++, addr = next, addr != end); ++} + +- addr = next; +- } ++static void stage2_flush_memslot(struct kvm *kvm, ++ struct kvm_memory_slot *memslot) ++{ ++ phys_addr_t addr = memslot->base_gfn << PAGE_SHIFT; ++ phys_addr_t end = addr + PAGE_SIZE * memslot->npages; ++ phys_addr_t next; ++ pgd_t *pgd; ++ ++ pgd = kvm->arch.pgd + kvm_pgd_index(addr); ++ do { ++ next = kvm_pgd_addr_end(addr, end); ++ stage2_flush_puds(kvm, pgd, addr, next); ++ } while (pgd++, addr = next, addr != end); ++} ++ ++/** ++ * stage2_flush_vm - Invalidate cache for pages mapped in stage 2 ++ * @kvm: The struct kvm pointer ++ * ++ * Go through the stage 2 page tables and invalidate any cache lines ++ * backing memory already mapped to the VM. ++ */ ++void stage2_flush_vm(struct kvm *kvm) ++{ ++ struct kvm_memslots *slots; ++ struct kvm_memory_slot *memslot; ++ int idx; ++ ++ idx = srcu_read_lock(&kvm->srcu); ++ spin_lock(&kvm->mmu_lock); ++ ++ slots = kvm_memslots(kvm); ++ kvm_for_each_memslot(memslot, slots) ++ stage2_flush_memslot(kvm, memslot); ++ ++ spin_unlock(&kvm->mmu_lock); ++ srcu_read_unlock(&kvm->srcu, idx); + } + + /** +@@ -450,6 +556,71 @@ static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size) + unmap_range(kvm, kvm->arch.pgd, start, size); + } + ++static void stage2_unmap_memslot(struct kvm *kvm, ++ struct kvm_memory_slot *memslot) ++{ ++ hva_t hva = memslot->userspace_addr; ++ phys_addr_t addr = memslot->base_gfn << PAGE_SHIFT; ++ phys_addr_t size = PAGE_SIZE * memslot->npages; ++ hva_t reg_end = hva + size; ++ ++ /* ++ * A memory region could potentially cover multiple VMAs, and any holes ++ * between them, so iterate over all of them to find out if we should ++ * unmap any of them. ++ * ++ * +--------------------------------------------+ ++ * +---------------+----------------+ +----------------+ ++ * | : VMA 1 | VMA 2 | | VMA 3 : | ++ * +---------------+----------------+ +----------------+ ++ * | memory region | ++ * +--------------------------------------------+ ++ */ ++ do { ++ struct vm_area_struct *vma = find_vma(current->mm, hva); ++ hva_t vm_start, vm_end; ++ ++ if (!vma || vma->vm_start >= reg_end) ++ break; ++ ++ /* ++ * Take the intersection of this VMA with the memory region ++ */ ++ vm_start = max(hva, vma->vm_start); ++ vm_end = min(reg_end, vma->vm_end); ++ ++ if (!(vma->vm_flags & VM_PFNMAP)) { ++ gpa_t gpa = addr + (vm_start - memslot->userspace_addr); ++ unmap_stage2_range(kvm, gpa, vm_end - vm_start); ++ } ++ hva = vm_end; ++ } while (hva < reg_end); ++} ++ ++/** ++ * stage2_unmap_vm - Unmap Stage-2 RAM mappings ++ * @kvm: The struct kvm pointer ++ * ++ * Go through the memregions and unmap any reguler RAM ++ * backing memory already mapped to the VM. ++ */ ++void stage2_unmap_vm(struct kvm *kvm) ++{ ++ struct kvm_memslots *slots; ++ struct kvm_memory_slot *memslot; ++ int idx; ++ ++ idx = srcu_read_lock(&kvm->srcu); ++ spin_lock(&kvm->mmu_lock); ++ ++ slots = kvm_memslots(kvm); ++ kvm_for_each_memslot(memslot, slots) ++ stage2_unmap_memslot(kvm, memslot); ++ ++ spin_unlock(&kvm->mmu_lock); ++ srcu_read_unlock(&kvm->srcu, idx); ++} ++ + /** + * kvm_free_stage2_pgd - free all stage-2 tables + * @kvm: The KVM struct pointer for the VM. +@@ -478,7 +649,7 @@ static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache + pud_t *pud; + pmd_t *pmd; + +- pgd = kvm->arch.pgd + pgd_index(addr); ++ pgd = kvm->arch.pgd + kvm_pgd_index(addr); + pud = pud_offset(pgd, addr); + if (pud_none(*pud)) { + if (!cache) +@@ -641,6 +812,19 @@ static bool transparent_hugepage_adjust(pfn_t *pfnp, phys_addr_t *ipap) + return false; + } + ++static bool kvm_is_write_fault(struct kvm_vcpu *vcpu) ++{ ++ if (kvm_vcpu_trap_is_iabt(vcpu)) ++ return false; ++ ++ return kvm_vcpu_dabt_iswrite(vcpu); ++} ++ ++static bool kvm_is_device_pfn(unsigned long pfn) ++{ ++ return !pfn_valid(pfn); ++} ++ + static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + struct kvm_memory_slot *memslot, + unsigned long fault_status) +@@ -654,8 +838,9 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache; + struct vm_area_struct *vma; + pfn_t pfn; ++ pgprot_t mem_type = PAGE_S2; + +- write_fault = kvm_is_write_fault(kvm_vcpu_get_hsr(vcpu)); ++ write_fault = kvm_is_write_fault(vcpu); + if (fault_status == FSC_PERM && !write_fault) { + kvm_err("Unexpected L2 read permission error\n"); + return -EFAULT; +@@ -664,6 +849,12 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + /* Let's check if we will get back a huge page backed by hugetlbfs */ + down_read(¤t->mm->mmap_sem); + vma = find_vma_intersection(current->mm, hva, hva + 1); ++ if (unlikely(!vma)) { ++ kvm_err("Failed to find VMA for hva 0x%lx\n", hva); ++ up_read(¤t->mm->mmap_sem); ++ return -EFAULT; ++ } ++ + if (is_vm_hugetlb_page(vma)) { + hugetlb = true; + gfn = (fault_ipa & PMD_MASK) >> PAGE_SHIFT; +@@ -704,6 +895,9 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + if (is_error_pfn(pfn)) + return -EFAULT; + ++ if (kvm_is_device_pfn(pfn)) ++ mem_type = PAGE_S2_DEVICE; ++ + spin_lock(&kvm->mmu_lock); + if (mmu_notifier_retry(kvm, mmu_seq)) + goto out_unlock; +@@ -711,22 +905,23 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, + hugetlb = transparent_hugepage_adjust(&pfn, &fault_ipa); + + if (hugetlb) { +- pmd_t new_pmd = pfn_pmd(pfn, PAGE_S2); ++ pmd_t new_pmd = pfn_pmd(pfn, mem_type); + new_pmd = pmd_mkhuge(new_pmd); + if (writable) { + kvm_set_s2pmd_writable(&new_pmd); + kvm_set_pfn_dirty(pfn); + } +- coherent_icache_guest_page(kvm, hva & PMD_MASK, PMD_SIZE); ++ coherent_cache_guest_page(vcpu, hva & PMD_MASK, PMD_SIZE); + ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd); + } else { +- pte_t new_pte = pfn_pte(pfn, PAGE_S2); ++ pte_t new_pte = pfn_pte(pfn, mem_type); + if (writable) { + kvm_set_s2pte_writable(&new_pte); + kvm_set_pfn_dirty(pfn); + } +- coherent_icache_guest_page(kvm, hva, PAGE_SIZE); +- ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, false); ++ coherent_cache_guest_page(vcpu, hva, PAGE_SIZE); ++ ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, ++ pgprot_val(mem_type) == pgprot_val(PAGE_S2_DEVICE)); + } + + +@@ -802,6 +997,9 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) + + memslot = gfn_to_memslot(vcpu->kvm, gfn); + ++ /* Userspace should not be able to register out-of-bounds IPAs */ ++ VM_BUG_ON(fault_ipa >= KVM_PHYS_SIZE); ++ + ret = user_mem_abort(vcpu, fault_ipa, memslot, fault_status); + if (ret == 0) + ret = 1; +@@ -1006,3 +1204,57 @@ out: + free_hyp_pgds(); + return err; + } ++ ++void kvm_arch_commit_memory_region(struct kvm *kvm, ++ struct kvm_userspace_memory_region *mem, ++ const struct kvm_memory_slot *old, ++ enum kvm_mr_change change) ++{ ++ gpa_t gpa = old->base_gfn << PAGE_SHIFT; ++ phys_addr_t size = old->npages << PAGE_SHIFT; ++ if (change == KVM_MR_DELETE || change == KVM_MR_MOVE) { ++ spin_lock(&kvm->mmu_lock); ++ unmap_stage2_range(kvm, gpa, size); ++ spin_unlock(&kvm->mmu_lock); ++ } ++} ++ ++int kvm_arch_prepare_memory_region(struct kvm *kvm, ++ struct kvm_memory_slot *memslot, ++ struct kvm_userspace_memory_region *mem, ++ enum kvm_mr_change change) ++{ ++ /* ++ * Prevent userspace from creating a memory region outside of the IPA ++ * space addressable by the KVM guest IPA space. ++ */ ++ if (memslot->base_gfn + memslot->npages >= ++ (KVM_PHYS_SIZE >> PAGE_SHIFT)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free, ++ struct kvm_memory_slot *dont) ++{ ++} ++ ++int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, ++ unsigned long npages) ++{ ++ return 0; ++} ++ ++void kvm_arch_memslots_updated(struct kvm *kvm) ++{ ++} ++ ++void kvm_arch_flush_shadow_all(struct kvm *kvm) ++{ ++} ++ ++void kvm_arch_flush_shadow_memslot(struct kvm *kvm, ++ struct kvm_memory_slot *slot) ++{ ++} +diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c +index 034529d..d66f102 100644 +--- a/arch/arm/mach-at91/clock.c ++++ b/arch/arm/mach-at91/clock.c +@@ -962,6 +962,7 @@ static int __init at91_clock_reset(void) + } + + at91_pmc_write(AT91_PMC_SCDR, scdr); ++ at91_pmc_write(AT91_PMC_PCDR, pcdr); + if (cpu_is_sama5d3()) + at91_pmc_write(AT91_PMC_PCDR1, pcdr1); + +diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h +index c5101dc..1d4df3b 100644 +--- a/arch/arm/mach-at91/pm.h ++++ b/arch/arm/mach-at91/pm.h +@@ -45,7 +45,7 @@ static inline void at91rm9200_standby(void) + " mcr p15, 0, %0, c7, c0, 4\n\t" + " str %5, [%1, %2]" + : +- : "r" (0), "r" (AT91_BASE_SYS), "r" (AT91RM9200_SDRAMC_LPR), ++ : "r" (0), "r" (at91_ramc_base[0]), "r" (AT91RM9200_SDRAMC_LPR), + "r" (1), "r" (AT91RM9200_SDRAMC_SRR), + "r" (lpr)); + } +diff --git a/arch/arm/mach-dove/board-dt.c b/arch/arm/mach-dove/board-dt.c +index 49fa9ab..7a7a09a5 100644 +--- a/arch/arm/mach-dove/board-dt.c ++++ b/arch/arm/mach-dove/board-dt.c +@@ -26,7 +26,7 @@ static void __init dove_dt_init(void) + #ifdef CONFIG_CACHE_TAUROS2 + tauros2_init(0); + #endif +- BUG_ON(mvebu_mbus_dt_init()); ++ BUG_ON(mvebu_mbus_dt_init(false)); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + } + +diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c +index 3c27907..fdabccd 100644 +--- a/arch/arm/mach-imx/clk-imx6q.c ++++ b/arch/arm/mach-imx/clk-imx6q.c +@@ -283,8 +283,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) + post_div_table[1].div = 1; + post_div_table[2].div = 1; + video_div_table[1].div = 1; +- video_div_table[2].div = 1; +- }; ++ video_div_table[3].div = 1; ++ } + + /* type name parent_name base div_mask */ + clk[pll1_sys] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f, false); +@@ -536,7 +536,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) + clk[gpmi_io] = imx_clk_gate2("gpmi_io", "enfc", base + 0x78, 28); + clk[gpmi_apb] = imx_clk_gate2("gpmi_apb", "usdhc3", base + 0x78, 30); + clk[rom] = imx_clk_gate2("rom", "ahb", base + 0x7c, 0); +- clk[sata] = imx_clk_gate2("sata", "ipg", base + 0x7c, 4); ++ clk[sata] = imx_clk_gate2("sata", "ahb", base + 0x7c, 4); + clk[sdma] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6); + clk[spba] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12); + clk[spdif] = imx_clk_gate2("spdif", "spdif_podf", base + 0x7c, 14); +diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c +index 7818815..79e629d 100644 +--- a/arch/arm/mach-kirkwood/board-dt.c ++++ b/arch/arm/mach-kirkwood/board-dt.c +@@ -116,7 +116,7 @@ static void __init kirkwood_dt_init(void) + */ + writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG); + +- BUG_ON(mvebu_mbus_dt_init()); ++ BUG_ON(mvebu_mbus_dt_init(false)); + + kirkwood_l2_init(); + +diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c +index f6c9d1d..79c3766 100644 +--- a/arch/arm/mach-mvebu/armada-370-xp.c ++++ b/arch/arm/mach-mvebu/armada-370-xp.c +@@ -41,7 +41,7 @@ static void __init armada_370_xp_timer_and_clk_init(void) + of_clk_init(NULL); + clocksource_of_init(); + coherency_init(); +- BUG_ON(mvebu_mbus_dt_init()); ++ BUG_ON(mvebu_mbus_dt_init(coherency_available())); + #ifdef CONFIG_CACHE_L2X0 + l2x0_of_init(0, ~0UL); + #endif +diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c +index 4e9d581..49bad4d 100644 +--- a/arch/arm/mach-mvebu/coherency.c ++++ b/arch/arm/mach-mvebu/coherency.c +@@ -121,10 +121,47 @@ static struct notifier_block mvebu_hwcc_platform_nb = { + .notifier_call = mvebu_hwcc_platform_notifier, + }; + ++/* ++ * Keep track of whether we have IO hardware coherency enabled or not. ++ * On Armada 370's we will not be using it for example. We need to make ++ * that available [through coherency_available()] so the mbus controller ++ * doesn't enable the IO coherency bit in the attribute bits of the ++ * chip selects. ++ */ ++static int coherency_enabled; ++ ++int coherency_available(void) ++{ ++ return coherency_enabled; ++} ++ + int __init coherency_init(void) + { + struct device_node *np; + ++ /* ++ * The coherency fabric is needed: ++ * - For coherency between processors on Armada XP, so only ++ * when SMP is enabled. ++ * - For coherency between the processor and I/O devices, but ++ * this coherency requires many pre-requisites (write ++ * allocate cache policy, shareable pages, SMP bit set) that ++ * are only meant in SMP situations. ++ * ++ * Note that this means that on Armada 370, there is currently ++ * no way to use hardware I/O coherency, because even when ++ * CONFIG_SMP is enabled, is_smp() returns false due to the ++ * Armada 370 being a single-core processor. To lift this ++ * limitation, we would have to find a way to make the cache ++ * policy set to write-allocate (on all Armada SoCs), and to ++ * set the shareable attribute in page tables (on all Armada ++ * SoCs except the Armada 370). Unfortunately, such decisions ++ * are taken very early in the kernel boot process, at a point ++ * where we don't know yet on which SoC we are running. ++ */ ++ if (!is_smp()) ++ return 0; ++ + np = of_find_matching_node(NULL, of_coherency_table); + if (np) { + struct resource res; +@@ -141,6 +178,7 @@ int __init coherency_init(void) + coherency_base = of_iomap(np, 0); + coherency_cpu_base = of_iomap(np, 1); + set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0); ++ coherency_enabled = 1; + of_node_put(np); + } + +@@ -151,6 +189,9 @@ static int __init coherency_late_init(void) + { + struct device_node *np; + ++ if (!is_smp()) ++ return 0; ++ + np = of_find_matching_node(NULL, of_coherency_table); + if (np) { + bus_register_notifier(&platform_bus_type, +diff --git a/arch/arm/mach-mvebu/coherency.h b/arch/arm/mach-mvebu/coherency.h +index 760226c..63e18c6 100644 +--- a/arch/arm/mach-mvebu/coherency.h ++++ b/arch/arm/mach-mvebu/coherency.h +@@ -17,6 +17,7 @@ + extern unsigned long coherency_phys_base; + + int set_cpu_coherent(unsigned int cpu_id, int smp_group_id); ++int coherency_available(void); + int coherency_init(void); + + #endif /* __MACH_370_XP_COHERENCY_H */ +diff --git a/arch/arm/mach-omap2/clockdomains7xx_data.c b/arch/arm/mach-omap2/clockdomains7xx_data.c +index 57d5df0..7581e03 100644 +--- a/arch/arm/mach-omap2/clockdomains7xx_data.c ++++ b/arch/arm/mach-omap2/clockdomains7xx_data.c +@@ -331,7 +331,7 @@ static struct clockdomain l4per2_7xx_clkdm = { + .dep_bit = DRA7XX_L4PER2_STATDEP_SHIFT, + .wkdep_srcs = l4per2_wkup_sleep_deps, + .sleepdep_srcs = l4per2_wkup_sleep_deps, +- .flags = CLKDM_CAN_HWSUP_SWSUP, ++ .flags = CLKDM_CAN_SWSUP, + }; + + static struct clockdomain mpu0_7xx_clkdm = { +diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c +index 44bb4d5..89cde07 100644 +--- a/arch/arm/mach-omap2/control.c ++++ b/arch/arm/mach-omap2/control.c +@@ -314,7 +314,8 @@ void omap3_save_scratchpad_contents(void) + scratchpad_contents.public_restore_ptr = + virt_to_phys(omap3_restore_3630); + else if (omap_rev() != OMAP3430_REV_ES3_0 && +- omap_rev() != OMAP3430_REV_ES3_1) ++ omap_rev() != OMAP3430_REV_ES3_1 && ++ omap_rev() != OMAP3430_REV_ES3_1_2) + scratchpad_contents.public_restore_ptr = + virt_to_phys(omap3_restore); + else +diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c +index 66c60fe..399af1e 100644 +--- a/arch/arm/mach-omap2/omap_hwmod.c ++++ b/arch/arm/mach-omap2/omap_hwmod.c +@@ -2185,6 +2185,8 @@ static int _enable(struct omap_hwmod *oh) + oh->mux->pads_dynamic))) { + omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED); + _reconfigure_io_chain(); ++ } else if (oh->flags & HWMOD_FORCE_MSTANDBY) { ++ _reconfigure_io_chain(); + } + + _add_initiator_dep(oh, mpu_oh); +@@ -2291,6 +2293,8 @@ static int _idle(struct omap_hwmod *oh) + if (oh->mux && oh->mux->pads_dynamic) { + omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE); + _reconfigure_io_chain(); ++ } else if (oh->flags & HWMOD_FORCE_MSTANDBY) { ++ _reconfigure_io_chain(); + } + + oh->_state = _HWMOD_STATE_IDLE; +@@ -2448,6 +2452,9 @@ static int of_dev_hwmod_lookup(struct device_node *np, + * registers. This address is needed early so the OCP registers that + * are part of the device's address space can be ioremapped properly. + * ++ * If SYSC access is not needed, the registers will not be remapped ++ * and non-availability of MPU access is not treated as an error. ++ * + * Returns 0 on success, -EINVAL if an invalid hwmod is passed, and + * -ENXIO on absent or invalid register target address space. + */ +@@ -2462,6 +2469,11 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data, + + _save_mpu_port_index(oh); + ++ /* if we don't need sysc access we don't need to ioremap */ ++ if (!oh->class->sysc) ++ return 0; ++ ++ /* we can't continue without MPU PORT if we need sysc access */ + if (oh->_int_flags & _HWMOD_NO_MPU_PORT) + return -ENXIO; + +@@ -2471,8 +2483,10 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data, + oh->name); + + /* Extract the IO space from device tree blob */ +- if (!np) ++ if (!np) { ++ pr_err("omap_hwmod: %s: no dt node\n", oh->name); + return -ENXIO; ++ } + + va_start = of_iomap(np, index + oh->mpu_rt_idx); + } else { +@@ -2531,13 +2545,11 @@ static int __init _init(struct omap_hwmod *oh, void *data) + oh->name, np->name); + } + +- if (oh->class->sysc) { +- r = _init_mpu_rt_base(oh, NULL, index, np); +- if (r < 0) { +- WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n", +- oh->name); +- return 0; +- } ++ r = _init_mpu_rt_base(oh, NULL, index, np); ++ if (r < 0) { ++ WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n", ++ oh->name); ++ return 0; + } + + r = _init_clocks(oh, NULL); +@@ -3345,6 +3357,9 @@ int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois) + if (!ois) + return 0; + ++ if (ois[0] == NULL) /* Empty list */ ++ return 0; ++ + if (!linkspace) { + if (_alloc_linkspace(ois)) { + pr_err("omap_hwmod: could not allocate link space\n"); +diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +index 810c205..d3ac4c6 100644 +--- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c ++++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +@@ -35,6 +35,7 @@ + #include "i2c.h" + #include "mmc.h" + #include "wd_timer.h" ++#include "soc.h" + + /* Base offset for all DRA7XX interrupts external to MPUSS */ + #define DRA7XX_IRQ_GIC_START 32 +@@ -1668,7 +1669,7 @@ static struct omap_hwmod dra7xx_uart3_hwmod = { + .class = &dra7xx_uart_hwmod_class, + .clkdm_name = "l4per_clkdm", + .main_clk = "uart3_gfclk_mux", +- .flags = HWMOD_SWSUP_SIDLE_ACT, ++ .flags = HWMOD_SWSUP_SIDLE_ACT | DEBUG_OMAP4UART3_FLAGS, + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_UART3_CLKCTRL_OFFSET, +@@ -2707,7 +2708,6 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = { + &dra7xx_l4_per3__usb_otg_ss1, + &dra7xx_l4_per3__usb_otg_ss2, + &dra7xx_l4_per3__usb_otg_ss3, +- &dra7xx_l4_per3__usb_otg_ss4, + &dra7xx_l3_main_1__vcp1, + &dra7xx_l4_per2__vcp1, + &dra7xx_l3_main_1__vcp2, +@@ -2716,8 +2716,26 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = { + NULL, + }; + ++static struct omap_hwmod_ocp_if *dra74x_hwmod_ocp_ifs[] __initdata = { ++ &dra7xx_l4_per3__usb_otg_ss4, ++ NULL, ++}; ++ ++static struct omap_hwmod_ocp_if *dra72x_hwmod_ocp_ifs[] __initdata = { ++ NULL, ++}; ++ + int __init dra7xx_hwmod_init(void) + { ++ int ret; ++ + omap_hwmod_init(); +- return omap_hwmod_register_links(dra7xx_hwmod_ocp_ifs); ++ ret = omap_hwmod_register_links(dra7xx_hwmod_ocp_ifs); ++ ++ if (!ret && soc_is_dra74x()) ++ return omap_hwmod_register_links(dra74x_hwmod_ocp_ifs); ++ else if (!ret && soc_is_dra72x()) ++ return omap_hwmod_register_links(dra72x_hwmod_ocp_ifs); ++ ++ return ret; + } +diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c +index eefb30c..2b9cff9 100644 +--- a/arch/arm/mach-omap2/pm44xx.c ++++ b/arch/arm/mach-omap2/pm44xx.c +@@ -148,26 +148,6 @@ static inline int omap4_init_static_deps(void) + struct clockdomain *ducati_clkdm, *l3_2_clkdm; + int ret = 0; + +- if (omap_rev() == OMAP4430_REV_ES1_0) { +- WARN(1, "Power Management not supported on OMAP4430 ES1.0\n"); +- return -ENODEV; +- } +- +- pr_err("Power Management for TI OMAP4.\n"); +- /* +- * OMAP4 chip PM currently works only with certain (newer) +- * versions of bootloaders. This is due to missing code in the +- * kernel to properly reset and initialize some devices. +- * http://www.spinics.net/lists/arm-kernel/msg218641.html +- */ +- pr_warn("OMAP4 PM: u-boot >= v2012.07 is required for full PM support\n"); +- +- ret = pwrdm_for_each(pwrdms_setup, NULL); +- if (ret) { +- pr_err("Failed to setup powerdomains\n"); +- return ret; +- } +- + /* + * The dynamic dependency between MPUSS -> MEMIF and + * MPUSS -> L4_PER/L3_* and DUCATI -> L3_* doesn't work as +@@ -231,6 +211,15 @@ int __init omap4_pm_init(void) + + pr_info("Power Management for TI OMAP4+ devices.\n"); + ++ /* ++ * OMAP4 chip PM currently works only with certain (newer) ++ * versions of bootloaders. This is due to missing code in the ++ * kernel to properly reset and initialize some devices. ++ * http://www.spinics.net/lists/arm-kernel/msg218641.html ++ */ ++ if (cpu_is_omap44xx()) ++ pr_warn("OMAP4 PM: u-boot >= v2012.07 is required for full PM support\n"); ++ + ret = pwrdm_for_each(pwrdms_setup, NULL); + if (ret) { + pr_err("Failed to setup powerdomains.\n"); +diff --git a/arch/arm/mach-omap2/soc.h b/arch/arm/mach-omap2/soc.h +index 076bd90..8a9be09 100644 +--- a/arch/arm/mach-omap2/soc.h ++++ b/arch/arm/mach-omap2/soc.h +@@ -245,6 +245,8 @@ IS_AM_SUBCLASS(437x, 0x437) + #define soc_is_omap54xx() 0 + #define soc_is_omap543x() 0 + #define soc_is_dra7xx() 0 ++#define soc_is_dra74x() 0 ++#define soc_is_dra72x() 0 + + #if defined(MULTI_OMAP2) + # if defined(CONFIG_ARCH_OMAP2) +@@ -393,7 +395,11 @@ IS_OMAP_TYPE(3430, 0x3430) + + #if defined(CONFIG_SOC_DRA7XX) + #undef soc_is_dra7xx ++#undef soc_is_dra74x ++#undef soc_is_dra72x + #define soc_is_dra7xx() (of_machine_is_compatible("ti,dra7")) ++#define soc_is_dra74x() (of_machine_is_compatible("ti,dra74")) ++#define soc_is_dra72x() (of_machine_is_compatible("ti,dra72")) + #endif + + /* Various silicon revisions for omap2 */ +diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c +index 74044aa..73d80b8 100644 +--- a/arch/arm/mach-omap2/timer.c ++++ b/arch/arm/mach-omap2/timer.c +@@ -513,11 +513,11 @@ static void __init realtime_counter_init(void) + rate = clk_get_rate(sys_clk); + /* Numerator/denumerator values refer TRM Realtime Counter section */ + switch (rate) { +- case 1200000: ++ case 12000000: + num = 64; + den = 125; + break; +- case 1300000: ++ case 13000000: + num = 768; + den = 1625; + break; +@@ -529,11 +529,11 @@ static void __init realtime_counter_init(void) + num = 192; + den = 625; + break; +- case 2600000: ++ case 26000000: + num = 384; + den = 1625; + break; +- case 2700000: ++ case 27000000: + num = 256; + den = 1125; + break; +diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c +index f162f1b..82fd9dd 100644 +--- a/arch/arm/mach-pxa/corgi.c ++++ b/arch/arm/mach-pxa/corgi.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -711,6 +712,8 @@ static void __init corgi_init(void) + sharpsl_nand_partitions[1].size = 53 * 1024 * 1024; + + platform_add_devices(devices, ARRAY_SIZE(devices)); ++ ++ regulator_has_full_constraints(); + } + + static void __init fixup_corgi(struct tag *tags, char **cmdline, +diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c +index a7c30eb..007fd8a 100644 +--- a/arch/arm/mach-pxa/hx4700.c ++++ b/arch/arm/mach-pxa/hx4700.c +@@ -892,6 +892,8 @@ static void __init hx4700_init(void) + mdelay(10); + gpio_set_value(GPIO71_HX4700_ASIC3_nRESET, 1); + mdelay(10); ++ ++ regulator_has_full_constraints(); + } + + MACHINE_START(H4700, "HP iPAQ HX4700") +diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c +index aedf053..b4fff29 100644 +--- a/arch/arm/mach-pxa/poodle.c ++++ b/arch/arm/mach-pxa/poodle.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -454,6 +455,7 @@ static void __init poodle_init(void) + pxa_set_i2c_info(NULL); + i2c_register_board_info(0, ARRAY_AND_SIZE(poodle_i2c_devices)); + poodle_init_spi(); ++ regulator_has_full_constraints(); + } + + static void __init fixup_poodle(struct tag *tags, char **cmdline, +diff --git a/arch/arm/mach-realview/include/mach/memory.h b/arch/arm/mach-realview/include/mach/memory.h +index 2022e09..db09170 100644 +--- a/arch/arm/mach-realview/include/mach/memory.h ++++ b/arch/arm/mach-realview/include/mach/memory.h +@@ -56,6 +56,8 @@ + #define PAGE_OFFSET1 (PAGE_OFFSET + 0x10000000) + #define PAGE_OFFSET2 (PAGE_OFFSET + 0x30000000) + ++#define PHYS_OFFSET PLAT_PHYS_OFFSET ++ + #define __phys_to_virt(phys) \ + ((phys) >= 0x80000000 ? (phys) - 0x80000000 + PAGE_OFFSET2 : \ + (phys) >= 0x20000000 ? (phys) - 0x20000000 + PAGE_OFFSET1 : \ +diff --git a/arch/arm/mach-s3c64xx/crag6410.h b/arch/arm/mach-s3c64xx/crag6410.h +index 7bc6668..dcbe17f 100644 +--- a/arch/arm/mach-s3c64xx/crag6410.h ++++ b/arch/arm/mach-s3c64xx/crag6410.h +@@ -14,6 +14,7 @@ + #include + + #define GLENFARCLAS_PMIC_IRQ_BASE IRQ_BOARD_START ++#define BANFF_PMIC_IRQ_BASE (IRQ_BOARD_START + 64) + + #define PCA935X_GPIO_BASE GPIO_BOARD_START + #define CODEC_GPIO_BASE (GPIO_BOARD_START + 8) +diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c +index 3df3c37..66b95c4 100644 +--- a/arch/arm/mach-s3c64xx/mach-crag6410.c ++++ b/arch/arm/mach-s3c64xx/mach-crag6410.c +@@ -555,6 +555,7 @@ static struct wm831x_touch_pdata touch_pdata = { + + static struct wm831x_pdata crag_pmic_pdata = { + .wm831x_num = 1, ++ .irq_base = BANFF_PMIC_IRQ_BASE, + .gpio_base = BANFF_PMIC_GPIO_BASE, + .soft_shutdown = true, + +diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c +index 6645d1e..34853d5 100644 +--- a/arch/arm/mach-sa1100/pm.c ++++ b/arch/arm/mach-sa1100/pm.c +@@ -81,6 +81,7 @@ static int sa11x0_pm_enter(suspend_state_t state) + /* + * Ensure not to come back here if it wasn't intended + */ ++ RCSR = RCSR_SMR; + PSPR = 0; + + /* +diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c +index f74ab53..2b73c8a 100644 +--- a/arch/arm/mach-shmobile/setup-sh73a0.c ++++ b/arch/arm/mach-shmobile/setup-sh73a0.c +@@ -617,6 +617,7 @@ static struct platform_device ipmmu_device = { + + static struct renesas_intc_irqpin_config irqpin0_platform_data = { + .irq_base = irq_pin(0), /* IRQ0 -> IRQ7 */ ++ .control_parent = true, + }; + + static struct resource irqpin0_resources[] = { +@@ -678,6 +679,7 @@ static struct platform_device irqpin1_device = { + + static struct renesas_intc_irqpin_config irqpin2_platform_data = { + .irq_base = irq_pin(16), /* IRQ16 -> IRQ23 */ ++ .control_parent = true, + }; + + static struct resource irqpin2_resources[] = { +@@ -708,6 +710,7 @@ static struct platform_device irqpin2_device = { + + static struct renesas_intc_irqpin_config irqpin3_platform_data = { + .irq_base = irq_pin(24), /* IRQ24 -> IRQ31 */ ++ .control_parent = true, + }; + + static struct resource irqpin3_resources[] = { +diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile +index d939720..27b168f 100644 +--- a/arch/arm/mach-sunxi/Makefile ++++ b/arch/arm/mach-sunxi/Makefile +@@ -1,2 +1,2 @@ + obj-$(CONFIG_ARCH_SUNXI) += sunxi.o +-obj-$(CONFIG_SMP) += platsmp.o headsmp.o ++obj-$(CONFIG_SMP) += platsmp.o +diff --git a/arch/arm/mach-sunxi/headsmp.S b/arch/arm/mach-sunxi/headsmp.S +deleted file mode 100644 +index a10d494..0000000 +--- a/arch/arm/mach-sunxi/headsmp.S ++++ /dev/null +@@ -1,9 +0,0 @@ +-#include +-#include +- +- .section ".text.head", "ax" +- +-ENTRY(sun6i_secondary_startup) +- msr cpsr_fsxc, #0xd3 +- b secondary_startup +-ENDPROC(sun6i_secondary_startup) +diff --git a/arch/arm/mach-sunxi/platsmp.c b/arch/arm/mach-sunxi/platsmp.c +index 7b141d8..0c7dbce 100644 +--- a/arch/arm/mach-sunxi/platsmp.c ++++ b/arch/arm/mach-sunxi/platsmp.c +@@ -82,7 +82,7 @@ static int sun6i_smp_boot_secondary(unsigned int cpu, + spin_lock(&cpu_lock); + + /* Set CPU boot address */ +- writel(virt_to_phys(sun6i_secondary_startup), ++ writel(virt_to_phys(secondary_startup), + cpucfg_membase + CPUCFG_PRIVATE0_REG); + + /* Assert the CPU core in reset */ +diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S +index 578d4d1..6448324 100644 +--- a/arch/arm/mach-tegra/reset-handler.S ++++ b/arch/arm/mach-tegra/reset-handler.S +@@ -50,6 +50,7 @@ ENTRY(tegra_resume) + THUMB( it ne ) + bne cpu_resume @ no + ++ tegra_get_soc_id TEGRA_APB_MISC_BASE, r6 + /* Are we on Tegra20? */ + cmp r6, #TEGRA20 + beq 1f @ Yes +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index 118d691..57b9650 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -798,6 +798,7 @@ config NEED_KUSER_HELPERS + + config KUSER_HELPERS + bool "Enable kuser helpers in vector page" if !NEED_KUSER_HELPERS ++ depends on MMU + default y + help + Warning: disabling this option may break user programs. +diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S +index 3815a82..8c48c5c 100644 +--- a/arch/arm/mm/abort-ev6.S ++++ b/arch/arm/mm/abort-ev6.S +@@ -17,12 +17,6 @@ + */ + .align 5 + ENTRY(v6_early_abort) +-#ifdef CONFIG_CPU_V6 +- sub r1, sp, #4 @ Get unused stack location +- strex r0, r1, [r1] @ Clear the exclusive monitor +-#elif defined(CONFIG_CPU_32v6K) +- clrex +-#endif + mrc p15, 0, r1, c5, c0, 0 @ get FSR + mrc p15, 0, r0, c6, c0, 0 @ get FAR + /* +diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S +index 7033752..4812ad0 100644 +--- a/arch/arm/mm/abort-ev7.S ++++ b/arch/arm/mm/abort-ev7.S +@@ -13,12 +13,6 @@ + */ + .align 5 + ENTRY(v7_early_abort) +- /* +- * The effect of data aborts on on the exclusive access monitor are +- * UNPREDICTABLE. Do a CLREX to clear the state +- */ +- clrex +- + mrc p15, 0, r1, c5, c0, 0 @ get FSR + mrc p15, 0, r0, c6, c0, 0 @ get FAR + +diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c +index 9240364..d301662 100644 +--- a/arch/arm/mm/alignment.c ++++ b/arch/arm/mm/alignment.c +@@ -40,6 +40,7 @@ + * This code is not portable to processors with late data abort handling. + */ + #define CODING_BITS(i) (i & 0x0e000000) ++#define COND_BITS(i) (i & 0xf0000000) + + #define LDST_I_BIT(i) (i & (1 << 26)) /* Immediate constant */ + #define LDST_P_BIT(i) (i & (1 << 24)) /* Preindex */ +@@ -817,6 +818,8 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) + break; + + case 0x04000000: /* ldr or str immediate */ ++ if (COND_BITS(instr) == 0xf0000000) /* NEON VLDn, VSTn */ ++ goto bad; + offset.un = OFFSET_BITS(instr); + handler = do_alignment_ldrstr; + break; +diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c +index 6eb97b3..4370933 100644 +--- a/arch/arm/mm/context.c ++++ b/arch/arm/mm/context.c +@@ -144,21 +144,17 @@ static void flush_context(unsigned int cpu) + /* Update the list of reserved ASIDs and the ASID bitmap. */ + bitmap_clear(asid_map, 0, NUM_USER_ASIDS); + for_each_possible_cpu(i) { +- if (i == cpu) { +- asid = 0; +- } else { +- asid = atomic64_xchg(&per_cpu(active_asids, i), 0); +- /* +- * If this CPU has already been through a +- * rollover, but hasn't run another task in +- * the meantime, we must preserve its reserved +- * ASID, as this is the only trace we have of +- * the process it is still running. +- */ +- if (asid == 0) +- asid = per_cpu(reserved_asids, i); +- __set_bit(asid & ~ASID_MASK, asid_map); +- } ++ asid = atomic64_xchg(&per_cpu(active_asids, i), 0); ++ /* ++ * If this CPU has already been through a ++ * rollover, but hasn't run another task in ++ * the meantime, we must preserve its reserved ++ * ASID, as this is the only trace we have of ++ * the process it is still running. ++ */ ++ if (asid == 0) ++ asid = per_cpu(reserved_asids, i); ++ __set_bit(asid & ~ASID_MASK, asid_map); + per_cpu(reserved_asids, i) = asid; + } + +diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c +index a810425..fae192b 100644 +--- a/arch/arm/mm/dma-mapping.c ++++ b/arch/arm/mm/dma-mapping.c +@@ -465,12 +465,21 @@ void __init dma_contiguous_remap(void) + map.type = MT_MEMORY_DMA_READY; + + /* +- * Clear previous low-memory mapping ++ * Clear previous low-memory mapping to ensure that the ++ * TLB does not see any conflicting entries, then flush ++ * the TLB of the old entries before creating new mappings. ++ * ++ * This ensures that any speculatively loaded TLB entries ++ * (even though they may be rare) can not cause any problems, ++ * and ensures that this code is architecturally compliant. + */ + for (addr = __phys_to_virt(start); addr < __phys_to_virt(end); + addr += PMD_SIZE) + pmd_clear(pmd_off_k(addr)); + ++ flush_tlb_kernel_range(__phys_to_virt(start), ++ __phys_to_virt(end)); ++ + iotable_init(&map, 1); + } + } +diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c +index 8e0e52e..d7a0ee8 100644 +--- a/arch/arm/mm/idmap.c ++++ b/arch/arm/mm/idmap.c +@@ -25,6 +25,13 @@ static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, + pr_warning("Failed to allocate identity pmd.\n"); + return; + } ++ /* ++ * Copy the original PMD to ensure that the PMD entries for ++ * the kernel image are preserved. ++ */ ++ if (!pud_none(*pud)) ++ memcpy(pmd, pmd_offset(pud, 0), ++ PTRS_PER_PMD * sizeof(pmd_t)); + pud_populate(&init_mm, pud, pmd); + pmd += pmd_index(addr); + } else +diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c +index b68c6b2..f15c22e 100644 +--- a/arch/arm/mm/mmu.c ++++ b/arch/arm/mm/mmu.c +@@ -1436,8 +1436,8 @@ void __init early_paging_init(const struct machine_desc *mdesc, + return; + + /* remap kernel code and data */ +- map_start = init_mm.start_code; +- map_end = init_mm.brk; ++ map_start = init_mm.start_code & PMD_MASK; ++ map_end = ALIGN(init_mm.brk, PMD_SIZE); + + /* get a handle on things... */ + pgd0 = pgd_offset_k(0); +@@ -1472,7 +1472,7 @@ void __init early_paging_init(const struct machine_desc *mdesc, + } + + /* remap pmds for kernel mapping */ +- phys = __pa(map_start) & PMD_MASK; ++ phys = __pa(map_start); + do { + *pmdk++ = __pmd(phys | pmdprot); + phys += PMD_SIZE; +diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S +index 22e3ad6..eb81123 100644 +--- a/arch/arm/mm/proc-v7-3level.S ++++ b/arch/arm/mm/proc-v7-3level.S +@@ -86,8 +86,13 @@ ENTRY(cpu_v7_set_pte_ext) + tst rh, #1 << (57 - 32) @ L_PTE_NONE + bicne rl, #L_PTE_VALID + bne 1f +- tst rh, #1 << (55 - 32) @ L_PTE_DIRTY +- orreq rl, #L_PTE_RDONLY ++ ++ eor ip, rh, #1 << (55 - 32) @ toggle L_PTE_DIRTY in temp reg to ++ @ test for !L_PTE_DIRTY || L_PTE_RDONLY ++ tst ip, #1 << (55 - 32) | 1 << (58 - 32) ++ orrne rl, #PTE_AP2 ++ biceq rl, #PTE_AP2 ++ + 1: strd r2, r3, [r0] + ALT_SMP(W(nop)) + ALT_UP (mcr p15, 0, r0, c7, c10, 1) @ flush_pte +diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S +index 158b875..bf7487d 100644 +--- a/arch/arm/mm/proc-v7.S ++++ b/arch/arm/mm/proc-v7.S +@@ -211,7 +211,6 @@ __v7_pj4b_setup: + /* Auxiliary Debug Modes Control 1 Register */ + #define PJ4B_STATIC_BP (1 << 2) /* Enable Static BP */ + #define PJ4B_INTER_PARITY (1 << 8) /* Disable Internal Parity Handling */ +-#define PJ4B_BCK_OFF_STREX (1 << 5) /* Enable the back off of STREX instr */ + #define PJ4B_CLEAN_LINE (1 << 16) /* Disable data transfer for clean line */ + + /* Auxiliary Debug Modes Control 2 Register */ +@@ -234,7 +233,6 @@ __v7_pj4b_setup: + /* Auxiliary Debug Modes Control 1 Register */ + mrc p15, 1, r0, c15, c1, 1 + orr r0, r0, #PJ4B_CLEAN_LINE +- orr r0, r0, #PJ4B_BCK_OFF_STREX + orr r0, r0, #PJ4B_INTER_PARITY + bic r0, r0, #PJ4B_STATIC_BP + mcr p15, 1, r0, c15, c1, 1 +diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S +index d19b1cf..b34b95f 100644 +--- a/arch/arm/mm/proc-xscale.S ++++ b/arch/arm/mm/proc-xscale.S +@@ -535,7 +535,7 @@ ENTRY(cpu_xscale_do_suspend) + mrc p15, 0, r5, c15, c1, 0 @ CP access reg + mrc p15, 0, r6, c13, c0, 0 @ PID + mrc p15, 0, r7, c3, c0, 0 @ domain ID +- mrc p15, 0, r8, c1, c1, 0 @ auxiliary control reg ++ mrc p15, 0, r8, c1, c0, 1 @ auxiliary control reg + mrc p15, 0, r9, c1, c0, 0 @ control reg + bic r4, r4, #2 @ clear frequency change bit + stmia r0, {r4 - r9} @ store cp regs +@@ -552,7 +552,7 @@ ENTRY(cpu_xscale_do_resume) + mcr p15, 0, r6, c13, c0, 0 @ PID + mcr p15, 0, r7, c3, c0, 0 @ domain ID + mcr p15, 0, r1, c2, c0, 0 @ translation table base addr +- mcr p15, 0, r8, c1, c1, 0 @ auxiliary control reg ++ mcr p15, 0, r8, c1, c0, 1 @ auxiliary control reg + mov r0, r9 @ control register + b cpu_resume_mmu + ENDPROC(cpu_xscale_do_resume) +diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c +index 271b5e9..6adf591 100644 +--- a/arch/arm/net/bpf_jit_32.c ++++ b/arch/arm/net/bpf_jit_32.c +@@ -449,10 +449,21 @@ static inline void emit_udiv(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx) + return; + } + #endif +- if (rm != ARM_R0) +- emit(ARM_MOV_R(ARM_R0, rm), ctx); ++ ++ /* ++ * For BPF_ALU | BPF_DIV | BPF_K instructions, rm is ARM_R4 ++ * (r_A) and rn is ARM_R0 (r_scratch) so load rn first into ++ * ARM_R1 to avoid accidentally overwriting ARM_R0 with rm ++ * before using it as a source for ARM_R1. ++ * ++ * For BPF_ALU | BPF_DIV | BPF_X rm is ARM_R4 (r_A) and rn is ++ * ARM_R5 (r_X) so there is no particular register overlap ++ * issues. ++ */ + if (rn != ARM_R1) + emit(ARM_MOV_R(ARM_R1, rn), ctx); ++ if (rm != ARM_R0) ++ emit(ARM_MOV_R(ARM_R0, rm), ctx); + + ctx->seen |= SEEN_CALL; + emit_mov_i(ARM_R3, (u32)jit_udiv, ctx); +diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h +index 253e33b..56de5aa 100644 +--- a/arch/arm64/include/asm/compat.h ++++ b/arch/arm64/include/asm/compat.h +@@ -37,8 +37,8 @@ typedef s32 compat_ssize_t; + typedef s32 compat_time_t; + typedef s32 compat_clock_t; + typedef s32 compat_pid_t; +-typedef u32 __compat_uid_t; +-typedef u32 __compat_gid_t; ++typedef u16 __compat_uid_t; ++typedef u16 __compat_gid_t; + typedef u16 __compat_uid16_t; + typedef u16 __compat_gid16_t; + typedef u32 __compat_uid32_t; +diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h +index c404fb0..64bc6c6 100644 +--- a/arch/arm64/include/asm/cputype.h ++++ b/arch/arm64/include/asm/cputype.h +@@ -77,6 +77,8 @@ static inline u32 __attribute_const__ read_cpuid_cachetype(void) + return read_cpuid(CTR_EL0); + } + ++void cpuinfo_store_cpu(void); ++ + #endif /* __ASSEMBLY__ */ + + #endif +diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h +index d064047..52b484b 100644 +--- a/arch/arm64/include/asm/hw_breakpoint.h ++++ b/arch/arm64/include/asm/hw_breakpoint.h +@@ -79,7 +79,6 @@ static inline void decode_ctrl_reg(u32 reg, + */ + #define ARM_MAX_BRP 16 + #define ARM_MAX_WRP 16 +-#define ARM_MAX_HBP_SLOTS (ARM_MAX_BRP + ARM_MAX_WRP) + + /* Virtual debug register bases. */ + #define AARCH64_DBG_REG_BVR 0 +diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h +index 024c461..0ad7351 100644 +--- a/arch/arm64/include/asm/hwcap.h ++++ b/arch/arm64/include/asm/hwcap.h +@@ -30,6 +30,7 @@ + #define COMPAT_HWCAP_IDIVA (1 << 17) + #define COMPAT_HWCAP_IDIVT (1 << 18) + #define COMPAT_HWCAP_IDIV (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT) ++#define COMPAT_HWCAP_LPAE (1 << 20) + #define COMPAT_HWCAP_EVTSTRM (1 << 21) + + #define COMPAT_HWCAP2_AES (1 << 0) +diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h +index 0eb3986..ea68925 100644 +--- a/arch/arm64/include/asm/kvm_arm.h ++++ b/arch/arm64/include/asm/kvm_arm.h +@@ -18,6 +18,7 @@ + #ifndef __ARM64_KVM_ARM_H__ + #define __ARM64_KVM_ARM_H__ + ++#include + #include + + /* Hyp Configuration Register (HCR) bits */ +@@ -62,6 +63,7 @@ + * RW: 64bit by default, can be overriden for 32bit VMs + * TAC: Trap ACTLR + * TSC: Trap SMC ++ * TVM: Trap VM ops (until M+C set in SCTLR_EL1) + * TSW: Trap cache operations by set/way + * TWE: Trap WFE + * TWI: Trap WFI +@@ -74,7 +76,7 @@ + * SWIO: Turn set/way invalidates into set/way clean+invalidate + */ + #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \ +- HCR_BSU_IS | HCR_FB | HCR_TAC | \ ++ HCR_TVM | HCR_BSU_IS | HCR_FB | HCR_TAC | \ + HCR_AMO | HCR_IMO | HCR_FMO | \ + HCR_SWIO | HCR_TIDCP | HCR_RW) + #define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF) +@@ -121,6 +123,17 @@ + #define VTCR_EL2_T0SZ_MASK 0x3f + #define VTCR_EL2_T0SZ_40B 24 + ++/* ++ * We configure the Stage-2 page tables to always restrict the IPA space to be ++ * 40 bits wide (T0SZ = 24). Systems with a PARange smaller than 40 bits are ++ * not known to exist and will break with this configuration. ++ * ++ * Note that when using 4K pages, we concatenate two first level page tables ++ * together. ++ * ++ * The magic numbers used for VTTBR_X in this patch can be found in Tables ++ * D4-23 and D4-25 in ARM DDI 0487A.b. ++ */ + #ifdef CONFIG_ARM64_64K_PAGES + /* + * Stage2 translation configuration: +@@ -150,9 +163,9 @@ + #endif + + #define VTTBR_BADDR_SHIFT (VTTBR_X - 1) +-#define VTTBR_BADDR_MASK (((1LLU << (40 - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT) +-#define VTTBR_VMID_SHIFT (48LLU) +-#define VTTBR_VMID_MASK (0xffLLU << VTTBR_VMID_SHIFT) ++#define VTTBR_BADDR_MASK (((UL(1) << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT) ++#define VTTBR_VMID_SHIFT (UL(48)) ++#define VTTBR_VMID_MASK (UL(0xFF) << VTTBR_VMID_SHIFT) + + /* Hyp System Trap Register */ + #define HSTR_EL2_TTEE (1 << 16) +@@ -175,13 +188,13 @@ + + /* Exception Syndrome Register (ESR) bits */ + #define ESR_EL2_EC_SHIFT (26) +-#define ESR_EL2_EC (0x3fU << ESR_EL2_EC_SHIFT) +-#define ESR_EL2_IL (1U << 25) ++#define ESR_EL2_EC (UL(0x3f) << ESR_EL2_EC_SHIFT) ++#define ESR_EL2_IL (UL(1) << 25) + #define ESR_EL2_ISS (ESR_EL2_IL - 1) + #define ESR_EL2_ISV_SHIFT (24) +-#define ESR_EL2_ISV (1U << ESR_EL2_ISV_SHIFT) ++#define ESR_EL2_ISV (UL(1) << ESR_EL2_ISV_SHIFT) + #define ESR_EL2_SAS_SHIFT (22) +-#define ESR_EL2_SAS (3U << ESR_EL2_SAS_SHIFT) ++#define ESR_EL2_SAS (UL(3) << ESR_EL2_SAS_SHIFT) + #define ESR_EL2_SSE (1 << 21) + #define ESR_EL2_SRT_SHIFT (16) + #define ESR_EL2_SRT_MASK (0x1f << ESR_EL2_SRT_SHIFT) +@@ -195,16 +208,16 @@ + #define ESR_EL2_FSC_TYPE (0x3c) + + #define ESR_EL2_CV_SHIFT (24) +-#define ESR_EL2_CV (1U << ESR_EL2_CV_SHIFT) ++#define ESR_EL2_CV (UL(1) << ESR_EL2_CV_SHIFT) + #define ESR_EL2_COND_SHIFT (20) +-#define ESR_EL2_COND (0xfU << ESR_EL2_COND_SHIFT) ++#define ESR_EL2_COND (UL(0xf) << ESR_EL2_COND_SHIFT) + + + #define FSC_FAULT (0x04) + #define FSC_PERM (0x0c) + + /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */ +-#define HPFAR_MASK (~0xFUL) ++#define HPFAR_MASK (~UL(0xf)) + + #define ESR_EL2_EC_UNKNOWN (0x00) + #define ESR_EL2_EC_WFI (0x01) +diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h +index b25763b..9fcd54b 100644 +--- a/arch/arm64/include/asm/kvm_asm.h ++++ b/arch/arm64/include/asm/kvm_asm.h +@@ -79,7 +79,8 @@ + #define c13_TID_URW (TPIDR_EL0 * 2) /* Thread ID, User R/W */ + #define c13_TID_URO (TPIDRRO_EL0 * 2)/* Thread ID, User R/O */ + #define c13_TID_PRIV (TPIDR_EL1 * 2) /* Thread ID, Privileged */ +-#define c10_AMAIR (AMAIR_EL1 * 2) /* Aux Memory Attr Indirection Reg */ ++#define c10_AMAIR0 (AMAIR_EL1 * 2) /* Aux Memory Attr Indirection Reg */ ++#define c10_AMAIR1 (c10_AMAIR0 + 1)/* Aux Memory Attr Indirection Reg */ + #define c14_CNTKCTL (CNTKCTL_EL1 * 2) /* Timer Control Register (PL1) */ + #define NR_CP15_REGS (NR_SYS_REGS * 2) + +diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h +index dd8ecfc..91f33c2 100644 +--- a/arch/arm64/include/asm/kvm_emulate.h ++++ b/arch/arm64/include/asm/kvm_emulate.h +@@ -38,6 +38,13 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu); + void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr); + void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr); + ++static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) ++{ ++ vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; ++ if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) ++ vcpu->arch.hcr_el2 &= ~HCR_RW; ++} ++ + static inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu) + { + return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pc; +diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h +index 0a1d697..3fb0946 100644 +--- a/arch/arm64/include/asm/kvm_host.h ++++ b/arch/arm64/include/asm/kvm_host.h +@@ -42,7 +42,7 @@ + #define KVM_VCPU_MAX_FEATURES 2 + + struct kvm_vcpu; +-int kvm_target_cpu(void); ++int __attribute_const__ kvm_target_cpu(void); + int kvm_reset_vcpu(struct kvm_vcpu *vcpu); + int kvm_arch_dev_ioctl_check_extension(long ext); + +@@ -177,7 +177,7 @@ static inline int kvm_test_age_hva(struct kvm *kvm, unsigned long hva) + } + + struct kvm_vcpu *kvm_arm_get_running_vcpu(void); +-struct kvm_vcpu __percpu **kvm_get_running_vcpus(void); ++struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void); + + u64 kvm_call_hyp(void *hypfn, ...); + +diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h +index 7f1f940..15a8a86 100644 +--- a/arch/arm64/include/asm/kvm_mmu.h ++++ b/arch/arm64/include/asm/kvm_mmu.h +@@ -59,10 +59,9 @@ + #define KERN_TO_HYP(kva) ((unsigned long)kva - PAGE_OFFSET + HYP_PAGE_OFFSET) + + /* +- * Align KVM with the kernel's view of physical memory. Should be +- * 40bit IPA, with PGD being 8kB aligned in the 4KB page configuration. ++ * We currently only support a 40bit IPA. + */ +-#define KVM_PHYS_SHIFT PHYS_MASK_SHIFT ++#define KVM_PHYS_SHIFT (40) + #define KVM_PHYS_SIZE (1UL << KVM_PHYS_SHIFT) + #define KVM_PHYS_MASK (KVM_PHYS_SIZE - 1UL) + +@@ -70,11 +69,14 @@ + #define PTRS_PER_S2_PGD (1 << (KVM_PHYS_SHIFT - PGDIR_SHIFT)) + #define S2_PGD_ORDER get_order(PTRS_PER_S2_PGD * sizeof(pgd_t)) + ++#define kvm_pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1)) ++ + int create_hyp_mappings(void *from, void *to); + int create_hyp_io_mappings(void *from, void *to, phys_addr_t); + void free_boot_hyp_pgd(void); + void free_hyp_pgds(void); + ++void stage2_unmap_vm(struct kvm *kvm); + int kvm_alloc_stage2_pgd(struct kvm *kvm); + void kvm_free_stage2_pgd(struct kvm *kvm); + int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, +@@ -93,20 +95,6 @@ void kvm_clear_hyp_idmap(void); + #define kvm_set_pte(ptep, pte) set_pte(ptep, pte) + #define kvm_set_pmd(pmdp, pmd) set_pmd(pmdp, pmd) + +-static inline bool kvm_is_write_fault(unsigned long esr) +-{ +- unsigned long esr_ec = esr >> ESR_EL2_EC_SHIFT; +- +- if (esr_ec == ESR_EL2_EC_IABT) +- return false; +- +- if ((esr & ESR_EL2_ISV) && !(esr & ESR_EL2_WNR)) +- return false; +- +- return true; +-} +- +-static inline void kvm_clean_dcache_area(void *addr, size_t size) {} + static inline void kvm_clean_pgd(pgd_t *pgd) {} + static inline void kvm_clean_pmd_entry(pmd_t *pmd) {} + static inline void kvm_clean_pte(pte_t *pte) {} +@@ -122,11 +110,40 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd) + pmd_val(*pmd) |= PMD_S2_RDWR; + } + ++#define kvm_pgd_addr_end(addr, end) pgd_addr_end(addr, end) ++#define kvm_pud_addr_end(addr, end) pud_addr_end(addr, end) ++#define kvm_pmd_addr_end(addr, end) pmd_addr_end(addr, end) ++ ++static inline bool kvm_page_empty(void *ptr) ++{ ++ struct page *ptr_page = virt_to_page(ptr); ++ return page_count(ptr_page) == 1; ++} ++ ++#define kvm_pte_table_empty(ptep) kvm_page_empty(ptep) ++#ifndef CONFIG_ARM64_64K_PAGES ++#define kvm_pmd_table_empty(pmdp) kvm_page_empty(pmdp) ++#else ++#define kvm_pmd_table_empty(pmdp) (0) ++#endif ++#define kvm_pud_table_empty(pudp) (0) ++ ++ + struct kvm; + +-static inline void coherent_icache_guest_page(struct kvm *kvm, hva_t hva, +- unsigned long size) ++#define kvm_flush_dcache_to_poc(a,l) __flush_dcache_area((a), (l)) ++ ++static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu) + { ++ return (vcpu_sys_reg(vcpu, SCTLR_EL1) & 0b101) == 0b101; ++} ++ ++static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva, ++ unsigned long size) ++{ ++ if (!vcpu_has_cache_enabled(vcpu)) ++ kvm_flush_dcache_to_poc((void *)hva, size); ++ + if (!icache_is_aliasing()) { /* PIPT */ + flush_icache_range(hva, hva + size); + } else if (!icache_is_aivivt()) { /* non ASID-tagged VIVT */ +@@ -135,8 +152,9 @@ static inline void coherent_icache_guest_page(struct kvm *kvm, hva_t hva, + } + } + +-#define kvm_flush_dcache_to_poc(a,l) __flush_dcache_area((a), (l)) + #define kvm_virt_to_phys(x) __virt_to_phys((unsigned long)(x)) + ++void stage2_flush_vm(struct kvm *kvm); ++ + #endif /* __ASSEMBLY__ */ + #endif /* __ARM64_KVM_MMU_H__ */ +diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h +index a9eee33..101a42b 100644 +--- a/arch/arm64/include/asm/mmu_context.h ++++ b/arch/arm64/include/asm/mmu_context.h +@@ -151,6 +151,15 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, + { + unsigned int cpu = smp_processor_id(); + ++ /* ++ * init_mm.pgd does not contain any user mappings and it is always ++ * active for kernel addresses in TTBR1. Just set the reserved TTBR0. ++ */ ++ if (next == &init_mm) { ++ cpu_set_reserved_ttbr0(); ++ return; ++ } ++ + if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) + check_and_switch_context(next, tsk); + } +diff --git a/arch/arm64/include/asm/suspend.h b/arch/arm64/include/asm/suspend.h +index e9c149c..456d67c 100644 +--- a/arch/arm64/include/asm/suspend.h ++++ b/arch/arm64/include/asm/suspend.h +@@ -21,6 +21,7 @@ struct sleep_save_sp { + phys_addr_t save_ptr_stash_phys; + }; + ++extern int __cpu_suspend(unsigned long arg, int (*fn)(unsigned long)); + extern void cpu_resume(void); + extern int cpu_suspend(unsigned long); + +diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c +index 92f3683..565e26f 100644 +--- a/arch/arm64/kernel/insn.c ++++ b/arch/arm64/kernel/insn.c +@@ -156,9 +156,10 @@ static int __kprobes aarch64_insn_patch_text_cb(void *arg) + * which ends with "dsb; isb" pair guaranteeing global + * visibility. + */ +- atomic_set(&pp->cpu_count, -1); ++ /* Notify other processors with an additional increment. */ ++ atomic_inc(&pp->cpu_count); + } else { +- while (atomic_read(&pp->cpu_count) != -1) ++ while (atomic_read(&pp->cpu_count) <= num_online_cpus()) + cpu_relax(); + isb(); + } +diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c +index 0f08dfd..dfa6e3e 100644 +--- a/arch/arm64/kernel/irq.c ++++ b/arch/arm64/kernel/irq.c +@@ -97,19 +97,15 @@ static bool migrate_one_irq(struct irq_desc *desc) + if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity)) + return false; + +- if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) ++ if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { ++ affinity = cpu_online_mask; + ret = true; ++ } + +- /* +- * when using forced irq_set_affinity we must ensure that the cpu +- * being offlined is not present in the affinity mask, it may be +- * selected as the target CPU otherwise +- */ +- affinity = cpu_online_mask; + c = irq_data_get_irq_chip(d); + if (!c->irq_set_affinity) + pr_debug("IRQ%u: unable to set affinity\n", d->irq); +- else if (c->irq_set_affinity(d, affinity, true) == IRQ_SET_MASK_OK && ret) ++ else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret) + cpumask_copy(d->affinity, affinity); + + return ret; +diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c +index fc8a387..98861d3 100644 +--- a/arch/arm64/kernel/process.c ++++ b/arch/arm64/kernel/process.c +@@ -188,9 +188,27 @@ void exit_thread(void) + { + } + ++static void tls_thread_flush(void) ++{ ++ asm ("msr tpidr_el0, xzr"); ++ ++ if (is_compat_task()) { ++ current->thread.tp_value = 0; ++ ++ /* ++ * We need to ensure ordering between the shadow state and the ++ * hardware state, so that we don't corrupt the hardware state ++ * with a stale shadow state during context switch. ++ */ ++ barrier(); ++ asm ("msr tpidrro_el0, xzr"); ++ } ++} ++ + void flush_thread(void) + { + fpsimd_flush_thread(); ++ tls_thread_flush(); + flush_ptrace_hw_breakpoint(current); + } + +diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c +index 7c8e809..8ba6b0f 100644 +--- a/arch/arm64/kernel/ptrace.c ++++ b/arch/arm64/kernel/ptrace.c +@@ -85,7 +85,8 @@ static void ptrace_hbptriggered(struct perf_event *bp, + break; + } + } +- for (i = ARM_MAX_BRP; i < ARM_MAX_HBP_SLOTS && !bp; ++i) { ++ ++ for (i = 0; i < ARM_MAX_WRP; ++i) { + if (current->thread.debug.hbp_watch[i] == bp) { + info.si_errno = -((i << 1) + 1); + break; +diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c +index e633c5e..4bc8d27 100644 +--- a/arch/arm64/kernel/setup.c ++++ b/arch/arm64/kernel/setup.c +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -67,13 +68,13 @@ EXPORT_SYMBOL_GPL(elf_hwcap); + COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\ + COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\ + COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\ +- COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV) ++ COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV|\ ++ COMPAT_HWCAP_LPAE) + unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT; + unsigned int compat_elf_hwcap2 __read_mostly; + #endif + + static const char *cpu_name; +-static const char *machine_name; + phys_addr_t __fdt_pointer __initdata; + + /* +@@ -193,6 +194,19 @@ static void __init smp_build_mpidr_hash(void) + } + #endif + ++struct cpuinfo_arm64 { ++ struct cpu cpu; ++ u32 reg_midr; ++}; ++ ++static DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data); ++ ++void cpuinfo_store_cpu(void) ++{ ++ struct cpuinfo_arm64 *info = this_cpu_ptr(&cpu_data); ++ info->reg_midr = read_cpuid_id(); ++} ++ + static void __init setup_processor(void) + { + struct cpu_info *cpu_info; +@@ -213,6 +227,8 @@ static void __init setup_processor(void) + sprintf(init_utsname()->machine, ELF_PLATFORM); + elf_hwcap = 0; + ++ cpuinfo_store_cpu(); ++ + /* + * ID_AA64ISAR0_EL1 contains 4-bit wide signed feature blocks. + * The blocks we test below represent incremental functionality +@@ -289,8 +305,6 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys) + while (true) + cpu_relax(); + } +- +- machine_name = of_flat_dt_get_machine_name(); + } + + /* +@@ -395,14 +409,12 @@ static int __init arm64_device_init(void) + } + arch_initcall_sync(arm64_device_init); + +-static DEFINE_PER_CPU(struct cpu, cpu_data); +- + static int __init topology_init(void) + { + int i; + + for_each_possible_cpu(i) { +- struct cpu *cpu = &per_cpu(cpu_data, i); ++ struct cpu *cpu = &per_cpu(cpu_data.cpu, i); + cpu->hotpluggable = 1; + register_cpu(cpu, i); + } +@@ -423,14 +435,41 @@ static const char *hwcap_str[] = { + NULL + }; + ++#ifdef CONFIG_COMPAT ++static const char *compat_hwcap_str[] = { ++ "swp", ++ "half", ++ "thumb", ++ "26bit", ++ "fastmult", ++ "fpa", ++ "vfp", ++ "edsp", ++ "java", ++ "iwmmxt", ++ "crunch", ++ "thumbee", ++ "neon", ++ "vfpv3", ++ "vfpv3d16", ++ "tls", ++ "vfpv4", ++ "idiva", ++ "idivt", ++ "vfpd32", ++ "lpae", ++ "evtstrm" ++}; ++#endif /* CONFIG_COMPAT */ ++ + static int c_show(struct seq_file *m, void *v) + { +- int i; +- +- seq_printf(m, "Processor\t: %s rev %d (%s)\n", +- cpu_name, read_cpuid_id() & 15, ELF_PLATFORM); ++ int i, j; + + for_each_online_cpu(i) { ++ struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i); ++ u32 midr = cpuinfo->reg_midr; ++ + /* + * glibc reads /proc/cpuinfo to determine the number of + * online processors, looking for lines beginning with +@@ -439,24 +478,33 @@ static int c_show(struct seq_file *m, void *v) + #ifdef CONFIG_SMP + seq_printf(m, "processor\t: %d\n", i); + #endif +- } +- +- /* dump out the processor features */ +- seq_puts(m, "Features\t: "); +- +- for (i = 0; hwcap_str[i]; i++) +- if (elf_hwcap & (1 << i)) +- seq_printf(m, "%s ", hwcap_str[i]); + +- seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24); +- seq_printf(m, "CPU architecture: AArch64\n"); +- seq_printf(m, "CPU variant\t: 0x%x\n", (read_cpuid_id() >> 20) & 15); +- seq_printf(m, "CPU part\t: 0x%03x\n", (read_cpuid_id() >> 4) & 0xfff); +- seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15); +- +- seq_puts(m, "\n"); ++ /* ++ * Dump out the common processor features in a single line. ++ * Userspace should read the hwcaps with getauxval(AT_HWCAP) ++ * rather than attempting to parse this, but there's a body of ++ * software which does already (at least for 32-bit). ++ */ ++ seq_puts(m, "Features\t:"); ++ if (personality(current->personality) == PER_LINUX32) { ++#ifdef CONFIG_COMPAT ++ for (j = 0; compat_hwcap_str[j]; j++) ++ if (compat_elf_hwcap & (1 << j)) ++ seq_printf(m, " %s", compat_hwcap_str[j]); ++#endif /* CONFIG_COMPAT */ ++ } else { ++ for (j = 0; hwcap_str[j]; j++) ++ if (elf_hwcap & (1 << j)) ++ seq_printf(m, " %s", hwcap_str[j]); ++ } ++ seq_puts(m, "\n"); + +- seq_printf(m, "Hardware\t: %s\n", machine_name); ++ seq_printf(m, "CPU implementer\t: 0x%02x\n", (midr >> 24)); ++ seq_printf(m, "CPU architecture: 8\n"); ++ seq_printf(m, "CPU variant\t: 0x%x\n", ((midr >> 20) & 0xf)); ++ seq_printf(m, "CPU part\t: 0x%03x\n", ((midr >> 4) & 0xfff)); ++ seq_printf(m, "CPU revision\t: %d\n\n", (midr & 0xf)); ++ } + + return 0; + } +diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c +index b3fc9f5..a966bac 100644 +--- a/arch/arm64/kernel/signal32.c ++++ b/arch/arm64/kernel/signal32.c +@@ -151,8 +151,7 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) + case __SI_TIMER: + err |= __put_user(from->si_tid, &to->si_tid); + err |= __put_user(from->si_overrun, &to->si_overrun); +- err |= __put_user((compat_uptr_t)(unsigned long)from->si_ptr, +- &to->si_ptr); ++ err |= __put_user(from->si_int, &to->si_int); + break; + case __SI_POLL: + err |= __put_user(from->si_band, &to->si_band); +@@ -166,7 +165,8 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) + * Other callers might not initialize the si_lsb field, + * so check explicitely for the right codes here. + */ +- if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO) ++ if (from->si_signo == SIGBUS && ++ (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)) + err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb); + #endif + break; +@@ -181,7 +181,7 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) + case __SI_MESGQ: /* But this is */ + err |= __put_user(from->si_pid, &to->si_pid); + err |= __put_user(from->si_uid, &to->si_uid); +- err |= __put_user((compat_uptr_t)(unsigned long)from->si_ptr, &to->si_ptr); ++ err |= __put_user(from->si_int, &to->si_int); + break; + default: /* this is just in case for now ... */ + err |= __put_user(from->si_pid, &to->si_pid); +@@ -193,8 +193,6 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) + + int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) + { +- memset(to, 0, sizeof *to); +- + if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) || + copy_from_user(to->_sifields._pad, + from->_sifields._pad, SI_PAD_SIZE)) +diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S +index b192572..ede186c 100644 +--- a/arch/arm64/kernel/sleep.S ++++ b/arch/arm64/kernel/sleep.S +@@ -49,28 +49,39 @@ + orr \dst, \dst, \mask // dst|=(aff3>>rs3) + .endm + /* +- * Save CPU state for a suspend. This saves callee registers, and allocates +- * space on the kernel stack to save the CPU specific registers + some +- * other data for resume. ++ * Save CPU state for a suspend and execute the suspend finisher. ++ * On success it will return 0 through cpu_resume - ie through a CPU ++ * soft/hard reboot from the reset vector. ++ * On failure it returns the suspend finisher return value or force ++ * -EOPNOTSUPP if the finisher erroneously returns 0 (the suspend finisher ++ * is not allowed to return, if it does this must be considered failure). ++ * It saves callee registers, and allocates space on the kernel stack ++ * to save the CPU specific registers + some other data for resume. + * + * x0 = suspend finisher argument ++ * x1 = suspend finisher function pointer + */ +-ENTRY(__cpu_suspend) ++ENTRY(__cpu_suspend_enter) + stp x29, lr, [sp, #-96]! + stp x19, x20, [sp,#16] + stp x21, x22, [sp,#32] + stp x23, x24, [sp,#48] + stp x25, x26, [sp,#64] + stp x27, x28, [sp,#80] ++ /* ++ * Stash suspend finisher and its argument in x20 and x19 ++ */ ++ mov x19, x0 ++ mov x20, x1 + mov x2, sp + sub sp, sp, #CPU_SUSPEND_SZ // allocate cpu_suspend_ctx +- mov x1, sp ++ mov x0, sp + /* +- * x1 now points to struct cpu_suspend_ctx allocated on the stack ++ * x0 now points to struct cpu_suspend_ctx allocated on the stack + */ +- str x2, [x1, #CPU_CTX_SP] +- ldr x2, =sleep_save_sp +- ldr x2, [x2, #SLEEP_SAVE_SP_VIRT] ++ str x2, [x0, #CPU_CTX_SP] ++ ldr x1, =sleep_save_sp ++ ldr x1, [x1, #SLEEP_SAVE_SP_VIRT] + #ifdef CONFIG_SMP + mrs x7, mpidr_el1 + ldr x9, =mpidr_hash +@@ -82,11 +93,21 @@ ENTRY(__cpu_suspend) + ldp w3, w4, [x9, #MPIDR_HASH_SHIFTS] + ldp w5, w6, [x9, #(MPIDR_HASH_SHIFTS + 8)] + compute_mpidr_hash x8, x3, x4, x5, x6, x7, x10 +- add x2, x2, x8, lsl #3 ++ add x1, x1, x8, lsl #3 + #endif +- bl __cpu_suspend_finisher ++ bl __cpu_suspend_save ++ /* ++ * Grab suspend finisher in x20 and its argument in x19 ++ */ ++ mov x0, x19 ++ mov x1, x20 ++ /* ++ * We are ready for power down, fire off the suspend finisher ++ * in x1, with argument in x0 ++ */ ++ blr x1 + /* +- * Never gets here, unless suspend fails. ++ * Never gets here, unless suspend finisher fails. + * Successful cpu_suspend should return from cpu_resume, returning + * through this code path is considered an error + * If the return value is set to 0 force x0 = -EOPNOTSUPP +@@ -103,7 +124,7 @@ ENTRY(__cpu_suspend) + ldp x27, x28, [sp, #80] + ldp x29, lr, [sp], #96 + ret +-ENDPROC(__cpu_suspend) ++ENDPROC(__cpu_suspend_enter) + .ltorg + + /* +@@ -126,14 +147,12 @@ cpu_resume_after_mmu: + ret + ENDPROC(cpu_resume_after_mmu) + +- .data + ENTRY(cpu_resume) + bl el2_setup // if in EL2 drop to EL1 cleanly + #ifdef CONFIG_SMP + mrs x1, mpidr_el1 +- adr x4, mpidr_hash_ptr +- ldr x5, [x4] +- add x8, x4, x5 // x8 = struct mpidr_hash phys address ++ adrp x8, mpidr_hash ++ add x8, x8, #:lo12:mpidr_hash // x8 = struct mpidr_hash phys address + /* retrieve mpidr_hash members to compute the hash */ + ldr x2, [x8, #MPIDR_HASH_MASK] + ldp w3, w4, [x8, #MPIDR_HASH_SHIFTS] +@@ -143,14 +162,15 @@ ENTRY(cpu_resume) + #else + mov x7, xzr + #endif +- adr x0, sleep_save_sp ++ adrp x0, sleep_save_sp ++ add x0, x0, #:lo12:sleep_save_sp + ldr x0, [x0, #SLEEP_SAVE_SP_PHYS] + ldr x0, [x0, x7, lsl #3] + /* load sp from context */ + ldr x2, [x0, #CPU_CTX_SP] +- adr x1, sleep_idmap_phys ++ adrp x1, sleep_idmap_phys + /* load physical address of identity map page table in x1 */ +- ldr x1, [x1] ++ ldr x1, [x1, #:lo12:sleep_idmap_phys] + mov sp, x2 + /* + * cpu_do_resume expects x0 to contain context physical address +@@ -159,26 +179,3 @@ ENTRY(cpu_resume) + bl cpu_do_resume // PC relative jump, MMU off + b cpu_resume_mmu // Resume MMU, never returns + ENDPROC(cpu_resume) +- +- .align 3 +-mpidr_hash_ptr: +- /* +- * offset of mpidr_hash symbol from current location +- * used to obtain run-time mpidr_hash address with MMU off +- */ +- .quad mpidr_hash - . +-/* +- * physical address of identity mapped page tables +- */ +- .type sleep_idmap_phys, #object +-ENTRY(sleep_idmap_phys) +- .quad 0 +-/* +- * struct sleep_save_sp { +- * phys_addr_t *save_ptr_stash; +- * phys_addr_t save_ptr_stash_phys; +- * }; +- */ +- .type sleep_save_sp, #object +-ENTRY(sleep_save_sp) +- .space SLEEP_SAVE_SP_SZ // struct sleep_save_sp +diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c +index 9660750..665049d 100644 +--- a/arch/arm64/kernel/smp.c ++++ b/arch/arm64/kernel/smp.c +@@ -153,6 +153,11 @@ asmlinkage void secondary_start_kernel(void) + cpu_ops[cpu]->cpu_postboot(); + + /* ++ * Log the CPU info before it is marked online and might get read. ++ */ ++ cpuinfo_store_cpu(); ++ ++ /* + * Enable GIC and timers. + */ + notify_cpu_starting(cpu); +diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c +index 1fa9ce4..2d6b606 100644 +--- a/arch/arm64/kernel/suspend.c ++++ b/arch/arm64/kernel/suspend.c +@@ -5,26 +5,24 @@ + #include + #include + #include ++#include + #include + #include + #include + +-extern int __cpu_suspend(unsigned long); ++extern int __cpu_suspend_enter(unsigned long arg, int (*fn)(unsigned long)); + /* +- * This is called by __cpu_suspend() to save the state, and do whatever ++ * This is called by __cpu_suspend_enter() to save the state, and do whatever + * flushing is required to ensure that when the CPU goes to sleep we have + * the necessary data available when the caches are not searched. + * +- * @arg: Argument to pass to suspend operations +- * @ptr: CPU context virtual address +- * @save_ptr: address of the location where the context physical address +- * must be saved ++ * ptr: CPU context virtual address ++ * save_ptr: address of the location where the context physical address ++ * must be saved + */ +-int __cpu_suspend_finisher(unsigned long arg, struct cpu_suspend_ctx *ptr, +- phys_addr_t *save_ptr) ++void notrace __cpu_suspend_save(struct cpu_suspend_ctx *ptr, ++ phys_addr_t *save_ptr) + { +- int cpu = smp_processor_id(); +- + *save_ptr = virt_to_phys(ptr); + + cpu_do_suspend(ptr); +@@ -35,8 +33,6 @@ int __cpu_suspend_finisher(unsigned long arg, struct cpu_suspend_ctx *ptr, + */ + __flush_dcache_area(ptr, sizeof(*ptr)); + __flush_dcache_area(save_ptr, sizeof(*save_ptr)); +- +- return cpu_ops[cpu]->cpu_suspend(arg); + } + + /* +@@ -56,15 +52,15 @@ void __init cpu_suspend_set_dbg_restorer(void (*hw_bp_restore)(void *)) + } + + /** +- * cpu_suspend ++ * cpu_suspend() - function to enter a low-power state ++ * @arg: argument to pass to CPU suspend operations + * +- * @arg: argument to pass to the finisher function ++ * Return: 0 on success, -EOPNOTSUPP if CPU suspend hook not initialized, CPU ++ * operations back-end error code otherwise. + */ + int cpu_suspend(unsigned long arg) + { +- struct mm_struct *mm = current->active_mm; +- int ret, cpu = smp_processor_id(); +- unsigned long flags; ++ int cpu = smp_processor_id(); + + /* + * If cpu_ops have not been registered or suspend +@@ -72,6 +68,21 @@ int cpu_suspend(unsigned long arg) + */ + if (!cpu_ops[cpu] || !cpu_ops[cpu]->cpu_suspend) + return -EOPNOTSUPP; ++ return cpu_ops[cpu]->cpu_suspend(arg); ++} ++ ++/* ++ * __cpu_suspend ++ * ++ * arg: argument to pass to the finisher function ++ * fn: finisher function pointer ++ * ++ */ ++int __cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) ++{ ++ struct mm_struct *mm = current->active_mm; ++ int ret; ++ unsigned long flags; + + /* + * From this point debug exceptions are disabled to prevent +@@ -86,16 +97,27 @@ int cpu_suspend(unsigned long arg) + * page tables, so that the thread address space is properly + * set-up on function return. + */ +- ret = __cpu_suspend(arg); ++ ret = __cpu_suspend_enter(arg, fn); + if (ret == 0) { +- cpu_switch_mm(mm->pgd, mm); ++ /* ++ * We are resuming from reset with TTBR0_EL1 set to the ++ * idmap to enable the MMU; restore the active_mm mappings in ++ * TTBR0_EL1 unless the active_mm == &init_mm, in which case ++ * the thread entered __cpu_suspend with TTBR0_EL1 set to ++ * reserved TTBR0 page tables and should be restored as such. ++ */ ++ if (mm == &init_mm) ++ cpu_set_reserved_ttbr0(); ++ else ++ cpu_switch_mm(mm->pgd, mm); ++ + flush_tlb_all(); + + /* + * Restore per-cpu offset before any kernel + * subsystem relying on it has a chance to run. + */ +- set_my_cpu_offset(per_cpu_offset(cpu)); ++ set_my_cpu_offset(per_cpu_offset(smp_processor_id())); + + /* + * Restore HW breakpoint registers to sane values +@@ -116,10 +138,10 @@ int cpu_suspend(unsigned long arg) + return ret; + } + +-extern struct sleep_save_sp sleep_save_sp; +-extern phys_addr_t sleep_idmap_phys; ++struct sleep_save_sp sleep_save_sp; ++phys_addr_t sleep_idmap_phys; + +-static int cpu_suspend_init(void) ++static int __init cpu_suspend_init(void) + { + void *ctx_ptr; + +diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c +index 26e9c4e..7803992 100644 +--- a/arch/arm64/kernel/sys_compat.c ++++ b/arch/arm64/kernel/sys_compat.c +@@ -79,6 +79,12 @@ long compat_arm_syscall(struct pt_regs *regs) + + case __ARM_NR_compat_set_tls: + current->thread.tp_value = regs->regs[0]; ++ ++ /* ++ * Protect against register corruption from context switch. ++ * See comment in tls_thread_flush. ++ */ ++ barrier(); + asm ("msr tpidrro_el0, %0" : : "r" (regs->regs[0])); + return 0; + +diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile +index 84b9426..f6fe17d 100644 +--- a/arch/arm64/kernel/vdso/Makefile ++++ b/arch/arm64/kernel/vdso/Makefile +@@ -15,6 +15,10 @@ ccflags-y := -shared -fno-common -fno-builtin + ccflags-y += -nostdlib -Wl,-soname=linux-vdso.so.1 \ + $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) + ++# Workaround for bare-metal (ELF) toolchains that neglect to pass -shared ++# down to collect2, resulting in silent corruption of the vDSO image. ++ccflags-y += -Wl,-shared ++ + obj-y += vdso.o + extra-y += vdso.lds vdso-offsets.h + CPPFLAGS_vdso.lds += -P -C -U$(ARCH) +@@ -43,7 +47,7 @@ $(obj)/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE + $(call if_changed,vdsosym) + + # Assembly rules for the .S files +-$(obj-vdso): %.o: %.S ++$(obj-vdso): %.o: %.S FORCE + $(call if_changed_dep,vdsoas) + + # Actual build commands +diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c +index 0874557..a8d81fa 100644 +--- a/arch/arm64/kvm/guest.c ++++ b/arch/arm64/kvm/guest.c +@@ -38,7 +38,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { + + int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) + { +- vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; + return 0; + } + +diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c +index 7bc41ea..fd9aeba 100644 +--- a/arch/arm64/kvm/handle_exit.c ++++ b/arch/arm64/kvm/handle_exit.c +@@ -62,6 +62,8 @@ static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run) + else + kvm_vcpu_block(vcpu); + ++ kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); ++ + return 1; + } + +diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S +index 2b0244d..12e26f3 100644 +--- a/arch/arm64/kvm/hyp-init.S ++++ b/arch/arm64/kvm/hyp-init.S +@@ -74,6 +74,10 @@ __do_hyp_init: + msr mair_el2, x4 + isb + ++ /* Invalidate the stale TLBs from Bootloader */ ++ tlbi alle2 ++ dsb sy ++ + mrs x4, sctlr_el2 + and x4, x4, #SCTLR_EL2_EE // preserve endianness of EL2 + ldr x5, =SCTLR_EL2_FLAGS +diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S +index 2c56012..3aaf3bc 100644 +--- a/arch/arm64/kvm/hyp.S ++++ b/arch/arm64/kvm/hyp.S +@@ -629,10 +629,17 @@ ENTRY(__kvm_tlb_flush_vmid_ipa) + * Instead, we invalidate Stage-2 for this IPA, and the + * whole of Stage-1. Weep... + */ ++ lsr x1, x1, #12 + tlbi ipas2e1is, x1 +- dsb sy ++ /* ++ * We have to ensure completion of the invalidation at Stage-2, ++ * since a table walk on another CPU could refill a TLB with a ++ * complete (S1 + S2) walk based on the old Stage-2 mapping if ++ * the Stage-1 invalidation happened first. ++ */ ++ dsb ish + tlbi vmalle1is +- dsb sy ++ dsb ish + isb + + msr vttbr_el2, xzr +@@ -643,7 +650,7 @@ ENTRY(__kvm_flush_vm_context) + dsb ishst + tlbi alle1is + ic ialluis +- dsb sy ++ dsb ish + ret + ENDPROC(__kvm_flush_vm_context) + +@@ -824,7 +831,7 @@ el1_trap: + mrs x2, far_el2 + + 2: mrs x0, tpidr_el2 +- str x1, [x0, #VCPU_ESR_EL2] ++ str w1, [x0, #VCPU_ESR_EL2] + str x2, [x0, #VCPU_FAR_EL2] + str x3, [x0, #VCPU_HPFAR_EL2] + +diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c +index 81a02a8..86825f8 100644 +--- a/arch/arm64/kvm/inject_fault.c ++++ b/arch/arm64/kvm/inject_fault.c +@@ -168,8 +168,8 @@ void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr) + { + if (!(vcpu->arch.hcr_el2 & HCR_RW)) + inject_abt32(vcpu, false, addr); +- +- inject_abt64(vcpu, false, addr); ++ else ++ inject_abt64(vcpu, false, addr); + } + + /** +@@ -184,8 +184,8 @@ void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr) + { + if (!(vcpu->arch.hcr_el2 & HCR_RW)) + inject_abt32(vcpu, true, addr); +- +- inject_abt64(vcpu, true, addr); ++ else ++ inject_abt64(vcpu, true, addr); + } + + /** +@@ -198,6 +198,6 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu) + { + if (!(vcpu->arch.hcr_el2 & HCR_RW)) + inject_undef32(vcpu); +- +- inject_undef64(vcpu); ++ else ++ inject_undef64(vcpu); + } +diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c +index 70a7816..0b43265 100644 +--- a/arch/arm64/kvm/reset.c ++++ b/arch/arm64/kvm/reset.c +@@ -90,7 +90,6 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) + if (!cpu_has_32bit_el1()) + return -EINVAL; + cpu_reset = &default_regs_reset32; +- vcpu->arch.hcr_el2 &= ~HCR_RW; + } else { + cpu_reset = &default_regs_reset; + } +diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c +index 02e9d09..7691b25 100644 +--- a/arch/arm64/kvm/sys_regs.c ++++ b/arch/arm64/kvm/sys_regs.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -121,6 +122,48 @@ done: + } + + /* ++ * Generic accessor for VM registers. Only called as long as HCR_TVM ++ * is set. ++ */ ++static bool access_vm_reg(struct kvm_vcpu *vcpu, ++ const struct sys_reg_params *p, ++ const struct sys_reg_desc *r) ++{ ++ unsigned long val; ++ ++ BUG_ON(!p->is_write); ++ ++ val = *vcpu_reg(vcpu, p->Rt); ++ if (!p->is_aarch32) { ++ vcpu_sys_reg(vcpu, r->reg) = val; ++ } else { ++ vcpu_cp15(vcpu, r->reg) = val & 0xffffffffUL; ++ if (!p->is_32bit) ++ vcpu_cp15(vcpu, r->reg + 1) = val >> 32; ++ } ++ return true; ++} ++ ++/* ++ * SCTLR_EL1 accessor. Only called as long as HCR_TVM is set. If the ++ * guest enables the MMU, we stop trapping the VM sys_regs and leave ++ * it in complete control of the caches. ++ */ ++static bool access_sctlr(struct kvm_vcpu *vcpu, ++ const struct sys_reg_params *p, ++ const struct sys_reg_desc *r) ++{ ++ access_vm_reg(vcpu, p, r); ++ ++ if (vcpu_has_cache_enabled(vcpu)) { /* MMU+Caches enabled? */ ++ vcpu->arch.hcr_el2 &= ~HCR_TVM; ++ stage2_flush_vm(vcpu->kvm); ++ } ++ ++ return true; ++} ++ ++/* + * We could trap ID_DFR0 and tell the guest we don't support performance + * monitoring. Unfortunately the patch to make the kernel check ID_DFR0 was + * NAKed, so it will read the PMCR anyway. +@@ -185,32 +228,32 @@ static const struct sys_reg_desc sys_reg_descs[] = { + NULL, reset_mpidr, MPIDR_EL1 }, + /* SCTLR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0001), CRm(0b0000), Op2(0b000), +- NULL, reset_val, SCTLR_EL1, 0x00C50078 }, ++ access_sctlr, reset_val, SCTLR_EL1, 0x00C50078 }, + /* CPACR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0001), CRm(0b0000), Op2(0b010), + NULL, reset_val, CPACR_EL1, 0 }, + /* TTBR0_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0010), CRm(0b0000), Op2(0b000), +- NULL, reset_unknown, TTBR0_EL1 }, ++ access_vm_reg, reset_unknown, TTBR0_EL1 }, + /* TTBR1_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0010), CRm(0b0000), Op2(0b001), +- NULL, reset_unknown, TTBR1_EL1 }, ++ access_vm_reg, reset_unknown, TTBR1_EL1 }, + /* TCR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0010), CRm(0b0000), Op2(0b010), +- NULL, reset_val, TCR_EL1, 0 }, ++ access_vm_reg, reset_val, TCR_EL1, 0 }, + + /* AFSR0_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0101), CRm(0b0001), Op2(0b000), +- NULL, reset_unknown, AFSR0_EL1 }, ++ access_vm_reg, reset_unknown, AFSR0_EL1 }, + /* AFSR1_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0101), CRm(0b0001), Op2(0b001), +- NULL, reset_unknown, AFSR1_EL1 }, ++ access_vm_reg, reset_unknown, AFSR1_EL1 }, + /* ESR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0101), CRm(0b0010), Op2(0b000), +- NULL, reset_unknown, ESR_EL1 }, ++ access_vm_reg, reset_unknown, ESR_EL1 }, + /* FAR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0110), CRm(0b0000), Op2(0b000), +- NULL, reset_unknown, FAR_EL1 }, ++ access_vm_reg, reset_unknown, FAR_EL1 }, + /* PAR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b0111), CRm(0b0100), Op2(0b000), + NULL, reset_unknown, PAR_EL1 }, +@@ -224,17 +267,17 @@ static const struct sys_reg_desc sys_reg_descs[] = { + + /* MAIR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b1010), CRm(0b0010), Op2(0b000), +- NULL, reset_unknown, MAIR_EL1 }, ++ access_vm_reg, reset_unknown, MAIR_EL1 }, + /* AMAIR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b1010), CRm(0b0011), Op2(0b000), +- NULL, reset_amair_el1, AMAIR_EL1 }, ++ access_vm_reg, reset_amair_el1, AMAIR_EL1 }, + + /* VBAR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b0000), Op2(0b000), + NULL, reset_val, VBAR_EL1, 0 }, + /* CONTEXTIDR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b0000), Op2(0b001), +- NULL, reset_val, CONTEXTIDR_EL1, 0 }, ++ access_vm_reg, reset_val, CONTEXTIDR_EL1, 0 }, + /* TPIDR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b0000), Op2(0b100), + NULL, reset_unknown, TPIDR_EL1 }, +@@ -305,14 +348,32 @@ static const struct sys_reg_desc sys_reg_descs[] = { + NULL, reset_val, FPEXC32_EL2, 0x70 }, + }; + +-/* Trapped cp15 registers */ ++/* ++ * Trapped cp15 registers. TTBR0/TTBR1 get a double encoding, ++ * depending on the way they are accessed (as a 32bit or a 64bit ++ * register). ++ */ + static const struct sys_reg_desc cp15_regs[] = { ++ { Op1( 0), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR0 }, ++ { Op1( 0), CRn( 1), CRm( 0), Op2( 0), access_sctlr, NULL, c1_SCTLR }, ++ { Op1( 0), CRn( 2), CRm( 0), Op2( 0), access_vm_reg, NULL, c2_TTBR0 }, ++ { Op1( 0), CRn( 2), CRm( 0), Op2( 1), access_vm_reg, NULL, c2_TTBR1 }, ++ { Op1( 0), CRn( 2), CRm( 0), Op2( 2), access_vm_reg, NULL, c2_TTBCR }, ++ { Op1( 0), CRn( 3), CRm( 0), Op2( 0), access_vm_reg, NULL, c3_DACR }, ++ { Op1( 0), CRn( 5), CRm( 0), Op2( 0), access_vm_reg, NULL, c5_DFSR }, ++ { Op1( 0), CRn( 5), CRm( 0), Op2( 1), access_vm_reg, NULL, c5_IFSR }, ++ { Op1( 0), CRn( 5), CRm( 1), Op2( 0), access_vm_reg, NULL, c5_ADFSR }, ++ { Op1( 0), CRn( 5), CRm( 1), Op2( 1), access_vm_reg, NULL, c5_AIFSR }, ++ { Op1( 0), CRn( 6), CRm( 0), Op2( 0), access_vm_reg, NULL, c6_DFAR }, ++ { Op1( 0), CRn( 6), CRm( 0), Op2( 2), access_vm_reg, NULL, c6_IFAR }, ++ + /* + * DC{C,I,CI}SW operations: + */ + { Op1( 0), CRn( 7), CRm( 6), Op2( 2), access_dcsw }, + { Op1( 0), CRn( 7), CRm(10), Op2( 2), access_dcsw }, + { Op1( 0), CRn( 7), CRm(14), Op2( 2), access_dcsw }, ++ + { Op1( 0), CRn( 9), CRm(12), Op2( 0), pm_fake }, + { Op1( 0), CRn( 9), CRm(12), Op2( 1), pm_fake }, + { Op1( 0), CRn( 9), CRm(12), Op2( 2), pm_fake }, +@@ -326,6 +387,14 @@ static const struct sys_reg_desc cp15_regs[] = { + { Op1( 0), CRn( 9), CRm(14), Op2( 0), pm_fake }, + { Op1( 0), CRn( 9), CRm(14), Op2( 1), pm_fake }, + { Op1( 0), CRn( 9), CRm(14), Op2( 2), pm_fake }, ++ ++ { Op1( 0), CRn(10), CRm( 2), Op2( 0), access_vm_reg, NULL, c10_PRRR }, ++ { Op1( 0), CRn(10), CRm( 2), Op2( 1), access_vm_reg, NULL, c10_NMRR }, ++ { Op1( 0), CRn(10), CRm( 3), Op2( 0), access_vm_reg, NULL, c10_AMAIR0 }, ++ { Op1( 0), CRn(10), CRm( 3), Op2( 1), access_vm_reg, NULL, c10_AMAIR1 }, ++ { Op1( 0), CRn(13), CRm( 0), Op2( 1), access_vm_reg, NULL, c13_CID }, ++ ++ { Op1( 1), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR1 }, + }; + + /* Target specific emulation tables */ +@@ -437,6 +506,8 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) + u32 hsr = kvm_vcpu_get_hsr(vcpu); + int Rt2 = (hsr >> 10) & 0xf; + ++ params.is_aarch32 = true; ++ params.is_32bit = false; + params.CRm = (hsr >> 1) & 0xf; + params.Rt = (hsr >> 5) & 0xf; + params.is_write = ((hsr & 1) == 0); +@@ -480,6 +551,8 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) + struct sys_reg_params params; + u32 hsr = kvm_vcpu_get_hsr(vcpu); + ++ params.is_aarch32 = true; ++ params.is_32bit = true; + params.CRm = (hsr >> 1) & 0xf; + params.Rt = (hsr >> 5) & 0xf; + params.is_write = ((hsr & 1) == 0); +@@ -549,6 +622,8 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run) + struct sys_reg_params params; + unsigned long esr = kvm_vcpu_get_hsr(vcpu); + ++ params.is_aarch32 = false; ++ params.is_32bit = false; + params.Op0 = (esr >> 20) & 3; + params.Op1 = (esr >> 14) & 0x7; + params.CRn = (esr >> 10) & 0xf; +@@ -761,7 +836,7 @@ static bool is_valid_cache(u32 val) + u32 level, ctype; + + if (val >= CSSELR_MAX) +- return -ENOENT; ++ return false; + + /* Bottom bit is Instruction or Data bit. Next 3 bits are level. */ + level = (val >> 1); +@@ -887,7 +962,7 @@ static unsigned int num_demux_regs(void) + + static int write_demux_regids(u64 __user *uindices) + { +- u64 val = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX; ++ u64 val = KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX; + unsigned int i; + + val |= KVM_REG_ARM_DEMUX_ID_CCSIDR; +diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h +index d50d372..d411e25 100644 +--- a/arch/arm64/kvm/sys_regs.h ++++ b/arch/arm64/kvm/sys_regs.h +@@ -30,6 +30,8 @@ struct sys_reg_params { + u8 Op2; + u8 Rt; + bool is_write; ++ bool is_aarch32; ++ bool is_32bit; /* Only valid if is_aarch32 is true */ + }; + + struct sys_reg_desc { +diff --git a/arch/arm64/lib/clear_user.S b/arch/arm64/lib/clear_user.S +index 6e0ed93..c17967f 100644 +--- a/arch/arm64/lib/clear_user.S ++++ b/arch/arm64/lib/clear_user.S +@@ -46,7 +46,7 @@ USER(9f, strh wzr, [x0], #2 ) + sub x1, x1, #2 + 4: adds x1, x1, #1 + b.mi 5f +- strb wzr, [x0] ++USER(9f, strb wzr, [x0] ) + 5: mov x0, #0 + ret + ENDPROC(__clear_user) +diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c +index baa758d..76c1e6c 100644 +--- a/arch/arm64/mm/context.c ++++ b/arch/arm64/mm/context.c +@@ -92,6 +92,14 @@ static void reset_context(void *info) + unsigned int cpu = smp_processor_id(); + struct mm_struct *mm = current->active_mm; + ++ /* ++ * current->active_mm could be init_mm for the idle thread immediately ++ * after secondary CPU boot or hotplug. TTBR0_EL1 is already set to ++ * the reserved value, so no need to reset any context. ++ */ ++ if (mm == &init_mm) ++ return; ++ + smp_rmb(); + asid = cpu_last_asid + cpu; + +diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c +index 9337524..05d9815 100644 +--- a/arch/arm64/mm/dma-mapping.c ++++ b/arch/arm64/mm/dma-mapping.c +@@ -57,6 +57,7 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size, + flags |= GFP_DMA; + if (IS_ENABLED(CONFIG_DMA_CMA)) { + struct page *page; ++ void *addr; + + size = PAGE_ALIGN(size); + page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT, +@@ -65,7 +66,9 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size, + return NULL; + + *dma_handle = phys_to_dma(dev, page_to_phys(page)); +- return page_address(page); ++ addr = page_address(page); ++ memset(addr, 0, size); ++ return addr; + } else { + return swiotlb_alloc_coherent(dev, size, dma_handle, flags); + } +diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c +index 023747b..e3a24b7 100644 +--- a/arch/arm64/mm/hugetlbpage.c ++++ b/arch/arm64/mm/hugetlbpage.c +@@ -46,13 +46,13 @@ struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address, + + int pmd_huge(pmd_t pmd) + { +- return !(pmd_val(pmd) & PMD_TABLE_BIT); ++ return pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT); + } + + int pud_huge(pud_t pud) + { + #ifndef __PAGETABLE_PMD_FOLDED +- return !(pud_val(pud) & PUD_TABLE_BIT); ++ return pud_val(pud) && !(pud_val(pud) & PUD_TABLE_BIT); + #else + return 0; + #endif +diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c +index c872988..6ca4285 100644 +--- a/arch/arm64/mm/init.c ++++ b/arch/arm64/mm/init.c +@@ -240,7 +240,7 @@ static void __init free_unused_memmap(void) + * memmap entries are valid from the bank end aligned to + * MAX_ORDER_NR_PAGES. + */ +- prev_end = ALIGN(start + __phys_to_pfn(reg->size), ++ prev_end = ALIGN(__phys_to_pfn(reg->base + reg->size), + MAX_ORDER_NR_PAGES); + } + +diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c +index 8ed6cb1..8f7ffff 100644 +--- a/arch/arm64/mm/mmap.c ++++ b/arch/arm64/mm/mmap.c +@@ -47,22 +47,14 @@ static int mmap_is_legacy(void) + return sysctl_legacy_va_layout; + } + +-/* +- * Since get_random_int() returns the same value within a 1 jiffy window, we +- * will almost always get the same randomisation for the stack and mmap +- * region. This will mean the relative distance between stack and mmap will be +- * the same. +- * +- * To avoid this we can shift the randomness by 1 bit. +- */ + static unsigned long mmap_rnd(void) + { + unsigned long rnd = 0; + + if (current->flags & PF_RANDOMIZE) +- rnd = (long)get_random_int() & (STACK_RND_MASK >> 1); ++ rnd = (long)get_random_int() & STACK_RND_MASK; + +- return rnd << (PAGE_SHIFT + 1); ++ return rnd << PAGE_SHIFT; + } + + static unsigned long mmap_base(void) +diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c +index 23b1a97..52c179b 100644 +--- a/arch/avr32/mach-at32ap/clock.c ++++ b/arch/avr32/mach-at32ap/clock.c +@@ -80,6 +80,9 @@ int clk_enable(struct clk *clk) + { + unsigned long flags; + ++ if (!clk) ++ return 0; ++ + spin_lock_irqsave(&clk_lock, flags); + __clk_enable(clk); + spin_unlock_irqrestore(&clk_lock, flags); +@@ -106,6 +109,9 @@ void clk_disable(struct clk *clk) + { + unsigned long flags; + ++ if (IS_ERR_OR_NULL(clk)) ++ return; ++ + spin_lock_irqsave(&clk_lock, flags); + __clk_disable(clk); + spin_unlock_irqrestore(&clk_lock, flags); +@@ -117,6 +123,9 @@ unsigned long clk_get_rate(struct clk *clk) + unsigned long flags; + unsigned long rate; + ++ if (!clk) ++ return 0; ++ + spin_lock_irqsave(&clk_lock, flags); + rate = clk->get_rate(clk); + spin_unlock_irqrestore(&clk_lock, flags); +@@ -129,6 +138,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate) + { + unsigned long flags, actual_rate; + ++ if (!clk) ++ return 0; ++ + if (!clk->set_rate) + return -ENOSYS; + +@@ -145,6 +157,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate) + unsigned long flags; + long ret; + ++ if (!clk) ++ return 0; ++ + if (!clk->set_rate) + return -ENOSYS; + +@@ -161,6 +176,9 @@ int clk_set_parent(struct clk *clk, struct clk *parent) + unsigned long flags; + int ret; + ++ if (!clk) ++ return 0; ++ + if (!clk->set_parent) + return -ENOSYS; + +@@ -174,7 +192,7 @@ EXPORT_SYMBOL(clk_set_parent); + + struct clk *clk_get_parent(struct clk *clk) + { +- return clk->parent; ++ return !clk ? NULL : clk->parent; + } + EXPORT_SYMBOL(clk_get_parent); + +diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c +index 0eca933..d223a8b 100644 +--- a/arch/avr32/mm/fault.c ++++ b/arch/avr32/mm/fault.c +@@ -142,6 +142,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/c6x/kernel/time.c b/arch/c6x/kernel/time.c +index 356ee84..04845aa 100644 +--- a/arch/c6x/kernel/time.c ++++ b/arch/c6x/kernel/time.c +@@ -49,7 +49,7 @@ u64 sched_clock(void) + return (tsc * sched_clock_multiplier) >> SCHED_CLOCK_SHIFT; + } + +-void time_init(void) ++void __init time_init(void) + { + u64 tmp = (u64)NSEC_PER_SEC << SCHED_CLOCK_SHIFT; + +diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c +index 1790f22..2686a7a 100644 +--- a/arch/cris/mm/fault.c ++++ b/arch/cris/mm/fault.c +@@ -176,6 +176,8 @@ retry: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/frv/mm/fault.c b/arch/frv/mm/fault.c +index 9a66372..ec4917d 100644 +--- a/arch/frv/mm/fault.c ++++ b/arch/frv/mm/fault.c +@@ -168,6 +168,8 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c +index 7225dad..ba5ba7a 100644 +--- a/arch/ia64/mm/fault.c ++++ b/arch/ia64/mm/fault.c +@@ -172,6 +172,8 @@ retry: + */ + if (fault & VM_FAULT_OOM) { + goto out_of_memory; ++ } else if (fault & VM_FAULT_SIGSEGV) { ++ goto bad_area; + } else if (fault & VM_FAULT_SIGBUS) { + signal = SIGBUS; + goto bad_area; +diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c +index e9c6a80..e3d4d48901 100644 +--- a/arch/m32r/mm/fault.c ++++ b/arch/m32r/mm/fault.c +@@ -200,6 +200,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c +index 2bd7487..b2f04ae 100644 +--- a/arch/m68k/mm/fault.c ++++ b/arch/m68k/mm/fault.c +@@ -145,6 +145,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto map_err; + else if (fault & VM_FAULT_SIGBUS) + goto bus_err; + BUG(); +diff --git a/arch/m68k/mm/hwtest.c b/arch/m68k/mm/hwtest.c +index 2c7dde3..2a5259f 100644 +--- a/arch/m68k/mm/hwtest.c ++++ b/arch/m68k/mm/hwtest.c +@@ -28,9 +28,11 @@ + int hwreg_present( volatile void *regp ) + { + int ret = 0; ++ unsigned long flags; + long save_sp, save_vbr; + long tmp_vectors[3]; + ++ local_irq_save(flags); + __asm__ __volatile__ + ( "movec %/vbr,%2\n\t" + "movel #Lberr1,%4@(8)\n\t" +@@ -46,6 +48,7 @@ int hwreg_present( volatile void *regp ) + : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr) + : "a" (regp), "a" (tmp_vectors) + ); ++ local_irq_restore(flags); + + return( ret ); + } +@@ -58,9 +61,11 @@ EXPORT_SYMBOL(hwreg_present); + int hwreg_write( volatile void *regp, unsigned short val ) + { + int ret; ++ unsigned long flags; + long save_sp, save_vbr; + long tmp_vectors[3]; + ++ local_irq_save(flags); + __asm__ __volatile__ + ( "movec %/vbr,%2\n\t" + "movel #Lberr2,%4@(8)\n\t" +@@ -78,6 +83,7 @@ int hwreg_write( volatile void *regp, unsigned short val ) + : "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr) + : "a" (regp), "a" (tmp_vectors), "g" (val) + ); ++ local_irq_restore(flags); + + return( ret ); + } +diff --git a/arch/metag/include/asm/processor.h b/arch/metag/include/asm/processor.h +index a8a3747..eb2005b 100644 +--- a/arch/metag/include/asm/processor.h ++++ b/arch/metag/include/asm/processor.h +@@ -149,8 +149,8 @@ extern void exit_thread(void); + + unsigned long get_wchan(struct task_struct *p); + +-#define KSTK_EIP(tsk) ((tsk)->thread.kernel_context->CurrPC) +-#define KSTK_ESP(tsk) ((tsk)->thread.kernel_context->AX[0].U0) ++#define KSTK_EIP(tsk) (task_pt_regs(tsk)->ctx.CurrPC) ++#define KSTK_ESP(tsk) (task_pt_regs(tsk)->ctx.AX[0].U0) + + #define user_stack_pointer(regs) ((regs)->ctx.AX[0].U0) + +diff --git a/arch/metag/mm/fault.c b/arch/metag/mm/fault.c +index 332680e..2de5dc6 100644 +--- a/arch/metag/mm/fault.c ++++ b/arch/metag/mm/fault.c +@@ -141,6 +141,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/microblaze/mm/fault.c b/arch/microblaze/mm/fault.c +index fa4cf52..d46a5eb 100644 +--- a/arch/microblaze/mm/fault.c ++++ b/arch/microblaze/mm/fault.c +@@ -224,6 +224,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c +index c00c4dd..5244cec 100644 +--- a/arch/mips/boot/compressed/decompress.c ++++ b/arch/mips/boot/compressed/decompress.c +@@ -13,6 +13,7 @@ + + #include + #include ++#include + + #include + +diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c +index 331b837..270cb3c 100644 +--- a/arch/mips/cavium-octeon/setup.c ++++ b/arch/mips/cavium-octeon/setup.c +@@ -458,6 +458,18 @@ static void octeon_halt(void) + octeon_kill_core(NULL); + } + ++static char __read_mostly octeon_system_type[80]; ++ ++static int __init init_octeon_system_type(void) ++{ ++ snprintf(octeon_system_type, sizeof(octeon_system_type), "%s (%s)", ++ cvmx_board_type_to_string(octeon_bootinfo->board_type), ++ octeon_model_get_string(read_c0_prid())); ++ ++ return 0; ++} ++early_initcall(init_octeon_system_type); ++ + /** + * Return a string representing the system type + * +@@ -465,11 +477,7 @@ static void octeon_halt(void) + */ + const char *octeon_board_type_string(void) + { +- static char name[80]; +- sprintf(name, "%s (%s)", +- cvmx_board_type_to_string(octeon_bootinfo->board_type), +- octeon_model_get_string(read_c0_prid())); +- return name; ++ return octeon_system_type; + } + + const char *get_system_type(void) +diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c +index 67a078f..34467ac 100644 +--- a/arch/mips/cavium-octeon/smp.c ++++ b/arch/mips/cavium-octeon/smp.c +@@ -263,9 +263,7 @@ static int octeon_cpu_disable(void) + + set_cpu_online(cpu, false); + cpu_clear(cpu, cpu_callin_map); +- local_irq_disable(); + octeon_fixup_irqs(); +- local_irq_enable(); + + flush_cache_all(); + local_flush_tlb_all(); +diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h +index 992aaba..b463f2a 100644 +--- a/arch/mips/include/asm/ftrace.h ++++ b/arch/mips/include/asm/ftrace.h +@@ -24,7 +24,7 @@ do { \ + asm volatile ( \ + "1: " load " %[tmp_dst], 0(%[tmp_src])\n" \ + " li %[tmp_err], 0\n" \ +- "2:\n" \ ++ "2: .insn\n" \ + \ + ".section .fixup, \"ax\"\n" \ + "3: li %[tmp_err], 1\n" \ +@@ -46,7 +46,7 @@ do { \ + asm volatile ( \ + "1: " store " %[tmp_src], 0(%[tmp_dst])\n"\ + " li %[tmp_err], 0\n" \ +- "2:\n" \ ++ "2: .insn\n" \ + \ + ".section .fixup, \"ax\"\n" \ + "3: li %[tmp_err], 1\n" \ +diff --git a/arch/mips/include/asm/mach-generic/spaces.h b/arch/mips/include/asm/mach-generic/spaces.h +index 9488fa5..afc96ec 100644 +--- a/arch/mips/include/asm/mach-generic/spaces.h ++++ b/arch/mips/include/asm/mach-generic/spaces.h +@@ -94,7 +94,11 @@ + #endif + + #ifndef FIXADDR_TOP ++#ifdef CONFIG_KVM_GUEST ++#define FIXADDR_TOP ((unsigned long)(long)(int)0x7ffe0000) ++#else + #define FIXADDR_TOP ((unsigned long)(long)(int)0xfffe0000) + #endif ++#endif + + #endif /* __ASM_MACH_GENERIC_SPACES_H */ +diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h +index 008324d..b154953 100644 +--- a/arch/mips/include/asm/pgtable.h ++++ b/arch/mips/include/asm/pgtable.h +@@ -150,8 +150,39 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) + * Make sure the buddy is global too (if it's !none, + * it better already be global) + */ ++#ifdef CONFIG_SMP ++ /* ++ * For SMP, multiple CPUs can race, so we need to do ++ * this atomically. ++ */ ++#ifdef CONFIG_64BIT ++#define LL_INSN "lld" ++#define SC_INSN "scd" ++#else /* CONFIG_32BIT */ ++#define LL_INSN "ll" ++#define SC_INSN "sc" ++#endif ++ unsigned long page_global = _PAGE_GLOBAL; ++ unsigned long tmp; ++ ++ __asm__ __volatile__ ( ++ " .set push\n" ++ " .set noreorder\n" ++ "1: " LL_INSN " %[tmp], %[buddy]\n" ++ " bnez %[tmp], 2f\n" ++ " or %[tmp], %[tmp], %[global]\n" ++ " " SC_INSN " %[tmp], %[buddy]\n" ++ " beqz %[tmp], 1b\n" ++ " nop\n" ++ "2:\n" ++ " .set pop" ++ : [buddy] "+m" (buddy->pte), ++ [tmp] "=&r" (tmp) ++ : [global] "r" (page_global)); ++#else /* !CONFIG_SMP */ + if (pte_none(*buddy)) + pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL; ++#endif /* CONFIG_SMP */ + } + #endif + } +diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h +index 7bba9da..6d019ca 100644 +--- a/arch/mips/include/asm/ptrace.h ++++ b/arch/mips/include/asm/ptrace.h +@@ -23,7 +23,7 @@ + struct pt_regs { + #ifdef CONFIG_32BIT + /* Pad bytes for argument save space on the stack. */ +- unsigned long pad0[6]; ++ unsigned long pad0[8]; + #endif + + /* Saved main processor registers. */ +diff --git a/arch/mips/include/asm/reg.h b/arch/mips/include/asm/reg.h +index 910e71a..b8343cc 100644 +--- a/arch/mips/include/asm/reg.h ++++ b/arch/mips/include/asm/reg.h +@@ -12,116 +12,194 @@ + #ifndef __ASM_MIPS_REG_H + #define __ASM_MIPS_REG_H + +- +-#if defined(CONFIG_32BIT) || defined(WANT_COMPAT_REG_H) +- +-#define EF_R0 6 +-#define EF_R1 7 +-#define EF_R2 8 +-#define EF_R3 9 +-#define EF_R4 10 +-#define EF_R5 11 +-#define EF_R6 12 +-#define EF_R7 13 +-#define EF_R8 14 +-#define EF_R9 15 +-#define EF_R10 16 +-#define EF_R11 17 +-#define EF_R12 18 +-#define EF_R13 19 +-#define EF_R14 20 +-#define EF_R15 21 +-#define EF_R16 22 +-#define EF_R17 23 +-#define EF_R18 24 +-#define EF_R19 25 +-#define EF_R20 26 +-#define EF_R21 27 +-#define EF_R22 28 +-#define EF_R23 29 +-#define EF_R24 30 +-#define EF_R25 31 ++#define MIPS32_EF_R0 6 ++#define MIPS32_EF_R1 7 ++#define MIPS32_EF_R2 8 ++#define MIPS32_EF_R3 9 ++#define MIPS32_EF_R4 10 ++#define MIPS32_EF_R5 11 ++#define MIPS32_EF_R6 12 ++#define MIPS32_EF_R7 13 ++#define MIPS32_EF_R8 14 ++#define MIPS32_EF_R9 15 ++#define MIPS32_EF_R10 16 ++#define MIPS32_EF_R11 17 ++#define MIPS32_EF_R12 18 ++#define MIPS32_EF_R13 19 ++#define MIPS32_EF_R14 20 ++#define MIPS32_EF_R15 21 ++#define MIPS32_EF_R16 22 ++#define MIPS32_EF_R17 23 ++#define MIPS32_EF_R18 24 ++#define MIPS32_EF_R19 25 ++#define MIPS32_EF_R20 26 ++#define MIPS32_EF_R21 27 ++#define MIPS32_EF_R22 28 ++#define MIPS32_EF_R23 29 ++#define MIPS32_EF_R24 30 ++#define MIPS32_EF_R25 31 + + /* + * k0/k1 unsaved + */ +-#define EF_R26 32 +-#define EF_R27 33 ++#define MIPS32_EF_R26 32 ++#define MIPS32_EF_R27 33 + +-#define EF_R28 34 +-#define EF_R29 35 +-#define EF_R30 36 +-#define EF_R31 37 ++#define MIPS32_EF_R28 34 ++#define MIPS32_EF_R29 35 ++#define MIPS32_EF_R30 36 ++#define MIPS32_EF_R31 37 + + /* + * Saved special registers + */ +-#define EF_LO 38 +-#define EF_HI 39 +- +-#define EF_CP0_EPC 40 +-#define EF_CP0_BADVADDR 41 +-#define EF_CP0_STATUS 42 +-#define EF_CP0_CAUSE 43 +-#define EF_UNUSED0 44 +- +-#define EF_SIZE 180 +- +-#endif +- +-#if defined(CONFIG_64BIT) && !defined(WANT_COMPAT_REG_H) +- +-#define EF_R0 0 +-#define EF_R1 1 +-#define EF_R2 2 +-#define EF_R3 3 +-#define EF_R4 4 +-#define EF_R5 5 +-#define EF_R6 6 +-#define EF_R7 7 +-#define EF_R8 8 +-#define EF_R9 9 +-#define EF_R10 10 +-#define EF_R11 11 +-#define EF_R12 12 +-#define EF_R13 13 +-#define EF_R14 14 +-#define EF_R15 15 +-#define EF_R16 16 +-#define EF_R17 17 +-#define EF_R18 18 +-#define EF_R19 19 +-#define EF_R20 20 +-#define EF_R21 21 +-#define EF_R22 22 +-#define EF_R23 23 +-#define EF_R24 24 +-#define EF_R25 25 ++#define MIPS32_EF_LO 38 ++#define MIPS32_EF_HI 39 ++ ++#define MIPS32_EF_CP0_EPC 40 ++#define MIPS32_EF_CP0_BADVADDR 41 ++#define MIPS32_EF_CP0_STATUS 42 ++#define MIPS32_EF_CP0_CAUSE 43 ++#define MIPS32_EF_UNUSED0 44 ++ ++#define MIPS32_EF_SIZE 180 ++ ++#define MIPS64_EF_R0 0 ++#define MIPS64_EF_R1 1 ++#define MIPS64_EF_R2 2 ++#define MIPS64_EF_R3 3 ++#define MIPS64_EF_R4 4 ++#define MIPS64_EF_R5 5 ++#define MIPS64_EF_R6 6 ++#define MIPS64_EF_R7 7 ++#define MIPS64_EF_R8 8 ++#define MIPS64_EF_R9 9 ++#define MIPS64_EF_R10 10 ++#define MIPS64_EF_R11 11 ++#define MIPS64_EF_R12 12 ++#define MIPS64_EF_R13 13 ++#define MIPS64_EF_R14 14 ++#define MIPS64_EF_R15 15 ++#define MIPS64_EF_R16 16 ++#define MIPS64_EF_R17 17 ++#define MIPS64_EF_R18 18 ++#define MIPS64_EF_R19 19 ++#define MIPS64_EF_R20 20 ++#define MIPS64_EF_R21 21 ++#define MIPS64_EF_R22 22 ++#define MIPS64_EF_R23 23 ++#define MIPS64_EF_R24 24 ++#define MIPS64_EF_R25 25 + + /* + * k0/k1 unsaved + */ +-#define EF_R26 26 +-#define EF_R27 27 ++#define MIPS64_EF_R26 26 ++#define MIPS64_EF_R27 27 + + +-#define EF_R28 28 +-#define EF_R29 29 +-#define EF_R30 30 +-#define EF_R31 31 ++#define MIPS64_EF_R28 28 ++#define MIPS64_EF_R29 29 ++#define MIPS64_EF_R30 30 ++#define MIPS64_EF_R31 31 + + /* + * Saved special registers + */ +-#define EF_LO 32 +-#define EF_HI 33 +- +-#define EF_CP0_EPC 34 +-#define EF_CP0_BADVADDR 35 +-#define EF_CP0_STATUS 36 +-#define EF_CP0_CAUSE 37 +- +-#define EF_SIZE 304 /* size in bytes */ ++#define MIPS64_EF_LO 32 ++#define MIPS64_EF_HI 33 ++ ++#define MIPS64_EF_CP0_EPC 34 ++#define MIPS64_EF_CP0_BADVADDR 35 ++#define MIPS64_EF_CP0_STATUS 36 ++#define MIPS64_EF_CP0_CAUSE 37 ++ ++#define MIPS64_EF_SIZE 304 /* size in bytes */ ++ ++#if defined(CONFIG_32BIT) ++ ++#define EF_R0 MIPS32_EF_R0 ++#define EF_R1 MIPS32_EF_R1 ++#define EF_R2 MIPS32_EF_R2 ++#define EF_R3 MIPS32_EF_R3 ++#define EF_R4 MIPS32_EF_R4 ++#define EF_R5 MIPS32_EF_R5 ++#define EF_R6 MIPS32_EF_R6 ++#define EF_R7 MIPS32_EF_R7 ++#define EF_R8 MIPS32_EF_R8 ++#define EF_R9 MIPS32_EF_R9 ++#define EF_R10 MIPS32_EF_R10 ++#define EF_R11 MIPS32_EF_R11 ++#define EF_R12 MIPS32_EF_R12 ++#define EF_R13 MIPS32_EF_R13 ++#define EF_R14 MIPS32_EF_R14 ++#define EF_R15 MIPS32_EF_R15 ++#define EF_R16 MIPS32_EF_R16 ++#define EF_R17 MIPS32_EF_R17 ++#define EF_R18 MIPS32_EF_R18 ++#define EF_R19 MIPS32_EF_R19 ++#define EF_R20 MIPS32_EF_R20 ++#define EF_R21 MIPS32_EF_R21 ++#define EF_R22 MIPS32_EF_R22 ++#define EF_R23 MIPS32_EF_R23 ++#define EF_R24 MIPS32_EF_R24 ++#define EF_R25 MIPS32_EF_R25 ++#define EF_R26 MIPS32_EF_R26 ++#define EF_R27 MIPS32_EF_R27 ++#define EF_R28 MIPS32_EF_R28 ++#define EF_R29 MIPS32_EF_R29 ++#define EF_R30 MIPS32_EF_R30 ++#define EF_R31 MIPS32_EF_R31 ++#define EF_LO MIPS32_EF_LO ++#define EF_HI MIPS32_EF_HI ++#define EF_CP0_EPC MIPS32_EF_CP0_EPC ++#define EF_CP0_BADVADDR MIPS32_EF_CP0_BADVADDR ++#define EF_CP0_STATUS MIPS32_EF_CP0_STATUS ++#define EF_CP0_CAUSE MIPS32_EF_CP0_CAUSE ++#define EF_UNUSED0 MIPS32_EF_UNUSED0 ++#define EF_SIZE MIPS32_EF_SIZE ++ ++#elif defined(CONFIG_64BIT) ++ ++#define EF_R0 MIPS64_EF_R0 ++#define EF_R1 MIPS64_EF_R1 ++#define EF_R2 MIPS64_EF_R2 ++#define EF_R3 MIPS64_EF_R3 ++#define EF_R4 MIPS64_EF_R4 ++#define EF_R5 MIPS64_EF_R5 ++#define EF_R6 MIPS64_EF_R6 ++#define EF_R7 MIPS64_EF_R7 ++#define EF_R8 MIPS64_EF_R8 ++#define EF_R9 MIPS64_EF_R9 ++#define EF_R10 MIPS64_EF_R10 ++#define EF_R11 MIPS64_EF_R11 ++#define EF_R12 MIPS64_EF_R12 ++#define EF_R13 MIPS64_EF_R13 ++#define EF_R14 MIPS64_EF_R14 ++#define EF_R15 MIPS64_EF_R15 ++#define EF_R16 MIPS64_EF_R16 ++#define EF_R17 MIPS64_EF_R17 ++#define EF_R18 MIPS64_EF_R18 ++#define EF_R19 MIPS64_EF_R19 ++#define EF_R20 MIPS64_EF_R20 ++#define EF_R21 MIPS64_EF_R21 ++#define EF_R22 MIPS64_EF_R22 ++#define EF_R23 MIPS64_EF_R23 ++#define EF_R24 MIPS64_EF_R24 ++#define EF_R25 MIPS64_EF_R25 ++#define EF_R26 MIPS64_EF_R26 ++#define EF_R27 MIPS64_EF_R27 ++#define EF_R28 MIPS64_EF_R28 ++#define EF_R29 MIPS64_EF_R29 ++#define EF_R30 MIPS64_EF_R30 ++#define EF_R31 MIPS64_EF_R31 ++#define EF_LO MIPS64_EF_LO ++#define EF_HI MIPS64_EF_HI ++#define EF_CP0_EPC MIPS64_EF_CP0_EPC ++#define EF_CP0_BADVADDR MIPS64_EF_CP0_BADVADDR ++#define EF_CP0_STATUS MIPS64_EF_CP0_STATUS ++#define EF_CP0_CAUSE MIPS64_EF_CP0_CAUSE ++#define EF_SIZE MIPS64_EF_SIZE + + #endif /* CONFIG_64BIT */ + +diff --git a/arch/mips/include/asm/suspend.h b/arch/mips/include/asm/suspend.h +deleted file mode 100644 +index 3adac3b..0000000 +--- a/arch/mips/include/asm/suspend.h ++++ /dev/null +@@ -1,7 +0,0 @@ +-#ifndef __ASM_SUSPEND_H +-#define __ASM_SUSPEND_H +- +-/* References to section boundaries */ +-extern const void __nosave_begin, __nosave_end; +- +-#endif /* __ASM_SUSPEND_H */ +diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c +index 7faf5f2..71df942 100644 +--- a/arch/mips/kernel/binfmt_elfo32.c ++++ b/arch/mips/kernel/binfmt_elfo32.c +@@ -72,12 +72,6 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + + #include + +-/* +- * When this file is selected, we are definitely running a 64bit kernel. +- * So using the right regs define in asm/reg.h +- */ +-#define WANT_COMPAT_REG_H +- + /* These MUST be defined before elf.h gets included */ + extern void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs); + #define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs); +@@ -149,21 +143,21 @@ void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs) + { + int i; + +- for (i = 0; i < EF_R0; i++) ++ for (i = 0; i < MIPS32_EF_R0; i++) + grp[i] = 0; +- grp[EF_R0] = 0; ++ grp[MIPS32_EF_R0] = 0; + for (i = 1; i <= 31; i++) +- grp[EF_R0 + i] = (elf_greg_t) regs->regs[i]; +- grp[EF_R26] = 0; +- grp[EF_R27] = 0; +- grp[EF_LO] = (elf_greg_t) regs->lo; +- grp[EF_HI] = (elf_greg_t) regs->hi; +- grp[EF_CP0_EPC] = (elf_greg_t) regs->cp0_epc; +- grp[EF_CP0_BADVADDR] = (elf_greg_t) regs->cp0_badvaddr; +- grp[EF_CP0_STATUS] = (elf_greg_t) regs->cp0_status; +- grp[EF_CP0_CAUSE] = (elf_greg_t) regs->cp0_cause; +-#ifdef EF_UNUSED0 +- grp[EF_UNUSED0] = 0; ++ grp[MIPS32_EF_R0 + i] = (elf_greg_t) regs->regs[i]; ++ grp[MIPS32_EF_R26] = 0; ++ grp[MIPS32_EF_R27] = 0; ++ grp[MIPS32_EF_LO] = (elf_greg_t) regs->lo; ++ grp[MIPS32_EF_HI] = (elf_greg_t) regs->hi; ++ grp[MIPS32_EF_CP0_EPC] = (elf_greg_t) regs->cp0_epc; ++ grp[MIPS32_EF_CP0_BADVADDR] = (elf_greg_t) regs->cp0_badvaddr; ++ grp[MIPS32_EF_CP0_STATUS] = (elf_greg_t) regs->cp0_status; ++ grp[MIPS32_EF_CP0_CAUSE] = (elf_greg_t) regs->cp0_cause; ++#ifdef MIPS32_EF_UNUSED0 ++ grp[MIPS32_EF_UNUSED0] = 0; + #endif + } + +diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c +index 5b5ddb2..78f1843 100644 +--- a/arch/mips/kernel/irq-gic.c ++++ b/arch/mips/kernel/irq-gic.c +@@ -255,11 +255,13 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu, + + /* Setup Intr to Pin mapping */ + if (pin & GIC_MAP_TO_NMI_MSK) { ++ int i; ++ + GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin); + /* FIXME: hack to route NMI to all cpu's */ +- for (cpu = 0; cpu < NR_CPUS; cpu += 32) { ++ for (i = 0; i < NR_CPUS; i += 32) { + GICWRITE(GIC_REG_ADDR(SHARED, +- GIC_SH_MAP_TO_VPE_REG_OFF(intr, cpu)), ++ GIC_SH_MAP_TO_VPE_REG_OFF(intr, i)), + 0xffffffff); + } + } else { +diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c +index d1fea7a..7479d8d 100644 +--- a/arch/mips/kernel/irq.c ++++ b/arch/mips/kernel/irq.c +@@ -110,7 +110,7 @@ void __init init_IRQ(void) + #endif + } + +-#ifdef DEBUG_STACKOVERFLOW ++#ifdef CONFIG_DEBUG_STACKOVERFLOW + static inline void check_stack_overflow(void) + { + unsigned long sp; +diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c +index e498f2b..f5598e2 100644 +--- a/arch/mips/kernel/irq_cpu.c ++++ b/arch/mips/kernel/irq_cpu.c +@@ -56,6 +56,8 @@ static struct irq_chip mips_cpu_irq_controller = { + .irq_mask_ack = mask_mips_irq, + .irq_unmask = unmask_mips_irq, + .irq_eoi = unmask_mips_irq, ++ .irq_disable = mask_mips_irq, ++ .irq_enable = unmask_mips_irq, + }; + + /* +@@ -92,6 +94,8 @@ static struct irq_chip mips_mt_cpu_irq_controller = { + .irq_mask_ack = mips_mt_cpu_irq_ack, + .irq_unmask = unmask_mips_irq, + .irq_eoi = unmask_mips_irq, ++ .irq_disable = mask_mips_irq, ++ .irq_enable = unmask_mips_irq, + }; + + void __init mips_cpu_irq_init(void) +diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S +index 539b629..8f89ff4 100644 +--- a/arch/mips/kernel/mcount.S ++++ b/arch/mips/kernel/mcount.S +@@ -123,7 +123,11 @@ NESTED(_mcount, PT_SIZE, ra) + nop + #endif + b ftrace_stub ++#ifdef CONFIG_32BIT ++ addiu sp, sp, 8 ++#else + nop ++#endif + + static_trace: + MCOUNT_SAVE_REGS +@@ -133,6 +137,9 @@ static_trace: + move a1, AT /* arg2: parent's return address */ + + MCOUNT_RESTORE_REGS ++#ifdef CONFIG_32BIT ++ addiu sp, sp, 8 ++#endif + .globl ftrace_stub + ftrace_stub: + RETURN_BACK +@@ -177,6 +184,11 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra) + jal prepare_ftrace_return + nop + MCOUNT_RESTORE_REGS ++#ifndef CONFIG_DYNAMIC_FTRACE ++#ifdef CONFIG_32BIT ++ addiu sp, sp, 8 ++#endif ++#endif + RETURN_BACK + END(ftrace_graph_caller) + +diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c +index cb09862..ca16964 100644 +--- a/arch/mips/kernel/mips-mt-fpaff.c ++++ b/arch/mips/kernel/mips-mt-fpaff.c +@@ -154,7 +154,7 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len, + unsigned long __user *user_mask_ptr) + { + unsigned int real_len; +- cpumask_t mask; ++ cpumask_t allowed, mask; + int retval; + struct task_struct *p; + +@@ -173,7 +173,8 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len, + if (retval) + goto out_unlock; + +- cpumask_and(&mask, &p->thread.user_cpus_allowed, cpu_possible_mask); ++ cpumask_or(&allowed, &p->thread.user_cpus_allowed, &p->cpus_allowed); ++ cpumask_and(&mask, &allowed, cpu_active_mask); + + out_unlock: + read_unlock(&tasklist_lock); +diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c +index 6e58e97..cedeb56 100644 +--- a/arch/mips/kernel/mips_ksyms.c ++++ b/arch/mips/kernel/mips_ksyms.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + extern void *__bzero(void *__s, size_t __count); + extern long __strncpy_from_user_nocheck_asm(char *__to, +@@ -26,6 +27,13 @@ extern long __strnlen_user_nocheck_asm(const char *s); + extern long __strnlen_user_asm(const char *s); + + /* ++ * Core architecture code ++ */ ++#ifdef CONFIG_CPU_R4K_FPU ++EXPORT_SYMBOL_GPL(_save_fp); ++#endif ++ ++/* + * String functions + */ + EXPORT_SYMBOL(memset); +diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c +index 7da9b76..60f48fe 100644 +--- a/arch/mips/kernel/ptrace.c ++++ b/arch/mips/kernel/ptrace.c +@@ -170,6 +170,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) + __get_user(fregs[i], i + (__u64 __user *) data); + + __get_user(child->thread.fpu.fcr31, data + 64); ++ child->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; + + /* FIR may not be written. */ + +@@ -265,36 +266,160 @@ int ptrace_set_watch_regs(struct task_struct *child, + + /* regset get/set implementations */ + +-static int gpr_get(struct task_struct *target, +- const struct user_regset *regset, +- unsigned int pos, unsigned int count, +- void *kbuf, void __user *ubuf) ++#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32) ++ ++static int gpr32_get(struct task_struct *target, ++ const struct user_regset *regset, ++ unsigned int pos, unsigned int count, ++ void *kbuf, void __user *ubuf) + { + struct pt_regs *regs = task_pt_regs(target); ++ u32 uregs[ELF_NGREG] = {}; ++ unsigned i; + +- return user_regset_copyout(&pos, &count, &kbuf, &ubuf, +- regs, 0, sizeof(*regs)); ++ for (i = MIPS32_EF_R1; i <= MIPS32_EF_R31; i++) { ++ /* k0/k1 are copied as zero. */ ++ if (i == MIPS32_EF_R26 || i == MIPS32_EF_R27) ++ continue; ++ ++ uregs[i] = regs->regs[i - MIPS32_EF_R0]; ++ } ++ ++ uregs[MIPS32_EF_LO] = regs->lo; ++ uregs[MIPS32_EF_HI] = regs->hi; ++ uregs[MIPS32_EF_CP0_EPC] = regs->cp0_epc; ++ uregs[MIPS32_EF_CP0_BADVADDR] = regs->cp0_badvaddr; ++ uregs[MIPS32_EF_CP0_STATUS] = regs->cp0_status; ++ uregs[MIPS32_EF_CP0_CAUSE] = regs->cp0_cause; ++ ++ return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, ++ sizeof(uregs)); + } + +-static int gpr_set(struct task_struct *target, +- const struct user_regset *regset, +- unsigned int pos, unsigned int count, +- const void *kbuf, const void __user *ubuf) ++static int gpr32_set(struct task_struct *target, ++ const struct user_regset *regset, ++ unsigned int pos, unsigned int count, ++ const void *kbuf, const void __user *ubuf) + { +- struct pt_regs newregs; +- int ret; ++ struct pt_regs *regs = task_pt_regs(target); ++ u32 uregs[ELF_NGREG]; ++ unsigned start, num_regs, i; ++ int err; + +- ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, +- &newregs, +- 0, sizeof(newregs)); +- if (ret) +- return ret; ++ start = pos / sizeof(u32); ++ num_regs = count / sizeof(u32); + +- *task_pt_regs(target) = newregs; ++ if (start + num_regs > ELF_NGREG) ++ return -EIO; ++ ++ err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0, ++ sizeof(uregs)); ++ if (err) ++ return err; ++ ++ for (i = start; i < num_regs; i++) { ++ /* ++ * Cast all values to signed here so that if this is a 64-bit ++ * kernel, the supplied 32-bit values will be sign extended. ++ */ ++ switch (i) { ++ case MIPS32_EF_R1 ... MIPS32_EF_R25: ++ /* k0/k1 are ignored. */ ++ case MIPS32_EF_R28 ... MIPS32_EF_R31: ++ regs->regs[i - MIPS32_EF_R0] = (s32)uregs[i]; ++ break; ++ case MIPS32_EF_LO: ++ regs->lo = (s32)uregs[i]; ++ break; ++ case MIPS32_EF_HI: ++ regs->hi = (s32)uregs[i]; ++ break; ++ case MIPS32_EF_CP0_EPC: ++ regs->cp0_epc = (s32)uregs[i]; ++ break; ++ } ++ } + + return 0; + } + ++#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */ ++ ++#ifdef CONFIG_64BIT ++ ++static int gpr64_get(struct task_struct *target, ++ const struct user_regset *regset, ++ unsigned int pos, unsigned int count, ++ void *kbuf, void __user *ubuf) ++{ ++ struct pt_regs *regs = task_pt_regs(target); ++ u64 uregs[ELF_NGREG] = {}; ++ unsigned i; ++ ++ for (i = MIPS64_EF_R1; i <= MIPS64_EF_R31; i++) { ++ /* k0/k1 are copied as zero. */ ++ if (i == MIPS64_EF_R26 || i == MIPS64_EF_R27) ++ continue; ++ ++ uregs[i] = regs->regs[i - MIPS64_EF_R0]; ++ } ++ ++ uregs[MIPS64_EF_LO] = regs->lo; ++ uregs[MIPS64_EF_HI] = regs->hi; ++ uregs[MIPS64_EF_CP0_EPC] = regs->cp0_epc; ++ uregs[MIPS64_EF_CP0_BADVADDR] = regs->cp0_badvaddr; ++ uregs[MIPS64_EF_CP0_STATUS] = regs->cp0_status; ++ uregs[MIPS64_EF_CP0_CAUSE] = regs->cp0_cause; ++ ++ return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, ++ sizeof(uregs)); ++} ++ ++static int gpr64_set(struct task_struct *target, ++ const struct user_regset *regset, ++ unsigned int pos, unsigned int count, ++ const void *kbuf, const void __user *ubuf) ++{ ++ struct pt_regs *regs = task_pt_regs(target); ++ u64 uregs[ELF_NGREG]; ++ unsigned start, num_regs, i; ++ int err; ++ ++ start = pos / sizeof(u64); ++ num_regs = count / sizeof(u64); ++ ++ if (start + num_regs > ELF_NGREG) ++ return -EIO; ++ ++ err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0, ++ sizeof(uregs)); ++ if (err) ++ return err; ++ ++ for (i = start; i < num_regs; i++) { ++ switch (i) { ++ case MIPS64_EF_R1 ... MIPS64_EF_R25: ++ /* k0/k1 are ignored. */ ++ case MIPS64_EF_R28 ... MIPS64_EF_R31: ++ regs->regs[i - MIPS64_EF_R0] = uregs[i]; ++ break; ++ case MIPS64_EF_LO: ++ regs->lo = uregs[i]; ++ break; ++ case MIPS64_EF_HI: ++ regs->hi = uregs[i]; ++ break; ++ case MIPS64_EF_CP0_EPC: ++ regs->cp0_epc = uregs[i]; ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++#endif /* CONFIG_64BIT */ ++ + static int fpr_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, +@@ -322,14 +447,16 @@ enum mips_regset { + REGSET_FPR, + }; + ++#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32) ++ + static const struct user_regset mips_regsets[] = { + [REGSET_GPR] = { + .core_note_type = NT_PRSTATUS, + .n = ELF_NGREG, + .size = sizeof(unsigned int), + .align = sizeof(unsigned int), +- .get = gpr_get, +- .set = gpr_set, ++ .get = gpr32_get, ++ .set = gpr32_set, + }, + [REGSET_FPR] = { + .core_note_type = NT_PRFPREG, +@@ -349,14 +476,18 @@ static const struct user_regset_view user_mips_view = { + .n = ARRAY_SIZE(mips_regsets), + }; + ++#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */ ++ ++#ifdef CONFIG_64BIT ++ + static const struct user_regset mips64_regsets[] = { + [REGSET_GPR] = { + .core_note_type = NT_PRSTATUS, + .n = ELF_NGREG, + .size = sizeof(unsigned long), + .align = sizeof(unsigned long), +- .get = gpr_get, +- .set = gpr_set, ++ .get = gpr64_get, ++ .set = gpr64_set, + }, + [REGSET_FPR] = { + .core_note_type = NT_PRFPREG, +@@ -369,25 +500,26 @@ static const struct user_regset mips64_regsets[] = { + }; + + static const struct user_regset_view user_mips64_view = { +- .name = "mips", ++ .name = "mips64", + .e_machine = ELF_ARCH, + .ei_osabi = ELF_OSABI, + .regsets = mips64_regsets, +- .n = ARRAY_SIZE(mips_regsets), ++ .n = ARRAY_SIZE(mips64_regsets), + }; + ++#endif /* CONFIG_64BIT */ ++ + const struct user_regset_view *task_user_regset_view(struct task_struct *task) + { + #ifdef CONFIG_32BIT + return &user_mips_view; +-#endif +- ++#else + #ifdef CONFIG_MIPS32_O32 +- if (test_thread_flag(TIF_32BIT_REGS)) +- return &user_mips_view; ++ if (test_tsk_thread_flag(task, TIF_32BIT_REGS)) ++ return &user_mips_view; + #endif +- + return &user_mips64_view; ++#endif + } + + long arch_ptrace(struct task_struct *child, long request, +@@ -593,7 +725,7 @@ long arch_ptrace(struct task_struct *child, long request, + break; + #endif + case FPC_CSR: +- child->thread.fpu.fcr31 = data; ++ child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X; + break; + case DSP_BASE ... DSP_BASE + 5: { + dspreg_t *dregs; +diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c +index 3d60f77..ea585cf 100644 +--- a/arch/mips/kernel/signal32.c ++++ b/arch/mips/kernel/signal32.c +@@ -370,8 +370,6 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) + + int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) + { +- memset(to, 0, sizeof *to); +- + if (copy_from_user(to, from, 3*sizeof(int)) || + copy_from_user(to->_sifields._pad, + from->_sifields._pad, SI_PAD_SIZE32)) +diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c +index 0a022ee..18ed112 100644 +--- a/arch/mips/kernel/smp.c ++++ b/arch/mips/kernel/smp.c +@@ -109,10 +109,10 @@ asmlinkage void start_secondary(void) + else + #endif /* CONFIG_MIPS_MT_SMTC */ + cpu_probe(); +- cpu_report(); + per_cpu_trap_init(false); + mips_clockevent_init(); + mp_ops->init_secondary(); ++ cpu_report(); + + /* + * XXX parity protection should be folded in here when it's converted +diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c +index c369a5d..b897dde 100644 +--- a/arch/mips/kernel/unaligned.c ++++ b/arch/mips/kernel/unaligned.c +@@ -605,7 +605,6 @@ static void emulate_load_store_insn(struct pt_regs *regs, + case sdc1_op: + die_if_kernel("Unaligned FP access in kernel code", regs); + BUG_ON(!used_math()); +- BUG_ON(!is_fpu_owner()); + + lose_fpu(1); /* Save FPU state for the emulator. */ + res = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, +diff --git a/arch/mips/kvm/kvm_locore.S b/arch/mips/kvm/kvm_locore.S +index bbace09..03a2db5 100644 +--- a/arch/mips/kvm/kvm_locore.S ++++ b/arch/mips/kvm/kvm_locore.S +@@ -428,7 +428,7 @@ __kvm_mips_return_to_guest: + /* Setup status register for running guest in UM */ + .set at + or v1, v1, (ST0_EXL | KSU_USER | ST0_IE) +- and v1, v1, ~ST0_CU0 ++ and v1, v1, ~(ST0_CU0 | ST0_MX) + .set noat + mtc0 v1, CP0_STATUS + ehb +diff --git a/arch/mips/kvm/kvm_mips.c b/arch/mips/kvm/kvm_mips.c +index 3e0ff8d..897c605 100644 +--- a/arch/mips/kvm/kvm_mips.c ++++ b/arch/mips/kvm/kvm_mips.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -418,11 +419,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) + vcpu->mmio_needed = 0; + } + ++ lose_fpu(1); ++ ++ local_irq_disable(); + /* Check if we have any exceptions/interrupts pending */ + kvm_mips_deliver_interrupts(vcpu, + kvm_read_c0_guest_cause(vcpu->arch.cop0)); + +- local_irq_disable(); + kvm_guest_enter(); + + r = __kvm_mips_vcpu_run(run, vcpu); +@@ -1021,9 +1024,6 @@ void kvm_mips_set_c0_status(void) + { + uint32_t status = read_c0_status(); + +- if (cpu_has_fpu) +- status |= (ST0_CU1); +- + if (cpu_has_dsp) + status |= (ST0_MX); + +diff --git a/arch/mips/kvm/kvm_mips_emul.c b/arch/mips/kvm/kvm_mips_emul.c +index e75ef82..c76f297 100644 +--- a/arch/mips/kvm/kvm_mips_emul.c ++++ b/arch/mips/kvm/kvm_mips_emul.c +@@ -1626,7 +1626,7 @@ kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run) + if (vcpu->mmio_needed == 2) + *gpr = *(int16_t *) run->mmio.data; + else +- *gpr = *(int16_t *) run->mmio.data; ++ *gpr = *(uint16_t *)run->mmio.data; + + break; + case 1: +diff --git a/arch/mips/kvm/trace.h b/arch/mips/kvm/trace.h +index bc9e0f4..e51621e 100644 +--- a/arch/mips/kvm/trace.h ++++ b/arch/mips/kvm/trace.h +@@ -26,18 +26,18 @@ TRACE_EVENT(kvm_exit, + TP_PROTO(struct kvm_vcpu *vcpu, unsigned int reason), + TP_ARGS(vcpu, reason), + TP_STRUCT__entry( +- __field(struct kvm_vcpu *, vcpu) ++ __field(unsigned long, pc) + __field(unsigned int, reason) + ), + + TP_fast_assign( +- __entry->vcpu = vcpu; ++ __entry->pc = vcpu->arch.pc; + __entry->reason = reason; + ), + + TP_printk("[%s]PC: 0x%08lx", + kvm_mips_exit_types_str[__entry->reason], +- __entry->vcpu->arch.pc) ++ __entry->pc) + ); + + #endif /* _TRACE_KVM_H */ +diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile +index 9e4484c..9005a8d6 100644 +--- a/arch/mips/loongson/common/Makefile ++++ b/arch/mips/loongson/common/Makefile +@@ -11,7 +11,8 @@ obj-$(CONFIG_PCI) += pci.o + # Serial port support + # + obj-$(CONFIG_EARLY_PRINTK) += early_printk.o +-obj-$(CONFIG_SERIAL_8250) += serial.o ++loongson-serial-$(CONFIG_SERIAL_8250) := serial.o ++obj-y += $(loongson-serial-m) $(loongson-serial-y) + obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o + obj-$(CONFIG_LOONGSON_MC146818) += rtc.o + +diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c +index becc42b..70ab5d6 100644 +--- a/arch/mips/mm/fault.c ++++ b/arch/mips/mm/fault.c +@@ -158,6 +158,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c +index b234b1b..dd012c5 100644 +--- a/arch/mips/mm/tlbex.c ++++ b/arch/mips/mm/tlbex.c +@@ -1057,6 +1057,7 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) + struct mips_huge_tlb_info { + int huge_pte; + int restore_scratch; ++ bool need_reload_pte; + }; + + static struct mips_huge_tlb_info +@@ -1071,6 +1072,7 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, + + rv.huge_pte = scratch; + rv.restore_scratch = 0; ++ rv.need_reload_pte = false; + + if (check_for_high_segbits) { + UASM_i_MFC0(p, tmp, C0_BADVADDR); +@@ -1259,6 +1261,7 @@ static void build_r4000_tlb_refill_handler(void) + } else { + htlb_info.huge_pte = K0; + htlb_info.restore_scratch = 0; ++ htlb_info.need_reload_pte = true; + vmalloc_mode = refill_noscratch; + /* + * create the plain linear handler +@@ -1295,6 +1298,8 @@ static void build_r4000_tlb_refill_handler(void) + } + #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT + uasm_l_tlb_huge_update(&l, p); ++ if (htlb_info.need_reload_pte) ++ UASM_i_LW(&p, htlb_info.huge_pte, 0, K1); + build_huge_update_entries(&p, htlb_info.huge_pte, K1); + build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random, + htlb_info.restore_scratch); +diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c +index 3190099..d4ab447 100644 +--- a/arch/mips/mti-malta/malta-time.c ++++ b/arch/mips/mti-malta/malta-time.c +@@ -168,14 +168,17 @@ unsigned int get_c0_compare_int(void) + + static void __init init_rtc(void) + { +- /* stop the clock whilst setting it up */ +- CMOS_WRITE(RTC_SET | RTC_24H, RTC_CONTROL); ++ unsigned char freq, ctrl; + +- /* 32KHz time base */ +- CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_FREQ_SELECT); ++ /* Set 32KHz time base if not already set */ ++ freq = CMOS_READ(RTC_FREQ_SELECT); ++ if ((freq & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ) ++ CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_FREQ_SELECT); + +- /* start the clock */ +- CMOS_WRITE(RTC_24H, RTC_CONTROL); ++ /* Ensure SET bit is clear so RTC can run */ ++ ctrl = CMOS_READ(RTC_CONTROL); ++ if (ctrl & RTC_SET) ++ CMOS_WRITE(ctrl & ~RTC_SET, RTC_CONTROL); + } + + void __init plat_time_init(void) +diff --git a/arch/mips/oprofile/backtrace.c b/arch/mips/oprofile/backtrace.c +index 6854ed5..83a1dfd 100644 +--- a/arch/mips/oprofile/backtrace.c ++++ b/arch/mips/oprofile/backtrace.c +@@ -92,7 +92,7 @@ static inline int unwind_user_frame(struct stackframe *old_frame, + /* This marks the end of the previous function, + which means we overran. */ + break; +- stack_size = (unsigned) stack_adjustment; ++ stack_size = (unsigned long) stack_adjustment; + } else if (is_ra_save_ins(&ip)) { + int ra_slot = ip.i_format.simmediate; + if (ra_slot < 0) +diff --git a/arch/mips/power/cpu.c b/arch/mips/power/cpu.c +index 521e596..2129e67 100644 +--- a/arch/mips/power/cpu.c ++++ b/arch/mips/power/cpu.c +@@ -7,7 +7,7 @@ + * Author: Hu Hongbing + * Wu Zhangjin + */ +-#include ++#include + #include + #include + +diff --git a/arch/mips/power/hibernate.S b/arch/mips/power/hibernate.S +index 32a7c82..e7567c8 100644 +--- a/arch/mips/power/hibernate.S ++++ b/arch/mips/power/hibernate.S +@@ -30,6 +30,8 @@ LEAF(swsusp_arch_suspend) + END(swsusp_arch_suspend) + + LEAF(swsusp_arch_resume) ++ /* Avoid TLB mismatch during and after kernel resume */ ++ jal local_flush_tlb_all + PTR_L t0, restore_pblist + 0: + PTR_L t1, PBE_ADDRESS(t0) /* source */ +@@ -43,7 +45,6 @@ LEAF(swsusp_arch_resume) + bne t1, t3, 1b + PTR_L t0, PBE_NEXT(t0) + bnez t0, 0b +- jal local_flush_tlb_all /* Avoid TLB mismatch after kernel resume */ + PTR_LA t0, saved_regs + PTR_L ra, PT_R31(t0) + PTR_L sp, PT_R29(t0) +diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c +index 3516cbd..0c2cc5d 100644 +--- a/arch/mn10300/mm/fault.c ++++ b/arch/mn10300/mm/fault.c +@@ -262,6 +262,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c +index 0703acf..230ac20 100644 +--- a/arch/openrisc/mm/fault.c ++++ b/arch/openrisc/mm/fault.c +@@ -171,6 +171,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile +index 7187664..5db8882 100644 +--- a/arch/parisc/Makefile ++++ b/arch/parisc/Makefile +@@ -48,7 +48,12 @@ cflags-y := -pipe + + # These flags should be implied by an hppa-linux configuration, but they + # are not in gcc 3.2. +-cflags-y += -mno-space-regs -mfast-indirect-calls ++cflags-y += -mno-space-regs ++ ++# -mfast-indirect-calls is only relevant for 32-bit kernels. ++ifndef CONFIG_64BIT ++cflags-y += -mfast-indirect-calls ++endif + + # Currently we save and restore fpregs on all kernel entry/interruption paths. + # If that gets optimized, we might need to disable the use of fpregs in the +diff --git a/arch/parisc/include/asm/ldcw.h b/arch/parisc/include/asm/ldcw.h +index d2d11b7..8121aa6 100644 +--- a/arch/parisc/include/asm/ldcw.h ++++ b/arch/parisc/include/asm/ldcw.h +@@ -33,11 +33,18 @@ + + #endif /*!CONFIG_PA20*/ + +-/* LDCW, the only atomic read-write operation PA-RISC has. *sigh*. */ ++/* LDCW, the only atomic read-write operation PA-RISC has. *sigh*. ++ We don't explicitly expose that "*a" may be written as reload ++ fails to find a register in class R1_REGS when "a" needs to be ++ reloaded when generating 64-bit PIC code. Instead, we clobber ++ memory to indicate to the compiler that the assembly code reads ++ or writes to items other than those listed in the input and output ++ operands. This may pessimize the code somewhat but __ldcw is ++ usually used within code blocks surrounded by memory barriors. */ + #define __ldcw(a) ({ \ + unsigned __ret; \ +- __asm__ __volatile__(__LDCW " 0(%2),%0" \ +- : "=r" (__ret), "+m" (*(a)) : "r" (a)); \ ++ __asm__ __volatile__(__LDCW " 0(%1),%0" \ ++ : "=r" (__ret) : "r" (a) : "memory"); \ + __ret; \ + }) + +diff --git a/arch/parisc/include/uapi/asm/shmbuf.h b/arch/parisc/include/uapi/asm/shmbuf.h +index 0a3eada..f395cde 100644 +--- a/arch/parisc/include/uapi/asm/shmbuf.h ++++ b/arch/parisc/include/uapi/asm/shmbuf.h +@@ -36,23 +36,16 @@ struct shmid64_ds { + unsigned int __unused2; + }; + +-#ifdef CONFIG_64BIT +-/* The 'unsigned int' (formerly 'unsigned long') data types below will +- * ensure that a 32-bit app calling shmctl(*,IPC_INFO,*) will work on +- * a wide kernel, but if some of these values are meant to contain pointers +- * they may need to be 'long long' instead. -PB XXX FIXME +- */ +-#endif + struct shminfo64 { +- unsigned int shmmax; +- unsigned int shmmin; +- unsigned int shmmni; +- unsigned int shmseg; +- unsigned int shmall; +- unsigned int __unused1; +- unsigned int __unused2; +- unsigned int __unused3; +- unsigned int __unused4; ++ unsigned long shmmax; ++ unsigned long shmmin; ++ unsigned long shmmni; ++ unsigned long shmseg; ++ unsigned long shmall; ++ unsigned long __unused1; ++ unsigned long __unused2; ++ unsigned long __unused3; ++ unsigned long __unused4; + }; + + #endif /* _PARISC_SHMBUF_H */ +diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h +index a2fa2971..f5645d6 100644 +--- a/arch/parisc/include/uapi/asm/signal.h ++++ b/arch/parisc/include/uapi/asm/signal.h +@@ -69,8 +69,6 @@ + #define SA_NOMASK SA_NODEFER + #define SA_ONESHOT SA_RESETHAND + +-#define SA_RESTORER 0x04000000 /* obsolete -- ignored */ +- + #define MINSIGSTKSZ 2048 + #define SIGSTKSZ 8192 + +diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S +index 8387860..7ef22e3 100644 +--- a/arch/parisc/kernel/syscall.S ++++ b/arch/parisc/kernel/syscall.S +@@ -74,7 +74,7 @@ ENTRY(linux_gateway_page) + /* ADDRESS 0xb0 to 0xb8, lws uses two insns for entry */ + /* Light-weight-syscall entry must always be located at 0xb0 */ + /* WARNING: Keep this number updated with table size changes */ +-#define __NR_lws_entries (2) ++#define __NR_lws_entries (3) + + lws_entry: + gate lws_start, %r0 /* increase privilege */ +@@ -502,7 +502,7 @@ lws_exit: + + + /*************************************************** +- Implementing CAS as an atomic operation: ++ Implementing 32bit CAS as an atomic operation: + + %r26 - Address to examine + %r25 - Old value to check (old) +@@ -659,6 +659,230 @@ cas_action: + ASM_EXCEPTIONTABLE_ENTRY(2b-linux_gateway_page, 3b-linux_gateway_page) + + ++ /*************************************************** ++ New CAS implementation which uses pointers and variable size ++ information. The value pointed by old and new MUST NOT change ++ while performing CAS. The lock only protect the value at %r26. ++ ++ %r26 - Address to examine ++ %r25 - Pointer to the value to check (old) ++ %r24 - Pointer to the value to set (new) ++ %r23 - Size of the variable (0/1/2/3 for 8/16/32/64 bit) ++ %r28 - Return non-zero on failure ++ %r21 - Kernel error code ++ ++ %r21 has the following meanings: ++ ++ EAGAIN - CAS is busy, ldcw failed, try again. ++ EFAULT - Read or write failed. ++ ++ Scratch: r20, r22, r28, r29, r1, fr4 (32bit for 64bit CAS only) ++ ++ ****************************************************/ ++ ++ /* ELF32 Process entry path */ ++lws_compare_and_swap_2: ++#ifdef CONFIG_64BIT ++ /* Clip the input registers */ ++ depdi 0, 31, 32, %r26 ++ depdi 0, 31, 32, %r25 ++ depdi 0, 31, 32, %r24 ++ depdi 0, 31, 32, %r23 ++#endif ++ ++ /* Check the validity of the size pointer */ ++ subi,>>= 4, %r23, %r0 ++ b,n lws_exit_nosys ++ ++ /* Jump to the functions which will load the old and new values into ++ registers depending on the their size */ ++ shlw %r23, 2, %r29 ++ blr %r29, %r0 ++ nop ++ ++ /* 8bit load */ ++4: ldb 0(%sr3,%r25), %r25 ++ b cas2_lock_start ++5: ldb 0(%sr3,%r24), %r24 ++ nop ++ nop ++ nop ++ nop ++ nop ++ ++ /* 16bit load */ ++6: ldh 0(%sr3,%r25), %r25 ++ b cas2_lock_start ++7: ldh 0(%sr3,%r24), %r24 ++ nop ++ nop ++ nop ++ nop ++ nop ++ ++ /* 32bit load */ ++8: ldw 0(%sr3,%r25), %r25 ++ b cas2_lock_start ++9: ldw 0(%sr3,%r24), %r24 ++ nop ++ nop ++ nop ++ nop ++ nop ++ ++ /* 64bit load */ ++#ifdef CONFIG_64BIT ++10: ldd 0(%sr3,%r25), %r25 ++11: ldd 0(%sr3,%r24), %r24 ++#else ++ /* Load new value into r22/r23 - high/low */ ++10: ldw 0(%sr3,%r25), %r22 ++11: ldw 4(%sr3,%r25), %r23 ++ /* Load new value into fr4 for atomic store later */ ++12: flddx 0(%sr3,%r24), %fr4 ++#endif ++ ++cas2_lock_start: ++ /* Load start of lock table */ ++ ldil L%lws_lock_start, %r20 ++ ldo R%lws_lock_start(%r20), %r28 ++ ++ /* Extract four bits from r26 and hash lock (Bits 4-7) */ ++ extru %r26, 27, 4, %r20 ++ ++ /* Find lock to use, the hash is either one of 0 to ++ 15, multiplied by 16 (keep it 16-byte aligned) ++ and add to the lock table offset. */ ++ shlw %r20, 4, %r20 ++ add %r20, %r28, %r20 ++ ++ rsm PSW_SM_I, %r0 /* Disable interrupts */ ++ /* COW breaks can cause contention on UP systems */ ++ LDCW 0(%sr2,%r20), %r28 /* Try to acquire the lock */ ++ cmpb,<>,n %r0, %r28, cas2_action /* Did we get it? */ ++cas2_wouldblock: ++ ldo 2(%r0), %r28 /* 2nd case */ ++ ssm PSW_SM_I, %r0 ++ b lws_exit /* Contended... */ ++ ldo -EAGAIN(%r0), %r21 /* Spin in userspace */ ++ ++ /* ++ prev = *addr; ++ if ( prev == old ) ++ *addr = new; ++ return prev; ++ */ ++ ++ /* NOTES: ++ This all works becuse intr_do_signal ++ and schedule both check the return iasq ++ and see that we are on the kernel page ++ so this process is never scheduled off ++ or is ever sent any signal of any sort, ++ thus it is wholly atomic from usrspaces ++ perspective ++ */ ++cas2_action: ++ /* Jump to the correct function */ ++ blr %r29, %r0 ++ /* Set %r28 as non-zero for now */ ++ ldo 1(%r0),%r28 ++ ++ /* 8bit CAS */ ++13: ldb,ma 0(%sr3,%r26), %r29 ++ sub,= %r29, %r25, %r0 ++ b,n cas2_end ++14: stb,ma %r24, 0(%sr3,%r26) ++ b cas2_end ++ copy %r0, %r28 ++ nop ++ nop ++ ++ /* 16bit CAS */ ++15: ldh,ma 0(%sr3,%r26), %r29 ++ sub,= %r29, %r25, %r0 ++ b,n cas2_end ++16: sth,ma %r24, 0(%sr3,%r26) ++ b cas2_end ++ copy %r0, %r28 ++ nop ++ nop ++ ++ /* 32bit CAS */ ++17: ldw,ma 0(%sr3,%r26), %r29 ++ sub,= %r29, %r25, %r0 ++ b,n cas2_end ++18: stw,ma %r24, 0(%sr3,%r26) ++ b cas2_end ++ copy %r0, %r28 ++ nop ++ nop ++ ++ /* 64bit CAS */ ++#ifdef CONFIG_64BIT ++19: ldd,ma 0(%sr3,%r26), %r29 ++ sub,= %r29, %r25, %r0 ++ b,n cas2_end ++20: std,ma %r24, 0(%sr3,%r26) ++ copy %r0, %r28 ++#else ++ /* Compare first word */ ++19: ldw,ma 0(%sr3,%r26), %r29 ++ sub,= %r29, %r22, %r0 ++ b,n cas2_end ++ /* Compare second word */ ++20: ldw,ma 4(%sr3,%r26), %r29 ++ sub,= %r29, %r23, %r0 ++ b,n cas2_end ++ /* Perform the store */ ++21: fstdx %fr4, 0(%sr3,%r26) ++ copy %r0, %r28 ++#endif ++ ++cas2_end: ++ /* Free lock */ ++ stw,ma %r20, 0(%sr2,%r20) ++ /* Enable interrupts */ ++ ssm PSW_SM_I, %r0 ++ /* Return to userspace, set no error */ ++ b lws_exit ++ copy %r0, %r21 ++ ++22: ++ /* Error occurred on load or store */ ++ /* Free lock */ ++ stw %r20, 0(%sr2,%r20) ++ ssm PSW_SM_I, %r0 ++ ldo 1(%r0),%r28 ++ b lws_exit ++ ldo -EFAULT(%r0),%r21 /* set errno */ ++ nop ++ nop ++ nop ++ ++ /* Exception table entries, for the load and store, return EFAULT. ++ Each of the entries must be relocated. */ ++ ASM_EXCEPTIONTABLE_ENTRY(4b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(5b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(6b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(7b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(8b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(9b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(10b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(11b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(13b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(14b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(15b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(16b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(17b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(18b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(19b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(20b-linux_gateway_page, 22b-linux_gateway_page) ++#ifndef CONFIG_64BIT ++ ASM_EXCEPTIONTABLE_ENTRY(12b-linux_gateway_page, 22b-linux_gateway_page) ++ ASM_EXCEPTIONTABLE_ENTRY(21b-linux_gateway_page, 22b-linux_gateway_page) ++#endif ++ + /* Make sure nothing else is placed on this page */ + .align PAGE_SIZE + END(linux_gateway_page) +@@ -675,8 +899,9 @@ ENTRY(end_linux_gateway_page) + /* Light-weight-syscall table */ + /* Start of lws table. */ + ENTRY(lws_table) +- LWS_ENTRY(compare_and_swap32) /* 0 - ELF32 Atomic compare and swap */ +- LWS_ENTRY(compare_and_swap64) /* 1 - ELF64 Atomic compare and swap */ ++ LWS_ENTRY(compare_and_swap32) /* 0 - ELF32 Atomic 32bit CAS */ ++ LWS_ENTRY(compare_and_swap64) /* 1 - ELF64 Atomic 32bit CAS */ ++ LWS_ENTRY(compare_and_swap_2) /* 2 - ELF32 Atomic 64bit CAS */ + END(lws_table) + /* End of lws table */ + +diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S +index 7dd8a3b..fc77d53 100644 +--- a/arch/parisc/kernel/syscall_table.S ++++ b/arch/parisc/kernel/syscall_table.S +@@ -286,11 +286,11 @@ + ENTRY_COMP(msgsnd) + ENTRY_COMP(msgrcv) + ENTRY_SAME(msgget) /* 190 */ +- ENTRY_SAME(msgctl) +- ENTRY_SAME(shmat) ++ ENTRY_COMP(msgctl) ++ ENTRY_COMP(shmat) + ENTRY_SAME(shmdt) + ENTRY_SAME(shmget) +- ENTRY_SAME(shmctl) /* 195 */ ++ ENTRY_COMP(shmctl) /* 195 */ + ENTRY_SAME(ni_syscall) /* streams1 */ + ENTRY_SAME(ni_syscall) /* streams2 */ + ENTRY_SAME(lstat64) +@@ -323,7 +323,7 @@ + ENTRY_SAME(epoll_ctl) /* 225 */ + ENTRY_SAME(epoll_wait) + ENTRY_SAME(remap_file_pages) +- ENTRY_SAME(semtimedop) ++ ENTRY_COMP(semtimedop) + ENTRY_COMP(mq_open) + ENTRY_SAME(mq_unlink) /* 230 */ + ENTRY_COMP(mq_timedsend) +diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c +index d72197f..d27e388 100644 +--- a/arch/parisc/mm/fault.c ++++ b/arch/parisc/mm/fault.c +@@ -256,6 +256,8 @@ good_area: + */ + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto bad_area; + BUG(); +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi +index 1382fec..7fcb1ac 100644 +--- a/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi +@@ -50,6 +50,7 @@ ethernet@b0000 { + fsl,num_tx_queues = <0x8>; + fsl,magic-packet; + local-mac-address = [ 00 00 00 00 00 00 ]; ++ ranges; + + queue-group@b0000 { + #address-cells = <1>; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi +index 221cd2e..9f25427 100644 +--- a/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi +@@ -50,6 +50,7 @@ ethernet@b1000 { + fsl,num_tx_queues = <0x8>; + fsl,magic-packet; + local-mac-address = [ 00 00 00 00 00 00 ]; ++ ranges; + + queue-group@b1000 { + #address-cells = <1>; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi +index 61456c3..cd7c318 100644 +--- a/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi +@@ -49,6 +49,7 @@ ethernet@b2000 { + fsl,num_tx_queues = <0x8>; + fsl,magic-packet; + local-mac-address = [ 00 00 00 00 00 00 ]; ++ ranges; + + queue-group@b2000 { + #address-cells = <1>; +diff --git a/arch/powerpc/crypto/sha1.c b/arch/powerpc/crypto/sha1.c +index f9e8b94..b51da91 100644 +--- a/arch/powerpc/crypto/sha1.c ++++ b/arch/powerpc/crypto/sha1.c +@@ -154,4 +154,5 @@ module_exit(sha1_powerpc_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); + +-MODULE_ALIAS("sha1-powerpc"); ++MODULE_ALIAS_CRYPTO("sha1"); ++MODULE_ALIAS_CRYPTO("sha1-powerpc"); +diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h +index ad3025d..f207868 100644 +--- a/arch/powerpc/include/asm/machdep.h ++++ b/arch/powerpc/include/asm/machdep.h +@@ -57,10 +57,10 @@ struct machdep_calls { + void (*hpte_removebolted)(unsigned long ea, + int psize, int ssize); + void (*flush_hash_range)(unsigned long number, int local); +- void (*hugepage_invalidate)(struct mm_struct *mm, ++ void (*hugepage_invalidate)(unsigned long vsid, ++ unsigned long addr, + unsigned char *hpte_slot_array, +- unsigned long addr, int psize); +- ++ int psize, int ssize); + /* special for kexec, to be called in real mode, linear mapping is + * destroyed as well */ + void (*hpte_clear_all)(void); +diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h +index eb92610..7b3d54f 100644 +--- a/arch/powerpc/include/asm/pgtable-ppc64.h ++++ b/arch/powerpc/include/asm/pgtable-ppc64.h +@@ -413,7 +413,7 @@ static inline char *get_hpte_slot_array(pmd_t *pmdp) + } + + extern void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, +- pmd_t *pmdp); ++ pmd_t *pmdp, unsigned long old_pmd); + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + extern pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot); + extern pmd_t mk_pmd(struct page *page, pgprot_t pgprot); +diff --git a/arch/powerpc/include/asm/pte-hash64-64k.h b/arch/powerpc/include/asm/pte-hash64-64k.h +index d836d94..9ecede1 100644 +--- a/arch/powerpc/include/asm/pte-hash64-64k.h ++++ b/arch/powerpc/include/asm/pte-hash64-64k.h +@@ -46,11 +46,31 @@ + * in order to deal with 64K made of 4K HW pages. Thus we override the + * generic accessors and iterators here + */ +-#define __real_pte(e,p) ((real_pte_t) { \ +- (e), (pte_val(e) & _PAGE_COMBO) ? \ +- (pte_val(*((p) + PTRS_PER_PTE))) : 0 }) +-#define __rpte_to_hidx(r,index) ((pte_val((r).pte) & _PAGE_COMBO) ? \ +- (((r).hidx >> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf)) ++#define __real_pte __real_pte ++static inline real_pte_t __real_pte(pte_t pte, pte_t *ptep) ++{ ++ real_pte_t rpte; ++ ++ rpte.pte = pte; ++ rpte.hidx = 0; ++ if (pte_val(pte) & _PAGE_COMBO) { ++ /* ++ * Make sure we order the hidx load against the _PAGE_COMBO ++ * check. The store side ordering is done in __hash_page_4K ++ */ ++ smp_rmb(); ++ rpte.hidx = pte_val(*((ptep) + PTRS_PER_PTE)); ++ } ++ return rpte; ++} ++ ++static inline unsigned long __rpte_to_hidx(real_pte_t rpte, unsigned long index) ++{ ++ if ((pte_val(rpte.pte) & _PAGE_COMBO)) ++ return (rpte.hidx >> (index<<2)) & 0xf; ++ return (pte_val(rpte.pte) >> 12) & 0xf; ++} ++ + #define __rpte_to_pte(r) ((r).pte) + #define __rpte_sub_valid(rpte, index) \ + (pte_val(rpte.pte) & (_PAGE_HPTE_SUB0 >> (index))) +diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h +index 279b80f..c0c61fa 100644 +--- a/arch/powerpc/include/asm/ptrace.h ++++ b/arch/powerpc/include/asm/ptrace.h +@@ -47,6 +47,12 @@ + STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE) + #define STACK_FRAME_MARKER 12 + ++#if defined(_CALL_ELF) && _CALL_ELF == 2 ++#define STACK_FRAME_MIN_SIZE 32 ++#else ++#define STACK_FRAME_MIN_SIZE STACK_FRAME_OVERHEAD ++#endif ++ + /* Size of dummy stack frame allocated when calling signal handler. */ + #define __SIGNAL_FRAMESIZE 128 + #define __SIGNAL_FRAMESIZE32 64 +@@ -60,6 +66,7 @@ + #define STACK_FRAME_REGS_MARKER ASM_CONST(0x72656773) + #define STACK_INT_FRAME_SIZE (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD) + #define STACK_FRAME_MARKER 2 ++#define STACK_FRAME_MIN_SIZE STACK_FRAME_OVERHEAD + + /* Size of stack frame allocated when calling signal handler. */ + #define __SIGNAL_FRAMESIZE 64 +diff --git a/arch/powerpc/include/asm/spinlock.h b/arch/powerpc/include/asm/spinlock.h +index 35aa339..4dbe072 100644 +--- a/arch/powerpc/include/asm/spinlock.h ++++ b/arch/powerpc/include/asm/spinlock.h +@@ -61,6 +61,7 @@ static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock) + + static inline int arch_spin_is_locked(arch_spinlock_t *lock) + { ++ smp_mb(); + return !arch_spin_value_unlocked(*lock); + } + +diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c +index 2912b87..3eb36ce 100644 +--- a/arch/powerpc/kernel/cacheinfo.c ++++ b/arch/powerpc/kernel/cacheinfo.c +@@ -61,12 +61,22 @@ struct cache_type_info { + }; + + /* These are used to index the cache_type_info array. */ +-#define CACHE_TYPE_UNIFIED 0 +-#define CACHE_TYPE_INSTRUCTION 1 +-#define CACHE_TYPE_DATA 2 ++#define CACHE_TYPE_UNIFIED 0 /* cache-size, cache-block-size, etc. */ ++#define CACHE_TYPE_UNIFIED_D 1 /* d-cache-size, d-cache-block-size, etc */ ++#define CACHE_TYPE_INSTRUCTION 2 ++#define CACHE_TYPE_DATA 3 + + static const struct cache_type_info cache_type_info[] = { + { ++ /* Embedded systems that use cache-size, cache-block-size, ++ * etc. for the Unified (typically L2) cache. */ ++ .name = "Unified", ++ .size_prop = "cache-size", ++ .line_size_props = { "cache-line-size", ++ "cache-block-size", }, ++ .nr_sets_prop = "cache-sets", ++ }, ++ { + /* PowerPC Processor binding says the [di]-cache-* + * must be equal on unified caches, so just use + * d-cache properties. */ +@@ -293,7 +303,8 @@ static struct cache *cache_find_first_sibling(struct cache *cache) + { + struct cache *iter; + +- if (cache->type == CACHE_TYPE_UNIFIED) ++ if (cache->type == CACHE_TYPE_UNIFIED || ++ cache->type == CACHE_TYPE_UNIFIED_D) + return cache; + + list_for_each_entry(iter, &cache_list, list) +@@ -324,16 +335,29 @@ static bool cache_node_is_unified(const struct device_node *np) + return of_get_property(np, "cache-unified", NULL); + } + +-static struct cache *cache_do_one_devnode_unified(struct device_node *node, +- int level) ++/* ++ * Unified caches can have two different sets of tags. Most embedded ++ * use cache-size, etc. for the unified cache size, but open firmware systems ++ * use d-cache-size, etc. Check on initialization for which type we have, and ++ * return the appropriate structure type. Assume it's embedded if it isn't ++ * open firmware. If it's yet a 3rd type, then there will be missing entries ++ * in /sys/devices/system/cpu/cpu0/cache/index2/, and this code will need ++ * to be extended further. ++ */ ++static int cache_is_unified_d(const struct device_node *np) + { +- struct cache *cache; ++ return of_get_property(np, ++ cache_type_info[CACHE_TYPE_UNIFIED_D].size_prop, NULL) ? ++ CACHE_TYPE_UNIFIED_D : CACHE_TYPE_UNIFIED; ++} + ++/* ++ */ ++static struct cache *cache_do_one_devnode_unified(struct device_node *node, int level) ++{ + pr_debug("creating L%d ucache for %s\n", level, node->full_name); + +- cache = new_cache(CACHE_TYPE_UNIFIED, level, node); +- +- return cache; ++ return new_cache(cache_is_unified_d(node), level, node); + } + + static struct cache *cache_do_one_devnode_split(struct device_node *node, +diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S +index 38d5073..5193116 100644 +--- a/arch/powerpc/kernel/exceptions-64s.S ++++ b/arch/powerpc/kernel/exceptions-64s.S +@@ -1422,7 +1422,7 @@ machine_check_handle_early: + bne 9f /* continue in V mode if we are. */ + + 5: +-#ifdef CONFIG_KVM_BOOK3S_64_HV ++#ifdef CONFIG_KVM_BOOK3S_64_HANDLER + /* + * We are coming from kernel context. Check if we are coming from + * guest. if yes, then we can continue. We will fall through +diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c +index 27c93f4..fc0927a 100644 +--- a/arch/powerpc/kernel/mce_power.c ++++ b/arch/powerpc/kernel/mce_power.c +@@ -78,7 +78,7 @@ static long mce_handle_derror(uint64_t dsisr, uint64_t slb_error_bits) + } + if (dsisr & P7_DSISR_MC_TLB_MULTIHIT_MFTLB) { + if (cur_cpu_spec && cur_cpu_spec->flush_tlb) +- cur_cpu_spec->flush_tlb(TLBIEL_INVAL_PAGE); ++ cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET); + /* reset error bits */ + dsisr &= ~P7_DSISR_MC_TLB_MULTIHIT_MFTLB; + } +@@ -109,7 +109,7 @@ static long mce_handle_common_ierror(uint64_t srr1) + break; + case P7_SRR1_MC_IFETCH_TLB_MULTIHIT: + if (cur_cpu_spec && cur_cpu_spec->flush_tlb) { +- cur_cpu_spec->flush_tlb(TLBIEL_INVAL_PAGE); ++ cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET); + handled = 1; + } + break; +diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c +index 4e47db6..e881e3f 100644 +--- a/arch/powerpc/kernel/signal_32.c ++++ b/arch/powerpc/kernel/signal_32.c +@@ -967,8 +967,6 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *d, const siginfo_t *s) + + int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from) + { +- memset(to, 0, sizeof *to); +- + if (copy_from_user(to, from, 3*sizeof(int)) || + copy_from_user(to->_sifields._pad, + from->_sifields._pad, SI_PAD_SIZE32)) +diff --git a/arch/powerpc/kernel/suspend.c b/arch/powerpc/kernel/suspend.c +index 0167d53..a531154 100644 +--- a/arch/powerpc/kernel/suspend.c ++++ b/arch/powerpc/kernel/suspend.c +@@ -9,9 +9,7 @@ + + #include + #include +- +-/* References to section boundaries */ +-extern const void __nosave_begin, __nosave_end; ++#include + + /* + * pfn_is_nosave - check if given pfn is in the 'nosave' section +diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c +index 75702e2..f7089fc 100644 +--- a/arch/powerpc/kernel/udbg_16550.c ++++ b/arch/powerpc/kernel/udbg_16550.c +@@ -69,8 +69,12 @@ static void udbg_uart_putc(char c) + + static int udbg_uart_getc_poll(void) + { +- if (!udbg_uart_in || !(udbg_uart_in(UART_LSR) & LSR_DR)) ++ if (!udbg_uart_in) ++ return -1; ++ ++ if (!(udbg_uart_in(UART_LSR) & LSR_DR)) + return udbg_uart_in(UART_RBR); ++ + return -1; + } + +diff --git a/arch/powerpc/kernel/vdso32/getcpu.S b/arch/powerpc/kernel/vdso32/getcpu.S +index 47afd08..fe7e97a 100644 +--- a/arch/powerpc/kernel/vdso32/getcpu.S ++++ b/arch/powerpc/kernel/vdso32/getcpu.S +@@ -30,8 +30,8 @@ + V_FUNCTION_BEGIN(__kernel_getcpu) + .cfi_startproc + mfspr r5,SPRN_USPRG3 +- cmpdi cr0,r3,0 +- cmpdi cr1,r4,0 ++ cmpwi cr0,r3,0 ++ cmpwi cr1,r4,0 + clrlwi r6,r5,16 + rlwinm r7,r5,16,31-15,31-0 + beq cr0,1f +diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S +index f096e72..1db6851 100644 +--- a/arch/powerpc/kernel/vmlinux.lds.S ++++ b/arch/powerpc/kernel/vmlinux.lds.S +@@ -213,6 +213,7 @@ SECTIONS + *(.opd) + } + ++ . = ALIGN(256); + .got : AT(ADDR(.got) - LOAD_OFFSET) { + __toc_start = .; + #ifndef CONFIG_RELOCATABLE +diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c +index 0c9c8d7..170a034 100644 +--- a/arch/powerpc/lib/locks.c ++++ b/arch/powerpc/lib/locks.c +@@ -70,12 +70,16 @@ void __rw_yield(arch_rwlock_t *rw) + + void arch_spin_unlock_wait(arch_spinlock_t *lock) + { ++ smp_mb(); ++ + while (lock->slock) { + HMT_low(); + if (SHARED_PROCESSOR) + __spin_yield(lock); + } + HMT_medium(); ++ ++ smp_mb(); + } + + EXPORT_SYMBOL(arch_spin_unlock_wait); +diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c +index 51ab9e7..010fabf 100644 +--- a/arch/powerpc/mm/fault.c ++++ b/arch/powerpc/mm/fault.c +@@ -432,6 +432,8 @@ good_area: + */ + fault = handle_mm_fault(mm, vma, address, flags); + if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) { ++ if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + rc = mm_fault_error(regs, address, fault); + if (rc >= MM_FAULT_RETURN) + goto bail; +diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c +index 3ea26c2..838de8e 100644 +--- a/arch/powerpc/mm/hash_native_64.c ++++ b/arch/powerpc/mm/hash_native_64.c +@@ -418,18 +418,18 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long vpn, + local_irq_restore(flags); + } + +-static void native_hugepage_invalidate(struct mm_struct *mm, ++static void native_hugepage_invalidate(unsigned long vsid, ++ unsigned long addr, + unsigned char *hpte_slot_array, +- unsigned long addr, int psize) ++ int psize, int ssize) + { +- int ssize = 0, i; +- int lock_tlbie; ++ int i; + struct hash_pte *hptep; + int actual_psize = MMU_PAGE_16M; + unsigned int max_hpte_count, valid; + unsigned long flags, s_addr = addr; + unsigned long hpte_v, want_v, shift; +- unsigned long hidx, vpn = 0, vsid, hash, slot; ++ unsigned long hidx, vpn = 0, hash, slot; + + shift = mmu_psize_defs[psize].shift; + max_hpte_count = 1U << (PMD_SHIFT - shift); +@@ -443,15 +443,6 @@ static void native_hugepage_invalidate(struct mm_struct *mm, + + /* get the vpn */ + addr = s_addr + (i * (1ul << shift)); +- if (!is_kernel_addr(addr)) { +- ssize = user_segment_size(addr); +- vsid = get_vsid(mm->context.id, addr, ssize); +- WARN_ON(vsid == 0); +- } else { +- vsid = get_kernel_vsid(addr, mmu_kernel_ssize); +- ssize = mmu_kernel_ssize; +- } +- + vpn = hpt_vpn(addr, vsid, ssize); + hash = hpt_hash(vpn, shift, ssize); + if (hidx & _PTEIDX_SECONDARY) +@@ -471,22 +462,13 @@ static void native_hugepage_invalidate(struct mm_struct *mm, + else + /* Invalidate the hpte. NOTE: this also unlocks it */ + hptep->v = 0; ++ /* ++ * We need to do tlb invalidate for all the address, tlbie ++ * instruction compares entry_VA in tlb with the VA specified ++ * here ++ */ ++ tlbie(vpn, psize, actual_psize, ssize, 0); + } +- /* +- * Since this is a hugepage, we just need a single tlbie. +- * use the last vpn. +- */ +- lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); +- if (lock_tlbie) +- raw_spin_lock(&native_tlbie_lock); +- +- asm volatile("ptesync":::"memory"); +- __tlbie(vpn, psize, actual_psize, ssize); +- asm volatile("eieio; tlbsync; ptesync":::"memory"); +- +- if (lock_tlbie) +- raw_spin_unlock(&native_tlbie_lock); +- + local_irq_restore(flags); + } + +diff --git a/arch/powerpc/mm/hugepage-hash64.c b/arch/powerpc/mm/hugepage-hash64.c +index 826893f..5f5e632 100644 +--- a/arch/powerpc/mm/hugepage-hash64.c ++++ b/arch/powerpc/mm/hugepage-hash64.c +@@ -18,6 +18,57 @@ + #include + #include + ++static void invalidate_old_hpte(unsigned long vsid, unsigned long addr, ++ pmd_t *pmdp, unsigned int psize, int ssize) ++{ ++ int i, max_hpte_count, valid; ++ unsigned long s_addr; ++ unsigned char *hpte_slot_array; ++ unsigned long hidx, shift, vpn, hash, slot; ++ ++ s_addr = addr & HPAGE_PMD_MASK; ++ hpte_slot_array = get_hpte_slot_array(pmdp); ++ /* ++ * IF we try to do a HUGE PTE update after a withdraw is done. ++ * we will find the below NULL. This happens when we do ++ * split_huge_page_pmd ++ */ ++ if (!hpte_slot_array) ++ return; ++ ++ if (ppc_md.hugepage_invalidate) ++ return ppc_md.hugepage_invalidate(vsid, s_addr, hpte_slot_array, ++ psize, ssize); ++ /* ++ * No bluk hpte removal support, invalidate each entry ++ */ ++ shift = mmu_psize_defs[psize].shift; ++ max_hpte_count = HPAGE_PMD_SIZE >> shift; ++ for (i = 0; i < max_hpte_count; i++) { ++ /* ++ * 8 bits per each hpte entries ++ * 000| [ secondary group (one bit) | hidx (3 bits) | valid bit] ++ */ ++ valid = hpte_valid(hpte_slot_array, i); ++ if (!valid) ++ continue; ++ hidx = hpte_hash_index(hpte_slot_array, i); ++ ++ /* get the vpn */ ++ addr = s_addr + (i * (1ul << shift)); ++ vpn = hpt_vpn(addr, vsid, ssize); ++ hash = hpt_hash(vpn, shift, ssize); ++ if (hidx & _PTEIDX_SECONDARY) ++ hash = ~hash; ++ ++ slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; ++ slot += hidx & _PTEIDX_GROUP_IX; ++ ppc_md.hpte_invalidate(slot, vpn, psize, ++ MMU_PAGE_16M, ssize, 0); ++ } ++} ++ ++ + int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, + pmd_t *pmdp, unsigned long trap, int local, int ssize, + unsigned int psize) +@@ -33,7 +84,9 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, + * atomically mark the linux large page PMD busy and dirty + */ + do { +- old_pmd = pmd_val(*pmdp); ++ pmd_t pmd = ACCESS_ONCE(*pmdp); ++ ++ old_pmd = pmd_val(pmd); + /* If PMD busy, retry the access */ + if (unlikely(old_pmd & _PAGE_BUSY)) + return 0; +@@ -85,6 +138,15 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, + vpn = hpt_vpn(ea, vsid, ssize); + hash = hpt_hash(vpn, shift, ssize); + hpte_slot_array = get_hpte_slot_array(pmdp); ++ if (psize == MMU_PAGE_4K) { ++ /* ++ * invalidate the old hpte entry if we have that mapped via 64K ++ * base page size. This is because demote_segment won't flush ++ * hash page table entries. ++ */ ++ if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO)) ++ invalidate_old_hpte(vsid, ea, pmdp, MMU_PAGE_64K, ssize); ++ } + + valid = hpte_valid(hpte_slot_array, index); + if (valid) { +@@ -107,11 +169,8 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, + * safely update this here. + */ + valid = 0; +- new_pmd &= ~_PAGE_HPTEFLAGS; + hpte_slot_array[index] = 0; +- } else +- /* clear the busy bits and set the hash pte bits */ +- new_pmd = (new_pmd & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE; ++ } + } + + if (!valid) { +@@ -119,11 +178,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, + + /* insert new entry */ + pa = pmd_pfn(__pmd(old_pmd)) << PAGE_SHIFT; +-repeat: +- hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; +- +- /* clear the busy bits and set the hash pte bits */ +- new_pmd = (new_pmd & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE; ++ new_pmd |= _PAGE_HASHPTE; + + /* Add in WIMG bits */ + rflags |= (new_pmd & (_PAGE_WRITETHRU | _PAGE_NO_CACHE | +@@ -132,6 +187,8 @@ repeat: + * enable the memory coherence always + */ + rflags |= HPTE_R_M; ++repeat: ++ hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; + + /* Insert into the hash table, primary slot */ + slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0, +@@ -172,8 +229,17 @@ repeat: + mark_hpte_slot_valid(hpte_slot_array, index, slot); + } + /* +- * No need to use ldarx/stdcx here ++ * Mark the pte with _PAGE_COMBO, if we are trying to hash it with ++ * base page size 4k. ++ */ ++ if (psize == MMU_PAGE_4K) ++ new_pmd |= _PAGE_COMBO; ++ /* ++ * The hpte valid is stored in the pgtable whose address is in the ++ * second half of the PMD. Order this against clearing of the busy bit in ++ * huge pmd. + */ ++ smp_wmb(); + *pmdp = __pmd(new_pmd & ~_PAGE_BUSY); + return 0; + } +diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c +index 30a42e2..a5fff17 100644 +--- a/arch/powerpc/mm/numa.c ++++ b/arch/powerpc/mm/numa.c +@@ -610,8 +610,8 @@ static int cpu_numa_callback(struct notifier_block *nfb, unsigned long action, + case CPU_UP_CANCELED: + case CPU_UP_CANCELED_FROZEN: + unmap_cpu_from_node(lcpu); +- break; + ret = NOTIFY_OK; ++ break; + #endif + } + return ret; +diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c +index 62bf5e8..c64da56 100644 +--- a/arch/powerpc/mm/pgtable_64.c ++++ b/arch/powerpc/mm/pgtable_64.c +@@ -538,7 +538,7 @@ unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr, + *pmdp = __pmd((old & ~clr) | set); + #endif + if (old & _PAGE_HASHPTE) +- hpte_do_hugepage_flush(mm, addr, pmdp); ++ hpte_do_hugepage_flush(mm, addr, pmdp, old); + return old; + } + +@@ -645,7 +645,7 @@ void pmdp_splitting_flush(struct vm_area_struct *vma, + if (!(old & _PAGE_SPLITTING)) { + /* We need to flush the hpte */ + if (old & _PAGE_HASHPTE) +- hpte_do_hugepage_flush(vma->vm_mm, address, pmdp); ++ hpte_do_hugepage_flush(vma->vm_mm, address, pmdp, old); + } + } + +@@ -718,7 +718,7 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, + * neesd to be flushed. + */ + void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, +- pmd_t *pmdp) ++ pmd_t *pmdp, unsigned long old_pmd) + { + int ssize, i; + unsigned long s_addr; +@@ -740,12 +740,29 @@ void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, + if (!hpte_slot_array) + return; + +- /* get the base page size */ ++ /* get the base page size,vsid and segment size */ ++#ifdef CONFIG_DEBUG_VM + psize = get_slice_psize(mm, s_addr); ++ BUG_ON(psize == MMU_PAGE_16M); ++#endif ++ if (old_pmd & _PAGE_COMBO) ++ psize = MMU_PAGE_4K; ++ else ++ psize = MMU_PAGE_64K; ++ ++ if (!is_kernel_addr(s_addr)) { ++ ssize = user_segment_size(s_addr); ++ vsid = get_vsid(mm->context.id, s_addr, ssize); ++ WARN_ON(vsid == 0); ++ } else { ++ vsid = get_kernel_vsid(s_addr, mmu_kernel_ssize); ++ ssize = mmu_kernel_ssize; ++ } + + if (ppc_md.hugepage_invalidate) +- return ppc_md.hugepage_invalidate(mm, hpte_slot_array, +- s_addr, psize); ++ return ppc_md.hugepage_invalidate(vsid, s_addr, ++ hpte_slot_array, ++ psize, ssize); + /* + * No bluk hpte removal support, invalidate each entry + */ +@@ -763,15 +780,6 @@ void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, + + /* get the vpn */ + addr = s_addr + (i * (1ul << shift)); +- if (!is_kernel_addr(addr)) { +- ssize = user_segment_size(addr); +- vsid = get_vsid(mm->context.id, addr, ssize); +- WARN_ON(vsid == 0); +- } else { +- vsid = get_kernel_vsid(addr, mmu_kernel_ssize); +- ssize = mmu_kernel_ssize; +- } +- + vpn = hpt_vpn(addr, vsid, ssize); + hash = hpt_hash(vpn, shift, ssize); + if (hidx & _PTEIDX_SECONDARY) +diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c +index c99f651..9adda57 100644 +--- a/arch/powerpc/mm/tlb_hash64.c ++++ b/arch/powerpc/mm/tlb_hash64.c +@@ -216,7 +216,7 @@ void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, + if (!(pte & _PAGE_HASHPTE)) + continue; + if (unlikely(hugepage_shift && pmd_trans_huge(*(pmd_t *)pte))) +- hpte_do_hugepage_flush(mm, start, (pmd_t *)pte); ++ hpte_do_hugepage_flush(mm, start, (pmd_t *)ptep, pte); + else + hpte_need_flush(mm, start, ptep, pte, 0); + } +diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c +index 74d1e78..ead5535 100644 +--- a/arch/powerpc/perf/callchain.c ++++ b/arch/powerpc/perf/callchain.c +@@ -35,7 +35,7 @@ static int valid_next_sp(unsigned long sp, unsigned long prev_sp) + return 0; /* must be 16-byte aligned */ + if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD)) + return 0; +- if (sp >= prev_sp + STACK_FRAME_OVERHEAD) ++ if (sp >= prev_sp + STACK_FRAME_MIN_SIZE) + return 1; + /* + * sp could decrease when we jump off an interrupt stack +@@ -243,7 +243,7 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry, + sp = regs->gpr[1]; + perf_callchain_store(entry, next_ip); + +- for (;;) { ++ while (entry->nr < PERF_MAX_STACK_DEPTH) { + fp = (unsigned long __user *) sp; + if (!valid_user_sp(sp, 1) || read_user_stack_64(fp, &next_sp)) + return; +diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c +index 38265dc..65dfbd0 100644 +--- a/arch/powerpc/perf/core-book3s.c ++++ b/arch/powerpc/perf/core-book3s.c +@@ -124,7 +124,16 @@ static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {} + + static bool regs_use_siar(struct pt_regs *regs) + { +- return !!regs->result; ++ /* ++ * When we take a performance monitor exception the regs are setup ++ * using perf_read_regs() which overloads some fields, in particular ++ * regs->result to tell us whether to use SIAR. ++ * ++ * However if the regs are from another exception, eg. a syscall, then ++ * they have not been setup using perf_read_regs() and so regs->result ++ * is something random. ++ */ ++ return ((TRAP(regs) == 0xf00) && regs->result); + } + + /* +diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c +index 2b90ff8..59ef76c 100644 +--- a/arch/powerpc/platforms/cell/iommu.c ++++ b/arch/powerpc/platforms/cell/iommu.c +@@ -197,7 +197,7 @@ static int tce_build_cell(struct iommu_table *tbl, long index, long npages, + + io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset); + +- for (i = 0; i < npages; i++, uaddr += tbl->it_page_shift) ++ for (i = 0; i < npages; i++, uaddr += (1 << tbl->it_page_shift)) + io_pte[i] = base_pte | (__pa(uaddr) & CBE_IOPTE_RPN_Mask); + + mb(); +diff --git a/arch/powerpc/platforms/cell/spu_fault.c b/arch/powerpc/platforms/cell/spu_fault.c +index 641e727..62f3e4e 100644 +--- a/arch/powerpc/platforms/cell/spu_fault.c ++++ b/arch/powerpc/platforms/cell/spu_fault.c +@@ -75,7 +75,7 @@ int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, + if (*flt & VM_FAULT_OOM) { + ret = -ENOMEM; + goto out_unlock; +- } else if (*flt & VM_FAULT_SIGBUS) { ++ } else if (*flt & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) { + ret = -EFAULT; + goto out_unlock; + } +diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c +index 87ba7cf..65d633f 100644 +--- a/arch/powerpc/platforms/cell/spufs/inode.c ++++ b/arch/powerpc/platforms/cell/spufs/inode.c +@@ -164,7 +164,7 @@ static void spufs_prune_dir(struct dentry *dir) + struct dentry *dentry, *tmp; + + mutex_lock(&dir->d_inode->i_mutex); +- list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) { ++ list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) { + spin_lock(&dentry->d_lock); + if (!(d_unhashed(dentry)) && dentry->d_inode) { + dget_dlock(dentry); +diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c +index 3b2b4fb..d558b85 100644 +--- a/arch/powerpc/platforms/powernv/pci-ioda.c ++++ b/arch/powerpc/platforms/powernv/pci-ioda.c +@@ -491,6 +491,7 @@ static int pnv_pci_ioda_dma_set_mask(struct pnv_phb *phb, + set_dma_ops(&pdev->dev, &dma_iommu_ops); + set_iommu_table_base(&pdev->dev, &pe->tce32_table); + } ++ *pdev->dev.dma_mask = dma_mask; + return 0; + } + +@@ -901,7 +902,6 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, + unsigned int is_64, struct msi_msg *msg) + { + struct pnv_ioda_pe *pe = pnv_ioda_get_pe(dev); +- struct pci_dn *pdn = pci_get_pdn(dev); + struct irq_data *idata; + struct irq_chip *ichip; + unsigned int xive_num = hwirq - phb->msi_base; +@@ -917,7 +917,7 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, + return -ENXIO; + + /* Force 32-bit MSI on some broken devices */ +- if (pdn && pdn->force_32bit_msi) ++ if (dev->no_64bit_msi) + is_64 = 0; + + /* Assign XIVE to PE */ +diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c +index 8518817..52c1162 100644 +--- a/arch/powerpc/platforms/powernv/pci.c ++++ b/arch/powerpc/platforms/powernv/pci.c +@@ -1,3 +1,4 @@ ++ + /* + * Support PCI/PCIe on PowerNV platforms + * +@@ -50,9 +51,8 @@ static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type) + { + struct pci_controller *hose = pci_bus_to_host(pdev->bus); + struct pnv_phb *phb = hose->private_data; +- struct pci_dn *pdn = pci_get_pdn(pdev); + +- if (pdn && pdn->force_32bit_msi && !phb->msi32_support) ++ if (pdev->no_64bit_msi && !phb->msi32_support) + return -ENODEV; + + return (phb && phb->msi_bmp.bitmap) ? 0 : -ENODEV; +diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c +index a8fe5aa..3b46eed 100644 +--- a/arch/powerpc/platforms/pseries/dlpar.c ++++ b/arch/powerpc/platforms/pseries/dlpar.c +@@ -380,7 +380,7 @@ static int dlpar_online_cpu(struct device_node *dn) + BUG_ON(get_cpu_current_state(cpu) + != CPU_STATE_OFFLINE); + cpu_maps_update_done(); +- rc = cpu_up(cpu); ++ rc = device_online(get_cpu_device(cpu)); + if (rc) + goto out; + cpu_maps_update_begin(); +@@ -463,7 +463,7 @@ static int dlpar_offline_cpu(struct device_node *dn) + if (get_cpu_current_state(cpu) == CPU_STATE_ONLINE) { + set_preferred_offline_state(cpu, CPU_STATE_OFFLINE); + cpu_maps_update_done(); +- rc = cpu_down(cpu); ++ rc = device_offline(get_cpu_device(cpu)); + if (rc) + goto out; + cpu_maps_update_begin(); +diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c +index 9590dbb..b9a8204 100644 +--- a/arch/powerpc/platforms/pseries/hotplug-memory.c ++++ b/arch/powerpc/platforms/pseries/hotplug-memory.c +@@ -160,7 +160,7 @@ static int pseries_remove_memory(struct device_node *np) + static inline int pseries_remove_memblock(unsigned long base, + unsigned int memblock_size) + { +- return -EOPNOTSUPP; ++ return 0; + } + static inline int pseries_remove_memory(struct device_node *np) + { +diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c +index 33b552f..de1ec54 100644 +--- a/arch/powerpc/platforms/pseries/iommu.c ++++ b/arch/powerpc/platforms/pseries/iommu.c +@@ -329,16 +329,16 @@ struct direct_window { + + /* Dynamic DMA Window support */ + struct ddw_query_response { +- __be32 windows_available; +- __be32 largest_available_block; +- __be32 page_size; +- __be32 migration_capable; ++ u32 windows_available; ++ u32 largest_available_block; ++ u32 page_size; ++ u32 migration_capable; + }; + + struct ddw_create_response { +- __be32 liobn; +- __be32 addr_hi; +- __be32 addr_lo; ++ u32 liobn; ++ u32 addr_hi; ++ u32 addr_lo; + }; + + static LIST_HEAD(direct_window_list); +@@ -721,20 +721,22 @@ static int __init disable_ddw_setup(char *str) + + early_param("disable_ddw", disable_ddw_setup); + +-static void remove_ddw(struct device_node *np) ++static void remove_ddw(struct device_node *np, bool remove_prop) + { + struct dynamic_dma_window_prop *dwp; + struct property *win64; +- const u32 *ddw_avail; ++ u32 ddw_avail[3]; + u64 liobn; +- int len, ret; ++ int ret = 0; ++ ++ ret = of_property_read_u32_array(np, "ibm,ddw-applicable", ++ &ddw_avail[0], 3); + +- ddw_avail = of_get_property(np, "ibm,ddw-applicable", &len); + win64 = of_find_property(np, DIRECT64_PROPNAME, NULL); + if (!win64) + return; + +- if (!ddw_avail || len < 3 * sizeof(u32) || win64->length < sizeof(*dwp)) ++ if (ret || win64->length < sizeof(*dwp)) + goto delprop; + + dwp = win64->value; +@@ -761,7 +763,8 @@ static void remove_ddw(struct device_node *np) + np->full_name, ret, ddw_avail[2], liobn); + + delprop: +- ret = of_remove_property(np, win64); ++ if (remove_prop) ++ ret = of_remove_property(np, win64); + if (ret) + pr_warning("%s: failed to remove direct window property: %d\n", + np->full_name, ret); +@@ -805,7 +808,7 @@ static int find_existing_ddw_windows(void) + window = kzalloc(sizeof(*window), GFP_KERNEL); + if (!window || len < sizeof(struct dynamic_dma_window_prop)) { + kfree(window); +- remove_ddw(pdn); ++ remove_ddw(pdn, true); + continue; + } + +@@ -871,8 +874,9 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail, + + do { + /* extra outputs are LIOBN and dma-addr (hi, lo) */ +- ret = rtas_call(ddw_avail[1], 5, 4, (u32 *)create, cfg_addr, +- BUID_HI(buid), BUID_LO(buid), page_shift, window_shift); ++ ret = rtas_call(ddw_avail[1], 5, 4, (u32 *)create, ++ cfg_addr, BUID_HI(buid), BUID_LO(buid), ++ page_shift, window_shift); + } while (rtas_busy_delay(ret)); + dev_info(&dev->dev, + "ibm,create-pe-dma-window(%x) %x %x %x %x %x returned %d " +@@ -909,7 +913,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) + int page_shift; + u64 dma_addr, max_addr; + struct device_node *dn; +- const u32 *uninitialized_var(ddw_avail); ++ u32 ddw_avail[3]; + struct direct_window *window; + struct property *win64; + struct dynamic_dma_window_prop *ddwprop; +@@ -941,8 +945,9 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) + * for the given node in that order. + * the property is actually in the parent, not the PE + */ +- ddw_avail = of_get_property(pdn, "ibm,ddw-applicable", &len); +- if (!ddw_avail || len < 3 * sizeof(u32)) ++ ret = of_property_read_u32_array(pdn, "ibm,ddw-applicable", ++ &ddw_avail[0], 3); ++ if (ret) + goto out_failed; + + /* +@@ -965,11 +970,11 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) + dev_dbg(&dev->dev, "no free dynamic windows"); + goto out_failed; + } +- if (be32_to_cpu(query.page_size) & 4) { ++ if (query.page_size & 4) { + page_shift = 24; /* 16MB */ +- } else if (be32_to_cpu(query.page_size) & 2) { ++ } else if (query.page_size & 2) { + page_shift = 16; /* 64kB */ +- } else if (be32_to_cpu(query.page_size) & 1) { ++ } else if (query.page_size & 1) { + page_shift = 12; /* 4kB */ + } else { + dev_dbg(&dev->dev, "no supported direct page size in mask %x", +@@ -979,7 +984,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) + /* verify the window * number of ptes will map the partition */ + /* check largest block * page size > max memory hotplug addr */ + max_addr = memory_hotplug_max(); +- if (be32_to_cpu(query.largest_available_block) < (max_addr >> page_shift)) { ++ if (query.largest_available_block < (max_addr >> page_shift)) { + dev_dbg(&dev->dev, "can't map partiton max 0x%llx with %u " + "%llu-sized pages\n", max_addr, query.largest_available_block, + 1ULL << page_shift); +@@ -1005,8 +1010,9 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) + if (ret != 0) + goto out_free_prop; + +- ddwprop->liobn = create.liobn; +- ddwprop->dma_base = cpu_to_be64(of_read_number(&create.addr_hi, 2)); ++ ddwprop->liobn = cpu_to_be32(create.liobn); ++ ddwprop->dma_base = cpu_to_be64(((u64)create.addr_hi << 32) | ++ create.addr_lo); + ddwprop->tce_shift = cpu_to_be32(page_shift); + ddwprop->window_shift = cpu_to_be32(len); + +@@ -1038,14 +1044,14 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) + list_add(&window->list, &direct_window_list); + spin_unlock(&direct_window_list_lock); + +- dma_addr = of_read_number(&create.addr_hi, 2); ++ dma_addr = be64_to_cpu(ddwprop->dma_base); + goto out_unlock; + + out_free_window: + kfree(window); + + out_clear_window: +- remove_ddw(pdn); ++ remove_ddw(pdn, true); + + out_free_prop: + kfree(win64->name); +@@ -1255,7 +1261,14 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti + + switch (action) { + case OF_RECONFIG_DETACH_NODE: +- remove_ddw(np); ++ /* ++ * Removing the property will invoke the reconfig ++ * notifier again, which causes dead-lock on the ++ * read-write semaphore of the notifier chain. So ++ * we have to remove the property when releasing ++ * the device node. ++ */ ++ remove_ddw(np, false); + if (pci && pci->iommu_table) + iommu_free_table(pci->iommu_table, np->full_name); + +diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c +index b02af9e..ccf6f16 100644 +--- a/arch/powerpc/platforms/pseries/lpar.c ++++ b/arch/powerpc/platforms/pseries/lpar.c +@@ -430,16 +430,17 @@ static void __pSeries_lpar_hugepage_invalidate(unsigned long *slot, + spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); + } + +-static void pSeries_lpar_hugepage_invalidate(struct mm_struct *mm, +- unsigned char *hpte_slot_array, +- unsigned long addr, int psize) ++static void pSeries_lpar_hugepage_invalidate(unsigned long vsid, ++ unsigned long addr, ++ unsigned char *hpte_slot_array, ++ int psize, int ssize) + { +- int ssize = 0, i, index = 0; ++ int i, index = 0; + unsigned long s_addr = addr; + unsigned int max_hpte_count, valid; + unsigned long vpn_array[PPC64_HUGE_HPTE_BATCH]; + unsigned long slot_array[PPC64_HUGE_HPTE_BATCH]; +- unsigned long shift, hidx, vpn = 0, vsid, hash, slot; ++ unsigned long shift, hidx, vpn = 0, hash, slot; + + shift = mmu_psize_defs[psize].shift; + max_hpte_count = 1U << (PMD_SHIFT - shift); +@@ -452,15 +453,6 @@ static void pSeries_lpar_hugepage_invalidate(struct mm_struct *mm, + + /* get the vpn */ + addr = s_addr + (i * (1ul << shift)); +- if (!is_kernel_addr(addr)) { +- ssize = user_segment_size(addr); +- vsid = get_vsid(mm->context.id, addr, ssize); +- WARN_ON(vsid == 0); +- } else { +- vsid = get_kernel_vsid(addr, mmu_kernel_ssize); +- ssize = mmu_kernel_ssize; +- } +- + vpn = hpt_vpn(addr, vsid, ssize); + hash = hpt_hash(vpn, shift, ssize); + if (hidx & _PTEIDX_SECONDARY) +diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c +index cde4e0a..bf38292 100644 +--- a/arch/powerpc/platforms/pseries/mobility.c ++++ b/arch/powerpc/platforms/pseries/mobility.c +@@ -24,10 +24,10 @@ + static struct kobject *mobility_kobj; + + struct update_props_workarea { +- u32 phandle; +- u32 state; +- u64 reserved; +- u32 nprops; ++ __be32 phandle; ++ __be32 state; ++ __be64 reserved; ++ __be32 nprops; + } __packed; + + #define NODE_ACTION_MASK 0xff000000 +@@ -53,11 +53,11 @@ static int mobility_rtas_call(int token, char *buf, s32 scope) + return rc; + } + +-static int delete_dt_node(u32 phandle) ++static int delete_dt_node(__be32 phandle) + { + struct device_node *dn; + +- dn = of_find_node_by_phandle(phandle); ++ dn = of_find_node_by_phandle(be32_to_cpu(phandle)); + if (!dn) + return -ENOENT; + +@@ -126,7 +126,7 @@ static int update_dt_property(struct device_node *dn, struct property **prop, + return 0; + } + +-static int update_dt_node(u32 phandle, s32 scope) ++static int update_dt_node(__be32 phandle, s32 scope) + { + struct update_props_workarea *upwa; + struct device_node *dn; +@@ -135,6 +135,7 @@ static int update_dt_node(u32 phandle, s32 scope) + char *prop_data; + char *rtas_buf; + int update_properties_token; ++ u32 nprops; + u32 vd; + + update_properties_token = rtas_token("ibm,update-properties"); +@@ -145,7 +146,7 @@ static int update_dt_node(u32 phandle, s32 scope) + if (!rtas_buf) + return -ENOMEM; + +- dn = of_find_node_by_phandle(phandle); ++ dn = of_find_node_by_phandle(be32_to_cpu(phandle)); + if (!dn) { + kfree(rtas_buf); + return -ENOENT; +@@ -161,6 +162,7 @@ static int update_dt_node(u32 phandle, s32 scope) + break; + + prop_data = rtas_buf + sizeof(*upwa); ++ nprops = be32_to_cpu(upwa->nprops); + + /* On the first call to ibm,update-properties for a node the + * the first property value descriptor contains an empty +@@ -169,17 +171,17 @@ static int update_dt_node(u32 phandle, s32 scope) + */ + if (*prop_data == 0) { + prop_data++; +- vd = *(u32 *)prop_data; ++ vd = be32_to_cpu(*(__be32 *)prop_data); + prop_data += vd + sizeof(vd); +- upwa->nprops--; ++ nprops--; + } + +- for (i = 0; i < upwa->nprops; i++) { ++ for (i = 0; i < nprops; i++) { + char *prop_name; + + prop_name = prop_data; + prop_data += strlen(prop_name) + 1; +- vd = *(u32 *)prop_data; ++ vd = be32_to_cpu(*(__be32 *)prop_data); + prop_data += sizeof(vd); + + switch (vd) { +@@ -211,13 +213,13 @@ static int update_dt_node(u32 phandle, s32 scope) + return 0; + } + +-static int add_dt_node(u32 parent_phandle, u32 drc_index) ++static int add_dt_node(__be32 parent_phandle, __be32 drc_index) + { + struct device_node *dn; + struct device_node *parent_dn; + int rc; + +- parent_dn = of_find_node_by_phandle(parent_phandle); ++ parent_dn = of_find_node_by_phandle(be32_to_cpu(parent_phandle)); + if (!parent_dn) + return -ENOENT; + +@@ -236,7 +238,7 @@ static int add_dt_node(u32 parent_phandle, u32 drc_index) + int pseries_devicetree_update(s32 scope) + { + char *rtas_buf; +- u32 *data; ++ __be32 *data; + int update_nodes_token; + int rc; + +@@ -253,17 +255,17 @@ int pseries_devicetree_update(s32 scope) + if (rc && rc != 1) + break; + +- data = (u32 *)rtas_buf + 4; +- while (*data & NODE_ACTION_MASK) { ++ data = (__be32 *)rtas_buf + 4; ++ while (be32_to_cpu(*data) & NODE_ACTION_MASK) { + int i; +- u32 action = *data & NODE_ACTION_MASK; +- int node_count = *data & NODE_COUNT_MASK; ++ u32 action = be32_to_cpu(*data) & NODE_ACTION_MASK; ++ u32 node_count = be32_to_cpu(*data) & NODE_COUNT_MASK; + + data++; + + for (i = 0; i < node_count; i++) { +- u32 phandle = *data++; +- u32 drc_index; ++ __be32 phandle = *data++; ++ __be32 drc_index; + + switch (action) { + case DELETE_DT_NODE: +diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c +index 0c882e8..6849d85 100644 +--- a/arch/powerpc/platforms/pseries/msi.c ++++ b/arch/powerpc/platforms/pseries/msi.c +@@ -428,7 +428,7 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type) + */ + again: + if (type == PCI_CAP_ID_MSI) { +- if (pdn->force_32bit_msi) { ++ if (pdev->no_64bit_msi) { + rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSI_FN, nvec); + if (rc < 0) { + /* +diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c +index efe6137..e68922b 100644 +--- a/arch/powerpc/platforms/pseries/pci_dlpar.c ++++ b/arch/powerpc/platforms/pseries/pci_dlpar.c +@@ -118,10 +118,10 @@ int remove_phb_dynamic(struct pci_controller *phb) + } + } + +- /* Unregister the bridge device from sysfs and remove the PCI bus */ +- device_unregister(b->bridge); ++ /* Remove the PCI bus and unregister the bridge device from sysfs */ + phb->bus = NULL; + pci_remove_bus(b); ++ device_unregister(b->bridge); + + /* Now release the IO resource */ + if (res->flags & IORESOURCE_IO) +diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c +index 47b6b9f..830edc8 100644 +--- a/arch/powerpc/sysdev/axonram.c ++++ b/arch/powerpc/sysdev/axonram.c +@@ -156,7 +156,7 @@ axon_ram_direct_access(struct block_device *device, sector_t sector, + } + + *kaddr = (void *)(bank->ph_addr + offset); +- *pfn = virt_to_phys(kaddr) >> PAGE_SHIFT; ++ *pfn = virt_to_phys(*kaddr) >> PAGE_SHIFT; + + return 0; + } +diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c +index b079098..f89389f 100644 +--- a/arch/powerpc/xmon/xmon.c ++++ b/arch/powerpc/xmon/xmon.c +@@ -288,10 +288,11 @@ static inline void disable_surveillance(void) + args.token = rtas_token("set-indicator"); + if (args.token == RTAS_UNKNOWN_SERVICE) + return; +- args.nargs = 3; +- args.nret = 1; ++ args.token = cpu_to_be32(args.token); ++ args.nargs = cpu_to_be32(3); ++ args.nret = cpu_to_be32(1); + args.rets = &args.args[3]; +- args.args[0] = SURVEILLANCE_TOKEN; ++ args.args[0] = cpu_to_be32(SURVEILLANCE_TOKEN); + args.args[1] = 0; + args.args[2] = 0; + enter_rtas(__pa(&args)); +diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig +index bb74b21..a0a3bed 100644 +--- a/arch/s390/Kconfig ++++ b/arch/s390/Kconfig +@@ -93,6 +93,7 @@ config S390 + select ARCH_INLINE_WRITE_UNLOCK_IRQ + select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE + select ARCH_SAVE_PAGE_KEYS if HIBERNATION ++ select ARCH_SUPPORTS_ATOMIC_RMW + select ARCH_USE_CMPXCHG_LOCKREF + select ARCH_WANT_IPC_PARSE_VERSION + select BUILDTIME_EXTABLE_SORT +diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c +index 23223cd..1f272b2 100644 +--- a/arch/s390/crypto/aes_s390.c ++++ b/arch/s390/crypto/aes_s390.c +@@ -979,7 +979,7 @@ static void __exit aes_s390_fini(void) + module_init(aes_s390_init); + module_exit(aes_s390_fini); + +-MODULE_ALIAS("aes-all"); ++MODULE_ALIAS_CRYPTO("aes-all"); + + MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); + MODULE_LICENSE("GPL"); +diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c +index 7acb77f..9e05cc4 100644 +--- a/arch/s390/crypto/des_s390.c ++++ b/arch/s390/crypto/des_s390.c +@@ -619,8 +619,8 @@ static void __exit des_s390_exit(void) + module_init(des_s390_init); + module_exit(des_s390_exit); + +-MODULE_ALIAS("des"); +-MODULE_ALIAS("des3_ede"); ++MODULE_ALIAS_CRYPTO("des"); ++MODULE_ALIAS_CRYPTO("des3_ede"); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); +diff --git a/arch/s390/crypto/ghash_s390.c b/arch/s390/crypto/ghash_s390.c +index d43485d..b258110 100644 +--- a/arch/s390/crypto/ghash_s390.c ++++ b/arch/s390/crypto/ghash_s390.c +@@ -16,11 +16,12 @@ + #define GHASH_DIGEST_SIZE 16 + + struct ghash_ctx { +- u8 icv[16]; +- u8 key[16]; ++ u8 key[GHASH_BLOCK_SIZE]; + }; + + struct ghash_desc_ctx { ++ u8 icv[GHASH_BLOCK_SIZE]; ++ u8 key[GHASH_BLOCK_SIZE]; + u8 buffer[GHASH_BLOCK_SIZE]; + u32 bytes; + }; +@@ -28,8 +29,10 @@ struct ghash_desc_ctx { + static int ghash_init(struct shash_desc *desc) + { + struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); ++ struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); + + memset(dctx, 0, sizeof(*dctx)); ++ memcpy(dctx->key, ctx->key, GHASH_BLOCK_SIZE); + + return 0; + } +@@ -45,7 +48,6 @@ static int ghash_setkey(struct crypto_shash *tfm, + } + + memcpy(ctx->key, key, GHASH_BLOCK_SIZE); +- memset(ctx->icv, 0, GHASH_BLOCK_SIZE); + + return 0; + } +@@ -54,7 +56,6 @@ static int ghash_update(struct shash_desc *desc, + const u8 *src, unsigned int srclen) + { + struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); +- struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); + unsigned int n; + u8 *buf = dctx->buffer; + int ret; +@@ -70,7 +71,7 @@ static int ghash_update(struct shash_desc *desc, + src += n; + + if (!dctx->bytes) { +- ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, ++ ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf, + GHASH_BLOCK_SIZE); + if (ret != GHASH_BLOCK_SIZE) + return -EIO; +@@ -79,7 +80,7 @@ static int ghash_update(struct shash_desc *desc, + + n = srclen & ~(GHASH_BLOCK_SIZE - 1); + if (n) { +- ret = crypt_s390_kimd(KIMD_GHASH, ctx, src, n); ++ ret = crypt_s390_kimd(KIMD_GHASH, dctx, src, n); + if (ret != n) + return -EIO; + src += n; +@@ -94,7 +95,7 @@ static int ghash_update(struct shash_desc *desc, + return 0; + } + +-static int ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx) ++static int ghash_flush(struct ghash_desc_ctx *dctx) + { + u8 *buf = dctx->buffer; + int ret; +@@ -104,24 +105,24 @@ static int ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx) + + memset(pos, 0, dctx->bytes); + +- ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, GHASH_BLOCK_SIZE); ++ ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf, GHASH_BLOCK_SIZE); + if (ret != GHASH_BLOCK_SIZE) + return -EIO; ++ ++ dctx->bytes = 0; + } + +- dctx->bytes = 0; + return 0; + } + + static int ghash_final(struct shash_desc *desc, u8 *dst) + { + struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); +- struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); + int ret; + +- ret = ghash_flush(ctx, dctx); ++ ret = ghash_flush(dctx); + if (!ret) +- memcpy(dst, ctx->icv, GHASH_BLOCK_SIZE); ++ memcpy(dst, dctx->icv, GHASH_BLOCK_SIZE); + return ret; + } + +@@ -160,7 +161,7 @@ static void __exit ghash_mod_exit(void) + module_init(ghash_mod_init); + module_exit(ghash_mod_exit); + +-MODULE_ALIAS("ghash"); ++MODULE_ALIAS_CRYPTO("ghash"); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("GHASH Message Digest Algorithm, s390 implementation"); +diff --git a/arch/s390/crypto/sha1_s390.c b/arch/s390/crypto/sha1_s390.c +index a1b3a9d..5b2bee3 100644 +--- a/arch/s390/crypto/sha1_s390.c ++++ b/arch/s390/crypto/sha1_s390.c +@@ -103,6 +103,6 @@ static void __exit sha1_s390_fini(void) + module_init(sha1_s390_init); + module_exit(sha1_s390_fini); + +-MODULE_ALIAS("sha1"); ++MODULE_ALIAS_CRYPTO("sha1"); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); +diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c +index 9b85380..b74ff15 100644 +--- a/arch/s390/crypto/sha256_s390.c ++++ b/arch/s390/crypto/sha256_s390.c +@@ -143,7 +143,7 @@ static void __exit sha256_s390_fini(void) + module_init(sha256_s390_init); + module_exit(sha256_s390_fini); + +-MODULE_ALIAS("sha256"); +-MODULE_ALIAS("sha224"); ++MODULE_ALIAS_CRYPTO("sha256"); ++MODULE_ALIAS_CRYPTO("sha224"); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA256 and SHA224 Secure Hash Algorithm"); +diff --git a/arch/s390/crypto/sha512_s390.c b/arch/s390/crypto/sha512_s390.c +index 32a8138..0c36989 100644 +--- a/arch/s390/crypto/sha512_s390.c ++++ b/arch/s390/crypto/sha512_s390.c +@@ -86,7 +86,7 @@ static struct shash_alg sha512_alg = { + } + }; + +-MODULE_ALIAS("sha512"); ++MODULE_ALIAS_CRYPTO("sha512"); + + static int sha384_init(struct shash_desc *desc) + { +@@ -126,7 +126,7 @@ static struct shash_alg sha384_alg = { + } + }; + +-MODULE_ALIAS("sha384"); ++MODULE_ALIAS_CRYPTO("sha384"); + + static int __init init(void) + { +diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c +index db02052..5426c9e 100644 +--- a/arch/s390/kernel/compat_linux.c ++++ b/arch/s390/kernel/compat_linux.c +@@ -245,7 +245,7 @@ asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist) + struct group_info *group_info; + int retval; + +- if (!capable(CAP_SETGID)) ++ if (!may_setgroups()) + return -EPERM; + if ((unsigned)gidsetsize > NGROUPS_MAX) + return -EINVAL; +diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c +index a48bc79..184d305 100644 +--- a/arch/s390/kernel/ptrace.c ++++ b/arch/s390/kernel/ptrace.c +@@ -323,9 +323,14 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data) + unsigned long mask = PSW_MASK_USER; + + mask |= is_ri_task(child) ? PSW_MASK_RI : 0; +- if ((data & ~mask) != PSW_USER_BITS) ++ if ((data ^ PSW_USER_BITS) & ~mask) ++ /* Invalid psw mask. */ ++ return -EINVAL; ++ if ((data & PSW_MASK_ASC) == PSW_ASC_HOME) ++ /* Invalid address-space-control bits */ + return -EINVAL; + if ((data & PSW_MASK_EA) && !(data & PSW_MASK_BA)) ++ /* Invalid addressing mode bits */ + return -EINVAL; + } + *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data; +@@ -661,9 +666,12 @@ static int __poke_user_compat(struct task_struct *child, + + mask |= is_ri_task(child) ? PSW32_MASK_RI : 0; + /* Build a 64 bit psw mask from 31 bit mask. */ +- if ((tmp & ~mask) != PSW32_USER_BITS) ++ if ((tmp ^ PSW32_USER_BITS) & ~mask) + /* Invalid psw mask. */ + return -EINVAL; ++ if ((data & PSW32_MASK_ASC) == PSW32_ASC_HOME) ++ /* Invalid address-space-control bits */ ++ return -EINVAL; + regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | + (regs->psw.mask & PSW_MASK_BA) | + (__u64)(tmp & mask) << 32; +diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S +index 29bd7be..1ecd47b 100644 +--- a/arch/s390/kernel/sclp.S ++++ b/arch/s390/kernel/sclp.S +@@ -276,6 +276,8 @@ ENTRY(_sclp_print_early) + jno .Lesa2 + ahi %r15,-80 + stmh %r6,%r15,96(%r15) # store upper register halves ++ basr %r13,0 ++ lmh %r0,%r15,.Lzeroes-.(%r13) # clear upper register halves + .Lesa2: + #endif + lr %r10,%r2 # save string pointer +@@ -299,6 +301,8 @@ ENTRY(_sclp_print_early) + #endif + lm %r6,%r15,120(%r15) # restore registers + br %r14 ++.Lzeroes: ++ .fill 64,4,0 + + .LwritedataS4: + .long 0x00760005 # SCLP command for write data +diff --git a/arch/s390/kernel/suspend.c b/arch/s390/kernel/suspend.c +index a7a7537..d3236c9 100644 +--- a/arch/s390/kernel/suspend.c ++++ b/arch/s390/kernel/suspend.c +@@ -13,14 +13,10 @@ + #include + #include + #include ++#include + #include "entry.h" + + /* +- * References to section boundaries +- */ +-extern const void __nosave_begin, __nosave_end; +- +-/* + * The restore of the saved pages in an hibernation image will set + * the change and referenced bits in the storage key for each page. + * Overindication of the referenced bits after an hibernation cycle +@@ -142,6 +138,8 @@ int pfn_is_nosave(unsigned long pfn) + { + unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin)); + unsigned long nosave_end_pfn = PFN_DOWN(__pa(&__nosave_end)); ++ unsigned long eshared_pfn = PFN_DOWN(__pa(&_eshared)) - 1; ++ unsigned long stext_pfn = PFN_DOWN(__pa(&_stext)); + + /* Always save lowcore pages (LC protection might be enabled). */ + if (pfn <= LC_PAGES) +@@ -149,6 +147,8 @@ int pfn_is_nosave(unsigned long pfn) + if (pfn >= nosave_begin_pfn && pfn < nosave_end_pfn) + return 1; + /* Skip memory holes and read-only pages (NSS, DCSS, ...). */ ++ if (pfn >= stext_pfn && pfn <= eshared_pfn) ++ return ipl_info.type == IPL_TYPE_NSS ? 1 : 0; + if (tprot(PFN_PHYS(pfn))) + return 1; + return 0; +diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c +index 5f79d2d..f1ba119 100644 +--- a/arch/s390/kvm/interrupt.c ++++ b/arch/s390/kvm/interrupt.c +@@ -71,6 +71,7 @@ static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu, + return 0; + if (vcpu->arch.sie_block->gcr[0] & 0x2000ul) + return 1; ++ return 0; + case KVM_S390_INT_EMERGENCY: + if (psw_extint_disabled(vcpu)) + return 0; +diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c +index 75beea6..3588f2f 100644 +--- a/arch/s390/kvm/priv.c ++++ b/arch/s390/kvm/priv.c +@@ -414,6 +414,7 @@ static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem) + for (n = mem->count - 1; n > 0 ; n--) + memcpy(&mem->vm[n], &mem->vm[n - 1], sizeof(mem->vm[0])); + ++ memset(&mem->vm[0], 0, sizeof(mem->vm[0])); + mem->vm[0].cpus_total = cpus; + mem->vm[0].cpus_configured = cpus; + mem->vm[0].cpus_standby = 0; +diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c +index d95265b2..8e95432 100644 +--- a/arch/s390/mm/fault.c ++++ b/arch/s390/mm/fault.c +@@ -239,6 +239,12 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault) + do_no_context(regs); + else + pagefault_out_of_memory(); ++ } else if (fault & VM_FAULT_SIGSEGV) { ++ /* Kernel mode? Handle exceptions or die */ ++ if (!user_mode(regs)) ++ do_no_context(regs); ++ else ++ do_sigsegv(regs, SEGV_MAPERR); + } else if (fault & VM_FAULT_SIGBUS) { + /* Kernel mode? Handle exceptions or die */ + if (!user_mode(regs)) +diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c +index 3584ed9..e309c5c 100644 +--- a/arch/s390/mm/pgtable.c ++++ b/arch/s390/mm/pgtable.c +@@ -810,11 +810,21 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr, + pte_t *ptep; + + down_read(&mm->mmap_sem); ++retry: + ptep = get_locked_pte(current->mm, addr, &ptl); + if (unlikely(!ptep)) { + up_read(&mm->mmap_sem); + return -EFAULT; + } ++ if (!(pte_val(*ptep) & _PAGE_INVALID) && ++ (pte_val(*ptep) & _PAGE_PROTECT)) { ++ pte_unmap_unlock(*ptep, ptl); ++ if (fixup_user_fault(current, mm, addr, FAULT_FLAG_WRITE)) { ++ up_read(&mm->mmap_sem); ++ return -EFAULT; ++ } ++ goto retry; ++ } + + new = old = pgste_get_lock(ptep); + pgste_val(new) &= ~(PGSTE_GR_BIT | PGSTE_GC_BIT | +diff --git a/arch/score/mm/fault.c b/arch/score/mm/fault.c +index 52238983..6860beb 100644 +--- a/arch/score/mm/fault.c ++++ b/arch/score/mm/fault.c +@@ -114,6 +114,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/sh/include/asm/sections.h b/arch/sh/include/asm/sections.h +index 1b61997..7a99e6a 100644 +--- a/arch/sh/include/asm/sections.h ++++ b/arch/sh/include/asm/sections.h +@@ -3,7 +3,6 @@ + + #include + +-extern long __nosave_begin, __nosave_end; + extern long __machvec_start, __machvec_end; + extern char __uncached_start, __uncached_end; + extern char __start_eh_frame[], __stop_eh_frame[]; +diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c +index ff1465c..5acf89c 100644 +--- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c ++++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c +@@ -118,7 +118,7 @@ static struct plat_sci_port scif0_platform_data = { + }; + + static struct resource scif0_resources[] = { +- DEFINE_RES_MEM(0xfffffe80, 0x100), ++ DEFINE_RES_MEM(0xfffffe80, 0x10), + DEFINE_RES_IRQ(evt2irq(0x4e0)), + }; + +@@ -143,7 +143,7 @@ static struct plat_sci_port scif1_platform_data = { + }; + + static struct resource scif1_resources[] = { +- DEFINE_RES_MEM(0xa4000150, 0x100), ++ DEFINE_RES_MEM(0xa4000150, 0x10), + DEFINE_RES_IRQ(evt2irq(0x900)), + }; + +@@ -169,7 +169,7 @@ static struct plat_sci_port scif2_platform_data = { + }; + + static struct resource scif2_resources[] = { +- DEFINE_RES_MEM(0xa4000140, 0x100), ++ DEFINE_RES_MEM(0xa4000140, 0x10), + DEFINE_RES_IRQ(evt2irq(0x880)), + }; + +diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c +index 541dc61..a58fec9 100644 +--- a/arch/sh/mm/fault.c ++++ b/arch/sh/mm/fault.c +@@ -353,6 +353,8 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, + } else { + if (fault & VM_FAULT_SIGBUS) + do_sigbus(regs, error_code, address); ++ else if (fault & VM_FAULT_SIGSEGV) ++ bad_area(regs, error_code, address); + else + BUG(); + } +diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig +index b398c68..a38513c 100644 +--- a/arch/sparc/Kconfig ++++ b/arch/sparc/Kconfig +@@ -67,6 +67,7 @@ config SPARC64 + select HAVE_SYSCALL_TRACEPOINTS + select HAVE_CONTEXT_TRACKING + select HAVE_DEBUG_KMEMLEAK ++ select SPARSE_IRQ + select RTC_DRV_CMOS + select RTC_DRV_BQ4802 + select RTC_DRV_SUN4V +diff --git a/arch/sparc/crypto/aes_glue.c b/arch/sparc/crypto/aes_glue.c +index 503e6d9..ded4cee3 100644 +--- a/arch/sparc/crypto/aes_glue.c ++++ b/arch/sparc/crypto/aes_glue.c +@@ -499,6 +499,6 @@ module_exit(aes_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("AES Secure Hash Algorithm, sparc64 aes opcode accelerated"); + +-MODULE_ALIAS("aes"); ++MODULE_ALIAS_CRYPTO("aes"); + + #include "crop_devid.c" +diff --git a/arch/sparc/crypto/camellia_glue.c b/arch/sparc/crypto/camellia_glue.c +index 888f6260..641f55c 100644 +--- a/arch/sparc/crypto/camellia_glue.c ++++ b/arch/sparc/crypto/camellia_glue.c +@@ -322,6 +322,6 @@ module_exit(camellia_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated"); + +-MODULE_ALIAS("aes"); ++MODULE_ALIAS_CRYPTO("aes"); + + #include "crop_devid.c" +diff --git a/arch/sparc/crypto/crc32c_glue.c b/arch/sparc/crypto/crc32c_glue.c +index 5162fad..d1064e4 100644 +--- a/arch/sparc/crypto/crc32c_glue.c ++++ b/arch/sparc/crypto/crc32c_glue.c +@@ -176,6 +176,6 @@ module_exit(crc32c_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("CRC32c (Castagnoli), sparc64 crc32c opcode accelerated"); + +-MODULE_ALIAS("crc32c"); ++MODULE_ALIAS_CRYPTO("crc32c"); + + #include "crop_devid.c" +diff --git a/arch/sparc/crypto/des_glue.c b/arch/sparc/crypto/des_glue.c +index 3065bc6..d115009 100644 +--- a/arch/sparc/crypto/des_glue.c ++++ b/arch/sparc/crypto/des_glue.c +@@ -532,6 +532,6 @@ module_exit(des_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated"); + +-MODULE_ALIAS("des"); ++MODULE_ALIAS_CRYPTO("des"); + + #include "crop_devid.c" +diff --git a/arch/sparc/crypto/md5_glue.c b/arch/sparc/crypto/md5_glue.c +index 09a9ea1..64c7ff5 100644 +--- a/arch/sparc/crypto/md5_glue.c ++++ b/arch/sparc/crypto/md5_glue.c +@@ -185,6 +185,6 @@ module_exit(md5_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, sparc64 md5 opcode accelerated"); + +-MODULE_ALIAS("md5"); ++MODULE_ALIAS_CRYPTO("md5"); + + #include "crop_devid.c" +diff --git a/arch/sparc/crypto/sha1_glue.c b/arch/sparc/crypto/sha1_glue.c +index 6cd5f29..1b3e47a 100644 +--- a/arch/sparc/crypto/sha1_glue.c ++++ b/arch/sparc/crypto/sha1_glue.c +@@ -180,6 +180,6 @@ module_exit(sha1_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, sparc64 sha1 opcode accelerated"); + +-MODULE_ALIAS("sha1"); ++MODULE_ALIAS_CRYPTO("sha1"); + + #include "crop_devid.c" +diff --git a/arch/sparc/crypto/sha256_glue.c b/arch/sparc/crypto/sha256_glue.c +index 04f555a..41f27cc 100644 +--- a/arch/sparc/crypto/sha256_glue.c ++++ b/arch/sparc/crypto/sha256_glue.c +@@ -237,7 +237,7 @@ module_exit(sha256_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm, sparc64 sha256 opcode accelerated"); + +-MODULE_ALIAS("sha224"); +-MODULE_ALIAS("sha256"); ++MODULE_ALIAS_CRYPTO("sha224"); ++MODULE_ALIAS_CRYPTO("sha256"); + + #include "crop_devid.c" +diff --git a/arch/sparc/crypto/sha512_glue.c b/arch/sparc/crypto/sha512_glue.c +index f04d199..9fff885 100644 +--- a/arch/sparc/crypto/sha512_glue.c ++++ b/arch/sparc/crypto/sha512_glue.c +@@ -222,7 +222,7 @@ module_exit(sha512_sparc64_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA-384 and SHA-512 Secure Hash Algorithm, sparc64 sha512 opcode accelerated"); + +-MODULE_ALIAS("sha384"); +-MODULE_ALIAS("sha512"); ++MODULE_ALIAS_CRYPTO("sha384"); ++MODULE_ALIAS_CRYPTO("sha512"); + + #include "crop_devid.c" +diff --git a/arch/sparc/include/asm/atomic_32.h b/arch/sparc/include/asm/atomic_32.h +index 905832a..a0ed182 100644 +--- a/arch/sparc/include/asm/atomic_32.h ++++ b/arch/sparc/include/asm/atomic_32.h +@@ -21,7 +21,7 @@ + + extern int __atomic_add_return(int, atomic_t *); + extern int atomic_cmpxchg(atomic_t *, int, int); +-#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) ++extern int atomic_xchg(atomic_t *, int); + extern int __atomic_add_unless(atomic_t *, int, int); + extern void atomic_set(atomic_t *, int); + +diff --git a/arch/sparc/include/asm/cmpxchg_32.h b/arch/sparc/include/asm/cmpxchg_32.h +index 1fae1a0..ae0f9a7 100644 +--- a/arch/sparc/include/asm/cmpxchg_32.h ++++ b/arch/sparc/include/asm/cmpxchg_32.h +@@ -11,22 +11,14 @@ + #ifndef __ARCH_SPARC_CMPXCHG__ + #define __ARCH_SPARC_CMPXCHG__ + +-static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val) +-{ +- __asm__ __volatile__("swap [%2], %0" +- : "=&r" (val) +- : "0" (val), "r" (m) +- : "memory"); +- return val; +-} +- ++extern unsigned long __xchg_u32(volatile u32 *m, u32 new); + extern void __xchg_called_with_bad_pointer(void); + + static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size) + { + switch (size) { + case 4: +- return xchg_u32(ptr, x); ++ return __xchg_u32(ptr, x); + } + __xchg_called_with_bad_pointer(); + return x; +diff --git a/arch/sparc/include/asm/hypervisor.h b/arch/sparc/include/asm/hypervisor.h +index ca121f0..17be9d6 100644 +--- a/arch/sparc/include/asm/hypervisor.h ++++ b/arch/sparc/include/asm/hypervisor.h +@@ -2944,6 +2944,16 @@ extern unsigned long sun4v_vt_set_perfreg(unsigned long reg_num, + unsigned long reg_val); + #endif + ++#define HV_FAST_T5_GET_PERFREG 0x1a8 ++#define HV_FAST_T5_SET_PERFREG 0x1a9 ++ ++#ifndef __ASSEMBLY__ ++unsigned long sun4v_t5_get_perfreg(unsigned long reg_num, ++ unsigned long *reg_val); ++unsigned long sun4v_t5_set_perfreg(unsigned long reg_num, ++ unsigned long reg_val); ++#endif ++ + /* Function numbers for HV_CORE_TRAP. */ + #define HV_CORE_SET_VER 0x00 + #define HV_CORE_PUTCHAR 0x01 +@@ -2975,6 +2985,7 @@ extern unsigned long sun4v_vt_set_perfreg(unsigned long reg_num, + #define HV_GRP_VF_CPU 0x0205 + #define HV_GRP_KT_CPU 0x0209 + #define HV_GRP_VT_CPU 0x020c ++#define HV_GRP_T5_CPU 0x0211 + #define HV_GRP_DIAG 0x0300 + + #ifndef __ASSEMBLY__ +diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h +index abf6afe..3deb07f 100644 +--- a/arch/sparc/include/asm/irq_64.h ++++ b/arch/sparc/include/asm/irq_64.h +@@ -37,7 +37,7 @@ + * + * ino_bucket->irq allocation is made during {sun4v_,}build_irq(). + */ +-#define NR_IRQS 255 ++#define NR_IRQS (2048) + + extern void irq_install_pre_handler(int irq, + void (*func)(unsigned int, void *, void *), +@@ -57,11 +57,8 @@ extern unsigned int sun4u_build_msi(u32 portid, unsigned int *irq_p, + unsigned long iclr_base); + extern void sun4u_destroy_msi(unsigned int irq); + +-extern unsigned char irq_alloc(unsigned int dev_handle, +- unsigned int dev_ino); +-#ifdef CONFIG_PCI_MSI +-extern void irq_free(unsigned int irq); +-#endif ++unsigned int irq_alloc(unsigned int dev_handle, unsigned int dev_ino); ++void irq_free(unsigned int irq); + + extern void __init init_IRQ(void); + extern void fixup_irqs(void); +diff --git a/arch/sparc/include/asm/ldc.h b/arch/sparc/include/asm/ldc.h +index bdb524a..8732ed3 100644 +--- a/arch/sparc/include/asm/ldc.h ++++ b/arch/sparc/include/asm/ldc.h +@@ -53,13 +53,14 @@ struct ldc_channel; + /* Allocate state for a channel. */ + extern struct ldc_channel *ldc_alloc(unsigned long id, + const struct ldc_channel_config *cfgp, +- void *event_arg); ++ void *event_arg, ++ const char *name); + + /* Shut down and free state for a channel. */ + extern void ldc_free(struct ldc_channel *lp); + + /* Register TX and RX queues of the link with the hypervisor. */ +-extern int ldc_bind(struct ldc_channel *lp, const char *name); ++extern int ldc_bind(struct ldc_channel *lp); + + /* For non-RAW protocols we need to complete a handshake before + * communication can proceed. ldc_connect() does that, if the +diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h +index a12dbe3..e48fdf4 100644 +--- a/arch/sparc/include/asm/oplib_64.h ++++ b/arch/sparc/include/asm/oplib_64.h +@@ -62,7 +62,8 @@ struct linux_mem_p1275 { + /* You must call prom_init() before using any of the library services, + * preferably as early as possible. Pass it the romvec pointer. + */ +-extern void prom_init(void *cif_handler, void *cif_stack); ++extern void prom_init(void *cif_handler); ++extern void prom_init_report(void); + + /* Boot argument acquisition, returns the boot command line string. */ + extern char *prom_getbootargs(void); +diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h +index aac53fc..b18e602 100644 +--- a/arch/sparc/include/asm/page_64.h ++++ b/arch/sparc/include/asm/page_64.h +@@ -57,18 +57,21 @@ extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct pag + typedef struct { unsigned long pte; } pte_t; + typedef struct { unsigned long iopte; } iopte_t; + typedef struct { unsigned long pmd; } pmd_t; ++typedef struct { unsigned long pud; } pud_t; + typedef struct { unsigned long pgd; } pgd_t; + typedef struct { unsigned long pgprot; } pgprot_t; + + #define pte_val(x) ((x).pte) + #define iopte_val(x) ((x).iopte) + #define pmd_val(x) ((x).pmd) ++#define pud_val(x) ((x).pud) + #define pgd_val(x) ((x).pgd) + #define pgprot_val(x) ((x).pgprot) + + #define __pte(x) ((pte_t) { (x) } ) + #define __iopte(x) ((iopte_t) { (x) } ) + #define __pmd(x) ((pmd_t) { (x) } ) ++#define __pud(x) ((pud_t) { (x) } ) + #define __pgd(x) ((pgd_t) { (x) } ) + #define __pgprot(x) ((pgprot_t) { (x) } ) + +@@ -77,18 +80,21 @@ typedef struct { unsigned long pgprot; } pgprot_t; + typedef unsigned long pte_t; + typedef unsigned long iopte_t; + typedef unsigned long pmd_t; ++typedef unsigned long pud_t; + typedef unsigned long pgd_t; + typedef unsigned long pgprot_t; + + #define pte_val(x) (x) + #define iopte_val(x) (x) + #define pmd_val(x) (x) ++#define pud_val(x) (x) + #define pgd_val(x) (x) + #define pgprot_val(x) (x) + + #define __pte(x) (x) + #define __iopte(x) (x) + #define __pmd(x) (x) ++#define __pud(x) (x) + #define __pgd(x) (x) + #define __pgprot(x) (x) + +@@ -96,21 +102,14 @@ typedef unsigned long pgprot_t; + + typedef pte_t *pgtable_t; + +-/* These two values define the virtual address space range in which we +- * must forbid 64-bit user processes from making mappings. It used to +- * represent precisely the virtual address space hole present in most +- * early sparc64 chips including UltraSPARC-I. But now it also is +- * further constrained by the limits of our page tables, which is +- * 43-bits of virtual address. +- */ +-#define SPARC64_VA_HOLE_TOP _AC(0xfffffc0000000000,UL) +-#define SPARC64_VA_HOLE_BOTTOM _AC(0x0000040000000000,UL) ++extern unsigned long sparc64_va_hole_top; ++extern unsigned long sparc64_va_hole_bottom; + + /* The next two defines specify the actual exclusion region we + * enforce, wherein we use a 4GB red zone on each side of the VA hole. + */ +-#define VA_EXCLUDE_START (SPARC64_VA_HOLE_BOTTOM - (1UL << 32UL)) +-#define VA_EXCLUDE_END (SPARC64_VA_HOLE_TOP + (1UL << 32UL)) ++#define VA_EXCLUDE_START (sparc64_va_hole_bottom - (1UL << 32UL)) ++#define VA_EXCLUDE_END (sparc64_va_hole_top + (1UL << 32UL)) + + #define TASK_UNMAPPED_BASE (test_thread_flag(TIF_32BIT) ? \ + _AC(0x0000000070000000,UL) : \ +@@ -118,20 +117,16 @@ typedef pte_t *pgtable_t; + + #include + +-#define PAGE_OFFSET_BY_BITS(X) (-(_AC(1,UL) << (X))) + extern unsigned long PAGE_OFFSET; + + #endif /* !(__ASSEMBLY__) */ + +-/* The maximum number of physical memory address bits we support, this +- * is used to size various tables used to manage kernel TLB misses and +- * also the sparsemem code. ++/* The maximum number of physical memory address bits we support. The ++ * largest value we can support is whatever "KPGD_SHIFT + KPTE_BITS" ++ * evaluates to. + */ +-#define MAX_PHYS_ADDRESS_BITS 47 ++#define MAX_PHYS_ADDRESS_BITS 53 + +-/* These two shift counts are used when indexing sparc64_valid_addr_bitmap +- * and kpte_linear_bitmap. +- */ + #define ILOG2_4MB 22 + #define ILOG2_256MB 28 + +diff --git a/arch/sparc/include/asm/pgalloc_64.h b/arch/sparc/include/asm/pgalloc_64.h +index bcfe063..2c8d41f 100644 +--- a/arch/sparc/include/asm/pgalloc_64.h ++++ b/arch/sparc/include/asm/pgalloc_64.h +@@ -15,6 +15,13 @@ + + extern struct kmem_cache *pgtable_cache; + ++static inline void __pgd_populate(pgd_t *pgd, pud_t *pud) ++{ ++ pgd_set(pgd, pud); ++} ++ ++#define pgd_populate(MM, PGD, PUD) __pgd_populate(PGD, PUD) ++ + static inline pgd_t *pgd_alloc(struct mm_struct *mm) + { + return kmem_cache_alloc(pgtable_cache, GFP_KERNEL); +@@ -25,7 +32,23 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) + kmem_cache_free(pgtable_cache, pgd); + } + +-#define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD) ++static inline void __pud_populate(pud_t *pud, pmd_t *pmd) ++{ ++ pud_set(pud, pmd); ++} ++ ++#define pud_populate(MM, PUD, PMD) __pud_populate(PUD, PMD) ++ ++static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) ++{ ++ return kmem_cache_alloc(pgtable_cache, ++ GFP_KERNEL|__GFP_REPEAT); ++} ++ ++static inline void pud_free(struct mm_struct *mm, pud_t *pud) ++{ ++ kmem_cache_free(pgtable_cache, pud); ++} + + static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) + { +@@ -91,4 +114,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pte_t *pte, + #define __pmd_free_tlb(tlb, pmd, addr) \ + pgtable_free_tlb(tlb, pmd, false) + ++#define __pud_free_tlb(tlb, pud, addr) \ ++ pgtable_free_tlb(tlb, pud, false) ++ + #endif /* _SPARC64_PGALLOC_H */ +diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h +index 0f9e945..e8dfabf 100644 +--- a/arch/sparc/include/asm/pgtable_64.h ++++ b/arch/sparc/include/asm/pgtable_64.h +@@ -20,11 +20,10 @@ + #include + #include + +-#include +- + /* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB). + * The page copy blockops can use 0x6000000 to 0x8000000. +- * The TSB is mapped in the 0x8000000 to 0xa000000 range. ++ * The 8K TSB is mapped in the 0x8000000 to 0x8400000 range. ++ * The 4M TSB is mapped in the 0x8400000 to 0x8800000 range. + * The PROM resides in an area spanning 0xf0000000 to 0x100000000. + * The vmalloc area spans 0x100000000 to 0x200000000. + * Since modules need to be in the lowest 32-bits of the address space, +@@ -33,17 +32,15 @@ + * 0x400000000. + */ + #define TLBTEMP_BASE _AC(0x0000000006000000,UL) +-#define TSBMAP_BASE _AC(0x0000000008000000,UL) ++#define TSBMAP_8K_BASE _AC(0x0000000008000000,UL) ++#define TSBMAP_4M_BASE _AC(0x0000000008400000,UL) + #define MODULES_VADDR _AC(0x0000000010000000,UL) + #define MODULES_LEN _AC(0x00000000e0000000,UL) + #define MODULES_END _AC(0x00000000f0000000,UL) + #define LOW_OBP_ADDRESS _AC(0x00000000f0000000,UL) + #define HI_OBP_ADDRESS _AC(0x0000000100000000,UL) + #define VMALLOC_START _AC(0x0000000100000000,UL) +-#define VMALLOC_END _AC(0x0000010000000000,UL) +-#define VMEMMAP_BASE _AC(0x0000010000000000,UL) +- +-#define vmemmap ((struct page *)VMEMMAP_BASE) ++#define VMEMMAP_BASE VMALLOC_END + + /* PMD_SHIFT determines the size of the area a second-level page + * table can map +@@ -53,13 +50,25 @@ + #define PMD_MASK (~(PMD_SIZE-1)) + #define PMD_BITS (PAGE_SHIFT - 3) + +-/* PGDIR_SHIFT determines what a third-level page table entry can map */ +-#define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-3) + PMD_BITS) ++/* PUD_SHIFT determines the size of the area a third-level page ++ * table can map ++ */ ++#define PUD_SHIFT (PMD_SHIFT + PMD_BITS) ++#define PUD_SIZE (_AC(1,UL) << PUD_SHIFT) ++#define PUD_MASK (~(PUD_SIZE-1)) ++#define PUD_BITS (PAGE_SHIFT - 3) ++ ++/* PGDIR_SHIFT determines what a fourth-level page table entry can map */ ++#define PGDIR_SHIFT (PUD_SHIFT + PUD_BITS) + #define PGDIR_SIZE (_AC(1,UL) << PGDIR_SHIFT) + #define PGDIR_MASK (~(PGDIR_SIZE-1)) + #define PGDIR_BITS (PAGE_SHIFT - 3) + +-#if (PGDIR_SHIFT + PGDIR_BITS) != 43 ++#if (MAX_PHYS_ADDRESS_BITS > PGDIR_SHIFT + PGDIR_BITS) ++#error MAX_PHYS_ADDRESS_BITS exceeds what kernel page tables can support ++#endif ++ ++#if (PGDIR_SHIFT + PGDIR_BITS) != 53 + #error Page table parameters do not cover virtual address space properly. + #endif + +@@ -69,19 +78,32 @@ + + #ifndef __ASSEMBLY__ + ++extern unsigned long VMALLOC_END; ++ ++#define vmemmap ((struct page *)VMEMMAP_BASE) ++ + #include + ++bool kern_addr_valid(unsigned long addr); ++ + /* Entries per page directory level. */ + #define PTRS_PER_PTE (1UL << (PAGE_SHIFT-3)) + #define PTRS_PER_PMD (1UL << PMD_BITS) ++#define PTRS_PER_PUD (1UL << PUD_BITS) + #define PTRS_PER_PGD (1UL << PGDIR_BITS) + + /* Kernel has a separate 44bit address space. */ + #define FIRST_USER_ADDRESS 0 + +-#define pte_ERROR(e) __builtin_trap() +-#define pmd_ERROR(e) __builtin_trap() +-#define pgd_ERROR(e) __builtin_trap() ++#define pmd_ERROR(e) \ ++ pr_err("%s:%d: bad pmd %p(%016lx) seen at (%pS)\n", \ ++ __FILE__, __LINE__, &(e), pmd_val(e), __builtin_return_address(0)) ++#define pud_ERROR(e) \ ++ pr_err("%s:%d: bad pud %p(%016lx) seen at (%pS)\n", \ ++ __FILE__, __LINE__, &(e), pud_val(e), __builtin_return_address(0)) ++#define pgd_ERROR(e) \ ++ pr_err("%s:%d: bad pgd %p(%016lx) seen at (%pS)\n", \ ++ __FILE__, __LINE__, &(e), pgd_val(e), __builtin_return_address(0)) + + #endif /* !(__ASSEMBLY__) */ + +@@ -90,6 +112,7 @@ + #define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/ + #define _PAGE_SPECIAL _AC(0x0200000000000000,UL) /* Special page */ + #define _PAGE_PMD_HUGE _AC(0x0100000000000000,UL) /* Huge page */ ++#define _PAGE_PUD_HUGE _PAGE_PMD_HUGE + + /* Advertise support for _PAGE_SPECIAL */ + #define __HAVE_ARCH_PTE_SPECIAL +@@ -258,8 +281,8 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot) + { + unsigned long mask, tmp; + +- /* SUN4U: 0x600307ffffffecb8 (negated == 0x9ffcf80000001347) +- * SUN4V: 0x30ffffffffffee17 (negated == 0xcf000000000011e8) ++ /* SUN4U: 0x630107ffffffec38 (negated == 0x9cfef800000013c7) ++ * SUN4V: 0x33ffffffffffee07 (negated == 0xcc000000000011f8) + * + * Even if we use negation tricks the result is still a 6 + * instruction sequence, so don't try to play fancy and just +@@ -289,10 +312,10 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot) + " .previous\n" + : "=r" (mask), "=r" (tmp) + : "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U | +- _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | _PAGE_PRESENT_4U | ++ _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | + _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4U), + "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V | +- _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | _PAGE_PRESENT_4V | ++ _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | + _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V)); + + return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask)); +@@ -633,29 +656,29 @@ static inline unsigned long pmd_large(pmd_t pmd) + { + pte_t pte = __pte(pmd_val(pmd)); + +- return (pte_val(pte) & _PAGE_PMD_HUGE) && pte_present(pte); ++ return pte_val(pte) & _PAGE_PMD_HUGE; + } + +-#ifdef CONFIG_TRANSPARENT_HUGEPAGE +-static inline unsigned long pmd_young(pmd_t pmd) ++static inline unsigned long pmd_pfn(pmd_t pmd) + { + pte_t pte = __pte(pmd_val(pmd)); + +- return pte_young(pte); ++ return pte_pfn(pte); + } + +-static inline unsigned long pmd_write(pmd_t pmd) ++#ifdef CONFIG_TRANSPARENT_HUGEPAGE ++static inline unsigned long pmd_young(pmd_t pmd) + { + pte_t pte = __pte(pmd_val(pmd)); + +- return pte_write(pte); ++ return pte_young(pte); + } + +-static inline unsigned long pmd_pfn(pmd_t pmd) ++static inline unsigned long pmd_write(pmd_t pmd) + { + pte_t pte = __pte(pmd_val(pmd)); + +- return pte_pfn(pte); ++ return pte_write(pte); + } + + static inline unsigned long pmd_trans_huge(pmd_t pmd) +@@ -719,20 +742,6 @@ static inline pmd_t pmd_mkwrite(pmd_t pmd) + return __pmd(pte_val(pte)); + } + +-static inline pmd_t pmd_mknotpresent(pmd_t pmd) +-{ +- unsigned long mask; +- +- if (tlb_type == hypervisor) +- mask = _PAGE_PRESENT_4V; +- else +- mask = _PAGE_PRESENT_4U; +- +- pmd_val(pmd) &= ~mask; +- +- return pmd; +-} +- + static inline pmd_t pmd_mksplitting(pmd_t pmd) + { + pte_t pte = __pte(pmd_val(pmd)); +@@ -757,6 +766,22 @@ static inline int pmd_present(pmd_t pmd) + + #define pmd_none(pmd) (!pmd_val(pmd)) + ++/* pmd_bad() is only called on non-trans-huge PMDs. Our encoding is ++ * very simple, it's just the physical address. PTE tables are of ++ * size PAGE_SIZE so make sure the sub-PAGE_SIZE bits are clear and ++ * the top bits outside of the range of any physical address size we ++ * support are clear as well. We also validate the physical itself. ++ */ ++#define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK) ++ ++#define pud_none(pud) (!pud_val(pud)) ++ ++#define pud_bad(pud) (pud_val(pud) & ~PAGE_MASK) ++ ++#define pgd_none(pgd) (!pgd_val(pgd)) ++ ++#define pgd_bad(pgd) (pgd_val(pgd) & ~PAGE_MASK) ++ + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + extern void set_pmd_at(struct mm_struct *mm, unsigned long addr, + pmd_t *pmdp, pmd_t pmd); +@@ -790,16 +815,34 @@ static inline unsigned long __pmd_page(pmd_t pmd) + #define pud_page_vaddr(pud) \ + ((unsigned long) __va(pud_val(pud))) + #define pud_page(pud) virt_to_page((void *)pud_page_vaddr(pud)) +-#define pmd_bad(pmd) (0) + #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0UL) +-#define pud_none(pud) (!pud_val(pud)) +-#define pud_bad(pud) (0) + #define pud_present(pud) (pud_val(pud) != 0U) + #define pud_clear(pudp) (pud_val(*(pudp)) = 0UL) ++#define pgd_page_vaddr(pgd) \ ++ ((unsigned long) __va(pgd_val(pgd))) ++#define pgd_present(pgd) (pgd_val(pgd) != 0U) ++#define pgd_clear(pgdp) (pgd_val(*(pgd)) = 0UL) ++ ++static inline unsigned long pud_large(pud_t pud) ++{ ++ pte_t pte = __pte(pud_val(pud)); ++ ++ return pte_val(pte) & _PAGE_PMD_HUGE; ++} ++ ++static inline unsigned long pud_pfn(pud_t pud) ++{ ++ pte_t pte = __pte(pud_val(pud)); ++ ++ return pte_pfn(pte); ++} + + /* Same in both SUN4V and SUN4U. */ + #define pte_none(pte) (!pte_val(pte)) + ++#define pgd_set(pgdp, pudp) \ ++ (pgd_val(*(pgdp)) = (__pa((unsigned long) (pudp)))) ++ + /* to find an entry in a page-table-directory. */ + #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) + #define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) +@@ -807,6 +850,11 @@ static inline unsigned long __pmd_page(pmd_t pmd) + /* to find an entry in a kernel page-table-directory */ + #define pgd_offset_k(address) pgd_offset(&init_mm, address) + ++/* Find an entry in the third-level page table.. */ ++#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) ++#define pud_offset(pgdp, address) \ ++ ((pud_t *) pgd_page_vaddr(*(pgdp)) + pud_index(address)) ++ + /* Find an entry in the second-level page table.. */ + #define pmd_offset(pudp, address) \ + ((pmd_t *) pud_page_vaddr(*(pudp)) + \ +@@ -879,7 +927,6 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, + #endif + + extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; +-extern pmd_t swapper_low_pmd_dir[PTRS_PER_PMD]; + + extern void paging_init(void); + extern unsigned long find_ecache_flush_span(unsigned long size); +@@ -893,6 +940,10 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *); + extern void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr, + pmd_t *pmd); + ++#define __HAVE_ARCH_PMDP_INVALIDATE ++extern void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, ++ pmd_t *pmdp); ++ + #define __HAVE_ARCH_PGTABLE_DEPOSIT + extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp, + pgtable_t pgtable); +@@ -919,18 +970,6 @@ extern unsigned long pte_file(pte_t); + extern pte_t pgoff_to_pte(unsigned long); + #define PTE_FILE_MAX_BITS (64UL - PAGE_SHIFT - 1UL) + +-extern unsigned long sparc64_valid_addr_bitmap[]; +- +-/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ +-static inline bool kern_addr_valid(unsigned long addr) +-{ +- unsigned long paddr = __pa(addr); +- +- if ((paddr >> 41UL) != 0UL) +- return false; +- return test_bit(paddr >> 22, sparc64_valid_addr_bitmap); +-} +- + extern int page_in_phys_avail(unsigned long paddr); + + /* +diff --git a/arch/sparc/include/asm/setup.h b/arch/sparc/include/asm/setup.h +index 5e35e05..acd6146 100644 +--- a/arch/sparc/include/asm/setup.h ++++ b/arch/sparc/include/asm/setup.h +@@ -24,6 +24,10 @@ static inline int con_is_present(void) + } + #endif + ++#ifdef CONFIG_SPARC64 ++extern void __init start_early_boot(void); ++#endif ++ + extern void sun_do_break(void); + extern int stop_a_enabled; + extern int scons_pwroff; +diff --git a/arch/sparc/include/asm/spitfire.h b/arch/sparc/include/asm/spitfire.h +index 6b67e50..69424d4 100644 +--- a/arch/sparc/include/asm/spitfire.h ++++ b/arch/sparc/include/asm/spitfire.h +@@ -45,6 +45,8 @@ + #define SUN4V_CHIP_NIAGARA3 0x03 + #define SUN4V_CHIP_NIAGARA4 0x04 + #define SUN4V_CHIP_NIAGARA5 0x05 ++#define SUN4V_CHIP_SPARC_M6 0x06 ++#define SUN4V_CHIP_SPARC_M7 0x07 + #define SUN4V_CHIP_SPARC64X 0x8a + #define SUN4V_CHIP_UNKNOWN 0xff + +diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h +index a5f01ac..cc6275c 100644 +--- a/arch/sparc/include/asm/thread_info_64.h ++++ b/arch/sparc/include/asm/thread_info_64.h +@@ -63,7 +63,8 @@ struct thread_info { + struct pt_regs *kern_una_regs; + unsigned int kern_una_insn; + +- unsigned long fpregs[0] __attribute__ ((aligned(64))); ++ unsigned long fpregs[(7 * 256) / sizeof(unsigned long)] ++ __attribute__ ((aligned(64))); + }; + + #endif /* !(__ASSEMBLY__) */ +@@ -102,6 +103,7 @@ struct thread_info { + #define FAULT_CODE_ITLB 0x04 /* Miss happened in I-TLB */ + #define FAULT_CODE_WINFIXUP 0x08 /* Miss happened during spill/fill */ + #define FAULT_CODE_BLKCOMMIT 0x10 /* Use blk-commit ASI in copy_page */ ++#define FAULT_CODE_BAD_RA 0x20 /* Bad RA for sun4v */ + + #if PAGE_SHIFT == 13 + #define THREAD_SIZE (2*PAGE_SIZE) +diff --git a/arch/sparc/include/asm/tlbflush_64.h b/arch/sparc/include/asm/tlbflush_64.h +index 3c3c89f..7f9bab2 100644 +--- a/arch/sparc/include/asm/tlbflush_64.h ++++ b/arch/sparc/include/asm/tlbflush_64.h +@@ -34,6 +34,8 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, + { + } + ++void flush_tlb_kernel_range(unsigned long start, unsigned long end); ++ + #define __HAVE_ARCH_ENTER_LAZY_MMU_MODE + + extern void flush_tlb_pending(void); +@@ -48,11 +50,6 @@ extern void __flush_tlb_kernel_range(unsigned long start, unsigned long end); + + #ifndef CONFIG_SMP + +-#define flush_tlb_kernel_range(start,end) \ +-do { flush_tsb_kernel_range(start,end); \ +- __flush_tlb_kernel_range(start,end); \ +-} while (0) +- + static inline void global_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr) + { + __flush_tlb_page(CTX_HWBITS(mm->context), vaddr); +@@ -63,11 +60,6 @@ static inline void global_flush_tlb_page(struct mm_struct *mm, unsigned long vad + extern void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end); + extern void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr); + +-#define flush_tlb_kernel_range(start, end) \ +-do { flush_tsb_kernel_range(start,end); \ +- smp_flush_tlb_kernel_range(start, end); \ +-} while (0) +- + #define global_flush_tlb_page(mm, vaddr) \ + smp_flush_tlb_page(mm, vaddr) + +diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h +index 2230f80..ecb49cf 100644 +--- a/arch/sparc/include/asm/tsb.h ++++ b/arch/sparc/include/asm/tsb.h +@@ -133,9 +133,24 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; + sub TSB, 0x8, TSB; \ + TSB_STORE(TSB, TAG); + +- /* Do a kernel page table walk. Leaves physical PTE pointer in +- * REG1. Jumps to FAIL_LABEL on early page table walk termination. +- * VADDR will not be clobbered, but REG2 will. ++ /* Do a kernel page table walk. Leaves valid PTE value in ++ * REG1. Jumps to FAIL_LABEL on early page table walk ++ * termination. VADDR will not be clobbered, but REG2 will. ++ * ++ * There are two masks we must apply to propagate bits from ++ * the virtual address into the PTE physical address field ++ * when dealing with huge pages. This is because the page ++ * table boundaries do not match the huge page size(s) the ++ * hardware supports. ++ * ++ * In these cases we propagate the bits that are below the ++ * page table level where we saw the huge page mapping, but ++ * are still within the relevant physical bits for the huge ++ * page size in question. So for PMD mappings (which fall on ++ * bit 23, for 8MB per PMD) we must propagate bit 22 for a ++ * 4MB huge page. For huge PUDs (which fall on bit 33, for ++ * 8GB per PUD), we have to accomodate 256MB and 2GB huge ++ * pages. So for those we propagate bits 32 to 28. + */ + #define KERN_PGTABLE_WALK(VADDR, REG1, REG2, FAIL_LABEL) \ + sethi %hi(swapper_pg_dir), REG1; \ +@@ -145,15 +160,40 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; + andn REG2, 0x7, REG2; \ + ldx [REG1 + REG2], REG1; \ + brz,pn REG1, FAIL_LABEL; \ +- sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ ++ sllx VADDR, 64 - (PUD_SHIFT + PUD_BITS), REG2; \ + srlx REG2, 64 - PAGE_SHIFT, REG2; \ + andn REG2, 0x7, REG2; \ + ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ + brz,pn REG1, FAIL_LABEL; \ +- sllx VADDR, 64 - PMD_SHIFT, REG2; \ ++ sethi %uhi(_PAGE_PUD_HUGE), REG2; \ ++ brz,pn REG1, FAIL_LABEL; \ ++ sllx REG2, 32, REG2; \ ++ andcc REG1, REG2, %g0; \ ++ sethi %hi(0xf8000000), REG2; \ ++ bne,pt %xcc, 697f; \ ++ sllx REG2, 1, REG2; \ ++ sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ + srlx REG2, 64 - PAGE_SHIFT, REG2; \ + andn REG2, 0x7, REG2; \ +- add REG1, REG2, REG1; ++ ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ ++ sethi %uhi(_PAGE_PMD_HUGE), REG2; \ ++ brz,pn REG1, FAIL_LABEL; \ ++ sllx REG2, 32, REG2; \ ++ andcc REG1, REG2, %g0; \ ++ be,pn %xcc, 698f; \ ++ sethi %hi(0x400000), REG2; \ ++697: brgez,pn REG1, FAIL_LABEL; \ ++ andn REG1, REG2, REG1; \ ++ and VADDR, REG2, REG2; \ ++ ba,pt %xcc, 699f; \ ++ or REG1, REG2, REG1; \ ++698: sllx VADDR, 64 - PMD_SHIFT, REG2; \ ++ srlx REG2, 64 - PAGE_SHIFT, REG2; \ ++ andn REG2, 0x7, REG2; \ ++ ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ ++ brgez,pn REG1, FAIL_LABEL; \ ++ nop; \ ++699: + + /* PMD has been loaded into REG1, interpret the value, seeing + * if it is a HUGE PMD or a normal one. If it is not valid +@@ -171,7 +211,8 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; + andcc REG1, REG2, %g0; \ + be,pt %xcc, 700f; \ + sethi %hi(4 * 1024 * 1024), REG2; \ +- andn REG1, REG2, REG1; \ ++ brgez,pn REG1, FAIL_LABEL; \ ++ andn REG1, REG2, REG1; \ + and VADDR, REG2, REG2; \ + brlz,pt REG1, PTE_LABEL; \ + or REG1, REG2, REG1; \ +@@ -197,6 +238,11 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; + andn REG2, 0x7, REG2; \ + ldxa [PHYS_PGD + REG2] ASI_PHYS_USE_EC, REG1; \ + brz,pn REG1, FAIL_LABEL; \ ++ sllx VADDR, 64 - (PUD_SHIFT + PUD_BITS), REG2; \ ++ srlx REG2, 64 - PAGE_SHIFT, REG2; \ ++ andn REG2, 0x7, REG2; \ ++ ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \ ++ brz,pn REG1, FAIL_LABEL; \ + sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \ + srlx REG2, 64 - PAGE_SHIFT, REG2; \ + andn REG2, 0x7, REG2; \ +@@ -245,8 +291,6 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; + (KERNEL_TSB_SIZE_BYTES / 16) + #define KERNEL_TSB4M_NENTRIES 4096 + +-#define KTSB_PHYS_SHIFT 15 +- + /* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL + * on TSB hit. REG1, REG2, REG3, and REG4 are used as temporaries + * and the found TTE will be left in REG1. REG3 and REG4 must +@@ -255,17 +299,15 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; + * VADDR and TAG will be preserved and not clobbered by this macro. + */ + #define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \ +-661: sethi %hi(swapper_tsb), REG1; \ +- or REG1, %lo(swapper_tsb), REG1; \ ++661: sethi %uhi(swapper_tsb), REG1; \ ++ sethi %hi(swapper_tsb), REG2; \ ++ or REG1, %ulo(swapper_tsb), REG1; \ ++ or REG2, %lo(swapper_tsb), REG2; \ + .section .swapper_tsb_phys_patch, "ax"; \ + .word 661b; \ + .previous; \ +-661: nop; \ +- .section .tsb_ldquad_phys_patch, "ax"; \ +- .word 661b; \ +- sllx REG1, KTSB_PHYS_SHIFT, REG1; \ +- sllx REG1, KTSB_PHYS_SHIFT, REG1; \ +- .previous; \ ++ sllx REG1, 32, REG1; \ ++ or REG1, REG2, REG1; \ + srlx VADDR, PAGE_SHIFT, REG2; \ + and REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \ + sllx REG2, 4, REG2; \ +@@ -280,17 +322,15 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end; + * we can make use of that for the index computation. + */ + #define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \ +-661: sethi %hi(swapper_4m_tsb), REG1; \ +- or REG1, %lo(swapper_4m_tsb), REG1; \ ++661: sethi %uhi(swapper_4m_tsb), REG1; \ ++ sethi %hi(swapper_4m_tsb), REG2; \ ++ or REG1, %ulo(swapper_4m_tsb), REG1; \ ++ or REG2, %lo(swapper_4m_tsb), REG2; \ + .section .swapper_4m_tsb_phys_patch, "ax"; \ + .word 661b; \ + .previous; \ +-661: nop; \ +- .section .tsb_ldquad_phys_patch, "ax"; \ +- .word 661b; \ +- sllx REG1, KTSB_PHYS_SHIFT, REG1; \ +- sllx REG1, KTSB_PHYS_SHIFT, REG1; \ +- .previous; \ ++ sllx REG1, 32, REG1; \ ++ or REG1, REG2, REG1; \ + and TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \ + sllx REG2, 4, REG2; \ + add REG1, REG2, REG2; \ +diff --git a/arch/sparc/include/asm/vio.h b/arch/sparc/include/asm/vio.h +index 432afa8..55841c1 100644 +--- a/arch/sparc/include/asm/vio.h ++++ b/arch/sparc/include/asm/vio.h +@@ -118,12 +118,18 @@ struct vio_disk_attr_info { + u8 vdisk_type; + #define VD_DISK_TYPE_SLICE 0x01 /* Slice in block device */ + #define VD_DISK_TYPE_DISK 0x02 /* Entire block device */ +- u16 resv1; ++ u8 vdisk_mtype; /* v1.1 */ ++#define VD_MEDIA_TYPE_FIXED 0x01 /* Fixed device */ ++#define VD_MEDIA_TYPE_CD 0x02 /* CD Device */ ++#define VD_MEDIA_TYPE_DVD 0x03 /* DVD Device */ ++ u8 resv1; + u32 vdisk_block_size; + u64 operations; +- u64 vdisk_size; ++ u64 vdisk_size; /* v1.1 */ + u64 max_xfer_size; +- u64 resv2[2]; ++ u32 phys_block_size; /* v1.2 */ ++ u32 resv2; ++ u64 resv3[1]; + }; + + struct vio_disk_desc { +@@ -259,7 +265,7 @@ static inline u32 vio_dring_avail(struct vio_dring_state *dr, + unsigned int ring_size) + { + return (dr->pending - +- ((dr->prod - dr->cons) & (ring_size - 1))); ++ ((dr->prod - dr->cons) & (ring_size - 1)) - 1); + } + + #define VIO_MAX_TYPE_LEN 32 +diff --git a/arch/sparc/include/asm/visasm.h b/arch/sparc/include/asm/visasm.h +index 39ca301..50d6f16 100644 +--- a/arch/sparc/include/asm/visasm.h ++++ b/arch/sparc/include/asm/visasm.h +@@ -28,18 +28,20 @@ + * Must preserve %o5 between VISEntryHalf and VISExitHalf */ + + #define VISEntryHalf \ ++ VISEntry ++ ++#define VISExitHalf \ ++ VISExit ++ ++#define VISEntryHalfFast(fail_label) \ + rd %fprs, %o5; \ + andcc %o5, FPRS_FEF, %g0; \ + be,pt %icc, 297f; \ +- sethi %hi(298f), %g7; \ +- sethi %hi(VISenterhalf), %g1; \ +- jmpl %g1 + %lo(VISenterhalf), %g0; \ +- or %g7, %lo(298f), %g7; \ +- clr %o5; \ +-297: wr %o5, FPRS_FEF, %fprs; \ +-298: ++ nop; \ ++ ba,a,pt %xcc, fail_label; \ ++297: wr %o5, FPRS_FEF, %fprs; + +-#define VISExitHalf \ ++#define VISExitHalfFast \ + wr %o5, 0, %fprs; + + #ifndef __ASSEMBLY__ +diff --git a/arch/sparc/include/uapi/asm/swab.h b/arch/sparc/include/uapi/asm/swab.h +index a34ad07..4c7c12d 100644 +--- a/arch/sparc/include/uapi/asm/swab.h ++++ b/arch/sparc/include/uapi/asm/swab.h +@@ -9,9 +9,9 @@ static inline __u16 __arch_swab16p(const __u16 *addr) + { + __u16 ret; + +- __asm__ __volatile__ ("lduha [%1] %2, %0" ++ __asm__ __volatile__ ("lduha [%2] %3, %0" + : "=r" (ret) +- : "r" (addr), "i" (ASI_PL)); ++ : "m" (*addr), "r" (addr), "i" (ASI_PL)); + return ret; + } + #define __arch_swab16p __arch_swab16p +@@ -20,9 +20,9 @@ static inline __u32 __arch_swab32p(const __u32 *addr) + { + __u32 ret; + +- __asm__ __volatile__ ("lduwa [%1] %2, %0" ++ __asm__ __volatile__ ("lduwa [%2] %3, %0" + : "=r" (ret) +- : "r" (addr), "i" (ASI_PL)); ++ : "m" (*addr), "r" (addr), "i" (ASI_PL)); + return ret; + } + #define __arch_swab32p __arch_swab32p +@@ -31,9 +31,9 @@ static inline __u64 __arch_swab64p(const __u64 *addr) + { + __u64 ret; + +- __asm__ __volatile__ ("ldxa [%1] %2, %0" ++ __asm__ __volatile__ ("ldxa [%2] %3, %0" + : "=r" (ret) +- : "r" (addr), "i" (ASI_PL)); ++ : "m" (*addr), "r" (addr), "i" (ASI_PL)); + return ret; + } + #define __arch_swab64p __arch_swab64p +diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c +index 5c51258..52e10de 100644 +--- a/arch/sparc/kernel/cpu.c ++++ b/arch/sparc/kernel/cpu.c +@@ -493,6 +493,18 @@ static void __init sun4v_cpu_probe(void) + sparc_pmu_type = "niagara5"; + break; + ++ case SUN4V_CHIP_SPARC_M6: ++ sparc_cpu_type = "SPARC-M6"; ++ sparc_fpu_type = "SPARC-M6 integrated FPU"; ++ sparc_pmu_type = "sparc-m6"; ++ break; ++ ++ case SUN4V_CHIP_SPARC_M7: ++ sparc_cpu_type = "SPARC-M7"; ++ sparc_fpu_type = "SPARC-M7 integrated FPU"; ++ sparc_pmu_type = "sparc-m7"; ++ break; ++ + case SUN4V_CHIP_SPARC64X: + sparc_cpu_type = "SPARC64-X"; + sparc_fpu_type = "SPARC64-X integrated FPU"; +diff --git a/arch/sparc/kernel/cpumap.c b/arch/sparc/kernel/cpumap.c +index de1c844..e69ec0e 100644 +--- a/arch/sparc/kernel/cpumap.c ++++ b/arch/sparc/kernel/cpumap.c +@@ -326,6 +326,8 @@ static int iterate_cpu(struct cpuinfo_tree *t, unsigned int root_index) + case SUN4V_CHIP_NIAGARA3: + case SUN4V_CHIP_NIAGARA4: + case SUN4V_CHIP_NIAGARA5: ++ case SUN4V_CHIP_SPARC_M6: ++ case SUN4V_CHIP_SPARC_M7: + case SUN4V_CHIP_SPARC64X: + rover_inc_table = niagara_iterate_method; + break; +diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c +index dff60ab..f87a55d 100644 +--- a/arch/sparc/kernel/ds.c ++++ b/arch/sparc/kernel/ds.c +@@ -1200,14 +1200,14 @@ static int ds_probe(struct vio_dev *vdev, const struct vio_device_id *id) + ds_cfg.tx_irq = vdev->tx_irq; + ds_cfg.rx_irq = vdev->rx_irq; + +- lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp); ++ lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp, "DS"); + if (IS_ERR(lp)) { + err = PTR_ERR(lp); + goto out_free_ds_states; + } + dp->lp = lp; + +- err = ldc_bind(lp, "DS"); ++ err = ldc_bind(lp); + if (err) + goto out_free_ldc; + +diff --git a/arch/sparc/kernel/dtlb_prot.S b/arch/sparc/kernel/dtlb_prot.S +index b2c2c5b..d668ca14 100644 +--- a/arch/sparc/kernel/dtlb_prot.S ++++ b/arch/sparc/kernel/dtlb_prot.S +@@ -24,11 +24,11 @@ + mov TLB_TAG_ACCESS, %g4 ! For reload of vaddr + + /* PROT ** ICACHE line 2: More real fault processing */ ++ ldxa [%g4] ASI_DMMU, %g5 ! Put tagaccess in %g5 + bgu,pn %xcc, winfix_trampoline ! Yes, perform winfixup +- ldxa [%g4] ASI_DMMU, %g5 ! Put tagaccess in %g5 +- ba,pt %xcc, sparc64_realfault_common ! Nope, normal fault + mov FAULT_CODE_DTLB | FAULT_CODE_WRITE, %g4 +- nop ++ ba,pt %xcc, sparc64_realfault_common ! Nope, normal fault ++ nop + nop + nop + nop +diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h +index 140966f..c88ffb9 100644 +--- a/arch/sparc/kernel/entry.h ++++ b/arch/sparc/kernel/entry.h +@@ -66,13 +66,10 @@ struct pause_patch_entry { + extern struct pause_patch_entry __pause_3insn_patch, + __pause_3insn_patch_end; + +-extern void __init per_cpu_patch(void); + extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *, + struct sun4v_1insn_patch_entry *); + extern void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *, + struct sun4v_2insn_patch_entry *); +-extern void __init sun4v_patch(void); +-extern void __init boot_cpu_id_too_large(int cpu); + extern unsigned int dcache_parity_tl1_occurred; + extern unsigned int icache_parity_tl1_occurred; + +diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S +index 26b706a..3d61fca 100644 +--- a/arch/sparc/kernel/head_64.S ++++ b/arch/sparc/kernel/head_64.S +@@ -282,8 +282,8 @@ sun4v_chip_type: + stx %l2, [%l4 + 0x0] + ldx [%sp + 2047 + 128 + 0x50], %l3 ! physaddr low + /* 4MB align */ +- srlx %l3, 22, %l3 +- sllx %l3, 22, %l3 ++ srlx %l3, ILOG2_4MB, %l3 ++ sllx %l3, ILOG2_4MB, %l3 + stx %l3, [%l4 + 0x8] + + /* Leave service as-is, "call-method" */ +@@ -427,6 +427,12 @@ sun4v_chip_type: + cmp %g2, '5' + be,pt %xcc, 5f + mov SUN4V_CHIP_NIAGARA5, %g4 ++ cmp %g2, '6' ++ be,pt %xcc, 5f ++ mov SUN4V_CHIP_SPARC_M6, %g4 ++ cmp %g2, '7' ++ be,pt %xcc, 5f ++ mov SUN4V_CHIP_SPARC_M7, %g4 + ba,pt %xcc, 49f + nop + +@@ -585,6 +591,12 @@ niagara_tlb_fixup: + cmp %g1, SUN4V_CHIP_NIAGARA5 + be,pt %xcc, niagara4_patch + nop ++ cmp %g1, SUN4V_CHIP_SPARC_M6 ++ be,pt %xcc, niagara4_patch ++ nop ++ cmp %g1, SUN4V_CHIP_SPARC_M7 ++ be,pt %xcc, niagara4_patch ++ nop + + call generic_patch_copyops + nop +@@ -660,14 +672,12 @@ tlb_fixup_done: + sethi %hi(init_thread_union), %g6 + or %g6, %lo(init_thread_union), %g6 + ldx [%g6 + TI_TASK], %g4 +- mov %sp, %l6 + + wr %g0, ASI_P, %asi + mov 1, %g1 + sllx %g1, THREAD_SHIFT, %g1 + sub %g1, (STACKFRAME_SZ + STACK_BIAS), %g1 + add %g6, %g1, %sp +- mov 0, %fp + + /* Set per-cpu pointer initially to zero, this makes + * the boot-cpu use the in-kernel-image per-cpu areas +@@ -694,44 +704,14 @@ tlb_fixup_done: + nop + #endif + +- mov %l6, %o1 ! OpenPROM stack + call prom_init + mov %l7, %o0 ! OpenPROM cif handler + +- /* Initialize current_thread_info()->cpu as early as possible. +- * In order to do that accurately we have to patch up the get_cpuid() +- * assembler sequences. And that, in turn, requires that we know +- * if we are on a Starfire box or not. While we're here, patch up +- * the sun4v sequences as well. ++ /* To create a one-register-window buffer between the kernel's ++ * initial stack and the last stack frame we use from the firmware, ++ * do the rest of the boot from a C helper function. + */ +- call check_if_starfire +- nop +- call per_cpu_patch +- nop +- call sun4v_patch +- nop +- +-#ifdef CONFIG_SMP +- call hard_smp_processor_id +- nop +- cmp %o0, NR_CPUS +- blu,pt %xcc, 1f +- nop +- call boot_cpu_id_too_large +- nop +- /* Not reached... */ +- +-1: +-#else +- mov 0, %o0 +-#endif +- sth %o0, [%g6 + TI_CPU] +- +- call prom_init_report +- nop +- +- /* Off we go.... */ +- call start_kernel ++ call start_early_boot + nop + /* Not reached... */ + +diff --git a/arch/sparc/kernel/hvapi.c b/arch/sparc/kernel/hvapi.c +index c0a2de0..5c55145 100644 +--- a/arch/sparc/kernel/hvapi.c ++++ b/arch/sparc/kernel/hvapi.c +@@ -46,6 +46,7 @@ static struct api_info api_table[] = { + { .group = HV_GRP_VF_CPU, }, + { .group = HV_GRP_KT_CPU, }, + { .group = HV_GRP_VT_CPU, }, ++ { .group = HV_GRP_T5_CPU, }, + { .group = HV_GRP_DIAG, .flags = FLAG_PRE_API }, + }; + +diff --git a/arch/sparc/kernel/hvcalls.S b/arch/sparc/kernel/hvcalls.S +index f3ab509..caedf83 100644 +--- a/arch/sparc/kernel/hvcalls.S ++++ b/arch/sparc/kernel/hvcalls.S +@@ -821,3 +821,19 @@ ENTRY(sun4v_vt_set_perfreg) + retl + nop + ENDPROC(sun4v_vt_set_perfreg) ++ ++ENTRY(sun4v_t5_get_perfreg) ++ mov %o1, %o4 ++ mov HV_FAST_T5_GET_PERFREG, %o5 ++ ta HV_FAST_TRAP ++ stx %o1, [%o4] ++ retl ++ nop ++ENDPROC(sun4v_t5_get_perfreg) ++ ++ENTRY(sun4v_t5_set_perfreg) ++ mov HV_FAST_T5_SET_PERFREG, %o5 ++ ta HV_FAST_TRAP ++ retl ++ nop ++ENDPROC(sun4v_t5_set_perfreg) +diff --git a/arch/sparc/kernel/hvtramp.S b/arch/sparc/kernel/hvtramp.S +index b7ddcdd..cdbfec2 100644 +--- a/arch/sparc/kernel/hvtramp.S ++++ b/arch/sparc/kernel/hvtramp.S +@@ -109,7 +109,6 @@ hv_cpu_startup: + sllx %g5, THREAD_SHIFT, %g5 + sub %g5, (STACKFRAME_SZ + STACK_BIAS), %g5 + add %g6, %g5, %sp +- mov 0, %fp + + call init_irqwork_curcpu + nop +diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c +index e7e215d..c2d81ad 100644 +--- a/arch/sparc/kernel/ioport.c ++++ b/arch/sparc/kernel/ioport.c +@@ -278,7 +278,8 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len, + } + + order = get_order(len_total); +- if ((va = __get_free_pages(GFP_KERNEL|__GFP_COMP, order)) == 0) ++ va = __get_free_pages(gfp, order); ++ if (va == 0) + goto err_nopages; + + if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) +@@ -443,7 +444,7 @@ static void *pci32_alloc_coherent(struct device *dev, size_t len, + } + + order = get_order(len_total); +- va = (void *) __get_free_pages(GFP_KERNEL, order); ++ va = (void *) __get_free_pages(gfp, order); + if (va == NULL) { + printk("pci_alloc_consistent: no %ld pages\n", len_total>>PAGE_SHIFT); + goto err_nopages; +diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c +index 666193f..4033c23 100644 +--- a/arch/sparc/kernel/irq_64.c ++++ b/arch/sparc/kernel/irq_64.c +@@ -47,8 +47,6 @@ + #include "cpumap.h" + #include "kstack.h" + +-#define NUM_IVECS (IMAP_INR + 1) +- + struct ino_bucket *ivector_table; + unsigned long ivector_table_pa; + +@@ -107,55 +105,196 @@ static void bucket_set_irq(unsigned long bucket_pa, unsigned int irq) + + #define irq_work_pa(__cpu) &(trap_block[(__cpu)].irq_worklist_pa) + +-static struct { +- unsigned int dev_handle; +- unsigned int dev_ino; +- unsigned int in_use; +-} irq_table[NR_IRQS]; +-static DEFINE_SPINLOCK(irq_alloc_lock); ++static unsigned long hvirq_major __initdata; ++static int __init early_hvirq_major(char *p) ++{ ++ int rc = kstrtoul(p, 10, &hvirq_major); ++ ++ return rc; ++} ++early_param("hvirq", early_hvirq_major); ++ ++static int hv_irq_version; ++ ++/* Major version 2.0 of HV_GRP_INTR added support for the VIRQ cookie ++ * based interfaces, but: ++ * ++ * 1) Several OSs, Solaris and Linux included, use them even when only ++ * negotiating version 1.0 (or failing to negotiate at all). So the ++ * hypervisor has a workaround that provides the VIRQ interfaces even ++ * when only verion 1.0 of the API is in use. ++ * ++ * 2) Second, and more importantly, with major version 2.0 these VIRQ ++ * interfaces only were actually hooked up for LDC interrupts, even ++ * though the Hypervisor specification clearly stated: ++ * ++ * The new interrupt API functions will be available to a guest ++ * when it negotiates version 2.0 in the interrupt API group 0x2. When ++ * a guest negotiates version 2.0, all interrupt sources will only ++ * support using the cookie interface, and any attempt to use the ++ * version 1.0 interrupt APIs numbered 0xa0 to 0xa6 will result in the ++ * ENOTSUPPORTED error being returned. ++ * ++ * with an emphasis on "all interrupt sources". ++ * ++ * To correct this, major version 3.0 was created which does actually ++ * support VIRQs for all interrupt sources (not just LDC devices). So ++ * if we want to move completely over the cookie based VIRQs we must ++ * negotiate major version 3.0 or later of HV_GRP_INTR. ++ */ ++static bool sun4v_cookie_only_virqs(void) ++{ ++ if (hv_irq_version >= 3) ++ return true; ++ return false; ++} + +-unsigned char irq_alloc(unsigned int dev_handle, unsigned int dev_ino) ++static void __init irq_init_hv(void) + { +- unsigned long flags; +- unsigned char ent; ++ unsigned long hv_error, major, minor = 0; ++ ++ if (tlb_type != hypervisor) ++ return; + +- BUILD_BUG_ON(NR_IRQS >= 256); ++ if (hvirq_major) ++ major = hvirq_major; ++ else ++ major = 3; + +- spin_lock_irqsave(&irq_alloc_lock, flags); ++ hv_error = sun4v_hvapi_register(HV_GRP_INTR, major, &minor); ++ if (!hv_error) ++ hv_irq_version = major; ++ else ++ hv_irq_version = 1; + +- for (ent = 1; ent < NR_IRQS; ent++) { +- if (!irq_table[ent].in_use) ++ pr_info("SUN4V: Using IRQ API major %d, cookie only virqs %s\n", ++ hv_irq_version, ++ sun4v_cookie_only_virqs() ? "enabled" : "disabled"); ++} ++ ++/* This function is for the timer interrupt.*/ ++int __init arch_probe_nr_irqs(void) ++{ ++ return 1; ++} ++ ++#define DEFAULT_NUM_IVECS (0xfffU) ++static unsigned int nr_ivec = DEFAULT_NUM_IVECS; ++#define NUM_IVECS (nr_ivec) ++ ++static unsigned int __init size_nr_ivec(void) ++{ ++ if (tlb_type == hypervisor) { ++ switch (sun4v_chip_type) { ++ /* Athena's devhandle|devino is large.*/ ++ case SUN4V_CHIP_SPARC64X: ++ nr_ivec = 0xffff; + break; ++ } + } +- if (ent >= NR_IRQS) { +- printk(KERN_ERR "IRQ: Out of virtual IRQs.\n"); +- ent = 0; +- } else { +- irq_table[ent].dev_handle = dev_handle; +- irq_table[ent].dev_ino = dev_ino; +- irq_table[ent].in_use = 1; +- } ++ return nr_ivec; ++} ++ ++struct irq_handler_data { ++ union { ++ struct { ++ unsigned int dev_handle; ++ unsigned int dev_ino; ++ }; ++ unsigned long sysino; ++ }; ++ struct ino_bucket bucket; ++ unsigned long iclr; ++ unsigned long imap; ++}; ++ ++static inline unsigned int irq_data_to_handle(struct irq_data *data) ++{ ++ struct irq_handler_data *ihd = data->handler_data; ++ ++ return ihd->dev_handle; ++} ++ ++static inline unsigned int irq_data_to_ino(struct irq_data *data) ++{ ++ struct irq_handler_data *ihd = data->handler_data; + +- spin_unlock_irqrestore(&irq_alloc_lock, flags); ++ return ihd->dev_ino; ++} ++ ++static inline unsigned long irq_data_to_sysino(struct irq_data *data) ++{ ++ struct irq_handler_data *ihd = data->handler_data; + +- return ent; ++ return ihd->sysino; + } + +-#ifdef CONFIG_PCI_MSI + void irq_free(unsigned int irq) + { +- unsigned long flags; ++ void *data = irq_get_handler_data(irq); + +- if (irq >= NR_IRQS) +- return; ++ kfree(data); ++ irq_set_handler_data(irq, NULL); ++ irq_free_descs(irq, 1); ++} + +- spin_lock_irqsave(&irq_alloc_lock, flags); ++unsigned int irq_alloc(unsigned int dev_handle, unsigned int dev_ino) ++{ ++ int irq; + +- irq_table[irq].in_use = 0; ++ irq = __irq_alloc_descs(-1, 1, 1, numa_node_id(), NULL); ++ if (irq <= 0) ++ goto out; + +- spin_unlock_irqrestore(&irq_alloc_lock, flags); ++ return irq; ++out: ++ return 0; ++} ++ ++static unsigned int cookie_exists(u32 devhandle, unsigned int devino) ++{ ++ unsigned long hv_err, cookie; ++ struct ino_bucket *bucket; ++ unsigned int irq = 0U; ++ ++ hv_err = sun4v_vintr_get_cookie(devhandle, devino, &cookie); ++ if (hv_err) { ++ pr_err("HV get cookie failed hv_err = %ld\n", hv_err); ++ goto out; ++ } ++ ++ if (cookie & ((1UL << 63UL))) { ++ cookie = ~cookie; ++ bucket = (struct ino_bucket *) __va(cookie); ++ irq = bucket->__irq; ++ } ++out: ++ return irq; ++} ++ ++static unsigned int sysino_exists(u32 devhandle, unsigned int devino) ++{ ++ unsigned long sysino = sun4v_devino_to_sysino(devhandle, devino); ++ struct ino_bucket *bucket; ++ unsigned int irq; ++ ++ bucket = &ivector_table[sysino]; ++ irq = bucket_get_irq(__pa(bucket)); ++ ++ return irq; ++} ++ ++void ack_bad_irq(unsigned int irq) ++{ ++ pr_crit("BAD IRQ ack %d\n", irq); ++} ++ ++void irq_install_pre_handler(int irq, ++ void (*func)(unsigned int, void *, void *), ++ void *arg1, void *arg2) ++{ ++ pr_warn("IRQ pre handler NOT supported.\n"); + } +-#endif + + /* + * /proc/interrupts printing: +@@ -206,15 +345,6 @@ static unsigned int sun4u_compute_tid(unsigned long imap, unsigned long cpuid) + return tid; + } + +-struct irq_handler_data { +- unsigned long iclr; +- unsigned long imap; +- +- void (*pre_handler)(unsigned int, void *, void *); +- void *arg1; +- void *arg2; +-}; +- + #ifdef CONFIG_SMP + static int irq_choose_cpu(unsigned int irq, const struct cpumask *affinity) + { +@@ -316,8 +446,8 @@ static void sun4u_irq_eoi(struct irq_data *data) + + static void sun4v_irq_enable(struct irq_data *data) + { +- unsigned int ino = irq_table[data->irq].dev_ino; + unsigned long cpuid = irq_choose_cpu(data->irq, data->affinity); ++ unsigned int ino = irq_data_to_sysino(data); + int err; + + err = sun4v_intr_settarget(ino, cpuid); +@@ -337,8 +467,8 @@ static void sun4v_irq_enable(struct irq_data *data) + static int sun4v_set_affinity(struct irq_data *data, + const struct cpumask *mask, bool force) + { +- unsigned int ino = irq_table[data->irq].dev_ino; + unsigned long cpuid = irq_choose_cpu(data->irq, mask); ++ unsigned int ino = irq_data_to_sysino(data); + int err; + + err = sun4v_intr_settarget(ino, cpuid); +@@ -351,7 +481,7 @@ static int sun4v_set_affinity(struct irq_data *data, + + static void sun4v_irq_disable(struct irq_data *data) + { +- unsigned int ino = irq_table[data->irq].dev_ino; ++ unsigned int ino = irq_data_to_sysino(data); + int err; + + err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); +@@ -362,7 +492,7 @@ static void sun4v_irq_disable(struct irq_data *data) + + static void sun4v_irq_eoi(struct irq_data *data) + { +- unsigned int ino = irq_table[data->irq].dev_ino; ++ unsigned int ino = irq_data_to_sysino(data); + int err; + + err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); +@@ -373,14 +503,13 @@ static void sun4v_irq_eoi(struct irq_data *data) + + static void sun4v_virq_enable(struct irq_data *data) + { +- unsigned long cpuid, dev_handle, dev_ino; ++ unsigned long dev_handle = irq_data_to_handle(data); ++ unsigned long dev_ino = irq_data_to_ino(data); ++ unsigned long cpuid; + int err; + + cpuid = irq_choose_cpu(data->irq, data->affinity); + +- dev_handle = irq_table[data->irq].dev_handle; +- dev_ino = irq_table[data->irq].dev_ino; +- + err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): " +@@ -403,14 +532,13 @@ static void sun4v_virq_enable(struct irq_data *data) + static int sun4v_virt_set_affinity(struct irq_data *data, + const struct cpumask *mask, bool force) + { +- unsigned long cpuid, dev_handle, dev_ino; ++ unsigned long dev_handle = irq_data_to_handle(data); ++ unsigned long dev_ino = irq_data_to_ino(data); ++ unsigned long cpuid; + int err; + + cpuid = irq_choose_cpu(data->irq, mask); + +- dev_handle = irq_table[data->irq].dev_handle; +- dev_ino = irq_table[data->irq].dev_ino; +- + err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): " +@@ -422,11 +550,10 @@ static int sun4v_virt_set_affinity(struct irq_data *data, + + static void sun4v_virq_disable(struct irq_data *data) + { +- unsigned long dev_handle, dev_ino; ++ unsigned long dev_handle = irq_data_to_handle(data); ++ unsigned long dev_ino = irq_data_to_ino(data); + int err; + +- dev_handle = irq_table[data->irq].dev_handle; +- dev_ino = irq_table[data->irq].dev_ino; + + err = sun4v_vintr_set_valid(dev_handle, dev_ino, + HV_INTR_DISABLED); +@@ -438,12 +565,10 @@ static void sun4v_virq_disable(struct irq_data *data) + + static void sun4v_virq_eoi(struct irq_data *data) + { +- unsigned long dev_handle, dev_ino; ++ unsigned long dev_handle = irq_data_to_handle(data); ++ unsigned long dev_ino = irq_data_to_ino(data); + int err; + +- dev_handle = irq_table[data->irq].dev_handle; +- dev_ino = irq_table[data->irq].dev_ino; +- + err = sun4v_vintr_set_state(dev_handle, dev_ino, + HV_INTR_STATE_IDLE); + if (err != HV_EOK) +@@ -479,31 +604,10 @@ static struct irq_chip sun4v_virq = { + .flags = IRQCHIP_EOI_IF_HANDLED, + }; + +-static void pre_flow_handler(struct irq_data *d) +-{ +- struct irq_handler_data *handler_data = irq_data_get_irq_handler_data(d); +- unsigned int ino = irq_table[d->irq].dev_ino; +- +- handler_data->pre_handler(ino, handler_data->arg1, handler_data->arg2); +-} +- +-void irq_install_pre_handler(int irq, +- void (*func)(unsigned int, void *, void *), +- void *arg1, void *arg2) +-{ +- struct irq_handler_data *handler_data = irq_get_handler_data(irq); +- +- handler_data->pre_handler = func; +- handler_data->arg1 = arg1; +- handler_data->arg2 = arg2; +- +- __irq_set_preflow_handler(irq, pre_flow_handler); +-} +- + unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) + { +- struct ino_bucket *bucket; + struct irq_handler_data *handler_data; ++ struct ino_bucket *bucket; + unsigned int irq; + int ino; + +@@ -537,119 +641,166 @@ out: + return irq; + } + +-static unsigned int sun4v_build_common(unsigned long sysino, +- struct irq_chip *chip) ++static unsigned int sun4v_build_common(u32 devhandle, unsigned int devino, ++ void (*handler_data_init)(struct irq_handler_data *data, ++ u32 devhandle, unsigned int devino), ++ struct irq_chip *chip) + { +- struct ino_bucket *bucket; +- struct irq_handler_data *handler_data; ++ struct irq_handler_data *data; + unsigned int irq; + +- BUG_ON(tlb_type != hypervisor); ++ irq = irq_alloc(devhandle, devino); ++ if (!irq) ++ goto out; + +- bucket = &ivector_table[sysino]; +- irq = bucket_get_irq(__pa(bucket)); +- if (!irq) { +- irq = irq_alloc(0, sysino); +- bucket_set_irq(__pa(bucket), irq); +- irq_set_chip_and_handler_name(irq, chip, handle_fasteoi_irq, +- "IVEC"); ++ data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); ++ if (unlikely(!data)) { ++ pr_err("IRQ handler data allocation failed.\n"); ++ irq_free(irq); ++ irq = 0; ++ goto out; + } + +- handler_data = irq_get_handler_data(irq); +- if (unlikely(handler_data)) +- goto out; ++ irq_set_handler_data(irq, data); ++ handler_data_init(data, devhandle, devino); ++ irq_set_chip_and_handler_name(irq, chip, handle_fasteoi_irq, "IVEC"); ++ data->imap = ~0UL; ++ data->iclr = ~0UL; ++out: ++ return irq; ++} + +- handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); +- if (unlikely(!handler_data)) { +- prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); +- prom_halt(); +- } +- irq_set_handler_data(irq, handler_data); ++static unsigned long cookie_assign(unsigned int irq, u32 devhandle, ++ unsigned int devino) ++{ ++ struct irq_handler_data *ihd = irq_get_handler_data(irq); ++ unsigned long hv_error, cookie; + +- /* Catch accidental accesses to these things. IMAP/ICLR handling +- * is done by hypervisor calls on sun4v platforms, not by direct +- * register accesses. ++ /* handler_irq needs to find the irq. cookie is seen signed in ++ * sun4v_dev_mondo and treated as a non ivector_table delivery. + */ +- handler_data->imap = ~0UL; +- handler_data->iclr = ~0UL; ++ ihd->bucket.__irq = irq; ++ cookie = ~__pa(&ihd->bucket); + +-out: +- return irq; ++ hv_error = sun4v_vintr_set_cookie(devhandle, devino, cookie); ++ if (hv_error) ++ pr_err("HV vintr set cookie failed = %ld\n", hv_error); ++ ++ return hv_error; + } + +-unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) ++static void cookie_handler_data(struct irq_handler_data *data, ++ u32 devhandle, unsigned int devino) + { +- unsigned long sysino = sun4v_devino_to_sysino(devhandle, devino); ++ data->dev_handle = devhandle; ++ data->dev_ino = devino; ++} + +- return sun4v_build_common(sysino, &sun4v_irq); ++static unsigned int cookie_build_irq(u32 devhandle, unsigned int devino, ++ struct irq_chip *chip) ++{ ++ unsigned long hv_error; ++ unsigned int irq; ++ ++ irq = sun4v_build_common(devhandle, devino, cookie_handler_data, chip); ++ ++ hv_error = cookie_assign(irq, devhandle, devino); ++ if (hv_error) { ++ irq_free(irq); ++ irq = 0; ++ } ++ ++ return irq; + } + +-unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) ++static unsigned int sun4v_build_cookie(u32 devhandle, unsigned int devino) + { +- struct irq_handler_data *handler_data; +- unsigned long hv_err, cookie; +- struct ino_bucket *bucket; + unsigned int irq; + +- bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC); +- if (unlikely(!bucket)) +- return 0; ++ irq = cookie_exists(devhandle, devino); ++ if (irq) ++ goto out; + +- /* The only reference we store to the IRQ bucket is +- * by physical address which kmemleak can't see, tell +- * it that this object explicitly is not a leak and +- * should be scanned. +- */ +- kmemleak_not_leak(bucket); ++ irq = cookie_build_irq(devhandle, devino, &sun4v_virq); + +- __flush_dcache_range((unsigned long) bucket, +- ((unsigned long) bucket + +- sizeof(struct ino_bucket))); ++out: ++ return irq; ++} + +- irq = irq_alloc(devhandle, devino); ++static void sysino_set_bucket(unsigned int irq) ++{ ++ struct irq_handler_data *ihd = irq_get_handler_data(irq); ++ struct ino_bucket *bucket; ++ unsigned long sysino; ++ ++ sysino = sun4v_devino_to_sysino(ihd->dev_handle, ihd->dev_ino); ++ BUG_ON(sysino >= nr_ivec); ++ bucket = &ivector_table[sysino]; + bucket_set_irq(__pa(bucket), irq); ++} + +- irq_set_chip_and_handler_name(irq, &sun4v_virq, handle_fasteoi_irq, +- "IVEC"); ++static void sysino_handler_data(struct irq_handler_data *data, ++ u32 devhandle, unsigned int devino) ++{ ++ unsigned long sysino; + +- handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); +- if (unlikely(!handler_data)) +- return 0; ++ sysino = sun4v_devino_to_sysino(devhandle, devino); ++ data->sysino = sysino; ++} + +- /* In order to make the LDC channel startup sequence easier, +- * especially wrt. locking, we do not let request_irq() enable +- * the interrupt. +- */ +- irq_set_status_flags(irq, IRQ_NOAUTOEN); +- irq_set_handler_data(irq, handler_data); ++static unsigned int sysino_build_irq(u32 devhandle, unsigned int devino, ++ struct irq_chip *chip) ++{ ++ unsigned int irq; + +- /* Catch accidental accesses to these things. IMAP/ICLR handling +- * is done by hypervisor calls on sun4v platforms, not by direct +- * register accesses. +- */ +- handler_data->imap = ~0UL; +- handler_data->iclr = ~0UL; ++ irq = sun4v_build_common(devhandle, devino, sysino_handler_data, chip); ++ if (!irq) ++ goto out; + +- cookie = ~__pa(bucket); +- hv_err = sun4v_vintr_set_cookie(devhandle, devino, cookie); +- if (hv_err) { +- prom_printf("IRQ: Fatal, cannot set cookie for [%x:%x] " +- "err=%lu\n", devhandle, devino, hv_err); +- prom_halt(); +- } ++ sysino_set_bucket(irq); ++out: ++ return irq; ++} + ++static int sun4v_build_sysino(u32 devhandle, unsigned int devino) ++{ ++ int irq; ++ ++ irq = sysino_exists(devhandle, devino); ++ if (irq) ++ goto out; ++ ++ irq = sysino_build_irq(devhandle, devino, &sun4v_irq); ++out: + return irq; + } + +-void ack_bad_irq(unsigned int irq) ++unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) + { +- unsigned int ino = irq_table[irq].dev_ino; ++ unsigned int irq; + +- if (!ino) +- ino = 0xdeadbeef; ++ if (sun4v_cookie_only_virqs()) ++ irq = sun4v_build_cookie(devhandle, devino); ++ else ++ irq = sun4v_build_sysino(devhandle, devino); + +- printk(KERN_CRIT "Unexpected IRQ from ino[%x] irq[%u]\n", +- ino, irq); ++ return irq; ++} ++ ++unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) ++{ ++ int irq; ++ ++ irq = cookie_build_irq(devhandle, devino, &sun4v_virq); ++ if (!irq) ++ goto out; ++ ++ /* This is borrowed from the original function. ++ */ ++ irq_set_status_flags(irq, IRQ_NOAUTOEN); ++ ++out: ++ return irq; + } + + void *hardirq_stack[NR_CPUS]; +@@ -720,9 +871,12 @@ void fixup_irqs(void) + + for (irq = 0; irq < NR_IRQS; irq++) { + struct irq_desc *desc = irq_to_desc(irq); +- struct irq_data *data = irq_desc_get_irq_data(desc); ++ struct irq_data *data; + unsigned long flags; + ++ if (!desc) ++ continue; ++ data = irq_desc_get_irq_data(desc); + raw_spin_lock_irqsave(&desc->lock, flags); + if (desc->action && !irqd_is_per_cpu(data)) { + if (data->chip->irq_set_affinity) +@@ -922,16 +1076,22 @@ static struct irqaction timer_irq_action = { + .name = "timer", + }; + +-/* Only invoked on boot processor. */ +-void __init init_IRQ(void) ++static void __init irq_ivector_init(void) + { +- unsigned long size; ++ unsigned long size, order; ++ unsigned int ivecs; + +- map_prom_timers(); +- kill_prom_timer(); ++ /* If we are doing cookie only VIRQs then we do not need the ivector ++ * table to process interrupts. ++ */ ++ if (sun4v_cookie_only_virqs()) ++ return; + +- size = sizeof(struct ino_bucket) * NUM_IVECS; +- ivector_table = kzalloc(size, GFP_KERNEL); ++ ivecs = size_nr_ivec(); ++ size = sizeof(struct ino_bucket) * ivecs; ++ order = get_order(size); ++ ivector_table = (struct ino_bucket *) ++ __get_free_pages(GFP_KERNEL | __GFP_ZERO, order); + if (!ivector_table) { + prom_printf("Fatal error, cannot allocate ivector_table\n"); + prom_halt(); +@@ -940,6 +1100,15 @@ void __init init_IRQ(void) + ((unsigned long) ivector_table) + size); + + ivector_table_pa = __pa(ivector_table); ++} ++ ++/* Only invoked on boot processor.*/ ++void __init init_IRQ(void) ++{ ++ irq_init_hv(); ++ irq_ivector_init(); ++ map_prom_timers(); ++ kill_prom_timer(); + + if (tlb_type == hypervisor) + sun4v_init_mondo_queues(); +diff --git a/arch/sparc/kernel/ktlb.S b/arch/sparc/kernel/ktlb.S +index 542e96a..ef0d8e9 100644 +--- a/arch/sparc/kernel/ktlb.S ++++ b/arch/sparc/kernel/ktlb.S +@@ -47,14 +47,6 @@ kvmap_itlb_vmalloc_addr: + KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_itlb_longpath) + + TSB_LOCK_TAG(%g1, %g2, %g7) +- +- /* Load and check PTE. */ +- ldxa [%g5] ASI_PHYS_USE_EC, %g5 +- mov 1, %g7 +- sllx %g7, TSB_TAG_INVALID_BIT, %g7 +- brgez,a,pn %g5, kvmap_itlb_longpath +- TSB_STORE(%g1, %g7) +- + TSB_WRITE(%g1, %g5, %g6) + + /* fallthrough to TLB load */ +@@ -118,6 +110,12 @@ kvmap_dtlb_obp: + ba,pt %xcc, kvmap_dtlb_load + nop + ++kvmap_linear_early: ++ sethi %hi(kern_linear_pte_xor), %g7 ++ ldx [%g7 + %lo(kern_linear_pte_xor)], %g2 ++ ba,pt %xcc, kvmap_dtlb_tsb4m_load ++ xor %g2, %g4, %g5 ++ + .align 32 + kvmap_dtlb_tsb4m_load: + TSB_LOCK_TAG(%g1, %g2, %g7) +@@ -146,105 +144,17 @@ kvmap_dtlb_4v: + /* Correct TAG_TARGET is already in %g6, check 4mb TSB. */ + KERN_TSB4M_LOOKUP_TL1(%g6, %g5, %g1, %g2, %g3, kvmap_dtlb_load) + #endif +- /* TSB entry address left in %g1, lookup linear PTE. +- * Must preserve %g1 and %g6 (TAG). +- */ +-kvmap_dtlb_tsb4m_miss: +- /* Clear the PAGE_OFFSET top virtual bits, shift +- * down to get PFN, and make sure PFN is in range. +- */ +-661: sllx %g4, 0, %g5 +- .section .page_offset_shift_patch, "ax" +- .word 661b +- .previous +- +- /* Check to see if we know about valid memory at the 4MB +- * chunk this physical address will reside within. ++ /* Linear mapping TSB lookup failed. Fallthrough to kernel ++ * page table based lookup. + */ +-661: srlx %g5, MAX_PHYS_ADDRESS_BITS, %g2 +- .section .page_offset_shift_patch, "ax" +- .word 661b +- .previous +- +- brnz,pn %g2, kvmap_dtlb_longpath +- nop +- +- /* This unconditional branch and delay-slot nop gets patched +- * by the sethi sequence once the bitmap is properly setup. +- */ +- .globl valid_addr_bitmap_insn +-valid_addr_bitmap_insn: +- ba,pt %xcc, 2f +- nop +- .subsection 2 +- .globl valid_addr_bitmap_patch +-valid_addr_bitmap_patch: +- sethi %hi(sparc64_valid_addr_bitmap), %g7 +- or %g7, %lo(sparc64_valid_addr_bitmap), %g7 +- .previous +- +-661: srlx %g5, ILOG2_4MB, %g2 +- .section .page_offset_shift_patch, "ax" +- .word 661b +- .previous +- +- srlx %g2, 6, %g5 +- and %g2, 63, %g2 +- sllx %g5, 3, %g5 +- ldx [%g7 + %g5], %g5 +- mov 1, %g7 +- sllx %g7, %g2, %g7 +- andcc %g5, %g7, %g0 +- be,pn %xcc, kvmap_dtlb_longpath +- +-2: sethi %hi(kpte_linear_bitmap), %g2 +- +- /* Get the 256MB physical address index. */ +-661: sllx %g4, 0, %g5 +- .section .page_offset_shift_patch, "ax" +- .word 661b +- .previous +- +- or %g2, %lo(kpte_linear_bitmap), %g2 +- +-661: srlx %g5, ILOG2_256MB, %g5 +- .section .page_offset_shift_patch, "ax" +- .word 661b +- .previous +- +- and %g5, (32 - 1), %g7 +- +- /* Divide by 32 to get the offset into the bitmask. */ +- srlx %g5, 5, %g5 +- add %g7, %g7, %g7 +- sllx %g5, 3, %g5 +- +- /* kern_linear_pte_xor[(mask >> shift) & 3)] */ +- ldx [%g2 + %g5], %g2 +- srlx %g2, %g7, %g7 +- sethi %hi(kern_linear_pte_xor), %g5 +- and %g7, 3, %g7 +- or %g5, %lo(kern_linear_pte_xor), %g5 +- sllx %g7, 3, %g7 +- ldx [%g5 + %g7], %g2 +- + .globl kvmap_linear_patch + kvmap_linear_patch: +- ba,pt %xcc, kvmap_dtlb_tsb4m_load +- xor %g2, %g4, %g5 ++ ba,a,pt %xcc, kvmap_linear_early + + kvmap_dtlb_vmalloc_addr: + KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_dtlb_longpath) + + TSB_LOCK_TAG(%g1, %g2, %g7) +- +- /* Load and check PTE. */ +- ldxa [%g5] ASI_PHYS_USE_EC, %g5 +- mov 1, %g7 +- sllx %g7, TSB_TAG_INVALID_BIT, %g7 +- brgez,a,pn %g5, kvmap_dtlb_longpath +- TSB_STORE(%g1, %g7) +- + TSB_WRITE(%g1, %g5, %g6) + + /* fallthrough to TLB load */ +@@ -276,13 +186,8 @@ kvmap_dtlb_load: + + #ifdef CONFIG_SPARSEMEM_VMEMMAP + kvmap_vmemmap: +- sub %g4, %g5, %g5 +- srlx %g5, 22, %g5 +- sethi %hi(vmemmap_table), %g1 +- sllx %g5, 3, %g5 +- or %g1, %lo(vmemmap_table), %g1 +- ba,pt %xcc, kvmap_dtlb_load +- ldx [%g1 + %g5], %g5 ++ KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_dtlb_longpath) ++ ba,a,pt %xcc, kvmap_dtlb_load + #endif + + kvmap_dtlb_nonlinear: +@@ -294,8 +199,8 @@ kvmap_dtlb_nonlinear: + + #ifdef CONFIG_SPARSEMEM_VMEMMAP + /* Do not use the TSB for vmemmap. */ +- mov (VMEMMAP_BASE >> 40), %g5 +- sllx %g5, 40, %g5 ++ sethi %hi(VMEMMAP_BASE), %g5 ++ ldx [%g5 + %lo(VMEMMAP_BASE)], %g5 + cmp %g4,%g5 + bgeu,pn %xcc, kvmap_vmemmap + nop +@@ -307,8 +212,8 @@ kvmap_dtlb_tsbmiss: + sethi %hi(MODULES_VADDR), %g5 + cmp %g4, %g5 + blu,pn %xcc, kvmap_dtlb_longpath +- mov (VMALLOC_END >> 40), %g5 +- sllx %g5, 40, %g5 ++ sethi %hi(VMALLOC_END), %g5 ++ ldx [%g5 + %lo(VMALLOC_END)], %g5 + cmp %g4, %g5 + bgeu,pn %xcc, kvmap_dtlb_longpath + nop +diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c +index e01d75d..7ef2862 100644 +--- a/arch/sparc/kernel/ldc.c ++++ b/arch/sparc/kernel/ldc.c +@@ -1078,7 +1078,8 @@ static void ldc_iommu_release(struct ldc_channel *lp) + + struct ldc_channel *ldc_alloc(unsigned long id, + const struct ldc_channel_config *cfgp, +- void *event_arg) ++ void *event_arg, ++ const char *name) + { + struct ldc_channel *lp; + const struct ldc_mode_ops *mops; +@@ -1093,6 +1094,8 @@ struct ldc_channel *ldc_alloc(unsigned long id, + err = -EINVAL; + if (!cfgp) + goto out_err; ++ if (!name) ++ goto out_err; + + switch (cfgp->mode) { + case LDC_MODE_RAW: +@@ -1185,6 +1188,21 @@ struct ldc_channel *ldc_alloc(unsigned long id, + + INIT_HLIST_HEAD(&lp->mh_list); + ++ snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name); ++ snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name); ++ ++ err = request_irq(lp->cfg.rx_irq, ldc_rx, 0, ++ lp->rx_irq_name, lp); ++ if (err) ++ goto out_free_txq; ++ ++ err = request_irq(lp->cfg.tx_irq, ldc_tx, 0, ++ lp->tx_irq_name, lp); ++ if (err) { ++ free_irq(lp->cfg.rx_irq, lp); ++ goto out_free_txq; ++ } ++ + return lp; + + out_free_txq: +@@ -1237,31 +1255,14 @@ EXPORT_SYMBOL(ldc_free); + * state. This does not initiate a handshake, ldc_connect() does + * that. + */ +-int ldc_bind(struct ldc_channel *lp, const char *name) ++int ldc_bind(struct ldc_channel *lp) + { + unsigned long hv_err, flags; + int err = -EINVAL; + +- if (!name || +- (lp->state != LDC_STATE_INIT)) ++ if (lp->state != LDC_STATE_INIT) + return -EINVAL; + +- snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name); +- snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name); +- +- err = request_irq(lp->cfg.rx_irq, ldc_rx, 0, +- lp->rx_irq_name, lp); +- if (err) +- return err; +- +- err = request_irq(lp->cfg.tx_irq, ldc_tx, 0, +- lp->tx_irq_name, lp); +- if (err) { +- free_irq(lp->cfg.rx_irq, lp); +- return err; +- } +- +- + spin_lock_irqsave(&lp->lock, flags); + + enable_irq(lp->cfg.rx_irq); +@@ -1336,7 +1337,7 @@ int ldc_connect(struct ldc_channel *lp) + if (!(lp->flags & LDC_FLAG_ALLOCED_QUEUES) || + !(lp->flags & LDC_FLAG_REGISTERED_QUEUES) || + lp->hs_state != LDC_HS_OPEN) +- err = -EINVAL; ++ err = ((lp->hs_state > LDC_HS_OPEN) ? 0 : -EINVAL); + else + err = start_handshake(lp); + +@@ -2306,7 +2307,7 @@ void *ldc_alloc_exp_dring(struct ldc_channel *lp, unsigned int len, + if (len & (8UL - 1)) + return ERR_PTR(-EINVAL); + +- buf = kzalloc(len, GFP_KERNEL); ++ buf = kzalloc(len, GFP_ATOMIC); + if (!buf) + return ERR_PTR(-ENOMEM); + +diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c +index 6479256..fce8ab1 100644 +--- a/arch/sparc/kernel/nmi.c ++++ b/arch/sparc/kernel/nmi.c +@@ -141,7 +141,6 @@ static inline unsigned int get_nmi_count(int cpu) + + static __init void nmi_cpu_busy(void *data) + { +- local_irq_enable_in_hardirq(); + while (endflag == 0) + mb(); + } +diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c +index 8f76f23..f9c6813 100644 +--- a/arch/sparc/kernel/pci_schizo.c ++++ b/arch/sparc/kernel/pci_schizo.c +@@ -581,7 +581,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) + { + unsigned long csr_reg, csr, csr_error_bits; + irqreturn_t ret = IRQ_NONE; +- u16 stat; ++ u32 stat; + + csr_reg = pbm->pbm_regs + SCHIZO_PCI_CTRL; + csr = upa_readq(csr_reg); +@@ -617,7 +617,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) + pbm->name); + ret = IRQ_HANDLED; + } +- pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat); ++ pbm->pci_ops->read(pbm->pci_bus, 0, PCI_STATUS, 2, &stat); + if (stat & (PCI_STATUS_PARITY | + PCI_STATUS_SIG_TARGET_ABORT | + PCI_STATUS_REC_TARGET_ABORT | +@@ -625,7 +625,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) + PCI_STATUS_SIG_SYSTEM_ERROR)) { + printk("%s: PCI bus error, PCI_STATUS[%04x]\n", + pbm->name, stat); +- pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff); ++ pbm->pci_ops->write(pbm->pci_bus, 0, PCI_STATUS, 2, 0xffff); + ret = IRQ_HANDLED; + } + return ret; +diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c +index 269af58..7e967c8 100644 +--- a/arch/sparc/kernel/pcr.c ++++ b/arch/sparc/kernel/pcr.c +@@ -191,12 +191,41 @@ static const struct pcr_ops n4_pcr_ops = { + .pcr_nmi_disable = PCR_N4_PICNPT, + }; + ++static u64 n5_pcr_read(unsigned long reg_num) ++{ ++ unsigned long val; ++ ++ (void) sun4v_t5_get_perfreg(reg_num, &val); ++ ++ return val; ++} ++ ++static void n5_pcr_write(unsigned long reg_num, u64 val) ++{ ++ (void) sun4v_t5_set_perfreg(reg_num, val); ++} ++ ++static const struct pcr_ops n5_pcr_ops = { ++ .read_pcr = n5_pcr_read, ++ .write_pcr = n5_pcr_write, ++ .read_pic = n4_pic_read, ++ .write_pic = n4_pic_write, ++ .nmi_picl_value = n4_picl_value, ++ .pcr_nmi_enable = (PCR_N4_PICNPT | PCR_N4_STRACE | ++ PCR_N4_UTRACE | PCR_N4_TOE | ++ (26 << PCR_N4_SL_SHIFT)), ++ .pcr_nmi_disable = PCR_N4_PICNPT, ++}; ++ ++ + static unsigned long perf_hsvc_group; + static unsigned long perf_hsvc_major; + static unsigned long perf_hsvc_minor; + + static int __init register_perf_hsvc(void) + { ++ unsigned long hverror; ++ + if (tlb_type == hypervisor) { + switch (sun4v_chip_type) { + case SUN4V_CHIP_NIAGARA1: +@@ -215,6 +244,10 @@ static int __init register_perf_hsvc(void) + perf_hsvc_group = HV_GRP_VT_CPU; + break; + ++ case SUN4V_CHIP_NIAGARA5: ++ perf_hsvc_group = HV_GRP_T5_CPU; ++ break; ++ + default: + return -ENODEV; + } +@@ -222,10 +255,12 @@ static int __init register_perf_hsvc(void) + + perf_hsvc_major = 1; + perf_hsvc_minor = 0; +- if (sun4v_hvapi_register(perf_hsvc_group, +- perf_hsvc_major, +- &perf_hsvc_minor)) { +- printk("perfmon: Could not register hvapi.\n"); ++ hverror = sun4v_hvapi_register(perf_hsvc_group, ++ perf_hsvc_major, ++ &perf_hsvc_minor); ++ if (hverror) { ++ pr_err("perfmon: Could not register hvapi(0x%lx).\n", ++ hverror); + return -ENODEV; + } + } +@@ -254,6 +289,10 @@ static int __init setup_sun4v_pcr_ops(void) + pcr_ops = &n4_pcr_ops; + break; + ++ case SUN4V_CHIP_NIAGARA5: ++ pcr_ops = &n5_pcr_ops; ++ break; ++ + default: + ret = -ENODEV; + break; +diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c +index b5c38fa..3ccb677 100644 +--- a/arch/sparc/kernel/perf_event.c ++++ b/arch/sparc/kernel/perf_event.c +@@ -960,6 +960,8 @@ out: + cpuc->pcr[0] |= cpuc->event[0]->hw.config_base; + } + ++static void sparc_pmu_start(struct perf_event *event, int flags); ++ + /* On this PMU each PIC has it's own PCR control register. */ + static void calculate_multiple_pcrs(struct cpu_hw_events *cpuc) + { +@@ -972,20 +974,13 @@ static void calculate_multiple_pcrs(struct cpu_hw_events *cpuc) + struct perf_event *cp = cpuc->event[i]; + struct hw_perf_event *hwc = &cp->hw; + int idx = hwc->idx; +- u64 enc; + + if (cpuc->current_idx[i] != PIC_NO_INDEX) + continue; + +- sparc_perf_event_set_period(cp, hwc, idx); + cpuc->current_idx[i] = idx; + +- enc = perf_event_get_enc(cpuc->events[i]); +- cpuc->pcr[idx] &= ~mask_for_index(idx); +- if (hwc->state & PERF_HES_STOPPED) +- cpuc->pcr[idx] |= nop_for_index(idx); +- else +- cpuc->pcr[idx] |= event_encoding(enc, idx); ++ sparc_pmu_start(cp, PERF_EF_RELOAD); + } + out: + for (i = 0; i < cpuc->n_events; i++) { +@@ -1101,7 +1096,6 @@ static void sparc_pmu_del(struct perf_event *event, int _flags) + int i; + + local_irq_save(flags); +- perf_pmu_disable(event->pmu); + + for (i = 0; i < cpuc->n_events; i++) { + if (event == cpuc->event[i]) { +@@ -1127,7 +1121,6 @@ static void sparc_pmu_del(struct perf_event *event, int _flags) + } + } + +- perf_pmu_enable(event->pmu); + local_irq_restore(flags); + } + +@@ -1361,7 +1354,6 @@ static int sparc_pmu_add(struct perf_event *event, int ef_flags) + unsigned long flags; + + local_irq_save(flags); +- perf_pmu_disable(event->pmu); + + n0 = cpuc->n_events; + if (n0 >= sparc_pmu->max_hw_events) +@@ -1394,7 +1386,6 @@ nocheck: + + ret = 0; + out: +- perf_pmu_enable(event->pmu); + local_irq_restore(flags); + return ret; + } +@@ -1662,7 +1653,8 @@ static bool __init supported_pmu(void) + sparc_pmu = &niagara2_pmu; + return true; + } +- if (!strcmp(sparc_pmu_type, "niagara4")) { ++ if (!strcmp(sparc_pmu_type, "niagara4") || ++ !strcmp(sparc_pmu_type, "niagara5")) { + sparc_pmu = &niagara4_pmu; + return true; + } +@@ -1671,9 +1663,12 @@ static bool __init supported_pmu(void) + + int __init init_hw_perf_events(void) + { ++ int err; ++ + pr_info("Performance events: "); + +- if (!supported_pmu()) { ++ err = pcr_arch_init(); ++ if (err || !supported_pmu()) { + pr_cont("No support for PMU type '%s'\n", sparc_pmu_type); + return 0; + } +@@ -1685,7 +1680,7 @@ int __init init_hw_perf_events(void) + + return 0; + } +-early_initcall(init_hw_perf_events); ++pure_initcall(init_hw_perf_events); + + void perf_callchain_kernel(struct perf_callchain_entry *entry, + struct pt_regs *regs) +diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c +index d7b4967..1a79d68 100644 +--- a/arch/sparc/kernel/process_64.c ++++ b/arch/sparc/kernel/process_64.c +@@ -281,6 +281,8 @@ void arch_trigger_all_cpu_backtrace(void) + printk(" TPC[%lx] O7[%lx] I7[%lx] RPC[%lx]\n", + gp->tpc, gp->o7, gp->i7, gp->rpc); + } ++ ++ touch_nmi_watchdog(); + } + + memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot)); +@@ -306,6 +308,9 @@ static void __global_pmu_self(int this_cpu) + struct global_pmu_snapshot *pp; + int i, num; + ++ if (!pcr_ops) ++ return; ++ + pp = &global_cpu_snapshot[this_cpu].pmu; + + num = 1; +@@ -353,6 +358,8 @@ static void pmu_snapshot_all_cpus(void) + (cpu == this_cpu ? '*' : ' '), cpu, + pp->pcr[0], pp->pcr[1], pp->pcr[2], pp->pcr[3], + pp->pic[0], pp->pic[1], pp->pic[2], pp->pic[3]); ++ ++ touch_nmi_watchdog(); + } + + memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot)); +diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c +index 3fdb455..61a5198 100644 +--- a/arch/sparc/kernel/setup_64.c ++++ b/arch/sparc/kernel/setup_64.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -174,7 +175,7 @@ char reboot_command[COMMAND_LINE_SIZE]; + + static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 }; + +-void __init per_cpu_patch(void) ++static void __init per_cpu_patch(void) + { + struct cpuid_patch_entry *p; + unsigned long ver; +@@ -266,7 +267,7 @@ void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start, + } + } + +-void __init sun4v_patch(void) ++static void __init sun4v_patch(void) + { + extern void sun4v_hvapi_init(void); + +@@ -335,14 +336,25 @@ static void __init pause_patch(void) + } + } + +-#ifdef CONFIG_SMP +-void __init boot_cpu_id_too_large(int cpu) ++void __init start_early_boot(void) + { +- prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n", +- cpu, NR_CPUS); +- prom_halt(); ++ int cpu; ++ ++ check_if_starfire(); ++ per_cpu_patch(); ++ sun4v_patch(); ++ ++ cpu = hard_smp_processor_id(); ++ if (cpu >= NR_CPUS) { ++ prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n", ++ cpu, NR_CPUS); ++ prom_halt(); ++ } ++ current_thread_info()->cpu = cpu; ++ ++ prom_init_report(); ++ start_kernel(); + } +-#endif + + /* On Ultra, we support all of the v8 capabilities. */ + unsigned long sparc64_elf_hwcap = (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | +@@ -500,12 +512,16 @@ static void __init init_sparc64_elf_hwcap(void) + sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA5 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M6 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M7 || + sun4v_chip_type == SUN4V_CHIP_SPARC64X) + cap |= HWCAP_SPARC_BLKINIT; + if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA5 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M6 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M7 || + sun4v_chip_type == SUN4V_CHIP_SPARC64X) + cap |= HWCAP_SPARC_N2; + } +@@ -533,6 +549,8 @@ static void __init init_sparc64_elf_hwcap(void) + sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA5 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M6 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M7 || + sun4v_chip_type == SUN4V_CHIP_SPARC64X) + cap |= (AV_SPARC_VIS | AV_SPARC_VIS2 | + AV_SPARC_ASI_BLK_INIT | +@@ -540,6 +558,8 @@ static void __init init_sparc64_elf_hwcap(void) + if (sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || + sun4v_chip_type == SUN4V_CHIP_NIAGARA5 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M6 || ++ sun4v_chip_type == SUN4V_CHIP_SPARC_M7 || + sun4v_chip_type == SUN4V_CHIP_SPARC64X) + cap |= (AV_SPARC_VIS3 | AV_SPARC_HPC | + AV_SPARC_FMAF); +diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c +index b085311..9af0a5d 100644 +--- a/arch/sparc/kernel/smp_64.c ++++ b/arch/sparc/kernel/smp_64.c +@@ -151,7 +151,7 @@ void cpu_panic(void) + #define NUM_ROUNDS 64 /* magic value */ + #define NUM_ITERS 5 /* likewise */ + +-static DEFINE_SPINLOCK(itc_sync_lock); ++static DEFINE_RAW_SPINLOCK(itc_sync_lock); + static unsigned long go[SLAVE + 1]; + + #define DEBUG_TICK_SYNC 0 +@@ -259,7 +259,7 @@ static void smp_synchronize_one_tick(int cpu) + go[MASTER] = 0; + membar_safe("#StoreLoad"); + +- spin_lock_irqsave(&itc_sync_lock, flags); ++ raw_spin_lock_irqsave(&itc_sync_lock, flags); + { + for (i = 0; i < NUM_ROUNDS*NUM_ITERS; i++) { + while (!go[MASTER]) +@@ -270,7 +270,7 @@ static void smp_synchronize_one_tick(int cpu) + membar_safe("#StoreLoad"); + } + } +- spin_unlock_irqrestore(&itc_sync_lock, flags); ++ raw_spin_unlock_irqrestore(&itc_sync_lock, flags); + } + + #if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU) +@@ -823,13 +823,17 @@ void arch_send_call_function_single_ipi(int cpu) + void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs) + { + clear_softint(1 << irq); ++ irq_enter(); + generic_smp_call_function_interrupt(); ++ irq_exit(); + } + + void __irq_entry smp_call_function_single_client(int irq, struct pt_regs *regs) + { + clear_softint(1 << irq); ++ irq_enter(); + generic_smp_call_function_single_interrupt(); ++ irq_exit(); + } + + static void tsb_sync(void *info) +@@ -1395,7 +1399,6 @@ void __cpu_die(unsigned int cpu) + + void __init smp_cpus_done(unsigned int max_cpus) + { +- pcr_arch_init(); + } + + void smp_send_reschedule(int cpu) +@@ -1480,6 +1483,13 @@ static void __init pcpu_populate_pte(unsigned long addr) + pud_t *pud; + pmd_t *pmd; + ++ if (pgd_none(*pgd)) { ++ pud_t *new; ++ ++ new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); ++ pgd_populate(&init_mm, pgd, new); ++ } ++ + pud = pud_offset(pgd, addr); + if (pud_none(*pud)) { + pmd_t *new; +diff --git a/arch/sparc/kernel/sun4v_tlb_miss.S b/arch/sparc/kernel/sun4v_tlb_miss.S +index e0c09bf8..6179e19 100644 +--- a/arch/sparc/kernel/sun4v_tlb_miss.S ++++ b/arch/sparc/kernel/sun4v_tlb_miss.S +@@ -195,6 +195,11 @@ sun4v_tsb_miss_common: + ldx [%g2 + TRAP_PER_CPU_PGD_PADDR], %g7 + + sun4v_itlb_error: ++ rdpr %tl, %g1 ++ cmp %g1, 1 ++ ble,pt %icc, sun4v_bad_ra ++ or %g0, FAULT_CODE_BAD_RA | FAULT_CODE_ITLB, %g1 ++ + sethi %hi(sun4v_err_itlb_vaddr), %g1 + stx %g4, [%g1 + %lo(sun4v_err_itlb_vaddr)] + sethi %hi(sun4v_err_itlb_ctx), %g1 +@@ -206,15 +211,10 @@ sun4v_itlb_error: + sethi %hi(sun4v_err_itlb_error), %g1 + stx %o0, [%g1 + %lo(sun4v_err_itlb_error)] + ++ sethi %hi(1f), %g7 + rdpr %tl, %g4 +- cmp %g4, 1 +- ble,pt %icc, 1f +- sethi %hi(2f), %g7 + ba,pt %xcc, etraptl1 +- or %g7, %lo(2f), %g7 +- +-1: ba,pt %xcc, etrap +-2: or %g7, %lo(2b), %g7 ++1: or %g7, %lo(1f), %g7 + mov %l4, %o1 + call sun4v_itlb_error_report + add %sp, PTREGS_OFF, %o0 +@@ -222,6 +222,11 @@ sun4v_itlb_error: + /* NOTREACHED */ + + sun4v_dtlb_error: ++ rdpr %tl, %g1 ++ cmp %g1, 1 ++ ble,pt %icc, sun4v_bad_ra ++ or %g0, FAULT_CODE_BAD_RA | FAULT_CODE_DTLB, %g1 ++ + sethi %hi(sun4v_err_dtlb_vaddr), %g1 + stx %g4, [%g1 + %lo(sun4v_err_dtlb_vaddr)] + sethi %hi(sun4v_err_dtlb_ctx), %g1 +@@ -233,21 +238,23 @@ sun4v_dtlb_error: + sethi %hi(sun4v_err_dtlb_error), %g1 + stx %o0, [%g1 + %lo(sun4v_err_dtlb_error)] + ++ sethi %hi(1f), %g7 + rdpr %tl, %g4 +- cmp %g4, 1 +- ble,pt %icc, 1f +- sethi %hi(2f), %g7 + ba,pt %xcc, etraptl1 +- or %g7, %lo(2f), %g7 +- +-1: ba,pt %xcc, etrap +-2: or %g7, %lo(2b), %g7 ++1: or %g7, %lo(1f), %g7 + mov %l4, %o1 + call sun4v_dtlb_error_report + add %sp, PTREGS_OFF, %o0 + + /* NOTREACHED */ + ++sun4v_bad_ra: ++ or %g0, %g4, %g5 ++ ba,pt %xcc, sparc64_realfault_common ++ or %g1, %g0, %g4 ++ ++ /* NOTREACHED */ ++ + /* Instruction Access Exception, tl0. */ + sun4v_iacc: + ldxa [%g0] ASI_SCRATCHPAD, %g2 +diff --git a/arch/sparc/kernel/sys32.S b/arch/sparc/kernel/sys32.S +index f7c72b6..d066eb1 100644 +--- a/arch/sparc/kernel/sys32.S ++++ b/arch/sparc/kernel/sys32.S +@@ -44,7 +44,7 @@ SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1) + SIGN1(sys32_io_submit, compat_sys_io_submit, %o1) + SIGN1(sys32_mq_open, compat_sys_mq_open, %o1) + SIGN1(sys32_select, compat_sys_select, %o0) +-SIGN3(sys32_futex, compat_sys_futex, %o1, %o2, %o5) ++SIGN1(sys32_futex, compat_sys_futex, %o1) + SIGN1(sys32_recvfrom, compat_sys_recvfrom, %o0) + SIGN1(sys32_recvmsg, compat_sys_recvmsg, %o0) + SIGN1(sys32_sendmsg, compat_sys_sendmsg, %o0) +diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c +index beb0b5a..25db14a 100644 +--- a/arch/sparc/kernel/sys_sparc_64.c ++++ b/arch/sparc/kernel/sys_sparc_64.c +@@ -332,7 +332,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second + long err; + + /* No need for backward compatibility. We can start fresh... */ +- if (call <= SEMCTL) { ++ if (call <= SEMTIMEDOP) { + switch (call) { + case SEMOP: + err = sys_semtimedop(first, ptr, +diff --git a/arch/sparc/kernel/trampoline_64.S b/arch/sparc/kernel/trampoline_64.S +index 737f8cb..88ede1d 100644 +--- a/arch/sparc/kernel/trampoline_64.S ++++ b/arch/sparc/kernel/trampoline_64.S +@@ -109,10 +109,13 @@ startup_continue: + brnz,pn %g1, 1b + nop + +- sethi %hi(p1275buf), %g2 +- or %g2, %lo(p1275buf), %g2 +- ldx [%g2 + 0x10], %l2 +- add %l2, -(192 + 128), %sp ++ /* Get onto temporary stack which will be in the locked ++ * kernel image. ++ */ ++ sethi %hi(tramp_stack), %g1 ++ or %g1, %lo(tramp_stack), %g1 ++ add %g1, TRAMP_STACK_SIZE, %g1 ++ sub %g1, STACKFRAME_SZ + STACK_BIAS + 256, %sp + flushw + + /* Setup the loop variables: +@@ -394,7 +397,6 @@ after_lock_tlb: + sllx %g5, THREAD_SHIFT, %g5 + sub %g5, (STACKFRAME_SZ + STACK_BIAS), %g5 + add %g6, %g5, %sp +- mov 0, %fp + + rdpr %pstate, %o1 + or %o1, PSTATE_IE, %o1 +diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c +index 4ced92f..25d0c7e 100644 +--- a/arch/sparc/kernel/traps_64.c ++++ b/arch/sparc/kernel/traps_64.c +@@ -2102,6 +2102,11 @@ void sun4v_nonresum_overflow(struct pt_regs *regs) + atomic_inc(&sun4v_nonresum_oflow_cnt); + } + ++static void sun4v_tlb_error(struct pt_regs *regs) ++{ ++ die_if_kernel("TLB/TSB error", regs); ++} ++ + unsigned long sun4v_err_itlb_vaddr; + unsigned long sun4v_err_itlb_ctx; + unsigned long sun4v_err_itlb_pte; +@@ -2109,8 +2114,7 @@ unsigned long sun4v_err_itlb_error; + + void sun4v_itlb_error_report(struct pt_regs *regs, int tl) + { +- if (tl > 1) +- dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); ++ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); + + printk(KERN_EMERG "SUN4V-ITLB: Error at TPC[%lx], tl %d\n", + regs->tpc, tl); +@@ -2123,7 +2127,7 @@ void sun4v_itlb_error_report(struct pt_regs *regs, int tl) + sun4v_err_itlb_vaddr, sun4v_err_itlb_ctx, + sun4v_err_itlb_pte, sun4v_err_itlb_error); + +- prom_halt(); ++ sun4v_tlb_error(regs); + } + + unsigned long sun4v_err_dtlb_vaddr; +@@ -2133,8 +2137,7 @@ unsigned long sun4v_err_dtlb_error; + + void sun4v_dtlb_error_report(struct pt_regs *regs, int tl) + { +- if (tl > 1) +- dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); ++ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); + + printk(KERN_EMERG "SUN4V-DTLB: Error at TPC[%lx], tl %d\n", + regs->tpc, tl); +@@ -2147,7 +2150,7 @@ void sun4v_dtlb_error_report(struct pt_regs *regs, int tl) + sun4v_err_dtlb_vaddr, sun4v_err_dtlb_ctx, + sun4v_err_dtlb_pte, sun4v_err_dtlb_error); + +- prom_halt(); ++ sun4v_tlb_error(regs); + } + + void hypervisor_tlbop_error(unsigned long err, unsigned long op) +diff --git a/arch/sparc/kernel/tsb.S b/arch/sparc/kernel/tsb.S +index 14158d4..be98685 100644 +--- a/arch/sparc/kernel/tsb.S ++++ b/arch/sparc/kernel/tsb.S +@@ -162,10 +162,10 @@ tsb_miss_page_table_walk_sun4v_fastpath: + nop + .previous + +- rdpr %tl, %g3 +- cmp %g3, 1 ++ rdpr %tl, %g7 ++ cmp %g7, 1 + bne,pn %xcc, winfix_trampoline +- nop ++ mov %g3, %g4 + ba,pt %xcc, etrap + rd %pc, %g7 + call hugetlb_setup +diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c +index 3c1a7cb..35ab8b6 100644 +--- a/arch/sparc/kernel/unaligned_64.c ++++ b/arch/sparc/kernel/unaligned_64.c +@@ -166,17 +166,23 @@ static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs) + unsigned long compute_effective_address(struct pt_regs *regs, + unsigned int insn, unsigned int rd) + { ++ int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; + unsigned int rs1 = (insn >> 14) & 0x1f; + unsigned int rs2 = insn & 0x1f; +- int from_kernel = (regs->tstate & TSTATE_PRIV) != 0; ++ unsigned long addr; + + if (insn & 0x2000) { + maybe_flush_windows(rs1, 0, rd, from_kernel); +- return (fetch_reg(rs1, regs) + sign_extend_imm13(insn)); ++ addr = (fetch_reg(rs1, regs) + sign_extend_imm13(insn)); + } else { + maybe_flush_windows(rs1, rs2, rd, from_kernel); +- return (fetch_reg(rs1, regs) + fetch_reg(rs2, regs)); ++ addr = (fetch_reg(rs1, regs) + fetch_reg(rs2, regs)); + } ++ ++ if (!from_kernel && test_thread_flag(TIF_32BIT)) ++ addr &= 0xffffffff; ++ ++ return addr; + } + + /* This is just to make gcc think die_if_kernel does return... */ +diff --git a/arch/sparc/kernel/viohs.c b/arch/sparc/kernel/viohs.c +index f8e7dd5..9c5fbd0 100644 +--- a/arch/sparc/kernel/viohs.c ++++ b/arch/sparc/kernel/viohs.c +@@ -714,7 +714,7 @@ int vio_ldc_alloc(struct vio_driver_state *vio, + cfg.tx_irq = vio->vdev->tx_irq; + cfg.rx_irq = vio->vdev->rx_irq; + +- lp = ldc_alloc(vio->vdev->channel_id, &cfg, event_arg); ++ lp = ldc_alloc(vio->vdev->channel_id, &cfg, event_arg, vio->name); + if (IS_ERR(lp)) + return PTR_ERR(lp); + +@@ -746,7 +746,7 @@ void vio_port_up(struct vio_driver_state *vio) + + err = 0; + if (state == LDC_STATE_INIT) { +- err = ldc_bind(vio->lp, vio->name); ++ err = ldc_bind(vio->lp); + if (err) + printk(KERN_WARNING "%s: Port %lu bind failed, " + "err=%d\n", +diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S +index 932ff90..0924305 100644 +--- a/arch/sparc/kernel/vmlinux.lds.S ++++ b/arch/sparc/kernel/vmlinux.lds.S +@@ -35,8 +35,9 @@ jiffies = jiffies_64; + + SECTIONS + { +- /* swapper_low_pmd_dir is sparc64 only */ +- swapper_low_pmd_dir = 0x0000000000402000; ++#ifdef CONFIG_SPARC64 ++ swapper_pg_dir = 0x0000000000402000; ++#endif + . = INITIAL_ADDRESS; + .text TEXTSTART : + { +@@ -122,11 +123,6 @@ SECTIONS + *(.swapper_4m_tsb_phys_patch) + __swapper_4m_tsb_phys_patch_end = .; + } +- .page_offset_shift_patch : { +- __page_offset_shift_patch = .; +- *(.page_offset_shift_patch) +- __page_offset_shift_patch_end = .; +- } + .popc_3insn_patch : { + __popc_3insn_patch = .; + *(.popc_3insn_patch) +diff --git a/arch/sparc/lib/NG2memcpy.S b/arch/sparc/lib/NG2memcpy.S +index 2c20ad6..30eee6e 100644 +--- a/arch/sparc/lib/NG2memcpy.S ++++ b/arch/sparc/lib/NG2memcpy.S +@@ -236,6 +236,7 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ + */ + VISEntryHalf + ++ membar #Sync + alignaddr %o1, %g0, %g0 + + add %o1, (64 - 1), %o4 +diff --git a/arch/sparc/lib/NG4memcpy.S b/arch/sparc/lib/NG4memcpy.S +index 9cf2ee0..83aeeb1 100644 +--- a/arch/sparc/lib/NG4memcpy.S ++++ b/arch/sparc/lib/NG4memcpy.S +@@ -41,6 +41,10 @@ + #endif + #endif + ++#if !defined(EX_LD) && !defined(EX_ST) ++#define NON_USER_COPY ++#endif ++ + #ifndef EX_LD + #define EX_LD(x) x + #endif +@@ -197,9 +201,13 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ + mov EX_RETVAL(%o3), %o0 + + .Llarge_src_unaligned: ++#ifdef NON_USER_COPY ++ VISEntryHalfFast(.Lmedium_vis_entry_fail) ++#else ++ VISEntryHalf ++#endif + andn %o2, 0x3f, %o4 + sub %o2, %o4, %o2 +- VISEntryHalf + alignaddr %o1, %g0, %g1 + add %o1, %o4, %o1 + EX_LD(LOAD(ldd, %g1 + 0x00, %f0)) +@@ -232,14 +240,21 @@ FUNC_NAME: /* %o0=dst, %o1=src, %o2=len */ + add %o0, 0x40, %o0 + bne,pt %icc, 1b + LOAD(prefetch, %g1 + 0x200, #n_reads_strong) ++#ifdef NON_USER_COPY ++ VISExitHalfFast ++#else + VISExitHalf +- ++#endif + brz,pn %o2, .Lexit + cmp %o2, 19 + ble,pn %icc, .Lsmall_unaligned + nop + ba,a,pt %icc, .Lmedium_unaligned + ++#ifdef NON_USER_COPY ++.Lmedium_vis_entry_fail: ++ or %o0, %o1, %g2 ++#endif + .Lmedium: + LOAD(prefetch, %o1 + 0x40, #n_reads_strong) + andcc %g2, 0x7, %g0 +diff --git a/arch/sparc/lib/VISsave.S b/arch/sparc/lib/VISsave.S +index b320ae9..a063d84 100644 +--- a/arch/sparc/lib/VISsave.S ++++ b/arch/sparc/lib/VISsave.S +@@ -44,9 +44,8 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3 + + stx %g3, [%g6 + TI_GSR] + 2: add %g6, %g1, %g3 +- cmp %o5, FPRS_DU +- be,pn %icc, 6f +- sll %g1, 3, %g1 ++ mov FPRS_DU | FPRS_DL | FPRS_FEF, %o5 ++ sll %g1, 3, %g1 + stb %o5, [%g3 + TI_FPSAVED] + rd %gsr, %g2 + add %g6, %g1, %g3 +@@ -80,65 +79,3 @@ vis1: ldub [%g6 + TI_FPSAVED], %g3 + .align 32 + 80: jmpl %g7 + %g0, %g0 + nop +- +-6: ldub [%g3 + TI_FPSAVED], %o5 +- or %o5, FPRS_DU, %o5 +- add %g6, TI_FPREGS+0x80, %g2 +- stb %o5, [%g3 + TI_FPSAVED] +- +- sll %g1, 5, %g1 +- add %g6, TI_FPREGS+0xc0, %g3 +- wr %g0, FPRS_FEF, %fprs +- membar #Sync +- stda %f32, [%g2 + %g1] ASI_BLK_P +- stda %f48, [%g3 + %g1] ASI_BLK_P +- membar #Sync +- ba,pt %xcc, 80f +- nop +- +- .align 32 +-80: jmpl %g7 + %g0, %g0 +- nop +- +- .align 32 +-VISenterhalf: +- ldub [%g6 + TI_FPDEPTH], %g1 +- brnz,a,pn %g1, 1f +- cmp %g1, 1 +- stb %g0, [%g6 + TI_FPSAVED] +- stx %fsr, [%g6 + TI_XFSR] +- clr %o5 +- jmpl %g7 + %g0, %g0 +- wr %g0, FPRS_FEF, %fprs +- +-1: bne,pn %icc, 2f +- srl %g1, 1, %g1 +- ba,pt %xcc, vis1 +- sub %g7, 8, %g7 +-2: addcc %g6, %g1, %g3 +- sll %g1, 3, %g1 +- andn %o5, FPRS_DU, %g2 +- stb %g2, [%g3 + TI_FPSAVED] +- +- rd %gsr, %g2 +- add %g6, %g1, %g3 +- stx %g2, [%g3 + TI_GSR] +- add %g6, %g1, %g2 +- stx %fsr, [%g2 + TI_XFSR] +- sll %g1, 5, %g1 +-3: andcc %o5, FPRS_DL, %g0 +- be,pn %icc, 4f +- add %g6, TI_FPREGS, %g2 +- +- add %g6, TI_FPREGS+0x40, %g3 +- membar #Sync +- stda %f0, [%g2 + %g1] ASI_BLK_P +- stda %f16, [%g3 + %g1] ASI_BLK_P +- membar #Sync +- ba,pt %xcc, 4f +- nop +- +- .align 32 +-4: and %o5, FPRS_DU, %o5 +- jmpl %g7 + %g0, %g0 +- wr %o5, FPRS_FEF, %fprs +diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c +index 1d32b54..8f2f94d 100644 +--- a/arch/sparc/lib/atomic32.c ++++ b/arch/sparc/lib/atomic32.c +@@ -40,6 +40,19 @@ int __atomic_add_return(int i, atomic_t *v) + } + EXPORT_SYMBOL(__atomic_add_return); + ++int atomic_xchg(atomic_t *v, int new) ++{ ++ int ret; ++ unsigned long flags; ++ ++ spin_lock_irqsave(ATOMIC_HASH(v), flags); ++ ret = v->counter; ++ v->counter = new; ++ spin_unlock_irqrestore(ATOMIC_HASH(v), flags); ++ return ret; ++} ++EXPORT_SYMBOL(atomic_xchg); ++ + int atomic_cmpxchg(atomic_t *v, int old, int new) + { + int ret; +@@ -132,3 +145,17 @@ unsigned long __cmpxchg_u32(volatile u32 *ptr, u32 old, u32 new) + return (unsigned long)prev; + } + EXPORT_SYMBOL(__cmpxchg_u32); ++ ++unsigned long __xchg_u32(volatile u32 *ptr, u32 new) ++{ ++ unsigned long flags; ++ u32 prev; ++ ++ spin_lock_irqsave(ATOMIC_HASH(ptr), flags); ++ prev = *ptr; ++ *ptr = new; ++ spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags); ++ ++ return (unsigned long)prev; ++} ++EXPORT_SYMBOL(__xchg_u32); +diff --git a/arch/sparc/lib/ksyms.c b/arch/sparc/lib/ksyms.c +index 323335b..ac094de 100644 +--- a/arch/sparc/lib/ksyms.c ++++ b/arch/sparc/lib/ksyms.c +@@ -126,10 +126,6 @@ EXPORT_SYMBOL(copy_user_page); + void VISenter(void); + EXPORT_SYMBOL(VISenter); + +-/* CRYPTO code needs this */ +-void VISenterhalf(void); +-EXPORT_SYMBOL(VISenterhalf); +- + extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *); + extern void xor_vis_3(unsigned long, unsigned long *, unsigned long *, + unsigned long *); +diff --git a/arch/sparc/lib/memmove.S b/arch/sparc/lib/memmove.S +index b7f6334..857ad4f 100644 +--- a/arch/sparc/lib/memmove.S ++++ b/arch/sparc/lib/memmove.S +@@ -8,9 +8,11 @@ + + .text + ENTRY(memmove) /* o0=dst o1=src o2=len */ +- mov %o0, %g1 ++ brz,pn %o2, 99f ++ mov %o0, %g1 ++ + cmp %o0, %o1 +- bleu,pt %xcc, memcpy ++ bleu,pt %xcc, 2f + add %o1, %o2, %g7 + cmp %g7, %o0 + bleu,pt %xcc, memcpy +@@ -24,7 +26,34 @@ ENTRY(memmove) /* o0=dst o1=src o2=len */ + stb %g7, [%o0] + bne,pt %icc, 1b + sub %o0, 1, %o0 +- ++99: + retl + mov %g1, %o0 ++ ++ /* We can't just call memcpy for these memmove cases. On some ++ * chips the memcpy uses cache initializing stores and when dst ++ * and src are close enough, those can clobber the source data ++ * before we've loaded it in. ++ */ ++2: or %o0, %o1, %g7 ++ or %o2, %g7, %g7 ++ andcc %g7, 0x7, %g0 ++ bne,pn %xcc, 4f ++ nop ++ ++3: ldx [%o1], %g7 ++ add %o1, 8, %o1 ++ subcc %o2, 8, %o2 ++ add %o0, 8, %o0 ++ bne,pt %icc, 3b ++ stx %g7, [%o0 - 0x8] ++ ba,a,pt %xcc, 99b ++ ++4: ldub [%o1], %g7 ++ add %o1, 1, %o1 ++ subcc %o2, 1, %o2 ++ add %o0, 1, %o0 ++ bne,pt %icc, 4b ++ stb %g7, [%o0 - 0x1] ++ ba,a,pt %xcc, 99b + ENDPROC(memmove) +diff --git a/arch/sparc/lib/memset.S b/arch/sparc/lib/memset.S +index 99c017b..f75e690 100644 +--- a/arch/sparc/lib/memset.S ++++ b/arch/sparc/lib/memset.S +@@ -3,8 +3,9 @@ + * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + * +- * Returns 0, if ok, and number of bytes not yet set if exception +- * occurs and we were called as clear_user. ++ * Calls to memset returns initial %o0. Calls to bzero returns 0, if ok, and ++ * number of bytes not yet set if exception occurs and we were called as ++ * clear_user. + */ + + #include +@@ -65,6 +66,8 @@ __bzero_begin: + .globl __memset_start, __memset_end + __memset_start: + memset: ++ mov %o0, %g1 ++ mov 1, %g4 + and %o1, 0xff, %g3 + sll %g3, 8, %g2 + or %g3, %g2, %g3 +@@ -89,6 +92,7 @@ memset: + sub %o0, %o2, %o0 + + __bzero: ++ clr %g4 + mov %g0, %g3 + 1: + cmp %o1, 7 +@@ -151,8 +155,8 @@ __bzero: + bne,a 8f + EX(stb %g3, [%o0], and %o1, 1) + 8: +- retl +- clr %o0 ++ b 0f ++ nop + 7: + be 13b + orcc %o1, 0, %g0 +@@ -164,6 +168,12 @@ __bzero: + bne 8b + EX(stb %g3, [%o0 - 1], add %o1, 1) + 0: ++ andcc %g4, 1, %g0 ++ be 5f ++ nop ++ retl ++ mov %g1, %o0 ++5: + retl + clr %o0 + __memset_end: +diff --git a/arch/sparc/math-emu/math_32.c b/arch/sparc/math-emu/math_32.c +index aa4d55b..5ce8f2f 100644 +--- a/arch/sparc/math-emu/math_32.c ++++ b/arch/sparc/math-emu/math_32.c +@@ -499,7 +499,7 @@ static int do_one_mathemu(u32 insn, unsigned long *pfsr, unsigned long *fregs) + case 0: fsr = *pfsr; + if (IR == -1) IR = 2; + /* fcc is always fcc0 */ +- fsr &= ~0xc00; fsr |= (IR << 10); break; ++ fsr &= ~0xc00; fsr |= (IR << 10); + *pfsr = fsr; + break; + case 1: rd->s = IR; break; +diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c +index 59dbd46..163c787 100644 +--- a/arch/sparc/mm/fault_32.c ++++ b/arch/sparc/mm/fault_32.c +@@ -252,6 +252,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c +index 69bb818..0d6de79 100644 +--- a/arch/sparc/mm/fault_64.c ++++ b/arch/sparc/mm/fault_64.c +@@ -96,38 +96,51 @@ static unsigned int get_user_insn(unsigned long tpc) + pte_t *ptep, pte; + unsigned long pa; + u32 insn = 0; +- unsigned long pstate; + +- if (pgd_none(*pgdp)) +- goto outret; ++ if (pgd_none(*pgdp) || unlikely(pgd_bad(*pgdp))) ++ goto out; + pudp = pud_offset(pgdp, tpc); +- if (pud_none(*pudp)) +- goto outret; +- pmdp = pmd_offset(pudp, tpc); +- if (pmd_none(*pmdp)) +- goto outret; ++ if (pud_none(*pudp) || unlikely(pud_bad(*pudp))) ++ goto out; + + /* This disables preemption for us as well. */ +- __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); +- __asm__ __volatile__("wrpr %0, %1, %%pstate" +- : : "r" (pstate), "i" (PSTATE_IE)); +- ptep = pte_offset_map(pmdp, tpc); +- pte = *ptep; +- if (!pte_present(pte)) +- goto out; ++ local_irq_disable(); ++ ++ pmdp = pmd_offset(pudp, tpc); ++ if (pmd_none(*pmdp) || unlikely(pmd_bad(*pmdp))) ++ goto out_irq_enable; + +- pa = (pte_pfn(pte) << PAGE_SHIFT); +- pa += (tpc & ~PAGE_MASK); ++#ifdef CONFIG_TRANSPARENT_HUGEPAGE ++ if (pmd_trans_huge(*pmdp)) { ++ if (pmd_trans_splitting(*pmdp)) ++ goto out_irq_enable; + +- /* Use phys bypass so we don't pollute dtlb/dcache. */ +- __asm__ __volatile__("lduwa [%1] %2, %0" +- : "=r" (insn) +- : "r" (pa), "i" (ASI_PHYS_USE_EC)); ++ pa = pmd_pfn(*pmdp) << PAGE_SHIFT; ++ pa += tpc & ~HPAGE_MASK; + ++ /* Use phys bypass so we don't pollute dtlb/dcache. */ ++ __asm__ __volatile__("lduwa [%1] %2, %0" ++ : "=r" (insn) ++ : "r" (pa), "i" (ASI_PHYS_USE_EC)); ++ } else ++#endif ++ { ++ ptep = pte_offset_map(pmdp, tpc); ++ pte = *ptep; ++ if (pte_present(pte)) { ++ pa = (pte_pfn(pte) << PAGE_SHIFT); ++ pa += (tpc & ~PAGE_MASK); ++ ++ /* Use phys bypass so we don't pollute dtlb/dcache. */ ++ __asm__ __volatile__("lduwa [%1] %2, %0" ++ : "=r" (insn) ++ : "r" (pa), "i" (ASI_PHYS_USE_EC)); ++ } ++ pte_unmap(ptep); ++ } ++out_irq_enable: ++ local_irq_enable(); + out: +- pte_unmap(ptep); +- __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); +-outret: + return insn; + } + +@@ -153,7 +166,8 @@ show_signal_msg(struct pt_regs *regs, int sig, int code, + } + + static void do_fault_siginfo(int code, int sig, struct pt_regs *regs, +- unsigned int insn, int fault_code) ++ unsigned long fault_addr, unsigned int insn, ++ int fault_code) + { + unsigned long addr; + siginfo_t info; +@@ -161,10 +175,18 @@ static void do_fault_siginfo(int code, int sig, struct pt_regs *regs, + info.si_code = code; + info.si_signo = sig; + info.si_errno = 0; +- if (fault_code & FAULT_CODE_ITLB) ++ if (fault_code & FAULT_CODE_ITLB) { + addr = regs->tpc; +- else +- addr = compute_effective_address(regs, insn, 0); ++ } else { ++ /* If we were able to probe the faulting instruction, use it ++ * to compute a precise fault address. Otherwise use the fault ++ * time provided address which may only have page granularity. ++ */ ++ if (insn) ++ addr = compute_effective_address(regs, insn, 0); ++ else ++ addr = fault_addr; ++ } + info.si_addr = (void __user *) addr; + info.si_trapno = 0; + +@@ -239,7 +261,7 @@ static void __kprobes do_kernel_fault(struct pt_regs *regs, int si_code, + /* The si_code was set to make clear whether + * this was a SEGV_MAPERR or SEGV_ACCERR fault. + */ +- do_fault_siginfo(si_code, SIGSEGV, regs, insn, fault_code); ++ do_fault_siginfo(si_code, SIGSEGV, regs, address, insn, fault_code); + return; + } + +@@ -259,18 +281,6 @@ static void noinline __kprobes bogus_32bit_fault_tpc(struct pt_regs *regs) + show_regs(regs); + } + +-static void noinline __kprobes bogus_32bit_fault_address(struct pt_regs *regs, +- unsigned long addr) +-{ +- static int times; +- +- if (times++ < 10) +- printk(KERN_ERR "FAULT[%s:%d]: 32-bit process " +- "reports 64-bit fault address [%lx]\n", +- current->comm, current->pid, addr); +- show_regs(regs); +-} +- + asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) + { + enum ctx_state prev_state = exception_enter(); +@@ -300,10 +310,8 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) + goto intr_or_no_mm; + } + } +- if (unlikely((address >> 32) != 0)) { +- bogus_32bit_fault_address(regs, address); ++ if (unlikely((address >> 32) != 0)) + goto intr_or_no_mm; +- } + } + + if (regs->tstate & TSTATE_PRIV) { +@@ -340,6 +348,9 @@ retry: + down_read(&mm->mmap_sem); + } + ++ if (fault_code & FAULT_CODE_BAD_RA) ++ goto do_sigbus; ++ + vma = find_vma(mm, address); + if (!vma) + goto bad_area; +@@ -437,6 +448,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +@@ -525,7 +538,7 @@ do_sigbus: + * Send a sigbus, regardless of whether we were in kernel + * or user mode. + */ +- do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, insn, fault_code); ++ do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, address, insn, fault_code); + + /* Kernel mode? Handle exceptions or die */ + if (regs->tstate & TSTATE_PRIV) +diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c +index c4d3da6..ae6ce38 100644 +--- a/arch/sparc/mm/gup.c ++++ b/arch/sparc/mm/gup.c +@@ -73,7 +73,7 @@ static int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr, + struct page *head, *page, *tail; + int refs; + +- if (!pmd_large(pmd)) ++ if (!(pmd_val(pmd) & _PAGE_VALID)) + return 0; + + if (write && !pmd_write(pmd)) +@@ -160,6 +160,36 @@ static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end, + return 1; + } + ++int __get_user_pages_fast(unsigned long start, int nr_pages, int write, ++ struct page **pages) ++{ ++ struct mm_struct *mm = current->mm; ++ unsigned long addr, len, end; ++ unsigned long next, flags; ++ pgd_t *pgdp; ++ int nr = 0; ++ ++ start &= PAGE_MASK; ++ addr = start; ++ len = (unsigned long) nr_pages << PAGE_SHIFT; ++ end = start + len; ++ ++ local_irq_save(flags); ++ pgdp = pgd_offset(mm, addr); ++ do { ++ pgd_t pgd = *pgdp; ++ ++ next = pgd_addr_end(addr, end); ++ if (pgd_none(pgd)) ++ break; ++ if (!gup_pud_range(pgd, addr, next, write, pages, &nr)) ++ break; ++ } while (pgdp++, addr = next, addr != end); ++ local_irq_restore(flags); ++ ++ return nr; ++} ++ + int get_user_pages_fast(unsigned long start, int nr_pages, int write, + struct page **pages) + { +diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c +index eafbc65..34506f2 100644 +--- a/arch/sparc/mm/init_64.c ++++ b/arch/sparc/mm/init_64.c +@@ -73,7 +73,6 @@ unsigned long kern_linear_pte_xor[4] __read_mostly; + * 'cpu' properties, but we need to have this table setup before the + * MDESC is initialized. + */ +-unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; + + #ifndef CONFIG_DEBUG_PAGEALLOC + /* A special kernel TSB for 4MB, 256MB, 2GB and 16GB linear mappings. +@@ -82,10 +81,11 @@ unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; + */ + extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES]; + #endif ++extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES]; + + static unsigned long cpu_pgsz_mask; + +-#define MAX_BANKS 32 ++#define MAX_BANKS 1024 + + static struct linux_prom64_registers pavail[MAX_BANKS]; + static int pavail_ents; +@@ -163,10 +163,6 @@ static void __init read_obp_memory(const char *property, + cmp_p64, NULL); + } + +-unsigned long sparc64_valid_addr_bitmap[VALID_ADDR_BITMAP_BYTES / +- sizeof(unsigned long)]; +-EXPORT_SYMBOL(sparc64_valid_addr_bitmap); +- + /* Kernel physical address base and size in bytes. */ + unsigned long kern_base __read_mostly; + unsigned long kern_size __read_mostly; +@@ -350,6 +346,10 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t * + + mm = vma->vm_mm; + ++ /* Don't insert a non-valid PTE into the TSB, we'll deadlock. */ ++ if (!pte_accessible(mm, pte)) ++ return; ++ + spin_lock_irqsave(&mm->context.lock, flags); + + #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) +@@ -588,7 +588,7 @@ static void __init remap_kernel(void) + int i, tlb_ent = sparc64_highest_locked_tlbent(); + + tte_vaddr = (unsigned long) KERNBASE; +- phys_page = (prom_boot_mapping_phys_low >> 22UL) << 22UL; ++ phys_page = (prom_boot_mapping_phys_low >> ILOG2_4MB) << ILOG2_4MB; + tte_data = kern_large_tte(phys_page); + + kern_locked_tte_data = tte_data; +@@ -834,7 +834,10 @@ static int find_node(unsigned long addr) + if ((addr & p->mask) == p->val) + return i; + } +- return -1; ++ /* The following condition has been observed on LDOM guests.*/ ++ WARN_ONCE(1, "find_node: A physical address doesn't match a NUMA node" ++ " rule. Some physical memory will be owned by node 0."); ++ return 0; + } + + static u64 memblock_nid_range(u64 start, u64 end, int *nid) +@@ -1356,9 +1359,144 @@ static unsigned long __init bootmem_init(unsigned long phys_base) + static struct linux_prom64_registers pall[MAX_BANKS] __initdata; + static int pall_ents __initdata; + +-#ifdef CONFIG_DEBUG_PAGEALLOC ++static unsigned long max_phys_bits = 40; ++ ++bool kern_addr_valid(unsigned long addr) ++{ ++ pgd_t *pgd; ++ pud_t *pud; ++ pmd_t *pmd; ++ pte_t *pte; ++ ++ if ((long)addr < 0L) { ++ unsigned long pa = __pa(addr); ++ ++ if ((addr >> max_phys_bits) != 0UL) ++ return false; ++ ++ return pfn_valid(pa >> PAGE_SHIFT); ++ } ++ ++ if (addr >= (unsigned long) KERNBASE && ++ addr < (unsigned long)&_end) ++ return true; ++ ++ pgd = pgd_offset_k(addr); ++ if (pgd_none(*pgd)) ++ return 0; ++ ++ pud = pud_offset(pgd, addr); ++ if (pud_none(*pud)) ++ return 0; ++ ++ if (pud_large(*pud)) ++ return pfn_valid(pud_pfn(*pud)); ++ ++ pmd = pmd_offset(pud, addr); ++ if (pmd_none(*pmd)) ++ return 0; ++ ++ if (pmd_large(*pmd)) ++ return pfn_valid(pmd_pfn(*pmd)); ++ ++ pte = pte_offset_kernel(pmd, addr); ++ if (pte_none(*pte)) ++ return 0; ++ ++ return pfn_valid(pte_pfn(*pte)); ++} ++EXPORT_SYMBOL(kern_addr_valid); ++ ++static unsigned long __ref kernel_map_hugepud(unsigned long vstart, ++ unsigned long vend, ++ pud_t *pud) ++{ ++ const unsigned long mask16gb = (1UL << 34) - 1UL; ++ u64 pte_val = vstart; ++ ++ /* Each PUD is 8GB */ ++ if ((vstart & mask16gb) || ++ (vend - vstart <= mask16gb)) { ++ pte_val ^= kern_linear_pte_xor[2]; ++ pud_val(*pud) = pte_val | _PAGE_PUD_HUGE; ++ ++ return vstart + PUD_SIZE; ++ } ++ ++ pte_val ^= kern_linear_pte_xor[3]; ++ pte_val |= _PAGE_PUD_HUGE; ++ ++ vend = vstart + mask16gb + 1UL; ++ while (vstart < vend) { ++ pud_val(*pud) = pte_val; ++ ++ pte_val += PUD_SIZE; ++ vstart += PUD_SIZE; ++ pud++; ++ } ++ return vstart; ++} ++ ++static bool kernel_can_map_hugepud(unsigned long vstart, unsigned long vend, ++ bool guard) ++{ ++ if (guard && !(vstart & ~PUD_MASK) && (vend - vstart) >= PUD_SIZE) ++ return true; ++ ++ return false; ++} ++ ++static unsigned long __ref kernel_map_hugepmd(unsigned long vstart, ++ unsigned long vend, ++ pmd_t *pmd) ++{ ++ const unsigned long mask256mb = (1UL << 28) - 1UL; ++ const unsigned long mask2gb = (1UL << 31) - 1UL; ++ u64 pte_val = vstart; ++ ++ /* Each PMD is 8MB */ ++ if ((vstart & mask256mb) || ++ (vend - vstart <= mask256mb)) { ++ pte_val ^= kern_linear_pte_xor[0]; ++ pmd_val(*pmd) = pte_val | _PAGE_PMD_HUGE; ++ ++ return vstart + PMD_SIZE; ++ } ++ ++ if ((vstart & mask2gb) || ++ (vend - vstart <= mask2gb)) { ++ pte_val ^= kern_linear_pte_xor[1]; ++ pte_val |= _PAGE_PMD_HUGE; ++ vend = vstart + mask256mb + 1UL; ++ } else { ++ pte_val ^= kern_linear_pte_xor[2]; ++ pte_val |= _PAGE_PMD_HUGE; ++ vend = vstart + mask2gb + 1UL; ++ } ++ ++ while (vstart < vend) { ++ pmd_val(*pmd) = pte_val; ++ ++ pte_val += PMD_SIZE; ++ vstart += PMD_SIZE; ++ pmd++; ++ } ++ ++ return vstart; ++} ++ ++static bool kernel_can_map_hugepmd(unsigned long vstart, unsigned long vend, ++ bool guard) ++{ ++ if (guard && !(vstart & ~PMD_MASK) && (vend - vstart) >= PMD_SIZE) ++ return true; ++ ++ return false; ++} ++ + static unsigned long __ref kernel_map_range(unsigned long pstart, +- unsigned long pend, pgprot_t prot) ++ unsigned long pend, pgprot_t prot, ++ bool use_huge) + { + unsigned long vstart = PAGE_OFFSET + pstart; + unsigned long vend = PAGE_OFFSET + pend; +@@ -1377,19 +1515,34 @@ static unsigned long __ref kernel_map_range(unsigned long pstart, + pmd_t *pmd; + pte_t *pte; + ++ if (pgd_none(*pgd)) { ++ pud_t *new; ++ ++ new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); ++ alloc_bytes += PAGE_SIZE; ++ pgd_populate(&init_mm, pgd, new); ++ } + pud = pud_offset(pgd, vstart); + if (pud_none(*pud)) { + pmd_t *new; + ++ if (kernel_can_map_hugepud(vstart, vend, use_huge)) { ++ vstart = kernel_map_hugepud(vstart, vend, pud); ++ continue; ++ } + new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + alloc_bytes += PAGE_SIZE; + pud_populate(&init_mm, pud, new); + } + + pmd = pmd_offset(pud, vstart); +- if (!pmd_present(*pmd)) { ++ if (pmd_none(*pmd)) { + pte_t *new; + ++ if (kernel_can_map_hugepmd(vstart, vend, use_huge)) { ++ vstart = kernel_map_hugepmd(vstart, vend, pmd); ++ continue; ++ } + new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); + alloc_bytes += PAGE_SIZE; + pmd_populate_kernel(&init_mm, pmd, new); +@@ -1412,100 +1565,34 @@ static unsigned long __ref kernel_map_range(unsigned long pstart, + return alloc_bytes; + } + +-extern unsigned int kvmap_linear_patch[1]; +-#endif /* CONFIG_DEBUG_PAGEALLOC */ +- +-static void __init kpte_set_val(unsigned long index, unsigned long val) +-{ +- unsigned long *ptr = kpte_linear_bitmap; +- +- val <<= ((index % (BITS_PER_LONG / 2)) * 2); +- ptr += (index / (BITS_PER_LONG / 2)); +- +- *ptr |= val; +-} +- +-static const unsigned long kpte_shift_min = 28; /* 256MB */ +-static const unsigned long kpte_shift_max = 34; /* 16GB */ +-static const unsigned long kpte_shift_incr = 3; +- +-static unsigned long kpte_mark_using_shift(unsigned long start, unsigned long end, +- unsigned long shift) ++static void __init flush_all_kernel_tsbs(void) + { +- unsigned long size = (1UL << shift); +- unsigned long mask = (size - 1UL); +- unsigned long remains = end - start; +- unsigned long val; +- +- if (remains < size || (start & mask)) +- return start; +- +- /* VAL maps: +- * +- * shift 28 --> kern_linear_pte_xor index 1 +- * shift 31 --> kern_linear_pte_xor index 2 +- * shift 34 --> kern_linear_pte_xor index 3 +- */ +- val = ((shift - kpte_shift_min) / kpte_shift_incr) + 1; +- +- remains &= ~mask; +- if (shift != kpte_shift_max) +- remains = size; +- +- while (remains) { +- unsigned long index = start >> kpte_shift_min; ++ int i; + +- kpte_set_val(index, val); ++ for (i = 0; i < KERNEL_TSB_NENTRIES; i++) { ++ struct tsb *ent = &swapper_tsb[i]; + +- start += 1UL << kpte_shift_min; +- remains -= 1UL << kpte_shift_min; ++ ent->tag = (1UL << TSB_TAG_INVALID_BIT); + } ++#ifndef CONFIG_DEBUG_PAGEALLOC ++ for (i = 0; i < KERNEL_TSB4M_NENTRIES; i++) { ++ struct tsb *ent = &swapper_4m_tsb[i]; + +- return start; +-} +- +-static void __init mark_kpte_bitmap(unsigned long start, unsigned long end) +-{ +- unsigned long smallest_size, smallest_mask; +- unsigned long s; +- +- smallest_size = (1UL << kpte_shift_min); +- smallest_mask = (smallest_size - 1UL); +- +- while (start < end) { +- unsigned long orig_start = start; +- +- for (s = kpte_shift_max; s >= kpte_shift_min; s -= kpte_shift_incr) { +- start = kpte_mark_using_shift(start, end, s); +- +- if (start != orig_start) +- break; +- } +- +- if (start == orig_start) +- start = (start + smallest_size) & ~smallest_mask; ++ ent->tag = (1UL << TSB_TAG_INVALID_BIT); + } ++#endif + } + +-static void __init init_kpte_bitmap(void) +-{ +- unsigned long i; +- +- for (i = 0; i < pall_ents; i++) { +- unsigned long phys_start, phys_end; +- +- phys_start = pall[i].phys_addr; +- phys_end = phys_start + pall[i].reg_size; +- +- mark_kpte_bitmap(phys_start, phys_end); +- } +-} ++extern unsigned int kvmap_linear_patch[1]; + + static void __init kernel_physical_mapping_init(void) + { +-#ifdef CONFIG_DEBUG_PAGEALLOC + unsigned long i, mem_alloced = 0UL; ++ bool use_huge = true; + ++#ifdef CONFIG_DEBUG_PAGEALLOC ++ use_huge = false; ++#endif + for (i = 0; i < pall_ents; i++) { + unsigned long phys_start, phys_end; + +@@ -1513,7 +1600,7 @@ static void __init kernel_physical_mapping_init(void) + phys_end = phys_start + pall[i].reg_size; + + mem_alloced += kernel_map_range(phys_start, phys_end, +- PAGE_KERNEL); ++ PAGE_KERNEL, use_huge); + } + + printk("Allocated %ld bytes for kernel page tables.\n", +@@ -1522,8 +1609,9 @@ static void __init kernel_physical_mapping_init(void) + kvmap_linear_patch[0] = 0x01000000; /* nop */ + flushi(&kvmap_linear_patch[0]); + ++ flush_all_kernel_tsbs(); ++ + __flush_tlb_all(); +-#endif + } + + #ifdef CONFIG_DEBUG_PAGEALLOC +@@ -1533,7 +1621,7 @@ void kernel_map_pages(struct page *page, int numpages, int enable) + unsigned long phys_end = phys_start + (numpages * PAGE_SIZE); + + kernel_map_range(phys_start, phys_end, +- (enable ? PAGE_KERNEL : __pgprot(0))); ++ (enable ? PAGE_KERNEL : __pgprot(0)), false); + + flush_tsb_kernel_range(PAGE_OFFSET + phys_start, + PAGE_OFFSET + phys_end); +@@ -1561,76 +1649,56 @@ unsigned long __init find_ecache_flush_span(unsigned long size) + unsigned long PAGE_OFFSET; + EXPORT_SYMBOL(PAGE_OFFSET); + +-static void __init page_offset_shift_patch_one(unsigned int *insn, unsigned long phys_bits) +-{ +- unsigned long final_shift; +- unsigned int val = *insn; +- unsigned int cnt; +- +- /* We are patching in ilog2(max_supported_phys_address), and +- * we are doing so in a manner similar to a relocation addend. +- * That is, we are adding the shift value to whatever value +- * is in the shift instruction count field already. +- */ +- cnt = (val & 0x3f); +- val &= ~0x3f; +- +- /* If we are trying to shift >= 64 bits, clear the destination +- * register. This can happen when phys_bits ends up being equal +- * to MAX_PHYS_ADDRESS_BITS. +- */ +- final_shift = (cnt + (64 - phys_bits)); +- if (final_shift >= 64) { +- unsigned int rd = (val >> 25) & 0x1f; +- +- val = 0x80100000 | (rd << 25); +- } else { +- val |= final_shift; +- } +- *insn = val; +- +- __asm__ __volatile__("flush %0" +- : /* no outputs */ +- : "r" (insn)); +-} +- +-static void __init page_offset_shift_patch(unsigned long phys_bits) +-{ +- extern unsigned int __page_offset_shift_patch; +- extern unsigned int __page_offset_shift_patch_end; +- unsigned int *p; +- +- p = &__page_offset_shift_patch; +- while (p < &__page_offset_shift_patch_end) { +- unsigned int *insn = (unsigned int *)(unsigned long)*p; ++unsigned long VMALLOC_END = 0x0000010000000000UL; ++EXPORT_SYMBOL(VMALLOC_END); + +- page_offset_shift_patch_one(insn, phys_bits); +- +- p++; +- } +-} ++unsigned long sparc64_va_hole_top = 0xfffff80000000000UL; ++unsigned long sparc64_va_hole_bottom = 0x0000080000000000UL; + + static void __init setup_page_offset(void) + { +- unsigned long max_phys_bits = 40; +- + if (tlb_type == cheetah || tlb_type == cheetah_plus) { ++ /* Cheetah/Panther support a full 64-bit virtual ++ * address, so we can use all that our page tables ++ * support. ++ */ ++ sparc64_va_hole_top = 0xfff0000000000000UL; ++ sparc64_va_hole_bottom = 0x0010000000000000UL; ++ + max_phys_bits = 42; + } else if (tlb_type == hypervisor) { + switch (sun4v_chip_type) { + case SUN4V_CHIP_NIAGARA1: + case SUN4V_CHIP_NIAGARA2: ++ /* T1 and T2 support 48-bit virtual addresses. */ ++ sparc64_va_hole_top = 0xffff800000000000UL; ++ sparc64_va_hole_bottom = 0x0000800000000000UL; ++ + max_phys_bits = 39; + break; + case SUN4V_CHIP_NIAGARA3: ++ /* T3 supports 48-bit virtual addresses. */ ++ sparc64_va_hole_top = 0xffff800000000000UL; ++ sparc64_va_hole_bottom = 0x0000800000000000UL; ++ + max_phys_bits = 43; + break; + case SUN4V_CHIP_NIAGARA4: + case SUN4V_CHIP_NIAGARA5: + case SUN4V_CHIP_SPARC64X: +- default: ++ case SUN4V_CHIP_SPARC_M6: ++ /* T4 and later support 52-bit virtual addresses. */ ++ sparc64_va_hole_top = 0xfff8000000000000UL; ++ sparc64_va_hole_bottom = 0x0008000000000000UL; + max_phys_bits = 47; + break; ++ case SUN4V_CHIP_SPARC_M7: ++ default: ++ /* M7 and later support 52-bit virtual addresses. */ ++ sparc64_va_hole_top = 0xfff8000000000000UL; ++ sparc64_va_hole_bottom = 0x0008000000000000UL; ++ max_phys_bits = 49; ++ break; + } + } + +@@ -1640,12 +1708,16 @@ static void __init setup_page_offset(void) + prom_halt(); + } + +- PAGE_OFFSET = PAGE_OFFSET_BY_BITS(max_phys_bits); ++ PAGE_OFFSET = sparc64_va_hole_top; ++ VMALLOC_END = ((sparc64_va_hole_bottom >> 1) + ++ (sparc64_va_hole_bottom >> 2)); + +- pr_info("PAGE_OFFSET is 0x%016lx (max_phys_bits == %lu)\n", ++ pr_info("MM: PAGE_OFFSET is 0x%016lx (max_phys_bits == %lu)\n", + PAGE_OFFSET, max_phys_bits); +- +- page_offset_shift_patch(max_phys_bits); ++ pr_info("MM: VMALLOC [0x%016lx --> 0x%016lx]\n", ++ VMALLOC_START, VMALLOC_END); ++ pr_info("MM: VMEMMAP [0x%016lx --> 0x%016lx]\n", ++ VMEMMAP_BASE, VMEMMAP_BASE << 1); + } + + static void __init tsb_phys_patch(void) +@@ -1690,21 +1762,42 @@ static void __init tsb_phys_patch(void) + #define NUM_KTSB_DESCR 1 + #endif + static struct hv_tsb_descr ktsb_descr[NUM_KTSB_DESCR]; +-extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES]; ++ ++/* The swapper TSBs are loaded with a base sequence of: ++ * ++ * sethi %uhi(SYMBOL), REG1 ++ * sethi %hi(SYMBOL), REG2 ++ * or REG1, %ulo(SYMBOL), REG1 ++ * or REG2, %lo(SYMBOL), REG2 ++ * sllx REG1, 32, REG1 ++ * or REG1, REG2, REG1 ++ * ++ * When we use physical addressing for the TSB accesses, we patch the ++ * first four instructions in the above sequence. ++ */ + + static void patch_one_ktsb_phys(unsigned int *start, unsigned int *end, unsigned long pa) + { +- pa >>= KTSB_PHYS_SHIFT; ++ unsigned long high_bits, low_bits; ++ ++ high_bits = (pa >> 32) & 0xffffffff; ++ low_bits = (pa >> 0) & 0xffffffff; + + while (start < end) { + unsigned int *ia = (unsigned int *)(unsigned long)*start; + +- ia[0] = (ia[0] & ~0x3fffff) | (pa >> 10); ++ ia[0] = (ia[0] & ~0x3fffff) | (high_bits >> 10); + __asm__ __volatile__("flush %0" : : "r" (ia)); + +- ia[1] = (ia[1] & ~0x3ff) | (pa & 0x3ff); ++ ia[1] = (ia[1] & ~0x3fffff) | (low_bits >> 10); + __asm__ __volatile__("flush %0" : : "r" (ia + 1)); + ++ ia[2] = (ia[2] & ~0x1fff) | (high_bits & 0x3ff); ++ __asm__ __volatile__("flush %0" : : "r" (ia + 2)); ++ ++ ia[3] = (ia[3] & ~0x1fff) | (low_bits & 0x3ff); ++ __asm__ __volatile__("flush %0" : : "r" (ia + 3)); ++ + start++; + } + } +@@ -1843,7 +1936,6 @@ static void __init sun4v_linear_pte_xor_finalize(void) + /* paging_init() sets up the page tables */ + + static unsigned long last_valid_pfn; +-pgd_t swapper_pg_dir[PTRS_PER_PGD]; + + static void sun4u_pgprot_init(void); + static void sun4v_pgprot_init(void); +@@ -1881,7 +1973,7 @@ void __init paging_init(void) + + BUILD_BUG_ON(NR_CPUS > 4096); + +- kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; ++ kern_base = (prom_boot_mapping_phys_low >> ILOG2_4MB) << ILOG2_4MB; + kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; + + /* Invalidate both kernel TSBs. */ +@@ -1937,7 +2029,7 @@ void __init paging_init(void) + shift = kern_base + PAGE_OFFSET - ((unsigned long)KERNBASE); + + real_end = (unsigned long)_end; +- num_kernel_image_mappings = DIV_ROUND_UP(real_end - KERNBASE, 1 << 22); ++ num_kernel_image_mappings = DIV_ROUND_UP(real_end - KERNBASE, 1 << ILOG2_4MB); + printk("Kernel: Using %d locked TLB entries for main kernel image.\n", + num_kernel_image_mappings); + +@@ -1946,16 +2038,10 @@ void __init paging_init(void) + */ + init_mm.pgd += ((shift) / (sizeof(pgd_t))); + +- memset(swapper_low_pmd_dir, 0, sizeof(swapper_low_pmd_dir)); ++ memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir)); + +- /* Now can init the kernel/bad page tables. */ +- pud_set(pud_offset(&swapper_pg_dir[0], 0), +- swapper_low_pmd_dir + (shift / sizeof(pgd_t))); +- + inherit_prom_mappings(); + +- init_kpte_bitmap(); +- + /* Ok, we can use our TLB miss and window trap handlers safely. */ + setup_tba(); + +@@ -2062,70 +2148,6 @@ int page_in_phys_avail(unsigned long paddr) + return 0; + } + +-static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata; +-static int pavail_rescan_ents __initdata; +- +-/* Certain OBP calls, such as fetching "available" properties, can +- * claim physical memory. So, along with initializing the valid +- * address bitmap, what we do here is refetch the physical available +- * memory list again, and make sure it provides at least as much +- * memory as 'pavail' does. +- */ +-static void __init setup_valid_addr_bitmap_from_pavail(unsigned long *bitmap) +-{ +- int i; +- +- read_obp_memory("available", &pavail_rescan[0], &pavail_rescan_ents); +- +- for (i = 0; i < pavail_ents; i++) { +- unsigned long old_start, old_end; +- +- old_start = pavail[i].phys_addr; +- old_end = old_start + pavail[i].reg_size; +- while (old_start < old_end) { +- int n; +- +- for (n = 0; n < pavail_rescan_ents; n++) { +- unsigned long new_start, new_end; +- +- new_start = pavail_rescan[n].phys_addr; +- new_end = new_start + +- pavail_rescan[n].reg_size; +- +- if (new_start <= old_start && +- new_end >= (old_start + PAGE_SIZE)) { +- set_bit(old_start >> 22, bitmap); +- goto do_next_page; +- } +- } +- +- prom_printf("mem_init: Lost memory in pavail\n"); +- prom_printf("mem_init: OLD start[%lx] size[%lx]\n", +- pavail[i].phys_addr, +- pavail[i].reg_size); +- prom_printf("mem_init: NEW start[%lx] size[%lx]\n", +- pavail_rescan[i].phys_addr, +- pavail_rescan[i].reg_size); +- prom_printf("mem_init: Cannot continue, aborting.\n"); +- prom_halt(); +- +- do_next_page: +- old_start += PAGE_SIZE; +- } +- } +-} +- +-static void __init patch_tlb_miss_handler_bitmap(void) +-{ +- extern unsigned int valid_addr_bitmap_insn[]; +- extern unsigned int valid_addr_bitmap_patch[]; +- +- valid_addr_bitmap_insn[1] = valid_addr_bitmap_patch[1]; +- mb(); +- valid_addr_bitmap_insn[0] = valid_addr_bitmap_patch[0]; +- flushi(&valid_addr_bitmap_insn[0]); +-} +- + static void __init register_page_bootmem_info(void) + { + #ifdef CONFIG_NEED_MULTIPLE_NODES +@@ -2138,18 +2160,6 @@ static void __init register_page_bootmem_info(void) + } + void __init mem_init(void) + { +- unsigned long addr, last; +- +- addr = PAGE_OFFSET + kern_base; +- last = PAGE_ALIGN(kern_size) + addr; +- while (addr < last) { +- set_bit(__pa(addr) >> 22, sparc64_valid_addr_bitmap); +- addr += PAGE_SIZE; +- } +- +- setup_valid_addr_bitmap_from_pavail(sparc64_valid_addr_bitmap); +- patch_tlb_miss_handler_bitmap(); +- + high_memory = __va(last_valid_pfn << PAGE_SHIFT); + + register_page_bootmem_info(); +@@ -2239,18 +2249,9 @@ unsigned long _PAGE_CACHE __read_mostly; + EXPORT_SYMBOL(_PAGE_CACHE); + + #ifdef CONFIG_SPARSEMEM_VMEMMAP +-unsigned long vmemmap_table[VMEMMAP_SIZE]; +- +-static long __meminitdata addr_start, addr_end; +-static int __meminitdata node_start; +- + int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend, + int node) + { +- unsigned long phys_start = (vstart - VMEMMAP_BASE); +- unsigned long phys_end = (vend - VMEMMAP_BASE); +- unsigned long addr = phys_start & VMEMMAP_CHUNK_MASK; +- unsigned long end = VMEMMAP_ALIGN(phys_end); + unsigned long pte_base; + + pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4U | +@@ -2261,47 +2262,52 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend, + _PAGE_CP_4V | _PAGE_CV_4V | + _PAGE_P_4V | _PAGE_W_4V); + +- for (; addr < end; addr += VMEMMAP_CHUNK) { +- unsigned long *vmem_pp = +- vmemmap_table + (addr >> VMEMMAP_CHUNK_SHIFT); +- void *block; ++ pte_base |= _PAGE_PMD_HUGE; + +- if (!(*vmem_pp & _PAGE_VALID)) { +- block = vmemmap_alloc_block(1UL << 22, node); +- if (!block) ++ vstart = vstart & PMD_MASK; ++ vend = ALIGN(vend, PMD_SIZE); ++ for (; vstart < vend; vstart += PMD_SIZE) { ++ pgd_t *pgd = pgd_offset_k(vstart); ++ unsigned long pte; ++ pud_t *pud; ++ pmd_t *pmd; ++ ++ if (pgd_none(*pgd)) { ++ pud_t *new = vmemmap_alloc_block(PAGE_SIZE, node); ++ ++ if (!new) + return -ENOMEM; ++ pgd_populate(&init_mm, pgd, new); ++ } + +- *vmem_pp = pte_base | __pa(block); ++ pud = pud_offset(pgd, vstart); ++ if (pud_none(*pud)) { ++ pmd_t *new = vmemmap_alloc_block(PAGE_SIZE, node); + +- /* check to see if we have contiguous blocks */ +- if (addr_end != addr || node_start != node) { +- if (addr_start) +- printk(KERN_DEBUG " [%lx-%lx] on node %d\n", +- addr_start, addr_end-1, node_start); +- addr_start = addr; +- node_start = node; +- } +- addr_end = addr + VMEMMAP_CHUNK; ++ if (!new) ++ return -ENOMEM; ++ pud_populate(&init_mm, pud, new); + } +- } +- return 0; +-} + +-void __meminit vmemmap_populate_print_last(void) +-{ +- if (addr_start) { +- printk(KERN_DEBUG " [%lx-%lx] on node %d\n", +- addr_start, addr_end-1, node_start); +- addr_start = 0; +- addr_end = 0; +- node_start = 0; ++ pmd = pmd_offset(pud, vstart); ++ ++ pte = pmd_val(*pmd); ++ if (!(pte & _PAGE_VALID)) { ++ void *block = vmemmap_alloc_block(PMD_SIZE, node); ++ ++ if (!block) ++ return -ENOMEM; ++ ++ pmd_val(*pmd) = pte_base | __pa(block); ++ } + } ++ ++ return 0; + } + + void vmemmap_free(unsigned long start, unsigned long end) + { + } +- + #endif /* CONFIG_SPARSEMEM_VMEMMAP */ + + static void prot_init_common(unsigned long page_none, +@@ -2614,6 +2620,10 @@ void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr, + + pte = pmd_val(entry); + ++ /* Don't insert a non-valid PMD into the TSB, we'll deadlock. */ ++ if (!(pte & _PAGE_VALID)) ++ return; ++ + /* We are fabricating 8MB pages using 4MB real hw pages. */ + pte |= (addr & (1UL << REAL_HPAGE_SHIFT)); + +@@ -2694,3 +2704,26 @@ void hugetlb_setup(struct pt_regs *regs) + } + } + #endif ++ ++#ifdef CONFIG_SMP ++#define do_flush_tlb_kernel_range smp_flush_tlb_kernel_range ++#else ++#define do_flush_tlb_kernel_range __flush_tlb_kernel_range ++#endif ++ ++void flush_tlb_kernel_range(unsigned long start, unsigned long end) ++{ ++ if (start < HI_OBP_ADDRESS && end > LOW_OBP_ADDRESS) { ++ if (start < LOW_OBP_ADDRESS) { ++ flush_tsb_kernel_range(start, LOW_OBP_ADDRESS); ++ do_flush_tlb_kernel_range(start, LOW_OBP_ADDRESS); ++ } ++ if (end > HI_OBP_ADDRESS) { ++ flush_tsb_kernel_range(HI_OBP_ADDRESS, end); ++ do_flush_tlb_kernel_range(HI_OBP_ADDRESS, end); ++ } ++ } else { ++ flush_tsb_kernel_range(start, end); ++ do_flush_tlb_kernel_range(start, end); ++ } ++} +diff --git a/arch/sparc/mm/init_64.h b/arch/sparc/mm/init_64.h +index 5d3782de..ac49119 100644 +--- a/arch/sparc/mm/init_64.h ++++ b/arch/sparc/mm/init_64.h +@@ -8,15 +8,8 @@ + */ + + #define MAX_PHYS_ADDRESS (1UL << MAX_PHYS_ADDRESS_BITS) +-#define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL) +-#define KPTE_BITMAP_BYTES \ +- ((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 4) +-#define VALID_ADDR_BITMAP_CHUNK_SZ (4UL * 1024UL * 1024UL) +-#define VALID_ADDR_BITMAP_BYTES \ +- ((MAX_PHYS_ADDRESS / VALID_ADDR_BITMAP_CHUNK_SZ) / 8) + + extern unsigned long kern_linear_pte_xor[4]; +-extern unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; + extern unsigned int sparc64_highest_unlocked_tlb_ent; + extern unsigned long sparc64_kern_pri_context; + extern unsigned long sparc64_kern_pri_nuc_bits; +@@ -38,15 +31,4 @@ extern unsigned long kern_locked_tte_data; + + extern void prom_world(int enter); + +-#ifdef CONFIG_SPARSEMEM_VMEMMAP +-#define VMEMMAP_CHUNK_SHIFT 22 +-#define VMEMMAP_CHUNK (1UL << VMEMMAP_CHUNK_SHIFT) +-#define VMEMMAP_CHUNK_MASK ~(VMEMMAP_CHUNK - 1UL) +-#define VMEMMAP_ALIGN(x) (((x)+VMEMMAP_CHUNK-1UL)&VMEMMAP_CHUNK_MASK) +- +-#define VMEMMAP_SIZE ((((1UL << MAX_PHYSADDR_BITS) >> PAGE_SHIFT) * \ +- sizeof(struct page)) >> VMEMMAP_CHUNK_SHIFT) +-extern unsigned long vmemmap_table[VMEMMAP_SIZE]; +-#endif +- + #endif /* _SPARC64_MM_INIT_H */ +diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c +index cfbe53c..09daebd 100644 +--- a/arch/sparc/mm/srmmu.c ++++ b/arch/sparc/mm/srmmu.c +@@ -460,10 +460,12 @@ static void __init sparc_context_init(int numctx) + void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, + struct task_struct *tsk) + { ++ unsigned long flags; ++ + if (mm->context == NO_CONTEXT) { +- spin_lock(&srmmu_context_spinlock); ++ spin_lock_irqsave(&srmmu_context_spinlock, flags); + alloc_context(old_mm, mm); +- spin_unlock(&srmmu_context_spinlock); ++ spin_unlock_irqrestore(&srmmu_context_spinlock, flags); + srmmu_ctxd_set(&srmmu_context_table[mm->context], mm->pgd); + } + +@@ -988,14 +990,15 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) + + void destroy_context(struct mm_struct *mm) + { ++ unsigned long flags; + + if (mm->context != NO_CONTEXT) { + flush_cache_mm(mm); + srmmu_ctxd_set(&srmmu_context_table[mm->context], srmmu_swapper_pg_dir); + flush_tlb_mm(mm); +- spin_lock(&srmmu_context_spinlock); ++ spin_lock_irqsave(&srmmu_context_spinlock, flags); + free_context(mm->context); +- spin_unlock(&srmmu_context_spinlock); ++ spin_unlock_irqrestore(&srmmu_context_spinlock, flags); + mm->context = NO_CONTEXT; + } + } +diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c +index b12cb5e..b89aba2 100644 +--- a/arch/sparc/mm/tlb.c ++++ b/arch/sparc/mm/tlb.c +@@ -134,7 +134,7 @@ no_cache_flush: + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + static void tlb_batch_pmd_scan(struct mm_struct *mm, unsigned long vaddr, +- pmd_t pmd, bool exec) ++ pmd_t pmd) + { + unsigned long end; + pte_t *pte; +@@ -142,8 +142,11 @@ static void tlb_batch_pmd_scan(struct mm_struct *mm, unsigned long vaddr, + pte = pte_offset_map(&pmd, vaddr); + end = vaddr + HPAGE_SIZE; + while (vaddr < end) { +- if (pte_val(*pte) & _PAGE_VALID) ++ if (pte_val(*pte) & _PAGE_VALID) { ++ bool exec = pte_exec(*pte); ++ + tlb_batch_add_one(mm, vaddr, exec); ++ } + pte++; + vaddr += PAGE_SIZE; + } +@@ -177,19 +180,30 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, + } + + if (!pmd_none(orig)) { +- pte_t orig_pte = __pte(pmd_val(orig)); +- bool exec = pte_exec(orig_pte); +- + addr &= HPAGE_MASK; + if (pmd_trans_huge(orig)) { ++ pte_t orig_pte = __pte(pmd_val(orig)); ++ bool exec = pte_exec(orig_pte); ++ + tlb_batch_add_one(mm, addr, exec); + tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec); + } else { +- tlb_batch_pmd_scan(mm, addr, orig, exec); ++ tlb_batch_pmd_scan(mm, addr, orig); + } + } + } + ++void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, ++ pmd_t *pmdp) ++{ ++ pmd_t entry = *pmdp; ++ ++ pmd_val(entry) &= ~_PAGE_VALID; ++ ++ set_pmd_at(vma->vm_mm, address, pmdp, entry); ++ flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); ++} ++ + void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp, + pgtable_t pgtable) + { +diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c +index f5d506f..fe19b81 100644 +--- a/arch/sparc/mm/tsb.c ++++ b/arch/sparc/mm/tsb.c +@@ -133,7 +133,19 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign + mm->context.tsb_block[tsb_idx].tsb_nentries = + tsb_bytes / sizeof(struct tsb); + +- base = TSBMAP_BASE; ++ switch (tsb_idx) { ++ case MM_TSB_BASE: ++ base = TSBMAP_8K_BASE; ++ break; ++#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) ++ case MM_TSB_HUGE: ++ base = TSBMAP_4M_BASE; ++ break; ++#endif ++ default: ++ BUG(); ++ } ++ + tte = pgprot_val(PAGE_KERNEL_LOCKED); + tsb_paddr = __pa(mm->context.tsb_block[tsb_idx].tsb); + BUG_ON(tsb_paddr & (tsb_bytes - 1UL)); +diff --git a/arch/sparc/power/hibernate.c b/arch/sparc/power/hibernate.c +index 42b0b8c..17bd2e1 100644 +--- a/arch/sparc/power/hibernate.c ++++ b/arch/sparc/power/hibernate.c +@@ -9,11 +9,9 @@ + #include + #include + #include ++#include + #include + +-/* References to section boundaries */ +-extern const void __nosave_begin, __nosave_end; +- + struct saved_context saved_context; + + /* +diff --git a/arch/sparc/power/hibernate_asm.S b/arch/sparc/power/hibernate_asm.S +index 7994216..d7d9017 100644 +--- a/arch/sparc/power/hibernate_asm.S ++++ b/arch/sparc/power/hibernate_asm.S +@@ -54,8 +54,8 @@ ENTRY(swsusp_arch_resume) + nop + + /* Write PAGE_OFFSET to %g7 */ +- sethi %uhi(PAGE_OFFSET), %g7 +- sllx %g7, 32, %g7 ++ sethi %hi(PAGE_OFFSET), %g7 ++ ldx [%g7 + %lo(PAGE_OFFSET)], %g7 + + setuw (PAGE_SIZE-8), %g3 + +diff --git a/arch/sparc/prom/bootstr_64.c b/arch/sparc/prom/bootstr_64.c +index ab9ccc6..7149e77 100644 +--- a/arch/sparc/prom/bootstr_64.c ++++ b/arch/sparc/prom/bootstr_64.c +@@ -14,7 +14,10 @@ + * the .bss section or it will break things. + */ + +-#define BARG_LEN 256 ++/* We limit BARG_LEN to 1024 because this is the size of the ++ * 'barg_out' command line buffer in the SILO bootloader. ++ */ ++#define BARG_LEN 1024 + struct { + int bootstr_len; + int bootstr_valid; +diff --git a/arch/sparc/prom/cif.S b/arch/sparc/prom/cif.S +index 9c86b4b..8050f38 100644 +--- a/arch/sparc/prom/cif.S ++++ b/arch/sparc/prom/cif.S +@@ -11,11 +11,10 @@ + .text + .globl prom_cif_direct + prom_cif_direct: ++ save %sp, -192, %sp + sethi %hi(p1275buf), %o1 + or %o1, %lo(p1275buf), %o1 +- ldx [%o1 + 0x0010], %o2 ! prom_cif_stack +- save %o2, -192, %sp +- ldx [%i1 + 0x0008], %l2 ! prom_cif_handler ++ ldx [%o1 + 0x0008], %l2 ! prom_cif_handler + mov %g4, %l0 + mov %g5, %l1 + mov %g6, %l3 +diff --git a/arch/sparc/prom/init_64.c b/arch/sparc/prom/init_64.c +index d95db75..110b0d7 100644 +--- a/arch/sparc/prom/init_64.c ++++ b/arch/sparc/prom/init_64.c +@@ -26,13 +26,13 @@ phandle prom_chosen_node; + * It gets passed the pointer to the PROM vector. + */ + +-extern void prom_cif_init(void *, void *); ++extern void prom_cif_init(void *); + +-void __init prom_init(void *cif_handler, void *cif_stack) ++void __init prom_init(void *cif_handler) + { + phandle node; + +- prom_cif_init(cif_handler, cif_stack); ++ prom_cif_init(cif_handler); + + prom_chosen_node = prom_finddevice(prom_chosen_path); + if (!prom_chosen_node || (s32)prom_chosen_node == -1) +diff --git a/arch/sparc/prom/p1275.c b/arch/sparc/prom/p1275.c +index e58b817..545d8bb 100644 +--- a/arch/sparc/prom/p1275.c ++++ b/arch/sparc/prom/p1275.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -19,7 +20,6 @@ + struct { + long prom_callback; /* 0x00 */ + void (*prom_cif_handler)(long *); /* 0x08 */ +- unsigned long prom_cif_stack; /* 0x10 */ + } p1275buf; + + extern void prom_world(int); +@@ -36,8 +36,8 @@ void p1275_cmd_direct(unsigned long *args) + { + unsigned long flags; + +- raw_local_save_flags(flags); +- raw_local_irq_restore((unsigned long)PIL_NMI); ++ local_save_flags(flags); ++ local_irq_restore((unsigned long)PIL_NMI); + raw_spin_lock(&prom_entry_lock); + + prom_world(1); +@@ -45,11 +45,10 @@ void p1275_cmd_direct(unsigned long *args) + prom_world(0); + + raw_spin_unlock(&prom_entry_lock); +- raw_local_irq_restore(flags); ++ local_irq_restore(flags); + } + + void prom_cif_init(void *cif_handler, void *cif_stack) + { + p1275buf.prom_cif_handler = (void (*)(long *))cif_handler; +- p1275buf.prom_cif_stack = (unsigned long)cif_stack; + } +diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c +index 74c9172..bdb3ecf 100644 +--- a/arch/tile/kernel/setup.c ++++ b/arch/tile/kernel/setup.c +@@ -1146,7 +1146,7 @@ static void __init load_hv_initrd(void) + + void __init free_initrd_mem(unsigned long begin, unsigned long end) + { +- free_bootmem(__pa(begin), end - begin); ++ free_bootmem_late(__pa(begin), end - begin); + } + + static int __init setup_initrd(char *str) +diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c +index 6c05712..c6d2a76 100644 +--- a/arch/tile/mm/fault.c ++++ b/arch/tile/mm/fault.c +@@ -444,6 +444,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c +index 004ba56..33294fd 100644 +--- a/arch/tile/mm/homecache.c ++++ b/arch/tile/mm/homecache.c +@@ -417,7 +417,7 @@ void __homecache_free_pages(struct page *page, unsigned int order) + if (put_page_testzero(page)) { + homecache_change_page_home(page, order, PAGE_HOME_HASH); + if (order == 0) { +- free_hot_cold_page(page, 0); ++ free_hot_cold_page(page, false); + } else { + init_page_count(page); + __free_pages(page, order); +diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common +index 21ca44c..1f0ea55 100644 +--- a/arch/um/Kconfig.common ++++ b/arch/um/Kconfig.common +@@ -2,6 +2,7 @@ config UML + bool + default y + select HAVE_UID16 ++ select HAVE_FUTEX_CMPXCHG if FUTEX + select GENERIC_IRQ_SHOW + select GENERIC_CPU_DEVICES + select GENERIC_IO +diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c +index 3716e69..e8ab93c 100644 +--- a/arch/um/drivers/ubd_kern.c ++++ b/arch/um/drivers/ubd_kern.c +@@ -1277,7 +1277,7 @@ static void do_ubd_request(struct request_queue *q) + + while(1){ + struct ubd *dev = q->queuedata; +- if(dev->end_sg == 0){ ++ if(dev->request == NULL){ + struct request *req = blk_fetch_request(q); + if(req == NULL) + return; +@@ -1299,7 +1299,8 @@ static void do_ubd_request(struct request_queue *q) + return; + } + prepare_flush_request(req, io_req); +- submit_request(io_req, dev); ++ if (submit_request(io_req, dev) == false) ++ return; + } + + while(dev->start_sg < dev->end_sg){ +diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c +index 974b874..53b8320 100644 +--- a/arch/um/kernel/trap.c ++++ b/arch/um/kernel/trap.c +@@ -80,6 +80,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) { + goto out_of_memory; ++ } else if (fault & VM_FAULT_SIGSEGV) { ++ goto out; + } else if (fault & VM_FAULT_SIGBUS) { + err = -EACCES; + goto out; +diff --git a/arch/unicore32/include/asm/mmu_context.h b/arch/unicore32/include/asm/mmu_context.h +index fb5e4c6..ef470a7 100644 +--- a/arch/unicore32/include/asm/mmu_context.h ++++ b/arch/unicore32/include/asm/mmu_context.h +@@ -14,6 +14,8 @@ + + #include + #include ++#include ++#include + #include + + #include +@@ -73,7 +75,7 @@ do { \ + else \ + mm->mmap = NULL; \ + rb_erase(&high_vma->vm_rb, &mm->mm_rb); \ +- mm->mmap_cache = NULL; \ ++ vmacache_invalidate(mm); \ + mm->map_count--; \ + remove_vma(high_vma); \ + } \ +diff --git a/arch/unicore32/include/mach/pm.h b/arch/unicore32/include/mach/pm.h +index 4dcd34a..77b5226 100644 +--- a/arch/unicore32/include/mach/pm.h ++++ b/arch/unicore32/include/mach/pm.h +@@ -36,8 +36,5 @@ extern int puv3_pm_enter(suspend_state_t state); + /* Defined in hibernate_asm.S */ + extern int restore_image(pgd_t *resume_pg_dir, struct pbe *restore_pblist); + +-/* References to section boundaries */ +-extern const void __nosave_begin, __nosave_end; +- + extern struct pbe *restore_pblist; + #endif +diff --git a/arch/unicore32/kernel/hibernate.c b/arch/unicore32/kernel/hibernate.c +index d75ef8b..9969ec3 100644 +--- a/arch/unicore32/kernel/hibernate.c ++++ b/arch/unicore32/kernel/hibernate.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + + #include "mach/pm.h" +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index 7324107..96e743a 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -160,7 +160,7 @@ config SBUS + + config NEED_DMA_MAP_STATE + def_bool y +- depends on X86_64 || INTEL_IOMMU || DMA_API_DEBUG ++ depends on X86_64 || INTEL_IOMMU || DMA_API_DEBUG || SWIOTLB + + config NEED_SG_DMA_LENGTH + def_bool y +@@ -854,7 +854,7 @@ source "kernel/Kconfig.preempt" + + config X86_UP_APIC + bool "Local APIC support on uniprocessors" +- depends on X86_32 && !SMP && !X86_32_NON_STANDARD && !PCI_MSI ++ depends on X86_32 && !SMP && !X86_32_NON_STANDARD + ---help--- + A local APIC (Advanced Programmable Interrupt Controller) is an + integrated interrupt controller in the CPU. If you have a single-CPU +@@ -865,6 +865,10 @@ config X86_UP_APIC + performance counters), and the NMI watchdog which detects hard + lockups. + ++config X86_UP_APIC_MSI ++ def_bool y ++ select X86_UP_APIC if X86_32 && !SMP && !X86_32_NON_STANDARD && PCI_MSI ++ + config X86_UP_IOAPIC + bool "IO-APIC support on uniprocessors" + depends on X86_UP_APIC +@@ -966,10 +970,27 @@ config VM86 + default y + depends on X86_32 + ---help--- +- This option is required by programs like DOSEMU to run 16-bit legacy +- code on X86 processors. It also may be needed by software like +- XFree86 to initialize some video cards via BIOS. Disabling this +- option saves about 6k. ++ This option is required by programs like DOSEMU to run ++ 16-bit real mode legacy code on x86 processors. It also may ++ be needed by software like XFree86 to initialize some video ++ cards via BIOS. Disabling this option saves about 6K. ++ ++config X86_16BIT ++ bool "Enable support for 16-bit segments" if EXPERT ++ default y ++ ---help--- ++ This option is required by programs like Wine to run 16-bit ++ protected mode legacy code on x86 processors. Disabling ++ this option saves about 300 bytes on i386, or around 6K text ++ plus 16K runtime memory on x86-64, ++ ++config X86_ESPFIX32 ++ def_bool y ++ depends on X86_16BIT && X86_32 ++ ++config X86_ESPFIX64 ++ def_bool y ++ depends on X86_16BIT && X86_64 + + config TOSHIBA + tristate "Toshiba Laptop support" +@@ -1580,6 +1601,7 @@ config EFI + config EFI_STUB + bool "EFI stub support" + depends on EFI ++ select RELOCATABLE + ---help--- + This kernel feature allows a bzImage to be loaded directly + by EFI firmware without the use of a bootloader. +@@ -2418,12 +2440,19 @@ config X86_DMA_REMAP + depends on STA2X11 + + config IOSF_MBI +- bool ++ tristate "Intel System On Chip IOSF Sideband support" + depends on PCI + ---help--- +- To be selected by modules requiring access to the Intel OnChip System +- Fabric (IOSF) Sideband MailBox Interface (MBI). For MBI platforms +- enumerable by PCI. ++ Enables sideband access to mailbox registers on SoC's. The sideband is ++ available on the following platforms. This list is not meant to be ++ exclusive. ++ - BayTrail ++ - Cherryview ++ - Braswell ++ - Quark ++ ++ You should say Y if you are running a kernel on one of these ++ platforms. + + source "net/Kconfig" + +diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile +index 0fcd913..67e9f5c 100644 +--- a/arch/x86/boot/compressed/Makefile ++++ b/arch/x86/boot/compressed/Makefile +@@ -75,8 +75,10 @@ suffix-$(CONFIG_KERNEL_XZ) := xz + suffix-$(CONFIG_KERNEL_LZO) := lzo + suffix-$(CONFIG_KERNEL_LZ4) := lz4 + ++RUN_SIZE = $(shell $(OBJDUMP) -h vmlinux | \ ++ $(CONFIG_SHELL) $(srctree)/arch/x86/tools/calc_run_size.sh) + quiet_cmd_mkpiggy = MKPIGGY $@ +- cmd_mkpiggy = $(obj)/mkpiggy $< > $@ || ( rm -f $@ ; false ) ++ cmd_mkpiggy = $(obj)/mkpiggy $< $(RUN_SIZE) > $@ || ( rm -f $@ ; false ) + + targets += piggy.S + $(obj)/piggy.S: $(obj)/vmlinux.bin.$(suffix-y) $(obj)/mkpiggy FORCE +diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c +index 4dbf967..6cfcf2a 100644 +--- a/arch/x86/boot/compressed/aslr.c ++++ b/arch/x86/boot/compressed/aslr.c +@@ -183,12 +183,27 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size, + static bool mem_avoid_overlap(struct mem_vector *img) + { + int i; ++ struct setup_data *ptr; + + for (i = 0; i < MEM_AVOID_MAX; i++) { + if (mem_overlaps(img, &mem_avoid[i])) + return true; + } + ++ /* Avoid all entries in the setup_data linked list. */ ++ ptr = (struct setup_data *)(unsigned long)real_mode->hdr.setup_data; ++ while (ptr) { ++ struct mem_vector avoid; ++ ++ avoid.start = (u64)ptr; ++ avoid.size = sizeof(*ptr) + ptr->len; ++ ++ if (mem_overlaps(img, &avoid)) ++ return true; ++ ++ ptr = (struct setup_data *)(unsigned long)ptr->next; ++ } ++ + return false; + } + +diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c +index 78cbb2d..ec5a3c7 100644 +--- a/arch/x86/boot/compressed/eboot.c ++++ b/arch/x86/boot/compressed/eboot.c +@@ -560,6 +560,10 @@ static efi_status_t setup_e820(struct boot_params *params, + unsigned int e820_type = 0; + unsigned long m = efi->efi_memmap; + ++#ifdef CONFIG_X86_64 ++ m |= (u64)efi->efi_memmap_hi << 32; ++#endif ++ + d = (efi_memory_desc_t *)(m + (i * efi->efi_memdesc_size)); + switch (d->type) { + case EFI_RESERVED_TYPE: +diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S +index f45ab7a..a814c80 100644 +--- a/arch/x86/boot/compressed/head_32.S ++++ b/arch/x86/boot/compressed/head_32.S +@@ -54,7 +54,7 @@ ENTRY(efi_pe_entry) + call reloc + reloc: + popl %ecx +- subl reloc, %ecx ++ subl $reloc, %ecx + movl %ecx, BP_code32_start(%eax) + + sub $0x4, %esp +@@ -186,7 +186,8 @@ relocated: + * Do the decompression, and jump to the new kernel.. + */ + /* push arguments for decompress_kernel: */ +- pushl $z_output_len /* decompressed length */ ++ pushl $z_run_size /* size of kernel with .bss and .brk */ ++ pushl $z_output_len /* decompressed length, end of relocs */ + leal z_extract_offset_negative(%ebx), %ebp + pushl %ebp /* output address */ + pushl $z_input_len /* input_len */ +@@ -196,7 +197,7 @@ relocated: + pushl %eax /* heap area */ + pushl %esi /* real mode pointer */ + call decompress_kernel /* returns kernel location in %eax */ +- addl $24, %esp ++ addl $28, %esp + + /* + * Jump to the decompressed kernel. +diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S +index b10fa66..34bbc09 100644 +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -334,13 +334,16 @@ relocated: + * Do the decompression, and jump to the new kernel.. + */ + pushq %rsi /* Save the real mode argument */ ++ movq $z_run_size, %r9 /* size of kernel with .bss and .brk */ ++ pushq %r9 + movq %rsi, %rdi /* real mode address */ + leaq boot_heap(%rip), %rsi /* malloc area for uncompression */ + leaq input_data(%rip), %rdx /* input_data */ + movl $z_input_len, %ecx /* input_len */ + movq %rbp, %r8 /* output target address */ +- movq $z_output_len, %r9 /* decompressed length */ ++ movq $z_output_len, %r9 /* decompressed length, end of relocs */ + call decompress_kernel /* returns kernel location in %rax */ ++ popq %r9 + popq %rsi + + /* +diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c +index 196eaf3..8f45c85 100644 +--- a/arch/x86/boot/compressed/misc.c ++++ b/arch/x86/boot/compressed/misc.c +@@ -393,8 +393,11 @@ asmlinkage void *decompress_kernel(void *rmode, memptr heap, + unsigned char *input_data, + unsigned long input_len, + unsigned char *output, +- unsigned long output_len) ++ unsigned long output_len, ++ unsigned long run_size) + { ++ unsigned char *output_orig = output; ++ + real_mode = rmode; + + sanitize_boot_params(real_mode); +@@ -416,8 +419,14 @@ asmlinkage void *decompress_kernel(void *rmode, memptr heap, + free_mem_ptr = heap; /* Heap */ + free_mem_end_ptr = heap + BOOT_HEAP_SIZE; + +- output = choose_kernel_location(input_data, input_len, +- output, output_len); ++ /* ++ * The memory hole needed for the kernel is the larger of either ++ * the entire decompressed kernel plus relocation table, or the ++ * entire decompressed kernel plus .bss and .brk sections. ++ */ ++ output = choose_kernel_location(input_data, input_len, output, ++ output_len > run_size ? output_len ++ : run_size); + + /* Validate memory location choices. */ + if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1)) +@@ -437,7 +446,12 @@ asmlinkage void *decompress_kernel(void *rmode, memptr heap, + debug_putstr("\nDecompressing Linux... "); + decompress(input_data, input_len, NULL, NULL, output, NULL, error); + parse_elf(output); +- handle_relocations(output, output_len); ++ /* ++ * 32-bit always performs relocations. 64-bit relocations are only ++ * needed if kASLR has chosen a different load address. ++ */ ++ if (!IS_ENABLED(CONFIG_X86_64) || output != output_orig) ++ handle_relocations(output, output_len); + debug_putstr("done.\nBooting the kernel.\n"); + return output; + } +diff --git a/arch/x86/boot/compressed/mkpiggy.c b/arch/x86/boot/compressed/mkpiggy.c +index b669ab6..d8222f2 100644 +--- a/arch/x86/boot/compressed/mkpiggy.c ++++ b/arch/x86/boot/compressed/mkpiggy.c +@@ -36,11 +36,13 @@ int main(int argc, char *argv[]) + uint32_t olen; + long ilen; + unsigned long offs; ++ unsigned long run_size; + FILE *f = NULL; + int retval = 1; + +- if (argc < 2) { +- fprintf(stderr, "Usage: %s compressed_file\n", argv[0]); ++ if (argc < 3) { ++ fprintf(stderr, "Usage: %s compressed_file run_size\n", ++ argv[0]); + goto bail; + } + +@@ -74,6 +76,7 @@ int main(int argc, char *argv[]) + offs += olen >> 12; /* Add 8 bytes for each 32K block */ + offs += 64*1024 + 128; /* Add 64K + 128 bytes slack */ + offs = (offs+4095) & ~4095; /* Round to a 4K boundary */ ++ run_size = atoi(argv[2]); + + printf(".section \".rodata..compressed\",\"a\",@progbits\n"); + printf(".globl z_input_len\n"); +@@ -85,6 +88,8 @@ int main(int argc, char *argv[]) + /* z_extract_offset_negative allows simplification of head_32.S */ + printf(".globl z_extract_offset_negative\n"); + printf("z_extract_offset_negative = -0x%lx\n", offs); ++ printf(".globl z_run_size\n"); ++ printf("z_run_size = %lu\n", run_size); + + printf(".globl input_data, input_data_end\n"); + printf("input_data:\n"); +diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S +index ec3b8ba..04da6c2 100644 +--- a/arch/x86/boot/header.S ++++ b/arch/x86/boot/header.S +@@ -91,10 +91,9 @@ bs_die: + + .section ".bsdata", "a" + bugger_off_msg: +- .ascii "Direct floppy boot is not supported. " +- .ascii "Use a boot loader program instead.\r\n" ++ .ascii "Use a boot loader.\r\n" + .ascii "\n" +- .ascii "Remove disk and press any key to reboot ...\r\n" ++ .ascii "Remove disk and press any key to reboot...\r\n" + .byte 0 + + #ifdef CONFIG_EFI_STUB +@@ -108,7 +107,7 @@ coff_header: + #else + .word 0x8664 # x86-64 + #endif +- .word 3 # nr_sections ++ .word 4 # nr_sections + .long 0 # TimeDateStamp + .long 0 # PointerToSymbolTable + .long 1 # NumberOfSymbols +@@ -250,6 +249,25 @@ section_table: + .word 0 # NumberOfLineNumbers + .long 0x60500020 # Characteristics (section flags) + ++ # ++ # The offset & size fields are filled in by build.c. ++ # ++ .ascii ".bss" ++ .byte 0 ++ .byte 0 ++ .byte 0 ++ .byte 0 ++ .long 0 ++ .long 0x0 ++ .long 0 # Size of initialized data ++ # on disk ++ .long 0x0 ++ .long 0 # PointerToRelocations ++ .long 0 # PointerToLineNumbers ++ .word 0 # NumberOfRelocations ++ .word 0 # NumberOfLineNumbers ++ .long 0xc8000080 # Characteristics (section flags) ++ + #endif /* CONFIG_EFI_STUB */ + + # Kernel attributes; used by setup. This is part 1 of the +diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c +index 8e15b22..3dafaeb 100644 +--- a/arch/x86/boot/tools/build.c ++++ b/arch/x86/boot/tools/build.c +@@ -142,7 +142,7 @@ static void usage(void) + + #ifdef CONFIG_EFI_STUB + +-static void update_pecoff_section_header(char *section_name, u32 offset, u32 size) ++static void update_pecoff_section_header_fields(char *section_name, u32 vma, u32 size, u32 datasz, u32 offset) + { + unsigned int pe_header; + unsigned short num_sections; +@@ -163,10 +163,10 @@ static void update_pecoff_section_header(char *section_name, u32 offset, u32 siz + put_unaligned_le32(size, section + 0x8); + + /* section header vma field */ +- put_unaligned_le32(offset, section + 0xc); ++ put_unaligned_le32(vma, section + 0xc); + + /* section header 'size of initialised data' field */ +- put_unaligned_le32(size, section + 0x10); ++ put_unaligned_le32(datasz, section + 0x10); + + /* section header 'file offset' field */ + put_unaligned_le32(offset, section + 0x14); +@@ -178,6 +178,11 @@ static void update_pecoff_section_header(char *section_name, u32 offset, u32 siz + } + } + ++static void update_pecoff_section_header(char *section_name, u32 offset, u32 size) ++{ ++ update_pecoff_section_header_fields(section_name, offset, size, size, offset); ++} ++ + static void update_pecoff_setup_and_reloc(unsigned int size) + { + u32 setup_offset = 0x200; +@@ -202,9 +207,6 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz) + + pe_header = get_unaligned_le32(&buf[0x3c]); + +- /* Size of image */ +- put_unaligned_le32(file_sz, &buf[pe_header + 0x50]); +- + /* + * Size of code: Subtract the size of the first sector (512 bytes) + * which includes the header. +@@ -219,6 +221,22 @@ static void update_pecoff_text(unsigned int text_start, unsigned int file_sz) + update_pecoff_section_header(".text", text_start, text_sz); + } + ++static void update_pecoff_bss(unsigned int file_sz, unsigned int init_sz) ++{ ++ unsigned int pe_header; ++ unsigned int bss_sz = init_sz - file_sz; ++ ++ pe_header = get_unaligned_le32(&buf[0x3c]); ++ ++ /* Size of uninitialized data */ ++ put_unaligned_le32(bss_sz, &buf[pe_header + 0x24]); ++ ++ /* Size of image */ ++ put_unaligned_le32(init_sz, &buf[pe_header + 0x50]); ++ ++ update_pecoff_section_header_fields(".bss", file_sz, bss_sz, 0, 0); ++} ++ + #endif /* CONFIG_EFI_STUB */ + + +@@ -270,6 +288,9 @@ int main(int argc, char ** argv) + int fd; + void *kernel; + u32 crc = 0xffffffffUL; ++#ifdef CONFIG_EFI_STUB ++ unsigned int init_sz; ++#endif + + /* Defaults for old kernel */ + #ifdef CONFIG_X86_32 +@@ -343,7 +364,9 @@ int main(int argc, char ** argv) + put_unaligned_le32(sys_size, &buf[0x1f4]); + + #ifdef CONFIG_EFI_STUB +- update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz)); ++ update_pecoff_text(setup_sectors * 512, i + (sys_size * 16)); ++ init_sz = get_unaligned_le32(&buf[0x260]); ++ update_pecoff_bss(i + (sys_size * 16), init_sz); + + #ifdef CONFIG_X86_64 /* Yes, this is really how we defined it :( */ + efi_stub_entry -= 0x200; +diff --git a/arch/x86/crypto/aes_glue.c b/arch/x86/crypto/aes_glue.c +index aafe8ce..e26984f 100644 +--- a/arch/x86/crypto/aes_glue.c ++++ b/arch/x86/crypto/aes_glue.c +@@ -66,5 +66,5 @@ module_exit(aes_fini); + + MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, asm optimized"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("aes"); +-MODULE_ALIAS("aes-asm"); ++MODULE_ALIAS_CRYPTO("aes"); ++MODULE_ALIAS_CRYPTO("aes-asm"); +diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c +index 948ad0e..6d4faba 100644 +--- a/arch/x86/crypto/aesni-intel_glue.c ++++ b/arch/x86/crypto/aesni-intel_glue.c +@@ -1109,7 +1109,7 @@ static int __driver_rfc4106_decrypt(struct aead_request *req) + src = kmalloc(req->cryptlen + req->assoclen, GFP_ATOMIC); + if (!src) + return -ENOMEM; +- assoc = (src + req->cryptlen + auth_tag_len); ++ assoc = (src + req->cryptlen); + scatterwalk_map_and_copy(src, req->src, 0, req->cryptlen, 0); + scatterwalk_map_and_copy(assoc, req->assoc, 0, + req->assoclen, 0); +@@ -1134,7 +1134,7 @@ static int __driver_rfc4106_decrypt(struct aead_request *req) + scatterwalk_done(&src_sg_walk, 0, 0); + scatterwalk_done(&assoc_sg_walk, 0, 0); + } else { +- scatterwalk_map_and_copy(dst, req->dst, 0, req->cryptlen, 1); ++ scatterwalk_map_and_copy(dst, req->dst, 0, tempCipherLen, 1); + kfree(src); + } + return retval; +@@ -1514,4 +1514,4 @@ module_exit(aesni_exit); + + MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, Intel AES-NI instructions optimized"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("aes"); ++MODULE_ALIAS_CRYPTO("aes"); +diff --git a/arch/x86/crypto/blowfish_glue.c b/arch/x86/crypto/blowfish_glue.c +index 50ec333..1477cfc 100644 +--- a/arch/x86/crypto/blowfish_glue.c ++++ b/arch/x86/crypto/blowfish_glue.c +@@ -481,5 +481,5 @@ module_exit(fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Blowfish Cipher Algorithm, asm optimized"); +-MODULE_ALIAS("blowfish"); +-MODULE_ALIAS("blowfish-asm"); ++MODULE_ALIAS_CRYPTO("blowfish"); ++MODULE_ALIAS_CRYPTO("blowfish-asm"); +diff --git a/arch/x86/crypto/camellia_aesni_avx2_glue.c b/arch/x86/crypto/camellia_aesni_avx2_glue.c +index 4209a76..9a07faf 100644 +--- a/arch/x86/crypto/camellia_aesni_avx2_glue.c ++++ b/arch/x86/crypto/camellia_aesni_avx2_glue.c +@@ -582,5 +582,5 @@ module_exit(camellia_aesni_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Camellia Cipher Algorithm, AES-NI/AVX2 optimized"); +-MODULE_ALIAS("camellia"); +-MODULE_ALIAS("camellia-asm"); ++MODULE_ALIAS_CRYPTO("camellia"); ++MODULE_ALIAS_CRYPTO("camellia-asm"); +diff --git a/arch/x86/crypto/camellia_aesni_avx_glue.c b/arch/x86/crypto/camellia_aesni_avx_glue.c +index 87a041a..ed38d95 100644 +--- a/arch/x86/crypto/camellia_aesni_avx_glue.c ++++ b/arch/x86/crypto/camellia_aesni_avx_glue.c +@@ -574,5 +574,5 @@ module_exit(camellia_aesni_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Camellia Cipher Algorithm, AES-NI/AVX optimized"); +-MODULE_ALIAS("camellia"); +-MODULE_ALIAS("camellia-asm"); ++MODULE_ALIAS_CRYPTO("camellia"); ++MODULE_ALIAS_CRYPTO("camellia-asm"); +diff --git a/arch/x86/crypto/camellia_glue.c b/arch/x86/crypto/camellia_glue.c +index c171dcb..5c8b626 100644 +--- a/arch/x86/crypto/camellia_glue.c ++++ b/arch/x86/crypto/camellia_glue.c +@@ -1725,5 +1725,5 @@ module_exit(fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Camellia Cipher Algorithm, asm optimized"); +-MODULE_ALIAS("camellia"); +-MODULE_ALIAS("camellia-asm"); ++MODULE_ALIAS_CRYPTO("camellia"); ++MODULE_ALIAS_CRYPTO("camellia-asm"); +diff --git a/arch/x86/crypto/cast5_avx_glue.c b/arch/x86/crypto/cast5_avx_glue.c +index e6a3700..f62e9db 100644 +--- a/arch/x86/crypto/cast5_avx_glue.c ++++ b/arch/x86/crypto/cast5_avx_glue.c +@@ -494,4 +494,4 @@ module_exit(cast5_exit); + + MODULE_DESCRIPTION("Cast5 Cipher Algorithm, AVX optimized"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("cast5"); ++MODULE_ALIAS_CRYPTO("cast5"); +diff --git a/arch/x86/crypto/cast6_avx_glue.c b/arch/x86/crypto/cast6_avx_glue.c +index 09f3677..0160f68 100644 +--- a/arch/x86/crypto/cast6_avx_glue.c ++++ b/arch/x86/crypto/cast6_avx_glue.c +@@ -611,4 +611,4 @@ module_exit(cast6_exit); + + MODULE_DESCRIPTION("Cast6 Cipher Algorithm, AVX optimized"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("cast6"); ++MODULE_ALIAS_CRYPTO("cast6"); +diff --git a/arch/x86/crypto/crc32-pclmul_glue.c b/arch/x86/crypto/crc32-pclmul_glue.c +index 9d014a7..1937fc1 100644 +--- a/arch/x86/crypto/crc32-pclmul_glue.c ++++ b/arch/x86/crypto/crc32-pclmul_glue.c +@@ -197,5 +197,5 @@ module_exit(crc32_pclmul_mod_fini); + MODULE_AUTHOR("Alexander Boyko "); + MODULE_LICENSE("GPL"); + +-MODULE_ALIAS("crc32"); +-MODULE_ALIAS("crc32-pclmul"); ++MODULE_ALIAS_CRYPTO("crc32"); ++MODULE_ALIAS_CRYPTO("crc32-pclmul"); +diff --git a/arch/x86/crypto/crc32c-intel_glue.c b/arch/x86/crypto/crc32c-intel_glue.c +index 6812ad9..28640c3 100644 +--- a/arch/x86/crypto/crc32c-intel_glue.c ++++ b/arch/x86/crypto/crc32c-intel_glue.c +@@ -280,5 +280,5 @@ MODULE_AUTHOR("Austin Zhang , Kent Liu "); + MODULE_DESCRIPTION("T10 DIF CRC calculation accelerated with PCLMULQDQ."); + MODULE_LICENSE("GPL"); + +-MODULE_ALIAS("crct10dif"); +-MODULE_ALIAS("crct10dif-pclmul"); ++MODULE_ALIAS_CRYPTO("crct10dif"); ++MODULE_ALIAS_CRYPTO("crct10dif-pclmul"); +diff --git a/arch/x86/crypto/fpu.c b/arch/x86/crypto/fpu.c +index 98d7a18..f368ba2 100644 +--- a/arch/x86/crypto/fpu.c ++++ b/arch/x86/crypto/fpu.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + + struct crypto_fpu_ctx { +@@ -159,3 +160,5 @@ void __exit crypto_fpu_exit(void) + { + crypto_unregister_template(&crypto_fpu_tmpl); + } ++ ++MODULE_ALIAS_CRYPTO("fpu"); +diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c +index d785cf2..4bcf841 100644 +--- a/arch/x86/crypto/ghash-clmulni-intel_glue.c ++++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c +@@ -291,6 +291,7 @@ static struct ahash_alg ghash_async_alg = { + .cra_name = "ghash", + .cra_driver_name = "ghash-clmulni", + .cra_priority = 400, ++ .cra_ctxsize = sizeof(struct ghash_async_ctx), + .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC, + .cra_blocksize = GHASH_BLOCK_SIZE, + .cra_type = &crypto_ahash_type, +@@ -341,4 +342,4 @@ module_exit(ghash_pclmulqdqni_mod_exit); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("GHASH Message Digest Algorithm, " + "acclerated by PCLMULQDQ-NI"); +-MODULE_ALIAS("ghash"); ++MODULE_ALIAS_CRYPTO("ghash"); +diff --git a/arch/x86/crypto/salsa20_glue.c b/arch/x86/crypto/salsa20_glue.c +index 5e8e677..399a29d 100644 +--- a/arch/x86/crypto/salsa20_glue.c ++++ b/arch/x86/crypto/salsa20_glue.c +@@ -119,5 +119,5 @@ module_exit(fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION ("Salsa20 stream cipher algorithm (optimized assembly version)"); +-MODULE_ALIAS("salsa20"); +-MODULE_ALIAS("salsa20-asm"); ++MODULE_ALIAS_CRYPTO("salsa20"); ++MODULE_ALIAS_CRYPTO("salsa20-asm"); +diff --git a/arch/x86/crypto/serpent_avx2_glue.c b/arch/x86/crypto/serpent_avx2_glue.c +index 2fae489..437e47a 100644 +--- a/arch/x86/crypto/serpent_avx2_glue.c ++++ b/arch/x86/crypto/serpent_avx2_glue.c +@@ -558,5 +558,5 @@ module_exit(fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Serpent Cipher Algorithm, AVX2 optimized"); +-MODULE_ALIAS("serpent"); +-MODULE_ALIAS("serpent-asm"); ++MODULE_ALIAS_CRYPTO("serpent"); ++MODULE_ALIAS_CRYPTO("serpent-asm"); +diff --git a/arch/x86/crypto/serpent_avx_glue.c b/arch/x86/crypto/serpent_avx_glue.c +index ff48708..7e21739 100644 +--- a/arch/x86/crypto/serpent_avx_glue.c ++++ b/arch/x86/crypto/serpent_avx_glue.c +@@ -617,4 +617,4 @@ module_exit(serpent_exit); + + MODULE_DESCRIPTION("Serpent Cipher Algorithm, AVX optimized"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("serpent"); ++MODULE_ALIAS_CRYPTO("serpent"); +diff --git a/arch/x86/crypto/serpent_sse2_glue.c b/arch/x86/crypto/serpent_sse2_glue.c +index 8c95f86..bf025ad 100644 +--- a/arch/x86/crypto/serpent_sse2_glue.c ++++ b/arch/x86/crypto/serpent_sse2_glue.c +@@ -618,4 +618,4 @@ module_exit(serpent_sse2_exit); + + MODULE_DESCRIPTION("Serpent Cipher Algorithm, SSE2 optimized"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("serpent"); ++MODULE_ALIAS_CRYPTO("serpent"); +diff --git a/arch/x86/crypto/sha1_ssse3_glue.c b/arch/x86/crypto/sha1_ssse3_glue.c +index 4a11a9d..29e1060 100644 +--- a/arch/x86/crypto/sha1_ssse3_glue.c ++++ b/arch/x86/crypto/sha1_ssse3_glue.c +@@ -237,4 +237,4 @@ module_exit(sha1_ssse3_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, Supplemental SSE3 accelerated"); + +-MODULE_ALIAS("sha1"); ++MODULE_ALIAS_CRYPTO("sha1"); +diff --git a/arch/x86/crypto/sha256_ssse3_glue.c b/arch/x86/crypto/sha256_ssse3_glue.c +index f248546..4dc100d 100644 +--- a/arch/x86/crypto/sha256_ssse3_glue.c ++++ b/arch/x86/crypto/sha256_ssse3_glue.c +@@ -318,5 +318,5 @@ module_exit(sha256_ssse3_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm, Supplemental SSE3 accelerated"); + +-MODULE_ALIAS("sha256"); +-MODULE_ALIAS("sha224"); ++MODULE_ALIAS_CRYPTO("sha256"); ++MODULE_ALIAS_CRYPTO("sha224"); +diff --git a/arch/x86/crypto/sha512_ssse3_glue.c b/arch/x86/crypto/sha512_ssse3_glue.c +index 8626b03..26a5898 100644 +--- a/arch/x86/crypto/sha512_ssse3_glue.c ++++ b/arch/x86/crypto/sha512_ssse3_glue.c +@@ -326,5 +326,5 @@ module_exit(sha512_ssse3_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA512 Secure Hash Algorithm, Supplemental SSE3 accelerated"); + +-MODULE_ALIAS("sha512"); +-MODULE_ALIAS("sha384"); ++MODULE_ALIAS_CRYPTO("sha512"); ++MODULE_ALIAS_CRYPTO("sha384"); +diff --git a/arch/x86/crypto/twofish_avx_glue.c b/arch/x86/crypto/twofish_avx_glue.c +index 4e3c665..1ac531e 100644 +--- a/arch/x86/crypto/twofish_avx_glue.c ++++ b/arch/x86/crypto/twofish_avx_glue.c +@@ -579,4 +579,4 @@ module_exit(twofish_exit); + + MODULE_DESCRIPTION("Twofish Cipher Algorithm, AVX optimized"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("twofish"); ++MODULE_ALIAS_CRYPTO("twofish"); +diff --git a/arch/x86/crypto/twofish_glue.c b/arch/x86/crypto/twofish_glue.c +index 0a52023..77e06c2 100644 +--- a/arch/x86/crypto/twofish_glue.c ++++ b/arch/x86/crypto/twofish_glue.c +@@ -96,5 +96,5 @@ module_exit(fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION ("Twofish Cipher Algorithm, asm optimized"); +-MODULE_ALIAS("twofish"); +-MODULE_ALIAS("twofish-asm"); ++MODULE_ALIAS_CRYPTO("twofish"); ++MODULE_ALIAS_CRYPTO("twofish-asm"); +diff --git a/arch/x86/crypto/twofish_glue_3way.c b/arch/x86/crypto/twofish_glue_3way.c +index 13e63b3..56d8a08 100644 +--- a/arch/x86/crypto/twofish_glue_3way.c ++++ b/arch/x86/crypto/twofish_glue_3way.c +@@ -495,5 +495,5 @@ module_exit(fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Twofish Cipher Algorithm, 3-way parallel asm optimized"); +-MODULE_ALIAS("twofish"); +-MODULE_ALIAS("twofish-asm"); ++MODULE_ALIAS_CRYPTO("twofish"); ++MODULE_ALIAS_CRYPTO("twofish-asm"); +diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S +index 4299eb0..92a2e93 100644 +--- a/arch/x86/ia32/ia32entry.S ++++ b/arch/x86/ia32/ia32entry.S +@@ -151,6 +151,16 @@ ENTRY(ia32_sysenter_target) + 1: movl (%rbp),%ebp + _ASM_EXTABLE(1b,ia32_badarg) + ASM_CLAC ++ ++ /* ++ * Sysenter doesn't filter flags, so we need to clear NT ++ * ourselves. To save a few cycles, we can check whether ++ * NT was set instead of doing an unconditional popfq. ++ */ ++ testl $X86_EFLAGS_NT,EFLAGS-ARGOFFSET(%rsp) ++ jnz sysenter_fix_flags ++sysenter_flags_fixed: ++ + orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) + testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) + CFI_REMEMBER_STATE +@@ -184,6 +194,8 @@ sysexit_from_sys_call: + TRACE_IRQS_ON + ENABLE_INTERRUPTS_SYSEXIT32 + ++ CFI_RESTORE_STATE ++ + #ifdef CONFIG_AUDITSYSCALL + .macro auditsys_entry_common + movl %esi,%r9d /* 6th arg: 4th syscall arg */ +@@ -226,7 +238,6 @@ sysexit_from_sys_call: + .endm + + sysenter_auditsys: +- CFI_RESTORE_STATE + auditsys_entry_common + movl %ebp,%r9d /* reload 6th syscall arg */ + jmp sysenter_dispatch +@@ -235,6 +246,11 @@ sysexit_audit: + auditsys_exit sysexit_from_sys_call + #endif + ++sysenter_fix_flags: ++ pushq_cfi $(X86_EFLAGS_IF|X86_EFLAGS_FIXED) ++ popfq_cfi ++ jmp sysenter_flags_fixed ++ + sysenter_tracesys: + #ifdef CONFIG_AUDITSYSCALL + testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) +diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h +index 5f12968..1717156 100644 +--- a/arch/x86/include/asm/cpufeature.h ++++ b/arch/x86/include/asm/cpufeature.h +@@ -203,6 +203,7 @@ + #define X86_FEATURE_DECODEASSISTS (8*32+12) /* AMD Decode Assists support */ + #define X86_FEATURE_PAUSEFILTER (8*32+13) /* AMD filtered pause intercept */ + #define X86_FEATURE_PFTHRESHOLD (8*32+14) /* AMD pause filter threshold */ ++#define X86_FEATURE_VMMCALL (8*32+15) /* Prefer vmmcall to vmcall */ + + + /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ +diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h +index 50d033a..a94b82e 100644 +--- a/arch/x86/include/asm/desc.h ++++ b/arch/x86/include/asm/desc.h +@@ -251,7 +251,8 @@ static inline void native_load_tls(struct thread_struct *t, unsigned int cpu) + gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]; + } + +-#define _LDT_empty(info) \ ++/* This intentionally ignores lm, since 32-bit apps don't have that field. */ ++#define LDT_empty(info) \ + ((info)->base_addr == 0 && \ + (info)->limit == 0 && \ + (info)->contents == 0 && \ +@@ -261,11 +262,18 @@ static inline void native_load_tls(struct thread_struct *t, unsigned int cpu) + (info)->seg_not_present == 1 && \ + (info)->useable == 0) + +-#ifdef CONFIG_X86_64 +-#define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0)) +-#else +-#define LDT_empty(info) (_LDT_empty(info)) +-#endif ++/* Lots of programs expect an all-zero user_desc to mean "no segment at all". */ ++static inline bool LDT_zero(const struct user_desc *info) ++{ ++ return (info->base_addr == 0 && ++ info->limit == 0 && ++ info->contents == 0 && ++ info->read_exec_only == 0 && ++ info->seg_32bit == 0 && ++ info->limit_in_pages == 0 && ++ info->seg_not_present == 0 && ++ info->useable == 0); ++} + + static inline void clear_LDT(void) + { +diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h +index 9c999c1..01f15b2 100644 +--- a/arch/x86/include/asm/elf.h ++++ b/arch/x86/include/asm/elf.h +@@ -155,8 +155,9 @@ do { \ + #define elf_check_arch(x) \ + ((x)->e_machine == EM_X86_64) + +-#define compat_elf_check_arch(x) \ +- (elf_check_arch_ia32(x) || (x)->e_machine == EM_X86_64) ++#define compat_elf_check_arch(x) \ ++ (elf_check_arch_ia32(x) || \ ++ (IS_ENABLED(CONFIG_X86_X32_ABI) && (x)->e_machine == EM_X86_64)) + + #if __USER32_DS != __USER_DS + # error "The following code assumes __USER32_DS == __USER_DS" +diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h +index 7252cd3..6762a55 100644 +--- a/arch/x86/include/asm/fixmap.h ++++ b/arch/x86/include/asm/fixmap.h +@@ -123,14 +123,14 @@ enum fixed_addresses { + __end_of_permanent_fixed_addresses, + + /* +- * 256 temporary boot-time mappings, used by early_ioremap(), ++ * 512 temporary boot-time mappings, used by early_ioremap(), + * before ioremap() is functional. + * +- * If necessary we round it up to the next 256 pages boundary so ++ * If necessary we round it up to the next 512 pages boundary so + * that we can have a single pgd entry and a single pte table: + */ + #define NR_FIX_BTMAPS 64 +-#define FIX_BTMAPS_SLOTS 4 ++#define FIX_BTMAPS_SLOTS 8 + #define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS) + FIX_BTMAP_END = + (__end_of_permanent_fixed_addresses ^ +diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h +index cea1c76..1ac1c00 100644 +--- a/arch/x86/include/asm/fpu-internal.h ++++ b/arch/x86/include/asm/fpu-internal.h +@@ -368,7 +368,7 @@ static inline void drop_fpu(struct task_struct *tsk) + preempt_disable(); + tsk->thread.fpu_counter = 0; + __drop_fpu(tsk); +- clear_used_math(); ++ clear_stopped_child_used_math(tsk); + preempt_enable(); + } + +diff --git a/arch/x86/include/asm/iosf_mbi.h b/arch/x86/include/asm/iosf_mbi.h +index 8e71c79..57995f0 100644 +--- a/arch/x86/include/asm/iosf_mbi.h ++++ b/arch/x86/include/asm/iosf_mbi.h +@@ -50,6 +50,32 @@ + #define BT_MBI_PCIE_READ 0x00 + #define BT_MBI_PCIE_WRITE 0x01 + ++/* Quark available units */ ++#define QRK_MBI_UNIT_HBA 0x00 ++#define QRK_MBI_UNIT_HB 0x03 ++#define QRK_MBI_UNIT_RMU 0x04 ++#define QRK_MBI_UNIT_MM 0x05 ++#define QRK_MBI_UNIT_MMESRAM 0x05 ++#define QRK_MBI_UNIT_SOC 0x31 ++ ++/* Quark read/write opcodes */ ++#define QRK_MBI_HBA_READ 0x10 ++#define QRK_MBI_HBA_WRITE 0x11 ++#define QRK_MBI_HB_READ 0x10 ++#define QRK_MBI_HB_WRITE 0x11 ++#define QRK_MBI_RMU_READ 0x10 ++#define QRK_MBI_RMU_WRITE 0x11 ++#define QRK_MBI_MM_READ 0x10 ++#define QRK_MBI_MM_WRITE 0x11 ++#define QRK_MBI_MMESRAM_READ 0x12 ++#define QRK_MBI_MMESRAM_WRITE 0x13 ++#define QRK_MBI_SOC_READ 0x06 ++#define QRK_MBI_SOC_WRITE 0x07 ++ ++#if IS_ENABLED(CONFIG_IOSF_MBI) ++ ++bool iosf_mbi_available(void); ++ + /** + * iosf_mbi_read() - MailBox Interface read command + * @port: port indicating subunit being accessed +@@ -87,4 +113,33 @@ int iosf_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr); + */ + int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask); + ++#else /* CONFIG_IOSF_MBI is not enabled */ ++static inline ++bool iosf_mbi_available(void) ++{ ++ return false; ++} ++ ++static inline ++int iosf_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr) ++{ ++ WARN(1, "IOSF_MBI driver not available"); ++ return -EPERM; ++} ++ ++static inline ++int iosf_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr) ++{ ++ WARN(1, "IOSF_MBI driver not available"); ++ return -EPERM; ++} ++ ++static inline ++int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask) ++{ ++ WARN(1, "IOSF_MBI driver not available"); ++ return -EPERM; ++} ++#endif /* CONFIG_IOSF_MBI */ ++ + #endif /* IOSF_MBI_SYMS_H */ +diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h +index bba3cf8..0a8b519 100644 +--- a/arch/x86/include/asm/irqflags.h ++++ b/arch/x86/include/asm/irqflags.h +@@ -129,7 +129,7 @@ static inline notrace unsigned long arch_local_irq_save(void) + + #define PARAVIRT_ADJUST_EXCEPTION_FRAME /* */ + +-#define INTERRUPT_RETURN iretq ++#define INTERRUPT_RETURN jmp native_iret + #define USERGS_SYSRET64 \ + swapgs; \ + sysretq; +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index 3092300..ac03bd7 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -99,7 +99,7 @@ static inline gfn_t gfn_to_index(gfn_t gfn, gfn_t base_gfn, int level) + #define KVM_REFILL_PAGES 25 + #define KVM_MAX_CPUID_ENTRIES 80 + #define KVM_NR_FIXED_MTRR_REGION 88 +-#define KVM_NR_VAR_MTRR 10 ++#define KVM_NR_VAR_MTRR 8 + + #define ASYNC_PF_PER_VCPU 64 + +@@ -480,6 +480,7 @@ struct kvm_vcpu_arch { + u64 mmio_gva; + unsigned access; + gfn_t mmio_gfn; ++ u64 mmio_gen; + + struct kvm_pmu pmu; + +@@ -570,7 +571,7 @@ struct kvm_arch { + struct kvm_pic *vpic; + struct kvm_ioapic *vioapic; + struct kvm_pit *vpit; +- int vapics_in_nmi_mode; ++ atomic_t vapics_in_nmi_mode; + struct mutex apic_map_lock; + struct kvm_apic_map *apic_map; + +@@ -983,6 +984,20 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code) + kvm_queue_exception_e(vcpu, GP_VECTOR, error_code); + } + ++static inline u64 get_canonical(u64 la) ++{ ++ return ((int64_t)la << 16) >> 16; ++} ++ ++static inline bool is_noncanonical_address(u64 la) ++{ ++#ifdef CONFIG_X86_64 ++ return get_canonical(la) != la; ++#else ++ return false; ++#endif ++} ++ + #define TSS_IOPB_BASE_OFFSET 0x66 + #define TSS_BASE_SIZE 0x68 + #define TSS_IOPB_SIZE (65536 / 8) +@@ -1041,7 +1056,7 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v); + void kvm_vcpu_reset(struct kvm_vcpu *vcpu); + + void kvm_define_shared_msr(unsigned index, u32 msr); +-void kvm_set_shared_msr(unsigned index, u64 val, u64 mask); ++int kvm_set_shared_msr(unsigned index, u64 val, u64 mask); + + bool kvm_is_linear_rip(struct kvm_vcpu *vcpu, unsigned long linear_rip); + +diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h +index c7678e4..e62cf89 100644 +--- a/arch/x86/include/asm/kvm_para.h ++++ b/arch/x86/include/asm/kvm_para.h +@@ -2,6 +2,7 @@ + #define _ASM_X86_KVM_PARA_H + + #include ++#include + #include + + extern void kvmclock_init(void); +@@ -16,10 +17,15 @@ static inline bool kvm_check_and_clear_guest_paused(void) + } + #endif /* CONFIG_KVM_GUEST */ + +-/* This instruction is vmcall. On non-VT architectures, it will generate a +- * trap that we will then rewrite to the appropriate instruction. ++#ifdef CONFIG_DEBUG_RODATA ++#define KVM_HYPERCALL \ ++ ALTERNATIVE(".byte 0x0f,0x01,0xc1", ".byte 0x0f,0x01,0xd9", X86_FEATURE_VMMCALL) ++#else ++/* On AMD processors, vmcall will generate a trap that we will ++ * then rewrite to the appropriate instruction. + */ + #define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1" ++#endif + + /* For KVM hypercalls, a three-byte sequence of either the vmcall or the vmmcall + * instruction. The hypervisor may replace it with something else but only the +diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h +index 1da25a5..3ba047c 100644 +--- a/arch/x86/include/asm/mwait.h ++++ b/arch/x86/include/asm/mwait.h +@@ -30,6 +30,14 @@ static inline void __mwait(unsigned long eax, unsigned long ecx) + :: "a" (eax), "c" (ecx)); + } + ++static inline void __sti_mwait(unsigned long eax, unsigned long ecx) ++{ ++ trace_hardirqs_on(); ++ /* "mwait %eax, %ecx;" */ ++ asm volatile("sti; .byte 0x0f, 0x01, 0xc9;" ++ :: "a" (eax), "c" (ecx)); ++} ++ + /* + * This uses new MONITOR/MWAIT instructions on P4 processors with PNI, + * which can obviate IPI to trigger checking of need_resched. +diff --git a/arch/x86/include/asm/page_32_types.h b/arch/x86/include/asm/page_32_types.h +index f48b17d..3a52ee0 100644 +--- a/arch/x86/include/asm/page_32_types.h ++++ b/arch/x86/include/asm/page_32_types.h +@@ -20,7 +20,6 @@ + #define THREAD_SIZE_ORDER 1 + #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) + +-#define STACKFAULT_STACK 0 + #define DOUBLEFAULT_STACK 1 + #define NMI_STACK 0 + #define DEBUG_STACK 0 +diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h +index 8de6d9c..d54d1ee 100644 +--- a/arch/x86/include/asm/page_64_types.h ++++ b/arch/x86/include/asm/page_64_types.h +@@ -14,12 +14,11 @@ + #define IRQ_STACK_ORDER 2 + #define IRQ_STACK_SIZE (PAGE_SIZE << IRQ_STACK_ORDER) + +-#define STACKFAULT_STACK 1 +-#define DOUBLEFAULT_STACK 2 +-#define NMI_STACK 3 +-#define DEBUG_STACK 4 +-#define MCE_STACK 5 +-#define N_EXCEPTION_STACKS 5 /* hw limit: 7 */ ++#define DOUBLEFAULT_STACK 1 ++#define NMI_STACK 2 ++#define DEBUG_STACK 3 ++#define MCE_STACK 4 ++#define N_EXCEPTION_STACKS 4 /* hw limit: 7 */ + + #define PUD_PAGE_SIZE (_AC(1, UL) << PUD_SHIFT) + #define PUD_PAGE_MASK (~(PUD_PAGE_SIZE-1)) +diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h +index e22c1db..d869931 100644 +--- a/arch/x86/include/asm/pgtable_64.h ++++ b/arch/x86/include/asm/pgtable_64.h +@@ -19,6 +19,7 @@ extern pud_t level3_ident_pgt[512]; + extern pmd_t level2_kernel_pgt[512]; + extern pmd_t level2_fixmap_pgt[512]; + extern pmd_t level2_ident_pgt[512]; ++extern pte_t level1_fixmap_pgt[512]; + extern pgd_t init_level4_pgt[]; + + #define swapper_pg_dir init_level4_pgt +diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h +index c883bf7..7166e25 100644 +--- a/arch/x86/include/asm/pgtable_64_types.h ++++ b/arch/x86/include/asm/pgtable_64_types.h +@@ -61,6 +61,8 @@ typedef struct { pteval_t pte; } pte_t; + #define MODULES_VADDR (__START_KERNEL_map + KERNEL_IMAGE_SIZE) + #define MODULES_END _AC(0xffffffffff000000, UL) + #define MODULES_LEN (MODULES_END - MODULES_VADDR) ++#define ESPFIX_PGD_ENTRY _AC(-2, UL) ++#define ESPFIX_BASE_ADDR (ESPFIX_PGD_ENTRY << PGDIR_SHIFT) + + #define EARLY_DYNAMIC_PAGE_TABLES 64 + +diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h +index 6f1c3a8..bcc9a2f 100644 +--- a/arch/x86/include/asm/segment.h ++++ b/arch/x86/include/asm/segment.h +@@ -212,10 +212,21 @@ + #define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8) + + #ifdef __KERNEL__ ++ ++/* ++ * early_idt_handler_array is an array of entry points referenced in the ++ * early IDT. For simplicity, it's a real array with one entry point ++ * every nine bytes. That leaves room for an optional 'push $0' if the ++ * vector has no error code (two bytes), a 'push $vector_number' (two ++ * bytes), and a jump to the common entry code (up to five bytes). ++ */ ++#define EARLY_IDT_HANDLER_SIZE 9 ++ + #ifndef __ASSEMBLY__ +-extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][2+2+5]; ++ ++extern const char early_idt_handler_array[NUM_EXCEPTION_VECTORS][EARLY_IDT_HANDLER_SIZE]; + #ifdef CONFIG_TRACING +-#define trace_early_idt_handlers early_idt_handlers ++# define trace_early_idt_handler_array early_idt_handler_array + #endif + + /* +diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h +index d62c9f8..75b14ca 100644 +--- a/arch/x86/include/asm/setup.h ++++ b/arch/x86/include/asm/setup.h +@@ -65,6 +65,8 @@ static inline void x86_ce4100_early_setup(void) { } + + #ifndef _SETUP + ++#include ++ + /* + * This is set up by the setup-routine at boot-time + */ +diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h +index e1940c0..e870ea9 100644 +--- a/arch/x86/include/asm/thread_info.h ++++ b/arch/x86/include/asm/thread_info.h +@@ -144,7 +144,7 @@ struct thread_info { + /* Only used for 64 bit */ + #define _TIF_DO_NOTIFY_MASK \ + (_TIF_SIGPENDING | _TIF_MCE_NOTIFY | _TIF_NOTIFY_RESUME | \ +- _TIF_USER_RETURN_NOTIFY) ++ _TIF_USER_RETURN_NOTIFY | _TIF_UPROBE) + + /* flags to check in __switch_to() */ + #define _TIF_WORK_CTXSW \ +diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h +index 58d66fe..b409b17 100644 +--- a/arch/x86/include/asm/traps.h ++++ b/arch/x86/include/asm/traps.h +@@ -39,6 +39,7 @@ asmlinkage void simd_coprocessor_error(void); + + #ifdef CONFIG_TRACING + asmlinkage void trace_page_fault(void); ++#define trace_stack_segment stack_segment + #define trace_divide_error divide_error + #define trace_bounds bounds + #define trace_invalid_op invalid_op +diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h +index 2a46ca7..2874be9 100644 +--- a/arch/x86/include/asm/vsyscall.h ++++ b/arch/x86/include/asm/vsyscall.h +@@ -34,7 +34,7 @@ static inline unsigned int __getcpu(void) + native_read_tscp(&p); + } else { + /* Load per CPU data from GDT */ +- asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG)); ++ asm volatile ("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG)); + } + + return p; +diff --git a/arch/x86/include/uapi/asm/ldt.h b/arch/x86/include/uapi/asm/ldt.h +index 46727eb..6e1aaf7 100644 +--- a/arch/x86/include/uapi/asm/ldt.h ++++ b/arch/x86/include/uapi/asm/ldt.h +@@ -28,6 +28,13 @@ struct user_desc { + unsigned int seg_not_present:1; + unsigned int useable:1; + #ifdef __x86_64__ ++ /* ++ * Because this bit is not present in 32-bit user code, user ++ * programs can pass uninitialized values here. Therefore, in ++ * any context in which a user_desc comes from a 32-bit program, ++ * the kernel must act as though lm == 0, regardless of the ++ * actual value. ++ */ + unsigned int lm:1; + #endif + }; +diff --git a/arch/x86/include/uapi/asm/vmx.h b/arch/x86/include/uapi/asm/vmx.h +index 0e79420..990a2fe 100644 +--- a/arch/x86/include/uapi/asm/vmx.h ++++ b/arch/x86/include/uapi/asm/vmx.h +@@ -67,6 +67,7 @@ + #define EXIT_REASON_EPT_MISCONFIG 49 + #define EXIT_REASON_INVEPT 50 + #define EXIT_REASON_PREEMPTION_TIMER 52 ++#define EXIT_REASON_INVVPID 53 + #define EXIT_REASON_WBINVD 54 + #define EXIT_REASON_XSETBV 55 + #define EXIT_REASON_APIC_WRITE 56 +@@ -114,6 +115,7 @@ + { EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, \ + { EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, \ + { EXIT_REASON_INVD, "INVD" }, \ ++ { EXIT_REASON_INVVPID, "INVVPID" }, \ + { EXIT_REASON_INVPCID, "INVPCID" } + + #endif /* _UAPIVMX_H */ +diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile +index cb648c8..56bac86 100644 +--- a/arch/x86/kernel/Makefile ++++ b/arch/x86/kernel/Makefile +@@ -29,6 +29,7 @@ obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o + obj-y += syscall_$(BITS).o + obj-$(CONFIG_X86_64) += vsyscall_64.o + obj-$(CONFIG_X86_64) += vsyscall_emu_64.o ++obj-$(CONFIG_X86_ESPFIX64) += espfix_64.o + obj-$(CONFIG_SYSFS) += ksysfs.o + obj-y += bootflag.o e820.o + obj-y += pci-dma.o quirks.o topology.o kdebugfs.o +diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c +index 7f26c9a..523f147 100644 +--- a/arch/x86/kernel/apic/apic.c ++++ b/arch/x86/kernel/apic/apic.c +@@ -1290,7 +1290,7 @@ void setup_local_APIC(void) + unsigned int value, queued; + int i, j, acked = 0; + unsigned long long tsc = 0, ntsc; +- long long max_loops = cpu_khz; ++ long long max_loops = cpu_khz ? cpu_khz : 1000000; + + if (cpu_has_tsc) + rdtscll(tsc); +@@ -1387,7 +1387,7 @@ void setup_local_APIC(void) + break; + } + if (queued) { +- if (cpu_has_tsc) { ++ if (cpu_has_tsc && cpu_khz) { + rdtscll(ntsc); + max_loops = (cpu_khz << 10) - (ntsc - tsc); + } else +diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c +index c67ffa6..c005fdd 100644 +--- a/arch/x86/kernel/cpu/amd.c ++++ b/arch/x86/kernel/cpu/amd.c +@@ -508,6 +508,13 @@ static void early_init_amd(struct cpuinfo_x86 *c) + } + #endif + ++ /* ++ * This is only needed to tell the kernel whether to use VMCALL ++ * and VMMCALL. VMMCALL is never executed except under virt, so ++ * we can set it unconditionally. ++ */ ++ set_cpu_cap(c, X86_FEATURE_VMMCALL); ++ + /* F16h erratum 793, CVE-2013-6885 */ + if (c->x86 == 0x16 && c->x86_model <= 0xf) { + u64 val; +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +index 8e28bf2..e6bddd5 100644 +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -144,6 +144,8 @@ EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); + + static int __init x86_xsave_setup(char *s) + { ++ if (strlen(s)) ++ return 0; + setup_clear_cpu_cap(X86_FEATURE_XSAVE); + setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT); + setup_clear_cpu_cap(X86_FEATURE_AVX); +@@ -1141,7 +1143,7 @@ void syscall_init(void) + /* Flags to clear on syscall */ + wrmsrl(MSR_SYSCALL_MASK, + X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF| +- X86_EFLAGS_IOPL|X86_EFLAGS_AC); ++ X86_EFLAGS_IOPL|X86_EFLAGS_AC|X86_EFLAGS_NT); + } + + /* +diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c +index 5cd9bfa..66746a8 100644 +--- a/arch/x86/kernel/cpu/intel.c ++++ b/arch/x86/kernel/cpu/intel.c +@@ -153,6 +153,21 @@ static void early_init_intel(struct cpuinfo_x86 *c) + setup_clear_cpu_cap(X86_FEATURE_ERMS); + } + } ++ ++ /* ++ * Intel Quark Core DevMan_001.pdf section 6.4.11 ++ * "The operating system also is required to invalidate (i.e., flush) ++ * the TLB when any changes are made to any of the page table entries. ++ * The operating system must reload CR3 to cause the TLB to be flushed" ++ * ++ * As a result cpu_has_pge() in arch/x86/include/asm/tlbflush.h should ++ * be false so that __flush_tlb_all() causes CR3 insted of CR4.PGE ++ * to be modified ++ */ ++ if (c->x86 == 5 && c->x86_model == 9) { ++ pr_info("Disabling PGE capability bit\n"); ++ setup_clear_cpu_cap(X86_FEATURE_PGE); ++ } + } + + #ifdef CONFIG_X86_32 +@@ -368,6 +383,13 @@ static void init_intel(struct cpuinfo_x86 *c) + detect_extended_topology(c); + + l2 = init_intel_cacheinfo(c); ++ ++ /* Detect legacy cache sizes if init_intel_cacheinfo did not */ ++ if (l2 == 0) { ++ cpu_detect_cache_sizes(c); ++ l2 = c->x86_cache_size; ++ } ++ + if (c->cpuid_level > 9) { + unsigned eax = cpuid_eax(10); + /* Check for version and the number of counters */ +@@ -482,6 +504,13 @@ static unsigned int intel_size_cache(struct cpuinfo_x86 *c, unsigned int size) + */ + if ((c->x86 == 6) && (c->x86_model == 11) && (size == 0)) + size = 256; ++ ++ /* ++ * Intel Quark SoC X1000 contains a 4-way set associative ++ * 16K cache with a 16 byte cache line and 256 lines per tag ++ */ ++ if ((c->x86 == 5) && (c->x86_model == 9)) ++ size = 16; + return size; + } + #endif +@@ -709,7 +738,8 @@ static const struct cpu_dev intel_cpu_dev = { + [3] = "OverDrive PODP5V83", + [4] = "Pentium MMX", + [7] = "Mobile Pentium 75 - 200", +- [8] = "Mobile Pentium MMX" ++ [8] = "Mobile Pentium MMX", ++ [9] = "Quark SoC X1000", + } + }, + { .family = 6, .model_names = +diff --git a/arch/x86/kernel/cpu/microcode/amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c +index 617a9e2..b63773b 100644 +--- a/arch/x86/kernel/cpu/microcode/amd_early.c ++++ b/arch/x86/kernel/cpu/microcode/amd_early.c +@@ -108,12 +108,13 @@ static size_t compute_container_size(u8 *data, u32 total_size) + * load_microcode_amd() to save equivalent cpu table and microcode patches in + * kernel heap memory. + */ +-static void apply_ucode_in_initrd(void *ucode, size_t size) ++static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch) + { + struct equiv_cpu_entry *eq; + size_t *cont_sz; + u32 *header; + u8 *data, **cont; ++ u8 (*patch)[PATCH_MAX_SIZE]; + u16 eq_id = 0; + int offset, left; + u32 rev, eax, ebx, ecx, edx; +@@ -123,10 +124,12 @@ static void apply_ucode_in_initrd(void *ucode, size_t size) + new_rev = (u32 *)__pa_nodebug(&ucode_new_rev); + cont_sz = (size_t *)__pa_nodebug(&container_size); + cont = (u8 **)__pa_nodebug(&container); ++ patch = (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch); + #else + new_rev = &ucode_new_rev; + cont_sz = &container_size; + cont = &container; ++ patch = &amd_ucode_patch; + #endif + + data = ucode; +@@ -213,9 +216,9 @@ static void apply_ucode_in_initrd(void *ucode, size_t size) + rev = mc->hdr.patch_id; + *new_rev = rev; + +- /* save ucode patch */ +- memcpy(amd_ucode_patch, mc, +- min_t(u32, header[1], PATCH_MAX_SIZE)); ++ if (save_patch) ++ memcpy(patch, mc, ++ min_t(u32, header[1], PATCH_MAX_SIZE)); + } + } + +@@ -246,7 +249,7 @@ void __init load_ucode_amd_bsp(void) + *data = cp.data; + *size = cp.size; + +- apply_ucode_in_initrd(cp.data, cp.size); ++ apply_ucode_in_initrd(cp.data, cp.size, true); + } + + #ifdef CONFIG_X86_32 +@@ -263,7 +266,7 @@ void load_ucode_amd_ap(void) + size_t *usize; + void **ucode; + +- mc = (struct microcode_amd *)__pa(amd_ucode_patch); ++ mc = (struct microcode_amd *)__pa_nodebug(amd_ucode_patch); + if (mc->hdr.patch_id && mc->hdr.processor_rev_id) { + __apply_microcode_amd(mc); + return; +@@ -275,7 +278,7 @@ void load_ucode_amd_ap(void) + if (!*ucode || !*usize) + return; + +- apply_ucode_in_initrd(*ucode, *usize); ++ apply_ucode_in_initrd(*ucode, *usize, false); + } + + static void __init collect_cpu_sig_on_bsp(void *arg) +@@ -339,7 +342,7 @@ void load_ucode_amd_ap(void) + * AP has a different equivalence ID than BSP, looks like + * mixed-steppings silicon so go through the ucode blob anew. + */ +- apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size); ++ apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size, false); + } + } + #endif +@@ -347,7 +350,9 @@ void load_ucode_amd_ap(void) + int __init save_microcode_in_initrd_amd(void) + { + unsigned long cont; ++ int retval = 0; + enum ucode_state ret; ++ u8 *cont_va; + u32 eax; + + if (!container) +@@ -355,13 +360,15 @@ int __init save_microcode_in_initrd_amd(void) + + #ifdef CONFIG_X86_32 + get_bsp_sig(); +- cont = (unsigned long)container; ++ cont = (unsigned long)container; ++ cont_va = __va(container); + #else + /* + * We need the physical address of the container for both bitness since + * boot_params.hdr.ramdisk_image is a physical address. + */ +- cont = __pa(container); ++ cont = __pa(container); ++ cont_va = container; + #endif + + /* +@@ -372,6 +379,8 @@ int __init save_microcode_in_initrd_amd(void) + if (relocated_ramdisk) + container = (u8 *)(__va(relocated_ramdisk) + + (cont - boot_params.hdr.ramdisk_image)); ++ else ++ container = cont_va; + + if (ucode_new_rev) + pr_info("microcode: updated early to new patch_level=0x%08x\n", +@@ -382,7 +391,7 @@ int __init save_microcode_in_initrd_amd(void) + + ret = load_microcode_amd(eax, container, container_size); + if (ret != UCODE_OK) +- return -EINVAL; ++ retval = -EINVAL; + + /* + * This will be freed any msec now, stash patches for the current +@@ -391,5 +400,5 @@ int __init save_microcode_in_initrd_amd(void) + container = NULL; + container_size = 0; + +- return 0; ++ return retval; + } +diff --git a/arch/x86/kernel/cpu/microcode/intel_early.c b/arch/x86/kernel/cpu/microcode/intel_early.c +index 18f7391..43a07bf 100644 +--- a/arch/x86/kernel/cpu/microcode/intel_early.c ++++ b/arch/x86/kernel/cpu/microcode/intel_early.c +@@ -321,7 +321,7 @@ get_matching_model_microcode(int cpu, unsigned long start, + unsigned int mc_saved_count = mc_saved_data->mc_saved_count; + int i; + +- while (leftover) { ++ while (leftover && mc_saved_count < ARRAY_SIZE(mc_saved_tmp)) { + mc_header = (struct microcode_header_intel *)ucode_ptr; + + mc_size = get_totalsize(mc_header); +diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c +index 832d05a..317c811 100644 +--- a/arch/x86/kernel/cpu/mshyperv.c ++++ b/arch/x86/kernel/cpu/mshyperv.c +@@ -67,6 +67,7 @@ static struct clocksource hyperv_cs = { + .rating = 400, /* use this when running on Hyperv*/ + .read = read_hv_clock, + .mask = CLOCKSOURCE_MASK(64), ++ .flags = CLOCK_SOURCE_IS_CONTINUOUS, + }; + + static void __init ms_hyperv_init_platform(void) +diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c +index 79f9f84..fb345c4 100644 +--- a/arch/x86/kernel/cpu/perf_event.c ++++ b/arch/x86/kernel/cpu/perf_event.c +@@ -118,6 +118,9 @@ static int x86_pmu_extra_regs(u64 config, struct perf_event *event) + continue; + if (event->attr.config1 & ~er->valid_mask) + return -EINVAL; ++ /* Check if the extra msrs can be safely accessed*/ ++ if (!er->extra_msr_access) ++ return -ENXIO; + + reg->idx = er->idx; + reg->config = event->attr.config1; +diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h +index 4972c24..7876c34 100644 +--- a/arch/x86/kernel/cpu/perf_event.h ++++ b/arch/x86/kernel/cpu/perf_event.h +@@ -293,14 +293,16 @@ struct extra_reg { + u64 config_mask; + u64 valid_mask; + int idx; /* per_xxx->regs[] reg index */ ++ bool extra_msr_access; + }; + + #define EVENT_EXTRA_REG(e, ms, m, vm, i) { \ +- .event = (e), \ +- .msr = (ms), \ +- .config_mask = (m), \ +- .valid_mask = (vm), \ +- .idx = EXTRA_REG_##i, \ ++ .event = (e), \ ++ .msr = (ms), \ ++ .config_mask = (m), \ ++ .valid_mask = (vm), \ ++ .idx = EXTRA_REG_##i, \ ++ .extra_msr_access = true, \ + } + + #define INTEL_EVENT_EXTRA_REG(event, msr, vm, idx) \ +diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c +index 1340ebf..d4c0a0e 100644 +--- a/arch/x86/kernel/cpu/perf_event_intel.c ++++ b/arch/x86/kernel/cpu/perf_event_intel.c +@@ -2183,6 +2183,41 @@ static void intel_snb_check_microcode(void) + } + } + ++/* ++ * Under certain circumstances, access certain MSR may cause #GP. ++ * The function tests if the input MSR can be safely accessed. ++ */ ++static bool check_msr(unsigned long msr, u64 mask) ++{ ++ u64 val_old, val_new, val_tmp; ++ ++ /* ++ * Read the current value, change it and read it back to see if it ++ * matches, this is needed to detect certain hardware emulators ++ * (qemu/kvm) that don't trap on the MSR access and always return 0s. ++ */ ++ if (rdmsrl_safe(msr, &val_old)) ++ return false; ++ ++ /* ++ * Only change the bits which can be updated by wrmsrl. ++ */ ++ val_tmp = val_old ^ mask; ++ if (wrmsrl_safe(msr, val_tmp) || ++ rdmsrl_safe(msr, &val_new)) ++ return false; ++ ++ if (val_new != val_tmp) ++ return false; ++ ++ /* Here it's sure that the MSR can be safely accessed. ++ * Restore the old value and return. ++ */ ++ wrmsrl(msr, val_old); ++ ++ return true; ++} ++ + static __init void intel_sandybridge_quirk(void) + { + x86_pmu.check_microcode = intel_snb_check_microcode; +@@ -2272,7 +2307,8 @@ __init int intel_pmu_init(void) + union cpuid10_ebx ebx; + struct event_constraint *c; + unsigned int unused; +- int version; ++ struct extra_reg *er; ++ int version, i; + + if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { + switch (boot_cpu_data.x86) { +@@ -2475,6 +2511,9 @@ __init int intel_pmu_init(void) + case 62: /* IvyBridge EP */ + memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, + sizeof(hw_cache_event_ids)); ++ /* dTLB-load-misses on IVB is different than SNB */ ++ hw_cache_event_ids[C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = 0x8108; /* DTLB_LOAD_MISSES.DEMAND_LD_MISS_CAUSES_A_WALK */ ++ + memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, + sizeof(hw_cache_extra_regs)); + +@@ -2575,6 +2614,34 @@ __init int intel_pmu_init(void) + } + } + ++ /* ++ * Access LBR MSR may cause #GP under certain circumstances. ++ * E.g. KVM doesn't support LBR MSR ++ * Check all LBT MSR here. ++ * Disable LBR access if any LBR MSRs can not be accessed. ++ */ ++ if (x86_pmu.lbr_nr && !check_msr(x86_pmu.lbr_tos, 0x3UL)) ++ x86_pmu.lbr_nr = 0; ++ for (i = 0; i < x86_pmu.lbr_nr; i++) { ++ if (!(check_msr(x86_pmu.lbr_from + i, 0xffffUL) && ++ check_msr(x86_pmu.lbr_to + i, 0xffffUL))) ++ x86_pmu.lbr_nr = 0; ++ } ++ ++ /* ++ * Access extra MSR may cause #GP under certain circumstances. ++ * E.g. KVM doesn't support offcore event ++ * Check all extra_regs here. ++ */ ++ if (x86_pmu.extra_regs) { ++ for (er = x86_pmu.extra_regs; er->msr; er++) { ++ er->extra_msr_access = check_msr(er->msr, 0x1ffUL); ++ /* Disable LBR select mapping */ ++ if ((er->idx == EXTRA_REG_LBR) && !er->extra_msr_access) ++ x86_pmu.lbr_sel_map = NULL; ++ } ++ } ++ + /* Support full width counters using alternative MSR range */ + if (x86_pmu.intel_cap.full_width_write) { + x86_pmu.max_period = x86_pmu.cntval_mask; +diff --git a/arch/x86/kernel/cpu/perf_event_intel_rapl.c b/arch/x86/kernel/cpu/perf_event_intel_rapl.c +index 5ad35ad..95700e5 100644 +--- a/arch/x86/kernel/cpu/perf_event_intel_rapl.c ++++ b/arch/x86/kernel/cpu/perf_event_intel_rapl.c +@@ -511,6 +511,7 @@ static int rapl_cpu_prepare(int cpu) + struct rapl_pmu *pmu = per_cpu(rapl_pmu, cpu); + int phys_id = topology_physical_package_id(cpu); + u64 ms; ++ u64 msr_rapl_power_unit_bits; + + if (pmu) + return 0; +@@ -518,6 +519,9 @@ static int rapl_cpu_prepare(int cpu) + if (phys_id < 0) + return -1; + ++ if (!rdmsrl_safe(MSR_RAPL_POWER_UNIT, &msr_rapl_power_unit_bits)) ++ return -1; ++ + pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu)); + if (!pmu) + return -1; +@@ -531,8 +535,7 @@ static int rapl_cpu_prepare(int cpu) + * + * we cache in local PMU instance + */ +- rdmsrl(MSR_RAPL_POWER_UNIT, pmu->hw_unit); +- pmu->hw_unit = (pmu->hw_unit >> 8) & 0x1FULL; ++ pmu->hw_unit = (msr_rapl_power_unit_bits >> 8) & 0x1FULL; + pmu->pmu = &rapl_pmu_class; + + /* +@@ -649,7 +652,9 @@ static int __init rapl_pmu_init(void) + get_online_cpus(); + + for_each_online_cpu(cpu) { +- rapl_cpu_prepare(cpu); ++ ret = rapl_cpu_prepare(cpu); ++ if (ret) ++ goto out; + rapl_cpu_init(cpu); + } + +@@ -672,6 +677,7 @@ static int __init rapl_pmu_init(void) + hweight32(rapl_cntr_mask), + ktime_to_ms(pmu->timer_interval)); + ++out: + put_online_cpus(); + + return 0; +diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c +index 047f540..2f98588 100644 +--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c ++++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c +@@ -2886,6 +2886,17 @@ static struct intel_uncore_box *uncore_event_to_box(struct perf_event *event) + return uncore_pmu_to_box(uncore_event_to_pmu(event), smp_processor_id()); + } + ++/* ++ * Using uncore_pmu_event_init pmu event_init callback ++ * as a detection point for uncore events. ++ */ ++static int uncore_pmu_event_init(struct perf_event *event); ++ ++static bool is_uncore_event(struct perf_event *event) ++{ ++ return event->pmu->event_init == uncore_pmu_event_init; ++} ++ + static int + uncore_collect_events(struct intel_uncore_box *box, struct perf_event *leader, bool dogrp) + { +@@ -2900,13 +2911,18 @@ uncore_collect_events(struct intel_uncore_box *box, struct perf_event *leader, b + return -EINVAL; + + n = box->n_events; +- box->event_list[n] = leader; +- n++; ++ ++ if (is_uncore_event(leader)) { ++ box->event_list[n] = leader; ++ n++; ++ } ++ + if (!dogrp) + return n; + + list_for_each_entry(event, &leader->sibling_list, group_entry) { +- if (event->state <= PERF_EVENT_STATE_OFF) ++ if (!is_uncore_event(event) || ++ event->state <= PERF_EVENT_STATE_OFF) + continue; + + if (n >= max_count) +diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c +index addb207..66e274a 100644 +--- a/arch/x86/kernel/dumpstack_64.c ++++ b/arch/x86/kernel/dumpstack_64.c +@@ -24,7 +24,6 @@ static char x86_stack_ids[][8] = { + [ DEBUG_STACK-1 ] = "#DB", + [ NMI_STACK-1 ] = "NMI", + [ DOUBLEFAULT_STACK-1 ] = "#DF", +- [ STACKFAULT_STACK-1 ] = "#SS", + [ MCE_STACK-1 ] = "#MC", + #if DEBUG_STKSZ > EXCEPTION_STKSZ + [ N_EXCEPTION_STACKS ... +diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S +index 6491353..c5a9cb9 100644 +--- a/arch/x86/kernel/entry_32.S ++++ b/arch/x86/kernel/entry_32.S +@@ -433,8 +433,8 @@ sysenter_do_call: + cmpl $(NR_syscalls), %eax + jae sysenter_badsys + call *sys_call_table(,%eax,4) +- movl %eax,PT_EAX(%esp) + sysenter_after_call: ++ movl %eax,PT_EAX(%esp) + LOCKDEP_SYS_EXIT + DISABLE_INTERRUPTS(CLBR_ANY) + TRACE_IRQS_OFF +@@ -514,6 +514,7 @@ ENTRY(system_call) + jae syscall_badsys + syscall_call: + call *sys_call_table(,%eax,4) ++syscall_after_call: + movl %eax,PT_EAX(%esp) # store the return value + syscall_exit: + LOCKDEP_SYS_EXIT +@@ -528,6 +529,7 @@ syscall_exit: + restore_all: + TRACE_IRQS_IRET + restore_all_notrace: ++#ifdef CONFIG_X86_ESPFIX32 + movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS + # Warning: PT_OLDSS(%esp) contains the wrong/random values if we + # are returning to the kernel. +@@ -538,6 +540,7 @@ restore_all_notrace: + cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax + CFI_REMEMBER_STATE + je ldt_ss # returning to user-space with LDT SS ++#endif + restore_nocheck: + RESTORE_REGS 4 # skip orig_eax/error_code + irq_return: +@@ -550,6 +553,7 @@ ENTRY(iret_exc) + .previous + _ASM_EXTABLE(irq_return,iret_exc) + ++#ifdef CONFIG_X86_ESPFIX32 + CFI_RESTORE_STATE + ldt_ss: + #ifdef CONFIG_PARAVIRT +@@ -593,6 +597,7 @@ ldt_ss: + lss (%esp), %esp /* switch to espfix segment */ + CFI_ADJUST_CFA_OFFSET -8 + jmp restore_nocheck ++#endif + CFI_ENDPROC + ENDPROC(system_call) + +@@ -683,12 +688,12 @@ syscall_fault: + END(syscall_fault) + + syscall_badsys: +- movl $-ENOSYS,PT_EAX(%esp) +- jmp syscall_exit ++ movl $-ENOSYS,%eax ++ jmp syscall_after_call + END(syscall_badsys) + + sysenter_badsys: +- movl $-ENOSYS,PT_EAX(%esp) ++ movl $-ENOSYS,%eax + jmp sysenter_after_call + END(syscall_badsys) + CFI_ENDPROC +@@ -705,6 +710,7 @@ END(syscall_badsys) + * the high word of the segment base from the GDT and swiches to the + * normal stack and adjusts ESP with the matching offset. + */ ++#ifdef CONFIG_X86_ESPFIX32 + /* fixup the stack */ + mov GDT_ESPFIX_SS + 4, %al /* bits 16..23 */ + mov GDT_ESPFIX_SS + 7, %ah /* bits 24..31 */ +@@ -714,8 +720,10 @@ END(syscall_badsys) + pushl_cfi %eax + lss (%esp), %esp /* switch to the normal stack segment */ + CFI_ADJUST_CFA_OFFSET -8 ++#endif + .endm + .macro UNWIND_ESPFIX_STACK ++#ifdef CONFIG_X86_ESPFIX32 + movl %ss, %eax + /* see if on espfix stack */ + cmpw $__ESPFIX_SS, %ax +@@ -726,6 +734,7 @@ END(syscall_badsys) + /* switch to normal stack */ + FIXUP_ESPFIX_STACK + 27: ++#endif + .endm + + /* +@@ -1356,11 +1365,13 @@ END(debug) + ENTRY(nmi) + RING0_INT_FRAME + ASM_CLAC ++#ifdef CONFIG_X86_ESPFIX32 + pushl_cfi %eax + movl %ss, %eax + cmpw $__ESPFIX_SS, %ax + popl_cfi %eax + je nmi_espfix_stack ++#endif + cmpl $ia32_sysenter_target,(%esp) + je nmi_stack_fixup + pushl_cfi %eax +@@ -1400,6 +1411,7 @@ nmi_debug_stack_check: + FIX_STACK 24, nmi_stack_correct, 1 + jmp nmi_stack_correct + ++#ifdef CONFIG_X86_ESPFIX32 + nmi_espfix_stack: + /* We have a RING0_INT_FRAME here. + * +@@ -1421,6 +1433,7 @@ nmi_espfix_stack: + lss 12+4(%esp), %esp # back to espfix stack + CFI_ADJUST_CFA_OFFSET -24 + jmp irq_return ++#endif + CFI_ENDPROC + END(nmi) + +diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S +index 1e96c36..06469ee 100644 +--- a/arch/x86/kernel/entry_64.S ++++ b/arch/x86/kernel/entry_64.S +@@ -58,6 +58,7 @@ + #include + #include + #include ++#include + #include + + /* Avoid __ASSEMBLER__'ifying just for this. */ +@@ -541,11 +542,14 @@ ENTRY(ret_from_fork) + testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread? + jz 1f + +- testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET +- jnz int_ret_from_sys_call +- +- RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET +- jmp ret_from_sys_call # go to the SYSRET fastpath ++ /* ++ * By the time we get here, we have no idea whether our pt_regs, ++ * ti flags, and ti status came from the 64-bit SYSCALL fast path, ++ * the slow path, or one of the ia32entry paths. ++ * Use int_ret_from_sys_call to return, since it can safely handle ++ * all of the above. ++ */ ++ jmp int_ret_from_sys_call + + 1: + subq $REST_SKIP, %rsp # leave space for volatiles +@@ -1041,32 +1045,52 @@ restore_args: + + irq_return: + INTERRUPT_RETURN +- _ASM_EXTABLE(irq_return, bad_iret) + +-#ifdef CONFIG_PARAVIRT + ENTRY(native_iret) +- iretq +- _ASM_EXTABLE(native_iret, bad_iret) ++ /* ++ * Are we returning to a stack segment from the LDT? Note: in ++ * 64-bit mode SS:RSP on the exception stack is always valid. ++ */ ++#ifdef CONFIG_X86_ESPFIX64 ++ testb $4,(SS-RIP)(%rsp) ++ jnz native_irq_return_ldt + #endif + +- .section .fixup,"ax" +-bad_iret: ++.global native_irq_return_iret ++native_irq_return_iret: + /* +- * The iret traps when the %cs or %ss being restored is bogus. +- * We've lost the original trap vector and error code. +- * #GPF is the most likely one to get for an invalid selector. +- * So pretend we completed the iret and took the #GPF in user mode. +- * +- * We are now running with the kernel GS after exception recovery. +- * But error_entry expects us to have user GS to match the user %cs, +- * so swap back. ++ * This may fault. Non-paranoid faults on return to userspace are ++ * handled by fixup_bad_iret. These include #SS, #GP, and #NP. ++ * Double-faults due to espfix64 are handled in do_double_fault. ++ * Other faults here are fatal. + */ +- pushq $0 ++ iretq + ++#ifdef CONFIG_X86_ESPFIX64 ++native_irq_return_ldt: ++ pushq_cfi %rax ++ pushq_cfi %rdi + SWAPGS +- jmp general_protection +- +- .previous ++ movq PER_CPU_VAR(espfix_waddr),%rdi ++ movq %rax,(0*8)(%rdi) /* RAX */ ++ movq (2*8)(%rsp),%rax /* RIP */ ++ movq %rax,(1*8)(%rdi) ++ movq (3*8)(%rsp),%rax /* CS */ ++ movq %rax,(2*8)(%rdi) ++ movq (4*8)(%rsp),%rax /* RFLAGS */ ++ movq %rax,(3*8)(%rdi) ++ movq (6*8)(%rsp),%rax /* SS */ ++ movq %rax,(5*8)(%rdi) ++ movq (5*8)(%rsp),%rax /* RSP */ ++ movq %rax,(4*8)(%rdi) ++ andl $0xffff0000,%eax ++ popq_cfi %rdi ++ orq PER_CPU_VAR(espfix_stack),%rax ++ SWAPGS ++ movq %rax,%rsp ++ popq_cfi %rax ++ jmp native_irq_return_iret ++#endif + + /* edi: workmask, edx: work */ + retint_careful: +@@ -1110,9 +1134,9 @@ ENTRY(retint_kernel) + call preempt_schedule_irq + jmp exit_intr + #endif +- + CFI_ENDPROC + END(common_interrupt) ++ + /* + * End of kprobes section + */ +@@ -1484,7 +1508,7 @@ apicinterrupt3 HYPERVISOR_CALLBACK_VECTOR \ + + paranoidzeroentry_ist debug do_debug DEBUG_STACK + paranoidzeroentry_ist int3 do_int3 DEBUG_STACK +-paranoiderrorentry stack_segment do_stack_segment ++errorentry stack_segment do_stack_segment + #ifdef CONFIG_XEN + zeroentry xen_debug do_debug + zeroentry xen_int3 do_int3 +@@ -1594,16 +1618,15 @@ error_sti: + + /* + * There are two places in the kernel that can potentially fault with +- * usergs. Handle them here. The exception handlers after iret run with +- * kernel gs again, so don't set the user space flag. B stepping K8s +- * sometimes report an truncated RIP for IRET exceptions returning to +- * compat mode. Check for these here too. ++ * usergs. Handle them here. B stepping K8s sometimes report a ++ * truncated RIP for IRET exceptions returning to compat mode. Check ++ * for these here too. + */ + error_kernelspace: + incl %ebx +- leaq irq_return(%rip),%rcx ++ leaq native_irq_return_iret(%rip),%rcx + cmpq %rcx,RIP+8(%rsp) +- je error_swapgs ++ je error_bad_iret + movl %ecx,%eax /* zero extend */ + cmpq %rax,RIP+8(%rsp) + je bstep_iret +@@ -1614,7 +1637,15 @@ error_kernelspace: + bstep_iret: + /* Fix truncated RIP */ + movq %rcx,RIP+8(%rsp) +- jmp error_swapgs ++ /* fall through */ ++ ++error_bad_iret: ++ SWAPGS ++ mov %rsp,%rdi ++ call fixup_bad_iret ++ mov %rax,%rsp ++ decl %ebx /* Return to usergs */ ++ jmp error_sti + CFI_ENDPROC + END(error_entry) + +diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c +index 85126cc..5fc4ac7 100644 +--- a/arch/x86/kernel/head64.c ++++ b/arch/x86/kernel/head64.c +@@ -162,7 +162,7 @@ asmlinkage void __init x86_64_start_kernel(char * real_mode_data) + clear_bss(); + + for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) +- set_intr_gate(i, early_idt_handlers[i]); ++ set_intr_gate(i, early_idt_handler_array[i]); + load_idt((const struct desc_ptr *)&idt_descr); + + copy_bootdata(__va(real_mode_data)); +diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S +index f36bd42..30a2aa3 100644 +--- a/arch/x86/kernel/head_32.S ++++ b/arch/x86/kernel/head_32.S +@@ -477,21 +477,22 @@ is486: + __INIT + setup_once: + /* +- * Set up a idt with 256 entries pointing to ignore_int, +- * interrupt gates. It doesn't actually load idt - that needs +- * to be done on each CPU. Interrupts are enabled elsewhere, +- * when we can be relatively sure everything is ok. ++ * Set up a idt with 256 interrupt gates that push zero if there ++ * is no error code and then jump to early_idt_handler_common. ++ * It doesn't actually load the idt - that needs to be done on ++ * each CPU. Interrupts are enabled elsewhere, when we can be ++ * relatively sure everything is ok. + */ + + movl $idt_table,%edi +- movl $early_idt_handlers,%eax ++ movl $early_idt_handler_array,%eax + movl $NUM_EXCEPTION_VECTORS,%ecx + 1: + movl %eax,(%edi) + movl %eax,4(%edi) + /* interrupt gate, dpl=0, present */ + movl $(0x8E000000 + __KERNEL_CS),2(%edi) +- addl $9,%eax ++ addl $EARLY_IDT_HANDLER_SIZE,%eax + addl $8,%edi + loop 1b + +@@ -523,26 +524,28 @@ setup_once: + andl $0,setup_once_ref /* Once is enough, thanks */ + ret + +-ENTRY(early_idt_handlers) ++ENTRY(early_idt_handler_array) + # 36(%esp) %eflags + # 32(%esp) %cs + # 28(%esp) %eip + # 24(%rsp) error code + i = 0 + .rept NUM_EXCEPTION_VECTORS +- .if (EXCEPTION_ERRCODE_MASK >> i) & 1 +- ASM_NOP2 +- .else ++ .ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1 + pushl $0 # Dummy error code, to make stack frame uniform + .endif + pushl $i # 20(%esp) Vector number +- jmp early_idt_handler ++ jmp early_idt_handler_common + i = i + 1 ++ .fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc + .endr +-ENDPROC(early_idt_handlers) ++ENDPROC(early_idt_handler_array) + +- /* This is global to keep gas from relaxing the jumps */ +-ENTRY(early_idt_handler) ++early_idt_handler_common: ++ /* ++ * The stack is the hardware frame, an error code or zero, and the ++ * vector number. ++ */ + cld + + cmpl $2,(%esp) # X86_TRAP_NMI +@@ -602,7 +605,7 @@ ex_entry: + is_nmi: + addl $8,%esp /* drop vector number and error code */ + iret +-ENDPROC(early_idt_handler) ++ENDPROC(early_idt_handler_common) + + /* This is the default interrupt "handler" :-) */ + ALIGN +diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S +index a468c0a..a2dc0ad 100644 +--- a/arch/x86/kernel/head_64.S ++++ b/arch/x86/kernel/head_64.S +@@ -321,26 +321,28 @@ bad_address: + jmp bad_address + + __INIT +- .globl early_idt_handlers +-early_idt_handlers: ++ENTRY(early_idt_handler_array) + # 104(%rsp) %rflags + # 96(%rsp) %cs + # 88(%rsp) %rip + # 80(%rsp) error code + i = 0 + .rept NUM_EXCEPTION_VECTORS +- .if (EXCEPTION_ERRCODE_MASK >> i) & 1 +- ASM_NOP2 +- .else ++ .ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1 + pushq $0 # Dummy error code, to make stack frame uniform + .endif + pushq $i # 72(%rsp) Vector number +- jmp early_idt_handler ++ jmp early_idt_handler_common + i = i + 1 ++ .fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc + .endr ++ENDPROC(early_idt_handler_array) + +-/* This is global to keep gas from relaxing the jumps */ +-ENTRY(early_idt_handler) ++early_idt_handler_common: ++ /* ++ * The stack is the hardware frame, an error code or zero, and the ++ * vector number. ++ */ + cld + + cmpl $2,(%rsp) # X86_TRAP_NMI +@@ -412,7 +414,7 @@ ENTRY(early_idt_handler) + is_nmi: + addq $16,%rsp # drop vector number and error code + INTERRUPT_RETURN +-ENDPROC(early_idt_handler) ++ENDPROC(early_idt_handler_common) + + __INITDATA + +diff --git a/arch/x86/kernel/iosf_mbi.c b/arch/x86/kernel/iosf_mbi.c +index c3aae66..2e97b3c 100644 +--- a/arch/x86/kernel/iosf_mbi.c ++++ b/arch/x86/kernel/iosf_mbi.c +@@ -25,6 +25,10 @@ + + #include + ++#define PCI_DEVICE_ID_BAYTRAIL 0x0F00 ++#define PCI_DEVICE_ID_BRASWELL 0x2280 ++#define PCI_DEVICE_ID_QUARK_X1000 0x0958 ++ + static DEFINE_SPINLOCK(iosf_mbi_lock); + + static inline u32 iosf_mbi_form_mcr(u8 op, u8 port, u8 offset) +@@ -177,6 +181,13 @@ int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask) + } + EXPORT_SYMBOL(iosf_mbi_modify); + ++bool iosf_mbi_available(void) ++{ ++ /* Mbi isn't hot-pluggable. No remove routine is provided */ ++ return mbi_pdev; ++} ++EXPORT_SYMBOL(iosf_mbi_available); ++ + static int iosf_mbi_probe(struct pci_dev *pdev, + const struct pci_device_id *unused) + { +@@ -193,7 +204,9 @@ static int iosf_mbi_probe(struct pci_dev *pdev, + } + + static DEFINE_PCI_DEVICE_TABLE(iosf_mbi_pci_ids) = { +- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0F00) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_BAYTRAIL) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_BRASWELL) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_QUARK_X1000) }, + { 0, }, + }; + MODULE_DEVICE_TABLE(pci, iosf_mbi_pci_ids); +diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c +index 79a3f96..490fee1 100644 +--- a/arch/x86/kernel/kprobes/core.c ++++ b/arch/x86/kernel/kprobes/core.c +@@ -326,13 +326,16 @@ int __kprobes __copy_instruction(u8 *dest, u8 *src) + { + struct insn insn; + kprobe_opcode_t buf[MAX_INSN_SIZE]; ++ int length; + + kernel_insn_init(&insn, (void *)recover_probed_instruction(buf, (unsigned long)src)); + insn_get_length(&insn); ++ length = insn.length; ++ + /* Another subsystem puts a breakpoint, failed to recover */ + if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION) + return 0; +- memcpy(dest, insn.kaddr, insn.length); ++ memcpy(dest, insn.kaddr, length); + + #ifdef CONFIG_X86_64 + if (insn_rip_relative(&insn)) { +@@ -362,7 +365,7 @@ int __kprobes __copy_instruction(u8 *dest, u8 *src) + *(s32 *) disp = (s32) newdisp; + } + #endif +- return insn.length; ++ return length; + } + + static int __kprobes arch_copy_kprobe(struct kprobe *p) +@@ -1017,6 +1020,15 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) + regs->flags &= ~X86_EFLAGS_IF; + trace_hardirqs_off(); + regs->ip = (unsigned long)(jp->entry); ++ ++ /* ++ * jprobes use jprobe_return() which skips the normal return ++ * path of the function, and this messes up the accounting of the ++ * function graph tracer to get messed up. ++ * ++ * Pause function graph tracing while performing the jprobe function. ++ */ ++ pause_graph_tracing(); + return 1; + } + +@@ -1042,24 +1054,25 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + u8 *addr = (u8 *) (regs->ip - 1); + struct jprobe *jp = container_of(p, struct jprobe, kp); ++ void *saved_sp = kcb->jprobe_saved_sp; + + if ((addr > (u8 *) jprobe_return) && + (addr < (u8 *) jprobe_return_end)) { +- if (stack_addr(regs) != kcb->jprobe_saved_sp) { ++ if (stack_addr(regs) != saved_sp) { + struct pt_regs *saved_regs = &kcb->jprobe_saved_regs; + printk(KERN_ERR + "current sp %p does not match saved sp %p\n", +- stack_addr(regs), kcb->jprobe_saved_sp); ++ stack_addr(regs), saved_sp); + printk(KERN_ERR "Saved registers for jprobe %p\n", jp); + show_regs(saved_regs); + printk(KERN_ERR "Current registers\n"); + show_regs(regs); + BUG(); + } ++ /* It's OK to start function graph tracing again */ ++ unpause_graph_tracing(); + *regs = kcb->jprobe_saved_regs; +- memcpy((kprobe_opcode_t *)(kcb->jprobe_saved_sp), +- kcb->jprobes_stack, +- MIN_STACK_SIZE(kcb->jprobe_saved_sp)); ++ memcpy(saved_sp, kcb->jprobes_stack, MIN_STACK_SIZE(saved_sp)); + preempt_enable_no_resched(); + return 1; + } +diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c +index 713f1b3..0b1e1d5 100644 +--- a/arch/x86/kernel/kvm.c ++++ b/arch/x86/kernel/kvm.c +@@ -280,7 +280,14 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code) + static void __init paravirt_ops_setup(void) + { + pv_info.name = "KVM"; +- pv_info.paravirt_enabled = 1; ++ ++ /* ++ * KVM isn't paravirt in the sense of paravirt_enabled. A KVM ++ * guest kernel works like a bare metal kernel with additional ++ * features, and paravirt_enabled is about features that are ++ * missing. ++ */ ++ pv_info.paravirt_enabled = 0; + + if (kvm_para_has_feature(KVM_FEATURE_NOP_IO_DELAY)) + pv_cpu_ops.io_delay = kvm_io_delay; +diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c +index e604109..c8e98cd 100644 +--- a/arch/x86/kernel/kvmclock.c ++++ b/arch/x86/kernel/kvmclock.c +@@ -263,7 +263,6 @@ void __init kvmclock_init(void) + #endif + kvm_get_preset_lpj(); + clocksource_register_hz(&kvm_clock, NSEC_PER_SEC); +- pv_info.paravirt_enabled = 1; + pv_info.name = "KVM"; + + if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE_STABLE_BIT)) +diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c +index dcbbaa1..c37886d 100644 +--- a/arch/x86/kernel/ldt.c ++++ b/arch/x86/kernel/ldt.c +@@ -20,8 +20,6 @@ + #include + #include + +-int sysctl_ldt16 = 0; +- + #ifdef CONFIG_SMP + static void flush_ldt(void *current_mm) + { +@@ -231,16 +229,10 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode) + } + } + +- /* +- * On x86-64 we do not support 16-bit segments due to +- * IRET leaking the high bits of the kernel stack address. +- */ +-#ifdef CONFIG_X86_64 +- if (!ldt_info.seg_32bit && !sysctl_ldt16) { ++ if (!IS_ENABLED(CONFIG_X86_16BIT) && !ldt_info.seg_32bit) { + error = -EINVAL; + goto out_unlock; + } +-#endif + + fill_ldt(&ldt, &ldt_info); + if (oldmode) +diff --git a/arch/x86/kernel/paravirt_patch_64.c b/arch/x86/kernel/paravirt_patch_64.c +index 3f08f34..a1da673 100644 +--- a/arch/x86/kernel/paravirt_patch_64.c ++++ b/arch/x86/kernel/paravirt_patch_64.c +@@ -6,7 +6,6 @@ DEF_NATIVE(pv_irq_ops, irq_disable, "cli"); + DEF_NATIVE(pv_irq_ops, irq_enable, "sti"); + DEF_NATIVE(pv_irq_ops, restore_fl, "pushq %rdi; popfq"); + DEF_NATIVE(pv_irq_ops, save_fl, "pushfq; popq %rax"); +-DEF_NATIVE(pv_cpu_ops, iret, "iretq"); + DEF_NATIVE(pv_mmu_ops, read_cr2, "movq %cr2, %rax"); + DEF_NATIVE(pv_mmu_ops, read_cr3, "movq %cr3, %rax"); + DEF_NATIVE(pv_mmu_ops, write_cr3, "movq %rdi, %cr3"); +@@ -50,7 +49,6 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf, + PATCH_SITE(pv_irq_ops, save_fl); + PATCH_SITE(pv_irq_ops, irq_enable); + PATCH_SITE(pv_irq_ops, irq_disable); +- PATCH_SITE(pv_cpu_ops, iret); + PATCH_SITE(pv_cpu_ops, irq_enable_sysexit); + PATCH_SITE(pv_cpu_ops, usergs_sysret32); + PATCH_SITE(pv_cpu_ops, usergs_sysret64); +diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c +index 3fb8d95..1a1ff42 100644 +--- a/arch/x86/kernel/process.c ++++ b/arch/x86/kernel/process.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + /* + * per-CPU TSS segments. Threads are completely 'soft' on Linux, +@@ -398,6 +399,52 @@ static void amd_e400_idle(void) + default_idle(); + } + ++/* ++ * Intel Core2 and older machines prefer MWAIT over HALT for C1. ++ * We can't rely on cpuidle installing MWAIT, because it will not load ++ * on systems that support only C1 -- so the boot default must be MWAIT. ++ * ++ * Some AMD machines are the opposite, they depend on using HALT. ++ * ++ * So for default C1, which is used during boot until cpuidle loads, ++ * use MWAIT-C1 on Intel HW that has it, else use HALT. ++ */ ++static int prefer_mwait_c1_over_halt(const struct cpuinfo_x86 *c) ++{ ++ if (c->x86_vendor != X86_VENDOR_INTEL) ++ return 0; ++ ++ if (!cpu_has(c, X86_FEATURE_MWAIT)) ++ return 0; ++ ++ return 1; ++} ++ ++/* ++ * MONITOR/MWAIT with no hints, used for default default C1 state. ++ * This invokes MWAIT with interrutps enabled and no flags, ++ * which is backwards compatible with the original MWAIT implementation. ++ */ ++ ++static void mwait_idle(void) ++{ ++ if (!current_set_polling_and_test()) { ++ if (static_cpu_has(X86_FEATURE_CLFLUSH_MONITOR)) { ++ mb(); ++ clflush((void *)¤t_thread_info()->flags); ++ mb(); ++ } ++ ++ __monitor((void *)¤t_thread_info()->flags, 0, 0); ++ if (!need_resched()) ++ __sti_mwait(0, 0); ++ else ++ local_irq_enable(); ++ } else ++ local_irq_enable(); ++ current_clr_polling(); ++} ++ + void select_idle_routine(const struct cpuinfo_x86 *c) + { + #ifdef CONFIG_SMP +@@ -411,6 +458,9 @@ void select_idle_routine(const struct cpuinfo_x86 *c) + /* E400: APIC timer interrupt does not wake up CPU from C1e */ + pr_info("using AMD E400 aware idle routine\n"); + x86_idle = amd_e400_idle; ++ } else if (prefer_mwait_c1_over_halt(c)) { ++ pr_info("using mwait in idle threads\n"); ++ x86_idle = mwait_idle; + } else + x86_idle = default_idle; + } +diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c +index 9c0280f..e2d26ce 100644 +--- a/arch/x86/kernel/process_64.c ++++ b/arch/x86/kernel/process_64.c +@@ -286,24 +286,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) + + fpu = switch_fpu_prepare(prev_p, next_p, cpu); + +- /* +- * Reload esp0, LDT and the page table pointer: +- */ ++ /* Reload esp0 and ss1. */ + load_sp0(tss, next); + +- /* +- * Switch DS and ES. +- * This won't pick up thread selector changes, but I guess that is ok. +- */ +- savesegment(es, prev->es); +- if (unlikely(next->es | prev->es)) +- loadsegment(es, next->es); +- +- savesegment(ds, prev->ds); +- if (unlikely(next->ds | prev->ds)) +- loadsegment(ds, next->ds); +- +- + /* We must save %fs and %gs before load_TLS() because + * %fs and %gs may be cleared by load_TLS(). + * +@@ -312,41 +297,101 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) + savesegment(fs, fsindex); + savesegment(gs, gsindex); + ++ /* ++ * Load TLS before restoring any segments so that segment loads ++ * reference the correct GDT entries. ++ */ + load_TLS(next, cpu); + + /* +- * Leave lazy mode, flushing any hypercalls made here. +- * This must be done before restoring TLS segments so +- * the GDT and LDT are properly updated, and must be +- * done before math_state_restore, so the TS bit is up +- * to date. ++ * Leave lazy mode, flushing any hypercalls made here. This ++ * must be done after loading TLS entries in the GDT but before ++ * loading segments that might reference them, and and it must ++ * be done before math_state_restore, so the TS bit is up to ++ * date. + */ + arch_end_context_switch(next_p); + ++ /* Switch DS and ES. ++ * ++ * Reading them only returns the selectors, but writing them (if ++ * nonzero) loads the full descriptor from the GDT or LDT. The ++ * LDT for next is loaded in switch_mm, and the GDT is loaded ++ * above. ++ * ++ * We therefore need to write new values to the segment ++ * registers on every context switch unless both the new and old ++ * values are zero. ++ * ++ * Note that we don't need to do anything for CS and SS, as ++ * those are saved and restored as part of pt_regs. ++ */ ++ savesegment(es, prev->es); ++ if (unlikely(next->es | prev->es)) ++ loadsegment(es, next->es); ++ ++ savesegment(ds, prev->ds); ++ if (unlikely(next->ds | prev->ds)) ++ loadsegment(ds, next->ds); ++ + /* + * Switch FS and GS. + * +- * Segment register != 0 always requires a reload. Also +- * reload when it has changed. When prev process used 64bit +- * base always reload to avoid an information leak. ++ * These are even more complicated than FS and GS: they have ++ * 64-bit bases are that controlled by arch_prctl. Those bases ++ * only differ from the values in the GDT or LDT if the selector ++ * is 0. ++ * ++ * Loading the segment register resets the hidden base part of ++ * the register to 0 or the value from the GDT / LDT. If the ++ * next base address zero, writing 0 to the segment register is ++ * much faster than using wrmsr to explicitly zero the base. ++ * ++ * The thread_struct.fs and thread_struct.gs values are 0 ++ * if the fs and gs bases respectively are not overridden ++ * from the values implied by fsindex and gsindex. They ++ * are nonzero, and store the nonzero base addresses, if ++ * the bases are overridden. ++ * ++ * (fs != 0 && fsindex != 0) || (gs != 0 && gsindex != 0) should ++ * be impossible. ++ * ++ * Therefore we need to reload the segment registers if either ++ * the old or new selector is nonzero, and we need to override ++ * the base address if next thread expects it to be overridden. ++ * ++ * This code is unnecessarily slow in the case where the old and ++ * new indexes are zero and the new base is nonzero -- it will ++ * unnecessarily write 0 to the selector before writing the new ++ * base address. ++ * ++ * Note: This all depends on arch_prctl being the only way that ++ * user code can override the segment base. Once wrfsbase and ++ * wrgsbase are enabled, most of this code will need to change. + */ + if (unlikely(fsindex | next->fsindex | prev->fs)) { + loadsegment(fs, next->fsindex); ++ + /* +- * Check if the user used a selector != 0; if yes +- * clear 64bit base, since overloaded base is always +- * mapped to the Null selector ++ * If user code wrote a nonzero value to FS, then it also ++ * cleared the overridden base address. ++ * ++ * XXX: if user code wrote 0 to FS and cleared the base ++ * address itself, we won't notice and we'll incorrectly ++ * restore the prior base address next time we reschdule ++ * the process. + */ + if (fsindex) + prev->fs = 0; + } +- /* when next process has a 64bit base use it */ + if (next->fs) + wrmsrl(MSR_FS_BASE, next->fs); + prev->fsindex = fsindex; + + if (unlikely(gsindex | next->gsindex | prev->gs)) { + load_gs_index(next->gsindex); ++ ++ /* This works (and fails) the same way as fsindex above. */ + if (gsindex) + prev->gs = 0; + } +diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c +index 7461f50..0686fe3 100644 +--- a/arch/x86/kernel/ptrace.c ++++ b/arch/x86/kernel/ptrace.c +@@ -1441,15 +1441,6 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, + force_sig_info(SIGTRAP, &info, tsk); + } + +- +-#ifdef CONFIG_X86_32 +-# define IS_IA32 1 +-#elif defined CONFIG_IA32_EMULATION +-# define IS_IA32 is_compat_task() +-#else +-# define IS_IA32 0 +-#endif +- + /* + * We must return the syscall number to actually look up in the table. + * This can be -1L to skip running any syscall at all. +@@ -1487,7 +1478,7 @@ long syscall_trace_enter(struct pt_regs *regs) + if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) + trace_sys_enter(regs, regs->orig_ax); + +- if (IS_IA32) ++ if (is_ia32_task()) + audit_syscall_entry(AUDIT_ARCH_I386, + regs->orig_ax, + regs->bx, regs->cx, +diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c +index c752cb4..a6aa91f 100644 +--- a/arch/x86/kernel/reboot.c ++++ b/arch/x86/kernel/reboot.c +@@ -181,6 +181,16 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { + }, + }, + ++ /* ASRock */ ++ { /* Handle problems with rebooting on ASRock Q1900DC-ITX */ ++ .callback = set_pci_reboot, ++ .ident = "ASRock Q1900DC-ITX", ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASRock"), ++ DMI_MATCH(DMI_BOARD_NAME, "Q1900DC-ITX"), ++ }, ++ }, ++ + /* ASUS */ + { /* Handle problems with rebooting on ASUS P4S800 */ + .callback = set_bios_reboot, +diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c +index 2a26819..80eab01 100644 +--- a/arch/x86/kernel/resource.c ++++ b/arch/x86/kernel/resource.c +@@ -37,10 +37,12 @@ static void remove_e820_regions(struct resource *avail) + + void arch_remove_reservations(struct resource *avail) + { +- /* Trim out BIOS areas (low 1MB and high 2MB) and E820 regions */ ++ /* ++ * Trim out BIOS area (high 2MB) and E820 regions. We do not remove ++ * the low 1MB unconditionally, as this area is needed for some ISA ++ * cards requiring a memory range, e.g. the i82365 PCMCIA controller. ++ */ + if (avail->flags & IORESOURCE_MEM) { +- if (avail->start < BIOS_END) +- avail->start = BIOS_END; + resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END); + + remove_e820_regions(avail); +diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c +index 9e5de68..b88fc86 100644 +--- a/arch/x86/kernel/signal.c ++++ b/arch/x86/kernel/signal.c +@@ -673,6 +673,11 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs) + * handler too. + */ + regs->flags &= ~(X86_EFLAGS_DF|X86_EFLAGS_RF|X86_EFLAGS_TF); ++ /* ++ * Ensure the signal handler starts with the new fpu state. ++ */ ++ if (used_math()) ++ drop_init_fpu(current); + } + signal_setup_done(failed, ksig, test_thread_flag(TIF_SINGLESTEP)); + } +diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c +index a32da80..6828765 100644 +--- a/arch/x86/kernel/smpboot.c ++++ b/arch/x86/kernel/smpboot.c +@@ -243,6 +243,13 @@ static void notrace start_secondary(void *unused) + check_tsc_sync_target(); + + /* ++ * Enable the espfix hack for this CPU ++ */ ++#ifdef CONFIG_X86_ESPFIX64 ++ init_espfix_ap(); ++#endif ++ ++ /* + * We need to hold vector_lock so there the set of online cpus + * does not change while we are assigning vectors to cpus. Holding + * this lock ensures we don't half assign or remove an irq from a cpu. +@@ -1280,6 +1287,9 @@ static void remove_siblinginfo(int cpu) + + for_each_cpu(sibling, cpu_sibling_mask(cpu)) + cpumask_clear_cpu(cpu, cpu_sibling_mask(sibling)); ++ for_each_cpu(sibling, cpu_llc_shared_mask(cpu)) ++ cpumask_clear_cpu(cpu, cpu_llc_shared_mask(sibling)); ++ cpumask_clear(cpu_llc_shared_mask(cpu)); + cpumask_clear(cpu_sibling_mask(cpu)); + cpumask_clear(cpu_core_mask(cpu)); + c->phys_proc_id = 0; +diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c +index f7fec09..7fc5e84 100644 +--- a/arch/x86/kernel/tls.c ++++ b/arch/x86/kernel/tls.c +@@ -27,6 +27,58 @@ static int get_free_idx(void) + return -ESRCH; + } + ++static bool tls_desc_okay(const struct user_desc *info) ++{ ++ /* ++ * For historical reasons (i.e. no one ever documented how any ++ * of the segmentation APIs work), user programs can and do ++ * assume that a struct user_desc that's all zeros except for ++ * entry_number means "no segment at all". This never actually ++ * worked. In fact, up to Linux 3.19, a struct user_desc like ++ * this would create a 16-bit read-write segment with base and ++ * limit both equal to zero. ++ * ++ * That was close enough to "no segment at all" until we ++ * hardened this function to disallow 16-bit TLS segments. Fix ++ * it up by interpreting these zeroed segments the way that they ++ * were almost certainly intended to be interpreted. ++ * ++ * The correct way to ask for "no segment at all" is to specify ++ * a user_desc that satisfies LDT_empty. To keep everything ++ * working, we accept both. ++ * ++ * Note that there's a similar kludge in modify_ldt -- look at ++ * the distinction between modes 1 and 0x11. ++ */ ++ if (LDT_empty(info) || LDT_zero(info)) ++ return true; ++ ++ /* ++ * espfix is required for 16-bit data segments, but espfix ++ * only works for LDT segments. ++ */ ++ if (!info->seg_32bit) ++ return false; ++ ++ /* Only allow data segments in the TLS array. */ ++ if (info->contents > 1) ++ return false; ++ ++ /* ++ * Non-present segments with DPL 3 present an interesting attack ++ * surface. The kernel should handle such segments correctly, ++ * but TLS is very difficult to protect in a sandbox, so prevent ++ * such segments from being created. ++ * ++ * If userspace needs to remove a TLS entry, it can still delete ++ * it outright. ++ */ ++ if (info->seg_not_present) ++ return false; ++ ++ return true; ++} ++ + static void set_tls_desc(struct task_struct *p, int idx, + const struct user_desc *info, int n) + { +@@ -40,7 +92,7 @@ static void set_tls_desc(struct task_struct *p, int idx, + cpu = get_cpu(); + + while (n-- > 0) { +- if (LDT_empty(info)) ++ if (LDT_empty(info) || LDT_zero(info)) + desc->a = desc->b = 0; + else + fill_ldt(desc, info); +@@ -66,6 +118,9 @@ int do_set_thread_area(struct task_struct *p, int idx, + if (copy_from_user(&info, u_info, sizeof(info))) + return -EFAULT; + ++ if (!tls_desc_okay(&info)) ++ return -EINVAL; ++ + if (idx == -1) + idx = info.entry_number; + +@@ -192,6 +247,7 @@ int regset_tls_set(struct task_struct *target, const struct user_regset *regset, + { + struct user_desc infobuf[GDT_ENTRY_TLS_ENTRIES]; + const struct user_desc *info; ++ int i; + + if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) || + (pos % sizeof(struct user_desc)) != 0 || +@@ -205,6 +261,10 @@ int regset_tls_set(struct task_struct *target, const struct user_regset *regset, + else + info = infobuf; + ++ for (i = 0; i < count / sizeof(struct user_desc); i++) ++ if (!tls_desc_okay(info + i)) ++ return -EINVAL; ++ + set_tls_desc(target, + GDT_ENTRY_TLS_MIN + (pos / sizeof(struct user_desc)), + info, count / sizeof(struct user_desc)); +diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c +index 57409f6..b1d9002 100644 +--- a/arch/x86/kernel/traps.c ++++ b/arch/x86/kernel/traps.c +@@ -218,32 +218,40 @@ DO_ERROR_INFO(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op, ILL + DO_ERROR (X86_TRAP_OLD_MF, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun ) + DO_ERROR (X86_TRAP_TS, SIGSEGV, "invalid TSS", invalid_TSS ) + DO_ERROR (X86_TRAP_NP, SIGBUS, "segment not present", segment_not_present ) +-#ifdef CONFIG_X86_32 + DO_ERROR (X86_TRAP_SS, SIGBUS, "stack segment", stack_segment ) +-#endif + DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0 ) + + #ifdef CONFIG_X86_64 + /* Runs on IST stack */ +-dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code) +-{ +- enum ctx_state prev_state; +- +- prev_state = exception_enter(); +- if (notify_die(DIE_TRAP, "stack segment", regs, error_code, +- X86_TRAP_SS, SIGBUS) != NOTIFY_STOP) { +- preempt_conditional_sti(regs); +- do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL); +- preempt_conditional_cli(regs); +- } +- exception_exit(prev_state); +-} +- + dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) + { + static const char str[] = "double fault"; + struct task_struct *tsk = current; + ++#ifdef CONFIG_X86_ESPFIX64 ++ extern unsigned char native_irq_return_iret[]; ++ ++ /* ++ * If IRET takes a non-IST fault on the espfix64 stack, then we ++ * end up promoting it to a doublefault. In that case, modify ++ * the stack to make it look like we just entered the #GP ++ * handler from user space, similar to bad_iret. ++ */ ++ if (((long)regs->sp >> PGDIR_SHIFT) == ESPFIX_PGD_ENTRY && ++ regs->cs == __KERNEL_CS && ++ regs->ip == (unsigned long)native_irq_return_iret) ++ { ++ struct pt_regs *normal_regs = task_pt_regs(current); ++ ++ /* Fake a #GP(0) from userspace. */ ++ memmove(&normal_regs->ip, (void *)regs->sp, 5*8); ++ normal_regs->orig_ax = 0; /* Missing (lost) #GP error code */ ++ regs->ip = (unsigned long)general_protection; ++ regs->sp = (unsigned long)&normal_regs->orig_ax; ++ return; ++ } ++#endif ++ + exception_enter(); + /* Return not checked because double check cannot be ignored */ + notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV); +@@ -357,7 +365,7 @@ exit: + * for scheduling or signal handling. The actual stack switch is done in + * entry.S + */ +-asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) ++asmlinkage notrace __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) + { + struct pt_regs *regs = eregs; + /* Did already sync */ +@@ -376,6 +384,35 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) + *regs = *eregs; + return regs; + } ++ ++struct bad_iret_stack { ++ void *error_entry_ret; ++ struct pt_regs regs; ++}; ++ ++asmlinkage __visible notrace __kprobes ++struct bad_iret_stack *fixup_bad_iret(struct bad_iret_stack *s) ++{ ++ /* ++ * This is called from entry_64.S early in handling a fault ++ * caused by a bad iret to user mode. To handle the fault ++ * correctly, we want move our stack frame to task_pt_regs ++ * and we want to pretend that the exception came from the ++ * iret target. ++ */ ++ struct bad_iret_stack *new_stack = ++ container_of(task_pt_regs(current), ++ struct bad_iret_stack, regs); ++ ++ /* Copy the IRET target to the new stack. */ ++ memmove(&new_stack->regs.ip, (void *)s->regs.sp, 5*8); ++ ++ /* Copy the remainder of the stack from the current stack. */ ++ memmove(new_stack, s, offsetof(struct bad_iret_stack, regs.ip)); ++ ++ BUG_ON(!user_mode_vm(&new_stack->regs)); ++ return new_stack; ++} + #endif + + /* +@@ -748,7 +785,7 @@ void __init trap_init(void) + set_intr_gate(X86_TRAP_OLD_MF, coprocessor_segment_overrun); + set_intr_gate(X86_TRAP_TS, invalid_TSS); + set_intr_gate(X86_TRAP_NP, segment_not_present); +- set_intr_gate_ist(X86_TRAP_SS, &stack_segment, STACKFAULT_STACK); ++ set_intr_gate(X86_TRAP_SS, stack_segment); + set_intr_gate(X86_TRAP_GP, general_protection); + set_intr_gate(X86_TRAP_SPURIOUS, spurious_interrupt_bug); + set_intr_gate(X86_TRAP_MF, coprocessor_error); +diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c +index e0d1d7a..b20bced 100644 +--- a/arch/x86/kernel/tsc.c ++++ b/arch/x86/kernel/tsc.c +@@ -618,7 +618,7 @@ static unsigned long quick_pit_calibrate(void) + goto success; + } + } +- pr_err("Fast TSC calibration failed\n"); ++ pr_info("Fast TSC calibration failed\n"); + return 0; + + success: +@@ -1173,14 +1173,17 @@ void __init tsc_init(void) + + x86_init.timers.tsc_pre_init(); + +- if (!cpu_has_tsc) ++ if (!cpu_has_tsc) { ++ setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER); + return; ++ } + + tsc_khz = x86_platform.calibrate_tsc(); + cpu_khz = tsc_khz; + + if (!tsc_khz) { + mark_tsc_unstable("could not calculate TSC khz"); ++ setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER); + return; + } + +diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c +index 1f96f93..09ce23a 100644 +--- a/arch/x86/kernel/vsyscall_64.c ++++ b/arch/x86/kernel/vsyscall_64.c +@@ -125,10 +125,10 @@ static void warn_bad_vsyscall(const char *level, struct pt_regs *regs, + if (!show_unhandled_signals) + return; + +- pr_notice_ratelimited("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n", +- level, current->comm, task_pid_nr(current), +- message, regs->ip, regs->cs, +- regs->sp, regs->ax, regs->si, regs->di); ++ printk_ratelimited("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n", ++ level, current->comm, task_pid_nr(current), ++ message, regs->ip, regs->cs, ++ regs->sp, regs->ax, regs->si, regs->di); + } + + static int addr_to_vsyscall_nr(unsigned long addr) +diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c +index a4b451c..7a09aca 100644 +--- a/arch/x86/kernel/xsave.c ++++ b/arch/x86/kernel/xsave.c +@@ -268,8 +268,6 @@ int save_xstate_sig(void __user *buf, void __user *buf_fx, int size) + if (use_fxsr() && save_xstate_epilog(buf_fx, ia32_fxstate)) + return -1; + +- drop_init_fpu(tsk); /* trigger finit */ +- + return 0; + } + +@@ -377,7 +375,7 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size) + * thread's fpu state, reconstruct fxstate from the fsave + * header. Sanitize the copied state etc. + */ +- struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave; ++ struct fpu *fpu = &tsk->thread.fpu; + struct user_i387_ia32_struct env; + int err = 0; + +@@ -391,16 +389,20 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size) + */ + drop_fpu(tsk); + +- if (__copy_from_user(xsave, buf_fx, state_size) || ++ if (__copy_from_user(&fpu->state->xsave, buf_fx, state_size) || + __copy_from_user(&env, buf, sizeof(env))) { ++ fpu_finit(fpu); + err = -1; + } else { + sanitize_restored_xstate(tsk, &env, xstate_bv, fx_only); +- set_used_math(); + } + +- if (use_eager_fpu()) ++ set_used_math(); ++ if (use_eager_fpu()) { ++ preempt_disable(); + math_state_restore(); ++ preempt_enable(); ++ } + + return err; + } else { +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index 07ffca0..cf1eeea 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -498,11 +498,6 @@ static void rsp_increment(struct x86_emulate_ctxt *ctxt, int inc) + masked_increment(reg_rmw(ctxt, VCPU_REGS_RSP), stack_mask(ctxt), inc); + } + +-static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel) +-{ +- register_address_increment(ctxt, &ctxt->_eip, rel); +-} +- + static u32 desc_limit_scaled(struct desc_struct *desc) + { + u32 limit = get_desc_limit(desc); +@@ -576,6 +571,38 @@ static int emulate_nm(struct x86_emulate_ctxt *ctxt) + return emulate_exception(ctxt, NM_VECTOR, 0, false); + } + ++static inline int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst, ++ int cs_l) ++{ ++ switch (ctxt->op_bytes) { ++ case 2: ++ ctxt->_eip = (u16)dst; ++ break; ++ case 4: ++ ctxt->_eip = (u32)dst; ++ break; ++ case 8: ++ if ((cs_l && is_noncanonical_address(dst)) || ++ (!cs_l && (dst & ~(u32)-1))) ++ return emulate_gp(ctxt, 0); ++ ctxt->_eip = dst; ++ break; ++ default: ++ WARN(1, "unsupported eip assignment size\n"); ++ } ++ return X86EMUL_CONTINUE; ++} ++ ++static inline int assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst) ++{ ++ return assign_eip_far(ctxt, dst, ctxt->mode == X86EMUL_MODE_PROT64); ++} ++ ++static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel) ++{ ++ return assign_eip_near(ctxt, ctxt->_eip + rel); ++} ++ + static u16 get_segment_selector(struct x86_emulate_ctxt *ctxt, unsigned seg) + { + u16 selector; +@@ -1958,13 +1985,15 @@ static int em_grp45(struct x86_emulate_ctxt *ctxt) + case 2: /* call near abs */ { + long int old_eip; + old_eip = ctxt->_eip; +- ctxt->_eip = ctxt->src.val; ++ rc = assign_eip_near(ctxt, ctxt->src.val); ++ if (rc != X86EMUL_CONTINUE) ++ break; + ctxt->src.val = old_eip; + rc = em_push(ctxt); + break; + } + case 4: /* jmp abs */ +- ctxt->_eip = ctxt->src.val; ++ rc = assign_eip_near(ctxt, ctxt->src.val); + break; + case 5: /* jmp far */ + rc = em_jmp_far(ctxt); +@@ -1996,16 +2025,21 @@ static int em_cmpxchg8b(struct x86_emulate_ctxt *ctxt) + + static int em_ret(struct x86_emulate_ctxt *ctxt) + { +- ctxt->dst.type = OP_REG; +- ctxt->dst.addr.reg = &ctxt->_eip; +- ctxt->dst.bytes = ctxt->op_bytes; +- return em_pop(ctxt); ++ int rc; ++ unsigned long eip; ++ ++ rc = emulate_pop(ctxt, &eip, ctxt->op_bytes); ++ if (rc != X86EMUL_CONTINUE) ++ return rc; ++ ++ return assign_eip_near(ctxt, eip); + } + + static int em_ret_far(struct x86_emulate_ctxt *ctxt) + { + int rc; + unsigned long cs; ++ int cpl = ctxt->ops->cpl(ctxt); + + rc = emulate_pop(ctxt, &ctxt->_eip, ctxt->op_bytes); + if (rc != X86EMUL_CONTINUE) +@@ -2015,6 +2049,9 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt) + rc = emulate_pop(ctxt, &cs, ctxt->op_bytes); + if (rc != X86EMUL_CONTINUE) + return rc; ++ /* Outer-privilege level return is not implemented */ ++ if (ctxt->mode >= X86EMUL_MODE_PROT16 && (cs & 3) > cpl) ++ return X86EMUL_UNHANDLEABLE; + rc = load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS); + return rc; + } +@@ -2221,7 +2258,7 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt) + * Not recognized on AMD in compat mode (but is recognized in legacy + * mode). + */ +- if ((ctxt->mode == X86EMUL_MODE_PROT32) && (efer & EFER_LMA) ++ if ((ctxt->mode != X86EMUL_MODE_PROT64) && (efer & EFER_LMA) + && !vendor_intel(ctxt)) + return emulate_ud(ctxt); + +@@ -2234,25 +2271,13 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt) + setup_syscalls_segments(ctxt, &cs, &ss); + + ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data); +- switch (ctxt->mode) { +- case X86EMUL_MODE_PROT32: +- if ((msr_data & 0xfffc) == 0x0) +- return emulate_gp(ctxt, 0); +- break; +- case X86EMUL_MODE_PROT64: +- if (msr_data == 0x0) +- return emulate_gp(ctxt, 0); +- break; +- default: +- break; +- } ++ if ((msr_data & 0xfffc) == 0x0) ++ return emulate_gp(ctxt, 0); + + ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF); +- cs_sel = (u16)msr_data; +- cs_sel &= ~SELECTOR_RPL_MASK; ++ cs_sel = (u16)msr_data & ~SELECTOR_RPL_MASK; + ss_sel = cs_sel + 8; +- ss_sel &= ~SELECTOR_RPL_MASK; +- if (ctxt->mode == X86EMUL_MODE_PROT64 || (efer & EFER_LMA)) { ++ if (efer & EFER_LMA) { + cs.d = 0; + cs.l = 1; + } +@@ -2261,10 +2286,11 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt) + ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS); + + ops->get_msr(ctxt, MSR_IA32_SYSENTER_EIP, &msr_data); +- ctxt->_eip = msr_data; ++ ctxt->_eip = (efer & EFER_LMA) ? msr_data : (u32)msr_data; + + ops->get_msr(ctxt, MSR_IA32_SYSENTER_ESP, &msr_data); +- *reg_write(ctxt, VCPU_REGS_RSP) = msr_data; ++ *reg_write(ctxt, VCPU_REGS_RSP) = (efer & EFER_LMA) ? msr_data : ++ (u32)msr_data; + + return X86EMUL_CONTINUE; + } +@@ -2273,7 +2299,7 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt) + { + const struct x86_emulate_ops *ops = ctxt->ops; + struct desc_struct cs, ss; +- u64 msr_data; ++ u64 msr_data, rcx, rdx; + int usermode; + u16 cs_sel = 0, ss_sel = 0; + +@@ -2289,6 +2315,9 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt) + else + usermode = X86EMUL_MODE_PROT32; + ++ rcx = reg_read(ctxt, VCPU_REGS_RCX); ++ rdx = reg_read(ctxt, VCPU_REGS_RDX); ++ + cs.dpl = 3; + ss.dpl = 3; + ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data); +@@ -2306,6 +2335,9 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt) + ss_sel = cs_sel + 8; + cs.d = 0; + cs.l = 1; ++ if (is_noncanonical_address(rcx) || ++ is_noncanonical_address(rdx)) ++ return emulate_gp(ctxt, 0); + break; + } + cs_sel |= SELECTOR_RPL_MASK; +@@ -2314,8 +2346,8 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt) + ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS); + ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS); + +- ctxt->_eip = reg_read(ctxt, VCPU_REGS_RDX); +- *reg_write(ctxt, VCPU_REGS_RSP) = reg_read(ctxt, VCPU_REGS_RCX); ++ ctxt->_eip = rdx; ++ *reg_write(ctxt, VCPU_REGS_RSP) = rcx; + + return X86EMUL_CONTINUE; + } +@@ -2854,10 +2886,13 @@ static int em_aad(struct x86_emulate_ctxt *ctxt) + + static int em_call(struct x86_emulate_ctxt *ctxt) + { ++ int rc; + long rel = ctxt->src.val; + + ctxt->src.val = (unsigned long)ctxt->_eip; +- jmp_rel(ctxt, rel); ++ rc = jmp_rel(ctxt, rel); ++ if (rc != X86EMUL_CONTINUE) ++ return rc; + return em_push(ctxt); + } + +@@ -2889,11 +2924,12 @@ static int em_call_far(struct x86_emulate_ctxt *ctxt) + static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt) + { + int rc; ++ unsigned long eip; + +- ctxt->dst.type = OP_REG; +- ctxt->dst.addr.reg = &ctxt->_eip; +- ctxt->dst.bytes = ctxt->op_bytes; +- rc = emulate_pop(ctxt, &ctxt->dst.val, ctxt->op_bytes); ++ rc = emulate_pop(ctxt, &eip, ctxt->op_bytes); ++ if (rc != X86EMUL_CONTINUE) ++ return rc; ++ rc = assign_eip_near(ctxt, eip); + if (rc != X86EMUL_CONTINUE) + return rc; + rsp_increment(ctxt, ctxt->src.val); +@@ -3223,20 +3259,24 @@ static int em_lmsw(struct x86_emulate_ctxt *ctxt) + + static int em_loop(struct x86_emulate_ctxt *ctxt) + { ++ int rc = X86EMUL_CONTINUE; ++ + register_address_increment(ctxt, reg_rmw(ctxt, VCPU_REGS_RCX), -1); + if ((address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) != 0) && + (ctxt->b == 0xe2 || test_cc(ctxt->b ^ 0x5, ctxt->eflags))) +- jmp_rel(ctxt, ctxt->src.val); ++ rc = jmp_rel(ctxt, ctxt->src.val); + +- return X86EMUL_CONTINUE; ++ return rc; + } + + static int em_jcxz(struct x86_emulate_ctxt *ctxt) + { ++ int rc = X86EMUL_CONTINUE; ++ + if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0) +- jmp_rel(ctxt, ctxt->src.val); ++ rc = jmp_rel(ctxt, ctxt->src.val); + +- return X86EMUL_CONTINUE; ++ return rc; + } + + static int em_in(struct x86_emulate_ctxt *ctxt) +@@ -4595,7 +4635,8 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) + if (rc != X86EMUL_CONTINUE) + goto done; + } +- ctxt->dst.orig_val = ctxt->dst.val; ++ /* Copy full 64-bit value for CMPXCHG8B. */ ++ ctxt->dst.orig_val64 = ctxt->dst.val64; + + special_insn: + +@@ -4633,7 +4674,7 @@ special_insn: + break; + case 0x70 ... 0x7f: /* jcc (short) */ + if (test_cc(ctxt->b, ctxt->eflags)) +- jmp_rel(ctxt, ctxt->src.val); ++ rc = jmp_rel(ctxt, ctxt->src.val); + break; + case 0x8d: /* lea r16/r32, m */ + ctxt->dst.val = ctxt->src.addr.mem.ea; +@@ -4662,7 +4703,7 @@ special_insn: + break; + case 0xe9: /* jmp rel */ + case 0xeb: /* jmp rel short */ +- jmp_rel(ctxt, ctxt->src.val); ++ rc = jmp_rel(ctxt, ctxt->src.val); + ctxt->dst.type = OP_NONE; /* Disable writeback. */ + break; + case 0xf4: /* hlt */ +@@ -4782,7 +4823,7 @@ twobyte_insn: + break; + case 0x80 ... 0x8f: /* jnz rel, etc*/ + if (test_cc(ctxt->b, ctxt->eflags)) +- jmp_rel(ctxt, ctxt->src.val); ++ rc = jmp_rel(ctxt, ctxt->src.val); + break; + case 0x90 ... 0x9f: /* setcc r/m8 */ + ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags); +diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c +index 518d864..1406ffd 100644 +--- a/arch/x86/kvm/i8254.c ++++ b/arch/x86/kvm/i8254.c +@@ -262,8 +262,10 @@ void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu) + return; + + timer = &pit->pit_state.timer; ++ mutex_lock(&pit->pit_state.lock); + if (hrtimer_cancel(timer)) + hrtimer_start_expires(timer, HRTIMER_MODE_ABS); ++ mutex_unlock(&pit->pit_state.lock); + } + + static void destroy_pit_timer(struct kvm_pit *pit) +@@ -303,7 +305,7 @@ static void pit_do_work(struct kthread_work *work) + * LVT0 to NMI delivery. Other PIC interrupts are just sent to + * VCPU0, and only if its LVT0 is in EXTINT mode. + */ +- if (kvm->arch.vapics_in_nmi_mode > 0) ++ if (atomic_read(&kvm->arch.vapics_in_nmi_mode) > 0) + kvm_for_each_vcpu(i, vcpu, kvm) + kvm_apic_nmi_wd_deliver(vcpu); + } +diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c +index 484bc87..3ec38cb 100644 +--- a/arch/x86/kvm/irq.c ++++ b/arch/x86/kvm/irq.c +@@ -108,7 +108,7 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v) + + vector = kvm_cpu_get_extint(v); + +- if (kvm_apic_vid_enabled(v->kvm) || vector != -1) ++ if (vector != -1) + return vector; /* PIC */ + + return kvm_get_apic_interrupt(v); /* APIC */ +diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c +index 0069118..6456734 100644 +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -352,25 +352,46 @@ static inline int apic_find_highest_irr(struct kvm_lapic *apic) + + static inline void apic_clear_irr(int vec, struct kvm_lapic *apic) + { +- apic->irr_pending = false; ++ struct kvm_vcpu *vcpu; ++ ++ vcpu = apic->vcpu; ++ + apic_clear_vector(vec, apic->regs + APIC_IRR); +- if (apic_search_irr(apic) != -1) +- apic->irr_pending = true; ++ if (unlikely(kvm_apic_vid_enabled(vcpu->kvm))) ++ /* try to update RVI */ ++ kvm_make_request(KVM_REQ_EVENT, vcpu); ++ else { ++ vec = apic_search_irr(apic); ++ apic->irr_pending = (vec != -1); ++ } + } + + static inline void apic_set_isr(int vec, struct kvm_lapic *apic) + { +- /* Note that we never get here with APIC virtualization enabled. */ ++ struct kvm_vcpu *vcpu; ++ ++ if (__apic_test_and_set_vector(vec, apic->regs + APIC_ISR)) ++ return; ++ ++ vcpu = apic->vcpu; + +- if (!__apic_test_and_set_vector(vec, apic->regs + APIC_ISR)) +- ++apic->isr_count; +- BUG_ON(apic->isr_count > MAX_APIC_VECTOR); + /* +- * ISR (in service register) bit is set when injecting an interrupt. +- * The highest vector is injected. Thus the latest bit set matches +- * the highest bit in ISR. ++ * With APIC virtualization enabled, all caching is disabled ++ * because the processor can modify ISR under the hood. Instead ++ * just set SVI. + */ +- apic->highest_isr_cache = vec; ++ if (unlikely(kvm_apic_vid_enabled(vcpu->kvm))) ++ kvm_x86_ops->hwapic_isr_update(vcpu->kvm, vec); ++ else { ++ ++apic->isr_count; ++ BUG_ON(apic->isr_count > MAX_APIC_VECTOR); ++ /* ++ * ISR (in service register) bit is set when injecting an interrupt. ++ * The highest vector is injected. Thus the latest bit set matches ++ * the highest bit in ISR. ++ */ ++ apic->highest_isr_cache = vec; ++ } + } + + static inline int apic_find_highest_isr(struct kvm_lapic *apic) +@@ -1088,10 +1109,10 @@ static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val) + if (!nmi_wd_enabled) { + apic_debug("Receive NMI setting on APIC_LVT0 " + "for cpu %d\n", apic->vcpu->vcpu_id); +- apic->vcpu->kvm->arch.vapics_in_nmi_mode++; ++ atomic_inc(&apic->vcpu->kvm->arch.vapics_in_nmi_mode); + } + } else if (nmi_wd_enabled) +- apic->vcpu->kvm->arch.vapics_in_nmi_mode--; ++ atomic_dec(&apic->vcpu->kvm->arch.vapics_in_nmi_mode); + } + + static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) +@@ -1627,11 +1648,16 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu) + int vector = kvm_apic_has_interrupt(vcpu); + struct kvm_lapic *apic = vcpu->arch.apic; + +- /* Note that we never get here with APIC virtualization enabled. */ +- + if (vector == -1) + return -1; + ++ /* ++ * We get here even with APIC virtualization enabled, if doing ++ * nested virtualization and L1 runs with the "acknowledge interrupt ++ * on exit" mode. Then we cannot inject the interrupt via RVI, ++ * because the process would deliver it through the IDT. ++ */ ++ + apic_set_isr(vector, apic); + apic_update_ppr(apic); + apic_clear_irr(vector, apic); +diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h +index 6a11845..7205173 100644 +--- a/arch/x86/kvm/lapic.h ++++ b/arch/x86/kvm/lapic.h +@@ -165,7 +165,7 @@ static inline u16 apic_logical_id(struct kvm_apic_map *map, u32 ldr) + + static inline bool kvm_apic_has_events(struct kvm_vcpu *vcpu) + { +- return vcpu->arch.apic->pending_events; ++ return kvm_vcpu_has_lapic(vcpu) && vcpu->arch.apic->pending_events; + } + + bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector); +diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c +index 9b53135..dba56fb 100644 +--- a/arch/x86/kvm/mmu.c ++++ b/arch/x86/kvm/mmu.c +@@ -198,16 +198,20 @@ void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask) + EXPORT_SYMBOL_GPL(kvm_mmu_set_mmio_spte_mask); + + /* +- * spte bits of bit 3 ~ bit 11 are used as low 9 bits of generation number, +- * the bits of bits 52 ~ bit 61 are used as high 10 bits of generation +- * number. ++ * the low bit of the generation number is always presumed to be zero. ++ * This disables mmio caching during memslot updates. The concept is ++ * similar to a seqcount but instead of retrying the access we just punt ++ * and ignore the cache. ++ * ++ * spte bits 3-11 are used as bits 1-9 of the generation number, ++ * the bits 52-61 are used as bits 10-19 of the generation number. + */ +-#define MMIO_SPTE_GEN_LOW_SHIFT 3 ++#define MMIO_SPTE_GEN_LOW_SHIFT 2 + #define MMIO_SPTE_GEN_HIGH_SHIFT 52 + +-#define MMIO_GEN_SHIFT 19 +-#define MMIO_GEN_LOW_SHIFT 9 +-#define MMIO_GEN_LOW_MASK ((1 << MMIO_GEN_LOW_SHIFT) - 1) ++#define MMIO_GEN_SHIFT 20 ++#define MMIO_GEN_LOW_SHIFT 10 ++#define MMIO_GEN_LOW_MASK ((1 << MMIO_GEN_LOW_SHIFT) - 2) + #define MMIO_GEN_MASK ((1 << MMIO_GEN_SHIFT) - 1) + #define MMIO_MAX_GEN ((1 << MMIO_GEN_SHIFT) - 1) + +@@ -377,12 +381,6 @@ static u64 __get_spte_lockless(u64 *sptep) + { + return ACCESS_ONCE(*sptep); + } +- +-static bool __check_direct_spte_mmio_pf(u64 spte) +-{ +- /* It is valid if the spte is zapped. */ +- return spte == 0ull; +-} + #else + union split_spte { + struct { +@@ -498,23 +496,6 @@ retry: + + return spte.spte; + } +- +-static bool __check_direct_spte_mmio_pf(u64 spte) +-{ +- union split_spte sspte = (union split_spte)spte; +- u32 high_mmio_mask = shadow_mmio_mask >> 32; +- +- /* It is valid if the spte is zapped. */ +- if (spte == 0ull) +- return true; +- +- /* It is valid if the spte is being zapped. */ +- if (sspte.spte_low == 0ull && +- (sspte.spte_high & high_mmio_mask) == high_mmio_mask) +- return true; +- +- return false; +-} + #endif + + static bool spte_is_locklessly_modifiable(u64 spte) +@@ -3157,7 +3138,7 @@ static void mmu_sync_roots(struct kvm_vcpu *vcpu) + if (!VALID_PAGE(vcpu->arch.mmu.root_hpa)) + return; + +- vcpu_clear_mmio_info(vcpu, ~0ul); ++ vcpu_clear_mmio_info(vcpu, MMIO_GVA_ANY); + kvm_mmu_audit(vcpu, AUDIT_PRE_SYNC); + if (vcpu->arch.mmu.root_level == PT64_ROOT_LEVEL) { + hpa_t root = vcpu->arch.mmu.root_hpa; +@@ -3211,21 +3192,6 @@ static bool quickly_check_mmio_pf(struct kvm_vcpu *vcpu, u64 addr, bool direct) + return vcpu_match_mmio_gva(vcpu, addr); + } + +- +-/* +- * On direct hosts, the last spte is only allows two states +- * for mmio page fault: +- * - It is the mmio spte +- * - It is zapped or it is being zapped. +- * +- * This function completely checks the spte when the last spte +- * is not the mmio spte. +- */ +-static bool check_direct_spte_mmio_pf(u64 spte) +-{ +- return __check_direct_spte_mmio_pf(spte); +-} +- + static u64 walk_shadow_page_get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr) + { + struct kvm_shadow_walk_iterator iterator; +@@ -3268,13 +3234,6 @@ int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct) + } + + /* +- * It's ok if the gva is remapped by other cpus on shadow guest, +- * it's a BUG if the gfn is not a mmio page. +- */ +- if (direct && !check_direct_spte_mmio_pf(spte)) +- return RET_MMIO_PF_BUG; +- +- /* + * If the page table is zapped by other cpus, let CPU fault again on + * the address. + */ +@@ -4074,7 +4033,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, + ++vcpu->kvm->stat.mmu_pte_write; + kvm_mmu_audit(vcpu, AUDIT_PRE_PTE_WRITE); + +- mask.cr0_wp = mask.cr4_pae = mask.nxe = 1; ++ mask.cr0_wp = mask.cr4_pae = mask.nxe = mask.smep_andnot_wp = 1; + for_each_gfn_indirect_valid_sp(vcpu->kvm, sp, gfn) { + if (detect_write_misaligned(sp, gpa, bytes) || + detect_write_flooding(sp)) { +@@ -4379,8 +4338,8 @@ void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm) + * The very rare case: if the generation-number is round, + * zap all shadow pages. + */ +- if (unlikely(kvm_current_mmio_generation(kvm) >= MMIO_MAX_GEN)) { +- printk_ratelimited(KERN_INFO "kvm: zapping shadow pages for mmio generation wraparound\n"); ++ if (unlikely(kvm_current_mmio_generation(kvm) == 0)) { ++ printk_ratelimited(KERN_DEBUG "kvm: zapping shadow pages for mmio generation wraparound\n"); + kvm_mmu_invalidate_zap_all_pages(kvm); + } + } +diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c +index 2de1bc0..0746334 100644 +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -495,8 +495,10 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu) + { + struct vcpu_svm *svm = to_svm(vcpu); + +- if (svm->vmcb->control.next_rip != 0) ++ if (svm->vmcb->control.next_rip != 0) { ++ WARN_ON(!static_cpu_has(X86_FEATURE_NRIPS)); + svm->next_rip = svm->vmcb->control.next_rip; ++ } + + if (!svm->next_rip) { + if (emulate_instruction(vcpu, EMULTYPE_SKIP) != +@@ -3213,7 +3215,7 @@ static int wrmsr_interception(struct vcpu_svm *svm) + msr.host_initiated = false; + + svm->next_rip = kvm_rip_read(&svm->vcpu) + 2; +- if (svm_set_msr(&svm->vcpu, &msr)) { ++ if (kvm_set_msr(&svm->vcpu, &msr)) { + trace_kvm_msr_write_ex(ecx, data); + kvm_inject_gp(&svm->vcpu, 0); + } else { +@@ -3495,9 +3497,9 @@ static int handle_exit(struct kvm_vcpu *vcpu) + + if (exit_code >= ARRAY_SIZE(svm_exit_handlers) + || !svm_exit_handlers[exit_code]) { +- kvm_run->exit_reason = KVM_EXIT_UNKNOWN; +- kvm_run->hw.hardware_exit_reason = exit_code; +- return 0; ++ WARN_ONCE(1, "vmx: unexpected exit reason 0x%x\n", exit_code); ++ kvm_queue_exception(vcpu, UD_VECTOR); ++ return 1; + } + + return svm_exit_handlers[exit_code](svm); +@@ -4246,7 +4248,9 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu, + break; + } + +- vmcb->control.next_rip = info->next_rip; ++ /* TODO: Advertise NRIPS to guest hypervisor unconditionally */ ++ if (static_cpu_has(X86_FEATURE_NRIPS)) ++ vmcb->control.next_rip = info->next_rip; + vmcb->control.exit_code = icpt_info.exit_code; + vmexit = nested_svm_exit_handled(svm); + +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 3927528..80c22a3 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -441,6 +441,7 @@ struct vcpu_vmx { + #endif + int gs_ldt_reload_needed; + int fs_reload_needed; ++ unsigned long vmcs_host_cr4; /* May not match real cr4 */ + } host_state; + struct { + int vm86_active; +@@ -2320,12 +2321,12 @@ static __init void nested_vmx_setup_ctls_msrs(void) + nested_vmx_secondary_ctls_low = 0; + nested_vmx_secondary_ctls_high &= + SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | +- SECONDARY_EXEC_UNRESTRICTED_GUEST | + SECONDARY_EXEC_WBINVD_EXITING; + + if (enable_ept) { + /* nested EPT: emulate EPT also to L1 */ +- nested_vmx_secondary_ctls_high |= SECONDARY_EXEC_ENABLE_EPT; ++ nested_vmx_secondary_ctls_high |= SECONDARY_EXEC_ENABLE_EPT | ++ SECONDARY_EXEC_UNRESTRICTED_GUEST; + nested_vmx_ept_caps = VMX_EPT_PAGE_WALK_4_BIT | + VMX_EPTP_WB_BIT | VMX_EPT_2MB_PAGE_BIT | + VMX_EPT_INVEPT_BIT; +@@ -2582,12 +2583,15 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) + default: + msr = find_msr_entry(vmx, msr_index); + if (msr) { ++ u64 old_msr_data = msr->data; + msr->data = data; + if (msr - vmx->guest_msrs < vmx->save_nmsrs) { + preempt_disable(); +- kvm_set_shared_msr(msr->index, msr->data, +- msr->mask); ++ ret = kvm_set_shared_msr(msr->index, msr->data, ++ msr->mask); + preempt_enable(); ++ if (ret) ++ msr->data = old_msr_data; + } + break; + } +@@ -4162,11 +4166,16 @@ static void vmx_set_constant_host_state(struct vcpu_vmx *vmx) + u32 low32, high32; + unsigned long tmpl; + struct desc_ptr dt; ++ unsigned long cr4; + + vmcs_writel(HOST_CR0, read_cr0() & ~X86_CR0_TS); /* 22.2.3 */ +- vmcs_writel(HOST_CR4, read_cr4()); /* 22.2.3, 22.2.5 */ + vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */ + ++ /* Save the most likely value for this task's CR4 in the VMCS. */ ++ cr4 = read_cr4(); ++ vmcs_writel(HOST_CR4, cr4); /* 22.2.3, 22.2.5 */ ++ vmx->host_state.vmcs_host_cr4 = cr4; ++ + vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */ + #ifdef CONFIG_X86_64 + /* +@@ -5169,7 +5178,7 @@ static int handle_wrmsr(struct kvm_vcpu *vcpu) + msr.data = data; + msr.index = ecx; + msr.host_initiated = false; +- if (vmx_set_msr(vcpu, &msr) != 0) { ++ if (kvm_set_msr(vcpu, &msr) != 0) { + trace_kvm_msr_write_ex(ecx, data); + kvm_inject_gp(vcpu, 0); + return 1; +@@ -6441,6 +6450,12 @@ static int handle_invept(struct kvm_vcpu *vcpu) + return 1; + } + ++static int handle_invvpid(struct kvm_vcpu *vcpu) ++{ ++ kvm_queue_exception(vcpu, UD_VECTOR); ++ return 1; ++} ++ + /* + * The exit handlers return 1 if the exit was handled fully and guest execution + * may resume. Otherwise they set the kvm_run parameter to indicate what needs +@@ -6486,6 +6501,7 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = { + [EXIT_REASON_MWAIT_INSTRUCTION] = handle_invalid_op, + [EXIT_REASON_MONITOR_INSTRUCTION] = handle_invalid_op, + [EXIT_REASON_INVEPT] = handle_invept, ++ [EXIT_REASON_INVVPID] = handle_invvpid, + }; + + static const int kvm_vmx_max_exit_handlers = +@@ -6719,7 +6735,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu) + case EXIT_REASON_VMPTRST: case EXIT_REASON_VMREAD: + case EXIT_REASON_VMRESUME: case EXIT_REASON_VMWRITE: + case EXIT_REASON_VMOFF: case EXIT_REASON_VMON: +- case EXIT_REASON_INVEPT: ++ case EXIT_REASON_INVEPT: case EXIT_REASON_INVVPID: + /* + * VMX instructions trap unconditionally. This allows L1 to + * emulate them for its L2 guest, i.e., allows 3-level nesting! +@@ -6884,10 +6900,10 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu) + && kvm_vmx_exit_handlers[exit_reason]) + return kvm_vmx_exit_handlers[exit_reason](vcpu); + else { +- vcpu->run->exit_reason = KVM_EXIT_UNKNOWN; +- vcpu->run->hw.hardware_exit_reason = exit_reason; ++ WARN_ONCE(1, "vmx: unexpected exit reason 0x%x\n", exit_reason); ++ kvm_queue_exception(vcpu, UD_VECTOR); ++ return 1; + } +- return 0; + } + + static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr) +@@ -7186,7 +7202,7 @@ static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx) + static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) + { + struct vcpu_vmx *vmx = to_vmx(vcpu); +- unsigned long debugctlmsr; ++ unsigned long debugctlmsr, cr4; + + /* Record the guest's net vcpu time for enforced NMI injections. */ + if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked)) +@@ -7207,6 +7223,12 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) + if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty)) + vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]); + ++ cr4 = read_cr4(); ++ if (unlikely(cr4 != vmx->host_state.vmcs_host_cr4)) { ++ vmcs_writel(HOST_CR4, cr4); ++ vmx->host_state.vmcs_host_cr4 = cr4; ++ } ++ + /* When single-stepping over STI and MOV SS, we must clear the + * corresponding interruptibility bits in the guest state. Otherwise + * vmentry fails as it then expects bit 14 (BS) in pending debug +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 8fbd1a7..1777f89 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -225,20 +225,25 @@ static void kvm_shared_msr_cpu_online(void) + shared_msr_update(i, shared_msrs_global.msrs[i]); + } + +-void kvm_set_shared_msr(unsigned slot, u64 value, u64 mask) ++int kvm_set_shared_msr(unsigned slot, u64 value, u64 mask) + { + unsigned int cpu = smp_processor_id(); + struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu); ++ int err; + + if (((value ^ smsr->values[slot].curr) & mask) == 0) +- return; ++ return 0; + smsr->values[slot].curr = value; +- wrmsrl(shared_msrs_global.msrs[slot], value); ++ err = wrmsrl_safe(shared_msrs_global.msrs[slot], value); ++ if (err) ++ return 1; ++ + if (!smsr->registered) { + smsr->urn.on_user_return = kvm_on_user_return; + user_return_notifier_register(&smsr->urn); + smsr->registered = true; + } ++ return 0; + } + EXPORT_SYMBOL_GPL(kvm_set_shared_msr); + +@@ -946,7 +951,6 @@ void kvm_enable_efer_bits(u64 mask) + } + EXPORT_SYMBOL_GPL(kvm_enable_efer_bits); + +- + /* + * Writes msr value into into the appropriate "register". + * Returns 0 on success, non-0 otherwise. +@@ -954,8 +958,34 @@ EXPORT_SYMBOL_GPL(kvm_enable_efer_bits); + */ + int kvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) + { ++ switch (msr->index) { ++ case MSR_FS_BASE: ++ case MSR_GS_BASE: ++ case MSR_KERNEL_GS_BASE: ++ case MSR_CSTAR: ++ case MSR_LSTAR: ++ if (is_noncanonical_address(msr->data)) ++ return 1; ++ break; ++ case MSR_IA32_SYSENTER_EIP: ++ case MSR_IA32_SYSENTER_ESP: ++ /* ++ * IA32_SYSENTER_ESP and IA32_SYSENTER_EIP cause #GP if ++ * non-canonical address is written on Intel but not on ++ * AMD (which ignores the top 32-bits, because it does ++ * not implement 64-bit SYSENTER). ++ * ++ * 64-bit code should hence be able to write a non-canonical ++ * value on AMD. Making the address canonical ensures that ++ * vmentry does not fail on Intel after writing a non-canonical ++ * value, and that something deterministic happens if the guest ++ * invokes 64-bit SYSENTER. ++ */ ++ msr->data = get_canonical(msr->data); ++ } + return kvm_x86_ops->set_msr(vcpu, msr); + } ++EXPORT_SYMBOL_GPL(kvm_set_msr); + + /* + * Adapt set_msr() to msr_io()'s calling convention +@@ -1177,21 +1207,22 @@ void kvm_track_tsc_matching(struct kvm_vcpu *vcpu) + { + #ifdef CONFIG_X86_64 + bool vcpus_matched; +- bool do_request = false; + struct kvm_arch *ka = &vcpu->kvm->arch; + struct pvclock_gtod_data *gtod = &pvclock_gtod_data; + + vcpus_matched = (ka->nr_vcpus_matched_tsc + 1 == + atomic_read(&vcpu->kvm->online_vcpus)); + +- if (vcpus_matched && gtod->clock.vclock_mode == VCLOCK_TSC) +- if (!ka->use_master_clock) +- do_request = 1; +- +- if (!vcpus_matched && ka->use_master_clock) +- do_request = 1; +- +- if (do_request) ++ /* ++ * Once the masterclock is enabled, always perform request in ++ * order to update it. ++ * ++ * In order to enable masterclock, the host clocksource must be TSC ++ * and the vcpus need to have matched TSCs. When that happens, ++ * perform request to enable masterclock. ++ */ ++ if (ka->use_master_clock || ++ (gtod->clock.vclock_mode == VCLOCK_TSC && vcpus_matched)) + kvm_make_request(KVM_REQ_MASTERCLOCK_UPDATE, vcpu); + + trace_kvm_track_tsc(vcpu->vcpu_id, ka->nr_vcpus_matched_tsc, +@@ -4881,7 +4912,7 @@ static int handle_emulation_failure(struct kvm_vcpu *vcpu) + + ++vcpu->stat.insn_emulation_fail; + trace_kvm_emulate_insn_failed(vcpu); +- if (!is_guest_mode(vcpu)) { ++ if (!is_guest_mode(vcpu) && kvm_x86_ops->get_cpl(vcpu) == 0) { + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION; + vcpu->run->internal.ndata = 0; +diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h +index 8da5823..21ea4fc 100644 +--- a/arch/x86/kvm/x86.h ++++ b/arch/x86/kvm/x86.h +@@ -78,15 +78,23 @@ static inline void vcpu_cache_mmio_info(struct kvm_vcpu *vcpu, + vcpu->arch.mmio_gva = gva & PAGE_MASK; + vcpu->arch.access = access; + vcpu->arch.mmio_gfn = gfn; ++ vcpu->arch.mmio_gen = kvm_memslots(vcpu->kvm)->generation; ++} ++ ++static inline bool vcpu_match_mmio_gen(struct kvm_vcpu *vcpu) ++{ ++ return vcpu->arch.mmio_gen == kvm_memslots(vcpu->kvm)->generation; + } + + /* +- * Clear the mmio cache info for the given gva, +- * specially, if gva is ~0ul, we clear all mmio cache info. ++ * Clear the mmio cache info for the given gva. If gva is MMIO_GVA_ANY, we ++ * clear all mmio cache info. + */ ++#define MMIO_GVA_ANY (~(gva_t)0) ++ + static inline void vcpu_clear_mmio_info(struct kvm_vcpu *vcpu, gva_t gva) + { +- if (gva != (~0ul) && vcpu->arch.mmio_gva != (gva & PAGE_MASK)) ++ if (gva != MMIO_GVA_ANY && vcpu->arch.mmio_gva != (gva & PAGE_MASK)) + return; + + vcpu->arch.mmio_gva = 0; +@@ -94,7 +102,8 @@ static inline void vcpu_clear_mmio_info(struct kvm_vcpu *vcpu, gva_t gva) + + static inline bool vcpu_match_mmio_gva(struct kvm_vcpu *vcpu, unsigned long gva) + { +- if (vcpu->arch.mmio_gva && vcpu->arch.mmio_gva == (gva & PAGE_MASK)) ++ if (vcpu_match_mmio_gen(vcpu) && vcpu->arch.mmio_gva && ++ vcpu->arch.mmio_gva == (gva & PAGE_MASK)) + return true; + + return false; +@@ -102,7 +111,8 @@ static inline bool vcpu_match_mmio_gva(struct kvm_vcpu *vcpu, unsigned long gva) + + static inline bool vcpu_match_mmio_gpa(struct kvm_vcpu *vcpu, gpa_t gpa) + { +- if (vcpu->arch.mmio_gfn && vcpu->arch.mmio_gfn == gpa >> PAGE_SHIFT) ++ if (vcpu_match_mmio_gen(vcpu) && vcpu->arch.mmio_gfn && ++ vcpu->arch.mmio_gfn == gpa >> PAGE_SHIFT) + return true; + + return false; +diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c +index 0002a3a..3620928 100644 +--- a/arch/x86/mm/dump_pagetables.c ++++ b/arch/x86/mm/dump_pagetables.c +@@ -30,11 +30,13 @@ struct pg_state { + unsigned long start_address; + unsigned long current_address; + const struct addr_marker *marker; ++ unsigned long lines; + }; + + struct addr_marker { + unsigned long start_address; + const char *name; ++ unsigned long max_lines; + }; + + /* indices for address_markers; keep sync'd w/ address_markers below */ +@@ -45,6 +47,7 @@ enum address_markers_idx { + LOW_KERNEL_NR, + VMALLOC_START_NR, + VMEMMAP_START_NR, ++ ESPFIX_START_NR, + HIGH_KERNEL_NR, + MODULES_VADDR_NR, + MODULES_END_NR, +@@ -67,6 +70,7 @@ static struct addr_marker address_markers[] = { + { PAGE_OFFSET, "Low Kernel Mapping" }, + { VMALLOC_START, "vmalloc() Area" }, + { VMEMMAP_START, "Vmemmap" }, ++ { ESPFIX_BASE_ADDR, "ESPfix Area", 16 }, + { __START_KERNEL_map, "High Kernel Mapping" }, + { MODULES_VADDR, "Modules" }, + { MODULES_END, "End Modules" }, +@@ -163,7 +167,7 @@ static void note_page(struct seq_file *m, struct pg_state *st, + pgprot_t new_prot, int level) + { + pgprotval_t prot, cur; +- static const char units[] = "KMGTPE"; ++ static const char units[] = "BKMGTPE"; + + /* + * If we have a "break" in the series, we need to flush the state that +@@ -178,6 +182,7 @@ static void note_page(struct seq_file *m, struct pg_state *st, + st->current_prot = new_prot; + st->level = level; + st->marker = address_markers; ++ st->lines = 0; + seq_printf(m, "---[ %s ]---\n", st->marker->name); + } else if (prot != cur || level != st->level || + st->current_address >= st->marker[1].start_address) { +@@ -188,17 +193,21 @@ static void note_page(struct seq_file *m, struct pg_state *st, + /* + * Now print the actual finished series + */ +- seq_printf(m, "0x%0*lx-0x%0*lx ", +- width, st->start_address, +- width, st->current_address); +- +- delta = (st->current_address - st->start_address) >> 10; +- while (!(delta & 1023) && unit[1]) { +- delta >>= 10; +- unit++; ++ if (!st->marker->max_lines || ++ st->lines < st->marker->max_lines) { ++ seq_printf(m, "0x%0*lx-0x%0*lx ", ++ width, st->start_address, ++ width, st->current_address); ++ ++ delta = (st->current_address - st->start_address) >> 10; ++ while (!(delta & 1023) && unit[1]) { ++ delta >>= 10; ++ unit++; ++ } ++ seq_printf(m, "%9lu%c ", delta, *unit); ++ printk_prot(m, st->current_prot, st->level); + } +- seq_printf(m, "%9lu%c ", delta, *unit); +- printk_prot(m, st->current_prot, st->level); ++ st->lines++; + + /* + * We print markers for special areas of address space, +diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c +index a10c8c7..ebc551c 100644 +--- a/arch/x86/mm/fault.c ++++ b/arch/x86/mm/fault.c +@@ -833,11 +833,8 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, + unsigned int fault) + { + struct task_struct *tsk = current; +- struct mm_struct *mm = tsk->mm; + int code = BUS_ADRERR; + +- up_read(&mm->mmap_sem); +- + /* Kernel mode? Handle exceptions or die: */ + if (!(error_code & PF_USER)) { + no_context(regs, error_code, address, SIGBUS, BUS_ADRERR); +@@ -868,7 +865,6 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, + unsigned long address, unsigned int fault) + { + if (fatal_signal_pending(current) && !(error_code & PF_USER)) { +- up_read(¤t->mm->mmap_sem); + no_context(regs, error_code, address, 0, 0); + return; + } +@@ -876,14 +872,11 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, + if (fault & VM_FAULT_OOM) { + /* Kernel mode? Handle exceptions or die: */ + if (!(error_code & PF_USER)) { +- up_read(¤t->mm->mmap_sem); + no_context(regs, error_code, address, + SIGSEGV, SEGV_MAPERR); + return; + } + +- up_read(¤t->mm->mmap_sem); +- + /* + * We ran out of memory, call the OOM killer, and return the + * userspace (which will retry the fault, or kill us if we got +@@ -894,6 +887,8 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, + if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON| + VM_FAULT_HWPOISON_LARGE)) + do_sigbus(regs, error_code, address, fault); ++ else if (fault & VM_FAULT_SIGSEGV) ++ bad_area_nosemaphore(regs, error_code, address); + else + BUG(); + } +@@ -1216,6 +1211,7 @@ good_area: + return; + + if (unlikely(fault & VM_FAULT_ERROR)) { ++ up_read(&mm->mmap_sem); + mm_fault_error(regs, error_code, address, fault); + return; + } +diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c +index 207d9aef..448ee89 100644 +--- a/arch/x86/mm/gup.c ++++ b/arch/x86/mm/gup.c +@@ -172,7 +172,7 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end, + */ + if (pmd_none(pmd) || pmd_trans_splitting(pmd)) + return 0; +- if (unlikely(pmd_large(pmd))) { ++ if (unlikely(pmd_large(pmd) || !pmd_present(pmd))) { + /* + * NUMA hinting faults need to be handled in the GUP + * slowpath for accounting purposes and so that they +diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c +index 8b977eb..006cc91 100644 +--- a/arch/x86/mm/hugetlbpage.c ++++ b/arch/x86/mm/hugetlbpage.c +@@ -66,9 +66,15 @@ follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) + return ERR_PTR(-EINVAL); + } + ++/* ++ * pmd_huge() returns 1 if @pmd is hugetlb related entry, that is normal ++ * hugetlb entry or non-present (migration or hwpoisoned) hugetlb entry. ++ * Otherwise, returns 0. ++ */ + int pmd_huge(pmd_t pmd) + { +- return !!(pmd_val(pmd) & _PAGE_PSE); ++ return !pmd_none(pmd) && ++ (pmd_val(pmd) & (_PAGE_PRESENT|_PAGE_PSE)) != _PAGE_PRESENT; + } + + int pud_huge(pud_t pud) +diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c +index f35c66c..2308a40 100644 +--- a/arch/x86/mm/init_64.c ++++ b/arch/x86/mm/init_64.c +@@ -1110,7 +1110,7 @@ void mark_rodata_ro(void) + unsigned long end = (unsigned long) &__end_rodata_hpage_align; + unsigned long text_end = PFN_ALIGN(&__stop___ex_table); + unsigned long rodata_end = PFN_ALIGN(&__end_rodata); +- unsigned long all_end = PFN_ALIGN(&_end); ++ unsigned long all_end; + + printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", + (end - start) >> 10); +@@ -1121,7 +1121,16 @@ void mark_rodata_ro(void) + /* + * The rodata/data/bss/brk section (but not the kernel text!) + * should also be not-executable. ++ * ++ * We align all_end to PMD_SIZE because the existing mapping ++ * is a full PMD. If we would align _brk_end to PAGE_SIZE we ++ * split the PMD and the reminder between _brk_end and the end ++ * of the PMD will remain mapped executable. ++ * ++ * Any PMD which was setup after the one which covers _brk_end ++ * has been zapped already via cleanup_highmem(). + */ ++ all_end = roundup((unsigned long)_brk_end, PMD_SIZE); + set_memory_nx(rodata_start, (all_end - rodata_start) >> PAGE_SHIFT); + + rodata_test(); +diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c +index 25e7e13..3601ff2 100644 +--- a/arch/x86/mm/mmap.c ++++ b/arch/x86/mm/mmap.c +@@ -35,12 +35,12 @@ struct __read_mostly va_alignment va_align = { + .flags = -1, + }; + +-static unsigned int stack_maxrandom_size(void) ++static unsigned long stack_maxrandom_size(void) + { +- unsigned int max = 0; ++ unsigned long max = 0; + if ((current->flags & PF_RANDOMIZE) && + !(current->personality & ADDR_NO_RANDOMIZE)) { +- max = ((-1U) & STACK_RND_MASK) << PAGE_SHIFT; ++ max = ((-1UL) & STACK_RND_MASK) << PAGE_SHIFT; + } + + return max; +diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c +index a348868..fed892d 100644 +--- a/arch/x86/mm/pageattr.c ++++ b/arch/x86/mm/pageattr.c +@@ -405,7 +405,7 @@ phys_addr_t slow_virt_to_phys(void *__virt_addr) + psize = page_level_size(level); + pmask = page_level_mask(level); + offset = virt_addr & ~pmask; +- phys_addr = pte_pfn(*pte) << PAGE_SHIFT; ++ phys_addr = (phys_addr_t)pte_pfn(*pte) << PAGE_SHIFT; + return (phys_addr | offset); + } + EXPORT_SYMBOL_GPL(slow_virt_to_phys); +diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c +index c96314a..0004ac7 100644 +--- a/arch/x86/mm/pgtable.c ++++ b/arch/x86/mm/pgtable.c +@@ -399,13 +399,20 @@ int pmdp_test_and_clear_young(struct vm_area_struct *vma, + int ptep_clear_flush_young(struct vm_area_struct *vma, + unsigned long address, pte_t *ptep) + { +- int young; +- +- young = ptep_test_and_clear_young(vma, address, ptep); +- if (young) +- flush_tlb_page(vma, address); +- +- return young; ++ /* ++ * On x86 CPUs, clearing the accessed bit without a TLB flush ++ * doesn't cause data corruption. [ It could cause incorrect ++ * page aging and the (mistaken) reclaim of hot pages, but the ++ * chance of that should be relatively low. ] ++ * ++ * So as a performance optimization don't flush the TLB when ++ * clearing the accessed bit, it will eventually be flushed by ++ * a context switch or a VM operation anyway. [ In the rare ++ * event of it not getting flushed for a long time the delay ++ * shouldn't really matter because there's no real memory ++ * pressure for swapout to react to. ] ++ */ ++ return ptep_test_and_clear_young(vma, address, ptep); + } + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE +diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c +index af2d431..1fed139 100644 +--- a/arch/x86/net/bpf_jit_comp.c ++++ b/arch/x86/net/bpf_jit_comp.c +@@ -211,7 +211,12 @@ void bpf_jit_compile(struct sk_filter *fp) + } + cleanup_addr = proglen; /* epilogue address */ + +- for (pass = 0; pass < 10; pass++) { ++ /* JITed image shrinks with every pass and the loop iterates ++ * until the image stops shrinking. Very large bpf programs ++ * may converge on the last pass. In such case do one more ++ * pass to emit the final image ++ */ ++ for (pass = 0; pass < 10 || image; pass++) { + u8 seen_or_pass0 = (pass == 0) ? (SEEN_XREG | SEEN_DATAREF | SEEN_MEM) : seen; + /* no prologue/epilogue for trivial filters (RET something) */ + proglen = 0; +diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c +index 4f25ec0..bf00138 100644 +--- a/arch/x86/pci/acpi.c ++++ b/arch/x86/pci/acpi.c +@@ -84,6 +84,17 @@ static const struct dmi_system_id pci_crs_quirks[] __initconst = { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"), + }, + }, ++ /* https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/931368 */ ++ /* https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/1033299 */ ++ { ++ .callback = set_use_crs, ++ .ident = "Foxconn K8M890-8237A", ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Foxconn"), ++ DMI_MATCH(DMI_BOARD_NAME, "K8M890-8237A"), ++ DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"), ++ }, ++ }, + + /* Now for the blacklist.. */ + +@@ -124,8 +135,10 @@ void __init pci_acpi_crs_quirks(void) + { + int year; + +- if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008) +- pci_use_crs = false; ++ if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008) { ++ if (iomem_resource.end <= 0xffffffff) ++ pci_use_crs = false; ++ } + + dmi_check_system(pci_crs_quirks); + +diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c +index 981c2db..88f143d 100644 +--- a/arch/x86/pci/common.c ++++ b/arch/x86/pci/common.c +@@ -448,6 +448,22 @@ static const struct dmi_system_id pciprobe_dmi_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "ftServer"), + }, + }, ++ { ++ .callback = set_scan_all, ++ .ident = "Stratus/NEC ftServer", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "NEC"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Express5800/R32"), ++ }, ++ }, ++ { ++ .callback = set_scan_all, ++ .ident = "Stratus/NEC ftServer", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "NEC"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Express5800/R31"), ++ }, ++ }, + {} + }; + +diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c +index db6b1ab..96a159a 100644 +--- a/arch/x86/pci/i386.c ++++ b/arch/x86/pci/i386.c +@@ -162,6 +162,10 @@ pcibios_align_resource(void *data, const struct resource *res, + return start; + if (start & 0x300) + start = (start + 0x3ff) & ~0x3ff; ++ } else if (res->flags & IORESOURCE_MEM) { ++ /* The low 1MB range is reserved for ISA cards */ ++ if (start < BIOS_END) ++ start = BIOS_END; + } + return start; + } +diff --git a/arch/x86/power/hibernate_32.c b/arch/x86/power/hibernate_32.c +index 7d28c88..291226b 100644 +--- a/arch/x86/power/hibernate_32.c ++++ b/arch/x86/power/hibernate_32.c +@@ -13,13 +13,11 @@ + #include + #include + #include ++#include + + /* Defined in hibernate_asm_32.S */ + extern int restore_image(void); + +-/* References to section boundaries */ +-extern const void __nosave_begin, __nosave_end; +- + /* Pointer to the temporary resume page tables */ + pgd_t *resume_pg_dir; + +diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c +index 304fca2..2276238 100644 +--- a/arch/x86/power/hibernate_64.c ++++ b/arch/x86/power/hibernate_64.c +@@ -17,11 +17,9 @@ + #include + #include + #include ++#include + #include + +-/* References to section boundaries */ +-extern __visible const void __nosave_begin, __nosave_end; +- + /* Defined in hibernate_asm_64.S */ + extern asmlinkage int restore_image(void); + +diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c +index 531d426..bd16d6c 100644 +--- a/arch/x86/um/sys_call_table_32.c ++++ b/arch/x86/um/sys_call_table_32.c +@@ -34,7 +34,7 @@ typedef asmlinkage void (*sys_call_ptr_t)(void); + + extern asmlinkage void sys_ni_syscall(void); + +-const sys_call_ptr_t sys_call_table[] __cacheline_aligned = { ++const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = { + /* + * Smells like a compiler bug -- it doesn't work + * when the & below is removed. +diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c +index f2f0723..9578308 100644 +--- a/arch/x86/um/sys_call_table_64.c ++++ b/arch/x86/um/sys_call_table_64.c +@@ -46,7 +46,7 @@ typedef void (*sys_call_ptr_t)(void); + + extern void sys_ni_syscall(void); + +-const sys_call_ptr_t sys_call_table[] __cacheline_aligned = { ++const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = { + /* + * Smells like a compiler bug -- it doesn't work + * when the & below is removed. +diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c +index f1d633a..d6bfb87 100644 +--- a/arch/x86/vdso/vdso32-setup.c ++++ b/arch/x86/vdso/vdso32-setup.c +@@ -41,7 +41,6 @@ enum { + #ifdef CONFIG_X86_64 + #define vdso_enabled sysctl_vsyscall32 + #define arch_setup_additional_pages syscall32_setup_pages +-extern int sysctl_ldt16; + #endif + + /* +@@ -381,13 +380,6 @@ static struct ctl_table abi_table2[] = { + .mode = 0644, + .proc_handler = proc_dointvec + }, +- { +- .procname = "ldt16", +- .data = &sysctl_ldt16, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = proc_dointvec +- }, + {} + }; + +diff --git a/arch/x86/vdso/vdso32/sigreturn.S b/arch/x86/vdso/vdso32/sigreturn.S +index 31776d0..d7ec4e2 100644 +--- a/arch/x86/vdso/vdso32/sigreturn.S ++++ b/arch/x86/vdso/vdso32/sigreturn.S +@@ -17,6 +17,7 @@ + .text + .globl __kernel_sigreturn + .type __kernel_sigreturn,@function ++ nop /* this guy is needed for .LSTARTFDEDLSI1 below (watch for HACK) */ + ALIGN + __kernel_sigreturn: + .LSTART_sigreturn: +diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c +index 431e875..ab6ba35 100644 +--- a/arch/x86/vdso/vma.c ++++ b/arch/x86/vdso/vma.c +@@ -117,30 +117,45 @@ subsys_initcall(init_vdso); + + struct linux_binprm; + +-/* Put the vdso above the (randomized) stack with another randomized offset. +- This way there is no hole in the middle of address space. +- To save memory make sure it is still in the same PTE as the stack top. +- This doesn't give that many random bits */ ++/* ++ * Put the vdso above the (randomized) stack with another randomized ++ * offset. This way there is no hole in the middle of address space. ++ * To save memory make sure it is still in the same PTE as the stack ++ * top. This doesn't give that many random bits. ++ * ++ * Note that this algorithm is imperfect: the distribution of the vdso ++ * start address within a PMD is biased toward the end. ++ * ++ * Only used for the 64-bit and x32 vdsos. ++ */ + static unsigned long vdso_addr(unsigned long start, unsigned len) + { + unsigned long addr, end; + unsigned offset; +- end = (start + PMD_SIZE - 1) & PMD_MASK; ++ ++ /* ++ * Round up the start address. It can start out unaligned as a result ++ * of stack start randomization. ++ */ ++ start = PAGE_ALIGN(start); ++ ++ /* Round the lowest possible end address up to a PMD boundary. */ ++ end = (start + len + PMD_SIZE - 1) & PMD_MASK; + if (end >= TASK_SIZE_MAX) + end = TASK_SIZE_MAX; + end -= len; +- /* This loses some more bits than a modulo, but is cheaper */ +- offset = get_random_int() & (PTRS_PER_PTE - 1); +- addr = start + (offset << PAGE_SHIFT); +- if (addr >= end) +- addr = end; ++ ++ if (end > start) { ++ offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1); ++ addr = start + (offset << PAGE_SHIFT); ++ } else { ++ addr = start; ++ } + + /* +- * page-align it here so that get_unmapped_area doesn't +- * align it wrongfully again to the next page. addr can come in 4K +- * unaligned here as a result of stack start randomization. ++ * Forcibly align the final address in case we have a hardware ++ * issue that requires alignment for performance reasons. + */ +- addr = PAGE_ALIGN(addr); + addr = align_vdso_addr(addr); + + return addr; +diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c +index 201d09a..2302f10 100644 +--- a/arch/x86/xen/enlighten.c ++++ b/arch/x86/xen/enlighten.c +@@ -481,6 +481,7 @@ static void set_aliased_prot(void *v, pgprot_t prot) + pte_t pte; + unsigned long pfn; + struct page *page; ++ unsigned char dummy; + + ptep = lookup_address((unsigned long)v, &level); + BUG_ON(ptep == NULL); +@@ -490,6 +491,32 @@ static void set_aliased_prot(void *v, pgprot_t prot) + + pte = pfn_pte(pfn, prot); + ++ /* ++ * Careful: update_va_mapping() will fail if the virtual address ++ * we're poking isn't populated in the page tables. We don't ++ * need to worry about the direct map (that's always in the page ++ * tables), but we need to be careful about vmap space. In ++ * particular, the top level page table can lazily propagate ++ * entries between processes, so if we've switched mms since we ++ * vmapped the target in the first place, we might not have the ++ * top-level page table entry populated. ++ * ++ * We disable preemption because we want the same mm active when ++ * we probe the target and when we issue the hypercall. We'll ++ * have the same nominal mm, but if we're a kernel thread, lazy ++ * mm dropping could change our pgd. ++ * ++ * Out of an abundance of caution, this uses __get_user() to fault ++ * in the target address just in case there's some obscure case ++ * in which the target address isn't readable. ++ */ ++ ++ preempt_disable(); ++ ++ pagefault_disable(); /* Avoid warnings due to being atomic. */ ++ __get_user(dummy, (unsigned char __user __force *)v); ++ pagefault_enable(); ++ + if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0)) + BUG(); + +@@ -501,6 +528,8 @@ static void set_aliased_prot(void *v, pgprot_t prot) + BUG(); + } else + kmap_flush_unused(); ++ ++ preempt_enable(); + } + + static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries) +@@ -508,6 +537,17 @@ static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries) + const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE; + int i; + ++ /* ++ * We need to mark the all aliases of the LDT pages RO. We ++ * don't need to call vm_flush_aliases(), though, since that's ++ * only responsible for flushing aliases out the TLBs, not the ++ * page tables, and Xen will flush the TLB for us if needed. ++ * ++ * To avoid confusing future readers: none of this is necessary ++ * to load the LDT. The hypervisor only checks this when the ++ * LDT is faulted in due to subsequent descriptor access. ++ */ ++ + for(i = 0; i < entries; i += entries_per_page) + set_aliased_prot(ldt + i, PAGE_KERNEL_RO); + } +diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c +index c985835..5b406fc 100644 +--- a/arch/x86/xen/grant-table.c ++++ b/arch/x86/xen/grant-table.c +@@ -134,6 +134,7 @@ static int __init xlated_setup_gnttab_pages(void) + { + struct page **pages; + xen_pfn_t *pfns; ++ void *vaddr; + int rc; + unsigned int i; + unsigned long nr_grant_frames = gnttab_max_grant_frames(); +@@ -159,21 +160,20 @@ static int __init xlated_setup_gnttab_pages(void) + for (i = 0; i < nr_grant_frames; i++) + pfns[i] = page_to_pfn(pages[i]); + +- rc = arch_gnttab_map_shared(pfns, nr_grant_frames, nr_grant_frames, +- &xen_auto_xlat_grant_frames.vaddr); +- +- if (rc) { ++ vaddr = vmap(pages, nr_grant_frames, 0, PAGE_KERNEL); ++ if (!vaddr) { + pr_warn("%s Couldn't map %ld pfns rc:%d\n", __func__, + nr_grant_frames, rc); + free_xenballooned_pages(nr_grant_frames, pages); + kfree(pages); + kfree(pfns); +- return rc; ++ return -ENOMEM; + } + kfree(pages); + + xen_auto_xlat_grant_frames.pfn = pfns; + xen_auto_xlat_grant_frames.count = nr_grant_frames; ++ xen_auto_xlat_grant_frames.vaddr = vaddr; + + return 0; + } +diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c +index 2423ef0..c83da6f 100644 +--- a/arch/x86/xen/mmu.c ++++ b/arch/x86/xen/mmu.c +@@ -1866,12 +1866,11 @@ static void __init check_pt_base(unsigned long *pt_base, unsigned long *pt_end, + * + * We can construct this by grafting the Xen provided pagetable into + * head_64.S's preconstructed pagetables. We copy the Xen L2's into +- * level2_ident_pgt, level2_kernel_pgt and level2_fixmap_pgt. This +- * means that only the kernel has a physical mapping to start with - +- * but that's enough to get __va working. We need to fill in the rest +- * of the physical mapping once some sort of allocator has been set +- * up. +- * NOTE: for PVH, the page tables are native. ++ * level2_ident_pgt, and level2_kernel_pgt. This means that only the ++ * kernel has a physical mapping to start with - but that's enough to ++ * get __va working. We need to fill in the rest of the physical ++ * mapping once some sort of allocator has been set up. NOTE: for ++ * PVH, the page tables are native. + */ + void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) + { +@@ -1902,8 +1901,11 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) + /* L3_i[0] -> level2_ident_pgt */ + convert_pfn_mfn(level3_ident_pgt); + /* L3_k[510] -> level2_kernel_pgt +- * L3_i[511] -> level2_fixmap_pgt */ ++ * L3_k[511] -> level2_fixmap_pgt */ + convert_pfn_mfn(level3_kernel_pgt); ++ ++ /* L3_k[511][506] -> level1_fixmap_pgt */ ++ convert_pfn_mfn(level2_fixmap_pgt); + } + /* We get [511][511] and have Xen's version of level2_kernel_pgt */ + l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd); +@@ -1913,21 +1915,15 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) + addr[1] = (unsigned long)l3; + addr[2] = (unsigned long)l2; + /* Graft it onto L4[272][0]. Note that we creating an aliasing problem: +- * Both L4[272][0] and L4[511][511] have entries that point to the same ++ * Both L4[272][0] and L4[511][510] have entries that point to the same + * L2 (PMD) tables. Meaning that if you modify it in __va space + * it will be also modified in the __ka space! (But if you just + * modify the PMD table to point to other PTE's or none, then you + * are OK - which is what cleanup_highmap does) */ + copy_page(level2_ident_pgt, l2); +- /* Graft it onto L4[511][511] */ ++ /* Graft it onto L4[511][510] */ + copy_page(level2_kernel_pgt, l2); + +- /* Get [511][510] and graft that in level2_fixmap_pgt */ +- l3 = m2v(pgd[pgd_index(__START_KERNEL_map + PMD_SIZE)].pgd); +- l2 = m2v(l3[pud_index(__START_KERNEL_map + PMD_SIZE)].pud); +- copy_page(level2_fixmap_pgt, l2); +- /* Note that we don't do anything with level1_fixmap_pgt which +- * we don't need. */ + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + /* Make pagetable pieces RO */ + set_page_prot(init_level4_pgt, PAGE_KERNEL_RO); +@@ -1937,6 +1933,7 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) + set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO); + set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); + set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); ++ set_page_prot(level1_fixmap_pgt, PAGE_KERNEL_RO); + + /* Pin down new L4 */ + pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE, +diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c +index 0982233..a6a72ce 100644 +--- a/arch/x86/xen/setup.c ++++ b/arch/x86/xen/setup.c +@@ -574,13 +574,7 @@ void xen_enable_syscall(void) + } + #endif /* CONFIG_X86_64 */ + } +-void xen_enable_nmi(void) +-{ +-#ifdef CONFIG_X86_64 +- if (register_callback(CALLBACKTYPE_nmi, (char *)nmi)) +- BUG(); +-#endif +-} ++ + void __init xen_pvmmu_arch_setup(void) + { + HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments); +@@ -595,7 +589,6 @@ void __init xen_pvmmu_arch_setup(void) + + xen_enable_sysenter(); + xen_enable_syscall(); +- xen_enable_nmi(); + } + + /* This function is not called for HVM domains */ +diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c +index 7b78f88..5718b0b 100644 +--- a/arch/x86/xen/time.c ++++ b/arch/x86/xen/time.c +@@ -444,7 +444,7 @@ void xen_setup_timer(int cpu) + + irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt, + IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER| +- IRQF_FORCE_RESUME, ++ IRQF_FORCE_RESUME|IRQF_EARLY_RESUME, + name, NULL); + (void)xen_set_irq_priority(irq, XEN_IRQ_PRIORITY_MAX); + +diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig +index c87ae7c..8879361 100644 +--- a/arch/xtensa/Kconfig ++++ b/arch/xtensa/Kconfig +@@ -336,6 +336,36 @@ menu "Executable file formats" + + source "fs/Kconfig.binfmt" + ++config XTFPGA_LCD ++ bool "Enable XTFPGA LCD driver" ++ depends on XTENSA_PLATFORM_XTFPGA ++ default n ++ help ++ There's a 2x16 LCD on most of XTFPGA boards, kernel may output ++ progress messages there during bootup/shutdown. It may be useful ++ during board bringup. ++ ++ If unsure, say N. ++ ++config XTFPGA_LCD_BASE_ADDR ++ hex "XTFPGA LCD base address" ++ depends on XTFPGA_LCD ++ default "0x0d0c0000" ++ help ++ Base address of the LCD controller inside KIO region. ++ Different boards from XTFPGA family have LCD controller at different ++ addresses. Please consult prototyping user guide for your board for ++ the correct address. Wrong address here may lead to hardware lockup. ++ ++config XTFPGA_LCD_8BIT_ACCESS ++ bool "Use 8-bit access to XTFPGA LCD" ++ depends on XTFPGA_LCD ++ default n ++ help ++ LCD may be connected with 4- or 8-bit interface, 8-bit access may ++ only be used with 8-bit interface. Please consult prototyping user ++ guide for your board for the correct interface width. ++ + endmenu + + source "net/Kconfig" +diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h +index 2164462..51230ba 100644 +--- a/arch/xtensa/include/asm/pgtable.h ++++ b/arch/xtensa/include/asm/pgtable.h +@@ -67,7 +67,12 @@ + #define VMALLOC_START 0xC0000000 + #define VMALLOC_END 0xC7FEFFFF + #define TLBTEMP_BASE_1 0xC7FF0000 +-#define TLBTEMP_BASE_2 0xC7FF8000 ++#define TLBTEMP_BASE_2 (TLBTEMP_BASE_1 + DCACHE_WAY_SIZE) ++#if 2 * DCACHE_WAY_SIZE > ICACHE_WAY_SIZE ++#define TLBTEMP_SIZE (2 * DCACHE_WAY_SIZE) ++#else ++#define TLBTEMP_SIZE ICACHE_WAY_SIZE ++#endif + + /* + * For the Xtensa architecture, the PTE layout is as follows: +diff --git a/arch/xtensa/include/asm/traps.h b/arch/xtensa/include/asm/traps.h +index 677bfcf..28f33a8 100644 +--- a/arch/xtensa/include/asm/traps.h ++++ b/arch/xtensa/include/asm/traps.h +@@ -25,30 +25,39 @@ static inline void spill_registers(void) + { + #if XCHAL_NUM_AREGS > 16 + __asm__ __volatile__ ( +- " call12 1f\n" ++ " call8 1f\n" + " _j 2f\n" + " retw\n" + " .align 4\n" + "1:\n" ++#if XCHAL_NUM_AREGS == 32 ++ " _entry a1, 32\n" ++ " addi a8, a0, 3\n" ++ " _entry a1, 16\n" ++ " mov a12, a12\n" ++ " retw\n" ++#else + " _entry a1, 48\n" +- " addi a12, a0, 3\n" +-#if XCHAL_NUM_AREGS > 32 +- " .rept (" __stringify(XCHAL_NUM_AREGS) " - 32) / 12\n" ++ " call12 1f\n" ++ " retw\n" ++ " .align 4\n" ++ "1:\n" ++ " .rept (" __stringify(XCHAL_NUM_AREGS) " - 16) / 12\n" + " _entry a1, 48\n" + " mov a12, a0\n" + " .endr\n" +-#endif +- " _entry a1, 48\n" ++ " _entry a1, 16\n" + #if XCHAL_NUM_AREGS % 12 == 0 +- " mov a8, a8\n" +-#elif XCHAL_NUM_AREGS % 12 == 4 + " mov a12, a12\n" +-#elif XCHAL_NUM_AREGS % 12 == 8 ++#elif XCHAL_NUM_AREGS % 12 == 4 + " mov a4, a4\n" ++#elif XCHAL_NUM_AREGS % 12 == 8 ++ " mov a8, a8\n" + #endif + " retw\n" ++#endif + "2:\n" +- : : : "a12", "a13", "memory"); ++ : : : "a8", "a9", "memory"); + #else + __asm__ __volatile__ ( + " mov a12, a12\n" +diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h +index fd686dc..c7211e7 100644 +--- a/arch/xtensa/include/asm/uaccess.h ++++ b/arch/xtensa/include/asm/uaccess.h +@@ -52,7 +52,12 @@ + */ + .macro get_fs ad, sp + GET_CURRENT(\ad,\sp) ++#if THREAD_CURRENT_DS > 1020 ++ addi \ad, \ad, TASK_THREAD ++ l32i \ad, \ad, THREAD_CURRENT_DS - TASK_THREAD ++#else + l32i \ad, \ad, THREAD_CURRENT_DS ++#endif + .endm + + /* +diff --git a/arch/xtensa/include/uapi/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h +index b4cb110..a47909f 100644 +--- a/arch/xtensa/include/uapi/asm/ioctls.h ++++ b/arch/xtensa/include/uapi/asm/ioctls.h +@@ -28,17 +28,17 @@ + #define TCSETSW 0x5403 + #define TCSETSF 0x5404 + +-#define TCGETA _IOR('t', 23, struct termio) +-#define TCSETA _IOW('t', 24, struct termio) +-#define TCSETAW _IOW('t', 25, struct termio) +-#define TCSETAF _IOW('t', 28, struct termio) ++#define TCGETA 0x80127417 /* _IOR('t', 23, struct termio) */ ++#define TCSETA 0x40127418 /* _IOW('t', 24, struct termio) */ ++#define TCSETAW 0x40127419 /* _IOW('t', 25, struct termio) */ ++#define TCSETAF 0x4012741C /* _IOW('t', 28, struct termio) */ + + #define TCSBRK _IO('t', 29) + #define TCXONC _IO('t', 30) + #define TCFLSH _IO('t', 31) + +-#define TIOCSWINSZ _IOW('t', 103, struct winsize) +-#define TIOCGWINSZ _IOR('t', 104, struct winsize) ++#define TIOCSWINSZ 0x40087467 /* _IOW('t', 103, struct winsize) */ ++#define TIOCGWINSZ 0x80087468 /* _IOR('t', 104, struct winsize) */ + #define TIOCSTART _IO('t', 110) /* start output, like ^Q */ + #define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ + #define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ +@@ -88,7 +88,6 @@ + #define TIOCSETD _IOW('T', 35, int) + #define TIOCGETD _IOR('T', 36, int) + #define TCSBRKP _IOW('T', 37, int) /* Needed for POSIX tcsendbreak()*/ +-#define TIOCTTYGSTRUCT _IOR('T', 38, struct tty_struct) /* For debugging only*/ + #define TIOCSBRK _IO('T', 39) /* BSD compatibility */ + #define TIOCCBRK _IO('T', 40) /* BSD compatibility */ + #define TIOCGSID _IOR('T', 41, pid_t) /* Return the session ID of FD*/ +@@ -114,8 +113,10 @@ + #define TIOCSERGETLSR _IOR('T', 89, unsigned int) /* Get line status reg. */ + /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ + # define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ +-#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* Get multiport config */ +-#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */ ++#define TIOCSERGETMULTI 0x80a8545a /* Get multiport config */ ++ /* _IOR('T', 90, struct serial_multiport_struct) */ ++#define TIOCSERSETMULTI 0x40a8545b /* Set multiport config */ ++ /* _IOW('T', 91, struct serial_multiport_struct) */ + + #define TIOCMIWAIT _IO('T', 92) /* wait for a change on serial input line(s) */ + #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h +index b939552..b54fa1b 100644 +--- a/arch/xtensa/include/uapi/asm/unistd.h ++++ b/arch/xtensa/include/uapi/asm/unistd.h +@@ -384,7 +384,8 @@ __SYSCALL(174, sys_chroot, 1) + #define __NR_pivot_root 175 + __SYSCALL(175, sys_pivot_root, 2) + #define __NR_umount 176 +-__SYSCALL(176, sys_umount, 2) ++__SYSCALL(176, sys_oldumount, 1) ++#define __ARCH_WANT_SYS_OLDUMOUNT + #define __NR_swapoff 177 + __SYSCALL(177, sys_swapoff, 1) + #define __NR_sync 178 +@@ -714,7 +715,7 @@ __SYSCALL(323, sys_process_vm_writev, 6) + __SYSCALL(324, sys_name_to_handle_at, 5) + #define __NR_open_by_handle_at 325 + __SYSCALL(325, sys_open_by_handle_at, 3) +-#define __NR_sync_file_range 326 ++#define __NR_sync_file_range2 326 + __SYSCALL(326, sys_sync_file_range2, 6) + #define __NR_perf_event_open 327 + __SYSCALL(327, sys_perf_event_open, 5) +diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S +index ef7f499..cf8a354 100644 +--- a/arch/xtensa/kernel/entry.S ++++ b/arch/xtensa/kernel/entry.S +@@ -568,12 +568,13 @@ user_exception_exit: + * (if we have restored WSBITS-1 frames). + */ + ++2: + #if XCHAL_HAVE_THREADPTR + l32i a3, a1, PT_THREADPTR + wur a3, threadptr + #endif + +-2: j common_exception_exit ++ j common_exception_exit + + /* This is the kernel exception exit. + * We avoided to do a MOVSP when we entered the exception, but we +@@ -1001,9 +1002,8 @@ ENTRY(fast_syscall_xtensa) + movi a7, 4 # sizeof(unsigned int) + access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp + +- addi a6, a6, -1 # assuming SYS_XTENSA_ATOMIC_SET = 1 +- _bgeui a6, SYS_XTENSA_COUNT - 1, .Lill +- _bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP - 1, .Lnswp ++ _bgeui a6, SYS_XTENSA_COUNT, .Lill ++ _bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP, .Lnswp + + /* Fall through for ATOMIC_CMP_SWP. */ + +@@ -1015,27 +1015,26 @@ TRY s32i a5, a3, 0 # different, modify value + l32i a7, a2, PT_AREG7 # restore a7 + l32i a0, a2, PT_AREG0 # restore a0 + movi a2, 1 # and return 1 +- addi a6, a6, 1 # restore a6 (really necessary?) + rfe + + 1: l32i a7, a2, PT_AREG7 # restore a7 + l32i a0, a2, PT_AREG0 # restore a0 + movi a2, 0 # return 0 (note that we cannot set +- addi a6, a6, 1 # restore a6 (really necessary?) + rfe + + .Lnswp: /* Atomic set, add, and exg_add. */ + + TRY l32i a7, a3, 0 # orig ++ addi a6, a6, -SYS_XTENSA_ATOMIC_SET + add a0, a4, a7 # + arg + moveqz a0, a4, a6 # set ++ addi a6, a6, SYS_XTENSA_ATOMIC_SET + TRY s32i a0, a3, 0 # write new value + + mov a0, a2 + mov a2, a7 + l32i a7, a0, PT_AREG7 # restore a7 + l32i a0, a0, PT_AREG0 # restore a0 +- addi a6, a6, 1 # restore a6 (really necessary?) + rfe + + CATCH +@@ -1044,7 +1043,7 @@ CATCH + movi a2, -EFAULT + rfe + +-.Lill: l32i a7, a2, PT_AREG0 # restore a7 ++.Lill: l32i a7, a2, PT_AREG7 # restore a7 + l32i a0, a2, PT_AREG0 # restore a0 + movi a2, -EINVAL + rfe +@@ -1565,7 +1564,7 @@ ENTRY(fast_second_level_miss) + rsr a0, excvaddr + bltu a0, a3, 2f + +- addi a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT)) ++ addi a1, a0, -TLBTEMP_SIZE + bgeu a1, a3, 2f + + /* Check if we have to restore an ITLB mapping. */ +@@ -1794,7 +1793,7 @@ ENDPROC(system_call) + mov a12, a0 + .endr + #endif +- _entry a1, 48 ++ _entry a1, 16 + #if XCHAL_NUM_AREGS % 12 == 0 + mov a8, a8 + #elif XCHAL_NUM_AREGS % 12 == 4 +@@ -1818,9 +1817,8 @@ ENDPROC(system_call) + + ENTRY(_switch_to) + +- entry a1, 16 ++ entry a1, 48 + +- mov a10, a2 # preserve 'prev' (a2) + mov a11, a3 # and 'next' (a3) + + l32i a4, a2, TASK_THREAD_INFO +@@ -1828,8 +1826,14 @@ ENTRY(_switch_to) + + save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER + +- s32i a0, a10, THREAD_RA # save return address +- s32i a1, a10, THREAD_SP # save stack pointer ++#if THREAD_RA > 1020 || THREAD_SP > 1020 ++ addi a10, a2, TASK_THREAD ++ s32i a0, a10, THREAD_RA - TASK_THREAD # save return address ++ s32i a1, a10, THREAD_SP - TASK_THREAD # save stack pointer ++#else ++ s32i a0, a2, THREAD_RA # save return address ++ s32i a1, a2, THREAD_SP # save stack pointer ++#endif + + /* Disable ints while we manipulate the stack pointer. */ + +@@ -1870,7 +1874,6 @@ ENTRY(_switch_to) + load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER + + wsr a14, ps +- mov a2, a10 # return 'prev' + rsync + + retw +diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c +index 2d9cc6d..e8b76b8 100644 +--- a/arch/xtensa/kernel/pci-dma.c ++++ b/arch/xtensa/kernel/pci-dma.c +@@ -49,9 +49,8 @@ dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag) + + /* We currently don't support coherent memory outside KSEG */ + +- if (ret < XCHAL_KSEG_CACHED_VADDR +- || ret >= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE) +- BUG(); ++ BUG_ON(ret < XCHAL_KSEG_CACHED_VADDR || ++ ret > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1); + + + if (ret != 0) { +@@ -68,10 +67,11 @@ EXPORT_SYMBOL(dma_alloc_coherent); + void dma_free_coherent(struct device *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) + { +- long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR; ++ unsigned long addr = (unsigned long)vaddr + ++ XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR; + +- if (addr < 0 || addr >= XCHAL_KSEG_SIZE) +- BUG(); ++ BUG_ON(addr < XCHAL_KSEG_CACHED_VADDR || ++ addr > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1); + + free_pages(addr, get_order(size)); + } +diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S +index f9e1ec3..8453e6e 100644 +--- a/arch/xtensa/kernel/vectors.S ++++ b/arch/xtensa/kernel/vectors.S +@@ -376,38 +376,42 @@ _DoubleExceptionVector_WindowOverflow: + beqz a2, 1f # if at start of vector, don't restore + + addi a0, a0, -128 +- bbsi a0, 8, 1f # don't restore except for overflow 8 and 12 +- bbsi a0, 7, 2f ++ bbsi.l a0, 8, 1f # don't restore except for overflow 8 and 12 ++ ++ /* ++ * This fixup handler is for the extremely unlikely case where the ++ * overflow handler's reference thru a0 gets a hardware TLB refill ++ * that bumps out the (distinct, aliasing) TLB entry that mapped its ++ * prior references thru a9/a13, and where our reference now thru ++ * a9/a13 gets a 2nd-level miss exception (not hardware TLB refill). ++ */ ++ movi a2, window_overflow_restore_a0_fixup ++ s32i a2, a3, EXC_TABLE_FIXUP ++ l32i a2, a3, EXC_TABLE_DOUBLE_SAVE ++ xsr a3, excsave1 ++ ++ bbsi.l a0, 7, 2f + + /* + * Restore a0 as saved by _WindowOverflow8(). +- * +- * FIXME: we really need a fixup handler for this L32E, +- * for the extremely unlikely case where the overflow handler's +- * reference thru a0 gets a hardware TLB refill that bumps out +- * the (distinct, aliasing) TLB entry that mapped its prior +- * references thru a9, and where our reference now thru a9 +- * gets a 2nd-level miss exception (not hardware TLB refill). + */ + +- l32e a2, a9, -16 +- wsr a2, depc # replace the saved a0 +- j 1f ++ l32e a0, a9, -16 ++ wsr a0, depc # replace the saved a0 ++ j 3f + + 2: + /* + * Restore a0 as saved by _WindowOverflow12(). +- * +- * FIXME: we really need a fixup handler for this L32E, +- * for the extremely unlikely case where the overflow handler's +- * reference thru a0 gets a hardware TLB refill that bumps out +- * the (distinct, aliasing) TLB entry that mapped its prior +- * references thru a13, and where our reference now thru a13 +- * gets a 2nd-level miss exception (not hardware TLB refill). + */ + +- l32e a2, a13, -16 +- wsr a2, depc # replace the saved a0 ++ l32e a0, a13, -16 ++ wsr a0, depc # replace the saved a0 ++3: ++ xsr a3, excsave1 ++ movi a0, 0 ++ s32i a0, a3, EXC_TABLE_FIXUP ++ s32i a2, a3, EXC_TABLE_DOUBLE_SAVE + 1: + /* + * Restore WindowBase while leaving all address registers restored. +@@ -449,6 +453,7 @@ _DoubleExceptionVector_WindowOverflow: + + s32i a0, a2, PT_DEPC + ++_DoubleExceptionVector_handle_exception: + addx4 a0, a0, a3 + l32i a0, a0, EXC_TABLE_FAST_USER + xsr a3, excsave1 +@@ -464,11 +469,120 @@ _DoubleExceptionVector_WindowOverflow: + rotw -3 + j 1b + +- .end literal_prefix + + ENDPROC(_DoubleExceptionVector) + + /* ++ * Fixup handler for TLB miss in double exception handler for window owerflow. ++ * We get here with windowbase set to the window that was being spilled and ++ * a0 trashed. a0 bit 7 determines if this is a call8 (bit clear) or call12 ++ * (bit set) window. ++ * ++ * We do the following here: ++ * - go to the original window retaining a0 value; ++ * - set up exception stack to return back to appropriate a0 restore code ++ * (we'll need to rotate window back and there's no place to save this ++ * information, use different return address for that); ++ * - handle the exception; ++ * - go to the window that was being spilled; ++ * - set up window_overflow_restore_a0_fixup as a fixup routine; ++ * - reload a0; ++ * - restore the original window; ++ * - reset the default fixup routine; ++ * - return to user. By the time we get to this fixup handler all information ++ * about the conditions of the original double exception that happened in ++ * the window overflow handler is lost, so we just return to userspace to ++ * retry overflow from start. ++ * ++ * a0: value of depc, original value in depc ++ * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE ++ * a3: exctable, original value in excsave1 ++ */ ++ ++ENTRY(window_overflow_restore_a0_fixup) ++ ++ rsr a0, ps ++ extui a0, a0, PS_OWB_SHIFT, PS_OWB_WIDTH ++ rsr a2, windowbase ++ sub a0, a2, a0 ++ extui a0, a0, 0, 3 ++ l32i a2, a3, EXC_TABLE_DOUBLE_SAVE ++ xsr a3, excsave1 ++ ++ _beqi a0, 1, .Lhandle_1 ++ _beqi a0, 3, .Lhandle_3 ++ ++ .macro overflow_fixup_handle_exception_pane n ++ ++ rsr a0, depc ++ rotw -\n ++ ++ xsr a3, excsave1 ++ wsr a2, depc ++ l32i a2, a3, EXC_TABLE_KSTK ++ s32i a0, a2, PT_AREG0 ++ ++ movi a0, .Lrestore_\n ++ s32i a0, a2, PT_DEPC ++ rsr a0, exccause ++ j _DoubleExceptionVector_handle_exception ++ ++ .endm ++ ++ overflow_fixup_handle_exception_pane 2 ++.Lhandle_1: ++ overflow_fixup_handle_exception_pane 1 ++.Lhandle_3: ++ overflow_fixup_handle_exception_pane 3 ++ ++ .macro overflow_fixup_restore_a0_pane n ++ ++ rotw \n ++ /* Need to preserve a0 value here to be able to handle exception ++ * that may occur on a0 reload from stack. It may occur because ++ * TLB miss handler may not be atomic and pointer to page table ++ * may be lost before we get here. There are no free registers, ++ * so we need to use EXC_TABLE_DOUBLE_SAVE area. ++ */ ++ xsr a3, excsave1 ++ s32i a2, a3, EXC_TABLE_DOUBLE_SAVE ++ movi a2, window_overflow_restore_a0_fixup ++ s32i a2, a3, EXC_TABLE_FIXUP ++ l32i a2, a3, EXC_TABLE_DOUBLE_SAVE ++ xsr a3, excsave1 ++ bbsi.l a0, 7, 1f ++ l32e a0, a9, -16 ++ j 2f ++1: ++ l32e a0, a13, -16 ++2: ++ rotw -\n ++ ++ .endm ++ ++.Lrestore_2: ++ overflow_fixup_restore_a0_pane 2 ++ ++.Lset_default_fixup: ++ xsr a3, excsave1 ++ s32i a2, a3, EXC_TABLE_DOUBLE_SAVE ++ movi a2, 0 ++ s32i a2, a3, EXC_TABLE_FIXUP ++ l32i a2, a3, EXC_TABLE_DOUBLE_SAVE ++ xsr a3, excsave1 ++ rfe ++ ++.Lrestore_1: ++ overflow_fixup_restore_a0_pane 1 ++ j .Lset_default_fixup ++.Lrestore_3: ++ overflow_fixup_restore_a0_pane 3 ++ j .Lset_default_fixup ++ ++ENDPROC(window_overflow_restore_a0_fixup) ++ ++ .end literal_prefix ++/* + * Debug interrupt vector + * + * There is not much space here, so simply jump to another handler. +diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S +index ee32c00..d16db6d 100644 +--- a/arch/xtensa/kernel/vmlinux.lds.S ++++ b/arch/xtensa/kernel/vmlinux.lds.S +@@ -269,13 +269,13 @@ SECTIONS + .UserExceptionVector.literal) + SECTION_VECTOR (_DoubleExceptionVector_literal, + .DoubleExceptionVector.literal, +- DOUBLEEXC_VECTOR_VADDR - 16, ++ DOUBLEEXC_VECTOR_VADDR - 40, + SIZEOF(.UserExceptionVector.text), + .UserExceptionVector.text) + SECTION_VECTOR (_DoubleExceptionVector_text, + .DoubleExceptionVector.text, + DOUBLEEXC_VECTOR_VADDR, +- 32, ++ 40, + .DoubleExceptionVector.literal) + + . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3; +diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c +index b57c4f9..9e3571a 100644 +--- a/arch/xtensa/mm/fault.c ++++ b/arch/xtensa/mm/fault.c +@@ -117,6 +117,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c +index d05f8fe..17b1ef3 100644 +--- a/arch/xtensa/platforms/iss/network.c ++++ b/arch/xtensa/platforms/iss/network.c +@@ -349,8 +349,8 @@ static void iss_net_timer(unsigned long priv) + { + struct iss_net_private *lp = (struct iss_net_private *)priv; + +- spin_lock(&lp->lock); + iss_net_poll(); ++ spin_lock(&lp->lock); + mod_timer(&lp->timer, jiffies + lp->timer_val); + spin_unlock(&lp->lock); + } +@@ -361,7 +361,7 @@ static int iss_net_open(struct net_device *dev) + struct iss_net_private *lp = netdev_priv(dev); + int err; + +- spin_lock(&lp->lock); ++ spin_lock_bh(&lp->lock); + + err = lp->tp.open(lp); + if (err < 0) +@@ -376,9 +376,11 @@ static int iss_net_open(struct net_device *dev) + while ((err = iss_net_rx(dev)) > 0) + ; + +- spin_lock(&opened_lock); ++ spin_unlock_bh(&lp->lock); ++ spin_lock_bh(&opened_lock); + list_add(&lp->opened_list, &opened); +- spin_unlock(&opened_lock); ++ spin_unlock_bh(&opened_lock); ++ spin_lock_bh(&lp->lock); + + init_timer(&lp->timer); + lp->timer_val = ISS_NET_TIMER_VALUE; +@@ -387,7 +389,7 @@ static int iss_net_open(struct net_device *dev) + mod_timer(&lp->timer, jiffies + lp->timer_val); + + out: +- spin_unlock(&lp->lock); ++ spin_unlock_bh(&lp->lock); + return err; + } + +@@ -395,7 +397,7 @@ static int iss_net_close(struct net_device *dev) + { + struct iss_net_private *lp = netdev_priv(dev); + netif_stop_queue(dev); +- spin_lock(&lp->lock); ++ spin_lock_bh(&lp->lock); + + spin_lock(&opened_lock); + list_del(&opened); +@@ -405,18 +407,17 @@ static int iss_net_close(struct net_device *dev) + + lp->tp.close(lp); + +- spin_unlock(&lp->lock); ++ spin_unlock_bh(&lp->lock); + return 0; + } + + static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct iss_net_private *lp = netdev_priv(dev); +- unsigned long flags; + int len; + + netif_stop_queue(dev); +- spin_lock_irqsave(&lp->lock, flags); ++ spin_lock_bh(&lp->lock); + + len = lp->tp.write(lp, &skb); + +@@ -438,7 +439,7 @@ static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev) + pr_err("%s: %s failed(%d)\n", dev->name, __func__, len); + } + +- spin_unlock_irqrestore(&lp->lock, flags); ++ spin_unlock_bh(&lp->lock); + + dev_kfree_skb(skb); + return NETDEV_TX_OK; +@@ -466,9 +467,9 @@ static int iss_net_set_mac(struct net_device *dev, void *addr) + + if (!is_valid_ether_addr(hwaddr->sa_data)) + return -EADDRNOTAVAIL; +- spin_lock(&lp->lock); ++ spin_lock_bh(&lp->lock); + memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN); +- spin_unlock(&lp->lock); ++ spin_unlock_bh(&lp->lock); + return 0; + } + +@@ -520,11 +521,11 @@ static int iss_net_configure(int index, char *init) + *lp = (struct iss_net_private) { + .device_list = LIST_HEAD_INIT(lp->device_list), + .opened_list = LIST_HEAD_INIT(lp->opened_list), +- .lock = __SPIN_LOCK_UNLOCKED(lp.lock), + .dev = dev, + .index = index, +- }; ++ }; + ++ spin_lock_init(&lp->lock); + /* + * If this name ends up conflicting with an existing registered + * netdevice, that is OK, register_netdev{,ice}() will notice this +diff --git a/arch/xtensa/platforms/xtfpga/Makefile b/arch/xtensa/platforms/xtfpga/Makefile +index b9ae206..7839d38 100644 +--- a/arch/xtensa/platforms/xtfpga/Makefile ++++ b/arch/xtensa/platforms/xtfpga/Makefile +@@ -6,4 +6,5 @@ + # + # Note 2! The CFLAGS definitions are in the main makefile... + +-obj-y = setup.o lcd.o ++obj-y += setup.o ++obj-$(CONFIG_XTFPGA_LCD) += lcd.o +diff --git a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h +index aeb316b..e8cc86f 100644 +--- a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h ++++ b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h +@@ -40,9 +40,6 @@ + + /* UART */ + #define DUART16552_PADDR (XCHAL_KIO_PADDR + 0x0D050020) +-/* LCD instruction and data addresses. */ +-#define LCD_INSTR_ADDR ((char *)IOADDR(0x0D040000)) +-#define LCD_DATA_ADDR ((char *)IOADDR(0x0D040004)) + + /* Misc. */ + #define XTFPGA_FPGAREGS_VADDR IOADDR(0x0D020000) +diff --git a/arch/xtensa/platforms/xtfpga/include/platform/lcd.h b/arch/xtensa/platforms/xtfpga/include/platform/lcd.h +index 0e43564..4c8541e 100644 +--- a/arch/xtensa/platforms/xtfpga/include/platform/lcd.h ++++ b/arch/xtensa/platforms/xtfpga/include/platform/lcd.h +@@ -11,10 +11,25 @@ + #ifndef __XTENSA_XTAVNET_LCD_H + #define __XTENSA_XTAVNET_LCD_H + ++#ifdef CONFIG_XTFPGA_LCD + /* Display string STR at position POS on the LCD. */ + void lcd_disp_at_pos(char *str, unsigned char pos); + + /* Shift the contents of the LCD display left or right. */ + void lcd_shiftleft(void); + void lcd_shiftright(void); ++#else ++static inline void lcd_disp_at_pos(char *str, unsigned char pos) ++{ ++} ++ ++static inline void lcd_shiftleft(void) ++{ ++} ++ ++static inline void lcd_shiftright(void) ++{ ++} ++#endif ++ + #endif +diff --git a/arch/xtensa/platforms/xtfpga/lcd.c b/arch/xtensa/platforms/xtfpga/lcd.c +index 2872301..4dc0c1b 100644 +--- a/arch/xtensa/platforms/xtfpga/lcd.c ++++ b/arch/xtensa/platforms/xtfpga/lcd.c +@@ -1,50 +1,63 @@ + /* +- * Driver for the LCD display on the Tensilica LX60 Board. ++ * Driver for the LCD display on the Tensilica XTFPGA board family. ++ * http://www.mytechcorp.com/cfdata/productFile/File1/MOC-16216B-B-A0A04.pdf + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2001, 2006 Tensilica Inc. ++ * Copyright (C) 2015 Cadence Design Systems Inc. + */ + +-/* +- * +- * FIXME: this code is from the examples from the LX60 user guide. +- * +- * The lcd_pause function does busy waiting, which is probably not +- * great. Maybe the code could be changed to use kernel timers, or +- * change the hardware to not need to wait. +- */ +- ++#include + #include + #include + + #include + #include +-#include + +-#define LCD_PAUSE_ITERATIONS 4000 ++/* LCD instruction and data addresses. */ ++#define LCD_INSTR_ADDR ((char *)IOADDR(CONFIG_XTFPGA_LCD_BASE_ADDR)) ++#define LCD_DATA_ADDR (LCD_INSTR_ADDR + 4) ++ + #define LCD_CLEAR 0x1 + #define LCD_DISPLAY_ON 0xc + + /* 8bit and 2 lines display */ + #define LCD_DISPLAY_MODE8BIT 0x38 ++#define LCD_DISPLAY_MODE4BIT 0x28 + #define LCD_DISPLAY_POS 0x80 + #define LCD_SHIFT_LEFT 0x18 + #define LCD_SHIFT_RIGHT 0x1c + ++static void lcd_put_byte(u8 *addr, u8 data) ++{ ++#ifdef CONFIG_XTFPGA_LCD_8BIT_ACCESS ++ ACCESS_ONCE(*addr) = data; ++#else ++ ACCESS_ONCE(*addr) = data & 0xf0; ++ ACCESS_ONCE(*addr) = (data << 4) & 0xf0; ++#endif ++} ++ + static int __init lcd_init(void) + { +- *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; ++ ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT; + mdelay(5); +- *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; ++ ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT; + udelay(200); +- *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; ++ ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT; ++ udelay(50); ++#ifndef CONFIG_XTFPGA_LCD_8BIT_ACCESS ++ ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE4BIT; ++ udelay(50); ++ lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_MODE4BIT); + udelay(50); +- *LCD_INSTR_ADDR = LCD_DISPLAY_ON; ++#endif ++ lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_ON); + udelay(50); +- *LCD_INSTR_ADDR = LCD_CLEAR; ++ lcd_put_byte(LCD_INSTR_ADDR, LCD_CLEAR); + mdelay(10); + lcd_disp_at_pos("XTENSA LINUX", 0); + return 0; +@@ -52,10 +65,10 @@ static int __init lcd_init(void) + + void lcd_disp_at_pos(char *str, unsigned char pos) + { +- *LCD_INSTR_ADDR = LCD_DISPLAY_POS | pos; ++ lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_POS | pos); + udelay(100); + while (*str != 0) { +- *LCD_DATA_ADDR = *str; ++ lcd_put_byte(LCD_DATA_ADDR, *str); + udelay(200); + str++; + } +@@ -63,13 +76,13 @@ void lcd_disp_at_pos(char *str, unsigned char pos) + + void lcd_shiftleft(void) + { +- *LCD_INSTR_ADDR = LCD_SHIFT_LEFT; ++ lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_LEFT); + udelay(50); + } + + void lcd_shiftright(void) + { +- *LCD_INSTR_ADDR = LCD_SHIFT_RIGHT; ++ lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_RIGHT); + udelay(50); + } + +diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c +index dd0dd2d..a717585 100644 +--- a/block/blk-cgroup.c ++++ b/block/blk-cgroup.c +@@ -703,8 +703,12 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, + return -EINVAL; + + disk = get_gendisk(MKDEV(major, minor), &part); +- if (!disk || part) ++ if (!disk) + return -EINVAL; ++ if (part) { ++ put_disk(disk); ++ return -EINVAL; ++ } + + rcu_read_lock(); + spin_lock_irq(disk->queue->queue_lock); +@@ -859,6 +863,13 @@ void blkcg_drain_queue(struct request_queue *q) + { + lockdep_assert_held(q->queue_lock); + ++ /* ++ * @q could be exiting and already have destroyed all blkgs as ++ * indicated by NULL root_blkg. If so, don't confuse policies. ++ */ ++ if (!q->root_blkg) ++ return; ++ + blk_throtl_drain(q); + } + +diff --git a/block/blk-mq-cpumap.c b/block/blk-mq-cpumap.c +index f872127..78d3835 100644 +--- a/block/blk-mq-cpumap.c ++++ b/block/blk-mq-cpumap.c +@@ -95,7 +95,7 @@ unsigned int *blk_mq_make_queue_map(struct blk_mq_reg *reg) + unsigned int *map; + + /* If cpus are offline, map them to first hctx */ +- map = kzalloc_node(sizeof(*map) * num_possible_cpus(), GFP_KERNEL, ++ map = kzalloc_node(sizeof(*map) * nr_cpu_ids, GFP_KERNEL, + reg->numa_node); + if (!map) + return NULL; +diff --git a/block/blk-settings.c b/block/blk-settings.c +index 5d21239..95138e9 100644 +--- a/block/blk-settings.c ++++ b/block/blk-settings.c +@@ -553,7 +553,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, + bottom = max(b->physical_block_size, b->io_min) + alignment; + + /* Verify that top and bottom intervals line up */ +- if (max(top, bottom) & (min(top, bottom) - 1)) { ++ if (max(top, bottom) % min(top, bottom)) { + t->misaligned = 1; + ret = -1; + } +@@ -598,7 +598,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, + + /* Find lowest common alignment_offset */ + t->alignment_offset = lcm(t->alignment_offset, alignment) +- & (max(t->physical_block_size, t->io_min) - 1); ++ % max(t->physical_block_size, t->io_min); + + /* Verify that new alignment_offset is on a logical block boundary */ + if (t->alignment_offset & (t->logical_block_size - 1)) { +diff --git a/block/blk-tag.c b/block/blk-tag.c +index 3f33d86..a185b86 100644 +--- a/block/blk-tag.c ++++ b/block/blk-tag.c +@@ -27,18 +27,15 @@ struct request *blk_queue_find_tag(struct request_queue *q, int tag) + EXPORT_SYMBOL(blk_queue_find_tag); + + /** +- * __blk_free_tags - release a given set of tag maintenance info ++ * blk_free_tags - release a given set of tag maintenance info + * @bqt: the tag map to free + * +- * Tries to free the specified @bqt. Returns true if it was +- * actually freed and false if there are still references using it ++ * Drop the reference count on @bqt and frees it when the last reference ++ * is dropped. + */ +-static int __blk_free_tags(struct blk_queue_tag *bqt) ++void blk_free_tags(struct blk_queue_tag *bqt) + { +- int retval; +- +- retval = atomic_dec_and_test(&bqt->refcnt); +- if (retval) { ++ if (atomic_dec_and_test(&bqt->refcnt)) { + BUG_ON(find_first_bit(bqt->tag_map, bqt->max_depth) < + bqt->max_depth); + +@@ -50,9 +47,8 @@ static int __blk_free_tags(struct blk_queue_tag *bqt) + + kfree(bqt); + } +- +- return retval; + } ++EXPORT_SYMBOL(blk_free_tags); + + /** + * __blk_queue_free_tags - release tag maintenance info +@@ -69,28 +65,13 @@ void __blk_queue_free_tags(struct request_queue *q) + if (!bqt) + return; + +- __blk_free_tags(bqt); ++ blk_free_tags(bqt); + + q->queue_tags = NULL; + queue_flag_clear_unlocked(QUEUE_FLAG_QUEUED, q); + } + + /** +- * blk_free_tags - release a given set of tag maintenance info +- * @bqt: the tag map to free +- * +- * For externally managed @bqt frees the map. Callers of this +- * function must guarantee to have released all the queues that +- * might have been using this tag map. +- */ +-void blk_free_tags(struct blk_queue_tag *bqt) +-{ +- if (unlikely(!__blk_free_tags(bqt))) +- BUG(); +-} +-EXPORT_SYMBOL(blk_free_tags); +- +-/** + * blk_queue_free_tags - release tag maintenance info + * @q: the request queue for the device + * +diff --git a/block/blk-throttle.c b/block/blk-throttle.c +index 1474c3a..1599878 100644 +--- a/block/blk-throttle.c ++++ b/block/blk-throttle.c +@@ -1292,6 +1292,9 @@ static u64 tg_prfill_cpu_rwstat(struct seq_file *sf, + struct blkg_rwstat rwstat = { }, tmp; + int i, cpu; + ++ if (tg->stats_cpu == NULL) ++ return 0; ++ + for_each_possible_cpu(cpu) { + struct tg_stats_cpu *sc = per_cpu_ptr(tg->stats_cpu, cpu); + +diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c +index 744833b..d9bba99 100644 +--- a/block/cfq-iosched.c ++++ b/block/cfq-iosched.c +@@ -1275,12 +1275,16 @@ __cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg) + static void + cfq_update_group_weight(struct cfq_group *cfqg) + { +- BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node)); +- + if (cfqg->new_weight) { + cfqg->weight = cfqg->new_weight; + cfqg->new_weight = 0; + } ++} ++ ++static void ++cfq_update_group_leaf_weight(struct cfq_group *cfqg) ++{ ++ BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node)); + + if (cfqg->new_leaf_weight) { + cfqg->leaf_weight = cfqg->new_leaf_weight; +@@ -1299,7 +1303,7 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg) + /* add to the service tree */ + BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node)); + +- cfq_update_group_weight(cfqg); ++ cfq_update_group_leaf_weight(cfqg); + __cfq_group_service_tree_add(st, cfqg); + + /* +@@ -1323,6 +1327,7 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg) + */ + while ((parent = cfqg_parent(pos))) { + if (propagate) { ++ cfq_update_group_weight(pos); + propagate = !parent->nr_active++; + parent->children_weight += pos->weight; + } +@@ -3580,6 +3585,11 @@ retry: + + blkcg = bio_blkcg(bio); + cfqg = cfq_lookup_create_cfqg(cfqd, blkcg); ++ if (!cfqg) { ++ cfqq = &cfqd->oom_cfqq; ++ goto out; ++ } ++ + cfqq = cic_to_cfqq(cic, is_sync); + + /* +@@ -3616,7 +3626,7 @@ retry: + } else + cfqq = &cfqd->oom_cfqq; + } +- ++out: + if (new_cfqq) + kmem_cache_free(cfq_pool, new_cfqq); + +@@ -3646,12 +3656,17 @@ static struct cfq_queue * + cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct cfq_io_cq *cic, + struct bio *bio, gfp_t gfp_mask) + { +- const int ioprio_class = IOPRIO_PRIO_CLASS(cic->ioprio); +- const int ioprio = IOPRIO_PRIO_DATA(cic->ioprio); ++ int ioprio_class = IOPRIO_PRIO_CLASS(cic->ioprio); ++ int ioprio = IOPRIO_PRIO_DATA(cic->ioprio); + struct cfq_queue **async_cfqq = NULL; + struct cfq_queue *cfqq = NULL; + + if (!is_sync) { ++ if (!ioprio_valid(cic->ioprio)) { ++ struct task_struct *tsk = current; ++ ioprio = task_nice_ioprio(tsk); ++ ioprio_class = task_nice_ioclass(tsk); ++ } + async_cfqq = cfq_async_queue_prio(cfqd, ioprio_class, ioprio); + cfqq = *async_cfqq; + } +diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c +index fbd5a67..a0926a6 100644 +--- a/block/compat_ioctl.c ++++ b/block/compat_ioctl.c +@@ -690,6 +690,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + case BLKROSET: + case BLKDISCARD: + case BLKSECDISCARD: ++ case BLKZEROOUT: + /* + * the ones below are implemented in blkdev_locked_ioctl, + * but we call blkdev_ioctl, which gets the lock for us +diff --git a/block/genhd.c b/block/genhd.c +index 791f419..9316f5f 100644 +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -28,10 +28,10 @@ struct kobject *block_depr; + /* for extended dynamic devt allocation, currently only one major is used */ + #define NR_EXT_DEVT (1 << MINORBITS) + +-/* For extended devt allocation. ext_devt_mutex prevents look up ++/* For extended devt allocation. ext_devt_lock prevents look up + * results from going away underneath its user. + */ +-static DEFINE_MUTEX(ext_devt_mutex); ++static DEFINE_SPINLOCK(ext_devt_lock); + static DEFINE_IDR(ext_devt_idr); + + static struct device_type disk_type; +@@ -420,9 +420,13 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt) + } + + /* allocate ext devt */ +- mutex_lock(&ext_devt_mutex); +- idx = idr_alloc(&ext_devt_idr, part, 0, NR_EXT_DEVT, GFP_KERNEL); +- mutex_unlock(&ext_devt_mutex); ++ idr_preload(GFP_KERNEL); ++ ++ spin_lock_bh(&ext_devt_lock); ++ idx = idr_alloc(&ext_devt_idr, part, 0, NR_EXT_DEVT, GFP_NOWAIT); ++ spin_unlock_bh(&ext_devt_lock); ++ ++ idr_preload_end(); + if (idx < 0) + return idx == -ENOSPC ? -EBUSY : idx; + +@@ -441,15 +445,13 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt) + */ + void blk_free_devt(dev_t devt) + { +- might_sleep(); +- + if (devt == MKDEV(0, 0)) + return; + + if (MAJOR(devt) == BLOCK_EXT_MAJOR) { +- mutex_lock(&ext_devt_mutex); ++ spin_lock_bh(&ext_devt_lock); + idr_remove(&ext_devt_idr, blk_mangle_minor(MINOR(devt))); +- mutex_unlock(&ext_devt_mutex); ++ spin_unlock_bh(&ext_devt_lock); + } + } + +@@ -665,7 +667,6 @@ void del_gendisk(struct gendisk *disk) + sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk))); + pm_runtime_set_memalloc_noio(disk_to_dev(disk), false); + device_del(disk_to_dev(disk)); +- blk_free_devt(disk_to_dev(disk)->devt); + } + EXPORT_SYMBOL(del_gendisk); + +@@ -690,13 +691,13 @@ struct gendisk *get_gendisk(dev_t devt, int *partno) + } else { + struct hd_struct *part; + +- mutex_lock(&ext_devt_mutex); ++ spin_lock_bh(&ext_devt_lock); + part = idr_find(&ext_devt_idr, blk_mangle_minor(MINOR(devt))); + if (part && get_disk(part_to_disk(part))) { + *partno = part->partno; + disk = part_to_disk(part); + } +- mutex_unlock(&ext_devt_mutex); ++ spin_unlock_bh(&ext_devt_lock); + } + + return disk; +@@ -1069,9 +1070,16 @@ int disk_expand_part_tbl(struct gendisk *disk, int partno) + struct disk_part_tbl *old_ptbl = disk->part_tbl; + struct disk_part_tbl *new_ptbl; + int len = old_ptbl ? old_ptbl->len : 0; +- int target = partno + 1; ++ int i, target; + size_t size; +- int i; ++ ++ /* ++ * check for int overflow, since we can get here from blkpg_ioctl() ++ * with a user passed 'partno'. ++ */ ++ target = partno + 1; ++ if (target < 0) ++ return -EINVAL; + + /* disk_max_parts() is zero during initialization, ignore if so */ + if (disk_max_parts(disk) && target > disk_max_parts(disk)) +@@ -1098,6 +1106,7 @@ static void disk_release(struct device *dev) + { + struct gendisk *disk = dev_to_disk(dev); + ++ blk_free_devt(dev->devt); + disk_release_events(disk); + kfree(disk->random); + disk_replace_part_tbl(disk, NULL); +diff --git a/block/partition-generic.c b/block/partition-generic.c +index 789cdea..0d9e5f9 100644 +--- a/block/partition-generic.c ++++ b/block/partition-generic.c +@@ -211,6 +211,7 @@ static const struct attribute_group *part_attr_groups[] = { + static void part_release(struct device *dev) + { + struct hd_struct *p = dev_to_part(dev); ++ blk_free_devt(dev->devt); + free_part_stats(p); + free_part_info(p); + kfree(p); +@@ -253,7 +254,6 @@ void delete_partition(struct gendisk *disk, int partno) + rcu_assign_pointer(ptbl->last_lookup, NULL); + kobject_put(part->holder_dir); + device_del(part_to_dev(part)); +- blk_free_devt(part_devt(part)); + + hd_struct_put(part); + } +diff --git a/block/partitions/aix.c b/block/partitions/aix.c +index 43be471..0931f51 100644 +--- a/block/partitions/aix.c ++++ b/block/partitions/aix.c +@@ -253,7 +253,7 @@ int aix_partition(struct parsed_partitions *state) + continue; + } + lv_ix = be16_to_cpu(p->lv_ix) - 1; +- if (lv_ix > state->limit) { ++ if (lv_ix >= state->limit) { + cur_lv_ix = -1; + continue; + } +diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c +index 2648797..4044cf7 100644 +--- a/block/scsi_ioctl.c ++++ b/block/scsi_ioctl.c +@@ -489,7 +489,7 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode, + + if (bytes && blk_rq_map_kern(q, rq, buffer, bytes, __GFP_WAIT)) { + err = DRIVER_ERROR << 24; +- goto out; ++ goto error; + } + + memset(sense, 0, sizeof(sense)); +@@ -499,7 +499,6 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode, + + blk_execute_rq(q, disk, rq, 0); + +-out: + err = rq->errors & 0xff; /* only 8 bit SCSI status */ + if (err) { + if (rq->sense_len && rq->sense) { +diff --git a/crypto/842.c b/crypto/842.c +index 65c7a89c..b48f4f1 100644 +--- a/crypto/842.c ++++ b/crypto/842.c +@@ -180,3 +180,4 @@ module_exit(nx842_mod_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("842 Compression Algorithm"); ++MODULE_ALIAS_CRYPTO("842"); +diff --git a/crypto/aes_generic.c b/crypto/aes_generic.c +index fd0d6b4..3dd1011 100644 +--- a/crypto/aes_generic.c ++++ b/crypto/aes_generic.c +@@ -1474,4 +1474,5 @@ module_exit(aes_fini); + + MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); + MODULE_LICENSE("Dual BSD/GPL"); +-MODULE_ALIAS("aes"); ++MODULE_ALIAS_CRYPTO("aes"); ++MODULE_ALIAS_CRYPTO("aes-generic"); +diff --git a/crypto/af_alg.c b/crypto/af_alg.c +index 966f893..1de4bee 100644 +--- a/crypto/af_alg.c ++++ b/crypto/af_alg.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + struct alg_type_list { + const struct af_alg_type *type; +@@ -243,6 +244,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock) + + sock_init_data(newsock, sk2); + sock_graft(sk2, newsock); ++ security_sk_clone(sk, sk2); + + err = type->accept(ask->private, sk2); + if (err) { +@@ -447,6 +449,9 @@ void af_alg_complete(struct crypto_async_request *req, int err) + { + struct af_alg_completion *completion = req->data; + ++ if (err == -EINPROGRESS) ++ return; ++ + completion->err = err; + complete(&completion->completion); + } +diff --git a/crypto/algapi.c b/crypto/algapi.c +index 7a1ae87..00d8d93 100644 +--- a/crypto/algapi.c ++++ b/crypto/algapi.c +@@ -495,8 +495,8 @@ static struct crypto_template *__crypto_lookup_template(const char *name) + + struct crypto_template *crypto_lookup_template(const char *name) + { +- return try_then_request_module(__crypto_lookup_template(name), "%s", +- name); ++ return try_then_request_module(__crypto_lookup_template(name), ++ "crypto-%s", name); + } + EXPORT_SYMBOL_GPL(crypto_lookup_template); + +diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c +index a19c027..83187f4 100644 +--- a/crypto/algif_skcipher.c ++++ b/crypto/algif_skcipher.c +@@ -49,7 +49,7 @@ struct skcipher_ctx { + struct ablkcipher_request req; + }; + +-#define MAX_SGL_ENTS ((PAGE_SIZE - sizeof(struct skcipher_sg_list)) / \ ++#define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \ + sizeof(struct scatterlist) - 1) + + static inline int skcipher_sndbuf(struct sock *sk) +diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c +index 666f196..6f5bebc 100644 +--- a/crypto/ansi_cprng.c ++++ b/crypto/ansi_cprng.c +@@ -476,4 +476,5 @@ module_param(dbg, int, 0); + MODULE_PARM_DESC(dbg, "Boolean to enable debugging (0/1 == off/on)"); + module_init(prng_mod_init); + module_exit(prng_mod_fini); +-MODULE_ALIAS("stdrng"); ++MODULE_ALIAS_CRYPTO("stdrng"); ++MODULE_ALIAS_CRYPTO("ansi_cprng"); +diff --git a/crypto/anubis.c b/crypto/anubis.c +index 008c8a4..4bb187c 100644 +--- a/crypto/anubis.c ++++ b/crypto/anubis.c +@@ -704,3 +704,4 @@ module_exit(anubis_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Anubis Cryptographic Algorithm"); ++MODULE_ALIAS_CRYPTO("anubis"); +diff --git a/crypto/api.c b/crypto/api.c +index a2b39c5..2a81e98 100644 +--- a/crypto/api.c ++++ b/crypto/api.c +@@ -216,11 +216,11 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask) + + alg = crypto_alg_lookup(name, type, mask); + if (!alg) { +- request_module("%s", name); ++ request_module("crypto-%s", name); + + if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask & + CRYPTO_ALG_NEED_FALLBACK)) +- request_module("%s-all", name); ++ request_module("crypto-%s-all", name); + + alg = crypto_alg_lookup(name, type, mask); + } +diff --git a/crypto/arc4.c b/crypto/arc4.c +index 5a772c3..f1a8192 100644 +--- a/crypto/arc4.c ++++ b/crypto/arc4.c +@@ -166,3 +166,4 @@ module_exit(arc4_exit); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("ARC4 Cipher Algorithm"); + MODULE_AUTHOR("Jon Oberheide "); ++MODULE_ALIAS_CRYPTO("arc4"); +diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c +index 3c562f5..e1bce26 100644 +--- a/crypto/async_tx/async_xor.c ++++ b/crypto/async_tx/async_xor.c +@@ -78,8 +78,6 @@ do_async_xor(struct dma_chan *chan, struct dmaengine_unmap_data *unmap, + tx = dma->device_prep_dma_xor(chan, dma_dest, src_list, + xor_src_cnt, unmap->len, + dma_flags); +- src_list[0] = tmp; +- + + if (unlikely(!tx)) + async_tx_quiesce(&submit->depend_tx); +@@ -92,6 +90,7 @@ do_async_xor(struct dma_chan *chan, struct dmaengine_unmap_data *unmap, + xor_src_cnt, unmap->len, + dma_flags); + } ++ src_list[0] = tmp; + + dma_set_unmap(tx, unmap); + async_tx_submit(chan, tx, submit); +diff --git a/crypto/authenc.c b/crypto/authenc.c +index e122355..78fb16c 100644 +--- a/crypto/authenc.c ++++ b/crypto/authenc.c +@@ -721,3 +721,4 @@ module_exit(crypto_authenc_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Simple AEAD wrapper for IPsec"); ++MODULE_ALIAS_CRYPTO("authenc"); +diff --git a/crypto/authencesn.c b/crypto/authencesn.c +index 4be0dd4..024bff2 100644 +--- a/crypto/authencesn.c ++++ b/crypto/authencesn.c +@@ -814,3 +814,4 @@ module_exit(crypto_authenc_esn_module_exit); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Steffen Klassert "); + MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers"); ++MODULE_ALIAS_CRYPTO("authencesn"); +diff --git a/crypto/blowfish_generic.c b/crypto/blowfish_generic.c +index 8baf544..87b392a 100644 +--- a/crypto/blowfish_generic.c ++++ b/crypto/blowfish_generic.c +@@ -138,4 +138,5 @@ module_exit(blowfish_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Blowfish Cipher Algorithm"); +-MODULE_ALIAS("blowfish"); ++MODULE_ALIAS_CRYPTO("blowfish"); ++MODULE_ALIAS_CRYPTO("blowfish-generic"); +diff --git a/crypto/camellia_generic.c b/crypto/camellia_generic.c +index 26bcd7a..a02286b 100644 +--- a/crypto/camellia_generic.c ++++ b/crypto/camellia_generic.c +@@ -1098,4 +1098,5 @@ module_exit(camellia_fini); + + MODULE_DESCRIPTION("Camellia Cipher Algorithm"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("camellia"); ++MODULE_ALIAS_CRYPTO("camellia"); ++MODULE_ALIAS_CRYPTO("camellia-generic"); +diff --git a/crypto/cast5_generic.c b/crypto/cast5_generic.c +index 5558f63..df5c726 100644 +--- a/crypto/cast5_generic.c ++++ b/crypto/cast5_generic.c +@@ -549,4 +549,5 @@ module_exit(cast5_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Cast5 Cipher Algorithm"); +-MODULE_ALIAS("cast5"); ++MODULE_ALIAS_CRYPTO("cast5"); ++MODULE_ALIAS_CRYPTO("cast5-generic"); +diff --git a/crypto/cast6_generic.c b/crypto/cast6_generic.c +index de73252..058c8d7 100644 +--- a/crypto/cast6_generic.c ++++ b/crypto/cast6_generic.c +@@ -291,4 +291,5 @@ module_exit(cast6_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Cast6 Cipher Algorithm"); +-MODULE_ALIAS("cast6"); ++MODULE_ALIAS_CRYPTO("cast6"); ++MODULE_ALIAS_CRYPTO("cast6-generic"); +diff --git a/crypto/cbc.c b/crypto/cbc.c +index 61ac42e..780ee27 100644 +--- a/crypto/cbc.c ++++ b/crypto/cbc.c +@@ -289,3 +289,4 @@ module_exit(crypto_cbc_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("CBC block cipher algorithm"); ++MODULE_ALIAS_CRYPTO("cbc"); +diff --git a/crypto/ccm.c b/crypto/ccm.c +index 1df8421..003bbbd 100644 +--- a/crypto/ccm.c ++++ b/crypto/ccm.c +@@ -879,5 +879,6 @@ module_exit(crypto_ccm_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Counter with CBC MAC"); +-MODULE_ALIAS("ccm_base"); +-MODULE_ALIAS("rfc4309"); ++MODULE_ALIAS_CRYPTO("ccm_base"); ++MODULE_ALIAS_CRYPTO("rfc4309"); ++MODULE_ALIAS_CRYPTO("ccm"); +diff --git a/crypto/chainiv.c b/crypto/chainiv.c +index 834d8dd..22b7e55 100644 +--- a/crypto/chainiv.c ++++ b/crypto/chainiv.c +@@ -359,3 +359,4 @@ module_exit(chainiv_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Chain IV Generator"); ++MODULE_ALIAS_CRYPTO("chainiv"); +diff --git a/crypto/cmac.c b/crypto/cmac.c +index 50880cf..7a8bfbd 100644 +--- a/crypto/cmac.c ++++ b/crypto/cmac.c +@@ -313,3 +313,4 @@ module_exit(crypto_cmac_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("CMAC keyed hash algorithm"); ++MODULE_ALIAS_CRYPTO("cmac"); +diff --git a/crypto/crc32.c b/crypto/crc32.c +index 9d1c415..187ded2 100644 +--- a/crypto/crc32.c ++++ b/crypto/crc32.c +@@ -156,3 +156,4 @@ module_exit(crc32_mod_fini); + MODULE_AUTHOR("Alexander Boyko "); + MODULE_DESCRIPTION("CRC32 calculations wrapper for lib/crc32"); + MODULE_LICENSE("GPL"); ++MODULE_ALIAS_CRYPTO("crc32"); +diff --git a/crypto/crc32c.c b/crypto/crc32c.c +index 06f7018..238f0e6 100644 +--- a/crypto/crc32c.c ++++ b/crypto/crc32c.c +@@ -170,3 +170,4 @@ module_exit(crc32c_mod_fini); + MODULE_AUTHOR("Clay Haapala "); + MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c"); + MODULE_LICENSE("GPL"); ++MODULE_ALIAS_CRYPTO("crc32c"); +diff --git a/crypto/crct10dif_generic.c b/crypto/crct10dif_generic.c +index 877e711..c1229614 100644 +--- a/crypto/crct10dif_generic.c ++++ b/crypto/crct10dif_generic.c +@@ -124,4 +124,5 @@ module_exit(crct10dif_mod_fini); + MODULE_AUTHOR("Tim Chen "); + MODULE_DESCRIPTION("T10 DIF CRC calculation."); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("crct10dif"); ++MODULE_ALIAS_CRYPTO("crct10dif"); ++MODULE_ALIAS_CRYPTO("crct10dif-generic"); +diff --git a/crypto/cryptd.c b/crypto/cryptd.c +index 7bdd61b..75c415d 100644 +--- a/crypto/cryptd.c ++++ b/crypto/cryptd.c +@@ -955,3 +955,4 @@ module_exit(cryptd_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Software async crypto daemon"); ++MODULE_ALIAS_CRYPTO("cryptd"); +diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c +index fee7265..7b39fa3 100644 +--- a/crypto/crypto_null.c ++++ b/crypto/crypto_null.c +@@ -149,9 +149,9 @@ static struct crypto_alg null_algs[3] = { { + .coa_decompress = null_compress } } + } }; + +-MODULE_ALIAS("compress_null"); +-MODULE_ALIAS("digest_null"); +-MODULE_ALIAS("cipher_null"); ++MODULE_ALIAS_CRYPTO("compress_null"); ++MODULE_ALIAS_CRYPTO("digest_null"); ++MODULE_ALIAS_CRYPTO("cipher_null"); + + static int __init crypto_null_mod_init(void) + { +diff --git a/crypto/ctr.c b/crypto/ctr.c +index f2b94f2..2386f73 100644 +--- a/crypto/ctr.c ++++ b/crypto/ctr.c +@@ -466,4 +466,5 @@ module_exit(crypto_ctr_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("CTR Counter block mode"); +-MODULE_ALIAS("rfc3686"); ++MODULE_ALIAS_CRYPTO("rfc3686"); ++MODULE_ALIAS_CRYPTO("ctr"); +diff --git a/crypto/cts.c b/crypto/cts.c +index 042223f..60b9da3 100644 +--- a/crypto/cts.c ++++ b/crypto/cts.c +@@ -350,3 +350,4 @@ module_exit(crypto_cts_module_exit); + + MODULE_LICENSE("Dual BSD/GPL"); + MODULE_DESCRIPTION("CTS-CBC CipherText Stealing for CBC"); ++MODULE_ALIAS_CRYPTO("cts"); +diff --git a/crypto/deflate.c b/crypto/deflate.c +index b57d70e..95d8d37 100644 +--- a/crypto/deflate.c ++++ b/crypto/deflate.c +@@ -222,4 +222,4 @@ module_exit(deflate_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Deflate Compression Algorithm for IPCOMP"); + MODULE_AUTHOR("James Morris "); +- ++MODULE_ALIAS_CRYPTO("deflate"); +diff --git a/crypto/des_generic.c b/crypto/des_generic.c +index f6cf63f..3ec6071 100644 +--- a/crypto/des_generic.c ++++ b/crypto/des_generic.c +@@ -971,8 +971,6 @@ static struct crypto_alg des_algs[2] = { { + .cia_decrypt = des3_ede_decrypt } } + } }; + +-MODULE_ALIAS("des3_ede"); +- + static int __init des_generic_mod_init(void) + { + return crypto_register_algs(des_algs, ARRAY_SIZE(des_algs)); +@@ -989,4 +987,7 @@ module_exit(des_generic_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); + MODULE_AUTHOR("Dag Arne Osvik "); +-MODULE_ALIAS("des"); ++MODULE_ALIAS_CRYPTO("des"); ++MODULE_ALIAS_CRYPTO("des-generic"); ++MODULE_ALIAS_CRYPTO("des3_ede"); ++MODULE_ALIAS_CRYPTO("des3_ede-generic"); +diff --git a/crypto/ecb.c b/crypto/ecb.c +index 935cfef..12011af 100644 +--- a/crypto/ecb.c ++++ b/crypto/ecb.c +@@ -185,3 +185,4 @@ module_exit(crypto_ecb_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("ECB block cipher algorithm"); ++MODULE_ALIAS_CRYPTO("ecb"); +diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c +index 42ce9f5..388f582 100644 +--- a/crypto/eseqiv.c ++++ b/crypto/eseqiv.c +@@ -267,3 +267,4 @@ module_exit(eseqiv_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Encrypted Sequence Number IV Generator"); ++MODULE_ALIAS_CRYPTO("eseqiv"); +diff --git a/crypto/fcrypt.c b/crypto/fcrypt.c +index 021d7fe..77286ea 100644 +--- a/crypto/fcrypt.c ++++ b/crypto/fcrypt.c +@@ -420,3 +420,4 @@ module_exit(fcrypt_mod_fini); + MODULE_LICENSE("Dual BSD/GPL"); + MODULE_DESCRIPTION("FCrypt Cipher Algorithm"); + MODULE_AUTHOR("David Howells "); ++MODULE_ALIAS_CRYPTO("fcrypt"); +diff --git a/crypto/gcm.c b/crypto/gcm.c +index b4f0179..9cea4d0 100644 +--- a/crypto/gcm.c ++++ b/crypto/gcm.c +@@ -1441,6 +1441,7 @@ module_exit(crypto_gcm_module_exit); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Galois/Counter Mode"); + MODULE_AUTHOR("Mikko Herranen "); +-MODULE_ALIAS("gcm_base"); +-MODULE_ALIAS("rfc4106"); +-MODULE_ALIAS("rfc4543"); ++MODULE_ALIAS_CRYPTO("gcm_base"); ++MODULE_ALIAS_CRYPTO("rfc4106"); ++MODULE_ALIAS_CRYPTO("rfc4543"); ++MODULE_ALIAS_CRYPTO("gcm"); +diff --git a/crypto/ghash-generic.c b/crypto/ghash-generic.c +index 9d3f0c6..bac7099 100644 +--- a/crypto/ghash-generic.c ++++ b/crypto/ghash-generic.c +@@ -172,4 +172,5 @@ module_exit(ghash_mod_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("GHASH Message Digest Algorithm"); +-MODULE_ALIAS("ghash"); ++MODULE_ALIAS_CRYPTO("ghash"); ++MODULE_ALIAS_CRYPTO("ghash-generic"); +diff --git a/crypto/hmac.c b/crypto/hmac.c +index 8d9544c..ade790b 100644 +--- a/crypto/hmac.c ++++ b/crypto/hmac.c +@@ -271,3 +271,4 @@ module_exit(hmac_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("HMAC hash algorithm"); ++MODULE_ALIAS_CRYPTO("hmac"); +diff --git a/crypto/khazad.c b/crypto/khazad.c +index 60e7cd6..873eb5d 100644 +--- a/crypto/khazad.c ++++ b/crypto/khazad.c +@@ -880,3 +880,4 @@ module_exit(khazad_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Khazad Cryptographic Algorithm"); ++MODULE_ALIAS_CRYPTO("khazad"); +diff --git a/crypto/krng.c b/crypto/krng.c +index a2d2b72..0224841 100644 +--- a/crypto/krng.c ++++ b/crypto/krng.c +@@ -62,4 +62,5 @@ module_exit(krng_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Kernel Random Number Generator"); +-MODULE_ALIAS("stdrng"); ++MODULE_ALIAS_CRYPTO("stdrng"); ++MODULE_ALIAS_CRYPTO("krng"); +diff --git a/crypto/lrw.c b/crypto/lrw.c +index ba42acc..6f9908a 100644 +--- a/crypto/lrw.c ++++ b/crypto/lrw.c +@@ -400,3 +400,4 @@ module_exit(crypto_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("LRW block cipher mode"); ++MODULE_ALIAS_CRYPTO("lrw"); +diff --git a/crypto/lz4.c b/crypto/lz4.c +index 4586dd1..53279ab 100644 +--- a/crypto/lz4.c ++++ b/crypto/lz4.c +@@ -104,3 +104,4 @@ module_exit(lz4_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("LZ4 Compression Algorithm"); ++MODULE_ALIAS_CRYPTO("lz4"); +diff --git a/crypto/lz4hc.c b/crypto/lz4hc.c +index 151ba31..eaec5fa 100644 +--- a/crypto/lz4hc.c ++++ b/crypto/lz4hc.c +@@ -104,3 +104,4 @@ module_exit(lz4hc_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("LZ4HC Compression Algorithm"); ++MODULE_ALIAS_CRYPTO("lz4hc"); +diff --git a/crypto/lzo.c b/crypto/lzo.c +index 1c2aa69..d1ff694 100644 +--- a/crypto/lzo.c ++++ b/crypto/lzo.c +@@ -103,3 +103,4 @@ module_exit(lzo_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("LZO Compression Algorithm"); ++MODULE_ALIAS_CRYPTO("lzo"); +diff --git a/crypto/md4.c b/crypto/md4.c +index 0477a6a..3515af4 100644 +--- a/crypto/md4.c ++++ b/crypto/md4.c +@@ -255,4 +255,4 @@ module_exit(md4_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("MD4 Message Digest Algorithm"); +- ++MODULE_ALIAS_CRYPTO("md4"); +diff --git a/crypto/md5.c b/crypto/md5.c +index 7febeaa..36f5e5b 100644 +--- a/crypto/md5.c ++++ b/crypto/md5.c +@@ -168,3 +168,4 @@ module_exit(md5_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("MD5 Message Digest Algorithm"); ++MODULE_ALIAS_CRYPTO("md5"); +diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c +index 079b761..46195e0 100644 +--- a/crypto/michael_mic.c ++++ b/crypto/michael_mic.c +@@ -184,3 +184,4 @@ module_exit(michael_mic_exit); + MODULE_LICENSE("GPL v2"); + MODULE_DESCRIPTION("Michael MIC"); + MODULE_AUTHOR("Jouni Malinen "); ++MODULE_ALIAS_CRYPTO("michael_mic"); +diff --git a/crypto/pcbc.c b/crypto/pcbc.c +index d1b8bdf..f654965 100644 +--- a/crypto/pcbc.c ++++ b/crypto/pcbc.c +@@ -295,3 +295,4 @@ module_exit(crypto_pcbc_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("PCBC block cipher algorithm"); ++MODULE_ALIAS_CRYPTO("pcbc"); +diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c +index 309d345..c305d41 100644 +--- a/crypto/pcrypt.c ++++ b/crypto/pcrypt.c +@@ -565,3 +565,4 @@ module_exit(pcrypt_exit); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Steffen Klassert "); + MODULE_DESCRIPTION("Parallel crypto wrapper"); ++MODULE_ALIAS_CRYPTO("pcrypt"); +diff --git a/crypto/rmd128.c b/crypto/rmd128.c +index 8a0f68b..049486e 100644 +--- a/crypto/rmd128.c ++++ b/crypto/rmd128.c +@@ -327,3 +327,4 @@ module_exit(rmd128_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Adrian-Ken Rueegsegger "); + MODULE_DESCRIPTION("RIPEMD-128 Message Digest"); ++MODULE_ALIAS_CRYPTO("rmd128"); +diff --git a/crypto/rmd160.c b/crypto/rmd160.c +index 525d7bb..de585e5 100644 +--- a/crypto/rmd160.c ++++ b/crypto/rmd160.c +@@ -371,3 +371,4 @@ module_exit(rmd160_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Adrian-Ken Rueegsegger "); + MODULE_DESCRIPTION("RIPEMD-160 Message Digest"); ++MODULE_ALIAS_CRYPTO("rmd160"); +diff --git a/crypto/rmd256.c b/crypto/rmd256.c +index 69293d9..4ec02a7 100644 +--- a/crypto/rmd256.c ++++ b/crypto/rmd256.c +@@ -346,3 +346,4 @@ module_exit(rmd256_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Adrian-Ken Rueegsegger "); + MODULE_DESCRIPTION("RIPEMD-256 Message Digest"); ++MODULE_ALIAS_CRYPTO("rmd256"); +diff --git a/crypto/rmd320.c b/crypto/rmd320.c +index 09f97df..770f2cb 100644 +--- a/crypto/rmd320.c ++++ b/crypto/rmd320.c +@@ -395,3 +395,4 @@ module_exit(rmd320_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Adrian-Ken Rueegsegger "); + MODULE_DESCRIPTION("RIPEMD-320 Message Digest"); ++MODULE_ALIAS_CRYPTO("rmd320"); +diff --git a/crypto/salsa20_generic.c b/crypto/salsa20_generic.c +index 9a4770c..f550b5d 100644 +--- a/crypto/salsa20_generic.c ++++ b/crypto/salsa20_generic.c +@@ -248,4 +248,5 @@ module_exit(salsa20_generic_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION ("Salsa20 stream cipher algorithm"); +-MODULE_ALIAS("salsa20"); ++MODULE_ALIAS_CRYPTO("salsa20"); ++MODULE_ALIAS_CRYPTO("salsa20-generic"); +diff --git a/crypto/seed.c b/crypto/seed.c +index 9c904d6..c6ba843 100644 +--- a/crypto/seed.c ++++ b/crypto/seed.c +@@ -476,3 +476,4 @@ module_exit(seed_fini); + MODULE_DESCRIPTION("SEED Cipher Algorithm"); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Hye-Shik Chang , Kim Hyun "); ++MODULE_ALIAS_CRYPTO("seed"); +diff --git a/crypto/seqiv.c b/crypto/seqiv.c +index f2cba4ed..49a4069 100644 +--- a/crypto/seqiv.c ++++ b/crypto/seqiv.c +@@ -362,3 +362,4 @@ module_exit(seqiv_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Sequence Number IV Generator"); ++MODULE_ALIAS_CRYPTO("seqiv"); +diff --git a/crypto/serpent_generic.c b/crypto/serpent_generic.c +index 7ddbd7e..94970a7 100644 +--- a/crypto/serpent_generic.c ++++ b/crypto/serpent_generic.c +@@ -665,5 +665,6 @@ module_exit(serpent_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Serpent and tnepres (kerneli compatible serpent reversed) Cipher Algorithm"); + MODULE_AUTHOR("Dag Arne Osvik "); +-MODULE_ALIAS("tnepres"); +-MODULE_ALIAS("serpent"); ++MODULE_ALIAS_CRYPTO("tnepres"); ++MODULE_ALIAS_CRYPTO("serpent"); ++MODULE_ALIAS_CRYPTO("serpent-generic"); +diff --git a/crypto/sha1_generic.c b/crypto/sha1_generic.c +index 4279480..fdf7c00 100644 +--- a/crypto/sha1_generic.c ++++ b/crypto/sha1_generic.c +@@ -153,4 +153,5 @@ module_exit(sha1_generic_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); + +-MODULE_ALIAS("sha1"); ++MODULE_ALIAS_CRYPTO("sha1"); ++MODULE_ALIAS_CRYPTO("sha1-generic"); +diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c +index 5433667..136381b 100644 +--- a/crypto/sha256_generic.c ++++ b/crypto/sha256_generic.c +@@ -384,5 +384,7 @@ module_exit(sha256_generic_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm"); + +-MODULE_ALIAS("sha224"); +-MODULE_ALIAS("sha256"); ++MODULE_ALIAS_CRYPTO("sha224"); ++MODULE_ALIAS_CRYPTO("sha224-generic"); ++MODULE_ALIAS_CRYPTO("sha256"); ++MODULE_ALIAS_CRYPTO("sha256-generic"); +diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c +index 6ed124f..6c6d901 100644 +--- a/crypto/sha512_generic.c ++++ b/crypto/sha512_generic.c +@@ -287,5 +287,7 @@ module_exit(sha512_generic_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms"); + +-MODULE_ALIAS("sha384"); +-MODULE_ALIAS("sha512"); ++MODULE_ALIAS_CRYPTO("sha384"); ++MODULE_ALIAS_CRYPTO("sha384-generic"); ++MODULE_ALIAS_CRYPTO("sha512"); ++MODULE_ALIAS_CRYPTO("sha512-generic"); +diff --git a/crypto/tea.c b/crypto/tea.c +index 0a57232..b70b441 100644 +--- a/crypto/tea.c ++++ b/crypto/tea.c +@@ -270,8 +270,9 @@ static void __exit tea_mod_fini(void) + crypto_unregister_algs(tea_algs, ARRAY_SIZE(tea_algs)); + } + +-MODULE_ALIAS("xtea"); +-MODULE_ALIAS("xeta"); ++MODULE_ALIAS_CRYPTO("tea"); ++MODULE_ALIAS_CRYPTO("xtea"); ++MODULE_ALIAS_CRYPTO("xeta"); + + module_init(tea_mod_init); + module_exit(tea_mod_fini); +diff --git a/crypto/tgr192.c b/crypto/tgr192.c +index 8740355..f7ed2fb 100644 +--- a/crypto/tgr192.c ++++ b/crypto/tgr192.c +@@ -676,8 +676,9 @@ static void __exit tgr192_mod_fini(void) + crypto_unregister_shashes(tgr_algs, ARRAY_SIZE(tgr_algs)); + } + +-MODULE_ALIAS("tgr160"); +-MODULE_ALIAS("tgr128"); ++MODULE_ALIAS_CRYPTO("tgr192"); ++MODULE_ALIAS_CRYPTO("tgr160"); ++MODULE_ALIAS_CRYPTO("tgr128"); + + module_init(tgr192_mod_init); + module_exit(tgr192_mod_fini); +diff --git a/crypto/twofish_generic.c b/crypto/twofish_generic.c +index 2d50005..ebf7a3e 100644 +--- a/crypto/twofish_generic.c ++++ b/crypto/twofish_generic.c +@@ -211,4 +211,5 @@ module_exit(twofish_mod_fini); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION ("Twofish Cipher Algorithm"); +-MODULE_ALIAS("twofish"); ++MODULE_ALIAS_CRYPTO("twofish"); ++MODULE_ALIAS_CRYPTO("twofish-generic"); +diff --git a/crypto/vmac.c b/crypto/vmac.c +index 2eb11a3..bf2d3a8 100644 +--- a/crypto/vmac.c ++++ b/crypto/vmac.c +@@ -713,3 +713,4 @@ module_exit(vmac_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("VMAC hash algorithm"); ++MODULE_ALIAS_CRYPTO("vmac"); +diff --git a/crypto/wp512.c b/crypto/wp512.c +index 180f1d6..253db94 100644 +--- a/crypto/wp512.c ++++ b/crypto/wp512.c +@@ -1167,8 +1167,9 @@ static void __exit wp512_mod_fini(void) + crypto_unregister_shashes(wp_algs, ARRAY_SIZE(wp_algs)); + } + +-MODULE_ALIAS("wp384"); +-MODULE_ALIAS("wp256"); ++MODULE_ALIAS_CRYPTO("wp512"); ++MODULE_ALIAS_CRYPTO("wp384"); ++MODULE_ALIAS_CRYPTO("wp256"); + + module_init(wp512_mod_init); + module_exit(wp512_mod_fini); +diff --git a/crypto/xcbc.c b/crypto/xcbc.c +index a5fbdf3..df90b33 100644 +--- a/crypto/xcbc.c ++++ b/crypto/xcbc.c +@@ -286,3 +286,4 @@ module_exit(crypto_xcbc_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("XCBC keyed hash algorithm"); ++MODULE_ALIAS_CRYPTO("xcbc"); +diff --git a/crypto/xts.c b/crypto/xts.c +index ca1608f..f6fd43f 100644 +--- a/crypto/xts.c ++++ b/crypto/xts.c +@@ -362,3 +362,4 @@ module_exit(crypto_module_exit); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("XTS block cipher mode"); ++MODULE_ALIAS_CRYPTO("xts"); +diff --git a/crypto/zlib.c b/crypto/zlib.c +index 06b62e5..d980788 100644 +--- a/crypto/zlib.c ++++ b/crypto/zlib.c +@@ -378,3 +378,4 @@ module_exit(zlib_mod_fini); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Zlib Compression Algorithm"); + MODULE_AUTHOR("Sony Corporation"); ++MODULE_ALIAS_CRYPTO("zlib"); +diff --git a/drivers/acpi/acpi_cmos_rtc.c b/drivers/acpi/acpi_cmos_rtc.c +index 84190ed..aff69d9 100644 +--- a/drivers/acpi/acpi_cmos_rtc.c ++++ b/drivers/acpi/acpi_cmos_rtc.c +@@ -35,7 +35,7 @@ acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address, + void *handler_context, void *region_context) + { + int i; +- u8 *value = (u8 *)&value64; ++ u8 *value = (u8 *)value64; + + if (address > 0xff || !value64) + return AE_BAD_PARAMETER; +diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h +index d95ca54..e6ab104 100644 +--- a/drivers/acpi/acpica/aclocal.h ++++ b/drivers/acpi/acpica/aclocal.h +@@ -254,6 +254,7 @@ struct acpi_create_field_info { + u32 field_bit_position; + u32 field_bit_length; + u16 resource_length; ++ u16 pin_number_index; + u8 field_flags; + u8 attribute; + u8 field_type; +diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h +index 2a86c65..97c7a52 100644 +--- a/drivers/acpi/acpica/acmacros.h ++++ b/drivers/acpi/acpica/acmacros.h +@@ -63,19 +63,15 @@ + #define ACPI_SET64(ptr, val) (*ACPI_CAST64 (ptr) = (u64) (val)) + + /* +- * printf() format helpers ++ * printf() format helper. This macros is a workaround for the difficulties ++ * with emitting 64-bit integers and 64-bit pointers with the same code ++ * for both 32-bit and 64-bit hosts. + */ + + /* Split 64-bit integer into two 32-bit values. Use with %8.8X%8.8X */ + + #define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i), ACPI_LODWORD(i) + +-#if ACPI_MACHINE_WIDTH == 64 +-#define ACPI_FORMAT_NATIVE_UINT(i) ACPI_FORMAT_UINT64(i) +-#else +-#define ACPI_FORMAT_NATIVE_UINT(i) 0, (i) +-#endif +- + /* + * Macros for moving data around to/from buffers that are possibly unaligned. + * If the hardware supports the transfer of unaligned data, just do the store. +diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h +index cc7ab6d..a47cc78f 100644 +--- a/drivers/acpi/acpica/acobject.h ++++ b/drivers/acpi/acpica/acobject.h +@@ -263,6 +263,7 @@ struct acpi_object_region_field { + ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO u16 resource_length; + union acpi_operand_object *region_obj; /* Containing op_region object */ + u8 *resource_buffer; /* resource_template for serial regions/fields */ ++ u16 pin_number_index; /* Index relative to previous Connection/Template */ + }; + + struct acpi_object_bank_field { +diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c +index e7a57c5..9af55bd 100644 +--- a/drivers/acpi/acpica/dsfield.c ++++ b/drivers/acpi/acpica/dsfield.c +@@ -360,6 +360,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, + */ + info->resource_buffer = NULL; + info->connection_node = NULL; ++ info->pin_number_index = 0; + + /* + * A Connection() is either an actual resource descriptor (buffer) +@@ -437,6 +438,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, + } + + info->field_bit_position += info->field_bit_length; ++ info->pin_number_index++; /* Index relative to previous Connection() */ + break; + + default: +diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c +index 5205edc..fe79296 100644 +--- a/drivers/acpi/acpica/dsopcode.c ++++ b/drivers/acpi/acpica/dsopcode.c +@@ -446,7 +446,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", + obj_desc, +- ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), ++ ACPI_FORMAT_UINT64(obj_desc->region.address), + obj_desc->region.length)); + + /* Now the address and length are valid for this opregion */ +@@ -539,13 +539,12 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, + return_ACPI_STATUS(AE_NOT_EXIST); + } + +- obj_desc->region.address = +- (acpi_physical_address) ACPI_TO_INTEGER(table); ++ obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table); + obj_desc->region.length = table->length; + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", + obj_desc, +- ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), ++ ACPI_FORMAT_UINT64(obj_desc->region.address), + obj_desc->region.length)); + + /* Now the address and length are valid for this opregion */ +diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c +index 144cbb9..ee8ec4b 100644 +--- a/drivers/acpi/acpica/evregion.c ++++ b/drivers/acpi/acpica/evregion.c +@@ -142,6 +142,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, + union acpi_operand_object *region_obj2; + void *region_context = NULL; + struct acpi_connection_info *context; ++ acpi_physical_address address; + + ACPI_FUNCTION_TRACE(ev_address_space_dispatch); + +@@ -231,25 +232,23 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, + /* We have everything we need, we can invoke the address space handler */ + + handler = handler_desc->address_space.handler; +- +- ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, +- "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", +- ®ion_obj->region.handler->address_space, handler, +- ACPI_FORMAT_NATIVE_UINT(region_obj->region.address + +- region_offset), +- acpi_ut_get_region_name(region_obj->region. +- space_id))); ++ address = (region_obj->region.address + region_offset); + + /* + * Special handling for generic_serial_bus and general_purpose_io: + * There are three extra parameters that must be passed to the + * handler via the context: +- * 1) Connection buffer, a resource template from Connection() op. +- * 2) Length of the above buffer. +- * 3) Actual access length from the access_as() op. ++ * 1) Connection buffer, a resource template from Connection() op ++ * 2) Length of the above buffer ++ * 3) Actual access length from the access_as() op ++ * ++ * In addition, for general_purpose_io, the Address and bit_width fields ++ * are defined as follows: ++ * 1) Address is the pin number index of the field (bit offset from ++ * the previous Connection) ++ * 2) bit_width is the actual bit length of the field (number of pins) + */ +- if (((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) || +- (region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) && ++ if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) && + context && field_obj) { + + /* Get the Connection (resource_template) buffer */ +@@ -258,6 +257,24 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, + context->length = field_obj->field.resource_length; + context->access_length = field_obj->field.access_length; + } ++ if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) && ++ context && field_obj) { ++ ++ /* Get the Connection (resource_template) buffer */ ++ ++ context->connection = field_obj->field.resource_buffer; ++ context->length = field_obj->field.resource_length; ++ context->access_length = field_obj->field.access_length; ++ address = field_obj->field.pin_number_index; ++ bit_width = field_obj->field.bit_length; ++ } ++ ++ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, ++ "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", ++ ®ion_obj->region.handler->address_space, handler, ++ ACPI_FORMAT_UINT64(address), ++ acpi_ut_get_region_name(region_obj->region. ++ space_id))); + + if (!(handler_desc->address_space.handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { +@@ -271,9 +288,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, + + /* Call the handler */ + +- status = handler(function, +- (region_obj->region.address + region_offset), +- bit_width, value, context, ++ status = handler(function, address, bit_width, value, context, + region_obj2->extra.region_context); + + if (ACPI_FAILURE(status)) { +diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c +index 4d046fa..b64fb68 100644 +--- a/drivers/acpi/acpica/exdump.c ++++ b/drivers/acpi/acpica/exdump.c +@@ -622,8 +622,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) + acpi_os_printf("\n"); + } else { + acpi_os_printf(" base %8.8X%8.8X Length %X\n", +- ACPI_FORMAT_NATIVE_UINT(obj_desc->region. +- address), ++ ACPI_FORMAT_UINT64(obj_desc->region. ++ address), + obj_desc->region.length); + } + break; +diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c +index cfd8752..d36894a 100644 +--- a/drivers/acpi/acpica/exfield.c ++++ b/drivers/acpi/acpica/exfield.c +@@ -178,6 +178,37 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, + buffer = &buffer_desc->integer.value; + } + ++ if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && ++ (obj_desc->field.region_obj->region.space_id == ++ ACPI_ADR_SPACE_GPIO)) { ++ /* ++ * For GPIO (general_purpose_io), the Address will be the bit offset ++ * from the previous Connection() operator, making it effectively a ++ * pin number index. The bit_length is the length of the field, which ++ * is thus the number of pins. ++ */ ++ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, ++ "GPIO FieldRead [FROM]: Pin %u Bits %u\n", ++ obj_desc->field.pin_number_index, ++ obj_desc->field.bit_length)); ++ ++ /* Lock entire transaction if requested */ ++ ++ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); ++ ++ /* Perform the write */ ++ ++ status = acpi_ex_access_region(obj_desc, 0, ++ (u64 *)buffer, ACPI_READ); ++ acpi_ex_release_global_lock(obj_desc->common_field.field_flags); ++ if (ACPI_FAILURE(status)) { ++ acpi_ut_remove_reference(buffer_desc); ++ } else { ++ *ret_buffer_desc = buffer_desc; ++ } ++ return_ACPI_STATUS(status); ++ } ++ + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, + "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", + obj_desc, obj_desc->common.type, buffer, +@@ -325,6 +356,42 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, + + *result_desc = buffer_desc; + return_ACPI_STATUS(status); ++ } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && ++ (obj_desc->field.region_obj->region.space_id == ++ ACPI_ADR_SPACE_GPIO)) { ++ /* ++ * For GPIO (general_purpose_io), we will bypass the entire field ++ * mechanism and handoff the bit address and bit width directly to ++ * the handler. The Address will be the bit offset ++ * from the previous Connection() operator, making it effectively a ++ * pin number index. The bit_length is the length of the field, which ++ * is thus the number of pins. ++ */ ++ if (source_desc->common.type != ACPI_TYPE_INTEGER) { ++ return_ACPI_STATUS(AE_AML_OPERAND_TYPE); ++ } ++ ++ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, ++ "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n", ++ acpi_ut_get_type_name(source_desc->common. ++ type), ++ source_desc->common.type, ++ (u32)source_desc->integer.value, ++ obj_desc->field.pin_number_index, ++ obj_desc->field.bit_length)); ++ ++ buffer = &source_desc->integer.value; ++ ++ /* Lock entire transaction if requested */ ++ ++ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); ++ ++ /* Perform the write */ ++ ++ status = acpi_ex_access_region(obj_desc, 0, ++ (u64 *)buffer, ACPI_WRITE); ++ acpi_ex_release_global_lock(obj_desc->common_field.field_flags); ++ return_ACPI_STATUS(status); + } + + /* Get a pointer to the data to be written */ +diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c +index 49fb742..98af39f 100644 +--- a/drivers/acpi/acpica/exfldio.c ++++ b/drivers/acpi/acpica/exfldio.c +@@ -263,17 +263,15 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD, +- " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n", ++ " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n", + acpi_ut_get_region_name(rgn_desc->region. + space_id), + rgn_desc->region.space_id, + obj_desc->common_field.access_byte_width, + obj_desc->common_field.base_byte_offset, +- field_datum_byte_offset, ACPI_CAST_PTR(void, +- (rgn_desc-> +- region. +- address + +- region_offset)))); ++ field_datum_byte_offset, ++ ACPI_FORMAT_UINT64(rgn_desc->region.address + ++ region_offset))); + + /* Invoke the appropriate address_space/op_region handler */ + +diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c +index 5a58861..8c88cfd 100644 +--- a/drivers/acpi/acpica/exprep.c ++++ b/drivers/acpi/acpica/exprep.c +@@ -484,6 +484,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) + obj_desc->field.resource_length = info->resource_length; + } + ++ obj_desc->field.pin_number_index = info->pin_number_index; ++ + /* Allow full data read from EC address space */ + + if ((obj_desc->field.region_obj->region.space_id == +diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c +index 9d28867e..cf40223 100644 +--- a/drivers/acpi/acpica/exregion.c ++++ b/drivers/acpi/acpica/exregion.c +@@ -181,7 +181,7 @@ acpi_ex_system_memory_space_handler(u32 function, + if (!mem_info->mapped_logical_address) { + ACPI_ERROR((AE_INFO, + "Could not map memory at 0x%8.8X%8.8X, size %u", +- ACPI_FORMAT_NATIVE_UINT(address), ++ ACPI_FORMAT_UINT64(address), + (u32) map_length)); + mem_info->mapped_length = 0; + return_ACPI_STATUS(AE_NO_MEMORY); +@@ -202,8 +202,7 @@ acpi_ex_system_memory_space_handler(u32 function, + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n", +- bit_width, function, +- ACPI_FORMAT_NATIVE_UINT(address))); ++ bit_width, function, ACPI_FORMAT_UINT64(address))); + + /* + * Perform the memory read or write +@@ -318,8 +317,7 @@ acpi_ex_system_io_space_handler(u32 function, + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n", +- bit_width, function, +- ACPI_FORMAT_NATIVE_UINT(address))); ++ bit_width, function, ACPI_FORMAT_UINT64(address))); + + /* Decode the function parameter */ + +diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c +index eab70d5..fae5758 100644 +--- a/drivers/acpi/acpica/hwvalid.c ++++ b/drivers/acpi/acpica/hwvalid.c +@@ -142,17 +142,17 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width) + byte_width = ACPI_DIV_8(bit_width); + last_address = address + byte_width - 1; + +- ACPI_DEBUG_PRINT((ACPI_DB_IO, "Address %p LastAddress %p Length %X", +- ACPI_CAST_PTR(void, address), ACPI_CAST_PTR(void, +- last_address), +- byte_width)); ++ ACPI_DEBUG_PRINT((ACPI_DB_IO, ++ "Address %8.8X%8.8X LastAddress %8.8X%8.8X Length %X", ++ ACPI_FORMAT_UINT64(address), ++ ACPI_FORMAT_UINT64(last_address), byte_width)); + + /* Maximum 16-bit address in I/O space */ + + if (last_address > ACPI_UINT16_MAX) { + ACPI_ERROR((AE_INFO, +- "Illegal I/O port address/length above 64K: %p/0x%X", +- ACPI_CAST_PTR(void, address), byte_width)); ++ "Illegal I/O port address/length above 64K: %8.8X%8.8X/0x%X", ++ ACPI_FORMAT_UINT64(address), byte_width)); + return_ACPI_STATUS(AE_LIMIT); + } + +@@ -181,8 +181,8 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width) + + if (acpi_gbl_osi_data >= port_info->osi_dependency) { + ACPI_DEBUG_PRINT((ACPI_DB_IO, +- "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)", +- ACPI_CAST_PTR(void, address), ++ "Denied AML access to port 0x%8.8X%8.8X/%X (%s 0x%.4X-0x%.4X)", ++ ACPI_FORMAT_UINT64(address), + byte_width, port_info->name, + port_info->start, + port_info->end)); +diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c +index 48b9c6f..fc82c53 100644 +--- a/drivers/acpi/acpica/nsdump.c ++++ b/drivers/acpi/acpica/nsdump.c +@@ -271,12 +271,11 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, + switch (type) { + case ACPI_TYPE_PROCESSOR: + +- acpi_os_printf("ID %02X Len %02X Addr %p\n", ++ acpi_os_printf("ID %02X Len %02X Addr %8.8X%8.8X\n", + obj_desc->processor.proc_id, + obj_desc->processor.length, +- ACPI_CAST_PTR(void, +- obj_desc->processor. +- address)); ++ ACPI_FORMAT_UINT64(obj_desc->processor. ++ address)); + break; + + case ACPI_TYPE_DEVICE: +@@ -347,8 +346,9 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, + space_id)); + if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { + acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n", +- ACPI_FORMAT_NATIVE_UINT +- (obj_desc->region.address), ++ ACPI_FORMAT_UINT64(obj_desc-> ++ region. ++ address), + obj_desc->region.length); + } else { + acpi_os_printf +diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c +index 634357d..c4d0977 100644 +--- a/drivers/acpi/acpica/tbinstal.c ++++ b/drivers/acpi/acpica/tbinstal.c +@@ -294,8 +294,7 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header + ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, + "%4.4s %p Attempted physical table override failed", + table_header->signature, +- ACPI_CAST_PTR(void, +- table_desc->address))); ++ ACPI_PHYSADDR_TO_PTR(table_desc->address))); + return (NULL); + } + +@@ -311,7 +310,7 @@ finish_override: + ACPI_INFO((AE_INFO, + "%4.4s %p %s table override, new table: %p", + table_header->signature, +- ACPI_CAST_PTR(void, table_desc->address), ++ ACPI_PHYSADDR_TO_PTR(table_desc->address), + override_type, new_table)); + + /* We can now unmap/delete the original table (if fully mapped) */ +diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c +index 6866e76..2957ed5 100644 +--- a/drivers/acpi/acpica/tbprint.c ++++ b/drivers/acpi/acpica/tbprint.c +@@ -127,16 +127,12 @@ acpi_tb_print_table_header(acpi_physical_address address, + { + struct acpi_table_header local_header; + +- /* +- * The reason that the Address is cast to a void pointer is so that we +- * can use %p which will work properly on both 32-bit and 64-bit hosts. +- */ + if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { + + /* FACS only has signature and length fields */ + +- ACPI_INFO((AE_INFO, "%4.4s %p %06X", +- header->signature, ACPI_CAST_PTR(void, address), ++ ACPI_INFO((AE_INFO, "%-4.4s 0x%8.8X%8.8X %06X", ++ header->signature, ACPI_FORMAT_UINT64(address), + header->length)); + } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) { + +@@ -147,8 +143,8 @@ acpi_tb_print_table_header(acpi_physical_address address, + header)->oem_id, ACPI_OEM_ID_SIZE); + acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); + +- ACPI_INFO((AE_INFO, "RSDP %p %06X (v%.2d %6.6s)", +- ACPI_CAST_PTR(void, address), ++ ACPI_INFO((AE_INFO, "RSDP 0x%8.8X%8.8X %06X (v%.2d %-6.6s)", ++ ACPI_FORMAT_UINT64(address), + (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> + revision > + 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, +@@ -162,8 +158,9 @@ acpi_tb_print_table_header(acpi_physical_address address, + acpi_tb_cleanup_table_header(&local_header, header); + + ACPI_INFO((AE_INFO, +- "%4.4s %p %06X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", +- local_header.signature, ACPI_CAST_PTR(void, address), ++ "%-4.4s 0x%8.8X%8.8X" ++ " %06X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)", ++ local_header.signature, ACPI_FORMAT_UINT64(address), + local_header.length, local_header.revision, + local_header.oem_id, local_header.oem_table_id, + local_header.oem_revision, +diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c +index 1bc879e..4cca6b7 100644 +--- a/drivers/acpi/acpica/tbutils.c ++++ b/drivers/acpi/acpica/tbutils.c +@@ -227,8 +227,8 @@ acpi_tb_install_table(acpi_physical_address address, + table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); + if (!table) { + ACPI_ERROR((AE_INFO, +- "Could not map memory for table [%s] at %p", +- signature, ACPI_CAST_PTR(void, address))); ++ "Could not map memory for table [%s] at %8.8X%8.8X", ++ signature, ACPI_FORMAT_UINT64(address))); + return; + } + +diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c +index 60b5a87..daad59d 100644 +--- a/drivers/acpi/acpica/tbxfload.c ++++ b/drivers/acpi/acpica/tbxfload.c +@@ -184,11 +184,10 @@ static acpi_status acpi_tb_load_namespace(void) + * be useful for debugging ACPI problems on some machines. + */ + if (acpi_gbl_disable_ssdt_table_load) { +- ACPI_INFO((AE_INFO, "Ignoring %4.4s at %p", ++ ACPI_INFO((AE_INFO, "Ignoring %4.4s at %8.8X%8.8X", + acpi_gbl_root_table_list.tables[i].signature. +- ascii, ACPI_CAST_PTR(void, +- acpi_gbl_root_table_list. +- tables[i].address))); ++ ascii, ACPI_FORMAT_UINT64(acpi_gbl_root_table_list. ++ tables[i].address))); + continue; + } + +diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c +index e4e1468..01bf7eb 100644 +--- a/drivers/acpi/acpica/tbxfroot.c ++++ b/drivers/acpi/acpica/tbxfroot.c +@@ -111,7 +111,7 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) + * + ******************************************************************************/ + +-acpi_status __init acpi_find_root_pointer(acpi_size *table_address) ++acpi_status __init acpi_find_root_pointer(acpi_physical_address * table_address) + { + u8 *table_ptr; + u8 *mem_rover; +@@ -169,7 +169,8 @@ acpi_status __init acpi_find_root_pointer(acpi_size *table_address) + physical_address += + (u32) ACPI_PTR_DIFF(mem_rover, table_ptr); + +- *table_address = physical_address; ++ *table_address = ++ (acpi_physical_address) physical_address; + return_ACPI_STATUS(AE_OK); + } + } +@@ -202,7 +203,7 @@ acpi_status __init acpi_find_root_pointer(acpi_size *table_address) + (ACPI_HI_RSDP_WINDOW_BASE + + ACPI_PTR_DIFF(mem_rover, table_ptr)); + +- *table_address = physical_address; ++ *table_address = (acpi_physical_address) physical_address; + return_ACPI_STATUS(AE_OK); + } + +diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c +index 2c2b6ae..3a02b65 100644 +--- a/drivers/acpi/acpica/utaddress.c ++++ b/drivers/acpi/acpica/utaddress.c +@@ -107,10 +107,10 @@ acpi_ut_add_address_range(acpi_adr_space_type space_id, + acpi_gbl_address_range_list[space_id] = range_info; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, +- "\nAdded [%4.4s] address range: 0x%p-0x%p\n", ++ "\nAdded [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n", + acpi_ut_get_node_name(range_info->region_node), +- ACPI_CAST_PTR(void, address), +- ACPI_CAST_PTR(void, range_info->end_address))); ++ ACPI_FORMAT_UINT64(address), ++ ACPI_FORMAT_UINT64(range_info->end_address))); + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(AE_OK); +@@ -160,15 +160,13 @@ acpi_ut_remove_address_range(acpi_adr_space_type space_id, + } + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, +- "\nRemoved [%4.4s] address range: 0x%p-0x%p\n", ++ "\nRemoved [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n", + acpi_ut_get_node_name(range_info-> + region_node), +- ACPI_CAST_PTR(void, +- range_info-> +- start_address), +- ACPI_CAST_PTR(void, +- range_info-> +- end_address))); ++ ACPI_FORMAT_UINT64(range_info-> ++ start_address), ++ ACPI_FORMAT_UINT64(range_info-> ++ end_address))); + + ACPI_FREE(range_info); + return_VOID; +@@ -245,16 +243,14 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id, + region_node); + + ACPI_WARNING((AE_INFO, +- "%s range 0x%p-0x%p conflicts with OpRegion 0x%p-0x%p (%s)", ++ "%s range 0x%8.8X%8.8X-0x%8.8X%8.8X conflicts with OpRegion 0x%8.8X%8.8X-0x%8.8X%8.8X (%s)", + acpi_ut_get_region_name(space_id), +- ACPI_CAST_PTR(void, address), +- ACPI_CAST_PTR(void, end_address), +- ACPI_CAST_PTR(void, +- range_info-> +- start_address), +- ACPI_CAST_PTR(void, +- range_info-> +- end_address), ++ ACPI_FORMAT_UINT64(address), ++ ACPI_FORMAT_UINT64(end_address), ++ ACPI_FORMAT_UINT64(range_info-> ++ start_address), ++ ACPI_FORMAT_UINT64(range_info-> ++ end_address), + pathname)); + ACPI_FREE(pathname); + } +diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c +index edff4e6..c66bca1 100644 +--- a/drivers/acpi/acpica/utcopy.c ++++ b/drivers/acpi/acpica/utcopy.c +@@ -1001,5 +1001,11 @@ acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc, + status = acpi_ut_copy_simple_object(source_desc, *dest_desc); + } + ++ /* Delete the allocated object if copy failed */ ++ ++ if (ACPI_FAILURE(status)) { ++ acpi_ut_remove_reference(*dest_desc); ++ } ++ + return_ACPI_STATUS(status); + } +diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c +index 246ef68..2c3c578 100644 +--- a/drivers/acpi/acpica/utxfinit.c ++++ b/drivers/acpi/acpica/utxfinit.c +@@ -175,10 +175,12 @@ acpi_status __init acpi_enable_subsystem(u32 flags) + * Obtain a permanent mapping for the FACS. This is required for the + * Global Lock and the Firmware Waking Vector + */ +- status = acpi_tb_initialize_facs(); +- if (ACPI_FAILURE(status)) { +- ACPI_WARNING((AE_INFO, "Could not map the FACS table")); +- return_ACPI_STATUS(status); ++ if (!(flags & ACPI_NO_FACS_INIT)) { ++ status = acpi_tb_initialize_facs(); ++ if (ACPI_FAILURE(status)) { ++ ACPI_WARNING((AE_INFO, "Could not map the FACS table")); ++ return_ACPI_STATUS(status); ++ } + } + #endif /* !ACPI_REDUCED_HARDWARE */ + +diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c +index b48aefa..60be8d0 100644 +--- a/drivers/acpi/bus.c ++++ b/drivers/acpi/bus.c +@@ -450,6 +450,16 @@ static int __init acpi_bus_init_irq(void) + u8 acpi_gbl_permanent_mmap; + + ++/** ++ * acpi_early_init - Initialize ACPICA and populate the ACPI namespace. ++ * ++ * The ACPI tables are accessible after this, but the handling of events has not ++ * been initialized and the global lock is not available yet, so AML should not ++ * be executed at this point. ++ * ++ * Doing this before switching the EFI runtime services to virtual mode allows ++ * the EfiBootServices memory to be freed slightly earlier on boot. ++ */ + void __init acpi_early_init(void) + { + acpi_status status; +@@ -510,26 +520,42 @@ void __init acpi_early_init(void) + acpi_gbl_FADT.sci_interrupt = acpi_sci_override_gsi; + } + #endif ++ return; ++ ++ error0: ++ disable_acpi(); ++} ++ ++/** ++ * acpi_subsystem_init - Finalize the early initialization of ACPI. ++ * ++ * Switch over the platform to the ACPI mode (if possible), initialize the ++ * handling of ACPI events, install the interrupt and global lock handlers. ++ * ++ * Doing this too early is generally unsafe, but at the same time it needs to be ++ * done before all things that really depend on ACPI. The right spot appears to ++ * be before finalizing the EFI initialization. ++ */ ++void __init acpi_subsystem_init(void) ++{ ++ acpi_status status; ++ ++ if (acpi_disabled) ++ return; + + status = acpi_enable_subsystem(~ACPI_NO_ACPI_ENABLE); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Unable to enable ACPI\n"); +- goto error0; ++ disable_acpi(); ++ } else { ++ /* ++ * If the system is using ACPI then we can be reasonably ++ * confident that any regulators are managed by the firmware ++ * so tell the regulator core it has everything it needs to ++ * know. ++ */ ++ regulator_has_full_constraints(); + } +- +- /* +- * If the system is using ACPI then we can be reasonably +- * confident that any regulators are managed by the firmware +- * so tell the regulator core it has everything it needs to +- * know. +- */ +- regulator_has_full_constraints(); +- +- return; +- +- error0: +- disable_acpi(); +- return; + } + + static int __init acpi_bus_init(void) +diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c +index 368f9dd..e4a6f78 100644 +--- a/drivers/acpi/container.c ++++ b/drivers/acpi/container.c +@@ -96,6 +96,13 @@ static void container_device_detach(struct acpi_device *adev) + device_unregister(dev); + } + ++static void container_device_online(struct acpi_device *adev) ++{ ++ struct device *dev = acpi_driver_data(adev); ++ ++ kobject_uevent(&dev->kobj, KOBJ_ONLINE); ++} ++ + static struct acpi_scan_handler container_handler = { + .ids = container_device_ids, + .attach = container_device_attach, +@@ -103,6 +110,7 @@ static struct acpi_scan_handler container_handler = { + .hotplug = { + .enabled = true, + .demand_offline = true, ++ .notify_online = container_device_online, + }, + }; + +diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c +index c14a00d..19f6505 100644 +--- a/drivers/acpi/device_pm.c ++++ b/drivers/acpi/device_pm.c +@@ -257,7 +257,7 @@ int acpi_bus_init_power(struct acpi_device *device) + + device->power.state = ACPI_STATE_UNKNOWN; + if (!acpi_device_is_present(device)) +- return 0; ++ return -ENXIO; + + result = acpi_device_get_power(device, &state); + if (result) +diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c +index fc1aa79..726c969 100644 +--- a/drivers/acpi/osl.c ++++ b/drivers/acpi/osl.c +@@ -172,7 +172,7 @@ static void __init acpi_request_region (struct acpi_generic_address *gas, + request_mem_region(addr, length, desc); + } + +-static int __init acpi_reserve_resources(void) ++static void __init acpi_reserve_resources(void) + { + acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length, + "ACPI PM1a_EVT_BLK"); +@@ -201,10 +201,7 @@ static int __init acpi_reserve_resources(void) + if (!(acpi_gbl_FADT.gpe1_block_length & 0x1)) + acpi_request_region(&acpi_gbl_FADT.xgpe1_block, + acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK"); +- +- return 0; + } +-device_initcall(acpi_reserve_resources); + + void acpi_os_printf(const char *fmt, ...) + { +@@ -1792,6 +1789,7 @@ acpi_status __init acpi_os_initialize(void) + + acpi_status __init acpi_os_initialize1(void) + { ++ acpi_reserve_resources(); + kacpid_wq = alloc_workqueue("kacpid", 0, 1); + kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1); + kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0); +diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c +index 3dca36d..fd8496a 100644 +--- a/drivers/acpi/processor_idle.c ++++ b/drivers/acpi/processor_idle.c +@@ -962,7 +962,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) + return -EINVAL; + + drv->safe_state_index = -1; +- for (i = 0; i < CPUIDLE_STATE_MAX; i++) { ++ for (i = CPUIDLE_DRIVER_STATE_START; i < CPUIDLE_STATE_MAX; i++) { + drv->states[i].name[0] = '\0'; + drv->states[i].desc[0] = '\0'; + } +@@ -1071,9 +1071,9 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) + + if (pr->id == 0 && cpuidle_get_driver() == &acpi_idle_driver) { + +- cpuidle_pause_and_lock(); + /* Protect against cpu-hotplug */ + get_online_cpus(); ++ cpuidle_pause_and_lock(); + + /* Disable all cpuidle devices */ + for_each_online_cpu(cpu) { +@@ -1100,8 +1100,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) + cpuidle_enable_device(dev); + } + } +- put_online_cpus(); + cpuidle_resume_and_unlock(); ++ put_online_cpus(); + } + + return 0; +diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c +index 57b053f..9498c3d 100644 +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -106,7 +106,7 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, + list_for_each_entry(id, &acpi_dev->pnp.ids, list) { + count = snprintf(&modalias[len], size, "%s:", id->id); + if (count < 0) +- return EINVAL; ++ return -EINVAL; + if (count >= size) + return -ENOMEM; + len += count; +@@ -192,7 +192,11 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent) + struct acpi_device_physical_node *pn; + bool offline = true; + +- mutex_lock(&adev->physical_node_lock); ++ /* ++ * acpi_container_offline() calls this for all of the container's ++ * children under the container's physical_node_lock lock. ++ */ ++ mutex_lock_nested(&adev->physical_node_lock, SINGLE_DEPTH_NESTING); + + list_for_each_entry(pn, &adev->physical_node_list, node) + if (device_supports_offline(pn->dev) && !pn->dev->offline) { +@@ -329,7 +333,8 @@ static int acpi_scan_hot_remove(struct acpi_device *device) + unsigned long long sta; + acpi_status status; + +- if (device->handler->hotplug.demand_offline && !acpi_force_hot_remove) { ++ if (device->handler && device->handler->hotplug.demand_offline ++ && !acpi_force_hot_remove) { + if (!acpi_scan_is_offline(device, true)) + return -EBUSY; + } else { +@@ -660,8 +665,14 @@ static ssize_t + acpi_device_sun_show(struct device *dev, struct device_attribute *attr, + char *buf) { + struct acpi_device *acpi_dev = to_acpi_device(dev); ++ acpi_status status; ++ unsigned long long sun; + +- return sprintf(buf, "%lu\n", acpi_dev->pnp.sun); ++ status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun); ++ if (ACPI_FAILURE(status)) ++ return -ENODEV; ++ ++ return sprintf(buf, "%llu\n", sun); + } + static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL); + +@@ -683,7 +694,6 @@ static int acpi_device_setup_files(struct acpi_device *dev) + { + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_status status; +- unsigned long long sun; + int result = 0; + + /* +@@ -724,14 +734,10 @@ static int acpi_device_setup_files(struct acpi_device *dev) + if (dev->pnp.unique_id) + result = device_create_file(&dev->dev, &dev_attr_uid); + +- status = acpi_evaluate_integer(dev->handle, "_SUN", NULL, &sun); +- if (ACPI_SUCCESS(status)) { +- dev->pnp.sun = (unsigned long)sun; ++ if (acpi_has_method(dev->handle, "_SUN")) { + result = device_create_file(&dev->dev, &dev_attr_sun); + if (result) + goto end; +- } else { +- dev->pnp.sun = (unsigned long)-1; + } + + if (acpi_has_method(dev->handle, "_STA")) { +@@ -863,7 +869,7 @@ static void acpi_free_power_resources_lists(struct acpi_device *device) + if (device->wakeup.flags.valid) + acpi_power_resources_list_free(&device->wakeup.resources); + +- if (!device->flags.power_manageable) ++ if (!device->power.flags.power_resources) + return; + + for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) { +@@ -915,12 +921,17 @@ static void acpi_device_notify(acpi_handle handle, u32 event, void *data) + device->driver->ops.notify(device, event); + } + +-static acpi_status acpi_device_notify_fixed(void *data) ++static void acpi_device_notify_fixed(void *data) + { + struct acpi_device *device = data; + + /* Fixed hardware devices have no handles */ + acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device); ++} ++ ++static acpi_status acpi_device_fixed_event(void *data) ++{ ++ acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data); + return AE_OK; + } + +@@ -931,12 +942,12 @@ static int acpi_device_install_notify_handler(struct acpi_device *device) + if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) + status = + acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, +- acpi_device_notify_fixed, ++ acpi_device_fixed_event, + device); + else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON) + status = + acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, +- acpi_device_notify_fixed, ++ acpi_device_fixed_event, + device); + else + status = acpi_install_notify_handler(device->handle, +@@ -953,10 +964,10 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device) + { + if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) + acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, +- acpi_device_notify_fixed); ++ acpi_device_fixed_event); + else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON) + acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, +- acpi_device_notify_fixed); ++ acpi_device_fixed_event); + else + acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, + acpi_device_notify); +@@ -1547,10 +1558,8 @@ static void acpi_bus_get_power_flags(struct acpi_device *device) + device->power.flags.power_resources) + device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible = 1; + +- if (acpi_bus_init_power(device)) { +- acpi_free_power_resources_lists(device); ++ if (acpi_bus_init_power(device)) + device->flags.power_manageable = 0; +- } + } + + static void acpi_bus_get_flags(struct acpi_device *device) +@@ -2036,13 +2045,18 @@ static void acpi_bus_attach(struct acpi_device *device) + /* Skip devices that are not present. */ + if (!acpi_device_is_present(device)) { + device->flags.visited = false; ++ device->flags.power_manageable = 0; + return; + } + if (device->handler) + goto ok; + + if (!device->flags.initialized) { +- acpi_bus_update_power(device, NULL); ++ device->flags.power_manageable = ++ device->power.states[ACPI_STATE_D0].flags.valid; ++ if (acpi_bus_init_power(device)) ++ device->flags.power_manageable = 0; ++ + device->flags.initialized = true; + } + device->flags.visited = false; +@@ -2061,6 +2075,9 @@ static void acpi_bus_attach(struct acpi_device *device) + ok: + list_for_each_entry(child, &device->children, node) + acpi_bus_attach(child); ++ ++ if (device->handler && device->handler->hotplug.notify_online) ++ device->handler->hotplug.notify_online(device); + } + + /** +diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c +index bb0b904..997540d 100644 +--- a/drivers/acpi/video.c ++++ b/drivers/acpi/video.c +@@ -2064,6 +2064,17 @@ EXPORT_SYMBOL(acpi_video_unregister); + + static int __init acpi_video_init(void) + { ++ /* ++ * Let the module load even if ACPI is disabled (e.g. due to ++ * a broken BIOS) so that i915.ko can still be loaded on such ++ * old systems without an AcpiOpRegion. ++ * ++ * acpi_video_register() will report -ENODEV later as well due ++ * to acpi_disabled when i915.ko tries to register itself afterwards. ++ */ ++ if (acpi_disabled) ++ return 0; ++ + dmi_check_system(video_dmi_table); + + if (intel_opregion_present()) +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index 3e23046..47d28b9 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -60,6 +60,7 @@ enum board_ids { + /* board IDs by feature in alphabetical order */ + board_ahci, + board_ahci_ign_iferr, ++ board_ahci_nomsi, + board_ahci_noncq, + board_ahci_nosntf, + board_ahci_yes_fbs, +@@ -121,6 +122,13 @@ static const struct ata_port_info ahci_port_info[] = { + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_ops, + }, ++ [board_ahci_nomsi] = { ++ AHCI_HFLAGS (AHCI_HFLAG_NO_MSI), ++ .flags = AHCI_FLAG_COMMON, ++ .pio_mask = ATA_PIO4, ++ .udma_mask = ATA_UDMA6, ++ .port_ops = &ahci_ops, ++ }, + [board_ahci_noncq] = { + AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ), + .flags = AHCI_FLAG_COMMON, +@@ -305,6 +313,22 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */ ++ { PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series AHCI */ ++ { PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */ ++ { PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */ ++ { PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */ ++ { PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */ ++ { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */ ++ { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H RAID */ ++ { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */ ++ { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */ ++ { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */ + + /* JMicron 360/1/3/5/6, match class to avoid IDE function */ + { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, +@@ -442,6 +466,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a), + .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172), ++ .driver_data = board_ahci_yes_fbs }, /* 88se9182 */ ++ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182), + .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192), + .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ +@@ -456,6 +482,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { + + /* Promise */ + { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ ++ { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */ + + /* Asmedia */ + { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ +@@ -464,10 +491,11 @@ static const struct pci_device_id ahci_pci_tbl[] = { + { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ + + /* +- * Samsung SSDs found on some macbooks. NCQ times out. +- * https://bugzilla.kernel.org/show_bug.cgi?id=60731 ++ * Samsung SSDs found on some macbooks. NCQ times out if MSI is ++ * enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731 + */ +- { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_noncq }, ++ { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi }, ++ { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi }, + + /* Enmotus */ + { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, +diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c +index 6334c8d..39f76b9 100644 +--- a/drivers/ata/ata_piix.c ++++ b/drivers/ata/ata_piix.c +@@ -340,6 +340,14 @@ static const struct pci_device_id piix_pci_tbl[] = { + { 0x8086, 0x0F21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt }, + /* SATA Controller IDE (Coleto Creek) */ + { 0x8086, 0x23a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, ++ /* SATA Controller IDE (9 Series) */ ++ { 0x8086, 0x8c88, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb }, ++ /* SATA Controller IDE (9 Series) */ ++ { 0x8086, 0x8c89, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb }, ++ /* SATA Controller IDE (9 Series) */ ++ { 0x8086, 0x8c80, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, ++ /* SATA Controller IDE (9 Series) */ ++ { 0x8086, 0x8c81, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + + { } /* terminate list */ + }; +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index 5509e8e..0b6cb25 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -1711,8 +1711,7 @@ static void ahci_handle_port_interrupt(struct ata_port *ap, + if (unlikely(resetting)) + status &= ~PORT_IRQ_BAD_PMP; + +- /* if LPM is enabled, PHYRDY doesn't mean anything */ +- if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) { ++ if (sata_lpm_ignore_phy_events(&ap->link)) { + status &= ~PORT_IRQ_PHYRDY; + ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG); + } +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index d09fca7..01354dd 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -4173,9 +4173,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { + { "ST3320[68]13AS", "SD1[5-9]", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + +- /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */ ++ /* drives which fail FPDMA_AA activation (some may freeze afterwards) */ + { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA }, + { "ST1000LM024 HN-M101MBB", "2BA30001", ATA_HORKAGE_BROKEN_FPDMA_AA }, ++ { "VB0250EAVER", "HPG7", ATA_HORKAGE_BROKEN_FPDMA_AA }, + + /* Blacklist entries taken from Silicon Image 3124/3132 + Windows driver .inf file - also several Linux problem reports */ +@@ -4227,7 +4228,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { + { "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Crucial_CT???M500SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Micron_M550*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, +- { "Crucial_CT???M550SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, ++ { "Crucial_CT*M550SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, ++ ++ /* devices that don't properly handle TRIM commands */ ++ { "SuperSSpeed S238*", NULL, ATA_HORKAGE_NOTRIM, }, + + /* + * Some WD SATA-I drives spin up and down erratically when the link +@@ -4533,7 +4537,8 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev) + else /* In the ancient relic department - skip all of this */ + return 0; + +- err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); ++ /* On some disks, this command causes spin-up, so we need longer timeout */ ++ err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 15000); + + DPRINTK("EXIT, err_mask=%x\n", err_mask); + return err_mask; +@@ -4787,6 +4792,10 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) + * ata_qc_new - Request an available ATA command, for queueing + * @ap: target port + * ++ * Some ATA host controllers may implement a queue depth which is less ++ * than ATA_MAX_QUEUE. So we shouldn't allocate a tag which is beyond ++ * the hardware limitation. ++ * + * LOCKING: + * None. + */ +@@ -4794,14 +4803,15 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) + static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) + { + struct ata_queued_cmd *qc = NULL; ++ unsigned int max_queue = ap->host->n_tags; + unsigned int i, tag; + + /* no command while frozen */ + if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) + return NULL; + +- for (i = 0; i < ATA_MAX_QUEUE; i++) { +- tag = (i + ap->last_tag + 1) % ATA_MAX_QUEUE; ++ for (i = 0, tag = ap->last_tag + 1; i < max_queue; i++, tag++) { ++ tag = tag < max_queue ? tag : 0; + + /* the last tag is reserved for internal command. */ + if (tag == ATA_TAG_INTERNAL) +@@ -6103,6 +6113,7 @@ void ata_host_init(struct ata_host *host, struct device *dev, + { + spin_lock_init(&host->lock); + mutex_init(&host->eh_mutex); ++ host->n_tags = ATA_MAX_QUEUE - 1; + host->dev = dev; + host->ops = ops; + } +@@ -6184,6 +6195,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) + { + int i, rc; + ++ host->n_tags = clamp(sht->can_queue, 1, ATA_MAX_QUEUE - 1); ++ + /* host must have been started */ + if (!(host->flags & ATA_HOST_STARTED)) { + dev_err(host->dev, "BUG: trying to register unstarted host\n"); +@@ -6817,6 +6830,38 @@ u32 ata_wait_register(struct ata_port *ap, void __iomem *reg, u32 mask, u32 val, + return tmp; + } + ++/** ++ * sata_lpm_ignore_phy_events - test if PHY event should be ignored ++ * @link: Link receiving the event ++ * ++ * Test whether the received PHY event has to be ignored or not. ++ * ++ * LOCKING: ++ * None: ++ * ++ * RETURNS: ++ * True if the event has to be ignored. ++ */ ++bool sata_lpm_ignore_phy_events(struct ata_link *link) ++{ ++ unsigned long lpm_timeout = link->last_lpm_change + ++ msecs_to_jiffies(ATA_TMOUT_SPURIOUS_PHY); ++ ++ /* if LPM is enabled, PHYRDY doesn't mean anything */ ++ if (link->lpm_policy > ATA_LPM_MAX_POWER) ++ return true; ++ ++ /* ignore the first PHY event after the LPM policy changed ++ * as it is might be spurious ++ */ ++ if ((link->flags & ATA_LFLAG_CHANGED) && ++ time_before(jiffies, lpm_timeout)) ++ return true; ++ ++ return false; ++} ++EXPORT_SYMBOL_GPL(sata_lpm_ignore_phy_events); ++ + /* + * Dummy port_ops + */ +diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c +index 6d87570..c6c77b7 100644 +--- a/drivers/ata/libata-eh.c ++++ b/drivers/ata/libata-eh.c +@@ -3488,6 +3488,9 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy, + } + } + ++ link->last_lpm_change = jiffies; ++ link->flags |= ATA_LFLAG_CHANGED; ++ + return 0; + + fail: +diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c +index 7ccc084..85aa761 100644 +--- a/drivers/ata/libata-pmp.c ++++ b/drivers/ata/libata-pmp.c +@@ -460,6 +460,13 @@ static void sata_pmp_quirks(struct ata_port *ap) + ATA_LFLAG_NO_SRST | + ATA_LFLAG_ASSUME_ATA; + } ++ } else if (vendor == 0x11ab && devid == 0x4140) { ++ /* Marvell 4140 quirks */ ++ ata_for_each_link(link, ap, EDGE) { ++ /* port 4 is for SEMB device and it doesn't like SRST */ ++ if (link->pmp == 4) ++ link->flags |= ATA_LFLAG_DISABLED; ++ } + } + } + +diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c +index ef8567d..6fecf0b 100644 +--- a/drivers/ata/libata-scsi.c ++++ b/drivers/ata/libata-scsi.c +@@ -2510,7 +2510,8 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf) + rbuf[14] = (lowest_aligned >> 8) & 0x3f; + rbuf[15] = lowest_aligned; + +- if (ata_id_has_trim(args->id)) { ++ if (ata_id_has_trim(args->id) && ++ !(dev->horkage & ATA_HORKAGE_NOTRIM)) { + rbuf[14] |= 0x80; /* TPE */ + + if (ata_id_has_zero_after_trim(args->id)) +diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c +index b603720..136803c 100644 +--- a/drivers/ata/libata-sff.c ++++ b/drivers/ata/libata-sff.c +@@ -1333,7 +1333,19 @@ void ata_sff_flush_pio_task(struct ata_port *ap) + DPRINTK("ENTER\n"); + + cancel_delayed_work_sync(&ap->sff_pio_task); ++ ++ /* ++ * We wanna reset the HSM state to IDLE. If we do so without ++ * grabbing the port lock, critical sections protected by it which ++ * expect the HSM state to stay stable may get surprised. For ++ * example, we may set IDLE in between the time ++ * __ata_sff_port_intr() checks for HSM_ST_IDLE and before it calls ++ * ata_sff_hsm_move() causing ata_sff_hsm_move() to BUG(). ++ */ ++ spin_lock_irq(ap->lock); + ap->hsm_task_state = HSM_ST_IDLE; ++ spin_unlock_irq(ap->lock); ++ + ap->sff_pio_task_link = NULL; + + if (ata_msg_ctl(ap)) +@@ -2008,13 +2020,15 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask, + + DPRINTK("ata%u: bus reset via SRST\n", ap->print_id); + +- /* software reset. causes dev0 to be selected */ +- iowrite8(ap->ctl, ioaddr->ctl_addr); +- udelay(20); /* FIXME: flush */ +- iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr); +- udelay(20); /* FIXME: flush */ +- iowrite8(ap->ctl, ioaddr->ctl_addr); +- ap->last_ctl = ap->ctl; ++ if (ap->ioaddr.ctl_addr) { ++ /* software reset. causes dev0 to be selected */ ++ iowrite8(ap->ctl, ioaddr->ctl_addr); ++ udelay(20); /* FIXME: flush */ ++ iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr); ++ udelay(20); /* FIXME: flush */ ++ iowrite8(ap->ctl, ioaddr->ctl_addr); ++ ap->last_ctl = ap->ctl; ++ } + + /* wait the port to become ready */ + return ata_sff_wait_after_reset(&ap->link, devmask, deadline); +@@ -2215,10 +2229,6 @@ void ata_sff_error_handler(struct ata_port *ap) + + spin_unlock_irqrestore(ap->lock, flags); + +- /* ignore ata_sff_softreset if ctl isn't accessible */ +- if (softreset == ata_sff_softreset && !ap->ioaddr.ctl_addr) +- softreset = NULL; +- + /* ignore built-in hardresets if SCR access is not available */ + if ((hardreset == sata_std_hardreset || + hardreset == sata_sff_hardreset) && !sata_scr_valid(&ap->link)) +diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c +index 83c4ddb..08223cc 100644 +--- a/drivers/ata/pata_octeon_cf.c ++++ b/drivers/ata/pata_octeon_cf.c +@@ -1069,7 +1069,7 @@ static struct of_device_id octeon_cf_match[] = { + }, + {}, + }; +-MODULE_DEVICE_TABLE(of, octeon_i2c_match); ++MODULE_DEVICE_TABLE(of, octeon_cf_match); + + static struct platform_driver octeon_cf_driver = { + .probe = octeon_cf_probe, +diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c +index f1f5b5a..f5640ec 100644 +--- a/drivers/ata/pata_scc.c ++++ b/drivers/ata/pata_scc.c +@@ -585,7 +585,7 @@ static int scc_wait_after_reset(struct ata_link *link, unsigned int devmask, + * Note: Original code is ata_bus_softreset(). + */ + +-static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask, ++static int scc_bus_softreset(struct ata_port *ap, unsigned int devmask, + unsigned long deadline) + { + struct ata_ioports *ioaddr = &ap->ioaddr; +@@ -599,9 +599,7 @@ static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask, + udelay(20); + out_be32(ioaddr->ctl_addr, ap->ctl); + +- scc_wait_after_reset(&ap->link, devmask, deadline); +- +- return 0; ++ return scc_wait_after_reset(&ap->link, devmask, deadline); + } + + /** +@@ -618,7 +616,8 @@ static int scc_softreset(struct ata_link *link, unsigned int *classes, + { + struct ata_port *ap = link->ap; + unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; +- unsigned int devmask = 0, err_mask; ++ unsigned int devmask = 0; ++ int rc; + u8 err; + + DPRINTK("ENTER\n"); +@@ -634,9 +633,9 @@ static int scc_softreset(struct ata_link *link, unsigned int *classes, + + /* issue bus reset */ + DPRINTK("about to softreset, devmask=%x\n", devmask); +- err_mask = scc_bus_softreset(ap, devmask, deadline); +- if (err_mask) { +- ata_port_err(ap, "SRST failed (err_mask=0x%x)\n", err_mask); ++ rc = scc_bus_softreset(ap, devmask, deadline); ++ if (rc) { ++ ata_port_err(ap, "SRST failed (err_mask=0x%x)\n", rc); + return -EIO; + } + +diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c +index e27f31f..9e79f55 100644 +--- a/drivers/ata/pata_serverworks.c ++++ b/drivers/ata/pata_serverworks.c +@@ -251,12 +251,18 @@ static void serverworks_set_dmamode(struct ata_port *ap, struct ata_device *adev + pci_write_config_byte(pdev, 0x54, ultra_cfg); + } + +-static struct scsi_host_template serverworks_sht = { ++static struct scsi_host_template serverworks_osb4_sht = { ++ ATA_BMDMA_SHT(DRV_NAME), ++ .sg_tablesize = LIBATA_DUMB_MAX_PRD, ++}; ++ ++static struct scsi_host_template serverworks_csb_sht = { + ATA_BMDMA_SHT(DRV_NAME), + }; + + static struct ata_port_operations serverworks_osb4_port_ops = { + .inherits = &ata_bmdma_port_ops, ++ .qc_prep = ata_bmdma_dumb_qc_prep, + .cable_detect = serverworks_cable_detect, + .mode_filter = serverworks_osb4_filter, + .set_piomode = serverworks_set_piomode, +@@ -265,6 +271,7 @@ static struct ata_port_operations serverworks_osb4_port_ops = { + + static struct ata_port_operations serverworks_csb_port_ops = { + .inherits = &serverworks_osb4_port_ops, ++ .qc_prep = ata_bmdma_qc_prep, + .mode_filter = serverworks_csb_filter, + }; + +@@ -404,6 +411,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id + } + }; + const struct ata_port_info *ppi[] = { &info[id->driver_data], NULL }; ++ struct scsi_host_template *sht = &serverworks_csb_sht; + int rc; + + rc = pcim_enable_device(pdev); +@@ -417,6 +425,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id + /* Select non UDMA capable OSB4 if we can't do fixups */ + if (rc < 0) + ppi[0] = &info[1]; ++ sht = &serverworks_osb4_sht; + } + /* setup CSB5/CSB6 : South Bridge and IDE option RAID */ + else if ((pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) || +@@ -433,7 +442,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id + ppi[1] = &ata_dummy_port_info; + } + +- return ata_pci_bmdma_init_one(pdev, ppi, &serverworks_sht, NULL, 0); ++ return ata_pci_bmdma_init_one(pdev, ppi, sht, NULL, 0); + } + + #ifdef CONFIG_PM +diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c +index 73510d0..113d722 100644 +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -798,7 +798,7 @@ static int dma_dwc_init(struct sata_dwc_device *hsdev, int irq) + if (err) { + dev_err(host_pvt.dwc_dev, "%s: dma_request_interrupts returns" + " %d\n", __func__, err); +- goto error_out; ++ return err; + } + + /* Enabe DMA */ +@@ -809,11 +809,6 @@ static int dma_dwc_init(struct sata_dwc_device *hsdev, int irq) + sata_dma_regs); + + return 0; +- +-error_out: +- dma_dwc_exit(hsdev); +- +- return err; + } + + static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val) +@@ -1663,7 +1658,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) + char *ver = (char *)&versionr; + u8 *base = NULL; + int err = 0; +- int irq, rc; ++ int irq; + struct ata_host *host; + struct ata_port_info pi = sata_dwc_port_info[0]; + const struct ata_port_info *ppi[] = { &pi, NULL }; +@@ -1726,7 +1721,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) + if (irq == NO_IRQ) { + dev_err(&ofdev->dev, "no SATA DMA irq\n"); + err = -ENODEV; +- goto error_out; ++ goto error_iomap; + } + + /* Get physical SATA DMA register base address */ +@@ -1735,14 +1730,16 @@ static int sata_dwc_probe(struct platform_device *ofdev) + dev_err(&ofdev->dev, "ioremap failed for AHBDMA register" + " address\n"); + err = -ENODEV; +- goto error_out; ++ goto error_iomap; + } + + /* Save dev for later use in dev_xxx() routines */ + host_pvt.dwc_dev = &ofdev->dev; + + /* Initialize AHB DMAC */ +- dma_dwc_init(hsdev, irq); ++ err = dma_dwc_init(hsdev, irq); ++ if (err) ++ goto error_dma_iomap; + + /* Enable SATA Interrupts */ + sata_dwc_enable_interrupts(hsdev); +@@ -1760,9 +1757,8 @@ static int sata_dwc_probe(struct platform_device *ofdev) + * device discovery process, invoking our port_start() handler & + * error_handler() to execute a dummy Softreset EH session + */ +- rc = ata_host_activate(host, irq, sata_dwc_isr, 0, &sata_dwc_sht); +- +- if (rc != 0) ++ err = ata_host_activate(host, irq, sata_dwc_isr, 0, &sata_dwc_sht); ++ if (err) + dev_err(&ofdev->dev, "failed to activate host"); + + dev_set_drvdata(&ofdev->dev, host); +@@ -1771,7 +1767,8 @@ static int sata_dwc_probe(struct platform_device *ofdev) + error_out: + /* Free SATA DMA resources */ + dma_dwc_exit(hsdev); +- ++error_dma_iomap: ++ iounmap((void __iomem *)host_pvt.sata_dma_regs); + error_iomap: + iounmap(base); + error_kmalloc: +@@ -1792,6 +1789,7 @@ static int sata_dwc_remove(struct platform_device *ofdev) + /* Free SATA DMA resources */ + dma_dwc_exit(hsdev); + ++ iounmap((void __iomem *)host_pvt.sata_dma_regs); + iounmap(hsdev->reg_base); + kfree(hsdev); + kfree(host); +diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c +index fb0b40a..ee2780d 100644 +--- a/drivers/ata/sata_fsl.c ++++ b/drivers/ata/sata_fsl.c +@@ -1503,7 +1503,7 @@ static int sata_fsl_probe(struct platform_device *ofdev) + host_priv->csr_base = csr_base; + + irq = irq_of_parse_and_map(ofdev->dev.of_node, 0); +- if (irq < 0) { ++ if (!irq) { + dev_err(&ofdev->dev, "invalid irq from platform\n"); + goto error_exit_with_cleanup; + } +diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c +index 2b25bd8..c1ea780 100644 +--- a/drivers/ata/sata_rcar.c ++++ b/drivers/ata/sata_rcar.c +@@ -146,6 +146,7 @@ + enum sata_rcar_type { + RCAR_GEN1_SATA, + RCAR_GEN2_SATA, ++ RCAR_R8A7790_ES1_SATA, + }; + + struct sata_rcar_priv { +@@ -763,6 +764,9 @@ static void sata_rcar_setup_port(struct ata_host *host) + ap->udma_mask = ATA_UDMA6; + ap->flags |= ATA_FLAG_SATA; + ++ if (priv->type == RCAR_R8A7790_ES1_SATA) ++ ap->flags |= ATA_FLAG_NO_DIPM; ++ + ioaddr->cmd_addr = base + SDATA_REG; + ioaddr->ctl_addr = base + SSDEVCON_REG; + ioaddr->scr_addr = base + SCRSSTS_REG; +@@ -792,6 +796,7 @@ static void sata_rcar_init_controller(struct ata_host *host) + sata_rcar_gen1_phy_init(priv); + break; + case RCAR_GEN2_SATA: ++ case RCAR_R8A7790_ES1_SATA: + sata_rcar_gen2_phy_init(priv); + break; + default: +@@ -838,6 +843,10 @@ static struct of_device_id sata_rcar_match[] = { + .data = (void *)RCAR_GEN2_SATA + }, + { ++ .compatible = "renesas,sata-r8a7790-es1", ++ .data = (void *)RCAR_R8A7790_ES1_SATA ++ }, ++ { + .compatible = "renesas,sata-r8a7791", + .data = (void *)RCAR_GEN2_SATA + }, +@@ -849,6 +858,7 @@ static const struct platform_device_id sata_rcar_id_table[] = { + { "sata_rcar", RCAR_GEN1_SATA }, /* Deprecated by "sata-r8a7779" */ + { "sata-r8a7779", RCAR_GEN1_SATA }, + { "sata-r8a7790", RCAR_GEN2_SATA }, ++ { "sata-r8a7790-es1", RCAR_R8A7790_ES1_SATA }, + { "sata-r8a7791", RCAR_GEN2_SATA }, + { }, + }; +diff --git a/drivers/auxdisplay/ks0108.c b/drivers/auxdisplay/ks0108.c +index 5b93852..0d75285 100644 +--- a/drivers/auxdisplay/ks0108.c ++++ b/drivers/auxdisplay/ks0108.c +@@ -139,6 +139,7 @@ static int __init ks0108_init(void) + + ks0108_pardevice = parport_register_device(ks0108_parport, KS0108_NAME, + NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); ++ parport_put_port(ks0108_parport); + if (ks0108_pardevice == NULL) { + printk(KERN_ERR KS0108_NAME ": ERROR: " + "parport didn't register new device\n"); +diff --git a/drivers/base/bus.c b/drivers/base/bus.c +index 83e910a..79bc203 100644 +--- a/drivers/base/bus.c ++++ b/drivers/base/bus.c +@@ -254,13 +254,15 @@ static ssize_t store_drivers_probe(struct bus_type *bus, + const char *buf, size_t count) + { + struct device *dev; ++ int err = -EINVAL; + + dev = bus_find_device_by_name(bus, NULL, buf); + if (!dev) + return -ENODEV; +- if (bus_rescan_devices_helper(dev, NULL) != 0) +- return -EINVAL; +- return count; ++ if (bus_rescan_devices_helper(dev, NULL) == 0) ++ err = count; ++ put_device(dev); ++ return err; + } + + static struct device *next_device(struct klist_iter *i) +@@ -513,11 +515,11 @@ int bus_add_device(struct device *dev) + goto out_put; + error = device_add_groups(dev, bus->dev_groups); + if (error) +- goto out_groups; ++ goto out_id; + error = sysfs_create_link(&bus->p->devices_kset->kobj, + &dev->kobj, dev_name(dev)); + if (error) +- goto out_id; ++ goto out_groups; + error = sysfs_create_link(&dev->kobj, + &dev->bus->p->subsys.kobj, "subsystem"); + if (error) +diff --git a/drivers/base/core.c b/drivers/base/core.c +index 2b56717..6a8955e 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -741,12 +741,12 @@ class_dir_create_and_add(struct class *class, struct kobject *parent_kobj) + return &dir->kobj; + } + ++static DEFINE_MUTEX(gdp_mutex); + + static struct kobject *get_device_parent(struct device *dev, + struct device *parent) + { + if (dev->class) { +- static DEFINE_MUTEX(gdp_mutex); + struct kobject *kobj = NULL; + struct kobject *parent_kobj; + struct kobject *k; +@@ -810,7 +810,9 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir) + glue_dir->kset != &dev->class->p->glue_dirs) + return; + ++ mutex_lock(&gdp_mutex); + kobject_put(glue_dir); ++ mutex_unlock(&gdp_mutex); + } + + static void cleanup_device_parent(struct device *dev) +diff --git a/drivers/base/devres.c b/drivers/base/devres.c +index 545c4de..cbe0b58 100644 +--- a/drivers/base/devres.c ++++ b/drivers/base/devres.c +@@ -297,10 +297,10 @@ void * devres_get(struct device *dev, void *new_res, + if (!dr) { + add_dr(dev, &new_dr->node); + dr = new_dr; +- new_dr = NULL; ++ new_res = NULL; + } + spin_unlock_irqrestore(&dev->devres_lock, flags); +- devres_free(new_dr); ++ devres_free(new_res); + + return dr->data; + } +diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c +index c30df50e..f0c15f9 100644 +--- a/drivers/base/firmware_class.c ++++ b/drivers/base/firmware_class.c +@@ -544,10 +544,8 @@ static void fw_dev_release(struct device *dev) + kfree(fw_priv); + } + +-static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) ++static int do_firmware_uevent(struct firmware_priv *fw_priv, struct kobj_uevent_env *env) + { +- struct firmware_priv *fw_priv = to_firmware_priv(dev); +- + if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->buf->fw_id)) + return -ENOMEM; + if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout)) +@@ -558,6 +556,18 @@ static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) + return 0; + } + ++static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) ++{ ++ struct firmware_priv *fw_priv = to_firmware_priv(dev); ++ int err = 0; ++ ++ mutex_lock(&fw_lock); ++ if (fw_priv->buf) ++ err = do_firmware_uevent(fw_priv, env); ++ mutex_unlock(&fw_lock); ++ return err; ++} ++ + static struct class firmware_class = { + .name = "firmware", + .class_attrs = firmware_class_attrs, +@@ -1081,6 +1091,9 @@ _request_firmware(const struct firmware **firmware_p, const char *name, + if (!firmware_p) + return -EINVAL; + ++ if (!name || name[0] == '\0') ++ return -EINVAL; ++ + ret = _request_firmware_prepare(&fw, name, device); + if (ret <= 0) /* error or already assigned */ + goto out; +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index 3c51eb0..57d8f67 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -89,8 +89,13 @@ int platform_get_irq(struct platform_device *dev, unsigned int num) + return dev->archdata.irqs[num]; + #else + struct resource *r; +- if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) +- return of_irq_get(dev->dev.of_node, num); ++ if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) { ++ int ret; ++ ++ ret = of_irq_get(dev->dev.of_node, num); ++ if (ret >= 0 || ret == -EPROBE_DEFER) ++ return ret; ++ } + + r = platform_get_resource(dev, IORESOURCE_IRQ, num); + +@@ -349,9 +354,7 @@ int platform_device_add(struct platform_device *pdev) + + while (--i >= 0) { + struct resource *r = &pdev->resource[i]; +- unsigned long type = resource_type(r); +- +- if (type == IORESOURCE_MEM || type == IORESOURCE_IO) ++ if (r->parent) + release_resource(r); + } + +@@ -382,9 +385,7 @@ void platform_device_del(struct platform_device *pdev) + + for (i = 0; i < pdev->num_resources; i++) { + struct resource *r = &pdev->resource[i]; +- unsigned long type = resource_type(r); +- +- if (type == IORESOURCE_MEM || type == IORESOURCE_IO) ++ if (r->parent) + release_resource(r); + } + } +diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c +index 930cad4..f3f7136 100644 +--- a/drivers/base/regmap/regcache-rbtree.c ++++ b/drivers/base/regmap/regcache-rbtree.c +@@ -302,18 +302,27 @@ static int regcache_rbtree_insert_to_block(struct regmap *map, + if (!blk) + return -ENOMEM; + +- present = krealloc(rbnode->cache_present, +- BITS_TO_LONGS(blklen) * sizeof(*present), GFP_KERNEL); +- if (!present) { +- kfree(blk); +- return -ENOMEM; ++ if (BITS_TO_LONGS(blklen) > BITS_TO_LONGS(rbnode->blklen)) { ++ present = krealloc(rbnode->cache_present, ++ BITS_TO_LONGS(blklen) * sizeof(*present), ++ GFP_KERNEL); ++ if (!present) { ++ kfree(blk); ++ return -ENOMEM; ++ } ++ ++ memset(present + BITS_TO_LONGS(rbnode->blklen), 0, ++ (BITS_TO_LONGS(blklen) - BITS_TO_LONGS(rbnode->blklen)) ++ * sizeof(*present)); ++ } else { ++ present = rbnode->cache_present; + } + + /* insert the register value in the correct place in the rbnode block */ + if (pos == 0) { + memmove(blk + offset * map->cache_word_size, + blk, rbnode->blklen * map->cache_word_size); +- bitmap_shift_right(present, present, offset, blklen); ++ bitmap_shift_left(present, present, offset, blklen); + } + + /* update the rbnode block, its size and the base register */ +diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c +index d4dd771..154e7a8 100644 +--- a/drivers/base/regmap/regcache.c ++++ b/drivers/base/regmap/regcache.c +@@ -701,7 +701,7 @@ int regcache_sync_block(struct regmap *map, void *block, + unsigned int block_base, unsigned int start, + unsigned int end) + { +- if (regmap_can_raw_write(map)) ++ if (regmap_can_raw_write(map) && !map->use_single_rw) + return regcache_sync_block_raw(map, block, cache_present, + block_base, start, end); + else +diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c +index c5471cd..d39fd61 100644 +--- a/drivers/base/regmap/regmap-debugfs.c ++++ b/drivers/base/regmap/regmap-debugfs.c +@@ -473,6 +473,7 @@ void regmap_debugfs_init(struct regmap *map, const char *name) + { + struct rb_node *next; + struct regmap_range_node *range_node; ++ const char *devname = "dummy"; + + /* If we don't have the debugfs root yet, postpone init */ + if (!regmap_debugfs_root) { +@@ -491,12 +492,15 @@ void regmap_debugfs_init(struct regmap *map, const char *name) + INIT_LIST_HEAD(&map->debugfs_off_cache); + mutex_init(&map->cache_lock); + ++ if (map->dev) ++ devname = dev_name(map->dev); ++ + if (name) { + map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s", +- dev_name(map->dev), name); ++ devname, name); + name = map->debugfs_name; + } else { +- name = dev_name(map->dev); ++ name = devname; + } + + map->debugfs = debugfs_create_dir(name, regmap_debugfs_root); +diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c +index 6a19515..58559d7 100644 +--- a/drivers/base/regmap/regmap.c ++++ b/drivers/base/regmap/regmap.c +@@ -105,7 +105,7 @@ bool regmap_readable(struct regmap *map, unsigned int reg) + + bool regmap_volatile(struct regmap *map, unsigned int reg) + { +- if (!regmap_readable(map, reg)) ++ if (!map->format.format_write && !regmap_readable(map, reg)) + return false; + + if (map->volatile_reg) +@@ -808,11 +808,10 @@ EXPORT_SYMBOL_GPL(devm_regmap_init); + static void regmap_field_init(struct regmap_field *rm_field, + struct regmap *regmap, struct reg_field reg_field) + { +- int field_bits = reg_field.msb - reg_field.lsb + 1; + rm_field->regmap = regmap; + rm_field->reg = reg_field.reg; + rm_field->shift = reg_field.lsb; +- rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb); ++ rm_field->mask = GENMASK(reg_field.msb, reg_field.lsb); + rm_field->id_size = reg_field.id_size; + rm_field->id_offset = reg_field.id_offset; + } +@@ -1308,7 +1307,7 @@ int _regmap_write(struct regmap *map, unsigned int reg, + } + + #ifdef LOG_DEVICE +- if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) ++ if (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0) + dev_info(map->dev, "%x <= %x\n", reg, val); + #endif + +@@ -1557,6 +1556,11 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, + } else { + void *wval; + ++ if (!val_count) { ++ ret = -EINVAL; ++ goto out; ++ } ++ + wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL); + if (!wval) { + ret = -ENOMEM; +@@ -1739,7 +1743,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg, + ret = map->reg_read(context, reg, val); + if (ret == 0) { + #ifdef LOG_DEVICE +- if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) ++ if (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0) + dev_info(map->dev, "%x => %x\n", reg, *val); + #endif + +@@ -1942,7 +1946,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, + &ival); + if (ret != 0) + return ret; +- memcpy(val + (i * val_bytes), &ival, val_bytes); ++ map->format.format_val(val + (i * val_bytes), ival, 0); + } + } + +diff --git a/drivers/block/drbd/drbd_interval.c b/drivers/block/drbd/drbd_interval.c +index 89c497c..04a14e0 100644 +--- a/drivers/block/drbd/drbd_interval.c ++++ b/drivers/block/drbd/drbd_interval.c +@@ -79,6 +79,7 @@ bool + drbd_insert_interval(struct rb_root *root, struct drbd_interval *this) + { + struct rb_node **new = &root->rb_node, *parent = NULL; ++ sector_t this_end = this->sector + (this->size >> 9); + + BUG_ON(!IS_ALIGNED(this->size, 512)); + +@@ -87,6 +88,8 @@ drbd_insert_interval(struct rb_root *root, struct drbd_interval *this) + rb_entry(*new, struct drbd_interval, rb); + + parent = *new; ++ if (here->end < this_end) ++ here->end = this_end; + if (this->sector < here->sector) + new = &(*new)->rb_left; + else if (this->sector > here->sector) +@@ -99,6 +102,7 @@ drbd_insert_interval(struct rb_root *root, struct drbd_interval *this) + return false; + } + ++ this->end = this_end; + rb_link_node(&this->rb, parent, new); + rb_insert_augmented(&this->rb, root, &augment_callbacks); + return true; +diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c +index c706d50..8c16c2f 100644 +--- a/drivers/block/drbd/drbd_nl.c ++++ b/drivers/block/drbd/drbd_nl.c +@@ -525,6 +525,12 @@ void conn_try_outdate_peer_async(struct drbd_tconn *tconn) + struct task_struct *opa; + + kref_get(&tconn->kref); ++ /* We may just have force_sig()'ed this thread ++ * to get it out of some blocking network function. ++ * Clear signals; otherwise kthread_run(), which internally uses ++ * wait_on_completion_killable(), will mistake our pending signal ++ * for a new fatal signal and fail. */ ++ flush_signals(current); + opa = kthread_run(_try_outdate_peer_async, tconn, "drbd_async_h"); + if (IS_ERR(opa)) { + conn_err(tconn, "out of mem, failed to invoke fence-peer helper\n"); +diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c +index 104a040..6efdbea 100644 +--- a/drivers/block/drbd/drbd_req.c ++++ b/drivers/block/drbd/drbd_req.c +@@ -1310,6 +1310,7 @@ int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct + struct request_queue * const b = + mdev->ldev->backing_bdev->bd_disk->queue; + if (b->merge_bvec_fn) { ++ bvm->bi_bdev = mdev->ldev->backing_bdev; + backing_limit = b->merge_bvec_fn(b, bvm, bvec); + limit = min(limit, backing_limit); + } +diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c +index 55298db..d180936 100644 +--- a/drivers/block/nbd.c ++++ b/drivers/block/nbd.c +@@ -814,10 +814,6 @@ static int __init nbd_init(void) + return -EINVAL; + } + +- nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL); +- if (!nbd_dev) +- return -ENOMEM; +- + part_shift = 0; + if (max_part > 0) { + part_shift = fls(max_part); +@@ -839,6 +835,10 @@ static int __init nbd_init(void) + if (nbds_max > 1UL << (MINORBITS - part_shift)) + return -EINVAL; + ++ nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL); ++ if (!nbd_dev) ++ return -ENOMEM; ++ + for (i = 0; i < nbds_max; i++) { + struct gendisk *disk = alloc_disk(1 << part_shift); + if (!disk) +diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c +index 7296c7f..b583773 100644 +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -508,6 +508,7 @@ void rbd_warn(struct rbd_device *rbd_dev, const char *fmt, ...) + # define rbd_assert(expr) ((void) 0) + #endif /* !RBD_DEBUG */ + ++static void rbd_osd_copyup_callback(struct rbd_obj_request *obj_request); + static int rbd_img_obj_request_submit(struct rbd_obj_request *obj_request); + static void rbd_img_parent_read(struct rbd_obj_request *obj_request); + static void rbd_dev_remove_parent(struct rbd_device *rbd_dev); +@@ -1651,6 +1652,16 @@ static void rbd_osd_stat_callback(struct rbd_obj_request *obj_request) + obj_request_done_set(obj_request); + } + ++static void rbd_osd_call_callback(struct rbd_obj_request *obj_request) ++{ ++ dout("%s: obj %p\n", __func__, obj_request); ++ ++ if (obj_request_img_data_test(obj_request)) ++ rbd_osd_copyup_callback(obj_request); ++ else ++ obj_request_done_set(obj_request); ++} ++ + static void rbd_osd_req_callback(struct ceph_osd_request *osd_req, + struct ceph_msg *msg) + { +@@ -1689,6 +1700,8 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req, + rbd_osd_stat_callback(obj_request); + break; + case CEPH_OSD_OP_CALL: ++ rbd_osd_call_callback(obj_request); ++ break; + case CEPH_OSD_OP_NOTIFY_ACK: + case CEPH_OSD_OP_WATCH: + rbd_osd_trivial_callback(obj_request); +@@ -1826,11 +1839,11 @@ static struct rbd_obj_request *rbd_obj_request_create(const char *object_name, + rbd_assert(obj_request_type_valid(type)); + + size = strlen(object_name) + 1; +- name = kmalloc(size, GFP_KERNEL); ++ name = kmalloc(size, GFP_NOIO); + if (!name) + return NULL; + +- obj_request = kmem_cache_zalloc(rbd_obj_request_cache, GFP_KERNEL); ++ obj_request = kmem_cache_zalloc(rbd_obj_request_cache, GFP_NOIO); + if (!obj_request) { + kfree(name); + return NULL; +@@ -1926,32 +1939,26 @@ static void rbd_dev_parent_put(struct rbd_device *rbd_dev) + * If an image has a non-zero parent overlap, get a reference to its + * parent. + * +- * We must get the reference before checking for the overlap to +- * coordinate properly with zeroing the parent overlap in +- * rbd_dev_v2_parent_info() when an image gets flattened. We +- * drop it again if there is no overlap. +- * + * Returns true if the rbd device has a parent with a non-zero + * overlap and a reference for it was successfully taken, or + * false otherwise. + */ + static bool rbd_dev_parent_get(struct rbd_device *rbd_dev) + { +- int counter; ++ int counter = 0; + + if (!rbd_dev->parent_spec) + return false; + +- counter = atomic_inc_return_safe(&rbd_dev->parent_ref); +- if (counter > 0 && rbd_dev->parent_overlap) +- return true; +- +- /* Image was flattened, but parent is not yet torn down */ ++ down_read(&rbd_dev->header_rwsem); ++ if (rbd_dev->parent_overlap) ++ counter = atomic_inc_return_safe(&rbd_dev->parent_ref); ++ up_read(&rbd_dev->header_rwsem); + + if (counter < 0) + rbd_warn(rbd_dev, "parent reference overflow\n"); + +- return false; ++ return counter > 0; + } + + /* +@@ -2090,6 +2097,11 @@ static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request) + result, xferred); + if (!img_request->result) + img_request->result = result; ++ /* ++ * Need to end I/O on the entire obj_request worth of ++ * bytes in case of error. ++ */ ++ xferred = obj_request->length; + } + + /* Image object requests don't own their page array */ +@@ -2276,13 +2288,15 @@ out_unwind: + } + + static void +-rbd_img_obj_copyup_callback(struct rbd_obj_request *obj_request) ++rbd_osd_copyup_callback(struct rbd_obj_request *obj_request) + { + struct rbd_img_request *img_request; + struct rbd_device *rbd_dev; + struct page **pages; + u32 page_count; + ++ dout("%s: obj %p\n", __func__, obj_request); ++ + rbd_assert(obj_request->type == OBJ_REQUEST_BIO); + rbd_assert(obj_request_img_data_test(obj_request)); + img_request = obj_request->img_request; +@@ -2308,9 +2322,7 @@ rbd_img_obj_copyup_callback(struct rbd_obj_request *obj_request) + if (!obj_request->result) + obj_request->xferred = obj_request->length; + +- /* Finish up with the normal image object callback */ +- +- rbd_img_obj_callback(obj_request); ++ obj_request_done_set(obj_request); + } + + static void +@@ -2407,7 +2419,6 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request) + + /* All set, send it off. */ + +- orig_request->callback = rbd_img_obj_copyup_callback; + osdc = &rbd_dev->rbd_client->client->osdc; + img_result = rbd_obj_request_submit(osdc, orig_request); + if (!img_result) +@@ -3217,7 +3228,7 @@ static int rbd_obj_read_sync(struct rbd_device *rbd_dev, + page_count = (u32) calc_pages_for(offset, length); + pages = ceph_alloc_page_vector(page_count, GFP_KERNEL); + if (IS_ERR(pages)) +- ret = PTR_ERR(pages); ++ return PTR_ERR(pages); + + ret = -ENOMEM; + obj_request = rbd_obj_request_create(object_name, offset, length, +@@ -3904,7 +3915,6 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev) + */ + if (rbd_dev->parent_overlap) { + rbd_dev->parent_overlap = 0; +- smp_mb(); + rbd_dev_parent_put(rbd_dev); + pr_info("%s: clone image has been flattened\n", + rbd_dev->disk->disk_name); +@@ -3948,7 +3958,6 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev) + * treat it specially. + */ + rbd_dev->parent_overlap = overlap; +- smp_mb(); + if (!overlap) { + + /* A null parent_spec indicates it's the initial probe */ +@@ -4764,10 +4773,7 @@ static void rbd_dev_unprobe(struct rbd_device *rbd_dev) + { + struct rbd_image_header *header; + +- /* Drop parent reference unless it's already been done (or none) */ +- +- if (rbd_dev->parent_overlap) +- rbd_dev_parent_put(rbd_dev); ++ rbd_dev_parent_put(rbd_dev); + + /* Free dynamic fields from the header, then zero it out */ + +diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c +index 5814deb..0ebadf9 100644 +--- a/drivers/block/sunvdc.c ++++ b/drivers/block/sunvdc.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -22,8 +23,8 @@ + + #define DRV_MODULE_NAME "sunvdc" + #define PFX DRV_MODULE_NAME ": " +-#define DRV_MODULE_VERSION "1.0" +-#define DRV_MODULE_RELDATE "June 25, 2007" ++#define DRV_MODULE_VERSION "1.1" ++#define DRV_MODULE_RELDATE "February 13, 2013" + + static char version[] = + DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; +@@ -32,7 +33,7 @@ MODULE_DESCRIPTION("Sun LDOM virtual disk client driver"); + MODULE_LICENSE("GPL"); + MODULE_VERSION(DRV_MODULE_VERSION); + +-#define VDC_TX_RING_SIZE 256 ++#define VDC_TX_RING_SIZE 512 + + #define WAITING_FOR_LINK_UP 0x01 + #define WAITING_FOR_TX_SPACE 0x02 +@@ -65,11 +66,9 @@ struct vdc_port { + u64 operations; + u32 vdisk_size; + u8 vdisk_type; ++ u8 vdisk_mtype; + + char disk_name[32]; +- +- struct vio_disk_geom geom; +- struct vio_disk_vtoc label; + }; + + static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio) +@@ -79,9 +78,16 @@ static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio) + + /* Ordered from largest major to lowest */ + static struct vio_version vdc_versions[] = { ++ { .major = 1, .minor = 1 }, + { .major = 1, .minor = 0 }, + }; + ++static inline int vdc_version_supported(struct vdc_port *port, ++ u16 major, u16 minor) ++{ ++ return port->vio.ver.major == major && port->vio.ver.minor >= minor; ++} ++ + #define VDCBLK_NAME "vdisk" + static int vdc_major; + #define PARTITION_SHIFT 3 +@@ -94,18 +100,54 @@ static inline u32 vdc_tx_dring_avail(struct vio_dring_state *dr) + static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo) + { + struct gendisk *disk = bdev->bd_disk; +- struct vdc_port *port = disk->private_data; ++ sector_t nsect = get_capacity(disk); ++ sector_t cylinders = nsect; + +- geo->heads = (u8) port->geom.num_hd; +- geo->sectors = (u8) port->geom.num_sec; +- geo->cylinders = port->geom.num_cyl; ++ geo->heads = 0xff; ++ geo->sectors = 0x3f; ++ sector_div(cylinders, geo->heads * geo->sectors); ++ geo->cylinders = cylinders; ++ if ((sector_t)(geo->cylinders + 1) * geo->heads * geo->sectors < nsect) ++ geo->cylinders = 0xffff; + + return 0; + } + ++/* Add ioctl/CDROM_GET_CAPABILITY to support cdrom_id in udev ++ * when vdisk_mtype is VD_MEDIA_TYPE_CD or VD_MEDIA_TYPE_DVD. ++ * Needed to be able to install inside an ldom from an iso image. ++ */ ++static int vdc_ioctl(struct block_device *bdev, fmode_t mode, ++ unsigned command, unsigned long argument) ++{ ++ int i; ++ struct gendisk *disk; ++ ++ switch (command) { ++ case CDROMMULTISESSION: ++ pr_debug(PFX "Multisession CDs not supported\n"); ++ for (i = 0; i < sizeof(struct cdrom_multisession); i++) ++ if (put_user(0, (char __user *)(argument + i))) ++ return -EFAULT; ++ return 0; ++ ++ case CDROM_GET_CAPABILITY: ++ disk = bdev->bd_disk; ++ ++ if (bdev->bd_disk && (disk->flags & GENHD_FL_CD)) ++ return 0; ++ return -EINVAL; ++ ++ default: ++ pr_debug(PFX "ioctl %08x not supported\n", command); ++ return -EINVAL; ++ } ++} ++ + static const struct block_device_operations vdc_fops = { + .owner = THIS_MODULE, + .getgeo = vdc_getgeo, ++ .ioctl = vdc_ioctl, + }; + + static void vdc_finish(struct vio_driver_state *vio, int err, int waiting_for) +@@ -165,9 +207,9 @@ static int vdc_handle_attr(struct vio_driver_state *vio, void *arg) + struct vio_disk_attr_info *pkt = arg; + + viodbg(HS, "GOT ATTR stype[0x%x] ops[%llx] disk_size[%llu] disk_type[%x] " +- "xfer_mode[0x%x] blksz[%u] max_xfer[%llu]\n", ++ "mtype[0x%x] xfer_mode[0x%x] blksz[%u] max_xfer[%llu]\n", + pkt->tag.stype, pkt->operations, +- pkt->vdisk_size, pkt->vdisk_type, ++ pkt->vdisk_size, pkt->vdisk_type, pkt->vdisk_mtype, + pkt->xfer_mode, pkt->vdisk_block_size, + pkt->max_xfer_size); + +@@ -192,8 +234,11 @@ static int vdc_handle_attr(struct vio_driver_state *vio, void *arg) + } + + port->operations = pkt->operations; +- port->vdisk_size = pkt->vdisk_size; + port->vdisk_type = pkt->vdisk_type; ++ if (vdc_version_supported(port, 1, 1)) { ++ port->vdisk_size = pkt->vdisk_size; ++ port->vdisk_mtype = pkt->vdisk_mtype; ++ } + if (pkt->max_xfer_size < port->max_xfer_size) + port->max_xfer_size = pkt->max_xfer_size; + port->vdisk_block_size = pkt->vdisk_block_size; +@@ -236,7 +281,9 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr, + + __blk_end_request(req, (desc->status ? -EIO : 0), desc->size); + +- if (blk_queue_stopped(port->disk->queue)) ++ /* restart blk queue when ring is half emptied */ ++ if (blk_queue_stopped(port->disk->queue) && ++ vdc_tx_dring_avail(dr) * 100 / VDC_TX_RING_SIZE >= 50) + blk_start_queue(port->disk->queue); + } + +@@ -388,12 +435,6 @@ static int __send_request(struct request *req) + for (i = 0; i < nsg; i++) + len += sg[i].length; + +- if (unlikely(vdc_tx_dring_avail(dr) < 1)) { +- blk_stop_queue(port->disk->queue); +- err = -ENOMEM; +- goto out; +- } +- + desc = vio_dring_cur(dr); + + err = ldc_map_sg(port->vio.lp, sg, nsg, +@@ -433,21 +474,32 @@ static int __send_request(struct request *req) + port->req_id++; + dr->prod = (dr->prod + 1) & (VDC_TX_RING_SIZE - 1); + } +-out: + + return err; + } + +-static void do_vdc_request(struct request_queue *q) ++static void do_vdc_request(struct request_queue *rq) + { +- while (1) { +- struct request *req = blk_fetch_request(q); ++ struct request *req; + +- if (!req) +- break; ++ while ((req = blk_peek_request(rq)) != NULL) { ++ struct vdc_port *port; ++ struct vio_dring_state *dr; + +- if (__send_request(req) < 0) +- __blk_end_request_all(req, -EIO); ++ port = req->rq_disk->private_data; ++ dr = &port->vio.drings[VIO_DRIVER_TX_RING]; ++ if (unlikely(vdc_tx_dring_avail(dr) < 1)) ++ goto wait; ++ ++ blk_start_request(req); ++ ++ if (__send_request(req) < 0) { ++ blk_requeue_request(rq, req); ++wait: ++ /* Avoid pointless unplugs. */ ++ blk_stop_queue(rq); ++ break; ++ } + } + } + +@@ -656,25 +708,27 @@ static int probe_disk(struct vdc_port *port) + if (comp.err) + return comp.err; + +- err = generic_request(port, VD_OP_GET_VTOC, +- &port->label, sizeof(port->label)); +- if (err < 0) { +- printk(KERN_ERR PFX "VD_OP_GET_VTOC returns error %d\n", err); +- return err; +- } +- +- err = generic_request(port, VD_OP_GET_DISKGEOM, +- &port->geom, sizeof(port->geom)); +- if (err < 0) { +- printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns " +- "error %d\n", err); +- return err; ++ if (vdc_version_supported(port, 1, 1)) { ++ /* vdisk_size should be set during the handshake, if it wasn't ++ * then the underlying disk is reserved by another system ++ */ ++ if (port->vdisk_size == -1) ++ return -ENODEV; ++ } else { ++ struct vio_disk_geom geom; ++ ++ err = generic_request(port, VD_OP_GET_DISKGEOM, ++ &geom, sizeof(geom)); ++ if (err < 0) { ++ printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns " ++ "error %d\n", err); ++ return err; ++ } ++ port->vdisk_size = ((u64)geom.num_cyl * ++ (u64)geom.num_hd * ++ (u64)geom.num_sec); + } + +- port->vdisk_size = ((u64)port->geom.num_cyl * +- (u64)port->geom.num_hd * +- (u64)port->geom.num_sec); +- + q = blk_init_queue(do_vdc_request, &port->vio.lock); + if (!q) { + printk(KERN_ERR PFX "%s: Could not allocate queue.\n", +@@ -691,6 +745,10 @@ static int probe_disk(struct vdc_port *port) + + port->disk = g; + ++ /* Each segment in a request is up to an aligned page in size. */ ++ blk_queue_segment_boundary(q, PAGE_SIZE - 1); ++ blk_queue_max_segment_size(q, PAGE_SIZE); ++ + blk_queue_max_segments(q, port->ring_cookies); + blk_queue_max_hw_sectors(q, port->max_xfer_size); + g->major = vdc_major; +@@ -704,9 +762,32 @@ static int probe_disk(struct vdc_port *port) + + set_capacity(g, port->vdisk_size); + +- printk(KERN_INFO PFX "%s: %u sectors (%u MB)\n", ++ if (vdc_version_supported(port, 1, 1)) { ++ switch (port->vdisk_mtype) { ++ case VD_MEDIA_TYPE_CD: ++ pr_info(PFX "Virtual CDROM %s\n", port->disk_name); ++ g->flags |= GENHD_FL_CD; ++ g->flags |= GENHD_FL_REMOVABLE; ++ set_disk_ro(g, 1); ++ break; ++ ++ case VD_MEDIA_TYPE_DVD: ++ pr_info(PFX "Virtual DVD %s\n", port->disk_name); ++ g->flags |= GENHD_FL_CD; ++ g->flags |= GENHD_FL_REMOVABLE; ++ set_disk_ro(g, 1); ++ break; ++ ++ case VD_MEDIA_TYPE_FIXED: ++ pr_info(PFX "Virtual Hard disk %s\n", port->disk_name); ++ break; ++ } ++ } ++ ++ pr_info(PFX "%s: %u sectors (%u MB) protocol %d.%d\n", + g->disk_name, +- port->vdisk_size, (port->vdisk_size >> (20 - 9))); ++ port->vdisk_size, (port->vdisk_size >> (20 - 9)), ++ port->vio.ver.major, port->vio.ver.minor); + + add_disk(g); + +@@ -765,6 +846,7 @@ static int vdc_port_probe(struct vio_dev *vdev, const struct vio_device_id *id) + else + snprintf(port->disk_name, sizeof(port->disk_name), + VDCBLK_NAME "%c", 'a' + ((int)vdev->dev_no % 26)); ++ port->vdisk_size = -1; + + err = vio_driver_init(&port->vio, vdev, VDEV_DISK, + vdc_versions, ARRAY_SIZE(vdc_versions), +diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c +index 64c60ed..63fc7f0 100644 +--- a/drivers/block/xen-blkback/blkback.c ++++ b/drivers/block/xen-blkback/blkback.c +@@ -763,6 +763,7 @@ again: + BUG_ON(new_map_idx >= segs_to_map); + if (unlikely(map[new_map_idx].status != 0)) { + pr_debug(DRV_PFX "invalid buffer -- could not remap it\n"); ++ put_free_pages(blkif, &pages[seg_idx]->page, 1); + pages[seg_idx]->handle = BLKBACK_INVALID_HANDLE; + ret |= 1; + goto next; +diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c +index efe1b47..e88556a 100644 +--- a/drivers/block/xen-blkfront.c ++++ b/drivers/block/xen-blkfront.c +@@ -1093,8 +1093,10 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info, + * Add the used indirect page back to the list of + * available pages for indirect grefs. + */ +- indirect_page = pfn_to_page(s->indirect_grants[i]->pfn); +- list_add(&indirect_page->lru, &info->indirect_pages); ++ if (!info->feature_persistent) { ++ indirect_page = pfn_to_page(s->indirect_grants[i]->pfn); ++ list_add(&indirect_page->lru, &info->indirect_pages); ++ } + s->indirect_grants[i]->gref = GRANT_INVALID_REF; + list_add_tail(&s->indirect_grants[i]->node, &info->grants); + } +diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c +index 51c557c..d8ddb8e 100644 +--- a/drivers/block/zram/zram_drv.c ++++ b/drivers/block/zram/zram_drv.c +@@ -447,7 +447,8 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, + } + + if (page_zero_filled(uncmem)) { +- kunmap_atomic(user_mem); ++ if (user_mem) ++ kunmap_atomic(user_mem); + /* Free memory associated with this sector now. */ + write_lock(&zram->meta->tb_lock); + zram_free_page(zram, index); +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index b11949c..8ff2b3c 100644 +--- a/drivers/bluetooth/ath3k.c ++++ b/drivers/bluetooth/ath3k.c +@@ -62,51 +62,62 @@ static const struct usb_device_id ath3k_table[] = { + { USB_DEVICE(0x0CF3, 0x3000) }, + + /* Atheros AR3011 with sflash firmware*/ ++ { USB_DEVICE(0x0489, 0xE027) }, ++ { USB_DEVICE(0x0489, 0xE03D) }, ++ { USB_DEVICE(0x04F2, 0xAFF1) }, ++ { USB_DEVICE(0x0930, 0x0215) }, + { USB_DEVICE(0x0CF3, 0x3002) }, + { USB_DEVICE(0x0CF3, 0xE019) }, + { USB_DEVICE(0x13d3, 0x3304) }, +- { USB_DEVICE(0x0930, 0x0215) }, +- { USB_DEVICE(0x0489, 0xE03D) }, +- { USB_DEVICE(0x0489, 0xE027) }, + + /* Atheros AR9285 Malbec with sflash firmware */ + { USB_DEVICE(0x03F0, 0x311D) }, + + /* Atheros AR3012 with sflash firmware*/ +- { USB_DEVICE(0x0CF3, 0x0036) }, +- { USB_DEVICE(0x0CF3, 0x3004) }, +- { USB_DEVICE(0x0CF3, 0x3008) }, +- { USB_DEVICE(0x0CF3, 0x311D) }, +- { USB_DEVICE(0x0CF3, 0x817a) }, +- { USB_DEVICE(0x13d3, 0x3375) }, ++ { USB_DEVICE(0x0489, 0xe04d) }, ++ { USB_DEVICE(0x0489, 0xe04e) }, ++ { USB_DEVICE(0x0489, 0xe057) }, ++ { USB_DEVICE(0x0489, 0xe056) }, ++ { USB_DEVICE(0x0489, 0xe05f) }, ++ { USB_DEVICE(0x0489, 0xe076) }, ++ { USB_DEVICE(0x0489, 0xe078) }, ++ { USB_DEVICE(0x04c5, 0x1330) }, + { USB_DEVICE(0x04CA, 0x3004) }, + { USB_DEVICE(0x04CA, 0x3005) }, + { USB_DEVICE(0x04CA, 0x3006) }, + { USB_DEVICE(0x04CA, 0x3007) }, + { USB_DEVICE(0x04CA, 0x3008) }, + { USB_DEVICE(0x04CA, 0x300b) }, +- { USB_DEVICE(0x13d3, 0x3362) }, +- { USB_DEVICE(0x0CF3, 0xE004) }, +- { USB_DEVICE(0x0CF3, 0xE005) }, ++ { USB_DEVICE(0x04CA, 0x3010) }, + { USB_DEVICE(0x0930, 0x0219) }, + { USB_DEVICE(0x0930, 0x0220) }, +- { USB_DEVICE(0x0489, 0xe057) }, +- { USB_DEVICE(0x13d3, 0x3393) }, +- { USB_DEVICE(0x0489, 0xe04e) }, +- { USB_DEVICE(0x0489, 0xe056) }, +- { USB_DEVICE(0x0489, 0xe04d) }, +- { USB_DEVICE(0x04c5, 0x1330) }, +- { USB_DEVICE(0x13d3, 0x3402) }, ++ { USB_DEVICE(0x0930, 0x0227) }, ++ { USB_DEVICE(0x0b05, 0x17d0) }, ++ { USB_DEVICE(0x0CF3, 0x0036) }, ++ { USB_DEVICE(0x0CF3, 0x3004) }, ++ { USB_DEVICE(0x0CF3, 0x3008) }, ++ { USB_DEVICE(0x0CF3, 0x311D) }, ++ { USB_DEVICE(0x0CF3, 0x311E) }, ++ { USB_DEVICE(0x0CF3, 0x311F) }, + { USB_DEVICE(0x0cf3, 0x3121) }, ++ { USB_DEVICE(0x0CF3, 0x817a) }, + { USB_DEVICE(0x0cf3, 0xe003) }, +- { USB_DEVICE(0x0489, 0xe05f) }, ++ { USB_DEVICE(0x0CF3, 0xE004) }, ++ { USB_DEVICE(0x0CF3, 0xE005) }, ++ { USB_DEVICE(0x13d3, 0x3362) }, ++ { USB_DEVICE(0x13d3, 0x3375) }, ++ { USB_DEVICE(0x13d3, 0x3393) }, ++ { USB_DEVICE(0x13d3, 0x3402) }, ++ { USB_DEVICE(0x13d3, 0x3408) }, ++ { USB_DEVICE(0x13d3, 0x3432) }, ++ { USB_DEVICE(0x13d3, 0x3474) }, + + /* Atheros AR5BBU12 with sflash firmware */ + { USB_DEVICE(0x0489, 0xE02C) }, + + /* Atheros AR5BBU22 with sflash firmware */ +- { USB_DEVICE(0x0489, 0xE03C) }, + { USB_DEVICE(0x0489, 0xE036) }, ++ { USB_DEVICE(0x0489, 0xE03C) }, + + { } /* Terminating entry */ + }; +@@ -119,37 +130,47 @@ MODULE_DEVICE_TABLE(usb, ath3k_table); + static const struct usb_device_id ath3k_blist_tbl[] = { + + /* Atheros AR3012 with sflash firmware*/ +- { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x311F), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 }, + + /* Atheros AR5BBU22 with sflash firmware */ +- { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, + + { } /* Terminating entry */ + }; +@@ -157,6 +178,8 @@ static const struct usb_device_id ath3k_blist_tbl[] = { + #define USB_REQ_DFU_DNLOAD 1 + #define BULK_SIZE 4096 + #define FW_HDR_SIZE 20 ++#define TIMEGAP_USEC_MIN 50 ++#define TIMEGAP_USEC_MAX 100 + + static int ath3k_load_firmware(struct usb_device *udev, + const struct firmware *firmware) +@@ -187,6 +210,9 @@ static int ath3k_load_firmware(struct usb_device *udev, + count -= 20; + + while (count) { ++ /* workaround the compatibility issue with xHCI controller*/ ++ usleep_range(TIMEGAP_USEC_MIN, TIMEGAP_USEC_MAX); ++ + size = min_t(uint, count, BULK_SIZE); + pipe = usb_sndbulkpipe(udev, 0x02); + memcpy(send_buf, firmware->data + sent, size); +@@ -283,6 +309,9 @@ static int ath3k_load_fwfile(struct usb_device *udev, + count -= size; + + while (count) { ++ /* workaround the compatibility issue with xHCI controller*/ ++ usleep_range(TIMEGAP_USEC_MIN, TIMEGAP_USEC_MAX); ++ + size = min_t(uint, count, BULK_SIZE); + pipe = usb_sndbulkpipe(udev, 0x02); + +diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h +index 7399303..9e81a3d0 100644 +--- a/drivers/bluetooth/btmrvl_drv.h ++++ b/drivers/bluetooth/btmrvl_drv.h +@@ -66,6 +66,7 @@ struct btmrvl_adapter { + u8 hs_state; + u8 wakeup_tries; + wait_queue_head_t cmd_wait_q; ++ wait_queue_head_t event_hs_wait_q; + u8 cmd_complete; + bool is_suspended; + }; +diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c +index 1e0320a..49d2098 100644 +--- a/drivers/bluetooth/btmrvl_main.c ++++ b/drivers/bluetooth/btmrvl_main.c +@@ -112,6 +112,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) + adapter->hs_state = HS_ACTIVATED; + if (adapter->psmode) + adapter->ps_state = PS_SLEEP; ++ wake_up_interruptible(&adapter->event_hs_wait_q); + BT_DBG("HS ACTIVATED!"); + } else { + BT_DBG("HS Enable failed"); +@@ -251,11 +252,31 @@ EXPORT_SYMBOL_GPL(btmrvl_enable_ps); + + int btmrvl_enable_hs(struct btmrvl_private *priv) + { ++ struct btmrvl_adapter *adapter = priv->adapter; + int ret; + + ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0); +- if (ret) ++ if (ret) { + BT_ERR("Host sleep enable command failed\n"); ++ return ret; ++ } ++ ++ ret = wait_event_interruptible_timeout(adapter->event_hs_wait_q, ++ adapter->hs_state, ++ msecs_to_jiffies(WAIT_UNTIL_HS_STATE_CHANGED)); ++ if (ret < 0) { ++ BT_ERR("event_hs_wait_q terminated (%d): %d,%d,%d", ++ ret, adapter->hs_state, adapter->ps_state, ++ adapter->wakeup_tries); ++ } else if (!ret) { ++ BT_ERR("hs_enable timeout: %d,%d,%d", adapter->hs_state, ++ adapter->ps_state, adapter->wakeup_tries); ++ ret = -ETIMEDOUT; ++ } else { ++ BT_DBG("host sleep enabled: %d,%d,%d", adapter->hs_state, ++ adapter->ps_state, adapter->wakeup_tries); ++ ret = 0; ++ } + + return ret; + } +@@ -341,6 +362,7 @@ static void btmrvl_init_adapter(struct btmrvl_private *priv) + priv->adapter->ps_state = PS_AWAKE; + + init_waitqueue_head(&priv->adapter->cmd_wait_q); ++ init_waitqueue_head(&priv->adapter->event_hs_wait_q); + } + + static void btmrvl_free_adapter(struct btmrvl_private *priv) +@@ -648,6 +670,7 @@ int btmrvl_remove_card(struct btmrvl_private *priv) + hdev = priv->btmrvl_dev.hcidev; + + wake_up_interruptible(&priv->adapter->cmd_wait_q); ++ wake_up_interruptible(&priv->adapter->event_hs_wait_q); + + kthread_stop(priv->main_thread.task); + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 1c7b504..c23658e 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -49,6 +49,7 @@ static struct usb_driver btusb_driver; + #define BTUSB_WRONG_SCO_MTU 0x40 + #define BTUSB_ATH3012 0x80 + #define BTUSB_INTEL 0x100 ++#define BTUSB_INTEL_BOOT 0x200 + + static const struct usb_device_id btusb_table[] = { + /* Generic Bluetooth USB device */ +@@ -101,21 +102,31 @@ static const struct usb_device_id btusb_table[] = { + { USB_DEVICE(0x0c10, 0x0000) }, + + /* Broadcom BCM20702A0 */ ++ { USB_DEVICE(0x0489, 0xe042) }, ++ { USB_DEVICE(0x04ca, 0x2003) }, + { USB_DEVICE(0x0b05, 0x17b5) }, + { USB_DEVICE(0x0b05, 0x17cb) }, +- { USB_DEVICE(0x04ca, 0x2003) }, +- { USB_DEVICE(0x0489, 0xe042) }, + { USB_DEVICE(0x413c, 0x8197) }, + + /* Foxconn - Hon Hai */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) }, + +- /*Broadcom devices with vendor specific id */ ++ /* Broadcom devices with vendor specific id */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) }, + ++ /* ASUSTek Computer - Broadcom based */ ++ { USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01) }, ++ + /* Belkin F8065bf - Broadcom based */ + { USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) }, + ++ /* IMC Networks - Broadcom based */ ++ { USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) }, ++ ++ /* Intel Bluetooth USB Bootloader (RAM module) */ ++ { USB_DEVICE(0x8087, 0x0a5a), ++ .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC }, ++ + { } /* Terminating entry */ + }; + +@@ -129,56 +140,67 @@ static const struct usb_device_id blacklist_table[] = { + { USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE }, + + /* Atheros 3011 with sflash firmware */ ++ { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE }, ++ { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE }, ++ { USB_DEVICE(0x04f2, 0xaff1), .driver_info = BTUSB_IGNORE }, ++ { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE }, +- { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE }, +- { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE }, +- { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE }, + + /* Atheros AR9285 Malbec with sflash firmware */ + { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, + + /* Atheros 3012 with sflash firmware */ +- { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, +- { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 }, + + /* Atheros AR5BBU12 with sflash firmware */ + { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, + + /* Atheros AR5BBU12 with sflash firmware */ +- { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 }, ++ { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, + + /* Broadcom BCM2035 */ +- { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, +- { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, + { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 }, ++ { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, ++ { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, + + /* Broadcom BCM2045 */ + { USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU }, +@@ -309,6 +331,9 @@ static void btusb_intr_complete(struct urb *urb) + BT_ERR("%s corrupted event packet", hdev->name); + hdev->stat.err_rx++; + } ++ } else if (urb->status == -ENOENT) { ++ /* Avoid suspend failed when usb_kill_urb */ ++ return; + } + + if (!test_bit(BTUSB_INTR_RUNNING, &data->flags)) +@@ -397,6 +422,9 @@ static void btusb_bulk_complete(struct urb *urb) + BT_ERR("%s corrupted ACL packet", hdev->name); + hdev->stat.err_rx++; + } ++ } else if (urb->status == -ENOENT) { ++ /* Avoid suspend failed when usb_kill_urb */ ++ return; + } + + if (!test_bit(BTUSB_BULK_RUNNING, &data->flags)) +@@ -491,6 +519,9 @@ static void btusb_isoc_complete(struct urb *urb) + hdev->stat.err_rx++; + } + } ++ } else if (urb->status == -ENOENT) { ++ /* Avoid suspend failed when usb_kill_urb */ ++ return; + } + + if (!test_bit(BTUSB_ISOC_RUNNING, &data->flags)) +@@ -1262,6 +1293,8 @@ static int btusb_setup_intel(struct hci_dev *hdev) + } + fw_ptr = fw->data; + ++ kfree_skb(skb); ++ + /* This Intel specific command enables the manufacturer mode of the + * controller. + * +@@ -1482,6 +1515,9 @@ static int btusb_probe(struct usb_interface *intf, + if (id->driver_info & BTUSB_INTEL) + hdev->setup = btusb_setup_intel; + ++ if (id->driver_info & BTUSB_INTEL_BOOT) ++ set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); ++ + /* Interface numbers are hardcoded in the specification */ + data->isoc = usb_ifnum_to_if(data->udev, 1); + +diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c +index e36a024..5651992 100644 +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -237,7 +237,7 @@ static void h5_pkt_cull(struct h5 *h5) + break; + + to_remove--; +- seq = (seq - 1) % 8; ++ seq = (seq - 1) & 0x07; + } + + if (seq != h5->rx_ack) +diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c +index 372ae72..1aa0130 100644 +--- a/drivers/bus/mvebu-mbus.c ++++ b/drivers/bus/mvebu-mbus.c +@@ -181,12 +181,25 @@ static void mvebu_mbus_disable_window(struct mvebu_mbus_state *mbus, + } + + /* Checks whether the given window number is available */ ++ ++/* On Armada XP, 375 and 38x the MBus window 13 has the remap ++ * capability, like windows 0 to 7. However, the mvebu-mbus driver ++ * isn't currently taking into account this special case, which means ++ * that when window 13 is actually used, the remap registers are left ++ * to 0, making the device using this MBus window unavailable. The ++ * quick fix for stable is to not use window 13. A follow up patch ++ * will correctly handle this window. ++*/ + static int mvebu_mbus_window_is_free(struct mvebu_mbus_state *mbus, + const int win) + { + void __iomem *addr = mbus->mbuswins_base + + mbus->soc->win_cfg_offset(win); + u32 ctrl = readl(addr + WIN_CTRL_OFF); ++ ++ if (win == 13) ++ return false; ++ + return !(ctrl & WIN_CTRL_ENABLE); + } + +@@ -688,7 +701,6 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus, + phys_addr_t sdramwins_phys_base, + size_t sdramwins_size) + { +- struct device_node *np; + int win; + + mbus->mbuswins_base = ioremap(mbuswins_phys_base, mbuswins_size); +@@ -701,12 +713,6 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus, + return -ENOMEM; + } + +- np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"); +- if (np) { +- mbus->hw_io_coherency = 1; +- of_node_put(np); +- } +- + for (win = 0; win < mbus->soc->num_wins; win++) + mvebu_mbus_disable_window(mbus, win); + +@@ -876,7 +882,7 @@ static void __init mvebu_mbus_get_pcie_resources(struct device_node *np, + } + } + +-int __init mvebu_mbus_dt_init(void) ++int __init mvebu_mbus_dt_init(bool is_coherent) + { + struct resource mbuswins_res, sdramwins_res; + struct device_node *np, *controller; +@@ -915,6 +921,8 @@ int __init mvebu_mbus_dt_init(void) + return -EINVAL; + } + ++ mbus_state.hw_io_coherency = is_coherent; ++ + /* Get optional pcie-{mem,io}-aperture properties */ + mvebu_mbus_get_pcie_resources(np, &mbus_state.pcie_mem_aperture, + &mbus_state.pcie_io_aperture); +diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c +index 5c85350..19e301f 100644 +--- a/drivers/char/agp/intel-gtt.c ++++ b/drivers/char/agp/intel-gtt.c +@@ -586,7 +586,7 @@ static inline int needs_ilk_vtd_wa(void) + /* Query intel_iommu to see if we need the workaround. Presumably that + * was loaded first. + */ +- if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || ++ if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG || + gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) && + intel_iommu_gfx_mapped) + return 1; +diff --git a/drivers/char/hw_random/pseries-rng.c b/drivers/char/hw_random/pseries-rng.c +index ab7ffde..f38f2c1 100644 +--- a/drivers/char/hw_random/pseries-rng.c ++++ b/drivers/char/hw_random/pseries-rng.c +@@ -25,18 +25,21 @@ + #include + + +-static int pseries_rng_data_read(struct hwrng *rng, u32 *data) ++static int pseries_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) + { ++ u64 buffer[PLPAR_HCALL_BUFSIZE]; ++ size_t size = max < 8 ? max : 8; + int rc; + +- rc = plpar_hcall(H_RANDOM, (unsigned long *)data); ++ rc = plpar_hcall(H_RANDOM, (unsigned long *)buffer); + if (rc != H_SUCCESS) { + pr_err_ratelimited("H_RANDOM call failed %d\n", rc); + return -EIO; + } ++ memcpy(data, buffer, size); + + /* The hypervisor interface returns 64 bits */ +- return 8; ++ return size; + } + + /** +@@ -55,7 +58,7 @@ static unsigned long pseries_rng_get_desired_dma(struct vio_dev *vdev) + + static struct hwrng pseries_rng = { + .name = KBUILD_MODNAME, +- .data_read = pseries_rng_data_read, ++ .read = pseries_rng_read, + }; + + static int __init pseries_rng_probe(struct vio_dev *dev, +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 429b75b..8a64dbe 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -1063,8 +1063,8 @@ static void extract_buf(struct entropy_store *r, __u8 *out) + * pool while mixing, and hash one final time. + */ + sha_transform(hash.w, extract, workspace); +- memset(extract, 0, sizeof(extract)); +- memset(workspace, 0, sizeof(workspace)); ++ memzero_explicit(extract, sizeof(extract)); ++ memzero_explicit(workspace, sizeof(workspace)); + + /* + * In case the hash function has some recognizable output +@@ -1076,7 +1076,7 @@ static void extract_buf(struct entropy_store *r, __u8 *out) + hash.w[2] ^= rol32(hash.w[2], 16); + + memcpy(out, &hash, EXTRACT_SIZE); +- memset(&hash, 0, sizeof(hash)); ++ memzero_explicit(&hash, sizeof(hash)); + } + + static ssize_t extract_entropy(struct entropy_store *r, void *buf, +@@ -1124,7 +1124,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, + } + + /* Wipe data just returned from memory */ +- memset(tmp, 0, sizeof(tmp)); ++ memzero_explicit(tmp, sizeof(tmp)); + + return ret; + } +@@ -1162,7 +1162,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, + } + + /* Wipe data just returned from memory */ +- memset(tmp, 0, sizeof(tmp)); ++ memzero_explicit(tmp, sizeof(tmp)); + + return ret; + } +diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c +index 62e10fd..cfb9089 100644 +--- a/drivers/char/tpm/tpm-interface.c ++++ b/drivers/char/tpm/tpm-interface.c +@@ -491,11 +491,10 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type) + int tpm_get_timeouts(struct tpm_chip *chip) + { + struct tpm_cmd_t tpm_cmd; +- struct timeout_t *timeout_cap; ++ unsigned long new_timeout[4]; ++ unsigned long old_timeout[4]; + struct duration_t *duration_cap; + ssize_t rc; +- u32 timeout; +- unsigned int scale = 1; + + tpm_cmd.header.in = tpm_getcap_header; + tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; +@@ -529,25 +528,46 @@ int tpm_get_timeouts(struct tpm_chip *chip) + != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) + return -EINVAL; + +- timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; +- /* Don't overwrite default if value is 0 */ +- timeout = be32_to_cpu(timeout_cap->a); +- if (timeout && timeout < 1000) { +- /* timeouts in msec rather usec */ +- scale = 1000; +- chip->vendor.timeout_adjusted = true; ++ old_timeout[0] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.a); ++ old_timeout[1] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.b); ++ old_timeout[2] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.c); ++ old_timeout[3] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.d); ++ memcpy(new_timeout, old_timeout, sizeof(new_timeout)); ++ ++ /* ++ * Provide ability for vendor overrides of timeout values in case ++ * of misreporting. ++ */ ++ if (chip->ops->update_timeouts != NULL) ++ chip->vendor.timeout_adjusted = ++ chip->ops->update_timeouts(chip, new_timeout); ++ ++ if (!chip->vendor.timeout_adjusted) { ++ /* Don't overwrite default if value is 0 */ ++ if (new_timeout[0] != 0 && new_timeout[0] < 1000) { ++ int i; ++ ++ /* timeouts in msec rather usec */ ++ for (i = 0; i != ARRAY_SIZE(new_timeout); i++) ++ new_timeout[i] *= 1000; ++ chip->vendor.timeout_adjusted = true; ++ } ++ } ++ ++ /* Report adjusted timeouts */ ++ if (chip->vendor.timeout_adjusted) { ++ dev_info(chip->dev, ++ HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n", ++ old_timeout[0], new_timeout[0], ++ old_timeout[1], new_timeout[1], ++ old_timeout[2], new_timeout[2], ++ old_timeout[3], new_timeout[3]); + } +- if (timeout) +- chip->vendor.timeout_a = usecs_to_jiffies(timeout * scale); +- timeout = be32_to_cpu(timeout_cap->b); +- if (timeout) +- chip->vendor.timeout_b = usecs_to_jiffies(timeout * scale); +- timeout = be32_to_cpu(timeout_cap->c); +- if (timeout) +- chip->vendor.timeout_c = usecs_to_jiffies(timeout * scale); +- timeout = be32_to_cpu(timeout_cap->d); +- if (timeout) +- chip->vendor.timeout_d = usecs_to_jiffies(timeout * scale); ++ ++ chip->vendor.timeout_a = usecs_to_jiffies(new_timeout[0]); ++ chip->vendor.timeout_b = usecs_to_jiffies(new_timeout[1]); ++ chip->vendor.timeout_c = usecs_to_jiffies(new_timeout[2]); ++ chip->vendor.timeout_d = usecs_to_jiffies(new_timeout[3]); + + duration: + tpm_cmd.header.in = tpm_getcap_header; +@@ -991,13 +1011,13 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) + int err, total = 0, retries = 5; + u8 *dest = out; + ++ if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) ++ return -EINVAL; ++ + chip = tpm_chip_find_get(chip_num); + if (chip == NULL) + return -ENODEV; + +- if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) +- return -EINVAL; +- + do { + tpm_cmd.header.in = tpm_getrandom_header; + tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); +@@ -1016,6 +1036,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) + num_bytes -= recd; + } while (retries-- && total < max); + ++ tpm_chip_put(chip); + return total ? total : -EIO; + } + EXPORT_SYMBOL_GPL(tpm_get_random); +@@ -1095,17 +1116,19 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, + goto del_misc; + + if (tpm_add_ppi(&dev->kobj)) +- goto del_misc; ++ goto del_sysfs; + + chip->bios_dir = tpm_bios_log_setup(chip->devname); + + /* Make chip available */ + spin_lock(&driver_lock); +- list_add_rcu(&chip->list, &tpm_chip_list); ++ list_add_tail_rcu(&chip->list, &tpm_chip_list); + spin_unlock(&driver_lock); + + return chip; + ++del_sysfs: ++ tpm_sysfs_del_device(chip); + del_misc: + tpm_dev_del_device(chip); + put_device: +diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c +index 7727292..503a85a 100644 +--- a/drivers/char/tpm/tpm_i2c_atmel.c ++++ b/drivers/char/tpm/tpm_i2c_atmel.c +@@ -168,6 +168,10 @@ static int i2c_atmel_probe(struct i2c_client *client, + + chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), + GFP_KERNEL); ++ if (!chip->vendor.priv) { ++ rc = -ENOMEM; ++ goto out_err; ++ } + + /* Default timeouts */ + chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); +diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c +index 7b158ef..23c7b13 100644 +--- a/drivers/char/tpm/tpm_i2c_nuvoton.c ++++ b/drivers/char/tpm/tpm_i2c_nuvoton.c +@@ -538,6 +538,11 @@ static int i2c_nuvoton_probe(struct i2c_client *client, + + chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), + GFP_KERNEL); ++ if (!chip->vendor.priv) { ++ rc = -ENOMEM; ++ goto out_err; ++ } ++ + init_waitqueue_head(&chip->vendor.read_queue); + init_waitqueue_head(&chip->vendor.int_queue); + +diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c +index 5b0dd8e..576d111 100644 +--- a/drivers/char/tpm/tpm_i2c_stm_st33.c ++++ b/drivers/char/tpm/tpm_i2c_stm_st33.c +@@ -488,7 +488,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf, + if (burstcnt < 0) + return burstcnt; + size = min_t(int, len - i - 1, burstcnt); +- ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf, size); ++ ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf + i, size); + if (ret < 0) + goto out_err; + +@@ -715,6 +715,7 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) + } + + tpm_get_timeouts(chip); ++ tpm_do_selftest(chip); + + dev_info(chip->dev, "TPM I2C Initialized\n"); + return 0; +diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c +index af74c57..643bba7 100644 +--- a/drivers/char/tpm/tpm_ibmvtpm.c ++++ b/drivers/char/tpm/tpm_ibmvtpm.c +@@ -124,7 +124,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) + { + struct ibmvtpm_dev *ibmvtpm; + struct ibmvtpm_crq crq; +- u64 *word = (u64 *) &crq; ++ __be64 *word = (__be64 *)&crq; + int rc; + + ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip); +@@ -145,10 +145,11 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) + memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count); + crq.valid = (u8)IBMVTPM_VALID_CMD; + crq.msg = (u8)VTPM_TPM_COMMAND; +- crq.len = (u16)count; +- crq.data = ibmvtpm->rtce_dma_handle; ++ crq.len = cpu_to_be16(count); ++ crq.data = cpu_to_be32(ibmvtpm->rtce_dma_handle); + +- rc = ibmvtpm_send_crq(ibmvtpm->vdev, word[0], word[1]); ++ rc = ibmvtpm_send_crq(ibmvtpm->vdev, be64_to_cpu(word[0]), ++ be64_to_cpu(word[1])); + if (rc != H_SUCCESS) { + dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc); + rc = 0; +@@ -186,7 +187,8 @@ static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm) + crq.valid = (u8)IBMVTPM_VALID_CMD; + crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE; + +- rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); ++ rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]), ++ cpu_to_be64(buf[1])); + if (rc != H_SUCCESS) + dev_err(ibmvtpm->dev, + "ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc); +@@ -212,7 +214,8 @@ static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm) + crq.valid = (u8)IBMVTPM_VALID_CMD; + crq.msg = (u8)VTPM_GET_VERSION; + +- rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); ++ rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]), ++ cpu_to_be64(buf[1])); + if (rc != H_SUCCESS) + dev_err(ibmvtpm->dev, + "ibmvtpm_crq_get_version failed rc=%d\n", rc); +@@ -307,6 +310,14 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev) + static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev) + { + struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev); ++ ++ /* ibmvtpm initializes at probe time, so the data we are ++ * asking for may not be set yet. Estimate that 4K required ++ * for TCE-mapped buffer in addition to CRQ. ++ */ ++ if (!ibmvtpm) ++ return CRQ_RES_BUF_SIZE + PAGE_SIZE; ++ + return CRQ_RES_BUF_SIZE + ibmvtpm->rtce_size; + } + +@@ -327,7 +338,8 @@ static int tpm_ibmvtpm_suspend(struct device *dev) + crq.valid = (u8)IBMVTPM_VALID_CMD; + crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND; + +- rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); ++ rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]), ++ cpu_to_be64(buf[1])); + if (rc != H_SUCCESS) + dev_err(ibmvtpm->dev, + "tpm_ibmvtpm_suspend failed rc=%d\n", rc); +@@ -472,11 +484,11 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, + case IBMVTPM_VALID_CMD: + switch (crq->msg) { + case VTPM_GET_RTCE_BUFFER_SIZE_RES: +- if (crq->len <= 0) { ++ if (be16_to_cpu(crq->len) <= 0) { + dev_err(ibmvtpm->dev, "Invalid rtce size\n"); + return; + } +- ibmvtpm->rtce_size = crq->len; ++ ibmvtpm->rtce_size = be16_to_cpu(crq->len); + ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size, + GFP_KERNEL); + if (!ibmvtpm->rtce_buf) { +@@ -497,11 +509,11 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, + + return; + case VTPM_GET_VERSION_RES: +- ibmvtpm->vtpm_version = crq->data; ++ ibmvtpm->vtpm_version = be32_to_cpu(crq->data); + return; + case VTPM_TPM_COMMAND_RES: + /* len of the data in rtce buffer */ +- ibmvtpm->res_len = crq->len; ++ ibmvtpm->res_len = be16_to_cpu(crq->len); + wake_up_interruptible(&ibmvtpm->wq); + return; + default: +@@ -567,6 +579,9 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, + goto cleanup; + } + ++ ibmvtpm->dev = dev; ++ ibmvtpm->vdev = vio_dev; ++ + crq_q = &ibmvtpm->crq_queue; + crq_q->crq_addr = (struct ibmvtpm_crq *)get_zeroed_page(GFP_KERNEL); + if (!crq_q->crq_addr) { +@@ -611,8 +626,6 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, + + crq_q->index = 0; + +- ibmvtpm->dev = dev; +- ibmvtpm->vdev = vio_dev; + TPM_VPRIV(chip) = (void *)ibmvtpm; + + spin_lock_init(&ibmvtpm->rtce_lock); +diff --git a/drivers/char/tpm/tpm_ibmvtpm.h b/drivers/char/tpm/tpm_ibmvtpm.h +index bd82a79..b2c231b 100644 +--- a/drivers/char/tpm/tpm_ibmvtpm.h ++++ b/drivers/char/tpm/tpm_ibmvtpm.h +@@ -22,9 +22,9 @@ + struct ibmvtpm_crq { + u8 valid; + u8 msg; +- u16 len; +- u32 data; +- u64 reserved; ++ __be16 len; ++ __be32 data; ++ __be64 reserved; + } __attribute__((packed, aligned(8))); + + struct ibmvtpm_crq_queue { +diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c +index a9ed227..51350cd 100644 +--- a/drivers/char/tpm/tpm_tis.c ++++ b/drivers/char/tpm/tpm_tis.c +@@ -75,6 +75,10 @@ enum tis_defaults { + #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) + #define TPM_RID(l) (0x0F04 | ((l) << 12)) + ++struct priv_data { ++ bool irq_tested; ++}; ++ + static LIST_HEAD(tis_chips); + static DEFINE_MUTEX(tis_lock); + +@@ -338,12 +342,27 @@ out_err: + return rc; + } + ++static void disable_interrupts(struct tpm_chip *chip) ++{ ++ u32 intmask; ++ ++ intmask = ++ ioread32(chip->vendor.iobase + ++ TPM_INT_ENABLE(chip->vendor.locality)); ++ intmask &= ~TPM_GLOBAL_INT_ENABLE; ++ iowrite32(intmask, ++ chip->vendor.iobase + ++ TPM_INT_ENABLE(chip->vendor.locality)); ++ free_irq(chip->vendor.irq, chip); ++ chip->vendor.irq = 0; ++} ++ + /* + * If interrupts are used (signaled by an irq set in the vendor structure) + * tpm.c can skip polling for the data to be available as the interrupt is + * waited for here + */ +-static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) ++static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) + { + int rc; + u32 ordinal; +@@ -373,6 +392,60 @@ out_err: + return rc; + } + ++static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) ++{ ++ int rc, irq; ++ struct priv_data *priv = chip->vendor.priv; ++ ++ if (!chip->vendor.irq || priv->irq_tested) ++ return tpm_tis_send_main(chip, buf, len); ++ ++ /* Verify receipt of the expected IRQ */ ++ irq = chip->vendor.irq; ++ chip->vendor.irq = 0; ++ rc = tpm_tis_send_main(chip, buf, len); ++ chip->vendor.irq = irq; ++ if (!priv->irq_tested) ++ msleep(1); ++ if (!priv->irq_tested) { ++ disable_interrupts(chip); ++ dev_err(chip->dev, ++ FW_BUG "TPM interrupt not working, polling instead\n"); ++ } ++ priv->irq_tested = true; ++ return rc; ++} ++ ++struct tis_vendor_timeout_override { ++ u32 did_vid; ++ unsigned long timeout_us[4]; ++}; ++ ++static const struct tis_vendor_timeout_override vendor_timeout_overrides[] = { ++ /* Atmel 3204 */ ++ { 0x32041114, { (TIS_SHORT_TIMEOUT*1000), (TIS_LONG_TIMEOUT*1000), ++ (TIS_SHORT_TIMEOUT*1000), (TIS_SHORT_TIMEOUT*1000) } }, ++}; ++ ++static bool tpm_tis_update_timeouts(struct tpm_chip *chip, ++ unsigned long *timeout_cap) ++{ ++ int i; ++ u32 did_vid; ++ ++ did_vid = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); ++ ++ for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) { ++ if (vendor_timeout_overrides[i].did_vid != did_vid) ++ continue; ++ memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us, ++ sizeof(vendor_timeout_overrides[i].timeout_us)); ++ return true; ++ } ++ ++ return false; ++} ++ + /* + * Early probing for iTPM with STS_DATA_EXPECT flaw. + * Try sending command without itpm flag set and if that +@@ -437,6 +510,7 @@ static const struct tpm_class_ops tpm_tis = { + .recv = tpm_tis_recv, + .send = tpm_tis_send, + .cancel = tpm_tis_ready, ++ .update_timeouts = tpm_tis_update_timeouts, + .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, + .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, + .req_canceled = tpm_tis_req_canceled, +@@ -474,6 +548,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id) + if (interrupt == 0) + return IRQ_NONE; + ++ ((struct priv_data *)chip->vendor.priv)->irq_tested = true; + if (interrupt & TPM_INTF_DATA_AVAIL_INT) + wake_up_interruptible(&chip->vendor.read_queue); + if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) +@@ -503,9 +578,14 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, + u32 vendor, intfcaps, intmask; + int rc, i, irq_s, irq_e, probe; + struct tpm_chip *chip; ++ struct priv_data *priv; + ++ priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL); ++ if (priv == NULL) ++ return -ENOMEM; + if (!(chip = tpm_register_hardware(dev, &tpm_tis))) + return -ENODEV; ++ chip->vendor.priv = priv; + + chip->vendor.iobase = ioremap(start, len); + if (!chip->vendor.iobase) { +@@ -574,19 +654,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, + if (intfcaps & TPM_INTF_DATA_AVAIL_INT) + dev_dbg(dev, "\tData Avail Int Support\n"); + +- /* get the timeouts before testing for irqs */ +- if (tpm_get_timeouts(chip)) { +- dev_err(dev, "Could not get TPM timeouts and durations\n"); +- rc = -ENODEV; +- goto out_err; +- } +- +- if (tpm_do_selftest(chip)) { +- dev_err(dev, "TPM self test failed\n"); +- rc = -ENODEV; +- goto out_err; +- } +- + /* INTERRUPT Setup */ + init_waitqueue_head(&chip->vendor.read_queue); + init_waitqueue_head(&chip->vendor.int_queue); +@@ -688,6 +755,18 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, + } + } + ++ if (tpm_get_timeouts(chip)) { ++ dev_err(dev, "Could not get TPM timeouts and durations\n"); ++ rc = -ENODEV; ++ goto out_err; ++ } ++ ++ if (tpm_do_selftest(chip)) { ++ dev_err(dev, "TPM self test failed\n"); ++ rc = -ENODEV; ++ goto out_err; ++ } ++ + INIT_LIST_HEAD(&chip->vendor.list); + mutex_lock(&tis_lock); + list_add(&chip->vendor.list, &tis_chips); +diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c +index 6928d09..b08eadb 100644 +--- a/drivers/char/virtio_console.c ++++ b/drivers/char/virtio_console.c +@@ -142,6 +142,7 @@ struct ports_device { + * notification + */ + struct work_struct control_work; ++ struct work_struct config_work; + + struct list_head ports; + +@@ -1832,10 +1833,21 @@ static void config_intr(struct virtio_device *vdev) + + portdev = vdev->priv; + ++ if (!use_multiport(portdev)) ++ schedule_work(&portdev->config_work); ++} ++ ++static void config_work_handler(struct work_struct *work) ++{ ++ struct ports_device *portdev; ++ ++ portdev = container_of(work, struct ports_device, control_work); + if (!use_multiport(portdev)) { ++ struct virtio_device *vdev; + struct port *port; + u16 rows, cols; + ++ vdev = portdev->vdev; + virtio_cread(vdev, struct virtio_console_config, cols, &cols); + virtio_cread(vdev, struct virtio_console_config, rows, &rows); + +@@ -2024,12 +2036,14 @@ static int virtcons_probe(struct virtio_device *vdev) + spin_lock_init(&portdev->ports_lock); + INIT_LIST_HEAD(&portdev->ports); + ++ INIT_WORK(&portdev->config_work, &config_work_handler); ++ INIT_WORK(&portdev->control_work, &control_work_handler); ++ + if (multiport) { + unsigned int nr_added_bufs; + + spin_lock_init(&portdev->c_ivq_lock); + spin_lock_init(&portdev->c_ovq_lock); +- INIT_WORK(&portdev->control_work, &control_work_handler); + + nr_added_bufs = fill_queue(portdev->c_ivq, + &portdev->c_ivq_lock); +@@ -2097,6 +2111,8 @@ static void virtcons_remove(struct virtio_device *vdev) + /* Finish up work that's lined up */ + if (use_multiport(portdev)) + cancel_work_sync(&portdev->control_work); ++ else ++ cancel_work_sync(&portdev->config_work); + + list_for_each_entry_safe(port, port2, &portdev->ports, list) + unplug_port(port); +@@ -2148,6 +2164,7 @@ static int virtcons_freeze(struct virtio_device *vdev) + + virtqueue_disable_cb(portdev->c_ivq); + cancel_work_sync(&portdev->control_work); ++ cancel_work_sync(&portdev->config_work); + /* + * Once more: if control_work_handler() was running, it would + * enable the cb as the last step. +diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c +index 4a58c55..797bab9 100644 +--- a/drivers/clk/clk-gate.c ++++ b/drivers/clk/clk-gate.c +@@ -128,7 +128,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name, + struct clk_init_data init; + + if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { +- if (bit_idx > 16) { ++ if (bit_idx > 15) { + pr_err("gate bit exceeds LOWORD field\n"); + return ERR_PTR(-EINVAL); + } +diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c +index 020400d..8b1e2ef 100644 +--- a/drivers/clk/clk.c ++++ b/drivers/clk/clk.c +@@ -1487,6 +1487,7 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even + static void clk_change_rate(struct clk *clk) + { + struct clk *child; ++ struct hlist_node *tmp; + unsigned long old_rate; + unsigned long best_parent_rate = 0; + bool skip_set_rate = false; +@@ -1525,7 +1526,11 @@ static void clk_change_rate(struct clk *clk) + if (clk->notifier_count && old_rate != clk->rate) + __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); + +- hlist_for_each_entry(child, &clk->children, child_node) { ++ /* ++ * Use safe iteration, as change_rate can actually swap parents ++ * for certain clock types. ++ */ ++ hlist_for_each_entry_safe(child, tmp, &clk->children, child_node) { + /* Skip children who will be reparented to another clock */ + if (child->new_parent && child->new_parent != clk) + continue; +@@ -2240,14 +2245,17 @@ int __clk_get(struct clk *clk) + + void __clk_put(struct clk *clk) + { ++ struct module *owner; ++ + if (!clk || WARN_ON_ONCE(IS_ERR(clk))) + return; + + clk_prepare_lock(); ++ owner = clk->owner; + kref_put(&clk->ref, __clk_release); + clk_prepare_unlock(); + +- module_put(clk->owner); ++ module_put(owner); + } + + /*** clk rate change notifiers ***/ +diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c +index 0996a3a..a9dd21a 100644 +--- a/drivers/clk/qcom/clk-rcg2.c ++++ b/drivers/clk/qcom/clk-rcg2.c +@@ -257,7 +257,7 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate) + mask |= CFG_SRC_SEL_MASK | CFG_MODE_MASK; + cfg = f->pre_div << CFG_SRC_DIV_SHIFT; + cfg |= rcg->parent_map[f->src] << CFG_SRC_SEL_SHIFT; +- if (rcg->mnd_width && f->n) ++ if (rcg->mnd_width && f->n && (f->m != f->n)) + cfg |= CFG_MODE_DUAL_EDGE; + ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, mask, + cfg); +diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c +index 9be47a8..f3c95d6 100644 +--- a/drivers/clk/qcom/mmcc-msm8960.c ++++ b/drivers/clk/qcom/mmcc-msm8960.c +@@ -37,6 +37,8 @@ + #define P_PLL2 2 + #define P_PLL3 3 + ++#define F_MN(f, s, _m, _n) { .freq = f, .src = s, .m = _m, .n = _n } ++ + static u8 mmcc_pxo_pll8_pll2_map[] = { + [P_PXO] = 0, + [P_PLL8] = 2, +@@ -58,8 +60,8 @@ static u8 mmcc_pxo_pll8_pll2_pll3_map[] = { + + static const char *mmcc_pxo_pll8_pll2_pll3[] = { + "pxo", +- "pll2", + "pll8_vote", ++ "pll2", + "pll3", + }; + +@@ -709,18 +711,18 @@ static struct clk_branch csiphy2_timer_clk = { + }; + + static struct freq_tbl clk_tbl_gfx2d[] = { +- { 27000000, P_PXO, 1, 0 }, +- { 48000000, P_PLL8, 1, 8 }, +- { 54857000, P_PLL8, 1, 7 }, +- { 64000000, P_PLL8, 1, 6 }, +- { 76800000, P_PLL8, 1, 5 }, +- { 96000000, P_PLL8, 1, 4 }, +- { 128000000, P_PLL8, 1, 3 }, +- { 145455000, P_PLL2, 2, 11 }, +- { 160000000, P_PLL2, 1, 5 }, +- { 177778000, P_PLL2, 2, 9 }, +- { 200000000, P_PLL2, 1, 4 }, +- { 228571000, P_PLL2, 2, 7 }, ++ F_MN( 27000000, P_PXO, 1, 0), ++ F_MN( 48000000, P_PLL8, 1, 8), ++ F_MN( 54857000, P_PLL8, 1, 7), ++ F_MN( 64000000, P_PLL8, 1, 6), ++ F_MN( 76800000, P_PLL8, 1, 5), ++ F_MN( 96000000, P_PLL8, 1, 4), ++ F_MN(128000000, P_PLL8, 1, 3), ++ F_MN(145455000, P_PLL2, 2, 11), ++ F_MN(160000000, P_PLL2, 1, 5), ++ F_MN(177778000, P_PLL2, 2, 9), ++ F_MN(200000000, P_PLL2, 1, 4), ++ F_MN(228571000, P_PLL2, 2, 7), + { } + }; + +@@ -841,22 +843,22 @@ static struct clk_branch gfx2d1_clk = { + }; + + static struct freq_tbl clk_tbl_gfx3d[] = { +- { 27000000, P_PXO, 1, 0 }, +- { 48000000, P_PLL8, 1, 8 }, +- { 54857000, P_PLL8, 1, 7 }, +- { 64000000, P_PLL8, 1, 6 }, +- { 76800000, P_PLL8, 1, 5 }, +- { 96000000, P_PLL8, 1, 4 }, +- { 128000000, P_PLL8, 1, 3 }, +- { 145455000, P_PLL2, 2, 11 }, +- { 160000000, P_PLL2, 1, 5 }, +- { 177778000, P_PLL2, 2, 9 }, +- { 200000000, P_PLL2, 1, 4 }, +- { 228571000, P_PLL2, 2, 7 }, +- { 266667000, P_PLL2, 1, 3 }, +- { 300000000, P_PLL3, 1, 4 }, +- { 320000000, P_PLL2, 2, 5 }, +- { 400000000, P_PLL2, 1, 2 }, ++ F_MN( 27000000, P_PXO, 1, 0), ++ F_MN( 48000000, P_PLL8, 1, 8), ++ F_MN( 54857000, P_PLL8, 1, 7), ++ F_MN( 64000000, P_PLL8, 1, 6), ++ F_MN( 76800000, P_PLL8, 1, 5), ++ F_MN( 96000000, P_PLL8, 1, 4), ++ F_MN(128000000, P_PLL8, 1, 3), ++ F_MN(145455000, P_PLL2, 2, 11), ++ F_MN(160000000, P_PLL2, 1, 5), ++ F_MN(177778000, P_PLL2, 2, 9), ++ F_MN(200000000, P_PLL2, 1, 4), ++ F_MN(228571000, P_PLL2, 2, 7), ++ F_MN(266667000, P_PLL2, 1, 3), ++ F_MN(300000000, P_PLL3, 1, 4), ++ F_MN(320000000, P_PLL2, 2, 5), ++ F_MN(400000000, P_PLL2, 1, 2), + { } + }; + +@@ -896,7 +898,7 @@ static struct clk_dyn_rcg gfx3d_src = { + .hw.init = &(struct clk_init_data){ + .name = "gfx3d_src", + .parent_names = mmcc_pxo_pll8_pll2_pll3, +- .num_parents = 3, ++ .num_parents = 4, + .ops = &clk_dyn_rcg_ops, + }, + }, +@@ -994,7 +996,7 @@ static struct clk_rcg jpegd_src = { + .ns_reg = 0x00ac, + .p = { + .pre_div_shift = 12, +- .pre_div_width = 2, ++ .pre_div_width = 4, + }, + .s = { + .src_sel_shift = 0, +@@ -1114,7 +1116,7 @@ static struct clk_branch mdp_lut_clk = { + .enable_reg = 0x016c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ +- .parent_names = (const char *[]){ "mdp_clk" }, ++ .parent_names = (const char *[]){ "mdp_src" }, + .num_parents = 1, + .name = "mdp_lut_clk", + .ops = &clk_branch_ops, +@@ -1341,15 +1343,15 @@ static struct clk_branch hdmi_app_clk = { + }; + + static struct freq_tbl clk_tbl_vcodec[] = { +- { 27000000, P_PXO, 1, 0 }, +- { 32000000, P_PLL8, 1, 12 }, +- { 48000000, P_PLL8, 1, 8 }, +- { 54860000, P_PLL8, 1, 7 }, +- { 96000000, P_PLL8, 1, 4 }, +- { 133330000, P_PLL2, 1, 6 }, +- { 200000000, P_PLL2, 1, 4 }, +- { 228570000, P_PLL2, 2, 7 }, +- { 266670000, P_PLL2, 1, 3 }, ++ F_MN( 27000000, P_PXO, 1, 0), ++ F_MN( 32000000, P_PLL8, 1, 12), ++ F_MN( 48000000, P_PLL8, 1, 8), ++ F_MN( 54860000, P_PLL8, 1, 7), ++ F_MN( 96000000, P_PLL8, 1, 4), ++ F_MN(133330000, P_PLL2, 1, 6), ++ F_MN(200000000, P_PLL2, 1, 4), ++ F_MN(228570000, P_PLL2, 2, 7), ++ F_MN(266670000, P_PLL2, 1, 3), + { } + }; + +diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c +index 884187f..7f30b94 100644 +--- a/drivers/clk/samsung/clk-exynos-audss.c ++++ b/drivers/clk/samsung/clk-exynos-audss.c +@@ -210,6 +210,10 @@ static int exynos_audss_clk_remove(struct platform_device *pdev) + { + int i; + ++#ifdef CONFIG_PM_SLEEP ++ unregister_syscore_ops(&exynos_audss_clk_syscore_ops); ++#endif ++ + of_clk_del_provider(pdev->dev.of_node); + + for (i = 0; i < clk_data.clk_num; i++) { +diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c +index 9e23264..ea4db84 100644 +--- a/drivers/clk/sunxi/clk-factors.c ++++ b/drivers/clk/sunxi/clk-factors.c +@@ -62,7 +62,7 @@ static unsigned long clk_factors_recalc_rate(struct clk_hw *hw, + p = FACTOR_GET(config->pshift, config->pwidth, reg); + + /* Calculate the rate */ +- rate = (parent_rate * n * (k + 1) >> p) / (m + 1); ++ rate = (parent_rate * (n + config->n_start) * (k + 1) >> p) / (m + 1); + + return rate; + } +diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h +index 02e1a43..d2d0efa 100644 +--- a/drivers/clk/sunxi/clk-factors.h ++++ b/drivers/clk/sunxi/clk-factors.h +@@ -15,6 +15,7 @@ struct clk_factors_config { + u8 mwidth; + u8 pshift; + u8 pwidth; ++ u8 n_start; + }; + + struct clk_factors { +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index abb6c5a..06a14b8 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -407,6 +407,7 @@ static struct clk_factors_config sun6i_a31_pll1_config = { + .kwidth = 2, + .mshift = 0, + .mwidth = 2, ++ .n_start = 1, + }; + + static struct clk_factors_config sun4i_pll5_config = { +diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c +index c0a7d77..a90af17 100644 +--- a/drivers/clk/tegra/clk.c ++++ b/drivers/clk/tegra/clk.c +@@ -266,7 +266,7 @@ void __init tegra_add_of_provider(struct device_node *np) + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + + rst_ctlr.of_node = np; +- rst_ctlr.nr_resets = clk_num * 32; ++ rst_ctlr.nr_resets = periph_banks * 32; + reset_controller_register(&rst_ctlr); + } + +diff --git a/drivers/clk/versatile/clk-sp810.c b/drivers/clk/versatile/clk-sp810.c +index c6e86a9..5122ef2 100644 +--- a/drivers/clk/versatile/clk-sp810.c ++++ b/drivers/clk/versatile/clk-sp810.c +@@ -128,8 +128,8 @@ static struct clk *clk_sp810_timerclken_of_get(struct of_phandle_args *clkspec, + { + struct clk_sp810 *sp810 = data; + +- if (WARN_ON(clkspec->args_count != 1 || clkspec->args[0] > +- ARRAY_SIZE(sp810->timerclken))) ++ if (WARN_ON(clkspec->args_count != 1 || ++ clkspec->args[0] >= ARRAY_SIZE(sp810->timerclken))) + return NULL; + + return sp810->timerclken[clkspec->args[0]].clk; +diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c +index 09dd017..5f52f3f 100644 +--- a/drivers/clk/zynq/clkc.c ++++ b/drivers/clk/zynq/clkc.c +@@ -300,6 +300,7 @@ static void __init zynq_clk_setup(struct device_node *np) + clks[cpu_2x] = clk_register_gate(NULL, clk_output_name[cpu_2x], + "cpu_2x_div", CLK_IGNORE_UNUSED, SLCR_ARM_CLK_CTRL, + 26, 0, &armclk_lock); ++ clk_prepare_enable(clks[cpu_2x]); + + clk = clk_register_fixed_factor(NULL, "cpu_1x_div", "cpu_div", 0, 1, + 4 + 2 * tmp); +diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c +index e252939..ddd03f8 100644 +--- a/drivers/clocksource/exynos_mct.c ++++ b/drivers/clocksource/exynos_mct.c +@@ -98,8 +98,8 @@ static void exynos4_mct_write(unsigned int value, unsigned long offset) + __raw_writel(value, reg_base + offset); + + if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) { +- stat_addr = (offset & ~EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET; +- switch (offset & EXYNOS4_MCT_L_MASK) { ++ stat_addr = (offset & EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET; ++ switch (offset & ~EXYNOS4_MCT_L_MASK) { + case MCT_L_TCON_OFFSET: + mask = 1 << 3; /* L_TCON write status */ + break; +@@ -422,15 +422,12 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) + exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET); + + if (mct_int_type == MCT_INT_SPI) { +- evt->irq = mct_irqs[MCT_L0_IRQ + cpu]; +- if (request_irq(evt->irq, exynos4_mct_tick_isr, +- IRQF_TIMER | IRQF_NOBALANCING, +- evt->name, mevt)) { +- pr_err("exynos-mct: cannot register IRQ %d\n", +- evt->irq); ++ ++ if (evt->irq == -1) + return -EIO; +- } +- irq_force_affinity(mct_irqs[MCT_L0_IRQ + cpu], cpumask_of(cpu)); ++ ++ irq_force_affinity(evt->irq, cpumask_of(cpu)); ++ enable_irq(evt->irq); + } else { + enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0); + } +@@ -443,10 +440,12 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) + static void exynos4_local_timer_stop(struct clock_event_device *evt) + { + evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); +- if (mct_int_type == MCT_INT_SPI) +- free_irq(evt->irq, this_cpu_ptr(&percpu_mct_tick)); +- else ++ if (mct_int_type == MCT_INT_SPI) { ++ if (evt->irq != -1) ++ disable_irq_nosync(evt->irq); ++ } else { + disable_percpu_irq(mct_irqs[MCT_L0_IRQ]); ++ } + } + + static int exynos4_mct_cpu_notify(struct notifier_block *self, +@@ -478,7 +477,7 @@ static struct notifier_block exynos4_mct_cpu_nb = { + + static void __init exynos4_timer_resources(struct device_node *np, void __iomem *base) + { +- int err; ++ int err, cpu; + struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); + struct clk *mct_clk, *tick_clk; + +@@ -505,7 +504,25 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomem + WARN(err, "MCT: can't request IRQ %d (%d)\n", + mct_irqs[MCT_L0_IRQ], err); + } else { +- irq_set_affinity(mct_irqs[MCT_L0_IRQ], cpumask_of(0)); ++ for_each_possible_cpu(cpu) { ++ int mct_irq = mct_irqs[MCT_L0_IRQ + cpu]; ++ struct mct_clock_event_device *pcpu_mevt = ++ per_cpu_ptr(&percpu_mct_tick, cpu); ++ ++ pcpu_mevt->evt.irq = -1; ++ ++ irq_set_status_flags(mct_irq, IRQ_NOAUTOEN); ++ if (request_irq(mct_irq, ++ exynos4_mct_tick_isr, ++ IRQF_TIMER | IRQF_NOBALANCING, ++ pcpu_mevt->name, pcpu_mevt)) { ++ pr_err("exynos-mct: cannot register IRQ (cpu%d)\n", ++ cpu); ++ ++ continue; ++ } ++ pcpu_mevt->evt.irq = mct_irq; ++ } + } + + err = register_cpu_notifier(&exynos4_mct_cpu_nb); +diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c +index bf497af..7d19f86 100644 +--- a/drivers/clocksource/sun4i_timer.c ++++ b/drivers/clocksource/sun4i_timer.c +@@ -182,6 +182,12 @@ static void __init sun4i_timer_init(struct device_node *node) + /* Make sure timer is stopped before playing with interrupts */ + sun4i_clkevt_time_stop(0); + ++ sun4i_clockevent.cpumask = cpu_possible_mask; ++ sun4i_clockevent.irq = irq; ++ ++ clockevents_config_and_register(&sun4i_clockevent, rate, ++ TIMER_SYNC_TICKS, 0xffffffff); ++ + ret = setup_irq(irq, &sun4i_timer_irq); + if (ret) + pr_warn("failed to setup irq %d\n", irq); +@@ -189,12 +195,6 @@ static void __init sun4i_timer_init(struct device_node *node) + /* Enable timer0 interrupt */ + val = readl(timer_base + TIMER_IRQ_EN_REG); + writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); +- +- sun4i_clockevent.cpumask = cpu_possible_mask; +- sun4i_clockevent.irq = irq; +- +- clockevents_config_and_register(&sun4i_clockevent, rate, +- TIMER_SYNC_TICKS, 0xffffffff); + } + CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-timer", + sun4i_timer_init); +diff --git a/drivers/clocksource/time-efm32.c b/drivers/clocksource/time-efm32.c +index 1a6205b..35b0161 100644 +--- a/drivers/clocksource/time-efm32.c ++++ b/drivers/clocksource/time-efm32.c +@@ -225,12 +225,12 @@ static int __init efm32_clockevent_init(struct device_node *np) + clock_event_ddata.base = base; + clock_event_ddata.periodic_top = DIV_ROUND_CLOSEST(rate, 1024 * HZ); + +- setup_irq(irq, &efm32_clock_event_irq); +- + clockevents_config_and_register(&clock_event_ddata.evtdev, + DIV_ROUND_CLOSEST(rate, 1024), + 0xf, 0xffff); + ++ setup_irq(irq, &efm32_clock_event_irq); ++ + return 0; + + err_get_irq: +diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c +index deebcd6..4f0f361 100644 +--- a/drivers/clocksource/timer-sun5i.c ++++ b/drivers/clocksource/timer-sun5i.c +@@ -172,10 +172,6 @@ static void __init sun5i_timer_init(struct device_node *node) + + ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); + +- ret = setup_irq(irq, &sun5i_timer_irq); +- if (ret) +- pr_warn("failed to setup irq %d\n", irq); +- + /* Enable timer0 interrupt */ + val = readl(timer_base + TIMER_IRQ_EN_REG); + writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); +@@ -185,6 +181,10 @@ static void __init sun5i_timer_init(struct device_node *node) + + clockevents_config_and_register(&sun5i_clockevent, rate, + TIMER_SYNC_TICKS, 0xffffffff); ++ ++ ret = setup_irq(irq, &sun5i_timer_irq); ++ if (ret) ++ pr_warn("failed to setup irq %d\n", irq); + } + CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer", + sun5i_timer_init); +diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c +index 199b52b..ef3b8ad 100644 +--- a/drivers/cpufreq/cpufreq.c ++++ b/drivers/cpufreq/cpufreq.c +@@ -460,7 +460,18 @@ show_one(cpuinfo_max_freq, cpuinfo.max_freq); + show_one(cpuinfo_transition_latency, cpuinfo.transition_latency); + show_one(scaling_min_freq, min); + show_one(scaling_max_freq, max); +-show_one(scaling_cur_freq, cur); ++ ++static ssize_t show_scaling_cur_freq( ++ struct cpufreq_policy *policy, char *buf) ++{ ++ ssize_t ret; ++ ++ if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get) ++ ret = sprintf(buf, "%u\n", cpufreq_driver->get(policy->cpu)); ++ else ++ ret = sprintf(buf, "%u\n", policy->cur); ++ return ret; ++} + + static int cpufreq_set_policy(struct cpufreq_policy *policy, + struct cpufreq_policy *new_policy); +@@ -854,11 +865,11 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy, + if (ret) + goto err_out_kobj_put; + } +- if (has_target()) { +- ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); +- if (ret) +- goto err_out_kobj_put; +- } ++ ++ ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); ++ if (ret) ++ goto err_out_kobj_put; ++ + if (cpufreq_driver->bios_limit) { + ret = sysfs_create_file(&policy->kobj, &bios_limit.attr); + if (ret) +@@ -1089,10 +1100,12 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, + * the creation of a brand new one. So we need to perform this update + * by invoking update_policy_cpu(). + */ +- if (frozen && cpu != policy->cpu) ++ if (frozen && cpu != policy->cpu) { + update_policy_cpu(policy, cpu); +- else ++ WARN_ON(kobject_move(&policy->kobj, &dev->kobj)); ++ } else { + policy->cpu = cpu; ++ } + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + cpumask_copy(policy->cpus, cpumask_of(cpu)); +@@ -1223,6 +1236,8 @@ err_get_freq: + per_cpu(cpufreq_cpu_data, j) = NULL; + write_unlock_irqrestore(&cpufreq_driver_lock, flags); + ++ up_write(&policy->rwsem); ++ + if (cpufreq_driver->exit) + cpufreq_driver->exit(policy); + err_set_policy_cpu: +@@ -1350,9 +1365,10 @@ static int __cpufreq_remove_dev_finish(struct device *dev, + unsigned long flags; + struct cpufreq_policy *policy; + +- read_lock_irqsave(&cpufreq_driver_lock, flags); ++ write_lock_irqsave(&cpufreq_driver_lock, flags); + policy = per_cpu(cpufreq_cpu_data, cpu); +- read_unlock_irqrestore(&cpufreq_driver_lock, flags); ++ per_cpu(cpufreq_cpu_data, cpu) = NULL; ++ write_unlock_irqrestore(&cpufreq_driver_lock, flags); + + if (!policy) { + pr_debug("%s: No cpu_data found\n", __func__); +@@ -1407,7 +1423,6 @@ static int __cpufreq_remove_dev_finish(struct device *dev, + } + } + +- per_cpu(cpufreq_cpu_data, cpu) = NULL; + return 0; + } + +diff --git a/drivers/cpufreq/integrator-cpufreq.c b/drivers/cpufreq/integrator-cpufreq.c +index 0e27844..8089dd2 100644 +--- a/drivers/cpufreq/integrator-cpufreq.c ++++ b/drivers/cpufreq/integrator-cpufreq.c +@@ -213,9 +213,9 @@ static int __init integrator_cpufreq_probe(struct platform_device *pdev) + return cpufreq_register_driver(&integrator_driver); + } + +-static void __exit integrator_cpufreq_remove(struct platform_device *pdev) ++static int __exit integrator_cpufreq_remove(struct platform_device *pdev) + { +- cpufreq_unregister_driver(&integrator_driver); ++ return cpufreq_unregister_driver(&integrator_driver); + } + + static const struct of_device_id integrator_cpufreq_match[] = { +diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c +index ae52c77..fbc693b 100644 +--- a/drivers/cpufreq/intel_pstate.c ++++ b/drivers/cpufreq/intel_pstate.c +@@ -55,6 +55,17 @@ static inline int32_t div_fp(int32_t x, int32_t y) + return div_s64((int64_t)x << FRAC_BITS, (int64_t)y); + } + ++static inline int ceiling_fp(int32_t x) ++{ ++ int mask, ret; ++ ++ ret = fp_toint(x); ++ mask = (1 << FRAC_BITS) - 1; ++ if (x & mask) ++ ret += 1; ++ return ret; ++} ++ + struct sample { + int32_t core_pct_busy; + u64 aperf; +@@ -67,6 +78,7 @@ struct pstate_data { + int current_pstate; + int min_pstate; + int max_pstate; ++ int scaling; + int turbo_pstate; + }; + +@@ -118,6 +130,7 @@ struct pstate_funcs { + int (*get_max)(void); + int (*get_min)(void); + int (*get_turbo)(void); ++ int (*get_scaling)(void); + void (*set)(struct cpudata*, int pstate); + void (*get_vid)(struct cpudata *); + }; +@@ -397,14 +410,30 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate) + cpudata->vid.ratio); + + vid_fp = clamp_t(int32_t, vid_fp, cpudata->vid.min, cpudata->vid.max); +- vid = fp_toint(vid_fp); ++ vid = ceiling_fp(vid_fp); + + if (pstate > cpudata->pstate.max_pstate) + vid = cpudata->vid.turbo; + + val |= vid; + +- wrmsrl(MSR_IA32_PERF_CTL, val); ++ wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val); ++} ++ ++#define BYT_BCLK_FREQS 5 ++static int byt_freq_table[BYT_BCLK_FREQS] = { 833, 1000, 1333, 1167, 800}; ++ ++static int byt_get_scaling(void) ++{ ++ u64 value; ++ int i; ++ ++ rdmsrl(MSR_FSB_FREQ, value); ++ i = value & 0x3; ++ ++ BUG_ON(i > BYT_BCLK_FREQS); ++ ++ return byt_freq_table[i] * 100; + } + + static void byt_get_vid(struct cpudata *cpudata) +@@ -451,6 +480,11 @@ static int core_get_turbo_pstate(void) + return ret; + } + ++static inline int core_get_scaling(void) ++{ ++ return 100000; ++} ++ + static void core_set_pstate(struct cpudata *cpudata, int pstate) + { + u64 val; +@@ -475,6 +509,7 @@ static struct cpu_defaults core_params = { + .get_max = core_get_max_pstate, + .get_min = core_get_min_pstate, + .get_turbo = core_get_turbo_pstate, ++ .get_scaling = core_get_scaling, + .set = core_set_pstate, + }, + }; +@@ -493,6 +528,7 @@ static struct cpu_defaults byt_params = { + .get_min = byt_get_min_pstate, + .get_turbo = byt_get_turbo_pstate, + .set = byt_set_pstate, ++ .get_scaling = byt_get_scaling, + .get_vid = byt_get_vid, + }, + }; +@@ -526,7 +562,7 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) + if (pstate == cpu->pstate.current_pstate) + return; + +- trace_cpu_frequency(pstate * 100000, cpu->cpu); ++ trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu); + + cpu->pstate.current_pstate = pstate; + +@@ -555,6 +591,7 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) + cpu->pstate.min_pstate = pstate_funcs.get_min(); + cpu->pstate.max_pstate = pstate_funcs.get_max(); + cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); ++ cpu->pstate.scaling = pstate_funcs.get_scaling(); + + if (pstate_funcs.get_vid) + pstate_funcs.get_vid(cpu); +@@ -574,7 +611,9 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu, + core_pct += 1; + + sample->freq = fp_toint( +- mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct)); ++ mul_fp(int_tofp( ++ cpu->pstate.max_pstate * cpu->pstate.scaling / 100), ++ core_pct)); + + sample->core_pct_busy = (int32_t)core_pct; + } +@@ -685,10 +724,14 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = { + ICPU(0x37, byt_params), + ICPU(0x3a, core_params), + ICPU(0x3c, core_params), ++ ICPU(0x3d, core_params), + ICPU(0x3e, core_params), + ICPU(0x3f, core_params), + ICPU(0x45, core_params), + ICPU(0x46, core_params), ++ ICPU(0x4c, byt_params), ++ ICPU(0x4f, core_params), ++ ICPU(0x56, core_params), + {} + }; + MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); +@@ -751,6 +794,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) { + limits.min_perf_pct = 100; + limits.min_perf = int_tofp(1); ++ limits.max_policy_pct = 100; + limits.max_perf_pct = 100; + limits.max_perf = int_tofp(1); + limits.no_turbo = limits.turbo_disabled; +@@ -812,12 +856,13 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy) + else + policy->policy = CPUFREQ_POLICY_POWERSAVE; + +- policy->min = cpu->pstate.min_pstate * 100000; +- policy->max = cpu->pstate.turbo_pstate * 100000; ++ policy->min = cpu->pstate.min_pstate * cpu->pstate.scaling; ++ policy->max = cpu->pstate.turbo_pstate * cpu->pstate.scaling; + + /* cpuinfo and default policy values */ +- policy->cpuinfo.min_freq = cpu->pstate.min_pstate * 100000; +- policy->cpuinfo.max_freq = cpu->pstate.turbo_pstate * 100000; ++ policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling; ++ policy->cpuinfo.max_freq = ++ cpu->pstate.turbo_pstate * cpu->pstate.scaling; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + cpumask_set_cpu(policy->cpu, policy->cpus); + +@@ -875,6 +920,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs) + pstate_funcs.get_max = funcs->get_max; + pstate_funcs.get_min = funcs->get_min; + pstate_funcs.get_turbo = funcs->get_turbo; ++ pstate_funcs.get_scaling = funcs->get_scaling; + pstate_funcs.set = funcs->set; + pstate_funcs.get_vid = funcs->get_vid; + } +diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c +index 826b8be..82cef00 100644 +--- a/drivers/cpufreq/s3c2416-cpufreq.c ++++ b/drivers/cpufreq/s3c2416-cpufreq.c +@@ -263,7 +263,7 @@ out: + } + + #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE +-static void __init s3c2416_cpufreq_cfg_regulator(struct s3c2416_data *s3c_freq) ++static void s3c2416_cpufreq_cfg_regulator(struct s3c2416_data *s3c_freq) + { + int count, v, i, found; + struct cpufreq_frequency_table *freq; +@@ -335,7 +335,7 @@ static struct notifier_block s3c2416_cpufreq_reboot_notifier = { + .notifier_call = s3c2416_cpufreq_reboot_notifier_evt, + }; + +-static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) ++static int s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) + { + struct s3c2416_data *s3c_freq = &s3c2416_cpufreq; + struct cpufreq_frequency_table *freq; +diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c +index 2506974..0eb5b40 100644 +--- a/drivers/cpufreq/s3c24xx-cpufreq.c ++++ b/drivers/cpufreq/s3c24xx-cpufreq.c +@@ -454,7 +454,7 @@ static struct cpufreq_driver s3c24xx_driver = { + }; + + +-int __init s3c_cpufreq_register(struct s3c_cpufreq_info *info) ++int s3c_cpufreq_register(struct s3c_cpufreq_info *info) + { + if (!info || !info->name) { + printk(KERN_ERR "%s: failed to pass valid information\n", +diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-lib.c +index 7047821..4ab7a21 100644 +--- a/drivers/cpufreq/speedstep-lib.c ++++ b/drivers/cpufreq/speedstep-lib.c +@@ -400,6 +400,7 @@ unsigned int speedstep_get_freqs(enum speedstep_processor processor, + + pr_debug("previous speed is %u\n", prev_speed); + ++ preempt_disable(); + local_irq_save(flags); + + /* switch to low state */ +@@ -464,6 +465,8 @@ unsigned int speedstep_get_freqs(enum speedstep_processor processor, + + out: + local_irq_restore(flags); ++ preempt_enable(); ++ + return ret; + } + EXPORT_SYMBOL_GPL(speedstep_get_freqs); +diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c +index 998c17b..b52d8af 100644 +--- a/drivers/cpufreq/speedstep-smi.c ++++ b/drivers/cpufreq/speedstep-smi.c +@@ -156,6 +156,7 @@ static void speedstep_set_state(unsigned int state) + return; + + /* Disable IRQs */ ++ preempt_disable(); + local_irq_save(flags); + + command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); +@@ -166,9 +167,19 @@ static void speedstep_set_state(unsigned int state) + + do { + if (retry) { ++ /* ++ * We need to enable interrupts, otherwise the blockage ++ * won't resolve. ++ * ++ * We disable preemption so that other processes don't ++ * run. If other processes were running, they could ++ * submit more DMA requests, making the blockage worse. ++ */ + pr_debug("retry %u, previous result %u, waiting...\n", + retry, result); ++ local_irq_enable(); + mdelay(retry * 50); ++ local_irq_disable(); + } + retry++; + __asm__ __volatile__( +@@ -185,6 +196,7 @@ static void speedstep_set_state(unsigned int state) + + /* enable IRQs */ + local_irq_restore(flags); ++ preempt_enable(); + + if (new_state == state) + pr_debug("change to %u MHz succeeded after %u tries " +diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c +index a55e68f..1adc039 100644 +--- a/drivers/cpuidle/cpuidle.c ++++ b/drivers/cpuidle/cpuidle.c +@@ -131,6 +131,9 @@ int cpuidle_idle_call(void) + + /* ask the governor for the next state */ + next_state = cpuidle_curr_governor->select(drv, dev); ++ if (next_state < 0) ++ return -EBUSY; ++ + if (need_resched()) { + dev->last_residency = 0; + /* give the governor an opportunity to reflect on the outcome */ +@@ -252,9 +255,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev) + if (!dev->registered) + return -EINVAL; + +- if (!dev->state_count) +- dev->state_count = drv->state_count; +- + ret = cpuidle_add_device_sysfs(dev); + if (ret) + return ret; +diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c +index cf7f2f0..027c484 100644 +--- a/drivers/cpuidle/governors/menu.c ++++ b/drivers/cpuidle/governors/menu.c +@@ -297,7 +297,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) + data->needs_update = 0; + } + +- data->last_state_idx = 0; ++ data->last_state_idx = CPUIDLE_DRIVER_STATE_START - 1; + data->exit_us = 0; + + /* Special case when user has set very strict latency requirement */ +diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c +index e918b6d..dcaae4c 100644 +--- a/drivers/cpuidle/sysfs.c ++++ b/drivers/cpuidle/sysfs.c +@@ -398,7 +398,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) + struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); + + /* state statistics */ +- for (i = 0; i < device->state_count; i++) { ++ for (i = 0; i < drv->state_count; i++) { + kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL); + if (!kobj) + goto error_state; +@@ -430,9 +430,10 @@ error_state: + */ + static void cpuidle_remove_state_sysfs(struct cpuidle_device *device) + { ++ struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); + int i; + +- for (i = 0; i < device->state_count; i++) ++ for (i = 0; i < drv->state_count; i++) + cpuidle_free_state_kobj(device, i); + } + +diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c +index 0378328..1489927 100644 +--- a/drivers/crypto/caam/caamhash.c ++++ b/drivers/crypto/caam/caamhash.c +@@ -835,8 +835,9 @@ static int ahash_update_ctx(struct ahash_request *req) + edesc->sec4_sg + sec4_sg_src_index, + chained); + if (*next_buflen) { +- sg_copy_part(next_buf, req->src, to_hash - +- *buflen, req->nbytes); ++ scatterwalk_map_and_copy(next_buf, req->src, ++ to_hash - *buflen, ++ *next_buflen, 0); + state->current_buf = !state->current_buf; + } + } else { +@@ -869,7 +870,8 @@ static int ahash_update_ctx(struct ahash_request *req) + kfree(edesc); + } + } else if (*next_buflen) { +- sg_copy(buf + *buflen, req->src, req->nbytes); ++ scatterwalk_map_and_copy(buf + *buflen, req->src, 0, ++ req->nbytes, 0); + *buflen = *next_buflen; + *next_buflen = last_buflen; + } +@@ -898,13 +900,14 @@ static int ahash_final_ctx(struct ahash_request *req) + state->buflen_1; + u32 *sh_desc = ctx->sh_desc_fin, *desc; + dma_addr_t ptr = ctx->sh_desc_fin_dma; +- int sec4_sg_bytes; ++ int sec4_sg_bytes, sec4_sg_src_index; + int digestsize = crypto_ahash_digestsize(ahash); + struct ahash_edesc *edesc; + int ret = 0; + int sh_len; + +- sec4_sg_bytes = (1 + (buflen ? 1 : 0)) * sizeof(struct sec4_sg_entry); ++ sec4_sg_src_index = 1 + (buflen ? 1 : 0); ++ sec4_sg_bytes = sec4_sg_src_index * sizeof(struct sec4_sg_entry); + + /* allocate space for base edesc and hw desc commands, link tables */ + edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN + +@@ -931,7 +934,7 @@ static int ahash_final_ctx(struct ahash_request *req) + state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1, + buf, state->buf_dma, buflen, + last_buflen); +- (edesc->sec4_sg + sec4_sg_bytes - 1)->len |= SEC4_SG_LEN_FIN; ++ (edesc->sec4_sg + sec4_sg_src_index - 1)->len |= SEC4_SG_LEN_FIN; + + append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + buflen, + LDST_SGF); +@@ -1216,8 +1219,9 @@ static int ahash_update_no_ctx(struct ahash_request *req) + src_map_to_sec4_sg(jrdev, req->src, src_nents, + edesc->sec4_sg + 1, chained); + if (*next_buflen) { +- sg_copy_part(next_buf, req->src, to_hash - *buflen, +- req->nbytes); ++ scatterwalk_map_and_copy(next_buf, req->src, ++ to_hash - *buflen, ++ *next_buflen, 0); + state->current_buf = !state->current_buf; + } + +@@ -1248,7 +1252,8 @@ static int ahash_update_no_ctx(struct ahash_request *req) + kfree(edesc); + } + } else if (*next_buflen) { +- sg_copy(buf + *buflen, req->src, req->nbytes); ++ scatterwalk_map_and_copy(buf + *buflen, req->src, 0, ++ req->nbytes, 0); + *buflen = *next_buflen; + *next_buflen = 0; + } +@@ -1348,9 +1353,9 @@ static int ahash_update_first(struct ahash_request *req) + struct device *jrdev = ctx->jrdev; + gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC; +- u8 *next_buf = state->buf_0 + state->current_buf * +- CAAM_MAX_HASH_BLOCK_SIZE; +- int *next_buflen = &state->buflen_0 + state->current_buf; ++ u8 *next_buf = state->current_buf ? state->buf_1 : state->buf_0; ++ int *next_buflen = state->current_buf ? ++ &state->buflen_1 : &state->buflen_0; + int to_hash; + u32 *sh_desc = ctx->sh_desc_update_first, *desc; + dma_addr_t ptr = ctx->sh_desc_update_first_dma; +@@ -1405,7 +1410,8 @@ static int ahash_update_first(struct ahash_request *req) + } + + if (*next_buflen) +- sg_copy_part(next_buf, req->src, to_hash, req->nbytes); ++ scatterwalk_map_and_copy(next_buf, req->src, to_hash, ++ *next_buflen, 0); + + sh_len = desc_len(sh_desc); + desc = edesc->hw_desc; +@@ -1438,7 +1444,8 @@ static int ahash_update_first(struct ahash_request *req) + state->update = ahash_update_no_ctx; + state->finup = ahash_finup_no_ctx; + state->final = ahash_final_no_ctx; +- sg_copy(next_buf, req->src, req->nbytes); ++ scatterwalk_map_and_copy(next_buf, req->src, 0, ++ req->nbytes, 0); + } + #ifdef DEBUG + print_hex_dump(KERN_ERR, "next buf@"__stringify(__LINE__)": ", +diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c +index 28486b1..ae6dae8 100644 +--- a/drivers/crypto/caam/caamrng.c ++++ b/drivers/crypto/caam/caamrng.c +@@ -56,7 +56,7 @@ + + /* Buffer, its dma address and lock */ + struct buf_data { +- u8 buf[RN_BUF_SIZE]; ++ u8 buf[RN_BUF_SIZE] ____cacheline_aligned; + dma_addr_t addr; + struct completion filled; + u32 hw_desc[DESC_JOB_O_LEN]; +diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c +index ea2e406..b872eed 100644 +--- a/drivers/crypto/caam/key_gen.c ++++ b/drivers/crypto/caam/key_gen.c +@@ -51,23 +51,29 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len, + u32 *desc; + struct split_key_result result; + dma_addr_t dma_addr_in, dma_addr_out; +- int ret = 0; ++ int ret = -ENOMEM; + + desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA); + if (!desc) { + dev_err(jrdev, "unable to allocate key input memory\n"); +- return -ENOMEM; ++ return ret; + } + +- init_job_desc(desc, 0); +- + dma_addr_in = dma_map_single(jrdev, (void *)key_in, keylen, + DMA_TO_DEVICE); + if (dma_mapping_error(jrdev, dma_addr_in)) { + dev_err(jrdev, "unable to map key input memory\n"); +- kfree(desc); +- return -ENOMEM; ++ goto out_free; + } ++ ++ dma_addr_out = dma_map_single(jrdev, key_out, split_key_pad_len, ++ DMA_FROM_DEVICE); ++ if (dma_mapping_error(jrdev, dma_addr_out)) { ++ dev_err(jrdev, "unable to map key output memory\n"); ++ goto out_unmap_in; ++ } ++ ++ init_job_desc(desc, 0); + append_key(desc, dma_addr_in, keylen, CLASS_2 | KEY_DEST_CLASS_REG); + + /* Sets MDHA up into an HMAC-INIT */ +@@ -84,13 +90,6 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len, + * FIFO_STORE with the explicit split-key content store + * (0x26 output type) + */ +- dma_addr_out = dma_map_single(jrdev, key_out, split_key_pad_len, +- DMA_FROM_DEVICE); +- if (dma_mapping_error(jrdev, dma_addr_out)) { +- dev_err(jrdev, "unable to map key output memory\n"); +- kfree(desc); +- return -ENOMEM; +- } + append_fifo_store(desc, dma_addr_out, split_key_len, + LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK); + +@@ -118,10 +117,10 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len, + + dma_unmap_single(jrdev, dma_addr_out, split_key_pad_len, + DMA_FROM_DEVICE); ++out_unmap_in: + dma_unmap_single(jrdev, dma_addr_in, keylen, DMA_TO_DEVICE); +- ++out_free: + kfree(desc); +- + return ret; + } + EXPORT_SYMBOL(gen_split_key); +diff --git a/drivers/crypto/caam/sg_sw_sec4.h b/drivers/crypto/caam/sg_sw_sec4.h +index b12ff85..ce28a56 100644 +--- a/drivers/crypto/caam/sg_sw_sec4.h ++++ b/drivers/crypto/caam/sg_sw_sec4.h +@@ -116,57 +116,3 @@ static int dma_unmap_sg_chained(struct device *dev, struct scatterlist *sg, + } + return nents; + } +- +-/* Map SG page in kernel virtual address space and copy */ +-static inline void sg_map_copy(u8 *dest, struct scatterlist *sg, +- int len, int offset) +-{ +- u8 *mapped_addr; +- +- /* +- * Page here can be user-space pinned using get_user_pages +- * Same must be kmapped before use and kunmapped subsequently +- */ +- mapped_addr = kmap_atomic(sg_page(sg)); +- memcpy(dest, mapped_addr + offset, len); +- kunmap_atomic(mapped_addr); +-} +- +-/* Copy from len bytes of sg to dest, starting from beginning */ +-static inline void sg_copy(u8 *dest, struct scatterlist *sg, unsigned int len) +-{ +- struct scatterlist *current_sg = sg; +- int cpy_index = 0, next_cpy_index = current_sg->length; +- +- while (next_cpy_index < len) { +- sg_map_copy(dest + cpy_index, current_sg, current_sg->length, +- current_sg->offset); +- current_sg = scatterwalk_sg_next(current_sg); +- cpy_index = next_cpy_index; +- next_cpy_index += current_sg->length; +- } +- if (cpy_index < len) +- sg_map_copy(dest + cpy_index, current_sg, len-cpy_index, +- current_sg->offset); +-} +- +-/* Copy sg data, from to_skip to end, to dest */ +-static inline void sg_copy_part(u8 *dest, struct scatterlist *sg, +- int to_skip, unsigned int end) +-{ +- struct scatterlist *current_sg = sg; +- int sg_index, cpy_index, offset; +- +- sg_index = current_sg->length; +- while (sg_index <= to_skip) { +- current_sg = scatterwalk_sg_next(current_sg); +- sg_index += current_sg->length; +- } +- cpy_index = sg_index - to_skip; +- offset = current_sg->offset + current_sg->length - cpy_index; +- sg_map_copy(dest, current_sg, cpy_index, offset); +- if (end - sg_index) { +- current_sg = scatterwalk_sg_next(current_sg); +- sg_copy(dest + cpy_index, current_sg, end - sg_index); +- } +-} +diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c +index f757a0f..3beed38 100644 +--- a/drivers/crypto/ixp4xx_crypto.c ++++ b/drivers/crypto/ixp4xx_crypto.c +@@ -904,7 +904,6 @@ static int ablk_perform(struct ablkcipher_request *req, int encrypt) + crypt->mode |= NPE_OP_NOT_IN_PLACE; + /* This was never tested by Intel + * for more than one dst buffer, I think. */ +- BUG_ON(req->dst->length < nbytes); + req_ctx->dst = NULL; + if (!chainup_buffers(dev, req->dst, nbytes, &dst_hook, + flags, DMA_FROM_DEVICE)) +diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c +index dde41f1d..d522396 100644 +--- a/drivers/crypto/omap-aes.c ++++ b/drivers/crypto/omap-aes.c +@@ -554,15 +554,23 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd) + return err; + } + +-static int omap_aes_check_aligned(struct scatterlist *sg) ++static int omap_aes_check_aligned(struct scatterlist *sg, int total) + { ++ int len = 0; ++ + while (sg) { + if (!IS_ALIGNED(sg->offset, 4)) + return -1; + if (!IS_ALIGNED(sg->length, AES_BLOCK_SIZE)) + return -1; ++ ++ len += sg->length; + sg = sg_next(sg); + } ++ ++ if (len != total) ++ return -1; ++ + return 0; + } + +@@ -633,8 +641,8 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd, + dd->in_sg = req->src; + dd->out_sg = req->dst; + +- if (omap_aes_check_aligned(dd->in_sg) || +- omap_aes_check_aligned(dd->out_sg)) { ++ if (omap_aes_check_aligned(dd->in_sg, dd->total) || ++ omap_aes_check_aligned(dd->out_sg, dd->total)) { + if (omap_aes_copy_sgs(dd)) + pr_err("Failed to copy SGs for unaligned cases\n"); + dd->sgs_copied = 1; +diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c +index 633ba94..c178ed8 100644 +--- a/drivers/crypto/padlock-aes.c ++++ b/drivers/crypto/padlock-aes.c +@@ -563,4 +563,4 @@ MODULE_DESCRIPTION("VIA PadLock AES algorithm support"); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Michal Ludvig"); + +-MODULE_ALIAS("aes"); ++MODULE_ALIAS_CRYPTO("aes"); +diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c +index 9266c0e..93d7753 100644 +--- a/drivers/crypto/padlock-sha.c ++++ b/drivers/crypto/padlock-sha.c +@@ -593,7 +593,7 @@ MODULE_DESCRIPTION("VIA PadLock SHA1/SHA256 algorithms support."); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Michal Ludvig"); + +-MODULE_ALIAS("sha1-all"); +-MODULE_ALIAS("sha256-all"); +-MODULE_ALIAS("sha1-padlock"); +-MODULE_ALIAS("sha256-padlock"); ++MODULE_ALIAS_CRYPTO("sha1-all"); ++MODULE_ALIAS_CRYPTO("sha256-all"); ++MODULE_ALIAS_CRYPTO("sha1-padlock"); ++MODULE_ALIAS_CRYPTO("sha256-padlock"); +diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c +index 5967667..1f35487 100644 +--- a/drivers/crypto/talitos.c ++++ b/drivers/crypto/talitos.c +@@ -927,7 +927,8 @@ static int sg_to_link_tbl(struct scatterlist *sg, int sg_count, + sg_count--; + link_tbl_ptr--; + } +- be16_add_cpu(&link_tbl_ptr->len, cryptlen); ++ link_tbl_ptr->len = cpu_to_be16(be16_to_cpu(link_tbl_ptr->len) ++ + cryptlen); + + /* tag end of link table */ + link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN; +@@ -2563,6 +2564,7 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, + break; + default: + dev_err(dev, "unknown algorithm type %d\n", t_alg->algt.type); ++ kfree(t_alg); + return ERR_PTR(-EINVAL); + } + +diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c +index a999f53..e4cea7c 100644 +--- a/drivers/crypto/ux500/cryp/cryp_core.c ++++ b/drivers/crypto/ux500/cryp/cryp_core.c +@@ -190,7 +190,7 @@ static void add_session_id(struct cryp_ctx *ctx) + static irqreturn_t cryp_interrupt_handler(int irq, void *param) + { + struct cryp_ctx *ctx; +- int i; ++ int count; + struct cryp_device_data *device_data; + + if (param == NULL) { +@@ -215,12 +215,11 @@ static irqreturn_t cryp_interrupt_handler(int irq, void *param) + if (cryp_pending_irq_src(device_data, + CRYP_IRQ_SRC_OUTPUT_FIFO)) { + if (ctx->outlen / ctx->blocksize > 0) { +- for (i = 0; i < ctx->blocksize / 4; i++) { +- *(ctx->outdata) = readl_relaxed( +- &device_data->base->dout); +- ctx->outdata += 4; +- ctx->outlen -= 4; +- } ++ count = ctx->blocksize / 4; ++ ++ readsl(&device_data->base->dout, ctx->outdata, count); ++ ctx->outdata += count; ++ ctx->outlen -= count; + + if (ctx->outlen == 0) { + cryp_disable_irq_src(device_data, +@@ -230,12 +229,12 @@ static irqreturn_t cryp_interrupt_handler(int irq, void *param) + } else if (cryp_pending_irq_src(device_data, + CRYP_IRQ_SRC_INPUT_FIFO)) { + if (ctx->datalen / ctx->blocksize > 0) { +- for (i = 0 ; i < ctx->blocksize / 4; i++) { +- writel_relaxed(ctx->indata, +- &device_data->base->din); +- ctx->indata += 4; +- ctx->datalen -= 4; +- } ++ count = ctx->blocksize / 4; ++ ++ writesl(&device_data->base->din, ctx->indata, count); ++ ++ ctx->indata += count; ++ ctx->datalen -= count; + + if (ctx->datalen == 0) + cryp_disable_irq_src(device_data, +@@ -1811,7 +1810,7 @@ module_exit(ux500_cryp_mod_fini); + module_param(cryp_mode, int, 0); + + MODULE_DESCRIPTION("Driver for ST-Ericsson UX500 CRYP crypto engine."); +-MODULE_ALIAS("aes-all"); +-MODULE_ALIAS("des-all"); ++MODULE_ALIAS_CRYPTO("aes-all"); ++MODULE_ALIAS_CRYPTO("des-all"); + + MODULE_LICENSE("GPL"); +diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c +index 1c73f4f..8e5e018 100644 +--- a/drivers/crypto/ux500/hash/hash_core.c ++++ b/drivers/crypto/ux500/hash/hash_core.c +@@ -1995,7 +1995,7 @@ module_exit(ux500_hash_mod_fini); + MODULE_DESCRIPTION("Driver for ST-Ericsson UX500 HASH engine."); + MODULE_LICENSE("GPL"); + +-MODULE_ALIAS("sha1-all"); +-MODULE_ALIAS("sha256-all"); +-MODULE_ALIAS("hmac-sha1-all"); +-MODULE_ALIAS("hmac-sha256-all"); ++MODULE_ALIAS_CRYPTO("sha1-all"); ++MODULE_ALIAS_CRYPTO("sha256-all"); ++MODULE_ALIAS_CRYPTO("hmac-sha1-all"); ++MODULE_ALIAS_CRYPTO("hmac-sha256-all"); +diff --git a/drivers/dma/TODO b/drivers/dma/TODO +index 734ed02..b8045cd 100644 +--- a/drivers/dma/TODO ++++ b/drivers/dma/TODO +@@ -7,7 +7,6 @@ TODO for slave dma + - imx-dma + - imx-sdma + - mxs-dma.c +- - dw_dmac + - intel_mid_dma + 4. Check other subsystems for dma drivers and merge/move to dmaengine + 5. Remove dma_slave_config's dma direction. +diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c +index 01a200c..b0972b3 100644 +--- a/drivers/dma/dw/core.c ++++ b/drivers/dma/dw/core.c +@@ -279,6 +279,15 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) + channel_set_bit(dw, CH_EN, dwc->mask); + } + ++static void dwc_dostart_first_queued(struct dw_dma_chan *dwc) ++{ ++ if (list_empty(&dwc->queue)) ++ return; ++ ++ list_move(dwc->queue.next, &dwc->active_list); ++ dwc_dostart(dwc, dwc_first_active(dwc)); ++} ++ + /*----------------------------------------------------------------------*/ + + static void +@@ -335,10 +344,7 @@ static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc) + * the completed ones. + */ + list_splice_init(&dwc->active_list, &list); +- if (!list_empty(&dwc->queue)) { +- list_move(dwc->queue.next, &dwc->active_list); +- dwc_dostart(dwc, dwc_first_active(dwc)); +- } ++ dwc_dostart_first_queued(dwc); + + spin_unlock_irqrestore(&dwc->lock, flags); + +@@ -467,10 +473,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) + /* Try to continue after resetting the channel... */ + dwc_chan_disable(dw, dwc); + +- if (!list_empty(&dwc->queue)) { +- list_move(dwc->queue.next, &dwc->active_list); +- dwc_dostart(dwc, dwc_first_active(dwc)); +- } ++ dwc_dostart_first_queued(dwc); + spin_unlock_irqrestore(&dwc->lock, flags); + } + +@@ -677,17 +680,9 @@ static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx) + * possible, perhaps even appending to those already submitted + * for DMA. But this is hard to do in a race-free manner. + */ +- if (list_empty(&dwc->active_list)) { +- dev_vdbg(chan2dev(tx->chan), "%s: started %u\n", __func__, +- desc->txd.cookie); +- list_add_tail(&desc->desc_node, &dwc->active_list); +- dwc_dostart(dwc, dwc_first_active(dwc)); +- } else { +- dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", __func__, +- desc->txd.cookie); + +- list_add_tail(&desc->desc_node, &dwc->queue); +- } ++ dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", __func__, desc->txd.cookie); ++ list_add_tail(&desc->desc_node, &dwc->queue); + + spin_unlock_irqrestore(&dwc->lock, flags); + +@@ -1092,9 +1087,12 @@ dwc_tx_status(struct dma_chan *chan, + static void dwc_issue_pending(struct dma_chan *chan) + { + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); ++ unsigned long flags; + +- if (!list_empty(&dwc->queue)) +- dwc_scan_descriptors(to_dw_dma(chan->device), dwc); ++ spin_lock_irqsave(&dwc->lock, flags); ++ if (list_empty(&dwc->active_list)) ++ dwc_dostart_first_queued(dwc); ++ spin_unlock_irqrestore(&dwc->lock, flags); + } + + static int dwc_alloc_chan_resources(struct dma_chan *chan) +diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c +index 453822c..fe8b0c9 100644 +--- a/drivers/dma/dw/platform.c ++++ b/drivers/dma/dw/platform.c +@@ -48,6 +48,8 @@ static bool dw_dma_of_filter(struct dma_chan *chan, void *param) + return true; + } + ++#define DRV_NAME "dw_dmac" ++ + static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) + { +@@ -293,7 +295,7 @@ static struct platform_driver dw_driver = { + .remove = dw_remove, + .shutdown = dw_shutdown, + .driver = { +- .name = "dw_dmac", ++ .name = DRV_NAME, + .pm = &dw_dev_pm_ops, + .of_match_table = of_match_ptr(dw_dma_of_id_table), + .acpi_match_table = ACPI_PTR(dw_dma_acpi_id_table), +@@ -314,3 +316,4 @@ module_exit(dw_exit); + + MODULE_LICENSE("GPL v2"); + MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller platform driver"); ++MODULE_ALIAS("platform:" DRV_NAME); +diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c +index 394cbc5..6b2f01d 100644 +--- a/drivers/dma/mv_xor.c ++++ b/drivers/dma/mv_xor.c +@@ -316,7 +316,8 @@ static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan) + dma_cookie_t cookie = 0; + int busy = mv_chan_is_busy(mv_chan); + u32 current_desc = mv_chan_get_current_desc(mv_chan); +- int seen_current = 0; ++ int current_cleaned = 0; ++ struct mv_xor_desc *hw_desc; + + dev_dbg(mv_chan_to_devp(mv_chan), "%s %d\n", __func__, __LINE__); + dev_dbg(mv_chan_to_devp(mv_chan), "current_desc %x\n", current_desc); +@@ -328,38 +329,57 @@ static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan) + + list_for_each_entry_safe(iter, _iter, &mv_chan->chain, + chain_node) { +- prefetch(_iter); +- prefetch(&_iter->async_tx); + +- /* do not advance past the current descriptor loaded into the +- * hardware channel, subsequent descriptors are either in +- * process or have not been submitted +- */ +- if (seen_current) +- break; ++ /* clean finished descriptors */ ++ hw_desc = iter->hw_desc; ++ if (hw_desc->status & XOR_DESC_SUCCESS) { ++ cookie = mv_xor_run_tx_complete_actions(iter, mv_chan, ++ cookie); + +- /* stop the search if we reach the current descriptor and the +- * channel is busy +- */ +- if (iter->async_tx.phys == current_desc) { +- seen_current = 1; +- if (busy) ++ /* done processing desc, clean slot */ ++ mv_xor_clean_slot(iter, mv_chan); ++ ++ /* break if we did cleaned the current */ ++ if (iter->async_tx.phys == current_desc) { ++ current_cleaned = 1; ++ break; ++ } ++ } else { ++ if (iter->async_tx.phys == current_desc) { ++ current_cleaned = 0; + break; ++ } + } +- +- cookie = mv_xor_run_tx_complete_actions(iter, mv_chan, cookie); +- +- if (mv_xor_clean_slot(iter, mv_chan)) +- break; + } + + if ((busy == 0) && !list_empty(&mv_chan->chain)) { +- struct mv_xor_desc_slot *chain_head; +- chain_head = list_entry(mv_chan->chain.next, +- struct mv_xor_desc_slot, +- chain_node); +- +- mv_xor_start_new_chain(mv_chan, chain_head); ++ if (current_cleaned) { ++ /* ++ * current descriptor cleaned and removed, run ++ * from list head ++ */ ++ iter = list_entry(mv_chan->chain.next, ++ struct mv_xor_desc_slot, ++ chain_node); ++ mv_xor_start_new_chain(mv_chan, iter); ++ } else { ++ if (!list_is_last(&iter->chain_node, &mv_chan->chain)) { ++ /* ++ * descriptors are still waiting after ++ * current, trigger them ++ */ ++ iter = list_entry(iter->chain_node.next, ++ struct mv_xor_desc_slot, ++ chain_node); ++ mv_xor_start_new_chain(mv_chan, iter); ++ } else { ++ /* ++ * some descriptors are still waiting ++ * to be cleaned ++ */ ++ tasklet_schedule(&mv_chan->irq_tasklet); ++ } ++ } + } + + if (cookie > 0) +diff --git a/drivers/dma/mv_xor.h b/drivers/dma/mv_xor.h +index d074922..5d14e4b 100644 +--- a/drivers/dma/mv_xor.h ++++ b/drivers/dma/mv_xor.h +@@ -33,6 +33,7 @@ + #define XOR_OPERATION_MODE_XOR 0 + #define XOR_OPERATION_MODE_MEMCPY 2 + #define XOR_DESCRIPTOR_SWAP BIT(14) ++#define XOR_DESC_SUCCESS 0x40000000 + + #define XOR_CURR_DESC(chan) (chan->mmr_high_base + 0x10 + (chan->idx * 4)) + #define XOR_NEXT_DESC(chan) (chan->mmr_high_base + 0x00 + (chan->idx * 4)) +diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c +index 362e7c4..12f8294 100644 +--- a/drivers/dma/omap-dma.c ++++ b/drivers/dma/omap-dma.c +@@ -487,6 +487,7 @@ static int omap_dma_terminate_all(struct omap_chan *c) + * c->desc is NULL and exit.) + */ + if (c->desc) { ++ omap_dma_desc_free(&c->desc->vd); + c->desc = NULL; + /* Avoid stopping the dma twice */ + if (!c->paused) +diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c +index 98e14ee..278603c 100644 +--- a/drivers/edac/amd64_edac.c ++++ b/drivers/edac/amd64_edac.c +@@ -2006,14 +2006,20 @@ static void __log_bus_error(struct mem_ctl_info *mci, struct err_info *err, + + static inline void decode_bus_error(int node_id, struct mce *m) + { +- struct mem_ctl_info *mci = mcis[node_id]; +- struct amd64_pvt *pvt = mci->pvt_info; ++ struct mem_ctl_info *mci; ++ struct amd64_pvt *pvt; + u8 ecc_type = (m->status >> 45) & 0x3; + u8 xec = XEC(m->status, 0x1f); + u16 ec = EC(m->status); + u64 sys_addr; + struct err_info err; + ++ mci = edac_mc_find(node_id); ++ if (!mci) ++ return; ++ ++ pvt = mci->pvt_info; ++ + /* Bail out early if this was an 'observed' error */ + if (PP(ec) == NBSL_PP_OBS) + return; +diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c +index df6575f..682288c 100644 +--- a/drivers/edac/cpc925_edac.c ++++ b/drivers/edac/cpc925_edac.c +@@ -562,7 +562,7 @@ static void cpc925_mc_check(struct mem_ctl_info *mci) + + if (apiexcp & UECC_EXCP_DETECTED) { + cpc925_mc_printk(mci, KERN_INFO, "DRAM UECC Fault\n"); +- edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, ++ edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, + pfn, offset, 0, + csrow, -1, -1, + mci->ctl_name, ""); +diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c +index 3cda79b..ece3aef 100644 +--- a/drivers/edac/e7xxx_edac.c ++++ b/drivers/edac/e7xxx_edac.c +@@ -226,7 +226,7 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) + static void process_ce_no_info(struct mem_ctl_info *mci) + { + edac_dbg(3, "\n"); +- edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, ++ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, + "e7xxx CE log register overflow", ""); + } + +diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c +index fa1326e..ad76f10 100644 +--- a/drivers/edac/i3200_edac.c ++++ b/drivers/edac/i3200_edac.c +@@ -242,11 +242,11 @@ static void i3200_process_error_info(struct mem_ctl_info *mci, + -1, -1, + "i3000 UE", ""); + } else if (log & I3200_ECCERRLOG_CE) { +- edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, ++ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, + 0, 0, eccerrlog_syndrome(log), + eccerrlog_row(channel, log), + -1, -1, +- "i3000 UE", ""); ++ "i3000 CE", ""); + } + } + } +diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c +index 3382f63..4382343 100644 +--- a/drivers/edac/i82860_edac.c ++++ b/drivers/edac/i82860_edac.c +@@ -124,7 +124,7 @@ static int i82860_process_error_info(struct mem_ctl_info *mci, + dimm->location[0], dimm->location[1], -1, + "i82860 UE", ""); + else +- edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, ++ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, + info->eap, 0, info->derrsyn, + dimm->location[0], dimm->location[1], -1, + "i82860 CE", ""); +diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c +index ef6b7e0..5c361f3 100644 +--- a/drivers/edac/ppc4xx_edac.c ++++ b/drivers/edac/ppc4xx_edac.c +@@ -921,7 +921,7 @@ static int ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) + */ + + for (row = 0; row < mci->nr_csrows; row++) { +- struct csrow_info *csi = &mci->csrows[row]; ++ struct csrow_info *csi = mci->csrows[row]; + + /* + * Get the configuration settings for this +diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c +index 54e2abe..3e623ab 100644 +--- a/drivers/edac/sb_edac.c ++++ b/drivers/edac/sb_edac.c +@@ -285,8 +285,9 @@ static const u32 correrrthrsld[] = { + * sbridge structs + */ + +-#define NUM_CHANNELS 4 +-#define MAX_DIMMS 3 /* Max DIMMS per channel */ ++#define NUM_CHANNELS 4 ++#define MAX_DIMMS 3 /* Max DIMMS per channel */ ++#define CHANNEL_UNSPECIFIED 0xf /* Intel IA32 SDM 15-14 */ + + enum type { + SANDY_BRIDGE, +@@ -764,7 +765,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + u32 reg; + u64 limit, prv = 0; + u64 tmp_mb; +- u32 mb, kb; ++ u32 gb, mb; + u32 rir_way; + + /* +@@ -774,15 +775,17 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + pvt->tolm = pvt->info.get_tolm(pvt); + tmp_mb = (1 + pvt->tolm) >> 20; + +- mb = div_u64_rem(tmp_mb, 1000, &kb); +- edac_dbg(0, "TOLM: %u.%03u GB (0x%016Lx)\n", mb, kb, (u64)pvt->tolm); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); ++ edac_dbg(0, "TOLM: %u.%03u GB (0x%016Lx)\n", ++ gb, (mb*1000)/1024, (u64)pvt->tolm); + + /* Address range is already 45:25 */ + pvt->tohm = pvt->info.get_tohm(pvt); + tmp_mb = (1 + pvt->tohm) >> 20; + +- mb = div_u64_rem(tmp_mb, 1000, &kb); +- edac_dbg(0, "TOHM: %u.%03u GB (0x%016Lx)\n", mb, kb, (u64)pvt->tohm); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); ++ edac_dbg(0, "TOHM: %u.%03u GB (0x%016Lx)\n", ++ gb, (mb*1000)/1024, (u64)pvt->tohm); + + /* + * Step 2) Get SAD range and SAD Interleave list +@@ -804,11 +807,11 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + break; + + tmp_mb = (limit + 1) >> 20; +- mb = div_u64_rem(tmp_mb, 1000, &kb); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); + edac_dbg(0, "SAD#%d %s up to %u.%03u GB (0x%016Lx) Interleave: %s reg=0x%08x\n", + n_sads, + get_dram_attr(reg), +- mb, kb, ++ gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, + INTERLEAVE_MODE(reg) ? "8:6" : "[8:6]XOR[18:16]", + reg); +@@ -839,9 +842,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + break; + tmp_mb = (limit + 1) >> 20; + +- mb = div_u64_rem(tmp_mb, 1000, &kb); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); + edac_dbg(0, "TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n", +- n_tads, mb, kb, ++ n_tads, gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, + (u32)TAD_SOCK(reg), + (u32)TAD_CH(reg), +@@ -864,10 +867,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + tad_ch_nilv_offset[j], + ®); + tmp_mb = TAD_OFFSET(reg) >> 20; +- mb = div_u64_rem(tmp_mb, 1000, &kb); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); + edac_dbg(0, "TAD CH#%d, offset #%d: %u.%03u GB (0x%016Lx), reg=0x%08x\n", + i, j, +- mb, kb, ++ gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, + reg); + } +@@ -889,10 +892,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + + tmp_mb = RIR_LIMIT(reg) >> 20; + rir_way = 1 << RIR_WAY(reg); +- mb = div_u64_rem(tmp_mb, 1000, &kb); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); + edac_dbg(0, "CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n", + i, j, +- mb, kb, ++ gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, + rir_way, + reg); +@@ -903,10 +906,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + ®); + tmp_mb = RIR_OFFSET(reg) << 6; + +- mb = div_u64_rem(tmp_mb, 1000, &kb); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); + edac_dbg(0, "CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n", + i, j, k, +- mb, kb, ++ gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, + (u32)RIR_RNK_TGT(reg), + reg); +@@ -944,7 +947,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, + u8 ch_way, sck_way, pkg, sad_ha = 0; + u32 tad_offset; + u32 rir_way; +- u32 mb, kb; ++ u32 mb, gb; + u64 ch_addr, offset, limit = 0, prv = 0; + + +@@ -1182,10 +1185,10 @@ static int get_memory_error_data(struct mem_ctl_info *mci, + continue; + + limit = RIR_LIMIT(reg); +- mb = div_u64_rem(limit >> 20, 1000, &kb); ++ gb = div_u64_rem(limit >> 20, 1024, &mb); + edac_dbg(0, "RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n", + n_rir, +- mb, kb, ++ gb, (mb*1000)/1024, + limit, + 1 << RIR_WAY(reg)); + if (ch_addr <= limit) +@@ -1750,6 +1753,9 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, + + /* FIXME: need support for channel mask */ + ++ if (channel == CHANNEL_UNSPECIFIED) ++ channel = -1; ++ + /* Call the helper to output message */ + edac_mc_handle_error(tp_event, mci, core_err_cnt, + m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0, +diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c +index d7d5c8a..6d44568 100644 +--- a/drivers/firewire/core-cdev.c ++++ b/drivers/firewire/core-cdev.c +@@ -1637,8 +1637,7 @@ static int dispatch_ioctl(struct client *client, + _IOC_SIZE(cmd) > sizeof(buffer)) + return -ENOTTY; + +- if (_IOC_DIR(cmd) == _IOC_READ) +- memset(&buffer, 0, _IOC_SIZE(cmd)); ++ memset(&buffer, 0, sizeof(buffer)); + + if (_IOC_DIR(cmd) & _IOC_WRITE) + if (copy_from_user(&buffer, arg, _IOC_SIZE(cmd))) +diff --git a/drivers/firmware/efi/runtime-map.c b/drivers/firmware/efi/runtime-map.c +index 97cdd16..c98b101 100644 +--- a/drivers/firmware/efi/runtime-map.c ++++ b/drivers/firmware/efi/runtime-map.c +@@ -170,7 +170,7 @@ int __init efi_runtime_map_init(struct kobject *efi_kobj) + + return 0; + out_add_entry: +- for (j = i - 1; j > 0; j--) { ++ for (j = i - 1; j >= 0; j--) { + entry = *(map_entries + j); + kobject_put(&entry->kobj); + } +diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c +index b22659c..e612552 100644 +--- a/drivers/firmware/efi/vars.c ++++ b/drivers/firmware/efi/vars.c +@@ -481,7 +481,7 @@ EXPORT_SYMBOL_GPL(efivar_entry_remove); + */ + static void efivar_entry_list_del_unlock(struct efivar_entry *entry) + { +- WARN_ON(!spin_is_locked(&__efivars->lock)); ++ lockdep_assert_held(&__efivars->lock); + + list_del(&entry->list); + spin_unlock_irq(&__efivars->lock); +@@ -507,7 +507,7 @@ int __efivar_entry_delete(struct efivar_entry *entry) + const struct efivar_operations *ops = __efivars->ops; + efi_status_t status; + +- WARN_ON(!spin_is_locked(&__efivars->lock)); ++ lockdep_assert_held(&__efivars->lock); + + status = ops->set_variable(entry->var.VariableName, + &entry->var.VendorGuid, +@@ -667,7 +667,7 @@ struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid, + int strsize1, strsize2; + bool found = false; + +- WARN_ON(!spin_is_locked(&__efivars->lock)); ++ lockdep_assert_held(&__efivars->lock); + + list_for_each_entry_safe(entry, n, head, list) { + strsize1 = ucs2_strsize(name, 1024); +@@ -739,7 +739,7 @@ int __efivar_entry_get(struct efivar_entry *entry, u32 *attributes, + const struct efivar_operations *ops = __efivars->ops; + efi_status_t status; + +- WARN_ON(!spin_is_locked(&__efivars->lock)); ++ lockdep_assert_held(&__efivars->lock); + + status = ops->get_variable(entry->var.VariableName, + &entry->var.VendorGuid, +diff --git a/drivers/gpio/gpio-kempld.c b/drivers/gpio/gpio-kempld.c +index c6d8817..fe6d4a1 100644 +--- a/drivers/gpio/gpio-kempld.c ++++ b/drivers/gpio/gpio-kempld.c +@@ -117,7 +117,7 @@ static int kempld_gpio_get_direction(struct gpio_chip *chip, unsigned offset) + = container_of(chip, struct kempld_gpio_data, chip); + struct kempld_device_data *pld = gpio->pld; + +- return kempld_gpio_get_bit(pld, KEMPLD_GPIO_DIR_NUM(offset), offset); ++ return !kempld_gpio_get_bit(pld, KEMPLD_GPIO_DIR_NUM(offset), offset); + } + + static int kempld_gpio_pincount(struct kempld_device_data *pld) +diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c +index 3b1fd1c..e9d8cf6 100644 +--- a/drivers/gpio/gpio-mvebu.c ++++ b/drivers/gpio/gpio-mvebu.c +@@ -304,11 +304,13 @@ static void mvebu_gpio_edge_irq_mask(struct irq_data *d) + { + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mvebu_gpio_chip *mvchip = gc->private; ++ struct irq_chip_type *ct = irq_data_get_chip_type(d); + u32 mask = 1 << (d->irq - gc->irq_base); + + irq_gc_lock(gc); +- gc->mask_cache &= ~mask; +- writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip)); ++ ct->mask_cache_priv &= ~mask; ++ ++ writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip)); + irq_gc_unlock(gc); + } + +@@ -316,11 +318,13 @@ static void mvebu_gpio_edge_irq_unmask(struct irq_data *d) + { + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mvebu_gpio_chip *mvchip = gc->private; ++ struct irq_chip_type *ct = irq_data_get_chip_type(d); ++ + u32 mask = 1 << (d->irq - gc->irq_base); + + irq_gc_lock(gc); +- gc->mask_cache |= mask; +- writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip)); ++ ct->mask_cache_priv |= mask; ++ writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_edge_mask(mvchip)); + irq_gc_unlock(gc); + } + +@@ -328,11 +332,13 @@ static void mvebu_gpio_level_irq_mask(struct irq_data *d) + { + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mvebu_gpio_chip *mvchip = gc->private; ++ struct irq_chip_type *ct = irq_data_get_chip_type(d); ++ + u32 mask = 1 << (d->irq - gc->irq_base); + + irq_gc_lock(gc); +- gc->mask_cache &= ~mask; +- writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip)); ++ ct->mask_cache_priv &= ~mask; ++ writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip)); + irq_gc_unlock(gc); + } + +@@ -340,11 +346,13 @@ static void mvebu_gpio_level_irq_unmask(struct irq_data *d) + { + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mvebu_gpio_chip *mvchip = gc->private; ++ struct irq_chip_type *ct = irq_data_get_chip_type(d); ++ + u32 mask = 1 << (d->irq - gc->irq_base); + + irq_gc_lock(gc); +- gc->mask_cache |= mask; +- writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip)); ++ ct->mask_cache_priv |= mask; ++ writel_relaxed(ct->mask_cache_priv, mvebu_gpioreg_level_mask(mvchip)); + irq_gc_unlock(gc); + } + +diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c +index 59ee486..6005d26 100644 +--- a/drivers/gpio/gpio-tps65912.c ++++ b/drivers/gpio/gpio-tps65912.c +@@ -26,9 +26,12 @@ struct tps65912_gpio_data { + struct gpio_chip gpio_chip; + }; + ++#define to_tgd(gc) container_of(gc, struct tps65912_gpio_data, gpio_chip) ++ + static int tps65912_gpio_get(struct gpio_chip *gc, unsigned offset) + { +- struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio); ++ struct tps65912_gpio_data *tps65912_gpio = to_tgd(gc); ++ struct tps65912 *tps65912 = tps65912_gpio->tps65912; + int val; + + val = tps65912_reg_read(tps65912, TPS65912_GPIO1 + offset); +@@ -42,7 +45,8 @@ static int tps65912_gpio_get(struct gpio_chip *gc, unsigned offset) + static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset, + int value) + { +- struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio); ++ struct tps65912_gpio_data *tps65912_gpio = to_tgd(gc); ++ struct tps65912 *tps65912 = tps65912_gpio->tps65912; + + if (value) + tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset, +@@ -55,7 +59,8 @@ static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset, + static int tps65912_gpio_output(struct gpio_chip *gc, unsigned offset, + int value) + { +- struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio); ++ struct tps65912_gpio_data *tps65912_gpio = to_tgd(gc); ++ struct tps65912 *tps65912 = tps65912_gpio->tps65912; + + /* Set the initial value */ + tps65912_gpio_set(gc, offset, value); +@@ -66,7 +71,8 @@ static int tps65912_gpio_output(struct gpio_chip *gc, unsigned offset, + + static int tps65912_gpio_input(struct gpio_chip *gc, unsigned offset) + { +- struct tps65912 *tps65912 = container_of(gc, struct tps65912, gpio); ++ struct tps65912_gpio_data *tps65912_gpio = to_tgd(gc); ++ struct tps65912 *tps65912 = tps65912_gpio->tps65912; + + return tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset, + GPIO_CFG_MASK); +diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c +index e0a98f5..d26028c 100644 +--- a/drivers/gpio/gpiolib-of.c ++++ b/drivers/gpio/gpiolib-of.c +@@ -44,8 +44,15 @@ static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data) + return false; + + ret = gc->of_xlate(gc, &gg_data->gpiospec, gg_data->flags); +- if (ret < 0) ++ if (ret < 0) { ++ /* We've found a gpio chip, but the translation failed. ++ * Store translation error in out_gpio. ++ * Return false to keep looking, as more than one gpio chip ++ * could be registered per of-node. ++ */ ++ gg_data->out_gpio = ERR_PTR(ret); + return false; ++ } + + gg_data->out_gpio = gpio_to_desc(ret + gc->base); + return true; +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index 50c4922..a03e18f 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -408,7 +408,7 @@ static ssize_t gpio_value_store(struct device *dev, + return status; + } + +-static const DEVICE_ATTR(value, 0644, ++static DEVICE_ATTR(value, 0644, + gpio_value_show, gpio_value_store); + + static irqreturn_t gpio_sysfs_irq(int irq, void *priv) +@@ -633,18 +633,16 @@ static ssize_t gpio_active_low_store(struct device *dev, + return status ? : size; + } + +-static const DEVICE_ATTR(active_low, 0644, ++static DEVICE_ATTR(active_low, 0644, + gpio_active_low_show, gpio_active_low_store); + +-static const struct attribute *gpio_attrs[] = { ++static struct attribute *gpio_attrs[] = { + &dev_attr_value.attr, + &dev_attr_active_low.attr, + NULL, + }; + +-static const struct attribute_group gpio_attr_group = { +- .attrs = (struct attribute **) gpio_attrs, +-}; ++ATTRIBUTE_GROUPS(gpio); + + /* + * /sys/class/gpio/gpiochipN/ +@@ -680,16 +678,13 @@ static ssize_t chip_ngpio_show(struct device *dev, + } + static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL); + +-static const struct attribute *gpiochip_attrs[] = { ++static struct attribute *gpiochip_attrs[] = { + &dev_attr_base.attr, + &dev_attr_label.attr, + &dev_attr_ngpio.attr, + NULL, + }; +- +-static const struct attribute_group gpiochip_attr_group = { +- .attrs = (struct attribute **) gpiochip_attrs, +-}; ++ATTRIBUTE_GROUPS(gpiochip); + + /* + * /sys/class/gpio/export ... write-only +@@ -805,6 +800,7 @@ static struct class gpio_class = { + */ + int gpiod_export(struct gpio_desc *desc, bool direction_may_change) + { ++ struct gpio_chip *chip; + unsigned long flags; + int status; + const char *ioname = NULL; +@@ -822,8 +818,16 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) + return -EINVAL; + } + ++ chip = desc->chip; ++ + mutex_lock(&sysfs_lock); + ++ /* check if chip is being removed */ ++ if (!chip || !chip->exported) { ++ status = -ENODEV; ++ goto fail_unlock; ++ } ++ + spin_lock_irqsave(&gpio_lock, flags); + if (!test_bit(FLAG_REQUESTED, &desc->flags) || + test_bit(FLAG_EXPORT, &desc->flags)) { +@@ -844,18 +848,15 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) + if (desc->chip->names && desc->chip->names[offset]) + ioname = desc->chip->names[offset]; + +- dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), +- desc, ioname ? ioname : "gpio%u", +- desc_to_gpio(desc)); ++ dev = device_create_with_groups(&gpio_class, desc->chip->dev, ++ MKDEV(0, 0), desc, gpio_groups, ++ ioname ? ioname : "gpio%u", ++ desc_to_gpio(desc)); + if (IS_ERR(dev)) { + status = PTR_ERR(dev); + goto fail_unlock; + } + +- status = sysfs_create_group(&dev->kobj, &gpio_attr_group); +- if (status) +- goto fail_unregister_device; +- + if (direction_may_change) { + status = device_create_file(dev, &dev_attr_direction); + if (status) +@@ -866,13 +867,15 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) + !test_bit(FLAG_IS_OUT, &desc->flags))) { + status = device_create_file(dev, &dev_attr_edge); + if (status) +- goto fail_unregister_device; ++ goto fail_remove_attr_direction; + } + + set_bit(FLAG_EXPORT, &desc->flags); + mutex_unlock(&sysfs_lock); + return 0; + ++fail_remove_attr_direction: ++ device_remove_file(dev, &dev_attr_direction); + fail_unregister_device: + device_unregister(dev); + fail_unlock: +@@ -917,6 +920,7 @@ int gpiod_export_link(struct device *dev, const char *name, + if (tdev != NULL) { + status = sysfs_create_link(&dev->kobj, &tdev->kobj, + name); ++ put_device(tdev); + } else { + status = -ENODEV; + } +@@ -964,7 +968,7 @@ int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value) + } + + status = sysfs_set_active_low(desc, dev, value); +- ++ put_device(dev); + unlock: + mutex_unlock(&sysfs_lock); + +@@ -1006,6 +1010,8 @@ void gpiod_unexport(struct gpio_desc *desc) + mutex_unlock(&sysfs_lock); + + if (dev) { ++ device_remove_file(dev, &dev_attr_edge); ++ device_remove_file(dev, &dev_attr_direction); + device_unregister(dev); + put_device(dev); + } +@@ -1030,13 +1036,13 @@ static int gpiochip_export(struct gpio_chip *chip) + + /* use chip->base for the ID; it's already known to be unique */ + mutex_lock(&sysfs_lock); +- dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip, +- "gpiochip%d", chip->base); +- if (!IS_ERR(dev)) { +- status = sysfs_create_group(&dev->kobj, +- &gpiochip_attr_group); +- } else ++ dev = device_create_with_groups(&gpio_class, chip->dev, MKDEV(0, 0), ++ chip, gpiochip_groups, ++ "gpiochip%d", chip->base); ++ if (IS_ERR(dev)) + status = PTR_ERR(dev); ++ else ++ status = 0; + chip->exported = (status == 0); + mutex_unlock(&sysfs_lock); + +@@ -1060,12 +1066,15 @@ static void gpiochip_unexport(struct gpio_chip *chip) + { + int status; + struct device *dev; ++ struct gpio_desc *desc; ++ unsigned int i; + + mutex_lock(&sysfs_lock); + dev = class_find_device(&gpio_class, NULL, chip, match_export); + if (dev) { + put_device(dev); + device_unregister(dev); ++ /* prevent further gpiod exports */ + chip->exported = false; + status = 0; + } else +@@ -1074,6 +1083,13 @@ static void gpiochip_unexport(struct gpio_chip *chip) + + if (status) + chip_dbg(chip, "%s: status %d\n", __func__, status); ++ ++ /* unregister gpiod class devices owned by sysfs */ ++ for (i = 0; i < chip->ngpio; i++) { ++ desc = &chip->desc[i]; ++ if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) ++ gpiod_free(desc); ++ } + } + + static int __init gpiolib_sysfs_init(void) +@@ -1222,6 +1238,9 @@ int gpiochip_add(struct gpio_chip *chip) + + spin_unlock_irqrestore(&gpio_lock, flags); + ++ if (status) ++ goto fail; ++ + #ifdef CONFIG_PINCTRL + INIT_LIST_HEAD(&chip->pin_ranges); + #endif +@@ -1229,12 +1248,12 @@ int gpiochip_add(struct gpio_chip *chip) + of_gpiochip_add(chip); + acpi_gpiochip_add(chip); + +- if (status) +- goto fail; +- + status = gpiochip_export(chip); +- if (status) ++ if (status) { ++ acpi_gpiochip_remove(chip); ++ of_gpiochip_remove(chip); + goto fail; ++ } + + pr_debug("%s: registered GPIOs %d to %d on device: %s\n", __func__, + chip->base, chip->base + chip->ngpio - 1, +@@ -1265,6 +1284,8 @@ int gpiochip_remove(struct gpio_chip *chip) + int status = 0; + unsigned id; + ++ gpiochip_unexport(chip); ++ + spin_lock_irqsave(&gpio_lock, flags); + + gpiochip_remove_pin_ranges(chip); +@@ -1286,9 +1307,6 @@ int gpiochip_remove(struct gpio_chip *chip) + + spin_unlock_irqrestore(&gpio_lock, flags); + +- if (status == 0) +- gpiochip_unexport(chip); +- + return status; + } + EXPORT_SYMBOL_GPL(gpiochip_remove); +@@ -1928,15 +1946,15 @@ EXPORT_SYMBOL_GPL(gpiod_is_active_low); + * that the GPIO was actually requested. + */ + +-static int _gpiod_get_raw_value(const struct gpio_desc *desc) ++static bool _gpiod_get_raw_value(const struct gpio_desc *desc) + { + struct gpio_chip *chip; +- int value; ++ bool value; + int offset; + + chip = desc->chip; + offset = gpio_chip_hwgpio(desc); +- value = chip->get ? chip->get(chip, offset) : 0; ++ value = chip->get ? chip->get(chip, offset) : false; + trace_gpio_value(desc_to_gpio(desc), 1, value); + return value; + } +@@ -1992,7 +2010,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_value); + * @desc: gpio descriptor whose state need to be set. + * @value: Non-zero for setting it HIGH otherise it will set to LOW. + */ +-static void _gpio_set_open_drain_value(struct gpio_desc *desc, int value) ++static void _gpio_set_open_drain_value(struct gpio_desc *desc, bool value) + { + int err = 0; + struct gpio_chip *chip = desc->chip; +@@ -2019,7 +2037,7 @@ static void _gpio_set_open_drain_value(struct gpio_desc *desc, int value) + * @desc: gpio descriptor whose state need to be set. + * @value: Non-zero for setting it HIGH otherise it will set to LOW. + */ +-static void _gpio_set_open_source_value(struct gpio_desc *desc, int value) ++static void _gpio_set_open_source_value(struct gpio_desc *desc, bool value) + { + int err = 0; + struct gpio_chip *chip = desc->chip; +@@ -2041,7 +2059,7 @@ static void _gpio_set_open_source_value(struct gpio_desc *desc, int value) + __func__, err); + } + +-static void _gpiod_set_raw_value(struct gpio_desc *desc, int value) ++static void _gpiod_set_raw_value(struct gpio_desc *desc, bool value) + { + struct gpio_chip *chip; + +diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c +index 50535fd..d830b38 100644 +--- a/drivers/gpu/drm/ast/ast_main.c ++++ b/drivers/gpu/drm/ast/ast_main.c +@@ -100,7 +100,7 @@ static int ast_detect_chip(struct drm_device *dev) + } + ast->vga2_clone = false; + } else { +- ast->chip = 2000; ++ ast->chip = AST2000; + DRM_INFO("AST 2000 detected\n"); + } + } +diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c +index cca063b..d2e56e9 100644 +--- a/drivers/gpu/drm/ast/ast_mode.c ++++ b/drivers/gpu/drm/ast/ast_mode.c +@@ -1012,8 +1012,8 @@ static u32 copy_cursor_image(u8 *src, u8 *dst, int width, int height) + srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0; + data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4); + data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); +- data32.b[2] = srcdata32[0].b[1] | (srcdata32[1].b[0] >> 4); +- data32.b[3] = srcdata32[0].b[3] | (srcdata32[1].b[2] >> 4); ++ data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4); ++ data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4); + + writel(data32.ul, dstxor); + csum += data32.ul; +diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c +index 08ce520..faa1f42 100644 +--- a/drivers/gpu/drm/cirrus/cirrus_drv.c ++++ b/drivers/gpu/drm/cirrus/cirrus_drv.c +@@ -32,6 +32,8 @@ static struct drm_driver driver; + static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { + { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, 0x1af4, 0x1100, 0, + 0, 0 }, ++ { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, PCI_VENDOR_ID_XEN, ++ 0x0001, 0, 0, 0 }, + {0,} + }; + +diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c +index 3b7d32d..903db3c 100644 +--- a/drivers/gpu/drm/drm_crtc.c ++++ b/drivers/gpu/drm/drm_crtc.c +@@ -2155,8 +2155,11 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + +- /* For some reason crtc x/y offsets are signed internally. */ +- if (crtc_req->x > INT_MAX || crtc_req->y > INT_MAX) ++ /* ++ * Universal plane src offsets are only 16.16, prevent havoc for ++ * drivers using universal plane code internally. ++ */ ++ if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000) + return -ERANGE; + + drm_modeset_lock_all(dev); +diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c +index 3ecb332..de5ab48 100644 +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -1426,10 +1426,13 @@ unlock: + out: + switch (ret) { + case -EIO: +- /* If this -EIO is due to a gpu hang, give the reset code a +- * chance to clean up the mess. Otherwise return the proper +- * SIGBUS. */ +- if (i915_terminally_wedged(&dev_priv->gpu_error)) { ++ /* ++ * We eat errors when the gpu is terminally wedged to avoid ++ * userspace unduly crashing (gl has no provisions for mmaps to ++ * fail). But any other -EIO isn't ours (e.g. swap in failure) ++ * and so needs to be reported. ++ */ ++ if (!i915_terminally_wedged(&dev_priv->gpu_error)) { + ret = VM_FAULT_SIGBUS; + break; + } +@@ -2890,6 +2893,13 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg, + u32 size = i915_gem_obj_ggtt_size(obj); + uint64_t val; + ++ /* Adjust fence size to match tiled area */ ++ if (obj->tiling_mode != I915_TILING_NONE) { ++ uint32_t row_size = obj->stride * ++ (obj->tiling_mode == I915_TILING_Y ? 32 : 8); ++ size = (size / row_size) * row_size; ++ } ++ + val = (uint64_t)((i915_gem_obj_ggtt_offset(obj) + size - 4096) & + 0xfffff000) << 32; + val |= i915_gem_obj_ggtt_offset(obj) & 0xfffff000; +@@ -4975,7 +4985,7 @@ static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task) + if (!mutex_is_locked(mutex)) + return false; + +-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES) ++#if defined(CONFIG_SMP) && !defined(CONFIG_DEBUG_MUTEXES) + return mutex->owner == task; + #else + /* Since UP may be pre-empted, we cannot assume that we own the lock */ +diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c +index d278be1..1855cdc 100644 +--- a/drivers/gpu/drm/i915/i915_gem_gtt.c ++++ b/drivers/gpu/drm/i915/i915_gem_gtt.c +@@ -827,6 +827,16 @@ void i915_check_and_clear_faults(struct drm_device *dev) + POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS])); + } + ++static void i915_ggtt_flush(struct drm_i915_private *dev_priv) ++{ ++ if (INTEL_INFO(dev_priv->dev)->gen < 6) { ++ intel_gtt_chipset_flush(); ++ } else { ++ I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); ++ POSTING_READ(GFX_FLSH_CNTL_GEN6); ++ } ++} ++ + void i915_gem_suspend_gtt_mappings(struct drm_device *dev) + { + struct drm_i915_private *dev_priv = dev->dev_private; +@@ -843,6 +853,8 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev) + dev_priv->gtt.base.start / PAGE_SIZE, + dev_priv->gtt.base.total / PAGE_SIZE, + true); ++ ++ i915_ggtt_flush(dev_priv); + } + + void i915_gem_restore_gtt_mappings(struct drm_device *dev) +@@ -863,7 +875,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) + i915_gem_gtt_bind_object(obj, obj->cache_level); + } + +- i915_gem_chipset_flush(dev); ++ i915_ggtt_flush(dev_priv); + } + + int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) +diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c +index 3c78b22..800e06c 100644 +--- a/drivers/gpu/drm/i915/i915_gem_stolen.c ++++ b/drivers/gpu/drm/i915/i915_gem_stolen.c +@@ -137,7 +137,11 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) + r = devm_request_mem_region(dev->dev, base + 1, + dev_priv->gtt.stolen_size - 1, + "Graphics Stolen Memory"); +- if (r == NULL) { ++ /* ++ * GEN3 firmware likes to smash pci bridges into the stolen ++ * range. Apparently this works. ++ */ ++ if (r == NULL && !IS_GEN3(dev)) { + DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n", + base, base + (uint32_t)dev_priv->gtt.stolen_size); + base = 0; +diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h +index 0a3b938..5b38bf8 100644 +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -320,6 +320,7 @@ + #define PIPE_CONTROL_GLOBAL_GTT_IVB (1<<24) /* gen7+ */ + #define PIPE_CONTROL_CS_STALL (1<<20) + #define PIPE_CONTROL_TLB_INVALIDATE (1<<18) ++#define PIPE_CONTROL_MEDIA_STATE_CLEAR (1<<16) + #define PIPE_CONTROL_QW_WRITE (1<<14) + #define PIPE_CONTROL_DEPTH_STALL (1<<13) + #define PIPE_CONTROL_WRITE_FLUSH (1<<12) +@@ -1180,6 +1181,7 @@ + #define GMBUS_CYCLE_INDEX (2<<25) + #define GMBUS_CYCLE_STOP (4<<25) + #define GMBUS_BYTE_COUNT_SHIFT 16 ++#define GMBUS_BYTE_COUNT_MAX 256U + #define GMBUS_SLAVE_INDEX_SHIFT 8 + #define GMBUS_SLAVE_ADDR_SHIFT 1 + #define GMBUS_SLAVE_READ (1<<0) +diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c +index f220419..08105fd 100644 +--- a/drivers/gpu/drm/i915/intel_bios.c ++++ b/drivers/gpu/drm/i915/intel_bios.c +@@ -839,7 +839,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) + } + } + +-static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id) ++static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id) + { + DRM_DEBUG_KMS("Falling back to manually reading VBT from " + "VBIOS ROM for %s\n", +diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c +index b19ddac..8348475 100644 +--- a/drivers/gpu/drm/i915/intel_crt.c ++++ b/drivers/gpu/drm/i915/intel_crt.c +@@ -750,7 +750,7 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = { + .destroy = intel_encoder_destroy, + }; + +-static int __init intel_no_crt_dmi_callback(const struct dmi_system_id *id) ++static int intel_no_crt_dmi_callback(const struct dmi_system_id *id) + { + DRM_INFO("Skipping CRT initialization for %s\n", id->ident); + return 1; +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index b6fb3eb..c514690 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -3817,7 +3817,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) + ironlake_fdi_disable(crtc); + + ironlake_disable_pch_transcoder(dev_priv, pipe); +- intel_set_pch_fifo_underrun_reporting(dev, pipe, true); + + if (HAS_PCH_CPT(dev)) { + /* disable TRANS_DP_CTL */ +@@ -3883,7 +3882,6 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) + + if (intel_crtc->config.has_pch_encoder) { + lpt_disable_pch_transcoder(dev_priv); +- intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true); + intel_ddi_fdi_disable(crtc); + } + +diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c +index b2d0887..462307c 100644 +--- a/drivers/gpu/drm/i915/intel_dp.c ++++ b/drivers/gpu/drm/i915/intel_dp.c +@@ -481,10 +481,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, + DP_AUX_CH_CTL_RECEIVE_ERROR)) + continue; + if (status & DP_AUX_CH_CTL_DONE) +- break; ++ goto done; + } +- if (status & DP_AUX_CH_CTL_DONE) +- break; + } + + if ((status & DP_AUX_CH_CTL_DONE) == 0) { +@@ -493,6 +491,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, + goto out; + } + ++done: + /* Check for timeout or receive error. + * Timeouts occur when the sink is not connected + */ +diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c +index d33b61d..81f8ec8 100644 +--- a/drivers/gpu/drm/i915/intel_i2c.c ++++ b/drivers/gpu/drm/i915/intel_i2c.c +@@ -324,18 +324,17 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv) + } + + static int +-gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, +- u32 gmbus1_index) ++gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv, ++ unsigned short addr, u8 *buf, unsigned int len, ++ u32 gmbus1_index) + { + int reg_offset = dev_priv->gpio_mmio_base; +- u16 len = msg->len; +- u8 *buf = msg->buf; + + I915_WRITE(GMBUS1 + reg_offset, + gmbus1_index | + GMBUS_CYCLE_WAIT | + (len << GMBUS_BYTE_COUNT_SHIFT) | +- (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) | ++ (addr << GMBUS_SLAVE_ADDR_SHIFT) | + GMBUS_SLAVE_READ | GMBUS_SW_RDY); + while (len) { + int ret; +@@ -357,11 +356,35 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, + } + + static int +-gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) ++gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, ++ u32 gmbus1_index) + { +- int reg_offset = dev_priv->gpio_mmio_base; +- u16 len = msg->len; + u8 *buf = msg->buf; ++ unsigned int rx_size = msg->len; ++ unsigned int len; ++ int ret; ++ ++ do { ++ len = min(rx_size, GMBUS_BYTE_COUNT_MAX); ++ ++ ret = gmbus_xfer_read_chunk(dev_priv, msg->addr, ++ buf, len, gmbus1_index); ++ if (ret) ++ return ret; ++ ++ rx_size -= len; ++ buf += len; ++ } while (rx_size != 0); ++ ++ return 0; ++} ++ ++static int ++gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv, ++ unsigned short addr, u8 *buf, unsigned int len) ++{ ++ int reg_offset = dev_priv->gpio_mmio_base; ++ unsigned int chunk_size = len; + u32 val, loop; + + val = loop = 0; +@@ -373,8 +396,8 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) + I915_WRITE(GMBUS3 + reg_offset, val); + I915_WRITE(GMBUS1 + reg_offset, + GMBUS_CYCLE_WAIT | +- (msg->len << GMBUS_BYTE_COUNT_SHIFT) | +- (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) | ++ (chunk_size << GMBUS_BYTE_COUNT_SHIFT) | ++ (addr << GMBUS_SLAVE_ADDR_SHIFT) | + GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); + while (len) { + int ret; +@@ -391,6 +414,29 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) + if (ret) + return ret; + } ++ ++ return 0; ++} ++ ++static int ++gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) ++{ ++ u8 *buf = msg->buf; ++ unsigned int tx_size = msg->len; ++ unsigned int len; ++ int ret; ++ ++ do { ++ len = min(tx_size, GMBUS_BYTE_COUNT_MAX); ++ ++ ret = gmbus_xfer_write_chunk(dev_priv, msg->addr, buf, len); ++ if (ret) ++ return ret; ++ ++ buf += len; ++ tx_size -= len; ++ } while (tx_size != 0); ++ + return 0; + } + +@@ -443,7 +489,7 @@ gmbus_xfer(struct i2c_adapter *adapter, + struct intel_gmbus, + adapter); + struct drm_i915_private *dev_priv = bus->dev_priv; +- int i, reg_offset; ++ int i = 0, inc, try = 0, reg_offset; + int ret = 0; + + intel_aux_display_runtime_get(dev_priv); +@@ -456,12 +502,14 @@ gmbus_xfer(struct i2c_adapter *adapter, + + reg_offset = dev_priv->gpio_mmio_base; + ++retry: + I915_WRITE(GMBUS0 + reg_offset, bus->reg0); + +- for (i = 0; i < num; i++) { ++ for (; i < num; i += inc) { ++ inc = 1; + if (gmbus_is_index_read(msgs, i, num)) { + ret = gmbus_xfer_index_read(dev_priv, &msgs[i]); +- i += 1; /* set i to the index of the read xfer */ ++ inc = 2; /* an index read is two msgs */ + } else if (msgs[i].flags & I2C_M_RD) { + ret = gmbus_xfer_read(dev_priv, &msgs[i], 0); + } else { +@@ -533,6 +581,18 @@ clear_err: + adapter->name, msgs[i].addr, + (msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len); + ++ /* ++ * Passive adapters sometimes NAK the first probe. Retry the first ++ * message once on -ENXIO for GMBUS transfers; the bit banging algorithm ++ * has retries internally. See also the retry loop in ++ * drm_do_probe_ddc_edid, which bails out on the first -ENXIO. ++ */ ++ if (ret == -ENXIO && i == 0 && try++ == 0) { ++ DRM_DEBUG_KMS("GMBUS [%s] NAK on first message, retry\n", ++ adapter->name); ++ goto retry; ++ } ++ + goto out; + + timeout: +diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c +index eb8f64b..1eb4994 100644 +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -544,7 +544,7 @@ static const struct drm_encoder_funcs intel_lvds_enc_funcs = { + .destroy = intel_encoder_destroy, + }; + +-static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id) ++static int intel_no_lvds_dmi_callback(const struct dmi_system_id *id) + { + DRM_INFO("Skipping LVDS initialization for %s\n", id->ident); + return 1; +@@ -815,12 +815,28 @@ static int intel_dual_link_lvds_callback(const struct dmi_system_id *id) + static const struct dmi_system_id intel_dual_link_lvds[] = { + { + .callback = intel_dual_link_lvds_callback, +- .ident = "Apple MacBook Pro (Core i5/i7 Series)", ++ .ident = "Apple MacBook Pro 15\" (2010)", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6,2"), ++ }, ++ }, ++ { ++ .callback = intel_dual_link_lvds_callback, ++ .ident = "Apple MacBook Pro 15\" (2011)", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"), + }, + }, ++ { ++ .callback = intel_dual_link_lvds_callback, ++ .ident = "Apple MacBook Pro 15\" (2012)", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro9,1"), ++ }, ++ }, + { } /* terminating entry */ + }; + +@@ -905,6 +921,17 @@ void intel_lvds_init(struct drm_device *dev) + int pipe; + u8 pin; + ++ /* ++ * Unlock registers and just leave them unlocked. Do this before ++ * checking quirk lists to avoid bogus WARNINGs. ++ */ ++ if (HAS_PCH_SPLIT(dev)) { ++ I915_WRITE(PCH_PP_CONTROL, ++ I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); ++ } else { ++ I915_WRITE(PP_CONTROL, ++ I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); ++ } + if (!intel_lvds_supported(dev)) + return; + +@@ -1099,17 +1126,6 @@ out: + DRM_DEBUG_KMS("detected %s-link lvds configuration\n", + lvds_encoder->is_dual_link ? "dual" : "single"); + +- /* +- * Unlock registers and just +- * leave them unlocked +- */ +- if (HAS_PCH_SPLIT(dev)) { +- I915_WRITE(PCH_PP_CONTROL, +- I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS); +- } else { +- I915_WRITE(PP_CONTROL, +- I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); +- } + lvds_connector->lid_notifier.notifier_call = intel_lid_notify; + if (acpi_lid_notifier_register(&lvds_connector->lid_notifier)) { + DRM_DEBUG_KMS("lid notifier registration failed\n"); +diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c +index fd98bec..c6d9777 100644 +--- a/drivers/gpu/drm/i915/intel_panel.c ++++ b/drivers/gpu/drm/i915/intel_panel.c +@@ -645,7 +645,7 @@ static void pch_enable_backlight(struct intel_connector *connector) + + cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); + if (cpu_ctl2 & BLM_PWM_ENABLE) { +- WARN(1, "cpu backlight already enabled\n"); ++ DRM_DEBUG_KMS("cpu backlight already enabled\n"); + cpu_ctl2 &= ~BLM_PWM_ENABLE; + I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); + } +@@ -693,7 +693,7 @@ static void i9xx_enable_backlight(struct intel_connector *connector) + + ctl = I915_READ(BLC_PWM_CTL); + if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) { +- WARN(1, "backlight already enabled\n"); ++ DRM_DEBUG_KMS("backlight already enabled\n"); + I915_WRITE(BLC_PWM_CTL, 0); + } + +@@ -724,7 +724,7 @@ static void i965_enable_backlight(struct intel_connector *connector) + + ctl2 = I915_READ(BLC_PWM_CTL2); + if (ctl2 & BLM_PWM_ENABLE) { +- WARN(1, "backlight already enabled\n"); ++ DRM_DEBUG_KMS("backlight already enabled\n"); + ctl2 &= ~BLM_PWM_ENABLE; + I915_WRITE(BLC_PWM_CTL2, ctl2); + } +@@ -758,7 +758,7 @@ static void vlv_enable_backlight(struct intel_connector *connector) + + ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe)); + if (ctl2 & BLM_PWM_ENABLE) { +- WARN(1, "backlight already enabled\n"); ++ DRM_DEBUG_KMS("backlight already enabled\n"); + ctl2 &= ~BLM_PWM_ENABLE; + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); + } +diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c +index 31b36c5..d2af1e1 100644 +--- a/drivers/gpu/drm/i915/intel_ringbuffer.c ++++ b/drivers/gpu/drm/i915/intel_ringbuffer.c +@@ -334,12 +334,15 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring, + flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; + flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; ++ flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR; + /* + * TLB invalidate requires a post-sync write. + */ + flags |= PIPE_CONTROL_QW_WRITE; + flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; + ++ flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; ++ + /* Workaround: we must issue a pipe_control with CS-stall bit + * set before a pipe_control command that has the state cache + * invalidate bit set. */ +@@ -475,6 +478,9 @@ static int init_ring_common(struct intel_ring_buffer *ring) + } + } + ++ /* Enforce ordering by reading HEAD register back */ ++ I915_READ_HEAD(ring); ++ + /* Initialize the ring. This must happen _after_ we've cleared the ring + * registers with the above sequence (the readback of the HEAD registers + * also enforces ordering), otherwise the hw might lose the new ring +diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c +index 365c7c4..9c9606c 100644 +--- a/drivers/gpu/drm/i915/intel_tv.c ++++ b/drivers/gpu/drm/i915/intel_tv.c +@@ -854,6 +854,10 @@ intel_enable_tv(struct intel_encoder *encoder) + struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + ++ /* Prevents vblank waits from timing out in intel_tv_detect_type() */ ++ intel_wait_for_vblank(encoder->base.dev, ++ to_intel_crtc(encoder->base.crtc)->pipe); ++ + I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE); + } + +diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c +index c879631..b6c063c 100644 +--- a/drivers/gpu/drm/i915/intel_uncore.c ++++ b/drivers/gpu/drm/i915/intel_uncore.c +@@ -451,8 +451,8 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg) + static void + assert_device_not_suspended(struct drm_i915_private *dev_priv) + { +- WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended, +- "Device suspended\n"); ++ WARN_ONCE(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended, ++ "Device suspended\n"); + } + + #define REG_READ_HEADER(x) \ +diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c +index 9683747..f2511a0 100644 +--- a/drivers/gpu/drm/mgag200/mgag200_mode.c ++++ b/drivers/gpu/drm/mgag200/mgag200_mode.c +@@ -1529,6 +1529,11 @@ static int mga_vga_mode_valid(struct drm_connector *connector, + return MODE_BANDWIDTH; + } + ++ if ((mode->hdisplay % 8) != 0 || (mode->hsync_start % 8) != 0 || ++ (mode->hsync_end % 8) != 0 || (mode->htotal % 8) != 0) { ++ return MODE_H_ILLEGAL; ++ } ++ + if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 || + mode->crtc_hsync_end > 4096 || mode->crtc_htotal > 4096 || + mode->crtc_vdisplay > 2048 || mode->crtc_vsync_start > 4096 || +diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +index 461df93..4f32b34 100644 +--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c ++++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +@@ -35,8 +35,6 @@ + A3XX_INT0_CP_AHB_ERROR_HALT | \ + A3XX_INT0_UCHE_OOB_ACCESS) + +-static struct platform_device *a3xx_pdev; +- + static void a3xx_me_init(struct msm_gpu *gpu) + { + struct msm_ringbuffer *ring = gpu->rb; +@@ -311,7 +309,6 @@ static void a3xx_destroy(struct msm_gpu *gpu) + ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl); + #endif + +- put_device(&a3xx_gpu->pdev->dev); + kfree(a3xx_gpu); + } + +@@ -439,7 +436,8 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) + struct a3xx_gpu *a3xx_gpu = NULL; + struct adreno_gpu *adreno_gpu; + struct msm_gpu *gpu; +- struct platform_device *pdev = a3xx_pdev; ++ struct msm_drm_private *priv = dev->dev_private; ++ struct platform_device *pdev = priv->gpu_pdev; + struct adreno_platform_config *config; + int ret; + +@@ -460,7 +458,6 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) + adreno_gpu = &a3xx_gpu->base; + gpu = &adreno_gpu->base; + +- get_device(&pdev->dev); + a3xx_gpu->pdev = pdev; + + gpu->fast_rate = config->fast_rate; +@@ -522,17 +519,24 @@ fail: + # include + #endif + +-static int a3xx_probe(struct platform_device *pdev) ++static void set_gpu_pdev(struct drm_device *dev, ++ struct platform_device *pdev) ++{ ++ struct msm_drm_private *priv = dev->dev_private; ++ priv->gpu_pdev = pdev; ++} ++ ++static int a3xx_bind(struct device *dev, struct device *master, void *data) + { + static struct adreno_platform_config config = {}; + #ifdef CONFIG_OF +- struct device_node *child, *node = pdev->dev.of_node; ++ struct device_node *child, *node = dev->of_node; + u32 val; + int ret; + + ret = of_property_read_u32(node, "qcom,chipid", &val); + if (ret) { +- dev_err(&pdev->dev, "could not find chipid: %d\n", ret); ++ dev_err(dev, "could not find chipid: %d\n", ret); + return ret; + } + +@@ -548,7 +552,7 @@ static int a3xx_probe(struct platform_device *pdev) + for_each_child_of_node(child, pwrlvl) { + ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val); + if (ret) { +- dev_err(&pdev->dev, "could not find gpu-freq: %d\n", ret); ++ dev_err(dev, "could not find gpu-freq: %d\n", ret); + return ret; + } + config.fast_rate = max(config.fast_rate, val); +@@ -558,12 +562,12 @@ static int a3xx_probe(struct platform_device *pdev) + } + + if (!config.fast_rate) { +- dev_err(&pdev->dev, "could not find clk rates\n"); ++ dev_err(dev, "could not find clk rates\n"); + return -ENXIO; + } + + #else +- struct kgsl_device_platform_data *pdata = pdev->dev.platform_data; ++ struct kgsl_device_platform_data *pdata = dev->platform_data; + uint32_t version = socinfo_get_version(); + if (cpu_is_apq8064ab()) { + config.fast_rate = 450000000; +@@ -609,14 +613,30 @@ static int a3xx_probe(struct platform_device *pdev) + config.bus_scale_table = pdata->bus_scale_table; + # endif + #endif +- pdev->dev.platform_data = &config; +- a3xx_pdev = pdev; ++ dev->platform_data = &config; ++ set_gpu_pdev(dev_get_drvdata(master), to_platform_device(dev)); + return 0; + } + ++static void a3xx_unbind(struct device *dev, struct device *master, ++ void *data) ++{ ++ set_gpu_pdev(dev_get_drvdata(master), NULL); ++} ++ ++static const struct component_ops a3xx_ops = { ++ .bind = a3xx_bind, ++ .unbind = a3xx_unbind, ++}; ++ ++static int a3xx_probe(struct platform_device *pdev) ++{ ++ return component_add(&pdev->dev, &a3xx_ops); ++} ++ + static int a3xx_remove(struct platform_device *pdev) + { +- a3xx_pdev = NULL; ++ component_del(&pdev->dev, &a3xx_ops); + return 0; + } + +@@ -624,7 +644,6 @@ static const struct of_device_id dt_match[] = { + { .compatible = "qcom,kgsl-3d0" }, + {} + }; +-MODULE_DEVICE_TABLE(of, dt_match); + + static struct platform_driver a3xx_driver = { + .probe = a3xx_probe, +diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c +index 6f1588a..8a04a1d 100644 +--- a/drivers/gpu/drm/msm/hdmi/hdmi.c ++++ b/drivers/gpu/drm/msm/hdmi/hdmi.c +@@ -17,8 +17,6 @@ + + #include "hdmi.h" + +-static struct platform_device *hdmi_pdev; +- + void hdmi_set_mode(struct hdmi *hdmi, bool power_on) + { + uint32_t ctrl = 0; +@@ -75,7 +73,7 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder) + { + struct hdmi *hdmi = NULL; + struct msm_drm_private *priv = dev->dev_private; +- struct platform_device *pdev = hdmi_pdev; ++ struct platform_device *pdev = priv->hdmi_pdev; + struct hdmi_platform_config *config; + int i, ret; + +@@ -95,8 +93,6 @@ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder) + + kref_init(&hdmi->refcount); + +- get_device(&pdev->dev); +- + hdmi->dev = dev; + hdmi->pdev = pdev; + hdmi->config = config; +@@ -249,17 +245,24 @@ fail: + + #include + +-static int hdmi_dev_probe(struct platform_device *pdev) ++static void set_hdmi_pdev(struct drm_device *dev, ++ struct platform_device *pdev) ++{ ++ struct msm_drm_private *priv = dev->dev_private; ++ priv->hdmi_pdev = pdev; ++} ++ ++static int hdmi_bind(struct device *dev, struct device *master, void *data) + { + static struct hdmi_platform_config config = {}; + #ifdef CONFIG_OF +- struct device_node *of_node = pdev->dev.of_node; ++ struct device_node *of_node = dev->of_node; + + int get_gpio(const char *name) + { + int gpio = of_get_named_gpio(of_node, name, 0); + if (gpio < 0) { +- dev_err(&pdev->dev, "failed to get gpio: %s (%d)\n", ++ dev_err(dev, "failed to get gpio: %s (%d)\n", + name, gpio); + gpio = -1; + } +@@ -336,14 +339,30 @@ static int hdmi_dev_probe(struct platform_device *pdev) + config.mux_sel_gpio = -1; + } + #endif +- pdev->dev.platform_data = &config; +- hdmi_pdev = pdev; ++ dev->platform_data = &config; ++ set_hdmi_pdev(dev_get_drvdata(master), to_platform_device(dev)); + return 0; + } + ++static void hdmi_unbind(struct device *dev, struct device *master, ++ void *data) ++{ ++ set_hdmi_pdev(dev_get_drvdata(master), NULL); ++} ++ ++static const struct component_ops hdmi_ops = { ++ .bind = hdmi_bind, ++ .unbind = hdmi_unbind, ++}; ++ ++static int hdmi_dev_probe(struct platform_device *pdev) ++{ ++ return component_add(&pdev->dev, &hdmi_ops); ++} ++ + static int hdmi_dev_remove(struct platform_device *pdev) + { +- hdmi_pdev = NULL; ++ component_del(&pdev->dev, &hdmi_ops); + return 0; + } + +@@ -351,7 +370,6 @@ static const struct of_device_id dt_match[] = { + { .compatible = "qcom,hdmi-tx" }, + {} + }; +-MODULE_DEVICE_TABLE(of, dt_match); + + static struct platform_driver hdmi_driver = { + .probe = hdmi_dev_probe, +diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c +index e6adafc..e79cfd0 100644 +--- a/drivers/gpu/drm/msm/msm_drv.c ++++ b/drivers/gpu/drm/msm/msm_drv.c +@@ -56,6 +56,10 @@ static char *vram; + MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU"); + module_param(vram, charp, 0); + ++/* ++ * Util/helpers: ++ */ ++ + void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, + const char *dbgname) + { +@@ -143,6 +147,8 @@ static int msm_unload(struct drm_device *dev) + priv->vram.paddr, &attrs); + } + ++ component_unbind_all(dev->dev, dev); ++ + dev->dev_private = NULL; + + kfree(priv); +@@ -175,6 +181,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags) + struct msm_kms *kms; + int ret; + ++ + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + dev_err(dev->dev, "failed to allocate private data\n"); +@@ -226,6 +233,13 @@ static int msm_load(struct drm_device *dev, unsigned long flags) + (uint32_t)(priv->vram.paddr + size)); + } + ++ platform_set_drvdata(pdev, dev); ++ ++ /* Bind all our sub-components: */ ++ ret = component_bind_all(dev->dev, dev); ++ if (ret) ++ return ret; ++ + switch (get_mdp_ver(pdev)) { + case 4: + kms = mdp4_kms_init(dev); +@@ -281,8 +295,6 @@ static int msm_load(struct drm_device *dev, unsigned long flags) + goto fail; + } + +- platform_set_drvdata(pdev, dev); +- + #ifdef CONFIG_DRM_MSM_FBDEV + priv->fbdev = msm_fbdev_init(dev); + #endif +@@ -819,18 +831,110 @@ static const struct dev_pm_ops msm_pm_ops = { + }; + + /* ++ * Componentized driver support: ++ */ ++ ++#ifdef CONFIG_OF ++/* NOTE: the CONFIG_OF case duplicates the same code as exynos or imx ++ * (or probably any other).. so probably some room for some helpers ++ */ ++static int compare_of(struct device *dev, void *data) ++{ ++ return dev->of_node == data; ++} ++ ++static int msm_drm_add_components(struct device *master, struct master *m) ++{ ++ struct device_node *np = master->of_node; ++ unsigned i; ++ int ret; ++ ++ for (i = 0; ; i++) { ++ struct device_node *node; ++ ++ node = of_parse_phandle(np, "connectors", i); ++ if (!node) ++ break; ++ ++ ret = component_master_add_child(m, compare_of, node); ++ of_node_put(node); ++ ++ if (ret) ++ return ret; ++ } ++ return 0; ++} ++#else ++static int compare_dev(struct device *dev, void *data) ++{ ++ return dev == data; ++} ++ ++static int msm_drm_add_components(struct device *master, struct master *m) ++{ ++ /* For non-DT case, it kinda sucks. We don't actually have a way ++ * to know whether or not we are waiting for certain devices (or if ++ * they are simply not present). But for non-DT we only need to ++ * care about apq8064/apq8060/etc (all mdp4/a3xx): ++ */ ++ static const char *devnames[] = { ++ "hdmi_msm.0", "kgsl-3d0.0", ++ }; ++ int i; ++ ++ DBG("Adding components.."); ++ ++ for (i = 0; i < ARRAY_SIZE(devnames); i++) { ++ struct device *dev; ++ int ret; ++ ++ dev = bus_find_device_by_name(&platform_bus_type, ++ NULL, devnames[i]); ++ if (!dev) { ++ dev_info(master, "still waiting for %s\n", devnames[i]); ++ return -EPROBE_DEFER; ++ } ++ ++ ret = component_master_add_child(m, compare_dev, dev); ++ if (ret) { ++ DBG("could not add child: %d", ret); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++#endif ++ ++static int msm_drm_bind(struct device *dev) ++{ ++ return drm_platform_init(&msm_driver, to_platform_device(dev)); ++} ++ ++static void msm_drm_unbind(struct device *dev) ++{ ++ drm_put_dev(platform_get_drvdata(to_platform_device(dev))); ++} ++ ++static const struct component_master_ops msm_drm_ops = { ++ .add_components = msm_drm_add_components, ++ .bind = msm_drm_bind, ++ .unbind = msm_drm_unbind, ++}; ++ ++/* + * Platform driver: + */ + + static int msm_pdev_probe(struct platform_device *pdev) + { + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); +- return drm_platform_init(&msm_driver, pdev); ++ return component_master_add(&pdev->dev, &msm_drm_ops); + } + + static int msm_pdev_remove(struct platform_device *pdev) + { +- drm_put_dev(platform_get_drvdata(pdev)); ++ component_master_del(&pdev->dev, &msm_drm_ops); + + return 0; + } +diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h +index 3d63269..9d10ee0 100644 +--- a/drivers/gpu/drm/msm/msm_drv.h ++++ b/drivers/gpu/drm/msm/msm_drv.h +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -69,6 +70,9 @@ struct msm_drm_private { + + struct msm_kms *kms; + ++ /* subordinate devices, if present: */ ++ struct platform_device *hdmi_pdev, *gpu_pdev; ++ + /* when we have more than one 'msm_gpu' these need to be an array: */ + struct msm_gpu *gpu; + struct msm_file_private *lastctx; +diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c +index 2d9b9d7..f3edd28 100644 +--- a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c ++++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c +@@ -124,6 +124,7 @@ dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len, + struct dcb_output *outp) + { + u16 dcb = dcb_outp(bios, idx, ver, len); ++ memset(outp, 0x00, sizeof(*outp)); + if (dcb) { + if (*ver >= 0x20) { + u32 conn = nv_ro32(bios, dcb + 0x00); +diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c +index a75c35c..165401c 100644 +--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c ++++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c +@@ -24,13 +24,6 @@ + + #include "nv04.h" + +-static void +-nv4c_mc_msi_rearm(struct nouveau_mc *pmc) +-{ +- struct nv04_mc_priv *priv = (void *)pmc; +- nv_wr08(priv, 0x088050, 0xff); +-} +- + struct nouveau_oclass * + nv4c_mc_oclass = &(struct nouveau_mc_oclass) { + .base.handle = NV_SUBDEV(MC, 0x4c), +@@ -41,5 +34,4 @@ nv4c_mc_oclass = &(struct nouveau_mc_oclass) { + .fini = _nouveau_mc_fini, + }, + .intr = nv04_mc_intr, +- .msi_rearm = nv4c_mc_msi_rearm, + }.base; +diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h +index 23ca7a5..74ed08a 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_drm.h ++++ b/drivers/gpu/drm/nouveau/nouveau_drm.h +@@ -10,7 +10,7 @@ + + #define DRIVER_MAJOR 1 + #define DRIVER_MINOR 1 +-#define DRIVER_PATCHLEVEL 1 ++#define DRIVER_PATCHLEVEL 2 + + /* + * 1.1.1: +@@ -21,6 +21,8 @@ + * to control registers on the MPs to enable performance counters, + * and to control the warp error enable mask (OpenGL requires out of + * bounds access to local memory to be silently ignored / return 0). ++ * 1.1.2: ++ * - fixes multiple bugs in flip completion events and timestamping + */ + + #include +diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c +index 471347e..a92fb01 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_vga.c ++++ b/drivers/gpu/drm/nouveau/nouveau_vga.c +@@ -100,7 +100,16 @@ void + nouveau_vga_fini(struct nouveau_drm *drm) + { + struct drm_device *dev = drm->dev; ++ bool runtime = false; ++ ++ if (nouveau_runtime_pm == 1) ++ runtime = true; ++ if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm())) ++ runtime = true; ++ + vga_switcheroo_unregister_client(dev->pdev); ++ if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus()) ++ vga_switcheroo_fini_domain_pm_ops(drm->dev->dev); + vga_client_register(dev->pdev, NULL, NULL, NULL); + } + +diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +index f926b4c..56c6055 100644 +--- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c ++++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +@@ -199,7 +199,7 @@ static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm) + static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area, + struct page **pages, uint32_t npages, uint32_t roll) + { +- dma_addr_t pat_pa = 0; ++ dma_addr_t pat_pa = 0, data_pa = 0; + uint32_t *data; + struct pat *pat; + struct refill_engine *engine = txn->engine_handle; +@@ -223,7 +223,9 @@ static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area, + .lut_id = engine->tcm->lut_id, + }; + +- data = alloc_dma(txn, 4*i, &pat->data_pa); ++ data = alloc_dma(txn, 4*i, &data_pa); ++ /* FIXME: what if data_pa is more than 32-bit ? */ ++ pat->data_pa = data_pa; + + while (i--) { + int n = i + roll; +diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c +index 5aec3e8..5fd3bab 100644 +--- a/drivers/gpu/drm/omapdrm/omap_gem.c ++++ b/drivers/gpu/drm/omapdrm/omap_gem.c +@@ -791,7 +791,7 @@ int omap_gem_get_paddr(struct drm_gem_object *obj, + omap_obj->paddr = tiler_ssptr(block); + omap_obj->block = block; + +- DBG("got paddr: %08x", omap_obj->paddr); ++ DBG("got paddr: %pad", &omap_obj->paddr); + } + + omap_obj->paddr_cnt++; +@@ -988,9 +988,9 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) + + off = drm_vma_node_start(&obj->vma_node); + +- seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d", ++ seq_printf(m, "%08x: %2d (%2d) %08llx %pad (%2d) %p %4d", + omap_obj->flags, obj->name, obj->refcount.refcount.counter, +- off, omap_obj->paddr, omap_obj->paddr_cnt, ++ off, &omap_obj->paddr, omap_obj->paddr_cnt, + omap_obj->vaddr, omap_obj->roll); + + if (omap_obj->flags & OMAP_BO_TILED) { +@@ -1468,8 +1468,8 @@ void omap_gem_init(struct drm_device *dev) + entry->paddr = tiler_ssptr(block); + entry->block = block; + +- DBG("%d:%d: %dx%d: paddr=%08x stride=%d", i, j, w, h, +- entry->paddr, ++ DBG("%d:%d: %dx%d: paddr=%pad stride=%d", i, j, w, h, ++ &entry->paddr, + usergart[i].stride_pfn << PAGE_SHIFT); + } + } +diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c +index 046d5e6..5b62e21 100644 +--- a/drivers/gpu/drm/omapdrm/omap_plane.c ++++ b/drivers/gpu/drm/omapdrm/omap_plane.c +@@ -142,8 +142,8 @@ static void omap_plane_pre_apply(struct omap_drm_apply *apply) + DBG("%dx%d -> %dx%d (%d)", info->width, info->height, + info->out_width, info->out_height, + info->screen_width); +- DBG("%d,%d %08x %08x", info->pos_x, info->pos_y, +- info->paddr, info->p_uv_addr); ++ DBG("%d,%d %pad %pad", info->pos_x, info->pos_y, ++ &info->paddr, &info->p_uv_addr); + + /* TODO: */ + ilace = false; +diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c +index eb89653..c5e96a3 100644 +--- a/drivers/gpu/drm/qxl/qxl_cmd.c ++++ b/drivers/gpu/drm/qxl/qxl_cmd.c +@@ -505,6 +505,7 @@ int qxl_hw_surface_alloc(struct qxl_device *qdev, + + cmd = (struct qxl_surface_cmd *)qxl_release_map(qdev, release); + cmd->type = QXL_SURFACE_CMD_CREATE; ++ cmd->flags = QXL_SURF_FLAG_KEEP_DATA; + cmd->u.surface_create.format = surf->surf.format; + cmd->u.surface_create.width = surf->surf.width; + cmd->u.surface_create.height = surf->surf.height; +diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c +index 798bde2..8e3267a 100644 +--- a/drivers/gpu/drm/qxl/qxl_display.c ++++ b/drivers/gpu/drm/qxl/qxl_display.c +@@ -136,9 +136,35 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector, + *pwidth = head->width; + *pheight = head->height; + drm_mode_probed_add(connector, mode); ++ /* remember the last custom size for mode validation */ ++ qdev->monitors_config_width = mode->hdisplay; ++ qdev->monitors_config_height = mode->vdisplay; + return 1; + } + ++static struct mode_size { ++ int w; ++ int h; ++} common_modes[] = { ++ { 640, 480}, ++ { 720, 480}, ++ { 800, 600}, ++ { 848, 480}, ++ {1024, 768}, ++ {1152, 768}, ++ {1280, 720}, ++ {1280, 800}, ++ {1280, 854}, ++ {1280, 960}, ++ {1280, 1024}, ++ {1440, 900}, ++ {1400, 1050}, ++ {1680, 1050}, ++ {1600, 1200}, ++ {1920, 1080}, ++ {1920, 1200} ++}; ++ + static int qxl_add_common_modes(struct drm_connector *connector, + unsigned pwidth, + unsigned pheight) +@@ -146,29 +172,6 @@ static int qxl_add_common_modes(struct drm_connector *connector, + struct drm_device *dev = connector->dev; + struct drm_display_mode *mode = NULL; + int i; +- struct mode_size { +- int w; +- int h; +- } common_modes[] = { +- { 640, 480}, +- { 720, 480}, +- { 800, 600}, +- { 848, 480}, +- {1024, 768}, +- {1152, 768}, +- {1280, 720}, +- {1280, 800}, +- {1280, 854}, +- {1280, 960}, +- {1280, 1024}, +- {1440, 900}, +- {1400, 1050}, +- {1680, 1050}, +- {1600, 1200}, +- {1920, 1080}, +- {1920, 1200} +- }; +- + for (i = 0; i < ARRAY_SIZE(common_modes); i++) { + mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, + 60, false, false, false); +@@ -523,7 +526,6 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc, + struct qxl_framebuffer *qfb; + struct qxl_bo *bo, *old_bo = NULL; + struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); +- uint32_t width, height, base_offset; + bool recreate_primary = false; + int ret; + int surf_id; +@@ -553,9 +555,10 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc, + if (qcrtc->index == 0) + recreate_primary = true; + +- width = mode->hdisplay; +- height = mode->vdisplay; +- base_offset = 0; ++ if (bo->surf.stride * bo->surf.height > qdev->vram_size) { ++ DRM_ERROR("Mode doesn't fit in vram size (vgamem)"); ++ return -EINVAL; ++ } + + ret = qxl_bo_reserve(bo, false); + if (ret != 0) +@@ -569,10 +572,10 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc, + if (recreate_primary) { + qxl_io_destroy_primary(qdev); + qxl_io_log(qdev, +- "recreate primary: %dx%d (was %dx%d,%d,%d)\n", +- width, height, bo->surf.width, +- bo->surf.height, bo->surf.stride, bo->surf.format); +- qxl_io_create_primary(qdev, base_offset, bo); ++ "recreate primary: %dx%d,%d,%d\n", ++ bo->surf.width, bo->surf.height, ++ bo->surf.stride, bo->surf.format); ++ qxl_io_create_primary(qdev, 0, bo); + bo->is_primary = true; + surf_id = 0; + } else { +@@ -753,11 +756,22 @@ static int qxl_conn_get_modes(struct drm_connector *connector) + static int qxl_conn_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) + { ++ struct drm_device *ddev = connector->dev; ++ struct qxl_device *qdev = ddev->dev_private; ++ int i; ++ + /* TODO: is this called for user defined modes? (xrandr --add-mode) + * TODO: check that the mode fits in the framebuffer */ +- DRM_DEBUG("%s: %dx%d status=%d\n", mode->name, mode->hdisplay, +- mode->vdisplay, mode->status); +- return MODE_OK; ++ ++ if(qdev->monitors_config_width == mode->hdisplay && ++ qdev->monitors_config_height == mode->vdisplay) ++ return MODE_OK; ++ ++ for (i = 0; i < ARRAY_SIZE(common_modes); i++) { ++ if (common_modes[i].w == mode->hdisplay && common_modes[i].h == mode->vdisplay) ++ return MODE_OK; ++ } ++ return MODE_BAD; + } + + static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector) +diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h +index 36ed40b..8aa077c 100644 +--- a/drivers/gpu/drm/qxl/qxl_drv.h ++++ b/drivers/gpu/drm/qxl/qxl_drv.h +@@ -325,6 +325,8 @@ struct qxl_device { + struct work_struct fb_work; + + struct drm_property *hotplug_mode_update_property; ++ int monitors_config_width; ++ int monitors_config_height; + }; + + /* forward declaration for QXL_INFO_IO */ +diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c +index 0bb86e6..56a13a9 100644 +--- a/drivers/gpu/drm/qxl/qxl_ioctl.c ++++ b/drivers/gpu/drm/qxl/qxl_ioctl.c +@@ -122,8 +122,10 @@ static struct qxl_bo *qxlhw_handle_to_bo(struct qxl_device *qdev, + qobj = gem_to_qxl_bo(gobj); + + ret = qxl_release_list_add(release, qobj); +- if (ret) ++ if (ret) { ++ drm_gem_object_unreference_unlocked(gobj); + return NULL; ++ } + + return qobj; + } +diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c +index 0cca5f2..0db3e20 100644 +--- a/drivers/gpu/drm/radeon/atombios_crtc.c ++++ b/drivers/gpu/drm/radeon/atombios_crtc.c +@@ -330,8 +330,10 @@ atombios_set_crtc_dtd_timing(struct drm_crtc *crtc, + misc |= ATOM_COMPOSITESYNC; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + misc |= ATOM_INTERLACE; +- if (mode->flags & DRM_MODE_FLAG_DBLSCAN) ++ if (mode->flags & DRM_MODE_FLAG_DBLCLK) + misc |= ATOM_DOUBLE_CLOCK_MODE; ++ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) ++ misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2; + + args.susModeMiscInfo.usAccess = cpu_to_le16(misc); + args.ucCRTC = radeon_crtc->crtc_id; +@@ -374,8 +376,10 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc, + misc |= ATOM_COMPOSITESYNC; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + misc |= ATOM_INTERLACE; +- if (mode->flags & DRM_MODE_FLAG_DBLSCAN) ++ if (mode->flags & DRM_MODE_FLAG_DBLCLK) + misc |= ATOM_DOUBLE_CLOCK_MODE; ++ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) ++ misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2; + + args.susModeMiscInfo.usAccess = cpu_to_le16(misc); + args.ucCRTC = radeon_crtc->crtc_id; +@@ -1306,6 +1310,9 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, + (x << 16) | y); + viewport_w = crtc->mode.hdisplay; + viewport_h = (crtc->mode.vdisplay + 1) & ~1; ++ if ((rdev->family >= CHIP_BONAIRE) && ++ (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)) ++ viewport_h *= 2; + WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, + (viewport_w << 16) | viewport_h); + +diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c +index 5727dbd..b4dbaded 100644 +--- a/drivers/gpu/drm/radeon/atombios_dp.c ++++ b/drivers/gpu/drm/radeon/atombios_dp.c +@@ -576,6 +576,10 @@ int radeon_dp_mode_valid_helper(struct drm_connector *connector, + struct radeon_connector_atom_dig *dig_connector; + int dp_clock; + ++ if ((mode->clock > 340000) && ++ (!radeon_connector_is_dp12_capable(connector))) ++ return MODE_CLOCK_HIGH; ++ + if (!radeon_connector->con_priv) + return MODE_CLOCK_HIGH; + dig_connector = radeon_connector->con_priv; +diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c +index 5fa854c..c7c2856 100644 +--- a/drivers/gpu/drm/radeon/ci_dpm.c ++++ b/drivers/gpu/drm/radeon/ci_dpm.c +@@ -851,6 +851,9 @@ static int ci_set_thermal_temperature_range(struct radeon_device *rdev, + WREG32_SMC(CG_THERMAL_CTRL, tmp); + #endif + ++ rdev->pm.dpm.thermal.min_temp = low_temp; ++ rdev->pm.dpm.thermal.max_temp = high_temp; ++ + return 0; + } + +@@ -922,7 +925,18 @@ static void ci_get_leakage_voltages(struct radeon_device *rdev) + pi->vddc_leakage.count = 0; + pi->vddci_leakage.count = 0; + +- if (radeon_atom_get_leakage_id_from_vbios(rdev, &leakage_id) == 0) { ++ if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) { ++ for (i = 0; i < CISLANDS_MAX_LEAKAGE_COUNT; i++) { ++ virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; ++ if (radeon_atom_get_voltage_evv(rdev, virtual_voltage_id, &vddc) != 0) ++ continue; ++ if (vddc != 0 && vddc != virtual_voltage_id) { ++ pi->vddc_leakage.actual_voltage[pi->vddc_leakage.count] = vddc; ++ pi->vddc_leakage.leakage_id[pi->vddc_leakage.count] = virtual_voltage_id; ++ pi->vddc_leakage.count++; ++ } ++ } ++ } else if (radeon_atom_get_leakage_id_from_vbios(rdev, &leakage_id) == 0) { + for (i = 0; i < CISLANDS_MAX_LEAKAGE_COUNT; i++) { + virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; + if (radeon_atom_get_leakage_vddc_based_on_leakage_params(rdev, &vddc, &vddci, +@@ -4719,7 +4733,7 @@ void ci_dpm_disable(struct radeon_device *rdev) + ci_enable_spread_spectrum(rdev, false); + ci_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, false); + ci_stop_dpm(rdev); +- ci_enable_ds_master_switch(rdev, true); ++ ci_enable_ds_master_switch(rdev, false); + ci_enable_ulv(rdev, false); + ci_clear_vc(rdev); + ci_reset_to_default(rdev); +diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c +index 270f68a..2fd2fb3 100644 +--- a/drivers/gpu/drm/radeon/cik.c ++++ b/drivers/gpu/drm/radeon/cik.c +@@ -2219,6 +2219,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev) + gb_tile_moden = 0; + break; + } ++ rdev->config.cik.macrotile_mode_array[reg_offset] = gb_tile_moden; + WREG32(GB_MACROTILE_MODE0 + (reg_offset * 4), gb_tile_moden); + } + } else if (num_pipe_configs == 8) { +@@ -3230,6 +3231,7 @@ static void cik_gpu_init(struct radeon_device *rdev) + (rdev->pdev->device == 0x130B) || + (rdev->pdev->device == 0x130E) || + (rdev->pdev->device == 0x1315) || ++ (rdev->pdev->device == 0x1318) || + (rdev->pdev->device == 0x131B)) { + rdev->config.cik.max_cu_per_sh = 4; + rdev->config.cik.max_backends_per_se = 1; +@@ -3556,7 +3558,21 @@ void cik_fence_gfx_ring_emit(struct radeon_device *rdev, + struct radeon_ring *ring = &rdev->ring[fence->ring]; + u64 addr = rdev->fence_drv[fence->ring].gpu_addr; + +- /* EVENT_WRITE_EOP - flush caches, send int */ ++ /* Workaround for cache flush problems. First send a dummy EOP ++ * event down the pipe with seq one below. ++ */ ++ radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); ++ radeon_ring_write(ring, (EOP_TCL1_ACTION_EN | ++ EOP_TC_ACTION_EN | ++ EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) | ++ EVENT_INDEX(5))); ++ radeon_ring_write(ring, addr & 0xfffffffc); ++ radeon_ring_write(ring, (upper_32_bits(addr) & 0xffff) | ++ DATA_SEL(1) | INT_SEL(0)); ++ radeon_ring_write(ring, fence->seq - 1); ++ radeon_ring_write(ring, 0); ++ ++ /* Then send the real EOP event down the pipe. */ + radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); + radeon_ring_write(ring, (EOP_TCL1_ACTION_EN | + EOP_TC_ACTION_EN | +@@ -3934,8 +3950,8 @@ static int cik_cp_gfx_start(struct radeon_device *rdev) + /* init the CE partitions. CE only used for gfx on CIK */ + radeon_ring_write(ring, PACKET3(PACKET3_SET_BASE, 2)); + radeon_ring_write(ring, PACKET3_BASE_INDEX(CE_PARTITION_BASE)); +- radeon_ring_write(ring, 0xc000); +- radeon_ring_write(ring, 0xc000); ++ radeon_ring_write(ring, 0x8000); ++ radeon_ring_write(ring, 0x8000); + + /* setup clear context state */ + radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); +@@ -4132,6 +4148,31 @@ void cik_compute_set_wptr(struct radeon_device *rdev, + WDOORBELL32(ring->doorbell_index, ring->wptr); + } + ++static void cik_compute_stop(struct radeon_device *rdev, ++ struct radeon_ring *ring) ++{ ++ u32 j, tmp; ++ ++ cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0); ++ /* Disable wptr polling. */ ++ tmp = RREG32(CP_PQ_WPTR_POLL_CNTL); ++ tmp &= ~WPTR_POLL_EN; ++ WREG32(CP_PQ_WPTR_POLL_CNTL, tmp); ++ /* Disable HQD. */ ++ if (RREG32(CP_HQD_ACTIVE) & 1) { ++ WREG32(CP_HQD_DEQUEUE_REQUEST, 1); ++ for (j = 0; j < rdev->usec_timeout; j++) { ++ if (!(RREG32(CP_HQD_ACTIVE) & 1)) ++ break; ++ udelay(1); ++ } ++ WREG32(CP_HQD_DEQUEUE_REQUEST, 0); ++ WREG32(CP_HQD_PQ_RPTR, 0); ++ WREG32(CP_HQD_PQ_WPTR, 0); ++ } ++ cik_srbm_select(rdev, 0, 0, 0, 0); ++} ++ + /** + * cik_cp_compute_enable - enable/disable the compute CP MEs + * +@@ -4145,6 +4186,15 @@ static void cik_cp_compute_enable(struct radeon_device *rdev, bool enable) + if (enable) + WREG32(CP_MEC_CNTL, 0); + else { ++ /* ++ * To make hibernation reliable we need to clear compute ring ++ * configuration before halting the compute ring. ++ */ ++ mutex_lock(&rdev->srbm_mutex); ++ cik_compute_stop(rdev,&rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]); ++ cik_compute_stop(rdev,&rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]); ++ mutex_unlock(&rdev->srbm_mutex); ++ + WREG32(CP_MEC_CNTL, (MEC_ME1_HALT | MEC_ME2_HALT)); + rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; + rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; +@@ -4390,7 +4440,7 @@ struct bonaire_mqd + */ + static int cik_cp_compute_resume(struct radeon_device *rdev) + { +- int r, i, idx; ++ int r, i, j, idx; + u32 tmp; + bool use_doorbell = true; + u64 hqd_gpu_addr; +@@ -4509,7 +4559,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev) + mqd->queue_state.cp_hqd_pq_wptr= 0; + if (RREG32(CP_HQD_ACTIVE) & 1) { + WREG32(CP_HQD_DEQUEUE_REQUEST, 1); +- for (i = 0; i < rdev->usec_timeout; i++) { ++ for (j = 0; j < rdev->usec_timeout; j++) { + if (!(RREG32(CP_HQD_ACTIVE) & 1)) + break; + udelay(1); +@@ -5344,7 +5394,7 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev) + */ + /* set vm size, must be a multiple of 4 */ + WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0); +- WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn); ++ WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn - 1); + for (i = 1; i < 16; i++) { + if (i < 8) + WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), +@@ -5543,12 +5593,13 @@ static void cik_vm_decode_fault(struct radeon_device *rdev, + void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) + { + struct radeon_ring *ring = &rdev->ring[ridx]; ++ int usepfp = (ridx == RADEON_RING_TYPE_GFX_INDEX); + + if (vm == NULL) + return; + + radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); +- radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | ++ radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) | + WRITE_DATA_DST_SEL(0))); + if (vm->id < 8) { + radeon_ring_write(ring, +@@ -5598,7 +5649,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) + radeon_ring_write(ring, 1 << vm->id); + + /* compute doesn't have PFP */ +- if (ridx == RADEON_RING_TYPE_GFX_INDEX) { ++ if (usepfp) { + /* sync PFP to ME, otherwise we might get invalid PFP reads */ + radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); + radeon_ring_write(ring, 0x0); +@@ -5876,6 +5927,7 @@ static void cik_enable_mgcg(struct radeon_device *rdev, bool enable) + } + + orig = data = RREG32(RLC_CGTT_MGCG_OVERRIDE); ++ data |= 0x00000001; + data &= 0xfffffffd; + if (orig != data) + WREG32(RLC_CGTT_MGCG_OVERRIDE, data); +@@ -5907,7 +5959,7 @@ static void cik_enable_mgcg(struct radeon_device *rdev, bool enable) + } + } else { + orig = data = RREG32(RLC_CGTT_MGCG_OVERRIDE); +- data |= 0x00000002; ++ data |= 0x00000003; + if (orig != data) + WREG32(RLC_CGTT_MGCG_OVERRIDE, data); + +@@ -6805,7 +6857,6 @@ int cik_irq_set(struct radeon_device *rdev) + u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; + u32 grbm_int_cntl = 0; + u32 dma_cntl, dma_cntl1; +- u32 thermal_int; + + if (!rdev->irq.installed) { + WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); +@@ -6842,13 +6893,6 @@ int cik_irq_set(struct radeon_device *rdev) + cp_m2p2 = RREG32(CP_ME2_PIPE2_INT_CNTL) & ~TIME_STAMP_INT_ENABLE; + cp_m2p3 = RREG32(CP_ME2_PIPE3_INT_CNTL) & ~TIME_STAMP_INT_ENABLE; + +- if (rdev->flags & RADEON_IS_IGP) +- thermal_int = RREG32_SMC(CG_THERMAL_INT_CTRL) & +- ~(THERM_INTH_MASK | THERM_INTL_MASK); +- else +- thermal_int = RREG32_SMC(CG_THERMAL_INT) & +- ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); +- + /* enable CP interrupts on all rings */ + if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { + DRM_DEBUG("cik_irq_set: sw int gfx\n"); +@@ -7006,14 +7050,6 @@ int cik_irq_set(struct radeon_device *rdev) + hpd6 |= DC_HPDx_INT_EN; + } + +- if (rdev->irq.dpm_thermal) { +- DRM_DEBUG("dpm thermal\n"); +- if (rdev->flags & RADEON_IS_IGP) +- thermal_int |= THERM_INTH_MASK | THERM_INTL_MASK; +- else +- thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW; +- } +- + WREG32(CP_INT_CNTL_RING0, cp_int_cntl); + + WREG32(SDMA0_CNTL + SDMA0_REGISTER_OFFSET, dma_cntl); +@@ -7067,10 +7103,8 @@ int cik_irq_set(struct radeon_device *rdev) + WREG32(DC_HPD5_INT_CONTROL, hpd5); + WREG32(DC_HPD6_INT_CONTROL, hpd6); + +- if (rdev->flags & RADEON_IS_IGP) +- WREG32_SMC(CG_THERMAL_INT_CTRL, thermal_int); +- else +- WREG32_SMC(CG_THERMAL_INT, thermal_int); ++ /* posting read */ ++ RREG32(SRBM_STATUS); + + return 0; + } +@@ -7270,6 +7304,7 @@ static inline u32 cik_get_ih_wptr(struct radeon_device *rdev) + tmp = RREG32(IH_RB_CNTL); + tmp |= IH_WPTR_OVERFLOW_CLEAR; + WREG32(IH_RB_CNTL, tmp); ++ wptr &= ~RB_OVERFLOW; + } + return (wptr & rdev->ih.ptr_mask); + } +@@ -7776,6 +7811,7 @@ restart_ih: + static int cik_startup(struct radeon_device *rdev) + { + struct radeon_ring *ring; ++ u32 nop; + int r; + + /* enable pcie gen2/3 link */ +@@ -7893,9 +7929,15 @@ static int cik_startup(struct radeon_device *rdev) + } + cik_irq_set(rdev); + ++ if (rdev->family == CHIP_HAWAII) { ++ nop = RADEON_CP_PACKET2; ++ } else { ++ nop = PACKET3(PACKET3_NOP, 0x3FFF); ++ } ++ + ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, +- PACKET3(PACKET3_NOP, 0x3FFF)); ++ nop); + if (r) + return r; + +@@ -7903,7 +7945,7 @@ static int cik_startup(struct radeon_device *rdev) + /* type-2 packets are deprecated on MEC, use type-3 instead */ + ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET, +- PACKET3(PACKET3_NOP, 0x3FFF)); ++ nop); + if (r) + return r; + ring->me = 1; /* first MEC */ +@@ -7914,7 +7956,7 @@ static int cik_startup(struct radeon_device *rdev) + /* type-2 packets are deprecated on MEC, use type-3 instead */ + ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]; + r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET, +- PACKET3(PACKET3_NOP, 0x3FFF)); ++ nop); + if (r) + return r; + /* dGPU only have 1 MEC */ +@@ -8882,6 +8924,9 @@ void dce8_bandwidth_update(struct radeon_device *rdev) + u32 num_heads = 0, lb_size; + int i; + ++ if (!rdev->mode_info.mode_config_initialized) ++ return; ++ + radeon_update_display_priority(rdev); + + for (i = 0; i < rdev->num_crtc; i++) { +diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c +index aac8f48..e590aec 100644 +--- a/drivers/gpu/drm/radeon/cik_sdma.c ++++ b/drivers/gpu/drm/radeon/cik_sdma.c +@@ -266,6 +266,17 @@ static void cik_sdma_gfx_stop(struct radeon_device *rdev) + } + rdev->ring[R600_RING_TYPE_DMA_INDEX].ready = false; + rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready = false; ++ ++ /* FIXME use something else than big hammer but after few days can not ++ * seem to find good combination so reset SDMA blocks as it seems we ++ * do not shut them down properly. This fix hibernation and does not ++ * affect suspend to ram. ++ */ ++ WREG32(SRBM_SOFT_RESET, SOFT_RESET_SDMA | SOFT_RESET_SDMA1); ++ (void)RREG32(SRBM_SOFT_RESET); ++ udelay(50); ++ WREG32(SRBM_SOFT_RESET, 0); ++ (void)RREG32(SRBM_SOFT_RESET); + } + + /** +@@ -461,13 +472,6 @@ int cik_sdma_resume(struct radeon_device *rdev) + { + int r; + +- /* Reset dma */ +- WREG32(SRBM_SOFT_RESET, SOFT_RESET_SDMA | SOFT_RESET_SDMA1); +- RREG32(SRBM_SOFT_RESET); +- udelay(50); +- WREG32(SRBM_SOFT_RESET, 0); +- RREG32(SRBM_SOFT_RESET); +- + r = cik_sdma_load_microcode(rdev); + if (r) + return r; +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index 64108db..ee9f0b4 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -2362,6 +2362,9 @@ void evergreen_bandwidth_update(struct radeon_device *rdev) + u32 num_heads = 0, lb_size; + int i; + ++ if (!rdev->mode_info.mode_config_initialized) ++ return; ++ + radeon_update_display_priority(rdev); + + for (i = 0; i < rdev->num_crtc; i++) { +@@ -2570,6 +2573,7 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; + WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); ++ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); + } + } else { + tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); +@@ -4592,6 +4596,9 @@ int evergreen_irq_set(struct radeon_device *rdev) + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, afmt5); + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, afmt6); + ++ /* posting read */ ++ RREG32(SRBM_STATUS); ++ + return 0; + } + +@@ -4763,6 +4770,7 @@ static u32 evergreen_get_ih_wptr(struct radeon_device *rdev) + tmp = RREG32(IH_RB_CNTL); + tmp |= IH_WPTR_OVERFLOW_CLEAR; + WREG32(IH_RB_CNTL, tmp); ++ wptr &= ~RB_OVERFLOW; + } + return (wptr & rdev->ih.ptr_mask); + } +diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c +index 351db36..c7c7bc5 100644 +--- a/drivers/gpu/drm/radeon/kv_dpm.c ++++ b/drivers/gpu/drm/radeon/kv_dpm.c +@@ -1121,6 +1121,19 @@ void kv_dpm_enable_bapm(struct radeon_device *rdev, bool enable) + } + } + ++static void kv_enable_thermal_int(struct radeon_device *rdev, bool enable) ++{ ++ u32 thermal_int; ++ ++ thermal_int = RREG32_SMC(CG_THERMAL_INT_CTRL); ++ if (enable) ++ thermal_int |= THERM_INTH_MASK | THERM_INTL_MASK; ++ else ++ thermal_int &= ~(THERM_INTH_MASK | THERM_INTL_MASK); ++ WREG32_SMC(CG_THERMAL_INT_CTRL, thermal_int); ++ ++} ++ + int kv_dpm_enable(struct radeon_device *rdev) + { + struct kv_power_info *pi = kv_get_pi(rdev); +@@ -1232,8 +1245,7 @@ int kv_dpm_late_enable(struct radeon_device *rdev) + DRM_ERROR("kv_set_thermal_temperature_range failed\n"); + return ret; + } +- rdev->irq.dpm_thermal = true; +- radeon_irq_set(rdev); ++ kv_enable_thermal_int(rdev, true); + } + + /* powerdown unused blocks for now */ +@@ -1261,6 +1273,7 @@ void kv_dpm_disable(struct radeon_device *rdev) + kv_stop_dpm(rdev); + kv_enable_ulv(rdev, false); + kv_reset_am(rdev); ++ kv_enable_thermal_int(rdev, false); + + kv_update_current_ps(rdev, rdev->pm.dpm.boot_ps); + } +diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c +index bf6300c..392d94b 100644 +--- a/drivers/gpu/drm/radeon/ni.c ++++ b/drivers/gpu/drm/radeon/ni.c +@@ -1073,12 +1073,12 @@ static void cayman_gpu_init(struct radeon_device *rdev) + + if ((rdev->config.cayman.max_backends_per_se == 1) && + (rdev->flags & RADEON_IS_IGP)) { +- if ((disabled_rb_mask & 3) == 1) { +- /* RB0 disabled, RB1 enabled */ +- tmp = 0x11111111; +- } else { ++ if ((disabled_rb_mask & 3) == 2) { + /* RB1 disabled, RB0 enabled */ + tmp = 0x00000000; ++ } else { ++ /* RB0 disabled, RB1 enabled */ ++ tmp = 0x11111111; + } + } else { + tmp = gb_addr_config & NUM_PIPES_MASK; +@@ -1256,7 +1256,8 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev) + */ + for (i = 1; i < 8; i++) { + WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0); +- WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), rdev->vm_manager.max_pfn); ++ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), ++ rdev->vm_manager.max_pfn - 1); + WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), + rdev->gart.table_addr >> 12); + } +diff --git a/drivers/gpu/drm/radeon/ni_dma.c b/drivers/gpu/drm/radeon/ni_dma.c +index 7cf96b1..94fa49e 100644 +--- a/drivers/gpu/drm/radeon/ni_dma.c ++++ b/drivers/gpu/drm/radeon/ni_dma.c +@@ -191,12 +191,6 @@ int cayman_dma_resume(struct radeon_device *rdev) + u32 reg_offset, wb_offset; + int i, r; + +- /* Reset dma */ +- WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1); +- RREG32(SRBM_SOFT_RESET); +- udelay(50); +- WREG32(SRBM_SOFT_RESET, 0); +- + for (i = 0; i < 2; i++) { + if (i == 0) { + ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; +diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c +index 3cc78bb..e28de20 100644 +--- a/drivers/gpu/drm/radeon/r100.c ++++ b/drivers/gpu/drm/radeon/r100.c +@@ -742,6 +742,10 @@ int r100_irq_set(struct radeon_device *rdev) + tmp |= RADEON_FP2_DETECT_MASK; + } + WREG32(RADEON_GEN_INT_CNTL, tmp); ++ ++ /* read back to post the write */ ++ RREG32(RADEON_GEN_INT_CNTL); ++ + return 0; + } + +@@ -3219,6 +3223,9 @@ void r100_bandwidth_update(struct radeon_device *rdev) + uint32_t pixel_bytes1 = 0; + uint32_t pixel_bytes2 = 0; + ++ if (!rdev->mode_info.mode_config_initialized) ++ return; ++ + radeon_update_display_priority(rdev); + + if (rdev->mode_info.crtcs[0]->base.enabled) { +diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c +index f28ab84..74a8a38 100644 +--- a/drivers/gpu/drm/radeon/r600.c ++++ b/drivers/gpu/drm/radeon/r600.c +@@ -3647,6 +3647,9 @@ int r600_irq_set(struct radeon_device *rdev) + WREG32(RV770_CG_THERMAL_INT, thermal_int); + } + ++ /* posting read */ ++ RREG32(R_000E50_SRBM_STATUS); ++ + return 0; + } + +@@ -3795,6 +3798,7 @@ static u32 r600_get_ih_wptr(struct radeon_device *rdev) + tmp = RREG32(IH_RB_CNTL); + tmp |= IH_WPTR_OVERFLOW_CLEAR; + WREG32(IH_RB_CNTL, tmp); ++ wptr &= ~RB_OVERFLOW; + } + return (wptr & rdev->ih.ptr_mask); + } +diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c +index b2d4c91..9949551 100644 +--- a/drivers/gpu/drm/radeon/r600_dma.c ++++ b/drivers/gpu/drm/radeon/r600_dma.c +@@ -124,15 +124,6 @@ int r600_dma_resume(struct radeon_device *rdev) + u32 rb_bufsz; + int r; + +- /* Reset dma */ +- if (rdev->family >= CHIP_RV770) +- WREG32(SRBM_SOFT_RESET, RV770_SOFT_RESET_DMA); +- else +- WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA); +- RREG32(SRBM_SOFT_RESET); +- udelay(50); +- WREG32(SRBM_SOFT_RESET, 0); +- + WREG32(DMA_SEM_INCOMPLETE_TIMER_CNTL, 0); + WREG32(DMA_SEM_WAIT_FAIL_TIMER_CNTL, 0); + +diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c +index 813db8d..e981082 100644 +--- a/drivers/gpu/drm/radeon/r600_dpm.c ++++ b/drivers/gpu/drm/radeon/r600_dpm.c +@@ -187,7 +187,7 @@ u32 r600_dpm_get_vrefresh(struct radeon_device *rdev) + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + radeon_crtc = to_radeon_crtc(crtc); + if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) { +- vrefresh = radeon_crtc->hw_mode.vrefresh; ++ vrefresh = drm_mode_vrefresh(&radeon_crtc->hw_mode); + break; + } + } +@@ -1209,7 +1209,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); + rdev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = +- ppt->usMaximumPowerDeliveryLimit; ++ le16_to_cpu(ppt->usMaximumPowerDeliveryLimit); + pt = &ppt->power_tune_table; + } else { + ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *) +diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h +index 08e86f9..b837e9f 100644 +--- a/drivers/gpu/drm/radeon/radeon.h ++++ b/drivers/gpu/drm/radeon/radeon.h +@@ -294,6 +294,9 @@ int radeon_atom_get_leakage_vddc_based_on_leakage_params(struct radeon_device *r + u16 *vddc, u16 *vddci, + u16 virtual_voltage_id, + u16 vbios_voltage_id); ++int radeon_atom_get_voltage_evv(struct radeon_device *rdev, ++ u16 virtual_voltage_id, ++ u16 *voltage); + int radeon_atom_round_to_true_voltage(struct radeon_device *rdev, + u8 voltage_type, + u16 nominal_voltage, +diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c +index 5600d4c..d625a14 100644 +--- a/drivers/gpu/drm/radeon/radeon_asic.c ++++ b/drivers/gpu/drm/radeon/radeon_asic.c +@@ -335,6 +335,20 @@ static struct radeon_asic_ring r300_gfx_ring = { + .set_wptr = &r100_gfx_set_wptr, + }; + ++static struct radeon_asic_ring rv515_gfx_ring = { ++ .ib_execute = &r100_ring_ib_execute, ++ .emit_fence = &r300_fence_ring_emit, ++ .emit_semaphore = &r100_semaphore_ring_emit, ++ .cs_parse = &r300_cs_parse, ++ .ring_start = &rv515_ring_start, ++ .ring_test = &r100_ring_test, ++ .ib_test = &r100_ib_test, ++ .is_lockup = &r100_gpu_is_lockup, ++ .get_rptr = &r100_gfx_get_rptr, ++ .get_wptr = &r100_gfx_get_wptr, ++ .set_wptr = &r100_gfx_set_wptr, ++}; ++ + static struct radeon_asic r300_asic = { + .init = &r300_init, + .fini = &r300_fini, +@@ -756,7 +770,7 @@ static struct radeon_asic rv515_asic = { + .set_page = &rv370_pcie_gart_set_page, + }, + .ring = { +- [RADEON_RING_TYPE_GFX_INDEX] = &r300_gfx_ring ++ [RADEON_RING_TYPE_GFX_INDEX] = &rv515_gfx_ring + }, + .irq = { + .set = &rs600_irq_set, +@@ -823,7 +837,7 @@ static struct radeon_asic r520_asic = { + .set_page = &rv370_pcie_gart_set_page, + }, + .ring = { +- [RADEON_RING_TYPE_GFX_INDEX] = &r300_gfx_ring ++ [RADEON_RING_TYPE_GFX_INDEX] = &rv515_gfx_ring + }, + .irq = { + .set = &rs600_irq_set, +@@ -1159,7 +1173,7 @@ static struct radeon_asic rs780_asic = { + static struct radeon_asic_ring rv770_uvd_ring = { + .ib_execute = &uvd_v1_0_ib_execute, + .emit_fence = &uvd_v2_2_fence_emit, +- .emit_semaphore = &uvd_v1_0_semaphore_emit, ++ .emit_semaphore = &uvd_v2_2_semaphore_emit, + .cs_parse = &radeon_uvd_cs_parse, + .ring_test = &uvd_v1_0_ring_test, + .ib_test = &uvd_v1_0_ib_test, +diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h +index ae637cf..f6e19ed 100644 +--- a/drivers/gpu/drm/radeon/radeon_asic.h ++++ b/drivers/gpu/drm/radeon/radeon_asic.h +@@ -853,6 +853,10 @@ void uvd_v1_0_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); + int uvd_v2_2_resume(struct radeon_device *rdev); + void uvd_v2_2_fence_emit(struct radeon_device *rdev, + struct radeon_fence *fence); ++bool uvd_v2_2_semaphore_emit(struct radeon_device *rdev, ++ struct radeon_ring *ring, ++ struct radeon_semaphore *semaphore, ++ bool emit_wait); + + /* uvd v3.1 */ + bool uvd_v3_1_semaphore_emit(struct radeon_device *rdev, +diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c +index 3084481..2fa3cf6 100644 +--- a/drivers/gpu/drm/radeon/radeon_atombios.c ++++ b/drivers/gpu/drm/radeon/radeon_atombios.c +@@ -447,6 +447,13 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, + } + } + ++ /* Fujitsu D3003-S2 board lists DVI-I as DVI-I and VGA */ ++ if ((dev->pdev->device == 0x9805) && ++ (dev->pdev->subsystem_vendor == 0x1734) && ++ (dev->pdev->subsystem_device == 0x11bd)) { ++ if (*connector_type == DRM_MODE_CONNECTOR_VGA) ++ return false; ++ } + + return true; + } +@@ -1955,7 +1962,7 @@ static const char *thermal_controller_names[] = { + "adm1032", + "adm1030", + "max6649", +- "lm64", ++ "lm63", /* lm64 */ + "f75375", + "asc7xxx", + }; +@@ -1966,7 +1973,7 @@ static const char *pp_lib_thermal_controller_names[] = { + "adm1032", + "adm1030", + "max6649", +- "lm64", ++ "lm63", /* lm64 */ + "f75375", + "RV6xx", + "RV770", +@@ -2273,19 +2280,31 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_KV; +- } else if ((controller->ucType == +- ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) || +- (controller->ucType == +- ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) || +- (controller->ucType == +- ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL)) { +- DRM_INFO("Special thermal controller config\n"); ++ } else if (controller->ucType == ++ ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) { ++ DRM_INFO("External GPIO thermal controller %s fan control\n", ++ (controller->ucFanParameters & ++ ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); ++ rdev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO; ++ } else if (controller->ucType == ++ ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) { ++ DRM_INFO("ADT7473 with internal thermal controller %s fan control\n", ++ (controller->ucFanParameters & ++ ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); ++ rdev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL; ++ } else if (controller->ucType == ++ ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) { ++ DRM_INFO("EMC2103 with internal thermal controller %s fan control\n", ++ (controller->ucFanParameters & ++ ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); ++ rdev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL; + } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) { + DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", + pp_lib_thermal_controller_names[controller->ucType], + controller->ucI2cAddress >> 1, + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); ++ rdev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL; + i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); + rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); + if (rdev->pm.i2c_bus) { +@@ -3228,6 +3247,42 @@ int radeon_atom_get_leakage_vddc_based_on_leakage_params(struct radeon_device *r + return 0; + } + ++union get_voltage_info { ++ struct _GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2 in; ++ struct _GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2 evv_out; ++}; ++ ++int radeon_atom_get_voltage_evv(struct radeon_device *rdev, ++ u16 virtual_voltage_id, ++ u16 *voltage) ++{ ++ int index = GetIndexIntoMasterTable(COMMAND, GetVoltageInfo); ++ u32 entry_id; ++ u32 count = rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; ++ union get_voltage_info args; ++ ++ for (entry_id = 0; entry_id < count; entry_id++) { ++ if (rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[entry_id].v == ++ virtual_voltage_id) ++ break; ++ } ++ ++ if (entry_id >= count) ++ return -EINVAL; ++ ++ args.in.ucVoltageType = VOLTAGE_TYPE_VDDC; ++ args.in.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE; ++ args.in.usVoltageLevel = cpu_to_le16(virtual_voltage_id); ++ args.in.ulSCLKFreq = ++ cpu_to_le32(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[entry_id].clk); ++ ++ atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); ++ ++ *voltage = le16_to_cpu(args.evv_out.usVoltageLevel); ++ ++ return 0; ++} ++ + int radeon_atom_get_voltage_gpio_settings(struct radeon_device *rdev, + u16 voltage_level, u8 voltage_type, + u32 *gpio_value, u32 *gpio_mask) +diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c +index 9ab3097..c43335c 100644 +--- a/drivers/gpu/drm/radeon/radeon_bios.c ++++ b/drivers/gpu/drm/radeon/radeon_bios.c +@@ -76,7 +76,7 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev) + + static bool radeon_read_bios(struct radeon_device *rdev) + { +- uint8_t __iomem *bios; ++ uint8_t __iomem *bios, val1, val2; + size_t size; + + rdev->bios = NULL; +@@ -86,15 +86,19 @@ static bool radeon_read_bios(struct radeon_device *rdev) + return false; + } + +- if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { ++ val1 = readb(&bios[0]); ++ val2 = readb(&bios[1]); ++ ++ if (size == 0 || val1 != 0x55 || val2 != 0xaa) { + pci_unmap_rom(rdev->pdev, bios); + return false; + } +- rdev->bios = kmemdup(bios, size, GFP_KERNEL); ++ rdev->bios = kzalloc(size, GFP_KERNEL); + if (rdev->bios == NULL) { + pci_unmap_rom(rdev->pdev, bios); + return false; + } ++ memcpy_fromio(rdev->bios, bios, size); + pci_unmap_rom(rdev->pdev, bios); + return true; + } +diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c +index 6651177..79a2669 100644 +--- a/drivers/gpu/drm/radeon/radeon_combios.c ++++ b/drivers/gpu/drm/radeon/radeon_combios.c +@@ -1255,10 +1255,15 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder + + if ((RBIOS16(tmp) == lvds->native_mode.hdisplay) && + (RBIOS16(tmp + 2) == lvds->native_mode.vdisplay)) { ++ u32 hss = (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - 1) * 8; ++ ++ if (hss > lvds->native_mode.hdisplay) ++ hss = (10 - 1) * 8; ++ + lvds->native_mode.htotal = lvds->native_mode.hdisplay + + (RBIOS16(tmp + 17) - RBIOS16(tmp + 19)) * 8; + lvds->native_mode.hsync_start = lvds->native_mode.hdisplay + +- (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - 1) * 8; ++ hss; + lvds->native_mode.hsync_end = lvds->native_mode.hsync_start + + (RBIOS8(tmp + 23) * 8); + +diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c +index 4d36b9e..17ae621 100644 +--- a/drivers/gpu/drm/radeon/radeon_connectors.c ++++ b/drivers/gpu/drm/radeon/radeon_connectors.c +@@ -71,6 +71,11 @@ void radeon_connector_hotplug(struct drm_connector *connector) + if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + } else if (radeon_dp_needs_link_train(radeon_connector)) { ++ /* Don't try to start link training before we ++ * have the dpcd */ ++ if (!radeon_dp_getdpcd(radeon_connector)) ++ return; ++ + /* set it to OFF so that drm_helper_connector_dpms() + * won't return immediately since the current state + * is ON at this point. +diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c +index 7f2d6c0..2f2d2ce 100644 +--- a/drivers/gpu/drm/radeon/radeon_cs.c ++++ b/drivers/gpu/drm/radeon/radeon_cs.c +@@ -179,11 +179,13 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) + u32 ring = RADEON_CS_RING_GFX; + s32 priority = 0; + ++ INIT_LIST_HEAD(&p->validated); ++ + if (!cs->num_chunks) { + return 0; + } ++ + /* get chunks */ +- INIT_LIST_HEAD(&p->validated); + p->idx = 0; + p->ib.sa_bo = NULL; + p->ib.semaphore = NULL; +diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c +index 0bf6f4a..129915e 100644 +--- a/drivers/gpu/drm/radeon/radeon_device.c ++++ b/drivers/gpu/drm/radeon/radeon_device.c +@@ -1314,7 +1314,7 @@ int radeon_device_init(struct radeon_device *rdev, + + r = radeon_init(rdev); + if (r) +- return r; ++ goto failed; + + r = radeon_ib_ring_tests(rdev); + if (r) +@@ -1334,7 +1334,22 @@ int radeon_device_init(struct radeon_device *rdev, + radeon_agp_disable(rdev); + r = radeon_init(rdev); + if (r) +- return r; ++ goto failed; ++ } ++ ++ /* ++ * Turks/Thames GPU will freeze whole laptop if DPM is not restarted ++ * after the CP ring have chew one packet at least. Hence here we stop ++ * and restart DPM after the radeon_ib_ring_tests(). ++ */ ++ if (rdev->pm.dpm_enabled && ++ (rdev->pm.pm_method == PM_METHOD_DPM) && ++ (rdev->family == CHIP_TURKS) && ++ (rdev->flags & RADEON_IS_MOBILITY)) { ++ mutex_lock(&rdev->pm.mutex); ++ radeon_dpm_disable(rdev); ++ radeon_dpm_enable(rdev); ++ mutex_unlock(&rdev->pm.mutex); + } + + if ((radeon_testing & 1)) { +@@ -1356,6 +1371,11 @@ int radeon_device_init(struct radeon_device *rdev, + DRM_INFO("radeon: acceleration disabled, skipping benchmarks\n"); + } + return 0; ++ ++failed: ++ if (runtime) ++ vga_switcheroo_fini_domain_pm_ops(rdev->dev); ++ return r; + } + + static void radeon_debugfs_remove_files(struct radeon_device *rdev); +@@ -1376,6 +1396,8 @@ void radeon_device_fini(struct radeon_device *rdev) + radeon_bo_evict_vram(rdev); + radeon_fini(rdev); + vga_switcheroo_unregister_client(rdev->pdev); ++ if (rdev->flags & RADEON_IS_PX) ++ vga_switcheroo_fini_domain_pm_ops(rdev->dev); + vga_client_register(rdev->pdev, NULL, NULL, NULL); + if (rdev->rio_mem) + pci_iounmap(rdev->pdev, rdev->rio_mem); +@@ -1600,7 +1622,6 @@ int radeon_gpu_reset(struct radeon_device *rdev) + radeon_save_bios_scratch_regs(rdev); + /* block TTM */ + resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); +- radeon_pm_suspend(rdev); + radeon_suspend(rdev); + + for (i = 0; i < RADEON_NUM_RINGS; ++i) { +@@ -1646,9 +1667,24 @@ retry: + } + } + +- radeon_pm_resume(rdev); ++ if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) { ++ /* do dpm late init */ ++ r = radeon_pm_late_init(rdev); ++ if (r) { ++ rdev->pm.dpm_enabled = false; ++ DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n"); ++ } ++ } else { ++ /* resume old pm late */ ++ radeon_pm_resume(rdev); ++ } ++ + drm_helper_resume_force_mode(rdev->ddev); + ++ /* set the power state here in case we are a PX system or headless */ ++ if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) ++ radeon_pm_compute_clocks(rdev); ++ + ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); + if (r) { + /* bad news, how to tell it to userspace ? */ +diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c +index a8f9b46..e609722 100644 +--- a/drivers/gpu/drm/radeon/radeon_gart.c ++++ b/drivers/gpu/drm/radeon/radeon_gart.c +@@ -251,8 +251,10 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, + } + } + } +- mb(); +- radeon_gart_tlb_flush(rdev); ++ if (rdev->gart.ptr) { ++ mb(); ++ radeon_gart_tlb_flush(rdev); ++ } + } + + /** +@@ -294,8 +296,10 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, + } + } + } +- mb(); +- radeon_gart_tlb_flush(rdev); ++ if (rdev->gart.ptr) { ++ mb(); ++ radeon_gart_tlb_flush(rdev); ++ } + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c +index 089c9ff..f8b20e1 100644 +--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c ++++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c +@@ -79,10 +79,12 @@ static void radeon_hotplug_work_func(struct work_struct *work) + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_connector *connector; + ++ mutex_lock(&mode_config->mutex); + if (mode_config->num_connector) { + list_for_each_entry(connector, &mode_config->connector_list, head) + radeon_connector_hotplug(connector); + } ++ mutex_unlock(&mode_config->mutex); + /* Just fire off a uevent and let userspace tell us what to do */ + drm_helper_hpd_irq_event(dev); + } +@@ -202,6 +204,16 @@ static bool radeon_msi_ok(struct radeon_device *rdev) + if (rdev->flags & RADEON_IS_AGP) + return false; + ++ /* ++ * Older chips have a HW limitation, they can only generate 40 bits ++ * of address for "64-bit" MSIs which breaks on some platforms, notably ++ * IBM POWER servers, so we limit them ++ */ ++ if (rdev->family < CHIP_BONAIRE) { ++ dev_info(rdev->dev, "radeon: MSI limited to 32-bit\n"); ++ rdev->pdev->no_64bit_msi = 1; ++ } ++ + /* force MSI on */ + if (radeon_msi == 1) + return true; +diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c +index ea34a31..6bffe82 100644 +--- a/drivers/gpu/drm/radeon/radeon_kms.c ++++ b/drivers/gpu/drm/radeon/radeon_kms.c +@@ -254,7 +254,14 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file + } + break; + case RADEON_INFO_ACCEL_WORKING2: +- *value = rdev->accel_working; ++ if (rdev->family == CHIP_HAWAII) { ++ if (rdev->accel_working) ++ *value = 2; ++ else ++ *value = 0; ++ } else { ++ *value = rdev->accel_working; ++ } + break; + case RADEON_INFO_TILING_CONFIG: + if (rdev->family >= CHIP_BONAIRE) +@@ -733,6 +740,8 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, + + /* Get associated drm_crtc: */ + drmcrtc = &rdev->mode_info.crtcs[crtc]->base; ++ if (!drmcrtc) ++ return -EINVAL; + + /* Helper routine in DRM core does all the work: */ + return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error, +diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c +index f77d9d0..0095ee7 100644 +--- a/drivers/gpu/drm/radeon/radeon_pm.c ++++ b/drivers/gpu/drm/radeon/radeon_pm.c +@@ -458,10 +458,6 @@ static ssize_t radeon_get_dpm_state(struct device *dev, + struct radeon_device *rdev = ddev->dev_private; + enum radeon_pm_state_type pm = rdev->pm.dpm.user_state; + +- if ((rdev->flags & RADEON_IS_PX) && +- (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) +- return snprintf(buf, PAGE_SIZE, "off\n"); +- + return snprintf(buf, PAGE_SIZE, "%s\n", + (pm == POWER_STATE_TYPE_BATTERY) ? "battery" : + (pm == POWER_STATE_TYPE_BALANCED) ? "balanced" : "performance"); +@@ -475,11 +471,6 @@ static ssize_t radeon_set_dpm_state(struct device *dev, + struct drm_device *ddev = dev_get_drvdata(dev); + struct radeon_device *rdev = ddev->dev_private; + +- /* Can't set dpm state when the card is off */ +- if ((rdev->flags & RADEON_IS_PX) && +- (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) +- return -EINVAL; +- + mutex_lock(&rdev->pm.mutex); + if (strncmp("battery", buf, strlen("battery")) == 0) + rdev->pm.dpm.user_state = POWER_STATE_TYPE_BATTERY; +@@ -493,7 +484,12 @@ static ssize_t radeon_set_dpm_state(struct device *dev, + goto fail; + } + mutex_unlock(&rdev->pm.mutex); +- radeon_pm_compute_clocks(rdev); ++ ++ /* Can't set dpm state when the card is off */ ++ if (!(rdev->flags & RADEON_IS_PX) || ++ (ddev->switch_power_state == DRM_SWITCH_POWER_ON)) ++ radeon_pm_compute_clocks(rdev); ++ + fail: + return count; + } +@@ -1264,8 +1260,39 @@ dpm_failed: + return ret; + } + ++struct radeon_dpm_quirk { ++ u32 chip_vendor; ++ u32 chip_device; ++ u32 subsys_vendor; ++ u32 subsys_device; ++}; ++ ++/* cards with dpm stability problems */ ++static struct radeon_dpm_quirk radeon_dpm_quirk_list[] = { ++ /* TURKS - https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1386534 */ ++ { PCI_VENDOR_ID_ATI, 0x6759, 0x1682, 0x3195 }, ++ /* TURKS - https://bugzilla.kernel.org/show_bug.cgi?id=83731 */ ++ { PCI_VENDOR_ID_ATI, 0x6840, 0x1179, 0xfb81 }, ++ { 0, 0, 0, 0 }, ++}; ++ + int radeon_pm_init(struct radeon_device *rdev) + { ++ struct radeon_dpm_quirk *p = radeon_dpm_quirk_list; ++ bool disable_dpm = false; ++ ++ /* Apply dpm quirks */ ++ while (p && p->chip_device != 0) { ++ if (rdev->pdev->vendor == p->chip_vendor && ++ rdev->pdev->device == p->chip_device && ++ rdev->pdev->subsystem_vendor == p->subsys_vendor && ++ rdev->pdev->subsystem_device == p->subsys_device) { ++ disable_dpm = true; ++ break; ++ } ++ ++p; ++ } ++ + /* enable dpm on rv6xx+ */ + switch (rdev->family) { + case CHIP_RV610: +@@ -1276,10 +1303,6 @@ int radeon_pm_init(struct radeon_device *rdev) + case CHIP_RS780: + case CHIP_RS880: + case CHIP_RV770: +- case CHIP_BARTS: +- case CHIP_TURKS: +- case CHIP_CAICOS: +- case CHIP_CAYMAN: + /* DPM requires the RLC, RV770+ dGPU requires SMC */ + if (!rdev->rlc_fw) + rdev->pm.pm_method = PM_METHOD_PROFILE; +@@ -1303,6 +1326,10 @@ int radeon_pm_init(struct radeon_device *rdev) + case CHIP_PALM: + case CHIP_SUMO: + case CHIP_SUMO2: ++ case CHIP_BARTS: ++ case CHIP_TURKS: ++ case CHIP_CAICOS: ++ case CHIP_CAYMAN: + case CHIP_ARUBA: + case CHIP_TAHITI: + case CHIP_PITCAIRN: +@@ -1320,6 +1347,8 @@ int radeon_pm_init(struct radeon_device *rdev) + (!(rdev->flags & RADEON_IS_IGP)) && + (!rdev->smc_fw)) + rdev->pm.pm_method = PM_METHOD_PROFILE; ++ else if (disable_dpm && (radeon_dpm == -1)) ++ rdev->pm.pm_method = PM_METHOD_PROFILE; + else if (radeon_dpm == 0) + rdev->pm.pm_method = PM_METHOD_PROFILE; + else +diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c +index 9006b32..eb7b600 100644 +--- a/drivers/gpu/drm/radeon/radeon_semaphore.c ++++ b/drivers/gpu/drm/radeon/radeon_semaphore.c +@@ -34,7 +34,7 @@ + int radeon_semaphore_create(struct radeon_device *rdev, + struct radeon_semaphore **semaphore) + { +- uint32_t *cpu_addr; ++ uint64_t *cpu_addr; + int i, r; + + *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL); +diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c +index 040a2a1..45a9a03 100644 +--- a/drivers/gpu/drm/radeon/radeon_ttm.c ++++ b/drivers/gpu/drm/radeon/radeon_ttm.c +@@ -191,7 +191,7 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo, + rbo = container_of(bo, struct radeon_bo, tbo); + switch (bo->mem.mem_type) { + case TTM_PL_VRAM: +- if (rbo->rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready == false) ++ if (rbo->rdev->ring[radeon_copy_ring_index(rbo->rdev)].ready == false) + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU); + else + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); +diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c +index 414e079..bcfac76 100644 +--- a/drivers/gpu/drm/radeon/radeon_uvd.c ++++ b/drivers/gpu/drm/radeon/radeon_uvd.c +@@ -350,6 +350,29 @@ static int radeon_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[]) + return 0; + } + ++static int radeon_uvd_validate_codec(struct radeon_cs_parser *p, ++ unsigned stream_type) ++{ ++ switch (stream_type) { ++ case 0: /* H264 */ ++ case 1: /* VC1 */ ++ /* always supported */ ++ return 0; ++ ++ case 3: /* MPEG2 */ ++ case 4: /* MPEG4 */ ++ /* only since UVD 3 */ ++ if (p->rdev->family >= CHIP_PALM) ++ return 0; ++ ++ /* fall through */ ++ default: ++ DRM_ERROR("UVD codec not supported by hardware %d!\n", ++ stream_type); ++ return -EINVAL; ++ } ++} ++ + static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, + unsigned offset, unsigned buf_sizes[]) + { +@@ -388,50 +411,70 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, + return -EINVAL; + } + +- if (msg_type == 1) { +- /* it's a decode msg, calc buffer sizes */ +- r = radeon_uvd_cs_msg_decode(msg, buf_sizes); +- /* calc image size (width * height) */ +- img_size = msg[6] * msg[7]; ++ switch (msg_type) { ++ case 0: ++ /* it's a create msg, calc image size (width * height) */ ++ img_size = msg[7] * msg[8]; ++ ++ r = radeon_uvd_validate_codec(p, msg[4]); ++ radeon_bo_kunmap(bo); ++ if (r) ++ return r; ++ ++ /* try to alloc a new handle */ ++ for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { ++ if (atomic_read(&p->rdev->uvd.handles[i]) == handle) { ++ DRM_ERROR("Handle 0x%x already in use!\n", handle); ++ return -EINVAL; ++ } ++ ++ if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) { ++ p->rdev->uvd.filp[i] = p->filp; ++ p->rdev->uvd.img_size[i] = img_size; ++ return 0; ++ } ++ } ++ ++ DRM_ERROR("No more free UVD handles!\n"); ++ return -EINVAL; ++ ++ case 1: ++ /* it's a decode msg, validate codec and calc buffer sizes */ ++ r = radeon_uvd_validate_codec(p, msg[4]); ++ if (!r) ++ r = radeon_uvd_cs_msg_decode(msg, buf_sizes); + radeon_bo_kunmap(bo); + if (r) + return r; + +- } else if (msg_type == 2) { ++ /* validate the handle */ ++ for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { ++ if (atomic_read(&p->rdev->uvd.handles[i]) == handle) { ++ if (p->rdev->uvd.filp[i] != p->filp) { ++ DRM_ERROR("UVD handle collision detected!\n"); ++ return -EINVAL; ++ } ++ return 0; ++ } ++ } ++ ++ DRM_ERROR("Invalid UVD handle 0x%x!\n", handle); ++ return -ENOENT; ++ ++ case 2: + /* it's a destroy msg, free the handle */ + for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) + atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0); + radeon_bo_kunmap(bo); + return 0; +- } else { +- /* it's a create msg, calc image size (width * height) */ +- img_size = msg[7] * msg[8]; +- radeon_bo_kunmap(bo); + +- if (msg_type != 0) { +- DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type); +- return -EINVAL; +- } +- +- /* it's a create msg, no special handling needed */ +- } +- +- /* create or decode, validate the handle */ +- for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { +- if (atomic_read(&p->rdev->uvd.handles[i]) == handle) +- return 0; +- } ++ default: + +- /* handle not found try to alloc a new one */ +- for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { +- if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) { +- p->rdev->uvd.filp[i] = p->filp; +- p->rdev->uvd.img_size[i] = img_size; +- return 0; +- } ++ DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type); ++ return -EINVAL; + } + +- DRM_ERROR("No more free UVD handles!\n"); ++ BUG(); + return -EINVAL; + } + +diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c +index 95b693c..4261b38 100644 +--- a/drivers/gpu/drm/radeon/rs600.c ++++ b/drivers/gpu/drm/radeon/rs600.c +@@ -700,6 +700,10 @@ int rs600_irq_set(struct radeon_device *rdev) + WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); + if (ASIC_IS_DCE2(rdev)) + WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0); ++ ++ /* posting read */ ++ RREG32(R_000040_GEN_INT_CNTL); ++ + return 0; + } + +@@ -890,6 +894,9 @@ void rs600_bandwidth_update(struct radeon_device *rdev) + u32 d1mode_priority_a_cnt, d2mode_priority_a_cnt; + /* FIXME: implement full support */ + ++ if (!rdev->mode_info.mode_config_initialized) ++ return; ++ + radeon_update_display_priority(rdev); + + if (rdev->mode_info.crtcs[0]->base.enabled) +diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c +index 3462b64..0a2d36e 100644 +--- a/drivers/gpu/drm/radeon/rs690.c ++++ b/drivers/gpu/drm/radeon/rs690.c +@@ -579,6 +579,9 @@ void rs690_bandwidth_update(struct radeon_device *rdev) + u32 d1mode_priority_a_cnt, d1mode_priority_b_cnt; + u32 d2mode_priority_a_cnt, d2mode_priority_b_cnt; + ++ if (!rdev->mode_info.mode_config_initialized) ++ return; ++ + radeon_update_display_priority(rdev); + + if (rdev->mode_info.crtcs[0]->base.enabled) +diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c +index 237dd29..b49965a 100644 +--- a/drivers/gpu/drm/radeon/rv515.c ++++ b/drivers/gpu/drm/radeon/rv515.c +@@ -1276,6 +1276,9 @@ void rv515_bandwidth_update(struct radeon_device *rdev) + struct drm_display_mode *mode0 = NULL; + struct drm_display_mode *mode1 = NULL; + ++ if (!rdev->mode_info.mode_config_initialized) ++ return; ++ + radeon_update_display_priority(rdev); + + if (rdev->mode_info.crtcs[0]->base.enabled) +diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h +index 3cf1e29..9ef2064 100644 +--- a/drivers/gpu/drm/radeon/rv770d.h ++++ b/drivers/gpu/drm/radeon/rv770d.h +@@ -989,6 +989,9 @@ + ((n) & 0x3FFF) << 16) + + /* UVD */ ++#define UVD_SEMA_ADDR_LOW 0xef00 ++#define UVD_SEMA_ADDR_HIGH 0xef04 ++#define UVD_SEMA_CMD 0xef08 + #define UVD_GPCOM_VCPU_CMD 0xef0c + #define UVD_GPCOM_VCPU_DATA0 0xef10 + #define UVD_GPCOM_VCPU_DATA1 0xef14 +diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c +index cb7508d..49da9fc 100644 +--- a/drivers/gpu/drm/radeon/si.c ++++ b/drivers/gpu/drm/radeon/si.c +@@ -2227,6 +2227,9 @@ void dce6_bandwidth_update(struct radeon_device *rdev) + u32 num_heads = 0, lb_size; + int i; + ++ if (!rdev->mode_info.mode_config_initialized) ++ return; ++ + radeon_update_display_priority(rdev); + + for (i = 0; i < rdev->num_crtc; i++) { +@@ -4081,7 +4084,7 @@ static int si_pcie_gart_enable(struct radeon_device *rdev) + /* empty context1-15 */ + /* set vm size, must be a multiple of 4 */ + WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0); +- WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn); ++ WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn - 1); + /* Assign the pt base to something valid for now; the pts used for + * the VMs are determined by the application and setup and assigned + * on the fly in the vm part of radeon_gart.c +@@ -4810,7 +4813,7 @@ void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) + + /* write new base address */ + radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); +- radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | ++ radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) | + WRITE_DATA_DST_SEL(0))); + + if (vm->id < 8) { +@@ -5955,6 +5958,9 @@ int si_irq_set(struct radeon_device *rdev) + + WREG32(CG_THERMAL_INT, thermal_int); + ++ /* posting read */ ++ RREG32(SRBM_STATUS); ++ + return 0; + } + +@@ -6098,6 +6104,7 @@ static inline u32 si_get_ih_wptr(struct radeon_device *rdev) + tmp = RREG32(IH_RB_CNTL); + tmp |= IH_WPTR_OVERFLOW_CLEAR; + WREG32(IH_RB_CNTL, tmp); ++ wptr &= ~RB_OVERFLOW; + } + return (wptr & rdev->ih.ptr_mask); + } +@@ -6871,8 +6878,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) + WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK); + + if (!vclk || !dclk) { +- /* keep the Bypass mode, put PLL to sleep */ +- WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); ++ /* keep the Bypass mode */ + return 0; + } + +@@ -6888,8 +6894,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) + /* set VCO_MODE to 1 */ + WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_VCO_MODE_MASK, ~UPLL_VCO_MODE_MASK); + +- /* toggle UPLL_SLEEP to 1 then back to 0 */ +- WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); ++ /* disable sleep mode */ + WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_SLEEP_MASK); + + /* deassert UPLL_RESET */ +diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c +index 0a2f5b4..c9053f7 100644 +--- a/drivers/gpu/drm/radeon/si_dpm.c ++++ b/drivers/gpu/drm/radeon/si_dpm.c +@@ -2900,6 +2900,24 @@ static int si_init_smc_spll_table(struct radeon_device *rdev) + return ret; + } + ++struct si_dpm_quirk { ++ u32 chip_vendor; ++ u32 chip_device; ++ u32 subsys_vendor; ++ u32 subsys_device; ++ u32 max_sclk; ++ u32 max_mclk; ++}; ++ ++/* cards with dpm stability problems */ ++static struct si_dpm_quirk si_dpm_quirk_list[] = { ++ /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */ ++ { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 }, ++ { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 }, ++ { PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 }, ++ { 0, 0, 0, 0 }, ++}; ++ + static void si_apply_state_adjust_rules(struct radeon_device *rdev, + struct radeon_ps *rps) + { +@@ -2910,7 +2928,22 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, + u32 mclk, sclk; + u16 vddc, vddci; + u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; ++ u32 max_sclk = 0, max_mclk = 0; + int i; ++ struct si_dpm_quirk *p = si_dpm_quirk_list; ++ ++ /* Apply dpm quirks */ ++ while (p && p->chip_device != 0) { ++ if (rdev->pdev->vendor == p->chip_vendor && ++ rdev->pdev->device == p->chip_device && ++ rdev->pdev->subsystem_vendor == p->subsys_vendor && ++ rdev->pdev->subsystem_device == p->subsys_device) { ++ max_sclk = p->max_sclk; ++ max_mclk = p->max_mclk; ++ break; ++ } ++ ++p; ++ } + + if ((rdev->pm.dpm.new_active_crtc_count > 1) || + ni_dpm_vblank_too_short(rdev)) +@@ -2964,6 +2997,14 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, + if (ps->performance_levels[i].mclk > max_mclk_vddc) + ps->performance_levels[i].mclk = max_mclk_vddc; + } ++ if (max_mclk) { ++ if (ps->performance_levels[i].mclk > max_mclk) ++ ps->performance_levels[i].mclk = max_mclk; ++ } ++ if (max_sclk) { ++ if (ps->performance_levels[i].sclk > max_sclk) ++ ps->performance_levels[i].sclk = max_sclk; ++ } + } + + /* XXX validate the min clocks required for display */ +@@ -6200,7 +6241,7 @@ static void si_parse_pplib_clock_info(struct radeon_device *rdev, + if ((rps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) && + index == 0) { + /* XXX disable for A0 tahiti */ +- si_pi->ulv.supported = true; ++ si_pi->ulv.supported = false; + si_pi->ulv.pl = *pl; + si_pi->ulv.one_pcie_lane_in_ulv = false; + si_pi->ulv.volt_change_delay = SISLANDS_ULVVOLTAGECHANGEDELAY_DFLT; +diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c +index 2da0e17..d9cfa09b 100644 +--- a/drivers/gpu/drm/radeon/trinity_dpm.c ++++ b/drivers/gpu/drm/radeon/trinity_dpm.c +@@ -1877,7 +1877,16 @@ int trinity_dpm_init(struct radeon_device *rdev) + for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) + pi->at[i] = TRINITY_AT_DFLT; + +- pi->enable_bapm = false; ++ /* There are stability issues reported on with ++ * bapm enabled when switching between AC and battery ++ * power. At the same time, some MSI boards hang ++ * if it's not enabled and dpm is enabled. Just enable ++ * it for MSI boards right now. ++ */ ++ if (rdev->pdev->subsystem_vendor == 0x1462) ++ pi->enable_bapm = true; ++ else ++ pi->enable_bapm = false; + pi->enable_nbps_policy = true; + pi->enable_sclk_ds = true; + pi->enable_gfx_power_gating = true; +diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c +index c310a0a..0fa9009 100644 +--- a/drivers/gpu/drm/radeon/uvd_v1_0.c ++++ b/drivers/gpu/drm/radeon/uvd_v1_0.c +@@ -365,18 +365,8 @@ bool uvd_v1_0_semaphore_emit(struct radeon_device *rdev, + struct radeon_semaphore *semaphore, + bool emit_wait) + { +- uint64_t addr = semaphore->gpu_addr; +- +- radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0)); +- radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF); +- +- radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0)); +- radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF); +- +- radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0)); +- radeon_ring_write(ring, emit_wait ? 1 : 0); +- +- return true; ++ /* disable semaphores for UVD V1 hardware */ ++ return false; + } + + /** +diff --git a/drivers/gpu/drm/radeon/uvd_v2_2.c b/drivers/gpu/drm/radeon/uvd_v2_2.c +index d177100..19ccb2a 100644 +--- a/drivers/gpu/drm/radeon/uvd_v2_2.c ++++ b/drivers/gpu/drm/radeon/uvd_v2_2.c +@@ -60,6 +60,35 @@ void uvd_v2_2_fence_emit(struct radeon_device *rdev, + } + + /** ++ * uvd_v2_2_semaphore_emit - emit semaphore command ++ * ++ * @rdev: radeon_device pointer ++ * @ring: radeon_ring pointer ++ * @semaphore: semaphore to emit commands for ++ * @emit_wait: true if we should emit a wait command ++ * ++ * Emit a semaphore command (either wait or signal) to the UVD ring. ++ */ ++bool uvd_v2_2_semaphore_emit(struct radeon_device *rdev, ++ struct radeon_ring *ring, ++ struct radeon_semaphore *semaphore, ++ bool emit_wait) ++{ ++ uint64_t addr = semaphore->gpu_addr; ++ ++ radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0)); ++ radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF); ++ ++ radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0)); ++ radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF); ++ ++ radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0)); ++ radeon_ring_write(ring, emit_wait ? 1 : 0); ++ ++ return true; ++} ++ ++/** + * uvd_v2_2_resume - memory controller programming + * + * @rdev: radeon_device pointer +diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c +index 171a820..52b4711 100644 +--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c ++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c +@@ -84,6 +84,7 @@ static int modeset_init(struct drm_device *dev) + if ((priv->num_encoders == 0) || (priv->num_connectors == 0)) { + /* oh nos! */ + dev_err(dev->dev, "no encoders/connectors found\n"); ++ drm_mode_config_cleanup(dev); + return -ENXIO; + } + +@@ -122,6 +123,7 @@ static int tilcdc_unload(struct drm_device *dev) + struct tilcdc_drm_private *priv = dev->dev_private; + struct tilcdc_module *mod, *cur; + ++ drm_fbdev_cma_fini(priv->fbdev); + drm_kms_helper_poll_fini(dev); + drm_mode_config_cleanup(dev); + drm_vblank_cleanup(dev); +@@ -177,33 +179,37 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) + dev->dev_private = priv; + + priv->wq = alloc_ordered_workqueue("tilcdc", 0); ++ if (!priv->wq) { ++ ret = -ENOMEM; ++ goto fail_free_priv; ++ } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev->dev, "failed to get memory resource\n"); + ret = -EINVAL; +- goto fail; ++ goto fail_free_wq; + } + + priv->mmio = ioremap_nocache(res->start, resource_size(res)); + if (!priv->mmio) { + dev_err(dev->dev, "failed to ioremap\n"); + ret = -ENOMEM; +- goto fail; ++ goto fail_free_wq; + } + + priv->clk = clk_get(dev->dev, "fck"); + if (IS_ERR(priv->clk)) { + dev_err(dev->dev, "failed to get functional clock\n"); + ret = -ENODEV; +- goto fail; ++ goto fail_iounmap; + } + + priv->disp_clk = clk_get(dev->dev, "dpll_disp_ck"); + if (IS_ERR(priv->clk)) { + dev_err(dev->dev, "failed to get display clock\n"); + ret = -ENODEV; +- goto fail; ++ goto fail_put_clk; + } + + #ifdef CONFIG_CPU_FREQ +@@ -213,7 +219,7 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) + CPUFREQ_TRANSITION_NOTIFIER); + if (ret) { + dev_err(dev->dev, "failed to register cpufreq notifier\n"); +- goto fail; ++ goto fail_put_disp_clk; + } + #endif + +@@ -258,13 +264,13 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) + ret = modeset_init(dev); + if (ret < 0) { + dev_err(dev->dev, "failed to initialize mode setting\n"); +- goto fail; ++ goto fail_cpufreq_unregister; + } + + ret = drm_vblank_init(dev, 1); + if (ret < 0) { + dev_err(dev->dev, "failed to initialize vblank\n"); +- goto fail; ++ goto fail_mode_config_cleanup; + } + + pm_runtime_get_sync(dev->dev); +@@ -272,7 +278,7 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) + pm_runtime_put_sync(dev->dev); + if (ret < 0) { + dev_err(dev->dev, "failed to install IRQ handler\n"); +- goto fail; ++ goto fail_vblank_cleanup; + } + + platform_set_drvdata(pdev, dev); +@@ -288,13 +294,48 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) + priv->fbdev = drm_fbdev_cma_init(dev, bpp, + dev->mode_config.num_crtc, + dev->mode_config.num_connector); ++ if (IS_ERR(priv->fbdev)) { ++ ret = PTR_ERR(priv->fbdev); ++ goto fail_irq_uninstall; ++ } + + drm_kms_helper_poll_init(dev); + + return 0; + +-fail: +- tilcdc_unload(dev); ++fail_irq_uninstall: ++ pm_runtime_get_sync(dev->dev); ++ drm_irq_uninstall(dev); ++ pm_runtime_put_sync(dev->dev); ++ ++fail_vblank_cleanup: ++ drm_vblank_cleanup(dev); ++ ++fail_mode_config_cleanup: ++ drm_mode_config_cleanup(dev); ++ ++fail_cpufreq_unregister: ++ pm_runtime_disable(dev->dev); ++#ifdef CONFIG_CPU_FREQ ++ cpufreq_unregister_notifier(&priv->freq_transition, ++ CPUFREQ_TRANSITION_NOTIFIER); ++fail_put_disp_clk: ++ clk_put(priv->disp_clk); ++#endif ++ ++fail_put_clk: ++ clk_put(priv->clk); ++ ++fail_iounmap: ++ iounmap(priv->mmio); ++ ++fail_free_wq: ++ flush_workqueue(priv->wq); ++ destroy_workqueue(priv->wq); ++ ++fail_free_priv: ++ dev->dev_private = NULL; ++ kfree(priv); + return ret; + } + +@@ -628,10 +669,10 @@ static int __init tilcdc_drm_init(void) + static void __exit tilcdc_drm_fini(void) + { + DBG("fini"); +- tilcdc_tfp410_fini(); +- tilcdc_slave_fini(); +- tilcdc_panel_fini(); + platform_driver_unregister(&tilcdc_platform_driver); ++ tilcdc_panel_fini(); ++ tilcdc_slave_fini(); ++ tilcdc_tfp410_fini(); + } + + late_initcall(tilcdc_drm_init); +diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c +index 86c6732..b085dcc 100644 +--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c ++++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c +@@ -151,6 +151,7 @@ struct panel_connector { + static void panel_connector_destroy(struct drm_connector *connector) + { + struct panel_connector *panel_connector = to_panel_connector(connector); ++ drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(panel_connector); + } +@@ -285,10 +286,8 @@ static void panel_destroy(struct tilcdc_module *mod) + { + struct panel_module *panel_mod = to_panel_module(mod); + +- if (panel_mod->timings) { ++ if (panel_mod->timings) + display_timings_release(panel_mod->timings); +- kfree(panel_mod->timings); +- } + + tilcdc_module_cleanup(mod); + kfree(panel_mod->info); +diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c +index 595068b..2f83ffb 100644 +--- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c ++++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c +@@ -166,6 +166,7 @@ struct slave_connector { + static void slave_connector_destroy(struct drm_connector *connector) + { + struct slave_connector *slave_connector = to_slave_connector(connector); ++ drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(slave_connector); + } +diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +index c38b56b..ce75ac8 100644 +--- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c ++++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +@@ -167,6 +167,7 @@ struct tfp410_connector { + static void tfp410_connector_destroy(struct drm_connector *connector) + { + struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector); ++ drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(tfp410_connector); + } +diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c +index 863bef9..76329d2 100644 +--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c ++++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c +@@ -297,9 +297,12 @@ static void ttm_pool_update_free_locked(struct ttm_page_pool *pool, + * + * @pool: to free the pages from + * @free_all: If set to true will free all pages in pool ++ * @use_static: Safe to use static buffer + **/ +-static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free) ++static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free, ++ bool use_static) + { ++ static struct page *static_buf[NUM_PAGES_TO_ALLOC]; + unsigned long irq_flags; + struct page *p; + struct page **pages_to_free; +@@ -309,8 +312,11 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free) + if (NUM_PAGES_TO_ALLOC < nr_free) + npages_to_free = NUM_PAGES_TO_ALLOC; + +- pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), +- GFP_KERNEL); ++ if (use_static) ++ pages_to_free = static_buf; ++ else ++ pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), ++ GFP_KERNEL); + if (!pages_to_free) { + pr_err("Failed to allocate memory for pool free operation\n"); + return 0; +@@ -373,7 +379,8 @@ restart: + if (freed_pages) + ttm_pages_put(pages_to_free, freed_pages); + out: +- kfree(pages_to_free); ++ if (pages_to_free != static_buf) ++ kfree(pages_to_free); + return nr_free; + } + +@@ -382,32 +389,33 @@ out: + * + * XXX: (dchinner) Deadlock warning! + * +- * ttm_page_pool_free() does memory allocation using GFP_KERNEL. that means +- * this can deadlock when called a sc->gfp_mask that is not equal to +- * GFP_KERNEL. +- * + * This code is crying out for a shrinker per pool.... + */ + static unsigned long + ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) + { +- static atomic_t start_pool = ATOMIC_INIT(0); ++ static DEFINE_MUTEX(lock); ++ static unsigned start_pool; + unsigned i; +- unsigned pool_offset = atomic_add_return(1, &start_pool); ++ unsigned pool_offset; + struct ttm_page_pool *pool; + int shrink_pages = sc->nr_to_scan; + unsigned long freed = 0; + +- pool_offset = pool_offset % NUM_POOLS; ++ if (!mutex_trylock(&lock)) ++ return SHRINK_STOP; ++ pool_offset = ++start_pool % NUM_POOLS; + /* select start pool in round robin fashion */ + for (i = 0; i < NUM_POOLS; ++i) { + unsigned nr_free = shrink_pages; + if (shrink_pages == 0) + break; + pool = &_manager->pools[(i + pool_offset)%NUM_POOLS]; +- shrink_pages = ttm_page_pool_free(pool, nr_free); ++ /* OK to use static buffer since global mutex is held. */ ++ shrink_pages = ttm_page_pool_free(pool, nr_free, true); + freed += nr_free - shrink_pages; + } ++ mutex_unlock(&lock); + return freed; + } + +@@ -706,7 +714,7 @@ static void ttm_put_pages(struct page **pages, unsigned npages, int flags, + } + spin_unlock_irqrestore(&pool->lock, irq_flags); + if (npages) +- ttm_page_pool_free(pool, npages); ++ ttm_page_pool_free(pool, npages, false); + } + + /* +@@ -845,8 +853,9 @@ void ttm_page_alloc_fini(void) + pr_info("Finalizing pool allocator\n"); + ttm_pool_mm_shrink_fini(_manager); + ++ /* OK to use static buffer since global mutex is no longer used. */ + for (i = 0; i < NUM_POOLS; ++i) +- ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES); ++ ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES, true); + + kobject_put(&_manager->kobj); + _manager = NULL; +diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +index fb8259f..3dfa97d 100644 +--- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c ++++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +@@ -411,9 +411,12 @@ static void ttm_dma_page_put(struct dma_pool *pool, struct dma_page *d_page) + * + * @pool: to free the pages from + * @nr_free: If set to true will free all pages in pool ++ * @use_static: Safe to use static buffer + **/ +-static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free) ++static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free, ++ bool use_static) + { ++ static struct page *static_buf[NUM_PAGES_TO_ALLOC]; + unsigned long irq_flags; + struct dma_page *dma_p, *tmp; + struct page **pages_to_free; +@@ -430,8 +433,11 @@ static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free) + npages_to_free, nr_free); + } + #endif +- pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), +- GFP_KERNEL); ++ if (use_static) ++ pages_to_free = static_buf; ++ else ++ pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), ++ GFP_KERNEL); + + if (!pages_to_free) { + pr_err("%s: Failed to allocate memory for pool free operation\n", +@@ -501,7 +507,8 @@ restart: + if (freed_pages) + ttm_dma_pages_put(pool, &d_pages, pages_to_free, freed_pages); + out: +- kfree(pages_to_free); ++ if (pages_to_free != static_buf) ++ kfree(pages_to_free); + return nr_free; + } + +@@ -530,7 +537,8 @@ static void ttm_dma_free_pool(struct device *dev, enum pool_type type) + if (pool->type != type) + continue; + /* Takes a spinlock.. */ +- ttm_dma_page_pool_free(pool, FREE_ALL_PAGES); ++ /* OK to use static buffer since global mutex is held. */ ++ ttm_dma_page_pool_free(pool, FREE_ALL_PAGES, true); + WARN_ON(((pool->npages_in_use + pool->npages_free) != 0)); + /* This code path is called after _all_ references to the + * struct device has been dropped - so nobody should be +@@ -983,7 +991,7 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev) + + /* shrink pool if necessary (only on !is_cached pools)*/ + if (npages) +- ttm_dma_page_pool_free(pool, npages); ++ ttm_dma_page_pool_free(pool, npages, false); + ttm->state = tt_unpopulated; + } + EXPORT_SYMBOL_GPL(ttm_dma_unpopulate); +@@ -993,20 +1001,15 @@ EXPORT_SYMBOL_GPL(ttm_dma_unpopulate); + * + * XXX: (dchinner) Deadlock warning! + * +- * ttm_dma_page_pool_free() does GFP_KERNEL memory allocation, and so attention +- * needs to be paid to sc->gfp_mask to determine if this can be done or not. +- * GFP_KERNEL memory allocation in a GFP_ATOMIC reclaim context woul dbe really +- * bad. +- * + * I'm getting sadder as I hear more pathetical whimpers about needing per-pool + * shrinkers + */ + static unsigned long + ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) + { +- static atomic_t start_pool = ATOMIC_INIT(0); ++ static unsigned start_pool; + unsigned idx = 0; +- unsigned pool_offset = atomic_add_return(1, &start_pool); ++ unsigned pool_offset; + unsigned shrink_pages = sc->nr_to_scan; + struct device_pools *p; + unsigned long freed = 0; +@@ -1014,8 +1017,11 @@ ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) + if (list_empty(&_manager->pools)) + return SHRINK_STOP; + +- mutex_lock(&_manager->lock); +- pool_offset = pool_offset % _manager->npools; ++ if (!mutex_trylock(&_manager->lock)) ++ return SHRINK_STOP; ++ if (!_manager->npools) ++ goto out; ++ pool_offset = ++start_pool % _manager->npools; + list_for_each_entry(p, &_manager->pools, pools) { + unsigned nr_free; + +@@ -1027,13 +1033,15 @@ ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) + if (++idx < pool_offset) + continue; + nr_free = shrink_pages; +- shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free); ++ /* OK to use static buffer since global mutex is held. */ ++ shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free, true); + freed += nr_free - shrink_pages; + + pr_debug("%s: (%s:%d) Asked to shrink %d, have %d more to go\n", + p->pool->dev_name, p->pool->name, current->pid, + nr_free, shrink_pages); + } ++out: + mutex_unlock(&_manager->lock); + return freed; + } +@@ -1044,7 +1052,8 @@ ttm_dma_pool_shrink_count(struct shrinker *shrink, struct shrink_control *sc) + struct device_pools *p; + unsigned long count = 0; + +- mutex_lock(&_manager->lock); ++ if (!mutex_trylock(&_manager->lock)) ++ return 0; + list_for_each_entry(p, &_manager->pools, pools) + count += p->pool->npages_free; + mutex_unlock(&_manager->lock); +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +index 0083cbf..0771dcb 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +@@ -688,7 +688,11 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) + goto out_err0; + } + +- if (unlikely(dev_priv->prim_bb_mem < dev_priv->vram_size)) ++ /* ++ * Limit back buffer size to VRAM size. Remove this once ++ * screen targets are implemented. ++ */ ++ if (dev_priv->prim_bb_mem > dev_priv->vram_size) + dev_priv->prim_bb_mem = dev_priv->vram_size; + + mutex_unlock(&dev_priv->hw_mutex); +@@ -729,32 +733,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) + goto out_err1; + } + +- ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM, +- (dev_priv->vram_size >> PAGE_SHIFT)); +- if (unlikely(ret != 0)) { +- DRM_ERROR("Failed initializing memory manager for VRAM.\n"); +- goto out_err2; +- } +- +- dev_priv->has_gmr = true; +- if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) || +- refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR, +- VMW_PL_GMR) != 0) { +- DRM_INFO("No GMR memory available. " +- "Graphics memory resources are very limited.\n"); +- dev_priv->has_gmr = false; +- } +- +- if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) { +- dev_priv->has_mob = true; +- if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB, +- VMW_PL_MOB) != 0) { +- DRM_INFO("No MOB memory available. " +- "3D will be disabled.\n"); +- dev_priv->has_mob = false; +- } +- } +- + dev_priv->mmio_mtrr = arch_phys_wc_add(dev_priv->mmio_start, + dev_priv->mmio_size); + +@@ -817,6 +795,33 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) + goto out_no_fman; + } + ++ ++ ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM, ++ (dev_priv->vram_size >> PAGE_SHIFT)); ++ if (unlikely(ret != 0)) { ++ DRM_ERROR("Failed initializing memory manager for VRAM.\n"); ++ goto out_no_vram; ++ } ++ ++ dev_priv->has_gmr = true; ++ if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) || ++ refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR, ++ VMW_PL_GMR) != 0) { ++ DRM_INFO("No GMR memory available. " ++ "Graphics memory resources are very limited.\n"); ++ dev_priv->has_gmr = false; ++ } ++ ++ if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) { ++ dev_priv->has_mob = true; ++ if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB, ++ VMW_PL_MOB) != 0) { ++ DRM_INFO("No MOB memory available. " ++ "3D will be disabled.\n"); ++ dev_priv->has_mob = false; ++ } ++ } ++ + vmw_kms_save_vga(dev_priv); + + /* Start kms and overlay systems, needs fifo. */ +@@ -842,6 +847,12 @@ out_no_fifo: + vmw_kms_close(dev_priv); + out_no_kms: + vmw_kms_restore_vga(dev_priv); ++ if (dev_priv->has_mob) ++ (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); ++ if (dev_priv->has_gmr) ++ (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); ++ (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); ++out_no_vram: + vmw_fence_manager_takedown(dev_priv->fman); + out_no_fman: + if (dev_priv->capabilities & SVGA_CAP_IRQMASK) +@@ -857,12 +868,6 @@ out_err4: + iounmap(dev_priv->mmio_virt); + out_err3: + arch_phys_wc_del(dev_priv->mmio_mtrr); +- if (dev_priv->has_mob) +- (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); +- if (dev_priv->has_gmr) +- (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); +- (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); +-out_err2: + (void)ttm_bo_device_release(&dev_priv->bdev); + out_err1: + vmw_ttm_global_release(dev_priv); +@@ -892,6 +897,13 @@ static int vmw_driver_unload(struct drm_device *dev) + } + vmw_kms_close(dev_priv); + vmw_overlay_close(dev_priv); ++ ++ if (dev_priv->has_mob) ++ (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); ++ if (dev_priv->has_gmr) ++ (void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); ++ (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); ++ + vmw_fence_manager_takedown(dev_priv->fman); + if (dev_priv->capabilities & SVGA_CAP_IRQMASK) + drm_irq_uninstall(dev_priv->dev); +@@ -903,11 +915,6 @@ static int vmw_driver_unload(struct drm_device *dev) + ttm_object_device_release(&dev_priv->tdev); + iounmap(dev_priv->mmio_virt); + arch_phys_wc_del(dev_priv->mmio_mtrr); +- if (dev_priv->has_mob) +- (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); +- if (dev_priv->has_gmr) +- (void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); +- (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); + (void)ttm_bo_device_release(&dev_priv->bdev); + vmw_ttm_global_release(dev_priv); + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +index a3480c1..9fe10d1 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +@@ -2475,7 +2475,7 @@ int vmw_execbuf_process(struct drm_file *file_priv, + + ret = vmw_resources_validate(sw_context); + if (unlikely(ret != 0)) +- goto out_err; ++ goto out_err_nores; + + if (throttle_us) { + ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue, +@@ -2511,6 +2511,7 @@ int vmw_execbuf_process(struct drm_file *file_priv, + vmw_resource_relocations_free(&sw_context->res_relocations); + + vmw_fifo_commit(dev_priv, command_size); ++ mutex_unlock(&dev_priv->binding_mutex); + + vmw_query_bo_switch_commit(dev_priv, sw_context); + ret = vmw_execbuf_fence_commands(file_priv, dev_priv, +@@ -2526,7 +2527,6 @@ int vmw_execbuf_process(struct drm_file *file_priv, + DRM_ERROR("Fence submission error. Syncing.\n"); + + vmw_resource_list_unreserve(&sw_context->resource_list, false); +- mutex_unlock(&dev_priv->binding_mutex); + + ttm_eu_fence_buffer_objects(&ticket, &sw_context->validate_nodes, + (void *) fence); +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +index 436b013..b65272d 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +@@ -1049,6 +1049,8 @@ static int vmw_event_fence_action_create(struct drm_file *file_priv, + if (ret != 0) + goto out_no_queue; + ++ return 0; ++ + out_no_queue: + event->base.destroy(&event->base); + out_no_event: +@@ -1124,17 +1126,10 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data, + + BUG_ON(fence == NULL); + +- if (arg->flags & DRM_VMW_FE_FLAG_REQ_TIME) +- ret = vmw_event_fence_action_create(file_priv, fence, +- arg->flags, +- arg->user_data, +- true); +- else +- ret = vmw_event_fence_action_create(file_priv, fence, +- arg->flags, +- arg->user_data, +- true); +- ++ ret = vmw_event_fence_action_create(file_priv, fence, ++ arg->flags, ++ arg->user_data, ++ true); + if (unlikely(ret != 0)) { + if (ret != -ERESTARTSYS) + DRM_ERROR("Failed to attach event to fence.\n"); +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +index 6ccd993..6eae14d 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +@@ -180,8 +180,9 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) + + mutex_lock(&dev_priv->hw_mutex); + ++ vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC); + while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0) +- vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC); ++ ; + + dev_priv->last_read_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE); + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +index 8a65041..c8f8ecf 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +@@ -1954,6 +1954,14 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) + }; + int i; ++ u32 assumed_bpp = 2; ++ ++ /* ++ * If using screen objects, then assume 32-bpp because that's what the ++ * SVGA device is assuming ++ */ ++ if (dev_priv->sou_priv) ++ assumed_bpp = 4; + + /* Add preferred mode */ + { +@@ -1964,8 +1972,9 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector, + mode->vdisplay = du->pref_height; + vmw_guess_mode_timing(mode); + +- if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2, +- mode->vdisplay)) { ++ if (vmw_kms_validate_mode_vram(dev_priv, ++ mode->hdisplay * assumed_bpp, ++ mode->vdisplay)) { + drm_mode_probed_add(connector, mode); + } else { + drm_mode_destroy(dev, mode); +@@ -1987,7 +1996,8 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector, + bmode->vdisplay > max_height) + continue; + +- if (!vmw_kms_validate_mode_vram(dev_priv, bmode->hdisplay * 2, ++ if (!vmw_kms_validate_mode_vram(dev_priv, ++ bmode->hdisplay * assumed_bpp, + bmode->vdisplay)) + continue; + +diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c +index 6866448..37ac7b5 100644 +--- a/drivers/gpu/vga/vga_switcheroo.c ++++ b/drivers/gpu/vga/vga_switcheroo.c +@@ -660,6 +660,12 @@ int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain * + } + EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_ops); + ++void vga_switcheroo_fini_domain_pm_ops(struct device *dev) ++{ ++ dev->pm_domain = NULL; ++} ++EXPORT_SYMBOL(vga_switcheroo_fini_domain_pm_ops); ++ + static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev) + { + struct pci_dev *pdev = to_pci_dev(dev); +diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c +index 1bdcccc..f745d2c 100644 +--- a/drivers/hid/hid-cherry.c ++++ b/drivers/hid/hid-cherry.c +@@ -28,7 +28,7 @@ + static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) + { +- if (*rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { ++ if (*rsize >= 18 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { + hid_info(hdev, "fixing up Cherry Cymotion report descriptor\n"); + rdesc[11] = rdesc[16] = 0xff; + rdesc[12] = rdesc[17] = 0x03; +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 7cd42ea..d92c7d9 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1743,6 +1743,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) }, +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 6e12cd0..4850da3 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -292,6 +292,11 @@ + #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7 0x73f7 + #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001 + ++#define USB_VENDOR_ID_ELAN 0x04f3 ++#define USB_DEVICE_ID_ELAN_TOUCHSCREEN 0x0089 ++#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B 0x009b ++#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F 0x016f ++ + #define USB_VENDOR_ID_ELECOM 0x056e + #define USB_DEVICE_ID_ELECOM_BM084 0x0061 + +@@ -506,6 +511,7 @@ + #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 + #define USB_DEVICE_ID_KYE_EASYPEN_I405X 0x5010 + #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X 0x5011 ++#define USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2 0x501a + #define USB_DEVICE_ID_KYE_EASYPEN_M610X 0x5013 + + #define USB_VENDOR_ID_LABTEC 0x1020 +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index a713e62..a413f76 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -312,6 +312,9 @@ static const struct hid_device_id hid_battery_quirks[] = { + USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI), + HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, ++ USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO), ++ HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE }, ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI), + HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE }, + {} +@@ -1063,6 +1066,23 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct + return; + } + ++ /* ++ * Ignore reports for absolute data if the data didn't change. This is ++ * not only an optimization but also fixes 'dead' key reports. Some ++ * RollOver implementations for localized keys (like BACKSLASH/PIPE; HID ++ * 0x31 and 0x32) report multiple keys, even though a localized keyboard ++ * can only have one of them physically available. The 'dead' keys ++ * report constant 0. As all map to the same keycode, they'd confuse ++ * the input layer. If we filter the 'dead' keys on the HID level, we ++ * skip the keycode translation and only forward real events. ++ */ ++ if (!(field->flags & (HID_MAIN_ITEM_RELATIVE | ++ HID_MAIN_ITEM_BUFFERED_BYTE)) && ++ (field->flags & HID_MAIN_ITEM_VARIABLE) && ++ usage->usage_index < field->maxusage && ++ value == field->value[usage->usage_index]) ++ return; ++ + /* report the usage code as scancode if the key status has changed */ + if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value) + input_event(input, EV_MSC, MSC_SCAN, usage->hid); +diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c +index e776963..158fcf5 100644 +--- a/drivers/hid/hid-kye.c ++++ b/drivers/hid/hid-kye.c +@@ -300,7 +300,7 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, + * - change the button usage range to 4-7 for the extra + * buttons + */ +- if (*rsize >= 74 && ++ if (*rsize >= 75 && + rdesc[61] == 0x05 && rdesc[62] == 0x08 && + rdesc[63] == 0x19 && rdesc[64] == 0x08 && + rdesc[65] == 0x29 && rdesc[66] == 0x0f && +@@ -323,6 +323,7 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, + } + break; + case USB_DEVICE_ID_KYE_MOUSEPEN_I608X: ++ case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2: + if (*rsize == MOUSEPEN_I608X_RDESC_ORIG_SIZE) { + rdesc = mousepen_i608x_rdesc_fixed; + *rsize = sizeof(mousepen_i608x_rdesc_fixed); +@@ -415,6 +416,7 @@ static int kye_probe(struct hid_device *hdev, const struct hid_device_id *id) + switch (id->product) { + case USB_DEVICE_ID_KYE_EASYPEN_I405X: + case USB_DEVICE_ID_KYE_MOUSEPEN_I608X: ++ case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2: + case USB_DEVICE_ID_KYE_EASYPEN_M610X: + ret = kye_tablet_enable(hdev); + if (ret) { +@@ -446,6 +448,8 @@ static const struct hid_device_id kye_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, + USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, ++ USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, + USB_DEVICE_ID_KYE_EASYPEN_M610X) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, + USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) }, +diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c +index 9fe9d4a..b8207e0 100644 +--- a/drivers/hid/hid-lg.c ++++ b/drivers/hid/hid-lg.c +@@ -345,14 +345,14 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, + struct usb_device_descriptor *udesc; + __u16 bcdDevice, rev_maj, rev_min; + +- if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 && ++ if ((drv_data->quirks & LG_RDESC) && *rsize >= 91 && rdesc[83] == 0x26 && + rdesc[84] == 0x8c && rdesc[85] == 0x02) { + hid_info(hdev, + "fixing up Logitech keyboard report descriptor\n"); + rdesc[84] = rdesc[89] = 0x4d; + rdesc[85] = rdesc[90] = 0x10; + } +- if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 50 && ++ if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 51 && + rdesc[32] == 0x81 && rdesc[33] == 0x06 && + rdesc[49] == 0x81 && rdesc[50] == 0x06) { + hid_info(hdev, +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index f45279c..5da115a 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -237,13 +237,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, + return; + } + +- if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) || +- (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) { +- dev_err(&djrcv_hdev->dev, "%s: invalid device index:%d\n", +- __func__, dj_report->device_index); +- return; +- } +- + if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { + /* The device is already known. No need to reallocate it. */ + dbg_hid("%s: device is already known\n", __func__); +@@ -694,7 +687,6 @@ static int logi_dj_raw_event(struct hid_device *hdev, + struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); + struct dj_report *dj_report = (struct dj_report *) data; + unsigned long flags; +- bool report_processed = false; + + dbg_hid("%s, size:%d\n", __func__, size); + +@@ -722,27 +714,41 @@ static int logi_dj_raw_event(struct hid_device *hdev, + * anything else with it. + */ + ++ /* case 1) */ ++ if (data[0] != REPORT_ID_DJ_SHORT) ++ return false; ++ ++ if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) || ++ (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) { ++ /* ++ * Device index is wrong, bail out. ++ * This driver can ignore safely the receiver notifications, ++ * so ignore those reports too. ++ */ ++ if (dj_report->device_index != DJ_RECEIVER_INDEX) ++ dev_err(&hdev->dev, "%s: invalid device index:%d\n", ++ __func__, dj_report->device_index); ++ return false; ++ } ++ + spin_lock_irqsave(&djrcv_dev->lock, flags); +- if (dj_report->report_id == REPORT_ID_DJ_SHORT) { +- switch (dj_report->report_type) { +- case REPORT_TYPE_NOTIF_DEVICE_PAIRED: +- case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED: +- logi_dj_recv_queue_notification(djrcv_dev, dj_report); +- break; +- case REPORT_TYPE_NOTIF_CONNECTION_STATUS: +- if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] == +- STATUS_LINKLOSS) { +- logi_dj_recv_forward_null_report(djrcv_dev, dj_report); +- } +- break; +- default: +- logi_dj_recv_forward_report(djrcv_dev, dj_report); ++ switch (dj_report->report_type) { ++ case REPORT_TYPE_NOTIF_DEVICE_PAIRED: ++ case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED: ++ logi_dj_recv_queue_notification(djrcv_dev, dj_report); ++ break; ++ case REPORT_TYPE_NOTIF_CONNECTION_STATUS: ++ if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] == ++ STATUS_LINKLOSS) { ++ logi_dj_recv_forward_null_report(djrcv_dev, dj_report); + } +- report_processed = true; ++ break; ++ default: ++ logi_dj_recv_forward_report(djrcv_dev, dj_report); + } + spin_unlock_irqrestore(&djrcv_dev->lock, flags); + +- return report_processed; ++ return true; + } + + static int logi_dj_probe(struct hid_device *hdev, +diff --git a/drivers/hid/hid-logitech-dj.h b/drivers/hid/hid-logitech-dj.h +index 4a40003..daeb0aa 100644 +--- a/drivers/hid/hid-logitech-dj.h ++++ b/drivers/hid/hid-logitech-dj.h +@@ -27,6 +27,7 @@ + + #define DJ_MAX_PAIRED_DEVICES 6 + #define DJ_MAX_NUMBER_NOTIFICATIONS 8 ++#define DJ_RECEIVER_INDEX 0 + #define DJ_DEVICE_INDEX_MIN 1 + #define DJ_DEVICE_INDEX_MAX 6 + +diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c +index 3b43d1c..991ba79 100644 +--- a/drivers/hid/hid-magicmouse.c ++++ b/drivers/hid/hid-magicmouse.c +@@ -290,6 +290,11 @@ static int magicmouse_raw_event(struct hid_device *hdev, + if (size < 4 || ((size - 4) % 9) != 0) + return 0; + npoints = (size - 4) / 9; ++ if (npoints > 15) { ++ hid_warn(hdev, "invalid size value (%d) for TRACKPAD_REPORT_ID\n", ++ size); ++ return 0; ++ } + msc->ntouches = 0; + for (ii = 0; ii < npoints; ii++) + magicmouse_emit_touch(msc, ii, data + ii * 9 + 4); +@@ -307,6 +312,11 @@ static int magicmouse_raw_event(struct hid_device *hdev, + if (size < 6 || ((size - 6) % 8) != 0) + return 0; + npoints = (size - 6) / 8; ++ if (npoints > 15) { ++ hid_warn(hdev, "invalid size value (%d) for MOUSE_REPORT_ID\n", ++ size); ++ return 0; ++ } + msc->ntouches = 0; + for (ii = 0; ii < npoints; ii++) + magicmouse_emit_touch(msc, ii, data + ii * 8 + 6); +diff --git a/drivers/hid/hid-monterey.c b/drivers/hid/hid-monterey.c +index 9e14c00..25daf28 100644 +--- a/drivers/hid/hid-monterey.c ++++ b/drivers/hid/hid-monterey.c +@@ -24,7 +24,7 @@ + static __u8 *mr_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) + { +- if (*rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) { ++ if (*rsize >= 31 && rdesc[29] == 0x05 && rdesc[30] == 0x09) { + hid_info(hdev, "fixing up button/consumer in HID report descriptor\n"); + rdesc[30] = 0x0c; + } +diff --git a/drivers/hid/hid-petalynx.c b/drivers/hid/hid-petalynx.c +index 736b250..6aca4f2 100644 +--- a/drivers/hid/hid-petalynx.c ++++ b/drivers/hid/hid-petalynx.c +@@ -25,7 +25,7 @@ + static __u8 *pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) + { +- if (*rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 && ++ if (*rsize >= 62 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 && + rdesc[41] == 0x00 && rdesc[59] == 0x26 && + rdesc[60] == 0xf9 && rdesc[61] == 0x00) { + hid_info(hdev, "fixing up Petalynx Maxter Remote report descriptor\n"); +diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c +index acbb0210..020df3c 100644 +--- a/drivers/hid/hid-picolcd_core.c ++++ b/drivers/hid/hid-picolcd_core.c +@@ -350,6 +350,12 @@ static int picolcd_raw_event(struct hid_device *hdev, + if (!data) + return 1; + ++ if (size > 64) { ++ hid_warn(hdev, "invalid size value (%d) for picolcd raw event\n", ++ size); ++ return 0; ++ } ++ + if (report->id == REPORT_KEY_STATE) { + if (data->input_keys) + ret = picolcd_raw_keypad(data, report, raw_data+1, size-1); +diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c +index 1a07e07..47d7e74 100644 +--- a/drivers/hid/hid-roccat-pyra.c ++++ b/drivers/hid/hid-roccat-pyra.c +@@ -35,6 +35,8 @@ static struct class *pyra_class; + static void profile_activated(struct pyra_device *pyra, + unsigned int new_profile) + { ++ if (new_profile >= ARRAY_SIZE(pyra->profile_settings)) ++ return; + pyra->actual_profile = new_profile; + pyra->actual_cpi = pyra->profile_settings[pyra->actual_profile].y_cpi; + } +@@ -257,9 +259,11 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp, + if (off != 0 || count != PYRA_SIZE_SETTINGS) + return -EINVAL; + +- mutex_lock(&pyra->pyra_lock); +- + settings = (struct pyra_settings const *)buf; ++ if (settings->startup_profile >= ARRAY_SIZE(pyra->profile_settings)) ++ return -EINVAL; ++ ++ mutex_lock(&pyra->pyra_lock); + + retval = pyra_set_settings(usb_dev, settings); + if (retval) { +diff --git a/drivers/hid/hid-sunplus.c b/drivers/hid/hid-sunplus.c +index 87fc91e..91072fa 100644 +--- a/drivers/hid/hid-sunplus.c ++++ b/drivers/hid/hid-sunplus.c +@@ -24,7 +24,7 @@ + static __u8 *sp_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) + { +- if (*rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 && ++ if (*rsize >= 112 && rdesc[104] == 0x26 && rdesc[105] == 0x80 && + rdesc[106] == 0x03) { + hid_info(hdev, "fixing up Sunplus Wireless Desktop report descriptor\n"); + rdesc[105] = rdesc[110] = 0x03; +diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c +index 42eebd1..17be889 100644 +--- a/drivers/hid/i2c-hid/i2c-hid.c ++++ b/drivers/hid/i2c-hid/i2c-hid.c +@@ -136,6 +136,7 @@ struct i2c_hid { + * descriptor. */ + unsigned int bufsize; /* i2c buffer size */ + char *inbuf; /* Input buffer */ ++ char *rawbuf; /* Raw Input buffer */ + char *cmdbuf; /* Command buffer */ + char *argsbuf; /* Command arguments buffer */ + +@@ -357,6 +358,9 @@ static void i2c_hid_get_input(struct i2c_hid *ihid) + int ret, ret_size; + int size = le16_to_cpu(ihid->hdesc.wMaxInputLength); + ++ if (size > ihid->bufsize) ++ size = ihid->bufsize; ++ + ret = i2c_master_recv(ihid->client, ihid->inbuf, size); + if (ret != size) { + if (ret < 0) +@@ -482,9 +486,11 @@ static void i2c_hid_find_max_report(struct hid_device *hid, unsigned int type, + static void i2c_hid_free_buffers(struct i2c_hid *ihid) + { + kfree(ihid->inbuf); ++ kfree(ihid->rawbuf); + kfree(ihid->argsbuf); + kfree(ihid->cmdbuf); + ihid->inbuf = NULL; ++ ihid->rawbuf = NULL; + ihid->cmdbuf = NULL; + ihid->argsbuf = NULL; + ihid->bufsize = 0; +@@ -500,10 +506,11 @@ static int i2c_hid_alloc_buffers(struct i2c_hid *ihid, size_t report_size) + report_size; /* report */ + + ihid->inbuf = kzalloc(report_size, GFP_KERNEL); ++ ihid->rawbuf = kzalloc(report_size, GFP_KERNEL); + ihid->argsbuf = kzalloc(args_len, GFP_KERNEL); + ihid->cmdbuf = kzalloc(sizeof(union command) + args_len, GFP_KERNEL); + +- if (!ihid->inbuf || !ihid->argsbuf || !ihid->cmdbuf) { ++ if (!ihid->inbuf || !ihid->rawbuf || !ihid->argsbuf || !ihid->cmdbuf) { + i2c_hid_free_buffers(ihid); + return -ENOMEM; + } +@@ -530,12 +537,12 @@ static int i2c_hid_get_raw_report(struct hid_device *hid, + + ret = i2c_hid_get_report(client, + report_type == HID_FEATURE_REPORT ? 0x03 : 0x01, +- report_number, ihid->inbuf, ask_count); ++ report_number, ihid->rawbuf, ask_count); + + if (ret < 0) + return ret; + +- ret_count = ihid->inbuf[0] | (ihid->inbuf[1] << 8); ++ ret_count = ihid->rawbuf[0] | (ihid->rawbuf[1] << 8); + + if (ret_count <= 2) + return 0; +@@ -544,7 +551,7 @@ static int i2c_hid_get_raw_report(struct hid_device *hid, + + /* The query buffer contains the size, dropping it in the reply */ + count = min(count, ret_count - 2); +- memcpy(buf, ihid->inbuf + 2, count); ++ memcpy(buf, ihid->rawbuf + 2, count); + + return count; + } +diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c +index 44df131..deabd2c 100644 +--- a/drivers/hid/usbhid/hid-core.c ++++ b/drivers/hid/usbhid/hid-core.c +@@ -82,7 +82,7 @@ static int hid_start_in(struct hid_device *hid) + struct usbhid_device *usbhid = hid->driver_data; + + spin_lock_irqsave(&usbhid->lock, flags); +- if (hid->open > 0 && ++ if ((hid->open > 0 || hid->quirks & HID_QUIRK_ALWAYS_POLL) && + !test_bit(HID_DISCONNECTED, &usbhid->iofl) && + !test_bit(HID_SUSPENDED, &usbhid->iofl) && + !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { +@@ -180,7 +180,7 @@ static void hid_io_error(struct hid_device *hid) + if (time_after(jiffies, usbhid->stop_retry)) { + + /* Retries failed, so do a port reset unless we lack bandwidth*/ +- if (test_bit(HID_NO_BANDWIDTH, &usbhid->iofl) ++ if (!test_bit(HID_NO_BANDWIDTH, &usbhid->iofl) + && !test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) { + + schedule_work(&usbhid->reset_work); +@@ -292,6 +292,8 @@ static void hid_irq_in(struct urb *urb) + case 0: /* success */ + usbhid_mark_busy(usbhid); + usbhid->retry_delay = 0; ++ if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open) ++ break; + hid_input_report(urb->context, HID_INPUT_REPORT, + urb->transfer_buffer, + urb->actual_length, 1); +@@ -734,8 +736,10 @@ void usbhid_close(struct hid_device *hid) + if (!--hid->open) { + spin_unlock_irq(&usbhid->lock); + hid_cancel_delayed_stuff(usbhid); +- usb_kill_urb(usbhid->urbin); +- usbhid->intf->needs_remote_wakeup = 0; ++ if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) { ++ usb_kill_urb(usbhid->urbin); ++ usbhid->intf->needs_remote_wakeup = 0; ++ } + } else { + spin_unlock_irq(&usbhid->lock); + } +@@ -1119,6 +1123,19 @@ static int usbhid_start(struct hid_device *hid) + + set_bit(HID_STARTED, &usbhid->iofl); + ++ if (hid->quirks & HID_QUIRK_ALWAYS_POLL) { ++ ret = usb_autopm_get_interface(usbhid->intf); ++ if (ret) ++ goto fail; ++ usbhid->intf->needs_remote_wakeup = 1; ++ ret = hid_start_in(hid); ++ if (ret) { ++ dev_err(&hid->dev, ++ "failed to start in urb: %d\n", ret); ++ } ++ usb_autopm_put_interface(usbhid->intf); ++ } ++ + /* Some keyboards don't work until their LEDs have been set. + * Since BIOSes do set the LEDs, it must be safe for any device + * that supports the keyboard boot protocol. +@@ -1151,6 +1168,9 @@ static void usbhid_stop(struct hid_device *hid) + if (WARN_ON(!usbhid)) + return; + ++ if (hid->quirks & HID_QUIRK_ALWAYS_POLL) ++ usbhid->intf->needs_remote_wakeup = 0; ++ + clear_bit(HID_STARTED, &usbhid->iofl); + spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */ + set_bit(HID_DISCONNECTED, &usbhid->iofl); +diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c +index 8e4ddb3..473c0c4 100644 +--- a/drivers/hid/usbhid/hid-quirks.c ++++ b/drivers/hid/usbhid/hid-quirks.c +@@ -69,6 +69,9 @@ static const struct hid_blacklist { + { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, ++ { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN, HID_QUIRK_ALWAYS_POLL }, ++ { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B, HID_QUIRK_ALWAYS_POLL }, ++ { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F, HID_QUIRK_ALWAYS_POLL }, + { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, +@@ -113,6 +116,7 @@ static const struct hid_blacklist { + { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT }, ++ { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS }, +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +index 69ea36f..356f22f 100644 +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -134,7 +134,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, + GFP_KERNEL); + if (!open_info) { + err = -ENOMEM; +- goto error0; ++ goto error_gpadl; + } + + init_completion(&open_info->waitevent); +@@ -150,7 +150,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, + + if (userdatalen > MAX_USER_DEFINED_BYTES) { + err = -EINVAL; +- goto error0; ++ goto error_gpadl; + } + + if (userdatalen) +@@ -164,8 +164,10 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, + ret = vmbus_post_msg(open_msg, + sizeof(struct vmbus_channel_open_channel)); + +- if (ret != 0) ++ if (ret != 0) { ++ err = ret; + goto error1; ++ } + + t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ); + if (t == 0) { +@@ -192,6 +194,9 @@ error1: + list_del(&open_info->msglistentry); + spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); + ++error_gpadl: ++ vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle); ++ + error0: + free_pages((unsigned long)out, + get_order(send_ringbuffer_size + recv_ringbuffer_size)); +@@ -362,7 +367,6 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, + u32 next_gpadl_handle; + unsigned long flags; + int ret = 0; +- int t; + + next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle); + atomic_inc(&vmbus_connection.next_gpadl_handle); +@@ -409,9 +413,7 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, + + } + } +- t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ); +- BUG_ON(t == 0); +- ++ wait_for_completion(&msginfo->waitevent); + + /* At this point, we received the gpadl created msg */ + *gpadl_handle = gpadlmsg->gpadl; +@@ -434,7 +436,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) + struct vmbus_channel_gpadl_teardown *msg; + struct vmbus_channel_msginfo *info; + unsigned long flags; +- int ret, t; ++ int ret; + + info = kmalloc(sizeof(*info) + + sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL); +@@ -456,11 +458,12 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) + ret = vmbus_post_msg(msg, + sizeof(struct vmbus_channel_gpadl_teardown)); + +- BUG_ON(ret != 0); +- t = wait_for_completion_timeout(&info->waitevent, 5*HZ); +- BUG_ON(t == 0); ++ if (ret) ++ goto post_msg_err; ++ ++ wait_for_completion(&info->waitevent); + +- /* Received a torndown response */ ++post_msg_err: + spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); + list_del(&info->msglistentry); + spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); +@@ -470,7 +473,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) + } + EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl); + +-static void vmbus_close_internal(struct vmbus_channel *channel) ++static int vmbus_close_internal(struct vmbus_channel *channel) + { + struct vmbus_channel_close_channel *msg; + int ret; +@@ -492,11 +495,28 @@ static void vmbus_close_internal(struct vmbus_channel *channel) + + ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel)); + +- BUG_ON(ret != 0); ++ if (ret) { ++ pr_err("Close failed: close post msg return is %d\n", ret); ++ /* ++ * If we failed to post the close msg, ++ * it is perhaps better to leak memory. ++ */ ++ return ret; ++ } ++ + /* Tear down the gpadl for the channel's ring buffer */ +- if (channel->ringbuffer_gpadlhandle) +- vmbus_teardown_gpadl(channel, +- channel->ringbuffer_gpadlhandle); ++ if (channel->ringbuffer_gpadlhandle) { ++ ret = vmbus_teardown_gpadl(channel, ++ channel->ringbuffer_gpadlhandle); ++ if (ret) { ++ pr_err("Close failed: teardown gpadl return %d\n", ret); ++ /* ++ * If we failed to teardown gpadl, ++ * it is perhaps better to leak memory. ++ */ ++ return ret; ++ } ++ } + + /* Cleanup the ring buffers for this channel */ + hv_ringbuffer_cleanup(&channel->outbound); +@@ -505,7 +525,7 @@ static void vmbus_close_internal(struct vmbus_channel *channel) + free_pages((unsigned long)channel->ringbuffer_pages, + get_order(channel->ringbuffer_pagecount * PAGE_SIZE)); + +- ++ return ret; + } + + /* +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index fa92046..8c24881 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -202,9 +202,16 @@ static void vmbus_process_rescind_offer(struct work_struct *work) + unsigned long flags; + struct vmbus_channel *primary_channel; + struct vmbus_channel_relid_released msg; ++ struct device *dev; ++ ++ if (channel->device_obj) { ++ dev = get_device(&channel->device_obj->device); ++ if (dev) { ++ vmbus_device_unregister(channel->device_obj); ++ put_device(dev); ++ } ++ } + +- if (channel->device_obj) +- vmbus_device_unregister(channel->device_obj); + memset(&msg, 0, sizeof(struct vmbus_channel_relid_released)); + msg.child_relid = channel->offermsg.child_relid; + msg.header.msgtype = CHANNELMSG_RELID_RELEASED; +@@ -709,7 +716,7 @@ int vmbus_request_offers(void) + { + struct vmbus_channel_message_header *msg; + struct vmbus_channel_msginfo *msginfo; +- int ret, t; ++ int ret; + + msginfo = kmalloc(sizeof(*msginfo) + + sizeof(struct vmbus_channel_message_header), +@@ -717,8 +724,6 @@ int vmbus_request_offers(void) + if (!msginfo) + return -ENOMEM; + +- init_completion(&msginfo->waitevent); +- + msg = (struct vmbus_channel_message_header *)msginfo->msg; + + msg->msgtype = CHANNELMSG_REQUESTOFFERS; +@@ -732,14 +737,6 @@ int vmbus_request_offers(void) + goto cleanup; + } + +- t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ); +- if (t == 0) { +- ret = -ETIMEDOUT; +- goto cleanup; +- } +- +- +- + cleanup: + kfree(msginfo); + +diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c +index ce5a9f2..d8fd95c 100644 +--- a/drivers/hv/connection.c ++++ b/drivers/hv/connection.c +@@ -408,10 +408,21 @@ int vmbus_post_msg(void *buffer, size_t buflen) + * insufficient resources. Retry the operation a couple of + * times before giving up. + */ +- while (retries < 3) { +- ret = hv_post_message(conn_id, 1, buffer, buflen); +- if (ret != HV_STATUS_INSUFFICIENT_BUFFERS) ++ while (retries < 10) { ++ ret = hv_post_message(conn_id, 1, buffer, buflen); ++ ++ switch (ret) { ++ case HV_STATUS_INSUFFICIENT_BUFFERS: ++ ret = -ENOMEM; ++ case -ENOMEM: ++ break; ++ case HV_STATUS_SUCCESS: + return ret; ++ default: ++ pr_err("hv_post_msg() failed; error code:%d\n", ret); ++ return -EINVAL; ++ } ++ + retries++; + msleep(100); + } +diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c +index 7f9dc2f..1265164 100644 +--- a/drivers/hwmon/ads1015.c ++++ b/drivers/hwmon/ads1015.c +@@ -198,7 +198,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) + } + + channel = be32_to_cpup(property); +- if (channel > ADS1015_CHANNELS) { ++ if (channel >= ADS1015_CHANNELS) { + dev_err(&client->dev, + "invalid channel index %d on %s\n", + channel, node->full_name); +@@ -212,6 +212,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) + dev_err(&client->dev, + "invalid gain on %s\n", + node->full_name); ++ return -EINVAL; + } + } + +@@ -222,6 +223,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) + dev_err(&client->dev, + "invalid data_rate on %s\n", + node->full_name); ++ return -EINVAL; + } + } + +diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c +index 9f2be3d..8a67ec6 100644 +--- a/drivers/hwmon/amc6821.c ++++ b/drivers/hwmon/amc6821.c +@@ -360,11 +360,13 @@ static ssize_t set_pwm1_enable( + if (config) + return config; + ++ mutex_lock(&data->update_lock); + config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); + if (config < 0) { + dev_err(&client->dev, + "Error reading configuration register, aborting.\n"); +- return config; ++ count = config; ++ goto unlock; + } + + switch (val) { +@@ -381,14 +383,15 @@ static ssize_t set_pwm1_enable( + config |= AMC6821_CONF1_FDRC1; + break; + default: +- return -EINVAL; ++ count = -EINVAL; ++ goto unlock; + } +- mutex_lock(&data->update_lock); + if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) { + dev_err(&client->dev, + "Configuration register write error, aborting.\n"); + count = -EIO; + } ++unlock: + mutex_unlock(&data->update_lock); + return count; + } +@@ -493,8 +496,9 @@ static ssize_t set_temp_auto_point_temp( + return -EINVAL; + } + +- data->valid = 0; + mutex_lock(&data->update_lock); ++ data->valid = 0; ++ + switch (ix) { + case 0: + ptemp[0] = clamp_val(val / 1000, 0, +@@ -658,13 +662,14 @@ static ssize_t set_fan1_div( + if (config) + return config; + ++ mutex_lock(&data->update_lock); + config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4); + if (config < 0) { + dev_err(&client->dev, + "Error reading configuration register, aborting.\n"); +- return config; ++ count = config; ++ goto EXIT; + } +- mutex_lock(&data->update_lock); + switch (val) { + case 2: + config &= ~AMC6821_CONF4_PSPR; +diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c +index 4ae3fff..bea0a34 100644 +--- a/drivers/hwmon/dme1737.c ++++ b/drivers/hwmon/dme1737.c +@@ -247,8 +247,8 @@ struct dme1737_data { + u8 pwm_acz[3]; + u8 pwm_freq[6]; + u8 pwm_rr[2]; +- u8 zone_low[3]; +- u8 zone_abs[3]; ++ s8 zone_low[3]; ++ s8 zone_abs[3]; + u8 zone_hyst[2]; + u32 alarms; + }; +@@ -277,7 +277,7 @@ static inline int IN_FROM_REG(int reg, int nominal, int res) + return (reg * nominal + (3 << (res - 3))) / (3 << (res - 2)); + } + +-static inline int IN_TO_REG(int val, int nominal) ++static inline int IN_TO_REG(long val, int nominal) + { + return clamp_val((val * 192 + nominal / 2) / nominal, 0, 255); + } +@@ -293,7 +293,7 @@ static inline int TEMP_FROM_REG(int reg, int res) + return (reg * 1000) >> (res - 8); + } + +-static inline int TEMP_TO_REG(int val) ++static inline int TEMP_TO_REG(long val) + { + return clamp_val((val < 0 ? val - 500 : val + 500) / 1000, -128, 127); + } +@@ -308,7 +308,7 @@ static inline int TEMP_RANGE_FROM_REG(int reg) + return TEMP_RANGE[(reg >> 4) & 0x0f]; + } + +-static int TEMP_RANGE_TO_REG(int val, int reg) ++static int TEMP_RANGE_TO_REG(long val, int reg) + { + int i; + +@@ -331,7 +331,7 @@ static inline int TEMP_HYST_FROM_REG(int reg, int ix) + return (((ix == 1) ? reg : reg >> 4) & 0x0f) * 1000; + } + +-static inline int TEMP_HYST_TO_REG(int val, int ix, int reg) ++static inline int TEMP_HYST_TO_REG(long val, int ix, int reg) + { + int hyst = clamp_val((val + 500) / 1000, 0, 15); + +@@ -347,7 +347,7 @@ static inline int FAN_FROM_REG(int reg, int tpc) + return (reg == 0 || reg == 0xffff) ? 0 : 90000 * 60 / reg; + } + +-static inline int FAN_TO_REG(int val, int tpc) ++static inline int FAN_TO_REG(long val, int tpc) + { + if (tpc) { + return clamp_val(val / tpc, 0, 0xffff); +@@ -379,7 +379,7 @@ static inline int FAN_TYPE_FROM_REG(int reg) + return (edge > 0) ? 1 << (edge - 1) : 0; + } + +-static inline int FAN_TYPE_TO_REG(int val, int reg) ++static inline int FAN_TYPE_TO_REG(long val, int reg) + { + int edge = (val == 4) ? 3 : val; + +@@ -402,7 +402,7 @@ static int FAN_MAX_FROM_REG(int reg) + return 1000 + i * 500; + } + +-static int FAN_MAX_TO_REG(int val) ++static int FAN_MAX_TO_REG(long val) + { + int i; + +@@ -460,7 +460,7 @@ static inline int PWM_ACZ_FROM_REG(int reg) + return acz[(reg >> 5) & 0x07]; + } + +-static inline int PWM_ACZ_TO_REG(int val, int reg) ++static inline int PWM_ACZ_TO_REG(long val, int reg) + { + int acz = (val == 4) ? 2 : val - 1; + +@@ -476,7 +476,7 @@ static inline int PWM_FREQ_FROM_REG(int reg) + return PWM_FREQ[reg & 0x0f]; + } + +-static int PWM_FREQ_TO_REG(int val, int reg) ++static int PWM_FREQ_TO_REG(long val, int reg) + { + int i; + +@@ -510,7 +510,7 @@ static inline int PWM_RR_FROM_REG(int reg, int ix) + return (rr & 0x08) ? PWM_RR[rr & 0x07] : 0; + } + +-static int PWM_RR_TO_REG(int val, int ix, int reg) ++static int PWM_RR_TO_REG(long val, int ix, int reg) + { + int i; + +@@ -528,7 +528,7 @@ static inline int PWM_RR_EN_FROM_REG(int reg, int ix) + return PWM_RR_FROM_REG(reg, ix) ? 1 : 0; + } + +-static inline int PWM_RR_EN_TO_REG(int val, int ix, int reg) ++static inline int PWM_RR_EN_TO_REG(long val, int ix, int reg) + { + int en = (ix == 1) ? 0x80 : 0x08; + +@@ -1481,13 +1481,16 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) + { + struct dme1737_data *data = dev_get_drvdata(dev); +- long val; ++ unsigned long val; + int err; + +- err = kstrtol(buf, 10, &val); ++ err = kstrtoul(buf, 10, &val); + if (err) + return err; + ++ if (val > 255) ++ return -EINVAL; ++ + data->vrm = val; + return count; + } +diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c +index fc6f5d5..8890870 100644 +--- a/drivers/hwmon/ds1621.c ++++ b/drivers/hwmon/ds1621.c +@@ -309,6 +309,7 @@ static ssize_t set_convrate(struct device *dev, struct device_attribute *da, + data->conf |= (resol << DS1621_REG_CONFIG_RESOL_SHIFT); + i2c_smbus_write_byte_data(client, DS1621_REG_CONF, data->conf); + data->update_interval = ds1721_convrates[resol]; ++ data->zbits = 7 - resol; + mutex_unlock(&data->update_lock); + + return count; +diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c +index 73181be..814f7ee 100644 +--- a/drivers/hwmon/gpio-fan.c ++++ b/drivers/hwmon/gpio-fan.c +@@ -173,7 +173,7 @@ static int get_fan_speed_index(struct gpio_fan_data *fan_data) + return -ENODEV; + } + +-static int rpm_to_speed_index(struct gpio_fan_data *fan_data, int rpm) ++static int rpm_to_speed_index(struct gpio_fan_data *fan_data, unsigned long rpm) + { + struct gpio_fan_speed *speed = fan_data->speed; + int i; +diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c +index 9efadfc..c1eb464 100644 +--- a/drivers/hwmon/lm78.c ++++ b/drivers/hwmon/lm78.c +@@ -108,7 +108,7 @@ static inline int FAN_FROM_REG(u8 val, int div) + * TEMP: mC (-128C to +127C) + * REG: 1C/bit, two's complement + */ +-static inline s8 TEMP_TO_REG(int val) ++static inline s8 TEMP_TO_REG(long val) + { + int nval = clamp_val(val, -128000, 127000) ; + return nval < 0 ? (nval - 500) / 1000 : (nval + 500) / 1000; +diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c +index bed4af35..21d6cc8 100644 +--- a/drivers/hwmon/lm85.c ++++ b/drivers/hwmon/lm85.c +@@ -158,7 +158,7 @@ static inline u16 FAN_TO_REG(unsigned long val) + + /* Temperature is reported in .001 degC increments */ + #define TEMP_TO_REG(val) \ +- clamp_val(SCALE(val, 1000, 1), -127, 127) ++ DIV_ROUND_CLOSEST(clamp_val((val), -127000, 127000), 1000) + #define TEMPEXT_FROM_REG(val, ext) \ + SCALE(((val) << 4) + (ext), 16, 1000) + #define TEMP_FROM_REG(val) ((val) * 1000) +@@ -192,7 +192,7 @@ static const int lm85_range_map[] = { + 13300, 16000, 20000, 26600, 32000, 40000, 53300, 80000 + }; + +-static int RANGE_TO_REG(int range) ++static int RANGE_TO_REG(long range) + { + int i; + +@@ -214,7 +214,7 @@ static const int adm1027_freq_map[8] = { /* 1 Hz */ + 11, 15, 22, 29, 35, 44, 59, 88 + }; + +-static int FREQ_TO_REG(const int *map, int freq) ++static int FREQ_TO_REG(const int *map, unsigned long freq) + { + int i; + +@@ -463,6 +463,9 @@ static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, + if (err) + return err; + ++ if (val > 255) ++ return -EINVAL; ++ + data->vrm = val; + return count; + } +diff --git a/drivers/hwmon/mcp3021.c b/drivers/hwmon/mcp3021.c +index d219c06..972444a 100644 +--- a/drivers/hwmon/mcp3021.c ++++ b/drivers/hwmon/mcp3021.c +@@ -31,14 +31,11 @@ + /* output format */ + #define MCP3021_SAR_SHIFT 2 + #define MCP3021_SAR_MASK 0x3ff +- + #define MCP3021_OUTPUT_RES 10 /* 10-bit resolution */ +-#define MCP3021_OUTPUT_SCALE 4 + + #define MCP3221_SAR_SHIFT 0 + #define MCP3221_SAR_MASK 0xfff + #define MCP3221_OUTPUT_RES 12 /* 12-bit resolution */ +-#define MCP3221_OUTPUT_SCALE 1 + + enum chips { + mcp3021, +@@ -54,7 +51,6 @@ struct mcp3021_data { + u16 sar_shift; + u16 sar_mask; + u8 output_res; +- u8 output_scale; + }; + + static int mcp3021_read16(struct i2c_client *client) +@@ -84,13 +80,7 @@ static int mcp3021_read16(struct i2c_client *client) + + static inline u16 volts_from_reg(struct mcp3021_data *data, u16 val) + { +- if (val == 0) +- return 0; +- +- val = val * data->output_scale - data->output_scale / 2; +- +- return val * DIV_ROUND_CLOSEST(data->vdd, +- (1 << data->output_res) * data->output_scale); ++ return DIV_ROUND_CLOSEST(data->vdd * val, 1 << data->output_res); + } + + static ssize_t show_in_input(struct device *dev, struct device_attribute *attr, +@@ -132,14 +122,12 @@ static int mcp3021_probe(struct i2c_client *client, + data->sar_shift = MCP3021_SAR_SHIFT; + data->sar_mask = MCP3021_SAR_MASK; + data->output_res = MCP3021_OUTPUT_RES; +- data->output_scale = MCP3021_OUTPUT_SCALE; + break; + + case mcp3221: + data->sar_shift = MCP3221_SAR_SHIFT; + data->sar_mask = MCP3221_SAR_MASK; + data->output_res = MCP3221_OUTPUT_RES; +- data->output_scale = MCP3221_OUTPUT_SCALE; + break; + } + +diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c +index 38d5a63..20b69bf 100644 +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -986,6 +986,7 @@ nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg, + (*t)->dev_attr.attr.name, tg->base + i); + if ((*t)->s2) { + a2 = &su->u.a2; ++ sysfs_attr_init(&a2->dev_attr.attr); + a2->dev_attr.attr.name = su->name; + a2->nr = (*t)->u.s.nr + i; + a2->index = (*t)->u.s.index; +@@ -996,6 +997,7 @@ nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg, + *attrs = &a2->dev_attr.attr; + } else { + a = &su->u.a1; ++ sysfs_attr_init(&a->dev_attr.attr); + a->dev_attr.attr.name = su->name; + a->index = (*t)->u.index + i; + a->dev_attr.attr.mode = +diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c +index e76feb86..3660cb6 100644 +--- a/drivers/hwmon/ntc_thermistor.c ++++ b/drivers/hwmon/ntc_thermistor.c +@@ -181,8 +181,10 @@ static struct ntc_thermistor_platform_data * + ntc_thermistor_parse_dt(struct platform_device *pdev) + { + struct iio_channel *chan; ++ enum iio_chan_type type; + struct device_node *np = pdev->dev.of_node; + struct ntc_thermistor_platform_data *pdata; ++ int ret; + + if (!np) + return NULL; +@@ -195,6 +197,13 @@ ntc_thermistor_parse_dt(struct platform_device *pdev) + if (IS_ERR(chan)) + return ERR_CAST(chan); + ++ ret = iio_get_channel_type(chan, &type); ++ if (ret < 0) ++ return ERR_PTR(ret); ++ ++ if (type != IIO_VOLTAGE) ++ return ERR_PTR(-EINVAL); ++ + if (of_property_read_u32(np, "pullup-uv", &pdata->pullup_uv)) + return ERR_PTR(-ENODEV); + if (of_property_read_u32(np, "pullup-ohm", &pdata->pullup_ohm)) +diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c +index 3532026..bf1d789 100644 +--- a/drivers/hwmon/sis5595.c ++++ b/drivers/hwmon/sis5595.c +@@ -159,7 +159,7 @@ static inline int TEMP_FROM_REG(s8 val) + { + return val * 830 + 52120; + } +-static inline s8 TEMP_TO_REG(int val) ++static inline s8 TEMP_TO_REG(long val) + { + int nval = clamp_val(val, -54120, 157530) ; + return nval < 0 ? (nval - 5212 - 415) / 830 : (nval - 5212 + 415) / 830; +diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c +index efee4c5..34b9a60 100644 +--- a/drivers/hwmon/smsc47m192.c ++++ b/drivers/hwmon/smsc47m192.c +@@ -86,7 +86,7 @@ static inline u8 IN_TO_REG(unsigned long val, int n) + */ + static inline s8 TEMP_TO_REG(int val) + { +- return clamp_val(SCALE(val, 1, 1000), -128000, 127000); ++ return SCALE(clamp_val(val, -128000, 127000), 1, 1000); + } + + static inline int TEMP_FROM_REG(s8 val) +@@ -384,6 +384,8 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, + err = kstrtoul(buf, 10, &val); + if (err) + return err; ++ if (val > 255) ++ return -EINVAL; + + data->vrm = val; + return count; +diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c +index 843d012..50862c9 100644 +--- a/drivers/i2c/busses/i2c-at91.c ++++ b/drivers/i2c/busses/i2c-at91.c +@@ -62,6 +62,9 @@ + #define AT91_TWI_UNRE 0x0080 /* Underrun Error */ + #define AT91_TWI_NACK 0x0100 /* Not Acknowledged */ + ++#define AT91_TWI_INT_MASK \ ++ (AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY | AT91_TWI_NACK) ++ + #define AT91_TWI_IER 0x0024 /* Interrupt Enable Register */ + #define AT91_TWI_IDR 0x0028 /* Interrupt Disable Register */ + #define AT91_TWI_IMR 0x002c /* Interrupt Mask Register */ +@@ -101,6 +104,7 @@ struct at91_twi_dev { + unsigned twi_cwgr_reg; + struct at91_twi_pdata *pdata; + bool use_dma; ++ bool recv_len_abort; + struct at91_twi_dma dma; + }; + +@@ -116,13 +120,12 @@ static void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, unsigned val) + + static void at91_disable_twi_interrupts(struct at91_twi_dev *dev) + { +- at91_twi_write(dev, AT91_TWI_IDR, +- AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY); ++ at91_twi_write(dev, AT91_TWI_IDR, AT91_TWI_INT_MASK); + } + + static void at91_twi_irq_save(struct at91_twi_dev *dev) + { +- dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & 0x7; ++ dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & AT91_TWI_INT_MASK; + at91_disable_twi_interrupts(dev); + } + +@@ -210,8 +213,16 @@ static void at91_twi_write_data_dma_callback(void *data) + struct at91_twi_dev *dev = (struct at91_twi_dev *)data; + + dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg), +- dev->buf_len, DMA_MEM_TO_DEV); ++ dev->buf_len, DMA_TO_DEVICE); + ++ /* ++ * When this callback is called, THR/TX FIFO is likely not to be empty ++ * yet. So we have to wait for TXCOMP or NACK bits to be set into the ++ * Status Register to be sure that the STOP bit has been sent and the ++ * transfer is completed. The NACK interrupt has already been enabled, ++ * we just have to enable TXCOMP one. ++ */ ++ at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP); + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP); + } + +@@ -267,12 +278,24 @@ static void at91_twi_read_next_byte(struct at91_twi_dev *dev) + *dev->buf = at91_twi_read(dev, AT91_TWI_RHR) & 0xff; + --dev->buf_len; + ++ /* return if aborting, we only needed to read RHR to clear RXRDY*/ ++ if (dev->recv_len_abort) ++ return; ++ + /* handle I2C_SMBUS_BLOCK_DATA */ + if (unlikely(dev->msg->flags & I2C_M_RECV_LEN)) { +- dev->msg->flags &= ~I2C_M_RECV_LEN; +- dev->buf_len += *dev->buf; +- dev->msg->len = dev->buf_len + 1; +- dev_dbg(dev->dev, "received block length %d\n", dev->buf_len); ++ /* ensure length byte is a valid value */ ++ if (*dev->buf <= I2C_SMBUS_BLOCK_MAX && *dev->buf > 0) { ++ dev->msg->flags &= ~I2C_M_RECV_LEN; ++ dev->buf_len += *dev->buf; ++ dev->msg->len = dev->buf_len + 1; ++ dev_dbg(dev->dev, "received block length %d\n", ++ dev->buf_len); ++ } else { ++ /* abort and send the stop by reading one more byte */ ++ dev->recv_len_abort = true; ++ dev->buf_len = 1; ++ } + } + + /* send stop if second but last byte has been read */ +@@ -289,12 +312,12 @@ static void at91_twi_read_data_dma_callback(void *data) + struct at91_twi_dev *dev = (struct at91_twi_dev *)data; + + dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg), +- dev->buf_len, DMA_DEV_TO_MEM); ++ dev->buf_len, DMA_FROM_DEVICE); + + /* The last two bytes have to be read without using dma */ + dev->buf += dev->buf_len - 2; + dev->buf_len = 2; +- at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_RXRDY); ++ at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_RXRDY | AT91_TWI_TXCOMP); + } + + static void at91_twi_read_data_dma(struct at91_twi_dev *dev) +@@ -355,7 +378,7 @@ static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id) + /* catch error flags */ + dev->transfer_status |= status; + +- if (irqstatus & AT91_TWI_TXCOMP) { ++ if (irqstatus & (AT91_TWI_TXCOMP | AT91_TWI_NACK)) { + at91_disable_twi_interrupts(dev); + complete(&dev->cmd_complete); + } +@@ -368,6 +391,34 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) + int ret; + bool has_unre_flag = dev->pdata->has_unre_flag; + ++ /* ++ * WARNING: the TXCOMP bit in the Status Register is NOT a clear on ++ * read flag but shows the state of the transmission at the time the ++ * Status Register is read. According to the programmer datasheet, ++ * TXCOMP is set when both holding register and internal shifter are ++ * empty and STOP condition has been sent. ++ * Consequently, we should enable NACK interrupt rather than TXCOMP to ++ * detect transmission failure. ++ * ++ * Besides, the TXCOMP bit is already set before the i2c transaction ++ * has been started. For read transactions, this bit is cleared when ++ * writing the START bit into the Control Register. So the ++ * corresponding interrupt can safely be enabled just after. ++ * However for write transactions managed by the CPU, we first write ++ * into THR, so TXCOMP is cleared. Then we can safely enable TXCOMP ++ * interrupt. If TXCOMP interrupt were enabled before writing into THR, ++ * the interrupt handler would be called immediately and the i2c command ++ * would be reported as completed. ++ * Also when a write transaction is managed by the DMA controller, ++ * enabling the TXCOMP interrupt in this function may lead to a race ++ * condition since we don't know whether the TXCOMP interrupt is enabled ++ * before or after the DMA has started to write into THR. So the TXCOMP ++ * interrupt is enabled later by at91_twi_write_data_dma_callback(). ++ * Immediately after in that DMA callback, we still need to send the ++ * STOP condition manually writing the corresponding bit into the ++ * Control Register. ++ */ ++ + dev_dbg(dev->dev, "transfer: %s %d bytes.\n", + (dev->msg->flags & I2C_M_RD) ? "read" : "write", dev->buf_len); + +@@ -398,31 +449,29 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) + * seems to be the best solution. + */ + if (dev->use_dma && (dev->buf_len > AT91_I2C_DMA_THRESHOLD)) { ++ at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_NACK); + at91_twi_read_data_dma(dev); +- /* +- * It is important to enable TXCOMP irq here because +- * doing it only when transferring the last two bytes +- * will mask NACK errors since TXCOMP is set when a +- * NACK occurs. +- */ +- at91_twi_write(dev, AT91_TWI_IER, +- AT91_TWI_TXCOMP); +- } else ++ } else { + at91_twi_write(dev, AT91_TWI_IER, +- AT91_TWI_TXCOMP | AT91_TWI_RXRDY); ++ AT91_TWI_TXCOMP | ++ AT91_TWI_NACK | ++ AT91_TWI_RXRDY); ++ } + } else { + if (dev->use_dma && (dev->buf_len > AT91_I2C_DMA_THRESHOLD)) { ++ at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_NACK); + at91_twi_write_data_dma(dev); +- at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP); + } else { + at91_twi_write_next_byte(dev); + at91_twi_write(dev, AT91_TWI_IER, +- AT91_TWI_TXCOMP | AT91_TWI_TXRDY); ++ AT91_TWI_TXCOMP | ++ AT91_TWI_NACK | ++ AT91_TWI_TXRDY); + } + } + +- ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, +- dev->adapter.timeout); ++ ret = wait_for_completion_timeout(&dev->cmd_complete, ++ dev->adapter.timeout); + if (ret == 0) { + dev_err(dev->dev, "controller timed out\n"); + at91_init_twi_bus(dev); +@@ -444,6 +493,12 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) + ret = -EIO; + goto error; + } ++ if (dev->recv_len_abort) { ++ dev_err(dev->dev, "invalid smbus block length recvd\n"); ++ ret = -EPROTO; ++ goto error; ++ } ++ + dev_dbg(dev->dev, "transfer complete\n"); + + return 0; +@@ -500,6 +555,7 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) + dev->buf_len = m_start->len; + dev->buf = m_start->buf; + dev->msg = m_start; ++ dev->recv_len_abort = false; + + ret = at91_do_twi_transfer(dev); + +diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c +index af0b583..e3c6a96 100644 +--- a/drivers/i2c/busses/i2c-davinci.c ++++ b/drivers/i2c/busses/i2c-davinci.c +@@ -411,11 +411,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) + if (dev->cmd_err & DAVINCI_I2C_STR_NACK) { + if (msg->flags & I2C_M_IGNORE_NAK) + return msg->len; +- if (stop) { +- w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); +- w |= DAVINCI_I2C_MDR_STP; +- davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); +- } ++ w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); ++ w |= DAVINCI_I2C_MDR_STP; ++ davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); + return -EREMOTEIO; + } + return -EIO; +diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c +index 8ce4f51..6e932d1 100644 +--- a/drivers/i2c/busses/i2c-ismt.c ++++ b/drivers/i2c/busses/i2c-ismt.c +@@ -497,7 +497,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, + desc->wr_len_cmd = dma_size; + desc->control |= ISMT_DESC_BLK; + priv->dma_buffer[0] = command; +- memcpy(&priv->dma_buffer[1], &data->block[1], dma_size); ++ memcpy(&priv->dma_buffer[1], &data->block[1], dma_size - 1); + } else { + /* Block Read */ + dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA: READ\n"); +@@ -525,7 +525,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, + desc->wr_len_cmd = dma_size; + desc->control |= ISMT_DESC_I2C; + priv->dma_buffer[0] = command; +- memcpy(&priv->dma_buffer[1], &data->block[1], dma_size); ++ memcpy(&priv->dma_buffer[1], &data->block[1], dma_size - 1); + } else { + /* i2c Block Read */ + dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA: READ\n"); +diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c +index d52d849..cf89175 100644 +--- a/drivers/i2c/busses/i2c-mv64xxx.c ++++ b/drivers/i2c/busses/i2c-mv64xxx.c +@@ -748,8 +748,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, + } + tclk = clk_get_rate(drv_data->clk); + +- rc = of_property_read_u32(np, "clock-frequency", &bus_freq); +- if (rc) ++ if (of_property_read_u32(np, "clock-frequency", &bus_freq)) + bus_freq = 100000; /* 100kHz by default */ + + if (!mv64xxx_find_baud_factors(bus_freq, tclk, +diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c +index 90dcc2e..a686057 100644 +--- a/drivers/i2c/busses/i2c-omap.c ++++ b/drivers/i2c/busses/i2c-omap.c +@@ -926,14 +926,12 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) + if (stat & OMAP_I2C_STAT_NACK) { + err |= OMAP_I2C_STAT_NACK; + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK); +- break; + } + + if (stat & OMAP_I2C_STAT_AL) { + dev_err(dev->dev, "Arbitration lost\n"); + err |= OMAP_I2C_STAT_AL; + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL); +- break; + } + + /* +@@ -958,11 +956,13 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) + if (dev->fifo_size) + num_bytes = dev->buf_len; + +- omap_i2c_receive_data(dev, num_bytes, true); +- +- if (dev->errata & I2C_OMAP_ERRATA_I207) ++ if (dev->errata & I2C_OMAP_ERRATA_I207) { + i2c_omap_errata_i207(dev, stat); ++ num_bytes = (omap_i2c_read_reg(dev, ++ OMAP_I2C_BUFSTAT_REG) >> 8) & 0x3F; ++ } + ++ omap_i2c_receive_data(dev, num_bytes, true); + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); + continue; + } +diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c +index 93ec376..79a2117 100644 +--- a/drivers/i2c/busses/i2c-s3c2410.c ++++ b/drivers/i2c/busses/i2c-s3c2410.c +@@ -753,14 +753,16 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, + int ret; + + pm_runtime_get_sync(&adap->dev); +- clk_prepare_enable(i2c->clk); ++ ret = clk_enable(i2c->clk); ++ if (ret) ++ return ret; + + for (retry = 0; retry < adap->retries; retry++) { + + ret = s3c24xx_i2c_doxfer(i2c, msgs, num); + + if (ret != -EAGAIN) { +- clk_disable_unprepare(i2c->clk); ++ clk_disable(i2c->clk); + pm_runtime_put(&adap->dev); + return ret; + } +@@ -770,7 +772,7 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, + udelay(100); + } + +- clk_disable_unprepare(i2c->clk); ++ clk_disable(i2c->clk); + pm_runtime_put(&adap->dev); + return -EREMOTEIO; + } +@@ -1153,7 +1155,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + + clk_prepare_enable(i2c->clk); + ret = s3c24xx_i2c_init(i2c); +- clk_disable_unprepare(i2c->clk); ++ clk_disable(i2c->clk); + if (ret != 0) { + dev_err(&pdev->dev, "I2C controller init failed\n"); + return ret; +@@ -1166,6 +1168,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + i2c->irq = ret = platform_get_irq(pdev, 0); + if (ret <= 0) { + dev_err(&pdev->dev, "cannot find IRQ\n"); ++ clk_unprepare(i2c->clk); + return ret; + } + +@@ -1174,6 +1177,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + + if (ret != 0) { + dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); ++ clk_unprepare(i2c->clk); + return ret; + } + } +@@ -1181,6 +1185,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + ret = s3c24xx_i2c_register_cpufreq(i2c); + if (ret < 0) { + dev_err(&pdev->dev, "failed to register cpufreq notifier\n"); ++ clk_unprepare(i2c->clk); + return ret; + } + +@@ -1197,6 +1202,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) + if (ret < 0) { + dev_err(&pdev->dev, "failed to add bus to i2c core\n"); + s3c24xx_i2c_deregister_cpufreq(i2c); ++ clk_unprepare(i2c->clk); + return ret; + } + +@@ -1218,6 +1224,8 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) + { + struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); + ++ clk_unprepare(i2c->clk); ++ + pm_runtime_disable(&i2c->adap.dev); + pm_runtime_disable(&pdev->dev); + +@@ -1246,10 +1254,13 @@ static int s3c24xx_i2c_resume(struct device *dev) + { + struct platform_device *pdev = to_platform_device(dev); + struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); ++ int ret; + +- clk_prepare_enable(i2c->clk); ++ ret = clk_enable(i2c->clk); ++ if (ret) ++ return ret; + s3c24xx_i2c_init(i2c); +- clk_disable_unprepare(i2c->clk); ++ clk_disable(i2c->clk); + i2c->suspended = 0; + + return 0; +diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c +index 5fb80b8..43fe15a 100644 +--- a/drivers/i2c/i2c-core.c ++++ b/drivers/i2c/i2c-core.c +@@ -217,6 +217,7 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap) + adap->bus_recovery_info->set_scl(adap, 1); + return i2c_generic_recovery(adap); + } ++EXPORT_SYMBOL_GPL(i2c_generic_scl_recovery); + + int i2c_generic_gpio_recovery(struct i2c_adapter *adap) + { +@@ -231,6 +232,7 @@ int i2c_generic_gpio_recovery(struct i2c_adapter *adap) + + return ret; + } ++EXPORT_SYMBOL_GPL(i2c_generic_gpio_recovery); + + int i2c_recover_bus(struct i2c_adapter *adap) + { +@@ -240,6 +242,7 @@ int i2c_recover_bus(struct i2c_adapter *adap) + dev_dbg(&adap->dev, "Trying i2c bus recovery\n"); + return adap->bus_recovery_info->recover_bus(adap); + } ++EXPORT_SYMBOL_GPL(i2c_recover_bus); + + static int i2c_device_probe(struct device *dev) + { +diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c +index bfec313..6f039c3 100644 +--- a/drivers/iio/accel/bma180.c ++++ b/drivers/iio/accel/bma180.c +@@ -68,13 +68,13 @@ + /* Defaults values */ + #define BMA180_DEF_PMODE 0 + #define BMA180_DEF_BW 20 +-#define BMA180_DEF_SCALE 250 ++#define BMA180_DEF_SCALE 2452 + + /* Available values for sysfs */ + #define BMA180_FLP_FREQ_AVAILABLE \ + "10 20 40 75 150 300" + #define BMA180_SCALE_AVAILABLE \ +- "0.000130 0.000190 0.000250 0.000380 0.000500 0.000990 0.001980" ++ "0.001275 0.001863 0.002452 0.003727 0.004903 0.009709 0.019417" + + struct bma180_data { + struct i2c_client *client; +@@ -94,7 +94,7 @@ enum bma180_axis { + }; + + static int bw_table[] = { 10, 20, 40, 75, 150, 300 }; /* Hz */ +-static int scale_table[] = { 130, 190, 250, 380, 500, 990, 1980 }; ++static int scale_table[] = { 1275, 1863, 2452, 3727, 4903, 9709, 19417 }; + + static int bma180_get_acc_reg(struct bma180_data *data, enum bma180_axis axis) + { +@@ -376,6 +376,8 @@ static int bma180_write_raw(struct iio_dev *indio_dev, + mutex_unlock(&data->mutex); + return ret; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: ++ if (val2) ++ return -EINVAL; + mutex_lock(&data->mutex); + ret = bma180_set_bw(data, val); + mutex_unlock(&data->mutex); +@@ -569,7 +571,7 @@ static int bma180_probe(struct i2c_client *client, + trig->ops = &bma180_trigger_ops; + iio_trigger_set_drvdata(trig, indio_dev); + data->trig = trig; +- indio_dev->trig = trig; ++ indio_dev->trig = iio_trigger_get(trig); + + ret = iio_trigger_register(trig); + if (ret) +diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c +index 9a4e0e3..eb799a4 100644 +--- a/drivers/iio/adc/ad_sigma_delta.c ++++ b/drivers/iio/adc/ad_sigma_delta.c +@@ -472,7 +472,7 @@ static int ad_sd_probe_trigger(struct iio_dev *indio_dev) + goto error_free_irq; + + /* select default trigger */ +- indio_dev->trig = sigma_delta->trig; ++ indio_dev->trig = iio_trigger_get(sigma_delta->trig); + + return 0; + +diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c +index e6bf77d..ed4e45f 100644 +--- a/drivers/iio/adc/at91_adc.c ++++ b/drivers/iio/adc/at91_adc.c +@@ -58,7 +58,7 @@ struct at91_adc_caps { + u8 ts_pen_detect_sensitivity; + + /* startup time calculate function */ +- u32 (*calc_startup_ticks)(u8 startup_time, u32 adc_clk_khz); ++ u32 (*calc_startup_ticks)(u32 startup_time, u32 adc_clk_khz); + + u8 num_channels; + struct at91_adc_reg_desc registers; +@@ -82,7 +82,7 @@ struct at91_adc_state { + u8 num_channels; + void __iomem *reg_base; + struct at91_adc_reg_desc *registers; +- u8 startup_time; ++ u32 startup_time; + u8 sample_hold_time; + bool sleep_mode; + struct iio_trigger **trig; +@@ -590,7 +590,7 @@ ret: + return ret; + } + +-static u32 calc_startup_ticks_9260(u8 startup_time, u32 adc_clk_khz) ++static u32 calc_startup_ticks_9260(u32 startup_time, u32 adc_clk_khz) + { + /* + * Number of ticks needed to cover the startup time of the ADC +@@ -601,7 +601,7 @@ static u32 calc_startup_ticks_9260(u8 startup_time, u32 adc_clk_khz) + return round_up((startup_time * adc_clk_khz / 1000) - 1, 8) / 8; + } + +-static u32 calc_startup_ticks_9x5(u8 startup_time, u32 adc_clk_khz) ++static u32 calc_startup_ticks_9x5(u32 startup_time, u32 adc_clk_khz) + { + /* + * For sama5d3x and at91sam9x5, the formula changes to: +diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c +index 47dcb34..3a615f3 100644 +--- a/drivers/iio/adc/mcp3422.c ++++ b/drivers/iio/adc/mcp3422.c +@@ -57,20 +57,11 @@ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + } + +-/* LSB is in nV to eliminate floating point */ +-static const u32 rates_to_lsb[] = {1000000, 250000, 62500, 15625}; +- +-/* +- * scales calculated as: +- * rates_to_lsb[sample_rate] / (1 << pga); +- * pga is 1 for 0, 2 +- */ +- + static const int mcp3422_scales[4][4] = { +- { 1000000, 250000, 62500, 15625 }, +- { 500000 , 125000, 31250, 7812 }, +- { 250000 , 62500 , 15625, 3906 }, +- { 125000 , 31250 , 7812 , 1953 } }; ++ { 1000000, 500000, 250000, 125000 }, ++ { 250000 , 125000, 62500 , 31250 }, ++ { 62500 , 31250 , 15625 , 7812 }, ++ { 15625 , 7812 , 3906 , 1953 } }; + + /* Constant msleep times for data acquisitions */ + static const int mcp3422_read_times[4] = { +diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c +index 53a24eb..779dac5 100644 +--- a/drivers/iio/adc/twl6030-gpadc.c ++++ b/drivers/iio/adc/twl6030-gpadc.c +@@ -1003,7 +1003,7 @@ static struct platform_driver twl6030_gpadc_driver = { + + module_platform_driver(twl6030_gpadc_driver); + +-MODULE_ALIAS("platform: " DRIVER_NAME); ++MODULE_ALIAS("platform:" DRIVER_NAME); + MODULE_AUTHOR("Balaji T K "); + MODULE_AUTHOR("Graeme Gregory "); + MODULE_AUTHOR("Oleksandr Kozaruk dev, "Trigger Register Failed\n"); + goto error_free_trig; + } +- indio_dev->trig = attrb->trigger = trig; ++ attrb->trigger = trig; ++ indio_dev->trig = iio_trigger_get(trig); + + return ret; + +diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c +index 1665c8e..e18bc67 100644 +--- a/drivers/iio/common/st_sensors/st_sensors_buffer.c ++++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c +@@ -71,7 +71,7 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) + goto st_sensors_free_memory; + } + +- for (i = 0; i < n * num_data_channels; i++) { ++ for (i = 0; i < n * byte_for_channel; i++) { + if (i < n) + buf[i] = rx_array[i]; + else +diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c +index 8fc3a97..8d8ca6f 100644 +--- a/drivers/iio/common/st_sensors/st_sensors_trigger.c ++++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c +@@ -49,7 +49,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, + dev_err(&indio_dev->dev, "failed to register iio trigger.\n"); + goto iio_trigger_register_error; + } +- indio_dev->trig = sdata->trig; ++ indio_dev->trig = iio_trigger_get(sdata->trig); + + return 0; + +diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c +index e8199cc..1e66651 100644 +--- a/drivers/iio/dac/ad5624r_spi.c ++++ b/drivers/iio/dac/ad5624r_spi.c +@@ -22,7 +22,7 @@ + #include "ad5624r.h" + + static int ad5624r_spi_write(struct spi_device *spi, +- u8 cmd, u8 addr, u16 val, u8 len) ++ u8 cmd, u8 addr, u16 val, u8 shift) + { + u32 data; + u8 msg[3]; +@@ -35,7 +35,7 @@ static int ad5624r_spi_write(struct spi_device *spi, + * 14-, 12-bit input code followed by 0, 2, or 4 don't care bits, + * for the AD5664R, AD5644R, and AD5624R, respectively. + */ +- data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << (16 - len)); ++ data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << shift); + msg[0] = data >> 16; + msg[1] = data >> 8; + msg[2] = data; +diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c +index 17aca4d..861ba3d 100644 +--- a/drivers/iio/dac/ad5686.c ++++ b/drivers/iio/dac/ad5686.c +@@ -322,7 +322,7 @@ static int ad5686_probe(struct spi_device *spi) + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + +- st->reg = devm_regulator_get(&spi->dev, "vcc"); ++ st->reg = devm_regulator_get_optional(&spi->dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) +diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig +index ac2d69e..6f64c5c 100644 +--- a/drivers/iio/gyro/Kconfig ++++ b/drivers/iio/gyro/Kconfig +@@ -93,7 +93,8 @@ config IIO_ST_GYRO_SPI_3AXIS + config ITG3200 + tristate "InvenSense ITG3200 Digital 3-Axis Gyroscope I2C driver" + depends on I2C +- select IIO_TRIGGERED_BUFFER if IIO_BUFFER ++ select IIO_BUFFER ++ select IIO_TRIGGERED_BUFFER + help + Say yes here to add support for the InvenSense ITG3200 digital + 3-axis gyroscope sensor. +diff --git a/drivers/iio/gyro/itg3200_buffer.c b/drivers/iio/gyro/itg3200_buffer.c +index e3b3c50..eef50e9 100644 +--- a/drivers/iio/gyro/itg3200_buffer.c ++++ b/drivers/iio/gyro/itg3200_buffer.c +@@ -132,7 +132,7 @@ int itg3200_probe_trigger(struct iio_dev *indio_dev) + goto error_free_irq; + + /* select default trigger */ +- indio_dev->trig = st->trig; ++ indio_dev->trig = iio_trigger_get(st->trig); + + return 0; + +diff --git a/drivers/iio/imu/adis16400.h b/drivers/iio/imu/adis16400.h +index 0916bf6..1e8fd2e 100644 +--- a/drivers/iio/imu/adis16400.h ++++ b/drivers/iio/imu/adis16400.h +@@ -165,6 +165,7 @@ struct adis16400_state { + int filt_int; + + struct adis adis; ++ unsigned long avail_scan_mask[2]; + }; + + /* At the moment triggers are only used for ring buffer +diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c +index 7c582f7..ccfaf3a 100644 +--- a/drivers/iio/imu/adis16400_core.c ++++ b/drivers/iio/imu/adis16400_core.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -437,6 +438,11 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, + *val = st->variant->temp_scale_nano / 1000000; + *val2 = (st->variant->temp_scale_nano % 1000000); + return IIO_VAL_INT_PLUS_MICRO; ++ case IIO_PRESSURE: ++ /* 20 uBar = 0.002kPascal */ ++ *val = 0; ++ *val2 = 2000; ++ return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +@@ -447,7 +453,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, + mutex_unlock(&indio_dev->mlock); + if (ret) + return ret; +- val16 = ((val16 & 0xFFF) << 4) >> 4; ++ val16 = sign_extend32(val16, 11); + *val = val16; + return IIO_VAL_INT; + case IIO_CHAN_INFO_OFFSET: +@@ -479,10 +485,10 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, + } + } + +-#define ADIS16400_VOLTAGE_CHAN(addr, bits, name, si) { \ ++#define ADIS16400_VOLTAGE_CHAN(addr, bits, name, si, chn) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ +- .channel = 0, \ ++ .channel = chn, \ + .extend_name = name, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ +@@ -498,10 +504,10 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, + } + + #define ADIS16400_SUPPLY_CHAN(addr, bits) \ +- ADIS16400_VOLTAGE_CHAN(addr, bits, "supply", ADIS16400_SCAN_SUPPLY) ++ ADIS16400_VOLTAGE_CHAN(addr, bits, "supply", ADIS16400_SCAN_SUPPLY, 0) + + #define ADIS16400_AUX_ADC_CHAN(addr, bits) \ +- ADIS16400_VOLTAGE_CHAN(addr, bits, NULL, ADIS16400_SCAN_ADC) ++ ADIS16400_VOLTAGE_CHAN(addr, bits, NULL, ADIS16400_SCAN_ADC, 1) + + #define ADIS16400_GYRO_CHAN(mod, addr, bits) { \ + .type = IIO_ANGL_VEL, \ +@@ -818,11 +824,6 @@ static const struct iio_info adis16400_info = { + .debugfs_reg_access = adis_debugfs_reg_access, + }; + +-static const unsigned long adis16400_burst_scan_mask[] = { +- ~0UL, +- 0, +-}; +- + static const char * const adis16400_status_error_msgs[] = { + [ADIS16400_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure", + [ADIS16400_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure", +@@ -870,6 +871,20 @@ static const struct adis_data adis16400_data = { + BIT(ADIS16400_DIAG_STAT_POWER_LOW), + }; + ++static void adis16400_setup_chan_mask(struct adis16400_state *st) ++{ ++ const struct adis16400_chip_info *chip_info = st->variant; ++ unsigned i; ++ ++ for (i = 0; i < chip_info->num_channels; i++) { ++ const struct iio_chan_spec *ch = &chip_info->channels[i]; ++ ++ if (ch->scan_index >= 0 && ++ ch->scan_index != ADIS16400_SCAN_TIMESTAMP) ++ st->avail_scan_mask[0] |= BIT(ch->scan_index); ++ } ++} ++ + static int adis16400_probe(struct spi_device *spi) + { + struct adis16400_state *st; +@@ -893,8 +908,10 @@ static int adis16400_probe(struct spi_device *spi) + indio_dev->info = &adis16400_info; + indio_dev->modes = INDIO_DIRECT_MODE; + +- if (!(st->variant->flags & ADIS16400_NO_BURST)) +- indio_dev->available_scan_masks = adis16400_burst_scan_mask; ++ if (!(st->variant->flags & ADIS16400_NO_BURST)) { ++ adis16400_setup_chan_mask(st); ++ indio_dev->available_scan_masks = st->avail_scan_mask; ++ } + + ret = adis_init(&st->adis, indio_dev, spi, &adis16400_data); + if (ret) +diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c +index dd4206c..5e1b117 100644 +--- a/drivers/iio/imu/adis16480.c ++++ b/drivers/iio/imu/adis16480.c +@@ -110,6 +110,10 @@ + struct adis16480_chip_info { + unsigned int num_channels; + const struct iio_chan_spec *channels; ++ unsigned int gyro_max_val; ++ unsigned int gyro_max_scale; ++ unsigned int accel_max_val; ++ unsigned int accel_max_scale; + }; + + struct adis16480 { +@@ -533,19 +537,21 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev, + static int adis16480_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *val, int *val2, long info) + { ++ struct adis16480 *st = iio_priv(indio_dev); ++ + switch (info) { + case IIO_CHAN_INFO_RAW: + return adis_single_conversion(indio_dev, chan, 0, val); + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: +- *val = 0; +- *val2 = IIO_DEGREE_TO_RAD(20000); /* 0.02 degree/sec */ +- return IIO_VAL_INT_PLUS_MICRO; ++ *val = st->chip_info->gyro_max_scale; ++ *val2 = st->chip_info->gyro_max_val; ++ return IIO_VAL_FRACTIONAL; + case IIO_ACCEL: +- *val = 0; +- *val2 = IIO_G_TO_M_S_2(800); /* 0.8 mg */ +- return IIO_VAL_INT_PLUS_MICRO; ++ *val = st->chip_info->accel_max_scale; ++ *val2 = st->chip_info->accel_max_val; ++ return IIO_VAL_FRACTIONAL; + case IIO_MAGN: + *val = 0; + *val2 = 100; /* 0.0001 gauss */ +@@ -702,18 +708,39 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { + [ADIS16375] = { + .channels = adis16485_channels, + .num_channels = ARRAY_SIZE(adis16485_channels), ++ /* ++ * storing the value in rad/degree and the scale in degree ++ * gives us the result in rad and better precession than ++ * storing the scale directly in rad. ++ */ ++ .gyro_max_val = IIO_RAD_TO_DEGREE(22887), ++ .gyro_max_scale = 300, ++ .accel_max_val = IIO_M_S_2_TO_G(21973), ++ .accel_max_scale = 18, + }, + [ADIS16480] = { + .channels = adis16480_channels, + .num_channels = ARRAY_SIZE(adis16480_channels), ++ .gyro_max_val = IIO_RAD_TO_DEGREE(22500), ++ .gyro_max_scale = 450, ++ .accel_max_val = IIO_M_S_2_TO_G(12500), ++ .accel_max_scale = 5, + }, + [ADIS16485] = { + .channels = adis16485_channels, + .num_channels = ARRAY_SIZE(adis16485_channels), ++ .gyro_max_val = IIO_RAD_TO_DEGREE(22500), ++ .gyro_max_scale = 450, ++ .accel_max_val = IIO_M_S_2_TO_G(20000), ++ .accel_max_scale = 5, + }, + [ADIS16488] = { + .channels = adis16480_channels, + .num_channels = ARRAY_SIZE(adis16480_channels), ++ .gyro_max_val = IIO_RAD_TO_DEGREE(22500), ++ .gyro_max_scale = 450, ++ .accel_max_val = IIO_M_S_2_TO_G(22500), ++ .accel_max_scale = 18, + }, + }; + +diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c +index e0017c2..f53e9a8 100644 +--- a/drivers/iio/imu/adis_trigger.c ++++ b/drivers/iio/imu/adis_trigger.c +@@ -60,7 +60,7 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) + iio_trigger_set_drvdata(adis->trig, adis); + ret = iio_trigger_register(adis->trig); + +- indio_dev->trig = adis->trig; ++ indio_dev->trig = iio_trigger_get(adis->trig); + if (ret) + goto error_free_irq; + +diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +index 4295171..30fce67 100644 +--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c ++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +@@ -25,6 +25,16 @@ + #include + #include "inv_mpu_iio.h" + ++static void inv_clear_kfifo(struct inv_mpu6050_state *st) ++{ ++ unsigned long flags; ++ ++ /* take the spin lock sem to avoid interrupt kick in */ ++ spin_lock_irqsave(&st->time_stamp_lock, flags); ++ kfifo_reset(&st->timestamps); ++ spin_unlock_irqrestore(&st->time_stamp_lock, flags); ++} ++ + int inv_reset_fifo(struct iio_dev *indio_dev) + { + int result; +@@ -51,6 +61,10 @@ int inv_reset_fifo(struct iio_dev *indio_dev) + INV_MPU6050_BIT_FIFO_RST); + if (result) + goto reset_fifo_fail; ++ ++ /* clear timestamps fifo */ ++ inv_clear_kfifo(st); ++ + /* enable interrupt */ + if (st->chip_config.accl_fifo_enable || + st->chip_config.gyro_fifo_enable) { +@@ -84,16 +98,6 @@ reset_fifo_fail: + return result; + } + +-static void inv_clear_kfifo(struct inv_mpu6050_state *st) +-{ +- unsigned long flags; +- +- /* take the spin lock sem to avoid interrupt kick in */ +- spin_lock_irqsave(&st->time_stamp_lock, flags); +- kfifo_reset(&st->timestamps); +- spin_unlock_irqrestore(&st->time_stamp_lock, flags); +-} +- + /** + * inv_mpu6050_irq_handler() - Cache a timestamp at each data ready interrupt. + */ +@@ -185,7 +189,6 @@ end_session: + flush_fifo: + /* Flush HW and SW FIFOs. */ + inv_reset_fifo(indio_dev); +- inv_clear_kfifo(st); + mutex_unlock(&indio_dev->mlock); + iio_trigger_notify_done(indio_dev->trig); + +diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +index 03b9372..926fcce 100644 +--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c ++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +@@ -135,7 +135,7 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev) + ret = iio_trigger_register(st->trig); + if (ret) + goto error_free_irq; +- indio_dev->trig = st->trig; ++ indio_dev->trig = iio_trigger_get(st->trig); + + return 0; + +diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c +index fe25042..37b52bd 100644 +--- a/drivers/iio/industrialio-buffer.c ++++ b/drivers/iio/industrialio-buffer.c +@@ -96,7 +96,7 @@ unsigned int iio_buffer_poll(struct file *filp, + struct iio_buffer *rb = indio_dev->buffer; + + if (!indio_dev->info) +- return -ENODEV; ++ return 0; + + poll_wait(filp, &rb->pollq, wait); + if (iio_buffer_data_available(rb)) +@@ -953,7 +953,7 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, + + /* Now we have the two masks, work from least sig and build up sizes */ + for_each_set_bit(out_ind, +- indio_dev->active_scan_mask, ++ buffer->scan_mask, + indio_dev->masklength) { + in_ind = find_next_bit(indio_dev->active_scan_mask, + indio_dev->masklength, +diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c +index f9360f4..05b5994 100644 +--- a/drivers/iio/industrialio-event.c ++++ b/drivers/iio/industrialio-event.c +@@ -83,7 +83,7 @@ static unsigned int iio_event_poll(struct file *filep, + unsigned int events = 0; + + if (!indio_dev->info) +- return -ENODEV; ++ return events; + + poll_wait(filep, &ev_int->wait, wait); + +diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c +index 1e8e94d..4fc88e6 100644 +--- a/drivers/iio/inkern.c ++++ b/drivers/iio/inkern.c +@@ -178,7 +178,7 @@ static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np, + index = of_property_match_string(np, "io-channel-names", + name); + chan = of_iio_channel_get(np, index); +- if (!IS_ERR(chan)) ++ if (!IS_ERR(chan) || PTR_ERR(chan) == -EPROBE_DEFER) + break; + else if (name && index >= 0) { + pr_err("ERROR: could not get IIO channel %s:%s(%i)\n", +diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c +index 52bbcfa..476aa13 100644 +--- a/drivers/iio/magnetometer/st_magn_core.c ++++ b/drivers/iio/magnetometer/st_magn_core.c +@@ -42,7 +42,8 @@ + #define ST_MAGN_FS_AVL_5600MG 5600 + #define ST_MAGN_FS_AVL_8000MG 8000 + #define ST_MAGN_FS_AVL_8100MG 8100 +-#define ST_MAGN_FS_AVL_10000MG 10000 ++#define ST_MAGN_FS_AVL_12000MG 12000 ++#define ST_MAGN_FS_AVL_16000MG 16000 + + /* CUSTOM VALUES FOR SENSOR 1 */ + #define ST_MAGN_1_WAI_EXP 0x3c +@@ -69,20 +70,20 @@ + #define ST_MAGN_1_FS_AVL_4700_VAL 0x05 + #define ST_MAGN_1_FS_AVL_5600_VAL 0x06 + #define ST_MAGN_1_FS_AVL_8100_VAL 0x07 +-#define ST_MAGN_1_FS_AVL_1300_GAIN_XY 1100 +-#define ST_MAGN_1_FS_AVL_1900_GAIN_XY 855 +-#define ST_MAGN_1_FS_AVL_2500_GAIN_XY 670 +-#define ST_MAGN_1_FS_AVL_4000_GAIN_XY 450 +-#define ST_MAGN_1_FS_AVL_4700_GAIN_XY 400 +-#define ST_MAGN_1_FS_AVL_5600_GAIN_XY 330 +-#define ST_MAGN_1_FS_AVL_8100_GAIN_XY 230 +-#define ST_MAGN_1_FS_AVL_1300_GAIN_Z 980 +-#define ST_MAGN_1_FS_AVL_1900_GAIN_Z 760 +-#define ST_MAGN_1_FS_AVL_2500_GAIN_Z 600 +-#define ST_MAGN_1_FS_AVL_4000_GAIN_Z 400 +-#define ST_MAGN_1_FS_AVL_4700_GAIN_Z 355 +-#define ST_MAGN_1_FS_AVL_5600_GAIN_Z 295 +-#define ST_MAGN_1_FS_AVL_8100_GAIN_Z 205 ++#define ST_MAGN_1_FS_AVL_1300_GAIN_XY 909 ++#define ST_MAGN_1_FS_AVL_1900_GAIN_XY 1169 ++#define ST_MAGN_1_FS_AVL_2500_GAIN_XY 1492 ++#define ST_MAGN_1_FS_AVL_4000_GAIN_XY 2222 ++#define ST_MAGN_1_FS_AVL_4700_GAIN_XY 2500 ++#define ST_MAGN_1_FS_AVL_5600_GAIN_XY 3030 ++#define ST_MAGN_1_FS_AVL_8100_GAIN_XY 4347 ++#define ST_MAGN_1_FS_AVL_1300_GAIN_Z 1020 ++#define ST_MAGN_1_FS_AVL_1900_GAIN_Z 1315 ++#define ST_MAGN_1_FS_AVL_2500_GAIN_Z 1666 ++#define ST_MAGN_1_FS_AVL_4000_GAIN_Z 2500 ++#define ST_MAGN_1_FS_AVL_4700_GAIN_Z 2816 ++#define ST_MAGN_1_FS_AVL_5600_GAIN_Z 3389 ++#define ST_MAGN_1_FS_AVL_8100_GAIN_Z 4878 + #define ST_MAGN_1_MULTIREAD_BIT false + + /* CUSTOM VALUES FOR SENSOR 2 */ +@@ -105,10 +106,12 @@ + #define ST_MAGN_2_FS_MASK 0x60 + #define ST_MAGN_2_FS_AVL_4000_VAL 0x00 + #define ST_MAGN_2_FS_AVL_8000_VAL 0x01 +-#define ST_MAGN_2_FS_AVL_10000_VAL 0x02 +-#define ST_MAGN_2_FS_AVL_4000_GAIN 430 +-#define ST_MAGN_2_FS_AVL_8000_GAIN 230 +-#define ST_MAGN_2_FS_AVL_10000_GAIN 230 ++#define ST_MAGN_2_FS_AVL_12000_VAL 0x02 ++#define ST_MAGN_2_FS_AVL_16000_VAL 0x03 ++#define ST_MAGN_2_FS_AVL_4000_GAIN 146 ++#define ST_MAGN_2_FS_AVL_8000_GAIN 292 ++#define ST_MAGN_2_FS_AVL_12000_GAIN 438 ++#define ST_MAGN_2_FS_AVL_16000_GAIN 584 + #define ST_MAGN_2_MULTIREAD_BIT false + #define ST_MAGN_2_OUT_X_L_ADDR 0x28 + #define ST_MAGN_2_OUT_Y_L_ADDR 0x2a +@@ -266,9 +269,14 @@ static const struct st_sensors st_magn_sensors[] = { + .gain = ST_MAGN_2_FS_AVL_8000_GAIN, + }, + [2] = { +- .num = ST_MAGN_FS_AVL_10000MG, +- .value = ST_MAGN_2_FS_AVL_10000_VAL, +- .gain = ST_MAGN_2_FS_AVL_10000_GAIN, ++ .num = ST_MAGN_FS_AVL_12000MG, ++ .value = ST_MAGN_2_FS_AVL_12000_VAL, ++ .gain = ST_MAGN_2_FS_AVL_12000_GAIN, ++ }, ++ [3] = { ++ .num = ST_MAGN_FS_AVL_16000MG, ++ .value = ST_MAGN_2_FS_AVL_16000_VAL, ++ .gain = ST_MAGN_2_FS_AVL_16000_GAIN, + }, + }, + }, +diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c +index 84a0789..7a80509 100644 +--- a/drivers/iio/temperature/tmp006.c ++++ b/drivers/iio/temperature/tmp006.c +@@ -132,6 +132,9 @@ static int tmp006_write_raw(struct iio_dev *indio_dev, + struct tmp006_data *data = iio_priv(indio_dev); + int i; + ++ if (mask != IIO_CHAN_INFO_SAMP_FREQ) ++ return -EINVAL; ++ + for (i = 0; i < ARRAY_SIZE(tmp006_freqs); i++) + if ((val == tmp006_freqs[i][0]) && + (val2 == tmp006_freqs[i][1])) { +diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c +index 42c3058..dbd7d66 100644 +--- a/drivers/infiniband/core/cma.c ++++ b/drivers/infiniband/core/cma.c +@@ -859,19 +859,27 @@ static void cma_save_ib_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id + memcpy(&ib->sib_addr, &path->dgid, 16); + } + ++static __be16 ss_get_port(const struct sockaddr_storage *ss) ++{ ++ if (ss->ss_family == AF_INET) ++ return ((struct sockaddr_in *)ss)->sin_port; ++ else if (ss->ss_family == AF_INET6) ++ return ((struct sockaddr_in6 *)ss)->sin6_port; ++ BUG(); ++} ++ + static void cma_save_ip4_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id, + struct cma_hdr *hdr) + { +- struct sockaddr_in *listen4, *ip4; ++ struct sockaddr_in *ip4; + +- listen4 = (struct sockaddr_in *) &listen_id->route.addr.src_addr; + ip4 = (struct sockaddr_in *) &id->route.addr.src_addr; +- ip4->sin_family = listen4->sin_family; ++ ip4->sin_family = AF_INET; + ip4->sin_addr.s_addr = hdr->dst_addr.ip4.addr; +- ip4->sin_port = listen4->sin_port; ++ ip4->sin_port = ss_get_port(&listen_id->route.addr.src_addr); + + ip4 = (struct sockaddr_in *) &id->route.addr.dst_addr; +- ip4->sin_family = listen4->sin_family; ++ ip4->sin_family = AF_INET; + ip4->sin_addr.s_addr = hdr->src_addr.ip4.addr; + ip4->sin_port = hdr->port; + } +@@ -879,16 +887,15 @@ static void cma_save_ip4_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_i + static void cma_save_ip6_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id, + struct cma_hdr *hdr) + { +- struct sockaddr_in6 *listen6, *ip6; ++ struct sockaddr_in6 *ip6; + +- listen6 = (struct sockaddr_in6 *) &listen_id->route.addr.src_addr; + ip6 = (struct sockaddr_in6 *) &id->route.addr.src_addr; +- ip6->sin6_family = listen6->sin6_family; ++ ip6->sin6_family = AF_INET6; + ip6->sin6_addr = hdr->dst_addr.ip6; +- ip6->sin6_port = listen6->sin6_port; ++ ip6->sin6_port = ss_get_port(&listen_id->route.addr.src_addr); + + ip6 = (struct sockaddr_in6 *) &id->route.addr.dst_addr; +- ip6->sin6_family = listen6->sin6_family; ++ ip6->sin6_family = AF_INET6; + ip6->sin6_addr = hdr->src_addr.ip6; + ip6->sin6_port = hdr->port; + } +diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c +index 3d2e489..ff9163d 100644 +--- a/drivers/infiniband/core/iwcm.c ++++ b/drivers/infiniband/core/iwcm.c +@@ -46,6 +46,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -65,6 +66,20 @@ struct iwcm_work { + struct list_head free_list; + }; + ++static unsigned int default_backlog = 256; ++ ++static struct ctl_table_header *iwcm_ctl_table_hdr; ++static struct ctl_table iwcm_ctl_table[] = { ++ { ++ .procname = "default_backlog", ++ .data = &default_backlog, ++ .maxlen = sizeof(default_backlog), ++ .mode = 0644, ++ .proc_handler = proc_dointvec, ++ }, ++ { } ++}; ++ + /* + * The following services provide a mechanism for pre-allocating iwcm_work + * elements. The design pre-allocates them based on the cm_id type: +@@ -425,6 +440,9 @@ int iw_cm_listen(struct iw_cm_id *cm_id, int backlog) + + cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); + ++ if (!backlog) ++ backlog = default_backlog; ++ + ret = alloc_work_entries(cm_id_priv, backlog); + if (ret) + return ret; +@@ -1030,11 +1048,20 @@ static int __init iw_cm_init(void) + if (!iwcm_wq) + return -ENOMEM; + ++ iwcm_ctl_table_hdr = register_net_sysctl(&init_net, "net/iw_cm", ++ iwcm_ctl_table); ++ if (!iwcm_ctl_table_hdr) { ++ pr_err("iw_cm: couldn't register sysctl paths\n"); ++ destroy_workqueue(iwcm_wq); ++ return -ENOMEM; ++ } ++ + return 0; + } + + static void __exit iw_cm_cleanup(void) + { ++ unregister_net_sysctl_table(iwcm_ctl_table_hdr); + destroy_workqueue(iwcm_wq); + } + +diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c +index 56a4b7c..45d67e9 100644 +--- a/drivers/infiniband/core/ucma.c ++++ b/drivers/infiniband/core/ucma.c +@@ -1124,6 +1124,9 @@ static int ucma_set_ib_path(struct ucma_context *ctx, + if (!optlen) + return -EINVAL; + ++ memset(&sa_path, 0, sizeof(sa_path)); ++ sa_path.vlan_id = 0xffff; ++ + ib_sa_unpack_path(path_data->path_rec, &sa_path); + ret = rdma_set_ib_paths(ctx->cm_id, &sa_path, 1); + if (ret) +diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c +index a841123..c1fef27 100644 +--- a/drivers/infiniband/core/umem.c ++++ b/drivers/infiniband/core/umem.c +@@ -94,6 +94,17 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, + if (dmasync) + dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs); + ++ if (!size) ++ return ERR_PTR(-EINVAL); ++ ++ /* ++ * If the combination of the addr and size requested for this memory ++ * region causes an integer overflow, return error. ++ */ ++ if (((addr + size) < addr) || ++ PAGE_ALIGN(addr + size) < (addr + size)) ++ return ERR_PTR(-EINVAL); ++ + if (!can_do_mlock()) + return ERR_PTR(-EPERM); + +diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c +index ea6203e..2adc143 100644 +--- a/drivers/infiniband/core/uverbs_cmd.c ++++ b/drivers/infiniband/core/uverbs_cmd.c +@@ -1964,20 +1964,21 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, + if (qp->real_qp == qp) { + ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd.attr_mask); + if (ret) +- goto out; ++ goto release_qp; + ret = qp->device->modify_qp(qp, attr, + modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata); + } else { + ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask)); + } + +- put_qp_read(qp); +- + if (ret) +- goto out; ++ goto release_qp; + + ret = in_len; + ++release_qp: ++ put_qp_read(qp); ++ + out: + kfree(attr); + +@@ -2425,6 +2426,8 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, + attr.grh.sgid_index = cmd.attr.grh.sgid_index; + attr.grh.hop_limit = cmd.attr.grh.hop_limit; + attr.grh.traffic_class = cmd.attr.grh.traffic_class; ++ attr.vlan_id = 0; ++ memset(&attr.dmac, 0, sizeof(attr.dmac)); + memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16); + + ah = ib_create_ah(pd, &attr); +diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c +index 08219fb..7a515c8 100644 +--- a/drivers/infiniband/core/uverbs_main.c ++++ b/drivers/infiniband/core/uverbs_main.c +@@ -476,6 +476,7 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file, + + entry->desc.async.element = element; + entry->desc.async.event_type = event; ++ entry->desc.async.reserved = 0; + entry->counter = counter; + + list_add_tail(&entry->list, &file->async_file->event_list); +diff --git a/drivers/infiniband/core/uverbs_marshall.c b/drivers/infiniband/core/uverbs_marshall.c +index e7bee46..abd9724 100644 +--- a/drivers/infiniband/core/uverbs_marshall.c ++++ b/drivers/infiniband/core/uverbs_marshall.c +@@ -140,5 +140,9 @@ void ib_copy_path_rec_from_user(struct ib_sa_path_rec *dst, + dst->packet_life_time = src->packet_life_time; + dst->preference = src->preference; + dst->packet_life_time_selector = src->packet_life_time_selector; ++ ++ memset(dst->smac, 0, sizeof(dst->smac)); ++ memset(dst->dmac, 0, sizeof(dst->dmac)); ++ dst->vlan_id = 0xffff; + } + EXPORT_SYMBOL(ib_copy_path_rec_from_user); +diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c +index f2a3f48..2592ab5 100644 +--- a/drivers/infiniband/hw/mlx4/mad.c ++++ b/drivers/infiniband/hw/mlx4/mad.c +@@ -64,6 +64,14 @@ enum { + #define GUID_TBL_BLK_NUM_ENTRIES 8 + #define GUID_TBL_BLK_SIZE (GUID_TBL_ENTRY_SIZE * GUID_TBL_BLK_NUM_ENTRIES) + ++/* Counters should be saturate once they reach their maximum value */ ++#define ASSIGN_32BIT_COUNTER(counter, value) do {\ ++ if ((value) > U32_MAX) \ ++ counter = cpu_to_be32(U32_MAX); \ ++ else \ ++ counter = cpu_to_be32(value); \ ++} while (0) ++ + struct mlx4_mad_rcv_buf { + struct ib_grh grh; + u8 payload[256]; +@@ -730,10 +738,14 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, + static void edit_counter(struct mlx4_counter *cnt, + struct ib_pma_portcounters *pma_cnt) + { +- pma_cnt->port_xmit_data = cpu_to_be32((be64_to_cpu(cnt->tx_bytes)>>2)); +- pma_cnt->port_rcv_data = cpu_to_be32((be64_to_cpu(cnt->rx_bytes)>>2)); +- pma_cnt->port_xmit_packets = cpu_to_be32(be64_to_cpu(cnt->tx_frames)); +- pma_cnt->port_rcv_packets = cpu_to_be32(be64_to_cpu(cnt->rx_frames)); ++ ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_data, ++ (be64_to_cpu(cnt->tx_bytes) >> 2)); ++ ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_data, ++ (be64_to_cpu(cnt->rx_bytes) >> 2)); ++ ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_packets, ++ be64_to_cpu(cnt->tx_frames)); ++ ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_packets, ++ be64_to_cpu(cnt->rx_frames)); + } + + static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, +diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c +index f9c12e9..1a3d924 100644 +--- a/drivers/infiniband/hw/mlx4/main.c ++++ b/drivers/infiniband/hw/mlx4/main.c +@@ -1161,8 +1161,7 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) + struct mlx4_ib_qp *mqp = to_mqp(ibqp); + u64 reg_id; + struct mlx4_ib_steering *ib_steering = NULL; +- enum mlx4_protocol prot = (gid->raw[1] == 0x0e) ? +- MLX4_PROT_IB_IPV4 : MLX4_PROT_IB_IPV6; ++ enum mlx4_protocol prot = MLX4_PROT_IB_IPV6; + + if (mdev->dev->caps.steering_mode == + MLX4_STEERING_MODE_DEVICE_MANAGED) { +@@ -1175,8 +1174,10 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) + !!(mqp->flags & + MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK), + prot, ®_id); +- if (err) ++ if (err) { ++ pr_err("multicast attach op failed, err %d\n", err); + goto err_malloc; ++ } + + err = add_gid_entry(ibqp, gid); + if (err) +@@ -1224,8 +1225,7 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) + struct net_device *ndev; + struct mlx4_ib_gid_entry *ge; + u64 reg_id = 0; +- enum mlx4_protocol prot = (gid->raw[1] == 0x0e) ? +- MLX4_PROT_IB_IPV4 : MLX4_PROT_IB_IPV6; ++ enum mlx4_protocol prot = MLX4_PROT_IB_IPV6; + + if (mdev->dev->caps.steering_mode == + MLX4_STEERING_MODE_DEVICE_MANAGED) { +@@ -1622,6 +1622,7 @@ static void mlx4_ib_get_dev_addr(struct net_device *dev, + struct inet6_dev *in6_dev; + union ib_gid *pgid; + struct inet6_ifaddr *ifp; ++ union ib_gid default_gid; + #endif + union ib_gid gid; + +@@ -1642,12 +1643,15 @@ static void mlx4_ib_get_dev_addr(struct net_device *dev, + in_dev_put(in_dev); + } + #if IS_ENABLED(CONFIG_IPV6) ++ mlx4_make_default_gid(dev, &default_gid); + /* IPv6 gids */ + in6_dev = in6_dev_get(dev); + if (in6_dev) { + read_lock_bh(&in6_dev->lock); + list_for_each_entry(ifp, &in6_dev->addr_list, if_list) { + pgid = (union ib_gid *)&ifp->addr; ++ if (!memcmp(pgid, &default_gid, sizeof(*pgid))) ++ continue; + update_gid_table(ibdev, port, pgid, 0, 0); + } + read_unlock_bh(&in6_dev->lock); +@@ -1723,31 +1727,34 @@ static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev) + port_state = (netif_running(curr_netdev) && netif_carrier_ok(curr_netdev)) ? + IB_PORT_ACTIVE : IB_PORT_DOWN; + mlx4_ib_set_default_gid(ibdev, curr_netdev, port); +- } else { +- reset_gid_table(ibdev, port); +- } +- /* if using bonding/team and a slave port is down, we don't the bond IP +- * based gids in the table since flows that select port by gid may get +- * the down port. +- */ +- if (curr_master && (port_state == IB_PORT_DOWN)) { +- reset_gid_table(ibdev, port); +- mlx4_ib_set_default_gid(ibdev, curr_netdev, port); +- } +- /* if bonding is used it is possible that we add it to masters +- * only after IP address is assigned to the net bonding +- * interface. +- */ +- if (curr_master && (old_master != curr_master)) { +- reset_gid_table(ibdev, port); +- mlx4_ib_set_default_gid(ibdev, curr_netdev, port); +- mlx4_ib_get_dev_addr(curr_master, ibdev, port); +- } ++ /* if using bonding/team and a slave port is down, we ++ * don't the bond IP based gids in the table since ++ * flows that select port by gid may get the down port. ++ */ ++ if (curr_master && (port_state == IB_PORT_DOWN)) { ++ reset_gid_table(ibdev, port); ++ mlx4_ib_set_default_gid(ibdev, ++ curr_netdev, port); ++ } ++ /* if bonding is used it is possible that we add it to ++ * masters only after IP address is assigned to the ++ * net bonding interface. ++ */ ++ if (curr_master && (old_master != curr_master)) { ++ reset_gid_table(ibdev, port); ++ mlx4_ib_set_default_gid(ibdev, ++ curr_netdev, port); ++ mlx4_ib_get_dev_addr(curr_master, ibdev, port); ++ } + +- if (!curr_master && (old_master != curr_master)) { ++ if (!curr_master && (old_master != curr_master)) { ++ reset_gid_table(ibdev, port); ++ mlx4_ib_set_default_gid(ibdev, ++ curr_netdev, port); ++ mlx4_ib_get_dev_addr(curr_netdev, ibdev, port); ++ } ++ } else { + reset_gid_table(ibdev, port); +- mlx4_ib_set_default_gid(ibdev, curr_netdev, port); +- mlx4_ib_get_dev_addr(curr_netdev, ibdev, port); + } + } + +diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c +index d8f4d1f..8d7cd98 100644 +--- a/drivers/infiniband/hw/mlx4/qp.c ++++ b/drivers/infiniband/hw/mlx4/qp.c +@@ -2274,8 +2274,7 @@ static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr, + + memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen); + +- *lso_hdr_sz = cpu_to_be32((wr->wr.ud.mss - wr->wr.ud.hlen) << 16 | +- wr->wr.ud.hlen); ++ *lso_hdr_sz = cpu_to_be32(wr->wr.ud.mss << 16 | wr->wr.ud.hlen); + *lso_seg_len = halign; + return 0; + } +diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h +index 1946101..675d3c7 100644 +--- a/drivers/infiniband/hw/qib/qib.h ++++ b/drivers/infiniband/hw/qib/qib.h +@@ -1080,12 +1080,6 @@ struct qib_devdata { + /* control high-level access to EEPROM */ + struct mutex eep_lock; + uint64_t traffic_wds; +- /* active time is kept in seconds, but logged in hours */ +- atomic_t active_time; +- /* Below are nominal shadow of EEPROM, new since last EEPROM update */ +- uint8_t eep_st_errs[QIB_EEP_LOG_CNT]; +- uint8_t eep_st_new_errs[QIB_EEP_LOG_CNT]; +- uint16_t eep_hrs; + /* + * masks for which bits of errs, hwerrs that cause + * each of the counters to increment. +@@ -1307,8 +1301,7 @@ int qib_twsi_blk_rd(struct qib_devdata *dd, int dev, int addr, void *buffer, + int qib_twsi_blk_wr(struct qib_devdata *dd, int dev, int addr, + const void *buffer, int len); + void qib_get_eeprom_info(struct qib_devdata *); +-int qib_update_eeprom_log(struct qib_devdata *dd); +-void qib_inc_eeprom_err(struct qib_devdata *dd, u32 eidx, u32 incr); ++#define qib_inc_eeprom_err(dd, eidx, incr) + void qib_dump_lookup_output_queue(struct qib_devdata *); + void qib_force_pio_avail_update(struct qib_devdata *); + void qib_clear_symerror_on_linkup(unsigned long opaque); +diff --git a/drivers/infiniband/hw/qib/qib_debugfs.c b/drivers/infiniband/hw/qib/qib_debugfs.c +index 799a0c3..6abd3ed 100644 +--- a/drivers/infiniband/hw/qib/qib_debugfs.c ++++ b/drivers/infiniband/hw/qib/qib_debugfs.c +@@ -193,6 +193,7 @@ static void *_qp_stats_seq_start(struct seq_file *s, loff_t *pos) + struct qib_qp_iter *iter; + loff_t n = *pos; + ++ rcu_read_lock(); + iter = qib_qp_iter_init(s->private); + if (!iter) + return NULL; +@@ -224,7 +225,7 @@ static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr, + + static void _qp_stats_seq_stop(struct seq_file *s, void *iter_ptr) + { +- /* nothing for now */ ++ rcu_read_unlock(); + } + + static int _qp_stats_seq_show(struct seq_file *s, void *iter_ptr) +diff --git a/drivers/infiniband/hw/qib/qib_eeprom.c b/drivers/infiniband/hw/qib/qib_eeprom.c +index 4d5d71a..e2280b0 100644 +--- a/drivers/infiniband/hw/qib/qib_eeprom.c ++++ b/drivers/infiniband/hw/qib/qib_eeprom.c +@@ -267,190 +267,9 @@ void qib_get_eeprom_info(struct qib_devdata *dd) + "Board SN %s did not pass functional test: %s\n", + dd->serial, ifp->if_comment); + +- memcpy(&dd->eep_st_errs, &ifp->if_errcntp, QIB_EEP_LOG_CNT); +- /* +- * Power-on (actually "active") hours are kept as little-endian value +- * in EEPROM, but as seconds in a (possibly as small as 24-bit) +- * atomic_t while running. +- */ +- atomic_set(&dd->active_time, 0); +- dd->eep_hrs = ifp->if_powerhour[0] | (ifp->if_powerhour[1] << 8); +- + done: + vfree(buf); + + bail:; + } + +-/** +- * qib_update_eeprom_log - copy active-time and error counters to eeprom +- * @dd: the qlogic_ib device +- * +- * Although the time is kept as seconds in the qib_devdata struct, it is +- * rounded to hours for re-write, as we have only 16 bits in EEPROM. +- * First-cut code reads whole (expected) struct qib_flash, modifies, +- * re-writes. Future direction: read/write only what we need, assuming +- * that the EEPROM had to have been "good enough" for driver init, and +- * if not, we aren't making it worse. +- * +- */ +-int qib_update_eeprom_log(struct qib_devdata *dd) +-{ +- void *buf; +- struct qib_flash *ifp; +- int len, hi_water; +- uint32_t new_time, new_hrs; +- u8 csum; +- int ret, idx; +- unsigned long flags; +- +- /* first, check if we actually need to do anything. */ +- ret = 0; +- for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) { +- if (dd->eep_st_new_errs[idx]) { +- ret = 1; +- break; +- } +- } +- new_time = atomic_read(&dd->active_time); +- +- if (ret == 0 && new_time < 3600) +- goto bail; +- +- /* +- * The quick-check above determined that there is something worthy +- * of logging, so get current contents and do a more detailed idea. +- * read full flash, not just currently used part, since it may have +- * been written with a newer definition +- */ +- len = sizeof(struct qib_flash); +- buf = vmalloc(len); +- ret = 1; +- if (!buf) { +- qib_dev_err(dd, +- "Couldn't allocate memory to read %u bytes from eeprom for logging\n", +- len); +- goto bail; +- } +- +- /* Grab semaphore and read current EEPROM. If we get an +- * error, let go, but if not, keep it until we finish write. +- */ +- ret = mutex_lock_interruptible(&dd->eep_lock); +- if (ret) { +- qib_dev_err(dd, "Unable to acquire EEPROM for logging\n"); +- goto free_bail; +- } +- ret = qib_twsi_blk_rd(dd, dd->twsi_eeprom_dev, 0, buf, len); +- if (ret) { +- mutex_unlock(&dd->eep_lock); +- qib_dev_err(dd, "Unable read EEPROM for logging\n"); +- goto free_bail; +- } +- ifp = (struct qib_flash *)buf; +- +- csum = flash_csum(ifp, 0); +- if (csum != ifp->if_csum) { +- mutex_unlock(&dd->eep_lock); +- qib_dev_err(dd, "EEPROM cks err (0x%02X, S/B 0x%02X)\n", +- csum, ifp->if_csum); +- ret = 1; +- goto free_bail; +- } +- hi_water = 0; +- spin_lock_irqsave(&dd->eep_st_lock, flags); +- for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) { +- int new_val = dd->eep_st_new_errs[idx]; +- if (new_val) { +- /* +- * If we have seen any errors, add to EEPROM values +- * We need to saturate at 0xFF (255) and we also +- * would need to adjust the checksum if we were +- * trying to minimize EEPROM traffic +- * Note that we add to actual current count in EEPROM, +- * in case it was altered while we were running. +- */ +- new_val += ifp->if_errcntp[idx]; +- if (new_val > 0xFF) +- new_val = 0xFF; +- if (ifp->if_errcntp[idx] != new_val) { +- ifp->if_errcntp[idx] = new_val; +- hi_water = offsetof(struct qib_flash, +- if_errcntp) + idx; +- } +- /* +- * update our shadow (used to minimize EEPROM +- * traffic), to match what we are about to write. +- */ +- dd->eep_st_errs[idx] = new_val; +- dd->eep_st_new_errs[idx] = 0; +- } +- } +- /* +- * Now update active-time. We would like to round to the nearest hour +- * but unless atomic_t are sure to be proper signed ints we cannot, +- * because we need to account for what we "transfer" to EEPROM and +- * if we log an hour at 31 minutes, then we would need to set +- * active_time to -29 to accurately count the _next_ hour. +- */ +- if (new_time >= 3600) { +- new_hrs = new_time / 3600; +- atomic_sub((new_hrs * 3600), &dd->active_time); +- new_hrs += dd->eep_hrs; +- if (new_hrs > 0xFFFF) +- new_hrs = 0xFFFF; +- dd->eep_hrs = new_hrs; +- if ((new_hrs & 0xFF) != ifp->if_powerhour[0]) { +- ifp->if_powerhour[0] = new_hrs & 0xFF; +- hi_water = offsetof(struct qib_flash, if_powerhour); +- } +- if ((new_hrs >> 8) != ifp->if_powerhour[1]) { +- ifp->if_powerhour[1] = new_hrs >> 8; +- hi_water = offsetof(struct qib_flash, if_powerhour) + 1; +- } +- } +- /* +- * There is a tiny possibility that we could somehow fail to write +- * the EEPROM after updating our shadows, but problems from holding +- * the spinlock too long are a much bigger issue. +- */ +- spin_unlock_irqrestore(&dd->eep_st_lock, flags); +- if (hi_water) { +- /* we made some change to the data, uopdate cksum and write */ +- csum = flash_csum(ifp, 1); +- ret = eeprom_write_with_enable(dd, 0, buf, hi_water + 1); +- } +- mutex_unlock(&dd->eep_lock); +- if (ret) +- qib_dev_err(dd, "Failed updating EEPROM\n"); +- +-free_bail: +- vfree(buf); +-bail: +- return ret; +-} +- +-/** +- * qib_inc_eeprom_err - increment one of the four error counters +- * that are logged to EEPROM. +- * @dd: the qlogic_ib device +- * @eidx: 0..3, the counter to increment +- * @incr: how much to add +- * +- * Each counter is 8-bits, and saturates at 255 (0xFF). They +- * are copied to the EEPROM (aka flash) whenever qib_update_eeprom_log() +- * is called, but it can only be called in a context that allows sleep. +- * This function can be called even at interrupt level. +- */ +-void qib_inc_eeprom_err(struct qib_devdata *dd, u32 eidx, u32 incr) +-{ +- uint new_val; +- unsigned long flags; +- +- spin_lock_irqsave(&dd->eep_st_lock, flags); +- new_val = dd->eep_st_new_errs[eidx] + incr; +- if (new_val > 255) +- new_val = 255; +- dd->eep_st_new_errs[eidx] = new_val; +- spin_unlock_irqrestore(&dd->eep_st_lock, flags); +-} +diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c +index 84e593d..295f631 100644 +--- a/drivers/infiniband/hw/qib/qib_iba6120.c ++++ b/drivers/infiniband/hw/qib/qib_iba6120.c +@@ -2682,8 +2682,6 @@ static void qib_get_6120_faststats(unsigned long opaque) + spin_lock_irqsave(&dd->eep_st_lock, flags); + traffic_wds -= dd->traffic_wds; + dd->traffic_wds += traffic_wds; +- if (traffic_wds >= QIB_TRAFFIC_ACTIVE_THRESHOLD) +- atomic_add(5, &dd->active_time); /* S/B #define */ + spin_unlock_irqrestore(&dd->eep_st_lock, flags); + + qib_chk_6120_errormask(dd); +diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c +index 454c2e7..c86e71b 100644 +--- a/drivers/infiniband/hw/qib/qib_iba7220.c ++++ b/drivers/infiniband/hw/qib/qib_iba7220.c +@@ -3299,8 +3299,6 @@ static void qib_get_7220_faststats(unsigned long opaque) + spin_lock_irqsave(&dd->eep_st_lock, flags); + traffic_wds -= dd->traffic_wds; + dd->traffic_wds += traffic_wds; +- if (traffic_wds >= QIB_TRAFFIC_ACTIVE_THRESHOLD) +- atomic_add(5, &dd->active_time); /* S/B #define */ + spin_unlock_irqrestore(&dd->eep_st_lock, flags); + done: + mod_timer(&dd->stats_timer, jiffies + HZ * ACTIVITY_TIMER); +diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c +index d1bd213..0f8d1f0 100644 +--- a/drivers/infiniband/hw/qib/qib_iba7322.c ++++ b/drivers/infiniband/hw/qib/qib_iba7322.c +@@ -5191,8 +5191,6 @@ static void qib_get_7322_faststats(unsigned long opaque) + spin_lock_irqsave(&ppd->dd->eep_st_lock, flags); + traffic_wds -= ppd->dd->traffic_wds; + ppd->dd->traffic_wds += traffic_wds; +- if (traffic_wds >= QIB_TRAFFIC_ACTIVE_THRESHOLD) +- atomic_add(ACTIVITY_TIMER, &ppd->dd->active_time); + spin_unlock_irqrestore(&ppd->dd->eep_st_lock, flags); + if (ppd->cpspec->qdr_dfe_on && (ppd->link_speed_active & + QIB_IB_QDR) && +diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c +index 76c3e17..8c9bb6c 100644 +--- a/drivers/infiniband/hw/qib/qib_init.c ++++ b/drivers/infiniband/hw/qib/qib_init.c +@@ -922,7 +922,6 @@ static void qib_shutdown_device(struct qib_devdata *dd) + } + } + +- qib_update_eeprom_log(dd); + } + + /** +diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c +index 0cad0c4..6a71b2b 100644 +--- a/drivers/infiniband/hw/qib/qib_qp.c ++++ b/drivers/infiniband/hw/qib/qib_qp.c +@@ -1324,7 +1324,6 @@ int qib_qp_iter_next(struct qib_qp_iter *iter) + struct qib_qp *pqp = iter->qp; + struct qib_qp *qp; + +- rcu_read_lock(); + for (; n < dev->qp_table_size; n++) { + if (pqp) + qp = rcu_dereference(pqp->next); +@@ -1332,18 +1331,11 @@ int qib_qp_iter_next(struct qib_qp_iter *iter) + qp = rcu_dereference(dev->qp_table[n]); + pqp = qp; + if (qp) { +- if (iter->qp) +- atomic_dec(&iter->qp->refcount); +- atomic_inc(&qp->refcount); +- rcu_read_unlock(); + iter->qp = qp; + iter->n = n; + return 0; + } + } +- rcu_read_unlock(); +- if (iter->qp) +- atomic_dec(&iter->qp->refcount); + return ret; + } + +diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c +index 3c8e4e3..b9ccbda 100644 +--- a/drivers/infiniband/hw/qib/qib_sysfs.c ++++ b/drivers/infiniband/hw/qib/qib_sysfs.c +@@ -611,28 +611,6 @@ bail: + return ret < 0 ? ret : count; + } + +-static ssize_t show_logged_errs(struct device *device, +- struct device_attribute *attr, char *buf) +-{ +- struct qib_ibdev *dev = +- container_of(device, struct qib_ibdev, ibdev.dev); +- struct qib_devdata *dd = dd_from_dev(dev); +- int idx, count; +- +- /* force consistency with actual EEPROM */ +- if (qib_update_eeprom_log(dd) != 0) +- return -ENXIO; +- +- count = 0; +- for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) { +- count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c", +- dd->eep_st_errs[idx], +- idx == (QIB_EEP_LOG_CNT - 1) ? '\n' : ' '); +- } +- +- return count; +-} +- + /* + * Dump tempsense regs. in decimal, to ease shell-scripts. + */ +@@ -679,7 +657,6 @@ static DEVICE_ATTR(nctxts, S_IRUGO, show_nctxts, NULL); + static DEVICE_ATTR(nfreectxts, S_IRUGO, show_nfreectxts, NULL); + static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL); + static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL); +-static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL); + static DEVICE_ATTR(tempsense, S_IRUGO, show_tempsense, NULL); + static DEVICE_ATTR(localbus_info, S_IRUGO, show_localbus_info, NULL); + static DEVICE_ATTR(chip_reset, S_IWUSR, NULL, store_chip_reset); +@@ -693,7 +670,6 @@ static struct device_attribute *qib_attributes[] = { + &dev_attr_nfreectxts, + &dev_attr_serial, + &dev_attr_boardversion, +- &dev_attr_logged_errors, + &dev_attr_tempsense, + &dev_attr_localbus_info, + &dev_attr_chip_reset, +diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c +index 156205a..dd2b610 100644 +--- a/drivers/infiniband/ulp/isert/ib_isert.c ++++ b/drivers/infiniband/ulp/isert/ib_isert.c +@@ -41,6 +41,7 @@ static DEFINE_MUTEX(device_list_mutex); + static LIST_HEAD(device_list); + static struct workqueue_struct *isert_rx_wq; + static struct workqueue_struct *isert_comp_wq; ++static struct workqueue_struct *isert_release_wq; + + static void + isert_unmap_cmd(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn); +@@ -52,6 +53,13 @@ isert_unreg_rdma(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn); + static int + isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd, + struct isert_rdma_wr *wr); ++static int ++isert_rdma_post_recvl(struct isert_conn *isert_conn); ++static int ++isert_rdma_accept(struct isert_conn *isert_conn); ++struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np); ++ ++static void isert_release_work(struct work_struct *work); + + static void + isert_qp_event_callback(struct ib_event *e, void *context) +@@ -112,9 +120,12 @@ isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id) + attr.cap.max_recv_wr = ISERT_QP_MAX_RECV_DTOS; + /* + * FIXME: Use devattr.max_sge - 2 for max_send_sge as +- * work-around for RDMA_READ.. ++ * work-around for RDMA_READs with ConnectX-2. ++ * ++ * Also, still make sure to have at least two SGEs for ++ * outgoing control PDU responses. + */ +- attr.cap.max_send_sge = device->dev_attr.max_sge - 2; ++ attr.cap.max_send_sge = max(2, device->dev_attr.max_sge - 2); + isert_conn->max_sge = attr.cap.max_send_sge; + + attr.cap.max_recv_sge = 1; +@@ -129,12 +140,18 @@ isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id) + ret = rdma_create_qp(cma_id, isert_conn->conn_pd, &attr); + if (ret) { + pr_err("rdma_create_qp failed for cma_id %d\n", ret); +- return ret; ++ goto err; + } + isert_conn->conn_qp = cma_id->qp; + pr_debug("rdma_create_qp() returned success >>>>>>>>>>>>>>>>>>>>>>>>>.\n"); + + return 0; ++err: ++ mutex_lock(&device_list_mutex); ++ device->cq_active_qps[min_index]--; ++ mutex_unlock(&device_list_mutex); ++ ++ return ret; + } + + static void +@@ -191,7 +208,7 @@ fail: + static void + isert_free_rx_descriptors(struct isert_conn *isert_conn) + { +- struct ib_device *ib_dev = isert_conn->conn_cm_id->device; ++ struct ib_device *ib_dev = isert_conn->conn_device->ib_device; + struct iser_rx_desc *rx_desc; + int i; + +@@ -220,12 +237,16 @@ isert_create_device_ib_res(struct isert_device *device) + struct isert_cq_desc *cq_desc; + struct ib_device_attr *dev_attr; + int ret = 0, i, j; ++ int max_rx_cqe, max_tx_cqe; + + dev_attr = &device->dev_attr; + ret = isert_query_device(ib_dev, dev_attr); + if (ret) + return ret; + ++ max_rx_cqe = min(ISER_MAX_RX_CQ_LEN, dev_attr->max_cqe); ++ max_tx_cqe = min(ISER_MAX_TX_CQ_LEN, dev_attr->max_cqe); ++ + /* asign function handlers */ + if (dev_attr->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS) { + device->use_fastreg = 1; +@@ -261,7 +282,7 @@ isert_create_device_ib_res(struct isert_device *device) + isert_cq_rx_callback, + isert_cq_event_callback, + (void *)&cq_desc[i], +- ISER_MAX_RX_CQ_LEN, i); ++ max_rx_cqe, i); + if (IS_ERR(device->dev_rx_cq[i])) { + ret = PTR_ERR(device->dev_rx_cq[i]); + device->dev_rx_cq[i] = NULL; +@@ -273,7 +294,7 @@ isert_create_device_ib_res(struct isert_device *device) + isert_cq_tx_callback, + isert_cq_event_callback, + (void *)&cq_desc[i], +- ISER_MAX_TX_CQ_LEN, i); ++ max_tx_cqe, i); + if (IS_ERR(device->dev_tx_cq[i])) { + ret = PTR_ERR(device->dev_tx_cq[i]); + device->dev_tx_cq[i] = NULL; +@@ -482,8 +503,8 @@ err: + static int + isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + { +- struct iscsi_np *np = cma_id->context; +- struct isert_np *isert_np = np->np_context; ++ struct isert_np *isert_np = cma_id->context; ++ struct iscsi_np *np = isert_np->np; + struct isert_conn *isert_conn; + struct isert_device *device; + struct ib_device *ib_dev = cma_id->device; +@@ -508,15 +529,15 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + isert_conn->state = ISER_CONN_INIT; + INIT_LIST_HEAD(&isert_conn->conn_accept_node); + init_completion(&isert_conn->conn_login_comp); ++ init_completion(&isert_conn->login_req_comp); + init_completion(&isert_conn->conn_wait); + init_completion(&isert_conn->conn_wait_comp_err); + kref_init(&isert_conn->conn_kref); +- kref_get(&isert_conn->conn_kref); + mutex_init(&isert_conn->conn_mutex); + spin_lock_init(&isert_conn->conn_lock); + INIT_LIST_HEAD(&isert_conn->conn_fr_pool); ++ INIT_WORK(&isert_conn->release_work, isert_release_work); + +- cma_id->context = isert_conn; + isert_conn->conn_cm_id = cma_id; + isert_conn->responder_resources = event->param.conn.responder_resources; + isert_conn->initiator_depth = event->param.conn.initiator_depth; +@@ -590,6 +611,14 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + if (ret) + goto out_conn_dev; + ++ ret = isert_rdma_post_recvl(isert_conn); ++ if (ret) ++ goto out_conn_dev; ++ ++ ret = isert_rdma_accept(isert_conn); ++ if (ret) ++ goto out_conn_dev; ++ + mutex_lock(&isert_np->np_accept_mutex); + list_add_tail(&isert_conn->conn_accept_node, &isert_np->np_accept_list); + mutex_unlock(&isert_np->np_accept_mutex); +@@ -614,33 +643,37 @@ out_login_buf: + kfree(isert_conn->login_buf); + out: + kfree(isert_conn); ++ rdma_reject(cma_id, NULL, 0); + return ret; + } + + static void + isert_connect_release(struct isert_conn *isert_conn) + { +- struct ib_device *ib_dev = isert_conn->conn_cm_id->device; + struct isert_device *device = isert_conn->conn_device; + int cq_index; ++ struct ib_device *ib_dev = device->ib_device; + + pr_debug("Entering isert_connect_release(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); + + if (device && device->use_fastreg) + isert_conn_free_fastreg_pool(isert_conn); + ++ isert_free_rx_descriptors(isert_conn); ++ if (isert_conn->conn_cm_id) ++ rdma_destroy_id(isert_conn->conn_cm_id); ++ + if (isert_conn->conn_qp) { + cq_index = ((struct isert_cq_desc *) + isert_conn->conn_qp->recv_cq->cq_context)->cq_index; + pr_debug("isert_connect_release: cq_index: %d\n", cq_index); ++ mutex_lock(&device_list_mutex); + isert_conn->conn_device->cq_active_qps[cq_index]--; ++ mutex_unlock(&device_list_mutex); + +- rdma_destroy_qp(isert_conn->conn_cm_id); ++ ib_destroy_qp(isert_conn->conn_qp); + } + +- isert_free_rx_descriptors(isert_conn); +- rdma_destroy_id(isert_conn->conn_cm_id); +- + ib_dereg_mr(isert_conn->conn_mr); + ib_dealloc_pd(isert_conn->conn_pd); + +@@ -663,7 +696,19 @@ isert_connect_release(struct isert_conn *isert_conn) + static void + isert_connected_handler(struct rdma_cm_id *cma_id) + { +- return; ++ struct isert_conn *isert_conn = cma_id->qp->qp_context; ++ ++ pr_info("conn %p\n", isert_conn); ++ ++ if (!kref_get_unless_zero(&isert_conn->conn_kref)) { ++ pr_warn("conn %p connect_release is running\n", isert_conn); ++ return; ++ } ++ ++ mutex_lock(&isert_conn->conn_mutex); ++ if (isert_conn->state != ISER_CONN_FULL_FEATURE) ++ isert_conn->state = ISER_CONN_UP; ++ mutex_unlock(&isert_conn->conn_mutex); + } + + static void +@@ -684,55 +729,125 @@ isert_put_conn(struct isert_conn *isert_conn) + kref_put(&isert_conn->conn_kref, isert_release_conn_kref); + } + ++/** ++ * isert_conn_terminate() - Initiate connection termination ++ * @isert_conn: isert connection struct ++ * ++ * Notes: ++ * In case the connection state is FULL_FEATURE, move state ++ * to TEMINATING and start teardown sequence (rdma_disconnect). ++ * In case the connection state is UP, complete flush as well. ++ * ++ * This routine must be called with conn_mutex held. Thus it is ++ * safe to call multiple times. ++ */ + static void +-isert_disconnect_work(struct work_struct *work) ++isert_conn_terminate(struct isert_conn *isert_conn) + { +- struct isert_conn *isert_conn = container_of(work, +- struct isert_conn, conn_logout_work); ++ int err; + +- pr_debug("isert_disconnect_work(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); +- mutex_lock(&isert_conn->conn_mutex); +- if (isert_conn->state == ISER_CONN_UP) ++ switch (isert_conn->state) { ++ case ISER_CONN_TERMINATING: ++ break; ++ case ISER_CONN_UP: ++ /* ++ * No flush completions will occur as we didn't ++ * get to ISER_CONN_FULL_FEATURE yet, complete ++ * to allow teardown progress. ++ */ ++ complete(&isert_conn->conn_wait_comp_err); ++ case ISER_CONN_FULL_FEATURE: /* FALLTHRU */ ++ pr_info("Terminating conn %p state %d\n", ++ isert_conn, isert_conn->state); + isert_conn->state = ISER_CONN_TERMINATING; +- +- if (isert_conn->post_recv_buf_count == 0 && +- atomic_read(&isert_conn->post_send_buf_count) == 0) { +- mutex_unlock(&isert_conn->conn_mutex); +- goto wake_up; +- } +- if (!isert_conn->conn_cm_id) { +- mutex_unlock(&isert_conn->conn_mutex); +- isert_put_conn(isert_conn); +- return; ++ err = rdma_disconnect(isert_conn->conn_cm_id); ++ if (err) ++ pr_warn("Failed rdma_disconnect isert_conn %p\n", ++ isert_conn); ++ break; ++ default: ++ pr_warn("conn %p teminating in state %d\n", ++ isert_conn, isert_conn->state); + } ++} ++ ++static int ++isert_np_cma_handler(struct isert_np *isert_np, ++ enum rdma_cm_event_type event) ++{ ++ pr_debug("isert np %p, handling event %d\n", isert_np, event); + +- if (isert_conn->disconnect) { +- /* Send DREQ/DREP towards our initiator */ +- rdma_disconnect(isert_conn->conn_cm_id); ++ switch (event) { ++ case RDMA_CM_EVENT_DEVICE_REMOVAL: ++ isert_np->np_cm_id = NULL; ++ break; ++ case RDMA_CM_EVENT_ADDR_CHANGE: ++ isert_np->np_cm_id = isert_setup_id(isert_np); ++ if (IS_ERR(isert_np->np_cm_id)) { ++ pr_err("isert np %p setup id failed: %ld\n", ++ isert_np, PTR_ERR(isert_np->np_cm_id)); ++ isert_np->np_cm_id = NULL; ++ } ++ break; ++ default: ++ pr_err("isert np %p Unexpected event %d\n", ++ isert_np, event); + } + ++ return -1; ++} ++ ++static int ++isert_disconnected_handler(struct rdma_cm_id *cma_id, ++ enum rdma_cm_event_type event) ++{ ++ struct isert_np *isert_np = cma_id->context; ++ struct isert_conn *isert_conn; ++ bool terminating = false; ++ ++ if (isert_np->np_cm_id == cma_id) ++ return isert_np_cma_handler(cma_id->context, event); ++ ++ isert_conn = cma_id->qp->qp_context; ++ ++ mutex_lock(&isert_conn->conn_mutex); ++ terminating = (isert_conn->state == ISER_CONN_TERMINATING); ++ isert_conn_terminate(isert_conn); + mutex_unlock(&isert_conn->conn_mutex); + +-wake_up: ++ pr_info("conn %p completing conn_wait\n", isert_conn); + complete(&isert_conn->conn_wait); +- isert_put_conn(isert_conn); ++ ++ if (terminating) ++ goto out; ++ ++ mutex_lock(&isert_np->np_accept_mutex); ++ if (!list_empty(&isert_conn->conn_accept_node)) { ++ list_del_init(&isert_conn->conn_accept_node); ++ isert_put_conn(isert_conn); ++ queue_work(isert_release_wq, &isert_conn->release_work); ++ } ++ mutex_unlock(&isert_np->np_accept_mutex); ++ ++out: ++ return 0; + } + +-static void +-isert_disconnected_handler(struct rdma_cm_id *cma_id, bool disconnect) ++static int ++isert_connect_error(struct rdma_cm_id *cma_id) + { +- struct isert_conn *isert_conn = (struct isert_conn *)cma_id->context; ++ struct isert_conn *isert_conn = cma_id->qp->qp_context; ++ ++ isert_conn->conn_cm_id = NULL; ++ isert_put_conn(isert_conn); + +- isert_conn->disconnect = disconnect; +- INIT_WORK(&isert_conn->conn_logout_work, isert_disconnect_work); +- schedule_work(&isert_conn->conn_logout_work); ++ return -1; + } + + static int + isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + { + int ret = 0; +- bool disconnect = false; + + pr_debug("isert_cma_handler: event %d status %d conn %p id %p\n", + event->event, event->status, cma_id->context, cma_id); +@@ -740,6 +855,9 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + switch (event->event) { + case RDMA_CM_EVENT_CONNECT_REQUEST: + ret = isert_connect_request(cma_id, event); ++ if (ret) ++ pr_err("isert_cma_handler failed RDMA_CM_EVENT: 0x%08x %d\n", ++ event->event, ret); + break; + case RDMA_CM_EVENT_ESTABLISHED: + isert_connected_handler(cma_id); +@@ -747,22 +865,19 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) + case RDMA_CM_EVENT_ADDR_CHANGE: /* FALLTHRU */ + case RDMA_CM_EVENT_DISCONNECTED: /* FALLTHRU */ + case RDMA_CM_EVENT_DEVICE_REMOVAL: /* FALLTHRU */ +- disconnect = true; + case RDMA_CM_EVENT_TIMEWAIT_EXIT: /* FALLTHRU */ +- isert_disconnected_handler(cma_id, disconnect); ++ ret = isert_disconnected_handler(cma_id, event->event); + break; ++ case RDMA_CM_EVENT_REJECTED: /* FALLTHRU */ ++ case RDMA_CM_EVENT_UNREACHABLE: /* FALLTHRU */ + case RDMA_CM_EVENT_CONNECT_ERROR: ++ ret = isert_connect_error(cma_id); ++ break; + default: + pr_err("Unhandled RDMA CMA event: %d\n", event->event); + break; + } + +- if (ret != 0) { +- pr_err("isert_cma_handler failed RDMA_CM_EVENT: 0x%08x %d\n", +- event->event, ret); +- dump_stack(); +- } +- + return ret; + } + +@@ -891,7 +1006,7 @@ isert_init_send_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, + * bit for every ISERT_COMP_BATCH_COUNT number of ib_post_send() calls. + */ + mutex_lock(&isert_conn->conn_mutex); +- if (coalesce && isert_conn->state == ISER_CONN_UP && ++ if (coalesce && isert_conn->state == ISER_CONN_FULL_FEATURE && + ++isert_conn->conn_comp_batch < ISERT_COMP_BATCH_COUNT) { + tx_desc->llnode_active = true; + llist_add(&tx_desc->comp_llnode, &isert_conn->conn_comp_llist); +@@ -970,7 +1085,8 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login, + } + if (!login->login_failed) { + if (login->login_complete) { +- if (isert_conn->conn_device->use_fastreg) { ++ if (!conn->sess->sess_ops->SessionType && ++ isert_conn->conn_device->use_fastreg) { + ret = isert_conn_create_fastreg_pool(isert_conn); + if (ret) { + pr_err("Conn: %p failed to create" +@@ -987,7 +1103,10 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login, + if (ret) + return ret; + +- isert_conn->state = ISER_CONN_UP; ++ /* Now we are in FULL_FEATURE phase */ ++ mutex_lock(&isert_conn->conn_mutex); ++ isert_conn->state = ISER_CONN_FULL_FEATURE; ++ mutex_unlock(&isert_conn->conn_mutex); + goto post_send; + } + +@@ -1004,18 +1123,17 @@ post_send: + } + + static void +-isert_rx_login_req(struct iser_rx_desc *rx_desc, int rx_buflen, +- struct isert_conn *isert_conn) ++isert_rx_login_req(struct isert_conn *isert_conn) + { ++ struct iser_rx_desc *rx_desc = (void *)isert_conn->login_req_buf; ++ int rx_buflen = isert_conn->login_req_len; + struct iscsi_conn *conn = isert_conn->conn; + struct iscsi_login *login = conn->conn_login; + int size; + +- if (!login) { +- pr_err("conn->conn_login is NULL\n"); +- dump_stack(); +- return; +- } ++ pr_info("conn %p\n", isert_conn); ++ ++ WARN_ON_ONCE(!login); + + if (login->first_request) { + struct iscsi_login_req *login_req = +@@ -1378,11 +1496,20 @@ isert_rx_completion(struct iser_rx_desc *desc, struct isert_conn *isert_conn, + hdr->opcode, hdr->itt, hdr->flags, + (int)(xfer_len - ISER_HEADERS_LEN)); + +- if ((char *)desc == isert_conn->login_req_buf) +- isert_rx_login_req(desc, xfer_len - ISER_HEADERS_LEN, +- isert_conn); +- else ++ if ((char *)desc == isert_conn->login_req_buf) { ++ isert_conn->login_req_len = xfer_len - ISER_HEADERS_LEN; ++ if (isert_conn->conn) { ++ struct iscsi_login *login = isert_conn->conn->conn_login; ++ ++ if (login && !login->first_request) ++ isert_rx_login_req(isert_conn); ++ } ++ mutex_lock(&isert_conn->conn_mutex); ++ complete(&isert_conn->login_req_comp); ++ mutex_unlock(&isert_conn->conn_mutex); ++ } else { + isert_rx_do_work(desc, isert_conn); ++ } + + ib_dma_sync_single_for_device(ib_dev, rx_dma, rx_buflen, + DMA_FROM_DEVICE); +@@ -1783,7 +1910,7 @@ isert_cq_rx_comp_err(struct isert_conn *isert_conn) + msleep(3000); + + mutex_lock(&isert_conn->conn_mutex); +- isert_conn->state = ISER_CONN_DOWN; ++ isert_conn_terminate(isert_conn); + mutex_unlock(&isert_conn->conn_mutex); + + iscsit_cause_connection_reinstatement(isert_conn->conn, 0); +@@ -1937,7 +2064,7 @@ isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd) + isert_cmd->tx_desc.num_sge = 2; + } + +- isert_init_send_wr(isert_conn, isert_cmd, send_wr, true); ++ isert_init_send_wr(isert_conn, isert_cmd, send_wr, false); + + pr_debug("Posting SCSI Response IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n"); + +@@ -2456,7 +2583,7 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd) + &isert_cmd->tx_desc.iscsi_header); + isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); + isert_init_send_wr(isert_conn, isert_cmd, +- &isert_cmd->tx_desc.send_wr, true); ++ &isert_cmd->tx_desc.send_wr, false); + + atomic_add(wr->send_wr_num + 1, &isert_conn->post_send_buf_count); + +@@ -2563,13 +2690,51 @@ isert_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state) + return ret; + } + ++struct rdma_cm_id * ++isert_setup_id(struct isert_np *isert_np) ++{ ++ struct iscsi_np *np = isert_np->np; ++ struct rdma_cm_id *id; ++ struct sockaddr *sa; ++ int ret; ++ ++ sa = (struct sockaddr *)&np->np_sockaddr; ++ pr_debug("ksockaddr: %p, sa: %p\n", &np->np_sockaddr, sa); ++ ++ id = rdma_create_id(isert_cma_handler, isert_np, ++ RDMA_PS_TCP, IB_QPT_RC); ++ if (IS_ERR(id)) { ++ pr_err("rdma_create_id() failed: %ld\n", PTR_ERR(id)); ++ ret = PTR_ERR(id); ++ goto out; ++ } ++ pr_debug("id %p context %p\n", id, id->context); ++ ++ ret = rdma_bind_addr(id, sa); ++ if (ret) { ++ pr_err("rdma_bind_addr() failed: %d\n", ret); ++ goto out_id; ++ } ++ ++ ret = rdma_listen(id, ISERT_RDMA_LISTEN_BACKLOG); ++ if (ret) { ++ pr_err("rdma_listen() failed: %d\n", ret); ++ goto out_id; ++ } ++ ++ return id; ++out_id: ++ rdma_destroy_id(id); ++out: ++ return ERR_PTR(ret); ++} ++ + static int + isert_setup_np(struct iscsi_np *np, + struct __kernel_sockaddr_storage *ksockaddr) + { + struct isert_np *isert_np; + struct rdma_cm_id *isert_lid; +- struct sockaddr *sa; + int ret; + + isert_np = kzalloc(sizeof(struct isert_np), GFP_KERNEL); +@@ -2581,9 +2746,8 @@ isert_setup_np(struct iscsi_np *np, + mutex_init(&isert_np->np_accept_mutex); + INIT_LIST_HEAD(&isert_np->np_accept_list); + init_completion(&isert_np->np_login_comp); ++ isert_np->np = np; + +- sa = (struct sockaddr *)ksockaddr; +- pr_debug("ksockaddr: %p, sa: %p\n", ksockaddr, sa); + /* + * Setup the np->np_sockaddr from the passed sockaddr setup + * in iscsi_target_configfs.c code.. +@@ -2591,37 +2755,20 @@ isert_setup_np(struct iscsi_np *np, + memcpy(&np->np_sockaddr, ksockaddr, + sizeof(struct __kernel_sockaddr_storage)); + +- isert_lid = rdma_create_id(isert_cma_handler, np, RDMA_PS_TCP, +- IB_QPT_RC); ++ isert_lid = isert_setup_id(isert_np); + if (IS_ERR(isert_lid)) { +- pr_err("rdma_create_id() for isert_listen_handler failed: %ld\n", +- PTR_ERR(isert_lid)); + ret = PTR_ERR(isert_lid); + goto out; + } + +- ret = rdma_bind_addr(isert_lid, sa); +- if (ret) { +- pr_err("rdma_bind_addr() for isert_lid failed: %d\n", ret); +- goto out_lid; +- } +- +- ret = rdma_listen(isert_lid, ISERT_RDMA_LISTEN_BACKLOG); +- if (ret) { +- pr_err("rdma_listen() for isert_lid failed: %d\n", ret); +- goto out_lid; +- } +- + isert_np->np_cm_id = isert_lid; + np->np_context = isert_np; +- pr_debug("Setup isert_lid->context: %p\n", isert_lid->context); + + return 0; + +-out_lid: +- rdma_destroy_id(isert_lid); + out: + kfree(isert_np); ++ + return ret; + } + +@@ -2657,7 +2804,15 @@ isert_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login) + struct isert_conn *isert_conn = (struct isert_conn *)conn->context; + int ret; + +- pr_debug("isert_get_login_rx before conn_login_comp conn: %p\n", conn); ++ pr_info("before login_req comp conn: %p\n", isert_conn); ++ ret = wait_for_completion_interruptible(&isert_conn->login_req_comp); ++ if (ret) { ++ pr_err("isert_conn %p interrupted before got login req\n", ++ isert_conn); ++ return ret; ++ } ++ reinit_completion(&isert_conn->login_req_comp); ++ + /* + * For login requests after the first PDU, isert_rx_login_req() will + * kick schedule_delayed_work(&conn->login_work) as the packet is +@@ -2667,11 +2822,15 @@ isert_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login) + if (!login->first_request) + return 0; + ++ isert_rx_login_req(isert_conn); ++ ++ pr_info("before conn_login_comp conn: %p\n", conn); + ret = wait_for_completion_interruptible(&isert_conn->conn_login_comp); + if (ret) + return ret; + +- pr_debug("isert_get_login_rx processing login->req: %p\n", login->req); ++ pr_info("processing login->req: %p\n", login->req); ++ + return 0; + } + +@@ -2749,17 +2908,10 @@ accept_wait: + isert_conn->conn = conn; + max_accept = 0; + +- ret = isert_rdma_post_recvl(isert_conn); +- if (ret) +- return ret; +- +- ret = isert_rdma_accept(isert_conn); +- if (ret) +- return ret; +- + isert_set_conn_info(np, conn, isert_conn); + +- pr_debug("Processing isert_accept_np: isert_conn: %p\n", isert_conn); ++ pr_debug("Processing isert_conn: %p\n", isert_conn); ++ + return 0; + } + +@@ -2768,12 +2920,31 @@ isert_free_np(struct iscsi_np *np) + { + struct isert_np *isert_np = (struct isert_np *)np->np_context; + +- rdma_destroy_id(isert_np->np_cm_id); ++ if (isert_np->np_cm_id) ++ rdma_destroy_id(isert_np->np_cm_id); + + np->np_context = NULL; + kfree(isert_np); + } + ++static void isert_release_work(struct work_struct *work) ++{ ++ struct isert_conn *isert_conn = container_of(work, ++ struct isert_conn, ++ release_work); ++ ++ pr_info("Starting release conn %p\n", isert_conn); ++ ++ wait_for_completion(&isert_conn->conn_wait); ++ ++ mutex_lock(&isert_conn->conn_mutex); ++ isert_conn->state = ISER_CONN_DOWN; ++ mutex_unlock(&isert_conn->conn_mutex); ++ ++ pr_info("Destroying conn %p\n", isert_conn); ++ isert_put_conn(isert_conn); ++} ++ + static void isert_wait_conn(struct iscsi_conn *conn) + { + struct isert_conn *isert_conn = conn->context; +@@ -2781,10 +2952,6 @@ static void isert_wait_conn(struct iscsi_conn *conn) + pr_debug("isert_wait_conn: Starting \n"); + + mutex_lock(&isert_conn->conn_mutex); +- if (isert_conn->conn_cm_id) { +- pr_debug("Calling rdma_disconnect from isert_wait_conn\n"); +- rdma_disconnect(isert_conn->conn_cm_id); +- } + /* + * Only wait for conn_wait_comp_err if the isert_conn made it + * into full feature phase.. +@@ -2793,13 +2960,12 @@ static void isert_wait_conn(struct iscsi_conn *conn) + mutex_unlock(&isert_conn->conn_mutex); + return; + } +- if (isert_conn->state == ISER_CONN_UP) +- isert_conn->state = ISER_CONN_TERMINATING; ++ isert_conn_terminate(isert_conn); + mutex_unlock(&isert_conn->conn_mutex); + + wait_for_completion(&isert_conn->conn_wait_comp_err); + +- wait_for_completion(&isert_conn->conn_wait); ++ queue_work(isert_release_wq, &isert_conn->release_work); + } + + static void isert_free_conn(struct iscsi_conn *conn) +@@ -2845,10 +3011,21 @@ static int __init isert_init(void) + goto destroy_rx_wq; + } + ++ isert_release_wq = alloc_workqueue("isert_release_wq", WQ_UNBOUND, ++ WQ_UNBOUND_MAX_ACTIVE); ++ if (!isert_release_wq) { ++ pr_err("Unable to allocate isert_release_wq\n"); ++ ret = -ENOMEM; ++ goto destroy_comp_wq; ++ } ++ + iscsit_register_transport(&iser_target_transport); +- pr_debug("iSER_TARGET[0] - Loaded iser_target_transport\n"); ++ pr_info("iSER_TARGET[0] - Loaded iser_target_transport\n"); ++ + return 0; + ++destroy_comp_wq: ++ destroy_workqueue(isert_comp_wq); + destroy_rx_wq: + destroy_workqueue(isert_rx_wq); + return ret; +@@ -2857,6 +3034,7 @@ destroy_rx_wq: + static void __exit isert_exit(void) + { + flush_scheduled_work(); ++ destroy_workqueue(isert_release_wq); + destroy_workqueue(isert_comp_wq); + destroy_workqueue(isert_rx_wq); + iscsit_unregister_transport(&iser_target_transport); +diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h +index cbecaab..1178c5b 100644 +--- a/drivers/infiniband/ulp/isert/ib_isert.h ++++ b/drivers/infiniband/ulp/isert/ib_isert.h +@@ -23,6 +23,7 @@ enum iser_ib_op_code { + enum iser_conn_state { + ISER_CONN_INIT, + ISER_CONN_UP, ++ ISER_CONN_FULL_FEATURE, + ISER_CONN_TERMINATING, + ISER_CONN_DOWN, + }; +@@ -102,6 +103,7 @@ struct isert_conn { + char *login_req_buf; + char *login_rsp_buf; + u64 login_req_dma; ++ int login_req_len; + u64 login_rsp_dma; + unsigned int conn_rx_desc_head; + struct iser_rx_desc *conn_rx_descs; +@@ -109,13 +111,13 @@ struct isert_conn { + struct iscsi_conn *conn; + struct list_head conn_accept_node; + struct completion conn_login_comp; ++ struct completion login_req_comp; + struct iser_tx_desc conn_login_tx_desc; + struct rdma_cm_id *conn_cm_id; + struct ib_pd *conn_pd; + struct ib_mr *conn_mr; + struct ib_qp *conn_qp; + struct isert_device *conn_device; +- struct work_struct conn_logout_work; + struct mutex conn_mutex; + struct completion conn_wait; + struct completion conn_wait_comp_err; +@@ -124,10 +126,10 @@ struct isert_conn { + int conn_fr_pool_size; + /* lock to protect fastreg pool */ + spinlock_t conn_lock; ++ struct work_struct release_work; + #define ISERT_COMP_BATCH_COUNT 8 + int conn_comp_batch; + struct llist_head conn_comp_llist; +- bool disconnect; + }; + + #define ISERT_MAX_CQ 64 +@@ -158,6 +160,7 @@ struct isert_device { + }; + + struct isert_np { ++ struct iscsi_np *np; + struct semaphore np_sem; + struct rdma_cm_id *np_cm_id; + struct mutex np_accept_mutex; +diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c +index e96c07e..ca0bc6c 100644 +--- a/drivers/infiniband/ulp/srp/ib_srp.c ++++ b/drivers/infiniband/ulp/srp/ib_srp.c +@@ -120,6 +120,7 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr); + static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event); + + static struct scsi_transport_template *ib_srp_transport_template; ++static struct workqueue_struct *srp_remove_wq; + + static struct ib_client srp_client = { + .name = "srp", +@@ -539,7 +540,7 @@ static bool srp_queue_remove_work(struct srp_target_port *target) + spin_unlock_irq(&target->lock); + + if (changed) +- queue_work(system_long_wq, &target->remove_work); ++ queue_work(srp_remove_wq, &target->remove_work); + + return changed; + } +@@ -2886,9 +2887,10 @@ static void srp_remove_one(struct ib_device *device) + spin_unlock(&host->target_lock); + + /* +- * Wait for target port removal tasks. ++ * Wait for tl_err and target port removal tasks. + */ + flush_workqueue(system_long_wq); ++ flush_workqueue(srp_remove_wq); + + kfree(host); + } +@@ -2940,16 +2942,22 @@ static int __init srp_init_module(void) + indirect_sg_entries = cmd_sg_entries; + } + ++ srp_remove_wq = create_workqueue("srp_remove"); ++ if (IS_ERR(srp_remove_wq)) { ++ ret = PTR_ERR(srp_remove_wq); ++ goto out; ++ } ++ ++ ret = -ENOMEM; + ib_srp_transport_template = + srp_attach_transport(&ib_srp_transport_functions); + if (!ib_srp_transport_template) +- return -ENOMEM; ++ goto destroy_wq; + + ret = class_register(&srp_class); + if (ret) { + pr_err("couldn't register class infiniband_srp\n"); +- srp_release_transport(ib_srp_transport_template); +- return ret; ++ goto release_tr; + } + + ib_sa_register_client(&srp_sa_client); +@@ -2957,13 +2965,22 @@ static int __init srp_init_module(void) + ret = ib_register_client(&srp_client); + if (ret) { + pr_err("couldn't register IB client\n"); +- srp_release_transport(ib_srp_transport_template); +- ib_sa_unregister_client(&srp_sa_client); +- class_unregister(&srp_class); +- return ret; ++ goto unreg_sa; + } + +- return 0; ++out: ++ return ret; ++ ++unreg_sa: ++ ib_sa_unregister_client(&srp_sa_client); ++ class_unregister(&srp_class); ++ ++release_tr: ++ srp_release_transport(ib_srp_transport_template); ++ ++destroy_wq: ++ destroy_workqueue(srp_remove_wq); ++ goto out; + } + + static void __exit srp_cleanup_module(void) +@@ -2972,6 +2989,7 @@ static void __exit srp_cleanup_module(void) + ib_sa_unregister_client(&srp_sa_client); + class_unregister(&srp_class); + srp_release_transport(ib_srp_transport_template); ++ destroy_workqueue(srp_remove_wq); + } + + module_init(srp_init_module); +diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c +index d1078ce..0097b8d 100644 +--- a/drivers/infiniband/ulp/srpt/ib_srpt.c ++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c +@@ -2091,6 +2091,7 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch) + if (!qp_init) + goto out; + ++retry: + ch->cq = ib_create_cq(sdev->device, srpt_completion, NULL, ch, + ch->rq_size + srp_sq_size, 0); + if (IS_ERR(ch->cq)) { +@@ -2114,6 +2115,13 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch) + ch->qp = ib_create_qp(sdev->pd, qp_init); + if (IS_ERR(ch->qp)) { + ret = PTR_ERR(ch->qp); ++ if (ret == -ENOMEM) { ++ srp_sq_size /= 2; ++ if (srp_sq_size >= MIN_SRPT_SQ_SIZE) { ++ ib_destroy_cq(ch->cq); ++ goto retry; ++ } ++ } + printk(KERN_ERR "failed to create_qp ret= %d\n", ret); + goto err_destroy_cq; + } +diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c +index ce953d8..fb787c3 100644 +--- a/drivers/input/evdev.c ++++ b/drivers/input/evdev.c +@@ -757,20 +757,23 @@ static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) + */ + static int evdev_handle_get_val(struct evdev_client *client, + struct input_dev *dev, unsigned int type, +- unsigned long *bits, unsigned int max, +- unsigned int size, void __user *p, int compat) ++ unsigned long *bits, unsigned int maxbit, ++ unsigned int maxlen, void __user *p, ++ int compat) + { + int ret; + unsigned long *mem; ++ size_t len; + +- mem = kmalloc(sizeof(unsigned long) * max, GFP_KERNEL); ++ len = BITS_TO_LONGS(maxbit) * sizeof(unsigned long); ++ mem = kmalloc(len, GFP_KERNEL); + if (!mem) + return -ENOMEM; + + spin_lock_irq(&dev->event_lock); + spin_lock(&client->buffer_lock); + +- memcpy(mem, bits, sizeof(unsigned long) * max); ++ memcpy(mem, bits, len); + + spin_unlock(&dev->event_lock); + +@@ -778,7 +781,7 @@ static int evdev_handle_get_val(struct evdev_client *client, + + spin_unlock_irq(&client->buffer_lock); + +- ret = bits_to_user(mem, max, size, p, compat); ++ ret = bits_to_user(mem, maxbit, maxlen, p, compat); + if (ret < 0) + evdev_queue_syn_dropped(client); + +diff --git a/drivers/input/input.c b/drivers/input/input.c +index 1c4c0db..29ca0bb 100644 +--- a/drivers/input/input.c ++++ b/drivers/input/input.c +@@ -257,9 +257,10 @@ static int input_handle_abs_event(struct input_dev *dev, + } + + static int input_get_disposition(struct input_dev *dev, +- unsigned int type, unsigned int code, int value) ++ unsigned int type, unsigned int code, int *pval) + { + int disposition = INPUT_IGNORE_EVENT; ++ int value = *pval; + + switch (type) { + +@@ -357,6 +358,7 @@ static int input_get_disposition(struct input_dev *dev, + break; + } + ++ *pval = value; + return disposition; + } + +@@ -365,7 +367,7 @@ static void input_handle_event(struct input_dev *dev, + { + int disposition; + +- disposition = input_get_disposition(dev, type, code, value); ++ disposition = input_get_disposition(dev, type, code, &value); + + if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event) + dev->event(dev, type, code, value); +diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c +index 603fe0d..517829f 100644 +--- a/drivers/input/joystick/xpad.c ++++ b/drivers/input/joystick/xpad.c +@@ -1003,9 +1003,19 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id + } + + ep_irq_in = &intf->cur_altsetting->endpoint[1].desc; +- usb_fill_bulk_urb(xpad->bulk_out, udev, +- usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress), +- xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad); ++ if (usb_endpoint_is_bulk_out(ep_irq_in)) { ++ usb_fill_bulk_urb(xpad->bulk_out, udev, ++ usb_sndbulkpipe(udev, ++ ep_irq_in->bEndpointAddress), ++ xpad->bdata, XPAD_PKT_LEN, ++ xpad_bulk_out, xpad); ++ } else { ++ usb_fill_int_urb(xpad->bulk_out, udev, ++ usb_sndintpipe(udev, ++ ep_irq_in->bEndpointAddress), ++ xpad->bdata, XPAD_PKT_LEN, ++ xpad_bulk_out, xpad, 0); ++ } + + /* + * Submit the int URB immediately rather than waiting for open +diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c +index 2dd1d0d..6f5d795 100644 +--- a/drivers/input/keyboard/atkbd.c ++++ b/drivers/input/keyboard/atkbd.c +@@ -1791,14 +1791,6 @@ static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), +- DMI_MATCH(DMI_PRODUCT_NAME, "LW25-B7HV"), +- }, +- .callback = atkbd_deactivate_fixup, +- }, +- { +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), +- DMI_MATCH(DMI_PRODUCT_NAME, "P1-J273B"), + }, + .callback = atkbd_deactivate_fixup, + }, +diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c +index fb15c64..4979b00 100644 +--- a/drivers/input/mouse/alps.c ++++ b/drivers/input/mouse/alps.c +@@ -1047,7 +1047,13 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + { + struct alps_data *priv = psmouse->private; + +- if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ ++ /* ++ * Check if we are dealing with a bare PS/2 packet, presumably from ++ * a device connected to the external PS/2 port. Because bare PS/2 ++ * protocol does not have enough constant bits to self-synchronize ++ * properly we only do this if the device is fully synchronized. ++ */ ++ if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) { + if (psmouse->pktcnt == 3) { + alps_report_bare_ps2_packet(psmouse, psmouse->packet, + true); +@@ -1071,12 +1077,27 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) + } + + /* Bytes 2 - pktsize should have 0 in the highest bit */ +- if ((priv->proto_version < ALPS_PROTO_V5) && ++ if (priv->proto_version < ALPS_PROTO_V5 && + psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && + (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { + psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", + psmouse->pktcnt - 1, + psmouse->packet[psmouse->pktcnt - 1]); ++ ++ if (priv->proto_version == ALPS_PROTO_V3 && ++ psmouse->pktcnt == psmouse->pktsize) { ++ /* ++ * Some Dell boxes, such as Latitude E6440 or E7440 ++ * with closed lid, quite often smash last byte of ++ * otherwise valid packet with 0xff. Given that the ++ * next packet is very likely to be valid let's ++ * report PSMOUSE_FULL_PACKET but not process data, ++ * rather than reporting PSMOUSE_BAD_DATA and ++ * filling the logs. ++ */ ++ return PSMOUSE_FULL_PACKET; ++ } ++ + return PSMOUSE_BAD_DATA; + } + +@@ -2148,6 +2169,9 @@ int alps_init(struct psmouse *psmouse) + /* We are having trouble resyncing ALPS touchpads so disable it for now */ + psmouse->resync_time = 0; + ++ /* Allow 2 invalid packets without resetting device */ ++ psmouse->resetafter = psmouse->pktsize * 2; ++ + return 0; + + init_fail: +diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c +index 233516a..94eaaf0 100644 +--- a/drivers/input/mouse/elantech.c ++++ b/drivers/input/mouse/elantech.c +@@ -314,7 +314,7 @@ static void elantech_report_semi_mt_data(struct input_dev *dev, + unsigned int x2, unsigned int y2) + { + elantech_set_slot(dev, 0, num_fingers != 0, x1, y1); +- elantech_set_slot(dev, 1, num_fingers == 2, x2, y2); ++ elantech_set_slot(dev, 1, num_fingers >= 2, x2, y2); + } + + /* +@@ -814,6 +814,21 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) + } + + /* ++ * This writes the reg_07 value again to the hardware at the end of every ++ * set_rate call because the register loses its value. reg_07 allows setting ++ * absolute mode on v4 hardware ++ */ ++static void elantech_set_rate_restore_reg_07(struct psmouse *psmouse, ++ unsigned int rate) ++{ ++ struct elantech_data *etd = psmouse->private; ++ ++ etd->original_set_rate(psmouse, rate); ++ if (elantech_write_reg(psmouse, 0x07, etd->reg_07)) ++ psmouse_err(psmouse, "restoring reg_07 failed\n"); ++} ++ ++/* + * Put the touchpad into absolute mode + */ + static int elantech_set_absolute_mode(struct psmouse *psmouse) +@@ -1015,6 +1030,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse, + * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons + * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons + * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons ++ * Asus TP500LN 0x381f17 10, 14, 0e clickpad ++ * Asus X750JN 0x381f17 10, 14, 0e clickpad + * Asus UX31 0x361f00 20, 15, 0e clickpad + * Asus UX32VD 0x361f02 00, 15, 0e clickpad + * Avatar AVIU-145A2 0x361f00 ? clickpad +@@ -1253,6 +1270,14 @@ static bool elantech_is_signature_valid(const unsigned char *param) + if (param[1] == 0) + return true; + ++ /* ++ * Some hw_version >= 4 models have a revision higher then 20. Meaning ++ * that param[2] may be 10 or 20, skip the rates check for these. ++ */ ++ if ((param[0] & 0x0f) >= 0x06 && (param[1] & 0xaf) == 0x0f && ++ param[2] < 40) ++ return true; ++ + for (i = 0; i < ARRAY_SIZE(rates); i++) + if (param[2] == rates[i]) + return false; +@@ -1483,6 +1508,11 @@ int elantech_init(struct psmouse *psmouse) + goto init_fail; + } + ++ if (etd->fw_version == 0x381f17) { ++ etd->original_set_rate = psmouse->set_rate; ++ psmouse->set_rate = elantech_set_rate_restore_reg_07; ++ } ++ + if (elantech_set_input_params(psmouse)) { + psmouse_err(psmouse, "failed to query touchpad range.\n"); + goto init_fail; +diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h +index 9e0e2a1..59263a3 100644 +--- a/drivers/input/mouse/elantech.h ++++ b/drivers/input/mouse/elantech.h +@@ -139,6 +139,7 @@ struct elantech_data { + struct finger_pos mt[ETP_MAX_FINGERS]; + unsigned char parity[256]; + int (*send_cmd)(struct psmouse *psmouse, unsigned char c, unsigned char *param); ++ void (*original_set_rate)(struct psmouse *psmouse, unsigned int rate); + }; + + #ifdef CONFIG_MOUSE_PS2_ELANTECH +diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c +index ec772d9..53f09a8 100644 +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -132,13 +132,23 @@ static const struct min_max_quirk min_max_pnpid_table[] = { + 1232, 5710, 1156, 4696 + }, + { +- (const char * const []){"LEN0034", "LEN0036", "LEN2004", NULL}, ++ (const char * const []){"LEN0034", "LEN0036", "LEN0037", ++ "LEN0039", "LEN2002", "LEN2004", ++ NULL}, + 1024, 5112, 2024, 4832 + }, + { ++ (const char * const []){"LEN2000", NULL}, ++ 1024, 5113, 2021, 4832 ++ }, ++ { + (const char * const []){"LEN2001", NULL}, + 1024, 5022, 2508, 4832 + }, ++ { ++ (const char * const []){"LEN2006", NULL}, ++ 1264, 5675, 1171, 4688 ++ }, + { } + }; + +@@ -157,8 +167,9 @@ static const char * const topbuttonpad_pnp_ids[] = { + "LEN0034", /* T431s, L440, L540, T540, W540, X1 Carbon 2nd */ + "LEN0035", /* X240 */ + "LEN0036", /* T440 */ +- "LEN0037", ++ "LEN0037", /* X1 Carbon 2nd */ + "LEN0038", ++ "LEN0039", /* T440s */ + "LEN0041", + "LEN0042", /* Yoga */ + "LEN0045", +@@ -166,9 +177,9 @@ static const char * const topbuttonpad_pnp_ids[] = { + "LEN0047", + "LEN0048", + "LEN0049", +- "LEN2000", ++ "LEN2000", /* S540 */ + "LEN2001", /* Edge E431 */ +- "LEN2002", ++ "LEN2002", /* Edge E531 */ + "LEN2003", + "LEN2004", /* L440 */ + "LEN2005", +@@ -625,10 +636,61 @@ static int synaptics_parse_hw_state(const unsigned char buf[], + ((buf[0] & 0x04) >> 1) | + ((buf[3] & 0x04) >> 2)); + ++ if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || ++ SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) && ++ hw->w == 2) { ++ synaptics_parse_agm(buf, priv, hw); ++ return 1; ++ } ++ ++ hw->x = (((buf[3] & 0x10) << 8) | ++ ((buf[1] & 0x0f) << 8) | ++ buf[4]); ++ hw->y = (((buf[3] & 0x20) << 7) | ++ ((buf[1] & 0xf0) << 4) | ++ buf[5]); ++ hw->z = buf[2]; ++ + hw->left = (buf[0] & 0x01) ? 1 : 0; + hw->right = (buf[0] & 0x02) ? 1 : 0; + +- if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { ++ if (SYN_CAP_FORCEPAD(priv->ext_cap_0c)) { ++ /* ++ * ForcePads, like Clickpads, use middle button ++ * bits to report primary button clicks. ++ * Unfortunately they report primary button not ++ * only when user presses on the pad above certain ++ * threshold, but also when there are more than one ++ * finger on the touchpad, which interferes with ++ * out multi-finger gestures. ++ */ ++ if (hw->z == 0) { ++ /* No contacts */ ++ priv->press = priv->report_press = false; ++ } else if (hw->w >= 4 && ((buf[0] ^ buf[3]) & 0x01)) { ++ /* ++ * Single-finger touch with pressure above ++ * the threshold. If pressure stays long ++ * enough, we'll start reporting primary ++ * button. We rely on the device continuing ++ * sending data even if finger does not ++ * move. ++ */ ++ if (!priv->press) { ++ priv->press_start = jiffies; ++ priv->press = true; ++ } else if (time_after(jiffies, ++ priv->press_start + ++ msecs_to_jiffies(50))) { ++ priv->report_press = true; ++ } ++ } else { ++ priv->press = false; ++ } ++ ++ hw->left = priv->report_press; ++ ++ } else if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { + /* + * Clickpad's button is transmitted as middle button, + * however, since it is primary button, we will report +@@ -647,21 +709,6 @@ static int synaptics_parse_hw_state(const unsigned char buf[], + hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; + } + +- if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || +- SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) && +- hw->w == 2) { +- synaptics_parse_agm(buf, priv, hw); +- return 1; +- } +- +- hw->x = (((buf[3] & 0x10) << 8) | +- ((buf[1] & 0x0f) << 8) | +- buf[4]); +- hw->y = (((buf[3] & 0x20) << 7) | +- ((buf[1] & 0xf0) << 4) | +- buf[5]); +- hw->z = buf[2]; +- + if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && + ((buf[0] ^ buf[3]) & 0x02)) { + switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { +diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h +index e594af0..fb2e076 100644 +--- a/drivers/input/mouse/synaptics.h ++++ b/drivers/input/mouse/synaptics.h +@@ -78,6 +78,11 @@ + * 2 0x08 image sensor image sensor tracks 5 fingers, but only + * reports 2. + * 2 0x20 report min query 0x0f gives min coord reported ++ * 2 0x80 forcepad forcepad is a variant of clickpad that ++ * does not have physical buttons but rather ++ * uses pressure above certain threshold to ++ * report primary clicks. Forcepads also have ++ * clickpad bit set. + */ + #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ + #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ +@@ -86,6 +91,7 @@ + #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) + #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) + #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) ++#define SYN_CAP_FORCEPAD(ex0c) ((ex0c) & 0x008000) + + /* synaptics modes query bits */ + #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) +@@ -177,6 +183,11 @@ struct synaptics_data { + */ + struct synaptics_hw_state agm; + bool agm_pending; /* new AGM packet received */ ++ ++ /* ForcePad handling */ ++ unsigned long press_start; ++ bool press; ++ bool report_press; + }; + + void synaptics_module_init(void); +diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h +index 381b20d..dd6d14d 100644 +--- a/drivers/input/serio/i8042-x86ia64io.h ++++ b/drivers/input/serio/i8042-x86ia64io.h +@@ -101,6 +101,12 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { + }, + { + .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "X750LN"), ++ }, ++ }, ++ { ++ .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), + DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"), + DMI_MATCH(DMI_PRODUCT_VERSION, "8500"), +@@ -146,6 +152,14 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { + }, + }, + { ++ /* Medion Akoya E7225 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Medion"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Akoya E7225"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"), ++ }, ++ }, ++ { + /* Blue FB5601 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "blue"), +@@ -402,6 +416,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { + }, + }, + { ++ /* Acer Aspire 7738 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Acer"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7738"), ++ }, ++ }, ++ { + /* Gericom Bellagio */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Gericom"), +@@ -458,6 +479,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"), + }, + }, ++ { ++ /* Avatar AVIU-145A6 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Intel"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "IC4I"), ++ }, ++ }, + { } + }; + +@@ -601,6 +629,30 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"), + }, + }, ++ { ++ /* Fujitsu A544 laptop */ ++ /* https://bugzilla.redhat.com/show_bug.cgi?id=1111138 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK A544"), ++ }, ++ }, ++ { ++ /* Fujitsu AH544 laptop */ ++ /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK AH544"), ++ }, ++ }, ++ { ++ /* Fujitsu U574 laptop */ ++ /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"), ++ }, ++ }, + { } + }; + +@@ -684,6 +736,35 @@ static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = { + { } + }; + ++/* ++ * Some laptops need keyboard reset before probing for the trackpad to get ++ * it detected, initialised & finally work. ++ */ ++static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = { ++ { ++ /* Gigabyte P35 v2 - Elantech touchpad */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "P35V2"), ++ }, ++ }, ++ { ++ /* Aorus branded Gigabyte X3 Plus - Elantech touchpad */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "X3"), ++ }, ++ }, ++ { ++ /* Gigabyte P34 - Elantech touchpad */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "P34"), ++ }, ++ }, ++ { } ++}; ++ + #endif /* CONFIG_X86 */ + + #ifdef CONFIG_PNP +@@ -979,6 +1060,9 @@ static int __init i8042_platform_init(void) + if (dmi_check_system(i8042_dmi_dritek_table)) + i8042_dritek = true; + ++ if (dmi_check_system(i8042_dmi_kbdreset_table)) ++ i8042_kbdreset = true; ++ + /* + * A20 was already enabled during early kernel init. But some buggy + * BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to +diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c +index 3807c3e..eb796ff 100644 +--- a/drivers/input/serio/i8042.c ++++ b/drivers/input/serio/i8042.c +@@ -67,6 +67,10 @@ static bool i8042_notimeout; + module_param_named(notimeout, i8042_notimeout, bool, 0); + MODULE_PARM_DESC(notimeout, "Ignore timeouts signalled by i8042"); + ++static bool i8042_kbdreset; ++module_param_named(kbdreset, i8042_kbdreset, bool, 0); ++MODULE_PARM_DESC(kbdreset, "Reset device connected to KBD port"); ++ + #ifdef CONFIG_X86 + static bool i8042_dritek; + module_param_named(dritek, i8042_dritek, bool, 0); +@@ -790,6 +794,16 @@ static int __init i8042_check_aux(void) + return -1; + + /* ++ * Reset keyboard (needed on some laptops to successfully detect ++ * touchpad, e.g., some Gigabyte laptop models with Elantech ++ * touchpads). ++ */ ++ if (i8042_kbdreset) { ++ pr_warn("Attempting to reset device connected to KBD port\n"); ++ i8042_kbd_write(NULL, (unsigned char) 0xff); ++ } ++ ++/* + * Test AUX IRQ delivery to make sure BIOS did not grab the IRQ and + * used it for a PCI card or somethig else. + */ +diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c +index 0cb7ef5..69175b8 100644 +--- a/drivers/input/serio/serport.c ++++ b/drivers/input/serio/serport.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + MODULE_AUTHOR("Vojtech Pavlik "); + MODULE_DESCRIPTION("Input device TTY line discipline"); +@@ -198,28 +199,55 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u + return 0; + } + ++static void serport_set_type(struct tty_struct *tty, unsigned long type) ++{ ++ struct serport *serport = tty->disc_data; ++ ++ serport->id.proto = type & 0x000000ff; ++ serport->id.id = (type & 0x0000ff00) >> 8; ++ serport->id.extra = (type & 0x00ff0000) >> 16; ++} ++ + /* + * serport_ldisc_ioctl() allows to set the port protocol, and device ID + */ + +-static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg) ++static int serport_ldisc_ioctl(struct tty_struct *tty, struct file *file, ++ unsigned int cmd, unsigned long arg) + { +- struct serport *serport = (struct serport*) tty->disc_data; +- unsigned long type; +- + if (cmd == SPIOCSTYPE) { ++ unsigned long type; ++ + if (get_user(type, (unsigned long __user *) arg)) + return -EFAULT; + +- serport->id.proto = type & 0x000000ff; +- serport->id.id = (type & 0x0000ff00) >> 8; +- serport->id.extra = (type & 0x00ff0000) >> 16; ++ serport_set_type(tty, type); ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++#ifdef CONFIG_COMPAT ++#define COMPAT_SPIOCSTYPE _IOW('q', 0x01, compat_ulong_t) ++static long serport_ldisc_compat_ioctl(struct tty_struct *tty, ++ struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ if (cmd == COMPAT_SPIOCSTYPE) { ++ void __user *uarg = compat_ptr(arg); ++ compat_ulong_t compat_type; ++ ++ if (get_user(compat_type, (compat_ulong_t __user *)uarg)) ++ return -EFAULT; + ++ serport_set_type(tty, compat_type); + return 0; + } + + return -EINVAL; + } ++#endif + + static void serport_ldisc_write_wakeup(struct tty_struct * tty) + { +@@ -243,6 +271,9 @@ static struct tty_ldisc_ops serport_ldisc = { + .close = serport_ldisc_close, + .read = serport_ldisc_read, + .ioctl = serport_ldisc_ioctl, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = serport_ldisc_compat_ioctl, ++#endif + .receive_buf = serport_ldisc_receive, + .write_wakeup = serport_ldisc_write_wakeup + }; +diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c +index 05f371d..d4b0a31 100644 +--- a/drivers/input/tablet/wacom_wac.c ++++ b/drivers/input/tablet/wacom_wac.c +@@ -700,6 +700,12 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) + input_report_key(input, BTN_7, (data[4] & 0x40)); /* Left */ + input_report_key(input, BTN_8, (data[4] & 0x80)); /* Down */ + input_report_key(input, BTN_0, (data[3] & 0x01)); /* Center */ ++ ++ if (data[4] | (data[3] & 0x01)) { ++ input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); ++ } else { ++ input_report_abs(input, ABS_MISC, 0); ++ } + } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) { + int i; + +diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c +index a096633..c6f7e91 100644 +--- a/drivers/input/touchscreen/usbtouchscreen.c ++++ b/drivers/input/touchscreen/usbtouchscreen.c +@@ -625,6 +625,9 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) + goto err_out; + } + ++ /* TSC-25 data sheet specifies a delay after the RESET command */ ++ msleep(150); ++ + /* set coordinate output rate */ + buf[0] = buf[1] = 0xFF; + ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), +diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c +index 71776ff..9359740 100644 +--- a/drivers/iommu/amd_iommu.c ++++ b/drivers/iommu/amd_iommu.c +@@ -1922,9 +1922,15 @@ static void free_pt_##LVL (unsigned long __pt) \ + pt = (u64 *)__pt; \ + \ + for (i = 0; i < 512; ++i) { \ ++ /* PTE present? */ \ + if (!IOMMU_PTE_PRESENT(pt[i])) \ + continue; \ + \ ++ /* Large PTE? */ \ ++ if (PM_PTE_LEVEL(pt[i]) == 0 || \ ++ PM_PTE_LEVEL(pt[i]) == 7) \ ++ continue; \ ++ \ + p = (unsigned long)IOMMU_PTE_PAGE(pt[i]); \ + FN(p); \ + } \ +@@ -3227,14 +3233,16 @@ free_domains: + + static void cleanup_domain(struct protection_domain *domain) + { +- struct iommu_dev_data *dev_data, *next; ++ struct iommu_dev_data *entry; + unsigned long flags; + + write_lock_irqsave(&amd_iommu_devtable_lock, flags); + +- list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) { +- __detach_device(dev_data); +- atomic_set(&dev_data->bind, 0); ++ while (!list_empty(&domain->dev_list)) { ++ entry = list_first_entry(&domain->dev_list, ++ struct iommu_dev_data, list); ++ __detach_device(entry); ++ atomic_set(&entry->bind, 0); + } + + write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); +diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c +index 1d9ab39..2ecac46 100644 +--- a/drivers/iommu/arm-smmu.c ++++ b/drivers/iommu/arm-smmu.c +@@ -794,8 +794,11 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) + reg |= TTBCR_EAE | + (TTBCR_SH_IS << TTBCR_SH0_SHIFT) | + (TTBCR_RGN_WBWA << TTBCR_ORGN0_SHIFT) | +- (TTBCR_RGN_WBWA << TTBCR_IRGN0_SHIFT) | +- (TTBCR_SL0_LVL_1 << TTBCR_SL0_SHIFT); ++ (TTBCR_RGN_WBWA << TTBCR_IRGN0_SHIFT); ++ ++ if (!stage1) ++ reg |= (TTBCR_SL0_LVL_1 << TTBCR_SL0_SHIFT); ++ + writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR); + + /* MAIR0 (stage-1 only) */ +diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c +index 40f6b47..8855ecb 100644 +--- a/drivers/iommu/intel-iommu.c ++++ b/drivers/iommu/intel-iommu.c +@@ -1768,7 +1768,7 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, + struct dma_pte *first_pte = NULL, *pte = NULL; + phys_addr_t uninitialized_var(pteval); + int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; +- unsigned long sg_res; ++ unsigned long sg_res = 0; + unsigned int largepage_lvl = 0; + unsigned long lvl_pages = 0; + +@@ -1779,10 +1779,8 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, + + prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP; + +- if (sg) +- sg_res = 0; +- else { +- sg_res = nr_pages + 1; ++ if (!sg) { ++ sg_res = nr_pages; + pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot; + } + +diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c +index f37d63c..825545c 100644 +--- a/drivers/leds/led-class.c ++++ b/drivers/leds/led-class.c +@@ -178,6 +178,7 @@ void led_classdev_resume(struct led_classdev *led_cdev) + } + EXPORT_SYMBOL_GPL(led_classdev_resume); + ++#ifdef CONFIG_PM_SLEEP + static int led_suspend(struct device *dev) + { + struct led_classdev *led_cdev = dev_get_drvdata(dev); +@@ -197,11 +198,9 @@ static int led_resume(struct device *dev) + + return 0; + } ++#endif + +-static const struct dev_pm_ops leds_class_dev_pm_ops = { +- .suspend = led_suspend, +- .resume = led_resume, +-}; ++static SIMPLE_DEV_PM_OPS(leds_class_dev_pm_ops, led_suspend, led_resume); + + /** + * led_classdev_register - register a new object of led_classdev class. +diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c +index 0bf1e4e..19da222 100644 +--- a/drivers/lguest/core.c ++++ b/drivers/lguest/core.c +@@ -176,7 +176,7 @@ static void unmap_switcher(void) + bool lguest_address_ok(const struct lguest *lg, + unsigned long addr, unsigned long len) + { +- return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr); ++ return addr+len <= lg->pfn_limit * PAGE_SIZE && (addr+len >= addr); + } + + /* +diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c +index 5f9c2a6..fbcb622 100644 +--- a/drivers/md/bcache/btree.c ++++ b/drivers/md/bcache/btree.c +@@ -199,7 +199,7 @@ void bch_btree_node_read_done(struct btree *b) + struct bset *i = btree_bset_first(b); + struct btree_iter *iter; + +- iter = mempool_alloc(b->c->fill_iter, GFP_NOWAIT); ++ iter = mempool_alloc(b->c->fill_iter, GFP_NOIO); + iter->size = b->c->sb.bucket_size / b->c->sb.block_size; + iter->used = 0; + +diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c +index 4195a01..cc3dc0c 100644 +--- a/drivers/md/bitmap.c ++++ b/drivers/md/bitmap.c +@@ -564,6 +564,8 @@ static int bitmap_read_sb(struct bitmap *bitmap) + if (err) + return err; + ++ err = -EINVAL; ++ + sb = kmap_atomic(sb_page); + + chunksize = le32_to_cpu(sb->chunksize); +@@ -883,7 +885,6 @@ void bitmap_unplug(struct bitmap *bitmap) + { + unsigned long i; + int dirty, need_write; +- int wait = 0; + + if (!bitmap || !bitmap->storage.filemap || + test_bit(BITMAP_STALE, &bitmap->flags)) +@@ -901,16 +902,13 @@ void bitmap_unplug(struct bitmap *bitmap) + clear_page_attr(bitmap, i, BITMAP_PAGE_PENDING); + write_page(bitmap, bitmap->storage.filemap[i], 0); + } +- if (dirty) +- wait = 1; +- } +- if (wait) { /* if any writes were performed, we need to wait on them */ +- if (bitmap->storage.file) +- wait_event(bitmap->write_wait, +- atomic_read(&bitmap->pending_writes)==0); +- else +- md_super_wait(bitmap->mddev); + } ++ if (bitmap->storage.file) ++ wait_event(bitmap->write_wait, ++ atomic_read(&bitmap->pending_writes)==0); ++ else ++ md_super_wait(bitmap->mddev); ++ + if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags)) + bitmap_file_kick(bitmap); + } +diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c +index 66c5d13..03c872f 100644 +--- a/drivers/md/dm-bufio.c ++++ b/drivers/md/dm-bufio.c +@@ -465,6 +465,7 @@ static void __relink_lru(struct dm_buffer *b, int dirty) + c->n_buffers[dirty]++; + b->list_mode = dirty; + list_move(&b->lru_list, &c->lru[dirty]); ++ b->last_accessed = jiffies; + } + + /*---------------------------------------------------------------- +@@ -531,6 +532,19 @@ static void use_dmio(struct dm_buffer *b, int rw, sector_t block, + end_io(&b->bio, r); + } + ++static void inline_endio(struct bio *bio, int error) ++{ ++ bio_end_io_t *end_fn = bio->bi_private; ++ ++ /* ++ * Reset the bio to free any attached resources ++ * (e.g. bio integrity profiles). ++ */ ++ bio_reset(bio); ++ ++ end_fn(bio, error); ++} ++ + static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block, + bio_end_io_t *end_io) + { +@@ -542,7 +556,12 @@ static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block, + b->bio.bi_max_vecs = DM_BUFIO_INLINE_VECS; + b->bio.bi_iter.bi_sector = block << b->c->sectors_per_block_bits; + b->bio.bi_bdev = b->c->bdev; +- b->bio.bi_end_io = end_io; ++ b->bio.bi_end_io = inline_endio; ++ /* ++ * Use of .bi_private isn't a problem here because ++ * the dm_buffer's inline bio is local to bufio. ++ */ ++ b->bio.bi_private = end_io; + + /* + * We assume that if len >= PAGE_SIZE ptr is page-aligned. +@@ -1447,9 +1466,9 @@ static void drop_buffers(struct dm_bufio_client *c) + + /* + * Test if the buffer is unused and too old, and commit it. +- * At if noio is set, we must not do any I/O because we hold +- * dm_bufio_clients_lock and we would risk deadlock if the I/O gets rerouted to +- * different bufio client. ++ * And if GFP_NOFS is used, we must not do any I/O because we hold ++ * dm_bufio_clients_lock and we would risk deadlock if the I/O gets ++ * rerouted to different bufio client. + */ + static int __cleanup_old_buffer(struct dm_buffer *b, gfp_t gfp, + unsigned long max_jiffies) +@@ -1457,7 +1476,7 @@ static int __cleanup_old_buffer(struct dm_buffer *b, gfp_t gfp, + if (jiffies - b->last_accessed < max_jiffies) + return 0; + +- if (!(gfp & __GFP_IO)) { ++ if (!(gfp & __GFP_FS)) { + if (test_bit(B_READING, &b->state) || + test_bit(B_WRITING, &b->state) || + test_bit(B_DIRTY, &b->state)) +@@ -1485,9 +1504,9 @@ static long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan, + list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list) { + freed += __cleanup_old_buffer(b, gfp_mask, 0); + if (!--nr_to_scan) +- break; ++ return freed; ++ dm_bufio_cond_resched(); + } +- dm_bufio_cond_resched(); + } + return freed; + } +@@ -1499,7 +1518,7 @@ dm_bufio_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) + unsigned long freed; + + c = container_of(shrink, struct dm_bufio_client, shrinker); +- if (sc->gfp_mask & __GFP_IO) ++ if (sc->gfp_mask & __GFP_FS) + dm_bufio_lock(c); + else if (!dm_bufio_trylock(c)) + return SHRINK_STOP; +@@ -1516,7 +1535,7 @@ dm_bufio_shrink_count(struct shrinker *shrink, struct shrink_control *sc) + unsigned long count; + + c = container_of(shrink, struct dm_bufio_client, shrinker); +- if (sc->gfp_mask & __GFP_IO) ++ if (sc->gfp_mask & __GFP_FS) + dm_bufio_lock(c); + else if (!dm_bufio_trylock(c)) + return 0; +@@ -1541,7 +1560,7 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign + BUG_ON(block_size < 1 << SECTOR_SHIFT || + (block_size & (block_size - 1))); + +- c = kmalloc(sizeof(*c), GFP_KERNEL); ++ c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) { + r = -ENOMEM; + goto bad_client; +diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c +index a87d3fa..b950a80 100644 +--- a/drivers/md/dm-cache-metadata.c ++++ b/drivers/md/dm-cache-metadata.c +@@ -94,6 +94,9 @@ struct cache_disk_superblock { + } __packed; + + struct dm_cache_metadata { ++ atomic_t ref_count; ++ struct list_head list; ++ + struct block_device *bdev; + struct dm_block_manager *bm; + struct dm_space_map *metadata_sm; +@@ -669,10 +672,10 @@ static void unpack_value(__le64 value_le, dm_oblock_t *block, unsigned *flags) + + /*----------------------------------------------------------------*/ + +-struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, +- sector_t data_block_size, +- bool may_format_device, +- size_t policy_hint_size) ++static struct dm_cache_metadata *metadata_open(struct block_device *bdev, ++ sector_t data_block_size, ++ bool may_format_device, ++ size_t policy_hint_size) + { + int r; + struct dm_cache_metadata *cmd; +@@ -680,9 +683,10 @@ struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + DMERR("could not allocate metadata struct"); +- return NULL; ++ return ERR_PTR(-ENOMEM); + } + ++ atomic_set(&cmd->ref_count, 1); + init_rwsem(&cmd->root_lock); + cmd->bdev = bdev; + cmd->data_block_size = data_block_size; +@@ -705,10 +709,96 @@ struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, + return cmd; + } + ++/* ++ * We keep a little list of ref counted metadata objects to prevent two ++ * different target instances creating separate bufio instances. This is ++ * an issue if a table is reloaded before the suspend. ++ */ ++static DEFINE_MUTEX(table_lock); ++static LIST_HEAD(table); ++ ++static struct dm_cache_metadata *lookup(struct block_device *bdev) ++{ ++ struct dm_cache_metadata *cmd; ++ ++ list_for_each_entry(cmd, &table, list) ++ if (cmd->bdev == bdev) { ++ atomic_inc(&cmd->ref_count); ++ return cmd; ++ } ++ ++ return NULL; ++} ++ ++static struct dm_cache_metadata *lookup_or_open(struct block_device *bdev, ++ sector_t data_block_size, ++ bool may_format_device, ++ size_t policy_hint_size) ++{ ++ struct dm_cache_metadata *cmd, *cmd2; ++ ++ mutex_lock(&table_lock); ++ cmd = lookup(bdev); ++ mutex_unlock(&table_lock); ++ ++ if (cmd) ++ return cmd; ++ ++ cmd = metadata_open(bdev, data_block_size, may_format_device, policy_hint_size); ++ if (!IS_ERR(cmd)) { ++ mutex_lock(&table_lock); ++ cmd2 = lookup(bdev); ++ if (cmd2) { ++ mutex_unlock(&table_lock); ++ __destroy_persistent_data_objects(cmd); ++ kfree(cmd); ++ return cmd2; ++ } ++ list_add(&cmd->list, &table); ++ mutex_unlock(&table_lock); ++ } ++ ++ return cmd; ++} ++ ++static bool same_params(struct dm_cache_metadata *cmd, sector_t data_block_size) ++{ ++ if (cmd->data_block_size != data_block_size) { ++ DMERR("data_block_size (%llu) different from that in metadata (%llu)\n", ++ (unsigned long long) data_block_size, ++ (unsigned long long) cmd->data_block_size); ++ return false; ++ } ++ ++ return true; ++} ++ ++struct dm_cache_metadata *dm_cache_metadata_open(struct block_device *bdev, ++ sector_t data_block_size, ++ bool may_format_device, ++ size_t policy_hint_size) ++{ ++ struct dm_cache_metadata *cmd = lookup_or_open(bdev, data_block_size, ++ may_format_device, policy_hint_size); ++ ++ if (!IS_ERR(cmd) && !same_params(cmd, data_block_size)) { ++ dm_cache_metadata_close(cmd); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ return cmd; ++} ++ + void dm_cache_metadata_close(struct dm_cache_metadata *cmd) + { +- __destroy_persistent_data_objects(cmd); +- kfree(cmd); ++ if (atomic_dec_and_test(&cmd->ref_count)) { ++ mutex_lock(&table_lock); ++ list_del(&cmd->list); ++ mutex_unlock(&table_lock); ++ ++ __destroy_persistent_data_objects(cmd); ++ kfree(cmd); ++ } + } + + /* +diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c +index c0ad90d..c10dec0 100644 +--- a/drivers/md/dm-cache-target.c ++++ b/drivers/md/dm-cache-target.c +@@ -222,7 +222,13 @@ struct cache { + struct list_head need_commit_migrations; + sector_t migration_threshold; + wait_queue_head_t migration_wait; +- atomic_t nr_migrations; ++ atomic_t nr_allocated_migrations; ++ ++ /* ++ * The number of in flight migrations that are performing ++ * background io. eg, promotion, writeback. ++ */ ++ atomic_t nr_io_migrations; + + wait_queue_head_t quiescing_wait; + atomic_t quiescing; +@@ -231,7 +237,7 @@ struct cache { + /* + * cache_size entries, dirty if set + */ +- dm_cblock_t nr_dirty; ++ atomic_t nr_dirty; + unsigned long *dirty_bitset; + + /* +@@ -259,7 +265,6 @@ struct cache { + struct dm_deferred_set *all_io_ds; + + mempool_t *migration_pool; +- struct dm_cache_migration *next_migration; + + struct dm_cache_policy *policy; + unsigned policy_nr_args; +@@ -350,10 +355,31 @@ static void free_prison_cell(struct cache *cache, struct dm_bio_prison_cell *cel + dm_bio_prison_free_cell(cache->prison, cell); + } + ++static struct dm_cache_migration *alloc_migration(struct cache *cache) ++{ ++ struct dm_cache_migration *mg; ++ ++ mg = mempool_alloc(cache->migration_pool, GFP_NOWAIT); ++ if (mg) { ++ mg->cache = cache; ++ atomic_inc(&mg->cache->nr_allocated_migrations); ++ } ++ ++ return mg; ++} ++ ++static void free_migration(struct dm_cache_migration *mg) ++{ ++ if (atomic_dec_and_test(&mg->cache->nr_allocated_migrations)) ++ wake_up(&mg->cache->migration_wait); ++ ++ mempool_free(mg, mg->cache->migration_pool); ++} ++ + static int prealloc_data_structs(struct cache *cache, struct prealloc *p) + { + if (!p->mg) { +- p->mg = mempool_alloc(cache->migration_pool, GFP_NOWAIT); ++ p->mg = alloc_migration(cache); + if (!p->mg) + return -ENOMEM; + } +@@ -382,7 +408,7 @@ static void prealloc_free_structs(struct cache *cache, struct prealloc *p) + free_prison_cell(cache, p->cell1); + + if (p->mg) +- mempool_free(p->mg, cache->migration_pool); ++ free_migration(p->mg); + } + + static struct dm_cache_migration *prealloc_get_migration(struct prealloc *p) +@@ -493,7 +519,7 @@ static bool is_dirty(struct cache *cache, dm_cblock_t b) + static void set_dirty(struct cache *cache, dm_oblock_t oblock, dm_cblock_t cblock) + { + if (!test_and_set_bit(from_cblock(cblock), cache->dirty_bitset)) { +- cache->nr_dirty = to_cblock(from_cblock(cache->nr_dirty) + 1); ++ atomic_inc(&cache->nr_dirty); + policy_set_dirty(cache->policy, oblock); + } + } +@@ -502,8 +528,7 @@ static void clear_dirty(struct cache *cache, dm_oblock_t oblock, dm_cblock_t cbl + { + if (test_and_clear_bit(from_cblock(cblock), cache->dirty_bitset)) { + policy_clear_dirty(cache->policy, oblock); +- cache->nr_dirty = to_cblock(from_cblock(cache->nr_dirty) - 1); +- if (!from_cblock(cache->nr_dirty)) ++ if (atomic_dec_return(&cache->nr_dirty) == 0) + dm_table_event(cache->ti->table); + } + } +@@ -813,24 +838,14 @@ static void remap_to_origin_then_cache(struct cache *cache, struct bio *bio, + * Migration covers moving data from the origin device to the cache, or + * vice versa. + *--------------------------------------------------------------*/ +-static void free_migration(struct dm_cache_migration *mg) ++static void inc_io_migrations(struct cache *cache) + { +- mempool_free(mg, mg->cache->migration_pool); ++ atomic_inc(&cache->nr_io_migrations); + } + +-static void inc_nr_migrations(struct cache *cache) ++static void dec_io_migrations(struct cache *cache) + { +- atomic_inc(&cache->nr_migrations); +-} +- +-static void dec_nr_migrations(struct cache *cache) +-{ +- atomic_dec(&cache->nr_migrations); +- +- /* +- * Wake the worker in case we're suspending the target. +- */ +- wake_up(&cache->migration_wait); ++ atomic_dec(&cache->nr_io_migrations); + } + + static void __cell_defer(struct cache *cache, struct dm_bio_prison_cell *cell, +@@ -853,11 +868,10 @@ static void cell_defer(struct cache *cache, struct dm_bio_prison_cell *cell, + wake_worker(cache); + } + +-static void cleanup_migration(struct dm_cache_migration *mg) ++static void free_io_migration(struct dm_cache_migration *mg) + { +- struct cache *cache = mg->cache; ++ dec_io_migrations(mg->cache); + free_migration(mg); +- dec_nr_migrations(cache); + } + + static void migration_failure(struct dm_cache_migration *mg) +@@ -882,7 +896,7 @@ static void migration_failure(struct dm_cache_migration *mg) + cell_defer(cache, mg->new_ocell, true); + } + +- cleanup_migration(mg); ++ free_io_migration(mg); + } + + static void migration_success_pre_commit(struct dm_cache_migration *mg) +@@ -891,9 +905,9 @@ static void migration_success_pre_commit(struct dm_cache_migration *mg) + struct cache *cache = mg->cache; + + if (mg->writeback) { +- cell_defer(cache, mg->old_ocell, false); + clear_dirty(cache, mg->old_oblock, mg->cblock); +- cleanup_migration(mg); ++ cell_defer(cache, mg->old_ocell, false); ++ free_io_migration(mg); + return; + + } else if (mg->demote) { +@@ -903,14 +917,14 @@ static void migration_success_pre_commit(struct dm_cache_migration *mg) + mg->old_oblock); + if (mg->promote) + cell_defer(cache, mg->new_ocell, true); +- cleanup_migration(mg); ++ free_io_migration(mg); + return; + } + } else { + if (dm_cache_insert_mapping(cache->cmd, mg->cblock, mg->new_oblock)) { + DMWARN_LIMIT("promotion failed; couldn't update on disk metadata"); + policy_remove_mapping(cache->policy, mg->new_oblock); +- cleanup_migration(mg); ++ free_io_migration(mg); + return; + } + } +@@ -943,18 +957,22 @@ static void migration_success_post_commit(struct dm_cache_migration *mg) + } else { + if (mg->invalidate) + policy_remove_mapping(cache->policy, mg->old_oblock); +- cleanup_migration(mg); ++ free_io_migration(mg); + } + + } else { +- if (mg->requeue_holder) ++ if (mg->requeue_holder) { ++ clear_dirty(cache, mg->new_oblock, mg->cblock); + cell_defer(cache, mg->new_ocell, true); +- else { ++ } else { ++ /* ++ * The block was promoted via an overwrite, so it's dirty. ++ */ ++ set_dirty(cache, mg->new_oblock, mg->cblock); + bio_endio(mg->new_ocell->holder, 0); + cell_defer(cache, mg->new_ocell, false); + } +- clear_dirty(cache, mg->new_oblock, mg->cblock); +- cleanup_migration(mg); ++ free_io_migration(mg); + } + } + +@@ -1061,7 +1079,8 @@ static void issue_copy(struct dm_cache_migration *mg) + + avoid = is_discarded_oblock(cache, mg->new_oblock); + +- if (!avoid && bio_writes_complete_block(cache, bio)) { ++ if (writeback_mode(&cache->features) && ++ !avoid && bio_writes_complete_block(cache, bio)) { + issue_overwrite(mg, bio); + return; + } +@@ -1165,7 +1184,7 @@ static void promote(struct cache *cache, struct prealloc *structs, + mg->new_ocell = cell; + mg->start_jiffies = jiffies; + +- inc_nr_migrations(cache); ++ inc_io_migrations(cache); + quiesce_migration(mg); + } + +@@ -1188,7 +1207,7 @@ static void writeback(struct cache *cache, struct prealloc *structs, + mg->new_ocell = NULL; + mg->start_jiffies = jiffies; + +- inc_nr_migrations(cache); ++ inc_io_migrations(cache); + quiesce_migration(mg); + } + +@@ -1214,7 +1233,7 @@ static void demote_then_promote(struct cache *cache, struct prealloc *structs, + mg->new_ocell = new_ocell; + mg->start_jiffies = jiffies; + +- inc_nr_migrations(cache); ++ inc_io_migrations(cache); + quiesce_migration(mg); + } + +@@ -1241,7 +1260,7 @@ static void invalidate(struct cache *cache, struct prealloc *structs, + mg->new_ocell = NULL; + mg->start_jiffies = jiffies; + +- inc_nr_migrations(cache); ++ inc_io_migrations(cache); + quiesce_migration(mg); + } + +@@ -1302,7 +1321,7 @@ static void process_discard_bio(struct cache *cache, struct bio *bio) + + static bool spare_migration_bandwidth(struct cache *cache) + { +- sector_t current_volume = (atomic_read(&cache->nr_migrations) + 1) * ++ sector_t current_volume = (atomic_read(&cache->nr_io_migrations) + 1) * + cache->sectors_per_block; + return current_volume < cache->migration_threshold; + } +@@ -1657,7 +1676,7 @@ static void stop_quiescing(struct cache *cache) + + static void wait_for_migrations(struct cache *cache) + { +- wait_event(cache->migration_wait, !atomic_read(&cache->nr_migrations)); ++ wait_event(cache->migration_wait, !atomic_read(&cache->nr_allocated_migrations)); + } + + static void stop_worker(struct cache *cache) +@@ -1768,9 +1787,6 @@ static void destroy(struct cache *cache) + { + unsigned i; + +- if (cache->next_migration) +- mempool_free(cache->next_migration, cache->migration_pool); +- + if (cache->migration_pool) + mempool_destroy(cache->migration_pool); + +@@ -2278,7 +2294,8 @@ static int cache_create(struct cache_args *ca, struct cache **result) + INIT_LIST_HEAD(&cache->quiesced_migrations); + INIT_LIST_HEAD(&cache->completed_migrations); + INIT_LIST_HEAD(&cache->need_commit_migrations); +- atomic_set(&cache->nr_migrations, 0); ++ atomic_set(&cache->nr_allocated_migrations, 0); ++ atomic_set(&cache->nr_io_migrations, 0); + init_waitqueue_head(&cache->migration_wait); + + init_waitqueue_head(&cache->quiescing_wait); +@@ -2286,7 +2303,7 @@ static int cache_create(struct cache_args *ca, struct cache **result) + atomic_set(&cache->quiescing_ack, 0); + + r = -ENOMEM; +- cache->nr_dirty = 0; ++ atomic_set(&cache->nr_dirty, 0); + cache->dirty_bitset = alloc_bitset(from_cblock(cache->cache_size)); + if (!cache->dirty_bitset) { + *error = "could not allocate dirty bitset"; +@@ -2338,8 +2355,6 @@ static int cache_create(struct cache_args *ca, struct cache **result) + goto bad; + } + +- cache->next_migration = NULL; +- + cache->need_tick_bio = true; + cache->sized = false; + cache->invalidate = false; +@@ -2828,7 +2843,7 @@ static void cache_status(struct dm_target *ti, status_type_t type, + + residency = policy_residency(cache->policy); + +- DMEMIT("%u %llu/%llu %u %llu/%llu %u %u %u %u %u %u %llu ", ++ DMEMIT("%u %llu/%llu %u %llu/%llu %u %u %u %u %u %u %lu ", + (unsigned)(DM_CACHE_METADATA_BLOCK_SIZE >> SECTOR_SHIFT), + (unsigned long long)(nr_blocks_metadata - nr_free_blocks_metadata), + (unsigned long long)nr_blocks_metadata, +@@ -2841,7 +2856,7 @@ static void cache_status(struct dm_target *ti, status_type_t type, + (unsigned) atomic_read(&cache->stats.write_miss), + (unsigned) atomic_read(&cache->stats.demotion), + (unsigned) atomic_read(&cache->stats.promotion), +- (unsigned long long) from_cblock(cache->nr_dirty)); ++ (unsigned long) atomic_read(&cache->nr_dirty)); + + if (writethrough_mode(&cache->features)) + DMEMIT("1 writethrough "); +diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c +index 53b2132..4a8d19d 100644 +--- a/drivers/md/dm-crypt.c ++++ b/drivers/md/dm-crypt.c +@@ -709,7 +709,7 @@ static int crypt_iv_tcw_whitening(struct crypt_config *cc, + for (i = 0; i < ((1 << SECTOR_SHIFT) / 8); i++) + crypto_xor(data + i * 8, buf, 8); + out: +- memset(buf, 0, sizeof(buf)); ++ memzero_explicit(buf, sizeof(buf)); + return r; + } + +@@ -1681,6 +1681,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) + unsigned int key_size, opt_params; + unsigned long long tmpll; + int ret; ++ size_t iv_size_padding; + struct dm_arg_set as; + const char *opt_string; + char dummy; +@@ -1717,12 +1718,23 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) + + cc->dmreq_start = sizeof(struct ablkcipher_request); + cc->dmreq_start += crypto_ablkcipher_reqsize(any_tfm(cc)); +- cc->dmreq_start = ALIGN(cc->dmreq_start, crypto_tfm_ctx_alignment()); +- cc->dmreq_start += crypto_ablkcipher_alignmask(any_tfm(cc)) & +- ~(crypto_tfm_ctx_alignment() - 1); ++ cc->dmreq_start = ALIGN(cc->dmreq_start, __alignof__(struct dm_crypt_request)); ++ ++ if (crypto_ablkcipher_alignmask(any_tfm(cc)) < CRYPTO_MINALIGN) { ++ /* Allocate the padding exactly */ ++ iv_size_padding = -(cc->dmreq_start + sizeof(struct dm_crypt_request)) ++ & crypto_ablkcipher_alignmask(any_tfm(cc)); ++ } else { ++ /* ++ * If the cipher requires greater alignment than kmalloc ++ * alignment, we don't know the exact position of the ++ * initialization vector. We must assume worst case. ++ */ ++ iv_size_padding = crypto_ablkcipher_alignmask(any_tfm(cc)); ++ } + + cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start + +- sizeof(struct dm_crypt_request) + cc->iv_size); ++ sizeof(struct dm_crypt_request) + iv_size_padding + cc->iv_size); + if (!cc->req_pool) { + ti->error = "Cannot allocate crypt request mempool"; + goto bad; +diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c +index db404a0..080e767 100644 +--- a/drivers/md/dm-io.c ++++ b/drivers/md/dm-io.c +@@ -291,6 +291,19 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, + struct request_queue *q = bdev_get_queue(where->bdev); + unsigned short logical_block_size = queue_logical_block_size(q); + sector_t num_sectors; ++ unsigned int uninitialized_var(special_cmd_max_sectors); ++ ++ /* ++ * Reject unsupported discard and write same requests. ++ */ ++ if (rw & REQ_DISCARD) ++ special_cmd_max_sectors = q->limits.max_discard_sectors; ++ else if (rw & REQ_WRITE_SAME) ++ special_cmd_max_sectors = q->limits.max_write_same_sectors; ++ if ((rw & (REQ_DISCARD | REQ_WRITE_SAME)) && special_cmd_max_sectors == 0) { ++ dec_count(io, region, -EOPNOTSUPP); ++ return; ++ } + + /* + * where->count may be zero if rw holds a flush and we need to +@@ -313,7 +326,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, + store_io_and_region_in_bio(bio, io, region); + + if (rw & REQ_DISCARD) { +- num_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining); ++ num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining); + bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT; + remaining -= num_sectors; + } else if (rw & REQ_WRITE_SAME) { +@@ -322,7 +335,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, + */ + dp->get_page(dp, &page, &len, &offset); + bio_add_page(bio, page, logical_block_size, offset); +- num_sectors = min_t(sector_t, q->limits.max_write_same_sectors, remaining); ++ num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining); + bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT; + + offset = 0; +diff --git a/drivers/md/dm-log-userspace-transfer.c b/drivers/md/dm-log-userspace-transfer.c +index 08d9a20..c69d0b7 100644 +--- a/drivers/md/dm-log-userspace-transfer.c ++++ b/drivers/md/dm-log-userspace-transfer.c +@@ -272,7 +272,7 @@ int dm_ulog_tfr_init(void) + + r = cn_add_callback(&ulog_cn_id, "dmlogusr", cn_ulog_callback); + if (r) { +- cn_del_callback(&ulog_cn_id); ++ kfree(prealloced_cn_msg); + return r; + } + +diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c +index 4880b69..5971538 100644 +--- a/drivers/md/dm-raid.c ++++ b/drivers/md/dm-raid.c +@@ -785,8 +785,7 @@ struct dm_raid_superblock { + __le32 layout; + __le32 stripe_sectors; + +- __u8 pad[452]; /* Round struct to 512 bytes. */ +- /* Always set to 0 when writing. */ ++ /* Remainder of a logical block is zero-filled when writing (see super_sync()). */ + } __packed; + + static int read_disk_sb(struct md_rdev *rdev, int size) +@@ -823,7 +822,7 @@ static void super_sync(struct mddev *mddev, struct md_rdev *rdev) + test_bit(Faulty, &(rs->dev[i].rdev.flags))) + failed_devices |= (1ULL << i); + +- memset(sb, 0, sizeof(*sb)); ++ memset(sb + 1, 0, rdev->sb_size - sizeof(*sb)); + + sb->magic = cpu_to_le32(DM_RAID_MAGIC); + sb->features = cpu_to_le32(0); /* No features yet */ +@@ -858,7 +857,11 @@ static int super_load(struct md_rdev *rdev, struct md_rdev *refdev) + uint64_t events_sb, events_refsb; + + rdev->sb_start = 0; +- rdev->sb_size = sizeof(*sb); ++ rdev->sb_size = bdev_logical_block_size(rdev->meta_bdev); ++ if (rdev->sb_size < sizeof(*sb) || rdev->sb_size > PAGE_SIZE) { ++ DMERR("superblock size of a logical block is no longer valid"); ++ return -EINVAL; ++ } + + ret = read_disk_sb(rdev, rdev->sb_size); + if (ret) +diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c +index 7dfdb5c..089d627 100644 +--- a/drivers/md/dm-raid1.c ++++ b/drivers/md/dm-raid1.c +@@ -604,6 +604,15 @@ static void write_callback(unsigned long error, void *context) + return; + } + ++ /* ++ * If the bio is discard, return an error, but do not ++ * degrade the array. ++ */ ++ if (bio->bi_rw & REQ_DISCARD) { ++ bio_endio(bio, -EOPNOTSUPP); ++ return; ++ } ++ + for (i = 0; i < ms->nr_mirrors; i++) + if (test_bit(i, &error)) + fail_mirror(ms->mirror + i, DM_RAID1_WRITE_ERROR); +diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c +index ebddef5..c356a10 100644 +--- a/drivers/md/dm-snap.c ++++ b/drivers/md/dm-snap.c +@@ -1440,8 +1440,6 @@ out: + full_bio->bi_private = pe->full_bio_private; + atomic_inc(&full_bio->bi_remaining); + } +- free_pending_exception(pe); +- + increment_pending_exceptions_done_count(); + + up_write(&s->lock); +@@ -1458,6 +1456,8 @@ out: + } + + retry_origin_bios(s, origin_bios); ++ ++ free_pending_exception(pe); + } + + static void commit_callback(void *context, int success) +diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c +index 28a9012..b3b0697 100644 +--- a/drivers/md/dm-stats.c ++++ b/drivers/md/dm-stats.c +@@ -795,6 +795,8 @@ static int message_stats_create(struct mapped_device *md, + return -EINVAL; + + if (sscanf(argv[2], "/%u%c", &divisor, &dummy) == 1) { ++ if (!divisor) ++ return -EINVAL; + step = end - start; + if (do_div(step, divisor)) + step++; +diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c +index e9d33ad..3412b86 100644 +--- a/drivers/md/dm-thin-metadata.c ++++ b/drivers/md/dm-thin-metadata.c +@@ -1295,8 +1295,8 @@ static int __release_metadata_snap(struct dm_pool_metadata *pmd) + return r; + + disk_super = dm_block_data(copy); +- dm_sm_dec_block(pmd->metadata_sm, le64_to_cpu(disk_super->data_mapping_root)); +- dm_sm_dec_block(pmd->metadata_sm, le64_to_cpu(disk_super->device_details_root)); ++ dm_btree_del(&pmd->info, le64_to_cpu(disk_super->data_mapping_root)); ++ dm_btree_del(&pmd->details_info, le64_to_cpu(disk_super->device_details_root)); + dm_sm_dec_block(pmd->metadata_sm, held_root); + + return dm_tm_unlock(pmd->tm, copy); +diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c +index 359af3a..c1120eb 100644 +--- a/drivers/md/dm-thin.c ++++ b/drivers/md/dm-thin.c +@@ -916,6 +916,24 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block, + } + } + ++static void set_pool_mode(struct pool *pool, enum pool_mode new_mode); ++ ++static void check_for_space(struct pool *pool) ++{ ++ int r; ++ dm_block_t nr_free; ++ ++ if (get_pool_mode(pool) != PM_OUT_OF_DATA_SPACE) ++ return; ++ ++ r = dm_pool_get_free_block_count(pool->pmd, &nr_free); ++ if (r) ++ return; ++ ++ if (nr_free) ++ set_pool_mode(pool, PM_WRITE); ++} ++ + /* + * A non-zero return indicates read_only or fail_io mode. + * Many callers don't care about the return value. +@@ -930,6 +948,8 @@ static int commit(struct pool *pool) + r = dm_pool_commit_metadata(pool->pmd); + if (r) + metadata_operation_failed(pool, "dm_pool_commit_metadata", r); ++ else ++ check_for_space(pool); + + return r; + } +@@ -948,8 +968,6 @@ static void check_low_water_mark(struct pool *pool, dm_block_t free_blocks) + } + } + +-static void set_pool_mode(struct pool *pool, enum pool_mode new_mode); +- + static int alloc_data_block(struct thin_c *tc, dm_block_t *result) + { + int r; +@@ -1592,7 +1610,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode) + pool->process_bio = process_bio_read_only; + pool->process_discard = process_discard; + pool->process_prepared_mapping = process_prepared_mapping; +- pool->process_prepared_discard = process_prepared_discard_passdown; ++ pool->process_prepared_discard = process_prepared_discard; + + if (!pool->pf.error_if_no_space && no_space_timeout) + queue_delayed_work(pool->wq, &pool->no_space_timeout, no_space_timeout); +@@ -1704,6 +1722,14 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) + return DM_MAPIO_SUBMITTED; + } + ++ /* ++ * We must hold the virtual cell before doing the lookup, otherwise ++ * there's a race with discard. ++ */ ++ build_virtual_key(tc->td, block, &key); ++ if (dm_bio_detain(tc->pool->prison, &key, bio, &cell1, &cell_result)) ++ return DM_MAPIO_SUBMITTED; ++ + r = dm_thin_find_block(td, block, 0, &result); + + /* +@@ -1727,13 +1753,10 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) + * shared flag will be set in their case. + */ + thin_defer_bio(tc, bio); ++ cell_defer_no_holder_no_free(tc, &cell1); + return DM_MAPIO_SUBMITTED; + } + +- build_virtual_key(tc->td, block, &key); +- if (dm_bio_detain(tc->pool->prison, &key, bio, &cell1, &cell_result)) +- return DM_MAPIO_SUBMITTED; +- + build_data_key(tc->td, result.block, &key); + if (dm_bio_detain(tc->pool->prison, &key, bio, &cell2, &cell_result)) { + cell_defer_no_holder_no_free(tc, &cell1); +@@ -1754,6 +1777,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) + * of doing so. + */ + handle_unserviceable_bio(tc->pool, bio); ++ cell_defer_no_holder_no_free(tc, &cell1); + return DM_MAPIO_SUBMITTED; + } + /* fall through */ +@@ -1764,6 +1788,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) + * provide the hint to load the metadata into cache. + */ + thin_defer_bio(tc, bio); ++ cell_defer_no_holder_no_free(tc, &cell1); + return DM_MAPIO_SUBMITTED; + + default: +@@ -1773,6 +1798,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) + * pool is switched to fail-io mode. + */ + bio_io_error(bio); ++ cell_defer_no_holder_no_free(tc, &cell1); + return DM_MAPIO_SUBMITTED; + } + } +@@ -2718,6 +2744,12 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv) + struct pool_c *pt = ti->private; + struct pool *pool = pt->pool; + ++ if (get_pool_mode(pool) >= PM_READ_ONLY) { ++ DMERR("%s: unable to service pool target messages in READ_ONLY or FAIL mode", ++ dm_device_name(pool->pool_md)); ++ return -EINVAL; ++ } ++ + if (!strcasecmp(argv[0], "create_thin")) + r = process_create_thin_mesg(argc, argv, pool); + +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index 65ee3a0..e400591 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -2288,7 +2288,7 @@ int dm_setup_md_queue(struct mapped_device *md) + return 0; + } + +-static struct mapped_device *dm_find_md(dev_t dev) ++struct mapped_device *dm_get_md(dev_t dev) + { + struct mapped_device *md; + unsigned minor = MINOR(dev); +@@ -2299,12 +2299,15 @@ static struct mapped_device *dm_find_md(dev_t dev) + spin_lock(&_minor_lock); + + md = idr_find(&_minor_idr, minor); +- if (md && (md == MINOR_ALLOCED || +- (MINOR(disk_devt(dm_disk(md))) != minor) || +- dm_deleting_md(md) || +- test_bit(DMF_FREEING, &md->flags))) { +- md = NULL; +- goto out; ++ if (md) { ++ if ((md == MINOR_ALLOCED || ++ (MINOR(disk_devt(dm_disk(md))) != minor) || ++ dm_deleting_md(md) || ++ test_bit(DMF_FREEING, &md->flags))) { ++ md = NULL; ++ goto out; ++ } ++ dm_get(md); + } + + out: +@@ -2312,16 +2315,6 @@ out: + + return md; + } +- +-struct mapped_device *dm_get_md(dev_t dev) +-{ +- struct mapped_device *md = dm_find_md(dev); +- +- if (md) +- dm_get(md); +- +- return md; +-} + EXPORT_SYMBOL_GPL(dm_get_md); + + void *dm_get_mdptr(struct mapped_device *md) +@@ -2359,10 +2352,16 @@ static void __dm_destroy(struct mapped_device *md, bool wait) + set_bit(DMF_FREEING, &md->flags); + spin_unlock(&_minor_lock); + ++ /* ++ * Take suspend_lock so that presuspend and postsuspend methods ++ * do not race with internal suspend. ++ */ ++ mutex_lock(&md->suspend_lock); + if (!dm_suspended_md(md)) { + dm_table_presuspend_targets(map); + dm_table_postsuspend_targets(map); + } ++ mutex_unlock(&md->suspend_lock); + + /* dm_put_live_table must be before msleep, otherwise deadlock is possible */ + dm_put_live_table(md, srcu_idx); +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 73aedcb..2ffd277 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -5333,6 +5333,7 @@ static int md_set_readonly(struct mddev *mddev, struct block_device *bdev) + printk("md: %s still in use.\n",mdname(mddev)); + if (did_freeze) { + clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); ++ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); + } + err = -EBUSY; +@@ -5347,6 +5348,8 @@ static int md_set_readonly(struct mddev *mddev, struct block_device *bdev) + mddev->ro = 1; + set_disk_ro(mddev->gendisk, 1); + clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); ++ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); ++ md_wakeup_thread(mddev->thread); + sysfs_notify_dirent_safe(mddev->sysfs_state); + err = 0; + } +@@ -5390,6 +5393,7 @@ static int do_md_stop(struct mddev * mddev, int mode, + mutex_unlock(&mddev->open_mutex); + if (did_freeze) { + clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); ++ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); + } + return -EBUSY; +@@ -5641,8 +5645,7 @@ static int get_bitmap_file(struct mddev * mddev, void __user * arg) + char *ptr, *buf = NULL; + int err = -ENOMEM; + +- file = kmalloc(sizeof(*file), GFP_NOIO); +- ++ file = kzalloc(sizeof(*file), GFP_NOIO); + if (!file) + goto out; + +@@ -6228,7 +6231,7 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info) + mddev->ctime != info->ctime || + mddev->level != info->level || + /* mddev->layout != info->layout || */ +- !mddev->persistent != info->not_persistent|| ++ mddev->persistent != !info->not_persistent || + mddev->chunk_sectors != info->chunk_size >> 9 || + /* ignore bottom 8 bits of state, and allow SB_BITMAP_PRESENT to change */ + ((state^info->state) & 0xfffffe00) +diff --git a/drivers/md/persistent-data/dm-btree-internal.h b/drivers/md/persistent-data/dm-btree-internal.h +index 37d367b..bf2b80d 100644 +--- a/drivers/md/persistent-data/dm-btree-internal.h ++++ b/drivers/md/persistent-data/dm-btree-internal.h +@@ -42,6 +42,12 @@ struct btree_node { + } __packed; + + ++/* ++ * Locks a block using the btree node validator. ++ */ ++int bn_read_lock(struct dm_btree_info *info, dm_block_t b, ++ struct dm_block **result); ++ + void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, + struct dm_btree_value_type *vt); + +diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c +index b88757c..a03178e 100644 +--- a/drivers/md/persistent-data/dm-btree-remove.c ++++ b/drivers/md/persistent-data/dm-btree-remove.c +@@ -309,8 +309,8 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, + + if (s < 0 && nr_center < -s) { + /* not enough in central node */ +- shift(left, center, nr_center); +- s = nr_center - target; ++ shift(left, center, -nr_center); ++ s += nr_center; + shift(left, right, s); + nr_right += s; + } else +@@ -323,7 +323,7 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, + if (s > 0 && nr_center < s) { + /* not enough in central node */ + shift(center, right, nr_center); +- s = target - nr_center; ++ s -= nr_center; + shift(left, right, s); + nr_left -= s; + } else +diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c +index cf9fd67..1b5e13e 100644 +--- a/drivers/md/persistent-data/dm-btree-spine.c ++++ b/drivers/md/persistent-data/dm-btree-spine.c +@@ -92,7 +92,7 @@ struct dm_block_validator btree_node_validator = { + + /*----------------------------------------------------------------*/ + +-static int bn_read_lock(struct dm_btree_info *info, dm_block_t b, ++int bn_read_lock(struct dm_btree_info *info, dm_block_t b, + struct dm_block **result) + { + return dm_tm_read_lock(info->tm, b, &btree_node_validator, result); +diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c +index 416060c..fdd3793 100644 +--- a/drivers/md/persistent-data/dm-btree.c ++++ b/drivers/md/persistent-data/dm-btree.c +@@ -255,7 +255,7 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root) + int r; + struct del_stack *s; + +- s = kmalloc(sizeof(*s), GFP_KERNEL); ++ s = kmalloc(sizeof(*s), GFP_NOIO); + if (!s) + return -ENOMEM; + s->info = info; +@@ -847,22 +847,26 @@ EXPORT_SYMBOL_GPL(dm_btree_find_lowest_key); + * FIXME: We shouldn't use a recursive algorithm when we have limited stack + * space. Also this only works for single level trees. + */ +-static int walk_node(struct ro_spine *s, dm_block_t block, ++static int walk_node(struct dm_btree_info *info, dm_block_t block, + int (*fn)(void *context, uint64_t *keys, void *leaf), + void *context) + { + int r; + unsigned i, nr; ++ struct dm_block *node; + struct btree_node *n; + uint64_t keys; + +- r = ro_step(s, block); +- n = ro_node(s); ++ r = bn_read_lock(info, block, &node); ++ if (r) ++ return r; ++ ++ n = dm_block_data(node); + + nr = le32_to_cpu(n->header.nr_entries); + for (i = 0; i < nr; i++) { + if (le32_to_cpu(n->header.flags) & INTERNAL_NODE) { +- r = walk_node(s, value64(n, i), fn, context); ++ r = walk_node(info, value64(n, i), fn, context); + if (r) + goto out; + } else { +@@ -874,7 +878,7 @@ static int walk_node(struct ro_spine *s, dm_block_t block, + } + + out: +- ro_pop(s); ++ dm_tm_unlock(info->tm, node); + return r; + } + +@@ -882,15 +886,7 @@ int dm_btree_walk(struct dm_btree_info *info, dm_block_t root, + int (*fn)(void *context, uint64_t *keys, void *leaf), + void *context) + { +- int r; +- struct ro_spine spine; +- + BUG_ON(info->levels > 1); +- +- init_ro_spine(&spine, info); +- r = walk_node(&spine, root, fn, context); +- exit_ro_spine(&spine); +- +- return r; ++ return walk_node(info, root, fn, context); + } + EXPORT_SYMBOL_GPL(dm_btree_walk); +diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c +index 786b689..199c9cc 100644 +--- a/drivers/md/persistent-data/dm-space-map-metadata.c ++++ b/drivers/md/persistent-data/dm-space-map-metadata.c +@@ -204,6 +204,27 @@ static void in(struct sm_metadata *smm) + smm->recursion_count++; + } + ++static int apply_bops(struct sm_metadata *smm) ++{ ++ int r = 0; ++ ++ while (!brb_empty(&smm->uncommitted)) { ++ struct block_op bop; ++ ++ r = brb_pop(&smm->uncommitted, &bop); ++ if (r) { ++ DMERR("bug in bop ring buffer"); ++ break; ++ } ++ ++ r = commit_bop(smm, &bop); ++ if (r) ++ break; ++ } ++ ++ return r; ++} ++ + static int out(struct sm_metadata *smm) + { + int r = 0; +@@ -216,21 +237,8 @@ static int out(struct sm_metadata *smm) + return -ENOMEM; + } + +- if (smm->recursion_count == 1) { +- while (!brb_empty(&smm->uncommitted)) { +- struct block_op bop; +- +- r = brb_pop(&smm->uncommitted, &bop); +- if (r) { +- DMERR("bug in bop ring buffer"); +- break; +- } +- +- r = commit_bop(smm, &bop); +- if (r) +- break; +- } +- } ++ if (smm->recursion_count == 1) ++ apply_bops(smm); + + smm->recursion_count--; + +@@ -564,7 +572,9 @@ static int sm_bootstrap_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count + { + struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); + +- return smm->ll.nr_blocks; ++ *count = smm->ll.nr_blocks; ++ ++ return 0; + } + + static int sm_bootstrap_get_nr_free(struct dm_space_map *sm, dm_block_t *count) +@@ -700,6 +710,12 @@ static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks) + } + old_len = smm->begin; + ++ r = apply_bops(smm); ++ if (r) { ++ DMERR("%s: apply_bops failed", __func__); ++ goto out; ++ } ++ + r = sm_ll_commit(&smm->ll); + if (r) + goto out; +@@ -769,6 +785,12 @@ int dm_sm_metadata_create(struct dm_space_map *sm, + if (r) + return r; + ++ r = apply_bops(smm); ++ if (r) { ++ DMERR("%s: apply_bops failed", __func__); ++ return r; ++ } ++ + return sm_metadata_commit(sm); + } + +diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c +index 407a99e..9afd00b 100644 +--- a/drivers/md/raid0.c ++++ b/drivers/md/raid0.c +@@ -320,7 +320,7 @@ static struct strip_zone *find_zone(struct r0conf *conf, + + /* + * remaps the bio to the target device. we separate two flows. +- * power 2 flow and a general flow for the sake of perfromance ++ * power 2 flow and a general flow for the sake of performance + */ + static struct md_rdev *map_sector(struct mddev *mddev, struct strip_zone *zone, + sector_t sector, sector_t *sector_offset) +@@ -531,6 +531,9 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio) + ? (sector & (chunk_sects-1)) + : sector_div(sector, chunk_sects)); + ++ /* Restore due to sector_div */ ++ sector = bio->bi_iter.bi_sector; ++ + if (sectors < bio_sectors(bio)) { + split = bio_split(bio, sectors, GFP_NOIO, fs_bio_set); + bio_chain(split, bio); +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 56e24c0..47b7c31 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -336,7 +336,7 @@ static void raid1_end_read_request(struct bio *bio, int error) + spin_lock_irqsave(&conf->device_lock, flags); + if (r1_bio->mddev->degraded == conf->raid_disks || + (r1_bio->mddev->degraded == conf->raid_disks-1 && +- !test_bit(Faulty, &conf->mirrors[mirror].rdev->flags))) ++ test_bit(In_sync, &conf->mirrors[mirror].rdev->flags))) + uptodate = 1; + spin_unlock_irqrestore(&conf->device_lock, flags); + } +@@ -540,11 +540,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect + has_nonrot_disk = 0; + choose_next_idle = 0; + +- if (conf->mddev->recovery_cp < MaxSector && +- (this_sector + sectors >= conf->next_resync)) +- choose_first = 1; +- else +- choose_first = 0; ++ choose_first = (conf->mddev->recovery_cp < this_sector + sectors); + + for (disk = 0 ; disk < conf->raid_disks * 2 ; disk++) { + sector_t dist; +@@ -565,7 +561,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect + if (test_bit(WriteMostly, &rdev->flags)) { + /* Don't balance among write-mostly, just + * use the first as a last resort */ +- if (best_disk < 0) { ++ if (best_dist_disk < 0) { + if (is_badblock(rdev, this_sector, sectors, + &first_bad, &bad_sectors)) { + if (first_bad < this_sector) +@@ -574,7 +570,8 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect + best_good_sectors = first_bad - this_sector; + } else + best_good_sectors = sectors; +- best_disk = disk; ++ best_dist_disk = disk; ++ best_pending_disk = disk; + } + continue; + } +@@ -831,7 +828,7 @@ static void flush_pending_writes(struct r1conf *conf) + * there is no normal IO happeing. It must arrange to call + * lower_barrier when the particular background IO completes. + */ +-static void raise_barrier(struct r1conf *conf) ++static void raise_barrier(struct r1conf *conf, sector_t sector_nr) + { + spin_lock_irq(&conf->resync_lock); + +@@ -841,6 +838,7 @@ static void raise_barrier(struct r1conf *conf) + + /* block any new IO from starting */ + conf->barrier++; ++ conf->next_resync = sector_nr; + + /* For these conditions we must wait: + * A: while the array is in frozen state +@@ -849,14 +847,17 @@ static void raise_barrier(struct r1conf *conf) + * C: next_resync + RESYNC_SECTORS > start_next_window, meaning + * next resync will reach to the window which normal bios are + * handling. ++ * D: while there are any active requests in the current window. + */ + wait_event_lock_irq(conf->wait_barrier, + !conf->array_frozen && + conf->barrier < RESYNC_DEPTH && ++ conf->current_window_requests == 0 && + (conf->start_next_window >= + conf->next_resync + RESYNC_SECTORS), + conf->resync_lock); + ++ conf->nr_pending++; + spin_unlock_irq(&conf->resync_lock); + } + +@@ -866,6 +867,7 @@ static void lower_barrier(struct r1conf *conf) + BUG_ON(conf->barrier <= 0); + spin_lock_irqsave(&conf->resync_lock, flags); + conf->barrier--; ++ conf->nr_pending--; + spin_unlock_irqrestore(&conf->resync_lock, flags); + wake_up(&conf->wait_barrier); + } +@@ -877,12 +879,10 @@ static bool need_to_wait_for_sync(struct r1conf *conf, struct bio *bio) + if (conf->array_frozen || !bio) + wait = true; + else if (conf->barrier && bio_data_dir(bio) == WRITE) { +- if (conf->next_resync < RESYNC_WINDOW_SECTORS) +- wait = true; +- else if ((conf->next_resync - RESYNC_WINDOW_SECTORS +- >= bio_end_sector(bio)) || +- (conf->next_resync + NEXT_NORMALIO_DISTANCE +- <= bio->bi_iter.bi_sector)) ++ if ((conf->mddev->curr_resync_completed ++ >= bio_end_sector(bio)) || ++ (conf->next_resync + NEXT_NORMALIO_DISTANCE ++ <= bio->bi_iter.bi_sector)) + wait = false; + else + wait = true; +@@ -919,8 +919,8 @@ static sector_t wait_barrier(struct r1conf *conf, struct bio *bio) + } + + if (bio && bio_data_dir(bio) == WRITE) { +- if (conf->next_resync + NEXT_NORMALIO_DISTANCE +- <= bio->bi_iter.bi_sector) { ++ if (bio->bi_iter.bi_sector >= ++ conf->mddev->curr_resync_completed) { + if (conf->start_next_window == MaxSector) + conf->start_next_window = + conf->next_resync + +@@ -1186,6 +1186,7 @@ read_again: + atomic_read(&bitmap->behind_writes) == 0); + } + r1_bio->read_disk = rdisk; ++ r1_bio->start_next_window = 0; + + read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev); + bio_trim(read_bio, r1_bio->sector - bio->bi_iter.bi_sector, +@@ -1476,6 +1477,7 @@ static void error(struct mddev *mddev, struct md_rdev *rdev) + { + char b[BDEVNAME_SIZE]; + struct r1conf *conf = mddev->private; ++ unsigned long flags; + + /* + * If it is not operational, then we have already marked it as dead +@@ -1495,18 +1497,17 @@ static void error(struct mddev *mddev, struct md_rdev *rdev) + return; + } + set_bit(Blocked, &rdev->flags); ++ spin_lock_irqsave(&conf->device_lock, flags); + if (test_and_clear_bit(In_sync, &rdev->flags)) { +- unsigned long flags; +- spin_lock_irqsave(&conf->device_lock, flags); + mddev->degraded++; + set_bit(Faulty, &rdev->flags); +- spin_unlock_irqrestore(&conf->device_lock, flags); +- /* +- * if recovery is running, make sure it aborts. +- */ +- set_bit(MD_RECOVERY_INTR, &mddev->recovery); + } else + set_bit(Faulty, &rdev->flags); ++ spin_unlock_irqrestore(&conf->device_lock, flags); ++ /* ++ * if recovery is running, make sure it aborts. ++ */ ++ set_bit(MD_RECOVERY_INTR, &mddev->recovery); + set_bit(MD_CHANGE_DEVS, &mddev->flags); + printk(KERN_ALERT + "md/raid1:%s: Disk failure on %s, disabling device.\n" +@@ -1548,8 +1549,13 @@ static void close_sync(struct r1conf *conf) + mempool_destroy(conf->r1buf_pool); + conf->r1buf_pool = NULL; + ++ spin_lock_irq(&conf->resync_lock); + conf->next_resync = 0; + conf->start_next_window = MaxSector; ++ conf->current_window_requests += ++ conf->next_window_requests; ++ conf->next_window_requests = 0; ++ spin_unlock_irq(&conf->resync_lock); + } + + static int raid1_spare_active(struct mddev *mddev) +@@ -1563,7 +1569,10 @@ static int raid1_spare_active(struct mddev *mddev) + * Find all failed disks within the RAID1 configuration + * and mark them readable. + * Called under mddev lock, so rcu protection not needed. ++ * device_lock used to avoid races with raid1_end_read_request ++ * which expects 'In_sync' flags and ->degraded to be consistent. + */ ++ spin_lock_irqsave(&conf->device_lock, flags); + for (i = 0; i < conf->raid_disks; i++) { + struct md_rdev *rdev = conf->mirrors[i].rdev; + struct md_rdev *repl = conf->mirrors[conf->raid_disks + i].rdev; +@@ -1593,7 +1602,6 @@ static int raid1_spare_active(struct mddev *mddev) + sysfs_notify_dirent_safe(rdev->sysfs_state); + } + } +- spin_lock_irqsave(&conf->device_lock, flags); + mddev->degraded -= count; + spin_unlock_irqrestore(&conf->device_lock, flags); + +@@ -2150,7 +2158,7 @@ static void fix_read_error(struct r1conf *conf, int read_disk, + d--; + rdev = conf->mirrors[d].rdev; + if (rdev && +- test_bit(In_sync, &rdev->flags)) ++ !test_bit(Faulty, &rdev->flags)) + r1_sync_page_io(rdev, sect, s, + conf->tmppage, WRITE); + } +@@ -2162,7 +2170,7 @@ static void fix_read_error(struct r1conf *conf, int read_disk, + d--; + rdev = conf->mirrors[d].rdev; + if (rdev && +- test_bit(In_sync, &rdev->flags)) { ++ !test_bit(Faulty, &rdev->flags)) { + if (r1_sync_page_io(rdev, sect, s, + conf->tmppage, READ)) { + atomic_add(s, &rdev->corrected_errors); +@@ -2541,9 +2549,8 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp + + bitmap_cond_end_sync(mddev->bitmap, sector_nr); + r1_bio = mempool_alloc(conf->r1buf_pool, GFP_NOIO); +- raise_barrier(conf); + +- conf->next_resync = sector_nr; ++ raise_barrier(conf, sector_nr); + + rcu_read_lock(); + /* +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index cb882aa..a46124e 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -1684,13 +1684,12 @@ static void error(struct mddev *mddev, struct md_rdev *rdev) + spin_unlock_irqrestore(&conf->device_lock, flags); + return; + } +- if (test_and_clear_bit(In_sync, &rdev->flags)) { ++ if (test_and_clear_bit(In_sync, &rdev->flags)) + mddev->degraded++; +- /* +- * if recovery is running, make sure it aborts. +- */ +- set_bit(MD_RECOVERY_INTR, &mddev->recovery); +- } ++ /* ++ * If recovery is running, make sure it aborts. ++ */ ++ set_bit(MD_RECOVERY_INTR, &mddev->recovery); + set_bit(Blocked, &rdev->flags); + set_bit(Faulty, &rdev->flags); + set_bit(MD_CHANGE_DEVS, &mddev->flags); +@@ -2954,6 +2953,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, + */ + if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) { + end_reshape(conf); ++ close_sync(conf); + return 0; + } + +@@ -4411,7 +4411,7 @@ read_more: + read_bio->bi_private = r10_bio; + read_bio->bi_end_io = end_sync_read; + read_bio->bi_rw = READ; +- read_bio->bi_flags &= ~(BIO_POOL_MASK - 1); ++ read_bio->bi_flags &= (~0UL << BIO_RESET_BITS); + read_bio->bi_flags |= 1 << BIO_UPTODATE; + read_bio->bi_vcnt = 0; + read_bio->bi_iter.bi_size = 0; +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 16f5c21..b98c70e 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -64,6 +64,10 @@ + #define cpu_to_group(cpu) cpu_to_node(cpu) + #define ANY_GROUP NUMA_NO_NODE + ++static bool devices_handle_discard_safely = false; ++module_param(devices_handle_discard_safely, bool, 0644); ++MODULE_PARM_DESC(devices_handle_discard_safely, ++ "Set to Y if all devices in each array reliably return zeroes on reads from discarded regions"); + static struct workqueue_struct *raid5_wq; + /* + * Stripe cache +@@ -1910,7 +1914,8 @@ static int resize_stripes(struct r5conf *conf, int newsize) + + conf->slab_cache = sc; + conf->active_name = 1-conf->active_name; +- conf->pool_size = newsize; ++ if (!err) ++ conf->pool_size = newsize; + return err; + } + +@@ -2892,7 +2897,8 @@ static int fetch_block(struct stripe_head *sh, struct stripe_head_state *s, + (s->failed >= 2 && fdev[1]->toread) || + (sh->raid_conf->level <= 5 && s->failed && fdev[0]->towrite && + !test_bit(R5_OVERWRITE, &fdev[0]->flags)) || +- (sh->raid_conf->level == 6 && s->failed && s->to_write))) { ++ ((sh->raid_conf->level == 6 || sh->sector >= sh->raid_conf->mddev->recovery_cp) ++ && s->failed && s->to_write))) { + /* we would like to get this block, possibly by computing it, + * otherwise read it if the backing disk is insync + */ +@@ -3066,7 +3072,8 @@ static void handle_stripe_dirtying(struct r5conf *conf, + * generate correct data from the parity. + */ + if (conf->max_degraded == 2 || +- (recovery_cp < MaxSector && sh->sector >= recovery_cp)) { ++ (recovery_cp < MaxSector && sh->sector >= recovery_cp && ++ s->failed == 0)) { + /* Calculate the real rcw later - for now make it + * look like rcw is cheaper + */ +@@ -3779,6 +3786,8 @@ static void handle_stripe(struct stripe_head *sh) + set_bit(R5_Wantwrite, &dev->flags); + if (prexor) + continue; ++ if (s.failed > 1) ++ continue; + if (!test_bit(R5_Insync, &dev->flags) || + ((i == sh->pd_idx || i == sh->qd_idx) && + s.failed == 0)) +@@ -6115,7 +6124,7 @@ static int run(struct mddev *mddev) + mddev->queue->limits.discard_granularity = stripe; + /* + * unaligned part of discard request will be ignored, so can't +- * guarantee discard_zerors_data ++ * guarantee discard_zeroes_data + */ + mddev->queue->limits.discard_zeroes_data = 0; + +@@ -6140,6 +6149,18 @@ static int run(struct mddev *mddev) + !bdev_get_queue(rdev->bdev)-> + limits.discard_zeroes_data) + discard_supported = false; ++ /* Unfortunately, discard_zeroes_data is not currently ++ * a guarantee - just a hint. So we only allow DISCARD ++ * if the sysadmin has confirmed that only safe devices ++ * are in use by setting a module parameter. ++ */ ++ if (!devices_handle_discard_safely) { ++ if (discard_supported) { ++ pr_info("md/raid456: discard support disabled due to uncertainty.\n"); ++ pr_info("Set raid456.devices_handle_discard_safely=Y to override.\n"); ++ } ++ discard_supported = false; ++ } + } + + if (discard_supported && +diff --git a/drivers/media/common/siano/Kconfig b/drivers/media/common/siano/Kconfig +index f953d33..4bfbd5f 100644 +--- a/drivers/media/common/siano/Kconfig ++++ b/drivers/media/common/siano/Kconfig +@@ -22,8 +22,7 @@ config SMS_SIANO_DEBUGFS + bool "Enable debugfs for smsdvb" + depends on SMS_SIANO_MDTV + depends on DEBUG_FS +- depends on SMS_USB_DRV +- depends on CONFIG_SMS_USB_DRV = CONFIG_SMS_SDIO_DRV ++ depends on SMS_USB_DRV = SMS_SDIO_DRV + + ---help--- + Choose Y to enable visualizing a dump of the frontend +diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h +index 80643ef..fabe2fc 100644 +--- a/drivers/media/dvb-core/dvb-usb-ids.h ++++ b/drivers/media/dvb-core/dvb-usb-ids.h +@@ -279,6 +279,8 @@ + #define USB_PID_PCTV_400E 0x020f + #define USB_PID_PCTV_450E 0x0222 + #define USB_PID_PCTV_452E 0x021f ++#define USB_PID_PCTV_78E 0x025a ++#define USB_PID_PCTV_79E 0x0262 + #define USB_PID_REALTEK_RTL2831U 0x2831 + #define USB_PID_REALTEK_RTL2832U 0x2832 + #define USB_PID_TECHNOTREND_CONNECT_S2_3600 0x3007 +diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c +index fb504f1..5930aee 100644 +--- a/drivers/media/dvb-frontends/af9013.c ++++ b/drivers/media/dvb-frontends/af9013.c +@@ -606,6 +606,10 @@ static int af9013_set_frontend(struct dvb_frontend *fe) + } + } + ++ /* Return an error if can't find bandwidth or the right clock */ ++ if (i == ARRAY_SIZE(coeff_lut)) ++ return -EINVAL; ++ + ret = af9013_wr_regs(state, 0xae00, coeff_lut[i].val, + sizeof(coeff_lut[i].val)); + } +diff --git a/drivers/media/dvb-frontends/cx24116.c b/drivers/media/dvb-frontends/cx24116.c +index 2916d7c..7bc68b3 100644 +--- a/drivers/media/dvb-frontends/cx24116.c ++++ b/drivers/media/dvb-frontends/cx24116.c +@@ -963,6 +963,10 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend *fe, + struct cx24116_state *state = fe->demodulator_priv; + int i, ret; + ++ /* Validate length */ ++ if (d->msg_len > sizeof(d->msg)) ++ return -EINVAL; ++ + /* Dump DiSEqC message */ + if (debug) { + printk(KERN_INFO "cx24116: %s(", __func__); +@@ -974,10 +978,6 @@ static int cx24116_send_diseqc_msg(struct dvb_frontend *fe, + printk(") toneburst=%d\n", toneburst); + } + +- /* Validate length */ +- if (d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS)) +- return -EINVAL; +- + /* DiSEqC message */ + for (i = 0; i < d->msg_len; i++) + state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i]; +diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c +index a6c3c9e..d2eab06 100644 +--- a/drivers/media/dvb-frontends/cx24117.c ++++ b/drivers/media/dvb-frontends/cx24117.c +@@ -1043,7 +1043,7 @@ static int cx24117_send_diseqc_msg(struct dvb_frontend *fe, + dev_dbg(&state->priv->i2c->dev, ")\n"); + + /* Validate length */ +- if (d->msg_len > 15) ++ if (d->msg_len > sizeof(d->msg)) + return -EINVAL; + + /* DiSEqC message */ +diff --git a/drivers/media/dvb-frontends/ds3000.c b/drivers/media/dvb-frontends/ds3000.c +index 1e344b0..22e8c20 100644 +--- a/drivers/media/dvb-frontends/ds3000.c ++++ b/drivers/media/dvb-frontends/ds3000.c +@@ -864,6 +864,13 @@ struct dvb_frontend *ds3000_attach(const struct ds3000_config *config, + memcpy(&state->frontend.ops, &ds3000_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; ++ ++ /* ++ * Some devices like T480 starts with voltage on. Be sure ++ * to turn voltage off during init, as this can otherwise ++ * interfere with Unicable SCR systems. ++ */ ++ ds3000_set_voltage(&state->frontend, SEC_VOLTAGE_OFF); + return &state->frontend; + + error3: +diff --git a/drivers/media/dvb-frontends/s5h1420.c b/drivers/media/dvb-frontends/s5h1420.c +index 93eeaf7..0b4f8fe 100644 +--- a/drivers/media/dvb-frontends/s5h1420.c ++++ b/drivers/media/dvb-frontends/s5h1420.c +@@ -180,7 +180,7 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, + int result = 0; + + dprintk("enter %s\n", __func__); +- if (cmd->msg_len > 8) ++ if (cmd->msg_len > sizeof(cmd->msg)) + return -EINVAL; + + /* setup for DISEQC */ +diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c +index 8ad3a57..287b977 100644 +--- a/drivers/media/dvb-frontends/tda10071.c ++++ b/drivers/media/dvb-frontends/tda10071.c +@@ -667,6 +667,7 @@ static int tda10071_set_frontend(struct dvb_frontend *fe) + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int ret, i; + u8 mode, rolloff, pilot, inversion, div; ++ fe_modulation_t modulation; + + dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d modulation=%d " \ + "frequency=%d symbol_rate=%d inversion=%d pilot=%d " \ +@@ -701,10 +702,13 @@ static int tda10071_set_frontend(struct dvb_frontend *fe) + + switch (c->delivery_system) { + case SYS_DVBS: ++ modulation = QPSK; + rolloff = 0; + pilot = 2; + break; + case SYS_DVBS2: ++ modulation = c->modulation; ++ + switch (c->rolloff) { + case ROLLOFF_20: + rolloff = 2; +@@ -749,7 +753,7 @@ static int tda10071_set_frontend(struct dvb_frontend *fe) + + for (i = 0, mode = 0xff; i < ARRAY_SIZE(TDA10071_MODCOD); i++) { + if (c->delivery_system == TDA10071_MODCOD[i].delivery_system && +- c->modulation == TDA10071_MODCOD[i].modulation && ++ modulation == TDA10071_MODCOD[i].modulation && + c->fec_inner == TDA10071_MODCOD[i].fec) { + mode = TDA10071_MODCOD[i].val; + dev_dbg(&priv->i2c->dev, "%s: mode found=%02x\n", +diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c +index 71c8570..112394d 100644 +--- a/drivers/media/i2c/adv7604.c ++++ b/drivers/media/i2c/adv7604.c +@@ -1984,7 +1984,7 @@ static int adv7604_log_status(struct v4l2_subdev *sd) + v4l2_info(sd, "HDCP keys read: %s%s\n", + (hdmi_read(sd, 0x04) & 0x20) ? "yes" : "no", + (hdmi_read(sd, 0x04) & 0x10) ? "ERROR" : ""); +- if (!is_hdmi(sd)) { ++ if (is_hdmi(sd)) { + bool audio_pll_locked = hdmi_read(sd, 0x04) & 0x01; + bool audio_sample_packet_detect = hdmi_read(sd, 0x18) & 0x01; + bool audio_mute = io_read(sd, 0x65) & 0x40; +diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c +index 36c504b..008ac87 100644 +--- a/drivers/media/i2c/mt9v032.c ++++ b/drivers/media/i2c/mt9v032.c +@@ -305,8 +305,8 @@ mt9v032_update_hblank(struct mt9v032 *mt9v032) + + if (mt9v032->version->version == MT9V034_CHIP_ID_REV1) + min_hblank += (mt9v032->hratio - 1) * 10; +- min_hblank = max_t(unsigned int, (int)mt9v032->model->data->min_row_time - crop->width, +- (int)min_hblank); ++ min_hblank = max_t(int, mt9v032->model->data->min_row_time - crop->width, ++ min_hblank); + hblank = max_t(unsigned int, mt9v032->hblank, min_hblank); + + return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, hblank); +diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c +index 2335529..ab5d9a3 100644 +--- a/drivers/media/i2c/smiapp-pll.c ++++ b/drivers/media/i2c/smiapp-pll.c +@@ -67,7 +67,7 @@ static void print_pll(struct device *dev, struct smiapp_pll *pll) + { + dev_dbg(dev, "pre_pll_clk_div\t%d\n", pll->pre_pll_clk_div); + dev_dbg(dev, "pll_multiplier \t%d\n", pll->pll_multiplier); +- if (pll->flags != SMIAPP_PLL_FLAG_NO_OP_CLOCKS) { ++ if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) { + dev_dbg(dev, "op_sys_clk_div \t%d\n", pll->op_sys_clk_div); + dev_dbg(dev, "op_pix_clk_div \t%d\n", pll->op_pix_clk_div); + } +@@ -77,7 +77,7 @@ static void print_pll(struct device *dev, struct smiapp_pll *pll) + dev_dbg(dev, "ext_clk_freq_hz \t%d\n", pll->ext_clk_freq_hz); + dev_dbg(dev, "pll_ip_clk_freq_hz \t%d\n", pll->pll_ip_clk_freq_hz); + dev_dbg(dev, "pll_op_clk_freq_hz \t%d\n", pll->pll_op_clk_freq_hz); +- if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) { ++ if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) { + dev_dbg(dev, "op_sys_clk_freq_hz \t%d\n", + pll->op_sys_clk_freq_hz); + dev_dbg(dev, "op_pix_clk_freq_hz \t%d\n", +diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c +index 8741cae..873d062 100644 +--- a/drivers/media/i2c/smiapp/smiapp-core.c ++++ b/drivers/media/i2c/smiapp/smiapp-core.c +@@ -2138,7 +2138,7 @@ static int smiapp_set_selection(struct v4l2_subdev *subdev, + ret = smiapp_set_compose(subdev, fh, sel); + break; + default: +- BUG(); ++ ret = -EINVAL; + } + + mutex_unlock(&sensor->mutex); +@@ -2624,7 +2624,9 @@ static int smiapp_registered(struct v4l2_subdev *subdev) + pll->flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE; + pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN]; + ++ mutex_lock(&sensor->mutex); + rval = smiapp_update_mode(sensor); ++ mutex_unlock(&sensor->mutex); + if (rval) { + dev_err(&client->dev, "update mode failed\n"); + goto out_nvm_release; +diff --git a/drivers/media/i2c/tda7432.c b/drivers/media/i2c/tda7432.c +index 72af644..cf93021 100644 +--- a/drivers/media/i2c/tda7432.c ++++ b/drivers/media/i2c/tda7432.c +@@ -293,7 +293,7 @@ static int tda7432_s_ctrl(struct v4l2_ctrl *ctrl) + if (t->mute->val) { + lf |= TDA7432_MUTE; + lr |= TDA7432_MUTE; +- lf |= TDA7432_MUTE; ++ rf |= TDA7432_MUTE; + rr |= TDA7432_MUTE; + } + /* Mute & update balance*/ +diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c +index 703560f..88c1606 100644 +--- a/drivers/media/media-device.c ++++ b/drivers/media/media-device.c +@@ -106,8 +106,6 @@ static long media_device_enum_entities(struct media_device *mdev, + if (ent->name) { + strncpy(u_ent.name, ent->name, sizeof(u_ent.name)); + u_ent.name[sizeof(u_ent.name) - 1] = '\0'; +- } else { +- memset(u_ent.name, 0, sizeof(u_ent.name)); + } + u_ent.type = ent->type; + u_ent.revision = ent->revision; +diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c +index 716bdc5..83f5074 100644 +--- a/drivers/media/pci/cx18/cx18-driver.c ++++ b/drivers/media/pci/cx18/cx18-driver.c +@@ -1091,6 +1091,7 @@ static int cx18_probe(struct pci_dev *pci_dev, + setup.addr = ADDR_UNSET; + setup.type = cx->options.tuner; + setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */ ++ setup.config = NULL; + if (cx->options.radio > 0) + setup.mode_mask |= T_RADIO; + setup.tuner_callback = (setup.type == TUNER_XC2028) ? +diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +index f723f1f..ab85127 100644 +--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h ++++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +@@ -30,7 +30,7 @@ + + /* Offset base used to differentiate between CAPTURE and OUTPUT + * while mmaping */ +-#define DST_QUEUE_OFF_BASE (TASK_SIZE / 2) ++#define DST_QUEUE_OFF_BASE (1 << 30) + + #define MFC_BANK1_ALLOC_CTX 0 + #define MFC_BANK2_ALLOC_CTX 1 +diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c +index 744e43b..f698e32 100644 +--- a/drivers/media/platform/sh_veu.c ++++ b/drivers/media/platform/sh_veu.c +@@ -1183,6 +1183,7 @@ static int sh_veu_probe(struct platform_device *pdev) + } + + *vdev = sh_veu_videodev; ++ vdev->v4l2_dev = &veu->v4l2_dev; + spin_lock_init(&veu->lock); + mutex_init(&veu->fop_lock); + vdev->lock = &veu->fop_lock; +diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c +index b4687a8..7245cca 100644 +--- a/drivers/media/platform/vsp1/vsp1_video.c ++++ b/drivers/media/platform/vsp1/vsp1_video.c +@@ -635,8 +635,6 @@ static int vsp1_video_buffer_prepare(struct vb2_buffer *vb) + if (vb->num_planes < format->num_planes) + return -EINVAL; + +- buf->video = video; +- + for (i = 0; i < vb->num_planes; ++i) { + buf->addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); + buf->length[i] = vb2_plane_size(vb, i); +diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h +index d8612a3..47b7a8a 100644 +--- a/drivers/media/platform/vsp1/vsp1_video.h ++++ b/drivers/media/platform/vsp1/vsp1_video.h +@@ -89,7 +89,6 @@ static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e) + } + + struct vsp1_video_buffer { +- struct vsp1_video *video; + struct vb2_buffer buf; + struct list_head queue; + +diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c +index ed2c8a1..98893a8 100644 +--- a/drivers/media/rc/ir-lirc-codec.c ++++ b/drivers/media/rc/ir-lirc-codec.c +@@ -42,11 +42,17 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) + return -EINVAL; + + /* Packet start */ +- if (ev.reset) +- return 0; ++ if (ev.reset) { ++ /* Userspace expects a long space event before the start of ++ * the signal to use as a sync. This may be done with repeat ++ * packets and normal samples. But if a reset has been sent ++ * then we assume that a long time has passed, so we send a ++ * space with the maximum time value. */ ++ sample = LIRC_SPACE(LIRC_VALUE_MASK); ++ IR_dprintk(2, "delivering reset sync space to lirc_dev\n"); + + /* Carrier reports */ +- if (ev.carrier_report) { ++ } else if (ev.carrier_report) { + sample = LIRC_FREQUENCY(ev.carrier); + IR_dprintk(2, "carrier report (freq: %d)\n", sample); + +diff --git a/drivers/media/tuners/m88ts2022.c b/drivers/media/tuners/m88ts2022.c +index 40c42de..7a62097 100644 +--- a/drivers/media/tuners/m88ts2022.c ++++ b/drivers/media/tuners/m88ts2022.c +@@ -314,7 +314,7 @@ static int m88ts2022_set_params(struct dvb_frontend *fe) + div_min = gdiv28 * 78 / 100; + div_max = clamp_val(div_max, 0U, 63U); + +- f_3db_hz = c->symbol_rate * 135UL / 200UL; ++ f_3db_hz = mult_frac(c->symbol_rate, 135, 200); + f_3db_hz += 2000000U + (frequency_offset_khz * 1000U); + f_3db_hz = clamp(f_3db_hz, 7000000U, 40000000U); + +diff --git a/drivers/media/tuners/xc4000.c b/drivers/media/tuners/xc4000.c +index 2018bef..e71decb 100644 +--- a/drivers/media/tuners/xc4000.c ++++ b/drivers/media/tuners/xc4000.c +@@ -93,7 +93,7 @@ struct xc4000_priv { + struct firmware_description *firm; + int firm_size; + u32 if_khz; +- u32 freq_hz; ++ u32 freq_hz, freq_offset; + u32 bandwidth; + u8 video_standard; + u8 rf_mode; +@@ -1157,14 +1157,14 @@ static int xc4000_set_params(struct dvb_frontend *fe) + case SYS_ATSC: + dprintk(1, "%s() VSB modulation\n", __func__); + priv->rf_mode = XC_RF_MODE_AIR; +- priv->freq_hz = c->frequency - 1750000; ++ priv->freq_offset = 1750000; + priv->video_standard = XC4000_DTV6; + type = DTV6; + break; + case SYS_DVBC_ANNEX_B: + dprintk(1, "%s() QAM modulation\n", __func__); + priv->rf_mode = XC_RF_MODE_CABLE; +- priv->freq_hz = c->frequency - 1750000; ++ priv->freq_offset = 1750000; + priv->video_standard = XC4000_DTV6; + type = DTV6; + break; +@@ -1173,23 +1173,23 @@ static int xc4000_set_params(struct dvb_frontend *fe) + dprintk(1, "%s() OFDM\n", __func__); + if (bw == 0) { + if (c->frequency < 400000000) { +- priv->freq_hz = c->frequency - 2250000; ++ priv->freq_offset = 2250000; + } else { +- priv->freq_hz = c->frequency - 2750000; ++ priv->freq_offset = 2750000; + } + priv->video_standard = XC4000_DTV7_8; + type = DTV78; + } else if (bw <= 6000000) { + priv->video_standard = XC4000_DTV6; +- priv->freq_hz = c->frequency - 1750000; ++ priv->freq_offset = 1750000; + type = DTV6; + } else if (bw <= 7000000) { + priv->video_standard = XC4000_DTV7; +- priv->freq_hz = c->frequency - 2250000; ++ priv->freq_offset = 2250000; + type = DTV7; + } else { + priv->video_standard = XC4000_DTV8; +- priv->freq_hz = c->frequency - 2750000; ++ priv->freq_offset = 2750000; + type = DTV8; + } + priv->rf_mode = XC_RF_MODE_AIR; +@@ -1200,6 +1200,8 @@ static int xc4000_set_params(struct dvb_frontend *fe) + goto fail; + } + ++ priv->freq_hz = c->frequency - priv->freq_offset; ++ + dprintk(1, "%s() frequency=%d (compensated)\n", + __func__, priv->freq_hz); + +@@ -1520,7 +1522,7 @@ static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq) + { + struct xc4000_priv *priv = fe->tuner_priv; + +- *freq = priv->freq_hz; ++ *freq = priv->freq_hz + priv->freq_offset; + + if (debug) { + mutex_lock(&priv->lock); +diff --git a/drivers/media/tuners/xc5000.c b/drivers/media/tuners/xc5000.c +index 5cd09a6..b2d9e9c 100644 +--- a/drivers/media/tuners/xc5000.c ++++ b/drivers/media/tuners/xc5000.c +@@ -55,7 +55,7 @@ struct xc5000_priv { + + u32 if_khz; + u16 xtal_khz; +- u32 freq_hz; ++ u32 freq_hz, freq_offset; + u32 bandwidth; + u8 video_standard; + u8 rf_mode; +@@ -755,13 +755,13 @@ static int xc5000_set_params(struct dvb_frontend *fe) + case SYS_ATSC: + dprintk(1, "%s() VSB modulation\n", __func__); + priv->rf_mode = XC_RF_MODE_AIR; +- priv->freq_hz = freq - 1750000; ++ priv->freq_offset = 1750000; + priv->video_standard = DTV6; + break; + case SYS_DVBC_ANNEX_B: + dprintk(1, "%s() QAM modulation\n", __func__); + priv->rf_mode = XC_RF_MODE_CABLE; +- priv->freq_hz = freq - 1750000; ++ priv->freq_offset = 1750000; + priv->video_standard = DTV6; + break; + case SYS_ISDBT: +@@ -776,15 +776,15 @@ static int xc5000_set_params(struct dvb_frontend *fe) + switch (bw) { + case 6000000: + priv->video_standard = DTV6; +- priv->freq_hz = freq - 1750000; ++ priv->freq_offset = 1750000; + break; + case 7000000: + priv->video_standard = DTV7; +- priv->freq_hz = freq - 2250000; ++ priv->freq_offset = 2250000; + break; + case 8000000: + priv->video_standard = DTV8; +- priv->freq_hz = freq - 2750000; ++ priv->freq_offset = 2750000; + break; + default: + printk(KERN_ERR "xc5000 bandwidth not set!\n"); +@@ -798,15 +798,15 @@ static int xc5000_set_params(struct dvb_frontend *fe) + priv->rf_mode = XC_RF_MODE_CABLE; + if (bw <= 6000000) { + priv->video_standard = DTV6; +- priv->freq_hz = freq - 1750000; ++ priv->freq_offset = 1750000; + b = 6; + } else if (bw <= 7000000) { + priv->video_standard = DTV7; +- priv->freq_hz = freq - 2250000; ++ priv->freq_offset = 2250000; + b = 7; + } else { + priv->video_standard = DTV7_8; +- priv->freq_hz = freq - 2750000; ++ priv->freq_offset = 2750000; + b = 8; + } + dprintk(1, "%s() Bandwidth %dMHz (%d)\n", __func__, +@@ -817,6 +817,8 @@ static int xc5000_set_params(struct dvb_frontend *fe) + return -EINVAL; + } + ++ priv->freq_hz = freq - priv->freq_offset; ++ + dprintk(1, "%s() frequency=%d (compensated to %d)\n", + __func__, freq, priv->freq_hz); + +@@ -1067,7 +1069,7 @@ static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq) + { + struct xc5000_priv *priv = fe->tuner_priv; + dprintk(1, "%s()\n", __func__); +- *freq = priv->freq_hz; ++ *freq = priv->freq_hz + priv->freq_offset; + return 0; + } + +diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c +index dd32dec..1d4b110 100644 +--- a/drivers/media/usb/au0828/au0828-cards.c ++++ b/drivers/media/usb/au0828/au0828-cards.c +@@ -36,6 +36,11 @@ static void hvr950q_cs5340_audio(void *priv, int enable) + au0828_clear(dev, REG_000, 0x10); + } + ++/* ++ * WARNING: There's a quirks table at sound/usb/quirks-table.h ++ * that should also be updated every time a new device with V4L2 support ++ * is added here. ++ */ + struct au0828_board au0828_boards[] = { + [AU0828_BOARD_UNKNOWN] = { + .name = "Unknown board", +diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c +index f615454..7ed75ef 100644 +--- a/drivers/media/usb/au0828/au0828-video.c ++++ b/drivers/media/usb/au0828/au0828-video.c +@@ -787,11 +787,27 @@ static int au0828_i2s_init(struct au0828_dev *dev) + + /* + * Auvitek au0828 analog stream enable +- * Please set interface0 to AS5 before enable the stream + */ + static int au0828_analog_stream_enable(struct au0828_dev *d) + { ++ struct usb_interface *iface; ++ int ret; ++ + dprintk(1, "au0828_analog_stream_enable called\n"); ++ ++ iface = usb_ifnum_to_if(d->usbdev, 0); ++ if (iface && iface->cur_altsetting->desc.bAlternateSetting != 5) { ++ dprintk(1, "Changing intf#0 to alt 5\n"); ++ /* set au0828 interface0 to AS5 here again */ ++ ret = usb_set_interface(d->usbdev, 0, 5); ++ if (ret < 0) { ++ printk(KERN_INFO "Au0828 can't set alt setting to 5!\n"); ++ return -EBUSY; ++ } ++ } ++ ++ /* FIXME: size should be calculated using d->width, d->height */ ++ + au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00); + au0828_writereg(d, 0x106, 0x00); + /* set x position */ +@@ -1002,15 +1018,6 @@ static int au0828_v4l2_open(struct file *filp) + return -ERESTARTSYS; + } + if (dev->users == 0) { +- /* set au0828 interface0 to AS5 here again */ +- ret = usb_set_interface(dev->usbdev, 0, 5); +- if (ret < 0) { +- mutex_unlock(&dev->lock); +- printk(KERN_INFO "Au0828 can't set alternate to 5!\n"); +- kfree(fh); +- return -EBUSY; +- } +- + au0828_analog_stream_enable(dev); + au0828_analog_stream_reset(dev); + +@@ -1252,13 +1259,6 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, + } + } + +- /* set au0828 interface0 to AS5 here again */ +- ret = usb_set_interface(dev->usbdev, 0, 5); +- if (ret < 0) { +- printk(KERN_INFO "Au0828 can't set alt setting to 5!\n"); +- return -EBUSY; +- } +- + au0828_analog_stream_enable(dev); + + return 0; +diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c +index 8ede8ea..88228f7 100644 +--- a/drivers/media/usb/dvb-usb-v2/af9035.c ++++ b/drivers/media/usb/dvb-usb-v2/af9035.c +@@ -1541,6 +1541,10 @@ static const struct usb_device_id af9035_id_table[] = { + &af9035_props, "Leadtek WinFast DTV Dongle Dual", NULL) }, + { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xf900, + &af9035_props, "Hauppauge WinTV-MiniStick 2", NULL) }, ++ { DVB_USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_78E, ++ &af9035_props, "PCTV 78e", RC_MAP_IT913X_V1) }, ++ { DVB_USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_79E, ++ &af9035_props, "PCTV 79e", RC_MAP_IT913X_V2) }, + { } + }; + MODULE_DEVICE_TABLE(usb, af9035_id_table); +diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c +index f674dc0..d2a4e6d 100644 +--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c ++++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c +@@ -350,6 +350,7 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap) + { + struct dvb_usb_device *d = adap_to_d(adap); + struct lme2510_state *lme_int = adap_to_priv(adap); ++ struct usb_host_endpoint *ep; + + lme_int->lme_urb = usb_alloc_urb(0, GFP_ATOMIC); + +@@ -371,6 +372,12 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap) + adap, + 8); + ++ /* Quirk of pipe reporting PIPE_BULK but behaves as interrupt */ ++ ep = usb_pipe_endpoint(d->udev, lme_int->lme_urb->pipe); ++ ++ if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK) ++ lme_int->lme_urb->pipe = usb_rcvbulkpipe(d->udev, 0xa), ++ + lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + usb_submit_urb(lme_int->lme_urb, GFP_ATOMIC); +diff --git a/drivers/media/usb/dvb-usb/af9005.c b/drivers/media/usb/dvb-usb/af9005.c +index af176b6..e6d3561 100644 +--- a/drivers/media/usb/dvb-usb/af9005.c ++++ b/drivers/media/usb/dvb-usb/af9005.c +@@ -1081,9 +1081,12 @@ static int __init af9005_usb_module_init(void) + err("usb_register failed. (%d)", result); + return result; + } ++#if IS_MODULE(CONFIG_DVB_USB_AF9005) || defined(CONFIG_DVB_USB_AF9005_REMOTE) ++ /* FIXME: convert to todays kernel IR infrastructure */ + rc_decode = symbol_request(af9005_rc_decode); + rc_keys = symbol_request(rc_map_af9005_table); + rc_keys_size = symbol_request(rc_map_af9005_table_size); ++#endif + if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) { + err("af9005_rc_decode function not found, disabling remote"); + af9005_properties.rc.legacy.rc_query = NULL; +diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c +index dfdfa77..c39f7d3 100644 +--- a/drivers/media/usb/em28xx/em28xx-audio.c ++++ b/drivers/media/usb/em28xx/em28xx-audio.c +@@ -814,7 +814,7 @@ static int em28xx_audio_urb_init(struct em28xx *dev) + if (urb_size > ep_size * npackets) + npackets = DIV_ROUND_UP(urb_size, ep_size); + +- em28xx_info("Number of URBs: %d, with %d packets and %d size", ++ em28xx_info("Number of URBs: %d, with %d packets and %d size\n", + num_urb, npackets, urb_size); + + /* Estimate the bytes per period */ +@@ -974,7 +974,7 @@ static int em28xx_audio_fini(struct em28xx *dev) + return 0; + } + +- em28xx_info("Closing audio extension"); ++ em28xx_info("Closing audio extension\n"); + + if (dev->adev.sndcard) { + snd_card_disconnect(dev->adev.sndcard); +diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c +index 4d97a76..c1a3f8f 100644 +--- a/drivers/media/usb/em28xx/em28xx-cards.c ++++ b/drivers/media/usb/em28xx/em28xx-cards.c +@@ -2993,16 +2993,6 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, + } + } + +- if (dev->chip_id == CHIP_ID_EM2870 || +- dev->chip_id == CHIP_ID_EM2874 || +- dev->chip_id == CHIP_ID_EM28174 || +- dev->chip_id == CHIP_ID_EM28178) { +- /* Digital only device - don't load any alsa module */ +- dev->audio_mode.has_audio = false; +- dev->has_audio_class = false; +- dev->has_alsa_audio = false; +- } +- + if (chip_name != default_chip_name) + printk(KERN_INFO DRIVER_NAME + ": chip ID is %s\n", chip_name); +@@ -3272,7 +3262,6 @@ static int em28xx_usb_probe(struct usb_interface *interface, + dev->alt = -1; + dev->is_audio_only = has_audio && !(has_video || has_dvb); + dev->has_alsa_audio = has_audio; +- dev->audio_mode.has_audio = has_audio; + dev->has_video = has_video; + dev->ifnum = ifnum; + +diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c +index 898fb9b..97fd881 100644 +--- a/drivers/media/usb/em28xx/em28xx-core.c ++++ b/drivers/media/usb/em28xx/em28xx-core.c +@@ -506,8 +506,18 @@ int em28xx_audio_setup(struct em28xx *dev) + int vid1, vid2, feat, cfg; + u32 vid; + +- if (!dev->audio_mode.has_audio) ++ if (dev->chip_id == CHIP_ID_EM2870 || ++ dev->chip_id == CHIP_ID_EM2874 || ++ dev->chip_id == CHIP_ID_EM28174 || ++ dev->chip_id == CHIP_ID_EM28178) { ++ /* Digital only device - don't load any alsa module */ ++ dev->audio_mode.has_audio = false; ++ dev->has_audio_class = false; ++ dev->has_alsa_audio = false; + return 0; ++ } ++ ++ dev->audio_mode.has_audio = true; + + /* See how this device is configured */ + cfg = em28xx_read_reg(dev, EM28XX_R00_CHIPCFG); +diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c +index 1373cfa..ec2ebe9 100644 +--- a/drivers/media/usb/em28xx/em28xx-dvb.c ++++ b/drivers/media/usb/em28xx/em28xx-dvb.c +@@ -1468,7 +1468,7 @@ static int em28xx_dvb_fini(struct em28xx *dev) + return 0; + } + +- em28xx_info("Closing DVB extension"); ++ em28xx_info("Closing DVB extension\n"); + + if (dev->dvb) { + struct em28xx_dvb *dvb = dev->dvb; +diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c +index 18f65d8..dd59c00 100644 +--- a/drivers/media/usb/em28xx/em28xx-input.c ++++ b/drivers/media/usb/em28xx/em28xx-input.c +@@ -810,7 +810,7 @@ static int em28xx_ir_fini(struct em28xx *dev) + return 0; + } + +- em28xx_info("Closing input extension"); ++ em28xx_info("Closing input extension\n"); + + em28xx_shutdown_buttons(dev); + +diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c +index c3c9289..0e8d085 100644 +--- a/drivers/media/usb/em28xx/em28xx-video.c ++++ b/drivers/media/usb/em28xx/em28xx-video.c +@@ -953,13 +953,16 @@ static int em28xx_stop_streaming(struct vb2_queue *vq) + } + + spin_lock_irqsave(&dev->slock, flags); ++ if (dev->usb_ctl.vid_buf != NULL) { ++ vb2_buffer_done(&dev->usb_ctl.vid_buf->vb, VB2_BUF_STATE_ERROR); ++ dev->usb_ctl.vid_buf = NULL; ++ } + while (!list_empty(&vidq->active)) { + struct em28xx_buffer *buf; + buf = list_entry(vidq->active.next, struct em28xx_buffer, list); + list_del(&buf->list); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + } +- dev->usb_ctl.vid_buf = NULL; + spin_unlock_irqrestore(&dev->slock, flags); + + return 0; +@@ -981,13 +984,16 @@ int em28xx_stop_vbi_streaming(struct vb2_queue *vq) + } + + spin_lock_irqsave(&dev->slock, flags); ++ if (dev->usb_ctl.vbi_buf != NULL) { ++ vb2_buffer_done(&dev->usb_ctl.vbi_buf->vb, VB2_BUF_STATE_ERROR); ++ dev->usb_ctl.vbi_buf = NULL; ++ } + while (!list_empty(&vbiq->active)) { + struct em28xx_buffer *buf; + buf = list_entry(vbiq->active.next, struct em28xx_buffer, list); + list_del(&buf->list); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + } +- dev->usb_ctl.vbi_buf = NULL; + spin_unlock_irqrestore(&dev->slock, flags); + + return 0; +@@ -1894,7 +1900,7 @@ static int em28xx_v4l2_fini(struct em28xx *dev) + return 0; + } + +- em28xx_info("Closing video extension"); ++ em28xx_info("Closing video extension\n"); + + mutex_lock(&dev->lock); + +diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c +index 0500c417..6bce01a 100644 +--- a/drivers/media/usb/hdpvr/hdpvr-video.c ++++ b/drivers/media/usb/hdpvr/hdpvr-video.c +@@ -82,7 +82,7 @@ static void hdpvr_read_bulk_callback(struct urb *urb) + } + + /*=========================================================================*/ +-/* bufffer bits */ ++/* buffer bits */ + + /* function expects dev->io_mutex to be hold by caller */ + int hdpvr_cancel_queue(struct hdpvr_device *dev) +@@ -926,7 +926,7 @@ static int hdpvr_s_ctrl(struct v4l2_ctrl *ctrl) + case V4L2_CID_MPEG_AUDIO_ENCODING: + if (dev->flags & HDPVR_FLAG_AC3_CAP) { + opt->audio_codec = ctrl->val; +- return hdpvr_set_audio(dev, opt->audio_input, ++ return hdpvr_set_audio(dev, opt->audio_input + 1, + opt->audio_codec); + } + return 0; +@@ -1198,7 +1198,7 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, + v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops, + V4L2_CID_MPEG_AUDIO_ENCODING, + ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : V4L2_MPEG_AUDIO_ENCODING_AAC, +- 0x7, V4L2_MPEG_AUDIO_ENCODING_AAC); ++ 0x7, ac3 ? dev->options.audio_codec : V4L2_MPEG_AUDIO_ENCODING_AAC); + v4l2_ctrl_new_std_menu(hdl, &hdpvr_ctrl_ops, + V4L2_CID_MPEG_VIDEO_ENCODING, + V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 0x3, +diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c +index c45c988..4572530 100644 +--- a/drivers/media/usb/stk1160/stk1160-v4l.c ++++ b/drivers/media/usb/stk1160/stk1160-v4l.c +@@ -244,6 +244,11 @@ static int stk1160_stop_streaming(struct stk1160 *dev) + if (mutex_lock_interruptible(&dev->v4l_lock)) + return -ERESTARTSYS; + ++ /* ++ * Once URBs are cancelled, the URB complete handler ++ * won't be running. This is required to safely release the ++ * current buffer (dev->isoc_ctl.buf). ++ */ + stk1160_cancel_isoc(dev); + + /* +@@ -624,8 +629,16 @@ void stk1160_clear_queue(struct stk1160 *dev) + stk1160_info("buffer [%p/%d] aborted\n", + buf, buf->vb.v4l2_buf.index); + } +- /* It's important to clear current buffer */ +- dev->isoc_ctl.buf = NULL; ++ ++ /* It's important to release the current buffer */ ++ if (dev->isoc_ctl.buf) { ++ buf = dev->isoc_ctl.buf; ++ dev->isoc_ctl.buf = NULL; ++ ++ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); ++ stk1160_info("buffer [%p/%d] aborted\n", ++ buf, buf->vb.v4l2_buf.index); ++ } + spin_unlock_irqrestore(&dev->buf_lock, flags); + } + +diff --git a/drivers/media/usb/ttusb-dec/ttusbdecfe.c b/drivers/media/usb/ttusb-dec/ttusbdecfe.c +index 5c45c9d..9c29552 100644 +--- a/drivers/media/usb/ttusb-dec/ttusbdecfe.c ++++ b/drivers/media/usb/ttusb-dec/ttusbdecfe.c +@@ -156,6 +156,9 @@ static int ttusbdecfe_dvbs_diseqc_send_master_cmd(struct dvb_frontend* fe, struc + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 }; + ++ if (cmd->msg_len > sizeof(b) - 4) ++ return -EINVAL; ++ + memcpy(&b[4], cmd->msg, cmd->msg_len); + + state->config->send_command(fe, 0x72, +diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c +index c3bb250..4531441 100644 +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -1603,12 +1603,12 @@ static void uvc_delete(struct uvc_device *dev) + { + struct list_head *p, *n; + +- usb_put_intf(dev->intf); +- usb_put_dev(dev->udev); +- + uvc_status_cleanup(dev); + uvc_ctrl_cleanup_device(dev); + ++ usb_put_intf(dev->intf); ++ usb_put_dev(dev->udev); ++ + if (dev->vdev.dev) + v4l2_device_unregister(&dev->vdev); + #ifdef CONFIG_MEDIA_CONTROLLER +@@ -2210,6 +2210,15 @@ static struct usb_device_id uvc_ids[] = { + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_DEF }, ++ /* Dell XPS M1330 (OmniVision OV7670 webcam) */ ++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE ++ | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x05a9, ++ .idProduct = 0x7670, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = 1, ++ .bInterfaceProtocol = 0, ++ .driver_info = UVC_QUIRK_PROBE_DEF }, + /* Apple Built-In iSight */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, +diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c +index 433d6d7..c5521ce 100644 +--- a/drivers/media/v4l2-core/v4l2-common.c ++++ b/drivers/media/v4l2-core/v4l2-common.c +@@ -431,16 +431,13 @@ static unsigned int clamp_align(unsigned int x, unsigned int min, + /* Bits that must be zero to be aligned */ + unsigned int mask = ~((1 << align) - 1); + ++ /* Clamp to aligned min and max */ ++ x = clamp(x, (min + ~mask) & mask, max & mask); ++ + /* Round to nearest aligned value */ + if (align) + x = (x + (1 << (align - 1))) & mask; + +- /* Clamp to aligned value of min and max */ +- if (x < min) +- x = (min + ~mask) & mask; +- else if (x > max) +- x = max & mask; +- + return x; + } + +diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c +index a2e2579..78d99b1 100644 +--- a/drivers/media/v4l2-core/v4l2-dv-timings.c ++++ b/drivers/media/v4l2-core/v4l2-dv-timings.c +@@ -595,10 +595,10 @@ struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait) + aspect.denominator = 9; + } else if (ratio == 34) { + aspect.numerator = 4; +- aspect.numerator = 3; ++ aspect.denominator = 3; + } else if (ratio == 68) { + aspect.numerator = 15; +- aspect.numerator = 9; ++ aspect.denominator = 9; + } else { + aspect.numerator = hor_landscape + 99; + aspect.denominator = 100; +diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c +index a127925..06faea4 100644 +--- a/drivers/media/v4l2-core/videobuf2-core.c ++++ b/drivers/media/v4l2-core/videobuf2-core.c +@@ -745,6 +745,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) + * to the userspace. + */ + req->count = allocated_buffers; ++ q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type); + + return 0; + } +@@ -793,6 +794,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create + memset(q->plane_sizes, 0, sizeof(q->plane_sizes)); + memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx)); + q->memory = create->memory; ++ q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type); + } + + num_buffers = min(create->count, VIDEO_MAX_FRAME - q->num_buffers); +@@ -1447,6 +1449,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) + * dequeued in dqbuf. + */ + list_add_tail(&vb->queued_entry, &q->queued_list); ++ q->waiting_for_buffers = false; + vb->state = VB2_BUF_STATE_QUEUED; + + /* +@@ -1841,6 +1844,7 @@ static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type) + * and videobuf, effectively returning control over them to userspace. + */ + __vb2_queue_cancel(q); ++ q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type); + + dprintk(3, "Streamoff successful\n"); + return 0; +@@ -2150,9 +2154,16 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) + } + + /* +- * There is nothing to wait for if no buffers have already been queued. ++ * There is nothing to wait for if the queue isn't streaming. + */ +- if (list_empty(&q->queued_list)) ++ if (!vb2_is_streaming(q)) ++ return res | POLLERR; ++ /* ++ * For compatibility with vb1: if QBUF hasn't been called yet, then ++ * return POLLERR as well. This only affects capture queues, output ++ * queues will always initialize waiting_for_buffers to false. ++ */ ++ if (q->waiting_for_buffers) + return res | POLLERR; + + if (list_empty(&q->done_list)) +diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c +index fc145d2..922a750 100644 +--- a/drivers/memstick/core/mspro_block.c ++++ b/drivers/memstick/core/mspro_block.c +@@ -758,7 +758,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error) + + if (error || (card->current_mrq.tpc == MSPRO_CMD_STOP)) { + if (msb->data_dir == READ) { +- for (cnt = 0; cnt < msb->current_seg; cnt++) ++ for (cnt = 0; cnt < msb->current_seg; cnt++) { + t_len += msb->req_sg[cnt].length + / msb->page_size; + +@@ -766,6 +766,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error) + t_len += msb->current_page - 1; + + t_len *= msb->page_size; ++ } + } + } else + t_len = blk_rq_bytes(msb->block_req); +diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c +index 5653e50..424f51d 100644 +--- a/drivers/message/fusion/mptspi.c ++++ b/drivers/message/fusion/mptspi.c +@@ -1422,6 +1422,11 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) + goto out_mptspi_probe; + } + ++ /* VMWare emulation doesn't properly implement WRITE_SAME ++ */ ++ if (pdev->subsystem_vendor == 0x15AD) ++ sh->no_write_same = 1; ++ + spin_lock_irqsave(&ioc->FreeQlock, flags); + + /* Attach the SCSI Host to the IOC structure +diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c +index 38917a8..2df3cbc 100644 +--- a/drivers/mfd/kempld-core.c ++++ b/drivers/mfd/kempld-core.c +@@ -629,7 +629,7 @@ static int __init kempld_init(void) + if (force_device_id[0]) { + for (id = kempld_dmi_table; id->matches[0].slot != DMI_NONE; id++) + if (strstr(id->ident, force_device_id)) +- if (id->callback && id->callback(id)) ++ if (id->callback && !id->callback(id)) + break; + if (id->matches[0].slot == DMI_NONE) + return -ENODEV; +diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c +index 90b630c..0aefe50 100644 +--- a/drivers/mfd/omap-usb-host.c ++++ b/drivers/mfd/omap-usb-host.c +@@ -445,7 +445,7 @@ static unsigned omap_usbhs_rev1_hostconfig(struct usbhs_hcd_omap *omap, + + for (i = 0; i < omap->nports; i++) { + if (is_ehci_phy_mode(pdata->port_mode[i])) { +- reg &= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; ++ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; + break; + } + } +diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c +index 1d15735..89b4c42 100644 +--- a/drivers/mfd/rtsx_pcr.c ++++ b/drivers/mfd/rtsx_pcr.c +@@ -1177,7 +1177,7 @@ static int rtsx_pci_probe(struct pci_dev *pcidev, + pcr->msi_en = msi_en; + if (pcr->msi_en) { + ret = pci_enable_msi(pcidev); +- if (ret < 0) ++ if (ret) + pcr->msi_en = false; + } + +diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c +index 11c19e5..48579e5 100644 +--- a/drivers/mfd/tc6393xb.c ++++ b/drivers/mfd/tc6393xb.c +@@ -263,6 +263,17 @@ static int tc6393xb_ohci_disable(struct platform_device *dev) + return 0; + } + ++static int tc6393xb_ohci_suspend(struct platform_device *dev) ++{ ++ struct tc6393xb_platform_data *tcpd = dev_get_platdata(dev->dev.parent); ++ ++ /* We can't properly store/restore OHCI state, so fail here */ ++ if (tcpd->resume_restore) ++ return -EBUSY; ++ ++ return tc6393xb_ohci_disable(dev); ++} ++ + static int tc6393xb_fb_enable(struct platform_device *dev) + { + struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent); +@@ -403,7 +414,7 @@ static struct mfd_cell tc6393xb_cells[] = { + .num_resources = ARRAY_SIZE(tc6393xb_ohci_resources), + .resources = tc6393xb_ohci_resources, + .enable = tc6393xb_ohci_enable, +- .suspend = tc6393xb_ohci_disable, ++ .suspend = tc6393xb_ohci_suspend, + .resume = tc6393xb_ohci_enable, + .disable = tc6393xb_ohci_disable, + }, +diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c +index d4e8604..e87a248 100644 +--- a/drivers/mfd/ti_am335x_tscadc.c ++++ b/drivers/mfd/ti_am335x_tscadc.c +@@ -54,11 +54,11 @@ void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val) + unsigned long flags; + + spin_lock_irqsave(&tsadc->reg_lock, flags); +- tsadc->reg_se_cache = val; ++ tsadc->reg_se_cache |= val; + if (tsadc->adc_waiting) + wake_up(&tsadc->reg_se_wait); + else if (!tsadc->adc_in_use) +- tscadc_writel(tsadc, REG_SE, val); ++ tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); + + spin_unlock_irqrestore(&tsadc->reg_lock, flags); + } +@@ -97,6 +97,7 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc) + void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val) + { + spin_lock_irq(&tsadc->reg_lock); ++ tsadc->reg_se_cache |= val; + am335x_tscadc_need_adc(tsadc); + + tscadc_writel(tsadc, REG_SE, val); +diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c +index 6b1a6ef..0c3a647 100644 +--- a/drivers/misc/genwqe/card_utils.c ++++ b/drivers/misc/genwqe/card_utils.c +@@ -490,6 +490,8 @@ int genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m, void *uaddr, + m->nr_pages, + 1, /* write by caller */ + m->page_list); /* ptrs to pages */ ++ if (rc < 0) ++ goto fail_get_user_pages; + + /* assumption: get_user_pages can be killed by signals. */ + if (rc < m->nr_pages) { +diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c +index 4bc7d62..9a07bba 100644 +--- a/drivers/misc/mei/bus.c ++++ b/drivers/misc/mei/bus.c +@@ -71,7 +71,7 @@ static int mei_cl_device_probe(struct device *dev) + + dev_dbg(dev, "Device probe\n"); + +- strncpy(id.name, dev_name(dev), sizeof(id.name)); ++ strlcpy(id.name, dev_name(dev), sizeof(id.name)); + + return driver->probe(device, &id); + } +diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c +index 5a9bfa7..540fe11 100644 +--- a/drivers/misc/mei/client.c ++++ b/drivers/misc/mei/client.c +@@ -459,6 +459,7 @@ int mei_cl_disconnect(struct mei_cl *cl) + cl_err(dev, cl, "failed to disconnect.\n"); + goto free; + } ++ cl->timer_count = MEI_CONNECT_TIMEOUT; + mdelay(10); /* Wait for hardware disconnection ready */ + list_add_tail(&cb->list, &dev->ctrl_rd_list.list); + } else { +@@ -563,6 +564,7 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file) + cl->timer_count = MEI_CONNECT_TIMEOUT; + list_add_tail(&cb->list, &dev->ctrl_rd_list.list); + } else { ++ cl->state = MEI_FILE_INITIALIZING; + list_add_tail(&cb->list, &dev->ctrl_wr_list.list); + } + +diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c +index cdd31c2..b296538 100644 +--- a/drivers/misc/mei/init.c ++++ b/drivers/misc/mei/init.c +@@ -275,6 +275,8 @@ void mei_stop(struct mei_device *dev) + + dev->dev_state = MEI_DEV_POWER_DOWN; + mei_reset(dev); ++ /* move device to disabled state unconditionally */ ++ dev->dev_state = MEI_DEV_DISABLED; + + mutex_unlock(&dev->device_lock); + +diff --git a/drivers/misc/mei/nfc.c b/drivers/misc/mei/nfc.c +index a58320c..3114901 100644 +--- a/drivers/misc/mei/nfc.c ++++ b/drivers/misc/mei/nfc.c +@@ -342,9 +342,10 @@ static int mei_nfc_send(struct mei_cl_device *cldev, u8 *buf, size_t length) + ndev = (struct mei_nfc_dev *) cldev->priv_data; + dev = ndev->cl->dev; + ++ err = -ENOMEM; + mei_buf = kzalloc(length + MEI_NFC_HEADER_SIZE, GFP_KERNEL); + if (!mei_buf) +- return -ENOMEM; ++ goto out; + + hdr = (struct mei_nfc_hci_hdr *) mei_buf; + hdr->cmd = MEI_NFC_CMD_HCI_SEND; +@@ -354,12 +355,9 @@ static int mei_nfc_send(struct mei_cl_device *cldev, u8 *buf, size_t length) + hdr->data_size = length; + + memcpy(mei_buf + MEI_NFC_HEADER_SIZE, buf, length); +- + err = __mei_cl_send(ndev->cl, mei_buf, length + MEI_NFC_HEADER_SIZE); + if (err < 0) +- return err; +- +- kfree(mei_buf); ++ goto out; + + if (!wait_event_interruptible_timeout(ndev->send_wq, + ndev->recv_req_id == ndev->req_id, HZ)) { +@@ -368,7 +366,8 @@ static int mei_nfc_send(struct mei_cl_device *cldev, u8 *buf, size_t length) + } else { + ndev->req_id++; + } +- ++out: ++ kfree(mei_buf); + return err; + } + +diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c +index 7b5424f..d71f5ef 100644 +--- a/drivers/mmc/card/block.c ++++ b/drivers/mmc/card/block.c +@@ -205,6 +205,8 @@ static ssize_t power_ro_lock_show(struct device *dev, + + ret = snprintf(buf, PAGE_SIZE, "%d\n", locked); + ++ mmc_blk_put(md); ++ + return ret; + } + +@@ -260,7 +262,7 @@ static ssize_t force_ro_show(struct device *dev, struct device_attribute *attr, + int ret; + struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev)); + +- ret = snprintf(buf, PAGE_SIZE, "%d", ++ ret = snprintf(buf, PAGE_SIZE, "%d\n", + get_disk_ro(dev_to_disk(dev)) ^ + md->read_only); + mmc_blk_put(md); +@@ -951,6 +953,18 @@ static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type) + md->reset_done &= ~type; + } + ++int mmc_access_rpmb(struct mmc_queue *mq) ++{ ++ struct mmc_blk_data *md = mq->data; ++ /* ++ * If this is a RPMB partition access, return ture ++ */ ++ if (md && md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB) ++ return true; ++ ++ return false; ++} ++ + static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) + { + struct mmc_blk_data *md = mq->data; +@@ -1849,9 +1863,11 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) + break; + case MMC_BLK_CMD_ERR: + ret = mmc_blk_cmd_err(md, card, brq, req, ret); +- if (!mmc_blk_reset(md, card->host, type)) +- break; +- goto cmd_abort; ++ if (mmc_blk_reset(md, card->host, type)) ++ goto cmd_abort; ++ if (!ret) ++ goto start_new_req; ++ break; + case MMC_BLK_RETRY: + if (retry++ < 5) + break; +diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c +index 3e049c1..6ceede0 100644 +--- a/drivers/mmc/card/queue.c ++++ b/drivers/mmc/card/queue.c +@@ -38,7 +38,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req) + return BLKPREP_KILL; + } + +- if (mq && mmc_card_removed(mq->card)) ++ if (mq && (mmc_card_removed(mq->card) || mmc_access_rpmb(mq))) + return BLKPREP_KILL; + + req->cmd_flags |= REQ_DONTPREP; +diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h +index 5752d50..99e6521 100644 +--- a/drivers/mmc/card/queue.h ++++ b/drivers/mmc/card/queue.h +@@ -73,4 +73,6 @@ extern void mmc_queue_bounce_post(struct mmc_queue_req *); + extern int mmc_packed_init(struct mmc_queue *, struct mmc_card *); + extern void mmc_packed_clean(struct mmc_queue *); + ++extern int mmc_access_rpmb(struct mmc_queue *); ++ + #endif +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index c43e6c8..daca58b 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -2699,6 +2699,7 @@ int mmc_pm_notify(struct notifier_block *notify_block, + switch (mode) { + case PM_HIBERNATION_PREPARE: + case PM_SUSPEND_PREPARE: ++ case PM_RESTORE_PREPARE: + spin_lock_irqsave(&host->lock, flags); + host->rescan_disable = 1; + spin_unlock_irqrestore(&host->lock, flags); +diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c +index 42706ea..201ce37 100644 +--- a/drivers/mmc/host/atmel-mci.c ++++ b/drivers/mmc/host/atmel-mci.c +@@ -1300,7 +1300,7 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + + if (ios->clock) { + unsigned int clock_min = ~0U; +- u32 clkdiv; ++ int clkdiv; + + clk_prepare(host->mck); + unprepare_clk = true; +@@ -1329,7 +1329,12 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) + /* Calculate clock divider */ + if (host->caps.has_odd_clk_div) { + clkdiv = DIV_ROUND_UP(host->bus_hz, clock_min) - 2; +- if (clkdiv > 511) { ++ if (clkdiv < 0) { ++ dev_warn(&mmc->class_dev, ++ "clock %u too fast; using %lu\n", ++ clock_min, host->bus_hz / 2); ++ clkdiv = 0; ++ } else if (clkdiv > 511) { + dev_warn(&mmc->class_dev, + "clock %u too slow; using %lu\n", + clock_min, host->bus_hz / (511 + 2)); +diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c +index 054e03d..5d59c92 100644 +--- a/drivers/mmc/host/dw_mmc.c ++++ b/drivers/mmc/host/dw_mmc.c +@@ -632,6 +632,13 @@ static void dw_mci_ctrl_rd_thld(struct dw_mci *host, struct mmc_data *data) + + WARN_ON(!(data->flags & MMC_DATA_READ)); + ++ /* ++ * CDTHRCTL doesn't exist prior to 240A (in fact that register offset is ++ * in the FIFO region, so we really shouldn't access it). ++ */ ++ if (host->verid < DW_MMC_240A) ++ return; ++ + if (host->timing != MMC_TIMING_MMC_HS200 && + host->timing != MMC_TIMING_UHS_SDR104) + goto disable; +diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c +index 7e18661..ca297d7 100644 +--- a/drivers/mmc/host/rtsx_pci_sdmmc.c ++++ b/drivers/mmc/host/rtsx_pci_sdmmc.c +@@ -342,6 +342,13 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, + } + + if (rsp_type == SD_RSP_TYPE_R2) { ++ /* ++ * The controller offloads the last byte {CRC-7, end bit 1'b1} ++ * of response type R2. Assign dummy CRC, 0, and end bit to the ++ * byte(ptr[16], goes into the LSB of resp[3] later). ++ */ ++ ptr[16] = 1; ++ + for (i = 0; i < 4; i++) { + cmd->resp[i] = get_unaligned_be32(ptr + 1 + i * 4); + dev_dbg(sdmmc_dev(host), "cmd->resp[%d] = 0x%08x\n", +diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h +index 5c0f27f..28f61b7 100644 +--- a/drivers/mmc/host/sdhci-esdhc.h ++++ b/drivers/mmc/host/sdhci-esdhc.h +@@ -46,6 +46,6 @@ + #define ESDHC_DMA_SYSCTL 0x40c + #define ESDHC_DMA_SNOOP 0x00000040 + +-#define ESDHC_HOST_CONTROL_RES 0x05 ++#define ESDHC_HOST_CONTROL_RES 0x01 + + #endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */ +diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c +index f49666b..257e9ca 100644 +--- a/drivers/mmc/host/sdhci-pci-o2micro.c ++++ b/drivers/mmc/host/sdhci-pci-o2micro.c +@@ -88,8 +88,6 @@ void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip) + return; + scratch_32 &= ~((1 << 21) | (1 << 30)); + +- /* Set RTD3 function disabled */ +- scratch_32 |= ((1 << 29) | (1 << 28)); + pci_write_config_dword(chip->pdev, O2_SD_FUNC_REG3, scratch_32); + + /* Set L1 Entrance Timer */ +diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c +index ba4eaf0..19de28b 100644 +--- a/drivers/mmc/host/sdhci-pci.c ++++ b/drivers/mmc/host/sdhci-pci.c +@@ -103,6 +103,10 @@ static const struct sdhci_pci_fixes sdhci_cafe = { + SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, + }; + ++static const struct sdhci_pci_fixes sdhci_intel_qrk = { ++ .quirks = SDHCI_QUIRK_NO_HISPD_BIT, ++}; ++ + static int mrst_hc_probe_slot(struct sdhci_pci_slot *slot) + { + slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA; +@@ -733,6 +737,14 @@ static const struct pci_device_id pci_ids[] = { + + { + .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_QRK_SD, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_intel_qrk, ++ }, ++ ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_MRST_SD0, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, +diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h +index 6d71871..c101477 100644 +--- a/drivers/mmc/host/sdhci-pci.h ++++ b/drivers/mmc/host/sdhci-pci.h +@@ -17,6 +17,7 @@ + #define PCI_DEVICE_ID_INTEL_CLV_SDIO2 0x08fb + #define PCI_DEVICE_ID_INTEL_CLV_EMMC0 0x08e5 + #define PCI_DEVICE_ID_INTEL_CLV_EMMC1 0x08e6 ++#define PCI_DEVICE_ID_INTEL_QRK_SD 0x08A7 + + /* + * PCI registers +diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c +index 4c5e52f..d70b8aa3 100644 +--- a/drivers/mmc/host/sdhci-pxav3.c ++++ b/drivers/mmc/host/sdhci-pxav3.c +@@ -204,8 +204,8 @@ static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev) + if (!pdata) + return NULL; + +- of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles); +- if (clk_delay_cycles > 0) ++ if (!of_property_read_u32(np, "mrvl,clk-delay-cycles", ++ &clk_delay_cycles)) + pdata->clk_delay_cycles = clk_delay_cycles; + + return pdata; +@@ -260,6 +260,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) + goto err_of_parse; + sdhci_get_of_property(pdev); + pdata = pxav3_get_mmc_pdata(dev); ++ pdev->dev.platform_data = pdata; + } else if (pdata) { + /* on-chip device */ + if (pdata->flags & PXA_FLAG_CARD_PERMANENT) +diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c +index 38e1cd4..af7507b 100644 +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c +@@ -1310,6 +1310,8 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) + + sdhci_runtime_pm_get(host); + ++ present = mmc_gpio_get_cd(host->mmc); ++ + spin_lock_irqsave(&host->lock, flags); + + WARN_ON(host->mrq != NULL); +@@ -1338,7 +1340,6 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) + * zero: cd-gpio is used, and card is removed + * one: cd-gpio is used, and card is present + */ +- present = mmc_gpio_get_cd(host->mmc); + if (present < 0) { + /* If polling, assume that the card is always present. */ + if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) +@@ -2049,15 +2050,18 @@ static void sdhci_card_event(struct mmc_host *mmc) + { + struct sdhci_host *host = mmc_priv(mmc); + unsigned long flags; ++ int present; + + /* First check if client has provided their own card event */ + if (host->ops->card_event) + host->ops->card_event(host); + ++ present = sdhci_do_get_cd(host); ++ + spin_lock_irqsave(&host->lock, flags); + + /* Check host->mrq first in case we are runtime suspended */ +- if (host->mrq && !sdhci_do_get_cd(host)) { ++ if (host->mrq && !present) { + pr_err("%s: Card removed during transfer!\n", + mmc_hostname(host->mmc)); + pr_err("%s: Resetting controller.\n", +diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c +index 54730f4..9c208fd 100644 +--- a/drivers/mmc/host/sh_mmcif.c ++++ b/drivers/mmc/host/sh_mmcif.c +@@ -1401,7 +1401,7 @@ static int sh_mmcif_probe(struct platform_device *pdev) + host = mmc_priv(mmc); + host->mmc = mmc; + host->addr = reg; +- host->timeout = msecs_to_jiffies(1000); ++ host->timeout = msecs_to_jiffies(10000); + host->ccs_enable = !pd || !pd->ccs_unsupported; + host->clk_ctrl2_enable = pd && pd->clk_ctrl2_present; + +diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c +index 19d6372..71e4f6c 100644 +--- a/drivers/mtd/ftl.c ++++ b/drivers/mtd/ftl.c +@@ -1075,7 +1075,6 @@ static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) + return; + } + +- ftl_freepart(partition); + kfree(partition); + } + +diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c +index f8a7dd1..70a3db3 100644 +--- a/drivers/mtd/maps/dc21285.c ++++ b/drivers/mtd/maps/dc21285.c +@@ -38,9 +38,9 @@ static void nw_en_write(void) + * we want to write a bit pattern XXX1 to Xilinx to enable + * the write gate, which will be open for about the next 2ms. + */ +- spin_lock_irqsave(&nw_gpio_lock, flags); ++ raw_spin_lock_irqsave(&nw_gpio_lock, flags); + nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE); +- spin_unlock_irqrestore(&nw_gpio_lock, flags); ++ raw_spin_unlock_irqrestore(&nw_gpio_lock, flags); + + /* + * let the ISA bus to catch on... +diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c +index 5073cbc..32d5e40 100644 +--- a/drivers/mtd/mtd_blkdevs.c ++++ b/drivers/mtd/mtd_blkdevs.c +@@ -199,6 +199,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode) + return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ + + mutex_lock(&dev->lock); ++ mutex_lock(&mtd_table_mutex); + + if (dev->open) + goto unlock; +@@ -222,6 +223,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode) + + unlock: + dev->open++; ++ mutex_unlock(&mtd_table_mutex); + mutex_unlock(&dev->lock); + blktrans_dev_put(dev); + return ret; +@@ -232,6 +234,7 @@ error_release: + error_put: + module_put(dev->tr->owner); + kref_put(&dev->ref, blktrans_dev_release); ++ mutex_unlock(&mtd_table_mutex); + mutex_unlock(&dev->lock); + blktrans_dev_put(dev); + return ret; +@@ -245,6 +248,7 @@ static void blktrans_release(struct gendisk *disk, fmode_t mode) + return; + + mutex_lock(&dev->lock); ++ mutex_lock(&mtd_table_mutex); + + if (--dev->open) + goto unlock; +@@ -258,6 +262,7 @@ static void blktrans_release(struct gendisk *disk, fmode_t mode) + __put_mtd_device(dev->mtd); + } + unlock: ++ mutex_unlock(&mtd_table_mutex); + mutex_unlock(&dev->lock); + blktrans_dev_put(dev); + } +diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c +index 9715a7b..efc542d 100644 +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -2000,7 +2000,7 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd, + oob += chip->ecc.prepad; + } + +- chip->read_buf(mtd, oob, eccbytes); ++ chip->write_buf(mtd, oob, eccbytes); + oob += eccbytes; + + if (chip->ecc.postpad) { +@@ -3063,7 +3063,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, + int *busw) + { + struct nand_onfi_params *p = &chip->onfi_params; +- int i; ++ int i, j; + int val; + + /* Try ONFI for unknown chip or LP */ +@@ -3072,18 +3072,10 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, + chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I') + return 0; + +- /* +- * ONFI must be probed in 8-bit mode or with NAND_BUSWIDTH_AUTO, not +- * with NAND_BUSWIDTH_16 +- */ +- if (chip->options & NAND_BUSWIDTH_16) { +- pr_err("ONFI cannot be probed in 16-bit mode; aborting\n"); +- return 0; +- } +- + chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); + for (i = 0; i < 3; i++) { +- chip->read_buf(mtd, (uint8_t *)p, sizeof(*p)); ++ for (j = 0; j < sizeof(*p); j++) ++ ((uint8_t *)p)[j] = chip->read_byte(mtd); + if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) == + le16_to_cpu(p->crc)) { + break; +diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c +index 6f55d92..64d8e32 100644 +--- a/drivers/mtd/nand/omap2.c ++++ b/drivers/mtd/nand/omap2.c +@@ -933,7 +933,7 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat, + u32 val; + + val = readl(info->reg.gpmc_ecc_config); +- if (((val >> ECC_CONFIG_CS_SHIFT) & ~CS_MASK) != info->gpmc_cs) ++ if (((val >> ECC_CONFIG_CS_SHIFT) & CS_MASK) != info->gpmc_cs) + return -EINVAL; + + /* read ecc result */ +diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c +index 51e15fd..d058b00 100644 +--- a/drivers/mtd/nand/pxa3xx_nand.c ++++ b/drivers/mtd/nand/pxa3xx_nand.c +@@ -481,6 +481,42 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) + nand_writel(info, NDCR, ndcr | int_mask); + } + ++static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len) ++{ ++ if (info->ecc_bch) { ++ int timeout; ++ ++ /* ++ * According to the datasheet, when reading from NDDB ++ * with BCH enabled, after each 32 bytes reads, we ++ * have to make sure that the NDSR.RDDREQ bit is set. ++ * ++ * Drain the FIFO 8 32 bits reads at a time, and skip ++ * the polling on the last read. ++ */ ++ while (len > 8) { ++ __raw_readsl(info->mmio_base + NDDB, data, 8); ++ ++ for (timeout = 0; ++ !(nand_readl(info, NDSR) & NDSR_RDDREQ); ++ timeout++) { ++ if (timeout >= 5) { ++ dev_err(&info->pdev->dev, ++ "Timeout on RDDREQ while draining the FIFO\n"); ++ return; ++ } ++ ++ mdelay(1); ++ } ++ ++ data += 32; ++ len -= 8; ++ } ++ } ++ ++ __raw_readsl(info->mmio_base + NDDB, data, len); ++} ++ + static void handle_data_pio(struct pxa3xx_nand_info *info) + { + unsigned int do_bytes = min(info->data_size, info->chunk_size); +@@ -497,14 +533,14 @@ static void handle_data_pio(struct pxa3xx_nand_info *info) + DIV_ROUND_UP(info->oob_size, 4)); + break; + case STATE_PIO_READING: +- __raw_readsl(info->mmio_base + NDDB, +- info->data_buff + info->data_buff_pos, +- DIV_ROUND_UP(do_bytes, 4)); ++ drain_fifo(info, ++ info->data_buff + info->data_buff_pos, ++ DIV_ROUND_UP(do_bytes, 4)); + + if (info->oob_size > 0) +- __raw_readsl(info->mmio_base + NDDB, +- info->oob_buff + info->oob_buff_pos, +- DIV_ROUND_UP(info->oob_size, 4)); ++ drain_fifo(info, ++ info->oob_buff + info->oob_buff_pos, ++ DIV_ROUND_UP(info->oob_size, 4)); + break; + default: + dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__, +diff --git a/drivers/mtd/tests/torturetest.c b/drivers/mtd/tests/torturetest.c +index eeab969..b55bc52 100644 +--- a/drivers/mtd/tests/torturetest.c ++++ b/drivers/mtd/tests/torturetest.c +@@ -264,7 +264,9 @@ static int __init tort_init(void) + int i; + void *patt; + +- mtdtest_erase_good_eraseblocks(mtd, bad_ebs, eb, ebcnt); ++ err = mtdtest_erase_good_eraseblocks(mtd, bad_ebs, eb, ebcnt); ++ if (err) ++ goto out; + + /* Check if the eraseblocks contain only 0xFF bytes */ + if (check) { +diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c +index 6f27d9a..21841fe 100644 +--- a/drivers/mtd/ubi/attach.c ++++ b/drivers/mtd/ubi/attach.c +@@ -408,7 +408,7 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, + second_is_newer = !second_is_newer; + } else { + dbg_bld("PEB %d CRC is OK", pnum); +- bitflips = !!err; ++ bitflips |= !!err; + } + mutex_unlock(&ubi->buf_mutex); + +diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c +index 8ca49f2..4cbbd55 100644 +--- a/drivers/mtd/ubi/cdev.c ++++ b/drivers/mtd/ubi/cdev.c +@@ -451,7 +451,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd, + /* Validate the request */ + err = -EINVAL; + if (req.lnum < 0 || req.lnum >= vol->reserved_pebs || +- req.bytes < 0 || req.lnum >= vol->usable_leb_size) ++ req.bytes < 0 || req.bytes > vol->usable_leb_size) + break; + + err = get_exclusive(desc); +diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c +index 0e11671d..930cf2c 100644 +--- a/drivers/mtd/ubi/eba.c ++++ b/drivers/mtd/ubi/eba.c +@@ -1362,7 +1362,8 @@ int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai) + * during re-size. + */ + ubi_move_aeb_to_list(av, aeb, &ai->erase); +- vol->eba_tbl[aeb->lnum] = aeb->pnum; ++ else ++ vol->eba_tbl[aeb->lnum] = aeb->pnum; + } + } + +diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c +index c5dad65..904b451 100644 +--- a/drivers/mtd/ubi/fastmap.c ++++ b/drivers/mtd/ubi/fastmap.c +@@ -330,6 +330,7 @@ static int process_pool_aeb(struct ubi_device *ubi, struct ubi_attach_info *ai, + av = tmp_av; + else { + ubi_err("orphaned volume in fastmap pool!"); ++ kmem_cache_free(ai->aeb_slab_cache, new_aeb); + return UBI_BAD_FASTMAP; + } + +diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c +index f913d70..c4b1af0 100644 +--- a/drivers/mtd/ubi/misc.c ++++ b/drivers/mtd/ubi/misc.c +@@ -74,6 +74,8 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id) + for (i = 0; i < vol->used_ebs; i++) { + int size; + ++ cond_resched(); ++ + if (i == vol->used_ebs - 1) + size = vol->last_eb_bytes; + else +diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c +index ec2c2dc..2a1b6e0 100644 +--- a/drivers/mtd/ubi/upd.c ++++ b/drivers/mtd/ubi/upd.c +@@ -133,6 +133,10 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, + ubi_assert(!vol->updating && !vol->changing_leb); + vol->updating = 1; + ++ vol->upd_buf = vmalloc(ubi->leb_size); ++ if (!vol->upd_buf) ++ return -ENOMEM; ++ + err = set_update_marker(ubi, vol); + if (err) + return err; +@@ -152,14 +156,12 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, + err = clear_update_marker(ubi, vol, 0); + if (err) + return err; ++ ++ vfree(vol->upd_buf); + vol->updating = 0; + return 0; + } + +- vol->upd_buf = vmalloc(ubi->leb_size); +- if (!vol->upd_buf) +- return -ENOMEM; +- + vol->upd_ebs = div_u64(bytes + vol->usable_leb_size - 1, + vol->usable_leb_size); + vol->upd_bytes = bytes; +diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c +index 02317c1..c6b0b07 100644 +--- a/drivers/mtd/ubi/wl.c ++++ b/drivers/mtd/ubi/wl.c +@@ -995,7 +995,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, + int cancel) + { + int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0; +- int vol_id = -1, uninitialized_var(lnum); ++ int vol_id = -1, lnum = -1; + #ifdef CONFIG_MTD_UBI_FASTMAP + int anchor = wrk->anchor; + #endif +@@ -1205,7 +1205,6 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, + + err = do_sync_erase(ubi, e1, vol_id, lnum, 0); + if (err) { +- kmem_cache_free(ubi_wl_entry_slab, e1); + if (e2) + kmem_cache_free(ubi_wl_entry_slab, e2); + goto out_ro; +@@ -1219,10 +1218,8 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, + dbg_wl("PEB %d (LEB %d:%d) was put meanwhile, erase", + e2->pnum, vol_id, lnum); + err = do_sync_erase(ubi, e2, vol_id, lnum, 0); +- if (err) { +- kmem_cache_free(ubi_wl_entry_slab, e2); ++ if (err) + goto out_ro; +- } + } + + dbg_wl("done"); +@@ -1258,10 +1255,9 @@ out_not_moved: + + ubi_free_vid_hdr(ubi, vid_hdr); + err = do_sync_erase(ubi, e2, vol_id, lnum, torture); +- if (err) { +- kmem_cache_free(ubi_wl_entry_slab, e2); ++ if (err) + goto out_ro; +- } ++ + mutex_unlock(&ubi->move_mutex); + return 0; + +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index 494b888..7e5c6a8 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -135,6 +135,7 @@ config MACVLAN + config MACVTAP + tristate "MAC-VLAN based tap driver" + depends on MACVLAN ++ depends on INET + help + This adds a specialized tap character device driver that is based + on the MAC-VLAN network interface, called macvtap. A macvtap device +@@ -205,6 +206,7 @@ config RIONET_RX_SIZE + + config TUN + tristate "Universal TUN/TAP device driver support" ++ depends on INET + select CRC32 + ---help--- + TUN/TAP provides packet reception and transmission for user space +diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c +index dcde560..3177498 100644 +--- a/drivers/net/bonding/bond_3ad.c ++++ b/drivers/net/bonding/bond_3ad.c +@@ -2479,7 +2479,7 @@ out: + return NETDEV_TX_OK; + err_free: + /* no suitable interface, frame not sent */ +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + goto out; + } + +diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c +index e8f133e..c67bbc9 100644 +--- a/drivers/net/bonding/bond_alb.c ++++ b/drivers/net/bonding/bond_alb.c +@@ -1479,7 +1479,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) + } + + /* no suitable interface, frame not sent */ +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + out: + return NETDEV_TX_OK; + } +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 1c5caf5..6f56d07 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -2454,9 +2454,9 @@ static void bond_loadbalance_arp_mon(struct work_struct *work) + if (!rtnl_trylock()) + goto re_arm; + +- if (slave_state_changed) { ++ if (slave_state_changed) + bond_slave_state_change(bond); +- } else if (do_failover) { ++ if (do_failover) { + /* the bond_select_active_slave must hold RTNL + * and curr_slave_lock for write. + */ +@@ -3572,7 +3572,7 @@ static void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int sl + } + } + /* no slave that can tx has been found */ +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + } + + /** +@@ -3628,8 +3628,14 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev + else + bond_xmit_slave_id(bond, skb, 0); + } else { +- slave_id = bond_rr_gen_slave_id(bond); +- bond_xmit_slave_id(bond, skb, slave_id % bond->slave_cnt); ++ int slave_cnt = ACCESS_ONCE(bond->slave_cnt); ++ ++ if (likely(slave_cnt)) { ++ slave_id = bond_rr_gen_slave_id(bond); ++ bond_xmit_slave_id(bond, skb, slave_id % slave_cnt); ++ } else { ++ dev_kfree_skb_any(skb); ++ } + } + + return NETDEV_TX_OK; +@@ -3648,7 +3654,7 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d + if (slave) + bond_dev_queue_xmit(bond, skb, slave->dev); + else +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + + return NETDEV_TX_OK; + } +@@ -3660,8 +3666,13 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d + static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev) + { + struct bonding *bond = netdev_priv(bond_dev); ++ int slave_cnt = ACCESS_ONCE(bond->slave_cnt); + +- bond_xmit_slave_id(bond, skb, bond_xmit_hash(bond, skb, bond->slave_cnt)); ++ if (likely(slave_cnt)) ++ bond_xmit_slave_id(bond, skb, ++ bond_xmit_hash(bond, skb, bond->slave_cnt)); ++ else ++ dev_kfree_skb_any(skb); + + return NETDEV_TX_OK; + } +@@ -3691,7 +3702,7 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev) + if (slave && IS_UP(slave->dev) && slave->link == BOND_LINK_UP) + bond_dev_queue_xmit(bond, skb, slave->dev); + else +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + + return NETDEV_TX_OK; + } +@@ -3778,7 +3789,7 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev + pr_err("%s: Error: Unknown bonding mode %d\n", + dev->name, bond->params.mode); + WARN_ON_ONCE(1); +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + } +@@ -3799,7 +3810,7 @@ static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev) + if (bond_has_slaves(bond)) + ret = __bond_start_xmit(skb, dev); + else +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + rcu_read_unlock(); + + return ret; +diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c +index fc59bc6..84ad2b4 100644 +--- a/drivers/net/can/dev.c ++++ b/drivers/net/can/dev.c +@@ -384,7 +384,7 @@ void can_free_echo_skb(struct net_device *dev, unsigned int idx) + BUG_ON(idx >= priv->echo_skb_max); + + if (priv->echo_skb[idx]) { +- kfree_skb(priv->echo_skb[idx]); ++ dev_kfree_skb_any(priv->echo_skb[idx]); + priv->echo_skb[idx] = NULL; + } + } +@@ -502,6 +502,14 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf) + skb->pkt_type = PACKET_BROADCAST; + skb->ip_summed = CHECKSUM_UNNECESSARY; + ++ skb_reset_mac_header(skb); ++ skb_reset_network_header(skb); ++ skb_reset_transport_header(skb); ++ ++ skb_reset_mac_header(skb); ++ skb_reset_network_header(skb); ++ skb_reset_transport_header(skb); ++ + can_skb_reserve(skb); + can_skb_prv(skb)->ifindex = dev->ifindex; + +@@ -664,10 +672,14 @@ static int can_changelink(struct net_device *dev, + if (dev->flags & IFF_UP) + return -EBUSY; + cm = nla_data(data[IFLA_CAN_CTRLMODE]); +- if (cm->flags & ~priv->ctrlmode_supported) ++ ++ /* check whether changed bits are allowed to be modified */ ++ if (cm->mask & ~priv->ctrlmode_supported) + return -EOPNOTSUPP; ++ ++ /* clear bits to be modified and copy the flag values */ + priv->ctrlmode &= ~cm->mask; +- priv->ctrlmode |= cm->flags; ++ priv->ctrlmode |= (cm->flags & cm->mask); + } + + if (data[IFLA_CAN_RESTART_MS]) { +diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c +index 9250e28..534c0b8 100644 +--- a/drivers/net/can/flexcan.c ++++ b/drivers/net/can/flexcan.c +@@ -1102,12 +1102,19 @@ static int flexcan_probe(struct platform_device *pdev) + const struct flexcan_devtype_data *devtype_data; + struct net_device *dev; + struct flexcan_priv *priv; ++ struct regulator *reg_xceiver; + struct resource *mem; + struct clk *clk_ipg = NULL, *clk_per = NULL; + void __iomem *base; + int err, irq; + u32 clock_freq = 0; + ++ reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver"); ++ if (PTR_ERR(reg_xceiver) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ else if (IS_ERR(reg_xceiver)) ++ reg_xceiver = NULL; ++ + if (pdev->dev.of_node) + of_property_read_u32(pdev->dev.of_node, + "clock-frequency", &clock_freq); +@@ -1169,9 +1176,7 @@ static int flexcan_probe(struct platform_device *pdev) + priv->pdata = dev_get_platdata(&pdev->dev); + priv->devtype_data = devtype_data; + +- priv->reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver"); +- if (IS_ERR(priv->reg_xceiver)) +- priv->reg_xceiver = NULL; ++ priv->reg_xceiver = reg_xceiver; + + netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT); + +diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c +index 7fbe859..f34f7fa 100644 +--- a/drivers/net/can/usb/esd_usb2.c ++++ b/drivers/net/can/usb/esd_usb2.c +@@ -1141,6 +1141,7 @@ static void esd_usb2_disconnect(struct usb_interface *intf) + } + } + unlink_all_urbs(dev); ++ kfree(dev); + } + } + +diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c +index e77d110..3d19867 100644 +--- a/drivers/net/can/usb/kvaser_usb.c ++++ b/drivers/net/can/usb/kvaser_usb.c +@@ -578,7 +578,7 @@ static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv, + usb_sndbulkpipe(dev->udev, + dev->bulk_out->bEndpointAddress), + buf, msg->len, +- kvaser_usb_simple_msg_callback, priv); ++ kvaser_usb_simple_msg_callback, netdev); + usb_anchor_urb(urb, &priv->tx_submitted); + + err = usb_submit_urb(urb, GFP_ATOMIC); +@@ -653,11 +653,6 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev, + priv = dev->nets[channel]; + stats = &priv->netdev->stats; + +- if (status & M16C_STATE_BUS_RESET) { +- kvaser_usb_unlink_tx_urbs(priv); +- return; +- } +- + skb = alloc_can_err_skb(priv->netdev, &cf); + if (!skb) { + stats->rx_dropped++; +@@ -668,7 +663,7 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev, + + netdev_dbg(priv->netdev, "Error status: 0x%02x\n", status); + +- if (status & M16C_STATE_BUS_OFF) { ++ if (status & (M16C_STATE_BUS_OFF | M16C_STATE_BUS_RESET)) { + cf->can_id |= CAN_ERR_BUSOFF; + + priv->can.can_stats.bus_off++; +@@ -694,9 +689,7 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev, + } + + new_state = CAN_STATE_ERROR_PASSIVE; +- } +- +- if (status == M16C_STATE_BUS_ERROR) { ++ } else if (status & M16C_STATE_BUS_ERROR) { + if ((priv->can.state < CAN_STATE_ERROR_WARNING) && + ((txerr >= 96) || (rxerr >= 96))) { + cf->can_id |= CAN_ERR_CRTL; +@@ -706,7 +699,8 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev, + + priv->can.can_stats.error_warning++; + new_state = CAN_STATE_ERROR_WARNING; +- } else if (priv->can.state > CAN_STATE_ERROR_ACTIVE) { ++ } else if ((priv->can.state > CAN_STATE_ERROR_ACTIVE) && ++ ((txerr < 96) && (rxerr < 96))) { + cf->can_id |= CAN_ERR_PROT; + cf->data[2] = CAN_ERR_PROT_ACTIVE; + +@@ -1237,6 +1231,9 @@ static int kvaser_usb_close(struct net_device *netdev) + if (err) + netdev_warn(netdev, "Cannot stop device, error %d\n", err); + ++ /* reset tx contexts */ ++ kvaser_usb_unlink_tx_urbs(priv); ++ + priv->can.state = CAN_STATE_STOPPED; + close_candev(priv->netdev); + +@@ -1285,12 +1282,14 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, + if (!urb) { + netdev_err(netdev, "No memory left for URBs\n"); + stats->tx_dropped++; +- goto nourbmem; ++ dev_kfree_skb(skb); ++ return NETDEV_TX_OK; + } + + buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC); + if (!buf) { + stats->tx_dropped++; ++ dev_kfree_skb(skb); + goto nobufmem; + } + +@@ -1325,6 +1324,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, + } + } + ++ /* This should never happen; it implies a flow control bug */ + if (!context) { + netdev_warn(netdev, "cannot find free context\n"); + ret = NETDEV_TX_BUSY; +@@ -1355,9 +1355,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, + if (unlikely(err)) { + can_free_echo_skb(netdev, context->echo_index); + +- skb = NULL; /* set to NULL to avoid double free in +- * dev_kfree_skb(skb) */ +- + atomic_dec(&priv->active_tx_urbs); + usb_unanchor_urb(urb); + +@@ -1379,8 +1376,6 @@ releasebuf: + kfree(buf); + nobufmem: + usb_free_urb(urb); +-nourbmem: +- dev_kfree_skb(skb); + return ret; + } + +@@ -1492,6 +1487,10 @@ static int kvaser_usb_init_one(struct usb_interface *intf, + struct kvaser_usb_net_priv *priv; + int i, err; + ++ err = kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, channel); ++ if (err) ++ return err; ++ + netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS); + if (!netdev) { + dev_err(&intf->dev, "Cannot alloc candev\n"); +@@ -1577,7 +1576,7 @@ static int kvaser_usb_probe(struct usb_interface *intf, + { + struct kvaser_usb *dev; + int err = -ENOMEM; +- int i; ++ int i, retry = 3; + + dev = devm_kzalloc(&intf->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) +@@ -1595,10 +1594,15 @@ static int kvaser_usb_probe(struct usb_interface *intf, + + usb_set_intfdata(intf, dev); + +- for (i = 0; i < MAX_NET_DEVICES; i++) +- kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, i); ++ /* On some x86 laptops, plugging a Kvaser device again after ++ * an unplug makes the firmware always ignore the very first ++ * command. For such a case, provide some room for retries ++ * instead of completely exiting the driver. ++ */ ++ do { ++ err = kvaser_usb_get_software_info(dev); ++ } while (--retry && err == -ETIMEDOUT); + +- err = kvaser_usb_get_software_info(dev); + if (err) { + dev_err(&intf->dev, + "Cannot get software infos, error %d\n", err); +diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c +index 0b7a4c3..03e7f0c 100644 +--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c ++++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c +@@ -734,7 +734,7 @@ static int peak_usb_create_dev(struct peak_usb_adapter *peak_usb_adapter, + dev->cmd_buf = kmalloc(PCAN_USB_MAX_CMD_LEN, GFP_KERNEL); + if (!dev->cmd_buf) { + err = -ENOMEM; +- goto lbl_set_intf_data; ++ goto lbl_free_candev; + } + + dev->udev = usb_dev; +@@ -773,7 +773,7 @@ static int peak_usb_create_dev(struct peak_usb_adapter *peak_usb_adapter, + err = register_candev(netdev); + if (err) { + dev_err(&intf->dev, "couldn't register CAN device: %d\n", err); +- goto lbl_free_cmd_buf; ++ goto lbl_restore_intf_data; + } + + if (dev->prev_siblings) +@@ -786,14 +786,14 @@ static int peak_usb_create_dev(struct peak_usb_adapter *peak_usb_adapter, + if (dev->adapter->dev_init) { + err = dev->adapter->dev_init(dev); + if (err) +- goto lbl_free_cmd_buf; ++ goto lbl_unregister_candev; + } + + /* set bus off */ + if (dev->adapter->dev_set_bus) { + err = dev->adapter->dev_set_bus(dev, 0); + if (err) +- goto lbl_free_cmd_buf; ++ goto lbl_unregister_candev; + } + + /* get device number early */ +@@ -805,11 +805,14 @@ static int peak_usb_create_dev(struct peak_usb_adapter *peak_usb_adapter, + + return 0; + +-lbl_free_cmd_buf: +- kfree(dev->cmd_buf); ++lbl_unregister_candev: ++ unregister_candev(netdev); + +-lbl_set_intf_data: ++lbl_restore_intf_data: + usb_set_intfdata(intf, dev->prev_siblings); ++ kfree(dev->cmd_buf); ++ ++lbl_free_candev: + free_candev(netdev); + + return err; +diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +index 263dd92..f7f796a 100644 +--- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c ++++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +@@ -333,8 +333,6 @@ static int pcan_usb_pro_send_req(struct peak_usb_device *dev, int req_id, + if (!(dev->state & PCAN_USB_STATE_CONNECTED)) + return 0; + +- memset(req_addr, '\0', req_size); +- + req_type = USB_TYPE_VENDOR | USB_RECIP_OTHER; + + switch (req_id) { +@@ -345,6 +343,7 @@ static int pcan_usb_pro_send_req(struct peak_usb_device *dev, int req_id, + default: + p = usb_rcvctrlpipe(dev->udev, 0); + req_type |= USB_DIR_IN; ++ memset(req_addr, '\0', req_size); + break; + } + +diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c +index 9339ccc..ad0e71c 100644 +--- a/drivers/net/ethernet/amd/pcnet32.c ++++ b/drivers/net/ethernet/amd/pcnet32.c +@@ -1516,7 +1516,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) + { + struct pcnet32_private *lp; + int i, media; +- int fdx, mii, fset, dxsuflo; ++ int fdx, mii, fset, dxsuflo, sram; + int chip_version; + char *chipname; + struct net_device *dev; +@@ -1553,7 +1553,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) + } + + /* initialize variables */ +- fdx = mii = fset = dxsuflo = 0; ++ fdx = mii = fset = dxsuflo = sram = 0; + chip_version = (chip_version >> 12) & 0xffff; + + switch (chip_version) { +@@ -1586,6 +1586,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) + chipname = "PCnet/FAST III 79C973"; /* PCI */ + fdx = 1; + mii = 1; ++ sram = 1; + break; + case 0x2626: + chipname = "PCnet/Home 79C978"; /* PCI */ +@@ -1609,6 +1610,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) + chipname = "PCnet/FAST III 79C975"; /* PCI */ + fdx = 1; + mii = 1; ++ sram = 1; + break; + case 0x2628: + chipname = "PCnet/PRO 79C976"; +@@ -1637,6 +1639,31 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) + dxsuflo = 1; + } + ++ /* ++ * The Am79C973/Am79C975 controllers come with 12K of SRAM ++ * which we can use for the Tx/Rx buffers but most importantly, ++ * the use of SRAM allow us to use the BCR18:NOUFLO bit to avoid ++ * Tx fifo underflows. ++ */ ++ if (sram) { ++ /* ++ * The SRAM is being configured in two steps. First we ++ * set the SRAM size in the BCR25:SRAM_SIZE bits. According ++ * to the datasheet, each bit corresponds to a 512-byte ++ * page so we can have at most 24 pages. The SRAM_SIZE ++ * holds the value of the upper 8 bits of the 16-bit SRAM size. ++ * The low 8-bits start at 0x00 and end at 0xff. So the ++ * address range is from 0x0000 up to 0x17ff. Therefore, ++ * the SRAM_SIZE is set to 0x17. The next step is to set ++ * the BCR26:SRAM_BND midway through so the Tx and Rx ++ * buffers can share the SRAM equally. ++ */ ++ a->write_bcr(ioaddr, 25, 0x17); ++ a->write_bcr(ioaddr, 26, 0xc); ++ /* And finally enable the NOUFLO bit */ ++ a->write_bcr(ioaddr, 18, a->read_bcr(ioaddr, 18) | (1 << 11)); ++ } ++ + dev = alloc_etherdev(sizeof(*lp)); + if (!dev) { + ret = -ENOMEM; +diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c +index 380d249..3e1d7d2 100644 +--- a/drivers/net/ethernet/atheros/alx/main.c ++++ b/drivers/net/ethernet/atheros/alx/main.c +@@ -184,15 +184,16 @@ static void alx_schedule_reset(struct alx_priv *alx) + schedule_work(&alx->reset_wk); + } + +-static bool alx_clean_rx_irq(struct alx_priv *alx, int budget) ++static int alx_clean_rx_irq(struct alx_priv *alx, int budget) + { + struct alx_rx_queue *rxq = &alx->rxq; + struct alx_rrd *rrd; + struct alx_buffer *rxb; + struct sk_buff *skb; + u16 length, rfd_cleaned = 0; ++ int work = 0; + +- while (budget > 0) { ++ while (work < budget) { + rrd = &rxq->rrd[rxq->rrd_read_idx]; + if (!(rrd->word3 & cpu_to_le32(1 << RRD_UPDATED_SHIFT))) + break; +@@ -203,7 +204,7 @@ static bool alx_clean_rx_irq(struct alx_priv *alx, int budget) + ALX_GET_FIELD(le32_to_cpu(rrd->word0), + RRD_NOR) != 1) { + alx_schedule_reset(alx); +- return 0; ++ return work; + } + + rxb = &rxq->bufs[rxq->read_idx]; +@@ -243,7 +244,7 @@ static bool alx_clean_rx_irq(struct alx_priv *alx, int budget) + } + + napi_gro_receive(&alx->napi, skb); +- budget--; ++ work++; + + next_pkt: + if (++rxq->read_idx == alx->rx_ringsz) +@@ -258,21 +259,22 @@ next_pkt: + if (rfd_cleaned) + alx_refill_rx_ring(alx, GFP_ATOMIC); + +- return budget > 0; ++ return work; + } + + static int alx_poll(struct napi_struct *napi, int budget) + { + struct alx_priv *alx = container_of(napi, struct alx_priv, napi); + struct alx_hw *hw = &alx->hw; +- bool complete = true; + unsigned long flags; ++ bool tx_complete; ++ int work; + +- complete = alx_clean_tx_irq(alx) && +- alx_clean_rx_irq(alx, budget); ++ tx_complete = alx_clean_tx_irq(alx); ++ work = alx_clean_rx_irq(alx, budget); + +- if (!complete) +- return 1; ++ if (!tx_complete || work == budget) ++ return budget; + + napi_complete(&alx->napi); + +@@ -284,7 +286,7 @@ static int alx_poll(struct napi_struct *napi, int budget) + + alx_post_write(hw); + +- return 0; ++ return work; + } + + static irqreturn_t alx_intr_handle(struct alx_priv *alx, u32 intr) +diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c +index 6c9e1c9..0c8a168 100644 +--- a/drivers/net/ethernet/broadcom/bnx2.c ++++ b/drivers/net/ethernet/broadcom/bnx2.c +@@ -2886,7 +2886,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) + sw_cons = BNX2_NEXT_TX_BD(sw_cons); + + tx_bytes += skb->len; +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + tx_pkt++; + if (tx_pkt == budget) + break; +@@ -6640,7 +6640,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) + + mapping = dma_map_single(&bp->pdev->dev, skb->data, len, PCI_DMA_TODEVICE); + if (dma_mapping_error(&bp->pdev->dev, mapping)) { +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +@@ -6733,7 +6733,7 @@ dma_error: + PCI_DMA_TODEVICE); + } + +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +index 391f29e..1fbeaa9 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +@@ -337,6 +337,7 @@ struct sw_tx_bd { + u8 flags; + /* Set on the first BD descriptor when there is a split BD */ + #define BNX2X_TSO_SPLIT_BD (1<<0) ++#define BNX2X_HAS_SECOND_PBD (1<<1) + }; + + struct sw_rx_page { +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +index 5ed5124..a830d42 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +@@ -223,6 +223,12 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata, + --nbd; + bd_idx = TX_BD(NEXT_TX_IDX(bd_idx)); + ++ if (tx_buf->flags & BNX2X_HAS_SECOND_PBD) { ++ /* Skip second parse bd... */ ++ --nbd; ++ bd_idx = TX_BD(NEXT_TX_IDX(bd_idx)); ++ } ++ + /* TSO headers+data bds share a common mapping. See bnx2x_tx_split() */ + if (tx_buf->flags & BNX2X_TSO_SPLIT_BD) { + tx_data_bd = &txdata->tx_desc_ring[bd_idx].reg_bd; +@@ -3125,7 +3131,7 @@ static int bnx2x_poll(struct napi_struct *napi, int budget) + } + #endif + if (!bnx2x_fp_lock_napi(fp)) +- return work_done; ++ return budget; + + for_each_cos_in_tx_queue(fp, cos) + if (bnx2x_tx_queue_has_work(fp->txdata_ptr[cos])) +@@ -3868,6 +3874,9 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) + /* set encapsulation flag in start BD */ + SET_FLAG(tx_start_bd->general_data, + ETH_TX_START_BD_TUNNEL_EXIST, 1); ++ ++ tx_buf->flags |= BNX2X_HAS_SECOND_PBD; ++ + nbd++; + } else if (xmit_type & XMIT_CSUM) { + /* Set PBD in checksum offload case w/o encapsulation */ +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +index 7d43822..2428740 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +@@ -12395,6 +12395,9 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev, + pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS, + PCICFG_VENDOR_ID_OFFSET); + ++ /* Set PCIe reset type to fundamental for EEH recovery */ ++ pdev->needs_freset = 1; ++ + /* AER (Advanced Error reporting) configuration */ + rc = pci_enable_pcie_error_reporting(pdev); + if (!rc) +diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c +index 9ab6cc3..1ff5698 100644 +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -6594,7 +6594,7 @@ static void tg3_tx(struct tg3_napi *tnapi) + pkts_compl++; + bytes_compl += skb->len; + +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + + if (unlikely(tx_bug)) { + tg3_tx_recover(tp); +@@ -6924,8 +6924,9 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) + skb->protocol = eth_type_trans(skb, tp->dev); + + if (len > (tp->dev->mtu + ETH_HLEN) && +- skb->protocol != htons(ETH_P_8021Q)) { +- dev_kfree_skb(skb); ++ skb->protocol != htons(ETH_P_8021Q) && ++ skb->protocol != htons(ETH_P_8021AD)) { ++ dev_kfree_skb_any(skb); + goto drop_it_no_recycle; + } + +@@ -7808,7 +7809,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, + PCI_DMA_TODEVICE); + /* Make sure the mapping succeeded */ + if (pci_dma_mapping_error(tp->pdev, new_addr)) { +- dev_kfree_skb(new_skb); ++ dev_kfree_skb_any(new_skb); + ret = -1; + } else { + u32 save_entry = *entry; +@@ -7823,13 +7824,13 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi, + new_skb->len, base_flags, + mss, vlan)) { + tg3_tx_skb_unmap(tnapi, save_entry, -1); +- dev_kfree_skb(new_skb); ++ dev_kfree_skb_any(new_skb); + ret = -1; + } + } + } + +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + *pskb = new_skb; + return ret; + } +@@ -7872,7 +7873,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb) + } while (segs); + + tg3_tso_bug_end: +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + + return NETDEV_TX_OK; + } +@@ -7916,8 +7917,6 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) + + entry = tnapi->tx_prod; + base_flags = 0; +- if (skb->ip_summed == CHECKSUM_PARTIAL) +- base_flags |= TXD_FLAG_TCPUDP_CSUM; + + mss = skb_shinfo(skb)->gso_size; + if (mss) { +@@ -7933,6 +7932,13 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) + + hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb) - ETH_HLEN; + ++ /* HW/FW can not correctly segment packets that have been ++ * vlan encapsulated. ++ */ ++ if (skb->protocol == htons(ETH_P_8021Q) || ++ skb->protocol == htons(ETH_P_8021AD)) ++ return tg3_tso_bug(tp, skb); ++ + if (!skb_is_gso_v6(skb)) { + iph->check = 0; + iph->tot_len = htons(mss + hdr_len); +@@ -7979,6 +7985,17 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) + base_flags |= tsflags << 12; + } + } ++ } else if (skb->ip_summed == CHECKSUM_PARTIAL) { ++ /* HW/FW can not correctly checksum packets that have been ++ * vlan encapsulated. ++ */ ++ if (skb->protocol == htons(ETH_P_8021Q) || ++ skb->protocol == htons(ETH_P_8021AD)) { ++ if (skb_checksum_help(skb)) ++ goto drop; ++ } else { ++ base_flags |= TXD_FLAG_TCPUDP_CSUM; ++ } + } + + if (tg3_flag(tp, USE_JUMBO_BDFLAG) && +@@ -8094,7 +8111,7 @@ dma_error: + tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, --i); + tnapi->tx_buffers[tnapi->tx_prod].skb = NULL; + drop: +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + drop_nofree: + tp->tx_dropped++; + return NETDEV_TX_OK; +@@ -8532,7 +8549,8 @@ static int tg3_init_rings(struct tg3 *tp) + if (tnapi->rx_rcb) + memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); + +- if (tg3_rx_prodring_alloc(tp, &tnapi->prodring)) { ++ if (tnapi->prodring.rx_std && ++ tg3_rx_prodring_alloc(tp, &tnapi->prodring)) { + tg3_free_rings(tp); + return -ENOMEM; + } +@@ -17714,23 +17732,6 @@ static int tg3_init_one(struct pci_dev *pdev, + goto err_out_apeunmap; + } + +- /* +- * Reset chip in case UNDI or EFI driver did not shutdown +- * DMA self test will enable WDMAC and we'll see (spurious) +- * pending DMA on the PCI bus at that point. +- */ +- if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || +- (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { +- tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); +- tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); +- } +- +- err = tg3_test_dma(tp); +- if (err) { +- dev_err(&pdev->dev, "DMA engine test failed, aborting\n"); +- goto err_out_apeunmap; +- } +- + intmbx = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW; + rcvmbx = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW; + sndmbx = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW; +@@ -17775,6 +17776,23 @@ static int tg3_init_one(struct pci_dev *pdev, + sndmbx += 0xc; + } + ++ /* ++ * Reset chip in case UNDI or EFI driver did not shutdown ++ * DMA self test will enable WDMAC and we'll see (spurious) ++ * pending DMA on the PCI bus at that point. ++ */ ++ if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || ++ (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { ++ tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); ++ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); ++ } ++ ++ err = tg3_test_dma(tp); ++ if (err) { ++ dev_err(&pdev->dev, "DMA engine test failed, aborting\n"); ++ goto err_out_apeunmap; ++ } ++ + tg3_init_coal(tp); + + pci_set_drvdata(pdev, dev); +diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c +index 4ad1187..669eeb4 100644 +--- a/drivers/net/ethernet/brocade/bna/bnad.c ++++ b/drivers/net/ethernet/brocade/bna/bnad.c +@@ -600,9 +600,9 @@ bnad_cq_process(struct bnad *bnad, struct bna_ccb *ccb, int budget) + prefetch(bnad->netdev); + + cq = ccb->sw_q; +- cmpl = &cq[ccb->producer_index]; + + while (packets < budget) { ++ cmpl = &cq[ccb->producer_index]; + if (!cmpl->valid) + break; + /* The 'valid' field is set by the adapter, only after writing +diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c +index 6c78848..9e8f4be 100644 +--- a/drivers/net/ethernet/cadence/macb.c ++++ b/drivers/net/ethernet/cadence/macb.c +@@ -30,7 +30,6 @@ + #include + #include + #include +-#include + + #include "macb.h" + +@@ -1800,7 +1799,6 @@ static int __init macb_probe(struct platform_device *pdev) + struct phy_device *phydev; + u32 config; + int err = -ENXIO; +- struct pinctrl *pinctrl; + const char *mac; + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); +@@ -1809,15 +1807,6 @@ static int __init macb_probe(struct platform_device *pdev) + goto err_out; + } + +- pinctrl = devm_pinctrl_get_select_default(&pdev->dev); +- if (IS_ERR(pinctrl)) { +- err = PTR_ERR(pinctrl); +- if (err == -EPROBE_DEFER) +- goto err_out; +- +- dev_warn(&pdev->dev, "No pinctrl provided\n"); +- } +- + err = -ENOMEM; + dev = alloc_etherdev(sizeof(*bp)); + if (!dev) +diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c +index b740bfc..ff9b423 100644 +--- a/drivers/net/ethernet/cisco/enic/enic_main.c ++++ b/drivers/net/ethernet/cisco/enic/enic_main.c +@@ -1044,10 +1044,14 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, + PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); + } + +- if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc) { +- skb->csum = htons(checksum); +- skb->ip_summed = CHECKSUM_COMPLETE; +- } ++ /* Hardware does not provide whole packet checksum. It only ++ * provides pseudo checksum. Since hw validates the packet ++ * checksum but not provide us the checksum value. use ++ * CHECSUM_UNNECESSARY. ++ */ ++ if ((netdev->features & NETIF_F_RXCSUM) && tcp_udp_csum_ok && ++ ipv4_csum_ok) ++ skb->ip_summed = CHECKSUM_UNNECESSARY; + + if (vlan_stripped) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci); +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index 80bfa03..075e7e7 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -1883,7 +1883,7 @@ static u16 be_tx_compl_process(struct be_adapter *adapter, + queue_tail_inc(txq); + } while (cur_index != last_index); + +- kfree_skb(sent_skb); ++ dev_kfree_skb_any(sent_skb); + return num_wrbs; + } + +diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c +index 1fc8334..55e3075 100644 +--- a/drivers/net/ethernet/ibm/ibmveth.c ++++ b/drivers/net/ethernet/ibm/ibmveth.c +@@ -292,6 +292,18 @@ failure: + atomic_add(buffers_added, &(pool->available)); + } + ++/* ++ * The final 8 bytes of the buffer list is a counter of frames dropped ++ * because there was not a buffer in the buffer list capable of holding ++ * the frame. ++ */ ++static void ibmveth_update_rx_no_buffer(struct ibmveth_adapter *adapter) ++{ ++ __be64 *p = adapter->buffer_list_addr + 4096 - 8; ++ ++ adapter->rx_no_buffer = be64_to_cpup(p); ++} ++ + /* replenish routine */ + static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) + { +@@ -307,8 +319,7 @@ static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) + ibmveth_replenish_buffer_pool(adapter, pool); + } + +- adapter->rx_no_buffer = *(u64 *)(((char*)adapter->buffer_list_addr) + +- 4096 - 8); ++ ibmveth_update_rx_no_buffer(adapter); + } + + /* empty and free ana buffer pool - also used to do cleanup in error paths */ +@@ -698,8 +709,7 @@ static int ibmveth_close(struct net_device *netdev) + + free_irq(netdev->irq, netdev); + +- adapter->rx_no_buffer = *(u64 *)(((char *)adapter->buffer_list_addr) + +- 4096 - 8); ++ ibmveth_update_rx_no_buffer(adapter); + + ibmveth_cleanup(adapter); + +diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c +index 46e6544..b655fe4 100644 +--- a/drivers/net/ethernet/intel/e1000/e1000_main.c ++++ b/drivers/net/ethernet/intel/e1000/e1000_main.c +@@ -144,6 +144,11 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, + static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, + struct e1000_rx_ring *rx_ring, + int *work_done, int work_to_do); ++static void e1000_alloc_dummy_rx_buffers(struct e1000_adapter *adapter, ++ struct e1000_rx_ring *rx_ring, ++ int cleaned_count) ++{ ++} + static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, + struct e1000_rx_ring *rx_ring, + int cleaned_count); +@@ -3531,8 +3536,11 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) + msleep(1); + /* e1000_down has a dependency on max_frame_size */ + hw->max_frame_size = max_frame; +- if (netif_running(netdev)) ++ if (netif_running(netdev)) { ++ /* prevent buffers from being reallocated */ ++ adapter->alloc_rx_buf = e1000_alloc_dummy_rx_buffers; + e1000_down(adapter); ++ } + + /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN + * means we reserve 2 more, this pushes us to allocate from the next +diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c +index b901371..5d3206d 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_main.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c +@@ -4024,6 +4024,9 @@ static int i40e_init_pf_dcb(struct i40e_pf *pf) + DCB_CAP_DCBX_VER_IEEE; + pf->flags |= I40E_FLAG_DCB_ENABLED; + } ++ } else { ++ dev_info(&pf->pdev->dev, "AQ Querying DCB configuration failed: %d\n", ++ pf->hw.aq.asq_last_status); + } + + out: +@@ -8003,7 +8006,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + if (err) { + dev_info(&pdev->dev, "init_pf_dcb failed: %d\n", err); + pf->flags &= ~I40E_FLAG_DCB_ENABLED; +- goto err_init_dcb; ++ /* Continue without DCB enabled */ + } + #endif /* CONFIG_I40E_DCB */ + +@@ -8119,9 +8122,6 @@ err_vsis: + err_switch_setup: + i40e_reset_interrupt_capability(pf); + del_timer_sync(&pf->service_timer); +-#ifdef CONFIG_I40E_DCB +-err_init_dcb: +-#endif /* CONFIG_I40E_DCB */ + err_mac_addr: + err_configure_lan_hmc: + (void)i40e_shutdown_lan_hmc(hw); +diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c +index 5ca8c47..206e79d 100644 +--- a/drivers/net/ethernet/intel/igb/igb_main.c ++++ b/drivers/net/ethernet/intel/igb/igb_main.c +@@ -1613,6 +1613,8 @@ void igb_power_up_link(struct igb_adapter *adapter) + igb_power_up_phy_copper(&adapter->hw); + else + igb_power_up_serdes_link_82575(&adapter->hw); ++ ++ igb_setup_link(&adapter->hw); + } + + /** +diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c +index 57e390c..f42c201 100644 +--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c ++++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c +@@ -1521,12 +1521,12 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) + int tso; + + if (test_bit(__IXGB_DOWN, &adapter->flags)) { +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + if (skb->len <= 0) { +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +@@ -1543,7 +1543,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) + + tso = ixgb_tso(adapter, skb); + if (tso < 0) { +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c +index c4c00d9f..96fc7fe 100644 +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -213,7 +213,7 @@ + /* Various constants */ + + /* Coalescing */ +-#define MVNETA_TXDONE_COAL_PKTS 16 ++#define MVNETA_TXDONE_COAL_PKTS 1 + #define MVNETA_RX_COAL_PKTS 32 + #define MVNETA_RX_COAL_USEC 100 + +@@ -1612,6 +1612,7 @@ static int mvneta_tx(struct sk_buff *skb, struct net_device *dev) + u16 txq_id = skb_get_queue_mapping(skb); + struct mvneta_tx_queue *txq = &pp->txqs[txq_id]; + struct mvneta_tx_desc *tx_desc; ++ int len = skb->len; + struct netdev_queue *nq; + int frags = 0; + u32 tx_cmd; +@@ -1675,7 +1676,7 @@ out: + + u64_stats_update_begin(&stats->syncp); + stats->tx_packets++; +- stats->tx_bytes += skb->len; ++ stats->tx_bytes += len; + u64_stats_update_end(&stats->syncp); + } else { + dev->stats.tx_dropped++; +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +index 2f83f34..8be0f3e 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +@@ -2497,13 +2497,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, + netif_carrier_off(dev); + mlx4_en_set_default_moderation(priv); + +- err = register_netdev(dev); +- if (err) { +- en_err(priv, "Netdev registration failed for port %d\n", port); +- goto out; +- } +- priv->registered = 1; +- + en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num); + en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num); + +@@ -2543,6 +2536,14 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, + queue_delayed_work(mdev->workqueue, &priv->service_task, + SERVICE_TASK_DELAY); + ++ err = register_netdev(dev); ++ if (err) { ++ en_err(priv, "Netdev registration failed for port %d\n", port); ++ goto out; ++ } ++ ++ priv->registered = 1; ++ + return 0; + + out: +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c +index 1345703..a467261 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c +@@ -325,7 +325,7 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv, + } + } + } +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return tx_info->nr_txbb; + } + +@@ -810,8 +810,11 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) + tx_desc->ctrl.fence_size = (real_size / 16) & 0x3f; + tx_desc->ctrl.srcrb_flags = priv->ctrl_flags; + if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { +- tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM | +- MLX4_WQE_CTRL_TCP_UDP_CSUM); ++ if (!skb->encapsulation) ++ tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM | ++ MLX4_WQE_CTRL_TCP_UDP_CSUM); ++ else ++ tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM); + ring->tx_csum++; + } + +diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +index 57428a0..1e8a4b4 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c ++++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +@@ -1456,7 +1456,7 @@ static int qp_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, + + switch (op) { + case RES_OP_RESERVE: +- count = get_param_l(&in_param); ++ count = get_param_l(&in_param) & 0xffffff; + align = get_param_h(&in_param); + err = mlx4_grant_resource(dev, slave, RES_QP, count, 0); + if (err) +diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +index 68026f7..4a474dd 100644 +--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c ++++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +@@ -872,6 +872,10 @@ static int myri10ge_dma_test(struct myri10ge_priv *mgp, int test_type) + return -ENOMEM; + dmatest_bus = pci_map_page(mgp->pdev, dmatest_page, 0, PAGE_SIZE, + DMA_BIDIRECTIONAL); ++ if (unlikely(pci_dma_mapping_error(mgp->pdev, dmatest_bus))) { ++ __free_page(dmatest_page); ++ return -ENOMEM; ++ } + + /* Run a small DMA test. + * The magic multipliers to the length tell the firmware +@@ -1293,6 +1297,7 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, + int bytes, int watchdog) + { + struct page *page; ++ dma_addr_t bus; + int idx; + #if MYRI10GE_ALLOC_SIZE > 4096 + int end_offset; +@@ -1317,11 +1322,21 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, + rx->watchdog_needed = 1; + return; + } ++ ++ bus = pci_map_page(mgp->pdev, page, 0, ++ MYRI10GE_ALLOC_SIZE, ++ PCI_DMA_FROMDEVICE); ++ if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) { ++ __free_pages(page, MYRI10GE_ALLOC_ORDER); ++ if (rx->fill_cnt - rx->cnt < 16) ++ rx->watchdog_needed = 1; ++ return; ++ } ++ + rx->page = page; + rx->page_offset = 0; +- rx->bus = pci_map_page(mgp->pdev, page, 0, +- MYRI10GE_ALLOC_SIZE, +- PCI_DMA_FROMDEVICE); ++ rx->bus = bus; ++ + } + rx->info[idx].page = rx->page; + rx->info[idx].page_offset = rx->page_offset; +@@ -2765,6 +2780,35 @@ myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src, + mb(); + } + ++static void myri10ge_unmap_tx_dma(struct myri10ge_priv *mgp, ++ struct myri10ge_tx_buf *tx, int idx) ++{ ++ unsigned int len; ++ int last_idx; ++ ++ /* Free any DMA resources we've alloced and clear out the skb slot */ ++ last_idx = (idx + 1) & tx->mask; ++ idx = tx->req & tx->mask; ++ do { ++ len = dma_unmap_len(&tx->info[idx], len); ++ if (len) { ++ if (tx->info[idx].skb != NULL) ++ pci_unmap_single(mgp->pdev, ++ dma_unmap_addr(&tx->info[idx], ++ bus), len, ++ PCI_DMA_TODEVICE); ++ else ++ pci_unmap_page(mgp->pdev, ++ dma_unmap_addr(&tx->info[idx], ++ bus), len, ++ PCI_DMA_TODEVICE); ++ dma_unmap_len_set(&tx->info[idx], len, 0); ++ tx->info[idx].skb = NULL; ++ } ++ idx = (idx + 1) & tx->mask; ++ } while (idx != last_idx); ++} ++ + /* + * Transmit a packet. We need to split the packet so that a single + * segment does not cross myri10ge->tx_boundary, so this makes segment +@@ -2788,7 +2832,7 @@ static netdev_tx_t myri10ge_xmit(struct sk_buff *skb, + u32 low; + __be32 high_swapped; + unsigned int len; +- int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments; ++ int idx, avail, frag_cnt, frag_idx, count, mss, max_segments; + u16 pseudo_hdr_offset, cksum_offset, queue; + int cum_len, seglen, boundary, rdma_count; + u8 flags, odd_flag; +@@ -2885,9 +2929,12 @@ again: + + /* map the skb for DMA */ + len = skb_headlen(skb); ++ bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE); ++ if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) ++ goto drop; ++ + idx = tx->req & tx->mask; + tx->info[idx].skb = skb; +- bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE); + dma_unmap_addr_set(&tx->info[idx], bus, bus); + dma_unmap_len_set(&tx->info[idx], len, len); + +@@ -2986,12 +3033,16 @@ again: + break; + + /* map next fragment for DMA */ +- idx = (count + tx->req) & tx->mask; + frag = &skb_shinfo(skb)->frags[frag_idx]; + frag_idx++; + len = skb_frag_size(frag); + bus = skb_frag_dma_map(&mgp->pdev->dev, frag, 0, len, + DMA_TO_DEVICE); ++ if (unlikely(pci_dma_mapping_error(mgp->pdev, bus))) { ++ myri10ge_unmap_tx_dma(mgp, tx, idx); ++ goto drop; ++ } ++ idx = (count + tx->req) & tx->mask; + dma_unmap_addr_set(&tx->info[idx], bus, bus); + dma_unmap_len_set(&tx->info[idx], len, len); + } +@@ -3022,31 +3073,8 @@ again: + return NETDEV_TX_OK; + + abort_linearize: +- /* Free any DMA resources we've alloced and clear out the skb +- * slot so as to not trip up assertions, and to avoid a +- * double-free if linearizing fails */ ++ myri10ge_unmap_tx_dma(mgp, tx, idx); + +- last_idx = (idx + 1) & tx->mask; +- idx = tx->req & tx->mask; +- tx->info[idx].skb = NULL; +- do { +- len = dma_unmap_len(&tx->info[idx], len); +- if (len) { +- if (tx->info[idx].skb != NULL) +- pci_unmap_single(mgp->pdev, +- dma_unmap_addr(&tx->info[idx], +- bus), len, +- PCI_DMA_TODEVICE); +- else +- pci_unmap_page(mgp->pdev, +- dma_unmap_addr(&tx->info[idx], +- bus), len, +- PCI_DMA_TODEVICE); +- dma_unmap_len_set(&tx->info[idx], len, 0); +- tx->info[idx].skb = NULL; +- } +- idx = (idx + 1) & tx->mask; +- } while (idx != last_idx); + if (skb_is_gso(skb)) { + netdev_err(mgp->dev, "TSO but wanted to linearize?!?!?\n"); + goto drop; +diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +index 70849de..5fa076f 100644 +--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c ++++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +@@ -2390,7 +2390,10 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget) + + work_done = netxen_process_rcv_ring(sds_ring, budget); + +- if ((work_done < budget) && tx_complete) { ++ if (!tx_complete) ++ work_done = budget; ++ ++ if (work_done < budget) { + napi_complete(&sds_ring->napi); + if (test_bit(__NX_DEV_UP, &adapter->state)) + netxen_nic_enable_int(sds_ring); +diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c +index 737c1a8..a3c1daa 100644 +--- a/drivers/net/ethernet/realtek/8139cp.c ++++ b/drivers/net/ethernet/realtek/8139cp.c +@@ -899,7 +899,7 @@ out_unlock: + + return NETDEV_TX_OK; + out_dma_error: +- kfree_skb(skb); ++ dev_kfree_skb_any(skb); + cp->dev->stats.tx_dropped++; + goto out_unlock; + } +diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c +index da5972e..8cb2f35 100644 +--- a/drivers/net/ethernet/realtek/8139too.c ++++ b/drivers/net/ethernet/realtek/8139too.c +@@ -1717,9 +1717,9 @@ static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, + if (len < ETH_ZLEN) + memset(tp->tx_buf[entry], 0, ETH_ZLEN); + skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + } else { +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } +diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c +index 3ff7bc3..90c14d1 100644 +--- a/drivers/net/ethernet/realtek/r8169.c ++++ b/drivers/net/ethernet/realtek/r8169.c +@@ -5834,7 +5834,7 @@ static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start, + tp->TxDescArray + entry); + if (skb) { + tp->dev->stats.tx_dropped++; +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + tx_skb->skb = NULL; + } + } +@@ -6059,7 +6059,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, + err_dma_1: + rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd); + err_dma_0: +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + err_update_stats: + dev->stats.tx_dropped++; + return NETDEV_TX_OK; +@@ -6142,7 +6142,7 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) + tp->tx_stats.packets++; + tp->tx_stats.bytes += tx_skb->skb->len; + u64_stats_update_end(&tp->tx_stats.syncp); +- dev_kfree_skb(tx_skb->skb); ++ dev_kfree_skb_any(tx_skb->skb); + tx_skb->skb = NULL; + } + dirty_tx++; +diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c +index 6382b7c..e10f5ed 100644 +--- a/drivers/net/ethernet/smsc/smsc911x.c ++++ b/drivers/net/ethernet/smsc/smsc911x.c +@@ -1341,6 +1341,42 @@ static void smsc911x_rx_multicast_update_workaround(struct smsc911x_data *pdata) + spin_unlock(&pdata->mac_lock); + } + ++static int smsc911x_phy_general_power_up(struct smsc911x_data *pdata) ++{ ++ int rc = 0; ++ ++ if (!pdata->phy_dev) ++ return rc; ++ ++ /* If the internal PHY is in General Power-Down mode, all, except the ++ * management interface, is powered-down and stays in that condition as ++ * long as Phy register bit 0.11 is HIGH. ++ * ++ * In that case, clear the bit 0.11, so the PHY powers up and we can ++ * access to the phy registers. ++ */ ++ rc = phy_read(pdata->phy_dev, MII_BMCR); ++ if (rc < 0) { ++ SMSC_WARN(pdata, drv, "Failed reading PHY control reg"); ++ return rc; ++ } ++ ++ /* If the PHY general power-down bit is not set is not necessary to ++ * disable the general power down-mode. ++ */ ++ if (rc & BMCR_PDOWN) { ++ rc = phy_write(pdata->phy_dev, MII_BMCR, rc & ~BMCR_PDOWN); ++ if (rc < 0) { ++ SMSC_WARN(pdata, drv, "Failed writing PHY control reg"); ++ return rc; ++ } ++ ++ usleep_range(1000, 1500); ++ } ++ ++ return 0; ++} ++ + static int smsc911x_phy_disable_energy_detect(struct smsc911x_data *pdata) + { + int rc = 0; +@@ -1414,6 +1450,16 @@ static int smsc911x_soft_reset(struct smsc911x_data *pdata) + int ret; + + /* ++ * Make sure to power-up the PHY chip before doing a reset, otherwise ++ * the reset fails. ++ */ ++ ret = smsc911x_phy_general_power_up(pdata); ++ if (ret) { ++ SMSC_WARN(pdata, drv, "Failed to power-up the PHY chip"); ++ return ret; ++ } ++ ++ /* + * LAN9210/LAN9211/LAN9220/LAN9221 chips have an internal PHY that + * are initialized in a Energy Detect Power-Down mode that prevents + * the MAC chip to be software reseted. So we have to wakeup the PHY +diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c +index fd411d6..03ae9de 100644 +--- a/drivers/net/ethernet/sun/sunvnet.c ++++ b/drivers/net/ethernet/sun/sunvnet.c +@@ -656,7 +656,7 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) + spin_lock_irqsave(&port->vio.lock, flags); + + dr = &port->vio.drings[VIO_DRIVER_TX_RING]; +- if (unlikely(vnet_tx_dring_avail(dr) < 2)) { ++ if (unlikely(vnet_tx_dring_avail(dr) < 1)) { + if (!netif_queue_stopped(dev)) { + netif_stop_queue(dev); + +@@ -704,7 +704,7 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) + dev->stats.tx_bytes += skb->len; + + dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1); +- if (unlikely(vnet_tx_dring_avail(dr) < 2)) { ++ if (unlikely(vnet_tx_dring_avail(dr) < 1)) { + netif_stop_queue(dev); + if (vnet_tx_dring_avail(dr) > VNET_TX_WAKEUP_THRESH(dr)) + netif_wake_queue(dev); +diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c +index 921b9df..4eb091d 100644 +--- a/drivers/net/ethernet/ti/cpsw.c ++++ b/drivers/net/ethernet/ti/cpsw.c +@@ -596,7 +596,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) + + /* Clear all mcast from ALE */ + cpsw_ale_flush_multicast(ale, ALE_ALL_PORTS << +- priv->host_port); ++ priv->host_port, -1); + + /* Flood All Unicast Packets to Host port */ + cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 1); +@@ -620,6 +620,12 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) + static void cpsw_ndo_set_rx_mode(struct net_device *ndev) + { + struct cpsw_priv *priv = netdev_priv(ndev); ++ int vid; ++ ++ if (priv->data.dual_emac) ++ vid = priv->slaves[priv->emac_port].port_vlan; ++ else ++ vid = priv->data.default_vlan; + + if (ndev->flags & IFF_PROMISC) { + /* Enable promiscuous mode */ +@@ -631,7 +637,8 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev) + } + + /* Clear all mcast from ALE */ +- cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port); ++ cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port, ++ vid); + + if (!netdev_mc_empty(ndev)) { + struct netdev_hw_addr *ha; +@@ -716,6 +723,14 @@ static void cpsw_rx_handler(void *token, int len, int status) + static irqreturn_t cpsw_interrupt(int irq, void *dev_id) + { + struct cpsw_priv *priv = dev_id; ++ int value = irq - priv->irqs_table[0]; ++ ++ /* NOTICE: Ending IRQ here. The trick with the 'value' variable above ++ * is to make sure we will always write the correct value to the EOI ++ * register. Namely 0 for RX_THRESH Interrupt, 1 for RX Interrupt, 2 ++ * for TX Interrupt and 3 for MISC Interrupt. ++ */ ++ cpdma_ctlr_eoi(priv->dma, value); + + cpsw_intr_disable(priv); + if (priv->irq_enabled == true) { +@@ -745,8 +760,6 @@ static int cpsw_poll(struct napi_struct *napi, int budget) + int num_tx, num_rx; + + num_tx = cpdma_chan_process(priv->txch, 128); +- if (num_tx) +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX); + + num_rx = cpdma_chan_process(priv->rxch, budget); + if (num_rx < budget) { +@@ -754,7 +767,6 @@ static int cpsw_poll(struct napi_struct *napi, int budget) + + napi_complete(napi); + cpsw_intr_enable(priv); +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX); + prim_cpsw = cpsw_get_slave_priv(priv, 0); + if (prim_cpsw->irq_enabled == false) { + prim_cpsw->irq_enabled = true; +@@ -1265,8 +1277,6 @@ static int cpsw_ndo_open(struct net_device *ndev) + napi_enable(&priv->napi); + cpdma_ctlr_start(priv->dma); + cpsw_intr_enable(priv); +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX); +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX); + + if (priv->data.dual_emac) + priv->slaves[priv->emac_port].open_stat = true; +@@ -1512,9 +1522,6 @@ static void cpsw_ndo_tx_timeout(struct net_device *ndev) + cpdma_chan_start(priv->txch); + cpdma_ctlr_int_ctrl(priv->dma, true); + cpsw_intr_enable(priv); +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX); +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX); +- + } + + static int cpsw_ndo_set_mac_address(struct net_device *ndev, void *p) +@@ -1560,9 +1567,6 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev) + cpsw_interrupt(ndev->irq, priv); + cpdma_ctlr_int_ctrl(priv->dma, true); + cpsw_intr_enable(priv); +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX); +- cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX); +- + } + #endif + +@@ -1606,6 +1610,19 @@ static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev, + if (vid == priv->data.default_vlan) + return 0; + ++ if (priv->data.dual_emac) { ++ /* In dual EMAC, reserved VLAN id should not be used for ++ * creating VLAN interfaces as this can break the dual ++ * EMAC port separation ++ */ ++ int i; ++ ++ for (i = 0; i < priv->data.slaves; i++) { ++ if (vid == priv->slaves[i].port_vlan) ++ return -EINVAL; ++ } ++ } ++ + dev_info(priv->dev, "Adding vlanid %d to vlan filter\n", vid); + return cpsw_add_vlan_ale_entry(priv, vid); + } +@@ -1619,6 +1636,15 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev, + if (vid == priv->data.default_vlan) + return 0; + ++ if (priv->data.dual_emac) { ++ int i; ++ ++ for (i = 0; i < priv->data.slaves; i++) { ++ if (vid == priv->slaves[i].port_vlan) ++ return -EINVAL; ++ } ++ } ++ + dev_info(priv->dev, "removing vlanid %d from vlan filter\n", vid); + ret = cpsw_ale_del_vlan(priv->ale, vid, 0); + if (ret != 0) +diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c +index 7f89306..4eceb7e 100644 +--- a/drivers/net/ethernet/ti/cpsw_ale.c ++++ b/drivers/net/ethernet/ti/cpsw_ale.c +@@ -236,7 +236,7 @@ static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry, + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE); + } + +-int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask) ++int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid) + { + u32 ale_entry[ALE_ENTRY_WORDS]; + int ret, idx; +@@ -247,6 +247,14 @@ int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask) + if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR) + continue; + ++ /* if vid passed is -1 then remove all multicast entry from ++ * the table irrespective of vlan id, if a valid vlan id is ++ * passed then remove only multicast added to that vlan id. ++ * if vlan id doesn't match then move on to next entry. ++ */ ++ if (vid != -1 && cpsw_ale_get_vlan_id(ale_entry) != vid) ++ continue; ++ + if (cpsw_ale_get_mcast(ale_entry)) { + u8 addr[6]; + +diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h +index de409c3..e701358 100644 +--- a/drivers/net/ethernet/ti/cpsw_ale.h ++++ b/drivers/net/ethernet/ti/cpsw_ale.h +@@ -88,7 +88,7 @@ void cpsw_ale_stop(struct cpsw_ale *ale); + + int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout); + int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask); +-int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask); ++int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid); + int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, + int flags, u16 vid); + int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port, +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +index d6fce97..3c1c33c 100644 +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -146,6 +146,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) + struct hv_netvsc_packet *packet; + int ret; + unsigned int i, num_pages, npg_data; ++ u32 skb_length = skb->len; + + /* Add multipages for skb->data and additional 2 for RNDIS */ + npg_data = (((unsigned long)skb->data + skb_headlen(skb) - 1) +@@ -216,7 +217,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) + ret = rndis_filter_send(net_device_ctx->device_ctx, + packet); + if (ret == 0) { +- net->stats.tx_bytes += skb->len; ++ net->stats.tx_bytes += skb_length; + net->stats.tx_packets++; + } else { + kfree(packet); +diff --git a/drivers/net/ieee802154/fakehard.c b/drivers/net/ieee802154/fakehard.c +index bf0d55e..6adbef8 100644 +--- a/drivers/net/ieee802154/fakehard.c ++++ b/drivers/net/ieee802154/fakehard.c +@@ -376,17 +376,20 @@ static int ieee802154fake_probe(struct platform_device *pdev) + + err = wpan_phy_register(phy); + if (err) +- goto out; ++ goto err_phy_reg; + + err = register_netdev(dev); +- if (err < 0) +- goto out; ++ if (err) ++ goto err_netdev_reg; + + dev_info(&pdev->dev, "Added ieee802154 HardMAC hardware\n"); + return 0; + +-out: +- unregister_netdev(dev); ++err_netdev_reg: ++ wpan_phy_unregister(phy); ++err_phy_reg: ++ free_netdev(dev); ++ wpan_phy_free(phy); + return err; + } + +diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c +index 5adecc5..fbf7dcd 100644 +--- a/drivers/net/macvlan.c ++++ b/drivers/net/macvlan.c +@@ -548,6 +548,7 @@ static int macvlan_init(struct net_device *dev) + (lowerdev->state & MACVLAN_STATE_MASK); + dev->features = lowerdev->features & MACVLAN_FEATURES; + dev->features |= ALWAYS_ON_FEATURES; ++ dev->vlan_features = lowerdev->vlan_features & MACVLAN_FEATURES; + dev->gso_max_size = lowerdev->gso_max_size; + dev->iflink = lowerdev->ifindex; + dev->hard_header_len = lowerdev->hard_header_len; +@@ -708,6 +709,7 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev, + features, + mask); + features |= ALWAYS_ON_FEATURES; ++ features &= ~NETIF_F_NETNS_LOCAL; + + return features; + } +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index 3381c4f..e8c21f9 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -16,6 +16,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -112,17 +113,15 @@ out: + return err; + } + ++/* Requires RTNL */ + static int macvtap_set_queue(struct net_device *dev, struct file *file, + struct macvtap_queue *q) + { + struct macvlan_dev *vlan = netdev_priv(dev); +- int err = -EBUSY; + +- rtnl_lock(); + if (vlan->numqueues == MAX_MACVTAP_QUEUES) +- goto out; ++ return -EBUSY; + +- err = 0; + rcu_assign_pointer(q->vlan, vlan); + rcu_assign_pointer(vlan->taps[vlan->numvtaps], q); + sock_hold(&q->sk); +@@ -136,9 +135,7 @@ static int macvtap_set_queue(struct net_device *dev, struct file *file, + vlan->numvtaps++; + vlan->numqueues++; + +-out: +- rtnl_unlock(); +- return err; ++ return 0; + } + + static int macvtap_disable_queue(struct macvtap_queue *q) +@@ -454,11 +451,12 @@ static void macvtap_sock_destruct(struct sock *sk) + static int macvtap_open(struct inode *inode, struct file *file) + { + struct net *net = current->nsproxy->net_ns; +- struct net_device *dev = dev_get_by_macvtap_minor(iminor(inode)); ++ struct net_device *dev; + struct macvtap_queue *q; +- int err; ++ int err = -ENODEV; + +- err = -ENODEV; ++ rtnl_lock(); ++ dev = dev_get_by_macvtap_minor(iminor(inode)); + if (!dev) + goto out; + +@@ -498,6 +496,7 @@ out: + if (dev) + dev_put(dev); + ++ rtnl_unlock(); + return err; + } + +@@ -572,6 +571,8 @@ static int macvtap_skb_from_vnet_hdr(struct sk_buff *skb, + break; + case VIRTIO_NET_HDR_GSO_UDP: + gso_type = SKB_GSO_UDP; ++ if (skb->protocol == htons(ETH_P_IPV6)) ++ ipv6_proxy_select_ident(skb); + break; + default: + return -EINVAL; +@@ -628,18 +629,23 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, + if (skb->ip_summed == CHECKSUM_PARTIAL) { + vnet_hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; + vnet_hdr->csum_start = skb_checksum_start_offset(skb); ++ if (vlan_tx_tag_present(skb)) ++ vnet_hdr->csum_start += VLAN_HLEN; + vnet_hdr->csum_offset = skb->csum_offset; + } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + vnet_hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID; + } /* else everything is zero */ + } + ++/* Neighbour code has some assumptions on HH_DATA_MOD alignment */ ++#define MACVTAP_RESERVE HH_DATA_OFF(ETH_HLEN) ++ + /* Get packet from user space buffer */ + static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, + const struct iovec *iv, unsigned long total_len, + size_t count, int noblock) + { +- int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN); ++ int good_linear = SKB_MAX_HEAD(MACVTAP_RESERVE); + struct sk_buff *skb; + struct macvlan_dev *vlan; + unsigned long len = total_len; +@@ -698,7 +704,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, + linear = vnet_hdr.hdr_len; + } + +- skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen, ++ skb = macvtap_alloc_skb(&q->sk, MACVTAP_RESERVE, copylen, + linear, noblock, &err); + if (!skb) + goto err; +diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c +index 98e7cbf..0be3f9d 100644 +--- a/drivers/net/phy/dp83640.c ++++ b/drivers/net/phy/dp83640.c +@@ -45,7 +45,7 @@ + #define PSF_TX 0x1000 + #define EXT_EVENT 1 + #define CAL_EVENT 7 +-#define CAL_TRIGGER 7 ++#define CAL_TRIGGER 1 + #define PER_TRIGGER 6 + + #define MII_DP83640_MICR 0x11 +@@ -442,7 +442,9 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp, + else + evnt |= EVNT_RISE; + } ++ mutex_lock(&clock->extreg_lock); + ext_write(0, phydev, PAGE5, PTP_EVNT, evnt); ++ mutex_unlock(&clock->extreg_lock); + return 0; + + case PTP_CLK_REQ_PEROUT: +@@ -463,6 +465,8 @@ static u8 status_frame_src[6] = { 0x08, 0x00, 0x17, 0x0B, 0x6B, 0x0F }; + + static void enable_status_frames(struct phy_device *phydev, bool on) + { ++ struct dp83640_private *dp83640 = phydev->priv; ++ struct dp83640_clock *clock = dp83640->clock; + u16 cfg0 = 0, ver; + + if (on) +@@ -470,9 +474,13 @@ static void enable_status_frames(struct phy_device *phydev, bool on) + + ver = (PSF_PTPVER & VERSIONPTP_MASK) << VERSIONPTP_SHIFT; + ++ mutex_lock(&clock->extreg_lock); ++ + ext_write(0, phydev, PAGE5, PSF_CFG0, cfg0); + ext_write(0, phydev, PAGE6, PSF_CFG1, ver); + ++ mutex_unlock(&clock->extreg_lock); ++ + if (!phydev->attached_dev) { + pr_warn("expected to find an attached netdevice\n"); + return; +@@ -1063,11 +1071,18 @@ static int dp83640_config_init(struct phy_device *phydev) + + if (clock->chosen && !list_empty(&clock->phylist)) + recalibrate(clock); +- else ++ else { ++ mutex_lock(&clock->extreg_lock); + enable_broadcast(phydev, clock->page, 1); ++ mutex_unlock(&clock->extreg_lock); ++ } + + enable_status_frames(phydev, true); ++ ++ mutex_lock(&clock->extreg_lock); + ext_write(0, phydev, PAGE4, PTP_CTL, PTP_ENABLE); ++ mutex_unlock(&clock->extreg_lock); ++ + return 0; + } + +diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c +index 76d96b9..65cfc5a 100644 +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -194,6 +194,25 @@ static inline unsigned int phy_find_valid(unsigned int idx, u32 features) + } + + /** ++ * phy_check_valid - check if there is a valid PHY setting which matches ++ * speed, duplex, and feature mask ++ * @speed: speed to match ++ * @duplex: duplex to match ++ * @features: A mask of the valid settings ++ * ++ * Description: Returns true if there is a valid setting, false otherwise. ++ */ ++static inline bool phy_check_valid(int speed, int duplex, u32 features) ++{ ++ unsigned int idx; ++ ++ idx = phy_find_valid(phy_find_setting(speed, duplex), features); ++ ++ return settings[idx].speed == speed && settings[idx].duplex == duplex && ++ (settings[idx].setting & features); ++} ++ ++/** + * phy_sanitize_settings - make sure the PHY is set to supported speed and duplex + * @phydev: the target phy_device struct + * +@@ -946,16 +965,17 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable) + { + /* According to 802.3az,the EEE is supported only in full duplex-mode. + * Also EEE feature is active when core is operating with MII, GMII +- * or RGMII. ++ * or RGMII (all kinds). Internal PHYs are also allowed to proceed and ++ * should return an error if they do not support EEE. + */ + if ((phydev->duplex == DUPLEX_FULL) && + ((phydev->interface == PHY_INTERFACE_MODE_MII) || + (phydev->interface == PHY_INTERFACE_MODE_GMII) || +- (phydev->interface == PHY_INTERFACE_MODE_RGMII))) { ++ (phydev->interface >= PHY_INTERFACE_MODE_RGMII && ++ phydev->interface <= PHY_INTERFACE_MODE_RGMII_TXID))) { + int eee_lp, eee_cap, eee_adv; + u32 lp, cap, adv; + int status; +- unsigned int idx; + + /* Read phy status to properly get the right settings */ + status = phy_read_status(phydev); +@@ -987,8 +1007,7 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable) + + adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv); + lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp); +- idx = phy_find_setting(phydev->speed, phydev->duplex); +- if (!(lp & adv & settings[idx].setting)) ++ if (!phy_check_valid(phydev->speed, phydev->duplex, lp & adv)) + return -EPROTONOSUPPORT; + + if (clk_stop_enable) { +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index 701cc2e..db7017c 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -353,7 +353,7 @@ int phy_device_register(struct phy_device *phydev) + phydev->bus->phy_map[phydev->addr] = phydev; + + /* Run all of the fixups for this PHY */ +- err = phy_init_hw(phydev); ++ err = phy_scan_fixups(phydev); + if (err) { + pr_err("PHY %d failed to initialize\n", phydev->addr); + goto out; +@@ -765,10 +765,11 @@ static int genphy_config_advert(struct phy_device *phydev) + if (phydev->supported & (SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full)) { + adv |= ethtool_adv_to_mii_ctrl1000_t(advertise); +- if (adv != oldadv) +- changed = 1; + } + ++ if (adv != oldadv) ++ changed = 1; ++ + err = phy_write(phydev, MII_CTRL1000, adv); + if (err < 0) + return err; +diff --git a/drivers/net/ppp/ppp_deflate.c b/drivers/net/ppp/ppp_deflate.c +index 602c625..b5edc7f 100644 +--- a/drivers/net/ppp/ppp_deflate.c ++++ b/drivers/net/ppp/ppp_deflate.c +@@ -246,7 +246,7 @@ static int z_compress(void *arg, unsigned char *rptr, unsigned char *obuf, + /* + * See if we managed to reduce the size of the packet. + */ +- if (olen < isize) { ++ if (olen < isize && olen <= osize) { + state->stats.comp_bytes += olen; + state->stats.comp_packets++; + } else { +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 72ff14b..5a1897d 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -601,7 +601,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + if (file == ppp->owner) + ppp_shutdown_interface(ppp); + } +- if (atomic_long_read(&file->f_count) <= 2) { ++ if (atomic_long_read(&file->f_count) < 2) { + ppp_release(NULL, file); + err = 0; + } else +diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c +index 0180531..1dc628f 100644 +--- a/drivers/net/ppp/pptp.c ++++ b/drivers/net/ppp/pptp.c +@@ -281,7 +281,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) + nf_reset(skb); + + skb->ip_summed = CHECKSUM_NONE; +- ip_select_ident(skb, &rt->dst, NULL); ++ ip_select_ident(skb, NULL); + ip_send_check(iph); + + ip_local_out(skb); +@@ -506,7 +506,9 @@ static int pptp_getname(struct socket *sock, struct sockaddr *uaddr, + int len = sizeof(struct sockaddr_pppox); + struct sockaddr_pppox sp; + +- sp.sa_family = AF_PPPOX; ++ memset(&sp.sa_addr, 0, sizeof(sp.sa_addr)); ++ ++ sp.sa_family = AF_PPPOX; + sp.sa_protocol = PX_PROTO_PPTP; + sp.sa_addr.pptp = pppox_sk(sock->sk)->proto.pptp.src_addr; + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 26d8c29..c28e2da 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -42,9 +42,7 @@ + + static struct team_port *team_port_get_rcu(const struct net_device *dev) + { +- struct team_port *port = rcu_dereference(dev->rx_handler_data); +- +- return team_port_exists(dev) ? port : NULL; ++ return rcu_dereference(dev->rx_handler_data); + } + + static struct team_port *team_port_get_rtnl(const struct net_device *dev) +@@ -629,6 +627,7 @@ static int team_change_mode(struct team *team, const char *kind) + static void team_notify_peers_work(struct work_struct *work) + { + struct team *team; ++ int val; + + team = container_of(work, struct team, notify_peers.dw.work); + +@@ -636,9 +635,14 @@ static void team_notify_peers_work(struct work_struct *work) + schedule_delayed_work(&team->notify_peers.dw, 0); + return; + } ++ val = atomic_dec_if_positive(&team->notify_peers.count_pending); ++ if (val < 0) { ++ rtnl_unlock(); ++ return; ++ } + call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, team->dev); + rtnl_unlock(); +- if (!atomic_dec_and_test(&team->notify_peers.count_pending)) ++ if (val) + schedule_delayed_work(&team->notify_peers.dw, + msecs_to_jiffies(team->notify_peers.interval)); + } +@@ -647,7 +651,7 @@ static void team_notify_peers(struct team *team) + { + if (!team->notify_peers.count || !netif_running(team->dev)) + return; +- atomic_set(&team->notify_peers.count_pending, team->notify_peers.count); ++ atomic_add(team->notify_peers.count, &team->notify_peers.count_pending); + schedule_delayed_work(&team->notify_peers.dw, 0); + } + +@@ -669,6 +673,7 @@ static void team_notify_peers_fini(struct team *team) + static void team_mcast_rejoin_work(struct work_struct *work) + { + struct team *team; ++ int val; + + team = container_of(work, struct team, mcast_rejoin.dw.work); + +@@ -676,9 +681,14 @@ static void team_mcast_rejoin_work(struct work_struct *work) + schedule_delayed_work(&team->mcast_rejoin.dw, 0); + return; + } ++ val = atomic_dec_if_positive(&team->mcast_rejoin.count_pending); ++ if (val < 0) { ++ rtnl_unlock(); ++ return; ++ } + call_netdevice_notifiers(NETDEV_RESEND_IGMP, team->dev); + rtnl_unlock(); +- if (!atomic_dec_and_test(&team->mcast_rejoin.count_pending)) ++ if (val) + schedule_delayed_work(&team->mcast_rejoin.dw, + msecs_to_jiffies(team->mcast_rejoin.interval)); + } +@@ -687,7 +697,7 @@ static void team_mcast_rejoin(struct team *team) + { + if (!team->mcast_rejoin.count || !netif_running(team->dev)) + return; +- atomic_set(&team->mcast_rejoin.count_pending, team->mcast_rejoin.count); ++ atomic_add(team->mcast_rejoin.count, &team->mcast_rejoin.count_pending); + schedule_delayed_work(&team->mcast_rejoin.dw, 0); + } + +@@ -1713,11 +1723,11 @@ static int team_set_mac_address(struct net_device *dev, void *p) + if (dev->type == ARPHRD_ETHER && !is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); +- rcu_read_lock(); +- list_for_each_entry_rcu(port, &team->port_list, list) ++ mutex_lock(&team->lock); ++ list_for_each_entry(port, &team->port_list, list) + if (team->ops.port_change_dev_addr) + team->ops.port_change_dev_addr(team, port); +- rcu_read_unlock(); ++ mutex_unlock(&team->lock); + return 0; + } + +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index 26f8635..ec63314 100644 +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -65,6 +65,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1140,6 +1141,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + break; + } + ++ skb_reset_network_header(skb); ++ + if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) { + pr_debug("GSO!\n"); + switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { +@@ -1151,6 +1154,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + break; + case VIRTIO_NET_HDR_GSO_UDP: + skb_shinfo(skb)->gso_type = SKB_GSO_UDP; ++ if (skb->protocol == htons(ETH_P_IPV6)) ++ ipv6_proxy_select_ident(skb); + break; + default: + tun->dev->stats.rx_frame_errors++; +@@ -1180,7 +1185,6 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, + skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; + } + +- skb_reset_network_header(skb); + skb_probe_transport_header(skb, 0); + + rxhash = skb_get_hash(skb); +@@ -1222,6 +1226,10 @@ static ssize_t tun_put_user(struct tun_struct *tun, + struct tun_pi pi = { 0, skb->protocol }; + ssize_t total = 0; + int vlan_offset = 0, copied; ++ int vlan_hlen = 0; ++ ++ if (vlan_tx_tag_present(skb)) ++ vlan_hlen = VLAN_HLEN; + + if (!(tun->flags & TUN_NO_PI)) { + if ((len -= sizeof(pi)) < 0) +@@ -1273,7 +1281,8 @@ static ssize_t tun_put_user(struct tun_struct *tun, + + if (skb->ip_summed == CHECKSUM_PARTIAL) { + gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; +- gso.csum_start = skb_checksum_start_offset(skb); ++ gso.csum_start = skb_checksum_start_offset(skb) + ++ vlan_hlen; + gso.csum_offset = skb->csum_offset; + } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + gso.flags = VIRTIO_NET_HDR_F_DATA_VALID; +@@ -1286,10 +1295,9 @@ static ssize_t tun_put_user(struct tun_struct *tun, + } + + copied = total; +- total += skb->len; +- if (!vlan_tx_tag_present(skb)) { +- len = min_t(int, skb->len, len); +- } else { ++ len = min_t(int, skb->len + vlan_hlen, len); ++ total += skb->len + vlan_hlen; ++ if (vlan_hlen) { + int copy, ret; + struct { + __be16 h_vlan_proto; +@@ -1300,8 +1308,6 @@ static ssize_t tun_put_user(struct tun_struct *tun, + veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb)); + + vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); +- len = min_t(int, skb->len + VLAN_HLEN, len); +- total += VLAN_HLEN; + + copy = min_t(int, vlan_offset, len); + ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy); +diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c +index 054e59c..8cee173 100644 +--- a/drivers/net/usb/ax88179_178a.c ++++ b/drivers/net/usb/ax88179_178a.c +@@ -696,6 +696,7 @@ static int ax88179_set_mac_addr(struct net_device *net, void *p) + { + struct usbnet *dev = netdev_priv(net); + struct sockaddr *addr = p; ++ int ret; + + if (netif_running(net)) + return -EBUSY; +@@ -705,8 +706,12 @@ static int ax88179_set_mac_addr(struct net_device *net, void *p) + memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); + + /* Set the MAC address */ +- return ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, ++ ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, + ETH_ALEN, net->dev_addr); ++ if (ret < 0) ++ return ret; ++ ++ return 0; + } + + static const struct net_device_ops ax88179_netdev_ops = { +diff --git a/drivers/net/usb/cx82310_eth.c b/drivers/net/usb/cx82310_eth.c +index 3eed708..fe48f4c 100644 +--- a/drivers/net/usb/cx82310_eth.c ++++ b/drivers/net/usb/cx82310_eth.c +@@ -300,9 +300,18 @@ static const struct driver_info cx82310_info = { + .tx_fixup = cx82310_tx_fixup, + }; + ++#define USB_DEVICE_CLASS(vend, prod, cl, sc, pr) \ ++ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ ++ USB_DEVICE_ID_MATCH_DEV_INFO, \ ++ .idVendor = (vend), \ ++ .idProduct = (prod), \ ++ .bDeviceClass = (cl), \ ++ .bDeviceSubClass = (sc), \ ++ .bDeviceProtocol = (pr) ++ + static const struct usb_device_id products[] = { + { +- USB_DEVICE_AND_INTERFACE_INFO(0x0572, 0xcb01, 0xff, 0, 0), ++ USB_DEVICE_CLASS(0x0572, 0xcb01, 0xff, 0, 0), + .driver_info = (unsigned long) &cx82310_info + }, + { }, +diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c +index 3d18bb0..1bfe0fc 100644 +--- a/drivers/net/usb/plusb.c ++++ b/drivers/net/usb/plusb.c +@@ -134,6 +134,11 @@ static const struct usb_device_id products [] = { + }, { + USB_DEVICE(0x050d, 0x258a), /* Belkin F5U258/F5U279 (PL-25A1) */ + .driver_info = (unsigned long) &prolific_info, ++}, { ++ USB_DEVICE(0x3923, 0x7825), /* National Instruments USB ++ * Host-to-Host Cable ++ */ ++ .driver_info = (unsigned long) &prolific_info, + }, + + { }, // END +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index d510f1d..db21af8 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -769,6 +769,7 @@ static const struct usb_device_id products[] = { + {QMI_FIXED_INTF(0x413c, 0x81a4, 8)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ + {QMI_FIXED_INTF(0x413c, 0x81a8, 8)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */ + {QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */ ++ {QMI_FIXED_INTF(0x03f0, 0x581d, 4)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */ + + /* 4. Gobi 1000 devices */ + {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ +diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c +index 40ad25d..5988910 100644 +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -279,13 +279,15 @@ static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb) + return list_first_entry(&fdb->remotes, struct vxlan_rdst, list); + } + +-/* Find VXLAN socket based on network namespace and UDP port */ +-static struct vxlan_sock *vxlan_find_sock(struct net *net, __be16 port) ++/* Find VXLAN socket based on network namespace, address family and UDP port */ ++static struct vxlan_sock *vxlan_find_sock(struct net *net, ++ sa_family_t family, __be16 port) + { + struct vxlan_sock *vs; + + hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) { +- if (inet_sk(vs->sock->sk)->inet_sport == port) ++ if (inet_sk(vs->sock->sk)->inet_sport == port && ++ inet_sk(vs->sock->sk)->sk.sk_family == family) + return vs; + } + return NULL; +@@ -304,11 +306,12 @@ static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, u32 id) + } + + /* Look up VNI in a per net namespace table */ +-static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id, __be16 port) ++static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id, ++ sa_family_t family, __be16 port) + { + struct vxlan_sock *vs; + +- vs = vxlan_find_sock(net, port); ++ vs = vxlan_find_sock(net, family, port); + if (!vs) + return NULL; + +@@ -1334,7 +1337,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb) + } else if (vxlan->flags & VXLAN_F_L3MISS) { + union vxlan_addr ipa = { + .sin.sin_addr.s_addr = tip, +- .sa.sa_family = AF_INET, ++ .sin.sin_family = AF_INET, + }; + + vxlan_ip_miss(dev, &ipa); +@@ -1447,9 +1450,6 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb) + if (!in6_dev) + goto out; + +- if (!pskb_may_pull(skb, skb->len)) +- goto out; +- + iphdr = ipv6_hdr(skb); + saddr = &iphdr->saddr; + daddr = &iphdr->daddr; +@@ -1495,7 +1495,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb) + } else if (vxlan->flags & VXLAN_F_L3MISS) { + union vxlan_addr ipa = { + .sin6.sin6_addr = msg->target, +- .sa.sa_family = AF_INET6, ++ .sin6.sin6_family = AF_INET6, + }; + + vxlan_ip_miss(dev, &ipa); +@@ -1528,7 +1528,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb) + if (!n && (vxlan->flags & VXLAN_F_L3MISS)) { + union vxlan_addr ipa = { + .sin.sin_addr.s_addr = pip->daddr, +- .sa.sa_family = AF_INET, ++ .sin.sin_family = AF_INET, + }; + + vxlan_ip_miss(dev, &ipa); +@@ -1549,7 +1549,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb) + if (!n && (vxlan->flags & VXLAN_F_L3MISS)) { + union vxlan_addr ipa = { + .sin6.sin6_addr = pip6->daddr, +- .sa.sa_family = AF_INET6, ++ .sin6.sin6_family = AF_INET6, + }; + + vxlan_ip_miss(dev, &ipa); +@@ -1770,6 +1770,8 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, + struct pcpu_sw_netstats *tx_stats, *rx_stats; + union vxlan_addr loopback; + union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip; ++ struct net_device *dev = skb->dev; ++ int len = skb->len; + + tx_stats = this_cpu_ptr(src_vxlan->dev->tstats); + rx_stats = this_cpu_ptr(dst_vxlan->dev->tstats); +@@ -1793,16 +1795,16 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, + + u64_stats_update_begin(&tx_stats->syncp); + tx_stats->tx_packets++; +- tx_stats->tx_bytes += skb->len; ++ tx_stats->tx_bytes += len; + u64_stats_update_end(&tx_stats->syncp); + + if (netif_rx(skb) == NET_RX_SUCCESS) { + u64_stats_update_begin(&rx_stats->syncp); + rx_stats->rx_packets++; +- rx_stats->rx_bytes += skb->len; ++ rx_stats->rx_bytes += len; + u64_stats_update_end(&rx_stats->syncp); + } else { +- skb->dev->stats.rx_dropped++; ++ dev->stats.rx_dropped++; + } + } + +@@ -1873,7 +1875,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, + struct vxlan_dev *dst_vxlan; + + ip_rt_put(rt); +- dst_vxlan = vxlan_find_vni(dev_net(dev), vni, dst_port); ++ dst_vxlan = vxlan_find_vni(dev_net(dev), vni, ++ dst->sa.sa_family, dst_port); + if (!dst_vxlan) + goto tx_error; + vxlan_encap_bypass(skb, vxlan, dst_vxlan); +@@ -1926,7 +1929,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, + struct vxlan_dev *dst_vxlan; + + dst_release(ndst); +- dst_vxlan = vxlan_find_vni(dev_net(dev), vni, dst_port); ++ dst_vxlan = vxlan_find_vni(dev_net(dev), vni, ++ dst->sa.sa_family, dst_port); + if (!dst_vxlan) + goto tx_error; + vxlan_encap_bypass(skb, vxlan, dst_vxlan); +@@ -1977,7 +1981,8 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) + return arp_reduce(dev, skb); + #if IS_ENABLED(CONFIG_IPV6) + else if (ntohs(eth->h_proto) == ETH_P_IPV6 && +- skb->len >= sizeof(struct ipv6hdr) + sizeof(struct nd_msg) && ++ pskb_may_pull(skb, sizeof(struct ipv6hdr) ++ + sizeof(struct nd_msg)) && + ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) { + struct nd_msg *msg; + +@@ -1986,6 +1991,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) + msg->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) + return neigh_reduce(dev, skb); + } ++ eth = eth_hdr(skb); + #endif + } + +@@ -2082,6 +2088,7 @@ static int vxlan_init(struct net_device *dev) + { + struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); ++ bool ipv6 = vxlan->flags & VXLAN_F_IPV6; + struct vxlan_sock *vs; + int i; + +@@ -2097,10 +2104,10 @@ static int vxlan_init(struct net_device *dev) + + + spin_lock(&vn->sock_lock); +- vs = vxlan_find_sock(dev_net(dev), vxlan->dst_port); +- if (vs) { ++ vs = vxlan_find_sock(dev_net(dev), ipv6 ? AF_INET6 : AF_INET, ++ vxlan->dst_port); ++ if (vs && atomic_add_unless(&vs->refcnt, 1, 0)) { + /* If we have a socket with same port already, reuse it */ +- atomic_inc(&vs->refcnt); + vxlan_vs_add_dev(vs, vxlan); + } else { + /* otherwise make new socket outside of RTNL */ +@@ -2565,13 +2572,10 @@ struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, + return vs; + + spin_lock(&vn->sock_lock); +- vs = vxlan_find_sock(net, port); +- if (vs) { +- if (vs->rcv == rcv) +- atomic_inc(&vs->refcnt); +- else ++ vs = vxlan_find_sock(net, ipv6 ? AF_INET6 : AF_INET, port); ++ if (vs && ((vs->rcv != rcv) || ++ !atomic_add_unless(&vs->refcnt, 1, 0))) + vs = ERR_PTR(-EBUSY); +- } + spin_unlock(&vn->sock_lock); + + if (!vs) +@@ -2711,7 +2715,8 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, + if (data[IFLA_VXLAN_PORT]) + vxlan->dst_port = nla_get_be16(data[IFLA_VXLAN_PORT]); + +- if (vxlan_find_vni(net, vni, vxlan->dst_port)) { ++ if (vxlan_find_vni(net, vni, use_ipv6 ? AF_INET6 : AF_INET, ++ vxlan->dst_port)) { + pr_info("duplicate VNI %u\n", vni); + return -EEXIST; + } +diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c +index 0583c69..ddaad71 100644 +--- a/drivers/net/wireless/ath/ath5k/qcu.c ++++ b/drivers/net/wireless/ath/ath5k/qcu.c +@@ -225,13 +225,7 @@ ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, + } else { + switch (queue_type) { + case AR5K_TX_QUEUE_DATA: +- for (queue = AR5K_TX_QUEUE_ID_DATA_MIN; +- ah->ah_txq[queue].tqi_type != +- AR5K_TX_QUEUE_INACTIVE; queue++) { +- +- if (queue > AR5K_TX_QUEUE_ID_DATA_MAX) +- return -EINVAL; +- } ++ queue = queue_info->tqi_subtype; + break; + case AR5K_TX_QUEUE_UAPSD: + queue = AR5K_TX_QUEUE_ID_UAPSD; +diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c +index a3399c4..b9b651e 100644 +--- a/drivers/net/wireless/ath/ath5k/reset.c ++++ b/drivers/net/wireless/ath/ath5k/reset.c +@@ -478,7 +478,7 @@ ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) + regval = ioread32(reg); + iowrite32(regval | val, reg); + regval = ioread32(reg); +- usleep_range(100, 150); ++ udelay(100); /* NB: should be atomic */ + + /* Bring BB/MAC out of reset */ + iowrite32(regval & ~val, reg); +diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +index 09facba..390c2de 100644 +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -647,6 +647,19 @@ static void ar9003_hw_override_ini(struct ath_hw *ah) + ah->enabled_cals |= TX_CL_CAL; + else + ah->enabled_cals &= ~TX_CL_CAL; ++ ++ if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) { ++ if (ah->is_clk_25mhz) { ++ REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); ++ REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); ++ REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae); ++ } else { ++ REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1); ++ REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400); ++ REG_WRITE(ah, AR_SLP32_INC, 0x0001e800); ++ } ++ udelay(100); ++ } + } + + static void ar9003_hw_prog_ini(struct ath_hw *ah, +diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c +index 9078a6c..dcc1494 100644 +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -858,19 +858,6 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, + udelay(RTC_PLL_SETTLE_DELAY); + + REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); +- +- if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) { +- if (ah->is_clk_25mhz) { +- REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); +- REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); +- REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae); +- } else { +- REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1); +- REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400); +- REG_WRITE(ah, AR_SLP32_INC, 0x0001e800); +- } +- udelay(100); +- } + } + + static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, +diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h +index 0acd4b5..32ae0a4 100644 +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -216,8 +216,8 @@ + #define AH_WOW_BEACON_MISS BIT(3) + + enum ath_hw_txq_subtype { +- ATH_TXQ_AC_BE = 0, +- ATH_TXQ_AC_BK = 1, ++ ATH_TXQ_AC_BK = 0, ++ ATH_TXQ_AC_BE = 1, + ATH_TXQ_AC_VI = 2, + ATH_TXQ_AC_VO = 3, + }; +diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c +index 5f72758..8f93ed3 100644 +--- a/drivers/net/wireless/ath/ath9k/mac.c ++++ b/drivers/net/wireless/ath/ath9k/mac.c +@@ -311,14 +311,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, + q = ATH9K_NUM_TX_QUEUES - 3; + break; + case ATH9K_TX_QUEUE_DATA: +- for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++) +- if (ah->txq[q].tqi_type == +- ATH9K_TX_QUEUE_INACTIVE) +- break; +- if (q == ATH9K_NUM_TX_QUEUES) { +- ath_err(common, "No available TX queue\n"); +- return -1; +- } ++ q = qinfo->tqi_subtype; + break; + default: + ath_err(common, "Invalid TX queue type: %u\n", type); +diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c +index a8e6d41..5d75b569 100644 +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -205,11 +205,13 @@ static bool ath_prepare_reset(struct ath_softc *sc) + ath_stop_ani(sc); + ath9k_hw_disable_interrupts(ah); + +- if (!ath_drain_all_txq(sc)) +- ret = false; +- +- if (!ath_stoprecv(sc)) +- ret = false; ++ if (AR_SREV_9300_20_OR_LATER(ah)) { ++ ret &= ath_stoprecv(sc); ++ ret &= ath_drain_all_txq(sc); ++ } else { ++ ret &= ath_drain_all_txq(sc); ++ ret &= ath_stoprecv(sc); ++ } + + return ret; + } +diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c +index 0526ddf..0fe7674 100644 +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -890,6 +890,15 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, + + tx_info = IEEE80211_SKB_CB(skb); + tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT; ++ ++ /* ++ * No aggregation session is running, but there may be frames ++ * from a previous session or a failed attempt in the queue. ++ * Send them out as normal data frames ++ */ ++ if (!tid->active) ++ tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU; ++ + if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) { + bf->bf_state.bf_type = 0; + return bf; +diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h +index 8596aba..237d0cd 100644 +--- a/drivers/net/wireless/ath/carl9170/carl9170.h ++++ b/drivers/net/wireless/ath/carl9170/carl9170.h +@@ -256,6 +256,7 @@ struct ar9170 { + atomic_t rx_work_urbs; + atomic_t rx_pool_urbs; + kernel_ulong_t features; ++ bool usb_ep_cmd_is_bulk; + + /* firmware settings */ + struct completion fw_load_wait; +diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c +index ca115f3..bc931f6 100644 +--- a/drivers/net/wireless/ath/carl9170/usb.c ++++ b/drivers/net/wireless/ath/carl9170/usb.c +@@ -621,9 +621,16 @@ int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd, + goto err_free; + } + +- usb_fill_int_urb(urb, ar->udev, usb_sndintpipe(ar->udev, +- AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4, +- carl9170_usb_cmd_complete, ar, 1); ++ if (ar->usb_ep_cmd_is_bulk) ++ usb_fill_bulk_urb(urb, ar->udev, ++ usb_sndbulkpipe(ar->udev, AR9170_USB_EP_CMD), ++ cmd, cmd->hdr.len + 4, ++ carl9170_usb_cmd_complete, ar); ++ else ++ usb_fill_int_urb(urb, ar->udev, ++ usb_sndintpipe(ar->udev, AR9170_USB_EP_CMD), ++ cmd, cmd->hdr.len + 4, ++ carl9170_usb_cmd_complete, ar, 1); + + if (free_buf) + urb->transfer_flags |= URB_FREE_BUFFER; +@@ -1032,9 +1039,10 @@ static void carl9170_usb_firmware_step2(const struct firmware *fw, + static int carl9170_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) + { ++ struct usb_endpoint_descriptor *ep; + struct ar9170 *ar; + struct usb_device *udev; +- int err; ++ int i, err; + + err = usb_reset_device(interface_to_usbdev(intf)); + if (err) +@@ -1050,6 +1058,21 @@ static int carl9170_usb_probe(struct usb_interface *intf, + ar->intf = intf; + ar->features = id->driver_info; + ++ /* We need to remember the type of endpoint 4 because it differs ++ * between high- and full-speed configuration. The high-speed ++ * configuration specifies it as interrupt and the full-speed ++ * configuration as bulk endpoint. This information is required ++ * later when sending urbs to that endpoint. ++ */ ++ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; ++i) { ++ ep = &intf->cur_altsetting->endpoint[i].desc; ++ ++ if (usb_endpoint_num(ep) == AR9170_USB_EP_CMD && ++ usb_endpoint_dir_out(ep) && ++ usb_endpoint_type(ep) == USB_ENDPOINT_XFER_BULK) ++ ar->usb_ep_cmd_is_bulk = true; ++ } ++ + usb_set_intfdata(intf, ar); + SET_IEEE80211_DEV(ar->hw, &intf->dev); + +diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +index fad77dd..3f9cb89 100644 +--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +@@ -185,7 +185,13 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, + ifevent->action, ifevent->ifidx, ifevent->bssidx, + ifevent->flags, ifevent->role); + +- if (ifevent->flags & BRCMF_E_IF_FLAG_NOIF) { ++ /* The P2P Device interface event must not be ignored ++ * contrary to what firmware tells us. The only way to ++ * distinguish the P2P Device is by looking at the ifidx ++ * and bssidx received. ++ */ ++ if (!(ifevent->ifidx == 0 && ifevent->bssidx == 1) && ++ (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) { + brcmf_dbg(EVENT, "event can be ignored\n"); + return; + } +@@ -210,12 +216,12 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, + return; + } + +- if (ifevent->action == BRCMF_E_IF_CHANGE) ++ if (ifp && ifevent->action == BRCMF_E_IF_CHANGE) + brcmf_fws_reset_interface(ifp); + + err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data); + +- if (ifevent->action == BRCMF_E_IF_DEL) { ++ if (ifp && ifevent->action == BRCMF_E_IF_DEL) { + brcmf_fws_del_interface(ifp); + brcmf_del_if(drvr, ifevent->bssidx); + } +diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +index 51b53a7..d26b476 100644 +--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h ++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +@@ -167,6 +167,8 @@ enum brcmf_fweh_event_code { + #define BRCMF_E_IF_ROLE_STA 0 + #define BRCMF_E_IF_ROLE_AP 1 + #define BRCMF_E_IF_ROLE_WDS 2 ++#define BRCMF_E_IF_ROLE_P2P_GO 3 ++#define BRCMF_E_IF_ROLE_P2P_CLIENT 4 + + /** + * definitions for event packet validation. +diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h +index 3441f70..6e8cdb8 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/dev.h ++++ b/drivers/net/wireless/iwlwifi/dvm/dev.h +@@ -708,7 +708,6 @@ struct iwl_priv { + unsigned long reload_jiffies; + int reload_count; + bool ucode_loaded; +- bool init_ucode_run; /* Don't run init uCode again */ + + u8 plcp_delta_threshold; + +diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c +index c1e3113..503a81e 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/rxon.c ++++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c +@@ -1068,6 +1068,13 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) + /* recalculate basic rates */ + iwl_calc_basic_rates(priv, ctx); + ++ /* ++ * force CTS-to-self frames protection if RTS-CTS is not preferred ++ * one aggregation protection method ++ */ ++ if (!priv->hw_params.use_rts_for_aggregation) ++ ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; ++ + if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || + !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK)) + ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; +@@ -1473,6 +1480,11 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, + else + ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; + ++ if (bss_conf->use_cts_prot) ++ ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; ++ else ++ ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN; ++ + memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN); + + if (vif->type == NL80211_IFTYPE_AP || +diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c +index cf03ef5..8b2dedc 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/ucode.c ++++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c +@@ -418,9 +418,6 @@ int iwl_run_init_ucode(struct iwl_priv *priv) + if (!priv->fw->img[IWL_UCODE_INIT].sec[0].len) + return 0; + +- if (priv->init_ucode_run) +- return 0; +- + iwl_init_notification_wait(&priv->notif_wait, &calib_wait, + calib_complete, ARRAY_SIZE(calib_complete), + iwlagn_wait_calib, priv); +@@ -440,8 +437,6 @@ int iwl_run_init_ucode(struct iwl_priv *priv) + */ + ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, + UCODE_CALIB_TIMEOUT); +- if (!ret) +- priv->init_ucode_run = true; + + goto out; + +diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h +index 1ced525..b45d78f 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-config.h ++++ b/drivers/net/wireless/iwlwifi/iwl-config.h +@@ -119,6 +119,8 @@ enum iwl_led_mode { + #define IWL_LONG_WD_TIMEOUT 10000 + #define IWL_MAX_WD_TIMEOUT 120000 + ++#define IWL_DEFAULT_MAX_TX_POWER 22 ++ + /* Antenna presence definitions */ + #define ANT_NONE 0x0 + #define ANT_A BIT(0) +diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +index 725e954..3c3eb78 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c ++++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +@@ -118,8 +118,6 @@ static const u8 iwl_nvm_channels[] = { + #define LAST_2GHZ_HT_PLUS 9 + #define LAST_5GHZ_HT 161 + +-#define DEFAULT_MAX_TX_POWER 16 +- + /* rate data (static) */ + static struct ieee80211_rate iwl_cfg80211_rates[] = { + { .bitrate = 1 * 10, .hw_value = 0, .hw_value_short = 0, }, +@@ -242,7 +240,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, + * Default value - highest tx power value. max_power + * is not used in mvm, and is used for backwards compatibility + */ +- channel->max_power = DEFAULT_MAX_TX_POWER; ++ channel->max_power = IWL_DEFAULT_MAX_TX_POWER; + is_5ghz = channel->band == IEEE80211_BAND_5GHZ; + IWL_DEBUG_EEPROM(dev, + "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", +diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h +index 1f065cf..d090ed7 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-trans.h ++++ b/drivers/net/wireless/iwlwifi/iwl-trans.h +@@ -514,6 +514,7 @@ enum iwl_trans_state { + * Set during transport allocation. + * @hw_id_str: a string with info about HW ID. Set during transport allocation. + * @pm_support: set to true in start_hw if link pm is supported ++ * @ltr_enabled: set to true if the LTR is enabled + * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only. + * The user should use iwl_trans_{alloc,free}_tx_cmd. + * @dev_cmd_headroom: room needed for the transport's private use before the +@@ -539,6 +540,7 @@ struct iwl_trans { + u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size; + + bool pm_support; ++ bool ltr_enabled; + + /* The following fields are internal only */ + struct kmem_cache *dev_cmd_pool; +diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +index 884c087..fa66471 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h ++++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +@@ -66,13 +66,46 @@ + + /* Power Management Commands, Responses, Notifications */ + ++/** ++ * enum iwl_ltr_config_flags - masks for LTR config command flags ++ * @LTR_CFG_FLAG_FEATURE_ENABLE: Feature operational status ++ * @LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS: allow LTR change on shadow ++ * memory access ++ * @LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH: allow LTR msg send on ANY LTR ++ * reg change ++ * @LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3: allow LTR msg send on transition from ++ * D0 to D3 ++ * @LTR_CFG_FLAG_SW_SET_SHORT: fixed static short LTR register ++ * @LTR_CFG_FLAG_SW_SET_LONG: fixed static short LONG register ++ * @LTR_CFG_FLAG_DENIE_C10_ON_PD: allow going into C10 on PD ++ */ ++enum iwl_ltr_config_flags { ++ LTR_CFG_FLAG_FEATURE_ENABLE = BIT(0), ++ LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS = BIT(1), ++ LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH = BIT(2), ++ LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3 = BIT(3), ++ LTR_CFG_FLAG_SW_SET_SHORT = BIT(4), ++ LTR_CFG_FLAG_SW_SET_LONG = BIT(5), ++ LTR_CFG_FLAG_DENIE_C10_ON_PD = BIT(6), ++}; ++ ++/** ++ * struct iwl_ltr_config_cmd - configures the LTR ++ * @flags: See %enum iwl_ltr_config_flags ++ */ ++struct iwl_ltr_config_cmd { ++ __le32 flags; ++ __le32 static_long; ++ __le32 static_short; ++} __packed; ++ + /* Radio LP RX Energy Threshold measured in dBm */ + #define POWER_LPRX_RSSI_THRESHOLD 75 + #define POWER_LPRX_RSSI_THRESHOLD_MAX 94 + #define POWER_LPRX_RSSI_THRESHOLD_MIN 30 + + /** +- * enum iwl_scan_flags - masks for power table command flags ++ * enum iwl_power_flags - masks for power table command flags + * @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off + * receiver and transmitter. '0' - does not allow. + * @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management, +diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h +index 989d7db..60dc387 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h ++++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h +@@ -142,6 +142,7 @@ enum { + /* Power - legacy power table command */ + POWER_TABLE_CMD = 0x77, + PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78, ++ LTR_CONFIG = 0xee, + + /* Thermal Throttling*/ + REPLY_THERMAL_MNG_BACKOFF = 0x7e, +@@ -1393,7 +1394,7 @@ enum iwl_sf_scenario { + #define SF_NUM_TIMEOUT_TYPES 2 /* Aging timer and Idle timer */ + + /* smart FIFO default values */ +-#define SF_W_MARK_SISO 4096 ++#define SF_W_MARK_SISO 6144 + #define SF_W_MARK_MIMO2 8192 + #define SF_W_MARK_MIMO3 6144 + #define SF_W_MARK_LEGACY 4096 +@@ -1415,14 +1416,14 @@ enum iwl_sf_scenario { + + /** + * Smart Fifo configuration command. +- * @state: smart fifo state, types listed in iwl_sf_sate. ++ * @state: smart fifo state, types listed in enum %iwl_sf_sate. + * @watermark: Minimum allowed availabe free space in RXF for transient state. + * @long_delay_timeouts: aging and idle timer values for each scenario + * in long delay state. + * @full_on_timeouts: timer values for each scenario in full on state. + */ + struct iwl_sf_cfg_cmd { +- enum iwl_sf_state state; ++ __le32 state; + __le32 watermark[SF_TRANSIENT_STATES_NUMBER]; + __le32 long_delay_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES]; + __le32 full_on_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES]; +diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c +index c03d395..2ef344f 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/fw.c ++++ b/drivers/net/wireless/iwlwifi/mvm/fw.c +@@ -439,6 +439,15 @@ int iwl_mvm_up(struct iwl_mvm *mvm) + goto error; + } + ++ if (mvm->trans->ltr_enabled) { ++ struct iwl_ltr_config_cmd cmd = { ++ .flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE), ++ }; ++ ++ WARN_ON(iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, ++ sizeof(cmd), &cmd)); ++ } ++ + ret = iwl_mvm_power_update_device_mode(mvm); + if (ret) + goto error; +diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c +index d06414e..4a3b8b7 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c +@@ -410,9 +410,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, + mvmvif->uploaded = false; + mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; + +- /* does this make sense at all? */ +- mvmvif->color++; +- + spin_lock_bh(&mvm->time_event_lock); + iwl_mvm_te_clear_data(mvm, &mvmvif->time_event_data); + spin_unlock_bh(&mvm->time_event_lock); +diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c +index a3d43de..dbff7f0 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/ops.c ++++ b/drivers/net/wireless/iwlwifi/mvm/ops.c +@@ -313,6 +313,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { + CMD(REPLY_BEACON_FILTERING_CMD), + CMD(REPLY_THERMAL_MNG_BACKOFF), + CMD(MAC_PM_POWER_TABLE), ++ CMD(LTR_CONFIG), + CMD(BT_COEX_CI), + CMD(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION), + }; +diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c +index 88809b2..dab8fd1 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/sf.c ++++ b/drivers/net/wireless/iwlwifi/mvm/sf.c +@@ -172,7 +172,7 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, + enum iwl_sf_state new_state) + { + struct iwl_sf_cfg_cmd sf_cmd = { +- .state = new_state, ++ .state = cpu_to_le32(new_state), + }; + struct ieee80211_sta *sta; + int ret = 0; +diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c +index 76ee486..4efcb28 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/tx.c ++++ b/drivers/net/wireless/iwlwifi/mvm/tx.c +@@ -835,6 +835,11 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, + sta_id = ba_notif->sta_id; + tid = ba_notif->tid; + ++ if (WARN_ONCE(sta_id >= IWL_MVM_STATION_COUNT || ++ tid >= IWL_MAX_TID_COUNT, ++ "sta_id %d tid %d", sta_id, tid)) ++ return 0; ++ + rcu_read_lock(); + + sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); +diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c +index df1f5e7..1ac33d9 100644 +--- a/drivers/net/wireless/iwlwifi/pcie/drv.c ++++ b/drivers/net/wireless/iwlwifi/pcie/drv.c +@@ -272,6 +272,8 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { + {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4072, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)}, ++ {IWL_PCI_DEVICE(0x08B1, 0x4C60, iwl7260_2ac_cfg)}, ++ {IWL_PCI_DEVICE(0x08B1, 0x4C70, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4060, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x406A, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4160, iwl7260_2n_cfg)}, +@@ -315,6 +317,8 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { + {IWL_PCI_DEVICE(0x08B1, 0xC770, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC760, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC270, iwl7260_2ac_cfg)}, ++ {IWL_PCI_DEVICE(0x08B1, 0xCC70, iwl7260_2ac_cfg)}, ++ {IWL_PCI_DEVICE(0x08B1, 0xCC60, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC272, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC260, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC26A, iwl7260_n_cfg)}, +diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c +index 16be0c0..fb62927 100644 +--- a/drivers/net/wireless/iwlwifi/pcie/trans.c ++++ b/drivers/net/wireless/iwlwifi/pcie/trans.c +@@ -94,6 +94,7 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans) + { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + u16 lctl; ++ u16 cap; + + /* + * HW bug W/A for instability in PCIe bus L0S->L1 transition. +@@ -104,16 +105,17 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans) + * power savings, even without L1. + */ + pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl); +- if (lctl & PCI_EXP_LNKCTL_ASPM_L1) { +- /* L1-ASPM enabled; disable(!) L0S */ ++ if (lctl & PCI_EXP_LNKCTL_ASPM_L1) + iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); +- dev_info(trans->dev, "L1 Enabled; Disabling L0S\n"); +- } else { +- /* L1-ASPM disabled; enable(!) L0S */ ++ else + iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); +- dev_info(trans->dev, "L1 Disabled; Enabling L0S\n"); +- } + trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S); ++ ++ pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_DEVCTL2, &cap); ++ trans->ltr_enabled = cap & PCI_EXP_DEVCTL2_LTR_EN; ++ dev_info(trans->dev, "L1 %sabled - LTR %sabled\n", ++ (lctl & PCI_EXP_LNKCTL_ASPM_L1) ? "En" : "Dis", ++ trans->ltr_enabled ? "En" : "Dis"); + } + + /* +diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c +index 3d54900..52427fb 100644 +--- a/drivers/net/wireless/iwlwifi/pcie/tx.c ++++ b/drivers/net/wireless/iwlwifi/pcie/tx.c +@@ -729,7 +729,12 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans) + iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, + trans_pcie->kw.dma >> 4); + +- iwl_pcie_tx_start(trans, trans_pcie->scd_base_addr); ++ /* ++ * Send 0 as the scd_base_addr since the device may have be reset ++ * while we were in WoWLAN in which case SCD_SRAM_BASE_ADDR will ++ * contain garbage. ++ */ ++ iwl_pcie_tx_start(trans, 0); + } + + /* +diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c +index 98718e4..5e836b1 100644 +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -1976,7 +1976,7 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, + if (err != 0) { + printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n", + err); +- goto failed_hw; ++ goto failed_bind; + } + + skb_queue_head_init(&data->pending); +@@ -2159,6 +2159,8 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, + return idx; + + failed_hw: ++ device_release_driver(data->dev); ++failed_bind: + device_unregister(data->dev); + failed_drvdata: + ieee80211_free_hw(hw); +diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h +index a394a9a..ebd5625 100644 +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -52,6 +52,7 @@ + * RF5592 2.4G/5G 2T2R + * RF3070 2.4G 1T1R + * RF5360 2.4G 1T1R ++ * RF5362 2.4G 1T1R + * RF5370 2.4G 1T1R + * RF5390 2.4G 1T1R + */ +@@ -72,6 +73,7 @@ + #define RF3070 0x3070 + #define RF3290 0x3290 + #define RF5360 0x5360 ++#define RF5362 0x5362 + #define RF5370 0x5370 + #define RF5372 0x5372 + #define RF5390 0x5390 +@@ -2039,7 +2041,7 @@ struct mac_iveiv_entry { + * 2 - drop tx power by 12dBm, + * 3 - increase tx power by 6dBm + */ +-#define BBP1_TX_POWER_CTRL FIELD8(0x07) ++#define BBP1_TX_POWER_CTRL FIELD8(0x03) + #define BBP1_TX_ANTENNA FIELD8(0x18) + + /* +@@ -2145,7 +2147,7 @@ struct mac_iveiv_entry { + /* Bits [7-4] for RF3320 (RT3370/RT3390), on other chipsets reserved */ + #define RFCSR3_PA1_BIAS_CCK FIELD8(0x70) + #define RFCSR3_PA2_CASCODE_BIAS_CCKK FIELD8(0x80) +-/* Bits for RF3290/RF5360/RF5370/RF5372/RF5390/RF5392 */ ++/* Bits for RF3290/RF5360/RF5362/RF5370/RF5372/RF5390/RF5392 */ + #define RFCSR3_VCOCAL_EN FIELD8(0x80) + /* Bits for RF3050 */ + #define RFCSR3_BIT1 FIELD8(0x02) +diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c +index 41d4a81..4e16d4d 100644 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -3142,6 +3142,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, + break; + case RF3070: + case RF5360: ++ case RF5362: + case RF5370: + case RF5372: + case RF5390: +@@ -3159,6 +3160,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, + rt2x00_rf(rt2x00dev, RF3290) || + rt2x00_rf(rt2x00dev, RF3322) || + rt2x00_rf(rt2x00dev, RF5360) || ++ rt2x00_rf(rt2x00dev, RF5362) || + rt2x00_rf(rt2x00dev, RF5370) || + rt2x00_rf(rt2x00dev, RF5372) || + rt2x00_rf(rt2x00dev, RF5390) || +@@ -4273,6 +4275,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev) + case RF3070: + case RF3290: + case RF5360: ++ case RF5362: + case RF5370: + case RF5372: + case RF5390: +@@ -7073,6 +7076,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) + case RF3320: + case RF3322: + case RF5360: ++ case RF5362: + case RF5370: + case RF5372: + case RF5390: +@@ -7529,6 +7533,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) + case RF3320: + case RF3322: + case RF5360: ++ case RF5362: + case RF5370: + case RF5372: + case RF5390: +@@ -7658,6 +7663,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) + case RF3070: + case RF3290: + case RF5360: ++ case RF5362: + case RF5370: + case RF5372: + case RF5390: +diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c +index caddc1b..e8abd0f 100644 +--- a/drivers/net/wireless/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/rt2x00/rt2800usb.c +@@ -991,6 +991,7 @@ static struct usb_device_id rt2800usb_device_table[] = { + { USB_DEVICE(0x07d1, 0x3c17) }, + { USB_DEVICE(0x2001, 0x3317) }, + { USB_DEVICE(0x2001, 0x3c1b) }, ++ { USB_DEVICE(0x2001, 0x3c25) }, + /* Draytek */ + { USB_DEVICE(0x07fa, 0x7712) }, + /* DVICO */ +@@ -1062,6 +1063,7 @@ static struct usb_device_id rt2800usb_device_table[] = { + /* Ovislink */ + { USB_DEVICE(0x1b75, 0x3071) }, + { USB_DEVICE(0x1b75, 0x3072) }, ++ { USB_DEVICE(0x1b75, 0xa200) }, + /* Para */ + { USB_DEVICE(0x20b8, 0x8888) }, + /* Pegatron */ +@@ -1235,6 +1237,8 @@ static struct usb_device_id rt2800usb_device_table[] = { + /* Arcadyan */ + { USB_DEVICE(0x043e, 0x7a12) }, + { USB_DEVICE(0x043e, 0x7a32) }, ++ /* ASUS */ ++ { USB_DEVICE(0x0b05, 0x17e8) }, + /* Azurewave */ + { USB_DEVICE(0x13d3, 0x3329) }, + { USB_DEVICE(0x13d3, 0x3365) }, +@@ -1271,6 +1275,7 @@ static struct usb_device_id rt2800usb_device_table[] = { + { USB_DEVICE(0x057c, 0x8501) }, + /* Buffalo */ + { USB_DEVICE(0x0411, 0x0241) }, ++ { USB_DEVICE(0x0411, 0x0253) }, + /* D-Link */ + { USB_DEVICE(0x2001, 0x3c1a) }, + { USB_DEVICE(0x2001, 0x3c21) }, +@@ -1361,6 +1366,7 @@ static struct usb_device_id rt2800usb_device_table[] = { + { USB_DEVICE(0x0df6, 0x0053) }, + { USB_DEVICE(0x0df6, 0x0069) }, + { USB_DEVICE(0x0df6, 0x006f) }, ++ { USB_DEVICE(0x0df6, 0x0078) }, + /* SMC */ + { USB_DEVICE(0x083a, 0xa512) }, + { USB_DEVICE(0x083a, 0xc522) }, +diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c +index 5642ccc..22d49d5 100644 +--- a/drivers/net/wireless/rt2x00/rt2x00queue.c ++++ b/drivers/net/wireless/rt2x00/rt2x00queue.c +@@ -158,55 +158,29 @@ void rt2x00queue_align_frame(struct sk_buff *skb) + skb_trim(skb, frame_length); + } + +-void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) ++/* ++ * H/W needs L2 padding between the header and the paylod if header size ++ * is not 4 bytes aligned. ++ */ ++void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int hdr_len) + { +- unsigned int payload_length = skb->len - header_length; +- unsigned int header_align = ALIGN_SIZE(skb, 0); +- unsigned int payload_align = ALIGN_SIZE(skb, header_length); +- unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0; ++ unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0; + +- /* +- * Adjust the header alignment if the payload needs to be moved more +- * than the header. +- */ +- if (payload_align > header_align) +- header_align += 4; +- +- /* There is nothing to do if no alignment is needed */ +- if (!header_align) ++ if (!l2pad) + return; + +- /* Reserve the amount of space needed in front of the frame */ +- skb_push(skb, header_align); +- +- /* +- * Move the header. +- */ +- memmove(skb->data, skb->data + header_align, header_length); +- +- /* Move the payload, if present and if required */ +- if (payload_length && payload_align) +- memmove(skb->data + header_length + l2pad, +- skb->data + header_length + l2pad + payload_align, +- payload_length); +- +- /* Trim the skb to the correct size */ +- skb_trim(skb, header_length + l2pad + payload_length); ++ skb_push(skb, l2pad); ++ memmove(skb->data, skb->data + l2pad, hdr_len); + } + +-void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) ++void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int hdr_len) + { +- /* +- * L2 padding is only present if the skb contains more than just the +- * IEEE 802.11 header. +- */ +- unsigned int l2pad = (skb->len > header_length) ? +- L2PAD_SIZE(header_length) : 0; ++ unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0; + + if (!l2pad) + return; + +- memmove(skb->data + l2pad, skb->data, header_length); ++ memmove(skb->data + l2pad, skb->data, hdr_len); + skb_pull(skb, l2pad); + } + +diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +index c613110..66c92a1 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +@@ -314,9 +314,11 @@ static struct usb_device_id rtl8192c_usb_ids[] = { + {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ + {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ + {RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/ ++ {RTL_USB_DEVICE(0x0b05, 0x17ba, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/ + {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/ + {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ + {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ ++ {RTL_USB_DEVICE(0x0df6, 0x0070, rtl92cu_hal_cfg)}, /*Sitecom - 150N */ + {RTL_USB_DEVICE(0x0df6, 0x0077, rtl92cu_hal_cfg)}, /*Sitecom-WLA2100V2*/ + {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/ + {RTL_USB_DEVICE(0x4856, 0x0091, rtl92cu_hal_cfg)}, /*NetweeN - Feixun*/ +@@ -369,6 +371,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { + {RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/ + {RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/ + {RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/ ++ {RTL_USB_DEVICE(0x2001, 0x330d, rtl92cu_hal_cfg)}, /*D-Link DWA-131 */ + {RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/ + {RTL_USB_DEVICE(0x20f4, 0x624d, rtl92cu_hal_cfg)}, /*TRENDNet*/ + {RTL_USB_DEVICE(0x2357, 0x0100, rtl92cu_hal_cfg)}, /*TP-Link WN8200ND*/ +diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c +index 4933f02..bc409ec 100644 +--- a/drivers/net/wireless/rtlwifi/usb.c ++++ b/drivers/net/wireless/rtlwifi/usb.c +@@ -126,7 +126,7 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request, + + do { + status = usb_control_msg(udev, pipe, request, reqtype, value, +- index, pdata, len, 0); /*max. timeout*/ ++ index, pdata, len, 1000); + if (status < 0) { + /* firmware download is checksumed, don't retry */ + if ((value >= FW_8192C_START_ADDRESS && +diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.c b/drivers/net/wireless/ti/wl18xx/debugfs.c +index 7f1669c..779dc2b 100644 +--- a/drivers/net/wireless/ti/wl18xx/debugfs.c ++++ b/drivers/net/wireless/ti/wl18xx/debugfs.c +@@ -136,7 +136,7 @@ WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, protection_filter, "%u"); + WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, accum_arp_pend_requests, "%u"); + WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, max_arp_queue_dep, "%u"); + +-WL18XX_DEBUGFS_FWSTATS_FILE(rx_rate, rx_frames_per_rates, "%u"); ++WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(rx_rate, rx_frames_per_rates, 50); + + WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(aggr_size, tx_agg_vs_rate, + AGGR_STATS_TX_AGG*AGGR_STATS_TX_RATE); +diff --git a/drivers/net/wireless/ti/wlcore/debugfs.h b/drivers/net/wireless/ti/wlcore/debugfs.h +index f7381dd..1bce432 100644 +--- a/drivers/net/wireless/ti/wlcore/debugfs.h ++++ b/drivers/net/wireless/ti/wlcore/debugfs.h +@@ -26,8 +26,8 @@ + + #include "wlcore.h" + +-int wl1271_format_buffer(char __user *userbuf, size_t count, +- loff_t *ppos, char *fmt, ...); ++__printf(4, 5) int wl1271_format_buffer(char __user *userbuf, size_t count, ++ loff_t *ppos, char *fmt, ...); + + int wl1271_debugfs_init(struct wl1271 *wl); + void wl1271_debugfs_exit(struct wl1271 *wl); +diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c +index 7a206cf..d18e653 100644 +--- a/drivers/net/xen-netback/xenbus.c ++++ b/drivers/net/xen-netback/xenbus.c +@@ -32,6 +32,8 @@ struct backend_info { + enum xenbus_state frontend_state; + struct xenbus_watch hotplug_status_watch; + u8 have_hotplug_status_watch:1; ++ ++ const char *hotplug_script; + }; + + static int connect_rings(struct backend_info *); +@@ -54,6 +56,7 @@ static int netback_remove(struct xenbus_device *dev) + xenvif_free(be->vif); + be->vif = NULL; + } ++ kfree(be->hotplug_script); + kfree(be); + dev_set_drvdata(&dev->dev, NULL); + return 0; +@@ -71,6 +74,7 @@ static int netback_probe(struct xenbus_device *dev, + struct xenbus_transaction xbt; + int err; + int sg; ++ const char *script; + struct backend_info *be = kzalloc(sizeof(struct backend_info), + GFP_KERNEL); + if (!be) { +@@ -157,6 +161,15 @@ static int netback_probe(struct xenbus_device *dev, + if (err) + pr_debug("Error writing feature-split-event-channels\n"); + ++ script = xenbus_read(XBT_NIL, dev->nodename, "script", NULL); ++ if (IS_ERR(script)) { ++ err = PTR_ERR(script); ++ xenbus_dev_fatal(dev, err, "reading script"); ++ goto fail; ++ } ++ ++ be->hotplug_script = script; ++ + err = xenbus_switch_state(dev, XenbusStateInitWait); + if (err) + goto fail; +@@ -187,22 +200,14 @@ static int netback_uevent(struct xenbus_device *xdev, + struct kobj_uevent_env *env) + { + struct backend_info *be = dev_get_drvdata(&xdev->dev); +- char *val; + +- val = xenbus_read(XBT_NIL, xdev->nodename, "script", NULL); +- if (IS_ERR(val)) { +- int err = PTR_ERR(val); +- xenbus_dev_fatal(xdev, err, "reading script"); +- return err; +- } else { +- if (add_uevent_var(env, "script=%s", val)) { +- kfree(val); +- return -ENOMEM; +- } +- kfree(val); +- } ++ if (!be) ++ return 0; ++ ++ if (add_uevent_var(env, "script=%s", be->hotplug_script)) ++ return -ENOMEM; + +- if (!be || !be->vif) ++ if (!be->vif) + return 0; + + return add_uevent_var(env, "vif=%s", be->vif->dev->name); +diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c +index e30d800..19db057 100644 +--- a/drivers/net/xen-netfront.c ++++ b/drivers/net/xen-netfront.c +@@ -469,9 +469,6 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, + len = skb_frag_size(frag); + offset = frag->page_offset; + +- /* Data must not cross a page boundary. */ +- BUG_ON(len + offset > PAGE_SIZE<> PAGE_SHIFT; + offset &= ~PAGE_MASK; +@@ -479,8 +476,6 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, + while (len > 0) { + unsigned long bytes; + +- BUG_ON(offset >= PAGE_SIZE); +- + bytes = PAGE_SIZE - offset; + if (bytes > len) + bytes = len; +diff --git a/drivers/nfc/microread/microread.c b/drivers/nfc/microread/microread.c +index f868333..963a4a5 100644 +--- a/drivers/nfc/microread/microread.c ++++ b/drivers/nfc/microread/microread.c +@@ -501,9 +501,13 @@ static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate, + targets->sens_res = + be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A_ATQA]); + targets->sel_res = skb->data[MICROREAD_EMCF_A_SAK]; +- memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A_UID], +- skb->data[MICROREAD_EMCF_A_LEN]); + targets->nfcid1_len = skb->data[MICROREAD_EMCF_A_LEN]; ++ if (targets->nfcid1_len > sizeof(targets->nfcid1)) { ++ r = -EINVAL; ++ goto exit_free; ++ } ++ memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A_UID], ++ targets->nfcid1_len); + break; + case MICROREAD_GATE_ID_MREAD_ISO_A_3: + targets->supported_protocols = +@@ -511,9 +515,13 @@ static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate, + targets->sens_res = + be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A3_ATQA]); + targets->sel_res = skb->data[MICROREAD_EMCF_A3_SAK]; +- memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A3_UID], +- skb->data[MICROREAD_EMCF_A3_LEN]); + targets->nfcid1_len = skb->data[MICROREAD_EMCF_A3_LEN]; ++ if (targets->nfcid1_len > sizeof(targets->nfcid1)) { ++ r = -EINVAL; ++ goto exit_free; ++ } ++ memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A3_UID], ++ targets->nfcid1_len); + break; + case MICROREAD_GATE_ID_MREAD_ISO_B: + targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK; +diff --git a/drivers/of/address.c b/drivers/of/address.c +index 1a54f1f..9eae613 100644 +--- a/drivers/of/address.c ++++ b/drivers/of/address.c +@@ -401,6 +401,21 @@ static struct of_bus *of_match_bus(struct device_node *np) + return NULL; + } + ++static int of_empty_ranges_quirk(void) ++{ ++ if (IS_ENABLED(CONFIG_PPC)) { ++ /* To save cycles, we cache the result */ ++ static int quirk_state = -1; ++ ++ if (quirk_state < 0) ++ quirk_state = ++ of_machine_is_compatible("Power Macintosh") || ++ of_machine_is_compatible("MacRISC"); ++ return quirk_state; ++ } ++ return false; ++} ++ + static int of_translate_one(struct device_node *parent, struct of_bus *bus, + struct of_bus *pbus, __be32 *addr, + int na, int ns, int pna, const char *rprop) +@@ -426,12 +441,10 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, + * This code is only enabled on powerpc. --gcl + */ + ranges = of_get_property(parent, rprop, &rlen); +-#if !defined(CONFIG_PPC) +- if (ranges == NULL) { ++ if (ranges == NULL && !of_empty_ranges_quirk()) { + pr_err("OF: no ranges; cannot translate\n"); + return 1; + } +-#endif /* !defined(CONFIG_PPC) */ + if (ranges == NULL || rlen == 0) { + offset = of_read_number(addr, na); + memset(addr, 0, pna * 4); +@@ -691,10 +704,10 @@ struct device_node *of_find_matching_node_by_address(struct device_node *from, + struct resource res; + + while (dn) { +- if (of_address_to_resource(dn, 0, &res)) +- continue; +- if (res.start == base_address) ++ if (!of_address_to_resource(dn, 0, &res) && ++ res.start == base_address) + return dn; ++ + dn = of_find_matching_node(dn, matches); + } + +diff --git a/drivers/of/base.c b/drivers/of/base.c +index 89e888a..e99f329 100644 +--- a/drivers/of/base.c ++++ b/drivers/of/base.c +@@ -77,7 +77,7 @@ EXPORT_SYMBOL(of_n_size_cells); + #ifdef CONFIG_NUMA + int __weak of_node_to_nid(struct device_node *np) + { +- return numa_node_id(); ++ return NUMA_NO_NODE; + } + #endif + +@@ -1117,52 +1117,6 @@ int of_property_read_string(struct device_node *np, const char *propname, + EXPORT_SYMBOL_GPL(of_property_read_string); + + /** +- * of_property_read_string_index - Find and read a string from a multiple +- * strings property. +- * @np: device node from which the property value is to be read. +- * @propname: name of the property to be searched. +- * @index: index of the string in the list of strings +- * @out_string: pointer to null terminated return string, modified only if +- * return value is 0. +- * +- * Search for a property in a device tree node and retrieve a null +- * terminated string value (pointer to data, not a copy) in the list of strings +- * contained in that property. +- * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if +- * property does not have a value, and -EILSEQ if the string is not +- * null-terminated within the length of the property data. +- * +- * The out_string pointer is modified only if a valid string can be decoded. +- */ +-int of_property_read_string_index(struct device_node *np, const char *propname, +- int index, const char **output) +-{ +- struct property *prop = of_find_property(np, propname, NULL); +- int i = 0; +- size_t l = 0, total = 0; +- const char *p; +- +- if (!prop) +- return -EINVAL; +- if (!prop->value) +- return -ENODATA; +- if (strnlen(prop->value, prop->length) >= prop->length) +- return -EILSEQ; +- +- p = prop->value; +- +- for (i = 0; total < prop->length; total += l, p += l) { +- l = strlen(p) + 1; +- if (i++ == index) { +- *output = p; +- return 0; +- } +- } +- return -ENODATA; +-} +-EXPORT_SYMBOL_GPL(of_property_read_string_index); +- +-/** + * of_property_match_string() - Find string in a list and return index + * @np: pointer to node containing string list property + * @propname: string list property name +@@ -1188,7 +1142,7 @@ int of_property_match_string(struct device_node *np, const char *propname, + end = p + prop->length; + + for (i = 0; p < end; i++, p += l) { +- l = strlen(p) + 1; ++ l = strnlen(p, end - p) + 1; + if (p + l > end) + return -EILSEQ; + pr_debug("comparing %s with %s\n", string, p); +@@ -1200,39 +1154,41 @@ int of_property_match_string(struct device_node *np, const char *propname, + EXPORT_SYMBOL_GPL(of_property_match_string); + + /** +- * of_property_count_strings - Find and return the number of strings from a +- * multiple strings property. ++ * of_property_read_string_util() - Utility helper for parsing string properties + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. ++ * @out_strs: output array of string pointers. ++ * @sz: number of array elements to read. ++ * @skip: Number of strings to skip over at beginning of list. + * +- * Search for a property in a device tree node and retrieve the number of null +- * terminated string contain in it. Returns the number of strings on +- * success, -EINVAL if the property does not exist, -ENODATA if property +- * does not have a value, and -EILSEQ if the string is not null-terminated +- * within the length of the property data. ++ * Don't call this function directly. It is a utility helper for the ++ * of_property_read_string*() family of functions. + */ +-int of_property_count_strings(struct device_node *np, const char *propname) ++int of_property_read_string_helper(struct device_node *np, const char *propname, ++ const char **out_strs, size_t sz, int skip) + { + struct property *prop = of_find_property(np, propname, NULL); +- int i = 0; +- size_t l = 0, total = 0; +- const char *p; ++ int l = 0, i = 0; ++ const char *p, *end; + + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; +- if (strnlen(prop->value, prop->length) >= prop->length) +- return -EILSEQ; +- + p = prop->value; ++ end = p + prop->length; + +- for (i = 0; total < prop->length; total += l, p += l, i++) +- l = strlen(p) + 1; +- +- return i; ++ for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) { ++ l = strnlen(p, end - p) + 1; ++ if (p + l > end) ++ return -EILSEQ; ++ if (out_strs && i >= skip) ++ *out_strs++ = p; ++ } ++ i -= skip; ++ return i <= 0 ? -ENODATA : i; + } +-EXPORT_SYMBOL_GPL(of_property_count_strings); ++EXPORT_SYMBOL_GPL(of_property_read_string_helper); + + void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) + { +diff --git a/drivers/of/irq.c b/drivers/of/irq.c +index ca01893..bbff99d 100644 +--- a/drivers/of/irq.c ++++ b/drivers/of/irq.c +@@ -290,7 +290,7 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar + struct device_node *p; + const __be32 *intspec, *tmp, *addr; + u32 intsize, intlen; +- int i, res = -EINVAL; ++ int i, res; + + pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index); + +@@ -301,16 +301,17 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar + /* Get the reg property (if any) */ + addr = of_get_property(device, "reg", NULL); + ++ /* Try the new-style interrupts-extended first */ ++ res = of_parse_phandle_with_args(device, "interrupts-extended", ++ "#interrupt-cells", index, out_irq); ++ if (!res) ++ return of_irq_parse_raw(addr, out_irq); ++ + /* Get the interrupts property */ + intspec = of_get_property(device, "interrupts", &intlen); +- if (intspec == NULL) { +- /* Try the new-style interrupts-extended */ +- res = of_parse_phandle_with_args(device, "interrupts-extended", +- "#interrupt-cells", index, out_irq); +- if (res) +- return -EINVAL; +- return of_irq_parse_raw(addr, out_irq); +- } ++ if (intspec == NULL) ++ return -EINVAL; ++ + intlen /= sizeof(*intspec); + + pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen); +@@ -322,15 +323,19 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar + + /* Get size of interrupt specifier */ + tmp = of_get_property(p, "#interrupt-cells", NULL); +- if (tmp == NULL) ++ if (tmp == NULL) { ++ res = -EINVAL; + goto out; ++ } + intsize = be32_to_cpu(*tmp); + + pr_debug(" intsize=%d intlen=%d\n", intsize, intlen); + + /* Check index */ +- if ((index + 1) * intsize > intlen) ++ if ((index + 1) * intsize > intlen) { ++ res = -EINVAL; + goto out; ++ } + + /* Copy intspec into irq structure */ + intspec += index * intsize; +diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c +index 6643d19..70c61d7 100644 +--- a/drivers/of/selftest.c ++++ b/drivers/of/selftest.c +@@ -132,8 +132,9 @@ static void __init of_selftest_parse_phandle_with_args(void) + selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + } + +-static void __init of_selftest_property_match_string(void) ++static void __init of_selftest_property_string(void) + { ++ const char *strings[4]; + struct device_node *np; + int rc; + +@@ -150,13 +151,66 @@ static void __init of_selftest_property_match_string(void) + rc = of_property_match_string(np, "phandle-list-names", "third"); + selftest(rc == 2, "third expected:0 got:%i\n", rc); + rc = of_property_match_string(np, "phandle-list-names", "fourth"); +- selftest(rc == -ENODATA, "unmatched string; rc=%i", rc); ++ selftest(rc == -ENODATA, "unmatched string; rc=%i\n", rc); + rc = of_property_match_string(np, "missing-property", "blah"); +- selftest(rc == -EINVAL, "missing property; rc=%i", rc); ++ selftest(rc == -EINVAL, "missing property; rc=%i\n", rc); + rc = of_property_match_string(np, "empty-property", "blah"); +- selftest(rc == -ENODATA, "empty property; rc=%i", rc); ++ selftest(rc == -ENODATA, "empty property; rc=%i\n", rc); + rc = of_property_match_string(np, "unterminated-string", "blah"); +- selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc); ++ selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc); ++ ++ /* of_property_count_strings() tests */ ++ rc = of_property_count_strings(np, "string-property"); ++ selftest(rc == 1, "Incorrect string count; rc=%i\n", rc); ++ rc = of_property_count_strings(np, "phandle-list-names"); ++ selftest(rc == 3, "Incorrect string count; rc=%i\n", rc); ++ rc = of_property_count_strings(np, "unterminated-string"); ++ selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc); ++ rc = of_property_count_strings(np, "unterminated-string-list"); ++ selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc); ++ ++ /* of_property_read_string_index() tests */ ++ rc = of_property_read_string_index(np, "string-property", 0, strings); ++ selftest(rc == 0 && !strcmp(strings[0], "foobar"), "of_property_read_string_index() failure; rc=%i\n", rc); ++ strings[0] = NULL; ++ rc = of_property_read_string_index(np, "string-property", 1, strings); ++ selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); ++ rc = of_property_read_string_index(np, "phandle-list-names", 0, strings); ++ selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc); ++ rc = of_property_read_string_index(np, "phandle-list-names", 1, strings); ++ selftest(rc == 0 && !strcmp(strings[0], "second"), "of_property_read_string_index() failure; rc=%i\n", rc); ++ rc = of_property_read_string_index(np, "phandle-list-names", 2, strings); ++ selftest(rc == 0 && !strcmp(strings[0], "third"), "of_property_read_string_index() failure; rc=%i\n", rc); ++ strings[0] = NULL; ++ rc = of_property_read_string_index(np, "phandle-list-names", 3, strings); ++ selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); ++ strings[0] = NULL; ++ rc = of_property_read_string_index(np, "unterminated-string", 0, strings); ++ selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); ++ rc = of_property_read_string_index(np, "unterminated-string-list", 0, strings); ++ selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc); ++ strings[0] = NULL; ++ rc = of_property_read_string_index(np, "unterminated-string-list", 2, strings); /* should fail */ ++ selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); ++ strings[1] = NULL; ++ ++ /* of_property_read_string_array() tests */ ++ rc = of_property_read_string_array(np, "string-property", strings, 4); ++ selftest(rc == 1, "Incorrect string count; rc=%i\n", rc); ++ rc = of_property_read_string_array(np, "phandle-list-names", strings, 4); ++ selftest(rc == 3, "Incorrect string count; rc=%i\n", rc); ++ rc = of_property_read_string_array(np, "unterminated-string", strings, 4); ++ selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc); ++ /* -- An incorrectly formed string should cause a failure */ ++ rc = of_property_read_string_array(np, "unterminated-string-list", strings, 4); ++ selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc); ++ /* -- parsing the correctly formed strings should still work: */ ++ strings[2] = NULL; ++ rc = of_property_read_string_array(np, "unterminated-string-list", strings, 2); ++ selftest(rc == 2 && strings[2] == NULL, "of_property_read_string_array() failure; rc=%i\n", rc); ++ strings[1] = NULL; ++ rc = of_property_read_string_array(np, "phandle-list-names", strings, 1); ++ selftest(rc == 1 && strings[1] == NULL, "Overwrote end of string array; rc=%i, str='%s'\n", rc, strings[1]); + } + + static void __init of_selftest_parse_interrupts(void) +@@ -379,7 +433,7 @@ static int __init of_selftest(void) + + pr_info("start of selftest - you will see error messages\n"); + of_selftest_parse_phandle_with_args(); +- of_selftest_property_match_string(); ++ of_selftest_property_string(); + of_selftest_parse_interrupts(); + of_selftest_parse_interrupts_extended(); + of_selftest_match_node(); +diff --git a/drivers/of/testcase-data/tests-phandle.dtsi b/drivers/of/testcase-data/tests-phandle.dtsi +index 0007d3c..eedee37 100644 +--- a/drivers/of/testcase-data/tests-phandle.dtsi ++++ b/drivers/of/testcase-data/tests-phandle.dtsi +@@ -32,7 +32,9 @@ + phandle-list-bad-args = <&provider2 1 0>, + <&provider3 0>; + empty-property; ++ string-property = "foobar"; + unterminated-string = [40 41 42 43]; ++ unterminated-string-list = "first", "second", [40 41 42 43]; + }; + }; + }; +diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig +index 2872ece..44333bd 100644 +--- a/drivers/parport/Kconfig ++++ b/drivers/parport/Kconfig +@@ -5,6 +5,12 @@ + # Parport configuration. + # + ++config ARCH_MIGHT_HAVE_PC_PARPORT ++ bool ++ help ++ Select this config option from the architecture Kconfig if ++ the architecture might have PC parallel port hardware. ++ + menuconfig PARPORT + tristate "Parallel port support" + depends on HAS_IOMEM +@@ -31,12 +37,6 @@ menuconfig PARPORT + + If unsure, say Y. + +-config ARCH_MIGHT_HAVE_PC_PARPORT +- bool +- help +- Select this config option from the architecture Kconfig if +- the architecture might have PC parallel port hardware. +- + if PARPORT + + config PARPORT_PC +diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c +index 483d9ad..9773667 100644 +--- a/drivers/pci/host/pci-mvebu.c ++++ b/drivers/pci/host/pci-mvebu.c +@@ -855,7 +855,7 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn, + rangesz = pna + na + ns; + nranges = rlen / sizeof(__be32) / rangesz; + +- for (i = 0; i < nranges; i++) { ++ for (i = 0; i < nranges; i++, range += rangesz) { + u32 flags = of_read_number(range, 1); + u32 slot = of_read_number(range + 1, 1); + u64 cpuaddr = of_read_number(range + na, pna); +@@ -865,14 +865,14 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn, + rtype = IORESOURCE_IO; + else if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_MEM32) + rtype = IORESOURCE_MEM; ++ else ++ continue; + + if (slot == PCI_SLOT(devfn) && type == rtype) { + *tgt = DT_CPUADDR_TO_TARGET(cpuaddr); + *attr = DT_CPUADDR_TO_ATTR(cpuaddr); + return 0; + } +- +- range += rangesz; + } + + return -ENOENT; +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index fb02fc2..ced17f2 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -599,6 +599,20 @@ error_attrs: + return ret; + } + ++static int msi_verify_entries(struct pci_dev *dev) ++{ ++ struct msi_desc *entry; ++ ++ list_for_each_entry(entry, &dev->msi_list, list) { ++ if (!dev->no_64bit_msi || !entry->msg.address_hi) ++ continue; ++ dev_err(&dev->dev, "Device has broken 64-bit MSI but arch" ++ " tried to assign one above 4G\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ + /** + * msi_capability_init - configure device's MSI capability structure + * @dev: pointer to the pci_dev data structure of MSI device function +@@ -652,6 +666,13 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) + return ret; + } + ++ ret = msi_verify_entries(dev); ++ if (ret) { ++ msi_mask_irq(entry, mask, ~mask); ++ free_msi_irqs(dev); ++ return ret; ++ } ++ + ret = populate_msi_sysfs(dev); + if (ret) { + msi_mask_irq(entry, mask, ~mask); +@@ -767,6 +788,11 @@ static int msix_capability_init(struct pci_dev *dev, + if (ret) + goto out_avail; + ++ /* Check if all MSI entries honor device restrictions */ ++ ret = msi_verify_entries(dev); ++ if (ret) ++ goto out_free; ++ + /* + * Some devices require MSI-X to be enabled before we can touch the + * MSI-X registers. We need to mask all the vectors to prevent +diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c +index 25f0bc6..7f41551 100644 +--- a/drivers/pci/pci-driver.c ++++ b/drivers/pci/pci-driver.c +@@ -1324,7 +1324,7 @@ static int pci_uevent(struct device *dev, struct kobj_uevent_env *env) + if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev))) + return -ENOMEM; + +- if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x", ++ if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02X", + pdev->vendor, pdev->device, + pdev->subsystem_vendor, pdev->subsystem_device, + (u8)(pdev->class >> 16), (u8)(pdev->class >> 8), +diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c +index 45113da..e27a3dc 100644 +--- a/drivers/pci/pci-label.c ++++ b/drivers/pci/pci-label.c +@@ -168,8 +168,8 @@ enum acpi_attr_enum { + static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf) + { + int len; +- len = utf16s_to_utf8s((const wchar_t *)obj->string.pointer, +- obj->string.length, ++ len = utf16s_to_utf8s((const wchar_t *)obj->buffer.pointer, ++ obj->buffer.length, + UTF16_LITTLE_ENDIAN, + buf, PAGE_SIZE); + buf[len] = '\n'; +@@ -194,16 +194,22 @@ dsm_get_label(struct device *dev, char *buf, enum acpi_attr_enum attr) + tmp = obj->package.elements; + if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 2 && + tmp[0].type == ACPI_TYPE_INTEGER && +- tmp[1].type == ACPI_TYPE_STRING) { ++ (tmp[1].type == ACPI_TYPE_STRING || ++ tmp[1].type == ACPI_TYPE_BUFFER)) { + /* + * The second string element is optional even when + * this _DSM is implemented; when not implemented, + * this entry must return a null string. + */ +- if (attr == ACPI_ATTR_INDEX_SHOW) ++ if (attr == ACPI_ATTR_INDEX_SHOW) { + scnprintf(buf, PAGE_SIZE, "%llu\n", tmp->integer.value); +- else if (attr == ACPI_ATTR_LABEL_SHOW) +- dsm_label_utf16s_to_utf8s(tmp + 1, buf); ++ } else if (attr == ACPI_ATTR_LABEL_SHOW) { ++ if (tmp[1].type == ACPI_TYPE_STRING) ++ scnprintf(buf, PAGE_SIZE, "%s\n", ++ tmp[1].string.pointer); ++ else if (tmp[1].type == ACPI_TYPE_BUFFER) ++ dsm_label_utf16s_to_utf8s(tmp + 1, buf); ++ } + len = strlen(buf) > 0 ? strlen(buf) : -1; + } + +diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c +index 276ef9c..a943c6c 100644 +--- a/drivers/pci/pci-sysfs.c ++++ b/drivers/pci/pci-sysfs.c +@@ -178,7 +178,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + { + struct pci_dev *pci_dev = to_pci_dev(dev); + +- return sprintf(buf, "pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n", ++ return sprintf(buf, "pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02X\n", + pci_dev->vendor, pci_dev->device, + pci_dev->subsystem_vendor, pci_dev->subsystem_device, + (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8), +@@ -186,9 +186,9 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + } + static DEVICE_ATTR_RO(modalias); + +-static ssize_t enabled_store(struct device *dev, +- struct device_attribute *attr, const char *buf, +- size_t count) ++static ssize_t enable_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, ++ size_t count) + { + struct pci_dev *pdev = to_pci_dev(dev); + unsigned long val; +@@ -212,15 +212,15 @@ static ssize_t enabled_store(struct device *dev, + return result < 0 ? result : count; + } + +-static ssize_t enabled_show(struct device *dev, +- struct device_attribute *attr, char *buf) ++static ssize_t enable_show(struct device *dev, ++ struct device_attribute *attr, char *buf) + { + struct pci_dev *pdev; + + pdev = to_pci_dev (dev); + return sprintf (buf, "%u\n", atomic_read(&pdev->enable_cnt)); + } +-static DEVICE_ATTR_RW(enabled); ++static DEVICE_ATTR_RW(enable); + + #ifdef CONFIG_NUMA + static ssize_t +@@ -526,7 +526,7 @@ static struct attribute *pci_dev_attrs[] = { + #endif + &dev_attr_dma_mask_bits.attr, + &dev_attr_consistent_dma_mask_bits.attr, +- &dev_attr_enabled.attr, ++ &dev_attr_enable.attr, + &dev_attr_broken_parity_status.attr, + &dev_attr_msi_bus.attr, + #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI) +diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c +index be36adf..78c65d3 100644 +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -830,12 +830,6 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) + + if (!__pci_complete_power_transition(dev, state)) + error = 0; +- /* +- * When aspm_policy is "powersave" this call ensures +- * that ASPM is configured. +- */ +- if (!error && dev->bus->self) +- pcie_aspm_powersave_config_link(dev->bus->self); + + return error; + } +@@ -1181,12 +1175,18 @@ EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state); + static int do_pci_enable_device(struct pci_dev *dev, int bars) + { + int err; ++ struct pci_dev *bridge; + u16 cmd; + u8 pin; + + err = pci_set_power_state(dev, PCI_D0); + if (err < 0 && err != -EIO) + return err; ++ ++ bridge = pci_upstream_bridge(dev); ++ if (bridge) ++ pcie_aspm_powersave_config_link(bridge); ++ + err = pcibios_enable_device(dev, bars); + if (err < 0) + return err; +@@ -3187,7 +3187,8 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe) + { + struct pci_dev *pdev; + +- if (pci_is_root_bus(dev->bus) || dev->subordinate || !dev->bus->self) ++ if (pci_is_root_bus(dev->bus) || dev->subordinate || ++ !dev->bus->self || dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET) + return -ENOTTY; + + list_for_each_entry(pdev, &dev->bus->devices, bus_list) +@@ -3221,7 +3222,8 @@ static int pci_dev_reset_slot_function(struct pci_dev *dev, int probe) + { + struct pci_dev *pdev; + +- if (dev->subordinate || !dev->slot) ++ if (dev->subordinate || !dev->slot || ++ dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET) + return -ENOTTY; + + list_for_each_entry(pdev, &dev->bus->devices, bus_list) +@@ -3452,6 +3454,20 @@ int pci_try_reset_function(struct pci_dev *dev) + } + EXPORT_SYMBOL_GPL(pci_try_reset_function); + ++/* Do any devices on or below this bus prevent a bus reset? */ ++static bool pci_bus_resetable(struct pci_bus *bus) ++{ ++ struct pci_dev *dev; ++ ++ list_for_each_entry(dev, &bus->devices, bus_list) { ++ if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || ++ (dev->subordinate && !pci_bus_resetable(dev->subordinate))) ++ return false; ++ } ++ ++ return true; ++} ++ + /* Lock devices from the top of the tree down */ + static void pci_bus_lock(struct pci_bus *bus) + { +@@ -3502,6 +3518,22 @@ unlock: + return 0; + } + ++/* Do any devices on or below this slot prevent a bus reset? */ ++static bool pci_slot_resetable(struct pci_slot *slot) ++{ ++ struct pci_dev *dev; ++ ++ list_for_each_entry(dev, &slot->bus->devices, bus_list) { ++ if (!dev->slot || dev->slot != slot) ++ continue; ++ if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || ++ (dev->subordinate && !pci_bus_resetable(dev->subordinate))) ++ return false; ++ } ++ ++ return true; ++} ++ + /* Lock devices from the top of the tree down */ + static void pci_slot_lock(struct pci_slot *slot) + { +@@ -3623,7 +3655,7 @@ static int pci_slot_reset(struct pci_slot *slot, int probe) + { + int rc; + +- if (!slot) ++ if (!slot || !pci_slot_resetable(slot)) + return -ENOTTY; + + if (!probe) +@@ -3715,7 +3747,7 @@ EXPORT_SYMBOL_GPL(pci_try_reset_slot); + + static int pci_bus_reset(struct pci_bus *bus, int probe) + { +- if (!bus->self) ++ if (!bus->self || !pci_bus_resetable(bus)) + return -ENOTTY; + + if (probe) +diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c +index 34ff702..5d3b456 100644 +--- a/drivers/pci/pcie/aer/aerdrv_errprint.c ++++ b/drivers/pci/pcie/aer/aerdrv_errprint.c +@@ -127,16 +127,8 @@ static const char *aer_agent_string[] = { + static void __print_tlp_header(struct pci_dev *dev, + struct aer_header_log_regs *t) + { +- unsigned char *tlp = (unsigned char *)&t; +- +- dev_err(&dev->dev, " TLP Header:" +- " %02x%02x%02x%02x %02x%02x%02x%02x" +- " %02x%02x%02x%02x %02x%02x%02x%02x\n", +- *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, +- *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), +- *(tlp + 11), *(tlp + 10), *(tlp + 9), +- *(tlp + 8), *(tlp + 15), *(tlp + 14), +- *(tlp + 13), *(tlp + 12)); ++ dev_err(&dev->dev, " TLP Header: %08x %08x %08x %08x\n", ++ t->dw0, t->dw1, t->dw2, t->dw3); + } + + static void __aer_print_error(struct pci_dev *dev, +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index 6e34498..5b428db 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -214,14 +214,17 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, + res->flags |= IORESOURCE_SIZEALIGN; + if (res->flags & IORESOURCE_IO) { + l &= PCI_BASE_ADDRESS_IO_MASK; ++ sz &= PCI_BASE_ADDRESS_IO_MASK; + mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT; + } else { + l &= PCI_BASE_ADDRESS_MEM_MASK; ++ sz &= PCI_BASE_ADDRESS_MEM_MASK; + mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; + } + } else { + res->flags |= (l & IORESOURCE_ROM_ENABLE); + l &= PCI_ROM_ADDRESS_MASK; ++ sz &= PCI_ROM_ADDRESS_MASK; + mask = (u32)PCI_ROM_ADDRESS_MASK; + } + +@@ -395,15 +398,16 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child) + { + struct pci_dev *dev = child->self; + u16 mem_base_lo, mem_limit_lo; +- unsigned long base, limit; ++ u64 base64, limit64; ++ dma_addr_t base, limit; + struct pci_bus_region region; + struct resource *res; + + res = child->resource[2]; + pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); + pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); +- base = ((unsigned long) mem_base_lo & PCI_PREF_RANGE_MASK) << 16; +- limit = ((unsigned long) mem_limit_lo & PCI_PREF_RANGE_MASK) << 16; ++ base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16; ++ limit64 = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16; + + if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) { + u32 mem_base_hi, mem_limit_hi; +@@ -417,18 +421,20 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child) + * this, just assume they are not being used. + */ + if (mem_base_hi <= mem_limit_hi) { +-#if BITS_PER_LONG == 64 +- base |= ((unsigned long) mem_base_hi) << 32; +- limit |= ((unsigned long) mem_limit_hi) << 32; +-#else +- if (mem_base_hi || mem_limit_hi) { +- dev_err(&dev->dev, "can't handle 64-bit " +- "address space for bridge\n"); +- return; +- } +-#endif ++ base64 |= (u64) mem_base_hi << 32; ++ limit64 |= (u64) mem_limit_hi << 32; + } + } ++ ++ base = (dma_addr_t) base64; ++ limit = (dma_addr_t) limit64; ++ ++ if (base != base64) { ++ dev_err(&dev->dev, "can't handle bridge window above 4GB (bus address %#010llx)\n", ++ (unsigned long long) base64); ++ return; ++ } ++ + if (base <= limit) { + res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) | + IORESOURCE_MEM | IORESOURCE_PREFETCH; +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 813f437..2afa480 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include /* isa_dma_bridge_buggy */ + #include "pci.h" + +@@ -287,6 +288,25 @@ static void quirk_citrine(struct pci_dev *dev) + } + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, quirk_citrine); + ++/* On IBM Crocodile ipr SAS adapters, expand BAR to system page size */ ++static void quirk_extend_bar_to_page(struct pci_dev *dev) ++{ ++ int i; ++ ++ for (i = 0; i < PCI_STD_RESOURCE_END; i++) { ++ struct resource *r = &dev->resource[i]; ++ ++ if (r->flags & IORESOURCE_MEM && resource_size(r) < PAGE_SIZE) { ++ r->end = PAGE_SIZE - 1; ++ r->start = 0; ++ r->flags |= IORESOURCE_UNSET; ++ dev_info(&dev->dev, "expanded BAR %d to page size: %pR\n", ++ i, r); ++ } ++ } ++} ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, 0x034a, quirk_extend_bar_to_page); ++ + /* + * S3 868 and 968 chips report region size equal to 32M, but they decode 64M. + * If it's needed, re-allocate the region. +@@ -2770,12 +2790,15 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors); + + static void fixup_ti816x_class(struct pci_dev *dev) + { ++ u32 class = dev->class; ++ + /* TI 816x devices do not have class code set when in PCIe boot mode */ +- dev_info(&dev->dev, "Setting PCI class for 816x PCIe device\n"); +- dev->class = PCI_CLASS_MULTIMEDIA_VIDEO; ++ dev->class = PCI_CLASS_MULTIMEDIA_VIDEO << 8; ++ dev_info(&dev->dev, "PCI class overridden (%#08x -> %#08x)\n", ++ class, dev->class); + } + DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_TI, 0xb800, +- PCI_CLASS_NOT_DEFINED, 0, fixup_ti816x_class); ++ PCI_CLASS_NOT_DEFINED, 0, fixup_ti816x_class); + + /* Some PCIe devices do not work reliably with the claimed maximum + * payload size supported. +@@ -2988,6 +3011,20 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CHELSIO, 0x0030, + DECLARE_PCI_FIXUP_HEADER(0x1814, 0x0601, /* Ralink RT2800 802.11n PCI */ + quirk_broken_intx_masking); + ++static void quirk_no_bus_reset(struct pci_dev *dev) ++{ ++ dev->dev_flags |= PCI_DEV_FLAGS_NO_BUS_RESET; ++} ++ ++/* ++ * Atheros AR93xx chips do not behave after a bus reset. The device will ++ * throw a Link Down error on AER-capable systems and regardless of AER, ++ * config space of the device is never accessible again and typically ++ * causes the system to hang or reset when access is attempted. ++ * http://www.spinics.net/lists/linux-pci/msg34797.html ++ */ ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, quirk_no_bus_reset); ++ + static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, + struct pci_fixup *end) + { +diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c +index 5d59572..5510c88 100644 +--- a/drivers/pci/rom.c ++++ b/drivers/pci/rom.c +@@ -69,6 +69,7 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size) + { + void __iomem *image; + int last_image; ++ unsigned length; + + image = rom; + do { +@@ -91,9 +92,9 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size) + if (readb(pds + 3) != 'R') + break; + last_image = readb(pds + 21) & 0x80; +- /* this length is reliable */ +- image += readw(pds + 16) * 512; +- } while (!last_image); ++ length = readw(pds + 16); ++ image += length * 512; ++ } while (length && !last_image); + + /* never return a size larger than the PCI resource window */ + /* there are known ROMs that get the size wrong */ +diff --git a/drivers/pcmcia/topic.h b/drivers/pcmcia/topic.h +index 615a45a..582688f 100644 +--- a/drivers/pcmcia/topic.h ++++ b/drivers/pcmcia/topic.h +@@ -104,6 +104,9 @@ + #define TOPIC_EXCA_IF_CONTROL 0x3e /* 8 bit */ + #define TOPIC_EXCA_IFC_33V_ENA 0x01 + ++#define TOPIC_PCI_CFG_PPBCN 0x3e /* 16-bit */ ++#define TOPIC_PCI_CFG_PPBCN_WBEN 0x0400 ++ + static void topic97_zoom_video(struct pcmcia_socket *sock, int onoff) + { + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); +@@ -138,6 +141,7 @@ static int topic97_override(struct yenta_socket *socket) + static int topic95_override(struct yenta_socket *socket) + { + u8 fctrl; ++ u16 ppbcn; + + /* enable 3.3V support for 16bit cards */ + fctrl = exca_readb(socket, TOPIC_EXCA_IF_CONTROL); +@@ -146,6 +150,18 @@ static int topic95_override(struct yenta_socket *socket) + /* tell yenta to use exca registers to power 16bit cards */ + socket->flags |= YENTA_16BIT_POWER_EXCA | YENTA_16BIT_POWER_DF; + ++ /* Disable write buffers to prevent lockups under load with numerous ++ Cardbus cards, observed on Tecra 500CDT and reported elsewhere on the ++ net. This is not a power-on default according to the datasheet ++ but some BIOSes seem to set it. */ ++ if (pci_read_config_word(socket->dev, TOPIC_PCI_CFG_PPBCN, &ppbcn) == 0 ++ && socket->dev->revision <= 7 ++ && (ppbcn & TOPIC_PCI_CFG_PPBCN_WBEN)) { ++ ppbcn &= ~TOPIC_PCI_CFG_PPBCN_WBEN; ++ pci_write_config_word(socket->dev, TOPIC_PCI_CFG_PPBCN, ppbcn); ++ dev_info(&socket->dev->dev, "Disabled ToPIC95 Cardbus write buffers.\n"); ++ } ++ + return 0; + } + +diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c +index 34d56f7..86592dd 100644 +--- a/drivers/phy/phy-core.c ++++ b/drivers/phy/phy-core.c +@@ -50,7 +50,9 @@ static void devm_phy_consume(struct device *dev, void *res) + + static int devm_phy_match(struct device *dev, void *res, void *match_data) + { +- return res == match_data; ++ struct phy **phy = res; ++ ++ return *phy == match_data; + } + + static struct phy *phy_lookup(struct device *device, const char *port) +diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c +index c3ace1d..aaac359 100644 +--- a/drivers/phy/phy-twl4030-usb.c ++++ b/drivers/phy/phy-twl4030-usb.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -422,37 +423,55 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) + } + } + +-static int twl4030_phy_power_off(struct phy *phy) ++static int twl4030_usb_runtime_suspend(struct device *dev) + { +- struct twl4030_usb *twl = phy_get_drvdata(phy); ++ struct twl4030_usb *twl = dev_get_drvdata(dev); + ++ dev_dbg(twl->dev, "%s\n", __func__); + if (twl->asleep) + return 0; + + twl4030_phy_power(twl, 0); + twl->asleep = 1; +- dev_dbg(twl->dev, "%s\n", __func__); ++ + return 0; + } + +-static void __twl4030_phy_power_on(struct twl4030_usb *twl) ++static int twl4030_usb_runtime_resume(struct device *dev) + { ++ struct twl4030_usb *twl = dev_get_drvdata(dev); ++ ++ dev_dbg(twl->dev, "%s\n", __func__); ++ if (!twl->asleep) ++ return 0; ++ + twl4030_phy_power(twl, 1); +- twl4030_i2c_access(twl, 1); +- twl4030_usb_set_mode(twl, twl->usb_mode); +- if (twl->usb_mode == T2_USB_MODE_ULPI) +- twl4030_i2c_access(twl, 0); ++ twl->asleep = 0; ++ ++ return 0; ++} ++ ++static int twl4030_phy_power_off(struct phy *phy) ++{ ++ struct twl4030_usb *twl = phy_get_drvdata(phy); ++ ++ dev_dbg(twl->dev, "%s\n", __func__); ++ pm_runtime_mark_last_busy(twl->dev); ++ pm_runtime_put_autosuspend(twl->dev); ++ ++ return 0; + } + + static int twl4030_phy_power_on(struct phy *phy) + { + struct twl4030_usb *twl = phy_get_drvdata(phy); + +- if (!twl->asleep) +- return 0; +- __twl4030_phy_power_on(twl); +- twl->asleep = 0; + dev_dbg(twl->dev, "%s\n", __func__); ++ pm_runtime_get_sync(twl->dev); ++ twl4030_i2c_access(twl, 1); ++ twl4030_usb_set_mode(twl, twl->usb_mode); ++ if (twl->usb_mode == T2_USB_MODE_ULPI) ++ twl4030_i2c_access(twl, 0); + + /* + * XXX When VBUS gets driven after musb goes to A mode, +@@ -558,9 +577,27 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) + * USB_LINK_VBUS state. musb_hdrc won't care until it + * starts to handle softconnect right. + */ ++ if ((status == OMAP_MUSB_VBUS_VALID) || ++ (status == OMAP_MUSB_ID_GROUND)) { ++ if (twl->asleep) ++ pm_runtime_get_sync(twl->dev); ++ } else { ++ if (!twl->asleep) { ++ pm_runtime_mark_last_busy(twl->dev); ++ pm_runtime_put_autosuspend(twl->dev); ++ } ++ } + omap_musb_mailbox(status); + } +- sysfs_notify(&twl->dev->kobj, NULL, "vbus"); ++ ++ /* don't schedule during sleep - irq works right then */ ++ if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) { ++ cancel_delayed_work(&twl->id_workaround_work); ++ schedule_delayed_work(&twl->id_workaround_work, HZ); ++ } ++ ++ if (irq) ++ sysfs_notify(&twl->dev->kobj, NULL, "vbus"); + + return IRQ_HANDLED; + } +@@ -569,29 +606,8 @@ static void twl4030_id_workaround_work(struct work_struct *work) + { + struct twl4030_usb *twl = container_of(work, struct twl4030_usb, + id_workaround_work.work); +- enum omap_musb_vbus_id_status status; +- bool status_changed = false; +- +- status = twl4030_usb_linkstat(twl); +- +- spin_lock_irq(&twl->lock); +- if (status >= 0 && status != twl->linkstat) { +- twl->linkstat = status; +- status_changed = true; +- } +- spin_unlock_irq(&twl->lock); +- +- if (status_changed) { +- dev_dbg(twl->dev, "handle missing status change to %d\n", +- status); +- omap_musb_mailbox(status); +- } + +- /* don't schedule during sleep - irq works right then */ +- if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) { +- cancel_delayed_work(&twl->id_workaround_work); +- schedule_delayed_work(&twl->id_workaround_work, HZ); +- } ++ twl4030_usb_irq(0, twl); + } + + static int twl4030_phy_init(struct phy *phy) +@@ -599,22 +615,17 @@ static int twl4030_phy_init(struct phy *phy) + struct twl4030_usb *twl = phy_get_drvdata(phy); + enum omap_musb_vbus_id_status status; + +- /* +- * Start in sleep state, we'll get called through set_suspend() +- * callback when musb is runtime resumed and it's time to start. +- */ +- __twl4030_phy_power(twl, 0); +- twl->asleep = 1; +- ++ pm_runtime_get_sync(twl->dev); + status = twl4030_usb_linkstat(twl); + twl->linkstat = status; + +- if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) { ++ if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) + omap_musb_mailbox(twl->linkstat); +- twl4030_phy_power_on(phy); +- } + + sysfs_notify(&twl->dev->kobj, NULL, "vbus"); ++ pm_runtime_mark_last_busy(twl->dev); ++ pm_runtime_put_autosuspend(twl->dev); ++ + return 0; + } + +@@ -650,6 +661,11 @@ static const struct phy_ops ops = { + .owner = THIS_MODULE, + }; + ++static const struct dev_pm_ops twl4030_usb_pm_ops = { ++ SET_RUNTIME_PM_OPS(twl4030_usb_runtime_suspend, ++ twl4030_usb_runtime_resume, NULL) ++}; ++ + static int twl4030_usb_probe(struct platform_device *pdev) + { + struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev); +@@ -726,6 +742,11 @@ static int twl4030_usb_probe(struct platform_device *pdev) + + ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); + ++ pm_runtime_use_autosuspend(&pdev->dev); ++ pm_runtime_set_autosuspend_delay(&pdev->dev, 2000); ++ pm_runtime_enable(&pdev->dev); ++ pm_runtime_get_sync(&pdev->dev); ++ + /* Our job is to use irqs and status from the power module + * to keep the transceiver disabled when nothing's connected. + * +@@ -744,6 +765,9 @@ static int twl4030_usb_probe(struct platform_device *pdev) + return status; + } + ++ pm_runtime_mark_last_busy(&pdev->dev); ++ pm_runtime_put_autosuspend(twl->dev); ++ + dev_info(&pdev->dev, "Initialized TWL4030 USB module\n"); + return 0; + } +@@ -753,6 +777,7 @@ static int twl4030_usb_remove(struct platform_device *pdev) + struct twl4030_usb *twl = platform_get_drvdata(pdev); + int val; + ++ pm_runtime_get_sync(twl->dev); + cancel_delayed_work(&twl->id_workaround_work); + device_remove_file(twl->dev, &dev_attr_vbus); + +@@ -772,9 +797,8 @@ static int twl4030_usb_remove(struct platform_device *pdev) + + /* disable complete OTG block */ + twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); +- +- if (!twl->asleep) +- twl4030_phy_power(twl, 0); ++ pm_runtime_mark_last_busy(twl->dev); ++ pm_runtime_put(twl->dev); + + return 0; + } +@@ -792,6 +816,7 @@ static struct platform_driver twl4030_usb_driver = { + .remove = twl4030_usb_remove, + .driver = { + .name = "twl4030_usb", ++ .pm = &twl4030_usb_pm_ops, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(twl4030_usb_id_table), + }, +diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c +index c0fe609..a2a79c7 100644 +--- a/drivers/pinctrl/core.c ++++ b/drivers/pinctrl/core.c +@@ -1121,7 +1121,7 @@ void devm_pinctrl_put(struct pinctrl *p) + EXPORT_SYMBOL_GPL(devm_pinctrl_put); + + int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps, +- bool dup, bool locked) ++ bool dup) + { + int i, ret; + struct pinctrl_maps *maps_node; +@@ -1189,11 +1189,9 @@ int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps, + maps_node->maps = maps; + } + +- if (!locked) +- mutex_lock(&pinctrl_maps_mutex); ++ mutex_lock(&pinctrl_maps_mutex); + list_add_tail(&maps_node->node, &pinctrl_maps); +- if (!locked) +- mutex_unlock(&pinctrl_maps_mutex); ++ mutex_unlock(&pinctrl_maps_mutex); + + return 0; + } +@@ -1208,7 +1206,7 @@ int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps, + int pinctrl_register_mappings(struct pinctrl_map const *maps, + unsigned num_maps) + { +- return pinctrl_register_map(maps, num_maps, true, false); ++ return pinctrl_register_map(maps, num_maps, true); + } + + void pinctrl_unregister_map(struct pinctrl_map const *map) +@@ -1812,14 +1810,15 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev) + if (pctldev == NULL) + return; + +- mutex_lock(&pinctrldev_list_mutex); + mutex_lock(&pctldev->mutex); +- + pinctrl_remove_device_debugfs(pctldev); ++ mutex_unlock(&pctldev->mutex); + + if (!IS_ERR(pctldev->p)) + pinctrl_put(pctldev->p); + ++ mutex_lock(&pinctrldev_list_mutex); ++ mutex_lock(&pctldev->mutex); + /* TODO: check that no pinmuxes are still active? */ + list_del(&pctldev->node); + /* Destroy descriptor tree */ +diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h +index 75476b3..b24ea84 100644 +--- a/drivers/pinctrl/core.h ++++ b/drivers/pinctrl/core.h +@@ -183,7 +183,7 @@ static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, + } + + int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps, +- bool dup, bool locked); ++ bool dup); + void pinctrl_unregister_map(struct pinctrl_map const *map); + + extern int pinctrl_force_sleep(struct pinctrl_dev *pctldev); +diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c +index a53d15c..243e533 100644 +--- a/drivers/pinctrl/devicetree.c ++++ b/drivers/pinctrl/devicetree.c +@@ -93,7 +93,7 @@ static int dt_remember_or_free_map(struct pinctrl *p, const char *statename, + dt_map->num_maps = num_maps; + list_add_tail(&dt_map->node, &p->dt_maps); + +- return pinctrl_register_map(map, num_maps, false, true); ++ return pinctrl_register_map(map, num_maps, false); + } + + struct pinctrl_dev *of_pinctrl_get(struct device_node *np) +diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-370.c b/drivers/pinctrl/mvebu/pinctrl-armada-370.c +index ae1f760..bb525b1 100644 +--- a/drivers/pinctrl/mvebu/pinctrl-armada-370.c ++++ b/drivers/pinctrl/mvebu/pinctrl-armada-370.c +@@ -358,11 +358,11 @@ static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = { + MPP_MODE(64, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "spi0", "miso"), +- MPP_FUNCTION(0x2, "spi0-1", "cs1")), ++ MPP_FUNCTION(0x2, "spi0", "cs1")), + MPP_MODE(65, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "spi0", "mosi"), +- MPP_FUNCTION(0x2, "spi0-1", "cs2")), ++ MPP_FUNCTION(0x2, "spi0", "cs2")), + }; + + static struct mvebu_pinctrl_soc_info armada_370_pinctrl_info; +diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c +index 843a51f..d918c51 100644 +--- a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c ++++ b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c +@@ -14,10 +14,7 @@ + * available: mv78230, mv78260 and mv78460. From a pin muxing + * perspective, the mv78230 has 49 MPP pins. The mv78260 and mv78460 + * both have 67 MPP pins (more GPIOs and address lines for the memory +- * bus mainly). The only difference between the mv78260 and the +- * mv78460 in terms of pin muxing is the addition of two functions on +- * pins 43 and 56 to access the VDD of the CPU2 and 3 (mv78260 has two +- * cores, mv78460 has four cores). ++ * bus mainly). + */ + + #include +@@ -159,20 +156,17 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { + MPP_MODE(24, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sata1", "prsnt", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x2, "nf", "bootcs-re", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "rst", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "hsync", V_MV78230_PLUS)), + MPP_MODE(25, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sata0", "prsnt", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x2, "nf", "bootcs-we", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "pclk", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "vsync", V_MV78230_PLUS)), + MPP_MODE(26, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "fsync", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x4, "lcd", "clk", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd", V_MV78230_PLUS)), ++ MPP_VAR_FUNCTION(0x4, "lcd", "clk", V_MV78230_PLUS)), + MPP_MODE(27, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ptp", "trig", V_MV78230_PLUS), +@@ -187,8 +181,7 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ptp", "clk", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "int0", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x4, "lcd", "ref-clk", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)), ++ MPP_VAR_FUNCTION(0x4, "lcd", "ref-clk", V_MV78230_PLUS)), + MPP_MODE(30, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sd0", "clk", V_MV78230_PLUS), +@@ -196,13 +189,11 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { + MPP_MODE(31, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sd0", "cmd", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x3, "tdm", "int2", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)), ++ MPP_VAR_FUNCTION(0x3, "tdm", "int2", V_MV78230_PLUS)), + MPP_MODE(32, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sd0", "d0", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x3, "tdm", "int3", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd", V_MV78230_PLUS)), ++ MPP_VAR_FUNCTION(0x3, "tdm", "int3", V_MV78230_PLUS)), + MPP_MODE(33, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sd0", "d1", V_MV78230_PLUS), +@@ -234,7 +225,6 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "spi", "cs1", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "uart2", "cts", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x3, "vdd", "cpu1-pd", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "vga-hsync", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x5, "pcie", "clkreq0", V_MV78230_PLUS)), + MPP_MODE(41, +@@ -249,15 +239,13 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { + MPP_VAR_FUNCTION(0x1, "uart2", "rxd", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "uart0", "cts", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "int7", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x4, "tdm-1", "timer", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)), ++ MPP_VAR_FUNCTION(0x4, "tdm-1", "timer", V_MV78230_PLUS)), + MPP_MODE(43, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "uart2", "txd", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "uart0", "rts", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "spi", "cs3", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x4, "pcie", "rstout", V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x5, "vdd", "cpu2-3-pd", V_MV78460)), ++ MPP_VAR_FUNCTION(0x4, "pcie", "rstout", V_MV78230_PLUS)), + MPP_MODE(44, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "uart2", "cts", V_MV78230_PLUS), +@@ -286,7 +274,7 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { + MPP_VAR_FUNCTION(0x5, "pcie", "clkreq3", V_MV78230_PLUS)), + MPP_MODE(48, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), +- MPP_VAR_FUNCTION(0x1, "tclk", NULL, V_MV78230_PLUS), ++ MPP_VAR_FUNCTION(0x1, "dev", "clkout", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "dev", "burst/last", V_MV78230_PLUS)), + MPP_MODE(49, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), +@@ -308,16 +296,13 @@ static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { + MPP_VAR_FUNCTION(0x1, "dev", "ad19", V_MV78260_PLUS)), + MPP_MODE(55, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), +- MPP_VAR_FUNCTION(0x1, "dev", "ad20", V_MV78260_PLUS), +- MPP_VAR_FUNCTION(0x2, "vdd", "cpu0-pd", V_MV78260_PLUS)), ++ MPP_VAR_FUNCTION(0x1, "dev", "ad20", V_MV78260_PLUS)), + MPP_MODE(56, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), +- MPP_VAR_FUNCTION(0x1, "dev", "ad21", V_MV78260_PLUS), +- MPP_VAR_FUNCTION(0x2, "vdd", "cpu1-pd", V_MV78260_PLUS)), ++ MPP_VAR_FUNCTION(0x1, "dev", "ad21", V_MV78260_PLUS)), + MPP_MODE(57, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), +- MPP_VAR_FUNCTION(0x1, "dev", "ad22", V_MV78260_PLUS), +- MPP_VAR_FUNCTION(0x2, "vdd", "cpu2-3-pd", V_MV78460)), ++ MPP_VAR_FUNCTION(0x1, "dev", "ad22", V_MV78260_PLUS)), + MPP_MODE(58, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad23", V_MV78260_PLUS)), +diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c +index 665b96b..eb9f190 100644 +--- a/drivers/pinctrl/pinctrl-baytrail.c ++++ b/drivers/pinctrl/pinctrl-baytrail.c +@@ -263,7 +263,7 @@ static int byt_gpio_direction_output(struct gpio_chip *chip, + spin_lock_irqsave(&vg->lock, flags); + + reg_val = readl(reg) | BYT_DIR_MASK; +- reg_val &= ~BYT_OUTPUT_EN; ++ reg_val &= ~(BYT_OUTPUT_EN | BYT_INPUT_EN); + + if (value) + writel(reg_val | BYT_LEVEL, reg); +diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c +index c91f69b3..dcfcaea 100644 +--- a/drivers/platform/x86/acer-wmi.c ++++ b/drivers/platform/x86/acer-wmi.c +@@ -570,6 +570,17 @@ static const struct dmi_system_id video_vendor_dmi_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"), + }, + }, ++ { ++ /* ++ * Note no video_set_backlight_video_vendor, we must use the ++ * acer interface, as there is no native backlight interface. ++ */ ++ .ident = "Acer KAV80", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Acer"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "KAV80"), ++ }, ++ }, + {} + }; + +diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c +index 7297df2..54407a8 100644 +--- a/drivers/platform/x86/compal-laptop.c ++++ b/drivers/platform/x86/compal-laptop.c +@@ -1027,9 +1027,9 @@ static int compal_probe(struct platform_device *pdev) + if (err) + return err; + +- hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, +- DRIVER_NAME, data, +- compal_hwmon_groups); ++ hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, ++ DRIVER_NAME, data, ++ compal_hwmon_groups); + if (IS_ERR(hwmon_dev)) { + err = PTR_ERR(hwmon_dev); + goto remove; +@@ -1037,7 +1037,9 @@ static int compal_probe(struct platform_device *pdev) + + /* Power supply */ + initialize_power_supply_data(data); +- power_supply_register(&compal_device->dev, &data->psy); ++ err = power_supply_register(&compal_device->dev, &data->psy); ++ if (err < 0) ++ goto remove; + + platform_set_drvdata(pdev, data); + +diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c +index fed4111..1beb232 100644 +--- a/drivers/platform/x86/dell-laptop.c ++++ b/drivers/platform/x86/dell-laptop.c +@@ -272,7 +272,6 @@ static struct dmi_system_id dell_quirks[] = { + }; + + static struct calling_interface_buffer *buffer; +-static struct page *bufferpage; + static DEFINE_MUTEX(buffer_mutex); + + static int hwswitch_state; +@@ -825,12 +824,11 @@ static int __init dell_init(void) + * Allocate buffer below 4GB for SMI data--only 32-bit physical addr + * is passed to SMI handler. + */ +- bufferpage = alloc_page(GFP_KERNEL | GFP_DMA32); +- if (!bufferpage) { ++ buffer = (void *)__get_free_page(GFP_KERNEL | GFP_DMA32); ++ if (!buffer) { + ret = -ENOMEM; + goto fail_buffer; + } +- buffer = page_address(bufferpage); + + ret = dell_setup_rfkill(); + +@@ -892,7 +890,7 @@ fail_backlight: + cancel_delayed_work_sync(&dell_rfkill_work); + dell_cleanup_rfkill(); + fail_rfkill: +- free_page((unsigned long)bufferpage); ++ free_page((unsigned long)buffer); + fail_buffer: + platform_device_del(platform_device); + fail_platform_device2: +diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c +index 390e8e3..25721bf 100644 +--- a/drivers/platform/x86/dell-wmi.c ++++ b/drivers/platform/x86/dell-wmi.c +@@ -163,18 +163,24 @@ static void dell_wmi_notify(u32 value, void *context) + const struct key_entry *key; + int reported_key; + u16 *buffer_entry = (u16 *)obj->buffer.pointer; ++ int buffer_size = obj->buffer.length/2; + +- if (dell_new_hk_type && (buffer_entry[1] != 0x10)) { ++ if (buffer_size >= 2 && dell_new_hk_type && buffer_entry[1] != 0x10) { + pr_info("Received unknown WMI event (0x%x)\n", + buffer_entry[1]); + kfree(obj); + return; + } + +- if (dell_new_hk_type || buffer_entry[1] == 0x0) ++ if (buffer_size >= 3 && (dell_new_hk_type || buffer_entry[1] == 0x0)) + reported_key = (int)buffer_entry[2]; +- else ++ else if (buffer_size >= 2) + reported_key = (int)buffer_entry[1] & 0xffff; ++ else { ++ pr_info("Received unknown WMI event\n"); ++ kfree(obj); ++ return; ++ } + + key = sparse_keymap_entry_from_scancode(dell_wmi_input_dev, + reported_key); +diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c +index 3dc9344..07fbcb0 100644 +--- a/drivers/platform/x86/hp_accel.c ++++ b/drivers/platform/x86/hp_accel.c +@@ -237,6 +237,7 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { + AXIS_DMI_MATCH("HPB64xx", "HP ProBook 64", xy_swap), + AXIS_DMI_MATCH("HPB64xx", "HP EliteBook 84", xy_swap), + AXIS_DMI_MATCH("HPB65xx", "HP ProBook 65", x_inverted), ++ AXIS_DMI_MATCH("HPZBook15", "HP ZBook 15", x_inverted), + { NULL, } + /* Laptop models without axis info (yet): + * "NC6910" "HP Compaq 6910" +diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c +index 6dd060a..0d1a5d4 100644 +--- a/drivers/platform/x86/ideapad-laptop.c ++++ b/drivers/platform/x86/ideapad-laptop.c +@@ -461,8 +461,9 @@ const struct ideapad_rfk_data ideapad_rfk_data[] = { + static int ideapad_rfk_set(void *data, bool blocked) + { + struct ideapad_rfk_priv *priv = data; ++ int opcode = ideapad_rfk_data[priv->dev].opcode; + +- return write_ec_cmd(priv->priv->adev->handle, priv->dev, !blocked); ++ return write_ec_cmd(priv->priv->adev->handle, opcode, !blocked); + } + + static struct rfkill_ops ideapad_rfk_ops = { +diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c +index c31aa07..da1c6cb 100644 +--- a/drivers/pnp/pnpacpi/core.c ++++ b/drivers/pnp/pnpacpi/core.c +@@ -339,8 +339,7 @@ static int __init acpi_pnp_match(struct device *dev, void *_pnp) + struct pnp_dev *pnp = _pnp; + + /* true means it matched */ +- return !acpi->physical_node_count +- && compare_pnp_id(pnp->id, acpi_device_hid(acpi)); ++ return pnp->data == acpi; + } + + static struct acpi_device * __init acpi_pnp_find_companion(struct device *dev) +diff --git a/drivers/power/88pm860x_charger.c b/drivers/power/88pm860x_charger.c +index de029bb..5ccca87 100644 +--- a/drivers/power/88pm860x_charger.c ++++ b/drivers/power/88pm860x_charger.c +@@ -711,6 +711,7 @@ static int pm860x_charger_probe(struct platform_device *pdev) + return 0; + + out_irq: ++ power_supply_unregister(&info->usb); + while (--i >= 0) + free_irq(info->irq[i], info); + out: +diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c +index 79a37f6..1f49986 100644 +--- a/drivers/power/bq2415x_charger.c ++++ b/drivers/power/bq2415x_charger.c +@@ -840,8 +840,7 @@ static int bq2415x_notifier_call(struct notifier_block *nb, + if (bq->automode < 1) + return NOTIFY_OK; + +- sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode"); +- bq2415x_set_mode(bq, bq->reported_mode); ++ schedule_delayed_work(&bq->work, 0); + + return NOTIFY_OK; + } +@@ -892,6 +891,11 @@ static void bq2415x_timer_work(struct work_struct *work) + int error; + int boost; + ++ if (bq->automode > 0 && (bq->reported_mode != bq->mode)) { ++ sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode"); ++ bq2415x_set_mode(bq, bq->reported_mode); ++ } ++ + if (!bq->autotimer) + return; + +@@ -1575,8 +1579,15 @@ static int bq2415x_probe(struct i2c_client *client, + if (np) { + bq->notify_psy = power_supply_get_by_phandle(np, "ti,usb-charger-detection"); + +- if (!bq->notify_psy) +- return -EPROBE_DEFER; ++ if (IS_ERR(bq->notify_psy)) { ++ dev_info(&client->dev, ++ "no 'ti,usb-charger-detection' property (err=%ld)\n", ++ PTR_ERR(bq->notify_psy)); ++ bq->notify_psy = NULL; ++ } else if (!bq->notify_psy) { ++ ret = -EPROBE_DEFER; ++ goto error_2; ++ } + } + else if (pdata->notify_device) + bq->notify_psy = power_supply_get_by_name(pdata->notify_device); +@@ -1598,27 +1609,27 @@ static int bq2415x_probe(struct i2c_client *client, + ret = of_property_read_u32(np, "ti,current-limit", + &bq->init_data.current_limit); + if (ret) +- return ret; ++ goto error_2; + ret = of_property_read_u32(np, "ti,weak-battery-voltage", + &bq->init_data.weak_battery_voltage); + if (ret) +- return ret; ++ goto error_2; + ret = of_property_read_u32(np, "ti,battery-regulation-voltage", + &bq->init_data.battery_regulation_voltage); + if (ret) +- return ret; ++ goto error_2; + ret = of_property_read_u32(np, "ti,charge-current", + &bq->init_data.charge_current); + if (ret) +- return ret; ++ goto error_2; + ret = of_property_read_u32(np, "ti,termination-current", + &bq->init_data.termination_current); + if (ret) +- return ret; ++ goto error_2; + ret = of_property_read_u32(np, "ti,resistor-sense", + &bq->init_data.resistor_sense); + if (ret) +- return ret; ++ goto error_2; + } else { + memcpy(&bq->init_data, pdata, sizeof(bq->init_data)); + } +diff --git a/drivers/power/bq24190_charger.c b/drivers/power/bq24190_charger.c +index ad3ff8f..e4c95e1 100644 +--- a/drivers/power/bq24190_charger.c ++++ b/drivers/power/bq24190_charger.c +@@ -929,7 +929,7 @@ static void bq24190_charger_init(struct power_supply *charger) + charger->properties = bq24190_charger_properties; + charger->num_properties = ARRAY_SIZE(bq24190_charger_properties); + charger->supplied_to = bq24190_charger_supplied_to; +- charger->num_supplies = ARRAY_SIZE(bq24190_charger_supplied_to); ++ charger->num_supplicants = ARRAY_SIZE(bq24190_charger_supplied_to); + charger->get_property = bq24190_charger_get_property; + charger->set_property = bq24190_charger_set_property; + charger->property_is_writeable = bq24190_charger_property_is_writeable; +diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c +index 9e4dab4..03bfac3 100644 +--- a/drivers/power/charger-manager.c ++++ b/drivers/power/charger-manager.c +@@ -97,6 +97,7 @@ static struct charger_global_desc *g_desc; /* init with setup_charger_manager */ + static bool is_batt_present(struct charger_manager *cm) + { + union power_supply_propval val; ++ struct power_supply *psy; + bool present = false; + int i, ret; + +@@ -107,16 +108,27 @@ static bool is_batt_present(struct charger_manager *cm) + case CM_NO_BATTERY: + break; + case CM_FUEL_GAUGE: +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ psy = power_supply_get_by_name(cm->desc->psy_fuel_gauge); ++ if (!psy) ++ break; ++ ++ ret = psy->get_property(psy, + POWER_SUPPLY_PROP_PRESENT, &val); + if (ret == 0 && val.intval) + present = true; + break; + case CM_CHARGER_STAT: +- for (i = 0; cm->charger_stat[i]; i++) { +- ret = cm->charger_stat[i]->get_property( +- cm->charger_stat[i], +- POWER_SUPPLY_PROP_PRESENT, &val); ++ for (i = 0; cm->desc->psy_charger_stat[i]; i++) { ++ psy = power_supply_get_by_name( ++ cm->desc->psy_charger_stat[i]); ++ if (!psy) { ++ dev_err(cm->dev, "Cannot find power supply \"%s\"\n", ++ cm->desc->psy_charger_stat[i]); ++ continue; ++ } ++ ++ ret = psy->get_property(psy, POWER_SUPPLY_PROP_PRESENT, ++ &val); + if (ret == 0 && val.intval) { + present = true; + break; +@@ -139,14 +151,20 @@ static bool is_batt_present(struct charger_manager *cm) + static bool is_ext_pwr_online(struct charger_manager *cm) + { + union power_supply_propval val; ++ struct power_supply *psy; + bool online = false; + int i, ret; + + /* If at least one of them has one, it's yes. */ +- for (i = 0; cm->charger_stat[i]; i++) { +- ret = cm->charger_stat[i]->get_property( +- cm->charger_stat[i], +- POWER_SUPPLY_PROP_ONLINE, &val); ++ for (i = 0; cm->desc->psy_charger_stat[i]; i++) { ++ psy = power_supply_get_by_name(cm->desc->psy_charger_stat[i]); ++ if (!psy) { ++ dev_err(cm->dev, "Cannot find power supply \"%s\"\n", ++ cm->desc->psy_charger_stat[i]); ++ continue; ++ } ++ ++ ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val); + if (ret == 0 && val.intval) { + online = true; + break; +@@ -167,12 +185,14 @@ static bool is_ext_pwr_online(struct charger_manager *cm) + static int get_batt_uV(struct charger_manager *cm, int *uV) + { + union power_supply_propval val; ++ struct power_supply *fuel_gauge; + int ret; + +- if (!cm->fuel_gauge) ++ fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge); ++ if (!fuel_gauge) + return -ENODEV; + +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ ret = fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_VOLTAGE_NOW, &val); + if (ret) + return ret; +@@ -189,6 +209,7 @@ static bool is_charging(struct charger_manager *cm) + { + int i, ret; + bool charging = false; ++ struct power_supply *psy; + union power_supply_propval val; + + /* If there is no battery, it cannot be charged */ +@@ -196,17 +217,22 @@ static bool is_charging(struct charger_manager *cm) + return false; + + /* If at least one of the charger is charging, return yes */ +- for (i = 0; cm->charger_stat[i]; i++) { ++ for (i = 0; cm->desc->psy_charger_stat[i]; i++) { + /* 1. The charger sholuld not be DISABLED */ + if (cm->emergency_stop) + continue; + if (!cm->charger_enabled) + continue; + ++ psy = power_supply_get_by_name(cm->desc->psy_charger_stat[i]); ++ if (!psy) { ++ dev_err(cm->dev, "Cannot find power supply \"%s\"\n", ++ cm->desc->psy_charger_stat[i]); ++ continue; ++ } ++ + /* 2. The charger should be online (ext-power) */ +- ret = cm->charger_stat[i]->get_property( +- cm->charger_stat[i], +- POWER_SUPPLY_PROP_ONLINE, &val); ++ ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val); + if (ret) { + dev_warn(cm->dev, "Cannot read ONLINE value from %s\n", + cm->desc->psy_charger_stat[i]); +@@ -219,9 +245,7 @@ static bool is_charging(struct charger_manager *cm) + * 3. The charger should not be FULL, DISCHARGING, + * or NOT_CHARGING. + */ +- ret = cm->charger_stat[i]->get_property( +- cm->charger_stat[i], +- POWER_SUPPLY_PROP_STATUS, &val); ++ ret = psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &val); + if (ret) { + dev_warn(cm->dev, "Cannot read STATUS value from %s\n", + cm->desc->psy_charger_stat[i]); +@@ -248,6 +272,7 @@ static bool is_full_charged(struct charger_manager *cm) + { + struct charger_desc *desc = cm->desc; + union power_supply_propval val; ++ struct power_supply *fuel_gauge; + int ret = 0; + int uV; + +@@ -255,11 +280,15 @@ static bool is_full_charged(struct charger_manager *cm) + if (!is_batt_present(cm)) + return false; + +- if (cm->fuel_gauge && desc->fullbatt_full_capacity > 0) { ++ fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge); ++ if (!fuel_gauge) ++ return false; ++ ++ if (desc->fullbatt_full_capacity > 0) { + val.intval = 0; + + /* Not full if capacity of fuel gauge isn't full */ +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ ret = fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_CHARGE_FULL, &val); + if (!ret && val.intval > desc->fullbatt_full_capacity) + return true; +@@ -273,10 +302,10 @@ static bool is_full_charged(struct charger_manager *cm) + } + + /* Full, if the capacity is more than fullbatt_soc */ +- if (cm->fuel_gauge && desc->fullbatt_soc > 0) { ++ if (desc->fullbatt_soc > 0) { + val.intval = 0; + +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ ret = fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_CAPACITY, &val); + if (!ret && val.intval >= desc->fullbatt_soc) + return true; +@@ -551,6 +580,20 @@ static int check_charging_duration(struct charger_manager *cm) + return ret; + } + ++static int cm_get_battery_temperature_by_psy(struct charger_manager *cm, ++ int *temp) ++{ ++ struct power_supply *fuel_gauge; ++ ++ fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge); ++ if (!fuel_gauge) ++ return -ENODEV; ++ ++ return fuel_gauge->get_property(fuel_gauge, ++ POWER_SUPPLY_PROP_TEMP, ++ (union power_supply_propval *)temp); ++} ++ + static int cm_get_battery_temperature(struct charger_manager *cm, + int *temp) + { +@@ -560,15 +603,18 @@ static int cm_get_battery_temperature(struct charger_manager *cm, + return -ENODEV; + + #ifdef CONFIG_THERMAL +- ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp); +- if (!ret) +- /* Calibrate temperature unit */ +- *temp /= 100; +-#else +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, +- POWER_SUPPLY_PROP_TEMP, +- (union power_supply_propval *)temp); ++ if (cm->tzd_batt) { ++ ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp); ++ if (!ret) ++ /* Calibrate temperature unit */ ++ *temp /= 100; ++ } else + #endif ++ { ++ /* if-else continued from CONFIG_THERMAL */ ++ ret = cm_get_battery_temperature_by_psy(cm, temp); ++ } ++ + return ret; + } + +@@ -827,6 +873,7 @@ static int charger_get_property(struct power_supply *psy, + struct charger_manager *cm = container_of(psy, + struct charger_manager, charger_psy); + struct charger_desc *desc = cm->desc; ++ struct power_supply *fuel_gauge; + int ret = 0; + int uV; + +@@ -857,14 +904,20 @@ static int charger_get_property(struct power_supply *psy, + ret = get_batt_uV(cm, &val->intval); + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge); ++ if (!fuel_gauge) { ++ ret = -ENODEV; ++ break; ++ } ++ ret = fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_CURRENT_NOW, val); + break; + case POWER_SUPPLY_PROP_TEMP: + case POWER_SUPPLY_PROP_TEMP_AMBIENT: + return cm_get_battery_temperature(cm, &val->intval); + case POWER_SUPPLY_PROP_CAPACITY: +- if (!cm->fuel_gauge) { ++ fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge); ++ if (!fuel_gauge) { + ret = -ENODEV; + break; + } +@@ -875,7 +928,7 @@ static int charger_get_property(struct power_supply *psy, + break; + } + +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ ret = fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_CAPACITY, val); + if (ret) + break; +@@ -924,7 +977,14 @@ static int charger_get_property(struct power_supply *psy, + break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + if (is_charging(cm)) { +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ fuel_gauge = power_supply_get_by_name( ++ cm->desc->psy_fuel_gauge); ++ if (!fuel_gauge) { ++ ret = -ENODEV; ++ break; ++ } ++ ++ ret = fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_CHARGE_NOW, + val); + if (ret) { +@@ -1485,14 +1545,15 @@ err: + return ret; + } + +-static int cm_init_thermal_data(struct charger_manager *cm) ++static int cm_init_thermal_data(struct charger_manager *cm, ++ struct power_supply *fuel_gauge) + { + struct charger_desc *desc = cm->desc; + union power_supply_propval val; + int ret; + + /* Verify whether fuel gauge provides battery temperature */ +- ret = cm->fuel_gauge->get_property(cm->fuel_gauge, ++ ret = fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_TEMP, &val); + + if (!ret) { +@@ -1502,8 +1563,6 @@ static int cm_init_thermal_data(struct charger_manager *cm) + cm->desc->measure_battery_temp = true; + } + #ifdef CONFIG_THERMAL +- cm->tzd_batt = cm->fuel_gauge->tzd; +- + if (ret && desc->thermal_zone) { + cm->tzd_batt = + thermal_zone_get_zone_by_name(desc->thermal_zone); +@@ -1666,6 +1725,7 @@ static int charger_manager_probe(struct platform_device *pdev) + int ret = 0, i = 0; + int j = 0; + union power_supply_propval val; ++ struct power_supply *fuel_gauge; + + if (g_desc && !rtc_dev && g_desc->rtc_name) { + rtc_dev = rtc_class_open(g_desc->rtc_name); +@@ -1720,27 +1780,29 @@ static int charger_manager_probe(struct platform_device *pdev) + return -EINVAL; + } + ++ if (!desc->psy_fuel_gauge) { ++ dev_err(&pdev->dev, "No fuel gauge power supply defined\n"); ++ return -EINVAL; ++ } ++ + /* Counting index only */ + while (desc->psy_charger_stat[i]) + i++; + +- cm->charger_stat = devm_kzalloc(&pdev->dev, +- sizeof(struct power_supply *) * i, GFP_KERNEL); +- if (!cm->charger_stat) +- return -ENOMEM; +- ++ /* Check if charger's supplies are present at probe */ + for (i = 0; desc->psy_charger_stat[i]; i++) { +- cm->charger_stat[i] = power_supply_get_by_name( +- desc->psy_charger_stat[i]); +- if (!cm->charger_stat[i]) { ++ struct power_supply *psy; ++ ++ psy = power_supply_get_by_name(desc->psy_charger_stat[i]); ++ if (!psy) { + dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n", + desc->psy_charger_stat[i]); + return -ENODEV; + } + } + +- cm->fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge); +- if (!cm->fuel_gauge) { ++ fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge); ++ if (!fuel_gauge) { + dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n", + desc->psy_fuel_gauge); + return -ENODEV; +@@ -1783,13 +1845,13 @@ static int charger_manager_probe(struct platform_device *pdev) + cm->charger_psy.num_properties = psy_default.num_properties; + + /* Find which optional psy-properties are available */ +- if (!cm->fuel_gauge->get_property(cm->fuel_gauge, ++ if (!fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_CHARGE_NOW, &val)) { + cm->charger_psy.properties[cm->charger_psy.num_properties] = + POWER_SUPPLY_PROP_CHARGE_NOW; + cm->charger_psy.num_properties++; + } +- if (!cm->fuel_gauge->get_property(cm->fuel_gauge, ++ if (!fuel_gauge->get_property(fuel_gauge, + POWER_SUPPLY_PROP_CURRENT_NOW, + &val)) { + cm->charger_psy.properties[cm->charger_psy.num_properties] = +@@ -1797,7 +1859,7 @@ static int charger_manager_probe(struct platform_device *pdev) + cm->charger_psy.num_properties++; + } + +- ret = cm_init_thermal_data(cm); ++ ret = cm_init_thermal_data(cm, fuel_gauge); + if (ret) { + dev_err(&pdev->dev, "Failed to initialize thermal data\n"); + cm->desc->measure_battery_temp = false; +@@ -2054,8 +2116,8 @@ static bool find_power_supply(struct charger_manager *cm, + int i; + bool found = false; + +- for (i = 0; cm->charger_stat[i]; i++) { +- if (psy == cm->charger_stat[i]) { ++ for (i = 0; cm->desc->psy_charger_stat[i]; i++) { ++ if (!strcmp(psy->name, cm->desc->psy_charger_stat[i])) { + found = true; + break; + } +diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c +index a0024b2..86e03c6 100644 +--- a/drivers/power/gpio-charger.c ++++ b/drivers/power/gpio-charger.c +@@ -168,7 +168,7 @@ static int gpio_charger_suspend(struct device *dev) + + if (device_may_wakeup(dev)) + gpio_charger->wakeup_enabled = +- enable_irq_wake(gpio_charger->irq); ++ !enable_irq_wake(gpio_charger->irq); + + return 0; + } +@@ -178,7 +178,7 @@ static int gpio_charger_resume(struct device *dev) + struct platform_device *pdev = to_platform_device(dev); + struct gpio_charger *gpio_charger = platform_get_drvdata(pdev); + +- if (gpio_charger->wakeup_enabled) ++ if (device_may_wakeup(dev) && gpio_charger->wakeup_enabled) + disable_irq_wake(gpio_charger->irq); + power_supply_changed(&gpio_charger->charger); + +diff --git a/drivers/power/lp8788-charger.c b/drivers/power/lp8788-charger.c +index ed49b50..72da2a6 100644 +--- a/drivers/power/lp8788-charger.c ++++ b/drivers/power/lp8788-charger.c +@@ -417,8 +417,10 @@ static int lp8788_psy_register(struct platform_device *pdev, + pchg->battery.num_properties = ARRAY_SIZE(lp8788_battery_prop); + pchg->battery.get_property = lp8788_battery_get_property; + +- if (power_supply_register(&pdev->dev, &pchg->battery)) ++ if (power_supply_register(&pdev->dev, &pchg->battery)) { ++ power_supply_unregister(&pchg->charger); + return -EPERM; ++ } + + return 0; + } +diff --git a/drivers/power/twl4030_madc_battery.c b/drivers/power/twl4030_madc_battery.c +index 7ef445a..cf90760 100644 +--- a/drivers/power/twl4030_madc_battery.c ++++ b/drivers/power/twl4030_madc_battery.c +@@ -192,6 +192,7 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev) + { + struct twl4030_madc_battery *twl4030_madc_bat; + struct twl4030_madc_bat_platform_data *pdata = pdev->dev.platform_data; ++ int ret = 0; + + twl4030_madc_bat = kzalloc(sizeof(*twl4030_madc_bat), GFP_KERNEL); + if (!twl4030_madc_bat) +@@ -216,9 +217,11 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev) + + twl4030_madc_bat->pdata = pdata; + platform_set_drvdata(pdev, twl4030_madc_bat); +- power_supply_register(&pdev->dev, &twl4030_madc_bat->psy); ++ ret = power_supply_register(&pdev->dev, &twl4030_madc_bat->psy); ++ if (ret < 0) ++ kfree(twl4030_madc_bat); + +- return 0; ++ return ret; + } + + static int twl4030_madc_battery_remove(struct platform_device *pdev) +diff --git a/drivers/rapidio/devices/tsi721_dma.c b/drivers/rapidio/devices/tsi721_dma.c +index 91245f5..47257b6 100644 +--- a/drivers/rapidio/devices/tsi721_dma.c ++++ b/drivers/rapidio/devices/tsi721_dma.c +@@ -287,6 +287,12 @@ struct tsi721_tx_desc *tsi721_desc_get(struct tsi721_bdma_chan *bdma_chan) + "desc %p not ACKed\n", tx_desc); + } + ++ if (ret == NULL) { ++ dev_dbg(bdma_chan->dchan.device->dev, ++ "%s: unable to obtain tx descriptor\n", __func__); ++ goto err_out; ++ } ++ + i = bdma_chan->wr_count_next % bdma_chan->bd_num; + if (i == bdma_chan->bd_num - 1) { + i = 0; +@@ -297,7 +303,7 @@ struct tsi721_tx_desc *tsi721_desc_get(struct tsi721_bdma_chan *bdma_chan) + tx_desc->txd.phys = bdma_chan->bd_phys + + i * sizeof(struct tsi721_dma_desc); + tx_desc->hw_desc = &((struct tsi721_dma_desc *)bdma_chan->bd_base)[i]; +- ++err_out: + spin_unlock_bh(&bdma_chan->lock); + + return ret; +diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c +index f0ea4fd..8b963a7 100644 +--- a/drivers/regulator/arizona-ldo1.c ++++ b/drivers/regulator/arizona-ldo1.c +@@ -141,8 +141,6 @@ static struct regulator_ops arizona_ldo1_ops = { + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, +- .get_bypass = regulator_get_bypass_regmap, +- .set_bypass = regulator_set_bypass_regmap, + }; + + static const struct regulator_desc arizona_ldo1 = { +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index 8a9f2b0..e4491c5 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -775,7 +775,7 @@ static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) + static void print_constraints(struct regulator_dev *rdev) + { + struct regulation_constraints *constraints = rdev->constraints; +- char buf[80] = ""; ++ char buf[160] = ""; + int count = 0; + int ret; + +@@ -1481,7 +1481,7 @@ struct regulator *regulator_get_optional(struct device *dev, const char *id) + } + EXPORT_SYMBOL_GPL(regulator_get_optional); + +-/* Locks held by regulator_put() */ ++/* regulator_list_mutex lock held by regulator_put() */ + static void _regulator_put(struct regulator *regulator) + { + struct regulator_dev *rdev; +@@ -1496,12 +1496,14 @@ static void _regulator_put(struct regulator *regulator) + /* remove any sysfs entries */ + if (regulator->dev) + sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); ++ mutex_lock(&rdev->mutex); + kfree(regulator->supply_name); + list_del(®ulator->list); + kfree(regulator); + + rdev->open_count--; + rdev->exclusive = 0; ++ mutex_unlock(&rdev->mutex); + + module_put(rdev->owner); + } +@@ -1767,10 +1769,12 @@ static int _regulator_do_enable(struct regulator_dev *rdev) + trace_regulator_enable(rdev_get_name(rdev)); + + if (rdev->ena_pin) { +- ret = regulator_ena_gpio_ctrl(rdev, true); +- if (ret < 0) +- return ret; +- rdev->ena_gpio_state = 1; ++ if (!rdev->ena_gpio_state) { ++ ret = regulator_ena_gpio_ctrl(rdev, true); ++ if (ret < 0) ++ return ret; ++ rdev->ena_gpio_state = 1; ++ } + } else if (rdev->desc->ops->enable) { + ret = rdev->desc->ops->enable(rdev); + if (ret < 0) +@@ -1902,10 +1906,12 @@ static int _regulator_do_disable(struct regulator_dev *rdev) + trace_regulator_disable(rdev_get_name(rdev)); + + if (rdev->ena_pin) { +- ret = regulator_ena_gpio_ctrl(rdev, false); +- if (ret < 0) +- return ret; +- rdev->ena_gpio_state = 0; ++ if (rdev->ena_gpio_state) { ++ ret = regulator_ena_gpio_ctrl(rdev, false); ++ if (ret < 0) ++ return ret; ++ rdev->ena_gpio_state = 0; ++ } + + } else if (rdev->desc->ops->disable) { + ret = rdev->desc->ops->disable(rdev); +@@ -3459,12 +3465,6 @@ regulator_register(const struct regulator_desc *regulator_desc, + config->ena_gpio, ret); + goto wash; + } +- +- if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH) +- rdev->ena_gpio_state = 1; +- +- if (config->ena_gpio_invert) +- rdev->ena_gpio_state = !rdev->ena_gpio_state; + } + + /* set regulator constraints */ +@@ -3636,9 +3636,11 @@ int regulator_suspend_finish(void) + list_for_each_entry(rdev, ®ulator_list, list) { + mutex_lock(&rdev->mutex); + if (rdev->use_count > 0 || rdev->constraints->always_on) { +- error = _regulator_do_enable(rdev); +- if (error) +- ret = error; ++ if (!_regulator_is_enabled(rdev)) { ++ error = _regulator_do_enable(rdev); ++ if (error) ++ ret = error; ++ } + } else { + if (!have_full_constraints()) + goto unlock; +diff --git a/drivers/regulator/max77693.c b/drivers/regulator/max77693.c +index 5fb899f..24c926b 100644 +--- a/drivers/regulator/max77693.c ++++ b/drivers/regulator/max77693.c +@@ -232,7 +232,7 @@ static int max77693_pmic_probe(struct platform_device *pdev) + struct max77693_pmic_dev *max77693_pmic; + struct max77693_regulator_data *rdata = NULL; + int num_rdata, i; +- struct regulator_config config; ++ struct regulator_config config = { }; + + num_rdata = max77693_pmic_init_rdata(&pdev->dev, &rdata); + if (!rdata || num_rdata <= 0) { +diff --git a/drivers/rtc/rtc-isl12057.c b/drivers/rtc/rtc-isl12057.c +index 7854a65..110eab8 100644 +--- a/drivers/rtc/rtc-isl12057.c ++++ b/drivers/rtc/rtc-isl12057.c +@@ -89,7 +89,7 @@ static void isl12057_rtc_regs_to_tm(struct rtc_time *tm, u8 *regs) + tm->tm_min = bcd2bin(regs[ISL12057_REG_RTC_MN]); + + if (regs[ISL12057_REG_RTC_HR] & ISL12057_REG_RTC_HR_MIL) { /* AM/PM */ +- tm->tm_hour = bcd2bin(regs[ISL12057_REG_RTC_HR] & 0x0f); ++ tm->tm_hour = bcd2bin(regs[ISL12057_REG_RTC_HR] & 0x1f); + if (regs[ISL12057_REG_RTC_HR] & ISL12057_REG_RTC_HR_PM) + tm->tm_hour += 12; + } else { /* 24 hour mode */ +@@ -98,7 +98,7 @@ static void isl12057_rtc_regs_to_tm(struct rtc_time *tm, u8 *regs) + + tm->tm_mday = bcd2bin(regs[ISL12057_REG_RTC_DT]); + tm->tm_wday = bcd2bin(regs[ISL12057_REG_RTC_DW]) - 1; /* starts at 1 */ +- tm->tm_mon = bcd2bin(regs[ISL12057_REG_RTC_MO]) - 1; /* starts at 1 */ ++ tm->tm_mon = bcd2bin(regs[ISL12057_REG_RTC_MO] & 0x1f) - 1; /* ditto */ + tm->tm_year = bcd2bin(regs[ISL12057_REG_RTC_YR]) + 100; + } + +diff --git a/drivers/rtc/rtc-sirfsoc.c b/drivers/rtc/rtc-sirfsoc.c +index 3eb3642..d2b1ab3 100644 +--- a/drivers/rtc/rtc-sirfsoc.c ++++ b/drivers/rtc/rtc-sirfsoc.c +@@ -290,14 +290,6 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev) + rtc_div = ((32768 / RTC_HZ) / 2) - 1; + sirfsoc_rtc_iobrg_writel(rtc_div, rtcdrv->rtc_base + RTC_DIV); + +- rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, +- &sirfsoc_rtc_ops, THIS_MODULE); +- if (IS_ERR(rtcdrv->rtc)) { +- err = PTR_ERR(rtcdrv->rtc); +- dev_err(&pdev->dev, "can't register RTC device\n"); +- return err; +- } +- + /* 0x3 -> RTC_CLK */ + sirfsoc_rtc_iobrg_writel(SIRFSOC_RTC_CLK, + rtcdrv->rtc_base + RTC_CLOCK_SWITCH); +@@ -312,6 +304,14 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev) + rtcdrv->overflow_rtc = + sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_SW_VALUE); + ++ rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, ++ &sirfsoc_rtc_ops, THIS_MODULE); ++ if (IS_ERR(rtcdrv->rtc)) { ++ err = PTR_ERR(rtcdrv->rtc); ++ dev_err(&pdev->dev, "can't register RTC device\n"); ++ return err; ++ } ++ + rtcdrv->irq = platform_get_irq(pdev, 0); + err = devm_request_irq( + &pdev->dev, +diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c +index bb86494..19915c5 100644 +--- a/drivers/s390/char/con3215.c ++++ b/drivers/s390/char/con3215.c +@@ -288,12 +288,16 @@ static void raw3215_timeout(unsigned long __data) + unsigned long flags; + + spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); +- if (raw->flags & RAW3215_TIMER_RUNS) { +- del_timer(&raw->timer); +- raw->flags &= ~RAW3215_TIMER_RUNS; +- if (!(raw->port.flags & ASYNC_SUSPENDED)) { +- raw3215_mk_write_req(raw); +- raw3215_start_io(raw); ++ raw->flags &= ~RAW3215_TIMER_RUNS; ++ if (!(raw->port.flags & ASYNC_SUSPENDED)) { ++ raw3215_mk_write_req(raw); ++ raw3215_start_io(raw); ++ if ((raw->queued_read || raw->queued_write) && ++ !(raw->flags & RAW3215_WORKING) && ++ !(raw->flags & RAW3215_TIMER_RUNS)) { ++ raw->timer.expires = RAW3215_TIMEOUT + jiffies; ++ add_timer(&raw->timer); ++ raw->flags |= RAW3215_TIMER_RUNS; + } + } + spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); +@@ -317,17 +321,15 @@ static inline void raw3215_try_io(struct raw3215_info *raw) + (raw->flags & RAW3215_FLUSHING)) { + /* execute write requests bigger than minimum size */ + raw3215_start_io(raw); +- if (raw->flags & RAW3215_TIMER_RUNS) { +- del_timer(&raw->timer); +- raw->flags &= ~RAW3215_TIMER_RUNS; +- } +- } else if (!(raw->flags & RAW3215_TIMER_RUNS)) { +- /* delay small writes */ +- raw->timer.expires = RAW3215_TIMEOUT + jiffies; +- add_timer(&raw->timer); +- raw->flags |= RAW3215_TIMER_RUNS; + } + } ++ if ((raw->queued_read || raw->queued_write) && ++ !(raw->flags & RAW3215_WORKING) && ++ !(raw->flags & RAW3215_TIMER_RUNS)) { ++ raw->timer.expires = RAW3215_TIMEOUT + jiffies; ++ add_timer(&raw->timer); ++ raw->flags |= RAW3215_TIMER_RUNS; ++ } + } + + /* +@@ -1027,12 +1029,26 @@ static int tty3215_write(struct tty_struct * tty, + const unsigned char *buf, int count) + { + struct raw3215_info *raw; ++ int i, written; + + if (!tty) + return 0; + raw = (struct raw3215_info *) tty->driver_data; +- raw3215_write(raw, buf, count); +- return count; ++ written = count; ++ while (count > 0) { ++ for (i = 0; i < count; i++) ++ if (buf[i] == '\t' || buf[i] == '\n') ++ break; ++ raw3215_write(raw, buf, i); ++ count -= i; ++ buf += i; ++ if (count > 0) { ++ raw3215_putchar(raw, *buf); ++ count--; ++ buf++; ++ } ++ } ++ return written; + } + + /* +@@ -1180,7 +1196,7 @@ static int __init tty3215_init(void) + driver->subtype = SYSTEM_TYPE_TTY; + driver->init_termios = tty_std_termios; + driver->init_termios.c_iflag = IGNBRK | IGNPAR; +- driver->init_termios.c_oflag = ONLCR | XTABS; ++ driver->init_termios.c_oflag = ONLCR; + driver->init_termios.c_lflag = ISIG; + driver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(driver, &tty3215_ops); +diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c +index 82f2c38..b334f68 100644 +--- a/drivers/s390/char/sclp_early.c ++++ b/drivers/s390/char/sclp_early.c +@@ -7,6 +7,7 @@ + #define KMSG_COMPONENT "sclp_early" + #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + ++#include + #include + #include + #include +diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c +index ab3baa7..86ade85 100644 +--- a/drivers/s390/crypto/ap_bus.c ++++ b/drivers/s390/crypto/ap_bus.c +@@ -44,6 +44,7 @@ + #include + #include + #include ++#include + + #include "ap_bus.h" + +@@ -71,7 +72,7 @@ MODULE_AUTHOR("IBM Corporation"); + MODULE_DESCRIPTION("Adjunct Processor Bus driver, " \ + "Copyright IBM Corp. 2006, 2012"); + MODULE_LICENSE("GPL"); +-MODULE_ALIAS("z90crypt"); ++MODULE_ALIAS_CRYPTO("z90crypt"); + + /* + * Module parameter +diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c +index 160e751..0787b97 100644 +--- a/drivers/sbus/char/bbc_envctrl.c ++++ b/drivers/sbus/char/bbc_envctrl.c +@@ -452,6 +452,9 @@ static void attach_one_temp(struct bbc_i2c_bus *bp, struct platform_device *op, + if (!tp) + return; + ++ INIT_LIST_HEAD(&tp->bp_list); ++ INIT_LIST_HEAD(&tp->glob_list); ++ + tp->client = bbc_i2c_attach(bp, op); + if (!tp->client) { + kfree(tp); +@@ -497,6 +500,9 @@ static void attach_one_fan(struct bbc_i2c_bus *bp, struct platform_device *op, + if (!fp) + return; + ++ INIT_LIST_HEAD(&fp->bp_list); ++ INIT_LIST_HEAD(&fp->glob_list); ++ + fp->client = bbc_i2c_attach(bp, op); + if (!fp->client) { + kfree(fp); +diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c +index c7763e4..812b5f0 100644 +--- a/drivers/sbus/char/bbc_i2c.c ++++ b/drivers/sbus/char/bbc_i2c.c +@@ -300,13 +300,18 @@ static struct bbc_i2c_bus * attach_one_i2c(struct platform_device *op, int index + if (!bp) + return NULL; + ++ INIT_LIST_HEAD(&bp->temps); ++ INIT_LIST_HEAD(&bp->fans); ++ + bp->i2c_control_regs = of_ioremap(&op->resource[0], 0, 0x2, "bbc_i2c_regs"); + if (!bp->i2c_control_regs) + goto fail; + +- bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel"); +- if (!bp->i2c_bussel_reg) +- goto fail; ++ if (op->num_resources == 2) { ++ bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel"); ++ if (!bp->i2c_bussel_reg) ++ goto fail; ++ } + + bp->waiting = 0; + init_waitqueue_head(&bp->wq); +diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c +index 0a73253..5f57e3d 100644 +--- a/drivers/scsi/3w-9xxx.c ++++ b/drivers/scsi/3w-9xxx.c +@@ -149,7 +149,6 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset); + static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg); + static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); + static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code); +-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id); + + /* Functions */ + +@@ -1352,11 +1351,11 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) + } + + /* Now complete the io */ ++ scsi_dma_unmap(cmd); ++ cmd->scsi_done(cmd); + tw_dev->state[request_id] = TW_S_COMPLETED; + twa_free_request_id(tw_dev, request_id); + tw_dev->posted_request_count--; +- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); +- twa_unmap_scsi_data(tw_dev, request_id); + } + + /* Check for valid status after each drain */ +@@ -1414,26 +1413,6 @@ static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_comm + } + } /* End twa_load_sgl() */ + +-/* This function will perform a pci-dma mapping for a scatter gather list */ +-static int twa_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id) +-{ +- int use_sg; +- struct scsi_cmnd *cmd = tw_dev->srb[request_id]; +- +- use_sg = scsi_dma_map(cmd); +- if (!use_sg) +- return 0; +- else if (use_sg < 0) { +- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list"); +- return 0; +- } +- +- cmd->SCp.phase = TW_PHASE_SGLIST; +- cmd->SCp.have_data_in = use_sg; +- +- return use_sg; +-} /* End twa_map_scsi_sg_data() */ +- + /* This function will poll for a response interrupt of a request */ + static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds) + { +@@ -1612,9 +1591,11 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev) + (tw_dev->state[i] != TW_S_INITIAL) && + (tw_dev->state[i] != TW_S_COMPLETED)) { + if (tw_dev->srb[i]) { +- tw_dev->srb[i]->result = (DID_RESET << 16); +- tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); +- twa_unmap_scsi_data(tw_dev, i); ++ struct scsi_cmnd *cmd = tw_dev->srb[i]; ++ ++ cmd->result = (DID_RESET << 16); ++ scsi_dma_unmap(cmd); ++ cmd->scsi_done(cmd); + } + } + } +@@ -1793,21 +1774,18 @@ static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_ + /* Save the scsi command for use by the ISR */ + tw_dev->srb[request_id] = SCpnt; + +- /* Initialize phase to zero */ +- SCpnt->SCp.phase = TW_PHASE_INITIAL; +- + retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL); + switch (retval) { + case SCSI_MLQUEUE_HOST_BUSY: ++ scsi_dma_unmap(SCpnt); + twa_free_request_id(tw_dev, request_id); +- twa_unmap_scsi_data(tw_dev, request_id); + break; + case 1: +- tw_dev->state[request_id] = TW_S_COMPLETED; +- twa_free_request_id(tw_dev, request_id); +- twa_unmap_scsi_data(tw_dev, request_id); + SCpnt->result = (DID_ERROR << 16); ++ scsi_dma_unmap(SCpnt); + done(SCpnt); ++ tw_dev->state[request_id] = TW_S_COMPLETED; ++ twa_free_request_id(tw_dev, request_id); + retval = 0; + } + out: +@@ -1875,8 +1853,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, + command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]); + command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH); + } else { +- sg_count = twa_map_scsi_sg_data(tw_dev, request_id); +- if (sg_count == 0) ++ sg_count = scsi_dma_map(srb); ++ if (sg_count < 0) + goto out; + + scsi_for_each_sg(srb, sg, sg_count, i) { +@@ -1991,15 +1969,6 @@ static char *twa_string_lookup(twa_message_type *table, unsigned int code) + return(table[index].text); + } /* End twa_string_lookup() */ + +-/* This function will perform a pci-dma unmap */ +-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id) +-{ +- struct scsi_cmnd *cmd = tw_dev->srb[request_id]; +- +- if (cmd->SCp.phase == TW_PHASE_SGLIST) +- scsi_dma_unmap(cmd); +-} /* End twa_unmap_scsi_data() */ +- + /* This function gets called when a disk is coming on-line */ + static int twa_slave_configure(struct scsi_device *sdev) + { +diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h +index 040f721..0fdc83c 100644 +--- a/drivers/scsi/3w-9xxx.h ++++ b/drivers/scsi/3w-9xxx.h +@@ -324,11 +324,6 @@ static twa_message_type twa_error_table[] = { + #define TW_CURRENT_DRIVER_BUILD 0 + #define TW_CURRENT_DRIVER_BRANCH 0 + +-/* Phase defines */ +-#define TW_PHASE_INITIAL 0 +-#define TW_PHASE_SINGLE 1 +-#define TW_PHASE_SGLIST 2 +- + /* Misc defines */ + #define TW_9550SX_DRAIN_COMPLETED 0xFFFF + #define TW_SECTOR_SIZE 512 +diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c +index 4de3460..61702ac 100644 +--- a/drivers/scsi/3w-sas.c ++++ b/drivers/scsi/3w-sas.c +@@ -303,26 +303,6 @@ static int twl_post_command_packet(TW_Device_Extension *tw_dev, int request_id) + return 0; + } /* End twl_post_command_packet() */ + +-/* This function will perform a pci-dma mapping for a scatter gather list */ +-static int twl_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id) +-{ +- int use_sg; +- struct scsi_cmnd *cmd = tw_dev->srb[request_id]; +- +- use_sg = scsi_dma_map(cmd); +- if (!use_sg) +- return 0; +- else if (use_sg < 0) { +- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1, "Failed to map scatter gather list"); +- return 0; +- } +- +- cmd->SCp.phase = TW_PHASE_SGLIST; +- cmd->SCp.have_data_in = use_sg; +- +- return use_sg; +-} /* End twl_map_scsi_sg_data() */ +- + /* This function hands scsi cdb's to the firmware */ + static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry_ISO *sglistarg) + { +@@ -370,8 +350,8 @@ static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, + if (!sglistarg) { + /* Map sglist from scsi layer to cmd packet */ + if (scsi_sg_count(srb)) { +- sg_count = twl_map_scsi_sg_data(tw_dev, request_id); +- if (sg_count == 0) ++ sg_count = scsi_dma_map(srb); ++ if (sg_count <= 0) + goto out; + + scsi_for_each_sg(srb, sg, sg_count, i) { +@@ -1116,15 +1096,6 @@ out: + return retval; + } /* End twl_initialize_device_extension() */ + +-/* This function will perform a pci-dma unmap */ +-static void twl_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id) +-{ +- struct scsi_cmnd *cmd = tw_dev->srb[request_id]; +- +- if (cmd->SCp.phase == TW_PHASE_SGLIST) +- scsi_dma_unmap(cmd); +-} /* End twl_unmap_scsi_data() */ +- + /* This function will handle attention interrupts */ + static int twl_handle_attention_interrupt(TW_Device_Extension *tw_dev) + { +@@ -1265,11 +1236,11 @@ static irqreturn_t twl_interrupt(int irq, void *dev_instance) + } + + /* Now complete the io */ ++ scsi_dma_unmap(cmd); ++ cmd->scsi_done(cmd); + tw_dev->state[request_id] = TW_S_COMPLETED; + twl_free_request_id(tw_dev, request_id); + tw_dev->posted_request_count--; +- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); +- twl_unmap_scsi_data(tw_dev, request_id); + } + + /* Check for another response interrupt */ +@@ -1414,10 +1385,12 @@ static int twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_res + if ((tw_dev->state[i] != TW_S_FINISHED) && + (tw_dev->state[i] != TW_S_INITIAL) && + (tw_dev->state[i] != TW_S_COMPLETED)) { +- if (tw_dev->srb[i]) { +- tw_dev->srb[i]->result = (DID_RESET << 16); +- tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); +- twl_unmap_scsi_data(tw_dev, i); ++ struct scsi_cmnd *cmd = tw_dev->srb[i]; ++ ++ if (cmd) { ++ cmd->result = (DID_RESET << 16); ++ scsi_dma_unmap(cmd); ++ cmd->scsi_done(cmd); + } + } + } +@@ -1521,9 +1494,6 @@ static int twl_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_ + /* Save the scsi command for use by the ISR */ + tw_dev->srb[request_id] = SCpnt; + +- /* Initialize phase to zero */ +- SCpnt->SCp.phase = TW_PHASE_INITIAL; +- + retval = twl_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL); + if (retval) { + tw_dev->state[request_id] = TW_S_COMPLETED; +diff --git a/drivers/scsi/3w-sas.h b/drivers/scsi/3w-sas.h +index d474892..fec6449 100644 +--- a/drivers/scsi/3w-sas.h ++++ b/drivers/scsi/3w-sas.h +@@ -103,10 +103,6 @@ static char *twl_aen_severity_table[] = + #define TW_CURRENT_DRIVER_BUILD 0 + #define TW_CURRENT_DRIVER_BRANCH 0 + +-/* Phase defines */ +-#define TW_PHASE_INITIAL 0 +-#define TW_PHASE_SGLIST 2 +- + /* Misc defines */ + #define TW_SECTOR_SIZE 512 + #define TW_MAX_UNITS 32 +diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c +index 752624e..b327742 100644 +--- a/drivers/scsi/3w-xxxx.c ++++ b/drivers/scsi/3w-xxxx.c +@@ -1284,32 +1284,6 @@ static int tw_initialize_device_extension(TW_Device_Extension *tw_dev) + return 0; + } /* End tw_initialize_device_extension() */ + +-static int tw_map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) +-{ +- int use_sg; +- +- dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n"); +- +- use_sg = scsi_dma_map(cmd); +- if (use_sg < 0) { +- printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n"); +- return 0; +- } +- +- cmd->SCp.phase = TW_PHASE_SGLIST; +- cmd->SCp.have_data_in = use_sg; +- +- return use_sg; +-} /* End tw_map_scsi_sg_data() */ +- +-static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) +-{ +- dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n"); +- +- if (cmd->SCp.phase == TW_PHASE_SGLIST) +- scsi_dma_unmap(cmd); +-} /* End tw_unmap_scsi_data() */ +- + /* This function will reset a device extension */ + static int tw_reset_device_extension(TW_Device_Extension *tw_dev) + { +@@ -1332,8 +1306,8 @@ static int tw_reset_device_extension(TW_Device_Extension *tw_dev) + srb = tw_dev->srb[i]; + if (srb != NULL) { + srb->result = (DID_RESET << 16); +- tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); +- tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]); ++ scsi_dma_unmap(srb); ++ srb->scsi_done(srb); + } + } + } +@@ -1780,8 +1754,8 @@ static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id) + command_packet->byte8.io.lba = lba; + command_packet->byte6.block_count = num_sectors; + +- use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); +- if (!use_sg) ++ use_sg = scsi_dma_map(srb); ++ if (use_sg <= 0) + return 1; + + scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) { +@@ -1968,9 +1942,6 @@ static int tw_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_c + /* Save the scsi command for use by the ISR */ + tw_dev->srb[request_id] = SCpnt; + +- /* Initialize phase to zero */ +- SCpnt->SCp.phase = TW_PHASE_INITIAL; +- + switch (*command) { + case READ_10: + case READ_6: +@@ -2198,12 +2169,11 @@ static irqreturn_t tw_interrupt(int irq, void *dev_instance) + + /* Now complete the io */ + if ((error != TW_ISR_DONT_COMPLETE)) { ++ scsi_dma_unmap(tw_dev->srb[request_id]); ++ tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); + tw_dev->state[request_id] = TW_S_COMPLETED; + tw_state_request_finish(tw_dev, request_id); + tw_dev->posted_request_count--; +- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); +- +- tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); + } + } + +diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h +index 49dcf03..1d31858 100644 +--- a/drivers/scsi/3w-xxxx.h ++++ b/drivers/scsi/3w-xxxx.h +@@ -195,11 +195,6 @@ static unsigned char tw_sense_table[][4] = + #define TW_AEN_SMART_FAIL 0x000F + #define TW_AEN_SBUF_FAIL 0x0024 + +-/* Phase defines */ +-#define TW_PHASE_INITIAL 0 +-#define TW_PHASE_SINGLE 1 +-#define TW_PHASE_SGLIST 2 +- + /* Misc defines */ + #define TW_ALIGNMENT_6000 64 /* 64 bytes */ + #define TW_ALIGNMENT_7000 4 /* 4 bytes */ +diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c +index 1e9d6ad..7563b3d 100644 +--- a/drivers/scsi/NCR5380.c ++++ b/drivers/scsi/NCR5380.c +@@ -2655,14 +2655,14 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) { + * + * Purpose : abort a command + * +- * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the +- * host byte of the result field to, if zero DID_ABORTED is ++ * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the ++ * host byte of the result field to, if zero DID_ABORTED is + * used. + * +- * Returns : 0 - success, -1 on failure. ++ * Returns : SUCCESS - success, FAILED on failure. + * +- * XXX - there is no way to abort the command that is currently +- * connected, you have to wait for it to complete. If this is ++ * XXX - there is no way to abort the command that is currently ++ * connected, you have to wait for it to complete. If this is + * a problem, we could implement longjmp() / setjmp(), setjmp() + * called where the loop started in NCR5380_main(). + * +@@ -2712,7 +2712,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) { + * aborted flag and get back into our main loop. + */ + +- return 0; ++ return SUCCESS; + } + #endif + +diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c +index 5f31017..31ace4b 100644 +--- a/drivers/scsi/aha1740.c ++++ b/drivers/scsi/aha1740.c +@@ -531,7 +531,7 @@ static int aha1740_eh_abort_handler (Scsi_Cmnd *dummy) + * quiet as possible... + */ + +- return 0; ++ return SUCCESS; + } + + static struct scsi_host_template aha1740_template = { +diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c +index 0f3cdbc..30073d4 100644 +--- a/drivers/scsi/atari_NCR5380.c ++++ b/drivers/scsi/atari_NCR5380.c +@@ -2613,7 +2613,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) + * host byte of the result field to, if zero DID_ABORTED is + * used. + * +- * Returns : 0 - success, -1 on failure. ++ * Returns : SUCCESS - success, FAILED on failure. + * + * XXX - there is no way to abort the command that is currently + * connected, you have to wait for it to complete. If this is +diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c +index 5642a9b..19ddd43 100644 +--- a/drivers/scsi/be2iscsi/be_main.c ++++ b/drivers/scsi/be2iscsi/be_main.c +@@ -581,7 +581,6 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) + "beiscsi_hba_alloc - iscsi_host_alloc failed\n"); + return NULL; + } +- shost->dma_boundary = pcidev->dma_mask; + shost->max_id = BE2_MAX_SESSIONS; + shost->max_channel = 0; + shost->max_cmd_len = BEISCSI_MAX_CMD_LEN; +@@ -5685,9 +5684,9 @@ free_port: + hba_free: + if (phba->msix_enabled) + pci_disable_msix(phba->pcidev); +- iscsi_host_remove(phba->shost); + pci_dev_put(phba->pcidev); + iscsi_host_free(phba->shost); ++ pci_set_drvdata(pcidev, NULL); + disable_pci: + pci_disable_device(pcidev); + return ret; +diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c +index b2fcac7..5bb9406 100644 +--- a/drivers/scsi/be2iscsi/be_mgmt.c ++++ b/drivers/scsi/be2iscsi/be_mgmt.c +@@ -897,17 +897,20 @@ mgmt_static_ip_modify(struct beiscsi_hba *phba, + + if (ip_action == IP_ACTION_ADD) { + memcpy(req->ip_params.ip_record.ip_addr.addr, ip_param->value, +- ip_param->len); ++ sizeof(req->ip_params.ip_record.ip_addr.addr)); + + if (subnet_param) + memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, +- subnet_param->value, subnet_param->len); ++ subnet_param->value, ++ sizeof(req->ip_params.ip_record.ip_addr.subnet_mask)); + } else { + memcpy(req->ip_params.ip_record.ip_addr.addr, +- if_info->ip_addr.addr, ip_param->len); ++ if_info->ip_addr.addr, ++ sizeof(req->ip_params.ip_record.ip_addr.addr)); + + memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, +- if_info->ip_addr.subnet_mask, ip_param->len); ++ if_info->ip_addr.subnet_mask, ++ sizeof(req->ip_params.ip_record.ip_addr.subnet_mask)); + } + + rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); +@@ -935,7 +938,7 @@ static int mgmt_modify_gateway(struct beiscsi_hba *phba, uint8_t *gt_addr, + req->action = gtway_action; + req->ip_addr.ip_type = BE2_IPV4; + +- memcpy(req->ip_addr.addr, gt_addr, param_len); ++ memcpy(req->ip_addr.addr, gt_addr, sizeof(req->ip_addr.addr)); + + return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); + } +diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c +index 65180e1..50c75e1 100644 +--- a/drivers/scsi/bfa/bfa_ioc.c ++++ b/drivers/scsi/bfa/bfa_ioc.c +@@ -7006,7 +7006,7 @@ bfa_flash_sem_get(void __iomem *bar) + while (!bfa_raw_sem_get(bar)) { + if (--n <= 0) + return BFA_STATUS_BADFLASH; +- udelay(10000); ++ mdelay(10); + } + return BFA_STATUS_OK; + } +diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h +index 2e28392..a38aafa0 100644 +--- a/drivers/scsi/bfa/bfa_ioc.h ++++ b/drivers/scsi/bfa/bfa_ioc.h +@@ -72,7 +72,7 @@ struct bfa_sge_s { + } while (0) + + #define bfa_swap_words(_x) ( \ +- ((_x) << 32) | ((_x) >> 32)) ++ ((u64)(_x) << 32) | ((u64)(_x) >> 32)) + + #ifdef __BIG_ENDIAN + #define bfa_sge_to_be(_x) +diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +index 9b94850..cc6b13b 100644 +--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c ++++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +@@ -411,6 +411,7 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev, + struct fc_frame_header *fh; + struct fcoe_rcv_info *fr; + struct fcoe_percpu_s *bg; ++ struct sk_buff *tmp_skb; + unsigned short oxid; + + interface = container_of(ptype, struct bnx2fc_interface, +@@ -423,6 +424,12 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev, + goto err; + } + ++ tmp_skb = skb_share_check(skb, GFP_ATOMIC); ++ if (!tmp_skb) ++ goto err; ++ ++ skb = tmp_skb; ++ + if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) { + printk(KERN_ERR PFX "bnx2fc_rcv: Wrong FC type frame\n"); + goto err; +diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c +index f37f3e3..28fe6fe 100644 +--- a/drivers/scsi/esas2r/esas2r_main.c ++++ b/drivers/scsi/esas2r/esas2r_main.c +@@ -1057,7 +1057,7 @@ int esas2r_eh_abort(struct scsi_cmnd *cmd) + + cmd->scsi_done(cmd); + +- return 0; ++ return SUCCESS; + } + + spin_lock_irqsave(&a->queue_lock, flags); +diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c +index 868318a..85d370e 100644 +--- a/drivers/scsi/hpsa.c ++++ b/drivers/scsi/hpsa.c +@@ -3131,7 +3131,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) + } + if (ioc->Request.Type.Direction == XFER_WRITE) { + if (copy_from_user(buff[sg_used], data_ptr, sz)) { +- status = -ENOMEM; ++ status = -EFAULT; + goto cleanup1; + } + } else +@@ -3984,10 +3984,6 @@ static int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev) + + /* Save the PCI command register */ + pci_read_config_word(pdev, 4, &command_register); +- /* Turn the board off. This is so that later pci_restore_state() +- * won't turn the board on before the rest of config space is ready. +- */ +- pci_disable_device(pdev); + pci_save_state(pdev); + + /* find the first memory BAR, so we can find the cfg table */ +@@ -4035,11 +4031,6 @@ static int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev) + goto unmap_cfgtable; + + pci_restore_state(pdev); +- rc = pci_enable_device(pdev); +- if (rc) { +- dev_warn(&pdev->dev, "failed to enable device.\n"); +- goto unmap_cfgtable; +- } + pci_write_config_word(pdev, 4, command_register); + + /* Some devices (notably the HP Smart Array 5i Controller) +@@ -4367,9 +4358,9 @@ static inline void hpsa_set_driver_support_bits(struct ctlr_info *h) + { + u32 driver_support; + +-#ifdef CONFIG_X86 +- /* Need to enable prefetch in the SCSI core for 6400 in x86 */ + driver_support = readl(&(h->cfgtable->driver_support)); ++ /* Need to enable prefetch in the SCSI core for 6400 in x86 */ ++#ifdef CONFIG_X86 + driver_support |= ENABLE_SCSI_PREFETCH; + #endif + driver_support |= ENABLE_UNIT_ATTN; +@@ -4525,6 +4516,23 @@ static int hpsa_init_reset_devices(struct pci_dev *pdev) + if (!reset_devices) + return 0; + ++ /* kdump kernel is loading, we don't know in which state is ++ * the pci interface. The dev->enable_cnt is equal zero ++ * so we call enable+disable, wait a while and switch it on. ++ */ ++ rc = pci_enable_device(pdev); ++ if (rc) { ++ dev_warn(&pdev->dev, "Failed to enable PCI device\n"); ++ return -ENODEV; ++ } ++ pci_disable_device(pdev); ++ msleep(260); /* a randomly chosen number */ ++ rc = pci_enable_device(pdev); ++ if (rc) { ++ dev_warn(&pdev->dev, "failed to enable device.\n"); ++ return -ENODEV; ++ } ++ pci_set_master(pdev); + /* Reset the controller with a PCI power-cycle or via doorbell */ + rc = hpsa_kdump_hard_reset_controller(pdev); + +@@ -4533,10 +4541,11 @@ static int hpsa_init_reset_devices(struct pci_dev *pdev) + * "performant mode". Or, it might be 640x, which can't reset + * due to concerns about shared bbwc between 6402/6404 pair. + */ +- if (rc == -ENOTSUPP) +- return rc; /* just try to do the kdump anyhow. */ +- if (rc) +- return -ENODEV; ++ if (rc) { ++ if (rc != -ENOTSUPP) /* just try to do the kdump anyhow. */ ++ rc = -ENODEV; ++ goto out_disable; ++ } + + /* Now try to get the controller to respond to a no-op */ + dev_warn(&pdev->dev, "Waiting for controller to respond to no-op\n"); +@@ -4547,7 +4556,11 @@ static int hpsa_init_reset_devices(struct pci_dev *pdev) + dev_warn(&pdev->dev, "no-op failed%s\n", + (i < 11 ? "; re-trying" : "")); + } +- return 0; ++ ++out_disable: ++ ++ pci_disable_device(pdev); ++ return rc; + } + + static int hpsa_allocate_cmd_pool(struct ctlr_info *h) +@@ -4690,6 +4703,7 @@ static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h) + iounmap(h->transtable); + if (h->cfgtable) + iounmap(h->cfgtable); ++ pci_disable_device(h->pdev); + pci_release_regions(h->pdev); + kfree(h); + } +diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c +index 3f5b56a..128dc2f 100644 +--- a/drivers/scsi/ipr.c ++++ b/drivers/scsi/ipr.c +@@ -592,9 +592,10 @@ static void ipr_trc_hook(struct ipr_cmnd *ipr_cmd, + { + struct ipr_trace_entry *trace_entry; + struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; ++ unsigned int trace_index; + +- trace_entry = &ioa_cfg->trace[atomic_add_return +- (1, &ioa_cfg->trace_index)%IPR_NUM_TRACE_ENTRIES]; ++ trace_index = atomic_add_return(1, &ioa_cfg->trace_index) & IPR_TRACE_INDEX_MASK; ++ trace_entry = &ioa_cfg->trace[trace_index]; + trace_entry->time = jiffies; + trace_entry->op_code = ipr_cmd->ioarcb.cmd_pkt.cdb[0]; + trace_entry->type = type; +@@ -683,6 +684,7 @@ static void ipr_init_ipr_cmnd(struct ipr_cmnd *ipr_cmd, + ipr_reinit_ipr_cmnd(ipr_cmd); + ipr_cmd->u.scratch = 0; + ipr_cmd->sibling = NULL; ++ ipr_cmd->eh_comp = NULL; + ipr_cmd->fast_done = fast_done; + init_timer(&ipr_cmd->timer); + } +@@ -848,6 +850,8 @@ static void ipr_scsi_eh_done(struct ipr_cmnd *ipr_cmd) + + scsi_dma_unmap(ipr_cmd->scsi_cmd); + scsi_cmd->scsi_done(scsi_cmd); ++ if (ipr_cmd->eh_comp) ++ complete(ipr_cmd->eh_comp); + list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); + } + +@@ -1041,10 +1045,15 @@ static void ipr_send_blocking_cmd(struct ipr_cmnd *ipr_cmd, + + static int ipr_get_hrrq_index(struct ipr_ioa_cfg *ioa_cfg) + { ++ unsigned int hrrq; ++ + if (ioa_cfg->hrrq_num == 1) +- return 0; +- else +- return (atomic_add_return(1, &ioa_cfg->hrrq_index) % (ioa_cfg->hrrq_num - 1)) + 1; ++ hrrq = 0; ++ else { ++ hrrq = atomic_add_return(1, &ioa_cfg->hrrq_index); ++ hrrq = (hrrq % (ioa_cfg->hrrq_num - 1)) + 1; ++ } ++ return hrrq; + } + + /** +@@ -4805,6 +4814,84 @@ static int ipr_slave_alloc(struct scsi_device *sdev) + return rc; + } + ++/** ++ * ipr_match_lun - Match function for specified LUN ++ * @ipr_cmd: ipr command struct ++ * @device: device to match (sdev) ++ * ++ * Returns: ++ * 1 if command matches sdev / 0 if command does not match sdev ++ **/ ++static int ipr_match_lun(struct ipr_cmnd *ipr_cmd, void *device) ++{ ++ if (ipr_cmd->scsi_cmd && ipr_cmd->scsi_cmd->device == device) ++ return 1; ++ return 0; ++} ++ ++/** ++ * ipr_wait_for_ops - Wait for matching commands to complete ++ * @ipr_cmd: ipr command struct ++ * @device: device to match (sdev) ++ * @match: match function to use ++ * ++ * Returns: ++ * SUCCESS / FAILED ++ **/ ++static int ipr_wait_for_ops(struct ipr_ioa_cfg *ioa_cfg, void *device, ++ int (*match)(struct ipr_cmnd *, void *)) ++{ ++ struct ipr_cmnd *ipr_cmd; ++ int wait; ++ unsigned long flags; ++ struct ipr_hrr_queue *hrrq; ++ signed long timeout = IPR_ABORT_TASK_TIMEOUT; ++ DECLARE_COMPLETION_ONSTACK(comp); ++ ++ ENTER; ++ do { ++ wait = 0; ++ ++ for_each_hrrq(hrrq, ioa_cfg) { ++ spin_lock_irqsave(hrrq->lock, flags); ++ list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) { ++ if (match(ipr_cmd, device)) { ++ ipr_cmd->eh_comp = ∁ ++ wait++; ++ } ++ } ++ spin_unlock_irqrestore(hrrq->lock, flags); ++ } ++ ++ if (wait) { ++ timeout = wait_for_completion_timeout(&comp, timeout); ++ ++ if (!timeout) { ++ wait = 0; ++ ++ for_each_hrrq(hrrq, ioa_cfg) { ++ spin_lock_irqsave(hrrq->lock, flags); ++ list_for_each_entry(ipr_cmd, &hrrq->hrrq_pending_q, queue) { ++ if (match(ipr_cmd, device)) { ++ ipr_cmd->eh_comp = NULL; ++ wait++; ++ } ++ } ++ spin_unlock_irqrestore(hrrq->lock, flags); ++ } ++ ++ if (wait) ++ dev_err(&ioa_cfg->pdev->dev, "Timed out waiting for aborted commands\n"); ++ LEAVE; ++ return wait ? FAILED : SUCCESS; ++ } ++ } ++ } while (wait); ++ ++ LEAVE; ++ return SUCCESS; ++} ++ + static int ipr_eh_host_reset(struct scsi_cmnd *cmd) + { + struct ipr_ioa_cfg *ioa_cfg; +@@ -5023,11 +5110,17 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd *scsi_cmd) + static int ipr_eh_dev_reset(struct scsi_cmnd *cmd) + { + int rc; ++ struct ipr_ioa_cfg *ioa_cfg; ++ ++ ioa_cfg = (struct ipr_ioa_cfg *) cmd->device->host->hostdata; + + spin_lock_irq(cmd->device->host->host_lock); + rc = __ipr_eh_dev_reset(cmd); + spin_unlock_irq(cmd->device->host->host_lock); + ++ if (rc == SUCCESS) ++ rc = ipr_wait_for_ops(ioa_cfg, cmd->device, ipr_match_lun); ++ + return rc; + } + +@@ -5205,13 +5298,18 @@ static int ipr_eh_abort(struct scsi_cmnd *scsi_cmd) + { + unsigned long flags; + int rc; ++ struct ipr_ioa_cfg *ioa_cfg; + + ENTER; + ++ ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata; ++ + spin_lock_irqsave(scsi_cmd->device->host->host_lock, flags); + rc = ipr_cancel_op(scsi_cmd); + spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, flags); + ++ if (rc == SUCCESS) ++ rc = ipr_wait_for_ops(ioa_cfg, scsi_cmd->device, ipr_match_lun); + LEAVE; + return rc; + } +@@ -6087,21 +6185,23 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd) + struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; + struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; + u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); +- unsigned long hrrq_flags; ++ unsigned long lock_flags; + + scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->s.ioasa.hdr.residual_data_len)); + + if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) { + scsi_dma_unmap(scsi_cmd); + +- spin_lock_irqsave(ipr_cmd->hrrq->lock, hrrq_flags); ++ spin_lock_irqsave(ipr_cmd->hrrq->lock, lock_flags); + list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); + scsi_cmd->scsi_done(scsi_cmd); +- spin_unlock_irqrestore(ipr_cmd->hrrq->lock, hrrq_flags); ++ spin_unlock_irqrestore(ipr_cmd->hrrq->lock, lock_flags); + } else { +- spin_lock_irqsave(ipr_cmd->hrrq->lock, hrrq_flags); ++ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); ++ spin_lock(&ipr_cmd->hrrq->_lock); + ipr_erp_start(ioa_cfg, ipr_cmd); +- spin_unlock_irqrestore(ipr_cmd->hrrq->lock, hrrq_flags); ++ spin_unlock(&ipr_cmd->hrrq->_lock); ++ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + } + } + +diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h +index 9ce38a2..694ec20 100644 +--- a/drivers/scsi/ipr.h ++++ b/drivers/scsi/ipr.h +@@ -264,7 +264,7 @@ + #define IPR_RUNTIME_RESET 0x40000000 + + #define IPR_IPL_INIT_MIN_STAGE_TIME 5 +-#define IPR_IPL_INIT_DEFAULT_STAGE_TIME 15 ++#define IPR_IPL_INIT_DEFAULT_STAGE_TIME 30 + #define IPR_IPL_INIT_STAGE_UNKNOWN 0x0 + #define IPR_IPL_INIT_STAGE_TRANSOP 0xB0000000 + #define IPR_IPL_INIT_STAGE_MASK 0xff000000 +@@ -1459,6 +1459,7 @@ struct ipr_ioa_cfg { + + #define IPR_NUM_TRACE_INDEX_BITS 8 + #define IPR_NUM_TRACE_ENTRIES (1 << IPR_NUM_TRACE_INDEX_BITS) ++#define IPR_TRACE_INDEX_MASK (IPR_NUM_TRACE_ENTRIES - 1) + #define IPR_TRACE_SIZE (sizeof(struct ipr_trace_entry) * IPR_NUM_TRACE_ENTRIES) + char trace_start[8]; + #define IPR_TRACE_START_LABEL "trace" +@@ -1585,6 +1586,7 @@ struct ipr_cmnd { + struct scsi_device *sdev; + } u; + ++ struct completion *eh_comp; + struct ipr_hrr_queue *hrrq; + struct ipr_ioa_cfg *ioa_cfg; + }; +diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c +index 1b3a094..30f9ef0 100644 +--- a/drivers/scsi/libfc/fc_exch.c ++++ b/drivers/scsi/libfc/fc_exch.c +@@ -733,8 +733,6 @@ static bool fc_invoke_resp(struct fc_exch *ep, struct fc_seq *sp, + if (resp) { + resp(sp, fp, arg); + res = true; +- } else if (!IS_ERR(fp)) { +- fc_frame_free(fp); + } + + spin_lock_bh(&ep->ex_lock); +@@ -1596,7 +1594,8 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) + * If new exch resp handler is valid then call that + * first. + */ +- fc_invoke_resp(ep, sp, fp); ++ if (!fc_invoke_resp(ep, sp, fp)) ++ fc_frame_free(fp); + + fc_exch_release(ep); + return; +@@ -1695,7 +1694,8 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) + fc_exch_hold(ep); + if (!rc) + fc_exch_delete(ep); +- fc_invoke_resp(ep, sp, fp); ++ if (!fc_invoke_resp(ep, sp, fp)) ++ fc_frame_free(fp); + if (has_rec) + fc_exch_timer_set(ep, ep->r_a_tov); + fc_exch_release(ep); +diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c +index 1d7e76e..ae6fc1a 100644 +--- a/drivers/scsi/libfc/fc_fcp.c ++++ b/drivers/scsi/libfc/fc_fcp.c +@@ -1039,11 +1039,26 @@ restart: + fc_fcp_pkt_hold(fsp); + spin_unlock_irqrestore(&si->scsi_queue_lock, flags); + +- if (!fc_fcp_lock_pkt(fsp)) { ++ spin_lock_bh(&fsp->scsi_pkt_lock); ++ if (!(fsp->state & FC_SRB_COMPL)) { ++ fsp->state |= FC_SRB_COMPL; ++ /* ++ * TODO: dropping scsi_pkt_lock and then reacquiring ++ * again around fc_fcp_cleanup_cmd() is required, ++ * since fc_fcp_cleanup_cmd() calls into ++ * fc_seq_set_resp() and that func preempts cpu using ++ * schedule. May be schedule and related code should be ++ * removed instead of unlocking here to avoid scheduling ++ * while atomic bug. ++ */ ++ spin_unlock_bh(&fsp->scsi_pkt_lock); ++ + fc_fcp_cleanup_cmd(fsp, error); ++ ++ spin_lock_bh(&fsp->scsi_pkt_lock); + fc_io_compl(fsp); +- fc_fcp_unlock_pkt(fsp); + } ++ spin_unlock_bh(&fsp->scsi_pkt_lock); + + fc_fcp_pkt_release(fsp); + spin_lock_irqsave(&si->scsi_queue_lock, flags); +diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c +index 4046241..4549986 100644 +--- a/drivers/scsi/libiscsi.c ++++ b/drivers/scsi/libiscsi.c +@@ -717,11 +717,21 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + return NULL; + } + ++ if (data_size > ISCSI_DEF_MAX_RECV_SEG_LEN) { ++ iscsi_conn_printk(KERN_ERR, conn, "Invalid buffer len of %u for login task. Max len is %u\n", data_size, ISCSI_DEF_MAX_RECV_SEG_LEN); ++ return NULL; ++ } ++ + task = conn->login_task; + } else { + if (session->state != ISCSI_STATE_LOGGED_IN) + return NULL; + ++ if (data_size != 0) { ++ iscsi_conn_printk(KERN_ERR, conn, "Can not send data buffer of len %u for op 0x%x\n", data_size, opcode); ++ return NULL; ++ } ++ + BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); + BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); + +diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c +index 62b58d3..60de662 100644 +--- a/drivers/scsi/libsas/sas_discover.c ++++ b/drivers/scsi/libsas/sas_discover.c +@@ -500,6 +500,7 @@ static void sas_revalidate_domain(struct work_struct *work) + struct sas_discovery_event *ev = to_sas_discovery_event(work); + struct asd_sas_port *port = ev->port; + struct sas_ha_struct *ha = port->ha; ++ struct domain_device *ddev = port->port_dev; + + /* prevent revalidation from finding sata links in recovery */ + mutex_lock(&ha->disco_mutex); +@@ -514,8 +515,9 @@ static void sas_revalidate_domain(struct work_struct *work) + SAS_DPRINTK("REVALIDATING DOMAIN on port %d, pid:%d\n", port->id, + task_pid_nr(current)); + +- if (port->port_dev) +- res = sas_ex_revalidate_domain(port->port_dev); ++ if (ddev && (ddev->dev_type == SAS_FANOUT_EXPANDER_DEVICE || ++ ddev->dev_type == SAS_EDGE_EXPANDER_DEVICE)) ++ res = sas_ex_revalidate_domain(ddev); + + SAS_DPRINTK("done REVALIDATING DOMAIN on port %d, pid:%d, res 0x%x\n", + port->id, task_pid_nr(current), res); +diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c +index 8f580fd..ce21132 100644 +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -265,6 +265,16 @@ lpfc_sli4_eq_get(struct lpfc_queue *q) + return NULL; + + q->hba_index = idx; ++ ++ /* ++ * insert barrier for instruction interlock : data from the hardware ++ * must have the valid bit checked before it can be copied and acted ++ * upon. Given what was seen in lpfc_sli4_cq_get() of speculative ++ * instructions allowing action on content before valid bit checked, ++ * add barrier here as well. May not be needed as "content" is a ++ * single 32-bit entity here (vs multi word structure for cq's). ++ */ ++ mb(); + return eqe; + } + +@@ -370,6 +380,17 @@ lpfc_sli4_cq_get(struct lpfc_queue *q) + + cqe = q->qe[q->hba_index].cqe; + q->hba_index = idx; ++ ++ /* ++ * insert barrier for instruction interlock : data from the hardware ++ * must have the valid bit checked before it can be copied and acted ++ * upon. Speculative instructions were allowing a bcopy at the start ++ * of lpfc_sli4_fp_handle_wcqe(), which is called immediately ++ * after our return, to copy data before the valid bit check above ++ * was done. As such, some of the copied data was stale. The barrier ++ * ensures the check is before any data is copied. ++ */ ++ mb(); + return cqe; + } + +diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c +index 816db12..52587ce 100644 +--- a/drivers/scsi/megaraid.c ++++ b/drivers/scsi/megaraid.c +@@ -1967,7 +1967,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor) + cmd->device->id, cmd->device->lun); + + if(list_empty(&adapter->pending_list)) +- return FALSE; ++ return FAILED; + + list_for_each_safe(pos, next, &adapter->pending_list) { + +@@ -1990,7 +1990,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor) + (aor==SCB_ABORT) ? "ABORTING":"RESET", + scb->idx); + +- return FALSE; ++ return FAILED; + } + else { + +@@ -2015,12 +2015,12 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor) + list_add_tail(SCSI_LIST(cmd), + &adapter->completed_list); + +- return TRUE; ++ return SUCCESS; + } + } + } + +- return FALSE; ++ return FAILED; + } + + static inline int +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index 3b7ad10..c80afde 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -953,7 +953,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, + cpu_to_le32(upper_32_bits(cmd_to_abort->frame_phys_addr)); + + cmd->sync_cmd = 1; +- cmd->cmd_status = 0xFF; ++ cmd->cmd_status = ENODATA; + + instance->instancet->issue_dcmd(instance, cmd); + +diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c +index f655592..a1f04e3 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c ++++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c +@@ -92,6 +92,8 @@ megasas_enable_intr_fusion(struct megasas_instance *instance) + { + struct megasas_register_set __iomem *regs; + regs = instance->reg_set; ++ ++ instance->mask_interrupts = 0; + /* For Thunderbolt/Invader also clear intr on enable */ + writel(~0, ®s->outbound_intr_status); + readl(®s->outbound_intr_status); +@@ -100,7 +102,6 @@ megasas_enable_intr_fusion(struct megasas_instance *instance) + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +- instance->mask_interrupts = 0; + } + + /** +diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c +index 410f4a3..72f9c55 100644 +--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c ++++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c +@@ -1006,12 +1006,9 @@ mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc, + &mpt2sas_phy->remote_identify); + _transport_add_phy_to_an_existing_port(ioc, sas_node, + mpt2sas_phy, mpt2sas_phy->remote_identify.sas_address); +- } else { ++ } else + memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct + sas_identify)); +- _transport_del_phy_from_an_existing_port(ioc, sas_node, +- mpt2sas_phy); +- } + + if (mpt2sas_phy->phy) + mpt2sas_phy->phy->negotiated_linkrate = +diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c +index 65170cb..55aa597 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c +@@ -1003,12 +1003,9 @@ mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc, + &mpt3sas_phy->remote_identify); + _transport_add_phy_to_an_existing_port(ioc, sas_node, + mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address); +- } else { ++ } else + memset(&mpt3sas_phy->remote_identify, 0 , sizeof(struct + sas_identify)); +- _transport_del_phy_from_an_existing_port(ioc, sas_node, +- mpt3sas_phy); +- } + + if (mpt3sas_phy->phy) + mpt3sas_phy->phy->negotiated_linkrate = +diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c +index 6c1f223..4c0b8b4 100644 +--- a/drivers/scsi/mvsas/mv_sas.c ++++ b/drivers/scsi/mvsas/mv_sas.c +@@ -441,14 +441,11 @@ static u32 mvs_get_ncq_tag(struct sas_task *task, u32 *tag) + static int mvs_task_prep_ata(struct mvs_info *mvi, + struct mvs_task_exec_info *tei) + { +- struct sas_ha_struct *sha = mvi->sas; + struct sas_task *task = tei->task; + struct domain_device *dev = task->dev; + struct mvs_device *mvi_dev = dev->lldd_dev; + struct mvs_cmd_hdr *hdr = tei->hdr; + struct asd_sas_port *sas_port = dev->port; +- struct sas_phy *sphy = dev->phy; +- struct asd_sas_phy *sas_phy = sha->sas_phy[sphy->number]; + struct mvs_slot_info *slot; + void *buf_prd; + u32 tag = tei->tag, hdr_tag; +@@ -468,7 +465,7 @@ static int mvs_task_prep_ata(struct mvs_info *mvi, + slot->tx = mvi->tx_prod; + del_q = TXQ_MODE_I | tag | + (TXQ_CMD_STP << TXQ_CMD_SHIFT) | +- (MVS_PHY_ID << TXQ_PHY_SHIFT) | ++ ((sas_port->phy_mask & TXQ_PHY_MASK) << TXQ_PHY_SHIFT) | + (mvi_dev->taskfileset << TXQ_SRS_SHIFT); + mvi->tx[mvi->tx_prod] = cpu_to_le32(del_q); + +diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h +index 1f42662..b5f22a9 100644 +--- a/drivers/scsi/qla2xxx/qla_gbl.h ++++ b/drivers/scsi/qla2xxx/qla_gbl.h +@@ -728,8 +728,6 @@ extern void qla8044_set_idc_dontreset(struct scsi_qla_host *ha); + extern int qla8044_rd_direct(struct scsi_qla_host *vha, const uint32_t crb_reg); + extern void qla8044_wr_direct(struct scsi_qla_host *vha, + const uint32_t crb_reg, const uint32_t value); +-extern inline void qla8044_set_qsnt_ready(struct scsi_qla_host *vha); +-extern inline void qla8044_need_reset_handler(struct scsi_qla_host *vha); + extern int qla8044_device_state_handler(struct scsi_qla_host *vha); + extern void qla8044_clear_qsnt_ready(struct scsi_qla_host *vha); + extern void qla8044_clear_drv_active(struct qla_hw_data *); +diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c +index 0a1dcb4..13f4bef 100644 +--- a/drivers/scsi/qla2xxx/qla_isr.c ++++ b/drivers/scsi/qla2xxx/qla_isr.c +@@ -572,8 +572,9 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24; + struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82; +- uint32_t rscn_entry, host_pid; ++ uint32_t rscn_entry, host_pid, tmp_pid; + unsigned long flags; ++ fc_port_t *fcport = NULL; + + /* Setup to process RIO completion. */ + handle_cnt = 0; +@@ -968,6 +969,20 @@ skip_rio: + if (qla2x00_is_a_vp_did(vha, rscn_entry)) + break; + ++ /* ++ * Search for the rport related to this RSCN entry and mark it ++ * as lost. ++ */ ++ list_for_each_entry(fcport, &vha->vp_fcports, list) { ++ if (atomic_read(&fcport->state) != FCS_ONLINE) ++ continue; ++ tmp_pid = fcport->d_id.b24; ++ if (fcport->d_id.b24 == rscn_entry) { ++ qla2x00_mark_device_lost(vha, fcport, 0, 0); ++ break; ++ } ++ } ++ + atomic_set(&vha->loop_down_timer, 0); + vha->flags.management_server_logged_in = 0; + +diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c +index f60989d..24f69ac 100644 +--- a/drivers/scsi/qla2xxx/qla_nx2.c ++++ b/drivers/scsi/qla2xxx/qla_nx2.c +@@ -146,7 +146,7 @@ qla8044_rmw_crb_reg(struct scsi_qla_host *vha, + return; + } + +-inline void ++static inline void + qla8044_set_qsnt_ready(struct scsi_qla_host *vha) + { + uint32_t qsnt_state; +diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c +index 83cb612..23c1b0c 100644 +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -3039,10 +3039,8 @@ qla2x00_unmap_iobases(struct qla_hw_data *ha) + } + + static void +-qla2x00_clear_drv_active(scsi_qla_host_t *vha) ++qla2x00_clear_drv_active(struct qla_hw_data *ha) + { +- struct qla_hw_data *ha = vha->hw; +- + if (IS_QLA8044(ha)) { + qla8044_idc_lock(ha); + qla8044_clear_drv_active(ha); +@@ -3111,7 +3109,7 @@ qla2x00_remove_one(struct pci_dev *pdev) + + scsi_host_put(base_vha->host); + +- qla2x00_clear_drv_active(base_vha); ++ qla2x00_clear_drv_active(ha); + + qla2x00_unmap_iobases(ha); + +diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c +index 0cb7307..2f264ac 100644 +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -1382,12 +1382,10 @@ static inline void qlt_unmap_sg(struct scsi_qla_host *vha, + static int qlt_check_reserve_free_req(struct scsi_qla_host *vha, + uint32_t req_cnt) + { +- struct qla_hw_data *ha = vha->hw; +- device_reg_t __iomem *reg = ha->iobase; + uint32_t cnt; + + if (vha->req->cnt < (req_cnt + 2)) { +- cnt = (uint16_t)RD_REG_DWORD(®->isp24.req_q_out); ++ cnt = (uint16_t)RD_REG_DWORD(vha->req->req_q_out); + + ql_dbg(ql_dbg_tgt, vha, 0xe00a, + "Request ring circled: cnt=%d, vha->->ring_index=%d, " +diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c +index 788c4fe..1817f3f 100644 +--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c ++++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c +@@ -707,7 +707,16 @@ static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess) + pr_debug("fc_rport domain: port_id 0x%06x\n", nacl->nport_id); + + node = btree_remove32(&lport->lport_fcport_map, nacl->nport_id); +- WARN_ON(node && (node != se_nacl)); ++ if (WARN_ON(node && (node != se_nacl))) { ++ /* ++ * The nacl no longer matches what we think it should be. ++ * Most likely a new dynamic acl has been added while ++ * someone dropped the hardware lock. It clearly is a ++ * bug elsewhere, but this bit can't make things worse. ++ */ ++ btree_insert32(&lport->lport_fcport_map, nacl->nport_id, ++ node, GFP_ATOMIC); ++ } + + pr_debug("Removed from fcport_map: %p for WWNN: 0x%016LX, port_id: 0x%06x\n", + se_nacl, nacl->nport_wwnn, nacl->nport_id); +@@ -1506,7 +1515,7 @@ static int tcm_qla2xxx_check_initiator_node_acl( + /* + * Finally register the new FC Nexus with TCM + */ +- __transport_register_session(se_nacl->se_tpg, se_nacl, se_sess, sess); ++ transport_register_session(se_nacl->se_tpg, se_nacl, se_sess, sess); + + return 0; + } +diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c +index f969aca..262ab83 100644 +--- a/drivers/scsi/scsi_devinfo.c ++++ b/drivers/scsi/scsi_devinfo.c +@@ -202,6 +202,7 @@ static struct { + {"IOMEGA", "Io20S *F", NULL, BLIST_KEY}, + {"INSITE", "Floptical F*8I", NULL, BLIST_KEY}, + {"INSITE", "I325VM", NULL, BLIST_KEY}, ++ {"Intel", "Multi-Flex", NULL, BLIST_NO_RSOC}, + {"iRiver", "iFP Mass Driver", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36}, + {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN}, + {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, +@@ -210,6 +211,7 @@ static struct { + {"Medion", "Flash XL MMC/SD", "2.6D", BLIST_FORCELUN}, + {"MegaRAID", "LD", NULL, BLIST_FORCELUN}, + {"MICROP", "4110", NULL, BLIST_NOTQ}, ++ {"MSFT", "Virtual HD", NULL, BLIST_NO_RSOC}, + {"MYLEX", "DACARMRB", "*", BLIST_REPORTLUN2}, + {"nCipher", "Fastness Crypto", NULL, BLIST_FORCELUN}, + {"NAKAMICH", "MJ-4.8S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, +@@ -222,6 +224,7 @@ static struct { + {"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, ++ {"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC}, + {"Promise", "", NULL, BLIST_SPARSELUN}, + {"QUANTUM", "XP34301", "1071", BLIST_NOTQ}, + {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN}, +diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c +index edb4d46..96b6664 100644 +--- a/drivers/scsi/scsi_error.c ++++ b/drivers/scsi/scsi_error.c +@@ -1984,8 +1984,10 @@ static void scsi_restart_operations(struct Scsi_Host *shost) + * is no point trying to lock the door of an off-line device. + */ + shost_for_each_device(sdev, shost) { +- if (scsi_device_online(sdev) && sdev->locked) ++ if (scsi_device_online(sdev) && sdev->was_reset && sdev->locked) { + scsi_eh_lock_door(sdev); ++ sdev->was_reset = 0; ++ } + } + + /* +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index 62ec84b..719bd82 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -831,6 +831,14 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) + scsi_next_command(cmd); + return; + } ++ } else if (blk_rq_bytes(req) == 0 && result && !sense_deferred) { ++ /* ++ * Certain non BLOCK_PC requests are commands that don't ++ * actually transfer anything (FLUSH), so cannot use ++ * good_bytes != blk_rq_bytes(req) as the signal for an error. ++ * This sets the error explicitly for the problem case. ++ */ ++ error = __scsi_error_from_host_byte(cmd, result); + } + + /* no bidi support for !REQ_TYPE_BLOCK_PC yet */ +@@ -1250,9 +1258,11 @@ int scsi_prep_state_check(struct scsi_device *sdev, struct request *req) + "rejecting I/O to dead device\n"); + ret = BLKPREP_KILL; + break; +- case SDEV_QUIESCE: + case SDEV_BLOCK: + case SDEV_CREATED_BLOCK: ++ ret = BLKPREP_DEFER; ++ break; ++ case SDEV_QUIESCE: + /* + * If the devices is blocked we defer normal commands. + */ +diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c +index 001e9ce..a59be67 100644 +--- a/drivers/scsi/scsi_pm.c ++++ b/drivers/scsi/scsi_pm.c +@@ -149,15 +149,15 @@ static int sdev_runtime_suspend(struct device *dev) + { + const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; + struct scsi_device *sdev = to_scsi_device(dev); +- int err; ++ int err = 0; + +- err = blk_pre_runtime_suspend(sdev->request_queue); +- if (err) +- return err; +- if (pm && pm->runtime_suspend) ++ if (pm && pm->runtime_suspend) { ++ err = blk_pre_runtime_suspend(sdev->request_queue); ++ if (err) ++ return err; + err = pm->runtime_suspend(dev); +- blk_post_runtime_suspend(sdev->request_queue, err); +- ++ blk_post_runtime_suspend(sdev->request_queue, err); ++ } + return err; + } + +@@ -180,11 +180,11 @@ static int sdev_runtime_resume(struct device *dev) + const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; + int err = 0; + +- blk_pre_runtime_resume(sdev->request_queue); +- if (pm && pm->runtime_resume) ++ if (pm && pm->runtime_resume) { ++ blk_pre_runtime_resume(sdev->request_queue); + err = pm->runtime_resume(dev); +- blk_post_runtime_resume(sdev->request_queue, err); +- ++ blk_post_runtime_resume(sdev->request_queue, err); ++ } + return err; + } + +diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c +index 4109530..054ec2c 100644 +--- a/drivers/scsi/scsi_scan.c ++++ b/drivers/scsi/scsi_scan.c +@@ -922,6 +922,12 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, + if (*bflags & BLIST_USE_10_BYTE_MS) + sdev->use_10_for_ms = 1; + ++ /* some devices don't like REPORT SUPPORTED OPERATION CODES ++ * and will simply timeout causing sd_mod init to take a very ++ * very long time */ ++ if (*bflags & BLIST_NO_RSOC) ++ sdev->no_report_opcodes = 1; ++ + /* set the device running here so that slave configure + * may do I/O */ + ret = scsi_device_set_state(sdev, SDEV_RUNNING); +@@ -950,7 +956,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, + + sdev->eh_timeout = SCSI_DEFAULT_EH_TIMEOUT; + +- if (*bflags & BLIST_SKIP_VPD_PAGES) ++ if (*bflags & BLIST_TRY_VPD_PAGES) ++ sdev->try_vpd_pages = 1; ++ else if (*bflags & BLIST_SKIP_VPD_PAGES) + sdev->skip_vpd_pages = 1; + + transport_configure_device(&sdev->sdev_gendev); +@@ -1236,6 +1244,12 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget, + max_dev_lun = min(8U, max_dev_lun); + + /* ++ * Stop scanning at 255 unless BLIST_SCSI3LUN ++ */ ++ if (!(bflags & BLIST_SCSI3LUN)) ++ max_dev_lun = min(256U, max_dev_lun); ++ ++ /* + * We have already scanned LUN 0, so start at LUN 1. Keep scanning + * until we reach the max, or no LUN is found and we are not + * sparse_lun. +diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c +index d47ffc8..b85eaa0 100644 +--- a/drivers/scsi/scsi_transport_srp.c ++++ b/drivers/scsi/scsi_transport_srp.c +@@ -397,6 +397,36 @@ static void srp_reconnect_work(struct work_struct *work) + } + } + ++/** ++ * scsi_request_fn_active() - number of kernel threads inside scsi_request_fn() ++ * @shost: SCSI host for which to count the number of scsi_request_fn() callers. ++ * ++ * To do: add support for scsi-mq in this function. ++ */ ++static int scsi_request_fn_active(struct Scsi_Host *shost) ++{ ++ struct scsi_device *sdev; ++ struct request_queue *q; ++ int request_fn_active = 0; ++ ++ shost_for_each_device(sdev, shost) { ++ q = sdev->request_queue; ++ ++ spin_lock_irq(q->queue_lock); ++ request_fn_active += q->request_fn_active; ++ spin_unlock_irq(q->queue_lock); ++ } ++ ++ return request_fn_active; ++} ++ ++/* Wait until ongoing shost->hostt->queuecommand() calls have finished. */ ++static void srp_wait_for_queuecommand(struct Scsi_Host *shost) ++{ ++ while (scsi_request_fn_active(shost)) ++ msleep(20); ++} ++ + static void __rport_fail_io_fast(struct srp_rport *rport) + { + struct Scsi_Host *shost = rport_to_shost(rport); +@@ -410,8 +440,10 @@ static void __rport_fail_io_fast(struct srp_rport *rport) + + /* Involve the LLD if possible to terminate all I/O on the rport. */ + i = to_srp_internal(shost->transportt); +- if (i->f->terminate_rport_io) ++ if (i->f->terminate_rport_io) { ++ srp_wait_for_queuecommand(shost); + i->f->terminate_rport_io(rport); ++ } + } + + /** +@@ -473,7 +505,8 @@ static void __srp_start_tl_fail_timers(struct srp_rport *rport) + if (delay > 0) + queue_delayed_work(system_long_wq, &rport->reconnect_work, + 1UL * delay * HZ); +- if (srp_rport_set_state(rport, SRP_RPORT_BLOCKED) == 0) { ++ if ((fast_io_fail_tmo >= 0 || dev_loss_tmo >= 0) && ++ srp_rport_set_state(rport, SRP_RPORT_BLOCKED) == 0) { + pr_debug("%s new state: %d\n", dev_name(&shost->shost_gendev), + rport->state); + scsi_target_block(&shost->shost_gendev); +@@ -504,27 +537,6 @@ void srp_start_tl_fail_timers(struct srp_rport *rport) + EXPORT_SYMBOL(srp_start_tl_fail_timers); + + /** +- * scsi_request_fn_active() - number of kernel threads inside scsi_request_fn() +- * @shost: SCSI host for which to count the number of scsi_request_fn() callers. +- */ +-static int scsi_request_fn_active(struct Scsi_Host *shost) +-{ +- struct scsi_device *sdev; +- struct request_queue *q; +- int request_fn_active = 0; +- +- shost_for_each_device(sdev, shost) { +- q = sdev->request_queue; +- +- spin_lock_irq(q->queue_lock); +- request_fn_active += q->request_fn_active; +- spin_unlock_irq(q->queue_lock); +- } +- +- return request_fn_active; +-} +- +-/** + * srp_reconnect_rport() - reconnect to an SRP target port + * @rport: SRP target port. + * +@@ -559,8 +571,7 @@ int srp_reconnect_rport(struct srp_rport *rport) + if (res) + goto out; + scsi_target_block(&shost->shost_gendev); +- while (scsi_request_fn_active(shost)) +- msleep(20); ++ srp_wait_for_queuecommand(shost); + res = rport->state != SRP_RPORT_LOST ? i->f->reconnect(rport) : -ENODEV; + pr_debug("%s (state %d): transport.reconnect() returned %d\n", + dev_name(&shost->shost_gendev), rport->state, res); +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index 36d1a23..a107064 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -1599,6 +1599,7 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) + { + u64 start_lba = blk_rq_pos(scmd->request); + u64 end_lba = blk_rq_pos(scmd->request) + (scsi_bufflen(scmd) / 512); ++ u64 factor = scmd->device->sector_size / 512; + u64 bad_lba; + int info_valid; + /* +@@ -1620,16 +1621,9 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) + if (scsi_bufflen(scmd) <= scmd->device->sector_size) + return 0; + +- if (scmd->device->sector_size < 512) { +- /* only legitimate sector_size here is 256 */ +- start_lba <<= 1; +- end_lba <<= 1; +- } else { +- /* be careful ... don't want any overflows */ +- unsigned int factor = scmd->device->sector_size / 512; +- do_div(start_lba, factor); +- do_div(end_lba, factor); +- } ++ /* be careful ... don't want any overflows */ ++ do_div(start_lba, factor); ++ do_div(end_lba, factor); + + /* The bad lba was reported incorrectly, we have no idea where + * the error is. +@@ -2196,8 +2190,7 @@ got_data: + if (sector_size != 512 && + sector_size != 1024 && + sector_size != 2048 && +- sector_size != 4096 && +- sector_size != 256) { ++ sector_size != 4096) { + sd_printk(KERN_NOTICE, sdkp, "Unsupported sector size %d.\n", + sector_size); + /* +@@ -2248,8 +2241,6 @@ got_data: + sdkp->capacity <<= 2; + else if (sector_size == 1024) + sdkp->capacity <<= 1; +- else if (sector_size == 256) +- sdkp->capacity >>= 1; + + blk_queue_physical_block_size(sdp->request_queue, + sdkp->physical_block_size); +@@ -2686,6 +2677,11 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) + + static int sd_try_extended_inquiry(struct scsi_device *sdp) + { ++ /* Attempt VPD inquiry if the device blacklist explicitly calls ++ * for it. ++ */ ++ if (sdp->try_vpd_pages) ++ return 1; + /* + * Although VPD inquiries can go to SCSI-2 type devices, + * some USB ones crash on receiving them, and the pages +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index df5e961..721d839 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -522,7 +522,7 @@ static ssize_t + sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp) + { + sg_io_hdr_t *hp = &srp->header; +- int err = 0; ++ int err = 0, err2; + int len; + + if (count < SZ_SG_IO_HDR) { +@@ -551,8 +551,8 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp) + goto err_out; + } + err_out: +- err = sg_finish_rem_req(srp); +- return (0 == err) ? count : err; ++ err2 = sg_finish_rem_req(srp); ++ return err ? : err2 ? : count; + } + + static ssize_t +@@ -1694,6 +1694,9 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) + md->from_user = 0; + } + ++ if (unlikely(iov_count > UIO_MAXIOV)) ++ return -EINVAL; ++ + if (iov_count) { + int len, size = sizeof(struct sg_iovec) * iov_count; + struct iovec *iov; +diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c +index a1d6986..f310982 100644 +--- a/drivers/scsi/st.c ++++ b/drivers/scsi/st.c +@@ -1262,9 +1262,9 @@ static int st_open(struct inode *inode, struct file *filp) + spin_lock(&st_use_lock); + STp->in_use = 0; + spin_unlock(&st_use_lock); +- scsi_tape_put(STp); + if (resumed) + scsi_autopm_put_device(STp->device); ++ scsi_tape_put(STp); + return retval; + + } +diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c +index 9969fa1..3bb6646 100644 +--- a/drivers/scsi/storvsc_drv.c ++++ b/drivers/scsi/storvsc_drv.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -330,17 +331,17 @@ static int storvsc_timeout = 180; + + static void storvsc_on_channel_callback(void *context); + +-/* +- * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In +- * reality, the path/target is not used (ie always set to 0) so our +- * scsi host adapter essentially has 1 bus with 1 target that contains +- * up to 256 luns. +- */ +-#define STORVSC_MAX_LUNS_PER_TARGET 64 +-#define STORVSC_MAX_TARGETS 1 +-#define STORVSC_MAX_CHANNELS 1 ++#define STORVSC_MAX_LUNS_PER_TARGET 255 ++#define STORVSC_MAX_TARGETS 2 ++#define STORVSC_MAX_CHANNELS 8 + ++#define STORVSC_FC_MAX_LUNS_PER_TARGET 255 ++#define STORVSC_FC_MAX_TARGETS 128 ++#define STORVSC_FC_MAX_CHANNELS 8 + ++#define STORVSC_IDE_MAX_LUNS_PER_TARGET 64 ++#define STORVSC_IDE_MAX_TARGETS 1 ++#define STORVSC_IDE_MAX_CHANNELS 1 + + struct storvsc_cmd_request { + struct list_head entry; +@@ -738,21 +739,22 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, + if (bounce_sgl[j].length == PAGE_SIZE) { + /* full..move to next entry */ + sg_kunmap_atomic(bounce_addr); ++ bounce_addr = 0; + j++; ++ } + +- /* if we need to use another bounce buffer */ +- if (srclen || i != orig_sgl_count - 1) +- bounce_addr = sg_kmap_atomic(bounce_sgl,j); ++ /* if we need to use another bounce buffer */ ++ if (srclen && bounce_addr == 0) ++ bounce_addr = sg_kmap_atomic(bounce_sgl, j); + +- } else if (srclen == 0 && i == orig_sgl_count - 1) { +- /* unmap the last bounce that is < PAGE_SIZE */ +- sg_kunmap_atomic(bounce_addr); +- } + } + + sg_kunmap_atomic(src_addr - orig_sgl[i].offset); + } + ++ if (bounce_addr) ++ sg_kunmap_atomic(bounce_addr); ++ + local_irq_restore(flags); + + return total_copied; +@@ -1017,6 +1019,13 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, + case ATA_12: + set_host_byte(scmnd, DID_PASSTHROUGH); + break; ++ /* ++ * On Some Windows hosts TEST_UNIT_READY command can return ++ * SRB_STATUS_ERROR, let the upper level code deal with it ++ * based on the sense information. ++ */ ++ case TEST_UNIT_READY: ++ break; + default: + set_host_byte(scmnd, DID_TARGET_FAILURE); + } +@@ -1518,6 +1527,16 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) + return SUCCESS; + } + ++/* ++ * The host guarantees to respond to each command, although I/O latencies might ++ * be unbounded on Azure. Reset the timer unconditionally to give the host a ++ * chance to perform EH. ++ */ ++static enum blk_eh_timer_return storvsc_eh_timed_out(struct scsi_cmnd *scmnd) ++{ ++ return BLK_EH_RESET_TIMER; ++} ++ + static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd) + { + bool allowed = true; +@@ -1553,9 +1572,19 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) + struct vmscsi_request *vm_srb; + struct stor_mem_pools *memp = scmnd->device->hostdata; + +- if (!storvsc_scsi_cmd_ok(scmnd)) { +- scmnd->scsi_done(scmnd); +- return 0; ++ if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) { ++ /* ++ * On legacy hosts filter unimplemented commands. ++ * Future hosts are expected to correctly handle ++ * unsupported commands. Furthermore, it is ++ * possible that some of the currently ++ * unsupported commands maybe supported in ++ * future versions of the host. ++ */ ++ if (!storvsc_scsi_cmd_ok(scmnd)) { ++ scmnd->scsi_done(scmnd); ++ return 0; ++ } + } + + request_size = sizeof(struct storvsc_cmd_request); +@@ -1580,26 +1609,23 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) + vm_srb = &cmd_request->vstor_packet.vm_srb; + vm_srb->win8_extension.time_out_value = 60; + ++ vm_srb->win8_extension.srb_flags |= ++ (SRB_FLAGS_QUEUE_ACTION_ENABLE | ++ SRB_FLAGS_DISABLE_SYNCH_TRANSFER); + + /* Build the SRB */ + switch (scmnd->sc_data_direction) { + case DMA_TO_DEVICE: + vm_srb->data_in = WRITE_TYPE; + vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_OUT; +- vm_srb->win8_extension.srb_flags |= +- (SRB_FLAGS_QUEUE_ACTION_ENABLE | +- SRB_FLAGS_DISABLE_SYNCH_TRANSFER); + break; + case DMA_FROM_DEVICE: + vm_srb->data_in = READ_TYPE; + vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_IN; +- vm_srb->win8_extension.srb_flags |= +- (SRB_FLAGS_QUEUE_ACTION_ENABLE | +- SRB_FLAGS_DISABLE_SYNCH_TRANSFER); + break; + default: + vm_srb->data_in = UNKNOWN_TYPE; +- vm_srb->win8_extension.srb_flags = 0; ++ vm_srb->win8_extension.srb_flags |= SRB_FLAGS_NO_DATA_TRANSFER; + break; + } + +@@ -1664,13 +1690,12 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) + if (ret == -EAGAIN) { + /* no more space */ + +- if (cmd_request->bounce_sgl_count) { ++ if (cmd_request->bounce_sgl_count) + destroy_bounce_buffer(cmd_request->bounce_sgl, + cmd_request->bounce_sgl_count); + +- ret = SCSI_MLQUEUE_DEVICE_BUSY; +- goto queue_error; +- } ++ ret = SCSI_MLQUEUE_DEVICE_BUSY; ++ goto queue_error; + } + + return 0; +@@ -1687,11 +1712,11 @@ static struct scsi_host_template scsi_driver = { + .bios_param = storvsc_get_chs, + .queuecommand = storvsc_queuecommand, + .eh_host_reset_handler = storvsc_host_reset_handler, ++ .eh_timed_out = storvsc_eh_timed_out, + .slave_alloc = storvsc_device_alloc, + .slave_destroy = storvsc_device_destroy, + .slave_configure = storvsc_device_configure, +- .cmd_per_lun = 1, +- /* 64 max_queue * 1 target */ ++ .cmd_per_lun = 255, + .can_queue = STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS, + .this_id = -1, + /* no use setting to 0 since ll_blk_rw reset it to 1 */ +@@ -1743,19 +1768,25 @@ static int storvsc_probe(struct hv_device *device, + * set state to properly communicate with the host. + */ + +- if (vmbus_proto_version == VERSION_WIN8) { +- sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; +- vmscsi_size_delta = 0; +- vmstor_current_major = VMSTOR_WIN8_MAJOR; +- vmstor_current_minor = VMSTOR_WIN8_MINOR; +- } else { ++ switch (vmbus_proto_version) { ++ case VERSION_WS2008: ++ case VERSION_WIN7: + sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; + vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); + vmstor_current_major = VMSTOR_WIN7_MAJOR; + vmstor_current_minor = VMSTOR_WIN7_MINOR; ++ break; ++ default: ++ sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; ++ vmscsi_size_delta = 0; ++ vmstor_current_major = VMSTOR_WIN8_MAJOR; ++ vmstor_current_minor = VMSTOR_WIN8_MINOR; ++ break; + } + +- ++ if (dev_id->driver_data == SFC_GUID) ++ scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS * ++ STORVSC_FC_MAX_TARGETS); + host = scsi_host_alloc(&scsi_driver, + sizeof(struct hv_host_device)); + if (!host) +@@ -1789,12 +1820,25 @@ static int storvsc_probe(struct hv_device *device, + host_dev->path = stor_device->path_id; + host_dev->target = stor_device->target_id; + +- /* max # of devices per target */ +- host->max_lun = STORVSC_MAX_LUNS_PER_TARGET; +- /* max # of targets per channel */ +- host->max_id = STORVSC_MAX_TARGETS; +- /* max # of channels */ +- host->max_channel = STORVSC_MAX_CHANNELS - 1; ++ switch (dev_id->driver_data) { ++ case SFC_GUID: ++ host->max_lun = STORVSC_FC_MAX_LUNS_PER_TARGET; ++ host->max_id = STORVSC_FC_MAX_TARGETS; ++ host->max_channel = STORVSC_FC_MAX_CHANNELS - 1; ++ break; ++ ++ case SCSI_GUID: ++ host->max_lun = STORVSC_MAX_LUNS_PER_TARGET; ++ host->max_id = STORVSC_MAX_TARGETS; ++ host->max_channel = STORVSC_MAX_CHANNELS - 1; ++ break; ++ ++ default: ++ host->max_lun = STORVSC_IDE_MAX_LUNS_PER_TARGET; ++ host->max_id = STORVSC_IDE_MAX_TARGETS; ++ host->max_channel = STORVSC_IDE_MAX_CHANNELS - 1; ++ break; ++ } + /* max cmd length */ + host->max_cmd_len = STORVSC_MAX_CMD_LEN; + +diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c +index 636bbe0..fc57c8a 100644 +--- a/drivers/scsi/sun3_NCR5380.c ++++ b/drivers/scsi/sun3_NCR5380.c +@@ -2597,15 +2597,15 @@ static void NCR5380_reselect (struct Scsi_Host *instance) + * Purpose : abort a command + * + * Inputs : cmd - the struct scsi_cmnd to abort, code - code to set the +- * host byte of the result field to, if zero DID_ABORTED is ++ * host byte of the result field to, if zero DID_ABORTED is + * used. + * +- * Returns : 0 - success, -1 on failure. ++ * Returns : SUCCESS - success, FAILED on failure. + * +- * XXX - there is no way to abort the command that is currently +- * connected, you have to wait for it to complete. If this is ++ * XXX - there is no way to abort the command that is currently ++ * connected, you have to wait for it to complete. If this is + * a problem, we could implement longjmp() / setjmp(), setjmp() +- * called where the loop started in NCR5380_main(). ++ * called where the loop started in NCR5380_main(). + */ + + static int NCR5380_abort(struct scsi_cmnd *cmd) +diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c +index 5d7b07f..5f8c6d2 100644 +--- a/drivers/spi/spi-atmel.c ++++ b/drivers/spi/spi-atmel.c +@@ -781,17 +781,17 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master, + (unsigned long long)xfer->rx_dma); + } + +- /* REVISIT: We're waiting for ENDRX before we start the next ++ /* REVISIT: We're waiting for RXBUFF before we start the next + * transfer because we need to handle some difficult timing +- * issues otherwise. If we wait for ENDTX in one transfer and +- * then starts waiting for ENDRX in the next, it's difficult +- * to tell the difference between the ENDRX interrupt we're +- * actually waiting for and the ENDRX interrupt of the ++ * issues otherwise. If we wait for TXBUFE in one transfer and ++ * then starts waiting for RXBUFF in the next, it's difficult ++ * to tell the difference between the RXBUFF interrupt we're ++ * actually waiting for and the RXBUFF interrupt of the + * previous transfer. + * + * It should be doable, though. Just not now... + */ +- spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES)); ++ spi_writel(as, IER, SPI_BIT(RXBUFF) | SPI_BIT(OVRES)); + spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN)); + } + +diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c +index 6d207af..996e16d 100644 +--- a/drivers/spi/spi-dw-mid.c ++++ b/drivers/spi/spi-dw-mid.c +@@ -89,7 +89,13 @@ err_exit: + + static void mid_spi_dma_exit(struct dw_spi *dws) + { ++ if (!dws->dma_inited) ++ return; ++ ++ dmaengine_terminate_all(dws->txchan); + dma_release_channel(dws->txchan); ++ ++ dmaengine_terminate_all(dws->rxchan); + dma_release_channel(dws->rxchan); + } + +@@ -136,7 +142,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) + txconf.dst_addr = dws->dma_addr; + txconf.dst_maxburst = LNW_DMA_MSIZE_16; + txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +- txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; ++ txconf.dst_addr_width = dws->dma_width; + txconf.device_fc = false; + + txchan->device->device_control(txchan, DMA_SLAVE_CONFIG, +@@ -159,7 +165,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change) + rxconf.src_addr = dws->dma_addr; + rxconf.src_maxburst = LNW_DMA_MSIZE_16; + rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; +- rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; ++ rxconf.src_addr_width = dws->dma_width; + rxconf.device_fc = false; + + rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG, +@@ -216,7 +222,6 @@ int dw_spi_mid_init(struct dw_spi *dws) + iounmap(clk_reg); + + dws->num_cs = 16; +- dws->fifo_len = 40; /* FIFO has 40 words buffer */ + + #ifdef CONFIG_SPI_DW_MID_DMA + dws->dma_priv = kzalloc(sizeof(struct mid_dma), GFP_KERNEL); +diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c +index 3f3dc12..e149604 100644 +--- a/drivers/spi/spi-dw-pci.c ++++ b/drivers/spi/spi-dw-pci.c +@@ -62,6 +62,8 @@ static int spi_pci_probe(struct pci_dev *pdev, + if (ret) + return ret; + ++ dws->regs = pcim_iomap_table(pdev)[pci_bar]; ++ + dws->bus_num = 0; + dws->num_cs = 4; + dws->irq = pdev->irq; +diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c +index e63d270..e543b80 100644 +--- a/drivers/spi/spi-dw.c ++++ b/drivers/spi/spi-dw.c +@@ -394,9 +394,6 @@ static void pump_transfers(unsigned long data) + chip = dws->cur_chip; + spi = message->spi; + +- if (unlikely(!chip->clk_div)) +- chip->clk_div = dws->max_freq / chip->speed_hz; +- + if (message->state == ERROR_STATE) { + message->status = -EIO; + goto early_exit; +@@ -437,7 +434,7 @@ static void pump_transfers(unsigned long data) + if (transfer->speed_hz) { + speed = chip->speed_hz; + +- if (transfer->speed_hz != speed) { ++ if ((transfer->speed_hz != speed) || (!chip->clk_div)) { + speed = transfer->speed_hz; + if (speed > dws->max_freq) { + printk(KERN_ERR "MRST SPI0: unsupported" +@@ -659,7 +656,6 @@ static int dw_spi_setup(struct spi_device *spi) + dev_err(&spi->dev, "No max speed HZ parameter\n"); + return -EINVAL; + } +- chip->speed_hz = spi->max_speed_hz; + + chip->tmode = 0; /* Tx & Rx */ + /* Default SPI mode is SCPOL = 0, SCPH = 0 */ +diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c +index a253920..a5db6f9 100644 +--- a/drivers/spi/spi-fsl-dspi.c ++++ b/drivers/spi/spi-fsl-dspi.c +@@ -45,7 +45,7 @@ + + #define SPI_TCR 0x08 + +-#define SPI_CTAR(x) (0x0c + (x * 4)) ++#define SPI_CTAR(x) (0x0c + (((x) & 0x3) * 4)) + #define SPI_CTAR_FMSZ(x) (((x) & 0x0000000f) << 27) + #define SPI_CTAR_CPOL(x) ((x) << 26) + #define SPI_CTAR_CPHA(x) ((x) << 25) +@@ -69,7 +69,7 @@ + + #define SPI_PUSHR 0x34 + #define SPI_PUSHR_CONT (1 << 31) +-#define SPI_PUSHR_CTAS(x) (((x) & 0x00000007) << 28) ++#define SPI_PUSHR_CTAS(x) (((x) & 0x00000003) << 28) + #define SPI_PUSHR_EOQ (1 << 27) + #define SPI_PUSHR_CTCNT (1 << 26) + #define SPI_PUSHR_PCS(x) (((1 << x) & 0x0000003f) << 16) +diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c +index 119f7af..4dcb292 100644 +--- a/drivers/spi/spi-fsl-spi.c ++++ b/drivers/spi/spi-fsl-spi.c +@@ -362,18 +362,28 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t, + static void fsl_spi_do_one_msg(struct spi_message *m) + { + struct spi_device *spi = m->spi; +- struct spi_transfer *t; ++ struct spi_transfer *t, *first; + unsigned int cs_change; + const int nsecs = 50; + int status; + +- cs_change = 1; +- status = 0; ++ /* Don't allow changes if CS is active */ ++ first = list_first_entry(&m->transfers, struct spi_transfer, ++ transfer_list); + list_for_each_entry(t, &m->transfers, transfer_list) { +- if (t->bits_per_word || t->speed_hz) { +- /* Don't allow changes if CS is active */ ++ if ((first->bits_per_word != t->bits_per_word) || ++ (first->speed_hz != t->speed_hz)) { + status = -EINVAL; ++ dev_err(&spi->dev, ++ "bits_per_word/speed_hz should be same for the same SPI transfer\n"); ++ return; ++ } ++ } + ++ cs_change = 1; ++ status = -EINVAL; ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ if (t->bits_per_word || t->speed_hz) { + if (cs_change) + status = fsl_spi_setup_transfer(spi, t); + if (status < 0) +diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c +index a72127f..b0059e7 100644 +--- a/drivers/spi/spi-omap2-mcspi.c ++++ b/drivers/spi/spi-omap2-mcspi.c +@@ -147,6 +147,7 @@ struct omap2_mcspi_cs { + void __iomem *base; + unsigned long phys; + int word_len; ++ u16 mode; + struct list_head node; + /* Context save and restore shadow register */ + u32 chconf0; +@@ -320,7 +321,8 @@ static void omap2_mcspi_set_fifo(const struct spi_device *spi, + disable_fifo: + if (t->rx_buf != NULL) + chconf &= ~OMAP2_MCSPI_CHCONF_FFER; +- else ++ ++ if (t->tx_buf != NULL) + chconf &= ~OMAP2_MCSPI_CHCONF_FFET; + + mcspi_write_chconf0(spi, chconf); +@@ -899,6 +901,8 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, + + mcspi_write_chconf0(spi, l); + ++ cs->mode = spi->mode; ++ + dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", + OMAP2_MCSPI_MAX_FREQ >> div, + (spi->mode & SPI_CPHA) ? "trailing" : "leading", +@@ -971,6 +975,7 @@ static int omap2_mcspi_setup(struct spi_device *spi) + return -ENOMEM; + cs->base = mcspi->base + spi->chip_select * 0x14; + cs->phys = mcspi->phys + spi->chip_select * 0x14; ++ cs->mode = 0; + cs->chconf0 = 0; + spi->controller_state = cs; + /* Link this to context save list */ +@@ -1051,6 +1056,16 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m) + cs = spi->controller_state; + cd = spi->controller_data; + ++ /* ++ * The slave driver could have changed spi->mode in which case ++ * it will be different from cs->mode (the current hardware setup). ++ * If so, set par_override (even though its not a parity issue) so ++ * omap2_mcspi_setup_transfer will be called to configure the hardware ++ * with the correct mode on the first iteration of the loop below. ++ */ ++ if (spi->mode != cs->mode) ++ par_override = 1; ++ + omap2_mcspi_set_enable(spi, 0); + list_for_each_entry(t, &m->transfers, transfer_list) { + if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { +diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c +index 7f2121f..977b061 100644 +--- a/drivers/spi/spi-orion.c ++++ b/drivers/spi/spi-orion.c +@@ -404,8 +404,6 @@ static int orion_spi_probe(struct platform_device *pdev) + struct resource *r; + unsigned long tclk_hz; + int status = 0; +- const u32 *iprop; +- int size; + + master = spi_alloc_master(&pdev->dev, sizeof(*spi)); + if (master == NULL) { +@@ -416,10 +414,10 @@ static int orion_spi_probe(struct platform_device *pdev) + if (pdev->id != -1) + master->bus_num = pdev->id; + if (pdev->dev.of_node) { +- iprop = of_get_property(pdev->dev.of_node, "cell-index", +- &size); +- if (iprop && size == sizeof(*iprop)) +- master->bus_num = *iprop; ++ u32 cell_index; ++ if (!of_property_read_u32(pdev->dev.of_node, "cell-index", ++ &cell_index)) ++ master->bus_num = cell_index; + } + + /* we support only mode 0, and no options */ +diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c +index 2789b45..fe091a8 100644 +--- a/drivers/spi/spi-pl022.c ++++ b/drivers/spi/spi-pl022.c +@@ -503,12 +503,12 @@ static void giveback(struct pl022 *pl022) + pl022->cur_msg = NULL; + pl022->cur_transfer = NULL; + pl022->cur_chip = NULL; +- spi_finalize_current_message(pl022->master); + + /* disable the SPI/SSP operation */ + writew((readw(SSP_CR1(pl022->virtbase)) & + (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); + ++ spi_finalize_current_message(pl022->master); + } + + /** +@@ -1075,7 +1075,7 @@ err_rxdesc: + pl022->sgt_tx.nents, DMA_TO_DEVICE); + err_tx_sgmap: + dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl, +- pl022->sgt_tx.nents, DMA_FROM_DEVICE); ++ pl022->sgt_rx.nents, DMA_FROM_DEVICE); + err_rx_sgmap: + sg_free_table(&pl022->sgt_tx); + err_alloc_tx_sg: +diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c +index c702fc5..458a148 100644 +--- a/drivers/spi/spi-pxa2xx.c ++++ b/drivers/spi/spi-pxa2xx.c +@@ -400,8 +400,8 @@ static void giveback(struct driver_data *drv_data) + cs_deassert(drv_data); + } + +- spi_finalize_current_message(drv_data->master); + drv_data->cur_chip = NULL; ++ spi_finalize_current_message(drv_data->master); + } + + static void reset_sccr1(struct driver_data *drv_data) +@@ -1078,6 +1078,7 @@ static struct acpi_device_id pxa2xx_spi_acpi_match[] = { + { "INT3430", 0 }, + { "INT3431", 0 }, + { "80860F0E", 0 }, ++ { "8086228E", 0 }, + { }, + }; + MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match); +@@ -1279,7 +1280,9 @@ static int pxa2xx_spi_suspend(struct device *dev) + if (status != 0) + return status; + write_SSCR0(0, drv_data->ioaddr); +- clk_disable_unprepare(ssp->clk); ++ ++ if (!pm_runtime_suspended(dev)) ++ clk_disable_unprepare(ssp->clk); + + return 0; + } +@@ -1293,7 +1296,8 @@ static int pxa2xx_spi_resume(struct device *dev) + pxa2xx_spi_dma_resume(drv_data); + + /* Enable the SSP clock */ +- clk_prepare_enable(ssp->clk); ++ if (!pm_runtime_suspended(dev)) ++ clk_prepare_enable(ssp->clk); + + /* Restore LPSS private register bits */ + lpss_ssp_setup(drv_data); +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index fbf3b22..f3e3ae8 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -834,9 +834,6 @@ void spi_finalize_current_message(struct spi_master *master) + + spin_lock_irqsave(&master->queue_lock, flags); + mesg = master->cur_msg; +- master->cur_msg = NULL; +- +- queue_kthread_work(&master->kworker, &master->pump_messages); + spin_unlock_irqrestore(&master->queue_lock, flags); + + if (master->cur_msg_prepared && master->unprepare_message) { +@@ -846,13 +843,18 @@ void spi_finalize_current_message(struct spi_master *master) + "failed to unprepare message: %d\n", ret); + } + } ++ ++ spin_lock_irqsave(&master->queue_lock, flags); ++ master->cur_msg = NULL; + master->cur_msg_prepared = false; ++ queue_kthread_work(&master->kworker, &master->pump_messages); ++ spin_unlock_irqrestore(&master->queue_lock, flags); ++ ++ trace_spi_message_done(mesg); + + mesg->state = NULL; + if (mesg->complete) + mesg->complete(mesg->context); +- +- trace_spi_message_done(mesg); + } + EXPORT_SYMBOL_GPL(spi_finalize_current_message); + +diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c +index d7c6e36..2fe5b61 100644 +--- a/drivers/spi/spidev.c ++++ b/drivers/spi/spidev.c +@@ -243,7 +243,10 @@ static int spidev_message(struct spidev_data *spidev, + k_tmp->len = u_tmp->len; + + total += k_tmp->len; +- if (total > bufsiz) { ++ /* Check total length of transfers. Also check each ++ * transfer length to avoid arithmetic overflow. ++ */ ++ if (total > bufsiz || k_tmp->len > bufsiz) { + status = -EMSGSIZE; + goto done; + } +diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c +index 1e9da40..5287810 100644 +--- a/drivers/staging/comedi/comedi_compat32.c ++++ b/drivers/staging/comedi/comedi_compat32.c +@@ -262,7 +262,7 @@ static int compat_cmd(struct file *file, unsigned long arg) + { + struct comedi_cmd __user *cmd; + struct comedi32_cmd_struct __user *cmd32; +- int rc; ++ int rc, err; + + cmd32 = compat_ptr(arg); + cmd = compat_alloc_user_space(sizeof(*cmd)); +@@ -271,7 +271,15 @@ static int compat_cmd(struct file *file, unsigned long arg) + if (rc) + return rc; + +- return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd); ++ rc = translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd); ++ if (rc == -EAGAIN) { ++ /* Special case: copy cmd back to user. */ ++ err = put_compat_cmd(cmd32, cmd); ++ if (err) ++ rc = err; ++ } ++ ++ return rc; + } + + /* Handle 32-bit COMEDI_CMDTEST ioctl. */ +diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c +index 6f622b4..927edd1 100644 +--- a/drivers/staging/comedi/drivers/adl_pci7x3x.c ++++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c +@@ -113,8 +113,20 @@ static int adl_pci7x3x_do_insn_bits(struct comedi_device *dev, + { + unsigned long reg = (unsigned long)s->private; + +- if (comedi_dio_update_state(s, data)) +- outl(s->state, dev->iobase + reg); ++ if (comedi_dio_update_state(s, data)) { ++ unsigned int val = s->state; ++ ++ if (s->n_chan == 16) { ++ /* ++ * It seems the PCI-7230 needs the 16-bit DO state ++ * to be shifted left by 16 bits before being written ++ * to the 32-bit register. Set the value in both ++ * halves of the register to be sure. ++ */ ++ val |= val << 16; ++ } ++ outl(val, dev->iobase + reg); ++ } + + data[1] = s->state; + +diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c +index 4fff173..3d1cb5b 100644 +--- a/drivers/staging/comedi/drivers/cb_pcidas64.c ++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c +@@ -441,6 +441,29 @@ static const struct comedi_lrange ai_ranges_64xx = { + } + }; + ++static const uint8_t ai_range_code_64xx[8] = { ++ 0x0, 0x1, 0x2, 0x3, /* bipolar 10, 5, 2,5, 1.25 */ ++ 0x8, 0x9, 0xa, 0xb /* unipolar 10, 5, 2.5, 1.25 */ ++}; ++ ++/* analog input ranges for 64-Mx boards */ ++static const struct comedi_lrange ai_ranges_64_mx = { ++ 7, { ++ BIP_RANGE(5), ++ BIP_RANGE(2.5), ++ BIP_RANGE(1.25), ++ BIP_RANGE(0.625), ++ UNI_RANGE(5), ++ UNI_RANGE(2.5), ++ UNI_RANGE(1.25) ++ } ++}; ++ ++static const uint8_t ai_range_code_64_mx[7] = { ++ 0x0, 0x1, 0x2, 0x3, /* bipolar 5, 2.5, 1.25, 0.625 */ ++ 0x9, 0xa, 0xb /* unipolar 5, 2.5, 1.25 */ ++}; ++ + /* analog input ranges for 60xx boards */ + static const struct comedi_lrange ai_ranges_60xx = { + 4, { +@@ -451,6 +474,10 @@ static const struct comedi_lrange ai_ranges_60xx = { + } + }; + ++static const uint8_t ai_range_code_60xx[4] = { ++ 0x0, 0x1, 0x4, 0x7 /* bipolar 10, 5, 0.5, 0.05 */ ++}; ++ + /* analog input ranges for 6030, etc boards */ + static const struct comedi_lrange ai_ranges_6030 = { + 14, { +@@ -471,6 +498,11 @@ static const struct comedi_lrange ai_ranges_6030 = { + } + }; + ++static const uint8_t ai_range_code_6030[14] = { ++ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, /* bip 10, 5, 2, 1, 0.5, 0.2, 0.1 */ ++ 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* uni 10, 5, 2, 1, 0.5, 0.2, 0.1 */ ++}; ++ + /* analog input ranges for 6052, etc boards */ + static const struct comedi_lrange ai_ranges_6052 = { + 15, { +@@ -492,6 +524,11 @@ static const struct comedi_lrange ai_ranges_6052 = { + } + }; + ++static const uint8_t ai_range_code_6052[15] = { ++ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, /* bipolar 10 ... 0.05 */ ++ 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* unipolar 10 ... 0.1 */ ++}; ++ + /* analog input ranges for 4020 board */ + static const struct comedi_lrange ai_ranges_4020 = { + 2, { +@@ -595,6 +632,7 @@ struct pcidas64_board { + int ai_bits; /* analog input resolution */ + int ai_speed; /* fastest conversion period in ns */ + const struct comedi_lrange *ai_range_table; ++ const uint8_t *ai_range_code; + int ao_nchan; /* number of analog out channels */ + int ao_bits; /* analog output resolution */ + int ao_scan_speed; /* analog output scan speed */ +@@ -653,6 +691,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, ++ .ai_range_code = ai_range_code_64xx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, +@@ -668,6 +707,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, ++ .ai_range_code = ai_range_code_64xx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, +@@ -682,7 +722,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_bits = 16, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, +@@ -697,7 +738,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_bits = 16, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, +@@ -712,7 +754,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_bits = 16, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, +@@ -727,6 +770,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_bits = 16, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -742,6 +786,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -756,6 +801,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -771,6 +817,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -786,6 +833,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 10000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, ++ .ai_range_code = ai_range_code_6030, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -801,6 +849,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 10000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, ++ .ai_range_code = ai_range_code_6030, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -814,6 +863,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 0, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, ++ .ai_range_code = ai_range_code_6030, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, +@@ -825,6 +875,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 0, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, ++ .ai_range_code = ai_range_code_6030, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, +@@ -837,6 +888,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 0, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, +@@ -850,6 +902,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -865,6 +918,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -880,6 +934,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 1000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, ++ .ai_range_code = ai_range_code_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -895,6 +950,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 3333, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, ++ .ai_range_code = ai_range_code_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -910,6 +966,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 1000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, ++ .ai_range_code = ai_range_code_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -925,6 +982,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 1000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, ++ .ai_range_code = ai_range_code_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -959,6 +1017,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, ++ .ai_range_code = ai_range_code_64xx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -970,7 +1029,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 0, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -982,7 +1042,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 0, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -994,7 +1055,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 0, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -1006,7 +1068,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 2, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -1018,7 +1081,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 2, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -1030,7 +1094,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 2, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -1127,45 +1192,8 @@ static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev, + unsigned int range_index) + { + const struct pcidas64_board *thisboard = comedi_board(dev); +- const struct comedi_krange *range = +- &thisboard->ai_range_table->range[range_index]; +- unsigned int bits = 0; + +- switch (range->max) { +- case 10000000: +- bits = 0x000; +- break; +- case 5000000: +- bits = 0x100; +- break; +- case 2000000: +- case 2500000: +- bits = 0x200; +- break; +- case 1000000: +- case 1250000: +- bits = 0x300; +- break; +- case 500000: +- bits = 0x400; +- break; +- case 200000: +- case 250000: +- bits = 0x500; +- break; +- case 100000: +- bits = 0x600; +- break; +- case 50000: +- bits = 0x700; +- break; +- default: +- comedi_error(dev, "bug! in ai_range_bits_6xxx"); +- break; +- } +- if (range->min == 0) +- bits += 0x900; +- return bits; ++ return thisboard->ai_range_code[range_index] << 8; + } + + static unsigned int hw_revision(const struct comedi_device *dev, +diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c +index e516bb6..907aa30 100644 +--- a/drivers/staging/et131x/et131x.c ++++ b/drivers/staging/et131x/et131x.c +@@ -1422,22 +1422,16 @@ static int et131x_mii_read(struct et131x_adapter *adapter, u8 reg, u16 *value) + * @reg: the register to read + * @value: 16-bit value to write + */ +-static int et131x_mii_write(struct et131x_adapter *adapter, u8 reg, u16 value) ++static int et131x_mii_write(struct et131x_adapter *adapter, u8 addr, u8 reg, ++ u16 value) + { + struct mac_regs __iomem *mac = &adapter->regs->mac; +- struct phy_device *phydev = adapter->phydev; + int status = 0; +- u8 addr; + u32 delay = 0; + u32 mii_addr; + u32 mii_cmd; + u32 mii_indicator; + +- if (!phydev) +- return -EIO; +- +- addr = phydev->addr; +- + /* Save a local copy of the registers we are dealing with so we can + * set them back + */ +@@ -1632,17 +1626,7 @@ static int et131x_mdio_write(struct mii_bus *bus, int phy_addr, + struct net_device *netdev = bus->priv; + struct et131x_adapter *adapter = netdev_priv(netdev); + +- return et131x_mii_write(adapter, reg, value); +-} +- +-static int et131x_mdio_reset(struct mii_bus *bus) +-{ +- struct net_device *netdev = bus->priv; +- struct et131x_adapter *adapter = netdev_priv(netdev); +- +- et131x_mii_write(adapter, MII_BMCR, BMCR_RESET); +- +- return 0; ++ return et131x_mii_write(adapter, phy_addr, reg, value); + } + + /* et1310_phy_power_switch - PHY power control +@@ -1657,18 +1641,20 @@ static int et131x_mdio_reset(struct mii_bus *bus) + static void et1310_phy_power_switch(struct et131x_adapter *adapter, bool down) + { + u16 data; ++ struct phy_device *phydev = adapter->phydev; + + et131x_mii_read(adapter, MII_BMCR, &data); + data &= ~BMCR_PDOWN; + if (down) + data |= BMCR_PDOWN; +- et131x_mii_write(adapter, MII_BMCR, data); ++ et131x_mii_write(adapter, phydev->addr, MII_BMCR, data); + } + + /* et131x_xcvr_init - Init the phy if we are setting it into force mode */ + static void et131x_xcvr_init(struct et131x_adapter *adapter) + { + u16 lcr2; ++ struct phy_device *phydev = adapter->phydev; + + /* Set the LED behavior such that LED 1 indicates speed (off = + * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates +@@ -1689,7 +1675,7 @@ static void et131x_xcvr_init(struct et131x_adapter *adapter) + else + lcr2 |= (LED_VAL_LINKON << LED_TXRX_SHIFT); + +- et131x_mii_write(adapter, PHY_LED_2, lcr2); ++ et131x_mii_write(adapter, phydev->addr, PHY_LED_2, lcr2); + } + } + +@@ -3638,14 +3624,14 @@ static void et131x_adjust_link(struct net_device *netdev) + + et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG, + ®ister18); +- et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, +- register18 | 0x4); +- et131x_mii_write(adapter, PHY_INDEX_REG, ++ et131x_mii_write(adapter, phydev->addr, ++ PHY_MPHY_CONTROL_REG, register18 | 0x4); ++ et131x_mii_write(adapter, phydev->addr, PHY_INDEX_REG, + register18 | 0x8402); +- et131x_mii_write(adapter, PHY_DATA_REG, ++ et131x_mii_write(adapter, phydev->addr, PHY_DATA_REG, + register18 | 511); +- et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, +- register18); ++ et131x_mii_write(adapter, phydev->addr, ++ PHY_MPHY_CONTROL_REG, register18); + } + + et1310_config_flow_control(adapter); +@@ -3657,7 +3643,8 @@ static void et131x_adjust_link(struct net_device *netdev) + et131x_mii_read(adapter, PHY_CONFIG, ®); + reg &= ~ET_PHY_CONFIG_TX_FIFO_DEPTH; + reg |= ET_PHY_CONFIG_FIFO_DEPTH_32; +- et131x_mii_write(adapter, PHY_CONFIG, reg); ++ et131x_mii_write(adapter, phydev->addr, PHY_CONFIG, ++ reg); + } + + et131x_set_rx_dma_timer(adapter); +@@ -3670,14 +3657,14 @@ static void et131x_adjust_link(struct net_device *netdev) + + et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG, + ®ister18); +- et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, +- register18 | 0x4); +- et131x_mii_write(adapter, PHY_INDEX_REG, +- register18 | 0x8402); +- et131x_mii_write(adapter, PHY_DATA_REG, +- register18 | 511); +- et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG, +- register18); ++ et131x_mii_write(adapter, phydev->addr, ++ PHY_MPHY_CONTROL_REG, register18 | 0x4); ++ et131x_mii_write(adapter, phydev->addr, ++ PHY_INDEX_REG, register18 | 0x8402); ++ et131x_mii_write(adapter, phydev->addr, ++ PHY_DATA_REG, register18 | 511); ++ et131x_mii_write(adapter, phydev->addr, ++ PHY_MPHY_CONTROL_REG, register18); + } + + /* Free the packets being actively sent & stopped */ +@@ -4646,10 +4633,6 @@ static int et131x_pci_setup(struct pci_dev *pdev, + /* Copy address into the net_device struct */ + memcpy(netdev->dev_addr, adapter->addr, ETH_ALEN); + +- /* Init variable for counting how long we do not have link status */ +- adapter->boot_coma = 0; +- et1310_disable_phy_coma(adapter); +- + rc = -ENOMEM; + + /* Setup the mii_bus struct */ +@@ -4665,7 +4648,6 @@ static int et131x_pci_setup(struct pci_dev *pdev, + adapter->mii_bus->priv = netdev; + adapter->mii_bus->read = et131x_mdio_read; + adapter->mii_bus->write = et131x_mdio_write; +- adapter->mii_bus->reset = et131x_mdio_reset; + adapter->mii_bus->irq = kmalloc_array(PHY_MAX_ADDR, sizeof(int), + GFP_KERNEL); + if (!adapter->mii_bus->irq) +@@ -4689,6 +4671,10 @@ static int et131x_pci_setup(struct pci_dev *pdev, + /* Setup et1310 as per the documentation */ + et131x_adapter_setup(adapter); + ++ /* Init variable for counting how long we do not have link status */ ++ adapter->boot_coma = 0; ++ et1310_disable_phy_coma(adapter); ++ + /* We can enable interrupts now + * + * NOTE - Because registration of interrupt handler is done in the +diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c +index 2fa3a5a..f2e6599 100644 +--- a/drivers/staging/gdm724x/gdm_mux.c ++++ b/drivers/staging/gdm724x/gdm_mux.c +@@ -158,7 +158,7 @@ static int up_to_host(struct mux_rx *r) + unsigned int start_flag; + unsigned int payload_size; + unsigned short packet_type; +- int dummy_cnt; ++ int total_len; + u32 packet_size_sum = r->offset; + int index; + int ret = TO_HOST_INVALID_PACKET; +@@ -175,10 +175,10 @@ static int up_to_host(struct mux_rx *r) + break; + } + +- dummy_cnt = ALIGN(MUX_HEADER_SIZE + payload_size, 4); ++ total_len = ALIGN(MUX_HEADER_SIZE + payload_size, 4); + + if (len - packet_size_sum < +- MUX_HEADER_SIZE + payload_size + dummy_cnt) { ++ total_len) { + pr_err("invalid payload : %d %d %04x\n", + payload_size, len, packet_type); + break; +@@ -201,7 +201,7 @@ static int up_to_host(struct mux_rx *r) + break; + } + +- packet_size_sum += MUX_HEADER_SIZE + payload_size + dummy_cnt; ++ packet_size_sum += total_len; + if (len - packet_size_sum <= MUX_HEADER_SIZE + 2) { + ret = r->callback(NULL, + 0, +@@ -359,7 +359,6 @@ static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index, + struct mux_pkt_header *mux_header; + struct mux_tx *t = NULL; + static u32 seq_num = 1; +- int dummy_cnt; + int total_len; + int ret; + unsigned long flags; +@@ -372,9 +371,7 @@ static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index, + + spin_lock_irqsave(&mux_dev->write_lock, flags); + +- dummy_cnt = ALIGN(MUX_HEADER_SIZE + len, 4); +- +- total_len = len + MUX_HEADER_SIZE + dummy_cnt; ++ total_len = ALIGN(MUX_HEADER_SIZE + len, 4); + + t = alloc_mux_tx(total_len); + if (!t) { +@@ -390,7 +387,8 @@ static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index, + mux_header->packet_type = __cpu_to_le16(packet_type[tty_index]); + + memcpy(t->buf+MUX_HEADER_SIZE, data, len); +- memset(t->buf+MUX_HEADER_SIZE+len, 0, dummy_cnt); ++ memset(t->buf+MUX_HEADER_SIZE+len, 0, total_len - MUX_HEADER_SIZE - ++ len); + + t->len = total_len; + t->callback = cb; +diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c +index 9ec1df9..27e1a6e 100644 +--- a/drivers/staging/iio/adc/mxs-lradc.c ++++ b/drivers/staging/iio/adc/mxs-lradc.c +@@ -214,11 +214,17 @@ struct mxs_lradc { + unsigned long is_divided; + + /* +- * Touchscreen LRADC channels receives a private slot in the CTRL4 +- * register, the slot #7. Therefore only 7 slots instead of 8 in the +- * CTRL4 register can be mapped to LRADC channels when using the +- * touchscreen. +- * ++ * When the touchscreen is enabled, we give it two private virtual ++ * channels: #6 and #7. This means that only 6 virtual channels (instead ++ * of 8) will be available for buffered capture. ++ */ ++#define TOUCHSCREEN_VCHANNEL1 7 ++#define TOUCHSCREEN_VCHANNEL2 6 ++#define BUFFER_VCHANS_LIMITED 0x3f ++#define BUFFER_VCHANS_ALL 0xff ++ u8 buffer_vchans; ++ ++ /* + * Furthermore, certain LRADC channels are shared between touchscreen + * and/or touch-buttons and generic LRADC block. Therefore when using + * either of these, these channels are not available for the regular +@@ -342,6 +348,9 @@ struct mxs_lradc { + #define LRADC_CTRL4 0x140 + #define LRADC_CTRL4_LRADCSELECT_MASK(n) (0xf << ((n) * 4)) + #define LRADC_CTRL4_LRADCSELECT_OFFSET(n) ((n) * 4) ++#define LRADC_CTRL4_LRADCSELECT(n, x) \ ++ (((x) << LRADC_CTRL4_LRADCSELECT_OFFSET(n)) & \ ++ LRADC_CTRL4_LRADCSELECT_MASK(n)) + + #define LRADC_RESOLUTION 12 + #define LRADC_SINGLE_SAMPLE_MASK ((1 << LRADC_RESOLUTION) - 1) +@@ -423,6 +432,14 @@ static bool mxs_lradc_check_touch_event(struct mxs_lradc *lradc) + LRADC_STATUS_TOUCH_DETECT_RAW); + } + ++static void mxs_lradc_map_channel(struct mxs_lradc *lradc, unsigned vch, ++ unsigned ch) ++{ ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(vch), ++ LRADC_CTRL4); ++ mxs_lradc_reg_set(lradc, LRADC_CTRL4_LRADCSELECT(vch, ch), LRADC_CTRL4); ++} ++ + static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) + { + /* +@@ -450,12 +467,8 @@ static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) + LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), + LRADC_DELAY(3)); + +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) | +- LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) | +- LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch), LRADC_CTRL1); + +- /* wake us again, when the complete conversion is done */ +- mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1); + /* + * after changing the touchscreen plates setting + * the signals need some initial time to settle. Start the +@@ -508,12 +521,8 @@ static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1, + LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), + LRADC_DELAY(3)); + +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) | +- LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) | +- LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch2), LRADC_CTRL1); + +- /* wake us again, when the conversions are done */ +- mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1); + /* + * after changing the touchscreen plates setting + * the signals need some initial time to settle. Start the +@@ -578,36 +587,6 @@ static unsigned mxs_lradc_read_ts_pressure(struct mxs_lradc *lradc, + #define TS_CH_XM 4 + #define TS_CH_YM 5 + +-static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc) +-{ +- u32 reg; +- int val; +- +- reg = readl(lradc->base + LRADC_CTRL1); +- +- /* only channels 3 to 5 are of interest here */ +- if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YP)) { +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YP) | +- LRADC_CTRL1_LRADC_IRQ(TS_CH_YP), LRADC_CTRL1); +- val = mxs_lradc_read_raw_channel(lradc, TS_CH_YP); +- } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_XM)) { +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_XM) | +- LRADC_CTRL1_LRADC_IRQ(TS_CH_XM), LRADC_CTRL1); +- val = mxs_lradc_read_raw_channel(lradc, TS_CH_XM); +- } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YM)) { +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YM) | +- LRADC_CTRL1_LRADC_IRQ(TS_CH_YM), LRADC_CTRL1); +- val = mxs_lradc_read_raw_channel(lradc, TS_CH_YM); +- } else { +- return -EIO; +- } +- +- mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); +- mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); +- +- return val; +-} +- + /* + * YP(open)--+-------------+ + * | |--+ +@@ -651,7 +630,8 @@ static void mxs_lradc_prepare_x_pos(struct mxs_lradc *lradc) + mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0); + + lradc->cur_plate = LRADC_SAMPLE_X; +- mxs_lradc_setup_ts_channel(lradc, TS_CH_YP); ++ mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YP); ++ mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1); + } + + /* +@@ -672,7 +652,8 @@ static void mxs_lradc_prepare_y_pos(struct mxs_lradc *lradc) + mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0); + + lradc->cur_plate = LRADC_SAMPLE_Y; +- mxs_lradc_setup_ts_channel(lradc, TS_CH_XM); ++ mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_XM); ++ mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1); + } + + /* +@@ -693,7 +674,10 @@ static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc) + mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0); + + lradc->cur_plate = LRADC_SAMPLE_PRESSURE; +- mxs_lradc_setup_ts_pressure(lradc, TS_CH_XP, TS_CH_YM); ++ mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YM); ++ mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL2, TS_CH_XP); ++ mxs_lradc_setup_ts_pressure(lradc, TOUCHSCREEN_VCHANNEL2, ++ TOUCHSCREEN_VCHANNEL1); + } + + static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) +@@ -706,6 +690,19 @@ static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) + mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); + } + ++static void mxs_lradc_start_touch_event(struct mxs_lradc *lradc) ++{ ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, ++ LRADC_CTRL1); ++ mxs_lradc_reg_set(lradc, ++ LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1); ++ /* ++ * start with the Y-pos, because it uses nearly the same plate ++ * settings like the touch detection ++ */ ++ mxs_lradc_prepare_y_pos(lradc); ++} ++ + static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc) + { + input_report_abs(lradc->ts_input, ABS_X, lradc->ts_x_pos); +@@ -723,10 +720,12 @@ static void mxs_lradc_complete_touch_event(struct mxs_lradc *lradc) + * start a dummy conversion to burn time to settle the signals + * note: we are not interested in the conversion's value + */ +- mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(5)); +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); +- mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(5), LRADC_CTRL1); +- mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << 5) | ++ mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(TOUCHSCREEN_VCHANNEL1)); ++ mxs_lradc_reg_clear(lradc, ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) | ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1); ++ mxs_lradc_reg_wrt(lradc, ++ LRADC_DELAY_TRIGGER(1 << TOUCHSCREEN_VCHANNEL1) | + LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10), /* waste 5 ms */ + LRADC_DELAY(2)); + } +@@ -758,59 +757,45 @@ static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid) + + /* if it is released, wait for the next touch via IRQ */ + lradc->cur_plate = LRADC_TOUCH; +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1); ++ mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); ++ mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ | ++ LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) | ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1); + mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); + } + + /* touchscreen's state machine */ + static void mxs_lradc_handle_touch(struct mxs_lradc *lradc) + { +- int val; +- + switch (lradc->cur_plate) { + case LRADC_TOUCH: +- /* +- * start with the Y-pos, because it uses nearly the same plate +- * settings like the touch detection +- */ +- if (mxs_lradc_check_touch_event(lradc)) { +- mxs_lradc_reg_clear(lradc, +- LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, +- LRADC_CTRL1); +- mxs_lradc_prepare_y_pos(lradc); +- } ++ if (mxs_lradc_check_touch_event(lradc)) ++ mxs_lradc_start_touch_event(lradc); + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, + LRADC_CTRL1); + return; + + case LRADC_SAMPLE_Y: +- val = mxs_lradc_read_ts_channel(lradc); +- if (val < 0) { +- mxs_lradc_enable_touch_detection(lradc); /* re-start */ +- return; +- } +- lradc->ts_y_pos = val; ++ lradc->ts_y_pos = mxs_lradc_read_raw_channel(lradc, ++ TOUCHSCREEN_VCHANNEL1); + mxs_lradc_prepare_x_pos(lradc); + return; + + case LRADC_SAMPLE_X: +- val = mxs_lradc_read_ts_channel(lradc); +- if (val < 0) { +- mxs_lradc_enable_touch_detection(lradc); /* re-start */ +- return; +- } +- lradc->ts_x_pos = val; ++ lradc->ts_x_pos = mxs_lradc_read_raw_channel(lradc, ++ TOUCHSCREEN_VCHANNEL1); + mxs_lradc_prepare_pressure(lradc); + return; + + case LRADC_SAMPLE_PRESSURE: +- lradc->ts_pressure = +- mxs_lradc_read_ts_pressure(lradc, TS_CH_XP, TS_CH_YM); ++ lradc->ts_pressure = mxs_lradc_read_ts_pressure(lradc, ++ TOUCHSCREEN_VCHANNEL2, ++ TOUCHSCREEN_VCHANNEL1); + mxs_lradc_complete_touch_event(lradc); + return; + + case LRADC_SAMPLE_VALID: +- val = mxs_lradc_read_ts_channel(lradc); /* ignore the value */ + mxs_lradc_finish_touch_event(lradc, 1); + break; + } +@@ -842,9 +827,9 @@ static int mxs_lradc_read_single(struct iio_dev *iio_dev, int chan, int *val) + * used if doing raw sampling. + */ + if (lradc->soc == IMX28_LRADC) +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), + LRADC_CTRL1); +- mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); ++ mxs_lradc_reg_clear(lradc, 0x1, LRADC_CTRL0); + + /* Enable / disable the divider per requirement */ + if (test_bit(chan, &lradc->is_divided)) +@@ -1091,9 +1076,8 @@ static void mxs_lradc_disable_ts(struct mxs_lradc *lradc) + { + /* stop all interrupts from firing */ + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN | +- LRADC_CTRL1_LRADC_IRQ_EN(2) | LRADC_CTRL1_LRADC_IRQ_EN(3) | +- LRADC_CTRL1_LRADC_IRQ_EN(4) | LRADC_CTRL1_LRADC_IRQ_EN(5), +- LRADC_CTRL1); ++ LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) | ++ LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1); + + /* Power-down touchscreen touch-detect circuitry. */ + mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); +@@ -1159,25 +1143,30 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) + struct iio_dev *iio = data; + struct mxs_lradc *lradc = iio_priv(iio); + unsigned long reg = readl(lradc->base + LRADC_CTRL1); ++ uint32_t clr_irq = mxs_lradc_irq_mask(lradc); + const uint32_t ts_irq_mask = + LRADC_CTRL1_TOUCH_DETECT_IRQ | +- LRADC_CTRL1_LRADC_IRQ(2) | +- LRADC_CTRL1_LRADC_IRQ(3) | +- LRADC_CTRL1_LRADC_IRQ(4) | +- LRADC_CTRL1_LRADC_IRQ(5); ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) | ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2); + + if (!(reg & mxs_lradc_irq_mask(lradc))) + return IRQ_NONE; + +- if (lradc->use_touchscreen && (reg & ts_irq_mask)) ++ if (lradc->use_touchscreen && (reg & ts_irq_mask)) { + mxs_lradc_handle_touch(lradc); ++ /* Make sure we don't clear the next conversion's interrupt. */ ++ clr_irq &= ~(LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) | ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2)); ++ } + +- if (iio_buffer_enabled(iio)) +- iio_trigger_poll(iio->trig, iio_get_time_ns()); +- else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) ++ if (iio_buffer_enabled(iio)) { ++ if (reg & lradc->buffer_vchans) ++ iio_trigger_poll(iio->trig, iio_get_time_ns()); ++ } else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) { + complete(&lradc->completion); ++ } + +- mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc), LRADC_CTRL1); ++ mxs_lradc_reg_clear(lradc, reg & clr_irq, LRADC_CTRL1); + + return IRQ_HANDLED; + } +@@ -1288,9 +1277,10 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio) + } + + if (lradc->soc == IMX28_LRADC) +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, +- LRADC_CTRL1); +- mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); ++ mxs_lradc_reg_clear(lradc, ++ lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET, ++ LRADC_CTRL1); ++ mxs_lradc_reg_clear(lradc, lradc->buffer_vchans, LRADC_CTRL0); + + for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) { + ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs); +@@ -1323,10 +1313,11 @@ static int mxs_lradc_buffer_postdisable(struct iio_dev *iio) + mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK | + LRADC_DELAY_KICK, LRADC_DELAY(0)); + +- mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); ++ mxs_lradc_reg_clear(lradc, lradc->buffer_vchans, LRADC_CTRL0); + if (lradc->soc == IMX28_LRADC) +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, +- LRADC_CTRL1); ++ mxs_lradc_reg_clear(lradc, ++ lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET, ++ LRADC_CTRL1); + + kfree(lradc->buffer); + mutex_unlock(&lradc->lock); +@@ -1352,7 +1343,7 @@ static bool mxs_lradc_validate_scan_mask(struct iio_dev *iio, + if (lradc->use_touchbutton) + rsvd_chans++; + if (lradc->use_touchscreen) +- rsvd_chans++; ++ rsvd_chans += 2; + + /* Test for attempts to map channels with special mode of operation. */ + if (bitmap_intersects(mask, &rsvd_mask, LRADC_MAX_TOTAL_CHANS)) +@@ -1412,6 +1403,13 @@ static const struct iio_chan_spec mxs_lradc_chan_spec[] = { + .channel = 8, + .scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,}, + }, ++ /* Hidden channel to keep indexes */ ++ { ++ .type = IIO_TEMP, ++ .indexed = 1, ++ .scan_index = -1, ++ .channel = 9, ++ }, + MXS_ADC_CHAN(10, IIO_VOLTAGE), /* VDDIO */ + MXS_ADC_CHAN(11, IIO_VOLTAGE), /* VTH */ + MXS_ADC_CHAN(12, IIO_VOLTAGE), /* VDDA */ +@@ -1563,6 +1561,11 @@ static int mxs_lradc_probe(struct platform_device *pdev) + + touch_ret = mxs_lradc_probe_touchscreen(lradc, node); + ++ if (touch_ret == 0) ++ lradc->buffer_vchans = BUFFER_VCHANS_LIMITED; ++ else ++ lradc->buffer_vchans = BUFFER_VCHANS_ALL; ++ + /* Grab all IRQ sources */ + for (i = 0; i < of_cfg->irq_count; i++) { + lradc->irq[i] = platform_get_irq(pdev, i); +diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c +index 2b96665..97d4b3f 100644 +--- a/drivers/staging/iio/impedance-analyzer/ad5933.c ++++ b/drivers/staging/iio/impedance-analyzer/ad5933.c +@@ -115,6 +115,7 @@ static const struct iio_chan_spec ad5933_channels[] = { + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .address = AD5933_REG_TEMP_DATA, ++ .scan_index = -1, + .scan_type = { + .sign = 's', + .realbits = 14, +@@ -124,9 +125,7 @@ static const struct iio_chan_spec ad5933_channels[] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, +- .extend_name = "real_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | +- BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "real", + .address = AD5933_REG_REAL_DATA, + .scan_index = 0, + .scan_type = { +@@ -138,9 +137,7 @@ static const struct iio_chan_spec ad5933_channels[] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, +- .extend_name = "imag_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | +- BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "imag", + .address = AD5933_REG_IMAG_DATA, + .scan_index = 1, + .scan_type = { +@@ -748,14 +745,14 @@ static int ad5933_probe(struct i2c_client *client, + indio_dev->name = id->name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ad5933_channels; +- indio_dev->num_channels = 1; /* only register temp0_input */ ++ indio_dev->num_channels = ARRAY_SIZE(ad5933_channels); + + ret = ad5933_register_ring_funcs_and_init(indio_dev); + if (ret) + goto error_disable_reg; + +- /* skip temp0_input, register in0_(real|imag)_raw */ +- ret = iio_buffer_register(indio_dev, &ad5933_channels[1], 2); ++ ret = iio_buffer_register(indio_dev, ad5933_channels, ++ ARRAY_SIZE(ad5933_channels)); + if (ret) + goto error_unreg_ring; + +diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h +index 0731820..e8c98cf 100644 +--- a/drivers/staging/iio/meter/ade7758.h ++++ b/drivers/staging/iio/meter/ade7758.h +@@ -119,7 +119,6 @@ struct ade7758_state { + u8 *tx; + u8 *rx; + struct mutex buf_lock; +- const struct iio_chan_spec *ade7758_ring_channels; + struct spi_transfer ring_xfer[4]; + struct spi_message ring_msg; + /* +diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c +index cba183e..94d9914 100644 +--- a/drivers/staging/iio/meter/ade7758_core.c ++++ b/drivers/staging/iio/meter/ade7758_core.c +@@ -630,9 +630,6 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, +- .extend_name = "raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_A, AD7758_VOLTAGE), + .scan_index = 0, + .scan_type = { +@@ -644,9 +641,6 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_CURRENT, + .indexed = 1, + .channel = 0, +- .extend_name = "raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_A, AD7758_CURRENT), + .scan_index = 1, + .scan_type = { +@@ -658,9 +652,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 0, +- .extend_name = "apparent_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "apparent", + .address = AD7758_WT(AD7758_PHASE_A, AD7758_APP_PWR), + .scan_index = 2, + .scan_type = { +@@ -672,9 +664,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 0, +- .extend_name = "active_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "active", + .address = AD7758_WT(AD7758_PHASE_A, AD7758_ACT_PWR), + .scan_index = 3, + .scan_type = { +@@ -686,9 +676,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 0, +- .extend_name = "reactive_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "reactive", + .address = AD7758_WT(AD7758_PHASE_A, AD7758_REACT_PWR), + .scan_index = 4, + .scan_type = { +@@ -700,9 +688,6 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 1, +- .extend_name = "raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_B, AD7758_VOLTAGE), + .scan_index = 5, + .scan_type = { +@@ -714,9 +699,6 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_CURRENT, + .indexed = 1, + .channel = 1, +- .extend_name = "raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_B, AD7758_CURRENT), + .scan_index = 6, + .scan_type = { +@@ -728,9 +710,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 1, +- .extend_name = "apparent_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "apparent", + .address = AD7758_WT(AD7758_PHASE_B, AD7758_APP_PWR), + .scan_index = 7, + .scan_type = { +@@ -742,9 +722,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 1, +- .extend_name = "active_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "active", + .address = AD7758_WT(AD7758_PHASE_B, AD7758_ACT_PWR), + .scan_index = 8, + .scan_type = { +@@ -756,9 +734,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 1, +- .extend_name = "reactive_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "reactive", + .address = AD7758_WT(AD7758_PHASE_B, AD7758_REACT_PWR), + .scan_index = 9, + .scan_type = { +@@ -770,9 +746,6 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 2, +- .extend_name = "raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_C, AD7758_VOLTAGE), + .scan_index = 10, + .scan_type = { +@@ -784,9 +757,6 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_CURRENT, + .indexed = 1, + .channel = 2, +- .extend_name = "raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = AD7758_WT(AD7758_PHASE_C, AD7758_CURRENT), + .scan_index = 11, + .scan_type = { +@@ -798,9 +768,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 2, +- .extend_name = "apparent_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "apparent", + .address = AD7758_WT(AD7758_PHASE_C, AD7758_APP_PWR), + .scan_index = 12, + .scan_type = { +@@ -812,9 +780,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 2, +- .extend_name = "active_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "active", + .address = AD7758_WT(AD7758_PHASE_C, AD7758_ACT_PWR), + .scan_index = 13, + .scan_type = { +@@ -826,9 +792,7 @@ static const struct iio_chan_spec ade7758_channels[] = { + .type = IIO_POWER, + .indexed = 1, + .channel = 2, +- .extend_name = "reactive_raw", +- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .extend_name = "reactive", + .address = AD7758_WT(AD7758_PHASE_C, AD7758_REACT_PWR), + .scan_index = 14, + .scan_type = { +@@ -869,13 +833,14 @@ static int ade7758_probe(struct spi_device *spi) + goto error_free_rx; + } + st->us = spi; +- st->ade7758_ring_channels = &ade7758_channels[0]; + mutex_init(&st->buf_lock); + + indio_dev->name = spi->dev.driver->name; + indio_dev->dev.parent = &spi->dev; + indio_dev->info = &ade7758_info; + indio_dev->modes = INDIO_DIRECT_MODE; ++ indio_dev->channels = ade7758_channels; ++ indio_dev->num_channels = ARRAY_SIZE(ade7758_channels); + + ret = ade7758_configure_ring(indio_dev); + if (ret) +diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c +index c0accf8..6e90064 100644 +--- a/drivers/staging/iio/meter/ade7758_ring.c ++++ b/drivers/staging/iio/meter/ade7758_ring.c +@@ -85,17 +85,16 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p) + **/ + static int ade7758_ring_preenable(struct iio_dev *indio_dev) + { +- struct ade7758_state *st = iio_priv(indio_dev); + unsigned channel; + +- if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) ++ if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) + return -EINVAL; + + channel = find_first_bit(indio_dev->active_scan_mask, + indio_dev->masklength); + + ade7758_write_waveform_type(&indio_dev->dev, +- st->ade7758_ring_channels[channel].address); ++ indio_dev->channels[channel].address); + + return 0; + } +diff --git a/drivers/staging/iio/meter/ade7758_trigger.c b/drivers/staging/iio/meter/ade7758_trigger.c +index 7a94ddd..8c4f289 100644 +--- a/drivers/staging/iio/meter/ade7758_trigger.c ++++ b/drivers/staging/iio/meter/ade7758_trigger.c +@@ -85,7 +85,7 @@ int ade7758_probe_trigger(struct iio_dev *indio_dev) + ret = iio_trigger_register(st->trig); + + /* select default trigger */ +- indio_dev->trig = st->trig; ++ indio_dev->trig = iio_trigger_get(st->trig); + if (ret) + goto error_free_irq; + +diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c +index 34b642a..c70f173 100644 +--- a/drivers/staging/imx-drm/ipuv3-plane.c ++++ b/drivers/staging/imx-drm/ipuv3-plane.c +@@ -277,7 +277,8 @@ static void ipu_plane_dpms(struct ipu_plane *ipu_plane, int mode) + + ipu_idmac_put(ipu_plane->ipu_ch); + ipu_dmfc_put(ipu_plane->dmfc); +- ipu_dp_put(ipu_plane->dp); ++ if (ipu_plane->dp) ++ ipu_dp_put(ipu_plane->dp); + } + } + +diff --git a/drivers/staging/lustre/lustre/Kconfig b/drivers/staging/lustre/lustre/Kconfig +index 209e4c7..4f65ba1 100644 +--- a/drivers/staging/lustre/lustre/Kconfig ++++ b/drivers/staging/lustre/lustre/Kconfig +@@ -57,4 +57,5 @@ config LUSTRE_TRANSLATE_ERRNOS + config LUSTRE_LLITE_LLOOP + tristate "Lustre virtual block device" + depends on LUSTRE_FS && BLOCK ++ depends on !PPC_64K_PAGES && !ARM64_64K_PAGES + default m +diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c +index cbd663e..19405ed 100644 +--- a/drivers/staging/lustre/lustre/llite/dcache.c ++++ b/drivers/staging/lustre/lustre/llite/dcache.c +@@ -278,7 +278,7 @@ void ll_invalidate_aliases(struct inode *inode) + inode->i_ino, inode->i_generation, inode); + + ll_lock_dcache(inode); +- ll_d_hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) { ++ ll_d_hlist_for_each_entry(dentry, p, &inode->i_dentry, d_u.d_alias) { + CDEBUG(D_DENTRY, "dentry in drop %.*s (%p) parent %p " + "inode %p flags %d\n", dentry->d_name.len, + dentry->d_name.name, dentry, dentry->d_parent, +diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c +index 6cfdb9e..5ae562e 100644 +--- a/drivers/staging/lustre/lustre/llite/llite_lib.c ++++ b/drivers/staging/lustre/lustre/llite/llite_lib.c +@@ -678,7 +678,7 @@ void lustre_dump_dentry(struct dentry *dentry, int recur) + return; + + list_for_each(tmp, &dentry->d_subdirs) { +- struct dentry *d = list_entry(tmp, struct dentry, d_u.d_child); ++ struct dentry *d = list_entry(tmp, struct dentry, d_child); + lustre_dump_dentry(d, recur - 1); + } + } +diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c +index fc8d264..8e9a9e9 100644 +--- a/drivers/staging/lustre/lustre/llite/namei.c ++++ b/drivers/staging/lustre/lustre/llite/namei.c +@@ -175,14 +175,14 @@ static void ll_invalidate_negative_children(struct inode *dir) + struct ll_d_hlist_node *p; + + ll_lock_dcache(dir); +- ll_d_hlist_for_each_entry(dentry, p, &dir->i_dentry, d_alias) { ++ ll_d_hlist_for_each_entry(dentry, p, &dir->i_dentry, d_u.d_alias) { + spin_lock(&dentry->d_lock); + if (!list_empty(&dentry->d_subdirs)) { + struct dentry *child; + + list_for_each_entry_safe(child, tmp_subdir, + &dentry->d_subdirs, +- d_u.d_child) { ++ d_child) { + if (child->d_inode == NULL) + d_lustre_invalidate(child, 1); + } +@@ -364,7 +364,7 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *dentry) + discon_alias = invalid_alias = NULL; + + ll_lock_dcache(inode); +- ll_d_hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) { ++ ll_d_hlist_for_each_entry(alias, p, &inode->i_dentry, d_u.d_alias) { + LASSERT(alias != dentry); + + spin_lock(&alias->d_lock); +@@ -953,7 +953,7 @@ static void ll_get_child_fid(struct inode * dir, struct qstr *name, + { + struct dentry *parent, *child; + +- parent = ll_d_hlist_entry(dir->i_dentry, struct dentry, d_alias); ++ parent = ll_d_hlist_entry(dir->i_dentry, struct dentry, d_u.d_alias); + child = d_lookup(parent, name); + if (child) { + if (child->d_inode) +diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c +index 93cbfbb..6096771 100644 +--- a/drivers/staging/lustre/lustre/llite/vvp_io.c ++++ b/drivers/staging/lustre/lustre/llite/vvp_io.c +@@ -642,7 +642,7 @@ static int vvp_io_kernel_fault(struct vvp_fault_io *cfio) + return 0; + } + +- if (cfio->fault.ft_flags & VM_FAULT_SIGBUS) { ++ if (cfio->fault.ft_flags & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) { + CDEBUG(D_PAGE, "got addr %p - SIGBUS\n", vmf->virtual_address); + return -EFAULT; + } +diff --git a/drivers/staging/media/omap4iss/Kconfig b/drivers/staging/media/omap4iss/Kconfig +index b9fe753..15940f8 100644 +--- a/drivers/staging/media/omap4iss/Kconfig ++++ b/drivers/staging/media/omap4iss/Kconfig +@@ -1,6 +1,6 @@ + config VIDEO_OMAP4 + bool "OMAP 4 Camera support" +- depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && I2C && ARCH_OMAP4 ++ depends on VIDEO_V4L2=y && VIDEO_V4L2_SUBDEV_API && I2C=y && ARCH_OMAP4 + select VIDEOBUF2_DMA_CONTIG + ---help--- + Driver for an OMAP 4 ISS controller. +diff --git a/drivers/staging/ozwpan/ozusbsvc1.c b/drivers/staging/ozwpan/ozusbsvc1.c +index 617f51c..b58e87e 100644 +--- a/drivers/staging/ozwpan/ozusbsvc1.c ++++ b/drivers/staging/ozwpan/ozusbsvc1.c +@@ -323,7 +323,11 @@ static void oz_usb_handle_ep_data(struct oz_usb_ctx *usb_ctx, + struct oz_multiple_fixed *body = + (struct oz_multiple_fixed *)data_hdr; + u8 *data = body->data; +- int n = (len - sizeof(struct oz_multiple_fixed)+1) ++ unsigned int n; ++ if (!body->unit_size || ++ len < sizeof(struct oz_multiple_fixed) - 1) ++ break; ++ n = (len - (sizeof(struct oz_multiple_fixed) - 1)) + / body->unit_size; + while (n--) { + oz_hcd_data_ind(usb_ctx->hport, body->endpoint, +@@ -386,10 +390,15 @@ void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt) + case OZ_GET_DESC_RSP: { + struct oz_get_desc_rsp *body = + (struct oz_get_desc_rsp *)usb_hdr; +- int data_len = elt->length - +- sizeof(struct oz_get_desc_rsp) + 1; +- u16 offs = le16_to_cpu(get_unaligned(&body->offset)); +- u16 total_size = ++ u16 offs, total_size; ++ u8 data_len; ++ ++ if (elt->length < sizeof(struct oz_get_desc_rsp) - 1) ++ break; ++ data_len = elt->length - ++ (sizeof(struct oz_get_desc_rsp) - 1); ++ offs = le16_to_cpu(get_unaligned(&body->offset)); ++ total_size = + le16_to_cpu(get_unaligned(&body->total_size)); + oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - cnf\n"); + oz_hcd_get_desc_cnf(usb_ctx->hport, body->req_id, +diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c +index ec4b1fd..790e12e 100644 +--- a/drivers/staging/panel/panel.c ++++ b/drivers/staging/panel/panel.c +@@ -275,11 +275,11 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES]; + * LCD types + */ + #define LCD_TYPE_NONE 0 +-#define LCD_TYPE_OLD 1 +-#define LCD_TYPE_KS0074 2 +-#define LCD_TYPE_HANTRONIX 3 +-#define LCD_TYPE_NEXCOM 4 +-#define LCD_TYPE_CUSTOM 5 ++#define LCD_TYPE_CUSTOM 1 ++#define LCD_TYPE_OLD 2 ++#define LCD_TYPE_KS0074 3 ++#define LCD_TYPE_HANTRONIX 4 ++#define LCD_TYPE_NEXCOM 5 + + /* + * keypad types +@@ -457,8 +457,7 @@ MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead"); + static int lcd_type = -1; + module_param(lcd_type, int, 0000); + MODULE_PARM_DESC(lcd_type, +- "LCD type: 0=none, 1=old //, 2=serial ks0074, " +- "3=hantronix //, 4=nexcom //, 5=compiled-in"); ++ "LCD type: 0=none, 1=compiled-in, 2=old, 3=serial ks0074, 4=hantronix, 5=nexcom"); + + static int lcd_proto = -1; + module_param(lcd_proto, int, 0000); +diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h +index 09ffd9b..6ebdd3f 100644 +--- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h ++++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h +@@ -1460,12 +1460,12 @@ extern void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, + + extern const long ieee80211_wlan_frequencies[]; + +-extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee) ++static inline void ieee80211_increment_scans(struct ieee80211_device *ieee) + { + ieee->scans++; + } + +-extern inline int ieee80211_get_scans(struct ieee80211_device *ieee) ++static inline int ieee80211_get_scans(struct ieee80211_device *ieee) + { + return ieee->scans; + } +diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c +index 2f40ff5..2185a71 100644 +--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c ++++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c +@@ -53,9 +53,12 @@ static struct usb_device_id rtw_usb_id_tbl[] = { + {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179)}, /* 8188ETV */ + /*=== Customer ID ===*/ + /****** 8188EUS ********/ ++ {USB_DEVICE(0x056e, 0x4008)}, /* Elecom WDC-150SU2M */ + {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */ + {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(0x0df6, 0x0076)}, /* Sitecom N150 v2 */ + {} /* Terminating entry */ + }; + +diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h +index 83f5f57..59dc078 100644 +--- a/drivers/staging/rtl8192e/rtllib.h ++++ b/drivers/staging/rtl8192e/rtllib.h +@@ -2761,7 +2761,6 @@ extern void rtllib_stop_scan(struct rtllib_device *ieee); + extern bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan); + extern void rtllib_stop_scan_syncro(struct rtllib_device *ieee); + extern void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh); +-extern inline struct sk_buff *rtllib_probe_req(struct rtllib_device *ieee); + extern u8 MgntQuery_MgntFrameTxRate(struct rtllib_device *ieee); + extern void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, + short pwr); +@@ -2943,12 +2942,12 @@ void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh); + + extern const long rtllib_wlan_frequencies[]; + +-extern inline void rtllib_increment_scans(struct rtllib_device *ieee) ++static inline void rtllib_increment_scans(struct rtllib_device *ieee) + { + ieee->scans++; + } + +-extern inline int rtllib_get_scans(struct rtllib_device *ieee) ++static inline int rtllib_get_scans(struct rtllib_device *ieee) + { + return ieee->scans; + } +diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c +index 4bf72bc..7b5093a 100644 +--- a/drivers/staging/rtl8192e/rtllib_softmac.c ++++ b/drivers/staging/rtl8192e/rtllib_softmac.c +@@ -341,7 +341,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, + } + } + +-inline struct sk_buff *rtllib_probe_req(struct rtllib_device *ieee) ++static inline struct sk_buff *rtllib_probe_req(struct rtllib_device *ieee) + { + unsigned int len, rate_len; + u8 *tag; +diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h +index bc64f05..b1a0380 100644 +--- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h ++++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h +@@ -2250,7 +2250,7 @@ static inline void *ieee80211_priv(struct net_device *dev) + return ((struct ieee80211_device *)netdev_priv(dev))->priv; + } + +-extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len) ++static inline int ieee80211_is_empty_essid(const char *essid, int essid_len) + { + /* Single white space is for Linksys APs */ + if (essid_len == 1 && essid[0] == ' ') +@@ -2266,7 +2266,7 @@ extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len) + return 1; + } + +-extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode) ++static inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode) + { + /* + * It is possible for both access points and our device to support +@@ -2292,7 +2292,7 @@ extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mod + return 0; + } + +-extern inline int ieee80211_get_hdrlen(u16 fc) ++static inline int ieee80211_get_hdrlen(u16 fc) + { + int hdrlen = IEEE80211_3ADDR_LEN; + +@@ -2578,12 +2578,12 @@ void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee); + + extern const long ieee80211_wlan_frequencies[]; + +-extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee) ++static inline void ieee80211_increment_scans(struct ieee80211_device *ieee) + { + ieee->scans++; + } + +-extern inline int ieee80211_get_scans(struct ieee80211_device *ieee) ++static inline int ieee80211_get_scans(struct ieee80211_device *ieee) + { + return ieee->scans; + } +diff --git a/drivers/staging/rtl8712/ieee80211.h b/drivers/staging/rtl8712/ieee80211.h +index da4000e..8269be8 100644 +--- a/drivers/staging/rtl8712/ieee80211.h ++++ b/drivers/staging/rtl8712/ieee80211.h +@@ -734,7 +734,7 @@ enum ieee80211_state { + #define IEEE_G (1<<2) + #define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G) + +-extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len) ++static inline int ieee80211_is_empty_essid(const char *essid, int essid_len) + { + /* Single white space is for Linksys APs */ + if (essid_len == 1 && essid[0] == ' ') +@@ -748,7 +748,7 @@ extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len) + return 1; + } + +-extern inline int ieee80211_get_hdrlen(u16 fc) ++static inline int ieee80211_get_hdrlen(u16 fc) + { + int hdrlen = 24; + +diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c +index ea96537..d060b1f 100644 +--- a/drivers/staging/rtl8712/rtl8712_recv.c ++++ b/drivers/staging/rtl8712/rtl8712_recv.c +@@ -1075,7 +1075,8 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) + /* for first fragment packet, driver need allocate 1536 + + * drvinfo_sz + RXDESC_SIZE to defrag packet. */ + if ((mf == 1) && (frag == 0)) +- alloc_sz = 1658;/*1658+6=1664, 1664 is 128 alignment.*/ ++ /*1658+6=1664, 1664 is 128 alignment.*/ ++ alloc_sz = max_t(u16, tmp_len, 1658); + else + alloc_sz = tmp_len; + /* 2 is for IP header 4 bytes alignment in QoS packet case. +diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c +index d7efd017..7d75788 100644 +--- a/drivers/staging/vt6655/bssdb.c ++++ b/drivers/staging/vt6655/bssdb.c +@@ -983,7 +983,7 @@ start: + pDevice->byERPFlag &= ~(WLAN_SET_ERP_USE_PROTECTION(1)); + } + +- { ++ if (pDevice->eCommandState == WLAN_ASSOCIATE_WAIT) { + pDevice->byReAssocCount++; + /* 10 sec timeout */ + if ((pDevice->byReAssocCount > 10) && (!pDevice->bLinkPass)) { +diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c +index a952df1..6f13f0e 100644 +--- a/drivers/staging/vt6655/device_main.c ++++ b/drivers/staging/vt6655/device_main.c +@@ -2430,6 +2430,7 @@ static irqreturn_t device_intr(int irq, void *dev_instance) { + int handled = 0; + unsigned char byData = 0; + int ii = 0; ++ unsigned long flags; + // unsigned char byRSSI; + + MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr); +@@ -2455,7 +2456,8 @@ static irqreturn_t device_intr(int irq, void *dev_instance) { + + handled = 1; + MACvIntDisable(pDevice->PortOffset); +- spin_lock_irq(&pDevice->lock); ++ ++ spin_lock_irqsave(&pDevice->lock, flags); + + //Make sure current page is 0 + VNSvInPortB(pDevice->PortOffset + MAC_REG_PAGE1SEL, &byOrgPageSel); +@@ -2696,7 +2698,8 @@ static irqreturn_t device_intr(int irq, void *dev_instance) { + MACvSelectPage1(pDevice->PortOffset); + } + +- spin_unlock_irq(&pDevice->lock); ++ spin_unlock_irqrestore(&pDevice->lock, flags); ++ + MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); + + return IRQ_RETVAL(handled); +diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c +index edb1b27..dbd9d44 100644 +--- a/drivers/staging/vt6655/rf.c ++++ b/drivers/staging/vt6655/rf.c +@@ -936,6 +936,7 @@ bool RFbSetPower( + break; + case RATE_6M: + case RATE_9M: ++ case RATE_12M: + case RATE_18M: + byPwr = pDevice->abyOFDMPwrTbl[uCH]; + if (pDevice->byRFType == RF_UW2452) { +diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c +index 1e8f64b..2dc48d4 100644 +--- a/drivers/staging/vt6656/rf.c ++++ b/drivers/staging/vt6656/rf.c +@@ -752,6 +752,7 @@ int RFbSetPower(struct vnt_private *priv, u32 rate, u32 channel) + break; + case RATE_6M: + case RATE_9M: ++ case RATE_12M: + case RATE_18M: + case RATE_24M: + case RATE_36M: +diff --git a/drivers/staging/wlags49_h2/wl_internal.h b/drivers/staging/wlags49_h2/wl_internal.h +index 78129e9..1ecb5cb 100644 +--- a/drivers/staging/wlags49_h2/wl_internal.h ++++ b/drivers/staging/wlags49_h2/wl_internal.h +@@ -1013,7 +1013,7 @@ static inline void wl_unlock(struct wl_private *lp, + /* Interrupt enable disable functions */ + /********************************************************************/ + +-extern inline void wl_act_int_on(struct wl_private *lp) ++static inline void wl_act_int_on(struct wl_private *lp) + { + /* + * Only do something when the driver is handling +@@ -1025,7 +1025,7 @@ extern inline void wl_act_int_on(struct wl_private *lp) + } + } + +-extern inline void wl_act_int_off(struct wl_private *lp) ++static inline void wl_act_int_off(struct wl_private *lp) + { + /* + * Only do something when the driver is handling +diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c +index f329ad2..9dbf176 100644 +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -518,7 +518,7 @@ static struct iscsit_transport iscsi_target_transport = { + + static int __init iscsi_target_init_module(void) + { +- int ret = 0; ++ int ret = 0, size; + + pr_debug("iSCSI-Target "ISCSIT_VERSION"\n"); + +@@ -527,6 +527,7 @@ static int __init iscsi_target_init_module(void) + pr_err("Unable to allocate memory for iscsit_global\n"); + return -1; + } ++ spin_lock_init(&iscsit_global->ts_bitmap_lock); + mutex_init(&auth_id_lock); + spin_lock_init(&sess_idr_lock); + idr_init(&tiqn_idr); +@@ -536,15 +537,11 @@ static int __init iscsi_target_init_module(void) + if (ret < 0) + goto out; + +- ret = iscsi_thread_set_init(); +- if (ret < 0) ++ size = BITS_TO_LONGS(ISCSIT_BITMAP_BITS) * sizeof(long); ++ iscsit_global->ts_bitmap = vzalloc(size); ++ if (!iscsit_global->ts_bitmap) { ++ pr_err("Unable to allocate iscsit_global->ts_bitmap\n"); + goto configfs_out; +- +- if (iscsi_allocate_thread_sets(TARGET_THREAD_SET_COUNT) != +- TARGET_THREAD_SET_COUNT) { +- pr_err("iscsi_allocate_thread_sets() returned" +- " unexpected value!\n"); +- goto ts_out1; + } + + lio_qr_cache = kmem_cache_create("lio_qr_cache", +@@ -553,7 +550,7 @@ static int __init iscsi_target_init_module(void) + if (!lio_qr_cache) { + pr_err("nable to kmem_cache_create() for" + " lio_qr_cache\n"); +- goto ts_out2; ++ goto bitmap_out; + } + + lio_dr_cache = kmem_cache_create("lio_dr_cache", +@@ -597,10 +594,8 @@ dr_out: + kmem_cache_destroy(lio_dr_cache); + qr_out: + kmem_cache_destroy(lio_qr_cache); +-ts_out2: +- iscsi_deallocate_thread_sets(); +-ts_out1: +- iscsi_thread_set_free(); ++bitmap_out: ++ vfree(iscsit_global->ts_bitmap); + configfs_out: + iscsi_target_deregister_configfs(); + out: +@@ -610,8 +605,6 @@ out: + + static void __exit iscsi_target_cleanup_module(void) + { +- iscsi_deallocate_thread_sets(); +- iscsi_thread_set_free(); + iscsit_release_discovery_tpg(); + iscsit_unregister_transport(&iscsi_target_transport); + kmem_cache_destroy(lio_qr_cache); +@@ -621,6 +614,7 @@ static void __exit iscsi_target_cleanup_module(void) + + iscsi_target_deregister_configfs(); + ++ vfree(iscsit_global->ts_bitmap); + kfree(iscsit_global); + } + +@@ -1165,7 +1159,7 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, + * traditional iSCSI block I/O. + */ + if (iscsit_allocate_iovecs(cmd) < 0) { +- return iscsit_add_reject_cmd(cmd, ++ return iscsit_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); + } + immed_data = cmd->immediate_data; +@@ -3653,17 +3647,16 @@ static int iscsit_send_reject( + + void iscsit_thread_get_cpumask(struct iscsi_conn *conn) + { +- struct iscsi_thread_set *ts = conn->thread_set; + int ord, cpu; + /* +- * thread_id is assigned from iscsit_global->ts_bitmap from +- * within iscsi_thread_set.c:iscsi_allocate_thread_sets() ++ * bitmap_id is assigned from iscsit_global->ts_bitmap from ++ * within iscsit_start_kthreads() + * +- * Here we use thread_id to determine which CPU that this +- * iSCSI connection's iscsi_thread_set will be scheduled to ++ * Here we use bitmap_id to determine which CPU that this ++ * iSCSI connection's RX/TX threads will be scheduled to + * execute upon. + */ +- ord = ts->thread_id % cpumask_weight(cpu_online_mask); ++ ord = conn->bitmap_id % cpumask_weight(cpu_online_mask); + for_each_online_cpu(cpu) { + if (ord-- == 0) { + cpumask_set_cpu(cpu, conn->conn_cpumask); +@@ -3855,7 +3848,7 @@ check_rsp_state: + switch (state) { + case ISTATE_SEND_LOGOUTRSP: + if (!iscsit_logout_post_handler(cmd, conn)) +- goto restart; ++ return -ECONNRESET; + /* fall through */ + case ISTATE_SEND_STATUS: + case ISTATE_SEND_ASYNCMSG: +@@ -3883,8 +3876,6 @@ check_rsp_state: + + err: + return -1; +-restart: +- return -EAGAIN; + } + + static int iscsit_handle_response_queue(struct iscsi_conn *conn) +@@ -3911,21 +3902,13 @@ static int iscsit_handle_response_queue(struct iscsi_conn *conn) + int iscsi_target_tx_thread(void *arg) + { + int ret = 0; +- struct iscsi_conn *conn; +- struct iscsi_thread_set *ts = arg; ++ struct iscsi_conn *conn = arg; + /* + * Allow ourselves to be interrupted by SIGINT so that a + * connection recovery / failure event can be triggered externally. + */ + allow_signal(SIGINT); + +-restart: +- conn = iscsi_tx_thread_pre_handler(ts); +- if (!conn) +- goto out; +- +- ret = 0; +- + while (!kthread_should_stop()) { + /* + * Ensure that both TX and RX per connection kthreads +@@ -3934,11 +3917,9 @@ restart: + iscsit_thread_check_cpumask(conn, current, 1); + + wait_event_interruptible(conn->queues_wq, +- !iscsit_conn_all_queues_empty(conn) || +- ts->status == ISCSI_THREAD_SET_RESET); ++ !iscsit_conn_all_queues_empty(conn)); + +- if ((ts->status == ISCSI_THREAD_SET_RESET) || +- signal_pending(current)) ++ if (signal_pending(current)) + goto transport_err; + + get_immediate: +@@ -3949,15 +3930,20 @@ get_immediate: + ret = iscsit_handle_response_queue(conn); + if (ret == 1) + goto get_immediate; +- else if (ret == -EAGAIN) +- goto restart; ++ else if (ret == -ECONNRESET) ++ goto out; + else if (ret < 0) + goto transport_err; + } + + transport_err: +- iscsit_take_action_for_connection_exit(conn); +- goto restart; ++ /* ++ * Avoid the normal connection failure code-path if this connection ++ * is still within LOGIN mode, and iscsi_np process context is ++ * responsible for cleaning up the early connection failure. ++ */ ++ if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN) ++ iscsit_take_action_for_connection_exit(conn); + out: + return 0; + } +@@ -4043,33 +4029,33 @@ reject: + + int iscsi_target_rx_thread(void *arg) + { +- int ret; ++ int ret, rc; + u8 buffer[ISCSI_HDR_LEN], opcode; + u32 checksum = 0, digest = 0; +- struct iscsi_conn *conn = NULL; +- struct iscsi_thread_set *ts = arg; ++ struct iscsi_conn *conn = arg; + struct kvec iov; + /* + * Allow ourselves to be interrupted by SIGINT so that a + * connection recovery / failure event can be triggered externally. + */ + allow_signal(SIGINT); +- +-restart: +- conn = iscsi_rx_thread_pre_handler(ts); +- if (!conn) +- goto out; ++ /* ++ * Wait for iscsi_post_login_handler() to complete before allowing ++ * incoming iscsi/tcp socket I/O, and/or failing the connection. ++ */ ++ rc = wait_for_completion_interruptible(&conn->rx_login_comp); ++ if (rc < 0) ++ return 0; + + if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) { + struct completion comp; +- int rc; + + init_completion(&comp); + rc = wait_for_completion_interruptible(&comp); + if (rc < 0) + goto transport_err; + +- goto out; ++ goto transport_err; + } + + while (!kthread_should_stop()) { +@@ -4145,8 +4131,6 @@ transport_err: + if (!signal_pending(current)) + atomic_set(&conn->transport_failed, 1); + iscsit_take_action_for_connection_exit(conn); +- goto restart; +-out: + return 0; + } + +@@ -4196,13 +4180,36 @@ int iscsit_close_connection( + pr_debug("Closing iSCSI connection CID %hu on SID:" + " %u\n", conn->cid, sess->sid); + /* +- * Always up conn_logout_comp just in case the RX Thread is sleeping +- * and the logout response never got sent because the connection +- * failed. ++ * Always up conn_logout_comp for the traditional TCP case just in case ++ * the RX Thread in iscsi_target_rx_opcode() is sleeping and the logout ++ * response never got sent because the connection failed. ++ * ++ * However for iser-target, isert_wait4logout() is using conn_logout_comp ++ * to signal logout response TX interrupt completion. Go ahead and skip ++ * this for iser since isert_rx_opcode() does not wait on logout failure, ++ * and to avoid iscsi_conn pointer dereference in iser-target code. + */ +- complete(&conn->conn_logout_comp); ++ if (conn->conn_transport->transport_type == ISCSI_TCP) ++ complete(&conn->conn_logout_comp); ++ ++ if (!strcmp(current->comm, ISCSI_RX_THREAD_NAME)) { ++ if (conn->tx_thread && ++ cmpxchg(&conn->tx_thread_active, true, false)) { ++ send_sig(SIGINT, conn->tx_thread, 1); ++ kthread_stop(conn->tx_thread); ++ } ++ } else if (!strcmp(current->comm, ISCSI_TX_THREAD_NAME)) { ++ if (conn->rx_thread && ++ cmpxchg(&conn->rx_thread_active, true, false)) { ++ send_sig(SIGINT, conn->rx_thread, 1); ++ kthread_stop(conn->rx_thread); ++ } ++ } + +- iscsi_release_thread_set(conn); ++ spin_lock(&iscsit_global->ts_bitmap_lock); ++ bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id, ++ get_order(1)); ++ spin_unlock(&iscsit_global->ts_bitmap_lock); + + iscsit_stop_timers_for_cmds(conn); + iscsit_stop_nopin_response_timer(conn); +@@ -4481,15 +4488,24 @@ static void iscsit_logout_post_handler_closesession( + struct iscsi_conn *conn) + { + struct iscsi_session *sess = conn->sess; +- +- iscsi_set_thread_clear(conn, ISCSI_CLEAR_TX_THREAD); +- iscsi_set_thread_set_signal(conn, ISCSI_SIGNAL_TX_THREAD); ++ int sleep = 1; ++ /* ++ * Traditional iscsi/tcp will invoke this logic from TX thread ++ * context during session logout, so clear tx_thread_active and ++ * sleep if iscsit_close_connection() has not already occured. ++ * ++ * Since iser-target invokes this logic from it's own workqueue, ++ * always sleep waiting for RX/TX thread shutdown to complete ++ * within iscsit_close_connection(). ++ */ ++ if (conn->conn_transport->transport_type == ISCSI_TCP) ++ sleep = cmpxchg(&conn->tx_thread_active, true, false); + + atomic_set(&conn->conn_logout_remove, 0); + complete(&conn->conn_logout_comp); + + iscsit_dec_conn_usage_count(conn); +- iscsit_stop_session(sess, 1, 1); ++ iscsit_stop_session(sess, sleep, sleep); + iscsit_dec_session_usage_count(sess); + target_put_session(sess->se_sess); + } +@@ -4497,13 +4513,15 @@ static void iscsit_logout_post_handler_closesession( + static void iscsit_logout_post_handler_samecid( + struct iscsi_conn *conn) + { +- iscsi_set_thread_clear(conn, ISCSI_CLEAR_TX_THREAD); +- iscsi_set_thread_set_signal(conn, ISCSI_SIGNAL_TX_THREAD); ++ int sleep = 1; ++ ++ if (conn->conn_transport->transport_type == ISCSI_TCP) ++ sleep = cmpxchg(&conn->tx_thread_active, true, false); + + atomic_set(&conn->conn_logout_remove, 0); + complete(&conn->conn_logout_comp); + +- iscsit_cause_connection_reinstatement(conn, 1); ++ iscsit_cause_connection_reinstatement(conn, sleep); + iscsit_dec_conn_usage_count(conn); + } + +@@ -4513,6 +4531,7 @@ static void iscsit_logout_post_handler_diffcid( + { + struct iscsi_conn *l_conn; + struct iscsi_session *sess = conn->sess; ++ bool conn_found = false; + + if (!sess) + return; +@@ -4521,12 +4540,13 @@ static void iscsit_logout_post_handler_diffcid( + list_for_each_entry(l_conn, &sess->sess_conn_list, conn_list) { + if (l_conn->cid == cid) { + iscsit_inc_conn_usage_count(l_conn); ++ conn_found = true; + break; + } + } + spin_unlock_bh(&sess->conn_lock); + +- if (!l_conn) ++ if (!conn_found) + return; + + if (l_conn->sock) +@@ -4715,6 +4735,7 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force) + struct iscsi_session *sess; + struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; + struct se_session *se_sess, *se_sess_tmp; ++ LIST_HEAD(free_list); + int session_count = 0; + + spin_lock_bh(&se_tpg->session_lock); +@@ -4736,14 +4757,17 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force) + } + atomic_set(&sess->session_reinstatement, 1); + spin_unlock(&sess->conn_lock); +- spin_unlock_bh(&se_tpg->session_lock); + +- iscsit_free_session(sess); +- spin_lock_bh(&se_tpg->session_lock); ++ list_move_tail(&se_sess->sess_list, &free_list); ++ } ++ spin_unlock_bh(&se_tpg->session_lock); + ++ list_for_each_entry_safe(se_sess, se_sess_tmp, &free_list, sess_list) { ++ sess = (struct iscsi_session *)se_sess->fabric_sess_ptr; ++ ++ iscsit_free_session(sess); + session_count++; + } +- spin_unlock_bh(&se_tpg->session_lock); + + pr_debug("Released %d iSCSI Session(s) from Target Portal" + " Group: %hu\n", session_count, tpg->tpgt); +diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h +index 1d4a8c8..92abbe2 100644 +--- a/drivers/target/iscsi/iscsi_target_core.h ++++ b/drivers/target/iscsi/iscsi_target_core.h +@@ -601,6 +601,12 @@ struct iscsi_conn { + struct iscsi_session *sess; + /* Pointer to thread_set in use for this conn's threads */ + struct iscsi_thread_set *thread_set; ++ int bitmap_id; ++ int rx_thread_active; ++ struct task_struct *rx_thread; ++ struct completion rx_login_comp; ++ int tx_thread_active; ++ struct task_struct *tx_thread; + /* list_head for session connection list */ + struct list_head conn_list; + } ____cacheline_aligned; +@@ -869,10 +875,12 @@ struct iscsit_global { + /* Unique identifier used for the authentication daemon */ + u32 auth_id; + u32 inactive_ts; ++#define ISCSIT_BITMAP_BITS 262144 + /* Thread Set bitmap count */ + int ts_bitmap_count; + /* Thread Set bitmap pointer */ + unsigned long *ts_bitmap; ++ spinlock_t ts_bitmap_lock; + /* Used for iSCSI discovery session authentication */ + struct iscsi_node_acl discovery_acl; + struct iscsi_portal_group *discovery_tpg; +diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c +index 0d1e6ee..7396d90 100644 +--- a/drivers/target/iscsi/iscsi_target_erl0.c ++++ b/drivers/target/iscsi/iscsi_target_erl0.c +@@ -864,7 +864,10 @@ void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *conn) + } + spin_unlock_bh(&conn->state_lock); + +- iscsi_thread_set_force_reinstatement(conn); ++ if (conn->tx_thread && conn->tx_thread_active) ++ send_sig(SIGINT, conn->tx_thread, 1); ++ if (conn->rx_thread && conn->rx_thread_active) ++ send_sig(SIGINT, conn->rx_thread, 1); + + sleep: + wait_for_completion(&conn->conn_wait_rcfr_comp); +@@ -889,10 +892,10 @@ void iscsit_cause_connection_reinstatement(struct iscsi_conn *conn, int sleep) + return; + } + +- if (iscsi_thread_set_force_reinstatement(conn) < 0) { +- spin_unlock_bh(&conn->state_lock); +- return; +- } ++ if (conn->tx_thread && conn->tx_thread_active) ++ send_sig(SIGINT, conn->tx_thread, 1); ++ if (conn->rx_thread && conn->rx_thread_active) ++ send_sig(SIGINT, conn->rx_thread, 1); + + atomic_set(&conn->connection_reinstatement, 1); + if (!sleep) { +diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c +index d509aa7..01c27aa 100644 +--- a/drivers/target/iscsi/iscsi_target_login.c ++++ b/drivers/target/iscsi/iscsi_target_login.c +@@ -83,6 +83,7 @@ static struct iscsi_login *iscsi_login_init_conn(struct iscsi_conn *conn) + init_completion(&conn->conn_logout_comp); + init_completion(&conn->rx_half_close_comp); + init_completion(&conn->tx_half_close_comp); ++ init_completion(&conn->rx_login_comp); + spin_lock_init(&conn->cmd_lock); + spin_lock_init(&conn->conn_usage_lock); + spin_lock_init(&conn->immed_queue_lock); +@@ -681,7 +682,53 @@ static void iscsi_post_login_start_timers(struct iscsi_conn *conn) + iscsit_start_nopin_timer(conn); + } + +-int iscsi_post_login_handler( ++int iscsit_start_kthreads(struct iscsi_conn *conn) ++{ ++ int ret = 0; ++ ++ spin_lock(&iscsit_global->ts_bitmap_lock); ++ conn->bitmap_id = bitmap_find_free_region(iscsit_global->ts_bitmap, ++ ISCSIT_BITMAP_BITS, get_order(1)); ++ spin_unlock(&iscsit_global->ts_bitmap_lock); ++ ++ if (conn->bitmap_id < 0) { ++ pr_err("bitmap_find_free_region() failed for" ++ " iscsit_start_kthreads()\n"); ++ return -ENOMEM; ++ } ++ ++ conn->tx_thread = kthread_run(iscsi_target_tx_thread, conn, ++ "%s", ISCSI_TX_THREAD_NAME); ++ if (IS_ERR(conn->tx_thread)) { ++ pr_err("Unable to start iscsi_target_tx_thread\n"); ++ ret = PTR_ERR(conn->tx_thread); ++ goto out_bitmap; ++ } ++ conn->tx_thread_active = true; ++ ++ conn->rx_thread = kthread_run(iscsi_target_rx_thread, conn, ++ "%s", ISCSI_RX_THREAD_NAME); ++ if (IS_ERR(conn->rx_thread)) { ++ pr_err("Unable to start iscsi_target_rx_thread\n"); ++ ret = PTR_ERR(conn->rx_thread); ++ goto out_tx; ++ } ++ conn->rx_thread_active = true; ++ ++ return 0; ++out_tx: ++ send_sig(SIGINT, conn->tx_thread, 1); ++ kthread_stop(conn->tx_thread); ++ conn->tx_thread_active = false; ++out_bitmap: ++ spin_lock(&iscsit_global->ts_bitmap_lock); ++ bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id, ++ get_order(1)); ++ spin_unlock(&iscsit_global->ts_bitmap_lock); ++ return ret; ++} ++ ++void iscsi_post_login_handler( + struct iscsi_np *np, + struct iscsi_conn *conn, + u8 zero_tsih) +@@ -691,7 +738,6 @@ int iscsi_post_login_handler( + struct se_session *se_sess = sess->se_sess; + struct iscsi_portal_group *tpg = sess->tpg; + struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; +- struct iscsi_thread_set *ts; + + iscsit_inc_conn_usage_count(conn); + +@@ -706,7 +752,6 @@ int iscsi_post_login_handler( + /* + * SCSI Initiator -> SCSI Target Port Mapping + */ +- ts = iscsi_get_thread_set(); + if (!zero_tsih) { + iscsi_set_session_parameters(sess->sess_ops, + conn->param_list, 0); +@@ -734,8 +779,6 @@ int iscsi_post_login_handler( + spin_unlock_bh(&sess->conn_lock); + + iscsi_post_login_start_timers(conn); +- +- iscsi_activate_thread_set(conn, ts); + /* + * Determine CPU mask to ensure connection's RX and TX kthreads + * are scheduled on the same CPU. +@@ -743,15 +786,20 @@ int iscsi_post_login_handler( + iscsit_thread_get_cpumask(conn); + conn->conn_rx_reset_cpumask = 1; + conn->conn_tx_reset_cpumask = 1; +- ++ /* ++ * Wakeup the sleeping iscsi_target_rx_thread() now that ++ * iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state. ++ */ ++ complete(&conn->rx_login_comp); + iscsit_dec_conn_usage_count(conn); ++ + if (stop_timer) { + spin_lock_bh(&se_tpg->session_lock); + iscsit_stop_time2retain_timer(sess); + spin_unlock_bh(&se_tpg->session_lock); + } + iscsit_dec_session_usage_count(sess); +- return 0; ++ return; + } + + iscsi_set_session_parameters(sess->sess_ops, conn->param_list, 1); +@@ -793,7 +841,6 @@ int iscsi_post_login_handler( + spin_unlock_bh(&se_tpg->session_lock); + + iscsi_post_login_start_timers(conn); +- iscsi_activate_thread_set(conn, ts); + /* + * Determine CPU mask to ensure connection's RX and TX kthreads + * are scheduled on the same CPU. +@@ -801,10 +848,12 @@ int iscsi_post_login_handler( + iscsit_thread_get_cpumask(conn); + conn->conn_rx_reset_cpumask = 1; + conn->conn_tx_reset_cpumask = 1; +- ++ /* ++ * Wakeup the sleeping iscsi_target_rx_thread() now that ++ * iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state. ++ */ ++ complete(&conn->rx_login_comp); + iscsit_dec_conn_usage_count(conn); +- +- return 0; + } + + static void iscsi_handle_login_thread_timeout(unsigned long data) +@@ -1186,6 +1235,9 @@ old_sess_out: + conn->sock = NULL; + } + ++ if (conn->conn_transport->iscsit_wait_conn) ++ conn->conn_transport->iscsit_wait_conn(conn); ++ + if (conn->conn_transport->iscsit_free_conn) + conn->conn_transport->iscsit_free_conn(conn); + +@@ -1366,23 +1418,12 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) + if (ret < 0) + goto new_sess_out; + +- if (!conn->sess) { +- pr_err("struct iscsi_conn session pointer is NULL!\n"); +- goto new_sess_out; +- } +- + iscsi_stop_login_thread_timer(np); + +- if (signal_pending(current)) +- goto new_sess_out; +- + if (ret == 1) { + tpg_np = conn->tpg_np; + +- ret = iscsi_post_login_handler(np, conn, zero_tsih); +- if (ret < 0) +- goto new_sess_out; +- ++ iscsi_post_login_handler(np, conn, zero_tsih); + iscsit_deaccess_np(np, tpg, tpg_np); + } + +diff --git a/drivers/target/iscsi/iscsi_target_login.h b/drivers/target/iscsi/iscsi_target_login.h +index 29d0983..55cbf45 100644 +--- a/drivers/target/iscsi/iscsi_target_login.h ++++ b/drivers/target/iscsi/iscsi_target_login.h +@@ -12,7 +12,8 @@ extern int iscsit_accept_np(struct iscsi_np *, struct iscsi_conn *); + extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *); + extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32); + extern void iscsit_free_conn(struct iscsi_np *, struct iscsi_conn *); +-extern int iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8); ++extern int iscsit_start_kthreads(struct iscsi_conn *); ++extern void iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8); + extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *, + bool, bool); + extern int iscsi_target_login_thread(void *); +diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c +index 582ba84..25ad113 100644 +--- a/drivers/target/iscsi/iscsi_target_nego.c ++++ b/drivers/target/iscsi/iscsi_target_nego.c +@@ -17,6 +17,7 @@ + ******************************************************************************/ + + #include ++#include + #include + #include + #include +@@ -361,10 +362,24 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log + ntohl(login_rsp->statsn), login->rsp_length); + + padding = ((-login->rsp_length) & 3); ++ /* ++ * Before sending the last login response containing the transition ++ * bit for full-feature-phase, go ahead and start up TX/RX threads ++ * now to avoid potential resource allocation failures after the ++ * final login response has been sent. ++ */ ++ if (login->login_complete) { ++ int rc = iscsit_start_kthreads(conn); ++ if (rc) { ++ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, ++ ISCSI_LOGIN_STATUS_NO_RESOURCES); ++ return -1; ++ } ++ } + + if (conn->conn_transport->iscsit_put_login_tx(conn, login, + login->rsp_length + padding) < 0) +- return -1; ++ goto err; + + login->rsp_length = 0; + mutex_lock(&sess->cmdsn_mutex); +@@ -373,6 +388,23 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log + mutex_unlock(&sess->cmdsn_mutex); + + return 0; ++ ++err: ++ if (login->login_complete) { ++ if (conn->rx_thread && conn->rx_thread_active) { ++ send_sig(SIGINT, conn->rx_thread, 1); ++ kthread_stop(conn->rx_thread); ++ } ++ if (conn->tx_thread && conn->tx_thread_active) { ++ send_sig(SIGINT, conn->tx_thread, 1); ++ kthread_stop(conn->tx_thread); ++ } ++ spin_lock(&iscsit_global->ts_bitmap_lock); ++ bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id, ++ get_order(1)); ++ spin_unlock(&iscsit_global->ts_bitmap_lock); ++ } ++ return -1; + } + + static void iscsi_target_sk_data_ready(struct sock *sk, int count) +diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c +index 4d2e23f..43b7e6a 100644 +--- a/drivers/target/iscsi/iscsi_target_parameters.c ++++ b/drivers/target/iscsi/iscsi_target_parameters.c +@@ -601,7 +601,7 @@ int iscsi_copy_param_list( + param_list = kzalloc(sizeof(struct iscsi_param_list), GFP_KERNEL); + if (!param_list) { + pr_err("Unable to allocate memory for struct iscsi_param_list.\n"); +- goto err_out; ++ return -1; + } + INIT_LIST_HEAD(¶m_list->param_list); + INIT_LIST_HEAD(¶m_list->extra_response_list); +diff --git a/drivers/target/iscsi/iscsi_target_tq.c b/drivers/target/iscsi/iscsi_target_tq.c +index 601e9cc..bb2890e 100644 +--- a/drivers/target/iscsi/iscsi_target_tq.c ++++ b/drivers/target/iscsi/iscsi_target_tq.c +@@ -24,36 +24,22 @@ + #include "iscsi_target_tq.h" + #include "iscsi_target.h" + +-static LIST_HEAD(active_ts_list); + static LIST_HEAD(inactive_ts_list); +-static DEFINE_SPINLOCK(active_ts_lock); + static DEFINE_SPINLOCK(inactive_ts_lock); + static DEFINE_SPINLOCK(ts_bitmap_lock); + +-static void iscsi_add_ts_to_active_list(struct iscsi_thread_set *ts) +-{ +- spin_lock(&active_ts_lock); +- list_add_tail(&ts->ts_list, &active_ts_list); +- iscsit_global->active_ts++; +- spin_unlock(&active_ts_lock); +-} +- + static void iscsi_add_ts_to_inactive_list(struct iscsi_thread_set *ts) + { ++ if (!list_empty(&ts->ts_list)) { ++ WARN_ON(1); ++ return; ++ } + spin_lock(&inactive_ts_lock); + list_add_tail(&ts->ts_list, &inactive_ts_list); + iscsit_global->inactive_ts++; + spin_unlock(&inactive_ts_lock); + } + +-static void iscsi_del_ts_from_active_list(struct iscsi_thread_set *ts) +-{ +- spin_lock(&active_ts_lock); +- list_del(&ts->ts_list); +- iscsit_global->active_ts--; +- spin_unlock(&active_ts_lock); +-} +- + static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void) + { + struct iscsi_thread_set *ts; +@@ -66,7 +52,7 @@ static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void) + + ts = list_first_entry(&inactive_ts_list, struct iscsi_thread_set, ts_list); + +- list_del(&ts->ts_list); ++ list_del_init(&ts->ts_list); + iscsit_global->inactive_ts--; + spin_unlock(&inactive_ts_lock); + +@@ -204,8 +190,6 @@ static void iscsi_deallocate_extra_thread_sets(void) + + void iscsi_activate_thread_set(struct iscsi_conn *conn, struct iscsi_thread_set *ts) + { +- iscsi_add_ts_to_active_list(ts); +- + spin_lock_bh(&ts->ts_state_lock); + conn->thread_set = ts; + ts->conn = conn; +@@ -397,7 +381,6 @@ struct iscsi_conn *iscsi_rx_thread_pre_handler(struct iscsi_thread_set *ts) + + if (ts->delay_inactive && (--ts->thread_count == 0)) { + spin_unlock_bh(&ts->ts_state_lock); +- iscsi_del_ts_from_active_list(ts); + + if (!iscsit_global->in_shutdown) + iscsi_deallocate_extra_thread_sets(); +@@ -452,7 +435,6 @@ struct iscsi_conn *iscsi_tx_thread_pre_handler(struct iscsi_thread_set *ts) + + if (ts->delay_inactive && (--ts->thread_count == 0)) { + spin_unlock_bh(&ts->ts_state_lock); +- iscsi_del_ts_from_active_list(ts); + + if (!iscsit_global->in_shutdown) + iscsi_deallocate_extra_thread_sets(); +diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c +index ab77f80..1e406af 100644 +--- a/drivers/target/iscsi/iscsi_target_util.c ++++ b/drivers/target/iscsi/iscsi_target_util.c +@@ -1356,15 +1356,15 @@ static int iscsit_do_tx_data( + struct iscsi_conn *conn, + struct iscsi_data_count *count) + { +- int data = count->data_length, total_tx = 0, tx_loop = 0, iov_len; ++ int ret, iov_len; + struct kvec *iov_p; + struct msghdr msg; + + if (!conn || !conn->sock || !conn->conn_ops) + return -1; + +- if (data <= 0) { +- pr_err("Data length is: %d\n", data); ++ if (count->data_length <= 0) { ++ pr_err("Data length is: %d\n", count->data_length); + return -1; + } + +@@ -1373,20 +1373,16 @@ static int iscsit_do_tx_data( + iov_p = count->iov; + iov_len = count->iov_count; + +- while (total_tx < data) { +- tx_loop = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len, +- (data - total_tx)); +- if (tx_loop <= 0) { +- pr_debug("tx_loop: %d total_tx %d\n", +- tx_loop, total_tx); +- return tx_loop; +- } +- total_tx += tx_loop; +- pr_debug("tx_loop: %d, total_tx: %d, data: %d\n", +- tx_loop, total_tx, data); ++ ret = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len, ++ count->data_length); ++ if (ret != count->data_length) { ++ pr_err("Unexpected ret: %d send data %d\n", ++ ret, count->data_length); ++ return -EPIPE; + } ++ pr_debug("ret: %d, sent data: %d\n", ret, count->data_length); + +- return total_tx; ++ return ret; + } + + int rx_data( +diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c +index fadad7c..67c802c 100644 +--- a/drivers/target/loopback/tcm_loop.c ++++ b/drivers/target/loopback/tcm_loop.c +@@ -153,18 +153,11 @@ static int tcm_loop_change_queue_type(struct scsi_device *sdev, int tag) + /* + * Locate the SAM Task Attr from struct scsi_cmnd * + */ +-static int tcm_loop_sam_attr(struct scsi_cmnd *sc) +-{ +- if (sc->device->tagged_supported) { +- switch (sc->tag) { +- case HEAD_OF_QUEUE_TAG: +- return MSG_HEAD_TAG; +- case ORDERED_QUEUE_TAG: +- return MSG_ORDERED_TAG; +- default: +- break; +- } +- } ++static int tcm_loop_sam_attr(struct scsi_cmnd *sc, int tag) ++{ ++ if (sc->device->tagged_supported && ++ sc->device->ordered_tags && tag >= 0) ++ return MSG_ORDERED_TAG; + + return MSG_SIMPLE_TAG; + } +@@ -197,7 +190,7 @@ static void tcm_loop_submission_work(struct work_struct *work) + set_host_byte(sc, DID_TRANSPORT_DISRUPTED); + goto out_done; + } +- tl_nexus = tl_hba->tl_nexus; ++ tl_nexus = tl_tpg->tl_nexus; + if (!tl_nexus) { + scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus" + " does not exist\n"); +@@ -214,7 +207,7 @@ static void tcm_loop_submission_work(struct work_struct *work) + } + rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus->se_sess, sc->cmnd, + &tl_cmd->tl_sense_buf[0], tl_cmd->sc->device->lun, +- scsi_bufflen(sc), tcm_loop_sam_attr(sc), ++ scsi_bufflen(sc), tcm_loop_sam_attr(sc, tl_cmd->sc_cmd_tag), + sc->sc_data_direction, 0, + scsi_sglist(sc), scsi_sg_count(sc), + sgl_bidi, sgl_bidi_count, +@@ -252,7 +245,7 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc) + } + + tl_cmd->sc = sc; +- tl_cmd->sc_cmd_tag = sc->tag; ++ tl_cmd->sc_cmd_tag = sc->request->tag; + INIT_WORK(&tl_cmd->work, tcm_loop_submission_work); + queue_work(tcm_loop_workqueue, &tl_cmd->work); + return 0; +@@ -263,16 +256,26 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc) + * to struct scsi_device + */ + static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg, +- struct tcm_loop_nexus *tl_nexus, + int lun, int task, enum tcm_tmreq_table tmr) + { + struct se_cmd *se_cmd = NULL; + struct se_session *se_sess; + struct se_portal_group *se_tpg; ++ struct tcm_loop_nexus *tl_nexus; + struct tcm_loop_cmd *tl_cmd = NULL; + struct tcm_loop_tmr *tl_tmr = NULL; + int ret = TMR_FUNCTION_FAILED, rc; + ++ /* ++ * Locate the tl_nexus and se_sess pointers ++ */ ++ tl_nexus = tl_tpg->tl_nexus; ++ if (!tl_nexus) { ++ pr_err("Unable to perform device reset without" ++ " active I_T Nexus\n"); ++ return ret; ++ } ++ + tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_KERNEL); + if (!tl_cmd) { + pr_err("Unable to allocate memory for tl_cmd\n"); +@@ -288,7 +291,7 @@ static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg, + + se_cmd = &tl_cmd->tl_se_cmd; + se_tpg = &tl_tpg->tl_se_tpg; +- se_sess = tl_nexus->se_sess; ++ se_sess = tl_tpg->tl_nexus->se_sess; + /* + * Initialize struct se_cmd descriptor from target_core_mod infrastructure + */ +@@ -333,7 +336,6 @@ release: + static int tcm_loop_abort_task(struct scsi_cmnd *sc) + { + struct tcm_loop_hba *tl_hba; +- struct tcm_loop_nexus *tl_nexus; + struct tcm_loop_tpg *tl_tpg; + int ret = FAILED; + +@@ -341,22 +343,9 @@ static int tcm_loop_abort_task(struct scsi_cmnd *sc) + * Locate the tcm_loop_hba_t pointer + */ + tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); +- /* +- * Locate the tl_nexus and se_sess pointers +- */ +- tl_nexus = tl_hba->tl_nexus; +- if (!tl_nexus) { +- pr_err("Unable to perform device reset without" +- " active I_T Nexus\n"); +- return FAILED; +- } +- +- /* +- * Locate the tl_tpg pointer from TargetID in sc->device->id +- */ + tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; +- ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun, +- sc->tag, TMR_ABORT_TASK); ++ ret = tcm_loop_issue_tmr(tl_tpg, sc->device->lun, ++ sc->request->tag, TMR_ABORT_TASK); + return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED; + } + +@@ -367,7 +356,6 @@ static int tcm_loop_abort_task(struct scsi_cmnd *sc) + static int tcm_loop_device_reset(struct scsi_cmnd *sc) + { + struct tcm_loop_hba *tl_hba; +- struct tcm_loop_nexus *tl_nexus; + struct tcm_loop_tpg *tl_tpg; + int ret = FAILED; + +@@ -375,20 +363,9 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc) + * Locate the tcm_loop_hba_t pointer + */ + tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); +- /* +- * Locate the tl_nexus and se_sess pointers +- */ +- tl_nexus = tl_hba->tl_nexus; +- if (!tl_nexus) { +- pr_err("Unable to perform device reset without" +- " active I_T Nexus\n"); +- return FAILED; +- } +- /* +- * Locate the tl_tpg pointer from TargetID in sc->device->id +- */ + tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; +- ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun, ++ ++ ret = tcm_loop_issue_tmr(tl_tpg, sc->device->lun, + 0, TMR_LUN_RESET); + return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED; + } +@@ -995,8 +972,8 @@ static int tcm_loop_make_nexus( + struct tcm_loop_nexus *tl_nexus; + int ret = -ENOMEM; + +- if (tl_tpg->tl_hba->tl_nexus) { +- pr_debug("tl_tpg->tl_hba->tl_nexus already exists\n"); ++ if (tl_tpg->tl_nexus) { ++ pr_debug("tl_tpg->tl_nexus already exists\n"); + return -EEXIST; + } + se_tpg = &tl_tpg->tl_se_tpg; +@@ -1031,7 +1008,7 @@ static int tcm_loop_make_nexus( + */ + __transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl, + tl_nexus->se_sess, tl_nexus); +- tl_tpg->tl_hba->tl_nexus = tl_nexus; ++ tl_tpg->tl_nexus = tl_nexus; + pr_debug("TCM_Loop_ConfigFS: Established I_T Nexus to emulated" + " %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba), + name); +@@ -1047,12 +1024,8 @@ static int tcm_loop_drop_nexus( + { + struct se_session *se_sess; + struct tcm_loop_nexus *tl_nexus; +- struct tcm_loop_hba *tl_hba = tpg->tl_hba; + +- if (!tl_hba) +- return -ENODEV; +- +- tl_nexus = tl_hba->tl_nexus; ++ tl_nexus = tpg->tl_nexus; + if (!tl_nexus) + return -ENODEV; + +@@ -1068,13 +1041,13 @@ static int tcm_loop_drop_nexus( + } + + pr_debug("TCM_Loop_ConfigFS: Removing I_T Nexus to emulated" +- " %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba), ++ " %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tpg->tl_hba), + tl_nexus->se_sess->se_node_acl->initiatorname); + /* + * Release the SCSI I_T Nexus to the emulated SAS Target Port + */ + transport_deregister_session(tl_nexus->se_sess); +- tpg->tl_hba->tl_nexus = NULL; ++ tpg->tl_nexus = NULL; + kfree(tl_nexus); + return 0; + } +@@ -1090,7 +1063,7 @@ static ssize_t tcm_loop_tpg_show_nexus( + struct tcm_loop_nexus *tl_nexus; + ssize_t ret; + +- tl_nexus = tl_tpg->tl_hba->tl_nexus; ++ tl_nexus = tl_tpg->tl_nexus; + if (!tl_nexus) + return -ENODEV; + +diff --git a/drivers/target/loopback/tcm_loop.h b/drivers/target/loopback/tcm_loop.h +index 54c59d0..6ae49f2 100644 +--- a/drivers/target/loopback/tcm_loop.h ++++ b/drivers/target/loopback/tcm_loop.h +@@ -27,11 +27,6 @@ struct tcm_loop_tmr { + }; + + struct tcm_loop_nexus { +- int it_nexus_active; +- /* +- * Pointer to Linux/SCSI HBA from linux/include/scsi_host.h +- */ +- struct scsi_host *sh; + /* + * Pointer to TCM session for I_T Nexus + */ +@@ -51,6 +46,7 @@ struct tcm_loop_tpg { + atomic_t tl_tpg_port_count; + struct se_portal_group tl_se_tpg; + struct tcm_loop_hba *tl_hba; ++ struct tcm_loop_nexus *tl_nexus; + }; + + struct tcm_loop_hba { +@@ -59,7 +55,6 @@ struct tcm_loop_hba { + struct se_hba_s *se_hba; + struct se_lun *tl_hba_lun; + struct se_port *tl_hba_lun_sep; +- struct tcm_loop_nexus *tl_nexus; + struct device dev; + struct Scsi_Host *sh; + struct tcm_loop_tpg tl_hba_tpgs[TL_TPGS_PER_HBA]; +diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c +index 483d324..f303853 100644 +--- a/drivers/target/target_core_configfs.c ++++ b/drivers/target/target_core_configfs.c +@@ -2359,7 +2359,7 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_support_##_name(\ + pr_err("Invalid value '%ld', must be '0' or '1'\n", tmp); \ + return -EINVAL; \ + } \ +- if (!tmp) \ ++ if (tmp) \ + t->_var |= _bit; \ + else \ + t->_var &= ~_bit; \ +diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c +index 6ea95d2..093b8cb 100644 +--- a/drivers/target/target_core_device.c ++++ b/drivers/target/target_core_device.c +@@ -1153,10 +1153,10 @@ int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors) + " changed for TCM/pSCSI\n", dev); + return -EINVAL; + } +- if (optimal_sectors > dev->dev_attrib.fabric_max_sectors) { ++ if (optimal_sectors > dev->dev_attrib.hw_max_sectors) { + pr_err("dev[%p]: Passed optimal_sectors %u cannot be" +- " greater than fabric_max_sectors: %u\n", dev, +- optimal_sectors, dev->dev_attrib.fabric_max_sectors); ++ " greater than hw_max_sectors: %u\n", dev, ++ optimal_sectors, dev->dev_attrib.hw_max_sectors); + return -EINVAL; + } + +@@ -1409,7 +1409,8 @@ int core_dev_add_initiator_node_lun_acl( + * Check to see if there are any existing persistent reservation APTPL + * pre-registrations that need to be enabled for this LUN ACL.. + */ +- core_scsi3_check_aptpl_registration(lun->lun_se_dev, tpg, lun, lacl); ++ core_scsi3_check_aptpl_registration(lun->lun_se_dev, tpg, lun, nacl, ++ lacl->mapped_lun); + return 0; + } + +@@ -1564,7 +1565,6 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) + DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT; + dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN; + dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS; +- dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS; + + xcopy_lun = &dev->xcopy_lun; + xcopy_lun->lun_se_dev = dev; +@@ -1591,8 +1591,6 @@ int target_configure_device(struct se_device *dev) + ret = dev->transport->configure_device(dev); + if (ret) + goto out; +- dev->dev_flags |= DF_CONFIGURED; +- + /* + * XXX: there is not much point to have two different values here.. + */ +@@ -1605,6 +1603,7 @@ int target_configure_device(struct se_device *dev) + dev->dev_attrib.hw_max_sectors = + se_dev_align_max_sectors(dev->dev_attrib.hw_max_sectors, + dev->dev_attrib.hw_block_size); ++ dev->dev_attrib.optimal_sectors = dev->dev_attrib.hw_max_sectors; + + dev->dev_index = scsi_get_new_index(SCSI_DEVICE_INDEX); + dev->creation_time = get_jiffies_64(); +@@ -1653,6 +1652,8 @@ int target_configure_device(struct se_device *dev) + list_add_tail(&dev->g_dev_node, &g_device_list); + mutex_unlock(&g_device_mutex); + ++ dev->dev_flags |= DF_CONFIGURED; ++ + return 0; + + out_free_alua: +diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c +index cf991a9..b199f1e 100644 +--- a/drivers/target/target_core_file.c ++++ b/drivers/target/target_core_file.c +@@ -263,40 +263,32 @@ static int fd_do_prot_rw(struct se_cmd *cmd, struct fd_prot *fd_prot, + struct se_device *se_dev = cmd->se_dev; + struct fd_dev *dev = FD_DEV(se_dev); + struct file *prot_fd = dev->fd_prot_file; +- struct scatterlist *sg; + loff_t pos = (cmd->t_task_lba * se_dev->prot_length); + unsigned char *buf; +- u32 prot_size, len, size; +- int rc, ret = 1, i; ++ u32 prot_size; ++ int rc, ret = 1; + + prot_size = (cmd->data_length / se_dev->dev_attrib.block_size) * + se_dev->prot_length; + + if (!is_write) { +- fd_prot->prot_buf = vzalloc(prot_size); ++ fd_prot->prot_buf = kzalloc(prot_size, GFP_KERNEL); + if (!fd_prot->prot_buf) { + pr_err("Unable to allocate fd_prot->prot_buf\n"); + return -ENOMEM; + } + buf = fd_prot->prot_buf; + +- fd_prot->prot_sg_nents = cmd->t_prot_nents; +- fd_prot->prot_sg = kzalloc(sizeof(struct scatterlist) * +- fd_prot->prot_sg_nents, GFP_KERNEL); ++ fd_prot->prot_sg_nents = 1; ++ fd_prot->prot_sg = kzalloc(sizeof(struct scatterlist), ++ GFP_KERNEL); + if (!fd_prot->prot_sg) { + pr_err("Unable to allocate fd_prot->prot_sg\n"); +- vfree(fd_prot->prot_buf); ++ kfree(fd_prot->prot_buf); + return -ENOMEM; + } +- size = prot_size; +- +- for_each_sg(fd_prot->prot_sg, sg, fd_prot->prot_sg_nents, i) { +- +- len = min_t(u32, PAGE_SIZE, size); +- sg_set_buf(sg, buf, len); +- size -= len; +- buf += len; +- } ++ sg_init_table(fd_prot->prot_sg, fd_prot->prot_sg_nents); ++ sg_set_buf(fd_prot->prot_sg, buf, prot_size); + } + + if (is_write) { +@@ -317,7 +309,7 @@ static int fd_do_prot_rw(struct se_cmd *cmd, struct fd_prot *fd_prot, + + if (is_write || ret < 0) { + kfree(fd_prot->prot_sg); +- vfree(fd_prot->prot_buf); ++ kfree(fd_prot->prot_buf); + } + + return ret; +@@ -620,7 +612,16 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, + struct fd_prot fd_prot; + sense_reason_t rc; + int ret = 0; +- ++ /* ++ * We are currently limited by the number of iovecs (2048) per ++ * single vfs_[writev,readv] call. ++ */ ++ if (cmd->data_length > FD_MAX_BYTES) { ++ pr_err("FILEIO: Not able to process I/O of %u bytes due to" ++ "FD_MAX_BYTES: %u iovec count limitiation\n", ++ cmd->data_length, FD_MAX_BYTES); ++ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; ++ } + /* + * Call vectorized fileio functions to map struct scatterlist + * physical memory addresses to struct iovec virtual memory. +@@ -643,11 +644,11 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, + 0, fd_prot.prot_sg, 0); + if (rc) { + kfree(fd_prot.prot_sg); +- vfree(fd_prot.prot_buf); ++ kfree(fd_prot.prot_buf); + return rc; + } + kfree(fd_prot.prot_sg); +- vfree(fd_prot.prot_buf); ++ kfree(fd_prot.prot_buf); + } + } else { + memset(&fd_prot, 0, sizeof(struct fd_prot)); +@@ -663,7 +664,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, + 0, fd_prot.prot_sg, 0); + if (rc) { + kfree(fd_prot.prot_sg); +- vfree(fd_prot.prot_buf); ++ kfree(fd_prot.prot_buf); + return rc; + } + } +@@ -694,7 +695,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, + + if (ret < 0) { + kfree(fd_prot.prot_sg); +- vfree(fd_prot.prot_buf); ++ kfree(fd_prot.prot_buf); + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + +diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c +index 9e0232c..feefe24 100644 +--- a/drivers/target/target_core_iblock.c ++++ b/drivers/target/target_core_iblock.c +@@ -123,7 +123,7 @@ static int iblock_configure_device(struct se_device *dev) + q = bdev_get_queue(bd); + + dev->dev_attrib.hw_block_size = bdev_logical_block_size(bd); +- dev->dev_attrib.hw_max_sectors = UINT_MAX; ++ dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q); + dev->dev_attrib.hw_queue_depth = q->nr_requests; + + /* +diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c +index 3013287..70cb375 100644 +--- a/drivers/target/target_core_pr.c ++++ b/drivers/target/target_core_pr.c +@@ -76,7 +76,7 @@ enum preempt_type { + }; + + static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, +- struct t10_pr_registration *, int); ++ struct t10_pr_registration *, int, int); + + static sense_reason_t + target_scsi2_reservation_check(struct se_cmd *cmd) +@@ -528,6 +528,18 @@ static int core_scsi3_pr_seq_non_holder( + + return 0; + } ++ } else if (we && registered_nexus) { ++ /* ++ * Reads are allowed for Write Exclusive locks ++ * from all registrants. ++ */ ++ if (cmd->data_direction == DMA_FROM_DEVICE) { ++ pr_debug("Allowing READ CDB: 0x%02x for %s" ++ " reservation\n", cdb[0], ++ core_scsi3_pr_dump_type(pr_reg_type)); ++ ++ return 0; ++ } + } + pr_debug("%s Conflict for %sregistered nexus %s CDB: 0x%2x" + " for %s reservation\n", transport_dump_cmd_direction(cmd), +@@ -944,10 +956,10 @@ int core_scsi3_check_aptpl_registration( + struct se_device *dev, + struct se_portal_group *tpg, + struct se_lun *lun, +- struct se_lun_acl *lun_acl) ++ struct se_node_acl *nacl, ++ u32 mapped_lun) + { +- struct se_node_acl *nacl = lun_acl->se_lun_nacl; +- struct se_dev_entry *deve = nacl->device_list[lun_acl->mapped_lun]; ++ struct se_dev_entry *deve = nacl->device_list[mapped_lun]; + + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) + return 0; +@@ -1186,7 +1198,7 @@ static int core_scsi3_check_implicit_release( + * service action with the SERVICE ACTION RESERVATION KEY + * field set to zero (see 5.7.11.3). + */ +- __core_scsi3_complete_pro_release(dev, nacl, pr_reg, 0); ++ __core_scsi3_complete_pro_release(dev, nacl, pr_reg, 0, 1); + ret = 1; + /* + * For 'All Registrants' reservation types, all existing +@@ -1228,7 +1240,8 @@ static void __core_scsi3_free_registration( + + pr_reg->pr_reg_deve->def_pr_registered = 0; + pr_reg->pr_reg_deve->pr_res_key = 0; +- list_del(&pr_reg->pr_reg_list); ++ if (!list_empty(&pr_reg->pr_reg_list)) ++ list_del(&pr_reg->pr_reg_list); + /* + * Caller accessing *pr_reg using core_scsi3_locate_pr_reg(), + * so call core_scsi3_put_pr_reg() to decrement our reference. +@@ -1280,6 +1293,7 @@ void core_scsi3_free_pr_reg_from_nacl( + { + struct t10_reservation *pr_tmpl = &dev->t10_pr; + struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder; ++ bool free_reg = false; + /* + * If the passed se_node_acl matches the reservation holder, + * release the reservation. +@@ -1287,13 +1301,18 @@ void core_scsi3_free_pr_reg_from_nacl( + spin_lock(&dev->dev_reservation_lock); + pr_res_holder = dev->dev_pr_res_holder; + if ((pr_res_holder != NULL) && +- (pr_res_holder->pr_reg_nacl == nacl)) +- __core_scsi3_complete_pro_release(dev, nacl, pr_res_holder, 0); ++ (pr_res_holder->pr_reg_nacl == nacl)) { ++ __core_scsi3_complete_pro_release(dev, nacl, pr_res_holder, 0, 1); ++ free_reg = true; ++ } + spin_unlock(&dev->dev_reservation_lock); + /* + * Release any registration associated with the struct se_node_acl. + */ + spin_lock(&pr_tmpl->registration_lock); ++ if (pr_res_holder && free_reg) ++ __core_scsi3_free_registration(dev, pr_res_holder, NULL, 0); ++ + list_for_each_entry_safe(pr_reg, pr_reg_tmp, + &pr_tmpl->registration_list, pr_reg_list) { + +@@ -1316,7 +1335,7 @@ void core_scsi3_free_all_registrations( + if (pr_res_holder != NULL) { + struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl; + __core_scsi3_complete_pro_release(dev, pr_res_nacl, +- pr_res_holder, 0); ++ pr_res_holder, 0, 0); + } + spin_unlock(&dev->dev_reservation_lock); + +@@ -1877,8 +1896,8 @@ static int core_scsi3_update_aptpl_buf( + } + + if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { +- pr_err("Unable to update renaming" +- " APTPL metadata\n"); ++ pr_err("Unable to update renaming APTPL metadata," ++ " reallocating larger buffer\n"); + ret = -EMSGSIZE; + goto out; + } +@@ -1895,8 +1914,8 @@ static int core_scsi3_update_aptpl_buf( + lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count); + + if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { +- pr_err("Unable to update renaming" +- " APTPL metadata\n"); ++ pr_err("Unable to update renaming APTPL metadata," ++ " reallocating larger buffer\n"); + ret = -EMSGSIZE; + goto out; + } +@@ -1959,7 +1978,7 @@ static int __core_scsi3_write_aptpl_to_file( + static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, bool aptpl) + { + unsigned char *buf; +- int rc; ++ int rc, len = PR_APTPL_BUF_LEN; + + if (!aptpl) { + char *null_buf = "No Registrations or Reservations\n"; +@@ -1973,25 +1992,26 @@ static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, b + + return 0; + } +- +- buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL); ++retry: ++ buf = vzalloc(len); + if (!buf) + return TCM_OUT_OF_RESOURCES; + +- rc = core_scsi3_update_aptpl_buf(dev, buf, PR_APTPL_BUF_LEN); ++ rc = core_scsi3_update_aptpl_buf(dev, buf, len); + if (rc < 0) { +- kfree(buf); +- return TCM_OUT_OF_RESOURCES; ++ vfree(buf); ++ len *= 2; ++ goto retry; + } + + rc = __core_scsi3_write_aptpl_to_file(dev, buf); + if (rc != 0) { + pr_err("SPC-3 PR: Could not update APTPL\n"); +- kfree(buf); ++ vfree(buf); + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + dev->t10_pr.pr_aptpl_active = 1; +- kfree(buf); ++ vfree(buf); + pr_debug("SPC-3 PR: Set APTPL Bit Activated\n"); + return 0; + } +@@ -2125,13 +2145,13 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, + /* + * sa_res_key=0 Unregister Reservation Key for registered I_T Nexus. + */ +- pr_holder = core_scsi3_check_implicit_release( +- cmd->se_dev, pr_reg); ++ type = pr_reg->pr_res_type; ++ pr_holder = core_scsi3_check_implicit_release(cmd->se_dev, ++ pr_reg); + if (pr_holder < 0) { + ret = TCM_RESERVATION_CONFLICT; + goto out; + } +- type = pr_reg->pr_res_type; + + spin_lock(&pr_tmpl->registration_lock); + /* +@@ -2289,6 +2309,7 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) + spin_lock(&dev->dev_reservation_lock); + pr_res_holder = dev->dev_pr_res_holder; + if (pr_res_holder) { ++ int pr_res_type = pr_res_holder->pr_res_type; + /* + * From spc4r17 Section 5.7.9: Reserving: + * +@@ -2299,7 +2320,9 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) + * the logical unit, then the command shall be completed with + * RESERVATION CONFLICT status. + */ +- if (pr_res_holder != pr_reg) { ++ if ((pr_res_holder != pr_reg) && ++ (pr_res_type != PR_TYPE_WRITE_EXCLUSIVE_ALLREG) && ++ (pr_res_type != PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) { + struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl; + pr_err("SPC-3 PR: Attempted RESERVE from" + " [%s]: %s while reservation already held by" +@@ -2405,23 +2428,59 @@ static void __core_scsi3_complete_pro_release( + struct se_device *dev, + struct se_node_acl *se_nacl, + struct t10_pr_registration *pr_reg, +- int explicit) ++ int explicit, ++ int unreg) + { + struct target_core_fabric_ops *tfo = se_nacl->se_tpg->se_tpg_tfo; + char i_buf[PR_REG_ISID_ID_LEN]; ++ int pr_res_type = 0, pr_res_scope = 0; + + memset(i_buf, 0, PR_REG_ISID_ID_LEN); + core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); + /* + * Go ahead and release the current PR reservation holder. ++ * If an All Registrants reservation is currently active and ++ * a unregister operation is requested, replace the current ++ * dev_pr_res_holder with another active registration. + */ +- dev->dev_pr_res_holder = NULL; ++ if (dev->dev_pr_res_holder) { ++ pr_res_type = dev->dev_pr_res_holder->pr_res_type; ++ pr_res_scope = dev->dev_pr_res_holder->pr_res_scope; ++ dev->dev_pr_res_holder->pr_res_type = 0; ++ dev->dev_pr_res_holder->pr_res_scope = 0; ++ dev->dev_pr_res_holder->pr_res_holder = 0; ++ dev->dev_pr_res_holder = NULL; ++ } ++ if (!unreg) ++ goto out; + +- pr_debug("SPC-3 PR [%s] Service Action: %s RELEASE cleared" +- " reservation holder TYPE: %s ALL_TG_PT: %d\n", +- tfo->get_fabric_name(), (explicit) ? "explicit" : "implicit", +- core_scsi3_pr_dump_type(pr_reg->pr_res_type), +- (pr_reg->pr_reg_all_tg_pt) ? 1 : 0); ++ spin_lock(&dev->t10_pr.registration_lock); ++ list_del_init(&pr_reg->pr_reg_list); ++ /* ++ * If the I_T nexus is a reservation holder, the persistent reservation ++ * is of an all registrants type, and the I_T nexus is the last remaining ++ * registered I_T nexus, then the device server shall also release the ++ * persistent reservation. ++ */ ++ if (!list_empty(&dev->t10_pr.registration_list) && ++ ((pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) || ++ (pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG))) { ++ dev->dev_pr_res_holder = ++ list_entry(dev->t10_pr.registration_list.next, ++ struct t10_pr_registration, pr_reg_list); ++ dev->dev_pr_res_holder->pr_res_type = pr_res_type; ++ dev->dev_pr_res_holder->pr_res_scope = pr_res_scope; ++ dev->dev_pr_res_holder->pr_res_holder = 1; ++ } ++ spin_unlock(&dev->t10_pr.registration_lock); ++out: ++ if (!dev->dev_pr_res_holder) { ++ pr_debug("SPC-3 PR [%s] Service Action: %s RELEASE cleared" ++ " reservation holder TYPE: %s ALL_TG_PT: %d\n", ++ tfo->get_fabric_name(), (explicit) ? "explicit" : ++ "implicit", core_scsi3_pr_dump_type(pr_res_type), ++ (pr_reg->pr_reg_all_tg_pt) ? 1 : 0); ++ } + pr_debug("SPC-3 PR [%s] RELEASE Node: %s%s\n", + tfo->get_fabric_name(), se_nacl->initiatorname, + i_buf); +@@ -2552,7 +2611,7 @@ core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope, + * server shall not establish a unit attention condition. + */ + __core_scsi3_complete_pro_release(dev, se_sess->se_node_acl, +- pr_reg, 1); ++ pr_reg, 1, 0); + + spin_unlock(&dev->dev_reservation_lock); + +@@ -2640,7 +2699,7 @@ core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key) + if (pr_res_holder) { + struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl; + __core_scsi3_complete_pro_release(dev, pr_res_nacl, +- pr_res_holder, 0); ++ pr_res_holder, 0, 0); + } + spin_unlock(&dev->dev_reservation_lock); + /* +@@ -2699,7 +2758,7 @@ static void __core_scsi3_complete_pro_preempt( + */ + if (dev->dev_pr_res_holder) + __core_scsi3_complete_pro_release(dev, nacl, +- dev->dev_pr_res_holder, 0); ++ dev->dev_pr_res_holder, 0, 0); + + dev->dev_pr_res_holder = pr_reg; + pr_reg->pr_res_holder = 1; +@@ -2943,8 +3002,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, + */ + if (pr_reg_n != pr_res_holder) + __core_scsi3_complete_pro_release(dev, +- pr_res_holder->pr_reg_nacl, +- dev->dev_pr_res_holder, 0); ++ pr_res_holder->pr_reg_nacl, ++ dev->dev_pr_res_holder, 0, 0); + /* + * b) Remove the registrations for all I_T nexuses identified + * by the SERVICE ACTION RESERVATION KEY field, except the +@@ -3414,7 +3473,7 @@ after_iport_check: + * holder (i.e., the I_T nexus on which the + */ + __core_scsi3_complete_pro_release(dev, pr_res_nacl, +- dev->dev_pr_res_holder, 0); ++ dev->dev_pr_res_holder, 0, 0); + /* + * g) Move the persistent reservation to the specified I_T nexus using + * the same scope and type as the persistent reservation released in +@@ -3854,7 +3913,8 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) + unsigned char *buf; + u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len; + u32 off = 8; /* off into first Full Status descriptor */ +- int format_code = 0; ++ int format_code = 0, pr_res_type = 0, pr_res_scope = 0; ++ bool all_reg = false; + + if (cmd->data_length < 8) { + pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u" +@@ -3871,6 +3931,19 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) + buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); + buf[3] = (dev->t10_pr.pr_generation & 0xff); + ++ spin_lock(&dev->dev_reservation_lock); ++ if (dev->dev_pr_res_holder) { ++ struct t10_pr_registration *pr_holder = dev->dev_pr_res_holder; ++ ++ if (pr_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG || ++ pr_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG) { ++ all_reg = true; ++ pr_res_type = pr_holder->pr_res_type; ++ pr_res_scope = pr_holder->pr_res_scope; ++ } ++ } ++ spin_unlock(&dev->dev_reservation_lock); ++ + spin_lock(&pr_tmpl->registration_lock); + list_for_each_entry_safe(pr_reg, pr_reg_tmp, + &pr_tmpl->registration_list, pr_reg_list) { +@@ -3920,14 +3993,20 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) + * reservation holder for PR_HOLDER bit. + * + * Also, if this registration is the reservation +- * holder, fill in SCOPE and TYPE in the next byte. ++ * holder or there is an All Registrants reservation ++ * active, fill in SCOPE and TYPE in the next byte. + */ + if (pr_reg->pr_res_holder) { + buf[off++] |= 0x01; + buf[off++] = (pr_reg->pr_res_scope & 0xf0) | + (pr_reg->pr_res_type & 0x0f); +- } else ++ } else if (all_reg) { ++ buf[off++] |= 0x01; ++ buf[off++] = (pr_res_scope & 0xf0) | ++ (pr_res_type & 0x0f); ++ } else { + off += 2; ++ } + + off += 4; /* Skip over reserved area */ + /* +diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h +index 2ee2936..749fd7b 100644 +--- a/drivers/target/target_core_pr.h ++++ b/drivers/target/target_core_pr.h +@@ -60,7 +60,7 @@ extern int core_scsi3_alloc_aptpl_registration( + unsigned char *, u16, u32, int, int, u8); + extern int core_scsi3_check_aptpl_registration(struct se_device *, + struct se_portal_group *, struct se_lun *, +- struct se_lun_acl *); ++ struct se_node_acl *, u32); + extern void core_scsi3_free_pr_reg_from_nacl(struct se_device *, + struct se_node_acl *); + extern void core_scsi3_free_all_registrations(struct se_device *); +diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c +index 0f199f6..9b90cfa 100644 +--- a/drivers/target/target_core_pscsi.c ++++ b/drivers/target/target_core_pscsi.c +@@ -520,6 +520,7 @@ static int pscsi_configure_device(struct se_device *dev) + " pdv_host_id: %d\n", pdv->pdv_host_id); + return -EINVAL; + } ++ pdv->pdv_lld_host = sh; + } + } else { + if (phv->phv_mode == PHV_VIRTUAL_HOST_ID) { +@@ -602,6 +603,8 @@ static void pscsi_free_device(struct se_device *dev) + if ((phv->phv_mode == PHV_LLD_SCSI_HOST_NO) && + (phv->phv_lld_host != NULL)) + scsi_host_put(phv->phv_lld_host); ++ else if (pdv->pdv_lld_host) ++ scsi_host_put(pdv->pdv_lld_host); + + if ((sd->type == TYPE_DISK) || (sd->type == TYPE_ROM)) + scsi_device_put(sd); +@@ -1111,7 +1114,7 @@ static u32 pscsi_get_device_type(struct se_device *dev) + struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); + struct scsi_device *sd = pdv->pdv_sd; + +- return sd->type; ++ return (sd) ? sd->type : TYPE_NO_LUN; + } + + static sector_t pscsi_get_blocks(struct se_device *dev) +diff --git a/drivers/target/target_core_pscsi.h b/drivers/target/target_core_pscsi.h +index 1bd757d..820d305 100644 +--- a/drivers/target/target_core_pscsi.h ++++ b/drivers/target/target_core_pscsi.h +@@ -45,6 +45,7 @@ struct pscsi_dev_virt { + int pdv_lun_id; + struct block_device *pdv_bd; + struct scsi_device *pdv_sd; ++ struct Scsi_Host *pdv_lld_host; + } ____cacheline_aligned; + + typedef enum phv_modes { +diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c +index 379033f..f89b24a 100644 +--- a/drivers/target/target_core_sbc.c ++++ b/drivers/target/target_core_sbc.c +@@ -266,6 +266,8 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb) + static sense_reason_t + sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops) + { ++ struct se_device *dev = cmd->se_dev; ++ sector_t end_lba = dev->transport->get_blocks(dev) + 1; + unsigned int sectors = sbc_get_write_same_sectors(cmd); + + if ((flags[0] & 0x04) || (flags[0] & 0x02)) { +@@ -279,6 +281,16 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o + sectors, cmd->se_dev->dev_attrib.max_write_same_len); + return TCM_INVALID_CDB_FIELD; + } ++ /* ++ * Sanity check for LBA wrap and request past end of device. ++ */ ++ if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) || ++ ((cmd->t_task_lba + sectors) > end_lba)) { ++ pr_err("WRITE_SAME exceeds last lba %llu (lba %llu, sectors %u)\n", ++ (unsigned long long)end_lba, cmd->t_task_lba, sectors); ++ return TCM_ADDRESS_OUT_OF_RANGE; ++ } ++ + /* We always have ANC_SUP == 0 so setting ANCHOR is always an error */ + if (flags[0] & 0x10) { + pr_warn("WRITE SAME with ANCHOR not supported\n"); +@@ -302,7 +314,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o + return 0; + } + +-static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd) ++static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd, bool success) + { + unsigned char *buf, *addr; + struct scatterlist *sg; +@@ -366,7 +378,7 @@ sbc_execute_rw(struct se_cmd *cmd) + cmd->data_direction); + } + +-static sense_reason_t compare_and_write_post(struct se_cmd *cmd) ++static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success) + { + struct se_device *dev = cmd->se_dev; + +@@ -389,7 +401,7 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd) + return TCM_NO_SENSE; + } + +-static sense_reason_t compare_and_write_callback(struct se_cmd *cmd) ++static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool success) + { + struct se_device *dev = cmd->se_dev; + struct scatterlist *write_sg = NULL, *sg; +@@ -404,11 +416,16 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd) + + /* + * Handle early failure in transport_generic_request_failure(), +- * which will not have taken ->caw_mutex yet.. ++ * which will not have taken ->caw_sem yet.. + */ +- if (!cmd->t_data_sg || !cmd->t_bidi_data_sg) ++ if (!success && (!cmd->t_data_sg || !cmd->t_bidi_data_sg)) + return TCM_NO_SENSE; + /* ++ * Handle special case for zero-length COMPARE_AND_WRITE ++ */ ++ if (!cmd->data_length) ++ goto out; ++ /* + * Immediately exit + release dev->caw_sem if command has already + * been failed with a non-zero SCSI status. + */ +@@ -910,23 +927,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) + if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { + unsigned long long end_lba; + +- if (sectors > dev->dev_attrib.fabric_max_sectors) { +- printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" +- " big sectors %u exceeds fabric_max_sectors:" +- " %u\n", cdb[0], sectors, +- dev->dev_attrib.fabric_max_sectors); +- return TCM_INVALID_CDB_FIELD; +- } +- if (sectors > dev->dev_attrib.hw_max_sectors) { +- printk_ratelimited(KERN_ERR "SCSI OP %02xh with too" +- " big sectors %u exceeds backend hw_max_sectors:" +- " %u\n", cdb[0], sectors, +- dev->dev_attrib.hw_max_sectors); +- return TCM_INVALID_CDB_FIELD; +- } +- + end_lba = dev->transport->get_blocks(dev) + 1; +- if (cmd->t_task_lba + sectors > end_lba) { ++ if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) || ++ ((cmd->t_task_lba + sectors) > end_lba)) { + pr_err("cmd exceeds last lba %llu " + "(lba %llu, sectors %u)\n", + end_lba, cmd->t_task_lba, sectors); +diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c +index fcdf98f..12a74f6 100644 +--- a/drivers/target/target_core_spc.c ++++ b/drivers/target/target_core_spc.c +@@ -503,7 +503,6 @@ static sense_reason_t + spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) + { + struct se_device *dev = cmd->se_dev; +- u32 max_sectors; + int have_tp = 0; + int opt, min; + +@@ -537,9 +536,7 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) + /* + * Set MAXIMUM TRANSFER LENGTH + */ +- max_sectors = min(dev->dev_attrib.fabric_max_sectors, +- dev->dev_attrib.hw_max_sectors); +- put_unaligned_be32(max_sectors, &buf[8]); ++ put_unaligned_be32(dev->dev_attrib.hw_max_sectors, &buf[8]); + + /* + * Set OPTIMAL TRANSFER LENGTH +diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c +index c036595..fb8a1a1 100644 +--- a/drivers/target/target_core_tpg.c ++++ b/drivers/target/target_core_tpg.c +@@ -40,6 +40,7 @@ + #include + + #include "target_core_internal.h" ++#include "target_core_pr.h" + + extern struct se_device *g_lun0_dev; + +@@ -166,6 +167,13 @@ void core_tpg_add_node_to_devs( + + core_enable_device_list_for_node(lun, NULL, lun->unpacked_lun, + lun_access, acl, tpg); ++ /* ++ * Check to see if there are any existing persistent reservation ++ * APTPL pre-registrations that need to be enabled for this dynamic ++ * LUN ACL now.. ++ */ ++ core_scsi3_check_aptpl_registration(dev, tpg, lun, acl, ++ lun->unpacked_lun); + spin_lock(&tpg->tpg_lun_lock); + } + spin_unlock(&tpg->tpg_lun_lock); +diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c +index 24f5279..6fc3890 100644 +--- a/drivers/target/target_core_transport.c ++++ b/drivers/target/target_core_transport.c +@@ -1600,11 +1600,11 @@ void transport_generic_request_failure(struct se_cmd *cmd, + transport_complete_task_attr(cmd); + /* + * Handle special case for COMPARE_AND_WRITE failure, where the +- * callback is expected to drop the per device ->caw_mutex. ++ * callback is expected to drop the per device ->caw_sem. + */ + if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) && + cmd->transport_complete_callback) +- cmd->transport_complete_callback(cmd); ++ cmd->transport_complete_callback(cmd, false); + + switch (sense_reason) { + case TCM_NON_EXISTENT_LUN: +@@ -1855,8 +1855,7 @@ static void transport_complete_qf(struct se_cmd *cmd) + if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { + trace_target_cmd_complete(cmd); + ret = cmd->se_tfo->queue_status(cmd); +- if (ret) +- goto out; ++ goto out; + } + + switch (cmd->data_direction) { +@@ -1942,8 +1941,12 @@ static void target_complete_ok_work(struct work_struct *work) + if (cmd->transport_complete_callback) { + sense_reason_t rc; + +- rc = cmd->transport_complete_callback(cmd); ++ rc = cmd->transport_complete_callback(cmd, true); + if (!rc && !(cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE_POST)) { ++ if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) && ++ !cmd->data_length) ++ goto queue_rsp; ++ + return; + } else if (rc) { + ret = transport_send_check_condition_and_sense(cmd, +@@ -1957,6 +1960,7 @@ static void target_complete_ok_work(struct work_struct *work) + } + } + ++queue_rsp: + switch (cmd->data_direction) { + case DMA_FROM_DEVICE: + spin_lock(&cmd->se_lun->lun_sep_lock); +@@ -2045,6 +2049,16 @@ static inline void transport_reset_sgl_orig(struct se_cmd *cmd) + static inline void transport_free_pages(struct se_cmd *cmd) + { + if (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) { ++ /* ++ * Release special case READ buffer payload required for ++ * SG_TO_MEM_NOALLOC to function with COMPARE_AND_WRITE ++ */ ++ if (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) { ++ transport_free_sgl(cmd->t_bidi_data_sg, ++ cmd->t_bidi_data_nents); ++ cmd->t_bidi_data_sg = NULL; ++ cmd->t_bidi_data_nents = 0; ++ } + transport_reset_sgl_orig(cmd); + return; + } +@@ -2193,6 +2207,7 @@ sense_reason_t + transport_generic_new_cmd(struct se_cmd *cmd) + { + int ret = 0; ++ bool zero_flag = !(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB); + + /* + * Determine is the TCM fabric module has already allocated physical +@@ -2201,7 +2216,6 @@ transport_generic_new_cmd(struct se_cmd *cmd) + */ + if (!(cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) && + cmd->data_length) { +- bool zero_flag = !(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB); + + if ((cmd->se_cmd_flags & SCF_BIDI) || + (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE)) { +@@ -2224,6 +2238,20 @@ transport_generic_new_cmd(struct se_cmd *cmd) + cmd->data_length, zero_flag); + if (ret < 0) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; ++ } else if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) && ++ cmd->data_length) { ++ /* ++ * Special case for COMPARE_AND_WRITE with fabrics ++ * using SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC. ++ */ ++ u32 caw_length = cmd->t_task_nolb * ++ cmd->se_dev->dev_attrib.block_size; ++ ++ ret = target_alloc_sgl(&cmd->t_bidi_data_sg, ++ &cmd->t_bidi_data_nents, ++ caw_length, zero_flag); ++ if (ret < 0) ++ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + /* + * If this command is not a write we can execute it right here, +@@ -2231,7 +2259,7 @@ transport_generic_new_cmd(struct se_cmd *cmd) + * and let it call back once the write buffers are ready. + */ + target_add_to_state_list(cmd); +- if (cmd->data_direction != DMA_TO_DEVICE) { ++ if (cmd->data_direction != DMA_TO_DEVICE || cmd->data_length == 0) { + target_execute_cmd(cmd); + return 0; + } +@@ -2328,6 +2356,10 @@ int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd, + list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list); + out: + spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); ++ ++ if (ret && ack_kref) ++ target_put_sess_cmd(se_sess, se_cmd); ++ + return ret; + } + EXPORT_SYMBOL(target_get_sess_cmd); +diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c +index e415af3..c67d379 100644 +--- a/drivers/target/tcm_fc/tfc_io.c ++++ b/drivers/target/tcm_fc/tfc_io.c +@@ -346,7 +346,7 @@ void ft_invl_hw_context(struct ft_cmd *cmd) + ep = fc_seq_exch(seq); + if (ep) { + lport = ep->lp; +- if (lport && (ep->xid <= lport->lro_xid)) ++ if (lport && (ep->xid <= lport->lro_xid)) { + /* + * "ddp_done" trigger invalidation of HW + * specific DDP context +@@ -361,6 +361,7 @@ void ft_invl_hw_context(struct ft_cmd *cmd) + * identified using ep->xid) + */ + cmd->was_ddp_setup = 0; ++ } + } + } + } +diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c +index a084325..6e75177 100644 +--- a/drivers/thermal/intel_powerclamp.c ++++ b/drivers/thermal/intel_powerclamp.c +@@ -435,7 +435,6 @@ static int clamp_thread(void *arg) + * allowed. thus jiffies are updated properly. + */ + preempt_disable(); +- tick_nohz_idle_enter(); + /* mwait until target jiffies is reached */ + while (time_before(jiffies, target_jiffies)) { + unsigned long ecx = 1; +@@ -451,7 +450,6 @@ static int clamp_thread(void *arg) + start_critical_timings(); + atomic_inc(&idle_wakeup_counter); + } +- tick_nohz_idle_exit(); + preempt_enable(); + } + del_timer_sync(&wakeup_timer); +diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c +index 4db78ea..8a6f06b 100644 +--- a/drivers/thermal/step_wise.c ++++ b/drivers/thermal/step_wise.c +@@ -79,7 +79,7 @@ static unsigned long get_target_state(struct thermal_instance *instance, + dev_dbg(&cdev->device, "THERMAL_TREND_RAISE_FULL: next_target=%ld\n", next_target); + break; + case THERMAL_TREND_DROPPING: +- if (cur_state == instance->lower) { ++ if (cur_state <= instance->lower) { + if (!throttle) + next_target = THERMAL_NO_TARGET; + } else { +@@ -153,9 +153,6 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) + dev_dbg(&instance->cdev->device, "old_target=%ld, target=%ld\n", + old_target, instance->target); + +- if (old_target == instance->target) +- continue; +- + /* Activate a passive thermal instance */ + if (old_target == THERMAL_NO_TARGET && + instance->target != THERMAL_NO_TARGET) +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index 691c756..0821074 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -1830,10 +1830,10 @@ static int __init thermal_init(void) + + exit_netlink: + genetlink_exit(); +-unregister_governors: +- thermal_unregister_governors(); + unregister_class: + class_unregister(&thermal_class); ++unregister_governors: ++ thermal_unregister_governors(); + error: + idr_destroy(&thermal_tz_idr); + idr_destroy(&thermal_cdev_idr); +diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c +index 2dc2831..59a7da7 100644 +--- a/drivers/tty/hvc/hvc_xen.c ++++ b/drivers/tty/hvc/hvc_xen.c +@@ -289,7 +289,7 @@ static int xen_initial_domain_console_init(void) + return -ENOMEM; + } + +- info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0); ++ info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false); + info->vtermno = HVC_COOKIE; + + spin_lock(&xencons_lock); +@@ -299,11 +299,27 @@ static int xen_initial_domain_console_init(void) + return 0; + } + ++static void xen_console_update_evtchn(struct xencons_info *info) ++{ ++ if (xen_hvm_domain()) { ++ uint64_t v; ++ int err; ++ ++ err = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v); ++ if (!err && v) ++ info->evtchn = v; ++ } else ++ info->evtchn = xen_start_info->console.domU.evtchn; ++} ++ + void xen_console_resume(void) + { + struct xencons_info *info = vtermno_to_xencons(HVC_COOKIE); +- if (info != NULL && info->irq) ++ if (info != NULL && info->irq) { ++ if (!xen_initial_domain()) ++ xen_console_update_evtchn(info); + rebind_evtchn_irq(info->evtchn, info->irq); ++ } + } + + static void xencons_disconnect_backend(struct xencons_info *info) +diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c +index 2ebe47b..5bfd807 100644 +--- a/drivers/tty/n_gsm.c ++++ b/drivers/tty/n_gsm.c +@@ -3166,7 +3166,7 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state) + return gsmtty_modem_update(dlci, encode); + } + +-static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty) ++static void gsmtty_cleanup(struct tty_struct *tty) + { + struct gsm_dlci *dlci = tty->driver_data; + struct gsm_mux *gsm = dlci->gsm; +@@ -3174,7 +3174,6 @@ static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty) + dlci_put(dlci); + dlci_put(gsm->dlci[0]); + mux_put(gsm); +- driver->ttys[tty->index] = NULL; + } + + /* Virtual ttys for the demux */ +@@ -3195,7 +3194,7 @@ static const struct tty_operations gsmtty_ops = { + .tiocmget = gsmtty_tiocmget, + .tiocmset = gsmtty_tiocmset, + .break_ctl = gsmtty_break_ctl, +- .remove = gsmtty_remove, ++ .cleanup = gsmtty_cleanup, + }; + + +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index 28ac3f3..8195190 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -186,6 +186,17 @@ static int receive_room(struct tty_struct *tty) + return left; + } + ++static inline int tty_copy_to_user(struct tty_struct *tty, ++ void __user *to, ++ const void *from, ++ unsigned long n) ++{ ++ struct n_tty_data *ldata = tty->disc_data; ++ ++ tty_audit_add_data(tty, to, n, ldata->icanon); ++ return copy_to_user(to, from, n); ++} ++ + /** + * n_tty_set_room - receive space + * @tty: terminal +@@ -247,8 +258,6 @@ static void n_tty_write_wakeup(struct tty_struct *tty) + + static void n_tty_check_throttle(struct tty_struct *tty) + { +- if (tty->driver->type == TTY_DRIVER_TYPE_PTY) +- return; + /* + * Check the remaining room for the input canonicalization + * mode. We don't want to throttle the driver if we're in +@@ -321,7 +330,8 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) + + static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata) + { +- *read_buf_addr(ldata, ldata->read_head++) = c; ++ *read_buf_addr(ldata, ldata->read_head) = c; ++ ldata->read_head++; + } + + /** +@@ -1511,23 +1521,6 @@ n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag) + n_tty_receive_char_flagged(tty, c, flag); + } + +-/** +- * n_tty_receive_buf - data receive +- * @tty: terminal device +- * @cp: buffer +- * @fp: flag buffer +- * @count: characters +- * +- * Called by the terminal driver when a block of characters has +- * been received. This function must be called from soft contexts +- * not from interrupt context. The driver is responsible for making +- * calls one at a time and in order (or using flush_to_ldisc) +- * +- * n_tty_receive_buf()/producer path: +- * claims non-exclusive termios_rwsem +- * publishes read_head and canon_head +- */ +- + static void + n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count) +@@ -1683,24 +1676,85 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, + } + } + ++/** ++ * n_tty_receive_buf_common - process input ++ * @tty: device to receive input ++ * @cp: input chars ++ * @fp: flags for each char (if NULL, all chars are TTY_NORMAL) ++ * @count: number of input chars in @cp ++ * ++ * Called by the terminal driver when a block of characters has ++ * been received. This function must be called from soft contexts ++ * not from interrupt context. The driver is responsible for making ++ * calls one at a time and in order (or using flush_to_ldisc) ++ * ++ * Returns the # of input chars from @cp which were processed. ++ * ++ * In canonical mode, the maximum line length is 4096 chars (including ++ * the line termination char); lines longer than 4096 chars are ++ * truncated. After 4095 chars, input data is still processed but ++ * not stored. Overflow processing ensures the tty can always ++ * receive more input until at least one line can be read. ++ * ++ * In non-canonical mode, the read buffer will only accept 4095 chars; ++ * this provides the necessary space for a newline char if the input ++ * mode is switched to canonical. ++ * ++ * Note it is possible for the read buffer to _contain_ 4096 chars ++ * in non-canonical mode: the read buffer could already contain the ++ * maximum canon line of 4096 chars when the mode is switched to ++ * non-canonical. ++ * ++ * n_tty_receive_buf()/producer path: ++ * claims non-exclusive termios_rwsem ++ * publishes commit_head or canon_head ++ */ + static int + n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count, int flow) + { + struct n_tty_data *ldata = tty->disc_data; +- int room, n, rcvd = 0; ++ int room, n, rcvd = 0, overflow; + + down_read(&tty->termios_rwsem); + + while (1) { +- room = receive_room(tty); ++ /* ++ * When PARMRK is set, each input char may take up to 3 chars ++ * in the read buf; reduce the buffer space avail by 3x ++ * ++ * If we are doing input canonicalization, and there are no ++ * pending newlines, let characters through without limit, so ++ * that erase characters will be handled. Other excess ++ * characters will be beeped. ++ * ++ * paired with store in *_copy_from_read_buf() -- guarantees ++ * the consumer has loaded the data in read_buf up to the new ++ * read_tail (so this producer will not overwrite unread data) ++ */ ++ size_t tail = ldata->read_tail; ++ ++ room = N_TTY_BUF_SIZE - (ldata->read_head - tail); ++ if (I_PARMRK(tty)) ++ room = (room + 2) / 3; ++ room--; ++ if (room <= 0) { ++ overflow = ldata->icanon && ldata->canon_head == tail; ++ if (overflow && room < 0) ++ ldata->read_head--; ++ room = overflow; ++ ldata->no_room = flow && !room; ++ } else ++ overflow = 0; ++ + n = min(count, room); +- if (!n) { +- if (flow && !room) +- ldata->no_room = 1; ++ if (!n) + break; +- } +- __receive_buf(tty, cp, fp, n); ++ ++ /* ignore parity errors if handling overflow */ ++ if (!overflow || !fp || *fp != TTY_PARITY) ++ __receive_buf(tty, cp, fp, n); ++ + cp += n; + if (fp) + fp += n; +@@ -1709,7 +1763,17 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, + } + + tty->receive_room = room; +- n_tty_check_throttle(tty); ++ ++ /* Unthrottle if handling overflow on pty */ ++ if (tty->driver->type == TTY_DRIVER_TYPE_PTY) { ++ if (overflow) { ++ tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE); ++ tty_unthrottle_safe(tty); ++ __tty_set_flow_change(tty, 0); ++ } ++ } else ++ n_tty_check_throttle(tty); ++ + up_read(&tty->termios_rwsem); + + return rcvd; +@@ -2031,12 +2095,12 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, + __func__, eol, found, n, c, size, more); + + if (n > size) { +- ret = copy_to_user(*b, read_buf_addr(ldata, tail), size); ++ ret = tty_copy_to_user(tty, *b, read_buf_addr(ldata, tail), size); + if (ret) + return -EFAULT; +- ret = copy_to_user(*b + size, ldata->read_buf, n - size); ++ ret = tty_copy_to_user(tty, *b + size, ldata->read_buf, n - size); + } else +- ret = copy_to_user(*b, read_buf_addr(ldata, tail), n); ++ ret = tty_copy_to_user(tty, *b, read_buf_addr(ldata, tail), n); + + if (ret) + return -EFAULT; +@@ -2416,12 +2480,17 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, + + poll_wait(file, &tty->read_wait, wait); + poll_wait(file, &tty->write_wait, wait); ++ if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) ++ mask |= POLLHUP; + if (input_available_p(tty, 1)) + mask |= POLLIN | POLLRDNORM; ++ else if (mask & POLLHUP) { ++ tty_flush_to_ldisc(tty); ++ if (input_available_p(tty, 1)) ++ mask |= POLLIN | POLLRDNORM; ++ } + if (tty->packet && tty->link->ctrl_status) + mask |= POLLPRI | POLLIN | POLLRDNORM; +- if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) +- mask |= POLLHUP; + if (tty_hung_up_p(file)) + mask |= POLLHUP; + if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) { +diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c +index 25c9bc7..e49616e 100644 +--- a/drivers/tty/pty.c ++++ b/drivers/tty/pty.c +@@ -209,6 +209,9 @@ static int pty_signal(struct tty_struct *tty, int sig) + unsigned long flags; + struct pid *pgrp; + ++ if (sig != SIGINT && sig != SIGQUIT && sig != SIGTSTP) ++ return -EINVAL; ++ + if (tty->link) { + spin_lock_irqsave(&tty->link->ctrl_lock, flags); + pgrp = get_pid(tty->link->pgrp); +diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c +index ab9096d..148ffe4 100644 +--- a/drivers/tty/serial/8250/8250_dma.c ++++ b/drivers/tty/serial/8250/8250_dma.c +@@ -192,21 +192,28 @@ int serial8250_request_dma(struct uart_8250_port *p) + + dma->rx_buf = dma_alloc_coherent(dma->rxchan->device->dev, dma->rx_size, + &dma->rx_addr, GFP_KERNEL); +- if (!dma->rx_buf) { +- dma_release_channel(dma->rxchan); +- dma_release_channel(dma->txchan); +- return -ENOMEM; +- } ++ if (!dma->rx_buf) ++ goto err; + + /* TX buffer */ + dma->tx_addr = dma_map_single(dma->txchan->device->dev, + p->port.state->xmit.buf, + UART_XMIT_SIZE, + DMA_TO_DEVICE); ++ if (dma_mapping_error(dma->txchan->device->dev, dma->tx_addr)) { ++ dma_free_coherent(dma->rxchan->device->dev, dma->rx_size, ++ dma->rx_buf, dma->rx_addr); ++ goto err; ++ } + + dev_dbg_ratelimited(p->port.dev, "got both dma channels\n"); + + return 0; ++err: ++ dma_release_channel(dma->rxchan); ++ dma_release_channel(dma->txchan); ++ ++ return -ENOMEM; + } + EXPORT_SYMBOL_GPL(serial8250_request_dma); + +diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c +index 0ff3e36..5892eab 100644 +--- a/drivers/tty/serial/8250/8250_pci.c ++++ b/drivers/tty/serial/8250/8250_pci.c +@@ -66,7 +66,7 @@ static void moan_device(const char *str, struct pci_dev *dev) + "Please send the output of lspci -vv, this\n" + "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n" + "manufacturer and name of serial board or\n" +- "modem board to rmk+serial@arm.linux.org.uk.\n", ++ "modem board to .\n", + pci_name(dev), str, dev->vendor, dev->device, + dev->subsystem_vendor, dev->subsystem_device); + } +@@ -1766,6 +1766,7 @@ pci_wch_ch353_setup(struct serial_private *priv, + #define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022 + #define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a + #define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e ++#define PCI_DEVICE_ID_INTEL_QRK_UART 0x0936 + + #define PCI_VENDOR_ID_SUNIX 0x1fd4 + #define PCI_DEVICE_ID_SUNIX_1999 0x1999 +@@ -1876,6 +1877,13 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { + .subdevice = PCI_ANY_ID, + .setup = byt_serial_setup, + }, ++ { ++ .vendor = PCI_VENDOR_ID_INTEL, ++ .device = PCI_DEVICE_ID_INTEL_QRK_UART, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .setup = pci_default_setup, ++ }, + /* + * ITE + */ +@@ -2710,6 +2718,7 @@ enum pci_board_num_t { + pbn_ADDIDATA_PCIe_8_3906250, + pbn_ce4100_1_115200, + pbn_byt, ++ pbn_qrk, + pbn_omegapci, + pbn_NETMOS9900_2s_115200, + pbn_brcm_trumanage, +@@ -3456,6 +3465,12 @@ static struct pciserial_board pci_boards[] = { + .uart_offset = 0x80, + .reg_shift = 2, + }, ++ [pbn_qrk] = { ++ .flags = FL_BASE0, ++ .num_ports = 1, ++ .base_baud = 2764800, ++ .reg_shift = 2, ++ }, + [pbn_omegapci] = { + .flags = FL_BASE0, + .num_ports = 8, +@@ -5150,6 +5165,12 @@ static struct pci_device_id serial_pci_tbl[] = { + pbn_byt }, + + /* ++ * Intel Quark x1000 ++ */ ++ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_UART, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ pbn_qrk }, ++ /* + * Cronyx Omega PCI + */ + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_CRONYX_OMEGA, +diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c +index 682a2fb..2b22cc1 100644 +--- a/drivers/tty/serial/8250/8250_pnp.c ++++ b/drivers/tty/serial/8250/8250_pnp.c +@@ -364,6 +364,11 @@ static const struct pnp_device_id pnp_dev_table[] = { + /* Winbond CIR port, should not be probed. We should keep track + of it to prevent the legacy serial driver from probing it */ + { "WEC1022", CIR_PORT }, ++ /* ++ * SMSC IrCC SIR/FIR port, should not be probed by serial driver ++ * as well so its own driver can bind to it. ++ */ ++ { "SMCF010", CIR_PORT }, + { "", 0 } + }; + +diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c +index ce352b8..9d162ef7 100644 +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -757,6 +757,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port) + config.direction = DMA_MEM_TO_DEV; + config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + config.dst_addr = port->mapbase + ATMEL_US_THR; ++ config.dst_maxburst = 1; + + ret = dmaengine_device_control(atmel_port->chan_tx, + DMA_SLAVE_CONFIG, +@@ -921,6 +922,7 @@ static int atmel_prepare_rx_dma(struct uart_port *port) + config.direction = DMA_DEV_TO_MEM; + config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + config.src_addr = port->mapbase + ATMEL_US_RHR; ++ config.src_maxburst = 1; + + ret = dmaengine_device_control(atmel_port->chan_rx, + DMA_SLAVE_CONFIG, +@@ -2392,7 +2394,7 @@ static int atmel_serial_probe(struct platform_device *pdev) + + ret = atmel_init_port(port, pdev); + if (ret) +- goto err; ++ goto err_clear_bit; + + if (!atmel_use_pdc_rx(&port->uart)) { + ret = -ENOMEM; +@@ -2441,6 +2443,8 @@ err_alloc_ring: + clk_put(port->clk); + port->clk = NULL; + } ++err_clear_bit: ++ clear_bit(port->uart.line, atmel_ports_in_use); + err: + return ret; + } +diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c +index 175f123..501c465 100644 +--- a/drivers/tty/serial/fsl_lpuart.c ++++ b/drivers/tty/serial/fsl_lpuart.c +@@ -362,6 +362,9 @@ static void lpuart_setup_watermark(struct lpuart_port *sport) + writeb(val | UARTPFIFO_TXFE | UARTPFIFO_RXFE, + sport->port.membase + UARTPFIFO); + ++ /* explicitly clear RDRF */ ++ readb(sport->port.membase + UARTSR1); ++ + /* flush Tx and Rx FIFO */ + writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH, + sport->port.membase + UARTCFIFO); +diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c +index d799140..1fd9bc6 100644 +--- a/drivers/tty/serial/imx.c ++++ b/drivers/tty/serial/imx.c +@@ -907,6 +907,14 @@ static void dma_rx_callback(void *data) + + status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state); + count = RX_BUF_SIZE - state.residue; ++ ++ if (readl(sport->port.membase + USR2) & USR2_IDLE) { ++ /* In condition [3] the SDMA counted up too early */ ++ count--; ++ ++ writel(USR2_IDLE, sport->port.membase + USR2); ++ } ++ + dev_dbg(sport->port.dev, "We get %d bytes.\n", count); + + if (count) { +diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c +index 9924660..9dd8a71 100644 +--- a/drivers/tty/serial/of_serial.c ++++ b/drivers/tty/serial/of_serial.c +@@ -261,7 +261,6 @@ static struct of_device_id of_platform_serial_table[] = { + { .compatible = "ibm,qpace-nwp-serial", + .data = (void *)PORT_NWPSERIAL, }, + #endif +- { .type = "serial", .data = (void *)PORT_UNKNOWN, }, + { /* end of list */ }, + }; + +diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c +index db8434d..f4e68b3 100644 +--- a/drivers/tty/serial/omap-serial.c ++++ b/drivers/tty/serial/omap-serial.c +@@ -260,8 +260,16 @@ serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud) + { + unsigned int n13 = port->uartclk / (13 * baud); + unsigned int n16 = port->uartclk / (16 * baud); +- int baudAbsDiff13 = baud - (port->uartclk / (13 * n13)); +- int baudAbsDiff16 = baud - (port->uartclk / (16 * n16)); ++ int baudAbsDiff13; ++ int baudAbsDiff16; ++ ++ if (n13 == 0) ++ n13 = 1; ++ if (n16 == 0) ++ n16 = 1; ++ ++ baudAbsDiff13 = baud - (port->uartclk / (13 * n13)); ++ baudAbsDiff16 = baud - (port->uartclk / (16 * n16)); + if (baudAbsDiff13 < 0) + baudAbsDiff13 = -baudAbsDiff13; + if (baudAbsDiff16 < 0) +diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c +index 9cd706d..7d3a3f5 100644 +--- a/drivers/tty/serial/samsung.c ++++ b/drivers/tty/serial/samsung.c +@@ -544,11 +544,15 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, + unsigned int old) + { + struct s3c24xx_uart_port *ourport = to_ourport(port); ++ int timeout = 10000; + + ourport->pm_level = level; + + switch (level) { + case 3: ++ while (--timeout && !s3c24xx_serial_txempty_nofifo(port)) ++ udelay(100); ++ + if (!IS_ERR(ourport->baudclk)) + clk_disable_unprepare(ourport->baudclk); + +diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c +index ece2049..27b5554 100644 +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -235,6 +235,9 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) + /* + * Turn off DTR and RTS early. + */ ++ if (uart_console(uport) && tty) ++ uport->cons->cflag = tty->termios.c_cflag; ++ + if (!tty || (tty->termios.c_cflag & HUPCL)) + uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); + +@@ -350,7 +353,7 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, + * The spd_hi, spd_vhi, spd_shi, spd_warp kludge... + * Die! Die! Die! + */ +- if (baud == 38400) ++ if (try == 0 && baud == 38400) + baud = altbaud; + + /* +diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c +index 80a58ec..e8f7760 100644 +--- a/drivers/tty/serial/sunsab.c ++++ b/drivers/tty/serial/sunsab.c +@@ -157,6 +157,15 @@ receive_chars(struct uart_sunsab_port *up, + (up->port.line == up->port.cons->index)) + saw_console_brk = 1; + ++ if (count == 0) { ++ if (unlikely(stat->sreg.isr1 & SAB82532_ISR1_BRK)) { ++ stat->sreg.isr0 &= ~(SAB82532_ISR0_PERR | ++ SAB82532_ISR0_FERR); ++ up->port.icount.brk++; ++ uart_handle_break(&up->port); ++ } ++ } ++ + for (i = 0; i < count; i++) { + unsigned char ch = buf[i], flag; + +diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c +index d3448a9..39988fa 100644 +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -996,8 +996,8 @@ EXPORT_SYMBOL(start_tty); + /* We limit tty time update visibility to every 8 seconds or so. */ + static void tty_update_time(struct timespec *time) + { +- unsigned long sec = get_seconds() & ~7; +- if ((long)(sec - time->tv_sec) > 0) ++ unsigned long sec = get_seconds(); ++ if (abs(sec - time->tv_sec) & ~7) + time->tv_sec = sec; + } + +@@ -1701,6 +1701,7 @@ int tty_release(struct inode *inode, struct file *filp) + int pty_master, tty_closing, o_tty_closing, do_sleep; + int idx; + char buf[64]; ++ long timeout = 0; + + if (tty_paranoia_check(tty, inode, __func__)) + return 0; +@@ -1785,7 +1786,11 @@ int tty_release(struct inode *inode, struct file *filp) + __func__, tty_name(tty, buf)); + tty_unlock_pair(tty, o_tty); + mutex_unlock(&tty_mutex); +- schedule(); ++ schedule_timeout_killable(timeout); ++ if (timeout < 120 * HZ) ++ timeout = 2 * timeout + 1; ++ else ++ timeout = MAX_SCHEDULE_TIMEOUT; + } + + /* +diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c +index 6fd60fe..22da05d 100644 +--- a/drivers/tty/tty_ioctl.c ++++ b/drivers/tty/tty_ioctl.c +@@ -217,11 +217,17 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout) + #endif + if (!timeout) + timeout = MAX_SCHEDULE_TIMEOUT; ++ + if (wait_event_interruptible_timeout(tty->write_wait, +- !tty_chars_in_buffer(tty), timeout) >= 0) { +- if (tty->ops->wait_until_sent) +- tty->ops->wait_until_sent(tty, timeout); ++ !tty_chars_in_buffer(tty), timeout) < 0) { ++ return; + } ++ ++ if (timeout == MAX_SCHEDULE_TIMEOUT) ++ timeout = 0; ++ ++ if (tty->ops->wait_until_sent) ++ tty->ops->wait_until_sent(tty, timeout); + } + EXPORT_SYMBOL(tty_wait_until_sent); + +diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c +index 2978ca5..0e75d2a 100644 +--- a/drivers/tty/vt/consolemap.c ++++ b/drivers/tty/vt/consolemap.c +@@ -540,6 +540,12 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) + + /* Save original vc_unipagdir_loc in case we allocate a new one */ + p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; ++ ++ if (!p) { ++ err = -EINVAL; ++ ++ goto out_unlock; ++ } + if (p->readonly) { + console_unlock(); + return -EIO; +@@ -633,6 +639,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) + set_inverse_transl(vc, p, i); /* Update inverse translations */ + set_inverse_trans_unicode(vc, p); + ++out_unlock: + console_unlock(); + return err; + } +diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c +index 23b5d32..693091a 100644 +--- a/drivers/tty/vt/vt.c ++++ b/drivers/tty/vt/vt.c +@@ -498,6 +498,7 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed) + #endif + if (DO_UPDATE(vc)) + do_update_region(vc, (unsigned long) p, count); ++ notify_update(vc); + } + + /* used by selection: complement pointer position */ +@@ -514,6 +515,7 @@ void complement_pos(struct vc_data *vc, int offset) + scr_writew(old, screenpos(vc, old_offset, 1)); + if (DO_UPDATE(vc)) + vc->vc_sw->con_putc(vc, old, oldy, oldx); ++ notify_update(vc); + } + + old_offset = offset; +@@ -531,8 +533,8 @@ void complement_pos(struct vc_data *vc, int offset) + oldy = (offset >> 1) / vc->vc_cols; + vc->vc_sw->con_putc(vc, new, oldy, oldx); + } ++ notify_update(vc); + } +- + } + + static void insert_char(struct vc_data *vc, unsigned int nr) +diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c +index 0b24e6e..7a9c5a4 100644 +--- a/drivers/usb/chipidea/ci_hdrc_msm.c ++++ b/drivers/usb/chipidea/ci_hdrc_msm.c +@@ -20,13 +20,13 @@ + static int ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) + { + struct device *dev = ci->gadget.dev.parent; +- int val; + + switch (event) { + case CI_HDRC_CONTROLLER_RESET_EVENT: + dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n"); + writel(0, USB_AHBBURST); + writel(0, USB_AHBMODE); ++ usb_phy_init(ci->transceiver); + break; + case CI_HDRC_CONTROLLER_STOPPED_EVENT: + dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n"); +@@ -34,10 +34,7 @@ static int ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) + * Put the transceiver in non-driving mode. Otherwise host + * may not detect soft-disconnection. + */ +- val = usb_phy_io_read(ci->transceiver, ULPI_FUNC_CTRL); +- val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; +- val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; +- usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL); ++ usb_phy_notify_disconnect(ci->transceiver, USB_SPEED_UNKNOWN); + break; + default: + dev_dbg(dev, "unknown ci_hdrc event\n"); +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index eabccd4..d7049c3 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -965,11 +965,12 @@ static void acm_tty_set_termios(struct tty_struct *tty, + /* FIXME: Needs to clear unsupported bits in the termios */ + acm->clocal = ((termios->c_cflag & CLOCAL) != 0); + +- if (!newline.dwDTERate) { ++ if (C_BAUD(tty) == B0) { + newline.dwDTERate = acm->line.dwDTERate; + newctrl &= ~ACM_CTRL_DTR; +- } else ++ } else if (termios_old && (termios_old->c_cflag & CBAUD) == B0) { + newctrl |= ACM_CTRL_DTR; ++ } + + if (newctrl != acm->ctrlout) + acm_set_control(acm, acm->ctrlout = newctrl); +@@ -1168,10 +1169,11 @@ next_desc: + } else { + control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0); + data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0)); +- if (!control_interface || !data_interface) { +- dev_dbg(&intf->dev, "no interfaces\n"); +- return -ENODEV; +- } ++ } ++ ++ if (!control_interface || !data_interface) { ++ dev_dbg(&intf->dev, "no interfaces\n"); ++ return -ENODEV; + } + + if (data_interface_num != call_interface_num) +@@ -1447,6 +1449,7 @@ alloc_fail8: + &dev_attr_wCountryCodes); + device_remove_file(&acm->control->dev, + &dev_attr_iCountryCodeRelDate); ++ kfree(acm->country_codes); + } + device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); + alloc_fail7: +@@ -1672,6 +1675,7 @@ static const struct usb_device_id acm_ids[] = { + { USB_DEVICE(0x0572, 0x1328), /* Shiro / Aztech USB MODEM UM-3100 */ + .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ + }, ++ { USB_DEVICE(0x2184, 0x001c) }, /* GW Instek AFG-2225 */ + { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */ + }, + /* Motorola H24 HSPA module: */ +diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c +index a051a7a..a81f9dd 100644 +--- a/drivers/usb/class/cdc-wdm.c ++++ b/drivers/usb/class/cdc-wdm.c +@@ -245,7 +245,7 @@ static void wdm_int_callback(struct urb *urb) + case USB_CDC_NOTIFY_RESPONSE_AVAILABLE: + dev_dbg(&desc->intf->dev, + "NOTIFY_RESPONSE_AVAILABLE received: index %d len %d", +- dr->wIndex, dr->wLength); ++ le16_to_cpu(dr->wIndex), le16_to_cpu(dr->wLength)); + break; + + case USB_CDC_NOTIFY_NETWORK_CONNECTION: +@@ -262,7 +262,9 @@ static void wdm_int_callback(struct urb *urb) + clear_bit(WDM_POLL_RUNNING, &desc->flags); + dev_err(&desc->intf->dev, + "unknown notification %d received: index %d len %d\n", +- dr->bNotificationType, dr->wIndex, dr->wLength); ++ dr->bNotificationType, ++ le16_to_cpu(dr->wIndex), ++ le16_to_cpu(dr->wLength)); + goto exit; + } + +@@ -408,7 +410,7 @@ static ssize_t wdm_write + USB_RECIP_INTERFACE); + req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND; + req->wValue = 0; +- req->wIndex = desc->inum; ++ req->wIndex = desc->inum; /* already converted */ + req->wLength = cpu_to_le16(count); + set_bit(WDM_IN_USE, &desc->flags); + desc->outbuf = buf; +@@ -422,7 +424,7 @@ static ssize_t wdm_write + rv = usb_translate_errors(rv); + } else { + dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d", +- req->wIndex); ++ le16_to_cpu(req->wIndex)); + } + out: + usb_autopm_put_interface(desc->intf); +@@ -820,7 +822,7 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor + desc->irq->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE); + desc->irq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE; + desc->irq->wValue = 0; +- desc->irq->wIndex = desc->inum; ++ desc->irq->wIndex = desc->inum; /* already converted */ + desc->irq->wLength = cpu_to_le16(desc->wMaxCommand); + + usb_fill_control_urb( +diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c +index 684ef70..506b969 100644 +--- a/drivers/usb/core/buffer.c ++++ b/drivers/usb/core/buffer.c +@@ -22,17 +22,25 @@ + */ + + /* FIXME tune these based on pool statistics ... */ +-static const size_t pool_max[HCD_BUFFER_POOLS] = { +- /* platforms without dma-friendly caches might need to +- * prevent cacheline sharing... +- */ +- 32, +- 128, +- 512, +- PAGE_SIZE / 2 +- /* bigger --> allocate pages */ ++static size_t pool_max[HCD_BUFFER_POOLS] = { ++ 32, 128, 512, 2048, + }; + ++void __init usb_init_pool_max(void) ++{ ++ /* ++ * The pool_max values must never be smaller than ++ * ARCH_KMALLOC_MINALIGN. ++ */ ++ if (ARCH_KMALLOC_MINALIGN <= 32) ++ ; /* Original value is okay */ ++ else if (ARCH_KMALLOC_MINALIGN <= 64) ++ pool_max[0] = 64; ++ else if (ARCH_KMALLOC_MINALIGN <= 128) ++ pool_max[0] = 0; /* Don't use this pool */ ++ else ++ BUILD_BUG(); /* We don't allow this */ ++} + + /* SETUP primitives */ + +diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c +index 90e18f6..8016aaa 100644 +--- a/drivers/usb/core/devio.c ++++ b/drivers/usb/core/devio.c +@@ -501,6 +501,7 @@ static void async_completed(struct urb *urb) + as->status = urb->status; + signr = as->signr; + if (signr) { ++ memset(&sinfo, 0, sizeof(sinfo)); + sinfo.si_signo = as->signr; + sinfo.si_errno = as->status; + sinfo.si_code = SI_ASYNCIO; +@@ -512,7 +513,7 @@ static void async_completed(struct urb *urb) + snoop(&urb->dev->dev, "urb complete\n"); + snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length, + as->status, COMPLETE, NULL, 0); +- if ((urb->transfer_flags & URB_DIR_MASK) == USB_DIR_IN) ++ if ((urb->transfer_flags & URB_DIR_MASK) == URB_DIR_IN) + snoop_urb_data(urb, urb->actual_length); + + if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET && +@@ -1411,7 +1412,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, + u = (is_in ? URB_DIR_IN : URB_DIR_OUT); + if (uurb->flags & USBDEVFS_URB_ISO_ASAP) + u |= URB_ISO_ASAP; +- if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK) ++ if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK && is_in) + u |= URB_SHORT_NOT_OK; + if (uurb->flags & USBDEVFS_URB_NO_FSBR) + u |= URB_NO_FSBR; +@@ -1590,7 +1591,7 @@ static struct async *reap_as(struct dev_state *ps) + for (;;) { + __set_current_state(TASK_INTERRUPTIBLE); + as = async_getcompleted(ps); +- if (as) ++ if (as || !connected(ps)) + break; + if (signal_pending(current)) + break; +@@ -1613,7 +1614,7 @@ static int proc_reapurb(struct dev_state *ps, void __user *arg) + } + if (signal_pending(current)) + return -EINTR; +- return -EIO; ++ return -ENODEV; + } + + static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg) +@@ -1622,10 +1623,11 @@ static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg) + struct async *as; + + as = async_getcompleted(ps); +- retval = -EAGAIN; + if (as) { + retval = processcompl(as, (void __user * __user *)arg); + free_async(as); ++ } else { ++ retval = (connected(ps) ? -EAGAIN : -ENODEV); + } + return retval; + } +@@ -1755,7 +1757,7 @@ static int proc_reapurb_compat(struct dev_state *ps, void __user *arg) + } + if (signal_pending(current)) + return -EINTR; +- return -EIO; ++ return -ENODEV; + } + + static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg) +@@ -1763,11 +1765,12 @@ static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg) + int retval; + struct async *as; + +- retval = -EAGAIN; + as = async_getcompleted(ps); + if (as) { + retval = processcompl_compat(as, (void __user * __user *)arg); + free_async(as); ++ } else { ++ retval = (connected(ps) ? -EAGAIN : -ENODEV); + } + return retval; + } +@@ -1939,7 +1942,8 @@ static int proc_get_capabilities(struct dev_state *ps, void __user *arg) + { + __u32 caps; + +- caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM; ++ caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM | ++ USBDEVFS_CAP_REAP_AFTER_DISCONNECT; + if (!ps->dev->bus->no_stop_on_short) + caps |= USBDEVFS_CAP_BULK_CONTINUATION; + if (ps->dev->bus->sg_tablesize) +@@ -2000,6 +2004,32 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, + return -EPERM; + + usb_lock_device(dev); ++ ++ /* Reap operations are allowed even after disconnection */ ++ switch (cmd) { ++ case USBDEVFS_REAPURB: ++ snoop(&dev->dev, "%s: REAPURB\n", __func__); ++ ret = proc_reapurb(ps, p); ++ goto done; ++ ++ case USBDEVFS_REAPURBNDELAY: ++ snoop(&dev->dev, "%s: REAPURBNDELAY\n", __func__); ++ ret = proc_reapurbnonblock(ps, p); ++ goto done; ++ ++#ifdef CONFIG_COMPAT ++ case USBDEVFS_REAPURB32: ++ snoop(&dev->dev, "%s: REAPURB32\n", __func__); ++ ret = proc_reapurb_compat(ps, p); ++ goto done; ++ ++ case USBDEVFS_REAPURBNDELAY32: ++ snoop(&dev->dev, "%s: REAPURBNDELAY32\n", __func__); ++ ret = proc_reapurbnonblock_compat(ps, p); ++ goto done; ++#endif ++ } ++ + if (!connected(ps)) { + usb_unlock_device(dev); + return -ENODEV; +@@ -2093,16 +2123,6 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, + inode->i_mtime = CURRENT_TIME; + break; + +- case USBDEVFS_REAPURB32: +- snoop(&dev->dev, "%s: REAPURB32\n", __func__); +- ret = proc_reapurb_compat(ps, p); +- break; +- +- case USBDEVFS_REAPURBNDELAY32: +- snoop(&dev->dev, "%s: REAPURBNDELAY32\n", __func__); +- ret = proc_reapurbnonblock_compat(ps, p); +- break; +- + case USBDEVFS_IOCTL32: + snoop(&dev->dev, "%s: IOCTL32\n", __func__); + ret = proc_ioctl_compat(ps, ptr_to_compat(p)); +@@ -2114,16 +2134,6 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, + ret = proc_unlinkurb(ps, p); + break; + +- case USBDEVFS_REAPURB: +- snoop(&dev->dev, "%s: REAPURB\n", __func__); +- ret = proc_reapurb(ps, p); +- break; +- +- case USBDEVFS_REAPURBNDELAY: +- snoop(&dev->dev, "%s: REAPURBNDELAY\n", __func__); +- ret = proc_reapurbnonblock(ps, p); +- break; +- + case USBDEVFS_DISCSIGNAL: + snoop(&dev->dev, "%s: DISCSIGNAL\n", __func__); + ret = proc_disconnectsignal(ps, p); +@@ -2160,6 +2170,8 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, + ret = proc_disconnect_claim(ps, p); + break; + } ++ ++ done: + usb_unlock_device(dev); + if (ret >= 0) + inode->i_atime = CURRENT_TIME; +@@ -2227,6 +2239,7 @@ static void usbdev_remove(struct usb_device *udev) + wake_up_all(&ps->wait); + list_del_init(&ps->list); + if (ps->discsignr) { ++ memset(&sinfo, 0, sizeof(sinfo)); + sinfo.si_signo = ps->discsignr; + sinfo.si_errno = EPIPE; + sinfo.si_code = SI_ASYNCIO; +diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c +index 2518c32..ee6c556 100644 +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -1617,6 +1617,7 @@ static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status) + int usb_hcd_unlink_urb (struct urb *urb, int status) + { + struct usb_hcd *hcd; ++ struct usb_device *udev = urb->dev; + int retval = -EIDRM; + unsigned long flags; + +@@ -1628,20 +1629,19 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) + spin_lock_irqsave(&hcd_urb_unlink_lock, flags); + if (atomic_read(&urb->use_count) > 0) { + retval = 0; +- usb_get_dev(urb->dev); ++ usb_get_dev(udev); + } + spin_unlock_irqrestore(&hcd_urb_unlink_lock, flags); + if (retval == 0) { + hcd = bus_to_hcd(urb->dev->bus); + retval = unlink1(hcd, urb, status); +- usb_put_dev(urb->dev); ++ if (retval == 0) ++ retval = -EINPROGRESS; ++ else if (retval != -EIDRM && retval != -EBUSY) ++ dev_dbg(&udev->dev, "hcd_unlink_urb %p fail %d\n", ++ urb, retval); ++ usb_put_dev(udev); + } +- +- if (retval == 0) +- retval = -EINPROGRESS; +- else if (retval != -EIDRM && retval != -EBUSY) +- dev_dbg(&urb->dev->dev, "hcd_unlink_urb %p fail %d\n", +- urb, retval); + return retval; + } + +@@ -2057,6 +2057,8 @@ int usb_alloc_streams(struct usb_interface *interface, + return -EINVAL; + if (dev->speed != USB_SPEED_SUPER) + return -EINVAL; ++ if (dev->state < USB_STATE_CONFIGURED) ++ return -ENODEV; + + /* Streams only apply to bulk endpoints. */ + for (i = 0; i < num_eps; i++) +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 5af4a66..e4e06ed 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -1695,8 +1695,14 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) + * - Change autosuspend delay of hub can avoid unnecessary auto + * suspend timer for hub, also may decrease power consumption + * of USB bus. ++ * ++ * - If user has indicated to prevent autosuspend by passing ++ * usbcore.autosuspend = -1 then keep autosuspend disabled. + */ +- pm_runtime_set_autosuspend_delay(&hdev->dev, 0); ++#ifdef CONFIG_PM_RUNTIME ++ if (hdev->dev.power.autosuspend_delay >= 0) ++ pm_runtime_set_autosuspend_delay(&hdev->dev, 0); ++#endif + + /* + * Hubs have proper suspend/resume support, except for root hubs +@@ -1942,8 +1948,10 @@ void usb_set_device_state(struct usb_device *udev, + || new_state == USB_STATE_SUSPENDED) + ; /* No change to wakeup settings */ + else if (new_state == USB_STATE_CONFIGURED) +- wakeup = udev->actconfig->desc.bmAttributes +- & USB_CONFIG_ATT_WAKEUP; ++ wakeup = (udev->quirks & ++ USB_QUIRK_IGNORE_REMOTE_WAKEUP) ? 0 : ++ udev->actconfig->desc.bmAttributes & ++ USB_CONFIG_ATT_WAKEUP; + else + wakeup = 0; + } +@@ -3174,6 +3182,43 @@ static int finish_port_resume(struct usb_device *udev) + } + + /* ++ * There are some SS USB devices which take longer time for link training. ++ * XHCI specs 4.19.4 says that when Link training is successful, port ++ * sets CSC bit to 1. So if SW reads port status before successful link ++ * training, then it will not find device to be present. ++ * USB Analyzer log with such buggy devices show that in some cases ++ * device switch on the RX termination after long delay of host enabling ++ * the VBUS. In few other cases it has been seen that device fails to ++ * negotiate link training in first attempt. It has been ++ * reported till now that few devices take as long as 2000 ms to train ++ * the link after host enabling its VBUS and termination. Following ++ * routine implements a 2000 ms timeout for link training. If in a case ++ * link trains before timeout, loop will exit earlier. ++ * ++ * FIXME: If a device was connected before suspend, but was removed ++ * while system was asleep, then the loop in the following routine will ++ * only exit at timeout. ++ * ++ * This routine should only be called when persist is enabled for a SS ++ * device. ++ */ ++static int wait_for_ss_port_enable(struct usb_device *udev, ++ struct usb_hub *hub, int *port1, ++ u16 *portchange, u16 *portstatus) ++{ ++ int status = 0, delay_ms = 0; ++ ++ while (delay_ms < 2000) { ++ if (status || *portstatus & USB_PORT_STAT_CONNECTION) ++ break; ++ msleep(20); ++ delay_ms += 20; ++ status = hub_port_status(hub, *port1, portstatus, portchange); ++ } ++ return status; ++} ++ ++/* + * usb_port_resume - re-activate a suspended usb device's upstream port + * @udev: device to re-activate, not a root hub + * Context: must be able to sleep; device not locked; pm locks held +@@ -3244,10 +3289,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) + dev_dbg(hub->intfdev, "can't resume port %d, status %d\n", + port1, status); + } else { +- /* drive resume for at least 20 msec */ ++ /* drive resume for USB_RESUME_TIMEOUT msec */ + dev_dbg(&udev->dev, "usb %sresume\n", + (PMSG_IS_AUTO(msg) ? "auto-" : "")); +- msleep(25); ++ msleep(USB_RESUME_TIMEOUT); + + /* Virtual root hubs can trigger on GET_PORT_STATUS to + * stop resume signaling. Then finish the resume +@@ -3275,6 +3320,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) + + clear_bit(port1, hub->busy_bits); + ++ if (udev->persist_enabled && hub_is_superspeed(hub->hdev)) ++ status = wait_for_ss_port_enable(udev, hub, &port1, &portchange, ++ &portstatus); ++ + status = check_port_resume_type(udev, + hub, port1, status, portchange, portstatus); + if (status == 0) +@@ -4335,6 +4384,9 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1) + struct usb_qualifier_descriptor *qual; + int status; + ++ if (udev->quirks & USB_QUIRK_DEVICE_QUALIFIER) ++ return; ++ + qual = kmalloc (sizeof *qual, GFP_KERNEL); + if (qual == NULL) + return; +@@ -4722,9 +4774,10 @@ static void hub_events(void) + + hub = list_entry(tmp, struct usb_hub, event_list); + kref_get(&hub->kref); ++ hdev = hub->hdev; ++ usb_get_dev(hdev); + spin_unlock_irq(&hub_event_lock); + +- hdev = hub->hdev; + hub_dev = hub->intfdev; + intf = to_usb_interface(hub_dev); + dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n", +@@ -4937,6 +4990,7 @@ static void hub_events(void) + usb_autopm_put_interface(intf); + loop_disconnected: + usb_unlock_device(hdev); ++ usb_put_dev(hdev); + kref_put(&hub->kref, hub_release); + + } /* end while (1) */ +diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c +index 739ee8e..b195fdb 100644 +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -44,6 +44,9 @@ static const struct usb_device_id usb_quirk_list[] = { + /* Creative SB Audigy 2 NX */ + { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* Microsoft Wireless Laser Mouse 6000 Receiver */ ++ { USB_DEVICE(0x045e, 0x00e1), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* Microsoft LifeCam-VX700 v2.0 */ + { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, + +@@ -93,6 +96,16 @@ static const struct usb_device_id usb_quirk_list[] = { + { USB_DEVICE(0x04e8, 0x6601), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + ++ /* Elan Touchscreen */ ++ { USB_DEVICE(0x04f3, 0x0089), .driver_info = ++ USB_QUIRK_DEVICE_QUALIFIER }, ++ ++ { USB_DEVICE(0x04f3, 0x009b), .driver_info = ++ USB_QUIRK_DEVICE_QUALIFIER }, ++ ++ { USB_DEVICE(0x04f3, 0x016f), .driver_info = ++ USB_QUIRK_DEVICE_QUALIFIER }, ++ + /* Roland SC-8820 */ + { USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME }, + +@@ -160,6 +173,10 @@ static const struct usb_device_id usb_interface_quirk_list[] = { + { USB_VENDOR_AND_INTERFACE_INFO(0x046d, USB_CLASS_VIDEO, 1, 0), + .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* ASUS Base Station(T100) */ ++ { USB_DEVICE(0x0b05, 0x17e0), .driver_info = ++ USB_QUIRK_IGNORE_REMOTE_WAKEUP }, ++ + { } /* terminating entry must be last */ + }; + +diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c +index 4d11449..a922730 100644 +--- a/drivers/usb/core/usb.c ++++ b/drivers/usb/core/usb.c +@@ -1050,6 +1050,7 @@ static int __init usb_init(void) + pr_info("%s: USB support disabled\n", usbcore_name); + return 0; + } ++ usb_init_pool_max(); + + retval = usb_debugfs_init(); + if (retval) +diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c +index 4d918ed..0f99800 100644 +--- a/drivers/usb/dwc2/hcd.c ++++ b/drivers/usb/dwc2/hcd.c +@@ -1501,7 +1501,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, + dev_dbg(hsotg->dev, + "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); + writel(0, hsotg->regs + PCGCTL); +- usleep_range(20000, 40000); ++ msleep(USB_RESUME_TIMEOUT); + + hprt0 = dwc2_read_hprt0(hsotg); + hprt0 |= HPRT0_RES; +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index a49217a..f074755 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -583,12 +583,6 @@ static int dwc3_remove(struct platform_device *pdev) + { + struct dwc3 *dwc = platform_get_drvdata(pdev); + +- usb_phy_set_suspend(dwc->usb2_phy, 1); +- usb_phy_set_suspend(dwc->usb3_phy, 1); +- +- pm_runtime_put_sync(&pdev->dev); +- pm_runtime_disable(&pdev->dev); +- + dwc3_debugfs_exit(dwc); + + switch (dwc->dr_mode) { +@@ -609,8 +603,15 @@ static int dwc3_remove(struct platform_device *pdev) + + dwc3_event_buffers_cleanup(dwc); + dwc3_free_event_buffers(dwc); ++ ++ usb_phy_set_suspend(dwc->usb2_phy, 1); ++ usb_phy_set_suspend(dwc->usb3_phy, 1); ++ + dwc3_core_exit(dwc); + ++ pm_runtime_put_sync(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); ++ + return 0; + } + +diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c +index b269dbd..cfca302 100644 +--- a/drivers/usb/dwc3/dwc3-omap.c ++++ b/drivers/usb/dwc3/dwc3-omap.c +@@ -211,6 +211,18 @@ static void dwc3_omap_write_irq0_set(struct dwc3_omap *omap, u32 value) + omap->irq0_offset, value); + } + ++static void dwc3_omap_write_irqmisc_clr(struct dwc3_omap *omap, u32 value) ++{ ++ dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_CLR_MISC + ++ omap->irqmisc_offset, value); ++} ++ ++static void dwc3_omap_write_irq0_clr(struct dwc3_omap *omap, u32 value) ++{ ++ dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_CLR_0 - ++ omap->irq0_offset, value); ++} ++ + static void dwc3_omap_set_mailbox(struct dwc3_omap *omap, + enum omap_dwc3_vbus_id_status status) + { +@@ -351,9 +363,23 @@ static void dwc3_omap_enable_irqs(struct dwc3_omap *omap) + + static void dwc3_omap_disable_irqs(struct dwc3_omap *omap) + { ++ u32 reg; ++ + /* disable all IRQs */ +- dwc3_omap_write_irqmisc_set(omap, 0x00); +- dwc3_omap_write_irq0_set(omap, 0x00); ++ reg = USBOTGSS_IRQO_COREIRQ_ST; ++ dwc3_omap_write_irq0_clr(omap, reg); ++ ++ reg = (USBOTGSS_IRQMISC_OEVT | ++ USBOTGSS_IRQMISC_DRVVBUS_RISE | ++ USBOTGSS_IRQMISC_CHRGVBUS_RISE | ++ USBOTGSS_IRQMISC_DISCHRGVBUS_RISE | ++ USBOTGSS_IRQMISC_IDPULLUP_RISE | ++ USBOTGSS_IRQMISC_DRVVBUS_FALL | ++ USBOTGSS_IRQMISC_CHRGVBUS_FALL | ++ USBOTGSS_IRQMISC_DISCHRGVBUS_FALL | ++ USBOTGSS_IRQMISC_IDPULLUP_FALL); ++ ++ dwc3_omap_write_irqmisc_clr(omap, reg); + } + + static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32); +@@ -582,9 +608,9 @@ static int dwc3_omap_remove(struct platform_device *pdev) + if (omap->extcon_id_dev.edev) + extcon_unregister_interest(&omap->extcon_id_dev); + dwc3_omap_disable_irqs(omap); ++ device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); +- device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core); + + return 0; + } +diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c +index 21a3520..965c9ac 100644 +--- a/drivers/usb/dwc3/ep0.c ++++ b/drivers/usb/dwc3/ep0.c +@@ -251,7 +251,7 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) + + /* stall is always issued on EP0 */ + dep = dwc->eps[0]; +- __dwc3_gadget_ep_set_halt(dep, 1); ++ __dwc3_gadget_ep_set_halt(dep, 1, false); + dep->flags = DWC3_EP_ENABLED; + dwc->delayed_status = false; + +@@ -461,7 +461,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, + return -EINVAL; + if (set == 0 && (dep->flags & DWC3_EP_WEDGE)) + break; +- ret = __dwc3_gadget_ep_set_halt(dep, set); ++ ret = __dwc3_gadget_ep_set_halt(dep, set, true); + if (ret) + return -EINVAL; + break; +@@ -707,6 +707,10 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) + dev_vdbg(dwc->dev, "USB_REQ_SET_ISOCH_DELAY\n"); + ret = dwc3_ep0_set_isoch_delay(dwc, ctrl); + break; ++ case USB_REQ_SET_INTERFACE: ++ dev_vdbg(dwc->dev, "USB_REQ_SET_INTERFACE\n"); ++ dwc->start_config_issued = false; ++ /* Fall through */ + default: + dev_vdbg(dwc->dev, "Forwarding to gadget driver\n"); + ret = dwc3_ep0_delegate_req(dwc, ctrl); +@@ -789,6 +793,11 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, + unsigned maxp = ep0->endpoint.maxpacket; + + transfer_size += (maxp - (transfer_size % maxp)); ++ ++ /* Maximum of DWC3_EP0_BOUNCE_SIZE can only be received */ ++ if (transfer_size > DWC3_EP0_BOUNCE_SIZE) ++ transfer_size = DWC3_EP0_BOUNCE_SIZE; ++ + transferred = min_t(u32, ur->length, + transfer_size - length); + memcpy(ur->buf, dwc->ep0_bounce, transferred); +@@ -901,11 +910,14 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, + return; + } + +- WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE); +- + maxpacket = dep->endpoint.maxpacket; + transfer_size = roundup(req->request.length, maxpacket); + ++ if (transfer_size > DWC3_EP0_BOUNCE_SIZE) { ++ dev_WARN(dwc->dev, "bounce buf can't handle req len\n"); ++ transfer_size = DWC3_EP0_BOUNCE_SIZE; ++ } ++ + dwc->ep0_bounced = true; + + /* +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 09e9619..a57ad1f 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -299,6 +299,8 @@ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, int cmd, u32 param) + if (!(reg & DWC3_DGCMD_CMDACT)) { + dev_vdbg(dwc->dev, "Command Complete --> %d\n", + DWC3_DGCMD_STATUS(reg)); ++ if (DWC3_DGCMD_STATUS(reg)) ++ return -EINVAL; + return 0; + } + +@@ -335,6 +337,8 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, + if (!(reg & DWC3_DEPCMD_CMDACT)) { + dev_vdbg(dwc->dev, "Command Complete --> %d\n", + DWC3_DEPCMD_STATUS(reg)); ++ if (DWC3_DEPCMD_STATUS(reg)) ++ return -EINVAL; + return 0; + } + +@@ -532,12 +536,11 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, + if (!usb_endpoint_xfer_isoc(desc)) + return 0; + +- memset(&trb_link, 0, sizeof(trb_link)); +- + /* Link TRB for ISOC. The HWO bit is never reset */ + trb_st_hw = &dep->trb_pool[0]; + + trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1]; ++ memset(trb_link, 0, sizeof(*trb_link)); + + trb_link->bpl = lower_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw)); + trb_link->bph = upper_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw)); +@@ -588,7 +591,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) + + /* make sure HW endpoint isn't stalled */ + if (dep->flags & DWC3_EP_STALL) +- __dwc3_gadget_ep_set_halt(dep, 0); ++ __dwc3_gadget_ep_set_halt(dep, 0, false); + + reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); + reg &= ~DWC3_DALEPENA_EP(dep->number); +@@ -888,8 +891,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) + + if (i == (request->num_mapped_sgs - 1) || + sg_is_last(s)) { +- if (list_is_last(&req->list, +- &dep->request_list)) ++ if (list_empty(&dep->request_list)) + last_one = true; + chain = false; + } +@@ -907,6 +909,9 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) + if (last_one) + break; + } ++ ++ if (last_one) ++ break; + } else { + dma = req->request.dma; + length = req->request.length; +@@ -1186,7 +1191,7 @@ out0: + return ret; + } + +-int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value) ++int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) + { + struct dwc3_gadget_ep_cmd_params params; + struct dwc3 *dwc = dep->dwc; +@@ -1195,6 +1200,14 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value) + memset(¶ms, 0x00, sizeof(params)); + + if (value) { ++ if (!protocol && ((dep->direction && dep->flags & DWC3_EP_BUSY) || ++ (!list_empty(&dep->req_queued) || ++ !list_empty(&dep->request_list)))) { ++ dev_dbg(dwc->dev, "%s: pending request, cannot halt\n", ++ dep->name); ++ return -EAGAIN; ++ } ++ + ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, + DWC3_DEPCMD_SETSTALL, ¶ms); + if (ret) +@@ -1234,7 +1247,7 @@ static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value) + goto out; + } + +- ret = __dwc3_gadget_ep_set_halt(dep, value); ++ ret = __dwc3_gadget_ep_set_halt(dep, value, false); + out: + spin_unlock_irqrestore(&dwc->lock, flags); + +@@ -1254,7 +1267,7 @@ static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep) + if (dep->number == 0 || dep->number == 1) + return dwc3_gadget_ep0_set_halt(ep, 1); + else +- return dwc3_gadget_ep_set_halt(ep, 1); ++ return __dwc3_gadget_ep_set_halt(dep, 1, false); + } + + /* -------------------------------------------------------------------------- */ +diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h +index a0ee75b..ac625582 100644 +--- a/drivers/usb/dwc3/gadget.h ++++ b/drivers/usb/dwc3/gadget.h +@@ -85,7 +85,7 @@ void dwc3_ep0_out_start(struct dwc3 *dwc); + int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value); + int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, + gfp_t gfp_flags); +-int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value); ++int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol); + + /** + * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW +diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig +index ebaae9a..a6101e0 100644 +--- a/drivers/usb/gadget/Kconfig ++++ b/drivers/usb/gadget/Kconfig +@@ -445,7 +445,7 @@ config USB_GOKU + gadget drivers to also be dynamically linked. + + config USB_EG20T +- tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC" ++ tristate "Intel QUARK X1000/EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC" + depends on PCI + help + This is a USB device driver for EG20T PCH. +@@ -466,6 +466,7 @@ config USB_EG20T + ML7213/ML7831 is companion chip for Intel Atom E6xx series. + ML7213/ML7831 is completely compatible for Intel EG20T PCH. + ++ This driver can be used with Intel's Quark X1000 SOC platform + # + # LAST -- dummy/emulated controller + # +diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c +index d742bed..82df926 100644 +--- a/drivers/usb/gadget/composite.c ++++ b/drivers/usb/gadget/composite.c +@@ -528,7 +528,7 @@ static int bos_desc(struct usb_composite_dev *cdev) + usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE; + usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY; + usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT; +- usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT); ++ usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT | USB_BESL_SUPPORT); + + /* + * The Superspeed USB Capability descriptor shall be implemented by all +diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c +index 7d1cc01..3740a3f 100644 +--- a/drivers/usb/gadget/configfs.c ++++ b/drivers/usb/gadget/configfs.c +@@ -765,6 +765,7 @@ static void purge_configs_funcs(struct gadget_info *gi) + } + } + c->next_interface_id = 0; ++ memset(c->interface, 0, sizeof(c->interface)); + c->superspeed = 0; + c->highspeed = 0; + c->fullspeed = 0; +diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c +index ab1065a..3384486 100644 +--- a/drivers/usb/gadget/f_acm.c ++++ b/drivers/usb/gadget/f_acm.c +@@ -430,11 +430,12 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) + if (acm->notify->driver_data) { + VDBG(cdev, "reset acm control interface %d\n", intf); + usb_ep_disable(acm->notify); +- } else { +- VDBG(cdev, "init acm ctrl interface %d\n", intf); ++ } ++ ++ if (!acm->notify->desc) + if (config_ep_by_speed(cdev->gadget, f, acm->notify)) + return -EINVAL; +- } ++ + usb_ep_enable(acm->notify); + acm->notify->driver_data = acm; + +diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c +index 5bcf7d0..afd0a15 100644 +--- a/drivers/usb/gadget/f_fs.c ++++ b/drivers/usb/gadget/f_fs.c +@@ -1995,8 +1995,6 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, + func->conf = c; + func->gadget = c->cdev->gadget; + +- ffs_data_get(func->ffs); +- + /* + * in drivers/usb/gadget/configfs.c:configfs_composite_bind() + * configurations are bound in sequence with list_for_each_entry, +diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c +index eb8c3be..460d953 100644 +--- a/drivers/usb/gadget/pch_udc.c ++++ b/drivers/usb/gadget/pch_udc.c +@@ -343,6 +343,7 @@ struct pch_vbus_gpio_data { + * @setup_data: Received setup data + * @phys_addr: of device memory + * @base_addr: for mapped device memory ++ * @bar: Indicates which PCI BAR for USB regs + * @irq: IRQ line for the device + * @cfg_data: current cfg, intf, and alt in use + * @vbus_gpio: GPIO informaton for detecting VBUS +@@ -370,14 +371,17 @@ struct pch_udc_dev { + struct usb_ctrlrequest setup_data; + unsigned long phys_addr; + void __iomem *base_addr; ++ unsigned bar; + unsigned irq; + struct pch_udc_cfg_data cfg_data; + struct pch_vbus_gpio_data vbus_gpio; + }; + #define to_pch_udc(g) (container_of((g), struct pch_udc_dev, gadget)) + ++#define PCH_UDC_PCI_BAR_QUARK_X1000 0 + #define PCH_UDC_PCI_BAR 1 + #define PCI_DEVICE_ID_INTEL_EG20T_UDC 0x8808 ++#define PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC 0x0939 + #define PCI_VENDOR_ID_ROHM 0x10DB + #define PCI_DEVICE_ID_ML7213_IOH_UDC 0x801D + #define PCI_DEVICE_ID_ML7831_IOH_UDC 0x8808 +@@ -3076,7 +3080,7 @@ static void pch_udc_remove(struct pci_dev *pdev) + iounmap(dev->base_addr); + if (dev->mem_region) + release_mem_region(dev->phys_addr, +- pci_resource_len(pdev, PCH_UDC_PCI_BAR)); ++ pci_resource_len(pdev, dev->bar)); + if (dev->active) + pci_disable_device(pdev); + kfree(dev); +@@ -3144,9 +3148,15 @@ static int pch_udc_probe(struct pci_dev *pdev, + dev->active = 1; + pci_set_drvdata(pdev, dev); + ++ /* Determine BAR based on PCI ID */ ++ if (id->device == PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC) ++ dev->bar = PCH_UDC_PCI_BAR_QUARK_X1000; ++ else ++ dev->bar = PCH_UDC_PCI_BAR; ++ + /* PCI resource allocation */ +- resource = pci_resource_start(pdev, 1); +- len = pci_resource_len(pdev, 1); ++ resource = pci_resource_start(pdev, dev->bar); ++ len = pci_resource_len(pdev, dev->bar); + + if (!request_mem_region(resource, len, KBUILD_MODNAME)) { + dev_err(&pdev->dev, "%s: pci device used already\n", __func__); +@@ -3212,6 +3222,12 @@ finished: + + static const struct pci_device_id pch_udc_pcidev_id[] = { + { ++ PCI_DEVICE(PCI_VENDOR_ID_INTEL, ++ PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC), ++ .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, ++ .class_mask = 0xffffffff, ++ }, ++ { + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EG20T_UDC), + .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, + .class_mask = 0xffffffff, +diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c +index 69b76ef..44e698c 100644 +--- a/drivers/usb/gadget/printer.c ++++ b/drivers/usb/gadget/printer.c +@@ -975,6 +975,15 @@ unknown: + break; + } + /* host either stalls (value < 0) or reports success */ ++ if (value >= 0) { ++ req->length = value; ++ req->zero = value < wLength; ++ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); ++ if (value < 0) { ++ ERROR(dev, "%s:%d Error!\n", __func__, __LINE__); ++ req->status = 0; ++ } ++ } + return value; + } + +diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c +index 27768a7..9ce0b13 100644 +--- a/drivers/usb/gadget/udc-core.c ++++ b/drivers/usb/gadget/udc-core.c +@@ -456,6 +456,11 @@ static ssize_t usb_udc_softconn_store(struct device *dev, + { + struct usb_udc *udc = container_of(dev, struct usb_udc, dev); + ++ if (!udc->driver) { ++ dev_err(dev, "soft-connect without a gadget driver\n"); ++ return -EOPNOTSUPP; ++ } ++ + if (sysfs_streq(buf, "connect")) { + usb_gadget_udc_start(udc->gadget, udc->driver); + usb_gadget_connect(udc->gadget); +diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c +index 142ebd8..1e0b9b9 100644 +--- a/drivers/usb/host/ehci-hcd.c ++++ b/drivers/usb/host/ehci-hcd.c +@@ -792,12 +792,12 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) + ehci->reset_done[i] == 0)) + continue; + +- /* start 20 msec resume signaling from this port, +- * and make khubd collect PORT_STAT_C_SUSPEND to +- * stop that signaling. Use 5 ms extra for safety, +- * like usb_port_resume() does. ++ /* start USB_RESUME_TIMEOUT msec resume signaling from ++ * this port, and make hub_wq collect ++ * PORT_STAT_C_SUSPEND to stop that signaling. + */ +- ehci->reset_done[i] = jiffies + msecs_to_jiffies(25); ++ ehci->reset_done[i] = jiffies + ++ msecs_to_jiffies(USB_RESUME_TIMEOUT); + set_bit(i, &ehci->resuming_ports); + ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); + usb_hcd_start_port_resume(&hcd->self, i); +@@ -970,8 +970,6 @@ rescan: + } + + qh->exception = 1; +- if (ehci->rh_state < EHCI_RH_RUNNING) +- qh->qh_state = QH_STATE_IDLE; + switch (qh->qh_state) { + case QH_STATE_LINKED: + WARN_ON(!list_empty(&qh->qtd_list)); +diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c +index de63775..857953c 100644 +--- a/drivers/usb/host/ehci-hub.c ++++ b/drivers/usb/host/ehci-hub.c +@@ -491,10 +491,13 @@ static int ehci_bus_resume (struct usb_hcd *hcd) + ehci_writel(ehci, temp, &ehci->regs->port_status [i]); + } + +- /* msleep for 20ms only if code is trying to resume port */ ++ /* ++ * msleep for USB_RESUME_TIMEOUT ms only if code is trying to resume ++ * port ++ */ + if (resume_needed) { + spin_unlock_irq(&ehci->lock); +- msleep(20); ++ msleep(USB_RESUME_TIMEOUT); + spin_lock_irq(&ehci->lock); + if (ehci->shutdown) + goto shutdown; +@@ -962,7 +965,7 @@ static int ehci_hub_control ( + temp &= ~PORT_WAKE_BITS; + ehci_writel(ehci, temp | PORT_RESUME, status_reg); + ehci->reset_done[wIndex] = jiffies +- + msecs_to_jiffies(20); ++ + msecs_to_jiffies(USB_RESUME_TIMEOUT); + set_bit(wIndex, &ehci->resuming_ports); + usb_hcd_start_port_resume(&hcd->self, wIndex); + break; +@@ -1248,7 +1251,7 @@ static int ehci_hub_control ( + if (selector == EHSET_TEST_SINGLE_STEP_SET_FEATURE) { + spin_unlock_irqrestore(&ehci->lock, flags); + retval = ehset_single_step_set_feature(hcd, +- wIndex); ++ wIndex + 1); + spin_lock_irqsave(&ehci->lock, flags); + break; + } +diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c +index 3e86bf4..ca7b964 100644 +--- a/drivers/usb/host/ehci-pci.c ++++ b/drivers/usb/host/ehci-pci.c +@@ -35,6 +35,21 @@ static const char hcd_name[] = "ehci-pci"; + #define PCI_DEVICE_ID_INTEL_CE4100_USB 0x2e70 + + /*-------------------------------------------------------------------------*/ ++#define PCI_DEVICE_ID_INTEL_QUARK_X1000_SOC 0x0939 ++static inline bool is_intel_quark_x1000(struct pci_dev *pdev) ++{ ++ return pdev->vendor == PCI_VENDOR_ID_INTEL && ++ pdev->device == PCI_DEVICE_ID_INTEL_QUARK_X1000_SOC; ++} ++ ++/* ++ * 0x84 is the offset of in/out threshold register, ++ * and it is the same offset as the register of 'hostpc'. ++ */ ++#define intel_quark_x1000_insnreg01 hostpc ++ ++/* Maximum usable threshold value is 0x7f dwords for both IN and OUT */ ++#define INTEL_QUARK_X1000_EHCI_MAX_THRESHOLD 0x007f007f + + /* called after powerup, by probe or system-pm "wakeup" */ + static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) +@@ -50,6 +65,16 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) + if (!retval) + ehci_dbg(ehci, "MWI active\n"); + ++ /* Reset the threshold limit */ ++ if (is_intel_quark_x1000(pdev)) { ++ /* ++ * For the Intel QUARK X1000, raise the I/O threshold to the ++ * maximum usable value in order to improve performance. ++ */ ++ ehci_writel(ehci, INTEL_QUARK_X1000_EHCI_MAX_THRESHOLD, ++ ehci->regs->intel_quark_x1000_insnreg01); ++ } ++ + return 0; + } + +diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c +index e113fd7..c399606 100644 +--- a/drivers/usb/host/ehci-sched.c ++++ b/drivers/usb/host/ehci-sched.c +@@ -1581,6 +1581,10 @@ iso_stream_schedule ( + else + next = (now + 2 + 7) & ~0x07; /* full frame cache */ + ++ /* If needed, initialize last_iso_frame so that this URB will be seen */ ++ if (ehci->isoc_count == 0) ++ ehci->last_iso_frame = now >> 3; ++ + /* + * Use ehci->last_iso_frame as the base. There can't be any + * TDs scheduled for earlier than that. +@@ -1671,10 +1675,6 @@ iso_stream_schedule ( + urb->start_frame = start & (mod - 1); + if (!stream->highspeed) + urb->start_frame >>= 3; +- +- /* Make sure scan_isoc() sees these */ +- if (ehci->isoc_count == 0) +- ehci->last_iso_frame = now >> 3; + return status; + + fail: +diff --git a/drivers/usb/host/ehci-sysfs.c b/drivers/usb/host/ehci-sysfs.c +index f6459df..94054da 100644 +--- a/drivers/usb/host/ehci-sysfs.c ++++ b/drivers/usb/host/ehci-sysfs.c +@@ -29,7 +29,7 @@ static ssize_t show_companion(struct device *dev, + int count = PAGE_SIZE; + char *ptr = buf; + +- ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); ++ ehci = hcd_to_ehci(dev_get_drvdata(dev)); + nports = HCS_N_PORTS(ehci->hcs_params); + + for (index = 0; index < nports; ++index) { +@@ -54,7 +54,7 @@ static ssize_t store_companion(struct device *dev, + struct ehci_hcd *ehci; + int portnum, new_owner; + +- ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); ++ ehci = hcd_to_ehci(dev_get_drvdata(dev)); + new_owner = PORT_OWNER; /* Owned by companion */ + if (sscanf(buf, "%d", &portnum) != 1) + return -EINVAL; +@@ -85,7 +85,7 @@ static ssize_t show_uframe_periodic_max(struct device *dev, + struct ehci_hcd *ehci; + int n; + +- ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); ++ ehci = hcd_to_ehci(dev_get_drvdata(dev)); + n = scnprintf(buf, PAGE_SIZE, "%d\n", ehci->uframe_periodic_max); + return n; + } +@@ -101,7 +101,7 @@ static ssize_t store_uframe_periodic_max(struct device *dev, + unsigned long flags; + ssize_t ret; + +- ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); ++ ehci = hcd_to_ehci(dev_get_drvdata(dev)); + if (kstrtouint(buf, 0, &uframe_periodic_max) < 0) + return -EINVAL; + +diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c +index 98a89d1..8aa4ba0 100644 +--- a/drivers/usb/host/fotg210-hcd.c ++++ b/drivers/usb/host/fotg210-hcd.c +@@ -1595,7 +1595,7 @@ static int fotg210_hub_control( + /* resume signaling for 20 msec */ + fotg210_writel(fotg210, temp | PORT_RESUME, status_reg); + fotg210->reset_done[wIndex] = jiffies +- + msecs_to_jiffies(20); ++ + msecs_to_jiffies(USB_RESUME_TIMEOUT); + break; + case USB_PORT_FEAT_C_SUSPEND: + clear_bit(wIndex, &fotg210->port_c_suspend); +diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c +index ba94990..3e3926a 100644 +--- a/drivers/usb/host/fusbh200-hcd.c ++++ b/drivers/usb/host/fusbh200-hcd.c +@@ -1550,10 +1550,9 @@ static int fusbh200_hub_control ( + if ((temp & PORT_PE) == 0) + goto error; + +- /* resume signaling for 20 msec */ + fusbh200_writel(fusbh200, temp | PORT_RESUME, status_reg); + fusbh200->reset_done[wIndex] = jiffies +- + msecs_to_jiffies(20); ++ + msecs_to_jiffies(USB_RESUME_TIMEOUT); + break; + case USB_PORT_FEAT_C_SUSPEND: + clear_bit(wIndex, &fusbh200->port_c_suspend); +diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c +index 240e792..b62298f 100644 +--- a/drivers/usb/host/isp116x-hcd.c ++++ b/drivers/usb/host/isp116x-hcd.c +@@ -1487,7 +1487,7 @@ static int isp116x_bus_resume(struct usb_hcd *hcd) + spin_unlock_irq(&isp116x->lock); + + hcd->state = HC_STATE_RESUMING; +- msleep(20); ++ msleep(USB_RESUME_TIMEOUT); + + /* Go operational */ + spin_lock_irq(&isp116x->lock); +diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c +index 45032e9..04f2186 100644 +--- a/drivers/usb/host/ohci-dbg.c ++++ b/drivers/usb/host/ohci-dbg.c +@@ -236,7 +236,7 @@ ohci_dump_roothub ( + } + } + +-static void ohci_dump (struct ohci_hcd *controller, int verbose) ++static void ohci_dump(struct ohci_hcd *controller) + { + ohci_dbg (controller, "OHCI controller state\n"); + +@@ -464,15 +464,16 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) + static ssize_t fill_async_buffer(struct debug_buffer *buf) + { + struct ohci_hcd *ohci; +- size_t temp; ++ size_t temp, size; + unsigned long flags; + + ohci = buf->ohci; ++ size = PAGE_SIZE; + + /* display control and bulk lists together, for simplicity */ + spin_lock_irqsave (&ohci->lock, flags); +- temp = show_list(ohci, buf->page, buf->count, ohci->ed_controltail); +- temp += show_list(ohci, buf->page + temp, buf->count - temp, ++ temp = show_list(ohci, buf->page, size, ohci->ed_controltail); ++ temp += show_list(ohci, buf->page + temp, size - temp, + ohci->ed_bulktail); + spin_unlock_irqrestore (&ohci->lock, flags); + +diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c +index 3586460..34fc86c 100644 +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -76,8 +76,8 @@ static const char hcd_name [] = "ohci_hcd"; + #include "ohci.h" + #include "pci-quirks.h" + +-static void ohci_dump (struct ohci_hcd *ohci, int verbose); +-static void ohci_stop (struct usb_hcd *hcd); ++static void ohci_dump(struct ohci_hcd *ohci); ++static void ohci_stop(struct usb_hcd *hcd); + + #include "ohci-hub.c" + #include "ohci-dbg.c" +@@ -744,7 +744,7 @@ retry: + ohci->ed_to_check = NULL; + } + +- ohci_dump (ohci, 1); ++ ohci_dump(ohci); + + return 0; + } +@@ -825,7 +825,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) + usb_hc_died(hcd); + } + +- ohci_dump (ohci, 1); ++ ohci_dump(ohci); + ohci_usb_reset (ohci); + } + +@@ -925,7 +925,7 @@ static void ohci_stop (struct usb_hcd *hcd) + { + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + +- ohci_dump (ohci, 1); ++ ohci_dump(ohci); + + if (quirk_nec(ohci)) + flush_work(&ohci->nec_work); +diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c +index d4253e3..a8bde5b 100644 +--- a/drivers/usb/host/ohci-q.c ++++ b/drivers/usb/host/ohci-q.c +@@ -311,8 +311,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) + * - ED_OPER: when there's any request queued, the ED gets rescheduled + * immediately. HC should be working on them. + * +- * - ED_IDLE: when there's no TD queue. there's no reason for the HC +- * to care about this ED; safe to disable the endpoint. ++ * - ED_IDLE: when there's no TD queue or the HC isn't running. + * + * When finish_unlinks() runs later, after SOF interrupt, it will often + * complete one or more URB unlinks before making that state change. +@@ -926,6 +925,10 @@ rescan_all: + int completed, modified; + __hc32 *prev; + ++ /* Is this ED already invisible to the hardware? */ ++ if (ed->state == ED_IDLE) ++ goto ed_idle; ++ + /* only take off EDs that the HC isn't using, accounting for + * frame counter wraps and EDs with partially retired TDs + */ +@@ -955,12 +958,20 @@ skip_ed: + } + } + ++ /* ED's now officially unlinked, hc doesn't see */ ++ ed->state = ED_IDLE; ++ if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT) ++ ohci->eds_scheduled--; ++ ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H); ++ ed->hwNextED = 0; ++ wmb(); ++ ed->hwINFO &= ~cpu_to_hc32(ohci, ED_SKIP | ED_DEQUEUE); ++ed_idle: ++ + /* reentrancy: if we drop the schedule lock, someone might + * have modified this list. normally it's just prepending + * entries (which we'd ignore), but paranoia won't hurt. + */ +- *last = ed->ed_next; +- ed->ed_next = NULL; + modified = 0; + + /* unlink urbs as requested, but rescan the list after +@@ -1018,19 +1029,20 @@ rescan_this: + if (completed && !list_empty (&ed->td_list)) + goto rescan_this; + +- /* ED's now officially unlinked, hc doesn't see */ +- ed->state = ED_IDLE; +- if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT) +- ohci->eds_scheduled--; +- ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H); +- ed->hwNextED = 0; +- wmb (); +- ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP | ED_DEQUEUE); +- +- /* but if there's work queued, reschedule */ +- if (!list_empty (&ed->td_list)) { +- if (ohci->rh_state == OHCI_RH_RUNNING) +- ed_schedule (ohci, ed); ++ /* ++ * If no TDs are queued, take ED off the ed_rm_list. ++ * Otherwise, if the HC is running, reschedule. ++ * If not, leave it on the list for further dequeues. ++ */ ++ if (list_empty(&ed->td_list)) { ++ *last = ed->ed_next; ++ ed->ed_next = NULL; ++ } else if (ohci->rh_state == OHCI_RH_RUNNING) { ++ *last = ed->ed_next; ++ ed->ed_next = NULL; ++ ed_schedule(ohci, ed); ++ } else { ++ last = &ed->ed_next; + } + + if (modified) +diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c +index e07248b..1b1e6e0 100644 +--- a/drivers/usb/host/oxu210hp-hcd.c ++++ b/drivers/usb/host/oxu210hp-hcd.c +@@ -2500,11 +2500,12 @@ static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd) + || oxu->reset_done[i] != 0) + continue; + +- /* start 20 msec resume signaling from this port, +- * and make khubd collect PORT_STAT_C_SUSPEND to ++ /* start USB_RESUME_TIMEOUT resume signaling from this ++ * port, and make hub_wq collect PORT_STAT_C_SUSPEND to + * stop that signaling. + */ +- oxu->reset_done[i] = jiffies + msecs_to_jiffies(20); ++ oxu->reset_done[i] = jiffies + ++ msecs_to_jiffies(USB_RESUME_TIMEOUT); + oxu_dbg(oxu, "port %d remote wakeup\n", i + 1); + mod_timer(&hcd->rh_timer, oxu->reset_done[i]); + } +diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c +index 2f3aceb..f4e6b94 100644 +--- a/drivers/usb/host/pci-quirks.c ++++ b/drivers/usb/host/pci-quirks.c +@@ -571,7 +571,8 @@ static void quirk_usb_handoff_ohci(struct pci_dev *pdev) + { + void __iomem *base; + u32 control; +- u32 fminterval; ++ u32 fminterval = 0; ++ bool no_fminterval = false; + int cnt; + + if (!mmio_resource_enabled(pdev, 0)) +@@ -581,6 +582,13 @@ static void quirk_usb_handoff_ohci(struct pci_dev *pdev) + if (base == NULL) + return; + ++ /* ++ * ULi M5237 OHCI controller locks the whole system when accessing ++ * the OHCI_FMINTERVAL offset. ++ */ ++ if (pdev->vendor == PCI_VENDOR_ID_AL && pdev->device == 0x5237) ++ no_fminterval = true; ++ + control = readl(base + OHCI_CONTROL); + + /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ +@@ -619,7 +627,9 @@ static void quirk_usb_handoff_ohci(struct pci_dev *pdev) + } + + /* software reset of the controller, preserving HcFmInterval */ +- fminterval = readl(base + OHCI_FMINTERVAL); ++ if (!no_fminterval) ++ fminterval = readl(base + OHCI_FMINTERVAL); ++ + writel(OHCI_HCR, base + OHCI_CMDSTATUS); + + /* reset requires max 10 us delay */ +@@ -628,7 +638,9 @@ static void quirk_usb_handoff_ohci(struct pci_dev *pdev) + break; + udelay(1); + } +- writel(fminterval, base + OHCI_FMINTERVAL); ++ ++ if (!no_fminterval) ++ writel(fminterval, base + OHCI_FMINTERVAL); + + /* Now the controller is safely in SUSPEND and nothing can wake it up */ + iounmap(base); +diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c +index 110b4b9..f130bb2 100644 +--- a/drivers/usb/host/r8a66597-hcd.c ++++ b/drivers/usb/host/r8a66597-hcd.c +@@ -2300,7 +2300,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd) + rh->port &= ~USB_PORT_STAT_SUSPEND; + rh->port |= USB_PORT_STAT_C_SUSPEND << 16; + r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg); +- msleep(50); ++ msleep(USB_RESUME_TIMEOUT); + r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg); + } + +diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c +index a517151..0f53cc8 100644 +--- a/drivers/usb/host/sl811-hcd.c ++++ b/drivers/usb/host/sl811-hcd.c +@@ -1259,7 +1259,7 @@ sl811h_hub_control( + sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); + + mod_timer(&sl811->timer, jiffies +- + msecs_to_jiffies(20)); ++ + msecs_to_jiffies(USB_RESUME_TIMEOUT)); + break; + case USB_PORT_FEAT_POWER: + port_power(sl811, 0); +diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c +index 93e17b1..98c66d8 100644 +--- a/drivers/usb/host/uhci-hub.c ++++ b/drivers/usb/host/uhci-hub.c +@@ -165,7 +165,7 @@ static void uhci_check_ports(struct uhci_hcd *uhci) + /* Port received a wakeup request */ + set_bit(port, &uhci->resuming_ports); + uhci->ports_timeout = jiffies + +- msecs_to_jiffies(25); ++ msecs_to_jiffies(USB_RESUME_TIMEOUT); + usb_hcd_start_port_resume( + &uhci_to_hcd(uhci)->self, port); + +@@ -337,7 +337,8 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + uhci_finish_suspend(uhci, port, port_addr); + + /* USB v2.0 7.1.7.5 */ +- uhci->ports_timeout = jiffies + msecs_to_jiffies(50); ++ uhci->ports_timeout = jiffies + ++ msecs_to_jiffies(USB_RESUME_TIMEOUT); + break; + case USB_PORT_FEAT_POWER: + /* UHCI has no power switching */ +diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c +index 9992fbf..5c95765 100644 +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -383,6 +383,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, + status = PORT_PLC; + port_change_bit = "link state"; + break; ++ case USB_PORT_FEAT_C_PORT_CONFIG_ERROR: ++ status = PORT_CEC; ++ port_change_bit = "config error"; ++ break; + default: + /* Should never happen */ + return; +@@ -470,15 +474,19 @@ static void xhci_hub_report_usb2_link_state(u32 *status, u32 status_reg) + } + + /* Updates Link Status for super Speed port */ +-static void xhci_hub_report_usb3_link_state(u32 *status, u32 status_reg) ++static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, ++ u32 *status, u32 status_reg) + { + u32 pls = status_reg & PORT_PLS_MASK; + + /* resume state is a xHCI internal state. +- * Do not report it to usb core. ++ * Do not report it to usb core, instead, pretend to be U3, ++ * thus usb core knows it's not ready for transfer + */ +- if (pls == XDEV_RESUME) ++ if (pls == XDEV_RESUME) { ++ *status |= USB_SS_PORT_LS_U3; + return; ++ } + + /* When the CAS bit is set then warm reset + * should be performed on port +@@ -509,7 +517,8 @@ static void xhci_hub_report_usb3_link_state(u32 *status, u32 status_reg) + * in which sometimes the port enters compliance mode + * caused by a delay on the host-device negotiation. + */ +- if (pls == USB_SS_PORT_LS_COMP_MOD) ++ if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && ++ (pls == USB_SS_PORT_LS_COMP_MOD)) + pls |= USB_PORT_STAT_CONNECTION; + } + +@@ -578,10 +587,19 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, + status |= USB_PORT_STAT_C_RESET << 16; + /* USB3.0 only */ + if (hcd->speed == HCD_USB3) { +- if ((raw_port_status & PORT_PLC)) ++ /* Port link change with port in resume state should not be ++ * reported to usbcore, as this is an internal state to be ++ * handled by xhci driver. Reporting PLC to usbcore may ++ * cause usbcore clearing PLC first and port change event ++ * irq won't be generated. ++ */ ++ if ((raw_port_status & PORT_PLC) && ++ (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) + status |= USB_PORT_STAT_C_LINK_STATE << 16; + if ((raw_port_status & PORT_WRC)) + status |= USB_PORT_STAT_C_BH_RESET << 16; ++ if ((raw_port_status & PORT_CEC)) ++ status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; + } + + if (hcd->speed != HCD_USB3) { +@@ -668,7 +686,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, + } + /* Update Port Link State */ + if (hcd->speed == HCD_USB3) { +- xhci_hub_report_usb3_link_state(&status, raw_port_status); ++ xhci_hub_report_usb3_link_state(xhci, &status, raw_port_status); + /* + * Verify if all USB3 Ports Have entered U0 already. + * Delete Compliance Mode Timer if so. +@@ -997,6 +1015,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + case USB_PORT_FEAT_C_OVER_CURRENT: + case USB_PORT_FEAT_C_ENABLE: + case USB_PORT_FEAT_C_PORT_LINK_STATE: ++ case USB_PORT_FEAT_C_PORT_CONFIG_ERROR: + xhci_clear_port_change_bit(xhci, wValue, wIndex, + port_array[wIndex], temp); + break; +@@ -1061,7 +1080,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) + */ + status = bus_state->resuming_ports; + +- mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC; ++ mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC | PORT_CEC; + + spin_lock_irqsave(&xhci->lock, flags); + /* For each port, did anything change? If so, set that bit in buf. */ +@@ -1105,10 +1124,10 @@ int xhci_bus_suspend(struct usb_hcd *hcd) + spin_lock_irqsave(&xhci->lock, flags); + + if (hcd->self.root_hub->do_remote_wakeup) { +- if (bus_state->resuming_ports) { ++ if (bus_state->resuming_ports || /* USB2 */ ++ bus_state->port_remote_wakeup) { /* USB3 */ + spin_unlock_irqrestore(&xhci->lock, flags); +- xhci_dbg(xhci, "suspend failed because " +- "a port is resuming\n"); ++ xhci_dbg(xhci, "suspend failed because a port is resuming\n"); + return -EBUSY; + } + } +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index 4133a00..f8893b3 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -1331,10 +1331,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, + /* Attempt to use the ring cache */ + if (virt_dev->num_rings_cached == 0) + return -ENOMEM; ++ virt_dev->num_rings_cached--; + virt_dev->eps[ep_index].new_ring = + virt_dev->ring_cache[virt_dev->num_rings_cached]; + virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL; +- virt_dev->num_rings_cached--; + xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring, + 1, type); + } +@@ -1723,7 +1723,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) + } + + num_ports = HCS_MAX_PORTS(xhci->hcs_params1); +- for (i = 0; i < num_ports; i++) { ++ for (i = 0; i < num_ports && xhci->rh_bw; i++) { + struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table; + for (j = 0; j < XHCI_MAX_INTERVAL; j++) { + struct list_head *ep = &bwt->interval_bw[j].endpoints; +diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c +index 08a5f92..eb3399f 100644 +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -101,9 +101,14 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + /* AMD PLL quirk */ + if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info()) + xhci->quirks |= XHCI_AMD_PLL_FIX; ++ ++ if (pdev->vendor == PCI_VENDOR_ID_AMD) ++ xhci->quirks |= XHCI_TRUST_TX_LENGTH; ++ + if (pdev->vendor == PCI_VENDOR_ID_INTEL) { + xhci->quirks |= XHCI_LPM_SUPPORT; + xhci->quirks |= XHCI_INTEL_HOST; ++ xhci->quirks |= XHCI_AVOID_BEI; + } + if (pdev->vendor == PCI_VENDOR_ID_INTEL && + pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) { +@@ -119,7 +124,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + * PPT chipsets. + */ + xhci->quirks |= XHCI_SPURIOUS_REBOOT; +- xhci->quirks |= XHCI_AVOID_BEI; + } + if (pdev->vendor == PCI_VENDOR_ID_INTEL && + (pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI || +@@ -277,7 +281,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) + if (xhci_compliance_mode_recovery_timer_quirk_check()) + pdev->no_d3cold = true; + +- return xhci_suspend(xhci); ++ return xhci_suspend(xhci, do_wakeup); + } + + static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index 8abda5c..1d5ba3c 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -205,7 +205,15 @@ static int xhci_plat_suspend(struct device *dev) + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + +- return xhci_suspend(xhci); ++ /* ++ * xhci_suspend() needs `do_wakeup` to know whether host is allowed ++ * to do wakeup during suspend. Since xhci_plat_suspend is currently ++ * only designed for system suspend, device_may_wakeup() is enough ++ * to dertermine whether host is allowed to do wakeup. Need to ++ * reconsider this when xhci_plat_suspend enlarges its scope, e.g., ++ * also applies to runtime suspend. ++ */ ++ return xhci_suspend(xhci, device_may_wakeup(dev)); + } + + static int xhci_plat_resume(struct device *dev) +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index 65091d9..a365e97 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -86,7 +86,7 @@ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, + return 0; + /* offset in TRBs */ + segment_offset = trb - seg->trbs; +- if (segment_offset > TRBS_PER_SEGMENT) ++ if (segment_offset >= TRBS_PER_SEGMENT) + return 0; + return seg->dma + (segment_offset * sizeof(*trb)); + } +@@ -1180,9 +1180,8 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id, + false); + xhci_ring_cmd_db(xhci); + } else { +- /* Clear our internal halted state and restart the ring(s) */ ++ /* Clear our internal halted state */ + xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_HALTED; +- ring_doorbell_for_active_rings(xhci, slot_id, ep_index); + } + } + +@@ -1741,6 +1740,9 @@ static void handle_port_status(struct xhci_hcd *xhci, + usb_hcd_resume_root_hub(hcd); + } + ++ if (hcd->speed == HCD_USB3 && (temp & PORT_PLS_MASK) == XDEV_INACTIVE) ++ bus_state->port_remote_wakeup &= ~(1 << faked_port_index); ++ + if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) { + xhci_dbg(xhci, "port resume event for port %d\n", port_id); + +@@ -1769,7 +1771,7 @@ static void handle_port_status(struct xhci_hcd *xhci, + } else { + xhci_dbg(xhci, "resume HS port %d\n", port_id); + bus_state->resume_done[faked_port_index] = jiffies + +- msecs_to_jiffies(20); ++ msecs_to_jiffies(USB_RESUME_TIMEOUT); + set_bit(faked_port_index, &bus_state->resuming_ports); + mod_timer(&hcd->rh_timer, + bus_state->resume_done[faked_port_index]); +@@ -1999,22 +2001,13 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td, + ep->stopped_td = td; + return 0; + } else { +- if (trb_comp_code == COMP_STALL) { +- /* The transfer is completed from the driver's +- * perspective, but we need to issue a set dequeue +- * command for this stalled endpoint to move the dequeue +- * pointer past the TD. We can't do that here because +- * the halt condition must be cleared first. Let the +- * USB class driver clear the stall later. +- */ +- ep->stopped_td = td; +- ep->stopped_stream = ep_ring->stream_id; +- } else if (xhci_requires_manual_halt_cleanup(xhci, +- ep_ctx, trb_comp_code)) { +- /* Other types of errors halt the endpoint, but the +- * class driver doesn't call usb_reset_endpoint() unless +- * the error is -EPIPE. Clear the halted status in the +- * xHCI hardware manually. ++ if (trb_comp_code == COMP_STALL || ++ xhci_requires_manual_halt_cleanup(xhci, ep_ctx, ++ trb_comp_code)) { ++ /* Issue a reset endpoint command to clear the host side ++ * halt, followed by a set dequeue command to move the ++ * dequeue pointer past the TD. ++ * The class driver clears the device side halt later. + */ + xhci_cleanup_halted_endpoint(xhci, + slot_id, ep_index, ep_ring->stream_id, +@@ -2134,9 +2127,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, + else + td->urb->actual_length = 0; + +- xhci_cleanup_halted_endpoint(xhci, +- slot_id, ep_index, 0, td, event_trb); +- return finish_td(xhci, td, event_trb, event, ep, status, true); ++ return finish_td(xhci, td, event_trb, event, ep, status, false); + } + /* + * Did we transfer any data, despite the errors that might have +@@ -2145,7 +2136,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, + if (event_trb != ep_ring->dequeue) { + /* The event was for the status stage */ + if (event_trb == td->last_trb) { +- if (td->urb->actual_length != 0) { ++ if (td->urb_length_set) { + /* Don't overwrite a previously set error code + */ + if ((*status == -EINPROGRESS || *status == 0) && +@@ -2159,7 +2150,13 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, + td->urb->transfer_buffer_length; + } + } else { +- /* Maybe the event was for the data stage? */ ++ /* ++ * Maybe the event was for the data stage? If so, update ++ * already the actual_length of the URB and flag it as ++ * set, so that it is not overwritten in the event for ++ * the last TRB. ++ */ ++ td->urb_length_set = true; + td->urb->actual_length = + td->urb->transfer_buffer_length - + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); +@@ -2219,8 +2216,13 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, + break; + case COMP_DEV_ERR: + case COMP_STALL: ++ frame->status = -EPROTO; ++ skip_td = true; ++ break; + case COMP_TX_ERR: + frame->status = -EPROTO; ++ if (event_trb != td->last_trb) ++ return 0; + skip_td = true; + break; + case COMP_STOP: +@@ -2612,7 +2614,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, + * last TRB of the previous TD. The command completion handle + * will take care the rest. + */ +- if (!event_seg && trb_comp_code == COMP_STOP_INVAL) { ++ if (!event_seg && (trb_comp_code == COMP_STOP || ++ trb_comp_code == COMP_STOP_INVAL)) { + ret = 0; + goto cleanup; + } +@@ -2689,17 +2692,8 @@ cleanup: + if (ret) { + urb = td->urb; + urb_priv = urb->hcpriv; +- /* Leave the TD around for the reset endpoint function +- * to use(but only if it's not a control endpoint, +- * since we already queued the Set TR dequeue pointer +- * command for stalled control endpoints). +- */ +- if (usb_endpoint_xfer_control(&urb->ep->desc) || +- (trb_comp_code != COMP_STALL && +- trb_comp_code != COMP_BABBLE)) +- xhci_urb_free_priv(xhci, urb_priv); +- else +- kfree(urb_priv); ++ ++ xhci_urb_free_priv(xhci, urb_priv); + + usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb); + if ((urb->actual_length != urb->transfer_buffer_length && +@@ -2836,7 +2830,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) + xhci_halt(xhci); + hw_died: + spin_unlock(&xhci->lock); +- return -ESHUTDOWN; ++ return IRQ_HANDLED; + } + + /* +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index ab83104..fc61e663b 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -35,6 +35,8 @@ + #define DRIVER_AUTHOR "Sarah Sharp" + #define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver" + ++#define PORT_WAKE_BITS (PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E) ++ + /* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */ + static int link_quirk; + module_param(link_quirk, int, S_IRUGO | S_IWUSR); +@@ -842,13 +844,47 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci) + xhci_set_cmd_ring_deq(xhci); + } + ++static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci) ++{ ++ int port_index; ++ __le32 __iomem **port_array; ++ unsigned long flags; ++ u32 t1, t2; ++ ++ spin_lock_irqsave(&xhci->lock, flags); ++ ++ /* disble usb3 ports Wake bits*/ ++ port_index = xhci->num_usb3_ports; ++ port_array = xhci->usb3_ports; ++ while (port_index--) { ++ t1 = readl(port_array[port_index]); ++ t1 = xhci_port_state_to_neutral(t1); ++ t2 = t1 & ~PORT_WAKE_BITS; ++ if (t1 != t2) ++ writel(t2, port_array[port_index]); ++ } ++ ++ /* disble usb2 ports Wake bits*/ ++ port_index = xhci->num_usb2_ports; ++ port_array = xhci->usb2_ports; ++ while (port_index--) { ++ t1 = readl(port_array[port_index]); ++ t1 = xhci_port_state_to_neutral(t1); ++ t2 = t1 & ~PORT_WAKE_BITS; ++ if (t1 != t2) ++ writel(t2, port_array[port_index]); ++ } ++ ++ spin_unlock_irqrestore(&xhci->lock, flags); ++} ++ + /* + * Stop HC (not bus-specific) + * + * This is called when the machine transition into S3/S4 mode. + * + */ +-int xhci_suspend(struct xhci_hcd *xhci) ++int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) + { + int rc = 0; + unsigned int delay = XHCI_MAX_HALT_USEC; +@@ -859,6 +895,10 @@ int xhci_suspend(struct xhci_hcd *xhci) + xhci->shared_hcd->state != HC_STATE_SUSPENDED) + return -EINVAL; + ++ /* Clear root port wake on bits if wakeup not allowed. */ ++ if (!do_wakeup) ++ xhci_disable_port_wake_on_bits(xhci); ++ + /* Don't poll the roothubs on bus suspend. */ + xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); +@@ -2885,63 +2925,33 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, + } + } + +-/* Deal with stalled endpoints. The core should have sent the control message +- * to clear the halt condition. However, we need to make the xHCI hardware +- * reset its sequence number, since a device will expect a sequence number of +- * zero after the halt condition is cleared. ++/* Called when clearing halted device. The core should have sent the control ++ * message to clear the device halt condition. The host side of the halt should ++ * already be cleared with a reset endpoint command issued when the STALL tx ++ * event was received. ++ * + * Context: in_interrupt + */ ++ + void xhci_endpoint_reset(struct usb_hcd *hcd, + struct usb_host_endpoint *ep) + { + struct xhci_hcd *xhci; +- struct usb_device *udev; +- unsigned int ep_index; +- unsigned long flags; +- int ret; +- struct xhci_virt_ep *virt_ep; + + xhci = hcd_to_xhci(hcd); +- udev = (struct usb_device *) ep->hcpriv; +- /* Called with a root hub endpoint (or an endpoint that wasn't added +- * with xhci_add_endpoint() +- */ +- if (!ep->hcpriv) +- return; +- ep_index = xhci_get_endpoint_index(&ep->desc); +- virt_ep = &xhci->devs[udev->slot_id]->eps[ep_index]; +- if (!virt_ep->stopped_td) { +- xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep, +- "Endpoint 0x%x not halted, refusing to reset.", +- ep->desc.bEndpointAddress); +- return; +- } +- if (usb_endpoint_xfer_control(&ep->desc)) { +- xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep, +- "Control endpoint stall already handled."); +- return; +- } + +- xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep, +- "Queueing reset endpoint command"); +- spin_lock_irqsave(&xhci->lock, flags); +- ret = xhci_queue_reset_ep(xhci, udev->slot_id, ep_index); + /* +- * Can't change the ring dequeue pointer until it's transitioned to the +- * stopped state, which is only upon a successful reset endpoint +- * command. Better hope that last command worked! ++ * We might need to implement the config ep cmd in xhci 4.8.1 note: ++ * The Reset Endpoint Command may only be issued to endpoints in the ++ * Halted state. If software wishes reset the Data Toggle or Sequence ++ * Number of an endpoint that isn't in the Halted state, then software ++ * may issue a Configure Endpoint Command with the Drop and Add bits set ++ * for the target endpoint. that is in the Stopped state. + */ +- if (!ret) { +- xhci_cleanup_stalled_ring(xhci, udev, ep_index); +- kfree(virt_ep->stopped_td); +- xhci_ring_cmd_db(xhci); +- } +- virt_ep->stopped_td = NULL; +- virt_ep->stopped_stream = 0; +- spin_unlock_irqrestore(&xhci->lock, flags); + +- if (ret) +- xhci_warn(xhci, "FIXME allocate a new ring segment\n"); ++ /* For now just print debug to follow the situation */ ++ xhci_dbg(xhci, "Endpoint 0x%x ep reset callback called\n", ++ ep->desc.bEndpointAddress); + } + + static int xhci_check_streams_endpoint(struct xhci_hcd *xhci, +@@ -3414,6 +3424,9 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) + return -EINVAL; + } + ++ if (virt_dev->tt_info) ++ old_active_eps = virt_dev->tt_info->active_eps; ++ + if (virt_dev->udev != udev) { + /* If the virt_dev and the udev does not match, this virt_dev + * may belong to another udev. +@@ -3928,13 +3941,21 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci, + int ret; + + spin_lock_irqsave(&xhci->lock, flags); +- if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) { ++ ++ virt_dev = xhci->devs[udev->slot_id]; ++ ++ /* ++ * virt_dev might not exists yet if xHC resumed from hibernate (S4) and ++ * xHC was re-initialized. Exit latency will be set later after ++ * hub_port_finish_reset() is done and xhci->devs[] are re-allocated ++ */ ++ ++ if (!virt_dev || max_exit_latency == virt_dev->current_mel) { + spin_unlock_irqrestore(&xhci->lock, flags); + return 0; + } + + /* Attempt to issue an Evaluate Context command to change the MEL. */ +- virt_dev = xhci->devs[udev->slot_id]; + command = xhci->lpm_command; + ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx); + if (!ctrl_ctx) { +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 8faef64..c167485 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1,3 +1,4 @@ ++ + /* + * xHCI host controller driver + * +@@ -88,9 +89,10 @@ struct xhci_cap_regs { + #define HCS_IST(p) (((p) >> 0) & 0xf) + /* bits 4:7, max number of Event Ring segments */ + #define HCS_ERST_MAX(p) (((p) >> 4) & 0xf) ++/* bits 21:25 Hi 5 bits of Scratchpad buffers SW must allocate for the HW */ + /* bit 26 Scratchpad restore - for save/restore HW state - not used yet */ +-/* bits 27:31 number of Scratchpad buffers SW must allocate for the HW */ +-#define HCS_MAX_SCRATCHPAD(p) (((p) >> 27) & 0x1f) ++/* bits 27:31 Lo 5 bits of Scratchpad buffers SW must allocate for the HW */ ++#define HCS_MAX_SCRATCHPAD(p) ((((p) >> 16) & 0x3e0) | (((p) >> 27) & 0x1f)) + + /* HCSPARAMS3 - hcs_params3 - bitmasks */ + /* bits 0:7, Max U1 to U0 latency for the roothub ports */ +@@ -283,6 +285,7 @@ struct xhci_op_regs { + #define XDEV_U0 (0x0 << 5) + #define XDEV_U2 (0x2 << 5) + #define XDEV_U3 (0x3 << 5) ++#define XDEV_INACTIVE (0x6 << 5) + #define XDEV_RESUME (0xf << 5) + /* true: port has power (see HCC_PPC) */ + #define PORT_POWER (1 << 9) +@@ -1266,7 +1269,7 @@ union xhci_trb { + * since the command ring is 64-byte aligned. + * It must also be greater than 16. + */ +-#define TRBS_PER_SEGMENT 64 ++#define TRBS_PER_SEGMENT 256 + /* Allow two commands + a link TRB, along with any reserved command TRBs */ + #define MAX_RSVD_CMD_TRBS (TRBS_PER_SEGMENT - 3) + #define TRB_SEGMENT_SIZE (TRBS_PER_SEGMENT*16) +@@ -1289,6 +1292,8 @@ struct xhci_td { + struct xhci_segment *start_seg; + union xhci_trb *first_trb; + union xhci_trb *last_trb; ++ /* actual_length of the URB has already been set */ ++ bool urb_length_set; + }; + + /* xHCI command default timeout value */ +@@ -1760,7 +1765,7 @@ void xhci_shutdown(struct usb_hcd *hcd); + int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks); + + #ifdef CONFIG_PM +-int xhci_suspend(struct xhci_hcd *xhci); ++int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup); + int xhci_resume(struct xhci_hcd *xhci, bool hibernated); + #else + #define xhci_suspend NULL +diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c +index de98906..0aef801 100644 +--- a/drivers/usb/misc/sisusbvga/sisusb.c ++++ b/drivers/usb/misc/sisusbvga/sisusb.c +@@ -3248,6 +3248,7 @@ static const struct usb_device_id sisusb_table[] = { + { USB_DEVICE(0x0711, 0x0918) }, + { USB_DEVICE(0x0711, 0x0920) }, + { USB_DEVICE(0x0711, 0x0950) }, ++ { USB_DEVICE(0x0711, 0x5200) }, + { USB_DEVICE(0x182d, 0x021c) }, + { USB_DEVICE(0x182d, 0x0269) }, + { } +diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c +index 0757690..ec69b90 100644 +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -99,6 +99,7 @@ + #include + #include + #include ++#include + + #include "musb_core.h" + +@@ -477,10 +478,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + (USB_PORT_STAT_C_SUSPEND << 16) + | MUSB_PORT_STAT_RESUME; + musb->rh_timer = jiffies +- + msecs_to_jiffies(20); ++ + msecs_to_jiffies(USB_RESUME_TIMEOUT); ++ + schedule_delayed_work( + &musb->finish_resume_work, +- msecs_to_jiffies(20)); ++ msecs_to_jiffies(USB_RESUME_TIMEOUT)); + + musb->xceiv->state = OTG_STATE_A_HOST; + musb->is_active = 1; +diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c +index c2d5afc..1d29bbf 100644 +--- a/drivers/usb/musb/musb_cppi41.c ++++ b/drivers/usb/musb/musb_cppi41.c +@@ -190,7 +190,8 @@ static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer) + } + } + +- if (!list_empty(&controller->early_tx_list)) { ++ if (!list_empty(&controller->early_tx_list) && ++ !hrtimer_is_queued(&controller->early_tx)) { + ret = HRTIMER_RESTART; + hrtimer_forward_now(&controller->early_tx, + ktime_set(0, 150 * NSEC_PER_USEC)); +diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c +index 7a109ea..865243e 100644 +--- a/drivers/usb/musb/musb_dsps.c ++++ b/drivers/usb/musb/musb_dsps.c +@@ -707,6 +707,7 @@ static int dsps_suspend(struct device *dev) + struct musb *musb = platform_get_drvdata(glue->musb); + void __iomem *mbase = musb->ctrl_base; + ++ del_timer_sync(&glue->timer); + glue->context.control = dsps_readl(mbase, wrp->control); + glue->context.epintr = dsps_readl(mbase, wrp->epintr_set); + glue->context.coreintr = dsps_readl(mbase, wrp->coreintr_set); +@@ -732,6 +733,9 @@ static int dsps_resume(struct device *dev) + dsps_writel(mbase, wrp->mode, glue->context.mode); + dsps_writel(mbase, wrp->tx_mode, glue->context.tx_mode); + dsps_writel(mbase, wrp->rx_mode, glue->context.rx_mode); ++ if (musb->xceiv->state == OTG_STATE_B_IDLE && ++ musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) ++ mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ); + + return 0; + } +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index abb38c3..6b0fb6a 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -2640,7 +2640,6 @@ void musb_host_cleanup(struct musb *musb) + if (musb->port_mode == MUSB_PORT_MODE_GADGET) + return; + usb_remove_hcd(musb->hcd); +- musb->hcd = NULL; + } + + void musb_host_free(struct musb *musb) +diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c +index e2d2d8c..1e9bde4 100644 +--- a/drivers/usb/musb/musb_virthub.c ++++ b/drivers/usb/musb/musb_virthub.c +@@ -136,7 +136,7 @@ void musb_port_suspend(struct musb *musb, bool do_suspend) + /* later, GetPortStatus will stop RESUME signaling */ + musb->port1_status |= MUSB_PORT_STAT_RESUME; + schedule_delayed_work(&musb->finish_resume_work, +- msecs_to_jiffies(20)); ++ msecs_to_jiffies(USB_RESUME_TIMEOUT)); + } + } + +@@ -273,9 +273,7 @@ static int musb_has_gadget(struct musb *musb) + #ifdef CONFIG_USB_MUSB_HOST + return 1; + #else +- if (musb->port_mode == MUSB_PORT_MODE_HOST) +- return 1; +- return musb->g.dev.driver != NULL; ++ return musb->port_mode == MUSB_PORT_MODE_HOST; + #endif + } + +diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c +index bbe4f8e..8834b70 100644 +--- a/drivers/usb/phy/phy-tegra-usb.c ++++ b/drivers/usb/phy/phy-tegra-usb.c +@@ -881,8 +881,8 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy, + return -ENOMEM; + } + +- tegra_phy->config = devm_kzalloc(&pdev->dev, +- sizeof(*tegra_phy->config), GFP_KERNEL); ++ tegra_phy->config = devm_kzalloc(&pdev->dev, sizeof(*config), ++ GFP_KERNEL); + if (!tegra_phy->config) { + dev_err(&pdev->dev, + "unable to allocate memory for USB UTMIP config\n"); +diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c +index 8afa813..964ebaf 100644 +--- a/drivers/usb/phy/phy.c ++++ b/drivers/usb/phy/phy.c +@@ -78,7 +78,9 @@ static void devm_usb_phy_release(struct device *dev, void *res) + + static int devm_usb_phy_match(struct device *dev, void *res, void *match_data) + { +- return res == match_data; ++ struct usb_phy **phy = res; ++ ++ return *phy == match_data; + } + + /** +@@ -229,6 +231,9 @@ struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index) + phy = __usb_find_phy_dev(dev, &phy_bind_list, index); + if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { + dev_dbg(dev, "unable to find transceiver\n"); ++ if (!IS_ERR(phy)) ++ phy = ERR_PTR(-ENODEV); ++ + goto err0; + } + +diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c +index 9374bd2..6f91eb9 100644 +--- a/drivers/usb/serial/bus.c ++++ b/drivers/usb/serial/bus.c +@@ -51,6 +51,7 @@ static int usb_serial_device_probe(struct device *dev) + { + struct usb_serial_driver *driver; + struct usb_serial_port *port; ++ struct device *tty_dev; + int retval = 0; + int minor; + +@@ -75,12 +76,20 @@ static int usb_serial_device_probe(struct device *dev) + retval = device_create_file(dev, &dev_attr_port_number); + if (retval) { + if (driver->port_remove) +- retval = driver->port_remove(port); ++ driver->port_remove(port); + goto exit_with_autopm; + } + + minor = port->minor; +- tty_register_device(usb_serial_tty_driver, minor, dev); ++ tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev); ++ if (IS_ERR(tty_dev)) { ++ retval = PTR_ERR(tty_dev); ++ device_remove_file(dev, &dev_attr_port_number); ++ if (driver->port_remove) ++ driver->port_remove(port); ++ goto exit_with_autopm; ++ } ++ + dev_info(&port->serial->dev->dev, + "%s converter now attached to ttyUSB%d\n", + driver->description, minor); +diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c +index 8d7fc48..29fa1c3 100644 +--- a/drivers/usb/serial/console.c ++++ b/drivers/usb/serial/console.c +@@ -46,6 +46,8 @@ static struct console usbcons; + * ------------------------------------------------------------ + */ + ++static const struct tty_operations usb_console_fake_tty_ops = { ++}; + + /* + * The parsing of the command line works exactly like the +@@ -137,13 +139,17 @@ static int usb_console_setup(struct console *co, char *options) + goto reset_open_count; + } + kref_init(&tty->kref); +- tty_port_tty_set(&port->port, tty); + tty->driver = usb_serial_tty_driver; + tty->index = co->index; ++ init_ldsem(&tty->ldisc_sem); ++ INIT_LIST_HEAD(&tty->tty_files); ++ kref_get(&tty->driver->kref); ++ tty->ops = &usb_console_fake_tty_ops; + if (tty_init_termios(tty)) { + retval = -ENOMEM; +- goto free_tty; ++ goto put_tty; + } ++ tty_port_tty_set(&port->port, tty); + } + + /* only call the device specific open if this +@@ -161,7 +167,7 @@ static int usb_console_setup(struct console *co, char *options) + serial->type->set_termios(tty, port, &dummy); + + tty_port_tty_set(&port->port, NULL); +- kfree(tty); ++ tty_kref_put(tty); + } + set_bit(ASYNCB_INITIALIZED, &port->port.flags); + } +@@ -177,8 +183,8 @@ static int usb_console_setup(struct console *co, char *options) + + fail: + tty_port_tty_set(&port->port, NULL); +- free_tty: +- kfree(tty); ++ put_tty: ++ tty_kref_put(tty); + reset_open_count: + port->port.count = 0; + usb_autopm_put_interface(serial->interface); +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index 330df5c..d11335d 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -56,6 +56,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x0846, 0x1100) }, /* NetGear Managed Switch M4100 series, M5300 series, M7100 series */ + { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ + { USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */ ++ { USB_DEVICE(0x0908, 0x01FF) }, /* Siemens RUGGEDCOM USB Serial Console */ + { USB_DEVICE(0x0BED, 0x1100) }, /* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */ + { USB_DEVICE(0x0BED, 0x1101) }, /* MEI series 2000 Combo Acceptor */ + { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ +@@ -120,8 +121,14 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */ + { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */ + { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ ++ { USB_DEVICE(0x10C4, 0x8856) }, /* CEL EM357 ZigBee USB Stick - LR */ ++ { USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */ + { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */ ++ { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */ ++ { USB_DEVICE(0x10C4, 0x8977) }, /* CEL MeshWorks DevKit Device */ ++ { USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */ ++ { USB_DEVICE(0x10C4, 0x8A2A) }, /* HubZ dual ZigBee and Z-Wave dongle */ + { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ +@@ -142,6 +149,8 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x166A, 0x0305) }, /* Clipsal C-5000CT2 C-Bus Spectrum Colour Touchscreen */ + { USB_DEVICE(0x166A, 0x0401) }, /* Clipsal L51xx C-Bus Architectural Dimmer */ + { USB_DEVICE(0x166A, 0x0101) }, /* Clipsal 5560884 C-Bus Multi-room Audio Matrix Switcher */ ++ { USB_DEVICE(0x16C0, 0x09B0) }, /* Lunatico Seletek */ ++ { USB_DEVICE(0x16C0, 0x09B1) }, /* Lunatico Seletek */ + { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ + { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */ + { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ +@@ -154,7 +163,9 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ + { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ + { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ ++ { USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */ + { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ ++ { USB_DEVICE(0x1D6F, 0x0010) }, /* Seluxit ApS RF Dongle */ + { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */ + { USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */ + { USB_DEVICE(0x1FB9, 0x0100) }, /* Lake Shore Model 121 Current Source */ +@@ -176,6 +187,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x1FB9, 0x0602) }, /* Lake Shore Model 648 Magnet Power Supply */ + { USB_DEVICE(0x1FB9, 0x0700) }, /* Lake Shore Model 737 VSM Controller */ + { USB_DEVICE(0x1FB9, 0x0701) }, /* Lake Shore Model 776 Hall Matrix */ ++ { USB_DEVICE(0x2626, 0xEA60) }, /* Aruba Networks 7xxx USB Serial Console */ + { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */ + { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */ + { USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */ +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index 8a3813b..7fb81db 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -145,12 +145,14 @@ static struct ftdi_sio_quirk ftdi_8u2232c_quirk = { + * /sys/bus/usb-serial/drivers/ftdi_sio/new_id and send a patch or report. + */ + static const struct usb_device_id id_table_combined[] = { ++ { USB_DEVICE(FTDI_VID, FTDI_BRICK_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) }, ++ { USB_DEVICE(FTDI_VID, FTDI_BM_ATOM_NANO_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_NXTCAM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_EV3CON_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) }, +@@ -481,6 +483,39 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FD_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FE_PID) }, + { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FF_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_4701_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9300_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9301_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9302_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9303_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9304_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9305_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9306_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9307_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9308_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9309_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930A_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930B_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930C_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930D_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930E_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930F_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9310_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9311_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9312_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9313_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9314_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9315_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9316_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9317_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9318_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9319_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931A_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931B_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931C_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931D_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931E_PID) }, ++ { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931F_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) }, +@@ -582,6 +617,11 @@ static const struct usb_device_id id_table_combined[] = { + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, ++ { USB_DEVICE(FTDI_VID, FTDI_SYNAPSE_SS200_PID) }, ++ { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX_PID) }, ++ { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2_PID) }, ++ { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2WI_PID) }, ++ { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX3_PID) }, + /* + * ELV devices: + */ +@@ -673,6 +713,11 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) }, + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) }, + { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, ++ { USB_DEVICE(XSENS_VID, XSENS_AWINDA_DONGLE_PID) }, ++ { USB_DEVICE(XSENS_VID, XSENS_AWINDA_STATION_PID) }, ++ { USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) }, ++ { USB_DEVICE(XSENS_VID, XSENS_MTDEVBOARD_PID) }, ++ { USB_DEVICE(XSENS_VID, XSENS_MTW_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) }, + { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, +@@ -738,6 +783,7 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID), + .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, + { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, ++ { USB_DEVICE(NOVITUS_VID, NOVITUS_BONO_E_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S03_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_59_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57A_PID) }, +@@ -772,6 +818,8 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) }, ++ { USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID), ++ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID), +@@ -945,8 +993,29 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_3_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_4_PID) }, ++ /* ekey Devices */ ++ { USB_DEVICE(FTDI_VID, FTDI_EKEY_CONV_USB_PID) }, + /* Infineon Devices */ + { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) }, ++ /* GE Healthcare devices */ ++ { USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) }, ++ /* Active Research (Actisense) devices */ ++ { USB_DEVICE(FTDI_VID, ACTISENSE_NDC_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_USG_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_NGT_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_NGW_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_D9AC_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_D9AD_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_D9AE_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_D9AF_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEAGAUGE_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASWITCH_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_NMEA2000_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ETHERNET_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_WIFI_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) }, + { } /* Terminating entry */ + }; + +@@ -1838,8 +1907,12 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial) + { + struct usb_device *udev = serial->dev; + +- if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) || +- (udev->product && !strcmp(udev->product, "BeagleBone/XDS100V2"))) ++ if (udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ++ return ftdi_jtag_probe(serial); ++ ++ if (udev->product && ++ (!strcmp(udev->product, "BeagleBone/XDS100V2") || ++ !strcmp(udev->product, "SNAP Connect E10"))) + return ftdi_jtag_probe(serial); + + return 0; +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index c4777bc..2943b97 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -30,8 +30,17 @@ + + /*** third-party PIDs (using FTDI_VID) ***/ + ++/* ++ * Certain versions of the official Windows FTDI driver reprogrammed ++ * counterfeit FTDI devices to PID 0. Support these devices anyway. ++ */ ++#define FTDI_BRICK_PID 0x0000 ++ + #define FTDI_LUMEL_PD12_PID 0x6002 + ++/* Cyber Cortex AV by Fabulous Silicon (http://fabuloussilicon.com) */ ++#define CYBER_CORTEX_AV_PID 0x8698 ++ + /* + * Marvell OpenRD Base, Client + * http://www.open-rd.org +@@ -42,6 +51,8 @@ + /* www.candapter.com Ewert Energy Systems CANdapter device */ + #define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */ + ++#define FTDI_BM_ATOM_NANO_PID 0xa559 /* Basic Micro ATOM Nano USB2Serial */ ++ + /* + * Texas Instruments XDS100v2 JTAG / BeagleBone A3 + * http://processors.wiki.ti.com/index.php/XDS100 +@@ -140,12 +151,20 @@ + /* + * Xsens Technologies BV products (http://www.xsens.com). + */ +-#define XSENS_CONVERTER_0_PID 0xD388 +-#define XSENS_CONVERTER_1_PID 0xD389 ++#define XSENS_VID 0x2639 ++#define XSENS_AWINDA_STATION_PID 0x0101 ++#define XSENS_AWINDA_DONGLE_PID 0x0102 ++#define XSENS_MTW_PID 0x0200 /* Xsens MTw */ ++#define XSENS_MTDEVBOARD_PID 0x0300 /* Motion Tracker Development Board */ ++#define XSENS_CONVERTER_PID 0xD00D /* Xsens USB-serial converter */ ++ ++/* Xsens devices using FTDI VID */ ++#define XSENS_CONVERTER_0_PID 0xD388 /* Xsens USB converter */ ++#define XSENS_CONVERTER_1_PID 0xD389 /* Xsens Wireless Receiver */ + #define XSENS_CONVERTER_2_PID 0xD38A +-#define XSENS_CONVERTER_3_PID 0xD38B +-#define XSENS_CONVERTER_4_PID 0xD38C +-#define XSENS_CONVERTER_5_PID 0xD38D ++#define XSENS_CONVERTER_3_PID 0xD38B /* Xsens USB-serial converter */ ++#define XSENS_CONVERTER_4_PID 0xD38C /* Xsens Wireless Receiver */ ++#define XSENS_CONVERTER_5_PID 0xD38D /* Xsens Awinda Station */ + #define XSENS_CONVERTER_6_PID 0xD38E + #define XSENS_CONVERTER_7_PID 0xD38F + +@@ -543,6 +562,20 @@ + */ + #define FTDI_NT_ORIONLXM_PID 0x7c90 /* OrionLXm Substation Automation Platform */ + ++/* ++ * Synapse Wireless product ids (FTDI_VID) ++ * http://www.synapse-wireless.com ++ */ ++#define FTDI_SYNAPSE_SS200_PID 0x9090 /* SS200 - SNAP Stick 200 */ ++ ++/* ++ * CustomWare / ShipModul NMEA multiplexers product ids (FTDI_VID) ++ */ ++#define FTDI_CUSTOMWARE_MINIPLEX_PID 0xfd48 /* MiniPlex first generation NMEA Multiplexer */ ++#define FTDI_CUSTOMWARE_MINIPLEX2_PID 0xfd49 /* MiniPlex-USB and MiniPlex-2 series */ ++#define FTDI_CUSTOMWARE_MINIPLEX2WI_PID 0xfd4a /* MiniPlex-2Wi */ ++#define FTDI_CUSTOMWARE_MINIPLEX3_PID 0xfd4b /* MiniPlex-3 series */ ++ + + /********************************/ + /** third-party VID/PID combos **/ +@@ -832,6 +865,12 @@ + #define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */ + + /* ++ * NOVITUS printers ++ */ ++#define NOVITUS_VID 0x1a28 ++#define NOVITUS_BONO_E_PID 0x6010 ++ ++/* + * RT Systems programming cables for various ham radios + */ + #define RTSYSTEMS_VID 0x2100 /* Vendor ID */ +@@ -905,8 +944,8 @@ + #define BAYER_CONTOUR_CABLE_PID 0x6001 + + /* +- * The following are the values for the Matrix Orbital FTDI Range +- * Anything in this range will use an FT232RL. ++ * Matrix Orbital Intelligent USB displays. ++ * http://www.matrixorbital.com + */ + #define MTXORB_VID 0x1B3D + #define MTXORB_FTDI_RANGE_0100_PID 0x0100 +@@ -1165,8 +1204,39 @@ + #define MTXORB_FTDI_RANGE_01FD_PID 0x01FD + #define MTXORB_FTDI_RANGE_01FE_PID 0x01FE + #define MTXORB_FTDI_RANGE_01FF_PID 0x01FF +- +- ++#define MTXORB_FTDI_RANGE_4701_PID 0x4701 ++#define MTXORB_FTDI_RANGE_9300_PID 0x9300 ++#define MTXORB_FTDI_RANGE_9301_PID 0x9301 ++#define MTXORB_FTDI_RANGE_9302_PID 0x9302 ++#define MTXORB_FTDI_RANGE_9303_PID 0x9303 ++#define MTXORB_FTDI_RANGE_9304_PID 0x9304 ++#define MTXORB_FTDI_RANGE_9305_PID 0x9305 ++#define MTXORB_FTDI_RANGE_9306_PID 0x9306 ++#define MTXORB_FTDI_RANGE_9307_PID 0x9307 ++#define MTXORB_FTDI_RANGE_9308_PID 0x9308 ++#define MTXORB_FTDI_RANGE_9309_PID 0x9309 ++#define MTXORB_FTDI_RANGE_930A_PID 0x930A ++#define MTXORB_FTDI_RANGE_930B_PID 0x930B ++#define MTXORB_FTDI_RANGE_930C_PID 0x930C ++#define MTXORB_FTDI_RANGE_930D_PID 0x930D ++#define MTXORB_FTDI_RANGE_930E_PID 0x930E ++#define MTXORB_FTDI_RANGE_930F_PID 0x930F ++#define MTXORB_FTDI_RANGE_9310_PID 0x9310 ++#define MTXORB_FTDI_RANGE_9311_PID 0x9311 ++#define MTXORB_FTDI_RANGE_9312_PID 0x9312 ++#define MTXORB_FTDI_RANGE_9313_PID 0x9313 ++#define MTXORB_FTDI_RANGE_9314_PID 0x9314 ++#define MTXORB_FTDI_RANGE_9315_PID 0x9315 ++#define MTXORB_FTDI_RANGE_9316_PID 0x9316 ++#define MTXORB_FTDI_RANGE_9317_PID 0x9317 ++#define MTXORB_FTDI_RANGE_9318_PID 0x9318 ++#define MTXORB_FTDI_RANGE_9319_PID 0x9319 ++#define MTXORB_FTDI_RANGE_931A_PID 0x931A ++#define MTXORB_FTDI_RANGE_931B_PID 0x931B ++#define MTXORB_FTDI_RANGE_931C_PID 0x931C ++#define MTXORB_FTDI_RANGE_931D_PID 0x931D ++#define MTXORB_FTDI_RANGE_931E_PID 0x931E ++#define MTXORB_FTDI_RANGE_931F_PID 0x931F + + /* + * The Mobility Lab (TML) +@@ -1375,3 +1445,34 @@ + #define BRAINBOXES_US_160_6_PID 0x9006 /* US-160 16xRS232 1Mbaud Port 11 and 12 */ + #define BRAINBOXES_US_160_7_PID 0x9007 /* US-160 16xRS232 1Mbaud Port 13 and 14 */ + #define BRAINBOXES_US_160_8_PID 0x9008 /* US-160 16xRS232 1Mbaud Port 15 and 16 */ ++ ++/* ++ * ekey biometric systems GmbH (http://ekey.net/) ++ */ ++#define FTDI_EKEY_CONV_USB_PID 0xCB08 /* Converter USB */ ++ ++/* ++ * GE Healthcare devices ++ */ ++#define GE_HEALTHCARE_VID 0x1901 ++#define GE_HEALTHCARE_NEMO_TRACKER_PID 0x0015 ++ ++/* ++ * Active Research (Actisense) devices ++ */ ++#define ACTISENSE_NDC_PID 0xD9A8 /* NDC USB Serial Adapter */ ++#define ACTISENSE_USG_PID 0xD9A9 /* USG USB Serial Adapter */ ++#define ACTISENSE_NGT_PID 0xD9AA /* NGT NMEA2000 Interface */ ++#define ACTISENSE_NGW_PID 0xD9AB /* NGW NMEA2000 Gateway */ ++#define ACTISENSE_D9AC_PID 0xD9AC /* Actisense Reserved */ ++#define ACTISENSE_D9AD_PID 0xD9AD /* Actisense Reserved */ ++#define ACTISENSE_D9AE_PID 0xD9AE /* Actisense Reserved */ ++#define ACTISENSE_D9AF_PID 0xD9AF /* Actisense Reserved */ ++#define CHETCO_SEAGAUGE_PID 0xA548 /* SeaGauge USB Adapter */ ++#define CHETCO_SEASWITCH_PID 0xA549 /* SeaSwitch USB Adapter */ ++#define CHETCO_SEASMART_NMEA2000_PID 0xA54A /* SeaSmart NMEA2000 Gateway */ ++#define CHETCO_SEASMART_ETHERNET_PID 0xA54B /* SeaSmart Ethernet Gateway */ ++#define CHETCO_SEASMART_WIFI_PID 0xA5AC /* SeaSmart Wifi Gateway */ ++#define CHETCO_SEASMART_DISPLAY_PID 0xA5AD /* SeaSmart NMEA2000 Display */ ++#define CHETCO_SEASMART_LITE_PID 0xA5AE /* SeaSmart Lite USB Adapter */ ++#define CHETCO_SEASMART_ANALOG_PID 0xA5AF /* SeaSmart Analog Adapter */ +diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c +index b63ce02..d6a1979 100644 +--- a/drivers/usb/serial/generic.c ++++ b/drivers/usb/serial/generic.c +@@ -258,7 +258,8 @@ void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout) + * character or at least one jiffy. + */ + period = max_t(unsigned long, (10 * HZ / bps), 1); +- period = min_t(unsigned long, period, timeout); ++ if (timeout) ++ period = min_t(unsigned long, period, timeout); + + dev_dbg(&port->dev, "%s - timeout = %u ms, period = %u ms\n", + __func__, jiffies_to_msecs(timeout), +@@ -268,7 +269,7 @@ void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout) + schedule_timeout_interruptible(period); + if (signal_pending(current)) + break; +- if (time_after(jiffies, expire)) ++ if (timeout && time_after(jiffies, expire)) + break; + } + } +diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c +index 265c677..35297a8 100644 +--- a/drivers/usb/serial/keyspan.c ++++ b/drivers/usb/serial/keyspan.c +@@ -311,24 +311,30 @@ static void usa26_indat_callback(struct urb *urb) + if ((data[0] & 0x80) == 0) { + /* no errors on individual bytes, only + possible overrun err */ +- if (data[0] & RXERROR_OVERRUN) +- err = TTY_OVERRUN; +- else +- err = 0; ++ if (data[0] & RXERROR_OVERRUN) { ++ tty_insert_flip_char(&port->port, 0, ++ TTY_OVERRUN); ++ } + for (i = 1; i < urb->actual_length ; ++i) +- tty_insert_flip_char(&port->port, data[i], err); ++ tty_insert_flip_char(&port->port, data[i], ++ TTY_NORMAL); + } else { + /* some bytes had errors, every byte has status */ + dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__); + for (i = 0; i + 1 < urb->actual_length; i += 2) { +- int stat = data[i], flag = 0; +- if (stat & RXERROR_OVERRUN) +- flag |= TTY_OVERRUN; +- if (stat & RXERROR_FRAMING) +- flag |= TTY_FRAME; +- if (stat & RXERROR_PARITY) +- flag |= TTY_PARITY; ++ int stat = data[i]; ++ int flag = TTY_NORMAL; ++ ++ if (stat & RXERROR_OVERRUN) { ++ tty_insert_flip_char(&port->port, 0, ++ TTY_OVERRUN); ++ } + /* XXX should handle break (0x10) */ ++ if (stat & RXERROR_PARITY) ++ flag = TTY_PARITY; ++ else if (stat & RXERROR_FRAMING) ++ flag = TTY_FRAME; ++ + tty_insert_flip_char(&port->port, data[i+1], + flag); + } +@@ -415,6 +421,8 @@ static void usa26_instat_callback(struct urb *urb) + } + port = serial->port[msg->port]; + p_priv = usb_get_serial_port_data(port); ++ if (!p_priv) ++ goto resubmit; + + /* Update handshaking pin state information */ + old_dcd_state = p_priv->dcd_state; +@@ -425,7 +433,7 @@ static void usa26_instat_callback(struct urb *urb) + + if (old_dcd_state != p_priv->dcd_state) + tty_port_tty_hangup(&port->port, true); +- ++resubmit: + /* Resubmit urb so we continue receiving */ + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) +@@ -535,6 +543,8 @@ static void usa28_instat_callback(struct urb *urb) + } + port = serial->port[msg->port]; + p_priv = usb_get_serial_port_data(port); ++ if (!p_priv) ++ goto resubmit; + + /* Update handshaking pin state information */ + old_dcd_state = p_priv->dcd_state; +@@ -545,7 +555,7 @@ static void usa28_instat_callback(struct urb *urb) + + if (old_dcd_state != p_priv->dcd_state && old_dcd_state) + tty_port_tty_hangup(&port->port, true); +- ++resubmit: + /* Resubmit urb so we continue receiving */ + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) +@@ -618,6 +628,8 @@ static void usa49_instat_callback(struct urb *urb) + } + port = serial->port[msg->portNumber]; + p_priv = usb_get_serial_port_data(port); ++ if (!p_priv) ++ goto resubmit; + + /* Update handshaking pin state information */ + old_dcd_state = p_priv->dcd_state; +@@ -628,7 +640,7 @@ static void usa49_instat_callback(struct urb *urb) + + if (old_dcd_state != p_priv->dcd_state && old_dcd_state) + tty_port_tty_hangup(&port->port, true); +- ++resubmit: + /* Resubmit urb so we continue receiving */ + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) +@@ -666,14 +678,19 @@ static void usa49_indat_callback(struct urb *urb) + } else { + /* some bytes had errors, every byte has status */ + for (i = 0; i + 1 < urb->actual_length; i += 2) { +- int stat = data[i], flag = 0; +- if (stat & RXERROR_OVERRUN) +- flag |= TTY_OVERRUN; +- if (stat & RXERROR_FRAMING) +- flag |= TTY_FRAME; +- if (stat & RXERROR_PARITY) +- flag |= TTY_PARITY; ++ int stat = data[i]; ++ int flag = TTY_NORMAL; ++ ++ if (stat & RXERROR_OVERRUN) { ++ tty_insert_flip_char(&port->port, 0, ++ TTY_OVERRUN); ++ } + /* XXX should handle break (0x10) */ ++ if (stat & RXERROR_PARITY) ++ flag = TTY_PARITY; ++ else if (stat & RXERROR_FRAMING) ++ flag = TTY_FRAME; ++ + tty_insert_flip_char(&port->port, data[i+1], + flag); + } +@@ -730,15 +747,19 @@ static void usa49wg_indat_callback(struct urb *urb) + */ + for (x = 0; x + 1 < len && + i + 1 < urb->actual_length; x += 2) { +- int stat = data[i], flag = 0; ++ int stat = data[i]; ++ int flag = TTY_NORMAL; + +- if (stat & RXERROR_OVERRUN) +- flag |= TTY_OVERRUN; +- if (stat & RXERROR_FRAMING) +- flag |= TTY_FRAME; +- if (stat & RXERROR_PARITY) +- flag |= TTY_PARITY; ++ if (stat & RXERROR_OVERRUN) { ++ tty_insert_flip_char(&port->port, 0, ++ TTY_OVERRUN); ++ } + /* XXX should handle break (0x10) */ ++ if (stat & RXERROR_PARITY) ++ flag = TTY_PARITY; ++ else if (stat & RXERROR_FRAMING) ++ flag = TTY_FRAME; ++ + tty_insert_flip_char(&port->port, data[i+1], + flag); + i += 2; +@@ -790,25 +811,31 @@ static void usa90_indat_callback(struct urb *urb) + if ((data[0] & 0x80) == 0) { + /* no errors on individual bytes, only + possible overrun err*/ +- if (data[0] & RXERROR_OVERRUN) +- err = TTY_OVERRUN; +- else +- err = 0; ++ if (data[0] & RXERROR_OVERRUN) { ++ tty_insert_flip_char(&port->port, 0, ++ TTY_OVERRUN); ++ } + for (i = 1; i < urb->actual_length ; ++i) + tty_insert_flip_char(&port->port, +- data[i], err); ++ data[i], TTY_NORMAL); + } else { + /* some bytes had errors, every byte has status */ + dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__); + for (i = 0; i + 1 < urb->actual_length; i += 2) { +- int stat = data[i], flag = 0; +- if (stat & RXERROR_OVERRUN) +- flag |= TTY_OVERRUN; +- if (stat & RXERROR_FRAMING) +- flag |= TTY_FRAME; +- if (stat & RXERROR_PARITY) +- flag |= TTY_PARITY; ++ int stat = data[i]; ++ int flag = TTY_NORMAL; ++ ++ if (stat & RXERROR_OVERRUN) { ++ tty_insert_flip_char( ++ &port->port, 0, ++ TTY_OVERRUN); ++ } + /* XXX should handle break (0x10) */ ++ if (stat & RXERROR_PARITY) ++ flag = TTY_PARITY; ++ else if (stat & RXERROR_FRAMING) ++ flag = TTY_FRAME; ++ + tty_insert_flip_char(&port->port, + data[i+1], flag); + } +@@ -851,6 +878,8 @@ static void usa90_instat_callback(struct urb *urb) + + port = serial->port[0]; + p_priv = usb_get_serial_port_data(port); ++ if (!p_priv) ++ goto resubmit; + + /* Update handshaking pin state information */ + old_dcd_state = p_priv->dcd_state; +@@ -861,7 +890,7 @@ static void usa90_instat_callback(struct urb *urb) + + if (old_dcd_state != p_priv->dcd_state && old_dcd_state) + tty_port_tty_hangup(&port->port, true); +- ++resubmit: + /* Resubmit urb so we continue receiving */ + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) +@@ -922,6 +951,8 @@ static void usa67_instat_callback(struct urb *urb) + + port = serial->port[msg->port]; + p_priv = usb_get_serial_port_data(port); ++ if (!p_priv) ++ goto resubmit; + + /* Update handshaking pin state information */ + old_dcd_state = p_priv->dcd_state; +@@ -930,7 +961,7 @@ static void usa67_instat_callback(struct urb *urb) + + if (old_dcd_state != p_priv->dcd_state && old_dcd_state) + tty_port_tty_hangup(&port->port, true); +- ++resubmit: + /* Resubmit urb so we continue receiving */ + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err != 0) +diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c +index 618c1c1..5cdb32b 100644 +--- a/drivers/usb/serial/kobil_sct.c ++++ b/drivers/usb/serial/kobil_sct.c +@@ -335,7 +335,8 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, + port->interrupt_out_urb->transfer_buffer_length = length; + + priv->cur_pos = priv->cur_pos + length; +- result = usb_submit_urb(port->interrupt_out_urb, GFP_NOIO); ++ result = usb_submit_urb(port->interrupt_out_urb, ++ GFP_ATOMIC); + dev_dbg(&port->dev, "%s - Send write URB returns: %i\n", __func__, result); + todo = priv->filled - priv->cur_pos; + +@@ -350,7 +351,7 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, + if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || + priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) { + result = usb_submit_urb(port->interrupt_in_urb, +- GFP_NOIO); ++ GFP_ATOMIC); + dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result); + } + } +diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c +index ab1d690..460a406 100644 +--- a/drivers/usb/serial/mxuport.c ++++ b/drivers/usb/serial/mxuport.c +@@ -1284,7 +1284,8 @@ static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port) + } + + /* Initial port termios */ +- mxuport_set_termios(tty, port, NULL); ++ if (tty) ++ mxuport_set_termios(tty, port, NULL); + + /* + * TODO: use RQ_VENDOR_GET_MSR, once we know what it +diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c +index 4856fb7..4b7bfb3 100644 +--- a/drivers/usb/serial/opticon.c ++++ b/drivers/usb/serial/opticon.c +@@ -215,7 +215,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, + + /* The connected devices do not have a bulk write endpoint, + * to transmit data to de barcode device the control endpoint is used */ +- dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO); ++ dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); + if (!dr) { + count = -ENOMEM; + goto error_no_dr; +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index 240c073..096438e 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -269,14 +269,19 @@ static void option_instat_callback(struct urb *urb); + #define TELIT_PRODUCT_DE910_DUAL 0x1010 + #define TELIT_PRODUCT_UE910_V2 0x1012 + #define TELIT_PRODUCT_LE920 0x1200 ++#define TELIT_PRODUCT_LE910 0x1201 + + /* ZTE PRODUCTS */ + #define ZTE_VENDOR_ID 0x19d2 + #define ZTE_PRODUCT_MF622 0x0001 + #define ZTE_PRODUCT_MF628 0x0015 + #define ZTE_PRODUCT_MF626 0x0031 +-#define ZTE_PRODUCT_MC2718 0xffe8 + #define ZTE_PRODUCT_AC2726 0xfff1 ++#define ZTE_PRODUCT_CDMA_TECH 0xfffe ++#define ZTE_PRODUCT_AC8710T 0xffff ++#define ZTE_PRODUCT_MC2718 0xffe8 ++#define ZTE_PRODUCT_AD3812 0xffeb ++#define ZTE_PRODUCT_MC2716 0xffed + + #define BENQ_VENDOR_ID 0x04a5 + #define BENQ_PRODUCT_H10 0x4068 +@@ -357,6 +362,7 @@ static void option_instat_callback(struct urb *urb); + + /* Haier products */ + #define HAIER_VENDOR_ID 0x201e ++#define HAIER_PRODUCT_CE81B 0x10f8 + #define HAIER_PRODUCT_CE100 0x2009 + + /* Cinterion (formerly Siemens) products */ +@@ -494,6 +500,10 @@ static void option_instat_callback(struct urb *urb); + #define INOVIA_VENDOR_ID 0x20a6 + #define INOVIA_SEW858 0x1105 + ++/* VIA Telecom */ ++#define VIATELECOM_VENDOR_ID 0x15eb ++#define VIATELECOM_PRODUCT_CDS7 0x0001 ++ + /* some devices interfaces need special handling due to a number of reasons */ + enum option_blacklist_reason { + OPTION_BLACKLIST_NONE = 0, +@@ -527,10 +537,18 @@ static const struct option_blacklist_info zte_k3765_z_blacklist = { + .reserved = BIT(4), + }; + ++static const struct option_blacklist_info zte_ad3812_z_blacklist = { ++ .sendsetup = BIT(0) | BIT(1) | BIT(2), ++}; ++ + static const struct option_blacklist_info zte_mc2718_z_blacklist = { + .sendsetup = BIT(1) | BIT(2) | BIT(3) | BIT(4), + }; + ++static const struct option_blacklist_info zte_mc2716_z_blacklist = { ++ .sendsetup = BIT(1) | BIT(2) | BIT(3), ++}; ++ + static const struct option_blacklist_info huawei_cdc12_blacklist = { + .reserved = BIT(1) | BIT(2), + }; +@@ -572,6 +590,11 @@ static const struct option_blacklist_info zte_1255_blacklist = { + .reserved = BIT(3) | BIT(4), + }; + ++static const struct option_blacklist_info telit_le910_blacklist = { ++ .sendsetup = BIT(0), ++ .reserved = BIT(1) | BIT(2), ++}; ++ + static const struct option_blacklist_info telit_le920_blacklist = { + .sendsetup = BIT(0), + .reserved = BIT(1) | BIT(5), +@@ -1070,6 +1093,7 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012, 0xff) }, + { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) }, + { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) }, ++ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */ + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */ +@@ -1120,6 +1144,8 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) }, ++ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910), ++ .driver_info = (kernel_ulong_t)&telit_le910_blacklist }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), + .driver_info = (kernel_ulong_t)&telit_le920_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ +@@ -1544,13 +1570,18 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff93, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff94, 0xff, 0xff, 0xff) }, + +- /* NOTE: most ZTE CDMA devices should be driven by zte_ev, not option */ ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2718, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&zte_mc2718_z_blacklist }, ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AD3812, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist }, ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff), ++ .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) }, +- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) }, + + { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, + { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, +@@ -1590,6 +1621,7 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) }, + { USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) }, + { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(HAIER_VENDOR_ID, HAIER_PRODUCT_CE81B, 0xff, 0xff, 0xff) }, + /* Pirelli */ + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2, 0xff) }, +@@ -1723,7 +1755,9 @@ static const struct usb_device_id option_ids[] = { + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) }, + { 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_INTERFACE_CLASS(0x2020, 0x4000, 0xff) }, /* OLICARD300 - MT6225 */ + { USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) }, ++ { USB_DEVICE(VIATELECOM_VENDOR_ID, VIATELECOM_PRODUCT_CDS7) }, + { } /* Terminating entry */ + }; + MODULE_DEVICE_TABLE(usb, option_ids); +diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c +index b3d5a35..5219593 100644 +--- a/drivers/usb/serial/pl2303.c ++++ b/drivers/usb/serial/pl2303.c +@@ -45,6 +45,7 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) }, ++ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) }, + { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, + { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, + { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, +@@ -60,7 +61,6 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) }, + { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) }, +- { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1), + .driver_info = PL2303_QUIRK_UART_STATE_IDX0 }, + { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65), +diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h +index 42bc082..e3b7af8 100644 +--- a/drivers/usb/serial/pl2303.h ++++ b/drivers/usb/serial/pl2303.h +@@ -22,6 +22,7 @@ + #define PL2303_PRODUCT_ID_GPRS 0x0609 + #define PL2303_PRODUCT_ID_HCR331 0x331a + #define PL2303_PRODUCT_ID_MOTOROLA 0x0307 ++#define PL2303_PRODUCT_ID_ZTEK 0xe1f1 + + #define ATEN_VENDOR_ID 0x0557 + #define ATEN_VENDOR_ID2 0x0547 +@@ -61,10 +62,6 @@ + #define ALCATEL_VENDOR_ID 0x11f7 + #define ALCATEL_PRODUCT_ID 0x02df + +-/* Samsung I330 phone cradle */ +-#define SAMSUNG_VENDOR_ID 0x04e8 +-#define SAMSUNG_PRODUCT_ID 0x8001 +- + #define SIEMENS_VENDOR_ID 0x11f5 + #define SIEMENS_PRODUCT_ID_SX1 0x0001 + #define SIEMENS_PRODUCT_ID_X65 0x0003 +diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c +index 3748034..89c55d4 100644 +--- a/drivers/usb/serial/sierra.c ++++ b/drivers/usb/serial/sierra.c +@@ -282,14 +282,20 @@ static const struct usb_device_id id_table[] = { + /* Sierra Wireless HSPA Non-Composite Device */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)}, + { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */ +- { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ ++ /* Sierra Wireless Direct IP modems */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68A3, 0xFF, 0xFF, 0xFF), + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, ++ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68AA, 0xFF, 0xFF, 0xFF), ++ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist ++ }, ++ { USB_DEVICE(0x1199, 0x68AB) }, /* Sierra Wireless AR8550 */ + /* AT&T Direct IP LTE modems */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF), + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, +- { USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */ ++ /* Airprime/Sierra Wireless Direct IP modems */ ++ { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68A3, 0xFF, 0xFF, 0xFF), + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, + +diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c +index a7fe664..70a098d 100644 +--- a/drivers/usb/serial/ssu100.c ++++ b/drivers/usb/serial/ssu100.c +@@ -490,10 +490,9 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr, + if (*tty_flag == TTY_NORMAL) + *tty_flag = TTY_FRAME; + } +- if (lsr & UART_LSR_OE){ ++ if (lsr & UART_LSR_OE) { + port->icount.overrun++; +- if (*tty_flag == TTY_NORMAL) +- *tty_flag = TTY_OVERRUN; ++ tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); + } + } + +@@ -511,12 +510,8 @@ static void ssu100_process_read_urb(struct urb *urb) + if ((len >= 4) && + (packet[0] == 0x1b) && (packet[1] == 0x1b) && + ((packet[2] == 0x00) || (packet[2] == 0x01))) { +- if (packet[2] == 0x00) { ++ if (packet[2] == 0x00) + ssu100_update_lsr(port, packet[3], &flag); +- if (flag == TTY_OVERRUN) +- tty_insert_flip_char(&port->port, 0, +- TTY_OVERRUN); +- } + if (packet[2] == 0x01) + ssu100_update_msr(port, packet[3]); + +diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c +index 9fa7dd4..5e5e882 100644 +--- a/drivers/usb/serial/symbolserial.c ++++ b/drivers/usb/serial/symbolserial.c +@@ -96,7 +96,7 @@ exit: + + static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port) + { +- struct symbol_private *priv = usb_get_serial_data(port->serial); ++ struct symbol_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + int result = 0; + +@@ -122,7 +122,7 @@ static void symbol_close(struct usb_serial_port *port) + static void symbol_throttle(struct tty_struct *tty) + { + struct usb_serial_port *port = tty->driver_data; +- struct symbol_private *priv = usb_get_serial_data(port->serial); ++ struct symbol_private *priv = usb_get_serial_port_data(port); + + spin_lock_irq(&priv->lock); + priv->throttled = true; +@@ -132,7 +132,7 @@ static void symbol_throttle(struct tty_struct *tty) + static void symbol_unthrottle(struct tty_struct *tty) + { + struct usb_serial_port *port = tty->driver_data; +- struct symbol_private *priv = usb_get_serial_data(port->serial); ++ struct symbol_private *priv = usb_get_serial_port_data(port); + int result; + bool was_throttled; + +diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c +index b169b0f..3d66e9c 100644 +--- a/drivers/usb/serial/usb-serial.c ++++ b/drivers/usb/serial/usb-serial.c +@@ -764,29 +764,39 @@ static int usb_serial_probe(struct usb_interface *interface, + if (usb_endpoint_is_bulk_in(endpoint)) { + /* we found a bulk in endpoint */ + dev_dbg(ddev, "found bulk in on endpoint %d\n", i); +- bulk_in_endpoint[num_bulk_in] = endpoint; +- ++num_bulk_in; ++ if (num_bulk_in < MAX_NUM_PORTS) { ++ bulk_in_endpoint[num_bulk_in] = endpoint; ++ ++num_bulk_in; ++ } + } + + if (usb_endpoint_is_bulk_out(endpoint)) { + /* we found a bulk out endpoint */ + dev_dbg(ddev, "found bulk out on endpoint %d\n", i); +- bulk_out_endpoint[num_bulk_out] = endpoint; +- ++num_bulk_out; ++ if (num_bulk_out < MAX_NUM_PORTS) { ++ bulk_out_endpoint[num_bulk_out] = endpoint; ++ ++num_bulk_out; ++ } + } + + if (usb_endpoint_is_int_in(endpoint)) { + /* we found a interrupt in endpoint */ + dev_dbg(ddev, "found interrupt in on endpoint %d\n", i); +- interrupt_in_endpoint[num_interrupt_in] = endpoint; +- ++num_interrupt_in; ++ if (num_interrupt_in < MAX_NUM_PORTS) { ++ interrupt_in_endpoint[num_interrupt_in] = ++ endpoint; ++ ++num_interrupt_in; ++ } + } + + if (usb_endpoint_is_int_out(endpoint)) { + /* we found an interrupt out endpoint */ + dev_dbg(ddev, "found interrupt out on endpoint %d\n", i); +- interrupt_out_endpoint[num_interrupt_out] = endpoint; +- ++num_interrupt_out; ++ if (num_interrupt_out < MAX_NUM_PORTS) { ++ interrupt_out_endpoint[num_interrupt_out] = ++ endpoint; ++ ++num_interrupt_out; ++ } + } + } + +@@ -809,8 +819,10 @@ static int usb_serial_probe(struct usb_interface *interface, + if (usb_endpoint_is_int_in(endpoint)) { + /* we found a interrupt in endpoint */ + dev_dbg(ddev, "found interrupt in for Prolific device on separate interface\n"); +- interrupt_in_endpoint[num_interrupt_in] = endpoint; +- ++num_interrupt_in; ++ if (num_interrupt_in < MAX_NUM_PORTS) { ++ interrupt_in_endpoint[num_interrupt_in] = endpoint; ++ ++num_interrupt_in; ++ } + } + } + } +@@ -850,6 +862,11 @@ static int usb_serial_probe(struct usb_interface *interface, + num_ports = type->num_ports; + } + ++ if (num_ports > MAX_NUM_PORTS) { ++ dev_warn(ddev, "too many ports requested: %d\n", num_ports); ++ num_ports = MAX_NUM_PORTS; ++ } ++ + serial->num_ports = num_ports; + serial->num_bulk_in = num_bulk_in; + serial->num_bulk_out = num_bulk_out; +@@ -1283,6 +1300,7 @@ static void __exit usb_serial_exit(void) + tty_unregister_driver(usb_serial_tty_driver); + put_tty_driver(usb_serial_tty_driver); + bus_unregister(&usb_serial_bus_type); ++ idr_destroy(&serial_minors); + } + + +diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c +index bf2bd40..60afb39 100644 +--- a/drivers/usb/serial/visor.c ++++ b/drivers/usb/serial/visor.c +@@ -95,7 +95,7 @@ static const struct usb_device_id id_table[] = { + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, + { USB_DEVICE(ACER_VENDOR_ID, ACER_S10_ID), + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, +- { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID), ++ { USB_DEVICE_INTERFACE_CLASS(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID, 0xff), + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, + { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID), + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, +diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c +index e62f2df..6c3734d 100644 +--- a/drivers/usb/serial/whiteheat.c ++++ b/drivers/usb/serial/whiteheat.c +@@ -514,6 +514,10 @@ static void command_port_read_callback(struct urb *urb) + dev_dbg(&urb->dev->dev, "%s - command_info is NULL, exiting.\n", __func__); + return; + } ++ if (!urb->actual_length) { ++ dev_dbg(&urb->dev->dev, "%s - empty response, exiting.\n", __func__); ++ return; ++ } + if (status) { + dev_dbg(&urb->dev->dev, "%s - nonzero urb status: %d\n", __func__, status); + if (status != -ENOENT) +@@ -534,7 +538,8 @@ static void command_port_read_callback(struct urb *urb) + /* These are unsolicited reports from the firmware, hence no + waiting command to wakeup */ + dev_dbg(&urb->dev->dev, "%s - event received\n", __func__); +- } else if (data[0] == WHITEHEAT_GET_DTR_RTS) { ++ } else if ((data[0] == WHITEHEAT_GET_DTR_RTS) && ++ (urb->actual_length - 1 <= sizeof(command_info->result_buffer))) { + memcpy(command_info->result_buffer, &data[1], + urb->actual_length - 1); + command_info->command_finished = WHITEHEAT_CMD_COMPLETE; +diff --git a/drivers/usb/serial/zte_ev.c b/drivers/usb/serial/zte_ev.c +index e40ab73..c9bb107 100644 +--- a/drivers/usb/serial/zte_ev.c ++++ b/drivers/usb/serial/zte_ev.c +@@ -272,28 +272,16 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port) + } + + static const struct usb_device_id id_table[] = { +- /* AC8710, AC8710T */ +- { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffff, 0xff, 0xff, 0xff) }, +- /* AC8700 */ +- { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xfffe, 0xff, 0xff, 0xff) }, +- /* MG880 */ +- { USB_DEVICE(0x19d2, 0xfffd) }, +- { USB_DEVICE(0x19d2, 0xfffc) }, +- { USB_DEVICE(0x19d2, 0xfffb) }, +- /* AC8710_V3 */ ++ { USB_DEVICE(0x19d2, 0xffec) }, ++ { USB_DEVICE(0x19d2, 0xffee) }, + { USB_DEVICE(0x19d2, 0xfff6) }, + { USB_DEVICE(0x19d2, 0xfff7) }, + { USB_DEVICE(0x19d2, 0xfff8) }, + { USB_DEVICE(0x19d2, 0xfff9) }, +- { USB_DEVICE(0x19d2, 0xffee) }, +- /* AC2716, MC2716 */ +- { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffed, 0xff, 0xff, 0xff) }, +- /* AD3812 */ +- { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffeb, 0xff, 0xff, 0xff) }, +- { USB_DEVICE(0x19d2, 0xffec) }, +- { USB_DEVICE(0x05C6, 0x3197) }, +- { USB_DEVICE(0x05C6, 0x6000) }, +- { USB_DEVICE(0x05C6, 0x9008) }, ++ { USB_DEVICE(0x19d2, 0xfffb) }, ++ { USB_DEVICE(0x19d2, 0xfffc) }, ++ /* MG880 */ ++ { USB_DEVICE(0x19d2, 0xfffd) }, + { }, + }; + MODULE_DEVICE_TABLE(usb, id_table); +diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c +index 22c7d43..b1d815e 100644 +--- a/drivers/usb/storage/transport.c ++++ b/drivers/usb/storage/transport.c +@@ -1118,6 +1118,31 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) + */ + if (result == USB_STOR_XFER_LONG) + fake_sense = 1; ++ ++ /* ++ * Sometimes a device will mistakenly skip the data phase ++ * and go directly to the status phase without sending a ++ * zero-length packet. If we get a 13-byte response here, ++ * check whether it really is a CSW. ++ */ ++ if (result == USB_STOR_XFER_SHORT && ++ srb->sc_data_direction == DMA_FROM_DEVICE && ++ transfer_length - scsi_get_resid(srb) == ++ US_BULK_CS_WRAP_LEN) { ++ struct scatterlist *sg = NULL; ++ unsigned int offset = 0; ++ ++ if (usb_stor_access_xfer_buf((unsigned char *) bcs, ++ US_BULK_CS_WRAP_LEN, srb, &sg, ++ &offset, FROM_XFER_BUF) == ++ US_BULK_CS_WRAP_LEN && ++ bcs->Signature == ++ cpu_to_le32(US_BULK_CS_SIGN)) { ++ usb_stor_dbg(us, "Device skipped data phase\n"); ++ scsi_set_resid(srb, transfer_length); ++ goto skipped_data_phase; ++ } ++ } + } + + /* See flow chart on pg 15 of the Bulk Only Transport spec for +@@ -1153,6 +1178,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) + if (result != USB_STOR_XFER_GOOD) + return USB_STOR_TRANSPORT_ERROR; + ++ skipped_data_phase: + /* check bulk status */ + residue = le32_to_cpu(bcs->Residue); + usb_stor_dbg(us, "Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n", +diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h +index 042c83b0..da380a9 100644 +--- a/drivers/usb/storage/unusual_devs.h ++++ b/drivers/usb/storage/unusual_devs.h +@@ -101,6 +101,12 @@ UNUSUAL_DEV( 0x03f0, 0x4002, 0x0001, 0x0001, + "PhotoSmart R707", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), + ++UNUSUAL_DEV( 0x03f3, 0x0001, 0x0000, 0x9999, ++ "Adaptec", ++ "USBConnect 2000", ++ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, ++ US_FL_SCM_MULT_TARG ), ++ + /* Reported by Sebastian Kapfer + * and Olaf Hering (different bcd's, same vendor/product) + * for USB floppies that need the SINGLE_LUN enforcement. +@@ -741,6 +747,12 @@ UNUSUAL_DEV( 0x059b, 0x0001, 0x0100, 0x0100, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_SINGLE_LUN ), + ++UNUSUAL_DEV( 0x059b, 0x0040, 0x0100, 0x0100, ++ "Iomega", ++ "Jaz USB Adapter", ++ USB_SC_DEVICE, USB_PR_DEVICE, NULL, ++ US_FL_SINGLE_LUN ), ++ + /* Reported by */ + UNUSUAL_DEV( 0x059f, 0x0643, 0x0000, 0x0000, + "LaCie", +@@ -748,6 +760,13 @@ UNUSUAL_DEV( 0x059f, 0x0643, 0x0000, 0x0000, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_GO_SLOW ), + ++/* Reported by Christian Schaller */ ++UNUSUAL_DEV( 0x059f, 0x0651, 0x0000, 0x0000, ++ "LaCie", ++ "External HDD", ++ USB_SC_DEVICE, USB_PR_DEVICE, NULL, ++ US_FL_NO_WP_DETECT ), ++ + /* Submitted by Joel Bourquard + * Some versions of this device need the SubClass and Protocol overrides + * while others don't. +@@ -1113,6 +1132,18 @@ UNUSUAL_DEV( 0x0851, 0x1543, 0x0200, 0x0200, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NOT_LOCKABLE), + ++UNUSUAL_DEV( 0x085a, 0x0026, 0x0100, 0x0133, ++ "Xircom", ++ "PortGear USB-SCSI (Mac USB Dock)", ++ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, ++ US_FL_SCM_MULT_TARG ), ++ ++UNUSUAL_DEV( 0x085a, 0x0028, 0x0100, 0x0133, ++ "Xircom", ++ "PortGear USB to SCSI Converter", ++ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, ++ US_FL_SCM_MULT_TARG ), ++ + /* Submitted by Jan De Luyck */ + UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000, + "CITIZEN", +@@ -1945,6 +1976,14 @@ UNUSUAL_DEV( 0x152d, 0x2329, 0x0100, 0x0100, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ), + ++/* Entrega Technologies U1-SC25 (later Xircom PortGear PGSCSI) ++ * and Mac USB Dock USB-SCSI */ ++UNUSUAL_DEV( 0x1645, 0x0007, 0x0100, 0x0133, ++ "Entrega Technologies", ++ "USB to SCSI Converter", ++ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, ++ US_FL_SCM_MULT_TARG ), ++ + /* Reported by Robert Schedel + * Note: this is a 'super top' device like the above 14cd/6600 device */ + UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, +@@ -1967,6 +2006,12 @@ UNUSUAL_DEV( 0x177f, 0x0400, 0x0000, 0x0000, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ), + ++UNUSUAL_DEV( 0x1822, 0x0001, 0x0000, 0x9999, ++ "Ariston Technologies", ++ "iConnect USB to SCSI adapter", ++ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, ++ US_FL_SCM_MULT_TARG ), ++ + /* Reported by Hans de Goede + * These Appotech controllers are found in Picture Frames, they provide a + * (buggy) emulation of a cdrom drive which contains the windows software +@@ -1987,6 +2032,18 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200, + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NO_READ_DISC_INFO ), + ++/* Reported by Oliver Neukum ++ * This device morphes spontaneously into another device if the access ++ * pattern of Windows isn't followed. Thus writable media would be dirty ++ * if the initial instance is used. So the device is limited to its ++ * virtual CD. ++ * And yes, the concept that BCD goes up to 9 is not heeded */ ++UNUSUAL_DEV( 0x19d2, 0x1225, 0x0000, 0xffff, ++ "ZTE,Incorporated", ++ "ZTE WCDMA Technologies MSM", ++ USB_SC_DEVICE, USB_PR_DEVICE, NULL, ++ US_FL_SINGLE_LUN ), ++ + /* Reported by Sven Geggus + * This encrypted pen drive returns bogus data for the initial READ(10). + */ +diff --git a/drivers/uwb/lc-dev.c b/drivers/uwb/lc-dev.c +index 80079b8..d0303f0 100644 +--- a/drivers/uwb/lc-dev.c ++++ b/drivers/uwb/lc-dev.c +@@ -431,16 +431,19 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce) + uwb_dev->mac_addr = *bce->mac_addr; + uwb_dev->dev_addr = bce->dev_addr; + dev_set_name(&uwb_dev->dev, "%s", macbuf); ++ ++ /* plug the beacon cache */ ++ bce->uwb_dev = uwb_dev; ++ uwb_dev->bce = bce; ++ uwb_bce_get(bce); /* released in uwb_dev_sys_release() */ ++ + result = uwb_dev_add(uwb_dev, &rc->uwb_dev.dev, rc); + if (result < 0) { + dev_err(dev, "new device %s: cannot instantiate device\n", + macbuf); + goto error_dev_add; + } +- /* plug the beacon cache */ +- bce->uwb_dev = uwb_dev; +- uwb_dev->bce = bce; +- uwb_bce_get(bce); /* released in uwb_dev_sys_release() */ ++ + dev_info(dev, "uwb device (mac %s dev %s) connected to %s %s\n", + macbuf, devbuf, rc->uwb_dev.dev.parent->bus->name, + dev_name(rc->uwb_dev.dev.parent)); +@@ -448,6 +451,8 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce) + return; + + error_dev_add: ++ bce->uwb_dev = NULL; ++ uwb_bce_put(bce); + kfree(uwb_dev); + return; + } +diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c +index 7ba0424..75e1d03 100644 +--- a/drivers/vfio/pci/vfio_pci.c ++++ b/drivers/vfio/pci/vfio_pci.c +@@ -810,13 +810,11 @@ static const struct vfio_device_ops vfio_pci_ops = { + + static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + { +- u8 type; + struct vfio_pci_device *vdev; + struct iommu_group *group; + int ret; + +- pci_read_config_byte(pdev, PCI_HEADER_TYPE, &type); +- if ((type & PCI_HEADER_TYPE) != PCI_HEADER_TYPE_NORMAL) ++ if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL) + return -EINVAL; + + group = iommu_group_get(&pdev->dev); +diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c +index e48d4a6..486d710 100644 +--- a/drivers/vhost/scsi.c ++++ b/drivers/vhost/scsi.c +@@ -861,6 +861,23 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd, + return 0; + } + ++static int vhost_scsi_to_tcm_attr(int attr) ++{ ++ switch (attr) { ++ case VIRTIO_SCSI_S_SIMPLE: ++ return MSG_SIMPLE_TAG; ++ case VIRTIO_SCSI_S_ORDERED: ++ return MSG_ORDERED_TAG; ++ case VIRTIO_SCSI_S_HEAD: ++ return MSG_HEAD_TAG; ++ case VIRTIO_SCSI_S_ACA: ++ return MSG_ACA_TAG; ++ default: ++ break; ++ } ++ return MSG_SIMPLE_TAG; ++} ++ + static void tcm_vhost_submission_work(struct work_struct *work) + { + struct tcm_vhost_cmd *cmd = +@@ -887,9 +904,10 @@ static void tcm_vhost_submission_work(struct work_struct *work) + rc = target_submit_cmd_map_sgls(se_cmd, tv_nexus->tvn_se_sess, + cmd->tvc_cdb, &cmd->tvc_sense_buf[0], + cmd->tvc_lun, cmd->tvc_exp_data_len, +- cmd->tvc_task_attr, cmd->tvc_data_direction, +- TARGET_SCF_ACK_KREF, sg_ptr, cmd->tvc_sgl_count, +- sg_bidi_ptr, sg_no_bidi, NULL, 0); ++ vhost_scsi_to_tcm_attr(cmd->tvc_task_attr), ++ cmd->tvc_data_direction, TARGET_SCF_ACK_KREF, ++ sg_ptr, cmd->tvc_sgl_count, sg_bidi_ptr, sg_no_bidi, ++ NULL, 0); + if (rc < 0) { + transport_send_check_condition_and_sense(se_cmd, + TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0); +@@ -1200,6 +1218,7 @@ static int + vhost_scsi_set_endpoint(struct vhost_scsi *vs, + struct vhost_scsi_target *t) + { ++ struct se_portal_group *se_tpg; + struct tcm_vhost_tport *tv_tport; + struct tcm_vhost_tpg *tpg; + struct tcm_vhost_tpg **vs_tpg; +@@ -1247,6 +1266,21 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs, + ret = -EEXIST; + goto out; + } ++ /* ++ * In order to ensure individual vhost-scsi configfs ++ * groups cannot be removed while in use by vhost ioctl, ++ * go ahead and take an explicit se_tpg->tpg_group.cg_item ++ * dependency now. ++ */ ++ se_tpg = &tpg->se_tpg; ++ ret = configfs_depend_item(se_tpg->se_tpg_tfo->tf_subsys, ++ &se_tpg->tpg_group.cg_item); ++ if (ret) { ++ pr_warn("configfs_depend_item() failed: %d\n", ret); ++ kfree(vs_tpg); ++ mutex_unlock(&tpg->tv_tpg_mutex); ++ goto out; ++ } + tpg->tv_tpg_vhost_count++; + tpg->vhost_scsi = vs; + vs_tpg[tpg->tport_tpgt] = tpg; +@@ -1289,6 +1323,7 @@ static int + vhost_scsi_clear_endpoint(struct vhost_scsi *vs, + struct vhost_scsi_target *t) + { ++ struct se_portal_group *se_tpg; + struct tcm_vhost_tport *tv_tport; + struct tcm_vhost_tpg *tpg; + struct vhost_virtqueue *vq; +@@ -1337,6 +1372,13 @@ vhost_scsi_clear_endpoint(struct vhost_scsi *vs, + vs->vs_tpg[target] = NULL; + match = true; + mutex_unlock(&tpg->tv_tpg_mutex); ++ /* ++ * Release se_tpg->tpg_group.cg_item configfs dependency now ++ * to allow vhost-scsi WWPN se_tpg->tpg_group shutdown to occur. ++ */ ++ se_tpg = &tpg->se_tpg; ++ configfs_undepend_item(se_tpg->se_tpg_tfo->tf_subsys, ++ &se_tpg->tpg_group.cg_item); + } + if (match) { + for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) { +diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c +index 78987e4..85095d7 100644 +--- a/drivers/vhost/vhost.c ++++ b/drivers/vhost/vhost.c +@@ -876,6 +876,7 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp) + } + if (eventfp != d->log_file) { + filep = d->log_file; ++ d->log_file = eventfp; + ctx = d->log_ctx; + d->log_ctx = eventfp ? + eventfd_ctx_fileget(eventfp) : NULL; +diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c +index 61b182b..dbfe4ee 100644 +--- a/drivers/video/console/bitblit.c ++++ b/drivers/video/console/bitblit.c +@@ -205,7 +205,6 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info, + static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, + int bottom_only) + { +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + unsigned int cw = vc->vc_font.width; + unsigned int ch = vc->vc_font.height; + unsigned int rw = info->var.xres - (vc->vc_cols*cw); +@@ -214,7 +213,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, + unsigned int bs = info->var.yres - bh; + struct fb_fillrect region; + +- region.color = attr_bgcol_ec(bgshift, vc, info); ++ region.color = 0; + region.rop = ROP_COPY; + + if (rw && !bottom_only) { +diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c +index 41b32ae..5a3cbf6 100644 +--- a/drivers/video/console/fbcon_ccw.c ++++ b/drivers/video/console/fbcon_ccw.c +@@ -197,9 +197,8 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info, + unsigned int bh = info->var.xres - (vc->vc_rows*ch); + unsigned int bs = vc->vc_rows*ch; + struct fb_fillrect region; +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + +- region.color = attr_bgcol_ec(bgshift,vc,info); ++ region.color = 0; + region.rop = ROP_COPY; + + if (rw && !bottom_only) { +diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c +index a93670e..e7ee44d 100644 +--- a/drivers/video/console/fbcon_cw.c ++++ b/drivers/video/console/fbcon_cw.c +@@ -180,9 +180,8 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info, + unsigned int bh = info->var.xres - (vc->vc_rows*ch); + unsigned int rs = info->var.yres - rw; + struct fb_fillrect region; +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + +- region.color = attr_bgcol_ec(bgshift,vc,info); ++ region.color = 0; + region.rop = ROP_COPY; + + if (rw && !bottom_only) { +diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c +index ff0872c..19e3714 100644 +--- a/drivers/video/console/fbcon_ud.c ++++ b/drivers/video/console/fbcon_ud.c +@@ -227,9 +227,8 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info, + unsigned int rw = info->var.xres - (vc->vc_cols*cw); + unsigned int bh = info->var.yres - (vc->vc_rows*ch); + struct fb_fillrect region; +- int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; + +- region.color = attr_bgcol_ec(bgshift,vc,info); ++ region.color = 0; + region.rop = ROP_COPY; + + if (rw && !bottom_only) { +diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c +index b670cbd..ffe024b 100644 +--- a/drivers/video/logo/logo.c ++++ b/drivers/video/logo/logo.c +@@ -21,6 +21,21 @@ static bool nologo; + module_param(nologo, bool, 0); + MODULE_PARM_DESC(nologo, "Disables startup logo"); + ++/* ++ * Logos are located in the initdata, and will be freed in kernel_init. ++ * Use late_init to mark the logos as freed to prevent any further use. ++ */ ++ ++static bool logos_freed; ++ ++static int __init fb_logo_late_init(void) ++{ ++ logos_freed = true; ++ return 0; ++} ++ ++late_initcall(fb_logo_late_init); ++ + /* logo's are marked __initdata. Use __init_refok to tell + * modpost that it is intended that this function uses data + * marked __initdata. +@@ -29,7 +44,7 @@ const struct linux_logo * __init_refok fb_find_logo(int depth) + { + const struct linux_logo *logo = NULL; + +- if (nologo) ++ if (nologo || logos_freed) + return NULL; + + if (depth >= 1) { +diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c +index a416f9b..827b5f8 100644 +--- a/drivers/virtio/virtio_pci.c ++++ b/drivers/virtio/virtio_pci.c +@@ -791,6 +791,7 @@ static int virtio_pci_restore(struct device *dev) + struct pci_dev *pci_dev = to_pci_dev(dev); + struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); + struct virtio_driver *drv; ++ unsigned status = 0; + int ret; + + drv = container_of(vp_dev->vdev.dev.driver, +@@ -801,14 +802,40 @@ static int virtio_pci_restore(struct device *dev) + return ret; + + pci_set_master(pci_dev); ++ /* We always start by resetting the device, in case a previous ++ * driver messed it up. */ ++ vp_reset(&vp_dev->vdev); ++ ++ /* Acknowledge that we've seen the device. */ ++ status |= VIRTIO_CONFIG_S_ACKNOWLEDGE; ++ vp_set_status(&vp_dev->vdev, status); ++ ++ /* Maybe driver failed before freeze. ++ * Restore the failed status, for debugging. */ ++ status |= vp_dev->saved_status & VIRTIO_CONFIG_S_FAILED; ++ vp_set_status(&vp_dev->vdev, status); ++ ++ if (!drv) ++ return 0; ++ ++ /* We have a driver! */ ++ status |= VIRTIO_CONFIG_S_DRIVER; ++ vp_set_status(&vp_dev->vdev, status); ++ + vp_finalize_features(&vp_dev->vdev); + +- if (drv && drv->restore) ++ if (drv->restore) { + ret = drv->restore(&vp_dev->vdev); ++ if (ret) { ++ status |= VIRTIO_CONFIG_S_FAILED; ++ vp_set_status(&vp_dev->vdev, status); ++ return ret; ++ } ++ } + + /* Finally, tell the device we're all set */ +- if (!ret) +- vp_set_status(&vp_dev->vdev, vp_dev->saved_status); ++ status |= VIRTIO_CONFIG_S_DRIVER_OK; ++ vp_set_status(&vp_dev->vdev, status); + + return ret; + } +diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c +index 09cf013..90a6406 100644 +--- a/drivers/watchdog/omap_wdt.c ++++ b/drivers/watchdog/omap_wdt.c +@@ -134,6 +134,13 @@ static int omap_wdt_start(struct watchdog_device *wdog) + + pm_runtime_get_sync(wdev->dev); + ++ /* ++ * Make sure the watchdog is disabled. This is unfortunately required ++ * because writing to various registers with the watchdog running has no ++ * effect. ++ */ ++ omap_wdt_disable(wdev); ++ + /* initialize prescaler */ + while (readl_relaxed(base + OMAP_WATCHDOG_WPS) & 0x01) + cpu_relax(); +diff --git a/drivers/xen/events/events_2l.c b/drivers/xen/events/events_2l.c +index d7ff917..843e5d8 100644 +--- a/drivers/xen/events/events_2l.c ++++ b/drivers/xen/events/events_2l.c +@@ -352,6 +352,15 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id) + return IRQ_HANDLED; + } + ++static void evtchn_2l_resume(void) ++{ ++ int i; ++ ++ for_each_online_cpu(i) ++ memset(per_cpu(cpu_evtchn_mask, i), 0, sizeof(xen_ulong_t) * ++ EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD); ++} ++ + static const struct evtchn_ops evtchn_ops_2l = { + .max_channels = evtchn_2l_max_channels, + .nr_channels = evtchn_2l_max_channels, +@@ -363,6 +372,7 @@ static const struct evtchn_ops evtchn_ops_2l = { + .mask = evtchn_2l_mask, + .unmask = evtchn_2l_unmask, + .handle_events = evtchn_2l_handle_events, ++ .resume = evtchn_2l_resume, + }; + + void __init xen_evtchn_2l_init(void) +diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c +index f4a9e33..5af64e9 100644 +--- a/drivers/xen/events/events_base.c ++++ b/drivers/xen/events/events_base.c +@@ -547,20 +547,26 @@ static unsigned int __startup_pirq(unsigned int irq) + pirq_query_unmask(irq); + + rc = set_evtchn_to_irq(evtchn, irq); +- if (rc != 0) { +- pr_err("irq%d: Failed to set port to irq mapping (%d)\n", +- irq, rc); +- xen_evtchn_close(evtchn); +- return 0; +- } +- bind_evtchn_to_cpu(evtchn, 0); ++ if (rc) ++ goto err; ++ + info->evtchn = evtchn; ++ bind_evtchn_to_cpu(evtchn, 0); ++ ++ rc = xen_evtchn_port_setup(info); ++ if (rc) ++ goto err; + + out: + unmask_evtchn(evtchn); + eoi_pirq(irq_get_irq_data(irq)); + + return 0; ++ ++err: ++ pr_err("irq%d: Failed to set port to irq mapping (%d)\n", irq, rc); ++ xen_evtchn_close(evtchn); ++ return 0; + } + + static unsigned int startup_pirq(struct irq_data *data) +@@ -967,7 +973,7 @@ unsigned xen_evtchn_nr_channels(void) + } + EXPORT_SYMBOL_GPL(xen_evtchn_nr_channels); + +-int bind_virq_to_irq(unsigned int virq, unsigned int cpu) ++int bind_virq_to_irq(unsigned int virq, unsigned int cpu, bool percpu) + { + struct evtchn_bind_virq bind_virq; + int evtchn, irq, ret; +@@ -981,8 +987,12 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu) + if (irq < 0) + goto out; + +- irq_set_chip_and_handler_name(irq, &xen_percpu_chip, +- handle_percpu_irq, "virq"); ++ if (percpu) ++ irq_set_chip_and_handler_name(irq, &xen_percpu_chip, ++ handle_percpu_irq, "virq"); ++ else ++ irq_set_chip_and_handler_name(irq, &xen_dynamic_chip, ++ handle_edge_irq, "virq"); + + bind_virq.virq = virq; + bind_virq.vcpu = cpu; +@@ -1072,7 +1082,7 @@ int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, + { + int irq, retval; + +- irq = bind_virq_to_irq(virq, cpu); ++ irq = bind_virq_to_irq(virq, cpu, irqflags & IRQF_PERCPU); + if (irq < 0) + return irq; + retval = request_irq(irq, handler, irqflags, devname, dev_id); +@@ -1288,8 +1298,9 @@ void rebind_evtchn_irq(int evtchn, int irq) + + mutex_unlock(&irq_mapping_update_lock); + +- /* new event channels are always bound to cpu 0 */ +- irq_set_affinity(irq, cpumask_of(0)); ++ bind_evtchn_to_cpu(evtchn, info->cpu); ++ /* This will be deferred until interrupt is processed */ ++ irq_set_affinity(irq, cpumask_of(info->cpu)); + + /* Unmask the event channel. */ + enable_irq(irq); +diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c +index 640b3cf..ef7d446 100644 +--- a/drivers/xen/events/events_fifo.c ++++ b/drivers/xen/events/events_fifo.c +@@ -67,10 +67,9 @@ static event_word_t *event_array[MAX_EVENT_ARRAY_PAGES] __read_mostly; + static unsigned event_array_pages __read_mostly; + + /* +- * sync_set_bit() and friends must be unsigned long aligned on non-x86 +- * platforms. ++ * sync_set_bit() and friends must be unsigned long aligned. + */ +-#if !defined(CONFIG_X86) && BITS_PER_LONG > 32 ++#if BITS_PER_LONG > 32 + + #define BM(w) (unsigned long *)((unsigned long)w & ~0x7UL) + #define EVTCHN_FIFO_BIT(b, w) \ +@@ -100,6 +99,25 @@ static unsigned evtchn_fifo_nr_channels(void) + return event_array_pages * EVENT_WORDS_PER_PAGE; + } + ++static int init_control_block(int cpu, ++ struct evtchn_fifo_control_block *control_block) ++{ ++ struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu); ++ struct evtchn_init_control init_control; ++ unsigned int i; ++ ++ /* Reset the control block and the local HEADs. */ ++ clear_page(control_block); ++ for (i = 0; i < EVTCHN_FIFO_MAX_QUEUES; i++) ++ q->head[i] = 0; ++ ++ init_control.control_gfn = virt_to_mfn(control_block); ++ init_control.offset = 0; ++ init_control.vcpu = cpu; ++ ++ return HYPERVISOR_event_channel_op(EVTCHNOP_init_control, &init_control); ++} ++ + static void free_unused_array_pages(void) + { + unsigned i; +@@ -328,7 +346,6 @@ static void evtchn_fifo_resume(void) + + for_each_possible_cpu(cpu) { + void *control_block = per_cpu(cpu_control_block, cpu); +- struct evtchn_init_control init_control; + int ret; + + if (!control_block) +@@ -345,12 +362,7 @@ static void evtchn_fifo_resume(void) + continue; + } + +- init_control.control_gfn = virt_to_mfn(control_block); +- init_control.offset = 0; +- init_control.vcpu = cpu; +- +- ret = HYPERVISOR_event_channel_op(EVTCHNOP_init_control, +- &init_control); ++ ret = init_control_block(cpu, control_block); + if (ret < 0) + BUG(); + } +@@ -378,30 +390,25 @@ static const struct evtchn_ops evtchn_ops_fifo = { + .resume = evtchn_fifo_resume, + }; + +-static int evtchn_fifo_init_control_block(unsigned cpu) ++static int evtchn_fifo_alloc_control_block(unsigned cpu) + { +- struct page *control_block = NULL; +- struct evtchn_init_control init_control; ++ void *control_block = NULL; + int ret = -ENOMEM; + +- control_block = alloc_page(GFP_KERNEL|__GFP_ZERO); ++ control_block = (void *)__get_free_page(GFP_KERNEL); + if (control_block == NULL) + goto error; + +- init_control.control_gfn = virt_to_mfn(page_address(control_block)); +- init_control.offset = 0; +- init_control.vcpu = cpu; +- +- ret = HYPERVISOR_event_channel_op(EVTCHNOP_init_control, &init_control); ++ ret = init_control_block(cpu, control_block); + if (ret < 0) + goto error; + +- per_cpu(cpu_control_block, cpu) = page_address(control_block); ++ per_cpu(cpu_control_block, cpu) = control_block; + + return 0; + + error: +- __free_page(control_block); ++ free_page((unsigned long)control_block); + return ret; + } + +@@ -415,7 +422,7 @@ static int evtchn_fifo_cpu_notification(struct notifier_block *self, + switch (action) { + case CPU_UP_PREPARE: + if (!per_cpu(cpu_control_block, cpu)) +- ret = evtchn_fifo_init_control_block(cpu); ++ ret = evtchn_fifo_alloc_control_block(cpu); + break; + default: + break; +@@ -432,7 +439,7 @@ int __init xen_evtchn_fifo_init(void) + int cpu = get_cpu(); + int ret; + +- ret = evtchn_fifo_init_control_block(cpu); ++ ret = evtchn_fifo_alloc_control_block(cpu); + if (ret < 0) + goto out; + +diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c +index 073b4a1..ff3c98f 100644 +--- a/drivers/xen/gntdev.c ++++ b/drivers/xen/gntdev.c +@@ -529,12 +529,14 @@ static int gntdev_release(struct inode *inode, struct file *flip) + + pr_debug("priv %p\n", priv); + ++ mutex_lock(&priv->lock); + while (!list_empty(&priv->maps)) { + map = list_entry(priv->maps.next, struct grant_map, next); + list_del(&map->next); + gntdev_put_map(NULL /* already removed */, map); + } + WARN_ON(!list_empty(&priv->freeable_maps)); ++ mutex_unlock(&priv->lock); + + if (use_ptemod) + mmu_notifier_unregister(&priv->mn, priv->mm); +diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c +index 624e8dc..edfd797 100644 +--- a/drivers/xen/manage.c ++++ b/drivers/xen/manage.c +@@ -111,16 +111,17 @@ static void do_suspend(void) + + shutting_down = SHUTDOWN_SUSPEND; + +-#ifdef CONFIG_PREEMPT +- /* If the kernel is preemptible, we need to freeze all the processes +- to prevent them from being in the middle of a pagetable update +- during suspend. */ + err = freeze_processes(); + if (err) { +- pr_err("%s: freeze failed %d\n", __func__, err); ++ pr_err("%s: freeze processes failed %d\n", __func__, err); + goto out; + } +-#endif ++ ++ err = freeze_kernel_threads(); ++ if (err) { ++ pr_err("%s: freeze kernel threads failed %d\n", __func__, err); ++ goto out_thaw; ++ } + + err = dpm_suspend_start(PMSG_FREEZE); + if (err) { +@@ -169,10 +170,8 @@ out_resume: + dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE); + + out_thaw: +-#ifdef CONFIG_PREEMPT + thaw_processes(); + out: +-#endif + shutting_down = SHUTDOWN_INVALID; + } + #endif /* CONFIG_HIBERNATE_CALLBACKS */ +diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c +index ebd8f21..f3a9d83 100644 +--- a/drivers/xen/swiotlb-xen.c ++++ b/drivers/xen/swiotlb-xen.c +@@ -96,8 +96,6 @@ static inline phys_addr_t xen_bus_to_phys(dma_addr_t baddr) + dma_addr_t dma = (dma_addr_t)pfn << PAGE_SHIFT; + phys_addr_t paddr = dma; + +- BUG_ON(paddr != dma); /* truncation has occurred, should never happen */ +- + paddr |= baddr & ~PAGE_MASK; + + return paddr; +@@ -447,7 +445,7 @@ static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr, + + BUG_ON(dir == DMA_NONE); + +- xen_dma_unmap_page(hwdev, paddr, size, dir, attrs); ++ xen_dma_unmap_page(hwdev, dev_addr, size, dir, attrs); + + /* NOTE: We use dev_addr here, not paddr! */ + if (is_xen_swiotlb_buffer(dev_addr)) { +@@ -495,14 +493,14 @@ xen_swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr, + BUG_ON(dir == DMA_NONE); + + if (target == SYNC_FOR_CPU) +- xen_dma_sync_single_for_cpu(hwdev, paddr, size, dir); ++ xen_dma_sync_single_for_cpu(hwdev, dev_addr, size, dir); + + /* NOTE: We use dev_addr here, not paddr! */ + if (is_xen_swiotlb_buffer(dev_addr)) + swiotlb_tbl_sync_single(hwdev, paddr, size, dir, target); + + if (target == SYNC_FOR_DEVICE) +- xen_dma_sync_single_for_cpu(hwdev, paddr, size, dir); ++ xen_dma_sync_single_for_device(hwdev, dev_addr, size, dir); + + if (dir != DMA_FROM_DEVICE) + return; +diff --git a/drivers/xen/xen-pciback/conf_space.c b/drivers/xen/xen-pciback/conf_space.c +index 46ae0f9..75fe3d4 100644 +--- a/drivers/xen/xen-pciback/conf_space.c ++++ b/drivers/xen/xen-pciback/conf_space.c +@@ -16,7 +16,7 @@ + #include "conf_space.h" + #include "conf_space_quirks.h" + +-static bool permissive; ++bool permissive; + module_param(permissive, bool, 0644); + + /* This is where xen_pcibk_read_config_byte, xen_pcibk_read_config_word, +diff --git a/drivers/xen/xen-pciback/conf_space.h b/drivers/xen/xen-pciback/conf_space.h +index e56c934..2e1d73d 100644 +--- a/drivers/xen/xen-pciback/conf_space.h ++++ b/drivers/xen/xen-pciback/conf_space.h +@@ -64,6 +64,8 @@ struct config_field_entry { + void *data; + }; + ++extern bool permissive; ++ + #define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset) + + /* Add fields to a device - the add_fields macro expects to get a pointer to +diff --git a/drivers/xen/xen-pciback/conf_space_header.c b/drivers/xen/xen-pciback/conf_space_header.c +index c5ee825..2d73693 100644 +--- a/drivers/xen/xen-pciback/conf_space_header.c ++++ b/drivers/xen/xen-pciback/conf_space_header.c +@@ -11,6 +11,10 @@ + #include "pciback.h" + #include "conf_space.h" + ++struct pci_cmd_info { ++ u16 val; ++}; ++ + struct pci_bar_info { + u32 val; + u32 len_val; +@@ -20,22 +24,36 @@ struct pci_bar_info { + #define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO)) + #define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER) + +-static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data) ++/* Bits guests are allowed to control in permissive mode. */ ++#define PCI_COMMAND_GUEST (PCI_COMMAND_MASTER|PCI_COMMAND_SPECIAL| \ ++ PCI_COMMAND_INVALIDATE|PCI_COMMAND_VGA_PALETTE| \ ++ PCI_COMMAND_WAIT|PCI_COMMAND_FAST_BACK) ++ ++static void *command_init(struct pci_dev *dev, int offset) + { +- int i; +- int ret; +- +- ret = xen_pcibk_read_config_word(dev, offset, value, data); +- if (!pci_is_enabled(dev)) +- return ret; +- +- for (i = 0; i < PCI_ROM_RESOURCE; i++) { +- if (dev->resource[i].flags & IORESOURCE_IO) +- *value |= PCI_COMMAND_IO; +- if (dev->resource[i].flags & IORESOURCE_MEM) +- *value |= PCI_COMMAND_MEMORY; ++ struct pci_cmd_info *cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); ++ int err; ++ ++ if (!cmd) ++ return ERR_PTR(-ENOMEM); ++ ++ err = pci_read_config_word(dev, PCI_COMMAND, &cmd->val); ++ if (err) { ++ kfree(cmd); ++ return ERR_PTR(err); + } + ++ return cmd; ++} ++ ++static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data) ++{ ++ int ret = pci_read_config_word(dev, offset, value); ++ const struct pci_cmd_info *cmd = data; ++ ++ *value &= PCI_COMMAND_GUEST; ++ *value |= cmd->val & ~PCI_COMMAND_GUEST; ++ + return ret; + } + +@@ -43,6 +61,8 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) + { + struct xen_pcibk_dev_data *dev_data; + int err; ++ u16 val; ++ struct pci_cmd_info *cmd = data; + + dev_data = pci_get_drvdata(dev); + if (!pci_is_enabled(dev) && is_enable_cmd(value)) { +@@ -83,6 +103,19 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) + } + } + ++ cmd->val = value; ++ ++ if (!permissive && (!dev_data || !dev_data->permissive)) ++ return 0; ++ ++ /* Only allow the guest to control certain bits. */ ++ err = pci_read_config_word(dev, offset, &val); ++ if (err || val == value) ++ return err; ++ ++ value &= PCI_COMMAND_GUEST; ++ value |= val & ~PCI_COMMAND_GUEST; ++ + return pci_write_config_word(dev, offset, value); + } + +@@ -282,6 +315,8 @@ static const struct config_field header_common[] = { + { + .offset = PCI_COMMAND, + .size = 2, ++ .init = command_init, ++ .release = bar_release, + .u.w.read = command_read, + .u.w.write = command_write, + }, +diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c +index bb7991c..bfdeadb 100644 +--- a/fs/9p/vfs_inode.c ++++ b/fs/9p/vfs_inode.c +@@ -540,8 +540,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb, + unlock_new_inode(inode); + return inode; + error: +- unlock_new_inode(inode); +- iput(inode); ++ iget_failed(inode); + return ERR_PTR(retval); + + } +diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c +index 59dc8e8..de8606c 100644 +--- a/fs/9p/vfs_inode_dotl.c ++++ b/fs/9p/vfs_inode_dotl.c +@@ -149,8 +149,7 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, + unlock_new_inode(inode); + return inode; + error: +- unlock_new_inode(inode); +- iput(inode); ++ iget_failed(inode); + return ERR_PTR(retval); + + } +diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c +index d9a4367..9cca0ea 100644 +--- a/fs/affs/amigaffs.c ++++ b/fs/affs/amigaffs.c +@@ -126,7 +126,7 @@ affs_fix_dcache(struct inode *inode, u32 entry_ino) + { + struct dentry *dentry; + spin_lock(&inode->i_lock); +- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) { + if (entry_ino == (u32)(long)dentry->d_fsdata) { + dentry->d_fsdata = (void *)inode->i_ino; + break; +diff --git a/fs/aio.c b/fs/aio.c +index 6d68e01..3241659 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -141,6 +141,7 @@ struct kioctx { + + struct { + unsigned tail; ++ unsigned completed_events; + spinlock_t completion_lock; + } ____cacheline_aligned_in_smp; + +@@ -164,6 +165,15 @@ static struct vfsmount *aio_mnt; + static const struct file_operations aio_ring_fops; + static const struct address_space_operations aio_ctx_aops; + ++/* Backing dev info for aio fs. ++ * -no dirty page accounting or writeback happens ++ */ ++static struct backing_dev_info aio_fs_backing_dev_info = { ++ .name = "aiofs", ++ .state = 0, ++ .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK | BDI_CAP_MAP_COPY, ++}; ++ + static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) + { + struct qstr this = QSTR_INIT("[aio]", 5); +@@ -175,6 +185,7 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) + + inode->i_mapping->a_ops = &aio_ctx_aops; + inode->i_mapping->private_data = ctx; ++ inode->i_mapping->backing_dev_info = &aio_fs_backing_dev_info; + inode->i_size = PAGE_SIZE * nr_pages; + + path.dentry = d_alloc_pseudo(aio_mnt->mnt_sb, &this); +@@ -220,6 +231,9 @@ static int __init aio_setup(void) + if (IS_ERR(aio_mnt)) + panic("Failed to create aio fs mount."); + ++ if (bdi_init(&aio_fs_backing_dev_info)) ++ panic("Failed to init aio fs backing dev info."); ++ + kiocb_cachep = KMEM_CACHE(kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC); + kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC); + +@@ -281,11 +295,6 @@ static const struct file_operations aio_ring_fops = { + .mmap = aio_ring_mmap, + }; + +-static int aio_set_page_dirty(struct page *page) +-{ +- return 0; +-} +- + #if IS_ENABLED(CONFIG_MIGRATION) + static int aio_migratepage(struct address_space *mapping, struct page *new, + struct page *old, enum migrate_mode mode) +@@ -357,7 +366,7 @@ out: + #endif + + static const struct address_space_operations aio_ctx_aops = { +- .set_page_dirty = aio_set_page_dirty, ++ .set_page_dirty = __set_page_dirty_no_writeback, + #if IS_ENABLED(CONFIG_MIGRATION) + .migratepage = aio_migratepage, + #endif +@@ -412,7 +421,6 @@ static int aio_setup_ring(struct kioctx *ctx) + pr_debug("pid(%d) page[%d]->count=%d\n", + current->pid, i, page_count(page)); + SetPageUptodate(page); +- SetPageDirty(page); + unlock_page(page); + + ctx->ring_pages[i] = page; +@@ -711,6 +719,9 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) + err_cleanup: + aio_nr_sub(ctx->max_reqs); + err_ctx: ++ atomic_set(&ctx->dead, 1); ++ if (ctx->mmap_size) ++ vm_munmap(ctx->mmap_base, ctx->mmap_size); + aio_free_ring(ctx); + err: + mutex_unlock(&ctx->ring_lock); +@@ -796,6 +807,9 @@ void exit_aio(struct mm_struct *mm) + unsigned i = 0; + + while (1) { ++ struct completion requests_done = ++ COMPLETION_INITIALIZER_ONSTACK(requests_done); ++ + rcu_read_lock(); + table = rcu_dereference(mm->ioctx_table); + +@@ -823,7 +837,10 @@ void exit_aio(struct mm_struct *mm) + */ + ctx->mmap_size = 0; + +- kill_ioctx(mm, ctx, NULL); ++ kill_ioctx(mm, ctx, &requests_done); ++ ++ /* Wait until all IO for the context are done. */ ++ wait_for_completion(&requests_done); + } + } + +@@ -880,6 +897,68 @@ out: + return ret; + } + ++/* refill_reqs_available ++ * Updates the reqs_available reference counts used for tracking the ++ * number of free slots in the completion ring. This can be called ++ * from aio_complete() (to optimistically update reqs_available) or ++ * from aio_get_req() (the we're out of events case). It must be ++ * called holding ctx->completion_lock. ++ */ ++static void refill_reqs_available(struct kioctx *ctx, unsigned head, ++ unsigned tail) ++{ ++ unsigned events_in_ring, completed; ++ ++ /* Clamp head since userland can write to it. */ ++ head %= ctx->nr_events; ++ if (head <= tail) ++ events_in_ring = tail - head; ++ else ++ events_in_ring = ctx->nr_events - (head - tail); ++ ++ completed = ctx->completed_events; ++ if (events_in_ring < completed) ++ completed -= events_in_ring; ++ else ++ completed = 0; ++ ++ if (!completed) ++ return; ++ ++ ctx->completed_events -= completed; ++ put_reqs_available(ctx, completed); ++} ++ ++/* user_refill_reqs_available ++ * Called to refill reqs_available when aio_get_req() encounters an ++ * out of space in the completion ring. ++ */ ++static void user_refill_reqs_available(struct kioctx *ctx) ++{ ++ spin_lock_irq(&ctx->completion_lock); ++ if (ctx->completed_events) { ++ struct aio_ring *ring; ++ unsigned head; ++ ++ /* Access of ring->head may race with aio_read_events_ring() ++ * here, but that's okay since whether we read the old version ++ * or the new version, and either will be valid. The important ++ * part is that head cannot pass tail since we prevent ++ * aio_complete() from updating tail by holding ++ * ctx->completion_lock. Even if head is invalid, the check ++ * against ctx->completed_events below will make sure we do the ++ * safe/right thing. ++ */ ++ ring = kmap_atomic(ctx->ring_pages[0]); ++ head = ring->head; ++ kunmap_atomic(ring); ++ ++ refill_reqs_available(ctx, head, ctx->tail); ++ } ++ ++ spin_unlock_irq(&ctx->completion_lock); ++} ++ + /* aio_get_req + * Allocate a slot for an aio request. + * Returns NULL if no requests are free. +@@ -888,8 +967,11 @@ static inline struct kiocb *aio_get_req(struct kioctx *ctx) + { + struct kiocb *req; + +- if (!get_reqs_available(ctx)) +- return NULL; ++ if (!get_reqs_available(ctx)) { ++ user_refill_reqs_available(ctx); ++ if (!get_reqs_available(ctx)) ++ return NULL; ++ } + + req = kmem_cache_alloc(kiocb_cachep, GFP_KERNEL|__GFP_ZERO); + if (unlikely(!req)) +@@ -948,8 +1030,8 @@ void aio_complete(struct kiocb *iocb, long res, long res2) + struct kioctx *ctx = iocb->ki_ctx; + struct aio_ring *ring; + struct io_event *ev_page, *event; ++ unsigned tail, pos, head; + unsigned long flags; +- unsigned tail, pos; + + /* + * Special case handling for sync iocbs: +@@ -1010,10 +1092,14 @@ void aio_complete(struct kiocb *iocb, long res, long res2) + ctx->tail = tail; + + ring = kmap_atomic(ctx->ring_pages[0]); ++ head = ring->head; + ring->tail = tail; + kunmap_atomic(ring); + flush_dcache_page(ctx->ring_pages[0]); + ++ ctx->completed_events++; ++ if (ctx->completed_events > 1) ++ refill_reqs_available(ctx, head, tail); + spin_unlock_irqrestore(&ctx->completion_lock, flags); + + pr_debug("added to ring %p at [%u]\n", iocb, tail); +@@ -1028,7 +1114,6 @@ void aio_complete(struct kiocb *iocb, long res, long res2) + + /* everything turned out well, dispose of the aiocb. */ + kiocb_free(iocb); +- put_reqs_available(ctx, 1); + + /* + * We have to order our ring_info tail store above and test +@@ -1065,6 +1150,12 @@ static long aio_read_events_ring(struct kioctx *ctx, + tail = ring->tail; + kunmap_atomic(ring); + ++ /* ++ * Ensure that once we've read the current tail pointer, that ++ * we also see the events that were stored up to the tail. ++ */ ++ smp_rmb(); ++ + pr_debug("h%u t%u m%u\n", head, tail, ctx->nr_events); + + if (head == tail) +diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c +index 3182c0e..e3399dc 100644 +--- a/fs/autofs4/dev-ioctl.c ++++ b/fs/autofs4/dev-ioctl.c +@@ -95,7 +95,7 @@ static int check_dev_ioctl_version(int cmd, struct autofs_dev_ioctl *param) + */ + static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *in) + { +- struct autofs_dev_ioctl tmp; ++ struct autofs_dev_ioctl tmp, *res; + + if (copy_from_user(&tmp, in, sizeof(tmp))) + return ERR_PTR(-EFAULT); +@@ -103,7 +103,11 @@ static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *i + if (tmp.size < sizeof(tmp)) + return ERR_PTR(-EINVAL); + +- return memdup_user(in, tmp.size); ++ res = memdup_user(in, tmp.size); ++ if (!IS_ERR(res)) ++ res->size = tmp.size; ++ ++ return res; + } + + static inline void free_dev_ioctl(struct autofs_dev_ioctl *param) +diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c +index 394e90b..edb46e6 100644 +--- a/fs/autofs4/expire.c ++++ b/fs/autofs4/expire.c +@@ -91,7 +91,7 @@ static struct dentry *get_next_positive_subdir(struct dentry *prev, + spin_lock(&root->d_lock); + + if (prev) +- next = prev->d_u.d_child.next; ++ next = prev->d_child.next; + else { + prev = dget_dlock(root); + next = prev->d_subdirs.next; +@@ -105,13 +105,13 @@ cont: + return NULL; + } + +- q = list_entry(next, struct dentry, d_u.d_child); ++ q = list_entry(next, struct dentry, d_child); + + spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED); + /* Already gone or negative dentry (under construction) - try next */ + if (!d_count(q) || !simple_positive(q)) { + spin_unlock(&q->d_lock); +- next = q->d_u.d_child.next; ++ next = q->d_child.next; + goto cont; + } + dget_dlock(q); +@@ -161,13 +161,13 @@ again: + goto relock; + } + spin_unlock(&p->d_lock); +- next = p->d_u.d_child.next; ++ next = p->d_child.next; + p = parent; + if (next != &parent->d_subdirs) + break; + } + } +- ret = list_entry(next, struct dentry, d_u.d_child); ++ ret = list_entry(next, struct dentry, d_child); + + spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED); + /* Negative dentry - try next */ +@@ -461,7 +461,7 @@ found: + spin_lock(&sbi->lookup_lock); + spin_lock(&expired->d_parent->d_lock); + spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED); +- list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child); ++ list_move(&expired->d_parent->d_subdirs, &expired->d_child); + spin_unlock(&expired->d_lock); + spin_unlock(&expired->d_parent->d_lock); + spin_unlock(&sbi->lookup_lock); +diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c +index cc87c1a..9e016e6 100644 +--- a/fs/autofs4/root.c ++++ b/fs/autofs4/root.c +@@ -655,7 +655,7 @@ static void autofs_clear_leaf_automount_flags(struct dentry *dentry) + /* only consider parents below dentrys in the root */ + if (IS_ROOT(parent->d_parent)) + return; +- d_child = &dentry->d_u.d_child; ++ d_child = &dentry->d_child; + /* Set parent managed if it's becoming empty */ + if (d_child->next == &parent->d_subdirs && + d_child->prev == &parent->d_subdirs) +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index 67be295..35240a7 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -549,11 +549,12 @@ out: + + static unsigned long randomize_stack_top(unsigned long stack_top) + { +- unsigned int random_variable = 0; ++ unsigned long random_variable = 0; + + if ((current->flags & PF_RANDOMIZE) && + !(current->personality & ADDR_NO_RANDOMIZE)) { +- random_variable = get_random_int() & STACK_RND_MASK; ++ random_variable = (unsigned long) get_random_int(); ++ random_variable &= STACK_RND_MASK; + random_variable <<= PAGE_SHIFT; + } + #ifdef CONFIG_STACK_GROWSUP +@@ -750,6 +751,7 @@ static int load_elf_binary(struct linux_binprm *bprm) + i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { + int elf_prot = 0, elf_flags; + unsigned long k, vaddr; ++ unsigned long total_size = 0; + + if (elf_ppnt->p_type != PT_LOAD) + continue; +@@ -814,10 +816,16 @@ static int load_elf_binary(struct linux_binprm *bprm) + #else + load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); + #endif ++ total_size = total_mapping_size(elf_phdata, ++ loc->elf_ex.e_phnum); ++ if (!total_size) { ++ retval = -EINVAL; ++ goto out_free_dentry; ++ } + } + + error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, +- elf_prot, elf_flags, 0); ++ elf_prot, elf_flags, total_size); + if (BAD_ADDR(error)) { + send_sig(SIGKILL, current, 0); + retval = IS_ERR((void *)error) ? +diff --git a/fs/bio.c b/fs/bio.c +index 8754e7b..b2b1451 100644 +--- a/fs/bio.c ++++ b/fs/bio.c +@@ -1806,8 +1806,9 @@ EXPORT_SYMBOL(bio_endio_nodec); + * Allocates and returns a new bio which represents @sectors from the start of + * @bio, and updates @bio to represent the remaining sectors. + * +- * The newly allocated bio will point to @bio's bi_io_vec; it is the caller's +- * responsibility to ensure that @bio is not freed before the split. ++ * Unless this is a discard request the newly allocated bio will point ++ * to @bio's bi_io_vec; it is the caller's responsibility to ensure that ++ * @bio is not freed before the split. + */ + struct bio *bio_split(struct bio *bio, int sectors, + gfp_t gfp, struct bio_set *bs) +@@ -1817,7 +1818,15 @@ struct bio *bio_split(struct bio *bio, int sectors, + BUG_ON(sectors <= 0); + BUG_ON(sectors >= bio_sectors(bio)); + +- split = bio_clone_fast(bio, gfp, bs); ++ /* ++ * Discards need a mutable bio_vec to accommodate the payload ++ * required by the DSM TRIM and UNMAP commands. ++ */ ++ if (bio->bi_rw & REQ_DISCARD) ++ split = bio_clone_bioset(bio, gfp, bs); ++ else ++ split = bio_clone_fast(bio, gfp, bs); ++ + if (!split) + return NULL; + +diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c +index 14d29d0..6244f9c 100644 +--- a/fs/btrfs/backref.c ++++ b/fs/btrfs/backref.c +@@ -275,9 +275,8 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, + } + if (ret > 0) + goto next; +- ret = ulist_add_merge(parents, eb->start, +- (uintptr_t)eie, +- (u64 *)&old, GFP_NOFS); ++ ret = ulist_add_merge_ptr(parents, eb->start, ++ eie, (void **)&old, GFP_NOFS); + if (ret < 0) + break; + if (!ret && extent_item_pos) { +@@ -985,16 +984,19 @@ again: + ret = -EIO; + goto out; + } ++ btrfs_tree_read_lock(eb); ++ btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); + ret = find_extent_in_eb(eb, bytenr, + *extent_item_pos, &eie); ++ btrfs_tree_read_unlock_blocking(eb); + free_extent_buffer(eb); + if (ret < 0) + goto out; + ref->inode_list = eie; + } +- ret = ulist_add_merge(refs, ref->parent, +- (uintptr_t)ref->inode_list, +- (u64 *)&eie, GFP_NOFS); ++ ret = ulist_add_merge_ptr(refs, ref->parent, ++ ref->inode_list, ++ (void **)&eie, GFP_NOFS); + if (ret < 0) + goto out; + if (!ret && extent_item_pos) { +diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c +index b01fb6c..d43c544 100644 +--- a/fs/btrfs/compression.c ++++ b/fs/btrfs/compression.c +@@ -472,7 +472,7 @@ static noinline int add_ra_bio_pages(struct inode *inode, + rcu_read_lock(); + page = radix_tree_lookup(&mapping->page_tree, pg_index); + rcu_read_unlock(); +- if (page) { ++ if (page && !radix_tree_exceptional_entry(page)) { + misses++; + if (misses > 4) + break; +diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c +index cbd3a7d..f8ffee4 100644 +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -2655,32 +2655,23 @@ static int key_search(struct extent_buffer *b, struct btrfs_key *key, + return 0; + } + +-int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *found_path, ++int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *path, + u64 iobjectid, u64 ioff, u8 key_type, + struct btrfs_key *found_key) + { + int ret; + struct btrfs_key key; + struct extent_buffer *eb; +- struct btrfs_path *path; ++ ++ ASSERT(path); + + key.type = key_type; + key.objectid = iobjectid; + key.offset = ioff; + +- if (found_path == NULL) { +- path = btrfs_alloc_path(); +- if (!path) +- return -ENOMEM; +- } else +- path = found_path; +- + ret = btrfs_search_slot(NULL, fs_root, &key, path, 0, 0); +- if ((ret < 0) || (found_key == NULL)) { +- if (path != found_path) +- btrfs_free_path(path); ++ if ((ret < 0) || (found_key == NULL)) + return ret; +- } + + eb = path->nodes[0]; + if (ret && path->slots[0] >= btrfs_header_nritems(eb)) { +@@ -2972,7 +2963,7 @@ done: + */ + if (!p->leave_spinning) + btrfs_set_path_blocking(p); +- if (ret < 0) ++ if (ret < 0 && !p->skip_release_on_error) + btrfs_release_path(p); + return ret; + } +diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h +index d3511cc..3b39eb4 100644 +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -608,6 +608,7 @@ struct btrfs_path { + unsigned int skip_locking:1; + unsigned int leave_spinning:1; + unsigned int search_commit_root:1; ++ unsigned int skip_release_on_error:1; + }; + + /* +@@ -3609,6 +3610,10 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, + int verify_dir_item(struct btrfs_root *root, + struct extent_buffer *leaf, + struct btrfs_dir_item *dir_item); ++struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, ++ struct btrfs_path *path, ++ const char *name, ++ int name_len); + + /* orphan.c */ + int btrfs_insert_orphan_item(struct btrfs_trans_handle *trans, +diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c +index 451b00c..12e3556 100644 +--- a/fs/btrfs/delayed-inode.c ++++ b/fs/btrfs/delayed-inode.c +@@ -1854,6 +1854,14 @@ int btrfs_delayed_delete_inode_ref(struct inode *inode) + { + struct btrfs_delayed_node *delayed_node; + ++ /* ++ * we don't do delayed inode updates during log recovery because it ++ * leads to enospc problems. This means we also can't do ++ * delayed inode refs ++ */ ++ if (BTRFS_I(inode)->root->fs_info->log_root_recovering) ++ return -EAGAIN; ++ + delayed_node = btrfs_get_or_create_delayed_node(inode); + if (IS_ERR(delayed_node)) + return PTR_ERR(delayed_node); +diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c +index a0691df..9521a93 100644 +--- a/fs/btrfs/dir-item.c ++++ b/fs/btrfs/dir-item.c +@@ -21,10 +21,6 @@ + #include "hash.h" + #include "transaction.h" + +-static struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, +- struct btrfs_path *path, +- const char *name, int name_len); +- + /* + * insert a name into a directory, doing overflow properly if there is a hash + * collision. data_size indicates how big the item inserted should be. On +@@ -383,9 +379,9 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, + * this walks through all the entries in a dir item and finds one + * for a specific name. + */ +-static struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, +- struct btrfs_path *path, +- const char *name, int name_len) ++struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, ++ struct btrfs_path *path, ++ const char *name, int name_len) + { + struct btrfs_dir_item *dir_item; + unsigned long name_ptr; +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index 370ef74..f48d5fc 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -1560,6 +1560,7 @@ struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info, + bool check_ref) + { + struct btrfs_root *root; ++ struct btrfs_path *path; + int ret; + + if (location->objectid == BTRFS_ROOT_TREE_OBJECTID) +@@ -1599,8 +1600,14 @@ again: + if (ret) + goto fail; + +- ret = btrfs_find_item(fs_info->tree_root, NULL, BTRFS_ORPHAN_OBJECTID, ++ path = btrfs_alloc_path(); ++ if (!path) { ++ ret = -ENOMEM; ++ goto fail; ++ } ++ ret = btrfs_find_item(fs_info->tree_root, path, BTRFS_ORPHAN_OBJECTID, + location->objectid, BTRFS_ORPHAN_ITEM_KEY, NULL); ++ btrfs_free_path(path); + if (ret < 0) + goto fail; + if (ret == 0) +@@ -2411,7 +2418,7 @@ int open_ctree(struct super_block *sb, + features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO; + + if (features & BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA) +- printk(KERN_ERR "BTRFS: has skinny extents\n"); ++ printk(KERN_INFO "BTRFS: has skinny extents\n"); + + /* + * flag our filesystem as having big metadata blocks if +@@ -3978,12 +3985,6 @@ again: + if (ret) + break; + +- /* opt_discard */ +- if (btrfs_test_opt(root, DISCARD)) +- ret = btrfs_error_discard_extent(root, start, +- end + 1 - start, +- NULL); +- + clear_extent_dirty(unpin, start, end, GFP_NOFS); + btrfs_error_unpin_extent_range(root, start, end); + cond_resched(); +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 3ff98e2..794d7c6 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -5503,7 +5503,8 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans, + update_global_block_rsv(fs_info); + } + +-static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) ++static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end, ++ const bool return_free_space) + { + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_block_group_cache *cache = NULL; +@@ -5527,7 +5528,8 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) + + if (start < cache->last_byte_to_unpin) { + len = min(len, cache->last_byte_to_unpin - start); +- btrfs_add_free_space(cache, start, len); ++ if (return_free_space) ++ btrfs_add_free_space(cache, start, len); + } + + start += len; +@@ -5590,7 +5592,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, + end + 1 - start, NULL); + + clear_extent_dirty(unpin, start, end, GFP_NOFS); +- unpin_extent_range(root, start, end); ++ unpin_extent_range(root, start, end, true); + cond_resched(); + } + +@@ -6643,12 +6645,11 @@ static int __btrfs_free_reserved_extent(struct btrfs_root *root, + return -ENOSPC; + } + +- if (btrfs_test_opt(root, DISCARD)) +- ret = btrfs_discard_extent(root, start, len, NULL); +- + if (pin) + pin_down_extent(root, cache, start, len, 1); + else { ++ if (btrfs_test_opt(root, DISCARD)) ++ ret = btrfs_discard_extent(root, start, len, NULL); + btrfs_add_free_space(cache, start, len); + btrfs_update_reserved_bytes(cache, len, RESERVE_FREE); + } +@@ -8886,7 +8887,7 @@ out: + + int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) + { +- return unpin_extent_range(root, start, end); ++ return unpin_extent_range(root, start, end, false); + } + + int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr, +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 2eea43f..8adfc65 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -2525,6 +2525,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err) + test_bit(BIO_UPTODATE, &bio->bi_flags); + if (err) + uptodate = 0; ++ offset += len; + continue; + } + } +@@ -4288,8 +4289,11 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + } + ret = fiemap_fill_next_extent(fieinfo, em_start, disko, + em_len, flags); +- if (ret) ++ if (ret) { ++ if (ret == 1) ++ ret = 0; + goto out_free; ++ } + } + out_free: + free_extent_map(em); +@@ -4506,7 +4510,8 @@ static void check_buffer_tree_ref(struct extent_buffer *eb) + spin_unlock(&eb->refs_lock); + } + +-static void mark_extent_buffer_accessed(struct extent_buffer *eb) ++static void mark_extent_buffer_accessed(struct extent_buffer *eb, ++ struct page *accessed) + { + unsigned long num_pages, i; + +@@ -4515,7 +4520,8 @@ static void mark_extent_buffer_accessed(struct extent_buffer *eb) + num_pages = num_extent_pages(eb->start, eb->len); + for (i = 0; i < num_pages; i++) { + struct page *p = extent_buffer_page(eb, i); +- mark_page_accessed(p); ++ if (p != accessed) ++ mark_page_accessed(p); + } + } + +@@ -4529,7 +4535,7 @@ struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info, + start >> PAGE_CACHE_SHIFT); + if (eb && atomic_inc_not_zero(&eb->refs)) { + rcu_read_unlock(); +- mark_extent_buffer_accessed(eb); ++ mark_extent_buffer_accessed(eb, NULL); + return eb; + } + rcu_read_unlock(); +@@ -4577,7 +4583,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, + spin_unlock(&mapping->private_lock); + unlock_page(p); + page_cache_release(p); +- mark_extent_buffer_accessed(exists); ++ mark_extent_buffer_accessed(exists, p); + goto free_eb; + } + +@@ -4592,7 +4598,6 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, + attach_extent_buffer_page(eb, p); + spin_unlock(&mapping->private_lock); + WARN_ON(PageDirty(p)); +- mark_page_accessed(p); + eb->pages[i] = p; + if (!PageUptodate(p)) + uptodate = 0; +diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c +index 996ad56b..82845a6 100644 +--- a/fs/btrfs/extent_map.c ++++ b/fs/btrfs/extent_map.c +@@ -290,8 +290,6 @@ int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, + if (!em) + goto out; + +- if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags)) +- list_move(&em->list, &tree->modified_extents); + em->generation = gen; + clear_bit(EXTENT_FLAG_PINNED, &em->flags); + em->mod_start = em->start; +diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c +index 127555b..196b089 100644 +--- a/fs/btrfs/file-item.c ++++ b/fs/btrfs/file-item.c +@@ -423,7 +423,7 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, + ret = 0; + fail: + while (ret < 0 && !list_empty(&tmplist)) { +- sums = list_entry(&tmplist, struct btrfs_ordered_sum, list); ++ sums = list_entry(tmplist.next, struct btrfs_ordered_sum, list); + list_del(&sums->list); + kfree(sums); + } +@@ -756,7 +756,7 @@ again: + found_next = 1; + if (ret != 0) + goto insert; +- slot = 0; ++ slot = path->slots[0]; + } + btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot); + if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || +diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c +index 0165b86..0a841dd 100644 +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -425,13 +425,8 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, + struct page *page = prepared_pages[pg]; + /* + * Copy data from userspace to the current page +- * +- * Disable pagefault to avoid recursive lock since +- * the pages are already locked + */ +- pagefault_disable(); + copied = iov_iter_copy_from_user_atomic(page, i, offset, count); +- pagefault_enable(); + + /* Flush processor's dcache for this page */ + flush_dcache_page(page); +@@ -475,11 +470,12 @@ static void btrfs_drop_pages(struct page **pages, size_t num_pages) + for (i = 0; i < num_pages; i++) { + /* page checked is some magic around finding pages that + * have been modified without going through btrfs_set_page_dirty +- * clear it here ++ * clear it here. There should be no need to mark the pages ++ * accessed as prepare_pages should have marked them accessed ++ * in prepare_pages via find_or_create_page() + */ + ClearPageChecked(pages[i]); + unlock_page(pages[i]); +- mark_page_accessed(pages[i]); + page_cache_release(pages[i]); + } + } +@@ -1778,22 +1774,10 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, + mutex_unlock(&inode->i_mutex); + + /* +- * we want to make sure fsync finds this change +- * but we haven't joined a transaction running right now. +- * +- * Later on, someone is sure to update the inode and get the +- * real transid recorded. +- * +- * We set last_trans now to the fs_info generation + 1, +- * this will either be one more than the running transaction +- * or the generation used for the next transaction if there isn't +- * one running right now. +- * + * We also have to set last_sub_trans to the current log transid, + * otherwise subsequent syncs to a file that's been synced in this + * transaction will appear to have already occured. + */ +- BTRFS_I(inode)->last_trans = root->fs_info->generation + 1; + BTRFS_I(inode)->last_sub_trans = root->log_transid; + if (num_written > 0) { + err = generic_write_sync(file, pos, num_written); +@@ -1896,25 +1880,37 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + atomic_inc(&root->log_batch); + + /* +- * check the transaction that last modified this inode +- * and see if its already been committed +- */ +- if (!BTRFS_I(inode)->last_trans) { +- mutex_unlock(&inode->i_mutex); +- goto out; +- } +- +- /* +- * if the last transaction that changed this file was before +- * the current transaction, we can bail out now without any +- * syncing ++ * If the last transaction that changed this file was before the current ++ * transaction and we have the full sync flag set in our inode, we can ++ * bail out now without any syncing. ++ * ++ * Note that we can't bail out if the full sync flag isn't set. This is ++ * because when the full sync flag is set we start all ordered extents ++ * and wait for them to fully complete - when they complete they update ++ * the inode's last_trans field through: ++ * ++ * btrfs_finish_ordered_io() -> ++ * btrfs_update_inode_fallback() -> ++ * btrfs_update_inode() -> ++ * btrfs_set_inode_last_trans() ++ * ++ * So we are sure that last_trans is up to date and can do this check to ++ * bail out safely. For the fast path, when the full sync flag is not ++ * set in our inode, we can not do it because we start only our ordered ++ * extents and don't wait for them to complete (that is when ++ * btrfs_finish_ordered_io runs), so here at this point their last_trans ++ * value might be less than or equals to fs_info->last_trans_committed, ++ * and setting a speculative last_trans for an inode when a buffered ++ * write is made (such as fs_info->generation + 1 for example) would not ++ * be reliable since after setting the value and before fsync is called ++ * any number of transactions can start and commit (transaction kthread ++ * commits the current transaction periodically), and a transaction ++ * commit does not start nor waits for ordered extents to complete. + */ + smp_mb(); + if (btrfs_inode_in_log(inode, root->fs_info->generation) || +- BTRFS_I(inode)->last_trans <= +- root->fs_info->last_trans_committed) { +- BTRFS_I(inode)->last_trans = 0; +- ++ (full_sync && BTRFS_I(inode)->last_trans <= ++ root->fs_info->last_trans_committed)) { + /* + * We'v had everything committed since the last time we were + * modified so clear this flag in case it was set for whatever +@@ -2510,23 +2506,28 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int whence) + struct btrfs_root *root = BTRFS_I(inode)->root; + struct extent_map *em = NULL; + struct extent_state *cached_state = NULL; +- u64 lockstart = *offset; +- u64 lockend = i_size_read(inode); +- u64 start = *offset; +- u64 len = i_size_read(inode); ++ u64 lockstart; ++ u64 lockend; ++ u64 start; ++ u64 len; + int ret = 0; + +- lockend = max_t(u64, root->sectorsize, lockend); ++ if (inode->i_size == 0) ++ return -ENXIO; ++ ++ /* ++ * *offset can be negative, in this case we start finding DATA/HOLE from ++ * the very start of the file. ++ */ ++ start = max_t(loff_t, 0, *offset); ++ ++ lockstart = round_down(start, root->sectorsize); ++ lockend = round_up(i_size_read(inode), root->sectorsize); + if (lockend <= lockstart) + lockend = lockstart + root->sectorsize; +- + lockend--; + len = lockend - lockstart + 1; + +- len = max_t(u64, len, root->sectorsize); +- if (inode->i_size == 0) +- return -ENXIO; +- + lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend, 0, + &cached_state); + +diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c +index ab485e5..644942a 100644 +--- a/fs/btrfs/inode-map.c ++++ b/fs/btrfs/inode-map.c +@@ -281,7 +281,7 @@ void btrfs_unpin_free_ino(struct btrfs_root *root) + __btrfs_add_free_space(ctl, info->offset, count); + free: + rb_erase(&info->offset_index, rbroot); +- kfree(info); ++ kmem_cache_free(btrfs_free_space_cachep, info); + } + } + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index d3d4448..653cdd8 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -701,6 +701,18 @@ retry: + unlock_extent(io_tree, async_extent->start, + async_extent->start + + async_extent->ram_size - 1); ++ ++ /* ++ * we need to redirty the pages if we decide to ++ * fallback to uncompressed IO, otherwise we ++ * will not submit these pages down to lower ++ * layers. ++ */ ++ extent_range_redirty_for_io(inode, ++ async_extent->start, ++ async_extent->start + ++ async_extent->ram_size - 1); ++ + goto retry; + } + goto out_free; +@@ -3584,7 +3596,8 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, + * without delay + */ + if (!btrfs_is_free_space_inode(inode) +- && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) { ++ && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID ++ && !root->fs_info->log_root_recovering) { + btrfs_update_root_times(trans, root); + + ret = btrfs_delayed_update_inode(trans, root, inode); +@@ -6857,7 +6870,6 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, + ((BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) && + em->block_start != EXTENT_MAP_HOLE)) { + int type; +- int ret; + u64 block_start, orig_start, orig_block_len, ram_bytes; + + if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) +diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c +index a6d8efa..d40ae42 100644 +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -302,6 +302,9 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) + goto out_drop; + + } else { ++ ret = btrfs_set_prop(inode, "btrfs.compression", NULL, 0, 0); ++ if (ret && ret != -ENODATA) ++ goto out_drop; + ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS); + } + +@@ -2705,6 +2708,9 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 len, + if (src == dst) + return -EINVAL; + ++ if (len == 0) ++ return 0; ++ + btrfs_double_lock(src, loff, dst, dst_loff, len); + + ret = extent_same_check_offsets(src, loff, len); +@@ -2737,7 +2743,7 @@ out_unlock: + static long btrfs_ioctl_file_extent_same(struct file *file, + struct btrfs_ioctl_same_args __user *argp) + { +- struct btrfs_ioctl_same_args *same; ++ struct btrfs_ioctl_same_args *same = NULL; + struct btrfs_ioctl_same_extent_info *info; + struct inode *src = file_inode(file); + u64 off; +@@ -2767,6 +2773,7 @@ static long btrfs_ioctl_file_extent_same(struct file *file, + + if (IS_ERR(same)) { + ret = PTR_ERR(same); ++ same = NULL; + goto out; + } + +@@ -2837,6 +2844,7 @@ static long btrfs_ioctl_file_extent_same(struct file *file, + + out: + mnt_drop_write_file(file); ++ kfree(same); + return ret; + } + +@@ -3223,6 +3231,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, + if (off + len == src->i_size) + len = ALIGN(src->i_size, bs) - off; + ++ if (len == 0) { ++ ret = 0; ++ goto out_unlock; ++ } ++ + /* verify the end result is block aligned */ + if (!IS_ALIGNED(off, bs) || !IS_ALIGNED(off + len, bs) || + !IS_ALIGNED(destoff, bs)) +@@ -4750,6 +4763,12 @@ long btrfs_ioctl(struct file *file, unsigned int + if (ret) + return ret; + ret = btrfs_sync_fs(file->f_dentry->d_sb, 1); ++ /* ++ * The transaction thread may want to do more work, ++ * namely it pokes the cleaner ktread that will start ++ * processing uncleaned subvols. ++ */ ++ wake_up_process(root->fs_info->transaction_kthread); + return ret; + } + case BTRFS_IOC_START_SYNC: +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 07b3b36..01f977e 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -736,7 +736,8 @@ again: + err = ret; + goto out; + } +- BUG_ON(!ret || !path1->slots[0]); ++ ASSERT(ret); ++ ASSERT(path1->slots[0]); + + path1->slots[0]--; + +@@ -746,10 +747,10 @@ again: + * the backref was added previously when processing + * backref of type BTRFS_TREE_BLOCK_REF_KEY + */ +- BUG_ON(!list_is_singular(&cur->upper)); ++ ASSERT(list_is_singular(&cur->upper)); + edge = list_entry(cur->upper.next, struct backref_edge, + list[LOWER]); +- BUG_ON(!list_empty(&edge->list[UPPER])); ++ ASSERT(list_empty(&edge->list[UPPER])); + exist = edge->node[UPPER]; + /* + * add the upper level block to pending list if we need +@@ -831,7 +832,7 @@ again: + cur->cowonly = 1; + } + #else +- BUG_ON(key.type == BTRFS_EXTENT_REF_V0_KEY); ++ ASSERT(key.type != BTRFS_EXTENT_REF_V0_KEY); + if (key.type == BTRFS_SHARED_BLOCK_REF_KEY) { + #endif + if (key.objectid == key.offset) { +@@ -840,7 +841,7 @@ again: + * backref of this type. + */ + root = find_reloc_root(rc, cur->bytenr); +- BUG_ON(!root); ++ ASSERT(root); + cur->root = root; + break; + } +@@ -868,7 +869,7 @@ again: + } else { + upper = rb_entry(rb_node, struct backref_node, + rb_node); +- BUG_ON(!upper->checked); ++ ASSERT(upper->checked); + INIT_LIST_HEAD(&edge->list[UPPER]); + } + list_add_tail(&edge->list[LOWER], &cur->upper); +@@ -892,7 +893,7 @@ again: + + if (btrfs_root_level(&root->root_item) == cur->level) { + /* tree root */ +- BUG_ON(btrfs_root_bytenr(&root->root_item) != ++ ASSERT(btrfs_root_bytenr(&root->root_item) == + cur->bytenr); + if (should_ignore_root(root)) + list_add(&cur->list, &useless); +@@ -927,7 +928,7 @@ again: + need_check = true; + for (; level < BTRFS_MAX_LEVEL; level++) { + if (!path2->nodes[level]) { +- BUG_ON(btrfs_root_bytenr(&root->root_item) != ++ ASSERT(btrfs_root_bytenr(&root->root_item) == + lower->bytenr); + if (should_ignore_root(root)) + list_add(&lower->list, &useless); +@@ -976,12 +977,15 @@ again: + need_check = false; + list_add_tail(&edge->list[UPPER], + &list); +- } else ++ } else { ++ if (upper->checked) ++ need_check = true; + INIT_LIST_HEAD(&edge->list[UPPER]); ++ } + } else { + upper = rb_entry(rb_node, struct backref_node, + rb_node); +- BUG_ON(!upper->checked); ++ ASSERT(upper->checked); + INIT_LIST_HEAD(&edge->list[UPPER]); + if (!upper->owner) + upper->owner = btrfs_header_owner(eb); +@@ -1025,7 +1029,7 @@ next: + * everything goes well, connect backref nodes and insert backref nodes + * into the cache. + */ +- BUG_ON(!node->checked); ++ ASSERT(node->checked); + cowonly = node->cowonly; + if (!cowonly) { + rb_node = tree_insert(&cache->rb_root, node->bytenr, +@@ -1061,8 +1065,21 @@ next: + continue; + } + +- BUG_ON(!upper->checked); +- BUG_ON(cowonly != upper->cowonly); ++ if (!upper->checked) { ++ /* ++ * Still want to blow up for developers since this is a ++ * logic bug. ++ */ ++ ASSERT(0); ++ err = -EINVAL; ++ goto out; ++ } ++ if (cowonly != upper->cowonly) { ++ ASSERT(0); ++ err = -EINVAL; ++ goto out; ++ } ++ + if (!cowonly) { + rb_node = tree_insert(&cache->rb_root, upper->bytenr, + &upper->rb_node); +@@ -1085,7 +1102,7 @@ next: + while (!list_empty(&useless)) { + upper = list_entry(useless.next, struct backref_node, list); + list_del_init(&upper->list); +- BUG_ON(!list_empty(&upper->upper)); ++ ASSERT(list_empty(&upper->upper)); + if (upper == node) + node = NULL; + if (upper->lowest) { +@@ -1118,29 +1135,45 @@ out: + if (err) { + while (!list_empty(&useless)) { + lower = list_entry(useless.next, +- struct backref_node, upper); +- list_del_init(&lower->upper); ++ struct backref_node, list); ++ list_del_init(&lower->list); + } +- upper = node; +- INIT_LIST_HEAD(&list); +- while (upper) { +- if (RB_EMPTY_NODE(&upper->rb_node)) { +- list_splice_tail(&upper->upper, &list); +- free_backref_node(cache, upper); +- } +- +- if (list_empty(&list)) +- break; +- +- edge = list_entry(list.next, struct backref_edge, +- list[LOWER]); ++ while (!list_empty(&list)) { ++ edge = list_first_entry(&list, struct backref_edge, ++ list[UPPER]); ++ list_del(&edge->list[UPPER]); + list_del(&edge->list[LOWER]); ++ lower = edge->node[LOWER]; + upper = edge->node[UPPER]; + free_backref_edge(cache, edge); ++ ++ /* ++ * Lower is no longer linked to any upper backref nodes ++ * and isn't in the cache, we can free it ourselves. ++ */ ++ if (list_empty(&lower->upper) && ++ RB_EMPTY_NODE(&lower->rb_node)) ++ list_add(&lower->list, &useless); ++ ++ if (!RB_EMPTY_NODE(&upper->rb_node)) ++ continue; ++ ++ /* Add this guy's upper edges to the list to proces */ ++ list_for_each_entry(edge, &upper->upper, list[LOWER]) ++ list_add_tail(&edge->list[UPPER], &list); ++ if (list_empty(&upper->upper)) ++ list_add(&upper->list, &useless); ++ } ++ ++ while (!list_empty(&useless)) { ++ lower = list_entry(useless.next, ++ struct backref_node, list); ++ list_del_init(&lower->list); ++ free_backref_node(cache, lower); + } + return ERR_PTR(err); + } +- BUG_ON(node && node->detached); ++ ASSERT(!node || !node->detached); + return node; + } + +diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c +index a65ed4c..20d7935 100644 +--- a/fs/btrfs/send.c ++++ b/fs/btrfs/send.c +@@ -4728,7 +4728,9 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end) + + if (S_ISREG(sctx->cur_inode_mode)) { + if (need_send_hole(sctx)) { +- if (sctx->cur_inode_last_extent == (u64)-1) { ++ if (sctx->cur_inode_last_extent == (u64)-1 || ++ sctx->cur_inode_last_extent < ++ sctx->cur_inode_size) { + ret = get_last_extent(sctx, (u64)-1); + if (ret) + goto out; +diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c +index d04db81..92cbfbf 100644 +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -906,6 +906,15 @@ find_root: + if (IS_ERR(new_root)) + return ERR_CAST(new_root); + ++ if (!(sb->s_flags & MS_RDONLY)) { ++ int ret; ++ down_read(&fs_info->cleanup_work_sem); ++ ret = btrfs_orphan_cleanup(new_root); ++ up_read(&fs_info->cleanup_work_sem); ++ if (ret) ++ return ERR_PTR(ret); ++ } ++ + dir_id = btrfs_root_dirid(&new_root->root_item); + setup_root: + location.objectid = dir_id; +diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c +index b05bf58..a0b65a0 100644 +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -592,7 +592,6 @@ int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid) + if (transid <= root->fs_info->last_trans_committed) + goto out; + +- ret = -EINVAL; + /* find specified transaction */ + spin_lock(&root->fs_info->trans_lock); + list_for_each_entry(t, &root->fs_info->trans_list, list) { +@@ -608,9 +607,16 @@ int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid) + } + } + spin_unlock(&root->fs_info->trans_lock); +- /* The specified transaction doesn't exist */ +- if (!cur_trans) ++ ++ /* ++ * The specified transaction doesn't exist, or we ++ * raced with btrfs_commit_transaction ++ */ ++ if (!cur_trans) { ++ if (transid > root->fs_info->last_trans_committed) ++ ret = -EINVAL; + goto out; ++ } + } else { + /* find newest transaction that is committing | committed */ + spin_lock(&root->fs_info->trans_lock); +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index 39d83da..ec8b654 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -979,7 +979,7 @@ again: + base = btrfs_item_ptr_offset(leaf, path->slots[0]); + + while (cur_offset < item_size) { +- extref = (struct btrfs_inode_extref *)base + cur_offset; ++ extref = (struct btrfs_inode_extref *)(base + cur_offset); + + victim_name_len = btrfs_inode_extref_name_len(leaf, extref); + +@@ -1235,13 +1235,14 @@ out: + } + + static int insert_orphan_item(struct btrfs_trans_handle *trans, +- struct btrfs_root *root, u64 offset) ++ struct btrfs_root *root, u64 ino) + { + int ret; +- ret = btrfs_find_item(root, NULL, BTRFS_ORPHAN_OBJECTID, +- offset, BTRFS_ORPHAN_ITEM_KEY, NULL); +- if (ret > 0) +- ret = btrfs_insert_orphan_item(trans, root, offset); ++ ++ ret = btrfs_insert_orphan_item(trans, root, ino); ++ if (ret == -EEXIST) ++ ret = 0; ++ + return ret; + } + +diff --git a/fs/btrfs/ulist.h b/fs/btrfs/ulist.h +index 7f78cbf..4c29db6 100644 +--- a/fs/btrfs/ulist.h ++++ b/fs/btrfs/ulist.h +@@ -57,6 +57,21 @@ void ulist_free(struct ulist *ulist); + int ulist_add(struct ulist *ulist, u64 val, u64 aux, gfp_t gfp_mask); + int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux, + u64 *old_aux, gfp_t gfp_mask); ++ ++/* just like ulist_add_merge() but take a pointer for the aux data */ ++static inline int ulist_add_merge_ptr(struct ulist *ulist, u64 val, void *aux, ++ void **old_aux, gfp_t gfp_mask) ++{ ++#if BITS_PER_LONG == 32 ++ u64 old64 = (uintptr_t)*old_aux; ++ int ret = ulist_add_merge(ulist, val, (uintptr_t)aux, &old64, gfp_mask); ++ *old_aux = (void *)((uintptr_t)old64); ++ return ret; ++#else ++ return ulist_add_merge(ulist, val, (u64)aux, (u64 *)old_aux, gfp_mask); ++#endif ++} ++ + struct ulist_node *ulist_next(struct ulist *ulist, + struct ulist_iterator *uiter); + +diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c +index ad8328d..618e86c 100644 +--- a/fs/btrfs/xattr.c ++++ b/fs/btrfs/xattr.c +@@ -29,6 +29,7 @@ + #include "xattr.h" + #include "disk-io.h" + #include "props.h" ++#include "locking.h" + + + ssize_t __btrfs_getxattr(struct inode *inode, const char *name, +@@ -91,7 +92,7 @@ static int do_setxattr(struct btrfs_trans_handle *trans, + struct inode *inode, const char *name, + const void *value, size_t size, int flags) + { +- struct btrfs_dir_item *di; ++ struct btrfs_dir_item *di = NULL; + struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_path *path; + size_t name_len = strlen(name); +@@ -103,84 +104,119 @@ static int do_setxattr(struct btrfs_trans_handle *trans, + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; ++ path->skip_release_on_error = 1; ++ ++ if (!value) { ++ di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), ++ name, name_len, -1); ++ if (!di && (flags & XATTR_REPLACE)) ++ ret = -ENODATA; ++ else if (di) ++ ret = btrfs_delete_one_dir_name(trans, root, path, di); ++ goto out; ++ } + ++ /* ++ * For a replace we can't just do the insert blindly. ++ * Do a lookup first (read-only btrfs_search_slot), and return if xattr ++ * doesn't exist. If it exists, fall down below to the insert/replace ++ * path - we can't race with a concurrent xattr delete, because the VFS ++ * locks the inode's i_mutex before calling setxattr or removexattr. ++ */ + if (flags & XATTR_REPLACE) { +- di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), name, +- name_len, -1); +- if (IS_ERR(di)) { +- ret = PTR_ERR(di); +- goto out; +- } else if (!di) { ++ ASSERT(mutex_is_locked(&inode->i_mutex)); ++ di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode), ++ name, name_len, 0); ++ if (!di) { + ret = -ENODATA; + goto out; + } +- ret = btrfs_delete_one_dir_name(trans, root, path, di); +- if (ret) +- goto out; + btrfs_release_path(path); ++ di = NULL; ++ } + ++ ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode), ++ name, name_len, value, size); ++ if (ret == -EOVERFLOW) { + /* +- * remove the attribute ++ * We have an existing item in a leaf, split_leaf couldn't ++ * expand it. That item might have or not a dir_item that ++ * matches our target xattr, so lets check. + */ +- if (!value) +- goto out; +- } else { +- di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode), +- name, name_len, 0); +- if (IS_ERR(di)) { +- ret = PTR_ERR(di); ++ ret = 0; ++ btrfs_assert_tree_locked(path->nodes[0]); ++ di = btrfs_match_dir_item_name(root, path, name, name_len); ++ if (!di && !(flags & XATTR_REPLACE)) { ++ ret = -ENOSPC; + goto out; + } +- if (!di && !value) +- goto out; +- btrfs_release_path(path); ++ } else if (ret == -EEXIST) { ++ ret = 0; ++ di = btrfs_match_dir_item_name(root, path, name, name_len); ++ ASSERT(di); /* logic error */ ++ } else if (ret) { ++ goto out; + } + +-again: +- ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode), +- name, name_len, value, size); +- /* +- * If we're setting an xattr to a new value but the new value is say +- * exactly BTRFS_MAX_XATTR_SIZE, we could end up with EOVERFLOW getting +- * back from split_leaf. This is because it thinks we'll be extending +- * the existing item size, but we're asking for enough space to add the +- * item itself. So if we get EOVERFLOW just set ret to EEXIST and let +- * the rest of the function figure it out. +- */ +- if (ret == -EOVERFLOW) ++ if (di && (flags & XATTR_CREATE)) { + ret = -EEXIST; ++ goto out; ++ } + +- if (ret == -EEXIST) { +- if (flags & XATTR_CREATE) +- goto out; ++ if (di) { + /* +- * We can't use the path we already have since we won't have the +- * proper locking for a delete, so release the path and +- * re-lookup to delete the thing. ++ * We're doing a replace, and it must be atomic, that is, at ++ * any point in time we have either the old or the new xattr ++ * value in the tree. We don't want readers (getxattr and ++ * listxattrs) to miss a value, this is specially important ++ * for ACLs. + */ +- btrfs_release_path(path); +- di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), +- name, name_len, -1); +- if (IS_ERR(di)) { +- ret = PTR_ERR(di); +- goto out; +- } else if (!di) { +- /* Shouldn't happen but just in case... */ +- btrfs_release_path(path); +- goto again; ++ const int slot = path->slots[0]; ++ struct extent_buffer *leaf = path->nodes[0]; ++ const u16 old_data_len = btrfs_dir_data_len(leaf, di); ++ const u32 item_size = btrfs_item_size_nr(leaf, slot); ++ const u32 data_size = sizeof(*di) + name_len + size; ++ struct btrfs_item *item; ++ unsigned long data_ptr; ++ char *ptr; ++ ++ if (size > old_data_len) { ++ if (btrfs_leaf_free_space(root, leaf) < ++ (size - old_data_len)) { ++ ret = -ENOSPC; ++ goto out; ++ } + } + +- ret = btrfs_delete_one_dir_name(trans, root, path, di); +- if (ret) +- goto out; ++ if (old_data_len + name_len + sizeof(*di) == item_size) { ++ /* No other xattrs packed in the same leaf item. */ ++ if (size > old_data_len) ++ btrfs_extend_item(root, path, ++ size - old_data_len); ++ else if (size < old_data_len) ++ btrfs_truncate_item(root, path, data_size, 1); ++ } else { ++ /* There are other xattrs packed in the same item. */ ++ ret = btrfs_delete_one_dir_name(trans, root, path, di); ++ if (ret) ++ goto out; ++ btrfs_extend_item(root, path, data_size); ++ } + ++ item = btrfs_item_nr(slot); ++ ptr = btrfs_item_ptr(leaf, slot, char); ++ ptr += btrfs_item_size(leaf, item) - data_size; ++ di = (struct btrfs_dir_item *)ptr; ++ btrfs_set_dir_data_len(leaf, di, size); ++ data_ptr = ((unsigned long)(di + 1)) + name_len; ++ write_extent_buffer(leaf, value, data_ptr, size); ++ btrfs_mark_buffer_dirty(leaf); ++ } else { + /* +- * We have a value to set, so go back and try to insert it now. ++ * Insert, and we had space for the xattr, so path->slots[0] is ++ * where our xattr dir_item is and btrfs_insert_xattr_item() ++ * filled it. + */ +- if (value) { +- btrfs_release_path(path); +- goto again; +- } + } + out: + btrfs_free_path(path); +@@ -324,22 +360,42 @@ const struct xattr_handler *btrfs_xattr_handlers[] = { + /* + * Check if the attribute is in a supported namespace. + * +- * This applied after the check for the synthetic attributes in the system ++ * This is applied after the check for the synthetic attributes in the system + * namespace. + */ +-static bool btrfs_is_valid_xattr(const char *name) ++static int btrfs_is_valid_xattr(const char *name) + { +- return !strncmp(name, XATTR_SECURITY_PREFIX, +- XATTR_SECURITY_PREFIX_LEN) || +- !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) || +- !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) || +- !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) || +- !strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN); ++ int len = strlen(name); ++ int prefixlen = 0; ++ ++ if (!strncmp(name, XATTR_SECURITY_PREFIX, ++ XATTR_SECURITY_PREFIX_LEN)) ++ prefixlen = XATTR_SECURITY_PREFIX_LEN; ++ else if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) ++ prefixlen = XATTR_SYSTEM_PREFIX_LEN; ++ else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) ++ prefixlen = XATTR_TRUSTED_PREFIX_LEN; ++ else if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) ++ prefixlen = XATTR_USER_PREFIX_LEN; ++ else if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN)) ++ prefixlen = XATTR_BTRFS_PREFIX_LEN; ++ else ++ return -EOPNOTSUPP; ++ ++ /* ++ * The name cannot consist of just prefix ++ */ ++ if (len <= prefixlen) ++ return -EINVAL; ++ ++ return 0; + } + + ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, + void *buffer, size_t size) + { ++ int ret; ++ + /* + * If this is a request for a synthetic attribute in the system.* + * namespace use the generic infrastructure to resolve a handler +@@ -348,8 +404,9 @@ ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, + if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) + return generic_getxattr(dentry, name, buffer, size); + +- if (!btrfs_is_valid_xattr(name)) +- return -EOPNOTSUPP; ++ ret = btrfs_is_valid_xattr(name); ++ if (ret) ++ return ret; + return __btrfs_getxattr(dentry->d_inode, name, buffer, size); + } + +@@ -357,6 +414,7 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, + size_t size, int flags) + { + struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root; ++ int ret; + + /* + * The permission on security.* and system.* is not checked +@@ -373,8 +431,9 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, + if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) + return generic_setxattr(dentry, name, value, size, flags); + +- if (!btrfs_is_valid_xattr(name)) +- return -EOPNOTSUPP; ++ ret = btrfs_is_valid_xattr(name); ++ if (ret) ++ return ret; + + if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN)) + return btrfs_set_prop(dentry->d_inode, name, +@@ -390,6 +449,7 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, + int btrfs_removexattr(struct dentry *dentry, const char *name) + { + struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root; ++ int ret; + + /* + * The permission on security.* and system.* is not checked +@@ -406,8 +466,9 @@ int btrfs_removexattr(struct dentry *dentry, const char *name) + if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) + return generic_removexattr(dentry, name); + +- if (!btrfs_is_valid_xattr(name)) +- return -EOPNOTSUPP; ++ ret = btrfs_is_valid_xattr(name); ++ if (ret) ++ return ret; + + if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN)) + return btrfs_set_prop(dentry->d_inode, name, +diff --git a/fs/buffer.c b/fs/buffer.c +index 8c53a2b..f48650c 100644 +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -227,7 +227,7 @@ __find_get_block_slow(struct block_device *bdev, sector_t block) + int all_mapped = 1; + + index = block >> (PAGE_CACHE_SHIFT - bd_inode->i_blkbits); +- page = find_get_page(bd_mapping, index); ++ page = find_get_page_flags(bd_mapping, index, FGP_ACCESSED); + if (!page) + goto out; + +@@ -1029,7 +1029,8 @@ grow_dev_page(struct block_device *bdev, sector_t block, + bh = page_buffers(page); + if (bh->b_size == size) { + end_block = init_page_buffers(page, bdev, +- index << sizebits, size); ++ (sector_t)index << sizebits, ++ size); + goto done; + } + if (!try_to_free_buffers(page)) +@@ -1050,7 +1051,8 @@ grow_dev_page(struct block_device *bdev, sector_t block, + */ + spin_lock(&inode->i_mapping->private_lock); + link_dev_buffers(page, bh); +- end_block = init_page_buffers(page, bdev, index << sizebits, size); ++ end_block = init_page_buffers(page, bdev, (sector_t)index << sizebits, ++ size); + spin_unlock(&inode->i_mapping->private_lock); + done: + ret = (block < end_block) ? 1 : -ENXIO; +@@ -1366,12 +1368,13 @@ __find_get_block(struct block_device *bdev, sector_t block, unsigned size) + struct buffer_head *bh = lookup_bh_lru(bdev, block, size); + + if (bh == NULL) { ++ /* __find_get_block_slow will mark the page accessed */ + bh = __find_get_block_slow(bdev, block); + if (bh) + bh_lru_install(bh); +- } +- if (bh) ++ } else + touch_buffer(bh); ++ + return bh; + } + EXPORT_SYMBOL(__find_get_block); +@@ -1483,16 +1486,27 @@ EXPORT_SYMBOL(set_bh_page); + /* + * Called when truncating a buffer on a page completely. + */ ++ ++/* Bits that are cleared during an invalidate */ ++#define BUFFER_FLAGS_DISCARD \ ++ (1 << BH_Mapped | 1 << BH_New | 1 << BH_Req | \ ++ 1 << BH_Delay | 1 << BH_Unwritten) ++ + static void discard_buffer(struct buffer_head * bh) + { ++ unsigned long b_state, b_state_old; ++ + lock_buffer(bh); + clear_buffer_dirty(bh); + bh->b_bdev = NULL; +- clear_buffer_mapped(bh); +- clear_buffer_req(bh); +- clear_buffer_new(bh); +- clear_buffer_delay(bh); +- clear_buffer_unwritten(bh); ++ b_state = bh->b_state; ++ for (;;) { ++ b_state_old = cmpxchg(&bh->b_state, b_state, ++ (b_state & ~BUFFER_FLAGS_DISCARD)); ++ if (b_state_old == b_state) ++ break; ++ b_state = b_state_old; ++ } + unlock_buffer(bh); + } + +@@ -2075,6 +2089,7 @@ int generic_write_end(struct file *file, struct address_space *mapping, + struct page *page, void *fsdata) + { + struct inode *inode = mapping->host; ++ loff_t old_size = inode->i_size; + int i_size_changed = 0; + + copied = block_write_end(file, mapping, pos, len, copied, page, fsdata); +@@ -2094,6 +2109,8 @@ int generic_write_end(struct file *file, struct address_space *mapping, + unlock_page(page); + page_cache_release(page); + ++ if (old_size < pos) ++ pagecache_isize_extended(inode, old_size, pos); + /* + * Don't mark the inode dirty under page lock. First, it unnecessarily + * makes the holding time of page lock longer. Second, it forces lock +@@ -2311,6 +2328,11 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping, + err = 0; + + balance_dirty_pages_ratelimited(mapping); ++ ++ if (unlikely(fatal_signal_pending(current))) { ++ err = -EINTR; ++ goto out; ++ } + } + + /* page covers the boundary, find the boundary offset */ +diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c +index b53278c..94a85ee 100644 +--- a/fs/ceph/addr.c ++++ b/fs/ceph/addr.c +@@ -676,7 +676,7 @@ static int ceph_writepages_start(struct address_space *mapping, + int rc = 0; + unsigned wsize = 1 << inode->i_blkbits; + struct ceph_osd_request *req = NULL; +- int do_sync; ++ int do_sync = 0; + u64 truncate_size, snap_size; + u32 truncate_seq; + +diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c +index 5e0982a..18e14cf 100644 +--- a/fs/ceph/dir.c ++++ b/fs/ceph/dir.c +@@ -111,7 +111,7 @@ static int fpos_cmp(loff_t l, loff_t r) + /* + * When possible, we try to satisfy a readdir by peeking at the + * dcache. We make this work by carefully ordering dentries on +- * d_u.d_child when we initially get results back from the MDS, and ++ * d_child when we initially get results back from the MDS, and + * falling back to a "normal" sync readdir if any dentries in the dir + * are dropped. + * +@@ -146,11 +146,11 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx) + p = parent->d_subdirs.prev; + dout(" initial p %p/%p\n", p->prev, p->next); + } else { +- p = last->d_u.d_child.prev; ++ p = last->d_child.prev; + } + + more: +- dentry = list_entry(p, struct dentry, d_u.d_child); ++ dentry = list_entry(p, struct dentry, d_child); + di = ceph_dentry(dentry); + while (1) { + dout(" p %p/%p %s d_subdirs %p/%p\n", p->prev, p->next, +@@ -172,7 +172,7 @@ more: + !dentry->d_inode ? " null" : ""); + spin_unlock(&dentry->d_lock); + p = p->prev; +- dentry = list_entry(p, struct dentry, d_u.d_child); ++ dentry = list_entry(p, struct dentry, d_child); + di = ceph_dentry(dentry); + } + +diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c +index 6471f9c..ee24490 100644 +--- a/fs/ceph/inode.c ++++ b/fs/ceph/inode.c +@@ -1289,7 +1289,7 @@ retry_lookup: + /* reorder parent's d_subdirs */ + spin_lock(&parent->d_lock); + spin_lock_nested(&dn->d_lock, DENTRY_D_LOCK_NESTED); +- list_move(&dn->d_u.d_child, &parent->d_subdirs); ++ list_move(&dn->d_child, &parent->d_subdirs); + spin_unlock(&dn->d_lock); + spin_unlock(&parent->d_lock); + } +diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c +index f4f050a..339c412 100644 +--- a/fs/ceph/mds_client.c ++++ b/fs/ceph/mds_client.c +@@ -1461,15 +1461,18 @@ static void discard_cap_releases(struct ceph_mds_client *mdsc, + + dout("discard_cap_releases mds%d\n", session->s_mds); + +- /* zero out the in-progress message */ +- msg = list_first_entry(&session->s_cap_releases, +- struct ceph_msg, list_head); +- head = msg->front.iov_base; +- num = le32_to_cpu(head->num); +- dout("discard_cap_releases mds%d %p %u\n", session->s_mds, msg, num); +- head->num = cpu_to_le32(0); +- msg->front.iov_len = sizeof(*head); +- session->s_num_cap_releases += num; ++ if (!list_empty(&session->s_cap_releases)) { ++ /* zero out the in-progress message */ ++ msg = list_first_entry(&session->s_cap_releases, ++ struct ceph_msg, list_head); ++ head = msg->front.iov_base; ++ num = le32_to_cpu(head->num); ++ dout("discard_cap_releases mds%d %p %u\n", ++ session->s_mds, msg, num); ++ head->num = cpu_to_le32(0); ++ msg->front.iov_len = sizeof(*head); ++ session->s_num_cap_releases += num; ++ } + + /* requeue completed messages */ + while (!list_empty(&session->s_cap_releases_done)) { +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index 30f6e92..5d12d69 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -70,11 +70,6 @@ + #define SERVER_NAME_LENGTH 40 + #define SERVER_NAME_LEN_WITH_NULL (SERVER_NAME_LENGTH + 1) + +-/* used to define string lengths for reversing unicode strings */ +-/* (256+1)*2 = 514 */ +-/* (max path length + 1 for null) * 2 for unicode */ +-#define MAX_NAME 514 +- + /* SMB echo "timeout" -- FIXME: tunable? */ + #define SMB_ECHO_INTERVAL (60 * HZ) + +@@ -404,6 +399,8 @@ struct smb_version_operations { + const struct cifs_fid *, u32 *); + int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *, + int); ++ /* check if we need to issue closedir */ ++ bool (*dir_needs_close)(struct cifsFileInfo *); + }; + + struct smb_version_values { +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index 87c4dd0..40ddb6e 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -366,6 +366,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) + struct cifsLockInfo *li, *tmp; + struct cifs_fid fid; + struct cifs_pending_open open; ++ bool oplock_break_cancelled; + + spin_lock(&cifs_file_list_lock); + if (--cifs_file->count > 0) { +@@ -397,7 +398,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) + } + spin_unlock(&cifs_file_list_lock); + +- cancel_work_sync(&cifs_file->oplock_break); ++ oplock_break_cancelled = cancel_work_sync(&cifs_file->oplock_break); + + if (!tcon->need_reconnect && !cifs_file->invalidHandle) { + struct TCP_Server_Info *server = tcon->ses->server; +@@ -409,6 +410,9 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) + _free_xid(xid); + } + ++ if (oplock_break_cancelled) ++ cifs_done_oplock_break(cifsi); ++ + cifs_del_pending_open(&open); + + /* +@@ -762,7 +766,7 @@ int cifs_closedir(struct inode *inode, struct file *file) + + cifs_dbg(FYI, "Freeing private data in close dir\n"); + spin_lock(&cifs_file_list_lock); +- if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) { ++ if (server->ops->dir_needs_close(cfile)) { + cfile->invalidHandle = true; + spin_unlock(&cifs_file_list_lock); + if (server->ops->close_dir) +@@ -1817,6 +1821,7 @@ refind_writable: + cifsFileInfo_put(inv_file); + spin_lock(&cifs_file_list_lock); + ++refind; ++ inv_file = NULL; + goto refind_writable; + } + } +@@ -2844,7 +2849,7 @@ cifs_uncached_read_into_pages(struct TCP_Server_Info *server, + total_read += result; + } + +- return total_read > 0 ? total_read : result; ++ return total_read > 0 && result != -EAGAIN ? total_read : result; + } + + static ssize_t +@@ -3267,7 +3272,7 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server, + total_read += result; + } + +- return total_read > 0 ? total_read : result; ++ return total_read > 0 && result != -EAGAIN ? total_read : result; + } + + static int cifs_readpages(struct file *file, struct address_space *mapping, +diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c +index aadc2b6..7ee427e 100644 +--- a/fs/cifs/inode.c ++++ b/fs/cifs/inode.c +@@ -883,7 +883,7 @@ inode_has_hashed_dentries(struct inode *inode) + struct dentry *dentry; + + spin_lock(&inode->i_lock); +- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) { + if (!d_unhashed(dentry) || IS_ROOT(dentry)) { + spin_unlock(&inode->i_lock); + return true; +@@ -1706,13 +1706,22 @@ cifs_rename(struct inode *source_dir, struct dentry *source_dentry, + unlink_target: + /* Try unlinking the target dentry if it's not negative */ + if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) { +- tmprc = cifs_unlink(target_dir, target_dentry); ++ if (d_is_dir(target_dentry)) ++ tmprc = cifs_rmdir(target_dir, target_dentry); ++ else ++ tmprc = cifs_unlink(target_dir, target_dentry); + if (tmprc) + goto cifs_rename_exit; + rc = cifs_do_rename(xid, source_dentry, from_name, + target_dentry, to_name); + } + ++ /* force revalidate to go get info when needed */ ++ CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0; ++ ++ source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime = ++ target_dir->i_mtime = current_fs_time(source_dir->i_sb); ++ + cifs_rename_exit: + kfree(info_buf_source); + kfree(from_name); +diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c +index 7749230..dfc9564 100644 +--- a/fs/cifs/ioctl.c ++++ b/fs/cifs/ioctl.c +@@ -86,21 +86,16 @@ static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file, + } + + src_inode = src_file.file->f_dentry->d_inode; ++ rc = -EINVAL; ++ if (S_ISDIR(src_inode->i_mode)) ++ goto out_fput; + + /* + * Note: cifs case is easier than btrfs since server responsible for + * checks for proper open modes and file type and if it wants + * server could even support copy of range where source = target + */ +- +- /* so we do not deadlock racing two ioctls on same files */ +- if (target_inode < src_inode) { +- mutex_lock_nested(&target_inode->i_mutex, I_MUTEX_PARENT); +- mutex_lock_nested(&src_inode->i_mutex, I_MUTEX_CHILD); +- } else { +- mutex_lock_nested(&src_inode->i_mutex, I_MUTEX_PARENT); +- mutex_lock_nested(&target_inode->i_mutex, I_MUTEX_CHILD); +- } ++ lock_two_nondirectories(target_inode, src_inode); + + /* determine range to clone */ + rc = -EINVAL; +@@ -124,13 +119,7 @@ static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file, + out_unlock: + /* although unlocking in the reverse order from locking is not + strictly necessary here it is a little cleaner to be consistent */ +- if (target_inode < src_inode) { +- mutex_unlock(&src_inode->i_mutex); +- mutex_unlock(&target_inode->i_mutex); +- } else { +- mutex_unlock(&target_inode->i_mutex); +- mutex_unlock(&src_inode->i_mutex); +- } ++ unlock_two_nondirectories(src_inode, target_inode); + out_fput: + fdput(src_file); + out_drop_write: +diff --git a/fs/cifs/link.c b/fs/cifs/link.c +index 68559fd..a5c2812 100644 +--- a/fs/cifs/link.c ++++ b/fs/cifs/link.c +@@ -213,8 +213,12 @@ create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, + if (rc) + goto out; + +- rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon, cifs_sb, +- fromName, buf, &bytes_written); ++ if (tcon->ses->server->ops->create_mf_symlink) ++ rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon, ++ cifs_sb, fromName, buf, &bytes_written); ++ else ++ rc = -EOPNOTSUPP; ++ + if (rc) + goto out; + +diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c +index b15862e..b334a89 100644 +--- a/fs/cifs/readdir.c ++++ b/fs/cifs/readdir.c +@@ -593,11 +593,11 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos, + /* close and restart search */ + cifs_dbg(FYI, "search backing up - close and restart search\n"); + spin_lock(&cifs_file_list_lock); +- if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) { ++ if (server->ops->dir_needs_close(cfile)) { + cfile->invalidHandle = true; + spin_unlock(&cifs_file_list_lock); +- if (server->ops->close) +- server->ops->close(xid, tcon, &cfile->fid); ++ if (server->ops->close_dir) ++ server->ops->close_dir(xid, tcon, &cfile->fid); + } else + spin_unlock(&cifs_file_list_lock); + if (cfile->srch_inf.ntwrk_buf_start) { +diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c +index d1fdfa8..e9ad8d3 100644 +--- a/fs/cifs/smb1ops.c ++++ b/fs/cifs/smb1ops.c +@@ -586,7 +586,7 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, + tmprc = CIFS_open(xid, &oparms, &oplock, NULL); + if (tmprc == -EOPNOTSUPP) + *symlink = true; +- else ++ else if (tmprc == 0) + CIFSSMBClose(xid, tcon, fid.netfid); + } + +@@ -1009,6 +1009,12 @@ cifs_is_read_op(__u32 oplock) + return oplock == OPLOCK_READ; + } + ++static bool ++cifs_dir_needs_close(struct cifsFileInfo *cfile) ++{ ++ return !cfile->srch_inf.endOfSearch && !cfile->invalidHandle; ++} ++ + struct smb_version_operations smb1_operations = { + .send_cancel = send_nt_cancel, + .compare_fids = cifs_compare_fids, +@@ -1078,6 +1084,7 @@ struct smb_version_operations smb1_operations = { + .query_mf_symlink = cifs_query_mf_symlink, + .create_mf_symlink = cifs_create_mf_symlink, + .is_read_op = cifs_is_read_op, ++ .dir_needs_close = cifs_dir_needs_close, + #ifdef CONFIG_CIFS_XATTR + .query_all_EAs = CIFSSMBQAllEAs, + .set_EA = CIFSSMBSetEA, +diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c +index 3f17b45..4599294 100644 +--- a/fs/cifs/smb2file.c ++++ b/fs/cifs/smb2file.c +@@ -50,7 +50,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, + goto out; + } + +- smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2, ++ smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, + GFP_KERNEL); + if (smb2_data == NULL) { + rc = -ENOMEM; +diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c +index 84c012a..215f8d3 100644 +--- a/fs/cifs/smb2inode.c ++++ b/fs/cifs/smb2inode.c +@@ -131,7 +131,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, + *adjust_tz = false; + *symlink = false; + +- smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2, ++ smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, + GFP_KERNEL); + if (smb2_data == NULL) + return -ENOMEM; +diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c +index 94bd4fb..a491814 100644 +--- a/fs/cifs/smb2maperror.c ++++ b/fs/cifs/smb2maperror.c +@@ -214,7 +214,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = { + {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"}, + {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"}, + {STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"}, +- {STATUS_NO_MORE_FILES, -EIO, "STATUS_NO_MORE_FILES"}, ++ {STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"}, + {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"}, + {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"}, + {STATUS_NO_INHERITANCE, -EIO, "STATUS_NO_INHERITANCE"}, +@@ -256,6 +256,8 @@ static const struct status_to_posix_error smb2_error_map_table[] = { + {STATUS_DLL_MIGHT_BE_INCOMPATIBLE, -EIO, + "STATUS_DLL_MIGHT_BE_INCOMPATIBLE"}, + {STATUS_STOPPED_ON_SYMLINK, -EOPNOTSUPP, "STATUS_STOPPED_ON_SYMLINK"}, ++ {STATUS_IO_REPARSE_TAG_NOT_HANDLED, -EOPNOTSUPP, ++ "STATUS_REPARSE_NOT_HANDLED"}, + {STATUS_DEVICE_REQUIRES_CLEANING, -EIO, + "STATUS_DEVICE_REQUIRES_CLEANING"}, + {STATUS_DEVICE_DOOR_OPEN, -EIO, "STATUS_DEVICE_DOOR_OPEN"}, +@@ -605,7 +607,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = { + {STATUS_MAPPED_FILE_SIZE_ZERO, -EIO, "STATUS_MAPPED_FILE_SIZE_ZERO"}, + {STATUS_TOO_MANY_OPENED_FILES, -EMFILE, "STATUS_TOO_MANY_OPENED_FILES"}, + {STATUS_CANCELLED, -EIO, "STATUS_CANCELLED"}, +- {STATUS_CANNOT_DELETE, -EIO, "STATUS_CANNOT_DELETE"}, ++ {STATUS_CANNOT_DELETE, -EACCES, "STATUS_CANNOT_DELETE"}, + {STATUS_INVALID_COMPUTER_NAME, -EIO, "STATUS_INVALID_COMPUTER_NAME"}, + {STATUS_FILE_DELETED, -EIO, "STATUS_FILE_DELETED"}, + {STATUS_SPECIAL_ACCOUNT, -EIO, "STATUS_SPECIAL_ACCOUNT"}, +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 35ddc3e..30f3eb5 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -339,7 +339,7 @@ smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon, + int rc; + struct smb2_file_all_info *smb2_data; + +- smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2, ++ smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, + GFP_KERNEL); + if (smb2_data == NULL) + return -ENOMEM; +@@ -630,7 +630,8 @@ smb2_clone_range(const unsigned int xid, + + /* No need to change MaxChunks since already set to 1 */ + chunk_sizes_updated = true; +- } ++ } else ++ goto cchunk_out; + } + + cchunk_out: +@@ -1102,6 +1103,12 @@ smb3_parse_lease_buf(void *buf, unsigned int *epoch) + return le32_to_cpu(lc->lcontext.LeaseState); + } + ++static bool ++smb2_dir_needs_close(struct cifsFileInfo *cfile) ++{ ++ return !cfile->invalidHandle; ++} ++ + struct smb_version_operations smb20_operations = { + .compare_fids = smb2_compare_fids, + .setup_request = smb2_setup_request, +@@ -1175,6 +1182,7 @@ struct smb_version_operations smb20_operations = { + .create_lease_buf = smb2_create_lease_buf, + .parse_lease_buf = smb2_parse_lease_buf, + .clone_range = smb2_clone_range, ++ .dir_needs_close = smb2_dir_needs_close, + }; + + struct smb_version_operations smb21_operations = { +@@ -1250,6 +1258,7 @@ struct smb_version_operations smb21_operations = { + .create_lease_buf = smb2_create_lease_buf, + .parse_lease_buf = smb2_parse_lease_buf, + .clone_range = smb2_clone_range, ++ .dir_needs_close = smb2_dir_needs_close, + }; + + struct smb_version_operations smb30_operations = { +@@ -1328,6 +1337,7 @@ struct smb_version_operations smb30_operations = { + .parse_lease_buf = smb3_parse_lease_buf, + .clone_range = smb2_clone_range, + .validate_negotiate = smb3_validate_negotiate, ++ .dir_needs_close = smb2_dir_needs_close, + }; + + struct smb_version_values smb20_values = { +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 049a3f2..3487929 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -916,7 +916,8 @@ tcon_exit: + tcon_error_exit: + if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) { + cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); +- tcon->bad_network_name = true; ++ if (tcon) ++ tcon->bad_network_name = true; + } + goto tcon_exit; + } +@@ -1539,7 +1540,7 @@ SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, + { + return query_info(xid, tcon, persistent_fid, volatile_fid, + FILE_ALL_INFORMATION, +- sizeof(struct smb2_file_all_info) + MAX_NAME * 2, ++ sizeof(struct smb2_file_all_info) + PATH_MAX * 2, + sizeof(struct smb2_file_all_info), data); + } + +@@ -2135,6 +2136,10 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + rsp = (struct smb2_query_directory_rsp *)iov[0].iov_base; + + if (rc) { ++ if (rc == -ENODATA && rsp->hdr.Status == STATUS_NO_MORE_FILES) { ++ srch_inf->endOfSearch = true; ++ rc = 0; ++ } + cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE); + goto qdir_exit; + } +@@ -2172,11 +2177,6 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, + else + cifs_dbg(VFS, "illegal search buffer type\n"); + +- if (rsp->hdr.Status == STATUS_NO_MORE_FILES) +- srch_inf->endOfSearch = 1; +- else +- srch_inf->endOfSearch = 0; +- + return rc; + + qdir_exit: +diff --git a/fs/coda/cache.c b/fs/coda/cache.c +index 1da168c..9bc1147 100644 +--- a/fs/coda/cache.c ++++ b/fs/coda/cache.c +@@ -92,7 +92,7 @@ static void coda_flag_children(struct dentry *parent, int flag) + struct dentry *de; + + spin_lock(&parent->d_lock); +- list_for_each_entry(de, &parent->d_subdirs, d_u.d_child) { ++ list_for_each_entry(de, &parent->d_subdirs, d_child) { + /* don't know what to do with negative dentries */ + if (de->d_inode ) + coda_flag_inode(de->d_inode, flag); +diff --git a/fs/coredump.c b/fs/coredump.c +index 0b2528f..a93f7e6 100644 +--- a/fs/coredump.c ++++ b/fs/coredump.c +@@ -306,7 +306,7 @@ static int zap_threads(struct task_struct *tsk, struct mm_struct *mm, + if (unlikely(nr < 0)) + return nr; + +- tsk->flags = PF_DUMPCORE; ++ tsk->flags |= PF_DUMPCORE; + if (atomic_read(&mm->mm_users) == nr + 1) + goto done; + /* +diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c +index 06610cf..a1f801c 100644 +--- a/fs/cramfs/inode.c ++++ b/fs/cramfs/inode.c +@@ -195,8 +195,7 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i + struct page *page = NULL; + + if (blocknr + i < devsize) { +- page = read_mapping_page_async(mapping, blocknr + i, +- NULL); ++ page = read_mapping_page(mapping, blocknr + i, NULL); + /* synchronous error? */ + if (IS_ERR(page)) + page = NULL; +diff --git a/fs/dcache.c b/fs/dcache.c +index 7f3b400..df323f8 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -44,7 +44,7 @@ + /* + * Usage: + * dcache->d_inode->i_lock protects: +- * - i_dentry, d_alias, d_inode of aliases ++ * - i_dentry, d_u.d_alias, d_inode of aliases + * dcache_hash_bucket lock protects: + * - the dcache hash table + * s_anon bl list spinlock protects: +@@ -59,7 +59,7 @@ + * - d_unhashed() + * - d_parent and d_subdirs + * - childrens' d_child and d_parent +- * - d_alias, d_inode ++ * - d_u.d_alias, d_inode + * + * Ordering: + * dentry->d_inode->i_lock +@@ -106,8 +106,7 @@ static inline struct hlist_bl_head *d_hash(const struct dentry *parent, + unsigned int hash) + { + hash += (unsigned long) parent / L1_CACHE_BYTES; +- hash = hash + (hash >> d_hash_shift); +- return dentry_hashtable + (hash & d_hash_mask); ++ return dentry_hashtable + hash_32(hash, d_hash_shift); + } + + /* Statistics gathering. */ +@@ -240,22 +239,13 @@ static void __d_free(struct rcu_head *head) + { + struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu); + +- WARN_ON(!hlist_unhashed(&dentry->d_alias)); + if (dname_external(dentry)) + kfree(dentry->d_name.name); + kmem_cache_free(dentry_cache, dentry); + } + +-/* +- * no locks, please. +- */ +-static void d_free(struct dentry *dentry) ++static void dentry_free(struct dentry *dentry) + { +- BUG_ON((int)dentry->d_lockref.count > 0); +- this_cpu_dec(nr_dentry); +- if (dentry->d_op && dentry->d_op->d_release) +- dentry->d_op->d_release(dentry); +- + /* if dentry was never visible to RCU, immediate free is OK */ + if (!(dentry->d_flags & DCACHE_RCUACCESS)) + __d_free(&dentry->d_u.d_rcu); +@@ -289,7 +279,7 @@ static void dentry_iput(struct dentry * dentry) + struct inode *inode = dentry->d_inode; + if (inode) { + dentry->d_inode = NULL; +- hlist_del_init(&dentry->d_alias); ++ hlist_del_init(&dentry->d_u.d_alias); + spin_unlock(&dentry->d_lock); + spin_unlock(&inode->i_lock); + if (!inode->i_nlink) +@@ -314,7 +304,7 @@ static void dentry_unlink_inode(struct dentry * dentry) + struct inode *inode = dentry->d_inode; + __d_clear_type(dentry); + dentry->d_inode = NULL; +- hlist_del_init(&dentry->d_alias); ++ hlist_del_init(&dentry->d_u.d_alias); + dentry_rcuwalk_barrier(dentry); + spin_unlock(&dentry->d_lock); + spin_unlock(&inode->i_lock); +@@ -403,56 +393,6 @@ static void dentry_lru_add(struct dentry *dentry) + d_lru_add(dentry); + } + +-/* +- * Remove a dentry with references from the LRU. +- * +- * If we are on the shrink list, then we can get to try_prune_one_dentry() and +- * lose our last reference through the parent walk. In this case, we need to +- * remove ourselves from the shrink list, not the LRU. +- */ +-static void dentry_lru_del(struct dentry *dentry) +-{ +- if (dentry->d_flags & DCACHE_LRU_LIST) { +- if (dentry->d_flags & DCACHE_SHRINK_LIST) +- return d_shrink_del(dentry); +- d_lru_del(dentry); +- } +-} +- +-/** +- * d_kill - kill dentry and return parent +- * @dentry: dentry to kill +- * @parent: parent dentry +- * +- * The dentry must already be unhashed and removed from the LRU. +- * +- * If this is the root of the dentry tree, return NULL. +- * +- * dentry->d_lock and parent->d_lock must be held by caller, and are dropped by +- * d_kill. +- */ +-static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) +- __releases(dentry->d_lock) +- __releases(parent->d_lock) +- __releases(dentry->d_inode->i_lock) +-{ +- list_del(&dentry->d_u.d_child); +- /* +- * Inform d_walk() that we are no longer attached to the +- * dentry tree +- */ +- dentry->d_flags |= DCACHE_DENTRY_KILLED; +- if (parent) +- spin_unlock(&parent->d_lock); +- dentry_iput(dentry); +- /* +- * dentry_iput drops the locks, at which point nobody (except +- * transient RCU lookups) can reach this dentry. +- */ +- d_free(dentry); +- return parent; +-} +- + /** + * d_drop - drop a dentry + * @dentry: dentry to drop +@@ -510,7 +450,14 @@ dentry_kill(struct dentry *dentry, int unlock_on_failure) + __releases(dentry->d_lock) + { + struct inode *inode; +- struct dentry *parent; ++ struct dentry *parent = NULL; ++ bool can_free = true; ++ ++ if (unlikely(dentry->d_flags & DCACHE_DENTRY_KILLED)) { ++ can_free = dentry->d_flags & DCACHE_MAY_FREE; ++ spin_unlock(&dentry->d_lock); ++ goto out; ++ } + + inode = dentry->d_inode; + if (inode && !spin_trylock(&inode->i_lock)) { +@@ -521,9 +468,7 @@ relock: + } + return dentry; /* try again with same dentry */ + } +- if (IS_ROOT(dentry)) +- parent = NULL; +- else ++ if (!IS_ROOT(dentry)) + parent = dentry->d_parent; + if (parent && !spin_trylock(&parent->d_lock)) { + if (inode) +@@ -543,10 +488,40 @@ relock: + if ((dentry->d_flags & DCACHE_OP_PRUNE) && !d_unhashed(dentry)) + dentry->d_op->d_prune(dentry); + +- dentry_lru_del(dentry); ++ if (dentry->d_flags & DCACHE_LRU_LIST) { ++ if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) ++ d_lru_del(dentry); ++ } + /* if it was on the hash then remove it */ + __d_drop(dentry); +- return d_kill(dentry, parent); ++ __list_del_entry(&dentry->d_child); ++ /* ++ * Inform d_walk() that we are no longer attached to the ++ * dentry tree ++ */ ++ dentry->d_flags |= DCACHE_DENTRY_KILLED; ++ if (parent) ++ spin_unlock(&parent->d_lock); ++ dentry_iput(dentry); ++ /* ++ * dentry_iput drops the locks, at which point nobody (except ++ * transient RCU lookups) can reach this dentry. ++ */ ++ BUG_ON((int)dentry->d_lockref.count > 0); ++ this_cpu_dec(nr_dentry); ++ if (dentry->d_op && dentry->d_op->d_release) ++ dentry->d_op->d_release(dentry); ++ ++ spin_lock(&dentry->d_lock); ++ if (dentry->d_flags & DCACHE_SHRINK_LIST) { ++ dentry->d_flags |= DCACHE_MAY_FREE; ++ can_free = false; ++ } ++ spin_unlock(&dentry->d_lock); ++out: ++ if (likely(can_free)) ++ dentry_free(dentry); ++ return parent; + } + + /* +@@ -588,6 +563,9 @@ repeat: + if (unlikely(d_unhashed(dentry))) + goto kill_it; + ++ if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) ++ goto kill_it; ++ + if (unlikely(dentry->d_flags & DCACHE_OP_DELETE)) { + if (dentry->d_op->d_delete(dentry)) + goto kill_it; +@@ -738,7 +716,7 @@ static struct dentry *__d_find_alias(struct inode *inode, int want_discon) + + again: + discon_alias = NULL; +- hlist_for_each_entry(alias, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) { + spin_lock(&alias->d_lock); + if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) { + if (IS_ROOT(alias) && +@@ -791,7 +769,7 @@ void d_prune_aliases(struct inode *inode) + struct dentry *dentry; + restart: + spin_lock(&inode->i_lock); +- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) { + spin_lock(&dentry->d_lock); + if (!dentry->d_lockref.count) { + /* +@@ -815,65 +793,13 @@ restart: + } + EXPORT_SYMBOL(d_prune_aliases); + +-/* +- * Try to throw away a dentry - free the inode, dput the parent. +- * Requires dentry->d_lock is held, and dentry->d_count == 0. +- * Releases dentry->d_lock. +- * +- * This may fail if locks cannot be acquired no problem, just try again. +- */ +-static struct dentry * try_prune_one_dentry(struct dentry *dentry) +- __releases(dentry->d_lock) +-{ +- struct dentry *parent; +- +- parent = dentry_kill(dentry, 0); +- /* +- * If dentry_kill returns NULL, we have nothing more to do. +- * if it returns the same dentry, trylocks failed. In either +- * case, just loop again. +- * +- * Otherwise, we need to prune ancestors too. This is necessary +- * to prevent quadratic behavior of shrink_dcache_parent(), but +- * is also expected to be beneficial in reducing dentry cache +- * fragmentation. +- */ +- if (!parent) +- return NULL; +- if (parent == dentry) +- return dentry; +- +- /* Prune ancestors. */ +- dentry = parent; +- while (dentry) { +- if (lockref_put_or_lock(&dentry->d_lockref)) +- return NULL; +- dentry = dentry_kill(dentry, 1); +- } +- return NULL; +-} +- + static void shrink_dentry_list(struct list_head *list) + { +- struct dentry *dentry; ++ struct dentry *dentry, *parent; + +- rcu_read_lock(); +- for (;;) { +- dentry = list_entry_rcu(list->prev, struct dentry, d_lru); +- if (&dentry->d_lru == list) +- break; /* empty */ +- +- /* +- * Get the dentry lock, and re-verify that the dentry is +- * this on the shrinking list. If it is, we know that +- * DCACHE_SHRINK_LIST and DCACHE_LRU_LIST are set. +- */ ++ while (!list_empty(list)) { ++ dentry = list_entry(list->prev, struct dentry, d_lru); + spin_lock(&dentry->d_lock); +- if (dentry != list_entry(list->prev, struct dentry, d_lru)) { +- spin_unlock(&dentry->d_lock); +- continue; +- } +- + /* + * The dispose list is isolated and dentries are not accounted + * to the LRU here, so we can simply remove it from the list +@@ -885,30 +811,38 @@ static void shrink_dentry_list(struct list_head *list) + * We found an inuse dentry which was not removed from + * the LRU because of laziness during lookup. Do not free it. + */ +- if (dentry->d_lockref.count) { ++ if ((int)dentry->d_lockref.count > 0) { + spin_unlock(&dentry->d_lock); + continue; + } +- rcu_read_unlock(); + ++ parent = dentry_kill(dentry, 0); + /* +- * If 'try_to_prune()' returns a dentry, it will +- * be the same one we passed in, and d_lock will +- * have been held the whole time, so it will not +- * have been added to any other lists. We failed +- * to get the inode lock. +- * +- * We just add it back to the shrink list. ++ * If dentry_kill returns NULL, we have nothing more to do. + */ +- dentry = try_prune_one_dentry(dentry); ++ if (!parent) ++ continue; + +- rcu_read_lock(); +- if (dentry) { ++ if (unlikely(parent == dentry)) { ++ /* ++ * trylocks have failed and d_lock has been held the ++ * whole time, so it could not have been added to any ++ * other lists. Just add it back to the shrink list. ++ */ + d_shrink_add(dentry, list); + spin_unlock(&dentry->d_lock); ++ continue; + } ++ /* ++ * We need to prune ancestors too. This is necessary to prevent ++ * quadratic behavior of shrink_dcache_parent(), but is also ++ * expected to be beneficial in reducing dentry cache ++ * fragmentation. ++ */ ++ dentry = parent; ++ while (dentry && !lockref_put_or_lock(&dentry->d_lockref)) ++ dentry = dentry_kill(dentry, 1); + } +- rcu_read_unlock(); + } + + static enum lru_status +@@ -1092,7 +1026,7 @@ repeat: + resume: + while (next != &this_parent->d_subdirs) { + struct list_head *tmp = next; +- struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child); ++ struct dentry *dentry = list_entry(tmp, struct dentry, d_child); + next = tmp->next; + + spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); +@@ -1124,33 +1058,31 @@ resume: + /* + * All done at this level ... ascend and resume the search. + */ ++ rcu_read_lock(); ++ascend: + if (this_parent != parent) { + struct dentry *child = this_parent; + this_parent = child->d_parent; + +- rcu_read_lock(); + spin_unlock(&child->d_lock); + spin_lock(&this_parent->d_lock); + +- /* +- * might go back up the wrong parent if we have had a rename +- * or deletion +- */ +- if (this_parent != child->d_parent || +- (child->d_flags & DCACHE_DENTRY_KILLED) || +- need_seqretry(&rename_lock, seq)) { +- spin_unlock(&this_parent->d_lock); +- rcu_read_unlock(); ++ /* might go back up the wrong parent if we have had a rename. */ ++ if (need_seqretry(&rename_lock, seq)) + goto rename_retry; +- } ++ /* go into the first sibling still alive */ ++ do { ++ next = child->d_child.next; ++ if (next == &this_parent->d_subdirs) ++ goto ascend; ++ child = list_entry(next, struct dentry, d_child); ++ } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)); + rcu_read_unlock(); +- next = child->d_u.d_child.next; + goto resume; + } +- if (need_seqretry(&rename_lock, seq)) { +- spin_unlock(&this_parent->d_lock); ++ if (need_seqretry(&rename_lock, seq)) + goto rename_retry; +- } ++ rcu_read_unlock(); + if (finish) + finish(data); + +@@ -1160,6 +1092,9 @@ out_unlock: + return; + + rename_retry: ++ spin_unlock(&this_parent->d_lock); ++ rcu_read_unlock(); ++ BUG_ON(seq & 1); + if (!retry) + return; + seq = 1; +@@ -1261,34 +1196,23 @@ static enum d_walk_ret select_collect(void *_data, struct dentry *dentry) + if (data->start == dentry) + goto out; + +- /* +- * move only zero ref count dentries to the dispose list. +- * +- * Those which are presently on the shrink list, being processed +- * by shrink_dentry_list(), shouldn't be moved. Otherwise the +- * loop in shrink_dcache_parent() might not make any progress +- * and loop forever. +- */ +- if (dentry->d_lockref.count) { +- dentry_lru_del(dentry); +- } else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) { +- /* +- * We can't use d_lru_shrink_move() because we +- * need to get the global LRU lock and do the +- * LRU accounting. +- */ +- d_lru_del(dentry); +- d_shrink_add(dentry, &data->dispose); ++ if (dentry->d_flags & DCACHE_SHRINK_LIST) { + data->found++; +- ret = D_WALK_NORETRY; ++ } else { ++ if (dentry->d_flags & DCACHE_LRU_LIST) ++ d_lru_del(dentry); ++ if (!dentry->d_lockref.count) { ++ d_shrink_add(dentry, &data->dispose); ++ data->found++; ++ } + } + /* + * We can return to the caller if we have found some (this + * ensures forward progress). We'll be coming back to find + * the rest. + */ +- if (data->found && need_resched()) +- ret = D_WALK_QUIT; ++ if (!list_empty(&data->dispose)) ++ ret = need_resched() ? D_WALK_QUIT : D_WALK_NORETRY; + out: + return ret; + } +@@ -1318,45 +1242,35 @@ void shrink_dcache_parent(struct dentry *parent) + } + EXPORT_SYMBOL(shrink_dcache_parent); + +-static enum d_walk_ret umount_collect(void *_data, struct dentry *dentry) ++static enum d_walk_ret umount_check(void *_data, struct dentry *dentry) + { +- struct select_data *data = _data; +- enum d_walk_ret ret = D_WALK_CONTINUE; ++ /* it has busy descendents; complain about those instead */ ++ if (!list_empty(&dentry->d_subdirs)) ++ return D_WALK_CONTINUE; + +- if (dentry->d_lockref.count) { +- dentry_lru_del(dentry); +- if (likely(!list_empty(&dentry->d_subdirs))) +- goto out; +- if (dentry == data->start && dentry->d_lockref.count == 1) +- goto out; +- printk(KERN_ERR +- "BUG: Dentry %p{i=%lx,n=%s}" +- " still in use (%d)" +- " [unmount of %s %s]\n", ++ /* root with refcount 1 is fine */ ++ if (dentry == _data && dentry->d_lockref.count == 1) ++ return D_WALK_CONTINUE; ++ ++ printk(KERN_ERR "BUG: Dentry %p{i=%lx,n=%pd} " ++ " still in use (%d) [unmount of %s %s]\n", + dentry, + dentry->d_inode ? + dentry->d_inode->i_ino : 0UL, +- dentry->d_name.name, ++ dentry, + dentry->d_lockref.count, + dentry->d_sb->s_type->name, + dentry->d_sb->s_id); +- BUG(); +- } else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) { +- /* +- * We can't use d_lru_shrink_move() because we +- * need to get the global LRU lock and do the +- * LRU accounting. +- */ +- if (dentry->d_flags & DCACHE_LRU_LIST) +- d_lru_del(dentry); +- d_shrink_add(dentry, &data->dispose); +- data->found++; +- ret = D_WALK_NORETRY; +- } +-out: +- if (data->found && need_resched()) +- ret = D_WALK_QUIT; +- return ret; ++ WARN_ON(1); ++ return D_WALK_CONTINUE; ++} ++ ++static void do_one_tree(struct dentry *dentry) ++{ ++ shrink_dcache_parent(dentry); ++ d_walk(dentry, dentry, umount_check, NULL); ++ d_drop(dentry); ++ dput(dentry); + } + + /* +@@ -1366,40 +1280,15 @@ void shrink_dcache_for_umount(struct super_block *sb) + { + struct dentry *dentry; + +- if (down_read_trylock(&sb->s_umount)) +- BUG(); ++ WARN(down_read_trylock(&sb->s_umount), "s_umount should've been locked"); + + dentry = sb->s_root; + sb->s_root = NULL; +- for (;;) { +- struct select_data data; +- +- INIT_LIST_HEAD(&data.dispose); +- data.start = dentry; +- data.found = 0; +- +- d_walk(dentry, &data, umount_collect, NULL); +- if (!data.found) +- break; +- +- shrink_dentry_list(&data.dispose); +- cond_resched(); +- } +- d_drop(dentry); +- dput(dentry); ++ do_one_tree(dentry); + + while (!hlist_bl_empty(&sb->s_anon)) { +- struct select_data data; +- dentry = hlist_bl_entry(hlist_bl_first(&sb->s_anon), struct dentry, d_hash); +- +- INIT_LIST_HEAD(&data.dispose); +- data.start = NULL; +- data.found = 0; +- +- d_walk(dentry, &data, umount_collect, NULL); +- if (data.found) +- shrink_dentry_list(&data.dispose); +- cond_resched(); ++ dentry = dget(hlist_bl_entry(hlist_bl_first(&sb->s_anon), struct dentry, d_hash)); ++ do_one_tree(dentry); + } + } + +@@ -1525,8 +1414,8 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name) + INIT_HLIST_BL_NODE(&dentry->d_hash); + INIT_LIST_HEAD(&dentry->d_lru); + INIT_LIST_HEAD(&dentry->d_subdirs); +- INIT_HLIST_NODE(&dentry->d_alias); +- INIT_LIST_HEAD(&dentry->d_u.d_child); ++ INIT_HLIST_NODE(&dentry->d_u.d_alias); ++ INIT_LIST_HEAD(&dentry->d_child); + d_set_d_op(dentry, dentry->d_sb->s_d_op); + + this_cpu_inc(nr_dentry); +@@ -1556,7 +1445,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) + */ + __dget_dlock(parent); + dentry->d_parent = parent; +- list_add(&dentry->d_u.d_child, &parent->d_subdirs); ++ list_add(&dentry->d_child, &parent->d_subdirs); + spin_unlock(&parent->d_lock); + + return dentry; +@@ -1649,7 +1538,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode) + spin_lock(&dentry->d_lock); + __d_set_type(dentry, add_flags); + if (inode) +- hlist_add_head(&dentry->d_alias, &inode->i_dentry); ++ hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry); + dentry->d_inode = inode; + dentry_rcuwalk_barrier(dentry); + spin_unlock(&dentry->d_lock); +@@ -1673,7 +1562,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode) + + void d_instantiate(struct dentry *entry, struct inode * inode) + { +- BUG_ON(!hlist_unhashed(&entry->d_alias)); ++ BUG_ON(!hlist_unhashed(&entry->d_u.d_alias)); + if (inode) + spin_lock(&inode->i_lock); + __d_instantiate(entry, inode); +@@ -1712,7 +1601,7 @@ static struct dentry *__d_instantiate_unique(struct dentry *entry, + return NULL; + } + +- hlist_for_each_entry(alias, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) { + /* + * Don't need alias->d_lock here, because aliases with + * d_parent == entry->d_parent are not subject to name or +@@ -1738,7 +1627,7 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode) + { + struct dentry *result; + +- BUG_ON(!hlist_unhashed(&entry->d_alias)); ++ BUG_ON(!hlist_unhashed(&entry->d_u.d_alias)); + + if (inode) + spin_lock(&inode->i_lock); +@@ -1769,7 +1658,7 @@ EXPORT_SYMBOL(d_instantiate_unique); + */ + int d_instantiate_no_diralias(struct dentry *entry, struct inode *inode) + { +- BUG_ON(!hlist_unhashed(&entry->d_alias)); ++ BUG_ON(!hlist_unhashed(&entry->d_u.d_alias)); + + spin_lock(&inode->i_lock); + if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry)) { +@@ -1808,7 +1697,7 @@ static struct dentry * __d_find_any_alias(struct inode *inode) + + if (hlist_empty(&inode->i_dentry)) + return NULL; +- alias = hlist_entry(inode->i_dentry.first, struct dentry, d_alias); ++ alias = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias); + __dget(alias); + return alias; + } +@@ -1885,7 +1774,7 @@ struct dentry *d_obtain_alias(struct inode *inode) + spin_lock(&tmp->d_lock); + tmp->d_inode = inode; + tmp->d_flags |= add_flags; +- hlist_add_head(&tmp->d_alias, &inode->i_dentry); ++ hlist_add_head(&tmp->d_u.d_alias, &inode->i_dentry); + hlist_bl_lock(&tmp->d_sb->s_anon); + hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); + hlist_bl_unlock(&tmp->d_sb->s_anon); +@@ -2328,7 +2217,7 @@ int d_validate(struct dentry *dentry, struct dentry *dparent) + struct dentry *child; + + spin_lock(&dparent->d_lock); +- list_for_each_entry(child, &dparent->d_subdirs, d_u.d_child) { ++ list_for_each_entry(child, &dparent->d_subdirs, d_child) { + if (dentry == child) { + spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); + __dget_dlock(dentry); +@@ -2575,8 +2464,8 @@ static void __d_move(struct dentry * dentry, struct dentry * target) + /* Unhash the target: dput() will then get rid of it */ + __d_drop(target); + +- list_del(&dentry->d_u.d_child); +- list_del(&target->d_u.d_child); ++ list_del(&dentry->d_child); ++ list_del(&target->d_child); + + /* Switch the names.. */ + switch_names(dentry, target); +@@ -2586,15 +2475,15 @@ static void __d_move(struct dentry * dentry, struct dentry * target) + if (IS_ROOT(dentry)) { + dentry->d_parent = target->d_parent; + target->d_parent = target; +- INIT_LIST_HEAD(&target->d_u.d_child); ++ INIT_LIST_HEAD(&target->d_child); + } else { + swap(dentry->d_parent, target->d_parent); + + /* And add them back to the (new) parent lists */ +- list_add(&target->d_u.d_child, &target->d_parent->d_subdirs); ++ list_add(&target->d_child, &target->d_parent->d_subdirs); + } + +- list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs); ++ list_add(&dentry->d_child, &dentry->d_parent->d_subdirs); + + write_seqcount_end(&target->d_seq); + write_seqcount_end(&dentry->d_seq); +@@ -2701,9 +2590,9 @@ static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon) + swap(dentry->d_name.hash, anon->d_name.hash); + + dentry->d_parent = dentry; +- list_del_init(&dentry->d_u.d_child); ++ list_del_init(&dentry->d_child); + anon->d_parent = dparent; +- list_move(&anon->d_u.d_child, &dparent->d_subdirs); ++ list_move(&anon->d_child, &dparent->d_subdirs); + + write_seqcount_end(&dentry->d_seq); + write_seqcount_end(&anon->d_seq); +@@ -2825,6 +2714,9 @@ static int prepend(char **buffer, int *buflen, const char *str, int namelen) + * the beginning of the name. The sequence number check at the caller will + * retry it again when a d_move() does happen. So any garbage in the buffer + * due to mismatched pointer and length will be discarded. ++ * ++ * Data dependency barrier is needed to make sure that we see that terminating ++ * NUL. Alpha strikes again, film at 11... + */ + static int prepend_name(char **buffer, int *buflen, struct qstr *name) + { +@@ -2832,6 +2724,8 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name) + u32 dlen = ACCESS_ONCE(name->len); + char *p; + ++ smp_read_barrier_depends(); ++ + *buflen -= dlen + 1; + if (*buflen < 0) + return -ENAMETOOLONG; +@@ -2900,17 +2794,6 @@ restart: + vfsmnt = &mnt->mnt; + continue; + } +- /* +- * Filesystems needing to implement special "root names" +- * should do so with ->d_dname() +- */ +- if (IS_ROOT(dentry) && +- (dentry->d_name.len != 1 || +- dentry->d_name.name[0] != '/')) { +- WARN(1, "Root dentry has weird name <%.*s>\n", +- (int) dentry->d_name.len, +- dentry->d_name.name); +- } + if (!error) + error = is_mounted(vfsmnt) ? 1 : 2; + break; +@@ -3329,7 +3212,7 @@ void d_tmpfile(struct dentry *dentry, struct inode *inode) + { + inode_dec_link_count(inode); + BUG_ON(dentry->d_name.name != dentry->d_iname || +- !hlist_unhashed(&dentry->d_alias) || ++ !hlist_unhashed(&dentry->d_u.d_alias) || + !d_unlinked(dentry)); + spin_lock(&dentry->d_parent->d_lock); + spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); +diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c +index ca4a08f..ece3842 100644 +--- a/fs/debugfs/inode.c ++++ b/fs/debugfs/inode.c +@@ -245,10 +245,19 @@ static int debugfs_show_options(struct seq_file *m, struct dentry *root) + return 0; + } + ++static void debugfs_evict_inode(struct inode *inode) ++{ ++ truncate_inode_pages(&inode->i_data, 0); ++ clear_inode(inode); ++ if (S_ISLNK(inode->i_mode)) ++ kfree(inode->i_private); ++} ++ + static const struct super_operations debugfs_super_operations = { + .statfs = simple_statfs, + .remount_fs = debugfs_remount, + .show_options = debugfs_show_options, ++ .evict_inode = debugfs_evict_inode, + }; + + static int debug_fill_super(struct super_block *sb, void *data, int silent) +@@ -465,23 +474,14 @@ static int __debugfs_remove(struct dentry *dentry, struct dentry *parent) + int ret = 0; + + if (debugfs_positive(dentry)) { +- if (dentry->d_inode) { +- dget(dentry); +- switch (dentry->d_inode->i_mode & S_IFMT) { +- case S_IFDIR: +- ret = simple_rmdir(parent->d_inode, dentry); +- break; +- case S_IFLNK: +- kfree(dentry->d_inode->i_private); +- /* fall through */ +- default: +- simple_unlink(parent->d_inode, dentry); +- break; +- } +- if (!ret) +- d_delete(dentry); +- dput(dentry); +- } ++ dget(dentry); ++ if (S_ISDIR(dentry->d_inode->i_mode)) ++ ret = simple_rmdir(parent->d_inode, dentry); ++ else ++ simple_unlink(parent->d_inode, dentry); ++ if (!ret) ++ d_delete(dentry); ++ dput(dentry); + } + return ret; + } +@@ -533,7 +533,7 @@ EXPORT_SYMBOL_GPL(debugfs_remove); + */ + void debugfs_remove_recursive(struct dentry *dentry) + { +- struct dentry *child, *next, *parent; ++ struct dentry *child, *parent; + + if (IS_ERR_OR_NULL(dentry)) + return; +@@ -545,30 +545,49 @@ void debugfs_remove_recursive(struct dentry *dentry) + parent = dentry; + down: + mutex_lock(&parent->d_inode->i_mutex); +- list_for_each_entry_safe(child, next, &parent->d_subdirs, d_u.d_child) { ++ loop: ++ /* ++ * The parent->d_subdirs is protected by the d_lock. Outside that ++ * lock, the child can be unlinked and set to be freed which can ++ * use the d_u.d_child as the rcu head and corrupt this list. ++ */ ++ spin_lock(&parent->d_lock); ++ list_for_each_entry(child, &parent->d_subdirs, d_child) { + if (!debugfs_positive(child)) + continue; + + /* perhaps simple_empty(child) makes more sense */ + if (!list_empty(&child->d_subdirs)) { ++ spin_unlock(&parent->d_lock); + mutex_unlock(&parent->d_inode->i_mutex); + parent = child; + goto down; + } +- up: ++ ++ spin_unlock(&parent->d_lock); ++ + if (!__debugfs_remove(child, parent)) + simple_release_fs(&debugfs_mount, &debugfs_mount_count); ++ ++ /* ++ * The parent->d_lock protects agaist child from unlinking ++ * from d_subdirs. When releasing the parent->d_lock we can ++ * no longer trust that the next pointer is valid. ++ * Restart the loop. We'll skip this one with the ++ * debugfs_positive() check. ++ */ ++ goto loop; + } ++ spin_unlock(&parent->d_lock); + + mutex_unlock(&parent->d_inode->i_mutex); + child = parent; + parent = parent->d_parent; + mutex_lock(&parent->d_inode->i_mutex); + +- if (child != dentry) { +- next = list_next_entry(child, d_u.d_child); +- goto up; +- } ++ if (child != dentry) ++ /* go up */ ++ goto loop; + + if (!__debugfs_remove(child, parent)) + simple_release_fs(&debugfs_mount, &debugfs_mount_count); +diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c +index 2f6735d..31b148f 100644 +--- a/fs/ecryptfs/crypto.c ++++ b/fs/ecryptfs/crypto.c +@@ -1917,7 +1917,6 @@ ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size, + break; + case 2: + dst[dst_byte_offset++] |= (src_byte); +- dst[dst_byte_offset] = 0; + current_bit_offset = 0; + break; + } +diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c +index b1eaa7a..03df502 100644 +--- a/fs/ecryptfs/file.c ++++ b/fs/ecryptfs/file.c +@@ -191,23 +191,11 @@ static int ecryptfs_open(struct inode *inode, struct file *file) + { + int rc = 0; + struct ecryptfs_crypt_stat *crypt_stat = NULL; +- struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + struct dentry *ecryptfs_dentry = file->f_path.dentry; + /* Private value of ecryptfs_dentry allocated in + * ecryptfs_lookup() */ + struct ecryptfs_file_info *file_info; + +- mount_crypt_stat = &ecryptfs_superblock_to_private( +- ecryptfs_dentry->d_sb)->mount_crypt_stat; +- if ((mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) +- && ((file->f_flags & O_WRONLY) || (file->f_flags & O_RDWR) +- || (file->f_flags & O_CREAT) || (file->f_flags & O_TRUNC) +- || (file->f_flags & O_APPEND))) { +- printk(KERN_WARNING "Mount has encrypted view enabled; " +- "files may only be read\n"); +- rc = -EPERM; +- goto out; +- } + /* Released in ecryptfs_release or end of function if failure */ + file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL); + ecryptfs_set_file_private(file, file_info); +diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c +index b167ca4..a85ceb7 100644 +--- a/fs/ecryptfs/inode.c ++++ b/fs/ecryptfs/inode.c +@@ -1039,7 +1039,7 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, + } + + rc = vfs_setxattr(lower_dentry, name, value, size, flags); +- if (!rc) ++ if (!rc && dentry->d_inode) + fsstack_copy_attr_all(dentry->d_inode, lower_dentry->d_inode); + out: + return rc; +diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c +index 1b119d3..34eb843 100644 +--- a/fs/ecryptfs/main.c ++++ b/fs/ecryptfs/main.c +@@ -493,6 +493,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags + { + struct super_block *s; + struct ecryptfs_sb_info *sbi; ++ struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + struct ecryptfs_dentry_info *root_info; + const char *err = "Getting sb failed"; + struct inode *inode; +@@ -511,6 +512,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags + err = "Error parsing options"; + goto out; + } ++ mount_crypt_stat = &sbi->mount_crypt_stat; + + s = sget(fs_type, NULL, set_anon_super, flags, NULL); + if (IS_ERR(s)) { +@@ -557,11 +559,19 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags + + /** + * Set the POSIX ACL flag based on whether they're enabled in the lower +- * mount. Force a read-only eCryptfs mount if the lower mount is ro. +- * Allow a ro eCryptfs mount even when the lower mount is rw. ++ * mount. + */ + s->s_flags = flags & ~MS_POSIXACL; +- s->s_flags |= path.dentry->d_sb->s_flags & (MS_RDONLY | MS_POSIXACL); ++ s->s_flags |= path.dentry->d_sb->s_flags & MS_POSIXACL; ++ ++ /** ++ * Force a read-only eCryptfs mount when: ++ * 1) The lower mount is ro ++ * 2) The ecryptfs_encrypted_view mount option is specified ++ */ ++ if (path.dentry->d_sb->s_flags & MS_RDONLY || ++ mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) ++ s->s_flags |= MS_RDONLY; + + s->s_maxbytes = path.dentry->d_sb->s_maxbytes; + s->s_blocksize = path.dentry->d_sb->s_blocksize; +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index ead0046..f50d79e 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -1852,7 +1852,8 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, + goto error_tgt_fput; + + /* Check if EPOLLWAKEUP is allowed */ +- ep_take_care_of_epollwakeup(&epds); ++ if (ep_op_has_event(op)) ++ ep_take_care_of_epollwakeup(&epds); + + /* + * We have to check that the file structure underneath the file descriptor +diff --git a/fs/exec.c b/fs/exec.c +index 31e46b1..05f1942 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -820,7 +821,7 @@ EXPORT_SYMBOL(read_code); + static int exec_mmap(struct mm_struct *mm) + { + struct task_struct *tsk; +- struct mm_struct * old_mm, *active_mm; ++ struct mm_struct *old_mm, *active_mm; + + /* Notify parent that we're no longer interested in the old VM */ + tsk = current; +@@ -846,6 +847,8 @@ static int exec_mmap(struct mm_struct *mm) + tsk->mm = mm; + tsk->active_mm = mm; + activate_mm(active_mm, mm); ++ tsk->mm->vmacache_seqnum = 0; ++ vmacache_flush(tsk); + task_unlock(tsk); + if (old_mm) { + up_read(&old_mm->mmap_sem); +@@ -1265,6 +1268,53 @@ static void check_unsafe_exec(struct linux_binprm *bprm) + spin_unlock(&p->fs->lock); + } + ++static void bprm_fill_uid(struct linux_binprm *bprm) ++{ ++ struct inode *inode; ++ unsigned int mode; ++ kuid_t uid; ++ kgid_t gid; ++ ++ /* clear any previous set[ug]id data from a previous binary */ ++ bprm->cred->euid = current_euid(); ++ bprm->cred->egid = current_egid(); ++ ++ if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ++ return; ++ ++ if (current->no_new_privs) ++ return; ++ ++ inode = file_inode(bprm->file); ++ mode = ACCESS_ONCE(inode->i_mode); ++ if (!(mode & (S_ISUID|S_ISGID))) ++ return; ++ ++ /* Be careful if suid/sgid is set */ ++ mutex_lock(&inode->i_mutex); ++ ++ /* reload atomically mode/uid/gid now that lock held */ ++ mode = inode->i_mode; ++ uid = inode->i_uid; ++ gid = inode->i_gid; ++ mutex_unlock(&inode->i_mutex); ++ ++ /* We ignore suid/sgid if there are no mappings for them in the ns */ ++ if (!kuid_has_mapping(bprm->cred->user_ns, uid) || ++ !kgid_has_mapping(bprm->cred->user_ns, gid)) ++ return; ++ ++ if (mode & S_ISUID) { ++ bprm->per_clear |= PER_CLEAR_ON_SETID; ++ bprm->cred->euid = uid; ++ } ++ ++ if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { ++ bprm->per_clear |= PER_CLEAR_ON_SETID; ++ bprm->cred->egid = gid; ++ } ++} ++ + /* + * Fill the binprm structure from the inode. + * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes +@@ -1273,36 +1323,9 @@ static void check_unsafe_exec(struct linux_binprm *bprm) + */ + int prepare_binprm(struct linux_binprm *bprm) + { +- struct inode *inode = file_inode(bprm->file); +- umode_t mode = inode->i_mode; + int retval; + +- +- /* clear any previous set[ug]id data from a previous binary */ +- bprm->cred->euid = current_euid(); +- bprm->cred->egid = current_egid(); +- +- if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) && +- !current->no_new_privs && +- kuid_has_mapping(bprm->cred->user_ns, inode->i_uid) && +- kgid_has_mapping(bprm->cred->user_ns, inode->i_gid)) { +- /* Set-uid? */ +- if (mode & S_ISUID) { +- bprm->per_clear |= PER_CLEAR_ON_SETID; +- bprm->cred->euid = inode->i_uid; +- } +- +- /* Set-gid? */ +- /* +- * If setgid is set but no group execute bit then this +- * is a candidate for mandatory locking, not a setgid +- * executable. +- */ +- if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { +- bprm->per_clear |= PER_CLEAR_ON_SETID; +- bprm->cred->egid = inode->i_gid; +- } +- } ++ bprm_fill_uid(bprm); + + /* fill in binprm security blob */ + retval = security_bprm_set_creds(bprm); +diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c +index 48a359d..831d4f0 100644 +--- a/fs/exportfs/expfs.c ++++ b/fs/exportfs/expfs.c +@@ -50,7 +50,7 @@ find_acceptable_alias(struct dentry *result, + + inode = result->d_inode; + spin_lock(&inode->i_lock); +- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) { + dget(dentry); + spin_unlock(&inode->i_lock); + if (toput) +diff --git a/fs/ext3/super.c b/fs/ext3/super.c +index 37fd31e..0498390 100644 +--- a/fs/ext3/super.c ++++ b/fs/ext3/super.c +@@ -1354,13 +1354,6 @@ set_qf_format: + "not specified."); + return 0; + } +- } else { +- if (sbi->s_jquota_fmt) { +- ext3_msg(sb, KERN_ERR, "error: journaled quota format " +- "specified with no journaling " +- "enabled."); +- return 0; +- } + } + #endif + return 1; +diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c +index 3285aa5..b610779 100644 +--- a/fs/ext4/bitmap.c ++++ b/fs/ext4/bitmap.c +@@ -24,8 +24,7 @@ int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, + __u32 provided, calculated; + struct ext4_sb_info *sbi = EXT4_SB(sb); + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return 1; + + provided = le16_to_cpu(gdp->bg_inode_bitmap_csum_lo); +@@ -46,8 +45,7 @@ void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group, + __u32 csum; + struct ext4_sb_info *sbi = EXT4_SB(sb); + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return; + + csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz); +@@ -65,8 +63,7 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, + struct ext4_sb_info *sbi = EXT4_SB(sb); + int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return 1; + + provided = le16_to_cpu(gdp->bg_block_bitmap_csum_lo); +@@ -91,8 +88,7 @@ void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group, + __u32 csum; + struct ext4_sb_info *sbi = EXT4_SB(sb); + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return; + + csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz); +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 62f024c..2a6830a 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -2110,6 +2110,7 @@ int do_journal_get_write_access(handle_t *handle, + #define CONVERT_INLINE_DATA 2 + + extern struct inode *ext4_iget(struct super_block *, unsigned long); ++extern struct inode *ext4_iget_normal(struct super_block *, unsigned long); + extern int ext4_write_inode(struct inode *, struct writeback_control *); + extern int ext4_setattr(struct dentry *, struct iattr *); + extern int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, +@@ -2340,10 +2341,18 @@ extern int ext4_register_li_request(struct super_block *sb, + static inline int ext4_has_group_desc_csum(struct super_block *sb) + { + return EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_GDT_CSUM | +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM); ++ EXT4_FEATURE_RO_COMPAT_GDT_CSUM) || ++ (EXT4_SB(sb)->s_chksum_driver != NULL); + } + ++static inline int ext4_has_metadata_csum(struct super_block *sb) ++{ ++ WARN_ON_ONCE(EXT4_HAS_RO_COMPAT_FEATURE(sb, ++ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) && ++ !EXT4_SB(sb)->s_chksum_driver); ++ ++ return (EXT4_SB(sb)->s_chksum_driver != NULL); ++} + static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es) + { + return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) | +diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c +index 3fe29de..ff42208 100644 +--- a/fs/ext4/ext4_jbd2.c ++++ b/fs/ext4/ext4_jbd2.c +@@ -87,6 +87,12 @@ int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) + ext4_put_nojournal(handle); + return 0; + } ++ ++ if (!handle->h_transaction) { ++ err = jbd2_journal_stop(handle); ++ return handle->h_err ? handle->h_err : err; ++ } ++ + sb = handle->h_transaction->t_journal->j_private; + err = handle->h_err; + rc = jbd2_journal_stop(handle); +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 4718891..4e237a6 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -74,8 +74,7 @@ static int ext4_extent_block_csum_verify(struct inode *inode, + { + struct ext4_extent_tail *et; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(inode->i_sb)) + return 1; + + et = find_ext4_extent_tail(eh); +@@ -89,8 +88,7 @@ static void ext4_extent_block_csum_set(struct inode *inode, + { + struct ext4_extent_tail *et; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(inode->i_sb)) + return; + + et = find_ext4_extent_tail(eh); +@@ -363,7 +361,7 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext) + ext4_lblk_t lblock = le32_to_cpu(ext->ee_block); + ext4_lblk_t last = lblock + len - 1; + +- if (lblock > last) ++ if (len == 0 || lblock > last) + return 0; + return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len); + } +diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c +index 171b9fa..4e8b79d 100644 +--- a/fs/ext4/extents_status.c ++++ b/fs/ext4/extents_status.c +@@ -656,6 +656,14 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk, + + BUG_ON(end < lblk); + ++ if ((status & EXTENT_STATUS_DELAYED) && ++ (status & EXTENT_STATUS_WRITTEN)) { ++ ext4_warning(inode->i_sb, "Inserting extent [%u/%u] as " ++ " delayed and written which can potentially " ++ " cause data loss.\n", lblk, len); ++ WARN_ON(1); ++ } ++ + newes.es_lblk = lblk; + newes.es_len = len; + ext4_es_store_pblock(&newes, pblk); +diff --git a/fs/ext4/file.c b/fs/ext4/file.c +index 2a8b2e1..589117e 100644 +--- a/fs/ext4/file.c ++++ b/fs/ext4/file.c +@@ -100,7 +100,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, + struct blk_plug plug; + int unaligned_aio = 0; + ssize_t ret; +- int overwrite = 0; ++ int *overwrite = iocb->private; + size_t length = iov_length(iov, nr_segs); + + if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) && +@@ -118,8 +118,6 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, + mutex_lock(&inode->i_mutex); + blk_start_plug(&plug); + +- iocb->private = &overwrite; +- + /* check whether we do a DIO overwrite or not */ + if (ext4_should_dioread_nolock(inode) && !unaligned_aio && + !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) { +@@ -143,7 +141,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, + * So we should check these two conditions. + */ + if (err == len && (map.m_flags & EXT4_MAP_MAPPED)) +- overwrite = 1; ++ *overwrite = 1; + } + + ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); +@@ -170,6 +168,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, + { + struct inode *inode = file_inode(iocb->ki_filp); + ssize_t ret; ++ int overwrite = 0; + + /* + * If we have encountered a bitmap-format file, the size limit +@@ -190,6 +189,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, + } + } + ++ iocb->private = &overwrite; + if (unlikely(iocb->ki_filp->f_flags & O_DIRECT)) + ret = ext4_file_dio_write(iocb, iov, nr_segs, pos); + else +diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c +index 64bb32f1..a8d1a64 100644 +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -864,6 +864,10 @@ got: + struct buffer_head *block_bitmap_bh; + + block_bitmap_bh = ext4_read_block_bitmap(sb, group); ++ if (!block_bitmap_bh) { ++ err = -EIO; ++ goto out; ++ } + BUFFER_TRACE(block_bitmap_bh, "get block bitmap access"); + err = ext4_journal_get_write_access(handle, block_bitmap_bh); + if (err) { +@@ -988,8 +992,7 @@ got: + spin_unlock(&sbi->s_next_gen_lock); + + /* Precompute checksum seed for inode metadata */ +- if (EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { ++ if (ext4_has_metadata_csum(sb)) { + __u32 csum; + __le32 inum = cpu_to_le32(inode->i_ino); + __le32 gen = cpu_to_le32(inode->i_generation); +diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c +index e6574d7..a7c5277 100644 +--- a/fs/ext4/indirect.c ++++ b/fs/ext4/indirect.c +@@ -576,7 +576,7 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, + EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { + EXT4_ERROR_INODE(inode, "Can't allocate blocks for " + "non-extent mapped inodes with bigalloc"); +- return -ENOSPC; ++ return -EUCLEAN; + } + + goal = ext4_find_goal(inode, map->m_lblk, partial); +diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c +index 82edf5b..8c03b74 100644 +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -1128,8 +1128,7 @@ static int ext4_finish_convert_inline_dir(handle_t *handle, + memcpy((void *)de, buf + EXT4_INLINE_DOTDOT_SIZE, + inline_size - EXT4_INLINE_DOTDOT_SIZE); + +- if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(inode->i_sb)) + csum_size = sizeof(struct ext4_dir_entry_tail); + + inode->i_size = inode->i_sb->s_blocksize; +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index a7029f4..f9c63ae 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -83,8 +83,7 @@ static int ext4_inode_csum_verify(struct inode *inode, struct ext4_inode *raw, + + if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != + cpu_to_le32(EXT4_OS_LINUX) || +- !EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ !ext4_has_metadata_csum(inode->i_sb)) + return 1; + + provided = le16_to_cpu(raw->i_checksum_lo); +@@ -105,8 +104,7 @@ static void ext4_inode_csum_set(struct inode *inode, struct ext4_inode *raw, + + if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != + cpu_to_le32(EXT4_OS_LINUX) || +- !EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ !ext4_has_metadata_csum(inode->i_sb)) + return; + + csum = ext4_inode_csum(inode, raw, ei); +@@ -571,6 +569,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, + status = map->m_flags & EXT4_MAP_UNWRITTEN ? + EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; + if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && ++ !(status & EXTENT_STATUS_WRITTEN) && + ext4_find_delalloc_range(inode, map->m_lblk, + map->m_lblk + map->m_len - 1)) + status |= EXTENT_STATUS_DELAYED; +@@ -680,6 +679,7 @@ found: + status = map->m_flags & EXT4_MAP_UNWRITTEN ? + EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; + if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && ++ !(status & EXTENT_STATUS_WRITTEN) && + ext4_find_delalloc_range(inode, map->m_lblk, + map->m_lblk + map->m_len - 1)) + status |= EXTENT_STATUS_DELAYED; +@@ -1357,7 +1357,7 @@ static void ext4_da_page_release_reservation(struct page *page, + unsigned int offset, + unsigned int length) + { +- int to_release = 0; ++ int to_release = 0, contiguous_blks = 0; + struct buffer_head *head, *bh; + unsigned int curr_off = 0; + struct inode *inode = page->mapping->host; +@@ -1378,14 +1378,23 @@ static void ext4_da_page_release_reservation(struct page *page, + + if ((offset <= curr_off) && (buffer_delay(bh))) { + to_release++; ++ contiguous_blks++; + clear_buffer_delay(bh); ++ } else if (contiguous_blks) { ++ lblk = page->index << ++ (PAGE_CACHE_SHIFT - inode->i_blkbits); ++ lblk += (curr_off >> inode->i_blkbits) - ++ contiguous_blks; ++ ext4_es_remove_extent(inode, lblk, contiguous_blks); ++ contiguous_blks = 0; + } + curr_off = next_off; + } while ((bh = bh->b_this_page) != head); + +- if (to_release) { ++ if (contiguous_blks) { + lblk = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); +- ext4_es_remove_extent(inode, lblk, to_release); ++ lblk += (curr_off >> inode->i_blkbits) - contiguous_blks; ++ ext4_es_remove_extent(inode, lblk, contiguous_blks); + } + + /* If we have released all the blocks belonging to a cluster, then we +@@ -1744,19 +1753,32 @@ static int __ext4_journalled_writepage(struct page *page, + ext4_walk_page_buffers(handle, page_bufs, 0, len, + NULL, bget_one); + } +- /* As soon as we unlock the page, it can go away, but we have +- * references to buffers so we are safe */ ++ /* ++ * We need to release the page lock before we start the ++ * journal, so grab a reference so the page won't disappear ++ * out from under us. ++ */ ++ get_page(page); + unlock_page(page); + + handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, + ext4_writepage_trans_blocks(inode)); + if (IS_ERR(handle)) { + ret = PTR_ERR(handle); +- goto out; ++ put_page(page); ++ goto out_no_pagelock; + } +- + BUG_ON(!ext4_handle_valid(handle)); + ++ lock_page(page); ++ put_page(page); ++ if (page->mapping != mapping) { ++ /* The page got truncated from under us */ ++ ext4_journal_stop(handle); ++ ret = 0; ++ goto out; ++ } ++ + if (inline_data) { + ret = ext4_journal_get_write_access(handle, inode_bh); + +@@ -1781,6 +1803,8 @@ static int __ext4_journalled_writepage(struct page *page, + NULL, bput_one); + ext4_set_inode_state(inode, EXT4_STATE_JDATA); + out: ++ unlock_page(page); ++out_no_pagelock: + brelse(inode_bh); + return ret; + } +@@ -2195,6 +2219,7 @@ static int mpage_map_and_submit_extent(handle_t *handle, + struct ext4_map_blocks *map = &mpd->map; + int err; + loff_t disksize; ++ int progress = 0; + + mpd->io_submit.io_end->offset = + ((loff_t)map->m_lblk) << inode->i_blkbits; +@@ -2211,8 +2236,11 @@ static int mpage_map_and_submit_extent(handle_t *handle, + * is non-zero, a commit should free up blocks. + */ + if ((err == -ENOMEM) || +- (err == -ENOSPC && ext4_count_free_clusters(sb))) ++ (err == -ENOSPC && ext4_count_free_clusters(sb))) { ++ if (progress) ++ goto update_disksize; + return err; ++ } + ext4_msg(sb, KERN_CRIT, + "Delayed block allocation failed for " + "inode %lu at logical offset %llu with" +@@ -2229,15 +2257,17 @@ static int mpage_map_and_submit_extent(handle_t *handle, + *give_up_on_write = true; + return err; + } ++ progress = 1; + /* + * Update buffer state, submit mapped pages, and get us new + * extent to map + */ + err = mpage_map_and_submit_buffers(mpd); + if (err < 0) +- return err; ++ goto update_disksize; + } while (map->m_len); + ++update_disksize: + /* + * Update on-disk size after IO is submitted. Races with + * truncate are avoided by checking i_size under i_data_sem. +@@ -2627,6 +2657,20 @@ static int ext4_nonda_switch(struct super_block *sb) + return 0; + } + ++/* We always reserve for an inode update; the superblock could be there too */ ++static int ext4_da_write_credits(struct inode *inode, loff_t pos, unsigned len) ++{ ++ if (likely(EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, ++ EXT4_FEATURE_RO_COMPAT_LARGE_FILE))) ++ return 1; ++ ++ if (pos + len <= 0x7fffffffULL) ++ return 1; ++ ++ /* We might need to update the superblock to set LARGE_FILE */ ++ return 2; ++} ++ + static int ext4_da_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned flags, + struct page **pagep, void **fsdata) +@@ -2677,7 +2721,8 @@ retry_grab: + * of file which has an already mapped buffer. + */ + retry_journal: +- handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, 1); ++ handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, ++ ext4_da_write_credits(inode, pos, len)); + if (IS_ERR(handle)) { + page_cache_release(page); + return PTR_ERR(handle); +@@ -4055,8 +4100,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) + ei->i_extra_isize = 0; + + /* Precompute checksum seed for inode metadata */ +- if (EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { ++ if (ext4_has_metadata_csum(sb)) { + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + __u32 csum; + __le32 inum = cpu_to_le32(inode->i_ino); +@@ -4244,6 +4288,13 @@ bad_inode: + return ERR_PTR(ret); + } + ++struct inode *ext4_iget_normal(struct super_block *sb, unsigned long ino) ++{ ++ if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO) ++ return ERR_PTR(-EIO); ++ return ext4_iget(sb, ino); ++} ++ + static int ext4_inode_blocks_set(handle_t *handle, + struct ext4_inode *raw_inode, + struct ext4_inode_info *ei) +@@ -4639,8 +4690,12 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) + ext4_orphan_del(NULL, inode); + goto err_out; + } +- } else ++ } else { ++ loff_t oldsize = inode->i_size; ++ + i_size_write(inode, attr->ia_size); ++ pagecache_isize_extended(inode, oldsize, inode->i_size); ++ } + + /* + * Blocks are going to be removed from the inode. Wait +diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c +index a2a837f..dfe982d 100644 +--- a/fs/ext4/ioctl.c ++++ b/fs/ext4/ioctl.c +@@ -343,8 +343,7 @@ flags_out: + if (!inode_owner_or_capable(inode)) + return -EPERM; + +- if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { ++ if (ext4_has_metadata_csum(inode->i_sb)) { + ext4_warning(sb, "Setting inode version is not " + "supported with metadata_csum enabled."); + return -ENOTTY; +@@ -544,9 +543,17 @@ group_add_out: + } + + case EXT4_IOC_SWAP_BOOT: ++ { ++ int err; + if (!(filp->f_mode & FMODE_WRITE)) + return -EBADF; +- return swap_inode_boot_loader(sb, inode); ++ err = mnt_want_write_file(filp); ++ if (err) ++ return err; ++ err = swap_inode_boot_loader(sb, inode); ++ mnt_drop_write_file(filp); ++ return err; ++ } + + case EXT4_IOC_RESIZE_FS: { + ext4_fsblk_t n_blocks_count; +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 502f0fd..c4a5e4d 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -1044,6 +1044,8 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group) + * allocating. If we are looking at the buddy cache we would + * have taken a reference using ext4_mb_load_buddy and that + * would have pinned buddy page to page cache. ++ * The call to ext4_mb_get_buddy_page_lock will mark the ++ * page accessed. + */ + ret = ext4_mb_get_buddy_page_lock(sb, group, &e4b); + if (ret || !EXT4_MB_GRP_NEED_INIT(this_grp)) { +@@ -1062,7 +1064,6 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group) + ret = -EIO; + goto err; + } +- mark_page_accessed(page); + + if (e4b.bd_buddy_page == NULL) { + /* +@@ -1082,7 +1083,6 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group) + ret = -EIO; + goto err; + } +- mark_page_accessed(page); + err: + ext4_mb_put_buddy_page_lock(&e4b); + return ret; +@@ -1141,7 +1141,7 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group, + + /* we could use find_or_create_page(), but it locks page + * what we'd like to avoid in fast path ... */ +- page = find_get_page(inode->i_mapping, pnum); ++ page = find_get_page_flags(inode->i_mapping, pnum, FGP_ACCESSED); + if (page == NULL || !PageUptodate(page)) { + if (page) + /* +@@ -1172,15 +1172,16 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group, + ret = -EIO; + goto err; + } ++ ++ /* Pages marked accessed already */ + e4b->bd_bitmap_page = page; + e4b->bd_bitmap = page_address(page) + (poff * sb->s_blocksize); +- mark_page_accessed(page); + + block++; + pnum = block / blocks_per_page; + poff = block % blocks_per_page; + +- page = find_get_page(inode->i_mapping, pnum); ++ page = find_get_page_flags(inode->i_mapping, pnum, FGP_ACCESSED); + if (page == NULL || !PageUptodate(page)) { + if (page) + page_cache_release(page); +@@ -1201,9 +1202,10 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group, + ret = -EIO; + goto err; + } ++ ++ /* Pages marked accessed already */ + e4b->bd_buddy_page = page; + e4b->bd_buddy = page_address(page) + (poff * sb->s_blocksize); +- mark_page_accessed(page); + + BUG_ON(e4b->bd_bitmap_page == NULL); + BUG_ON(e4b->bd_buddy_page == NULL); +@@ -1398,6 +1400,8 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, + int last = first + count - 1; + struct super_block *sb = e4b->bd_sb; + ++ if (WARN_ON(count == 0)) ++ return; + BUG_ON(last >= (sb->s_blocksize << 3)); + assert_spin_locked(ext4_group_lock_ptr(sb, e4b->bd_group)); + /* Don't bother if the block group is corrupt. */ +@@ -3196,8 +3200,30 @@ static void ext4_mb_collect_stats(struct ext4_allocation_context *ac) + static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac) + { + struct ext4_prealloc_space *pa = ac->ac_pa; ++ struct ext4_buddy e4b; ++ int err; + +- if (pa && pa->pa_type == MB_INODE_PA) ++ if (pa == NULL) { ++ if (ac->ac_f_ex.fe_len == 0) ++ return; ++ err = ext4_mb_load_buddy(ac->ac_sb, ac->ac_f_ex.fe_group, &e4b); ++ if (err) { ++ /* ++ * This should never happen since we pin the ++ * pages in the ext4_allocation_context so ++ * ext4_mb_load_buddy() should never fail. ++ */ ++ WARN(1, "mb_load_buddy failed (%d)", err); ++ return; ++ } ++ ext4_lock_group(ac->ac_sb, ac->ac_f_ex.fe_group); ++ mb_free_blocks(ac->ac_inode, &e4b, ac->ac_f_ex.fe_start, ++ ac->ac_f_ex.fe_len); ++ ext4_unlock_group(ac->ac_sb, ac->ac_f_ex.fe_group); ++ ext4_mb_unload_buddy(&e4b); ++ return; ++ } ++ if (pa->pa_type == MB_INODE_PA) + pa->pa_free += ac->ac_b_ex.fe_len; + } + +@@ -4767,18 +4793,12 @@ do_more: + /* + * blocks being freed are metadata. these blocks shouldn't + * be used until this transaction is committed ++ * ++ * We use __GFP_NOFAIL because ext4_free_blocks() is not allowed ++ * to fail. + */ +- retry: +- new_entry = kmem_cache_alloc(ext4_free_data_cachep, GFP_NOFS); +- if (!new_entry) { +- /* +- * We use a retry loop because +- * ext4_free_blocks() is not allowed to fail. +- */ +- cond_resched(); +- congestion_wait(BLK_RW_ASYNC, HZ/50); +- goto retry; +- } ++ new_entry = kmem_cache_alloc(ext4_free_data_cachep, ++ GFP_NOFS|__GFP_NOFAIL); + new_entry->efd_start_cluster = bit; + new_entry->efd_group = block_group; + new_entry->efd_count = count_clusters; +diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c +index 2ae73a8..be92ed2 100644 +--- a/fs/ext4/migrate.c ++++ b/fs/ext4/migrate.c +@@ -616,6 +616,7 @@ int ext4_ind_migrate(struct inode *inode) + struct ext4_inode_info *ei = EXT4_I(inode); + struct ext4_extent *ex; + unsigned int i, len; ++ ext4_lblk_t start, end; + ext4_fsblk_t blk; + handle_t *handle; + int ret; +@@ -629,6 +630,14 @@ int ext4_ind_migrate(struct inode *inode) + EXT4_FEATURE_RO_COMPAT_BIGALLOC)) + return -EOPNOTSUPP; + ++ /* ++ * In order to get correct extent info, force all delayed allocation ++ * blocks to be allocated, otherwise delayed allocation blocks may not ++ * be reflected and bypass the checks on extent header. ++ */ ++ if (test_opt(inode->i_sb, DELALLOC)) ++ ext4_alloc_da_blocks(inode); ++ + handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1); + if (IS_ERR(handle)) + return PTR_ERR(handle); +@@ -646,11 +655,13 @@ int ext4_ind_migrate(struct inode *inode) + goto errout; + } + if (eh->eh_entries == 0) +- blk = len = 0; ++ blk = len = start = end = 0; + else { + len = le16_to_cpu(ex->ee_len); + blk = ext4_ext_pblock(ex); +- if (len > EXT4_NDIR_BLOCKS) { ++ start = le32_to_cpu(ex->ee_block); ++ end = start + len - 1; ++ if (end >= EXT4_NDIR_BLOCKS) { + ret = -EOPNOTSUPP; + goto errout; + } +@@ -658,7 +669,7 @@ int ext4_ind_migrate(struct inode *inode) + + ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS); + memset(ei->i_data, 0, sizeof(ei->i_data)); +- for (i=0; i < len; i++) ++ for (i = start; i <= end; i++) + ei->i_data[i] = cpu_to_le32(blk++); + ext4_mark_inode_dirty(handle, inode); + errout: +diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c +index 04434ad..1268a1b 100644 +--- a/fs/ext4/mmp.c ++++ b/fs/ext4/mmp.c +@@ -20,8 +20,7 @@ static __le32 ext4_mmp_csum(struct super_block *sb, struct mmp_struct *mmp) + + int ext4_mmp_csum_verify(struct super_block *sb, struct mmp_struct *mmp) + { +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return 1; + + return mmp->mmp_checksum == ext4_mmp_csum(sb, mmp); +@@ -29,8 +28,7 @@ int ext4_mmp_csum_verify(struct super_block *sb, struct mmp_struct *mmp) + + void ext4_mmp_csum_set(struct super_block *sb, struct mmp_struct *mmp) + { +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return; + + mmp->mmp_checksum = ext4_mmp_csum(sb, mmp); +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index d050e04..bc7e37b 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -123,8 +123,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode, + "directory leaf block found instead of index block"); + return ERR_PTR(-EIO); + } +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) || ++ if (!ext4_has_metadata_csum(inode->i_sb) || + buffer_verified(bh)) + return bh; + +@@ -339,8 +338,7 @@ int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent) + { + struct ext4_dir_entry_tail *t; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(inode->i_sb)) + return 1; + + t = get_dirent_tail(inode, dirent); +@@ -361,8 +359,7 @@ static void ext4_dirent_csum_set(struct inode *inode, + { + struct ext4_dir_entry_tail *t; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(inode->i_sb)) + return; + + t = get_dirent_tail(inode, dirent); +@@ -437,8 +434,7 @@ static int ext4_dx_csum_verify(struct inode *inode, + struct dx_tail *t; + int count_offset, limit, count; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(inode->i_sb)) + return 1; + + c = get_dx_countlimit(inode, dirent, &count_offset); +@@ -467,8 +463,7 @@ static void ext4_dx_csum_set(struct inode *inode, struct ext4_dir_entry *dirent) + struct dx_tail *t; + int count_offset, limit, count; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(inode->i_sb)) + return; + + c = get_dx_countlimit(inode, dirent, &count_offset); +@@ -556,8 +551,7 @@ static inline unsigned dx_root_limit(struct inode *dir, unsigned infosize) + unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(1) - + EXT4_DIR_REC_LEN(2) - infosize; + +- if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(dir->i_sb)) + entry_space -= sizeof(struct dx_tail); + return entry_space / sizeof(struct dx_entry); + } +@@ -566,8 +560,7 @@ static inline unsigned dx_node_limit(struct inode *dir) + { + unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(0); + +- if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(dir->i_sb)) + entry_space -= sizeof(struct dx_tail); + return entry_space / sizeof(struct dx_entry); + } +@@ -1429,7 +1422,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi + dentry); + return ERR_PTR(-EIO); + } +- inode = ext4_iget(dir->i_sb, ino); ++ inode = ext4_iget_normal(dir->i_sb, ino); + if (inode == ERR_PTR(-ESTALE)) { + EXT4_ERROR_INODE(dir, + "deleted inode referenced: %u", +@@ -1460,7 +1453,7 @@ struct dentry *ext4_get_parent(struct dentry *child) + return ERR_PTR(-EIO); + } + +- return d_obtain_alias(ext4_iget(child->d_inode->i_sb, ino)); ++ return d_obtain_alias(ext4_iget_normal(child->d_inode->i_sb, ino)); + } + + /* +@@ -1534,8 +1527,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, + int csum_size = 0; + int err = 0, i; + +- if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(dir->i_sb)) + csum_size = sizeof(struct ext4_dir_entry_tail); + + bh2 = ext4_append(handle, dir, &newblock); +@@ -1704,8 +1696,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, + int csum_size = 0; + int err; + +- if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(inode->i_sb)) + csum_size = sizeof(struct ext4_dir_entry_tail); + + if (!de) { +@@ -1772,8 +1763,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, + struct fake_dirent *fde; + int csum_size = 0; + +- if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(inode->i_sb)) + csum_size = sizeof(struct ext4_dir_entry_tail); + + blocksize = dir->i_sb->s_blocksize; +@@ -1879,7 +1869,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, + struct inode *inode) + { + struct inode *dir = dentry->d_parent->d_inode; +- struct buffer_head *bh; ++ struct buffer_head *bh = NULL; + struct ext4_dir_entry_2 *de; + struct ext4_dir_entry_tail *t; + struct super_block *sb; +@@ -1889,8 +1879,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, + ext4_lblk_t block, blocks; + int csum_size = 0; + +- if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(inode->i_sb)) + csum_size = sizeof(struct ext4_dir_entry_tail); + + sb = dir->i_sb; +@@ -1904,14 +1893,14 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, + return retval; + if (retval == 1) { + retval = 0; +- return retval; ++ goto out; + } + } + + if (is_dx(dir)) { + retval = ext4_dx_add_entry(handle, dentry, inode); + if (!retval || (retval != ERR_BAD_DX_DIR)) +- return retval; ++ goto out; + ext4_clear_inode_flag(dir, EXT4_INODE_INDEX); + dx_fallback++; + ext4_mark_inode_dirty(handle, dir); +@@ -1923,14 +1912,15 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, + return PTR_ERR(bh); + + retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh); +- if (retval != -ENOSPC) { +- brelse(bh); +- return retval; +- } ++ if (retval != -ENOSPC) ++ goto out; + + if (blocks == 1 && !dx_fallback && +- EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) +- return make_indexed_dir(handle, dentry, inode, bh); ++ EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) { ++ retval = make_indexed_dir(handle, dentry, inode, bh); ++ bh = NULL; /* make_indexed_dir releases bh */ ++ goto out; ++ } + brelse(bh); + } + bh = ext4_append(handle, dir, &block); +@@ -1946,6 +1936,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry, + } + + retval = add_dirent_to_buf(handle, dentry, inode, de, bh); ++out: + brelse(bh); + if (retval == 0) + ext4_set_inode_state(inode, EXT4_STATE_NEWENTRY); +@@ -2152,8 +2143,7 @@ static int ext4_delete_entry(handle_t *handle, + return err; + } + +- if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(dir->i_sb)) + csum_size = sizeof(struct ext4_dir_entry_tail); + + BUFFER_TRACE(bh, "get_write_access"); +@@ -2372,8 +2362,7 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir, + int csum_size = 0; + int err; + +- if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(dir->i_sb)) + csum_size = sizeof(struct ext4_dir_entry_tail); + + if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) { +diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c +index f3b84cd..2400ad1 100644 +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -1071,7 +1071,7 @@ static void update_backups(struct super_block *sb, int blk_off, char *data, + break; + + if (meta_bg == 0) +- backup_block = group * bpg + blk_off; ++ backup_block = ((ext4_fsblk_t)group) * bpg + blk_off; + else + backup_block = (ext4_group_first_block_no(sb, group) + + ext4_bg_has_super(sb, group)); +@@ -1200,8 +1200,7 @@ static int ext4_set_bitmap_checksums(struct super_block *sb, + { + struct buffer_head *bh; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return 0; + + bh = ext4_get_bitmap(sb, group_data->inode_bitmap); +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 25b327e..a07af5b 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -140,8 +140,7 @@ static __le32 ext4_superblock_csum(struct super_block *sb, + int ext4_superblock_csum_verify(struct super_block *sb, + struct ext4_super_block *es) + { +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return 1; + + return es->s_checksum == ext4_superblock_csum(sb, es); +@@ -151,8 +150,7 @@ void ext4_superblock_csum_set(struct super_block *sb) + { + struct ext4_super_block *es = EXT4_SB(sb)->s_es; + +- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(sb)) + return; + + es->s_checksum = ext4_superblock_csum(sb, es); +@@ -834,6 +832,7 @@ static void ext4_put_super(struct super_block *sb) + dump_orphan_list(sb, sbi); + J_ASSERT(list_empty(&sbi->s_orphan)); + ++ sync_blockdev(sb->s_bdev); + invalidate_bdev(sb->s_bdev); + if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) { + /* +@@ -996,7 +995,7 @@ static struct inode *ext4_nfs_get_inode(struct super_block *sb, + * Currently we don't know the generation for parent directory, so + * a generation of 0 means "accept any" + */ +- inode = ext4_iget(sb, ino); ++ inode = ext4_iget_normal(sb, ino); + if (IS_ERR(inode)) + return ERR_CAST(inode); + if (generation && inode->i_generation != generation) { +@@ -1706,13 +1705,6 @@ static int parse_options(char *options, struct super_block *sb, + "not specified"); + return 0; + } +- } else { +- if (sbi->s_jquota_fmt) { +- ext4_msg(sb, KERN_ERR, "journaled quota format " +- "specified with no journaling " +- "enabled"); +- return 0; +- } + } + #endif + if (test_opt(sb, DIOREAD_NOLOCK)) { +@@ -2010,8 +2002,7 @@ static __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group, + __u16 crc = 0; + __le32 le_group = cpu_to_le32(block_group); + +- if ((sbi->s_es->s_feature_ro_compat & +- cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))) { ++ if (ext4_has_metadata_csum(sbi->s_sb)) { + /* Use new metadata_csum algorithm */ + __le16 save_csum; + __u32 csum32; +@@ -2029,6 +2020,10 @@ static __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group, + } + + /* old crc16 code */ ++ if (!(sbi->s_es->s_feature_ro_compat & ++ cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM))) ++ return 0; ++ + offset = offsetof(struct ext4_group_desc, bg_checksum); + + crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid)); +@@ -3167,11 +3162,10 @@ static int set_journal_csum_feature_set(struct super_block *sb) + int compat, incompat; + struct ext4_sb_info *sbi = EXT4_SB(sb); + +- if (EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { +- /* journal checksum v2 */ ++ if (ext4_has_metadata_csum(sb)) { ++ /* journal checksum v3 */ + compat = 0; +- incompat = JBD2_FEATURE_INCOMPAT_CSUM_V2; ++ incompat = JBD2_FEATURE_INCOMPAT_CSUM_V3; + } else { + /* journal checksum v1 */ + compat = JBD2_FEATURE_COMPAT_CHECKSUM; +@@ -3193,6 +3187,7 @@ static int set_journal_csum_feature_set(struct super_block *sb) + jbd2_journal_clear_features(sbi->s_journal, + JBD2_FEATURE_COMPAT_CHECKSUM, 0, + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT | ++ JBD2_FEATURE_INCOMPAT_CSUM_V3 | + JBD2_FEATURE_INCOMPAT_CSUM_V2); + } + +@@ -3474,8 +3469,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) + } + + /* Precompute checksum seed for all metadata */ +- if (EXT4_HAS_RO_COMPAT_FEATURE(sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (ext4_has_metadata_csum(sb)) + sbi->s_csum_seed = ext4_chksum(sbi, ~0, es->s_uuid, + sizeof(es->s_uuid)); + +@@ -3493,6 +3487,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) + #ifdef CONFIG_EXT4_FS_POSIX_ACL + set_opt(sb, POSIX_ACL); + #endif ++ /* don't forget to enable journal_csum when metadata_csum is enabled. */ ++ if (ext4_has_metadata_csum(sb)) ++ set_opt(sb, JOURNAL_CHECKSUM); ++ + if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA) + set_opt(sb, JOURNAL_DATA); + else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED) +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index 55e611c..8825154 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -141,8 +141,7 @@ static int ext4_xattr_block_csum_verify(struct inode *inode, + sector_t block_nr, + struct ext4_xattr_header *hdr) + { +- if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) && ++ if (ext4_has_metadata_csum(inode->i_sb) && + (hdr->h_checksum != ext4_xattr_block_csum(inode, block_nr, hdr))) + return 0; + return 1; +@@ -152,8 +151,7 @@ static void ext4_xattr_block_csum_set(struct inode *inode, + sector_t block_nr, + struct ext4_xattr_header *hdr) + { +- if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb, +- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) ++ if (!ext4_has_metadata_csum(inode->i_sb)) + return; + + hdr->h_checksum = ext4_xattr_block_csum(inode, block_nr, hdr); +@@ -189,14 +187,28 @@ ext4_listxattr(struct dentry *dentry, char *buffer, size_t size) + } + + static int +-ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end) ++ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end, ++ void *value_start) + { +- while (!IS_LAST_ENTRY(entry)) { +- struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(entry); ++ struct ext4_xattr_entry *e = entry; ++ ++ while (!IS_LAST_ENTRY(e)) { ++ struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(e); + if ((void *)next >= end) + return -EIO; +- entry = next; ++ e = next; + } ++ ++ while (!IS_LAST_ENTRY(entry)) { ++ if (entry->e_value_size != 0 && ++ (value_start + le16_to_cpu(entry->e_value_offs) < ++ (void *)e + sizeof(__u32) || ++ value_start + le16_to_cpu(entry->e_value_offs) + ++ le32_to_cpu(entry->e_value_size) > end)) ++ return -EIO; ++ entry = EXT4_XATTR_NEXT(entry); ++ } ++ + return 0; + } + +@@ -213,7 +225,8 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh) + return -EIO; + if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh))) + return -EIO; +- error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size); ++ error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size, ++ bh->b_data); + if (!error) + set_buffer_verified(bh); + return error; +@@ -329,7 +342,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name, + header = IHDR(inode, raw_inode); + entry = IFIRST(header); + end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; +- error = ext4_xattr_check_names(entry, end); ++ error = ext4_xattr_check_names(entry, end, entry); + if (error) + goto cleanup; + error = ext4_xattr_find_entry(&entry, name_index, name, +@@ -457,7 +470,7 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size) + raw_inode = ext4_raw_inode(&iloc); + header = IHDR(inode, raw_inode); + end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; +- error = ext4_xattr_check_names(IFIRST(header), end); ++ error = ext4_xattr_check_names(IFIRST(header), end, IFIRST(header)); + if (error) + goto cleanup; + error = ext4_xattr_list_entries(dentry, IFIRST(header), +@@ -972,7 +985,8 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, + is->s.here = is->s.first; + is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; + if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) { +- error = ext4_xattr_check_names(IFIRST(header), is->s.end); ++ error = ext4_xattr_check_names(IFIRST(header), is->s.end, ++ IFIRST(header)); + if (error) + return error; + /* Find the named attribute. */ +diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c +index 293d048..5c6fe27 100644 +--- a/fs/f2fs/checkpoint.c ++++ b/fs/f2fs/checkpoint.c +@@ -71,7 +71,6 @@ repeat: + goto repeat; + } + out: +- mark_page_accessed(page); + return page; + } + +diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c +index b0649b7..bb6478a 100644 +--- a/fs/f2fs/node.c ++++ b/fs/f2fs/node.c +@@ -969,7 +969,6 @@ repeat: + } + got_it: + f2fs_bug_on(nid != nid_of_node(page)); +- mark_page_accessed(page); + return page; + } + +@@ -1024,7 +1023,6 @@ page_hit: + f2fs_put_page(page, 1); + return ERR_PTR(-EIO); + } +- mark_page_accessed(page); + return page; + } + +diff --git a/fs/fhandle.c b/fs/fhandle.c +index 999ff5c..d59712d 100644 +--- a/fs/fhandle.c ++++ b/fs/fhandle.c +@@ -195,8 +195,9 @@ static int handle_to_path(int mountdirfd, struct file_handle __user *ufh, + goto out_err; + } + /* copy the full handle */ +- if (copy_from_user(handle, ufh, +- sizeof(struct file_handle) + ++ *handle = f_handle; ++ if (copy_from_user(&handle->f_handle, ++ &ufh->f_handle, + f_handle.handle_bytes)) { + retval = -EFAULT; + goto out_handle; +diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c +index a163159..23a51f0 100644 +--- a/fs/fs-writeback.c ++++ b/fs/fs-writeback.c +@@ -476,12 +476,28 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) + * write_inode() + */ + spin_lock(&inode->i_lock); +- /* Clear I_DIRTY_PAGES if we've written out all dirty pages */ +- if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) +- inode->i_state &= ~I_DIRTY_PAGES; ++ + dirty = inode->i_state & I_DIRTY; +- inode->i_state &= ~(I_DIRTY_SYNC | I_DIRTY_DATASYNC); ++ inode->i_state &= ~I_DIRTY; ++ ++ /* ++ * Paired with smp_mb() in __mark_inode_dirty(). This allows ++ * __mark_inode_dirty() to test i_state without grabbing i_lock - ++ * either they see the I_DIRTY bits cleared or we see the dirtied ++ * inode. ++ * ++ * I_DIRTY_PAGES is always cleared together above even if @mapping ++ * still has dirty pages. The flag is reinstated after smp_mb() if ++ * necessary. This guarantees that either __mark_inode_dirty() ++ * sees clear I_DIRTY_PAGES or we see PAGECACHE_TAG_DIRTY. ++ */ ++ smp_mb(); ++ ++ if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) ++ inode->i_state |= I_DIRTY_PAGES; ++ + spin_unlock(&inode->i_lock); ++ + /* Don't write the inode if only I_DIRTY_PAGES was set */ + if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { + int err = write_inode(inode, wbc); +@@ -1145,12 +1161,11 @@ void __mark_inode_dirty(struct inode *inode, int flags) + } + + /* +- * make sure that changes are seen by all cpus before we test i_state +- * -- mikulas ++ * Paired with smp_mb() in __writeback_single_inode() for the ++ * following lockless i_state test. See there for details. + */ + smp_mb(); + +- /* avoid the locking if we can */ + if ((inode->i_state & flags) == flags) + return; + +diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c +index 0a648bb..499155c 100644 +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -819,8 +819,8 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) + + newpage = buf->page; + +- if (WARN_ON(!PageUptodate(newpage))) +- return -EIO; ++ if (!PageUptodate(newpage)) ++ SetPageUptodate(newpage); + + ClearPageMappedToDisk(newpage); + +@@ -1614,7 +1614,7 @@ out_finish: + + static void fuse_retrieve_end(struct fuse_conn *fc, struct fuse_req *req) + { +- release_pages(req->pages, req->num_pages, 0); ++ release_pages(req->pages, req->num_pages, false); + } + + static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, +@@ -1726,6 +1726,9 @@ copy_finish: + static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, + unsigned int size, struct fuse_copy_state *cs) + { ++ /* Don't try to move pages (yet) */ ++ cs->move_pages = 0; ++ + switch (code) { + case FUSE_NOTIFY_POLL: + return fuse_notify_poll(fc, size, cs); +diff --git a/fs/fuse/file.c b/fs/fuse/file.c +index 77bcc30..d8a6027 100644 +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -1003,13 +1003,9 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, + if (mapping_writably_mapped(mapping)) + flush_dcache_page(page); + +- pagefault_disable(); + tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes); +- pagefault_enable(); + flush_dcache_page(page); + +- mark_page_accessed(page); +- + if (!tmp) { + unlock_page(page); + page_cache_release(page); +diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c +index 73f6bcb..faf00af 100644 +--- a/fs/fuse/inode.c ++++ b/fs/fuse/inode.c +@@ -1026,6 +1026,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) + goto err_fput; + + fuse_conn_init(fc); ++ fc->release = fuse_free_conn; + + fc->dev = sb->s_dev; + fc->sb = sb; +@@ -1040,7 +1041,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) + fc->dont_mask = 1; + sb->s_flags |= MS_POSIXACL; + +- fc->release = fuse_free_conn; + fc->flags = d.flags; + fc->user_id = d.user_id; + fc->group_id = d.group_id; +diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c +index 49436fa..4ccb60d 100644 +--- a/fs/gfs2/aops.c ++++ b/fs/gfs2/aops.c +@@ -517,7 +517,6 @@ int gfs2_internal_read(struct gfs2_inode *ip, char *buf, loff_t *pos, + p = kmap_atomic(page); + memcpy(buf + copied, p + offset, amt); + kunmap_atomic(p); +- mark_page_accessed(page); + page_cache_release(page); + copied += amt; + index++; +diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c +index 5c52418..bc643b9 100644 +--- a/fs/gfs2/inode.c ++++ b/fs/gfs2/inode.c +@@ -606,8 +606,10 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, + if (!IS_ERR(inode)) { + d = d_splice_alias(inode, dentry); + error = PTR_ERR(d); +- if (IS_ERR(d)) ++ if (IS_ERR(d)) { ++ inode = ERR_CAST(d); + goto fail_gunlock; ++ } + error = 0; + if (file) { + if (S_ISREG(inode->i_mode)) { +@@ -823,7 +825,6 @@ static struct dentry *__gfs2_lookup(struct inode *dir, struct dentry *dentry, + + d = d_splice_alias(inode, dentry); + if (IS_ERR(d)) { +- iput(inode); + gfs2_glock_dq_uninit(&gh); + return d; + } +diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c +index c7f2469..e7b1496 100644 +--- a/fs/gfs2/meta_io.c ++++ b/fs/gfs2/meta_io.c +@@ -97,6 +97,11 @@ const struct address_space_operations gfs2_meta_aops = { + .releasepage = gfs2_releasepage, + }; + ++const struct address_space_operations gfs2_rgrp_aops = { ++ .writepage = gfs2_aspace_writepage, ++ .releasepage = gfs2_releasepage, ++}; ++ + /** + * gfs2_getbuf - Get a buffer with a given address space + * @gl: the glock +@@ -131,7 +136,8 @@ struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create) + yield(); + } + } else { +- page = find_lock_page(mapping, index); ++ page = find_get_page_flags(mapping, index, ++ FGP_LOCK|FGP_ACCESSED); + if (!page) + return NULL; + } +@@ -148,7 +154,6 @@ struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create) + map_bh(bh, sdp->sd_vfs, blkno); + + unlock_page(page); +- mark_page_accessed(page); + page_cache_release(page); + + return bh; +diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h +index 4823b93..ac5d802 100644 +--- a/fs/gfs2/meta_io.h ++++ b/fs/gfs2/meta_io.h +@@ -38,12 +38,15 @@ static inline void gfs2_buffer_copy_tail(struct buffer_head *to_bh, + } + + extern const struct address_space_operations gfs2_meta_aops; ++extern const struct address_space_operations gfs2_rgrp_aops; + + static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping) + { + struct inode *inode = mapping->host; + if (mapping->a_ops == &gfs2_meta_aops) + return (((struct gfs2_glock *)mapping) - 1)->gl_sbd; ++ else if (mapping->a_ops == &gfs2_rgrp_aops) ++ return container_of(mapping, struct gfs2_sbd, sd_aspace); + else + return inode->i_sb->s_fs_info; + } +diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c +index c6872d0..f6c9d83 100644 +--- a/fs/gfs2/ops_fstype.c ++++ b/fs/gfs2/ops_fstype.c +@@ -104,7 +104,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) + mapping = &sdp->sd_aspace; + + address_space_init_once(mapping); +- mapping->a_ops = &gfs2_meta_aops; ++ mapping->a_ops = &gfs2_rgrp_aops; + mapping->host = sb->s_bdev->bd_inode; + mapping->flags = 0; + mapping_set_gfp_mask(mapping, GFP_NOFS); +diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c +index 6e560d5..754fdf8 100644 +--- a/fs/hfsplus/brec.c ++++ b/fs/hfsplus/brec.c +@@ -131,13 +131,16 @@ skip: + hfs_bnode_write(node, entry, data_off + key_len, entry_len); + hfs_bnode_dump(node); + +- if (new_node) { +- /* update parent key if we inserted a key +- * at the start of the first node +- */ +- if (!rec && new_node != node) +- hfs_brec_update_parent(fd); ++ /* ++ * update parent key if we inserted a key ++ * at the start of the node and it is not the new node ++ */ ++ if (!rec && new_node != node) { ++ hfs_bnode_read_key(node, fd->search_key, data_off + size); ++ hfs_brec_update_parent(fd); ++ } + ++ if (new_node) { + hfs_bnode_put(fd->bnode); + if (!new_node->parent) { + hfs_btree_inc_height(tree); +@@ -168,9 +171,6 @@ skip: + goto again; + } + +- if (!rec) +- hfs_brec_update_parent(fd); +- + return 0; + } + +@@ -370,6 +370,8 @@ again: + if (IS_ERR(parent)) + return PTR_ERR(parent); + __hfs_brec_find(parent, fd, hfs_find_rec_by_key); ++ if (fd->record < 0) ++ return -ENOENT; + hfs_bnode_dump(parent); + rec = fd->record; + +diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c +index 1b39afd..5f60bb2 100644 +--- a/fs/hpfs/namei.c ++++ b/fs/hpfs/namei.c +@@ -8,6 +8,17 @@ + #include + #include "hpfs_fn.h" + ++static void hpfs_update_directory_times(struct inode *dir) ++{ ++ time_t t = get_seconds(); ++ if (t == dir->i_mtime.tv_sec && ++ t == dir->i_ctime.tv_sec) ++ return; ++ dir->i_mtime.tv_sec = dir->i_ctime.tv_sec = t; ++ dir->i_mtime.tv_nsec = dir->i_ctime.tv_nsec = 0; ++ hpfs_write_inode_nolock(dir); ++} ++ + static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) + { + const unsigned char *name = dentry->d_name.name; +@@ -99,6 +110,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) + result->i_mode = mode | S_IFDIR; + hpfs_write_inode_nolock(result); + } ++ hpfs_update_directory_times(dir); + d_instantiate(dentry, result); + hpfs_unlock(dir->i_sb); + return 0; +@@ -187,6 +199,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, b + result->i_mode = mode | S_IFREG; + hpfs_write_inode_nolock(result); + } ++ hpfs_update_directory_times(dir); + d_instantiate(dentry, result); + hpfs_unlock(dir->i_sb); + return 0; +@@ -262,6 +275,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, de + insert_inode_hash(result); + + hpfs_write_inode_nolock(result); ++ hpfs_update_directory_times(dir); + d_instantiate(dentry, result); + brelse(bh); + hpfs_unlock(dir->i_sb); +@@ -340,6 +354,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy + insert_inode_hash(result); + + hpfs_write_inode_nolock(result); ++ hpfs_update_directory_times(dir); + d_instantiate(dentry, result); + hpfs_unlock(dir->i_sb); + return 0; +@@ -423,6 +438,8 @@ again: + out1: + hpfs_brelse4(&qbh); + out: ++ if (!err) ++ hpfs_update_directory_times(dir); + hpfs_unlock(dir->i_sb); + return err; + } +@@ -477,6 +494,8 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry) + out1: + hpfs_brelse4(&qbh); + out: ++ if (!err) ++ hpfs_update_directory_times(dir); + hpfs_unlock(dir->i_sb); + return err; + } +@@ -595,7 +614,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, + goto end1; + } + +- end: ++end: + hpfs_i(i)->i_parent_dir = new_dir->i_ino; + if (S_ISDIR(i->i_mode)) { + inc_nlink(new_dir); +@@ -610,6 +629,10 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry, + brelse(bh); + } + end1: ++ if (!err) { ++ hpfs_update_directory_times(old_dir); ++ hpfs_update_directory_times(new_dir); ++ } + hpfs_unlock(i->i_sb); + return err; + } +diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c +index 4534ff6..77b583d 100644 +--- a/fs/hpfs/super.c ++++ b/fs/hpfs/super.c +@@ -52,17 +52,20 @@ static void unmark_dirty(struct super_block *s) + } + + /* Filesystem error... */ +-static char err_buf[1024]; +- + void hpfs_error(struct super_block *s, const char *fmt, ...) + { ++ struct va_format vaf; + va_list args; + + va_start(args, fmt); +- vsnprintf(err_buf, sizeof(err_buf), fmt, args); ++ ++ vaf.fmt = fmt; ++ vaf.va = &args; ++ ++ pr_err("filesystem error: %pV", &vaf); ++ + va_end(args); + +- printk("HPFS: filesystem error: %s", err_buf); + if (!hpfs_sb(s)->sb_was_error) { + if (hpfs_sb(s)->sb_err == 2) { + printk("; crashing the system because you wanted it\n"); +diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c +index d19b30a..a4a8ed5 100644 +--- a/fs/hugetlbfs/inode.c ++++ b/fs/hugetlbfs/inode.c +@@ -1017,6 +1017,11 @@ static int __init init_hugetlbfs_fs(void) + int error; + int i; + ++ if (!hugepages_supported()) { ++ pr_info("hugetlbfs: disabling because there are no supported hugepage sizes\n"); ++ return -ENOTSUPP; ++ } ++ + error = bdi_init(&hugetlbfs_backing_dev_info); + if (error) + return error; +diff --git a/fs/inode.c b/fs/inode.c +index e846a32..644875b 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -1631,8 +1631,8 @@ int file_remove_suid(struct file *file) + error = security_inode_killpriv(dentry); + if (!error && killsuid) + error = __remove_suid(dentry, killsuid); +- if (!error && (inode->i_sb->s_flags & MS_NOSEC)) +- inode->i_flags |= S_NOSEC; ++ if (!error) ++ inode_has_no_xattr(inode); + + return error; + } +diff --git a/fs/ioprio.c b/fs/ioprio.c +index e50170c..31666c9 100644 +--- a/fs/ioprio.c ++++ b/fs/ioprio.c +@@ -157,14 +157,16 @@ out: + + int ioprio_best(unsigned short aprio, unsigned short bprio) + { +- unsigned short aclass = IOPRIO_PRIO_CLASS(aprio); +- unsigned short bclass = IOPRIO_PRIO_CLASS(bprio); ++ unsigned short aclass; ++ unsigned short bclass; + +- if (aclass == IOPRIO_CLASS_NONE) +- aclass = IOPRIO_CLASS_BE; +- if (bclass == IOPRIO_CLASS_NONE) +- bclass = IOPRIO_CLASS_BE; ++ if (!ioprio_valid(aprio)) ++ aprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, IOPRIO_NORM); ++ if (!ioprio_valid(bprio)) ++ bprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, IOPRIO_NORM); + ++ aclass = IOPRIO_PRIO_CLASS(aprio); ++ bclass = IOPRIO_PRIO_CLASS(bprio); + if (aclass == bclass) + return min(aprio, bprio); + if (aclass > bclass) +diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c +index 4a9e10e..a9daccb 100644 +--- a/fs/isofs/inode.c ++++ b/fs/isofs/inode.c +@@ -61,7 +61,7 @@ static void isofs_put_super(struct super_block *sb) + return; + } + +-static int isofs_read_inode(struct inode *); ++static int isofs_read_inode(struct inode *, int relocated); + static int isofs_statfs (struct dentry *, struct kstatfs *); + + static struct kmem_cache *isofs_inode_cachep; +@@ -1258,7 +1258,7 @@ out_toomany: + goto out; + } + +-static int isofs_read_inode(struct inode *inode) ++static int isofs_read_inode(struct inode *inode, int relocated) + { + struct super_block *sb = inode->i_sb; + struct isofs_sb_info *sbi = ISOFS_SB(sb); +@@ -1403,7 +1403,7 @@ static int isofs_read_inode(struct inode *inode) + */ + + if (!high_sierra) { +- parse_rock_ridge_inode(de, inode); ++ parse_rock_ridge_inode(de, inode, relocated); + /* if we want uid/gid set, override the rock ridge setting */ + if (sbi->s_uid_set) + inode->i_uid = sbi->s_uid; +@@ -1482,9 +1482,10 @@ static int isofs_iget5_set(struct inode *ino, void *data) + * offset that point to the underlying meta-data for the inode. The + * code below is otherwise similar to the iget() code in + * include/linux/fs.h */ +-struct inode *isofs_iget(struct super_block *sb, +- unsigned long block, +- unsigned long offset) ++struct inode *__isofs_iget(struct super_block *sb, ++ unsigned long block, ++ unsigned long offset, ++ int relocated) + { + unsigned long hashval; + struct inode *inode; +@@ -1506,7 +1507,7 @@ struct inode *isofs_iget(struct super_block *sb, + return ERR_PTR(-ENOMEM); + + if (inode->i_state & I_NEW) { +- ret = isofs_read_inode(inode); ++ ret = isofs_read_inode(inode, relocated); + if (ret < 0) { + iget_failed(inode); + inode = ERR_PTR(ret); +diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h +index 9916723..0ac4c1f 100644 +--- a/fs/isofs/isofs.h ++++ b/fs/isofs/isofs.h +@@ -107,7 +107,7 @@ extern int iso_date(char *, int); + + struct inode; /* To make gcc happy */ + +-extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *); ++extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *, int relocated); + extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *); + extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *); + +@@ -118,9 +118,24 @@ extern struct dentry *isofs_lookup(struct inode *, struct dentry *, unsigned int + extern struct buffer_head *isofs_bread(struct inode *, sector_t); + extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long); + +-extern struct inode *isofs_iget(struct super_block *sb, +- unsigned long block, +- unsigned long offset); ++struct inode *__isofs_iget(struct super_block *sb, ++ unsigned long block, ++ unsigned long offset, ++ int relocated); ++ ++static inline struct inode *isofs_iget(struct super_block *sb, ++ unsigned long block, ++ unsigned long offset) ++{ ++ return __isofs_iget(sb, block, offset, 0); ++} ++ ++static inline struct inode *isofs_iget_reloc(struct super_block *sb, ++ unsigned long block, ++ unsigned long offset) ++{ ++ return __isofs_iget(sb, block, offset, 1); ++} + + /* Because the inode number is no longer relevant to finding the + * underlying meta-data for an inode, we are free to choose a more +diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c +index c0bf424..735d752 100644 +--- a/fs/isofs/rock.c ++++ b/fs/isofs/rock.c +@@ -30,6 +30,7 @@ struct rock_state { + int cont_size; + int cont_extent; + int cont_offset; ++ int cont_loops; + struct inode *inode; + }; + +@@ -73,6 +74,9 @@ static void init_rock_state(struct rock_state *rs, struct inode *inode) + rs->inode = inode; + } + ++/* Maximum number of Rock Ridge continuation entries */ ++#define RR_MAX_CE_ENTRIES 32 ++ + /* + * Returns 0 if the caller should continue scanning, 1 if the scan must end + * and -ve on error. +@@ -105,6 +109,8 @@ static int rock_continue(struct rock_state *rs) + goto out; + } + ret = -EIO; ++ if (++rs->cont_loops >= RR_MAX_CE_ENTRIES) ++ goto out; + bh = sb_bread(rs->inode->i_sb, rs->cont_extent); + if (bh) { + memcpy(rs->buffer, bh->b_data + rs->cont_offset, +@@ -288,12 +294,16 @@ eio: + goto out; + } + ++#define RR_REGARD_XA 1 ++#define RR_RELOC_DE 2 ++ + static int + parse_rock_ridge_inode_internal(struct iso_directory_record *de, +- struct inode *inode, int regard_xa) ++ struct inode *inode, int flags) + { + int symlink_len = 0; + int cnt, sig; ++ unsigned int reloc_block; + struct inode *reloc; + struct rock_ridge *rr; + int rootflag; +@@ -305,7 +315,7 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de, + + init_rock_state(&rs, inode); + setup_rock_ridge(de, inode, &rs); +- if (regard_xa) { ++ if (flags & RR_REGARD_XA) { + rs.chr += 14; + rs.len -= 14; + if (rs.len < 0) +@@ -352,6 +362,9 @@ repeat: + rs.cont_size = isonum_733(rr->u.CE.size); + break; + case SIG('E', 'R'): ++ /* Invalid length of ER tag id? */ ++ if (rr->u.ER.len_id + offsetof(struct rock_ridge, u.ER.data) > rr->len) ++ goto out; + ISOFS_SB(inode->i_sb)->s_rock = 1; + printk(KERN_DEBUG "ISO 9660 Extensions: "); + { +@@ -485,12 +498,22 @@ repeat: + "relocated directory\n"); + goto out; + case SIG('C', 'L'): +- ISOFS_I(inode)->i_first_extent = +- isonum_733(rr->u.CL.location); +- reloc = +- isofs_iget(inode->i_sb, +- ISOFS_I(inode)->i_first_extent, +- 0); ++ if (flags & RR_RELOC_DE) { ++ printk(KERN_ERR ++ "ISOFS: Recursive directory relocation " ++ "is not supported\n"); ++ goto eio; ++ } ++ reloc_block = isonum_733(rr->u.CL.location); ++ if (reloc_block == ISOFS_I(inode)->i_iget5_block && ++ ISOFS_I(inode)->i_iget5_offset == 0) { ++ printk(KERN_ERR ++ "ISOFS: Directory relocation points to " ++ "itself\n"); ++ goto eio; ++ } ++ ISOFS_I(inode)->i_first_extent = reloc_block; ++ reloc = isofs_iget_reloc(inode->i_sb, reloc_block, 0); + if (IS_ERR(reloc)) { + ret = PTR_ERR(reloc); + goto out; +@@ -637,9 +660,11 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit) + return rpnt; + } + +-int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode) ++int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode, ++ int relocated) + { +- int result = parse_rock_ridge_inode_internal(de, inode, 0); ++ int flags = relocated ? RR_RELOC_DE : 0; ++ int result = parse_rock_ridge_inode_internal(de, inode, flags); + + /* + * if rockridge flag was reset and we didn't look for attributes +@@ -647,7 +672,8 @@ int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode) + */ + if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1) + && (ISOFS_SB(inode->i_sb)->s_rock == 2)) { +- result = parse_rock_ridge_inode_internal(de, inode, 14); ++ result = parse_rock_ridge_inode_internal(de, inode, ++ flags | RR_REGARD_XA); + } + return result; + } +diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c +index 7f34f47..b892355 100644 +--- a/fs/jbd2/checkpoint.c ++++ b/fs/jbd2/checkpoint.c +@@ -448,7 +448,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal) + unsigned long blocknr; + + if (is_journal_aborted(journal)) +- return 1; ++ return -EIO; + + if (!jbd2_journal_get_log_tail(journal, &first_tid, &blocknr)) + return 1; +@@ -463,10 +463,9 @@ int jbd2_cleanup_journal_tail(journal_t *journal) + * jbd2_cleanup_journal_tail() doesn't get called all that often. + */ + if (journal->j_flags & JBD2_BARRIER) +- blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); ++ blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL); + +- __jbd2_update_log_tail(journal, first_tid, blocknr); +- return 0; ++ return __jbd2_update_log_tail(journal, first_tid, blocknr); + } + + +diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c +index cf2fc05..9181c2b 100644 +--- a/fs/jbd2/commit.c ++++ b/fs/jbd2/commit.c +@@ -97,7 +97,7 @@ static void jbd2_commit_block_csum_set(journal_t *j, struct buffer_head *bh) + struct commit_header *h; + __u32 csum; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return; + + h = (struct commit_header *)(bh->b_data); +@@ -313,11 +313,11 @@ static __u32 jbd2_checksum_data(__u32 crc32_sum, struct buffer_head *bh) + return checksum; + } + +-static void write_tag_block(int tag_bytes, journal_block_tag_t *tag, ++static void write_tag_block(journal_t *j, journal_block_tag_t *tag, + unsigned long long block) + { + tag->t_blocknr = cpu_to_be32(block & (u32)~0); +- if (tag_bytes > JBD2_TAG_SIZE32) ++ if (JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_64BIT)) + tag->t_blocknr_high = cpu_to_be32((block >> 31) >> 1); + } + +@@ -327,7 +327,7 @@ static void jbd2_descr_block_csum_set(journal_t *j, + struct jbd2_journal_block_tail *tail; + __u32 csum; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return; + + tail = (struct jbd2_journal_block_tail *)(bh->b_data + j->j_blocksize - +@@ -340,12 +340,13 @@ static void jbd2_descr_block_csum_set(journal_t *j, + static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag, + struct buffer_head *bh, __u32 sequence) + { ++ journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag; + struct page *page = bh->b_page; + __u8 *addr; + __u32 csum32; + __be32 seq; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return; + + seq = cpu_to_be32(sequence); +@@ -355,8 +356,10 @@ static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag, + bh->b_size); + kunmap_atomic(addr); + +- /* We only have space to store the lower 16 bits of the crc32c. */ +- tag->t_checksum = cpu_to_be16(csum32); ++ if (JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V3)) ++ tag3->t_checksum = cpu_to_be32(csum32); ++ else ++ tag->t_checksum = cpu_to_be16(csum32); + } + /* + * jbd2_journal_commit_transaction +@@ -396,7 +399,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) + LIST_HEAD(io_bufs); + LIST_HEAD(log_bufs); + +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (jbd2_journal_has_csum_v2or3(journal)) + csum_size = sizeof(struct jbd2_journal_block_tail); + + /* +@@ -692,7 +695,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) + tag_flag |= JBD2_FLAG_SAME_UUID; + + tag = (journal_block_tag_t *) tagp; +- write_tag_block(tag_bytes, tag, jh2bh(jh)->b_blocknr); ++ write_tag_block(journal, tag, jh2bh(jh)->b_blocknr); + tag->t_flags = cpu_to_be16(tag_flag); + jbd2_block_tag_csum_set(journal, tag, wbuf[bufs], + commit_transaction->t_tid); +diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c +index 5fa344a..e8d62d7 100644 +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -124,7 +124,7 @@ EXPORT_SYMBOL(__jbd2_debug); + /* Checksumming functions */ + int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb) + { +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return 1; + + return sb->s_checksum_type == JBD2_CRC32C_CHKSUM; +@@ -145,7 +145,7 @@ static __be32 jbd2_superblock_csum(journal_t *j, journal_superblock_t *sb) + + int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb) + { +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return 1; + + return sb->s_checksum == jbd2_superblock_csum(j, sb); +@@ -153,7 +153,7 @@ int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb) + + void jbd2_superblock_csum_set(journal_t *j, journal_superblock_t *sb) + { +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return; + + sb->s_checksum = jbd2_superblock_csum(j, sb); +@@ -885,9 +885,10 @@ int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid, + * + * Requires j_checkpoint_mutex + */ +-void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) ++int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) + { + unsigned long freed; ++ int ret; + + BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); + +@@ -897,7 +898,10 @@ void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) + * space and if we lose sb update during power failure we'd replay + * old transaction with possibly newly overwritten data. + */ +- jbd2_journal_update_sb_log_tail(journal, tid, block, WRITE_FUA); ++ ret = jbd2_journal_update_sb_log_tail(journal, tid, block, WRITE_FUA); ++ if (ret) ++ goto out; ++ + write_lock(&journal->j_state_lock); + freed = block - journal->j_tail; + if (block < journal->j_tail) +@@ -913,6 +917,9 @@ void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) + journal->j_tail_sequence = tid; + journal->j_tail = block; + write_unlock(&journal->j_state_lock); ++ ++out: ++ return ret; + } + + /* +@@ -1331,7 +1338,7 @@ static int journal_reset(journal_t *journal) + return jbd2_journal_start_thread(journal); + } + +-static void jbd2_write_superblock(journal_t *journal, int write_op) ++static int jbd2_write_superblock(journal_t *journal, int write_op) + { + struct buffer_head *bh = journal->j_sb_buffer; + journal_superblock_t *sb = journal->j_superblock; +@@ -1370,7 +1377,10 @@ static void jbd2_write_superblock(journal_t *journal, int write_op) + printk(KERN_ERR "JBD2: Error %d detected when updating " + "journal superblock for %s.\n", ret, + journal->j_devname); ++ jbd2_journal_abort(journal, ret); + } ++ ++ return ret; + } + + /** +@@ -1383,10 +1393,11 @@ static void jbd2_write_superblock(journal_t *journal, int write_op) + * Update a journal's superblock information about log tail and write it to + * disk, waiting for the IO to complete. + */ +-void jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid, ++int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid, + unsigned long tail_block, int write_op) + { + journal_superblock_t *sb = journal->j_superblock; ++ int ret; + + BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); + jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n", +@@ -1395,13 +1406,18 @@ void jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid, + sb->s_sequence = cpu_to_be32(tail_tid); + sb->s_start = cpu_to_be32(tail_block); + +- jbd2_write_superblock(journal, write_op); ++ ret = jbd2_write_superblock(journal, write_op); ++ if (ret) ++ goto out; + + /* Log is no longer empty */ + write_lock(&journal->j_state_lock); + WARN_ON(!sb->s_sequence); + journal->j_flags &= ~JBD2_FLUSHED; + write_unlock(&journal->j_state_lock); ++ ++out: ++ return ret; + } + + /** +@@ -1522,21 +1538,29 @@ static int journal_get_superblock(journal_t *journal) + goto out; + } + +- if (JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM) && +- JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) { ++ if (jbd2_journal_has_csum_v2or3(journal) && ++ JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM)) { + /* Can't have checksum v1 and v2 on at the same time! */ + printk(KERN_ERR "JBD2: Can't enable checksumming v1 and v2 " + "at the same time!\n"); + goto out; + } + ++ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2) && ++ JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3)) { ++ /* Can't have checksum v2 and v3 at the same time! */ ++ printk(KERN_ERR "JBD2: Can't enable checksumming v2 and v3 " ++ "at the same time!\n"); ++ goto out; ++ } ++ + if (!jbd2_verify_csum_type(journal, sb)) { + printk(KERN_ERR "JBD2: Unknown checksum type\n"); + goto out; + } + + /* Load the checksum driver */ +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) { ++ if (jbd2_journal_has_csum_v2or3(journal)) { + journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0); + if (IS_ERR(journal->j_chksum_driver)) { + printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n"); +@@ -1553,7 +1577,7 @@ static int journal_get_superblock(journal_t *journal) + } + + /* Precompute checksum seed for all metadata */ +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (jbd2_journal_has_csum_v2or3(journal)) + journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid, + sizeof(sb->s_uuid)); + +@@ -1813,8 +1837,14 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, + if (!jbd2_journal_check_available_features(journal, compat, ro, incompat)) + return 0; + +- /* Asking for checksumming v2 and v1? Only give them v2. */ +- if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V2 && ++ /* If enabling v2 checksums, turn on v3 instead */ ++ if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V2) { ++ incompat &= ~JBD2_FEATURE_INCOMPAT_CSUM_V2; ++ incompat |= JBD2_FEATURE_INCOMPAT_CSUM_V3; ++ } ++ ++ /* Asking for checksumming v3 and v1? Only give them v3. */ ++ if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V3 && + compat & JBD2_FEATURE_COMPAT_CHECKSUM) + compat &= ~JBD2_FEATURE_COMPAT_CHECKSUM; + +@@ -1823,8 +1853,8 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, + + sb = journal->j_superblock; + +- /* If enabling v2 checksums, update superblock */ +- if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V2)) { ++ /* If enabling v3 checksums, update superblock */ ++ if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) { + sb->s_checksum_type = JBD2_CRC32C_CHKSUM; + sb->s_feature_compat &= + ~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM); +@@ -1842,8 +1872,7 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, + } + + /* Precompute checksum seed for all metadata */ +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, +- JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (jbd2_journal_has_csum_v2or3(journal)) + journal->j_csum_seed = jbd2_chksum(journal, ~0, + sb->s_uuid, + sizeof(sb->s_uuid)); +@@ -1852,7 +1881,8 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, + /* If enabling v1 checksums, downgrade superblock */ + if (COMPAT_FEATURE_ON(JBD2_FEATURE_COMPAT_CHECKSUM)) + sb->s_feature_incompat &= +- ~cpu_to_be32(JBD2_FEATURE_INCOMPAT_CSUM_V2); ++ ~cpu_to_be32(JBD2_FEATURE_INCOMPAT_CSUM_V2 | ++ JBD2_FEATURE_INCOMPAT_CSUM_V3); + + sb->s_feature_compat |= cpu_to_be32(compat); + sb->s_feature_ro_compat |= cpu_to_be32(ro); +@@ -1938,7 +1968,14 @@ int jbd2_journal_flush(journal_t *journal) + return -EIO; + + mutex_lock(&journal->j_checkpoint_mutex); +- jbd2_cleanup_journal_tail(journal); ++ if (!err) { ++ err = jbd2_cleanup_journal_tail(journal); ++ if (err < 0) { ++ mutex_unlock(&journal->j_checkpoint_mutex); ++ goto out; ++ } ++ err = 0; ++ } + + /* Finally, mark the journal as really needing no recovery. + * This sets s_start==0 in the underlying superblock, which is +@@ -1954,7 +1991,8 @@ int jbd2_journal_flush(journal_t *journal) + J_ASSERT(journal->j_head == journal->j_tail); + J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence); + write_unlock(&journal->j_state_lock); +- return 0; ++out: ++ return err; + } + + /** +@@ -2165,16 +2203,20 @@ int jbd2_journal_blocks_per_page(struct inode *inode) + */ + size_t journal_tag_bytes(journal_t *journal) + { +- journal_block_tag_t tag; +- size_t x = 0; ++ size_t sz; ++ ++ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3)) ++ return sizeof(journal_block_tag3_t); ++ ++ sz = sizeof(journal_block_tag_t); + + if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) +- x += sizeof(tag.t_checksum); ++ sz += sizeof(__u16); + + if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) +- return x + JBD2_TAG_SIZE64; ++ return sz; + else +- return x + JBD2_TAG_SIZE32; ++ return sz - sizeof(__u32); + } + + /* +diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c +index 3b6bb19..a5f72a3 100644 +--- a/fs/jbd2/recovery.c ++++ b/fs/jbd2/recovery.c +@@ -181,7 +181,7 @@ static int jbd2_descr_block_csum_verify(journal_t *j, + __be32 provided; + __u32 calculated; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return 1; + + tail = (struct jbd2_journal_block_tail *)(buf + j->j_blocksize - +@@ -205,7 +205,7 @@ static int count_tags(journal_t *journal, struct buffer_head *bh) + int nr = 0, size = journal->j_blocksize; + int tag_bytes = journal_tag_bytes(journal); + +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (jbd2_journal_has_csum_v2or3(journal)) + size -= sizeof(struct jbd2_journal_block_tail); + + tagp = &bh->b_data[sizeof(journal_header_t)]; +@@ -338,10 +338,11 @@ int jbd2_journal_skip_recovery(journal_t *journal) + return err; + } + +-static inline unsigned long long read_tag_block(int tag_bytes, journal_block_tag_t *tag) ++static inline unsigned long long read_tag_block(journal_t *journal, ++ journal_block_tag_t *tag) + { + unsigned long long block = be32_to_cpu(tag->t_blocknr); +- if (tag_bytes > JBD2_TAG_SIZE32) ++ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) + block |= (u64)be32_to_cpu(tag->t_blocknr_high) << 32; + return block; + } +@@ -384,7 +385,7 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf) + __be32 provided; + __u32 calculated; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return 1; + + h = buf; +@@ -399,17 +400,21 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf) + static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag, + void *buf, __u32 sequence) + { ++ journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag; + __u32 csum32; + __be32 seq; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return 1; + + seq = cpu_to_be32(sequence); + csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq)); + csum32 = jbd2_chksum(j, csum32, buf, j->j_blocksize); + +- return tag->t_checksum == cpu_to_be16(csum32); ++ if (JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V3)) ++ return tag3->t_checksum == cpu_to_be32(csum32); ++ else ++ return tag->t_checksum == cpu_to_be16(csum32); + } + + static int do_one_pass(journal_t *journal, +@@ -426,6 +431,7 @@ static int do_one_pass(journal_t *journal, + int tag_bytes = journal_tag_bytes(journal); + __u32 crc32_sum = ~0; /* Transactional Checksums */ + int descr_csum_size = 0; ++ int block_error = 0; + + /* + * First thing is to establish what we expect to find in the log +@@ -512,14 +518,14 @@ static int do_one_pass(journal_t *journal, + switch(blocktype) { + case JBD2_DESCRIPTOR_BLOCK: + /* Verify checksum first */ +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, +- JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (jbd2_journal_has_csum_v2or3(journal)) + descr_csum_size = + sizeof(struct jbd2_journal_block_tail); + if (descr_csum_size > 0 && + !jbd2_descr_block_csum_verify(journal, + bh->b_data)) { + err = -EIO; ++ brelse(bh); + goto failed; + } + +@@ -574,7 +580,7 @@ static int do_one_pass(journal_t *journal, + unsigned long long blocknr; + + J_ASSERT(obh != NULL); +- blocknr = read_tag_block(tag_bytes, ++ blocknr = read_tag_block(journal, + tag); + + /* If the block has been +@@ -598,7 +604,8 @@ static int do_one_pass(journal_t *journal, + "checksum recovering " + "block %llu in log\n", + blocknr); +- continue; ++ block_error = 1; ++ goto skip_write; + } + + /* Find a buffer for the new +@@ -797,7 +804,8 @@ static int do_one_pass(journal_t *journal, + success = -EIO; + } + } +- ++ if (block_error && success == 0) ++ success = -EIO; + return success; + + failed: +@@ -811,7 +819,7 @@ static int jbd2_revoke_block_csum_verify(journal_t *j, + __be32 provided; + __u32 calculated; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return 1; + + tail = (struct jbd2_journal_revoke_tail *)(buf + j->j_blocksize - +@@ -831,15 +839,23 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh, + { + jbd2_journal_revoke_header_t *header; + int offset, max; ++ int csum_size = 0; ++ __u32 rcount; + int record_len = 4; + + header = (jbd2_journal_revoke_header_t *) bh->b_data; + offset = sizeof(jbd2_journal_revoke_header_t); +- max = be32_to_cpu(header->r_count); ++ rcount = be32_to_cpu(header->r_count); + + if (!jbd2_revoke_block_csum_verify(journal, header)) + return -EINVAL; + ++ if (jbd2_journal_has_csum_v2or3(journal)) ++ csum_size = sizeof(struct jbd2_journal_revoke_tail); ++ if (rcount > journal->j_blocksize - csum_size) ++ return -EINVAL; ++ max = rcount; ++ + if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) + record_len = 8; + +diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c +index 198c9c1..8ecf9b9 100644 +--- a/fs/jbd2/revoke.c ++++ b/fs/jbd2/revoke.c +@@ -91,8 +91,8 @@ + #include + #include + #include +-#endif + #include ++#endif + + static struct kmem_cache *jbd2_revoke_record_cache; + static struct kmem_cache *jbd2_revoke_table_cache; +@@ -583,7 +583,7 @@ static void write_one_revoke_record(journal_t *journal, + { + int csum_size = 0; + struct buffer_head *descriptor; +- int offset; ++ int sz, offset; + journal_header_t *header; + + /* If we are already aborting, this all becomes a noop. We +@@ -597,12 +597,17 @@ static void write_one_revoke_record(journal_t *journal, + offset = *offsetp; + + /* Do we need to leave space at the end for a checksum? */ +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (jbd2_journal_has_csum_v2or3(journal)) + csum_size = sizeof(struct jbd2_journal_revoke_tail); + ++ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) ++ sz = 8; ++ else ++ sz = 4; ++ + /* Make sure we have a descriptor with space left for the record */ + if (descriptor) { +- if (offset >= journal->j_blocksize - csum_size) { ++ if (offset + sz > journal->j_blocksize - csum_size) { + flush_descriptor(journal, descriptor, offset, write_op); + descriptor = NULL; + } +@@ -625,16 +630,13 @@ static void write_one_revoke_record(journal_t *journal, + *descriptorp = descriptor; + } + +- if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) { ++ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) + * ((__be64 *)(&descriptor->b_data[offset])) = + cpu_to_be64(record->blocknr); +- offset += 8; +- +- } else { ++ else + * ((__be32 *)(&descriptor->b_data[offset])) = + cpu_to_be32(record->blocknr); +- offset += 4; +- } ++ offset += sz; + + *offsetp = offset; + } +@@ -644,7 +646,7 @@ static void jbd2_revoke_csum_set(journal_t *j, struct buffer_head *bh) + struct jbd2_journal_revoke_tail *tail; + __u32 csum; + +- if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) ++ if (!jbd2_journal_has_csum_v2or3(j)) + return; + + tail = (struct jbd2_journal_revoke_tail *)(bh->b_data + j->j_blocksize - +diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c +index f8a5d6a..ecc5707 100644 +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -551,7 +551,6 @@ int jbd2_journal_extend(handle_t *handle, int nblocks) + int result; + int wanted; + +- WARN_ON(!transaction); + if (is_handle_aborted(handle)) + return -EROFS; + journal = transaction->t_journal; +@@ -627,7 +626,6 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask) + tid_t tid; + int need_to_start, ret; + +- WARN_ON(!transaction); + /* If we've had an abort of any type, don't even think about + * actually doing the restart! */ + if (is_handle_aborted(handle)) +@@ -791,7 +789,6 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, + int need_copy = 0; + unsigned long start_lock, time_lock; + +- WARN_ON(!transaction); + if (is_handle_aborted(handle)) + return -EROFS; + journal = transaction->t_journal; +@@ -1057,7 +1054,6 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh) + int err; + + jbd_debug(5, "journal_head %p\n", jh); +- WARN_ON(!transaction); + err = -EROFS; + if (is_handle_aborted(handle)) + goto out; +@@ -1271,7 +1267,6 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) + struct journal_head *jh; + int ret = 0; + +- WARN_ON(!transaction); + if (is_handle_aborted(handle)) + return -EROFS; + journal = transaction->t_journal; +@@ -1407,7 +1402,6 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh) + int err = 0; + int was_modified = 0; + +- WARN_ON(!transaction); + if (is_handle_aborted(handle)) + return -EROFS; + journal = transaction->t_journal; +@@ -1538,8 +1532,22 @@ int jbd2_journal_stop(handle_t *handle) + tid_t tid; + pid_t pid; + +- if (!transaction) +- goto free_and_exit; ++ if (!transaction) { ++ /* ++ * Handle is already detached from the transaction so ++ * there is nothing to do other than decrease a refcount, ++ * or free the handle if refcount drops to zero ++ */ ++ if (--handle->h_ref > 0) { ++ jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1, ++ handle->h_ref); ++ return err; ++ } else { ++ if (handle->h_rsv_handle) ++ jbd2_free_handle(handle->h_rsv_handle); ++ goto free_and_exit; ++ } ++ } + journal = transaction->t_journal; + + J_ASSERT(journal_current_handle() == handle); +@@ -2381,7 +2389,6 @@ int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode) + transaction_t *transaction = handle->h_transaction; + journal_t *journal; + +- WARN_ON(!transaction); + if (is_handle_aborted(handle)) + return -EROFS; + journal = transaction->t_journal; +diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c +index a69e426..5b234db 100644 +--- a/fs/jffs2/fs.c ++++ b/fs/jffs2/fs.c +@@ -687,7 +687,7 @@ unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, + struct inode *inode = OFNI_EDONI_2SFFJ(f); + struct page *pg; + +- pg = read_cache_page_async(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, ++ pg = read_cache_page(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, + (void *)jffs2_do_readpage_unlock, inode); + if (IS_ERR(pg)) + return (void *)pg; +diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h +index 413ef89..046fee8 100644 +--- a/fs/jffs2/jffs2_fs_sb.h ++++ b/fs/jffs2/jffs2_fs_sb.h +@@ -134,8 +134,6 @@ struct jffs2_sb_info { + struct rw_semaphore wbuf_sem; /* Protects the write buffer */ + + struct delayed_work wbuf_dwork; /* write-buffer write-out work */ +- int wbuf_queued; /* non-zero delayed work is queued */ +- spinlock_t wbuf_dwork_lock; /* protects wbuf_dwork and and wbuf_queued */ + + unsigned char *oobbuf; + int oobavail; /* How many bytes are available for JFFS2 in OOB */ +diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c +index 7654e87..9ad5ba4 100644 +--- a/fs/jffs2/scan.c ++++ b/fs/jffs2/scan.c +@@ -510,6 +510,10 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo + sumlen = c->sector_size - je32_to_cpu(sm->offset); + sumptr = buf + buf_size - sumlen; + ++ /* sm->offset maybe wrong but MAGIC maybe right */ ++ if (sumlen > c->sector_size) ++ goto full_scan; ++ + /* Now, make sure the summary itself is available */ + if (sumlen > buf_size) { + /* Need to kmalloc for this. */ +@@ -544,6 +548,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo + } + } + ++full_scan: + buf_ofs = jeb->offset; + + if (!buf_size) { +diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c +index a6597d6..09ed551 100644 +--- a/fs/jffs2/wbuf.c ++++ b/fs/jffs2/wbuf.c +@@ -1162,10 +1162,6 @@ static void delayed_wbuf_sync(struct work_struct *work) + struct jffs2_sb_info *c = work_to_sb(work); + struct super_block *sb = OFNI_BS_2SFFJ(c); + +- spin_lock(&c->wbuf_dwork_lock); +- c->wbuf_queued = 0; +- spin_unlock(&c->wbuf_dwork_lock); +- + if (!(sb->s_flags & MS_RDONLY)) { + jffs2_dbg(1, "%s()\n", __func__); + jffs2_flush_wbuf_gc(c, 0); +@@ -1180,14 +1176,9 @@ void jffs2_dirty_trigger(struct jffs2_sb_info *c) + if (sb->s_flags & MS_RDONLY) + return; + +- spin_lock(&c->wbuf_dwork_lock); +- if (!c->wbuf_queued) { ++ delay = msecs_to_jiffies(dirty_writeback_interval * 10); ++ if (queue_delayed_work(system_long_wq, &c->wbuf_dwork, delay)) + jffs2_dbg(1, "%s()\n", __func__); +- delay = msecs_to_jiffies(dirty_writeback_interval * 10); +- queue_delayed_work(system_long_wq, &c->wbuf_dwork, delay); +- c->wbuf_queued = 1; +- } +- spin_unlock(&c->wbuf_dwork_lock); + } + + int jffs2_nand_flash_setup(struct jffs2_sb_info *c) +@@ -1211,7 +1202,6 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c) + + /* Initialise write buffer */ + init_rwsem(&c->wbuf_sem); +- spin_lock_init(&c->wbuf_dwork_lock); + INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync); + c->wbuf_pagesize = c->mtd->writesize; + c->wbuf_ofs = 0xFFFFFFFF; +@@ -1251,7 +1241,6 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) { + + /* Initialize write buffer */ + init_rwsem(&c->wbuf_sem); +- spin_lock_init(&c->wbuf_dwork_lock); + INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync); + c->wbuf_pagesize = c->mtd->erasesize; + +@@ -1311,7 +1300,6 @@ int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) { + + /* Initialize write buffer */ + init_rwsem(&c->wbuf_sem); +- spin_lock_init(&c->wbuf_dwork_lock); + INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync); + + c->wbuf_pagesize = c->mtd->writesize; +@@ -1346,7 +1334,6 @@ int jffs2_ubivol_setup(struct jffs2_sb_info *c) { + return 0; + + init_rwsem(&c->wbuf_sem); +- spin_lock_init(&c->wbuf_dwork_lock); + INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync); + + c->wbuf_pagesize = c->mtd->writesize; +diff --git a/fs/libfs.c b/fs/libfs.c +index a184424..868c0b7 100644 +--- a/fs/libfs.c ++++ b/fs/libfs.c +@@ -113,18 +113,18 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence) + + spin_lock(&dentry->d_lock); + /* d_lock not required for cursor */ +- list_del(&cursor->d_u.d_child); ++ list_del(&cursor->d_child); + p = dentry->d_subdirs.next; + while (n && p != &dentry->d_subdirs) { + struct dentry *next; +- next = list_entry(p, struct dentry, d_u.d_child); ++ next = list_entry(p, struct dentry, d_child); + spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED); + if (simple_positive(next)) + n--; + spin_unlock(&next->d_lock); + p = p->next; + } +- list_add_tail(&cursor->d_u.d_child, p); ++ list_add_tail(&cursor->d_child, p); + spin_unlock(&dentry->d_lock); + } + } +@@ -149,7 +149,7 @@ int dcache_readdir(struct file *file, struct dir_context *ctx) + { + struct dentry *dentry = file->f_path.dentry; + struct dentry *cursor = file->private_data; +- struct list_head *p, *q = &cursor->d_u.d_child; ++ struct list_head *p, *q = &cursor->d_child; + + if (!dir_emit_dots(file, ctx)) + return 0; +@@ -158,7 +158,7 @@ int dcache_readdir(struct file *file, struct dir_context *ctx) + list_move(q, &dentry->d_subdirs); + + for (p = q->next; p != &dentry->d_subdirs; p = p->next) { +- struct dentry *next = list_entry(p, struct dentry, d_u.d_child); ++ struct dentry *next = list_entry(p, struct dentry, d_child); + spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED); + if (!simple_positive(next)) { + spin_unlock(&next->d_lock); +@@ -286,7 +286,7 @@ int simple_empty(struct dentry *dentry) + int ret = 0; + + spin_lock(&dentry->d_lock); +- list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) { ++ list_for_each_entry(child, &dentry->d_subdirs, d_child) { + spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED); + if (simple_positive(child)) { + spin_unlock(&child->d_lock); +diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c +index 1812f02..6ae664b 100644 +--- a/fs/lockd/mon.c ++++ b/fs/lockd/mon.c +@@ -159,6 +159,12 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, + + msg.rpc_proc = &clnt->cl_procinfo[proc]; + status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN); ++ if (status == -ECONNREFUSED) { ++ dprintk("lockd: NSM upcall RPC failed, status=%d, forcing rebind\n", ++ status); ++ rpc_force_rebind(clnt); ++ status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN); ++ } + if (status < 0) + dprintk("lockd: NSM upcall RPC failed, status=%d\n", + status); +diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c +index 6bf06a0..59a53f6 100644 +--- a/fs/lockd/svc.c ++++ b/fs/lockd/svc.c +@@ -137,10 +137,6 @@ lockd(void *vrqstp) + + dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n"); + +- if (!nlm_timeout) +- nlm_timeout = LOCKD_DFLT_TIMEO; +- nlmsvc_timeout = nlm_timeout * HZ; +- + /* + * The main request loop. We don't terminate until the last + * NFS mount or NFS daemon has gone away. +@@ -253,13 +249,11 @@ static int lockd_up_net(struct svc_serv *serv, struct net *net) + + error = make_socks(serv, net); + if (error < 0) +- goto err_socks; ++ goto err_bind; + set_grace_period(net); + dprintk("lockd_up_net: per-net data created; net=%p\n", net); + return 0; + +-err_socks: +- svc_rpcb_cleanup(serv, net); + err_bind: + ln->nlmsvc_users--; + return error; +@@ -348,6 +342,10 @@ static struct svc_serv *lockd_create_svc(void) + printk(KERN_WARNING + "lockd_up: no pid, %d users??\n", nlmsvc_users); + ++ if (!nlm_timeout) ++ nlm_timeout = LOCKD_DFLT_TIMEO; ++ nlmsvc_timeout = nlm_timeout * HZ; ++ + serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL); + if (!serv) { + printk(KERN_WARNING "lockd_up: create service failed\n"); +diff --git a/fs/locks.c b/fs/locks.c +index 4dd39b9..2c61c4e 100644 +--- a/fs/locks.c ++++ b/fs/locks.c +@@ -2235,16 +2235,28 @@ void locks_remove_flock(struct file *filp) + + while ((fl = *before) != NULL) { + if (fl->fl_file == filp) { +- if (IS_FLOCK(fl)) { +- locks_delete_lock(before); +- continue; +- } + if (IS_LEASE(fl)) { + lease_modify(before, F_UNLCK); + continue; + } +- /* What? */ +- BUG(); ++ ++ /* ++ * There's a leftover lock on the list of a type that ++ * we didn't expect to see. Most likely a classic ++ * POSIX lock that ended up not getting released ++ * properly, or that raced onto the list somehow. Log ++ * some info about it and then just remove it from ++ * the list. ++ */ ++ WARN(!IS_FLOCK(fl), ++ "leftover lock: dev=%u:%u ino=%lu type=%hhd flags=0x%x start=%lld end=%lld\n", ++ MAJOR(inode->i_sb->s_dev), ++ MINOR(inode->i_sb->s_dev), inode->i_ino, ++ fl->fl_type, fl->fl_flags, ++ fl->fl_start, fl->fl_end); ++ ++ locks_delete_lock(before); ++ continue; + } + before = &fl->fl_next; + } +diff --git a/fs/namei.c b/fs/namei.c +index 8274c8d..c6fa079 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include + + #include "internal.h" +@@ -641,24 +642,22 @@ static int complete_walk(struct nameidata *nd) + + static __always_inline void set_root(struct nameidata *nd) + { +- if (!nd->root.mnt) +- get_fs_root(current->fs, &nd->root); ++ get_fs_root(current->fs, &nd->root); + } + + static int link_path_walk(const char *, struct nameidata *); + +-static __always_inline void set_root_rcu(struct nameidata *nd) ++static __always_inline unsigned set_root_rcu(struct nameidata *nd) + { +- if (!nd->root.mnt) { +- struct fs_struct *fs = current->fs; +- unsigned seq; ++ struct fs_struct *fs = current->fs; ++ unsigned seq, res; + +- do { +- seq = read_seqcount_begin(&fs->seq); +- nd->root = fs->root; +- nd->seq = __read_seqcount_begin(&nd->root.dentry->d_seq); +- } while (read_seqcount_retry(&fs->seq, seq)); +- } ++ do { ++ seq = read_seqcount_begin(&fs->seq); ++ nd->root = fs->root; ++ res = __read_seqcount_begin(&nd->root.dentry->d_seq); ++ } while (read_seqcount_retry(&fs->seq, seq)); ++ return res; + } + + static void path_put_conditional(struct path *path, struct nameidata *nd) +@@ -858,7 +857,8 @@ follow_link(struct path *link, struct nameidata *nd, void **p) + return PTR_ERR(s); + } + if (*s == '/') { +- set_root(nd); ++ if (!nd->root.mnt) ++ set_root(nd); + path_put(&nd->path); + nd->path = nd->root; + path_get(&nd->root); +@@ -1131,7 +1131,8 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, + + static int follow_dotdot_rcu(struct nameidata *nd) + { +- set_root_rcu(nd); ++ if (!nd->root.mnt) ++ set_root_rcu(nd); + + while (1) { + if (nd->path.dentry == nd->root.dentry && +@@ -1243,7 +1244,8 @@ static void follow_mount(struct path *path) + + static void follow_dotdot(struct nameidata *nd) + { +- set_root(nd); ++ if (!nd->root.mnt) ++ set_root(nd); + + while(1) { + struct dentry *old = nd->path.dentry; +@@ -1543,7 +1545,8 @@ static inline int walk_component(struct nameidata *nd, struct path *path, + + if (should_follow_link(path->dentry, follow)) { + if (nd->flags & LOOKUP_RCU) { +- if (unlikely(unlazy_walk(nd, path->dentry))) { ++ if (unlikely(nd->path.mnt != path->mnt || ++ unlazy_walk(nd, path->dentry))) { + err = -ECHILD; + goto out_err; + } +@@ -1624,8 +1627,7 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd) + + static inline unsigned int fold_hash(unsigned long hash) + { +- hash += hash >> (8*sizeof(int)); +- return hash; ++ return hash_64(hash, 32); + } + + #else /* 32-bit case */ +@@ -1797,7 +1799,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) + if (err) + return err; + } +- if (!d_is_directory(nd->path.dentry)) { ++ if (!d_can_lookup(nd->path.dentry)) { + err = -ENOTDIR; + break; + } +@@ -1818,7 +1820,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, + struct dentry *root = nd->root.dentry; + struct inode *inode = root->d_inode; + if (*name) { +- if (!d_is_directory(root)) ++ if (!d_can_lookup(root)) + return -ENOTDIR; + retval = inode_permission(inode, MAY_EXEC); + if (retval) +@@ -1842,7 +1844,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, + if (*name=='/') { + if (flags & LOOKUP_RCU) { + rcu_read_lock(); +- set_root_rcu(nd); ++ nd->seq = set_root_rcu(nd); + } else { + set_root(nd); + path_get(&nd->root); +@@ -1874,7 +1876,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, + dentry = f.file->f_path.dentry; + + if (*name) { +- if (!d_is_directory(dentry)) { ++ if (!d_can_lookup(dentry)) { + fdput(f); + return -ENOTDIR; + } +@@ -1956,7 +1958,7 @@ static int path_lookupat(int dfd, const char *name, + err = complete_walk(nd); + + if (!err && nd->flags & LOOKUP_DIRECTORY) { +- if (!d_is_directory(nd->path.dentry)) { ++ if (!d_can_lookup(nd->path.dentry)) { + path_put(&nd->path); + err = -ENOTDIR; + } +@@ -2247,9 +2249,10 @@ done: + goto out; + } + path->dentry = dentry; +- path->mnt = mntget(nd->path.mnt); ++ path->mnt = nd->path.mnt; + if (should_follow_link(dentry, nd->flags & LOOKUP_FOLLOW)) + return 1; ++ mntget(path->mnt); + follow_mount(path); + error = 0; + out: +@@ -2415,11 +2418,11 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) + IS_IMMUTABLE(inode) || IS_SWAPFILE(inode)) + return -EPERM; + if (isdir) { +- if (!d_is_directory(victim) && !d_is_autodir(victim)) ++ if (!d_is_dir(victim)) + return -ENOTDIR; + if (IS_ROOT(victim)) + return -EBUSY; +- } else if (d_is_directory(victim) || d_is_autodir(victim)) ++ } else if (d_is_dir(victim)) + return -EISDIR; + if (IS_DEADDIR(dir)) + return -ENOENT; +@@ -2990,7 +2993,8 @@ finish_lookup: + + if (should_follow_link(path->dentry, !symlink_ok)) { + if (nd->flags & LOOKUP_RCU) { +- if (unlikely(unlazy_walk(nd, path->dentry))) { ++ if (unlikely(nd->path.mnt != path->mnt || ++ unlazy_walk(nd, path->dentry))) { + error = -ECHILD; + goto out; + } +@@ -3017,11 +3021,10 @@ finish_open: + } + audit_inode(name, nd->path.dentry, 0); + error = -EISDIR; +- if ((open_flag & O_CREAT) && +- (d_is_directory(nd->path.dentry) || d_is_autodir(nd->path.dentry))) ++ if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry)) + goto out; + error = -ENOTDIR; +- if ((nd->flags & LOOKUP_DIRECTORY) && !d_is_directory(nd->path.dentry)) ++ if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry)) + goto out; + if (!S_ISREG(nd->inode->i_mode)) + will_truncate = false; +@@ -3127,7 +3130,8 @@ static int do_tmpfile(int dfd, struct filename *pathname, + if (error) + goto out2; + audit_inode(pathname, nd->path.dentry, 0); +- error = may_open(&nd->path, op->acc_mode, op->open_flag); ++ /* Don't check for other permissions, the inode was just created */ ++ error = may_open(&nd->path, MAY_OPEN, op->open_flag); + if (error) + goto out2; + file->f_path.mnt = nd->path.mnt; +@@ -3167,7 +3171,7 @@ static struct file *path_openat(int dfd, struct filename *pathname, + + if (unlikely(file->f_flags & __O_TMPFILE)) { + error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened); +- goto out; ++ goto out2; + } + + error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base); +@@ -3205,6 +3209,7 @@ out: + path_put(&nd->root); + if (base) + fput(base); ++out2: + if (!(opened & FILE_OPENED)) { + BUG_ON(!error); + put_filp(file); +@@ -3745,7 +3750,7 @@ exit1: + slashes: + if (d_is_negative(dentry)) + error = -ENOENT; +- else if (d_is_directory(dentry) || d_is_autodir(dentry)) ++ else if (d_is_dir(dentry)) + error = -EISDIR; + else + error = -ENOTDIR; +@@ -4124,7 +4129,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode **delegated_inode) + { + int error; +- int is_dir = d_is_directory(old_dentry) || d_is_autodir(old_dentry); ++ int is_dir = d_is_dir(old_dentry); + const unsigned char *old_name; + + if (old_dentry->d_inode == new_dentry->d_inode) +@@ -4217,7 +4222,7 @@ retry_deleg: + if (d_is_negative(old_dentry)) + goto exit4; + /* unless the source is a directory trailing slashes give -ENOTDIR */ +- if (!d_is_directory(old_dentry) && !d_is_autodir(old_dentry)) { ++ if (!d_is_dir(old_dentry)) { + error = -ENOTDIR; + if (oldnd.last.name[oldnd.last.len]) + goto exit4; +diff --git a/fs/namespace.c b/fs/namespace.c +index 65233a5..fc99d18 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -777,6 +777,20 @@ static void attach_mnt(struct mount *mnt, + list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); + } + ++static void attach_shadowed(struct mount *mnt, ++ struct mount *parent, ++ struct mount *shadows) ++{ ++ if (shadows) { ++ hlist_add_after_rcu(&shadows->mnt_hash, &mnt->mnt_hash); ++ list_add(&mnt->mnt_child, &shadows->mnt_child); ++ } else { ++ hlist_add_head_rcu(&mnt->mnt_hash, ++ m_hash(&parent->mnt, mnt->mnt_mountpoint)); ++ list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); ++ } ++} ++ + /* + * vfsmount lock must be held for write + */ +@@ -795,12 +809,7 @@ static void commit_tree(struct mount *mnt, struct mount *shadows) + + list_splice(&head, n->list.prev); + +- if (shadows) +- hlist_add_after_rcu(&shadows->mnt_hash, &mnt->mnt_hash); +- else +- hlist_add_head_rcu(&mnt->mnt_hash, +- m_hash(&parent->mnt, mnt->mnt_mountpoint)); +- list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); ++ attach_shadowed(mnt, parent, shadows); + touch_mnt_namespace(n); + } + +@@ -887,8 +896,21 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, + + mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~(MNT_WRITE_HOLD|MNT_MARKED); + /* Don't allow unprivileged users to change mount flags */ +- if ((flag & CL_UNPRIVILEGED) && (mnt->mnt.mnt_flags & MNT_READONLY)) +- mnt->mnt.mnt_flags |= MNT_LOCK_READONLY; ++ if (flag & CL_UNPRIVILEGED) { ++ mnt->mnt.mnt_flags |= MNT_LOCK_ATIME; ++ ++ if (mnt->mnt.mnt_flags & MNT_READONLY) ++ mnt->mnt.mnt_flags |= MNT_LOCK_READONLY; ++ ++ if (mnt->mnt.mnt_flags & MNT_NODEV) ++ mnt->mnt.mnt_flags |= MNT_LOCK_NODEV; ++ ++ if (mnt->mnt.mnt_flags & MNT_NOSUID) ++ mnt->mnt.mnt_flags |= MNT_LOCK_NOSUID; ++ ++ if (mnt->mnt.mnt_flags & MNT_NOEXEC) ++ mnt->mnt.mnt_flags |= MNT_LOCK_NOEXEC; ++ } + + /* Don't allow unprivileged users to reveal what is under a mount */ + if ((flag & CL_UNPRIVILEGED) && list_empty(&old->mnt_expire)) +@@ -1204,6 +1226,11 @@ static void namespace_unlock(void) + head.first->pprev = &head.first; + INIT_HLIST_HEAD(&unmounted); + ++ /* undo decrements we'd done in umount_tree() */ ++ hlist_for_each_entry(mnt, &head, mnt_hash) ++ if (mnt->mnt_ex_mountpoint.mnt) ++ mntget(mnt->mnt_ex_mountpoint.mnt); ++ + up_write(&namespace_sem); + + synchronize_rcu(); +@@ -1240,6 +1267,9 @@ void umount_tree(struct mount *mnt, int how) + hlist_add_head(&p->mnt_hash, &tmp_list); + } + ++ hlist_for_each_entry(p, &tmp_list, mnt_hash) ++ list_del_init(&p->mnt_child); ++ + if (how) + propagate_umount(&tmp_list); + +@@ -1250,9 +1280,9 @@ void umount_tree(struct mount *mnt, int how) + p->mnt_ns = NULL; + if (how < 2) + p->mnt.mnt_flags |= MNT_SYNC_UMOUNT; +- list_del_init(&p->mnt_child); + if (mnt_has_parent(p)) { + put_mountpoint(p->mnt_mp); ++ mnt_add_count(p->mnt_parent, -1); + /* move the reference to mountpoint into ->mnt_ex_mountpoint */ + p->mnt_ex_mountpoint.dentry = p->mnt_mountpoint; + p->mnt_ex_mountpoint.mnt = &p->mnt_parent->mnt; +@@ -1265,6 +1295,8 @@ void umount_tree(struct mount *mnt, int how) + } + if (last) { + last->mnt_hash.next = unmounted.first; ++ if (unmounted.first) ++ unmounted.first->pprev = &last->mnt_hash.next; + unmounted.first = tmp_list.first; + unmounted.first->pprev = &unmounted.first; + } +@@ -1335,6 +1367,8 @@ static int do_umount(struct mount *mnt, int flags) + * Special case for "unmounting" root ... + * we just try to remount it readonly. + */ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; + down_write(&sb->s_umount); + if (!(sb->s_flags & MS_RDONLY)) + retval = do_remount_sb(sb, MS_RDONLY, NULL, 0); +@@ -1407,6 +1441,9 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags) + goto dput_and_out; + if (mnt->mnt.mnt_flags & MNT_LOCKED) + goto dput_and_out; ++ retval = -EPERM; ++ if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN)) ++ goto dput_and_out; + + retval = do_umount(mnt, flags); + dput_and_out: +@@ -1483,6 +1520,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, + continue; + + for (s = r; s; s = next_mnt(s, r)) { ++ struct mount *t = NULL; + if (!(flag & CL_COPY_UNBINDABLE) && + IS_MNT_UNBINDABLE(s)) { + s = skip_mnt_tree(s); +@@ -1504,7 +1542,14 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, + goto out; + lock_mount_hash(); + list_add_tail(&q->mnt_list, &res->mnt_list); +- attach_mnt(q, parent, p->mnt_mp); ++ mnt_set_mountpoint(parent, p->mnt_mp, q); ++ if (!list_empty(&parent->mnt_mounts)) { ++ t = list_last_entry(&parent->mnt_mounts, ++ struct mount, mnt_child); ++ if (t->mnt_mp != p->mnt_mp) ++ t = NULL; ++ } ++ attach_shadowed(q, parent, t); + unlock_mount_hash(); + } + } +@@ -1887,9 +1932,6 @@ static int change_mount_flags(struct vfsmount *mnt, int ms_flags) + if (readonly_request == __mnt_is_readonly(mnt)) + return 0; + +- if (mnt->mnt_flags & MNT_LOCK_READONLY) +- return -EPERM; +- + if (readonly_request) + error = mnt_make_readonly(real_mount(mnt)); + else +@@ -1915,6 +1957,39 @@ static int do_remount(struct path *path, int flags, int mnt_flags, + if (path->dentry != path->mnt->mnt_root) + return -EINVAL; + ++ /* Don't allow changing of locked mnt flags. ++ * ++ * No locks need to be held here while testing the various ++ * MNT_LOCK flags because those flags can never be cleared ++ * once they are set. ++ */ ++ if ((mnt->mnt.mnt_flags & MNT_LOCK_READONLY) && ++ !(mnt_flags & MNT_READONLY)) { ++ return -EPERM; ++ } ++ if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) && ++ !(mnt_flags & MNT_NODEV)) { ++ /* Was the nodev implicitly added in mount? */ ++ if ((mnt->mnt_ns->user_ns != &init_user_ns) && ++ !(sb->s_type->fs_flags & FS_USERNS_DEV_MOUNT)) { ++ mnt_flags |= MNT_NODEV; ++ } else { ++ return -EPERM; ++ } ++ } ++ if ((mnt->mnt.mnt_flags & MNT_LOCK_NOSUID) && ++ !(mnt_flags & MNT_NOSUID)) { ++ return -EPERM; ++ } ++ if ((mnt->mnt.mnt_flags & MNT_LOCK_NOEXEC) && ++ !(mnt_flags & MNT_NOEXEC)) { ++ return -EPERM; ++ } ++ if ((mnt->mnt.mnt_flags & MNT_LOCK_ATIME) && ++ ((mnt->mnt.mnt_flags & MNT_ATIME_MASK) != (mnt_flags & MNT_ATIME_MASK))) { ++ return -EPERM; ++ } ++ + err = security_sb_remount(sb, data); + if (err) + return err; +@@ -1928,7 +2003,7 @@ static int do_remount(struct path *path, int flags, int mnt_flags, + err = do_remount_sb(sb, flags, data, 0); + if (!err) { + lock_mount_hash(); +- mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK; ++ mnt_flags |= mnt->mnt.mnt_flags & ~MNT_USER_SETTABLE_MASK; + mnt->mnt.mnt_flags = mnt_flags; + touch_mnt_namespace(mnt->mnt_ns); + unlock_mount_hash(); +@@ -2113,7 +2188,7 @@ static int do_new_mount(struct path *path, const char *fstype, int flags, + */ + if (!(type->fs_flags & FS_USERNS_DEV_MOUNT)) { + flags |= MS_NODEV; +- mnt_flags |= MNT_NODEV; ++ mnt_flags |= MNT_NODEV | MNT_LOCK_NODEV; + } + } + +@@ -2427,6 +2502,14 @@ long do_mount(const char *dev_name, const char *dir_name, + if (flags & MS_RDONLY) + mnt_flags |= MNT_READONLY; + ++ /* The default atime for remount is preservation */ ++ if ((flags & MS_REMOUNT) && ++ ((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME | ++ MS_STRICTATIME)) == 0)) { ++ mnt_flags &= ~MNT_ATIME_MASK; ++ mnt_flags |= path.mnt->mnt_flags & MNT_ATIME_MASK; ++ } ++ + flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN | + MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT | + MS_STRICTATIME); +@@ -2759,6 +2842,9 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, + /* make sure we can reach put_old from new_root */ + if (!is_path_reachable(old_mnt, old.dentry, &new)) + goto out4; ++ /* make certain new is below the root */ ++ if (!is_path_reachable(new_mnt, new.dentry, &root)) ++ goto out4; + root_mp->m_count++; /* pin it so it won't go away */ + lock_mount_hash(); + detach_mnt(new_mnt, &parent_path); +@@ -2939,11 +3025,21 @@ bool fs_fully_visible(struct file_system_type *type) + if (mnt->mnt.mnt_sb->s_type != type) + continue; + +- /* This mount is not fully visible if there are any child mounts +- * that cover anything except for empty directories. ++ /* This mount is not fully visible if it's root directory ++ * is not the root directory of the filesystem. ++ */ ++ if (mnt->mnt.mnt_root != mnt->mnt.mnt_sb->s_root) ++ continue; ++ ++ /* This mount is not fully visible if there are any ++ * locked child mounts that cover anything except for ++ * empty directories. + */ + list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) { + struct inode *inode = child->mnt_mountpoint->d_inode; ++ /* Only worry about locked mounts */ ++ if (!(mnt->mnt.mnt_flags & MNT_LOCKED)) ++ continue; + if (!S_ISDIR(inode->i_mode)) + goto next; + if (inode->i_nlink > 2) +diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c +index c320ac5..dc9747d 100644 +--- a/fs/ncpfs/dir.c ++++ b/fs/ncpfs/dir.c +@@ -406,7 +406,7 @@ ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos) + spin_lock(&parent->d_lock); + next = parent->d_subdirs.next; + while (next != &parent->d_subdirs) { +- dent = list_entry(next, struct dentry, d_u.d_child); ++ dent = list_entry(next, struct dentry, d_child); + if ((unsigned long)dent->d_fsdata == fpos) { + if (dent->d_inode) + dget(dent); +diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c +index 60426cc..2f970de 100644 +--- a/fs/ncpfs/ioctl.c ++++ b/fs/ncpfs/ioctl.c +@@ -448,7 +448,6 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg + result = -EIO; + } + } +- result = 0; + } + mutex_unlock(&server->root_setup_lock); + +diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h +index 32c0658..6d5e7c5 100644 +--- a/fs/ncpfs/ncplib_kernel.h ++++ b/fs/ncpfs/ncplib_kernel.h +@@ -194,7 +194,7 @@ ncp_renew_dentries(struct dentry *parent) + spin_lock(&parent->d_lock); + next = parent->d_subdirs.next; + while (next != &parent->d_subdirs) { +- dentry = list_entry(next, struct dentry, d_u.d_child); ++ dentry = list_entry(next, struct dentry, d_child); + + if (dentry->d_fsdata == NULL) + ncp_age_dentry(server, dentry); +@@ -216,7 +216,7 @@ ncp_invalidate_dircache_entries(struct dentry *parent) + spin_lock(&parent->d_lock); + next = parent->d_subdirs.next; + while (next != &parent->d_subdirs) { +- dentry = list_entry(next, struct dentry, d_u.d_child); ++ dentry = list_entry(next, struct dentry, d_child); + dentry->d_fsdata = NULL; + ncp_age_dentry(server, dentry); + next = next->next; +diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c +index 56ff823..65d849b 100644 +--- a/fs/nfs/blocklayout/blocklayout.c ++++ b/fs/nfs/blocklayout/blocklayout.c +@@ -1213,7 +1213,7 @@ static u64 pnfs_num_cont_bytes(struct inode *inode, pgoff_t idx) + end = DIV_ROUND_UP(i_size_read(inode), PAGE_CACHE_SIZE); + if (end != NFS_I(inode)->npages) { + rcu_read_lock(); +- end = radix_tree_next_hole(&mapping->page_tree, idx + 1, ULONG_MAX); ++ end = page_cache_next_hole(mapping, idx + 1, ULONG_MAX); + rcu_read_unlock(); + } + +diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c +index 073b4cf..0a2016b 100644 +--- a/fs/nfs/callback.c ++++ b/fs/nfs/callback.c +@@ -128,22 +128,24 @@ nfs41_callback_svc(void *vrqstp) + if (try_to_freeze()) + continue; + +- prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE); ++ prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_UNINTERRUPTIBLE); + spin_lock_bh(&serv->sv_cb_lock); + if (!list_empty(&serv->sv_cb_list)) { + req = list_first_entry(&serv->sv_cb_list, + struct rpc_rqst, rq_bc_list); + list_del(&req->rq_bc_list); + spin_unlock_bh(&serv->sv_cb_lock); ++ finish_wait(&serv->sv_cb_waitq, &wq); + dprintk("Invoking bc_svc_process()\n"); + error = bc_svc_process(serv, req, rqstp); + dprintk("bc_svc_process() returned w/ error code= %d\n", + error); + } else { + spin_unlock_bh(&serv->sv_cb_lock); +- schedule(); ++ /* schedule_timeout to game the hung task watchdog */ ++ schedule_timeout(60 * HZ); ++ finish_wait(&serv->sv_cb_waitq, &wq); + } +- finish_wait(&serv->sv_cb_waitq, &wq); + } + return 0; + } +diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c +index f4ccfe6..02f8d09 100644 +--- a/fs/nfs/callback_xdr.c ++++ b/fs/nfs/callback_xdr.c +@@ -464,8 +464,10 @@ static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp, + + for (i = 0; i < args->csa_nrclists; i++) { + status = decode_rc_list(xdr, &args->csa_rclists[i]); +- if (status) ++ if (status) { ++ args->csa_nrclists = i; + goto out_free; ++ } + } + } + status = 0; +diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c +index 5d8ccec..2ea3537 100644 +--- a/fs/nfs/delegation.c ++++ b/fs/nfs/delegation.c +@@ -109,6 +109,8 @@ again: + continue; + if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) + continue; ++ if (!nfs4_valid_open_stateid(state)) ++ continue; + if (!nfs4_stateid_match(&state->stateid, stateid)) + continue; + get_nfs_open_context(ctx); +@@ -159,8 +161,8 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, + &delegation->flags); + NFS_I(inode)->delegation_state = delegation->type; + spin_unlock(&delegation->lock); +- put_rpccred(oldcred); + rcu_read_unlock(); ++ put_rpccred(oldcred); + trace_nfs4_reclaim_delegation(inode, res->delegation_type); + } else { + /* We appear to have raced with a delegation return. */ +@@ -177,7 +179,11 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation * + { + int res = 0; + +- res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync); ++ if (!test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) ++ res = nfs4_proc_delegreturn(inode, ++ delegation->cred, ++ &delegation->stateid, ++ issync); + nfs_free_delegation(delegation); + return res; + } +@@ -364,11 +370,13 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation + { + struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; + struct nfs_inode *nfsi = NFS_I(inode); +- int err; ++ int err = 0; + + if (delegation == NULL) + return 0; + do { ++ if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) ++ break; + err = nfs_delegation_claim_opens(inode, &delegation->stateid); + if (!issync || err != -EAGAIN) + break; +@@ -589,10 +597,23 @@ static void nfs_client_mark_return_unused_delegation_types(struct nfs_client *cl + rcu_read_unlock(); + } + ++static void nfs_revoke_delegation(struct inode *inode) ++{ ++ struct nfs_delegation *delegation; ++ rcu_read_lock(); ++ delegation = rcu_dereference(NFS_I(inode)->delegation); ++ if (delegation != NULL) { ++ set_bit(NFS_DELEGATION_REVOKED, &delegation->flags); ++ nfs_mark_return_delegation(NFS_SERVER(inode), delegation); ++ } ++ rcu_read_unlock(); ++} ++ + void nfs_remove_bad_delegation(struct inode *inode) + { + struct nfs_delegation *delegation; + ++ nfs_revoke_delegation(inode); + delegation = nfs_inode_detach_delegation(inode); + if (delegation) { + nfs_inode_find_state_and_recover(inode, &delegation->stateid); +diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h +index 9a79c7a..e02b090 100644 +--- a/fs/nfs/delegation.h ++++ b/fs/nfs/delegation.h +@@ -31,6 +31,7 @@ enum { + NFS_DELEGATION_RETURN_IF_CLOSED, + NFS_DELEGATION_REFERENCED, + NFS_DELEGATION_RETURNING, ++ NFS_DELEGATION_REVOKED, + }; + + int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); +diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c +index b8797ae..7ececa1 100644 +--- a/fs/nfs/direct.c ++++ b/fs/nfs/direct.c +@@ -123,6 +123,12 @@ static inline int put_dreq(struct nfs_direct_req *dreq) + */ + ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs) + { ++ struct inode *inode = iocb->ki_filp->f_mapping->host; ++ ++ /* we only support swap file calling nfs_direct_IO */ ++ if (!IS_SWAPFILE(inode)) ++ return 0; ++ + #ifndef CONFIG_NFS_SWAP + dprintk("NFS: nfs_direct_IO (%pD) off/no(%Ld/%lu) EINVAL\n", + iocb->ki_filp, (long long) pos, nr_segs); +@@ -178,6 +184,7 @@ static void nfs_direct_req_free(struct kref *kref) + { + struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref); + ++ nfs_free_pnfs_ds_cinfo(&dreq->ds_cinfo); + if (dreq->l_ctx != NULL) + nfs_put_lock_context(dreq->l_ctx); + if (dreq->ctx != NULL) +diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c +index 66984a9..5b8ab0e 100644 +--- a/fs/nfs/getroot.c ++++ b/fs/nfs/getroot.c +@@ -58,7 +58,7 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i + */ + spin_lock(&sb->s_root->d_inode->i_lock); + spin_lock(&sb->s_root->d_lock); +- hlist_del_init(&sb->s_root->d_alias); ++ hlist_del_init(&sb->s_root->d_u.d_alias); + spin_unlock(&sb->s_root->d_lock); + spin_unlock(&sb->s_root->d_inode->i_lock); + } +diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c +index 15f9d98..6659ce5 100644 +--- a/fs/nfs/inode.c ++++ b/fs/nfs/inode.c +@@ -592,7 +592,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) + { + struct inode *inode = dentry->d_inode; + int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; +- int err; ++ int err = 0; + + trace_nfs_getattr_enter(inode); + /* Flush out writes to the server in order to update c/mtime. */ +diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c +index 871d6ed..24c6898 100644 +--- a/fs/nfs/nfs3acl.c ++++ b/fs/nfs/nfs3acl.c +@@ -129,7 +129,10 @@ static int __nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, + .rpc_argp = &args, + .rpc_resp = &fattr, + }; +- int status; ++ int status = 0; ++ ++ if (acl == NULL && (!S_ISDIR(inode->i_mode) || dfacl == NULL)) ++ goto out; + + status = -EOPNOTSUPP; + if (!nfs_server_capable(inode, NFS_CAP_ACLS)) +@@ -247,3 +250,46 @@ const struct xattr_handler *nfs3_xattr_handlers[] = { + &posix_acl_default_xattr_handler, + NULL, + }; ++ ++static int ++nfs3_list_one_acl(struct inode *inode, int type, const char *name, void *data, ++ size_t size, ssize_t *result) ++{ ++ struct posix_acl *acl; ++ char *p = data + *result; ++ ++ acl = get_acl(inode, type); ++ if (IS_ERR_OR_NULL(acl)) ++ return 0; ++ ++ posix_acl_release(acl); ++ ++ *result += strlen(name); ++ *result += 1; ++ if (!size) ++ return 0; ++ if (*result > size) ++ return -ERANGE; ++ ++ strcpy(p, name); ++ return 0; ++} ++ ++ssize_t ++nfs3_listxattr(struct dentry *dentry, char *data, size_t size) ++{ ++ struct inode *inode = dentry->d_inode; ++ ssize_t result = 0; ++ int error; ++ ++ error = nfs3_list_one_acl(inode, ACL_TYPE_ACCESS, ++ POSIX_ACL_XATTR_ACCESS, data, size, &result); ++ if (error) ++ return error; ++ ++ error = nfs3_list_one_acl(inode, ACL_TYPE_DEFAULT, ++ POSIX_ACL_XATTR_DEFAULT, data, size, &result); ++ if (error) ++ return error; ++ return result; ++} +diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c +index a462ef0..8a18b4a 100644 +--- a/fs/nfs/nfs3proc.c ++++ b/fs/nfs/nfs3proc.c +@@ -926,7 +926,7 @@ static const struct inode_operations nfs3_dir_inode_operations = { + .getattr = nfs_getattr, + .setattr = nfs_setattr, + #ifdef CONFIG_NFS_V3_ACL +- .listxattr = generic_listxattr, ++ .listxattr = nfs3_listxattr, + .getxattr = generic_getxattr, + .setxattr = generic_setxattr, + .removexattr = generic_removexattr, +@@ -940,7 +940,7 @@ static const struct inode_operations nfs3_file_inode_operations = { + .getattr = nfs_getattr, + .setattr = nfs_setattr, + #ifdef CONFIG_NFS_V3_ACL +- .listxattr = generic_listxattr, ++ .listxattr = nfs3_listxattr, + .getxattr = generic_getxattr, + .setxattr = generic_setxattr, + .removexattr = generic_removexattr, +diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c +index fa6d721..4495cad 100644 +--- a/fs/nfs/nfs3xdr.c ++++ b/fs/nfs/nfs3xdr.c +@@ -1342,7 +1342,7 @@ static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req, + if (args->npages != 0) + xdr_write_pages(xdr, args->pages, 0, args->len); + else +- xdr_reserve_space(xdr, NFS_ACL_INLINE_BUFSIZE); ++ xdr_reserve_space(xdr, args->len); + + error = nfsacl_encode(xdr->buf, base, args->inode, + (args->mask & NFS_ACL) ? +diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c +index 0e46d3d..d3f6062 100644 +--- a/fs/nfs/nfs4client.c ++++ b/fs/nfs/nfs4client.c +@@ -482,6 +482,16 @@ int nfs40_walk_client_list(struct nfs_client *new, + + spin_lock(&nn->nfs_client_lock); + list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { ++ ++ if (pos->rpc_ops != new->rpc_ops) ++ continue; ++ ++ if (pos->cl_proto != new->cl_proto) ++ continue; ++ ++ if (pos->cl_minorversion != new->cl_minorversion) ++ continue; ++ + /* If "pos" isn't marked ready, we can't trust the + * remaining fields in "pos" */ + if (pos->cl_cons_state > NFS_CS_READY) { +@@ -501,15 +511,6 @@ int nfs40_walk_client_list(struct nfs_client *new, + if (pos->cl_cons_state != NFS_CS_READY) + continue; + +- if (pos->rpc_ops != new->rpc_ops) +- continue; +- +- if (pos->cl_proto != new->cl_proto) +- continue; +- +- if (pos->cl_minorversion != new->cl_minorversion) +- continue; +- + if (pos->cl_clientid != new->cl_clientid) + continue; + +@@ -564,20 +565,14 @@ static bool nfs4_match_clientids(struct nfs_client *a, struct nfs_client *b) + } + + /* +- * Returns true if the server owners match ++ * Returns true if the server major ids match + */ + static bool +-nfs4_match_serverowners(struct nfs_client *a, struct nfs_client *b) ++nfs4_check_clientid_trunking(struct nfs_client *a, struct nfs_client *b) + { + struct nfs41_server_owner *o1 = a->cl_serverowner; + struct nfs41_server_owner *o2 = b->cl_serverowner; + +- if (o1->minor_id != o2->minor_id) { +- dprintk("NFS: --> %s server owner minor IDs do not match\n", +- __func__); +- return false; +- } +- + if (o1->major_id_sz != o2->major_id_sz) + goto out_major_mismatch; + if (memcmp(o1->major_id, o2->major_id, o1->major_id_sz) != 0) +@@ -615,6 +610,16 @@ int nfs41_walk_client_list(struct nfs_client *new, + + spin_lock(&nn->nfs_client_lock); + list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { ++ ++ if (pos->rpc_ops != new->rpc_ops) ++ continue; ++ ++ if (pos->cl_proto != new->cl_proto) ++ continue; ++ ++ if (pos->cl_minorversion != new->cl_minorversion) ++ continue; ++ + /* If "pos" isn't marked ready, we can't trust the + * remaining fields in "pos", especially the client + * ID and serverowner fields. Wait for CREATE_SESSION +@@ -628,7 +633,7 @@ int nfs41_walk_client_list(struct nfs_client *new, + prev = pos; + + status = nfs_wait_client_init_complete(pos); +- if (status == 0) { ++ if (pos->cl_cons_state == NFS_CS_SESSION_INITING) { + nfs4_schedule_lease_recovery(pos); + status = nfs4_wait_clnt_recover(pos); + } +@@ -640,19 +645,15 @@ int nfs41_walk_client_list(struct nfs_client *new, + if (pos->cl_cons_state != NFS_CS_READY) + continue; + +- if (pos->rpc_ops != new->rpc_ops) +- continue; +- +- if (pos->cl_proto != new->cl_proto) +- continue; +- +- if (pos->cl_minorversion != new->cl_minorversion) +- continue; +- + if (!nfs4_match_clientids(pos, new)) + continue; + +- if (!nfs4_match_serverowners(pos, new)) ++ /* ++ * Note that session trunking is just a special subcase of ++ * client id trunking. In either case, we want to fall back ++ * to using the existing nfs_client. ++ */ ++ if (!nfs4_check_clientid_trunking(pos, new)) + continue; + + atomic_inc(&pos->cl_count); +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index d5d06e8..58258ad 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -1587,7 +1587,7 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct + nfs_inode_find_state_and_recover(state->inode, + stateid); + nfs4_schedule_stateid_recovery(server, state); +- return 0; ++ return -EAGAIN; + case -NFS4ERR_DELAY: + case -NFS4ERR_GRACE: + set_bit(NFS_DELEGATED_STATE, &state->flags); +@@ -2034,46 +2034,60 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta + return ret; + } + ++static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state) ++{ ++ nfs_remove_bad_delegation(state->inode); ++ write_seqlock(&state->seqlock); ++ nfs4_stateid_copy(&state->stateid, &state->open_stateid); ++ write_sequnlock(&state->seqlock); ++ clear_bit(NFS_DELEGATED_STATE, &state->flags); ++} ++ ++static void nfs40_clear_delegation_stateid(struct nfs4_state *state) ++{ ++ if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL) ++ nfs_finish_clear_delegation_stateid(state); ++} ++ ++static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) ++{ ++ /* NFSv4.0 doesn't allow for delegation recovery on open expire */ ++ nfs40_clear_delegation_stateid(state); ++ return nfs4_open_expired(sp, state); ++} ++ + #if defined(CONFIG_NFS_V4_1) +-static void nfs41_clear_delegation_stateid(struct nfs4_state *state) ++static void nfs41_check_delegation_stateid(struct nfs4_state *state) + { + struct nfs_server *server = NFS_SERVER(state->inode); +- nfs4_stateid *stateid = &state->stateid; ++ nfs4_stateid stateid; + struct nfs_delegation *delegation; +- struct rpc_cred *cred = NULL; +- int status = -NFS4ERR_BAD_STATEID; +- +- /* If a state reset has been done, test_stateid is unneeded */ +- if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) +- return; ++ struct rpc_cred *cred; ++ int status; + + /* Get the delegation credential for use by test/free_stateid */ + rcu_read_lock(); + delegation = rcu_dereference(NFS_I(state->inode)->delegation); +- if (delegation != NULL && +- nfs4_stateid_match(&delegation->stateid, stateid)) { +- cred = get_rpccred(delegation->cred); +- rcu_read_unlock(); +- status = nfs41_test_stateid(server, stateid, cred); +- trace_nfs4_test_delegation_stateid(state, NULL, status); +- } else ++ if (delegation == NULL) { + rcu_read_unlock(); ++ return; ++ } ++ ++ nfs4_stateid_copy(&stateid, &delegation->stateid); ++ cred = get_rpccred(delegation->cred); ++ rcu_read_unlock(); ++ status = nfs41_test_stateid(server, &stateid, cred); ++ trace_nfs4_test_delegation_stateid(state, NULL, status); + + if (status != NFS_OK) { + /* Free the stateid unless the server explicitly + * informs us the stateid is unrecognized. */ + if (status != -NFS4ERR_BAD_STATEID) +- nfs41_free_stateid(server, stateid, cred); +- nfs_remove_bad_delegation(state->inode); +- +- write_seqlock(&state->seqlock); +- nfs4_stateid_copy(&state->stateid, &state->open_stateid); +- write_sequnlock(&state->seqlock); +- clear_bit(NFS_DELEGATED_STATE, &state->flags); ++ nfs41_free_stateid(server, &stateid, cred); ++ nfs_finish_clear_delegation_stateid(state); + } + +- if (cred != NULL) +- put_rpccred(cred); ++ put_rpccred(cred); + } + + /** +@@ -2117,7 +2131,7 @@ static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st + { + int status; + +- nfs41_clear_delegation_stateid(state); ++ nfs41_check_delegation_stateid(state); + status = nfs41_check_open_stateid(state); + if (status != NFS_OK) + status = nfs4_open_expired(sp, state); +@@ -2546,6 +2560,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) + struct nfs4_closedata *calldata = data; + struct nfs4_state *state = calldata->state; + struct inode *inode = calldata->inode; ++ bool is_rdonly, is_wronly, is_rdwr; + int call_close = 0; + + dprintk("%s: begin!\n", __func__); +@@ -2553,21 +2568,27 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) + goto out_wait; + + task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; +- calldata->arg.fmode = FMODE_READ|FMODE_WRITE; + spin_lock(&state->owner->so_lock); ++ is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags); ++ is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags); ++ is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags); + /* Calculate the change in open mode */ ++ calldata->arg.fmode = 0; + if (state->n_rdwr == 0) { +- if (state->n_rdonly == 0) { +- call_close |= test_bit(NFS_O_RDONLY_STATE, &state->flags); +- call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags); +- calldata->arg.fmode &= ~FMODE_READ; +- } +- if (state->n_wronly == 0) { +- call_close |= test_bit(NFS_O_WRONLY_STATE, &state->flags); +- call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags); +- calldata->arg.fmode &= ~FMODE_WRITE; +- } +- } ++ if (state->n_rdonly == 0) ++ call_close |= is_rdonly; ++ else if (is_rdonly) ++ calldata->arg.fmode |= FMODE_READ; ++ if (state->n_wronly == 0) ++ call_close |= is_wronly; ++ else if (is_wronly) ++ calldata->arg.fmode |= FMODE_WRITE; ++ } else if (is_rdwr) ++ calldata->arg.fmode |= FMODE_READ|FMODE_WRITE; ++ ++ if (calldata->arg.fmode == 0) ++ call_close |= is_rdwr; ++ + if (!nfs4_valid_open_stateid(state)) + call_close = 0; + spin_unlock(&state->owner->so_lock); +@@ -7235,7 +7256,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr + int ret = 0; + + if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) +- return 0; ++ return -EAGAIN; + task = _nfs41_proc_sequence(clp, cred, false); + if (IS_ERR(task)) + ret = PTR_ERR(task); +@@ -7568,6 +7589,9 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) + + dprintk("--> %s\n", __func__); + ++ /* nfs4_layoutget_release calls pnfs_put_layout_hdr */ ++ pnfs_get_layout_hdr(NFS_I(inode)->layout); ++ + lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); + if (!lgp->args.layout.pages) { + nfs4_layoutget_release(lgp); +@@ -7580,9 +7604,6 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) + lgp->res.seq_res.sr_slot = NULL; + nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); + +- /* nfs4_layoutget_release calls pnfs_put_layout_hdr */ +- pnfs_get_layout_hdr(NFS_I(inode)->layout); +- + task = rpc_run_task(&task_setup_data); + if (IS_ERR(task)) + return ERR_CAST(task); +@@ -8248,7 +8269,7 @@ static const struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = { + static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = { + .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE, + .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE, +- .recover_open = nfs4_open_expired, ++ .recover_open = nfs40_open_expired, + .recover_lock = nfs4_lock_expired, + .establish_clid = nfs4_init_clientid, + }; +diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c +index 1720d32..e1ba58c 100644 +--- a/fs/nfs/nfs4renewd.c ++++ b/fs/nfs/nfs4renewd.c +@@ -88,10 +88,18 @@ nfs4_renew_state(struct work_struct *work) + } + nfs_expire_all_delegations(clp); + } else { ++ int ret; ++ + /* Queue an asynchronous RENEW. */ +- ops->sched_state_renewal(clp, cred, renew_flags); ++ ret = ops->sched_state_renewal(clp, cred, renew_flags); + put_rpccred(cred); +- goto out_exp; ++ switch (ret) { ++ default: ++ goto out_exp; ++ case -EAGAIN: ++ case -ENOMEM: ++ break; ++ } + } + } else { + dprintk("%s: failed to call renewd. Reason: lease not expired \n", +diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c +index 27f5f85..c402b67 100644 +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -1482,6 +1482,8 @@ restart: + spin_unlock(&state->state_lock); + } + nfs4_put_open_state(state); ++ clear_bit(NFS4CLNT_RECLAIM_NOGRACE, ++ &state->flags); + spin_lock(&sp->so_lock); + goto restart; + } +@@ -1732,7 +1734,8 @@ restart: + if (status < 0) { + set_bit(ops->owner_flag_bit, &sp->so_flags); + nfs4_put_state_owner(sp); +- return nfs4_recovery_handle_error(clp, status); ++ status = nfs4_recovery_handle_error(clp, status); ++ return (status != 0) ? status : -EAGAIN; + } + + nfs4_put_state_owner(sp); +@@ -1741,7 +1744,7 @@ restart: + spin_unlock(&clp->cl_lock); + } + rcu_read_unlock(); +- return status; ++ return 0; + } + + static int nfs4_check_lease(struct nfs_client *clp) +@@ -1788,7 +1791,6 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status) + break; + case -NFS4ERR_STALE_CLIENTID: + clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state); +- nfs4_state_clear_reclaim_reboot(clp); + nfs4_state_start_reclaim_reboot(clp); + break; + case -NFS4ERR_CLID_INUSE: +@@ -2370,6 +2372,7 @@ static void nfs4_state_manager(struct nfs_client *clp) + status = nfs4_check_lease(clp); + if (status < 0) + goto out_error; ++ continue; + } + + if (test_and_clear_bit(NFS4CLNT_MOVED, &clp->cl_state)) { +@@ -2391,14 +2394,11 @@ static void nfs4_state_manager(struct nfs_client *clp) + section = "reclaim reboot"; + status = nfs4_do_reclaim(clp, + clp->cl_mvops->reboot_recovery_ops); +- if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || +- test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) +- continue; +- nfs4_state_end_reclaim_reboot(clp); +- if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) ++ if (status == -EAGAIN) + continue; + if (status < 0) + goto out_error; ++ nfs4_state_end_reclaim_reboot(clp); + } + + /* Now recover expired state... */ +@@ -2406,9 +2406,7 @@ static void nfs4_state_manager(struct nfs_client *clp) + section = "reclaim nograce"; + status = nfs4_do_reclaim(clp, + clp->cl_mvops->nograce_recovery_ops); +- if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || +- test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) || +- test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) ++ if (status == -EAGAIN) + continue; + if (status < 0) + goto out_error; +diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c +index 2ffebf2..27d7f27 100644 +--- a/fs/nfs/pagelist.c ++++ b/fs/nfs/pagelist.c +@@ -113,7 +113,7 @@ __nfs_iocounter_wait(struct nfs_io_counter *c) + if (atomic_read(&c->io_count) == 0) + break; + ret = nfs_wait_bit_killable(&c->flags); +- } while (atomic_read(&c->io_count) != 0); ++ } while (atomic_read(&c->io_count) != 0 && !ret); + finish_wait(wq, &q.wait); + return ret; + } +diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c +index 3eaa6e3..f42bbe5 100644 +--- a/fs/nfsd/nfs4callback.c ++++ b/fs/nfsd/nfs4callback.c +@@ -672,7 +672,8 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c + clp->cl_cb_session = ses; + args.bc_xprt = conn->cb_xprt; + args.prognumber = clp->cl_cb_session->se_cb_prog; +- args.protocol = XPRT_TRANSPORT_BC_TCP; ++ args.protocol = conn->cb_xprt->xpt_class->xcl_ident | ++ XPRT_TRANSPORT_BC; + args.authflavor = ses->se_cb_sec.flavor; + } + /* Create RPC client */ +@@ -783,8 +784,12 @@ static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task) + { + if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { + rpc_sleep_on(&clp->cl_cb_waitq, task, NULL); +- dprintk("%s slot is busy\n", __func__); +- return false; ++ /* Race breaker */ ++ if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { ++ dprintk("%s slot is busy\n", __func__); ++ return false; ++ } ++ rpc_wake_up_queued_task(&clp->cl_cb_waitq, task); + } + return true; + } +diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c +index f23a6ca..86f5d3e 100644 +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -1243,7 +1243,8 @@ static bool need_wrongsec_check(struct svc_rqst *rqstp) + */ + if (argp->opcnt == resp->opcnt) + return false; +- ++ if (next->opnum == OP_ILLEGAL) ++ return false; + nextd = OPDESC(next); + /* + * Rest of 2.6.3.1.1: certain operations will return WRONGSEC +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index 34d2a1f..daa53da 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -1209,15 +1209,14 @@ static int copy_cred(struct svc_cred *target, struct svc_cred *source) + return 0; + } + +-static long long ++static int + compare_blob(const struct xdr_netobj *o1, const struct xdr_netobj *o2) + { +- long long res; +- +- res = o1->len - o2->len; +- if (res) +- return res; +- return (long long)memcmp(o1->data, o2->data, o1->len); ++ if (o1->len < o2->len) ++ return -1; ++ if (o1->len > o2->len) ++ return 1; ++ return memcmp(o1->data, o2->data, o1->len); + } + + static int same_name(const char *n1, const char *n2) +@@ -1401,7 +1400,7 @@ add_clp_to_name_tree(struct nfs4_client *new_clp, struct rb_root *root) + static struct nfs4_client * + find_clp_in_name_tree(struct xdr_netobj *name, struct rb_root *root) + { +- long long cmp; ++ int cmp; + struct rb_node *node = root->rb_node; + struct nfs4_client *clp; + +diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c +index 8657335..dd1afa3 100644 +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -1809,6 +1809,9 @@ static __be32 nfsd4_encode_components_esc(char sep, char *components, + } + else + end++; ++ if (found_esc) ++ end = next; ++ + str = end; + } + *pp = p; +diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c +index f8f060f..6040da8 100644 +--- a/fs/nfsd/nfscache.c ++++ b/fs/nfsd/nfscache.c +@@ -224,13 +224,6 @@ hash_refile(struct svc_cacherep *rp) + hlist_add_head(&rp->c_hash, cache_hash + hash_32(rp->c_xid, maskbits)); + } + +-static inline bool +-nfsd_cache_entry_expired(struct svc_cacherep *rp) +-{ +- return rp->c_state != RC_INPROG && +- time_after(jiffies, rp->c_timestamp + RC_EXPIRE); +-} +- + /* + * Walk the LRU list and prune off entries that are older than RC_EXPIRE. + * Also prune the oldest ones when the total exceeds the max number of entries. +@@ -242,8 +235,14 @@ prune_cache_entries(void) + long freed = 0; + + list_for_each_entry_safe(rp, tmp, &lru_head, c_lru) { +- if (!nfsd_cache_entry_expired(rp) && +- num_drc_entries <= max_drc_entries) ++ /* ++ * Don't free entries attached to calls that are still ++ * in-progress, but do keep scanning the list. ++ */ ++ if (rp->c_state == RC_INPROG) ++ continue; ++ if (num_drc_entries <= max_drc_entries && ++ time_before(jiffies, rp->c_timestamp + RC_EXPIRE)) + break; + nfsd_reply_cache_free_locked(rp); + freed++; +diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h +index 479eb68..f417fef 100644 +--- a/fs/nfsd/nfsd.h ++++ b/fs/nfsd/nfsd.h +@@ -328,12 +328,15 @@ void nfsd_lockd_shutdown(void); + (NFSD4_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SUPPATTR_EXCLCREAT) + + #ifdef CONFIG_NFSD_V4_SECURITY_LABEL +-#define NFSD4_2_SUPPORTED_ATTRS_WORD2 \ +- (NFSD4_1_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SECURITY_LABEL) ++#define NFSD4_2_SECURITY_ATTRS FATTR4_WORD2_SECURITY_LABEL + #else +-#define NFSD4_2_SUPPORTED_ATTRS_WORD2 0 ++#define NFSD4_2_SECURITY_ATTRS 0 + #endif + ++#define NFSD4_2_SUPPORTED_ATTRS_WORD2 \ ++ (NFSD4_1_SUPPORTED_ATTRS_WORD2 | \ ++ NFSD4_2_SECURITY_ATTRS) ++ + static inline u32 nfsd_suppattrs0(u32 minorversion) + { + return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0 +diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c +index 9a4a5f9..c34e45d 100644 +--- a/fs/nfsd/nfssvc.c ++++ b/fs/nfsd/nfssvc.c +@@ -221,7 +221,8 @@ static int nfsd_startup_generic(int nrservs) + */ + ret = nfsd_racache_init(2*nrservs); + if (ret) +- return ret; ++ goto dec_users; ++ + ret = nfs4_state_start(); + if (ret) + goto out_racache; +@@ -229,6 +230,8 @@ static int nfsd_startup_generic(int nrservs) + + out_racache: + nfsd_racache_shutdown(); ++dec_users: ++ nfsd_users--; + return ret; + } + +diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c +index b2e3ff3..090d8ce 100644 +--- a/fs/nilfs2/btree.c ++++ b/fs/nilfs2/btree.c +@@ -31,6 +31,8 @@ + #include "alloc.h" + #include "dat.h" + ++static void __nilfs_btree_init(struct nilfs_bmap *bmap); ++ + static struct nilfs_btree_path *nilfs_btree_alloc_path(void) + { + struct nilfs_btree_path *path; +@@ -368,6 +370,34 @@ static int nilfs_btree_node_broken(const struct nilfs_btree_node *node, + return ret; + } + ++/** ++ * nilfs_btree_root_broken - verify consistency of btree root node ++ * @node: btree root node to be examined ++ * @ino: inode number ++ * ++ * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned. ++ */ ++static int nilfs_btree_root_broken(const struct nilfs_btree_node *node, ++ unsigned long ino) ++{ ++ int level, flags, nchildren; ++ int ret = 0; ++ ++ level = nilfs_btree_node_get_level(node); ++ flags = nilfs_btree_node_get_flags(node); ++ nchildren = nilfs_btree_node_get_nchildren(node); ++ ++ if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN || ++ level >= NILFS_BTREE_LEVEL_MAX || ++ nchildren < 0 || ++ nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) { ++ pr_crit("NILFS: bad btree root (inode number=%lu): level = %d, flags = 0x%x, nchildren = %d\n", ++ ino, level, flags, nchildren); ++ ret = 1; ++ } ++ return ret; ++} ++ + int nilfs_btree_broken_node_block(struct buffer_head *bh) + { + int ret; +@@ -1713,7 +1743,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *btree, + + /* convert and insert */ + dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL; +- nilfs_btree_init(btree); ++ __nilfs_btree_init(btree); + if (nreq != NULL) { + nilfs_bmap_commit_alloc_ptr(btree, dreq, dat); + nilfs_bmap_commit_alloc_ptr(btree, nreq, dat); +@@ -2294,12 +2324,23 @@ static const struct nilfs_bmap_operations nilfs_btree_ops_gc = { + .bop_gather_data = NULL, + }; + +-int nilfs_btree_init(struct nilfs_bmap *bmap) ++static void __nilfs_btree_init(struct nilfs_bmap *bmap) + { + bmap->b_ops = &nilfs_btree_ops; + bmap->b_nchildren_per_block = + NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap)); +- return 0; ++} ++ ++int nilfs_btree_init(struct nilfs_bmap *bmap) ++{ ++ int ret = 0; ++ ++ __nilfs_btree_init(bmap); ++ ++ if (nilfs_btree_root_broken(nilfs_btree_get_root(bmap), ++ bmap->b_inode->i_ino)) ++ ret = -EIO; ++ return ret; + } + + void nilfs_btree_init_gc(struct nilfs_bmap *bmap) +diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c +index 7e350c5..09480c53 100644 +--- a/fs/nilfs2/inode.c ++++ b/fs/nilfs2/inode.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + #include "nilfs.h" +@@ -48,6 +49,8 @@ struct nilfs_iget_args { + int for_gc; + }; + ++static int nilfs_iget_test(struct inode *inode, void *opaque); ++ + void nilfs_inode_add_blocks(struct inode *inode, int n) + { + struct nilfs_root *root = NILFS_I(inode)->i_root; +@@ -219,10 +222,10 @@ static int nilfs_writepage(struct page *page, struct writeback_control *wbc) + + static int nilfs_set_page_dirty(struct page *page) + { ++ struct inode *inode = page->mapping->host; + int ret = __set_page_dirty_nobuffers(page); + + if (page_has_buffers(page)) { +- struct inode *inode = page->mapping->host; + unsigned nr_dirty = 0; + struct buffer_head *bh, *head; + +@@ -245,6 +248,10 @@ static int nilfs_set_page_dirty(struct page *page) + + if (nr_dirty) + nilfs_set_file_dirty(inode, nr_dirty); ++ } else if (ret) { ++ unsigned nr_dirty = 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits); ++ ++ nilfs_set_file_dirty(inode, nr_dirty); + } + return ret; + } +@@ -342,6 +349,17 @@ const struct address_space_operations nilfs_aops = { + .is_partially_uptodate = block_is_partially_uptodate, + }; + ++static int nilfs_insert_inode_locked(struct inode *inode, ++ struct nilfs_root *root, ++ unsigned long ino) ++{ ++ struct nilfs_iget_args args = { ++ .ino = ino, .root = root, .cno = 0, .for_gc = 0 ++ }; ++ ++ return insert_inode_locked4(inode, ino, nilfs_iget_test, &args); ++} ++ + struct inode *nilfs_new_inode(struct inode *dir, umode_t mode) + { + struct super_block *sb = dir->i_sb; +@@ -377,7 +395,7 @@ struct inode *nilfs_new_inode(struct inode *dir, umode_t mode) + if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { + err = nilfs_bmap_read(ii->i_bmap, NULL); + if (err < 0) +- goto failed_bmap; ++ goto failed_after_creation; + + set_bit(NILFS_I_BMAP, &ii->i_state); + /* No lock is needed; iget() ensures it. */ +@@ -393,21 +411,24 @@ struct inode *nilfs_new_inode(struct inode *dir, umode_t mode) + spin_lock(&nilfs->ns_next_gen_lock); + inode->i_generation = nilfs->ns_next_generation++; + spin_unlock(&nilfs->ns_next_gen_lock); +- insert_inode_hash(inode); ++ if (nilfs_insert_inode_locked(inode, root, ino) < 0) { ++ err = -EIO; ++ goto failed_after_creation; ++ } + + err = nilfs_init_acl(inode, dir); + if (unlikely(err)) +- goto failed_acl; /* never occur. When supporting ++ goto failed_after_creation; /* never occur. When supporting + nilfs_init_acl(), proper cancellation of + above jobs should be considered */ + + return inode; + +- failed_acl: +- failed_bmap: ++ failed_after_creation: + clear_nlink(inode); ++ unlock_new_inode(inode); + iput(inode); /* raw_inode will be deleted through +- generic_delete_inode() */ ++ nilfs_evict_inode() */ + goto failed; + + failed_ifile_create_inode: +@@ -455,8 +476,8 @@ int nilfs_read_inode_common(struct inode *inode, + inode->i_atime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec); + inode->i_ctime.tv_nsec = le32_to_cpu(raw_inode->i_ctime_nsec); + inode->i_mtime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec); +- if (inode->i_nlink == 0 && inode->i_mode == 0) +- return -EINVAL; /* this inode is deleted */ ++ if (inode->i_nlink == 0) ++ return -ESTALE; /* this inode is deleted */ + + inode->i_blocks = le64_to_cpu(raw_inode->i_blocks); + ii->i_flags = le32_to_cpu(raw_inode->i_flags); +diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c +index 9de78f0..0f84b25 100644 +--- a/fs/nilfs2/namei.c ++++ b/fs/nilfs2/namei.c +@@ -51,9 +51,11 @@ static inline int nilfs_add_nondir(struct dentry *dentry, struct inode *inode) + int err = nilfs_add_link(dentry, inode); + if (!err) { + d_instantiate(dentry, inode); ++ unlock_new_inode(inode); + return 0; + } + inode_dec_link_count(inode); ++ unlock_new_inode(inode); + iput(inode); + return err; + } +@@ -182,6 +184,7 @@ out: + out_fail: + drop_nlink(inode); + nilfs_mark_inode_dirty(inode); ++ unlock_new_inode(inode); + iput(inode); + goto out; + } +@@ -201,11 +204,15 @@ static int nilfs_link(struct dentry *old_dentry, struct inode *dir, + inode_inc_link_count(inode); + ihold(inode); + +- err = nilfs_add_nondir(dentry, inode); +- if (!err) ++ err = nilfs_add_link(dentry, inode); ++ if (!err) { ++ d_instantiate(dentry, inode); + err = nilfs_transaction_commit(dir->i_sb); +- else ++ } else { ++ inode_dec_link_count(inode); ++ iput(inode); + nilfs_transaction_abort(dir->i_sb); ++ } + + return err; + } +@@ -243,6 +250,7 @@ static int nilfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) + + nilfs_mark_inode_dirty(inode); + d_instantiate(dentry, inode); ++ unlock_new_inode(inode); + out: + if (!err) + err = nilfs_transaction_commit(dir->i_sb); +@@ -255,6 +263,7 @@ out_fail: + drop_nlink(inode); + drop_nlink(inode); + nilfs_mark_inode_dirty(inode); ++ unlock_new_inode(inode); + iput(inode); + out_dir: + drop_nlink(dir); +diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h +index 9bc72de..b02c202 100644 +--- a/fs/nilfs2/nilfs.h ++++ b/fs/nilfs2/nilfs.h +@@ -141,7 +141,6 @@ enum { + * @ti_save: Backup of journal_info field of task_struct + * @ti_flags: Flags + * @ti_count: Nest level +- * @ti_garbage: List of inode to be put when releasing semaphore + */ + struct nilfs_transaction_info { + u32 ti_magic; +@@ -150,7 +149,6 @@ struct nilfs_transaction_info { + one of other filesystems has a bug. */ + unsigned short ti_flags; + unsigned short ti_count; +- struct list_head ti_garbage; + }; + + /* ti_magic */ +diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c +index a1a1916..14538a8 100644 +--- a/fs/nilfs2/segment.c ++++ b/fs/nilfs2/segment.c +@@ -305,7 +305,6 @@ static void nilfs_transaction_lock(struct super_block *sb, + ti->ti_count = 0; + ti->ti_save = cur_ti; + ti->ti_magic = NILFS_TI_MAGIC; +- INIT_LIST_HEAD(&ti->ti_garbage); + current->journal_info = ti; + + for (;;) { +@@ -332,8 +331,6 @@ static void nilfs_transaction_unlock(struct super_block *sb) + + up_write(&nilfs->ns_segctor_sem); + current->journal_info = ti->ti_save; +- if (!list_empty(&ti->ti_garbage)) +- nilfs_dispose_list(nilfs, &ti->ti_garbage, 0); + } + + static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci, +@@ -746,6 +743,15 @@ static void nilfs_dispose_list(struct the_nilfs *nilfs, + } + } + ++static void nilfs_iput_work_func(struct work_struct *work) ++{ ++ struct nilfs_sc_info *sci = container_of(work, struct nilfs_sc_info, ++ sc_iput_work); ++ struct the_nilfs *nilfs = sci->sc_super->s_fs_info; ++ ++ nilfs_dispose_list(nilfs, &sci->sc_iput_queue, 0); ++} ++ + static int nilfs_test_metadata_dirty(struct the_nilfs *nilfs, + struct nilfs_root *root) + { +@@ -1899,8 +1905,9 @@ static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci, + static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, + struct the_nilfs *nilfs) + { +- struct nilfs_transaction_info *ti = current->journal_info; + struct nilfs_inode_info *ii, *n; ++ int during_mount = !(sci->sc_super->s_flags & MS_ACTIVE); ++ int defer_iput = false; + + spin_lock(&nilfs->ns_inode_lock); + list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) { +@@ -1911,9 +1918,24 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, + clear_bit(NILFS_I_BUSY, &ii->i_state); + brelse(ii->i_bh); + ii->i_bh = NULL; +- list_move_tail(&ii->i_dirty, &ti->ti_garbage); ++ list_del_init(&ii->i_dirty); ++ if (!ii->vfs_inode.i_nlink || during_mount) { ++ /* ++ * Defer calling iput() to avoid deadlocks if ++ * i_nlink == 0 or mount is not yet finished. ++ */ ++ list_add_tail(&ii->i_dirty, &sci->sc_iput_queue); ++ defer_iput = true; ++ } else { ++ spin_unlock(&nilfs->ns_inode_lock); ++ iput(&ii->vfs_inode); ++ spin_lock(&nilfs->ns_inode_lock); ++ } + } + spin_unlock(&nilfs->ns_inode_lock); ++ ++ if (defer_iput) ++ schedule_work(&sci->sc_iput_work); + } + + /* +@@ -2580,6 +2602,8 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb, + INIT_LIST_HEAD(&sci->sc_segbufs); + INIT_LIST_HEAD(&sci->sc_write_logs); + INIT_LIST_HEAD(&sci->sc_gc_inodes); ++ INIT_LIST_HEAD(&sci->sc_iput_queue); ++ INIT_WORK(&sci->sc_iput_work, nilfs_iput_work_func); + init_timer(&sci->sc_timer); + + sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT; +@@ -2606,6 +2630,8 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) + ret = nilfs_segctor_construct(sci, SC_LSEG_SR); + nilfs_transaction_unlock(sci->sc_super); + ++ flush_work(&sci->sc_iput_work); ++ + } while (ret && retrycount-- > 0); + } + +@@ -2630,6 +2656,9 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) + || sci->sc_seq_request != sci->sc_seq_done); + spin_unlock(&sci->sc_state_lock); + ++ if (flush_work(&sci->sc_iput_work)) ++ flag = true; ++ + if (flag || !nilfs_segctor_confirm(sci)) + nilfs_segctor_write_out(sci); + +@@ -2639,6 +2668,12 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) + nilfs_dispose_list(nilfs, &sci->sc_dirty_files, 1); + } + ++ if (!list_empty(&sci->sc_iput_queue)) { ++ nilfs_warning(sci->sc_super, __func__, ++ "iput queue is not empty\n"); ++ nilfs_dispose_list(nilfs, &sci->sc_iput_queue, 1); ++ } ++ + WARN_ON(!list_empty(&sci->sc_segbufs)); + WARN_ON(!list_empty(&sci->sc_write_logs)); + +diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h +index 38a1d00..a48d6de 100644 +--- a/fs/nilfs2/segment.h ++++ b/fs/nilfs2/segment.h +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include "nilfs.h" + +@@ -92,6 +93,8 @@ struct nilfs_segsum_pointer { + * @sc_nblk_inc: Block count of current generation + * @sc_dirty_files: List of files to be written + * @sc_gc_inodes: List of GC inodes having blocks to be written ++ * @sc_iput_queue: list of inodes for which iput should be done ++ * @sc_iput_work: work struct to defer iput call + * @sc_freesegs: array of segment numbers to be freed + * @sc_nfreesegs: number of segments on @sc_freesegs + * @sc_dsync_inode: inode whose data pages are written for a sync operation +@@ -135,6 +138,8 @@ struct nilfs_sc_info { + + struct list_head sc_dirty_files; + struct list_head sc_gc_inodes; ++ struct list_head sc_iput_queue; ++ struct work_struct sc_iput_work; + + __u64 *sc_freesegs; + size_t sc_nfreesegs; +diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c +index 287a22c..de6323e 100644 +--- a/fs/notify/fanotify/fanotify_user.c ++++ b/fs/notify/fanotify/fanotify_user.c +@@ -71,7 +71,7 @@ static int create_fd(struct fsnotify_group *group, + + pr_debug("%s: group=%p event=%p\n", __func__, group, event); + +- client_fd = get_unused_fd(); ++ client_fd = get_unused_fd_flags(group->fanotify_data.f_flags); + if (client_fd < 0) + return client_fd; + +diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c +index 238a593..9d7e2b9 100644 +--- a/fs/notify/fdinfo.c ++++ b/fs/notify/fdinfo.c +@@ -42,7 +42,7 @@ static int show_mark_fhandle(struct seq_file *m, struct inode *inode) + { + struct { + struct file_handle handle; +- u8 pad[64]; ++ u8 pad[MAX_HANDLE_SZ]; + } f; + int size, ret, i; + +@@ -50,7 +50,7 @@ static int show_mark_fhandle(struct seq_file *m, struct inode *inode) + size = f.handle.handle_bytes >> 2; + + ret = exportfs_encode_inode_fh(inode, (struct fid *)f.handle.f_handle, &size, 0); +- if ((ret == 255) || (ret == -ENOSPC)) { ++ if ((ret == FILEID_INVALID) || (ret < 0)) { + WARN_ONCE(1, "Can't encode file handler for inotify: %d\n", ret); + return 0; + } +diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c +index 9d3e9c5..7001299 100644 +--- a/fs/notify/fsnotify.c ++++ b/fs/notify/fsnotify.c +@@ -63,14 +63,14 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) + spin_lock(&inode->i_lock); + /* run all of the dentries associated with this inode. Since this is a + * directory, there damn well better only be one item on this list */ +- hlist_for_each_entry(alias, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) { + struct dentry *child; + + /* run all of the children of the original inode and fix their + * d_flags to indicate parental interest (their parent is the + * original inode) */ + spin_lock(&alias->d_lock); +- list_for_each_entry(child, &alias->d_subdirs, d_u.d_child) { ++ list_for_each_entry(child, &alias->d_subdirs, d_child) { + if (!child->d_inode) + continue; + +diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c +index 74825be..fbb9dfb 100644 +--- a/fs/notify/inode_mark.c ++++ b/fs/notify/inode_mark.c +@@ -288,20 +288,25 @@ void fsnotify_unmount_inodes(struct list_head *list) + spin_unlock(&inode->i_lock); + + /* In case the dropping of a reference would nuke next_i. */ +- if ((&next_i->i_sb_list != list) && +- atomic_read(&next_i->i_count)) { ++ while (&next_i->i_sb_list != list) { + spin_lock(&next_i->i_lock); +- if (!(next_i->i_state & (I_FREEING | I_WILL_FREE))) { ++ if (!(next_i->i_state & (I_FREEING | I_WILL_FREE)) && ++ atomic_read(&next_i->i_count)) { + __iget(next_i); + need_iput = next_i; ++ spin_unlock(&next_i->i_lock); ++ break; + } + spin_unlock(&next_i->i_lock); ++ next_i = list_entry(next_i->i_sb_list.next, ++ struct inode, i_sb_list); + } + + /* +- * We can safely drop inode_sb_list_lock here because we hold +- * references on both inode and next_i. Also no new inodes +- * will be added since the umount has begun. ++ * We can safely drop inode_sb_list_lock here because either ++ * we actually hold references on both inode and next_i or ++ * end of list. Also no new inodes will be added since the ++ * umount has begun. + */ + spin_unlock(&inode_sb_list_lock); + +diff --git a/fs/notify/mark.c b/fs/notify/mark.c +index 923fe4a..6bffc33 100644 +--- a/fs/notify/mark.c ++++ b/fs/notify/mark.c +@@ -293,16 +293,36 @@ void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group, + unsigned int flags) + { + struct fsnotify_mark *lmark, *mark; ++ LIST_HEAD(to_free); + ++ /* ++ * We have to be really careful here. Anytime we drop mark_mutex, e.g. ++ * fsnotify_clear_marks_by_inode() can come and free marks. Even in our ++ * to_free list so we have to use mark_mutex even when accessing that ++ * list. And freeing mark requires us to drop mark_mutex. So we can ++ * reliably free only the first mark in the list. That's why we first ++ * move marks to free to to_free list in one go and then free marks in ++ * to_free list one by one. ++ */ + mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); + list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) { +- if (mark->flags & flags) { +- fsnotify_get_mark(mark); +- fsnotify_destroy_mark_locked(mark, group); +- fsnotify_put_mark(mark); +- } ++ if (mark->flags & flags) ++ list_move(&mark->g_list, &to_free); + } + mutex_unlock(&group->mark_mutex); ++ ++ while (1) { ++ mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); ++ if (list_empty(&to_free)) { ++ mutex_unlock(&group->mark_mutex); ++ break; ++ } ++ mark = list_first_entry(&to_free, struct fsnotify_mark, g_list); ++ fsnotify_get_mark(mark); ++ fsnotify_destroy_mark_locked(mark, group); ++ mutex_unlock(&group->mark_mutex); ++ fsnotify_put_mark(mark); ++ } + } + + /* +diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c +index a27e3fe..250ed5b 100644 +--- a/fs/ntfs/attrib.c ++++ b/fs/ntfs/attrib.c +@@ -1748,7 +1748,6 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size) + if (page) { + set_page_dirty(page); + unlock_page(page); +- mark_page_accessed(page); + page_cache_release(page); + } + ntfs_debug("Done."); +diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c +index db9bd8a..86ddab9 100644 +--- a/fs/ntfs/file.c ++++ b/fs/ntfs/file.c +@@ -2060,7 +2060,6 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb, + } + do { + unlock_page(pages[--do_pages]); +- mark_page_accessed(pages[do_pages]); + page_cache_release(pages[do_pages]); + } while (do_pages); + if (unlikely(status)) +diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c +index aeb44e8..bb6ee06 100644 +--- a/fs/ocfs2/aops.c ++++ b/fs/ocfs2/aops.c +@@ -899,7 +899,7 @@ void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages) + } + } + +-static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) ++static void ocfs2_unlock_pages(struct ocfs2_write_ctxt *wc) + { + int i; + +@@ -920,7 +920,11 @@ static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) + page_cache_release(wc->w_target_page); + } + ocfs2_unlock_and_free_pages(wc->w_pages, wc->w_num_pages); ++} + ++static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) ++{ ++ ocfs2_unlock_pages(wc); + brelse(wc->w_di_bh); + kfree(wc); + } +@@ -2045,11 +2049,19 @@ out_write_size: + di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); + ocfs2_journal_dirty(handle, wc->w_di_bh); + ++ /* unlock pages before dealloc since it needs acquiring j_trans_barrier ++ * lock, or it will cause a deadlock since journal commit threads holds ++ * this lock and will ask for the page lock when flushing the data. ++ * put it here to preserve the unlock order. ++ */ ++ ocfs2_unlock_pages(wc); ++ + ocfs2_commit_trans(osb, handle); + + ocfs2_run_deallocs(osb, &wc->w_dealloc); + +- ocfs2_free_write_ctxt(wc); ++ brelse(wc->w_di_bh); ++ kfree(wc); + + return copied; + } +diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c +index 0d3a97d..1167485 100644 +--- a/fs/ocfs2/dcache.c ++++ b/fs/ocfs2/dcache.c +@@ -173,7 +173,7 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode, + struct dentry *dentry; + + spin_lock(&inode->i_lock); +- hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { ++ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) { + spin_lock(&dentry->d_lock); + if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) { + trace_ocfs2_find_local_alias(dentry->d_name.len, +diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c +index af3f7aa..1dd0bcc 100644 +--- a/fs/ocfs2/dlm/dlmmaster.c ++++ b/fs/ocfs2/dlm/dlmmaster.c +@@ -650,12 +650,9 @@ void dlm_lockres_clear_refmap_bit(struct dlm_ctxt *dlm, + clear_bit(bit, res->refmap); + } + +- +-void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, ++static void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res) + { +- assert_spin_locked(&res->spinlock); +- + res->inflight_locks++; + + mlog(0, "%s: res %.*s, inflight++: now %u, %ps()\n", dlm->name, +@@ -663,6 +660,13 @@ void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, + __builtin_return_address(0)); + } + ++void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm, ++ struct dlm_lock_resource *res) ++{ ++ assert_spin_locked(&res->spinlock); ++ __dlm_lockres_grab_inflight_ref(dlm, res); ++} ++ + void dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res) + { +@@ -722,6 +726,19 @@ lookup: + if (tmpres) { + spin_unlock(&dlm->spinlock); + spin_lock(&tmpres->spinlock); ++ ++ /* ++ * Right after dlm spinlock was released, dlm_thread could have ++ * purged the lockres. Check if lockres got unhashed. If so ++ * start over. ++ */ ++ if (hlist_unhashed(&tmpres->hash_node)) { ++ spin_unlock(&tmpres->spinlock); ++ dlm_lockres_put(tmpres); ++ tmpres = NULL; ++ goto lookup; ++ } ++ + /* Wait on the thread that is mastering the resource */ + if (tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN) { + __dlm_wait_on_lockres(tmpres); +@@ -852,10 +869,8 @@ lookup: + /* finally add the lockres to its hash bucket */ + __dlm_insert_lockres(dlm, res); + +- /* Grab inflight ref to pin the resource */ +- spin_lock(&res->spinlock); +- dlm_lockres_grab_inflight_ref(dlm, res); +- spin_unlock(&res->spinlock); ++ /* since this lockres is new it doesn't not require the spinlock */ ++ __dlm_lockres_grab_inflight_ref(dlm, res); + + /* get an extra ref on the mle in case this is a BLOCK + * if so, the creator of the BLOCK may try to put the last +diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c +index 1998695..fa74259 100644 +--- a/fs/ocfs2/dlmglue.c ++++ b/fs/ocfs2/dlmglue.c +@@ -3973,9 +3973,13 @@ static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb) + osb->dc_work_sequence = osb->dc_wake_sequence; + + processed = osb->blocked_lock_count; +- while (processed) { +- BUG_ON(list_empty(&osb->blocked_lock_list)); +- ++ /* ++ * blocked lock processing in this loop might call iput which can ++ * remove items off osb->blocked_lock_list. Downconvert up to ++ * 'processed' number of locks, but stop short if we had some ++ * removed in ocfs2_mark_lockres_freeing when downconverting. ++ */ ++ while (processed && !list_empty(&osb->blocked_lock_list)) { + lockres = list_entry(osb->blocked_lock_list.next, + struct ocfs2_lock_res, l_blocked_list); + list_del_init(&lockres->l_blocked_list); +diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c +index 51632c4..35f54bc 100644 +--- a/fs/ocfs2/file.c ++++ b/fs/ocfs2/file.c +@@ -2391,10 +2391,14 @@ out_dio: + /* buffered aio wouldn't have proper lock coverage today */ + BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); + ++ if (unlikely(written <= 0)) ++ goto no_sync; ++ + if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) || + ((file->f_flags & O_DIRECT) && !direct_io)) { +- ret = filemap_fdatawrite_range(file->f_mapping, *ppos, +- *ppos + count - 1); ++ ret = filemap_fdatawrite_range(file->f_mapping, ++ iocb->ki_pos - written, ++ iocb->ki_pos - 1); + if (ret < 0) + written = ret; + +@@ -2407,10 +2411,12 @@ out_dio: + } + + if (!ret) +- ret = filemap_fdatawait_range(file->f_mapping, *ppos, +- *ppos + count - 1); ++ ret = filemap_fdatawait_range(file->f_mapping, ++ iocb->ki_pos - written, ++ iocb->ki_pos - 1); + } + ++no_sync: + /* + * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io + * function pointer which is called when o_direct io completes so that +@@ -2472,9 +2478,7 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, + struct address_space *mapping = out->f_mapping; + struct inode *inode = mapping->host; + struct splice_desc sd = { +- .total_len = len, + .flags = flags, +- .pos = *ppos, + .u.file = out, + }; + +@@ -2484,6 +2488,12 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, + out->f_path.dentry->d_name.len, + out->f_path.dentry->d_name.name, len); + ++ ret = generic_write_checks(out, ppos, &len, 0); ++ if (ret) ++ return ret; ++ sd.total_len = len; ++ sd.pos = *ppos; ++ + pipe_lock(pipe); + + splice_from_pipe_begin(&sd); +diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c +index feed025f..b242762 100644 +--- a/fs/ocfs2/namei.c ++++ b/fs/ocfs2/namei.c +@@ -94,6 +94,14 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb, + struct inode *inode, + const char *symname); + ++static int ocfs2_double_lock(struct ocfs2_super *osb, ++ struct buffer_head **bh1, ++ struct inode *inode1, ++ struct buffer_head **bh2, ++ struct inode *inode2, ++ int rename); ++ ++static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2); + /* An orphan dir name is an 8 byte value, printed as a hex string */ + #define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64))) + +@@ -656,8 +664,10 @@ static int ocfs2_link(struct dentry *old_dentry, + { + handle_t *handle; + struct inode *inode = old_dentry->d_inode; ++ struct inode *old_dir = old_dentry->d_parent->d_inode; + int err; + struct buffer_head *fe_bh = NULL; ++ struct buffer_head *old_dir_bh = NULL; + struct buffer_head *parent_fe_bh = NULL; + struct ocfs2_dinode *fe = NULL; + struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); +@@ -674,19 +684,33 @@ static int ocfs2_link(struct dentry *old_dentry, + + dquot_initialize(dir); + +- err = ocfs2_inode_lock_nested(dir, &parent_fe_bh, 1, OI_LS_PARENT); ++ err = ocfs2_double_lock(osb, &old_dir_bh, old_dir, ++ &parent_fe_bh, dir, 0); + if (err < 0) { + if (err != -ENOENT) + mlog_errno(err); + return err; + } + ++ /* make sure both dirs have bhs ++ * get an extra ref on old_dir_bh if old==new */ ++ if (!parent_fe_bh) { ++ if (old_dir_bh) { ++ parent_fe_bh = old_dir_bh; ++ get_bh(parent_fe_bh); ++ } else { ++ mlog(ML_ERROR, "%s: no old_dir_bh!\n", osb->uuid_str); ++ err = -EIO; ++ goto out; ++ } ++ } ++ + if (!dir->i_nlink) { + err = -ENOENT; + goto out; + } + +- err = ocfs2_lookup_ino_from_name(dir, old_dentry->d_name.name, ++ err = ocfs2_lookup_ino_from_name(old_dir, old_dentry->d_name.name, + old_dentry->d_name.len, &old_de_ino); + if (err) { + err = -ENOENT; +@@ -779,10 +803,11 @@ out_unlock_inode: + ocfs2_inode_unlock(inode, 1); + + out: +- ocfs2_inode_unlock(dir, 1); ++ ocfs2_double_unlock(old_dir, dir); + + brelse(fe_bh); + brelse(parent_fe_bh); ++ brelse(old_dir_bh); + + ocfs2_free_dir_lookup_result(&lookup); + +@@ -991,14 +1016,15 @@ leave: + } + + /* +- * The only place this should be used is rename! ++ * The only place this should be used is rename and link! + * if they have the same id, then the 1st one is the only one locked. + */ + static int ocfs2_double_lock(struct ocfs2_super *osb, + struct buffer_head **bh1, + struct inode *inode1, + struct buffer_head **bh2, +- struct inode *inode2) ++ struct inode *inode2, ++ int rename) + { + int status; + struct ocfs2_inode_info *oi1 = OCFS2_I(inode1); +@@ -1028,7 +1054,7 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, + } + /* lock id2 */ + status = ocfs2_inode_lock_nested(inode2, bh2, 1, +- OI_LS_RENAME1); ++ rename == 1 ? OI_LS_RENAME1 : OI_LS_PARENT); + if (status < 0) { + if (status != -ENOENT) + mlog_errno(status); +@@ -1037,7 +1063,8 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, + } + + /* lock id1 */ +- status = ocfs2_inode_lock_nested(inode1, bh1, 1, OI_LS_RENAME2); ++ status = ocfs2_inode_lock_nested(inode1, bh1, 1, ++ rename == 1 ? OI_LS_RENAME2 : OI_LS_PARENT); + if (status < 0) { + /* + * An error return must mean that no cluster locks +@@ -1137,7 +1164,7 @@ static int ocfs2_rename(struct inode *old_dir, + + /* if old and new are the same, this'll just do one lock. */ + status = ocfs2_double_lock(osb, &old_dir_bh, old_dir, +- &new_dir_bh, new_dir); ++ &new_dir_bh, new_dir, 1); + if (status < 0) { + mlog_errno(status); + goto bail; +diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c +index d8b0afd..2dba0ca 100644 +--- a/fs/omfs/inode.c ++++ b/fs/omfs/inode.c +@@ -361,7 +361,7 @@ nomem: + } + + enum { +- Opt_uid, Opt_gid, Opt_umask, Opt_dmask, Opt_fmask ++ Opt_uid, Opt_gid, Opt_umask, Opt_dmask, Opt_fmask, Opt_err + }; + + static const match_table_t tokens = { +@@ -370,6 +370,7 @@ static const match_table_t tokens = { + {Opt_umask, "umask=%o"}, + {Opt_dmask, "dmask=%o"}, + {Opt_fmask, "fmask=%o"}, ++ {Opt_err, NULL}, + }; + + static int parse_options(char *options, struct omfs_sb_info *sbi) +diff --git a/fs/open.c b/fs/open.c +index 2ed7325..17679f2 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -539,6 +539,7 @@ static int chown_common(struct path *path, uid_t user, gid_t group) + uid = make_kuid(current_user_ns(), user); + gid = make_kgid(current_user_ns(), group); + ++retry_deleg: + newattrs.ia_valid = ATTR_CTIME; + if (user != (uid_t) -1) { + if (!uid_valid(uid)) +@@ -555,7 +556,6 @@ static int chown_common(struct path *path, uid_t user, gid_t group) + if (!S_ISDIR(inode->i_mode)) + newattrs.ia_valid |= + ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; +-retry_deleg: + mutex_lock(&inode->i_mutex); + error = security_path_chown(path, uid, gid); + if (!error) +diff --git a/fs/pipe.c b/fs/pipe.c +index 78fd0d0..46f1ab2 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -117,25 +117,27 @@ void pipe_wait(struct pipe_inode_info *pipe) + } + + static int +-pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len, +- int atomic) ++pipe_iov_copy_from_user(void *addr, int *offset, struct iovec *iov, ++ size_t *remaining, int atomic) + { + unsigned long copy; + +- while (len > 0) { ++ while (*remaining > 0) { + while (!iov->iov_len) + iov++; +- copy = min_t(unsigned long, len, iov->iov_len); ++ copy = min_t(unsigned long, *remaining, iov->iov_len); + + if (atomic) { +- if (__copy_from_user_inatomic(to, iov->iov_base, copy)) ++ if (__copy_from_user_inatomic(addr + *offset, ++ iov->iov_base, copy)) + return -EFAULT; + } else { +- if (copy_from_user(to, iov->iov_base, copy)) ++ if (copy_from_user(addr + *offset, ++ iov->iov_base, copy)) + return -EFAULT; + } +- to += copy; +- len -= copy; ++ *offset += copy; ++ *remaining -= copy; + iov->iov_base += copy; + iov->iov_len -= copy; + } +@@ -143,25 +145,27 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len, + } + + static int +-pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len, +- int atomic) ++pipe_iov_copy_to_user(struct iovec *iov, void *addr, int *offset, ++ size_t *remaining, int atomic) + { + unsigned long copy; + +- while (len > 0) { ++ while (*remaining > 0) { + while (!iov->iov_len) + iov++; +- copy = min_t(unsigned long, len, iov->iov_len); ++ copy = min_t(unsigned long, *remaining, iov->iov_len); + + if (atomic) { +- if (__copy_to_user_inatomic(iov->iov_base, from, copy)) ++ if (__copy_to_user_inatomic(iov->iov_base, ++ addr + *offset, copy)) + return -EFAULT; + } else { +- if (copy_to_user(iov->iov_base, from, copy)) ++ if (copy_to_user(iov->iov_base, ++ addr + *offset, copy)) + return -EFAULT; + } +- from += copy; +- len -= copy; ++ *offset += copy; ++ *remaining -= copy; + iov->iov_base += copy; + iov->iov_len -= copy; + } +@@ -395,7 +399,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, + struct pipe_buffer *buf = pipe->bufs + curbuf; + const struct pipe_buf_operations *ops = buf->ops; + void *addr; +- size_t chars = buf->len; ++ size_t chars = buf->len, remaining; + int error, atomic; + + if (chars > total_len) +@@ -409,9 +413,11 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, + } + + atomic = !iov_fault_in_pages_write(iov, chars); ++ remaining = chars; + redo: + addr = ops->map(pipe, buf, atomic); +- error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars, atomic); ++ error = pipe_iov_copy_to_user(iov, addr, &buf->offset, ++ &remaining, atomic); + ops->unmap(pipe, buf, addr); + if (unlikely(error)) { + /* +@@ -426,7 +432,6 @@ redo: + break; + } + ret += chars; +- buf->offset += chars; + buf->len -= chars; + + /* Was it a packet buffer? Clean up and exit */ +@@ -531,6 +536,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov, + if (ops->can_merge && offset + chars <= PAGE_SIZE) { + int error, atomic = 1; + void *addr; ++ size_t remaining = chars; + + error = ops->confirm(pipe, buf); + if (error) +@@ -539,8 +545,8 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov, + iov_fault_in_pages_read(iov, chars); + redo1: + addr = ops->map(pipe, buf, atomic); +- error = pipe_iov_copy_from_user(offset + addr, iov, +- chars, atomic); ++ error = pipe_iov_copy_from_user(addr, &offset, iov, ++ &remaining, atomic); + ops->unmap(pipe, buf, addr); + ret = error; + do_wakeup = 1; +@@ -575,6 +581,8 @@ redo1: + struct page *page = pipe->tmp_page; + char *src; + int error, atomic = 1; ++ int offset = 0; ++ size_t remaining; + + if (!page) { + page = alloc_page(GFP_HIGHUSER); +@@ -595,14 +603,15 @@ redo1: + chars = total_len; + + iov_fault_in_pages_read(iov, chars); ++ remaining = chars; + redo2: + if (atomic) + src = kmap_atomic(page); + else + src = kmap(page); + +- error = pipe_iov_copy_from_user(src, iov, chars, +- atomic); ++ error = pipe_iov_copy_from_user(src, &offset, iov, ++ &remaining, atomic); + if (atomic) + kunmap_atomic(src); + else +diff --git a/fs/pnode.c b/fs/pnode.c +index a364a70..b7f8310 100644 +--- a/fs/pnode.c ++++ b/fs/pnode.c +@@ -381,6 +381,7 @@ static void __propagate_umount(struct mount *mnt) + * other children + */ + if (child && list_empty(&child->mnt_mounts)) { ++ list_del_init(&child->mnt_child); + hlist_del_init_rcu(&child->mnt_hash); + hlist_add_before_rcu(&child->mnt_hash, &mnt->mnt_hash); + } +diff --git a/fs/proc/array.c b/fs/proc/array.c +index 656e401..baf3464 100644 +--- a/fs/proc/array.c ++++ b/fs/proc/array.c +@@ -297,15 +297,11 @@ static void render_cap_t(struct seq_file *m, const char *header, + seq_puts(m, header); + CAP_FOR_EACH_U32(__capi) { + seq_printf(m, "%08x", +- a->cap[(_KERNEL_CAPABILITY_U32S-1) - __capi]); ++ a->cap[CAP_LAST_U32 - __capi]); + } + seq_putc(m, '\n'); + } + +-/* Remove non-existent capabilities */ +-#define NORM_CAPS(v) (v.cap[CAP_TO_INDEX(CAP_LAST_CAP)] &= \ +- CAP_TO_MASK(CAP_LAST_CAP + 1) - 1) +- + static inline void task_cap(struct seq_file *m, struct task_struct *p) + { + const struct cred *cred; +@@ -319,11 +315,6 @@ static inline void task_cap(struct seq_file *m, struct task_struct *p) + cap_bset = cred->cap_bset; + rcu_read_unlock(); + +- NORM_CAPS(cap_inheritable); +- NORM_CAPS(cap_permitted); +- NORM_CAPS(cap_effective); +- NORM_CAPS(cap_bset); +- + render_cap_t(m, "CapInh:\t", &cap_inheritable); + render_cap_t(m, "CapPrm:\t", &cap_permitted); + render_cap_t(m, "CapEff:\t", &cap_effective); +diff --git a/fs/proc/base.c b/fs/proc/base.c +index b976062..489ba8c 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -2555,6 +2555,57 @@ static const struct file_operations proc_projid_map_operations = { + .llseek = seq_lseek, + .release = proc_id_map_release, + }; ++ ++static int proc_setgroups_open(struct inode *inode, struct file *file) ++{ ++ struct user_namespace *ns = NULL; ++ struct task_struct *task; ++ int ret; ++ ++ ret = -ESRCH; ++ task = get_proc_task(inode); ++ if (task) { ++ rcu_read_lock(); ++ ns = get_user_ns(task_cred_xxx(task, user_ns)); ++ rcu_read_unlock(); ++ put_task_struct(task); ++ } ++ if (!ns) ++ goto err; ++ ++ if (file->f_mode & FMODE_WRITE) { ++ ret = -EACCES; ++ if (!ns_capable(ns, CAP_SYS_ADMIN)) ++ goto err_put_ns; ++ } ++ ++ ret = single_open(file, &proc_setgroups_show, ns); ++ if (ret) ++ goto err_put_ns; ++ ++ return 0; ++err_put_ns: ++ put_user_ns(ns); ++err: ++ return ret; ++} ++ ++static int proc_setgroups_release(struct inode *inode, struct file *file) ++{ ++ struct seq_file *seq = file->private_data; ++ struct user_namespace *ns = seq->private; ++ int ret = single_release(inode, file); ++ put_user_ns(ns); ++ return ret; ++} ++ ++static const struct file_operations proc_setgroups_operations = { ++ .open = proc_setgroups_open, ++ .write = proc_setgroups_write, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = proc_setgroups_release, ++}; + #endif /* CONFIG_USER_NS */ + + static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns, +@@ -2663,6 +2714,7 @@ static const struct pid_entry tgid_base_stuff[] = { + REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations), + REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations), + REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations), ++ REG("setgroups", S_IRUGO|S_IWUSR, proc_setgroups_operations), + #endif + #ifdef CONFIG_CHECKPOINT_RESTORE + REG("timers", S_IRUGO, proc_timers_operations), +@@ -2998,6 +3050,7 @@ static const struct pid_entry tid_base_stuff[] = { + REG("uid_map", S_IRUGO|S_IWUSR, proc_uid_map_operations), + REG("gid_map", S_IRUGO|S_IWUSR, proc_gid_map_operations), + REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations), ++ REG("setgroups", S_IRUGO|S_IWUSR, proc_setgroups_operations), + #endif + }; + +diff --git a/fs/proc/generic.c b/fs/proc/generic.c +index b7f268e..2e2d9d5 100644 +--- a/fs/proc/generic.c ++++ b/fs/proc/generic.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -162,17 +161,6 @@ void proc_free_inum(unsigned int inum) + spin_unlock_irqrestore(&proc_inum_lock, flags); + } + +-static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd) +-{ +- nd_set_link(nd, __PDE_DATA(dentry->d_inode)); +- return NULL; +-} +- +-static const struct inode_operations proc_link_inode_operations = { +- .readlink = generic_readlink, +- .follow_link = proc_follow_link, +-}; +- + /* + * Don't create negative dentries here, return -ENOENT by hand + * instead. +diff --git a/fs/proc/inode.c b/fs/proc/inode.c +index 124fc43..2f2815f 100644 +--- a/fs/proc/inode.c ++++ b/fs/proc/inode.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + #include + +@@ -401,6 +402,26 @@ static const struct file_operations proc_reg_file_ops_no_compat = { + }; + #endif + ++static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd) ++{ ++ struct proc_dir_entry *pde = PDE(dentry->d_inode); ++ if (unlikely(!use_pde(pde))) ++ return ERR_PTR(-EINVAL); ++ nd_set_link(nd, pde->data); ++ return pde; ++} ++ ++static void proc_put_link(struct dentry *dentry, struct nameidata *nd, void *p) ++{ ++ unuse_pde(p); ++} ++ ++const struct inode_operations proc_link_inode_operations = { ++ .readlink = generic_readlink, ++ .follow_link = proc_follow_link, ++ .put_link = proc_put_link, ++}; ++ + struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) + { + struct inode *inode = new_inode_pseudo(sb); +diff --git a/fs/proc/internal.h b/fs/proc/internal.h +index 651d09a..8b8ca1d 100644 +--- a/fs/proc/internal.h ++++ b/fs/proc/internal.h +@@ -202,6 +202,7 @@ struct pde_opener { + int closing; + struct completion *c; + }; ++extern const struct inode_operations proc_link_inode_operations; + + extern const struct inode_operations proc_pid_link_inode_operations; + +diff --git a/fs/proc/stat.c b/fs/proc/stat.c +index 6f599c6..dbd0272 100644 +--- a/fs/proc/stat.c ++++ b/fs/proc/stat.c +@@ -159,7 +159,7 @@ static int show_stat(struct seq_file *p, void *v) + + /* sum again ? it could be updated? */ + for_each_irq_nr(j) +- seq_put_decimal_ull(p, ' ', kstat_irqs(j)); ++ seq_put_decimal_ull(p, ' ', kstat_irqs_usr(j)); + + seq_printf(p, + "\nctxt %llu\n" +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index 8f78819..eaa7374 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -1,4 +1,5 @@ + #include ++#include + #include + #include + #include +@@ -152,7 +153,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) + + /* + * We remember last_addr rather than next_addr to hit with +- * mmap_cache most of the time. We have zero last_addr at ++ * vmacache most of the time. We have zero last_addr at + * the beginning and also after lseek. We will have -1 last_addr + * after the end of the vmas. + */ +@@ -992,9 +993,8 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, + struct vm_area_struct *vma; + struct pagemapread *pm = walk->private; + spinlock_t *ptl; +- pte_t *pte; ++ pte_t *pte, *orig_pte; + int err = 0; +- pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2)); + + /* find the first VMA at or above 'addr' */ + vma = find_vma(walk->mm, addr); +@@ -1008,6 +1008,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, + + for (; addr != end; addr += PAGE_SIZE) { + unsigned long offset; ++ pagemap_entry_t pme; + + offset = (addr & ~PAGEMAP_WALK_MASK) >> + PAGE_SHIFT; +@@ -1022,32 +1023,55 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, + + if (pmd_trans_unstable(pmd)) + return 0; +- for (; addr != end; addr += PAGE_SIZE) { +- int flags2; +- +- /* check to see if we've left 'vma' behind +- * and need a new, higher one */ +- if (vma && (addr >= vma->vm_end)) { +- vma = find_vma(walk->mm, addr); +- if (vma && (vma->vm_flags & VM_SOFTDIRTY)) +- flags2 = __PM_SOFT_DIRTY; +- else +- flags2 = 0; +- pme = make_pme(PM_NOT_PRESENT(pm->v2) | PM_STATUS2(pm->v2, flags2)); ++ ++ while (1) { ++ /* End of address space hole, which we mark as non-present. */ ++ unsigned long hole_end; ++ ++ if (vma) ++ hole_end = min(end, vma->vm_start); ++ else ++ hole_end = end; ++ ++ for (; addr < hole_end; addr += PAGE_SIZE) { ++ pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2)); ++ ++ err = add_to_pagemap(addr, &pme, pm); ++ if (err) ++ return err; + } + +- /* check that 'vma' actually covers this address, +- * and that it isn't a huge page vma */ +- if (vma && (vma->vm_start <= addr) && +- !is_vm_hugetlb_page(vma)) { +- pte = pte_offset_map(pmd, addr); ++ if (!vma || vma->vm_start >= end) ++ break; ++ /* ++ * We can't possibly be in a hugetlb VMA. In general, ++ * for a mm_walk with a pmd_entry and a hugetlb_entry, ++ * the pmd_entry can only be called on addresses in a ++ * hugetlb if the walk starts in a non-hugetlb VMA and ++ * spans a hugepage VMA. Since pagemap_read walks are ++ * PMD-sized and PMD-aligned, this will never be true. ++ */ ++ BUG_ON(is_vm_hugetlb_page(vma)); ++ ++ /* Addresses in the VMA. */ ++ orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); ++ for (; addr < min(end, vma->vm_end); pte++, addr += PAGE_SIZE) { ++ pagemap_entry_t pme; ++ + pte_to_pagemap_entry(&pme, pm, vma, addr, *pte); +- /* unmap before userspace copy */ +- pte_unmap(pte); ++ err = add_to_pagemap(addr, &pme, pm); ++ if (err) ++ break; + } +- err = add_to_pagemap(addr, &pme, pm); ++ pte_unmap_unlock(orig_pte, ptl); ++ + if (err) + return err; ++ ++ if (addr == end) ++ break; ++ ++ vma = find_vma(walk->mm, addr); + } + + cond_resched(); +@@ -1226,6 +1250,9 @@ out: + + static int pagemap_open(struct inode *inode, struct file *file) + { ++ /* do not disclose physical addresses: attack vector */ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; + pr_warn_once("Bits 55-60 of /proc/PID/pagemap entries are about " + "to stop being page-shift some time soon. See the " + "linux/Documentation/vm/pagemap.txt for details.\n"); +diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c +index 1282384..14120a3 100644 +--- a/fs/pstore/inode.c ++++ b/fs/pstore/inode.c +@@ -319,10 +319,10 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count, + compressed ? ".enc.z" : ""); + break; + case PSTORE_TYPE_CONSOLE: +- sprintf(name, "console-%s", psname); ++ sprintf(name, "console-%s-%lld", psname, id); + break; + case PSTORE_TYPE_FTRACE: +- sprintf(name, "ftrace-%s", psname); ++ sprintf(name, "ftrace-%s-%lld", psname, id); + break; + case PSTORE_TYPE_MCE: + sprintf(name, "mce-%s-%lld", psname, id); +diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c +index fa8cef2..fe68d8a 100644 +--- a/fs/pstore/ram.c ++++ b/fs/pstore/ram.c +@@ -61,6 +61,11 @@ module_param(mem_size, ulong, 0400); + MODULE_PARM_DESC(mem_size, + "size of reserved RAM used to store oops/panic logs"); + ++static unsigned int mem_type; ++module_param(mem_type, uint, 0600); ++MODULE_PARM_DESC(mem_type, ++ "set to 1 to try to use unbuffered memory (default 0)"); ++ + static int dump_oops = 1; + module_param(dump_oops, int, 0600); + MODULE_PARM_DESC(dump_oops, +@@ -79,6 +84,7 @@ struct ramoops_context { + struct persistent_ram_zone *fprz; + phys_addr_t phys_addr; + unsigned long size; ++ unsigned int memtype; + size_t record_size; + size_t console_size; + size_t ftrace_size; +@@ -86,6 +92,7 @@ struct ramoops_context { + struct persistent_ram_ecc_info ecc_info; + unsigned int max_dump_cnt; + unsigned int dump_write_cnt; ++ /* _read_cnt need clear on ramoops_pstore_open */ + unsigned int dump_read_cnt; + unsigned int console_read_cnt; + unsigned int ftrace_read_cnt; +@@ -101,6 +108,7 @@ static int ramoops_pstore_open(struct pstore_info *psi) + + cxt->dump_read_cnt = 0; + cxt->console_read_cnt = 0; ++ cxt->ftrace_read_cnt = 0; + return 0; + } + +@@ -117,13 +125,15 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], uint *c, uint max, + return NULL; + + prz = przs[i]; ++ if (!prz) ++ return NULL; + +- if (update) { +- /* Update old/shadowed buffer. */ ++ /* Update old/shadowed buffer. */ ++ if (update) + persistent_ram_save_old(prz); +- if (!persistent_ram_old_size(prz)) +- return NULL; +- } ++ ++ if (!persistent_ram_old_size(prz)) ++ return NULL; + + *typep = type; + *id = i; +@@ -353,7 +363,8 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt, + size_t sz = cxt->record_size; + + cxt->przs[i] = persistent_ram_new(*paddr, sz, 0, +- &cxt->ecc_info); ++ &cxt->ecc_info, ++ cxt->memtype); + if (IS_ERR(cxt->przs[i])) { + err = PTR_ERR(cxt->przs[i]); + dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", +@@ -383,7 +394,7 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt, + return -ENOMEM; + } + +- *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info); ++ *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info, cxt->memtype); + if (IS_ERR(*prz)) { + int err = PTR_ERR(*prz); + +@@ -428,9 +439,9 @@ static int ramoops_probe(struct platform_device *pdev) + if (pdata->ftrace_size && !is_power_of_2(pdata->ftrace_size)) + pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); + +- cxt->dump_read_cnt = 0; + cxt->size = pdata->mem_size; + cxt->phys_addr = pdata->mem_address; ++ cxt->memtype = pdata->mem_type; + cxt->record_size = pdata->record_size; + cxt->console_size = pdata->console_size; + cxt->ftrace_size = pdata->ftrace_size; +@@ -561,6 +572,7 @@ static void ramoops_register_dummy(void) + + dummy_data->mem_size = mem_size; + dummy_data->mem_address = mem_address; ++ dummy_data->mem_type = 0; + dummy_data->record_size = record_size; + dummy_data->console_size = ramoops_console_size; + dummy_data->ftrace_size = ramoops_ftrace_size; +diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c +index de272d4..bda61a7 100644 +--- a/fs/pstore/ram_core.c ++++ b/fs/pstore/ram_core.c +@@ -380,7 +380,8 @@ void persistent_ram_zap(struct persistent_ram_zone *prz) + persistent_ram_update_header_ecc(prz); + } + +-static void *persistent_ram_vmap(phys_addr_t start, size_t size) ++static void *persistent_ram_vmap(phys_addr_t start, size_t size, ++ unsigned int memtype) + { + struct page **pages; + phys_addr_t page_start; +@@ -392,7 +393,10 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size) + page_start = start - offset_in_page(start); + page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE); + +- prot = pgprot_noncached(PAGE_KERNEL); ++ if (memtype) ++ prot = pgprot_noncached(PAGE_KERNEL); ++ else ++ prot = pgprot_writecombine(PAGE_KERNEL); + + pages = kmalloc(sizeof(struct page *) * page_count, GFP_KERNEL); + if (!pages) { +@@ -411,8 +415,11 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size) + return vaddr; + } + +-static void *persistent_ram_iomap(phys_addr_t start, size_t size) ++static void *persistent_ram_iomap(phys_addr_t start, size_t size, ++ unsigned int memtype) + { ++ void *va; ++ + if (!request_mem_region(start, size, "persistent_ram")) { + pr_err("request mem region (0x%llx@0x%llx) failed\n", + (unsigned long long)size, (unsigned long long)start); +@@ -422,19 +429,24 @@ static void *persistent_ram_iomap(phys_addr_t start, size_t size) + buffer_start_add = buffer_start_add_locked; + buffer_size_add = buffer_size_add_locked; + +- return ioremap(start, size); ++ if (memtype) ++ va = ioremap(start, size); ++ else ++ va = ioremap_wc(start, size); ++ ++ return va; + } + + static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size, +- struct persistent_ram_zone *prz) ++ struct persistent_ram_zone *prz, int memtype) + { + prz->paddr = start; + prz->size = size; + + if (pfn_valid(start >> PAGE_SHIFT)) +- prz->vaddr = persistent_ram_vmap(start, size); ++ prz->vaddr = persistent_ram_vmap(start, size, memtype); + else +- prz->vaddr = persistent_ram_iomap(start, size); ++ prz->vaddr = persistent_ram_iomap(start, size, memtype); + + if (!prz->vaddr) { + pr_err("%s: Failed to map 0x%llx pages at 0x%llx\n", __func__, +@@ -502,7 +514,8 @@ void persistent_ram_free(struct persistent_ram_zone *prz) + } + + struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, +- u32 sig, struct persistent_ram_ecc_info *ecc_info) ++ u32 sig, struct persistent_ram_ecc_info *ecc_info, ++ unsigned int memtype) + { + struct persistent_ram_zone *prz; + int ret = -ENOMEM; +@@ -513,7 +526,7 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, + goto err; + } + +- ret = persistent_ram_buffer_map(start, size, prz); ++ ret = persistent_ram_buffer_map(start, size, prz, memtype); + if (ret) + goto err; + +diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c +index ce87c90..89da957 100644 +--- a/fs/quota/dquot.c ++++ b/fs/quota/dquot.c +@@ -637,7 +637,7 @@ int dquot_writeback_dquots(struct super_block *sb, int type) + dqstats_inc(DQST_LOOKUPS); + err = sb->dq_op->write_dquot(dquot); + if (!ret && err) +- err = ret; ++ ret = err; + dqput(dquot); + spin_lock(&dq_list_lock); + } +diff --git a/fs/signalfd.c b/fs/signalfd.c +index 424b7b6..148f8e7 100644 +--- a/fs/signalfd.c ++++ b/fs/signalfd.c +@@ -121,8 +121,9 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, + * Other callers might not initialize the si_lsb field, + * so check explicitly for the right codes here. + */ +- if (kinfo->si_code == BUS_MCEERR_AR || +- kinfo->si_code == BUS_MCEERR_AO) ++ if (kinfo->si_signo == SIGBUS && ++ (kinfo->si_code == BUS_MCEERR_AR || ++ kinfo->si_code == BUS_MCEERR_AO)) + err |= __put_user((short) kinfo->si_addr_lsb, + &uinfo->ssi_addr_lsb); + #endif +diff --git a/fs/splice.c b/fs/splice.c +index 12028fa..f345d53 100644 +--- a/fs/splice.c ++++ b/fs/splice.c +@@ -1012,13 +1012,17 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, + struct address_space *mapping = out->f_mapping; + struct inode *inode = mapping->host; + struct splice_desc sd = { +- .total_len = len, + .flags = flags, +- .pos = *ppos, + .u.file = out, + }; + ssize_t ret; + ++ ret = generic_write_checks(out, ppos, &len, S_ISBLK(inode->i_mode)); ++ if (ret) ++ return ret; ++ sd.total_len = len; ++ sd.pos = *ppos; ++ + pipe_lock(pipe); + + splice_from_pipe_begin(&sd); +diff --git a/fs/super.c b/fs/super.c +index 7624267..440ef51 100644 +--- a/fs/super.c ++++ b/fs/super.c +@@ -81,6 +81,8 @@ static unsigned long super_cache_scan(struct shrinker *shrink, + inodes = list_lru_count_node(&sb->s_inode_lru, sc->nid); + dentries = list_lru_count_node(&sb->s_dentry_lru, sc->nid); + total_objects = dentries + inodes + fs_objects + 1; ++ if (!total_objects) ++ total_objects = 1; + + /* proportion the scan between the caches */ + dentries = mult_frac(sc->nr_to_scan, dentries, total_objects); +@@ -112,9 +114,14 @@ static unsigned long super_cache_count(struct shrinker *shrink, + + sb = container_of(shrink, struct super_block, s_shrink); + +- if (!grab_super_passive(sb)) +- return 0; +- ++ /* ++ * Don't call grab_super_passive as it is a potential ++ * scalability bottleneck. The counts could get updated ++ * between super_cache_count and super_cache_scan anyway. ++ * Call to super_cache_count with shrinker_rwsem held ++ * ensures the safety of call to list_lru_count_node() and ++ * s_op->nr_cached_objects(). ++ */ + if (sb->s_op && sb->s_op->nr_cached_objects) + total_objects = sb->s_op->nr_cached_objects(sb, + sc->nid); +@@ -125,7 +132,6 @@ static unsigned long super_cache_count(struct shrinker *shrink, + sc->nid); + + total_objects = vfs_pressure_ratio(total_objects); +- drop_super(sb); + return total_objects; + } + +@@ -276,10 +282,8 @@ void deactivate_locked_super(struct super_block *s) + struct file_system_type *fs = s->s_type; + if (atomic_dec_and_test(&s->s_active)) { + cleancache_invalidate_fs(s); +- fs->kill_sb(s); +- +- /* caches are now gone, we can safely kill the shrinker now */ + unregister_shrinker(&s->s_shrink); ++ fs->kill_sb(s); + + put_filesystem(fs); + put_super(s); +diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c +index ff82293..26b69b2 100644 +--- a/fs/ubifs/commit.c ++++ b/fs/ubifs/commit.c +@@ -166,15 +166,10 @@ static int do_commit(struct ubifs_info *c) + err = ubifs_orphan_end_commit(c); + if (err) + goto out; +- old_ltail_lnum = c->ltail_lnum; +- err = ubifs_log_end_commit(c, new_ltail_lnum); +- if (err) +- goto out; + err = dbg_check_old_index(c, &zroot); + if (err) + goto out; + +- mutex_lock(&c->mst_mutex); + c->mst_node->cmt_no = cpu_to_le64(c->cmt_no); + c->mst_node->log_lnum = cpu_to_le32(new_ltail_lnum); + c->mst_node->root_lnum = cpu_to_le32(zroot.lnum); +@@ -203,8 +198,9 @@ static int do_commit(struct ubifs_info *c) + c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); + else + c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_NO_ORPHS); +- err = ubifs_write_master(c); +- mutex_unlock(&c->mst_mutex); ++ ++ old_ltail_lnum = c->ltail_lnum; ++ err = ubifs_log_end_commit(c, new_ltail_lnum); + if (err) + goto out; + +diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c +index a902c59..8d59de8 100644 +--- a/fs/ubifs/log.c ++++ b/fs/ubifs/log.c +@@ -106,10 +106,14 @@ static inline long long empty_log_bytes(const struct ubifs_info *c) + h = (long long)c->lhead_lnum * c->leb_size + c->lhead_offs; + t = (long long)c->ltail_lnum * c->leb_size; + +- if (h >= t) ++ if (h > t) + return c->log_bytes - h + t; +- else ++ else if (h != t) + return t - h; ++ else if (c->lhead_lnum != c->ltail_lnum) ++ return 0; ++ else ++ return c->log_bytes; + } + + /** +@@ -447,9 +451,9 @@ out: + * @ltail_lnum: new log tail LEB number + * + * This function is called on when the commit operation was finished. It +- * moves log tail to new position and unmaps LEBs which contain obsolete data. +- * Returns zero in case of success and a negative error code in case of +- * failure. ++ * moves log tail to new position and updates the master node so that it stores ++ * the new log tail LEB number. Returns zero in case of success and a negative ++ * error code in case of failure. + */ + int ubifs_log_end_commit(struct ubifs_info *c, int ltail_lnum) + { +@@ -477,7 +481,12 @@ int ubifs_log_end_commit(struct ubifs_info *c, int ltail_lnum) + spin_unlock(&c->buds_lock); + + err = dbg_check_bud_bytes(c); ++ if (err) ++ goto out; + ++ err = ubifs_write_master(c); ++ ++out: + mutex_unlock(&c->log_mutex); + return err; + } +diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c +index ab83ace..1a4bb9e 100644 +--- a/fs/ubifs/master.c ++++ b/fs/ubifs/master.c +@@ -352,10 +352,9 @@ int ubifs_read_master(struct ubifs_info *c) + * ubifs_write_master - write master node. + * @c: UBIFS file-system description object + * +- * This function writes the master node. The caller has to take the +- * @c->mst_mutex lock before calling this function. Returns zero in case of +- * success and a negative error code in case of failure. The master node is +- * written twice to enable recovery. ++ * This function writes the master node. Returns zero in case of success and a ++ * negative error code in case of failure. The master node is written twice to ++ * enable recovery. + */ + int ubifs_write_master(struct ubifs_info *c) + { +diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c +index 5ded849..94d9a64 100644 +--- a/fs/ubifs/super.c ++++ b/fs/ubifs/super.c +@@ -1957,7 +1957,6 @@ static struct ubifs_info *alloc_ubifs_info(struct ubi_volume_desc *ubi) + mutex_init(&c->lp_mutex); + mutex_init(&c->tnc_mutex); + mutex_init(&c->log_mutex); +- mutex_init(&c->mst_mutex); + mutex_init(&c->umount_mutex); + mutex_init(&c->bu_mutex); + mutex_init(&c->write_reserve_mutex); +diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h +index e8c8cfe..7ab9c71 100644 +--- a/fs/ubifs/ubifs.h ++++ b/fs/ubifs/ubifs.h +@@ -1042,7 +1042,6 @@ struct ubifs_debug_info; + * + * @mst_node: master node + * @mst_offs: offset of valid master node +- * @mst_mutex: protects the master node area, @mst_node, and @mst_offs + * + * @max_bu_buf_len: maximum bulk-read buffer length + * @bu_mutex: protects the pre-allocated bulk-read buffer and @c->bu +@@ -1282,7 +1281,6 @@ struct ubifs_info { + + struct ubifs_mst_node *mst_node; + int mst_offs; +- struct mutex mst_mutex; + + int max_bu_buf_len; + struct mutex bu_mutex; +diff --git a/fs/udf/inode.c b/fs/udf/inode.c +index 982ce05..287cd5f 100644 +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -1271,13 +1271,22 @@ update_time: + return 0; + } + ++/* ++ * Maximum length of linked list formed by ICB hierarchy. The chosen number is ++ * arbitrary - just that we hopefully don't limit any real use of rewritten ++ * inode on write-once media but avoid looping for too long on corrupted media. ++ */ ++#define UDF_MAX_ICB_NESTING 1024 ++ + static void __udf_read_inode(struct inode *inode) + { + struct buffer_head *bh = NULL; + struct fileEntry *fe; + uint16_t ident; + struct udf_inode_info *iinfo = UDF_I(inode); ++ unsigned int indirections = 0; + ++reread: + /* + * Set defaults, but the inode is still incomplete! + * Note: get_new_inode() sets the following on a new inode: +@@ -1314,28 +1323,26 @@ static void __udf_read_inode(struct inode *inode) + ibh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 1, + &ident); + if (ident == TAG_IDENT_IE && ibh) { +- struct buffer_head *nbh = NULL; + struct kernel_lb_addr loc; + struct indirectEntry *ie; + + ie = (struct indirectEntry *)ibh->b_data; + loc = lelb_to_cpu(ie->indirectICB.extLocation); + +- if (ie->indirectICB.extLength && +- (nbh = udf_read_ptagged(inode->i_sb, &loc, 0, +- &ident))) { +- if (ident == TAG_IDENT_FE || +- ident == TAG_IDENT_EFE) { +- memcpy(&iinfo->i_location, +- &loc, +- sizeof(struct kernel_lb_addr)); +- brelse(bh); +- brelse(ibh); +- brelse(nbh); +- __udf_read_inode(inode); ++ if (ie->indirectICB.extLength) { ++ brelse(bh); ++ brelse(ibh); ++ memcpy(&iinfo->i_location, &loc, ++ sizeof(struct kernel_lb_addr)); ++ if (++indirections > UDF_MAX_ICB_NESTING) { ++ udf_err(inode->i_sb, ++ "too many ICBs in ICB hierarchy" ++ " (max %d supported)\n", ++ UDF_MAX_ICB_NESTING); ++ make_bad_inode(inode); + return; + } +- brelse(nbh); ++ goto reread; + } + } + brelse(ibh); +diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c +index d7c6dbe..d89f324 100644 +--- a/fs/udf/symlink.c ++++ b/fs/udf/symlink.c +@@ -80,11 +80,17 @@ static int udf_symlink_filler(struct file *file, struct page *page) + struct inode *inode = page->mapping->host; + struct buffer_head *bh = NULL; + unsigned char *symlink; +- int err = -EIO; ++ int err; + unsigned char *p = kmap(page); + struct udf_inode_info *iinfo; + uint32_t pos; + ++ /* We don't support symlinks longer than one block */ ++ if (inode->i_size > inode->i_sb->s_blocksize) { ++ err = -ENAMETOOLONG; ++ goto out_unmap; ++ } ++ + iinfo = UDF_I(inode); + pos = udf_block_map(inode, 0); + +@@ -94,8 +100,10 @@ static int udf_symlink_filler(struct file *file, struct page *page) + } else { + bh = sb_bread(inode->i_sb, pos); + +- if (!bh) +- goto out; ++ if (!bh) { ++ err = -EIO; ++ goto out_unlock_inode; ++ } + + symlink = bh->b_data; + } +@@ -109,9 +117,10 @@ static int udf_symlink_filler(struct file *file, struct page *page) + unlock_page(page); + return 0; + +-out: ++out_unlock_inode: + up_read(&iinfo->i_data_sem); + SetPageError(page); ++out_unmap: + kunmap(page); + unlock_page(page); + return err; +diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c +index db2cfb0..0461fbe 100644 +--- a/fs/xfs/xfs_aops.c ++++ b/fs/xfs/xfs_aops.c +@@ -434,10 +434,22 @@ xfs_start_page_writeback( + { + ASSERT(PageLocked(page)); + ASSERT(!PageWriteback(page)); +- if (clear_dirty) ++ ++ /* ++ * if the page was not fully cleaned, we need to ensure that the higher ++ * layers come back to it correctly. That means we need to keep the page ++ * dirty, and for WB_SYNC_ALL writeback we need to ensure the ++ * PAGECACHE_TAG_TOWRITE index mark is not removed so another attempt to ++ * write this page in this writeback sweep will be made. ++ */ ++ if (clear_dirty) { + clear_page_dirty_for_io(page); +- set_page_writeback(page); ++ set_page_writeback(page); ++ } else ++ set_page_writeback_keepwrite(page); ++ + unlock_page(page); ++ + /* If no buffers on the page are to be written, finish it here */ + if (!buffers) + end_page_writeback(page); +@@ -1660,11 +1672,72 @@ xfs_vm_readpages( + return mpage_readpages(mapping, pages, nr_pages, xfs_get_blocks); + } + ++/* ++ * This is basically a copy of __set_page_dirty_buffers() with one ++ * small tweak: buffers beyond EOF do not get marked dirty. If we mark them ++ * dirty, we'll never be able to clean them because we don't write buffers ++ * beyond EOF, and that means we can't invalidate pages that span EOF ++ * that have been marked dirty. Further, the dirty state can leak into ++ * the file interior if the file is extended, resulting in all sorts of ++ * bad things happening as the state does not match the underlying data. ++ * ++ * XXX: this really indicates that bufferheads in XFS need to die. Warts like ++ * this only exist because of bufferheads and how the generic code manages them. ++ */ ++STATIC int ++xfs_vm_set_page_dirty( ++ struct page *page) ++{ ++ struct address_space *mapping = page->mapping; ++ struct inode *inode = mapping->host; ++ loff_t end_offset; ++ loff_t offset; ++ int newly_dirty; ++ ++ if (unlikely(!mapping)) ++ return !TestSetPageDirty(page); ++ ++ end_offset = i_size_read(inode); ++ offset = page_offset(page); ++ ++ spin_lock(&mapping->private_lock); ++ if (page_has_buffers(page)) { ++ struct buffer_head *head = page_buffers(page); ++ struct buffer_head *bh = head; ++ ++ do { ++ if (offset < end_offset) ++ set_buffer_dirty(bh); ++ bh = bh->b_this_page; ++ offset += 1 << inode->i_blkbits; ++ } while (bh != head); ++ } ++ newly_dirty = !TestSetPageDirty(page); ++ spin_unlock(&mapping->private_lock); ++ ++ if (newly_dirty) { ++ /* sigh - __set_page_dirty() is static, so copy it here, too */ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&mapping->tree_lock, flags); ++ if (page->mapping) { /* Race with truncate? */ ++ WARN_ON_ONCE(!PageUptodate(page)); ++ account_page_dirtied(page, mapping); ++ radix_tree_tag_set(&mapping->page_tree, ++ page_index(page), PAGECACHE_TAG_DIRTY); ++ } ++ spin_unlock_irqrestore(&mapping->tree_lock, flags); ++ __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); ++ } ++ return newly_dirty; ++} ++ + const struct address_space_operations xfs_address_space_operations = { + .readpage = xfs_vm_readpage, + .readpages = xfs_vm_readpages, + .writepage = xfs_vm_writepage, + .writepages = xfs_vm_writepages, ++ .set_page_dirty = xfs_vm_set_page_dirty, + .releasepage = xfs_vm_releasepage, + .invalidatepage = xfs_vm_invalidatepage, + .write_begin = xfs_vm_write_begin, +diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c +index 3314911..645f180 100644 +--- a/fs/xfs/xfs_buf_item.c ++++ b/fs/xfs/xfs_buf_item.c +@@ -319,6 +319,10 @@ xfs_buf_item_format( + ASSERT(atomic_read(&bip->bli_refcount) > 0); + ASSERT((bip->bli_flags & XFS_BLI_LOGGED) || + (bip->bli_flags & XFS_BLI_STALE)); ++ ASSERT((bip->bli_flags & XFS_BLI_STALE) || ++ (xfs_blft_from_flags(&bip->__bli_format) > XFS_BLFT_UNKNOWN_BUF ++ && xfs_blft_from_flags(&bip->__bli_format) < XFS_BLFT_MAX_BUF)); ++ + + /* + * If it is an inode buffer, transfer the in-memory state to the +diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c +index 7aeb4c8..95f9448 100644 +--- a/fs/xfs/xfs_dquot.c ++++ b/fs/xfs/xfs_dquot.c +@@ -1011,7 +1011,8 @@ xfs_qm_dqflush( + * Get the buffer containing the on-disk dquot + */ + error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno, +- mp->m_quotainfo->qi_dqchunklen, 0, &bp, NULL); ++ mp->m_quotainfo->qi_dqchunklen, 0, &bp, ++ &xfs_dquot_buf_ops); + if (error) + goto out_unlock; + +diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c +index 64b48ea..f50def6 100644 +--- a/fs/xfs/xfs_file.c ++++ b/fs/xfs/xfs_file.c +@@ -302,7 +302,16 @@ xfs_file_aio_read( + xfs_rw_iunlock(ip, XFS_IOLOCK_EXCL); + return ret; + } +- truncate_pagecache_range(VFS_I(ip), pos, -1); ++ ++ /* ++ * Invalidate whole pages. This can return an error if ++ * we fail to invalidate a page, but this should never ++ * happen on XFS. Warn if it does fail. ++ */ ++ ret = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping, ++ pos >> PAGE_CACHE_SHIFT, -1); ++ WARN_ON_ONCE(ret); ++ ret = 0; + } + xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); + } +@@ -683,7 +692,15 @@ xfs_file_dio_aio_write( + pos, -1); + if (ret) + goto out; +- truncate_pagecache_range(VFS_I(ip), pos, -1); ++ /* ++ * Invalidate whole pages. This can return an error if ++ * we fail to invalidate a page, but this should never ++ * happen on XFS. Warn if it does fail. ++ */ ++ ret = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping, ++ pos >> PAGE_CACHE_SHIFT, -1); ++ WARN_ON_ONCE(ret); ++ ret = 0; + } + + /* +diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c +index 3a137e9..5d90b8d 100644 +--- a/fs/xfs/xfs_inode.c ++++ b/fs/xfs/xfs_inode.c +@@ -1946,6 +1946,7 @@ xfs_iunlink( + agi->agi_unlinked[bucket_index] = cpu_to_be32(agino); + offset = offsetof(xfs_agi_t, agi_unlinked) + + (sizeof(xfs_agino_t) * bucket_index); ++ xfs_trans_buf_set_type(tp, agibp, XFS_BLFT_AGI_BUF); + xfs_trans_log_buf(tp, agibp, offset, + (offset + sizeof(xfs_agino_t) - 1)); + return 0; +@@ -2037,6 +2038,7 @@ xfs_iunlink_remove( + agi->agi_unlinked[bucket_index] = cpu_to_be32(next_agino); + offset = offsetof(xfs_agi_t, agi_unlinked) + + (sizeof(xfs_agino_t) * bucket_index); ++ xfs_trans_buf_set_type(tp, agibp, XFS_BLFT_AGI_BUF); + xfs_trans_log_buf(tp, agibp, offset, + (offset + sizeof(xfs_agino_t) - 1)); + } else { +diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h +index b0f4ef7..bf9781e 100644 +--- a/fs/xfs/xfs_log.h ++++ b/fs/xfs/xfs_log.h +@@ -24,7 +24,8 @@ struct xfs_log_vec { + struct xfs_log_iovec *lv_iovecp; /* iovec array */ + struct xfs_log_item *lv_item; /* owner */ + char *lv_buf; /* formatted buffer */ +- int lv_buf_len; /* size of formatted buffer */ ++ int lv_bytes; /* accounted space in buffer */ ++ int lv_buf_len; /* aligned size of buffer */ + int lv_size; /* size of allocated lv */ + }; + +@@ -52,15 +53,21 @@ xlog_prepare_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec **vecp, + return vec->i_addr; + } + ++/* ++ * We need to make sure the next buffer is naturally aligned for the biggest ++ * basic data type we put into it. We already accounted for this padding when ++ * sizing the buffer. ++ * ++ * However, this padding does not get written into the log, and hence we have to ++ * track the space used by the log vectors separately to prevent log space hangs ++ * due to inaccurate accounting (i.e. a leak) of the used log space through the ++ * CIL context ticket. ++ */ + static inline void + xlog_finish_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec *vec, int len) + { +- /* +- * We need to make sure the next buffer is naturally aligned for the +- * biggest basic data type we put into it. We already accounted for +- * this when sizing the buffer. +- */ + lv->lv_buf_len += round_up(len, sizeof(uint64_t)); ++ lv->lv_bytes += len; + vec->i_len = len; + } + +diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c +index 4ef6fdb..bcfbaae 100644 +--- a/fs/xfs/xfs_log_cil.c ++++ b/fs/xfs/xfs_log_cil.c +@@ -97,7 +97,7 @@ xfs_cil_prepare_item( + { + /* Account for the new LV being passed in */ + if (lv->lv_buf_len != XFS_LOG_VEC_ORDERED) { +- *diff_len += lv->lv_buf_len; ++ *diff_len += lv->lv_bytes; + *diff_iovecs += lv->lv_niovecs; + } + +@@ -111,7 +111,7 @@ xfs_cil_prepare_item( + else if (old_lv != lv) { + ASSERT(lv->lv_buf_len != XFS_LOG_VEC_ORDERED); + +- *diff_len -= old_lv->lv_buf_len; ++ *diff_len -= old_lv->lv_bytes; + *diff_iovecs -= old_lv->lv_niovecs; + kmem_free(old_lv); + } +@@ -239,7 +239,7 @@ xlog_cil_insert_format_items( + * that the space reservation accounting is correct. + */ + *diff_iovecs -= lv->lv_niovecs; +- *diff_len -= lv->lv_buf_len; ++ *diff_len -= lv->lv_bytes; + } else { + /* allocate new data chunk */ + lv = kmem_zalloc(buf_size, KM_SLEEP|KM_NOFS); +@@ -259,6 +259,7 @@ xlog_cil_insert_format_items( + + /* The allocated data region lies beyond the iovec region */ + lv->lv_buf_len = 0; ++ lv->lv_bytes = 0; + lv->lv_buf = (char *)lv + buf_size - nbytes; + ASSERT(IS_ALIGNED((unsigned long)lv->lv_buf, sizeof(uint64_t))); + +diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c +index bce53ac..eb26418 100644 +--- a/fs/xfs/xfs_log_recover.c ++++ b/fs/xfs/xfs_log_recover.c +@@ -2125,6 +2125,17 @@ xlog_recover_validate_buf_type( + __uint16_t magic16; + __uint16_t magicda; + ++ /* ++ * We can only do post recovery validation on items on CRC enabled ++ * fielsystems as we need to know when the buffer was written to be able ++ * to determine if we should have replayed the item. If we replay old ++ * metadata over a newer buffer, then it will enter a temporarily ++ * inconsistent state resulting in verification failures. Hence for now ++ * just avoid the verification stage for non-crc filesystems ++ */ ++ if (!xfs_sb_version_hascrc(&mp->m_sb)) ++ return; ++ + magic32 = be32_to_cpu(*(__be32 *)bp->b_addr); + magic16 = be16_to_cpu(*(__be16*)bp->b_addr); + magicda = be16_to_cpu(info->magic); +@@ -2160,8 +2171,6 @@ xlog_recover_validate_buf_type( + bp->b_ops = &xfs_agf_buf_ops; + break; + case XFS_BLFT_AGFL_BUF: +- if (!xfs_sb_version_hascrc(&mp->m_sb)) +- break; + if (magic32 != XFS_AGFL_MAGIC) { + xfs_warn(mp, "Bad AGFL block magic!"); + ASSERT(0); +@@ -2194,10 +2203,6 @@ xlog_recover_validate_buf_type( + #endif + break; + case XFS_BLFT_DINO_BUF: +- /* +- * we get here with inode allocation buffers, not buffers that +- * track unlinked list changes. +- */ + if (magic16 != XFS_DINODE_MAGIC) { + xfs_warn(mp, "Bad INODE block magic!"); + ASSERT(0); +@@ -2277,8 +2282,6 @@ xlog_recover_validate_buf_type( + bp->b_ops = &xfs_attr3_leaf_buf_ops; + break; + case XFS_BLFT_ATTR_RMT_BUF: +- if (!xfs_sb_version_hascrc(&mp->m_sb)) +- break; + if (magic32 != XFS_ATTR3_RMT_MAGIC) { + xfs_warn(mp, "Bad attr remote magic!"); + ASSERT(0); +@@ -2385,16 +2388,7 @@ xlog_recover_do_reg_buffer( + /* Shouldn't be any more regions */ + ASSERT(i == item->ri_total); + +- /* +- * We can only do post recovery validation on items on CRC enabled +- * fielsystems as we need to know when the buffer was written to be able +- * to determine if we should have replayed the item. If we replay old +- * metadata over a newer buffer, then it will enter a temporarily +- * inconsistent state resulting in verification failures. Hence for now +- * just avoid the verification stage for non-crc filesystems +- */ +- if (xfs_sb_version_hascrc(&mp->m_sb)) +- xlog_recover_validate_buf_type(mp, bp, buf_f); ++ xlog_recover_validate_buf_type(mp, bp, buf_f); + } + + /* +@@ -2502,12 +2496,29 @@ xlog_recover_buffer_pass2( + } + + /* +- * recover the buffer only if we get an LSN from it and it's less than ++ * Recover the buffer only if we get an LSN from it and it's less than + * the lsn of the transaction we are replaying. ++ * ++ * Note that we have to be extremely careful of readahead here. ++ * Readahead does not attach verfiers to the buffers so if we don't ++ * actually do any replay after readahead because of the LSN we found ++ * in the buffer if more recent than that current transaction then we ++ * need to attach the verifier directly. Failure to do so can lead to ++ * future recovery actions (e.g. EFI and unlinked list recovery) can ++ * operate on the buffers and they won't get the verifier attached. This ++ * can lead to blocks on disk having the correct content but a stale ++ * CRC. ++ * ++ * It is safe to assume these clean buffers are currently up to date. ++ * If the buffer is dirtied by a later transaction being replayed, then ++ * the verifier will be reset to match whatever recover turns that ++ * buffer into. + */ + lsn = xlog_recover_get_buf_lsn(mp, bp); +- if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) ++ if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) { ++ xlog_recover_validate_buf_type(mp, bp, buf_f); + goto out_release; ++ } + + if (buf_f->blf_flags & XFS_BLF_INODE_BUF) { + error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f); +diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c +index c6ff3cf5..0eaaa2d 100644 +--- a/fs/xfs/xfs_mount.c ++++ b/fs/xfs/xfs_mount.c +@@ -321,7 +321,6 @@ reread: + * Initialize the mount structure from the superblock. + */ + xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp)); +- xfs_sb_quota_from_disk(sbp); + + /* + * If we haven't validated the superblock, do so now before we try +diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c +index 348e4d2..1b271f5 100644 +--- a/fs/xfs/xfs_qm.c ++++ b/fs/xfs/xfs_qm.c +@@ -1108,6 +1108,11 @@ xfs_qm_reset_dqcounts( + */ + xfs_dqcheck(mp, ddq, id+j, type, XFS_QMOPT_DQREPAIR, + "xfs_quotacheck"); ++ /* ++ * Reset type in case we are reusing group quota file for ++ * project quotas or vice versa ++ */ ++ ddq->d_flags = type; + ddq->d_bcount = 0; + ddq->d_icount = 0; + ddq->d_rtbcount = 0; +@@ -1176,6 +1181,12 @@ xfs_qm_dqiter_bufs( + if (error) + break; + ++ /* ++ * A corrupt buffer might not have a verifier attached, so ++ * make sure we have the correct one attached before writeback ++ * occurs. ++ */ ++ bp->b_ops = &xfs_dquot_buf_ops; + xfs_qm_reset_dqcounts(mp, bp, firstid, type); + xfs_buf_delwri_queue(bp, buffer_list); + xfs_buf_relse(bp); +@@ -1261,7 +1272,7 @@ xfs_qm_dqiterate( + xfs_buf_readahead(mp->m_ddev_targp, + XFS_FSB_TO_DADDR(mp, rablkno), + mp->m_quotainfo->qi_dqchunklen, +- NULL); ++ &xfs_dquot_buf_ops); + rablkno++; + } + } +diff --git a/fs/xfs/xfs_sb.c b/fs/xfs/xfs_sb.c +index 1e11679..4afd393 100644 +--- a/fs/xfs/xfs_sb.c ++++ b/fs/xfs/xfs_sb.c +@@ -397,10 +397,11 @@ xfs_sb_quota_from_disk(struct xfs_sb *sbp) + } + } + +-void +-xfs_sb_from_disk( ++static void ++__xfs_sb_from_disk( + struct xfs_sb *to, +- xfs_dsb_t *from) ++ xfs_dsb_t *from, ++ bool convert_xquota) + { + to->sb_magicnum = be32_to_cpu(from->sb_magicnum); + to->sb_blocksize = be32_to_cpu(from->sb_blocksize); +@@ -456,6 +457,17 @@ xfs_sb_from_disk( + to->sb_pad = 0; + to->sb_pquotino = be64_to_cpu(from->sb_pquotino); + to->sb_lsn = be64_to_cpu(from->sb_lsn); ++ /* Convert on-disk flags to in-memory flags? */ ++ if (convert_xquota) ++ xfs_sb_quota_from_disk(to); ++} ++ ++void ++xfs_sb_from_disk( ++ struct xfs_sb *to, ++ xfs_dsb_t *from) ++{ ++ __xfs_sb_from_disk(to, from, true); + } + + static inline void +@@ -571,7 +583,11 @@ xfs_sb_verify( + struct xfs_mount *mp = bp->b_target->bt_mount; + struct xfs_sb sb; + +- xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp)); ++ /* ++ * Use call variant which doesn't convert quota flags from disk ++ * format, because xfs_mount_validate_sb checks the on-disk flags. ++ */ ++ __xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp), false); + + /* + * Only check the in progress field for the primary superblock as +diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c +index 14e58f2..98d4948 100644 +--- a/fs/xfs/xfs_symlink.c ++++ b/fs/xfs/xfs_symlink.c +@@ -102,7 +102,7 @@ xfs_readlink_bmap( + cur_chunk += sizeof(struct xfs_dsymlink_hdr); + } + +- memcpy(link + offset, bp->b_addr, byte_cnt); ++ memcpy(link + offset, cur_chunk, byte_cnt); + + pathlen -= byte_cnt; + offset += byte_cnt; +diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c +index c812c5c..b626f3d 100644 +--- a/fs/xfs/xfs_trans.c ++++ b/fs/xfs/xfs_trans.c +@@ -474,6 +474,7 @@ xfs_trans_apply_sb_deltas( + whole = 1; + } + ++ xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); + if (whole) + /* + * Log the whole thing, the fields are noncontiguous. +diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h +index 8256eb4..ac46782 100644 +--- a/include/acpi/acpi_bus.h ++++ b/include/acpi/acpi_bus.h +@@ -118,6 +118,7 @@ struct acpi_device; + struct acpi_hotplug_profile { + struct kobject kobj; + int (*scan_dependent)(struct acpi_device *adev); ++ void (*notify_online)(struct acpi_device *adev); + bool enabled:1; + bool demand_offline:1; + }; +@@ -228,7 +229,6 @@ struct acpi_device_pnp { + acpi_device_name device_name; /* Driver-determined */ + acpi_device_class device_class; /* " */ + union acpi_object *str_obj; /* unicode string for _STR method */ +- unsigned long sun; /* _SUN */ + }; + + #define acpi_device_bid(d) ((d)->pnp.bus_id) +diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h +index fea6773..5d51f27 100644 +--- a/include/acpi/acpixf.h ++++ b/include/acpi/acpixf.h +@@ -175,7 +175,7 @@ acpi_status __init acpi_load_tables(void); + */ + acpi_status __init acpi_reallocate_root_table(void); + +-acpi_status __init acpi_find_root_pointer(acpi_size *rsdp_address); ++acpi_status __init acpi_find_root_pointer(acpi_physical_address * rsdp_address); + + acpi_status acpi_unload_table_id(acpi_owner_id id); + +diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h +index 68a3ada..69afb57 100644 +--- a/include/acpi/actypes.h ++++ b/include/acpi/actypes.h +@@ -198,9 +198,29 @@ typedef int INT32; + typedef s32 acpi_native_int; + + typedef u32 acpi_size; ++ ++#ifdef ACPI_32BIT_PHYSICAL_ADDRESS ++ ++/* ++ * OSPMs can define this to shrink the size of the structures for 32-bit ++ * none PAE environment. ASL compiler may always define this to generate ++ * 32-bit OSPM compliant tables. ++ */ + typedef u32 acpi_io_address; + typedef u32 acpi_physical_address; + ++#else /* ACPI_32BIT_PHYSICAL_ADDRESS */ ++ ++/* ++ * It is reported that, after some calculations, the physical addresses can ++ * wrap over the 32-bit boundary on 32-bit PAE environment. ++ * https://bugzilla.kernel.org/show_bug.cgi?id=87971 ++ */ ++typedef u64 acpi_io_address; ++typedef u64 acpi_physical_address; ++ ++#endif /* ACPI_32BIT_PHYSICAL_ADDRESS */ ++ + #define ACPI_MAX_PTR ACPI_UINT32_MAX + #define ACPI_SIZE_MAX ACPI_UINT32_MAX + +@@ -541,6 +561,7 @@ typedef u64 acpi_integer; + #define ACPI_NO_ACPI_ENABLE 0x10 + #define ACPI_NO_DEVICE_INIT 0x20 + #define ACPI_NO_OBJECT_INIT 0x40 ++#define ACPI_NO_FACS_INIT 0x80 + + /* + * Initialization state +diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h +index b402eb6..579912c 100644 +--- a/include/acpi/platform/acenv.h ++++ b/include/acpi/platform/acenv.h +@@ -76,6 +76,7 @@ + #define ACPI_LARGE_NAMESPACE_NODE + #define ACPI_DATA_TABLE_DISASSEMBLY + #define ACPI_SINGLE_THREADED ++#define ACPI_32BIT_PHYSICAL_ADDRESS + #endif + + /* acpi_exec configuration. Multithreaded with full AML debugger */ +diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h +index f1a24b5..b58fd66 100644 +--- a/include/asm-generic/sections.h ++++ b/include/asm-generic/sections.h +@@ -3,6 +3,8 @@ + + /* References to section boundaries */ + ++#include ++ + /* + * Usage guidelines: + * _text, _data: architecture specific, don't use them in arch-independent code +@@ -37,6 +39,8 @@ extern char __start_rodata[], __end_rodata[]; + /* Start and end of .ctors section - used for constructor calls. */ + extern char __ctors_start[], __ctors_end[]; + ++extern __visible const void __nosave_begin, __nosave_end; ++ + /* function descriptor handling (if any). Override + * in asm/sections.h */ + #ifndef dereference_function_descriptor +diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h +index 49376ae..7e9a0a6 100644 +--- a/include/drm/drm_pciids.h ++++ b/include/drm/drm_pciids.h +@@ -17,6 +17,7 @@ + {0x1002, 0x1315, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x1316, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x1317, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ ++ {0x1002, 0x1318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x131B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x131C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x131D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +@@ -73,7 +74,6 @@ + {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \ + {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \ + {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \ +- {0x1002, 0x4C6E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \ + {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ + {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ + {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ +@@ -164,23 +164,30 @@ + {0x1002, 0x6601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6602, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6603, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6604, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6605, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6606, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6607, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6608, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6610, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6611, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6613, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6617, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6620, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6623, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6631, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6658, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x665c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x665d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x665f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6663, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6664, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ +@@ -297,6 +304,7 @@ + {0x1002, 0x6829, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x682A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x682B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x682C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x682D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x682F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ +diff --git a/include/dt-bindings/pinctrl/dra.h b/include/dt-bindings/pinctrl/dra.h +index 002a285..7448edf 100644 +--- a/include/dt-bindings/pinctrl/dra.h ++++ b/include/dt-bindings/pinctrl/dra.h +@@ -30,7 +30,8 @@ + #define MUX_MODE14 0xe + #define MUX_MODE15 0xf + +-#define PULL_ENA (1 << 16) ++#define PULL_ENA (0 << 16) ++#define PULL_DIS (1 << 16) + #define PULL_UP (1 << 17) + #define INPUT_EN (1 << 18) + #define SLEWCONTROL (1 << 19) +@@ -38,10 +39,10 @@ + #define WAKEUP_EVENT (1 << 25) + + /* Active pin states */ +-#define PIN_OUTPUT 0 +-#define PIN_OUTPUT_PULLUP (PIN_OUTPUT | PULL_ENA | PULL_UP) +-#define PIN_OUTPUT_PULLDOWN (PIN_OUTPUT | PULL_ENA) +-#define PIN_INPUT INPUT_EN ++#define PIN_OUTPUT (0 | PULL_DIS) ++#define PIN_OUTPUT_PULLUP (PULL_UP) ++#define PIN_OUTPUT_PULLDOWN (0) ++#define PIN_INPUT (INPUT_EN | PULL_DIS) + #define PIN_INPUT_SLEW (INPUT_EN | SLEWCONTROL) + #define PIN_INPUT_PULLUP (PULL_ENA | INPUT_EN | PULL_UP) + #define PIN_INPUT_PULLDOWN (PULL_ENA | INPUT_EN) +diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h +index 6d9aedd..327b155 100644 +--- a/include/kvm/arm_arch_timer.h ++++ b/include/kvm/arm_arch_timer.h +@@ -60,7 +60,8 @@ struct arch_timer_cpu { + + #ifdef CONFIG_KVM_ARM_TIMER + int kvm_timer_hyp_init(void); +-int kvm_timer_init(struct kvm *kvm); ++void kvm_timer_enable(struct kvm *kvm); ++void kvm_timer_init(struct kvm *kvm); + void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu, + const struct kvm_irq_level *irq); + void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu); +@@ -73,11 +74,8 @@ static inline int kvm_timer_hyp_init(void) + return 0; + }; + +-static inline int kvm_timer_init(struct kvm *kvm) +-{ +- return 0; +-} +- ++static inline void kvm_timer_enable(struct kvm *kvm) {} ++static inline void kvm_timer_init(struct kvm *kvm) {} + static inline void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu, + const struct kvm_irq_level *irq) {} + static inline void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) {} +diff --git a/include/linux/acpi.h b/include/linux/acpi.h +index cd80aa8..77af621 100644 +--- a/include/linux/acpi.h ++++ b/include/linux/acpi.h +@@ -402,6 +402,7 @@ extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, + #define ACPI_OST_SC_INSERT_NOT_SUPPORTED 0x82 + + extern void acpi_early_init(void); ++extern void acpi_subsystem_init(void); + + extern int acpi_nvs_register(__u64 start, __u64 size); + +@@ -436,6 +437,7 @@ static inline const char *acpi_dev_name(struct acpi_device *adev) + } + + static inline void acpi_early_init(void) { } ++static inline void acpi_subsystem_init(void) { } + + static inline int early_acpi_boot_init(void) + { +diff --git a/include/linux/audit.h b/include/linux/audit.h +index ec1464d..419b7d7 100644 +--- a/include/linux/audit.h ++++ b/include/linux/audit.h +@@ -47,6 +47,7 @@ struct sk_buff; + + struct audit_krule { + int vers_ops; ++ u32 pflags; + u32 flags; + u32 listnr; + u32 action; +@@ -64,6 +65,9 @@ struct audit_krule { + u64 prio; + }; + ++/* Flag to indicate legacy AUDIT_LOGINUID unset usage */ ++#define AUDIT_LOGINUID_LEGACY 0x1 ++ + struct audit_field { + u32 type; + u32 val; +diff --git a/include/linux/bitops.h b/include/linux/bitops.h +index be5fd38..5d858e0 100644 +--- a/include/linux/bitops.h ++++ b/include/linux/bitops.h +@@ -18,8 +18,11 @@ + * position @h. For example + * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000. + */ +-#define GENMASK(h, l) (((U32_C(1) << ((h) - (l) + 1)) - 1) << (l)) +-#define GENMASK_ULL(h, l) (((U64_C(1) << ((h) - (l) + 1)) - 1) << (l)) ++#define GENMASK(h, l) \ ++ (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) ++ ++#define GENMASK_ULL(h, l) \ ++ (((~0ULL) << (l)) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h)))) + + extern unsigned int __sw_hweight8(unsigned int w); + extern unsigned int __sw_hweight16(unsigned int w); +diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h +index bbc3a6c..33fd7ff 100644 +--- a/include/linux/blk_types.h ++++ b/include/linux/blk_types.h +@@ -180,7 +180,9 @@ enum rq_flag_bits { + __REQ_ELVPRIV, /* elevator private data attached */ + __REQ_FAILED, /* set if the request failed */ + __REQ_QUIET, /* don't worry about errors */ +- __REQ_PREEMPT, /* set for "ide_preempt" requests */ ++ __REQ_PREEMPT, /* set for "ide_preempt" requests and also ++ for requests for which the SCSI "quiesce" ++ state must be ignored. */ + __REQ_ALLOCED, /* request came from our alloc pool */ + __REQ_COPY_USER, /* contains copies of user pages */ + __REQ_FLUSH_SEQ, /* request for flush sequence */ +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index 4afa4f8..a693c6d 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -1232,10 +1232,9 @@ static inline int queue_alignment_offset(struct request_queue *q) + static inline int queue_limit_alignment_offset(struct queue_limits *lim, sector_t sector) + { + unsigned int granularity = max(lim->physical_block_size, lim->io_min); +- unsigned int alignment = (sector << 9) & (granularity - 1); ++ unsigned int alignment = sector_div(sector, granularity >> 9) << 9; + +- return (granularity + lim->alignment_offset - alignment) +- & (granularity - 1); ++ return (granularity + lim->alignment_offset - alignment) % granularity; + } + + static inline int bdev_alignment_offset(struct block_device *bdev) +diff --git a/include/linux/capability.h b/include/linux/capability.h +index 84b13ad..aa93e5e 100644 +--- a/include/linux/capability.h ++++ b/include/linux/capability.h +@@ -78,8 +78,11 @@ extern const kernel_cap_t __cap_init_eff_set; + # error Fix up hand-coded capability macro initializers + #else /* HAND-CODED capability initializers */ + ++#define CAP_LAST_U32 ((_KERNEL_CAPABILITY_U32S) - 1) ++#define CAP_LAST_U32_VALID_MASK (CAP_TO_MASK(CAP_LAST_CAP + 1) -1) ++ + # define CAP_EMPTY_SET ((kernel_cap_t){{ 0, 0 }}) +-# define CAP_FULL_SET ((kernel_cap_t){{ ~0, ~0 }}) ++# define CAP_FULL_SET ((kernel_cap_t){{ ~0, CAP_LAST_U32_VALID_MASK }}) + # define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ + | CAP_TO_MASK(CAP_LINUX_IMMUTABLE), \ + CAP_FS_MASK_B1 } }) +diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h +index 67301a4..879065d 100644 +--- a/include/linux/clocksource.h ++++ b/include/linux/clocksource.h +@@ -289,7 +289,7 @@ extern struct clocksource* clocksource_get_next(void); + extern void clocksource_change_rating(struct clocksource *cs, int rating); + extern void clocksource_suspend(void); + extern void clocksource_resume(void); +-extern struct clocksource * __init __weak clocksource_default_clock(void); ++extern struct clocksource * __init clocksource_default_clock(void); + extern void clocksource_mark_unstable(struct clocksource *cs); + + extern u64 +diff --git a/include/linux/compaction.h b/include/linux/compaction.h +index 7e1c76e..01e3132 100644 +--- a/include/linux/compaction.h ++++ b/include/linux/compaction.h +@@ -22,7 +22,7 @@ extern int sysctl_extfrag_handler(struct ctl_table *table, int write, + extern int fragmentation_index(struct zone *zone, unsigned int order); + extern unsigned long try_to_compact_pages(struct zonelist *zonelist, + int order, gfp_t gfp_mask, nodemask_t *mask, +- bool sync, bool *contended); ++ enum migrate_mode mode, bool *contended); + extern void compact_pgdat(pg_data_t *pgdat, int order); + extern void reset_isolation_suitable(pg_data_t *pgdat); + extern unsigned long compaction_suitable(struct zone *zone, int order); +@@ -91,7 +91,7 @@ static inline bool compaction_restarting(struct zone *zone, int order) + #else + static inline unsigned long try_to_compact_pages(struct zonelist *zonelist, + int order, gfp_t gfp_mask, nodemask_t *nodemask, +- bool sync, bool *contended) ++ enum migrate_mode mode, bool *contended) + { + return COMPACT_CONTINUE; + } +diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h +index 50fcbb0..d133817 100644 +--- a/include/linux/cpuidle.h ++++ b/include/linux/cpuidle.h +@@ -69,7 +69,6 @@ struct cpuidle_device { + unsigned int cpu; + + int last_residency; +- int state_count; + struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX]; + struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX]; + struct cpuidle_driver_kobj *kobj_driver; +diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h +index 3fe661f..ade2390 100644 +--- a/include/linux/cpuset.h ++++ b/include/linux/cpuset.h +@@ -12,10 +12,31 @@ + #include + #include + #include ++#include + + #ifdef CONFIG_CPUSETS + +-extern int number_of_cpusets; /* How many cpusets are defined in system? */ ++extern struct static_key cpusets_enabled_key; ++static inline bool cpusets_enabled(void) ++{ ++ return static_key_false(&cpusets_enabled_key); ++} ++ ++static inline int nr_cpusets(void) ++{ ++ /* jump label reference count + the top-level cpuset */ ++ return static_key_count(&cpusets_enabled_key) + 1; ++} ++ ++static inline void cpuset_inc(void) ++{ ++ static_key_slow_inc(&cpusets_enabled_key); ++} ++ ++static inline void cpuset_dec(void) ++{ ++ static_key_slow_dec(&cpusets_enabled_key); ++} + + extern int cpuset_init(void); + extern void cpuset_init_smp(void); +@@ -32,13 +53,13 @@ extern int __cpuset_node_allowed_hardwall(int node, gfp_t gfp_mask); + + static inline int cpuset_node_allowed_softwall(int node, gfp_t gfp_mask) + { +- return number_of_cpusets <= 1 || ++ return nr_cpusets() <= 1 || + __cpuset_node_allowed_softwall(node, gfp_mask); + } + + static inline int cpuset_node_allowed_hardwall(int node, gfp_t gfp_mask) + { +- return number_of_cpusets <= 1 || ++ return nr_cpusets() <= 1 || + __cpuset_node_allowed_hardwall(node, gfp_mask); + } + +@@ -87,25 +108,26 @@ extern void rebuild_sched_domains(void); + extern void cpuset_print_task_mems_allowed(struct task_struct *p); + + /* +- * get_mems_allowed is required when making decisions involving mems_allowed +- * such as during page allocation. mems_allowed can be updated in parallel +- * and depending on the new value an operation can fail potentially causing +- * process failure. A retry loop with get_mems_allowed and put_mems_allowed +- * prevents these artificial failures. ++ * read_mems_allowed_begin is required when making decisions involving ++ * mems_allowed such as during page allocation. mems_allowed can be updated in ++ * parallel and depending on the new value an operation can fail potentially ++ * causing process failure. A retry loop with read_mems_allowed_begin and ++ * read_mems_allowed_retry prevents these artificial failures. + */ +-static inline unsigned int get_mems_allowed(void) ++static inline unsigned int read_mems_allowed_begin(void) + { + return read_seqcount_begin(¤t->mems_allowed_seq); + } + + /* +- * If this returns false, the operation that took place after get_mems_allowed +- * may have failed. It is up to the caller to retry the operation if ++ * If this returns true, the operation that took place after ++ * read_mems_allowed_begin may have failed artificially due to a concurrent ++ * update of mems_allowed. It is up to the caller to retry the operation if + * appropriate. + */ +-static inline bool put_mems_allowed(unsigned int seq) ++static inline bool read_mems_allowed_retry(unsigned int seq) + { +- return !read_seqcount_retry(¤t->mems_allowed_seq, seq); ++ return read_seqcount_retry(¤t->mems_allowed_seq, seq); + } + + static inline void set_mems_allowed(nodemask_t nodemask) +@@ -123,6 +145,8 @@ static inline void set_mems_allowed(nodemask_t nodemask) + + #else /* !CONFIG_CPUSETS */ + ++static inline bool cpusets_enabled(void) { return false; } ++ + static inline int cpuset_init(void) { return 0; } + static inline void cpuset_init_smp(void) {} + +@@ -225,14 +249,14 @@ static inline void set_mems_allowed(nodemask_t nodemask) + { + } + +-static inline unsigned int get_mems_allowed(void) ++static inline unsigned int read_mems_allowed_begin(void) + { + return 0; + } + +-static inline bool put_mems_allowed(unsigned int seq) ++static inline bool read_mems_allowed_retry(unsigned int seq) + { +- return true; ++ return false; + } + + #endif /* !CONFIG_CPUSETS */ +diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h +index 7032518..60023e5 100644 +--- a/include/linux/crash_dump.h ++++ b/include/linux/crash_dump.h +@@ -14,14 +14,13 @@ + extern unsigned long long elfcorehdr_addr; + extern unsigned long long elfcorehdr_size; + +-extern int __weak elfcorehdr_alloc(unsigned long long *addr, +- unsigned long long *size); +-extern void __weak elfcorehdr_free(unsigned long long addr); +-extern ssize_t __weak elfcorehdr_read(char *buf, size_t count, u64 *ppos); +-extern ssize_t __weak elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos); +-extern int __weak remap_oldmem_pfn_range(struct vm_area_struct *vma, +- unsigned long from, unsigned long pfn, +- unsigned long size, pgprot_t prot); ++extern int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size); ++extern void elfcorehdr_free(unsigned long long addr); ++extern ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos); ++extern ssize_t elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos); ++extern int remap_oldmem_pfn_range(struct vm_area_struct *vma, ++ unsigned long from, unsigned long pfn, ++ unsigned long size, pgprot_t prot); + + extern ssize_t copy_oldmem_page(unsigned long, char *, size_t, + unsigned long, int); +diff --git a/include/linux/cred.h b/include/linux/cred.h +index 04421e8..6c58dd7 100644 +--- a/include/linux/cred.h ++++ b/include/linux/cred.h +@@ -68,6 +68,7 @@ extern void groups_free(struct group_info *); + extern int set_current_groups(struct group_info *); + extern int set_groups(struct cred *, struct group_info *); + extern int groups_search(const struct group_info *, kgid_t); ++extern bool may_setgroups(void); + + /* access the groups "array" with this macro */ + #define GROUP_AT(gi, i) \ +diff --git a/include/linux/crypto.h b/include/linux/crypto.h +index b92eadf..2b00d92 100644 +--- a/include/linux/crypto.h ++++ b/include/linux/crypto.h +@@ -26,6 +26,19 @@ + #include + + /* ++ * Autoloaded crypto modules should only use a prefixed name to avoid allowing ++ * arbitrary modules to be loaded. Loading from userspace may still need the ++ * unprefixed names, so retains those aliases as well. ++ * This uses __MODULE_INFO directly instead of MODULE_ALIAS because pre-4.3 ++ * gcc (e.g. avr32 toolchain) uses __LINE__ for uniqueness, and this macro ++ * expands twice on the same line. Instead, use a separate base name for the ++ * alias. ++ */ ++#define MODULE_ALIAS_CRYPTO(name) \ ++ __MODULE_INFO(alias, alias_userspace, name); \ ++ __MODULE_INFO(alias, alias_crypto, "crypto-" name) ++ ++/* + * Algorithm masks and types. + */ + #define CRYPTO_ALG_TYPE_MASK 0x0000000f +diff --git a/include/linux/dcache.h b/include/linux/dcache.h +index bf72e9a..2a23ecb 100644 +--- a/include/linux/dcache.h ++++ b/include/linux/dcache.h +@@ -124,15 +124,15 @@ struct dentry { + void *d_fsdata; /* fs-specific data */ + + struct list_head d_lru; /* LRU list */ ++ struct list_head d_child; /* child of parent list */ ++ struct list_head d_subdirs; /* our children */ + /* +- * d_child and d_rcu can share memory ++ * d_alias and d_rcu can share memory + */ + union { +- struct list_head d_child; /* child of parent list */ ++ struct hlist_node d_alias; /* inode alias list */ + struct rcu_head d_rcu; + } d_u; +- struct list_head d_subdirs; /* our children */ +- struct hlist_node d_alias; /* inode alias list */ + }; + + /* +@@ -221,6 +221,8 @@ struct dentry_operations { + #define DCACHE_SYMLINK_TYPE 0x00300000 /* Symlink */ + #define DCACHE_FILE_TYPE 0x00400000 /* Other file type */ + ++#define DCACHE_MAY_FREE 0x00800000 ++ + extern seqlock_t rename_lock; + + static inline int dname_external(const struct dentry *dentry) +@@ -429,7 +431,7 @@ static inline unsigned __d_entry_type(const struct dentry *dentry) + return dentry->d_flags & DCACHE_ENTRY_TYPE; + } + +-static inline bool d_is_directory(const struct dentry *dentry) ++static inline bool d_can_lookup(const struct dentry *dentry) + { + return __d_entry_type(dentry) == DCACHE_DIRECTORY_TYPE; + } +@@ -439,6 +441,11 @@ static inline bool d_is_autodir(const struct dentry *dentry) + return __d_entry_type(dentry) == DCACHE_AUTODIR_TYPE; + } + ++static inline bool d_is_dir(const struct dentry *dentry) ++{ ++ return d_can_lookup(dentry) || d_is_autodir(dentry); ++} ++ + static inline bool d_is_symlink(const struct dentry *dentry) + { + return __d_entry_type(dentry) == DCACHE_SYMLINK_TYPE; +diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h +index 1c804b0..7ee1774 100644 +--- a/include/linux/fsnotify.h ++++ b/include/linux/fsnotify.h +@@ -101,8 +101,10 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, + new_dir_mask |= FS_ISDIR; + } + +- fsnotify(old_dir, old_dir_mask, old_dir, FSNOTIFY_EVENT_INODE, old_name, fs_cookie); +- fsnotify(new_dir, new_dir_mask, new_dir, FSNOTIFY_EVENT_INODE, new_name, fs_cookie); ++ fsnotify(old_dir, old_dir_mask, source, FSNOTIFY_EVENT_INODE, old_name, ++ fs_cookie); ++ fsnotify(new_dir, new_dir_mask, source, FSNOTIFY_EVENT_INODE, new_name, ++ fs_cookie); + + if (target) + fsnotify_link_count(target); +diff --git a/include/linux/gfp.h b/include/linux/gfp.h +index 39b81dc..3824ac6 100644 +--- a/include/linux/gfp.h ++++ b/include/linux/gfp.h +@@ -369,8 +369,8 @@ void *alloc_pages_exact_nid(int nid, size_t size, gfp_t gfp_mask); + + extern void __free_pages(struct page *page, unsigned int order); + extern void free_pages(unsigned long addr, unsigned int order); +-extern void free_hot_cold_page(struct page *page, int cold); +-extern void free_hot_cold_page_list(struct list_head *list, int cold); ++extern void free_hot_cold_page(struct page *page, bool cold); ++extern void free_hot_cold_page_list(struct list_head *list, bool cold); + + extern void __free_memcg_kmem_pages(struct page *page, unsigned int order); + extern void free_memcg_kmem_pages(unsigned long addr, unsigned int order); +diff --git a/include/linux/hid.h b/include/linux/hid.h +index 31b9d29..00c88fc 100644 +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -286,6 +286,7 @@ struct hid_item { + #define HID_QUIRK_HIDINPUT_FORCE 0x00000080 + #define HID_QUIRK_NO_EMPTY_INPUT 0x00000100 + #define HID_QUIRK_NO_INIT_INPUT_REPORTS 0x00000200 ++#define HID_QUIRK_ALWAYS_POLL 0x00000400 + #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 + #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 + #define HID_QUIRK_NO_INIT_REPORTS 0x20000000 +diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h +index b826239..63579cb 100644 +--- a/include/linux/huge_mm.h ++++ b/include/linux/huge_mm.h +@@ -93,10 +93,6 @@ extern bool is_vma_temporary_stack(struct vm_area_struct *vma); + #endif /* CONFIG_DEBUG_VM */ + + extern unsigned long transparent_hugepage_flags; +-extern int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, +- pmd_t *dst_pmd, pmd_t *src_pmd, +- struct vm_area_struct *vma, +- unsigned long addr, unsigned long end); + extern int split_huge_page_to_list(struct page *page, struct list_head *list); + static inline int split_huge_page(struct page *page) + { +diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h +index bd1e9bc..42b05c4 100644 +--- a/include/linux/hugetlb.h ++++ b/include/linux/hugetlb.h +@@ -400,6 +400,16 @@ static inline spinlock_t *huge_pte_lockptr(struct hstate *h, + return &mm->page_table_lock; + } + ++static inline bool hugepages_supported(void) ++{ ++ /* ++ * Some platform decide whether they support huge pages at boot ++ * time. On these, such as powerpc, HPAGE_SHIFT is set to 0 when ++ * there is no such support ++ */ ++ return HPAGE_SHIFT != 0; ++} ++ + #else /* CONFIG_HUGETLB_PAGE */ + struct hstate {}; + #define alloc_huge_page_node(h, nid) NULL +diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h +index 72ba6f5..2abe67b 100644 +--- a/include/linux/if_vlan.h ++++ b/include/linux/if_vlan.h +@@ -186,7 +186,6 @@ vlan_dev_get_egress_qos_mask(struct net_device *dev, u32 skprio) + } + + extern bool vlan_do_receive(struct sk_buff **skb); +-extern struct sk_buff *vlan_untag(struct sk_buff *skb); + + extern int vlan_vid_add(struct net_device *dev, __be16 proto, u16 vid); + extern void vlan_vid_del(struct net_device *dev, __be16 proto, u16 vid); +@@ -228,11 +227,6 @@ static inline bool vlan_do_receive(struct sk_buff **skb) + return false; + } + +-static inline struct sk_buff *vlan_untag(struct sk_buff *skb) +-{ +- return skb; +-} +- + static inline int vlan_vid_add(struct net_device *dev, __be16 proto, u16 vid) + { + return 0; +diff --git a/include/linux/iio/events.h b/include/linux/iio/events.h +index 8bbd7bc..03fa332 100644 +--- a/include/linux/iio/events.h ++++ b/include/linux/iio/events.h +@@ -72,7 +72,7 @@ struct iio_event_data { + + #define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF) + +-#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0xCF) ++#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0x7F) + + #define IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(mask) ((mask >> 32) & 0xFF) + +diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h +index 75a8a20..c2fb6f3 100644 +--- a/include/linux/iio/iio.h ++++ b/include/linux/iio/iio.h +@@ -593,6 +593,15 @@ int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer, + #define IIO_DEGREE_TO_RAD(deg) (((deg) * 314159ULL + 9000000ULL) / 18000000ULL) + + /** ++ * IIO_RAD_TO_DEGREE() - Convert rad to degree ++ * @rad: A value in rad ++ * ++ * Returns the given value converted from rad to degree ++ */ ++#define IIO_RAD_TO_DEGREE(rad) \ ++ (((rad) * 18000000ULL + 314159ULL / 2) / 314159ULL) ++ ++/** + * IIO_G_TO_M_S_2() - Convert g to meter / second**2 + * @g: A value in g + * +@@ -600,4 +609,12 @@ int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer, + */ + #define IIO_G_TO_M_S_2(g) ((g) * 980665ULL / 100000ULL) + ++/** ++ * IIO_M_S_2_TO_G() - Convert meter / second**2 to g ++ * @ms2: A value in meter / second**2 ++ * ++ * Returns the given value converted from meter / second**2 to g ++ */ ++#define IIO_M_S_2_TO_G(ms2) (((ms2) * 100000ULL + 980665ULL / 2) / 980665ULL) ++ + #endif /* _INDUSTRIAL_IO_H_ */ +diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h +index 369cf2c..68f46cd 100644 +--- a/include/linux/iio/trigger.h ++++ b/include/linux/iio/trigger.h +@@ -84,10 +84,12 @@ static inline void iio_trigger_put(struct iio_trigger *trig) + put_device(&trig->dev); + } + +-static inline void iio_trigger_get(struct iio_trigger *trig) ++static inline struct iio_trigger *iio_trigger_get(struct iio_trigger *trig) + { + get_device(&trig->dev); + __module_get(trig->ops->owner); ++ ++ return trig; + } + + /** +diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h +index 0068708..0a21fbe 100644 +--- a/include/linux/inetdevice.h ++++ b/include/linux/inetdevice.h +@@ -242,7 +242,7 @@ static inline void in_dev_put(struct in_device *idev) + static __inline__ __be32 inet_make_mask(int logmask) + { + if (logmask) +- return htonl(~((1<<(32-logmask))-1)); ++ return htonl(~((1U<<(32-logmask))-1)); + return 0; + } + +diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h +index d5b50a1..e1fb0f6 100644 +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -159,7 +159,11 @@ typedef struct journal_header_s + * journal_block_tag (in the descriptor). The other h_chksum* fields are + * not used. + * +- * Checksum v1 and v2 are mutually exclusive features. ++ * If FEATURE_INCOMPAT_CSUM_V3 is set, the descriptor block uses ++ * journal_block_tag3_t to store a full 32-bit checksum. Everything else ++ * is the same as v2. ++ * ++ * Checksum v1, v2, and v3 are mutually exclusive features. + */ + struct commit_header { + __be32 h_magic; +@@ -179,6 +183,14 @@ struct commit_header { + * raw struct shouldn't be used for pointer math or sizeof() - use + * journal_tag_bytes(journal) instead to compute this. + */ ++typedef struct journal_block_tag3_s ++{ ++ __be32 t_blocknr; /* The on-disk block number */ ++ __be32 t_flags; /* See below */ ++ __be32 t_blocknr_high; /* most-significant high 32bits. */ ++ __be32 t_checksum; /* crc32c(uuid+seq+block) */ ++} journal_block_tag3_t; ++ + typedef struct journal_block_tag_s + { + __be32 t_blocknr; /* The on-disk block number */ +@@ -187,9 +199,6 @@ typedef struct journal_block_tag_s + __be32 t_blocknr_high; /* most-significant high 32bits. */ + } journal_block_tag_t; + +-#define JBD2_TAG_SIZE32 (offsetof(journal_block_tag_t, t_blocknr_high)) +-#define JBD2_TAG_SIZE64 (sizeof(journal_block_tag_t)) +- + /* Tail of descriptor block, for checksumming */ + struct jbd2_journal_block_tail { + __be32 t_checksum; /* crc32c(uuid+descr_block) */ +@@ -284,6 +293,7 @@ typedef struct journal_superblock_s + #define JBD2_FEATURE_INCOMPAT_64BIT 0x00000002 + #define JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT 0x00000004 + #define JBD2_FEATURE_INCOMPAT_CSUM_V2 0x00000008 ++#define JBD2_FEATURE_INCOMPAT_CSUM_V3 0x00000010 + + /* Features known to this kernel version: */ + #define JBD2_KNOWN_COMPAT_FEATURES JBD2_FEATURE_COMPAT_CHECKSUM +@@ -291,7 +301,8 @@ typedef struct journal_superblock_s + #define JBD2_KNOWN_INCOMPAT_FEATURES (JBD2_FEATURE_INCOMPAT_REVOKE | \ + JBD2_FEATURE_INCOMPAT_64BIT | \ + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT | \ +- JBD2_FEATURE_INCOMPAT_CSUM_V2) ++ JBD2_FEATURE_INCOMPAT_CSUM_V2 | \ ++ JBD2_FEATURE_INCOMPAT_CSUM_V3) + + #ifdef __KERNEL__ + +@@ -1024,7 +1035,7 @@ struct buffer_head *jbd2_journal_get_descriptor_buffer(journal_t *journal); + int jbd2_journal_next_log_block(journal_t *, unsigned long long *); + int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid, + unsigned long *block); +-void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); ++int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); + void jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); + + /* Commit management */ +@@ -1146,7 +1157,7 @@ extern int jbd2_journal_recover (journal_t *journal); + extern int jbd2_journal_wipe (journal_t *, int); + extern int jbd2_journal_skip_recovery (journal_t *); + extern void jbd2_journal_update_sb_errno(journal_t *); +-extern void jbd2_journal_update_sb_log_tail (journal_t *, tid_t, ++extern int jbd2_journal_update_sb_log_tail (journal_t *, tid_t, + unsigned long, int); + extern void __jbd2_journal_abort_hard (journal_t *); + extern void jbd2_journal_abort (journal_t *, int); +@@ -1296,6 +1307,15 @@ static inline int tid_geq(tid_t x, tid_t y) + extern int jbd2_journal_blocks_per_page(struct inode *inode); + extern size_t journal_tag_bytes(journal_t *journal); + ++static inline int jbd2_journal_has_csum_v2or3(journal_t *journal) ++{ ++ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2) || ++ JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3)) ++ return 1; ++ ++ return 0; ++} ++ + /* + * We reserve t_outstanding_credits >> JBD2_CONTROL_BLOCKS_SHIFT for + * transaction control blocks. +diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h +index 1f44466..c367cbd 100644 +--- a/include/linux/jiffies.h ++++ b/include/linux/jiffies.h +@@ -258,23 +258,11 @@ extern unsigned long preset_lpj; + #define SEC_JIFFIE_SC (32 - SHIFT_HZ) + #endif + #define NSEC_JIFFIE_SC (SEC_JIFFIE_SC + 29) +-#define USEC_JIFFIE_SC (SEC_JIFFIE_SC + 19) + #define SEC_CONVERSION ((unsigned long)((((u64)NSEC_PER_SEC << SEC_JIFFIE_SC) +\ + TICK_NSEC -1) / (u64)TICK_NSEC)) + + #define NSEC_CONVERSION ((unsigned long)((((u64)1 << NSEC_JIFFIE_SC) +\ + TICK_NSEC -1) / (u64)TICK_NSEC)) +-#define USEC_CONVERSION \ +- ((unsigned long)((((u64)NSEC_PER_USEC << USEC_JIFFIE_SC) +\ +- TICK_NSEC -1) / (u64)TICK_NSEC)) +-/* +- * USEC_ROUND is used in the timeval to jiffie conversion. See there +- * for more details. It is the scaled resolution rounding value. Note +- * that it is a 64-bit value. Since, when it is applied, we are already +- * in jiffies (albit scaled), it is nothing but the bits we will shift +- * off. +- */ +-#define USEC_ROUND (u64)(((u64)1 << USEC_JIFFIE_SC) - 1) + /* + * The maximum jiffie value is (MAX_INT >> 1). Here we translate that + * into seconds. The 64-bit case will overflow if we are not careful, +diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h +index 5c1dfb2..784304b 100644 +--- a/include/linux/jump_label.h ++++ b/include/linux/jump_label.h +@@ -69,6 +69,10 @@ struct static_key { + + # include + # define HAVE_JUMP_LABEL ++#else ++struct static_key { ++ atomic_t enabled; ++}; + #endif /* CC_HAVE_ASM_GOTO && CONFIG_JUMP_LABEL */ + + enum jump_label_type { +@@ -79,6 +83,12 @@ enum jump_label_type { + struct module; + + #include ++ ++static inline int static_key_count(struct static_key *key) ++{ ++ return atomic_read(&key->enabled); ++} ++ + #ifdef HAVE_JUMP_LABEL + + #define JUMP_LABEL_TYPE_FALSE_BRANCH 0UL +@@ -134,10 +144,6 @@ extern void jump_label_apply_nops(struct module *mod); + + #else /* !HAVE_JUMP_LABEL */ + +-struct static_key { +- atomic_t enabled; +-}; +- + static __always_inline void jump_label_init(void) + { + static_key_initialized = true; +@@ -145,14 +151,14 @@ static __always_inline void jump_label_init(void) + + static __always_inline bool static_key_false(struct static_key *key) + { +- if (unlikely(atomic_read(&key->enabled) > 0)) ++ if (unlikely(static_key_count(key) > 0)) + return true; + return false; + } + + static __always_inline bool static_key_true(struct static_key *key) + { +- if (likely(atomic_read(&key->enabled) > 0)) ++ if (likely(static_key_count(key) > 0)) + return true; + return false; + } +@@ -194,7 +200,7 @@ static inline int jump_label_apply_nops(struct module *mod) + + static inline bool static_key_enabled(struct static_key *key) + { +- return (atomic_read(&key->enabled) > 0); ++ return static_key_count(key) > 0; + } + + #endif /* _LINUX_JUMP_LABEL_H */ +diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h +index 51c72be..4b2053a 100644 +--- a/include/linux/kernel_stat.h ++++ b/include/linux/kernel_stat.h +@@ -74,6 +74,7 @@ static inline unsigned int kstat_softirqs_cpu(unsigned int irq, int cpu) + * Number of interrupts per specific IRQ source, since bootup + */ + extern unsigned int kstat_irqs(unsigned int irq); ++extern unsigned int kstat_irqs_usr(unsigned int irq); + + /* + * Number of interrupts per cpu, since bootup +diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h +index 6b06d37..e465bb1 100644 +--- a/include/linux/kgdb.h ++++ b/include/linux/kgdb.h +@@ -283,7 +283,7 @@ struct kgdb_io { + + extern struct kgdb_arch arch_kgdb_ops; + +-extern unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs); ++extern unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs); + + #ifdef CONFIG_SERIAL_KGDB_NMI + extern int kgdb_register_nmi_console(void); +diff --git a/include/linux/libata.h b/include/linux/libata.h +index 3fee55e..189c9ff 100644 +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -204,6 +204,7 @@ enum { + ATA_LFLAG_SW_ACTIVITY = (1 << 7), /* keep activity stats */ + ATA_LFLAG_NO_LPM = (1 << 8), /* disable LPM on this link */ + ATA_LFLAG_RST_ONCE = (1 << 9), /* limit recovery to one reset */ ++ ATA_LFLAG_CHANGED = (1 << 10), /* LPM state changed on this link */ + + /* struct ata_port flags */ + ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */ +@@ -307,6 +308,12 @@ enum { + */ + ATA_TMOUT_PMP_SRST_WAIT = 5000, + ++ /* When the LPM policy is set to ATA_LPM_MAX_POWER, there might ++ * be a spurious PHY event, so ignore the first PHY event that ++ * occurs within 10s after the policy change. ++ */ ++ ATA_TMOUT_SPURIOUS_PHY = 10000, ++ + /* ATA bus states */ + BUS_UNKNOWN = 0, + BUS_DMA = 1, +@@ -421,6 +428,7 @@ enum { + ATA_HORKAGE_NO_NCQ_TRIM = (1 << 19), /* don't use queued TRIM */ + ATA_HORKAGE_NOLPM = (1 << 20), /* don't use LPM */ + ATA_HORKAGE_WD_BROKEN_LPM = (1 << 21), /* some WDs have broken LPM */ ++ ATA_HORKAGE_NOTRIM = (1 << 24), /* don't use TRIM */ + + /* DMA mask for user DMA control: User visible values; DO NOT + renumber */ +@@ -593,6 +601,7 @@ struct ata_host { + struct device *dev; + void __iomem * const *iomap; + unsigned int n_ports; ++ unsigned int n_tags; /* nr of NCQ tags */ + void *private_data; + struct ata_port_operations *ops; + unsigned long flags; +@@ -784,6 +793,8 @@ struct ata_link { + struct ata_eh_context eh_context; + + struct ata_device device[ATA_MAX_DEVICES]; ++ ++ unsigned long last_lpm_change; /* when last LPM change happened */ + }; + #define ATA_LINK_CLEAR_BEGIN offsetof(struct ata_link, active_tag) + #define ATA_LINK_CLEAR_END offsetof(struct ata_link, device[0]) +@@ -1200,6 +1211,7 @@ extern struct ata_device *ata_dev_pair(struct ata_device *adev); + extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev); + extern void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap); + extern void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, struct list_head *eh_q); ++extern bool sata_lpm_ignore_phy_events(struct ata_link *link); + + extern int ata_cable_40wire(struct ata_port *ap); + extern int ata_cable_80wire(struct ata_port *ap); +diff --git a/include/linux/mbus.h b/include/linux/mbus.h +index 345b8c5..550c88f 100644 +--- a/include/linux/mbus.h ++++ b/include/linux/mbus.h +@@ -73,6 +73,6 @@ int mvebu_mbus_del_window(phys_addr_t base, size_t size); + int mvebu_mbus_init(const char *soc, phys_addr_t mbus_phys_base, + size_t mbus_size, phys_addr_t sdram_phys_base, + size_t sdram_size); +-int mvebu_mbus_dt_init(void); ++int mvebu_mbus_dt_init(bool is_coherent); + + #endif /* __LINUX_MBUS_H */ +diff --git a/include/linux/memory.h b/include/linux/memory.h +index bb7384e..8b8d8d1 100644 +--- a/include/linux/memory.h ++++ b/include/linux/memory.h +@@ -35,7 +35,7 @@ struct memory_block { + }; + + int arch_get_memory_phys_device(unsigned long start_pfn); +-unsigned long __weak memory_block_size_bytes(void); ++unsigned long memory_block_size_bytes(void); + + /* These states are exposed to userspace as text strings in sysfs */ + #define MEM_ONLINE (1<<0) /* exposed to userspace */ +diff --git a/include/linux/migrate.h b/include/linux/migrate.h +index 84a31ad..a2901c4 100644 +--- a/include/linux/migrate.h ++++ b/include/linux/migrate.h +@@ -5,7 +5,9 @@ + #include + #include + +-typedef struct page *new_page_t(struct page *, unsigned long private, int **); ++typedef struct page *new_page_t(struct page *page, unsigned long private, ++ int **reason); ++typedef void free_page_t(struct page *page, unsigned long private); + + /* + * Return values from addresss_space_operations.migratepage(): +@@ -38,7 +40,7 @@ enum migrate_reason { + extern void putback_movable_pages(struct list_head *l); + extern int migrate_page(struct address_space *, + struct page *, struct page *, enum migrate_mode); +-extern int migrate_pages(struct list_head *l, new_page_t x, ++extern int migrate_pages(struct list_head *l, new_page_t new, free_page_t free, + unsigned long private, enum migrate_mode mode, int reason); + + extern int migrate_prep(void); +@@ -56,8 +58,9 @@ extern int migrate_page_move_mapping(struct address_space *mapping, + #else + + static inline void putback_movable_pages(struct list_head *l) {} +-static inline int migrate_pages(struct list_head *l, new_page_t x, +- unsigned long private, enum migrate_mode mode, int reason) ++static inline int migrate_pages(struct list_head *l, new_page_t new, ++ free_page_t free, unsigned long private, enum migrate_mode mode, ++ int reason) + { return -ENOSYS; } + + static inline int migrate_prep(void) { return -ENOSYS; } +diff --git a/include/linux/mm.h b/include/linux/mm.h +index c1b7414..a7b311d 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1009,6 +1009,7 @@ static inline int page_mapped(struct page *page) + #define VM_FAULT_WRITE 0x0008 /* Special case for get_user_pages */ + #define VM_FAULT_HWPOISON 0x0010 /* Hit poisoned small page */ + #define VM_FAULT_HWPOISON_LARGE 0x0020 /* Hit poisoned large page. Index encoded in upper bits */ ++#define VM_FAULT_SIGSEGV 0x0040 + + #define VM_FAULT_NOPAGE 0x0100 /* ->fault installed the pte, not return page */ + #define VM_FAULT_LOCKED 0x0200 /* ->fault locked the returned page */ +@@ -1017,8 +1018,9 @@ static inline int page_mapped(struct page *page) + + #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */ + +-#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | \ +- VM_FAULT_FALLBACK | VM_FAULT_HWPOISON_LARGE) ++#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \ ++ VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \ ++ VM_FAULT_FALLBACK) + + /* Encode hstate index for a hwpoisoned large page */ + #define VM_FAULT_SET_HINDEX(x) ((x) << 12) +@@ -1041,6 +1043,14 @@ extern void show_free_areas(unsigned int flags); + extern bool skip_free_areas_node(unsigned int flags, int nid); + + int shmem_zero_setup(struct vm_area_struct *); ++#ifdef CONFIG_SHMEM ++bool shmem_mapping(struct address_space *mapping); ++#else ++static inline bool shmem_mapping(struct address_space *mapping) ++{ ++ return false; ++} ++#endif + + extern int can_do_mlock(void); + extern int user_shm_lock(size_t, struct user_struct *); +@@ -1123,6 +1133,7 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping, + + extern void truncate_pagecache(struct inode *inode, loff_t new); + extern void truncate_setsize(struct inode *inode, loff_t newsize); ++void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to); + void truncate_pagecache_range(struct inode *inode, loff_t offset, loff_t end); + int truncate_inode_page(struct address_space *mapping, struct page *page); + int generic_error_remove_page(struct address_space *mapping, struct page *page); +@@ -1847,9 +1858,6 @@ void page_cache_async_readahead(struct address_space *mapping, + unsigned long size); + + unsigned long max_sane_readahead(unsigned long nr); +-unsigned long ra_submit(struct file_ra_state *ra, +- struct address_space *mapping, +- struct file *filp); + + /* Generic expand stack which grows the stack according to GROWS{UP,DOWN} */ + extern int expand_stack(struct vm_area_struct *vma, unsigned long address); +@@ -1860,7 +1868,7 @@ extern int expand_downwards(struct vm_area_struct *vma, + #if VM_GROWSUP + extern int expand_upwards(struct vm_area_struct *vma, unsigned long address); + #else +- #define expand_upwards(vma, address) do { } while (0) ++ #define expand_upwards(vma, address) (0) + #endif + + /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ +diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h +index 290901a..2b58d19 100644 +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -342,9 +342,9 @@ struct mm_rss_stat { + + struct kioctx_table; + struct mm_struct { +- struct vm_area_struct * mmap; /* list of VMAs */ ++ struct vm_area_struct *mmap; /* list of VMAs */ + struct rb_root mm_rb; +- struct vm_area_struct * mmap_cache; /* last find_vma result */ ++ u32 vmacache_seqnum; /* per-thread vmacache */ + #ifdef CONFIG_MMU + unsigned long (*get_unmapped_area) (struct file *filp, + unsigned long addr, unsigned long len, +diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h +index e6800f0..ac819bf 100644 +--- a/include/linux/mmzone.h ++++ b/include/linux/mmzone.h +@@ -78,10 +78,15 @@ extern int page_group_by_mobility_disabled; + #define NR_MIGRATETYPE_BITS (PB_migrate_end - PB_migrate + 1) + #define MIGRATETYPE_MASK ((1UL << NR_MIGRATETYPE_BITS) - 1) + +-static inline int get_pageblock_migratetype(struct page *page) ++#define get_pageblock_migratetype(page) \ ++ get_pfnblock_flags_mask(page, page_to_pfn(page), \ ++ PB_migrate_end, MIGRATETYPE_MASK) ++ ++static inline int get_pfnblock_migratetype(struct page *page, unsigned long pfn) + { + BUILD_BUG_ON(PB_migrate_end - PB_migrate != 2); +- return get_pageblock_flags_mask(page, PB_migrate_end, MIGRATETYPE_MASK); ++ return get_pfnblock_flags_mask(page, pfn, PB_migrate_end, ++ MIGRATETYPE_MASK); + } + + struct free_area { +@@ -138,6 +143,7 @@ enum zone_stat_item { + NR_SHMEM, /* shmem pages (included tmpfs/GEM pages) */ + NR_DIRTIED, /* page dirtyings since bootup */ + NR_WRITTEN, /* page writings since bootup */ ++ NR_PAGES_SCANNED, /* pages scanned since last reclaim */ + #ifdef CONFIG_NUMA + NUMA_HIT, /* allocated in intended node */ + NUMA_MISS, /* allocated in non intended node */ +@@ -316,19 +322,12 @@ enum zone_type { + #ifndef __GENERATING_BOUNDS_H + + struct zone { +- /* Fields commonly accessed by the page allocator */ ++ /* Read-mostly fields */ + + /* zone watermarks, access with *_wmark_pages(zone) macros */ + unsigned long watermark[NR_WMARK]; + + /* +- * When free pages are below this point, additional steps are taken +- * when reading the number of free pages to avoid per-cpu counter +- * drift allowing watermarks to be breached +- */ +- unsigned long percpu_drift_mark; +- +- /* + * We don't know if the memory that we're going to allocate will be freeable + * or/and it will be released eventually, so to avoid totally wasting several + * GB of ram we must reserve some of the lower zone memory (otherwise we risk +@@ -336,40 +335,26 @@ struct zone { + * on the higher zones). This array is recalculated at runtime if the + * sysctl_lowmem_reserve_ratio sysctl changes. + */ +- unsigned long lowmem_reserve[MAX_NR_ZONES]; +- +- /* +- * This is a per-zone reserve of pages that should not be +- * considered dirtyable memory. +- */ +- unsigned long dirty_balance_reserve; ++ long lowmem_reserve[MAX_NR_ZONES]; + + #ifdef CONFIG_NUMA + int node; ++#endif ++ + /* +- * zone reclaim becomes active if more unmapped pages exist. ++ * The target ratio of ACTIVE_ANON to INACTIVE_ANON pages on ++ * this zone's LRU. Maintained by the pageout code. + */ +- unsigned long min_unmapped_pages; +- unsigned long min_slab_pages; +-#endif ++ unsigned int inactive_ratio; ++ ++ struct pglist_data *zone_pgdat; + struct per_cpu_pageset __percpu *pageset; ++ + /* +- * free areas of different sizes ++ * This is a per-zone reserve of pages that should not be ++ * considered dirtyable memory. + */ +- spinlock_t lock; +-#if defined CONFIG_COMPACTION || defined CONFIG_CMA +- /* Set to true when the PG_migrate_skip bits should be cleared */ +- bool compact_blockskip_flush; +- +- /* pfns where compaction scanners should start */ +- unsigned long compact_cached_free_pfn; +- unsigned long compact_cached_migrate_pfn; +-#endif +-#ifdef CONFIG_MEMORY_HOTPLUG +- /* see spanned/present_pages for more description */ +- seqlock_t span_seqlock; +-#endif +- struct free_area free_area[MAX_ORDER]; ++ unsigned long dirty_balance_reserve; + + #ifndef CONFIG_SPARSEMEM + /* +@@ -379,71 +364,14 @@ struct zone { + unsigned long *pageblock_flags; + #endif /* CONFIG_SPARSEMEM */ + +-#ifdef CONFIG_COMPACTION +- /* +- * On compaction failure, 1<> PAGE_SHIFT */ + unsigned long zone_start_pfn; + +@@ -489,9 +417,11 @@ struct zone { + * adjust_managed_page_count() should be used instead of directly + * touching zone->managed_pages and totalram_pages. + */ ++ unsigned long managed_pages; + unsigned long spanned_pages; + unsigned long present_pages; +- unsigned long managed_pages; ++ ++ const char *name; + + /* + * Number of MIGRATE_RESEVE page block. To maintain for just +@@ -499,10 +429,91 @@ struct zone { + */ + int nr_migrate_reserve_block; + ++#ifdef CONFIG_MEMORY_HOTPLUG ++ /* see spanned/present_pages for more description */ ++ seqlock_t span_seqlock; ++#endif ++ + /* +- * rarely used fields: ++ * wait_table -- the array holding the hash table ++ * wait_table_hash_nr_entries -- the size of the hash table array ++ * wait_table_bits -- wait_table_size == (1 << wait_table_bits) ++ * ++ * The purpose of all these is to keep track of the people ++ * waiting for a page to become available and make them ++ * runnable again when possible. The trouble is that this ++ * consumes a lot of space, especially when so few things ++ * wait on pages at a given time. So instead of using ++ * per-page waitqueues, we use a waitqueue hash table. ++ * ++ * The bucket discipline is to sleep on the same queue when ++ * colliding and wake all in that wait queue when removing. ++ * When something wakes, it must check to be sure its page is ++ * truly available, a la thundering herd. The cost of a ++ * collision is great, but given the expected load of the ++ * table, they should be so rare as to be outweighed by the ++ * benefits from the saved space. ++ * ++ * __wait_on_page_locked() and unlock_page() in mm/filemap.c, are the ++ * primary users of these fields, and in mm/page_alloc.c ++ * free_area_init_core() performs the initialization of them. + */ +- const char *name; ++ wait_queue_head_t *wait_table; ++ unsigned long wait_table_hash_nr_entries; ++ unsigned long wait_table_bits; ++ ++ ZONE_PADDING(_pad1_) ++ ++ /* Write-intensive fields used from the page allocator */ ++ spinlock_t lock; ++ ++ /* free areas of different sizes */ ++ struct free_area free_area[MAX_ORDER]; ++ ++ /* zone flags, see below */ ++ unsigned long flags; ++ ++ ZONE_PADDING(_pad2_) ++ ++ /* Write-intensive fields used by page reclaim */ ++ ++ /* Fields commonly accessed by the page reclaim scanner */ ++ spinlock_t lru_lock; ++ struct lruvec lruvec; ++ ++ /* ++ * When free pages are below this point, additional steps are taken ++ * when reading the number of free pages to avoid per-cpu counter ++ * drift allowing watermarks to be breached ++ */ ++ unsigned long percpu_drift_mark; ++ ++#if defined CONFIG_COMPACTION || defined CONFIG_CMA ++ /* pfn where compaction free scanner should start */ ++ unsigned long compact_cached_free_pfn; ++ /* pfn where async and sync compaction migration scanner should start */ ++ unsigned long compact_cached_migrate_pfn[2]; ++#endif ++ ++#ifdef CONFIG_COMPACTION ++ /* ++ * On compaction failure, 1<flags); + } + ++static inline int zone_is_fair_depleted(const struct zone *zone) ++{ ++ return test_bit(ZONE_FAIR_DEPLETED, &zone->flags); ++} ++ + static inline int zone_is_oom_locked(const struct zone *zone) + { + return test_bit(ZONE_OOM_LOCKED, &zone->flags); +@@ -806,10 +823,10 @@ static inline bool pgdat_is_empty(pg_data_t *pgdat) + extern struct mutex zonelists_mutex; + void build_all_zonelists(pg_data_t *pgdat, struct zone *zone); + void wakeup_kswapd(struct zone *zone, int order, enum zone_type classzone_idx); +-bool zone_watermark_ok(struct zone *z, int order, unsigned long mark, +- int classzone_idx, int alloc_flags); +-bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark, +- int classzone_idx, int alloc_flags); ++bool zone_watermark_ok(struct zone *z, unsigned int order, ++ unsigned long mark, int classzone_idx, int alloc_flags); ++bool zone_watermark_ok_safe(struct zone *z, unsigned int order, ++ unsigned long mark, int classzone_idx, int alloc_flags); + enum memmap_context { + MEMMAP_EARLY, + MEMMAP_HOTPLUG, +diff --git a/include/linux/mount.h b/include/linux/mount.h +index 839bac2..b0c1e65 100644 +--- a/include/linux/mount.h ++++ b/include/linux/mount.h +@@ -42,13 +42,20 @@ struct mnt_namespace; + * flag, consider how it interacts with shared mounts. + */ + #define MNT_SHARED_MASK (MNT_UNBINDABLE) +-#define MNT_PROPAGATION_MASK (MNT_SHARED | MNT_UNBINDABLE) ++#define MNT_USER_SETTABLE_MASK (MNT_NOSUID | MNT_NODEV | MNT_NOEXEC \ ++ | MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME \ ++ | MNT_READONLY) ++#define MNT_ATIME_MASK (MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME ) + + #define MNT_INTERNAL_FLAGS (MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL | \ + MNT_DOOMED | MNT_SYNC_UMOUNT | MNT_MARKED) + + #define MNT_INTERNAL 0x4000 + ++#define MNT_LOCK_ATIME 0x040000 ++#define MNT_LOCK_NOEXEC 0x080000 ++#define MNT_LOCK_NOSUID 0x100000 ++#define MNT_LOCK_NODEV 0x200000 + #define MNT_LOCK_READONLY 0x400000 + #define MNT_LOCKED 0x800000 + #define MNT_DOOMED 0x1000000 +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index 911718f..bf46cc8 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1880,6 +1880,12 @@ void netdev_freemem(struct net_device *dev); + void synchronize_net(void); + int init_dummy_netdev(struct net_device *dev); + ++DECLARE_PER_CPU(int, xmit_recursion); ++static inline int dev_recursion_level(void) ++{ ++ return this_cpu_read(xmit_recursion); ++} ++ + struct net_device *dev_get_by_index(struct net *net, int ifindex); + struct net_device *__dev_get_by_index(struct net *net, int ifindex); + struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex); +diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h +index 5624e4e..3a36a2c 100644 +--- a/include/linux/nfs_xdr.h ++++ b/include/linux/nfs_xdr.h +@@ -1155,7 +1155,7 @@ struct nfs41_state_protection { + struct nfs4_op_map allow; + }; + +-#define NFS4_EXCHANGE_ID_LEN (48) ++#define NFS4_EXCHANGE_ID_LEN (127) + struct nfs41_exchange_id_args { + struct nfs_client *client; + nfs4_verifier *verifier; +@@ -1247,11 +1247,22 @@ struct nfs41_free_stateid_res { + unsigned int status; + }; + ++static inline void ++nfs_free_pnfs_ds_cinfo(struct pnfs_ds_commit_info *cinfo) ++{ ++ kfree(cinfo->buckets); ++} ++ + #else + + struct pnfs_ds_commit_info { + }; + ++static inline void ++nfs_free_pnfs_ds_cinfo(struct pnfs_ds_commit_info *cinfo) ++{ ++} ++ + #endif /* CONFIG_NFS_V4_1 */ + + struct nfs_page; +diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h +index 9875576..1108aca 100644 +--- a/include/linux/nilfs2_fs.h ++++ b/include/linux/nilfs2_fs.h +@@ -458,7 +458,7 @@ struct nilfs_btree_node { + /* level */ + #define NILFS_BTREE_LEVEL_DATA 0 + #define NILFS_BTREE_LEVEL_NODE_MIN (NILFS_BTREE_LEVEL_DATA + 1) +-#define NILFS_BTREE_LEVEL_MAX 14 ++#define NILFS_BTREE_LEVEL_MAX 14 /* Max level (exclusive) */ + + /** + * struct nilfs_palloc_group_desc - block group descriptor +diff --git a/include/linux/of.h b/include/linux/of.h +index 435cb99..9f2698d 100644 +--- a/include/linux/of.h ++++ b/include/linux/of.h +@@ -215,14 +215,12 @@ extern int of_property_read_u64(const struct device_node *np, + extern int of_property_read_string(struct device_node *np, + const char *propname, + const char **out_string); +-extern int of_property_read_string_index(struct device_node *np, +- const char *propname, +- int index, const char **output); + extern int of_property_match_string(struct device_node *np, + const char *propname, + const char *string); +-extern int of_property_count_strings(struct device_node *np, +- const char *propname); ++extern int of_property_read_string_helper(struct device_node *np, ++ const char *propname, ++ const char **out_strs, size_t sz, int index); + extern int of_device_is_compatible(const struct device_node *device, + const char *); + extern int of_device_is_available(const struct device_node *device); +@@ -422,15 +420,9 @@ static inline int of_property_read_string(struct device_node *np, + return -ENOSYS; + } + +-static inline int of_property_read_string_index(struct device_node *np, +- const char *propname, int index, +- const char **out_string) +-{ +- return -ENOSYS; +-} +- +-static inline int of_property_count_strings(struct device_node *np, +- const char *propname) ++static inline int of_property_read_string_helper(struct device_node *np, ++ const char *propname, ++ const char **out_strs, size_t sz, int index) + { + return -ENOSYS; + } +@@ -525,7 +517,10 @@ static inline const char *of_prop_next_string(struct property *prop, + #if defined(CONFIG_OF) && defined(CONFIG_NUMA) + extern int of_node_to_nid(struct device_node *np); + #else +-static inline int of_node_to_nid(struct device_node *device) { return 0; } ++static inline int of_node_to_nid(struct device_node *device) ++{ ++ return NUMA_NO_NODE; ++} + #endif + + static inline struct device_node *of_find_matching_node( +@@ -536,6 +531,70 @@ static inline struct device_node *of_find_matching_node( + } + + /** ++ * of_property_read_string_array() - Read an array of strings from a multiple ++ * strings property. ++ * @np: device node from which the property value is to be read. ++ * @propname: name of the property to be searched. ++ * @out_strs: output array of string pointers. ++ * @sz: number of array elements to read. ++ * ++ * Search for a property in a device tree node and retrieve a list of ++ * terminated string values (pointer to data, not a copy) in that property. ++ * ++ * If @out_strs is NULL, the number of strings in the property is returned. ++ */ ++static inline int of_property_read_string_array(struct device_node *np, ++ const char *propname, const char **out_strs, ++ size_t sz) ++{ ++ return of_property_read_string_helper(np, propname, out_strs, sz, 0); ++} ++ ++/** ++ * of_property_count_strings() - Find and return the number of strings from a ++ * multiple strings property. ++ * @np: device node from which the property value is to be read. ++ * @propname: name of the property to be searched. ++ * ++ * Search for a property in a device tree node and retrieve the number of null ++ * terminated string contain in it. Returns the number of strings on ++ * success, -EINVAL if the property does not exist, -ENODATA if property ++ * does not have a value, and -EILSEQ if the string is not null-terminated ++ * within the length of the property data. ++ */ ++static inline int of_property_count_strings(struct device_node *np, ++ const char *propname) ++{ ++ return of_property_read_string_helper(np, propname, NULL, 0, 0); ++} ++ ++/** ++ * of_property_read_string_index() - Find and read a string from a multiple ++ * strings property. ++ * @np: device node from which the property value is to be read. ++ * @propname: name of the property to be searched. ++ * @index: index of the string in the list of strings ++ * @out_string: pointer to null terminated return string, modified only if ++ * return value is 0. ++ * ++ * Search for a property in a device tree node and retrieve a null ++ * terminated string value (pointer to data, not a copy) in the list of strings ++ * contained in that property. ++ * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if ++ * property does not have a value, and -EILSEQ if the string is not ++ * null-terminated within the length of the property data. ++ * ++ * The out_string pointer is modified only if a valid string can be decoded. ++ */ ++static inline int of_property_read_string_index(struct device_node *np, ++ const char *propname, ++ int index, const char **output) ++{ ++ int rc = of_property_read_string_helper(np, propname, output, 1, index); ++ return rc < 0 ? rc : 0; ++} ++ ++/** + * of_property_read_bool - Findfrom a property + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. +diff --git a/include/linux/oom.h b/include/linux/oom.h +index 4cd6267..17f0949 100644 +--- a/include/linux/oom.h ++++ b/include/linux/oom.h +@@ -50,6 +50,9 @@ static inline bool oom_task_origin(const struct task_struct *p) + extern unsigned long oom_badness(struct task_struct *p, + struct mem_cgroup *memcg, const nodemask_t *nodemask, + unsigned long totalpages); ++ ++extern int oom_kills_count(void); ++extern void note_oom_kill(void); + extern void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, + unsigned int points, unsigned long totalpages, + struct mem_cgroup *memcg, nodemask_t *nodemask, +diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h +index ca71a1d..3c545b4 100644 +--- a/include/linux/page-flags.h ++++ b/include/linux/page-flags.h +@@ -198,6 +198,7 @@ struct page; /* forward declaration */ + TESTPAGEFLAG(Locked, locked) + PAGEFLAG(Error, error) TESTCLEARFLAG(Error, error) + PAGEFLAG(Referenced, referenced) TESTCLEARFLAG(Referenced, referenced) ++ __SETPAGEFLAG(Referenced, referenced) + PAGEFLAG(Dirty, dirty) TESTSCFLAG(Dirty, dirty) __CLEARPAGEFLAG(Dirty, dirty) + PAGEFLAG(LRU, lru) __CLEARPAGEFLAG(LRU, lru) + PAGEFLAG(Active, active) __CLEARPAGEFLAG(Active, active) +@@ -208,6 +209,7 @@ PAGEFLAG(Pinned, pinned) TESTSCFLAG(Pinned, pinned) /* Xen */ + PAGEFLAG(SavePinned, savepinned); /* Xen */ + PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved) + PAGEFLAG(SwapBacked, swapbacked) __CLEARPAGEFLAG(SwapBacked, swapbacked) ++ __SETPAGEFLAG(SwapBacked, swapbacked) + + __PAGEFLAG(SlobFree, slob_free) + +diff --git a/include/linux/pageblock-flags.h b/include/linux/pageblock-flags.h +index c08730c..2baeee1 100644 +--- a/include/linux/pageblock-flags.h ++++ b/include/linux/pageblock-flags.h +@@ -65,33 +65,26 @@ extern int pageblock_order; + /* Forward declaration */ + struct page; + +-unsigned long get_pageblock_flags_mask(struct page *page, ++unsigned long get_pfnblock_flags_mask(struct page *page, ++ unsigned long pfn, + unsigned long end_bitidx, + unsigned long mask); +-void set_pageblock_flags_mask(struct page *page, ++ ++void set_pfnblock_flags_mask(struct page *page, + unsigned long flags, ++ unsigned long pfn, + unsigned long end_bitidx, + unsigned long mask); + + /* Declarations for getting and setting flags. See mm/page_alloc.c */ +-static inline unsigned long get_pageblock_flags_group(struct page *page, +- int start_bitidx, int end_bitidx) +-{ +- unsigned long nr_flag_bits = end_bitidx - start_bitidx + 1; +- unsigned long mask = (1 << nr_flag_bits) - 1; +- +- return get_pageblock_flags_mask(page, end_bitidx, mask); +-} +- +-static inline void set_pageblock_flags_group(struct page *page, +- unsigned long flags, +- int start_bitidx, int end_bitidx) +-{ +- unsigned long nr_flag_bits = end_bitidx - start_bitidx + 1; +- unsigned long mask = (1 << nr_flag_bits) - 1; +- +- set_pageblock_flags_mask(page, flags, end_bitidx, mask); +-} ++#define get_pageblock_flags_group(page, start_bitidx, end_bitidx) \ ++ get_pfnblock_flags_mask(page, page_to_pfn(page), \ ++ end_bitidx, \ ++ (1 << (end_bitidx - start_bitidx + 1)) - 1) ++#define set_pageblock_flags_group(page, flags, start_bitidx, end_bitidx) \ ++ set_pfnblock_flags_mask(page, flags, page_to_pfn(page), \ ++ end_bitidx, \ ++ (1 << (end_bitidx - start_bitidx + 1)) - 1) + + #ifdef CONFIG_COMPACTION + #define get_pageblock_skip(page) \ +diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h +index 1710d1b..fcebdda 100644 +--- a/include/linux/pagemap.h ++++ b/include/linux/pagemap.h +@@ -99,7 +99,7 @@ static inline void mapping_set_gfp_mask(struct address_space *m, gfp_t mask) + + #define page_cache_get(page) get_page(page) + #define page_cache_release(page) put_page(page) +-void release_pages(struct page **pages, int nr, int cold); ++void release_pages(struct page **pages, int nr, bool cold); + + /* + * speculatively take a reference to a page. +@@ -243,12 +243,116 @@ static inline struct page *page_cache_alloc_readahead(struct address_space *x) + + typedef int filler_t(void *, struct page *); + +-extern struct page * find_get_page(struct address_space *mapping, +- pgoff_t index); +-extern struct page * find_lock_page(struct address_space *mapping, +- pgoff_t index); +-extern struct page * find_or_create_page(struct address_space *mapping, +- pgoff_t index, gfp_t gfp_mask); ++pgoff_t page_cache_next_hole(struct address_space *mapping, ++ pgoff_t index, unsigned long max_scan); ++pgoff_t page_cache_prev_hole(struct address_space *mapping, ++ pgoff_t index, unsigned long max_scan); ++ ++#define FGP_ACCESSED 0x00000001 ++#define FGP_LOCK 0x00000002 ++#define FGP_CREAT 0x00000004 ++#define FGP_WRITE 0x00000008 ++#define FGP_NOFS 0x00000010 ++#define FGP_NOWAIT 0x00000020 ++ ++struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset, ++ int fgp_flags, gfp_t cache_gfp_mask); ++ ++/** ++ * find_get_page - find and get a page reference ++ * @mapping: the address_space to search ++ * @offset: the page index ++ * ++ * Looks up the page cache slot at @mapping & @offset. If there is a ++ * page cache page, it is returned with an increased refcount. ++ * ++ * Otherwise, %NULL is returned. ++ */ ++static inline struct page *find_get_page(struct address_space *mapping, ++ pgoff_t offset) ++{ ++ return pagecache_get_page(mapping, offset, 0, 0); ++} ++ ++static inline struct page *find_get_page_flags(struct address_space *mapping, ++ pgoff_t offset, int fgp_flags) ++{ ++ return pagecache_get_page(mapping, offset, fgp_flags, 0); ++} ++ ++/** ++ * find_lock_page - locate, pin and lock a pagecache page ++ * pagecache_get_page - find and get a page reference ++ * @mapping: the address_space to search ++ * @offset: the page index ++ * ++ * Looks up the page cache slot at @mapping & @offset. If there is a ++ * page cache page, it is returned locked and with an increased ++ * refcount. ++ * ++ * Otherwise, %NULL is returned. ++ * ++ * find_lock_page() may sleep. ++ */ ++static inline struct page *find_lock_page(struct address_space *mapping, ++ pgoff_t offset) ++{ ++ return pagecache_get_page(mapping, offset, FGP_LOCK, 0); ++} ++ ++/** ++ * find_or_create_page - locate or add a pagecache page ++ * @mapping: the page's address_space ++ * @index: the page's index into the mapping ++ * @gfp_mask: page allocation mode ++ * ++ * Looks up the page cache slot at @mapping & @offset. If there is a ++ * page cache page, it is returned locked and with an increased ++ * refcount. ++ * ++ * If the page is not present, a new page is allocated using @gfp_mask ++ * and added to the page cache and the VM's LRU list. The page is ++ * returned locked and with an increased refcount. ++ * ++ * On memory exhaustion, %NULL is returned. ++ * ++ * find_or_create_page() may sleep, even if @gfp_flags specifies an ++ * atomic allocation! ++ */ ++static inline struct page *find_or_create_page(struct address_space *mapping, ++ pgoff_t offset, gfp_t gfp_mask) ++{ ++ return pagecache_get_page(mapping, offset, ++ FGP_LOCK|FGP_ACCESSED|FGP_CREAT, ++ gfp_mask); ++} ++ ++/** ++ * grab_cache_page_nowait - returns locked page at given index in given cache ++ * @mapping: target address_space ++ * @index: the page index ++ * ++ * Same as grab_cache_page(), but do not wait if the page is unavailable. ++ * This is intended for speculative data generators, where the data can ++ * be regenerated if the page couldn't be grabbed. This routine should ++ * be safe to call while holding the lock for another page. ++ * ++ * Clear __GFP_FS when allocating the page to avoid recursion into the fs ++ * and deadlock against the caller's locked page. ++ */ ++static inline struct page *grab_cache_page_nowait(struct address_space *mapping, ++ pgoff_t index) ++{ ++ return pagecache_get_page(mapping, index, ++ FGP_LOCK|FGP_CREAT|FGP_NOFS|FGP_NOWAIT, ++ mapping_gfp_mask(mapping)); ++} ++ ++struct page *find_get_entry(struct address_space *mapping, pgoff_t offset); ++struct page *find_lock_entry(struct address_space *mapping, pgoff_t offset); ++unsigned find_get_entries(struct address_space *mapping, pgoff_t start, ++ unsigned int nr_entries, struct page **entries, ++ pgoff_t *indices); + unsigned find_get_pages(struct address_space *mapping, pgoff_t start, + unsigned int nr_pages, struct page **pages); + unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start, +@@ -268,10 +372,6 @@ static inline struct page *grab_cache_page(struct address_space *mapping, + return find_or_create_page(mapping, index, mapping_gfp_mask(mapping)); + } + +-extern struct page * grab_cache_page_nowait(struct address_space *mapping, +- pgoff_t index); +-extern struct page * read_cache_page_async(struct address_space *mapping, +- pgoff_t index, filler_t *filler, void *data); + extern struct page * read_cache_page(struct address_space *mapping, + pgoff_t index, filler_t *filler, void *data); + extern struct page * read_cache_page_gfp(struct address_space *mapping, +@@ -279,14 +379,6 @@ extern struct page * read_cache_page_gfp(struct address_space *mapping, + extern int read_cache_pages(struct address_space *mapping, + struct list_head *pages, filler_t *filler, void *data); + +-static inline struct page *read_mapping_page_async( +- struct address_space *mapping, +- pgoff_t index, void *data) +-{ +- filler_t *filler = (filler_t *)mapping->a_ops->readpage; +- return read_cache_page_async(mapping, index, filler, data); +-} +- + static inline struct page *read_mapping_page(struct address_space *mapping, + pgoff_t index, void *data) + { +diff --git a/include/linux/pagevec.h b/include/linux/pagevec.h +index e4dbfab..b45d391 100644 +--- a/include/linux/pagevec.h ++++ b/include/linux/pagevec.h +@@ -22,6 +22,11 @@ struct pagevec { + + void __pagevec_release(struct pagevec *pvec); + void __pagevec_lru_add(struct pagevec *pvec); ++unsigned pagevec_lookup_entries(struct pagevec *pvec, ++ struct address_space *mapping, ++ pgoff_t start, unsigned nr_entries, ++ pgoff_t *indices); ++void pagevec_remove_exceptionals(struct pagevec *pvec); + unsigned pagevec_lookup(struct pagevec *pvec, struct address_space *mapping, + pgoff_t start, unsigned nr_pages); + unsigned pagevec_lookup_tag(struct pagevec *pvec, +diff --git a/include/linux/pci.h b/include/linux/pci.h +index 33aa2ca..d662546 100644 +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -170,6 +170,8 @@ enum pci_dev_flags { + PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2, + /* Provide indication device is assigned by a Virtual Machine Manager */ + PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4, ++ /* Do not use bus resets for device */ ++ PCI_DEV_FLAGS_NO_BUS_RESET = (__force pci_dev_flags_t) (1 << 6), + }; + + enum pci_irq_reroute_variant { +@@ -324,6 +326,7 @@ struct pci_dev { + unsigned int is_added:1; + unsigned int is_busmaster:1; /* device is busmaster */ + unsigned int no_msi:1; /* device may not use msi */ ++ unsigned int no_64bit_msi:1; /* device may only use 32-bit MSIs */ + unsigned int block_cfg_access:1; /* config space access is blocked */ + unsigned int broken_parity_status:1; /* Device generates false positive parity */ + unsigned int irq_reroute_variant:2; /* device needs IRQ rerouting variant */ +diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h +index 97fbecd..057c1d8 100644 +--- a/include/linux/pci_ids.h ++++ b/include/linux/pci_ids.h +@@ -2551,6 +2551,7 @@ + #define PCI_DEVICE_ID_INTEL_MFD_EMMC0 0x0823 + #define PCI_DEVICE_ID_INTEL_MFD_EMMC1 0x0824 + #define PCI_DEVICE_ID_INTEL_MRST_SD2 0x084F ++#define PCI_DEVICE_ID_INTEL_QUARK_X1000_ILB 0x095E + #define PCI_DEVICE_ID_INTEL_I960 0x0960 + #define PCI_DEVICE_ID_INTEL_I960RM 0x0962 + #define PCI_DEVICE_ID_INTEL_CENTERTON_ILB 0x0c60 +diff --git a/include/linux/plist.h b/include/linux/plist.h +index aa0fb39..8b6c970 100644 +--- a/include/linux/plist.h ++++ b/include/linux/plist.h +@@ -98,6 +98,13 @@ struct plist_node { + } + + /** ++ * PLIST_HEAD - declare and init plist_head ++ * @head: name for struct plist_head variable ++ */ ++#define PLIST_HEAD(head) \ ++ struct plist_head head = PLIST_HEAD_INIT(head) ++ ++/** + * PLIST_NODE_INIT - static struct plist_node initializer + * @node: struct plist_node variable name + * @__prio: initial node priority +@@ -134,6 +141,8 @@ static inline void plist_node_init(struct plist_node *node, int prio) + extern void plist_add(struct plist_node *node, struct plist_head *head); + extern void plist_del(struct plist_node *node, struct plist_head *head); + ++extern void plist_requeue(struct plist_node *node, struct plist_head *head); ++ + /** + * plist_for_each - iterate over the plist + * @pos: the type * to use as a loop counter +@@ -143,6 +152,16 @@ extern void plist_del(struct plist_node *node, struct plist_head *head); + list_for_each_entry(pos, &(head)->node_list, node_list) + + /** ++ * plist_for_each_continue - continue iteration over the plist ++ * @pos: the type * to use as a loop cursor ++ * @head: the head for your list ++ * ++ * Continue to iterate over plist, continuing after the current position. ++ */ ++#define plist_for_each_continue(pos, head) \ ++ list_for_each_entry_continue(pos, &(head)->node_list, node_list) ++ ++/** + * plist_for_each_safe - iterate safely over a plist of given type + * @pos: the type * to use as a loop counter + * @n: another type * to use as temporary storage +@@ -163,6 +182,18 @@ extern void plist_del(struct plist_node *node, struct plist_head *head); + list_for_each_entry(pos, &(head)->node_list, mem.node_list) + + /** ++ * plist_for_each_entry_continue - continue iteration over list of given type ++ * @pos: the type * to use as a loop cursor ++ * @head: the head for your list ++ * @m: the name of the list_struct within the struct ++ * ++ * Continue to iterate over list of given type, continuing after ++ * the current position. ++ */ ++#define plist_for_each_entry_continue(pos, head, m) \ ++ list_for_each_entry_continue(pos, &(head)->node_list, m.node_list) ++ ++/** + * plist_for_each_entry_safe - iterate safely over list of given type + * @pos: the type * to use as a loop counter + * @n: another type * to use as temporary storage +@@ -229,6 +260,20 @@ static inline int plist_node_empty(const struct plist_node *node) + #endif + + /** ++ * plist_next - get the next entry in list ++ * @pos: the type * to cursor ++ */ ++#define plist_next(pos) \ ++ list_next_entry(pos, node_list) ++ ++/** ++ * plist_prev - get the prev entry in list ++ * @pos: the type * to cursor ++ */ ++#define plist_prev(pos) \ ++ list_prev_entry(pos, node_list) ++ ++/** + * plist_first - return the first node (and thus, highest priority) + * @head: the &struct plist_head pointer + * +diff --git a/include/linux/power/charger-manager.h b/include/linux/power/charger-manager.h +index 07e7945..e97fc65 100644 +--- a/include/linux/power/charger-manager.h ++++ b/include/linux/power/charger-manager.h +@@ -253,9 +253,6 @@ struct charger_manager { + struct device *dev; + struct charger_desc *desc; + +- struct power_supply *fuel_gauge; +- struct power_supply **charger_stat; +- + #ifdef CONFIG_THERMAL + struct thermal_zone_device *tzd_batt; + #endif +diff --git a/include/linux/printk.h b/include/linux/printk.h +index fa47e27..cbf094f 100644 +--- a/include/linux/printk.h ++++ b/include/linux/printk.h +@@ -132,9 +132,9 @@ asmlinkage __printf(1, 2) __cold + int printk(const char *fmt, ...); + + /* +- * Special printk facility for scheduler use only, _DO_NOT_USE_ ! ++ * Special printk facility for scheduler/timekeeping use only, _DO_NOT_USE_ ! + */ +-__printf(1, 2) __cold int printk_sched(const char *fmt, ...); ++__printf(1, 2) __cold int printk_deferred(const char *fmt, ...); + + /* + * Please don't use printk_ratelimit(), because it shares ratelimiting state +@@ -169,7 +169,7 @@ int printk(const char *s, ...) + return 0; + } + static inline __printf(1, 2) __cold +-int printk_sched(const char *s, ...) ++int printk_deferred(const char *s, ...) + { + return 0; + } +diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h +index 9974975..4af3fdc 100644 +--- a/include/linux/pstore_ram.h ++++ b/include/linux/pstore_ram.h +@@ -53,7 +53,8 @@ struct persistent_ram_zone { + }; + + struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, +- u32 sig, struct persistent_ram_ecc_info *ecc_info); ++ u32 sig, struct persistent_ram_ecc_info *ecc_info, ++ unsigned int memtype); + void persistent_ram_free(struct persistent_ram_zone *prz); + void persistent_ram_zap(struct persistent_ram_zone *prz); + +@@ -76,6 +77,7 @@ ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz, + struct ramoops_platform_data { + unsigned long mem_size; + unsigned long mem_address; ++ unsigned int mem_type; + unsigned long record_size; + unsigned long console_size; + unsigned long ftrace_size; +diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h +index 4039407..e8be53e 100644 +--- a/include/linux/radix-tree.h ++++ b/include/linux/radix-tree.h +@@ -219,6 +219,7 @@ static inline void radix_tree_replace_slot(void **pslot, void *item) + int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); + void *radix_tree_lookup(struct radix_tree_root *, unsigned long); + void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long); ++void *radix_tree_delete_item(struct radix_tree_root *, unsigned long, void *); + void *radix_tree_delete(struct radix_tree_root *, unsigned long); + unsigned int + radix_tree_gang_lookup(struct radix_tree_root *root, void **results, +@@ -226,10 +227,6 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results, + unsigned int radix_tree_gang_lookup_slot(struct radix_tree_root *root, + void ***results, unsigned long *indices, + unsigned long first_index, unsigned int max_items); +-unsigned long radix_tree_next_hole(struct radix_tree_root *root, +- unsigned long index, unsigned long max_scan); +-unsigned long radix_tree_prev_hole(struct radix_tree_root *root, +- unsigned long index, unsigned long max_scan); + int radix_tree_preload(gfp_t gfp_mask); + int radix_tree_maybe_preload(gfp_t gfp_mask); + void radix_tree_init(void); +diff --git a/include/linux/sched.h b/include/linux/sched.h +index ccd0c6f..91fe6a3 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -59,6 +59,10 @@ struct sched_param { + + #define SCHED_ATTR_SIZE_VER0 48 /* sizeof first published struct */ + ++#define VMACACHE_BITS 2 ++#define VMACACHE_SIZE (1U << VMACACHE_BITS) ++#define VMACACHE_MASK (VMACACHE_SIZE - 1) ++ + /* + * Extended scheduling parameters data structure. + * +@@ -1228,6 +1232,9 @@ struct task_struct { + #ifdef CONFIG_COMPAT_BRK + unsigned brk_randomized:1; + #endif ++ /* per-thread vma caching */ ++ u32 vmacache_seqnum; ++ struct vm_area_struct *vmacache[VMACACHE_SIZE]; + #if defined(SPLIT_RSS_COUNTING) + struct task_rss_stat rss_stat; + #endif +@@ -1688,7 +1695,7 @@ static inline pid_t task_tgid_vnr(struct task_struct *tsk) + } + + +-static int pid_alive(const struct task_struct *p); ++static inline int pid_alive(const struct task_struct *p); + static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns) + { + pid_t pid = 0; +@@ -1869,11 +1876,13 @@ extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, + #define tsk_used_math(p) ((p)->flags & PF_USED_MATH) + #define used_math() tsk_used_math(current) + +-/* __GFP_IO isn't allowed if PF_MEMALLOC_NOIO is set in current->flags */ ++/* __GFP_IO isn't allowed if PF_MEMALLOC_NOIO is set in current->flags ++ * __GFP_FS is also cleared as it implies __GFP_IO. ++ */ + static inline gfp_t memalloc_noio_flags(gfp_t flags) + { + if (unlikely(current->flags & PF_MEMALLOC_NOIO)) +- flags &= ~__GFP_IO; ++ flags &= ~(__GFP_IO | __GFP_FS); + return flags; + } + +diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h +index 535f158..8cf3503 100644 +--- a/include/linux/seqlock.h ++++ b/include/linux/seqlock.h +@@ -164,8 +164,6 @@ static inline unsigned read_seqcount_begin(const seqcount_t *s) + static inline unsigned raw_seqcount_begin(const seqcount_t *s) + { + unsigned ret = ACCESS_ONCE(s->sequence); +- +- seqcount_lockdep_reader_access(s); + smp_rmb(); + return ret & ~1; + } +diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h +index 9d55438..4d1771c 100644 +--- a/include/linux/shmem_fs.h ++++ b/include/linux/shmem_fs.h +@@ -51,6 +51,7 @@ extern struct file *shmem_kernel_file_setup(const char *name, loff_t size, + unsigned long flags); + extern int shmem_zero_setup(struct vm_area_struct *); + extern int shmem_lock(struct file *file, int lock, struct user_struct *user); ++extern bool shmem_mapping(struct address_space *mapping); + extern void shmem_unlock_mapping(struct address_space *mapping); + extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping, + pgoff_t index, gfp_t gfp_mask); +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 6b84663..5ab5f97 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -661,6 +661,7 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, + + struct sk_buff *__alloc_skb(unsigned int size, gfp_t priority, int flags, + int node); ++struct sk_buff *__build_skb(void *data, unsigned int frag_size); + struct sk_buff *build_skb(void *data, unsigned int frag_size); + static inline struct sk_buff *alloc_skb(unsigned int size, + gfp_t priority) +@@ -2458,6 +2459,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen); + void skb_scrub_packet(struct sk_buff *skb, bool xnet); + unsigned int skb_gso_transport_seglen(const struct sk_buff *skb); + struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features); ++struct sk_buff *skb_vlan_untag(struct sk_buff *skb); + + struct skb_checksum_ops { + __wsum (*update)(const void *mem, int len, __wsum wsum); +diff --git a/include/linux/string.h b/include/linux/string.h +index ac889c5..0ed878d 100644 +--- a/include/linux/string.h ++++ b/include/linux/string.h +@@ -129,7 +129,7 @@ int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...) __printf(3, 4); + #endif + + extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos, +- const void *from, size_t available); ++ const void *from, size_t available); + + /** + * strstarts - does @str start with @prefix? +@@ -141,7 +141,8 @@ static inline bool strstarts(const char *str, const char *prefix) + return strncmp(str, prefix, strlen(prefix)) == 0; + } + +-extern size_t memweight(const void *ptr, size_t bytes); ++size_t memweight(const void *ptr, size_t bytes); ++void memzero_explicit(void *s, size_t count); + + /** + * kbasename - return the last part of a pathname. +diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h +index b05963f..f5bfb1a 100644 +--- a/include/linux/sunrpc/svc_xprt.h ++++ b/include/linux/sunrpc/svc_xprt.h +@@ -32,6 +32,7 @@ struct svc_xprt_class { + struct svc_xprt_ops *xcl_ops; + struct list_head xcl_list; + u32 xcl_max_payload; ++ int xcl_ident; + }; + + /* +diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h +index 8097b9d..51009d2 100644 +--- a/include/linux/sunrpc/xprt.h ++++ b/include/linux/sunrpc/xprt.h +@@ -340,6 +340,7 @@ int xs_swapper(struct rpc_xprt *xprt, int enable); + #define XPRT_CONNECTION_ABORT (7) + #define XPRT_CONNECTION_CLOSE (8) + #define XPRT_CONGESTED (9) ++#define XPRT_CONNECTION_REUSE (10) + + static inline void xprt_set_connected(struct rpc_xprt *xprt) + { +diff --git a/include/linux/swap.h b/include/linux/swap.h +index 46ba0c6..241bf09 100644 +--- a/include/linux/swap.h ++++ b/include/linux/swap.h +@@ -214,8 +214,9 @@ struct percpu_cluster { + struct swap_info_struct { + unsigned long flags; /* SWP_USED etc: see above */ + signed short prio; /* swap priority of this type */ ++ struct plist_node list; /* entry in swap_active_head */ ++ struct plist_node avail_list; /* entry in swap_avail_head */ + signed char type; /* strange name for an index */ +- signed char next; /* next type on the swap list */ + unsigned int max; /* extent of the swap_map */ + unsigned char *swap_map; /* vmalloc'ed array of usage counts */ + struct swap_cluster_info *cluster_info; /* cluster info. Only for SSD */ +@@ -255,11 +256,6 @@ struct swap_info_struct { + struct swap_cluster_info discard_cluster_tail; /* list tail of discard clusters */ + }; + +-struct swap_list_t { +- int head; /* head of priority-ordered swapfile list */ +- int next; /* swapfile to be used next */ +-}; +- + /* linux/mm/page_alloc.c */ + extern unsigned long totalram_pages; + extern unsigned long totalreserve_pages; +@@ -272,12 +268,14 @@ extern unsigned long nr_free_pagecache_pages(void); + + + /* linux/mm/swap.c */ +-extern void __lru_cache_add(struct page *); + extern void lru_cache_add(struct page *); ++extern void lru_cache_add_anon(struct page *page); ++extern void lru_cache_add_file(struct page *page); + extern void lru_add_page_tail(struct page *page, struct page *page_tail, + struct lruvec *lruvec, struct list_head *head); + extern void activate_page(struct page *); + extern void mark_page_accessed(struct page *); ++extern void init_page_accessed(struct page *page); + extern void lru_add_drain(void); + extern void lru_add_drain_cpu(int cpu); + extern void lru_add_drain_all(void); +@@ -287,22 +285,6 @@ extern void swap_setup(void); + + extern void add_page_to_unevictable_list(struct page *page); + +-/** +- * lru_cache_add: add a page to the page lists +- * @page: the page to add +- */ +-static inline void lru_cache_add_anon(struct page *page) +-{ +- ClearPageActive(page); +- __lru_cache_add(page); +-} +- +-static inline void lru_cache_add_file(struct page *page) +-{ +- ClearPageActive(page); +- __lru_cache_add(page); +-} +- + /* linux/mm/vmscan.c */ + extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order, + gfp_t gfp_mask, nodemask_t *mask); +@@ -460,7 +442,7 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) + #define free_page_and_swap_cache(page) \ + page_cache_release(page) + #define free_pages_and_swap_cache(pages, nr) \ +- release_pages((pages), (nr), 0); ++ release_pages((pages), (nr), false); + + static inline void show_swap_cache_info(void) + { +diff --git a/include/linux/swapfile.h b/include/linux/swapfile.h +index e282624..388293a 100644 +--- a/include/linux/swapfile.h ++++ b/include/linux/swapfile.h +@@ -6,7 +6,7 @@ + * want to expose them to the dozens of source files that include swap.h + */ + extern spinlock_t swap_lock; +-extern struct swap_list_t swap_list; ++extern struct plist_head swap_active_head; + extern struct swap_info_struct *swap_info[]; + extern int try_to_unuse(unsigned int, bool, unsigned long); + +diff --git a/include/linux/time.h b/include/linux/time.h +index d5d229b..7d532a3 100644 +--- a/include/linux/time.h ++++ b/include/linux/time.h +@@ -173,6 +173,19 @@ extern void getboottime(struct timespec *ts); + extern void monotonic_to_bootbased(struct timespec *ts); + extern void get_monotonic_boottime(struct timespec *ts); + ++static inline bool timeval_valid(const struct timeval *tv) ++{ ++ /* Dates before 1970 are bogus */ ++ if (tv->tv_sec < 0) ++ return false; ++ ++ /* Can't have more microseconds then a second */ ++ if (tv->tv_usec < 0 || tv->tv_usec >= USEC_PER_SEC) ++ return false; ++ ++ return true; ++} ++ + extern struct timespec timespec_trunc(struct timespec t, unsigned gran); + extern int timekeeping_valid_for_hres(void); + extern u64 timekeeping_max_deferment(void); +diff --git a/include/linux/tpm.h b/include/linux/tpm.h +index fff1d09..8350c53 100644 +--- a/include/linux/tpm.h ++++ b/include/linux/tpm.h +@@ -39,6 +39,9 @@ struct tpm_class_ops { + int (*send) (struct tpm_chip *chip, u8 *buf, size_t len); + void (*cancel) (struct tpm_chip *chip); + u8 (*status) (struct tpm_chip *chip); ++ bool (*update_timeouts)(struct tpm_chip *chip, ++ unsigned long *timeout_cap); ++ + }; + + #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) +diff --git a/include/linux/usb.h b/include/linux/usb.h +index 7f6eb85..49466be 100644 +--- a/include/linux/usb.h ++++ b/include/linux/usb.h +@@ -206,6 +206,32 @@ void usb_put_intf(struct usb_interface *intf); + #define USB_MAXINTERFACES 32 + #define USB_MAXIADS (USB_MAXINTERFACES/2) + ++/* ++ * USB Resume Timer: Every Host controller driver should drive the resume ++ * signalling on the bus for the amount of time defined by this macro. ++ * ++ * That way we will have a 'stable' behavior among all HCDs supported by Linux. ++ * ++ * Note that the USB Specification states we should drive resume for *at least* ++ * 20 ms, but it doesn't give an upper bound. This creates two possible ++ * situations which we want to avoid: ++ * ++ * (a) sometimes an msleep(20) might expire slightly before 20 ms, which causes ++ * us to fail USB Electrical Tests, thus failing Certification ++ * ++ * (b) Some (many) devices actually need more than 20 ms of resume signalling, ++ * and while we can argue that's against the USB Specification, we don't have ++ * control over which devices a certification laboratory will be using for ++ * certification. If CertLab uses a device which was tested against Windows and ++ * that happens to have relaxed resume signalling rules, we might fall into ++ * situations where we fail interoperability and electrical tests. ++ * ++ * In order to avoid both conditions, we're using a 40 ms resume timeout, which ++ * should cope with both LPJ calibration errors and devices not following every ++ * detail of the USB Specification. ++ */ ++#define USB_RESUME_TIMEOUT 40 /* ms */ ++ + /** + * struct usb_interface_cache - long-term representation of a device interface + * @num_altsetting: number of altsettings defined. +diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h +index efe8d8a..e34bce3 100644 +--- a/include/linux/usb/hcd.h ++++ b/include/linux/usb/hcd.h +@@ -447,6 +447,7 @@ extern const struct dev_pm_ops usb_hcd_pci_pm_ops; + #endif /* CONFIG_PCI */ + + /* pci-ish (pdev null is ok) buffer alloc/mapping support */ ++void usb_init_pool_max(void); + int hcd_buffer_create(struct usb_hcd *hcd); + void hcd_buffer_destroy(struct usb_hcd *hcd); + +diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h +index 52f944d..8b96ae2 100644 +--- a/include/linux/usb/quirks.h ++++ b/include/linux/usb/quirks.h +@@ -30,4 +30,10 @@ + descriptor */ + #define USB_QUIRK_DELAY_INIT 0x00000040 + ++/* device generates spurious wakeup, ignore remote wakeup capability */ ++#define USB_QUIRK_IGNORE_REMOTE_WAKEUP 0x00000200 ++ ++/* device can't handle device_qualifier descriptor requests */ ++#define USB_QUIRK_DEVICE_QUALIFIER 0x00000100 ++ + #endif /* __LINUX_USB_QUIRKS_H */ +diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h +index 4836ba3..e92abf9 100644 +--- a/include/linux/user_namespace.h ++++ b/include/linux/user_namespace.h +@@ -17,6 +17,10 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */ + } extent[UID_GID_MAP_MAX_EXTENTS]; + }; + ++#define USERNS_SETGROUPS_ALLOWED 1UL ++ ++#define USERNS_INIT_FLAGS USERNS_SETGROUPS_ALLOWED ++ + struct user_namespace { + struct uid_gid_map uid_map; + struct uid_gid_map gid_map; +@@ -27,6 +31,7 @@ struct user_namespace { + kuid_t owner; + kgid_t group; + unsigned int proc_inum; ++ unsigned long flags; + + /* Register of per-UID persistent keyrings for this namespace */ + #ifdef CONFIG_PERSISTENT_KEYRINGS +@@ -63,6 +68,9 @@ extern struct seq_operations proc_projid_seq_operations; + extern ssize_t proc_uid_map_write(struct file *, const char __user *, size_t, loff_t *); + extern ssize_t proc_gid_map_write(struct file *, const char __user *, size_t, loff_t *); + extern ssize_t proc_projid_map_write(struct file *, const char __user *, size_t, loff_t *); ++extern ssize_t proc_setgroups_write(struct file *, const char __user *, size_t, loff_t *); ++extern int proc_setgroups_show(struct seq_file *m, void *v); ++extern bool userns_may_setgroups(const struct user_namespace *ns); + #else + + static inline struct user_namespace *get_user_ns(struct user_namespace *ns) +@@ -87,6 +95,10 @@ static inline void put_user_ns(struct user_namespace *ns) + { + } + ++static inline bool userns_may_setgroups(const struct user_namespace *ns) ++{ ++ return true; ++} + #endif + + #endif /* _LINUX_USER_H */ +diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h +index 502073a..b483abd 100644 +--- a/include/linux/vga_switcheroo.h ++++ b/include/linux/vga_switcheroo.h +@@ -64,6 +64,7 @@ int vga_switcheroo_get_client_state(struct pci_dev *dev); + void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo_state dynamic); + + int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain); ++void vga_switcheroo_fini_domain_pm_ops(struct device *dev); + int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct dev_pm_domain *domain); + #else + +@@ -82,6 +83,7 @@ static inline int vga_switcheroo_get_client_state(struct pci_dev *dev) { return + static inline void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo_state dynamic) {} + + static inline int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain) { return -EINVAL; } ++static inline void vga_switcheroo_fini_domain_pm_ops(struct device *dev) {} + static inline int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct dev_pm_domain *domain) { return -EINVAL; } + + #endif +diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h +index 704f4f6..bc9d2c2 100644 +--- a/include/linux/workqueue.h ++++ b/include/linux/workqueue.h +@@ -71,7 +71,8 @@ enum { + /* data contains off-queue information when !WORK_STRUCT_PWQ */ + WORK_OFFQ_FLAG_BASE = WORK_STRUCT_COLOR_SHIFT, + +- WORK_OFFQ_CANCELING = (1 << WORK_OFFQ_FLAG_BASE), ++ __WORK_OFFQ_CANCELING = WORK_OFFQ_FLAG_BASE, ++ WORK_OFFQ_CANCELING = (1 << __WORK_OFFQ_CANCELING), + + /* + * When a work item is off queue, its high bits point to the last +@@ -452,7 +453,7 @@ __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active, + alloc_workqueue("%s", WQ_FREEZABLE | WQ_UNBOUND | WQ_MEM_RECLAIM, \ + 1, (name)) + #define create_singlethread_workqueue(name) \ +- alloc_workqueue("%s", WQ_UNBOUND | WQ_MEM_RECLAIM, 1, (name)) ++ alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM, name) + + extern void destroy_workqueue(struct workqueue_struct *wq); + +diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h +index bef53ce..b10682c 100644 +--- a/include/media/videobuf2-core.h ++++ b/include/media/videobuf2-core.h +@@ -329,6 +329,9 @@ struct v4l2_fh; + * @retry_start_streaming: start_streaming() was called, but there were not enough + * buffers queued. If set, then retry calling start_streaming when + * queuing a new buffer. ++ * @waiting_for_buffers: used in poll() to check if vb2 is still waiting for ++ * buffers. Only set for capture queues if qbuf has not yet been ++ * called since poll() needs to return POLLERR in that situation. + * @fileio: file io emulator internal data, used only if emulator is active + */ + struct vb2_queue { +@@ -362,6 +365,7 @@ struct vb2_queue { + + unsigned int streaming:1; + unsigned int retry_start_streaming:1; ++ unsigned int waiting_for_buffers:1; + + struct vb2_fileio_data *fileio; + }; +diff --git a/include/net/dst.h b/include/net/dst.h +index 77eb53f..9090328 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -466,6 +466,7 @@ void dst_init(void); + /* Flags for xfrm_lookup flags argument. */ + enum { + XFRM_LOOKUP_ICMP = 1 << 0, ++ XFRM_LOOKUP_QUEUE = 1 << 1, + }; + + struct flowi; +@@ -476,7 +477,16 @@ static inline struct dst_entry *xfrm_lookup(struct net *net, + int flags) + { + return dst_orig; +-} ++} ++ ++static inline struct dst_entry *xfrm_lookup_route(struct net *net, ++ struct dst_entry *dst_orig, ++ const struct flowi *fl, ++ struct sock *sk, ++ int flags) ++{ ++ return dst_orig; ++} + + static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) + { +@@ -488,6 +498,10 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, + const struct flowi *fl, struct sock *sk, + int flags); + ++struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig, ++ const struct flowi *fl, struct sock *sk, ++ int flags); ++ + /* skb attached with this dst needs transformation if dst->xfrm is valid */ + static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) + { +diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h +index c55aeed..cf92728 100644 +--- a/include/net/inet_connection_sock.h ++++ b/include/net/inet_connection_sock.h +@@ -62,6 +62,7 @@ struct inet_connection_sock_af_ops { + void (*addr2sockaddr)(struct sock *sk, struct sockaddr *); + int (*bind_conflict)(const struct sock *sk, + const struct inet_bind_bucket *tb, bool relax); ++ void (*mtu_reduced)(struct sock *sk); + }; + + /** inet_connection_sock - INET connection oriented sock +diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h +index 058271b..823ec7b 100644 +--- a/include/net/inetpeer.h ++++ b/include/net/inetpeer.h +@@ -41,14 +41,13 @@ struct inet_peer { + struct rcu_head gc_rcu; + }; + /* +- * Once inet_peer is queued for deletion (refcnt == -1), following fields +- * are not available: rid, ip_id_count ++ * Once inet_peer is queued for deletion (refcnt == -1), following field ++ * is not available: rid + * We can share memory with rcu_head to help keep inet_peer small. + */ + union { + struct { + atomic_t rid; /* Frag reception counter */ +- atomic_t ip_id_count; /* IP ID for the next packet */ + }; + struct rcu_head rcu; + struct inet_peer *gc_next; +@@ -165,7 +164,7 @@ bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout); + void inetpeer_invalidate_tree(struct inet_peer_base *); + + /* +- * temporary check to make sure we dont access rid, ip_id_count, tcp_ts, ++ * temporary check to make sure we dont access rid, tcp_ts, + * tcp_ts_stamp if no refcount is taken on inet_peer + */ + static inline void inet_peer_refcheck(const struct inet_peer *p) +@@ -173,13 +172,4 @@ static inline void inet_peer_refcheck(const struct inet_peer *p) + WARN_ON_ONCE(atomic_read(&p->refcnt) <= 0); + } + +- +-/* can be called with or without local BH being disabled */ +-static inline int inet_getid(struct inet_peer *p, int more) +-{ +- more++; +- inet_peer_refcheck(p); +- return atomic_add_return(more, &p->ip_id_count) - more; +-} +- + #endif /* _NET_INETPEER_H */ +diff --git a/include/net/ip.h b/include/net/ip.h +index 23be0fd..5128fa7 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -38,11 +38,12 @@ struct inet_skb_parm { + struct ip_options opt; /* Compiled IP options */ + unsigned char flags; + +-#define IPSKB_FORWARDED 1 +-#define IPSKB_XFRM_TUNNEL_SIZE 2 +-#define IPSKB_XFRM_TRANSFORMED 4 +-#define IPSKB_FRAG_COMPLETE 8 +-#define IPSKB_REROUTED 16 ++#define IPSKB_FORWARDED BIT(0) ++#define IPSKB_XFRM_TUNNEL_SIZE BIT(1) ++#define IPSKB_XFRM_TRANSFORMED BIT(2) ++#define IPSKB_FRAG_COMPLETE BIT(3) ++#define IPSKB_REROUTED BIT(4) ++#define IPSKB_DOREDIRECT BIT(5) + + u16 frag_max_size; + }; +@@ -174,7 +175,7 @@ static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg) + return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0; + } + +-void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, ++void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, + __be32 saddr, const struct ip_reply_arg *arg, + unsigned int len); + +@@ -297,9 +298,10 @@ static inline unsigned int ip_skb_dst_mtu(const struct sk_buff *skb) + } + } + +-void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more); ++u32 ip_idents_reserve(u32 hash, int segs); ++void __ip_select_ident(struct iphdr *iph, int segs); + +-static inline void ip_select_ident(struct sk_buff *skb, struct dst_entry *dst, struct sock *sk) ++static inline void ip_select_ident_segs(struct sk_buff *skb, struct sock *sk, int segs) + { + struct iphdr *iph = ip_hdr(skb); + +@@ -309,24 +311,20 @@ static inline void ip_select_ident(struct sk_buff *skb, struct dst_entry *dst, s + * does not change, they drop every other packet in + * a TCP stream using header compression. + */ +- iph->id = (sk && inet_sk(sk)->inet_daddr) ? +- htons(inet_sk(sk)->inet_id++) : 0; +- } else +- __ip_select_ident(iph, dst, 0); +-} +- +-static inline void ip_select_ident_more(struct sk_buff *skb, struct dst_entry *dst, struct sock *sk, int more) +-{ +- struct iphdr *iph = ip_hdr(skb); +- +- if ((iph->frag_off & htons(IP_DF)) && !skb->local_df) { + if (sk && inet_sk(sk)->inet_daddr) { + iph->id = htons(inet_sk(sk)->inet_id); +- inet_sk(sk)->inet_id += 1 + more; +- } else ++ inet_sk(sk)->inet_id += segs; ++ } else { + iph->id = 0; +- } else +- __ip_select_ident(iph, dst, more); ++ } ++ } else { ++ __ip_select_ident(iph, segs); ++ } ++} ++ ++static inline void ip_select_ident(struct sk_buff *skb, struct sock *sk) ++{ ++ ip_select_ident_segs(skb, sk, 1); + } + + /* +@@ -409,22 +407,6 @@ static __inline__ void inet_reset_saddr(struct sock *sk) + + #endif + +-static inline int sk_mc_loop(struct sock *sk) +-{ +- if (!sk) +- return 1; +- switch (sk->sk_family) { +- case AF_INET: +- return inet_sk(sk)->mc_loop; +-#if IS_ENABLED(CONFIG_IPV6) +- case AF_INET6: +- return inet6_sk(sk)->mc_loop; +-#endif +- } +- WARN_ON(1); +- return 1; +-} +- + bool ip_call_ra_chain(struct sk_buff *skb); + + /* +diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h +index 2e74c6c..ee2d53a 100644 +--- a/include/net/ip6_route.h ++++ b/include/net/ip6_route.h +@@ -168,7 +168,8 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); + + static inline int ip6_skb_dst_mtu(struct sk_buff *skb) + { +- struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; ++ struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ? ++ inet6_sk(skb->sk) : NULL; + + return (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) ? + skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); +diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h +index e77c104..7b9ec58 100644 +--- a/include/net/ip_tunnels.h ++++ b/include/net/ip_tunnels.h +@@ -40,6 +40,7 @@ struct ip_tunnel_prl_entry { + + struct ip_tunnel_dst { + struct dst_entry __rcu *dst; ++ __be32 saddr; + }; + + struct ip_tunnel { +diff --git a/include/net/ipv6.h b/include/net/ipv6.h +index 4f541f1..a60948d 100644 +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -660,7 +660,7 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add + return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr)); + } + +-void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt); ++void ipv6_proxy_select_ident(struct sk_buff *skb); + + int ip6_dst_hoplimit(struct dst_entry *dst); + +diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h +index 80f500a..57c2da9 100644 +--- a/include/net/netns/ipv4.h ++++ b/include/net/netns/ipv4.h +@@ -47,6 +47,7 @@ struct netns_ipv4 { + struct inet_peer_base *peers; + struct tcpm_hash_bucket *tcp_metrics_hash; + unsigned int tcp_metrics_hash_log; ++ struct sock * __percpu *tcp_sk; + struct netns_frags frags; + #ifdef CONFIG_NETFILTER + struct xt_table *iptable_filter; +diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h +index 3573a81..8ba379f 100644 +--- a/include/net/netns/sctp.h ++++ b/include/net/netns/sctp.h +@@ -31,6 +31,7 @@ struct netns_sctp { + struct list_head addr_waitq; + struct timer_list addr_wq_timer; + struct list_head auto_asconf_splist; ++ /* Lock that protects both addr_waitq and auto_asconf_splist */ + spinlock_t addr_wq_lock; + + /* Lock that protects the local_addr_list writers */ +diff --git a/include/net/regulatory.h b/include/net/regulatory.h +index b07cdc9..f103f30 100644 +--- a/include/net/regulatory.h ++++ b/include/net/regulatory.h +@@ -160,7 +160,7 @@ struct ieee80211_reg_rule { + struct ieee80211_regdomain { + struct rcu_head rcu_head; + u32 n_reg_rules; +- char alpha2[2]; ++ char alpha2[3]; + enum nl80211_dfs_regions dfs_region; + struct ieee80211_reg_rule reg_rules[]; + }; +diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h +index 4b7cd69..cfcbc3f 100644 +--- a/include/net/sctp/command.h ++++ b/include/net/sctp/command.h +@@ -115,7 +115,7 @@ typedef enum { + * analysis of the state functions, but in reality just taken from + * thin air in the hopes othat we don't trigger a kernel panic. + */ +-#define SCTP_MAX_NUM_COMMANDS 14 ++#define SCTP_MAX_NUM_COMMANDS 20 + + typedef union { + __s32 i32; +diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h +index a3353f4..ba41e01 100644 +--- a/include/net/sctp/sctp.h ++++ b/include/net/sctp/sctp.h +@@ -433,6 +433,11 @@ static inline void sctp_assoc_pending_pmtu(struct sock *sk, struct sctp_associat + asoc->pmtu_pending = 0; + } + ++static inline bool sctp_chunk_pending(const struct sctp_chunk *chunk) ++{ ++ return !list_empty(&chunk->list); ++} ++ + /* Walk through a list of TLV parameters. Don't trust the + * individual parameter lengths and instead depend on + * the chunk length to indicate when to stop. Make sure +diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h +index 7f4eeb3..72a31db 100644 +--- a/include/net/sctp/sm.h ++++ b/include/net/sctp/sm.h +@@ -248,9 +248,9 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *, + int, __be16); + struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc, + union sctp_addr *addr); +-int sctp_verify_asconf(const struct sctp_association *asoc, +- struct sctp_paramhdr *param_hdr, void *chunk_end, +- struct sctp_paramhdr **errp); ++bool sctp_verify_asconf(const struct sctp_association *asoc, ++ struct sctp_chunk *chunk, bool addr_param_needed, ++ struct sctp_paramhdr **errp); + struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, + struct sctp_chunk *asconf); + int sctp_process_asconf_ack(struct sctp_association *asoc, +diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h +index 0dfcc92..2c2d388 100644 +--- a/include/net/sctp/structs.h ++++ b/include/net/sctp/structs.h +@@ -219,6 +219,10 @@ struct sctp_sock { + atomic_t pd_mode; + /* Receive to here while partial delivery is in effect. */ + struct sk_buff_head pd_lobby; ++ ++ /* These must be the last fields, as they will skipped on copies, ++ * like on accept and peeloff operations ++ */ + struct list_head auto_asconf_list; + int do_auto_asconf; + }; +diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h +index f257486..3f36d45 100644 +--- a/include/net/secure_seq.h ++++ b/include/net/secure_seq.h +@@ -3,8 +3,6 @@ + + #include + +-__u32 secure_ip_id(__be32 daddr); +-__u32 secure_ipv6_id(const __be32 daddr[4]); + u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport); + u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, + __be16 dport); +diff --git a/include/net/sock.h b/include/net/sock.h +index 2f7bc43..0c79a74 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -969,7 +969,6 @@ struct proto { + struct sk_buff *skb); + + void (*release_cb)(struct sock *sk); +- void (*mtu_reduced)(struct sock *sk); + + /* Keeping track of sk's, looking them up, and port selection methods. */ + void (*hash)(struct sock *sk); +@@ -1816,6 +1815,8 @@ struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie); + + struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie); + ++bool sk_mc_loop(struct sock *sk); ++ + static inline bool sk_can_gso(const struct sock *sk) + { + return net_gso_ok(sk->sk_route_caps, sk->sk_gso_type); +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 743acce..1f0d847 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -453,6 +453,7 @@ const u8 *tcp_parse_md5sig_option(const struct tcphdr *th); + */ + + void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb); ++void tcp_v4_mtu_reduced(struct sock *sk); + int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb); + struct sock *tcp_create_openreq_child(struct sock *sk, + struct request_sock *req, +@@ -720,8 +721,10 @@ struct tcp_skb_cb { + #define TCPCB_SACKED_RETRANS 0x02 /* SKB retransmitted */ + #define TCPCB_LOST 0x04 /* SKB is lost */ + #define TCPCB_TAGBITS 0x07 /* All tag bits */ ++#define TCPCB_REPAIRED 0x10 /* SKB repaired (no skb_mstamp) */ + #define TCPCB_EVER_RETRANS 0x80 /* Ever retransmitted frame */ +-#define TCPCB_RETRANS (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS) ++#define TCPCB_RETRANS (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS| \ ++ TCPCB_REPAIRED) + + __u8 ip_dsfield; /* IPv4 tos or IPv6 dsfield */ + /* 1 byte hole */ +diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h +index b4f1eff..409fafb 100644 +--- a/include/scsi/scsi_device.h ++++ b/include/scsi/scsi_device.h +@@ -149,6 +149,7 @@ struct scsi_device { + unsigned skip_ms_page_8:1; /* do not use MODE SENSE page 0x08 */ + unsigned skip_ms_page_3f:1; /* do not use MODE SENSE page 0x3f */ + unsigned skip_vpd_pages:1; /* do not read VPD pages */ ++ unsigned try_vpd_pages:1; /* attempt to read VPD pages */ + unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */ + unsigned no_start_on_add:1; /* do not issue start on add */ + unsigned allow_restart:1; /* issue START_UNIT in error handler */ +diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h +index 447d2d7..183eaab 100644 +--- a/include/scsi/scsi_devinfo.h ++++ b/include/scsi/scsi_devinfo.h +@@ -32,4 +32,9 @@ + #define BLIST_ATTACH_PQ3 0x1000000 /* Scan: Attach to PQ3 devices */ + #define BLIST_NO_DIF 0x2000000 /* Disable T10 PI (DIF) */ + #define BLIST_SKIP_VPD_PAGES 0x4000000 /* Ignore SBC-3 VPD pages */ ++#define BLIST_SCSI3LUN 0x8000000 /* Scan more than 256 LUNs ++ for sequential scan */ ++#define BLIST_TRY_VPD_PAGES 0x10000000 /* Attempt to read VPD pages */ ++#define BLIST_NO_RSOC 0x20000000 /* don't try to issue RSOC */ ++ + #endif +diff --git a/include/sound/ak4113.h b/include/sound/ak4113.h +index 2609048..3a34f6e 100644 +--- a/include/sound/ak4113.h ++++ b/include/sound/ak4113.h +@@ -286,7 +286,7 @@ struct ak4113 { + ak4113_write_t *write; + ak4113_read_t *read; + void *private_data; +- unsigned int init:1; ++ atomic_t wq_processing; + spinlock_t lock; + unsigned char regmap[AK4113_WRITABLE_REGS]; + struct snd_kcontrol *kctls[AK4113_CONTROLS]; +diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h +index 52f02a6..069299a 100644 +--- a/include/sound/ak4114.h ++++ b/include/sound/ak4114.h +@@ -168,7 +168,7 @@ struct ak4114 { + ak4114_write_t * write; + ak4114_read_t * read; + void * private_data; +- unsigned int init: 1; ++ atomic_t wq_processing; + spinlock_t lock; + unsigned char regmap[6]; + unsigned char txcsb[5]; +diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h +index dfb42ca..8898cde 100644 +--- a/include/sound/emu10k1.h ++++ b/include/sound/emu10k1.h +@@ -41,7 +41,8 @@ + + #define EMUPAGESIZE 4096 + #define MAXREQVOICES 8 +-#define MAXPAGES 8192 ++#define MAXPAGES0 4096 /* 32 bit mode */ ++#define MAXPAGES1 8192 /* 31 bit mode */ + #define RESERVED 0 + #define NUM_MIDI 16 + #define NUM_G 64 /* use all channels */ +@@ -50,8 +51,7 @@ + + /* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */ + #define EMU10K1_DMA_MASK 0x7fffffffUL /* 31bit */ +-#define AUDIGY_DMA_MASK 0x7fffffffUL /* 31bit FIXME - 32 should work? */ +- /* See ALSA bug #1276 - rlrevell */ ++#define AUDIGY_DMA_MASK 0xffffffffUL /* 32bit mode */ + + #define TMEMSIZE 256*1024 + #define TMEMSIZEREG 4 +@@ -468,8 +468,11 @@ + + #define MAPB 0x0d /* Cache map B */ + +-#define MAP_PTE_MASK 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */ +-#define MAP_PTI_MASK 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */ ++#define MAP_PTE_MASK0 0xfffff000 /* The 20 MSBs of the PTE indexed by the PTI */ ++#define MAP_PTI_MASK0 0x00000fff /* The 12 bit index to one of the 4096 PTE dwords */ ++ ++#define MAP_PTE_MASK1 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */ ++#define MAP_PTI_MASK1 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */ + + /* 0x0e, 0x0f: Not used */ + +@@ -1706,6 +1709,7 @@ struct snd_emu10k1 { + unsigned short model; /* subsystem id */ + unsigned int card_type; /* EMU10K1_CARD_* */ + unsigned int ecard_ctrl; /* ecard control bits */ ++ unsigned int address_mode; /* address mode */ + unsigned long dma_mask; /* PCI DMA mask */ + unsigned int delay_pcm_irq; /* in samples */ + int max_cache_pages; /* max memory size / PAGE_SIZE */ +diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h +index 6e89ef6..13412ab 100644 +--- a/include/sound/soc-dapm.h ++++ b/include/sound/soc-dapm.h +@@ -302,7 +302,7 @@ struct device; + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ + .tlv.p = (tlv_array), \ + .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ +- .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } ++ .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) } + #define SOC_DAPM_SINGLE_TLV_VIRT(xname, max, tlv_array) \ + SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0, tlv_array) + #define SOC_DAPM_ENUM(xname, xenum) \ +diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h +index 2883a7a..98f2ade 100644 +--- a/include/sound/soc-dpcm.h ++++ b/include/sound/soc-dpcm.h +@@ -102,6 +102,8 @@ struct snd_soc_dpcm_runtime { + /* state and update */ + enum snd_soc_dpcm_update runtime_update; + enum snd_soc_dpcm_state state; ++ ++ int trigger_pending; /* trigger cmd + 1 if pending, 0 if not */ + }; + + /* can this BE stop and free */ +diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h +index 1772fad..e4b9e01 100644 +--- a/include/target/target_core_base.h ++++ b/include/target/target_core_base.h +@@ -407,7 +407,7 @@ struct t10_reservation { + /* Activate Persistence across Target Power Loss enabled + * for SCSI device */ + int pr_aptpl_active; +-#define PR_APTPL_BUF_LEN 8192 ++#define PR_APTPL_BUF_LEN 262144 + u32 pr_generation; + spinlock_t registration_lock; + spinlock_t aptpl_reg_lock; +@@ -513,7 +513,7 @@ struct se_cmd { + sense_reason_t (*execute_cmd)(struct se_cmd *); + sense_reason_t (*execute_rw)(struct se_cmd *, struct scatterlist *, + u32, enum dma_data_direction); +- sense_reason_t (*transport_complete_callback)(struct se_cmd *); ++ sense_reason_t (*transport_complete_callback)(struct se_cmd *, bool); + + unsigned char *t_task_cdb; + unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE]; +diff --git a/include/trace/events/compaction.h b/include/trace/events/compaction.h +index 06f544e..c6814b9 100644 +--- a/include/trace/events/compaction.h ++++ b/include/trace/events/compaction.h +@@ -5,6 +5,7 @@ + #define _TRACE_COMPACTION_H + + #include ++#include + #include + #include + +@@ -47,10 +48,11 @@ DEFINE_EVENT(mm_compaction_isolate_template, mm_compaction_isolate_freepages, + + TRACE_EVENT(mm_compaction_migratepages, + +- TP_PROTO(unsigned long nr_migrated, +- unsigned long nr_failed), ++ TP_PROTO(unsigned long nr_all, ++ int migrate_rc, ++ struct list_head *migratepages), + +- TP_ARGS(nr_migrated, nr_failed), ++ TP_ARGS(nr_all, migrate_rc, migratepages), + + TP_STRUCT__entry( + __field(unsigned long, nr_migrated) +@@ -58,7 +60,22 @@ TRACE_EVENT(mm_compaction_migratepages, + ), + + TP_fast_assign( +- __entry->nr_migrated = nr_migrated; ++ unsigned long nr_failed = 0; ++ struct list_head *page_lru; ++ ++ /* ++ * migrate_pages() returns either a non-negative number ++ * with the number of pages that failed migration, or an ++ * error code, in which case we need to count the remaining ++ * pages manually ++ */ ++ if (migrate_rc >= 0) ++ nr_failed = migrate_rc; ++ else ++ list_for_each(page_lru, migratepages) ++ nr_failed++; ++ ++ __entry->nr_migrated = nr_all - nr_failed; + __entry->nr_failed = nr_failed; + ), + +diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h +index aece134..4ad10ba 100644 +--- a/include/trace/events/kmem.h ++++ b/include/trace/events/kmem.h +@@ -268,11 +268,11 @@ TRACE_EVENT(mm_page_alloc_extfrag, + + TP_PROTO(struct page *page, + int alloc_order, int fallback_order, +- int alloc_migratetype, int fallback_migratetype, int new_migratetype), ++ int alloc_migratetype, int fallback_migratetype), + + TP_ARGS(page, + alloc_order, fallback_order, +- alloc_migratetype, fallback_migratetype, new_migratetype), ++ alloc_migratetype, fallback_migratetype), + + TP_STRUCT__entry( + __field( struct page *, page ) +@@ -289,7 +289,8 @@ TRACE_EVENT(mm_page_alloc_extfrag, + __entry->fallback_order = fallback_order; + __entry->alloc_migratetype = alloc_migratetype; + __entry->fallback_migratetype = fallback_migratetype; +- __entry->change_ownership = (new_migratetype == alloc_migratetype); ++ __entry->change_ownership = (alloc_migratetype == ++ get_pageblock_migratetype(page)); + ), + + TP_printk("page=%p pfn=%lu alloc_order=%d fallback_order=%d pageblock_order=%d alloc_migratetype=%d fallback_migratetype=%d fragmenting=%d change_ownership=%d", +diff --git a/include/trace/events/pagemap.h b/include/trace/events/pagemap.h +index 1c9fabd..ce0803b 100644 +--- a/include/trace/events/pagemap.h ++++ b/include/trace/events/pagemap.h +@@ -28,12 +28,10 @@ TRACE_EVENT(mm_lru_insertion, + + TP_PROTO( + struct page *page, +- unsigned long pfn, +- int lru, +- unsigned long flags ++ int lru + ), + +- TP_ARGS(page, pfn, lru, flags), ++ TP_ARGS(page, lru), + + TP_STRUCT__entry( + __field(struct page *, page ) +@@ -44,9 +42,9 @@ TRACE_EVENT(mm_lru_insertion, + + TP_fast_assign( + __entry->page = page; +- __entry->pfn = pfn; ++ __entry->pfn = page_to_pfn(page); + __entry->lru = lru; +- __entry->flags = flags; ++ __entry->flags = trace_pagemap_flags(page); + ), + + /* Flag format is based on page-types.c formatting for pagemap */ +@@ -64,9 +62,9 @@ TRACE_EVENT(mm_lru_insertion, + + TRACE_EVENT(mm_lru_activate, + +- TP_PROTO(struct page *page, unsigned long pfn), ++ TP_PROTO(struct page *page), + +- TP_ARGS(page, pfn), ++ TP_ARGS(page), + + TP_STRUCT__entry( + __field(struct page *, page ) +@@ -75,7 +73,7 @@ TRACE_EVENT(mm_lru_activate, + + TP_fast_assign( + __entry->page = page; +- __entry->pfn = pfn; ++ __entry->pfn = page_to_pfn(page); + ), + + /* Flag format is based on page-types.c formatting for pagemap */ +diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h +index 67e1bbf..dc7bb01 100644 +--- a/include/trace/events/sched.h ++++ b/include/trace/events/sched.h +@@ -100,7 +100,7 @@ static inline long __trace_sched_switch_state(struct task_struct *p) + /* + * For all intents and purposes a preempted task is a running task. + */ +- if (task_preempt_count(p) & PREEMPT_ACTIVE) ++ if (preempt_count() & PREEMPT_ACTIVE) + state = TASK_RUNNING | TASK_STATE_MAX; + #endif + +diff --git a/include/uapi/drm/vmwgfx_drm.h b/include/uapi/drm/vmwgfx_drm.h +index 87792a5..33b7395 100644 +--- a/include/uapi/drm/vmwgfx_drm.h ++++ b/include/uapi/drm/vmwgfx_drm.h +@@ -29,7 +29,7 @@ + #define __VMWGFX_DRM_H__ + + #ifndef __KERNEL__ +-#include ++#include + #endif + + #define DRM_VMW_MAX_SURFACE_FACES 6 +diff --git a/include/uapi/linux/in6.h b/include/uapi/linux/in6.h +index e9a1d2d..4c399ae 100644 +--- a/include/uapi/linux/in6.h ++++ b/include/uapi/linux/in6.h +@@ -149,7 +149,7 @@ struct in6_flowlabel_req { + /* + * IPV6 socket options + */ +- ++#if __UAPI_DEF_IPV6_OPTIONS + #define IPV6_ADDRFORM 1 + #define IPV6_2292PKTINFO 2 + #define IPV6_2292HOPOPTS 3 +@@ -192,6 +192,7 @@ struct in6_flowlabel_req { + + #define IPV6_IPSEC_POLICY 34 + #define IPV6_XFRM_POLICY 35 ++#endif + + /* + * Multicast: +diff --git a/include/uapi/linux/libc-compat.h b/include/uapi/linux/libc-compat.h +index c140620..e28807a 100644 +--- a/include/uapi/linux/libc-compat.h ++++ b/include/uapi/linux/libc-compat.h +@@ -69,6 +69,7 @@ + #define __UAPI_DEF_SOCKADDR_IN6 0 + #define __UAPI_DEF_IPV6_MREQ 0 + #define __UAPI_DEF_IPPROTO_V6 0 ++#define __UAPI_DEF_IPV6_OPTIONS 0 + + #else + +@@ -82,6 +83,7 @@ + #define __UAPI_DEF_SOCKADDR_IN6 1 + #define __UAPI_DEF_IPV6_MREQ 1 + #define __UAPI_DEF_IPPROTO_V6 1 ++#define __UAPI_DEF_IPV6_OPTIONS 1 + + #endif /* _NETINET_IN_H */ + +@@ -103,6 +105,7 @@ + #define __UAPI_DEF_SOCKADDR_IN6 1 + #define __UAPI_DEF_IPV6_MREQ 1 + #define __UAPI_DEF_IPPROTO_V6 1 ++#define __UAPI_DEF_IPV6_OPTIONS 1 + + /* Definitions for xattr.h */ + #define __UAPI_DEF_XATTR 1 +diff --git a/include/uapi/linux/netfilter/xt_bpf.h b/include/uapi/linux/netfilter/xt_bpf.h +index 5dda450..2ec9fbc 100644 +--- a/include/uapi/linux/netfilter/xt_bpf.h ++++ b/include/uapi/linux/netfilter/xt_bpf.h +@@ -6,6 +6,8 @@ + + #define XT_BPF_MAX_NUM_INSTR 64 + ++struct sk_filter; ++ + struct xt_bpf_info { + __u16 bpf_program_num_elem; + struct sock_filter bpf_program[XT_BPF_MAX_NUM_INSTR]; +diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h +index 30db069..788c5aa 100644 +--- a/include/uapi/linux/pci_regs.h ++++ b/include/uapi/linux/pci_regs.h +@@ -319,6 +319,7 @@ + #define PCI_MSIX_PBA 8 /* Pending Bit Array offset */ + #define PCI_MSIX_PBA_BIR 0x00000007 /* BAR index */ + #define PCI_MSIX_PBA_OFFSET 0xfffffff8 /* Offset into specified BAR */ ++#define PCI_MSIX_FLAGS_BIRMASK PCI_MSIX_PBA_BIR /* deprecated */ + #define PCI_CAP_MSIX_SIZEOF 12 /* size of MSIX registers */ + + /* MSI-X Table entry format */ +diff --git a/include/uapi/linux/usb/functionfs.h b/include/uapi/linux/usb/functionfs.h +index 29e9c7a..f279394 100644 +--- a/include/uapi/linux/usb/functionfs.h ++++ b/include/uapi/linux/usb/functionfs.h +@@ -27,24 +27,18 @@ struct usb_endpoint_descriptor_no_audio { + __u8 bInterval; + } __attribute__((packed)); + +-/* Legacy format, deprecated as of 3.14. */ +-struct usb_functionfs_descs_head { +- __le32 magic; +- __le32 length; +- __le32 fs_count; +- __le32 hs_count; +-} __attribute__((packed, deprecated)); + + /* + * All numbers must be in little endian order. + */ + ++/* Legacy format, deprecated as of 3.14. */ + struct usb_functionfs_descs_head { + __le32 magic; + __le32 length; + __le32 fs_count; + __le32 hs_count; +-} __attribute__((packed)); ++} __attribute__((packed, deprecated)); + + /* + * Descriptors format: +diff --git a/include/uapi/linux/usbdevice_fs.h b/include/uapi/linux/usbdevice_fs.h +index 0c65e4b..ef29266 100644 +--- a/include/uapi/linux/usbdevice_fs.h ++++ b/include/uapi/linux/usbdevice_fs.h +@@ -125,11 +125,12 @@ struct usbdevfs_hub_portinfo { + char port [127]; /* e.g. port 3 connects to device 27 */ + }; + +-/* Device capability flags */ ++/* System and bus capability flags */ + #define USBDEVFS_CAP_ZERO_PACKET 0x01 + #define USBDEVFS_CAP_BULK_CONTINUATION 0x02 + #define USBDEVFS_CAP_NO_PACKET_SIZE_LIM 0x04 + #define USBDEVFS_CAP_BULK_SCATTER_GATHER 0x08 ++#define USBDEVFS_CAP_REAP_AFTER_DISCONNECT 0x10 + + /* USBDEVFS_DISCONNECT_CLAIM flags & struct */ + +diff --git a/include/uapi/linux/xattr.h b/include/uapi/linux/xattr.h +index c38355c..1590c49 100644 +--- a/include/uapi/linux/xattr.h ++++ b/include/uapi/linux/xattr.h +@@ -13,7 +13,7 @@ + #ifndef _UAPI_LINUX_XATTR_H + #define _UAPI_LINUX_XATTR_H + +-#ifdef __UAPI_DEF_XATTR ++#if __UAPI_DEF_XATTR + #define __USE_KERNEL_XATTR_DEFS + + #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */ +diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h +index 99b80ab..3066718 100644 +--- a/include/uapi/rdma/rdma_user_cm.h ++++ b/include/uapi/rdma/rdma_user_cm.h +@@ -34,6 +34,7 @@ + #define RDMA_USER_CM_H + + #include ++#include + #include + #include + #include +diff --git a/include/xen/events.h b/include/xen/events.h +index c9c85cf..5d84cd0 100644 +--- a/include/xen/events.h ++++ b/include/xen/events.h +@@ -14,7 +14,7 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn, + irq_handler_t handler, + unsigned long irqflags, const char *devname, + void *dev_id); +-int bind_virq_to_irq(unsigned int virq, unsigned int cpu); ++int bind_virq_to_irq(unsigned int virq, unsigned int cpu, bool percpu); + int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, + irq_handler_t handler, + unsigned long irqflags, const char *devname, +diff --git a/init/Kconfig b/init/Kconfig +index 93c5ef0..8b9521a 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1389,6 +1389,7 @@ config FUTEX + + config HAVE_FUTEX_CMPXCHG + bool ++ depends on FUTEX + help + Architectures should select this if futex_atomic_cmpxchg_inatomic() + is implemented and always working. This removes a couple of runtime +diff --git a/init/main.c b/init/main.c +index 9c7fd4c..008edce 100644 +--- a/init/main.c ++++ b/init/main.c +@@ -617,6 +617,10 @@ asmlinkage void __init start_kernel(void) + if (efi_enabled(EFI_RUNTIME_SERVICES)) + efi_enter_virtual_mode(); + #endif ++#ifdef CONFIG_X86_ESPFIX64 ++ /* Should be run before the first non-init thread is created */ ++ init_espfix_bsp(); ++#endif + thread_info_cache_init(); + cred_init(); + fork_init(totalram_pages); +@@ -639,6 +643,7 @@ asmlinkage void __init start_kernel(void) + + check_bugs(); + ++ acpi_subsystem_init(); + sfi_init_late(); + + if (efi_enabled(EFI_RUNTIME_SERVICES)) { +diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c +index 1702864..cadddc8 100644 +--- a/ipc/ipc_sysctl.c ++++ b/ipc/ipc_sysctl.c +@@ -123,7 +123,6 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) + { + struct ctl_table ipc_table; +- size_t lenp_bef = *lenp; + int oldval; + int rc; + +@@ -133,7 +132,7 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, + + rc = proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); + +- if (write && !rc && lenp_bef == *lenp) { ++ if (write && !rc) { + int newval = *((int *)(ipc_table.data)); + /* + * The file "auto_msgmni" has correctly been set. +diff --git a/ipc/mqueue.c b/ipc/mqueue.c +index c3b3117..9699d3f 100644 +--- a/ipc/mqueue.c ++++ b/ipc/mqueue.c +@@ -143,7 +143,6 @@ static int msg_insert(struct msg_msg *msg, struct mqueue_inode_info *info) + if (!leaf) + return -ENOMEM; + INIT_LIST_HEAD(&leaf->msg_list); +- info->qsize += sizeof(*leaf); + } + leaf->priority = msg->m_type; + rb_link_node(&leaf->rb_node, parent, p); +@@ -188,7 +187,6 @@ try_again: + "lazy leaf delete!\n"); + rb_erase(&leaf->rb_node, &info->msg_tree); + if (info->node_cache) { +- info->qsize -= sizeof(*leaf); + kfree(leaf); + } else { + info->node_cache = leaf; +@@ -201,7 +199,6 @@ try_again: + if (list_empty(&leaf->msg_list)) { + rb_erase(&leaf->rb_node, &info->msg_tree); + if (info->node_cache) { +- info->qsize -= sizeof(*leaf); + kfree(leaf); + } else { + info->node_cache = leaf; +@@ -1026,7 +1023,6 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr, + /* Save our speculative allocation into the cache */ + INIT_LIST_HEAD(&new_leaf->msg_list); + info->node_cache = new_leaf; +- info->qsize += sizeof(*new_leaf); + new_leaf = NULL; + } else { + kfree(new_leaf); +@@ -1133,7 +1129,6 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr, + /* Save our speculative allocation into the cache */ + INIT_LIST_HEAD(&new_leaf->msg_list); + info->node_cache = new_leaf; +- info->qsize += sizeof(*new_leaf); + } else { + kfree(new_leaf); + } +diff --git a/ipc/sem.c b/ipc/sem.c +index bee5554..e53c96f 100644 +--- a/ipc/sem.c ++++ b/ipc/sem.c +@@ -253,6 +253,16 @@ static void sem_rcu_free(struct rcu_head *head) + } + + /* ++ * spin_unlock_wait() and !spin_is_locked() are not memory barriers, they ++ * are only control barriers. ++ * The code must pair with spin_unlock(&sem->lock) or ++ * spin_unlock(&sem_perm.lock), thus just the control barrier is insufficient. ++ * ++ * smp_rmb() is sufficient, as writes cannot pass the control barrier. ++ */ ++#define ipc_smp_acquire__after_spin_is_unlocked() smp_rmb() ++ ++/* + * Wait until all currently ongoing simple ops have completed. + * Caller must own sem_perm.lock. + * New simple ops cannot start, because simple ops first check +@@ -275,6 +285,7 @@ static void sem_wait_array(struct sem_array *sma) + sem = sma->sem_base + i; + spin_unlock_wait(&sem->lock); + } ++ ipc_smp_acquire__after_spin_is_unlocked(); + } + + /* +@@ -326,8 +337,13 @@ static inline int sem_lock(struct sem_array *sma, struct sembuf *sops, + + /* Then check that the global lock is free */ + if (!spin_is_locked(&sma->sem_perm.lock)) { +- /* spin_is_locked() is not a memory barrier */ +- smp_mb(); ++ /* ++ * We need a memory barrier with acquire semantics, ++ * otherwise we can race with another thread that does: ++ * complex_count++; ++ * spin_unlock(sem_perm.lock); ++ */ ++ ipc_smp_acquire__after_spin_is_unlocked(); + + /* Now repeat the test of complex_count: + * It can't change anymore until we drop sem->lock. +@@ -2055,17 +2071,28 @@ void exit_sem(struct task_struct *tsk) + rcu_read_lock(); + un = list_entry_rcu(ulp->list_proc.next, + struct sem_undo, list_proc); +- if (&un->list_proc == &ulp->list_proc) +- semid = -1; +- else +- semid = un->semid; ++ if (&un->list_proc == &ulp->list_proc) { ++ /* ++ * We must wait for freeary() before freeing this ulp, ++ * in case we raced with last sem_undo. There is a small ++ * possibility where we exit while freeary() didn't ++ * finish unlocking sem_undo_list. ++ */ ++ spin_unlock_wait(&ulp->lock); ++ rcu_read_unlock(); ++ break; ++ } ++ spin_lock(&ulp->lock); ++ semid = un->semid; ++ spin_unlock(&ulp->lock); + ++ /* exit_sem raced with IPC_RMID, nothing to do */ + if (semid == -1) { + rcu_read_unlock(); +- break; ++ continue; + } + +- sma = sem_obtain_object_check(tsk->nsproxy->ipc_ns, un->semid); ++ sma = sem_obtain_object_check(tsk->nsproxy->ipc_ns, semid); + /* exit_sem raced with IPC_RMID, nothing to do */ + if (IS_ERR(sma)) { + rcu_read_unlock(); +diff --git a/kernel/audit.c b/kernel/audit.c +index 0c9dc86..b45b2da 100644 +--- a/kernel/audit.c ++++ b/kernel/audit.c +@@ -687,7 +687,7 @@ static int audit_get_feature(struct sk_buff *skb) + + seq = nlmsg_hdr(skb)->nlmsg_seq; + +- audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &af, sizeof(af)); ++ audit_send_reply(skb, seq, AUDIT_GET_FEATURE, 0, 0, &af, sizeof(af)); + + return 0; + } +@@ -702,7 +702,7 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature + + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE); + audit_log_task_info(ab, current); +- audit_log_format(ab, "feature=%s old=%u new=%u old_lock=%u new_lock=%u res=%d", ++ audit_log_format(ab, " feature=%s old=%u new=%u old_lock=%u new_lock=%u res=%d", + audit_feature_names[which], !!old_feature, !!new_feature, + !!old_lock, !!new_lock, res); + audit_log_end(ab); +@@ -1628,7 +1628,7 @@ void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap) + audit_log_format(ab, " %s=", prefix); + CAP_FOR_EACH_U32(i) { + audit_log_format(ab, "%08x", +- cap->cap[(_KERNEL_CAPABILITY_U32S-1) - i]); ++ cap->cap[CAP_LAST_U32 - i]); + } + } + +diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c +index 135944a..a79db03 100644 +--- a/kernel/audit_tree.c ++++ b/kernel/audit_tree.c +@@ -154,6 +154,7 @@ static struct audit_chunk *alloc_chunk(int count) + chunk->owners[i].index = i; + } + fsnotify_init_mark(&chunk->mark, audit_tree_destroy_watch); ++ chunk->mark.mask = FS_IN_IGNORED; + return chunk; + } + +diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c +index 92062fd..598c1dc 100644 +--- a/kernel/auditfilter.c ++++ b/kernel/auditfilter.c +@@ -429,6 +429,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, + if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) { + f->type = AUDIT_LOGINUID_SET; + f->val = 0; ++ entry->rule.pflags |= AUDIT_LOGINUID_LEGACY; + } + + err = audit_field_valid(entry, f); +@@ -604,6 +605,13 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) + data->buflen += data->values[i] = + audit_pack_string(&bufp, krule->filterkey); + break; ++ case AUDIT_LOGINUID_SET: ++ if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) { ++ data->fields[i] = AUDIT_LOGINUID; ++ data->values[i] = AUDIT_UID_UNSET; ++ break; ++ } ++ /* fallthrough if set */ + default: + data->values[i] = f->val; + } +@@ -620,6 +628,7 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b) + int i; + + if (a->flags != b->flags || ++ a->pflags != b->pflags || + a->listnr != b->listnr || + a->action != b->action || + a->field_count != b->field_count) +@@ -738,6 +747,7 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old) + new = &entry->rule; + new->vers_ops = old->vers_ops; + new->flags = old->flags; ++ new->pflags = old->pflags; + new->listnr = old->listnr; + new->action = old->action; + for (i = 0; i < AUDIT_BITMASK_SIZE; i++) +diff --git a/kernel/capability.c b/kernel/capability.c +index 1191a44..00adb21 100644 +--- a/kernel/capability.c ++++ b/kernel/capability.c +@@ -268,6 +268,10 @@ SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data) + i++; + } + ++ effective.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; ++ permitted.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; ++ inheritable.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; ++ + new = prepare_creds(); + if (!new) + return -ENOMEM; +diff --git a/kernel/cgroup.c b/kernel/cgroup.c +index 0c753dd..18711f3 100644 +--- a/kernel/cgroup.c ++++ b/kernel/cgroup.c +@@ -971,7 +971,7 @@ static void cgroup_d_remove_dir(struct dentry *dentry) + parent = dentry->d_parent; + spin_lock(&parent->d_lock); + spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); +- list_del_init(&dentry->d_u.d_child); ++ list_del_init(&dentry->d_child); + spin_unlock(&dentry->d_lock); + spin_unlock(&parent->d_lock); + remove_dir(dentry); +@@ -3663,7 +3663,6 @@ static int pidlist_array_load(struct cgroup *cgrp, enum cgroup_filetype type, + + l = cgroup_pidlist_find_create(cgrp, type); + if (!l) { +- mutex_unlock(&cgrp->pidlist_mutex); + pidlist_free(array); + return -ENOMEM; + } +diff --git a/kernel/cpuset.c b/kernel/cpuset.c +index 6b27e5c..7b4530b 100644 +--- a/kernel/cpuset.c ++++ b/kernel/cpuset.c +@@ -61,12 +61,7 @@ + #include + #include + +-/* +- * Tracks how many cpusets are currently defined in system. +- * When there is only one cpuset (the root cpuset) we can +- * short circuit some hooks. +- */ +-int number_of_cpusets __read_mostly; ++struct static_key cpusets_enabled_key __read_mostly = STATIC_KEY_INIT_FALSE; + + /* See "Frequency meter" comments, below. */ + +@@ -508,9 +503,6 @@ static void update_domain_attr_tree(struct sched_domain_attr *dattr, + + rcu_read_lock(); + cpuset_for_each_descendant_pre(cp, pos_css, root_cs) { +- if (cp == root_cs) +- continue; +- + /* skip the whole subtree if @cp doesn't have any CPU */ + if (cpumask_empty(cp->cpus_allowed)) { + pos_css = css_rightmost_descendant(pos_css); +@@ -611,7 +603,7 @@ static int generate_sched_domains(cpumask_var_t **domains, + goto done; + } + +- csa = kmalloc(number_of_cpusets * sizeof(cp), GFP_KERNEL); ++ csa = kmalloc(nr_cpusets() * sizeof(cp), GFP_KERNEL); + if (!csa) + goto done; + csn = 0; +@@ -1022,7 +1014,7 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk, + task_lock(tsk); + /* + * Determine if a loop is necessary if another thread is doing +- * get_mems_allowed(). If at least one node remains unchanged and ++ * read_mems_allowed_begin(). If at least one node remains unchanged and + * tsk does not have a mempolicy, then an empty nodemask will not be + * possible when mems_allowed is larger than a word. + */ +@@ -1961,7 +1953,7 @@ static int cpuset_css_online(struct cgroup_subsys_state *css) + if (is_spread_slab(parent)) + set_bit(CS_SPREAD_SLAB, &cs->flags); + +- number_of_cpusets++; ++ cpuset_inc(); + + if (!test_bit(CGRP_CPUSET_CLONE_CHILDREN, &css->cgroup->flags)) + goto out_unlock; +@@ -2012,7 +2004,7 @@ static void cpuset_css_offline(struct cgroup_subsys_state *css) + if (is_sched_load_balance(cs)) + update_flag(CS_SCHED_LOAD_BALANCE, cs, 0); + +- number_of_cpusets--; ++ cpuset_dec(); + clear_bit(CS_ONLINE, &cs->flags); + + mutex_unlock(&cpuset_mutex); +@@ -2067,7 +2059,6 @@ int __init cpuset_init(void) + if (!alloc_cpumask_var(&cpus_attach, GFP_KERNEL)) + BUG(); + +- number_of_cpusets = 1; + return 0; + } + +diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c +index 334b398..8865cae 100644 +--- a/kernel/debug/debug_core.c ++++ b/kernel/debug/debug_core.c +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -224,10 +225,17 @@ static void kgdb_flush_swbreak_addr(unsigned long addr) + if (!CACHE_FLUSH_IS_SAFE) + return; + +- if (current->mm && current->mm->mmap_cache) { +- flush_cache_range(current->mm->mmap_cache, +- addr, addr + BREAK_INSTR_SIZE); ++ if (current->mm) { ++ int i; ++ ++ for (i = 0; i < VMACACHE_SIZE; i++) { ++ if (!current->vmacache[i]) ++ continue; ++ flush_cache_range(current->vmacache[i], ++ addr, addr + BREAK_INSTR_SIZE); ++ } + } ++ + /* Force flush instruction cache if it was outside the mm */ + flush_icache_range(addr, addr + BREAK_INSTR_SIZE); + } +diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c +index 0b097c8..449518e 100644 +--- a/kernel/debug/kdb/kdb_main.c ++++ b/kernel/debug/kdb/kdb_main.c +@@ -2535,7 +2535,7 @@ static int kdb_summary(int argc, const char **argv) + #define K(x) ((x) << (PAGE_SHIFT - 10)) + kdb_printf("\nMemTotal: %8lu kB\nMemFree: %8lu kB\n" + "Buffers: %8lu kB\n", +- val.totalram, val.freeram, val.bufferram); ++ K(val.totalram), K(val.freeram), K(val.bufferram)); + return 0; + } + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index f774e93..3bf20e3 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + + #include "internal.h" + +@@ -1516,6 +1517,11 @@ retry: + */ + if (ctx->is_active) { + raw_spin_unlock_irq(&ctx->lock); ++ /* ++ * Reload the task pointer, it might have been changed by ++ * a concurrent perf_event_context_sched_out(). ++ */ ++ task = ctx->task; + goto retry; + } + +@@ -1957,6 +1963,11 @@ retry: + */ + if (ctx->is_active) { + raw_spin_unlock_irq(&ctx->lock); ++ /* ++ * Reload the task pointer, it might have been changed by ++ * a concurrent perf_event_context_sched_out(). ++ */ ++ task = ctx->task; + goto retry; + } + +@@ -3551,28 +3562,21 @@ static void perf_event_for_each(struct perf_event *event, + mutex_unlock(&ctx->mutex); + } + +-static int perf_event_period(struct perf_event *event, u64 __user *arg) +-{ +- struct perf_event_context *ctx = event->ctx; +- int ret = 0, active; ++struct period_event { ++ struct perf_event *event; + u64 value; ++}; + +- if (!is_sampling_event(event)) +- return -EINVAL; +- +- if (copy_from_user(&value, arg, sizeof(value))) +- return -EFAULT; +- +- if (!value) +- return -EINVAL; ++static int __perf_event_period(void *info) ++{ ++ struct period_event *pe = info; ++ struct perf_event *event = pe->event; ++ struct perf_event_context *ctx = event->ctx; ++ u64 value = pe->value; ++ bool active; + +- raw_spin_lock_irq(&ctx->lock); ++ raw_spin_lock(&ctx->lock); + if (event->attr.freq) { +- if (value > sysctl_perf_event_sample_rate) { +- ret = -EINVAL; +- goto unlock; +- } +- + event->attr.sample_freq = value; + } else { + event->attr.sample_period = value; +@@ -3591,11 +3595,53 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg) + event->pmu->start(event, PERF_EF_RELOAD); + perf_pmu_enable(ctx->pmu); + } ++ raw_spin_unlock(&ctx->lock); + +-unlock: ++ return 0; ++} ++ ++static int perf_event_period(struct perf_event *event, u64 __user *arg) ++{ ++ struct period_event pe = { .event = event, }; ++ struct perf_event_context *ctx = event->ctx; ++ struct task_struct *task; ++ u64 value; ++ ++ if (!is_sampling_event(event)) ++ return -EINVAL; ++ ++ if (copy_from_user(&value, arg, sizeof(value))) ++ return -EFAULT; ++ ++ if (!value) ++ return -EINVAL; ++ ++ if (event->attr.freq && value > sysctl_perf_event_sample_rate) ++ return -EINVAL; ++ ++ task = ctx->task; ++ pe.value = value; ++ ++ if (!task) { ++ cpu_function_call(event->cpu, __perf_event_period, &pe); ++ return 0; ++ } ++ ++retry: ++ if (!task_function_call(task, __perf_event_period, &pe)) ++ return 0; ++ ++ raw_spin_lock_irq(&ctx->lock); ++ if (ctx->is_active) { ++ raw_spin_unlock_irq(&ctx->lock); ++ task = ctx->task; ++ goto retry; ++ } ++ ++ __perf_event_period(&pe); + raw_spin_unlock_irq(&ctx->lock); + +- return ret; ++ return 0; + } + + static const struct file_operations perf_fops; +@@ -3683,6 +3729,26 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + return 0; + } + ++#ifdef CONFIG_COMPAT ++static long perf_compat_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ switch (_IOC_NR(cmd)) { ++ case _IOC_NR(PERF_EVENT_IOC_SET_FILTER): ++ case _IOC_NR(PERF_EVENT_IOC_ID): ++ /* Fix up pointer size (usually 4 -> 8 in 32-on-64-bit case */ ++ if (_IOC_SIZE(cmd) == sizeof(compat_uptr_t)) { ++ cmd &= ~IOCSIZE_MASK; ++ cmd |= sizeof(void *) << IOCSIZE_SHIFT; ++ } ++ break; ++ } ++ return perf_ioctl(file, cmd, arg); ++} ++#else ++# define perf_compat_ioctl NULL ++#endif ++ + int perf_event_task_enable(void) + { + struct perf_event *event; +@@ -4175,7 +4241,7 @@ static const struct file_operations perf_fops = { + .read = perf_read, + .poll = perf_poll, + .unlocked_ioctl = perf_ioctl, +- .compat_ioctl = perf_ioctl, ++ .compat_ioctl = perf_compat_ioctl, + .mmap = perf_mmap, + .fasync = perf_fasync, + }; +@@ -4187,12 +4253,20 @@ static const struct file_operations perf_fops = { + * to user-space before waking everybody up. + */ + ++static inline struct fasync_struct **perf_event_fasync(struct perf_event *event) ++{ ++ /* only the parent has fasync state */ ++ if (event->parent) ++ event = event->parent; ++ return &event->fasync; ++} ++ + void perf_event_wakeup(struct perf_event *event) + { + ring_buffer_wakeup(event); + + if (event->pending_kill) { +- kill_fasync(&event->fasync, SIGIO, event->pending_kill); ++ kill_fasync(perf_event_fasync(event), SIGIO, event->pending_kill); + event->pending_kill = 0; + } + } +@@ -4201,6 +4275,13 @@ static void perf_pending_event(struct irq_work *entry) + { + struct perf_event *event = container_of(entry, + struct perf_event, pending); ++ int rctx; ++ ++ rctx = perf_swevent_get_recursion_context(); ++ /* ++ * If we 'fail' here, that's OK, it means recursion is already disabled ++ * and we won't recurse 'further'. ++ */ + + if (event->pending_disable) { + event->pending_disable = 0; +@@ -4211,6 +4292,9 @@ static void perf_pending_event(struct irq_work *entry) + event->pending_wakeup = 0; + perf_event_wakeup(event); + } ++ ++ if (rctx >= 0) ++ perf_swevent_put_recursion_context(rctx); + } + + /* +@@ -5391,7 +5475,7 @@ static int __perf_event_overflow(struct perf_event *event, + else + perf_event_output(event, data, regs); + +- if (event->fasync && event->pending_kill) { ++ if (*perf_event_fasync(event) && event->pending_kill) { + event->pending_wakeup = 1; + irq_work_queue(&event->pending); + } +@@ -7209,11 +7293,11 @@ SYSCALL_DEFINE5(perf_event_open, + + if (move_group) { + synchronize_rcu(); +- perf_install_in_context(ctx, group_leader, event->cpu); ++ perf_install_in_context(ctx, group_leader, group_leader->cpu); + get_ctx(ctx); + list_for_each_entry(sibling, &group_leader->sibling_list, + group_entry) { +- perf_install_in_context(ctx, sibling, event->cpu); ++ perf_install_in_context(ctx, sibling, sibling->cpu); + get_ctx(ctx); + } + } +@@ -7826,8 +7910,10 @@ int perf_event_init_task(struct task_struct *child) + + for_each_task_context_nr(ctxn) { + ret = perf_event_init_context(child, ctxn); +- if (ret) ++ if (ret) { ++ perf_event_free_task(child); + return ret; ++ } + } + + return 0; +diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c +index 307d87c..1139b22 100644 +--- a/kernel/events/uprobes.c ++++ b/kernel/events/uprobes.c +@@ -1621,7 +1621,6 @@ bool uprobe_deny_signal(void) + if (__fatal_signal_pending(t) || arch_uprobe_xol_was_trapped(t)) { + utask->state = UTASK_SSTEP_TRAPPED; + set_tsk_thread_flag(t, TIF_UPROBE); +- set_tsk_thread_flag(t, TIF_NOTIFY_RESUME); + } + } + +diff --git a/kernel/fork.c b/kernel/fork.c +index c44bff8..e2c6853 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -28,6 +28,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -363,7 +365,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) + + mm->locked_vm = 0; + mm->mmap = NULL; +- mm->mmap_cache = NULL; ++ mm->vmacache_seqnum = 0; + mm->map_count = 0; + cpumask_clear(mm_cpumask(mm)); + mm->mm_rb = RB_ROOT; +@@ -876,6 +878,9 @@ static int copy_mm(unsigned long clone_flags, struct task_struct *tsk) + if (!oldmm) + return 0; + ++ /* initialize the new vmacache entries */ ++ vmacache_flush(tsk); ++ + if (clone_flags & CLONE_VM) { + atomic_inc(&oldmm->mm_users); + mm = oldmm; +@@ -1323,7 +1328,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, + goto bad_fork_cleanup_policy; + retval = audit_alloc(p); + if (retval) +- goto bad_fork_cleanup_policy; ++ goto bad_fork_cleanup_perf; + /* copy all the process information */ + retval = copy_semundo(clone_flags, p); + if (retval) +@@ -1522,8 +1527,9 @@ bad_fork_cleanup_semundo: + exit_sem(p); + bad_fork_cleanup_audit: + audit_free(p); +-bad_fork_cleanup_policy: ++bad_fork_cleanup_perf: + perf_event_free_task(p); ++bad_fork_cleanup_policy: + #ifdef CONFIG_NUMA + mpol_put(p->mempolicy); + bad_fork_cleanup_cgroup: +diff --git a/kernel/freezer.c b/kernel/freezer.c +index aa6a8aa..8f9279b 100644 +--- a/kernel/freezer.c ++++ b/kernel/freezer.c +@@ -42,6 +42,9 @@ bool freezing_slow_path(struct task_struct *p) + if (p->flags & (PF_NOFREEZE | PF_SUSPEND_TASK)) + return false; + ++ if (test_thread_flag(TIF_MEMDIE)) ++ return false; ++ + if (pm_nosig_freezing || cgroup_freezing(p)) + return true; + +diff --git a/kernel/futex.c b/kernel/futex.c +index e3087af..fda2950 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -329,6 +329,8 @@ static void get_futex_key_refs(union futex_key *key) + case FUT_OFF_MMSHARED: + futex_get_mm(key); /* implies MB (B) */ + break; ++ default: ++ smp_mb(); /* explicit MB (B) */ + } + } + +@@ -2614,6 +2616,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, + * shared futexes. We need to compare the keys: + */ + if (match_futex(&q.key, &key2)) { ++ queue_unlock(hb); + ret = -EINVAL; + goto out_put_keys; + } +diff --git a/kernel/groups.c b/kernel/groups.c +index 90cf1c3..67b4ba3 100644 +--- a/kernel/groups.c ++++ b/kernel/groups.c +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + #include + + /* init to 2 - one for init_task, one to ensure it is never freed */ +@@ -223,6 +224,14 @@ out: + return i; + } + ++bool may_setgroups(void) ++{ ++ struct user_namespace *user_ns = current_user_ns(); ++ ++ return ns_capable(user_ns, CAP_SETGID) && ++ userns_may_setgroups(user_ns); ++} ++ + /* + * SMP: Our groups are copy-on-write. We can set them safely + * without another task interfering. +@@ -233,7 +242,7 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist) + struct group_info *group_info; + int retval; + +- if (!ns_capable(current_user_ns(), CAP_SETGID)) ++ if (!may_setgroups()) + return -EPERM; + if ((unsigned)gidsetsize > NGROUPS_MAX) + return -EINVAL; +diff --git a/kernel/irq/devres.c b/kernel/irq/devres.c +index 1ef0606..0296d6f 100644 +--- a/kernel/irq/devres.c ++++ b/kernel/irq/devres.c +@@ -104,7 +104,7 @@ int devm_request_any_context_irq(struct device *dev, unsigned int irq, + return -ENOMEM; + + rc = request_any_context_irq(irq, handler, irqflags, devname, dev_id); +- if (rc) { ++ if (rc < 0) { + devres_free(dr); + return rc; + } +@@ -113,7 +113,7 @@ int devm_request_any_context_irq(struct device *dev, unsigned int irq, + dr->dev_id = dev_id; + devres_add(dev, dr); + +- return 0; ++ return rc; + } + EXPORT_SYMBOL(devm_request_any_context_irq); + +diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h +index 001fa5b..8a160e8 100644 +--- a/kernel/irq/internals.h ++++ b/kernel/irq/internals.h +@@ -74,6 +74,14 @@ extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu); + extern void mask_irq(struct irq_desc *desc); + extern void unmask_irq(struct irq_desc *desc); + ++#ifdef CONFIG_SPARSE_IRQ ++extern void irq_lock_sparse(void); ++extern void irq_unlock_sparse(void); ++#else ++static inline void irq_lock_sparse(void) { } ++static inline void irq_unlock_sparse(void) { } ++#endif ++ + extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr); + + irqreturn_t handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action); +diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c +index 8ab8e93..07d4551 100644 +--- a/kernel/irq/irqdesc.c ++++ b/kernel/irq/irqdesc.c +@@ -131,6 +131,16 @@ static void free_masks(struct irq_desc *desc) + static inline void free_masks(struct irq_desc *desc) { } + #endif + ++void irq_lock_sparse(void) ++{ ++ mutex_lock(&sparse_irq_lock); ++} ++ ++void irq_unlock_sparse(void) ++{ ++ mutex_unlock(&sparse_irq_lock); ++} ++ + static struct irq_desc *alloc_desc(int irq, int node, struct module *owner) + { + struct irq_desc *desc; +@@ -167,6 +177,12 @@ static void free_desc(unsigned int irq) + + unregister_irq_proc(irq, desc); + ++ /* ++ * sparse_irq_lock protects also show_interrupts() and ++ * kstat_irq_usr(). Once we deleted the descriptor from the ++ * sparse tree we can free it. Access in proc will fail to ++ * lookup the descriptor. ++ */ + mutex_lock(&sparse_irq_lock); + delete_irq_desc(irq); + mutex_unlock(&sparse_irq_lock); +@@ -489,6 +505,15 @@ void dynamic_irq_cleanup(unsigned int irq) + raw_spin_unlock_irqrestore(&desc->lock, flags); + } + ++/** ++ * kstat_irqs_cpu - Get the statistics for an interrupt on a cpu ++ * @irq: The interrupt number ++ * @cpu: The cpu number ++ * ++ * Returns the sum of interrupt counts on @cpu since boot for ++ * @irq. The caller must ensure that the interrupt is not removed ++ * concurrently. ++ */ + unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) + { + struct irq_desc *desc = irq_to_desc(irq); +@@ -497,6 +522,14 @@ unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) + *per_cpu_ptr(desc->kstat_irqs, cpu) : 0; + } + ++/** ++ * kstat_irqs - Get the statistics for an interrupt ++ * @irq: The interrupt number ++ * ++ * Returns the sum of interrupt counts on all cpus since boot for ++ * @irq. The caller must ensure that the interrupt is not removed ++ * concurrently. ++ */ + unsigned int kstat_irqs(unsigned int irq) + { + struct irq_desc *desc = irq_to_desc(irq); +@@ -509,3 +542,22 @@ unsigned int kstat_irqs(unsigned int irq) + sum += *per_cpu_ptr(desc->kstat_irqs, cpu); + return sum; + } ++ ++/** ++ * kstat_irqs_usr - Get the statistics for an interrupt ++ * @irq: The interrupt number ++ * ++ * Returns the sum of interrupt counts on all cpus since boot for ++ * @irq. Contrary to kstat_irqs() this can be called from any ++ * preemptible context. It's protected against concurrent removal of ++ * an interrupt descriptor when sparse irqs are enabled. ++ */ ++unsigned int kstat_irqs_usr(unsigned int irq) ++{ ++ int sum; ++ ++ irq_lock_sparse(); ++ sum = kstat_irqs(irq); ++ irq_unlock_sparse(); ++ return sum; ++} +diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c +index 36f6ee1..095cd72 100644 +--- a/kernel/irq/proc.c ++++ b/kernel/irq/proc.c +@@ -15,6 +15,23 @@ + + #include "internals.h" + ++/* ++ * Access rules: ++ * ++ * procfs protects read/write of /proc/irq/N/ files against a ++ * concurrent free of the interrupt descriptor. remove_proc_entry() ++ * immediately prevents new read/writes to happen and waits for ++ * already running read/write functions to complete. ++ * ++ * We remove the proc entries first and then delete the interrupt ++ * descriptor from the radix tree and free it. So it is guaranteed ++ * that irq_to_desc(N) is valid as long as the read/writes are ++ * permitted by procfs. ++ * ++ * The read from /proc/interrupts is a different problem because there ++ * is no protection. So the lookup and the access to irqdesc ++ * information must be protected by sparse_irq_lock. ++ */ + static struct proc_dir_entry *root_irq_dir; + + #ifdef CONFIG_SMP +@@ -437,9 +454,10 @@ int show_interrupts(struct seq_file *p, void *v) + seq_putc(p, '\n'); + } + ++ irq_lock_sparse(); + desc = irq_to_desc(i); + if (!desc) +- return 0; ++ goto outsparse; + + raw_spin_lock_irqsave(&desc->lock, flags); + for_each_online_cpu(j) +@@ -479,6 +497,8 @@ int show_interrupts(struct seq_file *p, void *v) + seq_putc(p, '\n'); + out: + raw_spin_unlock_irqrestore(&desc->lock, flags); ++outsparse: ++ irq_unlock_sparse(); + return 0; + } + #endif +diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c +index 9065107..7a5237a 100644 +--- a/kernel/irq/resend.c ++++ b/kernel/irq/resend.c +@@ -75,13 +75,21 @@ void check_irq_resend(struct irq_desc *desc, unsigned int irq) + !desc->irq_data.chip->irq_retrigger(&desc->irq_data)) { + #ifdef CONFIG_HARDIRQS_SW_RESEND + /* +- * If the interrupt has a parent irq and runs +- * in the thread context of the parent irq, +- * retrigger the parent. ++ * If the interrupt is running in the thread ++ * context of the parent irq we need to be ++ * careful, because we cannot trigger it ++ * directly. + */ +- if (desc->parent_irq && +- irq_settings_is_nested_thread(desc)) ++ if (irq_settings_is_nested_thread(desc)) { ++ /* ++ * If the parent_irq is valid, we ++ * retrigger the parent, otherwise we ++ * do nothing. ++ */ ++ if (!desc->parent_irq) ++ return; + irq = desc->parent_irq; ++ } + /* Set it pending and activate the softirq: */ + set_bit(irq, irqs_resend); + tasklet_schedule(&resend_tasklet); +diff --git a/kernel/kcmp.c b/kernel/kcmp.c +index e30ac0f..0aa69ea 100644 +--- a/kernel/kcmp.c ++++ b/kernel/kcmp.c +@@ -44,11 +44,12 @@ static long kptr_obfuscate(long v, int type) + */ + static int kcmp_ptr(void *v1, void *v2, enum kcmp_type type) + { +- long ret; ++ long t1, t2; + +- ret = kptr_obfuscate((long)v1, type) - kptr_obfuscate((long)v2, type); ++ t1 = kptr_obfuscate((long)v1, type); ++ t2 = kptr_obfuscate((long)v2, type); + +- return (ret < 0) | ((ret > 0) << 1); ++ return (t1 < t2) | ((t1 > t2) << 1); + } + + /* The caller must have pinned the task */ +diff --git a/kernel/module.c b/kernel/module.c +index 6716a1f..1d679a6 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -1841,7 +1841,9 @@ static void free_module(struct module *mod) + + /* We leave it in list to prevent duplicate loads, but make sure + * that noone uses it while it's being deconstructed. */ ++ mutex_lock(&module_mutex); + mod->state = MODULE_STATE_UNFORMED; ++ mutex_unlock(&module_mutex); + + /* Remove dynamic debug info */ + ddebug_remove_module(mod->name); +diff --git a/kernel/pid.c b/kernel/pid.c +index 9b9a266..82430c8 100644 +--- a/kernel/pid.c ++++ b/kernel/pid.c +@@ -341,6 +341,8 @@ out: + + out_unlock: + spin_unlock_irq(&pidmap_lock); ++ put_pid_ns(ns); ++ + out_free: + while (++i <= ns->level) + free_pidmap(pid->numbers + i); +diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c +index 424c2d4..77e6b83 100644 +--- a/kernel/posix-timers.c ++++ b/kernel/posix-timers.c +@@ -634,6 +634,7 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock, + goto out; + } + } else { ++ memset(&event.sigev_value, 0, sizeof(event.sigev_value)); + event.sigev_notify = SIGEV_SIGNAL; + event.sigev_signo = SIGALRM; + event.sigev_value.sival_int = new_timer->it_id; +diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig +index 2fac9cc..9d18628 100644 +--- a/kernel/power/Kconfig ++++ b/kernel/power/Kconfig +@@ -191,7 +191,7 @@ config DPM_WATCHDOG + config DPM_WATCHDOG_TIMEOUT + int "Watchdog timeout in seconds" + range 1 120 +- default 12 ++ default 60 + depends on DPM_WATCHDOG + + config PM_TRACE +diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c +index 37170d4..126586a 100644 +--- a/kernel/power/hibernate.c ++++ b/kernel/power/hibernate.c +@@ -492,8 +492,14 @@ int hibernation_restore(int platform_mode) + error = dpm_suspend_start(PMSG_QUIESCE); + if (!error) { + error = resume_target_kernel(platform_mode); +- dpm_resume_end(PMSG_RECOVER); ++ /* ++ * The above should either succeed and jump to the new kernel, ++ * or return with an error. Otherwise things are just ++ * undefined, so let's be paranoid. ++ */ ++ BUG_ON(!error); + } ++ dpm_resume_end(PMSG_RECOVER); + pm_restore_gfp_mask(); + ftrace_start(); + resume_console(); +diff --git a/kernel/power/main.c b/kernel/power/main.c +index 1d1bf63..3ae41cd 100644 +--- a/kernel/power/main.c ++++ b/kernel/power/main.c +@@ -293,12 +293,12 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, + { + char *s = buf; + #ifdef CONFIG_SUSPEND +- int i; ++ suspend_state_t i; ++ ++ for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++) ++ if (pm_states[i].state) ++ s += sprintf(s,"%s ", pm_states[i].label); + +- for (i = 0; i < PM_SUSPEND_MAX; i++) { +- if (pm_states[i] && valid_state(i)) +- s += sprintf(s,"%s ", pm_states[i]); +- } + #endif + #ifdef CONFIG_HIBERNATION + s += sprintf(s, "%s\n", "disk"); +@@ -314,7 +314,7 @@ static suspend_state_t decode_state(const char *buf, size_t n) + { + #ifdef CONFIG_SUSPEND + suspend_state_t state = PM_SUSPEND_MIN; +- const char * const *s; ++ struct pm_sleep_state *s; + #endif + char *p; + int len; +@@ -328,8 +328,9 @@ static suspend_state_t decode_state(const char *buf, size_t n) + + #ifdef CONFIG_SUSPEND + for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) +- if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) +- return state; ++ if (s->state && len == strlen(s->label) ++ && !strncmp(buf, s->label, len)) ++ return s->state; + #endif + + return PM_SUSPEND_ON; +@@ -447,8 +448,8 @@ static ssize_t autosleep_show(struct kobject *kobj, + + #ifdef CONFIG_SUSPEND + if (state < PM_SUSPEND_MAX) +- return sprintf(buf, "%s\n", valid_state(state) ? +- pm_states[state] : "error"); ++ return sprintf(buf, "%s\n", pm_states[state].state ? ++ pm_states[state].label : "error"); + #endif + #ifdef CONFIG_HIBERNATION + return sprintf(buf, "disk\n"); +diff --git a/kernel/power/power.h b/kernel/power/power.h +index 7d4b7ff..f770cad3 100644 +--- a/kernel/power/power.h ++++ b/kernel/power/power.h +@@ -175,17 +175,20 @@ extern void swsusp_show_speed(struct timeval *, struct timeval *, + unsigned int, char *); + + #ifdef CONFIG_SUSPEND ++struct pm_sleep_state { ++ const char *label; ++ suspend_state_t state; ++}; ++ + /* kernel/power/suspend.c */ +-extern const char *const pm_states[]; ++extern struct pm_sleep_state pm_states[]; + +-extern bool valid_state(suspend_state_t state); + extern int suspend_devices_and_enter(suspend_state_t state); + #else /* !CONFIG_SUSPEND */ + static inline int suspend_devices_and_enter(suspend_state_t state) + { + return -ENOSYS; + } +-static inline bool valid_state(suspend_state_t state) { return false; } + #endif /* !CONFIG_SUSPEND */ + + #ifdef CONFIG_PM_TEST_SUSPEND +diff --git a/kernel/power/process.c b/kernel/power/process.c +index 14f9a8d..f1fe7ec 100644 +--- a/kernel/power/process.c ++++ b/kernel/power/process.c +@@ -107,6 +107,28 @@ static int try_to_freeze_tasks(bool user_only) + return todo ? -EBUSY : 0; + } + ++/* ++ * Returns true if all freezable tasks (except for current) are frozen already ++ */ ++static bool check_frozen_processes(void) ++{ ++ struct task_struct *g, *p; ++ bool ret = true; ++ ++ read_lock(&tasklist_lock); ++ for_each_process_thread(g, p) { ++ if (p != current && !freezer_should_skip(p) && ++ !frozen(p)) { ++ ret = false; ++ goto done; ++ } ++ } ++done: ++ read_unlock(&tasklist_lock); ++ ++ return ret; ++} ++ + /** + * freeze_processes - Signal user space processes to enter the refrigerator. + * The current thread will not be frozen. The same process that calls +@@ -117,6 +139,7 @@ static int try_to_freeze_tasks(bool user_only) + int freeze_processes(void) + { + int error; ++ int oom_kills_saved; + + error = __usermodehelper_disable(UMH_FREEZING); + if (error) +@@ -130,12 +153,27 @@ int freeze_processes(void) + + printk("Freezing user space processes ... "); + pm_freezing = true; ++ oom_kills_saved = oom_kills_count(); + error = try_to_freeze_tasks(true); + if (!error) { +- printk("done."); + __usermodehelper_set_disable_depth(UMH_DISABLED); + oom_killer_disable(); ++ ++ /* ++ * There might have been an OOM kill while we were ++ * freezing tasks and the killed task might be still ++ * on the way out so we have to double check for race. ++ */ ++ if (oom_kills_count() != oom_kills_saved && ++ !check_frozen_processes()) { ++ __usermodehelper_set_disable_depth(UMH_ENABLED); ++ printk("OOM in progress."); ++ error = -EBUSY; ++ goto done; ++ } ++ printk("done."); + } ++done: + printk("\n"); + BUG_ON(in_atomic()); + +diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c +index 62ee437..5455d5c 100644 +--- a/kernel/power/suspend.c ++++ b/kernel/power/suspend.c +@@ -29,10 +29,10 @@ + + #include "power.h" + +-const char *const pm_states[PM_SUSPEND_MAX] = { +- [PM_SUSPEND_FREEZE] = "freeze", +- [PM_SUSPEND_STANDBY] = "standby", +- [PM_SUSPEND_MEM] = "mem", ++struct pm_sleep_state pm_states[PM_SUSPEND_MAX] = { ++ [PM_SUSPEND_FREEZE] = { .label = "freeze", .state = PM_SUSPEND_FREEZE }, ++ [PM_SUSPEND_STANDBY] = { .label = "standby", }, ++ [PM_SUSPEND_MEM] = { .label = "mem", }, + }; + + static const struct platform_suspend_ops *suspend_ops; +@@ -62,42 +62,34 @@ void freeze_wake(void) + } + EXPORT_SYMBOL_GPL(freeze_wake); + ++static bool valid_state(suspend_state_t state) ++{ ++ /* ++ * PM_SUSPEND_STANDBY and PM_SUSPEND_MEM states need low level ++ * support and need to be valid to the low level ++ * implementation, no valid callback implies that none are valid. ++ */ ++ return suspend_ops && suspend_ops->valid && suspend_ops->valid(state); ++} ++ + /** + * suspend_set_ops - Set the global suspend method table. + * @ops: Suspend operations to use. + */ + void suspend_set_ops(const struct platform_suspend_ops *ops) + { ++ suspend_state_t i; ++ + lock_system_sleep(); ++ + suspend_ops = ops; ++ for (i = PM_SUSPEND_STANDBY; i <= PM_SUSPEND_MEM; i++) ++ pm_states[i].state = valid_state(i) ? i : 0; ++ + unlock_system_sleep(); + } + EXPORT_SYMBOL_GPL(suspend_set_ops); + +-bool valid_state(suspend_state_t state) +-{ +- if (state == PM_SUSPEND_FREEZE) { +-#ifdef CONFIG_PM_DEBUG +- if (pm_test_level != TEST_NONE && +- pm_test_level != TEST_FREEZER && +- pm_test_level != TEST_DEVICES && +- pm_test_level != TEST_PLATFORM) { +- printk(KERN_WARNING "Unsupported pm_test mode for " +- "freeze state, please choose " +- "none/freezer/devices/platform.\n"); +- return false; +- } +-#endif +- return true; +- } +- /* +- * PM_SUSPEND_STANDBY and PM_SUSPEND_MEMORY states need lowlevel +- * support and need to be valid to the lowlevel +- * implementation, no valid callback implies that none are valid. +- */ +- return suspend_ops && suspend_ops->valid && suspend_ops->valid(state); +-} +- + /** + * suspend_valid_only_mem - Generic memory-only valid callback. + * +@@ -324,9 +316,17 @@ static int enter_state(suspend_state_t state) + { + int error; + +- if (!valid_state(state)) +- return -ENODEV; +- ++ if (state == PM_SUSPEND_FREEZE) { ++#ifdef CONFIG_PM_DEBUG ++ if (pm_test_level != TEST_NONE && pm_test_level <= TEST_CPUS) { ++ pr_warning("PM: Unsupported test mode for freeze state," ++ "please choose none/freezer/devices/platform.\n"); ++ return -EAGAIN; ++ } ++#endif ++ } else if (!valid_state(state)) { ++ return -EINVAL; ++ } + if (!mutex_trylock(&pm_mutex)) + return -EBUSY; + +@@ -337,7 +337,7 @@ static int enter_state(suspend_state_t state) + sys_sync(); + printk("done.\n"); + +- pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); ++ pr_debug("PM: Preparing system for %s sleep\n", pm_states[state].label); + error = suspend_prepare(state); + if (error) + goto Unlock; +@@ -345,7 +345,7 @@ static int enter_state(suspend_state_t state) + if (suspend_test(TEST_FREEZER)) + goto Finish; + +- pr_debug("PM: Entering %s sleep\n", pm_states[state]); ++ pr_debug("PM: Entering %s sleep\n", pm_states[state].label); + pm_restrict_gfp_mask(); + error = suspend_devices_and_enter(state); + pm_restore_gfp_mask(); +diff --git a/kernel/power/suspend_test.c b/kernel/power/suspend_test.c +index 9b2a1d5..269b097 100644 +--- a/kernel/power/suspend_test.c ++++ b/kernel/power/suspend_test.c +@@ -92,13 +92,13 @@ static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state) + } + + if (state == PM_SUSPEND_MEM) { +- printk(info_test, pm_states[state]); ++ printk(info_test, pm_states[state].label); + status = pm_suspend(state); + if (status == -ENODEV) + state = PM_SUSPEND_STANDBY; + } + if (state == PM_SUSPEND_STANDBY) { +- printk(info_test, pm_states[state]); ++ printk(info_test, pm_states[state].label); + status = pm_suspend(state); + } + if (status < 0) +@@ -136,18 +136,16 @@ static char warn_bad_state[] __initdata = + + static int __init setup_test_suspend(char *value) + { +- unsigned i; ++ suspend_state_t i; + + /* "=mem" ==> "mem" */ + value++; +- for (i = 0; i < PM_SUSPEND_MAX; i++) { +- if (!pm_states[i]) +- continue; +- if (strcmp(pm_states[i], value) != 0) +- continue; +- test_state = (__force suspend_state_t) i; +- return 0; +- } ++ for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++) ++ if (!strcmp(pm_states[i].label, value)) { ++ test_state = pm_states[i].state; ++ return 0; ++ } ++ + printk(warn_bad_state, value); + return 0; + } +@@ -164,8 +162,8 @@ static int __init test_suspend(void) + /* PM is initialized by now; is that state testable? */ + if (test_state == PM_SUSPEND_ON) + goto done; +- if (!valid_state(test_state)) { +- printk(warn_bad_state, pm_states[test_state]); ++ if (!pm_states[test_state].state) { ++ printk(warn_bad_state, pm_states[test_state].label); + goto done; + } + +diff --git a/kernel/printk/console_cmdline.h b/kernel/printk/console_cmdline.h +index cbd69d8..2ca4a8b 100644 +--- a/kernel/printk/console_cmdline.h ++++ b/kernel/printk/console_cmdline.h +@@ -3,7 +3,7 @@ + + struct console_cmdline + { +- char name[8]; /* Name of the driver */ ++ char name[16]; /* Name of the driver */ + int index; /* Minor dev. to use */ + char *options; /* Options for the driver */ + #ifdef CONFIG_A11Y_BRAILLE_CONSOLE +diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c +index 4dae9cb..02e7fb4 100644 +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -383,11 +383,11 @@ static int check_syslog_permissions(int type, bool from_file) + * already done the capabilities checks at open time. + */ + if (from_file && type != SYSLOG_ACTION_OPEN) +- return 0; ++ goto ok; + + if (syslog_action_restricted(type)) { + if (capable(CAP_SYSLOG)) +- return 0; ++ goto ok; + /* + * For historical reasons, accept CAP_SYS_ADMIN too, with + * a warning. +@@ -397,10 +397,11 @@ static int check_syslog_permissions(int type, bool from_file) + "CAP_SYS_ADMIN but no CAP_SYSLOG " + "(deprecated).\n", + current->comm, task_pid_nr(current)); +- return 0; ++ goto ok; + } + return -EPERM; + } ++ok: + return security_syslog(type); + } + +@@ -1126,10 +1127,6 @@ int do_syslog(int type, char __user *buf, int len, bool from_file) + if (error) + goto out; + +- error = security_syslog(type); +- if (error) +- return error; +- + switch (type) { + case SYSLOG_ACTION_CLOSE: /* Close log */ + break; +@@ -2280,6 +2277,7 @@ void register_console(struct console *newcon) + for (i = 0, c = console_cmdline; + i < MAX_CMDLINECONSOLES && c->name[0]; + i++, c++) { ++ BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name)); + if (strcmp(c->name, newcon->name) != 0) + continue; + if (newcon->index >= 0 && +@@ -2468,7 +2466,7 @@ void wake_up_klogd(void) + preempt_enable(); + } + +-int printk_sched(const char *fmt, ...) ++int printk_deferred(const char *fmt, ...) + { + unsigned long flags; + va_list args; +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index 1f4bcb3..be9760f 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -720,6 +720,8 @@ static int ptrace_peek_siginfo(struct task_struct *child, + static int ptrace_resume(struct task_struct *child, long request, + unsigned long data) + { ++ bool need_siglock; ++ + if (!valid_signal(data)) + return -EIO; + +@@ -747,8 +749,26 @@ static int ptrace_resume(struct task_struct *child, long request, + user_disable_single_step(child); + } + ++ /* ++ * Change ->exit_code and ->state under siglock to avoid the race ++ * with wait_task_stopped() in between; a non-zero ->exit_code will ++ * wrongly look like another report from tracee. ++ * ++ * Note that we need siglock even if ->exit_code == data and/or this ++ * status was not reported yet, the new status must not be cleared by ++ * wait_task_stopped() after resume. ++ * ++ * If data == 0 we do not care if wait_task_stopped() reports the old ++ * status and clears the code too; this can't race with the tracee, it ++ * takes siglock after resume. ++ */ ++ need_siglock = data && !thread_group_empty(current); ++ if (need_siglock) ++ spin_lock_irq(&child->sighand->siglock); + child->exit_code = data; + wake_up_state(child, __TASK_TRACED); ++ if (need_siglock) ++ spin_unlock_irq(&child->sighand->siglock); + + return 0; + } +diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c +index 1254f31..ae359f0 100644 +--- a/kernel/rcu/tiny.c ++++ b/kernel/rcu/tiny.c +@@ -284,6 +284,11 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp) + + /* Move the ready-to-invoke callbacks to a local list. */ + local_irq_save(flags); ++ if (rcp->donetail == &rcp->rcucblist) { ++ /* No callbacks ready, so just leave. */ ++ local_irq_restore(flags); ++ return; ++ } + RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, rcp->qlen, -1)); + list = rcp->rcucblist; + rcp->rcucblist = *rcp->donetail; +diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c +index b3d116c..6705d94 100644 +--- a/kernel/rcu/tree.c ++++ b/kernel/rcu/tree.c +@@ -1228,6 +1228,22 @@ static int rcu_future_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp) + } + + /* ++ * Awaken the grace-period kthread for the specified flavor of RCU. ++ * Don't do a self-awaken, and don't bother awakening when there is ++ * nothing for the grace-period kthread to do (as in several CPUs ++ * raced to awaken, and we lost), and finally don't try to awaken ++ * a kthread that has not yet been created. ++ */ ++static void rcu_gp_kthread_wake(struct rcu_state *rsp) ++{ ++ if (current == rsp->gp_kthread || ++ !ACCESS_ONCE(rsp->gp_flags) || ++ !rsp->gp_kthread) ++ return; ++ wake_up(&rsp->gp_wq); ++} ++ ++/* + * If there is room, assign a ->completed number to any callbacks on + * this CPU that have not already been assigned. Also accelerate any + * callbacks that were previously assigned a ->completed number that has +@@ -1670,7 +1686,7 @@ static void rsp_wakeup(struct irq_work *work) + struct rcu_state *rsp = container_of(work, struct rcu_state, wakeup_work); + + /* Wake up rcu_gp_kthread() to start the grace period. */ +- wake_up(&rsp->gp_wq); ++ rcu_gp_kthread_wake(rsp); + } + + /* +@@ -1746,7 +1762,7 @@ static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags) + { + WARN_ON_ONCE(!rcu_gp_in_progress(rsp)); + raw_spin_unlock_irqrestore(&rcu_get_root(rsp)->lock, flags); +- wake_up(&rsp->gp_wq); /* Memory barrier implied by wake_up() path. */ ++ rcu_gp_kthread_wake(rsp); + } + + /* +@@ -2322,7 +2338,7 @@ static void force_quiescent_state(struct rcu_state *rsp) + } + rsp->gp_flags |= RCU_GP_FLAG_FQS; + raw_spin_unlock_irqrestore(&rnp_old->lock, flags); +- wake_up(&rsp->gp_wq); /* Memory barrier implied by wake_up() path. */ ++ rcu_gp_kthread_wake(rsp); + } + + /* +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 0aae0fc..5e973ef 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -1322,7 +1322,7 @@ out: + * leave kernel. + */ + if (p->mm && printk_ratelimit()) { +- printk_sched("process %d (%s) no longer affine to cpu%d\n", ++ printk_deferred("process %d (%s) no longer affine to cpu%d\n", + task_pid_nr(p), p->comm, cpu); + } + } +@@ -1895,6 +1895,8 @@ unsigned long to_ratio(u64 period, u64 runtime) + #ifdef CONFIG_SMP + inline struct dl_bw *dl_bw_of(int i) + { ++ rcu_lockdep_assert(rcu_read_lock_sched_held(), ++ "sched RCU must be held"); + return &cpu_rq(i)->rd->dl_bw; + } + +@@ -1903,6 +1905,8 @@ static inline int dl_bw_cpus(int i) + struct root_domain *rd = cpu_rq(i)->rd; + int cpus = 0; + ++ rcu_lockdep_assert(rcu_read_lock_sched_held(), ++ "sched RCU must be held"); + for_each_cpu_and(i, rd->span, cpu_active_mask) + cpus++; + +@@ -2976,6 +2980,8 @@ void rt_mutex_setprio(struct task_struct *p, int prio) + } else { + if (dl_prio(oldprio)) + p->dl.dl_boosted = 0; ++ if (rt_prio(oldprio)) ++ p->rt.timeout = 0; + p->sched_class = &fair_sched_class; + } + +@@ -3511,9 +3517,10 @@ static int _sched_setscheduler(struct task_struct *p, int policy, + }; + + /* +- * Fixup the legacy SCHED_RESET_ON_FORK hack ++ * Fixup the legacy SCHED_RESET_ON_FORK hack, except if ++ * the policy=-1 was passed by sched_setparam(). + */ +- if (policy & SCHED_RESET_ON_FORK) { ++ if ((policy != -1) && (policy & SCHED_RESET_ON_FORK)) { + attr.sched_flags |= SCHED_FLAG_RESET_ON_FORK; + policy &= ~SCHED_RESET_ON_FORK; + attr.sched_policy = policy; +@@ -3936,13 +3943,14 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask) + * root_domain. + */ + #ifdef CONFIG_SMP +- if (task_has_dl_policy(p)) { +- const struct cpumask *span = task_rq(p)->rd->span; +- +- if (dl_bandwidth_enabled() && !cpumask_subset(span, new_mask)) { ++ if (task_has_dl_policy(p) && dl_bandwidth_enabled()) { ++ rcu_read_lock(); ++ if (!cpumask_subset(task_rq(p)->rd->span, new_mask)) { + retval = -EBUSY; ++ rcu_read_unlock(); + goto out_unlock; + } ++ rcu_read_unlock(); + } + #endif + again: +@@ -7457,6 +7465,8 @@ static int sched_dl_global_constraints(void) + int cpu, ret = 0; + unsigned long flags; + ++ rcu_read_lock(); ++ + /* + * Here we want to check the bandwidth not being set to some + * value smaller than the currently allocated bandwidth in +@@ -7478,6 +7488,8 @@ static int sched_dl_global_constraints(void) + break; + } + ++ rcu_read_unlock(); ++ + return ret; + } + +@@ -7493,6 +7505,7 @@ static void sched_dl_do_global(void) + if (global_rt_runtime() != RUNTIME_INF) + new_bw = to_ratio(global_rt_period(), global_rt_runtime()); + ++ rcu_read_lock(); + /* + * FIXME: As above... + */ +@@ -7503,6 +7516,7 @@ static void sched_dl_do_global(void) + dl_b->bw = new_bw; + raw_spin_unlock_irqrestore(&dl_b->lock, flags); + } ++ rcu_read_unlock(); + } + + static int sched_rt_global_validate(void) +diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c +index ce85264..8d3c5dd 100644 +--- a/kernel/sched/deadline.c ++++ b/kernel/sched/deadline.c +@@ -329,7 +329,7 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se, + + if (!lag_once) { + lag_once = true; +- printk_sched("sched: DL replenish lagged to much\n"); ++ printk_deferred("sched: DL replenish lagged to much\n"); + } + dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline; + dl_se->runtime = pi_se->dl_runtime; +@@ -550,24 +550,7 @@ void init_dl_task_timer(struct sched_dl_entity *dl_se) + static + int dl_runtime_exceeded(struct rq *rq, struct sched_dl_entity *dl_se) + { +- int dmiss = dl_time_before(dl_se->deadline, rq_clock(rq)); +- int rorun = dl_se->runtime <= 0; +- +- if (!rorun && !dmiss) +- return 0; +- +- /* +- * If we are beyond our current deadline and we are still +- * executing, then we have already used some of the runtime of +- * the next instance. Thus, if we do not account that, we are +- * stealing bandwidth from the system at each deadline miss! +- */ +- if (dmiss) { +- dl_se->runtime = rorun ? dl_se->runtime : 0; +- dl_se->runtime -= rq_clock(rq) - dl_se->deadline; +- } +- +- return 1; ++ return (dl_se->runtime <= 0); + } + + extern bool sched_rt_bandwidth_account(struct rt_rq *rt_rq); +@@ -806,10 +789,10 @@ enqueue_dl_entity(struct sched_dl_entity *dl_se, + * parameters of the task might need updating. Otherwise, + * we want a replenishment of its runtime. + */ +- if (!dl_se->dl_new && flags & ENQUEUE_REPLENISH) +- replenish_dl_entity(dl_se, pi_se); +- else ++ if (dl_se->dl_new || flags & ENQUEUE_WAKEUP) + update_dl_entity(dl_se, pi_se); ++ else if (flags & ENQUEUE_REPLENISH) ++ replenish_dl_entity(dl_se, pi_se); + + __enqueue_dl_entity(dl_se); + } +diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c +index 1999021..27b8e83 100644 +--- a/kernel/sched/rt.c ++++ b/kernel/sched/rt.c +@@ -837,7 +837,7 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq) + + if (!once) { + once = true; +- printk_sched("sched: RT throttling activated\n"); ++ printk_deferred("sched: RT throttling activated\n"); + } + } else { + /* +diff --git a/kernel/signal.c b/kernel/signal.c +index 5d4b05a..bd57d8d 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -2768,7 +2768,8 @@ int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from) + * Other callers might not initialize the si_lsb field, + * so check explicitly for the right codes here. + */ +- if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO) ++ if (from->si_signo == SIGBUS && ++ (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)) + err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb); + #endif + break; +@@ -3035,7 +3036,7 @@ COMPAT_SYSCALL_DEFINE3(rt_sigqueueinfo, + int, sig, + struct compat_siginfo __user *, uinfo) + { +- siginfo_t info; ++ siginfo_t info = {}; + int ret = copy_siginfo_from_user32(&info, uinfo); + if (unlikely(ret)) + return ret; +@@ -3081,7 +3082,7 @@ COMPAT_SYSCALL_DEFINE4(rt_tgsigqueueinfo, + int, sig, + struct compat_siginfo __user *, uinfo) + { +- siginfo_t info; ++ siginfo_t info = {}; + + if (copy_siginfo_from_user32(&info, uinfo)) + return -EFAULT; +diff --git a/kernel/smp.c b/kernel/smp.c +index ffee35b..ff87d44 100644 +--- a/kernel/smp.c ++++ b/kernel/smp.c +@@ -617,7 +617,7 @@ void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info), + if (cond_func(cpu, info)) { + ret = smp_call_function_single(cpu, func, + info, wait); +- WARN_ON_ONCE(!ret); ++ WARN_ON_ONCE(ret); + } + preempt_enable(); + } +diff --git a/kernel/smpboot.c b/kernel/smpboot.c +index eb89e18..60d35ac5 100644 +--- a/kernel/smpboot.c ++++ b/kernel/smpboot.c +@@ -279,6 +279,7 @@ int smpboot_register_percpu_thread(struct smp_hotplug_thread *plug_thread) + unsigned int cpu; + int ret = 0; + ++ get_online_cpus(); + mutex_lock(&smpboot_threads_lock); + for_each_online_cpu(cpu) { + ret = __smpboot_create_thread(plug_thread, cpu); +@@ -291,6 +292,7 @@ int smpboot_register_percpu_thread(struct smp_hotplug_thread *plug_thread) + list_add(&plug_thread->list, &hotplug_threads); + out: + mutex_unlock(&smpboot_threads_lock); ++ put_online_cpus(); + return ret; + } + EXPORT_SYMBOL_GPL(smpboot_register_percpu_thread); +diff --git a/kernel/softirq.c b/kernel/softirq.c +index 490fcbb..93be750 100644 +--- a/kernel/softirq.c ++++ b/kernel/softirq.c +@@ -657,9 +657,13 @@ static void run_ksoftirqd(unsigned int cpu) + * in the task stack here. + */ + __do_softirq(); +- rcu_note_context_switch(cpu); + local_irq_enable(); + cond_resched(); ++ ++ preempt_disable(); ++ rcu_note_context_switch(cpu); ++ preempt_enable(); ++ + return; + } + local_irq_enable(); +diff --git a/kernel/time.c b/kernel/time.c +index 7c7964c..3eb322e 100644 +--- a/kernel/time.c ++++ b/kernel/time.c +@@ -195,6 +195,10 @@ SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv, + if (tv) { + if (copy_from_user(&user_tv, tv, sizeof(*tv))) + return -EFAULT; ++ ++ if (!timeval_valid(&user_tv)) ++ return -EINVAL; ++ + new_ts.tv_sec = user_tv.tv_sec; + new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC; + } +@@ -496,17 +500,20 @@ EXPORT_SYMBOL(usecs_to_jiffies); + * that a remainder subtract here would not do the right thing as the + * resolution values don't fall on second boundries. I.e. the line: + * nsec -= nsec % TICK_NSEC; is NOT a correct resolution rounding. ++ * Note that due to the small error in the multiplier here, this ++ * rounding is incorrect for sufficiently large values of tv_nsec, but ++ * well formed timespecs should have tv_nsec < NSEC_PER_SEC, so we're ++ * OK. + * + * Rather, we just shift the bits off the right. + * + * The >> (NSEC_JIFFIE_SC - SEC_JIFFIE_SC) converts the scaled nsec + * value to a scaled second value. + */ +-unsigned long +-timespec_to_jiffies(const struct timespec *value) ++static unsigned long ++__timespec_to_jiffies(unsigned long sec, long nsec) + { +- unsigned long sec = value->tv_sec; +- long nsec = value->tv_nsec + TICK_NSEC - 1; ++ nsec = nsec + TICK_NSEC - 1; + + if (sec >= MAX_SEC_IN_JIFFIES){ + sec = MAX_SEC_IN_JIFFIES; +@@ -517,6 +524,13 @@ timespec_to_jiffies(const struct timespec *value) + (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC; + + } ++ ++unsigned long ++timespec_to_jiffies(const struct timespec *value) ++{ ++ return __timespec_to_jiffies(value->tv_sec, value->tv_nsec); ++} ++ + EXPORT_SYMBOL(timespec_to_jiffies); + + void +@@ -533,31 +547,27 @@ jiffies_to_timespec(const unsigned long jiffies, struct timespec *value) + } + EXPORT_SYMBOL(jiffies_to_timespec); + +-/* Same for "timeval" ++/* ++ * We could use a similar algorithm to timespec_to_jiffies (with a ++ * different multiplier for usec instead of nsec). But this has a ++ * problem with rounding: we can't exactly add TICK_NSEC - 1 to the ++ * usec value, since it's not necessarily integral. + * +- * Well, almost. The problem here is that the real system resolution is +- * in nanoseconds and the value being converted is in micro seconds. +- * Also for some machines (those that use HZ = 1024, in-particular), +- * there is a LARGE error in the tick size in microseconds. +- +- * The solution we use is to do the rounding AFTER we convert the +- * microsecond part. Thus the USEC_ROUND, the bits to be shifted off. +- * Instruction wise, this should cost only an additional add with carry +- * instruction above the way it was done above. ++ * We could instead round in the intermediate scaled representation ++ * (i.e. in units of 1/2^(large scale) jiffies) but that's also ++ * perilous: the scaling introduces a small positive error, which ++ * combined with a division-rounding-upward (i.e. adding 2^(scale) - 1 ++ * units to the intermediate before shifting) leads to accidental ++ * overflow and overestimates. ++ * ++ * At the cost of one additional multiplication by a constant, just ++ * use the timespec implementation. + */ + unsigned long + timeval_to_jiffies(const struct timeval *value) + { +- unsigned long sec = value->tv_sec; +- long usec = value->tv_usec; +- +- if (sec >= MAX_SEC_IN_JIFFIES){ +- sec = MAX_SEC_IN_JIFFIES; +- usec = 0; +- } +- return (((u64)sec * SEC_CONVERSION) + +- (((u64)usec * USEC_CONVERSION + USEC_ROUND) >> +- (USEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC; ++ return __timespec_to_jiffies(value->tv_sec, ++ value->tv_usec * NSEC_PER_USEC); + } + EXPORT_SYMBOL(timeval_to_jiffies); + +diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c +index fe75444..cd45a07 100644 +--- a/kernel/time/alarmtimer.c ++++ b/kernel/time/alarmtimer.c +@@ -464,18 +464,26 @@ static enum alarmtimer_type clock2alarm(clockid_t clockid) + static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm, + ktime_t now) + { ++ unsigned long flags; + struct k_itimer *ptr = container_of(alarm, struct k_itimer, + it.alarm.alarmtimer); +- if (posix_timer_event(ptr, 0) != 0) +- ptr->it_overrun++; ++ enum alarmtimer_restart result = ALARMTIMER_NORESTART; ++ ++ spin_lock_irqsave(&ptr->it_lock, flags); ++ if ((ptr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) { ++ if (posix_timer_event(ptr, 0) != 0) ++ ptr->it_overrun++; ++ } + + /* Re-add periodic timers */ + if (ptr->it.alarm.interval.tv64) { + ptr->it_overrun += alarm_forward(alarm, now, + ptr->it.alarm.interval); +- return ALARMTIMER_RESTART; ++ result = ALARMTIMER_RESTART; + } +- return ALARMTIMER_NORESTART; ++ spin_unlock_irqrestore(&ptr->it_lock, flags); ++ ++ return result; + } + + /** +@@ -541,18 +549,22 @@ static int alarm_timer_create(struct k_itimer *new_timer) + * @new_timer: k_itimer pointer + * @cur_setting: itimerspec data to fill + * +- * Copies the itimerspec data out from the k_itimer ++ * Copies out the current itimerspec data + */ + static void alarm_timer_get(struct k_itimer *timr, + struct itimerspec *cur_setting) + { +- memset(cur_setting, 0, sizeof(struct itimerspec)); ++ ktime_t relative_expiry_time = ++ alarm_expires_remaining(&(timr->it.alarm.alarmtimer)); ++ ++ if (ktime_to_ns(relative_expiry_time) > 0) { ++ cur_setting->it_value = ktime_to_timespec(relative_expiry_time); ++ } else { ++ cur_setting->it_value.tv_sec = 0; ++ cur_setting->it_value.tv_nsec = 0; ++ } + +- cur_setting->it_interval = +- ktime_to_timespec(timr->it.alarm.interval); +- cur_setting->it_value = +- ktime_to_timespec(timr->it.alarm.alarmtimer.node.expires); +- return; ++ cur_setting->it_interval = ktime_to_timespec(timr->it.alarm.interval); + } + + /** +diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c +index 086ad60..60ba1af 100644 +--- a/kernel/time/clockevents.c ++++ b/kernel/time/clockevents.c +@@ -146,7 +146,8 @@ static int clockevents_increase_min_delta(struct clock_event_device *dev) + { + /* Nothing to do if we already reached the limit */ + if (dev->min_delta_ns >= MIN_DELTA_LIMIT) { +- printk(KERN_WARNING "CE: Reprogramming failure. Giving up\n"); ++ printk_deferred(KERN_WARNING ++ "CE: Reprogramming failure. Giving up\n"); + dev->next_event.tv64 = KTIME_MAX; + return -ETIME; + } +@@ -159,9 +160,10 @@ static int clockevents_increase_min_delta(struct clock_event_device *dev) + if (dev->min_delta_ns > MIN_DELTA_LIMIT) + dev->min_delta_ns = MIN_DELTA_LIMIT; + +- printk(KERN_WARNING "CE: %s increased min_delta_ns to %llu nsec\n", +- dev->name ? dev->name : "?", +- (unsigned long long) dev->min_delta_ns); ++ printk_deferred(KERN_WARNING ++ "CE: %s increased min_delta_ns to %llu nsec\n", ++ dev->name ? dev->name : "?", ++ (unsigned long long) dev->min_delta_ns); + return 0; + } + +diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c +index af8d1d4..6211d5d 100644 +--- a/kernel/time/ntp.c ++++ b/kernel/time/ntp.c +@@ -631,6 +631,17 @@ int ntp_validate_timex(struct timex *txc) + if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME))) + return -EPERM; + ++ /* ++ * Check for potential multiplication overflows that can ++ * only happen on 64-bit systems: ++ */ ++ if ((txc->modes & ADJ_FREQUENCY) && (BITS_PER_LONG == 64)) { ++ if (LLONG_MIN / PPM_SCALE > txc->freq) ++ return -EINVAL; ++ if (LLONG_MAX / PPM_SCALE < txc->freq) ++ return -EINVAL; ++ } ++ + return 0; + } + +diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c +index 4d23dc4..313a662 100644 +--- a/kernel/time/sched_clock.c ++++ b/kernel/time/sched_clock.c +@@ -204,7 +204,8 @@ void __init sched_clock_postinit(void) + + static int sched_clock_suspend(void) + { +- sched_clock_poll(&sched_clock_timer); ++ update_sched_clock(); ++ hrtimer_cancel(&sched_clock_timer); + cd.suspended = true; + return 0; + } +@@ -212,6 +213,7 @@ static int sched_clock_suspend(void) + static void sched_clock_resume(void) + { + cd.epoch_cyc = read_sched_clock(); ++ hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL); + cd.suspended = false; + } + +diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c +index 6558b7a..8c08a6f 100644 +--- a/kernel/time/tick-sched.c ++++ b/kernel/time/tick-sched.c +@@ -807,7 +807,6 @@ void tick_nohz_idle_enter(void) + + local_irq_enable(); + } +-EXPORT_SYMBOL_GPL(tick_nohz_idle_enter); + + /** + * tick_nohz_irq_exit - update next tick event from interrupt exit +@@ -934,7 +933,6 @@ void tick_nohz_idle_exit(void) + + local_irq_enable(); + } +-EXPORT_SYMBOL_GPL(tick_nohz_idle_exit); + + static int tick_nohz_reprogram(struct tick_sched *ts, ktime_t now) + { +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index 0954450..da41de9 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -626,8 +626,22 @@ int ring_buffer_poll_wait(struct ring_buffer *buffer, int cpu, + work = &cpu_buffer->irq_work; + } + +- work->waiters_pending = true; + poll_wait(filp, &work->waiters, poll_table); ++ work->waiters_pending = true; ++ /* ++ * There's a tight race between setting the waiters_pending and ++ * checking if the ring buffer is empty. Once the waiters_pending bit ++ * is set, the next event will wake the task up, but we can get stuck ++ * if there's only a single event in. ++ * ++ * FIXME: Ideally, we need a memory barrier on the writer side as well, ++ * but adding a memory barrier to all events will cause too much of a ++ * performance hit in the fast path. We only need a memory barrier when ++ * the buffer goes from empty to having content. But as this race is ++ * extremely small, and it's not a problem if another event comes in, we ++ * will fix it later. ++ */ ++ smp_mb(); + + if ((cpu == RING_BUFFER_ALL_CPUS && !ring_buffer_empty(buffer)) || + (cpu != RING_BUFFER_ALL_CPUS && !ring_buffer_empty_cpu(buffer, cpu))) +@@ -1981,7 +1995,7 @@ rb_add_time_stamp(struct ring_buffer_event *event, u64 delta) + + /** + * rb_update_event - update event type and data +- * @event: the even to update ++ * @event: the event to update + * @type: the type of event + * @length: the size of the event field in the ring buffer + * +@@ -2637,7 +2651,7 @@ static DEFINE_PER_CPU(unsigned int, current_context); + + static __always_inline int trace_recursive_lock(void) + { +- unsigned int val = this_cpu_read(current_context); ++ unsigned int val = __this_cpu_read(current_context); + int bit; + + if (in_interrupt()) { +@@ -2654,18 +2668,17 @@ static __always_inline int trace_recursive_lock(void) + return 1; + + val |= (1 << bit); +- this_cpu_write(current_context, val); ++ __this_cpu_write(current_context, val); + + return 0; + } + + static __always_inline void trace_recursive_unlock(void) + { +- unsigned int val = this_cpu_read(current_context); ++ unsigned int val = __this_cpu_read(current_context); + +- val--; +- val &= this_cpu_read(current_context); +- this_cpu_write(current_context, val); ++ val &= val & (val - 1); ++ __this_cpu_write(current_context, val); + } + + #else +@@ -3354,21 +3367,16 @@ static void rb_iter_reset(struct ring_buffer_iter *iter) + struct ring_buffer_per_cpu *cpu_buffer = iter->cpu_buffer; + + /* Iterator usage is expected to have record disabled */ +- if (list_empty(&cpu_buffer->reader_page->list)) { +- iter->head_page = rb_set_head_page(cpu_buffer); +- if (unlikely(!iter->head_page)) +- return; +- iter->head = iter->head_page->read; +- } else { +- iter->head_page = cpu_buffer->reader_page; +- iter->head = cpu_buffer->reader_page->read; +- } ++ iter->head_page = cpu_buffer->reader_page; ++ iter->head = cpu_buffer->reader_page->read; ++ ++ iter->cache_reader_page = iter->head_page; ++ iter->cache_read = cpu_buffer->read; ++ + if (iter->head) + iter->read_stamp = cpu_buffer->read_stamp; + else + iter->read_stamp = iter->head_page->page->time_stamp; +- iter->cache_reader_page = cpu_buffer->reader_page; +- iter->cache_read = cpu_buffer->read; + } + + /** +@@ -3761,12 +3769,14 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts) + return NULL; + + /* +- * We repeat when a time extend is encountered. +- * Since the time extend is always attached to a data event, +- * we should never loop more than once. +- * (We never hit the following condition more than twice). ++ * We repeat when a time extend is encountered or we hit ++ * the end of the page. Since the time extend is always attached ++ * to a data event, we should never loop more than three times. ++ * Once for going to next page, once on time extend, and ++ * finally once to get the event. ++ * (We never hit the following condition more than thrice). + */ +- if (RB_WARN_ON(cpu_buffer, ++nr_loops > 2)) ++ if (RB_WARN_ON(cpu_buffer, ++nr_loops > 3)) + return NULL; + + if (rb_per_cpu_empty(cpu_buffer)) +diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c +index a5457d5..6ad2e2d 100644 +--- a/kernel/trace/ring_buffer_benchmark.c ++++ b/kernel/trace/ring_buffer_benchmark.c +@@ -455,7 +455,7 @@ static int __init ring_buffer_benchmark_init(void) + + if (producer_fifo >= 0) { + struct sched_param param = { +- .sched_priority = consumer_fifo ++ .sched_priority = producer_fifo + }; + sched_setscheduler(producer, SCHED_FIFO, ¶m); + } else +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index 7e259b2..a2d62b3 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -811,7 +811,7 @@ static struct { + { trace_clock_local, "local", 1 }, + { trace_clock_global, "global", 1 }, + { trace_clock_counter, "counter", 0 }, +- { trace_clock_jiffies, "uptime", 1 }, ++ { trace_clock_jiffies, "uptime", 0 }, + { trace_clock, "perf", 1 }, + ARCH_TRACE_CLOCKS + }; +@@ -4694,7 +4694,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, + *fpos += written; + + out_unlock: +- for (i = 0; i < nr_pages; i++){ ++ for (i = nr_pages - 1; i >= 0; i--) { + kunmap_atomic(map_page[i]); + put_page(pages[i]); + } +@@ -6158,7 +6158,7 @@ static int instance_mkdir (struct inode *inode, struct dentry *dentry, umode_t m + int ret; + + /* Paranoid: Make sure the parent is the "instances" directory */ +- parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias); ++ parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias); + if (WARN_ON_ONCE(parent != trace_instance_dir)) + return -ENOENT; + +@@ -6185,7 +6185,7 @@ static int instance_rmdir(struct inode *inode, struct dentry *dentry) + int ret; + + /* Paranoid: Make sure the parent is the "instances" directory */ +- parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias); ++ parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias); + if (WARN_ON_ONCE(parent != trace_instance_dir)) + return -ENOENT; + +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index c8bd809..c1be95c 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -422,6 +422,7 @@ enum { + + TRACE_CONTROL_BIT, + ++ TRACE_BRANCH_BIT, + /* + * Abuse of the trace_recursion. + * As we need a way to maintain state if we are tracing the function +diff --git a/kernel/trace/trace_branch.c b/kernel/trace/trace_branch.c +index 697fb9b..60850b4 100644 +--- a/kernel/trace/trace_branch.c ++++ b/kernel/trace/trace_branch.c +@@ -37,9 +37,12 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect) + struct trace_branch *entry; + struct ring_buffer *buffer; + unsigned long flags; +- int cpu, pc; ++ int pc; + const char *p; + ++ if (current->trace_recursion & TRACE_BRANCH_BIT) ++ return; ++ + /* + * I would love to save just the ftrace_likely_data pointer, but + * this code can also be used by modules. Ugly things can happen +@@ -50,10 +53,10 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect) + if (unlikely(!tr)) + return; + +- local_irq_save(flags); +- cpu = raw_smp_processor_id(); +- data = per_cpu_ptr(tr->trace_buffer.data, cpu); +- if (atomic_inc_return(&data->disabled) != 1) ++ raw_local_irq_save(flags); ++ current->trace_recursion |= TRACE_BRANCH_BIT; ++ data = this_cpu_ptr(tr->trace_buffer.data); ++ if (atomic_read(&data->disabled)) + goto out; + + pc = preempt_count(); +@@ -82,8 +85,8 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect) + __buffer_unlock_commit(buffer, event); + + out: +- atomic_dec(&data->disabled); +- local_irq_restore(flags); ++ current->trace_recursion &= ~TRACE_BRANCH_BIT; ++ raw_local_irq_restore(flags); + } + + static inline +diff --git a/kernel/trace/trace_clock.c b/kernel/trace/trace_clock.c +index 26dc348..57b67b1 100644 +--- a/kernel/trace/trace_clock.c ++++ b/kernel/trace/trace_clock.c +@@ -59,13 +59,14 @@ u64 notrace trace_clock(void) + + /* + * trace_jiffy_clock(): Simply use jiffies as a clock counter. ++ * Note that this use of jiffies_64 is not completely safe on ++ * 32-bit systems. But the window is tiny, and the effect if ++ * we are affected is that we will have an obviously bogus ++ * timestamp on a trace event - i.e. not life threatening. + */ + u64 notrace trace_clock_jiffies(void) + { +- u64 jiffy = jiffies - INITIAL_JIFFIES; +- +- /* Return nsecs */ +- return (u64)jiffies_to_usecs(jiffy) * 1000ULL; ++ return jiffies_64_to_clock_t(jiffies_64 - INITIAL_JIFFIES); + } + + /* +diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c +index e4c4efc..c6646a5 100644 +--- a/kernel/trace/trace_events.c ++++ b/kernel/trace/trace_events.c +@@ -428,7 +428,7 @@ static void remove_event_file_dir(struct ftrace_event_file *file) + + if (dir) { + spin_lock(&dir->d_lock); /* probably unneeded */ +- list_for_each_entry(child, &dir->d_subdirs, d_u.d_child) { ++ list_for_each_entry(child, &dir->d_subdirs, d_child) { + if (child->d_inode) /* probably unneeded */ + child->d_inode->i_private = NULL; + } +diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c +index 8a86319..7b244d0 100644 +--- a/kernel/trace/trace_events_filter.c ++++ b/kernel/trace/trace_events_filter.c +@@ -1086,6 +1086,9 @@ static void parse_init(struct filter_parse_state *ps, + + static char infix_next(struct filter_parse_state *ps) + { ++ if (!ps->infix.cnt) ++ return 0; ++ + ps->infix.cnt--; + + return ps->infix.string[ps->infix.tail++]; +@@ -1101,6 +1104,9 @@ static char infix_peek(struct filter_parse_state *ps) + + static void infix_advance(struct filter_parse_state *ps) + { ++ if (!ps->infix.cnt) ++ return; ++ + ps->infix.cnt--; + ps->infix.tail++; + } +@@ -1399,19 +1405,26 @@ static int check_preds(struct filter_parse_state *ps) + { + int n_normal_preds = 0, n_logical_preds = 0; + struct postfix_elt *elt; ++ int cnt = 0; + + list_for_each_entry(elt, &ps->postfix, list) { +- if (elt->op == OP_NONE) ++ if (elt->op == OP_NONE) { ++ cnt++; + continue; ++ } + ++ cnt--; + if (elt->op == OP_AND || elt->op == OP_OR) { + n_logical_preds++; + continue; + } + n_normal_preds++; ++ /* all ops should have operands */ ++ if (cnt < 0) ++ break; + } + +- if (!n_normal_preds || n_logical_preds >= n_normal_preds) { ++ if (cnt != 1 || !n_normal_preds || n_logical_preds >= n_normal_preds) { + parse_error(ps, FILT_ERR_INVALID_FILTER, 0); + return -EINVAL; + } +diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c +index 759d5e0..7e3cd7a 100644 +--- a/kernel/trace/trace_syscalls.c ++++ b/kernel/trace/trace_syscalls.c +@@ -313,7 +313,7 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id) + int size; + + syscall_nr = trace_get_syscall_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + + /* Here we're inside tp handler's rcu_read_lock_sched (__DO_TRACE) */ +@@ -360,7 +360,7 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret) + int syscall_nr; + + syscall_nr = trace_get_syscall_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + + /* Here we're inside tp handler's rcu_read_lock_sched (__DO_TRACE()) */ +@@ -567,7 +567,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) + int size; + + syscall_nr = trace_get_syscall_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + if (!test_bit(syscall_nr, enabled_perf_enter_syscalls)) + return; +@@ -641,7 +641,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) + int size; + + syscall_nr = trace_get_syscall_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + if (!test_bit(syscall_nr, enabled_perf_exit_syscalls)) + return; +diff --git a/kernel/uid16.c b/kernel/uid16.c +index 602e5bb..d58cc4d 100644 +--- a/kernel/uid16.c ++++ b/kernel/uid16.c +@@ -176,7 +176,7 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist) + struct group_info *group_info; + int retval; + +- if (!ns_capable(current_user_ns(), CAP_SETGID)) ++ if (!may_setgroups()) + return -EPERM; + if ((unsigned)gidsetsize > NGROUPS_MAX) + return -EINVAL; +diff --git a/kernel/user.c b/kernel/user.c +index c006131..c2bbb50 100644 +--- a/kernel/user.c ++++ b/kernel/user.c +@@ -51,6 +51,7 @@ struct user_namespace init_user_ns = { + .owner = GLOBAL_ROOT_UID, + .group = GLOBAL_ROOT_GID, + .proc_inum = PROC_USER_INIT_INO, ++ .flags = USERNS_INIT_FLAGS, + #ifdef CONFIG_PERSISTENT_KEYRINGS + .persistent_keyring_register_sem = + __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem), +diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c +index 80a57af..153971e 100644 +--- a/kernel/user_namespace.c ++++ b/kernel/user_namespace.c +@@ -24,6 +24,7 @@ + #include + + static struct kmem_cache *user_ns_cachep __read_mostly; ++static DEFINE_MUTEX(userns_state_mutex); + + static bool new_idmap_permitted(const struct file *file, + struct user_namespace *ns, int cap_setid, +@@ -99,6 +100,11 @@ int create_user_ns(struct cred *new) + ns->owner = owner; + ns->group = group; + ++ /* Inherit USERNS_SETGROUPS_ALLOWED from our parent */ ++ mutex_lock(&userns_state_mutex); ++ ns->flags = parent_ns->flags; ++ mutex_unlock(&userns_state_mutex); ++ + set_cred_user_ns(new, ns); + + #ifdef CONFIG_PERSISTENT_KEYRINGS +@@ -581,9 +587,6 @@ static bool mappings_overlap(struct uid_gid_map *new_map, struct uid_gid_extent + return false; + } + +- +-static DEFINE_MUTEX(id_map_mutex); +- + static ssize_t map_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos, + int cap_setid, +@@ -600,7 +603,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, + ssize_t ret = -EINVAL; + + /* +- * The id_map_mutex serializes all writes to any given map. ++ * The userns_state_mutex serializes all writes to any given map. + * + * Any map is only ever written once. + * +@@ -618,7 +621,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, + * order and smp_rmb() is guaranteed that we don't have crazy + * architectures returning stale data. + */ +- mutex_lock(&id_map_mutex); ++ mutex_lock(&userns_state_mutex); + + ret = -EPERM; + /* Only allow one successful write to the map */ +@@ -745,7 +748,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, + *ppos = count; + ret = count; + out: +- mutex_unlock(&id_map_mutex); ++ mutex_unlock(&userns_state_mutex); + if (page) + free_page(page); + return ret; +@@ -804,17 +807,21 @@ static bool new_idmap_permitted(const struct file *file, + struct user_namespace *ns, int cap_setid, + struct uid_gid_map *new_map) + { +- /* Allow mapping to your own filesystem ids */ +- if ((new_map->nr_extents == 1) && (new_map->extent[0].count == 1)) { ++ const struct cred *cred = file->f_cred; ++ /* Don't allow mappings that would allow anything that wouldn't ++ * be allowed without the establishment of unprivileged mappings. ++ */ ++ if ((new_map->nr_extents == 1) && (new_map->extent[0].count == 1) && ++ uid_eq(ns->owner, cred->euid)) { + u32 id = new_map->extent[0].lower_first; + if (cap_setid == CAP_SETUID) { + kuid_t uid = make_kuid(ns->parent, id); +- if (uid_eq(uid, file->f_cred->fsuid)) ++ if (uid_eq(uid, cred->euid)) + return true; +- } +- else if (cap_setid == CAP_SETGID) { ++ } else if (cap_setid == CAP_SETGID) { + kgid_t gid = make_kgid(ns->parent, id); +- if (gid_eq(gid, file->f_cred->fsgid)) ++ if (!(ns->flags & USERNS_SETGROUPS_ALLOWED) && ++ gid_eq(gid, cred->egid)) + return true; + } + } +@@ -834,6 +841,100 @@ static bool new_idmap_permitted(const struct file *file, + return false; + } + ++int proc_setgroups_show(struct seq_file *seq, void *v) ++{ ++ struct user_namespace *ns = seq->private; ++ unsigned long userns_flags = ACCESS_ONCE(ns->flags); ++ ++ seq_printf(seq, "%s\n", ++ (userns_flags & USERNS_SETGROUPS_ALLOWED) ? ++ "allow" : "deny"); ++ return 0; ++} ++ ++ssize_t proc_setgroups_write(struct file *file, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct seq_file *seq = file->private_data; ++ struct user_namespace *ns = seq->private; ++ char kbuf[8], *pos; ++ bool setgroups_allowed; ++ ssize_t ret; ++ ++ /* Only allow a very narrow range of strings to be written */ ++ ret = -EINVAL; ++ if ((*ppos != 0) || (count >= sizeof(kbuf))) ++ goto out; ++ ++ /* What was written? */ ++ ret = -EFAULT; ++ if (copy_from_user(kbuf, buf, count)) ++ goto out; ++ kbuf[count] = '\0'; ++ pos = kbuf; ++ ++ /* What is being requested? */ ++ ret = -EINVAL; ++ if (strncmp(pos, "allow", 5) == 0) { ++ pos += 5; ++ setgroups_allowed = true; ++ } ++ else if (strncmp(pos, "deny", 4) == 0) { ++ pos += 4; ++ setgroups_allowed = false; ++ } ++ else ++ goto out; ++ ++ /* Verify there is not trailing junk on the line */ ++ pos = skip_spaces(pos); ++ if (*pos != '\0') ++ goto out; ++ ++ ret = -EPERM; ++ mutex_lock(&userns_state_mutex); ++ if (setgroups_allowed) { ++ /* Enabling setgroups after setgroups has been disabled ++ * is not allowed. ++ */ ++ if (!(ns->flags & USERNS_SETGROUPS_ALLOWED)) ++ goto out_unlock; ++ } else { ++ /* Permanently disabling setgroups after setgroups has ++ * been enabled by writing the gid_map is not allowed. ++ */ ++ if (ns->gid_map.nr_extents != 0) ++ goto out_unlock; ++ ns->flags &= ~USERNS_SETGROUPS_ALLOWED; ++ } ++ mutex_unlock(&userns_state_mutex); ++ ++ /* Report a successful write */ ++ *ppos = count; ++ ret = count; ++out: ++ return ret; ++out_unlock: ++ mutex_unlock(&userns_state_mutex); ++ goto out; ++} ++ ++bool userns_may_setgroups(const struct user_namespace *ns) ++{ ++ bool allowed; ++ ++ mutex_lock(&userns_state_mutex); ++ /* It is not safe to use setgroups until a gid mapping in ++ * the user namespace has been established. ++ */ ++ allowed = ns->gid_map.nr_extents != 0; ++ /* Is setgroups allowed? */ ++ allowed = allowed && (ns->flags & USERNS_SETGROUPS_ALLOWED); ++ mutex_unlock(&userns_state_mutex); ++ ++ return allowed; ++} ++ + static void *userns_get(struct task_struct *task) + { + struct user_namespace *user_ns; +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index b4defde..423c9e3 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -1962,17 +1962,13 @@ static void pool_mayday_timeout(unsigned long __pool) + * spin_lock_irq(pool->lock) which may be released and regrabbed + * multiple times. Does GFP_KERNEL allocations. Called only from + * manager. +- * +- * Return: +- * %false if no action was taken and pool->lock stayed locked, %true +- * otherwise. + */ +-static bool maybe_create_worker(struct worker_pool *pool) ++static void maybe_create_worker(struct worker_pool *pool) + __releases(&pool->lock) + __acquires(&pool->lock) + { + if (!need_to_create_worker(pool)) +- return false; ++ return; + restart: + spin_unlock_irq(&pool->lock); + +@@ -1989,7 +1985,7 @@ restart: + start_worker(worker); + if (WARN_ON_ONCE(need_to_create_worker(pool))) + goto restart; +- return true; ++ return; + } + + if (!need_to_create_worker(pool)) +@@ -2006,7 +2002,7 @@ restart: + spin_lock_irq(&pool->lock); + if (need_to_create_worker(pool)) + goto restart; +- return true; ++ return; + } + + /** +@@ -2019,15 +2015,9 @@ restart: + * LOCKING: + * spin_lock_irq(pool->lock) which may be released and regrabbed + * multiple times. Called only from manager. +- * +- * Return: +- * %false if no action was taken and pool->lock stayed locked, %true +- * otherwise. + */ +-static bool maybe_destroy_workers(struct worker_pool *pool) ++static void maybe_destroy_workers(struct worker_pool *pool) + { +- bool ret = false; +- + while (too_many_workers(pool)) { + struct worker *worker; + unsigned long expires; +@@ -2041,10 +2031,7 @@ static bool maybe_destroy_workers(struct worker_pool *pool) + } + + destroy_worker(worker); +- ret = true; + } +- +- return ret; + } + + /** +@@ -2064,16 +2051,14 @@ static bool maybe_destroy_workers(struct worker_pool *pool) + * multiple times. Does GFP_KERNEL allocations. + * + * Return: +- * %false if the pool don't need management and the caller can safely start +- * processing works, %true indicates that the function released pool->lock +- * and reacquired it to perform some management function and that the +- * conditions that the caller verified while holding the lock before +- * calling the function might no longer be true. ++ * %false if the pool doesn't need management and the caller can safely ++ * start processing works, %true if management function was performed and ++ * the conditions that the caller verified before calling the function may ++ * no longer be true. + */ + static bool manage_workers(struct worker *worker) + { + struct worker_pool *pool = worker->pool; +- bool ret = false; + + /* + * Managership is governed by two mutexes - manager_arb and +@@ -2097,7 +2082,7 @@ static bool manage_workers(struct worker *worker) + * manager_mutex. + */ + if (!mutex_trylock(&pool->manager_arb)) +- return ret; ++ return false; + + /* + * With manager arbitration won, manager_mutex would be free in +@@ -2107,7 +2092,6 @@ static bool manage_workers(struct worker *worker) + spin_unlock_irq(&pool->lock); + mutex_lock(&pool->manager_mutex); + spin_lock_irq(&pool->lock); +- ret = true; + } + + pool->flags &= ~POOL_MANAGE_WORKERS; +@@ -2116,12 +2100,12 @@ static bool manage_workers(struct worker *worker) + * Destroy and then create so that may_start_working() is true + * on return. + */ +- ret |= maybe_destroy_workers(pool); +- ret |= maybe_create_worker(pool); ++ maybe_destroy_workers(pool); ++ maybe_create_worker(pool); + + mutex_unlock(&pool->manager_mutex); + mutex_unlock(&pool->manager_arb); +- return ret; ++ return true; + } + + /** +@@ -2909,19 +2893,57 @@ bool flush_work(struct work_struct *work) + } + EXPORT_SYMBOL_GPL(flush_work); + ++struct cwt_wait { ++ wait_queue_t wait; ++ struct work_struct *work; ++}; ++ ++static int cwt_wakefn(wait_queue_t *wait, unsigned mode, int sync, void *key) ++{ ++ struct cwt_wait *cwait = container_of(wait, struct cwt_wait, wait); ++ ++ if (cwait->work != key) ++ return 0; ++ return autoremove_wake_function(wait, mode, sync, key); ++} ++ + static bool __cancel_work_timer(struct work_struct *work, bool is_dwork) + { ++ static DECLARE_WAIT_QUEUE_HEAD(cancel_waitq); + unsigned long flags; + int ret; + + do { + ret = try_to_grab_pending(work, is_dwork, &flags); + /* +- * If someone else is canceling, wait for the same event it +- * would be waiting for before retrying. ++ * If someone else is already canceling, wait for it to ++ * finish. flush_work() doesn't work for PREEMPT_NONE ++ * because we may get scheduled between @work's completion ++ * and the other canceling task resuming and clearing ++ * CANCELING - flush_work() will return false immediately ++ * as @work is no longer busy, try_to_grab_pending() will ++ * return -ENOENT as @work is still being canceled and the ++ * other canceling task won't be able to clear CANCELING as ++ * we're hogging the CPU. ++ * ++ * Let's wait for completion using a waitqueue. As this ++ * may lead to the thundering herd problem, use a custom ++ * wake function which matches @work along with exclusive ++ * wait and wakeup. + */ +- if (unlikely(ret == -ENOENT)) +- flush_work(work); ++ if (unlikely(ret == -ENOENT)) { ++ struct cwt_wait cwait; ++ ++ init_wait(&cwait.wait); ++ cwait.wait.func = cwt_wakefn; ++ cwait.work = work; ++ ++ prepare_to_wait_exclusive(&cancel_waitq, &cwait.wait, ++ TASK_UNINTERRUPTIBLE); ++ if (work_is_canceling(work)) ++ schedule(); ++ finish_wait(&cancel_waitq, &cwait.wait); ++ } + } while (unlikely(ret < 0)); + + /* tell other tasks trying to grab @work to back off */ +@@ -2930,6 +2952,16 @@ static bool __cancel_work_timer(struct work_struct *work, bool is_dwork) + + flush_work(work); + clear_work_data(work); ++ ++ /* ++ * Paired with prepare_to_wait() above so that either ++ * waitqueue_active() is visible here or !work_is_canceling() is ++ * visible there. ++ */ ++ smp_mb(); ++ if (waitqueue_active(&cancel_waitq)) ++ __wake_up(&cancel_waitq, TASK_NORMAL, 1, work); ++ + return ret; + } + +diff --git a/lib/assoc_array.c b/lib/assoc_array.c +index c0b1007..2404d03 100644 +--- a/lib/assoc_array.c ++++ b/lib/assoc_array.c +@@ -1723,11 +1723,13 @@ ascend_old_tree: + shortcut = assoc_array_ptr_to_shortcut(ptr); + slot = shortcut->parent_slot; + cursor = shortcut->back_pointer; ++ if (!cursor) ++ goto gc_complete; + } else { + slot = node->parent_slot; + cursor = ptr; + } +- BUG_ON(!ptr); ++ BUG_ON(!cursor); + node = assoc_array_ptr_to_node(cursor); + slot++; + goto continue_node; +@@ -1735,7 +1737,7 @@ ascend_old_tree: + gc_complete: + edit->set[0].to = new_root; + assoc_array_apply_edit(edit); +- edit->array->nr_leaves_on_tree = nr_leaves_on_tree; ++ array->nr_leaves_on_tree = nr_leaves_on_tree; + return 0; + + enomem: +diff --git a/lib/bitmap.c b/lib/bitmap.c +index 06f7e4f..c0634aa 100644 +--- a/lib/bitmap.c ++++ b/lib/bitmap.c +@@ -131,7 +131,9 @@ void __bitmap_shift_right(unsigned long *dst, + lower = src[off + k]; + if (left && off + k == lim - 1) + lower &= mask; +- dst[k] = upper << (BITS_PER_LONG - rem) | lower >> rem; ++ dst[k] = lower >> rem; ++ if (rem) ++ dst[k] |= upper << (BITS_PER_LONG - rem); + if (left && k == lim - 1) + dst[k] &= mask; + } +@@ -172,7 +174,9 @@ void __bitmap_shift_left(unsigned long *dst, + upper = src[k]; + if (left && k == lim - 1) + upper &= (1UL << left) - 1; +- dst[k + off] = lower >> (BITS_PER_LONG - rem) | upper << rem; ++ dst[k + off] = upper << rem; ++ if (rem) ++ dst[k + off] |= lower >> (BITS_PER_LONG - rem); + if (left && k + off == lim - 1) + dst[k + off] &= (1UL << left) - 1; + } +@@ -599,12 +603,12 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen, + unsigned a, b; + int c, old_c, totaldigits; + const char __user __force *ubuf = (const char __user __force *)buf; +- int exp_digit, in_range; ++ int at_start, in_range; + + totaldigits = c = 0; + bitmap_zero(maskp, nmaskbits); + do { +- exp_digit = 1; ++ at_start = 1; + in_range = 0; + a = b = 0; + +@@ -633,11 +637,10 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen, + break; + + if (c == '-') { +- if (exp_digit || in_range) ++ if (at_start || in_range) + return -EINVAL; + b = 0; + in_range = 1; +- exp_digit = 1; + continue; + } + +@@ -647,16 +650,18 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen, + b = b * 10 + (c - '0'); + if (!in_range) + a = b; +- exp_digit = 0; ++ at_start = 0; + totaldigits++; + } + if (!(a <= b)) + return -EINVAL; + if (b >= nmaskbits) + return -ERANGE; +- while (a <= b) { +- set_bit(a, maskp); +- a++; ++ if (!at_start) { ++ while (a <= b) { ++ set_bit(a, maskp); ++ a++; ++ } + } + } while (buflen && c == ','); + return 0; +diff --git a/lib/btree.c b/lib/btree.c +index f9a4846..4264871 100644 +--- a/lib/btree.c ++++ b/lib/btree.c +@@ -198,6 +198,7 @@ EXPORT_SYMBOL_GPL(btree_init); + + void btree_destroy(struct btree_head *head) + { ++ mempool_free(head->node, head->mempool); + mempool_destroy(head->mempool); + head->mempool = NULL; + } +diff --git a/lib/checksum.c b/lib/checksum.c +index 129775e..8b39e86 100644 +--- a/lib/checksum.c ++++ b/lib/checksum.c +@@ -181,6 +181,15 @@ csum_partial_copy(const void *src, void *dst, int len, __wsum sum) + EXPORT_SYMBOL(csum_partial_copy); + + #ifndef csum_tcpudp_nofold ++static inline u32 from64to32(u64 x) ++{ ++ /* add up 32-bit and 32-bit for 32+c bit */ ++ x = (x & 0xffffffff) + (x >> 32); ++ /* add up carry.. */ ++ x = (x & 0xffffffff) + (x >> 32); ++ return (u32)x; ++} ++ + __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, + unsigned short len, + unsigned short proto, +@@ -195,8 +204,7 @@ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, + #else + s += (proto + len) << 8; + #endif +- s += (s >> 32); +- return (__force __wsum)s; ++ return (__force __wsum)from64to32(s); + } + EXPORT_SYMBOL(csum_tcpudp_nofold); + #endif +diff --git a/lib/decompress_bunzip2.c b/lib/decompress_bunzip2.c +index 31c5f76..f504027 100644 +--- a/lib/decompress_bunzip2.c ++++ b/lib/decompress_bunzip2.c +@@ -184,7 +184,7 @@ static int INIT get_next_block(struct bunzip_data *bd) + if (get_bits(bd, 1)) + return RETVAL_OBSOLETE_INPUT; + origPtr = get_bits(bd, 24); +- if (origPtr > dbufSize) ++ if (origPtr >= dbufSize) + return RETVAL_DATA_ERROR; + /* mapping table: if some byte values are never used (encoding things + like ascii text), the compression code removes the gaps to have fewer +diff --git a/lib/lz4/lz4_decompress.c b/lib/lz4/lz4_decompress.c +index 7a85967..f0f5c5c 100644 +--- a/lib/lz4/lz4_decompress.c ++++ b/lib/lz4/lz4_decompress.c +@@ -139,6 +139,9 @@ static int lz4_uncompress(const char *source, char *dest, int osize) + /* Error: request to write beyond destination buffer */ + if (cpy > oend) + goto _output_error; ++ if ((ref + COPYLENGTH) > oend || ++ (op + COPYLENGTH) > oend) ++ goto _output_error; + LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH)); + while (op < cpy) + *op++ = *ref++; +diff --git a/lib/lzo/lzo1x_decompress_safe.c b/lib/lzo/lzo1x_decompress_safe.c +index 8563081..a1c387f 100644 +--- a/lib/lzo/lzo1x_decompress_safe.c ++++ b/lib/lzo/lzo1x_decompress_safe.c +@@ -19,31 +19,21 @@ + #include + #include "lzodefs.h" + +-#define HAVE_IP(t, x) \ +- (((size_t)(ip_end - ip) >= (size_t)(t + x)) && \ +- (((t + x) >= t) && ((t + x) >= x))) ++#define HAVE_IP(x) ((size_t)(ip_end - ip) >= (size_t)(x)) ++#define HAVE_OP(x) ((size_t)(op_end - op) >= (size_t)(x)) ++#define NEED_IP(x) if (!HAVE_IP(x)) goto input_overrun ++#define NEED_OP(x) if (!HAVE_OP(x)) goto output_overrun ++#define TEST_LB(m_pos) if ((m_pos) < out) goto lookbehind_overrun + +-#define HAVE_OP(t, x) \ +- (((size_t)(op_end - op) >= (size_t)(t + x)) && \ +- (((t + x) >= t) && ((t + x) >= x))) +- +-#define NEED_IP(t, x) \ +- do { \ +- if (!HAVE_IP(t, x)) \ +- goto input_overrun; \ +- } while (0) +- +-#define NEED_OP(t, x) \ +- do { \ +- if (!HAVE_OP(t, x)) \ +- goto output_overrun; \ +- } while (0) +- +-#define TEST_LB(m_pos) \ +- do { \ +- if ((m_pos) < out) \ +- goto lookbehind_overrun; \ +- } while (0) ++/* This MAX_255_COUNT is the maximum number of times we can add 255 to a base ++ * count without overflowing an integer. The multiply will overflow when ++ * multiplying 255 by more than MAXINT/255. The sum will overflow earlier ++ * depending on the base count. Since the base count is taken from a u8 ++ * and a few bits, it is safe to assume that it will always be lower than ++ * or equal to 2*255, thus we can always prevent any overflow by accepting ++ * two less 255 steps. See Documentation/lzo.txt for more information. ++ */ ++#define MAX_255_COUNT ((((size_t)~0) / 255) - 2) + + int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, + unsigned char *out, size_t *out_len) +@@ -75,17 +65,24 @@ int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, + if (t < 16) { + if (likely(state == 0)) { + if (unlikely(t == 0)) { ++ size_t offset; ++ const unsigned char *ip_last = ip; ++ + while (unlikely(*ip == 0)) { +- t += 255; + ip++; +- NEED_IP(1, 0); ++ NEED_IP(1); + } +- t += 15 + *ip++; ++ offset = ip - ip_last; ++ if (unlikely(offset > MAX_255_COUNT)) ++ return LZO_E_ERROR; ++ ++ offset = (offset << 8) - offset; ++ t += offset + 15 + *ip++; + } + t += 3; + copy_literal_run: + #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) +- if (likely(HAVE_IP(t, 15) && HAVE_OP(t, 15))) { ++ if (likely(HAVE_IP(t + 15) && HAVE_OP(t + 15))) { + const unsigned char *ie = ip + t; + unsigned char *oe = op + t; + do { +@@ -101,8 +98,8 @@ copy_literal_run: + } else + #endif + { +- NEED_OP(t, 0); +- NEED_IP(t, 3); ++ NEED_OP(t); ++ NEED_IP(t + 3); + do { + *op++ = *ip++; + } while (--t > 0); +@@ -115,7 +112,7 @@ copy_literal_run: + m_pos -= t >> 2; + m_pos -= *ip++ << 2; + TEST_LB(m_pos); +- NEED_OP(2, 0); ++ NEED_OP(2); + op[0] = m_pos[0]; + op[1] = m_pos[1]; + op += 2; +@@ -136,13 +133,20 @@ copy_literal_run: + } else if (t >= 32) { + t = (t & 31) + (3 - 1); + if (unlikely(t == 2)) { ++ size_t offset; ++ const unsigned char *ip_last = ip; ++ + while (unlikely(*ip == 0)) { +- t += 255; + ip++; +- NEED_IP(1, 0); ++ NEED_IP(1); + } +- t += 31 + *ip++; +- NEED_IP(2, 0); ++ offset = ip - ip_last; ++ if (unlikely(offset > MAX_255_COUNT)) ++ return LZO_E_ERROR; ++ ++ offset = (offset << 8) - offset; ++ t += offset + 31 + *ip++; ++ NEED_IP(2); + } + m_pos = op - 1; + next = get_unaligned_le16(ip); +@@ -154,13 +158,20 @@ copy_literal_run: + m_pos -= (t & 8) << 11; + t = (t & 7) + (3 - 1); + if (unlikely(t == 2)) { ++ size_t offset; ++ const unsigned char *ip_last = ip; ++ + while (unlikely(*ip == 0)) { +- t += 255; + ip++; +- NEED_IP(1, 0); ++ NEED_IP(1); + } +- t += 7 + *ip++; +- NEED_IP(2, 0); ++ offset = ip - ip_last; ++ if (unlikely(offset > MAX_255_COUNT)) ++ return LZO_E_ERROR; ++ ++ offset = (offset << 8) - offset; ++ t += offset + 7 + *ip++; ++ NEED_IP(2); + } + next = get_unaligned_le16(ip); + ip += 2; +@@ -174,7 +185,7 @@ copy_literal_run: + #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) + if (op - m_pos >= 8) { + unsigned char *oe = op + t; +- if (likely(HAVE_OP(t, 15))) { ++ if (likely(HAVE_OP(t + 15))) { + do { + COPY8(op, m_pos); + op += 8; +@@ -184,7 +195,7 @@ copy_literal_run: + m_pos += 8; + } while (op < oe); + op = oe; +- if (HAVE_IP(6, 0)) { ++ if (HAVE_IP(6)) { + state = next; + COPY4(op, ip); + op += next; +@@ -192,7 +203,7 @@ copy_literal_run: + continue; + } + } else { +- NEED_OP(t, 0); ++ NEED_OP(t); + do { + *op++ = *m_pos++; + } while (op < oe); +@@ -201,7 +212,7 @@ copy_literal_run: + #endif + { + unsigned char *oe = op + t; +- NEED_OP(t, 0); ++ NEED_OP(t); + op[0] = m_pos[0]; + op[1] = m_pos[1]; + op += 2; +@@ -214,15 +225,15 @@ match_next: + state = next; + t = next; + #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) +- if (likely(HAVE_IP(6, 0) && HAVE_OP(4, 0))) { ++ if (likely(HAVE_IP(6) && HAVE_OP(4))) { + COPY4(op, ip); + op += t; + ip += t; + } else + #endif + { +- NEED_IP(t, 3); +- NEED_OP(t, 0); ++ NEED_IP(t + 3); ++ NEED_OP(t); + while (t > 0) { + *op++ = *ip++; + t--; +diff --git a/lib/plist.c b/lib/plist.c +index 1ebc95f..0f2084d 100644 +--- a/lib/plist.c ++++ b/lib/plist.c +@@ -134,6 +134,46 @@ void plist_del(struct plist_node *node, struct plist_head *head) + plist_check_head(head); + } + ++/** ++ * plist_requeue - Requeue @node at end of same-prio entries. ++ * ++ * This is essentially an optimized plist_del() followed by ++ * plist_add(). It moves an entry already in the plist to ++ * after any other same-priority entries. ++ * ++ * @node: &struct plist_node pointer - entry to be moved ++ * @head: &struct plist_head pointer - list head ++ */ ++void plist_requeue(struct plist_node *node, struct plist_head *head) ++{ ++ struct plist_node *iter; ++ struct list_head *node_next = &head->node_list; ++ ++ plist_check_head(head); ++ BUG_ON(plist_head_empty(head)); ++ BUG_ON(plist_node_empty(node)); ++ ++ if (node == plist_last(head)) ++ return; ++ ++ iter = plist_next(node); ++ ++ if (node->prio != iter->prio) ++ return; ++ ++ plist_del(node, head); ++ ++ plist_for_each_continue(iter, head) { ++ if (node->prio != iter->prio) { ++ node_next = &iter->node_list; ++ break; ++ } ++ } ++ list_add_tail(&node->node_list, node_next); ++ ++ plist_check_head(head); ++} ++ + #ifdef CONFIG_DEBUG_PI_LIST + #include + #include +@@ -170,6 +210,14 @@ static void __init plist_test_check(int nr_expect) + BUG_ON(prio_pos->prio_list.next != &first->prio_list); + } + ++static void __init plist_test_requeue(struct plist_node *node) ++{ ++ plist_requeue(node, &test_head); ++ ++ if (node != plist_last(&test_head)) ++ BUG_ON(node->prio == plist_next(node)->prio); ++} ++ + static int __init plist_test(void) + { + int nr_expect = 0, i, loop; +@@ -193,6 +241,10 @@ static int __init plist_test(void) + nr_expect--; + } + plist_test_check(nr_expect); ++ if (!plist_node_empty(test_node + i)) { ++ plist_test_requeue(test_node + i); ++ plist_test_check(nr_expect); ++ } + } + + for (i = 0; i < ARRAY_SIZE(test_node); i++) { +diff --git a/lib/radix-tree.c b/lib/radix-tree.c +index bd4a8df..7e30d2a 100644 +--- a/lib/radix-tree.c ++++ b/lib/radix-tree.c +@@ -946,81 +946,6 @@ next: + } + EXPORT_SYMBOL(radix_tree_range_tag_if_tagged); + +- +-/** +- * radix_tree_next_hole - find the next hole (not-present entry) +- * @root: tree root +- * @index: index key +- * @max_scan: maximum range to search +- * +- * Search the set [index, min(index+max_scan-1, MAX_INDEX)] for the lowest +- * indexed hole. +- * +- * Returns: the index of the hole if found, otherwise returns an index +- * outside of the set specified (in which case 'return - index >= max_scan' +- * will be true). In rare cases of index wrap-around, 0 will be returned. +- * +- * radix_tree_next_hole may be called under rcu_read_lock. However, like +- * radix_tree_gang_lookup, this will not atomically search a snapshot of +- * the tree at a single point in time. For example, if a hole is created +- * at index 5, then subsequently a hole is created at index 10, +- * radix_tree_next_hole covering both indexes may return 10 if called +- * under rcu_read_lock. +- */ +-unsigned long radix_tree_next_hole(struct radix_tree_root *root, +- unsigned long index, unsigned long max_scan) +-{ +- unsigned long i; +- +- for (i = 0; i < max_scan; i++) { +- if (!radix_tree_lookup(root, index)) +- break; +- index++; +- if (index == 0) +- break; +- } +- +- return index; +-} +-EXPORT_SYMBOL(radix_tree_next_hole); +- +-/** +- * radix_tree_prev_hole - find the prev hole (not-present entry) +- * @root: tree root +- * @index: index key +- * @max_scan: maximum range to search +- * +- * Search backwards in the range [max(index-max_scan+1, 0), index] +- * for the first hole. +- * +- * Returns: the index of the hole if found, otherwise returns an index +- * outside of the set specified (in which case 'index - return >= max_scan' +- * will be true). In rare cases of wrap-around, ULONG_MAX will be returned. +- * +- * radix_tree_next_hole may be called under rcu_read_lock. However, like +- * radix_tree_gang_lookup, this will not atomically search a snapshot of +- * the tree at a single point in time. For example, if a hole is created +- * at index 10, then subsequently a hole is created at index 5, +- * radix_tree_prev_hole covering both indexes may return 5 if called under +- * rcu_read_lock. +- */ +-unsigned long radix_tree_prev_hole(struct radix_tree_root *root, +- unsigned long index, unsigned long max_scan) +-{ +- unsigned long i; +- +- for (i = 0; i < max_scan; i++) { +- if (!radix_tree_lookup(root, index)) +- break; +- index--; +- if (index == ULONG_MAX) +- break; +- } +- +- return index; +-} +-EXPORT_SYMBOL(radix_tree_prev_hole); +- + /** + * radix_tree_gang_lookup - perform multiple lookup on a radix tree + * @root: radix tree root +@@ -1337,15 +1262,18 @@ static inline void radix_tree_shrink(struct radix_tree_root *root) + } + + /** +- * radix_tree_delete - delete an item from a radix tree ++ * radix_tree_delete_item - delete an item from a radix tree + * @root: radix tree root + * @index: index key ++ * @item: expected item + * +- * Remove the item at @index from the radix tree rooted at @root. ++ * Remove @item at @index from the radix tree rooted at @root. + * +- * Returns the address of the deleted item, or NULL if it was not present. ++ * Returns the address of the deleted item, or NULL if it was not present ++ * or the entry at the given @index was not @item. + */ +-void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) ++void *radix_tree_delete_item(struct radix_tree_root *root, ++ unsigned long index, void *item) + { + struct radix_tree_node *node = NULL; + struct radix_tree_node *slot = NULL; +@@ -1380,6 +1308,11 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) + if (slot == NULL) + goto out; + ++ if (item && slot != item) { ++ slot = NULL; ++ goto out; ++ } ++ + /* + * Clear all tags associated with the item to be deleted. + * This way of doing it would be inefficient, but seldom is any set. +@@ -1424,6 +1357,21 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) + out: + return slot; + } ++EXPORT_SYMBOL(radix_tree_delete_item); ++ ++/** ++ * radix_tree_delete - delete an item from a radix tree ++ * @root: radix tree root ++ * @index: index key ++ * ++ * Remove the item at @index from the radix tree rooted at @root. ++ * ++ * Returns the address of the deleted item, or NULL if it was not present. ++ */ ++void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) ++{ ++ return radix_tree_delete_item(root, index, NULL); ++} + EXPORT_SYMBOL(radix_tree_delete); + + /** +diff --git a/lib/string.c b/lib/string.c +index e5878de..cb9ea21 100644 +--- a/lib/string.c ++++ b/lib/string.c +@@ -586,6 +586,22 @@ void *memset(void *s, int c, size_t count) + EXPORT_SYMBOL(memset); + #endif + ++/** ++ * memzero_explicit - Fill a region of memory (e.g. sensitive ++ * keying data) with 0s. ++ * @s: Pointer to the start of the area. ++ * @count: The size of the area. ++ * ++ * memzero_explicit() doesn't need an arch-specific version as ++ * it just invokes the one of memset() implicitly. ++ */ ++void memzero_explicit(void *s, size_t count) ++{ ++ memset(s, 0, count); ++ barrier(); ++} ++EXPORT_SYMBOL(memzero_explicit); ++ + #ifndef __HAVE_ARCH_MEMCPY + /** + * memcpy - Copy one area of memory to another +diff --git a/lib/strnlen_user.c b/lib/strnlen_user.c +index a28df52..1164961 100644 +--- a/lib/strnlen_user.c ++++ b/lib/strnlen_user.c +@@ -57,7 +57,8 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count, + return res + find_zero(data) + 1 - align; + } + res += sizeof(unsigned long); +- if (unlikely(max < sizeof(unsigned long))) ++ /* We already handled 'unsigned long' bytes. Did we do it all ? */ ++ if (unlikely(max <= sizeof(unsigned long))) + break; + max -= sizeof(unsigned long); + if (unlikely(__get_user(c,(unsigned long __user *)(src+res)))) +diff --git a/mm/Makefile b/mm/Makefile +index b2aa3cc..2bad2e00 100644 +--- a/mm/Makefile ++++ b/mm/Makefile +@@ -16,7 +16,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \ + readahead.o swap.o truncate.o vmscan.o shmem.o \ + util.o mmzone.o vmstat.o backing-dev.o \ + mm_init.o mmu_context.o percpu.o slab_common.o \ +- compaction.o balloon_compaction.o \ ++ compaction.o balloon_compaction.o vmacache.o \ + interval_tree.o list_lru.o $(mmu-y) + + obj-y += init-mm.o +diff --git a/mm/compaction.c b/mm/compaction.c +index 5f702ef..a522208 100644 +--- a/mm/compaction.c ++++ b/mm/compaction.c +@@ -89,7 +89,8 @@ static void __reset_isolation_suitable(struct zone *zone) + unsigned long end_pfn = zone_end_pfn(zone); + unsigned long pfn; + +- zone->compact_cached_migrate_pfn = start_pfn; ++ zone->compact_cached_migrate_pfn[0] = start_pfn; ++ zone->compact_cached_migrate_pfn[1] = start_pfn; + zone->compact_cached_free_pfn = end_pfn; + zone->compact_blockskip_flush = false; + +@@ -131,9 +132,10 @@ void reset_isolation_suitable(pg_data_t *pgdat) + */ + static void update_pageblock_skip(struct compact_control *cc, + struct page *page, unsigned long nr_isolated, +- bool migrate_scanner) ++ bool set_unsuitable, bool migrate_scanner) + { + struct zone *zone = cc->zone; ++ unsigned long pfn; + + if (cc->ignore_skip_hint) + return; +@@ -141,20 +143,32 @@ static void update_pageblock_skip(struct compact_control *cc, + if (!page) + return; + +- if (!nr_isolated) { +- unsigned long pfn = page_to_pfn(page); ++ if (nr_isolated) ++ return; ++ ++ /* ++ * Only skip pageblocks when all forms of compaction will be known to ++ * fail in the near future. ++ */ ++ if (set_unsuitable) + set_pageblock_skip(page); + +- /* Update where compaction should restart */ +- if (migrate_scanner) { +- if (!cc->finished_update_migrate && +- pfn > zone->compact_cached_migrate_pfn) +- zone->compact_cached_migrate_pfn = pfn; +- } else { +- if (!cc->finished_update_free && +- pfn < zone->compact_cached_free_pfn) +- zone->compact_cached_free_pfn = pfn; +- } ++ pfn = page_to_pfn(page); ++ ++ /* Update where async and sync compaction should restart */ ++ if (migrate_scanner) { ++ if (cc->finished_update_migrate) ++ return; ++ if (pfn > zone->compact_cached_migrate_pfn[0]) ++ zone->compact_cached_migrate_pfn[0] = pfn; ++ if (cc->mode != MIGRATE_ASYNC && ++ pfn > zone->compact_cached_migrate_pfn[1]) ++ zone->compact_cached_migrate_pfn[1] = pfn; ++ } else { ++ if (cc->finished_update_free) ++ return; ++ if (pfn < zone->compact_cached_free_pfn) ++ zone->compact_cached_free_pfn = pfn; + } + } + #else +@@ -166,7 +180,7 @@ static inline bool isolation_suitable(struct compact_control *cc, + + static void update_pageblock_skip(struct compact_control *cc, + struct page *page, unsigned long nr_isolated, +- bool migrate_scanner) ++ bool set_unsuitable, bool migrate_scanner) + { + } + #endif /* CONFIG_COMPACTION */ +@@ -195,7 +209,7 @@ static bool compact_checklock_irqsave(spinlock_t *lock, unsigned long *flags, + } + + /* async aborts if taking too long or contended */ +- if (!cc->sync) { ++ if (cc->mode == MIGRATE_ASYNC) { + cc->contended = true; + return false; + } +@@ -208,30 +222,39 @@ static bool compact_checklock_irqsave(spinlock_t *lock, unsigned long *flags, + return true; + } + +-static inline bool compact_trylock_irqsave(spinlock_t *lock, +- unsigned long *flags, struct compact_control *cc) ++/* ++ * Aside from avoiding lock contention, compaction also periodically checks ++ * need_resched() and either schedules in sync compaction or aborts async ++ * compaction. This is similar to what compact_checklock_irqsave() does, but ++ * is used where no lock is concerned. ++ * ++ * Returns false when no scheduling was needed, or sync compaction scheduled. ++ * Returns true when async compaction should abort. ++ */ ++static inline bool compact_should_abort(struct compact_control *cc) + { +- return compact_checklock_irqsave(lock, flags, false, cc); ++ /* async compaction aborts if contended */ ++ if (need_resched()) { ++ if (cc->mode == MIGRATE_ASYNC) { ++ cc->contended = true; ++ return true; ++ } ++ ++ cond_resched(); ++ } ++ ++ return false; + } + + /* Returns true if the page is within a block suitable for migration to */ + static bool suitable_migration_target(struct page *page) + { +- int migratetype = get_pageblock_migratetype(page); +- +- /* Don't interfere with memory hot-remove or the min_free_kbytes blocks */ +- if (migratetype == MIGRATE_RESERVE) +- return false; +- +- if (is_migrate_isolate(migratetype)) +- return false; +- +- /* If the page is a large free page, then allow migration */ ++ /* If the page is a large free page, then disallow migration */ + if (PageBuddy(page) && page_order(page) >= pageblock_order) +- return true; ++ return false; + + /* If the block is MIGRATE_MOVABLE or MIGRATE_CMA, allow migration */ +- if (migrate_async_suitable(migratetype)) ++ if (migrate_async_suitable(get_pageblock_migratetype(page))) + return true; + + /* Otherwise skip the block */ +@@ -253,6 +276,7 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, + struct page *cursor, *valid_page = NULL; + unsigned long flags; + bool locked = false; ++ bool checked_pageblock = false; + + cursor = pfn_to_page(blockpfn); + +@@ -284,8 +308,16 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, + break; + + /* Recheck this is a suitable migration target under lock */ +- if (!strict && !suitable_migration_target(page)) +- break; ++ if (!strict && !checked_pageblock) { ++ /* ++ * We need to check suitability of pageblock only once ++ * and this isolate_freepages_block() is called with ++ * pageblock range, so just check once is sufficient. ++ */ ++ checked_pageblock = true; ++ if (!suitable_migration_target(page)) ++ break; ++ } + + /* Recheck this is a buddy page under lock */ + if (!PageBuddy(page)) +@@ -329,7 +361,8 @@ isolate_fail: + + /* Update the pageblock-skip if the whole pageblock was scanned */ + if (blockpfn == end_pfn) +- update_pageblock_skip(cc, valid_page, total_isolated, false); ++ update_pageblock_skip(cc, valid_page, total_isolated, true, ++ false); + + count_compact_events(COMPACTFREE_SCANNED, nr_scanned); + if (total_isolated) +@@ -460,12 +493,14 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + unsigned long last_pageblock_nr = 0, pageblock_nr; + unsigned long nr_scanned = 0, nr_isolated = 0; + struct list_head *migratelist = &cc->migratepages; +- isolate_mode_t mode = 0; + struct lruvec *lruvec; + unsigned long flags; + bool locked = false; + struct page *page = NULL, *valid_page = NULL; +- bool skipped_async_unsuitable = false; ++ bool set_unsuitable = true; ++ const isolate_mode_t mode = (cc->mode == MIGRATE_ASYNC ? ++ ISOLATE_ASYNC_MIGRATE : 0) | ++ (unevictable ? ISOLATE_UNEVICTABLE : 0); + + /* + * Ensure that there are not too many pages isolated from the LRU +@@ -474,7 +509,7 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + */ + while (unlikely(too_many_isolated(zone))) { + /* async migration should just abort */ +- if (!cc->sync) ++ if (cc->mode == MIGRATE_ASYNC) + return 0; + + congestion_wait(BLK_RW_ASYNC, HZ/10); +@@ -483,11 +518,13 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + return 0; + } + ++ if (compact_should_abort(cc)) ++ return 0; ++ + /* Time to isolate some pages for migration */ +- cond_resched(); + for (; low_pfn < end_pfn; low_pfn++) { + /* give a chance to irqs before checking need_resched() */ +- if (locked && !((low_pfn+1) % SWAP_CLUSTER_MAX)) { ++ if (locked && !(low_pfn % SWAP_CLUSTER_MAX)) { + if (should_release_lock(&zone->lru_lock)) { + spin_unlock_irqrestore(&zone->lru_lock, flags); + locked = false; +@@ -526,8 +563,25 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + + /* If isolation recently failed, do not retry */ + pageblock_nr = low_pfn >> pageblock_order; +- if (!isolation_suitable(cc, page)) +- goto next_pageblock; ++ if (last_pageblock_nr != pageblock_nr) { ++ int mt; ++ ++ last_pageblock_nr = pageblock_nr; ++ if (!isolation_suitable(cc, page)) ++ goto next_pageblock; ++ ++ /* ++ * For async migration, also only scan in MOVABLE ++ * blocks. Async migration is optimistic to see if ++ * the minimum amount of work satisfies the allocation ++ */ ++ mt = get_pageblock_migratetype(page); ++ if (cc->mode == MIGRATE_ASYNC && ++ !migrate_async_suitable(mt)) { ++ set_unsuitable = false; ++ goto next_pageblock; ++ } ++ } + + /* + * Skip if free. page_order cannot be used without zone->lock +@@ -537,18 +591,6 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + continue; + + /* +- * For async migration, also only scan in MOVABLE blocks. Async +- * migration is optimistic to see if the minimum amount of work +- * satisfies the allocation +- */ +- if (!cc->sync && last_pageblock_nr != pageblock_nr && +- !migrate_async_suitable(get_pageblock_migratetype(page))) { +- cc->finished_update_migrate = true; +- skipped_async_unsuitable = true; +- goto next_pageblock; +- } +- +- /* + * Check may be lockless but that's ok as we recheck later. + * It's possible to migrate LRU pages and balloon pages + * Skip any other type of page +@@ -557,11 +599,7 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + if (unlikely(balloon_page_movable(page))) { + if (locked && balloon_page_isolate(page)) { + /* Successfully isolated */ +- cc->finished_update_migrate = true; +- list_add(&page->lru, migratelist); +- cc->nr_migratepages++; +- nr_isolated++; +- goto check_compact_cluster; ++ goto isolate_success; + } + } + continue; +@@ -584,6 +622,15 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + continue; + } + ++ /* ++ * Migration will fail if an anonymous page is pinned in memory, ++ * so avoid taking lru_lock and isolating it unnecessarily in an ++ * admittedly racy check. ++ */ ++ if (!page_mapping(page) && ++ page_count(page) > page_mapcount(page)) ++ continue; ++ + /* Check if it is ok to still hold the lock */ + locked = compact_checklock_irqsave(&zone->lru_lock, &flags, + locked, cc); +@@ -598,12 +645,6 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + continue; + } + +- if (!cc->sync) +- mode |= ISOLATE_ASYNC_MIGRATE; +- +- if (unevictable) +- mode |= ISOLATE_UNEVICTABLE; +- + lruvec = mem_cgroup_page_lruvec(page, zone); + + /* Try isolate the page */ +@@ -613,13 +654,14 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, + VM_BUG_ON_PAGE(PageTransCompound(page), page); + + /* Successfully isolated */ +- cc->finished_update_migrate = true; + del_page_from_lru_list(page, lruvec, page_lru(page)); ++ ++isolate_success: ++ cc->finished_update_migrate = true; + list_add(&page->lru, migratelist); + cc->nr_migratepages++; + nr_isolated++; + +-check_compact_cluster: + /* Avoid isolating too much */ + if (cc->nr_migratepages == COMPACT_CLUSTER_MAX) { + ++low_pfn; +@@ -630,7 +672,6 @@ check_compact_cluster: + + next_pageblock: + low_pfn = ALIGN(low_pfn + 1, pageblock_nr_pages) - 1; +- last_pageblock_nr = pageblock_nr; + } + + acct_isolated(zone, locked, cc); +@@ -641,11 +682,10 @@ next_pageblock: + /* + * Update the pageblock-skip information and cached scanner pfn, + * if the whole pageblock was scanned without isolating any page. +- * This is not done when pageblock was skipped due to being unsuitable +- * for async compaction, so that eventual sync compaction can try. + */ +- if (low_pfn == end_pfn && !skipped_async_unsuitable) +- update_pageblock_skip(cc, valid_page, nr_isolated, true); ++ if (low_pfn == end_pfn) ++ update_pageblock_skip(cc, valid_page, nr_isolated, ++ set_unsuitable, true); + + trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated); + +@@ -666,7 +706,9 @@ static void isolate_freepages(struct zone *zone, + struct compact_control *cc) + { + struct page *page; +- unsigned long high_pfn, low_pfn, pfn, z_end_pfn; ++ unsigned long block_start_pfn; /* start of current pageblock */ ++ unsigned long block_end_pfn; /* end of current pageblock */ ++ unsigned long low_pfn; /* lowest pfn scanner is able to scan */ + int nr_freepages = cc->nr_freepages; + struct list_head *freelist = &cc->freepages; + +@@ -674,41 +716,38 @@ static void isolate_freepages(struct zone *zone, + * Initialise the free scanner. The starting point is where we last + * successfully isolated from, zone-cached value, or the end of the + * zone when isolating for the first time. We need this aligned to +- * the pageblock boundary, because we do pfn -= pageblock_nr_pages +- * in the for loop. ++ * the pageblock boundary, because we do ++ * block_start_pfn -= pageblock_nr_pages in the for loop. ++ * For ending point, take care when isolating in last pageblock of a ++ * a zone which ends in the middle of a pageblock. + * The low boundary is the end of the pageblock the migration scanner + * is using. + */ +- pfn = cc->free_pfn & ~(pageblock_nr_pages-1); ++ block_start_pfn = cc->free_pfn & ~(pageblock_nr_pages-1); ++ block_end_pfn = min(block_start_pfn + pageblock_nr_pages, ++ zone_end_pfn(zone)); + low_pfn = ALIGN(cc->migrate_pfn + 1, pageblock_nr_pages); + + /* +- * Take care that if the migration scanner is at the end of the zone +- * that the free scanner does not accidentally move to the next zone +- * in the next isolation cycle. +- */ +- high_pfn = min(low_pfn, pfn); +- +- z_end_pfn = zone_end_pfn(zone); +- +- /* + * Isolate free pages until enough are available to migrate the + * pages on cc->migratepages. We stop searching if the migrate + * and free page scanners meet or enough free pages are isolated. + */ +- for (; pfn >= low_pfn && cc->nr_migratepages > nr_freepages; +- pfn -= pageblock_nr_pages) { ++ for (; block_start_pfn >= low_pfn && cc->nr_migratepages > nr_freepages; ++ block_end_pfn = block_start_pfn, ++ block_start_pfn -= pageblock_nr_pages) { + unsigned long isolated; +- unsigned long end_pfn; + + /* + * This can iterate a massively long zone without finding any + * suitable migration targets, so periodically check if we need +- * to schedule. ++ * to schedule, or even abort async compaction. + */ +- cond_resched(); ++ if (!(block_start_pfn % (SWAP_CLUSTER_MAX * pageblock_nr_pages)) ++ && compact_should_abort(cc)) ++ break; + +- if (!pfn_valid(pfn)) ++ if (!pfn_valid(block_start_pfn)) + continue; + + /* +@@ -718,7 +757,7 @@ static void isolate_freepages(struct zone *zone, + * i.e. it's possible that all pages within a zones range of + * pages do not belong to a single zone. + */ +- page = pfn_to_page(pfn); ++ page = pfn_to_page(block_start_pfn); + if (page_zone(page) != zone) + continue; + +@@ -731,26 +770,26 @@ static void isolate_freepages(struct zone *zone, + continue; + + /* Found a block suitable for isolating free pages from */ +- isolated = 0; ++ cc->free_pfn = block_start_pfn; ++ isolated = isolate_freepages_block(cc, block_start_pfn, ++ block_end_pfn, freelist, false); ++ nr_freepages += isolated; + + /* +- * Take care when isolating in last pageblock of a zone which +- * ends in the middle of a pageblock. ++ * Set a flag that we successfully isolated in this pageblock. ++ * In the next loop iteration, zone->compact_cached_free_pfn ++ * will not be updated and thus it will effectively contain the ++ * highest pageblock we isolated pages from. + */ +- end_pfn = min(pfn + pageblock_nr_pages, z_end_pfn); +- isolated = isolate_freepages_block(cc, pfn, end_pfn, +- freelist, false); +- nr_freepages += isolated; ++ if (isolated) ++ cc->finished_update_free = true; + + /* +- * Record the highest PFN we isolated pages from. When next +- * looking for free pages, the search will restart here as +- * page migration may have returned some pages to the allocator ++ * isolate_freepages_block() might have aborted due to async ++ * compaction being contended + */ +- if (isolated) { +- cc->finished_update_free = true; +- high_pfn = max(high_pfn, pfn); +- } ++ if (cc->contended) ++ break; + } + + /* split_free_page does not map the pages */ +@@ -760,10 +799,9 @@ static void isolate_freepages(struct zone *zone, + * If we crossed the migrate scanner, we want to keep it that way + * so that compact_finished() may detect this + */ +- if (pfn < low_pfn) +- cc->free_pfn = max(pfn, zone->zone_start_pfn); +- else +- cc->free_pfn = high_pfn; ++ if (block_start_pfn < low_pfn) ++ cc->free_pfn = cc->migrate_pfn; ++ + cc->nr_freepages = nr_freepages; + } + +@@ -778,9 +816,13 @@ static struct page *compaction_alloc(struct page *migratepage, + struct compact_control *cc = (struct compact_control *)data; + struct page *freepage; + +- /* Isolate free pages if necessary */ ++ /* ++ * Isolate free pages if necessary, and if we are not aborting due to ++ * contention. ++ */ + if (list_empty(&cc->freepages)) { +- isolate_freepages(cc->zone, cc); ++ if (!cc->contended) ++ isolate_freepages(cc->zone, cc); + + if (list_empty(&cc->freepages)) + return NULL; +@@ -794,23 +836,16 @@ static struct page *compaction_alloc(struct page *migratepage, + } + + /* +- * We cannot control nr_migratepages and nr_freepages fully when migration is +- * running as migrate_pages() has no knowledge of compact_control. When +- * migration is complete, we count the number of pages on the lists by hand. ++ * This is a migrate-callback that "frees" freepages back to the isolated ++ * freelist. All pages on the freelist are from the same zone, so there is no ++ * special handling needed for NUMA. + */ +-static void update_nr_listpages(struct compact_control *cc) ++static void compaction_free(struct page *page, unsigned long data) + { +- int nr_migratepages = 0; +- int nr_freepages = 0; +- struct page *page; +- +- list_for_each_entry(page, &cc->migratepages, lru) +- nr_migratepages++; +- list_for_each_entry(page, &cc->freepages, lru) +- nr_freepages++; ++ struct compact_control *cc = (struct compact_control *)data; + +- cc->nr_migratepages = nr_migratepages; +- cc->nr_freepages = nr_freepages; ++ list_add(&page->lru, &cc->freepages); ++ cc->nr_freepages++; + } + + /* possible outcome of isolate_migratepages */ +@@ -857,13 +892,14 @@ static int compact_finished(struct zone *zone, + unsigned int order; + unsigned long watermark; + +- if (fatal_signal_pending(current)) ++ if (cc->contended || fatal_signal_pending(current)) + return COMPACT_PARTIAL; + + /* Compaction run completes if the migrate and free scanner meet */ + if (cc->free_pfn <= cc->migrate_pfn) { + /* Let the next compaction start anew. */ +- zone->compact_cached_migrate_pfn = zone->zone_start_pfn; ++ zone->compact_cached_migrate_pfn[0] = zone->zone_start_pfn; ++ zone->compact_cached_migrate_pfn[1] = zone->zone_start_pfn; + zone->compact_cached_free_pfn = zone_end_pfn(zone); + + /* +@@ -901,7 +937,7 @@ static int compact_finished(struct zone *zone, + return COMPACT_PARTIAL; + + /* Job done if allocation would set block type */ +- if (cc->order >= pageblock_order && area->nr_free) ++ if (order >= pageblock_order && area->nr_free) + return COMPACT_PARTIAL; + } + +@@ -963,6 +999,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) + int ret; + unsigned long start_pfn = zone->zone_start_pfn; + unsigned long end_pfn = zone_end_pfn(zone); ++ const bool sync = cc->mode != MIGRATE_ASYNC; + + ret = compaction_suitable(zone, cc->order); + switch (ret) { +@@ -988,7 +1025,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) + * information on where the scanners should start but check that it + * is initialised by ensuring the values are within zone boundaries. + */ +- cc->migrate_pfn = zone->compact_cached_migrate_pfn; ++ cc->migrate_pfn = zone->compact_cached_migrate_pfn[sync]; + cc->free_pfn = zone->compact_cached_free_pfn; + if (cc->free_pfn < start_pfn || cc->free_pfn > end_pfn) { + cc->free_pfn = end_pfn & ~(pageblock_nr_pages-1); +@@ -996,7 +1033,8 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) + } + if (cc->migrate_pfn < start_pfn || cc->migrate_pfn > end_pfn) { + cc->migrate_pfn = start_pfn; +- zone->compact_cached_migrate_pfn = cc->migrate_pfn; ++ zone->compact_cached_migrate_pfn[0] = cc->migrate_pfn; ++ zone->compact_cached_migrate_pfn[1] = cc->migrate_pfn; + } + + trace_mm_compaction_begin(start_pfn, cc->migrate_pfn, cc->free_pfn, end_pfn); +@@ -1004,7 +1042,6 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) + migrate_prep_local(); + + while ((ret = compact_finished(zone, cc)) == COMPACT_CONTINUE) { +- unsigned long nr_migrate, nr_remaining; + int err; + + switch (isolate_migratepages(zone, cc)) { +@@ -1019,21 +1056,20 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) + ; + } + +- nr_migrate = cc->nr_migratepages; ++ if (!cc->nr_migratepages) ++ continue; ++ + err = migrate_pages(&cc->migratepages, compaction_alloc, +- (unsigned long)cc, +- cc->sync ? MIGRATE_SYNC_LIGHT : MIGRATE_ASYNC, ++ compaction_free, (unsigned long)cc, cc->mode, + MR_COMPACTION); +- update_nr_listpages(cc); +- nr_remaining = cc->nr_migratepages; + +- trace_mm_compaction_migratepages(nr_migrate - nr_remaining, +- nr_remaining); ++ trace_mm_compaction_migratepages(cc->nr_migratepages, err, ++ &cc->migratepages); + +- /* Release isolated pages not migrated */ ++ /* All pages were either migrated or will be released */ ++ cc->nr_migratepages = 0; + if (err) { + putback_movable_pages(&cc->migratepages); +- cc->nr_migratepages = 0; + /* + * migrate_pages() may return -ENOMEM when scanners meet + * and we want compact_finished() to detect it +@@ -1055,9 +1091,8 @@ out: + return ret; + } + +-static unsigned long compact_zone_order(struct zone *zone, +- int order, gfp_t gfp_mask, +- bool sync, bool *contended) ++static unsigned long compact_zone_order(struct zone *zone, int order, ++ gfp_t gfp_mask, enum migrate_mode mode, bool *contended) + { + unsigned long ret; + struct compact_control cc = { +@@ -1066,7 +1101,7 @@ static unsigned long compact_zone_order(struct zone *zone, + .order = order, + .migratetype = allocflags_to_migratetype(gfp_mask), + .zone = zone, +- .sync = sync, ++ .mode = mode, + }; + INIT_LIST_HEAD(&cc.freepages); + INIT_LIST_HEAD(&cc.migratepages); +@@ -1088,7 +1123,7 @@ int sysctl_extfrag_threshold = 500; + * @order: The order of the current allocation + * @gfp_mask: The GFP mask of the current allocation + * @nodemask: The allowed nodes to allocate from +- * @sync: Whether migration is synchronous or not ++ * @mode: The migration mode for async, sync light, or sync migration + * @contended: Return value that is true if compaction was aborted due to lock contention + * @page: Optionally capture a free page of the requested order during compaction + * +@@ -1096,7 +1131,7 @@ int sysctl_extfrag_threshold = 500; + */ + unsigned long try_to_compact_pages(struct zonelist *zonelist, + int order, gfp_t gfp_mask, nodemask_t *nodemask, +- bool sync, bool *contended) ++ enum migrate_mode mode, bool *contended) + { + enum zone_type high_zoneidx = gfp_zone(gfp_mask); + int may_enter_fs = gfp_mask & __GFP_FS; +@@ -1121,7 +1156,7 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist, + nodemask) { + int status; + +- status = compact_zone_order(zone, order, gfp_mask, sync, ++ status = compact_zone_order(zone, order, gfp_mask, mode, + contended); + rc = max(status, rc); + +@@ -1160,9 +1195,6 @@ static void __compact_pgdat(pg_data_t *pgdat, struct compact_control *cc) + if (zone_watermark_ok(zone, cc->order, + low_wmark_pages(zone), 0, 0)) + compaction_defer_reset(zone, cc->order, false); +- /* Currently async compaction is never deferred. */ +- else if (cc->sync) +- defer_compaction(zone, cc->order); + } + + VM_BUG_ON(!list_empty(&cc->freepages)); +@@ -1174,7 +1206,7 @@ void compact_pgdat(pg_data_t *pgdat, int order) + { + struct compact_control cc = { + .order = order, +- .sync = false, ++ .mode = MIGRATE_ASYNC, + }; + + if (!order) +@@ -1187,7 +1219,8 @@ static void compact_node(int nid) + { + struct compact_control cc = { + .order = -1, +- .sync = true, ++ .mode = MIGRATE_SYNC, ++ .ignore_skip_hint = true, + }; + + __compact_pgdat(NODE_DATA(nid), &cc); +diff --git a/mm/filemap.c b/mm/filemap.c +index 7a13f6a..217cfd3 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -192,9 +192,11 @@ static int filemap_check_errors(struct address_space *mapping) + { + int ret = 0; + /* Check for outstanding write errors */ +- if (test_and_clear_bit(AS_ENOSPC, &mapping->flags)) ++ if (test_bit(AS_ENOSPC, &mapping->flags) && ++ test_and_clear_bit(AS_ENOSPC, &mapping->flags)) + ret = -ENOSPC; +- if (test_and_clear_bit(AS_EIO, &mapping->flags)) ++ if (test_bit(AS_EIO, &mapping->flags) && ++ test_and_clear_bit(AS_EIO, &mapping->flags)) + ret = -EIO; + return ret; + } +@@ -446,6 +448,29 @@ int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask) + } + EXPORT_SYMBOL_GPL(replace_page_cache_page); + ++static int page_cache_tree_insert(struct address_space *mapping, ++ struct page *page) ++{ ++ void **slot; ++ int error; ++ ++ slot = radix_tree_lookup_slot(&mapping->page_tree, page->index); ++ if (slot) { ++ void *p; ++ ++ p = radix_tree_deref_slot_protected(slot, &mapping->tree_lock); ++ if (!radix_tree_exceptional_entry(p)) ++ return -EEXIST; ++ radix_tree_replace_slot(slot, page); ++ mapping->nrpages++; ++ return 0; ++ } ++ error = radix_tree_insert(&mapping->page_tree, page->index, page); ++ if (!error) ++ mapping->nrpages++; ++ return error; ++} ++ + /** + * add_to_page_cache_locked - add a locked page to the pagecache + * @page: page to add +@@ -480,11 +505,10 @@ int add_to_page_cache_locked(struct page *page, struct address_space *mapping, + page->index = offset; + + spin_lock_irq(&mapping->tree_lock); +- error = radix_tree_insert(&mapping->page_tree, offset, page); ++ error = page_cache_tree_insert(mapping, page); + radix_tree_preload_end(); + if (unlikely(error)) + goto err_insert; +- mapping->nrpages++; + __inc_zone_page_state(page, NR_FILE_PAGES); + spin_unlock_irq(&mapping->tree_lock); + trace_mm_filemap_add_to_page_cache(page); +@@ -520,10 +544,10 @@ struct page *__page_cache_alloc(gfp_t gfp) + if (cpuset_do_page_mem_spread()) { + unsigned int cpuset_mems_cookie; + do { +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + n = cpuset_mem_spread_node(); + page = alloc_pages_exact_node(n, gfp, 0); +- } while (!put_mems_allowed(cpuset_mems_cookie) && !page); ++ } while (!page && read_mems_allowed_retry(cpuset_mems_cookie)); + + return page; + } +@@ -620,8 +644,17 @@ EXPORT_SYMBOL(unlock_page); + */ + void end_page_writeback(struct page *page) + { +- if (TestClearPageReclaim(page)) ++ /* ++ * TestClearPageReclaim could be used here but it is an atomic ++ * operation and overkill in this particular case. Failing to ++ * shuffle a page marked for immediate reclaim is too mild to ++ * justify taking an atomic operation penalty at the end of ++ * ever page writeback. ++ */ ++ if (PageReclaim(page)) { ++ ClearPageReclaim(page); + rotate_reclaimable_page(page); ++ } + + if (!test_clear_page_writeback(page)) + BUG(); +@@ -686,14 +719,101 @@ int __lock_page_or_retry(struct page *page, struct mm_struct *mm, + } + + /** +- * find_get_page - find and get a page reference ++ * page_cache_next_hole - find the next hole (not-present entry) ++ * @mapping: mapping ++ * @index: index ++ * @max_scan: maximum range to search ++ * ++ * Search the set [index, min(index+max_scan-1, MAX_INDEX)] for the ++ * lowest indexed hole. ++ * ++ * Returns: the index of the hole if found, otherwise returns an index ++ * outside of the set specified (in which case 'return - index >= ++ * max_scan' will be true). In rare cases of index wrap-around, 0 will ++ * be returned. ++ * ++ * page_cache_next_hole may be called under rcu_read_lock. However, ++ * like radix_tree_gang_lookup, this will not atomically search a ++ * snapshot of the tree at a single point in time. For example, if a ++ * hole is created at index 5, then subsequently a hole is created at ++ * index 10, page_cache_next_hole covering both indexes may return 10 ++ * if called under rcu_read_lock. ++ */ ++pgoff_t page_cache_next_hole(struct address_space *mapping, ++ pgoff_t index, unsigned long max_scan) ++{ ++ unsigned long i; ++ ++ for (i = 0; i < max_scan; i++) { ++ struct page *page; ++ ++ page = radix_tree_lookup(&mapping->page_tree, index); ++ if (!page || radix_tree_exceptional_entry(page)) ++ break; ++ index++; ++ if (index == 0) ++ break; ++ } ++ ++ return index; ++} ++EXPORT_SYMBOL(page_cache_next_hole); ++ ++/** ++ * page_cache_prev_hole - find the prev hole (not-present entry) ++ * @mapping: mapping ++ * @index: index ++ * @max_scan: maximum range to search ++ * ++ * Search backwards in the range [max(index-max_scan+1, 0), index] for ++ * the first hole. ++ * ++ * Returns: the index of the hole if found, otherwise returns an index ++ * outside of the set specified (in which case 'index - return >= ++ * max_scan' will be true). In rare cases of wrap-around, ULONG_MAX ++ * will be returned. ++ * ++ * page_cache_prev_hole may be called under rcu_read_lock. However, ++ * like radix_tree_gang_lookup, this will not atomically search a ++ * snapshot of the tree at a single point in time. For example, if a ++ * hole is created at index 10, then subsequently a hole is created at ++ * index 5, page_cache_prev_hole covering both indexes may return 5 if ++ * called under rcu_read_lock. ++ */ ++pgoff_t page_cache_prev_hole(struct address_space *mapping, ++ pgoff_t index, unsigned long max_scan) ++{ ++ unsigned long i; ++ ++ for (i = 0; i < max_scan; i++) { ++ struct page *page; ++ ++ page = radix_tree_lookup(&mapping->page_tree, index); ++ if (!page || radix_tree_exceptional_entry(page)) ++ break; ++ index--; ++ if (index == ULONG_MAX) ++ break; ++ } ++ ++ return index; ++} ++EXPORT_SYMBOL(page_cache_prev_hole); ++ ++/** ++ * find_get_entry - find and get a page cache entry + * @mapping: the address_space to search +- * @offset: the page index ++ * @offset: the page cache index + * +- * Is there a pagecache struct page at the given (mapping, offset) tuple? +- * If yes, increment its refcount and return it; if no, return NULL. ++ * Looks up the page cache slot at @mapping & @offset. If there is a ++ * page cache page, it is returned with an increased refcount. ++ * ++ * If the slot holds a shadow entry of a previously evicted page, it ++ * is returned. ++ * ++ * Otherwise, %NULL is returned. + */ +-struct page *find_get_page(struct address_space *mapping, pgoff_t offset) ++struct page *find_get_entry(struct address_space *mapping, pgoff_t offset) + { + void **pagep; + struct page *page; +@@ -734,24 +854,30 @@ out: + + return page; + } +-EXPORT_SYMBOL(find_get_page); ++EXPORT_SYMBOL(find_get_entry); + + /** +- * find_lock_page - locate, pin and lock a pagecache page ++ * find_lock_entry - locate, pin and lock a page cache entry + * @mapping: the address_space to search +- * @offset: the page index ++ * @offset: the page cache index + * +- * Locates the desired pagecache page, locks it, increments its reference +- * count and returns its address. ++ * Looks up the page cache slot at @mapping & @offset. If there is a ++ * page cache page, it is returned locked and with an increased ++ * refcount. + * +- * Returns zero if the page was not present. find_lock_page() may sleep. ++ * If the slot holds a shadow entry of a previously evicted page, it ++ * is returned. ++ * ++ * Otherwise, %NULL is returned. ++ * ++ * find_lock_entry() may sleep. + */ +-struct page *find_lock_page(struct address_space *mapping, pgoff_t offset) ++struct page *find_lock_entry(struct address_space *mapping, pgoff_t offset) + { + struct page *page; + + repeat: +- page = find_get_page(mapping, offset); ++ page = find_get_entry(mapping, offset); + if (page && !radix_tree_exception(page)) { + lock_page(page); + /* Has the page been truncated? */ +@@ -764,44 +890,86 @@ repeat: + } + return page; + } +-EXPORT_SYMBOL(find_lock_page); ++EXPORT_SYMBOL(find_lock_entry); + + /** +- * find_or_create_page - locate or add a pagecache page +- * @mapping: the page's address_space +- * @index: the page's index into the mapping +- * @gfp_mask: page allocation mode ++ * pagecache_get_page - find and get a page reference ++ * @mapping: the address_space to search ++ * @offset: the page index ++ * @fgp_flags: PCG flags ++ * @gfp_mask: gfp mask to use for the page cache data page allocation ++ * ++ * Looks up the page cache slot at @mapping & @offset. + * +- * Locates a page in the pagecache. If the page is not present, a new page +- * is allocated using @gfp_mask and is added to the pagecache and to the VM's +- * LRU list. The returned page is locked and has its reference count +- * incremented. ++ * PCG flags modify how the page is returned + * +- * find_or_create_page() may sleep, even if @gfp_flags specifies an atomic +- * allocation! ++ * FGP_ACCESSED: the page will be marked accessed ++ * FGP_LOCK: Page is return locked ++ * FGP_CREAT: If page is not present then a new page is allocated using ++ * @gfp_mask and added to the page cache and the VM's LRU ++ * list. The page is returned locked and with an increased ++ * refcount. Otherwise, %NULL is returned. + * +- * find_or_create_page() returns the desired page's address, or zero on +- * memory exhaustion. ++ * If FGP_LOCK or FGP_CREAT are specified then the function may sleep even ++ * if the GFP flags specified for FGP_CREAT are atomic. ++ * ++ * If there is a page cache page, it is returned with an increased refcount. + */ +-struct page *find_or_create_page(struct address_space *mapping, +- pgoff_t index, gfp_t gfp_mask) ++struct page *pagecache_get_page(struct address_space *mapping, pgoff_t offset, ++ int fgp_flags, gfp_t gfp_mask) + { + struct page *page; +- int err; ++ + repeat: +- page = find_lock_page(mapping, index); +- if (!page) { ++ page = find_get_entry(mapping, offset); ++ if (radix_tree_exceptional_entry(page)) ++ page = NULL; ++ if (!page) ++ goto no_page; ++ ++ if (fgp_flags & FGP_LOCK) { ++ if (fgp_flags & FGP_NOWAIT) { ++ if (!trylock_page(page)) { ++ page_cache_release(page); ++ return NULL; ++ } ++ } else { ++ lock_page(page); ++ } ++ ++ /* Has the page been truncated? */ ++ if (unlikely(page->mapping != mapping)) { ++ unlock_page(page); ++ page_cache_release(page); ++ goto repeat; ++ } ++ VM_BUG_ON(page->index != offset); ++ } ++ ++ if (page && (fgp_flags & FGP_ACCESSED)) ++ mark_page_accessed(page); ++ ++no_page: ++ if (!page && (fgp_flags & FGP_CREAT)) { ++ int err; ++ if ((fgp_flags & FGP_WRITE) && mapping_cap_account_dirty(mapping)) ++ gfp_mask |= __GFP_WRITE; ++ if (fgp_flags & FGP_NOFS) ++ gfp_mask &= ~__GFP_FS; ++ + page = __page_cache_alloc(gfp_mask); + if (!page) + return NULL; +- /* +- * We want a regular kernel memory (not highmem or DMA etc) +- * allocation for the radix tree nodes, but we need to honour +- * the context-specific requirements the caller has asked for. +- * GFP_RECLAIM_MASK collects those requirements. +- */ +- err = add_to_page_cache_lru(page, mapping, index, +- (gfp_mask & GFP_RECLAIM_MASK)); ++ ++ if (WARN_ON_ONCE(!(fgp_flags & FGP_LOCK))) ++ fgp_flags |= FGP_LOCK; ++ ++ /* Init accessed so avoit atomic mark_page_accessed later */ ++ if (fgp_flags & FGP_ACCESSED) ++ init_page_accessed(page); ++ ++ err = add_to_page_cache_lru(page, mapping, offset, ++ gfp_mask & GFP_RECLAIM_MASK); + if (unlikely(err)) { + page_cache_release(page); + page = NULL; +@@ -809,9 +977,80 @@ repeat: + goto repeat; + } + } ++ + return page; + } +-EXPORT_SYMBOL(find_or_create_page); ++EXPORT_SYMBOL(pagecache_get_page); ++ ++/** ++ * find_get_entries - gang pagecache lookup ++ * @mapping: The address_space to search ++ * @start: The starting page cache index ++ * @nr_entries: The maximum number of entries ++ * @entries: Where the resulting entries are placed ++ * @indices: The cache indices corresponding to the entries in @entries ++ * ++ * find_get_entries() will search for and return a group of up to ++ * @nr_entries entries in the mapping. The entries are placed at ++ * @entries. find_get_entries() takes a reference against any actual ++ * pages it returns. ++ * ++ * The search returns a group of mapping-contiguous page cache entries ++ * with ascending indexes. There may be holes in the indices due to ++ * not-present pages. ++ * ++ * Any shadow entries of evicted pages are included in the returned ++ * array. ++ * ++ * find_get_entries() returns the number of pages and shadow entries ++ * which were found. ++ */ ++unsigned find_get_entries(struct address_space *mapping, ++ pgoff_t start, unsigned int nr_entries, ++ struct page **entries, pgoff_t *indices) ++{ ++ void **slot; ++ unsigned int ret = 0; ++ struct radix_tree_iter iter; ++ ++ if (!nr_entries) ++ return 0; ++ ++ rcu_read_lock(); ++restart: ++ radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) { ++ struct page *page; ++repeat: ++ page = radix_tree_deref_slot(slot); ++ if (unlikely(!page)) ++ continue; ++ if (radix_tree_exception(page)) { ++ if (radix_tree_deref_retry(page)) ++ goto restart; ++ /* ++ * Otherwise, we must be storing a swap entry ++ * here as an exceptional entry: so return it ++ * without attempting to raise page count. ++ */ ++ goto export; ++ } ++ if (!page_cache_get_speculative(page)) ++ goto repeat; ++ ++ /* Has the page moved? */ ++ if (unlikely(page != *slot)) { ++ page_cache_release(page); ++ goto repeat; ++ } ++export: ++ indices[ret] = iter.index; ++ entries[ret] = page; ++ if (++ret == nr_entries) ++ break; ++ } ++ rcu_read_unlock(); ++ return ret; ++} + + /** + * find_get_pages - gang pagecache lookup +@@ -1031,39 +1270,6 @@ repeat: + } + EXPORT_SYMBOL(find_get_pages_tag); + +-/** +- * grab_cache_page_nowait - returns locked page at given index in given cache +- * @mapping: target address_space +- * @index: the page index +- * +- * Same as grab_cache_page(), but do not wait if the page is unavailable. +- * This is intended for speculative data generators, where the data can +- * be regenerated if the page couldn't be grabbed. This routine should +- * be safe to call while holding the lock for another page. +- * +- * Clear __GFP_FS when allocating the page to avoid recursion into the fs +- * and deadlock against the caller's locked page. +- */ +-struct page * +-grab_cache_page_nowait(struct address_space *mapping, pgoff_t index) +-{ +- struct page *page = find_get_page(mapping, index); +- +- if (page) { +- if (trylock_page(page)) +- return page; +- page_cache_release(page); +- return NULL; +- } +- page = __page_cache_alloc(mapping_gfp_mask(mapping) & ~__GFP_FS); +- if (page && add_to_page_cache_lru(page, mapping, index, GFP_NOFS)) { +- page_cache_release(page); +- page = NULL; +- } +- return page; +-} +-EXPORT_SYMBOL(grab_cache_page_nowait); +- + /* + * CD/DVDs are error prone. When a medium error occurs, the driver may fail + * a _large_ part of the i/o request. Imagine the worst scenario: +@@ -1795,6 +2001,18 @@ int generic_file_readonly_mmap(struct file * file, struct vm_area_struct * vma) + EXPORT_SYMBOL(generic_file_mmap); + EXPORT_SYMBOL(generic_file_readonly_mmap); + ++static struct page *wait_on_page_read(struct page *page) ++{ ++ if (!IS_ERR(page)) { ++ wait_on_page_locked(page); ++ if (!PageUptodate(page)) { ++ page_cache_release(page); ++ page = ERR_PTR(-EIO); ++ } ++ } ++ return page; ++} ++ + static struct page *__read_cache_page(struct address_space *mapping, + pgoff_t index, + int (*filler)(void *, struct page *), +@@ -1821,6 +2039,8 @@ repeat: + if (err < 0) { + page_cache_release(page); + page = ERR_PTR(err); ++ } else { ++ page = wait_on_page_read(page); + } + } + return page; +@@ -1857,6 +2077,10 @@ retry: + if (err < 0) { + page_cache_release(page); + return ERR_PTR(err); ++ } else { ++ page = wait_on_page_read(page); ++ if (IS_ERR(page)) ++ return page; + } + out: + mark_page_accessed(page); +@@ -1864,40 +2088,25 @@ out: + } + + /** +- * read_cache_page_async - read into page cache, fill it if needed ++ * read_cache_page - read into page cache, fill it if needed + * @mapping: the page's address_space + * @index: the page index + * @filler: function to perform the read + * @data: first arg to filler(data, page) function, often left as NULL + * +- * Same as read_cache_page, but don't wait for page to become unlocked +- * after submitting it to the filler. +- * + * Read into the page cache. If a page already exists, and PageUptodate() is +- * not set, try to fill the page but don't wait for it to become unlocked. ++ * not set, try to fill the page and wait for it to become unlocked. + * + * If the page does not get brought uptodate, return -EIO. + */ +-struct page *read_cache_page_async(struct address_space *mapping, ++struct page *read_cache_page(struct address_space *mapping, + pgoff_t index, + int (*filler)(void *, struct page *), + void *data) + { + return do_read_cache_page(mapping, index, filler, data, mapping_gfp_mask(mapping)); + } +-EXPORT_SYMBOL(read_cache_page_async); +- +-static struct page *wait_on_page_read(struct page *page) +-{ +- if (!IS_ERR(page)) { +- wait_on_page_locked(page); +- if (!PageUptodate(page)) { +- page_cache_release(page); +- page = ERR_PTR(-EIO); +- } +- } +- return page; +-} ++EXPORT_SYMBOL(read_cache_page); + + /** + * read_cache_page_gfp - read into page cache, using specified page allocation flags. +@@ -1916,31 +2125,10 @@ struct page *read_cache_page_gfp(struct address_space *mapping, + { + filler_t *filler = (filler_t *)mapping->a_ops->readpage; + +- return wait_on_page_read(do_read_cache_page(mapping, index, filler, NULL, gfp)); ++ return do_read_cache_page(mapping, index, filler, NULL, gfp); + } + EXPORT_SYMBOL(read_cache_page_gfp); + +-/** +- * read_cache_page - read into page cache, fill it if needed +- * @mapping: the page's address_space +- * @index: the page index +- * @filler: function to perform the read +- * @data: first arg to filler(data, page) function, often left as NULL +- * +- * Read into the page cache. If a page already exists, and PageUptodate() is +- * not set, try to fill the page then wait for it to become unlocked. +- * +- * If the page does not get brought uptodate, return -EIO. +- */ +-struct page *read_cache_page(struct address_space *mapping, +- pgoff_t index, +- int (*filler)(void *, struct page *), +- void *data) +-{ +- return wait_on_page_read(read_cache_page_async(mapping, index, filler, data)); +-} +-EXPORT_SYMBOL(read_cache_page); +- + static size_t __iovec_copy_from_user_inatomic(char *vaddr, + const struct iovec *iov, size_t base, size_t bytes) + { +@@ -1974,7 +2162,6 @@ size_t iov_iter_copy_from_user_atomic(struct page *page, + char *kaddr; + size_t copied; + +- BUG_ON(!in_atomic()); + kaddr = kmap_atomic(page); + if (likely(i->nr_segs == 1)) { + int left; +@@ -2184,7 +2371,6 @@ int pagecache_write_end(struct file *file, struct address_space *mapping, + { + const struct address_space_operations *aops = mapping->a_ops; + +- mark_page_accessed(page); + return aops->write_end(file, mapping, pos, len, copied, page, fsdata); + } + EXPORT_SYMBOL(pagecache_write_end); +@@ -2266,34 +2452,17 @@ EXPORT_SYMBOL(generic_file_direct_write); + struct page *grab_cache_page_write_begin(struct address_space *mapping, + pgoff_t index, unsigned flags) + { +- int status; +- gfp_t gfp_mask; + struct page *page; +- gfp_t gfp_notmask = 0; ++ int fgp_flags = FGP_LOCK|FGP_ACCESSED|FGP_WRITE|FGP_CREAT; + +- gfp_mask = mapping_gfp_mask(mapping); +- if (mapping_cap_account_dirty(mapping)) +- gfp_mask |= __GFP_WRITE; + if (flags & AOP_FLAG_NOFS) +- gfp_notmask = __GFP_FS; +-repeat: +- page = find_lock_page(mapping, index); ++ fgp_flags |= FGP_NOFS; ++ ++ page = pagecache_get_page(mapping, index, fgp_flags, ++ mapping_gfp_mask(mapping)); + if (page) +- goto found; ++ wait_for_stable_page(page); + +- page = __page_cache_alloc(gfp_mask & ~gfp_notmask); +- if (!page) +- return NULL; +- status = add_to_page_cache_lru(page, mapping, index, +- GFP_KERNEL & ~gfp_notmask); +- if (unlikely(status)) { +- page_cache_release(page); +- if (status == -EEXIST) +- goto repeat; +- return NULL; +- } +-found: +- wait_for_stable_page(page); + return page; + } + EXPORT_SYMBOL(grab_cache_page_write_begin); +@@ -2342,18 +2511,15 @@ again: + + status = a_ops->write_begin(file, mapping, pos, bytes, flags, + &page, &fsdata); +- if (unlikely(status)) ++ if (unlikely(status < 0)) + break; + + if (mapping_writably_mapped(mapping)) + flush_dcache_page(page); + +- pagefault_disable(); + copied = iov_iter_copy_from_user_atomic(page, i, offset, bytes); +- pagefault_enable(); + flush_dcache_page(page); + +- mark_page_accessed(page); + status = a_ops->write_end(file, mapping, pos, bytes, copied, + page, fsdata); + if (unlikely(status < 0)) +diff --git a/mm/frontswap.c b/mm/frontswap.c +index 1b24bdc..f2a3571 100644 +--- a/mm/frontswap.c ++++ b/mm/frontswap.c +@@ -244,8 +244,10 @@ int __frontswap_store(struct page *page) + the (older) page from frontswap + */ + inc_frontswap_failed_stores(); +- if (dup) ++ if (dup) { + __frontswap_clear(sis, offset); ++ frontswap_ops->invalidate_page(type, offset); ++ } + } + if (frontswap_writethrough_enabled) + /* report failure so swap also writes to swap device */ +@@ -327,15 +329,12 @@ EXPORT_SYMBOL(__frontswap_invalidate_area); + + static unsigned long __frontswap_curr_pages(void) + { +- int type; + unsigned long totalpages = 0; + struct swap_info_struct *si = NULL; + + assert_spin_locked(&swap_lock); +- for (type = swap_list.head; type >= 0; type = si->next) { +- si = swap_info[type]; ++ plist_for_each_entry(si, &swap_active_head, list) + totalpages += atomic_read(&si->frontswap_pages); +- } + return totalpages; + } + +@@ -347,11 +346,9 @@ static int __frontswap_unuse_pages(unsigned long total, unsigned long *unused, + int si_frontswap_pages; + unsigned long total_pages_to_unuse = total; + unsigned long pages = 0, pages_to_unuse = 0; +- int type; + + assert_spin_locked(&swap_lock); +- for (type = swap_list.head; type >= 0; type = si->next) { +- si = swap_info[type]; ++ plist_for_each_entry(si, &swap_active_head, list) { + si_frontswap_pages = atomic_read(&si->frontswap_pages); + if (total_pages_to_unuse < si_frontswap_pages) { + pages = pages_to_unuse = total_pages_to_unuse; +@@ -366,7 +363,7 @@ static int __frontswap_unuse_pages(unsigned long total, unsigned long *unused, + } + vm_unacct_memory(pages); + *unused = pages_to_unuse; +- *swapid = type; ++ *swapid = si->type; + ret = 0; + break; + } +@@ -413,7 +410,7 @@ void frontswap_shrink(unsigned long target_pages) + /* + * we don't want to hold swap_lock while doing a very + * lengthy try_to_unuse, but swap_list may change +- * so restart scan from swap_list.head each time ++ * so restart scan from swap_active_head each time + */ + spin_lock(&swap_lock); + ret = __frontswap_shrink(target_pages, &pages_to_unuse, &type); +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index 1c42d0c..adce656 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -199,7 +199,7 @@ retry: + preempt_disable(); + if (cmpxchg(&huge_zero_page, NULL, zero_page)) { + preempt_enable(); +- __free_page(zero_page); ++ __free_pages(zero_page, compound_order(zero_page)); + goto retry; + } + +@@ -231,7 +231,7 @@ static unsigned long shrink_huge_zero_page_scan(struct shrinker *shrink, + if (atomic_cmpxchg(&huge_zero_refcount, 1, 0) == 1) { + struct page *zero_page = xchg(&huge_zero_page, NULL); + BUG_ON(zero_page == NULL); +- __free_page(zero_page); ++ __free_pages(zero_page, compound_order(zero_page)); + return HPAGE_PMD_NR; + } + +@@ -1819,21 +1819,24 @@ static int __split_huge_page_map(struct page *page, + if (pmd) { + pgtable = pgtable_trans_huge_withdraw(mm, pmd); + pmd_populate(mm, &_pmd, pgtable); ++ if (pmd_write(*pmd)) ++ BUG_ON(page_mapcount(page) != 1); + + haddr = address; + for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) { + pte_t *pte, entry; + BUG_ON(PageCompound(page+i)); ++ /* ++ * Note that pmd_numa is not transferred deliberately ++ * to avoid any possibility that pte_numa leaks to ++ * a PROT_NONE VMA by accident. ++ */ + entry = mk_pte(page + i, vma->vm_page_prot); + entry = maybe_mkwrite(pte_mkdirty(entry), vma); + if (!pmd_write(*pmd)) + entry = pte_wrprotect(entry); +- else +- BUG_ON(page_mapcount(page) != 1); + if (!pmd_young(*pmd)) + entry = pte_mkold(entry); +- if (pmd_numa(*pmd)) +- entry = pte_mknuma(entry); + pte = pte_offset_map(&_pmd, haddr); + BUG_ON(!pte_none(*pte)); + set_pte_at(mm, haddr, pte, entry); +@@ -2270,6 +2273,30 @@ static void khugepaged_alloc_sleep(void) + + static int khugepaged_node_load[MAX_NUMNODES]; + ++static bool khugepaged_scan_abort(int nid) ++{ ++ int i; ++ ++ /* ++ * If zone_reclaim_mode is disabled, then no extra effort is made to ++ * allocate memory locally. ++ */ ++ if (!zone_reclaim_mode) ++ return false; ++ ++ /* If there is a count for this node already, it must be acceptable */ ++ if (khugepaged_node_load[nid]) ++ return false; ++ ++ for (i = 0; i < MAX_NUMNODES; i++) { ++ if (!khugepaged_node_load[i]) ++ continue; ++ if (node_distance(nid, i) > RECLAIM_DISTANCE) ++ return true; ++ } ++ return false; ++} ++ + #ifdef CONFIG_NUMA + static int khugepaged_find_target_node(void) + { +@@ -2586,6 +2613,8 @@ static int khugepaged_scan_pmd(struct mm_struct *mm, + * hit record. + */ + node = page_to_nid(page); ++ if (khugepaged_scan_abort(node)) ++ goto out_unmap; + khugepaged_node_load[node]++; + VM_BUG_ON_PAGE(PageCompound(page), page); + if (!PageLRU(page) || PageLocked(page) || !PageAnon(page)) +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 30dd626..c3e8660 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -540,7 +540,7 @@ static struct page *dequeue_huge_page_vma(struct hstate *h, + goto err; + + retry_cpuset: +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + zonelist = huge_zonelist(vma, address, + htlb_alloc_mask(h), &mpol, &nodemask); + +@@ -562,7 +562,7 @@ retry_cpuset: + } + + mpol_cond_put(mpol); +- if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) ++ if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie))) + goto retry_cpuset; + return page; + +@@ -2071,6 +2071,9 @@ static int hugetlb_sysctl_handler_common(bool obey_mempolicy, + unsigned long tmp; + int ret; + ++ if (!hugepages_supported()) ++ return -ENOTSUPP; ++ + tmp = h->max_huge_pages; + + if (write && h->order >= MAX_ORDER) +@@ -2124,6 +2127,9 @@ int hugetlb_overcommit_handler(struct ctl_table *table, int write, + unsigned long tmp; + int ret; + ++ if (!hugepages_supported()) ++ return -ENOTSUPP; ++ + tmp = h->nr_overcommit_huge_pages; + + if (write && h->order >= MAX_ORDER) +@@ -2149,6 +2155,8 @@ out: + void hugetlb_report_meminfo(struct seq_file *m) + { + struct hstate *h = &default_hstate; ++ if (!hugepages_supported()) ++ return; + seq_printf(m, + "HugePages_Total: %5lu\n" + "HugePages_Free: %5lu\n" +@@ -2165,6 +2173,8 @@ void hugetlb_report_meminfo(struct seq_file *m) + int hugetlb_report_node_meminfo(int nid, char *buf) + { + struct hstate *h = &default_hstate; ++ if (!hugepages_supported()) ++ return 0; + return sprintf(buf, + "Node %d HugePages_Total: %5u\n" + "Node %d HugePages_Free: %5u\n" +@@ -2179,6 +2189,9 @@ void hugetlb_show_meminfo(void) + struct hstate *h; + int nid; + ++ if (!hugepages_supported()) ++ return; ++ + for_each_node_state(nid, N_MEMORY) + for_each_hstate(h) + pr_info("Node %d hugepages_total=%u hugepages_free=%u hugepages_surp=%u hugepages_size=%lukB\n", +@@ -2422,6 +2435,7 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, + } else { + if (cow) + huge_ptep_set_wrprotect(src, addr, src_pte); ++ entry = huge_ptep_get(src_pte); + ptepage = pte_page(entry); + get_page(ptepage); + page_dup_rmap(ptepage); +@@ -2474,9 +2488,10 @@ again: + goto unlock; + + /* +- * HWPoisoned hugepage is already unmapped and dropped reference ++ * Migrating hugepage or HWPoisoned hugepage is already ++ * unmapped and its refcount is dropped, so just clear pte here. + */ +- if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) { ++ if (unlikely(!pte_present(pte))) { + huge_pte_clear(mm, address, ptep); + goto unlock; + } +@@ -3149,7 +3164,26 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma, + spin_unlock(ptl); + continue; + } +- if (!huge_pte_none(huge_ptep_get(ptep))) { ++ pte = huge_ptep_get(ptep); ++ if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) { ++ spin_unlock(ptl); ++ continue; ++ } ++ if (unlikely(is_hugetlb_entry_migration(pte))) { ++ swp_entry_t entry = pte_to_swp_entry(pte); ++ ++ if (is_write_migration_entry(entry)) { ++ pte_t newpte; ++ ++ make_migration_entry_read(&entry); ++ newpte = swp_entry_to_pte(entry); ++ set_huge_pte_at(mm, address, ptep, newpte); ++ pages++; ++ } ++ spin_unlock(ptl); ++ continue; ++ } ++ if (!huge_pte_none(pte)) { + pte = huge_ptep_get_and_clear(mm, address, ptep); + pte = pte_mkhuge(huge_pte_modify(pte, newprot)); + pte = arch_make_huge_pte(pte, vma, NULL, 0); +@@ -3442,6 +3476,8 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address, + { + struct page *page; + ++ if (!pmd_present(*pmd)) ++ return NULL; + page = pte_page(*(pte_t *)pmd); + if (page) + page += ((address & ~PMD_MASK) >> PAGE_SHIFT); +diff --git a/mm/internal.h b/mm/internal.h +index 3e91000..1a8a0d4 100644 +--- a/mm/internal.h ++++ b/mm/internal.h +@@ -11,6 +11,7 @@ + #ifndef __MM_INTERNAL_H + #define __MM_INTERNAL_H + ++#include + #include + + void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma, +@@ -21,6 +22,20 @@ static inline void set_page_count(struct page *page, int v) + atomic_set(&page->_count, v); + } + ++extern int __do_page_cache_readahead(struct address_space *mapping, ++ struct file *filp, pgoff_t offset, unsigned long nr_to_read, ++ unsigned long lookahead_size); ++ ++/* ++ * Submit IO for the read-ahead request in file_ra_state. ++ */ ++static inline unsigned long ra_submit(struct file_ra_state *ra, ++ struct address_space *mapping, struct file *filp) ++{ ++ return __do_page_cache_readahead(mapping, filp, ++ ra->start, ra->size, ra->async_size); ++} ++ + /* + * Turn a non-refcounted page (->_count == 0) into refcounted with + * a count of one. +@@ -119,7 +134,7 @@ struct compact_control { + unsigned long nr_migratepages; /* Number of pages to migrate */ + unsigned long free_pfn; /* isolate_freepages search base */ + unsigned long migrate_pfn; /* isolate_migratepages search base */ +- bool sync; /* Synchronous migration */ ++ enum migrate_mode mode; /* Async or sync migration mode */ + bool ignore_skip_hint; /* Scan blocks even if marked skip */ + bool finished_update_free; /* True when the zone cached pfns are + * no longer being updated +@@ -129,7 +144,10 @@ struct compact_control { + int order; /* order a direct compactor needs */ + int migratetype; /* MOVABLE, RECLAIMABLE etc */ + struct zone *zone; +- bool contended; /* True if a lock was contended */ ++ bool contended; /* True if a lock was contended, or ++ * need_resched() true during async ++ * compaction ++ */ + }; + + unsigned long +diff --git a/mm/ksm.c b/mm/ksm.c +index 68710e8..5e706e3 100644 +--- a/mm/ksm.c ++++ b/mm/ksm.c +@@ -376,7 +376,7 @@ static int break_ksm(struct vm_area_struct *vma, unsigned long addr) + else + ret = VM_FAULT_WRITE; + put_page(page); +- } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_OOM))); ++ } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | VM_FAULT_OOM))); + /* + * We must loop because handle_mm_fault() may back out if there's + * any difficulty e.g. if pte accessed bit gets updated concurrently. +diff --git a/mm/madvise.c b/mm/madvise.c +index 539eeb9..a402f8f 100644 +--- a/mm/madvise.c ++++ b/mm/madvise.c +@@ -195,7 +195,7 @@ static void force_shm_swapin_readahead(struct vm_area_struct *vma, + for (; start < end; start += PAGE_SIZE) { + index = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; + +- page = find_get_page(mapping, index); ++ page = find_get_entry(mapping, index); + if (!radix_tree_exceptional_entry(page)) { + if (page) + page_cache_release(page); +diff --git a/mm/memblock.c b/mm/memblock.c +index f3a07a4..dfee4aa 100644 +--- a/mm/memblock.c ++++ b/mm/memblock.c +@@ -183,8 +183,7 @@ phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size, + phys_addr_t align, phys_addr_t start, + phys_addr_t end, int nid) + { +- int ret; +- phys_addr_t kernel_end; ++ phys_addr_t kernel_end, ret; + + /* pump up @end */ + if (end == MEMBLOCK_ALLOC_ACCESSIBLE) +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index 5b6b003..b58d4fb 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -292,6 +292,9 @@ struct mem_cgroup { + /* vmpressure notifications */ + struct vmpressure vmpressure; + ++ /* css_online() has been completed */ ++ int initialized; ++ + /* + * the counter to account for mem+swap usage. + */ +@@ -1127,9 +1130,21 @@ skip_node: + * skipping css reference should be safe. + */ + if (next_css) { +- if ((next_css == &root->css) || +- ((next_css->flags & CSS_ONLINE) && css_tryget(next_css))) +- return mem_cgroup_from_css(next_css); ++ struct mem_cgroup *memcg = mem_cgroup_from_css(next_css); ++ ++ if (next_css == &root->css) ++ return memcg; ++ ++ if (css_tryget(next_css)) { ++ /* ++ * Make sure the memcg is initialized: ++ * mem_cgroup_css_online() orders the the ++ * initialization against setting the flag. ++ */ ++ if (smp_load_acquire(&memcg->initialized)) ++ return memcg; ++ css_put(next_css); ++ } + + prev_css = next_css; + goto skip_node; +@@ -5670,8 +5685,12 @@ static int mem_cgroup_oom_notify_cb(struct mem_cgroup *memcg) + { + struct mem_cgroup_eventfd_list *ev; + ++ spin_lock(&memcg_oom_lock); ++ + list_for_each_entry(ev, &memcg->oom_notify, list) + eventfd_signal(ev->eventfd, 1); ++ ++ spin_unlock(&memcg_oom_lock); + return 0; + } + +@@ -6534,6 +6553,7 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css) + { + struct mem_cgroup *memcg = mem_cgroup_from_css(css); + struct mem_cgroup *parent = mem_cgroup_from_css(css_parent(css)); ++ int ret; + + if (css->cgroup->id > MEM_CGROUP_ID_MAX) + return -ENOSPC; +@@ -6570,7 +6590,18 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css) + } + mutex_unlock(&memcg_create_mutex); + +- return memcg_init_kmem(memcg, &mem_cgroup_subsys); ++ ret = memcg_init_kmem(memcg, &mem_cgroup_subsys); ++ if (ret) ++ return ret; ++ ++ /* ++ * Make sure the memcg is initialized: mem_cgroup_iter() ++ * orders reading memcg->initialized against its callers ++ * reading the memcg members. ++ */ ++ smp_store_release(&memcg->initialized, 1); ++ ++ return 0; + } + + /* +diff --git a/mm/memory-failure.c b/mm/memory-failure.c +index 33365e9..42aeb84 100644 +--- a/mm/memory-failure.c ++++ b/mm/memory-failure.c +@@ -1149,10 +1149,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags) + * The check (unnecessarily) ignores LRU pages being isolated and + * walked by the page reclaim code, however that's not a big loss. + */ +- if (!PageHuge(p) && !PageTransTail(p)) { +- if (!PageLRU(p)) +- shake_page(p, 0); +- if (!PageLRU(p)) { ++ if (!PageHuge(p)) { ++ if (!PageLRU(hpage)) ++ shake_page(hpage, 0); ++ if (!PageLRU(hpage)) { + /* + * shake_page could have turned it free. + */ +@@ -1510,6 +1510,8 @@ static int get_any_page(struct page *page, unsigned long pfn, int flags) + */ + ret = __get_any_page(page, pfn, 0); + if (!PageLRU(page)) { ++ /* Drop page reference which is from __get_any_page() */ ++ put_page(page); + pr_info("soft_offline: %#lx: unknown non LRU page type %lx\n", + pfn, page->flags); + return -EIO; +@@ -1540,7 +1542,7 @@ static int soft_offline_huge_page(struct page *page, int flags) + + /* Keep page count to indicate a given hugepage is isolated. */ + list_move(&hpage->lru, &pagelist); +- ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, ++ ret = migrate_pages(&pagelist, new_page, NULL, MPOL_MF_MOVE_ALL, + MIGRATE_SYNC, MR_MEMORY_FAILURE); + if (ret) { + pr_info("soft offline: %#lx: migration failed %d, type %lx\n", +@@ -1621,7 +1623,7 @@ static int __soft_offline_page(struct page *page, int flags) + inc_zone_page_state(page, NR_ISOLATED_ANON + + page_is_file_cache(page)); + list_add(&page->lru, &pagelist); +- ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, ++ ret = migrate_pages(&pagelist, new_page, NULL, MPOL_MF_MOVE_ALL, + MIGRATE_SYNC, MR_MEMORY_FAILURE); + if (ret) { + if (!list_empty(&pagelist)) { +@@ -1645,8 +1647,6 @@ static int __soft_offline_page(struct page *page, int flags) + * setting PG_hwpoison. + */ + if (!is_free_buddy_page(page)) +- lru_add_drain_all(); +- if (!is_free_buddy_page(page)) + drain_all_pages(); + SetPageHWPoison(page); + if (!is_free_buddy_page(page)) +@@ -1725,12 +1725,12 @@ int soft_offline_page(struct page *page, int flags) + } else if (ret == 0) { /* for free pages */ + if (PageHuge(page)) { + set_page_hwpoison_huge_page(hpage); +- dequeue_hwpoisoned_huge_page(hpage); +- atomic_long_add(1 << compound_order(hpage), ++ if (!dequeue_hwpoisoned_huge_page(hpage)) ++ atomic_long_add(1 << compound_order(hpage), + &num_poisoned_pages); + } else { +- SetPageHWPoison(page); +- atomic_long_inc(&num_poisoned_pages); ++ if (!TestSetPageHWPoison(page)) ++ atomic_long_inc(&num_poisoned_pages); + } + } + unset_migratetype_isolate(page, MIGRATE_MOVABLE); +diff --git a/mm/memory.c b/mm/memory.c +index 2121d8b8..e9ddc7a 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -808,20 +808,20 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, + if (!pte_file(pte)) { + swp_entry_t entry = pte_to_swp_entry(pte); + +- if (swap_duplicate(entry) < 0) +- return entry.val; +- +- /* make sure dst_mm is on swapoff's mmlist. */ +- if (unlikely(list_empty(&dst_mm->mmlist))) { +- spin_lock(&mmlist_lock); +- if (list_empty(&dst_mm->mmlist)) +- list_add(&dst_mm->mmlist, +- &src_mm->mmlist); +- spin_unlock(&mmlist_lock); +- } +- if (likely(!non_swap_entry(entry))) ++ if (likely(!non_swap_entry(entry))) { ++ if (swap_duplicate(entry) < 0) ++ return entry.val; ++ ++ /* make sure dst_mm is on swapoff's mmlist. */ ++ if (unlikely(list_empty(&dst_mm->mmlist))) { ++ spin_lock(&mmlist_lock); ++ if (list_empty(&dst_mm->mmlist)) ++ list_add(&dst_mm->mmlist, ++ &src_mm->mmlist); ++ spin_unlock(&mmlist_lock); ++ } + rss[MM_SWAPENTS]++; +- else if (is_migration_entry(entry)) { ++ } else if (is_migration_entry(entry)) { + page = migration_entry_to_page(entry); + + if (PageAnon(page)) +@@ -878,7 +878,7 @@ out_set_pte: + return 0; + } + +-int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, ++static int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, + pmd_t *dst_pmd, pmd_t *src_pmd, struct vm_area_struct *vma, + unsigned long addr, unsigned long end) + { +@@ -1120,7 +1120,7 @@ again: + addr) != page->index) { + pte_t ptfile = pgoff_to_pte(page->index); + if (pte_soft_dirty(ptent)) +- pte_file_mksoft_dirty(ptfile); ++ ptfile = pte_file_mksoft_dirty(ptfile); + set_pte_at(mm, addr, pte, ptfile); + } + if (PageAnon(page)) +@@ -1836,7 +1836,8 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, + else + return -EFAULT; + } +- if (ret & VM_FAULT_SIGBUS) ++ if (ret & (VM_FAULT_SIGBUS | ++ VM_FAULT_SIGSEGV)) + return i ? i : -EFAULT; + BUG(); + } +@@ -1946,7 +1947,7 @@ int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm, + return -ENOMEM; + if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE)) + return -EHWPOISON; +- if (ret & VM_FAULT_SIGBUS) ++ if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) + return -EFAULT; + BUG(); + } +@@ -3204,7 +3205,7 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo + if (prev && prev->vm_end == address) + return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM; + +- expand_downwards(vma, address - PAGE_SIZE); ++ return expand_downwards(vma, address - PAGE_SIZE); + } + if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) { + struct vm_area_struct *next = vma->vm_next; +@@ -3213,7 +3214,7 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo + if (next && next->vm_start == address + PAGE_SIZE) + return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM; + +- expand_upwards(vma, address + PAGE_SIZE); ++ return expand_upwards(vma, address + PAGE_SIZE); + } + return 0; + } +@@ -3233,9 +3234,13 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, + + pte_unmap(page_table); + ++ /* File mapping without ->vm_ops ? */ ++ if (vma->vm_flags & VM_SHARED) ++ return VM_FAULT_SIGBUS; ++ + /* Check if we need to add a guard page to the stack */ + if (check_stack_guard_page(vma, address) < 0) +- return VM_FAULT_SIGBUS; ++ return VM_FAULT_SIGSEGV; + + /* Use the zero-page for reads */ + if (!(flags & FAULT_FLAG_WRITE)) { +@@ -3501,6 +3506,9 @@ static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, + - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; + + pte_unmap(page_table); ++ /* The VMA was not fully populated on mmap() or missing VM_DONTEXPAND */ ++ if (!vma->vm_ops->fault) ++ return VM_FAULT_SIGBUS; + return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte); + } + +@@ -3646,14 +3654,12 @@ static int handle_pte_fault(struct mm_struct *mm, + pte_t entry; + spinlock_t *ptl; + +- entry = *pte; ++ entry = ACCESS_ONCE(*pte); + if (!pte_present(entry)) { + if (pte_none(entry)) { +- if (vma->vm_ops) { +- if (likely(vma->vm_ops->fault)) +- return do_linear_fault(mm, vma, address, ++ if (vma->vm_ops) ++ return do_linear_fault(mm, vma, address, + pte, pmd, flags, entry); +- } + return do_anonymous_page(mm, vma, address, + pte, pmd, flags); + } +@@ -4024,7 +4030,7 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr, + if (follow_phys(vma, addr, write, &prot, &phys_addr)) + return -EINVAL; + +- maddr = ioremap_prot(phys_addr, PAGE_SIZE, prot); ++ maddr = ioremap_prot(phys_addr, PAGE_ALIGN(len + offset), prot); + if (write) + memcpy_toio(maddr + offset, buf, len); + else +diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c +index a650db2..5bba3b3 100644 +--- a/mm/memory_hotplug.c ++++ b/mm/memory_hotplug.c +@@ -1016,6 +1016,10 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start) + return NULL; + + arch_refresh_nodedata(nid, pgdat); ++ } else { ++ /* Reset the nr_zones and classzone_idx to 0 before reuse */ ++ pgdat->nr_zones = 0; ++ pgdat->classzone_idx = 0; + } + + /* we can use NODE_DATA(nid) from here */ +@@ -1332,7 +1336,7 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) + * alloc_migrate_target should be improooooved!! + * migrate_pages returns # of failed pages. + */ +- ret = migrate_pages(&source, alloc_migrate_target, 0, ++ ret = migrate_pages(&source, alloc_migrate_target, NULL, 0, + MIGRATE_SYNC, MR_MEMORY_HOTPLUG); + if (ret) + putback_movable_pages(&source); +@@ -1860,18 +1864,11 @@ void try_offline_node(int nid) + * wait_table may be allocated from boot memory, + * here only free if it's allocated by vmalloc. + */ +- if (is_vmalloc_addr(zone->wait_table)) ++ if (is_vmalloc_addr(zone->wait_table)) { + vfree(zone->wait_table); ++ zone->wait_table = NULL; ++ } + } +- +- /* +- * Since there is no way to guarentee the address of pgdat/zone is not +- * on stack of any kernel threads or used by other kernel objects +- * without reference counting or other symchronizing method, do not +- * reset node_data and free pgdat here. Just reset it to 0 and reuse +- * the memory when the node is online again. +- */ +- memset(pgdat, 0, sizeof(*pgdat)); + } + EXPORT_SYMBOL(try_offline_node); + +diff --git a/mm/mempolicy.c b/mm/mempolicy.c +index 15a8ea0..936866e 100644 +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -1060,7 +1060,7 @@ static int migrate_to_node(struct mm_struct *mm, int source, int dest, + flags | MPOL_MF_DISCONTIG_OK, &pagelist); + + if (!list_empty(&pagelist)) { +- err = migrate_pages(&pagelist, new_node_page, dest, ++ err = migrate_pages(&pagelist, new_node_page, NULL, dest, + MIGRATE_SYNC, MR_SYSCALL); + if (err) + putback_movable_pages(&pagelist); +@@ -1306,7 +1306,7 @@ static long do_mbind(unsigned long start, unsigned long len, + + if (!list_empty(&pagelist)) { + WARN_ON_ONCE(flags & MPOL_MF_LAZY); +- nr_failed = migrate_pages(&pagelist, new_page, ++ nr_failed = migrate_pages(&pagelist, new_page, NULL, + start, MIGRATE_SYNC, MR_MEMPOLICY_MBIND); + if (nr_failed) + putback_movable_pages(&pagelist); +@@ -1897,7 +1897,7 @@ int node_random(const nodemask_t *maskp) + * If the effective policy is 'BIND, returns a pointer to the mempolicy's + * @nodemask for filtering the zonelist. + * +- * Must be protected by get_mems_allowed() ++ * Must be protected by read_mems_allowed_begin() + */ + struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr, + gfp_t gfp_flags, struct mempolicy **mpol, +@@ -2061,7 +2061,7 @@ alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma, + + retry_cpuset: + pol = get_vma_policy(current, vma, addr); +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + + if (unlikely(pol->mode == MPOL_INTERLEAVE)) { + unsigned nid; +@@ -2069,7 +2069,7 @@ retry_cpuset: + nid = interleave_nid(pol, vma, addr, PAGE_SHIFT + order); + mpol_cond_put(pol); + page = alloc_page_interleave(gfp, order, nid); +- if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) ++ if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie))) + goto retry_cpuset; + + return page; +@@ -2079,7 +2079,7 @@ retry_cpuset: + policy_nodemask(gfp, pol)); + if (unlikely(mpol_needs_cond_ref(pol))) + __mpol_put(pol); +- if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) ++ if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie))) + goto retry_cpuset; + return page; + } +@@ -2113,7 +2113,7 @@ struct page *alloc_pages_current(gfp_t gfp, unsigned order) + pol = &default_policy; + + retry_cpuset: +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + + /* + * No reference counting needed for current->mempolicy +@@ -2126,7 +2126,7 @@ retry_cpuset: + policy_zonelist(gfp, pol, numa_node_id()), + policy_nodemask(gfp, pol)); + +- if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) ++ if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie))) + goto retry_cpuset; + + return page; +@@ -2663,7 +2663,7 @@ static void __init check_numabalancing_enable(void) + if (numabalancing_override) + set_numabalancing_state(numabalancing_override == 1); + +- if (nr_node_ids > 1 && !numabalancing_override) { ++ if (num_online_nodes() > 1 && !numabalancing_override) { + pr_info("%s automatic NUMA balancing. " + "Configure with numa_balancing= or the " + "kernel.numa_balancing sysctl", +diff --git a/mm/migrate.c b/mm/migrate.c +index bed4880..3acac4a 100644 +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -148,8 +148,11 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma, + pte = pte_mkold(mk_pte(new, vma->vm_page_prot)); + if (pte_swp_soft_dirty(*ptep)) + pte = pte_mksoft_dirty(pte); ++ ++ /* Recheck VMA as permissions can change since migration started */ + if (is_write_migration_entry(entry)) +- pte = pte_mkwrite(pte); ++ pte = maybe_mkwrite(pte, vma); ++ + #ifdef CONFIG_HUGETLB_PAGE + if (PageHuge(new)) { + pte = pte_mkhuge(pte); +@@ -938,8 +941,9 @@ out: + * Obtain the lock on page, remove all ptes and migrate the page + * to the newly allocated page in newpage. + */ +-static int unmap_and_move(new_page_t get_new_page, unsigned long private, +- struct page *page, int force, enum migrate_mode mode) ++static int unmap_and_move(new_page_t get_new_page, free_page_t put_new_page, ++ unsigned long private, struct page *page, int force, ++ enum migrate_mode mode) + { + int rc = 0; + int *result = NULL; +@@ -983,11 +987,18 @@ out: + page_is_file_cache(page)); + putback_lru_page(page); + } ++ + /* +- * Move the new page to the LRU. If migration was not successful +- * then this will free the page. ++ * If migration was not successful and there's a freeing callback, use ++ * it. Otherwise, putback_lru_page() will drop the reference grabbed ++ * during isolation. + */ +- putback_lru_page(newpage); ++ if (rc != MIGRATEPAGE_SUCCESS && put_new_page) { ++ ClearPageSwapBacked(newpage); ++ put_new_page(newpage, private); ++ } else ++ putback_lru_page(newpage); ++ + if (result) { + if (rc) + *result = rc; +@@ -1016,8 +1027,9 @@ out: + * will wait in the page fault for migration to complete. + */ + static int unmap_and_move_huge_page(new_page_t get_new_page, +- unsigned long private, struct page *hpage, +- int force, enum migrate_mode mode) ++ free_page_t put_new_page, unsigned long private, ++ struct page *hpage, int force, ++ enum migrate_mode mode) + { + int rc = 0; + int *result = NULL; +@@ -1056,20 +1068,30 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, + if (!page_mapped(hpage)) + rc = move_to_new_page(new_hpage, hpage, 1, mode); + +- if (rc) ++ if (rc != MIGRATEPAGE_SUCCESS) + remove_migration_ptes(hpage, hpage); + + if (anon_vma) + put_anon_vma(anon_vma); + +- if (!rc) ++ if (rc == MIGRATEPAGE_SUCCESS) + hugetlb_cgroup_migrate(hpage, new_hpage); + + unlock_page(hpage); + out: + if (rc != -EAGAIN) + putback_active_hugepage(hpage); +- put_page(new_hpage); ++ ++ /* ++ * If migration was not successful and there's a freeing callback, use ++ * it. Otherwise, put_page() will drop the reference grabbed during ++ * isolation. ++ */ ++ if (rc != MIGRATEPAGE_SUCCESS && put_new_page) ++ put_new_page(new_hpage, private); ++ else ++ put_page(new_hpage); ++ + if (result) { + if (rc) + *result = rc; +@@ -1086,6 +1108,8 @@ out: + * @from: The list of pages to be migrated. + * @get_new_page: The function used to allocate free pages to be used + * as the target of the page migration. ++ * @put_new_page: The function used to free target pages if migration ++ * fails, or NULL if no special handling is necessary. + * @private: Private data to be passed on to get_new_page() + * @mode: The migration mode that specifies the constraints for + * page migration, if any. +@@ -1099,7 +1123,8 @@ out: + * Returns the number of pages that were not migrated, or an error code. + */ + int migrate_pages(struct list_head *from, new_page_t get_new_page, +- unsigned long private, enum migrate_mode mode, int reason) ++ free_page_t put_new_page, unsigned long private, ++ enum migrate_mode mode, int reason) + { + int retry = 1; + int nr_failed = 0; +@@ -1121,10 +1146,11 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, + + if (PageHuge(page)) + rc = unmap_and_move_huge_page(get_new_page, +- private, page, pass > 2, mode); ++ put_new_page, private, page, ++ pass > 2, mode); + else +- rc = unmap_and_move(get_new_page, private, +- page, pass > 2, mode); ++ rc = unmap_and_move(get_new_page, put_new_page, ++ private, page, pass > 2, mode); + + switch(rc) { + case -ENOMEM: +@@ -1273,7 +1299,7 @@ set_status: + + err = 0; + if (!list_empty(&pagelist)) { +- err = migrate_pages(&pagelist, new_page_node, ++ err = migrate_pages(&pagelist, new_page_node, NULL, + (unsigned long)pm, MIGRATE_SYNC, MR_SYSCALL); + if (err) + putback_movable_pages(&pagelist); +@@ -1729,7 +1755,8 @@ int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma, + + list_add(&page->lru, &migratepages); + nr_remaining = migrate_pages(&migratepages, alloc_misplaced_dst_page, +- node, MIGRATE_ASYNC, MR_NUMA_MISPLACED); ++ NULL, node, MIGRATE_ASYNC, ++ MR_NUMA_MISPLACED); + if (nr_remaining) { + if (!list_empty(&migratepages)) { + list_del(&page->lru); +diff --git a/mm/mincore.c b/mm/mincore.c +index 1016233..725c809 100644 +--- a/mm/mincore.c ++++ b/mm/mincore.c +@@ -70,13 +70,21 @@ static unsigned char mincore_page(struct address_space *mapping, pgoff_t pgoff) + * any other file mapping (ie. marked !present and faulted in with + * tmpfs's .fault). So swapped out tmpfs mappings are tested here. + */ +- page = find_get_page(mapping, pgoff); + #ifdef CONFIG_SWAP +- /* shmem/tmpfs may return swap: account for swapcache page too. */ +- if (radix_tree_exceptional_entry(page)) { +- swp_entry_t swap = radix_to_swp_entry(page); +- page = find_get_page(swap_address_space(swap), swap.val); +- } ++ if (shmem_mapping(mapping)) { ++ page = find_get_entry(mapping, pgoff); ++ /* ++ * shmem/tmpfs may return swap: account for swapcache ++ * page too. ++ */ ++ if (radix_tree_exceptional_entry(page)) { ++ swp_entry_t swp = radix_to_swp_entry(page); ++ page = find_get_page(swap_address_space(swp), swp.val); ++ } ++ } else ++ page = find_get_page(mapping, pgoff); ++#else ++ page = find_get_page(mapping, pgoff); + #endif + if (page) { + present = PageUptodate(page); +diff --git a/mm/mmap.c b/mm/mmap.c +index 20ff0c3..d4c97ba 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -128,7 +129,7 @@ EXPORT_SYMBOL_GPL(vm_memory_committed); + */ + int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) + { +- unsigned long free, allowed, reserve; ++ long free, allowed, reserve; + + vm_acct_memory(pages); + +@@ -192,7 +193,7 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) + */ + if (mm) { + reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10); +- allowed -= min(mm->total_vm / 32, reserve); ++ allowed -= min_t(long, mm->total_vm / 32, reserve); + } + + if (percpu_counter_read_positive(&vm_committed_as) < allowed) +@@ -681,8 +682,9 @@ __vma_unlink(struct mm_struct *mm, struct vm_area_struct *vma, + prev->vm_next = next = vma->vm_next; + if (next) + next->vm_prev = prev; +- if (mm->mmap_cache == vma) +- mm->mmap_cache = prev; ++ ++ /* Kill the cache */ ++ vmacache_invalidate(mm); + } + + /* +@@ -743,8 +745,11 @@ again: remove_next = 1 + (end > next->vm_end); + * shrinking vma had, to cover any anon pages imported. + */ + if (exporter && exporter->anon_vma && !importer->anon_vma) { +- if (anon_vma_clone(importer, exporter)) +- return -ENOMEM; ++ int error; ++ ++ error = anon_vma_clone(importer, exporter); ++ if (error) ++ return error; + importer->anon_vma = exporter->anon_vma; + } + } +@@ -1989,34 +1994,33 @@ EXPORT_SYMBOL(get_unmapped_area); + /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ + struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) + { +- struct vm_area_struct *vma = NULL; ++ struct rb_node *rb_node; ++ struct vm_area_struct *vma; + + /* Check the cache first. */ +- /* (Cache hit rate is typically around 35%.) */ +- vma = ACCESS_ONCE(mm->mmap_cache); +- if (!(vma && vma->vm_end > addr && vma->vm_start <= addr)) { +- struct rb_node *rb_node; ++ vma = vmacache_find(mm, addr); ++ if (likely(vma)) ++ return vma; + +- rb_node = mm->mm_rb.rb_node; +- vma = NULL; ++ rb_node = mm->mm_rb.rb_node; ++ vma = NULL; + +- while (rb_node) { +- struct vm_area_struct *vma_tmp; +- +- vma_tmp = rb_entry(rb_node, +- struct vm_area_struct, vm_rb); +- +- if (vma_tmp->vm_end > addr) { +- vma = vma_tmp; +- if (vma_tmp->vm_start <= addr) +- break; +- rb_node = rb_node->rb_left; +- } else +- rb_node = rb_node->rb_right; +- } +- if (vma) +- mm->mmap_cache = vma; ++ while (rb_node) { ++ struct vm_area_struct *tmp; ++ ++ tmp = rb_entry(rb_node, struct vm_area_struct, vm_rb); ++ ++ if (tmp->vm_end > addr) { ++ vma = tmp; ++ if (tmp->vm_start <= addr) ++ break; ++ rb_node = rb_node->rb_left; ++ } else ++ rb_node = rb_node->rb_right; + } ++ ++ if (vma) ++ vmacache_update(addr, vma); + return vma; + } + +@@ -2054,14 +2058,17 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns + { + struct mm_struct *mm = vma->vm_mm; + struct rlimit *rlim = current->signal->rlim; +- unsigned long new_start; ++ unsigned long new_start, actual_size; + + /* address space limit tests */ + if (!may_expand_vm(mm, grow)) + return -ENOMEM; + + /* Stack limit test */ +- if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur)) ++ actual_size = size; ++ if (size && (vma->vm_flags & (VM_GROWSUP | VM_GROWSDOWN))) ++ actual_size -= PAGE_SIZE; ++ if (actual_size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur)) + return -ENOMEM; + + /* mlock limit tests */ +@@ -2388,7 +2395,9 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, + } else + mm->highest_vm_end = prev ? prev->vm_end : 0; + tail_vma->vm_next = NULL; +- mm->mmap_cache = NULL; /* Kill the cache. */ ++ ++ /* Kill the cache */ ++ vmacache_invalidate(mm); + } + + /* +@@ -2425,7 +2434,8 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, + if (err) + goto out_free_vma; + +- if (anon_vma_clone(new, vma)) ++ err = anon_vma_clone(new, vma); ++ if (err) + goto out_free_mpol; + + if (new->vm_file) +diff --git a/mm/nommu.c b/mm/nommu.c +index 8740213..76b3f90 100644 +--- a/mm/nommu.c ++++ b/mm/nommu.c +@@ -15,6 +15,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -768,16 +769,23 @@ static void add_vma_to_mm(struct mm_struct *mm, struct vm_area_struct *vma) + */ + static void delete_vma_from_mm(struct vm_area_struct *vma) + { ++ int i; + struct address_space *mapping; + struct mm_struct *mm = vma->vm_mm; ++ struct task_struct *curr = current; + + kenter("%p", vma); + + protect_vma(vma, 0); + + mm->map_count--; +- if (mm->mmap_cache == vma) +- mm->mmap_cache = NULL; ++ for (i = 0; i < VMACACHE_SIZE; i++) { ++ /* if the vma is cached, invalidate the entire cache */ ++ if (curr->vmacache[i] == vma) { ++ vmacache_invalidate(curr->mm); ++ break; ++ } ++ } + + /* remove the VMA from the mapping */ + if (vma->vm_file) { +@@ -825,8 +833,8 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) + struct vm_area_struct *vma; + + /* check the cache first */ +- vma = ACCESS_ONCE(mm->mmap_cache); +- if (vma && vma->vm_start <= addr && vma->vm_end > addr) ++ vma = vmacache_find(mm, addr); ++ if (likely(vma)) + return vma; + + /* trawl the list (there may be multiple mappings in which addr +@@ -835,7 +843,7 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) + if (vma->vm_start > addr) + return NULL; + if (vma->vm_end > addr) { +- mm->mmap_cache = vma; ++ vmacache_update(addr, vma); + return vma; + } + } +@@ -874,8 +882,8 @@ static struct vm_area_struct *find_vma_exact(struct mm_struct *mm, + unsigned long end = addr + len; + + /* check the cache first */ +- vma = mm->mmap_cache; +- if (vma && vma->vm_start == addr && vma->vm_end == end) ++ vma = vmacache_find_exact(mm, addr, end); ++ if (vma) + return vma; + + /* trawl the list (there may be multiple mappings in which addr +@@ -886,7 +894,7 @@ static struct vm_area_struct *find_vma_exact(struct mm_struct *mm, + if (vma->vm_start > addr) + return NULL; + if (vma->vm_end == end) { +- mm->mmap_cache = vma; ++ vmacache_update(addr, vma); + return vma; + } + } +@@ -1897,7 +1905,7 @@ EXPORT_SYMBOL(unmap_mapping_range); + */ + int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) + { +- unsigned long free, allowed, reserve; ++ long free, allowed, reserve; + + vm_acct_memory(pages); + +@@ -1961,7 +1969,7 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) + */ + if (mm) { + reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10); +- allowed -= min(mm->total_vm / 32, reserve); ++ allowed -= min_t(long, mm->total_vm / 32, reserve); + } + + if (percpu_counter_read_positive(&vm_committed_as) < allowed) +diff --git a/mm/oom_kill.c b/mm/oom_kill.c +index 3291e82..171c00f 100644 +--- a/mm/oom_kill.c ++++ b/mm/oom_kill.c +@@ -406,6 +406,23 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order, + dump_tasks(memcg, nodemask); + } + ++/* ++ * Number of OOM killer invocations (including memcg OOM killer). ++ * Primarily used by PM freezer to check for potential races with ++ * OOM killed frozen task. ++ */ ++static atomic_t oom_kills = ATOMIC_INIT(0); ++ ++int oom_kills_count(void) ++{ ++ return atomic_read(&oom_kills); ++} ++ ++void note_oom_kill(void) ++{ ++ atomic_inc(&oom_kills); ++} ++ + #define K(x) ((x) << (PAGE_SHIFT-10)) + /* + * Must be called while holding a reference to p, which will be released upon +diff --git a/mm/page-writeback.c b/mm/page-writeback.c +index d013dba..656a549 100644 +--- a/mm/page-writeback.c ++++ b/mm/page-writeback.c +@@ -601,7 +601,7 @@ static long long pos_ratio_polynom(unsigned long setpoint, + long x; + + x = div64_s64(((s64)setpoint - (s64)dirty) << RATELIMIT_CALC_SHIFT, +- limit - setpoint + 1); ++ (limit - setpoint) | 1); + pos_ratio = x; + pos_ratio = pos_ratio * x >> RATELIMIT_CALC_SHIFT; + pos_ratio = pos_ratio * x >> RATELIMIT_CALC_SHIFT; +@@ -828,7 +828,7 @@ static unsigned long bdi_position_ratio(struct backing_dev_info *bdi, + * scale global setpoint to bdi's: + * bdi_setpoint = setpoint * bdi_thresh / thresh + */ +- x = div_u64((u64)bdi_thresh << 16, thresh + 1); ++ x = div_u64((u64)bdi_thresh << 16, thresh | 1); + bdi_setpoint = setpoint * (u64)x >> 16; + /* + * Use span=(8*write_bw) in single bdi case as indicated by +@@ -843,7 +843,7 @@ static unsigned long bdi_position_ratio(struct backing_dev_info *bdi, + + if (bdi_dirty < x_intercept - span / 4) { + pos_ratio = div64_u64(pos_ratio * (x_intercept - bdi_dirty), +- x_intercept - bdi_setpoint + 1); ++ (x_intercept - bdi_setpoint) | 1); + } else + pos_ratio /= 4; + +@@ -878,8 +878,11 @@ static void bdi_update_write_bandwidth(struct backing_dev_info *bdi, + * bw * elapsed + write_bandwidth * (period - elapsed) + * write_bandwidth = --------------------------------------------------- + * period ++ * ++ * @written may have decreased due to account_page_redirty(). ++ * Avoid underflowing @bw calculation. + */ +- bw = written - bdi->written_stamp; ++ bw = written - min(written, bdi->written_stamp); + bw *= HZ; + if (unlikely(elapsed > period)) { + do_div(bw, elapsed); +@@ -943,7 +946,7 @@ static void global_update_bandwidth(unsigned long thresh, + unsigned long now) + { + static DEFINE_SPINLOCK(dirty_lock); +- static unsigned long update_time; ++ static unsigned long update_time = INITIAL_JIFFIES; + + /* + * check locklessly first to optimize away locking for the most time +@@ -1324,9 +1327,9 @@ static inline void bdi_dirty_limits(struct backing_dev_info *bdi, + *bdi_thresh = bdi_dirty_limit(bdi, dirty_thresh); + + if (bdi_bg_thresh) +- *bdi_bg_thresh = div_u64((u64)*bdi_thresh * +- background_thresh, +- dirty_thresh); ++ *bdi_bg_thresh = dirty_thresh ? div_u64((u64)*bdi_thresh * ++ background_thresh, ++ dirty_thresh) : 0; + + /* + * In order to avoid the stacked BDI deadlock we need +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 7e7f947..0479732 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -408,7 +408,8 @@ static int destroy_compound_page(struct page *page, unsigned long order) + return bad; + } + +-static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags) ++static inline void prep_zero_page(struct page *page, unsigned int order, ++ gfp_t gfp_flags) + { + int i; + +@@ -452,7 +453,7 @@ static inline void set_page_guard_flag(struct page *page) { } + static inline void clear_page_guard_flag(struct page *page) { } + #endif + +-static inline void set_page_order(struct page *page, int order) ++static inline void set_page_order(struct page *page, unsigned int order) + { + set_page_private(page, order); + __SetPageBuddy(page); +@@ -503,21 +504,31 @@ __find_buddy_index(unsigned long page_idx, unsigned int order) + * For recording page's order, we use page_private(page). + */ + static inline int page_is_buddy(struct page *page, struct page *buddy, +- int order) ++ unsigned int order) + { + if (!pfn_valid_within(page_to_pfn(buddy))) + return 0; + +- if (page_zone_id(page) != page_zone_id(buddy)) +- return 0; +- + if (page_is_guard(buddy) && page_order(buddy) == order) { + VM_BUG_ON_PAGE(page_count(buddy) != 0, buddy); ++ ++ if (page_zone_id(page) != page_zone_id(buddy)) ++ return 0; ++ + return 1; + } + + if (PageBuddy(buddy) && page_order(buddy) == order) { + VM_BUG_ON_PAGE(page_count(buddy) != 0, buddy); ++ ++ /* ++ * zone check is done late to avoid uselessly ++ * calculating zone/node ids for pages that could ++ * never merge. ++ */ ++ if (page_zone_id(page) != page_zone_id(buddy)) ++ return 0; ++ + return 1; + } + return 0; +@@ -549,6 +560,7 @@ static inline int page_is_buddy(struct page *page, struct page *buddy, + */ + + static inline void __free_one_page(struct page *page, ++ unsigned long pfn, + struct zone *zone, unsigned int order, + int migratetype) + { +@@ -565,7 +577,7 @@ static inline void __free_one_page(struct page *page, + + VM_BUG_ON(migratetype == -1); + +- page_idx = page_to_pfn(page) & ((1 << MAX_ORDER) - 1); ++ page_idx = pfn & ((1 << MAX_ORDER) - 1); + + VM_BUG_ON_PAGE(page_idx & ((1 << order) - 1), page); + VM_BUG_ON_PAGE(bad_range(zone, page), page); +@@ -666,9 +678,12 @@ static void free_pcppages_bulk(struct zone *zone, int count, + int migratetype = 0; + int batch_free = 0; + int to_free = count; ++ unsigned long nr_scanned; + + spin_lock(&zone->lock); +- zone->pages_scanned = 0; ++ nr_scanned = zone_page_state(zone, NR_PAGES_SCANNED); ++ if (nr_scanned) ++ __mod_zone_page_state(zone, NR_PAGES_SCANNED, -nr_scanned); + + while (to_free) { + struct page *page; +@@ -700,7 +715,7 @@ static void free_pcppages_bulk(struct zone *zone, int count, + list_del(&page->lru); + mt = get_freepage_migratetype(page); + /* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */ +- __free_one_page(page, zone, 0, mt); ++ __free_one_page(page, page_to_pfn(page), zone, 0, mt); + trace_mm_page_pcpu_drain(page, 0, mt); + if (likely(!is_migrate_isolate_page(page))) { + __mod_zone_page_state(zone, NR_FREE_PAGES, 1); +@@ -712,13 +727,18 @@ static void free_pcppages_bulk(struct zone *zone, int count, + spin_unlock(&zone->lock); + } + +-static void free_one_page(struct zone *zone, struct page *page, int order, ++static void free_one_page(struct zone *zone, ++ struct page *page, unsigned long pfn, ++ unsigned int order, + int migratetype) + { ++ unsigned long nr_scanned; + spin_lock(&zone->lock); +- zone->pages_scanned = 0; ++ nr_scanned = zone_page_state(zone, NR_PAGES_SCANNED); ++ if (nr_scanned) ++ __mod_zone_page_state(zone, NR_PAGES_SCANNED, -nr_scanned); + +- __free_one_page(page, zone, order, migratetype); ++ __free_one_page(page, pfn, zone, order, migratetype); + if (unlikely(!is_migrate_isolate(migratetype))) + __mod_zone_freepage_state(zone, 1 << order, migratetype); + spin_unlock(&zone->lock); +@@ -755,15 +775,16 @@ static void __free_pages_ok(struct page *page, unsigned int order) + { + unsigned long flags; + int migratetype; ++ unsigned long pfn = page_to_pfn(page); + + if (!free_pages_prepare(page, order)) + return; + ++ migratetype = get_pfnblock_migratetype(page, pfn); + local_irq_save(flags); + __count_vm_events(PGFREE, 1 << order); +- migratetype = get_pageblock_migratetype(page); + set_freepage_migratetype(page, migratetype); +- free_one_page(page_zone(page), page, order, migratetype); ++ free_one_page(page_zone(page), page, pfn, order, migratetype); + local_irq_restore(flags); + } + +@@ -894,7 +915,7 @@ static inline int check_new_page(struct page *page) + return 0; + } + +-static int prep_new_page(struct page *page, int order, gfp_t gfp_flags) ++static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags) + { + int i; + +@@ -943,6 +964,7 @@ struct page *__rmqueue_smallest(struct zone *zone, unsigned int order, + rmv_page_order(page); + area->nr_free--; + expand(zone, page, order, current_order, area, migratetype); ++ set_freepage_migratetype(page, migratetype); + return page; + } + +@@ -1059,8 +1081,8 @@ static void change_pageblock_range(struct page *pageblock_page, + * nor move CMA pages to different free lists. We don't want unmovable pages + * to be allocated from MIGRATE_CMA areas. + * +- * Returns the new migratetype of the pageblock (or the same old migratetype +- * if it was unchanged). ++ * Returns the allocation migratetype if free pages were stolen, or the ++ * fallback migratetype if it was decided not to steal. + */ + static int try_to_steal_freepages(struct zone *zone, struct page *page, + int start_type, int fallback_type) +@@ -1069,7 +1091,9 @@ static int try_to_steal_freepages(struct zone *zone, struct page *page, + + /* + * When borrowing from MIGRATE_CMA, we need to release the excess +- * buddy pages to CMA itself. ++ * buddy pages to CMA itself. We also ensure the freepage_migratetype ++ * is set to CMA so it is returned to the correct freelist in case ++ * the page ends up being not actually allocated from the pcp lists. + */ + if (is_migrate_cma(fallback_type)) + return fallback_type; +@@ -1089,12 +1113,10 @@ static int try_to_steal_freepages(struct zone *zone, struct page *page, + + /* Claim the whole block if over half of it is free */ + if (pages >= (1 << (pageblock_order-1)) || +- page_group_by_mobility_disabled) { +- ++ page_group_by_mobility_disabled) + set_pageblock_migratetype(page, start_type); +- return start_type; +- } + ++ return start_type; + } + + return fallback_type; +@@ -1102,16 +1124,17 @@ static int try_to_steal_freepages(struct zone *zone, struct page *page, + + /* Remove an element from the buddy allocator from the fallback list */ + static inline struct page * +-__rmqueue_fallback(struct zone *zone, int order, int start_migratetype) ++__rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype) + { + struct free_area *area; +- int current_order; ++ unsigned int current_order; + struct page *page; + int migratetype, new_type, i; + + /* Find the largest possible block of pages in the other list */ +- for (current_order = MAX_ORDER-1; current_order >= order; +- --current_order) { ++ for (current_order = MAX_ORDER-1; ++ current_order >= order && current_order <= MAX_ORDER-1; ++ --current_order) { + for (i = 0;; i++) { + migratetype = fallbacks[start_migratetype][i]; + +@@ -1137,9 +1160,15 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype) + + expand(zone, page, order, current_order, area, + new_type); ++ /* The freepage_migratetype may differ from pageblock's ++ * migratetype depending on the decisions in ++ * try_to_steal_freepages. This is OK as long as it does ++ * not differ for MIGRATE_CMA type. ++ */ ++ set_freepage_migratetype(page, new_type); + + trace_mm_page_alloc_extfrag(page, order, current_order, +- start_migratetype, migratetype, new_type); ++ start_migratetype, migratetype); + + return page; + } +@@ -1185,9 +1214,9 @@ retry_reserve: + */ + static int rmqueue_bulk(struct zone *zone, unsigned int order, + unsigned long count, struct list_head *list, +- int migratetype, int cold) ++ int migratetype, bool cold) + { +- int mt = migratetype, i; ++ int i; + + spin_lock(&zone->lock); + for (i = 0; i < count; ++i) { +@@ -1204,18 +1233,12 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, + * merge IO requests if the physical pages are ordered + * properly. + */ +- if (likely(cold == 0)) ++ if (likely(!cold)) + list_add(&page->lru, list); + else + list_add_tail(&page->lru, list); +- if (IS_ENABLED(CONFIG_CMA)) { +- mt = get_pageblock_migratetype(page); +- if (!is_migrate_cma(mt) && !is_migrate_isolate(mt)) +- mt = migratetype; +- } +- set_freepage_migratetype(page, mt); + list = &page->lru; +- if (is_migrate_cma(mt)) ++ if (is_migrate_cma(get_freepage_migratetype(page))) + __mod_zone_page_state(zone, NR_FREE_CMA_PAGES, + -(1 << order)); + } +@@ -1339,7 +1362,7 @@ void mark_free_pages(struct zone *zone) + { + unsigned long pfn, max_zone_pfn; + unsigned long flags; +- int order, t; ++ unsigned int order, t; + struct list_head *curr; + + if (zone_is_empty(zone)) +@@ -1371,19 +1394,20 @@ void mark_free_pages(struct zone *zone) + + /* + * Free a 0-order page +- * cold == 1 ? free a cold page : free a hot page ++ * cold == true ? free a cold page : free a hot page + */ +-void free_hot_cold_page(struct page *page, int cold) ++void free_hot_cold_page(struct page *page, bool cold) + { + struct zone *zone = page_zone(page); + struct per_cpu_pages *pcp; + unsigned long flags; ++ unsigned long pfn = page_to_pfn(page); + int migratetype; + + if (!free_pages_prepare(page, 0)) + return; + +- migratetype = get_pageblock_migratetype(page); ++ migratetype = get_pfnblock_migratetype(page, pfn); + set_freepage_migratetype(page, migratetype); + local_irq_save(flags); + __count_vm_event(PGFREE); +@@ -1397,17 +1421,17 @@ void free_hot_cold_page(struct page *page, int cold) + */ + if (migratetype >= MIGRATE_PCPTYPES) { + if (unlikely(is_migrate_isolate(migratetype))) { +- free_one_page(zone, page, 0, migratetype); ++ free_one_page(zone, page, pfn, 0, migratetype); + goto out; + } + migratetype = MIGRATE_MOVABLE; + } + + pcp = &this_cpu_ptr(zone->pageset)->pcp; +- if (cold) +- list_add_tail(&page->lru, &pcp->lists[migratetype]); +- else ++ if (!cold) + list_add(&page->lru, &pcp->lists[migratetype]); ++ else ++ list_add_tail(&page->lru, &pcp->lists[migratetype]); + pcp->count++; + if (pcp->count >= pcp->high) { + unsigned long batch = ACCESS_ONCE(pcp->batch); +@@ -1422,7 +1446,7 @@ out: + /* + * Free a list of 0-order pages + */ +-void free_hot_cold_page_list(struct list_head *list, int cold) ++void free_hot_cold_page_list(struct list_head *list, bool cold) + { + struct page *page, *next; + +@@ -1534,12 +1558,12 @@ int split_free_page(struct page *page) + */ + static inline + struct page *buffered_rmqueue(struct zone *preferred_zone, +- struct zone *zone, int order, gfp_t gfp_flags, +- int migratetype) ++ struct zone *zone, unsigned int order, ++ gfp_t gfp_flags, int migratetype) + { + unsigned long flags; + struct page *page; +- int cold = !!(gfp_flags & __GFP_COLD); ++ bool cold = ((gfp_flags & __GFP_COLD) != 0); + + again: + if (likely(order == 0)) { +@@ -1584,10 +1608,13 @@ again: + if (!page) + goto failed; + __mod_zone_freepage_state(zone, -(1 << order), +- get_pageblock_migratetype(page)); ++ get_freepage_migratetype(page)); + } + + __mod_zone_page_state(zone, NR_ALLOC_BATCH, -(1 << order)); ++ if (zone_page_state(zone, NR_ALLOC_BATCH) == 0 && ++ !zone_is_fair_depleted(zone)) ++ zone_set_flag(zone, ZONE_FAIR_DEPLETED); + + __count_zone_vm_events(PGALLOC, zone, 1 << order); + zone_statistics(preferred_zone, zone, gfp_flags); +@@ -1684,12 +1711,12 @@ static inline bool should_fail_alloc_page(gfp_t gfp_mask, unsigned int order) + * Return true if free pages are above 'mark'. This takes into account the order + * of the allocation. + */ +-static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark, +- int classzone_idx, int alloc_flags, long free_pages) ++static bool __zone_watermark_ok(struct zone *z, unsigned int order, ++ unsigned long mark, int classzone_idx, int alloc_flags, ++ long free_pages) + { + /* free_pages my go negative - that's OK */ + long min = mark; +- long lowmem_reserve = z->lowmem_reserve[classzone_idx]; + int o; + long free_cma = 0; + +@@ -1704,7 +1731,7 @@ static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark, + free_cma = zone_page_state(z, NR_FREE_CMA_PAGES); + #endif + +- if (free_pages - free_cma <= min + lowmem_reserve) ++ if (free_pages - free_cma <= min + z->lowmem_reserve[classzone_idx]) + return false; + for (o = 0; o < order; o++) { + /* At the next order, this order's pages become unavailable */ +@@ -1719,15 +1746,15 @@ static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark, + return true; + } + +-bool zone_watermark_ok(struct zone *z, int order, unsigned long mark, ++bool zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark, + int classzone_idx, int alloc_flags) + { + return __zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags, + zone_page_state(z, NR_FREE_PAGES)); + } + +-bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark, +- int classzone_idx, int alloc_flags) ++bool zone_watermark_ok_safe(struct zone *z, unsigned int order, ++ unsigned long mark, int classzone_idx, int alloc_flags) + { + long free_pages = zone_page_state(z, NR_FREE_PAGES); + +@@ -1869,7 +1896,7 @@ static void __paginginit init_zone_allows_reclaim(int nid) + { + int i; + +- for_each_online_node(i) ++ for_each_node_state(i, N_MEMORY) + if (node_distance(nid, i) <= RECLAIM_DISTANCE) + node_set(i, NODE_DATA(nid)->reclaim_nodes); + else +@@ -1912,6 +1939,18 @@ static inline void init_zone_allows_reclaim(int nid) + } + #endif /* CONFIG_NUMA */ + ++static void reset_alloc_batches(struct zone *preferred_zone) ++{ ++ struct zone *zone = preferred_zone->zone_pgdat->node_zones; ++ ++ do { ++ mod_zone_page_state(zone, NR_ALLOC_BATCH, ++ high_wmark_pages(zone) - low_wmark_pages(zone) - ++ atomic_long_read(&zone->vm_stat[NR_ALLOC_BATCH])); ++ zone_clear_flag(zone, ZONE_FAIR_DEPLETED); ++ } while (zone++ != preferred_zone); ++} ++ + /* + * get_page_from_freelist goes through the zonelist trying to allocate + * a page. +@@ -1919,18 +1958,22 @@ static inline void init_zone_allows_reclaim(int nid) + static struct page * + get_page_from_freelist(gfp_t gfp_mask, nodemask_t *nodemask, unsigned int order, + struct zonelist *zonelist, int high_zoneidx, int alloc_flags, +- struct zone *preferred_zone, int migratetype) ++ struct zone *preferred_zone, int classzone_idx, int migratetype) + { + struct zoneref *z; + struct page *page = NULL; +- int classzone_idx; + struct zone *zone; + nodemask_t *allowednodes = NULL;/* zonelist_cache approximation */ + int zlc_active = 0; /* set if using zonelist_cache */ + int did_zlc_setup = 0; /* just call zlc_setup() one time */ ++ bool consider_zone_dirty = (alloc_flags & ALLOC_WMARK_LOW) && ++ (gfp_mask & __GFP_WRITE); ++ int nr_fair_skipped = 0; ++ bool zonelist_rescan; + +- classzone_idx = zone_idx(preferred_zone); + zonelist_scan: ++ zonelist_rescan = false; ++ + /* + * Scan zonelist, looking for a zone with enough free. + * See also __cpuset_node_allowed_softwall() comment in kernel/cpuset.c. +@@ -1942,12 +1985,10 @@ zonelist_scan: + if (IS_ENABLED(CONFIG_NUMA) && zlc_active && + !zlc_zone_worth_trying(zonelist, z, allowednodes)) + continue; +- if ((alloc_flags & ALLOC_CPUSET) && ++ if (cpusets_enabled() && ++ (alloc_flags & ALLOC_CPUSET) && + !cpuset_zone_allowed_softwall(zone, gfp_mask)) + continue; +- BUILD_BUG_ON(ALLOC_NO_WATERMARKS < NR_WMARK); +- if (unlikely(alloc_flags & ALLOC_NO_WATERMARKS)) +- goto try_this_zone; + /* + * Distribute pages in proportion to the individual + * zone size to ensure fair page aging. The zone a +@@ -1956,9 +1997,11 @@ zonelist_scan: + */ + if (alloc_flags & ALLOC_FAIR) { + if (!zone_local(preferred_zone, zone)) ++ break; ++ if (zone_is_fair_depleted(zone)) { ++ nr_fair_skipped++; + continue; +- if (zone_page_state(zone, NR_ALLOC_BATCH) <= 0) +- continue; ++ } + } + /* + * When allocating a page cache page for writing, we +@@ -1986,15 +2029,19 @@ zonelist_scan: + * will require awareness of zones in the + * dirty-throttling and the flusher threads. + */ +- if ((alloc_flags & ALLOC_WMARK_LOW) && +- (gfp_mask & __GFP_WRITE) && !zone_dirty_ok(zone)) +- goto this_zone_full; ++ if (consider_zone_dirty && !zone_dirty_ok(zone)) ++ continue; + + mark = zone->watermark[alloc_flags & ALLOC_WMARK_MASK]; + if (!zone_watermark_ok(zone, order, mark, + classzone_idx, alloc_flags)) { + int ret; + ++ /* Checked here to keep the fast path fast */ ++ BUILD_BUG_ON(ALLOC_NO_WATERMARKS < NR_WMARK); ++ if (alloc_flags & ALLOC_NO_WATERMARKS) ++ goto try_this_zone; ++ + if (IS_ENABLED(CONFIG_NUMA) && + !did_zlc_setup && nr_online_nodes > 1) { + /* +@@ -2056,17 +2103,11 @@ try_this_zone: + if (page) + break; + this_zone_full: +- if (IS_ENABLED(CONFIG_NUMA)) ++ if (IS_ENABLED(CONFIG_NUMA) && zlc_active) + zlc_mark_zone_full(zonelist, z); + } + +- if (unlikely(IS_ENABLED(CONFIG_NUMA) && page == NULL && zlc_active)) { +- /* Disable zlc cache for second zonelist scan */ +- zlc_active = 0; +- goto zonelist_scan; +- } +- +- if (page) ++ if (page) { + /* + * page->pfmemalloc is set when ALLOC_NO_WATERMARKS was + * necessary to allocate the page. The expectation is +@@ -2075,8 +2116,37 @@ this_zone_full: + * for !PFMEMALLOC purposes. + */ + page->pfmemalloc = !!(alloc_flags & ALLOC_NO_WATERMARKS); ++ return page; ++ } + +- return page; ++ /* ++ * The first pass makes sure allocations are spread fairly within the ++ * local node. However, the local node might have free pages left ++ * after the fairness batches are exhausted, and remote zones haven't ++ * even been considered yet. Try once more without fairness, and ++ * include remote zones now, before entering the slowpath and waking ++ * kswapd: prefer spilling to a remote zone over swapping locally. ++ */ ++ if (alloc_flags & ALLOC_FAIR) { ++ alloc_flags &= ~ALLOC_FAIR; ++ if (nr_fair_skipped) { ++ zonelist_rescan = true; ++ reset_alloc_batches(preferred_zone); ++ } ++ if (nr_online_nodes > 1) ++ zonelist_rescan = true; ++ } ++ ++ if (unlikely(IS_ENABLED(CONFIG_NUMA) && zlc_active)) { ++ /* Disable zlc cache for second zonelist scan */ ++ zlc_active = 0; ++ zonelist_rescan = true; ++ } ++ ++ if (zonelist_rescan) ++ goto zonelist_scan; ++ ++ return NULL; + } + + /* +@@ -2185,7 +2255,7 @@ static inline struct page * + __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, enum zone_type high_zoneidx, + nodemask_t *nodemask, struct zone *preferred_zone, +- int migratetype) ++ int classzone_idx, int migratetype) + { + struct page *page; + +@@ -2196,6 +2266,14 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order, + } + + /* ++ * PM-freezer should be notified that there might be an OOM killer on ++ * its way to kill and wake somebody up. This is too early and we might ++ * end up not killing anything but false positives are acceptable. ++ * See freeze_processes. ++ */ ++ note_oom_kill(); ++ ++ /* + * Go through the zonelist yet one more time, keep very high watermark + * here, this is only to catch a parallel oom killing, we must fail if + * we're still under heavy pressure. +@@ -2203,7 +2281,7 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order, + page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, + order, zonelist, high_zoneidx, + ALLOC_WMARK_HIGH|ALLOC_CPUSET, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, migratetype); + if (page) + goto out; + +@@ -2238,7 +2316,7 @@ static struct page * + __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, enum zone_type high_zoneidx, + nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone, +- int migratetype, bool sync_migration, ++ int classzone_idx, int migratetype, enum migrate_mode mode, + bool *contended_compaction, bool *deferred_compaction, + unsigned long *did_some_progress) + { +@@ -2252,7 +2330,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, + + current->flags |= PF_MEMALLOC; + *did_some_progress = try_to_compact_pages(zonelist, order, gfp_mask, +- nodemask, sync_migration, ++ nodemask, mode, + contended_compaction); + current->flags &= ~PF_MEMALLOC; + +@@ -2266,7 +2344,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, + page = get_page_from_freelist(gfp_mask, nodemask, + order, zonelist, high_zoneidx, + alloc_flags & ~ALLOC_NO_WATERMARKS, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, migratetype); + if (page) { + preferred_zone->compact_blockskip_flush = false; + compaction_defer_reset(preferred_zone, order, true); +@@ -2285,7 +2363,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, + * As async compaction considers a subset of pageblocks, only + * defer if the failure was a sync compaction failure. + */ +- if (sync_migration) ++ if (mode != MIGRATE_ASYNC) + defer_compaction(preferred_zone, order); + + cond_resched(); +@@ -2298,9 +2376,9 @@ static inline struct page * + __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, enum zone_type high_zoneidx, + nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone, +- int migratetype, bool sync_migration, +- bool *contended_compaction, bool *deferred_compaction, +- unsigned long *did_some_progress) ++ int classzone_idx, int migratetype, ++ enum migrate_mode mode, bool *contended_compaction, ++ bool *deferred_compaction, unsigned long *did_some_progress) + { + return NULL; + } +@@ -2339,7 +2417,7 @@ static inline struct page * + __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, enum zone_type high_zoneidx, + nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone, +- int migratetype, unsigned long *did_some_progress) ++ int classzone_idx, int migratetype, unsigned long *did_some_progress) + { + struct page *page = NULL; + bool drained = false; +@@ -2357,7 +2435,8 @@ retry: + page = get_page_from_freelist(gfp_mask, nodemask, order, + zonelist, high_zoneidx, + alloc_flags & ~ALLOC_NO_WATERMARKS, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, ++ migratetype); + + /* + * If an allocation failed after direct reclaim, it could be because +@@ -2380,14 +2459,14 @@ static inline struct page * + __alloc_pages_high_priority(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, enum zone_type high_zoneidx, + nodemask_t *nodemask, struct zone *preferred_zone, +- int migratetype) ++ int classzone_idx, int migratetype) + { + struct page *page; + + do { + page = get_page_from_freelist(gfp_mask, nodemask, order, + zonelist, high_zoneidx, ALLOC_NO_WATERMARKS, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, migratetype); + + if (!page && gfp_mask & __GFP_NOFAIL) + wait_iff_congested(preferred_zone, BLK_RW_ASYNC, HZ/50); +@@ -2396,28 +2475,6 @@ __alloc_pages_high_priority(gfp_t gfp_mask, unsigned int order, + return page; + } + +-static void reset_alloc_batches(struct zonelist *zonelist, +- enum zone_type high_zoneidx, +- struct zone *preferred_zone) +-{ +- struct zoneref *z; +- struct zone *zone; +- +- for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) { +- /* +- * Only reset the batches of zones that were actually +- * considered in the fairness pass, we don't want to +- * trash fairness information for zones that are not +- * actually part of this zonelist's round-robin cycle. +- */ +- if (!zone_local(preferred_zone, zone)) +- continue; +- mod_zone_page_state(zone, NR_ALLOC_BATCH, +- high_wmark_pages(zone) - low_wmark_pages(zone) - +- atomic_long_read(&zone->vm_stat[NR_ALLOC_BATCH])); +- } +-} +- + static void wake_all_kswapds(unsigned int order, + struct zonelist *zonelist, + enum zone_type high_zoneidx, +@@ -2434,7 +2491,7 @@ static inline int + gfp_to_alloc_flags(gfp_t gfp_mask) + { + int alloc_flags = ALLOC_WMARK_MIN | ALLOC_CPUSET; +- const gfp_t wait = gfp_mask & __GFP_WAIT; ++ const bool atomic = !(gfp_mask & (__GFP_WAIT | __GFP_NO_KSWAPD)); + + /* __GFP_HIGH is assumed to be the same as ALLOC_HIGH to save a branch. */ + BUILD_BUG_ON(__GFP_HIGH != (__force gfp_t) ALLOC_HIGH); +@@ -2443,20 +2500,20 @@ gfp_to_alloc_flags(gfp_t gfp_mask) + * The caller may dip into page reserves a bit more if the caller + * cannot run direct reclaim, or if the caller has realtime scheduling + * policy or is asking for __GFP_HIGH memory. GFP_ATOMIC requests will +- * set both ALLOC_HARDER (!wait) and ALLOC_HIGH (__GFP_HIGH). ++ * set both ALLOC_HARDER (atomic == true) and ALLOC_HIGH (__GFP_HIGH). + */ + alloc_flags |= (__force int) (gfp_mask & __GFP_HIGH); + +- if (!wait) { ++ if (atomic) { + /* +- * Not worth trying to allocate harder for +- * __GFP_NOMEMALLOC even if it can't schedule. ++ * Not worth trying to allocate harder for __GFP_NOMEMALLOC even ++ * if it can't schedule. + */ +- if (!(gfp_mask & __GFP_NOMEMALLOC)) ++ if (!(gfp_mask & __GFP_NOMEMALLOC)) + alloc_flags |= ALLOC_HARDER; + /* +- * Ignore cpuset if GFP_ATOMIC (!wait) rather than fail alloc. +- * See also cpuset_zone_allowed() comment in kernel/cpuset.c. ++ * Ignore cpuset mems for GFP_ATOMIC rather than fail, see the ++ * comment for __cpuset_node_allowed_softwall(). + */ + alloc_flags &= ~ALLOC_CPUSET; + } else if (unlikely(rt_task(current)) && !in_interrupt()) +@@ -2488,14 +2545,14 @@ static inline struct page * + __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, enum zone_type high_zoneidx, + nodemask_t *nodemask, struct zone *preferred_zone, +- int migratetype) ++ int classzone_idx, int migratetype) + { + const gfp_t wait = gfp_mask & __GFP_WAIT; + struct page *page = NULL; + int alloc_flags; + unsigned long pages_reclaimed = 0; + unsigned long did_some_progress; +- bool sync_migration = false; ++ enum migrate_mode migration_mode = MIGRATE_ASYNC; + bool deferred_compaction = false; + bool contended_compaction = false; + +@@ -2537,15 +2594,19 @@ restart: + * Find the true preferred zone if the allocation is unconstrained by + * cpusets. + */ +- if (!(alloc_flags & ALLOC_CPUSET) && !nodemask) +- first_zones_zonelist(zonelist, high_zoneidx, NULL, +- &preferred_zone); ++ if (!(alloc_flags & ALLOC_CPUSET) && !nodemask) { ++ struct zoneref *preferred_zoneref; ++ preferred_zoneref = first_zones_zonelist(zonelist, high_zoneidx, ++ NULL, ++ &preferred_zone); ++ classzone_idx = zonelist_zone_idx(preferred_zoneref); ++ } + + rebalance: + /* This is the last chance, in general, before the goto nopage. */ + page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist, + high_zoneidx, alloc_flags & ~ALLOC_NO_WATERMARKS, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, migratetype); + if (page) + goto got_pg; + +@@ -2560,7 +2621,7 @@ rebalance: + + page = __alloc_pages_high_priority(gfp_mask, order, + zonelist, high_zoneidx, nodemask, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, migratetype); + if (page) { + goto got_pg; + } +@@ -2589,17 +2650,16 @@ rebalance: + * Try direct compaction. The first pass is asynchronous. Subsequent + * attempts after direct reclaim are synchronous + */ +- page = __alloc_pages_direct_compact(gfp_mask, order, +- zonelist, high_zoneidx, +- nodemask, +- alloc_flags, preferred_zone, +- migratetype, sync_migration, +- &contended_compaction, ++ page = __alloc_pages_direct_compact(gfp_mask, order, zonelist, ++ high_zoneidx, nodemask, alloc_flags, ++ preferred_zone, ++ classzone_idx, migratetype, ++ migration_mode, &contended_compaction, + &deferred_compaction, + &did_some_progress); + if (page) + goto got_pg; +- sync_migration = true; ++ migration_mode = MIGRATE_SYNC_LIGHT; + + /* + * If compaction is deferred for high-order allocations, it is because +@@ -2616,7 +2676,8 @@ rebalance: + zonelist, high_zoneidx, + nodemask, + alloc_flags, preferred_zone, +- migratetype, &did_some_progress); ++ classzone_idx, migratetype, ++ &did_some_progress); + if (page) + goto got_pg; + +@@ -2635,7 +2696,7 @@ rebalance: + page = __alloc_pages_may_oom(gfp_mask, order, + zonelist, high_zoneidx, + nodemask, preferred_zone, +- migratetype); ++ classzone_idx, migratetype); + if (page) + goto got_pg; + +@@ -2674,12 +2735,11 @@ rebalance: + * direct reclaim and reclaim/compaction depends on compaction + * being called after reclaim so call directly if necessary + */ +- page = __alloc_pages_direct_compact(gfp_mask, order, +- zonelist, high_zoneidx, +- nodemask, +- alloc_flags, preferred_zone, +- migratetype, sync_migration, +- &contended_compaction, ++ page = __alloc_pages_direct_compact(gfp_mask, order, zonelist, ++ high_zoneidx, nodemask, alloc_flags, ++ preferred_zone, ++ classzone_idx, migratetype, ++ migration_mode, &contended_compaction, + &deferred_compaction, + &did_some_progress); + if (page) +@@ -2705,11 +2765,13 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, + { + enum zone_type high_zoneidx = gfp_zone(gfp_mask); + struct zone *preferred_zone; ++ struct zoneref *preferred_zoneref; + struct page *page = NULL; + int migratetype = allocflags_to_migratetype(gfp_mask); + unsigned int cpuset_mems_cookie; + int alloc_flags = ALLOC_WMARK_LOW|ALLOC_CPUSET|ALLOC_FAIR; + struct mem_cgroup *memcg = NULL; ++ int classzone_idx; + + gfp_mask &= gfp_allowed_mask; + +@@ -2736,42 +2798,26 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, + return NULL; + + retry_cpuset: +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + + /* The preferred zone is used for statistics later */ +- first_zones_zonelist(zonelist, high_zoneidx, ++ preferred_zoneref = first_zones_zonelist(zonelist, high_zoneidx, + nodemask ? : &cpuset_current_mems_allowed, + &preferred_zone); + if (!preferred_zone) + goto out; ++ classzone_idx = zonelist_zone_idx(preferred_zoneref); + + #ifdef CONFIG_CMA + if (allocflags_to_migratetype(gfp_mask) == MIGRATE_MOVABLE) + alloc_flags |= ALLOC_CMA; + #endif +-retry: + /* First allocation attempt */ + page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, order, + zonelist, high_zoneidx, alloc_flags, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, migratetype); + if (unlikely(!page)) { + /* +- * The first pass makes sure allocations are spread +- * fairly within the local node. However, the local +- * node might have free pages left after the fairness +- * batches are exhausted, and remote zones haven't +- * even been considered yet. Try once more without +- * fairness, and include remote zones now, before +- * entering the slowpath and waking kswapd: prefer +- * spilling to a remote zone over swapping locally. +- */ +- if (alloc_flags & ALLOC_FAIR) { +- reset_alloc_batches(zonelist, high_zoneidx, +- preferred_zone); +- alloc_flags &= ~ALLOC_FAIR; +- goto retry; +- } +- /* + * Runtime PM, block IO and its error handling path + * can deadlock because I/O on the device might not + * complete. +@@ -2779,7 +2825,7 @@ retry: + gfp_mask = memalloc_noio_flags(gfp_mask); + page = __alloc_pages_slowpath(gfp_mask, order, + zonelist, high_zoneidx, nodemask, +- preferred_zone, migratetype); ++ preferred_zone, classzone_idx, migratetype); + } + + trace_mm_page_alloc(page, order, gfp_mask, migratetype); +@@ -2791,7 +2837,7 @@ out: + * the mask is being updated. If a page allocation is about to fail, + * check if the cpuset changed during allocation and if so, retry. + */ +- if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) ++ if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie))) + goto retry_cpuset; + + memcg_kmem_commit_charge(page, memcg, order); +@@ -2830,7 +2876,7 @@ void __free_pages(struct page *page, unsigned int order) + { + if (put_page_testzero(page)) { + if (order == 0) +- free_hot_cold_page(page, 0); ++ free_hot_cold_page(page, false); + else + __free_pages_ok(page, order); + } +@@ -3059,9 +3105,9 @@ bool skip_free_areas_node(unsigned int flags, int nid) + goto out; + + do { +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + ret = !node_isset(nid, cpuset_current_mems_allowed); +- } while (!put_mems_allowed(cpuset_mems_cookie)); ++ } while (read_mems_allowed_retry(cpuset_mems_cookie)); + out: + return ret; + } +@@ -3214,12 +3260,12 @@ void show_free_areas(unsigned int filter) + K(zone_page_state(zone, NR_BOUNCE)), + K(zone_page_state(zone, NR_FREE_CMA_PAGES)), + K(zone_page_state(zone, NR_WRITEBACK_TEMP)), +- zone->pages_scanned, ++ K(zone_page_state(zone, NR_PAGES_SCANNED)), + (!zone_reclaimable(zone) ? "yes" : "no") + ); + printk("lowmem_reserve[]:"); + for (i = 0; i < MAX_NR_ZONES; i++) +- printk(" %lu", zone->lowmem_reserve[i]); ++ printk(" %ld", zone->lowmem_reserve[i]); + printk("\n"); + } + +@@ -4107,7 +4153,7 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, + + static void __meminit zone_init_free_lists(struct zone *zone) + { +- int order, t; ++ unsigned int order, t; + for_each_migratetype_order(order, t) { + INIT_LIST_HEAD(&zone->free_area[order].free_list[t]); + zone->free_area[order].nr_free = 0; +@@ -4933,7 +4979,8 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size, + + pgdat->node_id = nid; + pgdat->node_start_pfn = node_start_pfn; +- init_zone_allows_reclaim(nid); ++ if (node_state(nid, N_MEMORY)) ++ init_zone_allows_reclaim(nid); + #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP + get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); + #endif +@@ -5546,7 +5593,7 @@ static void calculate_totalreserve_pages(void) + for_each_online_pgdat(pgdat) { + for (i = 0; i < MAX_NR_ZONES; i++) { + struct zone *zone = pgdat->node_zones + i; +- unsigned long max = 0; ++ long max = 0; + + /* Find valid and maximum lowmem_reserve in the zone */ + for (j = i; j < MAX_NR_ZONES; j++) { +@@ -5661,9 +5708,8 @@ static void __setup_per_zone_wmarks(void) + zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) + (tmp >> 1); + + __mod_zone_page_state(zone, NR_ALLOC_BATCH, +- high_wmark_pages(zone) - +- low_wmark_pages(zone) - +- zone_page_state(zone, NR_ALLOC_BATCH)); ++ high_wmark_pages(zone) - low_wmark_pages(zone) - ++ atomic_long_read(&zone->vm_stat[NR_ALLOC_BATCH])); + + setup_zone_migrate_reserve(zone); + spin_unlock_irqrestore(&zone->lock, flags); +@@ -6035,17 +6081,16 @@ static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn) + * @end_bitidx: The last bit of interest + * returns pageblock_bits flags + */ +-unsigned long get_pageblock_flags_mask(struct page *page, ++unsigned long get_pfnblock_flags_mask(struct page *page, unsigned long pfn, + unsigned long end_bitidx, + unsigned long mask) + { + struct zone *zone; + unsigned long *bitmap; +- unsigned long pfn, bitidx, word_bitidx; ++ unsigned long bitidx, word_bitidx; + unsigned long word; + + zone = page_zone(page); +- pfn = page_to_pfn(page); + bitmap = get_pageblock_bitmap(zone, pfn); + bitidx = pfn_to_bitidx(zone, pfn); + word_bitidx = bitidx / BITS_PER_LONG; +@@ -6057,25 +6102,25 @@ unsigned long get_pageblock_flags_mask(struct page *page, + } + + /** +- * set_pageblock_flags_mask - Set the requested group of flags for a pageblock_nr_pages block of pages ++ * set_pfnblock_flags_mask - Set the requested group of flags for a pageblock_nr_pages block of pages + * @page: The page within the block of interest + * @start_bitidx: The first bit of interest + * @end_bitidx: The last bit of interest + * @flags: The flags to set + */ +-void set_pageblock_flags_mask(struct page *page, unsigned long flags, ++void set_pfnblock_flags_mask(struct page *page, unsigned long flags, ++ unsigned long pfn, + unsigned long end_bitidx, + unsigned long mask) + { + struct zone *zone; + unsigned long *bitmap; +- unsigned long pfn, bitidx, word_bitidx; ++ unsigned long bitidx, word_bitidx; + unsigned long old_word, word; + + BUILD_BUG_ON(NR_PAGEBLOCK_BITS != 4); + + zone = page_zone(page); +- pfn = page_to_pfn(page); + bitmap = get_pageblock_bitmap(zone, pfn); + bitidx = pfn_to_bitidx(zone, pfn); + word_bitidx = bitidx / BITS_PER_LONG; +@@ -6253,7 +6298,7 @@ static int __alloc_contig_migrate_range(struct compact_control *cc, + cc->nr_migratepages -= nr_reclaimed; + + ret = migrate_pages(&cc->migratepages, alloc_migrate_target, +- 0, MIGRATE_SYNC, MR_CMA); ++ NULL, 0, cc->mode, MR_CMA); + } + if (ret < 0) { + putback_movable_pages(&cc->migratepages); +@@ -6292,7 +6337,7 @@ int alloc_contig_range(unsigned long start, unsigned long end, + .nr_migratepages = 0, + .order = -1, + .zone = page_zone(pfn_to_page(start)), +- .sync = true, ++ .mode = MIGRATE_SYNC, + .ignore_skip_hint = true, + }; + INIT_LIST_HEAD(&cc.migratepages); +@@ -6447,7 +6492,7 @@ __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn) + { + struct page *page; + struct zone *zone; +- int order, i; ++ unsigned int order, i; + unsigned long pfn; + unsigned long flags; + /* find the first valid pfn */ +@@ -6499,7 +6544,7 @@ bool is_free_buddy_page(struct page *page) + struct zone *zone = page_zone(page); + unsigned long pfn = page_to_pfn(page); + unsigned long flags; +- int order; ++ unsigned int order; + + spin_lock_irqsave(&zone->lock, flags); + for (order = 0; order < MAX_ORDER; order++) { +diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c +index cfd1628..0e9a319 100644 +--- a/mm/page_cgroup.c ++++ b/mm/page_cgroup.c +@@ -171,6 +171,7 @@ static void free_page_cgroup(void *addr) + sizeof(struct page_cgroup) * PAGES_PER_SECTION; + + BUG_ON(PageReserved(page)); ++ kmemleak_free(addr); + free_pages_exact(addr, table_size); + } + } +diff --git a/mm/pagewalk.c b/mm/pagewalk.c +index 2beeabf..9056d22 100644 +--- a/mm/pagewalk.c ++++ b/mm/pagewalk.c +@@ -199,7 +199,10 @@ int walk_page_range(unsigned long addr, unsigned long end, + */ + if ((vma->vm_start <= addr) && + (vma->vm_flags & VM_PFNMAP)) { +- next = vma->vm_end; ++ if (walk->pte_hole) ++ err = walk->pte_hole(addr, next, walk); ++ if (err) ++ break; + pgd = pgd_offset(walk->mm, next); + continue; + } +diff --git a/mm/percpu-vm.c b/mm/percpu-vm.c +index 3707c71..5110816 100644 +--- a/mm/percpu-vm.c ++++ b/mm/percpu-vm.c +@@ -108,7 +108,7 @@ static int pcpu_alloc_pages(struct pcpu_chunk *chunk, + int page_start, int page_end) + { + const gfp_t gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD; +- unsigned int cpu; ++ unsigned int cpu, tcpu; + int i; + + for_each_possible_cpu(cpu) { +@@ -116,14 +116,23 @@ static int pcpu_alloc_pages(struct pcpu_chunk *chunk, + struct page **pagep = &pages[pcpu_page_idx(cpu, i)]; + + *pagep = alloc_pages_node(cpu_to_node(cpu), gfp, 0); +- if (!*pagep) { +- pcpu_free_pages(chunk, pages, populated, +- page_start, page_end); +- return -ENOMEM; +- } ++ if (!*pagep) ++ goto err; + } + } + return 0; ++ ++err: ++ while (--i >= page_start) ++ __free_page(pages[pcpu_page_idx(cpu, i)]); ++ ++ for_each_possible_cpu(tcpu) { ++ if (tcpu == cpu) ++ break; ++ for (i = page_start; i < page_end; i++) ++ __free_page(pages[pcpu_page_idx(tcpu, i)]); ++ } ++ return -ENOMEM; + } + + /** +@@ -263,6 +272,7 @@ err: + __pcpu_unmap_pages(pcpu_chunk_addr(chunk, tcpu, page_start), + page_end - page_start); + } ++ pcpu_post_unmap_tlb_flush(chunk, page_start, page_end); + return err; + } + +diff --git a/mm/readahead.c b/mm/readahead.c +index 0de2360..0ca36a7 100644 +--- a/mm/readahead.c ++++ b/mm/readahead.c +@@ -8,9 +8,7 @@ + */ + + #include +-#include + #include +-#include + #include + #include + #include +@@ -20,6 +18,8 @@ + #include + #include + ++#include "internal.h" ++ + /* + * Initialise a struct file's readahead state. Assumes that the caller has + * memset *ra to zero. +@@ -149,8 +149,7 @@ out: + * + * Returns the number of pages requested, or the maximum amount of I/O allowed. + */ +-static int +-__do_page_cache_readahead(struct address_space *mapping, struct file *filp, ++int __do_page_cache_readahead(struct address_space *mapping, struct file *filp, + pgoff_t offset, unsigned long nr_to_read, + unsigned long lookahead_size) + { +@@ -179,7 +178,7 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp, + rcu_read_lock(); + page = radix_tree_lookup(&mapping->page_tree, page_offset); + rcu_read_unlock(); +- if (page) ++ if (page && !radix_tree_exceptional_entry(page)) + continue; + + page = page_cache_alloc_readahead(mapping); +@@ -233,28 +232,14 @@ int force_page_cache_readahead(struct address_space *mapping, struct file *filp, + return 0; + } + ++#define MAX_READAHEAD ((512*4096)/PAGE_CACHE_SIZE) + /* + * Given a desired number of PAGE_CACHE_SIZE readahead pages, return a + * sensible upper limit. + */ + unsigned long max_sane_readahead(unsigned long nr) + { +- return min(nr, (node_page_state(numa_node_id(), NR_INACTIVE_FILE) +- + node_page_state(numa_node_id(), NR_FREE_PAGES)) / 2); +-} +- +-/* +- * Submit IO for the read-ahead request in file_ra_state. +- */ +-unsigned long ra_submit(struct file_ra_state *ra, +- struct address_space *mapping, struct file *filp) +-{ +- int actual; +- +- actual = __do_page_cache_readahead(mapping, filp, +- ra->start, ra->size, ra->async_size); +- +- return actual; ++ return min(nr, MAX_READAHEAD); + } + + /* +@@ -347,7 +332,7 @@ static pgoff_t count_history_pages(struct address_space *mapping, + pgoff_t head; + + rcu_read_lock(); +- head = radix_tree_prev_hole(&mapping->page_tree, offset - 1, max); ++ head = page_cache_prev_hole(mapping, offset - 1, max); + rcu_read_unlock(); + + return offset - 1 - head; +@@ -427,7 +412,7 @@ ondemand_readahead(struct address_space *mapping, + pgoff_t start; + + rcu_read_lock(); +- start = radix_tree_next_hole(&mapping->page_tree, offset+1,max); ++ start = page_cache_next_hole(mapping, offset + 1, max); + rcu_read_unlock(); + + if (!start || start - offset > max) +diff --git a/mm/rmap.c b/mm/rmap.c +index cdbd312..cab9820 100644 +--- a/mm/rmap.c ++++ b/mm/rmap.c +@@ -274,6 +274,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma) + { + struct anon_vma_chain *avc; + struct anon_vma *anon_vma; ++ int error; + + /* Don't bother if the parent process has no anon_vma here. */ + if (!pvma->anon_vma) +@@ -283,8 +284,9 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma) + * First, attach the new VMA to the parent VMA's anon_vmas, + * so rmap can find non-COWed pages in child processes. + */ +- if (anon_vma_clone(vma, pvma)) +- return -ENOMEM; ++ error = anon_vma_clone(vma, pvma); ++ if (error) ++ return error; + + /* Then add our own anon_vma. */ + anon_vma = anon_vma_alloc(); +diff --git a/mm/shmem.c b/mm/shmem.c +index ff85863..85d8a1a 100644 +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -243,19 +243,17 @@ static int shmem_radix_tree_replace(struct address_space *mapping, + pgoff_t index, void *expected, void *replacement) + { + void **pslot; +- void *item = NULL; ++ void *item; + + VM_BUG_ON(!expected); ++ VM_BUG_ON(!replacement); + pslot = radix_tree_lookup_slot(&mapping->page_tree, index); +- if (pslot) +- item = radix_tree_deref_slot_protected(pslot, +- &mapping->tree_lock); ++ if (!pslot) ++ return -ENOENT; ++ item = radix_tree_deref_slot_protected(pslot, &mapping->tree_lock); + if (item != expected) + return -ENOENT; +- if (replacement) +- radix_tree_replace_slot(pslot, replacement); +- else +- radix_tree_delete(&mapping->page_tree, index); ++ radix_tree_replace_slot(pslot, replacement); + return 0; + } + +@@ -332,84 +330,20 @@ static void shmem_delete_from_page_cache(struct page *page, void *radswap) + } + + /* +- * Like find_get_pages, but collecting swap entries as well as pages. +- */ +-static unsigned shmem_find_get_pages_and_swap(struct address_space *mapping, +- pgoff_t start, unsigned int nr_pages, +- struct page **pages, pgoff_t *indices) +-{ +- void **slot; +- unsigned int ret = 0; +- struct radix_tree_iter iter; +- +- if (!nr_pages) +- return 0; +- +- rcu_read_lock(); +-restart: +- radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) { +- struct page *page; +-repeat: +- page = radix_tree_deref_slot(slot); +- if (unlikely(!page)) +- continue; +- if (radix_tree_exception(page)) { +- if (radix_tree_deref_retry(page)) +- goto restart; +- /* +- * Otherwise, we must be storing a swap entry +- * here as an exceptional entry: so return it +- * without attempting to raise page count. +- */ +- goto export; +- } +- if (!page_cache_get_speculative(page)) +- goto repeat; +- +- /* Has the page moved? */ +- if (unlikely(page != *slot)) { +- page_cache_release(page); +- goto repeat; +- } +-export: +- indices[ret] = iter.index; +- pages[ret] = page; +- if (++ret == nr_pages) +- break; +- } +- rcu_read_unlock(); +- return ret; +-} +- +-/* + * Remove swap entry from radix tree, free the swap and its page cache. + */ + static int shmem_free_swap(struct address_space *mapping, + pgoff_t index, void *radswap) + { +- int error; ++ void *old; + + spin_lock_irq(&mapping->tree_lock); +- error = shmem_radix_tree_replace(mapping, index, radswap, NULL); ++ old = radix_tree_delete_item(&mapping->page_tree, index, radswap); + spin_unlock_irq(&mapping->tree_lock); +- if (!error) +- free_swap_and_cache(radix_to_swp_entry(radswap)); +- return error; +-} +- +-/* +- * Pagevec may contain swap entries, so shuffle up pages before releasing. +- */ +-static void shmem_deswap_pagevec(struct pagevec *pvec) +-{ +- int i, j; +- +- for (i = 0, j = 0; i < pagevec_count(pvec); i++) { +- struct page *page = pvec->pages[i]; +- if (!radix_tree_exceptional_entry(page)) +- pvec->pages[j++] = page; +- } +- pvec->nr = j; ++ if (old != radswap) ++ return -ENOENT; ++ free_swap_and_cache(radix_to_swp_entry(radswap)); ++ return 0; + } + + /* +@@ -430,12 +364,12 @@ void shmem_unlock_mapping(struct address_space *mapping) + * Avoid pagevec_lookup(): find_get_pages() returns 0 as if it + * has finished, if it hits a row of PAGEVEC_SIZE swap entries. + */ +- pvec.nr = shmem_find_get_pages_and_swap(mapping, index, +- PAGEVEC_SIZE, pvec.pages, indices); ++ pvec.nr = find_get_entries(mapping, index, ++ PAGEVEC_SIZE, pvec.pages, indices); + if (!pvec.nr) + break; + index = indices[pvec.nr - 1] + 1; +- shmem_deswap_pagevec(&pvec); ++ pagevec_remove_exceptionals(&pvec); + check_move_unevictable_pages(pvec.pages, pvec.nr); + pagevec_release(&pvec); + cond_resched(); +@@ -467,9 +401,9 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, + pagevec_init(&pvec, 0); + index = start; + while (index < end) { +- pvec.nr = shmem_find_get_pages_and_swap(mapping, index, +- min(end - index, (pgoff_t)PAGEVEC_SIZE), +- pvec.pages, indices); ++ pvec.nr = find_get_entries(mapping, index, ++ min(end - index, (pgoff_t)PAGEVEC_SIZE), ++ pvec.pages, indices); + if (!pvec.nr) + break; + mem_cgroup_uncharge_start(); +@@ -498,7 +432,7 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, + } + unlock_page(page); + } +- shmem_deswap_pagevec(&pvec); ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + mem_cgroup_uncharge_end(); + cond_resched(); +@@ -536,9 +470,10 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, + index = start; + while (index < end) { + cond_resched(); +- pvec.nr = shmem_find_get_pages_and_swap(mapping, index, ++ ++ pvec.nr = find_get_entries(mapping, index, + min(end - index, (pgoff_t)PAGEVEC_SIZE), +- pvec.pages, indices); ++ pvec.pages, indices); + if (!pvec.nr) { + /* If all gone or hole-punch or unfalloc, we're done */ + if (index == start || end != -1) +@@ -581,7 +516,7 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend, + } + unlock_page(page); + } +- shmem_deswap_pagevec(&pvec); ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + mem_cgroup_uncharge_end(); + index++; +@@ -1088,7 +1023,7 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index, + return -EFBIG; + repeat: + swap.val = 0; +- page = find_lock_page(mapping, index); ++ page = find_lock_entry(mapping, index); + if (radix_tree_exceptional_entry(page)) { + swap = radix_to_swp_entry(page); + page = NULL; +@@ -1100,6 +1035,9 @@ repeat: + goto failed; + } + ++ if (page && sgp == SGP_WRITE) ++ mark_page_accessed(page); ++ + /* fallocated page? */ + if (page && !PageUptodate(page)) { + if (sgp != SGP_READ) +@@ -1181,6 +1119,9 @@ repeat: + shmem_recalc_inode(inode); + spin_unlock(&info->lock); + ++ if (sgp == SGP_WRITE) ++ mark_page_accessed(page); ++ + delete_from_swap_cache(page); + set_page_dirty(page); + swap_free(swap); +@@ -1205,8 +1146,11 @@ repeat: + goto decused; + } + +- SetPageSwapBacked(page); ++ __SetPageSwapBacked(page); + __set_page_locked(page); ++ if (sgp == SGP_WRITE) ++ init_page_accessed(page); ++ + error = mem_cgroup_cache_charge(page, current->mm, + gfp & GFP_RECLAIM_MASK); + if (error) +@@ -1483,6 +1427,11 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode + return inode; + } + ++bool shmem_mapping(struct address_space *mapping) ++{ ++ return mapping->backing_dev_info == &shmem_backing_dev_info; ++} ++ + #ifdef CONFIG_TMPFS + static const struct inode_operations shmem_symlink_inode_operations; + static const struct inode_operations shmem_short_symlink_operations; +@@ -1795,7 +1744,7 @@ static pgoff_t shmem_seek_hole_data(struct address_space *mapping, + pagevec_init(&pvec, 0); + pvec.nr = 1; /* start small: we may be there already */ + while (!done) { +- pvec.nr = shmem_find_get_pages_and_swap(mapping, index, ++ pvec.nr = find_get_entries(mapping, index, + pvec.nr, pvec.pages, indices); + if (!pvec.nr) { + if (whence == SEEK_DATA) +@@ -1822,7 +1771,7 @@ static pgoff_t shmem_seek_hole_data(struct address_space *mapping, + break; + } + } +- shmem_deswap_pagevec(&pvec); ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + pvec.nr = PAGEVEC_SIZE; + cond_resched(); +@@ -2143,8 +2092,10 @@ static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct + + if (new_dentry->d_inode) { + (void) shmem_unlink(new_dir, new_dentry); +- if (they_are_dirs) ++ if (they_are_dirs) { ++ drop_nlink(new_dentry->d_inode); + drop_nlink(old_dir); ++ } + } else if (they_are_dirs) { + drop_nlink(old_dir); + inc_nlink(new_dir); +diff --git a/mm/slab.c b/mm/slab.c +index 6dd8d5f..0b1c2a5 100644 +--- a/mm/slab.c ++++ b/mm/slab.c +@@ -2189,7 +2189,8 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) + int + __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) + { +- size_t left_over, freelist_size, ralign; ++ size_t left_over, freelist_size; ++ size_t ralign = BYTES_PER_WORD; + gfp_t gfp; + int err; + size_t size = cachep->size; +@@ -2222,14 +2223,6 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) + size &= ~(BYTES_PER_WORD - 1); + } + +- /* +- * Redzoning and user store require word alignment or possibly larger. +- * Note this will be overridden by architecture or caller mandated +- * alignment if either is greater than BYTES_PER_WORD. +- */ +- if (flags & SLAB_STORE_USER) +- ralign = BYTES_PER_WORD; +- + if (flags & SLAB_RED_ZONE) { + ralign = REDZONE_ALIGN; + /* If redzoning, ensure that the second redzone is suitably +@@ -3129,7 +3122,7 @@ static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags) + local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK); + + retry_cpuset: +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + zonelist = node_zonelist(slab_node(), flags); + + retry: +@@ -3187,7 +3180,7 @@ retry: + } + } + +- if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !obj)) ++ if (unlikely(!obj && read_mems_allowed_retry(cpuset_mems_cookie))) + goto retry_cpuset; + return obj; + } +diff --git a/mm/slab_common.c b/mm/slab_common.c +index 1ec3c61..f149e67 100644 +--- a/mm/slab_common.c ++++ b/mm/slab_common.c +@@ -56,7 +56,7 @@ static int kmem_cache_sanity_check(struct mem_cgroup *memcg, const char *name, + continue; + } + +-#if !defined(CONFIG_SLUB) || !defined(CONFIG_SLUB_DEBUG_ON) ++#if !defined(CONFIG_SLUB) + /* + * For simplicity, we won't check this in the list of memcg + * caches. We have control over memcg naming, and if there +diff --git a/mm/slub.c b/mm/slub.c +index 25f14ad..7611f14 100644 +--- a/mm/slub.c ++++ b/mm/slub.c +@@ -1684,7 +1684,7 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags, + return NULL; + + do { +- cpuset_mems_cookie = get_mems_allowed(); ++ cpuset_mems_cookie = read_mems_allowed_begin(); + zonelist = node_zonelist(slab_node(), flags); + for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) { + struct kmem_cache_node *n; +@@ -1696,19 +1696,17 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags, + object = get_partial_node(s, n, c, flags); + if (object) { + /* +- * Return the object even if +- * put_mems_allowed indicated that +- * the cpuset mems_allowed was +- * updated in parallel. It's a +- * harmless race between the alloc +- * and the cpuset update. ++ * Don't check read_mems_allowed_retry() ++ * here - if mems_allowed was updated in ++ * parallel, that was a harmless race ++ * between allocation and the cpuset ++ * update + */ +- put_mems_allowed(cpuset_mems_cookie); + return object; + } + } + } +- } while (!put_mems_allowed(cpuset_mems_cookie)); ++ } while (read_mems_allowed_retry(cpuset_mems_cookie)); + #endif + return NULL; + } +diff --git a/mm/swap.c b/mm/swap.c +index 0092097..d2ceddf 100644 +--- a/mm/swap.c ++++ b/mm/swap.c +@@ -67,7 +67,7 @@ static void __page_cache_release(struct page *page) + static void __put_single_page(struct page *page) + { + __page_cache_release(page); +- free_hot_cold_page(page, 0); ++ free_hot_cold_page(page, false); + } + + static void __put_compound_page(struct page *page) +@@ -469,7 +469,7 @@ static void __activate_page(struct page *page, struct lruvec *lruvec, + SetPageActive(page); + lru += LRU_ACTIVE; + add_page_to_lru_list(page, lruvec, lru); +- trace_mm_lru_activate(page, page_to_pfn(page)); ++ trace_mm_lru_activate(page); + + __count_vm_event(PGACTIVATE); + update_page_reclaim_stat(lruvec, file, 1); +@@ -581,12 +581,17 @@ void mark_page_accessed(struct page *page) + EXPORT_SYMBOL(mark_page_accessed); + + /* +- * Queue the page for addition to the LRU via pagevec. The decision on whether +- * to add the page to the [in]active [file|anon] list is deferred until the +- * pagevec is drained. This gives a chance for the caller of __lru_cache_add() +- * have the page added to the active list using mark_page_accessed(). ++ * Used to mark_page_accessed(page) that is not visible yet and when it is ++ * still safe to use non-atomic ops + */ +-void __lru_cache_add(struct page *page) ++void init_page_accessed(struct page *page) ++{ ++ if (!PageReferenced(page)) ++ __SetPageReferenced(page); ++} ++EXPORT_SYMBOL(init_page_accessed); ++ ++static void __lru_cache_add(struct page *page) + { + struct pagevec *pvec = &get_cpu_var(lru_add_pvec); + +@@ -596,11 +601,34 @@ void __lru_cache_add(struct page *page) + pagevec_add(pvec, page); + put_cpu_var(lru_add_pvec); + } +-EXPORT_SYMBOL(__lru_cache_add); ++ ++/** ++ * lru_cache_add: add a page to the page lists ++ * @page: the page to add ++ */ ++void lru_cache_add_anon(struct page *page) ++{ ++ if (PageActive(page)) ++ ClearPageActive(page); ++ __lru_cache_add(page); ++} ++ ++void lru_cache_add_file(struct page *page) ++{ ++ if (PageActive(page)) ++ ClearPageActive(page); ++ __lru_cache_add(page); ++} ++EXPORT_SYMBOL(lru_cache_add_file); + + /** + * lru_cache_add - add a page to a page list + * @page: the page to be added to the LRU. ++ * ++ * Queue the page for addition to the LRU via pagevec. The decision on whether ++ * to add the page to the [in]active [file|anon] list is deferred until the ++ * pagevec is drained. This gives a chance for the caller of lru_cache_add() ++ * have the page added to the active list using mark_page_accessed(). + */ + void lru_cache_add(struct page *page) + { +@@ -811,7 +839,7 @@ void lru_add_drain_all(void) + * grabbed the page via the LRU. If it did, give up: shrink_inactive_list() + * will free it. + */ +-void release_pages(struct page **pages, int nr, int cold) ++void release_pages(struct page **pages, int nr, bool cold) + { + int i; + LIST_HEAD(pages_to_free); +@@ -852,7 +880,7 @@ void release_pages(struct page **pages, int nr, int cold) + } + + /* Clear Active bit in case of parallel mark_page_accessed */ +- ClearPageActive(page); ++ __ClearPageActive(page); + + list_add(&page->lru, &pages_to_free); + } +@@ -934,7 +962,7 @@ static void __pagevec_lru_add_fn(struct page *page, struct lruvec *lruvec, + SetPageLRU(page); + add_page_to_lru_list(page, lruvec, lru); + update_page_reclaim_stat(lruvec, file, active); +- trace_mm_lru_insertion(page, page_to_pfn(page), lru, trace_pagemap_flags(page)); ++ trace_mm_lru_insertion(page, lru); + } + + /* +@@ -948,6 +976,57 @@ void __pagevec_lru_add(struct pagevec *pvec) + EXPORT_SYMBOL(__pagevec_lru_add); + + /** ++ * pagevec_lookup_entries - gang pagecache lookup ++ * @pvec: Where the resulting entries are placed ++ * @mapping: The address_space to search ++ * @start: The starting entry index ++ * @nr_entries: The maximum number of entries ++ * @indices: The cache indices corresponding to the entries in @pvec ++ * ++ * pagevec_lookup_entries() will search for and return a group of up ++ * to @nr_entries pages and shadow entries in the mapping. All ++ * entries are placed in @pvec. pagevec_lookup_entries() takes a ++ * reference against actual pages in @pvec. ++ * ++ * The search returns a group of mapping-contiguous entries with ++ * ascending indexes. There may be holes in the indices due to ++ * not-present entries. ++ * ++ * pagevec_lookup_entries() returns the number of entries which were ++ * found. ++ */ ++unsigned pagevec_lookup_entries(struct pagevec *pvec, ++ struct address_space *mapping, ++ pgoff_t start, unsigned nr_pages, ++ pgoff_t *indices) ++{ ++ pvec->nr = find_get_entries(mapping, start, nr_pages, ++ pvec->pages, indices); ++ return pagevec_count(pvec); ++} ++ ++/** ++ * pagevec_remove_exceptionals - pagevec exceptionals pruning ++ * @pvec: The pagevec to prune ++ * ++ * pagevec_lookup_entries() fills both pages and exceptional radix ++ * tree entries into the pagevec. This function prunes all ++ * exceptionals from @pvec without leaving holes, so that it can be ++ * passed on to page-only pagevec operations. ++ */ ++void pagevec_remove_exceptionals(struct pagevec *pvec) ++{ ++ int i, j; ++ ++ for (i = 0, j = 0; i < pagevec_count(pvec); i++) { ++ struct page *page = pvec->pages[i]; ++ if (!radix_tree_exceptional_entry(page)) ++ pvec->pages[j++] = page; ++ } ++ pvec->nr = j; ++} ++ ++/** + * pagevec_lookup - gang pagecache lookup + * @pvec: Where the resulting pages are placed + * @mapping: The address_space to search +diff --git a/mm/swap_state.c b/mm/swap_state.c +index e76ace3..2972eee 100644 +--- a/mm/swap_state.c ++++ b/mm/swap_state.c +@@ -270,7 +270,7 @@ void free_pages_and_swap_cache(struct page **pages, int nr) + + for (i = 0; i < todo; i++) + free_swap_cache(pagep[i]); +- release_pages(pagep, todo, 0); ++ release_pages(pagep, todo, false); + pagep += todo; + nr -= todo; + } +diff --git a/mm/swapfile.c b/mm/swapfile.c +index 4a7f7e6..beeeef8 100644 +--- a/mm/swapfile.c ++++ b/mm/swapfile.c +@@ -51,14 +51,32 @@ atomic_long_t nr_swap_pages; + /* protected with swap_lock. reading in vm_swap_full() doesn't need lock */ + long total_swap_pages; + static int least_priority; +-static atomic_t highest_priority_index = ATOMIC_INIT(-1); + + static const char Bad_file[] = "Bad swap file entry "; + static const char Unused_file[] = "Unused swap file entry "; + static const char Bad_offset[] = "Bad swap offset entry "; + static const char Unused_offset[] = "Unused swap offset entry "; + +-struct swap_list_t swap_list = {-1, -1}; ++/* ++ * all active swap_info_structs ++ * protected with swap_lock, and ordered by priority. ++ */ ++PLIST_HEAD(swap_active_head); ++ ++/* ++ * all available (active, not full) swap_info_structs ++ * protected with swap_avail_lock, ordered by priority. ++ * This is used by get_swap_page() instead of swap_active_head ++ * because swap_active_head includes all swap_info_structs, ++ * but get_swap_page() doesn't need to look at full ones. ++ * This uses its own lock instead of swap_lock because when a ++ * swap_info_struct changes between not-full/full, it needs to ++ * add/remove itself to/from this list, but the swap_info_struct->lock ++ * is held and the locking order requires swap_lock to be taken ++ * before any swap_info_struct->lock. ++ */ ++static PLIST_HEAD(swap_avail_head); ++static DEFINE_SPINLOCK(swap_avail_lock); + + struct swap_info_struct *swap_info[MAX_SWAPFILES]; + +@@ -591,6 +609,9 @@ checks: + if (si->inuse_pages == si->pages) { + si->lowest_bit = si->max; + si->highest_bit = 0; ++ spin_lock(&swap_avail_lock); ++ plist_del(&si->avail_list, &swap_avail_head); ++ spin_unlock(&swap_avail_lock); + } + si->swap_map[offset] = usage; + inc_cluster_info_page(si, si->cluster_info, offset); +@@ -640,71 +661,65 @@ no_page: + + swp_entry_t get_swap_page(void) + { +- struct swap_info_struct *si; ++ struct swap_info_struct *si, *next; + pgoff_t offset; +- int type, next; +- int wrapped = 0; +- int hp_index; + +- spin_lock(&swap_lock); + if (atomic_long_read(&nr_swap_pages) <= 0) + goto noswap; + atomic_long_dec(&nr_swap_pages); + +- for (type = swap_list.next; type >= 0 && wrapped < 2; type = next) { +- hp_index = atomic_xchg(&highest_priority_index, -1); +- /* +- * highest_priority_index records current highest priority swap +- * type which just frees swap entries. If its priority is +- * higher than that of swap_list.next swap type, we use it. It +- * isn't protected by swap_lock, so it can be an invalid value +- * if the corresponding swap type is swapoff. We double check +- * the flags here. It's even possible the swap type is swapoff +- * and swapon again and its priority is changed. In such rare +- * case, low prority swap type might be used, but eventually +- * high priority swap will be used after several rounds of +- * swap. +- */ +- if (hp_index != -1 && hp_index != type && +- swap_info[type]->prio < swap_info[hp_index]->prio && +- (swap_info[hp_index]->flags & SWP_WRITEOK)) { +- type = hp_index; +- swap_list.next = type; +- } +- +- si = swap_info[type]; +- next = si->next; +- if (next < 0 || +- (!wrapped && si->prio != swap_info[next]->prio)) { +- next = swap_list.head; +- wrapped++; +- } ++ spin_lock(&swap_avail_lock); + ++start_over: ++ plist_for_each_entry_safe(si, next, &swap_avail_head, avail_list) { ++ /* requeue si to after same-priority siblings */ ++ plist_requeue(&si->avail_list, &swap_avail_head); ++ spin_unlock(&swap_avail_lock); + spin_lock(&si->lock); +- if (!si->highest_bit) { ++ if (!si->highest_bit || !(si->flags & SWP_WRITEOK)) { ++ spin_lock(&swap_avail_lock); ++ if (plist_node_empty(&si->avail_list)) { ++ spin_unlock(&si->lock); ++ goto nextsi; ++ } ++ WARN(!si->highest_bit, ++ "swap_info %d in list but !highest_bit\n", ++ si->type); ++ WARN(!(si->flags & SWP_WRITEOK), ++ "swap_info %d in list but !SWP_WRITEOK\n", ++ si->type); ++ plist_del(&si->avail_list, &swap_avail_head); + spin_unlock(&si->lock); +- continue; ++ goto nextsi; + } +- if (!(si->flags & SWP_WRITEOK)) { +- spin_unlock(&si->lock); +- continue; +- } +- +- swap_list.next = next; + +- spin_unlock(&swap_lock); + /* This is called for allocating swap entry for cache */ + offset = scan_swap_map(si, SWAP_HAS_CACHE); + spin_unlock(&si->lock); + if (offset) +- return swp_entry(type, offset); +- spin_lock(&swap_lock); +- next = swap_list.next; ++ return swp_entry(si->type, offset); ++ pr_debug("scan_swap_map of si %d failed to find offset\n", ++ si->type); ++ spin_lock(&swap_avail_lock); ++nextsi: ++ /* ++ * if we got here, it's likely that si was almost full before, ++ * and since scan_swap_map() can drop the si->lock, multiple ++ * callers probably all tried to get a page from the same si ++ * and it filled up before we could get one; or, the si filled ++ * up between us dropping swap_avail_lock and taking si->lock. ++ * Since we dropped the swap_avail_lock, the swap_avail_head ++ * list may have been modified; so if next is still in the ++ * swap_avail_head list then try it, otherwise start over. ++ */ ++ if (plist_node_empty(&next->avail_list)) ++ goto start_over; + } + ++ spin_unlock(&swap_avail_lock); ++ + atomic_long_inc(&nr_swap_pages); + noswap: +- spin_unlock(&swap_lock); + return (swp_entry_t) {0}; + } + +@@ -766,27 +781,6 @@ out: + return NULL; + } + +-/* +- * This swap type frees swap entry, check if it is the highest priority swap +- * type which just frees swap entry. get_swap_page() uses +- * highest_priority_index to search highest priority swap type. The +- * swap_info_struct.lock can't protect us if there are multiple swap types +- * active, so we use atomic_cmpxchg. +- */ +-static void set_highest_priority_index(int type) +-{ +- int old_hp_index, new_hp_index; +- +- do { +- old_hp_index = atomic_read(&highest_priority_index); +- if (old_hp_index != -1 && +- swap_info[old_hp_index]->prio >= swap_info[type]->prio) +- break; +- new_hp_index = type; +- } while (atomic_cmpxchg(&highest_priority_index, +- old_hp_index, new_hp_index) != old_hp_index); +-} +- + static unsigned char swap_entry_free(struct swap_info_struct *p, + swp_entry_t entry, unsigned char usage) + { +@@ -828,9 +822,18 @@ static unsigned char swap_entry_free(struct swap_info_struct *p, + dec_cluster_info_page(p, p->cluster_info, offset); + if (offset < p->lowest_bit) + p->lowest_bit = offset; +- if (offset > p->highest_bit) ++ if (offset > p->highest_bit) { ++ bool was_full = !p->highest_bit; + p->highest_bit = offset; +- set_highest_priority_index(p->type); ++ if (was_full && (p->flags & SWP_WRITEOK)) { ++ spin_lock(&swap_avail_lock); ++ WARN_ON(!plist_node_empty(&p->avail_list)); ++ if (plist_node_empty(&p->avail_list)) ++ plist_add(&p->avail_list, ++ &swap_avail_head); ++ spin_unlock(&swap_avail_lock); ++ } ++ } + atomic_long_inc(&nr_swap_pages); + p->inuse_pages--; + frontswap_invalidate_page(p->type, offset); +@@ -1765,30 +1768,37 @@ static void _enable_swap_info(struct swap_info_struct *p, int prio, + unsigned char *swap_map, + struct swap_cluster_info *cluster_info) + { +- int i, prev; +- + if (prio >= 0) + p->prio = prio; + else + p->prio = --least_priority; ++ /* ++ * the plist prio is negated because plist ordering is ++ * low-to-high, while swap ordering is high-to-low ++ */ ++ p->list.prio = -p->prio; ++ p->avail_list.prio = -p->prio; + p->swap_map = swap_map; + p->cluster_info = cluster_info; + p->flags |= SWP_WRITEOK; + atomic_long_add(p->pages, &nr_swap_pages); + total_swap_pages += p->pages; + +- /* insert swap space into swap_list: */ +- prev = -1; +- for (i = swap_list.head; i >= 0; i = swap_info[i]->next) { +- if (p->prio >= swap_info[i]->prio) +- break; +- prev = i; +- } +- p->next = i; +- if (prev < 0) +- swap_list.head = swap_list.next = p->type; +- else +- swap_info[prev]->next = p->type; ++ assert_spin_locked(&swap_lock); ++ /* ++ * both lists are plists, and thus priority ordered. ++ * swap_active_head needs to be priority ordered for swapoff(), ++ * which on removal of any swap_info_struct with an auto-assigned ++ * (i.e. negative) priority increments the auto-assigned priority ++ * of any lower-priority swap_info_structs. ++ * swap_avail_head needs to be priority ordered for get_swap_page(), ++ * which allocates swap pages from the highest available priority ++ * swap_info_struct. ++ */ ++ plist_add(&p->list, &swap_active_head); ++ spin_lock(&swap_avail_lock); ++ plist_add(&p->avail_list, &swap_avail_head); ++ spin_unlock(&swap_avail_lock); + } + + static void enable_swap_info(struct swap_info_struct *p, int prio, +@@ -1823,8 +1833,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) + struct address_space *mapping; + struct inode *inode; + struct filename *pathname; +- int i, type, prev; +- int err; ++ int err, found = 0; + unsigned int old_block_size; + + if (!capable(CAP_SYS_ADMIN)) +@@ -1842,17 +1851,16 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) + goto out; + + mapping = victim->f_mapping; +- prev = -1; + spin_lock(&swap_lock); +- for (type = swap_list.head; type >= 0; type = swap_info[type]->next) { +- p = swap_info[type]; ++ plist_for_each_entry(p, &swap_active_head, list) { + if (p->flags & SWP_WRITEOK) { +- if (p->swap_file->f_mapping == mapping) ++ if (p->swap_file->f_mapping == mapping) { ++ found = 1; + break; ++ } + } +- prev = type; + } +- if (type < 0) { ++ if (!found) { + err = -EINVAL; + spin_unlock(&swap_lock); + goto out_dput; +@@ -1864,20 +1872,21 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) + spin_unlock(&swap_lock); + goto out_dput; + } +- if (prev < 0) +- swap_list.head = p->next; +- else +- swap_info[prev]->next = p->next; +- if (type == swap_list.next) { +- /* just pick something that's safe... */ +- swap_list.next = swap_list.head; +- } ++ spin_lock(&swap_avail_lock); ++ plist_del(&p->avail_list, &swap_avail_head); ++ spin_unlock(&swap_avail_lock); + spin_lock(&p->lock); + if (p->prio < 0) { +- for (i = p->next; i >= 0; i = swap_info[i]->next) +- swap_info[i]->prio = p->prio--; ++ struct swap_info_struct *si = p; ++ ++ plist_for_each_entry_continue(si, &swap_active_head, list) { ++ si->prio++; ++ si->list.prio--; ++ si->avail_list.prio--; ++ } + least_priority++; + } ++ plist_del(&p->list, &swap_active_head); + atomic_long_sub(p->pages, &nr_swap_pages); + total_swap_pages -= p->pages; + p->flags &= ~SWP_WRITEOK; +@@ -1885,7 +1894,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) + spin_unlock(&swap_lock); + + set_current_oom_origin(); +- err = try_to_unuse(type, false, 0); /* force all pages to be unused */ ++ err = try_to_unuse(p->type, false, 0); /* force unuse all pages */ + clear_current_oom_origin(); + + if (err) { +@@ -1926,7 +1935,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) + frontswap_map = frontswap_map_get(p); + spin_unlock(&p->lock); + spin_unlock(&swap_lock); +- frontswap_invalidate_area(type); ++ frontswap_invalidate_area(p->type); + frontswap_map_set(p, NULL); + mutex_unlock(&swapon_mutex); + free_percpu(p->percpu_cluster); +@@ -1935,7 +1944,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) + vfree(cluster_info); + vfree(frontswap_map); + /* Destroy swap account information */ +- swap_cgroup_swapoff(type); ++ swap_cgroup_swapoff(p->type); + + inode = mapping->host; + if (S_ISBLK(inode->i_mode)) { +@@ -2142,8 +2151,9 @@ static struct swap_info_struct *alloc_swap_info(void) + */ + } + INIT_LIST_HEAD(&p->first_swap_extent.list); ++ plist_node_init(&p->list, 0); ++ plist_node_init(&p->avail_list, 0); + p->flags = SWP_USED; +- p->next = -1; + spin_unlock(&swap_lock); + spin_lock_init(&p->lock); + +diff --git a/mm/truncate.c b/mm/truncate.c +index 353b683..827ad8d 100644 +--- a/mm/truncate.c ++++ b/mm/truncate.c +@@ -20,8 +20,25 @@ + #include /* grr. try_to_release_page, + do_invalidatepage */ + #include ++#include + #include "internal.h" + ++static void clear_exceptional_entry(struct address_space *mapping, ++ pgoff_t index, void *entry) ++{ ++ /* Handled by shmem itself */ ++ if (shmem_mapping(mapping)) ++ return; ++ ++ spin_lock_irq(&mapping->tree_lock); ++ /* ++ * Regular page slots are stabilized by the page lock even ++ * without the tree itself locked. These unlocked entries ++ * need verification under the tree lock. ++ */ ++ radix_tree_delete_item(&mapping->page_tree, index, entry); ++ spin_unlock_irq(&mapping->tree_lock); ++} + + /** + * do_invalidatepage - invalidate part or all of a page +@@ -208,6 +225,7 @@ void truncate_inode_pages_range(struct address_space *mapping, + unsigned int partial_start; /* inclusive */ + unsigned int partial_end; /* exclusive */ + struct pagevec pvec; ++ pgoff_t indices[PAGEVEC_SIZE]; + pgoff_t index; + int i; + +@@ -238,17 +256,23 @@ void truncate_inode_pages_range(struct address_space *mapping, + + pagevec_init(&pvec, 0); + index = start; +- while (index < end && pagevec_lookup(&pvec, mapping, index, +- min(end - index, (pgoff_t)PAGEVEC_SIZE))) { ++ while (index < end && pagevec_lookup_entries(&pvec, mapping, index, ++ min(end - index, (pgoff_t)PAGEVEC_SIZE), ++ indices)) { + mem_cgroup_uncharge_start(); + for (i = 0; i < pagevec_count(&pvec); i++) { + struct page *page = pvec.pages[i]; + + /* We rely upon deletion not changing page->index */ +- index = page->index; ++ index = indices[i]; + if (index >= end) + break; + ++ if (radix_tree_exceptional_entry(page)) { ++ clear_exceptional_entry(mapping, index, page); ++ continue; ++ } ++ + if (!trylock_page(page)) + continue; + WARN_ON(page->index != index); +@@ -259,6 +283,7 @@ void truncate_inode_pages_range(struct address_space *mapping, + truncate_inode_page(mapping, page); + unlock_page(page); + } ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + mem_cgroup_uncharge_end(); + cond_resched(); +@@ -307,14 +332,16 @@ void truncate_inode_pages_range(struct address_space *mapping, + index = start; + for ( ; ; ) { + cond_resched(); +- if (!pagevec_lookup(&pvec, mapping, index, +- min(end - index, (pgoff_t)PAGEVEC_SIZE))) { ++ if (!pagevec_lookup_entries(&pvec, mapping, index, ++ min(end - index, (pgoff_t)PAGEVEC_SIZE), ++ indices)) { + if (index == start) + break; + index = start; + continue; + } +- if (index == start && pvec.pages[0]->index >= end) { ++ if (index == start && indices[0] >= end) { ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + break; + } +@@ -323,16 +350,22 @@ void truncate_inode_pages_range(struct address_space *mapping, + struct page *page = pvec.pages[i]; + + /* We rely upon deletion not changing page->index */ +- index = page->index; ++ index = indices[i]; + if (index >= end) + break; + ++ if (radix_tree_exceptional_entry(page)) { ++ clear_exceptional_entry(mapping, index, page); ++ continue; ++ } ++ + lock_page(page); + WARN_ON(page->index != index); + wait_on_page_writeback(page); + truncate_inode_page(mapping, page); + unlock_page(page); + } ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + mem_cgroup_uncharge_end(); + index++; +@@ -375,6 +408,7 @@ EXPORT_SYMBOL(truncate_inode_pages); + unsigned long invalidate_mapping_pages(struct address_space *mapping, + pgoff_t start, pgoff_t end) + { ++ pgoff_t indices[PAGEVEC_SIZE]; + struct pagevec pvec; + pgoff_t index = start; + unsigned long ret; +@@ -390,17 +424,23 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping, + */ + + pagevec_init(&pvec, 0); +- while (index <= end && pagevec_lookup(&pvec, mapping, index, +- min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) { ++ while (index <= end && pagevec_lookup_entries(&pvec, mapping, index, ++ min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1, ++ indices)) { + mem_cgroup_uncharge_start(); + for (i = 0; i < pagevec_count(&pvec); i++) { + struct page *page = pvec.pages[i]; + + /* We rely upon deletion not changing page->index */ +- index = page->index; ++ index = indices[i]; + if (index > end) + break; + ++ if (radix_tree_exceptional_entry(page)) { ++ clear_exceptional_entry(mapping, index, page); ++ continue; ++ } ++ + if (!trylock_page(page)) + continue; + WARN_ON(page->index != index); +@@ -414,6 +454,7 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping, + deactivate_page(page); + count += ret; + } ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + mem_cgroup_uncharge_end(); + cond_resched(); +@@ -481,6 +522,7 @@ static int do_launder_page(struct address_space *mapping, struct page *page) + int invalidate_inode_pages2_range(struct address_space *mapping, + pgoff_t start, pgoff_t end) + { ++ pgoff_t indices[PAGEVEC_SIZE]; + struct pagevec pvec; + pgoff_t index; + int i; +@@ -491,17 +533,23 @@ int invalidate_inode_pages2_range(struct address_space *mapping, + cleancache_invalidate_inode(mapping); + pagevec_init(&pvec, 0); + index = start; +- while (index <= end && pagevec_lookup(&pvec, mapping, index, +- min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) { ++ while (index <= end && pagevec_lookup_entries(&pvec, mapping, index, ++ min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1, ++ indices)) { + mem_cgroup_uncharge_start(); + for (i = 0; i < pagevec_count(&pvec); i++) { + struct page *page = pvec.pages[i]; + + /* We rely upon deletion not changing page->index */ +- index = page->index; ++ index = indices[i]; + if (index > end) + break; + ++ if (radix_tree_exceptional_entry(page)) { ++ clear_exceptional_entry(mapping, index, page); ++ continue; ++ } ++ + lock_page(page); + WARN_ON(page->index != index); + if (page->mapping != mapping) { +@@ -539,6 +587,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping, + ret = ret2; + unlock_page(page); + } ++ pagevec_remove_exceptionals(&pvec); + pagevec_release(&pvec); + mem_cgroup_uncharge_end(); + cond_resched(); +@@ -613,12 +662,67 @@ EXPORT_SYMBOL(truncate_pagecache); + */ + void truncate_setsize(struct inode *inode, loff_t newsize) + { ++ loff_t oldsize = inode->i_size; ++ + i_size_write(inode, newsize); ++ if (newsize > oldsize) ++ pagecache_isize_extended(inode, oldsize, newsize); + truncate_pagecache(inode, newsize); + } + EXPORT_SYMBOL(truncate_setsize); + + /** ++ * pagecache_isize_extended - update pagecache after extension of i_size ++ * @inode: inode for which i_size was extended ++ * @from: original inode size ++ * @to: new inode size ++ * ++ * Handle extension of inode size either caused by extending truncate or by ++ * write starting after current i_size. We mark the page straddling current ++ * i_size RO so that page_mkwrite() is called on the nearest write access to ++ * the page. This way filesystem can be sure that page_mkwrite() is called on ++ * the page before user writes to the page via mmap after the i_size has been ++ * changed. ++ * ++ * The function must be called after i_size is updated so that page fault ++ * coming after we unlock the page will already see the new i_size. ++ * The function must be called while we still hold i_mutex - this not only ++ * makes sure i_size is stable but also that userspace cannot observe new ++ * i_size value before we are prepared to store mmap writes at new inode size. ++ */ ++void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to) ++{ ++ int bsize = 1 << inode->i_blkbits; ++ loff_t rounded_from; ++ struct page *page; ++ pgoff_t index; ++ ++ WARN_ON(to > inode->i_size); ++ ++ if (from >= to || bsize == PAGE_CACHE_SIZE) ++ return; ++ /* Page straddling @from will not have any hole block created? */ ++ rounded_from = round_up(from, bsize); ++ if (to <= rounded_from || !(rounded_from & (PAGE_CACHE_SIZE - 1))) ++ return; ++ ++ index = from >> PAGE_CACHE_SHIFT; ++ page = find_lock_page(inode->i_mapping, index); ++ /* Page not cached? Nothing to do */ ++ if (!page) ++ return; ++ /* ++ * See clear_page_dirty_for_io() for details why set_page_dirty() ++ * is needed. ++ */ ++ if (page_mkclean(page)) ++ set_page_dirty(page); ++ unlock_page(page); ++ page_cache_release(page); ++} ++EXPORT_SYMBOL(pagecache_isize_extended); ++ ++/** + * truncate_pagecache_range - unmap and remove pagecache that is hole-punched + * @inode: inode + * @lstart: offset of beginning of hole +diff --git a/mm/util.c b/mm/util.c +index a24aa22..c1010cb 100644 +--- a/mm/util.c ++++ b/mm/util.c +@@ -275,17 +275,14 @@ pid_t vm_is_stack(struct task_struct *task, + + if (in_group) { + struct task_struct *t; +- rcu_read_lock(); +- if (!pid_alive(task)) +- goto done; + +- t = task; +- do { ++ rcu_read_lock(); ++ for_each_thread(task, t) { + if (vm_is_stack_for_task(t, vma)) { + ret = t->pid; + goto done; + } +- } while_each_thread(task, t); ++ } + done: + rcu_read_unlock(); + } +diff --git a/mm/vmalloc.c b/mm/vmalloc.c +index 0fdf968..aa3891e 100644 +--- a/mm/vmalloc.c ++++ b/mm/vmalloc.c +@@ -2681,14 +2681,14 @@ void get_vmalloc_info(struct vmalloc_info *vmi) + + prev_end = VMALLOC_START; + +- spin_lock(&vmap_area_lock); ++ rcu_read_lock(); + + if (list_empty(&vmap_area_list)) { + vmi->largest_chunk = VMALLOC_TOTAL; + goto out; + } + +- list_for_each_entry(va, &vmap_area_list, list) { ++ list_for_each_entry_rcu(va, &vmap_area_list, list) { + unsigned long addr = va->va_start; + + /* +@@ -2715,7 +2715,7 @@ void get_vmalloc_info(struct vmalloc_info *vmi) + vmi->largest_chunk = VMALLOC_END - prev_end; + + out: +- spin_unlock(&vmap_area_lock); ++ rcu_read_unlock(); + } + #endif + +diff --git a/mm/vmpressure.c b/mm/vmpressure.c +index d4042e7..c5afd57 100644 +--- a/mm/vmpressure.c ++++ b/mm/vmpressure.c +@@ -165,6 +165,7 @@ static void vmpressure_work_fn(struct work_struct *work) + unsigned long scanned; + unsigned long reclaimed; + ++ spin_lock(&vmpr->sr_lock); + /* + * Several contexts might be calling vmpressure(), so it is + * possible that the work was rescheduled again before the old +@@ -173,11 +174,12 @@ static void vmpressure_work_fn(struct work_struct *work) + * here. No need for any locks here since we don't care if + * vmpr->reclaimed is in sync. + */ +- if (!vmpr->scanned) ++ scanned = vmpr->scanned; ++ if (!scanned) { ++ spin_unlock(&vmpr->sr_lock); + return; ++ } + +- spin_lock(&vmpr->sr_lock); +- scanned = vmpr->scanned; + reclaimed = vmpr->reclaimed; + vmpr->scanned = 0; + vmpr->reclaimed = 0; +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 6ef484f..88edf53 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -163,7 +163,8 @@ static unsigned long zone_reclaimable_pages(struct zone *zone) + + bool zone_reclaimable(struct zone *zone) + { +- return zone->pages_scanned < zone_reclaimable_pages(zone) * 6; ++ return zone_page_state(zone, NR_PAGES_SCANNED) < ++ zone_reclaimable_pages(zone) * 6; + } + + static unsigned long get_lru_size(struct lruvec *lruvec, enum lru_list lru) +@@ -224,15 +225,15 @@ shrink_slab_node(struct shrink_control *shrinkctl, struct shrinker *shrinker, + unsigned long freed = 0; + unsigned long long delta; + long total_scan; +- long max_pass; ++ long freeable; + long nr; + long new_nr; + int nid = shrinkctl->nid; + long batch_size = shrinker->batch ? shrinker->batch + : SHRINK_BATCH; + +- max_pass = shrinker->count_objects(shrinker, shrinkctl); +- if (max_pass == 0) ++ freeable = shrinker->count_objects(shrinker, shrinkctl); ++ if (freeable == 0) + return 0; + + /* +@@ -244,14 +245,14 @@ shrink_slab_node(struct shrink_control *shrinkctl, struct shrinker *shrinker, + + total_scan = nr; + delta = (4 * nr_pages_scanned) / shrinker->seeks; +- delta *= max_pass; ++ delta *= freeable; + do_div(delta, lru_pages + 1); + total_scan += delta; + if (total_scan < 0) { + printk(KERN_ERR + "shrink_slab: %pF negative objects to delete nr=%ld\n", + shrinker->scan_objects, total_scan); +- total_scan = max_pass; ++ total_scan = freeable; + } + + /* +@@ -260,26 +261,26 @@ shrink_slab_node(struct shrink_control *shrinkctl, struct shrinker *shrinker, + * shrinkers to return -1 all the time. This results in a large + * nr being built up so when a shrink that can do some work + * comes along it empties the entire cache due to nr >>> +- * max_pass. This is bad for sustaining a working set in ++ * freeable. This is bad for sustaining a working set in + * memory. + * + * Hence only allow the shrinker to scan the entire cache when + * a large delta change is calculated directly. + */ +- if (delta < max_pass / 4) +- total_scan = min(total_scan, max_pass / 2); ++ if (delta < freeable / 4) ++ total_scan = min(total_scan, freeable / 2); + + /* + * Avoid risking looping forever due to too large nr value: + * never try to free more than twice the estimate number of + * freeable entries. + */ +- if (total_scan > max_pass * 2) +- total_scan = max_pass * 2; ++ if (total_scan > freeable * 2) ++ total_scan = freeable * 2; + + trace_mm_shrink_slab_start(shrinker, shrinkctl, nr, + nr_pages_scanned, lru_pages, +- max_pass, delta, total_scan); ++ freeable, delta, total_scan); + + /* + * Normally, we should not scan less than batch_size objects in one +@@ -292,12 +293,12 @@ shrink_slab_node(struct shrink_control *shrinkctl, struct shrinker *shrinker, + * + * We detect the "tight on memory" situations by looking at the total + * number of objects we want to scan (total_scan). If it is greater +- * than the total number of objects on slab (max_pass), we must be ++ * than the total number of objects on slab (freeable), we must be + * scanning at high prio and therefore should try to reclaim as much as + * possible. + */ + while (total_scan >= batch_size || +- total_scan >= max_pass) { ++ total_scan >= freeable) { + unsigned long ret; + unsigned long nr_to_scan = min(batch_size, total_scan); + +@@ -870,21 +871,17 @@ static unsigned long shrink_page_list(struct list_head *page_list, + * + * 2) Global reclaim encounters a page, memcg encounters a + * page that is not marked for immediate reclaim or +- * the caller does not have __GFP_IO. In this case mark ++ * the caller does not have __GFP_FS (or __GFP_IO if it's ++ * simply going to swap, not to fs). In this case mark + * the page for immediate reclaim and continue scanning. + * +- * __GFP_IO is checked because a loop driver thread might ++ * Require may_enter_fs because we would wait on fs, which ++ * may not have submitted IO yet. And the loop driver might + * enter reclaim, and deadlock if it waits on a page for + * which it is needed to do the write (loop masks off + * __GFP_IO|__GFP_FS for this reason); but more thought + * would probably show more reasons. + * +- * Don't require __GFP_FS, since we're not going into the +- * FS, just waiting on its writeback completion. Worryingly, +- * ext4 gfs2 and xfs allocate pages with +- * grab_cache_page_write_begin(,,AOP_FLAG_NOFS), so testing +- * may_enter_fs here is liable to OOM on them. +- * + * 3) memcg encounters a page that is not already marked + * PageReclaim. memcg does not have any dirty pages + * throttling so we could easily OOM just because too many +@@ -901,7 +898,7 @@ static unsigned long shrink_page_list(struct list_head *page_list, + + /* Case 2 above */ + } else if (global_reclaim(sc) || +- !PageReclaim(page) || !(sc->gfp_mask & __GFP_IO)) { ++ !PageReclaim(page) || !may_enter_fs) { + /* + * This is slightly racy - end_page_writeback() + * might have just cleared PageReclaim, then +@@ -1107,7 +1104,7 @@ keep: + VM_BUG_ON_PAGE(PageLRU(page) || PageUnevictable(page), page); + } + +- free_hot_cold_page_list(&free_pages, 1); ++ free_hot_cold_page_list(&free_pages, true); + + list_splice(&ret_pages, page_list); + count_vm_events(PGACTIVATE, pgactivate); +@@ -1144,7 +1141,7 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone, + TTU_UNMAP|TTU_IGNORE_ACCESS, + &dummy1, &dummy2, &dummy3, &dummy4, &dummy5, true); + list_splice(&clean_pages, page_list); +- __mod_zone_page_state(zone, NR_ISOLATED_FILE, -ret); ++ mod_zone_page_state(zone, NR_ISOLATED_FILE, -ret); + return ret; + } + +@@ -1470,7 +1467,7 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec, + __mod_zone_page_state(zone, NR_ISOLATED_ANON + file, nr_taken); + + if (global_reclaim(sc)) { +- zone->pages_scanned += nr_scanned; ++ __mod_zone_page_state(zone, NR_PAGES_SCANNED, nr_scanned); + if (current_is_kswapd()) + __count_zone_vm_events(PGSCAN_KSWAPD, zone, nr_scanned); + else +@@ -1505,7 +1502,7 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec, + + spin_unlock_irq(&zone->lru_lock); + +- free_hot_cold_page_list(&page_list, 1); ++ free_hot_cold_page_list(&page_list, true); + + /* + * If reclaim is isolating dirty pages under writeback, it implies +@@ -1659,7 +1656,7 @@ static void shrink_active_list(unsigned long nr_to_scan, + nr_taken = isolate_lru_pages(nr_to_scan, lruvec, &l_hold, + &nr_scanned, sc, isolate_mode, lru); + if (global_reclaim(sc)) +- zone->pages_scanned += nr_scanned; ++ __mod_zone_page_state(zone, NR_PAGES_SCANNED, nr_scanned); + + reclaim_stat->recent_scanned[file] += nr_taken; + +@@ -1725,7 +1722,7 @@ static void shrink_active_list(unsigned long nr_to_scan, + __mod_zone_page_state(zone, NR_ISOLATED_ANON + file, -nr_taken); + spin_unlock_irq(&zone->lru_lock); + +- free_hot_cold_page_list(&l_hold, 1); ++ free_hot_cold_page_list(&l_hold, true); + } + + #ifdef CONFIG_SWAP +@@ -1847,7 +1844,7 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, + struct zone *zone = lruvec_zone(lruvec); + unsigned long anon_prio, file_prio; + enum scan_balance scan_balance; +- unsigned long anon, file, free; ++ unsigned long anon, file; + bool force_scan = false; + unsigned long ap, fp; + enum lru_list lru; +@@ -1895,11 +1892,6 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, + goto out; + } + +- anon = get_lru_size(lruvec, LRU_ACTIVE_ANON) + +- get_lru_size(lruvec, LRU_INACTIVE_ANON); +- file = get_lru_size(lruvec, LRU_ACTIVE_FILE) + +- get_lru_size(lruvec, LRU_INACTIVE_FILE); +- + /* + * If it's foreseeable that reclaiming the file cache won't be + * enough to get the zone back into a desirable shape, we have +@@ -1907,8 +1899,14 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, + * thrashing - remaining file pages alone. + */ + if (global_reclaim(sc)) { +- free = zone_page_state(zone, NR_FREE_PAGES); +- if (unlikely(file + free <= high_wmark_pages(zone))) { ++ unsigned long zonefile; ++ unsigned long zonefree; ++ ++ zonefree = zone_page_state(zone, NR_FREE_PAGES); ++ zonefile = zone_page_state(zone, NR_ACTIVE_FILE) + ++ zone_page_state(zone, NR_INACTIVE_FILE); ++ ++ if (unlikely(zonefile + zonefree <= high_wmark_pages(zone))) { + scan_balance = SCAN_ANON; + goto out; + } +@@ -1943,6 +1941,12 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, + * + * anon in [0], file in [1] + */ ++ ++ anon = get_lru_size(lruvec, LRU_ACTIVE_ANON) + ++ get_lru_size(lruvec, LRU_INACTIVE_ANON); ++ file = get_lru_size(lruvec, LRU_ACTIVE_FILE) + ++ get_lru_size(lruvec, LRU_INACTIVE_FILE); ++ + spin_lock_irq(&zone->lru_lock); + if (unlikely(reclaim_stat->recent_scanned[0] > anon / 4)) { + reclaim_stat->recent_scanned[0] /= 2; +@@ -2018,13 +2022,27 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) + unsigned long nr_reclaimed = 0; + unsigned long nr_to_reclaim = sc->nr_to_reclaim; + struct blk_plug plug; +- bool scan_adjusted = false; ++ bool scan_adjusted; + + get_scan_count(lruvec, sc, nr); + + /* Record the original scan target for proportional adjustments later */ + memcpy(targets, nr, sizeof(nr)); + ++ /* ++ * Global reclaiming within direct reclaim at DEF_PRIORITY is a normal ++ * event that can occur when there is little memory pressure e.g. ++ * multiple streaming readers/writers. Hence, we do not abort scanning ++ * when the requested number of pages are reclaimed when scanning at ++ * DEF_PRIORITY on the assumption that the fact we are direct ++ * reclaiming implies that kswapd is not keeping up and it is best to ++ * do a batch of work at once. For memcg reclaim one check is made to ++ * abort proportional reclaim if either the file or anon lru has already ++ * dropped to zero at the first pass. ++ */ ++ scan_adjusted = (global_reclaim(sc) && !current_is_kswapd() && ++ sc->priority == DEF_PRIORITY); ++ + blk_start_plug(&plug); + while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] || + nr[LRU_INACTIVE_FILE]) { +@@ -2045,17 +2063,8 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) + continue; + + /* +- * For global direct reclaim, reclaim only the number of pages +- * requested. Less care is taken to scan proportionally as it +- * is more important to minimise direct reclaim stall latency +- * than it is to properly age the LRU lists. +- */ +- if (global_reclaim(sc) && !current_is_kswapd()) +- break; +- +- /* + * For kswapd and memcg, reclaim at least the number of pages +- * requested. Ensure that the anon and file LRUs shrink ++ * requested. Ensure that the anon and file LRUs are scanned + * proportionally what was requested by get_scan_count(). We + * stop reclaiming one LRU and reduce the amount scanning + * proportional to the original scan target. +@@ -2063,6 +2072,15 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) + nr_file = nr[LRU_INACTIVE_FILE] + nr[LRU_ACTIVE_FILE]; + nr_anon = nr[LRU_INACTIVE_ANON] + nr[LRU_ACTIVE_ANON]; + ++ /* ++ * It's just vindictive to attack the larger once the smaller ++ * has gone to zero. And given the way we stop scanning the ++ * smaller below, this makes sure that we only make one nudge ++ * towards proportionality once we've got nr_to_reclaim. ++ */ ++ if (!nr_file || !nr_anon) ++ break; ++ + if (nr_file > nr_anon) { + unsigned long scan_target = targets[LRU_INACTIVE_ANON] + + targets[LRU_ACTIVE_ANON] + 1; +@@ -2424,8 +2442,8 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, + unsigned long lru_pages = 0; + + nodes_clear(shrink->nodes_to_scan); +- for_each_zone_zonelist(zone, z, zonelist, +- gfp_zone(sc->gfp_mask)) { ++ for_each_zone_zonelist_nodemask(zone, z, zonelist, ++ gfp_zone(sc->gfp_mask), sc->nodemask) { + if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL)) + continue; + +@@ -2846,18 +2864,20 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining, + return false; + + /* +- * There is a potential race between when kswapd checks its watermarks +- * and a process gets throttled. There is also a potential race if +- * processes get throttled, kswapd wakes, a large process exits therby +- * balancing the zones that causes kswapd to miss a wakeup. If kswapd +- * is going to sleep, no process should be sleeping on pfmemalloc_wait +- * so wake them now if necessary. If necessary, processes will wake +- * kswapd and get throttled again ++ * The throttled processes are normally woken up in balance_pgdat() as ++ * soon as pfmemalloc_watermark_ok() is true. But there is a potential ++ * race between when kswapd checks the watermarks and a process gets ++ * throttled. There is also a potential race if processes get ++ * throttled, kswapd wakes, a large process exits thereby balancing the ++ * zones, which causes kswapd to exit balance_pgdat() before reaching ++ * the wake up checks. If kswapd is going to sleep, no process should ++ * be sleeping on pfmemalloc_wait, so wake them now if necessary. If ++ * the wake up is premature, processes will wake kswapd and get ++ * throttled again. The difference from wake ups in balance_pgdat() is ++ * that here we are under prepare_to_wait(). + */ +- if (waitqueue_active(&pgdat->pfmemalloc_wait)) { +- wake_up(&pgdat->pfmemalloc_wait); +- return false; +- } ++ if (waitqueue_active(&pgdat->pfmemalloc_wait)) ++ wake_up_all(&pgdat->pfmemalloc_wait); + + return pgdat_balanced(pgdat, order, classzone_idx); + } +diff --git a/mm/vmstat.c b/mm/vmstat.c +index def5dd2..eded190 100644 +--- a/mm/vmstat.c ++++ b/mm/vmstat.c +@@ -200,7 +200,7 @@ void set_pgdat_percpu_threshold(pg_data_t *pgdat, + continue; + + threshold = (*calculate_pressure)(zone); +- for_each_possible_cpu(cpu) ++ for_each_online_cpu(cpu) + per_cpu_ptr(zone->pageset, cpu)->stat_threshold + = threshold; + } +@@ -761,6 +761,7 @@ const char * const vmstat_text[] = { + "nr_shmem", + "nr_dirtied", + "nr_written", ++ "nr_pages_scanned", + + #ifdef CONFIG_NUMA + "numa_hit", +@@ -1055,7 +1056,7 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat, + min_wmark_pages(zone), + low_wmark_pages(zone), + high_wmark_pages(zone), +- zone->pages_scanned, ++ zone_page_state(zone, NR_PAGES_SCANNED), + zone->spanned_pages, + zone->present_pages, + zone->managed_pages); +@@ -1065,10 +1066,10 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat, + zone_page_state(zone, i)); + + seq_printf(m, +- "\n protection: (%lu", ++ "\n protection: (%ld", + zone->lowmem_reserve[0]); + for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++) +- seq_printf(m, ", %lu", zone->lowmem_reserve[i]); ++ seq_printf(m, ", %ld", zone->lowmem_reserve[i]); + seq_printf(m, + ")" + "\n pagesets"); +diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c +index 7e57135..5d56e05 100644 +--- a/net/8021q/vlan_core.c ++++ b/net/8021q/vlan_core.c +@@ -106,59 +106,6 @@ u16 vlan_dev_vlan_id(const struct net_device *dev) + } + EXPORT_SYMBOL(vlan_dev_vlan_id); + +-static struct sk_buff *vlan_reorder_header(struct sk_buff *skb) +-{ +- if (skb_cow(skb, skb_headroom(skb)) < 0) { +- kfree_skb(skb); +- return NULL; +- } +- +- memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN); +- skb->mac_header += VLAN_HLEN; +- return skb; +-} +- +-struct sk_buff *vlan_untag(struct sk_buff *skb) +-{ +- struct vlan_hdr *vhdr; +- u16 vlan_tci; +- +- if (unlikely(vlan_tx_tag_present(skb))) { +- /* vlan_tci is already set-up so leave this for another time */ +- return skb; +- } +- +- skb = skb_share_check(skb, GFP_ATOMIC); +- if (unlikely(!skb)) +- goto err_free; +- +- if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) +- goto err_free; +- +- vhdr = (struct vlan_hdr *) skb->data; +- vlan_tci = ntohs(vhdr->h_vlan_TCI); +- __vlan_hwaccel_put_tag(skb, skb->protocol, vlan_tci); +- +- skb_pull_rcsum(skb, VLAN_HLEN); +- vlan_set_encap_proto(skb, vhdr); +- +- skb = vlan_reorder_header(skb); +- if (unlikely(!skb)) +- goto err_free; +- +- skb_reset_network_header(skb); +- skb_reset_transport_header(skb); +- skb_reset_mac_len(skb); +- +- return skb; +- +-err_free: +- kfree_skb(skb); +- return NULL; +-} +-EXPORT_SYMBOL(vlan_untag); +- +- + /* + * vlan info and vid list + */ +diff --git a/net/9p/client.c b/net/9p/client.c +index 9186550..08046f3 100644 +--- a/net/9p/client.c ++++ b/net/9p/client.c +@@ -839,7 +839,8 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, + if (err < 0) { + if (err == -EIO) + c->status = Disconnected; +- goto reterr; ++ if (err != -ERESTARTSYS) ++ goto reterr; + } + if (req->status == REQ_STATUS_ERROR) { + p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); +diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c +index cc1cfd6..e5c5f57 100644 +--- a/net/batman-adv/fragmentation.c ++++ b/net/batman-adv/fragmentation.c +@@ -128,6 +128,7 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node, + { + struct batadv_frag_table_entry *chain; + struct batadv_frag_list_entry *frag_entry_new = NULL, *frag_entry_curr; ++ struct batadv_frag_list_entry *frag_entry_last = NULL; + struct batadv_frag_packet *frag_packet; + uint8_t bucket; + uint16_t seqno, hdr_size = sizeof(struct batadv_frag_packet); +@@ -180,11 +181,14 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node, + ret = true; + goto out; + } ++ ++ /* store current entry because it could be the last in list */ ++ frag_entry_last = frag_entry_curr; + } + +- /* Reached the end of the list, so insert after 'frag_entry_curr'. */ +- if (likely(frag_entry_curr)) { +- hlist_add_after(&frag_entry_curr->list, &frag_entry_new->list); ++ /* Reached the end of the list, so insert after 'frag_entry_last'. */ ++ if (likely(frag_entry_last)) { ++ hlist_add_after(&frag_entry_last->list, &frag_entry_new->list); + chain->size += skb->len - hdr_size; + chain->timestamp = jiffies; + ret = true; +@@ -247,7 +251,7 @@ batadv_frag_merge_packets(struct hlist_head *chain, struct sk_buff *skb) + kfree(entry); + + /* Make room for the rest of the fragments. */ +- if (pskb_expand_head(skb_out, 0, size - skb->len, GFP_ATOMIC) < 0) { ++ if (pskb_expand_head(skb_out, 0, size - skb_out->len, GFP_ATOMIC) < 0) { + kfree_skb(skb_out); + skb_out = NULL; + goto free; +@@ -430,7 +434,7 @@ bool batadv_frag_send_packet(struct sk_buff *skb, + * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE + */ + mtu = min_t(unsigned, mtu, BATADV_FRAG_MAX_FRAG_SIZE); +- max_fragment_size = (mtu - header_size - ETH_HLEN); ++ max_fragment_size = mtu - header_size; + max_packet_size = max_fragment_size * BATADV_FRAG_MAX_FRAGMENTS; + + /* Don't even try to fragment, if we need more than 16 fragments */ +diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c +index 36b9ae6..2393ea7 100644 +--- a/net/batman-adv/gateway_client.c ++++ b/net/batman-adv/gateway_client.c +@@ -812,7 +812,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, + goto out; + + gw_node = batadv_gw_node_get(bat_priv, orig_dst_node); +- if (!gw_node->bandwidth_down == 0) ++ if (!gw_node) + goto out; + + switch (atomic_read(&bat_priv->gw_mode)) { +diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c +index b851cc5..fbda6b5 100644 +--- a/net/batman-adv/hard-interface.c ++++ b/net/batman-adv/hard-interface.c +@@ -83,7 +83,7 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev) + return true; + + /* no more parents..stop recursion */ +- if (net_dev->iflink == net_dev->ifindex) ++ if (net_dev->iflink == 0 || net_dev->iflink == net_dev->ifindex) + return false; + + /* recurse over the parent device */ +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 6afa3b4..0007c9e 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -2608,12 +2608,8 @@ static int l2cap_segment_le_sdu(struct l2cap_chan *chan, + + BT_DBG("chan %p, msg %p, len %zu", chan, msg, len); + +- pdu_len = chan->conn->mtu - L2CAP_HDR_SIZE; +- +- pdu_len = min_t(size_t, pdu_len, chan->remote_mps); +- + sdu_len = len; +- pdu_len -= L2CAP_SDULEN_SIZE; ++ pdu_len = chan->remote_mps - L2CAP_SDULEN_SIZE; + + while (len > 0) { + if (len <= pdu_len) +diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c +index 27ae841..06a7a76 100644 +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1112,7 +1112,8 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) + l2cap_chan_close(chan, 0); + lock_sock(sk); + +- if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) ++ if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && ++ !(current->flags & PF_EXITING)) + err = bt_sock_wait_state(sk, BT_CLOSED, + sk->sk_lingertime); + } +diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c +index facd8a7..b088651 100644 +--- a/net/bluetooth/rfcomm/core.c ++++ b/net/bluetooth/rfcomm/core.c +@@ -1859,10 +1859,13 @@ static struct rfcomm_session *rfcomm_process_rx(struct rfcomm_session *s) + /* Get data directly from socket receive queue without copying it. */ + while ((skb = skb_dequeue(&sk->sk_receive_queue))) { + skb_orphan(skb); +- if (!skb_linearize(skb)) ++ if (!skb_linearize(skb)) { + s = rfcomm_recv_frame(s, skb); +- else ++ if (!s) ++ break; ++ } else { + kfree_skb(skb); ++ } + } + + if (s && (sk->sk_state == BT_CLOSED)) +diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c +index 3c2d3e4..a0050de 100644 +--- a/net/bluetooth/rfcomm/sock.c ++++ b/net/bluetooth/rfcomm/sock.c +@@ -898,7 +898,8 @@ static int rfcomm_sock_shutdown(struct socket *sock, int how) + sk->sk_shutdown = SHUTDOWN_MASK; + __rfcomm_sock_close(sk); + +- if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) ++ if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && ++ !(current->flags & PF_EXITING)) + err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); + } + release_sock(sk); +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index 24fa396..316dd4e 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -909,7 +909,8 @@ static int sco_sock_shutdown(struct socket *sock, int how) + sco_sock_clear_timer(sk); + __sco_sock_close(sk); + +- if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) ++ if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && ++ !(current->flags & PF_EXITING)) + err = bt_sock_wait_state(sk, BT_CLOSED, + sk->sk_lingertime); + } +@@ -929,7 +930,8 @@ static int sco_sock_release(struct socket *sock) + + sco_sock_close(sk); + +- if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) { ++ if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && ++ !(current->flags & PF_EXITING)) { + lock_sock(sk); + err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); + release_sock(sk); +diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c +index 9203d5a..09152d1 100644 +--- a/net/bridge/br_fdb.c ++++ b/net/bridge/br_fdb.c +@@ -705,9 +705,11 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge_port *p, + int err = 0; + + if (ndm->ndm_flags & NTF_USE) { ++ local_bh_disable(); + rcu_read_lock(); + br_fdb_update(p->br, p, addr, vid, true); + rcu_read_unlock(); ++ local_bh_enable(); + } else { + spin_lock_bh(&p->br->hash_lock); + err = fdb_add_entry(p, addr, ndm->ndm_state, +diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c +index a9a4a1b..8d423bc 100644 +--- a/net/bridge/br_ioctl.c ++++ b/net/bridge/br_ioctl.c +@@ -247,9 +247,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) + if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) + return -EPERM; + +- spin_lock_bh(&br->lock); + br_stp_set_bridge_priority(br, args[1]); +- spin_unlock_bh(&br->lock); + return 0; + + case BRCTL_SET_PORT_PRIORITY: +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c +index 93067ec..7bbc8fe 100644 +--- a/net/bridge/br_multicast.c ++++ b/net/bridge/br_multicast.c +@@ -1056,7 +1056,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, + + err = br_ip6_multicast_add_group(br, port, &grec->grec_mca, + vid); +- if (!err) ++ if (err) + break; + } + +@@ -1086,6 +1086,9 @@ static void br_multicast_add_router(struct net_bridge *br, + struct net_bridge_port *p; + struct hlist_node *slot = NULL; + ++ if (!hlist_unhashed(&port->rlist)) ++ return; ++ + hlist_for_each_entry(p, &br->router_list, rlist) { + if ((unsigned long) port >= (unsigned long) p) + break; +@@ -1113,12 +1116,8 @@ static void br_multicast_mark_router(struct net_bridge *br, + if (port->multicast_router != 1) + return; + +- if (!hlist_unhashed(&port->rlist)) +- goto timer; +- + br_multicast_add_router(br, port); + +-timer: + mod_timer(&port->multicast_router_timer, + now + br->multicast_querier_interval); + } +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index f2d254b..4acfc3e 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -302,6 +302,9 @@ struct br_input_skb_cb { + int igmp; + int mrouters_only; + #endif ++#ifdef CONFIG_BRIDGE_VLAN_FILTERING ++ bool vlan_filtered; ++#endif + }; + + #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) +diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c +index 189ba1e..9a0005a 100644 +--- a/net/bridge/br_stp_if.c ++++ b/net/bridge/br_stp_if.c +@@ -243,12 +243,13 @@ bool br_stp_recalculate_bridge_id(struct net_bridge *br) + return true; + } + +-/* called under bridge lock */ ++/* Acquires and releases bridge lock */ + void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio) + { + struct net_bridge_port *p; + int wasroot; + ++ spin_lock_bh(&br->lock); + wasroot = br_is_root_bridge(br); + + list_for_each_entry(p, &br->port_list, list) { +@@ -266,6 +267,7 @@ void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio) + br_port_state_selection(br); + if (br_is_root_bridge(br) && !wasroot) + br_become_root_bridge(br); ++ spin_unlock_bh(&br->lock); + } + + /* called under bridge lock */ +diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c +index b1c6372..e1bd253 100644 +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -125,7 +125,8 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br, + { + u16 vid; + +- if (!br->vlan_enabled) ++ /* If this packet was not filtered at input, let it pass */ ++ if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) + goto out; + + /* Vlan filter table must be configured at this point. The +@@ -163,8 +164,10 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, + /* If VLAN filtering is disabled on the bridge, all packets are + * permitted. + */ +- if (!br->vlan_enabled) ++ if (!br->vlan_enabled) { ++ BR_INPUT_SKB_CB(skb)->vlan_filtered = false; + return true; ++ } + + /* If there are no vlan in the permitted list, all packets are + * rejected. +@@ -172,6 +175,8 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, + if (!v) + goto drop; + ++ BR_INPUT_SKB_CB(skb)->vlan_filtered = true; ++ + /* If vlan tx offload is disabled on bridge device and frame was + * sent from vlan device on the bridge device, it does not have + * HW accelerated vlan tag. +@@ -179,7 +184,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, + if (unlikely(!vlan_tx_tag_present(skb) && + (skb->protocol == htons(ETH_P_8021Q) || + skb->protocol == htons(ETH_P_8021AD)))) { +- skb = vlan_untag(skb); ++ skb = skb_vlan_untag(skb); + if (unlikely(!skb)) + return false; + } +@@ -228,7 +233,8 @@ bool br_allowed_egress(struct net_bridge *br, + { + u16 vid; + +- if (!br->vlan_enabled) ++ /* If this packet was not filtered at input, let it pass */ ++ if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) + return true; + + if (!v) +@@ -247,6 +253,7 @@ bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid) + struct net_bridge *br = p->br; + struct net_port_vlans *v; + ++ /* If filtering was disabled at input, let it pass. */ + if (!br->vlan_enabled) + return true; + +diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c +index d6be3ed..afeb8e0 100644 +--- a/net/caif/caif_socket.c ++++ b/net/caif/caif_socket.c +@@ -283,7 +283,7 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock, + int copylen; + + ret = -EOPNOTSUPP; +- if (m->msg_flags&MSG_OOB) ++ if (flags & MSG_OOB) + goto read_error; + + skb = skb_recv_datagram(sk, flags, 0 , &ret); +@@ -332,6 +332,10 @@ static long caif_stream_data_wait(struct sock *sk, long timeo) + release_sock(sk); + timeo = schedule_timeout(timeo); + lock_sock(sk); ++ ++ if (sock_flag(sk, SOCK_DEAD)) ++ break; ++ + clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); + } + +@@ -376,6 +380,10 @@ static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock, + struct sk_buff *skb; + + lock_sock(sk); ++ if (sock_flag(sk, SOCK_DEAD)) { ++ err = -ECONNRESET; ++ goto unlock; ++ } + skb = skb_dequeue(&sk->sk_receive_queue); + caif_check_flow_release(sk); + +diff --git a/net/can/af_can.c b/net/can/af_can.c +index a27f8aa..5e9a227 100644 +--- a/net/can/af_can.c ++++ b/net/can/af_can.c +@@ -262,6 +262,9 @@ int can_send(struct sk_buff *skb, int loop) + goto inval_skb; + } + ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ ++ skb_reset_mac_header(skb); + skb_reset_network_header(skb); + skb_reset_transport_header(skb); + +diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c +index 96238ba..de6662b 100644 +--- a/net/ceph/auth_x.c ++++ b/net/ceph/auth_x.c +@@ -13,8 +13,6 @@ + #include "auth_x.h" + #include "auth_x_protocol.h" + +-#define TEMP_TICKET_BUF_LEN 256 +- + static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed); + + static int ceph_x_is_authenticated(struct ceph_auth_client *ac) +@@ -64,7 +62,7 @@ static int ceph_x_encrypt(struct ceph_crypto_key *secret, + } + + static int ceph_x_decrypt(struct ceph_crypto_key *secret, +- void **p, void *end, void *obuf, size_t olen) ++ void **p, void *end, void **obuf, size_t olen) + { + struct ceph_x_encrypt_header head; + size_t head_len = sizeof(head); +@@ -75,8 +73,14 @@ static int ceph_x_decrypt(struct ceph_crypto_key *secret, + return -EINVAL; + + dout("ceph_x_decrypt len %d\n", len); +- ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen, +- *p, len); ++ if (*obuf == NULL) { ++ *obuf = kmalloc(len, GFP_NOFS); ++ if (!*obuf) ++ return -ENOMEM; ++ olen = len; ++ } ++ ++ ret = ceph_decrypt2(secret, &head, &head_len, *obuf, &olen, *p, len); + if (ret) + return ret; + if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC) +@@ -129,139 +133,120 @@ static void remove_ticket_handler(struct ceph_auth_client *ac, + kfree(th); + } + +-static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac, +- struct ceph_crypto_key *secret, +- void *buf, void *end) ++static int process_one_ticket(struct ceph_auth_client *ac, ++ struct ceph_crypto_key *secret, ++ void **p, void *end) + { + struct ceph_x_info *xi = ac->private; +- int num; +- void *p = buf; ++ int type; ++ u8 tkt_struct_v, blob_struct_v; ++ struct ceph_x_ticket_handler *th; ++ void *dbuf = NULL; ++ void *dp, *dend; ++ int dlen; ++ char is_enc; ++ struct timespec validity; ++ struct ceph_crypto_key old_key; ++ void *ticket_buf = NULL; ++ void *tp, *tpend; ++ struct ceph_timespec new_validity; ++ struct ceph_crypto_key new_session_key; ++ struct ceph_buffer *new_ticket_blob; ++ unsigned long new_expires, new_renew_after; ++ u64 new_secret_id; + int ret; +- char *dbuf; +- char *ticket_buf; +- u8 reply_struct_v; + +- dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS); +- if (!dbuf) +- return -ENOMEM; ++ ceph_decode_need(p, end, sizeof(u32) + 1, bad); + +- ret = -ENOMEM; +- ticket_buf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS); +- if (!ticket_buf) +- goto out_dbuf; ++ type = ceph_decode_32(p); ++ dout(" ticket type %d %s\n", type, ceph_entity_type_name(type)); + +- ceph_decode_need(&p, end, 1 + sizeof(u32), bad); +- reply_struct_v = ceph_decode_8(&p); +- if (reply_struct_v != 1) ++ tkt_struct_v = ceph_decode_8(p); ++ if (tkt_struct_v != 1) + goto bad; +- num = ceph_decode_32(&p); +- dout("%d tickets\n", num); +- while (num--) { +- int type; +- u8 tkt_struct_v, blob_struct_v; +- struct ceph_x_ticket_handler *th; +- void *dp, *dend; +- int dlen; +- char is_enc; +- struct timespec validity; +- struct ceph_crypto_key old_key; +- void *tp, *tpend; +- struct ceph_timespec new_validity; +- struct ceph_crypto_key new_session_key; +- struct ceph_buffer *new_ticket_blob; +- unsigned long new_expires, new_renew_after; +- u64 new_secret_id; +- +- ceph_decode_need(&p, end, sizeof(u32) + 1, bad); +- +- type = ceph_decode_32(&p); +- dout(" ticket type %d %s\n", type, ceph_entity_type_name(type)); +- +- tkt_struct_v = ceph_decode_8(&p); +- if (tkt_struct_v != 1) +- goto bad; +- +- th = get_ticket_handler(ac, type); +- if (IS_ERR(th)) { +- ret = PTR_ERR(th); +- goto out; +- } + +- /* blob for me */ +- dlen = ceph_x_decrypt(secret, &p, end, dbuf, +- TEMP_TICKET_BUF_LEN); +- if (dlen <= 0) { +- ret = dlen; +- goto out; +- } +- dout(" decrypted %d bytes\n", dlen); +- dend = dbuf + dlen; +- dp = dbuf; ++ th = get_ticket_handler(ac, type); ++ if (IS_ERR(th)) { ++ ret = PTR_ERR(th); ++ goto out; ++ } + +- tkt_struct_v = ceph_decode_8(&dp); +- if (tkt_struct_v != 1) +- goto bad; ++ /* blob for me */ ++ dlen = ceph_x_decrypt(secret, p, end, &dbuf, 0); ++ if (dlen <= 0) { ++ ret = dlen; ++ goto out; ++ } ++ dout(" decrypted %d bytes\n", dlen); ++ dp = dbuf; ++ dend = dp + dlen; + +- memcpy(&old_key, &th->session_key, sizeof(old_key)); +- ret = ceph_crypto_key_decode(&new_session_key, &dp, dend); +- if (ret) +- goto out; ++ tkt_struct_v = ceph_decode_8(&dp); ++ if (tkt_struct_v != 1) ++ goto bad; + +- ceph_decode_copy(&dp, &new_validity, sizeof(new_validity)); +- ceph_decode_timespec(&validity, &new_validity); +- new_expires = get_seconds() + validity.tv_sec; +- new_renew_after = new_expires - (validity.tv_sec / 4); +- dout(" expires=%lu renew_after=%lu\n", new_expires, +- new_renew_after); ++ memcpy(&old_key, &th->session_key, sizeof(old_key)); ++ ret = ceph_crypto_key_decode(&new_session_key, &dp, dend); ++ if (ret) ++ goto out; + +- /* ticket blob for service */ +- ceph_decode_8_safe(&p, end, is_enc, bad); +- tp = ticket_buf; +- if (is_enc) { +- /* encrypted */ +- dout(" encrypted ticket\n"); +- dlen = ceph_x_decrypt(&old_key, &p, end, ticket_buf, +- TEMP_TICKET_BUF_LEN); +- if (dlen < 0) { +- ret = dlen; +- goto out; +- } +- dlen = ceph_decode_32(&tp); +- } else { +- /* unencrypted */ +- ceph_decode_32_safe(&p, end, dlen, bad); +- ceph_decode_need(&p, end, dlen, bad); +- ceph_decode_copy(&p, ticket_buf, dlen); ++ ceph_decode_copy(&dp, &new_validity, sizeof(new_validity)); ++ ceph_decode_timespec(&validity, &new_validity); ++ new_expires = get_seconds() + validity.tv_sec; ++ new_renew_after = new_expires - (validity.tv_sec / 4); ++ dout(" expires=%lu renew_after=%lu\n", new_expires, ++ new_renew_after); ++ ++ /* ticket blob for service */ ++ ceph_decode_8_safe(p, end, is_enc, bad); ++ if (is_enc) { ++ /* encrypted */ ++ dout(" encrypted ticket\n"); ++ dlen = ceph_x_decrypt(&old_key, p, end, &ticket_buf, 0); ++ if (dlen < 0) { ++ ret = dlen; ++ goto out; + } +- tpend = tp + dlen; +- dout(" ticket blob is %d bytes\n", dlen); +- ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad); +- blob_struct_v = ceph_decode_8(&tp); +- new_secret_id = ceph_decode_64(&tp); +- ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend); +- if (ret) ++ tp = ticket_buf; ++ dlen = ceph_decode_32(&tp); ++ } else { ++ /* unencrypted */ ++ ceph_decode_32_safe(p, end, dlen, bad); ++ ticket_buf = kmalloc(dlen, GFP_NOFS); ++ if (!ticket_buf) { ++ ret = -ENOMEM; + goto out; +- +- /* all is well, update our ticket */ +- ceph_crypto_key_destroy(&th->session_key); +- if (th->ticket_blob) +- ceph_buffer_put(th->ticket_blob); +- th->session_key = new_session_key; +- th->ticket_blob = new_ticket_blob; +- th->validity = new_validity; +- th->secret_id = new_secret_id; +- th->expires = new_expires; +- th->renew_after = new_renew_after; +- dout(" got ticket service %d (%s) secret_id %lld len %d\n", +- type, ceph_entity_type_name(type), th->secret_id, +- (int)th->ticket_blob->vec.iov_len); +- xi->have_keys |= th->service; ++ } ++ tp = ticket_buf; ++ ceph_decode_need(p, end, dlen, bad); ++ ceph_decode_copy(p, ticket_buf, dlen); + } ++ tpend = tp + dlen; ++ dout(" ticket blob is %d bytes\n", dlen); ++ ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad); ++ blob_struct_v = ceph_decode_8(&tp); ++ new_secret_id = ceph_decode_64(&tp); ++ ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend); ++ if (ret) ++ goto out; ++ ++ /* all is well, update our ticket */ ++ ceph_crypto_key_destroy(&th->session_key); ++ if (th->ticket_blob) ++ ceph_buffer_put(th->ticket_blob); ++ th->session_key = new_session_key; ++ th->ticket_blob = new_ticket_blob; ++ th->validity = new_validity; ++ th->secret_id = new_secret_id; ++ th->expires = new_expires; ++ th->renew_after = new_renew_after; ++ dout(" got ticket service %d (%s) secret_id %lld len %d\n", ++ type, ceph_entity_type_name(type), th->secret_id, ++ (int)th->ticket_blob->vec.iov_len); ++ xi->have_keys |= th->service; + +- ret = 0; + out: + kfree(ticket_buf); +-out_dbuf: + kfree(dbuf); + return ret; + +@@ -270,6 +255,34 @@ bad: + goto out; + } + ++static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac, ++ struct ceph_crypto_key *secret, ++ void *buf, void *end) ++{ ++ void *p = buf; ++ u8 reply_struct_v; ++ u32 num; ++ int ret; ++ ++ ceph_decode_8_safe(&p, end, reply_struct_v, bad); ++ if (reply_struct_v != 1) ++ return -EINVAL; ++ ++ ceph_decode_32_safe(&p, end, num, bad); ++ dout("%d tickets\n", num); ++ ++ while (num--) { ++ ret = process_one_ticket(ac, secret, &p, end); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++ ++bad: ++ return -EINVAL; ++} ++ + static int ceph_x_build_authorizer(struct ceph_auth_client *ac, + struct ceph_x_ticket_handler *th, + struct ceph_x_authorizer *au) +@@ -583,13 +596,14 @@ static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac, + struct ceph_x_ticket_handler *th; + int ret = 0; + struct ceph_x_authorize_reply reply; ++ void *preply = &reply; + void *p = au->reply_buf; + void *end = p + sizeof(au->reply_buf); + + th = get_ticket_handler(ac, au->service); + if (IS_ERR(th)) + return PTR_ERR(th); +- ret = ceph_x_decrypt(&th->session_key, &p, end, &reply, sizeof(reply)); ++ ret = ceph_x_decrypt(&th->session_key, &p, end, &preply, sizeof(reply)); + if (ret < 0) + return ret; + if (ret != sizeof(reply)) +diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c +index 074bb2a..0a08902 100644 +--- a/net/ceph/crush/mapper.c ++++ b/net/ceph/crush/mapper.c +@@ -290,6 +290,7 @@ static int is_out(const struct crush_map *map, + * @type: the type of item to choose + * @out: pointer to output vector + * @outpos: our position in that vector ++ * @out_size: size of the out vector + * @tries: number of attempts to make + * @recurse_tries: number of attempts to have recursive chooseleaf make + * @local_retries: localized retries +@@ -302,6 +303,7 @@ static int crush_choose_firstn(const struct crush_map *map, + const __u32 *weight, int weight_max, + int x, int numrep, int type, + int *out, int outpos, ++ int out_size, + unsigned int tries, + unsigned int recurse_tries, + unsigned int local_retries, +@@ -318,11 +320,12 @@ static int crush_choose_firstn(const struct crush_map *map, + int item = 0; + int itemtype; + int collide, reject; ++ int count = out_size; + + dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d\n", recurse_to_leaf ? "_LEAF" : "", + bucket->id, x, outpos, numrep); + +- for (rep = outpos; rep < numrep; rep++) { ++ for (rep = outpos; rep < numrep && count > 0 ; rep++) { + /* keep trying until we get a non-out, non-colliding item */ + ftotal = 0; + skip_rep = 0; +@@ -391,7 +394,7 @@ static int crush_choose_firstn(const struct crush_map *map, + map->buckets[-1-item], + weight, weight_max, + x, outpos+1, 0, +- out2, outpos, ++ out2, outpos, count, + recurse_tries, 0, + local_retries, + local_fallback_retries, +@@ -449,6 +452,7 @@ reject: + dprintk("CHOOSE got %d\n", item); + out[outpos] = item; + outpos++; ++ count--; + } + + dprintk("CHOOSE returns %d\n", outpos); +@@ -640,6 +644,7 @@ int crush_do_rule(const struct crush_map *map, + __u32 step; + int i, j; + int numrep; ++ int out_size; + /* + * the original choose_total_tries value was off by one (it + * counted "retries" and not "tries"). add one. +@@ -740,6 +745,7 @@ int crush_do_rule(const struct crush_map *map, + x, numrep, + curstep->arg2, + o+osize, j, ++ result_max-osize, + choose_tries, + recurse_tries, + choose_local_retries, +@@ -747,11 +753,13 @@ int crush_do_rule(const struct crush_map *map, + recurse_to_leaf, + c+osize); + } else { ++ out_size = ((numrep < (result_max-osize)) ? ++ numrep : (result_max-osize)); + crush_choose_indep( + map, + map->buckets[-1-w[i]], + weight, weight_max, +- x, numrep, numrep, ++ x, out_size, numrep, + curstep->arg2, + o+osize, j, + choose_tries, +@@ -760,7 +768,7 @@ int crush_do_rule(const struct crush_map *map, + recurse_to_leaf, + c+osize, + 0); +- osize += numrep; ++ osize += out_size; + } + } + +diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c +index 6e7a236..06f19b9 100644 +--- a/net/ceph/crypto.c ++++ b/net/ceph/crypto.c +@@ -89,11 +89,82 @@ static struct crypto_blkcipher *ceph_crypto_alloc_cipher(void) + + static const u8 *aes_iv = (u8 *)CEPH_AES_IV; + ++/* ++ * Should be used for buffers allocated with ceph_kvmalloc(). ++ * Currently these are encrypt out-buffer (ceph_buffer) and decrypt ++ * in-buffer (msg front). ++ * ++ * Dispose of @sgt with teardown_sgtable(). ++ * ++ * @prealloc_sg is to avoid memory allocation inside sg_alloc_table() ++ * in cases where a single sg is sufficient. No attempt to reduce the ++ * number of sgs by squeezing physically contiguous pages together is ++ * made though, for simplicity. ++ */ ++static int setup_sgtable(struct sg_table *sgt, struct scatterlist *prealloc_sg, ++ const void *buf, unsigned int buf_len) ++{ ++ struct scatterlist *sg; ++ const bool is_vmalloc = is_vmalloc_addr(buf); ++ unsigned int off = offset_in_page(buf); ++ unsigned int chunk_cnt = 1; ++ unsigned int chunk_len = PAGE_ALIGN(off + buf_len); ++ int i; ++ int ret; ++ ++ if (buf_len == 0) { ++ memset(sgt, 0, sizeof(*sgt)); ++ return -EINVAL; ++ } ++ ++ if (is_vmalloc) { ++ chunk_cnt = chunk_len >> PAGE_SHIFT; ++ chunk_len = PAGE_SIZE; ++ } ++ ++ if (chunk_cnt > 1) { ++ ret = sg_alloc_table(sgt, chunk_cnt, GFP_NOFS); ++ if (ret) ++ return ret; ++ } else { ++ WARN_ON(chunk_cnt != 1); ++ sg_init_table(prealloc_sg, 1); ++ sgt->sgl = prealloc_sg; ++ sgt->nents = sgt->orig_nents = 1; ++ } ++ ++ for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) { ++ struct page *page; ++ unsigned int len = min(chunk_len - off, buf_len); ++ ++ if (is_vmalloc) ++ page = vmalloc_to_page(buf); ++ else ++ page = virt_to_page(buf); ++ ++ sg_set_page(sg, page, len, off); ++ ++ off = 0; ++ buf += len; ++ buf_len -= len; ++ } ++ WARN_ON(buf_len != 0); ++ ++ return 0; ++} ++ ++static void teardown_sgtable(struct sg_table *sgt) ++{ ++ if (sgt->orig_nents > 1) ++ sg_free_table(sgt); ++} ++ + static int ceph_aes_encrypt(const void *key, int key_len, + void *dst, size_t *dst_len, + const void *src, size_t src_len) + { +- struct scatterlist sg_in[2], sg_out[1]; ++ struct scatterlist sg_in[2], prealloc_sg; ++ struct sg_table sg_out; + struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); + struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 }; + int ret; +@@ -109,16 +180,18 @@ static int ceph_aes_encrypt(const void *key, int key_len, + + *dst_len = src_len + zero_padding; + +- crypto_blkcipher_setkey((void *)tfm, key, key_len); + sg_init_table(sg_in, 2); + sg_set_buf(&sg_in[0], src, src_len); + sg_set_buf(&sg_in[1], pad, zero_padding); +- sg_init_table(sg_out, 1); +- sg_set_buf(sg_out, dst, *dst_len); ++ ret = setup_sgtable(&sg_out, &prealloc_sg, dst, *dst_len); ++ if (ret) ++ goto out_tfm; ++ ++ crypto_blkcipher_setkey((void *)tfm, key, key_len); + iv = crypto_blkcipher_crt(tfm)->iv; + ivsize = crypto_blkcipher_ivsize(tfm); +- + memcpy(iv, aes_iv, ivsize); ++ + /* + print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1, + key, key_len, 1); +@@ -127,16 +200,22 @@ static int ceph_aes_encrypt(const void *key, int key_len, + print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1, + pad, zero_padding, 1); + */ +- ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in, ++ ret = crypto_blkcipher_encrypt(&desc, sg_out.sgl, sg_in, + src_len + zero_padding); +- crypto_free_blkcipher(tfm); +- if (ret < 0) ++ if (ret < 0) { + pr_err("ceph_aes_crypt failed %d\n", ret); ++ goto out_sg; ++ } + /* + print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1, + dst, *dst_len, 1); + */ +- return 0; ++ ++out_sg: ++ teardown_sgtable(&sg_out); ++out_tfm: ++ crypto_free_blkcipher(tfm); ++ return ret; + } + + static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, +@@ -144,7 +223,8 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, + const void *src1, size_t src1_len, + const void *src2, size_t src2_len) + { +- struct scatterlist sg_in[3], sg_out[1]; ++ struct scatterlist sg_in[3], prealloc_sg; ++ struct sg_table sg_out; + struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); + struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 }; + int ret; +@@ -160,17 +240,19 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, + + *dst_len = src1_len + src2_len + zero_padding; + +- crypto_blkcipher_setkey((void *)tfm, key, key_len); + sg_init_table(sg_in, 3); + sg_set_buf(&sg_in[0], src1, src1_len); + sg_set_buf(&sg_in[1], src2, src2_len); + sg_set_buf(&sg_in[2], pad, zero_padding); +- sg_init_table(sg_out, 1); +- sg_set_buf(sg_out, dst, *dst_len); ++ ret = setup_sgtable(&sg_out, &prealloc_sg, dst, *dst_len); ++ if (ret) ++ goto out_tfm; ++ ++ crypto_blkcipher_setkey((void *)tfm, key, key_len); + iv = crypto_blkcipher_crt(tfm)->iv; + ivsize = crypto_blkcipher_ivsize(tfm); +- + memcpy(iv, aes_iv, ivsize); ++ + /* + print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1, + key, key_len, 1); +@@ -181,23 +263,30 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, + print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1, + pad, zero_padding, 1); + */ +- ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in, ++ ret = crypto_blkcipher_encrypt(&desc, sg_out.sgl, sg_in, + src1_len + src2_len + zero_padding); +- crypto_free_blkcipher(tfm); +- if (ret < 0) ++ if (ret < 0) { + pr_err("ceph_aes_crypt2 failed %d\n", ret); ++ goto out_sg; ++ } + /* + print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1, + dst, *dst_len, 1); + */ +- return 0; ++ ++out_sg: ++ teardown_sgtable(&sg_out); ++out_tfm: ++ crypto_free_blkcipher(tfm); ++ return ret; + } + + static int ceph_aes_decrypt(const void *key, int key_len, + void *dst, size_t *dst_len, + const void *src, size_t src_len) + { +- struct scatterlist sg_in[1], sg_out[2]; ++ struct sg_table sg_in; ++ struct scatterlist sg_out[2], prealloc_sg; + struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); + struct blkcipher_desc desc = { .tfm = tfm }; + char pad[16]; +@@ -209,16 +298,16 @@ static int ceph_aes_decrypt(const void *key, int key_len, + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + +- crypto_blkcipher_setkey((void *)tfm, key, key_len); +- sg_init_table(sg_in, 1); + sg_init_table(sg_out, 2); +- sg_set_buf(sg_in, src, src_len); + sg_set_buf(&sg_out[0], dst, *dst_len); + sg_set_buf(&sg_out[1], pad, sizeof(pad)); ++ ret = setup_sgtable(&sg_in, &prealloc_sg, src, src_len); ++ if (ret) ++ goto out_tfm; + ++ crypto_blkcipher_setkey((void *)tfm, key, key_len); + iv = crypto_blkcipher_crt(tfm)->iv; + ivsize = crypto_blkcipher_ivsize(tfm); +- + memcpy(iv, aes_iv, ivsize); + + /* +@@ -227,12 +316,10 @@ static int ceph_aes_decrypt(const void *key, int key_len, + print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1, + src, src_len, 1); + */ +- +- ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len); +- crypto_free_blkcipher(tfm); ++ ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in.sgl, src_len); + if (ret < 0) { + pr_err("ceph_aes_decrypt failed %d\n", ret); +- return ret; ++ goto out_sg; + } + + if (src_len <= *dst_len) +@@ -250,7 +337,12 @@ static int ceph_aes_decrypt(const void *key, int key_len, + print_hex_dump(KERN_ERR, "dec out: ", DUMP_PREFIX_NONE, 16, 1, + dst, *dst_len, 1); + */ +- return 0; ++ ++out_sg: ++ teardown_sgtable(&sg_in); ++out_tfm: ++ crypto_free_blkcipher(tfm); ++ return ret; + } + + static int ceph_aes_decrypt2(const void *key, int key_len, +@@ -258,7 +350,8 @@ static int ceph_aes_decrypt2(const void *key, int key_len, + void *dst2, size_t *dst2_len, + const void *src, size_t src_len) + { +- struct scatterlist sg_in[1], sg_out[3]; ++ struct sg_table sg_in; ++ struct scatterlist sg_out[3], prealloc_sg; + struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); + struct blkcipher_desc desc = { .tfm = tfm }; + char pad[16]; +@@ -270,17 +363,17 @@ static int ceph_aes_decrypt2(const void *key, int key_len, + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + +- sg_init_table(sg_in, 1); +- sg_set_buf(sg_in, src, src_len); + sg_init_table(sg_out, 3); + sg_set_buf(&sg_out[0], dst1, *dst1_len); + sg_set_buf(&sg_out[1], dst2, *dst2_len); + sg_set_buf(&sg_out[2], pad, sizeof(pad)); ++ ret = setup_sgtable(&sg_in, &prealloc_sg, src, src_len); ++ if (ret) ++ goto out_tfm; + + crypto_blkcipher_setkey((void *)tfm, key, key_len); + iv = crypto_blkcipher_crt(tfm)->iv; + ivsize = crypto_blkcipher_ivsize(tfm); +- + memcpy(iv, aes_iv, ivsize); + + /* +@@ -289,12 +382,10 @@ static int ceph_aes_decrypt2(const void *key, int key_len, + print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1, + src, src_len, 1); + */ +- +- ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len); +- crypto_free_blkcipher(tfm); ++ ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in.sgl, src_len); + if (ret < 0) { + pr_err("ceph_aes_decrypt failed %d\n", ret); +- return ret; ++ goto out_sg; + } + + if (src_len <= *dst1_len) +@@ -324,7 +415,11 @@ static int ceph_aes_decrypt2(const void *key, int key_len, + dst2, *dst2_len, 1); + */ + +- return 0; ++out_sg: ++ teardown_sgtable(&sg_in); ++out_tfm: ++ crypto_free_blkcipher(tfm); ++ return ret; + } + + +diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c +index 988721a..2e87eec 100644 +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -291,7 +291,11 @@ int ceph_msgr_init(void) + if (ceph_msgr_slab_init()) + return -ENOMEM; + +- ceph_msgr_wq = alloc_workqueue("ceph-msgr", 0, 0); ++ /* ++ * The number of active work items is limited by the number of ++ * connections, so leave @max_active at default. ++ */ ++ ceph_msgr_wq = alloc_workqueue("ceph-msgr", WQ_MEM_RECLAIM, 0); + if (ceph_msgr_wq) + return 0; + +@@ -900,7 +904,7 @@ static void ceph_msg_data_pages_cursor_init(struct ceph_msg_data_cursor *cursor, + BUG_ON(page_count > (int)USHRT_MAX); + cursor->page_count = (unsigned short)page_count; + BUG_ON(length > SIZE_MAX - cursor->page_offset); +- cursor->last_piece = (size_t)cursor->page_offset + length <= PAGE_SIZE; ++ cursor->last_piece = cursor->page_offset + cursor->resid <= PAGE_SIZE; + } + + static struct page * +diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c +index 2ac9ef3..dbcbf5a 100644 +--- a/net/ceph/mon_client.c ++++ b/net/ceph/mon_client.c +@@ -1041,7 +1041,15 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con, + if (!m) { + pr_info("alloc_msg unknown type %d\n", type); + *skip = 1; ++ } else if (front_len > m->front_alloc_len) { ++ pr_warning("mon_alloc_msg front %d > prealloc %d (%u#%llu)\n", ++ front_len, m->front_alloc_len, ++ (unsigned int)con->peer_name.type, ++ le64_to_cpu(con->peer_name.num)); ++ ceph_msg_put(m); ++ m = ceph_msg_new(type, front_len, GFP_NOFS, false); + } ++ + return m; + } + +diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c +index 0676f2b..5b7ef5b 100644 +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -977,12 +977,24 @@ static void put_osd(struct ceph_osd *osd) + */ + static void __remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) + { +- dout("__remove_osd %p\n", osd); +- BUG_ON(!list_empty(&osd->o_requests)); +- rb_erase(&osd->o_node, &osdc->osds); ++ dout("%s %p osd%d\n", __func__, osd, osd->o_osd); ++ WARN_ON(!list_empty(&osd->o_requests)); ++ WARN_ON(!list_empty(&osd->o_linger_requests)); ++ + list_del_init(&osd->o_osd_lru); +- ceph_con_close(&osd->o_con); +- put_osd(osd); ++ rb_erase(&osd->o_node, &osdc->osds); ++ RB_CLEAR_NODE(&osd->o_node); ++} ++ ++static void remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) ++{ ++ dout("%s %p osd%d\n", __func__, osd, osd->o_osd); ++ ++ if (!RB_EMPTY_NODE(&osd->o_node)) { ++ ceph_con_close(&osd->o_con); ++ __remove_osd(osdc, osd); ++ put_osd(osd); ++ } + } + + static void remove_all_osds(struct ceph_osd_client *osdc) +@@ -992,7 +1004,7 @@ static void remove_all_osds(struct ceph_osd_client *osdc) + while (!RB_EMPTY_ROOT(&osdc->osds)) { + struct ceph_osd *osd = rb_entry(rb_first(&osdc->osds), + struct ceph_osd, o_node); +- __remove_osd(osdc, osd); ++ remove_osd(osdc, osd); + } + mutex_unlock(&osdc->request_mutex); + } +@@ -1022,7 +1034,7 @@ static void remove_old_osds(struct ceph_osd_client *osdc) + list_for_each_entry_safe(osd, nosd, &osdc->osd_lru, o_osd_lru) { + if (time_before(jiffies, osd->lru_ttl)) + break; +- __remove_osd(osdc, osd); ++ remove_osd(osdc, osd); + } + mutex_unlock(&osdc->request_mutex); + } +@@ -1037,8 +1049,7 @@ static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) + dout("__reset_osd %p osd%d\n", osd, osd->o_osd); + if (list_empty(&osd->o_requests) && + list_empty(&osd->o_linger_requests)) { +- __remove_osd(osdc, osd); +- ++ remove_osd(osdc, osd); + return -ENODEV; + } + +@@ -1840,6 +1851,7 @@ static void reset_changed_osds(struct ceph_osd_client *osdc) + { + struct rb_node *p, *n; + ++ dout("%s %p\n", __func__, osdc); + for (p = rb_first(&osdc->osds); p; p = n) { + struct ceph_osd *osd = rb_entry(p, struct ceph_osd, o_node); + +@@ -1920,20 +1932,29 @@ static void kick_requests(struct ceph_osd_client *osdc, bool force_resend, + err = __map_request(osdc, req, + force_resend || force_resend_writes); + dout("__map_request returned %d\n", err); +- if (err == 0) +- continue; /* no change and no osd was specified */ + if (err < 0) + continue; /* hrm! */ +- if (req->r_osd == NULL) { +- dout("tid %llu maps to no valid osd\n", req->r_tid); +- needmap++; /* request a newer map */ +- continue; +- } ++ if (req->r_osd == NULL || err > 0) { ++ if (req->r_osd == NULL) { ++ dout("lingering %p tid %llu maps to no osd\n", ++ req, req->r_tid); ++ /* ++ * A homeless lingering request makes ++ * no sense, as it's job is to keep ++ * a particular OSD connection open. ++ * Request a newer map and kick the ++ * request, knowing that it won't be ++ * resent until we actually get a map ++ * that can tell us where to send it. ++ */ ++ needmap++; ++ } + +- dout("kicking lingering %p tid %llu osd%d\n", req, req->r_tid, +- req->r_osd ? req->r_osd->o_osd : -1); +- __register_request(osdc, req); +- __unregister_linger_request(osdc, req); ++ dout("kicking lingering %p tid %llu osd%d\n", req, ++ req->r_tid, req->r_osd ? req->r_osd->o_osd : -1); ++ __register_request(osdc, req); ++ __unregister_linger_request(osdc, req); ++ } + } + reset_changed_osds(osdc); + mutex_unlock(&osdc->request_mutex); +diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c +index aade4a5..bde94d8 100644 +--- a/net/ceph/osdmap.c ++++ b/net/ceph/osdmap.c +@@ -89,7 +89,7 @@ static int crush_decode_tree_bucket(void **p, void *end, + { + int j; + dout("crush_decode_tree_bucket %p to %p\n", *p, end); +- ceph_decode_32_safe(p, end, b->num_nodes, bad); ++ ceph_decode_8_safe(p, end, b->num_nodes, bad); + b->node_weights = kcalloc(b->num_nodes, sizeof(u32), GFP_NOFS); + if (b->node_weights == NULL) + return -ENOMEM; +diff --git a/net/compat.c b/net/compat.c +index f50161f..d125290 100644 +--- a/net/compat.c ++++ b/net/compat.c +@@ -71,6 +71,13 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg) + __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || + __get_user(kmsg->msg_flags, &umsg->msg_flags)) + return -EFAULT; ++ ++ if (!tmp1) ++ kmsg->msg_namelen = 0; ++ ++ if (kmsg->msg_namelen < 0) ++ return -EINVAL; ++ + if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) + kmsg->msg_namelen = sizeof(struct sockaddr_storage); + kmsg->msg_name = compat_ptr(tmp1); +@@ -85,7 +92,7 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, + { + int tot_len; + +- if (kern_msg->msg_namelen) { ++ if (kern_msg->msg_name && kern_msg->msg_namelen) { + if (mode == VERIFY_READ) { + int err = move_addr_to_kernel(kern_msg->msg_name, + kern_msg->msg_namelen, +@@ -93,10 +100,11 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, + if (err < 0) + return err; + } +- if (kern_msg->msg_name) +- kern_msg->msg_name = kern_address; +- } else ++ kern_msg->msg_name = kern_address; ++ } else { + kern_msg->msg_name = NULL; ++ kern_msg->msg_namelen = 0; ++ } + + tot_len = iov_from_user_compat_to_kern(kern_iov, + (struct compat_iovec __user *)kern_msg->msg_iov, +@@ -737,24 +745,18 @@ static unsigned char nas[21] = { + + asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) + { +- if (flags & MSG_CMSG_COMPAT) +- return -EINVAL; + return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); + } + + asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, + unsigned int vlen, unsigned int flags) + { +- if (flags & MSG_CMSG_COMPAT) +- return -EINVAL; + return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, + flags | MSG_CMSG_COMPAT); + } + + asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) + { +- if (flags & MSG_CMSG_COMPAT) +- return -EINVAL; + return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); + } + +@@ -777,9 +779,6 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, + int datagrams; + struct timespec ktspec; + +- if (flags & MSG_CMSG_COMPAT) +- return -EINVAL; +- + if (timeout == NULL) + return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, + flags | MSG_CMSG_COMPAT, NULL); +diff --git a/net/core/dev.c b/net/core/dev.c +index 62f13f3..47a95f1 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -940,7 +940,7 @@ bool dev_valid_name(const char *name) + return false; + + while (*name) { +- if (*name == '/' || isspace(*name)) ++ if (*name == '/' || *name == ':' || isspace(*name)) + return false; + name++; + } +@@ -1709,6 +1709,7 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) + + skb_scrub_packet(skb, true); + skb->protocol = eth_type_trans(skb, dev); ++ skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); + + return netif_rx_internal(skb); + } +@@ -2529,11 +2530,14 @@ netdev_features_t netif_skb_dev_features(struct sk_buff *skb, + if (skb_shinfo(skb)->gso_segs > dev->gso_max_segs) + features &= ~NETIF_F_GSO_MASK; + +- if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) { +- struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; +- protocol = veh->h_vlan_encapsulated_proto; +- } else if (!vlan_tx_tag_present(skb)) { +- return harmonize_features(skb, dev, features); ++ if (!vlan_tx_tag_present(skb)) { ++ if (unlikely(protocol == htons(ETH_P_8021Q) || ++ protocol == htons(ETH_P_8021AD))) { ++ struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; ++ protocol = veh->h_vlan_encapsulated_proto; ++ } else { ++ return harmonize_features(skb, dev, features); ++ } + } + + features &= (dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX | +@@ -2771,7 +2775,9 @@ static void skb_update_prio(struct sk_buff *skb) + #define skb_update_prio(skb) + #endif + +-static DEFINE_PER_CPU(int, xmit_recursion); ++DEFINE_PER_CPU(int, xmit_recursion); ++EXPORT_SYMBOL(xmit_recursion); ++ + #define RECURSION_LIMIT 10 + + /** +@@ -3554,7 +3560,7 @@ another_round: + + if (skb->protocol == cpu_to_be16(ETH_P_8021Q) || + skb->protocol == cpu_to_be16(ETH_P_8021AD)) { +- skb = vlan_untag(skb); ++ skb = skb_vlan_untag(skb); + if (unlikely(!skb)) + goto unlock; + } +@@ -4701,9 +4707,14 @@ static void netdev_adjacent_sysfs_del(struct net_device *dev, + sysfs_remove_link(&(dev->dev.kobj), linkname); + } + +-#define netdev_adjacent_is_neigh_list(dev, dev_list) \ +- (dev_list == &dev->adj_list.upper || \ +- dev_list == &dev->adj_list.lower) ++static inline bool netdev_adjacent_is_neigh_list(struct net_device *dev, ++ struct net_device *adj_dev, ++ struct list_head *dev_list) ++{ ++ return (dev_list == &dev->adj_list.upper || ++ dev_list == &dev->adj_list.lower) && ++ net_eq(dev_net(dev), dev_net(adj_dev)); ++} + + static int __netdev_adjacent_dev_insert(struct net_device *dev, + struct net_device *adj_dev, +@@ -4733,7 +4744,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, + pr_debug("dev_hold for %s, because of link added from %s to %s\n", + adj_dev->name, dev->name, adj_dev->name); + +- if (netdev_adjacent_is_neigh_list(dev, dev_list)) { ++ if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) { + ret = netdev_adjacent_sysfs_add(dev, adj_dev, dev_list); + if (ret) + goto free_adj; +@@ -4754,7 +4765,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, + return 0; + + remove_symlinks: +- if (netdev_adjacent_is_neigh_list(dev, dev_list)) ++ if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) + netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); + free_adj: + kfree(adj); +@@ -4787,7 +4798,7 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev, + if (adj->master) + sysfs_remove_link(&(dev->dev.kobj), "master"); + +- if (netdev_adjacent_is_neigh_list(dev, dev_list)) ++ if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) + netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); + + list_del_rcu(&adj->list); +@@ -4892,7 +4903,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, + if (__netdev_find_adj(upper_dev, dev, &upper_dev->all_adj_list.upper)) + return -EBUSY; + +- if (__netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper)) ++ if (__netdev_find_adj(dev, upper_dev, &dev->adj_list.upper)) + return -EEXIST; + + if (master && netdev_master_upper_dev_get(dev)) +@@ -5057,11 +5068,65 @@ void netdev_upper_dev_unlink(struct net_device *dev, + } + EXPORT_SYMBOL(netdev_upper_dev_unlink); + ++void netdev_adjacent_add_links(struct net_device *dev) ++{ ++ struct netdev_adjacent *iter; ++ ++ struct net *net = dev_net(dev); ++ ++ list_for_each_entry(iter, &dev->adj_list.upper, list) { ++ if (!net_eq(net,dev_net(iter->dev))) ++ continue; ++ netdev_adjacent_sysfs_add(iter->dev, dev, ++ &iter->dev->adj_list.lower); ++ netdev_adjacent_sysfs_add(dev, iter->dev, ++ &dev->adj_list.upper); ++ } ++ ++ list_for_each_entry(iter, &dev->adj_list.lower, list) { ++ if (!net_eq(net,dev_net(iter->dev))) ++ continue; ++ netdev_adjacent_sysfs_add(iter->dev, dev, ++ &iter->dev->adj_list.upper); ++ netdev_adjacent_sysfs_add(dev, iter->dev, ++ &dev->adj_list.lower); ++ } ++} ++ ++void netdev_adjacent_del_links(struct net_device *dev) ++{ ++ struct netdev_adjacent *iter; ++ ++ struct net *net = dev_net(dev); ++ ++ list_for_each_entry(iter, &dev->adj_list.upper, list) { ++ if (!net_eq(net,dev_net(iter->dev))) ++ continue; ++ netdev_adjacent_sysfs_del(iter->dev, dev->name, ++ &iter->dev->adj_list.lower); ++ netdev_adjacent_sysfs_del(dev, iter->dev->name, ++ &dev->adj_list.upper); ++ } ++ ++ list_for_each_entry(iter, &dev->adj_list.lower, list) { ++ if (!net_eq(net,dev_net(iter->dev))) ++ continue; ++ netdev_adjacent_sysfs_del(iter->dev, dev->name, ++ &iter->dev->adj_list.upper); ++ netdev_adjacent_sysfs_del(dev, iter->dev->name, ++ &dev->adj_list.lower); ++ } ++} ++ + void netdev_adjacent_rename_links(struct net_device *dev, char *oldname) + { + struct netdev_adjacent *iter; + ++ struct net *net = dev_net(dev); ++ + list_for_each_entry(iter, &dev->adj_list.upper, list) { ++ if (!net_eq(net,dev_net(iter->dev))) ++ continue; + netdev_adjacent_sysfs_del(iter->dev, oldname, + &iter->dev->adj_list.lower); + netdev_adjacent_sysfs_add(iter->dev, dev, +@@ -5069,6 +5134,8 @@ void netdev_adjacent_rename_links(struct net_device *dev, char *oldname) + } + + list_for_each_entry(iter, &dev->adj_list.lower, list) { ++ if (!net_eq(net,dev_net(iter->dev))) ++ continue; + netdev_adjacent_sysfs_del(iter->dev, oldname, + &iter->dev->adj_list.upper); + netdev_adjacent_sysfs_add(iter->dev, dev, +@@ -6675,6 +6742,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char + + /* Send a netdev-removed uevent to the old namespace */ + kobject_uevent(&dev->dev.kobj, KOBJ_REMOVE); ++ netdev_adjacent_del_links(dev); + + /* Actually switch the network namespace */ + dev_net_set(dev, net); +@@ -6689,6 +6757,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char + + /* Send a netdev-add uevent to the new namespace */ + kobject_uevent(&dev->dev.kobj, KOBJ_ADD); ++ netdev_adjacent_add_links(dev); + + /* Fixup kobjects */ + err = device_rename(&dev->dev, dev->name); +@@ -6745,10 +6814,20 @@ static int dev_cpu_callback(struct notifier_block *nfb, + oldsd->output_queue = NULL; + oldsd->output_queue_tailp = &oldsd->output_queue; + } +- /* Append NAPI poll list from offline CPU. */ +- if (!list_empty(&oldsd->poll_list)) { +- list_splice_init(&oldsd->poll_list, &sd->poll_list); +- raise_softirq_irqoff(NET_RX_SOFTIRQ); ++ /* Append NAPI poll list from offline CPU, with one exception : ++ * process_backlog() must be called by cpu owning percpu backlog. ++ * We properly handle process_queue & input_pkt_queue later. ++ */ ++ while (!list_empty(&oldsd->poll_list)) { ++ struct napi_struct *napi = list_first_entry(&oldsd->poll_list, ++ struct napi_struct, ++ poll_list); ++ ++ list_del_init(&napi->poll_list); ++ if (napi->poll == process_backlog) ++ napi->state = 0; ++ else ++ ____napi_schedule(sd, napi); + } + + raise_softirq_irqoff(NET_TX_SOFTIRQ); +@@ -6759,7 +6838,7 @@ static int dev_cpu_callback(struct notifier_block *nfb, + netif_rx_internal(skb); + input_queue_head_incr(oldsd); + } +- while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) { ++ while ((skb = skb_dequeue(&oldsd->input_pkt_queue))) { + netif_rx_internal(skb); + input_queue_head_incr(oldsd); + } +diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c +index 9d3d9e7..372ac66 100644 +--- a/net/core/gen_stats.c ++++ b/net/core/gen_stats.c +@@ -32,6 +32,9 @@ gnet_stats_copy(struct gnet_dump *d, int type, void *buf, int size) + return 0; + + nla_put_failure: ++ kfree(d->xstats); ++ d->xstats = NULL; ++ d->xstats_len = 0; + spin_unlock_bh(d->lock); + return -1; + } +@@ -217,7 +220,9 @@ int + gnet_stats_copy_app(struct gnet_dump *d, void *st, int len) + { + if (d->compat_xstats) { +- d->xstats = st; ++ d->xstats = kmemdup(st, len, GFP_ATOMIC); ++ if (!d->xstats) ++ goto err_out; + d->xstats_len = len; + } + +@@ -225,6 +230,11 @@ gnet_stats_copy_app(struct gnet_dump *d, void *st, int len) + return gnet_stats_copy(d, TCA_STATS_APP, st, len); + + return 0; ++ ++err_out: ++ d->xstats_len = 0; ++ spin_unlock_bh(d->lock); ++ return -1; + } + EXPORT_SYMBOL(gnet_stats_copy_app); + +@@ -257,6 +267,9 @@ gnet_stats_finish_copy(struct gnet_dump *d) + return -1; + } + ++ kfree(d->xstats); ++ d->xstats = NULL; ++ d->xstats_len = 0; + spin_unlock_bh(d->lock); + return 0; + } +diff --git a/net/core/iovec.c b/net/core/iovec.c +index b618694..26dc006 100644 +--- a/net/core/iovec.c ++++ b/net/core/iovec.c +@@ -39,7 +39,7 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a + { + int size, ct, err; + +- if (m->msg_namelen) { ++ if (m->msg_name && m->msg_namelen) { + if (mode == VERIFY_READ) { + void __user *namep; + namep = (void __user __force *) m->msg_name; +@@ -48,10 +48,10 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a + if (err < 0) + return err; + } +- if (m->msg_name) +- m->msg_name = address; ++ m->msg_name = address; + } else { + m->msg_name = NULL; ++ m->msg_namelen = 0; + } + + size = m->msg_iovlen * sizeof(struct iovec); +@@ -107,6 +107,10 @@ EXPORT_SYMBOL(memcpy_toiovecend); + int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, + int offset, int len) + { ++ /* No data? Done! */ ++ if (len == 0) ++ return 0; ++ + /* Skip over the finished iovecs */ + while (offset >= iov->iov_len) { + offset -= iov->iov_len; +diff --git a/net/core/neighbour.c b/net/core/neighbour.c +index 7d95f69..0f062c6 100644 +--- a/net/core/neighbour.c ++++ b/net/core/neighbour.c +@@ -976,6 +976,8 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) + rc = 0; + if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE)) + goto out_unlock_bh; ++ if (neigh->dead) ++ goto out_dead; + + if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) { + if (NEIGH_VAR(neigh->parms, MCAST_PROBES) + +@@ -1032,6 +1034,13 @@ out_unlock_bh: + write_unlock(&neigh->lock); + local_bh_enable(); + return rc; ++ ++out_dead: ++ if (neigh->nud_state & NUD_STALE) ++ goto out_unlock_bh; ++ write_unlock_bh(&neigh->lock); ++ kfree_skb(skb); ++ return 1; + } + EXPORT_SYMBOL(__neigh_event_send); + +@@ -1095,6 +1104,8 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, + if (!(flags & NEIGH_UPDATE_F_ADMIN) && + (old & (NUD_NOARP | NUD_PERMANENT))) + goto out; ++ if (neigh->dead) ++ goto out; + + if (!(new & NUD_VALID)) { + neigh_del_timer(neigh); +@@ -1244,6 +1255,8 @@ EXPORT_SYMBOL(neigh_update); + */ + void __neigh_set_probe_once(struct neighbour *neigh) + { ++ if (neigh->dead) ++ return; + neigh->updated = jiffies; + if (!(neigh->nud_state & NUD_FAILED)) + return; +diff --git a/net/core/netpoll.c b/net/core/netpoll.c +index df9e6b1..723fa7d 100644 +--- a/net/core/netpoll.c ++++ b/net/core/netpoll.c +@@ -788,7 +788,7 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) + } + + if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { +- skb = vlan_untag(skb); ++ skb = skb_vlan_untag(skb); + if (unlikely(!skb)) + goto out; + } +diff --git a/net/core/pktgen.c b/net/core/pktgen.c +index fdac61c..ca68d32 100644 +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -2812,25 +2812,25 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, + skb->dev = odev; + skb->pkt_type = PACKET_HOST; + ++ pktgen_finalize_skb(pkt_dev, skb, datalen); ++ + if (!(pkt_dev->flags & F_UDPCSUM)) { + skb->ip_summed = CHECKSUM_NONE; + } else if (odev->features & NETIF_F_V4_CSUM) { + skb->ip_summed = CHECKSUM_PARTIAL; + skb->csum = 0; +- udp4_hwcsum(skb, udph->source, udph->dest); ++ udp4_hwcsum(skb, iph->saddr, iph->daddr); + } else { +- __wsum csum = udp_csum(skb); ++ __wsum csum = skb_checksum(skb, skb_transport_offset(skb), datalen + 8, 0); + + /* add protocol-dependent pseudo-header */ +- udph->check = csum_tcpudp_magic(udph->source, udph->dest, ++ udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, + datalen + 8, IPPROTO_UDP, csum); + + if (udph->check == 0) + udph->check = CSUM_MANGLED_0; + } + +- pktgen_finalize_skb(pkt_dev, skb, datalen); +- + #ifdef CONFIG_XFRM + if (!process_ipsec(pkt_dev, skb, protocol)) + return NULL; +@@ -2946,6 +2946,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, + skb->dev = odev; + skb->pkt_type = PACKET_HOST; + ++ pktgen_finalize_skb(pkt_dev, skb, datalen); ++ + if (!(pkt_dev->flags & F_UDPCSUM)) { + skb->ip_summed = CHECKSUM_NONE; + } else if (odev->features & NETIF_F_V6_CSUM) { +@@ -2954,7 +2956,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, + skb->csum_offset = offsetof(struct udphdr, check); + udph->check = ~csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, 0); + } else { +- __wsum csum = udp_csum(skb); ++ __wsum csum = skb_checksum(skb, skb_transport_offset(skb), udplen, 0); + + /* add protocol-dependent pseudo-header */ + udph->check = csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, csum); +@@ -2963,8 +2965,6 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, + udph->check = CSUM_MANGLED_0; + } + +- pktgen_finalize_skb(pkt_dev, skb, datalen); +- + return skb; + } + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index f19d2f2..c1bfd5a 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -799,7 +799,8 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev, + (nla_total_size(sizeof(struct ifla_vf_mac)) + + nla_total_size(sizeof(struct ifla_vf_vlan)) + + nla_total_size(sizeof(struct ifla_vf_tx_rate)) + +- nla_total_size(sizeof(struct ifla_vf_spoofchk))); ++ nla_total_size(sizeof(struct ifla_vf_spoofchk)) + ++ nla_total_size(sizeof(struct ifla_vf_link_state))); + return size; + } else + return 0; +@@ -1196,14 +1197,10 @@ static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = { + }; + + static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { +- [IFLA_VF_MAC] = { .type = NLA_BINARY, +- .len = sizeof(struct ifla_vf_mac) }, +- [IFLA_VF_VLAN] = { .type = NLA_BINARY, +- .len = sizeof(struct ifla_vf_vlan) }, +- [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, +- .len = sizeof(struct ifla_vf_tx_rate) }, +- [IFLA_VF_SPOOFCHK] = { .type = NLA_BINARY, +- .len = sizeof(struct ifla_vf_spoofchk) }, ++ [IFLA_VF_MAC] = { .len = sizeof(struct ifla_vf_mac) }, ++ [IFLA_VF_VLAN] = { .len = sizeof(struct ifla_vf_vlan) }, ++ [IFLA_VF_TX_RATE] = { .len = sizeof(struct ifla_vf_tx_rate) }, ++ [IFLA_VF_SPOOFCHK] = { .len = sizeof(struct ifla_vf_spoofchk) }, + }; + + static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = { +@@ -1440,6 +1437,7 @@ static int do_setlink(const struct sk_buff *skb, + goto errout; + } + if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) { ++ put_net(net); + err = -EPERM; + goto errout; + } +@@ -2020,8 +2018,16 @@ replay: + } + } + err = rtnl_configure_link(dev, ifm); +- if (err < 0) +- unregister_netdevice(dev); ++ if (err < 0) { ++ if (ops->newlink) { ++ LIST_HEAD(list_kill); ++ ++ ops->dellink(dev, &list_kill); ++ unregister_netdevice_many(&list_kill); ++ } else { ++ unregister_netdevice(dev); ++ } ++ } + out: + put_net(dest_net); + return err; +@@ -2635,12 +2641,16 @@ static int rtnl_bridge_notify(struct net_device *dev, u16 flags) + goto errout; + } + ++ if (!skb->len) ++ goto errout; ++ + rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); + return 0; + errout: + WARN_ON(err == -EMSGSIZE); + kfree_skb(skb); +- rtnl_set_sk_err(net, RTNLGRP_LINK, err); ++ if (err) ++ rtnl_set_sk_err(net, RTNLGRP_LINK, err); + return err; + } + +diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c +index 897da56..ba71212 100644 +--- a/net/core/secure_seq.c ++++ b/net/core/secure_seq.c +@@ -85,31 +85,6 @@ EXPORT_SYMBOL(secure_ipv6_port_ephemeral); + #endif + + #ifdef CONFIG_INET +-__u32 secure_ip_id(__be32 daddr) +-{ +- u32 hash[MD5_DIGEST_WORDS]; +- +- net_secret_init(); +- hash[0] = (__force __u32) daddr; +- hash[1] = net_secret[13]; +- hash[2] = net_secret[14]; +- hash[3] = net_secret[15]; +- +- md5_transform(hash, net_secret); +- +- return hash[0]; +-} +- +-__u32 secure_ipv6_id(const __be32 daddr[4]) +-{ +- __u32 hash[4]; +- +- net_secret_init(); +- memcpy(hash, daddr, 16); +- md5_transform(hash, net_secret); +- +- return hash[0]; +-} + + __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, + __be16 sport, __be16 dport) +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index 7f2e1fc..8207f8d 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -62,6 +62,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -277,13 +278,14 @@ nodata: + EXPORT_SYMBOL(__alloc_skb); + + /** +- * build_skb - build a network buffer ++ * __build_skb - build a network buffer + * @data: data buffer provided by caller +- * @frag_size: size of fragment, or 0 if head was kmalloced ++ * @frag_size: size of data, or 0 if head was kmalloced + * + * Allocate a new &sk_buff. Caller provides space holding head and + * skb_shared_info. @data must have been allocated by kmalloc() only if +- * @frag_size is 0, otherwise data should come from the page allocator. ++ * @frag_size is 0, otherwise data should come from the page allocator ++ * or vmalloc() + * The return is the new skb buffer. + * On a failure the return is %NULL, and @data is not freed. + * Notes : +@@ -294,7 +296,7 @@ EXPORT_SYMBOL(__alloc_skb); + * before giving packet to stack. + * RX rings only contains data buffers, not full skbs. + */ +-struct sk_buff *build_skb(void *data, unsigned int frag_size) ++struct sk_buff *__build_skb(void *data, unsigned int frag_size) + { + struct skb_shared_info *shinfo; + struct sk_buff *skb; +@@ -308,7 +310,6 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size) + + memset(skb, 0, offsetof(struct sk_buff, tail)); + skb->truesize = SKB_TRUESIZE(size); +- skb->head_frag = frag_size != 0; + atomic_set(&skb->users, 1); + skb->head = data; + skb->data = data; +@@ -325,6 +326,23 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size) + + return skb; + } ++ ++/* build_skb() is wrapper over __build_skb(), that specifically ++ * takes care of skb->head and skb->pfmemalloc ++ * This means that if @frag_size is not zero, then @data must be backed ++ * by a page fragment, not kmalloc() or vmalloc() ++ */ ++struct sk_buff *build_skb(void *data, unsigned int frag_size) ++{ ++ struct sk_buff *skb = __build_skb(data, frag_size); ++ ++ if (skb && frag_size) { ++ skb->head_frag = 1; ++ if (virt_to_head_page(data)->pfmemalloc) ++ skb->pfmemalloc = 1; ++ } ++ return skb; ++} + EXPORT_SYMBOL(build_skb); + + struct netdev_alloc_cache { +@@ -350,8 +368,11 @@ refill: + for (order = NETDEV_FRAG_PAGE_MAX_ORDER; ;) { + gfp_t gfp = gfp_mask; + +- if (order) +- gfp |= __GFP_COMP | __GFP_NOWARN; ++ if (order) { ++ gfp |= __GFP_COMP | __GFP_NOWARN | ++ __GFP_NOMEMALLOC; ++ gfp &= ~__GFP_WAIT; ++ } + nc->frag.page = alloc_pages(gfp, order); + if (likely(nc->frag.page)) + break; +@@ -2968,9 +2989,9 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb, + tail = nskb; + + __copy_skb_header(nskb, head_skb); +- nskb->mac_len = head_skb->mac_len; + + skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom); ++ skb_reset_mac_len(nskb); + + skb_copy_from_linear_data_offset(head_skb, -tnl_hlen, + nskb->data - tnl_hlen, +@@ -3139,6 +3160,9 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) + NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE_STOLEN_HEAD; + goto done; + } ++ /* switch back to head shinfo */ ++ pinfo = skb_shinfo(p); ++ + if (pinfo->frag_list) + goto merge; + if (skb_gro_len(p) != pinfo->gso_size) +@@ -3933,6 +3957,7 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet) + skb->local_df = 0; + skb_dst_drop(skb); + skb->mark = 0; ++ skb_init_secmark(skb); + secpath_reset(skb); + nf_reset(skb); + nf_reset_trace(skb); +@@ -3963,3 +3988,55 @@ unsigned int skb_gso_transport_seglen(const struct sk_buff *skb) + return shinfo->gso_size; + } + EXPORT_SYMBOL_GPL(skb_gso_transport_seglen); ++ ++static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb) ++{ ++ if (skb_cow(skb, skb_headroom(skb)) < 0) { ++ kfree_skb(skb); ++ return NULL; ++ } ++ ++ memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN); ++ skb->mac_header += VLAN_HLEN; ++ return skb; ++} ++ ++struct sk_buff *skb_vlan_untag(struct sk_buff *skb) ++{ ++ struct vlan_hdr *vhdr; ++ u16 vlan_tci; ++ ++ if (unlikely(vlan_tx_tag_present(skb))) { ++ /* vlan_tci is already set-up so leave this for another time */ ++ return skb; ++ } ++ ++ skb = skb_share_check(skb, GFP_ATOMIC); ++ if (unlikely(!skb)) ++ goto err_free; ++ ++ if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) ++ goto err_free; ++ ++ vhdr = (struct vlan_hdr *)skb->data; ++ vlan_tci = ntohs(vhdr->h_vlan_TCI); ++ __vlan_hwaccel_put_tag(skb, skb->protocol, vlan_tci); ++ ++ skb_pull_rcsum(skb, VLAN_HLEN); ++ vlan_set_encap_proto(skb, vhdr); ++ ++ skb = skb_reorder_vlan_header(skb); ++ if (unlikely(!skb)) ++ goto err_free; ++ ++ skb_reset_network_header(skb); ++ skb_reset_transport_header(skb); ++ skb_reset_mac_len(skb); ++ ++ return skb; ++ ++err_free: ++ kfree_skb(skb); ++ return NULL; ++} ++EXPORT_SYMBOL(skb_vlan_untag); +diff --git a/net/core/sock.c b/net/core/sock.c +index c806956..8ebfa52 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -659,6 +659,25 @@ static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool) + sock_reset_flag(sk, bit); + } + ++bool sk_mc_loop(struct sock *sk) ++{ ++ if (dev_recursion_level()) ++ return false; ++ if (!sk) ++ return true; ++ switch (sk->sk_family) { ++ case AF_INET: ++ return inet_sk(sk)->mc_loop; ++#if IS_ENABLED(CONFIG_IPV6) ++ case AF_INET6: ++ return inet6_sk(sk)->mc_loop; ++#endif ++ } ++ WARN_ON(1); ++ return true; ++} ++EXPORT_SYMBOL(sk_mc_loop); ++ + /* + * This is meant for all protocols to use and covers goings on + * at the socket level. Everything here is generic. +@@ -1895,8 +1914,10 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio) + do { + gfp_t gfp = prio; + +- if (order) ++ if (order) { + gfp |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY; ++ gfp &= ~__GFP_WAIT; ++ } + pfrag->page = alloc_pages(gfp, order); + if (likely(pfrag->page)) { + pfrag->offset = 0; +diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c +index cf9cd13..e731c96 100644 +--- a/net/core/sysctl_net_core.c ++++ b/net/core/sysctl_net_core.c +@@ -25,6 +25,8 @@ + static int zero = 0; + static int one = 1; + static int ushort_max = USHRT_MAX; ++static int min_sndbuf = SOCK_MIN_SNDBUF; ++static int min_rcvbuf = SOCK_MIN_RCVBUF; + + #ifdef CONFIG_RPS + static int rps_sock_flow_sysctl(struct ctl_table *table, int write, +@@ -223,7 +225,7 @@ static struct ctl_table net_core_table[] = { + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_sndbuf, + }, + { + .procname = "rmem_max", +@@ -231,7 +233,7 @@ static struct ctl_table net_core_table[] = { + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_rcvbuf, + }, + { + .procname = "wmem_default", +@@ -239,7 +241,7 @@ static struct ctl_table net_core_table[] = { + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_sndbuf, + }, + { + .procname = "rmem_default", +@@ -247,7 +249,7 @@ static struct ctl_table net_core_table[] = { + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_rcvbuf, + }, + { + .procname = "dev_weight", +diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c +index 07bd8ed..951fe55 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -228,6 +228,8 @@ int inet_listen(struct socket *sock, int backlog) + err = 0; + if (err) + goto out; ++ ++ tcp_fastopen_init_key_once(true); + } + err = inet_csk_listen_start(sk, backlog); + if (err) +diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c +index f2e1573..8f7bd56 100644 +--- a/net/ipv4/fib_rules.c ++++ b/net/ipv4/fib_rules.c +@@ -62,6 +62,10 @@ int __fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res) + else + res->tclassid = 0; + #endif ++ ++ if (err == -ESRCH) ++ err = -ENETUNREACH; ++ + return err; + } + EXPORT_SYMBOL_GPL(__fib_lookup); +diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c +index 9d43468..017fa5e 100644 +--- a/net/ipv4/fib_semantics.c ++++ b/net/ipv4/fib_semantics.c +@@ -535,7 +535,7 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi) + return 1; + + attrlen = rtnh_attrlen(rtnh); +- if (attrlen < 0) { ++ if (attrlen > 0) { + struct nlattr *nla, *attrs = rtnh_attrs(rtnh); + + nla = nla_find(attrs, attrlen, RTA_GATEWAY); +diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c +index 2d24f29..278836f 100644 +--- a/net/ipv4/gre_offload.c ++++ b/net/ipv4/gre_offload.c +@@ -50,7 +50,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, + + greh = (struct gre_base_hdr *)skb_transport_header(skb); + +- ghl = skb_inner_network_header(skb) - skb_transport_header(skb); ++ ghl = skb_inner_mac_header(skb) - skb_transport_header(skb); + if (unlikely(ghl < sizeof(*greh))) + goto out; + +@@ -271,6 +271,9 @@ static int gre_gro_complete(struct sk_buff *skb, int nhoff) + err = ptype->callbacks.gro_complete(skb, nhoff + grehlen); + + rcu_read_unlock(); ++ ++ skb_set_inner_mac_header(skb, nhoff + grehlen); ++ + return err; + } + +diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c +index 9db3b87..0ffcd4d 100644 +--- a/net/ipv4/igmp.c ++++ b/net/ipv4/igmp.c +@@ -369,7 +369,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) + pip->saddr = fl4.saddr; + pip->protocol = IPPROTO_IGMP; + pip->tot_len = 0; /* filled in later */ +- ip_select_ident(skb, &rt->dst, NULL); ++ ip_select_ident(skb, NULL); + ((u8 *)&pip[1])[0] = IPOPT_RA; + ((u8 *)&pip[1])[1] = 4; + ((u8 *)&pip[1])[2] = 0; +@@ -714,7 +714,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, + iph->daddr = dst; + iph->saddr = fl4.saddr; + iph->protocol = IPPROTO_IGMP; +- ip_select_ident(skb, &rt->dst, NULL); ++ ip_select_ident(skb, NULL); + ((u8 *)&iph[1])[0] = IPOPT_RA; + ((u8 *)&iph[1])[1] = 4; + ((u8 *)&iph[1])[2] = 0; +diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c +index e34dccb..4eeba4e 100644 +--- a/net/ipv4/inet_diag.c ++++ b/net/ipv4/inet_diag.c +@@ -71,6 +71,20 @@ static inline void inet_diag_unlock_handler( + mutex_unlock(&inet_diag_table_mutex); + } + ++static size_t inet_sk_attr_size(void) ++{ ++ 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(sizeof(struct inet_diag_meminfo)) ++ + nla_total_size(sizeof(struct inet_diag_msg)) ++ + nla_total_size(SK_MEMINFO_VARS * sizeof(u32)) ++ + nla_total_size(TCP_CA_NAME_MAX) ++ + nla_total_size(sizeof(struct tcpvegas_info)) ++ + 64; ++} ++ + int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, + struct sk_buff *skb, struct inet_diag_req_v2 *req, + struct user_namespace *user_ns, +@@ -324,9 +338,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s + if (err) + goto out; + +- rep = nlmsg_new(sizeof(struct inet_diag_msg) + +- sizeof(struct inet_diag_meminfo) + +- sizeof(struct tcp_info) + 64, GFP_KERNEL); ++ rep = nlmsg_new(inet_sk_attr_size(), GFP_KERNEL); + if (!rep) { + err = -ENOMEM; + goto out; +diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c +index 48f4244..bf2cb4a 100644 +--- a/net/ipv4/inetpeer.c ++++ b/net/ipv4/inetpeer.c +@@ -26,20 +26,7 @@ + * Theory of operations. + * We keep one entry for each peer IP address. The nodes contains long-living + * information about the peer which doesn't depend on routes. +- * At this moment this information consists only of ID field for the next +- * outgoing IP packet. This field is incremented with each packet as encoded +- * in inet_getid() function (include/net/inetpeer.h). +- * At the moment of writing this notes identifier of IP packets is generated +- * to be unpredictable using this code only for packets subjected +- * (actually or potentially) to defragmentation. I.e. DF packets less than +- * PMTU in size when local fragmentation is disabled use a constant ID and do +- * not use this code (see ip_select_ident() in include/net/ip.h). + * +- * Route cache entries hold references to our nodes. +- * New cache entries get references via lookup by destination IP address in +- * the avl tree. The reference is grabbed only when it's needed i.e. only +- * when we try to output IP packet which needs an unpredictable ID (see +- * __ip_select_ident() in net/ipv4/route.c). + * Nodes are removed only when reference counter goes to 0. + * When it's happened the node may be removed when a sufficient amount of + * time has been passed since its last use. The less-recently-used entry can +@@ -62,7 +49,6 @@ + * refcnt: atomically against modifications on other CPU; + * usually under some other lock to prevent node disappearing + * daddr: unchangeable +- * ip_id_count: atomic value (no lock needed) + */ + + static struct kmem_cache *peer_cachep __read_mostly; +@@ -497,10 +483,6 @@ relookup: + p->daddr = *daddr; + atomic_set(&p->refcnt, 1); + atomic_set(&p->rid, 0); +- atomic_set(&p->ip_id_count, +- (daddr->family == AF_INET) ? +- secure_ip_id(daddr->addr.a4) : +- secure_ipv6_id(daddr->addr.a6)); + p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW; + p->rate_tokens = 0; + /* 60*HZ is arbitrary, but chosen enough high so that the first +diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c +index 1c6bd43..57075c4 100644 +--- a/net/ipv4/ip_forward.c ++++ b/net/ipv4/ip_forward.c +@@ -127,6 +127,9 @@ int ip_forward(struct sk_buff *skb) + struct rtable *rt; /* Route we use */ + struct ip_options *opt = &(IPCB(skb)->opt); + ++ if (unlikely(skb->sk)) ++ goto drop; ++ + if (skb_warn_if_lro(skb)) + goto drop; + +@@ -178,7 +181,8 @@ int ip_forward(struct sk_buff *skb) + * We now generate an ICMP HOST REDIRECT giving the route + * we calculated. + */ +- if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr && !skb_sec_path(skb)) ++ if (IPCB(skb)->flags & IPSKB_DOREDIRECT && !opt->srr && ++ !skb_sec_path(skb)) + ip_rt_send_redirect(skb); + + skb->priority = rt_tos2priority(iph->tos); +diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c +index c10a3ce..9ff497d 100644 +--- a/net/ipv4/ip_fragment.c ++++ b/net/ipv4/ip_fragment.c +@@ -679,27 +679,30 @@ EXPORT_SYMBOL(ip_defrag); + struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user) + { + struct iphdr iph; ++ int netoff; + u32 len; + + if (skb->protocol != htons(ETH_P_IP)) + return skb; + +- if (!skb_copy_bits(skb, 0, &iph, sizeof(iph))) ++ netoff = skb_network_offset(skb); ++ ++ if (skb_copy_bits(skb, netoff, &iph, sizeof(iph)) < 0) + return skb; + + if (iph.ihl < 5 || iph.version != 4) + return skb; + + len = ntohs(iph.tot_len); +- if (skb->len < len || len < (iph.ihl * 4)) ++ if (skb->len < netoff + len || len < (iph.ihl * 4)) + return skb; + + if (ip_is_fragment(&iph)) { + skb = skb_share_check(skb, GFP_ATOMIC); + if (skb) { +- if (!pskb_may_pull(skb, iph.ihl*4)) ++ if (!pskb_may_pull(skb, netoff + iph.ihl * 4)) + return skb; +- if (pskb_trim_rcsum(skb, len)) ++ if (pskb_trim_rcsum(skb, netoff + len)) + return skb; + memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); + if (ip_defrag(skb, user)) +diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c +index 94213c8..b40b90d 100644 +--- a/net/ipv4/ip_gre.c ++++ b/net/ipv4/ip_gre.c +@@ -250,10 +250,6 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb, + struct ip_tunnel *tunnel = netdev_priv(dev); + const struct iphdr *tnl_params; + +- skb = gre_handle_offloads(skb, !!(tunnel->parms.o_flags&TUNNEL_CSUM)); +- if (IS_ERR(skb)) +- goto out; +- + if (dev->header_ops) { + /* Need space for new headers */ + if (skb_cow_head(skb, dev->needed_headroom - +@@ -266,6 +262,7 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb, + * to gre header. + */ + skb_pull(skb, tunnel->hlen + sizeof(struct iphdr)); ++ skb_reset_mac_header(skb); + } else { + if (skb_cow_head(skb, dev->needed_headroom)) + goto free_skb; +@@ -273,6 +270,10 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb, + tnl_params = &tunnel->parms.iph; + } + ++ skb = gre_handle_offloads(skb, !!(tunnel->parms.o_flags&TUNNEL_CSUM)); ++ if (IS_ERR(skb)) ++ goto out; ++ + __gre_xmit(skb, dev, tnl_params, skb->protocol); + + return NETDEV_TX_OK; +diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +index 73c6b63..05686c4 100644 +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -148,7 +148,7 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, + iph->daddr = (opt && opt->opt.srr ? opt->opt.faddr : daddr); + iph->saddr = saddr; + iph->protocol = sk->sk_protocol; +- ip_select_ident(skb, &rt->dst, sk); ++ ip_select_ident(skb, sk); + + if (opt && opt->opt.optlen) { + iph->ihl += opt->opt.optlen>>2; +@@ -386,8 +386,7 @@ packet_routed: + ip_options_build(skb, &inet_opt->opt, inet->inet_daddr, rt, 0); + } + +- ip_select_ident_more(skb, &rt->dst, sk, +- (skb_shinfo(skb)->gso_segs ?: 1) - 1); ++ ip_select_ident_segs(skb, sk, skb_shinfo(skb)->gso_segs ?: 1); + + skb->priority = sk->sk_priority; + skb->mark = sk->sk_mark; +@@ -844,7 +843,8 @@ static int __ip_append_data(struct sock *sk, + cork->length += length; + if (((length > mtu) || (skb && skb_is_gso(skb))) && + (sk->sk_protocol == IPPROTO_UDP) && +- (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) { ++ (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len && ++ (sk->sk_type == SOCK_DGRAM)) { + err = ip_ufo_append_data(sk, queue, getfrag, from, length, + hh_len, fragheaderlen, transhdrlen, + maxfraglen, flags); +@@ -1338,7 +1338,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk, + iph->ttl = ttl; + iph->protocol = sk->sk_protocol; + ip_copy_addrs(iph, fl4); +- ip_select_ident(skb, &rt->dst, sk); ++ ip_select_ident(skb, sk); + + if (opt) { + iph->ihl += opt->optlen>>2; +@@ -1461,23 +1461,8 @@ static int ip_reply_glue_bits(void *dptr, char *to, int offset, + /* + * Generic function to send a packet as reply to another packet. + * Used to send some TCP resets/acks so far. +- * +- * Use a fake percpu inet socket to avoid false sharing and contention. + */ +-static DEFINE_PER_CPU(struct inet_sock, unicast_sock) = { +- .sk = { +- .__sk_common = { +- .skc_refcnt = ATOMIC_INIT(1), +- }, +- .sk_wmem_alloc = ATOMIC_INIT(1), +- .sk_allocation = GFP_ATOMIC, +- .sk_flags = (1UL << SOCK_USE_WRITE_QUEUE), +- }, +- .pmtudisc = IP_PMTUDISC_WANT, +- .uc_ttl = -1, +-}; +- +-void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, ++void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, + __be32 saddr, const struct ip_reply_arg *arg, + unsigned int len) + { +@@ -1485,9 +1470,9 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, + struct ipcm_cookie ipc; + struct flowi4 fl4; + struct rtable *rt = skb_rtable(skb); ++ struct net *net = sock_net(sk); + struct sk_buff *nskb; +- struct sock *sk; +- struct inet_sock *inet; ++ int err; + + if (ip_options_echo(&replyopts.opt.opt, skb)) + return; +@@ -1516,18 +1501,19 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, + if (IS_ERR(rt)) + return; + +- inet = &get_cpu_var(unicast_sock); ++ inet_sk(sk)->tos = arg->tos; + +- inet->tos = arg->tos; +- sk = &inet->sk; + sk->sk_priority = skb->priority; + sk->sk_protocol = ip_hdr(skb)->protocol; + sk->sk_bound_dev_if = arg->bound_dev_if; +- sock_net_set(sk, net); +- __skb_queue_head_init(&sk->sk_write_queue); + sk->sk_sndbuf = sysctl_wmem_default; +- ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, len, 0, +- &ipc, &rt, MSG_DONTWAIT); ++ err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, ++ len, 0, &ipc, &rt, MSG_DONTWAIT); ++ if (unlikely(err)) { ++ ip_flush_pending_frames(sk); ++ goto out; ++ } ++ + nskb = skb_peek(&sk->sk_write_queue); + if (nskb) { + if (arg->csumoffset >= 0) +@@ -1535,13 +1521,10 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, + arg->csumoffset) = csum_fold(csum_add(nskb->csum, + arg->csum)); + nskb->ip_summed = CHECKSUM_NONE; +- skb_orphan(nskb); + skb_set_queue_mapping(nskb, skb_get_queue_mapping(skb)); + ip_push_pending_frames(sk, &fl4); + } +- +- put_cpu_var(unicast_sock); +- ++out: + ip_rt_put(rt); + } + +diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c +index 580dd96..135045e 100644 +--- a/net/ipv4/ip_sockglue.c ++++ b/net/ipv4/ip_sockglue.c +@@ -426,15 +426,11 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) + + memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); + sin = &errhdr.offender; +- sin->sin_family = AF_UNSPEC; ++ memset(sin, 0, sizeof(*sin)); + if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP) { +- struct inet_sock *inet = inet_sk(sk); +- + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = ip_hdr(skb)->saddr; +- sin->sin_port = 0; +- memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); +- if (inet->cmsg_flags) ++ if (inet_sk(sk)->cmsg_flags) + ip_cmsg_recv(msg, skb); + } + +diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c +index 62cd9e0..0a4af09 100644 +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -69,23 +69,25 @@ static unsigned int ip_tunnel_hash(__be32 key, __be32 remote) + } + + static void __tunnel_dst_set(struct ip_tunnel_dst *idst, +- struct dst_entry *dst) ++ struct dst_entry *dst, __be32 saddr) + { + struct dst_entry *old_dst; + + dst_clone(dst); + old_dst = xchg((__force struct dst_entry **)&idst->dst, dst); + dst_release(old_dst); ++ idst->saddr = saddr; + } + +-static void tunnel_dst_set(struct ip_tunnel *t, struct dst_entry *dst) ++static void tunnel_dst_set(struct ip_tunnel *t, ++ struct dst_entry *dst, __be32 saddr) + { +- __tunnel_dst_set(this_cpu_ptr(t->dst_cache), dst); ++ __tunnel_dst_set(this_cpu_ptr(t->dst_cache), dst, saddr); + } + + static void tunnel_dst_reset(struct ip_tunnel *t) + { +- tunnel_dst_set(t, NULL); ++ tunnel_dst_set(t, NULL, 0); + } + + void ip_tunnel_dst_reset_all(struct ip_tunnel *t) +@@ -93,20 +95,25 @@ void ip_tunnel_dst_reset_all(struct ip_tunnel *t) + int i; + + for_each_possible_cpu(i) +- __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL); ++ __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL, 0); + } + EXPORT_SYMBOL(ip_tunnel_dst_reset_all); + +-static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie) ++static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, ++ u32 cookie, __be32 *saddr) + { ++ struct ip_tunnel_dst *idst; + struct dst_entry *dst; + + rcu_read_lock(); +- dst = rcu_dereference(this_cpu_ptr(t->dst_cache)->dst); ++ idst = this_cpu_ptr(t->dst_cache); ++ dst = rcu_dereference(idst->dst); + if (dst && !atomic_inc_not_zero(&dst->__refcnt)) + dst = NULL; + if (dst) { +- if (dst->obsolete && dst->ops->check(dst, cookie) == NULL) { ++ if (!dst->obsolete || dst->ops->check(dst, cookie)) { ++ *saddr = idst->saddr; ++ } else { + tunnel_dst_reset(t); + dst_release(dst); + dst = NULL; +@@ -362,7 +369,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev) + + if (!IS_ERR(rt)) { + tdev = rt->dst.dev; +- tunnel_dst_set(tunnel, &rt->dst); ++ tunnel_dst_set(tunnel, &rt->dst, fl4.saddr); + ip_rt_put(rt); + } + if (dev->type != ARPHRD_ETHER) +@@ -606,7 +613,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, + init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr, + tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link); + +- rt = connected ? tunnel_rtable_get(tunnel, 0) : NULL; ++ rt = connected ? tunnel_rtable_get(tunnel, 0, &fl4.saddr) : NULL; + + if (!rt) { + rt = ip_route_output_key(tunnel->net, &fl4); +@@ -616,7 +623,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, + goto tx_error; + } + if (connected) +- tunnel_dst_set(tunnel, &rt->dst); ++ tunnel_dst_set(tunnel, &rt->dst, fl4.saddr); + } + + if (rt->dst.dev == dev) { +diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c +index 8d69626..791a419 100644 +--- a/net/ipv4/ip_tunnel_core.c ++++ b/net/ipv4/ip_tunnel_core.c +@@ -74,7 +74,7 @@ int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb, + iph->daddr = dst; + iph->saddr = src; + iph->ttl = ttl; +- __ip_select_ident(iph, &rt->dst, (skb_shinfo(skb)->gso_segs ?: 1) - 1); ++ __ip_select_ident(iph, skb_shinfo(skb)->gso_segs ?: 1); + + err = ip_local_out(skb); + if (unlikely(net_xmit_eval(err))) +@@ -91,11 +91,12 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto) + skb_pull_rcsum(skb, hdr_len); + + if (inner_proto == htons(ETH_P_TEB)) { +- struct ethhdr *eh = (struct ethhdr *)skb->data; ++ struct ethhdr *eh; + + if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) + return -ENOMEM; + ++ eh = (struct ethhdr *)skb->data; + if (likely(ntohs(eh->h_proto) >= ETH_P_802_3_MIN)) + skb->protocol = eh->h_proto; + else +diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c +index e4a8f76..b0a9cb4 100644 +--- a/net/ipv4/ip_vti.c ++++ b/net/ipv4/ip_vti.c +@@ -369,6 +369,7 @@ static struct rtnl_link_ops vti_link_ops __read_mostly = { + .validate = vti_tunnel_validate, + .newlink = vti_newlink, + .changelink = vti_changelink, ++ .dellink = ip_tunnel_dellink, + .get_size = vti_get_size, + .fill_info = vti_fill_info, + }; +diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c +index 2886357..1149fc2 100644 +--- a/net/ipv4/ipmr.c ++++ b/net/ipv4/ipmr.c +@@ -1663,7 +1663,7 @@ static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr) + iph->protocol = IPPROTO_IPIP; + iph->ihl = 5; + iph->tot_len = htons(skb->len); +- ip_select_ident(skb, skb_dst(skb), NULL); ++ ip_select_ident(skb, NULL); + ip_send_check(iph); + + memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index e21934b..1e2e9bf 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -158,6 +158,7 @@ void ping_unhash(struct sock *sk) + if (sk_hashed(sk)) { + write_lock_bh(&ping_table.lock); + hlist_nulls_del(&sk->sk_nulls_node); ++ sk_nulls_node_init(&sk->sk_nulls_node); + sock_put(sk); + isk->inet_num = 0; + isk->inet_sport = 0; +@@ -217,6 +218,8 @@ static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident) + &ipv6_hdr(skb)->daddr)) + continue; + #endif ++ } else { ++ continue; + } + + if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) +@@ -257,6 +260,10 @@ int ping_init_sock(struct sock *sk) + kgid_t low, high; + int ret = 0; + ++#if IS_ENABLED(CONFIG_IPV6) ++ if (sk->sk_family == AF_INET6) ++ inet6_sk(sk)->ipv6only = 1; ++#endif + inet_get_ping_group_range_net(net, &low, &high); + if (gid_lte(low, group) && gid_lte(group, high)) + return 0; +@@ -303,6 +310,11 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, + if (addr_len < sizeof(*addr)) + return -EINVAL; + ++ if (addr->sin_family != AF_INET && ++ !(addr->sin_family == AF_UNSPEC && ++ addr->sin_addr.s_addr == htonl(INADDR_ANY))) ++ return -EAFNOSUPPORT; ++ + pr_debug("ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)\n", + sk, &addr->sin_addr.s_addr, ntohs(addr->sin_port)); + +@@ -328,7 +340,7 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, + return -EINVAL; + + if (addr->sin6_family != AF_INET6) +- return -EINVAL; ++ return -EAFNOSUPPORT; + + pr_debug("ping_check_bind_addr(sk=%p,addr=%pI6c,port=%d)\n", + sk, addr->sin6_addr.s6_addr, ntohs(addr->sin6_port)); +@@ -714,7 +726,7 @@ static int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m + if (msg->msg_namelen < sizeof(*usin)) + return -EINVAL; + if (usin->sin_family != AF_INET) +- return -EINVAL; ++ return -EAFNOSUPPORT; + daddr = usin->sin_addr.s_addr; + /* no remote port */ + } else { +@@ -971,8 +983,11 @@ void ping_rcv(struct sk_buff *skb) + + sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); + if (sk != NULL) { ++ struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); ++ + pr_debug("rcv on socket %p\n", sk); +- ping_queue_rcv_skb(sk, skb_get(skb)); ++ if (skb2) ++ ping_queue_rcv_skb(sk, skb2); + sock_put(sk); + return; + } +diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c +index c04518f..11c8d81 100644 +--- a/net/ipv4/raw.c ++++ b/net/ipv4/raw.c +@@ -389,7 +389,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, + iph->check = 0; + iph->tot_len = htons(length); + if (!iph->id) +- ip_select_ident(skb, &rt->dst, NULL); ++ ip_select_ident(skb, NULL); + + iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); + } +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 031553f..625615c 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -89,6 +89,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -462,39 +463,45 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, + return neigh_create(&arp_tbl, pkey, dev); + } + +-/* +- * Peer allocation may fail only in serious out-of-memory conditions. However +- * we still can generate some output. +- * Random ID selection looks a bit dangerous because we have no chances to +- * select ID being unique in a reasonable period of time. +- * But broken packet identifier may be better than no packet at all. ++#define IP_IDENTS_SZ 2048u ++struct ip_ident_bucket { ++ atomic_t id; ++ u32 stamp32; ++}; ++ ++static struct ip_ident_bucket *ip_idents __read_mostly; ++ ++/* In order to protect privacy, we add a perturbation to identifiers ++ * if one generator is seldom used. This makes hard for an attacker ++ * to infer how many packets were sent between two points in time. + */ +-static void ip_select_fb_ident(struct iphdr *iph) ++u32 ip_idents_reserve(u32 hash, int segs) + { +- static DEFINE_SPINLOCK(ip_fb_id_lock); +- static u32 ip_fallback_id; +- u32 salt; ++ struct ip_ident_bucket *bucket = ip_idents + hash % IP_IDENTS_SZ; ++ u32 old = ACCESS_ONCE(bucket->stamp32); ++ u32 now = (u32)jiffies; ++ u32 delta = 0; ++ ++ if (old != now && cmpxchg(&bucket->stamp32, old, now) == old) ++ delta = prandom_u32_max(now - old); + +- spin_lock_bh(&ip_fb_id_lock); +- salt = secure_ip_id((__force __be32)ip_fallback_id ^ iph->daddr); +- iph->id = htons(salt & 0xFFFF); +- ip_fallback_id = salt; +- spin_unlock_bh(&ip_fb_id_lock); ++ return atomic_add_return(segs + delta, &bucket->id) - segs; + } ++EXPORT_SYMBOL(ip_idents_reserve); + +-void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more) ++void __ip_select_ident(struct iphdr *iph, int segs) + { +- struct net *net = dev_net(dst->dev); +- struct inet_peer *peer; ++ static u32 ip_idents_hashrnd __read_mostly; ++ u32 hash, id; + +- peer = inet_getpeer_v4(net->ipv4.peers, iph->daddr, 1); +- if (peer) { +- iph->id = htons(inet_getid(peer, more)); +- inet_putpeer(peer); +- return; +- } ++ net_get_random_once(&ip_idents_hashrnd, sizeof(ip_idents_hashrnd)); + +- ip_select_fb_ident(iph); ++ hash = jhash_3words((__force u32)iph->daddr, ++ (__force u32)iph->saddr, ++ iph->protocol, ++ ip_idents_hashrnd); ++ id = ip_idents_reserve(hash, segs); ++ iph->id = htons(id); + } + EXPORT_SYMBOL(__ip_select_ident); + +@@ -903,6 +910,10 @@ static int ip_error(struct sk_buff *skb) + bool send; + int code; + ++ /* IP on this device is disabled. */ ++ if (!in_dev) ++ goto out; ++ + net = dev_net(rt->dst.dev); + if (!IN_DEV_FORWARD(in_dev)) { + switch (rt->dst.error) { +@@ -1547,11 +1558,10 @@ static int __mkroute_input(struct sk_buff *skb, + + do_cache = res->fi && !itag; + if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) && ++ skb->protocol == htons(ETH_P_IP) && + (IN_DEV_SHARED_MEDIA(out_dev) || +- inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) { +- flags |= RTCF_DOREDIRECT; +- do_cache = false; +- } ++ inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) ++ IPCB(skb)->flags |= IPSKB_DOREDIRECT; + + if (skb->protocol != htons(ETH_P_IP)) { + /* Not IP (i.e. ARP). Do not create route, if it is +@@ -2261,9 +2271,9 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4, + return rt; + + if (flp4->flowi4_proto) +- rt = (struct rtable *) xfrm_lookup(net, &rt->dst, +- flowi4_to_flowi(flp4), +- sk, 0); ++ rt = (struct rtable *)xfrm_lookup_route(net, &rt->dst, ++ flowi4_to_flowi(flp4), ++ sk, 0); + + return rt; + } +@@ -2298,6 +2308,8 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, + r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; + if (rt->rt_flags & RTCF_NOTIFY) + r->rtm_flags |= RTM_F_NOTIFY; ++ if (IPCB(skb)->flags & IPSKB_DOREDIRECT) ++ r->rtm_flags |= RTCF_DOREDIRECT; + + if (nla_put_be32(skb, RTA_DST, dst)) + goto nla_put_failure; +@@ -2718,6 +2730,12 @@ int __init ip_rt_init(void) + { + int rc = 0; + ++ ip_idents = kmalloc(IP_IDENTS_SZ * sizeof(*ip_idents), GFP_KERNEL); ++ if (!ip_idents) ++ panic("IP: failed to allocate ip_idents\n"); ++ ++ prandom_bytes(ip_idents, IP_IDENTS_SZ * sizeof(*ip_idents)); ++ + #ifdef CONFIG_IP_ROUTE_CLASSID + ip_rt_acct = __alloc_percpu(256 * sizeof(struct ip_rt_acct), __alignof__(struct ip_rt_acct)); + if (!ip_rt_acct) +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index b48fba0..dc45221 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -1175,13 +1175,6 @@ new_segment: + goto wait_for_memory; + + /* +- * All packets are restored as if they have +- * already been sent. +- */ +- if (tp->repair) +- TCP_SKB_CB(skb)->when = tcp_time_stamp; +- +- /* + * Check whether we can use HW checksum. + */ + if (sk->sk_route_caps & NETIF_F_ALL_CSUM) +@@ -1190,6 +1183,13 @@ new_segment: + skb_entail(sk, skb); + copy = size_goal; + max = size_goal; ++ ++ /* All packets are restored as if they have ++ * already been sent. skb_mstamp isn't set to ++ * avoid wrong rtt estimation. ++ */ ++ if (tp->repair) ++ TCP_SKB_CB(skb)->sacked |= TCPCB_REPAIRED; + } + + /* Try to append data to the end of skb. */ +@@ -2684,10 +2684,13 @@ static int do_tcp_setsockopt(struct sock *sk, int level, + + case TCP_FASTOPEN: + if (val >= 0 && ((1 << sk->sk_state) & (TCPF_CLOSE | +- TCPF_LISTEN))) ++ TCPF_LISTEN))) { ++ tcp_fastopen_init_key_once(true); ++ + err = fastopen_init_queue(sk, val); +- else ++ } else { + err = -EINVAL; ++ } + break; + case TCP_TIMESTAMP: + if (!tp->repair) +@@ -2954,61 +2957,42 @@ EXPORT_SYMBOL(compat_tcp_getsockopt); + #endif + + #ifdef CONFIG_TCP_MD5SIG +-static struct tcp_md5sig_pool __percpu *tcp_md5sig_pool __read_mostly; ++static DEFINE_PER_CPU(struct tcp_md5sig_pool, tcp_md5sig_pool); + static DEFINE_MUTEX(tcp_md5sig_mutex); +- +-static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool __percpu *pool) +-{ +- int cpu; +- +- for_each_possible_cpu(cpu) { +- struct tcp_md5sig_pool *p = per_cpu_ptr(pool, cpu); +- +- if (p->md5_desc.tfm) +- crypto_free_hash(p->md5_desc.tfm); +- } +- free_percpu(pool); +-} ++static bool tcp_md5sig_pool_populated = false; + + static void __tcp_alloc_md5sig_pool(void) + { + int cpu; +- struct tcp_md5sig_pool __percpu *pool; +- +- pool = alloc_percpu(struct tcp_md5sig_pool); +- if (!pool) +- return; + + for_each_possible_cpu(cpu) { +- struct crypto_hash *hash; +- +- hash = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); +- if (IS_ERR_OR_NULL(hash)) +- goto out_free; ++ if (!per_cpu(tcp_md5sig_pool, cpu).md5_desc.tfm) { ++ struct crypto_hash *hash; + +- per_cpu_ptr(pool, cpu)->md5_desc.tfm = hash; ++ hash = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR_OR_NULL(hash)) ++ return; ++ per_cpu(tcp_md5sig_pool, cpu).md5_desc.tfm = hash; ++ } + } +- /* before setting tcp_md5sig_pool, we must commit all writes +- * to memory. See ACCESS_ONCE() in tcp_get_md5sig_pool() ++ /* before setting tcp_md5sig_pool_populated, we must commit all writes ++ * to memory. See smp_rmb() in tcp_get_md5sig_pool() + */ + smp_wmb(); +- tcp_md5sig_pool = pool; +- return; +-out_free: +- __tcp_free_md5sig_pool(pool); ++ tcp_md5sig_pool_populated = true; + } + + bool tcp_alloc_md5sig_pool(void) + { +- if (unlikely(!tcp_md5sig_pool)) { ++ if (unlikely(!tcp_md5sig_pool_populated)) { + mutex_lock(&tcp_md5sig_mutex); + +- if (!tcp_md5sig_pool) ++ if (!tcp_md5sig_pool_populated) + __tcp_alloc_md5sig_pool(); + + mutex_unlock(&tcp_md5sig_mutex); + } +- return tcp_md5sig_pool != NULL; ++ return tcp_md5sig_pool_populated; + } + EXPORT_SYMBOL(tcp_alloc_md5sig_pool); + +@@ -3022,13 +3006,13 @@ EXPORT_SYMBOL(tcp_alloc_md5sig_pool); + */ + struct tcp_md5sig_pool *tcp_get_md5sig_pool(void) + { +- struct tcp_md5sig_pool __percpu *p; +- + local_bh_disable(); +- p = ACCESS_ONCE(tcp_md5sig_pool); +- if (p) +- return __this_cpu_ptr(p); + ++ if (tcp_md5sig_pool_populated) { ++ /* coupled with smp_wmb() in __tcp_alloc_md5sig_pool() */ ++ smp_rmb(); ++ return this_cpu_ptr(&tcp_md5sig_pool); ++ } + local_bh_enable(); + return NULL; + } +diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c +index f195d93..ee6518d 100644 +--- a/net/ipv4/tcp_fastopen.c ++++ b/net/ipv4/tcp_fastopen.c +@@ -84,8 +84,6 @@ void tcp_fastopen_cookie_gen(__be32 src, __be32 dst, + __be32 path[4] = { src, dst, 0, 0 }; + struct tcp_fastopen_context *ctx; + +- tcp_fastopen_init_key_once(true); +- + rcu_read_lock(); + ctx = rcu_dereference(tcp_fastopen_ctx); + if (ctx) { +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 3898694..9fbd69e 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -2678,7 +2678,6 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack) + */ + static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) + { +- struct inet_connection_sock *icsk = inet_csk(sk); + struct tcp_sock *tp = tcp_sk(sk); + bool recovered = !before(tp->snd_una, tp->high_seq); + +@@ -2704,12 +2703,9 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) + + if (recovered) { + /* F-RTO RFC5682 sec 3.1 step 2.a and 1st part of step 3.a */ +- icsk->icsk_retransmits = 0; + tcp_try_undo_recovery(sk); + return; + } +- if (flag & FLAG_DATA_ACKED) +- icsk->icsk_retransmits = 0; + if (tcp_is_reno(tp)) { + /* A Reno DUPACK means new data in F-RTO step 2.b above are + * delivered. Lower inflight to clock out (re)tranmissions. +@@ -3068,10 +3064,11 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, + if (seq_rtt < 0) { + seq_rtt = ca_seq_rtt; + } +- if (!(sacked & TCPCB_SACKED_ACKED)) ++ if (!(sacked & TCPCB_SACKED_ACKED)) { + reord = min(pkts_acked, reord); +- if (!after(scb->end_seq, tp->high_seq)) +- flag |= FLAG_ORIG_SACK_ACKED; ++ if (!after(scb->end_seq, tp->high_seq)) ++ flag |= FLAG_ORIG_SACK_ACKED; ++ } + } + + if (sacked & TCPCB_SACKED_ACKED) +@@ -3398,8 +3395,10 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) + icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) + tcp_rearm_rto(sk); + +- if (after(ack, prior_snd_una)) ++ if (after(ack, prior_snd_una)) { + flag |= FLAG_SND_UNA_ADVANCED; ++ icsk->icsk_retransmits = 0; ++ } + + prior_fackets = tp->fackets_out; + prior_in_flight = tcp_packets_in_flight(tp); +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index 1e4eac7..e2f8bd0 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -269,7 +269,7 @@ EXPORT_SYMBOL(tcp_v4_connect); + * It can be called through tcp_release_cb() if socket was owned by user + * at the time tcp_v4_err() was called to handle ICMP message. + */ +-static void tcp_v4_mtu_reduced(struct sock *sk) ++void tcp_v4_mtu_reduced(struct sock *sk) + { + struct dst_entry *dst; + struct inet_sock *inet = inet_sk(sk); +@@ -300,6 +300,7 @@ static void tcp_v4_mtu_reduced(struct sock *sk) + tcp_simple_retransmit(sk); + } /* else let the usual retransmit timer handle it */ + } ++EXPORT_SYMBOL(tcp_v4_mtu_reduced); + + static void do_redirect(struct sk_buff *skb, struct sock *sk) + { +@@ -690,7 +691,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) + + net = dev_net(skb_dst(skb)->dev); + arg.tos = ip_hdr(skb)->tos; +- ip_send_unicast_reply(net, skb, ip_hdr(skb)->saddr, ++ ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), ++ skb, ip_hdr(skb)->saddr, + ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len); + + TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); +@@ -773,7 +775,8 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, + if (oif) + arg.bound_dev_if = oif; + arg.tos = tos; +- ip_send_unicast_reply(net, skb, ip_hdr(skb)->saddr, ++ ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), ++ skb, ip_hdr(skb)->saddr, + ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len); + + TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); +@@ -1872,7 +1875,7 @@ void tcp_v4_early_demux(struct sk_buff *skb) + skb->sk = sk; + skb->destructor = sock_edemux; + if (sk->sk_state != TCP_TIME_WAIT) { +- struct dst_entry *dst = sk->sk_rx_dst; ++ struct dst_entry *dst = ACCESS_ONCE(sk->sk_rx_dst); + + if (dst) + dst = dst_check(dst, 0); +@@ -2117,6 +2120,7 @@ const struct inet_connection_sock_af_ops ipv4_specific = { + .compat_setsockopt = compat_ip_setsockopt, + .compat_getsockopt = compat_ip_getsockopt, + #endif ++ .mtu_reduced = tcp_v4_mtu_reduced, + }; + EXPORT_SYMBOL(ipv4_specific); + +@@ -2736,7 +2740,6 @@ struct proto tcp_prot = { + .sendpage = tcp_sendpage, + .backlog_rcv = tcp_v4_do_rcv, + .release_cb = tcp_release_cb, +- .mtu_reduced = tcp_v4_mtu_reduced, + .hash = inet_hash, + .unhash = inet_unhash, + .get_port = inet_csk_get_port, +@@ -2768,14 +2771,39 @@ struct proto tcp_prot = { + }; + EXPORT_SYMBOL(tcp_prot); + ++static void __net_exit tcp_sk_exit(struct net *net) ++{ ++ int cpu; ++ ++ for_each_possible_cpu(cpu) ++ inet_ctl_sock_destroy(*per_cpu_ptr(net->ipv4.tcp_sk, cpu)); ++ free_percpu(net->ipv4.tcp_sk); ++} ++ + static int __net_init tcp_sk_init(struct net *net) + { ++ int res, cpu; ++ ++ net->ipv4.tcp_sk = alloc_percpu(struct sock *); ++ if (!net->ipv4.tcp_sk) ++ return -ENOMEM; ++ ++ for_each_possible_cpu(cpu) { ++ struct sock *sk; ++ ++ res = inet_ctl_sock_create(&sk, PF_INET, SOCK_RAW, ++ IPPROTO_TCP, net); ++ if (res) ++ goto fail; ++ *per_cpu_ptr(net->ipv4.tcp_sk, cpu) = sk; ++ } + net->ipv4.sysctl_tcp_ecn = 2; + return 0; +-} + +-static void __net_exit tcp_sk_exit(struct net *net) +-{ ++fail: ++ tcp_sk_exit(net); ++ ++ return res; + } + + static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list) +diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c +index 7a436c5..9128d0a 100644 +--- a/net/ipv4/tcp_minisocks.c ++++ b/net/ipv4/tcp_minisocks.c +@@ -297,7 +297,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) + tw->tw_v6_daddr = sk->sk_v6_daddr; + tw->tw_v6_rcv_saddr = sk->sk_v6_rcv_saddr; + tw->tw_tclass = np->tclass; +- tw->tw_flowlabel = np->flow_label >> 12; ++ tw->tw_flowlabel = be32_to_cpu(np->flow_label & IPV6_FLOWLABEL_MASK); + tw->tw_ipv6only = np->ipv6only; + } + #endif +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index b3d1add..a68cd71 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -787,7 +787,7 @@ void tcp_release_cb(struct sock *sk) + __sock_put(sk); + } + if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) { +- sk->sk_prot->mtu_reduced(sk); ++ inet_csk(sk)->icsk_af_ops->mtu_reduced(sk); + __sock_put(sk); + } + } +@@ -1876,8 +1876,11 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, + tso_segs = tcp_init_tso_segs(sk, skb, mss_now); + BUG_ON(!tso_segs); + +- if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE) ++ if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE) { ++ /* "when" is used as a start point for the retransmit timer */ ++ TCP_SKB_CB(skb)->when = tcp_time_stamp; + goto repair; /* Skip network transmission */ ++ } + + cwnd_quota = tcp_cwnd_test(tp, skb); + if (!cwnd_quota) { +@@ -1891,7 +1894,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, + if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now))) + break; + +- if (tso_segs == 1) { ++ if (tso_segs == 1 || !sk->sk_gso_max_segs) { + if (unlikely(!tcp_nagle_test(tp, skb, mss_now, + (tcp_skb_is_last(sk, skb) ? + nonagle : TCP_NAGLE_PUSH)))) +@@ -1928,7 +1931,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, + } + + limit = mss_now; +- if (tso_segs > 1 && !tcp_urg_mode(tp)) ++ if (tso_segs > 1 && sk->sk_gso_max_segs && !tcp_urg_mode(tp)) + limit = tcp_mss_split_point(sk, skb, mss_now, + min_t(unsigned int, + cwnd_quota, +@@ -2066,9 +2069,7 @@ void tcp_send_loss_probe(struct sock *sk) + if (WARN_ON(!skb || !tcp_skb_pcount(skb))) + goto rearm_timer; + +- /* Probe with zero data doesn't trigger fast recovery. */ +- if (skb->len > 0) +- err = __tcp_retransmit_skb(sk, skb); ++ err = __tcp_retransmit_skb(sk, skb); + + /* Record snd_nxt for loss detection. */ + if (likely(!err)) +@@ -2594,43 +2595,65 @@ begin_fwd: + } + } + +-/* Send a fin. The caller locks the socket for us. This cannot be +- * allowed to fail queueing a FIN frame under any circumstances. ++/* We allow to exceed memory limits for FIN packets to expedite ++ * connection tear down and (memory) recovery. ++ * Otherwise tcp_send_fin() could be tempted to either delay FIN ++ * or even be forced to close flow without any FIN. ++ */ ++static void sk_forced_wmem_schedule(struct sock *sk, int size) ++{ ++ int amt, status; ++ ++ if (size <= sk->sk_forward_alloc) ++ return; ++ amt = sk_mem_pages(size); ++ sk->sk_forward_alloc += amt * SK_MEM_QUANTUM; ++ sk_memory_allocated_add(sk, amt, &status); ++} ++ ++/* Send a FIN. The caller locks the socket for us. ++ * We should try to send a FIN packet really hard, but eventually give up. + */ + void tcp_send_fin(struct sock *sk) + { ++ struct sk_buff *skb, *tskb = tcp_write_queue_tail(sk); + struct tcp_sock *tp = tcp_sk(sk); +- struct sk_buff *skb = tcp_write_queue_tail(sk); +- int mss_now; + +- /* Optimization, tack on the FIN if we have a queue of +- * unsent frames. But be careful about outgoing SACKS +- * and IP options. ++ /* Optimization, tack on the FIN if we have one skb in write queue and ++ * this skb was not yet sent, or we are under memory pressure. ++ * Note: in the latter case, FIN packet will be sent after a timeout, ++ * as TCP stack thinks it has already been transmitted. + */ +- mss_now = tcp_current_mss(sk); +- +- if (tcp_send_head(sk) != NULL) { +- TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_FIN; +- TCP_SKB_CB(skb)->end_seq++; ++ if (tskb && (tcp_send_head(sk) || sk_under_memory_pressure(sk))) { ++coalesce: ++ TCP_SKB_CB(tskb)->tcp_flags |= TCPHDR_FIN; ++ TCP_SKB_CB(tskb)->end_seq++; + tp->write_seq++; ++ if (!tcp_send_head(sk)) { ++ /* This means tskb was already sent. ++ * Pretend we included the FIN on previous transmit. ++ * We need to set tp->snd_nxt to the value it would have ++ * if FIN had been sent. This is because retransmit path ++ * does not change tp->snd_nxt. ++ */ ++ tp->snd_nxt++; ++ return; ++ } + } else { +- /* Socket is locked, keep trying until memory is available. */ +- for (;;) { +- skb = alloc_skb_fclone(MAX_TCP_HEADER, +- sk->sk_allocation); +- if (skb) +- break; +- yield(); ++ skb = alloc_skb_fclone(MAX_TCP_HEADER, sk->sk_allocation); ++ if (unlikely(!skb)) { ++ if (tskb) ++ goto coalesce; ++ return; + } +- +- /* Reserve space for headers and prepare control bits. */ + skb_reserve(skb, MAX_TCP_HEADER); ++ sk_forced_wmem_schedule(sk, skb->truesize); + /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */ + tcp_init_nondata_skb(skb, tp->write_seq, + TCPHDR_ACK | TCPHDR_FIN); + tcp_queue_skb(sk, skb); + } +- __tcp_push_pending_frames(sk, mss_now, TCP_NAGLE_OFF); ++ __tcp_push_pending_frames(sk, tcp_current_mss(sk), TCP_NAGLE_OFF); + } + + /* We get here when a process closes a file descriptor (either due to +@@ -2799,6 +2822,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, + } + #endif + ++ /* Do not fool tcpdump (if any), clean our debris */ ++ skb->tstamp.tv64 = 0; + return skb; + } + EXPORT_SYMBOL(tcp_make_synack); +@@ -2898,9 +2923,9 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) + { + struct tcp_sock *tp = tcp_sk(sk); + struct tcp_fastopen_request *fo = tp->fastopen_req; +- int syn_loss = 0, space, i, err = 0, iovlen = fo->data->msg_iovlen; +- struct sk_buff *syn_data = NULL, *data; ++ int syn_loss = 0, space, err = 0; + unsigned long last_syn_loss = 0; ++ struct sk_buff *syn_data; + + tp->rx_opt.mss_clamp = tp->advmss; /* If MSS is not cached */ + tcp_fastopen_cache_get(sk, &tp->rx_opt.mss_clamp, &fo->cookie, +@@ -2931,42 +2956,39 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) + /* limit to order-0 allocations */ + space = min_t(size_t, space, SKB_MAX_HEAD(MAX_TCP_HEADER)); + +- syn_data = skb_copy_expand(syn, MAX_TCP_HEADER, space, +- sk->sk_allocation); +- if (syn_data == NULL) ++ syn_data = sk_stream_alloc_skb(sk, space, sk->sk_allocation); ++ if (!syn_data) ++ goto fallback; ++ syn_data->ip_summed = CHECKSUM_PARTIAL; ++ memcpy(syn_data->cb, syn->cb, sizeof(syn->cb)); ++ skb_shinfo(syn_data)->gso_segs = 1; ++ if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space), ++ fo->data->msg_iov, 0, space))) { ++ kfree_skb(syn_data); + goto fallback; ++ } + +- for (i = 0; i < iovlen && syn_data->len < space; ++i) { +- struct iovec *iov = &fo->data->msg_iov[i]; +- unsigned char __user *from = iov->iov_base; +- int len = iov->iov_len; ++ /* No more data pending in inet_wait_for_connect() */ ++ if (space == fo->size) ++ fo->data = NULL; ++ fo->copied = space; + +- if (syn_data->len + len > space) +- len = space - syn_data->len; +- else if (i + 1 == iovlen) +- /* No more data pending in inet_wait_for_connect() */ +- fo->data = NULL; ++ tcp_connect_queue_skb(sk, syn_data); + +- if (skb_add_data(syn_data, from, len)) +- goto fallback; +- } ++ err = tcp_transmit_skb(sk, syn_data, 1, sk->sk_allocation); + +- /* Queue a data-only packet after the regular SYN for retransmission */ +- data = pskb_copy(syn_data, sk->sk_allocation); +- if (data == NULL) +- goto fallback; +- TCP_SKB_CB(data)->seq++; +- TCP_SKB_CB(data)->tcp_flags &= ~TCPHDR_SYN; +- TCP_SKB_CB(data)->tcp_flags = (TCPHDR_ACK|TCPHDR_PSH); +- tcp_connect_queue_skb(sk, data); +- fo->copied = data->len; +- +- if (tcp_transmit_skb(sk, syn_data, 0, sk->sk_allocation) == 0) { ++ /* Now full SYN+DATA was cloned and sent (or not), ++ * remove the SYN from the original skb (syn_data) ++ * we keep in write queue in case of a retransmit, as we ++ * also have the SYN packet (with no data) in the same queue. ++ */ ++ TCP_SKB_CB(syn_data)->seq++; ++ TCP_SKB_CB(syn_data)->tcp_flags = TCPHDR_ACK | TCPHDR_PSH; ++ if (!err) { + tp->syn_data = (fo->copied > 0); + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE); + goto done; + } +- syn_data = NULL; + + fallback: + /* Send a regular SYN with Fast Open cookie request option */ +@@ -2975,7 +2997,6 @@ fallback: + err = tcp_transmit_skb(sk, syn, 1, sk->sk_allocation); + if (err) + tp->syn_fastopen = 0; +- kfree_skb(syn_data); + done: + fo->cookie.len = -1; /* Exclude Fast Open option for SYN retries */ + return err; +@@ -2995,13 +3016,10 @@ int tcp_connect(struct sock *sk) + return 0; + } + +- buff = alloc_skb_fclone(MAX_TCP_HEADER + 15, sk->sk_allocation); +- if (unlikely(buff == NULL)) ++ buff = sk_stream_alloc_skb(sk, 0, sk->sk_allocation); ++ if (unlikely(!buff)) + return -ENOBUFS; + +- /* Reserve space for headers. */ +- skb_reserve(buff, MAX_TCP_HEADER); +- + tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN); + tp->retrans_stamp = TCP_SKB_CB(buff)->when = tcp_time_stamp; + tcp_connect_queue_skb(sk, buff); +diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c +index 06cae62..6b1a5fd 100644 +--- a/net/ipv4/tcp_vegas.c ++++ b/net/ipv4/tcp_vegas.c +@@ -219,7 +219,8 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 acked, + * This is: + * (actual rate in segments) * baseRTT + */ +- target_cwnd = tp->snd_cwnd * vegas->baseRTT / rtt; ++ target_cwnd = (u64)tp->snd_cwnd * vegas->baseRTT; ++ do_div(target_cwnd, rtt); + + /* Calculate the difference between the window we had, + * and the window we would like to have. This quantity +diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c +index 326475a..603ad49 100644 +--- a/net/ipv4/tcp_veno.c ++++ b/net/ipv4/tcp_veno.c +@@ -145,7 +145,7 @@ static void tcp_veno_cong_avoid(struct sock *sk, u32 ack, u32 acked, + + rtt = veno->minrtt; + +- target_cwnd = (tp->snd_cwnd * veno->basertt); ++ target_cwnd = (u64)tp->snd_cwnd * veno->basertt; + target_cwnd <<= V_PARAM_SHIFT; + do_div(target_cwnd, rtt); + +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index b25e852..21a3a9e 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -90,6 +90,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1317,10 +1318,8 @@ csum_copy_err: + } + unlock_sock_fast(sk, slow); + +- if (noblock) +- return -EAGAIN; +- +- /* starting over for a new packet */ ++ /* starting over for a new packet, but check if we need to yield */ ++ cond_resched(); + msg->msg_flags &= ~MSG_TRUNC; + goto try_again; + } +@@ -1924,6 +1923,7 @@ void udp_v4_early_demux(struct sk_buff *skb) + struct sock *sk; + struct dst_entry *dst; + int dif = skb->dev->ifindex; ++ int ours; + + /* validate the packet */ + if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr))) +@@ -1933,14 +1933,24 @@ void udp_v4_early_demux(struct sk_buff *skb) + uh = udp_hdr(skb); + + if (skb->pkt_type == PACKET_BROADCAST || +- skb->pkt_type == PACKET_MULTICAST) ++ skb->pkt_type == PACKET_MULTICAST) { ++ struct in_device *in_dev = __in_dev_get_rcu(skb->dev); ++ ++ if (!in_dev) ++ return; ++ ++ ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr, ++ iph->protocol); ++ if (!ours) ++ return; + sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr, + uh->source, iph->saddr, dif); +- else if (skb->pkt_type == PACKET_HOST) ++ } else if (skb->pkt_type == PACKET_HOST) { + sk = __udp4_lib_demux_lookup(net, uh->dest, iph->daddr, + uh->source, iph->saddr, dif); +- else ++ } else { + return; ++ } + + if (!sk) + return; +diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c +index 7927db0..4a000f1 100644 +--- a/net/ipv4/udp_diag.c ++++ b/net/ipv4/udp_diag.c +@@ -99,11 +99,13 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlin + s_slot = cb->args[0]; + num = s_num = cb->args[1]; + +- for (slot = s_slot; slot <= table->mask; num = s_num = 0, slot++) { ++ for (slot = s_slot; slot <= table->mask; s_num = 0, slot++) { + struct sock *sk; + struct hlist_nulls_node *node; + struct udp_hslot *hslot = &table->hash[slot]; + ++ num = 0; ++ + if (hlist_nulls_empty(&hslot->head)) + continue; + +diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c +index 31b1815..1f564a1 100644 +--- a/net/ipv4/xfrm4_mode_tunnel.c ++++ b/net/ipv4/xfrm4_mode_tunnel.c +@@ -117,12 +117,12 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) + + top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ? + 0 : (XFRM_MODE_SKB_CB(skb)->frag_off & htons(IP_DF)); +- ip_select_ident(skb, dst->child, NULL); + + top_iph->ttl = ip4_dst_hoplimit(dst->child); + + top_iph->saddr = x->props.saddr.a4; + top_iph->daddr = x->id.daddr.a4; ++ ip_select_ident(skb, NULL); + + return 0; + } +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index 6c7fa08..3f0ec06 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -1684,14 +1684,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) + addrconf_mod_dad_work(ifp, 0); + } + +-/* Join to solicited addr multicast group. */ +- ++/* Join to solicited addr multicast group. ++ * caller must hold RTNL */ + void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) + { + struct in6_addr maddr; + +- ASSERT_RTNL(); +- + if (dev->flags&(IFF_LOOPBACK|IFF_NOARP)) + return; + +@@ -1699,12 +1697,11 @@ void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) + ipv6_dev_mc_inc(dev, &maddr); + } + ++/* caller must hold RTNL */ + void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) + { + struct in6_addr maddr; + +- ASSERT_RTNL(); +- + if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP)) + return; + +@@ -1712,12 +1709,11 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) + __ipv6_dev_mc_dec(idev, &maddr); + } + ++/* caller must hold RTNL */ + static void addrconf_join_anycast(struct inet6_ifaddr *ifp) + { + struct in6_addr addr; + +- ASSERT_RTNL(); +- + if (ifp->prefix_len >= 127) /* RFC 6164 */ + return; + ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); +@@ -1726,12 +1722,11 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp) + ipv6_dev_ac_inc(ifp->idev->dev, &addr); + } + ++/* caller must hold RTNL */ + static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) + { + struct in6_addr addr; + +- ASSERT_RTNL(); +- + if (ifp->prefix_len >= 127) /* RFC 6164 */ + return; + ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); +diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c +index 2101832..ff2de7d 100644 +--- a/net/ipv6/anycast.c ++++ b/net/ipv6/anycast.c +@@ -77,6 +77,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr) + pac->acl_next = NULL; + pac->acl_addr = *addr; + ++ rtnl_lock(); + rcu_read_lock(); + if (ifindex == 0) { + struct rt6_info *rt; +@@ -137,6 +138,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr) + + error: + rcu_read_unlock(); ++ rtnl_unlock(); + if (pac) + sock_kfree_s(sk, pac, sizeof(*pac)); + return err; +@@ -171,11 +173,13 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) + + spin_unlock_bh(&ipv6_sk_ac_lock); + ++ rtnl_lock(); + rcu_read_lock(); + dev = dev_get_by_index_rcu(net, pac->acl_ifindex); + if (dev) + ipv6_dev_ac_dec(dev, &pac->acl_addr); + rcu_read_unlock(); ++ rtnl_unlock(); + + sock_kfree_s(sk, pac, sizeof(*pac)); + return 0; +@@ -198,6 +202,7 @@ void ipv6_sock_ac_close(struct sock *sk) + spin_unlock_bh(&ipv6_sk_ac_lock); + + prev_index = 0; ++ rtnl_lock(); + rcu_read_lock(); + while (pac) { + struct ipv6_ac_socklist *next = pac->acl_next; +@@ -212,6 +217,7 @@ void ipv6_sock_ac_close(struct sock *sk) + pac = next; + } + rcu_read_unlock(); ++ rtnl_unlock(); + } + + static void aca_put(struct ifacaddr6 *ac) +@@ -233,6 +239,8 @@ int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr) + struct rt6_info *rt; + int err; + ++ ASSERT_RTNL(); ++ + idev = in6_dev_get(dev); + + if (idev == NULL) +@@ -302,6 +310,8 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr) + { + struct ifacaddr6 *aca, *prev_aca; + ++ ASSERT_RTNL(); ++ + write_lock_bh(&idev->lock); + prev_aca = NULL; + for (aca = idev->ac_list; aca; aca = aca->aca_next) { +diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c +index c3bf2d2..841cfa2 100644 +--- a/net/ipv6/datagram.c ++++ b/net/ipv6/datagram.c +@@ -382,11 +382,10 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) + + memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); + sin = &errhdr.offender; +- sin->sin6_family = AF_UNSPEC; ++ memset(sin, 0, sizeof(*sin)); ++ + if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { + sin->sin6_family = AF_INET6; +- sin->sin6_flowinfo = 0; +- sin->sin6_port = 0; + if (np->rxopt.all) + ip6_datagram_recv_common_ctl(sk, msg, skb); + if (skb->protocol == htons(ETH_P_IPV6)) { +@@ -397,12 +396,9 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) + ipv6_iface_scope_id(&sin->sin6_addr, + IP6CB(skb)->iif); + } else { +- struct inet_sock *inet = inet_sk(sk); +- + ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, + &sin->sin6_addr); +- sin->sin6_scope_id = 0; +- if (inet->cmsg_flags) ++ if (inet_sk(sk)->cmsg_flags) + ip_cmsg_recv(msg, skb); + } + } +diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c +index b4d5e1d..27ca796 100644 +--- a/net/ipv6/fib6_rules.c ++++ b/net/ipv6/fib6_rules.c +@@ -104,6 +104,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, + goto again; + flp6->saddr = saddr; + } ++ err = rt->dst.error; + goto out; + } + again: +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index 1e55f5e..7daaeaf 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -638,6 +638,29 @@ static inline bool rt6_qualify_for_ecmp(struct rt6_info *rt) + RTF_GATEWAY; + } + ++static void fib6_purge_rt(struct rt6_info *rt, struct fib6_node *fn, ++ struct net *net) ++{ ++ if (atomic_read(&rt->rt6i_ref) != 1) { ++ /* This route is used as dummy address holder in some split ++ * nodes. It is not leaked, but it still holds other resources, ++ * which must be released in time. So, scan ascendant nodes ++ * and replace dummy references to this route with references ++ * to still alive ones. ++ */ ++ while (fn) { ++ if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) { ++ fn->leaf = fib6_find_prefix(net, fn); ++ atomic_inc(&fn->leaf->rt6i_ref); ++ rt6_release(rt); ++ } ++ fn = fn->parent; ++ } ++ /* No more references are possible at this point. */ ++ BUG_ON(atomic_read(&rt->rt6i_ref) != 1); ++ } ++} ++ + /* + * Insert routing information in a node. + */ +@@ -775,11 +798,12 @@ add: + rt->dst.rt6_next = iter->dst.rt6_next; + atomic_inc(&rt->rt6i_ref); + inet6_rt_notify(RTM_NEWROUTE, rt, info); +- rt6_release(iter); + if (!(fn->fn_flags & RTN_RTINFO)) { + info->nl_net->ipv6.rt6_stats->fib_route_nodes++; + fn->fn_flags |= RTN_RTINFO; + } ++ fib6_purge_rt(iter, fn, info->nl_net); ++ rt6_release(iter); + } + + return 0; +@@ -1284,24 +1308,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, + fn = fib6_repair_tree(net, fn); + } + +- if (atomic_read(&rt->rt6i_ref) != 1) { +- /* This route is used as dummy address holder in some split +- * nodes. It is not leaked, but it still holds other resources, +- * which must be released in time. So, scan ascendant nodes +- * and replace dummy references to this route with references +- * to still alive ones. +- */ +- while (fn) { +- if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) { +- fn->leaf = fib6_find_prefix(net, fn); +- atomic_inc(&fn->leaf->rt6i_ref); +- rt6_release(rt); +- } +- fn = fn->parent; +- } +- /* No more references are possible at this point. */ +- BUG_ON(atomic_read(&rt->rt6i_ref) != 1); +- } ++ fib6_purge_rt(rt, fn, net); + + inet6_rt_notify(RTM_DELROUTE, rt, info); + rt6_release(rt); +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index 2465d18..4a230b1 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -508,11 +508,11 @@ static int ip6gre_rcv(struct sk_buff *skb) + + skb->protocol = gre_proto; + /* WCCP version 1 and 2 protocol decoding. +- * - Change protocol to IP ++ * - Change protocol to IPv6 + * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header + */ + if (flags == 0 && gre_proto == htons(ETH_P_WCCP)) { +- skb->protocol = htons(ETH_P_IP); ++ skb->protocol = htons(ETH_P_IPV6); + if ((*(h + offset) & 0xF0) != 0x40) + offset += 4; + } +@@ -787,7 +787,7 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev) + encap_limit = t->parms.encap_limit; + + memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); +- fl6.flowi6_proto = IPPROTO_IPIP; ++ fl6.flowi6_proto = IPPROTO_GRE; + + dsfield = ipv4_get_dsfield(iph); + +@@ -837,7 +837,7 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev) + encap_limit = t->parms.encap_limit; + + memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); +- fl6.flowi6_proto = IPPROTO_IPV6; ++ fl6.flowi6_proto = IPPROTO_GRE; + + dsfield = ipv6_get_dsfield(ipv6h); + if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) +@@ -962,8 +962,6 @@ static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu) + else + dev->flags &= ~IFF_POINTOPOINT; + +- dev->iflink = p->link; +- + /* Precalculate GRE options length */ + if (t->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) { + if (t->parms.o_flags&GRE_CSUM) +@@ -1273,6 +1271,7 @@ static int ip6gre_tunnel_init(struct net_device *dev) + u64_stats_init(&ip6gre_tunnel_stats->syncp); + } + ++ dev->iflink = tunnel->parms.link; + + return 0; + } +@@ -1474,6 +1473,8 @@ static int ip6gre_tap_init(struct net_device *dev) + u64_stats_init(&ip6gre_tap_stats->syncp); + } + ++ dev->iflink = tunnel->parms.link; ++ + return 0; + } + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index a62b610..066d0b0 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -537,11 +537,26 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) + skb_copy_secmark(to, from); + } + ++static void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) ++{ ++ static u32 ip6_idents_hashrnd __read_mostly; ++ u32 hash, id; ++ ++ net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd)); ++ ++ hash = __ipv6_addr_jhash(&rt->rt6i_dst.addr, ip6_idents_hashrnd); ++ hash = __ipv6_addr_jhash(&rt->rt6i_src.addr, hash); ++ ++ id = ip_idents_reserve(hash, 1); ++ fhdr->identification = htonl(id); ++} ++ + int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) + { + struct sk_buff *frag; + struct rt6_info *rt = (struct rt6_info*)skb_dst(skb); +- struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; ++ struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ? ++ inet6_sk(skb->sk) : NULL; + struct ipv6hdr *tmp_hdr; + struct frag_hdr *fh; + unsigned int mtu, hlen, left, len; +@@ -994,7 +1009,7 @@ struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, + if (final_dst) + fl6->daddr = *final_dst; + +- return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); ++ return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); + } + EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow); + +@@ -1026,7 +1041,7 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, + if (final_dst) + fl6->daddr = *final_dst; + +- return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); ++ return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); + } + EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); + +@@ -1280,7 +1295,8 @@ emsgsize: + if (((length > mtu) || + (skb && skb_is_gso(skb))) && + (sk->sk_protocol == IPPROTO_UDP) && +- (rt->dst.dev->features & NETIF_F_UFO)) { ++ (rt->dst.dev->features & NETIF_F_UFO) && ++ (sk->sk_type == SOCK_DGRAM)) { + err = ip6_ufo_append_data(sk, getfrag, from, length, + hh_len, fragheaderlen, + transhdrlen, mtu, flags, rt); +diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c +index 9120339..657639d 100644 +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -272,9 +272,6 @@ static int ip6_tnl_create2(struct net_device *dev) + int err; + + t = netdev_priv(dev); +- err = ip6_tnl_dev_init(dev); +- if (err < 0) +- goto out; + + err = register_netdevice(dev); + if (err < 0) +@@ -1456,6 +1453,7 @@ ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) + + + static const struct net_device_ops ip6_tnl_netdev_ops = { ++ .ndo_init = ip6_tnl_dev_init, + .ndo_uninit = ip6_tnl_dev_uninit, + .ndo_start_xmit = ip6_tnl_xmit, + .ndo_do_ioctl = ip6_tnl_ioctl, +@@ -1547,16 +1545,10 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev) + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = dev_net(dev); + struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); +- int err = ip6_tnl_dev_init_gen(dev); +- +- if (err) +- return err; + + t->parms.proto = IPPROTO_IPV6; + dev_hold(dev); + +- ip6_tnl_link_config(t); +- + rcu_assign_pointer(ip6n->tnls_wc[0], t); + return 0; + } +diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c +index 2d19272..28456c9 100644 +--- a/net/ipv6/ip6_vti.c ++++ b/net/ipv6/ip6_vti.c +@@ -172,10 +172,6 @@ static int vti6_tnl_create2(struct net_device *dev) + struct vti6_net *ip6n = net_generic(net, vti6_net_id); + int err; + +- err = vti6_dev_init(dev); +- if (err < 0) +- goto out; +- + err = register_netdevice(dev); + if (err < 0) + goto out; +@@ -693,6 +689,7 @@ static int vti6_change_mtu(struct net_device *dev, int new_mtu) + } + + static const struct net_device_ops vti6_netdev_ops = { ++ .ndo_init = vti6_dev_init, + .ndo_uninit = vti6_dev_uninit, + .ndo_start_xmit = vti6_tnl_xmit, + .ndo_do_ioctl = vti6_ioctl, +@@ -772,16 +769,10 @@ static int __net_init vti6_fb_tnl_dev_init(struct net_device *dev) + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = dev_net(dev); + struct vti6_net *ip6n = net_generic(net, vti6_net_id); +- int err = vti6_dev_init_gen(dev); +- +- if (err) +- return err; + + t->parms.proto = IPPROTO_IPV6; + dev_hold(dev); + +- vti6_link_config(t); +- + rcu_assign_pointer(ip6n->tnls_wc[0], t); + return 0; + } +@@ -834,6 +825,15 @@ static int vti6_newlink(struct net *src_net, struct net_device *dev, + return vti6_tnl_create2(dev); + } + ++static void vti6_dellink(struct net_device *dev, struct list_head *head) ++{ ++ struct net *net = dev_net(dev); ++ struct vti6_net *ip6n = net_generic(net, vti6_net_id); ++ ++ if (dev != ip6n->fb_tnl_dev) ++ unregister_netdevice_queue(dev, head); ++} ++ + static int vti6_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[]) + { +@@ -909,6 +909,7 @@ static struct rtnl_link_ops vti6_link_ops __read_mostly = { + .setup = vti6_dev_setup, + .validate = vti6_validate, + .newlink = vti6_newlink, ++ .dellink = vti6_dellink, + .changelink = vti6_changelink, + .get_size = vti6_get_size, + .fill_info = vti6_fill_info, +@@ -954,6 +955,7 @@ static int __net_init vti6_init_net(struct net *net) + if (!ip6n->fb_tnl_dev) + goto err_alloc_dev; + dev_net_set(ip6n->fb_tnl_dev, net); ++ ip6n->fb_tnl_dev->rtnl_link_ops = &vti6_link_ops; + + err = vti6_fb_tnl_dev_init(ip6n->fb_tnl_dev); + if (err < 0) +diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c +index 08b367c..761e458 100644 +--- a/net/ipv6/mcast.c ++++ b/net/ipv6/mcast.c +@@ -172,6 +172,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) + mc_lst->next = NULL; + mc_lst->addr = *addr; + ++ rtnl_lock(); + rcu_read_lock(); + if (ifindex == 0) { + struct rt6_info *rt; +@@ -185,6 +186,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) + + if (dev == NULL) { + rcu_read_unlock(); ++ rtnl_unlock(); + sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); + return -ENODEV; + } +@@ -202,6 +204,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) + + if (err) { + rcu_read_unlock(); ++ rtnl_unlock(); + sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); + return err; + } +@@ -212,6 +215,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) + spin_unlock(&ipv6_sk_mc_lock); + + rcu_read_unlock(); ++ rtnl_unlock(); + + return 0; + } +@@ -229,6 +233,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) + if (!ipv6_addr_is_multicast(addr)) + return -EINVAL; + ++ rtnl_lock(); + spin_lock(&ipv6_sk_mc_lock); + for (lnk = &np->ipv6_mc_list; + (mc_lst = rcu_dereference_protected(*lnk, +@@ -252,12 +257,15 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) + } else + (void) ip6_mc_leave_src(sk, mc_lst, NULL); + rcu_read_unlock(); ++ rtnl_unlock(); ++ + atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc); + kfree_rcu(mc_lst, rcu); + return 0; + } + } + spin_unlock(&ipv6_sk_mc_lock); ++ rtnl_unlock(); + + return -EADDRNOTAVAIL; + } +@@ -302,6 +310,7 @@ void ipv6_sock_mc_close(struct sock *sk) + if (!rcu_access_pointer(np->ipv6_mc_list)) + return; + ++ rtnl_lock(); + spin_lock(&ipv6_sk_mc_lock); + while ((mc_lst = rcu_dereference_protected(np->ipv6_mc_list, + lockdep_is_held(&ipv6_sk_mc_lock))) != NULL) { +@@ -328,6 +337,7 @@ void ipv6_sock_mc_close(struct sock *sk) + spin_lock(&ipv6_sk_mc_lock); + } + spin_unlock(&ipv6_sk_mc_lock); ++ rtnl_unlock(); + } + + int ip6_mc_source(int add, int omode, struct sock *sk, +@@ -845,6 +855,8 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr) + struct ifmcaddr6 *mc; + struct inet6_dev *idev; + ++ ASSERT_RTNL(); ++ + /* we need to take a reference on idev */ + idev = in6_dev_get(dev); + +@@ -916,6 +928,8 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr) + { + struct ifmcaddr6 *ma, **map; + ++ ASSERT_RTNL(); ++ + write_lock_bh(&idev->lock); + for (map = &idev->mc_list; (ma=*map) != NULL; map = &ma->next) { + if (ipv6_addr_equal(&ma->mca_addr, addr)) { +diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c +index 09a22f4..bcd6518 100644 +--- a/net/ipv6/ndisc.c ++++ b/net/ipv6/ndisc.c +@@ -1193,7 +1193,14 @@ static void ndisc_router_discovery(struct sk_buff *skb) + if (rt) + rt6_set_expires(rt, jiffies + (HZ * lifetime)); + if (ra_msg->icmph.icmp6_hop_limit) { +- in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; ++ /* Only set hop_limit on the interface if it is higher than ++ * the current hop_limit. ++ */ ++ if (in6_dev->cnf.hop_limit < ra_msg->icmph.icmp6_hop_limit) { ++ in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; ++ } else { ++ ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than current\n"); ++ } + if (rt) + dst_metric_set(&rt->dst, RTAX_HOPLIMIT, + ra_msg->icmph.icmp6_hop_limit); +diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c +index b31a012..ae4a06b 100644 +--- a/net/ipv6/output_core.c ++++ b/net/ipv6/output_core.c +@@ -3,33 +3,43 @@ + * not configured or static. These functions are needed by GSO/GRO implementation. + */ + #include ++#include + #include + #include + #include + +-void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) ++/* This function exists only for tap drivers that must support broken ++ * clients requesting UFO without specifying an IPv6 fragment ID. ++ * ++ * This is similar to ipv6_select_ident() but we use an independent hash ++ * seed to limit information leakage. ++ * ++ * The network header must be set before calling this. ++ */ ++void ipv6_proxy_select_ident(struct sk_buff *skb) + { +- static atomic_t ipv6_fragmentation_id; +- int ident; +- +-#if IS_ENABLED(CONFIG_IPV6) +- if (rt && !(rt->dst.flags & DST_NOPEER)) { +- struct inet_peer *peer; +- struct net *net; +- +- net = dev_net(rt->dst.dev); +- peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1); +- if (peer) { +- fhdr->identification = htonl(inet_getid(peer, 0)); +- inet_putpeer(peer); +- return; +- } +- } +-#endif +- ident = atomic_inc_return(&ipv6_fragmentation_id); +- fhdr->identification = htonl(ident); ++ static u32 ip6_proxy_idents_hashrnd __read_mostly; ++ struct in6_addr buf[2]; ++ struct in6_addr *addrs; ++ u32 hash, id; ++ ++ addrs = skb_header_pointer(skb, ++ skb_network_offset(skb) + ++ offsetof(struct ipv6hdr, saddr), ++ sizeof(buf), buf); ++ if (!addrs) ++ return; ++ ++ net_get_random_once(&ip6_proxy_idents_hashrnd, ++ sizeof(ip6_proxy_idents_hashrnd)); ++ ++ hash = __ipv6_addr_jhash(&addrs[1], ip6_proxy_idents_hashrnd); ++ hash = __ipv6_addr_jhash(&addrs[0], hash); ++ ++ id = ip_idents_reserve(hash, 1); ++ skb_shinfo(skb)->ip6_frag_id = htonl(id); + } +-EXPORT_SYMBOL(ipv6_select_ident); ++EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); + + int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) + { +diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c +index bda7429..4611995 100644 +--- a/net/ipv6/ping.c ++++ b/net/ipv6/ping.c +@@ -103,9 +103,10 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + + if (msg->msg_name) { + DECLARE_SOCKADDR(struct sockaddr_in6 *, u, msg->msg_name); +- if (msg->msg_namelen < sizeof(struct sockaddr_in6) || +- u->sin6_family != AF_INET6) { ++ if (msg->msg_namelen < sizeof(*u)) + return -EINVAL; ++ if (u->sin6_family != AF_INET6) { ++ return -EAFNOSUPPORT; + } + if (sk->sk_bound_dev_if && + sk->sk_bound_dev_if != u->sin6_scope_id) { +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 7cc1102..3809ca2 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -141,7 +141,7 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) + u32 *p = NULL; + + if (!(rt->dst.flags & DST_HOST)) +- return NULL; ++ return dst_cow_metrics_generic(dst, old); + + peer = rt6_get_peer_create(rt); + if (peer) { +@@ -1160,12 +1160,9 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, + struct net *net = dev_net(dst->dev); + + rt6->rt6i_flags |= RTF_MODIFIED; +- if (mtu < IPV6_MIN_MTU) { +- u32 features = dst_metric(dst, RTAX_FEATURES); ++ if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; +- features |= RTAX_FEATURE_ALLFRAG; +- dst_metric_set(dst, RTAX_FEATURES, features); +- } ++ + dst_metric_set(dst, RTAX_MTU, mtu); + rt6_update_expires(rt6, net->ipv6.sysctl.ip6_rt_mtu_expires); + } +diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c +index fe548ba..317b6db 100644 +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -101,19 +101,19 @@ static struct ip_tunnel *ipip6_tunnel_lookup(struct net *net, + for_each_ip_tunnel_rcu(t, sitn->tunnels_r_l[h0 ^ h1]) { + if (local == t->parms.iph.saddr && + remote == t->parms.iph.daddr && +- (!dev || !t->parms.link || dev->iflink == t->parms.link) && ++ (!dev || !t->parms.link || dev->ifindex == t->parms.link) && + (t->dev->flags & IFF_UP)) + return t; + } + for_each_ip_tunnel_rcu(t, sitn->tunnels_r[h0]) { + if (remote == t->parms.iph.daddr && +- (!dev || !t->parms.link || dev->iflink == t->parms.link) && ++ (!dev || !t->parms.link || dev->ifindex == t->parms.link) && + (t->dev->flags & IFF_UP)) + return t; + } + for_each_ip_tunnel_rcu(t, sitn->tunnels_l[h1]) { + if (local == t->parms.iph.saddr && +- (!dev || !t->parms.link || dev->iflink == t->parms.link) && ++ (!dev || !t->parms.link || dev->ifindex == t->parms.link) && + (t->dev->flags & IFF_UP)) + return t; + } +@@ -195,10 +195,8 @@ static int ipip6_tunnel_create(struct net_device *dev) + struct sit_net *sitn = net_generic(net, sit_net_id); + int err; + +- err = ipip6_tunnel_init(dev); +- if (err < 0) +- goto out; +- ipip6_tunnel_clone_6rd(dev, sitn); ++ memcpy(dev->dev_addr, &t->parms.iph.saddr, 4); ++ memcpy(dev->broadcast, &t->parms.iph.daddr, 4); + + if ((__force u16)t->parms.i_flags & SIT_ISATAP) + dev->priv_flags |= IFF_ISATAP; +@@ -207,7 +205,8 @@ static int ipip6_tunnel_create(struct net_device *dev) + if (err < 0) + goto out; + +- strcpy(t->parms.name, dev->name); ++ ipip6_tunnel_clone_6rd(dev, sitn); ++ + dev->rtnl_link_ops = &sit_link_ops; + + dev_hold(dev); +@@ -1321,6 +1320,7 @@ static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) + } + + static const struct net_device_ops ipip6_netdev_ops = { ++ .ndo_init = ipip6_tunnel_init, + .ndo_uninit = ipip6_tunnel_uninit, + .ndo_start_xmit = sit_tunnel_xmit, + .ndo_do_ioctl = ipip6_tunnel_ioctl, +@@ -1367,9 +1367,7 @@ static int ipip6_tunnel_init(struct net_device *dev) + + tunnel->dev = dev; + tunnel->net = dev_net(dev); +- +- memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); +- memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); ++ strcpy(tunnel->parms.name, dev->name); + + ipip6_tunnel_bind_dev(dev); + dev->tstats = alloc_percpu(struct pcpu_sw_netstats); +@@ -1401,7 +1399,6 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) + + tunnel->dev = dev; + tunnel->net = dev_net(dev); +- strcpy(tunnel->parms.name, dev->name); + + iph->version = 4; + iph->protocol = IPPROTO_IPV6; +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 889079b..b50ae29 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -905,7 +905,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) + tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, + tcp_time_stamp + tcptw->tw_ts_offset, + tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw), +- tw->tw_tclass, (tw->tw_flowlabel << 12)); ++ tw->tw_tclass, cpu_to_be32(tw->tw_flowlabel)); + + inet_twsk_put(tw); + } +@@ -1633,7 +1633,7 @@ static void tcp_v6_early_demux(struct sk_buff *skb) + skb->sk = sk; + skb->destructor = sock_edemux; + if (sk->sk_state != TCP_TIME_WAIT) { +- struct dst_entry *dst = sk->sk_rx_dst; ++ struct dst_entry *dst = ACCESS_ONCE(sk->sk_rx_dst); + + if (dst) + dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie); +@@ -1668,6 +1668,7 @@ static const struct inet_connection_sock_af_ops ipv6_specific = { + .compat_setsockopt = compat_ipv6_setsockopt, + .compat_getsockopt = compat_ipv6_getsockopt, + #endif ++ .mtu_reduced = tcp_v6_mtu_reduced, + }; + + #ifdef CONFIG_TCP_MD5SIG +@@ -1699,6 +1700,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = { + .compat_setsockopt = compat_ipv6_setsockopt, + .compat_getsockopt = compat_ipv6_getsockopt, + #endif ++ .mtu_reduced = tcp_v4_mtu_reduced, + }; + + #ifdef CONFIG_TCP_MD5SIG +@@ -1935,7 +1937,6 @@ struct proto tcpv6_prot = { + .sendpage = tcp_sendpage, + .backlog_rcv = tcp_v6_do_rcv, + .release_cb = tcp_release_cb, +- .mtu_reduced = tcp_v6_mtu_reduced, + .hash = tcp_v6_hash, + .unhash = inet_unhash, + .get_port = inet_csk_get_port, +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 20b63d2..38625a9 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -515,10 +515,8 @@ csum_copy_err: + } + unlock_sock_fast(sk, slow); + +- if (noblock) +- return -EAGAIN; +- +- /* starting over for a new packet */ ++ /* starting over for a new packet, but check if we need to yield */ ++ cond_resched(); + msg->msg_flags &= ~MSG_TRUNC; + goto try_again; + } +diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c +index 00b2a6d..d65aea2 100644 +--- a/net/ipx/af_ipx.c ++++ b/net/ipx/af_ipx.c +@@ -1763,6 +1763,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, + struct ipxhdr *ipx = NULL; + struct sk_buff *skb; + int copied, rc; ++ bool locked = true; + + lock_sock(sk); + /* put the autobinding in */ +@@ -1789,6 +1790,8 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, + if (sock_flag(sk, SOCK_ZAPPED)) + goto out; + ++ release_sock(sk); ++ locked = false; + skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, + flags & MSG_DONTWAIT, &rc); + if (!skb) +@@ -1822,7 +1825,8 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, + out_free: + skb_free_datagram(sk, skb); + out: +- release_sock(sk); ++ if (locked) ++ release_sock(sk); + return rc; + } + +diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c +index 2ba8b97..fdcb968 100644 +--- a/net/irda/ircomm/ircomm_tty.c ++++ b/net/irda/ircomm/ircomm_tty.c +@@ -818,7 +818,9 @@ static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout) + orig_jiffies = jiffies; + + /* Set poll time to 200 ms */ +- poll_time = IRDA_MIN(timeout, msecs_to_jiffies(200)); ++ poll_time = msecs_to_jiffies(200); ++ if (timeout) ++ poll_time = min_t(unsigned long, timeout, poll_time); + + spin_lock_irqsave(&self->spinlock, flags); + while (self->tx_skb && self->tx_skb->len) { +diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c +index ec66063..da8d067 100644 +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -758,7 +758,8 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, + /* If PMTU discovery was enabled, use the MTU that was discovered */ + dst = sk_dst_get(tunnel->sock); + if (dst != NULL) { +- u32 pmtu = dst_mtu(__sk_dst_get(tunnel->sock)); ++ u32 pmtu = dst_mtu(dst); ++ + if (pmtu != 0) + session->mtu = session->mru = pmtu - + PPPOL2TP_HEADER_OVERHEAD; +@@ -1368,7 +1369,7 @@ static int pppol2tp_setsockopt(struct socket *sock, int level, int optname, + int err; + + if (level != SOL_PPPOL2TP) +- return udp_prot.setsockopt(sk, level, optname, optval, optlen); ++ return -EINVAL; + + if (optlen < sizeof(int)) + return -EINVAL; +@@ -1494,7 +1495,7 @@ static int pppol2tp_getsockopt(struct socket *sock, int level, int optname, + struct pppol2tp_session *ps; + + if (level != SOL_PPPOL2TP) +- return udp_prot.getsockopt(sk, level, optname, optval, optlen); ++ return -EINVAL; + + if (get_user(len, optlen)) + return -EFAULT; +diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c +index 612a5dd..799bafc 100644 +--- a/net/llc/sysctl_net_llc.c ++++ b/net/llc/sysctl_net_llc.c +@@ -18,28 +18,28 @@ static struct ctl_table llc2_timeout_table[] = { + { + .procname = "ack", + .data = &sysctl_llc2_ack_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_ack_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "busy", + .data = &sysctl_llc2_busy_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_busy_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "p", + .data = &sysctl_llc2_p_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_p_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "rej", + .data = &sysctl_llc2_rej_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_rej_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, +diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c +index 7c7df47..f056f9ed 100644 +--- a/net/mac80211/aes_ccm.c ++++ b/net/mac80211/aes_ccm.c +@@ -54,6 +54,9 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, + + memset(&aead_req, 0, sizeof(aead_req)); + ++ if (data_len == 0) ++ return -EINVAL; ++ + sg_init_one(&pt, data, data_len); + sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); + sg_init_table(ct, 2); +diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c +index 653ce5d..5d8bc1f 100644 +--- a/net/mac80211/debugfs_netdev.c ++++ b/net/mac80211/debugfs_netdev.c +@@ -712,6 +712,7 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) + + debugfs_remove_recursive(sdata->vif.debugfs_dir); + sdata->vif.debugfs_dir = NULL; ++ sdata->debugfs.subdir_stations = NULL; + } + + void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) +diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c +index e09f10a..82fbf32 100644 +--- a/net/mac80211/ibss.c ++++ b/net/mac80211/ibss.c +@@ -815,7 +815,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, + + memset(¶ms, 0, sizeof(params)); + memset(&csa_ie, 0, sizeof(csa_ie)); +- err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, ++ err = ieee80211_parse_ch_switch_ie(sdata, elems, + ifibss->chandef.chan->band, + sta_flags, ifibss->bssid, &csa_ie); + /* can't switch to destination channel, fail */ +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index b127902..e278c64 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -57,13 +57,24 @@ struct ieee80211_local; + #define IEEE80211_UNSET_POWER_LEVEL INT_MIN + + /* +- * Some APs experience problems when working with U-APSD. Decrease the +- * probability of that happening by using legacy mode for all ACs but VO. +- * The AP that caused us trouble was a Cisco 4410N. It ignores our +- * setting, and always treats non-VO ACs as legacy. ++ * Some APs experience problems when working with U-APSD. Decreasing the ++ * probability of that happening by using legacy mode for all ACs but VO isn't ++ * enough. ++ * ++ * Cisco 4410N originally forced us to enable VO by default only because it ++ * treated non-VO ACs as legacy. ++ * ++ * However some APs (notably Netgear R7000) silently reclassify packets to ++ * different ACs. Since u-APSD ACs require trigger frames for frame retrieval ++ * clients would never see some frames (e.g. ARP responses) or would fetch them ++ * accidentally after a long time. ++ * ++ * It makes little sense to enable u-APSD queues by default because it needs ++ * userspace applications to be aware of it to actually take advantage of the ++ * possible additional powersavings. Implicitly depending on driver autotrigger ++ * frame support doesn't make much sense. + */ +-#define IEEE80211_DEFAULT_UAPSD_QUEUES \ +- IEEE80211_WMM_IE_STA_QOSINFO_AC_VO ++#define IEEE80211_DEFAULT_UAPSD_QUEUES 0 + + #define IEEE80211_DEFAULT_MAX_SP_LEN \ + IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL +@@ -1569,7 +1580,6 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, + * ieee80211_parse_ch_switch_ie - parses channel switch IEs + * @sdata: the sdata of the interface which has received the frame + * @elems: parsed 802.11 elements received with the frame +- * @beacon: indicates if the frame was a beacon or probe response + * @current_band: indicates the current band + * @sta_flags: contains information about own capabilities and restrictions + * to decide which channel switch announcements can be accepted. Only the +@@ -1583,7 +1593,7 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, + * Return: 0 on success, <0 on error and >0 if there is nothing to parse. + */ + int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, +- struct ieee802_11_elems *elems, bool beacon, ++ struct ieee802_11_elems *elems, + enum ieee80211_band current_band, + u32 sta_flags, u8 *bssid, + struct ieee80211_csa_ie *csa_ie); +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 8f7fabc..06f5de4 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -760,10 +760,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, + int i, flushed; + struct ps_data *ps; + struct cfg80211_chan_def chandef; ++ bool cancel_scan; + + clear_bit(SDATA_STATE_RUNNING, &sdata->state); + +- if (rcu_access_pointer(local->scan_sdata) == sdata) ++ cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata; ++ if (cancel_scan) + ieee80211_scan_cancel(local); + + /* +@@ -973,6 +975,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, + + ieee80211_recalc_ps(local, -1); + ++ if (cancel_scan) ++ flush_delayed_work(&local->scan_work); ++ + if (local->open_count == 0) { + ieee80211_stop_device(local); + +diff --git a/net/mac80211/key.c b/net/mac80211/key.c +index 6ff65a1..d78b37a 100644 +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -652,7 +652,7 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local, + int i; + + mutex_lock(&local->key_mtx); +- for (i = 0; i < NUM_DEFAULT_KEYS; i++) { ++ for (i = 0; i < ARRAY_SIZE(sta->gtk); i++) { + key = key_mtx_dereference(local, sta->gtk[i]); + if (!key) + continue; +diff --git a/net/mac80211/main.c b/net/mac80211/main.c +index c7a7a86..9e58c99 100644 +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -248,6 +248,7 @@ static void ieee80211_restart_work(struct work_struct *work) + { + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, restart_work); ++ struct ieee80211_sub_if_data *sdata; + + /* wait for scan work complete */ + flush_workqueue(local->workqueue); +@@ -256,6 +257,8 @@ static void ieee80211_restart_work(struct work_struct *work) + "%s called with hardware scan in progress\n", __func__); + + rtnl_lock(); ++ list_for_each_entry(sdata, &local->interfaces, list) ++ flush_delayed_work(&sdata->dec_tailroom_needed_wk); + ieee80211_scan_cancel(local); + ieee80211_reconfig(local); + rtnl_unlock(); +diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c +index 5b919ca..3d52d1d 100644 +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -885,7 +885,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, + + memset(¶ms, 0, sizeof(params)); + memset(&csa_ie, 0, sizeof(csa_ie)); +- err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, band, ++ err = ieee80211_parse_ch_switch_ie(sdata, elems, band, + sta_flags, sdata->vif.addr, + &csa_ie); + if (err < 0) +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index e6a84cb..c9535a9 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -1001,7 +1001,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, + + current_band = cbss->channel->band; + memset(&csa_ie, 0, sizeof(csa_ie)); +- res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band, ++ res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band, + ifmgd->flags, + ifmgd->associated->bssid, &csa_ie); + if (res < 0) +@@ -1086,7 +1086,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, + ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work); + else + mod_timer(&ifmgd->chswitch_timer, +- TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval)); ++ TU_TO_EXP_TIME((csa_ie.count - 1) * ++ cbss->beacon_interval)); + } + + static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, +@@ -4240,8 +4241,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, + rcu_read_unlock(); + + if (bss->wmm_used && bss->uapsd_supported && +- (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) && +- sdata->wmm_acm != 0xff) { ++ (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { + assoc_data->uapsd = true; + ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; + } else { +diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c +index 22b223f..74350c3 100644 +--- a/net/mac80211/rate.c ++++ b/net/mac80211/rate.c +@@ -462,7 +462,7 @@ static void rate_fixup_ratelist(struct ieee80211_vif *vif, + */ + if (!(rates[0].flags & IEEE80211_TX_RC_MCS)) { + u32 basic_rates = vif->bss_conf.basic_rates; +- s8 baserate = basic_rates ? ffs(basic_rates - 1) : 0; ++ s8 baserate = basic_rates ? ffs(basic_rates) - 1 : 0; + + rate = &sband->bitrates[rates[0].idx]; + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 3e57f96..9abb445 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -261,7 +261,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, + else if (rate && rate->flags & IEEE80211_RATE_ERP_G) + channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; + else if (rate) +- channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; ++ channel_flags |= IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ; + else + channel_flags |= IEEE80211_CHAN_2GHZ; + put_unaligned_le16(channel_flags, pos); +@@ -1679,11 +1679,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + sc = le16_to_cpu(hdr->seq_ctrl); + frag = sc & IEEE80211_SCTL_FRAG; + +- if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || +- is_multicast_ether_addr(hdr->addr1))) { +- /* not fragmented */ +- goto out; ++ if (is_multicast_ether_addr(hdr->addr1)) { ++ rx->local->dot11MulticastReceivedFrameCount++; ++ goto out_no_led; + } ++ ++ if (likely(!ieee80211_has_morefrags(fc) && frag == 0)) ++ goto out; ++ + I802_DEBUG_INC(rx->local->rx_handlers_fragments); + + if (skb_linearize(rx->skb)) +@@ -1774,12 +1777,10 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) + status->rx_flags |= IEEE80211_RX_FRAGMENTED; + + out: ++ ieee80211_led_rx(rx->local); ++ out_no_led: + if (rx->sta) + rx->sta->rx_packets++; +- if (is_multicast_ether_addr(hdr->addr1)) +- rx->local->dot11MulticastReceivedFrameCount++; +- else +- ieee80211_led_rx(rx->local); + return RX_CONTINUE; + } + +@@ -2106,6 +2107,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) + hdr = (struct ieee80211_hdr *) skb->data; + mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); + ++ if (ieee80211_drop_unencrypted(rx, hdr->frame_control)) ++ return RX_DROP_MONITOR; ++ + /* frame is in RMC, don't forward */ + if (ieee80211_is_data(hdr->frame_control) && + is_multicast_ether_addr(hdr->addr1) && +diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c +index 6ab0090..efeba56 100644 +--- a/net/mac80211/spectmgmt.c ++++ b/net/mac80211/spectmgmt.c +@@ -22,7 +22,7 @@ + #include "wme.h" + + int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, +- struct ieee802_11_elems *elems, bool beacon, ++ struct ieee802_11_elems *elems, + enum ieee80211_band current_band, + u32 sta_flags, u8 *bssid, + struct ieee80211_csa_ie *csa_ie) +@@ -91,19 +91,13 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, + return -EINVAL; + } + +- if (!beacon && sec_chan_offs) { ++ if (sec_chan_offs) { + secondary_channel_offset = sec_chan_offs->sec_chan_offs; +- } else if (beacon && ht_oper) { +- secondary_channel_offset = +- ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; + } else if (!(sta_flags & IEEE80211_STA_DISABLE_HT)) { +- /* If it's not a beacon, HT is enabled and the IE not present, +- * it's 20 MHz, 802.11-2012 8.5.2.6: +- * This element [the Secondary Channel Offset Element] is +- * present when switching to a 40 MHz channel. It may be +- * present when switching to a 20 MHz channel (in which +- * case the secondary channel offset is set to SCN). +- */ ++ /* If the secondary channel offset IE is not present, ++ * we can't know what's the post-CSA offset, so the ++ * best we can do is use 20MHz. ++ */ + secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; + } + +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index c14c16a..dca076f 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -414,6 +414,9 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) + if (ieee80211_has_order(hdr->frame_control)) + return TX_CONTINUE; + ++ if (ieee80211_is_probe_req(hdr->frame_control)) ++ return TX_CONTINUE; ++ + if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) + info->hw_queue = tx->sdata->vif.cab_queue; + +@@ -464,6 +467,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) + { + struct sta_info *sta = tx->sta; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; + struct ieee80211_local *local = tx->local; + + if (unlikely(!sta)) +@@ -474,6 +478,15 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) + !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) { + int ac = skb_get_queue_mapping(tx->skb); + ++ /* only deauth, disassoc and action are bufferable MMPDUs */ ++ if (ieee80211_is_mgmt(hdr->frame_control) && ++ !ieee80211_is_deauth(hdr->frame_control) && ++ !ieee80211_is_disassoc(hdr->frame_control) && ++ !ieee80211_is_action(hdr->frame_control)) { ++ info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; ++ return TX_CONTINUE; ++ } ++ + ps_dbg(sta->sdata, "STA %pM aid %d: PS buffer for AC %d\n", + sta->sta.addr, sta->sta.aid, ac); + if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) +@@ -532,22 +545,8 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) + static ieee80211_tx_result debug_noinline + ieee80211_tx_h_ps_buf(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(tx->flags & IEEE80211_TX_PS_BUFFERED)) + return TX_CONTINUE; +- +- /* only deauth, disassoc and action are bufferable MMPDUs */ +- if (ieee80211_is_mgmt(hdr->frame_control) && +- !ieee80211_is_deauth(hdr->frame_control) && +- !ieee80211_is_disassoc(hdr->frame_control) && +- !ieee80211_is_action(hdr->frame_control)) { +- if (tx->flags & IEEE80211_TX_UNICAST) +- info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; +- return TX_CONTINUE; +- } +- + if (tx->flags & IEEE80211_TX_UNICAST) + return ieee80211_tx_h_unicast_ps_buf(tx); + else +@@ -563,6 +562,7 @@ ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx) + if (tx->sdata->control_port_no_encrypt) + info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; + info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO; ++ info->flags |= IEEE80211_TX_CTL_USE_MINRATE; + } + + return TX_CONTINUE; +diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c +index 6ee2b58..f21b142 100644 +--- a/net/mac80211/wep.c ++++ b/net/mac80211/wep.c +@@ -98,8 +98,7 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local, + + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); + +- if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN || +- skb_headroom(skb) < IEEE80211_WEP_IV_LEN)) ++ if (WARN_ON(skb_headroom(skb) < IEEE80211_WEP_IV_LEN)) + return NULL; + + hdrlen = ieee80211_hdrlen(hdr->frame_control); +@@ -169,6 +168,9 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, + size_t len; + u8 rc4key[3 + WLAN_KEY_LEN_WEP104]; + ++ if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN)) ++ return -1; ++ + iv = ieee80211_wep_add_iv(local, skb, keylen, keyidx); + if (!iv) + return -1; +diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c +index de770ec..53ea164 100644 +--- a/net/netfilter/ipset/ip_set_core.c ++++ b/net/netfilter/ipset/ip_set_core.c +@@ -636,7 +636,7 @@ ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index) + struct ip_set *set; + struct ip_set_net *inst = ip_set_pernet(net); + +- if (index > inst->ip_set_max) ++ if (index >= inst->ip_set_max) + return IPSET_INVALID_ID; + + nfnl_lock(NFNL_SUBSYS_IPSET); +@@ -1839,6 +1839,12 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len) + if (*op < IP_SET_OP_VERSION) { + /* Check the version at the beginning of operations */ + struct ip_set_req_version *req_version = data; ++ ++ if (*len < sizeof(struct ip_set_req_version)) { ++ ret = -EINVAL; ++ goto done; ++ } ++ + if (req_version->version != IPSET_PROTOCOL) { + ret = -EPROTO; + goto done; +diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c +index a8eb0a8..610e19c 100644 +--- a/net/netfilter/ipvs/ip_vs_conn.c ++++ b/net/netfilter/ipvs/ip_vs_conn.c +@@ -797,7 +797,6 @@ static void ip_vs_conn_expire(unsigned long data) + ip_vs_control_del(cp); + + if (cp->flags & IP_VS_CONN_F_NFCT) { +- ip_vs_conn_drop_conntrack(cp); + /* Do not access conntracks during subsys cleanup + * because nf_conntrack_find_get can not be used after + * conntrack cleanup for the net. +diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c +index 3d2d2c8..847d2a2 100644 +--- a/net/netfilter/ipvs/ip_vs_core.c ++++ b/net/netfilter/ipvs/ip_vs_core.c +@@ -658,16 +658,24 @@ static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user) + return err; + } + +-static int ip_vs_route_me_harder(int af, struct sk_buff *skb) ++static int ip_vs_route_me_harder(int af, struct sk_buff *skb, ++ unsigned int hooknum) + { ++ if (!sysctl_snat_reroute(skb)) ++ return 0; ++ /* Reroute replies only to remote clients (FORWARD and LOCAL_OUT) */ ++ if (NF_INET_LOCAL_IN == hooknum) ++ return 0; + #ifdef CONFIG_IP_VS_IPV6 + if (af == AF_INET6) { +- if (sysctl_snat_reroute(skb) && ip6_route_me_harder(skb) != 0) ++ struct dst_entry *dst = skb_dst(skb); ++ ++ if (dst->dev && !(dst->dev->flags & IFF_LOOPBACK) && ++ ip6_route_me_harder(skb) != 0) + return 1; + } else + #endif +- if ((sysctl_snat_reroute(skb) || +- skb_rtable(skb)->rt_flags & RTCF_LOCAL) && ++ if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL) && + ip_route_me_harder(skb, RTN_LOCAL) != 0) + return 1; + +@@ -790,7 +798,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb, + union nf_inet_addr *snet, + __u8 protocol, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, +- unsigned int offset, unsigned int ihl) ++ unsigned int offset, unsigned int ihl, ++ unsigned int hooknum) + { + unsigned int verdict = NF_DROP; + +@@ -820,7 +829,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb, + #endif + ip_vs_nat_icmp(skb, pp, cp, 1); + +- if (ip_vs_route_me_harder(af, skb)) ++ if (ip_vs_route_me_harder(af, skb, hooknum)) + goto out; + + /* do the statistics and put it back */ +@@ -915,7 +924,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related, + + snet.ip = iph->saddr; + return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp, +- pp, ciph.len, ihl); ++ pp, ciph.len, ihl, hooknum); + } + + #ifdef CONFIG_IP_VS_IPV6 +@@ -980,7 +989,8 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related, + snet.in6 = ciph.saddr.in6; + writable = ciph.len; + return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp, +- pp, writable, sizeof(struct ipv6hdr)); ++ pp, writable, sizeof(struct ipv6hdr), ++ hooknum); + } + #endif + +@@ -1039,7 +1049,8 @@ static inline bool is_new_conn(const struct sk_buff *skb, + */ + static unsigned int + handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, +- struct ip_vs_conn *cp, struct ip_vs_iphdr *iph) ++ struct ip_vs_conn *cp, struct ip_vs_iphdr *iph, ++ unsigned int hooknum) + { + struct ip_vs_protocol *pp = pd->pp; + +@@ -1077,7 +1088,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, + * if it came from this machine itself. So re-compute + * the routing information. + */ +- if (ip_vs_route_me_harder(af, skb)) ++ if (ip_vs_route_me_harder(af, skb, hooknum)) + goto drop; + + IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT"); +@@ -1180,7 +1191,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) + cp = pp->conn_out_get(af, skb, &iph, 0); + + if (likely(cp)) +- return handle_response(af, skb, pd, cp, &iph); ++ return handle_response(af, skb, pd, cp, &iph, hooknum); + if (sysctl_nat_icmp_send(net) && + (pp->protocol == IPPROTO_TCP || + pp->protocol == IPPROTO_UDP || +@@ -1906,7 +1917,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { + { + .hook = ip_vs_local_reply6, + .owner = THIS_MODULE, +- .pf = NFPROTO_IPV4, ++ .pf = NFPROTO_IPV6, + .hooknum = NF_INET_LOCAL_OUT, + .priority = NF_IP6_PRI_NAT_DST + 1, + }, +diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c +index 77c1732..4a662f1 100644 +--- a/net/netfilter/ipvs/ip_vs_ftp.c ++++ b/net/netfilter/ipvs/ip_vs_ftp.c +@@ -183,6 +183,8 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, + struct nf_conn *ct; + struct net *net; + ++ *diff = 0; ++ + #ifdef CONFIG_IP_VS_IPV6 + /* This application helper doesn't work with IPv6 yet, + * so turn this into a no-op for IPv6 packets +@@ -191,8 +193,6 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, + return 1; + #endif + +- *diff = 0; +- + /* Only useful for established sessions */ + if (cp->state != IP_VS_TCP_S_ESTABLISHED) + return 1; +@@ -321,6 +321,9 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, + struct ip_vs_conn *n_cp; + struct net *net; + ++ /* no diff required for incoming packets */ ++ *diff = 0; ++ + #ifdef CONFIG_IP_VS_IPV6 + /* This application helper doesn't work with IPv6 yet, + * so turn this into a no-op for IPv6 packets +@@ -329,9 +332,6 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, + return 1; + #endif + +- /* no diff required for incoming packets */ +- *diff = 0; +- + /* Only useful for established sessions */ + if (cp->state != IP_VS_TCP_S_ESTABLISHED) + return 1; +diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c +index db80126..a8027e7 100644 +--- a/net/netfilter/ipvs/ip_vs_sync.c ++++ b/net/netfilter/ipvs/ip_vs_sync.c +@@ -891,6 +891,8 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param, + IP_VS_DBG(2, "BACKUP, add new conn. failed\n"); + return; + } ++ if (!(flags & IP_VS_CONN_F_TEMPLATE)) ++ kfree(param->pe_data); + } + + if (opt) +@@ -1164,6 +1166,7 @@ static inline int ip_vs_proc_sync_conn(struct net *net, __u8 *p, __u8 *msg_end) + (opt_flags & IPVS_OPT_F_SEQ_DATA ? &opt : NULL) + ); + #endif ++ ip_vs_pe_put(param.pe); + return 0; + /* Error exit */ + out: +diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c +index c47444e..1692e75 100644 +--- a/net/netfilter/ipvs/ip_vs_xmit.c ++++ b/net/netfilter/ipvs/ip_vs_xmit.c +@@ -883,7 +883,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, + iph->daddr = cp->daddr.ip; + iph->saddr = saddr; + iph->ttl = old_iph->ttl; +- ip_select_ident(skb, &rt->dst, NULL); ++ ip_select_ident(skb, NULL); + + /* Another hack: avoid icmp_send in ip_fragment */ + skb->local_df = 1; +@@ -967,8 +967,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + iph->nexthdr = IPPROTO_IPV6; + iph->payload_len = old_iph->payload_len; + be16_add_cpu(&iph->payload_len, sizeof(*old_iph)); +- iph->priority = old_iph->priority; + memset(&iph->flow_lbl, 0, sizeof(iph->flow_lbl)); ++ ipv6_change_dsfield(iph, 0, ipv6_get_dsfield(old_iph)); + iph->daddr = cp->daddr.in6; + iph->saddr = saddr; + iph->hop_limit = old_iph->hop_limit; +diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c +index d25f293..957c1db 100644 +--- a/net/netfilter/nf_conntrack_proto_generic.c ++++ b/net/netfilter/nf_conntrack_proto_generic.c +@@ -14,6 +14,30 @@ + + static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ; + ++static bool nf_generic_should_process(u8 proto) ++{ ++ switch (proto) { ++#ifdef CONFIG_NF_CT_PROTO_SCTP_MODULE ++ case IPPROTO_SCTP: ++ return false; ++#endif ++#ifdef CONFIG_NF_CT_PROTO_DCCP_MODULE ++ case IPPROTO_DCCP: ++ return false; ++#endif ++#ifdef CONFIG_NF_CT_PROTO_GRE_MODULE ++ case IPPROTO_GRE: ++ return false; ++#endif ++#ifdef CONFIG_NF_CT_PROTO_UDPLITE_MODULE ++ case IPPROTO_UDPLITE: ++ return false; ++#endif ++ default: ++ return true; ++ } ++} ++ + static inline struct nf_generic_net *generic_pernet(struct net *net) + { + return &net->ct.nf_ct_proto.generic; +@@ -67,7 +91,7 @@ static int generic_packet(struct nf_conn *ct, + static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb, + unsigned int dataoff, unsigned int *timeouts) + { +- return true; ++ return nf_generic_should_process(nf_ct_protonum(ct)); + } + + #if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT) +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index c68e5e0..99de240 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -855,7 +855,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, + + if (nla[NFTA_CHAIN_POLICY]) { + if ((chain != NULL && +- !(chain->flags & NFT_BASE_CHAIN)) || ++ !(chain->flags & NFT_BASE_CHAIN))) ++ return -EOPNOTSUPP; ++ ++ if (chain == NULL && + nla[NFTA_CHAIN_HOOK] == NULL) + return -EOPNOTSUPP; + +diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c +index bf8a108..6cf2f07 100644 +--- a/net/netfilter/nfnetlink.c ++++ b/net/netfilter/nfnetlink.c +@@ -265,7 +265,8 @@ replay: + nlh = nlmsg_hdr(skb); + err = 0; + +- if (nlh->nlmsg_len < NLMSG_HDRLEN) { ++ if (nlmsg_len(nlh) < sizeof(struct nfgenmsg) || ++ skb->len < nlh->nlmsg_len) { + err = -EINVAL; + goto ack; + } +diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c +index 9e287cb..54330fb 100644 +--- a/net/netfilter/nfnetlink_cthelper.c ++++ b/net/netfilter/nfnetlink_cthelper.c +@@ -77,6 +77,9 @@ nfnl_cthelper_parse_tuple(struct nf_conntrack_tuple *tuple, + if (!tb[NFCTH_TUPLE_L3PROTONUM] || !tb[NFCTH_TUPLE_L4PROTONUM]) + return -EINVAL; + ++ /* Not all fields are initialized so first zero the tuple */ ++ memset(tuple, 0, sizeof(struct nf_conntrack_tuple)); ++ + tuple->src.l3num = ntohs(nla_get_be16(tb[NFCTH_TUPLE_L3PROTONUM])); + tuple->dst.protonum = nla_get_u8(tb[NFCTH_TUPLE_L4PROTONUM]); + +@@ -86,7 +89,7 @@ nfnl_cthelper_parse_tuple(struct nf_conntrack_tuple *tuple, + static int + nfnl_cthelper_from_nlattr(struct nlattr *attr, struct nf_conn *ct) + { +- const struct nf_conn_help *help = nfct_help(ct); ++ struct nf_conn_help *help = nfct_help(ct); + + if (attr == NULL) + return -EINVAL; +@@ -94,7 +97,7 @@ nfnl_cthelper_from_nlattr(struct nlattr *attr, struct nf_conn *ct) + if (help->helper->data_len == 0) + return -EINVAL; + +- memcpy(&help->data, nla_data(attr), help->helper->data_len); ++ memcpy(help->data, nla_data(attr), help->helper->data_len); + return 0; + } + +diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c +index a155d19..6ff12a1 100644 +--- a/net/netfilter/nfnetlink_log.c ++++ b/net/netfilter/nfnetlink_log.c +@@ -45,7 +45,8 @@ + #define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE + #define NFULNL_TIMEOUT_DEFAULT 100 /* every second */ + #define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */ +-#define NFULNL_COPY_RANGE_MAX 0xFFFF /* max packet size is limited by 16-bit struct nfattr nfa_len field */ ++/* max packet size is limited by 16-bit struct nfattr nfa_len field */ ++#define NFULNL_COPY_RANGE_MAX (0xFFFF - NLA_HDRLEN) + + #define PRINTR(x, args...) do { if (net_ratelimit()) \ + printk(x, ## args); } while (0); +@@ -255,6 +256,8 @@ nfulnl_set_mode(struct nfulnl_instance *inst, u_int8_t mode, + + case NFULNL_COPY_PACKET: + inst->copy_mode = mode; ++ if (range == 0) ++ range = NFULNL_COPY_RANGE_MAX; + inst->copy_range = min_t(unsigned int, + range, NFULNL_COPY_RANGE_MAX); + break; +@@ -346,26 +349,25 @@ nfulnl_alloc_skb(struct net *net, u32 peer_portid, unsigned int inst_size, + return skb; + } + +-static int ++static void + __nfulnl_send(struct nfulnl_instance *inst) + { +- int status = -1; +- + if (inst->qlen > 1) { + struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0, + NLMSG_DONE, + sizeof(struct nfgenmsg), + 0); +- if (!nlh) ++ if (WARN_ONCE(!nlh, "bad nlskb size: %u, tailroom %d\n", ++ inst->skb->len, skb_tailroom(inst->skb))) { ++ kfree_skb(inst->skb); + goto out; ++ } + } +- status = nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid, +- MSG_DONTWAIT); +- ++ nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid, ++ MSG_DONTWAIT); ++out: + inst->qlen = 0; + inst->skb = NULL; +-out: +- return status; + } + + static void +@@ -652,7 +654,8 @@ nfulnl_log_packet(struct net *net, + + nla_total_size(sizeof(u_int32_t)) /* gid */ + + nla_total_size(plen) /* prefix */ + + nla_total_size(sizeof(struct nfulnl_msg_packet_hw)) +- + nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp)); ++ + nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp)) ++ + nla_total_size(sizeof(struct nfgenmsg)); /* NLMSG_DONE */ + + if (in && skb_mac_header_was_set(skb)) { + size += nla_total_size(skb->dev->hard_header_len) +@@ -681,8 +684,7 @@ nfulnl_log_packet(struct net *net, + break; + + case NFULNL_COPY_PACKET: +- if (inst->copy_range == 0 +- || inst->copy_range > skb->len) ++ if (inst->copy_range > skb->len) + data_len = skb->len; + else + data_len = inst->copy_range; +@@ -695,8 +697,7 @@ nfulnl_log_packet(struct net *net, + goto unlock_and_release; + } + +- if (inst->skb && +- size > skb_tailroom(inst->skb) - sizeof(struct nfgenmsg)) { ++ if (inst->skb && size > skb_tailroom(inst->skb)) { + /* either the queue len is too high or we don't have + * enough room in the skb left. flush to userspace. */ + __nfulnl_flush(inst); +diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c +index 82cb823..9695895 100644 +--- a/net/netfilter/nft_compat.c ++++ b/net/netfilter/nft_compat.c +@@ -82,6 +82,9 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par, + entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0; + break; + case AF_INET6: ++ if (proto) ++ entry->e6.ipv6.flags |= IP6T_F_PROTO; ++ + entry->e6.ipv6.proto = proto; + entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; + break; +@@ -313,6 +316,9 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx, + entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0; + break; + case AF_INET6: ++ if (proto) ++ entry->e6.ipv6.flags |= IP6T_F_PROTO; ++ + entry->e6.ipv6.proto = proto; + entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; + break; +@@ -611,8 +617,12 @@ nft_match_select_ops(const struct nft_ctx *ctx, + struct xt_match *match = nft_match->ops.data; + + if (strcmp(match->name, mt_name) == 0 && +- match->revision == rev && match->family == family) ++ match->revision == rev && match->family == family) { ++ if (!try_module_get(match->me)) ++ return ERR_PTR(-ENOENT); ++ + return &nft_match->ops; ++ } + } + + match = xt_request_find_match(family, mt_name, rev); +@@ -678,12 +688,16 @@ nft_target_select_ops(const struct nft_ctx *ctx, + family = ctx->afi->family; + + /* Re-use the existing target if it's already loaded. */ +- list_for_each_entry(nft_target, &nft_match_list, head) { ++ list_for_each_entry(nft_target, &nft_target_list, head) { + struct xt_target *target = nft_target->ops.data; + + if (strcmp(target->name, tg_name) == 0 && +- target->revision == rev && target->family == family) ++ target->revision == rev && target->family == family) { ++ if (!try_module_get(target->me)) ++ return ERR_PTR(-ENOENT); ++ + return &nft_target->ops; ++ } + } + + target = xt_request_find_target(family, tg_name, rev); +diff --git a/net/netfilter/xt_cgroup.c b/net/netfilter/xt_cgroup.c +index 9a8e77e7..ef5c75a 100644 +--- a/net/netfilter/xt_cgroup.c ++++ b/net/netfilter/xt_cgroup.c +@@ -31,7 +31,7 @@ static int cgroup_mt_check(const struct xt_mtchk_param *par) + if (info->invert & ~1) + return -EINVAL; + +- return info->id ? 0 : -EINVAL; ++ return 0; + } + + static bool +diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c +index a3910fc..47dc683 100644 +--- a/net/netfilter/xt_hashlimit.c ++++ b/net/netfilter/xt_hashlimit.c +@@ -104,7 +104,7 @@ struct xt_hashlimit_htable { + spinlock_t lock; /* lock for list_head */ + u_int32_t rnd; /* random seed for hash */ + unsigned int count; /* number entries in table */ +- struct timer_list timer; /* timer for gc */ ++ struct delayed_work gc_work; + + /* seq_file stuff */ + struct proc_dir_entry *pde; +@@ -213,7 +213,7 @@ dsthash_free(struct xt_hashlimit_htable *ht, struct dsthash_ent *ent) + call_rcu_bh(&ent->rcu, dsthash_free_rcu); + ht->count--; + } +-static void htable_gc(unsigned long htlong); ++static void htable_gc(struct work_struct *work); + + static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, + u_int8_t family) +@@ -273,9 +273,9 @@ static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, + } + hinfo->net = net; + +- setup_timer(&hinfo->timer, htable_gc, (unsigned long)hinfo); +- hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); +- add_timer(&hinfo->timer); ++ INIT_DEFERRABLE_WORK(&hinfo->gc_work, htable_gc); ++ queue_delayed_work(system_power_efficient_wq, &hinfo->gc_work, ++ msecs_to_jiffies(hinfo->cfg.gc_interval)); + + hlist_add_head(&hinfo->node, &hashlimit_net->htables); + +@@ -300,29 +300,30 @@ static void htable_selective_cleanup(struct xt_hashlimit_htable *ht, + { + unsigned int i; + +- /* lock hash table and iterate over it */ +- spin_lock_bh(&ht->lock); + for (i = 0; i < ht->cfg.size; i++) { + struct dsthash_ent *dh; + struct hlist_node *n; ++ ++ spin_lock_bh(&ht->lock); + hlist_for_each_entry_safe(dh, n, &ht->hash[i], node) { + if ((*select)(ht, dh)) + dsthash_free(ht, dh); + } ++ spin_unlock_bh(&ht->lock); ++ cond_resched(); + } +- spin_unlock_bh(&ht->lock); + } + +-/* hash table garbage collector, run by timer */ +-static void htable_gc(unsigned long htlong) ++static void htable_gc(struct work_struct *work) + { +- struct xt_hashlimit_htable *ht = (struct xt_hashlimit_htable *)htlong; ++ struct xt_hashlimit_htable *ht; ++ ++ ht = container_of(work, struct xt_hashlimit_htable, gc_work.work); + + htable_selective_cleanup(ht, select_gc); + +- /* re-add the timer accordingly */ +- ht->timer.expires = jiffies + msecs_to_jiffies(ht->cfg.gc_interval); +- add_timer(&ht->timer); ++ queue_delayed_work(system_power_efficient_wq, ++ &ht->gc_work, msecs_to_jiffies(ht->cfg.gc_interval)); + } + + static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo) +@@ -341,7 +342,7 @@ static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo) + + static void htable_destroy(struct xt_hashlimit_htable *hinfo) + { +- del_timer_sync(&hinfo->timer); ++ cancel_delayed_work_sync(&hinfo->gc_work); + htable_remove_proc_entry(hinfo); + htable_selective_cleanup(hinfo, select_all); + kfree(hinfo->name); +diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c +index 1ba6793..13332db 100644 +--- a/net/netfilter/xt_socket.c ++++ b/net/netfilter/xt_socket.c +@@ -243,12 +243,13 @@ static int + extract_icmp6_fields(const struct sk_buff *skb, + unsigned int outside_hdrlen, + int *protocol, +- struct in6_addr **raddr, +- struct in6_addr **laddr, ++ const struct in6_addr **raddr, ++ const struct in6_addr **laddr, + __be16 *rport, +- __be16 *lport) ++ __be16 *lport, ++ struct ipv6hdr *ipv6_var) + { +- struct ipv6hdr *inside_iph, _inside_iph; ++ const struct ipv6hdr *inside_iph; + struct icmp6hdr *icmph, _icmph; + __be16 *ports, _ports[2]; + u8 inside_nexthdr; +@@ -263,12 +264,14 @@ extract_icmp6_fields(const struct sk_buff *skb, + if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK) + return 1; + +- inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph), sizeof(_inside_iph), &_inside_iph); ++ inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph), ++ sizeof(*ipv6_var), ipv6_var); + if (inside_iph == NULL) + return 1; + inside_nexthdr = inside_iph->nexthdr; + +- inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + sizeof(_inside_iph), ++ inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + ++ sizeof(*ipv6_var), + &inside_nexthdr, &inside_fragoff); + if (inside_hdrlen < 0) + return 1; /* hjm: Packet has no/incomplete transport layer headers. */ +@@ -315,10 +318,10 @@ xt_socket_get_sock_v6(struct net *net, const u8 protocol, + static bool + socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) + { +- struct ipv6hdr *iph = ipv6_hdr(skb); ++ struct ipv6hdr ipv6_var, *iph = ipv6_hdr(skb); + struct udphdr _hdr, *hp = NULL; + struct sock *sk = skb->sk; +- struct in6_addr *daddr = NULL, *saddr = NULL; ++ const struct in6_addr *daddr = NULL, *saddr = NULL; + __be16 uninitialized_var(dport), uninitialized_var(sport); + int thoff = 0, uninitialized_var(tproto); + const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; +@@ -342,7 +345,7 @@ socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) + + } else if (tproto == IPPROTO_ICMPV6) { + if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr, +- &sport, &dport)) ++ &sport, &dport, &ipv6_var)) + return false; + } else { + return false; +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 0dfe894..a0b0ea9 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -205,7 +205,7 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb, + nskb->protocol = htons((u16) sk->sk_protocol); + nskb->pkt_type = netlink_is_kernel(sk) ? + PACKET_KERNEL : PACKET_USER; +- ++ skb_reset_network_header(nskb); + ret = dev_queue_xmit(nskb); + if (unlikely(ret > 0)) + ret = net_xmit_errno(ret); +@@ -510,14 +510,14 @@ out: + return err; + } + +-static void netlink_frame_flush_dcache(const struct nl_mmap_hdr *hdr) ++static void netlink_frame_flush_dcache(const struct nl_mmap_hdr *hdr, unsigned int nm_len) + { + #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE == 1 + struct page *p_start, *p_end; + + /* First page is flushed through netlink_{get,set}_status */ + p_start = pgvec_to_page(hdr + PAGE_SIZE); +- p_end = pgvec_to_page((void *)hdr + NL_MMAP_HDRLEN + hdr->nm_len - 1); ++ p_end = pgvec_to_page((void *)hdr + NL_MMAP_HDRLEN + nm_len - 1); + while (p_start <= p_end) { + flush_dcache_page(p_start); + p_start++; +@@ -535,9 +535,9 @@ static enum nl_mmap_status netlink_get_status(const struct nl_mmap_hdr *hdr) + static void netlink_set_status(struct nl_mmap_hdr *hdr, + enum nl_mmap_status status) + { ++ smp_mb(); + hdr->nm_status = status; + flush_dcache_page(pgvec_to_page(hdr)); +- smp_wmb(); + } + + static struct nl_mmap_hdr * +@@ -699,24 +699,16 @@ static int netlink_mmap_sendmsg(struct sock *sk, struct msghdr *msg, + struct nl_mmap_hdr *hdr; + struct sk_buff *skb; + unsigned int maxlen; +- bool excl = true; + int err = 0, len = 0; + +- /* Netlink messages are validated by the receiver before processing. +- * In order to avoid userspace changing the contents of the message +- * after validation, the socket and the ring may only be used by a +- * single process, otherwise we fall back to copying. +- */ +- if (atomic_long_read(&sk->sk_socket->file->f_count) > 2 || +- atomic_read(&nlk->mapped) > 1) +- excl = false; +- + mutex_lock(&nlk->pg_vec_lock); + + ring = &nlk->tx_ring; + maxlen = ring->frame_size - NL_MMAP_HDRLEN; + + do { ++ unsigned int nm_len; ++ + hdr = netlink_current_frame(ring, NL_MMAP_STATUS_VALID); + if (hdr == NULL) { + if (!(msg->msg_flags & MSG_DONTWAIT) && +@@ -724,35 +716,23 @@ static int netlink_mmap_sendmsg(struct sock *sk, struct msghdr *msg, + schedule(); + continue; + } +- if (hdr->nm_len > maxlen) { ++ ++ nm_len = ACCESS_ONCE(hdr->nm_len); ++ if (nm_len > maxlen) { + err = -EINVAL; + goto out; + } + +- netlink_frame_flush_dcache(hdr); ++ netlink_frame_flush_dcache(hdr, nm_len); + +- if (likely(dst_portid == 0 && dst_group == 0 && excl)) { +- skb = alloc_skb_head(GFP_KERNEL); +- if (skb == NULL) { +- err = -ENOBUFS; +- goto out; +- } +- sock_hold(sk); +- netlink_ring_setup_skb(skb, sk, ring, hdr); +- NETLINK_CB(skb).flags |= NETLINK_SKB_TX; +- __skb_put(skb, hdr->nm_len); +- netlink_set_status(hdr, NL_MMAP_STATUS_RESERVED); +- atomic_inc(&ring->pending); +- } else { +- skb = alloc_skb(hdr->nm_len, GFP_KERNEL); +- if (skb == NULL) { +- err = -ENOBUFS; +- goto out; +- } +- __skb_put(skb, hdr->nm_len); +- memcpy(skb->data, (void *)hdr + NL_MMAP_HDRLEN, hdr->nm_len); +- netlink_set_status(hdr, NL_MMAP_STATUS_UNUSED); ++ skb = alloc_skb(nm_len, GFP_KERNEL); ++ if (skb == NULL) { ++ err = -ENOBUFS; ++ goto out; + } ++ __skb_put(skb, nm_len); ++ memcpy(skb->data, (void *)hdr + NL_MMAP_HDRLEN, nm_len); ++ netlink_set_status(hdr, NL_MMAP_STATUS_UNUSED); + + netlink_increment_head(ring); + +@@ -798,7 +778,7 @@ static void netlink_queue_mmaped_skb(struct sock *sk, struct sk_buff *skb) + hdr->nm_pid = NETLINK_CB(skb).creds.pid; + hdr->nm_uid = from_kuid(sk_user_ns(sk), NETLINK_CB(skb).creds.uid); + hdr->nm_gid = from_kgid(sk_user_ns(sk), NETLINK_CB(skb).creds.gid); +- netlink_frame_flush_dcache(hdr); ++ netlink_frame_flush_dcache(hdr, hdr->nm_len); + netlink_set_status(hdr, NL_MMAP_STATUS_VALID); + + NETLINK_CB(skb).flags |= NETLINK_SKB_DELIVERED; +@@ -1644,13 +1624,11 @@ static struct sk_buff *netlink_alloc_large_skb(unsigned int size, + if (data == NULL) + return NULL; + +- skb = build_skb(data, size); ++ skb = __build_skb(data, size); + if (skb == NULL) + vfree(data); +- else { +- skb->head_frag = 0; ++ else + skb->destructor = netlink_skb_destructor; +- } + + return skb; + } +diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c +index 2c77e7b..600c764 100644 +--- a/net/openvswitch/actions.c ++++ b/net/openvswitch/actions.c +@@ -42,6 +42,9 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, + + static int make_writable(struct sk_buff *skb, int write_len) + { ++ if (!pskb_may_pull(skb, write_len)) ++ return -ENOMEM; ++ + if (!skb_cloned(skb) || skb_clone_writable(skb, write_len)) + return 0; + +@@ -70,6 +73,8 @@ static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci) + + vlan_set_encap_proto(skb, vhdr); + skb->mac_header += VLAN_HLEN; ++ if (skb_network_offset(skb) < ETH_HLEN) ++ skb_set_network_header(skb, ETH_HLEN); + skb_reset_mac_len(skb); + + return 0; +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 48a6a93..84a60b8 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -635,6 +635,7 @@ static void init_prb_bdqc(struct packet_sock *po, + p1->tov_in_jiffies = msecs_to_jiffies(p1->retire_blk_tov); + p1->blk_sizeof_priv = req_u->req3.tp_sizeof_priv; + ++ p1->max_frame_len = p1->kblk_size - BLK_PLUS_PRIV(p1->blk_sizeof_priv); + prb_init_ft_ops(p1, req_u); + prb_setup_retire_blk_timer(po, tx_ring); + prb_open_block(p1, pbd); +@@ -1263,16 +1264,6 @@ static void packet_sock_destruct(struct sock *sk) + sk_refcnt_debug_dec(sk); + } + +-static int fanout_rr_next(struct packet_fanout *f, unsigned int num) +-{ +- int x = atomic_read(&f->rr_cur) + 1; +- +- if (x >= num) +- x = 0; +- +- return x; +-} +- + static unsigned int fanout_demux_hash(struct packet_fanout *f, + struct sk_buff *skb, + unsigned int num) +@@ -1284,13 +1275,9 @@ static unsigned int fanout_demux_lb(struct packet_fanout *f, + struct sk_buff *skb, + unsigned int num) + { +- int cur, old; ++ unsigned int val = atomic_inc_return(&f->rr_cur); + +- cur = atomic_read(&f->rr_cur); +- while ((old = atomic_cmpxchg(&f->rr_cur, cur, +- fanout_rr_next(f, num))) != cur) +- cur = old; +- return cur; ++ return val % num; + } + + static unsigned int fanout_demux_cpu(struct packet_fanout *f, +@@ -1344,7 +1331,7 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *orig_dev) + { + struct packet_fanout *f = pt->af_packet_priv; +- unsigned int num = f->num_members; ++ unsigned int num = ACCESS_ONCE(f->num_members); + struct packet_sock *po; + unsigned int idx; + +@@ -1946,6 +1933,18 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, + if ((int)snaplen < 0) + snaplen = 0; + } ++ } else if (unlikely(macoff + snaplen > ++ GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len)) { ++ u32 nval; ++ ++ nval = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len - macoff; ++ pr_err_once("tpacket_rcv: packet too big, clamped from %u to %u. macoff=%u\n", ++ snaplen, nval, macoff); ++ snaplen = nval; ++ if (unlikely((int)snaplen < 0)) { ++ snaplen = 0; ++ macoff = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len; ++ } + } + spin_lock(&sk->sk_receive_queue.lock); + h.raw = packet_current_rx_frame(po, skb, +@@ -3779,6 +3778,10 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, + goto out; + if (unlikely(req->tp_block_size & (PAGE_SIZE - 1))) + goto out; ++ if (po->tp_version >= TPACKET_V3 && ++ (int)(req->tp_block_size - ++ BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0) ++ goto out; + if (unlikely(req->tp_frame_size < po->tp_hdrlen + + po->tp_reserve)) + goto out; +diff --git a/net/packet/internal.h b/net/packet/internal.h +index eb9580a..cdddf6a 100644 +--- a/net/packet/internal.h ++++ b/net/packet/internal.h +@@ -29,6 +29,7 @@ struct tpacket_kbdq_core { + char *pkblk_start; + char *pkblk_end; + int kblk_size; ++ unsigned int max_frame_len; + unsigned int knum_blocks; + uint64_t knxt_seq_num; + char *prev; +diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c +index e8fdb17..a985158 100644 +--- a/net/rds/ib_rdma.c ++++ b/net/rds/ib_rdma.c +@@ -759,8 +759,10 @@ void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents, + } + + ibmr = rds_ib_alloc_fmr(rds_ibdev); +- if (IS_ERR(ibmr)) ++ if (IS_ERR(ibmr)) { ++ rds_ib_dev_put(rds_ibdev); + return ibmr; ++ } + + ret = rds_ib_map_fmr(rds_ibdev, ibmr, sg, nents); + if (ret == 0) +diff --git a/net/rds/iw_rdma.c b/net/rds/iw_rdma.c +index a817705..dba8d08 100644 +--- a/net/rds/iw_rdma.c ++++ b/net/rds/iw_rdma.c +@@ -88,7 +88,9 @@ static unsigned int rds_iw_unmap_fastreg_list(struct rds_iw_mr_pool *pool, + int *unpinned); + static void rds_iw_destroy_fastreg(struct rds_iw_mr_pool *pool, struct rds_iw_mr *ibmr); + +-static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwdev, struct rdma_cm_id **cm_id) ++static int rds_iw_get_device(struct sockaddr_in *src, struct sockaddr_in *dst, ++ struct rds_iw_device **rds_iwdev, ++ struct rdma_cm_id **cm_id) + { + struct rds_iw_device *iwdev; + struct rds_iw_cm_id *i_cm_id; +@@ -112,15 +114,15 @@ static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwd + src_addr->sin_port, + dst_addr->sin_addr.s_addr, + dst_addr->sin_port, +- rs->rs_bound_addr, +- rs->rs_bound_port, +- rs->rs_conn_addr, +- rs->rs_conn_port); ++ src->sin_addr.s_addr, ++ src->sin_port, ++ dst->sin_addr.s_addr, ++ dst->sin_port); + #ifdef WORKING_TUPLE_DETECTION +- if (src_addr->sin_addr.s_addr == rs->rs_bound_addr && +- src_addr->sin_port == rs->rs_bound_port && +- dst_addr->sin_addr.s_addr == rs->rs_conn_addr && +- dst_addr->sin_port == rs->rs_conn_port) { ++ if (src_addr->sin_addr.s_addr == src->sin_addr.s_addr && ++ src_addr->sin_port == src->sin_port && ++ dst_addr->sin_addr.s_addr == dst->sin_addr.s_addr && ++ dst_addr->sin_port == dst->sin_port) { + #else + /* FIXME - needs to compare the local and remote + * ipaddr/port tuple, but the ipaddr is the only +@@ -128,7 +130,7 @@ static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwd + * zero'ed. It doesn't appear to be properly populated + * during connection setup... + */ +- if (src_addr->sin_addr.s_addr == rs->rs_bound_addr) { ++ if (src_addr->sin_addr.s_addr == src->sin_addr.s_addr) { + #endif + spin_unlock_irq(&iwdev->spinlock); + *rds_iwdev = iwdev; +@@ -180,19 +182,13 @@ int rds_iw_update_cm_id(struct rds_iw_device *rds_iwdev, struct rdma_cm_id *cm_i + { + struct sockaddr_in *src_addr, *dst_addr; + struct rds_iw_device *rds_iwdev_old; +- struct rds_sock rs; + struct rdma_cm_id *pcm_id; + int rc; + + src_addr = (struct sockaddr_in *)&cm_id->route.addr.src_addr; + dst_addr = (struct sockaddr_in *)&cm_id->route.addr.dst_addr; + +- rs.rs_bound_addr = src_addr->sin_addr.s_addr; +- rs.rs_bound_port = src_addr->sin_port; +- rs.rs_conn_addr = dst_addr->sin_addr.s_addr; +- rs.rs_conn_port = dst_addr->sin_port; +- +- rc = rds_iw_get_device(&rs, &rds_iwdev_old, &pcm_id); ++ rc = rds_iw_get_device(src_addr, dst_addr, &rds_iwdev_old, &pcm_id); + if (rc) + rds_iw_remove_cm_id(rds_iwdev, cm_id); + +@@ -598,9 +594,17 @@ void *rds_iw_get_mr(struct scatterlist *sg, unsigned long nents, + struct rds_iw_device *rds_iwdev; + struct rds_iw_mr *ibmr = NULL; + struct rdma_cm_id *cm_id; ++ struct sockaddr_in src = { ++ .sin_addr.s_addr = rs->rs_bound_addr, ++ .sin_port = rs->rs_bound_port, ++ }; ++ struct sockaddr_in dst = { ++ .sin_addr.s_addr = rs->rs_conn_addr, ++ .sin_port = rs->rs_conn_port, ++ }; + int ret; + +- ret = rds_iw_get_device(rs, &rds_iwdev, &cm_id); ++ ret = rds_iw_get_device(&src, &dst, &rds_iwdev, &cm_id); + if (ret || !cm_id) { + ret = -ENODEV; + goto out; +diff --git a/net/rds/sysctl.c b/net/rds/sysctl.c +index b5cb2aa..35773ad 100644 +--- a/net/rds/sysctl.c ++++ b/net/rds/sysctl.c +@@ -71,14 +71,14 @@ static struct ctl_table rds_sysctl_rds_table[] = { + { + .procname = "max_unacked_packets", + .data = &rds_sysctl_max_unacked_packets, +- .maxlen = sizeof(unsigned long), ++ .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "max_unacked_bytes", + .data = &rds_sysctl_max_unacked_bytes, +- .maxlen = sizeof(unsigned long), ++ .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, +diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c +index 34b5490..4949f75 100644 +--- a/net/rxrpc/ar-recvmsg.c ++++ b/net/rxrpc/ar-recvmsg.c +@@ -87,7 +87,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, + if (!skb) { + /* nothing remains on the queue */ + if (copied && +- (msg->msg_flags & MSG_PEEK || timeo == 0)) ++ (flags & MSG_PEEK || timeo == 0)) + goto out; + + /* wait for a message to turn up */ +diff --git a/net/sched/ematch.c b/net/sched/ematch.c +index 3a633de..a2abc44 100644 +--- a/net/sched/ematch.c ++++ b/net/sched/ematch.c +@@ -227,6 +227,7 @@ static int tcf_em_validate(struct tcf_proto *tp, + * to replay the request. + */ + module_put(em->ops->owner); ++ em->ops = NULL; + err = -EAGAIN; + } + #endif +diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c +index 98532cf..bdaed31 100644 +--- a/net/sched/sch_api.c ++++ b/net/sched/sch_api.c +@@ -812,10 +812,8 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, + if (dev->flags & IFF_UP) + dev_deactivate(dev); + +- if (new && new->ops->attach) { +- new->ops->attach(new); +- num_q = 0; +- } ++ if (new && new->ops->attach) ++ goto skip; + + for (i = 0; i < num_q; i++) { + struct netdev_queue *dev_queue = dev_ingress_queue(dev); +@@ -831,12 +829,16 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, + qdisc_destroy(old); + } + ++skip: + if (!ingress) { + notify_and_destroy(net, skb, n, classid, + dev->qdisc, new); + if (new && !new->ops->attach) + atomic_inc(&new->refcnt); + dev->qdisc = new ? : &noop_qdisc; ++ ++ if (new && new->ops->attach) ++ new->ops->attach(new); + } else { + notify_and_destroy(net, skb, n, classid, old, new); + } +diff --git a/net/sctp/associola.c b/net/sctp/associola.c +index a4d5701..abc0922 100644 +--- a/net/sctp/associola.c ++++ b/net/sctp/associola.c +@@ -1151,6 +1151,7 @@ void sctp_assoc_update(struct sctp_association *asoc, + asoc->c = new->c; + asoc->peer.rwnd = new->peer.rwnd; + asoc->peer.sack_needed = new->peer.sack_needed; ++ asoc->peer.auth_capable = new->peer.auth_capable; + asoc->peer.i = new->peer.i; + sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL, + asoc->peer.i.initial_tsn, GFP_ATOMIC); +@@ -1234,7 +1235,6 @@ void sctp_assoc_update(struct sctp_association *asoc, + asoc->peer.peer_hmacs = new->peer.peer_hmacs; + new->peer.peer_hmacs = NULL; + +- sctp_auth_key_put(asoc->asoc_shared_key); + sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC); + } + +@@ -1626,6 +1626,8 @@ struct sctp_chunk *sctp_assoc_lookup_asconf_ack( + * ack chunk whose serial number matches that of the request. + */ + list_for_each_entry(ack, &asoc->asconf_ack_list, transmitted_list) { ++ if (sctp_chunk_pending(ack)) ++ continue; + if (ack->subh.addip_hdr->serial == serial) { + sctp_chunk_hold(ack); + return ack; +diff --git a/net/sctp/auth.c b/net/sctp/auth.c +index 0e85291..fb7976a 100644 +--- a/net/sctp/auth.c ++++ b/net/sctp/auth.c +@@ -862,8 +862,6 @@ int sctp_auth_set_key(struct sctp_endpoint *ep, + list_add(&cur_key->key_list, sh_keys); + + cur_key->key = key; +- sctp_auth_key_hold(key); +- + return 0; + nomem: + if (!replace) +diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c +index 4de12af..7e8a16c 100644 +--- a/net/sctp/inqueue.c ++++ b/net/sctp/inqueue.c +@@ -140,18 +140,9 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) + } else { + /* Nothing to do. Next chunk in the packet, please. */ + ch = (sctp_chunkhdr_t *) chunk->chunk_end; +- + /* Force chunk->skb->data to chunk->chunk_end. */ +- skb_pull(chunk->skb, +- chunk->chunk_end - chunk->skb->data); +- +- /* Verify that we have at least chunk headers +- * worth of buffer left. +- */ +- if (skb_headlen(chunk->skb) < sizeof(sctp_chunkhdr_t)) { +- sctp_chunk_free(chunk); +- chunk = queue->in_progress = NULL; +- } ++ skb_pull(chunk->skb, chunk->chunk_end - chunk->skb->data); ++ /* We are guaranteed to pull a SCTP header. */ + } + } + +@@ -187,24 +178,14 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) + skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t)); + chunk->subh.v = NULL; /* Subheader is no longer valid. */ + +- if (chunk->chunk_end < skb_tail_pointer(chunk->skb)) { ++ if (chunk->chunk_end + sizeof(sctp_chunkhdr_t) < ++ skb_tail_pointer(chunk->skb)) { + /* This is not a singleton */ + chunk->singleton = 0; + } else if (chunk->chunk_end > skb_tail_pointer(chunk->skb)) { +- /* RFC 2960, Section 6.10 Bundling +- * +- * Partial chunks MUST NOT be placed in an SCTP packet. +- * If the receiver detects a partial chunk, it MUST drop +- * the chunk. +- * +- * Since the end of the chunk is past the end of our buffer +- * (which contains the whole packet, we can freely discard +- * the whole packet. +- */ +- sctp_chunk_free(chunk); +- chunk = queue->in_progress = NULL; +- +- return NULL; ++ /* Discard inside state machine. */ ++ chunk->pdiscard = 1; ++ chunk->chunk_end = skb_tail_pointer(chunk->skb); + } else { + /* We are at the end of the packet, so mark the chunk + * in case we need to send a SACK. +diff --git a/net/sctp/output.c b/net/sctp/output.c +index 0f4d15f..e39e6d5 100644 +--- a/net/sctp/output.c ++++ b/net/sctp/output.c +@@ -401,12 +401,12 @@ int sctp_packet_transmit(struct sctp_packet *packet) + sk = chunk->skb->sk; + + /* Allocate the new skb. */ +- nskb = alloc_skb(packet->size + LL_MAX_HEADER, GFP_ATOMIC); ++ nskb = alloc_skb(packet->size + MAX_HEADER, GFP_ATOMIC); + if (!nskb) + goto nomem; + + /* Make sure the outbound skb has enough header room reserved. */ +- skb_reserve(nskb, packet->overhead + LL_MAX_HEADER); ++ skb_reserve(nskb, packet->overhead + MAX_HEADER); + + /* Set the owning socket so that we know where to get the + * destination IP address. +@@ -599,7 +599,9 @@ out: + return err; + no_route: + kfree_skb(nskb); +- IP_INC_STATS_BH(sock_net(asoc->base.sk), IPSTATS_MIB_OUTNOROUTES); ++ ++ if (asoc) ++ IP_INC_STATS(sock_net(asoc->base.sk), IPSTATS_MIB_OUTNOROUTES); + + /* FIXME: Returning the 'err' will effect all the associations + * associated with a socket, although only one of the paths of the +diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c +index fee5552..df06b13 100644 +--- a/net/sctp/sm_make_chunk.c ++++ b/net/sctp/sm_make_chunk.c +@@ -2608,7 +2608,10 @@ do_addr_param: + + addr_param = param.v + sizeof(sctp_addip_param_t); + +- af = sctp_get_af_specific(param_type2af(param.p->type)); ++ af = sctp_get_af_specific(param_type2af(addr_param->p.type)); ++ if (af == NULL) ++ break; ++ + af->from_addr_param(&addr, addr_param, + htons(asoc->peer.port), 0); + +@@ -3110,50 +3113,63 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, + return SCTP_ERROR_NO_ERROR; + } + +-/* Verify the ASCONF packet before we process it. */ +-int sctp_verify_asconf(const struct sctp_association *asoc, +- struct sctp_paramhdr *param_hdr, void *chunk_end, +- struct sctp_paramhdr **errp) { +- sctp_addip_param_t *asconf_param; ++/* Verify the ASCONF packet before we process it. */ ++bool sctp_verify_asconf(const struct sctp_association *asoc, ++ struct sctp_chunk *chunk, bool addr_param_needed, ++ struct sctp_paramhdr **errp) ++{ ++ sctp_addip_chunk_t *addip = (sctp_addip_chunk_t *) chunk->chunk_hdr; + union sctp_params param; +- int length, plen; ++ bool addr_param_seen = false; + +- param.v = (sctp_paramhdr_t *) param_hdr; +- while (param.v <= chunk_end - sizeof(sctp_paramhdr_t)) { +- length = ntohs(param.p->length); +- *errp = param.p; +- +- if (param.v > chunk_end - length || +- length < sizeof(sctp_paramhdr_t)) +- return 0; ++ sctp_walk_params(param, addip, addip_hdr.params) { ++ size_t length = ntohs(param.p->length); + ++ *errp = param.p; + switch (param.p->type) { ++ case SCTP_PARAM_ERR_CAUSE: ++ break; ++ case SCTP_PARAM_IPV4_ADDRESS: ++ if (length != sizeof(sctp_ipv4addr_param_t)) ++ return false; ++ addr_param_seen = true; ++ break; ++ case SCTP_PARAM_IPV6_ADDRESS: ++ if (length != sizeof(sctp_ipv6addr_param_t)) ++ return false; ++ addr_param_seen = true; ++ break; + case SCTP_PARAM_ADD_IP: + case SCTP_PARAM_DEL_IP: + case SCTP_PARAM_SET_PRIMARY: +- asconf_param = (sctp_addip_param_t *)param.v; +- plen = ntohs(asconf_param->param_hdr.length); +- if (plen < sizeof(sctp_addip_param_t) + +- sizeof(sctp_paramhdr_t)) +- return 0; ++ /* In ASCONF chunks, these need to be first. */ ++ if (addr_param_needed && !addr_param_seen) ++ return false; ++ length = ntohs(param.addip->param_hdr.length); ++ if (length < sizeof(sctp_addip_param_t) + ++ sizeof(sctp_paramhdr_t)) ++ return false; + break; + case SCTP_PARAM_SUCCESS_REPORT: + case SCTP_PARAM_ADAPTATION_LAYER_IND: + if (length != sizeof(sctp_addip_param_t)) +- return 0; +- ++ return false; + break; + default: +- break; ++ /* This is unkown to us, reject! */ ++ return false; + } +- +- param.v += WORD_ROUND(length); + } + +- if (param.v != chunk_end) +- return 0; ++ /* Remaining sanity checks. */ ++ if (addr_param_needed && !addr_param_seen) ++ return false; ++ if (!addr_param_needed && addr_param_seen) ++ return false; ++ if (param.v != chunk->chunk_end) ++ return false; + +- return 1; ++ return true; + } + + /* Process an incoming ASCONF chunk with the next expected serial no. and +@@ -3162,16 +3178,17 @@ int sctp_verify_asconf(const struct sctp_association *asoc, + struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, + struct sctp_chunk *asconf) + { ++ sctp_addip_chunk_t *addip = (sctp_addip_chunk_t *) asconf->chunk_hdr; ++ bool all_param_pass = true; ++ union sctp_params param; + sctp_addiphdr_t *hdr; + union sctp_addr_param *addr_param; + sctp_addip_param_t *asconf_param; + struct sctp_chunk *asconf_ack; +- + __be16 err_code; + int length = 0; + int chunk_len; + __u32 serial; +- int all_param_pass = 1; + + chunk_len = ntohs(asconf->chunk_hdr->length) - sizeof(sctp_chunkhdr_t); + hdr = (sctp_addiphdr_t *)asconf->skb->data; +@@ -3199,9 +3216,14 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, + goto done; + + /* Process the TLVs contained within the ASCONF chunk. */ +- while (chunk_len > 0) { ++ sctp_walk_params(param, addip, addip_hdr.params) { ++ /* Skip preceeding address parameters. */ ++ if (param.p->type == SCTP_PARAM_IPV4_ADDRESS || ++ param.p->type == SCTP_PARAM_IPV6_ADDRESS) ++ continue; ++ + err_code = sctp_process_asconf_param(asoc, asconf, +- asconf_param); ++ param.addip); + /* ADDIP 4.1 A7) + * If an error response is received for a TLV parameter, + * all TLVs with no response before the failed TLV are +@@ -3209,28 +3231,20 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, + * the failed response are considered unsuccessful unless + * a specific success indication is present for the parameter. + */ +- if (SCTP_ERROR_NO_ERROR != err_code) +- all_param_pass = 0; +- ++ if (err_code != SCTP_ERROR_NO_ERROR) ++ all_param_pass = false; + if (!all_param_pass) +- sctp_add_asconf_response(asconf_ack, +- asconf_param->crr_id, err_code, +- asconf_param); ++ sctp_add_asconf_response(asconf_ack, param.addip->crr_id, ++ err_code, param.addip); + + /* ADDIP 4.3 D11) When an endpoint receiving an ASCONF to add + * an IP address sends an 'Out of Resource' in its response, it + * MUST also fail any subsequent add or delete requests bundled + * in the ASCONF. + */ +- if (SCTP_ERROR_RSRC_LOW == err_code) ++ if (err_code == SCTP_ERROR_RSRC_LOW) + goto done; +- +- /* Move to the next ASCONF param. */ +- length = ntohs(asconf_param->param_hdr.length); +- asconf_param = (void *)asconf_param + length; +- chunk_len -= length; + } +- + done: + asoc->peer.addip_serial++; + +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index 5170a1f..3e287a3 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -170,6 +170,9 @@ sctp_chunk_length_valid(struct sctp_chunk *chunk, + { + __u16 chunk_length = ntohs(chunk->chunk_hdr->length); + ++ /* Previously already marked? */ ++ if (unlikely(chunk->pdiscard)) ++ return 0; + if (unlikely(chunk_length < required_length)) + return 0; + +@@ -1775,9 +1778,22 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(struct net *net, + /* Update the content of current association. */ + sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); + sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); +- sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, +- SCTP_STATE(SCTP_STATE_ESTABLISHED)); +- sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); ++ if (sctp_state(asoc, SHUTDOWN_PENDING) && ++ (sctp_sstate(asoc->base.sk, CLOSING) || ++ sock_flag(asoc->base.sk, SOCK_DEAD))) { ++ /* if were currently in SHUTDOWN_PENDING, but the socket ++ * has been closed by user, don't transition to ESTABLISHED. ++ * Instead trigger SHUTDOWN bundled with COOKIE_ACK. ++ */ ++ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); ++ return sctp_sf_do_9_2_start_shutdown(net, ep, asoc, ++ SCTP_ST_CHUNK(0), NULL, ++ commands); ++ } else { ++ sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, ++ SCTP_STATE(SCTP_STATE_ESTABLISHED)); ++ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); ++ } + return SCTP_DISPOSITION_CONSUME; + + nomem_ev: +@@ -3578,9 +3594,7 @@ sctp_disposition_t sctp_sf_do_asconf(struct net *net, + struct sctp_chunk *asconf_ack = NULL; + struct sctp_paramhdr *err_param = NULL; + sctp_addiphdr_t *hdr; +- union sctp_addr_param *addr_param; + __u32 serial; +- int length; + + if (!sctp_vtag_verify(chunk, asoc)) { + sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, +@@ -3605,17 +3619,8 @@ sctp_disposition_t sctp_sf_do_asconf(struct net *net, + hdr = (sctp_addiphdr_t *)chunk->skb->data; + serial = ntohl(hdr->serial); + +- addr_param = (union sctp_addr_param *)hdr->params; +- length = ntohs(addr_param->p.length); +- if (length < sizeof(sctp_paramhdr_t)) +- return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, +- (void *)addr_param, commands); +- + /* Verify the ASCONF chunk before processing it. */ +- if (!sctp_verify_asconf(asoc, +- (sctp_paramhdr_t *)((void *)addr_param + length), +- (void *)chunk->chunk_end, +- &err_param)) ++ if (!sctp_verify_asconf(asoc, chunk, true, &err_param)) + return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, + (void *)err_param, commands); + +@@ -3732,10 +3737,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(struct net *net, + rcvd_serial = ntohl(addip_hdr->serial); + + /* Verify the ASCONF-ACK chunk before processing it. */ +- if (!sctp_verify_asconf(asoc, +- (sctp_paramhdr_t *)addip_hdr->params, +- (void *)asconf_ack->chunk_end, +- &err_param)) ++ if (!sctp_verify_asconf(asoc, asconf_ack, false, &err_param)) + return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, + (void *)err_param, commands); + +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index 604a6ac..f940fdc 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -1532,8 +1532,10 @@ static void sctp_close(struct sock *sk, long timeout) + + /* Supposedly, no process has access to the socket, but + * the net layers still may. ++ * Also, sctp_destroy_sock() needs to be called with addr_wq_lock ++ * held and that should be grabbed before socket lock. + */ +- local_bh_disable(); ++ spin_lock_bh(&net->sctp.addr_wq_lock); + bh_lock_sock(sk); + + /* Hold the sock, since sk_common_release() will put sock_put() +@@ -1543,7 +1545,7 @@ static void sctp_close(struct sock *sk, long timeout) + sk_common_release(sk); + + bh_unlock_sock(sk); +- local_bh_enable(); ++ spin_unlock_bh(&net->sctp.addr_wq_lock); + + sock_put(sk); + +@@ -3511,6 +3513,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval, + if ((val && sp->do_auto_asconf) || (!val && !sp->do_auto_asconf)) + return 0; + ++ spin_lock_bh(&sock_net(sk)->sctp.addr_wq_lock); + if (val == 0 && sp->do_auto_asconf) { + list_del(&sp->auto_asconf_list); + sp->do_auto_asconf = 0; +@@ -3519,6 +3522,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval, + &sock_net(sk)->sctp.auto_asconf_splist); + sp->do_auto_asconf = 1; + } ++ spin_unlock_bh(&sock_net(sk)->sctp.addr_wq_lock); + return 0; + } + +@@ -4009,18 +4013,28 @@ static int sctp_init_sock(struct sock *sk) + local_bh_disable(); + percpu_counter_inc(&sctp_sockets_allocated); + sock_prot_inuse_add(net, sk->sk_prot, 1); ++ ++ /* Nothing can fail after this block, otherwise ++ * sctp_destroy_sock() will be called without addr_wq_lock held ++ */ + if (net->sctp.default_auto_asconf) { ++ spin_lock(&sock_net(sk)->sctp.addr_wq_lock); + list_add_tail(&sp->auto_asconf_list, + &net->sctp.auto_asconf_splist); + sp->do_auto_asconf = 1; +- } else ++ spin_unlock(&sock_net(sk)->sctp.addr_wq_lock); ++ } else { + sp->do_auto_asconf = 0; ++ } ++ + local_bh_enable(); + + return 0; + } + +-/* Cleanup any SCTP per socket resources. */ ++/* Cleanup any SCTP per socket resources. Must be called with ++ * sock_net(sk)->sctp.addr_wq_lock held if sp->do_auto_asconf is true ++ */ + static void sctp_destroy_sock(struct sock *sk) + { + struct sctp_sock *sp; +@@ -6973,6 +6987,19 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, + newinet->mc_list = NULL; + } + ++static inline void sctp_copy_descendant(struct sock *sk_to, ++ const struct sock *sk_from) ++{ ++ int ancestor_size = sizeof(struct inet_sock) + ++ sizeof(struct sctp_sock) - ++ offsetof(struct sctp_sock, auto_asconf_list); ++ ++ if (sk_from->sk_family == PF_INET6) ++ ancestor_size += sizeof(struct ipv6_pinfo); ++ ++ __inet_sk_copy_descendant(sk_to, sk_from, ancestor_size); ++} ++ + /* Populate the fields of the newsk from the oldsk and migrate the assoc + * and its messages to the newsk. + */ +@@ -6987,7 +7014,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, + struct sk_buff *skb, *tmp; + struct sctp_ulpevent *event; + struct sctp_bind_hashbucket *head; +- struct list_head tmplist; + + /* Migrate socket buffer sizes and all the socket level options to the + * new socket. +@@ -6995,12 +7021,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, + newsk->sk_sndbuf = oldsk->sk_sndbuf; + newsk->sk_rcvbuf = oldsk->sk_rcvbuf; + /* Brute force copy old sctp opt. */ +- if (oldsp->do_auto_asconf) { +- memcpy(&tmplist, &newsp->auto_asconf_list, sizeof(tmplist)); +- inet_sk_copy_descendant(newsk, oldsk); +- memcpy(&newsp->auto_asconf_list, &tmplist, sizeof(tmplist)); +- } else +- inet_sk_copy_descendant(newsk, oldsk); ++ sctp_copy_descendant(newsk, oldsk); + + /* Restore the ep value that was overwritten with the above structure + * copy. +diff --git a/net/socket.c b/net/socket.c +index a19ae19..b72fc13 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -886,9 +886,6 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos, + static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, + struct sock_iocb *siocb) + { +- if (!is_sync_kiocb(iocb)) +- BUG(); +- + siocb->kiocb = iocb; + iocb->private = siocb; + return siocb; +@@ -2010,14 +2007,12 @@ static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, + int err, ctl_len, total_len; + + err = -EFAULT; +- if (MSG_CMSG_COMPAT & flags) { +- if (get_compat_msghdr(msg_sys, msg_compat)) +- return -EFAULT; +- } else { ++ if (MSG_CMSG_COMPAT & flags) ++ err = get_compat_msghdr(msg_sys, msg_compat); ++ else + err = copy_msghdr_from_user(msg_sys, msg); +- if (err) +- return err; +- } ++ if (err) ++ return err; + + if (msg_sys->msg_iovlen > UIO_FASTIOV) { + err = -EMSGSIZE; +@@ -2222,14 +2217,12 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, + struct sockaddr __user *uaddr; + int __user *uaddr_len; + +- if (MSG_CMSG_COMPAT & flags) { +- if (get_compat_msghdr(msg_sys, msg_compat)) +- return -EFAULT; +- } else { ++ if (MSG_CMSG_COMPAT & flags) ++ err = get_compat_msghdr(msg_sys, msg_compat); ++ else + err = copy_msghdr_from_user(msg_sys, msg); +- if (err) +- return err; +- } ++ if (err) ++ return err; + + if (msg_sys->msg_iovlen > UIO_FASTIOV) { + err = -EMSGSIZE; +diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c +index 1ec19f6..eeeba5a 100644 +--- a/net/sunrpc/auth_gss/gss_rpc_xdr.c ++++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c +@@ -793,20 +793,26 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, + { + u32 value_follows; + int err; ++ struct page *scratch; ++ ++ scratch = alloc_page(GFP_KERNEL); ++ if (!scratch) ++ return -ENOMEM; ++ xdr_set_scratch_buffer(xdr, page_address(scratch), PAGE_SIZE); + + /* res->status */ + err = gssx_dec_status(xdr, &res->status); + if (err) +- return err; ++ goto out_free; + + /* res->context_handle */ + err = gssx_dec_bool(xdr, &value_follows); + if (err) +- return err; ++ goto out_free; + if (value_follows) { + err = gssx_dec_ctx(xdr, res->context_handle); + if (err) +- return err; ++ goto out_free; + } else { + res->context_handle = NULL; + } +@@ -814,11 +820,11 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, + /* res->output_token */ + err = gssx_dec_bool(xdr, &value_follows); + if (err) +- return err; ++ goto out_free; + if (value_follows) { + err = gssx_dec_buffer(xdr, res->output_token); + if (err) +- return err; ++ goto out_free; + } else { + res->output_token = NULL; + } +@@ -826,14 +832,17 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, + /* res->delegated_cred_handle */ + err = gssx_dec_bool(xdr, &value_follows); + if (err) +- return err; ++ goto out_free; + if (value_follows) { + /* we do not support upcall servers sending this data. */ +- return -EINVAL; ++ err = -EINVAL; ++ goto out_free; + } + + /* res->options */ + err = gssx_dec_option_array(xdr, &res->options); + ++out_free: ++ __free_page(scratch); + return err; + } +diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c +index e860d4f..ab21968 100644 +--- a/net/sunrpc/backchannel_rqst.c ++++ b/net/sunrpc/backchannel_rqst.c +@@ -60,7 +60,7 @@ static void xprt_free_allocation(struct rpc_rqst *req) + + dprintk("RPC: free allocations for req= %p\n", req); + WARN_ON_ONCE(test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); +- xbufp = &req->rq_private_buf; ++ xbufp = &req->rq_rcv_buf; + free_page((unsigned long)xbufp->head[0].iov_base); + xbufp = &req->rq_snd_buf; + free_page((unsigned long)xbufp->head[0].iov_base); +diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c +index ae333c1..0adc66c 100644 +--- a/net/sunrpc/cache.c ++++ b/net/sunrpc/cache.c +@@ -920,7 +920,7 @@ static unsigned int cache_poll(struct file *filp, poll_table *wait, + poll_wait(filp, &queue_wait, wait); + + /* alway allow write */ +- mask = POLL_OUT | POLLWRNORM; ++ mask = POLLOUT | POLLWRNORM; + + if (!rp) + return mask; +diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c +index 3ea5cda..5ff8b87 100644 +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -533,6 +533,8 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) + + if (args->flags & RPC_CLNT_CREATE_AUTOBIND) + clnt->cl_autobind = 1; ++ if (args->flags & RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT) ++ clnt->cl_noretranstimeo = 1; + if (args->flags & RPC_CLNT_CREATE_DISCRTRY) + clnt->cl_discrtry = 1; + if (!(args->flags & RPC_CLNT_CREATE_QUIET)) +@@ -571,6 +573,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, + /* Turn off autobind on clones */ + new->cl_autobind = 0; + new->cl_softrtry = clnt->cl_softrtry; ++ new->cl_noretranstimeo = clnt->cl_noretranstimeo; + new->cl_discrtry = clnt->cl_discrtry; + new->cl_chatty = clnt->cl_chatty; + return new; +diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c +index d06cb87..5e8fe77 100644 +--- a/net/sunrpc/svcsock.c ++++ b/net/sunrpc/svcsock.c +@@ -685,6 +685,7 @@ static struct svc_xprt_class svc_udp_class = { + .xcl_owner = THIS_MODULE, + .xcl_ops = &svc_udp_ops, + .xcl_max_payload = RPCSVC_MAXPAYLOAD_UDP, ++ .xcl_ident = XPRT_TRANSPORT_UDP, + }; + + static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) +@@ -1279,6 +1280,7 @@ static struct svc_xprt_class svc_tcp_class = { + .xcl_owner = THIS_MODULE, + .xcl_ops = &svc_tcp_ops, + .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, ++ .xcl_ident = XPRT_TRANSPORT_TCP, + }; + + void svc_init_xprt_sock(void) +diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c +index 7d4df99..03ac884 100644 +--- a/net/sunrpc/xprt.c ++++ b/net/sunrpc/xprt.c +@@ -1316,7 +1316,7 @@ struct rpc_xprt *xprt_create_transport(struct xprt_create *args) + } + } + spin_unlock(&xprt_list_lock); +- printk(KERN_ERR "RPC: transport (%d) not supported\n", args->ident); ++ dprintk("RPC: transport (%d) not supported\n", args->ident); + return ERR_PTR(-EIO); + + found: +diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c +index 62e4f9b..ed36cb5 100644 +--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c ++++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c +@@ -89,6 +89,7 @@ struct svc_xprt_class svc_rdma_class = { + .xcl_owner = THIS_MODULE, + .xcl_ops = &svc_rdma_ops, + .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, ++ .xcl_ident = XPRT_TRANSPORT_RDMA, + }; + + struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) +diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c +index 0addefc..41c2f9d 100644 +--- a/net/sunrpc/xprtsock.c ++++ b/net/sunrpc/xprtsock.c +@@ -842,6 +842,8 @@ static void xs_error_report(struct sock *sk) + dprintk("RPC: xs_error_report client %p, error=%d...\n", + xprt, -err); + trace_rpc_socket_error(xprt, sk->sk_socket, err); ++ if (test_bit(XPRT_CONNECTION_REUSE, &xprt->state)) ++ goto out; + xprt_wake_pending_tasks(xprt, err); + out: + read_unlock_bh(&sk->sk_callback_lock); +@@ -2251,7 +2253,9 @@ static void xs_tcp_setup_socket(struct work_struct *work) + abort_and_exit = test_and_clear_bit(XPRT_CONNECTION_ABORT, + &xprt->state); + /* "close" the socket, preserving the local port */ ++ set_bit(XPRT_CONNECTION_REUSE, &xprt->state); + xs_tcp_reuse_connection(transport); ++ clear_bit(XPRT_CONNECTION_REUSE, &xprt->state); + + if (abort_and_exit) + goto out_eagain; +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 94404f1..4757f1c 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1893,6 +1893,10 @@ static long unix_stream_data_wait(struct sock *sk, long timeo, + unix_state_unlock(sk); + timeo = freezable_schedule_timeout(timeo); + unix_state_lock(sk); ++ ++ if (sock_flag(sk, SOCK_DEAD)) ++ break; ++ + clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); + } + +@@ -1957,6 +1961,10 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, + struct sk_buff *skb, *last; + + unix_state_lock(sk); ++ if (sock_flag(sk, SOCK_DEAD)) { ++ err = -ECONNRESET; ++ goto unlock; ++ } + last = skb = skb_peek(&sk->sk_receive_queue); + again: + if (skb == NULL) { +diff --git a/net/wireless/chan.c b/net/wireless/chan.c +index 78559b5..27157a78 100644 +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -516,7 +516,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, + { + struct ieee80211_sta_ht_cap *ht_cap; + struct ieee80211_sta_vht_cap *vht_cap; +- u32 width, control_freq; ++ u32 width, control_freq, cap; + + if (WARN_ON(!cfg80211_chandef_valid(chandef))) + return false; +@@ -554,7 +554,8 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, + return false; + break; + case NL80211_CHAN_WIDTH_80P80: +- if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) ++ cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; ++ if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) + return false; + case NL80211_CHAN_WIDTH_80: + if (!vht_cap->vht_supported) +@@ -565,7 +566,9 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, + case NL80211_CHAN_WIDTH_160: + if (!vht_cap->vht_supported) + return false; +- if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)) ++ cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; ++ if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ && ++ cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) + return false; + prohibited_flags |= IEEE80211_CHAN_NO_160MHZ; + width = 160; +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 4fe2e6e..c260243 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -1450,18 +1450,17 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, + } + CMD(start_p2p_device, START_P2P_DEVICE); + CMD(set_mcast_rate, SET_MCAST_RATE); ++#ifdef CONFIG_NL80211_TESTMODE ++ CMD(testmode_cmd, TESTMODE); ++#endif + if (state->split) { + CMD(crit_proto_start, CRIT_PROTOCOL_START); + CMD(crit_proto_stop, CRIT_PROTOCOL_STOP); + if (dev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH) + CMD(channel_switch, CHANNEL_SWITCH); ++ CMD(set_qos_map, SET_QOS_MAP); + } +- CMD(set_qos_map, SET_QOS_MAP); +- +-#ifdef CONFIG_NL80211_TESTMODE +- CMD(testmode_cmd, TESTMODE); +-#endif +- ++ /* add into the if now */ + #undef CMD + + if (dev->ops->connect || dev->ops->auth) { +@@ -2698,6 +2697,9 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) + if (!rdev->ops->get_key) + return -EOPNOTSUPP; + ++ if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) ++ return -ENOENT; ++ + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; +@@ -2717,10 +2719,6 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr)) + goto nla_put_failure; + +- if (pairwise && mac_addr && +- !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) +- return -ENOENT; +- + err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie, + get_key_callback); + +@@ -2891,7 +2889,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) + wdev_lock(dev->ieee80211_ptr); + err = nl80211_key_allowed(dev->ieee80211_ptr); + +- if (key.type == NL80211_KEYTYPE_PAIRWISE && mac_addr && ++ if (key.type == NL80211_KEYTYPE_GROUP && mac_addr && + !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) + err = -ENOENT; + +@@ -4192,6 +4190,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) + if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) + return -EINVAL; + ++ /* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT ++ * as userspace might just pass through the capabilities from the IEs ++ * directly, rather than enforcing this restriction and returning an ++ * error in this case. ++ */ ++ if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) { ++ params.ht_capa = NULL; ++ params.vht_capa = NULL; ++ } ++ + /* When you run into this, adjust the code below for the new flag */ + BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7); + +@@ -6797,6 +6805,9 @@ void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp) + struct nlattr *data = ((void **)skb->cb)[2]; + enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE; + ++ /* clear CB data for netlink core to own from now on */ ++ memset(skb->cb, 0, sizeof(skb->cb)); ++ + nla_nest_end(skb, data); + genlmsg_end(skb, hdr); + +@@ -9076,6 +9087,9 @@ int cfg80211_vendor_cmd_reply(struct sk_buff *skb) + void *hdr = ((void **)skb->cb)[1]; + struct nlattr *data = ((void **)skb->cb)[2]; + ++ /* clear CB data for netlink core to own from now on */ ++ memset(skb->cb, 0, sizeof(skb->cb)); ++ + if (WARN_ON(!rdev->cur_cmd_info)) { + kfree_skb(skb); + return -EINVAL; +diff --git a/net/wireless/reg.c b/net/wireless/reg.c +index 338794e..04d5305 100644 +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -1547,7 +1547,7 @@ static enum reg_request_treatment + reg_process_hint_driver(struct wiphy *wiphy, + struct regulatory_request *driver_request) + { +- const struct ieee80211_regdomain *regd; ++ const struct ieee80211_regdomain *regd, *tmp; + enum reg_request_treatment treatment; + + treatment = __reg_process_hint_driver(driver_request); +@@ -1566,7 +1566,10 @@ reg_process_hint_driver(struct wiphy *wiphy, + kfree(driver_request); + return REG_REQ_IGNORE; + } ++ ++ tmp = get_wiphy_regdom(wiphy); + rcu_assign_pointer(wiphy->regd, regd); ++ rcu_free_regdom(tmp); + } + + +@@ -1625,11 +1628,8 @@ __reg_process_hint_country_ie(struct wiphy *wiphy, + return REG_REQ_IGNORE; + return REG_REQ_ALREADY_SET; + } +- /* +- * Two consecutive Country IE hints on the same wiphy. +- * This should be picked up early by the driver/stack +- */ +- if (WARN_ON(regdom_changes(country_ie_request->alpha2))) ++ ++ if (regdom_changes(country_ie_request->alpha2)) + return REG_REQ_OK; + return REG_REQ_ALREADY_SET; + } +diff --git a/net/wireless/trace.h b/net/wireless/trace.h +index 5eaeed5..815a3b7 100644 +--- a/net/wireless/trace.h ++++ b/net/wireless/trace.h +@@ -2068,7 +2068,8 @@ TRACE_EVENT(cfg80211_michael_mic_failure, + MAC_ASSIGN(addr, addr); + __entry->key_type = key_type; + __entry->key_id = key_id; +- memcpy(__entry->tsc, tsc, 6); ++ if (tsc) ++ memcpy(__entry->tsc, tsc, 6); + ), + TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT ", key type: %d, key id: %d, tsc: %pm", + NETDEV_PR_ARG, MAC_PR_ARG(addr), __entry->key_type, +diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c +index 5661a54..ae1fe6f 100644 +--- a/net/wireless/wext-compat.c ++++ b/net/wireless/wext-compat.c +@@ -1331,6 +1331,8 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) + memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN); + wdev_unlock(wdev); + ++ memset(&sinfo, 0, sizeof(sinfo)); ++ + if (rdev_get_station(rdev, dev, bssid, &sinfo)) + return NULL; + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index 1d5c7bf..59cf325 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -41,6 +41,11 @@ + + static struct dst_entry *xfrm_policy_sk_bundles; + ++struct xfrm_flo { ++ struct dst_entry *dst_orig; ++ u8 flags; ++}; ++ + static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock); + static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO] + __read_mostly; +@@ -1889,13 +1894,14 @@ static int xdst_queue_output(struct sk_buff *skb) + } + + static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, +- struct dst_entry *dst, ++ struct xfrm_flo *xflo, + const struct flowi *fl, + int num_xfrms, + u16 family) + { + int err; + struct net_device *dev; ++ struct dst_entry *dst; + struct dst_entry *dst1; + struct xfrm_dst *xdst; + +@@ -1903,9 +1909,12 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, + if (IS_ERR(xdst)) + return xdst; + +- if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0) ++ if (!(xflo->flags & XFRM_LOOKUP_QUEUE) || ++ net->xfrm.sysctl_larval_drop || ++ num_xfrms <= 0) + return xdst; + ++ dst = xflo->dst_orig; + dst1 = &xdst->u.dst; + dst_hold(dst); + xdst->route = dst; +@@ -1947,7 +1956,7 @@ static struct flow_cache_object * + xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir, + struct flow_cache_object *oldflo, void *ctx) + { +- struct dst_entry *dst_orig = (struct dst_entry *)ctx; ++ struct xfrm_flo *xflo = (struct xfrm_flo *)ctx; + struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; + struct xfrm_dst *xdst, *new_xdst; + int num_pols = 0, num_xfrms = 0, i, err, pol_dead; +@@ -1988,7 +1997,8 @@ xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir, + goto make_dummy_bundle; + } + +- new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family, dst_orig); ++ new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family, ++ xflo->dst_orig); + if (IS_ERR(new_xdst)) { + err = PTR_ERR(new_xdst); + if (err != -EAGAIN) +@@ -2022,7 +2032,7 @@ make_dummy_bundle: + /* We found policies, but there's no bundles to instantiate: + * either because the policy blocks, has no transformations or + * we could not build template (no xfrm_states).*/ +- xdst = xfrm_create_dummy_bundle(net, dst_orig, fl, num_xfrms, family); ++ xdst = xfrm_create_dummy_bundle(net, xflo, fl, num_xfrms, family); + if (IS_ERR(xdst)) { + xfrm_pols_put(pols, num_pols); + return ERR_CAST(xdst); +@@ -2121,13 +2131,18 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, + } + + if (xdst == NULL) { ++ struct xfrm_flo xflo; ++ ++ xflo.dst_orig = dst_orig; ++ xflo.flags = flags; ++ + /* To accelerate a bit... */ + if ((dst_orig->flags & DST_NOXFRM) || + !net->xfrm.policy_count[XFRM_POLICY_OUT]) + goto nopol; + + flo = flow_cache_lookup(net, fl, family, dir, +- xfrm_bundle_lookup, dst_orig); ++ xfrm_bundle_lookup, &xflo); + if (flo == NULL) + goto nopol; + if (IS_ERR(flo)) { +@@ -2155,7 +2170,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, + xfrm_pols_put(pols, drop_pols); + XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); + +- return make_blackhole(net, family, dst_orig); ++ return ERR_PTR(-EREMOTE); + } + + err = -EAGAIN; +@@ -2212,6 +2227,23 @@ dropdst: + } + EXPORT_SYMBOL(xfrm_lookup); + ++/* Callers of xfrm_lookup_route() must ensure a call to dst_output(). ++ * Otherwise we may send out blackholed packets. ++ */ ++struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig, ++ const struct flowi *fl, ++ struct sock *sk, int flags) ++{ ++ struct dst_entry *dst = xfrm_lookup(net, dst_orig, fl, sk, ++ flags | XFRM_LOOKUP_QUEUE); ++ ++ if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE) ++ return make_blackhole(net, dst_orig->ops->family, dst_orig); ++ ++ return dst; ++} ++EXPORT_SYMBOL(xfrm_lookup_route); ++ + static inline int + xfrm_secpath_reject(int idx, struct sk_buff *skb, const struct flowi *fl) + { +@@ -2477,7 +2509,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) + + skb_dst_force(skb); + +- dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, 0); ++ dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, XFRM_LOOKUP_QUEUE); + if (IS_ERR(dst)) { + res = 0; + dst = NULL; +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index b10d04f..3bea4dd 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -176,9 +176,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, + attrs[XFRMA_ALG_AEAD] || + attrs[XFRMA_ALG_CRYPT] || + attrs[XFRMA_ALG_COMP] || +- attrs[XFRMA_TFCPAD] || +- (ntohl(p->id.spi) >= 0x10000)) +- ++ attrs[XFRMA_TFCPAD]) + goto out; + break; + +@@ -206,7 +204,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, + attrs[XFRMA_ALG_AUTH] || + attrs[XFRMA_ALG_AUTH_TRUNC] || + attrs[XFRMA_ALG_CRYPT] || +- attrs[XFRMA_TFCPAD]) ++ attrs[XFRMA_TFCPAD] || ++ (ntohl(p->id.spi) >= 0x10000)) + goto out; + break; + +diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c +index db1512a..f53542b 100644 +--- a/scripts/kconfig/menu.c ++++ b/scripts/kconfig/menu.c +@@ -545,7 +545,7 @@ static void get_prompt_str(struct gstr *r, struct property *prop, + { + int i, j; + struct menu *submenu[8], *menu, *location = NULL; +- struct jump_key *jump; ++ struct jump_key *jump = NULL; + + str_printf(r, _("Prompt: %s\n"), _(prop->text)); + menu = prop->menu->parent; +@@ -583,7 +583,7 @@ static void get_prompt_str(struct gstr *r, struct property *prop, + str_printf(r, _(" Location:\n")); + for (j = 4; --i >= 0; j += 2) { + menu = submenu[i]; +- if (head && location && menu == location) ++ if (jump && menu == location) + jump->offset = strlen(r->s); + str_printf(r, "%*c-> %s", j, ' ', + _(menu_get_prompt(menu))); +diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl +index 3133172..9969fee 100644 +--- a/scripts/kconfig/streamline_config.pl ++++ b/scripts/kconfig/streamline_config.pl +@@ -137,7 +137,7 @@ my $ksource = ($ARGV[0] ? $ARGV[0] : '.'); + my $kconfig = $ARGV[1]; + my $lsmod_file = $ENV{'LSMOD'}; + +-my @makefiles = `find $ksource -name Makefile 2>/dev/null`; ++my @makefiles = `find $ksource -name Makefile -or -name Kbuild 2>/dev/null`; + chomp @makefiles; + + my %depends; +diff --git a/scripts/kernel-doc b/scripts/kernel-doc +index da058da..2438cc3 100755 +--- a/scripts/kernel-doc ++++ b/scripts/kernel-doc +@@ -1753,7 +1753,7 @@ sub dump_struct($$) { + # strip kmemcheck_bitfield_{begin,end}.*; + $members =~ s/kmemcheck_bitfield_.*?;//gos; + # strip attributes +- $members =~ s/__aligned\s*\(.+\)//gos; ++ $members =~ s/__aligned\s*\([^;]*\)//gos; + + create_parameterlist($members, ';', $file); + check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested); +diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl +index 397b6b8..e28f38e 100755 +--- a/scripts/recordmcount.pl ++++ b/scripts/recordmcount.pl +@@ -262,7 +262,6 @@ if ($arch eq "x86_64") { + # force flags for this arch + $ld .= " -m shlelf_linux"; + $objcopy .= " -O elf32-sh-linux"; +- $cc .= " -m32"; + + } elsif ($arch eq "powerpc") { + $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)"; +diff --git a/security/commoncap.c b/security/commoncap.c +index b9d613e..963dc59 100644 +--- a/security/commoncap.c ++++ b/security/commoncap.c +@@ -421,6 +421,9 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data + cpu_caps->inheritable.cap[i] = le32_to_cpu(caps.data[i].inheritable); + } + ++ cpu_caps->permitted.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; ++ cpu_caps->inheritable.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; ++ + return 0; + } + +diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c +index 3c5cbb9..048550a 100644 +--- a/security/integrity/evm/evm_main.c ++++ b/security/integrity/evm/evm_main.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include "evm.h" + +@@ -269,6 +270,24 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, + goto out; + } + evm_status = evm_verify_current_integrity(dentry); ++ if (evm_status == INTEGRITY_NOXATTRS) { ++ struct integrity_iint_cache *iint; ++ ++ iint = integrity_iint_find(dentry->d_inode); ++ if (iint && (iint->flags & IMA_NEW_FILE)) ++ return 0; ++ ++ /* exception for pseudo filesystems */ ++ if (dentry->d_inode->i_sb->s_magic == TMPFS_MAGIC ++ || dentry->d_inode->i_sb->s_magic == SYSFS_MAGIC) ++ return 0; ++ ++ integrity_audit_msg(AUDIT_INTEGRITY_METADATA, ++ dentry->d_inode, dentry->d_name.name, ++ "update_metadata", ++ integrity_status_msg[evm_status], ++ -EPERM, 0); ++ } + out: + if (evm_status != INTEGRITY_PASS) + integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode, +@@ -296,9 +315,12 @@ int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name, + { + const struct evm_ima_xattr_data *xattr_data = xattr_value; + +- if ((strcmp(xattr_name, XATTR_NAME_EVM) == 0) +- && (xattr_data->type == EVM_XATTR_HMAC)) +- return -EPERM; ++ if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { ++ if (!xattr_value_len) ++ return -EINVAL; ++ if (xattr_data->type != EVM_IMA_XATTR_DIGSIG) ++ return -EPERM; ++ } + return evm_protect_xattr(dentry, xattr_name, xattr_value, + xattr_value_len); + } +diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h +index f79fa8b..5cb7de9 100644 +--- a/security/integrity/ima/ima.h ++++ b/security/integrity/ima/ima.h +@@ -106,7 +106,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename, + const char *op, const char *cause); + int ima_init_crypto(void); + void ima_putc(struct seq_file *m, void *data, int datalen); +-void ima_print_digest(struct seq_file *m, u8 *digest, int size); ++void ima_print_digest(struct seq_file *m, u8 *digest, u32 size); + struct ima_template_desc *ima_template_desc_current(void); + int ima_init_template(void); + +diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c +index 734e946..6df1b25 100644 +--- a/security/integrity/ima/ima_appraise.c ++++ b/security/integrity/ima/ima_appraise.c +@@ -194,8 +194,11 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, + goto out; + + cause = "missing-hash"; +- status = +- (inode->i_size == 0) ? INTEGRITY_PASS : INTEGRITY_NOLABEL; ++ status = INTEGRITY_NOLABEL; ++ if (inode->i_size == 0) { ++ iint->flags |= IMA_NEW_FILE; ++ status = INTEGRITY_PASS; ++ } + goto out; + } + +diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c +index 468a3ba..35f3c90 100644 +--- a/security/integrity/ima/ima_fs.c ++++ b/security/integrity/ima/ima_fs.c +@@ -186,9 +186,9 @@ static const struct file_operations ima_measurements_ops = { + .release = seq_release, + }; + +-void ima_print_digest(struct seq_file *m, u8 *digest, int size) ++void ima_print_digest(struct seq_file *m, u8 *digest, u32 size) + { +- int i; ++ u32 i; + + for (i = 0; i < size; i++) + seq_printf(m, "%02x", *(digest + i)); +diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c +index 76d8aad..9f70efd 100644 +--- a/security/integrity/ima/ima_main.c ++++ b/security/integrity/ima/ima_main.c +@@ -131,11 +131,13 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, + return; + + mutex_lock(&inode->i_mutex); +- if (atomic_read(&inode->i_writecount) == 1 && +- iint->version != inode->i_version) { +- iint->flags &= ~IMA_DONE_MASK; +- if (iint->flags & IMA_APPRAISE) +- ima_update_xattr(iint, file); ++ if (atomic_read(&inode->i_writecount) == 1) { ++ if ((iint->version != inode->i_version) || ++ (iint->flags & IMA_NEW_FILE)) { ++ iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE); ++ if (iint->flags & IMA_APPRAISE) ++ ima_update_xattr(iint, file); ++ } + } + mutex_unlock(&inode->i_mutex); + } +diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c +index 085c496..9d8e420 100644 +--- a/security/integrity/ima/ima_policy.c ++++ b/security/integrity/ima/ima_policy.c +@@ -27,6 +27,8 @@ + #define IMA_UID 0x0008 + #define IMA_FOWNER 0x0010 + #define IMA_FSUUID 0x0020 ++#define IMA_INMASK 0x0040 ++#define IMA_EUID 0x0080 + + #define UNKNOWN 0 + #define MEASURE 0x0001 /* same as IMA_MEASURE */ +@@ -171,6 +173,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule, + return false; + if ((rule->flags & IMA_MASK) && rule->mask != mask) + return false; ++ if ((rule->flags & IMA_INMASK) && ++ (!(rule->mask & mask) && func != POST_SETATTR)) ++ return false; + if ((rule->flags & IMA_FSMAGIC) + && rule->fsmagic != inode->i_sb->s_magic) + return false; +@@ -179,6 +184,16 @@ static bool ima_match_rules(struct ima_rule_entry *rule, + return false; + if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid)) + return false; ++ if (rule->flags & IMA_EUID) { ++ if (has_capability_noaudit(current, CAP_SETUID)) { ++ if (!uid_eq(rule->uid, cred->euid) ++ && !uid_eq(rule->uid, cred->suid) ++ && !uid_eq(rule->uid, cred->uid)) ++ return false; ++ } else if (!uid_eq(rule->uid, cred->euid)) ++ return false; ++ } ++ + if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid)) + return false; + for (i = 0; i < MAX_LSM_RULES; i++) { +@@ -350,7 +365,8 @@ enum { + Opt_audit, + Opt_obj_user, Opt_obj_role, Opt_obj_type, + Opt_subj_user, Opt_subj_role, Opt_subj_type, +- Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner, ++ Opt_func, Opt_mask, Opt_fsmagic, ++ Opt_uid, Opt_euid, Opt_fowner, + Opt_appraise_type, Opt_fsuuid, Opt_permit_directio + }; + +@@ -371,6 +387,7 @@ static match_table_t policy_tokens = { + {Opt_fsmagic, "fsmagic=%s"}, + {Opt_fsuuid, "fsuuid=%s"}, + {Opt_uid, "uid=%s"}, ++ {Opt_euid, "euid=%s"}, + {Opt_fowner, "fowner=%s"}, + {Opt_appraise_type, "appraise_type=%s"}, + {Opt_permit_directio, "permit_directio"}, +@@ -412,6 +429,7 @@ static void ima_log_string(struct audit_buffer *ab, char *key, char *value) + static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) + { + struct audit_buffer *ab; ++ char *from; + char *p; + int result = 0; + +@@ -500,18 +518,23 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) + if (entry->mask) + result = -EINVAL; + +- if ((strcmp(args[0].from, "MAY_EXEC")) == 0) ++ from = args[0].from; ++ if (*from == '^') ++ from++; ++ ++ if ((strcmp(from, "MAY_EXEC")) == 0) + entry->mask = MAY_EXEC; +- else if (strcmp(args[0].from, "MAY_WRITE") == 0) ++ else if (strcmp(from, "MAY_WRITE") == 0) + entry->mask = MAY_WRITE; +- else if (strcmp(args[0].from, "MAY_READ") == 0) ++ else if (strcmp(from, "MAY_READ") == 0) + entry->mask = MAY_READ; +- else if (strcmp(args[0].from, "MAY_APPEND") == 0) ++ else if (strcmp(from, "MAY_APPEND") == 0) + entry->mask = MAY_APPEND; + else + result = -EINVAL; + if (!result) +- entry->flags |= IMA_MASK; ++ entry->flags |= (*args[0].from == '^') ++ ? IMA_INMASK : IMA_MASK; + break; + case Opt_fsmagic: + ima_log_string(ab, "fsmagic", args[0].from); +@@ -542,6 +565,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) + break; + case Opt_uid: + ima_log_string(ab, "uid", args[0].from); ++ case Opt_euid: ++ if (token == Opt_euid) ++ ima_log_string(ab, "euid", args[0].from); + + if (uid_valid(entry->uid)) { + result = -EINVAL; +@@ -550,11 +576,14 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) + + result = strict_strtoul(args[0].from, 10, &lnum); + if (!result) { +- entry->uid = make_kuid(current_user_ns(), (uid_t)lnum); +- if (!uid_valid(entry->uid) || (((uid_t)lnum) != lnum)) ++ entry->uid = make_kuid(current_user_ns(), ++ (uid_t) lnum); ++ if (!uid_valid(entry->uid) || ++ (uid_t)lnum != lnum) + result = -EINVAL; + else +- entry->flags |= IMA_UID; ++ entry->flags |= (token == Opt_uid) ++ ? IMA_UID : IMA_EUID; + } + break; + case Opt_fowner: +diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c +index e8592e7..dcf77b7 100644 +--- a/security/integrity/ima/ima_template_lib.c ++++ b/security/integrity/ima/ima_template_lib.c +@@ -79,7 +79,8 @@ static void ima_show_template_data_ascii(struct seq_file *m, + enum data_formats datafmt, + struct ima_field_data *field_data) + { +- u8 *buf_ptr = field_data->data, buflen = field_data->len; ++ u8 *buf_ptr = field_data->data; ++ u32 buflen = field_data->len; + + switch (datafmt) { + case DATA_FMT_DIGEST_WITH_ALGO: +diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h +index 33c0a70..2f8715d 100644 +--- a/security/integrity/integrity.h ++++ b/security/integrity/integrity.h +@@ -31,6 +31,7 @@ + #define IMA_DIGSIG 0x01000000 + #define IMA_DIGSIG_REQUIRED 0x02000000 + #define IMA_PERMIT_DIRECTIO 0x04000000 ++#define IMA_NEW_FILE 0x08000000 + + #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ + IMA_APPRAISE_SUBMASK) +diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c +index 9e1e005..c4c8df4 100644 +--- a/security/keys/encrypted-keys/encrypted.c ++++ b/security/keys/encrypted-keys/encrypted.c +@@ -1018,10 +1018,13 @@ static int __init init_encrypted(void) + ret = encrypted_shash_alloc(); + if (ret < 0) + return ret; ++ ret = aes_get_sizes(); ++ if (ret < 0) ++ goto out; + ret = register_key_type(&key_type_encrypted); + if (ret < 0) + goto out; +- return aes_get_sizes(); ++ return 0; + out: + encrypted_shash_release(); + return ret; +diff --git a/security/keys/gc.c b/security/keys/gc.c +index d3222b6..009d937 100644 +--- a/security/keys/gc.c ++++ b/security/keys/gc.c +@@ -157,12 +157,12 @@ static noinline void key_gc_unused_keys(struct list_head *keys) + if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) + atomic_dec(&key->user->nikeys); + +- key_user_put(key->user); +- + /* now throw away the key memory */ + if (key->type->destroy) + key->type->destroy(key); + ++ key_user_put(key->user); ++ + kfree(key->description); + + #ifdef KEY_DEBUGGING +diff --git a/security/keys/keyring.c b/security/keys/keyring.c +index 2fb2576..04d0d7c 100644 +--- a/security/keys/keyring.c ++++ b/security/keys/keyring.c +@@ -1151,9 +1151,11 @@ void __key_link_end(struct key *keyring, + if (index_key->type == &key_type_keyring) + up_write(&keyring_serialise_link_sem); + +- if (edit && !edit->dead_leaf) { +- key_payload_reserve(keyring, +- keyring->datalen - KEYQUOTA_LINK_BYTES); ++ if (edit) { ++ if (!edit->dead_leaf) { ++ key_payload_reserve(keyring, ++ keyring->datalen - KEYQUOTA_LINK_BYTES); ++ } + assoc_array_cancel_edit(edit); + } + up_write(&keyring->sem); +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index e294b86..47b5c69 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -470,6 +470,7 @@ next_inode: + list_entry(sbsec->isec_head.next, + struct inode_security_struct, list); + struct inode *inode = isec->inode; ++ list_del_init(&isec->list); + spin_unlock(&sbsec->isec_lock); + inode = igrab(inode); + if (inode) { +@@ -478,7 +479,6 @@ next_inode: + iput(inode); + } + spin_lock(&sbsec->isec_lock); +- list_del_init(&isec->list); + goto next_inode; + } + spin_unlock(&sbsec->isec_lock); +diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c +index d60c0ee..fc68bf6 100644 +--- a/security/selinux/selinuxfs.c ++++ b/security/selinux/selinuxfs.c +@@ -152,7 +152,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, + goto out; + + /* No partial writes. */ +- length = EINVAL; ++ length = -EINVAL; + if (*ppos != 0) + goto out; + +@@ -1200,7 +1200,7 @@ static void sel_remove_entries(struct dentry *de) + spin_lock(&de->d_lock); + node = de->d_subdirs.next; + while (node != &de->d_subdirs) { +- struct dentry *d = list_entry(node, struct dentry, d_u.d_child); ++ struct dentry *d = list_entry(node, struct dentry, d_child); + + spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED); + list_del_init(node); +@@ -1674,12 +1674,12 @@ static void sel_remove_classes(void) + + list_for_each(class_node, &class_dir->d_subdirs) { + struct dentry *class_subdir = list_entry(class_node, +- struct dentry, d_u.d_child); ++ struct dentry, d_child); + struct list_head *class_subdir_node; + + list_for_each(class_subdir_node, &class_subdir->d_subdirs) { + struct dentry *d = list_entry(class_subdir_node, +- struct dentry, d_u.d_child); ++ struct dentry, d_child); + + if (d->d_inode) + if (d->d_inode->i_mode & S_IFDIR) +diff --git a/sound/core/control.c b/sound/core/control.c +index 98a29b2..f2082a3 100644 +--- a/sound/core/control.c ++++ b/sound/core/control.c +@@ -1168,6 +1168,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, + + if (info->count < 1) + return -EINVAL; ++ if (!*info->id.name) ++ return -EINVAL; ++ if (strnlen(info->id.name, sizeof(info->id.name)) >= sizeof(info->id.name)) ++ return -EINVAL; + access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : + (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| + SNDRV_CTL_ELEM_ACCESS_INACTIVE| +diff --git a/sound/core/info.c b/sound/core/info.c +index e79baa1..08070e1 100644 +--- a/sound/core/info.c ++++ b/sound/core/info.c +@@ -679,7 +679,7 @@ int snd_info_card_free(struct snd_card *card) + * snd_info_get_line - read one line from the procfs buffer + * @buffer: the procfs buffer + * @line: the buffer to store +- * @len: the max. buffer size - 1 ++ * @len: the max. buffer size + * + * Reads one line from the buffer and stores the string. + * +@@ -699,7 +699,7 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len) + buffer->stop = 1; + if (c == '\n') + break; +- if (len) { ++ if (len > 1) { + len--; + *line++ = c; + } +diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c +index af49721..c4ac3c1 100644 +--- a/sound/core/pcm_compat.c ++++ b/sound/core/pcm_compat.c +@@ -206,6 +206,8 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, + if (err < 0) + return err; + ++ if (clear_user(src, sizeof(*src))) ++ return -EFAULT; + if (put_user(status.state, &src->state) || + compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) || + compat_put_timespec(&status.tstamp, &src->tstamp) || +diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c +index a210467..e1ef106 100644 +--- a/sound/core/pcm_lib.c ++++ b/sound/core/pcm_lib.c +@@ -1783,14 +1783,16 @@ static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream, + { + struct snd_pcm_hw_params *params = arg; + snd_pcm_format_t format; +- int channels, width; ++ int channels; ++ ssize_t frame_size; + + params->fifo_size = substream->runtime->hw.fifo_size; + if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_FIFO_IN_FRAMES)) { + format = params_format(params); + channels = params_channels(params); +- width = snd_pcm_format_physical_width(format); +- params->fifo_size /= width * channels; ++ frame_size = snd_pcm_format_size(format, channels); ++ if (frame_size > 0) ++ params->fifo_size /= (unsigned)frame_size; + } + return 0; + } +diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c +index 01a5e05..ee24057 100644 +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -1404,6 +1404,8 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state) + if (! snd_pcm_playback_empty(substream)) { + snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING); + snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING); ++ } else { ++ runtime->status->state = SNDRV_PCM_STATE_SETUP; + } + break; + case SNDRV_PCM_STATE_RUNNING: +@@ -3189,7 +3191,7 @@ static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = { + + #ifndef ARCH_HAS_DMA_MMAP_COHERENT + /* This should be defined / handled globally! */ +-#ifdef CONFIG_ARM ++#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) + #define ARCH_HAS_DMA_MMAP_COHERENT + #endif + #endif +diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c +index dbc5507..f60d814 100644 +--- a/sound/core/seq/seq_dummy.c ++++ b/sound/core/seq/seq_dummy.c +@@ -82,36 +82,6 @@ struct snd_seq_dummy_port { + static int my_client = -1; + + /* +- * unuse callback - send ALL_SOUNDS_OFF and RESET_CONTROLLERS events +- * to subscribers. +- * Note: this callback is called only after all subscribers are removed. +- */ +-static int +-dummy_unuse(void *private_data, struct snd_seq_port_subscribe *info) +-{ +- struct snd_seq_dummy_port *p; +- int i; +- struct snd_seq_event ev; +- +- p = private_data; +- memset(&ev, 0, sizeof(ev)); +- if (p->duplex) +- ev.source.port = p->connect; +- else +- ev.source.port = p->port; +- ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; +- ev.type = SNDRV_SEQ_EVENT_CONTROLLER; +- for (i = 0; i < 16; i++) { +- ev.data.control.channel = i; +- ev.data.control.param = MIDI_CTL_ALL_SOUNDS_OFF; +- snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0); +- ev.data.control.param = MIDI_CTL_RESET_CONTROLLERS; +- snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0); +- } +- return 0; +-} +- +-/* + * event input callback - just redirect events to subscribers + */ + static int +@@ -175,7 +145,6 @@ create_port(int idx, int type) + | SNDRV_SEQ_PORT_TYPE_PORT; + memset(&pcb, 0, sizeof(pcb)); + pcb.owner = THIS_MODULE; +- pcb.unuse = dummy_unuse; + pcb.event_input = dummy_input; + pcb.private_free = dummy_free; + pcb.private_data = rec; +diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c +index e04e750..7a9149b 100644 +--- a/sound/i2c/other/ak4113.c ++++ b/sound/i2c/other/ak4113.c +@@ -56,8 +56,7 @@ static inline unsigned char reg_read(struct ak4113 *ak4113, unsigned char reg) + + static void snd_ak4113_free(struct ak4113 *chip) + { +- chip->init = 1; /* don't schedule new work */ +- mb(); ++ atomic_inc(&chip->wq_processing); /* don't schedule new work */ + cancel_delayed_work_sync(&chip->work); + kfree(chip); + } +@@ -89,6 +88,7 @@ int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read, + chip->write = write; + chip->private_data = private_data; + INIT_DELAYED_WORK(&chip->work, ak4113_stats); ++ atomic_set(&chip->wq_processing, 0); + + for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++) + chip->regmap[reg] = pgm[reg]; +@@ -139,13 +139,11 @@ static void ak4113_init_regs(struct ak4113 *chip) + + void snd_ak4113_reinit(struct ak4113 *chip) + { +- chip->init = 1; +- mb(); +- flush_delayed_work(&chip->work); ++ if (atomic_inc_return(&chip->wq_processing) == 1) ++ cancel_delayed_work_sync(&chip->work); + ak4113_init_regs(chip); + /* bring up statistics / event queing */ +- chip->init = 0; +- if (chip->kctls[0]) ++ if (atomic_dec_and_test(&chip->wq_processing)) + schedule_delayed_work(&chip->work, HZ / 10); + } + EXPORT_SYMBOL_GPL(snd_ak4113_reinit); +@@ -632,8 +630,9 @@ static void ak4113_stats(struct work_struct *work) + { + struct ak4113 *chip = container_of(work, struct ak4113, work.work); + +- if (!chip->init) ++ if (atomic_inc_return(&chip->wq_processing) == 1) + snd_ak4113_check_rate_and_errors(chip, chip->check_flags); + +- schedule_delayed_work(&chip->work, HZ / 10); ++ if (atomic_dec_and_test(&chip->wq_processing)) ++ schedule_delayed_work(&chip->work, HZ / 10); + } +diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c +index 15ae025..bf515db 100644 +--- a/sound/i2c/other/ak4114.c ++++ b/sound/i2c/other/ak4114.c +@@ -66,8 +66,7 @@ static void reg_dump(struct ak4114 *ak4114) + + static void snd_ak4114_free(struct ak4114 *chip) + { +- chip->init = 1; /* don't schedule new work */ +- mb(); ++ atomic_inc(&chip->wq_processing); /* don't schedule new work */ + cancel_delayed_work_sync(&chip->work); + kfree(chip); + } +@@ -100,6 +99,7 @@ int snd_ak4114_create(struct snd_card *card, + chip->write = write; + chip->private_data = private_data; + INIT_DELAYED_WORK(&chip->work, ak4114_stats); ++ atomic_set(&chip->wq_processing, 0); + + for (reg = 0; reg < 6; reg++) + chip->regmap[reg] = pgm[reg]; +@@ -152,13 +152,11 @@ static void ak4114_init_regs(struct ak4114 *chip) + + void snd_ak4114_reinit(struct ak4114 *chip) + { +- chip->init = 1; +- mb(); +- flush_delayed_work(&chip->work); ++ if (atomic_inc_return(&chip->wq_processing) == 1) ++ cancel_delayed_work_sync(&chip->work); + ak4114_init_regs(chip); + /* bring up statistics / event queing */ +- chip->init = 0; +- if (chip->kctls[0]) ++ if (atomic_dec_and_test(&chip->wq_processing)) + schedule_delayed_work(&chip->work, HZ / 10); + } + +@@ -612,10 +610,10 @@ static void ak4114_stats(struct work_struct *work) + { + struct ak4114 *chip = container_of(work, struct ak4114, work.work); + +- if (!chip->init) ++ if (atomic_inc_return(&chip->wq_processing) == 1) + snd_ak4114_check_rate_and_errors(chip, chip->check_flags); +- +- schedule_delayed_work(&chip->work, HZ / 10); ++ if (atomic_dec_and_test(&chip->wq_processing)) ++ schedule_delayed_work(&chip->work, HZ / 10); + } + + EXPORT_SYMBOL(snd_ak4114_create); +diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c +index 9b9f7d3..1010ca1 100644 +--- a/sound/oss/sequencer.c ++++ b/sound/oss/sequencer.c +@@ -683,13 +683,8 @@ static int seq_timing_event(unsigned char *event_rec) + break; + + case TMR_ECHO: +- if (seq_mode == SEQ_2) +- seq_copy_to_input(event_rec, 8); +- else +- { +- parm = (parm << 8 | SEQ_ECHO); +- seq_copy_to_input((unsigned char *) &parm, 4); +- } ++ parm = (parm << 8 | SEQ_ECHO); ++ seq_copy_to_input((unsigned char *) &parm, 4); + break; + + default:; +@@ -1330,7 +1325,6 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, void __user *a + int mode = translate_mode(file); + struct synth_info inf; + struct seq_event_rec event_rec; +- unsigned long flags; + int __user *p = arg; + + orig_dev = dev = dev >> 4; +@@ -1485,9 +1479,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, void __user *a + case SNDCTL_SEQ_OUTOFBAND: + if (copy_from_user(&event_rec, arg, sizeof(event_rec))) + return -EFAULT; +- spin_lock_irqsave(&lock,flags); + play_event(event_rec.arr); +- spin_unlock_irqrestore(&lock,flags); + return 0; + + case SNDCTL_MIDI_INFO: +diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig +index 8756c8e..46e5630 100644 +--- a/sound/pci/Kconfig ++++ b/sound/pci/Kconfig +@@ -859,8 +859,8 @@ config SND_VIRTUOSO + select SND_JACK if INPUT=y || INPUT=SND + help + Say Y here to include support for sound cards based on the +- Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS, +- Essence ST (Deluxe), and Essence STX. ++ Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS, DSX, ++ Essence ST (Deluxe), and Essence STX (II). + Support for the HDAV1.3 (Deluxe) and HDAV1.3 Slim is experimental; + for the Xense, missing. + +diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c +index 9e1bd0c..6757458 100644 +--- a/sound/pci/emu10k1/emu10k1.c ++++ b/sound/pci/emu10k1/emu10k1.c +@@ -181,8 +181,10 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, + } + #endif + +- strcpy(card->driver, emu->card_capabilities->driver); +- strcpy(card->shortname, emu->card_capabilities->name); ++ strlcpy(card->driver, emu->card_capabilities->driver, ++ sizeof(card->driver)); ++ strlcpy(card->shortname, emu->card_capabilities->name, ++ sizeof(card->shortname)); + snprintf(card->longname, sizeof(card->longname), + "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i", + card->shortname, emu->revision, emu->serial, emu->port, emu->irq); +diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c +index cae3659..f8a6549 100644 +--- a/sound/pci/emu10k1/emu10k1_callback.c ++++ b/sound/pci/emu10k1/emu10k1_callback.c +@@ -85,6 +85,8 @@ snd_emu10k1_ops_setup(struct snd_emux *emux) + * get more voice for pcm + * + * terminate most inactive voice and give it as a pcm voice. ++ * ++ * voice_lock is already held. + */ + int + snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw) +@@ -92,12 +94,10 @@ snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw) + struct snd_emux *emu; + struct snd_emux_voice *vp; + struct best_voice best[V_END]; +- unsigned long flags; + int i; + + emu = hw->synth; + +- spin_lock_irqsave(&emu->voice_lock, flags); + lookup_voices(emu, hw, best, 1); /* no OFF voices */ + for (i = 0; i < V_END; i++) { + if (best[i].voice >= 0) { +@@ -113,11 +113,9 @@ snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw) + vp->emu->num_voices--; + vp->ch = -1; + vp->state = SNDRV_EMUX_ST_OFF; +- spin_unlock_irqrestore(&emu->voice_lock, flags); + return ch; + } + } +- spin_unlock_irqrestore(&emu->voice_lock, flags); + + /* not found */ + return -ENOMEM; +@@ -417,7 +415,7 @@ start_voice(struct snd_emux_voice *vp) + snd_emu10k1_ptr_write(hw, Z2, ch, 0); + + /* invalidate maps */ +- temp = (hw->silent_page.addr << 1) | MAP_PTI_MASK; ++ temp = (hw->silent_page.addr << hw->address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); + snd_emu10k1_ptr_write(hw, MAPA, ch, temp); + snd_emu10k1_ptr_write(hw, MAPB, ch, temp); + #if 0 +@@ -438,7 +436,7 @@ start_voice(struct snd_emux_voice *vp) + snd_emu10k1_ptr_write(hw, CDF, ch, sample); + + /* invalidate maps */ +- temp = ((unsigned int)hw->silent_page.addr << 1) | MAP_PTI_MASK; ++ temp = ((unsigned int)hw->silent_page.addr << hw_address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); + snd_emu10k1_ptr_write(hw, MAPA, ch, temp); + snd_emu10k1_ptr_write(hw, MAPB, ch, temp); + +diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c +index bdd888e..a131092 100644 +--- a/sound/pci/emu10k1/emu10k1_main.c ++++ b/sound/pci/emu10k1/emu10k1_main.c +@@ -282,7 +282,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) + snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */ + snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */ + +- silent_page = (emu->silent_page.addr << 1) | MAP_PTI_MASK; ++ silent_page = (emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); + for (ch = 0; ch < NUM_G; ch++) { + snd_emu10k1_ptr_write(emu, MAPA, ch, silent_page); + snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page); +@@ -348,6 +348,11 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) + outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); + } + ++ if (emu->address_mode == 0) { ++ /* use 16M in 4G */ ++ outl(inl(emu->port + HCFG) | HCFG_EXPANDED_MEM, emu->port + HCFG); ++ } ++ + return 0; + } + +@@ -1411,7 +1416,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { + * + */ + {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102, +- .driver = "Audigy2", .name = "SB Audigy 2 ZS Notebook [SB0530]", ++ .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]", + .id = "Audigy2", + .emu10k2_chip = 1, + .ca0108_chip = 1, +@@ -1561,7 +1566,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { + .adc_1361t = 1, /* 24 bit capture instead of 16bit */ + .ac97_chip = 1} , + {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, +- .driver = "Audigy2", .name = "SB Audigy 2 Platinum EX [SB0280]", ++ .driver = "Audigy2", .name = "Audigy 2 Platinum EX [SB0280]", + .id = "Audigy2", + .emu10k2_chip = 1, + .ca0102_chip = 1, +@@ -1865,8 +1870,10 @@ int snd_emu10k1_create(struct snd_card *card, + + is_audigy = emu->audigy = c->emu10k2_chip; + ++ /* set addressing mode */ ++ emu->address_mode = is_audigy ? 0 : 1; + /* set the DMA transfer mask */ +- emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK; ++ emu->dma_mask = emu->address_mode ? EMU10K1_DMA_MASK : AUDIGY_DMA_MASK; + if (pci_set_dma_mask(pci, emu->dma_mask) < 0 || + pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) { + snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask); +@@ -1889,7 +1896,7 @@ int snd_emu10k1_create(struct snd_card *card, + + emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT; + if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), +- 32 * 1024, &emu->ptb_pages) < 0) { ++ (emu->address_mode ? 32 : 16) * 1024, &emu->ptb_pages) < 0) { + err = -ENOMEM; + goto error; + } +@@ -1988,8 +1995,8 @@ int snd_emu10k1_create(struct snd_card *card, + + /* Clear silent pages and set up pointers */ + memset(emu->silent_page.area, 0, PAGE_SIZE); +- silent_page = emu->silent_page.addr << 1; +- for (idx = 0; idx < MAXPAGES; idx++) ++ silent_page = emu->silent_page.addr << emu->address_mode; ++ for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++) + ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx); + + /* set up voice indices */ +diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c +index 5ae1d04..7581019 100644 +--- a/sound/pci/emu10k1/emupcm.c ++++ b/sound/pci/emu10k1/emupcm.c +@@ -379,7 +379,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, + snd_emu10k1_ptr_write(emu, Z1, voice, 0); + snd_emu10k1_ptr_write(emu, Z2, voice, 0); + /* invalidate maps */ +- silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK; ++ silent_page = ((unsigned int)emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0); + snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page); + snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page); + /* modulation envelope */ +diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c +index 2ca9f2e..53745f4 100644 +--- a/sound/pci/emu10k1/emuproc.c ++++ b/sound/pci/emu10k1/emuproc.c +@@ -241,31 +241,22 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry, + struct snd_emu10k1 *emu = entry->private_data; + u32 value; + u32 value2; +- unsigned long flags; + u32 rate; + + if (emu->card_capabilities->emu_model) { +- spin_lock_irqsave(&emu->emu_lock, flags); + snd_emu1010_fpga_read(emu, 0x38, &value); +- spin_unlock_irqrestore(&emu->emu_lock, flags); + if ((value & 0x1) == 0) { +- spin_lock_irqsave(&emu->emu_lock, flags); + snd_emu1010_fpga_read(emu, 0x2a, &value); + snd_emu1010_fpga_read(emu, 0x2b, &value2); +- spin_unlock_irqrestore(&emu->emu_lock, flags); + rate = 0x1770000 / (((value << 5) | value2)+1); + snd_iprintf(buffer, "ADAT Locked : %u\n", rate); + } else { + snd_iprintf(buffer, "ADAT Unlocked\n"); + } +- spin_lock_irqsave(&emu->emu_lock, flags); + snd_emu1010_fpga_read(emu, 0x20, &value); +- spin_unlock_irqrestore(&emu->emu_lock, flags); + if ((value & 0x4) == 0) { +- spin_lock_irqsave(&emu->emu_lock, flags); + snd_emu1010_fpga_read(emu, 0x28, &value); + snd_emu1010_fpga_read(emu, 0x29, &value2); +- spin_unlock_irqrestore(&emu->emu_lock, flags); + rate = 0x1770000 / (((value << 5) | value2)+1); + snd_iprintf(buffer, "SPDIF Locked : %d\n", rate); + } else { +@@ -410,14 +401,11 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry, + { + struct snd_emu10k1 *emu = entry->private_data; + u32 value; +- unsigned long flags; + int i; + snd_iprintf(buffer, "EMU1010 Registers:\n\n"); + + for(i = 0; i < 0x40; i+=1) { +- spin_lock_irqsave(&emu->emu_lock, flags); + snd_emu1010_fpga_read(emu, i, &value); +- spin_unlock_irqrestore(&emu->emu_lock, flags); + snd_iprintf(buffer, "%02X: %08X, %02X\n", i, value, (value >> 8) & 0x7f); + } + } +diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c +index ae709c1..d514458 100644 +--- a/sound/pci/emu10k1/memory.c ++++ b/sound/pci/emu10k1/memory.c +@@ -34,10 +34,11 @@ + * aligned pages in others + */ + #define __set_ptb_entry(emu,page,addr) \ +- (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << 1) | (page))) ++ (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << (emu->address_mode)) | (page))) + + #define UNIT_PAGES (PAGE_SIZE / EMUPAGESIZE) +-#define MAX_ALIGN_PAGES (MAXPAGES / UNIT_PAGES) ++#define MAX_ALIGN_PAGES0 (MAXPAGES0 / UNIT_PAGES) ++#define MAX_ALIGN_PAGES1 (MAXPAGES1 / UNIT_PAGES) + /* get aligned page from offset address */ + #define get_aligned_page(offset) ((offset) >> PAGE_SHIFT) + /* get offset address from aligned page */ +@@ -124,7 +125,7 @@ static int search_empty_map_area(struct snd_emu10k1 *emu, int npages, struct lis + } + page = blk->mapped_page + blk->pages; + } +- size = MAX_ALIGN_PAGES - page; ++ size = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0) - page; + if (size >= max_size) { + *nextp = pos; + return page; +@@ -181,7 +182,7 @@ static int unmap_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) + q = get_emu10k1_memblk(p, mapped_link); + end_page = q->mapped_page; + } else +- end_page = MAX_ALIGN_PAGES; ++ end_page = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0); + + /* remove links */ + list_del(&blk->mapped_link); +@@ -305,7 +306,7 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst + if (snd_BUG_ON(!emu)) + return NULL; + if (snd_BUG_ON(runtime->dma_bytes <= 0 || +- runtime->dma_bytes >= MAXPAGES * EMUPAGESIZE)) ++ runtime->dma_bytes >= (emu->address_mode ? MAXPAGES1 : MAXPAGES0) * EMUPAGESIZE)) + return NULL; + hdr = emu->memhdr; + if (snd_BUG_ON(!hdr)) +diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c +index dafcf82..97ebc10 100644 +--- a/sound/pci/hda/hda_codec.c ++++ b/sound/pci/hda/hda_codec.c +@@ -338,8 +338,10 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, + unsigned int parm; + + parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT); +- if (parm == -1) ++ if (parm == -1) { ++ *start_id = 0; + return 0; ++ } + *start_id = (parm >> 16) & 0x7fff; + return (int)(parm & 0x7fff); + } +@@ -2080,6 +2082,16 @@ static void put_vol_mute(struct hda_codec *codec, unsigned int amp_caps, + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm); + } + ++/* meta hook to call each driver's vmaster hook */ ++static void vmaster_hook(void *private_data, int enabled) ++{ ++ struct hda_vmaster_mute_hook *hook = private_data; ++ ++ if (hook->mute_mode != HDA_VMUTE_FOLLOW_MASTER) ++ enabled = hook->mute_mode; ++ hook->hook(hook->codec, enabled); ++} ++ + /** + * snd_hda_codec_amp_read - Read AMP value + * @codec: HD-audio codec +@@ -2915,9 +2927,9 @@ int snd_hda_add_vmaster_hook(struct hda_codec *codec, + + if (!hook->hook || !hook->sw_kctl) + return 0; +- snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec); + hook->codec = codec; + hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER; ++ snd_ctl_add_vmaster_hook(hook->sw_kctl, vmaster_hook, hook); + if (!expose_enum_ctl) + return 0; + kctl = snd_ctl_new1(&vmaster_mute_mode, hook); +@@ -2940,14 +2952,7 @@ void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook) + */ + if (hook->codec->bus->shutdown) + return; +- switch (hook->mute_mode) { +- case HDA_VMUTE_FOLLOW_MASTER: +- snd_ctl_sync_vmaster_hook(hook->sw_kctl); +- break; +- default: +- hook->hook(hook->codec, hook->mute_mode); +- break; +- } ++ snd_ctl_sync_vmaster_hook(hook->sw_kctl); + } + EXPORT_SYMBOL_GPL(snd_hda_sync_vmaster_hook); + +diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c +index d9a09bd..9a23bde 100644 +--- a/sound/pci/hda/hda_generic.c ++++ b/sound/pci/hda/hda_generic.c +@@ -653,12 +653,45 @@ static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid, + return val; + } + ++/* is this a stereo widget or a stereo-to-mono mix? */ ++static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, int dir) ++{ ++ unsigned int wcaps = get_wcaps(codec, nid); ++ hda_nid_t conn; ++ ++ if (wcaps & AC_WCAP_STEREO) ++ return true; ++ if (dir != HDA_INPUT || get_wcaps_type(wcaps) != AC_WID_AUD_MIX) ++ return false; ++ if (snd_hda_get_num_conns(codec, nid) != 1) ++ return false; ++ if (snd_hda_get_connections(codec, nid, &conn, 1) < 0) ++ return false; ++ return !!(get_wcaps(codec, conn) & AC_WCAP_STEREO); ++} ++ + /* initialize the amp value (only at the first time) */ + static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx) + { + unsigned int caps = query_amp_caps(codec, nid, dir); + int val = get_amp_val_to_activate(codec, nid, dir, caps, false); +- snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val); ++ ++ if (is_stereo_amps(codec, nid, dir)) ++ snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val); ++ else ++ snd_hda_codec_amp_init(codec, nid, 0, dir, idx, 0xff, val); ++} ++ ++/* update the amp, doing in stereo or mono depending on NID */ ++static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx, ++ unsigned int mask, unsigned int val) ++{ ++ if (is_stereo_amps(codec, nid, dir)) ++ return snd_hda_codec_amp_stereo(codec, nid, dir, idx, ++ mask, val); ++ else ++ return snd_hda_codec_amp_update(codec, nid, 0, dir, idx, ++ mask, val); + } + + /* calculate amp value mask we can modify; +@@ -698,7 +731,7 @@ static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir, + return; + + val &= mask; +- snd_hda_codec_amp_stereo(codec, nid, dir, idx, mask, val); ++ update_amp(codec, nid, dir, idx, mask, val); + } + + static void activate_amp_out(struct hda_codec *codec, struct nid_path *path, +@@ -4337,13 +4370,11 @@ static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix) + has_amp = nid_has_mute(codec, mix, HDA_INPUT); + for (i = 0; i < nums; i++) { + if (has_amp) +- snd_hda_codec_amp_stereo(codec, mix, +- HDA_INPUT, i, +- 0xff, HDA_AMP_MUTE); ++ update_amp(codec, mix, HDA_INPUT, i, ++ 0xff, HDA_AMP_MUTE); + else if (nid_has_volume(codec, conn[i], HDA_OUTPUT)) +- snd_hda_codec_amp_stereo(codec, conn[i], +- HDA_OUTPUT, 0, +- 0xff, HDA_AMP_MUTE); ++ update_amp(codec, conn[i], HDA_OUTPUT, 0, ++ 0xff, HDA_AMP_MUTE); + } + } + +diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c +index 7ec9142..84e8879 100644 +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -959,7 +959,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, + } + } + +- if (!bus->no_response_fallback) ++ if (bus->no_response_fallback) + return -1; + + if (!chip->polling_mode && chip->poll_count < 2) { +@@ -3984,7 +3984,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, + /* Panther Point */ + { PCI_DEVICE(0x8086, 0x1e20), +- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, ++ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, + /* Lynx Point */ + { PCI_DEVICE(0x8086, 0x8c20), + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, +@@ -4027,6 +4027,9 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { + /* BayTrail */ + { PCI_DEVICE(0x8086, 0x0f04), + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, ++ /* Braswell */ ++ { PCI_DEVICE(0x8086, 0x2284), ++ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, + /* ICH */ + { PCI_DEVICE(0x8086, 0x2668), + .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | +diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c +index ce5a6da..05e19f7 100644 +--- a/sound/pci/hda/hda_proc.c ++++ b/sound/pci/hda/hda_proc.c +@@ -134,13 +134,38 @@ static void print_amp_caps(struct snd_info_buffer *buffer, + (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT); + } + ++/* is this a stereo widget or a stereo-to-mono mix? */ ++static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, ++ int dir, unsigned int wcaps, int indices) ++{ ++ hda_nid_t conn; ++ ++ if (wcaps & AC_WCAP_STEREO) ++ return true; ++ /* check for a stereo-to-mono mix; it must be: ++ * only a single connection, only for input, and only a mixer widget ++ */ ++ if (indices != 1 || dir != HDA_INPUT || ++ get_wcaps_type(wcaps) != AC_WID_AUD_MIX) ++ return false; ++ ++ if (snd_hda_get_raw_connections(codec, nid, &conn, 1) < 0) ++ return false; ++ /* the connection source is a stereo? */ ++ wcaps = snd_hda_param_read(codec, conn, AC_PAR_AUDIO_WIDGET_CAP); ++ return !!(wcaps & AC_WCAP_STEREO); ++} ++ + static void print_amp_vals(struct snd_info_buffer *buffer, + struct hda_codec *codec, hda_nid_t nid, +- int dir, int stereo, int indices) ++ int dir, unsigned int wcaps, int indices) + { + unsigned int val; ++ bool stereo; + int i; + ++ stereo = is_stereo_amps(codec, nid, dir, wcaps, indices); ++ + dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT; + for (i = 0; i < indices; i++) { + snd_iprintf(buffer, " ["); +@@ -757,12 +782,10 @@ static void print_codec_info(struct snd_info_entry *entry, + (codec->single_adc_amp && + wid_type == AC_WID_AUD_IN)) + print_amp_vals(buffer, codec, nid, HDA_INPUT, +- wid_caps & AC_WCAP_STEREO, +- 1); ++ wid_caps, 1); + else + print_amp_vals(buffer, codec, nid, HDA_INPUT, +- wid_caps & AC_WCAP_STEREO, +- conn_len); ++ wid_caps, conn_len); + } + if (wid_caps & AC_WCAP_OUT_AMP) { + snd_iprintf(buffer, " Amp-Out caps: "); +@@ -771,11 +794,10 @@ static void print_codec_info(struct snd_info_entry *entry, + if (wid_type == AC_WID_PIN && + codec->pin_amp_workaround) + print_amp_vals(buffer, codec, nid, HDA_OUTPUT, +- wid_caps & AC_WCAP_STEREO, +- conn_len); ++ wid_caps, conn_len); + else + print_amp_vals(buffer, codec, nid, HDA_OUTPUT, +- wid_caps & AC_WCAP_STEREO, 1); ++ wid_caps, 1); + } + + switch (wid_type) { +diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c +index eaf64ea..1a05efa 100644 +--- a/sound/pci/hda/patch_analog.c ++++ b/sound/pci/hda/patch_analog.c +@@ -333,6 +333,7 @@ static const struct hda_fixup ad1986a_fixups[] = { + + static const struct snd_pci_quirk ad1986a_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_FIXUP_LAPTOP_IMIC), ++ SND_PCI_QUIRK(0x1043, 0x1443, "ASUS Z99He", AD1986A_FIXUP_EAPD), + SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8JN", AD1986A_FIXUP_EAPD), + SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8100, "ASUS P5", AD1986A_FIXUP_3STACK), + SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8200, "ASUS M2", AD1986A_FIXUP_3STACK), +diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c +index 46ecdbb..d5843da 100644 +--- a/sound/pci/hda/patch_ca0132.c ++++ b/sound/pci/hda/patch_ca0132.c +@@ -4379,6 +4379,9 @@ static void ca0132_download_dsp(struct hda_codec *codec) + return; /* NOP */ + #endif + ++ if (spec->dsp_state == DSP_DOWNLOAD_FAILED) ++ return; /* don't retry failures */ ++ + chipio_enable_clocks(codec); + spec->dsp_state = DSP_DOWNLOADING; + if (!ca0132_download_dsp_images(codec)) +@@ -4555,7 +4558,8 @@ static int ca0132_init(struct hda_codec *codec) + struct auto_pin_cfg *cfg = &spec->autocfg; + int i; + +- spec->dsp_state = DSP_DOWNLOAD_INIT; ++ if (spec->dsp_state != DSP_DOWNLOAD_FAILED) ++ spec->dsp_state = DSP_DOWNLOAD_INIT; + spec->curr_chip_addx = INVALID_CHIP_ADDRESS; + + snd_hda_power_up(codec); +@@ -4666,6 +4670,7 @@ static int patch_ca0132(struct hda_codec *codec) + codec->spec = spec; + spec->codec = codec; + ++ spec->dsp_state = DSP_DOWNLOAD_INIT; + spec->num_mixers = 1; + spec->mixers[0] = ca0132_mixer; + +diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c +index fc492ac..7b0aac9 100644 +--- a/sound/pci/hda/patch_cirrus.c ++++ b/sound/pci/hda/patch_cirrus.c +@@ -396,6 +396,7 @@ static const struct snd_pci_quirk cs420x_fixup_tbl[] = { + SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81), + SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122), + SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101), ++ SND_PCI_QUIRK(0x106b, 0x5600, "MacBookAir 5,2", CS420X_MBP81), + SND_PCI_QUIRK(0x106b, 0x5b00, "MacBookAir 4,2", CS420X_MBA42), + SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE), + {} /* terminator */ +@@ -587,6 +588,7 @@ static int patch_cs420x(struct hda_codec *codec) + return -ENOMEM; + + spec->gen.automute_hook = cs_automute; ++ codec->single_adc_amp = 1; + + snd_hda_pick_fixup(codec, cs420x_models, cs420x_fixup_tbl, + cs420x_fixups); +@@ -1000,9 +1002,7 @@ static void cs4210_spdif_automute(struct hda_codec *codec, + + spec->spdif_present = spdif_present; + /* SPDIF TX on/off */ +- if (spdif_present) +- snd_hda_set_pin_ctl(codec, spdif_pin, +- spdif_present ? PIN_OUT : 0); ++ snd_hda_set_pin_ctl(codec, spdif_pin, spdif_present ? PIN_OUT : 0); + + cs_automute(codec); + } +diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c +index bcf91be..50981b1 100644 +--- a/sound/pci/hda/patch_conexant.c ++++ b/sound/pci/hda/patch_conexant.c +@@ -3232,11 +3232,13 @@ enum { + CXT_PINCFG_LENOVO_TP410, + CXT_PINCFG_LEMOTE_A1004, + CXT_PINCFG_LEMOTE_A1205, ++ CXT_PINCFG_COMPAQ_CQ60, + CXT_FIXUP_STEREO_DMIC, + CXT_FIXUP_INC_MIC_BOOST, + CXT_FIXUP_HEADPHONE_MIC_PIN, + CXT_FIXUP_HEADPHONE_MIC, + CXT_FIXUP_GPIO1, ++ CXT_FIXUP_ASPIRE_DMIC, + CXT_FIXUP_THINKPAD_ACPI, + }; + +@@ -3367,6 +3369,15 @@ static const struct hda_fixup cxt_fixups[] = { + .type = HDA_FIXUP_PINS, + .v.pins = cxt_pincfg_lemote, + }, ++ [CXT_PINCFG_COMPAQ_CQ60] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ /* 0x17 was falsely set up as a mic, it should 0x1d */ ++ { 0x17, 0x400001f0 }, ++ { 0x1d, 0x97a70120 }, ++ { } ++ } ++ }, + [CXT_FIXUP_STEREO_DMIC] = { + .type = HDA_FIXUP_FUNC, + .v.func = cxt_fixup_stereo_dmic, +@@ -3397,6 +3408,12 @@ static const struct hda_fixup cxt_fixups[] = { + { } + }, + }, ++ [CXT_FIXUP_ASPIRE_DMIC] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = cxt_fixup_stereo_dmic, ++ .chained = true, ++ .chain_id = CXT_FIXUP_GPIO1, ++ }, + [CXT_FIXUP_THINKPAD_ACPI] = { + .type = HDA_FIXUP_FUNC, + .v.func = hda_fixup_thinkpad_acpi, +@@ -3404,13 +3421,14 @@ static const struct hda_fixup cxt_fixups[] = { + }; + + static const struct snd_pci_quirk cxt5051_fixups[] = { ++ SND_PCI_QUIRK(0x103c, 0x360b, "Compaq CQ60", CXT_PINCFG_COMPAQ_CQ60), + SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200), + {} + }; + + static const struct snd_pci_quirk cxt5066_fixups[] = { + SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC), +- SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_GPIO1), ++ SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC), + SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN), + SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410), + SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410), +@@ -3573,6 +3591,14 @@ static const struct hda_codec_preset snd_hda_preset_conexant[] = { + .patch = patch_conexant_auto }, + { .id = 0x14f150b9, .name = "CX20665", + .patch = patch_conexant_auto }, ++ { .id = 0x14f150f1, .name = "CX20721", ++ .patch = patch_conexant_auto }, ++ { .id = 0x14f150f2, .name = "CX20722", ++ .patch = patch_conexant_auto }, ++ { .id = 0x14f150f3, .name = "CX20723", ++ .patch = patch_conexant_auto }, ++ { .id = 0x14f150f4, .name = "CX20724", ++ .patch = patch_conexant_auto }, + { .id = 0x14f1510f, .name = "CX20751/2", + .patch = patch_conexant_auto }, + { .id = 0x14f15110, .name = "CX20751/2", +@@ -3607,6 +3633,10 @@ MODULE_ALIAS("snd-hda-codec-id:14f150ab"); + MODULE_ALIAS("snd-hda-codec-id:14f150ac"); + MODULE_ALIAS("snd-hda-codec-id:14f150b8"); + MODULE_ALIAS("snd-hda-codec-id:14f150b9"); ++MODULE_ALIAS("snd-hda-codec-id:14f150f1"); ++MODULE_ALIAS("snd-hda-codec-id:14f150f2"); ++MODULE_ALIAS("snd-hda-codec-id:14f150f3"); ++MODULE_ALIAS("snd-hda-codec-id:14f150f4"); + MODULE_ALIAS("snd-hda-codec-id:14f1510f"); + MODULE_ALIAS("snd-hda-codec-id:14f15110"); + MODULE_ALIAS("snd-hda-codec-id:14f15111"); +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index d135c90..611110a 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -1557,19 +1557,22 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) + } + } + +- if (pin_eld->eld_valid && !eld->eld_valid) { +- update_eld = true; ++ if (pin_eld->eld_valid != eld->eld_valid) + eld_changed = true; +- } ++ ++ if (pin_eld->eld_valid && !eld->eld_valid) ++ update_eld = true; ++ + if (update_eld) { + bool old_eld_valid = pin_eld->eld_valid; + pin_eld->eld_valid = eld->eld_valid; +- eld_changed = pin_eld->eld_size != eld->eld_size || ++ if (pin_eld->eld_size != eld->eld_size || + memcmp(pin_eld->eld_buffer, eld->eld_buffer, +- eld->eld_size) != 0; +- if (eld_changed) ++ eld->eld_size) != 0) { + memcpy(pin_eld->eld_buffer, eld->eld_buffer, + eld->eld_size); ++ eld_changed = true; ++ } + pin_eld->eld_size = eld->eld_size; + pin_eld->info = eld->info; + +@@ -3314,6 +3317,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { + { .id = 0x80862808, .name = "Broadwell HDMI", .patch = patch_generic_hdmi }, + { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, + { .id = 0x80862882, .name = "Valleyview2 HDMI", .patch = patch_generic_hdmi }, ++{ .id = 0x80862883, .name = "Braswell HDMI", .patch = patch_generic_hdmi }, + { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, + {} /* terminator */ + }; +@@ -3370,6 +3374,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862807"); + MODULE_ALIAS("snd-hda-codec-id:80862808"); + MODULE_ALIAS("snd-hda-codec-id:80862880"); + MODULE_ALIAS("snd-hda-codec-id:80862882"); ++MODULE_ALIAS("snd-hda-codec-id:80862883"); + MODULE_ALIAS("snd-hda-codec-id:808629fb"); + + MODULE_LICENSE("GPL"); +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 2a16a90..907371d 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -180,6 +180,8 @@ static void alc_fix_pll(struct hda_codec *codec) + spec->pll_coef_idx); + val = snd_hda_codec_read(codec, spec->pll_nid, 0, + AC_VERB_GET_PROC_COEF, 0); ++ if (val == -1) ++ return; + snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX, + spec->pll_coef_idx); + snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF, +@@ -269,7 +271,7 @@ static void alc_auto_setup_eapd(struct hda_codec *codec, bool on) + { + /* We currently only handle front, HP */ + static hda_nid_t pins[] = { +- 0x0f, 0x10, 0x14, 0x15, 0 ++ 0x0f, 0x10, 0x14, 0x15, 0x17, 0 + }; + hda_nid_t *p; + for (p = pins; *p; p++) +@@ -325,6 +327,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) + case 0x10ec0885: + case 0x10ec0887: + /*case 0x10ec0889:*/ /* this causes an SPDIF problem */ ++ case 0x10ec0900: + alc889_coef_init(codec); + break; + case 0x10ec0888: +@@ -2223,6 +2226,7 @@ static const struct hda_fixup alc882_fixups[] = { + static const struct snd_pci_quirk alc882_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD), + SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD), ++ SND_PCI_QUIRK(0x1025, 0x0107, "Acer Aspire", ALC883_FIXUP_ACER_EAPD), + SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_FIXUP_ACER_EAPD), + SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_FIXUP_ACER_EAPD), + SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_FIXUP_ACER_EAPD), +@@ -2278,7 +2282,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { + SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF), + SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF), + SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF), +- SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF), ++ SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF), + + SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), + SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD), +@@ -2328,6 +2332,7 @@ static int patch_alc882(struct hda_codec *codec) + switch (codec->vendor_id) { + case 0x10ec0882: + case 0x10ec0885: ++ case 0x10ec0900: + break; + default: + /* ALC883 and variants */ +@@ -2765,6 +2770,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec) + static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up) + { + int val = alc_read_coef_idx(codec, 0x04); ++ if (val == -1) ++ return; + if (power_up) + val |= 1 << 11; + else +@@ -2879,6 +2886,8 @@ static void alc283_init(struct hda_codec *codec) + + if (!hp_pin) + return; ++ ++ msleep(30); + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + + /* Index 0x43 Direct Drive HP AMP LPM Control 1 */ +@@ -2920,6 +2929,9 @@ static void alc283_shutup(struct hda_codec *codec) + + alc_write_coef_idx(codec, 0x43, 0x9004); + ++ /*depop hp during suspend*/ ++ alc_write_coef_idx(codec, 0x06, 0x2100); ++ + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + +@@ -3064,6 +3076,15 @@ static int alc269_resume(struct hda_codec *codec) + snd_hda_codec_resume_cache(codec); + alc_inv_dmic_sync(codec, true); + hda_call_check_power_status(codec, 0x01); ++ ++ /* on some machine, the BIOS will clear the codec gpio data when enter ++ * suspend, and won't restore the data after resume, so we restore it ++ * in the driver. ++ */ ++ if (spec->gpio_led) ++ snd_hda_codec_write(codec, codec->afg, 0, AC_VERB_SET_GPIO_DATA, ++ spec->gpio_led); ++ + if (spec->has_alc5505_dsp) + alc5505_dsp_resume(codec); + +@@ -3933,6 +3954,8 @@ enum { + ALC269_FIXUP_QUANTA_MUTE, + ALC269_FIXUP_LIFEBOOK, + ALC269_FIXUP_LIFEBOOK_EXTMIC, ++ ALC269_FIXUP_LIFEBOOK_HP_PIN, ++ ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT, + ALC269_FIXUP_AMIC, + ALC269_FIXUP_DMIC, + ALC269VB_FIXUP_AMIC, +@@ -3951,6 +3974,7 @@ enum { + ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, + ALC269_FIXUP_HEADSET_MODE, + ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, ++ ALC269_FIXUP_ASPIRE_HEADSET_MIC, + ALC269_FIXUP_ASUS_X101_FUNC, + ALC269_FIXUP_ASUS_X101_VERB, + ALC269_FIXUP_ASUS_X101, +@@ -4067,6 +4091,17 @@ static const struct hda_fixup alc269_fixups[] = { + { } + }, + }, ++ [ALC269_FIXUP_LIFEBOOK_HP_PIN] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x21, 0x0221102f }, /* HP out */ ++ { } ++ }, ++ }, ++ [ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc269_fixup_pincfg_no_hp_to_lineout, ++ }, + [ALC269_FIXUP_AMIC] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { +@@ -4185,6 +4220,15 @@ static const struct hda_fixup alc269_fixups[] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_headset_mode_no_hp_mic, + }, ++ [ALC269_FIXUP_ASPIRE_HEADSET_MIC] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x19, 0x01a1913c }, /* headset mic w/o jack detect */ ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC269_FIXUP_HEADSET_MODE, ++ }, + [ALC286_FIXUP_SONY_MIC_NO_PRESENCE] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { +@@ -4368,6 +4412,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC), + SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), + SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700), ++ SND_PCI_QUIRK(0x1025, 0x072d, "Acer Aspire V5-571G", ALC269_FIXUP_ASPIRE_HEADSET_MIC), ++ SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC), + SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK), + SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK), + SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC), +@@ -4435,6 +4481,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), + SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED), + /* ALC282 */ ++ SND_PCI_QUIRK(0x103c, 0x2191, "HP Touchsmart 14", ALC269_FIXUP_HP_MUTE_LED_MIC1), ++ SND_PCI_QUIRK(0x103c, 0x2192, "HP Touchsmart 15", ALC269_FIXUP_HP_MUTE_LED_MIC1), + SND_PCI_QUIRK(0x103c, 0x220d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), + SND_PCI_QUIRK(0x103c, 0x220e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), + SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), +@@ -4518,6 +4566,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), + SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), + SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), ++ SND_PCI_QUIRK(0x10cf, 0x159f, "Lifebook E780", ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT), ++ SND_PCI_QUIRK(0x10cf, 0x15dc, "Lifebook T731", ALC269_FIXUP_LIFEBOOK_HP_PIN), ++ SND_PCI_QUIRK(0x10cf, 0x1757, "Lifebook E752", ALC269_FIXUP_LIFEBOOK_HP_PIN), + SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), + SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), +@@ -4534,6 +4585,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), ++ SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), + SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP), + SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC), +@@ -4633,27 +4685,30 @@ static void alc269_fill_coef(struct hda_codec *codec) + if ((alc_get_coef0(codec) & 0x00ff) == 0x017) { + val = alc_read_coef_idx(codec, 0x04); + /* Power up output pin */ +- alc_write_coef_idx(codec, 0x04, val | (1<<11)); ++ if (val != -1) ++ alc_write_coef_idx(codec, 0x04, val | (1<<11)); + } + + if ((alc_get_coef0(codec) & 0x00ff) == 0x018) { + val = alc_read_coef_idx(codec, 0xd); +- if ((val & 0x0c00) >> 10 != 0x1) { ++ if (val != -1 && (val & 0x0c00) >> 10 != 0x1) { + /* Capless ramp up clock control */ + alc_write_coef_idx(codec, 0xd, val | (1<<10)); + } + val = alc_read_coef_idx(codec, 0x17); +- if ((val & 0x01c0) >> 6 != 0x4) { ++ if (val != -1 && (val & 0x01c0) >> 6 != 0x4) { + /* Class D power on reset */ + alc_write_coef_idx(codec, 0x17, val | (1<<7)); + } + } + + val = alc_read_coef_idx(codec, 0xd); /* Class D */ +- alc_write_coef_idx(codec, 0xd, val | (1<<14)); ++ if (val != -1) ++ alc_write_coef_idx(codec, 0xd, val | (1<<14)); + + val = alc_read_coef_idx(codec, 0x4); /* HP */ +- alc_write_coef_idx(codec, 0x4, val | (1<<11)); ++ if (val != -1) ++ alc_write_coef_idx(codec, 0x4, val | (1<<11)); + } + + /* +diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c +index 3bc29c9..231b264 100644 +--- a/sound/pci/hda/patch_sigmatel.c ++++ b/sound/pci/hda/patch_sigmatel.c +@@ -84,6 +84,8 @@ enum { + STAC_DELL_EQ, + STAC_ALIENWARE_M17X, + STAC_92HD89XX_HP_FRONT_JACK, ++ STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK, ++ STAC_92HD73XX_ASUS_MOBO, + STAC_92HD73XX_MODELS + }; + +@@ -558,8 +560,8 @@ static void stac_init_power_map(struct hda_codec *codec) + if (snd_hda_jack_tbl_get(codec, nid)) + continue; + if (def_conf == AC_JACK_PORT_COMPLEX && +- !(spec->vref_mute_led_nid == nid || +- is_jack_detectable(codec, nid))) { ++ spec->vref_mute_led_nid != nid && ++ is_jack_detectable(codec, nid)) { + snd_hda_jack_detect_enable_callback(codec, nid, + STAC_PWR_EVENT, + jack_update_power); +@@ -592,9 +594,9 @@ static void stac_store_hints(struct hda_codec *codec) + spec->gpio_mask; + } + if (get_int_hint(codec, "gpio_dir", &spec->gpio_dir)) +- spec->gpio_mask &= spec->gpio_mask; +- if (get_int_hint(codec, "gpio_data", &spec->gpio_data)) + spec->gpio_dir &= spec->gpio_mask; ++ if (get_int_hint(codec, "gpio_data", &spec->gpio_data)) ++ spec->gpio_data &= spec->gpio_mask; + if (get_int_hint(codec, "eapd_mask", &spec->eapd_mask)) + spec->eapd_mask &= spec->gpio_mask; + if (get_int_hint(codec, "gpio_mute", &spec->gpio_mute)) +@@ -1803,6 +1805,11 @@ static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = { + {} + }; + ++static const struct hda_pintbl stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs[] = { ++ { 0x0e, 0x400000f0 }, ++ {} ++}; ++ + static void stac92hd73xx_fixup_ref(struct hda_codec *codec, + const struct hda_fixup *fix, int action) + { +@@ -1925,7 +1932,22 @@ static const struct hda_fixup stac92hd73xx_fixups[] = { + [STAC_92HD89XX_HP_FRONT_JACK] = { + .type = HDA_FIXUP_PINS, + .v.pins = stac92hd89xx_hp_front_jack_pin_configs, +- } ++ }, ++ [STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs, ++ }, ++ [STAC_92HD73XX_ASUS_MOBO] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ /* enable 5.1 and SPDIF out */ ++ { 0x0c, 0x01014411 }, ++ { 0x0d, 0x01014410 }, ++ { 0x0e, 0x01014412 }, ++ { 0x22, 0x014b1180 }, ++ { } ++ } ++ }, + }; + + static const struct hda_model_fixup stac92hd73xx_models[] = { +@@ -1937,6 +1959,7 @@ static const struct hda_model_fixup stac92hd73xx_models[] = { + { .id = STAC_DELL_M6_BOTH, .name = "dell-m6" }, + { .id = STAC_DELL_EQ, .name = "dell-eq" }, + { .id = STAC_ALIENWARE_M17X, .name = "alienware" }, ++ { .id = STAC_92HD73XX_ASUS_MOBO, .name = "asus-mobo" }, + {} + }; + +@@ -1985,8 +2008,12 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = { + "Alienware M17x", STAC_ALIENWARE_M17X), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, + "Alienware M17x R3", STAC_DELL_EQ), ++ SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1927, ++ "HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17, + "unknown HP", STAC_92HD89XX_HP_FRONT_JACK), ++ SND_PCI_QUIRK(PCI_VENDOR_ID_ASUSTEK, 0x83f8, "ASUS AT4NM10", ++ STAC_92HD73XX_ASUS_MOBO), + {} /* terminator */ + }; + +@@ -4200,11 +4227,18 @@ static int stac_parse_auto_config(struct hda_codec *codec) + return err; + } + +- stac_init_power_map(codec); +- + return 0; + } + ++static int stac_build_controls(struct hda_codec *codec) ++{ ++ int err = snd_hda_gen_build_controls(codec); ++ ++ if (err < 0) ++ return err; ++ stac_init_power_map(codec); ++ return 0; ++} + + static int stac_init(struct hda_codec *codec) + { +@@ -4316,7 +4350,7 @@ static int stac_suspend(struct hda_codec *codec) + #endif /* CONFIG_PM */ + + static const struct hda_codec_ops stac_patch_ops = { +- .build_controls = snd_hda_gen_build_controls, ++ .build_controls = stac_build_controls, + .build_pcms = snd_hda_gen_build_pcms, + .init = stac_init, + .free = stac_free, +diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c +index 64b9fda..dbbbacf 100644 +--- a/sound/pci/oxygen/virtuoso.c ++++ b/sound/pci/oxygen/virtuoso.c +@@ -53,6 +53,7 @@ static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = { + { OXYGEN_PCI_SUBID(0x1043, 0x835e) }, + { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, + { OXYGEN_PCI_SUBID(0x1043, 0x8522) }, ++ { OXYGEN_PCI_SUBID(0x1043, 0x85f4) }, + { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, + { } + }; +diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c +index c8c7f2c..e026059 100644 +--- a/sound/pci/oxygen/xonar_pcm179x.c ++++ b/sound/pci/oxygen/xonar_pcm179x.c +@@ -100,8 +100,8 @@ + */ + + /* +- * Xonar Essence ST (Deluxe)/STX +- * ----------------------------- ++ * Xonar Essence ST (Deluxe)/STX (II) ++ * ---------------------------------- + * + * CMI8788: + * +@@ -1138,6 +1138,14 @@ int get_xonar_pcm179x_model(struct oxygen *chip, + chip->model.resume = xonar_stx_resume; + chip->model.set_dac_params = set_pcm1796_params; + break; ++ case 0x85f4: ++ chip->model = model_xonar_st; ++ /* TODO: daughterboard support */ ++ chip->model.shortname = "Xonar STX II"; ++ chip->model.init = xonar_stx_init; ++ chip->model.resume = xonar_stx_resume; ++ chip->model.set_dac_params = set_pcm1796_params; ++ break; + default: + return -EINVAL; + } +diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c +index 56cc891..d99c8d3 100644 +--- a/sound/pci/riptide/riptide.c ++++ b/sound/pci/riptide/riptide.c +@@ -2032,32 +2032,43 @@ snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id) + { + static int dev; + struct gameport *gameport; ++ int ret; + + if (dev >= SNDRV_CARDS) + return -ENODEV; ++ + if (!enable[dev]) { +- dev++; +- return -ENOENT; ++ ret = -ENOENT; ++ goto inc_dev; + } + +- if (!joystick_port[dev++]) +- return 0; ++ if (!joystick_port[dev]) { ++ ret = 0; ++ goto inc_dev; ++ } + + gameport = gameport_allocate_port(); +- if (!gameport) +- return -ENOMEM; ++ if (!gameport) { ++ ret = -ENOMEM; ++ goto inc_dev; ++ } + if (!request_region(joystick_port[dev], 8, "Riptide gameport")) { + snd_printk(KERN_WARNING + "Riptide: cannot grab gameport 0x%x\n", + joystick_port[dev]); + gameport_free_port(gameport); +- return -EBUSY; ++ ret = -EBUSY; ++ goto inc_dev; + } + + gameport->io = joystick_port[dev]; + gameport_register_port(gameport); + pci_set_drvdata(pci, gameport); +- return 0; ++ ++ ret = 0; ++inc_dev: ++ dev++; ++ return ret; + } + + static void snd_riptide_joystick_remove(struct pci_dev *pci) +diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c +index e98dc00..2116750 100644 +--- a/sound/pci/rme9652/hdspm.c ++++ b/sound/pci/rme9652/hdspm.c +@@ -6102,6 +6102,9 @@ static int snd_hdspm_playback_open(struct snd_pcm_substream *substream) + snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + 64, 8192); ++ snd_pcm_hw_constraint_minmax(runtime, ++ SNDRV_PCM_HW_PARAM_PERIODS, ++ 2, 2); + break; + } + +@@ -6176,6 +6179,9 @@ static int snd_hdspm_capture_open(struct snd_pcm_substream *substream) + snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + 64, 8192); ++ snd_pcm_hw_constraint_minmax(runtime, ++ SNDRV_PCM_HW_PARAM_PERIODS, ++ 2, 2); + break; + } + +diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c +index 1ead3c9..f20e703 100644 +--- a/sound/soc/atmel/atmel_ssc_dai.c ++++ b/sound/soc/atmel/atmel_ssc_dai.c +@@ -344,7 +344,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, + struct atmel_pcm_dma_params *dma_params; + int dir, channels, bits; + u32 tfmr, rfmr, tcmr, rcmr; +- int start_event; + int ret; + + /* +@@ -451,19 +450,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, + * The SSC transmit clock is obtained from the BCLK signal on + * on the TK line, and the SSC receive clock is + * generated from the transmit clock. +- * +- * For single channel data, one sample is transferred +- * on the falling edge of the LRC clock. +- * For two channel data, one sample is +- * transferred on both edges of the LRC clock. + */ +- start_event = ((channels == 1) +- ? SSC_START_FALLING_RF +- : SSC_START_EDGE_RF); +- + rcmr = SSC_BF(RCMR_PERIOD, 0) + | SSC_BF(RCMR_STTDLY, START_DELAY) +- | SSC_BF(RCMR_START, start_event) ++ | SSC_BF(RCMR_START, SSC_START_FALLING_RF) + | SSC_BF(RCMR_CKI, SSC_CKI_RISING) + | SSC_BF(RCMR_CKO, SSC_CKO_NONE) + | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK); +@@ -471,14 +461,14 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, + rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) + | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) + | SSC_BF(RFMR_FSLEN, 0) +- | SSC_BF(RFMR_DATNB, 0) ++ | SSC_BF(RFMR_DATNB, (channels - 1)) + | SSC_BIT(RFMR_MSBF) + | SSC_BF(RFMR_LOOP, 0) + | SSC_BF(RFMR_DATLEN, (bits - 1)); + + tcmr = SSC_BF(TCMR_PERIOD, 0) + | SSC_BF(TCMR_STTDLY, START_DELAY) +- | SSC_BF(TCMR_START, start_event) ++ | SSC_BF(TCMR_START, SSC_START_FALLING_RF) + | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) + | SSC_BF(TCMR_CKO, SSC_CKO_NONE) + | SSC_BF(TCMR_CKS, SSC_CKS_PIN); +@@ -487,7 +477,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, + | SSC_BF(TFMR_FSDEN, 0) + | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) + | SSC_BF(TFMR_FSLEN, 0) +- | SSC_BF(TFMR_DATNB, 0) ++ | SSC_BF(TFMR_DATNB, (channels - 1)) + | SSC_BIT(TFMR_MSBF) + | SSC_BF(TFMR_DATDEF, 0) + | SSC_BF(TFMR_DATLEN, (bits - 1)); +diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c +index a3881c4..bcf5913 100644 +--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c ++++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c +@@ -290,19 +290,19 @@ static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, + unsigned int sample_size = runtime->sample_bits / 8; + void *buf = runtime->dma_area; + struct bf5xx_i2s_pcm_data *dma_data; +- unsigned int offset, size; ++ unsigned int offset, samples; + + dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + + if (dma_data->tdm_mode) { + offset = pos * 8 * sample_size; +- size = count * 8 * sample_size; ++ samples = count * 8; + } else { + offset = frames_to_bytes(runtime, pos); +- size = frames_to_bytes(runtime, count); ++ samples = count * runtime->channels; + } + +- snd_pcm_format_set_silence(runtime->format, buf + offset, size); ++ snd_pcm_format_set_silence(runtime->format, buf + offset, samples); + + return 0; + } +diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c +index d71c59c..370b742 100644 +--- a/sound/soc/codecs/adau1701.c ++++ b/sound/soc/codecs/adau1701.c +@@ -230,8 +230,10 @@ static int adau1701_reg_read(void *context, unsigned int reg, + + *value = 0; + +- for (i = 0; i < size; i++) +- *value |= recv_buf[i] << (i * 8); ++ for (i = 0; i < size; i++) { ++ *value <<= 8; ++ *value |= recv_buf[i]; ++ } + + return 0; + } +diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c +index f78b27a..23454e9 100644 +--- a/sound/soc/codecs/adav80x.c ++++ b/sound/soc/codecs/adav80x.c +@@ -319,7 +319,7 @@ static int adav80x_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); +- unsigned int deemph = ucontrol->value.enumerated.item[0]; ++ unsigned int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; +@@ -335,7 +335,7 @@ static int adav80x_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = adav80x->deemph; ++ ucontrol->value.integer.value[0] = adav80x->deemph; + return 0; + }; + +diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c +index 94cbe50..d718472 100644 +--- a/sound/soc/codecs/ak4641.c ++++ b/sound/soc/codecs/ak4641.c +@@ -76,7 +76,7 @@ static int ak4641_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; +@@ -92,7 +92,7 @@ static int ak4641_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = ak4641->deemph; ++ ucontrol->value.integer.value[0] = ak4641->deemph; + return 0; + }; + +diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c +index ce05fd9..a0ad41a 100644 +--- a/sound/soc/codecs/cs4271.c ++++ b/sound/soc/codecs/cs4271.c +@@ -288,7 +288,7 @@ static int cs4271_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = cs4271->deemph; ++ ucontrol->value.integer.value[0] = cs4271->deemph; + return 0; + } + +@@ -298,7 +298,7 @@ static int cs4271_put_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); + +- cs4271->deemph = ucontrol->value.enumerated.item[0]; ++ cs4271->deemph = ucontrol->value.integer.value[0]; + return cs4271_set_deemph(codec); + } + +diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c +index b3f7c90..9dd260f 100644 +--- a/sound/soc/codecs/max98090.c ++++ b/sound/soc/codecs/max98090.c +@@ -1378,8 +1378,8 @@ static const struct snd_soc_dapm_route max98090_dapm_routes[] = { + {"STENL Mux", "Sidetone Left", "DMICL"}, + {"STENR Mux", "Sidetone Right", "ADCR"}, + {"STENR Mux", "Sidetone Right", "DMICR"}, +- {"DACL", "NULL", "STENL Mux"}, +- {"DACR", "NULL", "STENL Mux"}, ++ {"DACL", NULL, "STENL Mux"}, ++ {"DACR", NULL, "STENL Mux"}, + + {"AIFINL", NULL, "SHDN"}, + {"AIFINR", NULL, "SHDN"}, +@@ -2250,7 +2250,7 @@ static int max98090_probe(struct snd_soc_codec *codec) + /* Register for interrupts */ + dev_dbg(codec->dev, "irq = %d\n", max98090->irq); + +- ret = request_threaded_irq(max98090->irq, NULL, ++ ret = devm_request_threaded_irq(codec->dev, max98090->irq, NULL, + max98090_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "max98090_interrupt", codec); + if (ret < 0) { +diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c +index 582c2bb..b852293 100644 +--- a/sound/soc/codecs/mc13783.c ++++ b/sound/soc/codecs/mc13783.c +@@ -634,14 +634,14 @@ static int mc13783_probe(struct snd_soc_codec *codec) + AUDIO_SSI_SEL, 0); + else + mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_CODEC, +- 0, AUDIO_SSI_SEL); ++ AUDIO_SSI_SEL, AUDIO_SSI_SEL); + + if (priv->dac_ssi_port == MC13783_SSI1_PORT) + mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC, + AUDIO_SSI_SEL, 0); + else + mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC, +- 0, AUDIO_SSI_SEL); ++ AUDIO_SSI_SEL, AUDIO_SSI_SEL); + + return 0; + } +diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c +index 73f9c36..dfa9755 100644 +--- a/sound/soc/codecs/pcm1681.c ++++ b/sound/soc/codecs/pcm1681.c +@@ -102,7 +102,7 @@ static int pcm1681_set_deemph(struct snd_soc_codec *codec) + + if (val != -1) { + regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL, +- PCM1681_DEEMPH_RATE_MASK, val); ++ PCM1681_DEEMPH_RATE_MASK, val << 3); + enable = 1; + } else + enable = 0; +@@ -118,7 +118,7 @@ static int pcm1681_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = priv->deemph; ++ ucontrol->value.integer.value[0] = priv->deemph; + + return 0; + } +@@ -129,7 +129,7 @@ static int pcm1681_put_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); + +- priv->deemph = ucontrol->value.enumerated.item[0]; ++ priv->deemph = ucontrol->value.integer.value[0]; + + return pcm1681_set_deemph(codec); + } +diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c +index 8869249..5cb515b 100644 +--- a/sound/soc/codecs/rt5640.c ++++ b/sound/soc/codecs/rt5640.c +@@ -2071,6 +2071,7 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5640 = { + static const struct regmap_config rt5640_regmap = { + .reg_bits = 8, + .val_bits = 16, ++ .use_single_rw = true, + + .max_register = RT5640_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5640_ranges) * + RT5640_PR_SPACING), +diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c +index 893c95b..5ea3b4e 100644 +--- a/sound/soc/codecs/sgtl5000.c ++++ b/sound/soc/codecs/sgtl5000.c +@@ -1379,8 +1379,7 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) + + /* enable small pop, introduce 400ms delay in turning off */ + snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL, +- SGTL5000_SMALL_POP, +- SGTL5000_SMALL_POP); ++ SGTL5000_SMALL_POP, 1); + + /* disable short cut detector */ + snd_soc_write(codec, SGTL5000_CHIP_SHORT_CTRL, 0); +@@ -1534,6 +1533,9 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, + if (ret) + return ret; + ++ /* Need 8 clocks before I2C accesses */ ++ udelay(1); ++ + /* read chip information */ + ret = regmap_read(sgtl5000->regmap, SGTL5000_CHIP_ID, ®); + if (ret) +diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h +index 2f8c889..bd7a344 100644 +--- a/sound/soc/codecs/sgtl5000.h ++++ b/sound/soc/codecs/sgtl5000.h +@@ -275,7 +275,7 @@ + #define SGTL5000_BIAS_CTRL_MASK 0x000e + #define SGTL5000_BIAS_CTRL_SHIFT 1 + #define SGTL5000_BIAS_CTRL_WIDTH 3 +-#define SGTL5000_SMALL_POP 0x0001 ++#define SGTL5000_SMALL_POP 0 + + /* + * SGTL5000_CHIP_MIC_CTRL +diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c +index 4068f24..bb3878c 100644 +--- a/sound/soc/codecs/sigmadsp.c ++++ b/sound/soc/codecs/sigmadsp.c +@@ -176,6 +176,13 @@ static int _process_sigma_firmware(struct device *dev, + goto done; + } + ++ if (ssfw_head->version != 1) { ++ dev_err(dev, ++ "Failed to load firmware: Invalid version %d. Supported firmware versions: 1\n", ++ ssfw_head->version); ++ goto done; ++ } ++ + crc = crc32(0, fw->data + sizeof(*ssfw_head), + fw->size - sizeof(*ssfw_head)); + pr_debug("%s: crc=%x\n", __func__, crc); +diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c +index a895a5e..c6c6500 100644 +--- a/sound/soc/codecs/tas5086.c ++++ b/sound/soc/codecs/tas5086.c +@@ -275,7 +275,7 @@ static int tas5086_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = priv->deemph; ++ ucontrol->value.integer.value[0] = priv->deemph; + + return 0; + } +@@ -286,7 +286,7 @@ static int tas5086_put_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); + +- priv->deemph = ucontrol->value.enumerated.item[0]; ++ priv->deemph = ucontrol->value.integer.value[0]; + + return tas5086_set_deemph(codec); + } +diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c +index eb241c6..fd53d37 100644 +--- a/sound/soc/codecs/tlv320aic3x.c ++++ b/sound/soc/codecs/tlv320aic3x.c +@@ -1121,6 +1121,7 @@ static int aic3x_regulator_event(struct notifier_block *nb, + static int aic3x_set_power(struct snd_soc_codec *codec, int power) + { + struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); ++ unsigned int pll_c, pll_d; + int ret; + + if (power) { +@@ -1138,6 +1139,18 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power) + /* Sync reg_cache with the hardware */ + regcache_cache_only(aic3x->regmap, false); + regcache_sync(aic3x->regmap); ++ ++ /* Rewrite paired PLL D registers in case cached sync skipped ++ * writing one of them and thus caused other one also not ++ * being written ++ */ ++ pll_c = snd_soc_read(codec, AIC3X_PLL_PROGC_REG); ++ pll_d = snd_soc_read(codec, AIC3X_PLL_PROGD_REG); ++ if (pll_c == aic3x_reg[AIC3X_PLL_PROGC_REG].def || ++ pll_d == aic3x_reg[AIC3X_PLL_PROGD_REG].def) { ++ snd_soc_write(codec, AIC3X_PLL_PROGC_REG, pll_c); ++ snd_soc_write(codec, AIC3X_PLL_PROGD_REG, pll_d); ++ } + } else { + /* + * Do soft reset to this codec instance in order to clear +diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c +index 8ae5027..1a9f457 100644 +--- a/sound/soc/codecs/wm2000.c ++++ b/sound/soc/codecs/wm2000.c +@@ -610,7 +610,7 @@ static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); + +- ucontrol->value.enumerated.item[0] = wm2000->anc_active; ++ ucontrol->value.integer.value[0] = wm2000->anc_active; + + return 0; + } +@@ -620,7 +620,7 @@ static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); +- int anc_active = ucontrol->value.enumerated.item[0]; ++ int anc_active = ucontrol->value.integer.value[0]; + int ret; + + if (anc_active > 1) +@@ -643,7 +643,7 @@ static int wm2000_speaker_get(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); + +- ucontrol->value.enumerated.item[0] = wm2000->spk_ena; ++ ucontrol->value.integer.value[0] = wm2000->spk_ena; + + return 0; + } +@@ -653,7 +653,7 @@ static int wm2000_speaker_put(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); +- int val = ucontrol->value.enumerated.item[0]; ++ int val = ucontrol->value.integer.value[0]; + int ret; + + if (val > 1) +diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c +index ce9c8e1..fbee45c 100644 +--- a/sound/soc/codecs/wm5102.c ++++ b/sound/soc/codecs/wm5102.c +@@ -41,7 +41,7 @@ struct wm5102_priv { + static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); + static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); + static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); +-static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); ++static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0); + static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); + + static const struct wm_adsp_region wm5102_dsp1_regions[] = { +diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c +index 2c3c962..0fce853 100644 +--- a/sound/soc/codecs/wm5110.c ++++ b/sound/soc/codecs/wm5110.c +@@ -167,7 +167,7 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, + static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); + static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); + static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); +-static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); ++static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0); + static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); + + #define WM5110_NG_SRC(name, base) \ +diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c +index 0297203..e593722 100644 +--- a/sound/soc/codecs/wm8731.c ++++ b/sound/soc/codecs/wm8731.c +@@ -122,7 +122,7 @@ static int wm8731_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = wm8731->deemph; ++ ucontrol->value.integer.value[0] = wm8731->deemph; + + return 0; + } +@@ -132,7 +132,7 @@ static int wm8731_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + int ret = 0; + + if (deemph > 1) +diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c +index 2f167a8..62bacb8 100644 +--- a/sound/soc/codecs/wm8737.c ++++ b/sound/soc/codecs/wm8737.c +@@ -494,7 +494,8 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec, + + /* Fast VMID ramp at 2*2.5k */ + snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, +- WM8737_VMIDSEL_MASK, 0x4); ++ WM8737_VMIDSEL_MASK, ++ 2 << WM8737_VMIDSEL_SHIFT); + + /* Bring VMID up */ + snd_soc_update_bits(codec, WM8737_POWER_MANAGEMENT, +@@ -508,7 +509,8 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec, + + /* VMID at 2*300k */ + snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, +- WM8737_VMIDSEL_MASK, 2); ++ WM8737_VMIDSEL_MASK, ++ 1 << WM8737_VMIDSEL_SHIFT); + + break; + +diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c +index eebcb1d..ae7d76e 100644 +--- a/sound/soc/codecs/wm8903.c ++++ b/sound/soc/codecs/wm8903.c +@@ -442,7 +442,7 @@ static int wm8903_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = wm8903->deemph; ++ ucontrol->value.integer.value[0] = wm8903->deemph; + + return 0; + } +@@ -452,7 +452,7 @@ static int wm8903_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + int ret = 0; + + if (deemph > 1) +diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h +index db94931..0bb4a64 100644 +--- a/sound/soc/codecs/wm8903.h ++++ b/sound/soc/codecs/wm8903.h +@@ -172,7 +172,7 @@ extern int wm8903_mic_detect(struct snd_soc_codec *codec, + #define WM8903_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */ + + #define WM8903_VMID_RES_50K 2 +-#define WM8903_VMID_RES_250K 3 ++#define WM8903_VMID_RES_250K 4 + #define WM8903_VMID_RES_5K 6 + + /* +diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c +index 53bbfac..66cb9e9 100644 +--- a/sound/soc/codecs/wm8904.c ++++ b/sound/soc/codecs/wm8904.c +@@ -523,7 +523,7 @@ static int wm8904_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = wm8904->deemph; ++ ucontrol->value.integer.value[0] = wm8904->deemph; + return 0; + } + +@@ -532,7 +532,7 @@ static int wm8904_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; +diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c +index 82c8ba9..475fc24 100644 +--- a/sound/soc/codecs/wm8955.c ++++ b/sound/soc/codecs/wm8955.c +@@ -298,7 +298,7 @@ static int wm8955_configure_clocking(struct snd_soc_codec *codec) + snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2, + WM8955_K_17_9_MASK, + (pll.k >> 9) & WM8955_K_17_9_MASK); +- snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2, ++ snd_soc_update_bits(codec, WM8955_PLL_CONTROL_3, + WM8955_K_8_0_MASK, + pll.k & WM8955_K_8_0_MASK); + if (pll.k) +@@ -393,7 +393,7 @@ static int wm8955_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = wm8955->deemph; ++ ucontrol->value.integer.value[0] = wm8955->deemph; + return 0; + } + +@@ -402,7 +402,7 @@ static int wm8955_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; +diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c +index f156010..e04dbaa 100644 +--- a/sound/soc/codecs/wm8960.c ++++ b/sound/soc/codecs/wm8960.c +@@ -181,7 +181,7 @@ static int wm8960_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = wm8960->deemph; ++ ucontrol->value.integer.value[0] = wm8960->deemph; + return 0; + } + +@@ -190,7 +190,7 @@ static int wm8960_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; +@@ -242,7 +242,7 @@ SOC_SINGLE("PCM Playback -6dB Switch", WM8960_DACCTL1, 7, 1, 0), + SOC_ENUM("ADC Polarity", wm8960_enum[0]), + SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1, 0, 1, 0), + +-SOC_ENUM("DAC Polarity", wm8960_enum[2]), ++SOC_ENUM("DAC Polarity", wm8960_enum[1]), + SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0, + wm8960_get_deemph, wm8960_put_deemph), + +@@ -392,7 +392,7 @@ static const struct snd_soc_dapm_route audio_paths[] = { + { "Right Input Mixer", "Boost Switch", "Right Boost Mixer", }, + { "Right Input Mixer", NULL, "RINPUT1", }, /* Really Boost Switch */ + { "Right Input Mixer", NULL, "RINPUT2" }, +- { "Right Input Mixer", NULL, "LINPUT3" }, ++ { "Right Input Mixer", NULL, "RINPUT3" }, + + { "Left ADC", NULL, "Left Input Mixer" }, + { "Right ADC", NULL, "Right Input Mixer" }, +@@ -555,7 +555,7 @@ static struct { + { 22050, 2 }, + { 24000, 2 }, + { 16000, 3 }, +- { 11250, 4 }, ++ { 11025, 4 }, + { 12000, 4 }, + { 8000, 5 }, + }; +diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c +index adb7206..66aec0c 100644 +--- a/sound/soc/codecs/wm8994.c ++++ b/sound/soc/codecs/wm8994.c +@@ -2745,7 +2745,7 @@ static struct { + }; + + static int fs_ratios[] = { +- 64, 128, 192, 256, 348, 512, 768, 1024, 1408, 1536 ++ 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536 + }; + + static int bclk_divs[] = { +@@ -3497,6 +3497,7 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data) + return IRQ_HANDLED; + } + ++/* Should be called with accdet_lock held */ + static void wm1811_micd_stop(struct snd_soc_codec *codec) + { + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); +@@ -3504,14 +3505,10 @@ static void wm1811_micd_stop(struct snd_soc_codec *codec) + if (!wm8994->jackdet) + return; + +- mutex_lock(&wm8994->accdet_lock); +- + snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, WM8958_MICD_ENA, 0); + + wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK); + +- mutex_unlock(&wm8994->accdet_lock); +- + if (wm8994->wm8994->pdata.jd_ext_cap) + snd_soc_dapm_disable_pin(&codec->dapm, + "MICBIAS2"); +@@ -3552,10 +3549,10 @@ static void wm8958_open_circuit_work(struct work_struct *work) + open_circuit_work.work); + struct device *dev = wm8994->wm8994->dev; + +- wm1811_micd_stop(wm8994->hubs.codec); +- + mutex_lock(&wm8994->accdet_lock); + ++ wm1811_micd_stop(wm8994->hubs.codec); ++ + dev_dbg(dev, "Reporting open circuit\n"); + + wm8994->jack_mic = false; +diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c +index 555115e..1461ae61 100644 +--- a/sound/soc/codecs/wm8997.c ++++ b/sound/soc/codecs/wm8997.c +@@ -40,7 +40,7 @@ struct wm8997_priv { + static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0); + static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); + static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); +-static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); ++static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0); + static DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); + + static const struct reg_default wm8997_sysclk_reva_patch[] = { +diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c +index 444626f..0502e3f 100644 +--- a/sound/soc/codecs/wm_adsp.c ++++ b/sound/soc/codecs/wm_adsp.c +@@ -1341,6 +1341,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) + file, blocks, pos - firmware->size); + + out_fw: ++ regmap_async_complete(regmap); + release_firmware(firmware); + wm_adsp_buf_free(&buf_list); + out: +@@ -1745,3 +1746,5 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs) + return 0; + } + EXPORT_SYMBOL_GPL(wm_adsp2_init); ++ ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c +index 5e3bc3c..f40a7a4 100644 +--- a/sound/soc/davinci/davinci-evm.c ++++ b/sound/soc/davinci/davinci-evm.c +@@ -384,18 +384,8 @@ static int davinci_evm_probe(struct platform_device *pdev) + return ret; + } + +-static int davinci_evm_remove(struct platform_device *pdev) +-{ +- struct snd_soc_card *card = platform_get_drvdata(pdev); +- +- snd_soc_unregister_card(card); +- +- return 0; +-} +- + static struct platform_driver davinci_evm_driver = { + .probe = davinci_evm_probe, +- .remove = davinci_evm_remove, + .driver = { + .name = "davinci_evm", + .owner = THIS_MODULE, +diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c +index 670afa2..7350ebb 100644 +--- a/sound/soc/davinci/davinci-mcasp.c ++++ b/sound/soc/davinci/davinci-mcasp.c +@@ -418,8 +418,17 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, + { + u32 fmt; + u32 tx_rotate = (word_length / 4) & 0x7; +- u32 rx_rotate = (32 - word_length) / 4; + u32 mask = (1ULL << word_length) - 1; ++ /* ++ * For captured data we should not rotate, inversion and masking is ++ * enoguh to get the data to the right position: ++ * Format data from bus after reverse (XRBUF) ++ * S16_LE: |LSB|MSB|xxx|xxx| |xxx|xxx|MSB|LSB| ++ * S24_3LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB| ++ * S24_LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB| ++ * S32_LE: |LSB|DAT|DAT|MSB| |MSB|DAT|DAT|LSB| ++ */ ++ u32 rx_rotate = 0; + + /* + * if s BCLK-to-LRCLK ratio has been configured via the set_clkdiv() +diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c +index 25c31f1..2f63575 100644 +--- a/sound/soc/dwc/designware_i2s.c ++++ b/sound/soc/dwc/designware_i2s.c +@@ -263,6 +263,19 @@ static void dw_i2s_shutdown(struct snd_pcm_substream *substream, + snd_soc_dai_set_dma_data(dai, substream, NULL); + } + ++static int dw_i2s_prepare(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ i2s_write_reg(dev->i2s_base, TXFFR, 1); ++ else ++ i2s_write_reg(dev->i2s_base, RXFFR, 1); ++ ++ return 0; ++} ++ + static int dw_i2s_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) + { +@@ -294,6 +307,7 @@ static struct snd_soc_dai_ops dw_i2s_dai_ops = { + .startup = dw_i2s_startup, + .shutdown = dw_i2s_shutdown, + .hw_params = dw_i2s_hw_params, ++ .prepare = dw_i2s_prepare, + .trigger = dw_i2s_trigger, + }; + +diff --git a/sound/soc/fsl/fsl_esai.h b/sound/soc/fsl/fsl_esai.h +index 75e1403..dfdbaa0 100644 +--- a/sound/soc/fsl/fsl_esai.h ++++ b/sound/soc/fsl/fsl_esai.h +@@ -302,7 +302,7 @@ + #define ESAI_xCCR_xFP_MASK (((1 << ESAI_xCCR_xFP_WIDTH) - 1) << ESAI_xCCR_xFP_SHIFT) + #define ESAI_xCCR_xFP(v) ((((v) - 1) << ESAI_xCCR_xFP_SHIFT) & ESAI_xCCR_xFP_MASK) + #define ESAI_xCCR_xDC_SHIFT 9 +-#define ESAI_xCCR_xDC_WIDTH 4 ++#define ESAI_xCCR_xDC_WIDTH 5 + #define ESAI_xCCR_xDC_MASK (((1 << ESAI_xCCR_xDC_WIDTH) - 1) << ESAI_xCCR_xDC_SHIFT) + #define ESAI_xCCR_xDC(v) ((((v) - 1) << ESAI_xCCR_xDC_SHIFT) & ESAI_xCCR_xDC_MASK) + #define ESAI_xCCR_xPSR_SHIFT 8 +diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c +index fdd28a7..274c220 100644 +--- a/sound/soc/fsl/imx-wm8962.c ++++ b/sound/soc/fsl/imx-wm8962.c +@@ -439,7 +439,7 @@ static int imx_wm8962_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "audmux internal port setup failed\n"); + return ret; + } +- imx_audmux_v2_configure_port(ext_port, ++ ret = imx_audmux_v2_configure_port(ext_port, + IMX_AUDMUX_V2_PTCR_SYN, + IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)); + if (ret) { +diff --git a/sound/soc/jz4740/Makefile b/sound/soc/jz4740/Makefile +index be873c1..d32c540 100644 +--- a/sound/soc/jz4740/Makefile ++++ b/sound/soc/jz4740/Makefile +@@ -1,10 +1,8 @@ + # + # Jz4740 Platform Support + # +-snd-soc-jz4740-objs := jz4740-pcm.o + snd-soc-jz4740-i2s-objs := jz4740-i2s.o + +-obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o + obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o + + # Jz4740 Machine Support +diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c +index 6c19bba..6a339fb 100644 +--- a/sound/soc/omap/omap-mcbsp.c ++++ b/sound/soc/omap/omap-mcbsp.c +@@ -436,7 +436,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, + case SND_SOC_DAIFMT_CBM_CFS: + /* McBSP slave. FS clock as output */ + regs->srgr2 |= FSGM; +- regs->pcr0 |= FSXM; ++ regs->pcr0 |= FSXM | FSRM; + break; + case SND_SOC_DAIFMT_CBM_CFM: + /* McBSP slave */ +diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c +index 07b8b7b..81f6a75 100644 +--- a/sound/soc/omap/omap-pcm.c ++++ b/sound/soc/omap/omap-pcm.c +@@ -200,7 +200,7 @@ static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd) + struct snd_pcm *pcm = rtd->pcm; + int ret; + +- ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(64)); ++ ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + +diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c +index a3119a0..6c6b35e 100644 +--- a/sound/soc/pxa/pxa-ssp.c ++++ b/sound/soc/pxa/pxa-ssp.c +@@ -725,7 +725,8 @@ static int pxa_ssp_probe(struct snd_soc_dai *dai) + ssp_handle = of_parse_phandle(dev->of_node, "port", 0); + if (!ssp_handle) { + dev_err(dev, "unable to get 'port' phandle\n"); +- return -ENODEV; ++ ret = -ENODEV; ++ goto err_priv; + } + + priv->ssp = pxa_ssp_request_of(ssp_handle, "SoC audio"); +@@ -766,9 +767,7 @@ static int pxa_ssp_remove(struct snd_soc_dai *dai) + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) + +-#define PXA_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ +- SNDRV_PCM_FMTBIT_S24_LE | \ +- SNDRV_PCM_FMTBIT_S32_LE) ++#define PXA_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) + + static const struct snd_soc_dai_ops pxa_ssp_dai_ops = { + .startup = pxa_ssp_startup, +diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c +index 0a9b44c..5dae660 100644 +--- a/sound/soc/samsung/i2s.c ++++ b/sound/soc/samsung/i2s.c +@@ -915,11 +915,9 @@ static int i2s_suspend(struct snd_soc_dai *dai) + { + struct i2s_dai *i2s = to_info(dai); + +- if (dai->active) { +- i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); +- i2s->suspend_i2scon = readl(i2s->addr + I2SCON); +- i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR); +- } ++ i2s->suspend_i2smod = readl(i2s->addr + I2SMOD); ++ i2s->suspend_i2scon = readl(i2s->addr + I2SCON); ++ i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR); + + return 0; + } +@@ -928,11 +926,9 @@ static int i2s_resume(struct snd_soc_dai *dai) + { + struct i2s_dai *i2s = to_info(dai); + +- if (dai->active) { +- writel(i2s->suspend_i2scon, i2s->addr + I2SCON); +- writel(i2s->suspend_i2smod, i2s->addr + I2SMOD); +- writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR); +- } ++ writel(i2s->suspend_i2scon, i2s->addr + I2SCON); ++ writel(i2s->suspend_i2smod, i2s->addr + I2SMOD); ++ writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR); + + return 0; + } +diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c +index 1967f44..9d0c59c 100644 +--- a/sound/soc/sh/fsi.c ++++ b/sound/soc/sh/fsi.c +@@ -1785,8 +1785,7 @@ static const struct snd_soc_dai_ops fsi_dai_ops = { + static struct snd_pcm_hardware fsi_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | +- SNDRV_PCM_INFO_MMAP_VALID | +- SNDRV_PCM_INFO_PAUSE, ++ SNDRV_PCM_INFO_MMAP_VALID, + .buffer_bytes_max = 64 * 1024, + .period_bytes_min = 32, + .period_bytes_max = 8192, +diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c +index 743de5e..37fcd93 100644 +--- a/sound/soc/sh/rcar/core.c ++++ b/sound/soc/sh/rcar/core.c +@@ -626,8 +626,7 @@ static void rsnd_dai_remove(struct platform_device *pdev, + static struct snd_pcm_hardware rsnd_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | +- SNDRV_PCM_INFO_MMAP_VALID | +- SNDRV_PCM_INFO_PAUSE, ++ SNDRV_PCM_INFO_MMAP_VALID, + .buffer_bytes_max = 64 * 1024, + .period_bytes_min = 32, + .period_bytes_max = 8192, +diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c +index 5e9690c..4f98ff1 100644 +--- a/sound/soc/soc-compress.c ++++ b/sound/soc/soc-compress.c +@@ -696,7 +696,8 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) + rtd->dai_link->stream_name); + + ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, +- 1, 0, &be_pcm); ++ rtd->dai_link->dpcm_playback, ++ rtd->dai_link->dpcm_capture, &be_pcm); + if (ret < 0) { + dev_err(rtd->card->dev, "ASoC: can't create compressed for %s\n", + rtd->dai_link->name); +@@ -705,8 +706,10 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) + + rtd->pcm = be_pcm; + rtd->fe_compr = 1; +- be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; +- be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; ++ if (rtd->dai_link->dpcm_playback) ++ be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; ++ else if (rtd->dai_link->dpcm_capture) ++ be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; + memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops)); + } else + memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); +diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c +index 731d47b..e4da224 100644 +--- a/sound/soc/soc-dapm.c ++++ b/sound/soc/soc-dapm.c +@@ -689,9 +689,9 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, + int shared; + struct snd_kcontrol *kcontrol; + bool wname_in_long_name, kcname_in_long_name; +- char *long_name; ++ char *long_name = NULL; + const char *name; +- int ret; ++ int ret = 0; + + if (dapm->codec) + prefix = dapm->codec->name_prefix; +@@ -756,15 +756,17 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, + + kcontrol = snd_soc_cnew(&w->kcontrol_news[kci], NULL, name, + prefix); +- kfree(long_name); +- if (!kcontrol) +- return -ENOMEM; ++ if (!kcontrol) { ++ ret = -ENOMEM; ++ goto exit_free; ++ } ++ + kcontrol->private_free = dapm_kcontrol_free; + + ret = dapm_kcontrol_data_alloc(w, kcontrol); + if (ret) { + snd_ctl_free_one(kcontrol); +- return ret; ++ goto exit_free; + } + + ret = snd_ctl_add(card, kcontrol); +@@ -772,17 +774,18 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w, + dev_err(dapm->dev, + "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", + w->name, name, ret); +- return ret; ++ goto exit_free; + } + } + + ret = dapm_kcontrol_add_widget(kcontrol, w); +- if (ret) +- return ret; ++ if (ret == 0) ++ w->kcontrols[kci] = kcontrol; + +- w->kcontrols[kci] = kcontrol; ++exit_free: ++ kfree(long_name); + +- return 0; ++ return ret; + } + + /* create new dapm mixer control */ +diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c +index 8fa7cd3..18984c4 100644 +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -1258,13 +1258,36 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) + dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture); + } + ++static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd); ++ ++/* Set FE's runtime_update state; the state is protected via PCM stream lock ++ * for avoiding the race with trigger callback. ++ * If the state is unset and a trigger is pending while the previous operation, ++ * process the pending trigger action here. ++ */ ++static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe, ++ int stream, enum snd_soc_dpcm_update state) ++{ ++ struct snd_pcm_substream *substream = ++ snd_soc_dpcm_get_substream(fe, stream); ++ ++ snd_pcm_stream_lock_irq(substream); ++ if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) { ++ dpcm_fe_dai_do_trigger(substream, ++ fe->dpcm[stream].trigger_pending - 1); ++ fe->dpcm[stream].trigger_pending = 0; ++ } ++ fe->dpcm[stream].runtime_update = state; ++ snd_pcm_stream_unlock_irq(substream); ++} ++ + static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) + { + struct snd_soc_pcm_runtime *fe = fe_substream->private_data; + struct snd_pcm_runtime *runtime = fe_substream->runtime; + int stream = fe_substream->stream, ret = 0; + +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); + + ret = dpcm_be_dai_startup(fe, fe_substream->stream); + if (ret < 0) { +@@ -1286,13 +1309,13 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) + dpcm_set_fe_runtime(fe_substream); + snd_pcm_limit_hw_rates(runtime); + +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + return 0; + + unwind: + dpcm_be_dai_startup_unwind(fe, fe_substream->stream); + be_err: +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + return ret; + } + +@@ -1339,7 +1362,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream) + struct snd_soc_pcm_runtime *fe = substream->private_data; + int stream = substream->stream; + +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); + + /* shutdown the BEs */ + dpcm_be_dai_shutdown(fe, substream->stream); +@@ -1353,7 +1376,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream) + dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); + + fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + return 0; + } + +@@ -1401,7 +1424,7 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) + int err, stream = substream->stream; + + mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); + + dev_dbg(fe->dev, "ASoC: hw_free FE %s\n", fe->dai_link->name); + +@@ -1416,7 +1439,7 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) + err = dpcm_be_dai_hw_free(fe, stream); + + fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE; +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + + mutex_unlock(&fe->card->mutex); + return 0; +@@ -1509,7 +1532,7 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream, + int ret, stream = substream->stream; + + mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); + + memcpy(&fe->dpcm[substream->stream].hw_params, params, + sizeof(struct snd_pcm_hw_params)); +@@ -1532,7 +1555,7 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream, + fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS; + + out: +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + mutex_unlock(&fe->card->mutex); + return ret; + } +@@ -1646,7 +1669,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, + } + EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger); + +-static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd) ++static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) + { + struct snd_soc_pcm_runtime *fe = substream->private_data; + int stream = substream->stream, ret; +@@ -1720,6 +1743,23 @@ out: + return ret; + } + ++static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd) ++{ ++ struct snd_soc_pcm_runtime *fe = substream->private_data; ++ int stream = substream->stream; ++ ++ /* if FE's runtime_update is already set, we're in race; ++ * process this trigger later at exit ++ */ ++ if (fe->dpcm[stream].runtime_update != SND_SOC_DPCM_UPDATE_NO) { ++ fe->dpcm[stream].trigger_pending = cmd + 1; ++ return 0; /* delayed, assuming it's successful */ ++ } ++ ++ /* we're alone, let's trigger */ ++ return dpcm_fe_dai_do_trigger(substream, cmd); ++} ++ + int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) + { + struct snd_soc_dpcm *dpcm; +@@ -1763,7 +1803,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) + + dev_dbg(fe->dev, "ASoC: prepare FE %s\n", fe->dai_link->name); + +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); + + /* there is no point preparing this FE if there are no BEs */ + if (list_empty(&fe->dpcm[stream].be_clients)) { +@@ -1790,7 +1830,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) + fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; + + out: +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + mutex_unlock(&fe->card->mutex); + + return ret; +@@ -1937,11 +1977,11 @@ static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream) + { + int ret; + +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE); + ret = dpcm_run_update_startup(fe, stream); + if (ret < 0) + dev_err(fe->dev, "ASoC: failed to startup some BEs\n"); +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + + return ret; + } +@@ -1950,11 +1990,11 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream) + { + int ret; + +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE); + ret = dpcm_run_update_shutdown(fe, stream); + if (ret < 0) + dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n"); +- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; ++ dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + + return ret; + } +@@ -2011,6 +2051,7 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card) + dpcm_be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK); + } + ++ dpcm_path_put(&list); + capture: + /* skip if FE doesn't have capture capability */ + if (!fe->cpu_dai->driver->capture.channels_min) +diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c +index 319754c..daf61ab 100644 +--- a/sound/synth/emux/emux_oss.c ++++ b/sound/synth/emux/emux_oss.c +@@ -118,12 +118,8 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) + if (snd_BUG_ON(!arg || !emu)) + return -ENXIO; + +- mutex_lock(&emu->register_mutex); +- +- if (!snd_emux_inc_count(emu)) { +- mutex_unlock(&emu->register_mutex); ++ if (!snd_emux_inc_count(emu)) + return -EFAULT; +- } + + memset(&callback, 0, sizeof(callback)); + callback.owner = THIS_MODULE; +@@ -135,7 +131,6 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) + if (p == NULL) { + snd_printk(KERN_ERR "can't create port\n"); + snd_emux_dec_count(emu); +- mutex_unlock(&emu->register_mutex); + return -ENOMEM; + } + +@@ -148,8 +143,6 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) + reset_port_mode(p, arg->seq_mode); + + snd_emux_reset_port(p); +- +- mutex_unlock(&emu->register_mutex); + return 0; + } + +@@ -195,13 +188,11 @@ snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg) + if (snd_BUG_ON(!emu)) + return -ENXIO; + +- mutex_lock(&emu->register_mutex); + snd_emux_sounds_off_all(p); + snd_soundfont_close_check(emu->sflist, SF_CLIENT_NO(p->chset.port)); + snd_seq_event_port_detach(p->chset.client, p->chset.port); + snd_emux_dec_count(emu); + +- mutex_unlock(&emu->register_mutex); + return 0; + } + +diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c +index 7778b8e..a020920 100644 +--- a/sound/synth/emux/emux_seq.c ++++ b/sound/synth/emux/emux_seq.c +@@ -124,12 +124,10 @@ snd_emux_detach_seq(struct snd_emux *emu) + if (emu->voices) + snd_emux_terminate_all(emu); + +- mutex_lock(&emu->register_mutex); + if (emu->client >= 0) { + snd_seq_delete_kernel_client(emu->client); + emu->client = -1; + } +- mutex_unlock(&emu->register_mutex); + } + + +@@ -269,8 +267,8 @@ snd_emux_event_input(struct snd_seq_event *ev, int direct, void *private_data, + /* + * increment usage count + */ +-int +-snd_emux_inc_count(struct snd_emux *emu) ++static int ++__snd_emux_inc_count(struct snd_emux *emu) + { + emu->used++; + if (!try_module_get(emu->ops.owner)) +@@ -284,12 +282,21 @@ snd_emux_inc_count(struct snd_emux *emu) + return 1; + } + ++int snd_emux_inc_count(struct snd_emux *emu) ++{ ++ int ret; ++ ++ mutex_lock(&emu->register_mutex); ++ ret = __snd_emux_inc_count(emu); ++ mutex_unlock(&emu->register_mutex); ++ return ret; ++} + + /* + * decrease usage count + */ +-void +-snd_emux_dec_count(struct snd_emux *emu) ++static void ++__snd_emux_dec_count(struct snd_emux *emu) + { + module_put(emu->card->module); + emu->used--; +@@ -298,6 +305,12 @@ snd_emux_dec_count(struct snd_emux *emu) + module_put(emu->ops.owner); + } + ++void snd_emux_dec_count(struct snd_emux *emu) ++{ ++ mutex_lock(&emu->register_mutex); ++ __snd_emux_dec_count(emu); ++ mutex_unlock(&emu->register_mutex); ++} + + /* + * Routine that is called upon a first use of a particular port +@@ -317,7 +330,7 @@ snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info) + + mutex_lock(&emu->register_mutex); + snd_emux_init_port(p); +- snd_emux_inc_count(emu); ++ __snd_emux_inc_count(emu); + mutex_unlock(&emu->register_mutex); + return 0; + } +@@ -340,7 +353,7 @@ snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info) + + mutex_lock(&emu->register_mutex); + snd_emux_sounds_off_all(p); +- snd_emux_dec_count(emu); ++ __snd_emux_dec_count(emu); + mutex_unlock(&emu->register_mutex); + return 0; + } +diff --git a/sound/usb/card.c b/sound/usb/card.c +index af19560..ab433a0 100644 +--- a/sound/usb/card.c ++++ b/sound/usb/card.c +@@ -586,18 +586,19 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, + { + struct snd_card *card; + struct list_head *p; ++ bool was_shutdown; + + if (chip == (void *)-1L) + return; + + card = chip->card; + down_write(&chip->shutdown_rwsem); ++ was_shutdown = chip->shutdown; + chip->shutdown = 1; + up_write(&chip->shutdown_rwsem); + + mutex_lock(®ister_mutex); +- chip->num_interfaces--; +- if (chip->num_interfaces <= 0) { ++ if (!was_shutdown) { + struct snd_usb_endpoint *ep; + + snd_card_disconnect(card); +@@ -617,6 +618,10 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, + list_for_each(p, &chip->mixer_list) { + snd_usb_mixer_disconnect(p); + } ++ } ++ ++ chip->num_interfaces--; ++ if (chip->num_interfaces <= 0) { + usb_chip[chip->index] = NULL; + mutex_unlock(®ister_mutex); + snd_card_free_when_closed(card); +diff --git a/sound/usb/midi.c b/sound/usb/midi.c +index b901f46..c7aa71e 100644 +--- a/sound/usb/midi.c ++++ b/sound/usb/midi.c +@@ -364,6 +364,8 @@ static void snd_usbmidi_error_timer(unsigned long data) + if (in && in->error_resubmit) { + in->error_resubmit = 0; + for (j = 0; j < INPUT_URBS; ++j) { ++ if (atomic_read(&in->urbs[j]->use_count)) ++ continue; + in->urbs[j]->dev = umidi->dev; + snd_usbmidi_submit_urb(in->urbs[j], GFP_ATOMIC); + } +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index 1bed780..c601033 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -886,10 +886,12 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, + case USB_ID(0x046d, 0x0807): /* Logitech Webcam C500 */ + case USB_ID(0x046d, 0x0808): + case USB_ID(0x046d, 0x0809): ++ case USB_ID(0x046d, 0x0819): /* Logitech Webcam C210 */ + case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */ + case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ + case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */ + case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */ ++ case USB_ID(0x046d, 0x08ca): /* Logitech Quickcam Fusion */ + case USB_ID(0x046d, 0x0991): + /* Most audio usb devices lie about volume resolution. + * Most Logitech webcams have res = 384. +diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c +index d1d72ff..9a3e107 100644 +--- a/sound/usb/mixer_maps.c ++++ b/sound/usb/mixer_maps.c +@@ -328,11 +328,28 @@ static struct usbmix_name_map gamecom780_map[] = { + {} + }; + +-static const struct usbmix_name_map kef_x300a_map[] = { +- { 10, NULL }, /* firmware locks up (?) when we try to access this FU */ ++/* some (all?) SCMS USB3318 devices are affected by a firmware lock up ++ * when anything attempts to access FU 10 (control) ++ */ ++static const struct usbmix_name_map scms_usb3318_map[] = { ++ { 10, NULL }, + { 0 } + }; + ++/* Bose companion 5, the dB conversion factor is 16 instead of 256 */ ++static struct usbmix_dB_map bose_companion5_dB = {-5006, -6}; ++static struct usbmix_name_map bose_companion5_map[] = { ++ { 3, NULL, .dB = &bose_companion5_dB }, ++ { 0 } /* terminator */ ++}; ++ ++/* Dragonfly DAC 1.2, the dB conversion factor is 1 instead of 256 */ ++static struct usbmix_dB_map dragonfly_1_2_dB = {0, 5000}; ++static struct usbmix_name_map dragonfly_1_2_map[] = { ++ { 7, NULL, .dB = &dragonfly_1_2_dB }, ++ { 0 } /* terminator */ ++}; ++ + /* + * Control map entries + */ +@@ -425,8 +442,29 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { + .map = ebox44_map, + }, + { ++ /* MAYA44 USB+ */ ++ .id = USB_ID(0x2573, 0x0008), ++ .map = maya44_map, ++ }, ++ { ++ /* KEF X300A */ + .id = USB_ID(0x27ac, 0x1000), +- .map = kef_x300a_map, ++ .map = scms_usb3318_map, ++ }, ++ { ++ /* Arcam rPAC */ ++ .id = USB_ID(0x25c4, 0x0003), ++ .map = scms_usb3318_map, ++ }, ++ { ++ /* Bose Companion 5 */ ++ .id = USB_ID(0x05a7, 0x1020), ++ .map = bose_companion5_map, ++ }, ++ { ++ /* Dragonfly DAC 1.2 */ ++ .id = USB_ID(0x21b4, 0x0081), ++ .map = dragonfly_1_2_map, + }, + { 0 } /* terminator */ + }; +diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c +index f4b12c2..a82ec53 100644 +--- a/sound/usb/mixer_quirks.c ++++ b/sound/usb/mixer_quirks.c +@@ -178,6 +178,7 @@ static const struct rc_config { + { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ + { USB_ID(0x041e, 0x3042), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 */ + { USB_ID(0x041e, 0x30df), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */ ++ { USB_ID(0x041e, 0x3237), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */ + { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ + }; + +@@ -885,6 +886,11 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, + return changed; + } + ++static void kctl_private_value_free(struct snd_kcontrol *kctl) ++{ ++ kfree((void *)kctl->private_value); ++} ++ + static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer, + int validx, int bUnitID) + { +@@ -919,6 +925,7 @@ static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer, + return -ENOMEM; + } + ++ kctl->private_free = kctl_private_value_free; + err = snd_ctl_add(mixer->chip->card, kctl); + if (err < 0) + return err; +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index f652b10..7c24088 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -385,6 +385,36 @@ YAMAHA_DEVICE(0x105d, NULL), + } + }, + { ++ USB_DEVICE(0x0499, 0x1509), ++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { ++ /* .vendor_name = "Yamaha", */ ++ /* .product_name = "Steinberg UR22", */ ++ .ifnum = QUIRK_ANY_INTERFACE, ++ .type = QUIRK_COMPOSITE, ++ .data = (const struct snd_usb_audio_quirk[]) { ++ { ++ .ifnum = 1, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 2, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 3, ++ .type = QUIRK_MIDI_YAMAHA ++ }, ++ { ++ .ifnum = 4, ++ .type = QUIRK_IGNORE_INTERFACE ++ }, ++ { ++ .ifnum = -1 ++ } ++ } ++ } ++}, ++{ + USB_DEVICE(0x0499, 0x150a), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + /* .vendor_name = "Yamaha", */ +@@ -1581,6 +1611,35 @@ YAMAHA_DEVICE(0x7010, "UB99"), + } + }, + { ++ /* BOSS ME-25 */ ++ USB_DEVICE(0x0582, 0x0113), ++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { ++ .ifnum = QUIRK_ANY_INTERFACE, ++ .type = QUIRK_COMPOSITE, ++ .data = (const struct snd_usb_audio_quirk[]) { ++ { ++ .ifnum = 0, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 1, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 2, ++ .type = QUIRK_MIDI_FIXED_ENDPOINT, ++ .data = & (const struct snd_usb_midi_endpoint_info) { ++ .out_cables = 0x0001, ++ .in_cables = 0x0001 ++ } ++ }, ++ { ++ .ifnum = -1 ++ } ++ } ++ } ++}, ++{ + /* only 44.1 kHz works at the moment */ + USB_DEVICE(0x0582, 0x0120), + .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { +@@ -1714,6 +1773,36 @@ YAMAHA_DEVICE(0x7010, "UB99"), + } + } + }, ++{ ++ USB_DEVICE(0x0582, 0x0159), ++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { ++ /* .vendor_name = "Roland", */ ++ /* .product_name = "UA-22", */ ++ .ifnum = QUIRK_ANY_INTERFACE, ++ .type = QUIRK_COMPOSITE, ++ .data = (const struct snd_usb_audio_quirk[]) { ++ { ++ .ifnum = 0, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 1, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 2, ++ .type = QUIRK_MIDI_FIXED_ENDPOINT, ++ .data = & (const struct snd_usb_midi_endpoint_info) { ++ .out_cables = 0x0001, ++ .in_cables = 0x0001 ++ } ++ }, ++ { ++ .ifnum = -1 ++ } ++ } ++ } ++}, + /* this catches most recent vendor-specific Roland devices */ + { + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | +@@ -2427,6 +2516,74 @@ YAMAHA_DEVICE(0x7010, "UB99"), + } + }, + ++/* Steinberg devices */ ++{ ++ /* Steinberg MI2 */ ++ USB_DEVICE_VENDOR_SPEC(0x0a4e, 0x2040), ++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { ++ .ifnum = QUIRK_ANY_INTERFACE, ++ .type = QUIRK_COMPOSITE, ++ .data = & (const struct snd_usb_audio_quirk[]) { ++ { ++ .ifnum = 0, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 1, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 2, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 3, ++ .type = QUIRK_MIDI_FIXED_ENDPOINT, ++ .data = &(const struct snd_usb_midi_endpoint_info) { ++ .out_cables = 0x0001, ++ .in_cables = 0x0001 ++ } ++ }, ++ { ++ .ifnum = -1 ++ } ++ } ++ } ++}, ++{ ++ /* Steinberg MI4 */ ++ USB_DEVICE_VENDOR_SPEC(0x0a4e, 0x4040), ++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { ++ .ifnum = QUIRK_ANY_INTERFACE, ++ .type = QUIRK_COMPOSITE, ++ .data = & (const struct snd_usb_audio_quirk[]) { ++ { ++ .ifnum = 0, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 1, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 2, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 3, ++ .type = QUIRK_MIDI_FIXED_ENDPOINT, ++ .data = &(const struct snd_usb_midi_endpoint_info) { ++ .out_cables = 0x0001, ++ .in_cables = 0x0001 ++ } ++ }, ++ { ++ .ifnum = -1 ++ } ++ } ++ } ++}, ++ + /* TerraTec devices */ + { + USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012), +@@ -2745,133 +2902,45 @@ YAMAHA_DEVICE(0x7010, "UB99"), + } + }, + +-/* Hauppauge HVR-950Q and HVR-850 */ +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x7200), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x7210), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x7217), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x721b), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x721e), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x721f), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x7240), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-850", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x2040, 0x7280), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, +-{ +- USB_DEVICE_VENDOR_SPEC(0x0fd9, 0x0008), +- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | +- USB_DEVICE_ID_MATCH_INT_CLASS | +- USB_DEVICE_ID_MATCH_INT_SUBCLASS, +- .bInterfaceClass = USB_CLASS_AUDIO, +- .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, +- .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { +- .vendor_name = "Hauppauge", +- .product_name = "HVR-950Q", +- .ifnum = QUIRK_ANY_INTERFACE, +- .type = QUIRK_AUDIO_ALIGN_TRANSFER, +- } +-}, ++/* ++ * Auvitek au0828 devices with audio interface. ++ * This should be kept in sync with drivers/media/usb/au0828/au0828-cards.c ++ * Please notice that some drivers are DVB only, and don't need to be ++ * here. That's the case, for example, of DVICO_FUSIONHDTV7. ++ */ ++ ++#define AU0828_DEVICE(vid, pid, vname, pname) { \ ++ USB_DEVICE_VENDOR_SPEC(vid, pid), \ ++ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ ++ USB_DEVICE_ID_MATCH_INT_CLASS | \ ++ USB_DEVICE_ID_MATCH_INT_SUBCLASS, \ ++ .bInterfaceClass = USB_CLASS_AUDIO, \ ++ .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, \ ++ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { \ ++ .vendor_name = vname, \ ++ .product_name = pname, \ ++ .ifnum = QUIRK_ANY_INTERFACE, \ ++ .type = QUIRK_AUDIO_ALIGN_TRANSFER, \ ++ } \ ++} ++ ++AU0828_DEVICE(0x2040, 0x7200, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x7240, "Hauppauge", "HVR-850"), ++AU0828_DEVICE(0x2040, 0x7210, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x7217, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x721b, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x721e, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x721f, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x7280, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x0fd9, 0x0008, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x7201, "Hauppauge", "HVR-950Q-MXL"), ++AU0828_DEVICE(0x2040, 0x7211, "Hauppauge", "HVR-950Q-MXL"), ++AU0828_DEVICE(0x2040, 0x7281, "Hauppauge", "HVR-950Q-MXL"), ++AU0828_DEVICE(0x05e1, 0x0480, "Hauppauge", "Woodbury"), ++AU0828_DEVICE(0x2040, 0x8200, "Hauppauge", "Woodbury"), ++AU0828_DEVICE(0x2040, 0x7260, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x7213, "Hauppauge", "HVR-950Q"), ++AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), + + /* Digidesign Mbox */ + { +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 8973070..827d404 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -666,7 +666,7 @@ static int snd_usb_gamecon780_boot_quirk(struct usb_device *dev) + /* set the initial volume and don't change; other values are either + * too loud or silent due to firmware bug (bko#65251) + */ +- u8 buf[2] = { 0x74, 0xdc }; ++ u8 buf[2] = { 0x74, 0xe3 }; + return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, + UAC_FU_VOLUME << 8, 9 << 8, buf, 2); +@@ -1142,6 +1142,20 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, + if ((le16_to_cpu(dev->descriptor.idVendor) == 0x23ba) && + (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) + mdelay(20); ++ ++ /* Marantz/Denon devices with USB DAC functionality need a delay ++ * after each class compliant request ++ */ ++ if ((le16_to_cpu(dev->descriptor.idVendor) == 0x154e) && ++ (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) { ++ ++ switch (le16_to_cpu(dev->descriptor.idProduct)) { ++ case 0x3005: /* Marantz HD-DAC1 */ ++ case 0x3006: /* Marantz SA-14S1 */ ++ mdelay(20); ++ break; ++ } ++ } + } + + /* +diff --git a/tools/lib/traceevent/kbuffer-parse.c b/tools/lib/traceevent/kbuffer-parse.c +index dcc6652..deb3569 100644 +--- a/tools/lib/traceevent/kbuffer-parse.c ++++ b/tools/lib/traceevent/kbuffer-parse.c +@@ -372,7 +372,6 @@ translate_data(struct kbuffer *kbuf, void *data, void **rptr, + switch (type_len) { + case KBUFFER_TYPE_PADDING: + *length = read_4(kbuf, data); +- data += *length; + break; + + case KBUFFER_TYPE_TIME_EXTEND: +diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h +index a59743f..0001c9a 100644 +--- a/tools/perf/util/hist.h ++++ b/tools/perf/util/hist.h +@@ -36,6 +36,7 @@ struct events_stats { + u32 nr_invalid_chains; + u32 nr_unknown_id; + u32 nr_unprocessable_samples; ++ u32 nr_unordered_events; + }; + + enum hist_column { +diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c +index 5da6ce7..c1f20e9 100644 +--- a/tools/perf/util/session.c ++++ b/tools/perf/util/session.c +@@ -638,8 +638,7 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event, + return -ETIME; + + if (timestamp < s->ordered_samples.last_flush) { +- printf("Warning: Timestamp below last timeslice flush\n"); +- return -EINVAL; ++ s->stats.nr_unordered_events++; + } + + if (!list_empty(sc)) { +@@ -1135,6 +1134,8 @@ static void perf_session__warn_about_errors(const struct perf_session *session, + "Do you have a KVM guest running and not using 'perf kvm'?\n", + session->stats.nr_unprocessable_samples); + } ++ if (session->stats.nr_unordered_events != 0) ++ ui__warning("%u out of order events recorded.\n", session->stats.nr_unordered_events); + } + + volatile int session_done; +diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile +index d1b3a36..4039854 100644 +--- a/tools/power/x86/turbostat/Makefile ++++ b/tools/power/x86/turbostat/Makefile +@@ -1,8 +1,12 @@ + CC = $(CROSS_COMPILE)gcc +-BUILD_OUTPUT := $(PWD) ++BUILD_OUTPUT := $(CURDIR) + PREFIX := /usr + DESTDIR := + ++ifeq ("$(origin O)", "command line") ++ BUILD_OUTPUT := $(O) ++endif ++ + turbostat : turbostat.c + CFLAGS += -Wall + CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/uapi/asm/msr-index.h"' +diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile +index 32487ed..3d5979b2 100644 +--- a/tools/testing/selftests/Makefile ++++ b/tools/testing/selftests/Makefile +@@ -4,6 +4,7 @@ TARGETS += efivarfs + TARGETS += kcmp + TARGETS += memory-hotplug + TARGETS += mqueue ++TARGETS += mount + TARGETS += net + TARGETS += ptrace + TARGETS += timers +diff --git a/tools/vm/Makefile b/tools/vm/Makefile +index 3d907da..c604f3e 100644 +--- a/tools/vm/Makefile ++++ b/tools/vm/Makefile +@@ -3,7 +3,7 @@ + TARGETS=page-types slabinfo + + LIB_DIR = ../lib/api +-LIBS = $(LIB_DIR)/libapikfs.a ++LIBS = $(LIB_DIR)/libapi.a + + CC = $(CROSS_COMPILE)gcc + CFLAGS = -Wall -Wextra -I../lib/ +diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c +index 5081e80..c6fe405 100644 +--- a/virt/kvm/arm/arch_timer.c ++++ b/virt/kvm/arm/arch_timer.c +@@ -61,12 +61,14 @@ static void timer_disarm(struct arch_timer_cpu *timer) + + static void kvm_timer_inject_irq(struct kvm_vcpu *vcpu) + { ++ int ret; + struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; + + timer->cntv_ctl |= ARCH_TIMER_CTRL_IT_MASK; +- kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id, +- timer->irq->irq, +- timer->irq->level); ++ ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id, ++ timer->irq->irq, ++ timer->irq->level); ++ WARN_ON(ret); + } + + static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id) +@@ -307,12 +309,24 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu) + timer_disarm(timer); + } + +-int kvm_timer_init(struct kvm *kvm) ++void kvm_timer_enable(struct kvm *kvm) + { +- if (timecounter && wqueue) { +- kvm->arch.timer.cntvoff = kvm_phys_timer_read(); ++ if (kvm->arch.timer.enabled) ++ return; ++ ++ /* ++ * There is a potential race here between VCPUs starting for the first ++ * time, which may be enabling the timer multiple times. That doesn't ++ * hurt though, because we're just setting a variable to the same ++ * variable that it already was. The important thing is that all ++ * VCPUs have the enabled variable set, before entering the guest, if ++ * the arch timers are enabled. ++ */ ++ if (timecounter && wqueue) + kvm->arch.timer.enabled = 1; +- } ++} + +- return 0; ++void kvm_timer_init(struct kvm *kvm) ++{ ++ kvm->arch.timer.cntvoff = kvm_phys_timer_read(); + } +diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c +index 26954a7..152ec76 100644 +--- a/virt/kvm/arm/vgic.c ++++ b/virt/kvm/arm/vgic.c +@@ -548,11 +548,10 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu, + u32 val; + u32 *reg; + +- offset >>= 1; + reg = vgic_bitmap_get_reg(&vcpu->kvm->arch.vgic.irq_cfg, +- vcpu->vcpu_id, offset); ++ vcpu->vcpu_id, offset >> 1); + +- if (offset & 2) ++ if (offset & 4) + val = *reg >> 16; + else + val = *reg & 0xffff; +@@ -561,13 +560,13 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu, + vgic_reg_access(mmio, &val, offset, + ACCESS_READ_VALUE | ACCESS_WRITE_VALUE); + if (mmio->is_write) { +- if (offset < 4) { ++ if (offset < 8) { + *reg = ~0U; /* Force PPIs/SGIs to 1 */ + return false; + } + + val = vgic_cfg_compress(val); +- if (offset & 2) { ++ if (offset & 4) { + *reg &= 0xffff; + *reg |= val << 16; + } else { +@@ -675,7 +674,7 @@ static bool read_set_clear_sgi_pend_reg(struct kvm_vcpu *vcpu, + { + struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + int sgi; +- int min_sgi = (offset & ~0x3) * 4; ++ int min_sgi = (offset & ~0x3); + int max_sgi = min_sgi + 3; + int vcpu_id = vcpu->vcpu_id; + u32 reg = 0; +@@ -696,7 +695,7 @@ static bool write_set_clear_sgi_pend_reg(struct kvm_vcpu *vcpu, + { + struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + int sgi; +- int min_sgi = (offset & ~0x3) * 4; ++ int min_sgi = (offset & ~0x3); + int max_sgi = min_sgi + 3; + int vcpu_id = vcpu->vcpu_id; + u32 reg; +@@ -1043,6 +1042,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq) + lr, irq, vgic_cpu->vgic_lr[lr]); + BUG_ON(!test_bit(lr, vgic_cpu->lr_used)); + vgic_cpu->vgic_lr[lr] |= GICH_LR_PENDING_BIT; ++ __clear_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr); + return true; + } + +@@ -1056,6 +1056,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq) + vgic_cpu->vgic_lr[lr] = MK_LR_PEND(sgi_source_id, irq); + vgic_cpu->vgic_irq_lr_map[irq] = lr; + set_bit(lr, vgic_cpu->lr_used); ++ __clear_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr); + + if (!vgic_irq_is_edge(vcpu, irq)) + vgic_cpu->vgic_lr[lr] |= GICH_LR_EOI; +@@ -1210,6 +1211,14 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) + if (vgic_cpu->vgic_misr & GICH_MISR_U) + vgic_cpu->vgic_hcr &= ~GICH_HCR_UIE; + ++ /* ++ * In the next iterations of the vcpu loop, if we sync the vgic state ++ * after flushing it, but before entering the guest (this happens for ++ * pending signals and vmid rollovers), then make sure we don't pick ++ * up any old maintenance interrupts here. ++ */ ++ memset(vgic_cpu->vgic_eisr, 0, sizeof(vgic_cpu->vgic_eisr[0]) * 2); ++ + return level_pending; + } + +@@ -1388,7 +1397,8 @@ out: + int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num, + bool level) + { +- if (vgic_update_irq_state(kvm, cpuid, irq_num, level)) ++ if (likely(vgic_initialized(kvm)) && ++ vgic_update_irq_state(kvm, cpuid, irq_num, level)) + vgic_kick_vcpus(kvm); + + return 0; +@@ -1527,17 +1537,33 @@ int kvm_vgic_hyp_init(void) + goto out_unmap; + } + +- kvm_info("%s@%llx IRQ%d\n", vgic_node->name, +- vctrl_res.start, vgic_maint_irq); +- on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1); +- + if (of_address_to_resource(vgic_node, 3, &vcpu_res)) { + kvm_err("Cannot obtain VCPU resource\n"); + ret = -ENXIO; + goto out_unmap; + } ++ ++ if (!PAGE_ALIGNED(vcpu_res.start)) { ++ kvm_err("GICV physical address 0x%llx not page aligned\n", ++ (unsigned long long)vcpu_res.start); ++ ret = -ENXIO; ++ goto out_unmap; ++ } ++ ++ if (!PAGE_ALIGNED(resource_size(&vcpu_res))) { ++ kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n", ++ (unsigned long long)resource_size(&vcpu_res), ++ PAGE_SIZE); ++ ret = -ENXIO; ++ goto out_unmap; ++ } ++ + vgic_vcpu_base = vcpu_res.start; + ++ kvm_info("%s@%llx IRQ%d\n", vgic_node->name, ++ vctrl_res.start, vgic_maint_irq); ++ on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1); ++ + goto out; + + out_unmap: +@@ -1595,7 +1621,7 @@ out: + + int kvm_vgic_create(struct kvm *kvm) + { +- int i, vcpu_lock_idx = -1, ret = 0; ++ int i, vcpu_lock_idx = -1, ret; + struct kvm_vcpu *vcpu; + + mutex_lock(&kvm->lock); +@@ -1610,6 +1636,7 @@ int kvm_vgic_create(struct kvm *kvm) + * vcpu->mutex. By grabbing the vcpu->mutex of all VCPUs we ensure + * that no other VCPUs are run while we create the vgic. + */ ++ ret = -EBUSY; + kvm_for_each_vcpu(i, vcpu, kvm) { + if (!mutex_trylock(&vcpu->mutex)) + goto out_unlock; +@@ -1617,11 +1644,10 @@ int kvm_vgic_create(struct kvm *kvm) + } + + kvm_for_each_vcpu(i, vcpu, kvm) { +- if (vcpu->arch.has_run_once) { +- ret = -EBUSY; ++ if (vcpu->arch.has_run_once) + goto out_unlock; +- } + } ++ ret = 0; + + spin_lock_init(&kvm->arch.vgic.lock); + kvm->arch.vgic.vctrl_base = vgic_vctrl_base; +@@ -1639,7 +1665,7 @@ out: + return ret; + } + +-static bool vgic_ioaddr_overlap(struct kvm *kvm) ++static int vgic_ioaddr_overlap(struct kvm *kvm) + { + phys_addr_t dist = kvm->arch.vgic.vgic_dist_base; + phys_addr_t cpu = kvm->arch.vgic.vgic_cpu_base; +@@ -1668,10 +1694,11 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr, + if (addr + size < addr) + return -EINVAL; + ++ *ioaddr = addr; + ret = vgic_ioaddr_overlap(kvm); + if (ret) +- return ret; +- *ioaddr = addr; ++ *ioaddr = VGIC_ADDR_UNDEF; ++ + return ret; + } + +diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c +index 8c805a0..b47541d 100644 +--- a/virt/kvm/ioapic.c ++++ b/virt/kvm/ioapic.c +@@ -203,10 +203,9 @@ void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap, + spin_lock(&ioapic->lock); + for (index = 0; index < IOAPIC_NUM_PINS; index++) { + e = &ioapic->redirtbl[index]; +- if (!e->fields.mask && +- (e->fields.trig_mode == IOAPIC_LEVEL_TRIG || +- kvm_irq_has_notifier(ioapic->kvm, KVM_IRQCHIP_IOAPIC, +- index) || index == RTC_GSI)) { ++ if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG || ++ kvm_irq_has_notifier(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index) || ++ index == RTC_GSI) { + if (kvm_apic_match_dest(vcpu, NULL, 0, + e->fields.dest_id, e->fields.dest_mode)) { + __set_bit(e->fields.vector, +diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c +index 0df7d4b..1f0dc1e 100644 +--- a/virt/kvm/iommu.c ++++ b/virt/kvm/iommu.c +@@ -43,13 +43,13 @@ static void kvm_iommu_put_pages(struct kvm *kvm, + gfn_t base_gfn, unsigned long npages); + + static pfn_t kvm_pin_pages(struct kvm_memory_slot *slot, gfn_t gfn, +- unsigned long size) ++ unsigned long npages) + { + gfn_t end_gfn; + pfn_t pfn; + + pfn = gfn_to_pfn_memslot(slot, gfn); +- end_gfn = gfn + (size >> PAGE_SHIFT); ++ end_gfn = gfn + npages; + gfn += 1; + + if (is_error_noslot_pfn(pfn)) +@@ -61,6 +61,14 @@ static pfn_t kvm_pin_pages(struct kvm_memory_slot *slot, gfn_t gfn, + return pfn; + } + ++static void kvm_unpin_pages(struct kvm *kvm, pfn_t pfn, unsigned long npages) ++{ ++ unsigned long i; ++ ++ for (i = 0; i < npages; ++i) ++ kvm_release_pfn_clean(pfn + i); ++} ++ + int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) + { + gfn_t gfn, end_gfn; +@@ -111,7 +119,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) + * Pin all pages we are about to map in memory. This is + * important because we unmap and unpin in 4kb steps later. + */ +- pfn = kvm_pin_pages(slot, gfn, page_size); ++ pfn = kvm_pin_pages(slot, gfn, page_size >> PAGE_SHIFT); + if (is_error_noslot_pfn(pfn)) { + gfn += 1; + continue; +@@ -123,6 +131,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) + if (r) { + printk(KERN_ERR "kvm_iommu_map_address:" + "iommu failed to map pfn=%llx\n", pfn); ++ kvm_unpin_pages(kvm, pfn, page_size >> PAGE_SHIFT); + goto unmap_pages; + } + +@@ -134,7 +143,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) + return 0; + + unmap_pages: +- kvm_iommu_put_pages(kvm, slot->base_gfn, gfn); ++ kvm_iommu_put_pages(kvm, slot->base_gfn, gfn - slot->base_gfn); + return r; + } + +@@ -266,14 +275,6 @@ out_unlock: + return r; + } + +-static void kvm_unpin_pages(struct kvm *kvm, pfn_t pfn, unsigned long npages) +-{ +- unsigned long i; +- +- for (i = 0; i < npages; ++i) +- kvm_release_pfn_clean(pfn + i); +-} +- + static void kvm_iommu_put_pages(struct kvm *kvm, + gfn_t base_gfn, unsigned long npages) + { +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 03a0381..eed250e 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -52,6 +52,7 @@ + + #include + #include ++#include + #include + #include + +@@ -95,8 +96,6 @@ static int hardware_enable_all(void); + static void hardware_disable_all(void); + + static void kvm_io_bus_destroy(struct kvm_io_bus *bus); +-static void update_memslots(struct kvm_memslots *slots, +- struct kvm_memory_slot *new, u64 last_generation); + + static void kvm_release_pfn_dirty(pfn_t pfn); + static void mark_page_dirty_in_slot(struct kvm *kvm, +@@ -682,8 +681,7 @@ static void sort_memslots(struct kvm_memslots *slots) + } + + static void update_memslots(struct kvm_memslots *slots, +- struct kvm_memory_slot *new, +- u64 last_generation) ++ struct kvm_memory_slot *new) + { + if (new) { + int id = new->id; +@@ -694,8 +692,6 @@ static void update_memslots(struct kvm_memslots *slots, + if (new->npages != npages) + sort_memslots(slots); + } +- +- slots->generation = last_generation + 1; + } + + static int check_memory_region_flags(struct kvm_userspace_memory_region *mem) +@@ -717,10 +713,24 @@ static struct kvm_memslots *install_new_memslots(struct kvm *kvm, + { + struct kvm_memslots *old_memslots = kvm->memslots; + +- update_memslots(slots, new, kvm->memslots->generation); ++ /* ++ * Set the low bit in the generation, which disables SPTE caching ++ * until the end of synchronize_srcu_expedited. ++ */ ++ WARN_ON(old_memslots->generation & 1); ++ slots->generation = old_memslots->generation + 1; ++ ++ update_memslots(slots, new); + rcu_assign_pointer(kvm->memslots, slots); + synchronize_srcu_expedited(&kvm->srcu); + ++ /* ++ * Increment the new memslot generation a second time. This prevents ++ * vm exits that race with memslot updates from caching a memslot ++ * generation that will (potentially) be valid forever. ++ */ ++ slots->generation++; ++ + kvm_arch_memslots_updated(kvm); + + return old_memslots; +@@ -1539,8 +1549,8 @@ int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc, + ghc->generation = slots->generation; + ghc->len = len; + ghc->memslot = gfn_to_memslot(kvm, start_gfn); +- ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, &nr_pages_avail); +- if (!kvm_is_error_hva(ghc->hva) && nr_pages_avail >= nr_pages_needed) { ++ ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, NULL); ++ if (!kvm_is_error_hva(ghc->hva) && nr_pages_needed <= 1) { + ghc->hva += offset; + } else { + /* +@@ -1970,6 +1980,9 @@ static long kvm_vcpu_ioctl(struct file *filp, + if (vcpu->kvm->mm != current->mm) + return -EIO; + ++ if (unlikely(_IOC_TYPE(ioctl) != KVMIO)) ++ return -EINVAL; ++ + #if defined(CONFIG_S390) || defined(CONFIG_PPC) || defined(CONFIG_MIPS) + /* + * Special cases: vcpu ioctls that are asynchronous to vcpu execution, diff --git a/patch/kernel/fix_dts_4.4.patch b/patch/kernel/fix_dts_4.4.patch new file mode 100644 index 000000000..90f8c4000 --- /dev/null +++ b/patch/kernel/fix_dts_4.4.patch @@ -0,0 +1,21 @@ +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -619,17 +619,5 @@ + sun5i-a13-q8-tablet.dtb \ + sun5i-a13-utoo-p66.dtb \ + sun5i-r8-chip.dtb +-dtb-$(CONFIG_MACH_SUN6I) += \ +- sun6i-a31-app4-evb1.dtb \ +- sun6i-a31-colombus.dtb \ +- sun6i-a31-hummingbird.dtb \ +- sun6i-a31-i7.dtb \ +- sun6i-a31-m9.dtb \ +- sun6i-a31-mele-a1000g-quad.dtb \ +- sun6i-a31s-cs908.dtb \ +- sun6i-a31s-primo81.dtb \ +- sun6i-a31s-sina31s.dtb \ +- sun6i-a31s-sinovoip-bpi-m2.dtb \ +- sun6i-a31s-yones-toptech-bs1078-v2.dtb + dtb-$(CONFIG_MACH_SUN7I) += \ + sun7i-a20-bananapi.dtb \ + \ No newline at end of file diff --git a/patch/kernel/h3-7498741.patch b/patch/kernel/h3-7498741.patch new file mode 100644 index 000000000..5608eb91c --- /dev/null +++ b/patch/kernel/h3-7498741.patch @@ -0,0 +1,119 @@ +From patchwork Tue Oct 27 16:50:21 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4, + 1/6] clk: sunxi: Let divs clocks read the base factor clock name from + devicetree +From: Jens Kuske +X-Patchwork-Id: 7498741 +Message-Id: <1445964626-6484-2-git-send-email-jenskuske@gmail.com> +To: Maxime Ripard , + Chen-Yu Tsai , Michael Turquette , + Linus Walleij , + Rob Herring , Philipp Zabel , + =?UTF-8?q?Emilio=20L=C3=B3pez?= +Cc: devicetree@vger.kernel.org, Vishnu Patekar , + linux-kernel@vger.kernel.org, Hans de Goede , + linux-sunxi@googlegroups.com, Jens Kuske , + linux-arm-kernel@lists.infradead.org +Date: Tue, 27 Oct 2015 17:50:21 +0100 + +Currently, the sunxi clock driver gets the name for the base factor clock +of divs clocks from the name field in factors_data. This prevents reusing +of the factor clock for clocks with same properties, but different name. + +This commit makes the divs setup function try to get a name from +clock-output-names in the devicetree. It also removes the name field where +possible and merges the sun4i PLL5 and PLL6 clocks. + +Signed-off-by: Jens Kuske + +--- +drivers/clk/sunxi/clk-sunxi.c | 38 +++++++++++++++++++++++++++----------- + 1 file changed, 27 insertions(+), 11 deletions(-) + +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 9c79af0c..270de42 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -704,21 +704,12 @@ static const struct factors_data sun4i_pll5_data __initconst = { + .enable = 31, + .table = &sun4i_pll5_config, + .getter = sun4i_get_pll5_factors, +- .name = "pll5", +-}; +- +-static const struct factors_data sun4i_pll6_data __initconst = { +- .enable = 31, +- .table = &sun4i_pll5_config, +- .getter = sun4i_get_pll5_factors, +- .name = "pll6", + }; + + static const struct factors_data sun6i_a31_pll6_data __initconst = { + .enable = 31, + .table = &sun6i_a31_pll6_config, + .getter = sun6i_a31_get_pll6_factors, +- .name = "pll6x2", + }; + + static const struct factors_data sun5i_a13_ahb_data __initconst = { +@@ -902,6 +893,7 @@ struct gates_data { + + #define SUNXI_DIVS_MAX_QTY 4 + #define SUNXI_DIVISOR_WIDTH 2 ++#define SUNXI_DIVS_BASE_NAME_MAX_LEN 8 + + struct divs_data { + const struct factors_data *factors; /* data for the factor clock */ +@@ -941,7 +933,7 @@ static const struct divs_data pll5_divs_data __initconst = { + }; + + static const struct divs_data pll6_divs_data __initconst = { +- .factors = &sun4i_pll6_data, ++ .factors = &sun4i_pll5_data, + .ndivs = 4, + .div = { + { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */ +@@ -983,6 +975,8 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, + struct clk_gate *gate = NULL; + struct clk_fixed_factor *fix_factor; + struct clk_divider *divider; ++ struct factors_data factors = *data->factors; ++ char base_name[SUNXI_DIVS_BASE_NAME_MAX_LEN]; + void __iomem *reg; + int ndivs = SUNXI_DIVS_MAX_QTY, i = 0; + int flags, clkflags; +@@ -991,8 +985,30 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, + if (data->ndivs) + ndivs = data->ndivs; + ++ /* Try to find a name for base factor clock */ ++ for (i = 0; i < ndivs; i++) { ++ if (data->div[i].self) { ++ of_property_read_string_index(node, "clock-output-names", ++ i, &factors.name); ++ break; ++ } ++ } ++ /* If we don't have a .self clk use the first output-name up to '_' */ ++ if (factors.name == NULL) { ++ of_property_read_string_index(node, "clock-output-names", ++ 0, &clk_name); ++ ++ for (i = 0; i < SUNXI_DIVS_BASE_NAME_MAX_LEN - 1 && ++ clk_name[i] != '_' && ++ clk_name[i] != '\0'; i++) ++ base_name[i] = clk_name[i]; ++ ++ base_name[i] = '\0'; ++ factors.name = base_name; ++ } ++ + /* Set up factor clock that we will be dividing */ +- pclk = sunxi_factors_clk_setup(node, data->factors); ++ pclk = sunxi_factors_clk_setup(node, &factors); + parent = __clk_get_name(pclk); + + reg = of_iomap(node, 0); diff --git a/patch/kernel/h3-7498751.patch b/patch/kernel/h3-7498751.patch new file mode 100644 index 000000000..3167c4c25 --- /dev/null +++ b/patch/kernel/h3-7498751.patch @@ -0,0 +1,232 @@ +From patchwork Tue Oct 27 16:50:22 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,2/6] clk: sunxi: Add H3 clocks support +From: Jens Kuske +X-Patchwork-Id: 7498751 +Message-Id: <1445964626-6484-3-git-send-email-jenskuske@gmail.com> +To: Maxime Ripard , + Chen-Yu Tsai , Michael Turquette , + Linus Walleij , + Rob Herring , Philipp Zabel , + =?UTF-8?q?Emilio=20L=C3=B3pez?= +Cc: devicetree@vger.kernel.org, Vishnu Patekar , + linux-kernel@vger.kernel.org, Hans de Goede , + linux-sunxi@googlegroups.com, Jens Kuske , + linux-arm-kernel@lists.infradead.org +Date: Tue, 27 Oct 2015 17:50:22 +0100 + +The H3 clock control unit is similar to the those of other sun8i family +members like the A23. + +It adds a new bus gates clock similar to the simple gates, but with a +different parent clock for each single gate. +Some of the gates use the new AHB2 clock as parent, whose clock source +is muxable between AHB1 and PLL6/2. The documentation isn't totally clear +about which devices belong to AHB2 now, especially USB EHIC/OHIC, so it +is mostly based on Allwinner kernel source code. + +Signed-off-by: Jens Kuske + +--- +Documentation/devicetree/bindings/clock/sunxi.txt | 2 + + drivers/clk/sunxi/Makefile | 1 + + drivers/clk/sunxi/clk-sun8i-bus-gates.c | 111 ++++++++++++++++++++++ + drivers/clk/sunxi/clk-sunxi.c | 9 +- + 4 files changed, 122 insertions(+), 1 deletion(-) + create mode 100644 drivers/clk/sunxi/clk-sun8i-bus-gates.c + +diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt +index 8a47b77..d303dec 100644 +--- a/Documentation/devicetree/bindings/clock/sunxi.txt ++++ b/Documentation/devicetree/bindings/clock/sunxi.txt +@@ -28,6 +28,7 @@ Required properties: + "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20 + "allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31 + "allwinner,sun6i-a31-ahb1-clk" - for the AHB1 clock on A31 ++ "allwinner,sun8i-h3-ahb2-clk" - for the AHB2 clock on H3 + "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 + "allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23 + "allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80 +@@ -55,6 +56,7 @@ Required properties: + "allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80 + "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 + "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23 ++ "allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3 + "allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13 + "allwinner,sun4i-a10-mmc-clk" - for the MMC clock + "allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80 +diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile +index cb4c299..f520af6 100644 +--- a/drivers/clk/sunxi/Makefile ++++ b/drivers/clk/sunxi/Makefile +@@ -10,6 +10,7 @@ obj-y += clk-a10-pll2.o + obj-y += clk-a20-gmac.o + obj-y += clk-mod0.o + obj-y += clk-simple-gates.o ++obj-y += clk-sun8i-bus-gates.o + obj-y += clk-sun8i-mbus.o + obj-y += clk-sun9i-core.o + obj-y += clk-sun9i-mmc.o +diff --git a/drivers/clk/sunxi/clk-sun8i-bus-gates.c b/drivers/clk/sunxi/clk-sun8i-bus-gates.c +new file mode 100644 +index 0000000..ad605fa +--- /dev/null ++++ b/drivers/clk/sunxi/clk-sun8i-bus-gates.c +@@ -0,0 +1,111 @@ ++/* ++ * Copyright (C) 2015 Jens Kuske ++ * ++ * Based on clk-simple-gates.c, which is: ++ * Copyright 2015 Maxime Ripard ++ * ++ * Maxime Ripard ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static DEFINE_SPINLOCK(gates_lock); ++ ++static void __init sun8i_h3_bus_gates_init(struct device_node *node) ++{ ++ const char *clocks[] = { "ahb1", "ahb2", "apb1", "apb2" }; ++ enum { AHB1, AHB2, APB1, APB2 } clk_parent; ++ struct clk_onecell_data *clk_data; ++ const char *clk_name; ++ struct property *prop; ++ struct resource res; ++ void __iomem *clk_reg; ++ void __iomem *reg; ++ const __be32 *p; ++ int number, i; ++ u8 clk_bit; ++ u32 index; ++ ++ reg = of_io_request_and_map(node, 0, of_node_full_name(node)); ++ if (IS_ERR(reg)) ++ return; ++ ++ for (i = 0; i < ARRAY_SIZE(clocks); i++) { ++ index = of_property_match_string(node, "clock-names", clocks[i]); ++ if (index < 0) ++ return; ++ ++ clocks[i] = of_clk_get_parent_name(node, index); ++ } ++ ++ clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL); ++ if (!clk_data) ++ goto err_unmap; ++ ++ number = of_property_count_u32_elems(node, "clock-indices"); ++ of_property_read_u32_index(node, "clock-indices", number - 1, &number); ++ ++ clk_data->clks = kcalloc(number + 1, sizeof(struct clk *), GFP_KERNEL); ++ if (!clk_data->clks) ++ goto err_free_data; ++ ++ i = 0; ++ of_property_for_each_u32(node, "clock-indices", prop, p, index) { ++ of_property_read_string_index(node, "clock-output-names", ++ i, &clk_name); ++ ++ if (index == 17 || (index >= 29 && index <= 31)) ++ clk_parent = AHB2; ++ else if (index <= 63 || index >= 128) ++ clk_parent = AHB1; ++ else if (index >= 64 && index <= 95) ++ clk_parent = APB1; ++ else if (index >= 96 && index <= 127) ++ clk_parent = APB2; ++ ++ clk_reg = reg + 4 * (index / 32); ++ clk_bit = index % 32; ++ ++ clk_data->clks[index] = clk_register_gate(NULL, clk_name, ++ clocks[clk_parent], 0, ++ clk_reg, ++ clk_bit, ++ 0, &gates_lock); ++ i++; ++ ++ if (IS_ERR(clk_data->clks[index])) { ++ WARN_ON(true); ++ continue; ++ } ++ } ++ ++ clk_data->clk_num = number + 1; ++ of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ ++ return; ++ ++err_free_data: ++ kfree(clk_data); ++err_unmap: ++ iounmap(reg); ++ of_address_to_resource(node, 0, &res); ++ release_mem_region(res.start, resource_size(&res)); ++} ++ ++CLK_OF_DECLARE(sun8i_h3_bus_gates, "allwinner,sun8i-h3-bus-gates-clk", ++ sun8i_h3_bus_gates_init); +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 270de42..6293c65 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -769,6 +769,10 @@ static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = { + .shift = 12, + }; + ++static const struct mux_data sun8i_h3_ahb2_mux_data __initconst = { ++ .shift = 0, ++}; ++ + static void __init sunxi_mux_clk_setup(struct device_node *node, + struct mux_data *data) + { +@@ -945,10 +949,11 @@ static const struct divs_data pll6_divs_data __initconst = { + + static const struct divs_data sun6i_a31_pll6_divs_data __initconst = { + .factors = &sun6i_a31_pll6_data, +- .ndivs = 2, ++ .ndivs = 3, + .div = { + { .fixed = 2 }, /* normal output */ + { .self = 1 }, /* base factor clock, 2x */ ++ { .fixed = 4 }, /* divided output, /2 */ + } + }; + +@@ -1146,6 +1151,7 @@ static const struct of_device_id clk_divs_match[] __initconst = { + static const struct of_device_id clk_mux_match[] __initconst = { + {.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,}, + {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,}, ++ {.compatible = "allwinner,sun8i-h3-ahb2-clk", .data = &sun8i_h3_ahb2_mux_data,}, + {} + }; + +@@ -1228,6 +1234,7 @@ CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks); + CLK_OF_DECLARE(sun6i_a31s_clk_init, "allwinner,sun6i-a31s", sun6i_init_clocks); + CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks); + CLK_OF_DECLARE(sun8i_a33_clk_init, "allwinner,sun8i-a33", sun6i_init_clocks); ++CLK_OF_DECLARE(sun8i_h3_clk_init, "allwinner,sun8i-h3", sun6i_init_clocks); + + static void __init sun9i_init_clocks(struct device_node *node) + { diff --git a/patch/kernel/h3-7498761.patch b/patch/kernel/h3-7498761.patch new file mode 100644 index 000000000..eeaa6d398 --- /dev/null +++ b/patch/kernel/h3-7498761.patch @@ -0,0 +1,110 @@ +From patchwork Tue Oct 27 16:50:24 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,4/6] reset: sunxi: Add Allwinner H3 bus resets +From: Jens Kuske +X-Patchwork-Id: 7498761 +Message-Id: <1445964626-6484-5-git-send-email-jenskuske@gmail.com> +To: Maxime Ripard , + Chen-Yu Tsai , Michael Turquette , + Linus Walleij , + Rob Herring , Philipp Zabel , + =?UTF-8?q?Emilio=20L=C3=B3pez?= +Cc: devicetree@vger.kernel.org, Vishnu Patekar , + linux-kernel@vger.kernel.org, Hans de Goede , + linux-sunxi@googlegroups.com, Jens Kuske , + linux-arm-kernel@lists.infradead.org +Date: Tue, 27 Oct 2015 17:50:24 +0100 + +The H3 bus resets have some holes between the registers, so we add +an of_xlate() function to skip them according to the datasheet. + +Signed-off-by: Jens Kuske + +--- +.../bindings/reset/allwinner,sunxi-clock-reset.txt | 1 + + drivers/reset/reset-sunxi.c | 30 +++++++++++++++++++--- + 2 files changed, 28 insertions(+), 3 deletions(-) + +diff --git a/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt b/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt +index c8f7757..e11f023 100644 +--- a/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt ++++ b/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt +@@ -8,6 +8,7 @@ Required properties: + - compatible: Should be one of the following: + "allwinner,sun6i-a31-ahb1-reset" + "allwinner,sun6i-a31-clock-reset" ++ "allwinner,sun8i-h3-bus-reset" + - reg: should be register base and length as documented in the + datasheet + - #reset-cells: 1, see below +diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c +index 3d95c87..c91e146 100644 +--- a/drivers/reset/reset-sunxi.c ++++ b/drivers/reset/reset-sunxi.c +@@ -75,7 +75,9 @@ static struct reset_control_ops sunxi_reset_ops = { + .deassert = sunxi_reset_deassert, + }; + +-static int sunxi_reset_init(struct device_node *np) ++static int sunxi_reset_init(struct device_node *np, ++ int (*of_xlate)(struct reset_controller_dev *rcdev, ++ const struct of_phandle_args *reset_spec)) + { + struct sunxi_reset_data *data; + struct resource res; +@@ -108,6 +110,7 @@ static int sunxi_reset_init(struct device_node *np) + data->rcdev.nr_resets = size * 32; + data->rcdev.ops = &sunxi_reset_ops; + data->rcdev.of_node = np; ++ data->rcdev.of_xlate = of_xlate; + reset_controller_register(&data->rcdev); + + return 0; +@@ -117,6 +120,21 @@ err_alloc: + return ret; + }; + ++static int sun8i_h3_bus_reset_xlate(struct reset_controller_dev *rcdev, ++ const struct of_phandle_args *reset_spec) ++{ ++ unsigned int index = reset_spec->args[0]; ++ ++ if (index < 96) ++ return index; ++ else if (index < 128) ++ return index + 32; ++ else if (index < 160) ++ return index + 64; ++ else ++ return -EINVAL; ++} ++ + /* + * These are the reset controller we need to initialize early on in + * our system, before we can even think of using a regular device +@@ -124,15 +142,21 @@ err_alloc: + */ + static const struct of_device_id sunxi_early_reset_dt_ids[] __initdata = { + { .compatible = "allwinner,sun6i-a31-ahb1-reset", }, ++ { .compatible = "allwinner,sun8i-h3-bus-reset", .data = sun8i_h3_bus_reset_xlate, }, + { /* sentinel */ }, + }; + + void __init sun6i_reset_init(void) + { + struct device_node *np; ++ const struct of_device_id *match; ++ int (*of_xlate)(struct reset_controller_dev *rcdev, ++ const struct of_phandle_args *reset_spec); + +- for_each_matching_node(np, sunxi_early_reset_dt_ids) +- sunxi_reset_init(np); ++ for_each_matching_node_and_match(np, sunxi_early_reset_dt_ids, &match) { ++ of_xlate = match->data; ++ sunxi_reset_init(np, of_xlate); ++ } + } + + /* diff --git a/patch/kernel/h3-7498771.patch b/patch/kernel/h3-7498771.patch new file mode 100644 index 000000000..cb7ec49c4 --- /dev/null +++ b/patch/kernel/h3-7498771.patch @@ -0,0 +1,130 @@ +From patchwork Tue Oct 27 16:50:26 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,6/6] ARM: dts: sun8i: Add Orange Pi Plus support +From: Jens Kuske +X-Patchwork-Id: 7498771 +Message-Id: <1445964626-6484-7-git-send-email-jenskuske@gmail.com> +To: Maxime Ripard , + Chen-Yu Tsai , Michael Turquette , + Linus Walleij , + Rob Herring , Philipp Zabel , + =?UTF-8?q?Emilio=20L=C3=B3pez?= +Cc: devicetree@vger.kernel.org, Vishnu Patekar , + linux-kernel@vger.kernel.org, Hans de Goede , + linux-sunxi@googlegroups.com, Jens Kuske , + linux-arm-kernel@lists.infradead.org +Date: Tue, 27 Oct 2015 17:50:26 +0100 + +The Orange Pi Plus is a SBC based on the Allwinner H3 SoC +with 8GB eMMC, multiple USB ports through a USB hub chip, SATA through +a USB-SATA bridge, one uSD slot, a 10/100/1000M ethernet port, +WiFi, HDMI, headphone jack, IR receiver, a microphone, a CSI connector +and a 40-pin GPIO header. + +Signed-off-by: Jens Kuske + +--- +arch/arm/boot/dts/Makefile | 3 +- + arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 77 ++++++++++++++++++++++++++++ + 2 files changed, 79 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts + +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index 78ade1a..476658d 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -645,7 +645,8 @@ dtb-$(CONFIG_MACH_SUN8I) += \ + sun8i-a33-ga10h-v1.1.dtb \ + sun8i-a33-ippo-q8h-v1.2.dtb \ + sun8i-a33-q8-tablet.dtb \ +- sun8i-a33-sinlinx-sina33.dtb ++ sun8i-a33-sinlinx-sina33.dtb \ ++ sun8i-h3-orangepi-plus.dtb + dtb-$(CONFIG_MACH_SUN9I) += \ + sun9i-a80-optimus.dtb \ + sun9i-a80-cubieboard4.dtb +diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts +new file mode 100644 +index 0000000..e67df59 +--- /dev/null ++++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (C) 2015 Jens Kuske ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This file is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++#include "sun8i-h3.dtsi" ++#include "sunxi-common-regulators.dtsi" ++ ++#include ++#include ++ ++/ { ++ model = "Xunlong Orange Pi Plus"; ++ compatible = "xunlong,orangepi-plus", "allwinner,sun8i-h3"; ++ ++ aliases { ++ serial0 = &uart0; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++}; ++ ++&mmc0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>; ++ vmmc-supply = <®_vcc3v3>; ++ bus-width = <4>; ++ cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */ ++ cd-inverted; ++ status = "okay"; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins_a>; ++ status = "okay"; ++}; diff --git a/patch/kernel/h3-7498831.patch b/patch/kernel/h3-7498831.patch new file mode 100644 index 000000000..13d1e94cf --- /dev/null +++ b/patch/kernel/h3-7498831.patch @@ -0,0 +1,592 @@ +From patchwork Tue Oct 27 16:50:23 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,3/6] pinctrl: sunxi: Add H3 PIO controller support +From: Jens Kuske +X-Patchwork-Id: 7498831 +Message-Id: <1445964626-6484-4-git-send-email-jenskuske@gmail.com> +To: Maxime Ripard , + Chen-Yu Tsai , Michael Turquette , + Linus Walleij , + Rob Herring , Philipp Zabel , + =?UTF-8?q?Emilio=20L=C3=B3pez?= +Cc: devicetree@vger.kernel.org, Vishnu Patekar , + linux-kernel@vger.kernel.org, Hans de Goede , + linux-sunxi@googlegroups.com, Jens Kuske , + linux-arm-kernel@lists.infradead.org +Date: Tue, 27 Oct 2015 17:50:23 +0100 + +The H3 uses the same pin controller as previous SoC's from Allwinner. +Add support for the pins controlled by the main PIO controller. + +Signed-off-by: Jens Kuske +Acked-by: Maxime Ripard + +--- +.../bindings/pinctrl/allwinner,sunxi-pinctrl.txt | 1 + + drivers/pinctrl/sunxi/Kconfig | 4 + + drivers/pinctrl/sunxi/Makefile | 1 + + drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c | 516 +++++++++++++++++++++ + 4 files changed, 522 insertions(+) + create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c + +diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt +index b321b26..e6ba602 100644 +--- a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt ++++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt +@@ -18,6 +18,7 @@ Required properties: + "allwinner,sun8i-a23-r-pinctrl" + "allwinner,sun8i-a33-pinctrl" + "allwinner,sun8i-a83t-pinctrl" ++ "allwinner,sun8i-h3-pinctrl" + + - reg: Should contain the register physical address and length for the + pin controller. +diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig +index e68fd95..89ab7f5 100644 +--- a/drivers/pinctrl/sunxi/Kconfig ++++ b/drivers/pinctrl/sunxi/Kconfig +@@ -51,6 +51,10 @@ config PINCTRL_SUN8I_A23_R + depends on RESET_CONTROLLER + select PINCTRL_SUNXI_COMMON + ++config PINCTRL_SUN8I_H3 ++ def_bool MACH_SUN8I ++ select PINCTRL_SUNXI_COMMON ++ + config PINCTRL_SUN9I_A80 + def_bool MACH_SUN9I + select PINCTRL_SUNXI_COMMON +diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile +index e080290..6bd818e 100644 +--- a/drivers/pinctrl/sunxi/Makefile ++++ b/drivers/pinctrl/sunxi/Makefile +@@ -13,4 +13,5 @@ obj-$(CONFIG_PINCTRL_SUN8I_A23) += pinctrl-sun8i-a23.o + obj-$(CONFIG_PINCTRL_SUN8I_A23_R) += pinctrl-sun8i-a23-r.o + obj-$(CONFIG_PINCTRL_SUN8I_A33) += pinctrl-sun8i-a33.o + obj-$(CONFIG_PINCTRL_SUN8I_A83T) += pinctrl-sun8i-a83t.o ++obj-$(CONFIG_PINCTRL_SUN8I_H3) += pinctrl-sun8i-h3.o + obj-$(CONFIG_PINCTRL_SUN9I_A80) += pinctrl-sun9i-a80.o +diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c +new file mode 100644 +index 0000000..98d465d +--- /dev/null ++++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c +@@ -0,0 +1,516 @@ ++/* ++ * Allwinner H3 SoCs pinctrl driver. ++ * ++ * Copyright (C) 2015 Jens Kuske ++ * ++ * Based on pinctrl-sun8i-a23.c, which is: ++ * Copyright (C) 2014 Chen-Yu Tsai ++ * Copyright (C) 2014 Maxime Ripard ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "pinctrl-sunxi.h" ++ ++static const struct sunxi_desc_pin sun8i_h3_pins[] = { ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart2"), /* TX */ ++ SUNXI_FUNCTION(0x3, "jtag"), /* MS */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PA_EINT0 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart2"), /* RX */ ++ SUNXI_FUNCTION(0x3, "jtag"), /* CK */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PA_EINT1 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart2"), /* RTS */ ++ SUNXI_FUNCTION(0x3, "jtag"), /* DO */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)), /* PA_EINT2 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart2"), /* CTS */ ++ SUNXI_FUNCTION(0x3, "jtag"), /* DI */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)), /* PA_EINT3 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart0"), /* TX */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)), /* PA_EINT4 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart0"), /* RX */ ++ SUNXI_FUNCTION(0x3, "pwm0"), ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)), /* PA_EINT5 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "sim"), /* PWREN */ ++ SUNXI_FUNCTION(0x3, "pwm1"), ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)), /* PA_EINT6 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "sim"), /* CLK */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)), /* PA_EINT7 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "sim"), /* DATA */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)), /* PA_EINT8 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "sim"), /* RST */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)), /* PA_EINT9 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "sim"), /* DET */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 10)), /* PA_EINT10 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2c0"), /* SCK */ ++ SUNXI_FUNCTION(0x3, "di"), /* TX */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 11)), /* PA_EINT11 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2c0"), /* SDA */ ++ SUNXI_FUNCTION(0x3, "di"), /* RX */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 12)), /* PA_EINT12 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 13), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "spi1"), /* CS */ ++ SUNXI_FUNCTION(0x3, "uart3"), /* TX */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 13)), /* PA_EINT13 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 14), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "spi1"), /* CLK */ ++ SUNXI_FUNCTION(0x3, "uart3"), /* RX */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 14)), /* PA_EINT14 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 15), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "spi1"), /* MOSI */ ++ SUNXI_FUNCTION(0x3, "uart3"), /* RTS */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 15)), /* PA_EINT15 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "spi1"), /* MISO */ ++ SUNXI_FUNCTION(0x3, "uart3"), /* CTS */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 16)), /* PA_EINT16 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "spdif"), /* OUT */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 17)), /* PA_EINT17 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s0"), /* SYNC */ ++ SUNXI_FUNCTION(0x3, "i2c1"), /* SCK */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 18)), /* PA_EINT18 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s0"), /* CLK */ ++ SUNXI_FUNCTION(0x3, "i2c1"), /* SDA */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 19)), /* PA_EINT19 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 20), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s0"), /* DOUT */ ++ SUNXI_FUNCTION(0x3, "sim"), /* VPPEN */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 20)), /* PA_EINT20 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 21), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s0"), /* DIN */ ++ SUNXI_FUNCTION(0x3, "sim"), /* VPPPP */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 21)), /* PA_EINT21 */ ++ /* Hole */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* WE */ ++ SUNXI_FUNCTION(0x3, "spi0")), /* MOSI */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* ALE */ ++ SUNXI_FUNCTION(0x3, "spi0")), /* MISO */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* CLE */ ++ SUNXI_FUNCTION(0x3, "spi0")), /* CLK */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* CE1 */ ++ SUNXI_FUNCTION(0x3, "spi0")), /* CS */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0")), /* CE0 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* RE */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* CLK */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* RB0 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* CMD */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0")), /* RB1 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* DQ0 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D0 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* DQ1 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D1 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* DQ2 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D2 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* DQ3 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D3 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 12), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* DQ4 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D4 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 13), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* DQ5 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D5 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand"), /* DQ6 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D6 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand"), /* DQ7 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D7 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 16), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand"), /* DQS */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* RST */ ++ /* Hole */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* RXD3 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* RXD2 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* RXD1 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* RXD0 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* RXCK */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* RXCTL/RCDV */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* RXERR */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* TXD3 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* TXD2L */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* TXD1 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* TXD0 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* CRS */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* TXCK */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* TXCTL/TXEN */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* TXERR */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* CLKIN/COL */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* MDC */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* MDIO */ ++ /* Hole */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* PCLK */ ++ SUNXI_FUNCTION(0x3, "ts")), /* CLK */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* MCLK */ ++ SUNXI_FUNCTION(0x3, "ts")), /* ERR */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* HSYNC */ ++ SUNXI_FUNCTION(0x3, "ts")), /* SYNC */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* VSYNC */ ++ SUNXI_FUNCTION(0x3, "ts")), /* DVLD */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D0 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D0 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D1 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D1 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D2 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D2 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D3 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D3 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D4 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D4 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D5 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D5 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D6 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D6 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D7 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D7 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* SCK */ ++ SUNXI_FUNCTION(0x3, "i2c2")), /* SCK */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* SDA */ ++ SUNXI_FUNCTION(0x3, "i2c2")), /* SDA */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out")), ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out")), ++ /* Hole */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc0"), /* D1 */ ++ SUNXI_FUNCTION(0x3, "jtag")), /* MS */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc0"), /* D0 */ ++ SUNXI_FUNCTION(0x3, "jtag")), /* DI */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc0"), /* CLK */ ++ SUNXI_FUNCTION(0x3, "uart0")), /* TX */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc0"), /* CMD */ ++ SUNXI_FUNCTION(0x3, "jtag")), /* DO */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc0"), /* D3 */ ++ SUNXI_FUNCTION(0x3, "uart0")), /* RX */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc0"), /* D2 */ ++ SUNXI_FUNCTION(0x3, "jtag")), /* CK */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc0")), /* DET */ ++ /* Hole */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc1"), /* CLK */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 0)), /* PG_EINT0 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc1"), /* CMD */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 1)), /* PG_EINT1 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc1"), /* D0 */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 2)), /* PG_EINT2 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc1"), /* D1 */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 3)), /* PG_EINT3 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc1"), /* D2 */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 4)), /* PG_EINT4 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc1"), /* D3 */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 5)), /* PG_EINT5 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart1"), /* TX */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 6)), /* PG_EINT6 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart1"), /* RX */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 7)), /* PG_EINT7 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart1"), /* RTS */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 8)), /* PG_EINT8 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart1"), /* CTS */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 9)), /* PG_EINT9 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s1"), /* SYNC */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 10)), /* PG_EINT10 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s1"), /* CLK */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 11)), /* PG_EINT11 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s1"), /* DOUT */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 12)), /* PG_EINT12 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s1"), /* DIN */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 13)), /* PG_EINT13 */ ++}; ++ ++static const struct sunxi_pinctrl_desc sun8i_h3_pinctrl_data = { ++ .pins = sun8i_h3_pins, ++ .npins = ARRAY_SIZE(sun8i_h3_pins), ++ .irq_banks = 2, ++}; ++ ++static int sun8i_h3_pinctrl_probe(struct platform_device *pdev) ++{ ++ return sunxi_pinctrl_init(pdev, ++ &sun8i_h3_pinctrl_data); ++} ++ ++static const struct of_device_id sun8i_h3_pinctrl_match[] = { ++ { .compatible = "allwinner,sun8i-h3-pinctrl", }, ++ {} ++}; ++ ++static struct platform_driver sun8i_h3_pinctrl_driver = { ++ .probe = sun8i_h3_pinctrl_probe, ++ .driver = { ++ .name = "sun8i-h3-pinctrl", ++ .of_match_table = sun8i_h3_pinctrl_match, ++ }, ++}; ++builtin_platform_driver(sun8i_h3_pinctrl_driver); diff --git a/patch/kernel/h3-7498891.patch b/patch/kernel/h3-7498891.patch new file mode 100644 index 000000000..0aef469e3 --- /dev/null +++ b/patch/kernel/h3-7498891.patch @@ -0,0 +1,517 @@ +From patchwork Tue Oct 27 16:50:25 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v4,5/6] ARM: dts: sunxi: Add Allwinner H3 DTSI +From: Jens Kuske +X-Patchwork-Id: 7498891 +Message-Id: <1445964626-6484-6-git-send-email-jenskuske@gmail.com> +To: Maxime Ripard , + Chen-Yu Tsai , Michael Turquette , + Linus Walleij , + Rob Herring , Philipp Zabel , + =?UTF-8?q?Emilio=20L=C3=B3pez?= +Cc: devicetree@vger.kernel.org, Vishnu Patekar , + linux-kernel@vger.kernel.org, Hans de Goede , + linux-sunxi@googlegroups.com, Jens Kuske , + linux-arm-kernel@lists.infradead.org +Date: Tue, 27 Oct 2015 17:50:25 +0100 + +The Allwinner H3 is a home entertainment system oriented SoC with +four Cortex-A7 cores and a Mali-400MP2 GPU. + +Signed-off-by: Jens Kuske + +--- +arch/arm/boot/dts/sun8i-h3.dtsi | 482 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 482 insertions(+) + create mode 100644 arch/arm/boot/dts/sun8i-h3.dtsi + +diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi +new file mode 100644 +index 0000000..c18b5f7 +--- /dev/null ++++ b/arch/arm/boot/dts/sun8i-h3.dtsi +@@ -0,0 +1,482 @@ ++/* ++ * Copyright (C) 2015 Jens Kuske ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This file is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include "skeleton.dtsi" ++ ++#include ++#include ++ ++/ { ++ interrupt-parent = <&gic>; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ reg = <0>; ++ }; ++ ++ cpu@1 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ reg = <1>; ++ }; ++ ++ cpu@2 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ reg = <2>; ++ }; ++ ++ cpu@3 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ reg = <3>; ++ }; ++ }; ++ ++ timer { ++ compatible = "arm,armv7-timer"; ++ interrupts = , ++ , ++ , ++ ; ++ clock-frequency = <24000000>; ++ arm,cpu-registers-not-fw-configured; ++ }; ++ ++ memory { ++ reg = <0x40000000 0x80000000>; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ osc24M: osc24M_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <24000000>; ++ clock-output-names = "osc24M"; ++ }; ++ ++ osc32k: osc32k_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ clock-output-names = "osc32k"; ++ }; ++ ++ pll1: clk@01c20000 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun8i-a23-pll1-clk"; ++ reg = <0x01c20000 0x4>; ++ clocks = <&osc24M>; ++ clock-output-names = "pll1"; ++ }; ++ ++ /* dummy clock until actually implemented */ ++ pll5: pll5_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++ clock-output-names = "pll5"; ++ }; ++ ++ pll6: clk@01c20028 { ++ #clock-cells = <1>; ++ compatible = "allwinner,sun6i-a31-pll6-clk"; ++ reg = <0x01c20028 0x4>; ++ clocks = <&osc24M>; ++ clock-output-names = "pll6", "pll6x2", "pll6d2"; ++ }; ++ ++ pll8: clk@01c20044 { ++ #clock-cells = <1>; ++ compatible = "allwinner,sun6i-a31-pll6-clk"; ++ reg = <0x01c20044 0x4>; ++ clocks = <&osc24M>; ++ clock-output-names = "pll8", "pll8x2"; ++ }; ++ ++ cpu: cpu_clk@01c20050 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-cpu-clk"; ++ reg = <0x01c20050 0x4>; ++ clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>; ++ clock-output-names = "cpu"; ++ }; ++ ++ axi: axi_clk@01c20050 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-axi-clk"; ++ reg = <0x01c20050 0x4>; ++ clocks = <&cpu>; ++ clock-output-names = "axi"; ++ }; ++ ++ ahb1: ahb1_clk@01c20054 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun6i-a31-ahb1-clk"; ++ reg = <0x01c20054 0x4>; ++ clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>; ++ clock-output-names = "ahb1"; ++ }; ++ ++ ahb2: ahb2_clk@01c2005c { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun8i-h3-ahb2-clk"; ++ reg = <0x01c2005c 0x4>; ++ clocks = <&ahb1>, <&pll6 2>; ++ clock-output-names = "ahb2"; ++ }; ++ ++ apb1: apb1_clk@01c20054 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-apb0-clk"; ++ reg = <0x01c20054 0x4>; ++ clocks = <&ahb1>; ++ clock-output-names = "apb1"; ++ }; ++ ++ apb2: apb2_clk@01c20058 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-apb1-clk"; ++ reg = <0x01c20058 0x4>; ++ clocks = <&osc32k>, <&osc24M>, <&pll6 0>, <&pll6 0>; ++ clock-output-names = "apb2"; ++ }; ++ ++ bus_gates: clk@01c20060 { ++ #clock-cells = <1>; ++ compatible = "allwinner,sun8i-h3-bus-gates-clk"; ++ reg = <0x01c20060 0x14>; ++ clocks = <&ahb1>, <&ahb2>, <&apb1>, <&apb2>; ++ clock-names = "ahb1", "ahb2", "apb1", "apb2"; ++ clock-indices = <5>, <6>, <8>, ++ <9>, <10>, <13>, ++ <14>, <17>, <18>, ++ <19>, <20>, ++ <21>, <23>, ++ <24>, <25>, ++ <26>, <27>, ++ <28>, <29>, ++ <30>, <31>, <32>, ++ <35>, <36>, <37>, ++ <40>, <41>, <43>, ++ <44>, <52>, <53>, ++ <54>, <64>, ++ <65>, <69>, <72>, ++ <76>, <77>, <78>, ++ <96>, <97>, <98>, ++ <112>, <113>, ++ <114>, <115>, <116>, ++ <128>, <135>; ++ clock-output-names = "ahb1_ce", "ahb1_dma", "ahb1_mmc0", ++ "ahb1_mmc1", "ahb1_mmc2", "ahb1_nand", ++ "ahb1_sdram", "ahb2_gmac", "ahb1_ts", ++ "ahb1_hstimer", "ahb1_spi0", ++ "ahb1_spi1", "ahb1_otg", ++ "ahb1_otg_ehci0", "ahb1_ehic1", ++ "ahb1_ehic2", "ahb1_ehic3", ++ "ahb1_otg_ohci0", "ahb2_ohic1", ++ "ahb2_ohic2", "ahb2_ohic3", "ahb1_ve", ++ "ahb1_lcd0", "ahb1_lcd1", "ahb1_deint", ++ "ahb1_csi", "ahb1_tve", "ahb1_hdmi", ++ "ahb1_de", "ahb1_gpu", "ahb1_msgbox", ++ "ahb1_spinlock", "apb1_codec", ++ "apb1_spdif", "apb1_pio", "apb1_ths", ++ "apb1_i2s0", "apb1_i2s1", "apb1_i2s2", ++ "apb2_i2c0", "apb2_i2c1", "apb2_i2c2", ++ "apb2_uart0", "apb2_uart1", ++ "apb2_uart2", "apb2_uart3", "apb2_scr", ++ "ahb1_ephy", "ahb1_dbg"; ++ }; ++ ++ mmc0_clk: clk@01c20088 { ++ #clock-cells = <1>; ++ compatible = "allwinner,sun4i-a10-mmc-clk"; ++ reg = <0x01c20088 0x4>; ++ clocks = <&osc24M>, <&pll6 0>, <&pll8 0>; ++ clock-output-names = "mmc0", ++ "mmc0_output", ++ "mmc0_sample"; ++ }; ++ ++ mmc1_clk: clk@01c2008c { ++ #clock-cells = <1>; ++ compatible = "allwinner,sun4i-a10-mmc-clk"; ++ reg = <0x01c2008c 0x4>; ++ clocks = <&osc24M>, <&pll6 0>, <&pll8 0>; ++ clock-output-names = "mmc1", ++ "mmc1_output", ++ "mmc1_sample"; ++ }; ++ ++ mmc2_clk: clk@01c20090 { ++ #clock-cells = <1>; ++ compatible = "allwinner,sun4i-a10-mmc-clk"; ++ reg = <0x01c20090 0x4>; ++ clocks = <&osc24M>, <&pll6 0>, <&pll8 0>; ++ clock-output-names = "mmc2", ++ "mmc2_output", ++ "mmc2_sample"; ++ }; ++ ++ mbus_clk: clk@01c2015c { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun8i-a23-mbus-clk"; ++ reg = <0x01c2015c 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5>; ++ clock-output-names = "mbus"; ++ }; ++ }; ++ ++ soc { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ dma: dma-controller@01c02000 { ++ compatible = "allwinner,sun8i-h3-dma"; ++ reg = <0x01c02000 0x1000>; ++ interrupts = ; ++ clocks = <&bus_gates 6>; ++ resets = <&bus_rst 6>; ++ #dma-cells = <1>; ++ }; ++ ++ mmc0: mmc@01c0f000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c0f000 0x1000>; ++ clocks = <&bus_gates 8>, ++ <&mmc0_clk 0>, ++ <&mmc0_clk 1>, ++ <&mmc0_clk 2>; ++ clock-names = "ahb", ++ "mmc", ++ "output", ++ "sample"; ++ resets = <&bus_rst 8>; ++ reset-names = "ahb"; ++ interrupts = ; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ mmc1: mmc@01c10000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c10000 0x1000>; ++ clocks = <&bus_gates 9>, ++ <&mmc1_clk 0>, ++ <&mmc1_clk 1>, ++ <&mmc1_clk 2>; ++ clock-names = "ahb", ++ "mmc", ++ "output", ++ "sample"; ++ resets = <&bus_rst 9>; ++ reset-names = "ahb"; ++ interrupts = ; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ mmc2: mmc@01c11000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c11000 0x1000>; ++ clocks = <&bus_gates 10>, ++ <&mmc2_clk 0>, ++ <&mmc2_clk 1>, ++ <&mmc2_clk 2>; ++ clock-names = "ahb", ++ "mmc", ++ "output", ++ "sample"; ++ resets = <&bus_rst 10>; ++ reset-names = "ahb"; ++ interrupts = ; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ pio: pinctrl@01c20800 { ++ compatible = "allwinner,sun8i-h3-pinctrl"; ++ reg = <0x01c20800 0x400>; ++ interrupts = , ++ ; ++ clocks = <&bus_gates 69>; ++ gpio-controller; ++ #gpio-cells = <3>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ++ uart0_pins_a: uart0@0 { ++ allwinner,pins = "PA4", "PA5"; ++ allwinner,function = "uart0"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++ ++ mmc0_pins_a: mmc0@0 { ++ allwinner,pins = "PF0", "PF1", "PF2", "PF3", ++ "PF4", "PF5"; ++ allwinner,function = "mmc0"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++ ++ mmc0_cd_pin: mmc0_cd_pin@0 { ++ allwinner,pins = "PF6"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++ ++ mmc1_pins_a: mmc1@0 { ++ allwinner,pins = "PG0", "PG1", "PG2", "PG3", ++ "PG4", "PG5"; ++ allwinner,function = "mmc1"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++ }; ++ ++ bus_rst: reset@01c202c0 { ++ #reset-cells = <1>; ++ compatible = "allwinner,sun8i-h3-bus-reset"; ++ reg = <0x01c202c0 0x1c>; ++ }; ++ ++ timer@01c20c00 { ++ compatible = "allwinner,sun4i-a10-timer"; ++ reg = <0x01c20c00 0xa0>; ++ interrupts = , ++ ; ++ clocks = <&osc24M>; ++ }; ++ ++ wdt0: watchdog@01c20ca0 { ++ compatible = "allwinner,sun6i-a31-wdt"; ++ reg = <0x01c20ca0 0x20>; ++ interrupts = ; ++ }; ++ ++ uart0: serial@01c28000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x01c28000 0x400>; ++ interrupts = ; ++ reg-shift = <2>; ++ reg-io-width = <4>; ++ clocks = <&bus_gates 112>; ++ resets = <&bus_rst 144>; ++ dmas = <&dma 6>, <&dma 6>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; ++ ++ uart1: serial@01c28400 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x01c28400 0x400>; ++ interrupts = ; ++ reg-shift = <2>; ++ reg-io-width = <4>; ++ clocks = <&bus_gates 113>; ++ resets = <&bus_rst 145>; ++ dmas = <&dma 7>, <&dma 7>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; ++ ++ uart2: serial@01c28800 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x01c28800 0x400>; ++ interrupts = ; ++ reg-shift = <2>; ++ reg-io-width = <4>; ++ clocks = <&bus_gates 114>; ++ resets = <&bus_rst 146>; ++ dmas = <&dma 8>, <&dma 8>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; ++ ++ uart3: serial@01c28c00 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x01c28c00 0x400>; ++ interrupts = ; ++ reg-shift = <2>; ++ reg-io-width = <4>; ++ clocks = <&bus_gates 115>; ++ resets = <&bus_rst 147>; ++ dmas = <&dma 9>, <&dma 9>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; ++ ++ gic: interrupt-controller@01c81000 { ++ compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic"; ++ reg = <0x01c81000 0x1000>, ++ <0x01c82000 0x1000>, ++ <0x01c84000 0x2000>, ++ <0x01c86000 0x2000>; ++ interrupt-controller; ++ #interrupt-cells = <3>; ++ interrupts = ; ++ }; ++ ++ rtc: rtc@01f00000 { ++ compatible = "allwinner,sun6i-a31-rtc"; ++ reg = <0x01f00000 0x54>; ++ interrupts = , ++ ; ++ }; ++ }; ++}; diff --git a/patch/kernel/headers-debian-byteshift.patch b/patch/kernel/headers-debian-byteshift.patch new file mode 100644 index 000000000..ef375ff66 --- /dev/null +++ b/patch/kernel/headers-debian-byteshift.patch @@ -0,0 +1,156 @@ +Signed-off-by: Matt Fleming +Link: http://lkml.kernel.org/r/1330436245-24875-2-git-send-email-matt@console-pimps.org +Signed-off-by: H. Peter Anvin +Signed-off-by: Greg Kroah-Hartman + +--- +tools/include/tools/be_byteshift.h | 70 +++++++++++++++++++++++++++++++++++++ +tools/include/tools/le_byteshift.h | 70 +++++++++++++++++++++++++++++++++++++ +2 files changed, 140 insertions(+) + +--- /dev/null ++++ b/tools/include/tools/be_byteshift.h +@@ -0,0 +1,70 @@ ++#ifndef _TOOLS_BE_BYTESHIFT_H ++#define _TOOLS_BE_BYTESHIFT_H ++ ++#include ++ ++static inline __u16 __get_unaligned_be16(const __u8 *p) ++{ ++ return p[0] << 8 | p[1]; ++} ++ ++static inline __u32 __get_unaligned_be32(const __u8 *p) ++{ ++ return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; ++} ++ ++static inline __u64 __get_unaligned_be64(const __u8 *p) ++{ ++ return (__u64)__get_unaligned_be32(p) << 32 | ++ __get_unaligned_be32(p + 4); ++} ++ ++static inline void __put_unaligned_be16(__u16 val, __u8 *p) ++{ ++ *p++ = val >> 8; ++ *p++ = val; ++} ++ ++static inline void __put_unaligned_be32(__u32 val, __u8 *p) ++{ ++ __put_unaligned_be16(val >> 16, p); ++ __put_unaligned_be16(val, p + 2); ++} ++ ++static inline void __put_unaligned_be64(__u64 val, __u8 *p) ++{ ++ __put_unaligned_be32(val >> 32, p); ++ __put_unaligned_be32(val, p + 4); ++} ++ ++static inline __u16 get_unaligned_be16(const void *p) ++{ ++ return __get_unaligned_be16((const __u8 *)p); ++} ++ ++static inline __u32 get_unaligned_be32(const void *p) ++{ ++ return __get_unaligned_be32((const __u8 *)p); ++} ++ ++static inline __u64 get_unaligned_be64(const void *p) ++{ ++ return __get_unaligned_be64((const __u8 *)p); ++} ++ ++static inline void put_unaligned_be16(__u16 val, void *p) ++{ ++ __put_unaligned_be16(val, p); ++} ++ ++static inline void put_unaligned_be32(__u32 val, void *p) ++{ ++ __put_unaligned_be32(val, p); ++} ++ ++static inline void put_unaligned_be64(__u64 val, void *p) ++{ ++ __put_unaligned_be64(val, p); ++} ++ ++#endif /* _TOOLS_BE_BYTESHIFT_H */ +--- /dev/null ++++ b/tools/include/tools/le_byteshift.h +@@ -0,0 +1,70 @@ ++#ifndef _TOOLS_LE_BYTESHIFT_H ++#define _TOOLS_LE_BYTESHIFT_H ++ ++#include ++ ++static inline __u16 __get_unaligned_le16(const __u8 *p) ++{ ++ return p[0] | p[1] << 8; ++} ++ ++static inline __u32 __get_unaligned_le32(const __u8 *p) ++{ ++ return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; ++} ++ ++static inline __u64 __get_unaligned_le64(const __u8 *p) ++{ ++ return (__u64)__get_unaligned_le32(p + 4) << 32 | ++ __get_unaligned_le32(p); ++} ++ ++static inline void __put_unaligned_le16(__u16 val, __u8 *p) ++{ ++ *p++ = val; ++ *p++ = val >> 8; ++} ++ ++static inline void __put_unaligned_le32(__u32 val, __u8 *p) ++{ ++ __put_unaligned_le16(val >> 16, p + 2); ++ __put_unaligned_le16(val, p); ++} ++ ++static inline void __put_unaligned_le64(__u64 val, __u8 *p) ++{ ++ __put_unaligned_le32(val >> 32, p + 4); ++ __put_unaligned_le32(val, p); ++} ++ ++static inline __u16 get_unaligned_le16(const void *p) ++{ ++ return __get_unaligned_le16((const __u8 *)p); ++} ++ ++static inline __u32 get_unaligned_le32(const void *p) ++{ ++ return __get_unaligned_le32((const __u8 *)p); ++} ++ ++static inline __u64 get_unaligned_le64(const void *p) ++{ ++ return __get_unaligned_le64((const __u8 *)p); ++} ++ ++static inline void put_unaligned_le16(__u16 val, void *p) ++{ ++ __put_unaligned_le16(val, p); ++} ++ ++static inline void put_unaligned_le32(__u32 val, void *p) ++{ ++ __put_unaligned_le32(val, p); ++} ++ ++static inline void put_unaligned_le64(__u64 val, void *p) ++{ ++ __put_unaligned_le64(val, p); ++} ++ ++#endif /* _TOOLS_LE_BYTESHIFT_H */ diff --git a/patch/kernel/legacy-logo.patch b/patch/kernel/legacy-logo.patch new file mode 100644 index 000000000..a9348a69d --- /dev/null +++ b/patch/kernel/legacy-logo.patch @@ -0,0 +1,15377 @@ +From 12764804c214085d4c37473c5f6566761134c44e Mon Sep 17 00:00:00 2001 +From: michalliu +Date: Mon, 28 Apr 2014 01:30:42 +0800 +Subject: [PATCH 1/3] Add Cubian logo + +--- + drivers/video/logo/Kconfig | 5 + + drivers/video/logo/Makefile | 1 + + drivers/video/logo/logo.c | 5 + + drivers/video/logo/logo_cubian_clut224.ppm | 8733 ++++++++++++++++++++++++++++ + 4 files changed, 8744 insertions(+) + create mode 100644 drivers/video/logo/logo_cubian_clut224.ppm + +diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig +index 39ac49e..2ee8966 100644 +--- a/drivers/video/logo/Kconfig ++++ b/drivers/video/logo/Kconfig +@@ -82,4 +82,9 @@ config LOGO_M32R_CLUT224 + depends on M32R + default y + ++config LOGO_CUBIAN_CLUT224 ++ bool "224-color Cubian Linux logo" ++ depends on ARCH_SUN4I || ARCH_SUN7I ++ default y ++ + endif # LOGO +diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile +index 3b43781..394a735 100644 +--- a/drivers/video/logo/Makefile ++++ b/drivers/video/logo/Makefile +@@ -15,6 +15,7 @@ obj-$(CONFIG_LOGO_SUPERH_MONO) += logo_superh_mono.o + obj-$(CONFIG_LOGO_SUPERH_VGA16) += logo_superh_vga16.o + obj-$(CONFIG_LOGO_SUPERH_CLUT224) += logo_superh_clut224.o + obj-$(CONFIG_LOGO_M32R_CLUT224) += logo_m32r_clut224.o ++obj-$(CONFIG_LOGO_CUBIAN_CLUT224) += logo_cubian_clut224.o + + obj-$(CONFIG_SPU_BASE) += logo_spe_clut224.o + +diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c +index 080c35b..0413e80 100644 +--- a/drivers/video/logo/logo.c ++++ b/drivers/video/logo/logo.c +@@ -32,6 +32,7 @@ MODULE_PARM_DESC(nologo, "Disables startup logo"); + const struct linux_logo * __init_refok fb_find_logo(int depth) + { + const struct linux_logo *logo = NULL; ++ extern const struct linux_logo logo_cubian_clut224; + + if (nologo) + return NULL; +@@ -100,6 +101,10 @@ const struct linux_logo * __init_refok fb_find_logo(int depth) + /* M32R Linux logo */ + logo = &logo_m32r_clut224; + #endif ++#ifdef CONFIG_LOGO_CUBIAN_CLUT224 ++ /* Cubian Linux logo */ ++ logo = &logo_cubian_clut224; ++#endif + } + return logo; + } +diff --git a/drivers/video/logo/logo_cubian_clut224.ppm b/drivers/video/logo/logo_cubian_clut224.ppm +new file mode 100644 +index 0000000..6d2ebeb +--- /dev/null ++++ b/drivers/video/logo/logo_cubian_clut224.ppm +@@ -0,0 +1,8733 @@ ++P3 ++180 291 ++255 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 8 3 5 0 0 0 ++0 0 0 0 0 0 35 9 18 100 5 39 64 24 39 21 8 12 ++19 7 11 54 21 33 78 24 43 42 19 27 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++15 6 9 70 20 37 158 23 71 129 6 50 6 3 4 0 0 0 ++0 0 0 0 0 0 30 13 19 45 14 25 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++125 28 63 216 11 85 116 21 55 116 21 55 177 29 82 204 18 83 ++215 2 77 215 10 84 110 23 54 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 96 29 53 186 9 72 ++119 35 66 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 19 7 11 143 30 71 215 4 80 ++213 0 71 215 0 73 213 0 76 213 0 76 213 0 72 215 0 73 ++215 5 80 167 25 75 143 7 55 219 31 98 217 21 91 187 21 79 ++167 25 75 145 33 73 113 34 62 28 12 17 0 0 0 3 1 2 ++0 0 0 0 0 0 9 3 5 14 1 6 9 3 5 0 0 0 ++62 22 36 217 21 91 70 20 37 3 0 1 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 85 18 42 183 28 83 213 0 71 212 0 69 215 1 77 ++215 7 82 215 8 82 215 8 81 215 8 81 215 9 82 215 8 82 ++215 8 81 214 0 75 215 0 74 212 0 68 213 0 69 215 0 76 ++212 0 69 158 7 61 64 24 39 54 21 33 57 3 22 105 27 53 ++154 21 68 202 23 85 216 11 85 215 4 78 216 10 83 167 25 75 ++145 33 73 213 0 72 212 0 65 217 21 91 160 33 78 85 18 42 ++19 7 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 122 32 64 ++202 23 85 213 0 72 212 0 67 213 2 78 216 10 83 215 8 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 82 215 8 82 215 10 82 215 10 82 215 8 82 ++214 8 82 201 9 77 215 0 76 213 0 70 215 1 78 212 0 69 ++212 0 69 213 0 70 215 2 77 215 9 82 215 3 77 213 0 69 ++212 0 71 215 10 84 215 8 82 213 0 69 212 0 67 215 1 79 ++215 10 83 186 9 72 122 32 64 28 12 17 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 24 8 13 145 33 73 214 0 76 212 0 67 ++212 0 71 215 4 78 215 9 83 215 8 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 81 215 4 80 213 0 73 213 0 76 215 7 82 215 9 82 ++216 8 82 215 10 82 215 8 82 215 7 81 215 7 82 215 10 82 ++215 8 82 215 7 81 215 7 81 215 10 84 215 9 82 215 4 79 ++213 0 76 215 0 74 213 0 71 213 0 69 219 31 98 87 25 46 ++3 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++47 14 26 158 23 71 213 0 71 212 0 67 215 0 76 215 9 82 ++216 9 82 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 81 215 8 82 215 8 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 81 ++215 8 82 215 9 82 215 7 81 215 0 76 212 0 68 212 0 67 ++215 10 84 134 33 69 24 8 13 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 42 19 27 172 8 66 ++214 7 81 213 0 67 215 4 78 215 9 83 215 8 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 8 82 215 9 82 216 9 83 ++213 0 75 212 0 67 214 5 77 151 31 73 19 7 11 0 0 0 ++0 0 0 0 0 0 19 7 11 43 2 17 47 14 26 19 7 11 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 26 9 15 158 23 71 214 0 74 212 0 72 ++213 0 73 215 10 83 215 8 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 10 82 216 8 81 213 0 73 210 0 65 214 3 78 145 33 73 ++113 34 62 170 31 81 215 7 81 214 0 76 213 1 77 215 0 74 ++173 32 82 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 134 33 69 215 1 77 212 0 71 213 0 75 215 7 81 ++215 10 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 8 82 216 9 81 213 0 75 210 0 65 ++212 0 65 212 0 72 215 0 76 215 7 81 215 4 78 215 0 74 ++210 1 58 119 35 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 70 20 37 ++216 12 84 211 0 68 213 0 75 216 9 83 215 8 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 216 9 82 ++215 8 82 215 8 82 215 8 82 215 7 81 215 8 82 215 10 83 ++213 0 75 216 8 81 54 21 33 0 0 0 83 26 46 29 1 11 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 154 21 68 213 0 75 ++215 0 73 215 7 81 215 8 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++216 10 83 212 0 71 210 0 64 96 29 53 8 3 5 147 30 72 ++58 17 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 35 9 18 217 16 87 212 0 69 215 2 77 ++215 9 83 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 216 10 83 213 0 76 213 0 67 142 22 65 83 26 46 ++215 6 80 117 32 63 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 31 52 ++42 19 27 62 22 36 214 0 71 212 0 70 216 8 83 215 8 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 82 215 10 82 215 7 81 215 7 81 ++215 8 82 215 8 82 215 8 82 215 10 82 215 7 81 215 8 82 ++215 9 82 215 8 82 215 7 81 215 10 82 215 8 82 215 8 82 ++215 8 82 215 8 82 215 8 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 9 82 215 5 80 212 0 70 213 10 82 ++215 2 77 211 0 63 194 27 87 6 3 4 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 21 8 12 210 1 58 ++216 11 85 213 3 76 215 0 74 215 10 83 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 8 82 215 8 82 215 8 82 ++215 7 81 215 6 80 214 3 78 213 0 75 215 4 80 215 6 80 ++213 0 76 215 0 74 212 0 74 212 0 69 215 7 81 213 0 73 ++211 0 65 213 0 73 216 9 83 212 0 67 215 0 74 213 0 76 ++213 0 74 213 0 76 215 4 79 215 7 82 215 8 82 215 8 82 ++215 8 82 215 8 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 8 81 215 9 82 215 2 77 ++215 8 82 215 5 79 212 0 68 215 1 77 76 23 42 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 32 13 20 215 10 84 212 1 64 ++213 0 75 215 3 77 215 9 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 9 82 215 6 80 215 3 77 213 0 73 214 0 75 ++211 0 65 212 0 66 212 0 66 186 9 72 213 0 76 212 0 69 ++217 16 87 198 18 82 187 21 79 160 33 78 115 5 44 127 25 61 ++134 33 69 127 25 61 115 5 44 155 33 77 180 25 80 187 21 79 ++202 23 85 214 15 84 213 0 72 213 0 73 212 0 71 213 0 71 ++215 0 76 215 4 79 215 7 81 215 9 83 215 8 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 ++215 7 81 215 8 82 216 10 83 213 0 74 213 0 67 145 33 73 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 64 24 39 213 0 67 212 0 70 216 10 84 ++215 8 82 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 ++216 9 83 213 0 72 214 0 72 215 1 78 217 21 91 132 19 59 ++45 14 25 32 13 20 15 6 9 28 12 17 45 14 25 28 12 17 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 26 9 15 47 14 26 125 28 63 191 22 83 ++216 9 83 215 0 76 212 0 67 212 0 67 215 0 74 215 9 82 ++215 9 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 9 83 215 0 76 213 0 70 ++187 21 79 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 78 24 43 212 0 67 215 0 76 215 9 83 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 10 82 213 1 77 ++212 0 69 215 10 83 129 26 63 21 8 12 0 0 0 0 0 0 ++0 0 0 26 9 15 3 1 2 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 35 9 18 119 35 66 183 28 83 216 9 83 213 0 71 ++212 0 70 213 6 80 215 8 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 215 9 82 ++212 0 66 219 31 98 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++113 34 62 212 1 64 213 0 75 215 10 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 82 215 8 82 215 8 80 213 0 73 214 0 71 ++154 21 68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 85 18 42 ++183 28 83 212 0 66 214 0 71 215 6 80 215 8 82 215 8 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 10 82 212 1 64 213 1 77 6 3 4 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 142 22 65 ++212 0 74 215 0 74 215 9 83 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 ++215 7 82 213 0 76 213 0 72 213 0 73 215 0 76 32 13 20 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 13 6 8 164 30 78 213 0 74 213 0 69 215 3 79 ++215 9 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 216 8 83 212 0 71 212 0 69 21 8 12 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 162 40 83 211 0 58 ++215 6 80 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 8 81 215 8 82 212 0 72 ++213 0 70 215 10 82 172 8 66 85 18 42 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 11 4 6 173 32 82 213 0 76 ++213 0 72 215 9 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 216 11 85 209 0 60 214 15 84 8 3 5 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 183 28 83 211 0 63 215 7 81 ++215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 215 8 82 215 8 81 215 3 79 214 0 76 158 23 71 ++58 17 31 58 17 31 8 3 5 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 47 14 26 ++217 16 87 214 0 72 215 5 79 215 8 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 216 11 85 212 0 68 212 0 65 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 183 28 83 209 0 60 215 4 79 215 8 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 215 7 82 ++215 2 77 214 0 74 215 1 78 215 1 79 213 0 73 164 30 78 ++167 25 75 186 9 72 42 19 27 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 158 23 71 215 0 74 215 0 74 215 9 83 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 216 10 84 211 0 62 ++217 21 91 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 173 32 82 210 1 58 216 8 82 215 8 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 9 82 215 0 76 214 0 76 ++216 10 84 187 21 79 132 19 59 85 18 42 73 20 39 85 18 42 ++35 9 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 78 24 43 214 5 77 214 0 72 215 8 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 216 10 84 ++210 1 58 183 28 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++162 40 83 210 1 58 216 8 82 215 8 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 81 215 8 82 213 0 70 214 0 76 132 19 59 ++24 8 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 26 9 15 216 11 85 213 0 67 ++215 10 83 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++216 10 84 210 1 58 162 40 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 31 52 ++210 1 58 215 4 78 215 8 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 215 5 81 211 0 65 219 31 98 21 8 12 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 217 21 91 ++213 0 67 215 7 81 215 8 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 215 6 80 210 1 58 81 25 45 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 6 3 4 211 0 63 ++213 0 71 215 9 83 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 ++215 4 79 211 0 60 154 21 68 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++186 9 72 212 0 67 215 7 81 215 8 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 9 83 213 0 70 212 0 71 8 3 5 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 186 9 72 211 0 63 ++216 10 84 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 215 8 82 ++212 0 66 101 33 58 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 194 27 87 210 1 62 216 8 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 216 10 84 209 0 60 213 18 87 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 212 0 71 215 2 77 ++215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 8 82 215 9 82 215 4 78 212 0 69 ++136 20 62 87 25 46 78 24 43 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 201 9 77 210 0 59 216 11 85 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 216 9 82 210 1 58 119 35 66 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 8 3 5 201 9 77 213 0 73 215 9 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 216 9 83 215 4 78 215 0 73 214 0 76 213 18 87 ++186 9 72 183 28 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 217 21 91 210 1 58 216 11 85 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 9 82 215 0 74 210 1 58 ++15 6 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 194 27 87 210 1 58 216 8 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 10 82 ++215 6 80 212 0 72 215 0 74 186 9 72 73 20 39 4 1 2 ++1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 8 80 210 0 59 ++216 11 85 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 10 84 211 0 62 ++194 27 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 42 19 27 210 0 64 215 0 76 215 9 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 10 83 215 2 77 ++211 0 65 214 15 84 70 20 37 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 30 13 19 210 0 64 ++214 0 74 216 11 85 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 8 81 213 6 80 ++211 0 60 73 20 39 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 183 28 83 211 0 63 215 10 83 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 216 10 83 212 0 71 214 0 71 ++141 35 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 101 33 58 ++210 1 58 215 4 80 215 10 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 216 9 83 ++212 0 68 219 31 98 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++28 12 17 213 0 69 213 0 73 215 10 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 82 216 9 82 212 0 66 215 1 77 58 17 31 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++158 23 71 210 1 58 216 10 83 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 81 ++215 7 81 212 0 65 87 25 46 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++141 35 72 211 0 62 216 8 83 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 216 8 82 210 1 58 217 21 91 8 3 5 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 217 16 87 210 0 64 216 11 85 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 9 82 213 0 73 216 12 84 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 54 21 33 212 0 74 24 8 13 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 9 82 213 0 70 215 9 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 ++213 3 79 211 0 65 194 27 87 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 42 19 27 210 1 58 214 0 75 215 9 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 215 4 78 213 0 69 96 29 53 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 116 21 55 210 1 58 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 31 52 ++209 0 60 216 8 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 215 4 78 ++211 0 63 167 25 75 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 138 29 68 210 1 58 216 9 83 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 215 10 83 212 0 65 186 26 82 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 217 16 87 162 40 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 191 22 83 ++212 0 66 215 7 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 8 81 215 5 81 212 0 69 ++162 40 83 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 213 1 77 211 0 65 216 10 83 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 8 82 215 10 82 215 9 83 ++213 0 73 216 8 81 213 0 74 213 0 75 54 21 33 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 54 21 33 143 7 55 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 81 25 45 210 1 58 ++215 3 79 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 8 81 215 7 82 211 0 58 129 6 50 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 76 23 42 211 0 60 213 3 79 ++215 10 84 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 9 82 214 0 71 212 0 69 212 0 66 ++217 16 87 213 0 76 216 4 80 212 0 66 141 35 72 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 13 6 8 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 19 7 11 217 21 91 212 0 71 ++215 9 83 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 82 215 5 80 213 0 67 162 40 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 194 27 87 211 0 62 ++216 10 83 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 82 213 0 73 183 28 83 141 35 72 160 33 78 ++0 0 0 201 9 77 210 1 58 138 29 68 83 26 46 30 13 19 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 28 12 17 216 10 84 211 0 68 213 0 73 215 9 83 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 216 8 81 209 0 60 162 40 83 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 42 19 27 211 0 62 ++214 0 76 215 10 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 9 82 211 0 65 62 22 36 0 0 0 0 0 0 ++0 0 0 90 31 52 210 1 58 158 7 61 0 0 0 24 8 13 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 142 22 65 209 0 60 216 8 81 215 8 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 212 0 69 180 25 80 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 183 28 83 ++210 0 65 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 6 80 213 0 69 105 27 53 0 0 0 0 0 0 ++0 0 0 0 0 0 215 6 80 213 0 67 3 1 2 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++21 8 12 215 3 77 213 0 69 216 11 85 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 10 84 ++212 1 64 202 23 85 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 21 33 ++212 0 68 213 0 74 215 8 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 9 83 212 0 66 173 32 82 0 0 0 0 0 0 ++0 0 0 0 0 0 101 33 58 210 1 58 7 2 4 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++117 32 63 209 0 60 216 9 84 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 216 12 84 212 0 65 ++213 0 69 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++202 23 85 212 0 68 215 9 83 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 82 213 0 75 215 6 80 0 0 0 0 0 0 ++0 0 0 0 0 0 4 1 2 219 31 98 29 1 11 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 2 77 213 0 72 215 10 84 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 216 9 83 212 0 70 211 0 63 ++18 7 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++113 34 62 210 0 65 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 214 0 72 167 25 75 215 7 82 ++28 12 17 0 0 0 0 0 0 134 33 69 101 33 58 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 83 26 46 ++210 1 58 216 8 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 10 82 215 4 80 210 1 58 64 24 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 32 13 20 110 23 54 ++164 30 78 172 8 66 186 9 72 202 23 85 202 23 85 198 18 82 ++172 8 66 167 25 75 132 19 59 42 19 27 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++18 7 11 215 0 74 213 0 73 215 10 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 10 83 213 0 69 210 1 58 ++173 32 82 0 0 0 0 0 0 62 22 36 162 40 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 213 10 82 ++212 0 65 215 10 83 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 216 10 84 210 1 58 162 40 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 29 1 11 145 33 73 217 21 91 214 0 72 212 0 72 ++213 0 70 215 4 79 215 1 78 212 0 65 213 0 69 213 0 71 ++215 0 74 214 0 71 212 0 74 214 0 72 217 16 87 158 23 71 ++28 12 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 180 25 80 212 0 69 216 9 83 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 10 83 215 0 76 ++186 9 72 0 0 0 0 0 0 0 0 0 162 40 83 30 13 19 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++13 6 8 0 0 0 0 0 0 0 0 0 42 19 27 211 0 63 ++213 1 77 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 216 9 83 211 0 68 191 22 83 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 62 22 36 ++183 28 83 214 0 75 210 0 65 213 0 71 215 3 79 215 6 80 ++215 5 79 213 0 72 213 0 74 213 1 77 212 0 71 213 0 73 ++215 9 83 215 9 83 212 0 72 213 0 72 211 0 68 210 0 64 ++211 0 68 183 28 83 58 17 31 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 113 34 62 212 0 68 214 5 77 215 8 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 213 0 73 ++201 23 85 0 0 0 0 0 0 0 0 0 101 33 58 90 31 52 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 21 33 ++129 26 63 0 0 0 0 0 0 0 0 0 160 33 78 211 0 60 ++216 9 84 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 213 0 74 216 12 84 3 1 2 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 14 1 6 183 28 83 212 0 66 ++210 0 64 215 6 80 217 16 87 216 8 83 213 0 73 214 0 75 ++215 1 78 217 16 87 201 23 85 154 21 68 145 33 73 117 32 63 ++72 3 28 72 3 28 119 35 66 142 22 65 158 23 71 202 23 85 ++215 3 77 211 0 60 212 0 68 183 28 83 9 3 5 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 30 13 19 213 0 76 213 0 73 215 8 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 215 0 74 ++215 10 84 32 13 20 0 0 0 0 0 0 42 19 27 162 40 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 219 31 98 ++110 23 54 0 0 0 0 0 0 0 0 0 215 10 82 213 0 71 ++215 9 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 5 79 213 10 82 212 0 66 28 12 17 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 87 25 46 213 0 71 212 1 64 213 3 76 ++216 12 84 215 4 78 212 0 70 213 0 72 213 18 87 154 21 68 ++58 17 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++6 3 4 85 18 42 158 7 61 212 0 68 211 0 65 127 25 61 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 216 9 84 214 0 72 215 9 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 215 0 74 ++210 0 59 64 24 39 0 0 0 0 0 0 0 0 0 119 35 66 ++6 3 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 213 0 74 ++9 3 5 0 0 0 0 0 0 90 31 52 211 0 63 213 3 79 ++215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 216 12 84 212 1 64 217 16 87 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 154 21 68 213 0 71 213 0 73 216 10 83 216 8 81 ++212 0 71 215 3 79 191 22 83 85 18 42 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 4 1 2 132 19 59 213 0 69 ++219 31 98 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 164 30 78 212 0 72 215 7 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 6 80 204 18 83 ++213 0 72 160 33 78 0 0 0 0 0 0 0 0 0 78 24 43 ++62 22 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 219 31 98 ++0 0 0 0 0 0 0 0 0 162 40 83 210 1 58 216 11 85 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 82 210 1 58 68 22 37 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++194 27 87 210 1 58 215 5 81 216 12 84 213 0 72 213 0 70 ++194 27 87 47 14 26 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++180 25 80 217 21 91 19 7 11 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 96 29 53 212 0 69 215 5 80 215 8 81 ++215 7 81 215 7 81 215 7 81 215 8 82 214 0 74 180 25 80 ++54 21 33 213 6 80 0 0 0 0 0 0 0 0 0 54 21 33 ++101 33 58 6 3 4 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 31 52 ++0 0 0 0 0 0 4 1 2 215 6 80 213 0 71 215 8 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++216 11 85 210 1 62 214 15 84 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 164 30 78 ++210 1 58 216 8 83 215 9 82 211 0 63 216 10 83 85 18 42 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 73 20 39 186 9 72 42 19 27 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 78 24 43 213 0 71 215 4 78 215 8 82 ++215 7 81 215 7 81 215 7 81 215 8 82 215 1 77 212 1 64 ++0 0 0 141 35 72 62 22 36 0 0 0 0 0 0 15 6 9 ++83 26 46 42 19 27 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 1 2 ++0 0 0 0 0 0 81 25 45 210 0 64 216 10 83 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 ++215 6 80 210 1 58 119 35 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 119 35 66 210 1 58 ++214 3 78 216 9 84 212 1 64 194 27 87 11 4 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 29 1 11 119 35 66 18 7 11 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 45 14 25 213 0 73 215 4 78 215 8 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 82 211 0 61 ++141 35 72 0 0 0 19 7 11 0 0 0 0 0 0 0 0 0 ++58 17 31 70 20 37 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 194 27 87 210 0 65 216 11 85 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 216 9 83 ++212 0 71 210 0 70 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 18 7 11 210 1 58 213 0 74 ++216 8 83 211 0 63 170 31 81 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 1 0 0 15 6 9 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 35 9 18 211 0 62 215 7 81 215 8 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 9 82 212 0 71 ++215 9 82 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++40 16 25 62 22 36 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 213 0 76 215 1 77 215 8 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 9 82 216 4 80 ++210 0 59 83 26 46 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 219 31 98 211 0 61 216 11 85 ++211 0 60 143 7 55 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 162 40 83 213 0 69 215 6 80 ++215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 215 4 78 ++212 0 66 113 34 62 0 0 0 0 0 0 0 0 0 0 0 0 ++18 7 11 30 13 19 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 101 33 58 211 0 61 215 7 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 216 11 85 212 0 65 ++186 9 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 141 35 72 211 0 60 216 11 85 210 1 58 ++162 40 83 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 119 35 66 211 0 65 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 9 83 ++214 0 71 215 0 74 41 16 25 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 194 27 87 210 0 59 216 9 83 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 10 82 215 3 77 211 0 62 ++62 22 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 141 35 72 210 1 58 215 6 80 210 0 59 217 21 91 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 129 26 63 214 0 72 215 7 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 82 ++213 0 73 173 32 82 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 214 5 77 213 0 73 215 9 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 216 9 84 211 0 61 186 26 82 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++83 26 46 210 1 58 214 3 78 212 0 74 211 0 60 11 4 6 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 141 35 72 211 0 65 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 81 ++215 4 80 72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++90 31 52 211 0 61 215 3 79 215 8 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 8 82 215 2 77 212 0 68 68 22 37 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 7 82 212 0 67 216 10 84 210 1 58 101 33 58 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 141 35 72 211 0 62 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 6 80 ++213 0 73 116 21 55 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++170 31 81 211 0 62 215 10 83 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 216 9 83 210 0 65 213 18 87 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 35 66 ++211 0 61 216 9 83 212 0 68 213 18 87 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 115 5 44 215 0 76 215 8 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 82 ++212 0 71 155 33 77 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++217 21 91 212 0 68 215 9 83 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 211 0 62 119 35 66 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 202 23 85 ++212 0 68 216 12 84 210 1 58 40 16 25 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 100 5 39 215 9 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 9 82 ++212 0 69 194 27 87 0 0 0 0 0 0 3 0 1 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++155 33 77 212 0 67 215 9 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 82 215 2 77 212 0 67 54 21 33 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 64 24 39 212 0 66 ++216 4 80 212 0 67 180 25 80 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 115 5 44 215 4 79 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 ++215 2 77 216 10 83 116 21 55 85 18 42 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++116 21 55 214 0 71 215 9 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 81 215 4 80 215 1 78 37 7 18 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 141 35 72 209 0 60 ++215 7 82 211 0 60 64 24 39 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 113 34 62 213 0 71 215 6 80 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 215 2 77 210 1 58 162 40 83 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++110 23 54 214 0 75 215 6 80 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 82 213 0 75 215 10 83 35 9 18 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 219 31 98 212 0 68 ++212 0 70 201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 107 28 56 214 0 71 215 7 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 9 82 212 0 74 215 4 78 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++119 35 66 211 0 61 215 5 79 215 8 82 215 7 81 215 7 81 ++215 7 81 215 8 82 215 0 74 217 16 87 6 3 4 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 64 24 39 211 0 60 215 3 79 ++212 0 68 138 29 68 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 113 34 62 214 0 71 215 6 80 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 82 213 0 69 177 29 82 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++119 35 66 210 1 62 215 5 79 215 8 82 215 7 81 215 7 81 ++215 7 81 215 8 82 215 0 74 187 21 79 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 180 25 80 210 0 65 215 4 80 ++214 0 71 76 23 42 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 141 35 72 162 40 83 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 100 5 39 215 4 78 215 8 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 ++213 1 77 212 0 65 54 21 33 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++119 35 66 211 0 62 215 5 79 215 8 82 215 7 81 215 7 81 ++215 7 81 215 8 82 212 0 71 167 25 75 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 83 26 46 212 0 66 215 4 80 213 0 76 ++215 1 78 13 6 8 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 3 77 186 9 72 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 110 23 54 215 0 76 215 8 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 9 82 ++213 0 72 215 9 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++119 35 66 212 0 67 215 4 80 215 8 81 215 7 81 215 7 81 ++215 7 81 215 8 82 212 0 71 154 21 68 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 158 7 61 212 0 71 216 12 84 213 0 69 ++194 27 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 194 27 87 186 9 72 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 122 32 64 212 0 72 215 6 80 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 82 215 6 80 ++211 0 61 173 32 82 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++116 21 55 215 0 76 215 8 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 82 214 0 71 129 26 63 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 183 28 83 212 0 70 215 9 83 214 0 71 ++154 21 68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 64 24 39 162 40 83 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 154 21 68 215 0 74 215 8 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 6 80 213 10 82 ++215 0 74 142 22 65 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++100 5 39 216 11 85 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 82 213 0 72 85 18 42 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 3 1 2 204 18 83 215 0 74 215 10 83 212 0 70 ++134 33 69 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 3 1 2 213 18 87 211 0 68 216 9 83 ++215 7 81 215 7 81 215 7 81 215 8 82 214 0 75 213 18 87 ++162 40 83 115 5 44 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++116 21 55 212 0 71 215 8 82 215 7 81 215 7 81 215 7 81 ++215 8 81 213 6 80 213 0 72 76 23 42 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 11 4 6 217 21 91 213 0 73 215 10 82 213 0 76 ++86 4 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 15 6 9 219 31 98 214 3 78 215 4 80 ++215 8 81 215 7 81 215 7 81 215 8 82 215 0 74 213 0 75 ++64 24 39 73 20 39 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++162 40 83 210 1 58 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 213 2 78 213 0 72 64 24 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 4 1 2 212 0 74 216 9 83 215 6 80 215 0 74 ++72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 32 13 20 162 40 83 215 4 78 215 0 74 ++215 8 82 215 7 81 215 7 81 215 8 82 213 0 71 73 20 39 ++13 6 8 54 21 33 18 7 11 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++141 35 72 213 0 67 215 9 83 215 7 81 215 7 81 215 7 81 ++215 7 82 215 4 78 215 0 74 37 7 18 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 14 1 6 216 12 84 213 3 76 216 9 83 211 0 60 ++54 21 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 8 3 5 0 0 0 73 20 39 212 0 68 215 7 82 ++215 7 81 215 7 81 215 7 81 215 9 83 210 0 59 0 0 0 ++0 0 0 4 1 2 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++136 20 62 214 0 74 215 8 82 215 7 81 215 7 81 215 7 81 ++215 10 82 213 0 74 217 16 87 11 4 6 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 28 12 17 219 31 98 212 0 66 216 12 84 211 0 63 ++117 32 63 30 13 19 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 96 29 53 212 0 67 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 82 212 0 68 7 2 4 ++42 19 27 0 0 0 3 1 2 32 13 20 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++129 6 50 215 8 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 10 82 213 0 72 191 22 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 9 3 5 215 10 84 215 3 79 215 8 82 213 2 78 ++212 0 72 73 20 39 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 158 23 71 212 0 70 215 7 82 ++215 7 81 215 7 81 215 8 82 213 0 76 213 10 82 11 4 6 ++57 3 22 0 0 0 32 13 20 78 24 43 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++129 6 50 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 214 0 72 186 9 72 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 7 2 4 213 3 79 214 7 81 215 7 81 215 5 79 ++212 0 72 85 18 42 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++11 4 6 26 9 15 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 9 3 5 217 21 91 213 0 69 215 9 82 ++215 7 81 215 7 81 215 9 82 212 0 69 183 28 83 0 0 0 ++35 9 18 0 0 0 70 20 37 62 22 36 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++129 6 50 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 212 0 70 183 28 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 8 3 5 217 21 91 213 0 69 216 11 85 215 4 80 ++212 0 70 122 32 64 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 26 9 15 0 0 0 ++30 13 19 54 21 33 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 64 24 39 212 1 64 213 3 79 215 8 82 ++215 7 81 215 7 81 216 9 81 209 0 60 83 26 46 28 12 17 ++18 7 11 0 0 0 62 22 36 24 8 13 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++138 29 68 214 0 72 215 8 82 215 7 81 215 7 81 215 7 81 ++215 8 82 215 3 79 158 7 61 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 201 23 85 213 0 72 215 10 82 215 7 81 ++212 0 65 143 30 71 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 26 9 15 141 35 72 0 0 0 ++64 24 39 18 7 11 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 180 25 80 211 0 68 215 7 81 215 7 81 ++215 7 81 215 8 82 213 0 75 214 0 72 9 3 5 40 16 25 ++0 0 0 0 0 0 113 34 62 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++162 40 83 211 0 61 215 7 81 215 7 81 215 7 81 215 8 81 ++215 5 80 212 0 67 162 40 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 151 31 73 213 0 67 215 9 83 215 10 83 ++212 0 66 173 32 82 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 162 40 83 54 21 33 18 7 11 ++141 35 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 15 6 9 212 0 72 213 0 73 215 9 82 215 7 81 ++215 7 81 216 9 81 210 0 64 173 32 82 0 0 0 0 0 0 ++0 0 0 8 3 5 101 33 58 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++115 5 44 215 0 74 215 8 82 215 7 81 215 7 81 215 7 81 ++215 7 82 214 0 71 134 33 69 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 119 35 66 210 0 65 216 4 80 215 10 84 ++213 0 74 212 0 71 26 9 15 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 83 26 46 141 35 72 0 0 0 141 35 72 ++37 7 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 119 35 66 211 0 65 215 5 81 215 8 81 215 7 81 ++215 8 81 215 7 82 210 1 58 45 14 25 0 0 0 0 0 0 ++0 0 0 41 16 25 47 14 26 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++117 32 63 212 0 68 215 9 82 215 7 81 215 7 81 215 7 81 ++215 9 82 213 0 76 115 5 44 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 81 25 45 213 0 67 213 3 79 216 10 84 ++213 3 76 211 0 63 64 24 39 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 162 40 83 0 0 0 116 21 55 155 33 77 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 213 18 87 213 0 72 215 9 82 215 7 81 215 7 81 ++215 9 83 211 0 62 194 27 87 0 0 0 0 0 0 0 0 0 ++0 0 0 64 24 39 18 7 11 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++162 40 83 211 0 62 215 7 81 215 7 81 215 7 81 215 8 81 ++215 4 80 215 4 78 116 21 55 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 19 7 11 215 2 77 213 0 74 215 10 82 ++216 11 85 210 1 62 129 26 63 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 42 19 27 209 2 59 216 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 116 21 55 ++215 0 76 213 0 73 215 9 82 215 7 81 215 7 81 215 7 81 ++215 7 81 210 1 58 42 19 27 0 0 0 0 0 0 0 0 0 ++0 0 0 101 33 58 9 3 5 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++138 29 68 213 0 70 215 8 82 215 7 81 215 7 81 215 8 82 ++215 4 78 215 3 77 116 21 55 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 194 27 87 210 0 64 216 9 81 ++215 10 84 213 0 70 213 0 76 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 47 14 26 30 13 19 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 155 33 77 211 0 58 ++213 0 76 215 9 82 215 7 81 215 7 81 215 7 81 216 11 85 ++211 0 60 194 27 87 0 0 0 0 0 0 0 0 0 0 0 0 ++32 13 20 54 21 33 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++129 6 50 215 2 77 215 8 82 215 7 81 215 7 81 215 7 81 ++215 6 80 215 1 77 116 21 55 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 119 35 66 210 1 58 215 6 80 ++215 7 81 216 9 83 210 0 59 64 24 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 18 7 11 216 9 81 212 0 69 ++216 11 85 215 7 81 215 7 81 215 8 82 215 4 80 215 4 78 ++211 0 58 42 19 27 0 0 0 0 0 0 0 0 0 0 0 0 ++54 21 33 32 13 20 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++138 29 68 213 0 69 215 8 82 215 7 81 215 7 81 215 7 81 ++215 9 83 213 0 70 116 21 55 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 21 8 12 212 0 74 213 0 71 ++215 9 82 216 10 83 210 0 65 204 18 83 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 45 14 25 216 12 84 213 0 74 ++215 10 82 215 7 81 215 7 81 216 8 81 213 0 72 210 1 58 ++194 27 87 0 0 0 0 0 0 0 0 0 0 0 0 4 1 2 ++81 25 45 4 1 2 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++141 35 72 212 0 69 215 9 82 215 7 81 215 7 81 215 7 81 ++215 6 80 212 0 71 162 40 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 162 40 83 209 0 60 ++216 10 83 215 7 82 215 5 79 211 0 61 64 24 39 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 26 9 15 4 1 2 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 11 4 6 217 21 91 213 0 72 ++215 10 82 215 9 82 216 10 84 210 1 58 119 35 66 219 31 98 ++158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 18 7 11 ++54 21 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++141 35 72 211 0 61 215 7 81 215 7 81 215 7 81 215 7 81 ++215 9 82 214 0 71 172 8 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 13 6 8 0 0 0 32 13 20 213 0 67 ++213 0 76 215 8 82 216 9 83 210 0 64 202 23 85 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++122 32 64 186 9 72 167 25 75 162 40 83 145 33 73 143 7 55 ++219 31 98 138 29 68 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 21 8 12 212 0 70 213 2 78 ++215 8 81 216 9 84 211 0 61 204 18 83 0 0 0 41 16 25 ++164 30 78 0 0 0 0 0 0 0 0 0 0 0 0 62 22 36 ++6 3 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++115 5 44 215 3 79 215 8 82 215 7 81 215 7 81 215 7 81 ++215 9 82 212 0 68 180 25 80 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 1 0 0 83 26 46 0 0 0 162 40 83 ++211 0 58 216 10 84 215 7 82 216 8 81 210 1 58 96 29 53 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++32 13 20 142 22 65 213 18 87 212 1 64 211 0 61 214 0 72 ++125 28 63 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 194 27 87 212 0 66 216 9 83 ++215 8 82 213 4 75 209 0 60 90 31 52 0 0 0 0 0 0 ++13 6 8 3 1 2 0 0 0 0 0 0 8 3 5 54 21 33 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++117 32 63 212 0 72 215 5 81 215 8 81 215 7 81 215 7 81 ++215 8 82 213 0 72 213 18 87 6 3 4 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 78 24 43 64 24 39 0 0 0 ++211 0 63 213 0 73 215 10 82 215 10 84 213 0 70 212 0 72 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 9 3 5 50 16 28 47 14 26 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 201 9 77 210 1 58 215 10 82 215 7 81 ++215 9 83 214 0 68 187 21 79 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 42 19 27 13 6 8 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++83 26 46 212 0 66 215 8 80 215 7 81 215 7 81 215 7 81 ++215 10 82 213 0 76 214 0 68 64 24 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 162 40 83 0 0 0 ++90 31 52 210 1 58 215 4 80 215 7 81 216 12 84 210 0 64 ++201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++3 1 2 219 31 98 211 0 60 216 8 83 215 9 82 215 7 81 ++216 10 83 212 0 66 154 21 68 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 4 1 2 32 13 20 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++58 17 31 215 2 77 215 1 78 215 8 82 215 7 81 215 7 81 ++215 7 81 216 10 84 209 0 60 134 33 69 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++42 19 27 64 24 39 0 0 0 0 0 0 81 25 45 142 22 65 ++0 0 0 186 9 72 210 1 58 216 11 85 215 7 81 216 9 82 ++210 1 58 141 35 72 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 8 13 ++215 10 82 214 0 68 215 8 82 215 10 82 215 7 81 216 12 84 ++213 0 74 213 2 78 187 21 79 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++26 9 15 215 12 82 213 0 75 215 8 82 215 7 81 215 7 81 ++215 7 81 215 9 82 213 0 71 215 3 79 11 4 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++122 32 64 210 1 62 0 0 0 0 0 0 0 0 0 101 33 58 ++0 0 0 0 0 0 211 0 68 212 0 66 216 10 83 215 8 82 ++215 1 78 210 1 58 101 33 58 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 54 21 33 214 3 78 ++211 0 68 216 8 81 215 8 82 215 7 81 216 12 83 213 0 70 ++212 0 72 87 25 46 183 28 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++9 3 5 215 5 79 215 2 77 215 8 82 215 7 81 215 7 81 ++215 7 81 215 7 81 216 8 82 211 0 58 162 40 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++30 13 19 210 1 58 101 33 58 0 0 0 7 2 4 0 0 0 ++13 6 8 0 0 0 42 19 27 211 0 60 212 0 74 215 9 82 ++216 9 83 213 0 71 213 0 69 64 24 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 90 31 52 212 0 65 213 0 73 ++216 10 83 215 7 81 215 7 81 216 10 84 212 0 70 213 0 67 ++19 7 11 0 0 0 101 33 58 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 213 10 82 213 0 75 215 8 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 82 214 0 72 186 9 72 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 119 35 66 210 1 58 0 0 0 64 24 39 115 5 44 ++0 0 0 0 0 0 0 0 0 83 26 46 214 0 68 215 3 77 ++215 8 82 216 12 84 213 0 69 211 0 68 78 24 43 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 6 9 ++0 0 0 0 0 0 138 29 68 212 0 67 215 0 74 215 10 83 ++215 7 81 215 7 81 216 10 84 211 0 62 215 10 83 42 19 27 ++0 0 0 13 6 8 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 194 27 87 212 0 68 215 9 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 6 80 212 0 72 143 30 71 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 214 0 68 173 32 82 0 0 0 219 31 98 ++141 35 72 0 0 0 0 0 0 0 0 0 72 3 28 213 1 77 ++215 4 79 215 8 82 216 10 83 213 0 72 212 0 71 105 27 53 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 72 3 28 0 0 0 ++0 0 0 186 26 82 211 0 63 215 4 78 215 9 82 215 7 81 ++215 7 81 216 10 83 212 0 69 216 12 83 40 16 25 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 170 31 81 212 0 65 215 9 83 215 7 81 215 7 81 ++215 7 81 215 7 81 215 6 80 213 0 73 116 21 55 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 13 6 8 210 0 64 35 9 18 0 0 0 ++212 0 65 64 24 39 0 0 0 0 0 0 0 0 0 57 3 22 ++215 0 74 215 0 76 216 11 85 216 9 82 213 1 77 211 0 68 ++151 31 73 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 119 35 66 28 12 17 35 9 18 ++217 21 91 211 0 68 215 8 81 215 8 82 215 7 81 215 8 81 ++216 10 84 212 0 66 215 6 80 18 7 11 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 134 33 69 212 0 68 215 7 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 6 80 214 0 72 58 17 31 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 113 34 62 215 0 74 0 0 0 ++42 19 27 210 1 58 18 7 11 15 6 9 15 6 9 0 0 0 ++76 23 42 213 0 74 212 0 68 216 12 84 215 10 82 215 4 80 ++212 0 68 217 21 91 37 7 18 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 134 33 69 214 0 75 145 33 73 213 0 71 ++210 0 70 216 8 81 215 8 82 215 7 81 215 9 82 215 5 80 ++211 0 63 217 21 91 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 54 21 33 212 0 67 215 6 80 215 7 81 215 7 81 ++215 7 81 215 7 81 215 8 80 212 0 69 145 33 73 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 173 32 82 162 40 83 ++0 0 0 90 31 52 210 1 58 8 3 5 119 35 66 0 0 0 ++0 0 0 45 14 25 215 1 77 213 0 70 215 8 81 215 9 82 ++215 5 80 212 0 71 215 1 78 143 30 71 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 143 30 71 213 0 73 215 0 73 214 0 71 215 4 80 ++216 9 82 215 7 81 215 7 81 216 9 83 213 0 76 213 0 72 ++167 25 75 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 6 3 4 213 0 72 215 2 77 215 8 82 215 7 81 ++215 7 81 215 7 81 215 8 82 213 0 73 214 0 72 11 4 6 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 141 35 72 ++32 13 20 0 0 0 101 33 58 214 4 79 18 7 11 162 40 83 ++0 0 0 0 0 0 15 6 9 215 3 79 212 0 69 215 8 82 ++215 8 82 215 9 82 215 3 79 212 0 71 216 12 84 105 27 53 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 ++202 23 85 213 0 70 215 4 79 215 9 82 215 8 82 215 8 81 ++215 7 81 215 8 81 216 8 83 212 0 68 213 0 73 85 18 42 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 216 9 81 213 0 72 215 10 82 215 7 81 ++215 7 81 215 7 81 215 7 81 216 10 84 209 0 60 183 28 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++11 4 6 0 0 0 0 0 0 100 5 39 201 9 77 62 22 36 ++198 18 82 0 0 0 0 0 0 0 0 0 194 27 87 211 0 62 ++215 4 80 215 9 82 215 8 81 215 9 82 215 0 76 213 0 69 ++217 21 91 136 20 62 40 16 25 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 73 20 39 58 17 31 127 25 61 202 23 85 213 3 76 ++214 0 72 215 9 82 215 8 81 215 7 81 215 7 81 215 8 82 ++215 9 82 215 1 78 211 0 68 194 27 87 13 6 8 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 173 32 82 210 0 65 216 11 85 215 7 81 ++215 7 81 215 7 81 215 8 81 215 4 80 214 0 74 142 22 65 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 90 31 52 180 25 80 ++145 33 73 216 10 84 3 1 2 0 0 0 0 0 0 145 33 73 ++213 0 70 213 0 71 216 10 83 215 7 81 215 8 82 215 7 82 ++214 0 75 213 0 73 215 6 80 204 18 83 132 19 59 45 14 25 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 64 24 39 154 21 68 ++215 7 82 215 4 78 214 8 82 214 0 74 212 0 74 215 6 80 ++215 8 82 215 7 81 215 7 81 215 8 82 215 9 82 213 0 76 ++212 0 69 216 9 82 85 18 42 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 101 33 58 211 0 62 215 7 82 215 7 81 ++215 7 81 215 7 81 215 8 82 215 5 79 210 0 59 101 33 58 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 29 1 11 ++164 30 78 217 21 91 217 16 87 81 25 45 0 0 0 0 0 0 ++68 22 37 213 6 80 212 0 68 216 9 84 215 8 82 215 8 81 ++215 8 82 215 8 82 215 4 79 215 0 76 214 0 76 215 0 76 ++215 4 78 219 31 98 167 25 75 145 33 73 129 6 50 129 6 50 ++143 30 71 167 25 75 213 18 87 215 4 80 213 0 70 212 0 74 ++215 3 77 215 5 79 215 4 79 215 8 82 215 8 82 215 8 81 ++215 7 81 215 8 82 215 7 82 213 0 76 214 0 72 215 7 81 ++147 30 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 19 7 11 212 0 70 216 4 80 215 7 81 ++215 7 81 215 7 81 215 7 81 216 11 85 211 0 61 194 27 87 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 119 35 66 215 7 81 210 1 58 167 25 75 4 1 2 ++0 0 0 13 6 8 214 15 84 209 0 60 213 0 75 215 6 80 ++215 6 80 215 8 82 215 8 82 215 8 82 215 8 82 215 5 79 ++215 5 79 213 0 73 215 0 73 212 0 67 215 8 82 215 8 82 ++212 0 71 215 0 76 215 0 76 215 3 79 215 6 80 215 8 82 ++215 7 82 215 8 81 215 8 82 215 8 82 215 8 82 215 5 81 ++215 5 79 213 0 75 213 0 70 214 4 79 127 25 61 21 8 12 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 213 18 87 212 0 67 216 11 85 ++215 7 81 215 7 81 215 7 81 215 10 82 215 2 77 211 0 62 ++54 21 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 40 16 25 217 21 91 210 0 64 213 0 75 ++115 5 44 0 0 0 54 21 33 85 18 42 217 21 91 212 0 71 ++214 0 76 214 0 74 215 0 76 215 3 77 215 5 80 215 8 82 ++215 8 82 215 9 82 215 9 82 216 10 83 215 7 81 215 8 81 ++215 8 82 215 8 82 215 8 82 215 8 82 215 8 82 215 8 82 ++215 8 82 215 7 81 215 3 79 215 3 77 214 0 72 212 0 72 ++212 0 72 217 21 91 83 26 46 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 151 31 73 211 0 62 215 9 83 ++215 7 81 215 7 81 215 7 81 215 7 81 216 11 85 210 1 58 ++155 33 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 110 23 54 216 8 81 ++211 0 68 212 1 64 210 0 70 0 0 0 0 0 0 26 9 15 ++129 26 63 191 22 83 216 12 84 215 9 82 214 0 75 214 0 72 ++214 0 75 214 0 75 215 3 79 213 0 74 215 8 82 215 3 79 ++215 5 79 215 8 82 215 3 79 215 0 76 215 0 76 214 0 75 ++213 0 73 214 0 75 215 7 82 215 6 80 201 23 85 129 26 63 ++26 9 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 83 26 46 212 0 65 215 5 79 ++215 8 82 215 7 81 215 7 81 215 7 81 215 10 84 214 0 74 ++209 0 60 13 6 8 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 3 5 ++142 22 65 217 16 87 211 0 60 215 1 77 87 25 46 0 0 0 ++0 0 0 0 0 0 9 3 5 43 2 17 96 29 53 143 30 71 ++154 21 68 191 22 83 217 16 87 217 21 91 215 5 79 216 12 84 ++216 12 84 215 2 77 216 12 84 217 21 91 204 18 83 167 25 75 ++154 21 68 110 23 54 57 3 22 15 6 9 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 13 6 8 214 5 77 213 0 72 ++215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 216 11 85 ++210 1 58 173 32 82 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 7 2 4 138 29 68 215 0 74 210 1 58 217 21 91 ++35 9 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 3 0 1 9 3 5 7 2 4 9 3 5 ++11 4 6 7 2 4 9 3 5 7 2 4 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 194 27 87 210 0 64 ++216 9 83 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++216 10 84 210 1 58 142 22 65 11 4 6 14 1 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 122 32 64 215 8 81 ++213 0 69 219 31 98 113 34 62 43 2 17 3 0 1 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 119 35 66 210 1 58 ++215 7 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 81 215 5 81 212 0 69 215 2 77 217 16 87 172 8 66 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 158 23 71 214 3 78 216 12 84 216 4 80 194 27 87 ++142 22 65 132 19 59 73 20 39 43 2 17 47 14 26 42 19 27 ++14 1 6 29 1 11 43 2 17 57 3 22 43 2 17 3 1 2 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 8 3 5 213 0 67 ++213 0 74 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 10 82 215 7 81 215 2 77 213 0 71 211 0 61 ++217 16 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 24 8 13 96 29 53 180 25 80 ++214 8 82 217 16 87 217 16 87 216 8 81 214 5 77 215 6 80 ++216 12 84 217 21 91 198 18 82 145 33 73 54 21 33 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 194 27 87 ++210 0 64 216 10 83 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 8 81 216 11 85 216 8 83 ++210 1 58 162 40 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 4 1 2 24 8 13 14 1 6 29 1 11 ++28 12 17 3 1 2 3 0 1 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 81 25 45 ++210 1 58 216 9 84 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 ++215 1 79 209 0 60 30 13 19 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 1 2 ++214 0 75 213 0 71 215 10 84 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 ++215 7 81 210 1 58 180 25 80 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++134 33 69 211 0 60 216 9 84 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 4 79 ++214 15 84 204 18 83 210 1 58 30 13 19 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++41 16 25 212 0 70 214 2 74 215 10 84 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 8 81 215 3 79 ++215 0 74 42 19 27 210 1 58 219 31 98 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 180 25 80 211 0 61 216 10 84 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 9 83 ++211 0 63 119 35 66 0 0 0 210 0 70 32 13 20 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 78 24 43 211 0 60 213 1 77 215 8 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 ++215 0 76 213 0 73 0 0 0 0 0 0 8 3 5 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 213 18 87 212 0 65 215 10 83 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 10 83 210 0 59 145 33 73 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 85 18 42 211 0 61 216 8 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 213 0 75 212 0 72 15 6 9 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 219 31 98 211 0 63 216 12 84 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 216 10 84 211 0 58 194 27 87 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 113 34 62 211 0 60 213 3 79 ++215 10 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 81 215 5 81 209 0 60 101 33 58 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 213 4 75 213 0 69 ++215 10 83 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 9 82 215 0 74 211 0 61 54 21 33 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 83 26 46 211 0 62 ++215 1 77 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 8 82 215 0 73 204 18 83 30 13 19 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 191 22 83 ++211 0 62 216 8 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 8 82 211 0 65 162 40 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 21 33 ++210 0 65 213 0 74 215 9 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 8 81 215 4 80 212 0 70 83 26 46 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++160 33 78 210 0 59 216 9 84 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 8 82 215 0 76 212 0 70 ++85 18 42 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 212 0 70 213 0 72 215 9 83 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 10 83 212 0 68 ++217 16 87 42 19 27 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 101 33 58 209 0 60 216 4 80 215 8 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 216 8 83 210 0 64 ++155 33 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 194 27 87 211 0 58 216 10 84 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 9 82 213 0 73 ++212 0 69 28 12 17 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 28 12 17 210 0 64 213 0 73 215 9 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 216 10 84 ++210 0 64 201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 119 35 66 210 1 58 216 8 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 81 ++215 7 82 210 1 58 113 34 62 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 202 23 85 210 0 64 ++216 10 84 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 9 82 213 0 73 212 0 66 26 9 15 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 212 0 65 ++212 0 70 216 9 83 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 216 10 84 210 1 58 204 18 83 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 83 26 46 ++210 1 58 215 4 80 215 8 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 82 215 3 79 209 0 60 141 35 72 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++162 40 83 210 1 58 216 11 85 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 10 83 214 0 75 210 1 58 64 24 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 216 8 83 210 1 58 216 11 85 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 216 11 85 212 0 70 214 0 71 ++0 0 0 0 0 0 0 0 0 3 1 2 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 213 0 72 213 0 70 216 11 85 215 7 81 ++215 7 81 215 7 81 215 7 81 215 9 82 216 11 85 210 0 59 ++177 29 82 15 6 9 41 16 25 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 42 19 27 211 0 60 213 0 76 215 8 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++213 0 70 212 0 72 101 33 58 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 87 25 46 211 0 61 216 4 80 ++215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 ++215 7 82 210 1 58 177 29 82 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 122 32 64 210 1 58 ++216 8 82 215 10 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 10 84 215 5 80 210 1 58 54 21 33 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 162 40 83 ++209 0 60 216 8 81 215 9 82 215 7 81 215 7 81 215 7 81 ++215 7 81 216 9 84 211 0 62 204 18 83 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++158 7 61 210 1 58 216 10 83 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 216 9 83 210 1 58 119 35 66 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 219 31 98 210 1 58 216 9 84 215 9 82 215 7 81 ++215 7 81 215 7 81 215 8 82 213 2 78 210 1 58 54 21 33 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 201 23 85 210 1 58 216 10 84 215 10 84 ++215 7 81 215 7 81 215 7 81 216 10 84 210 0 64 219 31 98 ++4 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 194 27 87 211 0 61 215 6 80 ++215 8 82 215 7 81 215 7 81 215 7 81 216 9 84 213 0 70 ++215 1 77 210 0 70 214 0 72 32 13 20 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 167 25 75 211 0 58 ++215 3 79 215 9 82 215 7 81 215 7 81 215 7 81 215 8 82 ++215 5 79 216 10 84 211 0 61 215 6 80 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 160 33 78 ++212 0 67 215 2 77 215 9 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 216 10 84 211 0 58 219 31 98 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++134 33 69 210 0 65 213 0 75 216 9 83 215 8 81 215 7 81 ++215 7 81 215 7 81 215 7 81 216 8 83 210 0 65 202 23 85 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 85 18 42 213 0 75 213 0 70 215 7 82 215 8 81 ++215 7 81 215 7 81 215 7 81 215 8 81 215 7 81 212 0 65 ++217 16 87 35 9 18 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 40 16 25 217 16 87 212 0 69 215 8 81 ++215 8 82 215 7 81 215 7 81 215 7 81 215 8 81 215 10 83 ++213 0 73 213 0 75 186 9 72 54 21 33 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 4 1 2 202 23 85 212 0 66 ++215 3 79 215 9 82 215 7 81 215 7 81 215 7 81 215 7 81 ++216 10 83 212 0 67 219 31 98 21 8 12 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 142 22 65 ++213 0 72 213 0 71 216 8 81 215 8 82 215 7 81 215 7 81 ++215 7 81 213 0 73 119 35 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++78 24 43 215 7 82 211 0 65 215 5 81 215 10 82 215 7 81 ++215 7 81 215 8 82 212 0 71 215 5 80 147 30 72 13 6 8 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 8 3 5 183 28 83 211 0 65 213 0 72 216 10 83 ++215 8 81 215 7 81 215 6 80 213 0 75 213 0 67 217 16 87 ++73 20 39 0 0 0 0 0 0 8 3 5 18 7 11 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 85 18 42 216 9 82 212 0 68 ++215 5 81 215 9 82 215 8 82 215 10 82 215 8 81 213 0 71 ++214 0 74 154 21 68 15 6 9 0 0 0 90 31 52 57 3 22 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 18 7 11 186 26 82 ++213 0 69 214 0 72 215 5 81 215 9 82 215 7 81 215 9 83 ++215 4 78 212 0 71 214 3 78 125 28 63 42 19 27 204 18 83 ++21 8 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++73 20 39 217 16 87 214 0 71 213 0 72 216 10 83 215 10 82 ++215 7 82 215 9 82 215 1 77 212 0 68 213 2 78 213 0 69 ++219 31 98 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 110 23 54 217 16 87 212 0 67 213 0 72 ++216 9 83 215 8 82 215 8 82 215 7 82 213 1 77 214 4 79 ++211 0 62 204 18 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 3 1 2 132 19 59 217 16 87 ++212 0 69 215 1 77 215 7 81 215 9 83 215 8 82 215 8 82 ++215 7 81 214 0 68 201 9 77 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++132 19 59 214 7 81 213 0 69 212 0 68 215 5 81 215 10 82 ++215 10 82 215 9 83 214 0 71 216 12 84 21 8 12 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 107 28 56 191 22 83 214 0 71 212 0 69 ++215 1 77 215 9 82 215 10 83 212 0 69 215 6 80 96 29 53 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 47 14 26 143 30 71 ++215 0 76 210 0 65 215 0 74 215 4 78 213 0 75 213 0 67 ++213 18 87 96 29 53 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 81 25 45 158 23 71 215 7 81 215 4 78 213 0 73 ++211 0 62 212 0 72 215 2 77 167 25 75 87 25 46 11 4 6 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 58 17 31 138 29 68 ++194 27 87 215 5 79 214 0 71 212 0 67 209 0 60 210 0 65 ++214 7 81 180 25 80 136 20 62 96 29 53 73 20 39 29 1 11 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 24 8 13 47 14 26 87 25 46 138 29 68 154 21 68 ++183 28 83 210 0 70 219 31 98 215 3 79 212 0 67 219 31 98 ++219 31 98 219 31 98 132 19 59 50 16 28 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++29 1 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 86 4 33 ++72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 29 1 11 ++158 7 61 37 7 18 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 43 2 17 115 5 44 186 9 72 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 3 0 1 129 6 50 ++213 10 82 201 9 77 37 7 18 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 43 2 17 57 3 22 100 5 39 ++143 7 55 201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 43 2 17 158 7 61 215 10 83 ++215 10 83 215 10 83 201 9 77 37 7 18 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 4 1 2 143 7 55 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 201 9 77 37 7 18 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 129 6 50 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 37 7 18 129 6 50 201 9 77 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 37 7 18 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 43 2 17 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++43 2 17 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 ++29 1 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++43 2 17 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 143 7 55 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 213 10 82 158 7 61 ++72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 143 7 55 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 129 6 50 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 158 7 61 14 1 6 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 129 6 50 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 186 9 72 57 3 22 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 129 6 50 215 10 83 ++215 10 83 213 10 82 143 7 55 29 1 11 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 129 6 50 ++215 10 83 186 9 72 43 2 17 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++129 6 50 57 3 22 3 0 1 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 72 3 28 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++14 1 6 57 3 22 72 3 28 100 5 39 100 5 39 100 5 39 ++100 5 39 72 3 28 43 2 17 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++14 1 6 72 3 28 100 5 39 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 72 3 28 129 6 50 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 57 3 22 86 4 33 100 5 39 100 5 39 72 3 28 ++29 1 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 14 1 6 86 4 33 86 4 33 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 14 1 6 57 3 22 57 3 22 100 5 39 ++100 5 39 100 5 39 100 5 39 100 5 39 57 3 22 57 3 22 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 29 1 11 100 5 39 43 2 17 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 100 5 39 100 5 39 100 5 39 100 5 39 86 4 33 ++43 2 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 72 3 28 129 6 50 186 9 72 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 115 5 44 57 3 22 ++57 3 22 57 3 22 86 4 33 100 5 39 129 6 50 172 8 66 ++215 10 83 215 10 83 129 6 50 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 57 3 22 57 3 22 86 4 33 100 5 39 115 5 44 ++158 7 61 215 10 83 215 10 83 172 8 66 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 100 5 39 ++201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 172 8 66 72 3 28 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 ++57 3 22 100 5 39 143 7 55 201 9 77 215 10 83 86 4 33 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 86 4 33 ++143 7 55 201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 172 8 66 86 4 33 14 1 6 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 29 1 11 ++57 3 22 100 5 39 172 8 66 215 10 83 215 10 83 57 3 22 ++0 0 0 0 0 0 0 0 0 29 1 11 129 6 50 201 9 77 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 186 9 72 86 4 33 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++14 1 6 100 5 39 201 9 77 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 86 4 33 129 6 50 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++43 2 17 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 158 7 61 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 43 2 17 172 8 66 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 158 7 61 14 1 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 29 1 11 158 7 61 158 7 61 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 57 3 22 129 6 50 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 201 9 77 72 3 28 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 115 5 44 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 ++0 0 0 0 0 0 86 4 33 201 9 77 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 158 7 61 14 1 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 72 3 28 ++201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 14 1 6 0 0 0 ++186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 86 4 33 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 129 6 50 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 129 6 50 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 29 1 11 201 9 77 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 172 8 66 14 1 6 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 14 1 6 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++72 3 28 172 8 66 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 115 5 44 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 14 1 6 201 9 77 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 ++0 0 0 86 4 33 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 143 7 55 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 115 5 44 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 158 7 61 0 0 0 0 0 0 ++115 5 44 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 172 8 66 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 172 8 66 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 14 1 6 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++86 4 33 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 129 6 50 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 ++29 1 11 201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 129 6 50 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 115 5 44 0 0 0 0 0 0 ++100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 29 1 11 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++186 9 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 86 4 33 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 ++129 6 50 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 143 7 55 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++158 7 61 100 5 39 57 3 22 57 3 22 57 3 22 57 3 22 ++86 4 33 158 7 61 215 10 83 86 4 33 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++14 1 6 201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++201 9 77 14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 143 7 55 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 86 4 33 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 201 9 77 143 7 55 100 5 39 57 3 22 43 2 17 ++0 0 0 14 1 6 57 3 22 100 5 39 201 9 77 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 86 4 33 ++215 10 83 215 10 83 215 10 83 129 6 50 72 3 28 57 3 22 ++57 3 22 72 3 28 158 7 61 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 172 8 66 57 3 22 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 57 3 22 43 2 17 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 186 9 72 ++100 5 39 215 10 83 215 10 83 215 10 83 143 7 55 57 3 22 ++14 1 6 43 2 17 86 4 33 186 9 72 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 14 1 6 215 10 83 215 10 83 215 10 83 186 9 72 ++86 4 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 172 8 66 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 115 5 44 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 29 1 11 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 172 8 66 ++215 10 83 201 9 77 43 2 17 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++43 2 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 129 6 50 14 1 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 158 7 61 ++186 9 72 215 10 83 215 10 83 86 4 33 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 14 1 6 172 8 66 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 172 8 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 158 7 61 201 9 77 100 5 39 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 29 1 11 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 186 9 72 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++86 4 33 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 172 8 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 ++215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 186 9 72 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 29 1 11 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 72 3 28 29 1 11 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++143 7 55 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 186 9 72 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 43 2 17 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 186 9 72 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 86 4 33 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 72 3 28 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++86 4 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 72 3 28 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++86 4 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 129 6 50 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++72 3 28 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 115 5 44 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 43 2 17 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++129 6 50 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 129 6 50 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 72 3 28 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 186 9 72 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 186 9 72 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++14 1 6 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++72 3 28 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 158 7 61 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 201 9 77 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 158 7 61 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++143 7 55 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++29 1 11 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 158 7 61 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 143 7 55 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 29 1 11 57 3 22 100 5 39 ++100 5 39 100 5 39 100 5 39 100 5 39 100 5 39 100 5 39 ++100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 43 2 17 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 172 8 66 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++86 4 33 143 7 55 201 9 77 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 86 4 33 186 9 72 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 14 1 6 158 7 61 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 14 1 6 172 8 66 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 172 8 66 158 7 61 158 7 61 158 7 61 158 7 61 ++158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++43 2 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 172 8 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 186 9 72 100 5 39 29 1 11 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++43 2 17 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 158 7 61 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++86 4 33 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 129 6 50 14 1 6 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 143 7 55 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 129 6 50 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++86 4 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 14 1 6 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43 2 17 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++201 9 77 14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 72 3 28 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++129 6 50 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++72 3 28 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 43 2 17 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 143 7 55 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 172 8 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 172 8 66 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 29 1 11 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++29 1 11 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 201 9 77 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++72 3 28 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 143 7 55 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 201 9 77 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 143 7 55 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 129 6 50 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++115 5 44 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 86 4 33 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 72 3 28 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 86 4 33 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 29 1 11 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 86 4 33 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 ++201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 143 7 55 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 86 4 33 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++14 1 6 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++129 6 50 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++129 6 50 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 86 4 33 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++43 2 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 29 1 11 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++29 1 11 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 86 4 33 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++43 2 17 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 172 8 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 ++201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 72 3 28 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 86 4 33 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 158 7 61 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 143 7 55 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 86 4 33 215 10 83 215 10 83 ++186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 143 7 55 ++29 1 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 86 4 33 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 172 8 66 ++215 10 83 186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 43 2 17 201 9 77 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 29 1 11 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 143 7 55 29 1 11 0 0 0 0 0 0 ++0 0 0 43 2 17 129 6 50 215 10 83 215 10 83 215 10 83 ++86 4 33 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 14 1 6 172 8 66 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 129 6 50 86 4 33 57 3 22 0 0 0 0 0 0 ++0 0 0 43 2 17 86 4 33 115 5 44 0 0 0 0 0 0 ++0 0 0 201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 129 6 50 43 2 17 ++0 0 0 0 0 0 43 2 17 100 5 39 201 9 77 215 10 83 ++215 10 83 86 4 33 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 86 4 33 201 9 77 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 158 7 61 ++201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 186 9 72 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 43 2 17 201 9 77 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 115 5 44 0 0 0 0 0 0 ++0 0 0 143 7 55 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++158 7 61 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 129 6 50 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++115 5 44 57 3 22 14 1 6 0 0 0 0 0 0 43 2 17 ++86 4 33 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 129 6 50 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 43 2 17 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 86 4 33 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 43 2 17 201 9 77 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 ++0 0 0 57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 ++29 1 11 0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 158 7 61 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 129 6 50 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 129 6 50 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++14 1 6 201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 143 7 55 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 29 1 11 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 43 2 17 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 115 5 44 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 72 3 28 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 158 7 61 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 129 6 50 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 43 2 17 ++0 0 0 0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 186 9 72 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 172 8 66 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 186 9 72 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 86 4 33 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 72 3 28 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 172 8 66 14 1 6 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 158 7 61 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++86 4 33 186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 186 9 72 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 129 6 50 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 186 9 72 43 2 17 0 0 0 ++0 0 0 0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 0 0 0 ++0 0 0 0 0 0 0 0 0 14 1 6 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 158 7 61 ++43 2 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 29 1 11 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 129 6 50 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 86 4 33 201 9 77 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 143 7 55 14 1 6 0 0 0 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 115 5 44 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 172 8 66 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 115 5 44 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++186 9 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 72 3 28 143 7 55 201 9 77 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 158 7 61 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 158 7 61 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 201 9 77 100 5 39 14 1 6 0 0 0 0 0 0 ++0 0 0 0 0 0 158 7 61 215 10 83 186 9 72 158 7 61 ++158 7 61 158 7 61 158 7 61 186 9 72 172 8 66 14 1 6 ++0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 86 4 33 ++129 6 50 186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 186 9 72 115 5 44 43 2 17 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 158 7 61 ++158 7 61 158 7 61 158 7 61 158 7 61 186 9 72 201 9 77 ++14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 29 1 11 129 6 50 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++158 7 61 72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 201 9 77 29 1 11 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 215 10 83 ++158 7 61 158 7 61 186 9 72 215 10 83 215 10 83 215 10 83 ++14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 186 9 72 201 9 77 ++158 7 61 158 7 61 158 7 61 158 7 61 172 8 66 215 10 83 ++215 10 83 43 2 17 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43 2 17 ++72 3 28 100 5 39 100 5 39 129 6 50 158 7 61 158 7 61 ++100 5 39 100 5 39 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++29 1 11 72 3 28 100 5 39 100 5 39 100 5 39 100 5 39 ++57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 14 1 6 57 3 22 72 3 28 100 5 39 ++100 5 39 100 5 39 100 5 39 100 5 39 100 5 39 100 5 39 ++72 3 28 29 1 11 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 14 1 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++57 3 22 86 4 33 100 5 39 100 5 39 57 3 22 29 1 11 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 29 1 11 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 14 1 6 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-- +1.9.1 + + +From c84b6ebe7b01b7de19a33e8b8eaacc484e7ca627 Mon Sep 17 00:00:00 2001 +From: michalliu +Date: Mon, 28 Apr 2014 04:50:34 +0800 +Subject: [PATCH 2/3] Add option to determine whether to centers the logo + display, and option the number of logo to display. + +--- + drivers/video/console/fbcon.c | 3 +++ + drivers/video/fbmem.c | 15 ++++++++++++++- + drivers/video/logo/Kconfig | 13 +++++++++++++ + 3 files changed, 30 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c +index a01317c..3330cc7 100644 +--- a/drivers/video/console/fbcon.c ++++ b/drivers/video/console/fbcon.c +@@ -612,6 +612,9 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, + if (fb_get_color_depth(&info->var, &info->fix) == 1) + erase &= ~0x400; + logo_height = fb_prepare_logo(info, ops->rotate); ++#ifdef CONFIG_FB_LOGO_CENTERED ++ logo_height += (info->var.yres - logo_height) / 2; ++#endif + logo_lines = DIV_ROUND_UP(logo_height, vc->vc_font.height); + q = (unsigned short *) (vc->vc_origin + + vc->vc_size_row * rows); +diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c +index 5641a22..a9bb9cf 100644 +--- a/drivers/video/fbmem.c ++++ b/drivers/video/fbmem.c +@@ -505,6 +505,12 @@ static int fb_show_logo_line(struct fb_info *info, int rotate, + fb_rotate_logo(info, logo_rotate, &image, rotate); + } + ++#ifdef CONFIG_FB_LOGO_CENTERED ++ /* Center the logo in the screen */ ++ image.dx = (info->var.xres - image.width * n) / 2; ++ image.dy = (info->var.yres - image.height) / 2; ++#endif ++ + fb_do_show_logo(info, &image, rotate, n); + + kfree(palette); +@@ -658,9 +664,16 @@ int fb_prepare_logo(struct fb_info *info, int rotate) + int fb_show_logo(struct fb_info *info, int rotate) + { + int y; ++ unsigned int fb_logo_number = num_online_cpus(); ++ ++#ifdef CONFIG_NR_FB_LOGO ++ if(CONFIG_NR_FB_LOGO) { ++ fb_logo_number=CONFIG_NR_FB_LOGO; ++ } ++#endif + + y = fb_show_logo_line(info, rotate, fb_logo.logo, 0, +- num_online_cpus()); ++ fb_logo_number); + y = fb_show_extra_logos(info, y, rotate); + + return y; +diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig +index 2ee8966..7c8ba22 100644 +--- a/drivers/video/logo/Kconfig ++++ b/drivers/video/logo/Kconfig +@@ -15,6 +15,19 @@ config FB_LOGO_EXTRA + depends on FB=y + default y if SPU_BASE + ++config FB_LOGO_CENTERED ++ bool "Show the logo centered in the screen" ++ depends on FB=y ++ default y if LOGO_CUBIAN_CLUT224 ++ ++config NR_FB_LOGO ++ int "Logo count shall display in the screen" ++ depends on FB=y ++ default 0 ++ help ++ This is the amount of logo shall display in the screen, ++ the default value is zero which means automatically sets to the online CPU numbers. ++ + config LOGO_LINUX_MONO + bool "Standard black and white Linux logo" + default y +-- +1.9.1 + + +From 1f255d67a092c8b8bb3611bb00ead4955b68b7bf Mon Sep 17 00:00:00 2001 +From: michalliu +Date: Mon, 28 Apr 2014 13:10:05 +0800 +Subject: [PATCH 3/3] Update Cubian logo, capitalize the first letter "C" + +--- + drivers/video/logo/logo_cubian_clut224.ppm | 3412 ++++++++++++++-------------- + 1 file changed, 1706 insertions(+), 1706 deletions(-) + +diff --git a/drivers/video/logo/logo_cubian_clut224.ppm b/drivers/video/logo/logo_cubian_clut224.ppm +index 6d2ebeb..5abf577 100644 +--- a/drivers/video/logo/logo_cubian_clut224.ppm ++++ b/drivers/video/logo/logo_cubian_clut224.ppm +@@ -735,9 +735,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 8 3 5 0 0 0 +-0 0 0 0 0 0 35 9 18 100 5 39 64 24 39 21 8 12 +-19 7 11 54 21 33 78 24 43 42 19 27 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 9 3 5 0 0 0 ++0 0 0 0 0 0 32 12 19 110 22 53 64 23 38 22 10 14 ++21 6 11 55 20 32 79 23 43 41 17 25 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -765,8 +765,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-15 6 9 70 20 37 158 23 71 129 6 50 6 3 4 0 0 0 +-0 0 0 0 0 0 30 13 19 45 14 25 0 0 0 0 0 0 ++14 6 9 74 19 38 158 22 70 130 4 47 6 3 4 0 0 0 ++0 0 0 0 0 0 30 14 19 44 14 25 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -794,10 +794,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-125 28 63 216 11 85 116 21 55 116 21 55 177 29 82 204 18 83 +-215 2 77 215 10 84 110 23 54 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 96 29 53 186 9 72 +-119 35 66 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++129 30 65 216 11 85 110 22 53 116 26 58 181 30 84 205 16 79 ++215 2 77 215 10 84 110 22 53 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 96 28 53 186 7 71 ++118 42 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -823,12 +823,12 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 19 7 11 143 30 71 215 4 80 ++0 0 0 0 0 0 0 0 0 21 6 11 142 26 67 215 4 80 + 213 0 71 215 0 73 213 0 76 213 0 76 213 0 72 215 0 73 +-215 5 80 167 25 75 143 7 55 219 31 98 217 21 91 187 21 79 +-167 25 75 145 33 73 113 34 62 28 12 17 0 0 0 3 1 2 +-0 0 0 0 0 0 9 3 5 14 1 6 9 3 5 0 0 0 +-62 22 36 217 21 91 70 20 37 3 0 1 0 0 0 0 0 0 ++215 6 80 169 30 80 132 20 59 219 31 98 217 21 91 190 21 82 ++158 22 70 145 33 73 118 42 70 30 14 19 0 0 0 4 1 2 ++0 0 0 0 0 0 10 3 6 13 5 7 10 3 6 0 0 0 ++62 23 37 217 21 91 70 21 38 2 0 1 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -853,13 +853,13 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 85 18 42 183 28 83 213 0 71 212 0 69 215 1 77 ++0 0 0 74 19 38 181 30 84 213 0 71 212 0 69 215 1 77 + 215 7 82 215 8 82 215 8 81 215 8 81 215 9 82 215 8 82 + 215 8 81 214 0 75 215 0 74 212 0 68 213 0 69 215 0 76 +-212 0 69 158 7 61 64 24 39 54 21 33 57 3 22 105 27 53 +-154 21 68 202 23 85 216 11 85 215 4 78 216 10 83 167 25 75 +-145 33 73 213 0 72 212 0 65 217 21 91 160 33 78 85 18 42 +-19 7 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++212 0 69 154 5 57 64 23 38 53 19 31 73 1 23 106 29 55 ++154 23 69 201 22 84 216 11 85 215 4 78 216 10 83 166 29 77 ++144 32 72 213 0 72 212 0 65 217 21 91 163 31 78 74 19 38 ++21 6 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -882,14 +882,14 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 122 32 64 +-202 23 85 213 0 72 212 0 67 213 2 78 216 10 83 215 8 82 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 123 28 62 ++201 22 84 213 0 72 212 0 67 214 3 78 216 10 83 215 8 82 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 8 82 215 8 82 215 10 82 215 10 82 215 8 82 +-214 8 82 201 9 77 215 0 76 213 0 70 215 1 78 212 0 69 +-212 0 69 213 0 70 215 2 77 215 9 82 215 3 77 213 0 69 ++214 8 82 196 8 75 215 0 76 213 0 70 215 1 78 212 0 69 ++211 0 69 213 0 70 215 2 77 215 9 82 215 3 77 213 0 69 + 212 0 71 215 10 84 215 8 82 213 0 69 212 0 67 215 1 79 +-215 10 83 186 9 72 122 32 64 28 12 17 0 0 0 0 0 0 ++215 10 83 186 7 71 118 28 60 26 11 17 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -912,15 +912,15 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 24 8 13 145 33 73 214 0 76 212 0 67 ++0 0 0 0 0 0 24 7 13 145 33 73 213 0 76 212 0 67 + 212 0 71 215 4 78 215 9 83 215 8 82 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 8 81 215 4 80 213 0 73 213 0 76 215 7 82 215 9 82 + 216 8 82 215 10 82 215 8 82 215 7 81 215 7 82 215 10 82 + 215 8 82 215 7 81 215 7 81 215 10 84 215 9 82 215 4 79 +-213 0 76 215 0 74 213 0 71 213 0 69 219 31 98 87 25 46 +-3 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++213 0 76 215 0 74 213 0 71 213 0 69 219 31 98 86 25 47 ++4 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -942,7 +942,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-47 14 26 158 23 71 213 0 71 212 0 67 215 0 76 215 9 82 ++47 15 26 155 31 75 213 0 71 212 0 67 215 0 76 215 9 82 + 216 9 82 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +@@ -950,7 +950,7 @@ P3 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 81 + 215 8 82 215 9 82 215 7 81 215 0 76 212 0 68 212 0 67 +-215 10 84 134 33 69 24 8 13 0 0 0 0 0 0 0 0 0 ++215 10 84 134 32 68 24 7 13 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -971,8 +971,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 42 19 27 172 8 66 +-214 7 81 213 0 67 215 4 78 215 9 83 215 8 82 215 7 81 ++0 0 0 0 0 0 0 0 0 0 0 0 47 15 26 179 21 77 ++215 7 81 212 0 67 215 4 78 215 9 83 215 8 82 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +@@ -980,8 +980,8 @@ P3 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 8 82 215 9 82 216 9 83 +-213 0 75 212 0 67 214 5 77 151 31 73 19 7 11 0 0 0 +-0 0 0 0 0 0 19 7 11 43 2 17 47 14 26 19 7 11 ++213 0 75 212 0 67 214 4 78 152 30 73 18 7 11 0 0 0 ++0 0 0 0 0 0 21 6 11 44 14 25 47 15 26 21 6 11 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1001,7 +1001,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 26 9 15 158 23 71 214 0 74 212 0 72 ++0 0 0 0 0 0 28 11 17 158 22 70 213 0 74 212 0 72 + 213 0 73 215 10 83 215 8 82 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +@@ -1010,9 +1010,9 @@ P3 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 10 82 216 8 81 213 0 73 210 0 65 214 3 78 145 33 73 +-113 34 62 170 31 81 215 7 81 214 0 76 213 1 77 215 0 74 +-173 32 82 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 82 216 8 81 213 0 73 209 0 65 214 3 78 145 33 73 ++113 34 62 169 30 80 215 7 81 213 0 76 213 0 76 215 0 74 ++181 30 84 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1031,7 +1031,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 134 33 69 215 1 77 212 0 71 213 0 75 215 7 81 ++0 0 0 134 32 68 215 1 77 212 0 71 213 0 75 215 7 81 + 215 10 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +@@ -1040,9 +1040,9 @@ P3 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 215 8 82 216 9 81 213 0 75 210 0 65 ++215 7 81 215 7 81 215 8 82 216 9 81 213 0 75 209 0 65 + 212 0 65 212 0 72 215 0 76 215 7 81 215 4 78 215 0 74 +-210 1 58 119 35 66 0 0 0 0 0 0 0 0 0 0 0 0 ++207 3 57 120 35 65 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1060,7 +1060,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 70 20 37 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 74 19 38 + 216 12 84 211 0 68 213 0 75 216 9 83 215 8 82 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +@@ -1072,7 +1072,7 @@ P3 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 216 9 82 + 215 8 82 215 8 82 215 8 82 215 7 81 215 8 82 215 10 83 +-213 0 75 216 8 81 54 21 33 0 0 0 83 26 46 29 1 11 ++213 0 75 216 8 81 62 23 37 0 0 0 83 26 46 25 7 13 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1090,7 +1090,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 154 21 68 213 0 75 ++0 0 0 0 0 0 0 0 0 0 0 0 158 22 70 213 0 75 + 215 0 73 215 7 81 215 8 82 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +@@ -1102,7 +1102,7 @@ P3 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-216 10 83 212 0 71 210 0 64 96 29 53 8 3 5 147 30 72 ++216 10 83 212 0 71 211 0 63 96 28 53 9 3 5 149 32 74 + 58 17 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1120,7 +1120,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 35 9 18 217 16 87 212 0 69 215 2 77 ++0 0 0 0 0 0 38 14 23 217 16 87 211 0 69 215 2 77 + 215 9 83 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +@@ -1132,8 +1132,8 @@ P3 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 216 10 83 213 0 76 213 0 67 142 22 65 83 26 46 +-215 6 80 117 32 63 0 0 0 0 0 0 0 0 0 0 0 0 ++215 7 81 216 10 83 213 0 76 212 0 67 154 5 57 83 26 46 ++215 6 80 113 34 62 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1149,8 +1149,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 31 52 +-42 19 27 62 22 36 214 0 71 212 0 70 216 8 83 215 8 82 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 91 31 52 ++44 14 25 62 23 37 214 0 71 212 0 70 216 8 83 215 8 82 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +@@ -1162,8 +1162,8 @@ P3 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 215 9 82 215 5 80 212 0 70 213 10 82 +-215 2 77 211 0 63 194 27 87 6 3 4 0 0 0 0 0 0 ++215 7 81 215 7 81 215 9 82 215 6 80 212 0 70 213 10 82 ++215 2 77 211 0 63 196 24 85 5 2 3 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1179,21 +1179,21 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 21 8 12 210 1 58 +-216 11 85 213 3 76 215 0 74 215 10 83 215 7 81 215 7 81 ++0 0 0 0 0 0 0 0 0 0 0 0 22 10 14 207 3 57 ++216 11 85 214 1 75 215 0 74 215 10 83 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 8 82 215 8 82 215 8 82 +-215 7 81 215 6 80 214 3 78 213 0 75 215 4 80 215 6 80 +-213 0 76 215 0 74 212 0 74 212 0 69 215 7 81 213 0 73 +-211 0 65 213 0 73 216 9 83 212 0 67 215 0 74 213 0 76 ++215 7 81 215 6 80 213 4 77 213 0 75 215 4 80 215 6 80 ++213 0 76 215 0 74 213 0 74 212 0 69 215 7 81 213 0 73 ++212 0 66 213 0 73 216 9 83 212 0 67 215 0 74 213 0 76 + 213 0 74 213 0 76 215 4 79 215 7 82 215 8 82 215 8 82 + 215 8 82 215 8 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 8 81 215 9 82 215 2 77 +-215 8 82 215 5 79 212 0 68 215 1 77 76 23 42 0 0 0 ++215 8 82 214 4 79 212 0 68 215 1 77 79 23 43 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1209,21 +1209,21 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 32 13 20 215 10 84 212 1 64 ++0 0 0 0 0 0 0 0 0 32 12 19 215 10 84 212 0 64 + 213 0 75 215 3 77 215 9 82 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 9 82 215 6 80 215 3 77 213 0 73 214 0 75 +-211 0 65 212 0 66 212 0 66 186 9 72 213 0 76 212 0 69 +-217 16 87 198 18 82 187 21 79 160 33 78 115 5 44 127 25 61 +-134 33 69 127 25 61 115 5 44 155 33 77 180 25 80 187 21 79 +-202 23 85 214 15 84 213 0 72 213 0 73 212 0 71 213 0 71 ++212 0 65 212 0 66 212 0 66 186 7 71 213 0 76 212 0 69 ++217 16 87 197 20 84 187 21 79 163 31 78 118 3 42 126 24 61 ++134 32 68 126 24 61 118 3 42 155 31 75 179 21 77 187 21 79 ++201 22 84 216 12 84 213 0 72 213 0 73 212 0 71 213 0 71 + 215 0 76 215 4 79 215 7 81 215 9 83 215 8 82 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 +-215 7 81 215 8 82 216 10 83 213 0 74 213 0 67 145 33 73 ++215 7 81 215 8 82 216 10 83 213 0 74 212 0 67 145 33 73 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1239,16 +1239,16 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 64 24 39 213 0 67 212 0 70 216 10 84 ++0 0 0 0 0 0 64 23 38 212 0 67 212 0 70 216 10 84 + 215 8 82 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 +-216 9 83 213 0 72 214 0 72 215 1 78 217 21 91 132 19 59 +-45 14 25 32 13 20 15 6 9 28 12 17 45 14 25 28 12 17 ++216 9 83 213 0 72 214 0 72 215 1 78 217 21 91 132 20 59 ++44 14 25 32 12 19 15 7 10 26 11 17 44 14 25 28 11 17 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 26 9 15 47 14 26 125 28 63 191 22 83 ++0 0 0 0 0 0 28 11 17 47 15 26 118 28 60 190 21 82 + 216 9 83 215 0 76 212 0 67 212 0 67 215 0 74 215 9 82 + 215 9 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +@@ -1269,18 +1269,18 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 78 24 43 212 0 67 215 0 76 215 9 83 215 7 81 ++0 0 0 79 23 43 212 0 67 215 0 76 215 9 83 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 215 7 81 215 7 81 215 10 82 213 1 77 +-212 0 69 215 10 83 129 26 63 21 8 12 0 0 0 0 0 0 +-0 0 0 26 9 15 3 1 2 0 0 0 0 0 0 0 0 0 ++215 7 81 215 7 81 215 7 81 215 7 81 215 10 82 213 0 76 ++212 0 69 215 10 83 129 30 65 20 7 12 0 0 0 0 0 0 ++0 0 0 26 11 17 4 1 2 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 35 9 18 119 35 66 183 28 83 216 9 83 213 0 71 +-212 0 70 213 6 80 215 8 82 215 7 81 215 7 81 215 7 81 ++0 0 0 36 6 17 118 42 70 184 29 84 216 9 83 213 0 71 ++212 0 70 215 7 81 215 8 82 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 215 9 82 +@@ -1299,22 +1299,22 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-113 34 62 212 1 64 213 0 75 215 10 82 215 7 81 215 7 81 ++113 34 62 212 0 64 213 0 75 215 10 82 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 8 82 215 8 82 215 8 80 213 0 73 214 0 71 +-154 21 68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++154 23 69 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 85 18 42 +-183 28 83 212 0 66 214 0 71 215 6 80 215 8 82 215 8 81 ++0 0 0 0 0 0 0 0 0 0 0 0 10 3 6 74 19 38 ++184 29 84 212 0 66 214 0 71 215 6 80 215 8 82 215 8 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 10 82 212 1 64 213 1 77 6 3 4 0 0 0 0 0 0 ++215 10 82 212 0 64 214 3 78 6 3 4 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1328,23 +1328,23 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 142 22 65 +-212 0 74 215 0 74 215 9 83 215 7 81 215 7 81 215 7 81 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 142 26 67 ++213 0 74 215 0 74 215 9 83 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 +-215 7 82 213 0 76 213 0 72 213 0 73 215 0 76 32 13 20 ++215 7 82 213 0 76 213 0 72 213 0 73 215 0 76 38 14 23 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 13 6 8 164 30 78 213 0 74 213 0 69 215 3 79 ++0 0 0 14 6 9 166 29 77 213 0 74 214 0 70 215 3 79 + 215 9 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 216 8 83 212 0 71 212 0 69 21 8 12 0 0 0 ++215 7 81 216 8 83 212 0 71 212 0 69 22 10 14 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1358,23 +1358,23 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 162 40 83 211 0 58 ++0 0 0 0 0 0 0 0 0 0 0 0 160 37 81 211 0 58 + 215 6 80 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 8 81 215 8 82 212 0 72 +-213 0 70 215 10 82 172 8 66 85 18 42 0 0 0 0 0 0 ++213 0 70 215 10 82 165 7 62 79 23 43 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 11 4 6 173 32 82 213 0 76 ++0 0 0 0 0 0 0 0 0 10 3 6 181 30 84 213 0 76 + 213 0 72 215 9 82 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 216 11 85 209 0 60 214 15 84 8 3 5 ++215 7 81 215 7 81 216 11 85 210 0 60 216 12 84 9 3 5 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1388,19 +1388,19 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 183 28 83 211 0 63 215 7 81 ++0 0 0 0 0 0 0 0 0 181 30 84 211 0 63 215 7 81 + 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 8 82 215 8 82 215 8 81 215 3 79 214 0 76 158 23 71 +-58 17 31 58 17 31 8 3 5 0 0 0 0 0 0 0 0 0 ++215 8 82 215 8 82 215 8 81 215 3 79 213 0 76 154 23 69 ++58 17 31 58 17 31 8 3 4 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 47 14 26 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 47 15 26 + 217 16 87 214 0 72 215 5 79 215 8 82 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +@@ -1418,12 +1418,12 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 183 28 83 209 0 60 215 4 79 215 8 82 ++0 0 0 0 0 0 181 30 84 210 0 60 215 4 79 215 8 82 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 215 7 82 +-215 2 77 214 0 74 215 1 78 215 1 79 213 0 73 164 30 78 +-167 25 75 186 9 72 42 19 27 0 0 0 0 0 0 0 0 0 ++215 2 77 213 0 74 215 1 78 215 1 79 213 0 73 163 31 78 ++166 29 77 176 6 66 41 17 25 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1431,7 +1431,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 158 23 71 215 0 74 215 0 74 215 9 83 215 7 81 ++0 0 0 154 23 69 215 0 74 215 0 74 215 9 83 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 216 10 84 211 0 62 +@@ -1448,12 +1448,12 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 173 32 82 210 1 58 216 8 82 215 8 82 215 7 81 ++0 0 0 181 30 84 211 0 58 216 8 82 215 8 82 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 215 7 81 215 9 82 215 0 76 214 0 76 +-216 10 84 187 21 79 132 19 59 85 18 42 73 20 39 85 18 42 +-35 9 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 7 81 215 7 81 215 7 81 215 9 82 215 0 76 213 0 76 ++216 10 84 190 21 82 132 20 59 79 23 43 74 19 38 79 23 43 ++31 7 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1461,11 +1461,11 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 78 24 43 214 5 77 214 0 72 215 8 81 ++0 0 0 0 0 0 79 23 43 214 6 77 214 0 72 215 8 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 216 10 84 +-210 1 58 183 28 83 0 0 0 0 0 0 0 0 0 0 0 0 ++211 0 58 184 29 84 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1478,11 +1478,11 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-162 40 83 210 1 58 216 8 82 215 8 82 215 7 81 215 7 81 ++160 37 81 207 3 57 216 8 82 215 8 82 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 8 81 215 8 82 213 0 70 214 0 76 132 19 59 +-24 8 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 7 81 215 8 81 215 8 82 214 0 70 213 0 76 126 24 61 ++21 6 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1491,11 +1491,11 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 26 9 15 216 11 85 213 0 67 ++0 0 0 0 0 0 0 0 0 25 7 13 216 11 85 212 0 67 + 215 10 83 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-216 10 84 210 1 58 162 40 83 0 0 0 0 0 0 0 0 0 ++216 10 84 207 3 57 160 37 81 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1507,11 +1507,11 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 31 52 +-210 1 58 215 4 78 215 8 82 215 7 81 215 7 81 215 7 81 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 91 31 52 ++207 3 57 215 4 78 215 8 82 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 8 82 215 5 81 211 0 65 219 31 98 21 8 12 0 0 0 ++215 8 82 215 5 81 212 0 66 219 31 98 20 7 12 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1522,10 +1522,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 217 21 91 +-213 0 67 215 7 81 215 8 82 215 7 81 215 7 81 215 7 81 ++212 0 67 215 7 81 215 8 82 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 8 82 215 6 80 210 1 58 81 25 45 0 0 0 0 0 0 ++215 8 82 215 6 80 211 0 58 79 23 43 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1541,7 +1541,7 @@ P3 + 213 0 71 215 9 83 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 +-215 4 79 211 0 60 154 21 68 0 0 0 0 0 0 0 0 0 ++215 4 79 211 0 60 154 23 69 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1552,10 +1552,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-186 9 72 212 0 67 215 7 81 215 8 82 215 7 81 215 7 81 ++186 7 71 212 0 67 215 7 81 215 8 82 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 9 83 213 0 70 212 0 71 8 3 5 0 0 0 ++215 7 81 215 9 83 213 0 70 212 0 71 8 3 4 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1567,11 +1567,11 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 186 9 72 211 0 63 ++0 0 0 0 0 0 0 0 0 0 0 0 176 6 66 211 0 63 + 216 10 84 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 215 8 82 +-212 0 66 101 33 58 0 0 0 0 0 0 0 0 0 0 0 0 ++212 0 66 101 34 58 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1582,10 +1582,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 194 27 87 210 1 62 216 8 82 215 7 81 215 7 81 ++0 0 0 219 31 98 210 0 63 216 8 82 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 216 10 84 209 0 60 213 18 87 0 0 0 ++215 7 81 215 7 81 216 10 84 209 0 59 217 21 91 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1601,7 +1601,7 @@ P3 + 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 8 82 215 9 82 215 4 78 212 0 69 +-136 20 62 87 25 46 78 24 43 0 0 0 0 0 0 0 0 0 ++137 22 63 86 25 47 77 26 44 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1612,10 +1612,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 201 9 77 210 0 59 216 11 85 215 7 81 ++0 0 0 0 0 0 196 8 75 211 0 60 216 11 85 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 215 7 81 216 9 82 210 1 58 119 35 66 ++215 7 81 215 7 81 215 7 81 216 9 82 207 3 57 118 42 70 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1627,11 +1627,11 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 8 3 5 201 9 77 213 0 73 215 9 82 ++0 0 0 0 0 0 8 3 4 196 8 75 213 0 73 215 9 82 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 8 82 216 9 83 215 4 78 215 0 73 214 0 76 213 18 87 +-186 9 72 183 28 83 0 0 0 0 0 0 0 0 0 0 0 0 ++215 8 82 216 9 83 215 4 78 215 0 73 214 1 75 217 16 87 ++186 7 71 181 30 84 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1642,11 +1642,11 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 217 21 91 210 1 58 216 11 85 ++0 0 0 0 0 0 0 0 0 217 21 91 209 0 59 216 11 85 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 215 7 81 215 9 82 215 0 74 210 1 58 +-15 6 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 7 81 215 7 81 215 7 81 215 9 82 215 0 74 209 0 59 ++15 7 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1657,10 +1657,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 194 27 87 210 1 58 216 8 82 215 7 81 ++0 0 0 0 0 0 193 26 85 207 3 57 216 8 82 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 10 82 +-215 6 80 212 0 72 215 0 74 186 9 72 73 20 39 4 1 2 ++215 6 80 212 0 72 215 0 74 179 21 77 74 19 38 4 1 2 + 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1676,7 +1676,7 @@ P3 + 216 11 85 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 10 84 211 0 62 +-194 27 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++193 26 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1687,10 +1687,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 42 19 27 210 0 64 215 0 76 215 9 82 215 7 81 ++0 0 0 53 19 31 210 0 63 215 0 76 215 9 82 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 10 83 215 2 77 +-211 0 65 214 15 84 70 20 37 0 0 0 0 0 0 0 0 0 ++212 0 65 215 12 82 70 21 38 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1702,11 +1702,11 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 30 13 19 210 0 64 +-214 0 74 216 11 85 215 7 81 215 7 81 215 7 81 215 7 81 ++0 0 0 0 0 0 0 0 0 0 0 0 30 14 19 210 0 63 ++213 0 74 216 11 85 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 215 7 81 215 7 81 215 8 81 213 6 80 +-211 0 60 73 20 39 0 0 0 0 0 0 0 0 0 0 0 0 ++215 7 81 215 7 81 215 7 81 215 7 81 215 8 81 215 7 81 ++211 0 60 70 21 38 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1717,10 +1717,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 183 28 83 211 0 63 215 10 83 215 7 81 215 7 81 ++0 0 0 181 30 84 211 0 63 215 10 83 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 216 10 83 212 0 71 214 0 71 +-141 35 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++139 34 71 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1732,8 +1732,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 101 33 58 +-210 1 58 215 4 80 215 10 82 215 7 81 215 7 81 215 7 81 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 101 34 58 ++207 3 57 215 4 80 215 10 82 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 216 9 83 + 212 0 68 219 31 98 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1747,7 +1747,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-28 12 17 213 0 69 213 0 73 215 10 82 215 7 81 215 7 81 ++26 11 17 214 0 70 213 0 73 215 10 82 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 8 82 216 9 82 212 0 66 215 1 77 58 17 31 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1763,10 +1763,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-158 23 71 210 1 58 216 10 83 215 7 81 215 7 81 215 7 81 ++155 31 75 207 3 57 216 10 83 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 81 +-215 7 81 212 0 65 87 25 46 0 0 0 0 0 0 0 0 0 ++215 7 81 212 0 65 86 25 47 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1777,9 +1777,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-141 35 72 211 0 62 216 8 83 215 7 81 215 7 81 215 7 81 ++145 33 73 211 0 62 216 8 83 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 8 82 216 8 82 210 1 58 217 21 91 8 3 5 0 0 0 ++215 8 82 216 8 82 209 0 59 217 21 91 8 3 4 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1793,7 +1793,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 217 16 87 210 0 64 216 11 85 215 7 81 215 7 81 ++0 0 0 217 16 87 210 0 63 216 11 85 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 9 82 213 0 73 216 12 84 0 0 0 0 0 0 0 0 0 +@@ -1805,11 +1805,11 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 54 21 33 212 0 74 24 8 13 ++0 0 0 0 0 0 0 0 0 53 19 31 212 1 73 22 10 14 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 215 9 82 213 0 70 215 9 82 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 +-213 3 79 211 0 65 194 27 87 0 0 0 0 0 0 0 0 0 ++213 3 79 212 0 66 193 26 85 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1823,10 +1823,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 42 19 27 210 1 58 214 0 75 215 9 82 215 7 81 ++0 0 0 41 17 25 211 0 58 214 0 75 215 9 82 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 8 82 215 4 78 213 0 69 96 29 53 0 0 0 0 0 0 ++215 8 82 215 4 78 214 0 70 96 28 53 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1835,11 +1835,11 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 116 21 55 210 1 58 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 31 52 +-209 0 60 216 8 81 215 7 81 215 7 81 215 7 81 215 7 81 ++0 0 0 0 0 0 0 0 0 116 26 58 207 3 57 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 91 31 52 ++210 0 60 216 8 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 215 4 78 +-211 0 63 167 25 75 0 0 0 0 0 0 0 0 0 0 0 0 ++211 0 63 179 21 77 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1853,10 +1853,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 138 29 68 210 1 58 216 9 83 215 7 81 ++0 0 0 0 0 0 139 34 71 211 0 58 216 9 83 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 8 82 215 10 83 212 0 65 186 26 82 0 0 0 0 0 0 ++215 8 82 215 10 83 212 0 65 186 26 81 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1865,11 +1865,11 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 217 16 87 162 40 83 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 191 22 83 ++0 0 0 0 0 0 0 0 0 217 16 87 160 37 81 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 196 24 85 + 212 0 66 215 7 82 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 8 81 215 5 81 212 0 69 +-162 40 83 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++160 37 81 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1883,10 +1883,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 213 1 77 211 0 65 216 10 83 ++0 0 0 0 0 0 0 0 0 213 0 76 212 0 65 216 10 83 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 8 82 215 10 82 215 9 83 +-213 0 73 216 8 81 213 0 74 213 0 75 54 21 33 0 0 0 ++213 0 73 216 8 81 213 0 74 213 0 75 53 19 31 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1895,10 +1895,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 54 21 33 143 7 55 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 81 25 45 210 1 58 ++0 0 0 0 0 0 55 20 32 143 4 52 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 77 26 44 211 0 58 + 215 3 79 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 215 8 81 215 7 82 211 0 58 129 6 50 ++215 7 81 215 7 81 215 8 81 215 7 82 211 0 58 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1913,10 +1913,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 76 23 42 211 0 60 213 3 79 ++0 0 0 0 0 0 0 0 0 77 26 44 211 0 60 213 3 79 + 215 10 84 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 9 82 214 0 71 212 0 69 212 0 66 +-217 16 87 213 0 76 216 4 80 212 0 66 141 35 72 0 0 0 ++217 16 87 213 0 76 216 4 80 212 0 66 139 34 71 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1925,10 +1925,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 13 6 8 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 19 7 11 217 21 91 212 0 71 ++0 0 0 0 0 0 11 5 7 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 21 6 11 217 21 91 212 0 71 + 215 9 83 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 8 82 215 5 80 213 0 67 162 40 83 0 0 0 ++215 7 81 215 8 82 215 6 80 212 0 67 160 37 81 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1943,10 +1943,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 194 27 87 211 0 62 ++0 0 0 0 0 0 0 0 0 0 0 0 193 26 85 211 0 62 + 216 10 83 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 8 82 213 0 73 183 28 83 141 35 72 160 33 78 +-0 0 0 201 9 77 210 1 58 138 29 68 83 26 46 30 13 19 ++215 7 81 215 8 82 213 0 73 184 29 84 144 32 72 160 37 81 ++0 0 0 196 8 75 211 0 58 134 32 68 77 26 44 30 14 19 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1956,9 +1956,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 28 12 17 216 10 84 211 0 68 213 0 73 215 9 83 ++0 0 0 26 11 17 216 10 84 211 0 68 213 0 73 215 9 83 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 8 82 216 8 81 209 0 60 162 40 83 0 0 0 0 0 0 ++215 8 82 216 8 81 210 0 60 160 37 81 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1973,10 +1973,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 42 19 27 211 0 62 +-214 0 76 215 10 82 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 9 82 211 0 65 62 22 36 0 0 0 0 0 0 +-0 0 0 90 31 52 210 1 58 158 7 61 0 0 0 24 8 13 ++0 0 0 0 0 0 0 0 0 0 0 0 41 17 25 211 0 62 ++213 0 76 215 10 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 9 82 212 0 66 62 23 37 0 0 0 0 0 0 ++0 0 0 91 31 52 207 3 57 165 7 62 0 0 0 22 10 14 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -1986,9 +1986,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 142 22 65 209 0 60 216 8 81 215 8 82 215 7 81 ++0 0 0 142 26 67 209 0 59 216 8 81 215 8 82 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 212 0 69 180 25 80 0 0 0 0 0 0 0 0 0 ++215 7 81 211 0 69 178 28 81 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2003,10 +2003,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 183 28 83 +-210 0 65 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 6 80 213 0 69 105 27 53 0 0 0 0 0 0 +-0 0 0 0 0 0 215 6 80 213 0 67 3 1 2 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 181 30 84 ++209 0 65 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 6 80 214 0 70 106 29 55 0 0 0 0 0 0 ++0 0 0 0 0 0 215 6 80 212 0 67 4 1 2 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2016,9 +2016,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-21 8 12 215 3 77 213 0 69 216 11 85 215 7 81 215 7 81 ++22 10 14 215 3 77 213 0 69 216 11 85 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 10 84 +-212 1 64 202 23 85 0 0 0 0 0 0 0 0 0 0 0 0 ++212 0 64 201 22 84 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2033,10 +2033,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 21 33 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 53 19 31 + 212 0 68 213 0 74 215 8 82 215 7 81 215 7 81 215 7 81 +-215 7 81 215 9 83 212 0 66 173 32 82 0 0 0 0 0 0 +-0 0 0 0 0 0 101 33 58 210 1 58 7 2 4 0 0 0 ++215 7 81 215 9 83 212 0 66 181 30 84 0 0 0 0 0 0 ++0 0 0 0 0 0 101 34 58 207 3 57 7 2 4 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2046,7 +2046,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-117 32 63 209 0 60 216 9 84 215 7 81 215 7 81 215 7 81 ++118 28 60 209 0 59 216 9 84 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 216 12 84 212 0 65 + 213 0 69 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2064,9 +2064,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-202 23 85 212 0 68 215 9 83 215 7 81 215 7 81 215 7 81 ++201 22 84 212 0 68 215 9 83 215 7 81 215 7 81 215 7 81 + 215 7 81 215 8 82 213 0 75 215 6 80 0 0 0 0 0 0 +-0 0 0 0 0 0 4 1 2 219 31 98 29 1 11 0 0 0 ++0 0 0 0 0 0 5 2 3 219 31 98 25 7 13 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2094,9 +2094,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-113 34 62 210 0 65 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 215 7 81 214 0 72 167 25 75 215 7 82 +-28 12 17 0 0 0 0 0 0 134 33 69 101 33 58 0 0 0 ++118 42 70 209 0 65 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 214 0 72 179 21 77 215 7 82 ++26 11 17 0 0 0 0 0 0 134 32 68 101 34 58 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2106,8 +2106,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 83 26 46 +-210 1 58 216 8 82 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 215 10 82 215 4 80 210 1 58 64 24 39 ++209 0 59 216 8 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 10 82 214 4 79 211 0 58 67 23 39 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2116,17 +2116,17 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 32 13 20 110 23 54 +-164 30 78 172 8 66 186 9 72 202 23 85 202 23 85 198 18 82 +-172 8 66 167 25 75 132 19 59 42 19 27 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 30 14 19 110 22 53 ++163 31 78 176 6 66 176 6 66 201 22 84 201 22 84 197 20 84 ++179 21 77 166 29 77 132 20 59 47 15 26 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-18 7 11 215 0 74 213 0 73 215 10 82 215 7 81 215 7 81 +-215 7 81 215 7 81 215 7 81 215 10 83 213 0 69 210 1 58 +-173 32 82 0 0 0 0 0 0 62 22 36 162 40 83 0 0 0 ++15 7 10 215 0 74 213 0 73 215 10 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 215 10 83 213 0 69 211 0 58 ++173 30 81 0 0 0 0 0 0 62 23 37 160 37 81 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2135,9 +2135,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 213 10 82 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 206 9 79 + 212 0 65 215 10 83 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 216 10 84 210 1 58 162 40 83 0 0 0 ++215 7 81 215 7 81 216 10 84 207 3 57 160 37 81 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2146,17 +2146,17 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 29 1 11 145 33 73 217 21 91 214 0 72 212 0 72 +-213 0 70 215 4 79 215 1 78 212 0 65 213 0 69 213 0 71 +-215 0 74 214 0 71 212 0 74 214 0 72 217 16 87 158 23 71 +-28 12 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 21 6 11 145 33 73 217 21 91 214 0 72 212 0 72 ++214 0 70 215 4 79 215 1 78 212 0 65 213 0 69 213 0 71 ++215 0 74 214 0 71 213 0 74 214 0 72 217 16 87 155 31 75 ++32 12 19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 180 25 80 212 0 69 216 9 83 215 7 81 215 7 81 ++0 0 0 178 28 81 212 0 69 216 9 83 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 10 83 215 0 76 +-186 9 72 0 0 0 0 0 0 0 0 0 162 40 83 30 13 19 ++196 8 75 0 0 0 0 0 0 0 0 0 160 37 81 32 12 19 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2165,9 +2165,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-13 6 8 0 0 0 0 0 0 0 0 0 42 19 27 211 0 63 +-213 1 77 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 216 9 83 211 0 68 191 22 83 0 0 0 0 0 0 ++13 5 7 0 0 0 0 0 0 0 0 0 41 17 25 211 0 63 ++214 3 78 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 216 9 83 211 0 68 190 21 82 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2175,18 +2175,18 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 62 22 36 +-183 28 83 214 0 75 210 0 65 213 0 71 215 3 79 215 6 80 +-215 5 79 213 0 72 213 0 74 213 1 77 212 0 71 213 0 73 +-215 9 83 215 9 83 212 0 72 213 0 72 211 0 68 210 0 64 +-211 0 68 183 28 83 58 17 31 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 64 23 38 ++184 29 84 214 0 75 209 0 65 213 0 71 215 3 79 215 6 80 ++215 5 79 213 0 72 213 0 74 214 3 78 212 0 71 213 0 73 ++215 9 83 215 9 83 212 0 72 213 0 72 211 0 68 210 0 63 ++211 0 68 184 29 84 58 17 31 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 113 34 62 212 0 68 214 5 77 215 8 82 215 7 81 ++0 0 0 101 34 58 212 0 68 213 4 77 215 8 82 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 213 0 73 +-201 23 85 0 0 0 0 0 0 0 0 0 101 33 58 90 31 52 ++197 20 84 0 0 0 0 0 0 0 0 0 106 29 55 91 31 52 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2194,10 +2194,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 21 33 +-129 26 63 0 0 0 0 0 0 0 0 0 160 33 78 211 0 60 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 62 23 37 ++129 30 65 0 0 0 0 0 0 0 0 0 163 31 78 211 0 60 + 216 9 84 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 8 82 213 0 74 216 12 84 3 1 2 0 0 0 0 0 0 ++215 8 82 213 0 74 216 12 84 3 1 1 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2205,18 +2205,18 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 14 1 6 183 28 83 212 0 66 +-210 0 64 215 6 80 217 16 87 216 8 83 213 0 73 214 0 75 +-215 1 78 217 16 87 201 23 85 154 21 68 145 33 73 117 32 63 +-72 3 28 72 3 28 119 35 66 142 22 65 158 23 71 202 23 85 +-215 3 77 211 0 60 212 0 68 183 28 83 9 3 5 0 0 0 ++0 0 0 0 0 0 0 0 0 13 5 7 181 30 84 212 0 66 ++210 0 63 215 6 80 217 16 87 216 8 83 213 0 73 214 0 75 ++215 1 78 217 16 87 196 24 85 154 23 69 145 33 73 113 34 62 ++73 1 23 73 1 23 120 35 65 137 22 63 158 22 70 217 21 91 ++215 3 77 211 0 60 212 0 68 184 29 84 9 3 5 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 30 13 19 213 0 76 213 0 73 215 8 82 215 7 81 +-215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 215 0 74 +-215 10 84 32 13 20 0 0 0 0 0 0 42 19 27 162 40 83 ++0 0 0 30 14 19 213 0 76 213 0 73 215 8 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 214 1 75 ++215 10 84 32 12 19 0 0 0 0 0 0 41 17 25 160 37 81 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2225,9 +2225,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 219 31 98 +-110 23 54 0 0 0 0 0 0 0 0 0 215 10 82 213 0 71 ++110 22 53 0 0 0 0 0 0 0 0 0 215 10 82 213 0 71 + 215 9 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 5 79 213 10 82 212 0 66 28 12 17 0 0 0 ++215 7 81 215 5 79 213 10 82 212 0 66 26 11 17 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2235,19 +2235,19 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 87 25 46 213 0 71 212 1 64 213 3 76 +-216 12 84 215 4 78 212 0 70 213 0 72 213 18 87 154 21 68 ++0 0 0 0 0 0 86 25 47 213 0 71 212 0 64 213 4 77 ++216 12 84 215 4 78 212 0 70 213 0 72 217 21 91 154 23 69 + 58 17 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-6 3 4 85 18 42 158 7 61 212 0 68 211 0 65 127 25 61 ++5 2 3 86 25 47 165 7 62 212 0 68 212 0 65 126 24 61 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 216 9 84 214 0 72 215 9 82 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 215 0 74 +-210 0 59 64 24 39 0 0 0 0 0 0 0 0 0 119 35 66 +-6 3 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++210 0 59 62 23 37 0 0 0 0 0 0 0 0 0 118 42 70 ++7 2 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2255,9 +2255,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 213 0 74 +-9 3 5 0 0 0 0 0 0 90 31 52 211 0 63 213 3 79 ++9 3 5 0 0 0 0 0 0 91 31 52 211 0 63 213 3 79 + 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 216 12 84 212 1 64 217 16 87 0 0 0 0 0 0 ++215 7 81 216 12 84 212 0 64 217 16 87 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2265,19 +2265,19 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 154 21 68 213 0 71 213 0 73 216 10 83 216 8 81 +-212 0 71 215 3 79 191 22 83 85 18 42 0 0 0 0 0 0 ++0 0 0 154 23 69 213 0 71 213 0 73 216 10 83 216 8 81 ++212 0 71 215 3 79 190 21 82 79 23 43 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 4 1 2 132 19 59 213 0 69 ++0 0 0 0 0 0 0 0 0 4 1 2 132 20 59 213 0 69 + 219 31 98 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 164 30 78 212 0 72 215 7 82 215 7 81 +-215 7 81 215 7 81 215 7 81 215 7 81 215 6 80 204 18 83 +-213 0 72 160 33 78 0 0 0 0 0 0 0 0 0 78 24 43 +-62 22 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 166 29 77 212 0 72 215 7 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 215 6 80 205 16 79 ++213 0 72 155 31 75 0 0 0 0 0 0 0 0 0 77 26 44 ++62 23 37 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2285,9 +2285,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 219 31 98 +-0 0 0 0 0 0 0 0 0 162 40 83 210 1 58 216 11 85 ++0 0 0 0 0 0 0 0 0 160 37 81 210 0 59 216 11 85 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 82 210 1 58 68 22 37 0 0 0 0 0 0 ++215 7 81 215 7 82 211 0 58 70 21 38 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2295,49 +2295,49 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-194 27 87 210 1 58 215 5 81 216 12 84 213 0 72 213 0 70 +-194 27 87 47 14 26 0 0 0 0 0 0 0 0 0 0 0 0 ++184 29 84 207 3 57 215 5 81 216 12 84 213 0 72 213 0 70 ++193 26 85 47 15 26 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-180 25 80 217 21 91 19 7 11 0 0 0 0 0 0 0 0 0 ++179 21 77 217 21 91 21 6 11 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 96 29 53 212 0 69 215 5 80 215 8 81 +-215 7 81 215 7 81 215 7 81 215 8 82 214 0 74 180 25 80 +-54 21 33 213 6 80 0 0 0 0 0 0 0 0 0 54 21 33 +-101 33 58 6 3 4 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 96 28 53 212 0 69 215 6 80 215 8 81 ++215 7 81 215 7 81 215 7 81 215 8 82 213 0 74 186 26 81 ++55 20 32 215 7 81 0 0 0 0 0 0 0 0 0 53 19 31 ++101 34 58 5 2 3 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 31 52 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 91 31 52 + 0 0 0 0 0 0 4 1 2 215 6 80 213 0 71 215 8 82 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-216 11 85 210 1 62 214 15 84 0 0 0 0 0 0 0 0 0 ++216 11 85 210 0 63 215 12 82 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 164 30 78 +-210 1 58 216 8 83 215 9 82 211 0 63 216 10 83 85 18 42 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 166 29 77 ++211 0 58 216 8 83 215 9 82 211 0 63 216 10 83 79 23 43 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 73 20 39 186 9 72 42 19 27 0 0 0 0 0 0 ++0 0 0 74 19 38 186 7 71 41 17 25 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 78 24 43 213 0 71 215 4 78 215 8 82 +-215 7 81 215 7 81 215 7 81 215 8 82 215 1 77 212 1 64 +-0 0 0 141 35 72 62 22 36 0 0 0 0 0 0 15 6 9 +-83 26 46 42 19 27 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 77 26 44 213 0 71 215 4 78 215 8 82 ++215 7 81 215 7 81 215 7 81 215 8 82 215 1 77 212 0 64 ++0 0 0 118 42 70 62 23 37 0 0 0 0 0 0 15 7 10 ++83 26 46 47 15 26 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2345,29 +2345,29 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 1 2 +-0 0 0 0 0 0 81 25 45 210 0 64 216 10 83 215 7 81 ++0 0 0 0 0 0 79 23 43 211 0 63 216 10 83 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 +-215 6 80 210 1 58 119 35 66 0 0 0 0 0 0 0 0 0 ++215 6 80 211 0 58 118 42 70 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 119 35 66 210 1 58 +-214 3 78 216 9 84 212 1 64 194 27 87 11 4 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 118 42 70 211 0 58 ++214 3 78 216 9 84 212 0 64 193 26 85 10 3 6 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 29 1 11 119 35 66 18 7 11 0 0 0 ++0 0 0 0 0 0 25 7 13 118 42 70 18 7 11 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 45 14 25 213 0 73 215 4 78 215 8 82 +-215 7 81 215 7 81 215 7 81 215 7 81 215 7 82 211 0 61 +-141 35 72 0 0 0 19 7 11 0 0 0 0 0 0 0 0 0 +-58 17 31 70 20 37 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 44 14 25 213 0 73 215 4 78 215 8 82 ++215 7 81 215 7 81 215 7 81 215 7 81 215 7 82 211 0 60 ++118 42 70 0 0 0 18 7 11 0 0 0 0 0 0 0 0 0 ++58 17 31 70 21 38 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2375,29 +2375,29 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 194 27 87 210 0 65 216 11 85 215 7 81 ++0 0 0 0 0 0 193 26 85 209 0 65 216 11 85 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 216 9 83 +-212 0 71 210 0 70 0 0 0 0 0 0 0 0 0 0 0 0 ++212 0 71 211 0 69 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 18 7 11 210 1 58 213 0 74 +-216 8 83 211 0 63 170 31 81 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 15 7 10 209 0 59 213 0 74 ++216 8 83 211 0 63 169 30 80 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 1 0 0 15 6 9 0 0 0 ++0 0 0 0 0 0 0 0 0 2 0 1 15 7 10 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 35 9 18 211 0 62 215 7 81 215 8 82 ++0 0 0 0 0 0 36 6 17 211 0 62 215 7 81 215 8 82 + 215 7 81 215 7 81 215 7 81 215 7 81 215 9 82 212 0 71 + 215 9 82 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-40 16 25 62 22 36 0 0 0 0 0 0 0 0 0 0 0 0 ++38 14 23 62 23 37 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2407,15 +2407,15 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 213 0 76 215 1 77 215 8 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 9 82 216 4 80 +-210 0 59 83 26 46 0 0 0 0 0 0 0 0 0 0 0 0 ++210 0 59 77 26 44 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 219 31 98 211 0 61 216 11 85 +-211 0 60 143 7 55 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 219 31 98 211 0 60 216 11 85 ++211 0 60 154 5 57 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2424,10 +2424,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 162 40 83 213 0 69 215 6 80 ++0 0 0 0 0 0 0 0 0 160 37 81 214 0 70 215 6 80 + 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 215 4 78 +-212 0 66 113 34 62 0 0 0 0 0 0 0 0 0 0 0 0 +-18 7 11 30 13 19 0 0 0 0 0 0 0 0 0 0 0 0 ++212 0 66 118 42 70 0 0 0 0 0 0 0 0 0 0 0 0 ++18 7 11 30 14 19 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2435,17 +2435,17 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 101 33 58 211 0 61 215 7 82 215 7 81 215 7 81 ++0 0 0 101 34 58 211 0 60 215 7 82 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 216 11 85 212 0 65 +-186 9 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++186 7 71 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 141 35 72 211 0 60 216 11 85 210 1 58 +-162 40 83 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 139 34 71 211 0 60 216 11 85 207 3 57 ++181 30 84 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2454,9 +2454,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 119 35 66 211 0 65 215 7 81 ++0 0 0 0 0 0 0 0 0 118 42 70 212 0 66 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 9 83 +-214 0 71 215 0 74 41 16 25 0 0 0 0 0 0 0 0 0 ++214 0 71 215 0 74 41 17 25 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2465,16 +2465,16 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 194 27 87 210 0 59 216 9 83 215 7 81 215 7 81 ++0 0 0 184 29 84 210 0 59 216 9 83 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 10 82 215 3 77 211 0 62 +-62 22 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++62 23 37 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 141 35 72 210 1 58 215 6 80 210 0 59 217 21 91 ++0 0 0 145 33 73 211 0 58 215 6 80 211 0 60 217 21 91 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2484,9 +2484,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 129 26 63 214 0 72 215 7 82 ++0 0 0 0 0 0 0 0 0 126 24 61 214 0 72 215 7 82 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 82 +-213 0 73 173 32 82 0 0 0 0 0 0 0 0 0 0 0 0 ++213 0 73 173 30 81 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2495,8 +2495,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 214 5 77 213 0 73 215 9 82 215 7 81 215 7 81 +-215 7 81 215 7 81 215 7 81 216 9 84 211 0 61 186 26 82 ++0 0 0 214 6 77 213 0 73 215 9 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 7 81 216 9 84 210 1 61 186 26 81 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2504,7 +2504,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-83 26 46 210 1 58 214 3 78 212 0 74 211 0 60 11 4 6 ++77 26 44 211 0 58 214 3 78 213 0 75 211 0 60 11 5 7 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2514,9 +2514,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 141 35 72 211 0 65 215 7 81 ++0 0 0 0 0 0 0 0 0 139 34 71 212 0 66 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 81 +-215 4 80 72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 ++215 4 80 73 1 23 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2525,8 +2525,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-90 31 52 211 0 61 215 3 79 215 8 82 215 7 81 215 7 81 +-215 7 81 215 7 81 215 8 82 215 2 77 212 0 68 68 22 37 ++91 31 52 211 0 60 215 3 79 215 8 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 8 82 215 2 77 212 0 68 70 21 38 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2534,7 +2534,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-215 7 82 212 0 67 216 10 84 210 1 58 101 33 58 0 0 0 ++215 7 82 212 0 67 216 10 84 207 3 57 101 34 58 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2544,9 +2544,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 141 35 72 211 0 62 215 7 81 ++0 0 0 0 0 0 0 0 0 139 34 71 211 0 62 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 6 80 +-213 0 73 116 21 55 0 0 0 0 0 0 0 0 0 0 0 0 ++213 0 73 110 22 53 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2555,16 +2555,16 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-170 31 81 211 0 62 215 10 83 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 216 9 83 210 0 65 213 18 87 0 0 0 ++169 30 80 211 0 62 215 10 83 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 216 9 83 209 0 65 217 16 87 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 35 66 +-211 0 61 216 9 83 212 0 68 213 18 87 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 118 42 70 ++210 1 61 216 9 83 212 0 68 217 16 87 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2574,9 +2574,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 115 5 44 215 0 76 215 8 82 ++0 0 0 0 0 0 0 0 0 110 22 53 215 0 76 215 8 82 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 82 +-212 0 71 155 33 77 0 0 0 0 0 0 0 0 0 0 0 0 ++212 0 71 155 31 75 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2586,15 +2586,15 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 217 21 91 212 0 68 215 9 83 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 215 7 81 211 0 62 119 35 66 0 0 0 ++215 7 81 215 7 81 215 7 81 211 0 62 120 35 65 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 202 23 85 +-212 0 68 216 12 84 210 1 58 40 16 25 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 201 22 84 ++212 0 68 216 12 84 207 3 57 40 16 25 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2604,9 +2604,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 100 5 39 215 9 82 215 7 81 ++0 0 0 0 0 0 0 0 0 104 3 36 215 9 82 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 9 82 +-212 0 69 194 27 87 0 0 0 0 0 0 3 0 1 0 0 0 ++212 0 69 193 26 85 0 0 0 0 0 0 2 0 1 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2615,16 +2615,16 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-155 33 77 212 0 67 215 9 82 215 7 81 215 7 81 215 7 81 +-215 7 81 215 8 82 215 2 77 212 0 67 54 21 33 0 0 0 ++155 31 75 212 0 67 215 9 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 82 215 2 77 212 0 67 62 23 37 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 64 24 39 212 0 66 +-216 4 80 212 0 67 180 25 80 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 67 23 39 212 0 66 ++216 4 80 212 0 67 179 21 77 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2634,9 +2634,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 115 5 44 215 4 79 215 7 81 ++0 0 0 0 0 0 0 0 0 110 22 53 215 4 79 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 +-215 2 77 216 10 83 116 21 55 85 18 42 0 0 0 0 0 0 ++215 2 77 216 10 83 110 22 53 74 19 38 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2645,16 +2645,16 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-116 21 55 214 0 71 215 9 82 215 7 81 215 7 81 215 7 81 +-215 7 81 215 8 81 215 4 80 215 1 78 37 7 18 0 0 0 ++110 22 53 214 0 71 215 9 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 81 215 4 80 215 1 78 36 6 17 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 141 35 72 209 0 60 +-215 7 82 211 0 60 64 24 39 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 139 34 71 209 0 59 ++215 7 82 211 0 60 67 23 39 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2666,7 +2666,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 113 34 62 213 0 71 215 6 80 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 8 82 215 2 77 210 1 58 162 40 83 0 0 0 0 0 0 ++215 8 82 215 2 77 207 3 57 160 37 81 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2675,8 +2675,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-110 23 54 214 0 75 215 6 80 215 7 81 215 7 81 215 7 81 +-215 7 81 215 8 82 213 0 75 215 10 83 35 9 18 0 0 0 ++110 22 53 214 0 75 215 6 80 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 82 213 0 75 215 10 83 31 7 16 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2684,7 +2684,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 219 31 98 212 0 68 +-212 0 70 201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 ++212 0 70 206 9 79 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2694,9 +2694,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 107 28 56 214 0 71 215 7 82 ++0 0 0 0 0 0 0 0 0 116 26 58 214 0 71 215 7 82 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 9 82 212 0 74 215 4 78 0 0 0 0 0 0 0 0 0 ++215 9 82 213 0 74 215 4 78 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2705,16 +2705,16 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-119 35 66 211 0 61 215 5 79 215 8 82 215 7 81 215 7 81 +-215 7 81 215 8 82 215 0 74 217 16 87 6 3 4 0 0 0 ++118 42 70 210 1 61 215 5 79 215 8 82 215 7 81 215 7 81 ++215 7 81 215 8 82 215 0 74 217 16 87 5 2 3 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 64 24 39 211 0 60 215 3 79 +-212 0 68 138 29 68 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 64 23 38 211 0 60 214 4 79 ++212 0 68 142 26 67 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2726,7 +2726,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 113 34 62 214 0 71 215 6 80 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 82 213 0 69 177 29 82 0 0 0 0 0 0 0 0 0 ++215 7 82 213 0 69 178 28 81 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2735,28 +2735,28 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-119 35 66 210 1 62 215 5 79 215 8 82 215 7 81 215 7 81 +-215 7 81 215 8 82 215 0 74 187 21 79 0 0 0 0 0 0 ++118 42 70 210 0 63 215 5 79 215 8 82 215 7 81 215 7 81 ++215 7 81 215 8 82 215 0 74 179 21 77 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 180 25 80 210 0 65 215 4 80 +-214 0 71 76 23 42 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 178 28 81 209 0 65 214 4 79 ++214 0 71 77 26 44 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 141 35 72 162 40 83 0 0 0 0 0 0 ++0 0 0 0 0 0 139 34 71 160 37 81 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 100 5 39 215 4 78 215 8 82 ++0 0 0 0 0 0 0 0 0 104 3 36 215 4 78 215 8 82 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 +-213 1 77 212 0 65 54 21 33 0 0 0 0 0 0 0 0 0 ++212 1 78 212 0 65 62 23 37 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2765,26 +2765,26 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-119 35 66 211 0 62 215 5 79 215 8 82 215 7 81 215 7 81 +-215 7 81 215 8 82 212 0 71 167 25 75 0 0 0 0 0 0 ++118 42 70 211 0 62 215 5 79 215 8 82 215 7 81 215 7 81 ++215 7 81 215 8 82 212 0 71 166 29 77 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 83 26 46 212 0 66 215 4 80 213 0 76 +-215 1 78 13 6 8 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 83 26 46 212 0 66 214 4 79 213 0 76 ++215 1 78 14 6 9 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 3 77 186 9 72 0 0 0 0 0 0 ++0 0 0 0 0 0 215 3 77 186 7 71 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 110 23 54 215 0 76 215 8 82 ++0 0 0 0 0 0 0 0 0 110 22 53 215 0 76 215 8 82 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 9 82 + 213 0 72 215 9 83 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2795,28 +2795,28 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-119 35 66 212 0 67 215 4 80 215 8 81 215 7 81 215 7 81 +-215 7 81 215 8 82 212 0 71 154 21 68 0 0 0 0 0 0 ++118 42 70 212 0 67 215 4 80 215 8 81 215 7 81 215 7 81 ++215 7 81 215 8 82 212 0 71 154 23 69 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 158 7 61 212 0 71 216 12 84 213 0 69 +-194 27 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 165 7 62 212 0 71 216 12 84 213 0 69 ++193 26 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 194 27 87 186 9 72 0 0 0 0 0 0 ++0 0 0 0 0 0 193 26 85 186 7 71 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 122 32 64 212 0 72 215 6 80 ++0 0 0 0 0 0 0 0 0 129 30 65 212 0 72 215 6 80 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 82 215 6 80 +-211 0 61 173 32 82 0 0 0 0 0 0 0 0 0 0 0 0 ++211 0 60 181 30 84 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2825,28 +2825,28 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-116 21 55 215 0 76 215 8 82 215 7 81 215 7 81 215 7 81 +-215 7 81 215 8 82 214 0 71 129 26 63 0 0 0 0 0 0 ++110 22 53 215 0 76 215 8 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 82 214 0 71 126 24 61 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 183 28 83 212 0 70 215 9 83 214 0 71 +-154 21 68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 184 29 84 212 0 70 215 9 83 214 0 71 ++154 23 69 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 64 24 39 162 40 83 0 0 0 0 0 0 ++0 0 0 0 0 0 64 23 38 160 37 81 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 154 21 68 215 0 74 215 8 82 ++0 0 0 0 0 0 0 0 0 154 23 69 215 0 74 215 8 82 + 215 7 81 215 7 81 215 7 81 215 7 81 215 6 80 213 10 82 +-215 0 74 142 22 65 0 0 0 0 0 0 0 0 0 0 0 0 ++215 0 74 142 26 67 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2855,16 +2855,16 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-100 5 39 216 11 85 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 82 213 0 72 85 18 42 0 0 0 0 0 0 ++104 3 36 216 11 85 215 7 81 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 82 213 0 72 86 25 47 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 3 1 2 204 18 83 215 0 74 215 10 83 212 0 70 +-134 33 69 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 4 1 2 205 16 79 215 0 74 215 10 83 212 0 70 ++134 32 68 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2874,9 +2874,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 3 1 2 213 18 87 211 0 68 216 9 83 +-215 7 81 215 7 81 215 7 81 215 8 82 214 0 75 213 18 87 +-162 40 83 115 5 44 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 2 0 1 217 21 91 211 0 68 216 9 83 ++215 7 81 215 7 81 215 7 81 215 8 82 214 0 75 205 16 79 ++160 37 81 118 3 42 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2885,16 +2885,16 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-116 21 55 212 0 71 215 8 82 215 7 81 215 7 81 215 7 81 +-215 8 81 213 6 80 213 0 72 76 23 42 0 0 0 0 0 0 ++116 26 58 212 0 71 215 8 82 215 7 81 215 7 81 215 7 81 ++215 8 81 214 4 79 213 0 72 79 23 43 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 11 4 6 217 21 91 213 0 73 215 10 82 213 0 76 +-86 4 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 10 3 6 217 21 91 213 0 73 215 10 82 213 0 76 ++74 19 38 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2904,9 +2904,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 15 6 9 219 31 98 214 3 78 215 4 80 ++0 0 0 0 0 0 14 6 9 219 31 98 214 3 78 215 4 80 + 215 8 81 215 7 81 215 7 81 215 8 82 215 0 74 213 0 75 +-64 24 39 73 20 39 0 0 0 0 0 0 0 0 0 0 0 0 ++62 23 37 74 19 38 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2915,16 +2915,16 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-162 40 83 210 1 58 215 7 81 215 7 81 215 7 81 215 7 81 +-215 8 82 213 2 78 213 0 72 64 24 39 0 0 0 0 0 0 ++160 37 81 209 0 59 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 214 3 78 213 0 72 67 23 39 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 4 1 2 212 0 74 216 9 83 215 6 80 215 0 74 +-72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 4 1 2 206 0 73 216 9 83 215 6 80 215 0 74 ++74 19 38 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2934,9 +2934,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 32 13 20 162 40 83 215 4 78 215 0 74 +-215 8 82 215 7 81 215 7 81 215 8 82 213 0 71 73 20 39 +-13 6 8 54 21 33 18 7 11 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 32 12 19 160 37 81 214 4 78 215 0 74 ++215 8 82 215 7 81 215 7 81 215 8 82 213 0 71 74 19 38 ++14 6 9 55 20 32 18 7 11 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2945,16 +2945,16 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-141 35 72 213 0 67 215 9 83 215 7 81 215 7 81 215 7 81 +-215 7 82 215 4 78 215 0 74 37 7 18 0 0 0 0 0 0 ++139 34 71 212 0 66 215 9 83 215 7 81 215 7 81 215 7 81 ++215 7 82 215 4 78 215 0 74 44 14 25 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 14 1 6 216 12 84 213 3 76 216 9 83 211 0 60 +-54 21 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 13 5 7 216 12 84 213 4 77 216 9 83 211 0 60 ++55 20 32 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2964,9 +2964,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 8 3 5 0 0 0 73 20 39 212 0 68 215 7 82 +-215 7 81 215 7 81 215 7 81 215 9 83 210 0 59 0 0 0 +-0 0 0 4 1 2 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 8 3 4 0 0 0 74 19 38 212 0 68 215 7 82 ++215 7 81 215 7 81 215 7 81 215 9 83 211 0 60 0 0 0 ++0 0 0 5 2 3 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2975,16 +2975,16 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-136 20 62 214 0 74 215 8 82 215 7 81 215 7 81 215 7 81 +-215 10 82 213 0 74 217 16 87 11 4 6 0 0 0 0 0 0 ++137 22 63 213 0 74 215 8 82 215 7 81 215 7 81 215 7 81 ++215 10 82 213 0 74 217 16 87 13 5 7 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 28 12 17 219 31 98 212 0 66 216 12 84 211 0 63 +-117 32 63 30 13 19 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 28 11 17 219 31 98 212 0 66 216 12 84 211 0 63 ++118 28 60 30 14 19 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -2994,9 +2994,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 96 29 53 212 0 67 215 7 81 ++0 0 0 0 0 0 0 0 0 96 28 53 212 0 67 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 82 212 0 68 7 2 4 +-42 19 27 0 0 0 3 1 2 32 13 20 0 0 0 0 0 0 ++53 19 31 0 0 0 2 0 1 30 14 19 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3005,16 +3005,16 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-129 6 50 215 8 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 10 82 213 0 72 191 22 83 0 0 0 0 0 0 0 0 0 ++130 4 47 215 8 81 215 7 81 215 7 81 215 7 81 215 7 81 ++215 10 82 213 0 72 190 21 82 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 9 3 5 215 10 84 215 3 79 215 8 82 213 2 78 +-212 0 72 73 20 39 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 9 3 5 215 10 84 215 3 79 215 8 82 214 3 78 ++212 0 72 74 19 38 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3024,9 +3024,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 158 23 71 212 0 70 215 7 82 +-215 7 81 215 7 81 215 8 82 213 0 76 213 10 82 11 4 6 +-57 3 22 0 0 0 32 13 20 78 24 43 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 158 22 70 212 0 70 215 7 82 ++215 7 81 215 7 81 215 8 82 213 0 76 213 10 82 13 5 7 ++50 16 28 0 0 0 32 12 19 77 26 44 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3035,28 +3035,28 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-129 6 50 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 +-215 8 82 214 0 72 186 9 72 0 0 0 0 0 0 0 0 0 ++130 4 47 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 214 0 72 179 21 77 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 7 2 4 213 3 79 214 7 81 215 7 81 215 5 79 +-212 0 72 85 18 42 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 7 2 4 213 4 77 215 7 82 215 7 81 215 5 79 ++212 0 72 74 19 38 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-11 4 6 26 9 15 0 0 0 0 0 0 0 0 0 0 0 0 ++11 5 7 22 10 14 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 9 3 5 217 21 91 213 0 69 215 9 82 +-215 7 81 215 7 81 215 9 82 212 0 69 183 28 83 0 0 0 +-35 9 18 0 0 0 70 20 37 62 22 36 0 0 0 0 0 0 ++0 0 0 0 0 0 10 3 6 217 21 91 213 0 69 215 9 82 ++215 7 81 215 7 81 215 9 82 212 0 69 184 29 84 0 0 0 ++36 6 17 0 0 0 70 21 38 58 17 31 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3065,28 +3065,28 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-129 6 50 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 +-215 8 82 212 0 70 183 28 83 0 0 0 0 0 0 0 0 0 ++130 4 47 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 ++215 8 82 212 0 70 181 30 84 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 8 3 5 217 21 91 213 0 69 216 11 85 215 4 80 +-212 0 70 122 32 64 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 8 3 4 217 21 91 213 0 69 216 11 85 215 4 80 ++212 0 70 120 35 65 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 26 9 15 0 0 0 +-30 13 19 54 21 33 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 25 7 13 0 0 0 ++30 14 19 53 19 31 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 64 24 39 212 1 64 213 3 79 215 8 82 +-215 7 81 215 7 81 216 9 81 209 0 60 83 26 46 28 12 17 +-18 7 11 0 0 0 62 22 36 24 8 13 0 0 0 0 0 0 ++0 0 0 0 0 0 62 23 37 212 0 64 213 3 79 215 8 82 ++215 7 81 215 7 81 216 9 81 210 0 60 83 26 46 26 11 17 ++15 7 10 0 0 0 62 23 37 25 7 13 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3095,27 +3095,27 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-138 29 68 214 0 72 215 8 82 215 7 81 215 7 81 215 7 81 +-215 8 82 215 3 79 158 7 61 0 0 0 0 0 0 0 0 0 ++142 26 67 214 0 72 215 8 82 215 7 81 215 7 81 215 7 81 ++215 8 82 215 3 79 154 5 57 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 201 23 85 213 0 72 215 10 82 215 7 81 +-212 0 65 143 30 71 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 197 20 84 213 0 72 215 10 82 215 7 81 ++212 0 65 139 34 71 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 26 9 15 141 35 72 0 0 0 +-64 24 39 18 7 11 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 22 10 14 139 34 71 0 0 0 ++67 23 39 18 7 11 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 180 25 80 211 0 68 215 7 81 215 7 81 +-215 7 81 215 8 82 213 0 75 214 0 72 9 3 5 40 16 25 ++0 0 0 0 0 0 178 28 81 211 0 68 215 7 81 215 7 81 ++215 7 81 215 8 82 213 0 75 214 0 72 10 3 6 40 16 25 + 0 0 0 0 0 0 113 34 62 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3125,28 +3125,28 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-162 40 83 211 0 61 215 7 81 215 7 81 215 7 81 215 8 81 +-215 5 80 212 0 67 162 40 83 0 0 0 0 0 0 0 0 0 ++160 37 81 211 0 60 215 7 81 215 7 81 215 7 81 215 8 81 ++215 6 80 212 0 67 160 37 81 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 151 31 73 213 0 67 215 9 83 215 10 83 +-212 0 66 173 32 82 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 155 31 75 212 0 67 215 9 83 215 10 83 ++212 0 66 181 30 84 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 162 40 83 54 21 33 18 7 11 +-141 35 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 160 37 81 55 20 32 18 7 11 ++118 42 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 15 6 9 212 0 72 213 0 73 215 9 82 215 7 81 +-215 7 81 216 9 81 210 0 64 173 32 82 0 0 0 0 0 0 +-0 0 0 8 3 5 101 33 58 0 0 0 0 0 0 0 0 0 ++0 0 0 15 7 10 212 0 72 213 0 73 215 9 82 215 7 81 ++215 7 81 216 9 81 210 0 63 173 30 81 0 0 0 0 0 0 ++0 0 0 8 3 4 101 34 58 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3155,28 +3155,28 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-115 5 44 215 0 74 215 8 82 215 7 81 215 7 81 215 7 81 +-215 7 82 214 0 71 134 33 69 0 0 0 0 0 0 0 0 0 ++118 3 42 215 0 74 215 8 82 215 7 81 215 7 81 215 7 81 ++215 7 82 214 0 71 129 30 65 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 119 35 66 210 0 65 216 4 80 215 10 84 +-213 0 74 212 0 71 26 9 15 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 118 42 70 209 0 65 216 4 80 215 10 84 ++213 0 74 212 0 71 22 10 14 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 83 26 46 141 35 72 0 0 0 141 35 72 +-37 7 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 83 26 46 139 34 71 0 0 0 139 34 71 ++38 14 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 119 35 66 211 0 65 215 5 81 215 8 81 215 7 81 +-215 8 81 215 7 82 210 1 58 45 14 25 0 0 0 0 0 0 +-0 0 0 41 16 25 47 14 26 0 0 0 0 0 0 0 0 0 ++0 0 0 118 42 70 212 0 66 215 5 81 215 8 81 215 7 81 ++215 8 81 215 7 82 209 0 59 44 14 25 0 0 0 0 0 0 ++0 0 0 40 16 25 47 15 26 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3185,28 +3185,28 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-117 32 63 212 0 68 215 9 82 215 7 81 215 7 81 215 7 81 +-215 9 82 213 0 76 115 5 44 0 0 0 0 0 0 0 0 0 ++113 34 62 212 0 68 215 9 82 215 7 81 215 7 81 215 7 81 ++215 9 82 213 0 76 104 3 36 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 81 25 45 213 0 67 213 3 79 216 10 84 +-213 3 76 211 0 63 64 24 39 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 77 26 44 212 0 67 213 3 79 216 10 84 ++213 4 77 211 0 63 62 23 37 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 162 40 83 0 0 0 116 21 55 155 33 77 ++0 0 0 0 0 0 160 37 81 0 0 0 116 26 58 149 32 74 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 213 18 87 213 0 72 215 9 82 215 7 81 215 7 81 +-215 9 83 211 0 62 194 27 87 0 0 0 0 0 0 0 0 0 +-0 0 0 64 24 39 18 7 11 0 0 0 0 0 0 0 0 0 ++0 0 0 217 21 91 213 0 72 215 9 82 215 7 81 215 7 81 ++215 9 83 211 0 62 196 24 85 0 0 0 0 0 0 0 0 0 ++0 0 0 64 23 38 18 7 11 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3215,28 +3215,28 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-162 40 83 211 0 62 215 7 81 215 7 81 215 7 81 215 8 81 +-215 4 80 215 4 78 116 21 55 0 0 0 0 0 0 0 0 0 ++160 37 81 211 0 62 215 7 81 215 7 81 215 7 81 215 8 81 ++215 4 80 215 4 78 116 26 58 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 19 7 11 215 2 77 213 0 74 215 10 82 +-216 11 85 210 1 62 129 26 63 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 18 7 11 215 2 77 213 0 74 215 10 82 ++216 11 85 210 0 63 129 30 65 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 42 19 27 209 2 59 216 10 83 0 0 0 ++0 0 0 0 0 0 41 17 25 207 3 57 216 10 83 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 116 21 55 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 116 26 58 + 215 0 76 213 0 73 215 9 82 215 7 81 215 7 81 215 7 81 +-215 7 81 210 1 58 42 19 27 0 0 0 0 0 0 0 0 0 +-0 0 0 101 33 58 9 3 5 0 0 0 0 0 0 0 0 0 ++215 7 81 211 0 58 41 17 25 0 0 0 0 0 0 0 0 0 ++0 0 0 101 34 58 10 3 6 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3245,28 +3245,28 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-138 29 68 213 0 70 215 8 82 215 7 81 215 7 81 215 8 82 +-215 4 78 215 3 77 116 21 55 0 0 0 0 0 0 0 0 0 ++142 26 67 214 0 70 215 8 82 215 7 81 215 7 81 215 8 82 ++215 4 78 215 3 77 116 26 58 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 194 27 87 210 0 64 216 9 81 ++0 0 0 0 0 0 0 0 0 184 29 84 210 0 63 216 9 81 + 215 10 84 213 0 70 213 0 76 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 47 14 26 30 13 19 0 0 0 ++0 0 0 0 0 0 0 0 0 47 15 26 30 14 19 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 155 33 77 211 0 58 ++0 0 0 0 0 0 0 0 0 0 0 0 160 37 81 211 0 58 + 213 0 76 215 9 82 215 7 81 215 7 81 215 7 81 216 11 85 +-211 0 60 194 27 87 0 0 0 0 0 0 0 0 0 0 0 0 +-32 13 20 54 21 33 0 0 0 0 0 0 0 0 0 0 0 0 ++211 0 60 193 26 85 0 0 0 0 0 0 0 0 0 0 0 0 ++30 14 19 62 23 37 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3275,16 +3275,16 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-129 6 50 215 2 77 215 8 82 215 7 81 215 7 81 215 7 81 +-215 6 80 215 1 77 116 21 55 0 0 0 0 0 0 0 0 0 ++130 4 47 215 2 77 215 8 82 215 7 81 215 7 81 215 7 81 ++215 6 80 215 1 77 110 22 53 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 119 35 66 210 1 58 215 6 80 +-215 7 81 216 9 83 210 0 59 64 24 39 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 118 42 70 211 0 58 215 6 80 ++215 7 81 216 9 83 210 0 59 67 23 39 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3293,10 +3293,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 18 7 11 216 9 81 212 0 69 ++0 0 0 0 0 0 0 0 0 18 7 11 216 9 81 211 0 69 + 216 11 85 215 7 81 215 7 81 215 8 82 215 4 80 215 4 78 +-211 0 58 42 19 27 0 0 0 0 0 0 0 0 0 0 0 0 +-54 21 33 32 13 20 0 0 0 0 0 0 0 0 0 0 0 0 ++211 0 58 50 16 28 0 0 0 0 0 0 0 0 0 0 0 0 ++55 20 32 30 14 19 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3305,16 +3305,16 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-138 29 68 213 0 69 215 8 82 215 7 81 215 7 81 215 7 81 +-215 9 83 213 0 70 116 21 55 0 0 0 0 0 0 0 0 0 ++134 32 68 214 0 70 215 8 82 215 7 81 215 7 81 215 7 81 ++215 9 83 213 0 70 110 22 53 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 21 8 12 212 0 74 213 0 71 +-215 9 82 216 10 83 210 0 65 204 18 83 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 22 10 14 212 1 73 213 0 71 ++215 9 82 216 10 83 209 0 65 201 22 84 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3323,10 +3323,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 45 14 25 216 12 84 213 0 74 +-215 10 82 215 7 81 215 7 81 216 8 81 213 0 72 210 1 58 +-194 27 87 0 0 0 0 0 0 0 0 0 0 0 0 4 1 2 +-81 25 45 4 1 2 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 44 14 25 216 12 84 213 0 74 ++215 10 82 215 7 81 215 7 81 216 8 81 213 0 72 207 3 57 ++193 26 85 0 0 0 0 0 0 0 0 0 0 0 0 4 1 2 ++77 26 44 4 1 2 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3335,28 +3335,28 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-141 35 72 212 0 69 215 9 82 215 7 81 215 7 81 215 7 81 +-215 6 80 212 0 71 162 40 83 0 0 0 0 0 0 0 0 0 ++139 34 71 212 0 69 215 9 82 215 7 81 215 7 81 215 7 81 ++215 6 80 212 0 71 160 37 81 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 162 40 83 209 0 60 +-216 10 83 215 7 82 215 5 79 211 0 61 64 24 39 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 160 37 81 210 1 61 ++216 10 83 215 7 82 215 5 79 211 0 60 67 23 39 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 26 9 15 4 1 2 0 0 0 0 0 0 0 0 0 ++0 0 0 28 11 17 4 1 2 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 11 4 6 217 21 91 213 0 72 +-215 10 82 215 9 82 216 10 84 210 1 58 119 35 66 219 31 98 +-158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 18 7 11 +-54 21 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 10 3 6 217 21 91 213 0 72 ++215 10 82 215 9 82 216 10 84 207 3 57 118 42 70 219 31 98 ++165 7 62 0 0 0 0 0 0 0 0 0 0 0 0 18 7 11 ++53 19 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3365,27 +3365,27 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-141 35 72 211 0 61 215 7 81 215 7 81 215 7 81 215 7 81 +-215 9 82 214 0 71 172 8 66 0 0 0 0 0 0 0 0 0 ++139 34 71 211 0 60 215 7 81 215 7 81 215 7 81 215 7 81 ++215 9 82 214 0 71 165 7 62 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 13 6 8 0 0 0 32 13 20 213 0 67 +-213 0 76 215 8 82 216 9 83 210 0 64 202 23 85 0 0 0 ++0 0 0 0 0 0 14 6 9 0 0 0 32 12 19 212 0 67 ++213 0 76 215 8 82 216 9 83 210 0 63 201 22 84 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-122 32 64 186 9 72 167 25 75 162 40 83 145 33 73 143 7 55 +-219 31 98 138 29 68 0 0 0 0 0 0 0 0 0 0 0 0 ++120 35 65 176 6 66 173 30 81 160 37 81 145 33 73 143 4 52 ++219 31 98 134 32 68 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 21 8 12 212 0 70 213 2 78 +-215 8 81 216 9 84 211 0 61 204 18 83 0 0 0 41 16 25 +-164 30 78 0 0 0 0 0 0 0 0 0 0 0 0 62 22 36 ++0 0 0 0 0 0 0 0 0 22 10 14 212 0 70 214 3 78 ++215 8 81 216 9 84 210 1 61 205 16 79 0 0 0 41 17 25 ++169 30 80 0 0 0 0 0 0 0 0 0 0 0 0 62 23 37 + 6 3 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3395,27 +3395,27 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-115 5 44 215 3 79 215 8 82 215 7 81 215 7 81 215 7 81 +-215 9 82 212 0 68 180 25 80 0 0 0 0 0 0 0 0 0 ++118 3 42 215 3 79 215 8 82 215 7 81 215 7 81 215 7 81 ++215 9 82 212 0 68 178 28 81 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 1 0 0 83 26 46 0 0 0 162 40 83 +-211 0 58 216 10 84 215 7 82 216 8 81 210 1 58 96 29 53 ++0 0 0 0 0 0 2 0 1 83 26 46 0 0 0 160 37 81 ++211 0 58 216 10 84 215 7 82 216 8 81 211 0 58 91 31 52 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-32 13 20 142 22 65 213 18 87 212 1 64 211 0 61 214 0 72 +-125 28 63 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++30 14 19 154 23 69 217 16 87 212 0 64 211 0 60 214 0 72 ++123 28 62 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 194 27 87 212 0 66 216 9 83 +-215 8 82 213 4 75 209 0 60 90 31 52 0 0 0 0 0 0 +-13 6 8 3 1 2 0 0 0 0 0 0 8 3 5 54 21 33 ++0 0 0 0 0 0 0 0 0 184 29 84 212 0 66 216 9 83 ++215 8 82 214 2 74 209 0 59 91 31 52 0 0 0 0 0 0 ++14 6 9 2 0 1 0 0 0 0 0 0 8 3 4 53 19 31 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3425,27 +3425,27 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-117 32 63 212 0 72 215 5 81 215 8 81 215 7 81 215 7 81 +-215 8 82 213 0 72 213 18 87 6 3 4 0 0 0 0 0 0 ++116 26 58 212 0 72 215 5 81 215 8 81 215 7 81 215 7 81 ++215 8 82 213 0 72 217 16 87 7 2 4 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 78 24 43 64 24 39 0 0 0 ++0 0 0 0 0 0 0 0 0 77 26 44 77 26 44 0 0 0 + 211 0 63 213 0 73 215 10 82 215 10 84 213 0 70 212 0 72 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 9 3 5 50 16 28 47 14 26 ++0 0 0 0 0 0 0 0 0 10 3 6 50 16 28 47 15 26 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 201 9 77 210 1 58 215 10 82 215 7 81 +-215 9 83 214 0 68 187 21 79 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 42 19 27 13 6 8 ++0 0 0 0 0 0 196 8 75 209 0 59 215 10 82 215 7 81 ++215 9 83 213 0 69 187 21 79 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 41 17 25 11 5 7 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3456,16 +3456,16 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 83 26 46 212 0 66 215 8 80 215 7 81 215 7 81 215 7 81 +-215 10 82 213 0 76 214 0 68 64 24 39 0 0 0 0 0 0 ++215 10 82 213 0 76 213 0 69 64 23 38 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 162 40 83 0 0 0 +-90 31 52 210 1 58 215 4 80 215 7 81 216 12 84 210 0 64 +-201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 160 37 81 0 0 0 ++91 31 52 211 0 58 215 4 80 215 7 81 216 12 84 210 0 63 ++205 16 79 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3473,9 +3473,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-3 1 2 219 31 98 211 0 60 216 8 83 215 9 82 215 7 81 +-216 10 83 212 0 66 154 21 68 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 4 1 2 32 13 20 0 0 0 ++2 0 1 219 31 98 211 0 60 216 8 83 215 9 82 215 7 81 ++216 10 83 212 0 66 154 23 69 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 5 2 3 30 14 19 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3486,26 +3486,26 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 58 17 31 215 2 77 215 1 78 215 8 82 215 7 81 215 7 81 +-215 7 81 216 10 84 209 0 60 134 33 69 0 0 0 0 0 0 ++215 7 81 216 10 84 209 0 59 118 42 70 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-42 19 27 64 24 39 0 0 0 0 0 0 81 25 45 142 22 65 +-0 0 0 186 9 72 210 1 58 216 11 85 215 7 81 216 9 82 +-210 1 58 141 35 72 0 0 0 0 0 0 0 0 0 0 0 0 ++41 17 25 64 23 38 0 0 0 0 0 0 83 26 46 142 26 67 ++0 0 0 196 8 75 211 0 58 216 11 85 215 7 81 216 9 82 ++211 0 58 139 34 71 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 8 13 +-215 10 82 214 0 68 215 8 82 215 10 82 215 7 81 216 12 84 +-213 0 74 213 2 78 187 21 79 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 7 13 ++215 10 82 213 0 69 215 8 82 215 10 82 215 7 81 216 12 84 ++213 0 74 214 3 78 187 21 79 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 2 0 1 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3515,26 +3515,26 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-26 9 15 215 12 82 213 0 75 215 8 82 215 7 81 215 7 81 +-215 7 81 215 9 82 213 0 71 215 3 79 11 4 6 0 0 0 ++31 7 16 215 12 82 213 0 75 215 8 82 215 7 81 215 7 81 ++215 7 81 215 9 82 213 0 71 215 3 79 11 5 7 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-122 32 64 210 1 62 0 0 0 0 0 0 0 0 0 101 33 58 ++120 35 65 210 0 63 0 0 0 0 0 0 0 0 0 118 42 70 + 0 0 0 0 0 0 211 0 68 212 0 66 216 10 83 215 8 82 +-215 1 78 210 1 58 101 33 58 0 0 0 0 0 0 0 0 0 ++215 1 78 207 3 57 101 34 58 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 54 21 33 214 3 78 ++0 0 0 0 0 0 0 0 0 0 0 0 53 19 31 214 3 78 + 211 0 68 216 8 81 215 8 82 215 7 81 216 12 83 213 0 70 +-212 0 72 87 25 46 183 28 83 0 0 0 0 0 0 0 0 0 ++212 0 72 96 28 53 181 30 84 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3545,26 +3545,26 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-9 3 5 215 5 79 215 2 77 215 8 82 215 7 81 215 7 81 +-215 7 81 215 7 81 216 8 82 211 0 58 162 40 83 0 0 0 ++10 3 6 215 5 79 215 2 77 215 8 82 215 7 81 215 7 81 ++215 7 81 215 7 81 216 8 82 211 0 58 160 37 81 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-30 13 19 210 1 58 101 33 58 0 0 0 7 2 4 0 0 0 +-13 6 8 0 0 0 42 19 27 211 0 60 212 0 74 215 9 82 +-216 9 83 213 0 71 213 0 69 64 24 39 0 0 0 0 0 0 ++30 14 19 207 3 57 101 34 58 0 0 0 7 2 4 0 0 0 ++11 5 7 0 0 0 41 17 25 211 0 60 213 0 74 215 9 82 ++216 9 83 213 0 71 214 0 70 64 23 38 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 90 31 52 212 0 65 213 0 73 +-216 10 83 215 7 81 215 7 81 216 10 84 212 0 70 213 0 67 +-19 7 11 0 0 0 101 33 58 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 91 31 52 212 0 65 213 0 73 ++216 10 83 215 7 81 215 7 81 216 10 84 212 0 70 212 0 66 ++21 6 11 0 0 0 101 34 58 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3576,25 +3576,25 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 213 10 82 213 0 75 215 8 82 215 7 81 215 7 81 +-215 7 81 215 7 81 215 7 82 214 0 72 186 9 72 0 0 0 ++215 7 81 215 7 81 215 7 82 214 0 72 179 21 77 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 119 35 66 210 1 58 0 0 0 64 24 39 115 5 44 +-0 0 0 0 0 0 0 0 0 83 26 46 214 0 68 215 3 77 +-215 8 82 216 12 84 213 0 69 211 0 68 78 24 43 0 0 0 ++0 0 0 118 42 70 207 3 57 0 0 0 77 26 44 118 3 42 ++0 0 0 0 0 0 0 0 0 77 26 44 213 0 69 215 3 77 ++215 8 82 216 12 84 213 0 69 211 0 68 77 26 44 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 6 9 +-0 0 0 0 0 0 138 29 68 212 0 67 215 0 74 215 10 83 +-215 7 81 215 7 81 216 10 84 211 0 62 215 10 83 42 19 27 +-0 0 0 13 6 8 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 6 9 ++0 0 0 0 0 0 134 32 68 212 0 67 215 0 74 215 10 83 ++215 7 81 215 7 81 216 10 84 211 0 62 215 10 83 41 17 25 ++0 0 0 15 7 10 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3605,25 +3605,25 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 194 27 87 212 0 68 215 9 82 215 7 81 215 7 81 +-215 7 81 215 7 81 215 6 80 212 0 72 143 30 71 0 0 0 ++0 0 0 193 26 85 212 0 68 215 9 82 215 7 81 215 7 81 ++215 7 81 215 7 81 215 6 80 212 0 72 146 27 70 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 214 0 68 173 32 82 0 0 0 219 31 98 +-141 35 72 0 0 0 0 0 0 0 0 0 72 3 28 213 1 77 +-215 4 79 215 8 82 216 10 83 213 0 72 212 0 71 105 27 53 ++0 0 0 0 0 0 213 0 69 181 30 84 0 0 0 219 31 98 ++139 34 71 0 0 0 0 0 0 0 0 0 73 1 23 212 1 78 ++215 4 79 215 8 82 216 10 83 213 0 72 212 0 71 106 29 55 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 72 3 28 0 0 0 +-0 0 0 186 26 82 211 0 63 215 4 78 215 9 82 215 7 81 +-215 7 81 216 10 83 212 0 69 216 12 83 40 16 25 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 74 19 38 0 0 0 ++0 0 0 184 29 84 211 0 63 215 4 78 215 9 82 215 7 81 ++215 7 81 216 10 83 212 0 69 216 12 83 38 14 23 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3635,23 +3635,23 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 170 31 81 212 0 65 215 9 83 215 7 81 215 7 81 +-215 7 81 215 7 81 215 6 80 213 0 73 116 21 55 0 0 0 ++0 0 0 169 30 80 212 0 65 215 9 83 215 7 81 215 7 81 ++215 7 81 215 7 81 215 6 80 213 0 73 116 26 58 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 13 6 8 210 0 64 35 9 18 0 0 0 +-212 0 65 64 24 39 0 0 0 0 0 0 0 0 0 57 3 22 +-215 0 74 215 0 76 216 11 85 216 9 82 213 1 77 211 0 68 +-151 31 73 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 14 6 9 210 0 63 31 7 16 0 0 0 ++212 0 65 67 23 39 0 0 0 0 0 0 0 0 0 73 1 23 ++215 0 74 215 0 76 216 11 85 216 9 82 213 0 76 211 0 68 ++152 30 73 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 119 35 66 28 12 17 35 9 18 ++0 0 0 0 0 0 0 0 0 118 42 70 31 7 16 32 12 19 + 217 21 91 211 0 68 215 8 81 215 8 82 215 7 81 215 8 81 + 216 10 84 212 0 66 215 6 80 18 7 11 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3665,7 +3665,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 134 33 69 212 0 68 215 7 82 215 7 81 215 7 81 ++0 0 0 134 32 68 212 0 68 215 7 82 215 7 81 215 7 81 + 215 7 81 215 7 81 215 6 80 214 0 72 58 17 31 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3674,15 +3674,15 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 113 34 62 215 0 74 0 0 0 +-42 19 27 210 1 58 18 7 11 15 6 9 15 6 9 0 0 0 +-76 23 42 213 0 74 212 0 68 216 12 84 215 10 82 215 4 80 +-212 0 68 217 21 91 37 7 18 0 0 0 0 0 0 0 0 0 ++41 17 25 211 0 58 15 7 10 15 7 10 15 7 10 0 0 0 ++79 23 43 213 0 74 212 0 68 216 12 84 215 10 82 215 4 80 ++212 0 68 217 21 91 36 6 17 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 134 33 69 214 0 75 145 33 73 213 0 71 +-210 0 70 216 8 81 215 8 82 215 7 81 215 9 82 215 5 80 ++0 0 0 0 0 0 129 30 65 214 0 75 145 33 73 213 0 71 ++211 0 69 216 8 81 215 8 82 215 7 81 215 9 82 215 6 80 + 211 0 63 217 21 91 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3695,7 +3695,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 54 21 33 212 0 67 215 6 80 215 7 81 215 7 81 ++0 0 0 55 20 32 212 0 67 215 6 80 215 7 81 215 7 81 + 215 7 81 215 7 81 215 8 80 212 0 69 145 33 73 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3703,17 +3703,17 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 173 32 82 162 40 83 +-0 0 0 90 31 52 210 1 58 8 3 5 119 35 66 0 0 0 +-0 0 0 45 14 25 215 1 77 213 0 70 215 8 81 215 9 82 +-215 5 80 212 0 71 215 1 78 143 30 71 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 181 30 84 160 37 81 ++0 0 0 91 31 52 207 3 57 8 3 4 118 42 70 0 0 0 ++0 0 0 47 15 26 215 1 77 214 0 70 215 8 81 215 9 82 ++215 6 80 212 0 71 215 1 78 144 32 72 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 143 30 71 213 0 73 215 0 73 214 0 71 215 4 80 ++0 0 0 146 27 70 213 0 73 215 0 73 214 0 71 215 4 80 + 216 9 82 215 7 81 215 7 81 216 9 83 213 0 76 213 0 72 +-167 25 75 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++166 29 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3725,24 +3725,24 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 6 3 4 213 0 72 215 2 77 215 8 82 215 7 81 +-215 7 81 215 7 81 215 8 82 213 0 73 214 0 72 11 4 6 ++0 0 0 5 2 3 213 0 72 215 2 77 215 8 82 215 7 81 ++215 7 81 215 7 81 215 8 82 213 0 73 214 0 72 11 5 7 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 141 35 72 +-32 13 20 0 0 0 101 33 58 214 4 79 18 7 11 162 40 83 +-0 0 0 0 0 0 15 6 9 215 3 79 212 0 69 215 8 82 +-215 8 82 215 9 82 215 3 79 212 0 71 216 12 84 105 27 53 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 160 37 81 ++30 14 19 0 0 0 101 34 58 214 4 79 15 7 10 160 37 81 ++0 0 0 0 0 0 15 7 10 215 3 79 211 0 69 215 8 82 ++215 8 82 215 9 82 215 3 79 212 0 71 216 12 84 106 29 55 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 +-202 23 85 213 0 70 215 4 79 215 9 82 215 8 82 215 8 81 +-215 7 81 215 8 81 216 8 83 212 0 68 213 0 73 85 18 42 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 1 15 ++217 21 91 213 0 70 215 4 79 215 9 82 215 8 82 215 8 81 ++215 7 81 215 8 81 216 8 83 212 0 68 213 0 73 86 25 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3756,7 +3756,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 216 9 81 213 0 72 215 10 82 215 7 81 +-215 7 81 215 7 81 215 7 81 216 10 84 209 0 60 183 28 83 ++215 7 81 215 7 81 215 7 81 216 10 84 209 0 59 181 30 84 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3764,15 +3764,15 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-11 4 6 0 0 0 0 0 0 100 5 39 201 9 77 62 22 36 +-198 18 82 0 0 0 0 0 0 0 0 0 194 27 87 211 0 62 ++11 5 7 0 0 0 0 0 0 104 3 36 206 9 79 58 17 31 ++197 20 84 0 0 0 0 0 0 0 0 0 193 26 85 211 0 62 + 215 4 80 215 9 82 215 8 81 215 9 82 215 0 76 213 0 69 +-217 21 91 136 20 62 40 16 25 0 0 0 0 0 0 0 0 0 ++217 21 91 137 22 63 40 16 25 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 73 20 39 58 17 31 127 25 61 202 23 85 213 3 76 ++0 0 0 74 19 38 58 17 31 126 24 61 201 22 84 213 4 77 + 214 0 72 215 9 82 215 8 81 215 7 81 215 7 81 215 8 82 +-215 9 82 215 1 78 211 0 68 194 27 87 13 6 8 0 0 0 ++215 9 82 215 1 78 211 0 68 193 26 85 14 6 9 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3785,8 +3785,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 173 32 82 210 0 65 216 11 85 215 7 81 +-215 7 81 215 7 81 215 8 81 215 4 80 214 0 74 142 22 65 ++0 0 0 0 0 0 173 30 81 209 0 65 216 11 85 215 7 81 ++215 7 81 215 7 81 215 8 81 215 4 80 213 0 74 146 27 70 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3794,15 +3794,15 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 90 31 52 180 25 80 +-145 33 73 216 10 84 3 1 2 0 0 0 0 0 0 145 33 73 +-213 0 70 213 0 71 216 10 83 215 7 81 215 8 82 215 7 82 +-214 0 75 213 0 73 215 6 80 204 18 83 132 19 59 45 14 25 ++0 0 0 0 0 0 0 0 0 0 0 0 91 31 52 179 21 77 ++145 33 73 216 10 84 4 1 2 0 0 0 0 0 0 145 33 73 ++214 0 70 213 0 71 216 10 83 215 7 81 215 8 82 215 7 82 ++214 0 75 213 0 73 215 6 80 205 16 79 132 20 59 44 14 25 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 64 24 39 154 21 68 +-215 7 82 215 4 78 214 8 82 214 0 74 212 0 74 215 6 80 ++0 0 0 0 0 0 0 0 0 0 0 0 64 23 38 158 22 70 ++215 7 82 215 4 78 214 8 82 213 0 74 213 0 74 215 6 80 + 215 8 82 215 7 81 215 7 81 215 8 82 215 9 82 213 0 76 +-212 0 69 216 9 82 85 18 42 0 0 0 0 0 0 0 0 0 ++212 0 69 216 9 82 86 25 47 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3815,8 +3815,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 101 33 58 211 0 62 215 7 82 215 7 81 +-215 7 81 215 7 81 215 8 82 215 5 79 210 0 59 101 33 58 ++0 0 0 0 0 0 101 34 58 211 0 62 215 7 82 215 7 81 ++215 7 81 215 7 81 215 8 82 215 5 79 211 0 60 101 34 58 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3824,15 +3824,15 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 29 1 11 +-164 30 78 217 21 91 217 16 87 81 25 45 0 0 0 0 0 0 +-68 22 37 213 6 80 212 0 68 216 9 84 215 8 82 215 8 81 +-215 8 82 215 8 82 215 4 79 215 0 76 214 0 76 215 0 76 +-215 4 78 219 31 98 167 25 75 145 33 73 129 6 50 129 6 50 +-143 30 71 167 25 75 213 18 87 215 4 80 213 0 70 212 0 74 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 25 7 13 ++166 29 77 217 21 91 217 16 87 79 23 43 0 0 0 0 0 0 ++67 23 39 214 4 79 212 0 68 216 9 84 215 8 82 215 8 81 ++215 8 82 215 8 82 215 4 79 215 0 76 213 0 76 215 0 76 ++215 4 78 219 31 98 166 29 77 149 32 74 118 3 42 130 4 47 ++142 26 67 158 22 70 217 16 87 214 4 79 213 0 70 213 0 74 + 215 3 77 215 5 79 215 4 79 215 8 82 215 8 82 215 8 81 + 215 7 81 215 8 82 215 7 82 213 0 76 214 0 72 215 7 81 +-147 30 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++146 27 70 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3845,8 +3845,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 19 7 11 212 0 70 216 4 80 215 7 81 +-215 7 81 215 7 81 215 7 81 216 11 85 211 0 61 194 27 87 ++0 0 0 0 0 0 20 7 12 212 0 70 216 4 80 215 7 81 ++215 7 81 215 7 81 215 7 81 216 11 85 210 1 61 193 26 85 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3855,13 +3855,13 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 119 35 66 215 7 81 210 1 58 167 25 75 4 1 2 +-0 0 0 13 6 8 214 15 84 209 0 60 213 0 75 215 6 80 ++0 0 0 118 42 70 215 7 81 207 3 57 179 21 77 4 1 2 ++0 0 0 14 6 9 217 16 87 209 0 59 213 0 75 215 6 80 + 215 6 80 215 8 82 215 8 82 215 8 82 215 8 82 215 5 79 + 215 5 79 213 0 73 215 0 73 212 0 67 215 8 82 215 8 82 + 212 0 71 215 0 76 215 0 76 215 3 79 215 6 80 215 8 82 + 215 7 82 215 8 81 215 8 82 215 8 82 215 8 82 215 5 81 +-215 5 79 213 0 75 213 0 70 214 4 79 127 25 61 21 8 12 ++215 5 79 213 0 75 213 0 70 214 4 79 126 24 61 20 7 12 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3875,9 +3875,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 213 18 87 212 0 67 216 11 85 ++0 0 0 0 0 0 0 0 0 217 21 91 212 0 67 216 11 85 + 215 7 81 215 7 81 215 7 81 215 10 82 215 2 77 211 0 62 +-54 21 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++53 19 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3885,9 +3885,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 40 16 25 217 21 91 210 0 64 213 0 75 +-115 5 44 0 0 0 54 21 33 85 18 42 217 21 91 212 0 71 +-214 0 76 214 0 74 215 0 76 215 3 77 215 5 80 215 8 82 ++0 0 0 0 0 0 38 14 23 217 21 91 211 0 63 213 0 75 ++118 3 42 0 0 0 53 19 31 86 25 47 217 21 91 212 0 71 ++213 0 76 213 0 74 215 0 76 215 3 77 215 6 80 215 8 82 + 215 8 82 215 9 82 215 9 82 216 10 83 215 7 81 215 8 81 + 215 8 82 215 8 82 215 8 82 215 8 82 215 8 82 215 8 82 + 215 8 82 215 7 81 215 3 79 215 3 77 214 0 72 212 0 72 +@@ -3905,9 +3905,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 151 31 73 211 0 62 215 9 83 +-215 7 81 215 7 81 215 7 81 215 7 81 216 11 85 210 1 58 +-155 33 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 149 32 74 211 0 62 215 9 83 ++215 7 81 215 7 81 215 7 81 215 7 81 216 11 85 209 0 59 ++149 32 74 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3915,13 +3915,13 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 110 23 54 216 8 81 +-211 0 68 212 1 64 210 0 70 0 0 0 0 0 0 26 9 15 +-129 26 63 191 22 83 216 12 84 215 9 82 214 0 75 214 0 72 ++0 0 0 0 0 0 0 0 0 0 0 0 110 22 53 216 8 81 ++211 0 68 212 0 64 206 0 73 0 0 0 0 0 0 25 7 13 ++132 20 59 190 21 82 216 12 84 215 9 82 214 1 75 214 0 72 + 214 0 75 214 0 75 215 3 79 213 0 74 215 8 82 215 3 79 + 215 5 79 215 8 82 215 3 79 215 0 76 215 0 76 214 0 75 +-213 0 73 214 0 75 215 7 82 215 6 80 201 23 85 129 26 63 +-26 9 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++213 0 73 214 0 75 215 7 82 215 6 80 196 24 85 129 30 65 ++22 10 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3936,8 +3936,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 83 26 46 212 0 65 215 5 79 +-215 8 82 215 7 81 215 7 81 215 7 81 215 10 84 214 0 74 +-209 0 60 13 6 8 0 0 0 0 0 0 0 0 0 0 0 0 ++215 8 82 215 7 81 215 7 81 215 7 81 215 10 84 213 0 74 ++210 0 60 14 6 9 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3945,12 +3945,12 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 3 5 +-142 22 65 217 16 87 211 0 60 215 1 77 87 25 46 0 0 0 +-0 0 0 0 0 0 9 3 5 43 2 17 96 29 53 143 30 71 +-154 21 68 191 22 83 217 16 87 217 21 91 215 5 79 216 12 84 +-216 12 84 215 2 77 216 12 84 217 21 91 204 18 83 167 25 75 +-154 21 68 110 23 54 57 3 22 15 6 9 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 3 4 ++137 22 63 217 16 87 211 0 60 215 1 77 86 25 47 0 0 0 ++0 0 0 0 0 0 10 3 6 44 14 25 96 28 53 144 32 72 ++158 22 70 190 21 82 217 16 87 217 21 91 214 4 79 216 12 84 ++216 12 84 215 2 77 216 12 84 217 21 91 201 22 84 179 21 77 ++154 23 69 110 22 53 50 16 28 14 6 9 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3965,9 +3965,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 13 6 8 214 5 77 213 0 72 ++0 0 0 0 0 0 0 0 0 13 5 7 213 4 77 213 0 72 + 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 216 11 85 +-210 1 58 173 32 82 0 0 0 0 0 0 0 0 0 0 0 0 ++207 3 57 181 30 84 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3976,10 +3976,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 7 2 4 138 29 68 215 0 74 210 1 58 217 21 91 +-35 9 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 3 0 1 9 3 5 7 2 4 9 3 5 +-11 4 6 7 2 4 9 3 5 7 2 4 0 0 0 0 0 0 ++0 0 0 7 2 4 142 26 67 215 0 74 209 0 59 217 21 91 ++31 7 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 2 0 1 10 3 6 7 2 4 10 3 6 ++10 3 6 7 2 4 8 3 4 7 2 4 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -3995,9 +3995,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 194 27 87 210 0 64 ++0 0 0 0 0 0 0 0 0 0 0 0 193 26 85 210 0 63 + 216 9 83 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-216 10 84 210 1 58 142 22 65 11 4 6 14 1 6 0 0 0 ++216 10 84 211 0 58 142 26 67 10 3 6 13 5 7 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4006,8 +4006,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 122 32 64 215 8 81 +-213 0 69 219 31 98 113 34 62 43 2 17 3 0 1 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 129 30 65 215 8 81 ++213 0 69 219 31 98 113 34 62 36 6 17 2 0 1 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4025,9 +4025,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 119 35 66 210 1 58 ++0 0 0 0 0 0 0 0 0 0 0 0 118 42 70 209 0 59 + 215 7 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 8 81 215 5 81 212 0 69 215 2 77 217 16 87 172 8 66 ++215 8 81 215 5 81 211 0 69 215 2 77 217 16 87 165 7 62 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4037,9 +4037,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 158 23 71 214 3 78 216 12 84 216 4 80 194 27 87 +-142 22 65 132 19 59 73 20 39 43 2 17 47 14 26 42 19 27 +-14 1 6 29 1 11 43 2 17 57 3 22 43 2 17 3 1 2 ++58 17 31 158 22 70 214 3 78 216 12 84 216 4 80 196 24 85 ++142 26 67 132 20 59 74 19 38 54 1 15 47 15 26 41 17 25 ++21 6 11 31 0 6 36 6 17 54 1 15 44 14 25 4 1 2 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4055,9 +4055,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 8 3 5 213 0 67 ++0 0 0 0 0 0 0 0 0 0 0 0 8 3 4 212 0 67 + 213 0 74 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 10 82 215 7 81 215 2 77 213 0 71 211 0 61 ++215 7 81 215 10 82 215 7 81 215 2 77 213 0 71 210 1 61 + 217 16 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4067,9 +4067,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 24 8 13 96 29 53 180 25 80 +-214 8 82 217 16 87 217 16 87 216 8 81 214 5 77 215 6 80 +-216 12 84 217 21 91 198 18 82 145 33 73 54 21 33 0 0 0 ++0 0 0 0 0 0 0 0 0 25 7 13 96 28 53 179 21 77 ++214 8 82 217 16 87 217 16 87 216 8 81 214 6 77 215 6 80 ++216 12 84 217 21 91 197 20 84 144 32 72 55 20 32 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4085,10 +4085,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 194 27 87 +-210 0 64 216 10 83 215 7 81 215 7 81 215 7 81 215 7 81 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 193 26 85 ++210 0 63 216 10 83 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 8 81 216 11 85 216 8 83 +-210 1 58 162 40 83 0 0 0 0 0 0 0 0 0 0 0 0 ++207 3 57 160 37 81 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4098,8 +4098,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 4 1 2 24 8 13 14 1 6 29 1 11 +-28 12 17 3 1 2 3 0 1 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 4 1 2 25 7 13 21 6 11 31 0 6 ++28 11 17 4 1 2 2 0 1 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4115,10 +4115,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 81 25 45 +-210 1 58 216 9 84 215 7 81 215 7 81 215 7 81 215 7 81 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 77 26 44 ++211 0 58 216 9 84 215 7 81 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 +-215 1 79 209 0 60 30 13 19 0 0 0 0 0 0 0 0 0 ++215 1 79 209 0 59 30 14 19 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4145,10 +4145,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 1 2 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 2 3 + 214 0 75 213 0 71 215 10 84 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 +-215 7 81 210 1 58 180 25 80 0 0 0 0 0 0 0 0 0 ++215 7 81 209 0 59 179 21 77 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4176,9 +4176,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-134 33 69 211 0 60 216 9 84 215 7 81 215 7 81 215 7 81 ++134 32 68 211 0 60 216 9 84 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 4 79 +-214 15 84 204 18 83 210 1 58 30 13 19 0 0 0 0 0 0 ++215 12 82 205 16 79 207 3 57 30 14 19 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4206,9 +4206,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-41 16 25 212 0 70 214 2 74 215 10 84 215 7 81 215 7 81 ++41 17 25 212 0 70 214 2 74 215 10 84 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 8 81 215 3 79 +-215 0 74 42 19 27 210 1 58 219 31 98 0 0 0 0 0 0 ++214 1 75 41 17 25 207 3 57 219 31 98 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4236,9 +4236,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 180 25 80 211 0 61 216 10 84 215 7 81 215 7 81 ++0 0 0 179 21 77 210 1 61 216 10 84 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 9 83 +-211 0 63 119 35 66 0 0 0 210 0 70 32 13 20 0 0 0 ++211 0 63 120 35 65 0 0 0 211 0 69 30 14 19 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4266,9 +4266,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 78 24 43 211 0 60 213 1 77 215 8 82 215 7 81 ++0 0 0 77 26 44 211 0 60 212 1 78 215 8 82 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 +-215 0 76 213 0 73 0 0 0 0 0 0 8 3 5 0 0 0 ++215 0 76 213 0 73 0 0 0 0 0 0 8 3 4 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4296,9 +4296,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 213 18 87 212 0 65 215 10 83 215 7 81 ++0 0 0 0 0 0 205 16 79 212 0 65 215 10 83 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 10 83 210 0 59 145 33 73 0 0 0 0 0 0 0 0 0 ++215 10 83 211 0 60 149 32 74 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4326,9 +4326,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 85 18 42 211 0 61 216 8 82 215 7 81 ++0 0 0 0 0 0 79 23 43 210 1 61 216 8 82 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 8 82 213 0 75 212 0 72 15 6 9 0 0 0 0 0 0 ++215 8 82 213 0 75 212 0 72 15 7 10 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4358,7 +4358,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 219 31 98 211 0 63 216 12 84 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 216 10 84 211 0 58 194 27 87 0 0 0 0 0 0 ++215 7 81 216 10 84 211 0 58 184 29 84 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4386,9 +4386,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 113 34 62 211 0 60 213 3 79 ++0 0 0 0 0 0 0 0 0 118 42 70 211 0 60 213 3 79 + 215 10 82 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 8 81 215 5 81 209 0 60 101 33 58 0 0 0 ++215 7 81 215 8 81 215 5 81 210 1 61 101 34 58 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4416,9 +4416,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 213 4 75 213 0 69 ++0 0 0 0 0 0 0 0 0 0 0 0 206 9 79 213 0 69 + 215 10 83 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 215 9 82 215 0 74 211 0 61 54 21 33 ++215 7 81 215 7 81 215 9 82 215 0 74 210 1 61 55 20 32 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4448,7 +4448,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 83 26 46 211 0 62 + 215 1 77 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 215 8 82 215 0 73 204 18 83 30 13 19 ++215 7 81 215 7 81 215 8 82 215 0 73 201 22 84 30 14 19 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4476,9 +4476,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 191 22 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 190 21 82 + 211 0 62 216 8 82 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 215 8 82 211 0 65 162 40 83 0 0 0 ++215 7 81 215 7 81 215 8 82 212 0 66 160 37 81 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4506,8 +4506,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 21 33 +-210 0 65 213 0 74 215 9 82 215 7 81 215 7 81 215 7 81 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 55 20 32 ++209 0 65 213 0 74 215 9 82 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 8 81 215 4 80 212 0 70 83 26 46 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4537,9 +4537,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-160 33 78 210 0 59 216 9 84 215 7 81 215 7 81 215 7 81 ++160 37 81 211 0 60 216 9 84 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 8 82 215 0 76 212 0 70 +-85 18 42 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++86 25 47 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4569,7 +4569,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 212 0 70 213 0 72 215 9 83 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 10 83 212 0 68 +-217 16 87 42 19 27 0 0 0 0 0 0 0 0 0 0 0 0 ++217 16 87 41 17 25 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4597,9 +4597,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 101 33 58 209 0 60 216 4 80 215 8 82 215 7 81 +-215 7 81 215 7 81 215 7 81 215 7 81 216 8 83 210 0 64 +-155 33 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 101 34 58 209 0 59 216 4 80 215 8 82 215 7 81 ++215 7 81 215 7 81 215 7 81 215 7 81 216 8 83 210 0 63 ++149 32 74 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4627,9 +4627,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 194 27 87 211 0 58 216 10 84 215 7 81 ++0 0 0 0 0 0 193 26 85 211 0 58 216 10 84 215 7 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 9 82 213 0 73 +-212 0 69 28 12 17 0 0 0 0 0 0 0 0 0 0 0 0 ++212 0 69 26 11 17 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4657,9 +4657,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 28 12 17 210 0 64 213 0 73 215 9 82 ++0 0 0 0 0 0 26 11 17 211 0 63 213 0 73 215 9 82 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 216 10 84 +-210 0 64 201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 ++210 0 63 196 8 75 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4687,9 +4687,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 119 35 66 210 1 58 216 8 81 ++0 0 0 0 0 0 0 0 0 118 42 70 211 0 58 216 8 81 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 8 81 +-215 7 82 210 1 58 113 34 62 0 0 0 0 0 0 0 0 0 ++215 7 82 209 0 59 118 42 70 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4717,9 +4717,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 202 23 85 210 0 64 ++0 0 0 0 0 0 0 0 0 0 0 0 201 22 84 211 0 63 + 216 10 84 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-215 9 82 213 0 73 212 0 66 26 9 15 0 0 0 0 0 0 ++215 9 82 213 0 73 212 0 66 22 10 14 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4749,7 +4749,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 212 0 65 + 212 0 70 216 9 83 215 7 81 215 7 81 215 7 81 215 7 81 +-215 7 81 216 10 84 210 1 58 204 18 83 0 0 0 0 0 0 ++215 7 81 216 10 84 209 0 59 205 16 79 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4778,8 +4778,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 83 26 46 +-210 1 58 215 4 80 215 8 82 215 7 81 215 7 81 215 7 81 +-215 7 81 215 8 82 215 3 79 209 0 60 141 35 72 0 0 0 ++211 0 58 214 4 79 215 8 82 215 7 81 215 7 81 215 7 81 ++215 7 81 215 8 82 215 3 79 210 0 60 139 34 71 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4808,8 +4808,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-162 40 83 210 1 58 216 11 85 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 215 10 83 214 0 75 210 1 58 64 24 39 ++160 37 81 207 3 57 216 11 85 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 215 10 83 214 1 75 207 3 57 67 23 39 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4838,9 +4838,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 216 8 83 210 1 58 216 11 85 215 7 81 215 7 81 ++0 0 0 216 8 83 209 0 59 216 11 85 215 7 81 215 7 81 + 215 7 81 215 7 81 215 7 81 216 11 85 212 0 70 214 0 71 +-0 0 0 0 0 0 0 0 0 3 1 2 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 2 0 1 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4869,8 +4869,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 213 0 72 213 0 70 216 11 85 215 7 81 +-215 7 81 215 7 81 215 7 81 215 9 82 216 11 85 210 0 59 +-177 29 82 15 6 9 41 16 25 0 0 0 0 0 0 0 0 0 ++215 7 81 215 7 81 215 7 81 215 9 82 216 11 85 211 0 60 ++181 30 84 15 7 10 40 16 25 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4898,9 +4898,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 42 19 27 211 0 60 213 0 76 215 8 82 ++0 0 0 0 0 0 53 19 31 211 0 60 213 0 76 215 8 82 + 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 215 7 81 +-213 0 70 212 0 72 101 33 58 0 0 0 0 0 0 0 0 0 ++213 0 70 212 0 72 101 34 58 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4928,9 +4928,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 87 25 46 211 0 61 216 4 80 ++0 0 0 0 0 0 0 0 0 86 25 47 211 0 60 216 4 80 + 215 8 82 215 7 81 215 7 81 215 7 81 215 7 81 215 8 82 +-215 7 82 210 1 58 177 29 82 0 0 0 0 0 0 0 0 0 ++215 7 82 211 0 58 181 30 84 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4958,9 +4958,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 122 32 64 210 1 58 ++0 0 0 0 0 0 0 0 0 0 0 0 129 30 65 207 3 57 + 216 8 82 215 10 82 215 7 81 215 7 81 215 7 81 215 7 81 +-215 10 84 215 5 80 210 1 58 54 21 33 0 0 0 0 0 0 ++215 10 84 215 6 80 209 0 59 53 19 31 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -4988,9 +4988,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 162 40 83 +-209 0 60 216 8 81 215 9 82 215 7 81 215 7 81 215 7 81 +-215 7 81 216 9 84 211 0 62 204 18 83 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 160 37 81 ++210 0 60 216 8 81 215 9 82 215 7 81 215 7 81 215 7 81 ++215 7 81 216 9 84 211 0 62 201 22 84 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5019,8 +5019,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-158 7 61 210 1 58 216 10 83 215 7 81 215 7 81 215 7 81 +-215 7 81 215 7 81 216 9 83 210 1 58 119 35 66 0 0 0 ++165 7 62 207 3 57 216 10 83 215 7 81 215 7 81 215 7 81 ++215 7 81 215 7 81 216 9 83 211 0 58 120 35 65 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5049,8 +5049,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 219 31 98 210 1 58 216 9 84 215 9 82 215 7 81 +-215 7 81 215 7 81 215 8 82 213 2 78 210 1 58 54 21 33 ++0 0 0 219 31 98 207 3 57 216 9 84 215 9 82 215 7 81 ++215 7 81 215 7 81 215 8 82 214 3 78 211 0 58 62 23 37 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5079,8 +5079,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 201 23 85 210 1 58 216 10 84 215 10 84 +-215 7 81 215 7 81 215 7 81 216 10 84 210 0 64 219 31 98 ++0 0 0 0 0 0 201 22 84 207 3 57 216 10 84 215 10 84 ++215 7 81 215 7 81 215 7 81 216 10 84 210 0 63 219 31 98 + 4 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5109,9 +5109,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 194 27 87 211 0 61 215 6 80 +-215 8 82 215 7 81 215 7 81 215 7 81 216 9 84 213 0 70 +-215 1 77 210 0 70 214 0 72 32 13 20 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 184 29 84 210 1 61 215 6 80 ++215 8 82 215 7 81 215 7 81 215 7 81 216 9 84 214 0 70 ++215 1 77 206 0 73 214 0 72 30 14 19 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5139,9 +5139,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 167 25 75 211 0 58 ++0 0 0 0 0 0 0 0 0 0 0 0 166 29 77 211 0 58 + 215 3 79 215 9 82 215 7 81 215 7 81 215 7 81 215 8 82 +-215 5 79 216 10 84 211 0 61 215 6 80 0 0 0 0 0 0 ++215 5 79 216 10 84 211 0 60 215 6 80 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5169,7 +5169,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 160 33 78 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 160 37 81 + 212 0 67 215 2 77 215 9 82 215 7 81 215 7 81 215 7 81 + 215 7 81 215 7 81 216 10 84 211 0 58 219 31 98 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5200,8 +5200,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-134 33 69 210 0 65 213 0 75 216 9 83 215 8 81 215 7 81 +-215 7 81 215 7 81 215 7 81 216 8 83 210 0 65 202 23 85 ++134 32 68 209 0 65 213 0 75 216 9 83 215 8 81 215 7 81 ++215 7 81 215 7 81 215 7 81 216 8 83 209 0 65 201 22 84 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5230,9 +5230,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 85 18 42 213 0 75 213 0 70 215 7 82 215 8 81 ++0 0 0 79 23 43 213 0 75 213 0 70 215 7 82 215 8 81 + 215 7 81 215 7 81 215 7 81 215 8 81 215 7 81 212 0 65 +-217 16 87 35 9 18 0 0 0 0 0 0 0 0 0 0 0 0 ++217 16 87 38 14 23 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5260,9 +5260,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 40 16 25 217 16 87 212 0 69 215 8 81 ++0 0 0 0 0 0 38 14 23 217 16 87 212 0 69 215 8 81 + 215 8 82 215 7 81 215 7 81 215 7 81 215 8 81 215 10 83 +-213 0 73 213 0 75 186 9 72 54 21 33 0 0 0 0 0 0 ++213 0 73 213 0 75 186 7 71 55 20 32 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5290,9 +5290,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 4 1 2 202 23 85 212 0 66 ++0 0 0 0 0 0 0 0 0 4 1 2 201 22 84 212 0 66 + 215 3 79 215 9 82 215 7 81 215 7 81 215 7 81 215 7 81 +-216 10 83 212 0 67 219 31 98 21 8 12 0 0 0 0 0 0 ++216 10 83 212 0 67 219 31 98 22 10 14 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5320,9 +5320,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 142 22 65 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 137 22 63 + 213 0 72 213 0 71 216 8 81 215 8 82 215 7 81 215 7 81 +-215 7 81 213 0 73 119 35 66 0 0 0 0 0 0 0 0 0 ++215 7 81 213 0 73 120 35 65 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5351,8 +5351,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-78 24 43 215 7 82 211 0 65 215 5 81 215 10 82 215 7 81 +-215 7 81 215 8 82 212 0 71 215 5 80 147 30 72 13 6 8 ++77 26 44 215 7 82 212 0 66 215 5 81 215 10 82 215 7 81 ++215 7 81 215 8 82 212 0 71 215 6 80 146 27 70 13 5 7 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5381,9 +5381,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 8 3 5 183 28 83 211 0 65 213 0 72 216 10 83 +-215 8 81 215 7 81 215 6 80 213 0 75 213 0 67 217 16 87 +-73 20 39 0 0 0 0 0 0 8 3 5 18 7 11 0 0 0 ++0 0 0 8 3 4 181 30 84 212 0 66 213 0 72 216 10 83 ++215 8 81 215 7 81 215 6 80 213 0 75 212 0 67 217 16 87 ++74 19 38 0 0 0 0 0 0 11 5 7 18 7 11 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5411,9 +5411,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 85 18 42 216 9 82 212 0 68 ++0 0 0 0 0 0 0 0 0 86 25 47 216 9 82 212 0 68 + 215 5 81 215 9 82 215 8 82 215 10 82 215 8 81 213 0 71 +-214 0 74 154 21 68 15 6 9 0 0 0 90 31 52 57 3 22 ++213 0 74 154 23 69 14 6 9 0 0 0 91 31 52 54 1 15 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5441,10 +5441,10 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 18 7 11 186 26 82 ++0 0 0 0 0 0 0 0 0 0 0 0 18 7 11 184 29 84 + 213 0 69 214 0 72 215 5 81 215 9 82 215 7 81 215 9 83 +-215 4 78 212 0 71 214 3 78 125 28 63 42 19 27 204 18 83 +-21 8 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 4 78 212 0 71 214 3 78 129 30 65 50 16 28 201 22 84 ++22 10 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5472,8 +5472,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-73 20 39 217 16 87 214 0 71 213 0 72 216 10 83 215 10 82 +-215 7 82 215 9 82 215 1 77 212 0 68 213 2 78 213 0 69 ++74 19 38 217 16 87 214 0 71 213 0 72 216 10 83 215 10 82 ++215 7 82 215 9 82 215 1 77 212 0 68 212 1 78 213 0 69 + 219 31 98 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5502,9 +5502,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 110 23 54 217 16 87 212 0 67 213 0 72 +-216 9 83 215 8 82 215 8 82 215 7 82 213 1 77 214 4 79 +-211 0 62 204 18 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 110 22 53 217 16 87 212 0 67 213 0 72 ++216 9 83 215 8 82 215 8 82 215 7 82 213 0 76 214 4 79 ++211 0 62 205 16 79 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5532,9 +5532,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 3 1 2 132 19 59 217 16 87 ++0 0 0 0 0 0 0 0 0 3 1 1 132 20 59 217 16 87 + 212 0 69 215 1 77 215 7 81 215 9 83 215 8 82 215 8 82 +-215 7 81 214 0 68 201 9 77 0 0 0 0 0 0 0 0 0 ++215 7 81 213 0 69 196 8 75 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5563,8 +5563,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-132 19 59 214 7 81 213 0 69 212 0 68 215 5 81 215 10 82 +-215 10 82 215 9 83 214 0 71 216 12 84 21 8 12 0 0 0 ++132 20 59 215 7 81 214 0 70 212 0 68 215 5 81 215 10 82 ++215 10 82 215 9 83 214 0 71 216 12 84 20 7 12 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5593,8 +5593,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 107 28 56 191 22 83 214 0 71 212 0 69 +-215 1 77 215 9 82 215 10 83 212 0 69 215 6 80 96 29 53 ++0 0 0 0 0 0 106 29 55 193 26 85 214 0 70 212 0 69 ++215 1 77 215 9 82 215 10 83 212 0 69 215 6 80 96 28 53 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5623,9 +5623,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 47 14 26 143 30 71 +-215 0 76 210 0 65 215 0 74 215 4 78 213 0 75 213 0 67 +-213 18 87 96 29 53 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 47 15 26 144 32 72 ++215 0 76 209 0 65 215 0 74 215 4 78 213 0 75 212 0 67 ++217 16 87 96 28 53 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5654,8 +5654,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 81 25 45 158 23 71 215 7 81 215 4 78 213 0 73 +-211 0 62 212 0 72 215 2 77 167 25 75 87 25 46 11 4 6 ++0 0 0 77 26 44 158 22 70 215 7 81 214 4 78 213 0 73 ++211 0 62 212 0 72 215 2 77 179 21 77 86 25 47 13 5 7 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5684,9 +5684,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 58 17 31 138 29 68 +-194 27 87 215 5 79 214 0 71 212 0 67 209 0 60 210 0 65 +-214 7 81 180 25 80 136 20 62 96 29 53 73 20 39 29 1 11 ++0 0 0 0 0 0 0 0 0 0 0 0 58 17 31 137 22 63 ++193 26 85 215 5 79 214 0 71 212 0 67 209 0 59 209 0 65 ++215 7 81 179 21 77 137 22 63 96 28 53 74 19 38 25 7 13 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -5715,9 +5715,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 24 8 13 47 14 26 87 25 46 138 29 68 154 21 68 +-183 28 83 210 0 70 219 31 98 215 3 79 212 0 67 219 31 98 +-219 31 98 219 31 98 132 19 59 50 16 28 0 0 0 0 0 0 ++0 0 0 25 7 13 47 15 26 96 28 53 134 32 68 146 27 70 ++184 29 84 206 0 73 219 31 98 215 3 79 212 0 67 219 31 98 ++219 31 98 219 31 98 132 20 59 53 19 31 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6468,7 +6468,6 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-29 1 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6492,13 +6491,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 86 4 33 +-72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 29 1 11 +-158 7 61 37 7 18 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6522,13 +6517,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 43 2 17 115 5 44 186 9 72 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 3 0 1 129 6 50 +-213 10 82 201 9 77 37 7 18 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6537,6 +6528,7 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6551,14 +6543,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 43 2 17 57 3 22 100 5 39 +-143 7 55 201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 43 2 17 158 7 61 215 10 83 +-215 10 83 215 10 83 201 9 77 37 7 18 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6571,6 +6558,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 36 6 17 154 5 57 ++36 6 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6581,14 +6570,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 4 1 2 143 7 55 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 201 9 77 37 7 18 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6599,10 +6583,13 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 73 1 23 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 2 0 1 130 4 47 213 10 82 ++196 8 75 36 6 17 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6611,14 +6598,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 129 6 50 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 37 7 18 129 6 50 201 9 77 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 37 7 18 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6631,39 +6613,44 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 54 1 15 130 4 47 186 7 71 215 10 83 176 6 66 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 36 6 17 154 5 57 215 10 83 215 10 83 ++215 10 83 196 8 75 36 6 17 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 43 2 17 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-43 2 17 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 +-29 1 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++73 1 23 118 3 42 130 4 47 154 5 57 176 6 66 176 6 66 ++176 6 66 176 6 66 176 6 66 176 6 66 130 4 47 130 4 47 ++89 2 30 31 0 6 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 31 0 6 89 2 30 104 3 36 130 4 47 165 7 62 ++196 8 75 215 10 83 215 10 83 215 10 83 215 10 83 176 6 66 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 4 1 2 143 4 52 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 196 8 75 36 6 17 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6671,24 +6658,28 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-43 2 17 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 104 3 36 154 5 57 206 9 79 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 215 10 83 186 7 71 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 104 3 36 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 176 6 66 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++36 6 17 130 4 47 206 9 79 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 196 8 75 36 6 17 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6701,20 +6692,24 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 118 3 42 196 8 75 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 143 7 55 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 213 10 82 158 7 61 +-72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 154 5 57 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 143 4 52 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 1 15 ++154 5 57 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 196 8 75 31 0 6 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6727,18 +6722,27 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 2 30 ++196 8 75 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 54 1 15 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 104 3 36 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 143 7 55 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 1 15 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 154 5 57 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 129 6 50 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 158 7 61 14 1 6 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6748,40 +6752,54 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 186 7 71 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 31 0 6 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++143 4 52 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 213 10 82 165 7 62 73 1 23 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 129 6 50 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 186 9 72 57 3 22 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 154 5 57 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 176 6 66 ++176 6 66 176 6 66 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 143 4 52 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 206 9 79 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 143 4 52 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 154 5 57 21 6 11 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6791,22 +6809,27 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 154 5 57 104 3 36 31 0 6 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 31 0 6 118 3 42 196 8 75 ++215 10 83 130 4 47 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 129 6 50 215 10 83 +-215 10 83 213 10 82 143 7 55 29 1 11 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 176 6 66 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 143 4 52 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 186 7 71 54 1 15 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6819,19 +6842,24 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 165 7 62 ++54 1 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 ++154 5 57 89 2 30 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 176 6 66 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 129 6 50 +-215 10 83 186 9 72 43 2 17 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 143 4 52 215 10 83 215 10 83 ++213 10 82 143 4 52 31 0 6 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6844,21 +6872,25 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++31 0 6 196 8 75 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 118 3 42 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 54 1 15 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 176 6 66 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 143 4 52 215 10 83 ++186 7 71 54 1 15 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-129 6 50 57 3 22 3 0 1 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6870,6 +6902,8 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 118 3 42 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6878,12 +6912,14 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 72 3 28 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 143 4 52 ++54 1 15 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6895,6 +6931,9 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 ++206 9 79 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +@@ -6903,1234 +6942,1195 @@ P3 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-14 1 6 57 3 22 72 3 28 100 5 39 100 5 39 100 5 39 +-100 5 39 72 3 28 43 2 17 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-14 1 6 72 3 28 100 5 39 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 72 3 28 129 6 50 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 57 3 22 86 4 33 100 5 39 100 5 39 72 3 28 +-29 1 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 14 1 6 86 4 33 86 4 33 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 14 1 6 57 3 22 57 3 22 100 5 39 +-100 5 39 100 5 39 100 5 39 100 5 39 57 3 22 57 3 22 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 29 1 11 100 5 39 43 2 17 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 100 5 39 100 5 39 100 5 39 100 5 39 86 4 33 +-43 2 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 72 3 28 129 6 50 186 9 72 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 115 5 44 57 3 22 +-57 3 22 57 3 22 86 4 33 100 5 39 129 6 50 172 8 66 +-215 10 83 215 10 83 129 6 50 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 57 3 22 57 3 22 86 4 33 100 5 39 115 5 44 +-158 7 61 215 10 83 215 10 83 172 8 66 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 100 5 39 +-201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 172 8 66 72 3 28 0 0 0 0 0 0 0 0 0 ++215 10 83 196 8 75 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 +-57 3 22 100 5 39 143 7 55 201 9 77 215 10 83 86 4 33 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 86 4 33 +-143 7 55 201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 172 8 66 86 4 33 14 1 6 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 29 1 11 +-57 3 22 100 5 39 172 8 66 215 10 83 215 10 83 57 3 22 +-0 0 0 0 0 0 0 0 0 29 1 11 129 6 50 201 9 77 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 186 9 72 86 4 33 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 31 0 6 118 3 42 31 0 6 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-14 1 6 100 5 39 201 9 77 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 86 4 33 129 6 50 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 ++0 0 0 31 0 6 118 3 42 54 1 15 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 104 3 36 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-43 2 17 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 158 7 61 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-0 0 0 0 0 0 0 0 0 43 2 17 172 8 66 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 158 7 61 14 1 6 0 0 0 ++0 0 0 89 2 30 89 2 30 89 2 30 54 1 15 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 29 1 11 158 7 61 158 7 61 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 57 3 22 129 6 50 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 201 9 77 72 3 28 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 115 5 44 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 +-0 0 0 0 0 0 86 4 33 201 9 77 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 158 7 61 14 1 6 0 0 0 ++0 0 0 0 0 0 31 0 6 118 3 42 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 72 3 28 +-201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 14 1 6 0 0 0 +-186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 86 4 33 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 54 1 15 89 2 30 89 2 30 89 2 30 ++89 2 30 89 2 30 54 1 15 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 129 6 50 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 129 6 50 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-0 0 0 0 0 0 29 1 11 201 9 77 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 172 8 66 14 1 6 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 14 1 6 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-72 3 28 172 8 66 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 115 5 44 ++54 1 15 130 4 47 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 31 0 6 89 2 30 89 2 30 89 2 30 ++89 2 30 54 1 15 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 14 1 6 201 9 77 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 +-0 0 0 86 4 33 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 196 8 75 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 143 7 55 0 0 0 ++215 10 83 118 3 42 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 115 5 44 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 158 7 61 0 0 0 0 0 0 +-115 5 44 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++31 0 6 89 2 30 89 2 30 89 2 30 118 3 42 130 4 47 ++176 6 66 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++54 1 15 89 2 30 89 2 30 89 2 30 118 3 42 130 4 47 ++176 6 66 215 10 83 215 10 83 54 1 15 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 ++0 0 0 0 0 0 0 0 0 0 0 0 89 2 30 176 6 66 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 196 8 75 ++130 4 47 31 0 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 73 1 23 ++118 3 42 165 7 62 215 10 83 176 6 66 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 31 0 6 118 3 42 154 5 57 ++196 8 75 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 186 7 71 143 4 52 ++54 1 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 89 2 30 130 4 47 186 7 71 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++118 3 42 186 7 71 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 206 9 79 130 4 47 31 0 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 73 1 23 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-0 0 0 0 0 0 172 8 66 215 10 83 215 10 83 215 10 83 ++196 8 75 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 ++186 7 71 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 186 7 71 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++154 5 57 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 ++0 0 0 0 0 0 31 0 6 165 7 62 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 172 8 66 ++215 10 83 206 9 79 104 3 36 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 14 1 6 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++73 1 23 154 5 57 176 6 66 196 8 75 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-86 4 33 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 104 3 36 165 7 62 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 154 5 57 31 0 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 165 7 62 ++176 6 66 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 73 1 23 186 7 71 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 129 6 50 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 +-29 1 11 201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 206 9 79 73 1 23 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 ++143 4 52 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 129 6 50 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 115 5 44 0 0 0 0 0 0 +-100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 29 1 11 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-0 0 0 100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++31 0 6 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 196 8 75 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 ++0 0 0 0 0 0 186 7 71 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++215 10 83 215 10 83 215 10 83 118 3 42 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 165 7 62 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 104 3 36 ++196 8 75 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 196 8 75 54 1 15 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 2 30 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-186 9 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 86 4 33 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 +-129 6 50 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 54 1 15 206 9 79 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 143 7 55 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 206 9 79 ++54 1 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 176 6 66 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++73 1 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 176 6 66 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 215 10 83 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 196 8 75 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 ++0 0 0 143 4 52 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-158 7 61 100 5 39 57 3 22 57 3 22 57 3 22 57 3 22 +-86 4 33 158 7 61 215 10 83 86 4 33 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 118 3 42 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-14 1 6 201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-201 9 77 14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 143 7 55 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++215 10 83 215 10 83 215 10 83 186 7 71 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 86 4 33 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 201 9 77 143 7 55 100 5 39 57 3 22 43 2 17 +-0 0 0 14 1 6 57 3 22 100 5 39 201 9 77 215 10 83 ++186 7 71 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 186 7 71 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 86 4 33 +-215 10 83 215 10 83 215 10 83 129 6 50 72 3 28 57 3 22 +-57 3 22 72 3 28 158 7 61 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++154 5 57 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 206 9 79 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 206 9 79 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 172 8 66 57 3 22 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 57 3 22 43 2 17 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 143 4 52 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 118 3 42 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 196 8 75 31 0 6 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 186 9 72 +-100 5 39 215 10 83 215 10 83 215 10 83 143 7 55 57 3 22 +-14 1 6 43 2 17 86 4 33 186 9 72 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 ++206 9 79 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 118 3 42 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 14 1 6 215 10 83 215 10 83 215 10 83 186 9 72 +-86 4 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 172 8 66 ++143 4 52 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 118 3 42 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 115 5 44 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 29 1 11 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 172 8 66 +-215 10 83 201 9 77 43 2 17 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-43 2 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 31 0 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 54 1 15 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 176 6 66 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 129 6 50 14 1 6 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 158 7 61 +-186 9 72 215 10 83 215 10 83 86 4 33 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 14 1 6 172 8 66 215 10 83 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 ++176 6 66 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 172 8 66 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 158 7 61 201 9 77 100 5 39 0 0 0 ++0 0 0 0 0 0 196 8 75 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 29 1 11 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 186 9 72 215 10 83 ++154 5 57 215 10 83 215 10 83 215 10 83 215 10 83 206 9 79 ++154 5 57 118 3 42 73 1 23 0 0 0 0 0 0 0 0 0 ++31 0 6 118 3 42 186 7 71 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 186 7 71 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 196 8 75 215 10 83 206 9 79 130 4 47 ++73 1 23 0 0 0 0 0 0 89 2 30 154 5 57 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 104 3 36 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 89 2 30 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-86 4 33 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 172 8 66 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 +-215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 186 9 72 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 29 1 11 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 72 3 28 29 1 11 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 118 3 42 ++215 10 83 215 10 83 215 10 83 130 4 47 54 1 15 0 0 0 ++0 0 0 73 1 23 176 6 66 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 196 8 75 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 176 6 66 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-143 7 55 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 186 9 72 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++104 3 36 215 10 83 215 10 83 196 8 75 118 3 42 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 31 0 6 176 6 66 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 206 9 79 215 10 83 206 9 79 73 1 23 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 130 4 47 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 118 3 42 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 43 2 17 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 186 9 72 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 86 4 33 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 186 7 71 ++215 10 83 215 10 83 118 3 42 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 165 7 62 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 72 3 28 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++73 1 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 176 6 66 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 215 10 83 130 4 47 31 0 6 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 54 1 15 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 ++206 9 79 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 143 4 52 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-86 4 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 72 3 28 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-86 4 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 ++215 10 83 130 4 47 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 31 0 6 206 9 79 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 129 6 50 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 176 6 66 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 73 1 23 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 186 7 71 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 196 8 75 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++176 6 66 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-72 3 28 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 115 5 44 ++206 9 79 31 0 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 ++165 7 62 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 176 6 66 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 43 2 17 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 154 5 57 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-129 6 50 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 129 6 50 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 72 3 28 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 143 4 52 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 186 9 72 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 186 9 72 ++154 5 57 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 176 6 66 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-14 1 6 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-72 3 28 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 158 7 61 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 201 9 77 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 158 7 61 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 215 10 83 ++118 3 42 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 176 6 66 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-143 7 55 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-29 1 11 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 158 7 61 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++31 0 6 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 54 1 15 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 143 7 55 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++54 1 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 29 1 11 57 3 22 100 5 39 +-100 5 39 100 5 39 100 5 39 100 5 39 100 5 39 100 5 39 +-100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 43 2 17 215 10 83 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 104 3 36 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 31 0 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 54 1 15 89 2 30 ++89 2 30 89 2 30 31 0 6 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 172 8 66 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-86 4 33 143 7 55 201 9 77 215 10 83 215 10 83 215 10 83 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 176 6 66 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 2 30 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 89 2 30 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 73 1 23 ++130 4 47 176 6 66 206 9 79 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 118 3 42 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 86 4 33 186 9 72 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 176 6 66 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 1 15 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++215 10 83 89 2 30 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++0 0 0 0 0 0 0 0 0 118 3 42 196 8 75 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 14 1 6 158 7 61 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 154 5 57 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++215 10 83 89 2 30 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++0 0 0 54 1 15 186 7 71 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 118 3 42 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 143 4 52 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 14 1 6 172 8 66 215 10 83 215 10 83 215 10 83 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 143 4 52 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 172 8 66 158 7 61 158 7 61 158 7 61 158 7 61 +-158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++215 10 83 89 2 30 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 ++73 1 23 206 9 79 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 89 2 30 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 176 6 66 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-43 2 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 172 8 66 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 186 9 72 100 5 39 29 1 11 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-43 2 17 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 ++196 8 75 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 154 5 57 104 3 36 31 0 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 89 2 30 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 54 1 15 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 158 7 61 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-86 4 33 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 129 6 50 14 1 6 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 143 4 52 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++186 7 71 73 1 23 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 206 9 79 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++73 1 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 143 7 55 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 129 6 50 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++206 9 79 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 206 9 79 ++31 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 176 6 66 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-86 4 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++143 4 52 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 14 1 6 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43 2 17 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 1 15 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-201 9 77 14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 ++176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 118 3 42 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 118 3 42 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++196 8 75 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 72 3 28 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 89 2 30 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-129 6 50 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++143 4 52 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 165 7 62 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 31 0 6 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-72 3 28 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 73 1 23 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 89 2 30 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 104 3 36 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++118 3 42 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 186 7 71 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 186 7 71 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 165 7 62 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 43 2 17 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 143 7 55 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 196 8 75 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 172 8 66 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 172 8 66 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 29 1 11 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++0 0 0 143 4 52 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++73 1 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 176 6 66 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 176 6 66 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-29 1 11 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 ++31 0 6 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 143 4 52 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 176 6 66 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 165 7 62 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 196 8 75 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++215 10 83 215 10 83 215 10 83 215 10 83 176 6 66 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 201 9 77 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 1 15 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 215 10 83 186 7 71 31 0 6 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 143 4 52 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 196 8 75 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-72 3 28 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 143 7 55 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 201 9 77 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 206 9 79 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 143 4 52 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 176 6 66 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++215 10 83 215 10 83 215 10 83 215 10 83 196 8 75 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 143 7 55 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 129 6 50 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 104 3 36 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++154 5 57 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 154 5 57 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-115 5 44 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 86 4 33 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 72 3 28 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 201 9 77 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++31 0 6 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 104 3 36 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 73 1 23 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 176 6 66 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 31 0 6 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 86 4 33 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 29 1 11 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 154 5 57 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++54 1 15 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 154 5 57 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 86 4 33 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 +-201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 143 7 55 0 0 0 0 0 0 0 0 0 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 86 4 33 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 176 6 66 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 176 6 66 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-14 1 6 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 176 6 66 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 206 9 79 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 118 3 42 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-129 6 50 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 0 0 0 73 1 23 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-129 6 50 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 86 4 33 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 176 6 66 ++31 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-43 2 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 158 7 61 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 29 1 11 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++0 0 0 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 ++196 8 75 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 89 2 30 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 104 3 36 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-29 1 11 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 86 4 33 0 0 0 ++0 0 0 0 0 0 176 6 66 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 176 6 66 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 176 6 66 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 31 0 6 186 7 71 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-43 2 17 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 172 8 66 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 +-201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 72 3 28 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 86 4 33 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 158 7 61 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 186 7 71 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 143 7 55 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 86 4 33 215 10 83 215 10 83 +-186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++206 9 79 118 3 42 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 ++0 0 0 89 2 30 143 4 52 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 154 5 57 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 143 7 55 +-29 1 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 31 0 6 206 9 79 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 86 4 33 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 172 8 66 +-215 10 83 186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++0 0 0 0 0 0 176 6 66 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 130 4 47 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 43 2 17 201 9 77 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 29 1 11 ++154 5 57 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++89 2 30 186 7 71 215 10 83 215 10 83 154 5 57 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 89 2 30 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 143 7 55 29 1 11 0 0 0 0 0 0 +-0 0 0 43 2 17 129 6 50 215 10 83 215 10 83 215 10 83 +-86 4 33 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 206 9 79 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 14 1 6 172 8 66 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 129 6 50 86 4 33 57 3 22 0 0 0 0 0 0 +-0 0 0 43 2 17 86 4 33 115 5 44 0 0 0 0 0 0 +-0 0 0 201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 129 6 50 43 2 17 +-0 0 0 0 0 0 43 2 17 100 5 39 201 9 77 215 10 83 +-215 10 83 86 4 33 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 ++0 0 0 0 0 0 31 0 6 206 9 79 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 86 4 33 201 9 77 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 0 0 0 ++215 10 83 215 10 83 206 9 79 154 5 57 118 3 42 89 2 30 ++31 0 6 0 0 0 0 0 0 0 0 0 89 2 30 118 3 42 ++186 7 71 215 10 83 143 4 52 0 0 0 0 0 0 0 0 0 ++0 0 0 73 1 23 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 0 0 0 ++0 0 0 0 0 0 0 0 0 73 1 23 176 6 66 215 10 83 ++215 10 83 130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 154 5 57 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 0 0 0 ++0 0 0 73 1 23 186 7 71 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 206 9 79 73 1 23 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 158 7 61 +-201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 186 9 72 +-0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 176 6 66 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 73 1 23 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 196 8 75 154 5 57 130 4 47 143 4 52 186 7 71 ++215 10 83 215 10 83 215 10 83 196 8 75 89 2 30 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 104 3 36 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 43 2 17 201 9 77 215 10 83 215 10 83 ++0 0 0 0 0 0 0 0 0 73 1 23 196 8 75 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 115 5 44 0 0 0 0 0 0 +-0 0 0 143 7 55 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 118 3 42 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 206 9 79 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 206 9 79 ++176 6 66 176 6 66 196 8 75 215 10 83 215 10 83 215 10 83 ++176 6 66 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 196 8 75 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 176 6 66 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 154 5 57 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 54 1 15 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 118 3 42 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 196 8 75 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 196 8 75 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-158 7 61 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 129 6 50 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-115 5 44 57 3 22 14 1 6 0 0 0 0 0 0 43 2 17 +-86 4 33 158 7 61 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 129 6 50 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 43 2 17 ++215 10 83 215 10 83 215 10 83 118 3 42 89 2 30 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-100 5 39 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 86 4 33 +-0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 100 5 39 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 176 6 66 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 43 2 17 201 9 77 215 10 83 ++0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 186 7 71 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 +-0 0 0 57 3 22 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 +-29 1 11 0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 158 7 61 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 129 6 50 215 10 83 ++215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 154 5 57 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 206 9 79 ++54 1 15 89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 176 6 66 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 206 9 79 176 6 66 176 6 66 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 129 6 50 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 ++215 10 83 118 3 42 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-14 1 6 201 9 77 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 104 3 36 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 143 7 55 0 0 0 +-0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 29 1 11 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 43 2 17 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 115 5 44 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 72 3 28 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 215 10 83 176 6 66 0 0 0 89 2 30 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 130 4 47 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 158 7 61 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++89 2 30 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++143 4 52 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 186 7 71 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 129 6 50 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 201 9 77 43 2 17 +-0 0 0 0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 186 9 72 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 172 8 66 215 10 83 ++215 10 83 215 10 83 89 2 30 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 54 1 15 206 9 79 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 206 9 79 73 1 23 ++0 0 0 31 0 6 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 73 1 23 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 100 5 39 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 206 9 79 ++104 3 36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 186 9 72 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 86 4 33 ++0 0 0 31 0 6 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 165 7 62 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 72 3 28 215 10 83 215 10 83 215 10 83 215 10 83 ++154 5 57 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 172 8 66 14 1 6 0 0 0 +-0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 57 3 22 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 57 3 22 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 158 7 61 ++215 10 83 186 7 71 31 0 6 0 0 0 89 2 30 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 154 5 57 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-158 7 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++130 4 47 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++176 6 66 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-86 4 33 186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 ++0 0 0 54 1 15 154 5 57 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 186 9 72 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 129 6 50 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 186 9 72 43 2 17 0 0 0 +-0 0 0 0 0 0 158 7 61 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 57 3 22 0 0 0 +-0 0 0 0 0 0 0 0 0 14 1 6 215 10 83 215 10 83 ++215 10 83 215 10 83 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 73 1 23 206 9 79 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 206 9 79 73 1 23 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 73 1 23 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 158 7 61 +-43 2 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++215 10 83 215 10 83 215 10 83 215 10 83 154 5 57 54 1 15 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 29 1 11 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 129 6 50 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 86 4 33 201 9 77 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 143 7 55 14 1 6 0 0 0 0 0 0 +-0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 115 5 44 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 172 8 66 ++0 0 0 104 3 36 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 196 8 75 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 115 5 44 215 10 83 ++0 0 0 154 5 57 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-186 9 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++186 7 71 31 0 6 0 0 0 0 0 0 89 2 30 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 196 8 75 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++154 5 57 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 73 1 23 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 72 3 28 143 7 55 201 9 77 215 10 83 +-215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 158 7 61 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 57 3 22 158 7 61 ++186 7 71 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 215 10 83 73 1 23 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 31 0 6 118 3 42 165 7 62 ++206 9 79 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 201 9 77 100 5 39 14 1 6 0 0 0 0 0 0 +-0 0 0 0 0 0 158 7 61 215 10 83 186 9 72 158 7 61 +-158 7 61 158 7 61 158 7 61 186 9 72 172 8 66 14 1 6 +-0 0 0 0 0 0 0 0 0 0 0 0 14 1 6 86 4 33 +-129 6 50 186 9 72 215 10 83 215 10 83 215 10 83 215 10 83 ++206 9 79 165 7 62 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 130 4 47 ++206 9 79 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 ++215 10 83 206 9 79 143 4 52 31 0 6 0 0 0 0 0 0 ++0 0 0 0 0 0 215 10 83 215 10 83 186 7 71 176 6 66 ++176 6 66 176 6 66 186 7 71 206 9 79 54 1 15 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 54 1 15 130 4 47 ++176 6 66 206 9 79 215 10 83 215 10 83 215 10 83 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 186 9 72 115 5 44 43 2 17 0 0 0 ++215 10 83 196 8 75 143 4 52 54 1 15 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 154 5 57 215 10 83 206 9 79 176 6 66 176 6 66 ++176 6 66 176 6 66 186 7 71 215 10 83 89 2 30 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 100 5 39 215 10 83 215 10 83 158 7 61 +-158 7 61 158 7 61 158 7 61 158 7 61 186 9 72 201 9 77 +-14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 29 1 11 129 6 50 215 10 83 ++0 0 0 0 0 0 104 3 36 196 8 75 215 10 83 215 10 83 ++215 10 83 215 10 83 215 10 83 215 10 83 196 8 75 118 3 42 ++0 0 0 0 0 0 0 0 0 0 0 0 89 2 30 215 10 83 + 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-158 7 61 72 3 28 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 215 10 83 215 10 83 215 10 83 215 10 83 215 10 83 +-215 10 83 215 10 83 201 9 77 29 1 11 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 158 7 61 215 10 83 215 10 83 +-158 7 61 158 7 61 186 9 72 215 10 83 215 10 83 215 10 83 +-14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 186 9 72 201 9 77 +-158 7 61 158 7 61 158 7 61 158 7 61 172 8 66 215 10 83 +-215 10 83 43 2 17 0 0 0 0 0 0 0 0 0 0 0 0 ++118 3 42 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++196 8 75 215 10 83 215 10 83 176 6 66 176 6 66 215 10 83 ++215 10 83 215 10 83 118 3 42 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 ++215 10 83 196 8 75 176 6 66 176 6 66 176 6 66 176 6 66 ++215 10 83 215 10 83 130 4 47 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 54 1 15 89 2 30 130 4 47 130 4 47 130 4 47 ++130 4 47 130 4 47 130 4 47 130 4 47 89 2 30 31 0 6 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 43 2 17 +-72 3 28 100 5 39 100 5 39 129 6 50 158 7 61 158 7 61 +-100 5 39 100 5 39 57 3 22 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-29 1 11 72 3 28 100 5 39 100 5 39 100 5 39 100 5 39 +-57 3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 89 2 30 118 3 42 130 4 47 130 4 47 130 4 47 ++89 2 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 14 1 6 57 3 22 72 3 28 100 5 39 +-100 5 39 100 5 39 100 5 39 100 5 39 100 5 39 100 5 39 +-72 3 28 29 1 11 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 54 1 15 89 2 30 118 3 42 130 4 47 ++130 4 47 130 4 47 130 4 47 130 4 47 130 4 47 89 2 30 ++54 1 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 14 1 6 0 0 0 0 0 0 0 0 0 ++0 0 0 31 0 6 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 54 1 15 89 2 30 ++130 4 47 130 4 47 89 2 30 54 1 15 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-57 3 22 86 4 33 100 5 39 100 5 39 57 3 22 29 1 11 ++54 1 15 0 0 0 0 0 0 0 0 0 0 0 0 31 0 6 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 29 1 11 0 0 0 0 0 0 +-0 0 0 0 0 0 0 0 0 14 1 6 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-0 0 0 14 1 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 31 0 6 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +-- +1.9.1 + diff --git a/patch/kernel/neo-patch-3.14.35-36 b/patch/kernel/neo-patch-3.14.35-36 new file mode 100644 index 000000000..261ccc851 --- /dev/null +++ b/patch/kernel/neo-patch-3.14.35-36 @@ -0,0 +1,3448 @@ +diff --git a/Makefile b/Makefile +index 9720e863c06f..4e6537bd8aa0 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 35 ++SUBLEVEL = 36 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h +index 15334ab66b56..fb95aa807215 100644 +--- a/arch/arc/include/asm/processor.h ++++ b/arch/arc/include/asm/processor.h +@@ -69,18 +69,19 @@ unsigned long thread_saved_pc(struct task_struct *t); + #define release_segments(mm) do { } while (0) + + #define KSTK_EIP(tsk) (task_pt_regs(tsk)->ret) ++#define KSTK_ESP(tsk) (task_pt_regs(tsk)->sp) + + /* + * Where abouts of Task's sp, fp, blink when it was last seen in kernel mode. + * Look in process.c for details of kernel stack layout + */ +-#define KSTK_ESP(tsk) (tsk->thread.ksp) ++#define TSK_K_ESP(tsk) (tsk->thread.ksp) + +-#define KSTK_REG(tsk, off) (*((unsigned int *)(KSTK_ESP(tsk) + \ ++#define TSK_K_REG(tsk, off) (*((unsigned int *)(TSK_K_ESP(tsk) + \ + sizeof(struct callee_regs) + off))) + +-#define KSTK_BLINK(tsk) KSTK_REG(tsk, 4) +-#define KSTK_FP(tsk) KSTK_REG(tsk, 0) ++#define TSK_K_BLINK(tsk) TSK_K_REG(tsk, 4) ++#define TSK_K_FP(tsk) TSK_K_REG(tsk, 0) + + /* + * Do necessary setup to start up a newly executed thread. +diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c +index 9ce47cfe2303..fb98769b6a98 100644 +--- a/arch/arc/kernel/stacktrace.c ++++ b/arch/arc/kernel/stacktrace.c +@@ -64,9 +64,9 @@ static void seed_unwind_frame_info(struct task_struct *tsk, + + frame_info->task = tsk; + +- frame_info->regs.r27 = KSTK_FP(tsk); +- frame_info->regs.r28 = KSTK_ESP(tsk); +- frame_info->regs.r31 = KSTK_BLINK(tsk); ++ frame_info->regs.r27 = TSK_K_FP(tsk); ++ frame_info->regs.r28 = TSK_K_ESP(tsk); ++ frame_info->regs.r31 = TSK_K_BLINK(tsk); + frame_info->regs.r63 = (unsigned int)__switch_to; + + /* In the prologue of __switch_to, first FP is saved on stack +diff --git a/arch/mips/kvm/trace.h b/arch/mips/kvm/trace.h +index bc9e0f406c08..e51621e36152 100644 +--- a/arch/mips/kvm/trace.h ++++ b/arch/mips/kvm/trace.h +@@ -26,18 +26,18 @@ TRACE_EVENT(kvm_exit, + TP_PROTO(struct kvm_vcpu *vcpu, unsigned int reason), + TP_ARGS(vcpu, reason), + TP_STRUCT__entry( +- __field(struct kvm_vcpu *, vcpu) ++ __field(unsigned long, pc) + __field(unsigned int, reason) + ), + + TP_fast_assign( +- __entry->vcpu = vcpu; ++ __entry->pc = vcpu->arch.pc; + __entry->reason = reason; + ), + + TP_printk("[%s]PC: 0x%08lx", + kvm_mips_exit_types_str[__entry->reason], +- __entry->vcpu->arch.pc) ++ __entry->pc) + ); + + #endif /* _TRACE_KVM_H */ +diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S +index 02553d6d183d..06469ee0f26e 100644 +--- a/arch/x86/kernel/entry_64.S ++++ b/arch/x86/kernel/entry_64.S +@@ -542,11 +542,14 @@ ENTRY(ret_from_fork) + testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread? + jz 1f + +- testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET +- jnz int_ret_from_sys_call +- +- RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET +- jmp ret_from_sys_call # go to the SYSRET fastpath ++ /* ++ * By the time we get here, we have no idea whether our pt_regs, ++ * ti flags, and ti status came from the 64-bit SYSCALL fast path, ++ * the slow path, or one of the ia32entry paths. ++ * Use int_ret_from_sys_call to return, since it can safely handle ++ * all of the above. ++ */ ++ jmp int_ret_from_sys_call + + 1: + subq $REST_SKIP, %rsp # leave space for volatiles +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index 38d3751472e4..09651d4a9038 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -4646,7 +4646,8 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) + if (rc != X86EMUL_CONTINUE) + goto done; + } +- ctxt->dst.orig_val = ctxt->dst.val; ++ /* Copy full 64-bit value for CMPXCHG8B. */ ++ ctxt->dst.orig_val64 = ctxt->dst.val64; + + special_insn: + +diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c +index bb0b90461a6b..997540dc8250 100644 +--- a/drivers/acpi/video.c ++++ b/drivers/acpi/video.c +@@ -2064,6 +2064,17 @@ EXPORT_SYMBOL(acpi_video_unregister); + + static int __init acpi_video_init(void) + { ++ /* ++ * Let the module load even if ACPI is disabled (e.g. due to ++ * a broken BIOS) so that i915.ko can still be loaded on such ++ * old systems without an AcpiOpRegion. ++ * ++ * acpi_video_register() will report -ENODEV later as well due ++ * to acpi_disabled when i915.ko tries to register itself afterwards. ++ */ ++ if (acpi_disabled) ++ return 0; ++ + dmi_check_system(video_dmi_table); + + if (intel_opregion_present()) +diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c +index 4a58c55255bd..797bab97cea6 100644 +--- a/drivers/clk/clk-gate.c ++++ b/drivers/clk/clk-gate.c +@@ -128,7 +128,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name, + struct clk_init_data init; + + if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { +- if (bit_idx > 16) { ++ if (bit_idx > 15) { + pr_err("gate bit exceeds LOWORD field\n"); + return ERR_PTR(-EINVAL); + } +diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c +index 9e232644f07e..ea4db844aee3 100644 +--- a/drivers/clk/sunxi/clk-factors.c ++++ b/drivers/clk/sunxi/clk-factors.c +@@ -62,7 +62,7 @@ static unsigned long clk_factors_recalc_rate(struct clk_hw *hw, + p = FACTOR_GET(config->pshift, config->pwidth, reg); + + /* Calculate the rate */ +- rate = (parent_rate * n * (k + 1) >> p) / (m + 1); ++ rate = (parent_rate * (n + config->n_start) * (k + 1) >> p) / (m + 1); + + return rate; + } +diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h +index 02e1a43ebac7..d2d0efa39379 100644 +--- a/drivers/clk/sunxi/clk-factors.h ++++ b/drivers/clk/sunxi/clk-factors.h +@@ -15,6 +15,7 @@ struct clk_factors_config { + u8 mwidth; + u8 pshift; + u8 pwidth; ++ u8 n_start; + }; + + struct clk_factors { +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index abb6c5ac8a10..06a14b808683 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -407,6 +407,7 @@ static struct clk_factors_config sun6i_a31_pll1_config = { + .kwidth = 2, + .mshift = 0, + .mwidth = 2, ++ .n_start = 1, + }; + + static struct clk_factors_config sun4i_pll5_config = { +diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c +index 09dd0173ea0a..5f52f3f62644 100644 +--- a/drivers/clk/zynq/clkc.c ++++ b/drivers/clk/zynq/clkc.c +@@ -300,6 +300,7 @@ static void __init zynq_clk_setup(struct device_node *np) + clks[cpu_2x] = clk_register_gate(NULL, clk_output_name[cpu_2x], + "cpu_2x_div", CLK_IGNORE_UNUSED, SLCR_ARM_CLK_CTRL, + 26, 0, &armclk_lock); ++ clk_prepare_enable(clks[cpu_2x]); + + clk = clk_register_fixed_factor(NULL, "cpu_1x_div", "cpu_div", 0, 1, + 4 + 2 * tmp); +diff --git a/drivers/firmware/efi/runtime-map.c b/drivers/firmware/efi/runtime-map.c +index 97cdd16a2169..c98b101a73ae 100644 +--- a/drivers/firmware/efi/runtime-map.c ++++ b/drivers/firmware/efi/runtime-map.c +@@ -170,7 +170,7 @@ int __init efi_runtime_map_init(struct kobject *efi_kobj) + + return 0; + out_add_entry: +- for (j = i - 1; j > 0; j--) { ++ for (j = i - 1; j >= 0; j--) { + entry = *(map_entries + j); + kobject_put(&entry->kobj); + } +diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c +index 8ef67cb4ef1e..f0ed0baddf70 100644 +--- a/drivers/gpu/drm/radeon/cik.c ++++ b/drivers/gpu/drm/radeon/cik.c +@@ -3558,7 +3558,21 @@ void cik_fence_gfx_ring_emit(struct radeon_device *rdev, + struct radeon_ring *ring = &rdev->ring[fence->ring]; + u64 addr = rdev->fence_drv[fence->ring].gpu_addr; + +- /* EVENT_WRITE_EOP - flush caches, send int */ ++ /* Workaround for cache flush problems. First send a dummy EOP ++ * event down the pipe with seq one below. ++ */ ++ radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); ++ radeon_ring_write(ring, (EOP_TCL1_ACTION_EN | ++ EOP_TC_ACTION_EN | ++ EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) | ++ EVENT_INDEX(5))); ++ radeon_ring_write(ring, addr & 0xfffffffc); ++ radeon_ring_write(ring, (upper_32_bits(addr) & 0xffff) | ++ DATA_SEL(1) | INT_SEL(0)); ++ radeon_ring_write(ring, fence->seq - 1); ++ radeon_ring_write(ring, 0); ++ ++ /* Then send the real EOP event down the pipe. */ + radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); + radeon_ring_write(ring, (EOP_TCL1_ACTION_EN | + EOP_TC_ACTION_EN | +@@ -6809,7 +6823,6 @@ int cik_irq_set(struct radeon_device *rdev) + u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; + u32 grbm_int_cntl = 0; + u32 dma_cntl, dma_cntl1; +- u32 thermal_int; + + if (!rdev->irq.installed) { + WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); +@@ -6846,13 +6859,6 @@ int cik_irq_set(struct radeon_device *rdev) + cp_m2p2 = RREG32(CP_ME2_PIPE2_INT_CNTL) & ~TIME_STAMP_INT_ENABLE; + cp_m2p3 = RREG32(CP_ME2_PIPE3_INT_CNTL) & ~TIME_STAMP_INT_ENABLE; + +- if (rdev->flags & RADEON_IS_IGP) +- thermal_int = RREG32_SMC(CG_THERMAL_INT_CTRL) & +- ~(THERM_INTH_MASK | THERM_INTL_MASK); +- else +- thermal_int = RREG32_SMC(CG_THERMAL_INT) & +- ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); +- + /* enable CP interrupts on all rings */ + if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { + DRM_DEBUG("cik_irq_set: sw int gfx\n"); +@@ -7010,14 +7016,6 @@ int cik_irq_set(struct radeon_device *rdev) + hpd6 |= DC_HPDx_INT_EN; + } + +- if (rdev->irq.dpm_thermal) { +- DRM_DEBUG("dpm thermal\n"); +- if (rdev->flags & RADEON_IS_IGP) +- thermal_int |= THERM_INTH_MASK | THERM_INTL_MASK; +- else +- thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW; +- } +- + WREG32(CP_INT_CNTL_RING0, cp_int_cntl); + + WREG32(SDMA0_CNTL + SDMA0_REGISTER_OFFSET, dma_cntl); +@@ -7071,11 +7069,6 @@ int cik_irq_set(struct radeon_device *rdev) + WREG32(DC_HPD5_INT_CONTROL, hpd5); + WREG32(DC_HPD6_INT_CONTROL, hpd6); + +- if (rdev->flags & RADEON_IS_IGP) +- WREG32_SMC(CG_THERMAL_INT_CTRL, thermal_int); +- else +- WREG32_SMC(CG_THERMAL_INT, thermal_int); +- + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c +index 351db361239d..c7c7bc5d573f 100644 +--- a/drivers/gpu/drm/radeon/kv_dpm.c ++++ b/drivers/gpu/drm/radeon/kv_dpm.c +@@ -1121,6 +1121,19 @@ void kv_dpm_enable_bapm(struct radeon_device *rdev, bool enable) + } + } + ++static void kv_enable_thermal_int(struct radeon_device *rdev, bool enable) ++{ ++ u32 thermal_int; ++ ++ thermal_int = RREG32_SMC(CG_THERMAL_INT_CTRL); ++ if (enable) ++ thermal_int |= THERM_INTH_MASK | THERM_INTL_MASK; ++ else ++ thermal_int &= ~(THERM_INTH_MASK | THERM_INTL_MASK); ++ WREG32_SMC(CG_THERMAL_INT_CTRL, thermal_int); ++ ++} ++ + int kv_dpm_enable(struct radeon_device *rdev) + { + struct kv_power_info *pi = kv_get_pi(rdev); +@@ -1232,8 +1245,7 @@ int kv_dpm_late_enable(struct radeon_device *rdev) + DRM_ERROR("kv_set_thermal_temperature_range failed\n"); + return ret; + } +- rdev->irq.dpm_thermal = true; +- radeon_irq_set(rdev); ++ kv_enable_thermal_int(rdev, true); + } + + /* powerdown unused blocks for now */ +@@ -1261,6 +1273,7 @@ void kv_dpm_disable(struct radeon_device *rdev) + kv_stop_dpm(rdev); + kv_enable_ulv(rdev, false); + kv_reset_am(rdev); ++ kv_enable_thermal_int(rdev, false); + + kv_update_current_ps(rdev, rdev->pm.dpm.boot_ps); + } +diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c +index bf6300cfd62d..f8c01b8d1594 100644 +--- a/drivers/gpu/drm/radeon/ni.c ++++ b/drivers/gpu/drm/radeon/ni.c +@@ -1073,12 +1073,12 @@ static void cayman_gpu_init(struct radeon_device *rdev) + + if ((rdev->config.cayman.max_backends_per_se == 1) && + (rdev->flags & RADEON_IS_IGP)) { +- if ((disabled_rb_mask & 3) == 1) { +- /* RB0 disabled, RB1 enabled */ +- tmp = 0x11111111; +- } else { ++ if ((disabled_rb_mask & 3) == 2) { + /* RB1 disabled, RB0 enabled */ + tmp = 0x00000000; ++ } else { ++ /* RB0 disabled, RB1 enabled */ ++ tmp = 0x11111111; + } + } else { + tmp = gb_addr_config & NUM_PIPES_MASK; +diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c +index 3334f916945b..e98108236e04 100644 +--- a/drivers/gpu/drm/radeon/r600_dpm.c ++++ b/drivers/gpu/drm/radeon/r600_dpm.c +@@ -187,7 +187,7 @@ u32 r600_dpm_get_vrefresh(struct radeon_device *rdev) + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + radeon_crtc = to_radeon_crtc(crtc); + if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) { +- vrefresh = radeon_crtc->hw_mode.vrefresh; ++ vrefresh = drm_mode_vrefresh(&radeon_crtc->hw_mode); + break; + } + } +diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c +index e2de749327ad..2fa3cf615a67 100644 +--- a/drivers/gpu/drm/radeon/radeon_atombios.c ++++ b/drivers/gpu/drm/radeon/radeon_atombios.c +@@ -3272,6 +3272,7 @@ int radeon_atom_get_voltage_evv(struct radeon_device *rdev, + + args.in.ucVoltageType = VOLTAGE_TYPE_VDDC; + args.in.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE; ++ args.in.usVoltageLevel = cpu_to_le16(virtual_voltage_id); + args.in.ulSCLKFreq = + cpu_to_le32(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[entry_id].clk); + +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index 4b87bb164f30..a413f76e84d4 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -1066,6 +1066,23 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct + return; + } + ++ /* ++ * Ignore reports for absolute data if the data didn't change. This is ++ * not only an optimization but also fixes 'dead' key reports. Some ++ * RollOver implementations for localized keys (like BACKSLASH/PIPE; HID ++ * 0x31 and 0x32) report multiple keys, even though a localized keyboard ++ * can only have one of them physically available. The 'dead' keys ++ * report constant 0. As all map to the same keycode, they'd confuse ++ * the input layer. If we filter the 'dead' keys on the HID level, we ++ * skip the keycode translation and only forward real events. ++ */ ++ if (!(field->flags & (HID_MAIN_ITEM_RELATIVE | ++ HID_MAIN_ITEM_BUFFERED_BYTE)) && ++ (field->flags & HID_MAIN_ITEM_VARIABLE) && ++ usage->usage_index < field->maxusage && ++ value == field->value[usage->usage_index]) ++ return; ++ + /* report the usage code as scancode if the key status has changed */ + if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value) + input_event(input, EV_MSC, MSC_SCAN, usage->hid); +diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c +index 47dcb34ff44c..3a615f3b5d80 100644 +--- a/drivers/iio/adc/mcp3422.c ++++ b/drivers/iio/adc/mcp3422.c +@@ -57,20 +57,11 @@ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + } + +-/* LSB is in nV to eliminate floating point */ +-static const u32 rates_to_lsb[] = {1000000, 250000, 62500, 15625}; +- +-/* +- * scales calculated as: +- * rates_to_lsb[sample_rate] / (1 << pga); +- * pga is 1 for 0, 2 +- */ +- + static const int mcp3422_scales[4][4] = { +- { 1000000, 250000, 62500, 15625 }, +- { 500000 , 125000, 31250, 7812 }, +- { 250000 , 62500 , 15625, 3906 }, +- { 125000 , 31250 , 7812 , 1953 } }; ++ { 1000000, 500000, 250000, 125000 }, ++ { 250000 , 125000, 62500 , 31250 }, ++ { 62500 , 31250 , 15625 , 7812 }, ++ { 15625 , 7812 , 3906 , 1953 } }; + + /* Constant msleep times for data acquisitions */ + static const int mcp3422_read_times[4] = { +diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c +index 17aca4d9bd06..861ba3d60163 100644 +--- a/drivers/iio/dac/ad5686.c ++++ b/drivers/iio/dac/ad5686.c +@@ -322,7 +322,7 @@ static int ad5686_probe(struct spi_device *spi) + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + +- st->reg = devm_regulator_get(&spi->dev, "vcc"); ++ st->reg = devm_regulator_get_optional(&spi->dev, "vcc"); + if (!IS_ERR(st->reg)) { + ret = regulator_enable(st->reg); + if (ret) +diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c +index 7c582f7ae34e..70753bf23a86 100644 +--- a/drivers/iio/imu/adis16400_core.c ++++ b/drivers/iio/imu/adis16400_core.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -447,7 +448,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, + mutex_unlock(&indio_dev->mlock); + if (ret) + return ret; +- val16 = ((val16 & 0xFFF) << 4) >> 4; ++ val16 = sign_extend32(val16, 11); + *val = val16; + return IIO_VAL_INT; + case IIO_CHAN_INFO_OFFSET: +diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c +index 56a4b7ca7ee3..45d67e9228d7 100644 +--- a/drivers/infiniband/core/ucma.c ++++ b/drivers/infiniband/core/ucma.c +@@ -1124,6 +1124,9 @@ static int ucma_set_ib_path(struct ucma_context *ctx, + if (!optlen) + return -EINVAL; + ++ memset(&sa_path, 0, sizeof(sa_path)); ++ sa_path.vlan_id = 0xffff; ++ + ib_sa_unpack_path(path_data->path_rec, &sa_path); + ret = rdma_set_ib_paths(ctx->cm_id, &sa_path, 1); + if (ret) +diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c +index 23467a2abd62..2adc14372b94 100644 +--- a/drivers/infiniband/core/uverbs_cmd.c ++++ b/drivers/infiniband/core/uverbs_cmd.c +@@ -1964,20 +1964,21 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, + if (qp->real_qp == qp) { + ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd.attr_mask); + if (ret) +- goto out; ++ goto release_qp; + ret = qp->device->modify_qp(qp, attr, + modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata); + } else { + ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask)); + } + +- put_qp_read(qp); +- + if (ret) +- goto out; ++ goto release_qp; + + ret = in_len; + ++release_qp: ++ put_qp_read(qp); ++ + out: + kfree(attr); + +diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c +index 11f0606792bb..1a3d924744cc 100644 +--- a/drivers/infiniband/hw/mlx4/main.c ++++ b/drivers/infiniband/hw/mlx4/main.c +@@ -1161,8 +1161,7 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) + struct mlx4_ib_qp *mqp = to_mqp(ibqp); + u64 reg_id; + struct mlx4_ib_steering *ib_steering = NULL; +- enum mlx4_protocol prot = (gid->raw[1] == 0x0e) ? +- MLX4_PROT_IB_IPV4 : MLX4_PROT_IB_IPV6; ++ enum mlx4_protocol prot = MLX4_PROT_IB_IPV6; + + if (mdev->dev->caps.steering_mode == + MLX4_STEERING_MODE_DEVICE_MANAGED) { +@@ -1175,8 +1174,10 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) + !!(mqp->flags & + MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK), + prot, ®_id); +- if (err) ++ if (err) { ++ pr_err("multicast attach op failed, err %d\n", err); + goto err_malloc; ++ } + + err = add_gid_entry(ibqp, gid); + if (err) +@@ -1224,8 +1225,7 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) + struct net_device *ndev; + struct mlx4_ib_gid_entry *ge; + u64 reg_id = 0; +- enum mlx4_protocol prot = (gid->raw[1] == 0x0e) ? +- MLX4_PROT_IB_IPV4 : MLX4_PROT_IB_IPV6; ++ enum mlx4_protocol prot = MLX4_PROT_IB_IPV6; + + if (mdev->dev->caps.steering_mode == + MLX4_STEERING_MODE_DEVICE_MANAGED) { +diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h +index 1946101419a3..675d3c796b9f 100644 +--- a/drivers/infiniband/hw/qib/qib.h ++++ b/drivers/infiniband/hw/qib/qib.h +@@ -1080,12 +1080,6 @@ struct qib_devdata { + /* control high-level access to EEPROM */ + struct mutex eep_lock; + uint64_t traffic_wds; +- /* active time is kept in seconds, but logged in hours */ +- atomic_t active_time; +- /* Below are nominal shadow of EEPROM, new since last EEPROM update */ +- uint8_t eep_st_errs[QIB_EEP_LOG_CNT]; +- uint8_t eep_st_new_errs[QIB_EEP_LOG_CNT]; +- uint16_t eep_hrs; + /* + * masks for which bits of errs, hwerrs that cause + * each of the counters to increment. +@@ -1307,8 +1301,7 @@ int qib_twsi_blk_rd(struct qib_devdata *dd, int dev, int addr, void *buffer, + int qib_twsi_blk_wr(struct qib_devdata *dd, int dev, int addr, + const void *buffer, int len); + void qib_get_eeprom_info(struct qib_devdata *); +-int qib_update_eeprom_log(struct qib_devdata *dd); +-void qib_inc_eeprom_err(struct qib_devdata *dd, u32 eidx, u32 incr); ++#define qib_inc_eeprom_err(dd, eidx, incr) + void qib_dump_lookup_output_queue(struct qib_devdata *); + void qib_force_pio_avail_update(struct qib_devdata *); + void qib_clear_symerror_on_linkup(unsigned long opaque); +diff --git a/drivers/infiniband/hw/qib/qib_eeprom.c b/drivers/infiniband/hw/qib/qib_eeprom.c +index 4d5d71aaa2b4..e2280b07df02 100644 +--- a/drivers/infiniband/hw/qib/qib_eeprom.c ++++ b/drivers/infiniband/hw/qib/qib_eeprom.c +@@ -267,190 +267,9 @@ void qib_get_eeprom_info(struct qib_devdata *dd) + "Board SN %s did not pass functional test: %s\n", + dd->serial, ifp->if_comment); + +- memcpy(&dd->eep_st_errs, &ifp->if_errcntp, QIB_EEP_LOG_CNT); +- /* +- * Power-on (actually "active") hours are kept as little-endian value +- * in EEPROM, but as seconds in a (possibly as small as 24-bit) +- * atomic_t while running. +- */ +- atomic_set(&dd->active_time, 0); +- dd->eep_hrs = ifp->if_powerhour[0] | (ifp->if_powerhour[1] << 8); +- + done: + vfree(buf); + + bail:; + } + +-/** +- * qib_update_eeprom_log - copy active-time and error counters to eeprom +- * @dd: the qlogic_ib device +- * +- * Although the time is kept as seconds in the qib_devdata struct, it is +- * rounded to hours for re-write, as we have only 16 bits in EEPROM. +- * First-cut code reads whole (expected) struct qib_flash, modifies, +- * re-writes. Future direction: read/write only what we need, assuming +- * that the EEPROM had to have been "good enough" for driver init, and +- * if not, we aren't making it worse. +- * +- */ +-int qib_update_eeprom_log(struct qib_devdata *dd) +-{ +- void *buf; +- struct qib_flash *ifp; +- int len, hi_water; +- uint32_t new_time, new_hrs; +- u8 csum; +- int ret, idx; +- unsigned long flags; +- +- /* first, check if we actually need to do anything. */ +- ret = 0; +- for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) { +- if (dd->eep_st_new_errs[idx]) { +- ret = 1; +- break; +- } +- } +- new_time = atomic_read(&dd->active_time); +- +- if (ret == 0 && new_time < 3600) +- goto bail; +- +- /* +- * The quick-check above determined that there is something worthy +- * of logging, so get current contents and do a more detailed idea. +- * read full flash, not just currently used part, since it may have +- * been written with a newer definition +- */ +- len = sizeof(struct qib_flash); +- buf = vmalloc(len); +- ret = 1; +- if (!buf) { +- qib_dev_err(dd, +- "Couldn't allocate memory to read %u bytes from eeprom for logging\n", +- len); +- goto bail; +- } +- +- /* Grab semaphore and read current EEPROM. If we get an +- * error, let go, but if not, keep it until we finish write. +- */ +- ret = mutex_lock_interruptible(&dd->eep_lock); +- if (ret) { +- qib_dev_err(dd, "Unable to acquire EEPROM for logging\n"); +- goto free_bail; +- } +- ret = qib_twsi_blk_rd(dd, dd->twsi_eeprom_dev, 0, buf, len); +- if (ret) { +- mutex_unlock(&dd->eep_lock); +- qib_dev_err(dd, "Unable read EEPROM for logging\n"); +- goto free_bail; +- } +- ifp = (struct qib_flash *)buf; +- +- csum = flash_csum(ifp, 0); +- if (csum != ifp->if_csum) { +- mutex_unlock(&dd->eep_lock); +- qib_dev_err(dd, "EEPROM cks err (0x%02X, S/B 0x%02X)\n", +- csum, ifp->if_csum); +- ret = 1; +- goto free_bail; +- } +- hi_water = 0; +- spin_lock_irqsave(&dd->eep_st_lock, flags); +- for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) { +- int new_val = dd->eep_st_new_errs[idx]; +- if (new_val) { +- /* +- * If we have seen any errors, add to EEPROM values +- * We need to saturate at 0xFF (255) and we also +- * would need to adjust the checksum if we were +- * trying to minimize EEPROM traffic +- * Note that we add to actual current count in EEPROM, +- * in case it was altered while we were running. +- */ +- new_val += ifp->if_errcntp[idx]; +- if (new_val > 0xFF) +- new_val = 0xFF; +- if (ifp->if_errcntp[idx] != new_val) { +- ifp->if_errcntp[idx] = new_val; +- hi_water = offsetof(struct qib_flash, +- if_errcntp) + idx; +- } +- /* +- * update our shadow (used to minimize EEPROM +- * traffic), to match what we are about to write. +- */ +- dd->eep_st_errs[idx] = new_val; +- dd->eep_st_new_errs[idx] = 0; +- } +- } +- /* +- * Now update active-time. We would like to round to the nearest hour +- * but unless atomic_t are sure to be proper signed ints we cannot, +- * because we need to account for what we "transfer" to EEPROM and +- * if we log an hour at 31 minutes, then we would need to set +- * active_time to -29 to accurately count the _next_ hour. +- */ +- if (new_time >= 3600) { +- new_hrs = new_time / 3600; +- atomic_sub((new_hrs * 3600), &dd->active_time); +- new_hrs += dd->eep_hrs; +- if (new_hrs > 0xFFFF) +- new_hrs = 0xFFFF; +- dd->eep_hrs = new_hrs; +- if ((new_hrs & 0xFF) != ifp->if_powerhour[0]) { +- ifp->if_powerhour[0] = new_hrs & 0xFF; +- hi_water = offsetof(struct qib_flash, if_powerhour); +- } +- if ((new_hrs >> 8) != ifp->if_powerhour[1]) { +- ifp->if_powerhour[1] = new_hrs >> 8; +- hi_water = offsetof(struct qib_flash, if_powerhour) + 1; +- } +- } +- /* +- * There is a tiny possibility that we could somehow fail to write +- * the EEPROM after updating our shadows, but problems from holding +- * the spinlock too long are a much bigger issue. +- */ +- spin_unlock_irqrestore(&dd->eep_st_lock, flags); +- if (hi_water) { +- /* we made some change to the data, uopdate cksum and write */ +- csum = flash_csum(ifp, 1); +- ret = eeprom_write_with_enable(dd, 0, buf, hi_water + 1); +- } +- mutex_unlock(&dd->eep_lock); +- if (ret) +- qib_dev_err(dd, "Failed updating EEPROM\n"); +- +-free_bail: +- vfree(buf); +-bail: +- return ret; +-} +- +-/** +- * qib_inc_eeprom_err - increment one of the four error counters +- * that are logged to EEPROM. +- * @dd: the qlogic_ib device +- * @eidx: 0..3, the counter to increment +- * @incr: how much to add +- * +- * Each counter is 8-bits, and saturates at 255 (0xFF). They +- * are copied to the EEPROM (aka flash) whenever qib_update_eeprom_log() +- * is called, but it can only be called in a context that allows sleep. +- * This function can be called even at interrupt level. +- */ +-void qib_inc_eeprom_err(struct qib_devdata *dd, u32 eidx, u32 incr) +-{ +- uint new_val; +- unsigned long flags; +- +- spin_lock_irqsave(&dd->eep_st_lock, flags); +- new_val = dd->eep_st_new_errs[eidx] + incr; +- if (new_val > 255) +- new_val = 255; +- dd->eep_st_new_errs[eidx] = new_val; +- spin_unlock_irqrestore(&dd->eep_st_lock, flags); +-} +diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c +index 84e593d6007b..295f6312e6a9 100644 +--- a/drivers/infiniband/hw/qib/qib_iba6120.c ++++ b/drivers/infiniband/hw/qib/qib_iba6120.c +@@ -2682,8 +2682,6 @@ static void qib_get_6120_faststats(unsigned long opaque) + spin_lock_irqsave(&dd->eep_st_lock, flags); + traffic_wds -= dd->traffic_wds; + dd->traffic_wds += traffic_wds; +- if (traffic_wds >= QIB_TRAFFIC_ACTIVE_THRESHOLD) +- atomic_add(5, &dd->active_time); /* S/B #define */ + spin_unlock_irqrestore(&dd->eep_st_lock, flags); + + qib_chk_6120_errormask(dd); +diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c +index 454c2e7668fe..c86e71b9e160 100644 +--- a/drivers/infiniband/hw/qib/qib_iba7220.c ++++ b/drivers/infiniband/hw/qib/qib_iba7220.c +@@ -3299,8 +3299,6 @@ static void qib_get_7220_faststats(unsigned long opaque) + spin_lock_irqsave(&dd->eep_st_lock, flags); + traffic_wds -= dd->traffic_wds; + dd->traffic_wds += traffic_wds; +- if (traffic_wds >= QIB_TRAFFIC_ACTIVE_THRESHOLD) +- atomic_add(5, &dd->active_time); /* S/B #define */ + spin_unlock_irqrestore(&dd->eep_st_lock, flags); + done: + mod_timer(&dd->stats_timer, jiffies + HZ * ACTIVITY_TIMER); +diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c +index d1bd21319d7d..0f8d1f0bd929 100644 +--- a/drivers/infiniband/hw/qib/qib_iba7322.c ++++ b/drivers/infiniband/hw/qib/qib_iba7322.c +@@ -5191,8 +5191,6 @@ static void qib_get_7322_faststats(unsigned long opaque) + spin_lock_irqsave(&ppd->dd->eep_st_lock, flags); + traffic_wds -= ppd->dd->traffic_wds; + ppd->dd->traffic_wds += traffic_wds; +- if (traffic_wds >= QIB_TRAFFIC_ACTIVE_THRESHOLD) +- atomic_add(ACTIVITY_TIMER, &ppd->dd->active_time); + spin_unlock_irqrestore(&ppd->dd->eep_st_lock, flags); + if (ppd->cpspec->qdr_dfe_on && (ppd->link_speed_active & + QIB_IB_QDR) && +diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c +index 76c3e177164d..8c9bb6c35838 100644 +--- a/drivers/infiniband/hw/qib/qib_init.c ++++ b/drivers/infiniband/hw/qib/qib_init.c +@@ -922,7 +922,6 @@ static void qib_shutdown_device(struct qib_devdata *dd) + } + } + +- qib_update_eeprom_log(dd); + } + + /** +diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c +index 3c8e4e3caca6..b9ccbda7817d 100644 +--- a/drivers/infiniband/hw/qib/qib_sysfs.c ++++ b/drivers/infiniband/hw/qib/qib_sysfs.c +@@ -611,28 +611,6 @@ bail: + return ret < 0 ? ret : count; + } + +-static ssize_t show_logged_errs(struct device *device, +- struct device_attribute *attr, char *buf) +-{ +- struct qib_ibdev *dev = +- container_of(device, struct qib_ibdev, ibdev.dev); +- struct qib_devdata *dd = dd_from_dev(dev); +- int idx, count; +- +- /* force consistency with actual EEPROM */ +- if (qib_update_eeprom_log(dd) != 0) +- return -ENXIO; +- +- count = 0; +- for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) { +- count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c", +- dd->eep_st_errs[idx], +- idx == (QIB_EEP_LOG_CNT - 1) ? '\n' : ' '); +- } +- +- return count; +-} +- + /* + * Dump tempsense regs. in decimal, to ease shell-scripts. + */ +@@ -679,7 +657,6 @@ static DEVICE_ATTR(nctxts, S_IRUGO, show_nctxts, NULL); + static DEVICE_ATTR(nfreectxts, S_IRUGO, show_nfreectxts, NULL); + static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL); + static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL); +-static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL); + static DEVICE_ATTR(tempsense, S_IRUGO, show_tempsense, NULL); + static DEVICE_ATTR(localbus_info, S_IRUGO, show_localbus_info, NULL); + static DEVICE_ATTR(chip_reset, S_IWUSR, NULL, store_chip_reset); +@@ -693,7 +670,6 @@ static struct device_attribute *qib_attributes[] = { + &dev_attr_nfreectxts, + &dev_attr_serial, + &dev_attr_boardversion, +- &dev_attr_logged_errors, + &dev_attr_tempsense, + &dev_attr_localbus_info, + &dev_attr_chip_reset, +diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c +index 05f371df6c40..d4b0a31ab66b 100644 +--- a/drivers/input/tablet/wacom_wac.c ++++ b/drivers/input/tablet/wacom_wac.c +@@ -700,6 +700,12 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) + input_report_key(input, BTN_7, (data[4] & 0x40)); /* Left */ + input_report_key(input, BTN_8, (data[4] & 0x80)); /* Down */ + input_report_key(input, BTN_0, (data[3] & 0x01)); /* Center */ ++ ++ if (data[4] | (data[3] & 0x01)) { ++ input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); ++ } else { ++ input_report_abs(input, ABS_MISC, 0); ++ } + } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) { + int i; + +diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c +index db404a0f7e2c..d2a8d64f8526 100644 +--- a/drivers/md/dm-io.c ++++ b/drivers/md/dm-io.c +@@ -292,6 +292,12 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, + unsigned short logical_block_size = queue_logical_block_size(q); + sector_t num_sectors; + ++ /* Reject unsupported discard requests */ ++ if ((rw & REQ_DISCARD) && !blk_queue_discard(q)) { ++ dec_count(io, region, -EOPNOTSUPP); ++ return; ++ } ++ + /* + * where->count may be zero if rw holds a flush and we need to + * send a zero-sized flush. +diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c +index 7dfdb5c746d6..089d62751f7f 100644 +--- a/drivers/md/dm-raid1.c ++++ b/drivers/md/dm-raid1.c +@@ -604,6 +604,15 @@ static void write_callback(unsigned long error, void *context) + return; + } + ++ /* ++ * If the bio is discard, return an error, but do not ++ * degrade the array. ++ */ ++ if (bio->bi_rw & REQ_DISCARD) { ++ bio_endio(bio, -EOPNOTSUPP); ++ return; ++ } ++ + for (i = 0; i < ms->nr_mirrors; i++) + if (test_bit(i, &error)) + fail_mirror(ms->mirror + i, DM_RAID1_WRITE_ERROR); +diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c +index ebddef5237e4..c356a10b9ba5 100644 +--- a/drivers/md/dm-snap.c ++++ b/drivers/md/dm-snap.c +@@ -1440,8 +1440,6 @@ out: + full_bio->bi_private = pe->full_bio_private; + atomic_inc(&full_bio->bi_remaining); + } +- free_pending_exception(pe); +- + increment_pending_exceptions_done_count(); + + up_write(&s->lock); +@@ -1458,6 +1456,8 @@ out: + } + + retry_origin_bios(s, origin_bios); ++ ++ free_pending_exception(pe); + } + + static void commit_callback(void *context, int success) +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index 65ee3a0d4683..1582c3dac3ac 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -2288,7 +2288,7 @@ int dm_setup_md_queue(struct mapped_device *md) + return 0; + } + +-static struct mapped_device *dm_find_md(dev_t dev) ++struct mapped_device *dm_get_md(dev_t dev) + { + struct mapped_device *md; + unsigned minor = MINOR(dev); +@@ -2299,12 +2299,15 @@ static struct mapped_device *dm_find_md(dev_t dev) + spin_lock(&_minor_lock); + + md = idr_find(&_minor_idr, minor); +- if (md && (md == MINOR_ALLOCED || +- (MINOR(disk_devt(dm_disk(md))) != minor) || +- dm_deleting_md(md) || +- test_bit(DMF_FREEING, &md->flags))) { +- md = NULL; +- goto out; ++ if (md) { ++ if ((md == MINOR_ALLOCED || ++ (MINOR(disk_devt(dm_disk(md))) != minor) || ++ dm_deleting_md(md) || ++ test_bit(DMF_FREEING, &md->flags))) { ++ md = NULL; ++ goto out; ++ } ++ dm_get(md); + } + + out: +@@ -2312,16 +2315,6 @@ out: + + return md; + } +- +-struct mapped_device *dm_get_md(dev_t dev) +-{ +- struct mapped_device *md = dm_find_md(dev); +- +- if (md) +- dm_get(md); +- +- return md; +-} + EXPORT_SYMBOL_GPL(dm_get_md); + + void *dm_get_mdptr(struct mapped_device *md) +diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c +index cdd31c2a2a2b..b2965382d0ec 100644 +--- a/drivers/misc/mei/init.c ++++ b/drivers/misc/mei/init.c +@@ -275,6 +275,8 @@ void mei_stop(struct mei_device *dev) + + dev->dev_state = MEI_DEV_POWER_DOWN; + mei_reset(dev); ++ /* move device to disabled state unconditionally */ ++ dev->dev_state = MEI_DEV_DISABLED; + + mutex_unlock(&dev->device_lock); + +diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c +index 07c942b6ae01..e8c21f911b6f 100644 +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -637,12 +637,15 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, + } /* else everything is zero */ + } + ++/* Neighbour code has some assumptions on HH_DATA_MOD alignment */ ++#define MACVTAP_RESERVE HH_DATA_OFF(ETH_HLEN) ++ + /* Get packet from user space buffer */ + static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, + const struct iovec *iv, unsigned long total_len, + size_t count, int noblock) + { +- int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN); ++ int good_linear = SKB_MAX_HEAD(MACVTAP_RESERVE); + struct sk_buff *skb; + struct macvlan_dev *vlan; + unsigned long len = total_len; +@@ -701,7 +704,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, + linear = vnet_hdr.hdr_len; + } + +- skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen, ++ skb = macvtap_alloc_skb(&q->sk, MACVTAP_RESERVE, copylen, + linear, noblock, &err); + if (!skb) + goto err; +diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c +index 76d96b9ebcdb..1d568788c3e3 100644 +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -194,6 +194,25 @@ static inline unsigned int phy_find_valid(unsigned int idx, u32 features) + } + + /** ++ * phy_check_valid - check if there is a valid PHY setting which matches ++ * speed, duplex, and feature mask ++ * @speed: speed to match ++ * @duplex: duplex to match ++ * @features: A mask of the valid settings ++ * ++ * Description: Returns true if there is a valid setting, false otherwise. ++ */ ++static inline bool phy_check_valid(int speed, int duplex, u32 features) ++{ ++ unsigned int idx; ++ ++ idx = phy_find_valid(phy_find_setting(speed, duplex), features); ++ ++ return settings[idx].speed == speed && settings[idx].duplex == duplex && ++ (settings[idx].setting & features); ++} ++ ++/** + * phy_sanitize_settings - make sure the PHY is set to supported speed and duplex + * @phydev: the target phy_device struct + * +@@ -955,7 +974,6 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable) + int eee_lp, eee_cap, eee_adv; + u32 lp, cap, adv; + int status; +- unsigned int idx; + + /* Read phy status to properly get the right settings */ + status = phy_read_status(phydev); +@@ -987,8 +1005,7 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable) + + adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv); + lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp); +- idx = phy_find_setting(phydev->speed, phydev->duplex); +- if (!(lp & adv & settings[idx].setting)) ++ if (!phy_check_valid(phydev->speed, phydev->duplex, lp & adv)) + return -EPROTONOSUPPORT; + + if (clk_stop_enable) { +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 32efe8371ff8..c28e2dafb3f0 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -42,9 +42,7 @@ + + static struct team_port *team_port_get_rcu(const struct net_device *dev) + { +- struct team_port *port = rcu_dereference(dev->rx_handler_data); +- +- return team_port_exists(dev) ? port : NULL; ++ return rcu_dereference(dev->rx_handler_data); + } + + static struct team_port *team_port_get_rtnl(const struct net_device *dev) +@@ -1725,11 +1723,11 @@ static int team_set_mac_address(struct net_device *dev, void *p) + if (dev->type == ARPHRD_ETHER && !is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); +- rcu_read_lock(); +- list_for_each_entry_rcu(port, &team->port_list, list) ++ mutex_lock(&team->lock); ++ list_for_each_entry(port, &team->port_list, list) + if (team->ops.port_change_dev_addr) + team->ops.port_change_dev_addr(team, port); +- rcu_read_unlock(); ++ mutex_unlock(&team->lock); + return 0; + } + +diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c +index 3d18bb0eee85..1bfe0fcaccf5 100644 +--- a/drivers/net/usb/plusb.c ++++ b/drivers/net/usb/plusb.c +@@ -134,6 +134,11 @@ static const struct usb_device_id products [] = { + }, { + USB_DEVICE(0x050d, 0x258a), /* Belkin F5U258/F5U279 (PL-25A1) */ + .driver_info = (unsigned long) &prolific_info, ++}, { ++ USB_DEVICE(0x3923, 0x7825), /* National Instruments USB ++ * Host-to-Host Cable ++ */ ++ .driver_info = (unsigned long) &prolific_info, + }, + + { }, // END +diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c +index a3399c4f13a9..b9b651ea9851 100644 +--- a/drivers/net/wireless/ath/ath5k/reset.c ++++ b/drivers/net/wireless/ath/ath5k/reset.c +@@ -478,7 +478,7 @@ ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) + regval = ioread32(reg); + iowrite32(regval | val, reg); + regval = ioread32(reg); +- usleep_range(100, 150); ++ udelay(100); /* NB: should be atomic */ + + /* Bring BB/MAC out of reset */ + iowrite32(regval & ~val, reg); +diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c +index 5642a9b250c2..953bd0bfdf0d 100644 +--- a/drivers/scsi/be2iscsi/be_main.c ++++ b/drivers/scsi/be2iscsi/be_main.c +@@ -581,7 +581,6 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) + "beiscsi_hba_alloc - iscsi_host_alloc failed\n"); + return NULL; + } +- shost->dma_boundary = pcidev->dma_mask; + shost->max_id = BE2_MAX_SESSIONS; + shost->max_channel = 0; + shost->max_cmd_len = BEISCSI_MAX_CMD_LEN; +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index df5e961484e1..eb81c98386b9 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -522,7 +522,7 @@ static ssize_t + sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp) + { + sg_io_hdr_t *hp = &srp->header; +- int err = 0; ++ int err = 0, err2; + int len; + + if (count < SZ_SG_IO_HDR) { +@@ -551,8 +551,8 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp) + goto err_out; + } + err_out: +- err = sg_finish_rem_req(srp); +- return (0 == err) ? count : err; ++ err2 = sg_finish_rem_req(srp); ++ return err ? : err2 ? : count; + } + + static ssize_t +diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c +index 1e9da405d833..528781049ad5 100644 +--- a/drivers/staging/comedi/comedi_compat32.c ++++ b/drivers/staging/comedi/comedi_compat32.c +@@ -262,7 +262,7 @@ static int compat_cmd(struct file *file, unsigned long arg) + { + struct comedi_cmd __user *cmd; + struct comedi32_cmd_struct __user *cmd32; +- int rc; ++ int rc, err; + + cmd32 = compat_ptr(arg); + cmd = compat_alloc_user_space(sizeof(*cmd)); +@@ -271,7 +271,15 @@ static int compat_cmd(struct file *file, unsigned long arg) + if (rc) + return rc; + +- return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd); ++ rc = translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd); ++ if (rc == -EAGAIN) { ++ /* Special case: copy cmd back to user. */ ++ err = put_compat_cmd(cmd32, cmd); ++ if (err) ++ rc = err; ++ } ++ ++ return rc; + } + + /* Handle 32-bit COMEDI_CMDTEST ioctl. */ +diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c +index 4fff1738e3f8..3d1cb5b0a956 100644 +--- a/drivers/staging/comedi/drivers/cb_pcidas64.c ++++ b/drivers/staging/comedi/drivers/cb_pcidas64.c +@@ -441,6 +441,29 @@ static const struct comedi_lrange ai_ranges_64xx = { + } + }; + ++static const uint8_t ai_range_code_64xx[8] = { ++ 0x0, 0x1, 0x2, 0x3, /* bipolar 10, 5, 2,5, 1.25 */ ++ 0x8, 0x9, 0xa, 0xb /* unipolar 10, 5, 2.5, 1.25 */ ++}; ++ ++/* analog input ranges for 64-Mx boards */ ++static const struct comedi_lrange ai_ranges_64_mx = { ++ 7, { ++ BIP_RANGE(5), ++ BIP_RANGE(2.5), ++ BIP_RANGE(1.25), ++ BIP_RANGE(0.625), ++ UNI_RANGE(5), ++ UNI_RANGE(2.5), ++ UNI_RANGE(1.25) ++ } ++}; ++ ++static const uint8_t ai_range_code_64_mx[7] = { ++ 0x0, 0x1, 0x2, 0x3, /* bipolar 5, 2.5, 1.25, 0.625 */ ++ 0x9, 0xa, 0xb /* unipolar 5, 2.5, 1.25 */ ++}; ++ + /* analog input ranges for 60xx boards */ + static const struct comedi_lrange ai_ranges_60xx = { + 4, { +@@ -451,6 +474,10 @@ static const struct comedi_lrange ai_ranges_60xx = { + } + }; + ++static const uint8_t ai_range_code_60xx[4] = { ++ 0x0, 0x1, 0x4, 0x7 /* bipolar 10, 5, 0.5, 0.05 */ ++}; ++ + /* analog input ranges for 6030, etc boards */ + static const struct comedi_lrange ai_ranges_6030 = { + 14, { +@@ -471,6 +498,11 @@ static const struct comedi_lrange ai_ranges_6030 = { + } + }; + ++static const uint8_t ai_range_code_6030[14] = { ++ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, /* bip 10, 5, 2, 1, 0.5, 0.2, 0.1 */ ++ 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* uni 10, 5, 2, 1, 0.5, 0.2, 0.1 */ ++}; ++ + /* analog input ranges for 6052, etc boards */ + static const struct comedi_lrange ai_ranges_6052 = { + 15, { +@@ -492,6 +524,11 @@ static const struct comedi_lrange ai_ranges_6052 = { + } + }; + ++static const uint8_t ai_range_code_6052[15] = { ++ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, /* bipolar 10 ... 0.05 */ ++ 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* unipolar 10 ... 0.1 */ ++}; ++ + /* analog input ranges for 4020 board */ + static const struct comedi_lrange ai_ranges_4020 = { + 2, { +@@ -595,6 +632,7 @@ struct pcidas64_board { + int ai_bits; /* analog input resolution */ + int ai_speed; /* fastest conversion period in ns */ + const struct comedi_lrange *ai_range_table; ++ const uint8_t *ai_range_code; + int ao_nchan; /* number of analog out channels */ + int ao_bits; /* analog output resolution */ + int ao_scan_speed; /* analog output scan speed */ +@@ -653,6 +691,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, ++ .ai_range_code = ai_range_code_64xx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, +@@ -668,6 +707,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, ++ .ai_range_code = ai_range_code_64xx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, +@@ -682,7 +722,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_bits = 16, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, +@@ -697,7 +738,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_bits = 16, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, +@@ -712,7 +754,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_bits = 16, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ao_range_table = &ao_ranges_64xx, + .ao_range_code = ao_range_code_64xx, + .ai_fifo = &ai_fifo_64xx, +@@ -727,6 +770,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_bits = 16, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -742,6 +786,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -756,6 +801,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -771,6 +817,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -786,6 +833,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 10000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, ++ .ai_range_code = ai_range_code_6030, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -801,6 +849,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 10000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, ++ .ai_range_code = ai_range_code_6030, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -814,6 +863,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 0, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, ++ .ai_range_code = ai_range_code_6030, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, +@@ -825,6 +875,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 0, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6030, ++ .ai_range_code = ai_range_code_6030, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, +@@ -837,6 +888,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 0, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, + .has_8255 = 0, + }, +@@ -850,6 +902,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -865,6 +918,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 100000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_60xx, ++ .ai_range_code = ai_range_code_60xx, + .ao_range_table = &range_bipolar10, + .ao_range_code = ao_range_code_60xx, + .ai_fifo = &ai_fifo_60xx, +@@ -880,6 +934,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 1000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, ++ .ai_range_code = ai_range_code_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -895,6 +950,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 3333, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, ++ .ai_range_code = ai_range_code_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -910,6 +966,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 1000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, ++ .ai_range_code = ai_range_code_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -925,6 +982,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 1000, + .layout = LAYOUT_60XX, + .ai_range_table = &ai_ranges_6052, ++ .ai_range_code = ai_range_code_6052, + .ao_range_table = &ao_ranges_6030, + .ao_range_code = ao_range_code_6030, + .ai_fifo = &ai_fifo_60xx, +@@ -959,6 +1017,7 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, + .ai_range_table = &ai_ranges_64xx, ++ .ai_range_code = ai_range_code_64xx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -970,7 +1029,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 0, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -982,7 +1042,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 0, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -994,7 +1055,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 0, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -1006,7 +1068,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 2, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -1018,7 +1081,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 2, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -1030,7 +1094,8 @@ static const struct pcidas64_board pcidas64_boards[] = { + .ao_nchan = 2, + .ao_scan_speed = 10000, + .layout = LAYOUT_64XX, +- .ai_range_table = &ai_ranges_64xx, ++ .ai_range_table = &ai_ranges_64_mx, ++ .ai_range_code = ai_range_code_64_mx, + .ai_fifo = ai_fifo_64xx, + .has_8255 = 1, + }, +@@ -1127,45 +1192,8 @@ static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev, + unsigned int range_index) + { + const struct pcidas64_board *thisboard = comedi_board(dev); +- const struct comedi_krange *range = +- &thisboard->ai_range_table->range[range_index]; +- unsigned int bits = 0; + +- switch (range->max) { +- case 10000000: +- bits = 0x000; +- break; +- case 5000000: +- bits = 0x100; +- break; +- case 2000000: +- case 2500000: +- bits = 0x200; +- break; +- case 1000000: +- case 1250000: +- bits = 0x300; +- break; +- case 500000: +- bits = 0x400; +- break; +- case 200000: +- case 250000: +- bits = 0x500; +- break; +- case 100000: +- bits = 0x600; +- break; +- case 50000: +- bits = 0x700; +- break; +- default: +- comedi_error(dev, "bug! in ai_range_bits_6xxx"); +- break; +- } +- if (range->min == 0) +- bits += 0x900; +- return bits; ++ return thisboard->ai_range_code[range_index] << 8; + } + + static unsigned int hw_revision(const struct comedi_device *dev, +diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c +index 9ec1df9cff95..be89260c23a6 100644 +--- a/drivers/staging/iio/adc/mxs-lradc.c ++++ b/drivers/staging/iio/adc/mxs-lradc.c +@@ -214,11 +214,17 @@ struct mxs_lradc { + unsigned long is_divided; + + /* +- * Touchscreen LRADC channels receives a private slot in the CTRL4 +- * register, the slot #7. Therefore only 7 slots instead of 8 in the +- * CTRL4 register can be mapped to LRADC channels when using the +- * touchscreen. +- * ++ * When the touchscreen is enabled, we give it two private virtual ++ * channels: #6 and #7. This means that only 6 virtual channels (instead ++ * of 8) will be available for buffered capture. ++ */ ++#define TOUCHSCREEN_VCHANNEL1 7 ++#define TOUCHSCREEN_VCHANNEL2 6 ++#define BUFFER_VCHANS_LIMITED 0x3f ++#define BUFFER_VCHANS_ALL 0xff ++ u8 buffer_vchans; ++ ++ /* + * Furthermore, certain LRADC channels are shared between touchscreen + * and/or touch-buttons and generic LRADC block. Therefore when using + * either of these, these channels are not available for the regular +@@ -342,6 +348,9 @@ struct mxs_lradc { + #define LRADC_CTRL4 0x140 + #define LRADC_CTRL4_LRADCSELECT_MASK(n) (0xf << ((n) * 4)) + #define LRADC_CTRL4_LRADCSELECT_OFFSET(n) ((n) * 4) ++#define LRADC_CTRL4_LRADCSELECT(n, x) \ ++ (((x) << LRADC_CTRL4_LRADCSELECT_OFFSET(n)) & \ ++ LRADC_CTRL4_LRADCSELECT_MASK(n)) + + #define LRADC_RESOLUTION 12 + #define LRADC_SINGLE_SAMPLE_MASK ((1 << LRADC_RESOLUTION) - 1) +@@ -423,6 +432,14 @@ static bool mxs_lradc_check_touch_event(struct mxs_lradc *lradc) + LRADC_STATUS_TOUCH_DETECT_RAW); + } + ++static void mxs_lradc_map_channel(struct mxs_lradc *lradc, unsigned vch, ++ unsigned ch) ++{ ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(vch), ++ LRADC_CTRL4); ++ mxs_lradc_reg_set(lradc, LRADC_CTRL4_LRADCSELECT(vch, ch), LRADC_CTRL4); ++} ++ + static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) + { + /* +@@ -450,12 +467,8 @@ static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) + LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), + LRADC_DELAY(3)); + +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) | +- LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) | +- LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch), LRADC_CTRL1); + +- /* wake us again, when the complete conversion is done */ +- mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1); + /* + * after changing the touchscreen plates setting + * the signals need some initial time to settle. Start the +@@ -508,12 +521,8 @@ static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1, + LRADC_DELAY_DELAY(lradc->over_sample_delay - 1), + LRADC_DELAY(3)); + +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) | +- LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) | +- LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch2), LRADC_CTRL1); + +- /* wake us again, when the conversions are done */ +- mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1); + /* + * after changing the touchscreen plates setting + * the signals need some initial time to settle. Start the +@@ -578,36 +587,6 @@ static unsigned mxs_lradc_read_ts_pressure(struct mxs_lradc *lradc, + #define TS_CH_XM 4 + #define TS_CH_YM 5 + +-static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc) +-{ +- u32 reg; +- int val; +- +- reg = readl(lradc->base + LRADC_CTRL1); +- +- /* only channels 3 to 5 are of interest here */ +- if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YP)) { +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YP) | +- LRADC_CTRL1_LRADC_IRQ(TS_CH_YP), LRADC_CTRL1); +- val = mxs_lradc_read_raw_channel(lradc, TS_CH_YP); +- } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_XM)) { +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_XM) | +- LRADC_CTRL1_LRADC_IRQ(TS_CH_XM), LRADC_CTRL1); +- val = mxs_lradc_read_raw_channel(lradc, TS_CH_XM); +- } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YM)) { +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YM) | +- LRADC_CTRL1_LRADC_IRQ(TS_CH_YM), LRADC_CTRL1); +- val = mxs_lradc_read_raw_channel(lradc, TS_CH_YM); +- } else { +- return -EIO; +- } +- +- mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); +- mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); +- +- return val; +-} +- + /* + * YP(open)--+-------------+ + * | |--+ +@@ -651,7 +630,8 @@ static void mxs_lradc_prepare_x_pos(struct mxs_lradc *lradc) + mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0); + + lradc->cur_plate = LRADC_SAMPLE_X; +- mxs_lradc_setup_ts_channel(lradc, TS_CH_YP); ++ mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YP); ++ mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1); + } + + /* +@@ -672,7 +652,8 @@ static void mxs_lradc_prepare_y_pos(struct mxs_lradc *lradc) + mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0); + + lradc->cur_plate = LRADC_SAMPLE_Y; +- mxs_lradc_setup_ts_channel(lradc, TS_CH_XM); ++ mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_XM); ++ mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1); + } + + /* +@@ -693,7 +674,10 @@ static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc) + mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0); + + lradc->cur_plate = LRADC_SAMPLE_PRESSURE; +- mxs_lradc_setup_ts_pressure(lradc, TS_CH_XP, TS_CH_YM); ++ mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YM); ++ mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL2, TS_CH_XP); ++ mxs_lradc_setup_ts_pressure(lradc, TOUCHSCREEN_VCHANNEL2, ++ TOUCHSCREEN_VCHANNEL1); + } + + static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) +@@ -706,6 +690,19 @@ static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc) + mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); + } + ++static void mxs_lradc_start_touch_event(struct mxs_lradc *lradc) ++{ ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, ++ LRADC_CTRL1); ++ mxs_lradc_reg_set(lradc, ++ LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1); ++ /* ++ * start with the Y-pos, because it uses nearly the same plate ++ * settings like the touch detection ++ */ ++ mxs_lradc_prepare_y_pos(lradc); ++} ++ + static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc) + { + input_report_abs(lradc->ts_input, ABS_X, lradc->ts_x_pos); +@@ -723,10 +720,12 @@ static void mxs_lradc_complete_touch_event(struct mxs_lradc *lradc) + * start a dummy conversion to burn time to settle the signals + * note: we are not interested in the conversion's value + */ +- mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(5)); +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1); +- mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(5), LRADC_CTRL1); +- mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << 5) | ++ mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(TOUCHSCREEN_VCHANNEL1)); ++ mxs_lradc_reg_clear(lradc, ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) | ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1); ++ mxs_lradc_reg_wrt(lradc, ++ LRADC_DELAY_TRIGGER(1 << TOUCHSCREEN_VCHANNEL1) | + LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10), /* waste 5 ms */ + LRADC_DELAY(2)); + } +@@ -758,59 +757,45 @@ static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid) + + /* if it is released, wait for the next touch via IRQ */ + lradc->cur_plate = LRADC_TOUCH; +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1); ++ mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2)); ++ mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3)); ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ | ++ LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) | ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1); + mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1); + } + + /* touchscreen's state machine */ + static void mxs_lradc_handle_touch(struct mxs_lradc *lradc) + { +- int val; +- + switch (lradc->cur_plate) { + case LRADC_TOUCH: +- /* +- * start with the Y-pos, because it uses nearly the same plate +- * settings like the touch detection +- */ +- if (mxs_lradc_check_touch_event(lradc)) { +- mxs_lradc_reg_clear(lradc, +- LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, +- LRADC_CTRL1); +- mxs_lradc_prepare_y_pos(lradc); +- } ++ if (mxs_lradc_check_touch_event(lradc)) ++ mxs_lradc_start_touch_event(lradc); + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, + LRADC_CTRL1); + return; + + case LRADC_SAMPLE_Y: +- val = mxs_lradc_read_ts_channel(lradc); +- if (val < 0) { +- mxs_lradc_enable_touch_detection(lradc); /* re-start */ +- return; +- } +- lradc->ts_y_pos = val; ++ lradc->ts_y_pos = mxs_lradc_read_raw_channel(lradc, ++ TOUCHSCREEN_VCHANNEL1); + mxs_lradc_prepare_x_pos(lradc); + return; + + case LRADC_SAMPLE_X: +- val = mxs_lradc_read_ts_channel(lradc); +- if (val < 0) { +- mxs_lradc_enable_touch_detection(lradc); /* re-start */ +- return; +- } +- lradc->ts_x_pos = val; ++ lradc->ts_x_pos = mxs_lradc_read_raw_channel(lradc, ++ TOUCHSCREEN_VCHANNEL1); + mxs_lradc_prepare_pressure(lradc); + return; + + case LRADC_SAMPLE_PRESSURE: +- lradc->ts_pressure = +- mxs_lradc_read_ts_pressure(lradc, TS_CH_XP, TS_CH_YM); ++ lradc->ts_pressure = mxs_lradc_read_ts_pressure(lradc, ++ TOUCHSCREEN_VCHANNEL2, ++ TOUCHSCREEN_VCHANNEL1); + mxs_lradc_complete_touch_event(lradc); + return; + + case LRADC_SAMPLE_VALID: +- val = mxs_lradc_read_ts_channel(lradc); /* ignore the value */ + mxs_lradc_finish_touch_event(lradc, 1); + break; + } +@@ -842,9 +827,9 @@ static int mxs_lradc_read_single(struct iio_dev *iio_dev, int chan, int *val) + * used if doing raw sampling. + */ + if (lradc->soc == IMX28_LRADC) +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, ++ mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), + LRADC_CTRL1); +- mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); ++ mxs_lradc_reg_clear(lradc, 0x1, LRADC_CTRL0); + + /* Enable / disable the divider per requirement */ + if (test_bit(chan, &lradc->is_divided)) +@@ -1091,9 +1076,8 @@ static void mxs_lradc_disable_ts(struct mxs_lradc *lradc) + { + /* stop all interrupts from firing */ + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN | +- LRADC_CTRL1_LRADC_IRQ_EN(2) | LRADC_CTRL1_LRADC_IRQ_EN(3) | +- LRADC_CTRL1_LRADC_IRQ_EN(4) | LRADC_CTRL1_LRADC_IRQ_EN(5), +- LRADC_CTRL1); ++ LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) | ++ LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1); + + /* Power-down touchscreen touch-detect circuitry. */ + mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0); +@@ -1159,25 +1143,31 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) + struct iio_dev *iio = data; + struct mxs_lradc *lradc = iio_priv(iio); + unsigned long reg = readl(lradc->base + LRADC_CTRL1); ++ uint32_t clr_irq = mxs_lradc_irq_mask(lradc); + const uint32_t ts_irq_mask = + LRADC_CTRL1_TOUCH_DETECT_IRQ | +- LRADC_CTRL1_LRADC_IRQ(2) | +- LRADC_CTRL1_LRADC_IRQ(3) | +- LRADC_CTRL1_LRADC_IRQ(4) | +- LRADC_CTRL1_LRADC_IRQ(5); ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) | ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2); + + if (!(reg & mxs_lradc_irq_mask(lradc))) + return IRQ_NONE; + +- if (lradc->use_touchscreen && (reg & ts_irq_mask)) ++ if (lradc->use_touchscreen && (reg & ts_irq_mask)) { + mxs_lradc_handle_touch(lradc); ++ /* Make sure we don't clear the next conversion's interrupt. */ ++ clr_irq &= ~(LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) | ++ LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2)); ++ } + + if (iio_buffer_enabled(iio)) +- iio_trigger_poll(iio->trig, iio_get_time_ns()); +- else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) ++ if (iio_buffer_enabled(iio)) { ++ if (reg & lradc->buffer_vchans) ++ iio_trigger_poll(iio->trig, iio_get_time_ns()); ++ } else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) { + complete(&lradc->completion); ++ } + +- mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc), LRADC_CTRL1); ++ mxs_lradc_reg_clear(lradc, reg & clr_irq, LRADC_CTRL1); + + return IRQ_HANDLED; + } +@@ -1288,9 +1278,10 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio) + } + + if (lradc->soc == IMX28_LRADC) +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, +- LRADC_CTRL1); +- mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); ++ mxs_lradc_reg_clear(lradc, ++ lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET, ++ LRADC_CTRL1); ++ mxs_lradc_reg_clear(lradc, lradc->buffer_vchans, LRADC_CTRL0); + + for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) { + ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs); +@@ -1323,10 +1314,11 @@ static int mxs_lradc_buffer_postdisable(struct iio_dev *iio) + mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK | + LRADC_DELAY_KICK, LRADC_DELAY(0)); + +- mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0); ++ mxs_lradc_reg_clear(lradc, lradc->buffer_vchans, LRADC_CTRL0); + if (lradc->soc == IMX28_LRADC) +- mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK, +- LRADC_CTRL1); ++ mxs_lradc_reg_clear(lradc, ++ lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET, ++ LRADC_CTRL1); + + kfree(lradc->buffer); + mutex_unlock(&lradc->lock); +@@ -1352,7 +1344,7 @@ static bool mxs_lradc_validate_scan_mask(struct iio_dev *iio, + if (lradc->use_touchbutton) + rsvd_chans++; + if (lradc->use_touchscreen) +- rsvd_chans++; ++ rsvd_chans += 2; + + /* Test for attempts to map channels with special mode of operation. */ + if (bitmap_intersects(mask, &rsvd_mask, LRADC_MAX_TOTAL_CHANS)) +@@ -1412,6 +1404,13 @@ static const struct iio_chan_spec mxs_lradc_chan_spec[] = { + .channel = 8, + .scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,}, + }, ++ /* Hidden channel to keep indexes */ ++ { ++ .type = IIO_TEMP, ++ .indexed = 1, ++ .scan_index = -1, ++ .channel = 9, ++ }, + MXS_ADC_CHAN(10, IIO_VOLTAGE), /* VDDIO */ + MXS_ADC_CHAN(11, IIO_VOLTAGE), /* VTH */ + MXS_ADC_CHAN(12, IIO_VOLTAGE), /* VDDA */ +@@ -1563,6 +1562,11 @@ static int mxs_lradc_probe(struct platform_device *pdev) + + touch_ret = mxs_lradc_probe_touchscreen(lradc, node); + ++ if (touch_ret == 0) ++ lradc->buffer_vchans = BUFFER_VCHANS_LIMITED; ++ else ++ lradc->buffer_vchans = BUFFER_VCHANS_ALL; ++ + /* Grab all IRQ sources */ + for (i = 0; i < of_cfg->irq_count; i++) { + lradc->irq[i] = platform_get_irq(pdev, i); +diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c +index 1205dbd4f83d..0fccdcfd1015 100644 +--- a/drivers/target/target_core_pr.c ++++ b/drivers/target/target_core_pr.c +@@ -1877,8 +1877,8 @@ static int core_scsi3_update_aptpl_buf( + } + + if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { +- pr_err("Unable to update renaming" +- " APTPL metadata\n"); ++ pr_err("Unable to update renaming APTPL metadata," ++ " reallocating larger buffer\n"); + ret = -EMSGSIZE; + goto out; + } +@@ -1895,8 +1895,8 @@ static int core_scsi3_update_aptpl_buf( + lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count); + + if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { +- pr_err("Unable to update renaming" +- " APTPL metadata\n"); ++ pr_err("Unable to update renaming APTPL metadata," ++ " reallocating larger buffer\n"); + ret = -EMSGSIZE; + goto out; + } +@@ -1959,7 +1959,7 @@ static int __core_scsi3_write_aptpl_to_file( + static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, bool aptpl) + { + unsigned char *buf; +- int rc; ++ int rc, len = PR_APTPL_BUF_LEN; + + if (!aptpl) { + char *null_buf = "No Registrations or Reservations\n"; +@@ -1973,25 +1973,26 @@ static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, b + + return 0; + } +- +- buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL); ++retry: ++ buf = vzalloc(len); + if (!buf) + return TCM_OUT_OF_RESOURCES; + +- rc = core_scsi3_update_aptpl_buf(dev, buf, PR_APTPL_BUF_LEN); ++ rc = core_scsi3_update_aptpl_buf(dev, buf, len); + if (rc < 0) { +- kfree(buf); +- return TCM_OUT_OF_RESOURCES; ++ vfree(buf); ++ len *= 2; ++ goto retry; + } + + rc = __core_scsi3_write_aptpl_to_file(dev, buf); + if (rc != 0) { + pr_err("SPC-3 PR: Could not update APTPL\n"); +- kfree(buf); ++ vfree(buf); + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + dev->t10_pr.pr_aptpl_active = 1; +- kfree(buf); ++ vfree(buf); + pr_debug("SPC-3 PR: Set APTPL Bit Activated\n"); + return 0; + } +diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c +index 5216acd68b4b..68511e83486b 100644 +--- a/drivers/target/target_core_sbc.c ++++ b/drivers/target/target_core_sbc.c +@@ -266,6 +266,8 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb) + static sense_reason_t + sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops) + { ++ struct se_device *dev = cmd->se_dev; ++ sector_t end_lba = dev->transport->get_blocks(dev) + 1; + unsigned int sectors = sbc_get_write_same_sectors(cmd); + + if ((flags[0] & 0x04) || (flags[0] & 0x02)) { +@@ -279,6 +281,16 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o + sectors, cmd->se_dev->dev_attrib.max_write_same_len); + return TCM_INVALID_CDB_FIELD; + } ++ /* ++ * Sanity check for LBA wrap and request past end of device. ++ */ ++ if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) || ++ ((cmd->t_task_lba + sectors) > end_lba)) { ++ pr_err("WRITE_SAME exceeds last lba %llu (lba %llu, sectors %u)\n", ++ (unsigned long long)end_lba, cmd->t_task_lba, sectors); ++ return TCM_ADDRESS_OUT_OF_RANGE; ++ } ++ + /* We always have ANC_SUP == 0 so setting ANCHOR is always an error */ + if (flags[0] & 0x10) { + pr_warn("WRITE SAME with ANCHOR not supported\n"); +@@ -911,7 +923,8 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) + unsigned long long end_lba; + + end_lba = dev->transport->get_blocks(dev) + 1; +- if (cmd->t_task_lba + sectors > end_lba) { ++ if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) || ++ ((cmd->t_task_lba + sectors) > end_lba)) { + pr_err("cmd exceeds last lba %llu " + "(lba %llu, sectors %u)\n", + end_lba, cmd->t_task_lba, sectors); +diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c +index 25d07412e08e..39988fa91294 100644 +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -996,8 +996,8 @@ EXPORT_SYMBOL(start_tty); + /* We limit tty time update visibility to every 8 seconds or so. */ + static void tty_update_time(struct timespec *time) + { +- unsigned long sec = get_seconds() & ~7; +- if ((long)(sec - time->tv_sec) > 0) ++ unsigned long sec = get_seconds(); ++ if (abs(sec - time->tv_sec) & ~7) + time->tv_sec = sec; + } + +diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c +index 6fd60fece6b4..22da05d27009 100644 +--- a/drivers/tty/tty_ioctl.c ++++ b/drivers/tty/tty_ioctl.c +@@ -217,11 +217,17 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout) + #endif + if (!timeout) + timeout = MAX_SCHEDULE_TIMEOUT; ++ + if (wait_event_interruptible_timeout(tty->write_wait, +- !tty_chars_in_buffer(tty), timeout) >= 0) { +- if (tty->ops->wait_until_sent) +- tty->ops->wait_until_sent(tty, timeout); ++ !tty_chars_in_buffer(tty), timeout) < 0) { ++ return; + } ++ ++ if (timeout == MAX_SCHEDULE_TIMEOUT) ++ timeout = 0; ++ ++ if (tty->ops->wait_until_sent) ++ tty->ops->wait_until_sent(tty, timeout); + } + EXPORT_SYMBOL(tty_wait_until_sent); + +diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c +index 9ca77166d37e..45b7b96f9ed3 100644 +--- a/drivers/usb/core/devio.c ++++ b/drivers/usb/core/devio.c +@@ -501,6 +501,7 @@ static void async_completed(struct urb *urb) + as->status = urb->status; + signr = as->signr; + if (signr) { ++ memset(&sinfo, 0, sizeof(sinfo)); + sinfo.si_signo = as->signr; + sinfo.si_errno = as->status; + sinfo.si_code = SI_ASYNCIO; +@@ -2227,6 +2228,7 @@ static void usbdev_remove(struct usb_device *udev) + wake_up_all(&ps->wait); + list_del_init(&ps->list); + if (ps->discsignr) { ++ memset(&sinfo, 0, sizeof(sinfo)); + sinfo.si_signo = ps->discsignr; + sinfo.si_errno = EPIPE; + sinfo.si_code = SI_ASYNCIO; +diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c +index 2a6841c95b64..cfca302d3d88 100644 +--- a/drivers/usb/dwc3/dwc3-omap.c ++++ b/drivers/usb/dwc3/dwc3-omap.c +@@ -211,6 +211,18 @@ static void dwc3_omap_write_irq0_set(struct dwc3_omap *omap, u32 value) + omap->irq0_offset, value); + } + ++static void dwc3_omap_write_irqmisc_clr(struct dwc3_omap *omap, u32 value) ++{ ++ dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_CLR_MISC + ++ omap->irqmisc_offset, value); ++} ++ ++static void dwc3_omap_write_irq0_clr(struct dwc3_omap *omap, u32 value) ++{ ++ dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_CLR_0 - ++ omap->irq0_offset, value); ++} ++ + static void dwc3_omap_set_mailbox(struct dwc3_omap *omap, + enum omap_dwc3_vbus_id_status status) + { +@@ -351,9 +363,23 @@ static void dwc3_omap_enable_irqs(struct dwc3_omap *omap) + + static void dwc3_omap_disable_irqs(struct dwc3_omap *omap) + { ++ u32 reg; ++ + /* disable all IRQs */ +- dwc3_omap_write_irqmisc_set(omap, 0x00); +- dwc3_omap_write_irq0_set(omap, 0x00); ++ reg = USBOTGSS_IRQO_COREIRQ_ST; ++ dwc3_omap_write_irq0_clr(omap, reg); ++ ++ reg = (USBOTGSS_IRQMISC_OEVT | ++ USBOTGSS_IRQMISC_DRVVBUS_RISE | ++ USBOTGSS_IRQMISC_CHRGVBUS_RISE | ++ USBOTGSS_IRQMISC_DISCHRGVBUS_RISE | ++ USBOTGSS_IRQMISC_IDPULLUP_RISE | ++ USBOTGSS_IRQMISC_DRVVBUS_FALL | ++ USBOTGSS_IRQMISC_CHRGVBUS_FALL | ++ USBOTGSS_IRQMISC_DISCHRGVBUS_FALL | ++ USBOTGSS_IRQMISC_IDPULLUP_FALL); ++ ++ dwc3_omap_write_irqmisc_clr(omap, reg); + } + + static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32); +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index faa8b98954d9..a95eee8ddc38 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -2133,7 +2133,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, + if (event_trb != ep_ring->dequeue) { + /* The event was for the status stage */ + if (event_trb == td->last_trb) { +- if (td->urb->actual_length != 0) { ++ if (td->urb_length_set) { + /* Don't overwrite a previously set error code + */ + if ((*status == -EINPROGRESS || *status == 0) && +@@ -2147,7 +2147,13 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, + td->urb->transfer_buffer_length; + } + } else { +- /* Maybe the event was for the data stage? */ ++ /* ++ * Maybe the event was for the data stage? If so, update ++ * already the actual_length of the URB and flag it as ++ * set, so that it is not overwritten in the event for ++ * the last TRB. ++ */ ++ td->urb_length_set = true; + td->urb->actual_length = + td->urb->transfer_buffer_length - + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 96e9e780ccae..7225dd242bfa 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1,3 +1,4 @@ ++ + /* + * xHCI host controller driver + * +@@ -88,9 +89,10 @@ struct xhci_cap_regs { + #define HCS_IST(p) (((p) >> 0) & 0xf) + /* bits 4:7, max number of Event Ring segments */ + #define HCS_ERST_MAX(p) (((p) >> 4) & 0xf) ++/* bits 21:25 Hi 5 bits of Scratchpad buffers SW must allocate for the HW */ + /* bit 26 Scratchpad restore - for save/restore HW state - not used yet */ +-/* bits 27:31 number of Scratchpad buffers SW must allocate for the HW */ +-#define HCS_MAX_SCRATCHPAD(p) (((p) >> 27) & 0x1f) ++/* bits 27:31 Lo 5 bits of Scratchpad buffers SW must allocate for the HW */ ++#define HCS_MAX_SCRATCHPAD(p) ((((p) >> 16) & 0x3e0) | (((p) >> 27) & 0x1f)) + + /* HCSPARAMS3 - hcs_params3 - bitmasks */ + /* bits 0:7, Max U1 to U0 latency for the roothub ports */ +@@ -1289,6 +1291,8 @@ struct xhci_td { + struct xhci_segment *start_seg; + union xhci_trb *first_trb; + union xhci_trb *last_trb; ++ /* actual_length of the URB has already been set */ ++ bool urb_length_set; + }; + + /* xHCI command default timeout value */ +diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c +index 9374bd2aba20..6f91eb9ae81a 100644 +--- a/drivers/usb/serial/bus.c ++++ b/drivers/usb/serial/bus.c +@@ -51,6 +51,7 @@ static int usb_serial_device_probe(struct device *dev) + { + struct usb_serial_driver *driver; + struct usb_serial_port *port; ++ struct device *tty_dev; + int retval = 0; + int minor; + +@@ -75,12 +76,20 @@ static int usb_serial_device_probe(struct device *dev) + retval = device_create_file(dev, &dev_attr_port_number); + if (retval) { + if (driver->port_remove) +- retval = driver->port_remove(port); ++ driver->port_remove(port); + goto exit_with_autopm; + } + + minor = port->minor; +- tty_register_device(usb_serial_tty_driver, minor, dev); ++ tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev); ++ if (IS_ERR(tty_dev)) { ++ retval = PTR_ERR(tty_dev); ++ device_remove_file(dev, &dev_attr_port_number); ++ if (driver->port_remove) ++ driver->port_remove(port); ++ goto exit_with_autopm; ++ } ++ + dev_info(&port->serial->dev->dev, + "%s converter now attached to ttyUSB%d\n", + driver->description, minor); +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index a2d040971afe..8d114b9733ed 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -147,6 +147,8 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x166A, 0x0305) }, /* Clipsal C-5000CT2 C-Bus Spectrum Colour Touchscreen */ + { USB_DEVICE(0x166A, 0x0401) }, /* Clipsal L51xx C-Bus Architectural Dimmer */ + { USB_DEVICE(0x166A, 0x0101) }, /* Clipsal 5560884 C-Bus Multi-room Audio Matrix Switcher */ ++ { USB_DEVICE(0x16C0, 0x09B0) }, /* Lunatico Seletek */ ++ { USB_DEVICE(0x16C0, 0x09B1) }, /* Lunatico Seletek */ + { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ + { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */ + { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index debcdef4cbf0..923500595357 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -812,6 +812,8 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) }, ++ { USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID), ++ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID), +@@ -991,6 +993,23 @@ static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) }, + /* GE Healthcare devices */ + { USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) }, ++ /* Active Research (Actisense) devices */ ++ { USB_DEVICE(FTDI_VID, ACTISENSE_NDC_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_USG_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_NGT_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_NGW_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_D9AC_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_D9AD_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_D9AE_PID) }, ++ { USB_DEVICE(FTDI_VID, ACTISENSE_D9AF_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEAGAUGE_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASWITCH_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_NMEA2000_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ETHERNET_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_WIFI_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) }, ++ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) }, + { } /* Terminating entry */ + }; + +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index e52409c9be99..56b1b55c4751 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -38,6 +38,9 @@ + + #define FTDI_LUMEL_PD12_PID 0x6002 + ++/* Cyber Cortex AV by Fabulous Silicon (http://fabuloussilicon.com) */ ++#define CYBER_CORTEX_AV_PID 0x8698 ++ + /* + * Marvell OpenRD Base, Client + * http://www.open-rd.org +@@ -1438,3 +1441,23 @@ + */ + #define GE_HEALTHCARE_VID 0x1901 + #define GE_HEALTHCARE_NEMO_TRACKER_PID 0x0015 ++ ++/* ++ * Active Research (Actisense) devices ++ */ ++#define ACTISENSE_NDC_PID 0xD9A8 /* NDC USB Serial Adapter */ ++#define ACTISENSE_USG_PID 0xD9A9 /* USG USB Serial Adapter */ ++#define ACTISENSE_NGT_PID 0xD9AA /* NGT NMEA2000 Interface */ ++#define ACTISENSE_NGW_PID 0xD9AB /* NGW NMEA2000 Gateway */ ++#define ACTISENSE_D9AC_PID 0xD9AC /* Actisense Reserved */ ++#define ACTISENSE_D9AD_PID 0xD9AD /* Actisense Reserved */ ++#define ACTISENSE_D9AE_PID 0xD9AE /* Actisense Reserved */ ++#define ACTISENSE_D9AF_PID 0xD9AF /* Actisense Reserved */ ++#define CHETCO_SEAGAUGE_PID 0xA548 /* SeaGauge USB Adapter */ ++#define CHETCO_SEASWITCH_PID 0xA549 /* SeaSwitch USB Adapter */ ++#define CHETCO_SEASMART_NMEA2000_PID 0xA54A /* SeaSmart NMEA2000 Gateway */ ++#define CHETCO_SEASMART_ETHERNET_PID 0xA54B /* SeaSmart Ethernet Gateway */ ++#define CHETCO_SEASMART_WIFI_PID 0xA5AC /* SeaSmart Wifi Gateway */ ++#define CHETCO_SEASMART_DISPLAY_PID 0xA5AD /* SeaSmart NMEA2000 Display */ ++#define CHETCO_SEASMART_LITE_PID 0xA5AE /* SeaSmart Lite USB Adapter */ ++#define CHETCO_SEASMART_ANALOG_PID 0xA5AF /* SeaSmart Analog Adapter */ +diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c +index b63ce023f96f..d6a197917ebd 100644 +--- a/drivers/usb/serial/generic.c ++++ b/drivers/usb/serial/generic.c +@@ -258,7 +258,8 @@ void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout) + * character or at least one jiffy. + */ + period = max_t(unsigned long, (10 * HZ / bps), 1); +- period = min_t(unsigned long, period, timeout); ++ if (timeout) ++ period = min_t(unsigned long, period, timeout); + + dev_dbg(&port->dev, "%s - timeout = %u ms, period = %u ms\n", + __func__, jiffies_to_msecs(timeout), +@@ -268,7 +269,7 @@ void usb_serial_generic_wait_until_sent(struct tty_struct *tty, long timeout) + schedule_timeout_interruptible(period); + if (signal_pending(current)) + break; +- if (time_after(jiffies, expire)) ++ if (timeout && time_after(jiffies, expire)) + break; + } + } +diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c +index ab1d690274ae..460a40669967 100644 +--- a/drivers/usb/serial/mxuport.c ++++ b/drivers/usb/serial/mxuport.c +@@ -1284,7 +1284,8 @@ static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port) + } + + /* Initial port termios */ +- mxuport_set_termios(tty, port, NULL); ++ if (tty) ++ mxuport_set_termios(tty, port, NULL); + + /* + * TODO: use RQ_VENDOR_GET_MSR, once we know what it +diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c +index 3182c0e68b42..e3399dc2453b 100644 +--- a/fs/autofs4/dev-ioctl.c ++++ b/fs/autofs4/dev-ioctl.c +@@ -95,7 +95,7 @@ static int check_dev_ioctl_version(int cmd, struct autofs_dev_ioctl *param) + */ + static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *in) + { +- struct autofs_dev_ioctl tmp; ++ struct autofs_dev_ioctl tmp, *res; + + if (copy_from_user(&tmp, in, sizeof(tmp))) + return ERR_PTR(-EFAULT); +@@ -103,7 +103,11 @@ static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *i + if (tmp.size < sizeof(tmp)) + return ERR_PTR(-EINVAL); + +- return memdup_user(in, tmp.size); ++ res = memdup_user(in, tmp.size); ++ if (!IS_ERR(res)) ++ res->size = tmp.size; ++ ++ return res; + } + + static inline void free_dev_ioctl(struct autofs_dev_ioctl *param) +diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c +index 279b06ef5522..0a841ddd6843 100644 +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -1774,22 +1774,10 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, + mutex_unlock(&inode->i_mutex); + + /* +- * we want to make sure fsync finds this change +- * but we haven't joined a transaction running right now. +- * +- * Later on, someone is sure to update the inode and get the +- * real transid recorded. +- * +- * We set last_trans now to the fs_info generation + 1, +- * this will either be one more than the running transaction +- * or the generation used for the next transaction if there isn't +- * one running right now. +- * + * We also have to set last_sub_trans to the current log transid, + * otherwise subsequent syncs to a file that's been synced in this + * transaction will appear to have already occured. + */ +- BTRFS_I(inode)->last_trans = root->fs_info->generation + 1; + BTRFS_I(inode)->last_sub_trans = root->log_transid; + if (num_written > 0) { + err = generic_write_sync(file, pos, num_written); +@@ -1892,25 +1880,37 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) + atomic_inc(&root->log_batch); + + /* +- * check the transaction that last modified this inode +- * and see if its already been committed +- */ +- if (!BTRFS_I(inode)->last_trans) { +- mutex_unlock(&inode->i_mutex); +- goto out; +- } +- +- /* +- * if the last transaction that changed this file was before +- * the current transaction, we can bail out now without any +- * syncing ++ * If the last transaction that changed this file was before the current ++ * transaction and we have the full sync flag set in our inode, we can ++ * bail out now without any syncing. ++ * ++ * Note that we can't bail out if the full sync flag isn't set. This is ++ * because when the full sync flag is set we start all ordered extents ++ * and wait for them to fully complete - when they complete they update ++ * the inode's last_trans field through: ++ * ++ * btrfs_finish_ordered_io() -> ++ * btrfs_update_inode_fallback() -> ++ * btrfs_update_inode() -> ++ * btrfs_set_inode_last_trans() ++ * ++ * So we are sure that last_trans is up to date and can do this check to ++ * bail out safely. For the fast path, when the full sync flag is not ++ * set in our inode, we can not do it because we start only our ordered ++ * extents and don't wait for them to complete (that is when ++ * btrfs_finish_ordered_io runs), so here at this point their last_trans ++ * value might be less than or equals to fs_info->last_trans_committed, ++ * and setting a speculative last_trans for an inode when a buffered ++ * write is made (such as fs_info->generation + 1 for example) would not ++ * be reliable since after setting the value and before fsync is called ++ * any number of transactions can start and commit (transaction kthread ++ * commits the current transaction periodically), and a transaction ++ * commit does not start nor waits for ordered extents to complete. + */ + smp_mb(); + if (btrfs_inode_in_log(inode, root->fs_info->generation) || +- BTRFS_I(inode)->last_trans <= +- root->fs_info->last_trans_committed) { +- BTRFS_I(inode)->last_trans = 0; +- ++ (full_sync && BTRFS_I(inode)->last_trans <= ++ root->fs_info->last_trans_committed)) { + /* + * We'v had everything committed since the last time we were + * modified so clear this flag in case it was set for whatever +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index d68a7250f00b..653cdd85e0f2 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -6870,7 +6870,6 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock, + ((BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) && + em->block_start != EXTENT_MAP_HOLE)) { + int type; +- int ret; + u64 block_start, orig_start, orig_block_len, ram_bytes; + + if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index aeb57b98c53f..a7f32bfdd5e7 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -979,7 +979,7 @@ again: + base = btrfs_item_ptr_offset(leaf, path->slots[0]); + + while (cur_offset < item_size) { +- extref = (struct btrfs_inode_extref *)base + cur_offset; ++ extref = (struct btrfs_inode_extref *)(base + cur_offset); + + victim_name_len = btrfs_inode_extref_name_len(leaf, extref); + +diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c +index 15761957cc3f..1ff8fe5dab0d 100644 +--- a/fs/debugfs/inode.c ++++ b/fs/debugfs/inode.c +@@ -245,10 +245,19 @@ static int debugfs_show_options(struct seq_file *m, struct dentry *root) + return 0; + } + ++static void debugfs_evict_inode(struct inode *inode) ++{ ++ truncate_inode_pages(&inode->i_data, 0); ++ clear_inode(inode); ++ if (S_ISLNK(inode->i_mode)) ++ kfree(inode->i_private); ++} ++ + static const struct super_operations debugfs_super_operations = { + .statfs = simple_statfs, + .remount_fs = debugfs_remount, + .show_options = debugfs_show_options, ++ .evict_inode = debugfs_evict_inode, + }; + + static int debug_fill_super(struct super_block *sb, void *data, int silent) +@@ -465,23 +474,14 @@ static int __debugfs_remove(struct dentry *dentry, struct dentry *parent) + int ret = 0; + + if (debugfs_positive(dentry)) { +- if (dentry->d_inode) { +- dget(dentry); +- switch (dentry->d_inode->i_mode & S_IFMT) { +- case S_IFDIR: +- ret = simple_rmdir(parent->d_inode, dentry); +- break; +- case S_IFLNK: +- kfree(dentry->d_inode->i_private); +- /* fall through */ +- default: +- simple_unlink(parent->d_inode, dentry); +- break; +- } +- if (!ret) +- d_delete(dentry); +- dput(dentry); +- } ++ dget(dentry); ++ if (S_ISDIR(dentry->d_inode->i_mode)) ++ ret = simple_rmdir(parent->d_inode, dentry); ++ else ++ simple_unlink(parent->d_inode, dentry); ++ if (!ret) ++ d_delete(dentry); ++ dput(dentry); + } + return ret; + } +diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c +index 3ed1be9aade3..2ea3537b8bde 100644 +--- a/fs/nfs/delegation.c ++++ b/fs/nfs/delegation.c +@@ -161,8 +161,8 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, + &delegation->flags); + NFS_I(inode)->delegation_state = delegation->type; + spin_unlock(&delegation->lock); +- put_rpccred(oldcred); + rcu_read_unlock(); ++ put_rpccred(oldcred); + trace_nfs4_reclaim_delegation(inode, res->delegation_type); + } else { + /* We appear to have raced with a delegation return. */ +diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c +index b2e3ff347620..ecdbae19a766 100644 +--- a/fs/nilfs2/btree.c ++++ b/fs/nilfs2/btree.c +@@ -31,6 +31,8 @@ + #include "alloc.h" + #include "dat.h" + ++static void __nilfs_btree_init(struct nilfs_bmap *bmap); ++ + static struct nilfs_btree_path *nilfs_btree_alloc_path(void) + { + struct nilfs_btree_path *path; +@@ -368,6 +370,34 @@ static int nilfs_btree_node_broken(const struct nilfs_btree_node *node, + return ret; + } + ++/** ++ * nilfs_btree_root_broken - verify consistency of btree root node ++ * @node: btree root node to be examined ++ * @ino: inode number ++ * ++ * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned. ++ */ ++static int nilfs_btree_root_broken(const struct nilfs_btree_node *node, ++ unsigned long ino) ++{ ++ int level, flags, nchildren; ++ int ret = 0; ++ ++ level = nilfs_btree_node_get_level(node); ++ flags = nilfs_btree_node_get_flags(node); ++ nchildren = nilfs_btree_node_get_nchildren(node); ++ ++ if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN || ++ level > NILFS_BTREE_LEVEL_MAX || ++ nchildren < 0 || ++ nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) { ++ pr_crit("NILFS: bad btree root (inode number=%lu): level = %d, flags = 0x%x, nchildren = %d\n", ++ ino, level, flags, nchildren); ++ ret = 1; ++ } ++ return ret; ++} ++ + int nilfs_btree_broken_node_block(struct buffer_head *bh) + { + int ret; +@@ -1713,7 +1743,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *btree, + + /* convert and insert */ + dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL; +- nilfs_btree_init(btree); ++ __nilfs_btree_init(btree); + if (nreq != NULL) { + nilfs_bmap_commit_alloc_ptr(btree, dreq, dat); + nilfs_bmap_commit_alloc_ptr(btree, nreq, dat); +@@ -2294,12 +2324,23 @@ static const struct nilfs_bmap_operations nilfs_btree_ops_gc = { + .bop_gather_data = NULL, + }; + +-int nilfs_btree_init(struct nilfs_bmap *bmap) ++static void __nilfs_btree_init(struct nilfs_bmap *bmap) + { + bmap->b_ops = &nilfs_btree_ops; + bmap->b_nchildren_per_block = + NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap)); +- return 0; ++} ++ ++int nilfs_btree_init(struct nilfs_bmap *bmap) ++{ ++ int ret = 0; ++ ++ __nilfs_btree_init(bmap); ++ ++ if (nilfs_btree_root_broken(nilfs_btree_get_root(bmap), ++ bmap->b_inode->i_ino)) ++ ret = -EIO; ++ return ret; + } + + void nilfs_btree_init_gc(struct nilfs_bmap *bmap) +diff --git a/fs/proc/generic.c b/fs/proc/generic.c +index b7f268eb5f45..2e2d9d5d78d9 100644 +--- a/fs/proc/generic.c ++++ b/fs/proc/generic.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -162,17 +161,6 @@ void proc_free_inum(unsigned int inum) + spin_unlock_irqrestore(&proc_inum_lock, flags); + } + +-static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd) +-{ +- nd_set_link(nd, __PDE_DATA(dentry->d_inode)); +- return NULL; +-} +- +-static const struct inode_operations proc_link_inode_operations = { +- .readlink = generic_readlink, +- .follow_link = proc_follow_link, +-}; +- + /* + * Don't create negative dentries here, return -ENOENT by hand + * instead. +diff --git a/fs/proc/inode.c b/fs/proc/inode.c +index 124fc43c7090..2f2815f3176e 100644 +--- a/fs/proc/inode.c ++++ b/fs/proc/inode.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + #include + +@@ -401,6 +402,26 @@ static const struct file_operations proc_reg_file_ops_no_compat = { + }; + #endif + ++static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd) ++{ ++ struct proc_dir_entry *pde = PDE(dentry->d_inode); ++ if (unlikely(!use_pde(pde))) ++ return ERR_PTR(-EINVAL); ++ nd_set_link(nd, pde->data); ++ return pde; ++} ++ ++static void proc_put_link(struct dentry *dentry, struct nameidata *nd, void *p) ++{ ++ unuse_pde(p); ++} ++ ++const struct inode_operations proc_link_inode_operations = { ++ .readlink = generic_readlink, ++ .follow_link = proc_follow_link, ++ .put_link = proc_put_link, ++}; ++ + struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) + { + struct inode *inode = new_inode_pseudo(sb); +diff --git a/fs/proc/internal.h b/fs/proc/internal.h +index 651d09a11dde..8b8ca1db6316 100644 +--- a/fs/proc/internal.h ++++ b/fs/proc/internal.h +@@ -202,6 +202,7 @@ struct pde_opener { + int closing; + struct completion *c; + }; ++extern const struct inode_operations proc_link_inode_operations; + + extern const struct inode_operations proc_pid_link_inode_operations; + +diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h +index 1772fadcff62..349325404add 100644 +--- a/include/target/target_core_base.h ++++ b/include/target/target_core_base.h +@@ -407,7 +407,7 @@ struct t10_reservation { + /* Activate Persistence across Target Power Loss enabled + * for SCSI device */ + int pr_aptpl_active; +-#define PR_APTPL_BUF_LEN 8192 ++#define PR_APTPL_BUF_LEN 262144 + u32 pr_generation; + spinlock_t registration_lock; + spinlock_t aptpl_reg_lock; +diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h +index aece1346ceb7..4ad10baecd4d 100644 +--- a/include/trace/events/kmem.h ++++ b/include/trace/events/kmem.h +@@ -268,11 +268,11 @@ TRACE_EVENT(mm_page_alloc_extfrag, + + TP_PROTO(struct page *page, + int alloc_order, int fallback_order, +- int alloc_migratetype, int fallback_migratetype, int new_migratetype), ++ int alloc_migratetype, int fallback_migratetype), + + TP_ARGS(page, + alloc_order, fallback_order, +- alloc_migratetype, fallback_migratetype, new_migratetype), ++ alloc_migratetype, fallback_migratetype), + + TP_STRUCT__entry( + __field( struct page *, page ) +@@ -289,7 +289,8 @@ TRACE_EVENT(mm_page_alloc_extfrag, + __entry->fallback_order = fallback_order; + __entry->alloc_migratetype = alloc_migratetype; + __entry->fallback_migratetype = fallback_migratetype; +- __entry->change_ownership = (new_migratetype == alloc_migratetype); ++ __entry->change_ownership = (alloc_migratetype == ++ get_pageblock_migratetype(page)); + ), + + TP_printk("page=%p pfn=%lu alloc_order=%d fallback_order=%d pageblock_order=%d alloc_migratetype=%d fallback_migratetype=%d fragmenting=%d change_ownership=%d", +diff --git a/mm/compaction.c b/mm/compaction.c +index 4229fc22a477..a522208bb8ea 100644 +--- a/mm/compaction.c ++++ b/mm/compaction.c +@@ -937,7 +937,7 @@ static int compact_finished(struct zone *zone, + return COMPACT_PARTIAL; + + /* Job done if allocation would set block type */ +- if (cc->order >= pageblock_order && area->nr_free) ++ if (order >= pageblock_order && area->nr_free) + return COMPACT_PARTIAL; + } + +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 472259b00618..c3e8660cb616 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -2488,9 +2488,10 @@ again: + goto unlock; + + /* +- * HWPoisoned hugepage is already unmapped and dropped reference ++ * Migrating hugepage or HWPoisoned hugepage is already ++ * unmapped and its refcount is dropped, so just clear pte here. + */ +- if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) { ++ if (unlikely(!pte_present(pte))) { + huge_pte_clear(mm, address, ptep); + goto unlock; + } +@@ -3163,7 +3164,26 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma, + spin_unlock(ptl); + continue; + } +- if (!huge_pte_none(huge_ptep_get(ptep))) { ++ pte = huge_ptep_get(ptep); ++ if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) { ++ spin_unlock(ptl); ++ continue; ++ } ++ if (unlikely(is_hugetlb_entry_migration(pte))) { ++ swp_entry_t entry = pte_to_swp_entry(pte); ++ ++ if (is_write_migration_entry(entry)) { ++ pte_t newpte; ++ ++ make_migration_entry_read(&entry); ++ newpte = swp_entry_to_pte(entry); ++ set_huge_pte_at(mm, address, ptep, newpte); ++ pages++; ++ } ++ spin_unlock(ptl); ++ continue; ++ } ++ if (!huge_pte_none(pte)) { + pte = huge_ptep_get_and_clear(mm, address, ptep); + pte = pte_mkhuge(huge_pte_modify(pte, newprot)); + pte = arch_make_huge_pte(pte, vma, NULL, 0); +diff --git a/mm/memory.c b/mm/memory.c +index 7f30beaba74f..102af096cbc5 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -4024,7 +4024,7 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr, + if (follow_phys(vma, addr, write, &prot, &phys_addr)) + return -EINVAL; + +- maddr = ioremap_prot(phys_addr, PAGE_SIZE, prot); ++ maddr = ioremap_prot(phys_addr, PAGE_ALIGN(len + offset), prot); + if (write) + memcpy_toio(maddr + offset, buf, len); + else +diff --git a/mm/mmap.c b/mm/mmap.c +index 085bcd890ad2..d4c97ba6843b 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -129,7 +129,7 @@ EXPORT_SYMBOL_GPL(vm_memory_committed); + */ + int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) + { +- unsigned long free, allowed, reserve; ++ long free, allowed, reserve; + + vm_acct_memory(pages); + +@@ -193,7 +193,7 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) + */ + if (mm) { + reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10); +- allowed -= min(mm->total_vm / 32, reserve); ++ allowed -= min_t(long, mm->total_vm / 32, reserve); + } + + if (percpu_counter_read_positive(&vm_committed_as) < allowed) +diff --git a/mm/nommu.c b/mm/nommu.c +index 3ee4f74fbfbe..76b3f90ada7b 100644 +--- a/mm/nommu.c ++++ b/mm/nommu.c +@@ -1905,7 +1905,7 @@ EXPORT_SYMBOL(unmap_mapping_range); + */ + int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) + { +- unsigned long free, allowed, reserve; ++ long free, allowed, reserve; + + vm_acct_memory(pages); + +@@ -1969,7 +1969,7 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) + */ + if (mm) { + reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10); +- allowed -= min(mm->total_vm / 32, reserve); ++ allowed -= min_t(long, mm->total_vm / 32, reserve); + } + + if (percpu_counter_read_positive(&vm_committed_as) < allowed) +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index ea419137f845..0479732f6b02 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -1081,8 +1081,8 @@ static void change_pageblock_range(struct page *pageblock_page, + * nor move CMA pages to different free lists. We don't want unmovable pages + * to be allocated from MIGRATE_CMA areas. + * +- * Returns the new migratetype of the pageblock (or the same old migratetype +- * if it was unchanged). ++ * Returns the allocation migratetype if free pages were stolen, or the ++ * fallback migratetype if it was decided not to steal. + */ + static int try_to_steal_freepages(struct zone *zone, struct page *page, + int start_type, int fallback_type) +@@ -1113,12 +1113,10 @@ static int try_to_steal_freepages(struct zone *zone, struct page *page, + + /* Claim the whole block if over half of it is free */ + if (pages >= (1 << (pageblock_order-1)) || +- page_group_by_mobility_disabled) { +- ++ page_group_by_mobility_disabled) + set_pageblock_migratetype(page, start_type); +- return start_type; +- } + ++ return start_type; + } + + return fallback_type; +@@ -1170,7 +1168,7 @@ __rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype) + set_freepage_migratetype(page, new_type); + + trace_mm_page_alloc_extfrag(page, order, current_order, +- start_migratetype, migratetype, new_type); ++ start_migratetype, migratetype); + + return page; + } +diff --git a/net/compat.c b/net/compat.c +index cbc1a2a26587..275af79c131b 100644 +--- a/net/compat.c ++++ b/net/compat.c +@@ -738,24 +738,18 @@ static unsigned char nas[21] = { + + asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) + { +- if (flags & MSG_CMSG_COMPAT) +- return -EINVAL; + return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); + } + + asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, + unsigned int vlen, unsigned int flags) + { +- if (flags & MSG_CMSG_COMPAT) +- return -EINVAL; + return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, + flags | MSG_CMSG_COMPAT); + } + + asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) + { +- if (flags & MSG_CMSG_COMPAT) +- return -EINVAL; + return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); + } + +@@ -778,9 +772,6 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, + int datagrams; + struct timespec ktspec; + +- if (flags & MSG_CMSG_COMPAT) +- return -EINVAL; +- + if (timeout == NULL) + return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, + flags | MSG_CMSG_COMPAT, NULL); +diff --git a/net/core/dev.c b/net/core/dev.c +index 4ed77d7245c0..f6d8d7fe29ab 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -940,7 +940,7 @@ bool dev_valid_name(const char *name) + return false; + + while (*name) { +- if (*name == '/' || isspace(*name)) ++ if (*name == '/' || *name == ':' || isspace(*name)) + return false; + name++; + } +diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c +index 9d3d9e78397b..372ac662adf9 100644 +--- a/net/core/gen_stats.c ++++ b/net/core/gen_stats.c +@@ -32,6 +32,9 @@ gnet_stats_copy(struct gnet_dump *d, int type, void *buf, int size) + return 0; + + nla_put_failure: ++ kfree(d->xstats); ++ d->xstats = NULL; ++ d->xstats_len = 0; + spin_unlock_bh(d->lock); + return -1; + } +@@ -217,7 +220,9 @@ int + gnet_stats_copy_app(struct gnet_dump *d, void *st, int len) + { + if (d->compat_xstats) { +- d->xstats = st; ++ d->xstats = kmemdup(st, len, GFP_ATOMIC); ++ if (!d->xstats) ++ goto err_out; + d->xstats_len = len; + } + +@@ -225,6 +230,11 @@ gnet_stats_copy_app(struct gnet_dump *d, void *st, int len) + return gnet_stats_copy(d, TCA_STATS_APP, st, len); + + return 0; ++ ++err_out: ++ d->xstats_len = 0; ++ spin_unlock_bh(d->lock); ++ return -1; + } + EXPORT_SYMBOL(gnet_stats_copy_app); + +@@ -257,6 +267,9 @@ gnet_stats_finish_copy(struct gnet_dump *d) + return -1; + } + ++ kfree(d->xstats); ++ d->xstats = NULL; ++ d->xstats_len = 0; + spin_unlock_bh(d->lock); + return 0; + } +diff --git a/net/core/pktgen.c b/net/core/pktgen.c +index fdac61cac1bd..ca68d32b49ba 100644 +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -2812,25 +2812,25 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, + skb->dev = odev; + skb->pkt_type = PACKET_HOST; + ++ pktgen_finalize_skb(pkt_dev, skb, datalen); ++ + if (!(pkt_dev->flags & F_UDPCSUM)) { + skb->ip_summed = CHECKSUM_NONE; + } else if (odev->features & NETIF_F_V4_CSUM) { + skb->ip_summed = CHECKSUM_PARTIAL; + skb->csum = 0; +- udp4_hwcsum(skb, udph->source, udph->dest); ++ udp4_hwcsum(skb, iph->saddr, iph->daddr); + } else { +- __wsum csum = udp_csum(skb); ++ __wsum csum = skb_checksum(skb, skb_transport_offset(skb), datalen + 8, 0); + + /* add protocol-dependent pseudo-header */ +- udph->check = csum_tcpudp_magic(udph->source, udph->dest, ++ udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, + datalen + 8, IPPROTO_UDP, csum); + + if (udph->check == 0) + udph->check = CSUM_MANGLED_0; + } + +- pktgen_finalize_skb(pkt_dev, skb, datalen); +- + #ifdef CONFIG_XFRM + if (!process_ipsec(pkt_dev, skb, protocol)) + return NULL; +@@ -2946,6 +2946,8 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, + skb->dev = odev; + skb->pkt_type = PACKET_HOST; + ++ pktgen_finalize_skb(pkt_dev, skb, datalen); ++ + if (!(pkt_dev->flags & F_UDPCSUM)) { + skb->ip_summed = CHECKSUM_NONE; + } else if (odev->features & NETIF_F_V6_CSUM) { +@@ -2954,7 +2956,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, + skb->csum_offset = offsetof(struct udphdr, check); + udph->check = ~csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, 0); + } else { +- __wsum csum = udp_csum(skb); ++ __wsum csum = skb_checksum(skb, skb_transport_offset(skb), udplen, 0); + + /* add protocol-dependent pseudo-header */ + udph->check = csum_ipv6_magic(&iph->saddr, &iph->daddr, udplen, IPPROTO_UDP, csum); +@@ -2963,8 +2965,6 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, + udph->check = CSUM_MANGLED_0; + } + +- pktgen_finalize_skb(pkt_dev, skb, datalen); +- + return skb; + } + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index a6613ff972c1..8aadd6a072a4 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -1264,14 +1264,10 @@ static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = { + }; + + static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { +- [IFLA_VF_MAC] = { .type = NLA_BINARY, +- .len = sizeof(struct ifla_vf_mac) }, +- [IFLA_VF_VLAN] = { .type = NLA_BINARY, +- .len = sizeof(struct ifla_vf_vlan) }, +- [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, +- .len = sizeof(struct ifla_vf_tx_rate) }, +- [IFLA_VF_SPOOFCHK] = { .type = NLA_BINARY, +- .len = sizeof(struct ifla_vf_spoofchk) }, ++ [IFLA_VF_MAC] = { .len = sizeof(struct ifla_vf_mac) }, ++ [IFLA_VF_VLAN] = { .len = sizeof(struct ifla_vf_vlan) }, ++ [IFLA_VF_TX_RATE] = { .len = sizeof(struct ifla_vf_tx_rate) }, ++ [IFLA_VF_SPOOFCHK] = { .len = sizeof(struct ifla_vf_spoofchk) }, + }; + + static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = { +@@ -2034,8 +2030,16 @@ replay: + } + } + err = rtnl_configure_link(dev, ifm); +- if (err < 0) +- unregister_netdevice(dev); ++ if (err < 0) { ++ if (ops->newlink) { ++ LIST_HEAD(list_kill); ++ ++ ops->dellink(dev, &list_kill); ++ unregister_netdevice_many(&list_kill); ++ } else { ++ unregister_netdevice(dev); ++ } ++ } + out: + put_net(dest_net); + return err; +diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c +index c10a3ce5cbff..9ff497d17545 100644 +--- a/net/ipv4/ip_fragment.c ++++ b/net/ipv4/ip_fragment.c +@@ -679,27 +679,30 @@ EXPORT_SYMBOL(ip_defrag); + struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user) + { + struct iphdr iph; ++ int netoff; + u32 len; + + if (skb->protocol != htons(ETH_P_IP)) + return skb; + +- if (!skb_copy_bits(skb, 0, &iph, sizeof(iph))) ++ netoff = skb_network_offset(skb); ++ ++ if (skb_copy_bits(skb, netoff, &iph, sizeof(iph)) < 0) + return skb; + + if (iph.ihl < 5 || iph.version != 4) + return skb; + + len = ntohs(iph.tot_len); +- if (skb->len < len || len < (iph.ihl * 4)) ++ if (skb->len < netoff + len || len < (iph.ihl * 4)) + return skb; + + if (ip_is_fragment(&iph)) { + skb = skb_share_check(skb, GFP_ATOMIC); + if (skb) { +- if (!pskb_may_pull(skb, iph.ihl*4)) ++ if (!pskb_may_pull(skb, netoff + iph.ihl * 4)) + return skb; +- if (pskb_trim_rcsum(skb, len)) ++ if (pskb_trim_rcsum(skb, netoff + len)) + return skb; + memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); + if (ip_defrag(skb, user)) +diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +index dd637fc4b553..05686c47a289 100644 +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -843,7 +843,8 @@ static int __ip_append_data(struct sock *sk, + cork->length += length; + if (((length > mtu) || (skb && skb_is_gso(skb))) && + (sk->sk_protocol == IPPROTO_UDP) && +- (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) { ++ (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len && ++ (sk->sk_type == SOCK_DGRAM)) { + err = ip_ufo_append_data(sk, queue, getfrag, from, length, + hh_len, fragheaderlen, transhdrlen, + maxfraglen, flags); +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index 04ce671430cb..b94002ab8052 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -259,6 +259,10 @@ int ping_init_sock(struct sock *sk) + kgid_t low, high; + int ret = 0; + ++#if IS_ENABLED(CONFIG_IPV6) ++ if (sk->sk_family == AF_INET6) ++ inet6_sk(sk)->ipv6only = 1; ++#endif + inet_get_ping_group_range_net(net, &low, &high); + if (gid_lte(low, group) && gid_lte(group, high)) + return 0; +@@ -305,6 +309,11 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, + if (addr_len < sizeof(*addr)) + return -EINVAL; + ++ if (addr->sin_family != AF_INET && ++ !(addr->sin_family == AF_UNSPEC && ++ addr->sin_addr.s_addr == htonl(INADDR_ANY))) ++ return -EAFNOSUPPORT; ++ + pr_debug("ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)\n", + sk, &addr->sin_addr.s_addr, ntohs(addr->sin_port)); + +@@ -330,7 +339,7 @@ static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, + return -EINVAL; + + if (addr->sin6_family != AF_INET6) +- return -EINVAL; ++ return -EAFNOSUPPORT; + + pr_debug("ping_check_bind_addr(sk=%p,addr=%pI6c,port=%d)\n", + sk, addr->sin6_addr.s6_addr, ntohs(addr->sin6_port)); +@@ -716,7 +725,7 @@ static int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m + if (msg->msg_namelen < sizeof(*usin)) + return -EINVAL; + if (usin->sin_family != AF_INET) +- return -EINVAL; ++ return -EAFNOSUPPORT; + daddr = usin->sin_addr.s_addr; + /* no remote port */ + } else { +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 12f7ef0f243a..d7907ecf0b75 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1294,7 +1294,8 @@ emsgsize: + if (((length > mtu) || + (skb && skb_is_gso(skb))) && + (sk->sk_protocol == IPPROTO_UDP) && +- (rt->dst.dev->features & NETIF_F_UFO)) { ++ (rt->dst.dev->features & NETIF_F_UFO) && ++ (sk->sk_type == SOCK_DGRAM)) { + err = ip6_ufo_append_data(sk, getfrag, from, length, + hh_len, fragheaderlen, + transhdrlen, mtu, flags, rt); +diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c +index bda74291c3e0..461199533fe4 100644 +--- a/net/ipv6/ping.c ++++ b/net/ipv6/ping.c +@@ -103,9 +103,10 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + + if (msg->msg_name) { + DECLARE_SOCKADDR(struct sockaddr_in6 *, u, msg->msg_name); +- if (msg->msg_namelen < sizeof(struct sockaddr_in6) || +- u->sin6_family != AF_INET6) { ++ if (msg->msg_namelen < sizeof(*u)) + return -EINVAL; ++ if (u->sin6_family != AF_INET6) { ++ return -EAFNOSUPPORT; + } + if (sk->sk_bound_dev_if && + sk->sk_bound_dev_if != u->sin6_scope_id) { +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 6f1b8503a431..3809ca234c69 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -141,7 +141,7 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) + u32 *p = NULL; + + if (!(rt->dst.flags & DST_HOST)) +- return NULL; ++ return dst_cow_metrics_generic(dst, old); + + peer = rt6_get_peer_create(rt); + if (peer) { +diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c +index 2ba8b9705bb7..fdcb9688b5d3 100644 +--- a/net/irda/ircomm/ircomm_tty.c ++++ b/net/irda/ircomm/ircomm_tty.c +@@ -818,7 +818,9 @@ static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout) + orig_jiffies = jiffies; + + /* Set poll time to 200 ms */ +- poll_time = IRDA_MIN(timeout, msecs_to_jiffies(200)); ++ poll_time = msecs_to_jiffies(200); ++ if (timeout) ++ poll_time = min_t(unsigned long, timeout, poll_time); + + spin_lock_irqsave(&self->spinlock, flags); + while (self->tx_skb && self->tx_skb->len) { +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index e5a7ac2f3687..dca076f6252c 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -562,6 +562,7 @@ ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx) + if (tx->sdata->control_port_no_encrypt) + info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; + info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO; ++ info->flags |= IEEE80211_TX_CTL_USE_MINRATE; + } + + return TX_CONTINUE; +diff --git a/net/sched/ematch.c b/net/sched/ematch.c +index 3a633debb6df..a2abc449ce8f 100644 +--- a/net/sched/ematch.c ++++ b/net/sched/ematch.c +@@ -227,6 +227,7 @@ static int tcf_em_validate(struct tcf_proto *tp, + * to replay the request. + */ + module_put(em->ops->owner); ++ em->ops = NULL; + err = -EAGAIN; + } + #endif +diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c +index ae333c1845bb..0adc66caae2f 100644 +--- a/net/sunrpc/cache.c ++++ b/net/sunrpc/cache.c +@@ -920,7 +920,7 @@ static unsigned int cache_poll(struct file *filp, poll_table *wait, + poll_wait(filp, &queue_wait, wait); + + /* alway allow write */ +- mask = POLL_OUT | POLLWRNORM; ++ mask = POLLOUT | POLLWRNORM; + + if (!rp) + return mask; +diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c +index 566b0f69d628..ee2405723188 100644 +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -1404,6 +1404,8 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state) + if (! snd_pcm_playback_empty(substream)) { + snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING); + snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING); ++ } else { ++ runtime->status->state = SNDRV_PCM_STATE_SETUP; + } + break; + case SNDRV_PCM_STATE_RUNNING: +diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c +index 103e85a13f35..2f3059b50ffa 100644 +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -3984,7 +3984,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, + /* Panther Point */ + { PCI_DEVICE(0x8086, 0x1e20), +- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, ++ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, + /* Lynx Point */ + { PCI_DEVICE(0x8086, 0x8c20), + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, +diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c +index 12f28d7e0fdc..231b26471a63 100644 +--- a/sound/pci/hda/patch_sigmatel.c ++++ b/sound/pci/hda/patch_sigmatel.c +@@ -85,6 +85,7 @@ enum { + STAC_ALIENWARE_M17X, + STAC_92HD89XX_HP_FRONT_JACK, + STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK, ++ STAC_92HD73XX_ASUS_MOBO, + STAC_92HD73XX_MODELS + }; + +@@ -1935,7 +1936,18 @@ static const struct hda_fixup stac92hd73xx_fixups[] = { + [STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK] = { + .type = HDA_FIXUP_PINS, + .v.pins = stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs, +- } ++ }, ++ [STAC_92HD73XX_ASUS_MOBO] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ /* enable 5.1 and SPDIF out */ ++ { 0x0c, 0x01014411 }, ++ { 0x0d, 0x01014410 }, ++ { 0x0e, 0x01014412 }, ++ { 0x22, 0x014b1180 }, ++ { } ++ } ++ }, + }; + + static const struct hda_model_fixup stac92hd73xx_models[] = { +@@ -1947,6 +1959,7 @@ static const struct hda_model_fixup stac92hd73xx_models[] = { + { .id = STAC_DELL_M6_BOTH, .name = "dell-m6" }, + { .id = STAC_DELL_EQ, .name = "dell-eq" }, + { .id = STAC_ALIENWARE_M17X, .name = "alienware" }, ++ { .id = STAC_92HD73XX_ASUS_MOBO, .name = "asus-mobo" }, + {} + }; + +@@ -1999,6 +2012,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = { + "HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17, + "unknown HP", STAC_92HD89XX_HP_FRONT_JACK), ++ SND_PCI_QUIRK(PCI_VENDOR_ID_ASUSTEK, 0x83f8, "ASUS AT4NM10", ++ STAC_92HD73XX_ASUS_MOBO), + {} /* terminator */ + }; + +diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c +index 07b8b7bc9d20..81f6a7545ef5 100644 +--- a/sound/soc/omap/omap-pcm.c ++++ b/sound/soc/omap/omap-pcm.c +@@ -200,7 +200,7 @@ static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd) + struct snd_pcm *pcm = rtd->pcm; + int ret; + +- ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(64)); ++ ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + diff --git a/patch/kernel/neo-patch-3.14.36-37 b/patch/kernel/neo-patch-3.14.36-37 new file mode 100644 index 000000000..6b928d9ec --- /dev/null +++ b/patch/kernel/neo-patch-3.14.36-37 @@ -0,0 +1,2861 @@ +diff --git a/Makefile b/Makefile +index 4e6537bd8aa0..c24acc0d34a1 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 36 ++SUBLEVEL = 37 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/dra7xx-clocks.dtsi +index e96da9a898ad..f2512e1d28c7 100644 +--- a/arch/arm/boot/dts/dra7xx-clocks.dtsi ++++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi +@@ -243,10 +243,18 @@ + ti,invert-autoidle-bit; + }; + ++ dpll_core_byp_mux: dpll_core_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ ti,bit-shift = <23>; ++ reg = <0x012c>; ++ }; ++ + dpll_core_ck: dpll_core_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-core-clock"; +- clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ clocks = <&sys_clkin1>, <&dpll_core_byp_mux>; + reg = <0x0120>, <0x0124>, <0x012c>, <0x0128>; + }; + +@@ -309,10 +317,18 @@ + clock-div = <1>; + }; + ++ dpll_dsp_byp_mux: dpll_dsp_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&dsp_dpll_hs_clk_div>; ++ ti,bit-shift = <23>; ++ reg = <0x0240>; ++ }; ++ + dpll_dsp_ck: dpll_dsp_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&dsp_dpll_hs_clk_div>; ++ clocks = <&sys_clkin1>, <&dpll_dsp_byp_mux>; + reg = <0x0234>, <0x0238>, <0x0240>, <0x023c>; + }; + +@@ -335,10 +351,18 @@ + clock-div = <1>; + }; + ++ dpll_iva_byp_mux: dpll_iva_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&iva_dpll_hs_clk_div>; ++ ti,bit-shift = <23>; ++ reg = <0x01ac>; ++ }; ++ + dpll_iva_ck: dpll_iva_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&iva_dpll_hs_clk_div>; ++ clocks = <&sys_clkin1>, <&dpll_iva_byp_mux>; + reg = <0x01a0>, <0x01a4>, <0x01ac>, <0x01a8>; + }; + +@@ -361,10 +385,18 @@ + clock-div = <1>; + }; + ++ dpll_gpu_byp_mux: dpll_gpu_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ ti,bit-shift = <23>; ++ reg = <0x02e4>; ++ }; ++ + dpll_gpu_ck: dpll_gpu_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ clocks = <&sys_clkin1>, <&dpll_gpu_byp_mux>; + reg = <0x02d8>, <0x02dc>, <0x02e4>, <0x02e0>; + }; + +@@ -398,10 +430,18 @@ + clock-div = <1>; + }; + ++ dpll_ddr_byp_mux: dpll_ddr_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ ti,bit-shift = <23>; ++ reg = <0x021c>; ++ }; ++ + dpll_ddr_ck: dpll_ddr_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ clocks = <&sys_clkin1>, <&dpll_ddr_byp_mux>; + reg = <0x0210>, <0x0214>, <0x021c>, <0x0218>; + }; + +@@ -416,10 +456,18 @@ + ti,invert-autoidle-bit; + }; + ++ dpll_gmac_byp_mux: dpll_gmac_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ ti,bit-shift = <23>; ++ reg = <0x02b4>; ++ }; ++ + dpll_gmac_ck: dpll_gmac_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ clocks = <&sys_clkin1>, <&dpll_gmac_byp_mux>; + reg = <0x02a8>, <0x02ac>, <0x02b4>, <0x02b0>; + }; + +@@ -482,10 +530,18 @@ + clock-div = <1>; + }; + ++ dpll_eve_byp_mux: dpll_eve_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&eve_dpll_hs_clk_div>; ++ ti,bit-shift = <23>; ++ reg = <0x0290>; ++ }; ++ + dpll_eve_ck: dpll_eve_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&eve_dpll_hs_clk_div>; ++ clocks = <&sys_clkin1>, <&dpll_eve_byp_mux>; + reg = <0x0284>, <0x0288>, <0x0290>, <0x028c>; + }; + +@@ -1214,10 +1270,18 @@ + clock-div = <1>; + }; + ++ dpll_per_byp_mux: dpll_per_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&per_dpll_hs_clk_div>; ++ ti,bit-shift = <23>; ++ reg = <0x014c>; ++ }; ++ + dpll_per_ck: dpll_per_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-clock"; +- clocks = <&sys_clkin1>, <&per_dpll_hs_clk_div>; ++ clocks = <&sys_clkin1>, <&dpll_per_byp_mux>; + reg = <0x0140>, <0x0144>, <0x014c>, <0x0148>; + }; + +@@ -1240,10 +1304,18 @@ + clock-div = <1>; + }; + ++ dpll_usb_byp_mux: dpll_usb_byp_mux { ++ #clock-cells = <0>; ++ compatible = "ti,mux-clock"; ++ clocks = <&sys_clkin1>, <&usb_dpll_hs_clk_div>; ++ ti,bit-shift = <23>; ++ reg = <0x018c>; ++ }; ++ + dpll_usb_ck: dpll_usb_ck { + #clock-cells = <0>; + compatible = "ti,omap4-dpll-j-type-clock"; +- clocks = <&sys_clkin1>, <&usb_dpll_hs_clk_div>; ++ clocks = <&sys_clkin1>, <&dpll_usb_byp_mux>; + reg = <0x0180>, <0x0184>, <0x018c>, <0x0188>; + }; + +diff --git a/arch/arm/crypto/aesbs-core.S_shipped b/arch/arm/crypto/aesbs-core.S_shipped +index 71e5fc7cfb18..1d1800f71c5b 100644 +--- a/arch/arm/crypto/aesbs-core.S_shipped ++++ b/arch/arm/crypto/aesbs-core.S_shipped +@@ -58,14 +58,18 @@ + # define VFP_ABI_FRAME 0 + # define BSAES_ASM_EXTENDED_KEY + # define XTS_CHAIN_TWEAK +-# define __ARM_ARCH__ 7 ++# define __ARM_ARCH__ __LINUX_ARM_ARCH__ ++# define __ARM_MAX_ARCH__ 7 + #endif + + #ifdef __thumb__ + # define adrl adr + #endif + +-#if __ARM_ARCH__>=7 ++#if __ARM_MAX_ARCH__>=7 ++.arch armv7-a ++.fpu neon ++ + .text + .syntax unified @ ARMv7-capable assembler is expected to handle this + #ifdef __thumb2__ +@@ -74,8 +78,6 @@ + .code 32 + #endif + +-.fpu neon +- + .type _bsaes_decrypt8,%function + .align 4 + _bsaes_decrypt8: +@@ -2095,9 +2097,11 @@ bsaes_xts_decrypt: + vld1.8 {q8}, [r0] @ initial tweak + adr r2, .Lxts_magic + ++#ifndef XTS_CHAIN_TWEAK + tst r9, #0xf @ if not multiple of 16 + it ne @ Thumb2 thing, sanity check in ARM + subne r9, #0x10 @ subtract another 16 bytes ++#endif + subs r9, #0x80 + + blo .Lxts_dec_short +diff --git a/arch/arm/crypto/bsaes-armv7.pl b/arch/arm/crypto/bsaes-armv7.pl +index be068db960ee..a4d3856e7d24 100644 +--- a/arch/arm/crypto/bsaes-armv7.pl ++++ b/arch/arm/crypto/bsaes-armv7.pl +@@ -701,14 +701,18 @@ $code.=<<___; + # define VFP_ABI_FRAME 0 + # define BSAES_ASM_EXTENDED_KEY + # define XTS_CHAIN_TWEAK +-# define __ARM_ARCH__ 7 ++# define __ARM_ARCH__ __LINUX_ARM_ARCH__ ++# define __ARM_MAX_ARCH__ 7 + #endif + + #ifdef __thumb__ + # define adrl adr + #endif + +-#if __ARM_ARCH__>=7 ++#if __ARM_MAX_ARCH__>=7 ++.arch armv7-a ++.fpu neon ++ + .text + .syntax unified @ ARMv7-capable assembler is expected to handle this + #ifdef __thumb2__ +@@ -717,8 +721,6 @@ $code.=<<___; + .code 32 + #endif + +-.fpu neon +- + .type _bsaes_decrypt8,%function + .align 4 + _bsaes_decrypt8: +@@ -2076,9 +2078,11 @@ bsaes_xts_decrypt: + vld1.8 {@XMM[8]}, [r0] @ initial tweak + adr $magic, .Lxts_magic + ++#ifndef XTS_CHAIN_TWEAK + tst $len, #0xf @ if not multiple of 16 + it ne @ Thumb2 thing, sanity check in ARM + subne $len, #0x10 @ subtract another 16 bytes ++#endif + subs $len, #0x80 + + blo .Lxts_dec_short +diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h +index c5101dcb4fb0..1d4df3b70ebc 100644 +--- a/arch/arm/mach-at91/pm.h ++++ b/arch/arm/mach-at91/pm.h +@@ -45,7 +45,7 @@ static inline void at91rm9200_standby(void) + " mcr p15, 0, %0, c7, c0, 4\n\t" + " str %5, [%1, %2]" + : +- : "r" (0), "r" (AT91_BASE_SYS), "r" (AT91RM9200_SDRAMC_LPR), ++ : "r" (0), "r" (at91_ramc_base[0]), "r" (AT91RM9200_SDRAMC_LPR), + "r" (1), "r" (AT91RM9200_SDRAMC_SRR), + "r" (lpr)); + } +diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c +index fbd76785c5db..3974881388bb 100644 +--- a/arch/arm64/mm/dma-mapping.c ++++ b/arch/arm64/mm/dma-mapping.c +@@ -44,6 +44,7 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size, + flags |= GFP_DMA32; + if (IS_ENABLED(CONFIG_DMA_CMA)) { + struct page *page; ++ void *addr; + + size = PAGE_ALIGN(size); + page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT, +@@ -52,7 +53,10 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size, + return NULL; + + *dma_handle = phys_to_dma(dev, page_to_phys(page)); +- return page_address(page); ++ addr = page_address(page); ++ if (flags & __GFP_ZERO) ++ memset(addr, 0, size); ++ return addr; + } else { + return swiotlb_alloc_coherent(dev, size, dma_handle, flags); + } +diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c +index 617b9fe33771..3ccb6777a7e1 100644 +--- a/arch/sparc/kernel/perf_event.c ++++ b/arch/sparc/kernel/perf_event.c +@@ -960,6 +960,8 @@ out: + cpuc->pcr[0] |= cpuc->event[0]->hw.config_base; + } + ++static void sparc_pmu_start(struct perf_event *event, int flags); ++ + /* On this PMU each PIC has it's own PCR control register. */ + static void calculate_multiple_pcrs(struct cpu_hw_events *cpuc) + { +@@ -972,20 +974,13 @@ static void calculate_multiple_pcrs(struct cpu_hw_events *cpuc) + struct perf_event *cp = cpuc->event[i]; + struct hw_perf_event *hwc = &cp->hw; + int idx = hwc->idx; +- u64 enc; + + if (cpuc->current_idx[i] != PIC_NO_INDEX) + continue; + +- sparc_perf_event_set_period(cp, hwc, idx); + cpuc->current_idx[i] = idx; + +- enc = perf_event_get_enc(cpuc->events[i]); +- cpuc->pcr[idx] &= ~mask_for_index(idx); +- if (hwc->state & PERF_HES_STOPPED) +- cpuc->pcr[idx] |= nop_for_index(idx); +- else +- cpuc->pcr[idx] |= event_encoding(enc, idx); ++ sparc_pmu_start(cp, PERF_EF_RELOAD); + } + out: + for (i = 0; i < cpuc->n_events; i++) { +@@ -1101,7 +1096,6 @@ static void sparc_pmu_del(struct perf_event *event, int _flags) + int i; + + local_irq_save(flags); +- perf_pmu_disable(event->pmu); + + for (i = 0; i < cpuc->n_events; i++) { + if (event == cpuc->event[i]) { +@@ -1127,7 +1121,6 @@ static void sparc_pmu_del(struct perf_event *event, int _flags) + } + } + +- perf_pmu_enable(event->pmu); + local_irq_restore(flags); + } + +@@ -1361,7 +1354,6 @@ static int sparc_pmu_add(struct perf_event *event, int ef_flags) + unsigned long flags; + + local_irq_save(flags); +- perf_pmu_disable(event->pmu); + + n0 = cpuc->n_events; + if (n0 >= sparc_pmu->max_hw_events) +@@ -1394,7 +1386,6 @@ nocheck: + + ret = 0; + out: +- perf_pmu_enable(event->pmu); + local_irq_restore(flags); + return ret; + } +diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c +index c6f7113b6e2f..1a79d6877981 100644 +--- a/arch/sparc/kernel/process_64.c ++++ b/arch/sparc/kernel/process_64.c +@@ -281,6 +281,8 @@ void arch_trigger_all_cpu_backtrace(void) + printk(" TPC[%lx] O7[%lx] I7[%lx] RPC[%lx]\n", + gp->tpc, gp->o7, gp->i7, gp->rpc); + } ++ ++ touch_nmi_watchdog(); + } + + memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot)); +@@ -356,6 +358,8 @@ static void pmu_snapshot_all_cpus(void) + (cpu == this_cpu ? '*' : ' '), cpu, + pp->pcr[0], pp->pcr[1], pp->pcr[2], pp->pcr[3], + pp->pic[0], pp->pic[1], pp->pic[2], pp->pic[3]); ++ ++ touch_nmi_watchdog(); + } + + memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot)); +diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c +index beb0b5a5f21f..25db14a33d03 100644 +--- a/arch/sparc/kernel/sys_sparc_64.c ++++ b/arch/sparc/kernel/sys_sparc_64.c +@@ -332,7 +332,7 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second + long err; + + /* No need for backward compatibility. We can start fresh... */ +- if (call <= SEMCTL) { ++ if (call <= SEMTIMEDOP) { + switch (call) { + case SEMOP: + err = sys_semtimedop(first, ptr, +diff --git a/arch/sparc/lib/memmove.S b/arch/sparc/lib/memmove.S +index b7f6334e159f..857ad4f8905f 100644 +--- a/arch/sparc/lib/memmove.S ++++ b/arch/sparc/lib/memmove.S +@@ -8,9 +8,11 @@ + + .text + ENTRY(memmove) /* o0=dst o1=src o2=len */ +- mov %o0, %g1 ++ brz,pn %o2, 99f ++ mov %o0, %g1 ++ + cmp %o0, %o1 +- bleu,pt %xcc, memcpy ++ bleu,pt %xcc, 2f + add %o1, %o2, %g7 + cmp %g7, %o0 + bleu,pt %xcc, memcpy +@@ -24,7 +26,34 @@ ENTRY(memmove) /* o0=dst o1=src o2=len */ + stb %g7, [%o0] + bne,pt %icc, 1b + sub %o0, 1, %o0 +- ++99: + retl + mov %g1, %o0 ++ ++ /* We can't just call memcpy for these memmove cases. On some ++ * chips the memcpy uses cache initializing stores and when dst ++ * and src are close enough, those can clobber the source data ++ * before we've loaded it in. ++ */ ++2: or %o0, %o1, %g7 ++ or %o2, %g7, %g7 ++ andcc %g7, 0x7, %g0 ++ bne,pn %xcc, 4f ++ nop ++ ++3: ldx [%o1], %g7 ++ add %o1, 8, %o1 ++ subcc %o2, 8, %o2 ++ add %o0, 8, %o0 ++ bne,pt %icc, 3b ++ stx %g7, [%o0 - 0x8] ++ ba,a,pt %xcc, 99b ++ ++4: ldub [%o1], %g7 ++ add %o1, 1, %o1 ++ subcc %o2, 1, %o2 ++ add %o0, 1, %o0 ++ bne,pt %icc, 4b ++ stb %g7, [%o0 - 0x1] ++ ba,a,pt %xcc, 99b + ENDPROC(memmove) +diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c +index cfbe53c17b0d..09daebdee552 100644 +--- a/arch/sparc/mm/srmmu.c ++++ b/arch/sparc/mm/srmmu.c +@@ -460,10 +460,12 @@ static void __init sparc_context_init(int numctx) + void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, + struct task_struct *tsk) + { ++ unsigned long flags; ++ + if (mm->context == NO_CONTEXT) { +- spin_lock(&srmmu_context_spinlock); ++ spin_lock_irqsave(&srmmu_context_spinlock, flags); + alloc_context(old_mm, mm); +- spin_unlock(&srmmu_context_spinlock); ++ spin_unlock_irqrestore(&srmmu_context_spinlock, flags); + srmmu_ctxd_set(&srmmu_context_table[mm->context], mm->pgd); + } + +@@ -988,14 +990,15 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) + + void destroy_context(struct mm_struct *mm) + { ++ unsigned long flags; + + if (mm->context != NO_CONTEXT) { + flush_cache_mm(mm); + srmmu_ctxd_set(&srmmu_context_table[mm->context], srmmu_swapper_pg_dir); + flush_tlb_mm(mm); +- spin_lock(&srmmu_context_spinlock); ++ spin_lock_irqsave(&srmmu_context_spinlock, flags); + free_context(mm->context); +- spin_unlock(&srmmu_context_spinlock); ++ spin_unlock_irqrestore(&srmmu_context_spinlock, flags); + mm->context = NO_CONTEXT; + } + } +diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c +index 6dfb7d0b139a..6d4fabac779c 100644 +--- a/arch/x86/crypto/aesni-intel_glue.c ++++ b/arch/x86/crypto/aesni-intel_glue.c +@@ -1109,7 +1109,7 @@ static int __driver_rfc4106_decrypt(struct aead_request *req) + src = kmalloc(req->cryptlen + req->assoclen, GFP_ATOMIC); + if (!src) + return -ENOMEM; +- assoc = (src + req->cryptlen + auth_tag_len); ++ assoc = (src + req->cryptlen); + scatterwalk_map_and_copy(src, req->src, 0, req->cryptlen, 0); + scatterwalk_map_and_copy(assoc, req->assoc, 0, + req->assoclen, 0); +@@ -1134,7 +1134,7 @@ static int __driver_rfc4106_decrypt(struct aead_request *req) + scatterwalk_done(&src_sg_walk, 0, 0); + scatterwalk_done(&assoc_sg_walk, 0, 0); + } else { +- scatterwalk_map_and_copy(dst, req->dst, 0, req->cryptlen, 1); ++ scatterwalk_map_and_copy(dst, req->dst, 0, tempCipherLen, 1); + kfree(src); + } + return retval; +diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h +index cea1c76d49bf..1ac1c009090d 100644 +--- a/arch/x86/include/asm/fpu-internal.h ++++ b/arch/x86/include/asm/fpu-internal.h +@@ -368,7 +368,7 @@ static inline void drop_fpu(struct task_struct *tsk) + preempt_disable(); + tsk->thread.fpu_counter = 0; + __drop_fpu(tsk); +- clear_used_math(); ++ clear_stopped_child_used_math(tsk); + preempt_enable(); + } + +diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c +index dd50e26c58f6..7a09aca4b33a 100644 +--- a/arch/x86/kernel/xsave.c ++++ b/arch/x86/kernel/xsave.c +@@ -375,7 +375,7 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size) + * thread's fpu state, reconstruct fxstate from the fsave + * header. Sanitize the copied state etc. + */ +- struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave; ++ struct fpu *fpu = &tsk->thread.fpu; + struct user_i387_ia32_struct env; + int err = 0; + +@@ -389,14 +389,15 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size) + */ + drop_fpu(tsk); + +- if (__copy_from_user(xsave, buf_fx, state_size) || ++ if (__copy_from_user(&fpu->state->xsave, buf_fx, state_size) || + __copy_from_user(&env, buf, sizeof(env))) { ++ fpu_finit(fpu); + err = -1; + } else { + sanitize_restored_xstate(tsk, &env, xstate_bv, fx_only); +- set_used_math(); + } + ++ set_used_math(); + if (use_eager_fpu()) { + preempt_disable(); + math_state_restore(); +diff --git a/arch/x86/vdso/vdso32/sigreturn.S b/arch/x86/vdso/vdso32/sigreturn.S +index 31776d0efc8c..d7ec4e251c0a 100644 +--- a/arch/x86/vdso/vdso32/sigreturn.S ++++ b/arch/x86/vdso/vdso32/sigreturn.S +@@ -17,6 +17,7 @@ + .text + .globl __kernel_sigreturn + .type __kernel_sigreturn,@function ++ nop /* this guy is needed for .LSTARTFDEDLSI1 below (watch for HACK) */ + ALIGN + __kernel_sigreturn: + .LSTART_sigreturn: +diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c +index eff9d5870034..102463ba745d 100644 +--- a/drivers/char/tpm/tpm_ibmvtpm.c ++++ b/drivers/char/tpm/tpm_ibmvtpm.c +@@ -124,7 +124,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) + { + struct ibmvtpm_dev *ibmvtpm; + struct ibmvtpm_crq crq; +- u64 *word = (u64 *) &crq; ++ __be64 *word = (__be64 *)&crq; + int rc; + + ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip); +@@ -145,11 +145,11 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) + memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count); + crq.valid = (u8)IBMVTPM_VALID_CMD; + crq.msg = (u8)VTPM_TPM_COMMAND; +- crq.len = (u16)count; +- crq.data = ibmvtpm->rtce_dma_handle; ++ crq.len = cpu_to_be16(count); ++ crq.data = cpu_to_be32(ibmvtpm->rtce_dma_handle); + +- rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(word[0]), +- cpu_to_be64(word[1])); ++ rc = ibmvtpm_send_crq(ibmvtpm->vdev, be64_to_cpu(word[0]), ++ be64_to_cpu(word[1])); + if (rc != H_SUCCESS) { + dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc); + rc = 0; +diff --git a/drivers/char/tpm/tpm_ibmvtpm.h b/drivers/char/tpm/tpm_ibmvtpm.h +index bd82a791f995..b2c231b1beec 100644 +--- a/drivers/char/tpm/tpm_ibmvtpm.h ++++ b/drivers/char/tpm/tpm_ibmvtpm.h +@@ -22,9 +22,9 @@ + struct ibmvtpm_crq { + u8 valid; + u8 msg; +- u16 len; +- u32 data; +- u64 reserved; ++ __be16 len; ++ __be32 data; ++ __be64 reserved; + } __attribute__((packed, aligned(8))); + + struct ibmvtpm_crq_queue { +diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c +index 6928d094451d..b08eadb4b1d2 100644 +--- a/drivers/char/virtio_console.c ++++ b/drivers/char/virtio_console.c +@@ -142,6 +142,7 @@ struct ports_device { + * notification + */ + struct work_struct control_work; ++ struct work_struct config_work; + + struct list_head ports; + +@@ -1832,10 +1833,21 @@ static void config_intr(struct virtio_device *vdev) + + portdev = vdev->priv; + ++ if (!use_multiport(portdev)) ++ schedule_work(&portdev->config_work); ++} ++ ++static void config_work_handler(struct work_struct *work) ++{ ++ struct ports_device *portdev; ++ ++ portdev = container_of(work, struct ports_device, control_work); + if (!use_multiport(portdev)) { ++ struct virtio_device *vdev; + struct port *port; + u16 rows, cols; + ++ vdev = portdev->vdev; + virtio_cread(vdev, struct virtio_console_config, cols, &cols); + virtio_cread(vdev, struct virtio_console_config, rows, &rows); + +@@ -2024,12 +2036,14 @@ static int virtcons_probe(struct virtio_device *vdev) + spin_lock_init(&portdev->ports_lock); + INIT_LIST_HEAD(&portdev->ports); + ++ INIT_WORK(&portdev->config_work, &config_work_handler); ++ INIT_WORK(&portdev->control_work, &control_work_handler); ++ + if (multiport) { + unsigned int nr_added_bufs; + + spin_lock_init(&portdev->c_ivq_lock); + spin_lock_init(&portdev->c_ovq_lock); +- INIT_WORK(&portdev->control_work, &control_work_handler); + + nr_added_bufs = fill_queue(portdev->c_ivq, + &portdev->c_ivq_lock); +@@ -2097,6 +2111,8 @@ static void virtcons_remove(struct virtio_device *vdev) + /* Finish up work that's lined up */ + if (use_multiport(portdev)) + cancel_work_sync(&portdev->control_work); ++ else ++ cancel_work_sync(&portdev->config_work); + + list_for_each_entry_safe(port, port2, &portdev->ports, list) + unplug_port(port); +@@ -2148,6 +2164,7 @@ static int virtcons_freeze(struct virtio_device *vdev) + + virtqueue_disable_cb(portdev->c_ivq); + cancel_work_sync(&portdev->control_work); ++ cancel_work_sync(&portdev->config_work); + /* + * Once more: if control_work_handler() was running, it would + * enable the cb as the last step. +diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c +index 0cca5f24196a..663394f0c166 100644 +--- a/drivers/gpu/drm/radeon/atombios_crtc.c ++++ b/drivers/gpu/drm/radeon/atombios_crtc.c +@@ -1306,6 +1306,9 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, + (x << 16) | y); + viewport_w = crtc->mode.hdisplay; + viewport_h = (crtc->mode.vdisplay + 1) & ~1; ++ if ((rdev->family >= CHIP_BONAIRE) && ++ (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)) ++ viewport_h *= 2; + WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, + (viewport_w << 16) | viewport_h); + +diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c +index f0ed0baddf70..c3664bc05acf 100644 +--- a/drivers/gpu/drm/radeon/cik.c ++++ b/drivers/gpu/drm/radeon/cik.c +@@ -7069,6 +7069,9 @@ int cik_irq_set(struct radeon_device *rdev) + WREG32(DC_HPD5_INT_CONTROL, hpd5); + WREG32(DC_HPD6_INT_CONTROL, hpd6); + ++ /* posting read */ ++ RREG32(SRBM_STATUS); ++ + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index 7138f3e31b7c..ee9f0b4e90d6 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -4596,6 +4596,9 @@ int evergreen_irq_set(struct radeon_device *rdev) + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, afmt5); + WREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, afmt6); + ++ /* posting read */ ++ RREG32(SRBM_STATUS); ++ + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c +index 07620e198a6d..e28de20d469a 100644 +--- a/drivers/gpu/drm/radeon/r100.c ++++ b/drivers/gpu/drm/radeon/r100.c +@@ -742,6 +742,10 @@ int r100_irq_set(struct radeon_device *rdev) + tmp |= RADEON_FP2_DETECT_MASK; + } + WREG32(RADEON_GEN_INT_CNTL, tmp); ++ ++ /* read back to post the write */ ++ RREG32(RADEON_GEN_INT_CNTL); ++ + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c +index 788f602e8989..74a8a38db4d5 100644 +--- a/drivers/gpu/drm/radeon/r600.c ++++ b/drivers/gpu/drm/radeon/r600.c +@@ -3647,6 +3647,9 @@ int r600_irq_set(struct radeon_device *rdev) + WREG32(RV770_CG_THERMAL_INT, thermal_int); + } + ++ /* posting read */ ++ RREG32(R_000E50_SRBM_STATUS); ++ + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c +index 7f2d6c0d11c1..2f2d2ce34709 100644 +--- a/drivers/gpu/drm/radeon/radeon_cs.c ++++ b/drivers/gpu/drm/radeon/radeon_cs.c +@@ -179,11 +179,13 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) + u32 ring = RADEON_CS_RING_GFX; + s32 priority = 0; + ++ INIT_LIST_HEAD(&p->validated); ++ + if (!cs->num_chunks) { + return 0; + } ++ + /* get chunks */ +- INIT_LIST_HEAD(&p->validated); + p->idx = 0; + p->ib.sa_bo = NULL; + p->ib.semaphore = NULL; +diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c +index e5619d5e2a30..4261b3865cb0 100644 +--- a/drivers/gpu/drm/radeon/rs600.c ++++ b/drivers/gpu/drm/radeon/rs600.c +@@ -700,6 +700,10 @@ int rs600_irq_set(struct radeon_device *rdev) + WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); + if (ASIC_IS_DCE2(rdev)) + WREG32(R_007408_HDMI0_AUDIO_PACKET_CONTROL, hdmi0); ++ ++ /* posting read */ ++ RREG32(R_000040_GEN_INT_CNTL); ++ + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c +index 52b64ad285d6..2f2deccb3b78 100644 +--- a/drivers/gpu/drm/radeon/si.c ++++ b/drivers/gpu/drm/radeon/si.c +@@ -5958,6 +5958,9 @@ int si_irq_set(struct radeon_device *rdev) + + WREG32(CG_THERMAL_INT, thermal_int); + ++ /* posting read */ ++ RREG32(SRBM_STATUS); ++ + return 0; + } + +@@ -6875,8 +6878,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) + WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK); + + if (!vclk || !dclk) { +- /* keep the Bypass mode, put PLL to sleep */ +- WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); ++ /* keep the Bypass mode */ + return 0; + } + +@@ -6892,8 +6894,7 @@ int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) + /* set VCO_MODE to 1 */ + WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_VCO_MODE_MASK, ~UPLL_VCO_MODE_MASK); + +- /* toggle UPLL_SLEEP to 1 then back to 0 */ +- WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); ++ /* disable sleep mode */ + WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_SLEEP_MASK); + + /* deassert UPLL_RESET */ +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +index fb7c36e93fd4..0771dcbf9ed0 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +@@ -733,32 +733,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) + goto out_err1; + } + +- ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM, +- (dev_priv->vram_size >> PAGE_SHIFT)); +- if (unlikely(ret != 0)) { +- DRM_ERROR("Failed initializing memory manager for VRAM.\n"); +- goto out_err2; +- } +- +- dev_priv->has_gmr = true; +- if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) || +- refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR, +- VMW_PL_GMR) != 0) { +- DRM_INFO("No GMR memory available. " +- "Graphics memory resources are very limited.\n"); +- dev_priv->has_gmr = false; +- } +- +- if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) { +- dev_priv->has_mob = true; +- if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB, +- VMW_PL_MOB) != 0) { +- DRM_INFO("No MOB memory available. " +- "3D will be disabled.\n"); +- dev_priv->has_mob = false; +- } +- } +- + dev_priv->mmio_mtrr = arch_phys_wc_add(dev_priv->mmio_start, + dev_priv->mmio_size); + +@@ -821,6 +795,33 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) + goto out_no_fman; + } + ++ ++ ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM, ++ (dev_priv->vram_size >> PAGE_SHIFT)); ++ if (unlikely(ret != 0)) { ++ DRM_ERROR("Failed initializing memory manager for VRAM.\n"); ++ goto out_no_vram; ++ } ++ ++ dev_priv->has_gmr = true; ++ if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) || ++ refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR, ++ VMW_PL_GMR) != 0) { ++ DRM_INFO("No GMR memory available. " ++ "Graphics memory resources are very limited.\n"); ++ dev_priv->has_gmr = false; ++ } ++ ++ if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) { ++ dev_priv->has_mob = true; ++ if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB, ++ VMW_PL_MOB) != 0) { ++ DRM_INFO("No MOB memory available. " ++ "3D will be disabled.\n"); ++ dev_priv->has_mob = false; ++ } ++ } ++ + vmw_kms_save_vga(dev_priv); + + /* Start kms and overlay systems, needs fifo. */ +@@ -846,6 +847,12 @@ out_no_fifo: + vmw_kms_close(dev_priv); + out_no_kms: + vmw_kms_restore_vga(dev_priv); ++ if (dev_priv->has_mob) ++ (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); ++ if (dev_priv->has_gmr) ++ (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); ++ (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); ++out_no_vram: + vmw_fence_manager_takedown(dev_priv->fman); + out_no_fman: + if (dev_priv->capabilities & SVGA_CAP_IRQMASK) +@@ -861,12 +868,6 @@ out_err4: + iounmap(dev_priv->mmio_virt); + out_err3: + arch_phys_wc_del(dev_priv->mmio_mtrr); +- if (dev_priv->has_mob) +- (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); +- if (dev_priv->has_gmr) +- (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); +- (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); +-out_err2: + (void)ttm_bo_device_release(&dev_priv->bdev); + out_err1: + vmw_ttm_global_release(dev_priv); +@@ -896,6 +897,13 @@ static int vmw_driver_unload(struct drm_device *dev) + } + vmw_kms_close(dev_priv); + vmw_overlay_close(dev_priv); ++ ++ if (dev_priv->has_mob) ++ (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); ++ if (dev_priv->has_gmr) ++ (void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); ++ (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); ++ + vmw_fence_manager_takedown(dev_priv->fman); + if (dev_priv->capabilities & SVGA_CAP_IRQMASK) + drm_irq_uninstall(dev_priv->dev); +@@ -907,11 +915,6 @@ static int vmw_driver_unload(struct drm_device *dev) + ttm_object_device_release(&dev_priv->tdev); + iounmap(dev_priv->mmio_virt); + arch_phys_wc_del(dev_priv->mmio_mtrr); +- if (dev_priv->has_mob) +- (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); +- if (dev_priv->has_gmr) +- (void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); +- (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); + (void)ttm_bo_device_release(&dev_priv->bdev); + vmw_ttm_global_release(dev_priv); + +diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c +index 51e15fd53108..d058b00ba218 100644 +--- a/drivers/mtd/nand/pxa3xx_nand.c ++++ b/drivers/mtd/nand/pxa3xx_nand.c +@@ -481,6 +481,42 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) + nand_writel(info, NDCR, ndcr | int_mask); + } + ++static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len) ++{ ++ if (info->ecc_bch) { ++ int timeout; ++ ++ /* ++ * According to the datasheet, when reading from NDDB ++ * with BCH enabled, after each 32 bytes reads, we ++ * have to make sure that the NDSR.RDDREQ bit is set. ++ * ++ * Drain the FIFO 8 32 bits reads at a time, and skip ++ * the polling on the last read. ++ */ ++ while (len > 8) { ++ __raw_readsl(info->mmio_base + NDDB, data, 8); ++ ++ for (timeout = 0; ++ !(nand_readl(info, NDSR) & NDSR_RDDREQ); ++ timeout++) { ++ if (timeout >= 5) { ++ dev_err(&info->pdev->dev, ++ "Timeout on RDDREQ while draining the FIFO\n"); ++ return; ++ } ++ ++ mdelay(1); ++ } ++ ++ data += 32; ++ len -= 8; ++ } ++ } ++ ++ __raw_readsl(info->mmio_base + NDDB, data, len); ++} ++ + static void handle_data_pio(struct pxa3xx_nand_info *info) + { + unsigned int do_bytes = min(info->data_size, info->chunk_size); +@@ -497,14 +533,14 @@ static void handle_data_pio(struct pxa3xx_nand_info *info) + DIV_ROUND_UP(info->oob_size, 4)); + break; + case STATE_PIO_READING: +- __raw_readsl(info->mmio_base + NDDB, +- info->data_buff + info->data_buff_pos, +- DIV_ROUND_UP(do_bytes, 4)); ++ drain_fifo(info, ++ info->data_buff + info->data_buff_pos, ++ DIV_ROUND_UP(do_bytes, 4)); + + if (info->oob_size > 0) +- __raw_readsl(info->mmio_base + NDDB, +- info->oob_buff + info->oob_buff_pos, +- DIV_ROUND_UP(info->oob_size, 4)); ++ drain_fifo(info, ++ info->oob_buff + info->oob_buff_pos, ++ DIV_ROUND_UP(info->oob_size, 4)); + break; + default: + dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__, +diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c +index 1468c4658804..84ad2b44377c 100644 +--- a/drivers/net/can/dev.c ++++ b/drivers/net/can/dev.c +@@ -502,6 +502,14 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf) + skb->pkt_type = PACKET_BROADCAST; + skb->ip_summed = CHECKSUM_UNNECESSARY; + ++ skb_reset_mac_header(skb); ++ skb_reset_network_header(skb); ++ skb_reset_transport_header(skb); ++ ++ skb_reset_mac_header(skb); ++ skb_reset_network_header(skb); ++ skb_reset_transport_header(skb); ++ + can_skb_reserve(skb); + can_skb_prv(skb)->ifindex = dev->ifindex; + +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +index 7d4382286457..242874041ba4 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +@@ -12395,6 +12395,9 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev, + pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS, + PCICFG_VENDOR_ID_OFFSET); + ++ /* Set PCIe reset type to fundamental for EEH recovery */ ++ pdev->needs_freset = 1; ++ + /* AER (Advanced Error reporting) configuration */ + rc = pci_enable_pcie_error_reporting(pdev); + if (!rc) +diff --git a/drivers/net/usb/cx82310_eth.c b/drivers/net/usb/cx82310_eth.c +index 3eed708a6182..fe48f4c51373 100644 +--- a/drivers/net/usb/cx82310_eth.c ++++ b/drivers/net/usb/cx82310_eth.c +@@ -300,9 +300,18 @@ static const struct driver_info cx82310_info = { + .tx_fixup = cx82310_tx_fixup, + }; + ++#define USB_DEVICE_CLASS(vend, prod, cl, sc, pr) \ ++ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ ++ USB_DEVICE_ID_MATCH_DEV_INFO, \ ++ .idVendor = (vend), \ ++ .idProduct = (prod), \ ++ .bDeviceClass = (cl), \ ++ .bDeviceSubClass = (sc), \ ++ .bDeviceProtocol = (pr) ++ + static const struct usb_device_id products[] = { + { +- USB_DEVICE_AND_INTERFACE_INFO(0x0572, 0xcb01, 0xff, 0, 0), ++ USB_DEVICE_CLASS(0x0572, 0xcb01, 0xff, 0, 0), + .driver_info = (unsigned long) &cx82310_info + }, + { }, +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index b7984044232d..5d8d2dcd975e 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1764,10 +1764,12 @@ static int _regulator_do_enable(struct regulator_dev *rdev) + trace_regulator_enable(rdev_get_name(rdev)); + + if (rdev->ena_pin) { +- ret = regulator_ena_gpio_ctrl(rdev, true); +- if (ret < 0) +- return ret; +- rdev->ena_gpio_state = 1; ++ if (!rdev->ena_gpio_state) { ++ ret = regulator_ena_gpio_ctrl(rdev, true); ++ if (ret < 0) ++ return ret; ++ rdev->ena_gpio_state = 1; ++ } + } else if (rdev->desc->ops->enable) { + ret = rdev->desc->ops->enable(rdev); + if (ret < 0) +@@ -1897,10 +1899,12 @@ static int _regulator_do_disable(struct regulator_dev *rdev) + trace_regulator_disable(rdev_get_name(rdev)); + + if (rdev->ena_pin) { +- ret = regulator_ena_gpio_ctrl(rdev, false); +- if (ret < 0) +- return ret; +- rdev->ena_gpio_state = 0; ++ if (rdev->ena_gpio_state) { ++ ret = regulator_ena_gpio_ctrl(rdev, false); ++ if (ret < 0) ++ return ret; ++ rdev->ena_gpio_state = 0; ++ } + + } else if (rdev->desc->ops->disable) { + ret = rdev->desc->ops->disable(rdev); +@@ -3454,12 +3458,6 @@ regulator_register(const struct regulator_desc *regulator_desc, + config->ena_gpio, ret); + goto wash; + } +- +- if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH) +- rdev->ena_gpio_state = 1; +- +- if (config->ena_gpio_invert) +- rdev->ena_gpio_state = !rdev->ena_gpio_state; + } + + /* set regulator constraints */ +@@ -3631,9 +3629,11 @@ int regulator_suspend_finish(void) + list_for_each_entry(rdev, ®ulator_list, list) { + mutex_lock(&rdev->mutex); + if (rdev->use_count > 0 || rdev->constraints->always_on) { +- error = _regulator_do_enable(rdev); +- if (error) +- ret = error; ++ if (!_regulator_is_enabled(rdev)) { ++ error = _regulator_do_enable(rdev); ++ if (error) ++ ret = error; ++ } + } else { + if (!have_full_constraints()) + goto unlock; +diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c +index 62b58d38ce2e..60de66252fa2 100644 +--- a/drivers/scsi/libsas/sas_discover.c ++++ b/drivers/scsi/libsas/sas_discover.c +@@ -500,6 +500,7 @@ static void sas_revalidate_domain(struct work_struct *work) + struct sas_discovery_event *ev = to_sas_discovery_event(work); + struct asd_sas_port *port = ev->port; + struct sas_ha_struct *ha = port->ha; ++ struct domain_device *ddev = port->port_dev; + + /* prevent revalidation from finding sata links in recovery */ + mutex_lock(&ha->disco_mutex); +@@ -514,8 +515,9 @@ static void sas_revalidate_domain(struct work_struct *work) + SAS_DPRINTK("REVALIDATING DOMAIN on port %d, pid:%d\n", port->id, + task_pid_nr(current)); + +- if (port->port_dev) +- res = sas_ex_revalidate_domain(port->port_dev); ++ if (ddev && (ddev->dev_type == SAS_FANOUT_EXPANDER_DEVICE || ++ ddev->dev_type == SAS_EDGE_EXPANDER_DEVICE)) ++ res = sas_ex_revalidate_domain(ddev); + + SAS_DPRINTK("done REVALIDATING DOMAIN on port %d, pid:%d, res 0x%x\n", + port->id, task_pid_nr(current), res); +diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c +index 5d7b07f08326..5f8c6d2f4df7 100644 +--- a/drivers/spi/spi-atmel.c ++++ b/drivers/spi/spi-atmel.c +@@ -781,17 +781,17 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master, + (unsigned long long)xfer->rx_dma); + } + +- /* REVISIT: We're waiting for ENDRX before we start the next ++ /* REVISIT: We're waiting for RXBUFF before we start the next + * transfer because we need to handle some difficult timing +- * issues otherwise. If we wait for ENDTX in one transfer and +- * then starts waiting for ENDRX in the next, it's difficult +- * to tell the difference between the ENDRX interrupt we're +- * actually waiting for and the ENDRX interrupt of the ++ * issues otherwise. If we wait for TXBUFE in one transfer and ++ * then starts waiting for RXBUFF in the next, it's difficult ++ * to tell the difference between the RXBUFF interrupt we're ++ * actually waiting for and the RXBUFF interrupt of the + * previous transfer. + * + * It should be doable, though. Just not now... + */ +- spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES)); ++ spi_writel(as, IER, SPI_BIT(RXBUFF) | SPI_BIT(OVRES)); + spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN)); + } + +diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c +index 971855e859c7..fe091a87fd6d 100644 +--- a/drivers/spi/spi-pl022.c ++++ b/drivers/spi/spi-pl022.c +@@ -503,12 +503,12 @@ static void giveback(struct pl022 *pl022) + pl022->cur_msg = NULL; + pl022->cur_transfer = NULL; + pl022->cur_chip = NULL; +- spi_finalize_current_message(pl022->master); + + /* disable the SPI/SSP operation */ + writew((readw(SSP_CR1(pl022->virtbase)) & + (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); + ++ spi_finalize_current_message(pl022->master); + } + + /** +diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c +index be89260c23a6..27e1a6e62d06 100644 +--- a/drivers/staging/iio/adc/mxs-lradc.c ++++ b/drivers/staging/iio/adc/mxs-lradc.c +@@ -1159,7 +1159,6 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data) + LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2)); + } + +- if (iio_buffer_enabled(iio)) + if (iio_buffer_enabled(iio)) { + if (reg & lradc->buffer_vchans) + iio_trigger_poll(iio->trig, iio_get_time_ns()); +diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c +index 104f29e6b290..e168a63e77ea 100644 +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -4196,11 +4196,17 @@ int iscsit_close_connection( + pr_debug("Closing iSCSI connection CID %hu on SID:" + " %u\n", conn->cid, sess->sid); + /* +- * Always up conn_logout_comp just in case the RX Thread is sleeping +- * and the logout response never got sent because the connection +- * failed. ++ * Always up conn_logout_comp for the traditional TCP case just in case ++ * the RX Thread in iscsi_target_rx_opcode() is sleeping and the logout ++ * response never got sent because the connection failed. ++ * ++ * However for iser-target, isert_wait4logout() is using conn_logout_comp ++ * to signal logout response TX interrupt completion. Go ahead and skip ++ * this for iser since isert_rx_opcode() does not wait on logout failure, ++ * and to avoid iscsi_conn pointer dereference in iser-target code. + */ +- complete(&conn->conn_logout_comp); ++ if (conn->conn_transport->transport_type == ISCSI_TCP) ++ complete(&conn->conn_logout_comp); + + iscsi_release_thread_set(conn); + +diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c +index 26ae6886ac59..093b8cb85de7 100644 +--- a/drivers/target/target_core_device.c ++++ b/drivers/target/target_core_device.c +@@ -1591,8 +1591,6 @@ int target_configure_device(struct se_device *dev) + ret = dev->transport->configure_device(dev); + if (ret) + goto out; +- dev->dev_flags |= DF_CONFIGURED; +- + /* + * XXX: there is not much point to have two different values here.. + */ +@@ -1654,6 +1652,8 @@ int target_configure_device(struct se_device *dev) + list_add_tail(&dev->g_dev_node, &g_device_list); + mutex_unlock(&g_device_mutex); + ++ dev->dev_flags |= DF_CONFIGURED; ++ + return 0; + + out_free_alua: +diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c +index 0fccdcfd1015..70cb37516d40 100644 +--- a/drivers/target/target_core_pr.c ++++ b/drivers/target/target_core_pr.c +@@ -76,7 +76,7 @@ enum preempt_type { + }; + + static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, +- struct t10_pr_registration *, int); ++ struct t10_pr_registration *, int, int); + + static sense_reason_t + target_scsi2_reservation_check(struct se_cmd *cmd) +@@ -528,6 +528,18 @@ static int core_scsi3_pr_seq_non_holder( + + return 0; + } ++ } else if (we && registered_nexus) { ++ /* ++ * Reads are allowed for Write Exclusive locks ++ * from all registrants. ++ */ ++ if (cmd->data_direction == DMA_FROM_DEVICE) { ++ pr_debug("Allowing READ CDB: 0x%02x for %s" ++ " reservation\n", cdb[0], ++ core_scsi3_pr_dump_type(pr_reg_type)); ++ ++ return 0; ++ } + } + pr_debug("%s Conflict for %sregistered nexus %s CDB: 0x%2x" + " for %s reservation\n", transport_dump_cmd_direction(cmd), +@@ -1186,7 +1198,7 @@ static int core_scsi3_check_implicit_release( + * service action with the SERVICE ACTION RESERVATION KEY + * field set to zero (see 5.7.11.3). + */ +- __core_scsi3_complete_pro_release(dev, nacl, pr_reg, 0); ++ __core_scsi3_complete_pro_release(dev, nacl, pr_reg, 0, 1); + ret = 1; + /* + * For 'All Registrants' reservation types, all existing +@@ -1228,7 +1240,8 @@ static void __core_scsi3_free_registration( + + pr_reg->pr_reg_deve->def_pr_registered = 0; + pr_reg->pr_reg_deve->pr_res_key = 0; +- list_del(&pr_reg->pr_reg_list); ++ if (!list_empty(&pr_reg->pr_reg_list)) ++ list_del(&pr_reg->pr_reg_list); + /* + * Caller accessing *pr_reg using core_scsi3_locate_pr_reg(), + * so call core_scsi3_put_pr_reg() to decrement our reference. +@@ -1280,6 +1293,7 @@ void core_scsi3_free_pr_reg_from_nacl( + { + struct t10_reservation *pr_tmpl = &dev->t10_pr; + struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder; ++ bool free_reg = false; + /* + * If the passed se_node_acl matches the reservation holder, + * release the reservation. +@@ -1287,13 +1301,18 @@ void core_scsi3_free_pr_reg_from_nacl( + spin_lock(&dev->dev_reservation_lock); + pr_res_holder = dev->dev_pr_res_holder; + if ((pr_res_holder != NULL) && +- (pr_res_holder->pr_reg_nacl == nacl)) +- __core_scsi3_complete_pro_release(dev, nacl, pr_res_holder, 0); ++ (pr_res_holder->pr_reg_nacl == nacl)) { ++ __core_scsi3_complete_pro_release(dev, nacl, pr_res_holder, 0, 1); ++ free_reg = true; ++ } + spin_unlock(&dev->dev_reservation_lock); + /* + * Release any registration associated with the struct se_node_acl. + */ + spin_lock(&pr_tmpl->registration_lock); ++ if (pr_res_holder && free_reg) ++ __core_scsi3_free_registration(dev, pr_res_holder, NULL, 0); ++ + list_for_each_entry_safe(pr_reg, pr_reg_tmp, + &pr_tmpl->registration_list, pr_reg_list) { + +@@ -1316,7 +1335,7 @@ void core_scsi3_free_all_registrations( + if (pr_res_holder != NULL) { + struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl; + __core_scsi3_complete_pro_release(dev, pr_res_nacl, +- pr_res_holder, 0); ++ pr_res_holder, 0, 0); + } + spin_unlock(&dev->dev_reservation_lock); + +@@ -2126,13 +2145,13 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, + /* + * sa_res_key=0 Unregister Reservation Key for registered I_T Nexus. + */ +- pr_holder = core_scsi3_check_implicit_release( +- cmd->se_dev, pr_reg); ++ type = pr_reg->pr_res_type; ++ pr_holder = core_scsi3_check_implicit_release(cmd->se_dev, ++ pr_reg); + if (pr_holder < 0) { + ret = TCM_RESERVATION_CONFLICT; + goto out; + } +- type = pr_reg->pr_res_type; + + spin_lock(&pr_tmpl->registration_lock); + /* +@@ -2290,6 +2309,7 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) + spin_lock(&dev->dev_reservation_lock); + pr_res_holder = dev->dev_pr_res_holder; + if (pr_res_holder) { ++ int pr_res_type = pr_res_holder->pr_res_type; + /* + * From spc4r17 Section 5.7.9: Reserving: + * +@@ -2300,7 +2320,9 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) + * the logical unit, then the command shall be completed with + * RESERVATION CONFLICT status. + */ +- if (pr_res_holder != pr_reg) { ++ if ((pr_res_holder != pr_reg) && ++ (pr_res_type != PR_TYPE_WRITE_EXCLUSIVE_ALLREG) && ++ (pr_res_type != PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) { + struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl; + pr_err("SPC-3 PR: Attempted RESERVE from" + " [%s]: %s while reservation already held by" +@@ -2406,23 +2428,59 @@ static void __core_scsi3_complete_pro_release( + struct se_device *dev, + struct se_node_acl *se_nacl, + struct t10_pr_registration *pr_reg, +- int explicit) ++ int explicit, ++ int unreg) + { + struct target_core_fabric_ops *tfo = se_nacl->se_tpg->se_tpg_tfo; + char i_buf[PR_REG_ISID_ID_LEN]; ++ int pr_res_type = 0, pr_res_scope = 0; + + memset(i_buf, 0, PR_REG_ISID_ID_LEN); + core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); + /* + * Go ahead and release the current PR reservation holder. ++ * If an All Registrants reservation is currently active and ++ * a unregister operation is requested, replace the current ++ * dev_pr_res_holder with another active registration. + */ +- dev->dev_pr_res_holder = NULL; ++ if (dev->dev_pr_res_holder) { ++ pr_res_type = dev->dev_pr_res_holder->pr_res_type; ++ pr_res_scope = dev->dev_pr_res_holder->pr_res_scope; ++ dev->dev_pr_res_holder->pr_res_type = 0; ++ dev->dev_pr_res_holder->pr_res_scope = 0; ++ dev->dev_pr_res_holder->pr_res_holder = 0; ++ dev->dev_pr_res_holder = NULL; ++ } ++ if (!unreg) ++ goto out; + +- pr_debug("SPC-3 PR [%s] Service Action: %s RELEASE cleared" +- " reservation holder TYPE: %s ALL_TG_PT: %d\n", +- tfo->get_fabric_name(), (explicit) ? "explicit" : "implicit", +- core_scsi3_pr_dump_type(pr_reg->pr_res_type), +- (pr_reg->pr_reg_all_tg_pt) ? 1 : 0); ++ spin_lock(&dev->t10_pr.registration_lock); ++ list_del_init(&pr_reg->pr_reg_list); ++ /* ++ * If the I_T nexus is a reservation holder, the persistent reservation ++ * is of an all registrants type, and the I_T nexus is the last remaining ++ * registered I_T nexus, then the device server shall also release the ++ * persistent reservation. ++ */ ++ if (!list_empty(&dev->t10_pr.registration_list) && ++ ((pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) || ++ (pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG))) { ++ dev->dev_pr_res_holder = ++ list_entry(dev->t10_pr.registration_list.next, ++ struct t10_pr_registration, pr_reg_list); ++ dev->dev_pr_res_holder->pr_res_type = pr_res_type; ++ dev->dev_pr_res_holder->pr_res_scope = pr_res_scope; ++ dev->dev_pr_res_holder->pr_res_holder = 1; ++ } ++ spin_unlock(&dev->t10_pr.registration_lock); ++out: ++ if (!dev->dev_pr_res_holder) { ++ pr_debug("SPC-3 PR [%s] Service Action: %s RELEASE cleared" ++ " reservation holder TYPE: %s ALL_TG_PT: %d\n", ++ tfo->get_fabric_name(), (explicit) ? "explicit" : ++ "implicit", core_scsi3_pr_dump_type(pr_res_type), ++ (pr_reg->pr_reg_all_tg_pt) ? 1 : 0); ++ } + pr_debug("SPC-3 PR [%s] RELEASE Node: %s%s\n", + tfo->get_fabric_name(), se_nacl->initiatorname, + i_buf); +@@ -2553,7 +2611,7 @@ core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope, + * server shall not establish a unit attention condition. + */ + __core_scsi3_complete_pro_release(dev, se_sess->se_node_acl, +- pr_reg, 1); ++ pr_reg, 1, 0); + + spin_unlock(&dev->dev_reservation_lock); + +@@ -2641,7 +2699,7 @@ core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key) + if (pr_res_holder) { + struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl; + __core_scsi3_complete_pro_release(dev, pr_res_nacl, +- pr_res_holder, 0); ++ pr_res_holder, 0, 0); + } + spin_unlock(&dev->dev_reservation_lock); + /* +@@ -2700,7 +2758,7 @@ static void __core_scsi3_complete_pro_preempt( + */ + if (dev->dev_pr_res_holder) + __core_scsi3_complete_pro_release(dev, nacl, +- dev->dev_pr_res_holder, 0); ++ dev->dev_pr_res_holder, 0, 0); + + dev->dev_pr_res_holder = pr_reg; + pr_reg->pr_res_holder = 1; +@@ -2944,8 +3002,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, + */ + if (pr_reg_n != pr_res_holder) + __core_scsi3_complete_pro_release(dev, +- pr_res_holder->pr_reg_nacl, +- dev->dev_pr_res_holder, 0); ++ pr_res_holder->pr_reg_nacl, ++ dev->dev_pr_res_holder, 0, 0); + /* + * b) Remove the registrations for all I_T nexuses identified + * by the SERVICE ACTION RESERVATION KEY field, except the +@@ -3415,7 +3473,7 @@ after_iport_check: + * holder (i.e., the I_T nexus on which the + */ + __core_scsi3_complete_pro_release(dev, pr_res_nacl, +- dev->dev_pr_res_holder, 0); ++ dev->dev_pr_res_holder, 0, 0); + /* + * g) Move the persistent reservation to the specified I_T nexus using + * the same scope and type as the persistent reservation released in +@@ -3855,7 +3913,8 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) + unsigned char *buf; + u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len; + u32 off = 8; /* off into first Full Status descriptor */ +- int format_code = 0; ++ int format_code = 0, pr_res_type = 0, pr_res_scope = 0; ++ bool all_reg = false; + + if (cmd->data_length < 8) { + pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u" +@@ -3872,6 +3931,19 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) + buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); + buf[3] = (dev->t10_pr.pr_generation & 0xff); + ++ spin_lock(&dev->dev_reservation_lock); ++ if (dev->dev_pr_res_holder) { ++ struct t10_pr_registration *pr_holder = dev->dev_pr_res_holder; ++ ++ if (pr_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG || ++ pr_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG) { ++ all_reg = true; ++ pr_res_type = pr_holder->pr_res_type; ++ pr_res_scope = pr_holder->pr_res_scope; ++ } ++ } ++ spin_unlock(&dev->dev_reservation_lock); ++ + spin_lock(&pr_tmpl->registration_lock); + list_for_each_entry_safe(pr_reg, pr_reg_tmp, + &pr_tmpl->registration_list, pr_reg_list) { +@@ -3921,14 +3993,20 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) + * reservation holder for PR_HOLDER bit. + * + * Also, if this registration is the reservation +- * holder, fill in SCOPE and TYPE in the next byte. ++ * holder or there is an All Registrants reservation ++ * active, fill in SCOPE and TYPE in the next byte. + */ + if (pr_reg->pr_res_holder) { + buf[off++] |= 0x01; + buf[off++] = (pr_reg->pr_res_scope & 0xf0) | + (pr_reg->pr_res_type & 0x0f); +- } else ++ } else if (all_reg) { ++ buf[off++] |= 0x01; ++ buf[off++] = (pr_res_scope & 0xf0) | ++ (pr_res_type & 0x0f); ++ } else { + off += 2; ++ } + + off += 4; /* Skip over reserved area */ + /* +diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c +index 0f199f6a0738..29f28808fc03 100644 +--- a/drivers/target/target_core_pscsi.c ++++ b/drivers/target/target_core_pscsi.c +@@ -1111,7 +1111,7 @@ static u32 pscsi_get_device_type(struct se_device *dev) + struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); + struct scsi_device *sd = pdv->pdv_sd; + +- return sd->type; ++ return (sd) ? sd->type : TYPE_NO_LUN; + } + + static sector_t pscsi_get_blocks(struct se_device *dev) +diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c +index e6463ef33cd2..9e54c0fe718d 100644 +--- a/drivers/target/target_core_transport.c ++++ b/drivers/target/target_core_transport.c +@@ -2327,6 +2327,10 @@ int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd, + list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list); + out: + spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); ++ ++ if (ret && ack_kref) ++ target_put_sess_cmd(se_sess, se_cmd); ++ + return ret; + } + EXPORT_SYMBOL(target_get_sess_cmd); +diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c +index feda34404ed0..5892eab03874 100644 +--- a/drivers/tty/serial/8250/8250_pci.c ++++ b/drivers/tty/serial/8250/8250_pci.c +@@ -66,7 +66,7 @@ static void moan_device(const char *str, struct pci_dev *dev) + "Please send the output of lspci -vv, this\n" + "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n" + "manufacturer and name of serial board or\n" +- "modem board to rmk+serial@arm.linux.org.uk.\n", ++ "modem board to .\n", + pci_name(dev), str, dev->vendor, dev->device, + dev->subsystem_vendor, dev->subsystem_device); + } +diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c +index f4a9e3311297..c8860a8757ac 100644 +--- a/drivers/xen/events/events_base.c ++++ b/drivers/xen/events/events_base.c +@@ -547,20 +547,26 @@ static unsigned int __startup_pirq(unsigned int irq) + pirq_query_unmask(irq); + + rc = set_evtchn_to_irq(evtchn, irq); +- if (rc != 0) { +- pr_err("irq%d: Failed to set port to irq mapping (%d)\n", +- irq, rc); +- xen_evtchn_close(evtchn); +- return 0; +- } ++ if (rc) ++ goto err; ++ + bind_evtchn_to_cpu(evtchn, 0); + info->evtchn = evtchn; + ++ rc = xen_evtchn_port_setup(info); ++ if (rc) ++ goto err; ++ + out: + unmask_evtchn(evtchn); + eoi_pirq(irq_get_irq_data(irq)); + + return 0; ++ ++err: ++ pr_err("irq%d: Failed to set port to irq mapping (%d)\n", irq, rc); ++ xen_evtchn_close(evtchn); ++ return 0; + } + + static unsigned int startup_pirq(struct irq_data *data) +diff --git a/drivers/xen/xen-pciback/conf_space.c b/drivers/xen/xen-pciback/conf_space.c +index 46ae0f9f02ad..75fe3d466515 100644 +--- a/drivers/xen/xen-pciback/conf_space.c ++++ b/drivers/xen/xen-pciback/conf_space.c +@@ -16,7 +16,7 @@ + #include "conf_space.h" + #include "conf_space_quirks.h" + +-static bool permissive; ++bool permissive; + module_param(permissive, bool, 0644); + + /* This is where xen_pcibk_read_config_byte, xen_pcibk_read_config_word, +diff --git a/drivers/xen/xen-pciback/conf_space.h b/drivers/xen/xen-pciback/conf_space.h +index e56c934ad137..2e1d73d1d5d0 100644 +--- a/drivers/xen/xen-pciback/conf_space.h ++++ b/drivers/xen/xen-pciback/conf_space.h +@@ -64,6 +64,8 @@ struct config_field_entry { + void *data; + }; + ++extern bool permissive; ++ + #define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset) + + /* Add fields to a device - the add_fields macro expects to get a pointer to +diff --git a/drivers/xen/xen-pciback/conf_space_header.c b/drivers/xen/xen-pciback/conf_space_header.c +index c5ee82587e8c..2d7369391472 100644 +--- a/drivers/xen/xen-pciback/conf_space_header.c ++++ b/drivers/xen/xen-pciback/conf_space_header.c +@@ -11,6 +11,10 @@ + #include "pciback.h" + #include "conf_space.h" + ++struct pci_cmd_info { ++ u16 val; ++}; ++ + struct pci_bar_info { + u32 val; + u32 len_val; +@@ -20,22 +24,36 @@ struct pci_bar_info { + #define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO)) + #define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER) + +-static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data) ++/* Bits guests are allowed to control in permissive mode. */ ++#define PCI_COMMAND_GUEST (PCI_COMMAND_MASTER|PCI_COMMAND_SPECIAL| \ ++ PCI_COMMAND_INVALIDATE|PCI_COMMAND_VGA_PALETTE| \ ++ PCI_COMMAND_WAIT|PCI_COMMAND_FAST_BACK) ++ ++static void *command_init(struct pci_dev *dev, int offset) + { +- int i; +- int ret; +- +- ret = xen_pcibk_read_config_word(dev, offset, value, data); +- if (!pci_is_enabled(dev)) +- return ret; +- +- for (i = 0; i < PCI_ROM_RESOURCE; i++) { +- if (dev->resource[i].flags & IORESOURCE_IO) +- *value |= PCI_COMMAND_IO; +- if (dev->resource[i].flags & IORESOURCE_MEM) +- *value |= PCI_COMMAND_MEMORY; ++ struct pci_cmd_info *cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); ++ int err; ++ ++ if (!cmd) ++ return ERR_PTR(-ENOMEM); ++ ++ err = pci_read_config_word(dev, PCI_COMMAND, &cmd->val); ++ if (err) { ++ kfree(cmd); ++ return ERR_PTR(err); + } + ++ return cmd; ++} ++ ++static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data) ++{ ++ int ret = pci_read_config_word(dev, offset, value); ++ const struct pci_cmd_info *cmd = data; ++ ++ *value &= PCI_COMMAND_GUEST; ++ *value |= cmd->val & ~PCI_COMMAND_GUEST; ++ + return ret; + } + +@@ -43,6 +61,8 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) + { + struct xen_pcibk_dev_data *dev_data; + int err; ++ u16 val; ++ struct pci_cmd_info *cmd = data; + + dev_data = pci_get_drvdata(dev); + if (!pci_is_enabled(dev) && is_enable_cmd(value)) { +@@ -83,6 +103,19 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data) + } + } + ++ cmd->val = value; ++ ++ if (!permissive && (!dev_data || !dev_data->permissive)) ++ return 0; ++ ++ /* Only allow the guest to control certain bits. */ ++ err = pci_read_config_word(dev, offset, &val); ++ if (err || val == value) ++ return err; ++ ++ value &= PCI_COMMAND_GUEST; ++ value |= val & ~PCI_COMMAND_GUEST; ++ + return pci_write_config_word(dev, offset, value); + } + +@@ -282,6 +315,8 @@ static const struct config_field header_common[] = { + { + .offset = PCI_COMMAND, + .size = 2, ++ .init = command_init, ++ .release = bar_release, + .u.w.read = command_read, + .u.w.write = command_write, + }, +diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c +index 6eb13c621a14..499155ca3e84 100644 +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -819,8 +819,8 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) + + newpage = buf->page; + +- if (WARN_ON(!PageUptodate(newpage))) +- return -EIO; ++ if (!PageUptodate(newpage)) ++ SetPageUptodate(newpage); + + ClearPageMappedToDisk(newpage); + +@@ -1726,6 +1726,9 @@ copy_finish: + static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, + unsigned int size, struct fuse_copy_state *cs) + { ++ /* Don't try to move pages (yet) */ ++ cs->move_pages = 0; ++ + switch (code) { + case FUSE_NOTIFY_POLL: + return fuse_notify_poll(fc, size, cs); +diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c +index 5bee81674d53..14538a865102 100644 +--- a/fs/nilfs2/segment.c ++++ b/fs/nilfs2/segment.c +@@ -1906,6 +1906,7 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, + struct the_nilfs *nilfs) + { + struct nilfs_inode_info *ii, *n; ++ int during_mount = !(sci->sc_super->s_flags & MS_ACTIVE); + int defer_iput = false; + + spin_lock(&nilfs->ns_inode_lock); +@@ -1918,10 +1919,10 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, + brelse(ii->i_bh); + ii->i_bh = NULL; + list_del_init(&ii->i_dirty); +- if (!ii->vfs_inode.i_nlink) { ++ if (!ii->vfs_inode.i_nlink || during_mount) { + /* +- * Defer calling iput() to avoid a deadlock +- * over I_SYNC flag for inodes with i_nlink == 0 ++ * Defer calling iput() to avoid deadlocks if ++ * i_nlink == 0 or mount is not yet finished. + */ + list_add_tail(&ii->i_dirty, &sci->sc_iput_queue); + defer_iput = true; +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index c4b2646b6d7c..c2546717fc2b 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -1227,6 +1227,9 @@ out: + + static int pagemap_open(struct inode *inode, struct file *file) + { ++ /* do not disclose physical addresses: attack vector */ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; + pr_warn_once("Bits 55-60 of /proc/PID/pagemap entries are about " + "to stop being page-shift some time soon. See the " + "linux/Documentation/vm/pagemap.txt for details.\n"); +diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h +index 6c62cfa25f1a..bc9d2c2ddf87 100644 +--- a/include/linux/workqueue.h ++++ b/include/linux/workqueue.h +@@ -71,7 +71,8 @@ enum { + /* data contains off-queue information when !WORK_STRUCT_PWQ */ + WORK_OFFQ_FLAG_BASE = WORK_STRUCT_COLOR_SHIFT, + +- WORK_OFFQ_CANCELING = (1 << WORK_OFFQ_FLAG_BASE), ++ __WORK_OFFQ_CANCELING = WORK_OFFQ_FLAG_BASE, ++ WORK_OFFQ_CANCELING = (1 << __WORK_OFFQ_CANCELING), + + /* + * When a work item is off queue, its high bits point to the last +diff --git a/kernel/cpuset.c b/kernel/cpuset.c +index 2fb2877e6961..7b4530b0b16b 100644 +--- a/kernel/cpuset.c ++++ b/kernel/cpuset.c +@@ -503,9 +503,6 @@ static void update_domain_attr_tree(struct sched_domain_attr *dattr, + + rcu_read_lock(); + cpuset_for_each_descendant_pre(cp, pos_css, root_cs) { +- if (cp == root_cs) +- continue; +- + /* skip the whole subtree if @cp doesn't have any CPU */ + if (cpumask_empty(cp->cpus_allowed)) { + pos_css = css_rightmost_descendant(pos_css); +diff --git a/kernel/printk/console_cmdline.h b/kernel/printk/console_cmdline.h +index cbd69d842341..2ca4a8b5fe57 100644 +--- a/kernel/printk/console_cmdline.h ++++ b/kernel/printk/console_cmdline.h +@@ -3,7 +3,7 @@ + + struct console_cmdline + { +- char name[8]; /* Name of the driver */ ++ char name[16]; /* Name of the driver */ + int index; /* Minor dev. to use */ + char *options; /* Options for the driver */ + #ifdef CONFIG_A11Y_BRAILLE_CONSOLE +diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c +index 8c086e6049b9..a755ad70fe8f 100644 +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -2280,6 +2280,7 @@ void register_console(struct console *newcon) + for (i = 0, c = console_cmdline; + i < MAX_CMDLINECONSOLES && c->name[0]; + i++, c++) { ++ BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name)); + if (strcmp(c->name, newcon->name) != 0) + continue; + if (newcon->index >= 0 && +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index f6f31d823e8e..423c9e37a9e7 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -2893,19 +2893,57 @@ bool flush_work(struct work_struct *work) + } + EXPORT_SYMBOL_GPL(flush_work); + ++struct cwt_wait { ++ wait_queue_t wait; ++ struct work_struct *work; ++}; ++ ++static int cwt_wakefn(wait_queue_t *wait, unsigned mode, int sync, void *key) ++{ ++ struct cwt_wait *cwait = container_of(wait, struct cwt_wait, wait); ++ ++ if (cwait->work != key) ++ return 0; ++ return autoremove_wake_function(wait, mode, sync, key); ++} ++ + static bool __cancel_work_timer(struct work_struct *work, bool is_dwork) + { ++ static DECLARE_WAIT_QUEUE_HEAD(cancel_waitq); + unsigned long flags; + int ret; + + do { + ret = try_to_grab_pending(work, is_dwork, &flags); + /* +- * If someone else is canceling, wait for the same event it +- * would be waiting for before retrying. ++ * If someone else is already canceling, wait for it to ++ * finish. flush_work() doesn't work for PREEMPT_NONE ++ * because we may get scheduled between @work's completion ++ * and the other canceling task resuming and clearing ++ * CANCELING - flush_work() will return false immediately ++ * as @work is no longer busy, try_to_grab_pending() will ++ * return -ENOENT as @work is still being canceled and the ++ * other canceling task won't be able to clear CANCELING as ++ * we're hogging the CPU. ++ * ++ * Let's wait for completion using a waitqueue. As this ++ * may lead to the thundering herd problem, use a custom ++ * wake function which matches @work along with exclusive ++ * wait and wakeup. + */ +- if (unlikely(ret == -ENOENT)) +- flush_work(work); ++ if (unlikely(ret == -ENOENT)) { ++ struct cwt_wait cwait; ++ ++ init_wait(&cwait.wait); ++ cwait.wait.func = cwt_wakefn; ++ cwait.work = work; ++ ++ prepare_to_wait_exclusive(&cancel_waitq, &cwait.wait, ++ TASK_UNINTERRUPTIBLE); ++ if (work_is_canceling(work)) ++ schedule(); ++ finish_wait(&cancel_waitq, &cwait.wait); ++ } + } while (unlikely(ret < 0)); + + /* tell other tasks trying to grab @work to back off */ +@@ -2914,6 +2952,16 @@ static bool __cancel_work_timer(struct work_struct *work, bool is_dwork) + + flush_work(work); + clear_work_data(work); ++ ++ /* ++ * Paired with prepare_to_wait() above so that either ++ * waitqueue_active() is visible here or !work_is_canceling() is ++ * visible there. ++ */ ++ smp_mb(); ++ if (waitqueue_active(&cancel_waitq)) ++ __wake_up(&cancel_waitq, TASK_NORMAL, 1, work); ++ + return ret; + } + +diff --git a/lib/lz4/lz4_decompress.c b/lib/lz4/lz4_decompress.c +index 7a85967060a5..f0f5c5c3de12 100644 +--- a/lib/lz4/lz4_decompress.c ++++ b/lib/lz4/lz4_decompress.c +@@ -139,6 +139,9 @@ static int lz4_uncompress(const char *source, char *dest, int osize) + /* Error: request to write beyond destination buffer */ + if (cpy > oend) + goto _output_error; ++ if ((ref + COPYLENGTH) > oend || ++ (op + COPYLENGTH) > oend) ++ goto _output_error; + LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH)); + while (op < cpy) + *op++ = *ref++; +diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c +index d6be3edb7a43..526bf56f4d31 100644 +--- a/net/caif/caif_socket.c ++++ b/net/caif/caif_socket.c +@@ -283,7 +283,7 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock, + int copylen; + + ret = -EOPNOTSUPP; +- if (m->msg_flags&MSG_OOB) ++ if (flags & MSG_OOB) + goto read_error; + + skb = skb_recv_datagram(sk, flags, 0 , &ret); +diff --git a/net/can/af_can.c b/net/can/af_can.c +index a27f8aad9e99..5e9a2272b7a7 100644 +--- a/net/can/af_can.c ++++ b/net/can/af_can.c +@@ -262,6 +262,9 @@ int can_send(struct sk_buff *skb, int loop) + goto inval_skb; + } + ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ ++ skb_reset_mac_header(skb); + skb_reset_network_header(skb); + skb_reset_transport_header(skb); + +diff --git a/net/compat.c b/net/compat.c +index 275af79c131b..d12529050b29 100644 +--- a/net/compat.c ++++ b/net/compat.c +@@ -71,6 +71,13 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg) + __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || + __get_user(kmsg->msg_flags, &umsg->msg_flags)) + return -EFAULT; ++ ++ if (!tmp1) ++ kmsg->msg_namelen = 0; ++ ++ if (kmsg->msg_namelen < 0) ++ return -EINVAL; ++ + if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) + kmsg->msg_namelen = sizeof(struct sockaddr_storage); + kmsg->msg_name = compat_ptr(tmp1); +diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c +index cf9cd13509a7..e731c96eac4b 100644 +--- a/net/core/sysctl_net_core.c ++++ b/net/core/sysctl_net_core.c +@@ -25,6 +25,8 @@ + static int zero = 0; + static int one = 1; + static int ushort_max = USHRT_MAX; ++static int min_sndbuf = SOCK_MIN_SNDBUF; ++static int min_rcvbuf = SOCK_MIN_RCVBUF; + + #ifdef CONFIG_RPS + static int rps_sock_flow_sysctl(struct ctl_table *table, int write, +@@ -223,7 +225,7 @@ static struct ctl_table net_core_table[] = { + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_sndbuf, + }, + { + .procname = "rmem_max", +@@ -231,7 +233,7 @@ static struct ctl_table net_core_table[] = { + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_rcvbuf, + }, + { + .procname = "wmem_default", +@@ -239,7 +241,7 @@ static struct ctl_table net_core_table[] = { + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_sndbuf, + }, + { + .procname = "rmem_default", +@@ -247,7 +249,7 @@ static struct ctl_table net_core_table[] = { + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_rcvbuf, + }, + { + .procname = "dev_weight", +diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c +index e34dccbc4d70..4eeba4e497a0 100644 +--- a/net/ipv4/inet_diag.c ++++ b/net/ipv4/inet_diag.c +@@ -71,6 +71,20 @@ static inline void inet_diag_unlock_handler( + mutex_unlock(&inet_diag_table_mutex); + } + ++static size_t inet_sk_attr_size(void) ++{ ++ 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(sizeof(struct inet_diag_meminfo)) ++ + nla_total_size(sizeof(struct inet_diag_msg)) ++ + nla_total_size(SK_MEMINFO_VARS * sizeof(u32)) ++ + nla_total_size(TCP_CA_NAME_MAX) ++ + nla_total_size(sizeof(struct tcpvegas_info)) ++ + 64; ++} ++ + int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, + struct sk_buff *skb, struct inet_diag_req_v2 *req, + struct user_namespace *user_ns, +@@ -324,9 +338,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s + if (err) + goto out; + +- rep = nlmsg_new(sizeof(struct inet_diag_msg) + +- sizeof(struct inet_diag_meminfo) + +- sizeof(struct tcp_info) + 64, GFP_KERNEL); ++ rep = nlmsg_new(inet_sk_attr_size(), GFP_KERNEL); + if (!rep) { + err = -ENOMEM; + goto out; +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 7efa26bb872c..d0c310801479 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -2617,15 +2617,11 @@ void tcp_send_fin(struct sock *sk) + } else { + /* Socket is locked, keep trying until memory is available. */ + for (;;) { +- skb = alloc_skb_fclone(MAX_TCP_HEADER, +- sk->sk_allocation); ++ skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation); + if (skb) + break; + yield(); + } +- +- /* Reserve space for headers and prepare control bits. */ +- skb_reserve(skb, MAX_TCP_HEADER); + /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */ + tcp_init_nondata_skb(skb, tp->write_seq, + TCPHDR_ACK | TCPHDR_FIN); +@@ -2899,9 +2895,9 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) + { + struct tcp_sock *tp = tcp_sk(sk); + struct tcp_fastopen_request *fo = tp->fastopen_req; +- int syn_loss = 0, space, i, err = 0, iovlen = fo->data->msg_iovlen; +- struct sk_buff *syn_data = NULL, *data; ++ int syn_loss = 0, space, err = 0; + unsigned long last_syn_loss = 0; ++ struct sk_buff *syn_data; + + tp->rx_opt.mss_clamp = tp->advmss; /* If MSS is not cached */ + tcp_fastopen_cache_get(sk, &tp->rx_opt.mss_clamp, &fo->cookie, +@@ -2932,42 +2928,38 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) + /* limit to order-0 allocations */ + space = min_t(size_t, space, SKB_MAX_HEAD(MAX_TCP_HEADER)); + +- syn_data = skb_copy_expand(syn, MAX_TCP_HEADER, space, +- sk->sk_allocation); +- if (syn_data == NULL) ++ syn_data = sk_stream_alloc_skb(sk, space, sk->sk_allocation); ++ if (!syn_data) + goto fallback; ++ syn_data->ip_summed = CHECKSUM_PARTIAL; ++ memcpy(syn_data->cb, syn->cb, sizeof(syn->cb)); ++ if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space), ++ fo->data->msg_iov, 0, space))) { ++ kfree_skb(syn_data); ++ goto fallback; ++ } + +- for (i = 0; i < iovlen && syn_data->len < space; ++i) { +- struct iovec *iov = &fo->data->msg_iov[i]; +- unsigned char __user *from = iov->iov_base; +- int len = iov->iov_len; +- +- if (syn_data->len + len > space) +- len = space - syn_data->len; +- else if (i + 1 == iovlen) +- /* No more data pending in inet_wait_for_connect() */ +- fo->data = NULL; ++ /* No more data pending in inet_wait_for_connect() */ ++ if (space == fo->size) ++ fo->data = NULL; ++ fo->copied = space; + +- if (skb_add_data(syn_data, from, len)) +- goto fallback; +- } ++ tcp_connect_queue_skb(sk, syn_data); + +- /* Queue a data-only packet after the regular SYN for retransmission */ +- data = pskb_copy(syn_data, sk->sk_allocation); +- if (data == NULL) +- goto fallback; +- TCP_SKB_CB(data)->seq++; +- TCP_SKB_CB(data)->tcp_flags &= ~TCPHDR_SYN; +- TCP_SKB_CB(data)->tcp_flags = (TCPHDR_ACK|TCPHDR_PSH); +- tcp_connect_queue_skb(sk, data); +- fo->copied = data->len; ++ err = tcp_transmit_skb(sk, syn_data, 1, sk->sk_allocation); + +- if (tcp_transmit_skb(sk, syn_data, 0, sk->sk_allocation) == 0) { ++ /* Now full SYN+DATA was cloned and sent (or not), ++ * remove the SYN from the original skb (syn_data) ++ * we keep in write queue in case of a retransmit, as we ++ * also have the SYN packet (with no data) in the same queue. ++ */ ++ TCP_SKB_CB(syn_data)->seq++; ++ TCP_SKB_CB(syn_data)->tcp_flags = TCPHDR_ACK | TCPHDR_PSH; ++ if (!err) { + tp->syn_data = (fo->copied > 0); + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE); + goto done; + } +- syn_data = NULL; + + fallback: + /* Send a regular SYN with Fast Open cookie request option */ +@@ -2976,7 +2968,6 @@ fallback: + err = tcp_transmit_skb(sk, syn, 1, sk->sk_allocation); + if (err) + tp->syn_fastopen = 0; +- kfree_skb(syn_data); + done: + fo->cookie.len = -1; /* Exclude Fast Open option for SYN retries */ + return err; +@@ -2996,13 +2987,10 @@ int tcp_connect(struct sock *sk) + return 0; + } + +- buff = alloc_skb_fclone(MAX_TCP_HEADER + 15, sk->sk_allocation); +- if (unlikely(buff == NULL)) ++ buff = sk_stream_alloc_skb(sk, 0, sk->sk_allocation); ++ if (unlikely(!buff)) + return -ENOBUFS; + +- /* Reserve space for headers. */ +- skb_reserve(buff, MAX_TCP_HEADER); +- + tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN); + tp->retrans_stamp = TCP_SKB_CB(buff)->when = tcp_time_stamp; + tcp_connect_queue_skb(sk, buff); +diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c +index b4d5e1d97c1b..27ca79682efb 100644 +--- a/net/ipv6/fib6_rules.c ++++ b/net/ipv6/fib6_rules.c +@@ -104,6 +104,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, + goto again; + flp6->saddr = saddr; + } ++ err = rt->dst.error; + goto out; + } + again: +diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c +index 27d3f40de3cd..847d2a2c5d05 100644 +--- a/net/netfilter/ipvs/ip_vs_core.c ++++ b/net/netfilter/ipvs/ip_vs_core.c +@@ -658,16 +658,24 @@ static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user) + return err; + } + +-static int ip_vs_route_me_harder(int af, struct sk_buff *skb) ++static int ip_vs_route_me_harder(int af, struct sk_buff *skb, ++ unsigned int hooknum) + { ++ if (!sysctl_snat_reroute(skb)) ++ return 0; ++ /* Reroute replies only to remote clients (FORWARD and LOCAL_OUT) */ ++ if (NF_INET_LOCAL_IN == hooknum) ++ return 0; + #ifdef CONFIG_IP_VS_IPV6 + if (af == AF_INET6) { +- if (sysctl_snat_reroute(skb) && ip6_route_me_harder(skb) != 0) ++ struct dst_entry *dst = skb_dst(skb); ++ ++ if (dst->dev && !(dst->dev->flags & IFF_LOOPBACK) && ++ ip6_route_me_harder(skb) != 0) + return 1; + } else + #endif +- if ((sysctl_snat_reroute(skb) || +- skb_rtable(skb)->rt_flags & RTCF_LOCAL) && ++ if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL) && + ip_route_me_harder(skb, RTN_LOCAL) != 0) + return 1; + +@@ -790,7 +798,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb, + union nf_inet_addr *snet, + __u8 protocol, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, +- unsigned int offset, unsigned int ihl) ++ unsigned int offset, unsigned int ihl, ++ unsigned int hooknum) + { + unsigned int verdict = NF_DROP; + +@@ -820,7 +829,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb, + #endif + ip_vs_nat_icmp(skb, pp, cp, 1); + +- if (ip_vs_route_me_harder(af, skb)) ++ if (ip_vs_route_me_harder(af, skb, hooknum)) + goto out; + + /* do the statistics and put it back */ +@@ -915,7 +924,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related, + + snet.ip = iph->saddr; + return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp, +- pp, ciph.len, ihl); ++ pp, ciph.len, ihl, hooknum); + } + + #ifdef CONFIG_IP_VS_IPV6 +@@ -980,7 +989,8 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related, + snet.in6 = ciph.saddr.in6; + writable = ciph.len; + return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp, +- pp, writable, sizeof(struct ipv6hdr)); ++ pp, writable, sizeof(struct ipv6hdr), ++ hooknum); + } + #endif + +@@ -1039,7 +1049,8 @@ static inline bool is_new_conn(const struct sk_buff *skb, + */ + static unsigned int + handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, +- struct ip_vs_conn *cp, struct ip_vs_iphdr *iph) ++ struct ip_vs_conn *cp, struct ip_vs_iphdr *iph, ++ unsigned int hooknum) + { + struct ip_vs_protocol *pp = pd->pp; + +@@ -1077,7 +1088,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, + * if it came from this machine itself. So re-compute + * the routing information. + */ +- if (ip_vs_route_me_harder(af, skb)) ++ if (ip_vs_route_me_harder(af, skb, hooknum)) + goto drop; + + IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT"); +@@ -1180,7 +1191,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) + cp = pp->conn_out_get(af, skb, &iph, 0); + + if (likely(cp)) +- return handle_response(af, skb, pd, cp, &iph); ++ return handle_response(af, skb, pd, cp, &iph, hooknum); + if (sysctl_nat_icmp_send(net) && + (pp->protocol == IPPROTO_TCP || + pp->protocol == IPPROTO_UDP || +diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c +index db801263ee9f..a8027e73b6a2 100644 +--- a/net/netfilter/ipvs/ip_vs_sync.c ++++ b/net/netfilter/ipvs/ip_vs_sync.c +@@ -891,6 +891,8 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param, + IP_VS_DBG(2, "BACKUP, add new conn. failed\n"); + return; + } ++ if (!(flags & IP_VS_CONN_F_TEMPLATE)) ++ kfree(param->pe_data); + } + + if (opt) +@@ -1164,6 +1166,7 @@ static inline int ip_vs_proc_sync_conn(struct net *net, __u8 *p, __u8 *msg_end) + (opt_flags & IPVS_OPT_F_SEQ_DATA ? &opt : NULL) + ); + #endif ++ ip_vs_pe_put(param.pe); + return 0; + /* Error exit */ + out: +diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c +index ad979612238a..7350723aeb15 100644 +--- a/net/netfilter/nft_compat.c ++++ b/net/netfilter/nft_compat.c +@@ -611,8 +611,12 @@ nft_match_select_ops(const struct nft_ctx *ctx, + struct xt_match *match = nft_match->ops.data; + + if (strcmp(match->name, mt_name) == 0 && +- match->revision == rev && match->family == family) ++ match->revision == rev && match->family == family) { ++ if (!try_module_get(match->me)) ++ return ERR_PTR(-ENOENT); ++ + return &nft_match->ops; ++ } + } + + match = xt_request_find_match(family, mt_name, rev); +@@ -682,8 +686,12 @@ nft_target_select_ops(const struct nft_ctx *ctx, + struct xt_target *target = nft_target->ops.data; + + if (strcmp(target->name, tg_name) == 0 && +- target->revision == rev && target->family == family) ++ target->revision == rev && target->family == family) { ++ if (!try_module_get(target->me)) ++ return ERR_PTR(-ENOENT); ++ + return &nft_target->ops; ++ } + } + + target = xt_request_find_target(family, tg_name, rev); +diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c +index 1ba67931eb1b..13332dbf291d 100644 +--- a/net/netfilter/xt_socket.c ++++ b/net/netfilter/xt_socket.c +@@ -243,12 +243,13 @@ static int + extract_icmp6_fields(const struct sk_buff *skb, + unsigned int outside_hdrlen, + int *protocol, +- struct in6_addr **raddr, +- struct in6_addr **laddr, ++ const struct in6_addr **raddr, ++ const struct in6_addr **laddr, + __be16 *rport, +- __be16 *lport) ++ __be16 *lport, ++ struct ipv6hdr *ipv6_var) + { +- struct ipv6hdr *inside_iph, _inside_iph; ++ const struct ipv6hdr *inside_iph; + struct icmp6hdr *icmph, _icmph; + __be16 *ports, _ports[2]; + u8 inside_nexthdr; +@@ -263,12 +264,14 @@ extract_icmp6_fields(const struct sk_buff *skb, + if (icmph->icmp6_type & ICMPV6_INFOMSG_MASK) + return 1; + +- inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph), sizeof(_inside_iph), &_inside_iph); ++ inside_iph = skb_header_pointer(skb, outside_hdrlen + sizeof(_icmph), ++ sizeof(*ipv6_var), ipv6_var); + if (inside_iph == NULL) + return 1; + inside_nexthdr = inside_iph->nexthdr; + +- inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + sizeof(_inside_iph), ++ inside_hdrlen = ipv6_skip_exthdr(skb, outside_hdrlen + sizeof(_icmph) + ++ sizeof(*ipv6_var), + &inside_nexthdr, &inside_fragoff); + if (inside_hdrlen < 0) + return 1; /* hjm: Packet has no/incomplete transport layer headers. */ +@@ -315,10 +318,10 @@ xt_socket_get_sock_v6(struct net *net, const u8 protocol, + static bool + socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) + { +- struct ipv6hdr *iph = ipv6_hdr(skb); ++ struct ipv6hdr ipv6_var, *iph = ipv6_hdr(skb); + struct udphdr _hdr, *hp = NULL; + struct sock *sk = skb->sk; +- struct in6_addr *daddr = NULL, *saddr = NULL; ++ const struct in6_addr *daddr = NULL, *saddr = NULL; + __be16 uninitialized_var(dport), uninitialized_var(sport); + int thoff = 0, uninitialized_var(tproto); + const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; +@@ -342,7 +345,7 @@ socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) + + } else if (tproto == IPPROTO_ICMPV6) { + if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr, +- &sport, &dport)) ++ &sport, &dport, &ipv6_var)) + return false; + } else { + return false; +diff --git a/net/rds/iw_rdma.c b/net/rds/iw_rdma.c +index a817705ce2d0..dba8d0864f18 100644 +--- a/net/rds/iw_rdma.c ++++ b/net/rds/iw_rdma.c +@@ -88,7 +88,9 @@ static unsigned int rds_iw_unmap_fastreg_list(struct rds_iw_mr_pool *pool, + int *unpinned); + static void rds_iw_destroy_fastreg(struct rds_iw_mr_pool *pool, struct rds_iw_mr *ibmr); + +-static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwdev, struct rdma_cm_id **cm_id) ++static int rds_iw_get_device(struct sockaddr_in *src, struct sockaddr_in *dst, ++ struct rds_iw_device **rds_iwdev, ++ struct rdma_cm_id **cm_id) + { + struct rds_iw_device *iwdev; + struct rds_iw_cm_id *i_cm_id; +@@ -112,15 +114,15 @@ static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwd + src_addr->sin_port, + dst_addr->sin_addr.s_addr, + dst_addr->sin_port, +- rs->rs_bound_addr, +- rs->rs_bound_port, +- rs->rs_conn_addr, +- rs->rs_conn_port); ++ src->sin_addr.s_addr, ++ src->sin_port, ++ dst->sin_addr.s_addr, ++ dst->sin_port); + #ifdef WORKING_TUPLE_DETECTION +- if (src_addr->sin_addr.s_addr == rs->rs_bound_addr && +- src_addr->sin_port == rs->rs_bound_port && +- dst_addr->sin_addr.s_addr == rs->rs_conn_addr && +- dst_addr->sin_port == rs->rs_conn_port) { ++ if (src_addr->sin_addr.s_addr == src->sin_addr.s_addr && ++ src_addr->sin_port == src->sin_port && ++ dst_addr->sin_addr.s_addr == dst->sin_addr.s_addr && ++ dst_addr->sin_port == dst->sin_port) { + #else + /* FIXME - needs to compare the local and remote + * ipaddr/port tuple, but the ipaddr is the only +@@ -128,7 +130,7 @@ static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwd + * zero'ed. It doesn't appear to be properly populated + * during connection setup... + */ +- if (src_addr->sin_addr.s_addr == rs->rs_bound_addr) { ++ if (src_addr->sin_addr.s_addr == src->sin_addr.s_addr) { + #endif + spin_unlock_irq(&iwdev->spinlock); + *rds_iwdev = iwdev; +@@ -180,19 +182,13 @@ int rds_iw_update_cm_id(struct rds_iw_device *rds_iwdev, struct rdma_cm_id *cm_i + { + struct sockaddr_in *src_addr, *dst_addr; + struct rds_iw_device *rds_iwdev_old; +- struct rds_sock rs; + struct rdma_cm_id *pcm_id; + int rc; + + src_addr = (struct sockaddr_in *)&cm_id->route.addr.src_addr; + dst_addr = (struct sockaddr_in *)&cm_id->route.addr.dst_addr; + +- rs.rs_bound_addr = src_addr->sin_addr.s_addr; +- rs.rs_bound_port = src_addr->sin_port; +- rs.rs_conn_addr = dst_addr->sin_addr.s_addr; +- rs.rs_conn_port = dst_addr->sin_port; +- +- rc = rds_iw_get_device(&rs, &rds_iwdev_old, &pcm_id); ++ rc = rds_iw_get_device(src_addr, dst_addr, &rds_iwdev_old, &pcm_id); + if (rc) + rds_iw_remove_cm_id(rds_iwdev, cm_id); + +@@ -598,9 +594,17 @@ void *rds_iw_get_mr(struct scatterlist *sg, unsigned long nents, + struct rds_iw_device *rds_iwdev; + struct rds_iw_mr *ibmr = NULL; + struct rdma_cm_id *cm_id; ++ struct sockaddr_in src = { ++ .sin_addr.s_addr = rs->rs_bound_addr, ++ .sin_port = rs->rs_bound_port, ++ }; ++ struct sockaddr_in dst = { ++ .sin_addr.s_addr = rs->rs_conn_addr, ++ .sin_port = rs->rs_conn_port, ++ }; + int ret; + +- ret = rds_iw_get_device(rs, &rds_iwdev, &cm_id); ++ ret = rds_iw_get_device(&src, &dst, &rds_iwdev, &cm_id); + if (ret || !cm_id) { + ret = -ENODEV; + goto out; +diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c +index 34b5490dde65..4949f753686c 100644 +--- a/net/rxrpc/ar-recvmsg.c ++++ b/net/rxrpc/ar-recvmsg.c +@@ -87,7 +87,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, + if (!skb) { + /* nothing remains on the queue */ + if (copied && +- (msg->msg_flags & MSG_PEEK || timeo == 0)) ++ (flags & MSG_PEEK || timeo == 0)) + goto out; + + /* wait for a message to turn up */ +diff --git a/sound/core/control.c b/sound/core/control.c +index 98a29b26c5f4..f2082a35b890 100644 +--- a/sound/core/control.c ++++ b/sound/core/control.c +@@ -1168,6 +1168,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, + + if (info->count < 1) + return -EINVAL; ++ if (!*info->id.name) ++ return -EINVAL; ++ if (strnlen(info->id.name, sizeof(info->id.name)) >= sizeof(info->id.name)) ++ return -EINVAL; + access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : + (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| + SNDRV_CTL_ELEM_ACCESS_INACTIVE| +diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c +index d9a09bdd09db..9a23bdea97d8 100644 +--- a/sound/pci/hda/hda_generic.c ++++ b/sound/pci/hda/hda_generic.c +@@ -653,12 +653,45 @@ static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid, + return val; + } + ++/* is this a stereo widget or a stereo-to-mono mix? */ ++static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, int dir) ++{ ++ unsigned int wcaps = get_wcaps(codec, nid); ++ hda_nid_t conn; ++ ++ if (wcaps & AC_WCAP_STEREO) ++ return true; ++ if (dir != HDA_INPUT || get_wcaps_type(wcaps) != AC_WID_AUD_MIX) ++ return false; ++ if (snd_hda_get_num_conns(codec, nid) != 1) ++ return false; ++ if (snd_hda_get_connections(codec, nid, &conn, 1) < 0) ++ return false; ++ return !!(get_wcaps(codec, conn) & AC_WCAP_STEREO); ++} ++ + /* initialize the amp value (only at the first time) */ + static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx) + { + unsigned int caps = query_amp_caps(codec, nid, dir); + int val = get_amp_val_to_activate(codec, nid, dir, caps, false); +- snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val); ++ ++ if (is_stereo_amps(codec, nid, dir)) ++ snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val); ++ else ++ snd_hda_codec_amp_init(codec, nid, 0, dir, idx, 0xff, val); ++} ++ ++/* update the amp, doing in stereo or mono depending on NID */ ++static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx, ++ unsigned int mask, unsigned int val) ++{ ++ if (is_stereo_amps(codec, nid, dir)) ++ return snd_hda_codec_amp_stereo(codec, nid, dir, idx, ++ mask, val); ++ else ++ return snd_hda_codec_amp_update(codec, nid, 0, dir, idx, ++ mask, val); + } + + /* calculate amp value mask we can modify; +@@ -698,7 +731,7 @@ static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir, + return; + + val &= mask; +- snd_hda_codec_amp_stereo(codec, nid, dir, idx, mask, val); ++ update_amp(codec, nid, dir, idx, mask, val); + } + + static void activate_amp_out(struct hda_codec *codec, struct nid_path *path, +@@ -4337,13 +4370,11 @@ static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix) + has_amp = nid_has_mute(codec, mix, HDA_INPUT); + for (i = 0; i < nums; i++) { + if (has_amp) +- snd_hda_codec_amp_stereo(codec, mix, +- HDA_INPUT, i, +- 0xff, HDA_AMP_MUTE); ++ update_amp(codec, mix, HDA_INPUT, i, ++ 0xff, HDA_AMP_MUTE); + else if (nid_has_volume(codec, conn[i], HDA_OUTPUT)) +- snd_hda_codec_amp_stereo(codec, conn[i], +- HDA_OUTPUT, 0, +- 0xff, HDA_AMP_MUTE); ++ update_amp(codec, conn[i], HDA_OUTPUT, 0, ++ 0xff, HDA_AMP_MUTE); + } + } + +diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c +index 2f3059b50ffa..84e8879cc372 100644 +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -959,7 +959,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, + } + } + +- if (!bus->no_response_fallback) ++ if (bus->no_response_fallback) + return -1; + + if (!chip->polling_mode && chip->poll_count < 2) { +diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c +index ce5a6da83419..05e19f78b4cb 100644 +--- a/sound/pci/hda/hda_proc.c ++++ b/sound/pci/hda/hda_proc.c +@@ -134,13 +134,38 @@ static void print_amp_caps(struct snd_info_buffer *buffer, + (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT); + } + ++/* is this a stereo widget or a stereo-to-mono mix? */ ++static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, ++ int dir, unsigned int wcaps, int indices) ++{ ++ hda_nid_t conn; ++ ++ if (wcaps & AC_WCAP_STEREO) ++ return true; ++ /* check for a stereo-to-mono mix; it must be: ++ * only a single connection, only for input, and only a mixer widget ++ */ ++ if (indices != 1 || dir != HDA_INPUT || ++ get_wcaps_type(wcaps) != AC_WID_AUD_MIX) ++ return false; ++ ++ if (snd_hda_get_raw_connections(codec, nid, &conn, 1) < 0) ++ return false; ++ /* the connection source is a stereo? */ ++ wcaps = snd_hda_param_read(codec, conn, AC_PAR_AUDIO_WIDGET_CAP); ++ return !!(wcaps & AC_WCAP_STEREO); ++} ++ + static void print_amp_vals(struct snd_info_buffer *buffer, + struct hda_codec *codec, hda_nid_t nid, +- int dir, int stereo, int indices) ++ int dir, unsigned int wcaps, int indices) + { + unsigned int val; ++ bool stereo; + int i; + ++ stereo = is_stereo_amps(codec, nid, dir, wcaps, indices); ++ + dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT; + for (i = 0; i < indices; i++) { + snd_iprintf(buffer, " ["); +@@ -757,12 +782,10 @@ static void print_codec_info(struct snd_info_entry *entry, + (codec->single_adc_amp && + wid_type == AC_WID_AUD_IN)) + print_amp_vals(buffer, codec, nid, HDA_INPUT, +- wid_caps & AC_WCAP_STEREO, +- 1); ++ wid_caps, 1); + else + print_amp_vals(buffer, codec, nid, HDA_INPUT, +- wid_caps & AC_WCAP_STEREO, +- conn_len); ++ wid_caps, conn_len); + } + if (wid_caps & AC_WCAP_OUT_AMP) { + snd_iprintf(buffer, " Amp-Out caps: "); +@@ -771,11 +794,10 @@ static void print_codec_info(struct snd_info_entry *entry, + if (wid_type == AC_WID_PIN && + codec->pin_amp_workaround) + print_amp_vals(buffer, codec, nid, HDA_OUTPUT, +- wid_caps & AC_WCAP_STEREO, +- conn_len); ++ wid_caps, conn_len); + else + print_amp_vals(buffer, codec, nid, HDA_OUTPUT, +- wid_caps & AC_WCAP_STEREO, 1); ++ wid_caps, 1); + } + + switch (wid_type) { +diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c +index fc492ac24caa..51e208022cc8 100644 +--- a/sound/pci/hda/patch_cirrus.c ++++ b/sound/pci/hda/patch_cirrus.c +@@ -396,6 +396,7 @@ static const struct snd_pci_quirk cs420x_fixup_tbl[] = { + SND_PCI_QUIRK(0x106b, 0x1c00, "MacBookPro 8,1", CS420X_MBP81), + SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122), + SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101), ++ SND_PCI_QUIRK(0x106b, 0x5600, "MacBookAir 5,2", CS420X_MBP81), + SND_PCI_QUIRK(0x106b, 0x5b00, "MacBookAir 4,2", CS420X_MBA42), + SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE), + {} /* terminator */ +@@ -587,6 +588,7 @@ static int patch_cs420x(struct hda_codec *codec) + return -ENOMEM; + + spec->gen.automute_hook = cs_automute; ++ codec->single_adc_amp = 1; + + snd_hda_pick_fixup(codec, cs420x_models, cs420x_fixup_tbl, + cs420x_fixups); +diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c +index ffc19464b978..976493c4a695 100644 +--- a/sound/pci/hda/patch_conexant.c ++++ b/sound/pci/hda/patch_conexant.c +@@ -3232,6 +3232,7 @@ enum { + CXT_PINCFG_LENOVO_TP410, + CXT_PINCFG_LEMOTE_A1004, + CXT_PINCFG_LEMOTE_A1205, ++ CXT_PINCFG_COMPAQ_CQ60, + CXT_FIXUP_STEREO_DMIC, + CXT_FIXUP_INC_MIC_BOOST, + CXT_FIXUP_HEADPHONE_MIC_PIN, +@@ -3368,6 +3369,15 @@ static const struct hda_fixup cxt_fixups[] = { + .type = HDA_FIXUP_PINS, + .v.pins = cxt_pincfg_lemote, + }, ++ [CXT_PINCFG_COMPAQ_CQ60] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ /* 0x17 was falsely set up as a mic, it should 0x1d */ ++ { 0x17, 0x400001f0 }, ++ { 0x1d, 0x97a70120 }, ++ { } ++ } ++ }, + [CXT_FIXUP_STEREO_DMIC] = { + .type = HDA_FIXUP_FUNC, + .v.func = cxt_fixup_stereo_dmic, +@@ -3411,6 +3421,7 @@ static const struct hda_fixup cxt_fixups[] = { + }; + + static const struct snd_pci_quirk cxt5051_fixups[] = { ++ SND_PCI_QUIRK(0x103c, 0x360b, "Compaq CQ60", CXT_PINCFG_COMPAQ_CQ60), + SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200), + {} + }; +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index 83bddbdb90e9..5293b5ac8b9d 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -1773,6 +1773,36 @@ YAMAHA_DEVICE(0x7010, "UB99"), + } + } + }, ++{ ++ USB_DEVICE(0x0582, 0x0159), ++ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { ++ /* .vendor_name = "Roland", */ ++ /* .product_name = "UA-22", */ ++ .ifnum = QUIRK_ANY_INTERFACE, ++ .type = QUIRK_COMPOSITE, ++ .data = (const struct snd_usb_audio_quirk[]) { ++ { ++ .ifnum = 0, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 1, ++ .type = QUIRK_AUDIO_STANDARD_INTERFACE ++ }, ++ { ++ .ifnum = 2, ++ .type = QUIRK_MIDI_FIXED_ENDPOINT, ++ .data = & (const struct snd_usb_midi_endpoint_info) { ++ .out_cables = 0x0001, ++ .in_cables = 0x0001 ++ } ++ }, ++ { ++ .ifnum = -1 ++ } ++ } ++ } ++}, + /* this catches most recent vendor-specific Roland devices */ + { + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | diff --git a/patch/kernel/neo-patch-3.14.37-38 b/patch/kernel/neo-patch-3.14.37-38 new file mode 100644 index 000000000..75314290a --- /dev/null +++ b/patch/kernel/neo-patch-3.14.37-38 @@ -0,0 +1,1016 @@ +diff --git a/Makefile b/Makefile +index c24acc0d34a1..f09e19d2cc4f 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 37 ++SUBLEVEL = 38 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h +index a9eee33dfa62..101a42bde728 100644 +--- a/arch/arm64/include/asm/mmu_context.h ++++ b/arch/arm64/include/asm/mmu_context.h +@@ -151,6 +151,15 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, + { + unsigned int cpu = smp_processor_id(); + ++ /* ++ * init_mm.pgd does not contain any user mappings and it is always ++ * active for kernel addresses in TTBR1. Just set the reserved TTBR0. ++ */ ++ if (next == &init_mm) { ++ cpu_set_reserved_ttbr0(); ++ return; ++ } ++ + if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) + check_and_switch_context(next, tsk); + } +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi +index 1382fec9e8c5..7fcb1ac0f232 100644 +--- a/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-0.dtsi +@@ -50,6 +50,7 @@ ethernet@b0000 { + fsl,num_tx_queues = <0x8>; + fsl,magic-packet; + local-mac-address = [ 00 00 00 00 00 00 ]; ++ ranges; + + queue-group@b0000 { + #address-cells = <1>; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi +index 221cd2ea5b31..9f25427c1527 100644 +--- a/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-1.dtsi +@@ -50,6 +50,7 @@ ethernet@b1000 { + fsl,num_tx_queues = <0x8>; + fsl,magic-packet; + local-mac-address = [ 00 00 00 00 00 00 ]; ++ ranges; + + queue-group@b1000 { + #address-cells = <1>; +diff --git a/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi b/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi +index 61456c317609..cd7c318ab131 100644 +--- a/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi ++++ b/arch/powerpc/boot/dts/fsl/pq3-etsec2-2.dtsi +@@ -49,6 +49,7 @@ ethernet@b2000 { + fsl,num_tx_queues = <0x8>; + fsl,magic-packet; + local-mac-address = [ 00 00 00 00 00 00 ]; ++ ranges; + + queue-group@b2000 { + #address-cells = <1>; +diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S +index 38d507306a11..5193116eadc0 100644 +--- a/arch/powerpc/kernel/exceptions-64s.S ++++ b/arch/powerpc/kernel/exceptions-64s.S +@@ -1422,7 +1422,7 @@ machine_check_handle_early: + bne 9f /* continue in V mode if we are. */ + + 5: +-#ifdef CONFIG_KVM_BOOK3S_64_HV ++#ifdef CONFIG_KVM_BOOK3S_64_HANDLER + /* + * We are coming from kernel context. Check if we are coming from + * guest. if yes, then we can continue. We will fall through +diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c +index cde4e0a095ae..bf3829242aff 100644 +--- a/arch/powerpc/platforms/pseries/mobility.c ++++ b/arch/powerpc/platforms/pseries/mobility.c +@@ -24,10 +24,10 @@ + static struct kobject *mobility_kobj; + + struct update_props_workarea { +- u32 phandle; +- u32 state; +- u64 reserved; +- u32 nprops; ++ __be32 phandle; ++ __be32 state; ++ __be64 reserved; ++ __be32 nprops; + } __packed; + + #define NODE_ACTION_MASK 0xff000000 +@@ -53,11 +53,11 @@ static int mobility_rtas_call(int token, char *buf, s32 scope) + return rc; + } + +-static int delete_dt_node(u32 phandle) ++static int delete_dt_node(__be32 phandle) + { + struct device_node *dn; + +- dn = of_find_node_by_phandle(phandle); ++ dn = of_find_node_by_phandle(be32_to_cpu(phandle)); + if (!dn) + return -ENOENT; + +@@ -126,7 +126,7 @@ static int update_dt_property(struct device_node *dn, struct property **prop, + return 0; + } + +-static int update_dt_node(u32 phandle, s32 scope) ++static int update_dt_node(__be32 phandle, s32 scope) + { + struct update_props_workarea *upwa; + struct device_node *dn; +@@ -135,6 +135,7 @@ static int update_dt_node(u32 phandle, s32 scope) + char *prop_data; + char *rtas_buf; + int update_properties_token; ++ u32 nprops; + u32 vd; + + update_properties_token = rtas_token("ibm,update-properties"); +@@ -145,7 +146,7 @@ static int update_dt_node(u32 phandle, s32 scope) + if (!rtas_buf) + return -ENOMEM; + +- dn = of_find_node_by_phandle(phandle); ++ dn = of_find_node_by_phandle(be32_to_cpu(phandle)); + if (!dn) { + kfree(rtas_buf); + return -ENOENT; +@@ -161,6 +162,7 @@ static int update_dt_node(u32 phandle, s32 scope) + break; + + prop_data = rtas_buf + sizeof(*upwa); ++ nprops = be32_to_cpu(upwa->nprops); + + /* On the first call to ibm,update-properties for a node the + * the first property value descriptor contains an empty +@@ -169,17 +171,17 @@ static int update_dt_node(u32 phandle, s32 scope) + */ + if (*prop_data == 0) { + prop_data++; +- vd = *(u32 *)prop_data; ++ vd = be32_to_cpu(*(__be32 *)prop_data); + prop_data += vd + sizeof(vd); +- upwa->nprops--; ++ nprops--; + } + +- for (i = 0; i < upwa->nprops; i++) { ++ for (i = 0; i < nprops; i++) { + char *prop_name; + + prop_name = prop_data; + prop_data += strlen(prop_name) + 1; +- vd = *(u32 *)prop_data; ++ vd = be32_to_cpu(*(__be32 *)prop_data); + prop_data += sizeof(vd); + + switch (vd) { +@@ -211,13 +213,13 @@ static int update_dt_node(u32 phandle, s32 scope) + return 0; + } + +-static int add_dt_node(u32 parent_phandle, u32 drc_index) ++static int add_dt_node(__be32 parent_phandle, __be32 drc_index) + { + struct device_node *dn; + struct device_node *parent_dn; + int rc; + +- parent_dn = of_find_node_by_phandle(parent_phandle); ++ parent_dn = of_find_node_by_phandle(be32_to_cpu(parent_phandle)); + if (!parent_dn) + return -ENOENT; + +@@ -236,7 +238,7 @@ static int add_dt_node(u32 parent_phandle, u32 drc_index) + int pseries_devicetree_update(s32 scope) + { + char *rtas_buf; +- u32 *data; ++ __be32 *data; + int update_nodes_token; + int rc; + +@@ -253,17 +255,17 @@ int pseries_devicetree_update(s32 scope) + if (rc && rc != 1) + break; + +- data = (u32 *)rtas_buf + 4; +- while (*data & NODE_ACTION_MASK) { ++ data = (__be32 *)rtas_buf + 4; ++ while (be32_to_cpu(*data) & NODE_ACTION_MASK) { + int i; +- u32 action = *data & NODE_ACTION_MASK; +- int node_count = *data & NODE_COUNT_MASK; ++ u32 action = be32_to_cpu(*data) & NODE_ACTION_MASK; ++ u32 node_count = be32_to_cpu(*data) & NODE_COUNT_MASK; + + data++; + + for (i = 0; i < node_count; i++) { +- u32 phandle = *data++; +- u32 drc_index; ++ __be32 phandle = *data++; ++ __be32 drc_index; + + switch (action) { + case DELETE_DT_NODE: +diff --git a/drivers/clocksource/time-efm32.c b/drivers/clocksource/time-efm32.c +index 1a6205b7bed3..35b016100673 100644 +--- a/drivers/clocksource/time-efm32.c ++++ b/drivers/clocksource/time-efm32.c +@@ -225,12 +225,12 @@ static int __init efm32_clockevent_init(struct device_node *np) + clock_event_ddata.base = base; + clock_event_ddata.periodic_top = DIV_ROUND_CLOSEST(rate, 1024 * HZ); + +- setup_irq(irq, &efm32_clock_event_irq); +- + clockevents_config_and_register(&clock_event_ddata.evtdev, + DIV_ROUND_CLOSEST(rate, 1024), + 0xf, 0xffff); + ++ setup_irq(irq, &efm32_clock_event_irq); ++ + return 0; + + err_get_irq: +diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c +index deebcd6469fc..4f0f3610371a 100644 +--- a/drivers/clocksource/timer-sun5i.c ++++ b/drivers/clocksource/timer-sun5i.c +@@ -172,10 +172,6 @@ static void __init sun5i_timer_init(struct device_node *node) + + ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); + +- ret = setup_irq(irq, &sun5i_timer_irq); +- if (ret) +- pr_warn("failed to setup irq %d\n", irq); +- + /* Enable timer0 interrupt */ + val = readl(timer_base + TIMER_IRQ_EN_REG); + writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); +@@ -185,6 +181,10 @@ static void __init sun5i_timer_init(struct device_node *node) + + clockevents_config_and_register(&sun5i_clockevent, rate, + TIMER_SYNC_TICKS, 0xffffffff); ++ ++ ret = setup_irq(irq, &sun5i_timer_irq); ++ if (ret) ++ pr_warn("failed to setup irq %d\n", irq); + } + CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer", + sun5i_timer_init); +diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c +index 453822cc4f9d..fe8b0c991518 100644 +--- a/drivers/dma/dw/platform.c ++++ b/drivers/dma/dw/platform.c +@@ -48,6 +48,8 @@ static bool dw_dma_of_filter(struct dma_chan *chan, void *param) + return true; + } + ++#define DRV_NAME "dw_dmac" ++ + static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) + { +@@ -293,7 +295,7 @@ static struct platform_driver dw_driver = { + .remove = dw_remove, + .shutdown = dw_shutdown, + .driver = { +- .name = "dw_dmac", ++ .name = DRV_NAME, + .pm = &dw_dev_pm_ops, + .of_match_table = of_match_ptr(dw_dma_of_id_table), + .acpi_match_table = ACPI_PTR(dw_dma_acpi_id_table), +@@ -314,3 +316,4 @@ module_exit(dw_exit); + + MODULE_LICENSE("GPL v2"); + MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller platform driver"); ++MODULE_ALIAS("platform:" DRV_NAME); +diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c +index d2a8d64f8526..080e767250d3 100644 +--- a/drivers/md/dm-io.c ++++ b/drivers/md/dm-io.c +@@ -291,9 +291,16 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, + struct request_queue *q = bdev_get_queue(where->bdev); + unsigned short logical_block_size = queue_logical_block_size(q); + sector_t num_sectors; ++ unsigned int uninitialized_var(special_cmd_max_sectors); + +- /* Reject unsupported discard requests */ +- if ((rw & REQ_DISCARD) && !blk_queue_discard(q)) { ++ /* ++ * Reject unsupported discard and write same requests. ++ */ ++ if (rw & REQ_DISCARD) ++ special_cmd_max_sectors = q->limits.max_discard_sectors; ++ else if (rw & REQ_WRITE_SAME) ++ special_cmd_max_sectors = q->limits.max_write_same_sectors; ++ if ((rw & (REQ_DISCARD | REQ_WRITE_SAME)) && special_cmd_max_sectors == 0) { + dec_count(io, region, -EOPNOTSUPP); + return; + } +@@ -319,7 +326,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, + store_io_and_region_in_bio(bio, io, region); + + if (rw & REQ_DISCARD) { +- num_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining); ++ num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining); + bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT; + remaining -= num_sectors; + } else if (rw & REQ_WRITE_SAME) { +@@ -328,7 +335,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, + */ + dp->get_page(dp, &page, &len, &offset); + bio_add_page(bio, page, logical_block_size, offset); +- num_sectors = min_t(sector_t, q->limits.max_write_same_sectors, remaining); ++ num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining); + bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT; + + offset = 0; +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index 1582c3dac3ac..e40059143272 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -2352,10 +2352,16 @@ static void __dm_destroy(struct mapped_device *md, bool wait) + set_bit(DMF_FREEING, &md->flags); + spin_unlock(&_minor_lock); + ++ /* ++ * Take suspend_lock so that presuspend and postsuspend methods ++ * do not race with internal suspend. ++ */ ++ mutex_lock(&md->suspend_lock); + if (!dm_suspended_md(md)) { + dm_table_presuspend_targets(map); + dm_table_postsuspend_targets(map); + } ++ mutex_unlock(&md->suspend_lock); + + /* dm_put_live_table must be before msleep, otherwise deadlock is possible */ + dm_put_live_table(md, srcu_idx); +diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c +index 38917a822335..2df3cbc968d1 100644 +--- a/drivers/mfd/kempld-core.c ++++ b/drivers/mfd/kempld-core.c +@@ -629,7 +629,7 @@ static int __init kempld_init(void) + if (force_device_id[0]) { + for (id = kempld_dmi_table; id->matches[0].slot != DMI_NONE; id++) + if (strstr(id->ident, force_device_id)) +- if (id->callback && id->callback(id)) ++ if (id->callback && !id->callback(id)) + break; + if (id->matches[0].slot == DMI_NONE) + return -ENODEV; +diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c +index 9339cccfe05a..ad0e71c7a607 100644 +--- a/drivers/net/ethernet/amd/pcnet32.c ++++ b/drivers/net/ethernet/amd/pcnet32.c +@@ -1516,7 +1516,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) + { + struct pcnet32_private *lp; + int i, media; +- int fdx, mii, fset, dxsuflo; ++ int fdx, mii, fset, dxsuflo, sram; + int chip_version; + char *chipname; + struct net_device *dev; +@@ -1553,7 +1553,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) + } + + /* initialize variables */ +- fdx = mii = fset = dxsuflo = 0; ++ fdx = mii = fset = dxsuflo = sram = 0; + chip_version = (chip_version >> 12) & 0xffff; + + switch (chip_version) { +@@ -1586,6 +1586,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) + chipname = "PCnet/FAST III 79C973"; /* PCI */ + fdx = 1; + mii = 1; ++ sram = 1; + break; + case 0x2626: + chipname = "PCnet/Home 79C978"; /* PCI */ +@@ -1609,6 +1610,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) + chipname = "PCnet/FAST III 79C975"; /* PCI */ + fdx = 1; + mii = 1; ++ sram = 1; + break; + case 0x2628: + chipname = "PCnet/PRO 79C976"; +@@ -1637,6 +1639,31 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) + dxsuflo = 1; + } + ++ /* ++ * The Am79C973/Am79C975 controllers come with 12K of SRAM ++ * which we can use for the Tx/Rx buffers but most importantly, ++ * the use of SRAM allow us to use the BCR18:NOUFLO bit to avoid ++ * Tx fifo underflows. ++ */ ++ if (sram) { ++ /* ++ * The SRAM is being configured in two steps. First we ++ * set the SRAM size in the BCR25:SRAM_SIZE bits. According ++ * to the datasheet, each bit corresponds to a 512-byte ++ * page so we can have at most 24 pages. The SRAM_SIZE ++ * holds the value of the upper 8 bits of the 16-bit SRAM size. ++ * The low 8-bits start at 0x00 and end at 0xff. So the ++ * address range is from 0x0000 up to 0x17ff. Therefore, ++ * the SRAM_SIZE is set to 0x17. The next step is to set ++ * the BCR26:SRAM_BND midway through so the Tx and Rx ++ * buffers can share the SRAM equally. ++ */ ++ a->write_bcr(ioaddr, 25, 0x17); ++ a->write_bcr(ioaddr, 26, 0xc); ++ /* And finally enable the NOUFLO bit */ ++ a->write_bcr(ioaddr, 18, a->read_bcr(ioaddr, 18) | (1 << 11)); ++ } ++ + dev = alloc_etherdev(sizeof(*lp)); + if (!dev) { + ret = -ENOMEM; +diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c +index a04174607e97..4a3b8b72c8af 100644 +--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c +@@ -594,7 +594,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, + + ret = iwl_mvm_mac_ctxt_add(mvm, vif); + if (ret) +- goto out_remove_mac; ++ goto out_release; + + iwl_mvm_power_disable(mvm, vif); + +diff --git a/drivers/of/irq.c b/drivers/of/irq.c +index 48f20ff1add9..bbff99dcbaea 100644 +--- a/drivers/of/irq.c ++++ b/drivers/of/irq.c +@@ -290,7 +290,7 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar + struct device_node *p; + const __be32 *intspec, *tmp, *addr; + u32 intsize, intlen; +- int i, res = -EINVAL; ++ int i, res; + + pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index); + +@@ -323,15 +323,19 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar + + /* Get size of interrupt specifier */ + tmp = of_get_property(p, "#interrupt-cells", NULL); +- if (tmp == NULL) ++ if (tmp == NULL) { ++ res = -EINVAL; + goto out; ++ } + intsize = be32_to_cpu(*tmp); + + pr_debug(" intsize=%d intlen=%d\n", intsize, intlen); + + /* Check index */ +- if ((index + 1) * intsize > intlen) ++ if ((index + 1) * intsize > intlen) { ++ res = -EINVAL; + goto out; ++ } + + /* Copy intspec into irq structure */ + intspec += index * intsize; +diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c +index 34d56f7864d6..86592dd24da5 100644 +--- a/drivers/phy/phy-core.c ++++ b/drivers/phy/phy-core.c +@@ -50,7 +50,9 @@ static void devm_phy_consume(struct device *dev, void *res) + + static int devm_phy_match(struct device *dev, void *res, void *match_data) + { +- return res == match_data; ++ struct phy **phy = res; ++ ++ return *phy == match_data; + } + + static struct phy *phy_lookup(struct device *device, const char *port) +diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c +index 9d81f7693f99..1817f3f2b02d 100644 +--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c ++++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c +@@ -1515,7 +1515,7 @@ static int tcm_qla2xxx_check_initiator_node_acl( + /* + * Finally register the new FC Nexus with TCM + */ +- __transport_register_session(se_nacl->se_tpg, se_nacl, se_sess, sess); ++ transport_register_session(se_nacl->se_tpg, se_nacl, se_sess, sess); + + return 0; + } +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index fbf3b22efe5a..d6563ec700d4 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -846,13 +846,14 @@ void spi_finalize_current_message(struct spi_master *master) + "failed to unprepare message: %d\n", ret); + } + } ++ ++ trace_spi_message_done(mesg); ++ + master->cur_msg_prepared = false; + + mesg->state = NULL; + if (mesg->complete) + mesg->complete(mesg->context); +- +- trace_spi_message_done(mesg); + } + EXPORT_SYMBOL_GPL(spi_finalize_current_message); + +diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c +index edb1b2768b17..dbd9d44919ac 100644 +--- a/drivers/staging/vt6655/rf.c ++++ b/drivers/staging/vt6655/rf.c +@@ -936,6 +936,7 @@ bool RFbSetPower( + break; + case RATE_6M: + case RATE_9M: ++ case RATE_12M: + case RATE_18M: + byPwr = pDevice->abyOFDMPwrTbl[uCH]; + if (pDevice->byRFType == RF_UW2452) { +diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c +index 1e8f64bff03c..2dc48d4ff433 100644 +--- a/drivers/staging/vt6656/rf.c ++++ b/drivers/staging/vt6656/rf.c +@@ -752,6 +752,7 @@ int RFbSetPower(struct vnt_private *priv, u32 rate, u32 channel) + break; + case RATE_6M: + case RATE_9M: ++ case RATE_12M: + case RATE_18M: + case RATE_24M: + case RATE_36M: +diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c +index e415af32115a..c67d3795db4a 100644 +--- a/drivers/target/tcm_fc/tfc_io.c ++++ b/drivers/target/tcm_fc/tfc_io.c +@@ -346,7 +346,7 @@ void ft_invl_hw_context(struct ft_cmd *cmd) + ep = fc_seq_exch(seq); + if (ep) { + lport = ep->lp; +- if (lport && (ep->xid <= lport->lro_xid)) ++ if (lport && (ep->xid <= lport->lro_xid)) { + /* + * "ddp_done" trigger invalidation of HW + * specific DDP context +@@ -361,6 +361,7 @@ void ft_invl_hw_context(struct ft_cmd *cmd) + * identified using ep->xid) + */ + cmd->was_ddp_setup = 0; ++ } + } + } + } +diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c +index 6e560d56094b..754fdf8c6356 100644 +--- a/fs/hfsplus/brec.c ++++ b/fs/hfsplus/brec.c +@@ -131,13 +131,16 @@ skip: + hfs_bnode_write(node, entry, data_off + key_len, entry_len); + hfs_bnode_dump(node); + +- if (new_node) { +- /* update parent key if we inserted a key +- * at the start of the first node +- */ +- if (!rec && new_node != node) +- hfs_brec_update_parent(fd); ++ /* ++ * update parent key if we inserted a key ++ * at the start of the node and it is not the new node ++ */ ++ if (!rec && new_node != node) { ++ hfs_bnode_read_key(node, fd->search_key, data_off + size); ++ hfs_brec_update_parent(fd); ++ } + ++ if (new_node) { + hfs_bnode_put(fd->bnode); + if (!new_node->parent) { + hfs_btree_inc_height(tree); +@@ -168,9 +171,6 @@ skip: + goto again; + } + +- if (!rec) +- hfs_brec_update_parent(fd); +- + return 0; + } + +@@ -370,6 +370,8 @@ again: + if (IS_ERR(parent)) + return PTR_ERR(parent); + __hfs_brec_find(parent, fd, hfs_find_rec_by_key); ++ if (fd->record < 0) ++ return -ENOENT; + hfs_bnode_dump(parent); + rec = fd->record; + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 69cffb46db17..60146febb9b3 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -4232,6 +4232,13 @@ static void perf_pending_event(struct irq_work *entry) + { + struct perf_event *event = container_of(entry, + struct perf_event, pending); ++ int rctx; ++ ++ rctx = perf_swevent_get_recursion_context(); ++ /* ++ * If we 'fail' here, that's OK, it means recursion is already disabled ++ * and we won't recurse 'further'. ++ */ + + if (event->pending_disable) { + event->pending_disable = 0; +@@ -4242,6 +4249,9 @@ static void perf_pending_event(struct irq_work *entry) + event->pending_wakeup = 0; + perf_event_wakeup(event); + } ++ ++ if (rctx >= 0) ++ perf_swevent_put_recursion_context(rctx); + } + + /* +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index bf7a1bbb975f..e278c64572de 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -57,13 +57,24 @@ struct ieee80211_local; + #define IEEE80211_UNSET_POWER_LEVEL INT_MIN + + /* +- * Some APs experience problems when working with U-APSD. Decrease the +- * probability of that happening by using legacy mode for all ACs but VO. +- * The AP that caused us trouble was a Cisco 4410N. It ignores our +- * setting, and always treats non-VO ACs as legacy. ++ * Some APs experience problems when working with U-APSD. Decreasing the ++ * probability of that happening by using legacy mode for all ACs but VO isn't ++ * enough. ++ * ++ * Cisco 4410N originally forced us to enable VO by default only because it ++ * treated non-VO ACs as legacy. ++ * ++ * However some APs (notably Netgear R7000) silently reclassify packets to ++ * different ACs. Since u-APSD ACs require trigger frames for frame retrieval ++ * clients would never see some frames (e.g. ARP responses) or would fetch them ++ * accidentally after a long time. ++ * ++ * It makes little sense to enable u-APSD queues by default because it needs ++ * userspace applications to be aware of it to actually take advantage of the ++ * possible additional powersavings. Implicitly depending on driver autotrigger ++ * frame support doesn't make much sense. + */ +-#define IEEE80211_DEFAULT_UAPSD_QUEUES \ +- IEEE80211_WMM_IE_STA_QOSINFO_AC_VO ++#define IEEE80211_DEFAULT_UAPSD_QUEUES 0 + + #define IEEE80211_DEFAULT_MAX_SP_LEN \ + IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 815ca56b39e7..9abb445ea261 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2107,6 +2107,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) + hdr = (struct ieee80211_hdr *) skb->data; + mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); + ++ if (ieee80211_drop_unencrypted(rx, hdr->frame_control)) ++ return RX_DROP_MONITOR; ++ + /* frame is in RMC, don't forward */ + if (ieee80211_is_data(hdr->frame_control) && + is_multicast_ether_addr(hdr->addr1) && +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 18d73df72531..c260243dbe07 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -4190,6 +4190,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) + if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) + return -EINVAL; + ++ /* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT ++ * as userspace might just pass through the capabilities from the IEs ++ * directly, rather than enforcing this restriction and returning an ++ * error in this case. ++ */ ++ if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME))) { ++ params.ht_capa = NULL; ++ params.vht_capa = NULL; ++ } ++ + /* When you run into this, adjust the code below for the new flag */ + BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7); + +diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c +index f78b27a7c461..23454e9a5d3a 100644 +--- a/sound/soc/codecs/adav80x.c ++++ b/sound/soc/codecs/adav80x.c +@@ -319,7 +319,7 @@ static int adav80x_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); +- unsigned int deemph = ucontrol->value.enumerated.item[0]; ++ unsigned int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; +@@ -335,7 +335,7 @@ static int adav80x_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = adav80x->deemph; ++ ucontrol->value.integer.value[0] = adav80x->deemph; + return 0; + }; + +diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c +index 94cbe508dd37..d7184726f8a0 100644 +--- a/sound/soc/codecs/ak4641.c ++++ b/sound/soc/codecs/ak4641.c +@@ -76,7 +76,7 @@ static int ak4641_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; +@@ -92,7 +92,7 @@ static int ak4641_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = ak4641->deemph; ++ ucontrol->value.integer.value[0] = ak4641->deemph; + return 0; + }; + +diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c +index ce05fd93dc74..a0ad41ac5574 100644 +--- a/sound/soc/codecs/cs4271.c ++++ b/sound/soc/codecs/cs4271.c +@@ -288,7 +288,7 @@ static int cs4271_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = cs4271->deemph; ++ ucontrol->value.integer.value[0] = cs4271->deemph; + return 0; + } + +@@ -298,7 +298,7 @@ static int cs4271_put_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); + +- cs4271->deemph = ucontrol->value.enumerated.item[0]; ++ cs4271->deemph = ucontrol->value.integer.value[0]; + return cs4271_set_deemph(codec); + } + +diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c +index 73f9c3630e2c..651e2fe2c31f 100644 +--- a/sound/soc/codecs/pcm1681.c ++++ b/sound/soc/codecs/pcm1681.c +@@ -118,7 +118,7 @@ static int pcm1681_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = priv->deemph; ++ ucontrol->value.integer.value[0] = priv->deemph; + + return 0; + } +@@ -129,7 +129,7 @@ static int pcm1681_put_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct pcm1681_private *priv = snd_soc_codec_get_drvdata(codec); + +- priv->deemph = ucontrol->value.enumerated.item[0]; ++ priv->deemph = ucontrol->value.integer.value[0]; + + return pcm1681_set_deemph(codec); + } +diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c +index 715589ff0eda..e93c36fd3073 100644 +--- a/sound/soc/codecs/sgtl5000.c ++++ b/sound/soc/codecs/sgtl5000.c +@@ -1198,13 +1198,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec) + /* Enable VDDC charge pump */ + ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP; + } else if (vddio >= 3100 && vdda >= 3100) { +- /* +- * if vddio and vddd > 3.1v, +- * charge pump should be clean before set ana_pwr +- */ +- snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, +- SGTL5000_VDDC_CHRGPMP_POWERUP, 0); +- ++ ana_pwr &= ~SGTL5000_VDDC_CHRGPMP_POWERUP; + /* VDDC use VDDIO rail */ + lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD; + lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO << +diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c +index a895a5e4bdf2..c6c65001457d 100644 +--- a/sound/soc/codecs/tas5086.c ++++ b/sound/soc/codecs/tas5086.c +@@ -275,7 +275,7 @@ static int tas5086_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = priv->deemph; ++ ucontrol->value.integer.value[0] = priv->deemph; + + return 0; + } +@@ -286,7 +286,7 @@ static int tas5086_put_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); + +- priv->deemph = ucontrol->value.enumerated.item[0]; ++ priv->deemph = ucontrol->value.integer.value[0]; + + return tas5086_set_deemph(codec); + } +diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c +index 8ae50274ea8f..1a9f4574b65b 100644 +--- a/sound/soc/codecs/wm2000.c ++++ b/sound/soc/codecs/wm2000.c +@@ -610,7 +610,7 @@ static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); + +- ucontrol->value.enumerated.item[0] = wm2000->anc_active; ++ ucontrol->value.integer.value[0] = wm2000->anc_active; + + return 0; + } +@@ -620,7 +620,7 @@ static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); +- int anc_active = ucontrol->value.enumerated.item[0]; ++ int anc_active = ucontrol->value.integer.value[0]; + int ret; + + if (anc_active > 1) +@@ -643,7 +643,7 @@ static int wm2000_speaker_get(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); + +- ucontrol->value.enumerated.item[0] = wm2000->spk_ena; ++ ucontrol->value.integer.value[0] = wm2000->spk_ena; + + return 0; + } +@@ -653,7 +653,7 @@ static int wm2000_speaker_put(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); +- int val = ucontrol->value.enumerated.item[0]; ++ int val = ucontrol->value.integer.value[0]; + int ret; + + if (val > 1) +diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c +index 029720366ff8..e593722574de 100644 +--- a/sound/soc/codecs/wm8731.c ++++ b/sound/soc/codecs/wm8731.c +@@ -122,7 +122,7 @@ static int wm8731_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = wm8731->deemph; ++ ucontrol->value.integer.value[0] = wm8731->deemph; + + return 0; + } +@@ -132,7 +132,7 @@ static int wm8731_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + int ret = 0; + + if (deemph > 1) +diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c +index eebcb1da3b7b..ae7d76efe063 100644 +--- a/sound/soc/codecs/wm8903.c ++++ b/sound/soc/codecs/wm8903.c +@@ -442,7 +442,7 @@ static int wm8903_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = wm8903->deemph; ++ ucontrol->value.integer.value[0] = wm8903->deemph; + + return 0; + } +@@ -452,7 +452,7 @@ static int wm8903_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + int ret = 0; + + if (deemph > 1) +diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c +index 53bbfac6a83a..66cb9e95b5eb 100644 +--- a/sound/soc/codecs/wm8904.c ++++ b/sound/soc/codecs/wm8904.c +@@ -523,7 +523,7 @@ static int wm8904_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = wm8904->deemph; ++ ucontrol->value.integer.value[0] = wm8904->deemph; + return 0; + } + +@@ -532,7 +532,7 @@ static int wm8904_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; +diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c +index 82c8ba975720..1c1fc6119758 100644 +--- a/sound/soc/codecs/wm8955.c ++++ b/sound/soc/codecs/wm8955.c +@@ -393,7 +393,7 @@ static int wm8955_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = wm8955->deemph; ++ ucontrol->value.integer.value[0] = wm8955->deemph; + return 0; + } + +@@ -402,7 +402,7 @@ static int wm8955_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; +diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c +index 942ef8427347..2a0bfb848512 100644 +--- a/sound/soc/codecs/wm8960.c ++++ b/sound/soc/codecs/wm8960.c +@@ -181,7 +181,7 @@ static int wm8960_get_deemph(struct snd_kcontrol *kcontrol, + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.enumerated.item[0] = wm8960->deemph; ++ ucontrol->value.integer.value[0] = wm8960->deemph; + return 0; + } + +@@ -190,7 +190,7 @@ static int wm8960_put_deemph(struct snd_kcontrol *kcontrol, + { + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); +- int deemph = ucontrol->value.enumerated.item[0]; ++ int deemph = ucontrol->value.integer.value[0]; + + if (deemph > 1) + return -EINVAL; +diff --git a/sound/soc/jz4740/Makefile b/sound/soc/jz4740/Makefile +index be873c1b0c20..d32c540555c4 100644 +--- a/sound/soc/jz4740/Makefile ++++ b/sound/soc/jz4740/Makefile +@@ -1,10 +1,8 @@ + # + # Jz4740 Platform Support + # +-snd-soc-jz4740-objs := jz4740-pcm.o + snd-soc-jz4740-i2s-objs := jz4740-i2s.o + +-obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o + obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o + + # Jz4740 Machine Support diff --git a/patch/kernel/neo-patch-3.14.38-39 b/patch/kernel/neo-patch-3.14.38-39 new file mode 100644 index 000000000..181872fd9 --- /dev/null +++ b/patch/kernel/neo-patch-3.14.38-39 @@ -0,0 +1,1101 @@ +diff --git a/Makefile b/Makefile +index f09e19d2cc4f..b40845e11b84 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 14 +-SUBLEVEL = 38 ++SUBLEVEL = 39 + EXTRAVERSION = + NAME = Remembering Coco + +diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c +index 7e95e1a86510..d68b410595c8 100644 +--- a/arch/arc/kernel/signal.c ++++ b/arch/arc/kernel/signal.c +@@ -67,7 +67,7 @@ stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs, + sigset_t *set) + { + int err; +- err = __copy_to_user(&(sf->uc.uc_mcontext.regs), regs, ++ err = __copy_to_user(&(sf->uc.uc_mcontext.regs.scratch), regs, + sizeof(sf->uc.uc_mcontext.regs.scratch)); + err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t)); + +@@ -83,7 +83,7 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf) + if (!err) + set_current_blocked(&set); + +- err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs), ++ err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs.scratch), + sizeof(sf->uc.uc_mcontext.regs.scratch)); + + return err; +diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c +index c752cb43e52f..a6aa91f77654 100644 +--- a/arch/x86/kernel/reboot.c ++++ b/arch/x86/kernel/reboot.c +@@ -181,6 +181,16 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { + }, + }, + ++ /* ASRock */ ++ { /* Handle problems with rebooting on ASRock Q1900DC-ITX */ ++ .callback = set_pci_reboot, ++ .ident = "ASRock Q1900DC-ITX", ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "ASRock"), ++ DMI_MATCH(DMI_BOARD_NAME, "Q1900DC-ITX"), ++ }, ++ }, ++ + /* ASUS */ + { /* Handle problems with rebooting on ASUS P4S800 */ + .callback = set_bios_reboot, +diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c +index 17f9ec501972..fd8496a92b45 100644 +--- a/drivers/acpi/processor_idle.c ++++ b/drivers/acpi/processor_idle.c +@@ -962,7 +962,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) + return -EINVAL; + + drv->safe_state_index = -1; +- for (i = 0; i < CPUIDLE_STATE_MAX; i++) { ++ for (i = CPUIDLE_DRIVER_STATE_START; i < CPUIDLE_STATE_MAX; i++) { + drv->states[i].name[0] = '\0'; + drv->states[i].desc[0] = '\0'; + } +diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c +index 55298db36b2d..d18093681af2 100644 +--- a/drivers/block/nbd.c ++++ b/drivers/block/nbd.c +@@ -814,10 +814,6 @@ static int __init nbd_init(void) + return -EINVAL; + } + +- nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL); +- if (!nbd_dev) +- return -ENOMEM; +- + part_shift = 0; + if (max_part > 0) { + part_shift = fls(max_part); +@@ -839,6 +835,10 @@ static int __init nbd_init(void) + if (nbds_max > 1UL << (MINORBITS - part_shift)) + return -EINVAL; + ++ nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL); ++ if (!nbd_dev) ++ return -ENOMEM; ++ + for (i = 0; i < nbds_max; i++) { + struct gendisk *disk = alloc_disk(1 << part_shift); + if (!disk) +diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c +index a55e68f2cfc8..e3d2052e7552 100644 +--- a/drivers/cpuidle/cpuidle.c ++++ b/drivers/cpuidle/cpuidle.c +@@ -252,9 +252,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev) + if (!dev->registered) + return -EINVAL; + +- if (!dev->state_count) +- dev->state_count = drv->state_count; +- + ret = cpuidle_add_device_sysfs(dev); + if (ret) + return ret; +diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c +index e918b6d0caf7..dcaae4c8bc08 100644 +--- a/drivers/cpuidle/sysfs.c ++++ b/drivers/cpuidle/sysfs.c +@@ -398,7 +398,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) + struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); + + /* state statistics */ +- for (i = 0; i < device->state_count; i++) { ++ for (i = 0; i < drv->state_count; i++) { + kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL); + if (!kobj) + goto error_state; +@@ -430,9 +430,10 @@ error_state: + */ + static void cpuidle_remove_state_sysfs(struct cpuidle_device *device) + { ++ struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); + int i; + +- for (i = 0; i < device->state_count; i++) ++ for (i = 0; i < drv->state_count; i++) + cpuidle_free_state_kobj(device, i); + } + +diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c +index 362e7c49f2e1..12f82942e347 100644 +--- a/drivers/dma/omap-dma.c ++++ b/drivers/dma/omap-dma.c +@@ -487,6 +487,7 @@ static int omap_dma_terminate_all(struct omap_chan *c) + * c->desc is NULL and exit.) + */ + if (c->desc) { ++ omap_dma_desc_free(&c->desc->vd); + c->desc = NULL; + /* Avoid stopping the dma twice */ + if (!c->paused) +diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c +index 9ab30976287d..c43335ce8778 100644 +--- a/drivers/gpu/drm/radeon/radeon_bios.c ++++ b/drivers/gpu/drm/radeon/radeon_bios.c +@@ -76,7 +76,7 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev) + + static bool radeon_read_bios(struct radeon_device *rdev) + { +- uint8_t __iomem *bios; ++ uint8_t __iomem *bios, val1, val2; + size_t size; + + rdev->bios = NULL; +@@ -86,15 +86,19 @@ static bool radeon_read_bios(struct radeon_device *rdev) + return false; + } + +- if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { ++ val1 = readb(&bios[0]); ++ val2 = readb(&bios[1]); ++ ++ if (size == 0 || val1 != 0x55 || val2 != 0xaa) { + pci_unmap_rom(rdev->pdev, bios); + return false; + } +- rdev->bios = kmemdup(bios, size, GFP_KERNEL); ++ rdev->bios = kzalloc(size, GFP_KERNEL); + if (rdev->bios == NULL) { + pci_unmap_rom(rdev->pdev, bios); + return false; + } ++ memcpy_fromio(rdev->bios, bios, size); + pci_unmap_rom(rdev->pdev, bios); + return true; + } +diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c +index e0017c22bb9c..f53e9a803a0e 100644 +--- a/drivers/iio/imu/adis_trigger.c ++++ b/drivers/iio/imu/adis_trigger.c +@@ -60,7 +60,7 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) + iio_trigger_set_drvdata(adis->trig, adis); + ret = iio_trigger_register(adis->trig); + +- indio_dev->trig = adis->trig; ++ indio_dev->trig = iio_trigger_get(adis->trig); + if (ret) + goto error_free_irq; + +diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +index 429517117eff..30fce6723e61 100644 +--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c ++++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +@@ -25,6 +25,16 @@ + #include + #include "inv_mpu_iio.h" + ++static void inv_clear_kfifo(struct inv_mpu6050_state *st) ++{ ++ unsigned long flags; ++ ++ /* take the spin lock sem to avoid interrupt kick in */ ++ spin_lock_irqsave(&st->time_stamp_lock, flags); ++ kfifo_reset(&st->timestamps); ++ spin_unlock_irqrestore(&st->time_stamp_lock, flags); ++} ++ + int inv_reset_fifo(struct iio_dev *indio_dev) + { + int result; +@@ -51,6 +61,10 @@ int inv_reset_fifo(struct iio_dev *indio_dev) + INV_MPU6050_BIT_FIFO_RST); + if (result) + goto reset_fifo_fail; ++ ++ /* clear timestamps fifo */ ++ inv_clear_kfifo(st); ++ + /* enable interrupt */ + if (st->chip_config.accl_fifo_enable || + st->chip_config.gyro_fifo_enable) { +@@ -84,16 +98,6 @@ reset_fifo_fail: + return result; + } + +-static void inv_clear_kfifo(struct inv_mpu6050_state *st) +-{ +- unsigned long flags; +- +- /* take the spin lock sem to avoid interrupt kick in */ +- spin_lock_irqsave(&st->time_stamp_lock, flags); +- kfifo_reset(&st->timestamps); +- spin_unlock_irqrestore(&st->time_stamp_lock, flags); +-} +- + /** + * inv_mpu6050_irq_handler() - Cache a timestamp at each data ready interrupt. + */ +@@ -185,7 +189,6 @@ end_session: + flush_fifo: + /* Flush HW and SW FIFOs. */ + inv_reset_fifo(indio_dev); +- inv_clear_kfifo(st); + mutex_unlock(&indio_dev->mlock); + iio_trigger_notify_done(indio_dev->trig); + +diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c +index a84112322071..055ebebc07dd 100644 +--- a/drivers/infiniband/core/umem.c ++++ b/drivers/infiniband/core/umem.c +@@ -94,6 +94,14 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, + if (dmasync) + dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs); + ++ /* ++ * If the combination of the addr and size requested for this memory ++ * region causes an integer overflow, return error. ++ */ ++ if ((PAGE_ALIGN(addr + size) <= size) || ++ (PAGE_ALIGN(addr + size) <= addr)) ++ return ERR_PTR(-EINVAL); ++ + if (!can_do_mlock()) + return ERR_PTR(-EPERM); + +diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c +index 08219fb3338b..7a515c867674 100644 +--- a/drivers/infiniband/core/uverbs_main.c ++++ b/drivers/infiniband/core/uverbs_main.c +@@ -476,6 +476,7 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file, + + entry->desc.async.element = element; + entry->desc.async.event_type = event; ++ entry->desc.async.reserved = 0; + entry->counter = counter; + + list_add_tail(&entry->list, &file->async_file->event_list); +diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c +index f2a3f48107e7..2592ab5f21b1 100644 +--- a/drivers/infiniband/hw/mlx4/mad.c ++++ b/drivers/infiniband/hw/mlx4/mad.c +@@ -64,6 +64,14 @@ enum { + #define GUID_TBL_BLK_NUM_ENTRIES 8 + #define GUID_TBL_BLK_SIZE (GUID_TBL_ENTRY_SIZE * GUID_TBL_BLK_NUM_ENTRIES) + ++/* Counters should be saturate once they reach their maximum value */ ++#define ASSIGN_32BIT_COUNTER(counter, value) do {\ ++ if ((value) > U32_MAX) \ ++ counter = cpu_to_be32(U32_MAX); \ ++ else \ ++ counter = cpu_to_be32(value); \ ++} while (0) ++ + struct mlx4_mad_rcv_buf { + struct ib_grh grh; + u8 payload[256]; +@@ -730,10 +738,14 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, + static void edit_counter(struct mlx4_counter *cnt, + struct ib_pma_portcounters *pma_cnt) + { +- pma_cnt->port_xmit_data = cpu_to_be32((be64_to_cpu(cnt->tx_bytes)>>2)); +- pma_cnt->port_rcv_data = cpu_to_be32((be64_to_cpu(cnt->rx_bytes)>>2)); +- pma_cnt->port_xmit_packets = cpu_to_be32(be64_to_cpu(cnt->tx_frames)); +- pma_cnt->port_rcv_packets = cpu_to_be32(be64_to_cpu(cnt->rx_frames)); ++ ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_data, ++ (be64_to_cpu(cnt->tx_bytes) >> 2)); ++ ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_data, ++ (be64_to_cpu(cnt->rx_bytes) >> 2)); ++ ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_packets, ++ be64_to_cpu(cnt->tx_frames)); ++ ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_packets, ++ be64_to_cpu(cnt->rx_frames)); + } + + static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, +diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +index f723f1f2f578..ab851278d9d0 100644 +--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h ++++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h +@@ -30,7 +30,7 @@ + + /* Offset base used to differentiate between CAPTURE and OUTPUT + * while mmaping */ +-#define DST_QUEUE_OFF_BASE (TASK_SIZE / 2) ++#define DST_QUEUE_OFF_BASE (1 << 30) + + #define MFC_BANK1_ALLOC_CTX 0 + #define MFC_BANK2_ALLOC_CTX 1 +diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c +index 744e43b480bc..f698e322a1cd 100644 +--- a/drivers/media/platform/sh_veu.c ++++ b/drivers/media/platform/sh_veu.c +@@ -1183,6 +1183,7 @@ static int sh_veu_probe(struct platform_device *pdev) + } + + *vdev = sh_veu_videodev; ++ vdev->v4l2_dev = &veu->v4l2_dev; + spin_lock_init(&veu->lock); + mutex_init(&veu->fop_lock); + vdev->lock = &veu->fop_lock; +diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c +index 61376abdab39..dbd8d21a8f10 100644 +--- a/drivers/net/can/flexcan.c ++++ b/drivers/net/can/flexcan.c +@@ -1196,6 +1196,7 @@ + const struct flexcan_devtype_data *devtype_data; + struct net_device *dev; + struct flexcan_priv *priv; ++ struct regulator *reg_xceiver; + struct resource *mem; + struct clk *clk_ipg = NULL, *clk_per = NULL; + void __iomem *base; +@@ -1203,6 +1204,12 @@ + u32 clock_freq = 0; + int wakeup = 1; + ++ reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver"); ++ if (PTR_ERR(reg_xceiver) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ else if (IS_ERR(reg_xceiver)) ++ reg_xceiver = NULL; ++ + if (pdev->dev.of_node) + of_property_read_u32(pdev->dev.of_node, + "clock-frequency", &clock_freq); +@@ -1162,9 +1169,7 @@ static int flexcan_probe(struct platform_device *pdev) + priv->pdata = dev_get_platdata(&pdev->dev); + priv->devtype_data = devtype_data; + +- priv->reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver"); +- if (IS_ERR(priv->reg_xceiver)) +- priv->reg_xceiver = NULL; ++ priv->reg_xceiver = reg_xceiver; + + netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT); + +diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h +index 3441f70d0ff9..6e8cdb8a0cc5 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/dev.h ++++ b/drivers/net/wireless/iwlwifi/dvm/dev.h +@@ -708,7 +708,6 @@ struct iwl_priv { + unsigned long reload_jiffies; + int reload_count; + bool ucode_loaded; +- bool init_ucode_run; /* Don't run init uCode again */ + + u8 plcp_delta_threshold; + +diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c +index cf03ef5619d9..8b2dedc30159 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/ucode.c ++++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c +@@ -418,9 +418,6 @@ int iwl_run_init_ucode(struct iwl_priv *priv) + if (!priv->fw->img[IWL_UCODE_INIT].sec[0].len) + return 0; + +- if (priv->init_ucode_run) +- return 0; +- + iwl_init_notification_wait(&priv->notif_wait, &calib_wait, + calib_complete, ARRAY_SIZE(calib_complete), + iwlagn_wait_calib, priv); +@@ -440,8 +437,6 @@ int iwl_run_init_ucode(struct iwl_priv *priv) + */ + ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, + UCODE_CALIB_TIMEOUT); +- if (!ret) +- priv->init_ucode_run = true; + + goto out; + +diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c +index 34ff7026440c..5d3b45640181 100644 +--- a/drivers/pci/pcie/aer/aerdrv_errprint.c ++++ b/drivers/pci/pcie/aer/aerdrv_errprint.c +@@ -127,16 +127,8 @@ static const char *aer_agent_string[] = { + static void __print_tlp_header(struct pci_dev *dev, + struct aer_header_log_regs *t) + { +- unsigned char *tlp = (unsigned char *)&t; +- +- dev_err(&dev->dev, " TLP Header:" +- " %02x%02x%02x%02x %02x%02x%02x%02x" +- " %02x%02x%02x%02x %02x%02x%02x%02x\n", +- *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, +- *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), +- *(tlp + 11), *(tlp + 10), *(tlp + 9), +- *(tlp + 8), *(tlp + 15), *(tlp + 14), +- *(tlp + 13), *(tlp + 12)); ++ dev_err(&dev->dev, " TLP Header: %08x %08x %08x %08x\n", ++ t->dw0, t->dw1, t->dw2, t->dw3); + } + + static void __aer_print_error(struct pci_dev *dev, +diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c +index 953bd0bfdf0d..19ddd43a00cf 100644 +--- a/drivers/scsi/be2iscsi/be_main.c ++++ b/drivers/scsi/be2iscsi/be_main.c +@@ -5684,9 +5684,9 @@ free_port: + hba_free: + if (phba->msix_enabled) + pci_disable_msix(phba->pcidev); +- iscsi_host_remove(phba->shost); + pci_dev_put(phba->pcidev); + iscsi_host_free(phba->shost); ++ pci_set_drvdata(pcidev, NULL); + disable_pci: + pci_disable_device(pcidev); + return ret; +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index 64e487a8bf59..719bd8257520 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -1258,9 +1258,11 @@ int scsi_prep_state_check(struct scsi_device *sdev, struct request *req) + "rejecting I/O to dead device\n"); + ret = BLKPREP_KILL; + break; +- case SDEV_QUIESCE: + case SDEV_BLOCK: + case SDEV_CREATED_BLOCK: ++ ret = BLKPREP_DEFER; ++ break; ++ case SDEV_QUIESCE: + /* + * If the devices is blocked we defer normal commands. + */ +diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c +index e168a63e77ea..b61c555a5a8f 100644 +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -1165,7 +1165,7 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, + * traditional iSCSI block I/O. + */ + if (iscsit_allocate_iovecs(cmd) < 0) { +- return iscsit_add_reject_cmd(cmd, ++ return iscsit_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); + } + immed_data = cmd->immediate_data; +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index 850e232d086e..8ab46ad40f28 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -247,8 +247,6 @@ static void n_tty_write_wakeup(struct tty_struct *tty) + + static void n_tty_check_throttle(struct tty_struct *tty) + { +- if (tty->driver->type == TTY_DRIVER_TYPE_PTY) +- return; + /* + * Check the remaining room for the input canonicalization + * mode. We don't want to throttle the driver if we're in +@@ -1512,23 +1510,6 @@ n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag) + n_tty_receive_char_flagged(tty, c, flag); + } + +-/** +- * n_tty_receive_buf - data receive +- * @tty: terminal device +- * @cp: buffer +- * @fp: flag buffer +- * @count: characters +- * +- * Called by the terminal driver when a block of characters has +- * been received. This function must be called from soft contexts +- * not from interrupt context. The driver is responsible for making +- * calls one at a time and in order (or using flush_to_ldisc) +- * +- * n_tty_receive_buf()/producer path: +- * claims non-exclusive termios_rwsem +- * publishes read_head and canon_head +- */ +- + static void + n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count) +@@ -1684,24 +1665,85 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, + } + } + ++/** ++ * n_tty_receive_buf_common - process input ++ * @tty: device to receive input ++ * @cp: input chars ++ * @fp: flags for each char (if NULL, all chars are TTY_NORMAL) ++ * @count: number of input chars in @cp ++ * ++ * Called by the terminal driver when a block of characters has ++ * been received. This function must be called from soft contexts ++ * not from interrupt context. The driver is responsible for making ++ * calls one at a time and in order (or using flush_to_ldisc) ++ * ++ * Returns the # of input chars from @cp which were processed. ++ * ++ * In canonical mode, the maximum line length is 4096 chars (including ++ * the line termination char); lines longer than 4096 chars are ++ * truncated. After 4095 chars, input data is still processed but ++ * not stored. Overflow processing ensures the tty can always ++ * receive more input until at least one line can be read. ++ * ++ * In non-canonical mode, the read buffer will only accept 4095 chars; ++ * this provides the necessary space for a newline char if the input ++ * mode is switched to canonical. ++ * ++ * Note it is possible for the read buffer to _contain_ 4096 chars ++ * in non-canonical mode: the read buffer could already contain the ++ * maximum canon line of 4096 chars when the mode is switched to ++ * non-canonical. ++ * ++ * n_tty_receive_buf()/producer path: ++ * claims non-exclusive termios_rwsem ++ * publishes commit_head or canon_head ++ */ + static int + n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count, int flow) + { + struct n_tty_data *ldata = tty->disc_data; +- int room, n, rcvd = 0; ++ int room, n, rcvd = 0, overflow; + + down_read(&tty->termios_rwsem); + + while (1) { +- room = receive_room(tty); ++ /* ++ * When PARMRK is set, each input char may take up to 3 chars ++ * in the read buf; reduce the buffer space avail by 3x ++ * ++ * If we are doing input canonicalization, and there are no ++ * pending newlines, let characters through without limit, so ++ * that erase characters will be handled. Other excess ++ * characters will be beeped. ++ * ++ * paired with store in *_copy_from_read_buf() -- guarantees ++ * the consumer has loaded the data in read_buf up to the new ++ * read_tail (so this producer will not overwrite unread data) ++ */ ++ size_t tail = ldata->read_tail; ++ ++ room = N_TTY_BUF_SIZE - (ldata->read_head - tail); ++ if (I_PARMRK(tty)) ++ room = (room + 2) / 3; ++ room--; ++ if (room <= 0) { ++ overflow = ldata->icanon && ldata->canon_head == tail; ++ if (overflow && room < 0) ++ ldata->read_head--; ++ room = overflow; ++ ldata->no_room = flow && !room; ++ } else ++ overflow = 0; ++ + n = min(count, room); +- if (!n) { +- if (flow && !room) +- ldata->no_room = 1; ++ if (!n) + break; +- } +- __receive_buf(tty, cp, fp, n); ++ ++ /* ignore parity errors if handling overflow */ ++ if (!overflow || !fp || *fp != TTY_PARITY) ++ __receive_buf(tty, cp, fp, n); ++ + cp += n; + if (fp) + fp += n; +@@ -1710,7 +1752,17 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, + } + + tty->receive_room = room; +- n_tty_check_throttle(tty); ++ ++ /* Unthrottle if handling overflow on pty */ ++ if (tty->driver->type == TTY_DRIVER_TYPE_PTY) { ++ if (overflow) { ++ tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE); ++ tty_unthrottle_safe(tty); ++ __tty_set_flow_change(tty, 0); ++ } ++ } else ++ n_tty_check_throttle(tty); ++ + up_read(&tty->termios_rwsem); + + return rcvd; +diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c +index 175f123f4f09..501c465feb59 100644 +--- a/drivers/tty/serial/fsl_lpuart.c ++++ b/drivers/tty/serial/fsl_lpuart.c +@@ -362,6 +362,9 @@ static void lpuart_setup_watermark(struct lpuart_port *sport) + writeb(val | UARTPFIFO_TXFE | UARTPFIFO_RXFE, + sport->port.membase + UARTPFIFO); + ++ /* explicitly clear RDRF */ ++ readb(sport->port.membase + UARTSR1); ++ + /* flush Tx and Rx FIFO */ + writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH, + sport->port.membase + UARTCFIFO); +diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c +index 93fe089cd51a..b9e16abb0fab 100644 +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -383,6 +383,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, + status = PORT_PLC; + port_change_bit = "link state"; + break; ++ case USB_PORT_FEAT_C_PORT_CONFIG_ERROR: ++ status = PORT_CEC; ++ port_change_bit = "config error"; ++ break; + default: + /* Should never happen */ + return; +@@ -584,6 +588,8 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, + status |= USB_PORT_STAT_C_LINK_STATE << 16; + if ((raw_port_status & PORT_WRC)) + status |= USB_PORT_STAT_C_BH_RESET << 16; ++ if ((raw_port_status & PORT_CEC)) ++ status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; + } + + if (hcd->speed != HCD_USB3) { +@@ -999,6 +1005,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + case USB_PORT_FEAT_C_OVER_CURRENT: + case USB_PORT_FEAT_C_ENABLE: + case USB_PORT_FEAT_C_PORT_LINK_STATE: ++ case USB_PORT_FEAT_C_PORT_CONFIG_ERROR: + xhci_clear_port_change_bit(xhci, wValue, wIndex, + port_array[wIndex], temp); + break; +@@ -1063,7 +1070,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) + */ + status = bus_state->resuming_ports; + +- mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC; ++ mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC | PORT_CEC; + + spin_lock_irqsave(&xhci->lock, flags); + /* For each port, did anything change? If so, set that bit in buf. */ +diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c +index 73c43e5e231b..eb3399f4c1ed 100644 +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -108,6 +108,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + if (pdev->vendor == PCI_VENDOR_ID_INTEL) { + xhci->quirks |= XHCI_LPM_SUPPORT; + xhci->quirks |= XHCI_INTEL_HOST; ++ xhci->quirks |= XHCI_AVOID_BEI; + } + if (pdev->vendor == PCI_VENDOR_ID_INTEL && + pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) { +@@ -123,7 +124,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + * PPT chipsets. + */ + xhci->quirks |= XHCI_SPURIOUS_REBOOT; +- xhci->quirks |= XHCI_AVOID_BEI; + } + if (pdev->vendor == PCI_VENDOR_ID_INTEL && + (pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI || +diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c +index 923500595357..2d858f81ab33 100644 +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -617,6 +617,7 @@ static const struct usb_device_id id_table_combined[] = { + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, ++ { USB_DEVICE(FTDI_VID, FTDI_SYNAPSE_SS200_PID) }, + /* + * ELV devices: + */ +@@ -1901,8 +1902,12 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial) + { + struct usb_device *udev = serial->dev; + +- if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) || +- (udev->product && !strcmp(udev->product, "BeagleBone/XDS100V2"))) ++ if (udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ++ return ftdi_jtag_probe(serial); ++ ++ if (udev->product && ++ (!strcmp(udev->product, "BeagleBone/XDS100V2") || ++ !strcmp(udev->product, "SNAP Connect E10"))) + return ftdi_jtag_probe(serial); + + return 0; +diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h +index 56b1b55c4751..4e4f46f3c89c 100644 +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -561,6 +561,12 @@ + */ + #define FTDI_NT_ORIONLXM_PID 0x7c90 /* OrionLXm Substation Automation Platform */ + ++/* ++ * Synapse Wireless product ids (FTDI_VID) ++ * http://www.synapse-wireless.com ++ */ ++#define FTDI_SYNAPSE_SS200_PID 0x9090 /* SS200 - SNAP Stick 200 */ ++ + + /********************************/ + /** third-party VID/PID combos **/ +diff --git a/fs/aio.c b/fs/aio.c +index 2f7e8c2e3e76..3241659491b1 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -719,6 +719,9 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) + err_cleanup: + aio_nr_sub(ctx->max_reqs); + err_ctx: ++ atomic_set(&ctx->dead, 1); ++ if (ctx->mmap_size) ++ vm_munmap(ctx->mmap_base, ctx->mmap_size); + aio_free_ring(ctx); + err: + mutex_unlock(&ctx->ring_lock); +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index a7f32bfdd5e7..ec8b6542c8bd 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -1235,21 +1235,13 @@ out: + } + + static int insert_orphan_item(struct btrfs_trans_handle *trans, +- struct btrfs_root *root, u64 offset) ++ struct btrfs_root *root, u64 ino) + { + int ret; +- struct btrfs_path *path; +- +- path = btrfs_alloc_path(); +- if (!path) +- return -ENOMEM; + +- ret = btrfs_find_item(root, path, BTRFS_ORPHAN_OBJECTID, +- offset, BTRFS_ORPHAN_ITEM_KEY, NULL); +- if (ret > 0) +- ret = btrfs_insert_orphan_item(trans, root, offset); +- +- btrfs_free_path(path); ++ ret = btrfs_insert_orphan_item(trans, root, ino); ++ if (ret == -EEXIST) ++ ret = 0; + + return ret; + } +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index 0218a9b23b38..40ddb6e93912 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -1821,6 +1821,7 @@ refind_writable: + cifsFileInfo_put(inv_file); + spin_lock(&cifs_file_list_lock); + ++refind; ++ inv_file = NULL; + goto refind_writable; + } + } +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 34a17d425be6..30f3eb5bc022 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -630,7 +630,8 @@ smb2_clone_range(const unsigned int xid, + + /* No need to change MaxChunks since already set to 1 */ + chunk_sizes_updated = true; +- } ++ } else ++ goto cchunk_out; + } + + cchunk_out: +diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c +index 51632c40e896..7fe30f655aa5 100644 +--- a/fs/ocfs2/file.c ++++ b/fs/ocfs2/file.c +@@ -2391,10 +2391,14 @@ out_dio: + /* buffered aio wouldn't have proper lock coverage today */ + BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); + ++ if (unlikely(written <= 0)) ++ goto no_sync; ++ + if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) || + ((file->f_flags & O_DIRECT) && !direct_io)) { +- ret = filemap_fdatawrite_range(file->f_mapping, *ppos, +- *ppos + count - 1); ++ ret = filemap_fdatawrite_range(file->f_mapping, ++ iocb->ki_pos - written, ++ iocb->ki_pos - 1); + if (ret < 0) + written = ret; + +@@ -2407,10 +2411,12 @@ out_dio: + } + + if (!ret) +- ret = filemap_fdatawait_range(file->f_mapping, *ppos, +- *ppos + count - 1); ++ ret = filemap_fdatawait_range(file->f_mapping, ++ iocb->ki_pos - written, ++ iocb->ki_pos - 1); + } + ++no_sync: + /* + * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io + * function pointer which is called when o_direct io completes so that +diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h +index bbc3a6c88fce..33fd7ff53a77 100644 +--- a/include/linux/blk_types.h ++++ b/include/linux/blk_types.h +@@ -180,7 +180,9 @@ enum rq_flag_bits { + __REQ_ELVPRIV, /* elevator private data attached */ + __REQ_FAILED, /* set if the request failed */ + __REQ_QUIET, /* don't worry about errors */ +- __REQ_PREEMPT, /* set for "ide_preempt" requests */ ++ __REQ_PREEMPT, /* set for "ide_preempt" requests and also ++ for requests for which the SCSI "quiesce" ++ state must be ignored. */ + __REQ_ALLOCED, /* request came from our alloc pool */ + __REQ_COPY_USER, /* contains copies of user pages */ + __REQ_FLUSH_SEQ, /* request for flush sequence */ +diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h +index 50fcbb0ac4e7..d1338170b6b9 100644 +--- a/include/linux/cpuidle.h ++++ b/include/linux/cpuidle.h +@@ -69,7 +69,6 @@ struct cpuidle_device { + unsigned int cpu; + + int last_residency; +- int state_count; + struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX]; + struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX]; + struct cpuidle_driver_kobj *kobj_driver; +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 9a3f3c4e1f5a..5e973efc036e 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -2980,6 +2980,8 @@ void rt_mutex_setprio(struct task_struct *p, int prio) + } else { + if (dl_prio(oldprio)) + p->dl.dl_boosted = 0; ++ if (rt_prio(oldprio)) ++ p->rt.timeout = 0; + p->sched_class = &fair_sched_class; + } + +diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c +index f6f23833de44..c8e450132813 100644 +--- a/mm/memory_hotplug.c ++++ b/mm/memory_hotplug.c +@@ -1016,6 +1016,10 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start) + return NULL; + + arch_refresh_nodedata(nid, pgdat); ++ } else { ++ /* Reset the nr_zones and classzone_idx to 0 before reuse */ ++ pgdat->nr_zones = 0; ++ pgdat->classzone_idx = 0; + } + + /* we can use NODE_DATA(nid) from here */ +@@ -1863,15 +1867,6 @@ void try_offline_node(int nid) + if (is_vmalloc_addr(zone->wait_table)) + vfree(zone->wait_table); + } +- +- /* +- * Since there is no way to guarentee the address of pgdat/zone is not +- * on stack of any kernel threads or used by other kernel objects +- * without reference counting or other symchronizing method, do not +- * reset node_data and free pgdat here. Just reset it to 0 and reuse +- * the memory when the node is online again. +- */ +- memset(pgdat, 0, sizeof(*pgdat)); + } + EXPORT_SYMBOL(try_offline_node); + +diff --git a/mm/page-writeback.c b/mm/page-writeback.c +index 9f45f87a5859..51d8d15f48d7 100644 +--- a/mm/page-writeback.c ++++ b/mm/page-writeback.c +@@ -878,8 +878,11 @@ static void bdi_update_write_bandwidth(struct backing_dev_info *bdi, + * bw * elapsed + write_bandwidth * (period - elapsed) + * write_bandwidth = --------------------------------------------------- + * period ++ * ++ * @written may have decreased due to account_page_redirty(). ++ * Avoid underflowing @bw calculation. + */ +- bw = written - bdi->written_stamp; ++ bw = written - min(written, bdi->written_stamp); + bw *= HZ; + if (unlikely(elapsed > period)) { + do_div(bw, elapsed); +@@ -943,7 +946,7 @@ static void global_update_bandwidth(unsigned long thresh, + unsigned long now) + { + static DEFINE_SPINLOCK(dirty_lock); +- static unsigned long update_time; ++ static unsigned long update_time = INITIAL_JIFFIES; + + /* + * check locklessly first to optimize away locking for the most time +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index d0c310801479..96f64e59d70c 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -2933,6 +2933,7 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) + goto fallback; + syn_data->ip_summed = CHECKSUM_PARTIAL; + memcpy(syn_data->cb, syn->cb, sizeof(syn->cb)); ++ skb_shinfo(syn_data)->gso_segs = 1; + if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space), + fo->data->msg_iov, 0, space))) { + kfree_skb(syn_data); +diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c +index 612a5ddaf93b..799bafc2af39 100644 +--- a/net/llc/sysctl_net_llc.c ++++ b/net/llc/sysctl_net_llc.c +@@ -18,28 +18,28 @@ static struct ctl_table llc2_timeout_table[] = { + { + .procname = "ack", + .data = &sysctl_llc2_ack_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_ack_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "busy", + .data = &sysctl_llc2_busy_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_busy_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "p", + .data = &sysctl_llc2_p_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_p_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "rej", + .data = &sysctl_llc2_rej_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_rej_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, +diff --git a/net/rds/sysctl.c b/net/rds/sysctl.c +index b5cb2aa08f33..35773ad6d23d 100644 +--- a/net/rds/sysctl.c ++++ b/net/rds/sysctl.c +@@ -71,14 +71,14 @@ static struct ctl_table rds_sysctl_rds_table[] = { + { + .procname = "max_unacked_packets", + .data = &rds_sysctl_max_unacked_packets, +- .maxlen = sizeof(unsigned long), ++ .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "max_unacked_bytes", + .data = &rds_sysctl_max_unacked_bytes, +- .maxlen = sizeof(unsigned long), ++ .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, +diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c +index d60c0ee66387..6c4cbd97a673 100644 +--- a/security/selinux/selinuxfs.c ++++ b/security/selinux/selinuxfs.c +@@ -152,7 +152,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, + goto out; + + /* No partial writes. */ +- length = EINVAL; ++ length = -EINVAL; + if (*ppos != 0) + goto out; + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 910f2dbe1b24..ca26373ebe70 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -271,7 +271,7 @@ static void alc_auto_setup_eapd(struct hda_codec *codec, bool on) + { + /* We currently only handle front, HP */ + static hda_nid_t pins[] = { +- 0x0f, 0x10, 0x14, 0x15, 0 ++ 0x0f, 0x10, 0x14, 0x15, 0x17, 0 + }; + hda_nid_t *p; + for (p = pins; *p; p++) +@@ -2885,6 +2885,8 @@ static void alc283_init(struct hda_codec *codec) + + if (!hp_pin) + return; ++ ++ msleep(30); + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + + /* Index 0x43 Direct Drive HP AMP LPM Control 1 */ +@@ -3951,6 +3953,7 @@ enum { + ALC269_FIXUP_QUANTA_MUTE, + ALC269_FIXUP_LIFEBOOK, + ALC269_FIXUP_LIFEBOOK_EXTMIC, ++ ALC269_FIXUP_LIFEBOOK_HP_PIN, + ALC269_FIXUP_AMIC, + ALC269_FIXUP_DMIC, + ALC269VB_FIXUP_AMIC, +@@ -4085,6 +4088,13 @@ static const struct hda_fixup alc269_fixups[] = { + { } + }, + }, ++ [ALC269_FIXUP_LIFEBOOK_HP_PIN] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x21, 0x0221102f }, /* HP out */ ++ { } ++ }, ++ }, + [ALC269_FIXUP_AMIC] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { +@@ -4538,6 +4548,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), + SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), + SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK), ++ SND_PCI_QUIRK(0x10cf, 0x15dc, "Lifebook T731", ALC269_FIXUP_LIFEBOOK_HP_PIN), + SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), + SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), +diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c +index 5a723df670b4..a82ec53b8fb3 100644 +--- a/sound/usb/mixer_quirks.c ++++ b/sound/usb/mixer_quirks.c +@@ -178,6 +178,7 @@ static const struct rc_config { + { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ + { USB_ID(0x041e, 0x3042), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 */ + { USB_ID(0x041e, 0x30df), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */ ++ { USB_ID(0x041e, 0x3237), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */ + { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ + }; + diff --git a/patch/kernel/old-h3-7458441.patch b/patch/kernel/old-h3-7458441.patch new file mode 100644 index 000000000..69585f3a4 --- /dev/null +++ b/patch/kernel/old-h3-7458441.patch @@ -0,0 +1,226 @@ +From patchwork Wed Oct 21 16:13:23 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [2/6] clk: sunxi: Add H3 clocks support +From: Jens Kuske +X-Patchwork-Id: 7458441 +Message-Id: <1445444007-4260-3-git-send-email-jenskuske@gmail.com> +To: Maxime Ripard , + Chen-Yu Tsai , Mike Turquette , + Linus Walleij , + Rob Herring , Philipp Zabel , + =?UTF-8?q?Emilio=20L=C3=B3pez?= +Cc: devicetree@vger.kernel.org, Vishnu Patekar , + linux-kernel@vger.kernel.org, Hans de Goede , + linux-sunxi@googlegroups.com, Jens Kuske , + linux-arm-kernel@lists.infradead.org +Date: Wed, 21 Oct 2015 18:13:23 +0200 + +The H3 clock control unit is similar to the those of other sun8i family +members like the A23. + +It adds a new bus gates clock similar to the simple gates, but with a +different parent clock for each single gate. +Some of the gates use the new AHB2 clock as parent, whose clock source +is muxable between AHB1 and PLL6/2. The documentation isn't totally clear +about which devices belong to AHB2 now, especially USB EHIC/OHIC, so it +is mostly based on Allwinner kernel source code. + +Signed-off-by: Jens Kuske + +--- +Documentation/devicetree/bindings/clock/sunxi.txt | 2 + + drivers/clk/sunxi/Makefile | 1 + + drivers/clk/sunxi/clk-bus-gates.c | 105 ++++++++++++++++++++++ + drivers/clk/sunxi/clk-sunxi.c | 12 ++- + 4 files changed, 117 insertions(+), 3 deletions(-) + create mode 100644 drivers/clk/sunxi/clk-bus-gates.c + +diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt +index 8a47b77..d303dec 100644 +--- a/Documentation/devicetree/bindings/clock/sunxi.txt ++++ b/Documentation/devicetree/bindings/clock/sunxi.txt +@@ -28,6 +28,7 @@ Required properties: + "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20 + "allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31 + "allwinner,sun6i-a31-ahb1-clk" - for the AHB1 clock on A31 ++ "allwinner,sun8i-h3-ahb2-clk" - for the AHB2 clock on H3 + "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 + "allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23 + "allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80 +@@ -55,6 +56,7 @@ Required properties: + "allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80 + "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 + "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23 ++ "allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3 + "allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13 + "allwinner,sun4i-a10-mmc-clk" - for the MMC clock + "allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80 +diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile +index f5a35b8..ecaff7f 100644 +--- a/drivers/clk/sunxi/Makefile ++++ b/drivers/clk/sunxi/Makefile +@@ -5,6 +5,7 @@ + obj-y += clk-sunxi.o clk-factors.o + obj-y += clk-a10-hosc.o + obj-y += clk-a20-gmac.o ++obj-y += clk-bus-gates.o + obj-y += clk-mod0.o + obj-y += clk-simple-gates.o + obj-y += clk-sun8i-mbus.o +diff --git a/drivers/clk/sunxi/clk-bus-gates.c b/drivers/clk/sunxi/clk-bus-gates.c +new file mode 100644 +index 0000000..5bba0b9 +--- /dev/null ++++ b/drivers/clk/sunxi/clk-bus-gates.c +@@ -0,0 +1,105 @@ ++/* ++ * Copyright (C) 2015 Jens Kuske ++ * ++ * Based on clk-simple-gates.c, which is: ++ * Copyright 2015 Maxime Ripard ++ * ++ * Maxime Ripard ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static DEFINE_SPINLOCK(gates_lock); ++ ++static void __init sunxi_bus_gates_setup(struct device_node *node, ++ const int protected[], ++ int nprotected) ++{ ++ struct clk_onecell_data *clk_data; ++ const char *clk_parent, *clk_name; ++ struct property *prop; ++ struct resource res; ++ void __iomem *clk_reg; ++ void __iomem *reg; ++ const __be32 *p; ++ int number, i = 0, j; ++ u8 clk_bit; ++ u32 index; ++ ++ reg = of_io_request_and_map(node, 0, of_node_full_name(node)); ++ if (IS_ERR(reg)) ++ return; ++ ++ clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL); ++ if (!clk_data) ++ goto err_unmap; ++ ++ number = of_property_count_u32_elems(node, "clock-indices"); ++ of_property_read_u32_index(node, "clock-indices", number - 1, &number); ++ ++ clk_data->clks = kcalloc(number + 1, sizeof(struct clk *), GFP_KERNEL); ++ if (!clk_data->clks) ++ goto err_free_data; ++ ++ of_property_for_each_u32(node, "clock-indices", prop, p, index) { ++ of_property_read_string_index(node, "clock-output-names", ++ i, &clk_name); ++ ++ clk_parent = of_clk_get_parent_name(node, i); ++ ++ clk_reg = reg + 4 * (index / 32); ++ clk_bit = index % 32; ++ ++ clk_data->clks[index] = clk_register_gate(NULL, clk_name, ++ clk_parent, 0, ++ clk_reg, ++ clk_bit, ++ 0, &gates_lock); ++ i++; ++ ++ if (IS_ERR(clk_data->clks[index])) { ++ WARN_ON(true); ++ continue; ++ } ++ ++ for (j = 0; j < nprotected; j++) ++ if (protected[j] == index) ++ clk_prepare_enable(clk_data->clks[index]); ++ ++ } ++ ++ clk_data->clk_num = number + 1; ++ of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); ++ ++ return; ++ ++err_free_data: ++ kfree(clk_data); ++err_unmap: ++ iounmap(reg); ++ of_address_to_resource(node, 0, &res); ++ release_mem_region(res.start, resource_size(&res)); ++} ++ ++static void __init sunxi_bus_gates_init(struct device_node *node) ++{ ++ sunxi_bus_gates_setup(node, NULL, 0); ++} ++ ++CLK_OF_DECLARE(sun8i_h3_bus_gates, "allwinner,sun8i-h3-bus-gates-clk", ++ sunxi_bus_gates_init); +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 7c4aee0..6293c65 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -769,6 +769,10 @@ static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = { + .shift = 12, + }; + ++static const struct mux_data sun8i_h3_ahb2_mux_data __initconst = { ++ .shift = 0, ++}; ++ + static void __init sunxi_mux_clk_setup(struct device_node *node, + struct mux_data *data) + { +@@ -945,10 +949,11 @@ static const struct divs_data pll6_divs_data __initconst = { + + static const struct divs_data sun6i_a31_pll6_divs_data __initconst = { + .factors = &sun6i_a31_pll6_data, +- .ndivs = 2, ++ .ndivs = 3, + .div = { + { .fixed = 2 }, /* normal output */ + { .self = 1 }, /* base factor clock, 2x */ ++ { .fixed = 4 }, /* divided output, /2 */ + } + }; + +@@ -1147,6 +1151,7 @@ static const struct of_device_id clk_divs_match[] __initconst = { + static const struct of_device_id clk_mux_match[] __initconst = { + {.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,}, + {.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,}, ++ {.compatible = "allwinner,sun8i-h3-ahb2-clk", .data = &sun8i_h3_ahb2_mux_data,}, + {} + }; + +@@ -1229,6 +1234,7 @@ CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks); + CLK_OF_DECLARE(sun6i_a31s_clk_init, "allwinner,sun6i-a31s", sun6i_init_clocks); + CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks); + CLK_OF_DECLARE(sun8i_a33_clk_init, "allwinner,sun8i-a33", sun6i_init_clocks); ++CLK_OF_DECLARE(sun8i_h3_clk_init, "allwinner,sun8i-h3", sun6i_init_clocks); + + static void __init sun9i_init_clocks(struct device_node *node) + { diff --git a/patch/kernel/old-h3-7458451.patch b/patch/kernel/old-h3-7458451.patch new file mode 100644 index 000000000..f7a4923f7 --- /dev/null +++ b/patch/kernel/old-h3-7458451.patch @@ -0,0 +1,119 @@ +From patchwork Wed Oct 21 16:13:22 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [1/6] clk: sunxi: Let divs clocks read the base factor clock name + from devicetree +From: Jens Kuske +X-Patchwork-Id: 7458451 +Message-Id: <1445444007-4260-2-git-send-email-jenskuske@gmail.com> +To: Maxime Ripard , + Chen-Yu Tsai , Mike Turquette , + Linus Walleij , + Rob Herring , Philipp Zabel , + =?UTF-8?q?Emilio=20L=C3=B3pez?= +Cc: devicetree@vger.kernel.org, Vishnu Patekar , + linux-kernel@vger.kernel.org, Hans de Goede , + linux-sunxi@googlegroups.com, Jens Kuske , + linux-arm-kernel@lists.infradead.org +Date: Wed, 21 Oct 2015 18:13:22 +0200 + +Currently, the sunxi clock driver gets the name for the base factor clock +of divs clocks from the name field in factors_data. This prevents reusing +of the factor clock for clocks with same properties, but different name. + +This commit makes the divs setup function try to get a name from +clock-output-names in the devicetree. It also removes the name field where +possible and merges the sun4i PLL5 and PLL6 clocks. + +Signed-off-by: Jens Kuske + +--- +drivers/clk/sunxi/clk-sunxi.c | 39 ++++++++++++++++++++++++++++----------- + 1 file changed, 28 insertions(+), 11 deletions(-) + +diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c +index 9c79af0c..7c4aee0 100644 +--- a/drivers/clk/sunxi/clk-sunxi.c ++++ b/drivers/clk/sunxi/clk-sunxi.c +@@ -704,21 +704,12 @@ static const struct factors_data sun4i_pll5_data __initconst = { + .enable = 31, + .table = &sun4i_pll5_config, + .getter = sun4i_get_pll5_factors, +- .name = "pll5", +-}; +- +-static const struct factors_data sun4i_pll6_data __initconst = { +- .enable = 31, +- .table = &sun4i_pll5_config, +- .getter = sun4i_get_pll5_factors, +- .name = "pll6", + }; + + static const struct factors_data sun6i_a31_pll6_data __initconst = { + .enable = 31, + .table = &sun6i_a31_pll6_config, + .getter = sun6i_a31_get_pll6_factors, +- .name = "pll6x2", + }; + + static const struct factors_data sun5i_a13_ahb_data __initconst = { +@@ -902,6 +893,7 @@ struct gates_data { + + #define SUNXI_DIVS_MAX_QTY 4 + #define SUNXI_DIVISOR_WIDTH 2 ++#define SUNXI_DIVS_BASE_NAME_MAX_LEN 8 + + struct divs_data { + const struct factors_data *factors; /* data for the factor clock */ +@@ -941,7 +933,7 @@ static const struct divs_data pll5_divs_data __initconst = { + }; + + static const struct divs_data pll6_divs_data __initconst = { +- .factors = &sun4i_pll6_data, ++ .factors = &sun4i_pll5_data, + .ndivs = 4, + .div = { + { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */ +@@ -983,6 +975,8 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, + struct clk_gate *gate = NULL; + struct clk_fixed_factor *fix_factor; + struct clk_divider *divider; ++ struct factors_data factors = *data->factors; ++ char base_name[SUNXI_DIVS_BASE_NAME_MAX_LEN]; + void __iomem *reg; + int ndivs = SUNXI_DIVS_MAX_QTY, i = 0; + int flags, clkflags; +@@ -991,8 +985,31 @@ static void __init sunxi_divs_clk_setup(struct device_node *node, + if (data->ndivs) + ndivs = data->ndivs; + ++ /* Try to find a name for base factor clock */ ++ for (i = 0; i < ndivs; i++) { ++ if (data->div[i].self) { ++ of_property_read_string_index(node, "clock-output-names", ++ i, &factors.name); ++ break; ++ } ++ } ++ /* If we don't have a .self clk use the first output-name up to '_' */ ++ if (factors.name == NULL) { ++ of_property_read_string_index(node, "clock-output-names", ++ 0, &clk_name); ++ ++ for (i = 0; i < SUNXI_DIVS_BASE_NAME_MAX_LEN - 1 && ++ clk_name[i] != '_' && ++ clk_name[i] != '\0'; i++) { ++ base_name[i] = clk_name[i]; ++ } ++ ++ base_name[i] = '\0'; ++ factors.name = base_name; ++ } ++ + /* Set up factor clock that we will be dividing */ +- pclk = sunxi_factors_clk_setup(node, data->factors); ++ pclk = sunxi_factors_clk_setup(node, &factors); + parent = __clk_get_name(pclk); + + reg = of_iomap(node, 0); diff --git a/patch/kernel/old-h3-7458631.patch b/patch/kernel/old-h3-7458631.patch new file mode 100644 index 000000000..bb3f009ca --- /dev/null +++ b/patch/kernel/old-h3-7458631.patch @@ -0,0 +1,55 @@ +From patchwork Wed Oct 21 16:20:26 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [4/6] reset: sunxi: Add compatible for Allwinner H3 bus resets +From: Jens Kuske +X-Patchwork-Id: 7458631 +Message-Id: <1445444428-4652-1-git-send-email-jenskuske@gmail.com> +To: Maxime Ripard , + Chen-Yu Tsai , Michael Turquette , + Linus Walleij , + Rob Herring , Philipp Zabel , + =?UTF-8?q?Emilio=20L=C3=B3pez?= +Cc: devicetree@vger.kernel.org, Vishnu Patekar , + linux-kernel@vger.kernel.org, Hans de Goede , + linux-sunxi@googlegroups.com, Jens Kuske , + linux-arm-kernel@lists.infradead.org +Date: Wed, 21 Oct 2015 18:20:26 +0200 + +Adding a new compatible allows us to define SoC specific behaviour +if necessary, for example forcing a particular device out of reset +even if no driver is actually using it. + +Signed-off-by: Jens Kuske +Acked-by: Maxime Ripard + +--- +Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt | 1 + + drivers/reset/reset-sunxi.c | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt b/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt +index c8f7757..e11f023 100644 +--- a/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt ++++ b/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt +@@ -8,6 +8,7 @@ Required properties: + - compatible: Should be one of the following: + "allwinner,sun6i-a31-ahb1-reset" + "allwinner,sun6i-a31-clock-reset" ++ "allwinner,sun8i-h3-bus-reset" + - reg: should be register base and length as documented in the + datasheet + - #reset-cells: 1, see below +diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c +index 3d95c87..6f12b5c 100644 +--- a/drivers/reset/reset-sunxi.c ++++ b/drivers/reset/reset-sunxi.c +@@ -124,6 +124,7 @@ err_alloc: + */ + static const struct of_device_id sunxi_early_reset_dt_ids[] __initdata = { + { .compatible = "allwinner,sun6i-a31-ahb1-reset", }, ++ { .compatible = "allwinner,sun8i-h3-bus-reset", }, + { /* sentinel */ }, + }; + diff --git a/patch/kernel/old-h3-7458651.patch b/patch/kernel/old-h3-7458651.patch new file mode 100644 index 000000000..59d294fa7 --- /dev/null +++ b/patch/kernel/old-h3-7458651.patch @@ -0,0 +1,534 @@ +From patchwork Wed Oct 21 16:20:27 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [5/6] ARM: dts: sunxi: Add Allwinner H3 DTSI +From: Jens Kuske +X-Patchwork-Id: 7458651 +Message-Id: <1445444428-4652-2-git-send-email-jenskuske@gmail.com> +To: Maxime Ripard , + Chen-Yu Tsai , Michael Turquette , + Linus Walleij , + Rob Herring , Philipp Zabel , + =?UTF-8?q?Emilio=20L=C3=B3pez?= +Cc: devicetree@vger.kernel.org, Vishnu Patekar , + linux-kernel@vger.kernel.org, Hans de Goede , + linux-sunxi@googlegroups.com, Jens Kuske , + linux-arm-kernel@lists.infradead.org +Date: Wed, 21 Oct 2015 18:20:27 +0200 + +The Allwinner H3 is a home entertainment system oriented SoC with +four Cortex-A7 cores and a Mali-400MP2 GPU. + +Signed-off-by: Jens Kuske + +--- +arch/arm/boot/dts/sun8i-h3.dtsi | 499 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 499 insertions(+) + create mode 100644 arch/arm/boot/dts/sun8i-h3.dtsi + +diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi +new file mode 100644 +index 0000000..4114e17 +--- /dev/null ++++ b/arch/arm/boot/dts/sun8i-h3.dtsi +@@ -0,0 +1,499 @@ ++/* ++ * Copyright (C) 2015 Jens Kuske ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This file is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#include "skeleton.dtsi" ++ ++#include ++#include ++ ++/ { ++ interrupt-parent = <&gic>; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ reg = <0>; ++ }; ++ ++ cpu@1 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ reg = <1>; ++ }; ++ ++ cpu@2 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ reg = <2>; ++ }; ++ ++ cpu@3 { ++ compatible = "arm,cortex-a7"; ++ device_type = "cpu"; ++ reg = <3>; ++ }; ++ }; ++ ++ timer { ++ compatible = "arm,armv7-timer"; ++ interrupts = , ++ , ++ , ++ ; ++ clock-frequency = <24000000>; ++ arm,cpu-registers-not-fw-configured; ++ }; ++ ++ memory { ++ reg = <0x40000000 0x80000000>; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ osc24M: osc24M_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <24000000>; ++ clock-output-names = "osc24M"; ++ }; ++ ++ osc32k: osc32k_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ clock-output-names = "osc32k"; ++ }; ++ ++ pll1: clk@01c20000 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun8i-a23-pll1-clk"; ++ reg = <0x01c20000 0x4>; ++ clocks = <&osc24M>; ++ clock-output-names = "pll1"; ++ }; ++ ++ /* dummy clock until actually implemented */ ++ pll5: pll5_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++ clock-output-names = "pll5"; ++ }; ++ ++ pll6: clk@01c20028 { ++ #clock-cells = <1>; ++ compatible = "allwinner,sun6i-a31-pll6-clk"; ++ reg = <0x01c20028 0x4>; ++ clocks = <&osc24M>; ++ clock-output-names = "pll6", "pll6x2", "pll6d2"; ++ }; ++ ++ pll8: clk@01c20044 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun6i-a31-pll6-clk"; ++ reg = <0x01c20044 0x4>; ++ clocks = <&osc24M>; ++ clock-output-names = "pll8", "pll8x2"; ++ }; ++ ++ cpu: cpu_clk@01c20050 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-cpu-clk"; ++ reg = <0x01c20050 0x4>; ++ clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>; ++ clock-output-names = "cpu"; ++ }; ++ ++ axi: axi_clk@01c20050 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-axi-clk"; ++ reg = <0x01c20050 0x4>; ++ clocks = <&cpu>; ++ clock-output-names = "axi"; ++ }; ++ ++ ahb1: ahb1_clk@01c20054 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun6i-a31-ahb1-clk"; ++ reg = <0x01c20054 0x4>; ++ clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>; ++ clock-output-names = "ahb1"; ++ }; ++ ++ ahb2: ahb2_clk@01c2005c { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun8i-h3-ahb2-clk"; ++ reg = <0x01c2005c 0x4>; ++ clocks = <&ahb1>, <&pll6 2>; ++ clock-output-names = "ahb2"; ++ }; ++ ++ apb1: apb1_clk@01c20054 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-apb0-clk"; ++ reg = <0x01c20054 0x4>; ++ clocks = <&ahb1>; ++ clock-output-names = "apb1"; ++ }; ++ ++ apb2: apb2_clk@01c20058 { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun4i-a10-apb1-clk"; ++ reg = <0x01c20058 0x4>; ++ clocks = <&osc32k>, <&osc24M>, <&pll6 0>, <&pll6 0>; ++ clock-output-names = "apb2"; ++ }; ++ ++ bus_gates: clk@01c20060 { ++ #clock-cells = <1>; ++ compatible = "allwinner,sun8i-h3-bus-gates-clk"; ++ reg = <0x01c20060 0x14>; ++ clock-indices = <5>, <6>, <8>, ++ <9>, <10>, <13>, ++ <14>, <17>, <18>, ++ <19>, <20>, ++ <21>, <23>, ++ <24>, <25>, ++ <26>, <27>, ++ <28>, <29>, ++ <30>, <31>, <32>, ++ <35>, <36>, <37>, ++ <40>, <41>, <43>, ++ <44>, <52>, <53>, ++ <54>, <64>, ++ <65>, <69>, <72>, ++ <76>, <77>, <78>, ++ <96>, <97>, <98>, ++ <112>, <113>, ++ <114>, <115>, <116>, ++ <128>, <135>; ++ clocks = <&ahb1>, <&ahb1>, <&ahb1>, ++ <&ahb1>, <&ahb1>, <&ahb1>, ++ <&ahb1>, <&ahb2>, <&ahb1>, ++ <&ahb1>, <&ahb1>, ++ <&ahb1>, <&ahb1>, ++ <&ahb1>, <&ahb1>, ++ <&ahb1>, <&ahb1>, ++ <&ahb1>, <&ahb2>, ++ <&ahb2>, <&ahb2>, <&ahb1>, ++ <&ahb1>, <&ahb1>, <&ahb1>, ++ <&ahb1>, <&ahb1>, <&ahb1>, ++ <&ahb1>, <&ahb1>, <&ahb1>, ++ <&ahb1>, <&apb1>, ++ <&apb1>, <&apb1>, <&apb1>, ++ <&apb1>, <&apb1>, <&apb1>, ++ <&apb2>, <&apb2>, <&apb2>, ++ <&apb2>, <&apb2>, ++ <&apb2>, <&apb2>, <&apb2>, ++ <&ahb1>, <&ahb1>; ++ clock-output-names = "ahb1_ce", "ahb1_dma", "ahb1_mmc0", ++ "ahb1_mmc1", "ahb1_mmc2", "ahb1_nand", ++ "ahb1_sdram", "ahb2_gmac", "ahb1_ts", ++ "ahb1_hstimer", "ahb1_spi0", ++ "ahb1_spi1", "ahb1_otg", ++ "ahb1_otg_ehci0", "ahb1_ehic1", ++ "ahb1_ehic2", "ahb1_ehic3", ++ "ahb1_otg_ohci0", "ahb2_ohic1", ++ "ahb2_ohic2", "ahb2_ohic3", "ahb1_ve", ++ "ahb1_lcd0", "ahb1_lcd1", "ahb1_deint", ++ "ahb1_csi", "ahb1_tve", "ahb1_hdmi", ++ "ahb1_de", "ahb1_gpu", "ahb1_msgbox", ++ "ahb1_spinlock", "apb1_codec", ++ "apb1_spdif", "apb1_pio", "apb1_ths", ++ "apb1_i2s0", "apb1_i2s1", "apb1_i2s2", ++ "apb2_i2c0", "apb2_i2c1", "apb2_i2c2", ++ "apb2_uart0", "apb2_uart1", ++ "apb2_uart2", "apb2_uart3", "apb2_scr", ++ "ahb1_ephy", "ahb1_dbg"; ++ }; ++ ++ mmc0_clk: clk@01c20088 { ++ #clock-cells = <1>; ++ compatible = "allwinner,sun4i-a10-mmc-clk"; ++ reg = <0x01c20088 0x4>; ++ clocks = <&osc24M>, <&pll6 0>, <&pll8 0>; ++ clock-output-names = "mmc0", ++ "mmc0_output", ++ "mmc0_sample"; ++ }; ++ ++ mmc1_clk: clk@01c2008c { ++ #clock-cells = <1>; ++ compatible = "allwinner,sun4i-a10-mmc-clk"; ++ reg = <0x01c2008c 0x4>; ++ clocks = <&osc24M>, <&pll6 0>, <&pll8 0>; ++ clock-output-names = "mmc1", ++ "mmc1_output", ++ "mmc1_sample"; ++ }; ++ ++ mmc2_clk: clk@01c20090 { ++ #clock-cells = <1>; ++ compatible = "allwinner,sun4i-a10-mmc-clk"; ++ reg = <0x01c20090 0x4>; ++ clocks = <&osc24M>, <&pll6 0>, <&pll8 0>; ++ clock-output-names = "mmc2", ++ "mmc2_output", ++ "mmc2_sample"; ++ }; ++ ++ mbus_clk: clk@01c2015c { ++ #clock-cells = <0>; ++ compatible = "allwinner,sun8i-a23-mbus-clk"; ++ reg = <0x01c2015c 0x4>; ++ clocks = <&osc24M>, <&pll6 1>, <&pll5>; ++ clock-output-names = "mbus"; ++ }; ++ }; ++ ++ soc@01c00000 { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ dma: dma-controller@01c02000 { ++ compatible = "allwinner,sun8i-h3-dma"; ++ reg = <0x01c02000 0x1000>; ++ interrupts = ; ++ clocks = <&bus_gates 6>; ++ resets = <&bus_rst 6>; ++ #dma-cells = <1>; ++ }; ++ ++ mmc0: mmc@01c0f000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c0f000 0x1000>; ++ clocks = <&bus_gates 8>, ++ <&mmc0_clk 0>, ++ <&mmc0_clk 1>, ++ <&mmc0_clk 2>; ++ clock-names = "ahb", ++ "mmc", ++ "output", ++ "sample"; ++ resets = <&bus_rst 8>; ++ reset-names = "ahb"; ++ interrupts = ; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ mmc1: mmc@01c10000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c10000 0x1000>; ++ clocks = <&bus_gates 9>, ++ <&mmc1_clk 0>, ++ <&mmc1_clk 1>, ++ <&mmc1_clk 2>; ++ clock-names = "ahb", ++ "mmc", ++ "output", ++ "sample"; ++ resets = <&bus_rst 9>; ++ reset-names = "ahb"; ++ interrupts = ; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ mmc2: mmc@01c11000 { ++ compatible = "allwinner,sun5i-a13-mmc"; ++ reg = <0x01c11000 0x1000>; ++ clocks = <&bus_gates 10>, ++ <&mmc2_clk 0>, ++ <&mmc2_clk 1>, ++ <&mmc2_clk 2>; ++ clock-names = "ahb", ++ "mmc", ++ "output", ++ "sample"; ++ resets = <&bus_rst 10>; ++ reset-names = "ahb"; ++ interrupts = ; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ pio: pinctrl@01c20800 { ++ compatible = "allwinner,sun8i-h3-pinctrl"; ++ reg = <0x01c20800 0x400>; ++ interrupts = , ++ ; ++ clocks = <&bus_gates 69>; ++ gpio-controller; ++ #gpio-cells = <3>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ++ uart0_pins_a: uart0@0 { ++ allwinner,pins = "PA4", "PA5"; ++ allwinner,function = "uart0"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++ ++ mmc0_pins_a: mmc0@0 { ++ allwinner,pins = "PF0", "PF1", "PF2", "PF3", ++ "PF4", "PF5"; ++ allwinner,function = "mmc0"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++ ++ mmc0_cd_pin: mmc0_cd_pin@0 { ++ allwinner,pins = "PF6"; ++ allwinner,function = "gpio_in"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++ ++ mmc1_pins_a: mmc1@0 { ++ allwinner,pins = "PG0", "PG1", "PG2", "PG3", ++ "PG4", "PG5"; ++ allwinner,function = "mmc1"; ++ allwinner,drive = ; ++ allwinner,pull = ; ++ }; ++ }; ++ ++ bus_rst: reset@01c202c0 { ++ #reset-cells = <1>; ++ compatible = "allwinner,sun8i-h3-bus-reset"; ++ reg = <0x01c202c0 0x1c>; ++ }; ++ ++ timer@01c20c00 { ++ compatible = "allwinner,sun4i-a10-timer"; ++ reg = <0x01c20c00 0xa0>; ++ interrupts = , ++ ; ++ clocks = <&osc24M>; ++ }; ++ ++ wdt0: watchdog@01c20ca0 { ++ compatible = "allwinner,sun6i-a31-wdt"; ++ reg = <0x01c20ca0 0x20>; ++ interrupts = ; ++ }; ++ ++ uart0: serial@01c28000 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x01c28000 0x400>; ++ interrupts = ; ++ reg-shift = <2>; ++ reg-io-width = <4>; ++ clocks = <&bus_gates 112>; ++ resets = <&bus_rst 208>; ++ dmas = <&dma 6>, <&dma 6>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; ++ ++ uart1: serial@01c28400 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x01c28400 0x400>; ++ interrupts = ; ++ reg-shift = <2>; ++ reg-io-width = <4>; ++ clocks = <&bus_gates 113>; ++ resets = <&bus_rst 209>; ++ dmas = <&dma 7>, <&dma 7>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; ++ ++ uart2: serial@01c28800 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x01c28800 0x400>; ++ interrupts = ; ++ reg-shift = <2>; ++ reg-io-width = <4>; ++ clocks = <&bus_gates 114>; ++ resets = <&bus_rst 210>; ++ dmas = <&dma 8>, <&dma 8>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; ++ ++ uart3: serial@01c28c00 { ++ compatible = "snps,dw-apb-uart"; ++ reg = <0x01c28c00 0x400>; ++ interrupts = ; ++ reg-shift = <2>; ++ reg-io-width = <4>; ++ clocks = <&bus_gates 115>; ++ resets = <&bus_rst 211>; ++ dmas = <&dma 9>, <&dma 9>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; ++ ++ gic: interrupt-controller@01c81000 { ++ compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic"; ++ reg = <0x01c81000 0x1000>, ++ <0x01c82000 0x1000>, ++ <0x01c84000 0x2000>, ++ <0x01c86000 0x2000>; ++ interrupt-controller; ++ #interrupt-cells = <3>; ++ interrupts = ; ++ }; ++ ++ rtc: rtc@01f00000 { ++ compatible = "allwinner,sun6i-a31-rtc"; ++ reg = <0x01f00000 0x54>; ++ interrupts = , ++ ; ++ }; ++ }; ++}; diff --git a/patch/kernel/old-h3-7458661.patch b/patch/kernel/old-h3-7458661.patch new file mode 100644 index 000000000..347d40452 --- /dev/null +++ b/patch/kernel/old-h3-7458661.patch @@ -0,0 +1,127 @@ +From patchwork Wed Oct 21 16:20:28 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [6/6] ARM: dts: sun8i: Add Orange Pi Plus support +From: Jens Kuske +X-Patchwork-Id: 7458661 +Message-Id: <1445444428-4652-3-git-send-email-jenskuske@gmail.com> +To: Maxime Ripard , + Chen-Yu Tsai , Michael Turquette , + Linus Walleij , + Rob Herring , Philipp Zabel , + =?UTF-8?q?Emilio=20L=C3=B3pez?= +Cc: devicetree@vger.kernel.org, Vishnu Patekar , + linux-kernel@vger.kernel.org, Hans de Goede , + linux-sunxi@googlegroups.com, Jens Kuske , + linux-arm-kernel@lists.infradead.org +Date: Wed, 21 Oct 2015 18:20:28 +0200 + +The Orange Pi Plus is a SBC based on the Allwinner H3 SoC +with 8GB eMMC, multiple USB ports through a USB hub chip, SATA through +a USB-SATA bridge, one uSD slot, a 10/100/1000M ethernet port, +WiFi, HDMI, headphone jack, IR receiver, a microphone, a CSI connector +and a 40-pin GPIO header. + +Signed-off-by: Jens Kuske + +--- +arch/arm/boot/dts/Makefile | 3 +- + arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 77 ++++++++++++++++++++++++++++ + 2 files changed, 79 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts + +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index 35a3cf4..bedf51b 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -643,3 +643,4 @@ dtb-$(CONFIG_MACH_SUN8I) += \ +- sun8i-a33-sinlinx-sina33.dtb ++ sun8i-a33-sinlinx-sina33.dtb \ ++ sun8i-h3-orangepi-plus.dtb + dtb-$(CONFIG_MACH_SUN9I) += \ + sun9i-a80-optimus.dtb \ + sun9i-a80-cubieboard4.dtb +diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts +new file mode 100644 +index 0000000..e67df59 +--- /dev/null ++++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (C) 2015 Jens Kuske ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This file is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++#include "sun8i-h3.dtsi" ++#include "sunxi-common-regulators.dtsi" ++ ++#include ++#include ++ ++/ { ++ model = "Xunlong Orange Pi Plus"; ++ compatible = "xunlong,orangepi-plus", "allwinner,sun8i-h3"; ++ ++ aliases { ++ serial0 = &uart0; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++}; ++ ++&mmc0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>; ++ vmmc-supply = <®_vcc3v3>; ++ bus-width = <4>; ++ cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */ ++ cd-inverted; ++ status = "okay"; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins_a>; ++ status = "okay"; ++}; diff --git a/patch/kernel/old-h3-7458701.patch b/patch/kernel/old-h3-7458701.patch new file mode 100644 index 000000000..dec13d98d --- /dev/null +++ b/patch/kernel/old-h3-7458701.patch @@ -0,0 +1,593 @@ +From patchwork Wed Oct 21 16:30:46 2015 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [3/6] pinctrl: sunxi: Add H3 PIO controller support +From: Jens Kuske +X-Patchwork-Id: 7458701 +Message-Id: <5627BDB6.6020501@gmail.com> +To: Maxime Ripard , + Chen-Yu Tsai , Michael Turquette , + Linus Walleij , + Rob Herring , + Philipp Zabel , =?UTF-8?Q?Emilio_L=c3=b3pez?= + +Cc: devicetree@vger.kernel.org, Vishnu Patekar , + linux-kernel@vger.kernel.org, Hans de Goede , + linux-sunxi , + Jens Kuske , linux-arm-kernel@lists.infradead.org +Date: Wed, 21 Oct 2015 18:30:46 +0200 + +The H3 uses the same pin controller as previous SoC's from Allwinner. +Add support for the pins controlled by the main PIO controller. + +Signed-off-by: Jens Kuske +Acked-by: Maxime Ripard + +--- +.../bindings/pinctrl/allwinner,sunxi-pinctrl.txt | 1 + + drivers/pinctrl/sunxi/Kconfig | 4 + + drivers/pinctrl/sunxi/Makefile | 1 + + drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c | 516 +++++++++++++++++++++ + 4 files changed, 522 insertions(+) + create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c + +diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt +index 3c821cd..094451c 100644 +--- a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt ++++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt +@@ -17,6 +17,7 @@ Required properties: + "allwinner,sun8i-a23-pinctrl" + "allwinner,sun8i-a23-r-pinctrl" + "allwinner,sun8i-a33-pinctrl" ++ "allwinner,sun8i-h3-pinctrl" + + - reg: Should contain the register physical address and length for the + pin controller. +diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig +index ae27872..f161e4c 100644 +--- a/drivers/pinctrl/sunxi/Kconfig ++++ b/drivers/pinctrl/sunxi/Kconfig +@@ -47,6 +47,10 @@ config PINCTRL_SUN8I_A23_R + depends on RESET_CONTROLLER + select PINCTRL_SUNXI_COMMON + ++config PINCTRL_SUN8I_H3 ++ def_bool MACH_SUN8I ++ select PINCTRL_SUNXI_COMMON ++ + config PINCTRL_SUN9I_A80 + def_bool MACH_SUN9I + select PINCTRL_SUNXI_COMMON +diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile +index 227a121..ca19592 100644 +--- a/drivers/pinctrl/sunxi/Makefile ++++ b/drivers/pinctrl/sunxi/Makefile +@@ -12,4 +12,5 @@ obj-$(CONFIG_PINCTRL_SUN7I_A20) += pinctrl-sun7i-a20.o + obj-$(CONFIG_PINCTRL_SUN8I_A23) += pinctrl-sun8i-a23.o + obj-$(CONFIG_PINCTRL_SUN8I_A23_R) += pinctrl-sun8i-a23-r.o + obj-$(CONFIG_PINCTRL_SUN8I_A33) += pinctrl-sun8i-a33.o ++obj-$(CONFIG_PINCTRL_SUN8I_H3) += pinctrl-sun8i-h3.o + obj-$(CONFIG_PINCTRL_SUN9I_A80) += pinctrl-sun9i-a80.o +diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c +new file mode 100644 +index 0000000..98d465d +--- /dev/null ++++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c +@@ -0,0 +1,516 @@ ++/* ++ * Allwinner H3 SoCs pinctrl driver. ++ * ++ * Copyright (C) 2015 Jens Kuske ++ * ++ * Based on pinctrl-sun8i-a23.c, which is: ++ * Copyright (C) 2014 Chen-Yu Tsai ++ * Copyright (C) 2014 Maxime Ripard ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "pinctrl-sunxi.h" ++ ++static const struct sunxi_desc_pin sun8i_h3_pins[] = { ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart2"), /* TX */ ++ SUNXI_FUNCTION(0x3, "jtag"), /* MS */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PA_EINT0 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart2"), /* RX */ ++ SUNXI_FUNCTION(0x3, "jtag"), /* CK */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PA_EINT1 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart2"), /* RTS */ ++ SUNXI_FUNCTION(0x3, "jtag"), /* DO */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)), /* PA_EINT2 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart2"), /* CTS */ ++ SUNXI_FUNCTION(0x3, "jtag"), /* DI */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)), /* PA_EINT3 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart0"), /* TX */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)), /* PA_EINT4 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart0"), /* RX */ ++ SUNXI_FUNCTION(0x3, "pwm0"), ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)), /* PA_EINT5 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "sim"), /* PWREN */ ++ SUNXI_FUNCTION(0x3, "pwm1"), ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)), /* PA_EINT6 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "sim"), /* CLK */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)), /* PA_EINT7 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "sim"), /* DATA */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)), /* PA_EINT8 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "sim"), /* RST */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)), /* PA_EINT9 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "sim"), /* DET */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 10)), /* PA_EINT10 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2c0"), /* SCK */ ++ SUNXI_FUNCTION(0x3, "di"), /* TX */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 11)), /* PA_EINT11 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2c0"), /* SDA */ ++ SUNXI_FUNCTION(0x3, "di"), /* RX */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 12)), /* PA_EINT12 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 13), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "spi1"), /* CS */ ++ SUNXI_FUNCTION(0x3, "uart3"), /* TX */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 13)), /* PA_EINT13 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 14), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "spi1"), /* CLK */ ++ SUNXI_FUNCTION(0x3, "uart3"), /* RX */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 14)), /* PA_EINT14 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 15), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "spi1"), /* MOSI */ ++ SUNXI_FUNCTION(0x3, "uart3"), /* RTS */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 15)), /* PA_EINT15 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "spi1"), /* MISO */ ++ SUNXI_FUNCTION(0x3, "uart3"), /* CTS */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 16)), /* PA_EINT16 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "spdif"), /* OUT */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 17)), /* PA_EINT17 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s0"), /* SYNC */ ++ SUNXI_FUNCTION(0x3, "i2c1"), /* SCK */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 18)), /* PA_EINT18 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s0"), /* CLK */ ++ SUNXI_FUNCTION(0x3, "i2c1"), /* SDA */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 19)), /* PA_EINT19 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 20), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s0"), /* DOUT */ ++ SUNXI_FUNCTION(0x3, "sim"), /* VPPEN */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 20)), /* PA_EINT20 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 21), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s0"), /* DIN */ ++ SUNXI_FUNCTION(0x3, "sim"), /* VPPPP */ ++ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 21)), /* PA_EINT21 */ ++ /* Hole */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* WE */ ++ SUNXI_FUNCTION(0x3, "spi0")), /* MOSI */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* ALE */ ++ SUNXI_FUNCTION(0x3, "spi0")), /* MISO */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* CLE */ ++ SUNXI_FUNCTION(0x3, "spi0")), /* CLK */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* CE1 */ ++ SUNXI_FUNCTION(0x3, "spi0")), /* CS */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0")), /* CE0 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* RE */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* CLK */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* RB0 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* CMD */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0")), /* RB1 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* DQ0 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D0 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* DQ1 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D1 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* DQ2 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D2 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* DQ3 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D3 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 12), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* DQ4 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D4 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 13), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand0"), /* DQ5 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D5 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand"), /* DQ6 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D6 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand"), /* DQ7 */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* D7 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 16), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "nand"), /* DQS */ ++ SUNXI_FUNCTION(0x3, "mmc2")), /* RST */ ++ /* Hole */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* RXD3 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* RXD2 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* RXD1 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* RXD0 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* RXCK */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* RXCTL/RCDV */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* RXERR */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* TXD3 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* TXD2L */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* TXD1 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* TXD0 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* CRS */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* TXCK */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* TXCTL/TXEN */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* TXERR */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* CLKIN/COL */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* MDC */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "emac")), /* MDIO */ ++ /* Hole */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* PCLK */ ++ SUNXI_FUNCTION(0x3, "ts")), /* CLK */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* MCLK */ ++ SUNXI_FUNCTION(0x3, "ts")), /* ERR */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* HSYNC */ ++ SUNXI_FUNCTION(0x3, "ts")), /* SYNC */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* VSYNC */ ++ SUNXI_FUNCTION(0x3, "ts")), /* DVLD */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D0 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D0 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D1 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D1 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D2 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D2 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D3 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D3 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D4 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D4 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D5 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D5 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D6 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D6 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* D7 */ ++ SUNXI_FUNCTION(0x3, "ts")), /* D7 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* SCK */ ++ SUNXI_FUNCTION(0x3, "i2c2")), /* SCK */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "csi"), /* SDA */ ++ SUNXI_FUNCTION(0x3, "i2c2")), /* SDA */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out")), ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out")), ++ /* Hole */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc0"), /* D1 */ ++ SUNXI_FUNCTION(0x3, "jtag")), /* MS */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc0"), /* D0 */ ++ SUNXI_FUNCTION(0x3, "jtag")), /* DI */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc0"), /* CLK */ ++ SUNXI_FUNCTION(0x3, "uart0")), /* TX */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc0"), /* CMD */ ++ SUNXI_FUNCTION(0x3, "jtag")), /* DO */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc0"), /* D3 */ ++ SUNXI_FUNCTION(0x3, "uart0")), /* RX */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc0"), /* D2 */ ++ SUNXI_FUNCTION(0x3, "jtag")), /* CK */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc0")), /* DET */ ++ /* Hole */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc1"), /* CLK */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 0)), /* PG_EINT0 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc1"), /* CMD */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 1)), /* PG_EINT1 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc1"), /* D0 */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 2)), /* PG_EINT2 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc1"), /* D1 */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 3)), /* PG_EINT3 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc1"), /* D2 */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 4)), /* PG_EINT4 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "mmc1"), /* D3 */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 5)), /* PG_EINT5 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart1"), /* TX */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 6)), /* PG_EINT6 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart1"), /* RX */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 7)), /* PG_EINT7 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart1"), /* RTS */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 8)), /* PG_EINT8 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "uart1"), /* CTS */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 9)), /* PG_EINT9 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s1"), /* SYNC */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 10)), /* PG_EINT10 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s1"), /* CLK */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 11)), /* PG_EINT11 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s1"), /* DOUT */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 12)), /* PG_EINT12 */ ++ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13), ++ SUNXI_FUNCTION(0x0, "gpio_in"), ++ SUNXI_FUNCTION(0x1, "gpio_out"), ++ SUNXI_FUNCTION(0x2, "i2s1"), /* DIN */ ++ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 13)), /* PG_EINT13 */ ++}; ++ ++static const struct sunxi_pinctrl_desc sun8i_h3_pinctrl_data = { ++ .pins = sun8i_h3_pins, ++ .npins = ARRAY_SIZE(sun8i_h3_pins), ++ .irq_banks = 2, ++}; ++ ++static int sun8i_h3_pinctrl_probe(struct platform_device *pdev) ++{ ++ return sunxi_pinctrl_init(pdev, ++ &sun8i_h3_pinctrl_data); ++} ++ ++static const struct of_device_id sun8i_h3_pinctrl_match[] = { ++ { .compatible = "allwinner,sun8i-h3-pinctrl", }, ++ {} ++}; ++ ++static struct platform_driver sun8i_h3_pinctrl_driver = { ++ .probe = sun8i_h3_pinctrl_probe, ++ .driver = { ++ .name = "sun8i-h3-pinctrl", ++ .of_match_table = sun8i_h3_pinctrl_match, ++ }, ++}; ++builtin_platform_driver(sun8i_h3_pinctrl_driver); diff --git a/patch/kernel/packaging-next.patch.old b/patch/kernel/packaging-next.patch.old new file mode 100644 index 000000000..b32606c43 --- /dev/null +++ b/patch/kernel/packaging-next.patch.old @@ -0,0 +1,133 @@ +diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst +old mode 100644 +new mode 100755 +index 909ed7a..f69e726 +--- a/scripts/Makefile.dtbinst ++++ b/scripts/Makefile.dtbinst +@@ -23,8 +23,8 @@ include $(srctree)/$(obj)/Makefile + PHONY += __dtbs_install_prep + __dtbs_install_prep: + ifeq ("$(dtbinst-root)", "$(obj)") +- $(Q)if [ -d $(INSTALL_DTBS_PATH).old ]; then rm -rf $(INSTALL_DTBS_PATH).old; fi +- $(Q)if [ -d $(INSTALL_DTBS_PATH) ]; then mv $(INSTALL_DTBS_PATH) $(INSTALL_DTBS_PATH).old; fi ++ #$(Q)if [ -d $(INSTALL_DTBS_PATH).old ]; then rm -rf $(INSTALL_DTBS_PATH).old; fi ++ #$(Q)if [ -d $(INSTALL_DTBS_PATH) ]; then mv $(INSTALL_DTBS_PATH) $(INSTALL_DTBS_PATH).old; fi + $(Q)mkdir -p $(INSTALL_DTBS_PATH) + endif + +diff --git a/scripts/package/builddeb b/scripts/package/builddeb +index 5972624..272d558 100755 +--- a/scripts/package/builddeb ++++ b/scripts/package/builddeb +@@ -80,11 +80,13 @@ + fwdir="$objtree/debian/fwtmp" + kernel_headers_dir="$objtree/debian/hdrtmp" + libc_headers_dir="$objtree/debian/headertmp" ++dtb_dir="$objtree/debian/dtbtmp" + dbg_dir="$objtree/debian/dbgtmp" +-packagename=linux-image-$version +-fwpackagename=linux-firmware-image-$version +-kernel_headers_packagename=linux-headers-$version +-libc_headers_packagename=linux-libc-dev ++packagename=linux-image-next"$LOCALVERSION" ++fwpackagename=linux-firmware-image-next"$LOCALVERSION" ++kernel_headers_packagename=linux-headers-next"$LOCALVERSION" ++dtb_packagename=linux-dtb-next"$LOCALVERSION" ++libc_headers_packagename=linux-libc-dev-next"$LOCALVERSION" + dbg_packagename=$packagename-dbg + + if [ "$ARCH" = "um" ] ; then +@@ -108,13 +110,17 @@ + BUILD_DEBUG="$(grep -s '^CONFIG_DEBUG_INFO=y' $KCONFIG_CONFIG || true)" + + # Setup the directory structure +-rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" ++rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" "$dtb_dir" + mkdir -m 755 -p "$tmpdir/DEBIAN" + mkdir -p "$tmpdir/lib" "$tmpdir/boot" "$tmpdir/usr/share/doc/$packagename" + mkdir -m 755 -p "$fwdir/DEBIAN" + mkdir -p "$fwdir/lib/firmware/$version/" "$fwdir/usr/share/doc/$fwpackagename" + mkdir -m 755 -p "$libc_headers_dir/DEBIAN" + mkdir -p "$libc_headers_dir/usr/share/doc/$libc_headers_packagename" ++ ++mkdir -m 755 -p "$dtb_dir/DEBIAN" ++mkdir -p "$dtb_dir/boot/dtb" "$dtb_dir/usr/share/doc/$dtb_packagename" ++ + mkdir -m 755 -p "$kernel_headers_dir/DEBIAN" + mkdir -p "$kernel_headers_dir/usr/share/doc/$kernel_headers_packagename" + mkdir -p "$kernel_headers_dir/lib/modules/$version/" +@@ -165,6 +171,11 @@ + fi + fi + ++if grep -q '^CONFIG_OF=y' $KCONFIG_CONFIG ; then ++ #mkdir -p "$tmpdir/boot/dtb" ++ INSTALL_DTBS_PATH="$dtb_dir/boot/dtb" $MAKE KBUILD_SRC= dtbs_install ++fi ++ + if [ "$ARCH" != "um" ]; then + $MAKE headers_check KBUILD_SRC= + $MAKE headers_install KBUILD_SRC= INSTALL_HDR_PATH="$libc_headers_dir/usr" +@@ -189,9 +200,11 @@ + set -e + + # Pass maintainer script parameters to hook scripts ++ + export DEB_MAINT_PARAMS="\$*" + + # Tell initramfs builder whether it's wanted ++ + export INITRD=$want_initrd + + test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d +@@ -200,6 +213,15 @@ + chmod 755 "$tmpdir/DEBIAN/$script" + done + ++## ++## Create sym link to kernel image ++## ++kernel_tmp_version="${installed_image_path////\\/}" ++sed -e "s/exit 0/ln -sf \/$kernel_tmp_version \/boot\/zImage || cp \/$kernel_tmp_version \/boot\/zImage/g" -i $tmpdir/DEBIAN/postinst ++echo "touch /boot/.next" >> $tmpdir/DEBIAN/postinst ++echo "exit 0" >> $tmpdir/DEBIAN/postinst ++ ++ + # Try to determine maintainer and email values + if [ -n "$DEBEMAIL" ]; then + email=$DEBEMAIL +@@ -315,7 +337,7 @@ + cat <> debian/control + + Package: $kernel_headers_packagename +-Provides: linux-headers, linux-headers-2.6 ++Provides: linux-headers + Architecture: any + Description: Linux kernel headers for $KERNELRELEASE on \${kernel:debarch} + This package provides kernel header files for $KERNELRELEASE on \${kernel:debarch} +@@ -341,6 +363,16 @@ + + cat <> debian/control + ++Package: $dtb_packagename ++Architecture: any ++Description: Linux DTB, version $version ++ This package contains device blobs from the Linux kernel, version $version. ++EOF ++ ++create_package "$dtb_packagename" "$dtb_dir" ++ ++cat <> debian/control ++ + Package: $libc_headers_packagename + Section: devel + Provides: linux-kernel-headers +@@ -352,7 +384,7 @@ + + if [ "$ARCH" != "um" ]; then + create_package "$kernel_headers_packagename" "$kernel_headers_dir" +- create_package "$libc_headers_packagename" "$libc_headers_dir" ++# create_package "$libc_headers_packagename" "$libc_headers_dir" + fi + + create_package "$packagename" "$tmpdir" diff --git a/patch/kernel/packaging-udoo-fix.patch b/patch/kernel/packaging-udoo-fix.patch new file mode 100644 index 000000000..4ac98d11c --- /dev/null +++ b/patch/kernel/packaging-udoo-fix.patch @@ -0,0 +1,104 @@ +--- a/scripts/package/builddeb ++++ b/scripts/package/builddeb +@@ -82,11 +82,11 @@ + libc_headers_dir="$objtree/debian/headertmp" + dtb_dir="$objtree/debian/dtbtmp" + dbg_dir="$objtree/debian/dbgtmp" +-packagename=linux-image-$version +-fwpackagename=linux-firmware-image-$version +-kernel_headers_packagename=linux-headers-$version +-dtb_packagename=linux-dtb-$version +-libc_headers_packagename=linux-libc-dev ++packagename=linux-image"$LOCALVERSION" ++fwpackagename=linux-firmware-image"$LOCALVERSION" ++kernel_headers_packagename=linux-headers"$LOCALVERSION" ++dtb_packagename=linux-dtb"$LOCALVERSION" ++libc_headers_packagename=linux-libc-dev"$LOCALVERSION" + dbg_packagename=$packagename-dbg + + if [ "$ARCH" = "um" ] ; then +@@ -173,7 +173,7 @@ + + if grep -q '^CONFIG_OF=y' $KCONFIG_CONFIG ; then + mkdir -p "$tmpdir/boot/dtb" +- cp $objtree/arch/arm/boot/dts/*.dtb $dtb_dir/boot/dtb ++ cp $objtree/arch/arm/boot/dts/*.dtb $dtb_dir/boot/dtb + #INSTALL_DTBS_PATH="$dtb_dir/boot/dtb" $MAKE KBUILD_SRC= dtbs_install + fi + +@@ -218,7 +218,8 @@ + ## Create sym link to kernel image + ## + kernel_tmp_version="${installed_image_path////\\/}" +-sed -e "s/exit 0/ln -sf \/$kernel_tmp_version \/boot\/zImage/g" -i $tmpdir/DEBIAN/postinst ++sed -e "s/exit 0/ln -sf \/$kernel_tmp_version \/boot\/zImage || cp \/$kernel_tmp_version \/boot\/zImage/g" -i $tmpdir/DEBIAN/postinst ++#echo "touch /boot/.next" >> $tmpdir/DEBIAN/postinst + echo "exit 0" >> $tmpdir/DEBIAN/postinst + + +@@ -239,9 +240,20 @@ + fi + maintainer="$name <$email>" + ++# Try to determine distribution ++if [ -n "$KDEB_CHANGELOG_DIST" ]; then ++ distribution=$KDEB_CHANGELOG_DIST ++elif distribution=$(lsb_release -cs 2>/dev/null) && [ -n "$distribution" ]; then ++ : # nothing to do in this case ++else ++ distribution="unstable" ++ echo >&2 "Using default distribution of 'unstable' in the changelog" ++ echo >&2 "Install lsb-release or set \$KDEB_CHANGELOG_DIST explicitly" ++fi ++ + # Generate a simple changelog template + cat < debian/changelog +-linux-upstream ($packageversion) unstable; urgency=low ++linux-upstream ($packageversion) $distribution; urgency=low + + * Custom built Linux kernel. + +@@ -255,10 +267,10 @@ + The sources may be found at most Linux ftp sites, including: + ftp://ftp.kernel.org/pub/linux/kernel + +-Copyright: 1991 - 2009 Linus Torvalds and others. ++Copyright: 1991 - 2015 Linus Torvalds and others. + + The git repository for mainline kernel development is at: +-git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git ++git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +@@ -317,6 +329,12 @@ + (cd $objtree; find arch/$SRCARCH/include Module.symvers include scripts -type f) >> "$objtree/debian/hdrobjfiles" + destdir=$kernel_headers_dir/usr/src/linux-headers-$version + mkdir -p "$destdir" ++######################## headers patch ++ZACNI=$(pwd) ++cd $destdir ++patch -p1 < /tmp/headers-debian-byteshift.patch ++cd $ZACNI ++######################## headers patch + (cd $srctree; tar -c -f - -T -) < "$objtree/debian/hdrsrcfiles" | (cd $destdir; tar -xf -) + (cd $objtree; tar -c -f - -T -) < "$objtree/debian/hdrobjfiles" | (cd $destdir; tar -xf -) + (cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be +@@ -326,7 +344,7 @@ + cat <> debian/control + + Package: $kernel_headers_packagename +-Provides: linux-headers, linux-headers-2.6 ++Provides: linux-headers + Architecture: any + Description: Linux kernel headers for $KERNELRELEASE on \${kernel:debarch} + This package provides kernel header files for $KERNELRELEASE on \${kernel:debarch} +@@ -373,7 +391,7 @@ + + if [ "$ARCH" != "um" ]; then + create_package "$kernel_headers_packagename" "$kernel_headers_dir" +- create_package "$libc_headers_packagename" "$libc_headers_dir" ++# create_package "$libc_headers_packagename" "$libc_headers_dir" + fi + + create_package "$packagename" "$tmpdir" diff --git a/patch/kernel/s500-default/packagin-guitar.patch b/patch/kernel/s500-default/packagin-guitar.patch new file mode 100644 index 000000000..a6bdb1383 --- /dev/null +++ b/patch/kernel/s500-default/packagin-guitar.patch @@ -0,0 +1,311 @@ +diff --git a/scripts/package/builddeb b/scripts/package/builddeb +old mode 100644 +new mode 100755 +index 3001ec5..d6b844d +--- a/scripts/package/builddeb ++++ b/scripts/package/builddeb +@@ -35,15 +35,17 @@ create_package() { + sparc*) + debarch=sparc ;; + s390*) +- debarch=s390 ;; ++ debarch=s390$(grep -q CONFIG_64BIT=y $KCONFIG_CONFIG && echo x || true) ;; + ppc*) +- debarch=powerpc ;; ++ debarch=$(grep -q CPU_LITTLE_ENDIAN=y $KCONFIG_CONFIG && echo ppc64el || echo powerpc) ;; + parisc*) + debarch=hppa ;; + mips*) +- debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y .config && echo el) ;; ++ debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y $KCONFIG_CONFIG && echo el || true) ;; ++ arm64) ++ debarch=arm64 ;; + arm*) +- debarch=arm$(grep -q CONFIG_AEABI=y .config && echo el) ;; ++ debarch=arm$(grep -q CONFIG_AEABI=y $KCONFIG_CONFIG && echo el || true) ;; + *) + echo "" >&2 + echo "** ** ** WARNING ** ** **" >&2 +@@ -62,7 +64,7 @@ create_package() { + fi + + # Create the package +- dpkg-gencontrol -isp $forcearch -Vkernel:debarch="${debarch:-$(dpkg --print-architecture)}" -p$pname -P"$pdir" ++ dpkg-gencontrol $forcearch -Vkernel:debarch="${debarch:-$(dpkg --print-architecture)}" -p$pname -P"$pdir" + dpkg --build "$pdir" .. + } + +@@ -78,49 +80,76 @@ tmpdir="$objtree/debian/tmp" + fwdir="$objtree/debian/fwtmp" + kernel_headers_dir="$objtree/debian/hdrtmp" + libc_headers_dir="$objtree/debian/headertmp" +-packagename=linux-image-$version +-fwpackagename=linux-firmware-image +-kernel_headers_packagename=linux-headers-$version +-libc_headers_packagename=linux-libc-dev ++dtb_dir="$objtree/debian/dtbtmp" ++dbg_dir="$objtree/debian/dbgtmp" ++packagename=linux-image"$LOCALVERSION" ++fwpackagename=linux-firmware-image"$LOCALVERSION" ++kernel_headers_packagename=linux-headers"$LOCALVERSION" ++dtb_packagename=linux-dtb"$LOCALVERSION" ++libc_headers_packagename=linux-libc-dev"$LOCALVERSION" ++dbg_packagename=$packagename-dbg + + if [ "$ARCH" = "um" ] ; then + packagename=user-mode-linux-$version + fi + ++# Not all arches have the same installed path in debian ++# XXX: have each arch Makefile export a variable of the canonical image install ++# path instead ++case $ARCH in ++um) ++ installed_image_path="usr/bin/linux-$version" ++ ;; ++parisc|mips|powerpc) ++ installed_image_path="boot/vmlinux-$version" ++ ;; ++*) ++ installed_image_path="boot/vmlinuz-$version" ++esac ++ ++BUILD_DEBUG="$(grep -s '^CONFIG_DEBUG_INFO=y' $KCONFIG_CONFIG || true)" ++ + # Setup the directory structure +-rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" ++rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" "$dtb_dir" + mkdir -m 755 -p "$tmpdir/DEBIAN" + mkdir -p "$tmpdir/lib" "$tmpdir/boot" "$tmpdir/usr/share/doc/$packagename" + mkdir -m 755 -p "$fwdir/DEBIAN" + mkdir -p "$fwdir/lib/firmware/$version/" "$fwdir/usr/share/doc/$fwpackagename" + mkdir -m 755 -p "$libc_headers_dir/DEBIAN" + mkdir -p "$libc_headers_dir/usr/share/doc/$libc_headers_packagename" ++ ++mkdir -m 755 -p "$dtb_dir/DEBIAN" ++mkdir -p "$dtb_dir/boot/dtb" "$dtb_dir/usr/share/doc/$dtb_packagename" ++ + mkdir -m 755 -p "$kernel_headers_dir/DEBIAN" + mkdir -p "$kernel_headers_dir/usr/share/doc/$kernel_headers_packagename" + mkdir -p "$kernel_headers_dir/lib/modules/$version/" + if [ "$ARCH" = "um" ] ; then + mkdir -p "$tmpdir/usr/lib/uml/modules/$version" "$tmpdir/usr/bin" + fi ++if [ -n "$BUILD_DEBUG" ] ; then ++ mkdir -p "$dbg_dir/usr/share/doc/$dbg_packagename" ++ mkdir -m 755 -p "$dbg_dir/DEBIAN" ++fi + + # Build and install the kernel + if [ "$ARCH" = "um" ] ; then + $MAKE linux + cp System.map "$tmpdir/usr/lib/uml/modules/$version/System.map" +- cp .config "$tmpdir/usr/share/doc/$packagename/config" ++ cp $KCONFIG_CONFIG "$tmpdir/usr/share/doc/$packagename/config" + gzip "$tmpdir/usr/share/doc/$packagename/config" +- cp $KBUILD_IMAGE "$tmpdir/usr/bin/linux-$version" +-else ++else + cp System.map "$tmpdir/boot/System.map-$version" +- cp .config "$tmpdir/boot/config-$version" +- # Not all arches include the boot path in KBUILD_IMAGE +- if [ -e $KBUILD_IMAGE ]; then +- cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version" +- else +- cp arch/$ARCH/boot/$KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version" +- fi ++ cp $KCONFIG_CONFIG "$tmpdir/boot/config-$version" ++fi ++# Not all arches include the boot path in KBUILD_IMAGE ++if [ -e $KBUILD_IMAGE ]; then ++ cp $KBUILD_IMAGE "$tmpdir/$installed_image_path" ++else ++ cp arch/$ARCH/boot/$KBUILD_IMAGE "$tmpdir/$installed_image_path" + fi + +-if grep -q '^CONFIG_MODULES=y' .config ; then ++if grep -q '^CONFIG_MODULES=y' $KCONFIG_CONFIG ; then + INSTALL_MOD_PATH="$tmpdir" $MAKE KBUILD_SRC= modules_install + rm -f "$tmpdir/lib/modules/$version/build" + rm -f "$tmpdir/lib/modules/$version/source" +@@ -128,6 +157,24 @@ if grep -q '^CONFIG_MODULES=y' .config ; then + mv "$tmpdir/lib/modules/$version"/* "$tmpdir/usr/lib/uml/modules/$version/" + rmdir "$tmpdir/lib/modules/$version" + fi ++ if [ -n "$BUILD_DEBUG" ] ; then ++ for module in $(find $tmpdir/lib/modules/ -name *.ko -printf '%P\n'); do ++ module=lib/modules/$module ++ mkdir -p $(dirname $dbg_dir/usr/lib/debug/$module) ++ # only keep debug symbols in the debug file ++ $OBJCOPY --only-keep-debug $tmpdir/$module $dbg_dir/usr/lib/debug/$module ++ # strip original module from debug symbols ++ $OBJCOPY --strip-debug $tmpdir/$module ++ # then add a link to those ++ $OBJCOPY --add-gnu-debuglink=$dbg_dir/usr/lib/debug/$module $tmpdir/$module ++ done ++ fi ++fi ++ ++if grep -q '^CONFIG_OF=y' $KCONFIG_CONFIG ; then ++ mkdir -p "$tmpdir/boot/dtb" ++ cp $objtree/arch/arm/boot/dts/*.dtb $dtb_dir/boot/dtb ++ #INSTALL_DTBS_PATH="$dtb_dir/boot/dtb" $MAKE KBUILD_SRC= dtbs_install + fi + + if [ "$ARCH" != "um" ]; then +@@ -137,8 +184,15 @@ fi + + # Install the maintainer scripts + # Note: hook scripts under /etc/kernel are also executed by official Debian +-# kernel packages, as well as kernel packages built using make-kpkg ++# kernel packages, as well as kernel packages built using make-kpkg. ++# make-kpkg sets $INITRD to indicate whether an initramfs is wanted, and ++# so do we; recent versions of dracut and initramfs-tools will obey this. + debhookdir=${KDEB_HOOKDIR:-/etc/kernel} ++if grep -q '^CONFIG_BLK_DEV_INITRD=y' $KCONFIG_CONFIG; then ++ want_initrd=Yes ++else ++ want_initrd=No ++fi + for script in postinst postrm preinst prerm ; do + mkdir -p "$tmpdir$debhookdir/$script.d" + cat < "$tmpdir/DEBIAN/$script" +@@ -147,14 +201,43 @@ for script in postinst postrm preinst prerm ; do + set -e + + # Pass maintainer script parameters to hook scripts ++ + export DEB_MAINT_PARAMS="\$*" + +-test -d $debhookdir/$script.d && run-parts --arg="$version" $debhookdir/$script.d ++# Tell initramfs builder whether it's wanted ++ ++export INITRD=$want_initrd ++ ++test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d + exit 0 + EOF + chmod 755 "$tmpdir/DEBIAN/$script" + done + ++## ++## Create sym link to kernel image ++## ++sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/postinst ++cat >> $tmpdir/DEBIAN/postinst < /dev/null 2>&1 ++rm -f /$installed_image_path /boot/zImage ++else ++ln -sf /$installed_image_path /boot/zImage > /dev/null 2>&1 || mv /$installed_image_path /boot/zImage ++fi ++rm -f /boot/.next ++exit 0 ++EOT ++## ++## FAT install workaround ++## ++sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/preinst ++cat >> $tmpdir/DEBIAN/preinst <> $tmpdir/DEBIAN/preinst ++ ++ + # Try to determine maintainer and email values + if [ -n "$DEBEMAIL" ]; then + email=$DEBEMAIL +@@ -242,21 +325,30 @@ EOF + + fi + +-# Build header package +-(cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl > "$objtree/debian/hdrsrcfiles") +-(cd $srctree; find arch/$SRCARCH/include include scripts -type f >> "$objtree/debian/hdrsrcfiles") +-(cd $objtree; find arch/$SRCARCH/include .config Module.symvers include scripts -type f >> "$objtree/debian/hdrobjfiles") ++# Build kernel header package ++(cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl) > "$objtree/debian/hdrsrcfiles" ++(cd $srctree; find arch/$SRCARCH/include include scripts -type f) >> "$objtree/debian/hdrsrcfiles" ++(cd $srctree; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$objtree/debian/hdrsrcfiles" ++(cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$objtree/debian/hdrsrcfiles" ++(cd $objtree; find arch/$SRCARCH/include Module.symvers include scripts -type f) >> "$objtree/debian/hdrobjfiles" + destdir=$kernel_headers_dir/usr/src/linux-headers-$version + mkdir -p "$destdir" +-(cd $srctree; tar -c -f - -T "$objtree/debian/hdrsrcfiles") | (cd $destdir; tar -xf -) +-(cd $objtree; tar -c -f - -T "$objtree/debian/hdrobjfiles") | (cd $destdir; tar -xf -) ++######################## headers patch ++ZACNI=$(pwd) ++cd $destdir ++patch -p1 < /tmp/headers-debian-byteshift.patch ++cd $ZACNI ++######################## headers patch ++(cd $srctree; tar -c -f - -T -) < "$objtree/debian/hdrsrcfiles" | (cd $destdir; tar -xf -) ++(cd $objtree; tar -c -f - -T -) < "$objtree/debian/hdrobjfiles" | (cd $destdir; tar -xf -) ++(cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be + ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build" + rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles" + + cat <> debian/control + + Package: $kernel_headers_packagename +-Provides: linux-headers, linux-headers-2.6 ++Provides: linux-headers + Architecture: any + Description: Linux kernel headers for $KERNELRELEASE on \${kernel:debarch} + This package provides kernel header files for $KERNELRELEASE on \${kernel:debarch} +@@ -282,6 +374,16 @@ fi + + cat <> debian/control + ++Package: $dtb_packagename ++Architecture: any ++Description: Linux DTB, version $version ++ This package contains device blobs from the Linux kernel, version $version. ++EOF ++ ++create_package "$dtb_packagename" "$dtb_dir" ++ ++cat <> debian/control ++ + Package: $libc_headers_packagename + Section: devel + Provides: linux-kernel-headers +@@ -293,9 +395,35 @@ EOF + + if [ "$ARCH" != "um" ]; then + create_package "$kernel_headers_packagename" "$kernel_headers_dir" +- create_package "$libc_headers_packagename" "$libc_headers_dir" ++# create_package "$libc_headers_packagename" "$libc_headers_dir" + fi + + create_package "$packagename" "$tmpdir" + +-exit 0 ++if [ -n "$BUILD_DEBUG" ] ; then ++ # Build debug package ++ # Different tools want the image in different locations ++ # perf ++ mkdir -p $dbg_dir/usr/lib/debug/lib/modules/$version/ ++ cp vmlinux $dbg_dir/usr/lib/debug/lib/modules/$version/ ++ # systemtap ++ mkdir -p $dbg_dir/usr/lib/debug/boot/ ++ ln -s ../lib/modules/$version/vmlinux $dbg_dir/usr/lib/debug/boot/vmlinux-$version ++ # kdump-tools ++ ln -s lib/modules/$version/vmlinux $dbg_dir/usr/lib/debug/vmlinux-$version ++ ++ cat <> debian/control ++ ++Package: $dbg_packagename ++Section: debug ++Provides: linux-debug, linux-debug-$version ++Architecture: any ++Description: Linux kernel debugging symbols for $version ++ This package will come in handy if you need to debug the kernel. It provides ++ all the necessary debug symbols for the kernel and its modules. ++EOF ++ ++ create_package "$dbg_packagename" "$dbg_dir" ++fi ++ ++exit 0 +\ No newline at end of file diff --git a/patch/kernel/s500-default/patch-3.10.37-38.patch b/patch/kernel/s500-default/patch-3.10.37-38.patch new file mode 100644 index 000000000..e51b075a1 --- /dev/null +++ b/patch/kernel/s500-default/patch-3.10.37-38.patch @@ -0,0 +1,719 @@ +diff --git a/Makefile b/Makefile +index bd9fb5b72fc0..bd51b50a567b 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 10 +-SUBLEVEL = 37 ++SUBLEVEL = 38 + EXTRAVERSION = + NAME = TOSSUG Baby Fish + +diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig +index 9ac9f1666339..2668b3142fa2 100644 +--- a/arch/sparc/Kconfig ++++ b/arch/sparc/Kconfig +@@ -25,7 +25,7 @@ config SPARC + select RTC_DRV_M48T59 + select HAVE_DMA_ATTRS + select HAVE_DMA_API_DEBUG +- select HAVE_ARCH_JUMP_LABEL ++ select HAVE_ARCH_JUMP_LABEL if SPARC64 + select HAVE_GENERIC_HARDIRQS + select GENERIC_IRQ_SHOW + select ARCH_WANT_IPC_PARSE_VERSION +diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h +index e562d3caee57..ad7e178337f1 100644 +--- a/arch/sparc/include/asm/uaccess_64.h ++++ b/arch/sparc/include/asm/uaccess_64.h +@@ -262,8 +262,8 @@ extern unsigned long __must_check __clear_user(void __user *, unsigned long); + extern __must_check long strlen_user(const char __user *str); + extern __must_check long strnlen_user(const char __user *str, long n); + +-#define __copy_to_user_inatomic ___copy_to_user +-#define __copy_from_user_inatomic ___copy_from_user ++#define __copy_to_user_inatomic __copy_to_user ++#define __copy_from_user_inatomic __copy_from_user + + struct pt_regs; + extern unsigned long compute_effective_address(struct pt_regs *, +diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c +index baf4366e2d6a..906cbf0f8608 100644 +--- a/arch/sparc/kernel/pci.c ++++ b/arch/sparc/kernel/pci.c +@@ -399,8 +399,8 @@ static void apb_fake_ranges(struct pci_dev *dev, + apb_calc_first_last(map, &first, &last); + res = bus->resource[1]; + res->flags = IORESOURCE_MEM; +- region.start = (first << 21); +- region.end = (last << 21) + ((1 << 21) - 1); ++ region.start = (first << 29); ++ region.end = (last << 29) + ((1 << 29) - 1); + pcibios_bus_to_resource(dev, res, ®ion); + } + +diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c +index baebab215492..b9cc9763faf4 100644 +--- a/arch/sparc/kernel/process_64.c ++++ b/arch/sparc/kernel/process_64.c +@@ -57,9 +57,12 @@ void arch_cpu_idle(void) + { + if (tlb_type != hypervisor) { + touch_nmi_watchdog(); ++ local_irq_enable(); + } else { + unsigned long pstate; + ++ local_irq_enable(); ++ + /* The sun4v sleeping code requires that we have PSTATE.IE cleared over + * the cpu sleep hypervisor call. + */ +@@ -81,7 +84,6 @@ void arch_cpu_idle(void) + : "=&r" (pstate) + : "i" (PSTATE_IE)); + } +- local_irq_enable(); + } + + #ifdef CONFIG_HOTPLUG_CPU +diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S +index 73ec8a798d95..c79c687fbe1e 100644 +--- a/arch/sparc/kernel/syscalls.S ++++ b/arch/sparc/kernel/syscalls.S +@@ -189,7 +189,8 @@ linux_sparc_syscall32: + mov %i0, %l5 ! IEU1 + 5: call %l7 ! CTI Group brk forced + srl %i5, 0, %o5 ! IEU1 +- ba,a,pt %xcc, 3f ++ ba,pt %xcc, 3f ++ sra %o0, 0, %o0 + + /* Linux native system calls enter here... */ + .align 32 +@@ -217,7 +218,6 @@ linux_sparc_syscall: + 3: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] + ret_sys_call: + ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3 +- sra %o0, 0, %o0 + mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 + sllx %g2, 32, %g2 + +diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c +index 63bdb29b2549..4f7c82cdd0f5 100644 +--- a/arch/x86/kernel/early-quirks.c ++++ b/arch/x86/kernel/early-quirks.c +@@ -202,18 +202,15 @@ static void __init intel_remapping_check(int num, int slot, int func) + revision = read_pci_config_byte(num, slot, func, PCI_REVISION_ID); + + /* +- * Revision 13 of all triggering devices id in this quirk have +- * a problem draining interrupts when irq remapping is enabled, +- * and should be flagged as broken. Additionally revisions 0x12 +- * and 0x22 of device id 0x3405 has this problem. ++ * Revision <= 13 of all triggering devices id in this quirk ++ * have a problem draining interrupts when irq remapping is ++ * enabled, and should be flagged as broken. Additionally ++ * revision 0x22 of device id 0x3405 has this problem. + */ +- if (revision == 0x13) ++ if (revision <= 0x13) + set_irq_remapping_broken(); +- else if ((device == 0x3405) && +- ((revision == 0x12) || +- (revision == 0x22))) ++ else if (device == 0x3405 && revision == 0x22) + set_irq_remapping_broken(); +- + } + + #define QFLAG_APPLY_ONCE 0x1 +diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c +index a22a7a502740..8156cafad11a 100644 +--- a/drivers/char/ipmi/ipmi_bt_sm.c ++++ b/drivers/char/ipmi/ipmi_bt_sm.c +@@ -352,7 +352,7 @@ static inline void write_all_bytes(struct si_sm_data *bt) + + static inline int read_all_bytes(struct si_sm_data *bt) + { +- unsigned char i; ++ unsigned int i; + + /* + * length is "framing info", minimum = 4: NetFn, Seq, Cmd, cCode. +diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c +index 05bcf0dffb8c..e54031c558e8 100644 +--- a/drivers/staging/comedi/drivers/8255_pci.c ++++ b/drivers/staging/comedi/drivers/8255_pci.c +@@ -59,6 +59,7 @@ Configuration Options: not applicable, uses PCI auto config + #include "../comedidev.h" + + #include "8255.h" ++#include "mite.h" + + enum pci_8255_boardid { + BOARD_ADLINK_PCI7224, +@@ -82,6 +83,7 @@ struct pci_8255_boardinfo { + const char *name; + int dio_badr; + int n_8255; ++ unsigned int has_mite:1; + }; + + static const struct pci_8255_boardinfo pci_8255_boards[] = { +@@ -129,36 +131,43 @@ static const struct pci_8255_boardinfo pci_8255_boards[] = { + .name = "ni_pci-dio-96", + .dio_badr = 1, + .n_8255 = 4, ++ .has_mite = 1, + }, + [BOARD_NI_PCIDIO96B] = { + .name = "ni_pci-dio-96b", + .dio_badr = 1, + .n_8255 = 4, ++ .has_mite = 1, + }, + [BOARD_NI_PXI6508] = { + .name = "ni_pxi-6508", + .dio_badr = 1, + .n_8255 = 4, ++ .has_mite = 1, + }, + [BOARD_NI_PCI6503] = { + .name = "ni_pci-6503", + .dio_badr = 1, + .n_8255 = 1, ++ .has_mite = 1, + }, + [BOARD_NI_PCI6503B] = { + .name = "ni_pci-6503b", + .dio_badr = 1, + .n_8255 = 1, ++ .has_mite = 1, + }, + [BOARD_NI_PCI6503X] = { + .name = "ni_pci-6503x", + .dio_badr = 1, + .n_8255 = 1, ++ .has_mite = 1, + }, + [BOARD_NI_PXI_6503] = { + .name = "ni_pxi-6503", + .dio_badr = 1, + .n_8255 = 1, ++ .has_mite = 1, + }, + }; + +@@ -166,6 +175,25 @@ struct pci_8255_private { + void __iomem *mmio_base; + }; + ++static int pci_8255_mite_init(struct pci_dev *pcidev) ++{ ++ void __iomem *mite_base; ++ u32 main_phys_addr; ++ ++ /* ioremap the MITE registers (BAR 0) temporarily */ ++ mite_base = pci_ioremap_bar(pcidev, 0); ++ if (!mite_base) ++ return -ENOMEM; ++ ++ /* set data window to main registers (BAR 1) */ ++ main_phys_addr = pci_resource_start(pcidev, 1); ++ writel(main_phys_addr | WENAB, mite_base + MITE_IODWBSR); ++ ++ /* finished with MITE registers */ ++ iounmap(mite_base); ++ return 0; ++} ++ + static int pci_8255_mmio(int dir, int port, int data, unsigned long iobase) + { + void __iomem *mmio_base = (void __iomem *)iobase; +@@ -205,6 +233,12 @@ static int pci_8255_auto_attach(struct comedi_device *dev, + if (ret) + return ret; + ++ if (board->has_mite) { ++ ret = pci_8255_mite_init(pcidev); ++ if (ret) ++ return ret; ++ } ++ + is_mmio = (pci_resource_flags(pcidev, board->dio_badr) & + IORESOURCE_MEM) != 0; + if (is_mmio) { +diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c +index 59d26ef538d8..3723c0ebb316 100644 +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -1267,12 +1267,13 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p) + * + * Locking: None + */ +-static void tty_line_name(struct tty_driver *driver, int index, char *p) ++static ssize_t tty_line_name(struct tty_driver *driver, int index, char *p) + { + if (driver->flags & TTY_DRIVER_UNNUMBERED_NODE) +- strcpy(p, driver->name); ++ return sprintf(p, "%s", driver->name); + else +- sprintf(p, "%s%d", driver->name, index + driver->name_base); ++ return sprintf(p, "%s%d", driver->name, ++ index + driver->name_base); + } + + /** +@@ -3538,9 +3539,19 @@ static ssize_t show_cons_active(struct device *dev, + if (i >= ARRAY_SIZE(cs)) + break; + } +- while (i--) +- count += sprintf(buf + count, "%s%d%c", +- cs[i]->name, cs[i]->index, i ? ' ':'\n'); ++ while (i--) { ++ int index = cs[i]->index; ++ struct tty_driver *drv = cs[i]->device(cs[i], &index); ++ ++ /* don't resolve tty0 as some programs depend on it */ ++ if (drv && (cs[i]->index > 0 || drv->major != TTY_MAJOR)) ++ count += tty_line_name(drv, index, buf + count); ++ else ++ count += sprintf(buf + count, "%s%d", ++ cs[i]->name, cs[i]->index); ++ ++ count += sprintf(buf + count, "%c", i ? ' ':'\n'); ++ } + console_unlock(); + + return count; +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index b8b60b660c8f..4354b9127713 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -3161,6 +3161,8 @@ static int barrier_all_devices(struct btrfs_fs_info *info) + /* send down all the barriers */ + head = &info->fs_devices->devices; + list_for_each_entry_rcu(dev, head, dev_list) { ++ if (dev->missing) ++ continue; + if (!dev->bdev) { + errors_send++; + continue; +@@ -3175,6 +3177,8 @@ static int barrier_all_devices(struct btrfs_fs_info *info) + + /* wait for all the barriers */ + list_for_each_entry_rcu(dev, head, dev_list) { ++ if (dev->missing) ++ continue; + if (!dev->bdev) { + errors_wait++; + continue; +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index a2b625e279db..84d817b842a8 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -2511,6 +2511,27 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, + ex_ee_block = le32_to_cpu(ex->ee_block); + ex_ee_len = ext4_ext_get_actual_len(ex); + ++ /* ++ * If we're starting with an extent other than the last one in the ++ * node, we need to see if it shares a cluster with the extent to ++ * the right (towards the end of the file). If its leftmost cluster ++ * is this extent's rightmost cluster and it is not cluster aligned, ++ * we'll mark it as a partial that is not to be deallocated. ++ */ ++ ++ if (ex != EXT_LAST_EXTENT(eh)) { ++ ext4_fsblk_t current_pblk, right_pblk; ++ long long current_cluster, right_cluster; ++ ++ current_pblk = ext4_ext_pblock(ex) + ex_ee_len - 1; ++ current_cluster = (long long)EXT4_B2C(sbi, current_pblk); ++ right_pblk = ext4_ext_pblock(ex + 1); ++ right_cluster = (long long)EXT4_B2C(sbi, right_pblk); ++ if (current_cluster == right_cluster && ++ EXT4_PBLK_COFF(sbi, right_pblk)) ++ *partial_cluster = -right_cluster; ++ } ++ + trace_ext4_ext_rm_leaf(inode, start, ex, *partial_cluster); + + while (ex >= EXT_FIRST_EXTENT(eh) && +@@ -4032,7 +4053,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, + struct ext4_extent newex, *ex, *ex2; + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + ext4_fsblk_t newblock = 0; +- int free_on_err = 0, err = 0, depth; ++ int free_on_err = 0, err = 0, depth, ret; + unsigned int allocated = 0, offset = 0; + unsigned int allocated_clusters = 0; + struct ext4_allocation_request ar; +@@ -4093,9 +4114,13 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, + if (!ext4_ext_is_uninitialized(ex)) + goto out; + +- allocated = ext4_ext_handle_uninitialized_extents( ++ ret = ext4_ext_handle_uninitialized_extents( + handle, inode, map, path, flags, + allocated, newblock); ++ if (ret < 0) ++ err = ret; ++ else ++ allocated = ret; + goto out3; + } + } +diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c +index e3ab1e4dc442..387213ac2608 100644 +--- a/fs/fs-writeback.c ++++ b/fs/fs-writeback.c +@@ -87,16 +87,29 @@ static inline struct inode *wb_inode(struct list_head *head) + #define CREATE_TRACE_POINTS + #include + ++static void bdi_wakeup_thread(struct backing_dev_info *bdi) ++{ ++ spin_lock_bh(&bdi->wb_lock); ++ if (test_bit(BDI_registered, &bdi->state)) ++ mod_delayed_work(bdi_wq, &bdi->wb.dwork, 0); ++ spin_unlock_bh(&bdi->wb_lock); ++} ++ + static void bdi_queue_work(struct backing_dev_info *bdi, + struct wb_writeback_work *work) + { + trace_writeback_queue(bdi, work); + + spin_lock_bh(&bdi->wb_lock); ++ if (!test_bit(BDI_registered, &bdi->state)) { ++ if (work->done) ++ complete(work->done); ++ goto out_unlock; ++ } + list_add_tail(&work->list, &bdi->work_list); +- spin_unlock_bh(&bdi->wb_lock); +- + mod_delayed_work(bdi_wq, &bdi->wb.dwork, 0); ++out_unlock: ++ spin_unlock_bh(&bdi->wb_lock); + } + + static void +@@ -112,7 +125,7 @@ __bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages, + work = kzalloc(sizeof(*work), GFP_ATOMIC); + if (!work) { + trace_writeback_nowork(bdi); +- mod_delayed_work(bdi_wq, &bdi->wb.dwork, 0); ++ bdi_wakeup_thread(bdi); + return; + } + +@@ -159,7 +172,7 @@ void bdi_start_background_writeback(struct backing_dev_info *bdi) + * writeback as soon as there is no other work to do. + */ + trace_writeback_wake_background(bdi); +- mod_delayed_work(bdi_wq, &bdi->wb.dwork, 0); ++ bdi_wakeup_thread(bdi); + } + + /* +@@ -1016,7 +1029,7 @@ void bdi_writeback_workfn(struct work_struct *work) + current->flags |= PF_SWAPWRITE; + + if (likely(!current_is_workqueue_rescuer() || +- list_empty(&bdi->bdi_list))) { ++ !test_bit(BDI_registered, &bdi->state))) { + /* + * The normal path. Keep writing back @bdi until its + * work_list is empty. Note that this path is also taken +@@ -1038,10 +1051,10 @@ void bdi_writeback_workfn(struct work_struct *work) + trace_writeback_pages_written(pages_written); + } + +- if (!list_empty(&bdi->work_list) || +- (wb_has_dirty_io(wb) && dirty_writeback_interval)) +- queue_delayed_work(bdi_wq, &wb->dwork, +- msecs_to_jiffies(dirty_writeback_interval * 10)); ++ if (!list_empty(&bdi->work_list)) ++ mod_delayed_work(bdi_wq, &wb->dwork, 0); ++ else if (wb_has_dirty_io(wb) && dirty_writeback_interval) ++ bdi_wakeup_thread_delayed(bdi); + + current->flags &= ~PF_SWAPWRITE; + } +diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c +index 16a5047903a6..406d9cc84ba8 100644 +--- a/fs/jffs2/compr_rtime.c ++++ b/fs/jffs2/compr_rtime.c +@@ -33,7 +33,7 @@ static int jffs2_rtime_compress(unsigned char *data_in, + unsigned char *cpage_out, + uint32_t *sourcelen, uint32_t *dstlen) + { +- short positions[256]; ++ unsigned short positions[256]; + int outpos = 0; + int pos=0; + +@@ -74,7 +74,7 @@ static int jffs2_rtime_decompress(unsigned char *data_in, + unsigned char *cpage_out, + uint32_t srclen, uint32_t destlen) + { +- short positions[256]; ++ unsigned short positions[256]; + int outpos = 0; + int pos=0; + +diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h +index e4619b00f7c5..fa35ff79ab35 100644 +--- a/fs/jffs2/nodelist.h ++++ b/fs/jffs2/nodelist.h +@@ -231,7 +231,7 @@ struct jffs2_tmp_dnode_info + uint32_t version; + uint32_t data_crc; + uint32_t partial_crc; +- uint16_t csize; ++ uint32_t csize; + uint16_t overlapped; + }; + +diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c +index 03310721712f..b6bd4affd9ad 100644 +--- a/fs/jffs2/nodemgmt.c ++++ b/fs/jffs2/nodemgmt.c +@@ -179,6 +179,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, + spin_unlock(&c->erase_completion_lock); + + schedule(); ++ remove_wait_queue(&c->erase_wait, &wait); + } else + spin_unlock(&c->erase_completion_lock); + } else if (ret) +@@ -211,20 +212,25 @@ out: + int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, + uint32_t *len, uint32_t sumsize) + { +- int ret = -EAGAIN; ++ int ret; + minsize = PAD(minsize); + + jffs2_dbg(1, "%s(): Requested 0x%x bytes\n", __func__, minsize); + +- spin_lock(&c->erase_completion_lock); +- while(ret == -EAGAIN) { ++ while (true) { ++ spin_lock(&c->erase_completion_lock); + ret = jffs2_do_reserve_space(c, minsize, len, sumsize); + if (ret) { + jffs2_dbg(1, "%s(): looping, ret is %d\n", + __func__, ret); + } ++ spin_unlock(&c->erase_completion_lock); ++ ++ if (ret == -EAGAIN) ++ cond_resched(); ++ else ++ break; + } +- spin_unlock(&c->erase_completion_lock); + if (!ret) + ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1); + +diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h +index c3881553f7d1..4cfdbf28fc6a 100644 +--- a/include/linux/backing-dev.h ++++ b/include/linux/backing-dev.h +@@ -95,7 +95,7 @@ struct backing_dev_info { + unsigned int max_ratio, max_prop_frac; + + struct bdi_writeback wb; /* default writeback info for this bdi */ +- spinlock_t wb_lock; /* protects work_list */ ++ spinlock_t wb_lock; /* protects work_list & wb.dwork scheduling */ + + struct list_head work_list; + +diff --git a/kernel/exit.c b/kernel/exit.c +index 7bb73f9d09db..6682b2ea5b11 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -570,9 +570,6 @@ static void reparent_leader(struct task_struct *father, struct task_struct *p, + struct list_head *dead) + { + list_move_tail(&p->sibling, &p->real_parent->children); +- +- if (p->exit_state == EXIT_DEAD) +- return; + /* + * If this is a threaded reparent there is no need to + * notify anyone anything has happened. +@@ -580,9 +577,19 @@ static void reparent_leader(struct task_struct *father, struct task_struct *p, + if (same_thread_group(p->real_parent, father)) + return; + +- /* We don't want people slaying init. */ ++ /* ++ * We don't want people slaying init. ++ * ++ * Note: we do this even if it is EXIT_DEAD, wait_task_zombie() ++ * can change ->exit_state to EXIT_ZOMBIE. If this is the final ++ * state, do_notify_parent() was already called and ->exit_signal ++ * doesn't matter. ++ */ + p->exit_signal = SIGCHLD; + ++ if (p->exit_state == EXIT_DEAD) ++ return; ++ + /* If it has exited notify the new parent about this child's death. */ + if (!p->ptrace && + p->exit_state == EXIT_ZOMBIE && thread_group_empty(p)) { +@@ -794,6 +801,8 @@ void do_exit(long code) + exit_shm(tsk); + exit_files(tsk); + exit_fs(tsk); ++ if (group_dead) ++ disassociate_ctty(1); + exit_task_namespaces(tsk); + exit_task_work(tsk); + check_stack_usage(); +@@ -809,13 +818,9 @@ void do_exit(long code) + + cgroup_exit(tsk, 1); + +- if (group_dead) +- disassociate_ctty(1); +- + module_put(task_thread_info(tsk)->exec_domain->module); + + proc_exit_connector(tsk); +- + /* + * FIXME: do that only when needed, using sched_exit tracepoint + */ +diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c +index 6917e8edb48e..e32703d5e0ab 100644 +--- a/kernel/pid_namespace.c ++++ b/kernel/pid_namespace.c +@@ -312,7 +312,9 @@ static void *pidns_get(struct task_struct *task) + struct pid_namespace *ns; + + rcu_read_lock(); +- ns = get_pid_ns(task_active_pid_ns(task)); ++ ns = task_active_pid_ns(task); ++ if (ns) ++ get_pid_ns(ns); + rcu_read_unlock(); + + return ns; +diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c +index 9064b919a406..9bea1d7dd21f 100644 +--- a/kernel/user_namespace.c ++++ b/kernel/user_namespace.c +@@ -148,7 +148,7 @@ static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count) + + /* Find the matching extent */ + extents = map->nr_extents; +- smp_read_barrier_depends(); ++ smp_rmb(); + for (idx = 0; idx < extents; idx++) { + first = map->extent[idx].first; + last = first + map->extent[idx].count - 1; +@@ -172,7 +172,7 @@ static u32 map_id_down(struct uid_gid_map *map, u32 id) + + /* Find the matching extent */ + extents = map->nr_extents; +- smp_read_barrier_depends(); ++ smp_rmb(); + for (idx = 0; idx < extents; idx++) { + first = map->extent[idx].first; + last = first + map->extent[idx].count - 1; +@@ -195,7 +195,7 @@ static u32 map_id_up(struct uid_gid_map *map, u32 id) + + /* Find the matching extent */ + extents = map->nr_extents; +- smp_read_barrier_depends(); ++ smp_rmb(); + for (idx = 0; idx < extents; idx++) { + first = map->extent[idx].lower_first; + last = first + map->extent[idx].count - 1; +@@ -611,9 +611,8 @@ static ssize_t map_write(struct file *file, const char __user *buf, + * were written before the count of the extents. + * + * To achieve this smp_wmb() is used on guarantee the write +- * order and smp_read_barrier_depends() is guaranteed that we +- * don't have crazy architectures returning stale data. +- * ++ * order and smp_rmb() is guaranteed that we don't have crazy ++ * architectures returning stale data. + */ + mutex_lock(&id_map_mutex); + +diff --git a/mm/backing-dev.c b/mm/backing-dev.c +index 502517492258..eea1a9dfac38 100644 +--- a/mm/backing-dev.c ++++ b/mm/backing-dev.c +@@ -287,13 +287,19 @@ int bdi_has_dirty_io(struct backing_dev_info *bdi) + * Note, we wouldn't bother setting up the timer, but this function is on the + * fast-path (used by '__mark_inode_dirty()'), so we save few context switches + * by delaying the wake-up. ++ * ++ * We have to be careful not to postpone flush work if it is scheduled for ++ * earlier. Thus we use queue_delayed_work(). + */ + void bdi_wakeup_thread_delayed(struct backing_dev_info *bdi) + { + unsigned long timeout; + + timeout = msecs_to_jiffies(dirty_writeback_interval * 10); +- mod_delayed_work(bdi_wq, &bdi->wb.dwork, timeout); ++ spin_lock_bh(&bdi->wb_lock); ++ if (test_bit(BDI_registered, &bdi->state)) ++ queue_delayed_work(bdi_wq, &bdi->wb.dwork, timeout); ++ spin_unlock_bh(&bdi->wb_lock); + } + + /* +@@ -306,9 +312,6 @@ static void bdi_remove_from_list(struct backing_dev_info *bdi) + spin_unlock_bh(&bdi_lock); + + synchronize_rcu_expedited(); +- +- /* bdi_list is now unused, clear it to mark @bdi dying */ +- INIT_LIST_HEAD(&bdi->bdi_list); + } + + int bdi_register(struct backing_dev_info *bdi, struct device *parent, +@@ -359,6 +362,11 @@ static void bdi_wb_shutdown(struct backing_dev_info *bdi) + */ + bdi_remove_from_list(bdi); + ++ /* Make sure nobody queues further work */ ++ spin_lock_bh(&bdi->wb_lock); ++ clear_bit(BDI_registered, &bdi->state); ++ spin_unlock_bh(&bdi->wb_lock); ++ + /* + * Drain work list and shutdown the delayed_work. At this point, + * @bdi->bdi_list is empty telling bdi_Writeback_workfn() that @bdi +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index dcaa6dbbab2c..cfca44f8d048 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -3619,7 +3619,13 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) + + hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); + +- if (ltk->type & HCI_SMP_STK) { ++ /* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a ++ * temporary key used to encrypt a connection following ++ * pairing. It is used during the Encrypted Session Setup to ++ * distribute the keys. Later, security can be re-established ++ * using a distributed LTK. ++ */ ++ if (ltk->type == HCI_SMP_STK_SLAVE) { + list_del(<k->list); + kfree(ltk); + } diff --git a/patch/kernel/s500-default/patch-3.10.38-39.patch b/patch/kernel/s500-default/patch-3.10.38-39.patch new file mode 100644 index 000000000..14e238d99 --- /dev/null +++ b/patch/kernel/s500-default/patch-3.10.38-39.patch @@ -0,0 +1,2664 @@ +diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt +index 1e6b6531bbcc..d2ba80bb7af5 100644 +--- a/Documentation/video4linux/gspca.txt ++++ b/Documentation/video4linux/gspca.txt +@@ -55,6 +55,7 @@ zc3xx 0458:700f Genius VideoCam Web V2 + sonixj 0458:7025 Genius Eye 311Q + sn9c20x 0458:7029 Genius Look 320s + sonixj 0458:702e Genius Slim 310 NB ++sn9c20x 0458:7045 Genius Look 1320 V2 + sn9c20x 0458:704a Genius Slim 1320 + sn9c20x 0458:704c Genius i-Look 1321 + sn9c20x 045e:00f4 LifeCam VX-6000 (SN9C20x + OV9650) +diff --git a/Makefile b/Makefile +index bd51b50a567b..1e07514be6f8 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 10 +-SUBLEVEL = 38 ++SUBLEVEL = 39 + EXTRAVERSION = + NAME = TOSSUG Baby Fish + +diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi +index 4d12d2347c15..ddd068bb1457 100644 +--- a/arch/arm/boot/dts/armada-370-xp.dtsi ++++ b/arch/arm/boot/dts/armada-370-xp.dtsi +@@ -92,6 +92,7 @@ + #size-cells = <0>; + compatible = "marvell,orion-mdio"; + reg = <0x72004 0x4>; ++ clocks = <&gateclk 4>; + }; + + ethernet@70000 { +diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts +index 02cfc76d002f..b64cb43a7295 100644 +--- a/arch/arm/boot/dts/exynos5250-arndale.dts ++++ b/arch/arm/boot/dts/exynos5250-arndale.dts +@@ -263,6 +263,7 @@ + regulator-name = "vdd_g3d"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; ++ regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; +diff --git a/arch/arm/include/asm/div64.h b/arch/arm/include/asm/div64.h +index fe92ccf1d0b0..a66061aef29c 100644 +--- a/arch/arm/include/asm/div64.h ++++ b/arch/arm/include/asm/div64.h +@@ -156,7 +156,7 @@ + /* Select the best insn combination to perform the */ \ + /* actual __m * __n / (__p << 64) operation. */ \ + if (!__c) { \ +- asm ( "umull %Q0, %R0, %1, %Q2\n\t" \ ++ asm ( "umull %Q0, %R0, %Q1, %Q2\n\t" \ + "mov %Q0, #0" \ + : "=&r" (__res) \ + : "r" (__m), "r" (__n) \ +diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h +index e42cf597f6e6..2aff798fbef4 100644 +--- a/arch/arm/include/asm/futex.h ++++ b/arch/arm/include/asm/futex.h +@@ -3,11 +3,6 @@ + + #ifdef __KERNEL__ + +-#if defined(CONFIG_CPU_USE_DOMAINS) && defined(CONFIG_SMP) +-/* ARM doesn't provide unprivileged exclusive memory accessors */ +-#include +-#else +- + #include + #include + #include +@@ -164,6 +159,5 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) + return ret; + } + +-#endif /* !(CPU_USE_DOMAINS && SMP) */ + #endif /* __KERNEL__ */ + #endif /* _ASM_ARM_FUTEX_H */ +diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h +index 652b56086de7..d070741b2b37 100644 +--- a/arch/arm/include/asm/io.h ++++ b/arch/arm/include/asm/io.h +@@ -130,16 +130,16 @@ static inline u32 __raw_readl(const volatile void __iomem *addr) + */ + extern void __iomem *__arm_ioremap_pfn_caller(unsigned long, unsigned long, + size_t, unsigned int, void *); +-extern void __iomem *__arm_ioremap_caller(unsigned long, size_t, unsigned int, ++extern void __iomem *__arm_ioremap_caller(phys_addr_t, size_t, unsigned int, + void *); + + extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int); +-extern void __iomem *__arm_ioremap(unsigned long, size_t, unsigned int); +-extern void __iomem *__arm_ioremap_exec(unsigned long, size_t, bool cached); ++extern void __iomem *__arm_ioremap(phys_addr_t, size_t, unsigned int); ++extern void __iomem *__arm_ioremap_exec(phys_addr_t, size_t, bool cached); + extern void __iounmap(volatile void __iomem *addr); + extern void __arm_iounmap(volatile void __iomem *addr); + +-extern void __iomem * (*arch_ioremap_caller)(unsigned long, size_t, ++extern void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, + unsigned int, void *); + extern void (*arch_iounmap)(volatile void __iomem *); + +diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h +index f97ee02386ee..c98c9c89b95c 100644 +--- a/arch/arm/include/asm/pgtable-2level.h ++++ b/arch/arm/include/asm/pgtable-2level.h +@@ -140,6 +140,7 @@ + #define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2) /* 1100 */ + #define L_PTE_MT_DEV_WC (_AT(pteval_t, 0x09) << 2) /* 1001 */ + #define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */ ++#define L_PTE_MT_VECTORS (_AT(pteval_t, 0x0f) << 2) /* 1111 */ + #define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2) + + #ifndef __ASSEMBLY__ +diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h +index 141baa3f9a72..cbd61977c996 100644 +--- a/arch/arm/include/asm/unistd.h ++++ b/arch/arm/include/asm/unistd.h +@@ -48,6 +48,5 @@ + */ + #define __IGNORE_fadvise64_64 + #define __IGNORE_migrate_pages +-#define __IGNORE_kcmp + + #endif /* __ASM_ARM_UNISTD_H */ +diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c +index 163b160c69e9..c3ef920823b6 100644 +--- a/arch/arm/kernel/machine_kexec.c ++++ b/arch/arm/kernel/machine_kexec.c +@@ -169,3 +169,10 @@ void machine_kexec(struct kimage *image) + + soft_restart(reboot_code_buffer_phys); + } ++ ++void arch_crash_save_vmcoreinfo(void) ++{ ++#ifdef CONFIG_ARM_LPAE ++ VMCOREINFO_CONFIG(ARM_LPAE); ++#endif ++} +diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c +index b13cc74114db..8a53f346cdb3 100644 +--- a/arch/arm/mach-ebsa110/core.c ++++ b/arch/arm/mach-ebsa110/core.c +@@ -116,7 +116,7 @@ static void __init ebsa110_map_io(void) + iotable_init(ebsa110_io_desc, ARRAY_SIZE(ebsa110_io_desc)); + } + +-static void __iomem *ebsa110_ioremap_caller(unsigned long cookie, size_t size, ++static void __iomem *ebsa110_ioremap_caller(phys_addr_t cookie, size_t size, + unsigned int flags, void *caller) + { + return (void __iomem *)cookie; +diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c +index e0e69a682174..eed32ca0b8ab 100644 +--- a/arch/arm/mach-imx/mm-imx3.c ++++ b/arch/arm/mach-imx/mm-imx3.c +@@ -65,7 +65,7 @@ static void imx3_idle(void) + : "=r" (reg)); + } + +-static void __iomem *imx3_ioremap_caller(unsigned long phys_addr, size_t size, ++static void __iomem *imx3_ioremap_caller(phys_addr_t phys_addr, size_t size, + unsigned int mtype, void *caller) + { + if (mtype == MT_DEVICE) { +diff --git a/arch/arm/mach-iop13xx/io.c b/arch/arm/mach-iop13xx/io.c +index 183dc8b5511b..faaf7d4482c5 100644 +--- a/arch/arm/mach-iop13xx/io.c ++++ b/arch/arm/mach-iop13xx/io.c +@@ -23,7 +23,7 @@ + + #include "pci.h" + +-static void __iomem *__iop13xx_ioremap_caller(unsigned long cookie, ++static void __iomem *__iop13xx_ioremap_caller(phys_addr_t cookie, + size_t size, unsigned int mtype, void *caller) + { + void __iomem * retval; +diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c +index 6600cff6bd92..d7223b3b81f3 100644 +--- a/arch/arm/mach-ixp4xx/common.c ++++ b/arch/arm/mach-ixp4xx/common.c +@@ -559,7 +559,7 @@ void ixp4xx_restart(char mode, const char *cmd) + * fallback to the default. + */ + +-static void __iomem *ixp4xx_ioremap_caller(unsigned long addr, size_t size, ++static void __iomem *ixp4xx_ioremap_caller(phys_addr_t addr, size_t size, + unsigned int mtype, void *caller) + { + if (!is_pci_memory(addr)) +diff --git a/arch/arm/mach-msm/common.h b/arch/arm/mach-msm/common.h +index ce8215a269e5..421cf7751a80 100644 +--- a/arch/arm/mach-msm/common.h ++++ b/arch/arm/mach-msm/common.h +@@ -23,7 +23,7 @@ extern void msm_map_msm8x60_io(void); + extern void msm_map_msm8960_io(void); + extern void msm_map_qsd8x50_io(void); + +-extern void __iomem *__msm_ioremap_caller(unsigned long phys_addr, size_t size, ++extern void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size, + unsigned int mtype, void *caller); + + extern struct smp_operations msm_smp_ops; +diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c +index 123ef9cbce1b..fd65b6d42cde 100644 +--- a/arch/arm/mach-msm/io.c ++++ b/arch/arm/mach-msm/io.c +@@ -172,7 +172,7 @@ void __init msm_map_msm7x30_io(void) + } + #endif /* CONFIG_ARCH_MSM7X30 */ + +-void __iomem *__msm_ioremap_caller(unsigned long phys_addr, size_t size, ++void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size, + unsigned int mtype, void *caller) + { + if (mtype == MT_DEVICE) { +diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c +index e022a869bff2..6037a9a01ed5 100644 +--- a/arch/arm/mach-omap2/irq.c ++++ b/arch/arm/mach-omap2/irq.c +@@ -222,6 +222,7 @@ void __init ti81xx_init_irq(void) + static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs *regs) + { + u32 irqnr; ++ int handled_irq = 0; + + do { + irqnr = readl_relaxed(base_addr + 0x98); +@@ -249,8 +250,15 @@ out: + if (irqnr) { + irqnr = irq_find_mapping(domain, irqnr); + handle_IRQ(irqnr, regs); ++ handled_irq = 1; + } + } while (irqnr); ++ ++ /* If an irq is masked or deasserted while active, we will ++ * keep ending up here with no irq handled. So remove it from ++ * the INTC with an ack.*/ ++ if (!handled_irq) ++ omap_ack_irq(NULL); + } + + asmlinkage void __exception_irq_entry omap2_intc_handle_irq(struct pt_regs *regs) +diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +index 9f6238c9dfc9..8691c8cbe2c7 100644 +--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c ++++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +@@ -1955,7 +1955,7 @@ static struct omap_hwmod_irq_info omap3xxx_usb_host_hs_irqs[] = { + static struct omap_hwmod omap3xxx_usb_host_hs_hwmod = { + .name = "usb_host_hs", + .class = &omap3xxx_usb_host_hs_hwmod_class, +- .clkdm_name = "l3_init_clkdm", ++ .clkdm_name = "usbhost_clkdm", + .mpu_irqs = omap3xxx_usb_host_hs_irqs, + .main_clk = "usbhost_48m_fck", + .prcm = { +@@ -2040,7 +2040,7 @@ static struct omap_hwmod_irq_info omap3xxx_usb_tll_hs_irqs[] = { + static struct omap_hwmod omap3xxx_usb_tll_hs_hwmod = { + .name = "usb_tll_hs", + .class = &omap3xxx_usb_tll_hs_hwmod_class, +- .clkdm_name = "l3_init_clkdm", ++ .clkdm_name = "core_l4_clkdm", + .mpu_irqs = omap3xxx_usb_tll_hs_irqs, + .main_clk = "usbtll_fck", + .prcm = { +diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h +index 7bdd22afce69..d4d0fce325c7 100644 +--- a/arch/arm/mach-omap2/pm.h ++++ b/arch/arm/mach-omap2/pm.h +@@ -103,7 +103,7 @@ static inline void enable_omap3630_toggle_l2_on_restore(void) { } + + #define PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD (1 << 0) + +-#if defined(CONFIG_ARCH_OMAP4) ++#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4) + extern u16 pm44xx_errata; + #define IS_PM44XX_ERRATUM(id) (pm44xx_errata & (id)) + #else +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index 08c9fe917d1f..c21082d664ed 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -436,7 +436,6 @@ config CPU_32v5 + + config CPU_32v6 + bool +- select CPU_USE_DOMAINS if CPU_V6 && MMU + select TLS_REG_EMUL if !CPU_32v6K && !MMU + + config CPU_32v6K +@@ -651,7 +650,7 @@ config ARM_VIRT_EXT + + config SWP_EMULATE + bool "Emulate SWP/SWPB instructions" +- depends on !CPU_USE_DOMAINS && CPU_V7 ++ depends on CPU_V7 + default y if SMP + select HAVE_PROC_CPU if PROC_FS + help +diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c +index 04d9006eab1f..f123d6eb074b 100644 +--- a/arch/arm/mm/ioremap.c ++++ b/arch/arm/mm/ioremap.c +@@ -331,10 +331,10 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, + return (void __iomem *) (offset + addr); + } + +-void __iomem *__arm_ioremap_caller(unsigned long phys_addr, size_t size, ++void __iomem *__arm_ioremap_caller(phys_addr_t phys_addr, size_t size, + unsigned int mtype, void *caller) + { +- unsigned long last_addr; ++ phys_addr_t last_addr; + unsigned long offset = phys_addr & ~PAGE_MASK; + unsigned long pfn = __phys_to_pfn(phys_addr); + +@@ -367,12 +367,12 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, + } + EXPORT_SYMBOL(__arm_ioremap_pfn); + +-void __iomem * (*arch_ioremap_caller)(unsigned long, size_t, ++void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, + unsigned int, void *) = + __arm_ioremap_caller; + + void __iomem * +-__arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype) ++__arm_ioremap(phys_addr_t phys_addr, size_t size, unsigned int mtype) + { + return arch_ioremap_caller(phys_addr, size, mtype, + __builtin_return_address(0)); +@@ -387,7 +387,7 @@ EXPORT_SYMBOL(__arm_ioremap); + * CONFIG_GENERIC_ALLOCATOR for allocating external memory. + */ + void __iomem * +-__arm_ioremap_exec(unsigned long phys_addr, size_t size, bool cached) ++__arm_ioremap_exec(phys_addr_t phys_addr, size_t size, bool cached) + { + unsigned int mtype; + +diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c +index daf336fe0be8..fb3c446af9e5 100644 +--- a/arch/arm/mm/mmu.c ++++ b/arch/arm/mm/mmu.c +@@ -459,6 +459,16 @@ static void __init build_mem_type_table(void) + hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte; + + /* ++ * We don't use domains on ARMv6 (since this causes problems with ++ * v6/v7 kernels), so we must use a separate memory type for user ++ * r/o, kernel r/w to map the vectors page. ++ */ ++#ifndef CONFIG_ARM_LPAE ++ if (cpu_arch == CPU_ARCH_ARMv6) ++ vecs_pgprot |= L_PTE_MT_VECTORS; ++#endif ++ ++ /* + * ARMv6 and above have extended page tables. + */ + if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) { +diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c +index eb5293a69a84..7fe0524a5449 100644 +--- a/arch/arm/mm/nommu.c ++++ b/arch/arm/mm/nommu.c +@@ -87,16 +87,16 @@ void __iomem *__arm_ioremap_pfn_caller(unsigned long pfn, unsigned long offset, + return __arm_ioremap_pfn(pfn, offset, size, mtype); + } + +-void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size, ++void __iomem *__arm_ioremap(phys_addr_t phys_addr, size_t size, + unsigned int mtype) + { + return (void __iomem *)phys_addr; + } + EXPORT_SYMBOL(__arm_ioremap); + +-void __iomem * (*arch_ioremap_caller)(unsigned long, size_t, unsigned int, void *); ++void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, unsigned int, void *); + +-void __iomem *__arm_ioremap_caller(unsigned long phys_addr, size_t size, ++void __iomem *__arm_ioremap_caller(phys_addr_t phys_addr, size_t size, + unsigned int mtype, void *caller) + { + return __arm_ioremap(phys_addr, size, mtype); +diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S +index e3c48a3fe063..ee1d80593958 100644 +--- a/arch/arm/mm/proc-macros.S ++++ b/arch/arm/mm/proc-macros.S +@@ -112,13 +112,9 @@ + * 100x 1 0 1 r/o no acc + * 10x0 1 0 1 r/o no acc + * 1011 0 0 1 r/w no acc +- * 110x 0 1 0 r/w r/o +- * 11x0 0 1 0 r/w r/o +- * 1111 0 1 1 r/w r/w +- * +- * If !CONFIG_CPU_USE_DOMAINS, the following permissions are changed: + * 110x 1 1 1 r/o r/o + * 11x0 1 1 1 r/o r/o ++ * 1111 0 1 1 r/w r/w + */ + .macro armv6_mt_table pfx + \pfx\()_mt_table: +@@ -137,7 +133,7 @@ + .long PTE_EXT_TEX(2) @ L_PTE_MT_DEV_NONSHARED + .long 0x00 @ unused + .long 0x00 @ unused +- .long 0x00 @ unused ++ .long PTE_CACHEABLE | PTE_BUFFERABLE | PTE_EXT_APX @ L_PTE_MT_VECTORS + .endm + + .macro armv6_set_pte_ext pfx +@@ -158,24 +154,21 @@ + + tst r1, #L_PTE_USER + orrne r3, r3, #PTE_EXT_AP1 +-#ifdef CONFIG_CPU_USE_DOMAINS +- @ allow kernel read/write access to read-only user pages + tstne r3, #PTE_EXT_APX +- bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 +-#endif ++ ++ @ user read-only -> kernel read-only ++ bicne r3, r3, #PTE_EXT_AP0 + + tst r1, #L_PTE_XN + orrne r3, r3, #PTE_EXT_XN + +- orr r3, r3, r2 ++ eor r3, r3, r2 + + tst r1, #L_PTE_YOUNG + tstne r1, #L_PTE_PRESENT + moveq r3, #0 +-#ifndef CONFIG_CPU_USE_DOMAINS + tstne r1, #L_PTE_NONE + movne r3, #0 +-#endif + + str r3, [r0] + mcr p15, 0, r0, c7, c10, 1 @ flush_pte +diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S +index b3997c70af32..bb20ba0f7bc7 100644 +--- a/arch/arm/mm/proc-v7-2level.S ++++ b/arch/arm/mm/proc-v7-2level.S +@@ -90,21 +90,14 @@ ENTRY(cpu_v7_set_pte_ext) + + tst r1, #L_PTE_USER + orrne r3, r3, #PTE_EXT_AP1 +-#ifdef CONFIG_CPU_USE_DOMAINS +- @ allow kernel read/write access to read-only user pages +- tstne r3, #PTE_EXT_APX +- bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 +-#endif + + tst r1, #L_PTE_XN + orrne r3, r3, #PTE_EXT_XN + + tst r1, #L_PTE_YOUNG + tstne r1, #L_PTE_VALID +-#ifndef CONFIG_CPU_USE_DOMAINS + eorne r1, r1, #L_PTE_NONE + tstne r1, #L_PTE_NONE +-#endif + moveq r3, #0 + + ARM( str r3, [r0, #2048]! ) +diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h +index e9a1a1d81892..3a710d7b14ce 100644 +--- a/arch/arm64/include/asm/pgtable.h ++++ b/arch/arm64/include/asm/pgtable.h +@@ -161,7 +161,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pte) + { + if (pte_valid_user(pte)) { +- if (pte_exec(pte)) ++ if (!pte_special(pte) && pte_exec(pte)) + __sync_icache_dcache(pte, addr); + if (!pte_dirty(pte)) + pte = pte_wrprotect(pte); +@@ -182,11 +182,11 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, + * Mark the prot value as uncacheable and unbufferable. + */ + #define pgprot_noncached(prot) \ +- __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE)) ++ __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE) | PTE_PXN | PTE_UXN) + #define pgprot_writecombine(prot) \ +- __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC)) ++ __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN) + #define pgprot_dmacoherent(prot) \ +- __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC)) ++ __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN) + #define __HAVE_PHYS_MEM_ACCESS_PROT + struct file; + extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, +diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h +index f201af8be580..31b5ca8f8c3d 100644 +--- a/arch/s390/include/asm/ccwdev.h ++++ b/arch/s390/include/asm/ccwdev.h +@@ -219,7 +219,7 @@ extern void ccw_device_get_id(struct ccw_device *, struct ccw_dev_id *); + #define to_ccwdev(n) container_of(n, struct ccw_device, dev) + #define to_ccwdrv(n) container_of(n, struct ccw_driver, driver) + +-extern struct ccw_device *ccw_device_probe_console(void); ++extern struct ccw_device *ccw_device_probe_console(struct ccw_driver *); + extern void ccw_device_wait_idle(struct ccw_device *); + extern int ccw_device_force_console(struct ccw_device *); + +diff --git a/arch/sh/kernel/dumpstack.c b/arch/sh/kernel/dumpstack.c +index b959f5592604..8dfe645bcc4b 100644 +--- a/arch/sh/kernel/dumpstack.c ++++ b/arch/sh/kernel/dumpstack.c +@@ -115,7 +115,7 @@ static int print_trace_stack(void *data, char *name) + */ + static void print_trace_address(void *data, unsigned long addr, int reliable) + { +- printk(data); ++ printk("%s", (char *)data); + printk_address(addr, reliable); + } + +diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c +index d606463aa6d6..1308beed7abe 100644 +--- a/arch/x86/boot/compressed/eboot.c ++++ b/arch/x86/boot/compressed/eboot.c +@@ -865,6 +865,9 @@ fail: + * Because the x86 boot code expects to be passed a boot_params we + * need to create one ourselves (usually the bootloader would create + * one for us). ++ * ++ * The caller is responsible for filling out ->code32_start in the ++ * returned boot_params. + */ + struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table) + { +@@ -921,8 +924,6 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table) + hdr->vid_mode = 0xffff; + hdr->boot_flag = 0xAA55; + +- hdr->code32_start = (__u64)(unsigned long)image->image_base; +- + hdr->type_of_loader = 0x21; + + /* Convert unicode cmdline to ascii */ +diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S +index 1e3184f6072f..abb988a54c69 100644 +--- a/arch/x86/boot/compressed/head_32.S ++++ b/arch/x86/boot/compressed/head_32.S +@@ -50,6 +50,13 @@ ENTRY(efi_pe_entry) + pushl %eax + pushl %esi + pushl %ecx ++ ++ call reloc ++reloc: ++ popl %ecx ++ subl reloc, %ecx ++ movl %ecx, BP_code32_start(%eax) ++ + sub $0x4, %esp + + ENTRY(efi_stub_entry) +@@ -63,12 +70,7 @@ ENTRY(efi_stub_entry) + hlt + jmp 1b + 2: +- call 3f +-3: +- popl %eax +- subl $3b, %eax +- subl BP_pref_address(%esi), %eax +- add BP_code32_start(%esi), %eax ++ movl BP_code32_start(%esi), %eax + leal preferred_addr(%eax), %eax + jmp *%eax + +diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S +index 16f24e6dad79..92059b8f3f7b 100644 +--- a/arch/x86/boot/compressed/head_64.S ++++ b/arch/x86/boot/compressed/head_64.S +@@ -217,6 +217,8 @@ ENTRY(efi_pe_entry) + cmpq $0,%rax + je 1f + mov %rax, %rdx ++ leaq startup_32(%rip), %rax ++ movl %eax, BP_code32_start(%rdx) + popq %rsi + popq %rdi + +@@ -230,12 +232,7 @@ ENTRY(efi_stub_entry) + hlt + jmp 1b + 2: +- call 3f +-3: +- popq %rax +- subq $3b, %rax +- subq BP_pref_address(%rsi), %rax +- add BP_code32_start(%esi), %eax ++ movl BP_code32_start(%esi), %eax + leaq preferred_addr(%rax), %rax + jmp *%rax + +diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c +index e6253195a301..1ffc32dbe450 100644 +--- a/arch/x86/kernel/ftrace.c ++++ b/arch/x86/kernel/ftrace.c +@@ -659,8 +659,8 @@ ftrace_modify_code(unsigned long ip, unsigned const char *old_code, + ret = -EPERM; + goto out; + } +- run_sync(); + out: ++ run_sync(); + return ret; + + fail_update: +diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c +index ebc987398923..af1d14a9ebda 100644 +--- a/arch/x86/kernel/ldt.c ++++ b/arch/x86/kernel/ldt.c +@@ -229,6 +229,17 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode) + } + } + ++ /* ++ * On x86-64 we do not support 16-bit segments due to ++ * IRET leaking the high bits of the kernel stack address. ++ */ ++#ifdef CONFIG_X86_64 ++ if (!ldt_info.seg_32bit) { ++ error = -EINVAL; ++ goto out_unlock; ++ } ++#endif ++ + fill_ldt(&ldt, &ldt_info); + if (oldmode) + ldt.avl = 0; +diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c +index 20dd52a2f92f..6e514583aa76 100644 +--- a/drivers/block/mtip32xx/mtip32xx.c ++++ b/drivers/block/mtip32xx/mtip32xx.c +@@ -4040,6 +4040,7 @@ skip_create_disk: + blk_queue_max_hw_sectors(dd->queue, 0xffff); + blk_queue_max_segment_size(dd->queue, 0x400000); + blk_queue_io_min(dd->queue, 4096); ++ blk_queue_bounce_limit(dd->queue, dd->pdev->dma_mask); + + /* + * write back cache is not supported in the device. FUA depends on +diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c +index aaadd32f9f0d..d344cf3ac9e3 100644 +--- a/drivers/iio/industrialio-buffer.c ++++ b/drivers/iio/industrialio-buffer.c +@@ -119,7 +119,8 @@ static ssize_t iio_scan_el_show(struct device *dev, + int ret; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + +- ret = test_bit(to_iio_dev_attr(attr)->address, ++ /* Ensure ret is 0 or 1. */ ++ ret = !!test_bit(to_iio_dev_attr(attr)->address, + indio_dev->buffer->scan_mask); + + return sprintf(buf, "%d\n", ret); +@@ -762,7 +763,8 @@ int iio_scan_mask_query(struct iio_dev *indio_dev, + if (!buffer->scan_mask) + return 0; + +- return test_bit(bit, buffer->scan_mask); ++ /* Ensure return value is 0 or 1. */ ++ return !!test_bit(bit, buffer->scan_mask); + }; + EXPORT_SYMBOL_GPL(iio_scan_mask_query); + +diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c +index 212150c25ea0..8cc837537768 100644 +--- a/drivers/infiniband/hw/ehca/ehca_cq.c ++++ b/drivers/infiniband/hw/ehca/ehca_cq.c +@@ -283,6 +283,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector, + (my_cq->galpas.user.fw_handle & (PAGE_SIZE - 1)); + if (ib_copy_to_udata(udata, &resp, sizeof(resp))) { + ehca_err(device, "Copy to udata failed."); ++ cq = ERR_PTR(-EFAULT); + goto create_cq_exit4; + } + } +diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c +index 714293b78518..e2f9a51f4a38 100644 +--- a/drivers/infiniband/hw/ipath/ipath_diag.c ++++ b/drivers/infiniband/hw/ipath/ipath_diag.c +@@ -326,7 +326,7 @@ static ssize_t ipath_diagpkt_write(struct file *fp, + size_t count, loff_t *off) + { + u32 __iomem *piobuf; +- u32 plen, clen, pbufn; ++ u32 plen, pbufn, maxlen_reserve; + struct ipath_diag_pkt odp; + struct ipath_diag_xpkt dp; + u32 *tmpbuf = NULL; +@@ -335,51 +335,29 @@ static ssize_t ipath_diagpkt_write(struct file *fp, + u64 val; + u32 l_state, lt_state; /* LinkState, LinkTrainingState */ + +- if (count < sizeof(odp)) { +- ret = -EINVAL; +- goto bail; +- } + + if (count == sizeof(dp)) { + if (copy_from_user(&dp, data, sizeof(dp))) { + ret = -EFAULT; + goto bail; + } +- } else if (copy_from_user(&odp, data, sizeof(odp))) { +- ret = -EFAULT; ++ } else if (count == sizeof(odp)) { ++ if (copy_from_user(&odp, data, sizeof(odp))) { ++ ret = -EFAULT; ++ goto bail; ++ } ++ } else { ++ ret = -EINVAL; + goto bail; + } + +- /* +- * Due to padding/alignment issues (lessened with new struct) +- * the old and new structs are the same length. We need to +- * disambiguate them, which we can do because odp.len has never +- * been less than the total of LRH+BTH+DETH so far, while +- * dp.unit (same offset) unit is unlikely to get that high. +- * Similarly, dp.data, the pointer to user at the same offset +- * as odp.unit, is almost certainly at least one (512byte)page +- * "above" NULL. The if-block below can be omitted if compatibility +- * between a new driver and older diagnostic code is unimportant. +- * compatibility the other direction (new diags, old driver) is +- * handled in the diagnostic code, with a warning. +- */ +- if (dp.unit >= 20 && dp.data < 512) { +- /* very probable version mismatch. Fix it up */ +- memcpy(&odp, &dp, sizeof(odp)); +- /* We got a legacy dp, copy elements to dp */ +- dp.unit = odp.unit; +- dp.data = odp.data; +- dp.len = odp.len; +- dp.pbc_wd = 0; /* Indicate we need to compute PBC wd */ +- } +- + /* send count must be an exact number of dwords */ + if (dp.len & 3) { + ret = -EINVAL; + goto bail; + } + +- clen = dp.len >> 2; ++ plen = dp.len >> 2; + + dd = ipath_lookup(dp.unit); + if (!dd || !(dd->ipath_flags & IPATH_PRESENT) || +@@ -422,16 +400,22 @@ static ssize_t ipath_diagpkt_write(struct file *fp, + goto bail; + } + +- /* need total length before first word written */ +- /* +1 word is for the qword padding */ +- plen = sizeof(u32) + dp.len; +- +- if ((plen + 4) > dd->ipath_ibmaxlen) { ++ /* ++ * need total length before first word written, plus 2 Dwords. One Dword ++ * is for padding so we get the full user data when not aligned on ++ * a word boundary. The other Dword is to make sure we have room for the ++ * ICRC which gets tacked on later. ++ */ ++ maxlen_reserve = 2 * sizeof(u32); ++ if (dp.len > dd->ipath_ibmaxlen - maxlen_reserve) { + ipath_dbg("Pkt len 0x%x > ibmaxlen %x\n", +- plen - 4, dd->ipath_ibmaxlen); ++ dp.len, dd->ipath_ibmaxlen); + ret = -EINVAL; +- goto bail; /* before writing pbc */ ++ goto bail; + } ++ ++ plen = sizeof(u32) + dp.len; ++ + tmpbuf = vmalloc(plen); + if (!tmpbuf) { + dev_info(&dd->pcidev->dev, "Unable to allocate tmp buffer, " +@@ -473,11 +457,11 @@ static ssize_t ipath_diagpkt_write(struct file *fp, + */ + if (dd->ipath_flags & IPATH_PIO_FLUSH_WC) { + ipath_flush_wc(); +- __iowrite32_copy(piobuf + 2, tmpbuf, clen - 1); ++ __iowrite32_copy(piobuf + 2, tmpbuf, plen - 1); + ipath_flush_wc(); +- __raw_writel(tmpbuf[clen - 1], piobuf + clen + 1); ++ __raw_writel(tmpbuf[plen - 1], piobuf + plen + 1); + } else +- __iowrite32_copy(piobuf + 2, tmpbuf, clen); ++ __iowrite32_copy(piobuf + 2, tmpbuf, plen); + + ipath_flush_wc(); + +diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c +index 5b71d43bd89c..42dde06fdb91 100644 +--- a/drivers/infiniband/hw/mthca/mthca_provider.c ++++ b/drivers/infiniband/hw/mthca/mthca_provider.c +@@ -695,6 +695,7 @@ static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries, + + if (context && ib_copy_to_udata(udata, &cq->cqn, sizeof (__u32))) { + mthca_free_cq(to_mdev(ibdev), cq); ++ err = -EFAULT; + goto err_free; + } + +diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c +index 8f67fe2e91e6..7510a3c80757 100644 +--- a/drivers/infiniband/hw/nes/nes_verbs.c ++++ b/drivers/infiniband/hw/nes/nes_verbs.c +@@ -1186,7 +1186,7 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, + nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num); + kfree(nesqp->allocated_buffer); + nes_debug(NES_DBG_QP, "ib_copy_from_udata() Failed \n"); +- return NULL; ++ return ERR_PTR(-EFAULT); + } + if (req.user_wqe_buffers) { + virt_wqs = 1; +diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c +index 6c66a728a37f..64953dfa9d8a 100644 +--- a/drivers/infiniband/ulp/srpt/ib_srpt.c ++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c +@@ -1078,6 +1078,7 @@ static void srpt_unmap_sg_to_ib_sge(struct srpt_rdma_ch *ch, + static int srpt_map_sg_to_ib_sge(struct srpt_rdma_ch *ch, + struct srpt_send_ioctx *ioctx) + { ++ struct ib_device *dev = ch->sport->sdev->device; + struct se_cmd *cmd; + struct scatterlist *sg, *sg_orig; + int sg_cnt; +@@ -1124,7 +1125,7 @@ static int srpt_map_sg_to_ib_sge(struct srpt_rdma_ch *ch, + + db = ioctx->rbufs; + tsize = cmd->data_length; +- dma_len = sg_dma_len(&sg[0]); ++ dma_len = ib_sg_dma_len(dev, &sg[0]); + riu = ioctx->rdma_ius; + + /* +@@ -1155,7 +1156,8 @@ static int srpt_map_sg_to_ib_sge(struct srpt_rdma_ch *ch, + ++j; + if (j < count) { + sg = sg_next(sg); +- dma_len = sg_dma_len(sg); ++ dma_len = ib_sg_dma_len( ++ dev, sg); + } + } + } else { +@@ -1192,8 +1194,8 @@ static int srpt_map_sg_to_ib_sge(struct srpt_rdma_ch *ch, + tsize = cmd->data_length; + riu = ioctx->rdma_ius; + sg = sg_orig; +- dma_len = sg_dma_len(&sg[0]); +- dma_addr = sg_dma_address(&sg[0]); ++ dma_len = ib_sg_dma_len(dev, &sg[0]); ++ dma_addr = ib_sg_dma_address(dev, &sg[0]); + + /* this second loop is really mapped sg_addres to rdma_iu->ib_sge */ + for (i = 0, j = 0; +@@ -1216,8 +1218,10 @@ static int srpt_map_sg_to_ib_sge(struct srpt_rdma_ch *ch, + ++j; + if (j < count) { + sg = sg_next(sg); +- dma_len = sg_dma_len(sg); +- dma_addr = sg_dma_address(sg); ++ dma_len = ib_sg_dma_len( ++ dev, sg); ++ dma_addr = ib_sg_dma_address( ++ dev, sg); + } + } + } else { +diff --git a/drivers/media/dvb-frontends/m88rs2000.c b/drivers/media/dvb-frontends/m88rs2000.c +index 02699c111019..c7a1c8eba475 100644 +--- a/drivers/media/dvb-frontends/m88rs2000.c ++++ b/drivers/media/dvb-frontends/m88rs2000.c +@@ -712,6 +712,22 @@ static int m88rs2000_get_frontend(struct dvb_frontend *fe) + return 0; + } + ++static int m88rs2000_get_tune_settings(struct dvb_frontend *fe, ++ struct dvb_frontend_tune_settings *tune) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ ++ if (c->symbol_rate > 3000000) ++ tune->min_delay_ms = 2000; ++ else ++ tune->min_delay_ms = 3000; ++ ++ tune->step_size = c->symbol_rate / 16000; ++ tune->max_drift = c->symbol_rate / 2000; ++ ++ return 0; ++} ++ + static int m88rs2000_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) + { + struct m88rs2000_state *state = fe->demodulator_priv; +@@ -743,7 +759,7 @@ static struct dvb_frontend_ops m88rs2000_ops = { + .symbol_rate_tolerance = 500, /* ppm */ + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | +- FE_CAN_QPSK | ++ FE_CAN_QPSK | FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_AUTO + }, + +@@ -763,6 +779,7 @@ static struct dvb_frontend_ops m88rs2000_ops = { + + .set_frontend = m88rs2000_set_frontend, + .get_frontend = m88rs2000_get_frontend, ++ .get_tune_settings = m88rs2000_get_tune_settings, + }; + + struct dvb_frontend *m88rs2000_attach(const struct m88rs2000_config *config, +diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c +index d45e7f6ff332..e87a734637a9 100644 +--- a/drivers/media/pci/saa7134/saa7134-cards.c ++++ b/drivers/media/pci/saa7134/saa7134-cards.c +@@ -8045,8 +8045,8 @@ int saa7134_board_init2(struct saa7134_dev *dev) + break; + } /* switch() */ + +- /* initialize tuner */ +- if (TUNER_ABSENT != dev->tuner_type) { ++ /* initialize tuner (don't do this when resuming) */ ++ if (!dev->insuspend && TUNER_ABSENT != dev->tuner_type) { + int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); + + /* Note: radio tuner address is always filled in, +diff --git a/drivers/media/platform/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c +index cd8831aebdeb..e2e4610d5550 100644 +--- a/drivers/media/platform/omap3isp/isppreview.c ++++ b/drivers/media/platform/omap3isp/isppreview.c +@@ -1079,6 +1079,7 @@ static void preview_config_input_format(struct isp_prev_device *prev, + */ + static void preview_config_input_size(struct isp_prev_device *prev, u32 active) + { ++ const struct v4l2_mbus_framefmt *format = &prev->formats[PREV_PAD_SINK]; + struct isp_device *isp = to_isp_device(prev); + unsigned int sph = prev->crop.left; + unsigned int eph = prev->crop.left + prev->crop.width - 1; +@@ -1086,6 +1087,14 @@ static void preview_config_input_size(struct isp_prev_device *prev, u32 active) + unsigned int elv = prev->crop.top + prev->crop.height - 1; + u32 features; + ++ if (format->code != V4L2_MBUS_FMT_Y8_1X8 && ++ format->code != V4L2_MBUS_FMT_Y10_1X10) { ++ sph -= 2; ++ eph += 2; ++ slv -= 2; ++ elv += 2; ++ } ++ + features = (prev->params.params[0].features & active) + | (prev->params.params[1].features & ~active); + +diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c +index b22f8fed8127..c4d669648dc7 100644 +--- a/drivers/media/usb/em28xx/em28xx-dvb.c ++++ b/drivers/media/usb/em28xx/em28xx-dvb.c +@@ -673,7 +673,8 @@ static void pctv_520e_init(struct em28xx *dev) + static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe) + { + struct dtv_frontend_properties *c = &fe->dtv_property_cache; +- struct em28xx *dev = fe->dvb->priv; ++ struct em28xx_i2c_bus *i2c_bus = fe->dvb->priv; ++ struct em28xx *dev = i2c_bus->dev; + #ifdef CONFIG_GPIOLIB + struct em28xx_dvb *dvb = dev->dvb; + int ret; +diff --git a/drivers/media/usb/gspca/sn9c20x.c b/drivers/media/usb/gspca/sn9c20x.c +index ead9a1f58513..8b59e5d37bae 100644 +--- a/drivers/media/usb/gspca/sn9c20x.c ++++ b/drivers/media/usb/gspca/sn9c20x.c +@@ -2394,6 +2394,7 @@ static const struct usb_device_id device_table[] = { + {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)}, + {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)}, + {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)}, ++ {USB_DEVICE(0x0458, 0x7045), SN9C20X(MT9M112, 0x5d, LED_REVERSE)}, + {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)}, + {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)}, + {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)}, +diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +index f1295519f285..f56b729581e7 100644 +--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c ++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +@@ -787,8 +787,8 @@ static int put_v4l2_subdev_edid32(struct v4l2_subdev_edid *kp, struct v4l2_subde + #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32) + #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32) + #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32) +-#define VIDIOC_SUBDEV_G_EDID32 _IOWR('V', 63, struct v4l2_subdev_edid32) +-#define VIDIOC_SUBDEV_S_EDID32 _IOWR('V', 64, struct v4l2_subdev_edid32) ++#define VIDIOC_SUBDEV_G_EDID32 _IOWR('V', 40, struct v4l2_subdev_edid32) ++#define VIDIOC_SUBDEV_S_EDID32 _IOWR('V', 41, struct v4l2_subdev_edid32) + #define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32) + #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32) + #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32) +diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c +index 31ca55548ef9..30cf7eef2a8f 100644 +--- a/drivers/mfd/88pm860x-core.c ++++ b/drivers/mfd/88pm860x-core.c +@@ -1179,12 +1179,18 @@ static int pm860x_probe(struct i2c_client *client, + chip->companion_addr = pdata->companion_addr; + chip->companion = i2c_new_dummy(chip->client->adapter, + chip->companion_addr); ++ if (!chip->companion) { ++ dev_err(&client->dev, ++ "Failed to allocate I2C companion device\n"); ++ return -ENODEV; ++ } + chip->regmap_companion = regmap_init_i2c(chip->companion, + &pm860x_regmap_config); + if (IS_ERR(chip->regmap_companion)) { + ret = PTR_ERR(chip->regmap_companion); + dev_err(&chip->companion->dev, + "Failed to allocate register map: %d\n", ret); ++ i2c_unregister_device(chip->companion); + return ret; + } + i2c_set_clientdata(chip->companion, chip); +diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c +index 8290c2382395..1b6f45a14109 100644 +--- a/drivers/mfd/max77686.c ++++ b/drivers/mfd/max77686.c +@@ -121,6 +121,10 @@ static int max77686_i2c_probe(struct i2c_client *i2c, + dev_info(max77686->dev, "device found\n"); + + max77686->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC); ++ if (!max77686->rtc) { ++ dev_err(max77686->dev, "Failed to allocate I2C device for RTC\n"); ++ return -ENODEV; ++ } + i2c_set_clientdata(max77686->rtc, max77686); + + max77686_irq_init(max77686); +diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c +index 9e60fed5ff82..299970f99588 100644 +--- a/drivers/mfd/max77693.c ++++ b/drivers/mfd/max77693.c +@@ -149,9 +149,18 @@ static int max77693_i2c_probe(struct i2c_client *i2c, + dev_info(max77693->dev, "device ID: 0x%x\n", reg_data); + + max77693->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC); ++ if (!max77693->muic) { ++ dev_err(max77693->dev, "Failed to allocate I2C device for MUIC\n"); ++ return -ENODEV; ++ } + i2c_set_clientdata(max77693->muic, max77693); + + max77693->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC); ++ if (!max77693->haptic) { ++ dev_err(max77693->dev, "Failed to allocate I2C device for Haptic\n"); ++ ret = -ENODEV; ++ goto err_i2c_haptic; ++ } + i2c_set_clientdata(max77693->haptic, max77693); + + /* +@@ -187,8 +196,9 @@ err_mfd: + max77693_irq_exit(max77693); + err_irq: + err_regmap_muic: +- i2c_unregister_device(max77693->muic); + i2c_unregister_device(max77693->haptic); ++err_i2c_haptic: ++ i2c_unregister_device(max77693->muic); + return ret; + } + +diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c +index 92bbebd31598..c94d3337bdfd 100644 +--- a/drivers/mfd/max8925-i2c.c ++++ b/drivers/mfd/max8925-i2c.c +@@ -180,9 +180,18 @@ static int max8925_probe(struct i2c_client *client, + mutex_init(&chip->io_lock); + + chip->rtc = i2c_new_dummy(chip->i2c->adapter, RTC_I2C_ADDR); ++ if (!chip->rtc) { ++ dev_err(chip->dev, "Failed to allocate I2C device for RTC\n"); ++ return -ENODEV; ++ } + i2c_set_clientdata(chip->rtc, chip); + + chip->adc = i2c_new_dummy(chip->i2c->adapter, ADC_I2C_ADDR); ++ if (!chip->adc) { ++ dev_err(chip->dev, "Failed to allocate I2C device for ADC\n"); ++ i2c_unregister_device(chip->rtc); ++ return -ENODEV; ++ } + i2c_set_clientdata(chip->adc, chip); + + device_init_wakeup(&client->dev, 1); +diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c +index 14714058f2d2..ea1defbcf2cb 100644 +--- a/drivers/mfd/max8997.c ++++ b/drivers/mfd/max8997.c +@@ -218,10 +218,26 @@ static int max8997_i2c_probe(struct i2c_client *i2c, + mutex_init(&max8997->iolock); + + max8997->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC); ++ if (!max8997->rtc) { ++ dev_err(max8997->dev, "Failed to allocate I2C device for RTC\n"); ++ return -ENODEV; ++ } + i2c_set_clientdata(max8997->rtc, max8997); ++ + max8997->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC); ++ if (!max8997->haptic) { ++ dev_err(max8997->dev, "Failed to allocate I2C device for Haptic\n"); ++ ret = -ENODEV; ++ goto err_i2c_haptic; ++ } + i2c_set_clientdata(max8997->haptic, max8997); ++ + max8997->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC); ++ if (!max8997->muic) { ++ dev_err(max8997->dev, "Failed to allocate I2C device for MUIC\n"); ++ ret = -ENODEV; ++ goto err_i2c_muic; ++ } + i2c_set_clientdata(max8997->muic, max8997); + + pm_runtime_set_active(max8997->dev); +@@ -248,7 +264,9 @@ static int max8997_i2c_probe(struct i2c_client *i2c, + err_mfd: + mfd_remove_devices(max8997->dev); + i2c_unregister_device(max8997->muic); ++err_i2c_muic: + i2c_unregister_device(max8997->haptic); ++err_i2c_haptic: + i2c_unregister_device(max8997->rtc); + err: + kfree(max8997); +diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c +index d7218cc90945..8381a76c69c0 100644 +--- a/drivers/mfd/max8998.c ++++ b/drivers/mfd/max8998.c +@@ -152,6 +152,10 @@ static int max8998_i2c_probe(struct i2c_client *i2c, + mutex_init(&max8998->iolock); + + max8998->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR); ++ if (!max8998->rtc) { ++ dev_err(&i2c->dev, "Failed to allocate I2C device for RTC\n"); ++ return -ENODEV; ++ } + i2c_set_clientdata(max8998->rtc, max8998); + + max8998_irq_init(max8998); +diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c +index 77ee26ef5941..81cfe8817fe0 100644 +--- a/drivers/mfd/sec-core.c ++++ b/drivers/mfd/sec-core.c +@@ -199,6 +199,10 @@ static int sec_pmic_probe(struct i2c_client *i2c, + } + + sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR); ++ if (!sec_pmic->rtc) { ++ dev_err(&i2c->dev, "Failed to allocate I2C for RTC\n"); ++ return -ENODEV; ++ } + i2c_set_clientdata(sec_pmic->rtc, sec_pmic); + + if (pdata && pdata->cfg_pmic_irq) +diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c +index d79277204835..de87eafbeb05 100644 +--- a/drivers/mfd/tps65910.c ++++ b/drivers/mfd/tps65910.c +@@ -254,8 +254,10 @@ static int tps65910_irq_init(struct tps65910 *tps65910, int irq, + ret = regmap_add_irq_chip(tps65910->regmap, tps65910->chip_irq, + IRQF_ONESHOT, pdata->irq_base, + tps6591x_irqs_chip, &tps65910->irq_data); +- if (ret < 0) ++ if (ret < 0) { + dev_warn(tps65910->dev, "Failed to add irq_chip %d\n", ret); ++ tps65910->chip_irq = 0; ++ } + return ret; + } + +diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h +index 66f411a6e8ea..cabc04383685 100644 +--- a/drivers/misc/mei/hw-me-regs.h ++++ b/drivers/misc/mei/hw-me-regs.h +@@ -115,6 +115,11 @@ + #define MEI_DEV_ID_LPT_HR 0x8CBA /* Lynx Point H Refresh */ + + #define MEI_DEV_ID_WPT_LP 0x9CBA /* Wildcat Point LP */ ++ ++/* Host Firmware Status Registers in PCI Config Space */ ++#define PCI_CFG_HFS_1 0x40 ++#define PCI_CFG_HFS_2 0x48 ++ + /* + * MEI HW Section + */ +diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c +index 371c65ae6be6..3c9e257982e3 100644 +--- a/drivers/misc/mei/pci-me.c ++++ b/drivers/misc/mei/pci-me.c +@@ -105,15 +105,31 @@ static bool mei_me_quirk_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) + { + u32 reg; +- if (ent->device == MEI_DEV_ID_PBG_1) { +- pci_read_config_dword(pdev, 0x48, ®); +- /* make sure that bit 9 is up and bit 10 is down */ +- if ((reg & 0x600) == 0x200) { +- dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n"); +- return false; +- } ++ /* Cougar Point || Patsburg */ ++ if (ent->device == MEI_DEV_ID_CPT_1 || ++ ent->device == MEI_DEV_ID_PBG_1) { ++ pci_read_config_dword(pdev, PCI_CFG_HFS_2, ®); ++ /* make sure that bit 9 (NM) is up and bit 10 (DM) is down */ ++ if ((reg & 0x600) == 0x200) ++ goto no_mei; + } ++ ++ /* Lynx Point */ ++ if (ent->device == MEI_DEV_ID_LPT_H || ++ ent->device == MEI_DEV_ID_LPT_W || ++ ent->device == MEI_DEV_ID_LPT_HR) { ++ /* Read ME FW Status check for SPS Firmware */ ++ pci_read_config_dword(pdev, PCI_CFG_HFS_1, ®); ++ /* if bits [19:16] = 15, running SPS Firmware */ ++ if ((reg & 0xf0000) == 0xf0000) ++ goto no_mei; ++ } ++ + return true; ++ ++no_mei: ++ dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n"); ++ return false; + } + /** + * mei_probe - Device Initialization Routine +diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c +index eb5d22795c47..bb86494e2b7b 100644 +--- a/drivers/s390/char/con3215.c ++++ b/drivers/s390/char/con3215.c +@@ -922,7 +922,7 @@ static int __init con3215_init(void) + raw3215_freelist = req; + } + +- cdev = ccw_device_probe_console(); ++ cdev = ccw_device_probe_console(&raw3215_ccw_driver); + if (IS_ERR(cdev)) + return -ENODEV; + +diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c +index 699fd3e363df..bb6b0df50b33 100644 +--- a/drivers/s390/char/con3270.c ++++ b/drivers/s390/char/con3270.c +@@ -576,7 +576,6 @@ static struct console con3270 = { + static int __init + con3270_init(void) + { +- struct ccw_device *cdev; + struct raw3270 *rp; + void *cbuf; + int i; +@@ -591,10 +590,7 @@ con3270_init(void) + cpcmd("TERM AUTOCR OFF", NULL, 0, NULL); + } + +- cdev = ccw_device_probe_console(); +- if (IS_ERR(cdev)) +- return -ENODEV; +- rp = raw3270_setup_console(cdev); ++ rp = raw3270_setup_console(); + if (IS_ERR(rp)) + return PTR_ERR(rp); + +diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c +index 24a08e8f19e1..651d1f5da7c4 100644 +--- a/drivers/s390/char/raw3270.c ++++ b/drivers/s390/char/raw3270.c +@@ -776,16 +776,24 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc) + } + + #ifdef CONFIG_TN3270_CONSOLE ++/* Tentative definition - see below for actual definition. */ ++static struct ccw_driver raw3270_ccw_driver; ++ + /* + * Setup 3270 device configured as console. + */ +-struct raw3270 __init *raw3270_setup_console(struct ccw_device *cdev) ++struct raw3270 __init *raw3270_setup_console(void) + { ++ struct ccw_device *cdev; + unsigned long flags; + struct raw3270 *rp; + char *ascebc; + int rc; + ++ cdev = ccw_device_probe_console(&raw3270_ccw_driver); ++ if (IS_ERR(cdev)) ++ return ERR_CAST(cdev); ++ + rp = kzalloc(sizeof(struct raw3270), GFP_KERNEL | GFP_DMA); + ascebc = kzalloc(256, GFP_KERNEL); + rc = raw3270_setup_device(cdev, rp, ascebc); +diff --git a/drivers/s390/char/raw3270.h b/drivers/s390/char/raw3270.h +index 7b73ff8c1bd7..359276a88396 100644 +--- a/drivers/s390/char/raw3270.h ++++ b/drivers/s390/char/raw3270.h +@@ -190,7 +190,7 @@ raw3270_put_view(struct raw3270_view *view) + wake_up(&raw3270_wait_queue); + } + +-struct raw3270 *raw3270_setup_console(struct ccw_device *cdev); ++struct raw3270 *raw3270_setup_console(void); + void raw3270_wait_cons_dev(struct raw3270 *); + + /* Notifier for device addition/removal */ +diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c +index 1ab5f6c36d9b..8d04a9a88cc4 100644 +--- a/drivers/s390/cio/device.c ++++ b/drivers/s390/cio/device.c +@@ -1610,7 +1610,7 @@ out_unlock: + return rc; + } + +-struct ccw_device *ccw_device_probe_console(void) ++struct ccw_device *ccw_device_probe_console(struct ccw_driver *drv) + { + struct io_subchannel_private *io_priv; + struct ccw_device *cdev; +@@ -1632,6 +1632,7 @@ struct ccw_device *ccw_device_probe_console(void) + kfree(io_priv); + return cdev; + } ++ cdev->drv = drv; + set_io_private(sch, io_priv); + ret = ccw_device_console_enable(cdev, sch); + if (ret) { +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index 278c9fa62067..1822cb9ec623 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -2501,16 +2501,15 @@ static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, + static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) + { + uint32_t cdb_phyaddr, cdb_phyaddr_hi32; +- dma_addr_t dma_coherent_handle; ++ + /* + ******************************************************************** + ** here we need to tell iop 331 our freeccb.HighPart + ** if freeccb.HighPart is not zero + ******************************************************************** + */ +- dma_coherent_handle = acb->dma_coherent_handle; +- cdb_phyaddr = (uint32_t)(dma_coherent_handle); +- cdb_phyaddr_hi32 = (uint32_t)((cdb_phyaddr >> 16) >> 16); ++ cdb_phyaddr = lower_32_bits(acb->dma_coherent_handle); ++ cdb_phyaddr_hi32 = upper_32_bits(acb->dma_coherent_handle); + acb->cdb_phyaddr_hi32 = cdb_phyaddr_hi32; + /* + *********************************************************************** +diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c +index ad72c1d85111..66c495d21016 100644 +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -2553,7 +2553,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) + ha->flags.enable_64bit_addressing ? "enable" : + "disable"); + ret = qla2x00_mem_alloc(ha, req_length, rsp_length, &req, &rsp); +- if (!ret) { ++ if (ret) { + ql_log_pci(ql_log_fatal, pdev, 0x0031, + "Failed to allocate memory for adapter, aborting.\n"); + +@@ -3458,10 +3458,10 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, + else { + qla2x00_set_reserved_loop_ids(ha); + ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0123, +- "loop_id_map=%p. \n", ha->loop_id_map); ++ "loop_id_map=%p.\n", ha->loop_id_map); + } + +- return 1; ++ return 0; + + fail_async_pd: + dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma); +diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c +index 23ec684b60e1..274c359279ef 100644 +--- a/drivers/staging/rtl8712/rtl871x_recv.c ++++ b/drivers/staging/rtl8712/rtl871x_recv.c +@@ -254,7 +254,7 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter, + struct sta_info *psta; + struct sta_priv *pstapriv; + union recv_frame *prtnframe; +- u16 ether_type = 0; ++ u16 ether_type; + + pstapriv = &adapter->stapriv; + ptr = get_recvframe_data(precv_frame); +@@ -263,15 +263,14 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter, + psta = r8712_get_stainfo(pstapriv, psta_addr); + auth_alg = adapter->securitypriv.AuthAlgrthm; + if (auth_alg == 2) { ++ /* get ether_type */ ++ ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE; ++ memcpy(ðer_type, ptr, 2); ++ ether_type = ntohs((unsigned short)ether_type); ++ + if ((psta != NULL) && (psta->ieee8021x_blocked)) { + /* blocked + * only accept EAPOL frame */ +- prtnframe = precv_frame; +- /*get ether_type */ +- ptr = ptr + pfhdr->attrib.hdrlen + +- pfhdr->attrib.iv_len + LLC_HEADER_SIZE; +- memcpy(ðer_type, ptr, 2); +- ether_type = ntohs((unsigned short)ether_type); + if (ether_type == 0x888e) + prtnframe = precv_frame; + else { +diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c +index 8a6e5ea476e1..380d9d707109 100644 +--- a/drivers/staging/serqt_usb2/serqt_usb2.c ++++ b/drivers/staging/serqt_usb2/serqt_usb2.c +@@ -725,7 +725,7 @@ static int qt_startup(struct usb_serial *serial) + goto startup_error; + } + +- switch (serial->dev->descriptor.idProduct) { ++ switch (le16_to_cpu(serial->dev->descriptor.idProduct)) { + case QUATECH_DSU100: + case QUATECH_QSU100: + case QUATECH_ESU100A: +diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c +index 5232ac7b0745..58c479d13b57 100644 +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -2454,6 +2454,7 @@ static void iscsit_build_conn_drop_async_message(struct iscsi_conn *conn) + { + struct iscsi_cmd *cmd; + struct iscsi_conn *conn_p; ++ bool found = false; + + /* + * Only send a Asynchronous Message on connections whos network +@@ -2462,11 +2463,12 @@ static void iscsit_build_conn_drop_async_message(struct iscsi_conn *conn) + list_for_each_entry(conn_p, &conn->sess->sess_conn_list, conn_list) { + if (conn_p->conn_state == TARG_CONN_STATE_LOGGED_IN) { + iscsit_inc_conn_usage_count(conn_p); ++ found = true; + break; + } + } + +- if (!conn_p) ++ if (!found) + return; + + cmd = iscsit_allocate_cmd(conn_p, GFP_ATOMIC); +diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c +index 4859505ae2ed..639fdb395fb7 100644 +--- a/drivers/target/tcm_fc/tfc_sess.c ++++ b/drivers/target/tcm_fc/tfc_sess.c +@@ -68,6 +68,7 @@ static struct ft_tport *ft_tport_create(struct fc_lport *lport) + + if (tport) { + tport->tpg = tpg; ++ tpg->tport = tport; + return tport; + } + +diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c +index eb255e807c06..a2a2645b296c 100644 +--- a/drivers/tty/hvc/hvc_console.c ++++ b/drivers/tty/hvc/hvc_console.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -70,6 +71,9 @@ static struct task_struct *hvc_task; + /* Picks up late kicks after list walk but before schedule() */ + static int hvc_kicked; + ++/* hvc_init is triggered from hvc_alloc, i.e. only when actually used */ ++static atomic_t hvc_needs_init __read_mostly = ATOMIC_INIT(-1); ++ + static int hvc_init(void); + + #ifdef CONFIG_MAGIC_SYSRQ +@@ -842,7 +846,7 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data, + int i; + + /* We wait until a driver actually comes along */ +- if (!hvc_driver) { ++ if (atomic_inc_not_zero(&hvc_needs_init)) { + int err = hvc_init(); + if (err) + return ERR_PTR(err); +diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c +index 6eab440e1542..4ed35231e552 100644 +--- a/drivers/usb/core/driver.c ++++ b/drivers/usb/core/driver.c +@@ -953,8 +953,7 @@ EXPORT_SYMBOL_GPL(usb_deregister); + * it doesn't support pre_reset/post_reset/reset_resume or + * because it doesn't support suspend/resume. + * +- * The caller must hold @intf's device's lock, but not its pm_mutex +- * and not @intf->dev.sem. ++ * The caller must hold @intf's device's lock, but not @intf's lock. + */ + void usb_forced_unbind_intf(struct usb_interface *intf) + { +@@ -967,16 +966,37 @@ void usb_forced_unbind_intf(struct usb_interface *intf) + intf->needs_binding = 1; + } + ++/* ++ * Unbind drivers for @udev's marked interfaces. These interfaces have ++ * the needs_binding flag set, for example by usb_resume_interface(). ++ * ++ * The caller must hold @udev's device lock. ++ */ ++static void unbind_marked_interfaces(struct usb_device *udev) ++{ ++ struct usb_host_config *config; ++ int i; ++ struct usb_interface *intf; ++ ++ config = udev->actconfig; ++ if (config) { ++ for (i = 0; i < config->desc.bNumInterfaces; ++i) { ++ intf = config->interface[i]; ++ if (intf->dev.driver && intf->needs_binding) ++ usb_forced_unbind_intf(intf); ++ } ++ } ++} ++ + /* Delayed forced unbinding of a USB interface driver and scan + * for rebinding. + * +- * The caller must hold @intf's device's lock, but not its pm_mutex +- * and not @intf->dev.sem. ++ * The caller must hold @intf's device's lock, but not @intf's lock. + * + * Note: Rebinds will be skipped if a system sleep transition is in + * progress and the PM "complete" callback hasn't occurred yet. + */ +-void usb_rebind_intf(struct usb_interface *intf) ++static void usb_rebind_intf(struct usb_interface *intf) + { + int rc; + +@@ -993,68 +1013,66 @@ void usb_rebind_intf(struct usb_interface *intf) + } + } + +-#ifdef CONFIG_PM +- +-/* Unbind drivers for @udev's interfaces that don't support suspend/resume +- * There is no check for reset_resume here because it can be determined +- * only during resume whether reset_resume is needed. ++/* ++ * Rebind drivers to @udev's marked interfaces. These interfaces have ++ * the needs_binding flag set. + * + * The caller must hold @udev's device lock. + */ +-static void unbind_no_pm_drivers_interfaces(struct usb_device *udev) ++static void rebind_marked_interfaces(struct usb_device *udev) + { + struct usb_host_config *config; + int i; + struct usb_interface *intf; +- struct usb_driver *drv; + + config = udev->actconfig; + if (config) { + for (i = 0; i < config->desc.bNumInterfaces; ++i) { + intf = config->interface[i]; +- +- if (intf->dev.driver) { +- drv = to_usb_driver(intf->dev.driver); +- if (!drv->suspend || !drv->resume) +- usb_forced_unbind_intf(intf); +- } ++ if (intf->needs_binding) ++ usb_rebind_intf(intf); + } + } + } + +-/* Unbind drivers for @udev's interfaces that failed to support reset-resume. +- * These interfaces have the needs_binding flag set by usb_resume_interface(). ++/* ++ * Unbind all of @udev's marked interfaces and then rebind all of them. ++ * This ordering is necessary because some drivers claim several interfaces ++ * when they are first probed. + * + * The caller must hold @udev's device lock. + */ +-static void unbind_no_reset_resume_drivers_interfaces(struct usb_device *udev) ++void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev) + { +- struct usb_host_config *config; +- int i; +- struct usb_interface *intf; +- +- config = udev->actconfig; +- if (config) { +- for (i = 0; i < config->desc.bNumInterfaces; ++i) { +- intf = config->interface[i]; +- if (intf->dev.driver && intf->needs_binding) +- usb_forced_unbind_intf(intf); +- } +- } ++ unbind_marked_interfaces(udev); ++ rebind_marked_interfaces(udev); + } + +-static void do_rebind_interfaces(struct usb_device *udev) ++#ifdef CONFIG_PM ++ ++/* Unbind drivers for @udev's interfaces that don't support suspend/resume ++ * There is no check for reset_resume here because it can be determined ++ * only during resume whether reset_resume is needed. ++ * ++ * The caller must hold @udev's device lock. ++ */ ++static void unbind_no_pm_drivers_interfaces(struct usb_device *udev) + { + struct usb_host_config *config; + int i; + struct usb_interface *intf; ++ struct usb_driver *drv; + + config = udev->actconfig; + if (config) { + for (i = 0; i < config->desc.bNumInterfaces; ++i) { + intf = config->interface[i]; +- if (intf->needs_binding) +- usb_rebind_intf(intf); ++ ++ if (intf->dev.driver) { ++ drv = to_usb_driver(intf->dev.driver); ++ if (!drv->suspend || !drv->resume) ++ usb_forced_unbind_intf(intf); ++ } + } + } + } +@@ -1379,7 +1397,7 @@ int usb_resume_complete(struct device *dev) + * whose needs_binding flag is set + */ + if (udev->state != USB_STATE_NOTATTACHED) +- do_rebind_interfaces(udev); ++ rebind_marked_interfaces(udev); + return 0; + } + +@@ -1401,7 +1419,7 @@ int usb_resume(struct device *dev, pm_message_t msg) + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); +- unbind_no_reset_resume_drivers_interfaces(udev); ++ unbind_marked_interfaces(udev); + } + + /* Avoid PM error messages for devices disconnected while suspended +diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c +index caeb8d6d39fb..4676917e2b1f 100644 +--- a/drivers/usb/core/hcd-pci.c ++++ b/drivers/usb/core/hcd-pci.c +@@ -75,7 +75,7 @@ static void for_each_companion(struct pci_dev *pdev, struct usb_hcd *hcd, + PCI_SLOT(companion->devfn) != slot) + continue; + companion_hcd = pci_get_drvdata(companion); +- if (!companion_hcd) ++ if (!companion_hcd || !companion_hcd->self.root_hub) + continue; + fn(pdev, hcd, companion, companion_hcd); + } +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 3a2eb4cc8959..a036e03ae1b3 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -5252,10 +5252,11 @@ int usb_reset_device(struct usb_device *udev) + else if (cintf->condition == + USB_INTERFACE_BOUND) + rebind = 1; ++ if (rebind) ++ cintf->needs_binding = 1; + } +- if (ret == 0 && rebind) +- usb_rebind_intf(cintf); + } ++ usb_unbind_and_rebind_marked_interfaces(udev); + } + + usb_autosuspend_device(udev); +diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h +index 823857767a16..0923add72b59 100644 +--- a/drivers/usb/core/usb.h ++++ b/drivers/usb/core/usb.h +@@ -55,7 +55,7 @@ extern int usb_match_one_id_intf(struct usb_device *dev, + extern int usb_match_device(struct usb_device *dev, + const struct usb_device_id *id); + extern void usb_forced_unbind_intf(struct usb_interface *intf); +-extern void usb_rebind_intf(struct usb_interface *intf); ++extern void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev); + + extern int usb_hub_claim_port(struct usb_device *hdev, unsigned port, + struct dev_state *owner); +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index 27dad993b007..7ab3c9985253 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -836,15 +836,15 @@ struct dwc3_event_depevt { + * 12 - VndrDevTstRcved + * @reserved15_12: Reserved, not used + * @event_info: Information about this event +- * @reserved31_24: Reserved, not used ++ * @reserved31_25: Reserved, not used + */ + struct dwc3_event_devt { + u32 one_bit:1; + u32 device_event:7; + u32 type:4; + u32 reserved15_12:4; +- u32 event_info:8; +- u32 reserved31_24:8; ++ u32 event_info:9; ++ u32 reserved31_25:7; + } __packed; + + /** +diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c +index 7cacd6ae818e..e4d8d79a4993 100644 +--- a/drivers/usb/gadget/tcm_usb_gadget.c ++++ b/drivers/usb/gadget/tcm_usb_gadget.c +@@ -1614,7 +1614,7 @@ static struct se_wwn *usbg_make_tport( + return ERR_PTR(-ENOMEM); + } + tport->tport_wwpn = wwpn; +- snprintf(tport->tport_name, sizeof(tport->tport_name), wnn_name); ++ snprintf(tport->tport_name, sizeof(tport->tport_name), "%s", wnn_name); + return &tport->tport_wwn; + } + +diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c +index 0deb9d6cde26..d31814c7238f 100644 +--- a/drivers/usb/gadget/zero.c ++++ b/drivers/usb/gadget/zero.c +@@ -280,7 +280,7 @@ static int __init zero_bind(struct usb_composite_dev *cdev) + ss_opts->isoc_interval = gzero_options.isoc_interval; + ss_opts->isoc_maxpacket = gzero_options.isoc_maxpacket; + ss_opts->isoc_mult = gzero_options.isoc_mult; +- ss_opts->isoc_maxburst = gzero_options.isoc_maxpacket; ++ ss_opts->isoc_maxburst = gzero_options.isoc_maxburst; + ss_opts->bulk_buflen = gzero_options.bulk_buflen; + + func_ss = usb_get_function(func_inst_ss); +diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c +index 3581416a24d8..a736d82695cb 100644 +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -114,9 +114,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) + xhci->quirks |= XHCI_TRUST_TX_LENGTH; + } + if (pdev->vendor == PCI_VENDOR_ID_RENESAS && +- pdev->device == 0x0015 && +- pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG && +- pdev->subsystem_device == 0xc0cd) ++ pdev->device == 0x0015) + xhci->quirks |= XHCI_RESET_ON_RESUME; + if (pdev->vendor == PCI_VENDOR_ID_VIA) + xhci->quirks |= XHCI_RESET_ON_RESUME; +@@ -161,6 +159,10 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) + struct usb_hcd *hcd; + + driver = (struct hc_driver *)id->driver_data; ++ ++ /* Prevent runtime suspending between USB-2 and USB-3 initialization */ ++ pm_runtime_get_noresume(&dev->dev); ++ + /* Register the USB 2.0 roothub. + * FIXME: USB core must know to register the USB 2.0 roothub first. + * This is sort of silly, because we could just set the HCD driver flags +@@ -170,7 +172,7 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) + retval = usb_hcd_pci_probe(dev, id); + + if (retval) +- return retval; ++ goto put_runtime_pm; + + /* USB 2.0 roothub is stored in the PCI device now. */ + hcd = dev_get_drvdata(&dev->dev); +@@ -199,12 +201,17 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) + if (xhci->quirks & XHCI_LPM_SUPPORT) + hcd_to_bus(xhci->shared_hcd)->root_hub->lpm_capable = 1; + ++ /* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */ ++ pm_runtime_put_noidle(&dev->dev); ++ + return 0; + + put_usb3_hcd: + usb_put_hcd(xhci->shared_hcd); + dealloc_usb2_hcd: + usb_hcd_pci_remove(dev); ++put_runtime_pm: ++ pm_runtime_put_noidle(&dev->dev); + return retval; + } + +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index a90819b83224..4b46de842175 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -394,16 +394,16 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd) + + #else + +-static int xhci_try_enable_msi(struct usb_hcd *hcd) ++static inline int xhci_try_enable_msi(struct usb_hcd *hcd) + { + return 0; + } + +-static void xhci_cleanup_msix(struct xhci_hcd *xhci) ++static inline void xhci_cleanup_msix(struct xhci_hcd *xhci) + { + } + +-static void xhci_msix_sync_irqs(struct xhci_hcd *xhci) ++static inline void xhci_msix_sync_irqs(struct xhci_hcd *xhci) + { + } + +diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c +index 37a261a6bb6a..da0caf3f4b27 100644 +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -440,7 +440,6 @@ void musb_hnp_stop(struct musb *musb) + static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + u8 devctl) + { +- struct usb_otg *otg = musb->xceiv->otg; + irqreturn_t handled = IRQ_NONE; + + dev_dbg(musb->controller, "<== DevCtl=%02x, int_usb=0x%x\n", devctl, +@@ -655,7 +654,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + break; + case OTG_STATE_B_PERIPHERAL: + musb_g_suspend(musb); +- musb->is_active = otg->gadget->b_hnp_enable; ++ musb->is_active = musb->g.b_hnp_enable; + if (musb->is_active) { + musb->xceiv->state = OTG_STATE_B_WAIT_ACON; + dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n"); +@@ -671,7 +670,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + break; + case OTG_STATE_A_HOST: + musb->xceiv->state = OTG_STATE_A_SUSPEND; +- musb->is_active = otg->host->b_hnp_enable; ++ musb->is_active = musb_to_hcd(musb)->self.b_hnp_enable; + break; + case OTG_STATE_B_HOST: + /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */ +diff --git a/drivers/usb/phy/phy-ulpi.c b/drivers/usb/phy/phy-ulpi.c +index 217339dd7a90..17ea3f271bd8 100644 +--- a/drivers/usb/phy/phy-ulpi.c ++++ b/drivers/usb/phy/phy-ulpi.c +@@ -47,6 +47,8 @@ struct ulpi_info { + static struct ulpi_info ulpi_ids[] = { + ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"), + ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"), ++ ULPI_INFO(ULPI_ID(0x0424, 0x0007), "SMSC USB3320"), ++ ULPI_INFO(ULPI_ID(0x0451, 0x1507), "TI TUSB1210"), + }; + + static int ulpi_set_otg_flags(struct usb_phy *phy) +diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c +index 4471f464ca26..a0b58e252073 100644 +--- a/drivers/usb/serial/pl2303.c ++++ b/drivers/usb/serial/pl2303.c +@@ -82,6 +82,9 @@ static const struct usb_device_id id_table[] = { + { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, + { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, ++ { USB_DEVICE(HP_VENDOR_ID, HP_LD960_PRODUCT_ID) }, ++ { USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) }, ++ { USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) }, + { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, + { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) }, + { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, +diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h +index c38b8c00c06f..42bc082896ac 100644 +--- a/drivers/usb/serial/pl2303.h ++++ b/drivers/usb/serial/pl2303.h +@@ -121,8 +121,11 @@ + #define SUPERIAL_VENDOR_ID 0x5372 + #define SUPERIAL_PRODUCT_ID 0x2303 + +-/* Hewlett-Packard LD220-HP POS Pole Display */ ++/* Hewlett-Packard POS Pole Displays */ + #define HP_VENDOR_ID 0x03f0 ++#define HP_LD960_PRODUCT_ID 0x0b39 ++#define HP_LCM220_PRODUCT_ID 0x3139 ++#define HP_LCM960_PRODUCT_ID 0x3239 + #define HP_LD220_PRODUCT_ID 0x3524 + + /* Cressi Edy (diving computer) PC interface */ +diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c +index 40788c925d1c..73705aff53cb 100644 +--- a/drivers/w1/w1_netlink.c ++++ b/drivers/w1/w1_netlink.c +@@ -54,28 +54,29 @@ static void w1_send_slave(struct w1_master *dev, u64 rn) + struct w1_netlink_msg *hdr = (struct w1_netlink_msg *)(msg + 1); + struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)(hdr + 1); + int avail; ++ u64 *data; + + /* update kernel slave list */ + w1_slave_found(dev, rn); + + avail = dev->priv_size - cmd->len; + +- if (avail > 8) { +- u64 *data = (void *)(cmd + 1) + cmd->len; ++ if (avail < 8) { ++ msg->ack++; ++ cn_netlink_send(msg, 0, GFP_KERNEL); + +- *data = rn; +- cmd->len += 8; +- hdr->len += 8; +- msg->len += 8; +- return; ++ msg->len = sizeof(struct w1_netlink_msg) + ++ sizeof(struct w1_netlink_cmd); ++ hdr->len = sizeof(struct w1_netlink_cmd); ++ cmd->len = 0; + } + +- msg->ack++; +- cn_netlink_send(msg, 0, GFP_KERNEL); ++ data = (void *)(cmd + 1) + cmd->len; + +- msg->len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd); +- hdr->len = sizeof(struct w1_netlink_cmd); +- cmd->len = 0; ++ *data = rn; ++ cmd->len += 8; ++ hdr->len += 8; ++ msg->len += 8; + } + + static int w1_process_search_command(struct w1_master *dev, struct cn_msg *msg, +diff --git a/fs/ext4/file.c b/fs/ext4/file.c +index b19f0a457f32..4635788e14bf 100644 +--- a/fs/ext4/file.c ++++ b/fs/ext4/file.c +@@ -82,7 +82,7 @@ ext4_unaligned_aio(struct inode *inode, const struct iovec *iov, + size_t count = iov_length(iov, nr_segs); + loff_t final_size = pos + count; + +- if (pos >= inode->i_size) ++ if (pos >= i_size_read(inode)) + return 0; + + if ((pos & blockmask) || (final_size & blockmask)) +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index 1423c4816a47..298e9c8da364 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -517,8 +517,8 @@ static void ext4_xattr_update_super_block(handle_t *handle, + } + + /* +- * Release the xattr block BH: If the reference count is > 1, decrement +- * it; otherwise free the block. ++ * Release the xattr block BH: If the reference count is > 1, decrement it; ++ * otherwise free the block. + */ + static void + ext4_xattr_release_block(handle_t *handle, struct inode *inode, +@@ -538,16 +538,31 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, + if (ce) + mb_cache_entry_free(ce); + get_bh(bh); ++ unlock_buffer(bh); + ext4_free_blocks(handle, inode, bh, 0, 1, + EXT4_FREE_BLOCKS_METADATA | + EXT4_FREE_BLOCKS_FORGET); +- unlock_buffer(bh); + } else { + le32_add_cpu(&BHDR(bh)->h_refcount, -1); + if (ce) + mb_cache_entry_release(ce); ++ /* ++ * Beware of this ugliness: Releasing of xattr block references ++ * from different inodes can race and so we have to protect ++ * from a race where someone else frees the block (and releases ++ * its journal_head) before we are done dirtying the buffer. In ++ * nojournal mode this race is harmless and we actually cannot ++ * call ext4_handle_dirty_xattr_block() with locked buffer as ++ * that function can call sync_dirty_buffer() so for that case ++ * we handle the dirtying after unlocking the buffer. ++ */ ++ if (ext4_handle_valid(handle)) ++ error = ext4_handle_dirty_xattr_block(handle, inode, ++ bh); + unlock_buffer(bh); +- error = ext4_handle_dirty_xattr_block(handle, inode, bh); ++ if (!ext4_handle_valid(handle)) ++ error = ext4_handle_dirty_xattr_block(handle, inode, ++ bh); + if (IS_SYNC(inode)) + ext4_handle_sync(handle); + dquot_free_block(inode, EXT4_C2B(EXT4_SB(inode->i_sb), 1)); +diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c +index 7f05cd140de3..3eaa6e30a2dc 100644 +--- a/fs/nfsd/nfs4callback.c ++++ b/fs/nfsd/nfs4callback.c +@@ -637,9 +637,11 @@ static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc + + static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses) + { ++ int maxtime = max_cb_time(clp->net); + struct rpc_timeout timeparms = { +- .to_initval = max_cb_time(clp->net), ++ .to_initval = maxtime, + .to_retries = 0, ++ .to_maxval = maxtime, + }; + struct rpc_create_args args = { + .net = clp->net, +diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c +index 27d74a294515..f7d7d04674fb 100644 +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -1307,6 +1307,12 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, + /* If op is non-idempotent */ + if (opdesc->op_flags & OP_MODIFIES_SOMETHING) { + plen = opdesc->op_rsize_bop(rqstp, op); ++ /* ++ * If there's still another operation, make sure ++ * we'll have space to at least encode an error: ++ */ ++ if (resp->opcnt < args->opcnt) ++ plen += COMPOUND_ERR_SLACK_SPACE; + op->status = nfsd4_check_resp_size(resp, plen); + } + +@@ -1471,7 +1477,8 @@ static inline u32 nfsd4_setattr_rsize(struct svc_rqst *rqstp, struct nfsd4_op *o + + static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) + { +- return (op_encode_hdr_size + 2 + 1024) * sizeof(__be32); ++ return (op_encode_hdr_size + 2 + XDR_QUADLEN(NFS4_VERIFIER_SIZE)) * ++ sizeof(__be32); + } + + static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index 316ec843dec2..442509285ca9 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -4958,7 +4958,6 @@ nfs4_state_destroy_net(struct net *net) + int i; + struct nfs4_client *clp = NULL; + struct nfsd_net *nn = net_generic(net, nfsd_net_id); +- struct rb_node *node, *tmp; + + for (i = 0; i < CLIENT_HASH_SIZE; i++) { + while (!list_empty(&nn->conf_id_hashtbl[i])) { +@@ -4967,13 +4966,11 @@ nfs4_state_destroy_net(struct net *net) + } + } + +- node = rb_first(&nn->unconf_name_tree); +- while (node != NULL) { +- tmp = node; +- node = rb_next(tmp); +- clp = rb_entry(tmp, struct nfs4_client, cl_namenode); +- rb_erase(tmp, &nn->unconf_name_tree); +- destroy_client(clp); ++ for (i = 0; i < CLIENT_HASH_SIZE; i++) { ++ while (!list_empty(&nn->unconf_id_hashtbl[i])) { ++ clp = list_entry(nn->unconf_id_hashtbl[i].next, struct nfs4_client, cl_idhash); ++ destroy_client(clp); ++ } + } + + kfree(nn->sessionid_hashtbl); +diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c +index 582321a978b0..5188a38fef06 100644 +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -2401,6 +2401,8 @@ out_acl: + WRITE64(stat.ino); + } + if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) { ++ if ((buflen -= 16) < 0) ++ goto out_resource; + WRITE32(3); + WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0); + WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD1); +@@ -3382,6 +3384,9 @@ nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr, + struct nfsd4_test_stateid_id *stateid, *next; + __be32 *p; + ++ if (nfserr) ++ return nfserr; ++ + RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids)); + *p++ = htonl(test_stateid->ts_num_ids); + +diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c +index 7f555179bf81..f34d9de802ab 100644 +--- a/fs/nfsd/nfsctl.c ++++ b/fs/nfsd/nfsctl.c +@@ -699,6 +699,11 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net) + if (err != 0 || fd < 0) + return -EINVAL; + ++ if (svc_alien_sock(net, fd)) { ++ printk(KERN_ERR "%s: socket net is different to NFSd's one\n", __func__); ++ return -EINVAL; ++ } ++ + err = nfsd_create_serv(net); + if (err != 0) + return err; +diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c +index 62fd6616801d..d9b298cbfe5c 100644 +--- a/fs/nfsd/vfs.c ++++ b/fs/nfsd/vfs.c +@@ -406,6 +406,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, + umode_t ftype = 0; + __be32 err; + int host_err; ++ bool get_write_count; + int size_change = 0; + + if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) +@@ -413,10 +414,18 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, + if (iap->ia_valid & ATTR_SIZE) + ftype = S_IFREG; + ++ /* Callers that do fh_verify should do the fh_want_write: */ ++ get_write_count = !fhp->fh_dentry; ++ + /* Get inode */ + err = fh_verify(rqstp, fhp, ftype, accmode); + if (err) + goto out; ++ if (get_write_count) { ++ host_err = fh_want_write(fhp); ++ if (host_err) ++ return nfserrno(host_err); ++ } + + dentry = fhp->fh_dentry; + inode = dentry->d_inode; +diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c +index 5d18ad10c27f..4f66e007dae1 100644 +--- a/fs/ocfs2/buffer_head_io.c ++++ b/fs/ocfs2/buffer_head_io.c +@@ -90,7 +90,6 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, + * information for this bh as it's not marked locally + * uptodate. */ + ret = -EIO; +- put_bh(bh); + mlog_errno(ret); + } + +@@ -420,7 +419,6 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb, + + if (!buffer_uptodate(bh)) { + ret = -EIO; +- put_bh(bh); + mlog_errno(ret); + } + +diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c +index e68588e6b1e8..9bd981cd3142 100644 +--- a/fs/ocfs2/dlm/dlmrecovery.c ++++ b/fs/ocfs2/dlm/dlmrecovery.c +@@ -540,7 +540,10 @@ master_here: + /* success! see if any other nodes need recovery */ + mlog(0, "DONE mastering recovery of %s:%u here(this=%u)!\n", + dlm->name, dlm->reco.dead_node, dlm->node_num); +- dlm_reset_recovery(dlm); ++ spin_lock(&dlm->spinlock); ++ __dlm_reset_recovery(dlm); ++ dlm->reco.state &= ~DLM_RECO_STATE_FINALIZE; ++ spin_unlock(&dlm->spinlock); + } + dlm_end_recovery(dlm); + +@@ -698,6 +701,14 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node) + if (all_nodes_done) { + int ret; + ++ /* Set this flag on recovery master to avoid ++ * a new recovery for another dead node start ++ * before the recovery is not done. That may ++ * cause recovery hung.*/ ++ spin_lock(&dlm->spinlock); ++ dlm->reco.state |= DLM_RECO_STATE_FINALIZE; ++ spin_unlock(&dlm->spinlock); ++ + /* all nodes are now in DLM_RECO_NODE_DATA_DONE state + * just send a finalize message to everyone and + * clean up */ +@@ -1751,13 +1762,13 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm, + struct dlm_migratable_lockres *mres) + { + struct dlm_migratable_lock *ml; +- struct list_head *queue; ++ struct list_head *queue, *iter; + struct list_head *tmpq = NULL; + struct dlm_lock *newlock = NULL; + struct dlm_lockstatus *lksb = NULL; + int ret = 0; + int i, j, bad; +- struct dlm_lock *lock = NULL; ++ struct dlm_lock *lock; + u8 from = O2NM_MAX_NODES; + unsigned int added = 0; + __be64 c; +@@ -1792,14 +1803,16 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm, + /* MIGRATION ONLY! */ + BUG_ON(!(mres->flags & DLM_MRES_MIGRATION)); + ++ lock = NULL; + spin_lock(&res->spinlock); + for (j = DLM_GRANTED_LIST; j <= DLM_BLOCKED_LIST; j++) { + tmpq = dlm_list_idx_to_ptr(res, j); +- list_for_each_entry(lock, tmpq, list) { +- if (lock->ml.cookie != ml->cookie) +- lock = NULL; +- else ++ list_for_each(iter, tmpq) { ++ lock = list_entry(iter, ++ struct dlm_lock, list); ++ if (lock->ml.cookie == ml->cookie) + break; ++ lock = NULL; + } + if (lock) + break; +@@ -2867,8 +2880,8 @@ int dlm_finalize_reco_handler(struct o2net_msg *msg, u32 len, void *data, + BUG(); + } + dlm->reco.state &= ~DLM_RECO_STATE_FINALIZE; ++ __dlm_reset_recovery(dlm); + spin_unlock(&dlm->spinlock); +- dlm_reset_recovery(dlm); + dlm_kick_recovery_thread(dlm); + break; + default: +diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c +index 6c2d136561cb..2b96b59f75da 100644 +--- a/fs/reiserfs/dir.c ++++ b/fs/reiserfs/dir.c +@@ -128,6 +128,7 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent, + char *d_name; + off_t d_off; + ino_t d_ino; ++ loff_t cur_pos = deh_offset(deh); + + if (!de_visible(deh)) + /* it is hidden entry */ +@@ -200,8 +201,9 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent, + if (local_buf != small_buf) { + kfree(local_buf); + } +- // next entry should be looked for with such offset +- next_pos = deh_offset(deh) + 1; ++ ++ /* deh_offset(deh) may be invalid now. */ ++ next_pos = cur_pos + 1; + + if (item_moved(&tmp_ih, &path_to_entry)) { + set_cpu_key_k_offset(&pos_key, +diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c +index eca6f9d8a263..79ddbaf93206 100644 +--- a/fs/xfs/xfs_da_btree.c ++++ b/fs/xfs/xfs_da_btree.c +@@ -1334,7 +1334,7 @@ xfs_da3_fixhashpath( + node = blk->bp->b_addr; + xfs_da3_node_hdr_from_disk(&nodehdr, node); + btree = xfs_da3_node_tree_p(node); +- if (be32_to_cpu(btree->hashval) == lasthash) ++ if (be32_to_cpu(btree[blk->index].hashval) == lasthash) + break; + blk->hashval = lasthash; + btree[blk->index].hashval = cpu_to_be32(lasthash); +diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h +index 62fd1b756e99..947009ed5996 100644 +--- a/include/linux/sunrpc/svcsock.h ++++ b/include/linux/sunrpc/svcsock.h +@@ -56,6 +56,7 @@ int svc_recv(struct svc_rqst *, long); + int svc_send(struct svc_rqst *); + void svc_drop(struct svc_rqst *); + void svc_sock_update_bufs(struct svc_serv *serv); ++bool svc_alien_sock(struct net *net, int fd); + int svc_addsock(struct svc_serv *serv, const int fd, + char *name_return, const size_t len); + void svc_init_xprt_sock(void); +diff --git a/kernel/sysctl.c b/kernel/sysctl.c +index 9edcf456e0fc..ed6c01626acd 100644 +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -144,6 +144,11 @@ static int min_percpu_pagelist_fract = 8; + static int ngroups_max = NGROUPS_MAX; + static const int cap_last_cap = CAP_LAST_CAP; + ++/*this is needed for proc_doulongvec_minmax of sysctl_hung_task_timeout_secs */ ++#ifdef CONFIG_DETECT_HUNG_TASK ++static unsigned long hung_task_timeout_max = (LONG_MAX/HZ); ++#endif ++ + #ifdef CONFIG_INOTIFY_USER + #include + #endif +@@ -966,6 +971,7 @@ static struct ctl_table kern_table[] = { + .maxlen = sizeof(unsigned long), + .mode = 0644, + .proc_handler = proc_dohung_task_timeout_secs, ++ .extra2 = &hung_task_timeout_max, + }, + { + .procname = "hung_task_warnings", +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index aa3b9a63394b..8a7f27b42131 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -1487,6 +1487,7 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count, + while (min_count < persistent_huge_pages(h)) { + if (!free_pool_huge_page(h, nodes_allowed, 0)) + break; ++ cond_resched_lock(&hugetlb_lock); + } + while (count < persistent_huge_pages(h)) { + if (!adjust_pool_surplus(h, nodes_allowed, 1)) +diff --git a/mm/mlock.c b/mm/mlock.c +index 79b7cf7d1bca..713e462c0776 100644 +--- a/mm/mlock.c ++++ b/mm/mlock.c +@@ -76,6 +76,7 @@ void clear_page_mlock(struct page *page) + */ + void mlock_vma_page(struct page *page) + { ++ /* Serialize with page migration */ + BUG_ON(!PageLocked(page)); + + if (!TestSetPageMlocked(page)) { +@@ -106,6 +107,7 @@ unsigned int munlock_vma_page(struct page *page) + { + unsigned int page_mask = 0; + ++ /* For try_to_munlock() and to serialize with page migration */ + BUG_ON(!PageLocked(page)); + + if (TestClearPageMlocked(page)) { +diff --git a/mm/rmap.c b/mm/rmap.c +index 3f6077461aea..fbf0040a7342 100644 +--- a/mm/rmap.c ++++ b/mm/rmap.c +@@ -1390,9 +1390,19 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount, + BUG_ON(!page || PageAnon(page)); + + if (locked_vma) { +- mlock_vma_page(page); /* no-op if already mlocked */ +- if (page == check_page) ++ if (page == check_page) { ++ /* we know we have check_page locked */ ++ mlock_vma_page(page); + ret = SWAP_MLOCK; ++ } else if (trylock_page(page)) { ++ /* ++ * If we can lock the page, perform mlock. ++ * Otherwise leave the page alone, it will be ++ * eventually encountered again later. ++ */ ++ mlock_vma_page(page); ++ unlock_page(page); ++ } + continue; /* don't unmap */ + } + +diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c +index 305374d4fb98..422759bae60d 100644 +--- a/net/sunrpc/svcsock.c ++++ b/net/sunrpc/svcsock.c +@@ -1393,6 +1393,22 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, + return svsk; + } + ++bool svc_alien_sock(struct net *net, int fd) ++{ ++ int err; ++ struct socket *sock = sockfd_lookup(fd, &err); ++ bool ret = false; ++ ++ if (!sock) ++ goto out; ++ if (sock_net(sock->sk) != net) ++ ret = true; ++ sockfd_put(sock); ++out: ++ return ret; ++} ++EXPORT_SYMBOL_GPL(svc_alien_sock); ++ + /** + * svc_addsock - add a listener socket to an RPC service + * @serv: pointer to RPC service to which to add a new listener +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 34548589f419..7de7cf1ec852 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -937,6 +937,7 @@ static int alc_codec_rename_from_preset(struct hda_codec *codec) + + static const struct snd_pci_quirk beep_white_list[] = { + SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1), ++ SND_PCI_QUIRK(0x1043, 0x115d, "ASUS", 1), + SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), + SND_PCI_QUIRK(0x1043, 0x8376, "EeePC", 1), + SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1), +@@ -2858,8 +2859,9 @@ static void alc269_fixup_mic_mute_hook(void *private_data, int enabled) + + if (spec->mute_led_polarity) + enabled = !enabled; +- pinval = AC_PINCTL_IN_EN | +- (enabled ? AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_80); ++ pinval = snd_hda_codec_get_pin_target(codec, spec->mute_led_nid); ++ pinval &= ~AC_PINCTL_VREFEN; ++ pinval |= enabled ? AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_80; + if (spec->mute_led_nid) + snd_hda_set_pin_ctl_cache(codec, spec->mute_led_nid, pinval); + } +@@ -3901,6 +3903,7 @@ static int patch_alc269(struct hda_codec *codec) + spec->codec_variant = ALC269_TYPE_ALC284; + break; + case 0x10ec0286: ++ case 0x10ec0288: + spec->codec_variant = ALC269_TYPE_ALC286; + break; + case 0x10ec0255: +@@ -4643,6 +4646,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { + { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 }, + { .id = 0x10ec0284, .name = "ALC284", .patch = patch_alc269 }, + { .id = 0x10ec0286, .name = "ALC286", .patch = patch_alc269 }, ++ { .id = 0x10ec0288, .name = "ALC288", .patch = patch_alc269 }, + { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 }, + { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 }, + { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", +diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c +index 806407a3973e..e6b70e35f628 100644 +--- a/sound/pci/ice1712/ice1712.c ++++ b/sound/pci/ice1712/ice1712.c +@@ -685,9 +685,10 @@ static snd_pcm_uframes_t snd_ice1712_playback_pointer(struct snd_pcm_substream * + if (!(snd_ice1712_read(ice, ICE1712_IREG_PBK_CTRL) & 1)) + return 0; + ptr = runtime->buffer_size - inw(ice->ddma_port + 4); ++ ptr = bytes_to_frames(substream->runtime, ptr); + if (ptr == runtime->buffer_size) + ptr = 0; +- return bytes_to_frames(substream->runtime, ptr); ++ return ptr; + } + + static snd_pcm_uframes_t snd_ice1712_playback_ds_pointer(struct snd_pcm_substream *substream) +@@ -704,9 +705,10 @@ static snd_pcm_uframes_t snd_ice1712_playback_ds_pointer(struct snd_pcm_substrea + addr = ICE1712_DSC_ADDR0; + ptr = snd_ice1712_ds_read(ice, substream->number * 2, addr) - + ice->playback_con_virt_addr[substream->number]; ++ ptr = bytes_to_frames(substream->runtime, ptr); + if (ptr == substream->runtime->buffer_size) + ptr = 0; +- return bytes_to_frames(substream->runtime, ptr); ++ return ptr; + } + + static snd_pcm_uframes_t snd_ice1712_capture_pointer(struct snd_pcm_substream *substream) +@@ -717,9 +719,10 @@ static snd_pcm_uframes_t snd_ice1712_capture_pointer(struct snd_pcm_substream *s + if (!(snd_ice1712_read(ice, ICE1712_IREG_CAP_CTRL) & 1)) + return 0; + ptr = inl(ICEREG(ice, CONCAP_ADDR)) - ice->capture_con_virt_addr; ++ ptr = bytes_to_frames(substream->runtime, ptr); + if (ptr == substream->runtime->buffer_size) + ptr = 0; +- return bytes_to_frames(substream->runtime, ptr); ++ return ptr; + } + + static const struct snd_pcm_hardware snd_ice1712_playback = { +@@ -1113,9 +1116,10 @@ static snd_pcm_uframes_t snd_ice1712_playback_pro_pointer(struct snd_pcm_substre + if (!(inl(ICEMT(ice, PLAYBACK_CONTROL)) & ICE1712_PLAYBACK_START)) + return 0; + ptr = ice->playback_pro_size - (inw(ICEMT(ice, PLAYBACK_SIZE)) << 2); ++ ptr = bytes_to_frames(substream->runtime, ptr); + if (ptr == substream->runtime->buffer_size) + ptr = 0; +- return bytes_to_frames(substream->runtime, ptr); ++ return ptr; + } + + static snd_pcm_uframes_t snd_ice1712_capture_pro_pointer(struct snd_pcm_substream *substream) +@@ -1126,9 +1130,10 @@ static snd_pcm_uframes_t snd_ice1712_capture_pro_pointer(struct snd_pcm_substrea + if (!(inl(ICEMT(ice, PLAYBACK_CONTROL)) & ICE1712_CAPTURE_START_SHADOW)) + return 0; + ptr = ice->capture_pro_size - (inw(ICEMT(ice, CAPTURE_SIZE)) << 2); ++ ptr = bytes_to_frames(substream->runtime, ptr); + if (ptr == substream->runtime->buffer_size) + ptr = 0; +- return bytes_to_frames(substream->runtime, ptr); ++ return ptr; + } + + static const struct snd_pcm_hardware snd_ice1712_playback_pro = { +diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c +index 1e0fa3b5f79a..e1dfebbea650 100644 +--- a/sound/soc/codecs/cs42l51.c ++++ b/sound/soc/codecs/cs42l51.c +@@ -124,9 +124,8 @@ static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol, + + static const DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -5150, 50, 0); + static const DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0); +-/* This is a lie. after -102 db, it stays at -102 */ +-/* maybe a range would be better */ +-static const DECLARE_TLV_DB_SCALE(aout_tlv, -11550, 50, 0); ++ ++static const DECLARE_TLV_DB_SCALE(aout_tlv, -10200, 50, 0); + + static const DECLARE_TLV_DB_SCALE(boost_tlv, 1600, 1600, 0); + static const char *chan_mix[] = { +@@ -141,7 +140,7 @@ static const struct soc_enum cs42l51_chan_mix = + static const struct snd_kcontrol_new cs42l51_snd_controls[] = { + SOC_DOUBLE_R_SX_TLV("PCM Playback Volume", + CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, +- 6, 0x19, 0x7F, adc_pcm_tlv), ++ 0, 0x19, 0x7F, adc_pcm_tlv), + SOC_DOUBLE_R("PCM Playback Switch", + CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 7, 1, 1), + SOC_DOUBLE_R_SX_TLV("Analog Playback Volume", +@@ -149,7 +148,7 @@ static const struct snd_kcontrol_new cs42l51_snd_controls[] = { + 0, 0x34, 0xE4, aout_tlv), + SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", + CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, +- 6, 0x19, 0x7F, adc_pcm_tlv), ++ 0, 0x19, 0x7F, adc_pcm_tlv), + SOC_DOUBLE_R("ADC Mixer Switch", + CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 7, 1, 1), + SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0), +diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c +index ee25f325d65c..b99af6362de6 100644 +--- a/sound/soc/codecs/cs42l52.c ++++ b/sound/soc/codecs/cs42l52.c +@@ -350,7 +350,7 @@ static const char * const right_swap_text[] = { + static const unsigned int swap_values[] = { 0, 1, 3 }; + + static const struct soc_enum adca_swap_enum = +- SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 1, ++ SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 3, + ARRAY_SIZE(left_swap_text), + left_swap_text, + swap_values); +@@ -359,7 +359,7 @@ static const struct snd_kcontrol_new adca_mixer = + SOC_DAPM_ENUM("Route", adca_swap_enum); + + static const struct soc_enum pcma_swap_enum = +- SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 1, ++ SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 3, + ARRAY_SIZE(left_swap_text), + left_swap_text, + swap_values); +@@ -368,7 +368,7 @@ static const struct snd_kcontrol_new pcma_mixer = + SOC_DAPM_ENUM("Route", pcma_swap_enum); + + static const struct soc_enum adcb_swap_enum = +- SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 1, ++ SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 3, + ARRAY_SIZE(right_swap_text), + right_swap_text, + swap_values); +@@ -377,7 +377,7 @@ static const struct snd_kcontrol_new adcb_mixer = + SOC_DAPM_ENUM("Route", adcb_swap_enum); + + static const struct soc_enum pcmb_swap_enum = +- SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 1, ++ SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 3, + ARRAY_SIZE(right_swap_text), + right_swap_text, + swap_values); +diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c +index 3b20c86cdb01..eade6e2d883d 100644 +--- a/sound/soc/codecs/cs42l73.c ++++ b/sound/soc/codecs/cs42l73.c +@@ -325,7 +325,7 @@ static const char * const cs42l73_mono_mix_texts[] = { + static const unsigned int cs42l73_mono_mix_values[] = { 0, 1, 2 }; + + static const struct soc_enum spk_asp_enum = +- SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 1, ++ SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 3, + ARRAY_SIZE(cs42l73_mono_mix_texts), + cs42l73_mono_mix_texts, + cs42l73_mono_mix_values); +@@ -343,7 +343,7 @@ static const struct snd_kcontrol_new spk_xsp_mixer = + SOC_DAPM_ENUM("Route", spk_xsp_enum); + + static const struct soc_enum esl_asp_enum = +- SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 5, ++ SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 3, + ARRAY_SIZE(cs42l73_mono_mix_texts), + cs42l73_mono_mix_texts, + cs42l73_mono_mix_values); +@@ -352,7 +352,7 @@ static const struct snd_kcontrol_new esl_asp_mixer = + SOC_DAPM_ENUM("Route", esl_asp_enum); + + static const struct soc_enum esl_xsp_enum = +- SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 7, ++ SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 3, + ARRAY_SIZE(cs42l73_mono_mix_texts), + cs42l73_mono_mix_texts, + cs42l73_mono_mix_values); diff --git a/patch/kernel/s500-default/patch-3.10.39-40.patch b/patch/kernel/s500-default/patch-3.10.39-40.patch new file mode 100644 index 000000000..e31088c15 --- /dev/null +++ b/patch/kernel/s500-default/patch-3.10.39-40.patch @@ -0,0 +1,2267 @@ +diff --git a/Makefile b/Makefile +index 1e07514be6f8..b2285cababb0 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 10 +-SUBLEVEL = 39 ++SUBLEVEL = 40 + EXTRAVERSION = + NAME = TOSSUG Baby Fish + +diff --git a/arch/arc/include/asm/irqflags.h b/arch/arc/include/asm/irqflags.h +index eac071668201..c29d56587bf0 100644 +--- a/arch/arc/include/asm/irqflags.h ++++ b/arch/arc/include/asm/irqflags.h +@@ -137,13 +137,6 @@ static inline void arch_unmask_irq(unsigned int irq) + flag \scratch + .endm + +-.macro IRQ_DISABLE_SAVE scratch, save +- lr \scratch, [status32] +- mov \save, \scratch /* Make a copy */ +- bic \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK) +- flag \scratch +-.endm +- + .macro IRQ_ENABLE scratch + lr \scratch, [status32] + or \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK) +diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S +index 6dbe359c760d..6f3cd0fb4b54 100644 +--- a/arch/arc/kernel/entry.S ++++ b/arch/arc/kernel/entry.S +@@ -589,11 +589,7 @@ ARC_ENTRY ret_from_exception + ; Pre-{IRQ,Trap,Exception} K/U mode from pt_regs->status32 + ld r8, [sp, PT_status32] ; returning to User/Kernel Mode + +-#ifdef CONFIG_PREEMPT + bbit0 r8, STATUS_U_BIT, resume_kernel_mode +-#else +- bbit0 r8, STATUS_U_BIT, restore_regs +-#endif + + ; Before returning to User mode check-for-and-complete any pending work + ; such as rescheduling/signal-delivery etc. +@@ -653,10 +649,15 @@ resume_user_mode_begin: + b resume_user_mode_begin ; unconditionally back to U mode ret chks + ; for single exit point from this block + +-#ifdef CONFIG_PREEMPT +- + resume_kernel_mode: + ++ ; Disable Interrupts from this point on ++ ; CONFIG_PREEMPT: This is a must for preempt_schedule_irq() ++ ; !CONFIG_PREEMPT: To ensure restore_regs is intr safe ++ IRQ_DISABLE r9 ++ ++#ifdef CONFIG_PREEMPT ++ + ; Can't preempt if preemption disabled + GET_CURR_THR_INFO_FROM_SP r10 + ld r8, [r10, THREAD_INFO_PREEMPT_COUNT] +@@ -666,8 +667,6 @@ resume_kernel_mode: + ld r9, [r10, THREAD_INFO_FLAGS] + bbit0 r9, TIF_NEED_RESCHED, restore_regs + +- IRQ_DISABLE r9 +- + ; Invoke PREEMPTION + bl preempt_schedule_irq + +@@ -680,12 +679,11 @@ resume_kernel_mode: + ; + ; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap) + ; IRQ shd definitely not happen between now and rtie ++; All 2 entry points to here already disable interrupts + + restore_regs : + +- ; Disable Interrupts while restoring reg-file back +- ; XXX can this be optimised out +- IRQ_DISABLE_SAVE r9, r10 ;@r10 has prisitine (pre-disable) copy ++ lr r10, [status32] + + #ifdef CONFIG_ARC_CURR_IN_REG + ; Restore User R25 +diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c +index f0ef2f7d4ad7..5ef506c6f492 100644 +--- a/arch/arm/mm/mmap.c ++++ b/arch/arm/mm/mmap.c +@@ -204,13 +204,11 @@ int valid_phys_addr_range(phys_addr_t addr, size_t size) + } + + /* +- * We don't use supersection mappings for mmap() on /dev/mem, which +- * means that we can't map the memory area above the 4G barrier into +- * userspace. ++ * Do not allow /dev/mem mappings beyond the supported physical range. + */ + int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) + { +- return !(pfn + (size >> PAGE_SHIFT) > 0x00100000); ++ return (pfn + (size >> PAGE_SHIFT)) <= (1 + (PHYS_MASK >> PAGE_SHIFT)); + } + + #ifdef CONFIG_STRICT_DEVMEM +diff --git a/arch/mips/kvm/kvm_mips_emul.c b/arch/mips/kvm/kvm_mips_emul.c +index 4b6274b47f33..e75ef8219caf 100644 +--- a/arch/mips/kvm/kvm_mips_emul.c ++++ b/arch/mips/kvm/kvm_mips_emul.c +@@ -1571,17 +1571,17 @@ kvm_mips_handle_ri(unsigned long cause, uint32_t *opc, + arch->gprs[rt] = kvm_read_c0_guest_userlocal(cop0); + #else + /* UserLocal not implemented */ +- er = kvm_mips_emulate_ri_exc(cause, opc, run, vcpu); ++ er = EMULATE_FAIL; + #endif + break; + + default: +- printk("RDHWR not supported\n"); ++ kvm_debug("RDHWR %#x not supported @ %p\n", rd, opc); + er = EMULATE_FAIL; + break; + } + } else { +- printk("Emulate RI not supported @ %p: %#x\n", opc, inst); ++ kvm_debug("Emulate RI not supported @ %p: %#x\n", opc, inst); + er = EMULATE_FAIL; + } + +@@ -1590,6 +1590,7 @@ kvm_mips_handle_ri(unsigned long cause, uint32_t *opc, + */ + if (er == EMULATE_FAIL) { + vcpu->arch.pc = curr_pc; ++ er = kvm_mips_emulate_ri_exc(cause, opc, run, vcpu); + } + return er; + } +diff --git a/arch/mips/power/hibernate.S b/arch/mips/power/hibernate.S +index 7e0277a1048f..32a7c828f073 100644 +--- a/arch/mips/power/hibernate.S ++++ b/arch/mips/power/hibernate.S +@@ -43,6 +43,7 @@ LEAF(swsusp_arch_resume) + bne t1, t3, 1b + PTR_L t0, PBE_NEXT(t0) + bnez t0, 0b ++ jal local_flush_tlb_all /* Avoid TLB mismatch after kernel resume */ + PTR_LA t0, saved_regs + PTR_L ra, PT_R31(t0) + PTR_L sp, PT_R29(t0) +diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h +index 84fdf6857c31..ef22898daa93 100644 +--- a/arch/powerpc/include/asm/compat.h ++++ b/arch/powerpc/include/asm/compat.h +@@ -8,7 +8,11 @@ + #include + + #define COMPAT_USER_HZ 100 ++#ifdef __BIG_ENDIAN__ + #define COMPAT_UTS_MACHINE "ppc\0\0" ++#else ++#define COMPAT_UTS_MACHINE "ppcle\0\0" ++#endif + + typedef u32 compat_size_t; + typedef s32 compat_ssize_t; +diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h +index e1fb161252ef..795f67792ea9 100644 +--- a/arch/powerpc/include/asm/reg.h ++++ b/arch/powerpc/include/asm/reg.h +@@ -208,6 +208,7 @@ + #define SPRN_ACOP 0x1F /* Available Coprocessor Register */ + #define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */ + #define SPRN_TEXASR 0x82 /* Transaction EXception & Summary */ ++#define TEXASR_FS __MASK(63-36) /* Transaction Failure Summary */ + #define SPRN_TEXASRU 0x83 /* '' '' '' Upper 32 */ + #define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */ + #define SPRN_CTRLF 0x088 +diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c +index 7baa27b7abbe..1e1c995ddacc 100644 +--- a/arch/powerpc/kernel/process.c ++++ b/arch/powerpc/kernel/process.c +@@ -523,6 +523,31 @@ out_and_saveregs: + tm_save_sprs(thr); + } + ++extern void __tm_recheckpoint(struct thread_struct *thread, ++ unsigned long orig_msr); ++ ++void tm_recheckpoint(struct thread_struct *thread, ++ unsigned long orig_msr) ++{ ++ unsigned long flags; ++ ++ /* We really can't be interrupted here as the TEXASR registers can't ++ * change and later in the trecheckpoint code, we have a userspace R1. ++ * So let's hard disable over this region. ++ */ ++ local_irq_save(flags); ++ hard_irq_disable(); ++ ++ /* The TM SPRs are restored here, so that TEXASR.FS can be set ++ * before the trecheckpoint and no explosion occurs. ++ */ ++ tm_restore_sprs(thread); ++ ++ __tm_recheckpoint(thread, orig_msr); ++ ++ local_irq_restore(flags); ++} ++ + static inline void tm_recheckpoint_new_task(struct task_struct *new) + { + unsigned long msr; +@@ -541,13 +566,10 @@ static inline void tm_recheckpoint_new_task(struct task_struct *new) + if (!new->thread.regs) + return; + +- /* The TM SPRs are restored here, so that TEXASR.FS can be set +- * before the trecheckpoint and no explosion occurs. +- */ +- tm_restore_sprs(&new->thread); +- +- if (!MSR_TM_ACTIVE(new->thread.regs->msr)) ++ if (!MSR_TM_ACTIVE(new->thread.regs->msr)){ ++ tm_restore_sprs(&new->thread); + return; ++ } + msr = new->thread.tm_orig_msr; + /* Recheckpoint to restore original checkpointed register state. */ + TM_DEBUG("*** tm_recheckpoint of pid %d " +diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c +index 7e9dff80e1dc..81f929f026f2 100644 +--- a/arch/powerpc/kernel/signal_32.c ++++ b/arch/powerpc/kernel/signal_32.c +@@ -863,6 +863,8 @@ static long restore_tm_user_regs(struct pt_regs *regs, + * transactional versions should be loaded. + */ + tm_enable(); ++ /* Make sure the transaction is marked as failed */ ++ current->thread.tm_texasr |= TEXASR_FS; + /* This loads the checkpointed FP/VEC state, if used */ + tm_recheckpoint(¤t->thread, msr); + /* Get the top half of the MSR */ +diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c +index 35c20a1fb365..74d9615a6bb6 100644 +--- a/arch/powerpc/kernel/signal_64.c ++++ b/arch/powerpc/kernel/signal_64.c +@@ -513,6 +513,8 @@ static long restore_tm_sigcontexts(struct pt_regs *regs, + } + #endif + tm_enable(); ++ /* Make sure the transaction is marked as failed */ ++ current->thread.tm_texasr |= TEXASR_FS; + /* This loads the checkpointed FP/VEC state, if used */ + tm_recheckpoint(¤t->thread, msr); + +diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S +index f2abb219a17b..1e43ed404b95 100644 +--- a/arch/powerpc/kernel/tm.S ++++ b/arch/powerpc/kernel/tm.S +@@ -296,7 +296,7 @@ dont_backup_fp: + * Call with IRQs off, stacks get all out of sync for + * some periods in here! + */ +-_GLOBAL(tm_recheckpoint) ++_GLOBAL(__tm_recheckpoint) + mfcr r5 + mflr r0 + std r5, 8(r1) +diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c +index 1919db6c0607..3bc6b7e43b24 100644 +--- a/arch/s390/net/bpf_jit_comp.c ++++ b/arch/s390/net/bpf_jit_comp.c +@@ -243,7 +243,6 @@ static void bpf_jit_noleaks(struct bpf_jit *jit, struct sock_filter *filter) + case BPF_S_LD_W_IND: + case BPF_S_LD_H_IND: + case BPF_S_LD_B_IND: +- case BPF_S_LDX_B_MSH: + case BPF_S_LD_IMM: + case BPF_S_LD_MEM: + case BPF_S_MISC_TXA: +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index 8b8cbe9bcb92..9cf616b5210b 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -4765,21 +4765,26 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) + static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) + { + struct ata_queued_cmd *qc = NULL; +- unsigned int i; ++ unsigned int i, tag; + + /* no command while frozen */ + if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) + return NULL; + +- /* the last tag is reserved for internal command. */ +- for (i = 0; i < ATA_MAX_QUEUE - 1; i++) +- if (!test_and_set_bit(i, &ap->qc_allocated)) { +- qc = __ata_qc_from_tag(ap, i); ++ for (i = 0; i < ATA_MAX_QUEUE; i++) { ++ tag = (i + ap->last_tag + 1) % ATA_MAX_QUEUE; ++ ++ /* the last tag is reserved for internal command. */ ++ if (tag == ATA_TAG_INTERNAL) ++ continue; ++ ++ if (!test_and_set_bit(tag, &ap->qc_allocated)) { ++ qc = __ata_qc_from_tag(ap, tag); ++ qc->tag = tag; ++ ap->last_tag = tag; + break; + } +- +- if (qc) +- qc->tag = i; ++ } + + return qc; + } +diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c +index 04ceb7e2fadd..eb3575b3fbf0 100644 +--- a/drivers/block/floppy.c ++++ b/drivers/block/floppy.c +@@ -3053,7 +3053,10 @@ static int raw_cmd_copyout(int cmd, void __user *param, + int ret; + + while (ptr) { +- ret = copy_to_user(param, ptr, sizeof(*ptr)); ++ struct floppy_raw_cmd cmd = *ptr; ++ cmd.next = NULL; ++ cmd.kernel_data = NULL; ++ ret = copy_to_user(param, &cmd, sizeof(cmd)); + if (ret) + return -EFAULT; + param += sizeof(struct floppy_raw_cmd); +@@ -3107,10 +3110,11 @@ loop: + return -ENOMEM; + *rcmd = ptr; + ret = copy_from_user(ptr, param, sizeof(*ptr)); +- if (ret) +- return -EFAULT; + ptr->next = NULL; + ptr->buffer_length = 0; ++ ptr->kernel_data = NULL; ++ if (ret) ++ return -EFAULT; + param += sizeof(struct floppy_raw_cmd); + if (ptr->cmd_count > 33) + /* the command may now also take up the space +@@ -3126,7 +3130,6 @@ loop: + for (i = 0; i < 16; i++) + ptr->reply[i] = 0; + ptr->resultcode = 0; +- ptr->kernel_data = NULL; + + if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { + if (ptr->length <= 0) +diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c +index f8e6af20dfbf..d599fc42ae8b 100644 +--- a/drivers/gpio/gpio-mxs.c ++++ b/drivers/gpio/gpio-mxs.c +@@ -214,7 +214,8 @@ static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base) + ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR; + ct->regs.mask = PINCTRL_IRQEN(port); + +- irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0); ++ irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK, ++ IRQ_NOREQUEST, 0); + } + + static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) +diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c +index 8ecb601152ef..64bfc235021a 100644 +--- a/drivers/gpu/drm/cirrus/cirrus_drv.c ++++ b/drivers/gpu/drm/cirrus/cirrus_drv.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + #include "cirrus_drv.h" + +@@ -75,6 +76,41 @@ static void cirrus_pci_remove(struct pci_dev *pdev) + drm_put_dev(dev); + } + ++static int cirrus_pm_suspend(struct device *dev) ++{ ++ struct pci_dev *pdev = to_pci_dev(dev); ++ struct drm_device *drm_dev = pci_get_drvdata(pdev); ++ struct cirrus_device *cdev = drm_dev->dev_private; ++ ++ drm_kms_helper_poll_disable(drm_dev); ++ ++ if (cdev->mode_info.gfbdev) { ++ console_lock(); ++ fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 1); ++ console_unlock(); ++ } ++ ++ return 0; ++} ++ ++static int cirrus_pm_resume(struct device *dev) ++{ ++ struct pci_dev *pdev = to_pci_dev(dev); ++ struct drm_device *drm_dev = pci_get_drvdata(pdev); ++ struct cirrus_device *cdev = drm_dev->dev_private; ++ ++ drm_helper_resume_force_mode(drm_dev); ++ ++ if (cdev->mode_info.gfbdev) { ++ console_lock(); ++ fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 0); ++ console_unlock(); ++ } ++ ++ drm_kms_helper_poll_enable(drm_dev); ++ return 0; ++} ++ + static const struct file_operations cirrus_driver_fops = { + .owner = THIS_MODULE, + .open = drm_open, +@@ -105,11 +141,17 @@ static struct drm_driver driver = { + .dumb_destroy = cirrus_dumb_destroy, + }; + ++static const struct dev_pm_ops cirrus_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(cirrus_pm_suspend, ++ cirrus_pm_resume) ++}; ++ + static struct pci_driver cirrus_pci_driver = { + .name = DRIVER_NAME, + .id_table = pciidlist, + .probe = cirrus_pci_probe, + .remove = cirrus_pci_remove, ++ .driver.pm = &cirrus_pm_ops, + }; + + static int __init cirrus_init(void) +diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c +index 379a47ea99f6..b86f68d8b726 100644 +--- a/drivers/gpu/drm/cirrus/cirrus_mode.c ++++ b/drivers/gpu/drm/cirrus/cirrus_mode.c +@@ -308,6 +308,9 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc, + + WREG_HDR(hdr); + cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0); ++ ++ /* Unblank (needed on S3 resume, vgabios doesn't do it then) */ ++ outb(0x20, 0x3c0); + return 0; + } + +diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c +index 58b4a53715cd..4a809969c5ac 100644 +--- a/drivers/gpu/drm/i915/intel_crt.c ++++ b/drivers/gpu/drm/i915/intel_crt.c +@@ -717,6 +717,14 @@ static const struct dmi_system_id intel_no_crt[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), + }, + }, ++ { ++ .callback = intel_no_crt_dmi_callback, ++ .ident = "DELL XPS 8700", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "XPS 8700"), ++ }, ++ }, + { } + }; + +diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c +index 588a5eca63d8..ce6c603a3cc9 100644 +--- a/drivers/infiniband/ulp/isert/ib_isert.c ++++ b/drivers/infiniband/ulp/isert/ib_isert.c +@@ -1201,7 +1201,7 @@ isert_unmap_cmd(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn) + } + + static void +-isert_put_cmd(struct isert_cmd *isert_cmd) ++isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err) + { + struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd; + struct isert_conn *isert_conn = isert_cmd->conn; +@@ -1216,8 +1216,21 @@ isert_put_cmd(struct isert_cmd *isert_cmd) + list_del_init(&cmd->i_conn_node); + spin_unlock_bh(&conn->cmd_lock); + +- if (cmd->data_direction == DMA_TO_DEVICE) ++ if (cmd->data_direction == DMA_TO_DEVICE) { + iscsit_stop_dataout_timer(cmd); ++ /* ++ * Check for special case during comp_err where ++ * WRITE_PENDING has been handed off from core, ++ * but requires an extra target_put_sess_cmd() ++ * before transport_generic_free_cmd() below. ++ */ ++ if (comp_err && ++ cmd->se_cmd.t_state == TRANSPORT_WRITE_PENDING) { ++ struct se_cmd *se_cmd = &cmd->se_cmd; ++ ++ target_put_sess_cmd(se_cmd->se_sess, se_cmd); ++ } ++ } + + isert_unmap_cmd(isert_cmd, isert_conn); + transport_generic_free_cmd(&cmd->se_cmd, 0); +@@ -1271,7 +1284,7 @@ isert_unmap_tx_desc(struct iser_tx_desc *tx_desc, struct ib_device *ib_dev) + + static void + isert_completion_put(struct iser_tx_desc *tx_desc, struct isert_cmd *isert_cmd, +- struct ib_device *ib_dev) ++ struct ib_device *ib_dev, bool comp_err) + { + if (isert_cmd->sense_buf_dma != 0) { + pr_debug("Calling ib_dma_unmap_single for isert_cmd->sense_buf_dma\n"); +@@ -1281,7 +1294,7 @@ isert_completion_put(struct iser_tx_desc *tx_desc, struct isert_cmd *isert_cmd, + } + + isert_unmap_tx_desc(tx_desc, ib_dev); +- isert_put_cmd(isert_cmd); ++ isert_put_cmd(isert_cmd, comp_err); + } + + static void +@@ -1336,14 +1349,14 @@ isert_do_control_comp(struct work_struct *work) + iscsit_tmr_post_handler(cmd, cmd->conn); + + cmd->i_state = ISTATE_SENT_STATUS; +- isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); ++ isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev, false); + break; + case ISTATE_SEND_REJECT: + pr_debug("Got isert_do_control_comp ISTATE_SEND_REJECT: >>>\n"); + atomic_dec(&isert_conn->post_send_buf_count); + + cmd->i_state = ISTATE_SENT_STATUS; +- isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); ++ isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev, false); + break; + case ISTATE_SEND_LOGOUTRSP: + pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n"); +@@ -1382,7 +1395,7 @@ isert_response_completion(struct iser_tx_desc *tx_desc, + atomic_sub(wr->send_wr_num + 1, &isert_conn->post_send_buf_count); + + cmd->i_state = ISTATE_SENT_STATUS; +- isert_completion_put(tx_desc, isert_cmd, ib_dev); ++ isert_completion_put(tx_desc, isert_cmd, ib_dev, false); + } + + static void +@@ -1436,7 +1449,7 @@ isert_cq_tx_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn + if (!isert_cmd) + isert_unmap_tx_desc(tx_desc, ib_dev); + else +- isert_completion_put(tx_desc, isert_cmd, ib_dev); ++ isert_completion_put(tx_desc, isert_cmd, ib_dev, true); + } + + static void +diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c +index c69c81608f43..d60c9b7ad1b8 100644 +--- a/drivers/input/mouse/synaptics.c ++++ b/drivers/input/mouse/synaptics.c +@@ -1515,6 +1515,22 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = { + .driver_data = (int []){1232, 5710, 1156, 4696}, + }, + { ++ /* Lenovo ThinkPad Edge E431 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Edge E431"), ++ }, ++ .driver_data = (int []){1024, 5022, 2508, 4832}, ++ }, ++ { ++ /* Lenovo ThinkPad T431s */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T431"), ++ }, ++ .driver_data = (int []){1024, 5112, 2024, 4832}, ++ }, ++ { + /* Lenovo ThinkPad T440s */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +@@ -1523,6 +1539,14 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = { + .driver_data = (int []){1024, 5112, 2024, 4832}, + }, + { ++ /* Lenovo ThinkPad L440 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L440"), ++ }, ++ .driver_data = (int []){1024, 5112, 2024, 4832}, ++ }, ++ { + /* Lenovo ThinkPad T540p */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +@@ -1530,6 +1554,32 @@ static const struct dmi_system_id min_max_dmi_table[] __initconst = { + }, + .driver_data = (int []){1024, 5056, 2058, 4832}, + }, ++ { ++ /* Lenovo ThinkPad L540 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L540"), ++ }, ++ .driver_data = (int []){1024, 5112, 2024, 4832}, ++ }, ++ { ++ /* Lenovo Yoga S1 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, ++ "ThinkPad S1 Yoga"), ++ }, ++ .driver_data = (int []){1232, 5710, 1156, 4696}, ++ }, ++ { ++ /* Lenovo ThinkPad X1 Carbon Haswell (3rd generation) */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, ++ "ThinkPad X1 Carbon 2nd"), ++ }, ++ .driver_data = (int []){1024, 5112, 2024, 4832}, ++ }, + #endif + { } + }; +diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c +index 1af7255bbffb..a33e07f4222e 100644 +--- a/drivers/md/dm-cache-metadata.c ++++ b/drivers/md/dm-cache-metadata.c +@@ -511,8 +511,9 @@ static int __begin_transaction_flags(struct dm_cache_metadata *cmd, + disk_super = dm_block_data(sblock); + update_flags(disk_super, mutator); + read_superblock_fields(cmd, disk_super); ++ dm_bm_unlock(sblock); + +- return dm_bm_flush_and_unlock(cmd->bm, sblock); ++ return dm_bm_flush(cmd->bm); + } + + static int __begin_transaction(struct dm_cache_metadata *cmd) +diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c +index 901aac27e522..7d0ac0a6e724 100644 +--- a/drivers/md/dm-thin.c ++++ b/drivers/md/dm-thin.c +@@ -1322,9 +1322,9 @@ static void process_deferred_bios(struct pool *pool) + */ + if (ensure_next_mapping(pool)) { + spin_lock_irqsave(&pool->lock, flags); ++ bio_list_add(&pool->deferred_bios, bio); + bio_list_merge(&pool->deferred_bios, &bios); + spin_unlock_irqrestore(&pool->lock, flags); +- + break; + } + +diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c +index 81b513890e2b..6372d0bea532 100644 +--- a/drivers/md/persistent-data/dm-block-manager.c ++++ b/drivers/md/persistent-data/dm-block-manager.c +@@ -595,25 +595,14 @@ int dm_bm_unlock(struct dm_block *b) + } + EXPORT_SYMBOL_GPL(dm_bm_unlock); + +-int dm_bm_flush_and_unlock(struct dm_block_manager *bm, +- struct dm_block *superblock) ++int dm_bm_flush(struct dm_block_manager *bm) + { +- int r; +- + if (bm->read_only) + return -EPERM; + +- r = dm_bufio_write_dirty_buffers(bm->bufio); +- if (unlikely(r)) { +- dm_bm_unlock(superblock); +- return r; +- } +- +- dm_bm_unlock(superblock); +- + return dm_bufio_write_dirty_buffers(bm->bufio); + } +-EXPORT_SYMBOL_GPL(dm_bm_flush_and_unlock); ++EXPORT_SYMBOL_GPL(dm_bm_flush); + + void dm_bm_set_read_only(struct dm_block_manager *bm) + { +diff --git a/drivers/md/persistent-data/dm-block-manager.h b/drivers/md/persistent-data/dm-block-manager.h +index be5bff61be28..f74c0462e5e4 100644 +--- a/drivers/md/persistent-data/dm-block-manager.h ++++ b/drivers/md/persistent-data/dm-block-manager.h +@@ -105,8 +105,7 @@ int dm_bm_unlock(struct dm_block *b); + * + * This method always blocks. + */ +-int dm_bm_flush_and_unlock(struct dm_block_manager *bm, +- struct dm_block *superblock); ++int dm_bm_flush(struct dm_block_manager *bm); + + /* + * Switches the bm to a read only mode. Once read-only mode +diff --git a/drivers/md/persistent-data/dm-transaction-manager.c b/drivers/md/persistent-data/dm-transaction-manager.c +index 81da1a26042e..3bc30a0ae3d6 100644 +--- a/drivers/md/persistent-data/dm-transaction-manager.c ++++ b/drivers/md/persistent-data/dm-transaction-manager.c +@@ -154,7 +154,7 @@ int dm_tm_pre_commit(struct dm_transaction_manager *tm) + if (r < 0) + return r; + +- return 0; ++ return dm_bm_flush(tm->bm); + } + EXPORT_SYMBOL_GPL(dm_tm_pre_commit); + +@@ -164,8 +164,9 @@ int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *root) + return -EWOULDBLOCK; + + wipe_shadow_table(tm); ++ dm_bm_unlock(root); + +- return dm_bm_flush_and_unlock(tm->bm, root); ++ return dm_bm_flush(tm->bm); + } + EXPORT_SYMBOL_GPL(dm_tm_commit); + +diff --git a/drivers/md/persistent-data/dm-transaction-manager.h b/drivers/md/persistent-data/dm-transaction-manager.h +index b5b139076ca5..2772ed2a781a 100644 +--- a/drivers/md/persistent-data/dm-transaction-manager.h ++++ b/drivers/md/persistent-data/dm-transaction-manager.h +@@ -38,18 +38,17 @@ struct dm_transaction_manager *dm_tm_create_non_blocking_clone(struct dm_transac + /* + * We use a 2-phase commit here. + * +- * i) In the first phase the block manager is told to start flushing, and +- * the changes to the space map are written to disk. You should interrogate +- * your particular space map to get detail of its root node etc. to be +- * included in your superblock. ++ * i) Make all changes for the transaction *except* for the superblock. ++ * Then call dm_tm_pre_commit() to flush them to disk. + * +- * ii) @root will be committed last. You shouldn't use more than the +- * first 512 bytes of @root if you wish the transaction to survive a power +- * failure. You *must* have a write lock held on @root for both stage (i) +- * and (ii). The commit will drop the write lock. ++ * ii) Lock your superblock. Update. Then call dm_tm_commit() which will ++ * unlock the superblock and flush it. No other blocks should be updated ++ * during this period. Care should be taken to never unlock a partially ++ * updated superblock; perform any operations that could fail *before* you ++ * take the superblock lock. + */ + int dm_tm_pre_commit(struct dm_transaction_manager *tm); +-int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *root); ++int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *superblock); + + /* + * These methods are the only way to get hold of a writeable block. +diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c +index 2d23d2929438..cc69e415df35 100644 +--- a/drivers/mtd/nand/atmel_nand.c ++++ b/drivers/mtd/nand/atmel_nand.c +@@ -1096,6 +1096,7 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev, + goto err_pmecc_data_alloc; + } + ++ nand_chip->options |= NAND_NO_SUBPAGE_WRITE; + nand_chip->ecc.read_page = atmel_nand_pmecc_read_page; + nand_chip->ecc.write_page = atmel_nand_pmecc_write_page; + +diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c +index cd6be2ed53a8..14203f3bb0cd 100644 +--- a/drivers/mtd/nand/nuc900_nand.c ++++ b/drivers/mtd/nand/nuc900_nand.c +@@ -225,7 +225,7 @@ static void nuc900_nand_enable(struct nuc900_nand *nand) + val = __raw_readl(nand->reg + REG_FMICSR); + + if (!(val & NAND_EN)) +- __raw_writel(val | NAND_EN, REG_FMICSR); ++ __raw_writel(val | NAND_EN, nand->reg + REG_FMICSR); + + val = __raw_readl(nand->reg + REG_SMCSR); + +diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c +index f9d5615c5727..4b55cd45287b 100644 +--- a/drivers/mtd/sm_ftl.c ++++ b/drivers/mtd/sm_ftl.c +@@ -59,15 +59,12 @@ struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl) + struct attribute_group *attr_group; + struct attribute **attributes; + struct sm_sysfs_attribute *vendor_attribute; ++ char *vendor; + +- int vendor_len = strnlen(ftl->cis_buffer + SM_CIS_VENDOR_OFFSET, +- SM_SMALL_PAGE - SM_CIS_VENDOR_OFFSET); +- +- char *vendor = kmalloc(vendor_len, GFP_KERNEL); ++ vendor = kstrndup(ftl->cis_buffer + SM_CIS_VENDOR_OFFSET, ++ SM_SMALL_PAGE - SM_CIS_VENDOR_OFFSET, GFP_KERNEL); + if (!vendor) + goto error1; +- memcpy(vendor, ftl->cis_buffer + SM_CIS_VENDOR_OFFSET, vendor_len); +- vendor[vendor_len] = 0; + + /* Initialize sysfs attributes */ + vendor_attribute = +@@ -78,7 +75,7 @@ struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl) + sysfs_attr_init(&vendor_attribute->dev_attr.attr); + + vendor_attribute->data = vendor; +- vendor_attribute->len = vendor_len; ++ vendor_attribute->len = strlen(vendor); + vendor_attribute->dev_attr.attr.name = "vendor"; + vendor_attribute->dev_attr.attr.mode = S_IRUGO; + vendor_attribute->dev_attr.show = sm_attr_show; +diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c +index 7c970d3ae358..80ecca3e1465 100644 +--- a/drivers/net/wireless/b43/phy_n.c ++++ b/drivers/net/wireless/b43/phy_n.c +@@ -5175,22 +5175,22 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev, + int ch = new_channel->hw_value; + + u16 old_band_5ghz; +- u32 tmp32; ++ u16 tmp16; + + old_band_5ghz = + b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ; + if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) { +- tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); +- b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); ++ tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR); ++ b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4); + b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000); +- b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32); ++ b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16); + b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); + } else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) { + b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); +- tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); +- b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); ++ tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR); ++ b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4); + b43_phy_mask(dev, B43_PHY_B_BBCFG, 0x3FFF); +- b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32); ++ b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16); + } + + b43_chantab_phy_upload(dev, e); +diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c +index a8afc7bee545..c2b8e49d00d3 100644 +--- a/drivers/net/wireless/iwlwifi/dvm/main.c ++++ b/drivers/net/wireless/iwlwifi/dvm/main.c +@@ -252,13 +252,17 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work) + struct iwl_priv *priv = + container_of(work, struct iwl_priv, bt_runtime_config); + ++ mutex_lock(&priv->mutex); + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) +- return; ++ goto out; + + /* dont send host command if rf-kill is on */ + if (!iwl_is_ready_rf(priv)) +- return; ++ goto out; ++ + iwlagn_send_advance_bt_config(priv); ++out: ++ mutex_unlock(&priv->mutex); + } + + static void iwl_bg_bt_full_concurrency(struct work_struct *work) +diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c +index e06971be7df7..f923d8c9a296 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c +@@ -1025,9 +1025,20 @@ int rtl88ee_hw_init(struct ieee80211_hw *hw) + bool rtstatus = true; + int err = 0; + u8 tmp_u1b, u1byte; ++ unsigned long flags; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Rtl8188EE hw init\n"); + rtlpriv->rtlhal.being_init_adapter = true; ++ /* As this function can take a very long time (up to 350 ms) ++ * and can be called with irqs disabled, reenable the irqs ++ * to let the other devices continue being serviced. ++ * ++ * It is safe doing so since our own interrupts will only be enabled ++ * in a subsequent step. ++ */ ++ local_save_flags(flags); ++ local_irq_enable(); ++ + rtlpriv->intf_ops->disable_aspm(hw); + + tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CLKR+1); +@@ -1043,7 +1054,7 @@ int rtl88ee_hw_init(struct ieee80211_hw *hw) + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); + err = 1; +- return err; ++ goto exit; + } + + err = rtl88e_download_fw(hw, false); +@@ -1051,8 +1062,7 @@ int rtl88ee_hw_init(struct ieee80211_hw *hw) + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Failed to download FW. Init HW without FW now..\n"); + err = 1; +- rtlhal->fw_ready = false; +- return err; ++ goto exit; + } else { + rtlhal->fw_ready = true; + } +@@ -1135,10 +1145,12 @@ int rtl88ee_hw_init(struct ieee80211_hw *hw) + } + rtl_write_byte(rtlpriv, REG_NAV_CTRL+2, ((30000+127)/128)); + rtl88e_dm_init(hw); ++exit: ++ local_irq_restore(flags); + rtlpriv->rtlhal.being_init_adapter = false; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "end of Rtl8188EE hw init %x\n", + err); +- return 0; ++ return err; + } + + static enum version_8188e _rtl88ee_read_chip_version(struct ieee80211_hw *hw) +diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c +index a8871d66d56a..ea4d014a2884 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c ++++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c +@@ -293,7 +293,7 @@ static void _rtl88ee_translate_rx_signal_stuff(struct ieee80211_hw *hw, + u8 *psaddr; + __le16 fc; + u16 type, ufc; +- bool match_bssid, packet_toself, packet_beacon, addr; ++ bool match_bssid, packet_toself, packet_beacon = false, addr; + + tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift; + +diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +index 189ba124a8c6..324aa581938e 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +@@ -985,6 +985,17 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + int err = 0; + static bool iqk_initialized; ++ unsigned long flags; ++ ++ /* As this function can take a very long time (up to 350 ms) ++ * and can be called with irqs disabled, reenable the irqs ++ * to let the other devices continue being serviced. ++ * ++ * It is safe doing so since our own interrupts will only be enabled ++ * in a subsequent step. ++ */ ++ local_save_flags(flags); ++ local_irq_enable(); + + rtlhal->hw_type = HARDWARE_TYPE_RTL8192CU; + err = _rtl92cu_init_mac(hw); +@@ -997,7 +1008,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Failed to download FW. Init HW without FW now..\n"); + err = 1; +- return err; ++ goto exit; + } + rtlhal->last_hmeboxnum = 0; /* h2c */ + _rtl92cu_phy_param_tab_init(hw); +@@ -1034,6 +1045,8 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) + _InitPABias(hw); + _update_mac_setting(hw); + rtl92c_dm_init(hw); ++exit: ++ local_irq_restore(flags); + return err; + } + +diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +index 4f461786a7eb..c471400fe8f0 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +@@ -955,7 +955,7 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 tmp_byte = 0; +- ++ unsigned long flags; + bool rtstatus = true; + u8 tmp_u1b; + int err = false; +@@ -967,6 +967,16 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) + + rtlpci->being_init_adapter = true; + ++ /* As this function can take a very long time (up to 350 ms) ++ * and can be called with irqs disabled, reenable the irqs ++ * to let the other devices continue being serviced. ++ * ++ * It is safe doing so since our own interrupts will only be enabled ++ * in a subsequent step. ++ */ ++ local_save_flags(flags); ++ local_irq_enable(); ++ + rtlpriv->intf_ops->disable_aspm(hw); + + /* 1. MAC Initialize */ +@@ -984,7 +994,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Failed to download FW. Init HW without FW now... " + "Please copy FW into /lib/firmware/rtlwifi\n"); +- return 1; ++ err = 1; ++ goto exit; + } + + /* After FW download, we have to reset MAC register */ +@@ -997,7 +1008,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) + /* 3. Initialize MAC/PHY Config by MACPHY_reg.txt */ + if (!rtl92s_phy_mac_config(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "MAC Config failed\n"); +- return rtstatus; ++ err = rtstatus; ++ goto exit; + } + + /* because last function modify RCR, so we update +@@ -1016,7 +1028,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) + /* 4. Initialize BB After MAC Config PHY_reg.txt, AGC_Tab.txt */ + if (!rtl92s_phy_bb_config(hw)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "BB Config failed\n"); +- return rtstatus; ++ err = rtstatus; ++ goto exit; + } + + /* 5. Initiailze RF RAIO_A.txt RF RAIO_B.txt */ +@@ -1033,7 +1046,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) + + if (!rtl92s_phy_rf_config(hw)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "RF Config failed\n"); +- return rtstatus; ++ err = rtstatus; ++ goto exit; + } + + /* After read predefined TXT, we must set BB/MAC/RF +@@ -1122,8 +1136,9 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) + + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_ON); + rtl92s_dm_init(hw); ++exit: ++ local_irq_restore(flags); + rtlpci->being_init_adapter = false; +- + return err; + } + +diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +index 7d0f2e20f1a2..c240b7591cf0 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +@@ -49,6 +49,12 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue) + if (ieee80211_is_nullfunc(fc)) + return QSLT_HIGH; + ++ /* Kernel commit 1bf4bbb4024dcdab changed EAPOL packets to use ++ * queue V0 at priority 7; however, the RTL8192SE appears to have ++ * that queue at priority 6 ++ */ ++ if (skb->priority == 7) ++ return QSLT_VO; + return skb->priority; + } + +diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c +index c333dfd116b8..99f6bc5fa986 100644 +--- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c +@@ -880,14 +880,25 @@ int rtl8723ae_hw_init(struct ieee80211_hw *hw) + bool rtstatus = true; + int err; + u8 tmp_u1b; ++ unsigned long flags; + + rtlpriv->rtlhal.being_init_adapter = true; ++ /* As this function can take a very long time (up to 350 ms) ++ * and can be called with irqs disabled, reenable the irqs ++ * to let the other devices continue being serviced. ++ * ++ * It is safe doing so since our own interrupts will only be enabled ++ * in a subsequent step. ++ */ ++ local_save_flags(flags); ++ local_irq_enable(); ++ + rtlpriv->intf_ops->disable_aspm(hw); + rtstatus = _rtl8712e_init_mac(hw); + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); + err = 1; +- return err; ++ goto exit; + } + + err = rtl8723ae_download_fw(hw); +@@ -895,8 +906,7 @@ int rtl8723ae_hw_init(struct ieee80211_hw *hw) + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Failed to download FW. Init HW without FW now..\n"); + err = 1; +- rtlhal->fw_ready = false; +- return err; ++ goto exit; + } else { + rtlhal->fw_ready = true; + } +@@ -971,6 +981,8 @@ int rtl8723ae_hw_init(struct ieee80211_hw *hw) + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "under 1.5V\n"); + } + rtl8723ae_dm_init(hw); ++exit: ++ local_irq_restore(flags); + rtlpriv->rtlhal.being_init_adapter = false; + return err; + } +diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c +index 8ea7d9b2c671..815e290a1afb 100644 +--- a/drivers/s390/cio/chsc.c ++++ b/drivers/s390/cio/chsc.c +@@ -500,18 +500,27 @@ static void chsc_process_sei_nt0(struct chsc_sei_nt0_area *sei_area) + + static void chsc_process_event_information(struct chsc_sei *sei, u64 ntsm) + { +- do { ++ static int ntsm_unsupported; ++ ++ while (true) { + memset(sei, 0, sizeof(*sei)); + sei->request.length = 0x0010; + sei->request.code = 0x000e; +- sei->ntsm = ntsm; ++ if (!ntsm_unsupported) ++ sei->ntsm = ntsm; + + if (chsc(sei)) + break; + + if (sei->response.code != 0x0001) { +- CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n", +- sei->response.code); ++ CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x, ntsm=%llx)\n", ++ sei->response.code, sei->ntsm); ++ ++ if (sei->response.code == 3 && sei->ntsm) { ++ /* Fallback for old firmware. */ ++ ntsm_unsupported = 1; ++ continue; ++ } + break; + } + +@@ -527,7 +536,10 @@ static void chsc_process_event_information(struct chsc_sei *sei, u64 ntsm) + CIO_CRW_EVENT(2, "chsc: unhandled nt: %d\n", sei->nt); + break; + } +- } while (sei->u.nt0_area.flags & 0x80); ++ ++ if (!(sei->u.nt0_area.flags & 0x80)) ++ break; ++ } + } + + /* +diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c +index 8dbe500c935d..fe76185cd79a 100644 +--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c ++++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c +@@ -8174,7 +8174,6 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state) + + mpt2sas_base_free_resources(ioc); + pci_save_state(pdev); +- pci_disable_device(pdev); + pci_set_power_state(pdev, device_state); + return 0; + } +diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c +index b26f1a5cc0ec..95a5d73e675c 100644 +--- a/drivers/scsi/virtio_scsi.c ++++ b/drivers/scsi/virtio_scsi.c +@@ -751,8 +751,12 @@ static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) + + vscsi->affinity_hint_set = true; + } else { +- for (i = 0; i < vscsi->num_queues; i++) ++ for (i = 0; i < vscsi->num_queues; i++) { ++ if (!vscsi->req_vqs[i].vq) ++ continue; ++ + virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1); ++ } + + vscsi->affinity_hint_set = false; + } +diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c +index a2a2645b296c..f179033eaa3e 100644 +--- a/drivers/tty/hvc/hvc_console.c ++++ b/drivers/tty/hvc/hvc_console.c +@@ -190,7 +190,7 @@ static struct tty_driver *hvc_console_device(struct console *c, int *index) + return hvc_driver; + } + +-static int __init hvc_console_setup(struct console *co, char *options) ++static int hvc_console_setup(struct console *co, char *options) + { + if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES) + return -ENODEV; +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index 6c7fe90ad72d..6cfe4019abc6 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -2066,8 +2066,12 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, + if (tty->ops->flush_chars) + tty->ops->flush_chars(tty); + } else { ++ struct n_tty_data *ldata = tty->disc_data; ++ + while (nr > 0) { ++ mutex_lock(&ldata->output_lock); + c = tty->ops->write(tty, b, nr); ++ mutex_unlock(&ldata->output_lock); + if (c < 0) { + retval = c; + goto break_out; +diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c +index d28d7afc128a..b167665b7de2 100644 +--- a/drivers/tty/serial/8250/8250_core.c ++++ b/drivers/tty/serial/8250/8250_core.c +@@ -555,7 +555,7 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) + */ + if ((p->port.type == PORT_XR17V35X) || + (p->port.type == PORT_XR17D15X)) { +- serial_out(p, UART_EXAR_SLEEP, 0xff); ++ serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0); + return; + } + +diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c +index e45833ce975b..182bd680141f 100644 +--- a/drivers/video/aty/mach64_accel.c ++++ b/drivers/video/aty/mach64_accel.c +@@ -4,6 +4,7 @@ + */ + + #include ++#include + #include + #include